1+ from PyQt6 .QtCore import *
2+ from PyQt6 .QtWidgets import *
3+ from PyQt6 .QtGui import *
4+ from PyQt6 .QtWebEngineWidgets import *
5+ from PyQt6 .QtWebEngineCore import *
6+
7+ import os
8+ import sys
9+
10+
11+ class AboutDialog (QDialog ):
12+ def __init__ (self , * args , ** kwargs ):
13+ super (AboutDialog , self ).__init__ (* args , ** kwargs )
14+
15+ QBtn = QDialogButtonBox ()
16+ self .buttonBox = QDialogButtonBox (QBtn )
17+ self .buttonBox .accepted .connect (self .accept )
18+ self .buttonBox .rejected .connect (self .reject )
19+
20+ layout = QVBoxLayout ()
21+
22+ title = QLabel ("GoWeb" )
23+ font = title .font ()
24+ font .setPointSize (20 )
25+ title .setFont (font )
26+
27+ layout .addWidget (title )
28+
29+ layout .addWidget (QLabel ("Version 0.2.1 Snakebite" ))
30+ layout .addWidget (QLabel ("Snakebite is a project in progress, with many features to modern browser features being developed." ))
31+ layout .addWidget (QLabel ("Copyright 2022 nathandev" ))
32+
33+ layout .addWidget (self .buttonBox )
34+
35+ self .setLayout (layout )
36+
37+
38+ class MainWindow (QMainWindow ):
39+ def __init__ (self , * args , ** kwargs ):
40+ super (MainWindow , self ).__init__ (* args , ** kwargs )
41+
42+ # QWebEngineSettings.setAttribute(QWebEngineSettings.FullScreenSupportEnabled, True)
43+ # QWebEngineSettings.setAttribute(QWebEngineSettings.FocusOnNavigationEnabled, True)
44+ # QWebEngineSettings.setAttribute(QWebEngineSettings.ScrollAnimatorEnabled, True)
45+
46+ self .tabs = QTabWidget ()
47+ self .tabs .setDocumentMode (True )
48+ self .tabs .tabBarDoubleClicked .connect (self .tab_open_doubleclick )
49+ self .tabs .currentChanged .connect (self .current_tab_changed )
50+ self .tabs .setTabsClosable (True )
51+ self .tabs .tabCloseRequested .connect (self .close_current_tab )
52+
53+ self .setCentralWidget (self .tabs )
54+
55+ self .status = QStatusBar ()
56+ self .setStatusBar (self .status )
57+
58+ load_indication = QProgressBar ()
59+ self .status .addWidget (load_indication )
60+
61+ navtb = QToolBar ("Navigation" )
62+ navtb .setIconSize (QSize (16 , 16 ))
63+ navtb .setMovable (False )
64+ self .addToolBar (navtb )
65+
66+ back_btn = QAction ("<" , self )
67+ back_btn .setStatusTip ("Back to previous page" )
68+ back_btn .triggered .connect (lambda : self .tabs .currentWidget ().back ())
69+ navtb .addAction (back_btn )
70+
71+ next_btn = QAction (">" , self )
72+ next_btn .setStatusTip ("Forward to next page" )
73+ next_btn .triggered .connect (lambda : self .tabs .currentWidget ().forward ())
74+ navtb .addAction (next_btn )
75+
76+ reload_btn = QAction ("🔁" , self )
77+ reload_btn .setStatusTip ("Reload page" )
78+ reload_btn .triggered .connect (lambda : self .tabs .currentWidget ().reload ())
79+ navtb .addAction (reload_btn )
80+
81+ home_btn = QAction ("🏠" , self )
82+ home_btn .setStatusTip ("Go home" )
83+ home_btn .triggered .connect (self .navigate_home )
84+ navtb .addAction (home_btn )
85+
86+ navtb .addSeparator ()
87+
88+ self .httpsicon = QLabel () # Yes, really!
89+ self .httpsicon .setText ('🔒' )
90+ navtb .addWidget (self .httpsicon )
91+
92+ self .urlbar = QLineEdit ()
93+ self .urlbar .returnPressed .connect (self .navigate_to_url )
94+ navtb .addWidget (self .urlbar )
95+
96+ stop_btn = QAction ("Stop" , self )
97+ stop_btn .setStatusTip ("Stop loading current page" )
98+ stop_btn .triggered .connect (lambda : self .tabs .currentWidget ().stop ())
99+ navtb .addAction (stop_btn )
100+
101+ new_tab_action = QAction ("+" , self )
102+ new_tab_action .setStatusTip ("Open a new tab" )
103+ new_tab_action .triggered .connect (lambda _ : self .add_new_tab ())
104+ navtb .addAction (new_tab_action )
105+
106+ # Uncomment to disable native menubar on Mac
107+ # self.menuBar().setNativeMenuBar(False)
108+
109+
110+ file_menu = self .menuBar ().addMenu ("&File" )
111+
112+ open_file_action = QAction ("Open file..." , self )
113+ open_file_action .setStatusTip ("Open from file" )
114+ open_file_action .triggered .connect (self .open_file )
115+ file_menu .addAction (open_file_action )
116+
117+ save_file_action = QAction ("💾" , self )
118+ save_file_action .setStatusTip ("Save current page to file" )
119+ save_file_action .triggered .connect (self .save_file )
120+ file_menu .addAction (save_file_action )
121+
122+ help_menu = self .menuBar ().addMenu ("&Help" )
123+
124+ about_action = QAction ("About GoWeb" , self )
125+ about_action .setStatusTip ("Find out more about GoWeb" )
126+ about_action .triggered .connect (self .about )
127+ help_menu .addAction (about_action )
128+
129+ navigate_mozarella_action = QAction (
130+ "GoWeb Homepage" , self )
131+ navigate_mozarella_action .setStatusTip ("Go to GoWeb Homepage" )
132+ navigate_mozarella_action .triggered .connect (self .navigate_mozarella )
133+ help_menu .addAction (navigate_mozarella_action )
134+
135+ self .add_new_tab (QUrl ('http://www.google.com' ), 'Homepage' )
136+
137+ self .show ()
138+
139+ self .setWindowTitle ("GoWeb" )
140+ self .setWindowIcon (QIcon (os .path .join ('GoWebSnakebiteLogo.ico' )))
141+
142+ def add_new_tab (self , qurl = None , label = "Blank" ):
143+
144+ if qurl is None :
145+ qurl = QUrl ('https://www.google.com' )
146+
147+ browser = QWebEngineView ()
148+
149+ browser .setUrl (qurl )
150+ i = self .tabs .addTab (browser , label )
151+
152+ self .tabs .setCurrentIndex (i )
153+
154+ # More difficult! We only want to update the url when it's from the
155+ # correct tab
156+ browser .urlChanged .connect (lambda qurl , browser = browser :
157+ self .update_urlbar (qurl , browser ))
158+
159+ browser .loadFinished .connect (lambda _ , i = i , browser = browser :
160+ self .tabs .setTabText (i , browser .page ().title ()))
161+
162+ browser .loadFinished .connect (lambda _ , i = i , browser = browser :
163+ self .update_title (self .tabs .currentWidget ()))
164+
165+ def tab_open_doubleclick (self , i ):
166+ if i == - 1 : # No tab under the click
167+ self .add_new_tab ()
168+
169+ def current_tab_changed (self , i ):
170+ qurl = self .tabs .currentWidget ().url ()
171+ self .update_urlbar (qurl , self .tabs .currentWidget ())
172+ self .update_title (self .tabs .currentWidget ())
173+
174+ def close_current_tab (self , i ):
175+ if self .tabs .count () < 2 :
176+ return
177+
178+ self .tabs .removeTab (i )
179+
180+ def update_title (self , browser ):
181+ if browser != self .tabs .currentWidget ():
182+ # If this signal is not from the current tab, ignore
183+ return
184+
185+ title = self .tabs .currentWidget ().page ().title ()
186+ self .setWindowTitle ("%s - GoWeb" % title )
187+
188+ def navigate_mozarella (self ):
189+ self .tabs .currentWidget ().setUrl (QUrl ("https://imtruenathan.itch.io/goweb-snakebite" ))
190+
191+ def about (self ):
192+ dlg = AboutDialog ()
193+ dlg .exec ()
194+
195+ def open_file (self ):
196+ filename , _ = QFileDialog .getOpenFileName (self , "Open file" , "" ,
197+ "Hypertext Markup Language (*.htm *.html);;"
198+ "All files (*.*)" )
199+
200+ if filename :
201+ with open (filename , 'r' ) as f :
202+ html = f .read ()
203+
204+ self .tabs .currentWidget ().setHtml (html )
205+ self .urlbar .setText (filename )
206+
207+ def save_file (self ):
208+ filename , _ = QFileDialog .getSaveFileName (self , "Save Page As" , "" ,
209+ "Hypertext Markup Language (*.htm *html);;"
210+ "All files (*.*)" )
211+
212+ if filename :
213+ html = self .tabs .currentWidget ().page ().toHtml ()
214+ with open (filename , 'w' ) as f :
215+ f .write (html .encode ('utf8' ))
216+
217+ def navigate_home (self ):
218+ self .tabs .currentWidget ().setUrl (QUrl ("http://www.google.com" ))
219+
220+ def navigate_to_url (self ): # Does not receive the Url
221+ q = QUrl (self .urlbar .text ())
222+ if q .scheme () == "" :
223+ q .setScheme ("http" )
224+
225+ self .tabs .currentWidget ().setUrl (q )
226+
227+ def update_urlbar (self , q , browser = None ):
228+
229+ if browser != self .tabs .currentWidget ():
230+ # If this signal is not from the current tab, ignore
231+ return
232+
233+ if q .scheme () == 'https' :
234+ # Secure padlock icon
235+ self .httpsicon .setText ('🔒' )
236+
237+ else :
238+ # Insecure padlock icon
239+ self .httpsicon .setText ('🔓' )
240+
241+ self .urlbar .setText (q .toString ())
242+ self .urlbar .setCursorPosition (0 )
243+
244+ app = QApplication (sys .argv )
245+ app .setApplicationName ("GoWeb" )
246+ app .setOrganizationName ("nathandev" )
247+ app .setOrganizationDomain ("imtruenathan.itch.io" )
248+
249+ window = MainWindow ()
250+
251+ app .exec ()
0 commit comments