1
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
3
# Copyright (C) 2012 Thomas Hearing <thomas.hearing@gmail.com>
4
# This program is free software: you can redistribute it and/or modify it
5
# under the terms of the GNU General Public License version 3, as published
6
# by the Free Software Foundation.
8
# This program is distributed in the hope that it will be useful, but
9
# WITHOUT ANY WARRANTY; without even the implied warranties of
10
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11
# PURPOSE. See the GNU General Public License for more details.
13
# You should have received a copy of the GNU General Public License along
14
# with this program. If not, see <http://www.gnu.org/licenses/>.
18
from gettext import gettext as _
19
gettext.textdomain('wikitron')
21
from gi.repository import Gtk, WebKit, Unity, Dbusmenu # pylint: disable=E0611
23
logger = logging.getLogger('wikitron')
25
from wikitron_lib import Window
26
from wikitron.AboutWikitronDialog import AboutWikitronDialog
27
from wikitron.PreferencesWikitronDialog import PreferencesWikitronDialog
30
from math import floor
32
import BookmarksDialog
34
# See wikitron_lib.Window.py for more details about how this class works
35
class WikitronWindow(Window):
36
__gtype_name__ = "WikitronWindow"
38
wiki_base_url="http://en.wikipedia.org"
39
wiki_api_url="http://en.wikipedia.org/w/api.php"
46
def finish_initializing(self, builder): # pylint: disable=E1002
47
"""Set up the main window"""
48
super(WikitronWindow, self).finish_initializing(builder)
50
self.AboutDialog = AboutWikitronDialog
51
self.PreferencesDialog = PreferencesWikitronDialog
53
# Code for other initialization actions should be added here.
56
self.connect("delete-event",self.closing_handler)
57
self.main_webview=WebKit.WebView()
59
self.main_scrollview=builder.get_object("main_scroll")
60
self.b_back=builder.get_object("back_button")
61
self.b_forward=builder.get_object("forward_button")
62
self.b_addbookmark=builder.get_object("addbookmark_button")
63
self.main_scrollview.add(self.main_webview)
68
self.main_webview.connect("navigation-policy-decision-requested",self.main_policy_handler)
69
self.open_page_from_title("Main Page",0)
71
def apply_config(self):
72
#Apply some setting to the webview to enhace viewing
73
cs=self.main_webview.get_settings()
74
cs.set_property("enable-default-context-menu",False)
75
cs.set_property("enable-page-cache",True)
76
cs.set_property("enable-scripts",False)
77
self.main_webview.set_settings(cs)
79
def api_query(self,params):
82
apiurl=self.wiki_api_url+"?"
83
for i,d in params.iteritems():
84
apiurl+=i+"="+urllib2.quote(d)+"&"
86
req=urllib2.Request(apiurl)
88
req.add_header("User-Agent","WikiTron")
89
reply=urllib2.urlopen(req)
90
replytext=reply.read()
92
#print "\n\n"+replytext+"\n\n"
93
return json.loads(replytext)
97
def open_page_from_title(self,title,hm):
100
if title.lower() in self.cache_index["contents"]:
101
#print "Checking LOAD"
103
if (self.cache_index["contents"][title.lower()]["time"]+(60*60*6)) > time.time():
105
#recent copy in cache. load from there
107
filename=self.cache_index["contents"][title.lower()]["filename"]
108
filepath=path.join(self.cache_folder,filename)
114
self.load_page(self.cache_index["contents"][title.lower()]["title"],text,hm)
118
#print "LOAD error from cache"
121
#print "LOAD: online"
123
rep=self.api_query({"action":"parse","format":"json","page":title,"prop":"text"})
125
self.load_error_page(title,rep["error"]["info"],hm)
127
self.load_error_page(title,rep["error"]["info"],hm)
129
ptitle=rep["parse"]["title"]
130
ptext=rep["parse"]["text"]["*"]
132
#Store the page in the cache
135
filename=m.hexdigest()
136
filepath=path.join(self.cache_folder,filename)
139
f=codecs.open(filepath,encoding="utf-8",mode="w")
142
self.cache_index["contents"][ptitle.lower()]={"title":ptitle,"time":floor(time.time()),"type":"standard","filename":filename}
144
#Cache isn't working, but we should be OK
147
self.load_page(ptitle,ptext,hm)
149
def load_error_page(self,title,message,hm):
150
self.set_title("Error Loading Page - WikiTron")
151
self.main_webview.load_html_string(hconstants.eheader+message+hconstants.efooter,self.wiki_base_url)
154
self.pdata["history"].append({"time":time.time(), "page":title})
159
self.session_history_place-=1
162
self.session_history_place+=1
165
self.session_history=self.session_history[:self.session_history_place-1]
166
self.session_history.insert(self.session_history_place,title)
167
self.session_history_place+=1
169
self.update_back_forward_sens()
171
self.current_title=""
172
self.b_addbookmark.set_sensitive(False)
174
def load_page(self,title,text,hm):
175
self.set_title(title+" - WikiTron")
176
#+"<h1>"+title+"</h1>\n"+
177
self.main_webview.load_html_string(hconstants.header+text+hconstants.footer,self.wiki_base_url)
180
self.pdata["history"].append({"time":time.time(), "page":title})
182
#Update the session history
183
#print "LOADING: "+title
184
#print "\n\nBEFORE:\n"+str(self.session_history_place)+"\n"+str(self.session_history)
187
self.session_history_place-=1
190
self.session_history_place+=1
193
#print "Start with: "+str(self.session_history)
194
self.session_history=self.session_history[:self.session_history_place-1]
195
#print "Now: "+str(self.session_history)
196
self.session_history.insert(self.session_history_place,title)
197
#print "And after insert: "+str(self.session_history)
198
self.session_history_place+=1
200
#print "\n\nAFTER:\n"+str(self.session_history_place)+"\n"+str(self.session_history)
201
self.update_back_forward_sens()
203
self.current_title=title
204
if self.current_title in self.pdata["bookmarks"]:
205
self.b_addbookmark.set_sensitive(False)
207
self.b_addbookmark.set_sensitive(True)
210
def update_back_forward_sens(self):
211
if self.session_history_place>2:
212
self.b_back.set_sensitive(True)
214
self.b_back.set_sensitive(False)
215
if self.session_history_place<=len(self.session_history):
216
self.b_forward.set_sensitive(True)
218
self.b_forward.set_sensitive(False)
220
def main_policy_handler(self,webview,webframe,networkrequest,webnavigationaction,webpolicydecision):
221
target_url=webnavigationaction.get_original_uri()
222
#Check if its on the wiki
223
if target_url.startswith(self.wiki_base_url):
224
#Now check what type of link it is on the wiki
225
remainder=target_url[len(self.wiki_base_url):]
227
#Probably some special page - open in browser, to be safe
229
webbrowser.open(target_url)
231
elif remainder.startswith("/wiki/"):
232
#Looks like a wiki page
234
self.open_page_from_title(remainder[6:].replace("_"," "),0)
240
#Assume its not on the wiki, and open it in the default browser
242
webbrowser.open(target_url)
245
def closing_handler(self,a,b):
252
def cache_init(self):
253
from gi.repository import GLib
255
self.cache_folder=os.path.join(GLib.get_user_cache_dir(),"wikitron")
256
if not os.path.exists(self.cache_folder):
257
os.mkdir(self.cache_folder,0700)
258
self.cache_index_file=os.path.join(self.cache_folder,"index.json")
259
if os.path.exists(self.cache_index_file):
260
f=open(self.cache_index_file)
261
self.cache_index=json.load(f)
264
self.cache_index={"version":1, "contents":{}}
266
def cache_close(self):
268
if not os.path.exists(self.cache_folder):
269
os.mkdir(self.cache_folder,0700)
270
f=open(self.cache_index_file,"w")
271
json.dump(self.cache_index,f)
274
def empty_cache(self,a):
276
for i,d in self.cache_index["contents"].iteritems():
277
filename=self.cache_index["contents"][i]["filename"]
278
filepath=os.path.join(self.cache_folder,filename)
280
del self.cache_index["contents"]
281
self.cache_index["contents"]={}
283
def search_activated(self,button_obj):
284
self.open_page_from_title(button_obj.get_text(),0)
286
def search_image_activated(self,button_obj,a,b):
287
self.open_page_from_title(button_obj.get_text(),0)
289
def hbs_show(self,a):
290
self.mbs_win=BookmarksDialog.BookmarksDialog()
294
session_history_place=1
297
#Probably shouldn't call it like this
298
self.closing_handler(0,0)
302
self.main_webview.copy_clipboard()
304
def back_clicked(self,a):
305
target=self.session_history[self.session_history_place-3]
306
if type(target) is dict:
307
self.load_special_page(target["Spec"],-1)
309
self.open_page_from_title(target,-1)
311
def forward_clicked(self,b):
312
target=self.session_history[self.session_history_place-1]
313
if type(target) is dict:
314
self.load_special_page(target["Spec"],1)
316
self.open_page_from_title(target,1)
318
def unity_init(self):
319
ul=Unity.LauncherEntry.get_for_desktop_id ("extras-wikitron.desktop")
321
l=Dbusmenu.Menuitem.new()
322
i_mp=Dbusmenu.Menuitem.new()
323
i_mp.property_set (Dbusmenu.MENUITEM_PROP_LABEL, "Main Page")
324
i_mp.property_set_bool (Dbusmenu.MENUITEM_PROP_VISIBLE, True)
325
i_mp.connect("item-activated",self.unity_main_page)
328
i_b=Dbusmenu.Menuitem.new()
329
i_b.property_set (Dbusmenu.MENUITEM_PROP_LABEL, "Bookmarks")
330
i_b.property_set_bool (Dbusmenu.MENUITEM_PROP_VISIBLE, True)
331
i_b.connect("item-activated",self.unity_bookmarks)
334
i_h=Dbusmenu.Menuitem.new()
335
i_h.property_set (Dbusmenu.MENUITEM_PROP_LABEL, "History")
336
i_h.property_set_bool (Dbusmenu.MENUITEM_PROP_VISIBLE, True)
337
i_h.connect("item-activated",self.unity_history)
340
ul.set_property("quicklist", l)
342
def unity_main_page(self,a,b):
343
self.open_page_from_title("Main Page",0)
345
def unity_bookmarks(self,a,b):
346
self.load_special_page("Bookmarks",0)
348
def unity_history(self,a,b):
349
self.load_special_page("History",0)
354
def pdata_init(self):
355
from gi.repository import GLib
357
self.pdata_folder=os.path.join(GLib.get_user_config_dir(),"wikitron")
358
if not os.path.exists(self.pdata_folder):
359
os.mkdir(self.pdata_folder,0700)
360
self.pdata_file=os.path.join(self.pdata_folder,"pdata.json")
361
if os.path.exists(self.pdata_file):
362
f=open(self.pdata_file)
363
self.pdata=json.load(f)
366
self.pdata={"version":1, "history":[], "bookmarks":[]}
368
def pdata_close(self):
370
if not os.path.exists(self.pdata_folder):
371
os.mkdir(self.pdata_folder,0700)
372
f=open(self.pdata_file,"w")
373
json.dump(self.pdata,f)
378
def addbookmark_clicked(self,a):
379
if not self.current_title=="":
380
if not self.current_title in self.pdata["bookmarks"]:
381
self.pdata["bookmarks"].append(self.current_title)
382
self.b_addbookmark.set_sensitive(False)
384
def load_special_page(self,page,hm):
385
if page=="Bookmarks":
386
self.pdata["bookmarks"].sort()
388
for i in self.pdata["bookmarks"]:
389
content+="<li><a href=\""+self.wiki_base_url+"/wiki/"+i.replace(" ","_")+"\" title=\""+i+"\">"+i+"</a></li>\n"
391
elif page=="History":
392
dl=sorted(self.pdata["history"],key=lambda a:a["time"],reverse=True)
395
content+="<li><a href=\""+self.wiki_base_url+"/wiki/"+i["page"].replace(" ","_")+"\" title=\""+i["page"]+"\">"+i["page"]+"</a> <em>(Accessed on "+time.strftime("%A, %d of %B %Y at %I:%M:%S%p",time.localtime(i["time"]))+")</em></li>\n"
402
content=hconstants.special_page.replace("!TITLE!",page,1).replace("!CONTENTS!",content,1)
404
self.set_title(page+" - WikiTron")
405
self.main_webview.load_html_string(content,self.wiki_base_url)
410
self.session_history_place-=1
413
self.session_history_place+=1
416
self.session_history=self.session_history[:self.session_history_place-1]
417
self.session_history.insert(self.session_history_place,{"Spec":page})
418
self.session_history_place+=1
420
self.update_back_forward_sens()
422
self.current_title=""
423
self.b_addbookmark.set_sensitive(False)
425
def show_bookmarks(self,a):
426
self.load_special_page("Bookmarks",0)
428
def show_history(self,a):
429
self.load_special_page("History",0)