X-Git-Url: http://dolda2000.com/gitweb/?a=blobdiff_plain;f=manga%2Freader.py;h=ca8f43337d5d374de45308a324a02763fc9af7df;hb=04f773e3923930aa517e196962e4304eecabd1ce;hp=ed58ff7b998f95916e2f7f55e7decd206bb519ae;hpb=95213fa6b373916e7aefef1284aaa5619a8419b7;p=automanga.git diff --git a/manga/reader.py b/manga/reader.py index ed58ff7..ca8f433 100644 --- a/manga/reader.py +++ b/manga/reader.py @@ -1,5 +1,5 @@ -import threading, gtk, gio, gobject -import lib +import threading, gtk, gobject +import lib, profile class notdone(Exception): pass @@ -23,17 +23,18 @@ class future(threading.Thread): try: val = self.value() except Exception as e: - with gtk.gdk.lock: - self._exc = e - for cb in self._notlist: - cb() - self._notlist = [] + self._exc = e + gobject.idle_add(self._callcbs, True) else: - with gtk.gdk.lock: - self._val = [val] - for cb in self._notlist: - cb() - self._notlist = [] + self._val = [val] + gobject.idle_add(self._callcbs, True) + + def _callcbs(self, final): + nls = [] + for cb in self._notlist: + if cb(): + nls.append(cb) + self._notlist = [] if final else nls # Caller must hold GDK lock def notify(self, cb): @@ -44,12 +45,7 @@ class future(threading.Thread): cb() def progcb(self): - with gtk.gdk.lock: - nls = [] - for cb in self._notlist: - if cb(): - nls.append(cb) - self._notlist = nls + gobject.idle_add(self._callcbs, False) @property def val(self): @@ -79,7 +75,7 @@ class imgload(future): self.start() def value(self): - buf = bytearray() + buf = gtk.gdk.PixbufLoader() with self.page.open() as st: self.p = 0 self.st = st @@ -88,10 +84,11 @@ class imgload(future): if read == "": break self.p += len(read) - buf.extend(read) + buf.write(read) self.progcb() self.st = None - return gtk.gdk.pixbuf_new_from_stream(gio.memory_input_stream_new_from_data(str(buf))) + buf.close() + return buf.get_pixbuf() @property def prog(self): @@ -112,9 +109,17 @@ class pagecache(object): f = imgload(page) self.bk.append((idl, f)) if len(self.bk) > self.sz: - self.bk = self.bk[-sz:] + self.bk = self.bk[-self.sz:] return f + def __delitem__(self, page): + idl = page.idlist() + for i, (ol, f) in enumerate(self.bk): + if ol == idl: + del self.bk[i] + return + raise KeyError(idl) + class relpageget(future): def __init__(self, cur, prev, cache=None): super(relpageget, self).__init__() @@ -136,6 +141,15 @@ class relpageget(future): self.cache[page] return page +class idpageget(future): + def __init__(self, base, idlist): + super(idpageget, self).__init__() + self.bnode = base + self.idlist = idlist + + def value(self): + return lib.cursor(self.bnode.byidlist(self.idlist)).cur + class pageget(future): def __init__(self, fnode): super(pageget, self).__init__() @@ -185,7 +199,8 @@ class pageview(gtk.Widget): self.window.set_user_data(None) def do_size_request(self, req): - req.width, req.height = self.get_osize() + w, h = self.get_osize() + req.width, req.height = max(min(w, 4096), 0), max(min(h, 4096), 0) def fitzoom(self): w, h = self.get_osize() @@ -263,23 +278,41 @@ class pageview(gtk.Widget): self.set_off((ox, oy)) gobject.type_register(pageview) -class pagefetch(object): - def __init__(self, fpage, setcb=None): - self.pg = fpage - self.setcb = setcb - +class msgproc(object): def attach(self, reader): self.rd = reader self.msg = gtk.Alignment(0, 0.5, 0, 0) self.hlay = gtk.HBox() - self.lbl = gtk.Label("Fetching page...") + self.lbl = gtk.Label("") self.hlay.pack_start(self.lbl) self.lbl.show() self.msg.add(self.hlay) self.hlay.show() self.rd.sbar.pack_start(self.msg) self.msg.show() + self._prog = None + + def prog(self, p): + if p is not None and self._prog is None: + self._prog = gtk.ProgressBar() + self._prog.set_fraction(p) + self.hlay.pack_start(self._prog, padding=5) + self._prog.show() + elif p is None and self._prog is not None: + self.hlay.remove(self._prog) + self._prog = None + + def abort(self): + self.rd.sbar.remove(self.msg) + +class pagefetch(msgproc): + def __init__(self, fpage, setcb=None): + self.pg = fpage + self.setcb = setcb + def attach(self, reader): + super(pagefetch, self).attach(reader) + self.lbl.set_text("Fetching page...") self.pg.notify(self.haspage) def haspage(self): @@ -292,31 +325,15 @@ class pagefetch(object): self.setcb(self.pg.val) self.rd.pagefetch.set(None) - def abort(self): - self.rd.sbar.remove(self.msg) - -class imgfetch(object): +class imgfetch(msgproc): def __init__(self, fimage): self.img = fimage self.upd = False self.error = None def attach(self, reader): - self.rd = reader - self.msg = gtk.Alignment(0, 0.5, 0, 0) - self.hlay = gtk.HBox() - self.lbl = gtk.Label("Fetching image...") - self.hlay.pack_start(self.lbl) - self.lbl.show() - self.prog = gtk.ProgressBar() - self.prog.set_fraction(0.0) - self.hlay.pack_start(self.prog, padding=5) - self.prog.show() - self.msg.add(self.hlay) - self.hlay.show() - self.rd.sbar.pack_start(self.msg) - self.msg.show() - + super(imgfetch, self).attach(reader) + self.lbl.set_text("Fetching image...") self.img.notify(self.imgprog) def imgprog(self): @@ -331,8 +348,7 @@ class imgfetch(object): self.upd = True self.rd.imgfetch.set(None) else: - p = self.img.prog - if p: self.prog.set_fraction(p) + self.prog(self.img.prog) return True def abort(self): @@ -342,22 +358,13 @@ class imgfetch(object): if self.error is not None: self.rd.pagelbl.set_text("Error fetching image: " + self.error) -class preload(object): +class preload(msgproc): def __init__(self, fpage): self.pg = fpage def attach(self, reader): - self.rd = reader - self.msg = gtk.Alignment(0, 0.5, 0, 0) - self.hlay = gtk.HBox() - self.lbl = gtk.Label("Fetching next page...") - self.hlay.pack_start(self.lbl) - self.lbl.show() - self.msg.add(self.hlay) - self.hlay.show() - self.rd.sbar.pack_start(self.msg) - self.msg.show() - + super(preload, self).attach(reader) + self.lbl.set_text("Fetching next page...") self.pg.notify(self.haspage) def haspage(self): @@ -365,10 +372,6 @@ class preload(object): if not self.pg.done: return True if self.pg.val is not None: self.img = self.rd.cache[self.pg.val] - self.prog = gtk.ProgressBar() - self.prog.set_fraction(0.0) - self.hlay.pack_start(self.prog, padding=5) - self.prog.show() self.lbl.set_text("Loading next page...") self.img.notify(self.imgprog) else: @@ -379,8 +382,7 @@ class preload(object): if self.img.done: self.rd.preload.set(None) else: - p = self.img.prog - if p: self.prog.set_fraction(p) + self.prog(self.img.prog) return True def abort(self): @@ -404,8 +406,77 @@ class procslot(object): self.cur = None raise +class plistget(future): + def __init__(self, node): + super(plistget, self).__init__() + self.node = node + + def value(self): + return list(self.node) + +class loadplist(object): + def __init__(self, pnode): + self.pnode = pnode + self.flist = plistget(self.pnode) + + def attach(self, sbox): + self.sbox = sbox + self.flist.notify(self.haslist) + + def haslist(self): + if self.sbox.loadlist.cur != self: return False + if not self.flist.done: return True + self.sbox.setlist(self.flist.val) + +class sbox(gtk.ComboBox): + def __init__(self, reader, ptnode): + super(sbox, self).__init__() + self.rd = reader + self.node = ptnode + self.pnode, self.pidx = self.node.stack[-1] + + self.bk = gtk.ListStore(str) + self.set_model(self.bk) + cell = gtk.CellRendererText() + self.pack_start(cell, True) + self.add_attribute(cell, "text", 0) + self.set_active(0) + + self.set_sensitive(False) + self.set_focus_on_click(False) + self.bk.append([ptnode.name]) + self.loadlist = procslot(self) + self.loadlist.set(loadplist(self.pnode)) + + def setlist(self, ls): + self.bk.clear() + for i, ch in enumerate(ls): + self.bk.append(["%i/%i: %s" % (i + 1, len(ls), ch.name)]) + self.set_active(self.pidx) + self.set_sensitive(True) + self.connect("changed", self.changed_cb) + + def changed_cb(self, wdg, data=None): + self.rd.fetchpage(pageget(self.pnode[self.get_active()])) + +class profprop(object): + def __init__(self, key, default=None): + self.key = key + self.default = default + + def __get__(self, ins, cls): + return ins.profile.props.get(self.key, self.default) + + def __set__(self, ins, val): + ins.profile.props[self.key] = val + ins.profile.save() + + def __delete__(self, ins): + del ins.profile.props[self.key] + ins.profile.save() + class reader(gtk.Window): - def __init__(self, manga): + def __init__(self, manga, prof=None): super(reader, self).__init__(gtk.WINDOW_TOPLEVEL) self.connect("delete_event", lambda wdg, ev, data=None: False) self.connect("destroy", lambda wdg, data=None: self.quit()) @@ -414,12 +485,27 @@ class reader(gtk.Window): self.pagefetch = procslot(self) self.imgfetch = procslot(self) self.preload = procslot(self) + self.profile = prof if prof else profile.memmanga(None, None, manga.id) + + self.manga = manga + self.page = None + self.sboxes = [] + self.point = None vlay = gtk.VBox() self.pfr = gtk.Frame(None) self.pfr.set_shadow_type(gtk.SHADOW_NONE) vlay.pack_start(self.pfr) self.pfr.show() + self.sboxbar = gtk.HBox() + algn = gtk.Alignment(0, 0.5, 0, 0) + sboxlbl = gtk.Label(self.manga.name + u": ") + algn.add(sboxlbl) + sboxlbl.show() + self.sboxbar.pack_start(algn, False) + algn.show() + vlay.pack_start(self.sboxbar, False) + self.sboxbar.show() self.sbar = gtk.HBox() self.pagelbl = gtk.Label("") algn = gtk.Alignment(0, 0.5, 0, 0) @@ -432,11 +518,14 @@ class reader(gtk.Window): self.add(vlay) vlay.show() - self.manga = manga - self.page = None - self.fetchpage(pageget(self.manga)) + if self.curpage is not None: + self.fetchpage(idpageget(self.manga, self.curpage)) + else: + self.fetchpage(pageget(self.manga)) self.updtitle() - self.point = None + + zmode = profprop("zmode", "fit") + curpage = profprop("curpage") def updpagelbl(self): if self.page is None: @@ -445,12 +534,31 @@ class reader(gtk.Window): w, h = self.page.get_osize() self.pagelbl.set_text(u"%s\u00d7%s (%d%%)" % (w, h, int(self.page.zoom * 100))) + def updsboxes(self, page): + nodes = [node for node, idx in page.stack[1:]] + [page] + l = min(len(self.sboxes), len(nodes)) + for i, (pbox, node) in enumerate(zip(self.sboxes, nodes)): + if pbox.node != node: + l = i + break + for i in xrange(l, len(self.sboxes)): + self.sboxbar.remove(self.sboxes[i]) + self.sboxes = self.sboxes[:l] + for i in xrange(l, len(nodes)): + new = sbox(self, nodes[i]) + self.sboxbar.pack_start(new, False, padding=5) + self.sboxes.append(new) + new.show() + def setimg(self, img): if self.page is not None: self.pfr.remove(self.page) self.page = None if img is not None: self.page = pageview(img) + if self.zmode == "1": + self.page.set_zoom(1) + self.page.set_off((0, 0)) self.pfr.add(self.page) self.page.show() self.updpagelbl() @@ -459,10 +567,12 @@ class reader(gtk.Window): if self.point is not None: self.point = None if page is not None: + self.curpage = page.idlist() self.point = ccursor(page, self.cache) self.imgfetch.set(imgfetch(self.cache[page])) else: self.setimg(None) + self.updsboxes(page) def fetchpage(self, fpage, setcb=None): self.imgfetch.set(None) @@ -496,8 +606,10 @@ class reader(gtk.Window): if self.page is not None: if ev.keyval in [ord('O'), ord('o')]: self.zoom = 1.0 + self.zmode = "1" elif ev.keyval in [ord('P'), ord('p')]: self.zoom = None + self.zmode = "fit" elif ev.keyval in [ord('[')]: self.zoom = min(self.zoom * 1.25, 3) elif ev.keyval in [ord(']')]: @@ -523,6 +635,10 @@ class reader(gtk.Window): self.fetchpage(self.point.next, lambda page: self.preload.set(preload(relpageget(page, False, self.cache)))) elif ev.keyval in [65288]: self.fetchpage(self.point.prev, lambda page: self.preload.set(preload(relpageget(page, True, self.cache)))) + elif ev.keyval in [ord('R'), ord('r')]: + page = self.point.cur.cur + del self.cache[page] + self.imgfetch.set(imgfetch(self.cache[page])) def quit(self): self.hide()