2 # PrisPy, a PyGTK Webkit implementation of Mozilla Prism released under the GPLv3
3 # Special thanks to Andy Breiner for the initial webkit browser code
4 # Special thanks also goes to Vladimir Kolev for the PyBrowser code
15 class Browser(object):
16 def delete_event(self
, widget
, event
, data
=None):
19 def destroy(self
, widget
, data
=None):
22 def __init__(self
, shortcut
):
23 imp
.load_source('config', os
.path
.join(os
.path
.expanduser('~'), '.prispy', shortcut
+ '.conf'))
26 gobject
.threads_init()
27 self
.window
= gtk
.Window(gtk
.WINDOW_TOPLEVEL
)
28 self
.window
.set_resizable(True)
29 self
.window
.set_default_size(800,600)
30 self
.window
.set_title('PrisPy: '+ config
.name
)
31 self
.window
.connect("delete_event", self
.delete_event
)
32 self
.window
.connect("destroy", self
.destroy
)
33 self
.web_view
= webkit
.WebView()
38 settings
= webkit
.WebSettings()
39 settings
.set_property('user-agent', config
.userAgent
)
40 self
.web_view
.set_settings(settings
)
41 if not config
.url
.find('http://') > -1:
42 config
.url
= 'http://'+config
.url
43 self
.web_view
.open(config
.url
)
44 scroll_window
= gtk
.ScrolledWindow(None, None)
45 scroll_window
.add(self
.web_view
)
46 vbox
= gtk
.VBox(False, 0)
47 vbox
.add(scroll_window
)
48 if config
.wantStatusbar
== 1:
49 backButton
= gtk
.Button()
50 backButton
.set_relief(gtk
.RELIEF_NONE
)
51 backImage
= gtk
.Image()
52 backImage
.set_from_stock(gtk
.STOCK_GO_BACK
, gtk
.ICON_SIZE_MENU
)
53 backImage
.set_pixel_size(16)
54 backButton
.add(backImage
)
55 backButton
.connect('clicked', self
.back
)
56 forwardButton
= gtk
.Button()
57 forwardButton
.set_relief(gtk
.RELIEF_NONE
)
58 forwardImage
= gtk
.Image()
59 forwardImage
.set_from_stock(gtk
.STOCK_GO_FORWARD
, gtk
.ICON_SIZE_MENU
)
60 forwardImage
.set_pixel_size(16)
61 forwardButton
.add(forwardImage
)
62 forwardButton
.connect('clicked', self
.forward
)
63 self
.reloadButton
= gtk
.Button()
64 self
.reloadButton
.set_relief(gtk
.RELIEF_NONE
)
65 reloadImage
= gtk
.Image()
66 reloadImage
.set_from_stock(gtk
.STOCK_REFRESH
, gtk
.ICON_SIZE_MENU
)
67 reloadImage
.set_pixel_size(16)
68 self
.reloadButton
.add(reloadImage
)
69 self
.reloadButton
.connect('clicked', self
.refresh
)
70 self
.stopButton
= gtk
.Button()
71 self
.stopButton
.set_relief(gtk
.RELIEF_NONE
)
72 stopImage
= gtk
.Image()
73 stopImage
.set_from_stock(gtk
.STOCK_STOP
, gtk
.ICON_SIZE_MENU
)
74 stopImage
.set_pixel_size(16)
75 self
.stopButton
.add(stopImage
)
76 self
.stopButton
.connect('clicked', self
.stop
)
77 self
.stopButton
.hide()
78 homeButton
= gtk
.Button()
79 homeButton
.set_relief(gtk
.RELIEF_NONE
)
80 homeImage
= gtk
.Image()
81 homeImage
.set_from_stock(gtk
.STOCK_HOME
, gtk
.ICON_SIZE_MENU
)
82 homeImage
.set_pixel_size(16)
83 homeButton
.add(homeImage
)
84 homeButton
.connect('clicked', self
.home
)
85 switchButton
= gtk
.Button()
86 switchButton
.set_relief(gtk
.RELIEF_NONE
)
87 switchImage
= gtk
.Image()
88 switchImage
.set_from_stock(gtk
.STOCK_INDEX
, gtk
.ICON_SIZE_MENU
)
89 switchImage
.set_pixel_size(16)
90 switchButton
.add(switchImage
)
91 switchButton
.connect('clicked', self
.switch
)
92 self
.statusbar
= gtk
.Statusbar()
93 self
.progressBar
= gtk
.ProgressBar()
94 self
.progressBar
.set_size_request(150, -1)
95 statusHBox
= gtk
.HBox(False, 0)
96 statusHBox
.pack_start(backButton
, False)
97 statusHBox
.pack_start(forwardButton
, False)
98 statusHBox
.pack_start(self
.reloadButton
, False)
99 statusHBox
.pack_start(self
.stopButton
, False)
100 statusHBox
.pack_start(homeButton
, False)
101 statusHBox
.pack_start(switchButton
, False)
102 statusHBox
.pack_start(self
.statusbar
, True)
103 statusHBox
.pack_start(self
.progressBar
, False)
104 vbox
.pack_start(statusHBox
, False)
106 self
.web_view
.connect('load-progress-changed', self
.progress_changed
)
107 self
.web_view
.connect('load-started', self
.progress_started
)
108 self
.web_view
.connect('load-finished', self
.progress_finished
)
109 self
.window
.add(vbox
)
110 self
.window
.show_all()
112 def back(self
, widget
, data
=None):
113 self
.web_view
.go_back()
115 def forward(self
, widget
, data
=None):
116 self
.web_view
.go_forward()
118 def home(self
, widget
, data
=None):
119 self
.web_view
.open(self
.url
)
121 def refresh(self
, widget
, data
=None):
122 self
.web_view
.reload()
123 self
.reloadButton
.hide()
124 self
.stopButton
.show()
126 def stop(self
, widget
, data
=None):
127 self
.web_view
.stop_loading()
128 self
.stopButton
.hide()
129 self
.reloadButton
.show()
131 def switch(self
, widget
, data
=None):
132 self
.window
.destroy()
136 def progress_changed(self
, web_view
, amount
):
137 self
.progressBar
.set_fraction(amount
/ 100.0)
139 def progress_started(self
, web_view
, frame
):
140 self
.progressBar
.show()
142 def progress_finished(self
, web_view
, frame
):
143 self
.progressBar
.hide()
148 class NewShortcut(object):
149 def save_config(self
, widget
, data
=None):
150 url
= self
.urlEntry
.get_text()
151 name
= self
.nameEntry
.get_text()
152 userAgent
= self
.userAgentEntry
.get_text()
153 confName
= os
.path
.join(os
.path
.expanduser('~'), '.prispy', name
+ '.conf')
154 confFile
= open(confName
, 'wb')
155 confFile
.write("name = '"+name
+"'\nurl = '"+url
+"'\nuserAgent = '"+userAgent
+"'\nwantStatusbar = "+self
.wantStatusbar
)
157 if not self
.createDeskFile
== '0':
158 deskName
= os
.path
.join(os
.path
.expanduser('~'), '.local', 'share', 'applications', name
+ '.desktop')
159 deskFile
= open(deskName
, 'wb')
160 deskFile
.write("[Desktop Entry]\nExec=/usr/bin/prispy "+name
+"\nIcon=browser\nName="+name
+"\nComment=Created with PrisPy\nTerminal=false\nType=Application\nCategories=GNOME;Application;Network;\nVersion=1.0")
162 self
.window
.destroy()
166 def delete_event(self
, widget
, event
, data
=None):
169 def destroy(self
, widget
, data
=None):
172 def cancel_action(self
, widget
, data
=None):
173 self
.window
.destroy()
176 def status_is_checked(self
, widget
, data
=None):
177 self
.wantStatusbar
= "%s" % ((0, 1)[widget
.get_active()])
179 def desk_is_checked(self
, widget
, data
=None):
180 self
.createDeskFile
= "%s" % ((0, 1)[widget
.get_active()])
183 self
.wantStatusbar
= 0
184 self
.createDeskFile
= 0
185 gobject
.threads_init()
186 self
.window
= gtk
.Window(gtk
.WINDOW_TOPLEVEL
)
187 self
.window
.set_border_width(10)
188 self
.window
.set_resizable(True)
189 self
.window
.set_title('PrisPy: Create new shortcut')
190 self
.window
.connect("delete_event", self
.delete_event
)
191 self
.window
.connect("destroy", self
.destroy
)
192 urlLabel
= gtk
.Label('URL:')
193 self
.urlEntry
= gtk
.Entry()
194 nameLabel
= gtk
.Label('Name:')
195 self
.nameEntry
= gtk
.Entry()
196 userAgentLabel
= gtk
.Label('User Agent:\n(optional)')
197 self
.userAgentEntry
= gtk
.Entry()
198 labelVBox
= gtk
.VBox(False, 0)
199 labelVBox
.add(urlLabel
)
200 labelVBox
.add(nameLabel
)
201 labelVBox
.add(userAgentLabel
)
202 entryVBox
= gtk
.VBox(False, 0)
203 entryVBox
.add(self
.urlEntry
)
204 entryVBox
.add(self
.nameEntry
)
205 entryVBox
.add(self
.userAgentEntry
)
206 combinedHBox
= gtk
.HBox(False, 0)
207 combinedHBox
.pack_start(labelVBox
, False, True, 0)
208 combinedHBox
.add(entryVBox
)
209 wantStatusButton
= gtk
.CheckButton('Show combined status/toolbar?')
210 wantStatusButton
.connect("clicked", self
.status_is_checked
, None)
211 deskFileButton
= gtk
.CheckButton('Create a desktop file for app?')
212 deskFileButton
.connect("clicked", self
.desk_is_checked
, None)
213 cancelButton
= gtk
.Button('Cancel')
214 cancelButton
.connect('clicked', self
.cancel_action
, None)
215 okButton
= gtk
.Button('Ok')
216 okButton
.connect('clicked', self
.save_config
, None)
217 buttonHBox
= gtk
.HBox(False, 0)
218 buttonHBox
.add(cancelButton
)
219 buttonHBox
.add(okButton
)
220 buttonAlign
= gtk
.Alignment(1, 0, 0, 0)
221 buttonAlign
.add(buttonHBox
)
222 vbox
= gtk
.VBox(False, 0)
223 vbox
.add(combinedHBox
)
225 #self.urlEntry.show()
227 #self.nameEntry.show()
228 #userAgentLabel.show()
229 #self.userAgentEntry.show()
230 vbox
.add(wantStatusButton
)
231 #wantStatusButton.show()
232 vbox
.add(deskFileButton
)
233 vbox
.add(buttonAlign
)
236 self
.window
.add(vbox
)
237 self
.window
.show_all()
242 class EditShortcut(object):
243 def save_config(self
, widget
, data
=None):
244 urlTmp
= self
.urlEntry
.get_text()
245 name
= self
.nameEntry
.get_text()
246 userAgent
= self
.userAgentEntry
.get_text()
247 os
.remove(os
.path
.join(os
.path
.expanduser('~'), '.prispy', self
.oldName
+ '.conf'))
248 os
.remove(os
.path
.join(os
.path
.expanduser('~'), '.prispy', self
.oldName
+ '.confc'))
249 confName
= os
.path
.join(os
.path
.expanduser('~'), '.prispy', name
+ '.conf')
250 confFile
= open(confName
, 'wb')
251 confFile
.write("name = '"+name
+"'\nurl = '"+url
+"'\nuserAgent = '"+userAgent
+"'\nwantStatusbar = "+self
.wantStatusbar
)
253 self
.window
.destroy()
257 def delete_event(self
, widget
, event
, data
=None):
260 def destroy(self
, widget
, data
=None):
263 def cancel_action(self
, widget
, data
=None):
264 self
.window
.destroy()
267 def is_checked(self
, widget
, data
=None):
268 self
.wantStatusbar
= "%s" % ((0, 1)[widget
.get_active()])
270 def __init__(self
, configFile
):
271 imp
.load_source('config', configFile
)
273 self
.oldName
= config
.name
274 gobject
.threads_init()
275 self
.window
= gtk
.Window(gtk
.WINDOW_TOPLEVEL
)
276 self
.window
.set_border_width(10)
277 self
.window
.set_resizable(True)
278 self
.window
.set_title('PrisPy: Create new shortcut')
279 self
.window
.connect("delete_event", self
.delete_event
)
280 self
.window
.connect("destroy", self
.destroy
)
281 urlLabel
= gtk
.Label('URL:')
282 self
.urlEntry
= gtk
.Entry()
283 self
.urlEntry
.set_text(config
.url
)
284 nameLabel
= gtk
.Label('Name:')
285 self
.nameEntry
= gtk
.Entry()
286 self
.nameEntry
.set_text(config
.name
)
287 userAgentLabel
= gtk
.Label('User Agent:\n(optional)')
288 self
.userAgentEntry
= gtk
.Entry()
289 self
.userAgentEntry
.set_text(config
.userAgent
)
290 labelVBox
= gtk
.VBox(False, 0)
291 labelVBox
.add(urlLabel
)
292 labelVBox
.add(nameLabel
)
293 labelVBox
.add(userAgentLabel
)
294 entryVBox
= gtk
.VBox(False, 0)
295 entryVBox
.add(self
.urlEntry
)
296 entryVBox
.add(self
.nameEntry
)
297 entryVBox
.add(self
.userAgentEntry
)
298 combinedHBox
= gtk
.HBox(False, 0)
299 combinedHBox
.pack_start(labelVBox
, False, True, 0)
300 combinedHBox
.add(entryVBox
)
301 wantStatusButton
= gtk
.CheckButton('Show combined status/toolbar?')
302 wantStatusButton
.connect("clicked", self
.is_checked
, None)
303 if config
.wantStatusbar
== 1:
304 wantStatusButton
.set_active(True)
305 self
.wantStatusbar
= 1
307 wantStatusButton
.set_active(False)
308 self
.wantStatusbar
= 0
309 cancelButton
= gtk
.Button('Cancel')
310 cancelButton
.connect('clicked', self
.cancel_action
, None)
311 okButton
= gtk
.Button('Ok')
312 okButton
.connect('clicked', self
.save_config
, None)
313 buttonHBox
= gtk
.HBox(False, 0)
314 buttonHBox
.add(cancelButton
)
315 buttonHBox
.add(okButton
)
316 buttonAlign
= gtk
.Alignment(1, 0, 0, 0)
317 buttonAlign
.add(buttonHBox
)
318 vbox
= gtk
.VBox(False, 0)
319 vbox
.add(combinedHBox
)
323 self
.nameEntry
.show()
324 userAgentLabel
.show()
325 self
.userAgentEntry
.show()
326 vbox
.add(wantStatusButton
)
327 wantStatusButton
.show()
328 vbox
.add(buttonAlign
)
331 self
.window
.add(vbox
)
332 self
.window
.show_all()
337 class Startup(object):
338 def select_shortcut(self
, widget
, data
=None):
339 selection
= self
.treeview
.get_selection()
340 model
, iter = selection
.get_selected()
341 self
.shortcut
= model
.get_value(iter, 0)
342 self
.window
.destroy()
343 browser
= Browser(self
.shortcut
)
346 def new_shortcut(self
, widget
, data
=None):
347 self
.window
.destroy()
348 newshortcut
= NewShortcut()
351 def edit_shortcut(self
, widget
, data
=None):
352 selection
= self
.treeview
.get_selection()
353 model
, iter = selection
.get_selected()
354 self
.shortcut
= model
.get_value(iter, 0)
355 self
.configFile
= os
.path
.join(os
.path
.expanduser('~'), '.prispy', self
.shortcut
+ '.conf')
356 self
.window
.destroy()
357 editshortcut
= EditShortcut(self
.configFile
)
360 def delete_shortcut(self
, widget
, data
=None):
361 selection
= self
.treeview
.get_selection()
362 model
, iter = selection
.get_selected()
363 self
.shortcut
= model
.get_value(iter, 0)
364 configFile
= os
.path
.join(os
.path
.expanduser('~'), '.prispy', self
.shortcut
+ '.conf')
365 os
.remove(configFile
)
366 deskFile
= os
.path
.join(os
.path
.expanduser('~'), '.local', 'share', 'applications', self
.shortcut
+ '.desktop')
368 selection
= self
.treeview
.get_selection()
369 model
, iter = selection
.get_selected()
372 def delete_event(self
, widget
, event
, data
=None):
375 def destroy(self
, widget
, data
=None):
379 gobject
.threads_init()
380 self
.window
= gtk
.Window(gtk
.WINDOW_TOPLEVEL
)
381 self
.window
.set_border_width(0)
382 self
.window
.set_resizable(True)
383 self
.window
.set_default_size(300, 250)
384 self
.window
.set_title('PrisPy: Start')
385 self
.window
.connect("delete_event", self
.delete_event
)
386 self
.window
.connect("destroy", self
.destroy
)
387 titleText
= gtk
.Label()
388 titleText
.set_markup('<span size="large"><b>Welcome to PrisPy!</b></span>')
389 liststore
= gtk
.ListStore(str)
390 self
.treeview
= gtk
.TreeView(liststore
)
391 renderText
= gtk
.CellRendererText()
392 column
= gtk
.TreeViewColumn('Shortcuts', renderText
, text
=0)
393 column
.set_sort_column_id(1)
394 self
.treeview
.append_column(column
)
395 configDir
= os
.path
.join(os
.path
.expanduser('~'), '.prispy')
396 if not os
.path
.exists(configDir
):
397 os
.makedirs(configDir
)
398 shortcuts
= os
.listdir(configDir
)
399 for config
in shortcuts
:
400 fname
, ext
= os
.path
.splitext(config
)
402 appendShort
= liststore
.append([fname
])
403 scrolledWindow
= gtk
.ScrolledWindow()
404 scrolledWindow
.add_with_viewport(self
.treeview
)
405 newButton
= gtk
.Button('New')
406 newButton
.connect('clicked', self
.new_shortcut
, None)
407 editButton
= gtk
.Button('Edit')
408 editButton
.connect('clicked', self
.edit_shortcut
, None)
409 delButton
= gtk
.Button('Delete')
410 delButton
.connect('clicked', self
.delete_shortcut
, None)
411 cancelButton
= gtk
.Button('Cancel')
412 cancelButton
.connect('clicked', self
.destroy
, None)
413 okButton
= gtk
.Button('Ok')
414 okButton
.connect('clicked', self
.select_shortcut
, None)
415 treeButtonVBox
= gtk
.VBox(False,0)
416 treeButtonVBox
.pack_start(newButton
, False, True, 0)
417 treeButtonVBox
.pack_start(editButton
, False, True, 0)
418 treeButtonVBox
.pack_start(delButton
, False, True, 0)
419 treeHBox
= gtk
.HBox(False, 0)
420 treeHBox
.add(scrolledWindow
)
421 treeHBox
.pack_start(treeButtonVBox
, False, True, 5)
425 buttonHBox
= gtk
.HBox(False, 0)
426 buttonHBox
.pack_start(cancelButton
, False, True, 0)
427 buttonHBox
.pack_start(okButton
, False, True, 0)
428 buttonAlign
= gtk
.Alignment(1, 0, 0, 0)
429 buttonAlign
.add(buttonHBox
)
430 vbox
= gtk
.VBox(False, 0)
431 vbox
.pack_start(titleText
, False, True, 10)
435 vbox
.pack_start(buttonAlign
, False, True, 5)
438 self
.window
.add(vbox
)
439 self
.window
.show_all()
444 if __name__
== "__main__":
450 shortcut
= sys
.argv
[1]
451 browser
= Browser(shortcut
)