1 import threading, gtk, gio, gobject
4 class notdone(Exception): pass
6 class future(threading.Thread):
10 super(future, self).__init__()
18 except Exception as e:
25 if self._exc is not None:
33 return self._exc != None or self._val != None
35 class imgload(future):
36 def __init__(self, page):
39 super(imgload, self).__init__()
43 with self.page.open() as st:
53 return gtk.gdk.pixbuf_new_from_stream(gio.memory_input_stream_new_from_data(str(buf)))
57 if self.st is None or self.st.clen is None:
59 return float(self.p) / float(self.st.clen)
61 class pageview(gtk.Widget):
62 def __init__(self, pixbuf):
63 super(pageview, self).__init__()
65 self.zoomed = None, None
68 self.interp = gtk.gdk.INTERP_HYPER
72 return self.pixbuf.get_width(), self.pixbuf.get_height()
75 return self.allocation.width, self.allocation.height
78 self.set_flags(self.flags() | gtk.REALIZED)
79 alloc = self.allocation
80 self.window = gtk.gdk.Window(self.get_parent_window(),
81 width=alloc.width, height=alloc.height,
82 window_type = gtk.gdk.WINDOW_CHILD,
83 wclass = gtk.gdk.INPUT_OUTPUT,
84 event_mask = self.get_events() | gtk.gdk.EXPOSURE_MASK
86 self.window.set_user_data(self)
87 self.style.attach(self.window)
88 self.style.set_background(self.window, gtk.STATE_NORMAL)
89 self.window.move_resize(*alloc)
91 def do_unrealize(self):
92 self.window.set_user_data(None)
94 def do_size_request(self, req):
95 req.width, req.height = self.get_osize()
98 w, h = self.get_osize()
99 alloc = self.allocation
100 return min(float(alloc.width) / float(w), float(alloc.height) / float(h))
102 def do_size_allocate(self, alloc):
103 self.allocation = alloc
105 self.zoom = self.fitzoom()
106 if self.flags() & gtk.REALIZED:
107 self.window.move_resize(*alloc)
109 def get_zoomed(self):
111 pz, zbuf = self.zoomed
113 w, h = self.get_osize()
114 zbuf = self.pixbuf.scale_simple(int(w * zoom), int(h * zoom), self.interp)
115 self.zoomed = zoom, zbuf
119 zbuf = self.get_zoomed()
120 return zbuf.get_width(), zbuf.get_height()
122 def do_expose_event(self, event):
123 aw, ah = self.get_asize()
125 zbuf = self.get_zoomed()
126 zw, zh = self.get_zsize()
135 gc = self.style.fg_gc[gtk.STATE_NORMAL]
136 self.window.draw_pixbuf(gc, zbuf, ox, oy, dx, dy, dw, dh)
138 def set_off(self, off):
139 aw, ah = self.get_asize()
140 zw, zh = self.get_zsize()
142 ox, oy = int(ox), int(oy)
143 if ox > zw - aw: ox = zw - aw
144 if oy > zh - ah: oy = zh - ah
150 def set_zoom(self, zoom):
151 if zoom is not None: zoom = float(zoom)
152 aw, ah = self.get_asize()
153 zw, zh = self.get_zsize()
154 dw, dh = zw - aw, zh - ah
156 xa = float(ox) / float(dw) if dw > 0 else 0.5
157 ya = float(oy) / float(dh) if dh > 0 else 0.5
161 self.zoom = self.fitzoom()
166 zw, zh = self.get_zsize()
167 dw, dh = zw - aw, zh - ah
168 ox = int(xa * dw) if dw > 0 else 0
169 oy = int(ya * dh) if dh > 0 else 0
170 self.set_off((ox, oy))
171 gobject.type_register(pageview)
173 class mangaview(gtk.VBox):
174 def __init__(self, manga):
175 super(mangaview, self).__init__()
178 self.cursor = lib.cursor(manga)
179 self.setpage(self.cursor.cur)
183 return self.page.zoom
185 def zoom(self, zoom):
186 self.page.set_zoom(zoom)
189 ox, oy = self.page.off
191 self.page.set_off((ox + px, oy + py))
193 def setpage(self, page):
194 if self.page is not None:
195 self.remove(self.page)
198 with self.cursor.cur.open() as inp:
199 pb = gtk.gdk.pixbuf_new_from_stream(gio.memory_input_stream_new_from_data(inp.read()))
200 self.page = pageview(pb)
201 self.pack_start(self.page)
204 class reader(gtk.Window):
206 super(reader, self).__init__(gtk.WINDOW_TOPLEVEL)
207 self.connect("delete_event", lambda wdg, ev, data=None: False)
208 self.connect("destroy", lambda wdg, data=None: self.quit())
209 self.connect("key_press_event", self.key)
213 self.set_title("Automanga")
215 def setmanga(self, manga):
216 if self.mview is not None:
217 self.remove(self.mview)
219 if manga is not None:
220 self.mview = mangaview(manga)
225 def key(self, wdg, ev, data=None):
226 if ev.keyval in [ord('Q'), ord('q'), 65307]:
230 if ev.keyval in [ord('O'), ord('o')]:
232 elif ev.keyval in [ord('P'), ord('p')]:
234 elif ev.keyval in [ord('[')]:
235 mv.zoom = min(mv.zoom * 1.25, 3)
236 elif ev.keyval in [ord(']')]:
238 elif ev.keyval in [ord('H'), ord('h')]:
240 elif ev.keyval in [ord('J'), ord('j')]:
242 elif ev.keyval in [ord('K'), ord('k')]:
244 elif ev.keyval in [ord('L'), ord('l')]:
246 elif ev.keyval in [ord(' ')]:
247 mv.setpage(mv.cursor.next())
248 elif ev.keyval in [65288]:
249 mv.setpage(mv.cursor.prev())