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