added begin and end icons
[xkcdha] / xkcdha.py
1 #!/usr/bin/python -tt
2
3 import os
4 import sys
5 import re
6 import urllib
7
8 import gtk
9 import hildondesktop
10
11 MAX_HEIGHT = 370. 
12 MAX_WIDTH = 700.
13
14 class XKCDha(hildondesktop.HomeItem):
15         
16     image_dir = "/home/user/MyDocs/.images/xkcdha/"
17     icons_dir = "/usr/share/xkcdha/icons/"
18     connection_required_img = "/usr/share/xkcdha/img/connection_required.png"
19
20     def __init__(self, max_height, max_width):
21         def controls():
22             hbox = gtk.HBox()
23             hbox.pack_start(gtk.Alignment())
24             for name in ("prev", "random", "next"):
25                 box = gtk.EventBox()
26                 image  = gtk.Image()
27                 image.set_from_file(self.icons_dir + "%s.png" % name)
28                 box.add(image)
29                 box.set_events(gtk.gdk.BUTTON_PRESS_MASK)
30                 box.connect("button-press-event", getattr(self, "cb_%s" % name))
31                 hbox.pack_start(box, False, False)
32                 hbox.pack_start(gtk.Alignment(), False, False, 5)
33             hbox.pack_start(gtk.Alignment())
34             return hbox
35
36         hildondesktop.HomeItem.__init__(self)
37         self.max_height, self.max_width = max_height, max_width
38         self.number = None
39         self.prev = None
40         self.next = None
41         self.image = gtk.Image()
42                 
43         self.set_image()
44
45         image_box = gtk.EventBox()
46         image_box.add(self.image)
47         image_box.set_events(gtk.gdk.BUTTON_PRESS_MASK)
48         image_box.connect("button-press-event", self.cb_random)
49                 
50         vbox = gtk.VBox()
51         vbox.pack_start(controls())
52         vbox.pack_start(image_box)
53         vbox.pack_start(controls())
54         vbox.show_all()
55
56         self.add(vbox)
57
58     def set_image(self, number=""):
59         def get_image(number=""):
60             
61             if self.number and number != "random":
62                 if not number:
63                     number = self.number
64                 elif number == "next" and self.next:
65                     number = self.next
66                 if number == "prev" and self.prev:
67                     number = self.prev
68
69             print 'number=', number, self.number
70
71             url = "http://xkcd.com/"
72             if number == 'random':
73                 url = "http://dynamic.xkcd.com/comic/random/"
74             elif number:
75                 url = "http://xkcd.com/%s/" % number
76             
77             print 'url:', url
78             
79             try:
80                 content = urllib.urlopen(url).read()
81             except IOError:
82                 if self.number:
83                     filename = os.path.join(self.image_dir, self.number + '.png')
84                     if os.path.exists(filename):
85                         return filename
86                 return self.connection_required_img
87
88             img_url = re.search('(http://imgs.xkcd.com/comics/[^"]+)" title="[^"]+"', 
89                     content).group(1)
90             next = re.search('<a href="([^"]+)" accesskey="n">Next', content).group(1)
91             prev = re.search('<a href="([^"]+)" accesskey="p">&lt; Prev', content).group(1)
92             self.number = re.search(\
93                     '<h3>Permanent link to this comic: http://xkcd.com/([^/]+)/</h3>', 
94                     content).group(1)
95             self.next = self.number
96             if next != '#':
97                 self.next = next[1:-1]
98
99             self.prev = self.number
100             if prev != '#':
101                 self.prev = prev[1:-1]
102
103             filename = os.path.join(self.image_dir, self.number + '.png')
104             if not os.path.exists(filename):
105                 print 'getting url', img_url, 'to', filename
106                 urllib.urlretrieve(img_url, filename)
107             else:
108                 print 'already exists', filename
109             
110             print 'filename:', filename, 'img_url:', img_url
111             print 'next:', next, self.next
112             print 'prev:', prev, self.prev
113             print 'number:', self.number
114             return filename
115
116         pixbuf = gtk.gdk.pixbuf_new_from_file(get_image(number))
117         scale_y = self.max_height / pixbuf.props.height
118         scale_x = self.max_width / pixbuf.props.width
119         if scale_x > scale_y:
120             newx = int(pixbuf.props.width * scale_y)
121             newy = int(self.max_height)
122         else:
123             newx = int(self.max_width)
124             newy = int(pixbuf.props.height * scale_x)
125         
126         self.image.set_from_pixbuf(pixbuf.scale_simple(newx, newy, gtk.gdk.INTERP_BILINEAR))
127         self.image.show()
128
129     def cb_random(self, widget, data = None):      
130         self.set_image('random')
131
132     def cb_next(self, widget, data = None):
133         self.set_image('next')
134
135     def cb_prev(self, widget, data = None):
136          self.set_image('prev')
137
138 def hd_plugin_get_objects():
139     return [XKCDha(MAX_HEIGHT, MAX_WIDTH)]
140
141 def run_in_window():
142     main_window = gtk.Window(gtk.WINDOW_TOPLEVEL)
143     main_window.set_title("XKCD Home Applet")
144     main_window.connect("destroy", gtk.main_quit)
145     main_window.add(XKCDha(MAX_HEIGHT, MAX_WIDTH))                            
146     main_window.show_all()
147     gtk.main()
148
149 if __name__ == "__main__":
150     run_in_window()
151     sys.exit()
152