PyGObject CBZ Viewer

MComix のデザインや操作性が古すぎて GNOME3 に合わない。
Python2 は諦めるけど PyGtk はもう入れたくない。

キーバインドが eog と同じように使える cbz コミックビューアが欲しい。
特に [→] キーで改ページがやりたい、筆者が eog で一番使うキーである。

Evince でも見開き表示にはできるが左ページから始まるようにしか設定できない。
次ページが [→] キーなのはこのアプリも同じ。

etc…

だったら自分で作ればいいじゃないか!

今から作るなら当然 ClutterImage を使って OpenGL 表示だよね。
昔ながらのノウハウが使えないという意味でもあるけど。

#!/usr/bin/env python3

import sys, zipfile, gi
gi.require_version('Gtk', '3.0')
gi.require_version('Clutter', '1.0')
gi.require_version('GtkClutter', '1.0')
from gi.repository import Gtk, Gio, GLib, Gdk, GdkPixbuf, Clutter, GtkClutter, Cogl

PATH = "gf(kari).cbz";

class ComipoliWindow(Gtk.ApplicationWindow):
    def __init__(self, app):
        Gtk.ApplicationWindow.__init__(self, application=app)
        # var
        self.num = 0
        self.datas = []
        self.is_fullscreen = False
        # Clutter
        embed = GtkClutter.Embed()
        self.add(embed)
        self.stage = embed.get_stage()
        #
        self.actor1 = Clutter.Actor()
        self.stage.add_child(self.actor1)
        self.image1 = Clutter.Image()
        self.actor1.set_content(self.image1)
        # signal
        self.stage.connect("allocation-changed", self.on_stage_allocation_changed)
        # unzip
        with zipfile.ZipFile(PATH) as f:
            l = f.namelist()
            l.sort()
            for name in l:
                try:
                    data = f.read(name)
                    stream = Gio.MemoryInputStream.new_from_data(data)
                    p = GdkPixbuf.Pixbuf.new_from_stream(stream)
                    self.datas.append(p)
                except Exception as e:
                    pass
        # set
        self.set_pixbuf(0)
        #
        self.show_all()

    def set_pixbuf(self, num):
        pixbuf = self.datas[num]
        self.image1.set_data(
            pixbuf.get_pixels(),
            Cogl.PixelFormat.RGB_888,
            pixbuf.get_width(),
            pixbuf.get_height(),
            pixbuf.get_rowstride()
        )
        self.num = num

    def change_pixbuf(self, bool_next):
        """
            TODO: Spread display
        """
        if bool_next:
            if len(self.datas) > self.num + 1:
                self.set_pixbuf(self.num + 1)
        else:
            if self.num > 0:
                self.set_pixbuf(self.num - 1)

    def on_stage_allocation_changed(self, actor, box, flags):
        """
            TODO: Aspect ratio
        """
        self.actor1.set_size(box.x2 , box.y2)

    def do_key_press_event(self, event):
        """
            eog like Key Bind
        """
        if event.keyval == Gdk.KEY_Down:
            self.change_pixbuf(True)
        elif event.keyval == Gdk.KEY_Right:
            self.change_pixbuf(True)
        elif event.keyval == Gdk.KEY_space:
            self.change_pixbuf(True)

        elif event.keyval == Gdk.KEY_Up:
            self.change_pixbuf(False)
        elif event.keyval == Gdk.KEY_Left:
            self.change_pixbuf(False)
        elif event.keyval == Gdk.KEY_BackSpace:
            self.change_pixbuf(False)

        elif event.keyval == Gdk.KEY_F11:
            if self.is_fullscreen:
                self.unfullscreen()
                self.is_fullscreen = False
            else:
                self.fullscreen()
                self.is_fullscreen = True
        elif event.keyval == Gdk.KEY_Escape:
            if self.is_fullscreen:
                self.unfullscreen()
                self.is_fullscreen = False
            else:
                self.close()

class ComipoliApp(Gtk.Application):
    def __init__(self):
        GLib.set_prgname("Comipoli");
        Gtk.Application.__init__(
            self,
            application_id="apps.sasakima.comipoli",
            flags=Gio.ApplicationFlags.FLAGS_NONE )

    def do_activate(self):
        ComipoliWindow(self)

#Clutter.init(); @ Error
GtkClutter.init();
app = ComipoliApp()
app.run(sys.argv)

comipoli000

とりあえず読み込みと表示関連はなんとかなった。
後はアスペクト比の保持と見開き表示等々。

実は、キーバインドが eog と同じだと少々問題が。

GANMA! むさむらだけ読んでいる
となりのヤングジャンプ えびなちゃんだけ(同
ガンガンONLINE ぐるぐる(同

と筆者が利用しているマンガサイトはことごとく改ページが [←] キーなのだ。
縦書き文化の国で生まれたマンガなのだからそのほうが自然といえる。

横書きの英語文化で作られたアプリとキーバインドを共通にするべきかどうか。
もう完全に好みの問題、左右キーのみ設定で入れ替えできるようにするのが一番かなと。
タッチパネルでもどちらにフリックかで問題になりそう。