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
110
111
112
113
114
115
116
117
118
119
120
121
|
#!/usr/bin/env python
import sys
from PySide2 import QtCore, QtWidgets, QtGui
import gemini
class GViewport(QtWidgets.QTextBrowser):
hoverUrlChanged = QtCore.Signal(str)
resourceLoadedStatus = QtCore.Signal(str)
def __init__(self, address_bar):
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()
if hover_url:
hover_url = gemini.urljoin(self.address_bar.text(), hover_url)
if hover_url != self._hover_url:
self._hover_url = hover_url
self.hoverUrlChanged.emit(self._hover_url)
return super().mouseMoveEvent(event)
def loadResource(self, type_, url):
gem = gemini.get(url.toString())
print(gem['body'])
if 'body' in gem:
html = gemini.gem2html(gem['body'])
else:
html = '<h1>{} {}</h1>'.format(gem['status'], gem['meta'])
self.resourceLoadedStatus.emit(
'{status} {meta}'.format(status=gem['status'], meta=gem['meta'])
)
return html
def setSource(self, url, type_=None):
"""
send all unsupported urls to the OS
"""
if url.scheme() == 'gemini':
if type_ is None:
return super().setSource(url)
return super().setSource(url, type_)
return QtGui.QDesktopServices().openUrl(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)
## Create widgets
# Navigation Toolbar
back = QtWidgets.QPushButton("back")
forward = QtWidgets.QPushButton("forward")
address = GUrlBar()
toolbar = QtWidgets.QToolBar()
toolbar.setObjectName('navigationToolbar')
toolbar.addWidget(back)
toolbar.addWidget(forward)
toolbar.addWidget(address)
self.addToolBar(toolbar)
# Main Viewport
browser = GViewport(address)
self.setCentralWidget(browser)
# Status Bar
request_status = QtWidgets.QLabel()
self.statusBar().addWidget(request_status)
# Connect signals
back.clicked.connect(browser.backward)
forward.clicked.connect(browser.forward)
browser.sourceChanged.connect(address.setUrl)
address.returnPressed.connect(browser.setRawSource)
browser.hoverUrlChanged.connect(self.set_status_url)
browser.resourceLoadedStatus.connect(request_status.setText)
#
browser.document().setDefaultStyleSheet(open('style.css').read())
browser.setSource(QtCore.QUrl('gemini://gemini.circumlunar.space/'))
settings = QtCore.QSettings("xcolour.net", "GeminiBrowser")
self.restoreGeometry(settings.value("geometry"))
self.restoreState(settings.value("windowState"))
self.setWindowTitle('Gemini Browser')
self.show()
def set_status_url(self, url):
if url:
self.statusBar().showMessage(url)
else:
self.statusBar().clearMessage()
def closeEvent(self, event):
settings = QtCore.QSettings("xcolour.net", "GeminiBrowser")
settings.setValue("geometry", self.saveGeometry())
settings.setValue("windowState", self.saveState())
super().closeEvent(event)
app = QtWidgets.QApplication(sys.argv)
ex = GBrowser()
sys.exit(app.exec_())
|