投稿者「sasakima-nao」のアーカイブ

gzip, zip

zip 書庫の中にある画像を表示したい。
もちろん展開ファイルを作らずメモリ内でやりくり。

って Gjs ではどうすればいいんだ?
Java なら ZipInputStream という便利なクラスがあるんだが。

ホイール欲しい ハンドル欲しい ? データ圧縮 zlib と gzip と zip (zlib で zip にアクセスする)

zlib でできるっぽい、サイト名が関係なさすぎでワロタ。
Gio で zlib はアクセスできるはず。

Projects/Vala/GIOCompressionSample – GNOME Wiki!

Vala コードだけど gir なら同様に扱えるはず。
ということでこんなコードを書いてみた。

#!/usr/bin/gjs

const Gtk = imports.gi.Gtk;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const GdkPixbuf = imports.gi.GdkPixbuf;

//const PATH = "akazukin.zip";
const PATH = "akazukin.gz";

const UnzipTestWin = new Lang.Class({
    Name: 'UnzipTestWin',
    Extends: Gtk.ApplicationWindow,

    _init: function(app) {
        this.parent({
            application: app
        });
        // Read gzip file
        let source = Gio.File.new_for_path(PATH);
        let stream = source.read(null);
        let converter = new Gio.ZlibDecompressor({
            //format: Gio.ZlibCompressorFormat.RAW
            format: Gio.ZlibCompressorFormat.GZIP
        });
        let cnv_stream = new Gio.ConverterInputStream ({
            base_stream: stream,
            converter: converter
        });
        // Create Pixbuf
        let pixbuf = GdkPixbuf.Pixbuf.new_from_stream(cnv_stream, null);
        let image = new Gtk.Image({
            pixbuf: pixbuf
        });
        this.add(image);
        this.show_all();
    }
});

const UnzipApp = new Lang.Class({
    Name: 'UnzipApp',
    Extends: Gtk.Application,

    _init: function() {
        GLib.set_prgname("UnzipApp");
        this.parent({
            application_id: 'org.sasakima.unzip',
            flags: Gio.ApplicationFlags.FLAGS_NONE
        });
    },
    vfunc_activate: function() {
        new UnzipTestWin(this);
    }
});
let application = new UnzipApp();
application.run(null);

gzip は上手くいったけど zip はダメだ。
そんなに甘くはなかった、いや筆者が無知なだけかも。
てか gzip は普通 tar とセットだ、tar も展開しないと…

いや違うだろ、zip でなきゃ意味が無いんだ。
何を作ろうとしているかバレバレ臭いのは気にしない。

ええい面倒だ、Python3 の zipfile を使ってしまえ!
スクリプト言語の速度で大丈夫かな?試してみるべ。

#!/usr/bin/env python3

import sys, zipfile, gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gio, GLib, GdkPixbuf

PATH = "なえコレ.zip";

class UnzipTestWin(Gtk.ApplicationWindow):
    def __init__(self, app):
        Gtk.ApplicationWindow.__init__(self, application=app)
        fbox = Gtk.FlowBox(valign=Gtk.Align.START, min_children_per_line=5)
        datas = []
        # unzip
        with zipfile.ZipFile(PATH) as f:
            l = f.namelist()
            for name in l:
                d = f.read(name)
                datas.append(d)
        for data in datas:
            stream = Gio.MemoryInputStream.new_from_data(data)
            p = GdkPixbuf.Pixbuf.new_from_stream(stream)
            minp = p.scale_simple(80, 100, GdkPixbuf.InterpType.BILINEAR)
            image = Gtk.Image(pixbuf=minp)
            fbox.add(image)
        self.add(fbox)
        self.show_all()


class UnzipApp(Gtk.Application):
    def __init__(self):
        GLib.set_prgname("UnzipApp");
        Gtk.Application.__init__(
            self,
            application_id="apps.test.naecore",
            flags=Gio.ApplicationFlags.FLAGS_NONE )

    def do_activate(self):
        UnzipTestWin(self)

app = UnzipApp()
app.run(sys.argv)

naekore

なんだ一瞬だった。
これなら速度も問題ないし簡単だし Python で作ることにしよう。
しかし PyGObject でもプロパティ指定がすっかり Gjs 風になってしまった。

GtkShortcutWindow

GTK+ (GNOME) 3.20 の目玉は当然 GtkShortcutWindow です。

メニューバーの中に表示しなければいけないなんて誰も決めていないぞ。
まさか「メニューバーの中のほうが直感的に使える!」なんて言う無知はいないよね。
今だに Ctrl+C すら知らない人が大多数という事実をヲタは知らない。

って、それはどうでもよくて。
実際に GtkShortcutWindow を作ってみよう。

#!/usr/bin/gjs

const Gtk = imports.gi.Gtk;
const GLib = imports.gi.GLib;
const Gio = imports.gi.Gio;
const Lang = imports.lang;

const TestWindow = new Lang.Class({
    Name: 'TestWindow',
    Extends: Gtk.ApplicationWindow,

    _init: function(app) {
        this.parent({
            application: app
        });
        this.resize(300, 300);
        this.show_all();
    }
});

const ShortcutApp = new Lang.Class({
    Name: 'ShortcutApp',
    Extends: Gtk.Application,

    _init: function() {
        // TaskBar Title
        GLib.set_prgname("ShortcutApp");
        // property
        this.parent({
            application_id: 'org.sasakima.shortcutapp',
            flags: Gio.ApplicationFlags.FLAGS_NONE
        });
    },
    vfunc_startup: function() {
        this.parent();
        //
        // Create ShortcutWindow
        this.scwin = new Gtk.ShortcutsWindow();
        let sec = new Gtk.ShortcutsSection({
            visible: true,
            section_name: "Name"
        });
        let doc = new Gtk.ShortcutsGroup({
            title: "Document"
        });
        doc.add(new Gtk.ShortcutsShortcut({
            accelerator: "<ctl>Q",
            title: "Ctrl : <ctl>,  Shift : <shift>, Alt : <alt>"
        }));
        doc.add(new Gtk.ShortcutsShortcut({
            accelerator: "Escape",
            title: "Single Key"
        }));
        doc.add(new Gtk.ShortcutsShortcut({
            accelerator: "1",
            title: "Num Key"
        }));
        sec.add(doc);
        this.scwin.add(sec);
        //
        // Menu
        let menu = new Gio.Menu();
        menu.append("_Keyboard Shortcuts", "app.shortcut_action");
        menu.append("_Quit", "app.quit_action");
        this.set_app_menu(menu);
        // Accel
        this.set_accels_for_action("app.shortcut_action", ["<Control>F1", "question"]);
        this.set_accels_for_action("app.quit_action", ["<Control>Q"]);
        // Action
        let shortcut_action = new Gio.SimpleAction({
            name: "shortcut_action"
        });
        shortcut_action.connect("activate", Lang.bind(this, function(action) {
            this.scwin.show_all();
        }));
        let quit_action = new Gio.SimpleAction({
            name: "quit_action"
        });
        quit_action.connect("activate", Lang.bind(this, function(action) {
            this.quit();
        }));
        this.add_action(shortcut_action);
        this.add_action(quit_action);
    },
    vfunc_activate: function() {
        let w = new TestWindow(this);
        // Set ShortcutWindow Palent
        w.set_help_overlay(this.scwin);
    }
});
let application = new ShortcutApp();
application.run(ARGV);

gtk_shortcutswindow

アレ?と思ったのが GtkShortcutsGroup に配置が add だったこと。
GtkBox のようなパッキングだと思っていた。

ShortcutsSection に max_height プロパティがある。
この数を超える場合はグループを次ペインに全自動で移すようです。

gtk_application_window_set_help_overlay

は凄く重要、GtkApplicationWindow 指定を必ず行うこと。
実際に GNOME アプリで GtkShortcutWindow を出して移動してみよう。

後はこのブログを見ているような人なら説明不要かと。
スクリプト言語から最新 API を試せるって本当に面白いよね。

GTK+ 3.20 GtkHeaderBar and CSS

GTK+ 3.20 で GtkHeaderBar を使う場合の注意。
GtkWindow のリサイズがクライアント領域に変更されたようです。
というか GtkHeaderBar があってもなくても同じ扱いということ。

let w = 320;
let h = 240;
/* under 3.18 in GtkHeaderBar
let diff_x = window.get_allocated_width() - window.vbox.get_allocated_width();
let diff_y = window.get_allocated_height() - window.vbox.get_allocated_height();
window.resize(w + diff_x, h + diff_y);
*/
window.resize(w, h); // 3.20

3.18 以前にも対応させるには振り分け処理が必要。
我がアプリは GtkShortcutWindow を使う予定なので 3.20 専用にする。

*****

GStreamer に変更があったのか他の要因か解らないけど。
皮肉なことに Y901x 1.1.3 で動画がリサイズできるようになった。
せっかく ClutterGst で丸ごと作り替えはじめたのにな。

ただ CSS の仕様が 3.20 で丸々変更されている。
3.18 以前で Style Properties を使っていた場合は WARNING だらけに。

gtk_style

こいつは 3.18 以前との振り分けは無理っぽいな。
詳しいことは今度調べる。

*****

Gjs で ARGV の仕様は変わっていないみたい。
相変わらず Clutter を使って多重起動すると落ちる。
つまり Gjs は筆者の解る範囲では何も変わっていない。

ClutterGst Aspect Rate | PaePoi

多重起動で不具合が出まくるなら原点に戻って多重起動防止だ!
って Totem も多重起動防止だった、知らなかった…

つか、多重起動って実は問題があるのよね。
設定を変更した時に既に起動しているウインドウへの適用をどうするか。
今の GNOME アプリは GSettings を使って見事に適用させている。
ini ファイルの奴でも手段はあるけど、ほぼ誰もやっていない。

まあそれはいいとして、大ボケに気が付いた。
y901x beta ではインストールする起動スクリプトをこうしていた。

#!/bin/sh
cd /usr/share/y901x
gjs y901main.js $*

これだと端末で cd 移動からの起動がおかしいジャン。
引数がファイル名だけだと[カレントディレクトリ + ファイル名]だよ。

#!/bin/sh
gjs /usr/share/y901x/y901main.js $*

に変更してソースには以下を追記。

imports.searchPath.unshift("/usr/share/y901x");

うん、大ボケはとりあえずなんとかなった。
もう少し調べて明日には 3.20 対応版を出そう。

Fedora 24 app

Fedora 24 は問題なく使えそうなのでアプリをボチボチ。

Google Chrome を入れたら依存関係で Python2 が入った。
使っていたのかよオマエ!

いや、構成部品に PLY とかがあるせいだろうけど。
もはや現代人必須アイテムなんだからもう少し部品点数を少く…

ならば MComix も入れちゃえ、これで PyGtk も入ってしまう。
あーあ元通り、cbz が見られるビューアが少ないからしかたがない。

Python2 恐るべし、気が付かない所でまだ使われている。
Linux で完全な非依存はまだ難しい。

***

H.264 デコーダーはよくワカランので結局 RPM Fusion のを入れた。
んで、こいつがよく解らないんだが。

codec

まさか Blu-ray が再生できるのか?
一応入れてみた、ディスクをドライブに入れると「オーディオディスク」に。
まあ無理だよな、再生できたところで画質は絶対にボロボロだろうし。

***

さて自作のアプリやプラグインはどうだ?
Gedit プラグインは動くけどキーボードアクセラレータが動作しない。
何故だろう、不具合が出るほうが嬉しいんですけど。

エラー内容を見ると action_name が Valid だとか。
アクション名からアンダーバーを消して全置換。
なんだこれだけか、私は何故ガッカリしているんだろう?

eog プラグインのほうは元々アンダーバーが無かったのでそのまんま動く。
つーことで Gedit Plugin だけ更新。

Gedit 及び Eye of Gnome プラグイン – L’Isola di Niente

アプリのほうの検証は休日にでも。

Fedora 24 Install (SSD)

起きたので ISO を焼いてインストール開始。
マシン構成は以下で作った Skylake の自作パソコン。
SKYLAKE on Fedora | PaePoi

今回はいきなり日本語になった、マジどうやって見分けたの?
インストール中に fedoraproject 関連の広告が、今迄あったかな?
ウブなんとかほどはウザくはない、まぁアッチは商売なわけで。

それ以外は今迄と何も変わらずインストール完了。
Fedora 23 Install (SSD) | PaePoi

さて起動、何が変わっているかな。
デフォルトフォントが変わって少し小さくなっている。
有線 LAN のアイコンがありがちなものに変わっている。

とっとと dconf-editor を入れて色々と確認。
デフォルトフォントは Cantarell のまま、あれ?
全部今迄どおりみたいだけど、気のせいなのかな。
つーか dconf-editor 変わり過ぎだろ、ShortcutWindow もあるし。

dconf_editor

フォントについては再起動したら何故か今迄と同じになった。
単なる初回起動の不具合だったみたい。

GtkShortcutWindow 追加での変更はどうだ。
Nautilus でコンテキストメニューを出すとショートカットキーが出る。
Gedit は完全に消したようだ、アプリによってバラバラみたい。

なんかデフォルトで入っている GUI アプリがえらく減ったような?
DevAssistant がとうとう消えた、イラネーし。
メモリは 8G になったし Boxes は使おうかな。

gnome-softwere でシェル拡張機能が入れられるようになった。
又三列になって見やすく、ちょっと嬉しい。
openh264 というデコーダーがあるけどライセンス問題をクリアしたのか。
H264 だけみたいですが、やはり RPM Fusion 追加は必須かも。

h264

んで、Sylpheed も KeePassX も検索で出てこないまんまと。
mono のゴミアプリをフィルターで隠す機能が付いたら嬉しいのに。

そんなことより、衝撃!

なんと Python2 が入っていない!
/usr/bin/dnf も Python3 に書き換えられている。
Fedora はとうとう Python2 への依存から脱却できたということか。

del_python2

逆に gcc は入っていた、GTK+ や Clutter のヘッダは無いけど。
perl, lua, gjs, jjs は今迄どおり使える。

以上、今のところ気が付いたこと。
遅番出勤いってきまーす。