summaryrefslogtreecommitdiff
path: root/browser.py
blob: e0868b3bf1e630b270f19d2eb1562241f0deb97f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import sys

from PySide2 import QtCore, QtWidgets

import gemini

class GViewport(QtWidgets.QTextBrowser):

    hoverUrlChanged = QtCore.Signal(str)

    def __init__(self, address_bar):
        self._current_url = None
        self._last_redirect = (QtCore.QUrl(), {})
        self.address_bar = address_bar
        self._hover_url = None
        QtWidgets.QTextBrowser.__init__(self)

    def mouseMoveEvent(self, event):
        cur = self.cursorForPosition(event.localPos().toPoint())
        hover_url = cur.charFormat().anchorHref()
        hover_url = gemini.absolute_url(self._current_url, QtCore.QUrl(hover_url))
        if hover_url != self._hover_url:
            self._hover_url = hover_url
            self.hoverUrlChanged.emit(self._hover_url.toString())
        return super().mouseMoveEvent(event)

    def loadResource(self, type_, url):
        if self._last_redirect[0].toString() == url.toString():
            gem = self._last_redirect[1]
        else:
            if not url.scheme():
                url.setScheme(self._current_url.scheme())
            if not url.host():
                url.setHost(self._current_url.host())
            if url.port() == -1:
                url.setPort(1965)
            if not url.path().startswith('/'):
                url.setPath(self._current_url.path().rsplit('/', 1)[0] + '/' + url.path())
            gem = gemini.get(gemini.absolute_url(self._current_url, url))
        if 'body' in gem:
            html = gemini.gem2html(gem['body'])
        else:
            html = '<h1>{} {}</h1>'.format(gem['status'], gem['meta'])
        self._current_url = url
        return html

    def setSource(self, url):
        if url.scheme() != 'gemini':
            return
        gem = gemini.get(gemini.absolute_url(self._current_url, url))
        while gem['status'][0] == '3':
            url = QtCore.QUrl(gem['meta'])
            if url.port() == 1965:
                url.setPort(-1)
            print('redirect: {}'.format(url))
            gem = gemini.get(gemini.absolute_url(self._current_url, url))
        self._last_redirect = (url, gem)
        if url.port() == 1965:
            url.setPort(-1)
        print('setSource: {}'.format(url))
        return super().setSource(url)

    def setRawSource(self):
        return self.setSource(QtCore.QUrl(self.address_bar.text()))

class GUrlBar(QtWidgets.QLineEdit):

    def __init__(self):
        QtWidgets.QLineEdit.__init__(self)

    def setUrl(self, url):
        return self.setText(url.toDisplayString())

class GBrowser(QtWidgets.QMainWindow):

    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)
        self.initUI()

    def initUI(self):
        self.statusBar().showMessage('Ready')

        back = QtWidgets.QPushButton("back")
        forward = QtWidgets.QPushButton("forward")
        address = GUrlBar()
        toolbar = QtWidgets.QToolBar()
        toolbar.addWidget(back)
        toolbar.addWidget(forward)
        toolbar.addWidget(address)
        browser = GViewport(address)

        back.clicked.connect(browser.backward)
        forward.clicked.connect(browser.forward)
        browser.sourceChanged.connect(address.setUrl)
        address.returnPressed.connect(browser.setRawSource)
        browser.hoverUrlChanged.connect(self.statusBar().showMessage)

        self.addToolBar(toolbar)
        self.setCentralWidget(browser)

        browser.setSource(QtCore.QUrl('gemini://gemini.circumlunar.space/'))

        self.setGeometry(10, 10, 1024, 750)
        self.setWindowTitle('Gemini Browser')
        self.show()

app = QtWidgets.QApplication(sys.argv)
ex = GBrowser()
sys.exit(app.exec_())