X-Git-Url: http://git.maemo.org/git/?p=comic-widget;a=blobdiff_plain;f=src%2Fusr%2Flib%2Fhildon-desktop%2Fcomicwidget.py;h=20b5eb4f09938b318811a7575ecc220d102eb1eb;hp=984470e67eb55ad84a44f3f711925c685a0a9104;hb=7e59ecdfa54de46c7c6e6c862498bdc8f659d37a;hpb=40d9e0fd70097f0eece19f0f1d9911956bdf0575 diff --git a/src/usr/lib/hildon-desktop/comicwidget.py b/src/usr/lib/hildon-desktop/comicwidget.py index 984470e..20b5eb4 100644 --- a/src/usr/lib/hildon-desktop/comicwidget.py +++ b/src/usr/lib/hildon-desktop/comicwidget.py @@ -11,21 +11,36 @@ import osso import cairo import datetime import shutil +import sys supports_alpha = False +# LOGGING! +# sys.stdout = open('/home/user/.comic-widget/output_log.txt', 'a') +# sys.stderr = open('/home/user/.comic-widget/error_log.txt', 'a') +# print "Start logging!" + # constants. dbfile is the location of the csv # comiccache is the location of the images -APP_VERSION = "0.2.5" +APP_VERSION = "0.3.2-2" basedbdir = "/opt/comic-widget/db/" imagedir = "/opt/comic-widget/images/" dbdir = "/home/user/.comic-widget/" +activecomics = dbdir + "activecomics.cfg" comiccache = "/home/user/MyDocs/.comics/" comics = {"xkcd":{"name":"xkcd","link":"http://xkcd.org/","start":666,"dbfile":dbdir + "comicdb.xkcd.csv"}, "sinfest":{"name":"Sinfest","link":"http://sinfest.com/","start":3400,"dbfile":dbdir + "comicdb.sinfest.csv"}, "phd":{"name":"PHD Comics","link":"http://www.phdcomics.com/","start":1240,"dbfile":dbdir + "comicdb.phd.csv"}, - "dilbert":{"name":"Dilbert","link":"http://dilbert.com.com/","start":"2009-01-01","dbfile":dbdir + "comicdb.dilbert.csv"}} + "dilbert":{"name":"Dilbert","link":"http://dilbert.com/","start":"2009-01-01","dbfile":dbdir + "comicdb.dilbert.csv"}, + "cyanide":{"name":"C and H","link":"http://explosm.com/","start":"1920","dbfile":dbdir + "comicdb.cyanide.csv"}, + } +defaults = {'width':480,'height':230} +#defaults = {'width':480,'height':240} +sizefile = "/home/user/.comic-widget/size.cfg" +previous = False +next = False + # handling of the comics class ComicDb(): @@ -44,6 +59,8 @@ class ComicDb(): for row in dbr: self.db.insert(0,row) dbf.close() + if len(self.db) == 0: + self.refresh() self.currentcomic = 0 @@ -73,6 +90,7 @@ class ComicDb(): dbf = open(self.dbfile, 'w') dbf.write('comic,id,link,url,filename,title\n') dbf.close() + if os.path.isfile(self.dbfile) == True: dbf = open(self.dbfile, 'r') return dbf @@ -83,10 +101,20 @@ class ComicDb(): def get_comic(self): print str(self.currentcomic) if self.currentcomic < 0: - self.refresh() self.currentcomic = 0 + if len(self.db) > 0: + fetchid = self.db[self.currentcomic]['id'] + else: + fetchid = comics[self.comic]['start'] + self.fetch_newer(self.comic, fetchid) + self.refresh() if len(self.db) < (self.currentcomic + 1): - self.currentcomic -= 1 + self.currentcomic = len(self.db) - 1 + if len(self.db) > 0: + fetchid = self.db[self.currentcomic]['id'] + else: + fetchid = comics[self.comic]['start'] + self.fetch_earlier(self.comic, fetchid) self.refresh() self.currentcomic = len(self.db) - 1 @@ -146,12 +174,13 @@ class ComicDb(): dbf.close() def refresh(self): - if len(self.db) < 1: - self.fetch_latest_std(self.comic, self.start) - elif self.currentcomic == 0 or self.currentcomic < 0: - self.fetch_latest_std(self.comic, self.db[0]['id']) - elif self.currentcomic == (len(self.db) - 1): - self.fetch_earlier(self.comic, self.db[self.currentcomic]['id']) + # if len(self.db) < 1: + # self.currentcomic = -1 + # self.fetch_latest_std(self.comic, self.start) + # elif self.currentcomic == 0 or self.currentcomic < 0: + # self.fetch_latest_std(self.comic, self.db[0]['id']) + # elif self.currentcomic == (len(self.db) - 1): + # self.fetch_earlier(self.comic, self.db[self.currentcomic]['id']) dbf = open(self.dbfile, 'r') dbr = csv.DictReader(dbf) self.db = [] @@ -159,8 +188,14 @@ class ComicDb(): self.db.insert(0,row) dbf.close() + +# fetch earlier def fetch_earlier(self, comic, earliest): - if len(earliest) == 10: + print "fetch before, " + comic + " earliest" + if comic == "cyanide": + comicid = self.get_prev_id(comic,earliest) + print "got " + comicid + " as the one before current..." + elif len(earliest) == 10: # date id. dt = string.split(earliest, "-") d = datetime.date(int(dt[0]),int(dt[1]),int(dt[2])) @@ -170,49 +205,170 @@ class ComicDb(): comicid = int(earliest) - 1 irow = self.get_irow(comic, comicid) - if irow: + if irow and irow[0] == "skip": + print "problem with this one, fetching " + str(irow[2]) + " instead." + irow = self.get_irow(comic, irow[2]) + + if irow and len(irow) > 3: print "got irow: " print irow - print "\ninserting first...\n" - self.insert_row_first(irow) + print "\ninserting...\n" + self.insert_row_first([irow[0],irow[1],irow[2],irow[3],irow[4],irow[5]]) else: print "No comic found at " + comicid - def fetch_latest_std(self, comic, latest): - print "fetching new after " + str(comic) + " " + str(latest) - dateid = False - if len(str(latest)) == 10: + + + + + def fetch_newer(self, comic, newest): + if comic == "cyanide": + comicid = self.get_next_id(comic,newest) + elif len(newest) == 10: # date id. - dateid = True - dt = string.split(latest, "-") + dt = string.split(newest, "-") d = datetime.date(int(dt[0]),int(dt[1]),int(dt[2])) - newer = d + datetime.timedelta( 1 ) - comicid = newer.isoformat() + newest = d + datetime.timedelta( 1 ) + comicid = newest.isoformat() + else: + comicid = int(newest) + 1 + + irow = self.get_irow(comic, comicid) + if irow and irow[0] == "skip": + print "problem with this one, fetching " + str(irow[1]) + " instead." + irow = self.get_irow(comic, irow[1]) + + if irow and len(irow) > 3: + print "got irow: " + print irow + print "\ninserting...\n" + self.insert_row([irow[0],irow[1],irow[2],irow[3],irow[4],irow[5]]) else: - comicid = int(latest) + 1 + print "No comic found at " + str(comicid) + + - lasturl = self.db[0]['url'] + + def fetch_latest_std(self, comic, latest): + print "fetching new after " + str(comic) + " " + str(latest) + next = False + dateid = False + if comic == 'cyanide': + next = self.get_next_id(comic, latest) + if not next: + return + else: + comicid = next + else: + if len(str(latest)) == 10: + # date id. + dateid = True + dt = string.split(latest, "-") + d = datetime.date(int(dt[0]),int(dt[1]),int(dt[2])) + newer = d + datetime.timedelta( 1 ) + comicid = newer.isoformat() + else: + comicid = int(latest) + 1 + + if len(self.db) > 0: + lasturl = self.db[0]['url'] + else: + lasturl = "http" while True: irow = self.get_irow(comic, comicid) if irow: print "got irow: " + str(irow) - if irow[3] == lasturl: - print "Looping the same, break break break!" - break - lasturl = irow[3] - print "inserting..." - self.insert_row(irow) + if str(irow[0]) == 'skip': + print "skipping this one..." + next = int(irow[1]) + else: + if irow[3] == lasturl: + print "Looping the same, break break break!" + break + lasturl = irow[3] + print "inserting..." + self.insert_row([irow[0],irow[1],irow[2],irow[3],irow[4],irow[5]]) + if len(irow) > 6: + next = irow[6] + if not next: + break if dateid: dt = string.split(comicid, "-") d = datetime.date(int(dt[0]),int(dt[1]),int(dt[2])) newer = d + datetime.timedelta( 1 ) comicid = newer.isoformat() + elif next: + comicid = next else: comicid += 1 else: break + + + def get_next_id(self, comic, number): + if comic == 'cyanide': + link = "http://www.explosm.net/comics/" + str(number) + "/" + print "link: " + link + try: + f = urllib2.urlopen(link) + hcode = f.code + except: + hcode = 404 + print "got hcode = " + str(hcode) + "\n" + if (hcode != 200): + return False + else: + # print "Cyanide & Happiness is unreliable, so we need to track next and prev" + s = f.read() + f.close() + # title: + splt = string.split(s, 'Previous | Next >', 1) + if len(splt) < 2: + print "no 'next' found" + return False + else: + print "got next: " + splt[0] + return splt[0] + + def get_prev_id(self, comic, number): + if comic == 'cyanide': + link = "http://www.explosm.net/comics/" + str(number) + "/" + print "link: " + link + try: + f = urllib2.urlopen(link) + hcode = f.code + except: + hcode = 404 + print "got hcode = " + str(hcode) + "\n" + if (hcode != 200): + return False + else: + print "Cyanide & Happiness is unreliable, so we need to track next and prev" + s = f.read() + f.close() + # title: + splt = string.split(s, 'First | < Previous', 1) + if len(splt) < 2 or len(splt[0]) > 5: + print "no 'next' found" + return False + else: + print "got previous: " + splt[0] + return splt[0] + + + + + def get_irow(self, comic, number): dateid = False if len(str(number)) == 10: @@ -229,6 +385,8 @@ class ComicDb(): link = "http://dilbert.com/" + str(number) + "/" elif comic == 'phd': link = "http://www.phdcomics.com/comics/archive.php?comicid=" + str(number) + elif comic == 'cyanide': + link = "http://www.explosm.net/comics/" + str(number) + "/" else: return False @@ -295,10 +453,57 @@ class ComicDb(): if len(url) < 49: print "Fake 404! Break break break!" return False - + elif comic == 'cyanide': + s = f.read() + f.close() + # title: + splt = string.split(s, ' First | < ', 1) + prev = splt[0]; + print "got prev: " + prev + splt = string.split(s, 'Previous | Next >', 1) + if len(splt[0]) > 10: + next = False + else: + next = splt[0] + print "got next: " + next + + splt = string.split(s, '', 1) + if len(splt) < 2: + print "no comic?" + return False + splt = string.split(splt[1], ' by ', 1) + url = "http://www.explosm" + splt[0] + splt2 = string.rsplit(url, "/", 1) + filename = splt2[1] + irow = [comic,number,link,url,filename,title,next,prev] + return irow + splt2 = string.rsplit(url, "/", 1) filename = splt2[1] + if filename == self.db[0]['filename']: + print "already exists! Break break break!" + return False irow = [comic,number,link,url,filename,title] return irow @@ -306,18 +511,23 @@ class ComicDb(): # ------------UI class ComicHomePlugin(hildondesktop.HomePluginItem): - __gtype_name__ = 'ComicHomePlugin' + # __gtype_name__ = 'ComicHomePlugin' def __init__(self): hildondesktop.HomePluginItem.__init__(self) global supports_alpha self.set_settings(True) + self.active_comics = self.get_active_comics() + self.sizes = self.get_size_settings() + self.new_width = self.sizes['width'] + self.new_height = self.sizes['height'] self.connect("show-settings", self.show_options) - self.osso_c = osso.Context("comic-widget", "0.2.6", False) + self.osso_c = osso.Context("comic-widget", "0.3.0", False) self.osso_rpc = osso.Rpc(self.osso_c) - self.keys = comics.keys() - self.keypointer = 1 - self.db = ComicDb(self.keys[self.keypointer]) - self.comicname = comics[self.keys[self.keypointer]]['name'] + self.keypointer = 0 + if len(self.active_comics) < 1: + self.active_comics = ['xkcd'] + self.db = ComicDb(self.active_comics[self.keypointer]) + self.comicname = comics[self.active_comics[self.keypointer]]['name'] self.set_name = "comicwidget" screen = self.get_screen() colormap = screen.get_rgba_colormap() @@ -329,7 +539,7 @@ class ComicHomePlugin(hildondesktop.HomePluginItem): self.set_colormap(colormap) self.set_app_paintable(True) #setup internal area - self.set_size_request(480, 230) + self.set_size_request(self.sizes['width'], self.sizes['height']) self.imgvpos = 0; self.vbox = gtk.VBox() self.hbox = gtk.HBox() @@ -434,6 +644,8 @@ class ComicHomePlugin(hildondesktop.HomePluginItem): self.vbox.show_all() self.add(self.vbox) + + # **************** Cairo draw functions *************** def realize(self, widget): @@ -540,12 +752,19 @@ class ComicHomePlugin(hildondesktop.HomePluginItem): self.e_goweb.show_all() elif func == 'switch': - self.keypointer = (self.keypointer + 1) % len(comics) + self.active_comics = self.get_active_comics() + print "closing log" + #sys.stdout.close() + #sys.stdout = sys.__stdout__ + #sys.stderr.close() + #sys.stderr = sys.__stderr__ + print "active comics: " + str(self.active_comics) + self.keypointer = (self.keypointer + 1) % len(self.active_comics) self.imgvpos = 0 self.db = [] - print "switching to " + self.keys[self.keypointer] - self.comicname = comics[self.keys[self.keypointer]]['name'] - self.db = ComicDb(self.keys[self.keypointer]) + print "switching to " + self.active_comics[self.keypointer] + self.comicname = comics[self.active_comics[self.keypointer]]['name'] + self.db = ComicDb(self.active_comics[self.keypointer]) self.e_open.remove(self.comic_image) self.comic_image = self.get_resized_pixmap(self.db.get_comic(), self.imgvpos) self.e_goweb.remove(self.label) @@ -587,32 +806,39 @@ class ComicHomePlugin(hildondesktop.HomePluginItem): def get_resized_pixmap(self, filename, vpos): print "vpos: " + str(vpos) - - maxheight = 182 + + width = int(self.sizes['width']) + height = int(self.sizes['height']) + picwidth = width - 2 + maxheight = height - 48 pixbuf = gtk.gdk.pixbuf_new_from_file(filename) - parent_buf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, pixbuf.get_has_alpha(), 8, 480, maxheight) + parent_buf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, pixbuf.get_has_alpha(), 8, width, maxheight) parent_buf.fill(0xffffffff) retimg = gtk.Image() # get correct width/height new_height = 1 - new_width = 478 - new_height = int((478.0 / pixbuf.get_width()) * pixbuf.get_height()) + new_width = picwidth + new_height = int((float(picwidth) / pixbuf.get_width()) * pixbuf.get_height()) scaled_buf = pixbuf.scale_simple(new_width,new_height,gtk.gdk.INTERP_BILINEAR) print "scaled height: " + str(scaled_buf.get_height()) if scaled_buf.get_height() > maxheight: if scaled_buf.get_height() - (vpos + maxheight) < 0: vpos = scaled_buf.get_height() - maxheight - scaled_buf.copy_area(0,vpos,478,maxheight,parent_buf,1,0) + scaled_buf.copy_area(0,vpos,picwidth,maxheight,parent_buf,1,0) + # parent_buf.composite(scaled_buf, 0, 0, 478, maxheight, 0, 0, 478, maxheight, gtk.gdk.INTERP_BILINEAR, 0) self.imgvpos = vpos else: tmpy = maxheight - scaled_buf.get_height() if tmpy > 0: tmpy = tmpy / 2 - scaled_buf.copy_area(0,0,478,scaled_buf.get_height(),parent_buf,1,tmpy) + scaled_buf.copy_area(0,0,picwidth,scaled_buf.get_height(),parent_buf,1,tmpy) self.imgvpos = 0 +# test = parent_buf.render_pixmap_and_mask(0) +# parent_buf.add_alpha(True,chr(255),chr(255),chr(255)) retimg.set_from_pixbuf(parent_buf) + print retimg.get_pixel_size() print "vpos after fixing image: " + str(self.imgvpos) return retimg @@ -635,9 +861,55 @@ class ComicHomePlugin(hildondesktop.HomePluginItem): return False -# ************************* OPTIONS ******************************** + + def get_active_comics(self): + print "get list" + + if os.path.isfile(activecomics) == True: + print "found " + activecomics + dbf = open(activecomics, 'r') + dbr = csv.reader(dbf) + try: + active = dbr.next() + except: + active = [] + dbf.close() + return active + # if not, copy it. + else: + print "file " + activecomics + " not found" + if not os.path.exists(dbdir): + print "path not found: " + dbdir + try: + os.makedirs(dbdir) + except: + print "settings dir creation failed. Exiting." + exit() + try: +# dbf = file(activecomics, 'w') +# dbf.close() + dbf = open(activecomics, 'w') + except: + print "error storing settings" + exit() + dbw = csv.writer(dbf) + dbw.writerow(comics.keys()) + print comics.keys() + dbf.close() + ret = comics.keys() + return ret + + + + + #check if settings file exists + + #if not, write defaults + +# ************************* OPTION DIALOGS ******************************** def show_options(self, widget): + print "loading options dialog" dialog = gtk.Dialog("Comic Widget", None, gtk.DIALOG_DESTROY_WITH_PARENT) about_button = hildon.Button(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL) @@ -645,27 +917,145 @@ class ComicHomePlugin(hildondesktop.HomePluginItem): about_button.set_alignment(0,0,0,0) about_button.connect("clicked", self.show_about) - dialog.vbox.pack_start(about_button, True, True, 0) + comics_button = hildon.Button(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL) + comics_button.set_text("Comics", "Choose which comics to view") + comics_button.set_alignment(0,0,0,0) + comics_button.connect("clicked", self.show_comics) + # size_button = hildon.Button(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL) + # size_button.set_text("Change size", "Change the size of the widget") + # size_button.set_alignment(0,0,0,0) + # size_button.connect("clicked", self.show_size) + + print "adding buttons to dialog, starting with comics" + dialog.vbox.pack_start(comics_button, True, True, 0) + print "adding about button" + dialog.vbox.pack_start(about_button, True, True, 0) + # dialog.vbox.pack_start(size_button, True, True, 0) + print "show!" dialog.show_all() dialog.run() dialog.destroy() def show_about(self, widget): + print "in about dialog" dialog = gtk.AboutDialog() dialog.set_title("About") dialog.set_name("Comic widget") dialog.set_version(APP_VERSION) dialog.set_copyright("Copyright 2010 Marcus Wikstrom") dialog.set_authors(["Marcus Wikstrom \nLogo by Martin Wikstrom\n\nSpecial thanks to all the great python developers on t.m.o who share their code, and the helpful wizards on #maemo."]) - # dialog.set_logo(gtk.gdk.pixbuf_new_from_file("/usr/share/touchsearch/icon.png")) - # dialog.set_comments("Thanks to Benoit Hervier, Daniel Would and Brent Chiodo for some nice code to sample.") + dialog.set_logo(gtk.gdk.pixbuf_new_from_file("/opt/comic-widget/images/icon2-64x64.png")) + dialog.set_comments("Silly rabbit, tricks are for kids.") dialog.set_license("""This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License. .""") dialog.set_wrap_license(True) dialog.show_all() dialog.run() dialog.destroy() + def show_comics(self, widget): + print "in comics dialog! yay!" + dialog = gtk.Dialog("Configure Search Engines", None, gtk.DIALOG_DESTROY_WITH_PARENT | gtk.DIALOG_NO_SEPARATOR) + comiclist = comics.keys() + comiclist.sort() + buttonlist = {} + self.connlist = {} + for comicid in comiclist: + buttonlist[comicid] = hildon.Button(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL) + print buttonlist[comicid].get_name() + + print buttonlist[comicid].set_alignment(0, 0.5, 0, 0.5) + active = False + for acomic in self.active_comics: + if acomic == comicid: + active = True + break + if active: + buttonlist[comicid].set_text(comics[comicid]['name'] + " *", comicid + ": click to remove") + self.connlist[comicid] = buttonlist[comicid].connect("clicked", self.remove_comic) + else: + buttonlist[comicid].set_text(comics[comicid]['name'], comicid + ": click to add") + self.connlist[comicid] = buttonlist[comicid].connect("clicked", self.add_comic) + dialog.vbox.pack_start(buttonlist[comicid], True, True, 0) + + + dialog.show_all() + dialog.run() + dialog.destroy() + + def add_comic(self, widget): + print "add " + widget.get_title() + splt = string.split(widget.get_value(), ':', 1) + comicid = splt[0] + if os.path.isfile(activecomics) == True: + print "added " + comicid + " to " + str(self.active_comics) + try: + found = self.active_comics.index(comicid) + except: + self.active_comics.append(comicid) + dbf = open(activecomics, 'w') + dbw = csv.writer(dbf) + dbw.writerow(self.active_comics) + dbf.close() + widget.set_text(comics[comicid]['name'] + " *", comicid + ": click to remove") + widget.disconnect(self.connlist[comicid]) + self.connlist[comicid] = widget.connect("clicked", self.remove_comic) + + def remove_comic(self, widget): + print "remove " + widget.get_title() + if len(self.active_comics) == 1: + return + splt = string.split(widget.get_value(), ':', 1) + comicid = splt[0] + if os.path.isfile(activecomics) == True: + print "removing " + comicid + " from " + str(self.active_comics) + try: + del self.active_comics[self.active_comics.index(comicid)] + except: + pass + dbf = open(activecomics, 'w') + dbw = csv.writer(dbf) + dbw.writerow(self.active_comics) + dbf.close() + widget.set_text(comics[comicid]['name'], comicid + ": click to add") + widget.disconnect(self.connlist[comicid]) + self.connlist[comicid] = widget.connect("clicked", self.add_comic) + + def get_size_settings(self): + # defaults = {'width':480,'height':230} + # options: w 798 700 600 500 480 400 + # options: h 420 360 310 270 240 200 + print "checking to see if config file is available" + if os.path.isfile(sizefile) == True: + print "found " + sizefile + dbf = open(sizefile, 'r') + dbr = csv.reader(dbf) + try: + cfg = dbr.next() + except: + dbf.close() + print "empty config file" + return defaults + dbf.close() + + sizes = {'width':int(cfg[0]),'height':int(cfg[1])} + if sizes['width'] > 798: + sizes['width'] = 798 + if sizes['width'] < 400: + sizes['width'] = 400 + if sizes['height'] > 420: + sizes['height'] = 420 + if sizes['height'] < 200: + sizes['height'] = 200 + + return sizes + + + # if not, copy it. + else: + print "no config file" + return defaults + hd_plugin_type = ComicHomePlugin