Initial commit
[comic-widget] / comic_widget.py
1 import hildon
2 import hildondesktop
3 import gtk
4 import csv
5 import urllib2
6 import urllib
7 import string
8 import os
9 import osso
10
11 # constants. dbfile is the location of the csv
12 # comiccache is the location of the images
13 dbfile = "/home/user/.comicdb.csv"
14 comiccache = "/home/user/MyDocs/comics/"
15 comics = {"xkcd":{"name":"xkcd","link":"http://xkcd.org/","start":666,"dbfile":"/home/user/.comicdb.xkcd.csv"},
16                 "sinfest":{"name":"Sinfest","link":"http://sinfest.com/","start":3400,"dbfile":"/home/user/.comicdb.sinfest.csv"}}
17
18 # handling of the comics
19 class ComicDb():
20         def __init__(self, comic):
21                 #if no db, start from this comic id.
22                 self.comic = comic
23                 self.start = comics[self.comic]["start"]
24                 self.dbfile = comics[self.comic]["dbfile"]
25
26                 #if db file exist, read it
27                 if os.path.isfile(self.dbfile) == True:
28                         dbf = open(self.dbfile, 'r')
29                 # if not, create it.
30                 else:
31                         dbf = open(self.dbfile, 'w')
32                         dbf.write('comic,id,link,url,filename,title\n')
33                         dbf.close()
34                         dbf = open(self.dbfile, 'r')
35                         self.fetch_latest_std(self.comic, self.start)
36
37                 if not os.path.exists(comiccache + self.comic + "/"):
38                         os.makedirs(comiccache + self.comic + "/")
39                 dbr = csv.DictReader(dbf)
40                 self.db = []
41                 for row in dbr:
42                         self.db.insert(0,row)
43                 dbf.close()
44                 self.currentcomic = 0
45
46         def get_comic(self):
47                 print str(self.currentcomic)
48                 if self.currentcomic < 0:
49                         self.refresh()
50                         self.currentcomic = 0
51                 if  len(self.db) < (self.currentcomic + 1):
52                         self.currentcomic -= 1
53                         self.refresh()
54                         self.currentcomic = len(self.db) - 1
55                         
56                 dbrow = self.db[self.currentcomic]
57                 filename = comiccache + self.comic + "/" + dbrow['filename']
58                 print filename + "\n"
59                 
60                 if os.path.isfile(filename):
61                         print "found, returning " + filename + "\n"
62                         return filename
63                 else:
64                         #fetch file
65                         print filename + " not found\nretrieving " + dbrow['url'] + "\n"
66                         urllib.urlretrieve(dbrow['url'], filename)
67                         print "success\n"
68                         return filename
69
70         def get_current_row(self):
71                 return self.db[self.currentcomic]               
72
73         def get_link(self):
74                 print str(self.currentcomic)
75                 if self.currentcomic < 0:
76                         self.refresh()
77                         self.currentcomic = 0
78                 if  len(self.db) < (self.currentcomic + 1):
79                         self.currentcomic -= 1
80                 return self.db[self.currentcomic]['link']
81
82
83
84         def insert_row(self, irow):
85                 dbf = open(self.dbfile, 'a')
86                 dbw = csv.writer(dbf)
87                 dbw.writerow(irow)
88                 dbf.close()
89
90         def insert_row_first(self, irow):
91                 dbf = open(self.dbfile, 'w')
92                 dbf.write('comic,id,link,url,filename,title\n')
93                 dbw = csv.writer(dbf)
94                 dbw.writerow(irow)
95                 dbf.close()
96                 dbf = open(self.dbfile, 'a')
97                 dbw = csv.DictWriter(dbf, ['comic','id','link','url','filename','title'])
98                 tmpdb = self.db
99                 tmpdb.reverse()
100                 for row in tmpdb:
101                         dbw.writerow(row)
102                 dbf.close()
103
104         def refresh(self):
105                 if len(self.db) < 1:
106                         self.fetch_latest_std(self.comic, self.start)
107                 elif self.currentcomic == 0 or self.currentcomic < 0:
108                         self.fetch_latest_std(self.comic, self.db[0]['id'])
109                 elif self.currentcomic == (len(self.db) - 1):
110                         self.fetch_earlier(self.comic, self.db[self.currentcomic]['id'])
111                 dbf = open(self.dbfile, 'r')
112                 dbr = csv.DictReader(dbf)
113                 self.db = []
114                 for row in dbr:
115                         self.db.insert(0,row)
116                 dbf.close()
117
118         def fetch_earlier(self, comic, earliest):
119                 number = int(earliest) - 1
120                 if number < 0:
121                         return False
122                 print "number is now: " + str(number) + "\n"
123                 if comic == 'xkcd':
124                         link = "http://xkcd.org/" + str(number) + "/"
125                 elif comic == 'sinfest':
126                         link = "http://www.sinfest.net/archive_page.php?comicID=" + str(number)
127                 else:
128                         return False
129                 print "link: " + link + "\n"
130                 try:
131                         f = urllib2.urlopen(link)
132                         hcode = f.code
133                 except:
134                         hcode = 404
135                 print "got hcode = " + str(hcode) + "\n"
136                 if (hcode != 200):
137                         return False
138                 else:
139                         # Build db entry.
140                         # they look like: comic,id,link,url,filename,title
141                         # We already have comic, number/id and link
142                         
143                         if comic == 'xkcd':
144                                 s = f.read()
145                                 f.close()
146                                 splt = string.split(s, "<h3>Image URL (for hotlinking/embedding): ", 1)
147                                 splt2 = string.split(splt[1], "</h3>", 1)
148                                 url = splt2[0]
149                                 splt = string.split(splt[0], "<h1>", 1)
150                                 splt = string.split(splt[1], "</h1>", 1)
151                                 title = splt[0]
152
153                         elif comic == 'sinfest':
154                                 s = f.read()
155                                 f.close()
156                                 splt = string.split(s, 'height="107"', 1)
157                                 splt = string.split(splt[1], '<img src="', 1)
158                                 splt = string.split(splt[1], '" alt="', 1)
159                                 url = splt[0]
160                                 if len(url) < 49:
161                                         print "Fake 404! Break break break!"
162                                         return False
163                                 splt = string.split(splt[1], '" border="0" />', 1)
164                                 title = splt[0]
165                         splt2 = string.rsplit(url, "/", 1)
166                         filename = splt2[1]                             
167                         irow = [comic,number,link,url,filename,title]
168                         print "got irow: "
169                         print irow
170                         print "\ninserting first...\n"
171                         self.insert_row_first(irow)
172
173
174         def fetch_latest_std(self, comic, latest):
175                 
176                 print "fetching new after " + str(comic) + " " + str(latest) + "\n"
177                 hcode = 200
178                 number = int(latest) + 1
179                 while hcode == 200:
180                         print "number is now: " + str(number) + "\n"
181                         if comic == 'xkcd':
182                                 link = "http://xkcd.org/" + str(number) + "/"
183                         elif comic == 'sinfest':
184                                 link = "http://www.sinfest.net/archive_page.php?comicID=" + str(number)
185                         else:
186                                 break
187                         print "link: " + link + "\n"
188                         try:
189                                 f = urllib2.urlopen(link)
190                                 hcode = f.code
191                         except:
192                                 hcode = 404
193                         print "got hcode = " + str(hcode) + "\n"
194                         if (hcode != 200):
195                                 break
196                         else:
197                                 # Build db entry.
198                                 # they look like: comic,id,link,url,filename,title
199                                 # We already have comic, number/id and link
200                                 
201                                 if comic == 'xkcd':
202                                         s = f.read()
203                                         f.close()
204                                         splt = string.split(s, "<h3>Image URL (for hotlinking/embedding): ", 1)
205                                         splt2 = string.split(splt[1], "</h3>", 1)
206                                         url = splt2[0]
207                                         splt = string.split(splt[0], "<h1>", 1)
208                                         splt = string.split(splt[1], "</h1>", 1)
209                                         title = splt[0]
210
211                                 elif comic == 'sinfest':
212                                         s = f.read()
213                                         f.close()
214                                         splt = string.split(s, 'height="107"', 1)
215                                         splt = string.split(splt[1], '<img src="', 1)
216                                         splt = string.split(splt[1], '" alt="', 1)
217                                         url = splt[0]
218                                         if len(url) < 49:
219                                                 print "Fake 404! Break break break!"
220                                                 break
221                                         splt = string.split(splt[1], '" border="0" />', 1)
222                                         title = splt[0]
223
224                                 splt2 = string.rsplit(url, "/", 1)
225                                 filename = splt2[1]                                     
226                                 irow = [comic,number,link,url,filename,title]
227                                 print "got irow: "
228                                 print irow
229                                 print "\ninserting...\n"
230                                 
231                                 self.insert_row(irow)
232
233                         number += 1
234
235 class ComicHomePlugin(hildondesktop.HomePluginItem):
236         def __init__(self):
237                 hildondesktop.HomePluginItem.__init__(self)
238                 self.osso_c = osso.Context("comic_widget", "0.0.1", False)
239                 self.osso_rpc = osso.Rpc(self.osso_c)
240                 self.keys = comics.keys()
241                 self.keypointer = 1
242                 self.db = ComicDb(self.keys[self.keypointer])
243                 self.comicname = comics[self.keys[self.keypointer]]['name']
244                 screen = self.get_screen()
245                 colormap = screen.get_rgba_colormap()
246                 self.set_colormap(colormap)
247                 #setup internal area
248                 self.set_size_request(480, 230)
249                 self.imgvpos = 0;
250                 self.vbox = gtk.VBox()
251                 self.hbox = gtk.HBox()
252                 self.label = gtk.Label(self.comicname + " " + str(self.db.db[self.db.currentcomic]['id']))
253                 self.e_goweb = gtk.EventBox()
254                 self.e_open = gtk.EventBox()
255                 self.e_switch = gtk.EventBox()
256                 self.e_next = gtk.EventBox()
257                 self.e_prev = gtk.EventBox()
258                 self.e_up = gtk.EventBox()
259                 self.e_down = gtk.EventBox()
260                 self.comic_image = self.get_resized_pixmap(self.db.get_comic(), self.imgvpos)
261                 self.comic_image.show()
262                 self.next = gtk.image_new_from_file("/home/user/comic_widget/right.png")
263                 self.prev = gtk.image_new_from_file("/home/user/comic_widget/left.png")
264                 self.up = gtk.image_new_from_file("/home/user/comic_widget/up.png")
265                 self.down = gtk.image_new_from_file("/home/user/comic_widget/down.png")
266                 self.switch = gtk.image_new_from_file("/home/user/comic_widget/star.png")
267
268                 self.e_goweb.add(self.label)
269                 self.e_goweb.set_events(gtk.gdk.BUTTON_PRESS_MASK)
270                 self.e_goweb.connect("button-press-event", self.view_comic)
271
272                 self.e_open.add(self.comic_image)
273
274                 self.e_switch.add(self.switch)
275                 self.e_switch.set_events(gtk.gdk.BUTTON_PRESS_MASK)
276                 self.e_switch.connect("button-press-event", self.switch_comic)
277
278
279                 self.e_next.add(self.next)
280                 self.e_next.set_events(gtk.gdk.BUTTON_PRESS_MASK)
281                 self.e_next.connect("button-press-event", self.get_next)
282
283                 self.e_prev.add(self.prev)
284                 self.e_prev.set_events(gtk.gdk.BUTTON_PRESS_MASK)
285                 self.e_prev.connect("button_press_event", self.get_prev)
286
287                 self.e_up.add(self.up)
288                 self.e_up.set_events(gtk.gdk.BUTTON_PRESS_MASK)
289                 self.e_up.connect("button-press-event", self.scroll_up)
290
291                 self.e_down.add(self.down)
292                 self.e_down.set_events(gtk.gdk.BUTTON_PRESS_MASK)
293                 self.e_down.connect("button-press-event", self.scroll_down)
294
295                 self.vbox.pack_start(self.e_open,False,False,0)
296                 self.vbox.pack_end(self.hbox,False,False,0)
297
298                 self.hbox.pack_start(self.e_switch,False,False,5)
299                 self.hbox.pack_start(self.e_goweb,False,False,5)
300                 self.hbox.pack_end(self.e_next,False,False,5)
301                 self.hbox.pack_end(self.e_down,False,False,5)
302                 self.hbox.pack_end(self.e_up,False,False,5)
303                 self.hbox.pack_end(self.e_prev,False,False,5)
304                 self.vbox.show_all()
305                 self.add(self.vbox)
306
307
308         def switch_comic(self, widget, event):
309                 if not event.type == gtk.gdk.BUTTON_PRESS:
310                         return False
311                 self.keypointer = (self.keypointer + 1) % 2
312                 self.imgvpos = 0
313                 self.db = []
314                 print "switching to " + self.keys[self.keypointer]
315                 self.comicname = comics[self.keys[self.keypointer]]['name']
316                 self.db = ComicDb(self.keys[self.keypointer])
317                 self.e_goweb.remove(self.label)
318                 self.label = gtk.Label(self.comicname + " " + str(self.db.db[self.db.currentcomic]['id']))
319                 self.e_goweb.add(self.label)
320                 self.e_goweb.show_all()
321                 self.e_open.remove(self.comic_image)
322                 self.comic_image = self.get_resized_pixmap(self.db.get_comic(), self.imgvpos)
323                 self.e_open.add(self.comic_image)
324                 self.e_open.show_all()          
325
326         def switch_rel(self, widget, event):
327                 if not event.type == gtk.gdk.BUTTON_RELEASE:
328                         return False
329                 widget.remove(self.switch)
330                 self.switch = gtk.image_new_from_file("/home/user/comic_widget/star.png")
331                 widget.add(self.switch)
332                 widget.show_all()
333
334         def view_comic(self, widget, event):
335                 if not event.type == gtk.gdk.BUTTON_PRESS:
336                         return False
337                 link = self.db.get_link()
338                 self.osso_rpc.rpc_run_with_defaults("osso_browser", "open_new_window", (link,))
339
340         def scroll_down(self, widget, event):
341                 if not event.type == gtk.gdk.BUTTON_PRESS:
342                         return False
343                 self.e_open.remove(self.comic_image)
344                 self.imgvpos = self.imgvpos + 50
345                 self.comic_image = self.get_resized_pixmap(self.db.get_comic(), self.imgvpos)
346                 self.e_open.add(self.comic_image)
347                 self.e_open.show_all()
348
349         def scroll_up(self, widget, event):
350                 if not event.type == gtk.gdk.BUTTON_PRESS:
351                         return False
352                 self.e_open.remove(self.comic_image)
353                 self.imgvpos = self.imgvpos - 50
354                 if self.imgvpos < 0:
355                         self.imgvpos = 0
356                 self.comic_image = self.get_resized_pixmap(self.db.get_comic(), self.imgvpos)
357                 self.e_open.add(self.comic_image)
358                 self.e_open.show_all()
359
360         def get_next(self, widget, event):
361                 if not event.type == gtk.gdk.BUTTON_PRESS:
362                         return False
363                 self.db.currentcomic -= 1
364                 self.imgvpos = 0
365                 self.e_open.remove(self.comic_image)
366                 self.comic_image = self.get_resized_pixmap(self.db.get_comic(), self.imgvpos)
367                 self.e_open.add(self.comic_image)
368                 self.e_open.show_all()
369                 self.e_goweb.remove(self.label)
370                 self.label = gtk.Label(self.comicname + " " + str(self.db.db[self.db.currentcomic]['id']))
371                 self.e_goweb.add(self.label)
372                 self.e_goweb.show_all()
373                         
374         def get_prev(self, widget, event):
375                 if not event.type == gtk.gdk.BUTTON_PRESS:
376                         return False
377                 self.db.currentcomic += 1
378                 self.imgvpos = 0
379                 self.e_open.remove(self.comic_image)
380                 self.comic_image = self.get_resized_pixmap(self.db.get_comic(), self.imgvpos)
381                 self.e_open.add(self.comic_image)
382                 self.e_open.show_all()
383                 self.e_goweb.remove(self.label)
384                 self.label = gtk.Label(self.comicname + " " + str(self.db.db[self.db.currentcomic]['id']))
385                 self.e_goweb.add(self.label)
386                 self.e_goweb.show_all()
387
388         def get_resized_pixmap(self, filename, vpos):
389                 pixbuf = gtk.gdk.pixbuf_new_from_file(filename)
390                 parent_buf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, pixbuf.get_has_alpha(), 8, 478, 190)
391                 parent_buf.fill(0x00000000)
392                 retimg = gtk.Image()
393                 # get correct width/height
394                 new_width = 0
395                 new_height = 1
396                 new_width = 478
397                 new_height = int((478.0 / pixbuf.get_width()) * pixbuf.get_height())
398                 scaled_buf = pixbuf.scale_simple(new_width,new_height,gtk.gdk.INTERP_BILINEAR)
399
400                 if scaled_buf.get_height() > 190:
401                         if scaled_buf.get_height() - (vpos + 190) < 0:
402                                 vpos = scaled_buf.get_height() - 190
403                         scaled_buf.copy_area(0,vpos,478,190,parent_buf,0,0)
404
405                 else:
406                         tmpy = 190 - scaled_buf.get_height()
407                         if tmpy > 0:
408                                 tmpy = tmpy / 2
409
410                         scaled_buf.copy_area(0,vpos,478,scaled_buf.get_height(),parent_buf,0,tmpy)
411
412                 retimg.set_from_pixbuf(parent_buf)
413                 return retimg
414
415
416 hd_plugin_type = ComicHomePlugin
417
418
419 if __name__ == "__main__":
420         import gobject
421         gobject.type_register(hd_plugin_type)
422         obj = gobject.new(hd_plugin_type, plugin_id="plugin_id")
423         obj.show_all()
424         gtk.main()