~ubuntu-app-review-contributors/ubuntu-app-reviews/wikitron

« back to all changes in this revision

Viewing changes to wikitron/WikitronWindow.py

  • Committer: App Bot
  • Author(s): Thomas Hearing
  • Date: 2012-07-09 04:15:05 UTC
  • Revision ID: appbot@holba.ch-20120709041505-2gmxb7nvg0zoqnz4
Tags: 12.07.2
New release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
 
2
### BEGIN LICENSE
 
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.
 
7
 
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.
 
12
 
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/>.
 
15
### END LICENSE
 
16
 
 
17
import gettext
 
18
from gettext import gettext as _
 
19
gettext.textdomain('wikitron')
 
20
 
 
21
from gi.repository import Gtk, WebKit, Unity, Dbusmenu # pylint: disable=E0611
 
22
import logging
 
23
logger = logging.getLogger('wikitron')
 
24
 
 
25
from wikitron_lib import Window
 
26
from wikitron.AboutWikitronDialog import AboutWikitronDialog
 
27
from wikitron.PreferencesWikitronDialog import PreferencesWikitronDialog
 
28
 
 
29
import time
 
30
from math import floor
 
31
 
 
32
import BookmarksDialog
 
33
import hconstants
 
34
# See wikitron_lib.Window.py for more details about how this class works
 
35
class WikitronWindow(Window):
 
36
    __gtype_name__ = "WikitronWindow"
 
37
    
 
38
    wiki_base_url="http://en.wikipedia.org"
 
39
    wiki_api_url="http://en.wikipedia.org/w/api.php"
 
40
    main_webview=0
 
41
    main_scrollview=0
 
42
    mbs_win=0
 
43
    b_back=0
 
44
    b_forward=0
 
45
    b_addbookmark=0
 
46
    def finish_initializing(self, builder): # pylint: disable=E1002
 
47
        """Set up the main window"""
 
48
        super(WikitronWindow, self).finish_initializing(builder)
 
49
 
 
50
        self.AboutDialog = AboutWikitronDialog
 
51
        self.PreferencesDialog = PreferencesWikitronDialog
 
52
 
 
53
        # Code for other initialization actions should be added here.
 
54
        self.pdata_init()
 
55
        self.cache_init()
 
56
        self.connect("delete-event",self.closing_handler)
 
57
        self.main_webview=WebKit.WebView()
 
58
        self.apply_config()
 
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)
 
64
        self.show_all()
 
65
        
 
66
        self.unity_init()        
 
67
        
 
68
        self.main_webview.connect("navigation-policy-decision-requested",self.main_policy_handler)
 
69
        self.open_page_from_title("Main Page",0)
 
70
        
 
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)
 
78
        
 
79
    def api_query(self,params):
 
80
        try:
 
81
            import urllib2, json
 
82
            apiurl=self.wiki_api_url+"?"
 
83
            for i,d in params.iteritems():
 
84
                apiurl+=i+"="+urllib2.quote(d)+"&"
 
85
            apiurl=apiurl[:-1]
 
86
            req=urllib2.Request(apiurl)
 
87
            #Add a url
 
88
            req.add_header("User-Agent","WikiTron")
 
89
            reply=urllib2.urlopen(req)
 
90
            replytext=reply.read()
 
91
            reply.close()
 
92
            #print "\n\n"+replytext+"\n\n"
 
93
            return json.loads(replytext)
 
94
        except:
 
95
            return False
 
96
        
 
97
    def open_page_from_title(self,title,hm):
 
98
        import hashlib
 
99
        from os import path
 
100
        if title.lower() in self.cache_index["contents"]:
 
101
            #print "Checking LOAD"
 
102
            #print ""
 
103
            if (self.cache_index["contents"][title.lower()]["time"]+(60*60*6)) > time.time():
 
104
                #print "LOAD: cache"
 
105
                #recent copy in cache. load from there
 
106
                try:
 
107
                    filename=self.cache_index["contents"][title.lower()]["filename"]
 
108
                    filepath=path.join(self.cache_folder,filename)
 
109
                    #print "1"
 
110
                    f=open(filepath)
 
111
                    text=f.read()
 
112
                    f.close()
 
113
                    #print "2"
 
114
                    self.load_page(self.cache_index["contents"][title.lower()]["title"],text,hm)
 
115
                    #print "LOAD ok"
 
116
                    return
 
117
                except:
 
118
                    #print "LOAD error from cache"
 
119
                    pass
 
120
            
 
121
        #print "LOAD: online"
 
122
        #Request the page
 
123
        rep=self.api_query({"action":"parse","format":"json","page":title,"prop":"text"})
 
124
        if rep == False:
 
125
            self.load_error_page(title,rep["error"]["info"],hm)
 
126
        elif "error" in rep:
 
127
            self.load_error_page(title,rep["error"]["info"],hm)
 
128
        else:
 
129
            ptitle=rep["parse"]["title"]
 
130
            ptext=rep["parse"]["text"]["*"]
 
131
            
 
132
            #Store the page in the cache
 
133
            m=hashlib.md5()
 
134
            m.update(ptitle)
 
135
            filename=m.hexdigest()
 
136
            filepath=path.join(self.cache_folder,filename)
 
137
            try:
 
138
                import codecs
 
139
                f=codecs.open(filepath,encoding="utf-8",mode="w")
 
140
                f.write(ptext)
 
141
                f.close()
 
142
                self.cache_index["contents"][ptitle.lower()]={"title":ptitle,"time":floor(time.time()),"type":"standard","filename":filename}
 
143
            except:
 
144
                #Cache isn't working, but we should be OK
 
145
                pass
 
146
            #Display the page
 
147
            self.load_page(ptitle,ptext,hm)
 
148
        
 
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)
 
152
        
 
153
        #Update the history
 
154
        self.pdata["history"].append({"time":time.time(), "page":title})
 
155
        
 
156
        #Update the history
 
157
        if hm == (-1):
 
158
            #Going back
 
159
            self.session_history_place-=1
 
160
        elif hm == 1:
 
161
            #Going forward
 
162
            self.session_history_place+=1
 
163
        else:
 
164
            #Normal navigation
 
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
 
168
            
 
169
        self.update_back_forward_sens()
 
170
        
 
171
        self.current_title=""
 
172
        self.b_addbookmark.set_sensitive(False)
 
173
        
 
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)
 
178
        
 
179
        #Update the history
 
180
        self.pdata["history"].append({"time":time.time(), "page":title})
 
181
        
 
182
        #Update the session history
 
183
        #print "LOADING: "+title
 
184
        #print "\n\nBEFORE:\n"+str(self.session_history_place)+"\n"+str(self.session_history)
 
185
        if hm == (-1):
 
186
            #Going back
 
187
            self.session_history_place-=1
 
188
        elif hm == 1:
 
189
            #Going forward
 
190
            self.session_history_place+=1
 
191
        else:
 
192
            #Normal navigation
 
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
 
199
            
 
200
        #print "\n\nAFTER:\n"+str(self.session_history_place)+"\n"+str(self.session_history)
 
201
        self.update_back_forward_sens()
 
202
        
 
203
        self.current_title=title
 
204
        if self.current_title in self.pdata["bookmarks"]:
 
205
            self.b_addbookmark.set_sensitive(False)
 
206
        else:
 
207
            self.b_addbookmark.set_sensitive(True)
 
208
        
 
209
        
 
210
    def update_back_forward_sens(self):
 
211
        if self.session_history_place>2:
 
212
            self.b_back.set_sensitive(True)
 
213
        else:
 
214
            self.b_back.set_sensitive(False)
 
215
        if self.session_history_place<=len(self.session_history):
 
216
            self.b_forward.set_sensitive(True)
 
217
        else:
 
218
            self.b_forward.set_sensitive(False)
 
219
        
 
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):]
 
226
            if ":" in remainder:
 
227
                #Probably some special page - open in browser, to be safe
 
228
                import webbrowser
 
229
                webbrowser.open(target_url)
 
230
                return True
 
231
            elif remainder.startswith("/wiki/"):
 
232
                #Looks like a wiki page
 
233
                try:
 
234
                    self.open_page_from_title(remainder[6:].replace("_"," "),0)
 
235
                except:
 
236
                    pass
 
237
                return True
 
238
            #Not sure what it is
 
239
            return False
 
240
        #Assume its not on the wiki, and open it in the default browser
 
241
        import webbrowser
 
242
        webbrowser.open(target_url)
 
243
        return True
 
244
    
 
245
    def closing_handler(self,a,b):
 
246
        self.cache_close()
 
247
        self.pdata_close()
 
248
    
 
249
    cache_index={}
 
250
    cache_index_file=""
 
251
    cache_folder=""
 
252
    def cache_init(self):
 
253
        from gi.repository import GLib
 
254
        import os, json
 
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)
 
262
            f.close()
 
263
        else:
 
264
            self.cache_index={"version":1, "contents":{}}
 
265
            
 
266
    def cache_close(self):
 
267
        import json, os
 
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)
 
272
        f.close()
 
273
        
 
274
    def empty_cache(self,a):
 
275
        import os
 
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)
 
279
            os.remove(filepath)
 
280
        del self.cache_index["contents"]
 
281
        self.cache_index["contents"]={}
 
282
    
 
283
    def search_activated(self,button_obj):
 
284
        self.open_page_from_title(button_obj.get_text(),0)
 
285
    
 
286
    def search_image_activated(self,button_obj,a,b):
 
287
        self.open_page_from_title(button_obj.get_text(),0)
 
288
        
 
289
    def hbs_show(self,a):
 
290
        self.mbs_win=BookmarksDialog.BookmarksDialog()
 
291
        self.mbs_win.run()
 
292
    
 
293
    session_history=[]
 
294
    session_history_place=1
 
295
    
 
296
    def m_quit(self,a):
 
297
        #Probably shouldn't call it like this
 
298
        self.closing_handler(0,0)
 
299
        self.destroy()
 
300
    
 
301
    def m_copy(self,a):
 
302
        self.main_webview.copy_clipboard()
 
303
    
 
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)
 
308
        else:
 
309
            self.open_page_from_title(target,-1)
 
310
        
 
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)
 
315
        else:
 
316
            self.open_page_from_title(target,1)
 
317
        
 
318
    def unity_init(self):
 
319
        ul=Unity.LauncherEntry.get_for_desktop_id ("extras-wikitron.desktop")
 
320
        
 
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)
 
326
        l.child_append(i_mp)
 
327
        
 
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)
 
332
        l.child_append(i_b)
 
333
        
 
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)
 
338
        l.child_append(i_h)
 
339
        
 
340
        ul.set_property("quicklist", l)
 
341
        
 
342
    def unity_main_page(self,a,b):
 
343
        self.open_page_from_title("Main Page",0)
 
344
        
 
345
    def unity_bookmarks(self,a,b):
 
346
        self.load_special_page("Bookmarks",0)
 
347
        
 
348
    def unity_history(self,a,b):
 
349
        self.load_special_page("History",0)
 
350
        
 
351
    pdata={}
 
352
    pdata_file=""
 
353
    pdata_folder=""
 
354
    def pdata_init(self):
 
355
        from gi.repository import GLib
 
356
        import os, json
 
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)
 
364
            f.close()
 
365
        else:
 
366
            self.pdata={"version":1, "history":[], "bookmarks":[]}
 
367
            
 
368
    def pdata_close(self):
 
369
        import json, os
 
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)
 
374
        f.close()
 
375
    
 
376
    current_title=""
 
377
    
 
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)
 
383
                
 
384
    def load_special_page(self,page,hm):
 
385
        if page=="Bookmarks":
 
386
            self.pdata["bookmarks"].sort()
 
387
            content="<ul>\n"
 
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"
 
390
            content+="</ul>"
 
391
        elif page=="History":
 
392
            dl=sorted(self.pdata["history"],key=lambda a:a["time"],reverse=True)
 
393
            content="<ul>\n"
 
394
            for i in dl:
 
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"
 
396
            content+="</ul>"
 
397
        else:
 
398
            content="Error"
 
399
        #print "\n\n"
 
400
        #print content
 
401
        #print "\n\n"
 
402
        content=hconstants.special_page.replace("!TITLE!",page,1).replace("!CONTENTS!",content,1)
 
403
        
 
404
        self.set_title(page+" - WikiTron")
 
405
        self.main_webview.load_html_string(content,self.wiki_base_url)
 
406
        
 
407
        #Update the history
 
408
        if hm == (-1):
 
409
            #Going back
 
410
            self.session_history_place-=1
 
411
        elif hm == 1:
 
412
            #Going forward
 
413
            self.session_history_place+=1
 
414
        else:
 
415
            #Normal navigation
 
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
 
419
            
 
420
        self.update_back_forward_sens()
 
421
        
 
422
        self.current_title=""
 
423
        self.b_addbookmark.set_sensitive(False)
 
424
    
 
425
    def show_bookmarks(self,a):
 
426
        self.load_special_page("Bookmarks",0)
 
427
    
 
428
    def show_history(self,a):
 
429
        self.load_special_page("History",0)