Fedora 34 gir

PyGObject が Fedora 34 では例外になってもプロセスが続くようになった。
GTK4 だからかと思ったら GTK3 でやっても同じだった。

#!/usr/bin/env python3

import gi, sys
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk

class TestWindow(Gtk.ApplicationWindow):
    def __init__(self, app):
        Gtk.ApplicationWindow.__init__(self, application=app)
        try:
            btn = Gtk.Button(label='SUZUKI')
            btn.connect('clicked', self.on_button_clicked)
            self.label = Gtk.Label(label='Motor Cycle')
            box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
            self.add(box)
            box.pack_start(btn, False, False, 0)
            box.pack_start(self.label, False, False, 0)
            # err
            box.pack_start(null_widget, False, False, 0)
        except Exception as e:
            print(f'@@@Error@@@@: ${e}', file=sys.stderr)

    def on_button_clicked(self, widget):
        # err
        self.label.null_func()

class TestApplication(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(self, application_id='org.suzuki.sv')

    def do_activate(self):
        w = TestWindow(self)
        w.show_all()

app = TestApplication()
app.run()

ところで前回は例外を受け取っても pass するコードだった。
これだと何も出力されなくなってしまうね。
stderr に出力するようにしたらアプリを実行中でも表示される。
Gedit の外部ツールなら色が着くというおまけ付き。

この仕様変更は gir 側なのか PyGObject 独自なのか。
ということで Gjs で同じことをやってみる。

GNOME Javascript

いつのまにかこんなサイトができていたのね。
ガイドを見るとまだ GTK3 での解説だけどね。

Legacy Class Syntax | GNOME Javascript

ES6 以降でクラスにする方法が筆者がよく使っている方法に。
コレだ!って解説が無かったから動いたのを書いていただけですが。
こういうサイトがこう書いてくれると以後安心して書けますね。

ただ、PyGObject と比べるとちょっと面倒臭いよね。
ただでさえ let と new とセミコロンとブレースが面倒なのに。
それはいいとして、とっとと上記を GTK4 で Gjs に書き換え。

#!/usr/bin/gjs

imports.gi.versions.Gtk = '4.0';
const {GObject, Gtk} = imports.gi;

var TestWindow = GObject.registerClass({
    GTypeName: 'TestWindow'
}, class TestWindow extends Gtk.ApplicationWindow {
    _init(app) {
        super._init({
            application: app
        });
        try {
            let btn = new Gtk.Button({label: 'SUZUKI'});
            btn.connect('clicked', ()=> {
                // err
                this.label.null_func();
            });
            this.label = new Gtk.Label({label: 'Motor Cycle'});
            let box = new Gtk.Box({orientation: Gtk.Orientation.VERTICAL});
            this.set_child(box);
            box.append(btn);
            box.append(this.label);
            // err
            box.append(null_widget);
        } catch(e) {
            printerr(`@@@Error@@@@: ${e.message}`);
        }
    }
});

var TestApplication = GObject.registerClass({
    GTypeName: 'TestApplication'
}, class TestApplication extends Gtk.Application {
    _init() {
        super._init({
            application_id: 'org.suzuki.bandit'
        });
    }
    vfunc_activate() {
        let w = new TestWindow(this);
        w.present();
    }
});

let app = new TestApplication();
app.run(null);

gjs_gedit4

うん完全に同じだ、gir 側の仕様変更だったようです。
プロセスの終了を待たずに printf debug ができるのは嬉しいね。

Fedora 34 etc…

Fedora 34 をしばらく使ってみて。

ibus-anthy には困った。
変換候補のページ切り替えで PageDown が動作しない。
設定を見るとキチンと指定されているのだが。

Fedora 側の不具合なのかと試しに ibus-kkc を入れてみる。
kana kanji って奴、Fedora 33 までのデフォルトインプットメソッド。

設定で切り替えようとしたら出てこない、なんでや!
dconf-editor で org.gnome.desktop.input-sources に自力追加。

[('xkb', 'us'), ('ibus', 'anthy'), ('ibus', 'kkc')]

それでも切り替えできない、まじでなんでや!
もしかしてと再起動、普通に切り替えできるようになった。
てか入れた後で再起動すれば多分 GUI で設定できたんだろうな。

まあいい切り替え、普通に PageDown が使えるや。
つまり anthy だめだこりゃ、削除して kkc にします。
相変わらず初期状態はバカだなぁ、そのうち学習するからいいけど。

それと先日 Gedit プラグイン更新分の配布のためアーカイブした。
そのとき気が付く、file-roller が無くなっていたのね。
今は Nautilus にアーカイブ機能があるからだろうね、ショボいけど。
筆者は必須だから入れる、おいらは tar.gz と cbz を作りたいんや。

それと make は今回は最初から入っていた。
gcc があって make が無いとか変だったもんね。

それと Gedit から PyGObject のアプリを起動の件。
__init__ で例外になった時に勝手に死んでくれなくなっている。
でもシグナルの例外等は即時 stdout に表示されるようになった。
つまりどこでどう例外になってもプロセスは続くということね。
どうにか present させれば後はなんとかなるかも。

#!/usr/bin/env python3

import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk

class TestWindow(Gtk.ApplicationWindow):
    def __init__(self, app):
        Gtk.ApplicationWindow.__init__(self, application=app)
        try:
            btn = Gtk.Button(label='SUZUKI')
            btn.connect('clicked', self.on_button_clicked)
            self.label = Gtk.Label(label='Motor Cycle')
            box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
            self.set_child(box)
            box.append(btn)
            box.append(self.label)
            # err
            box.append(null_widget)
        except Exception as e:
            pass

    def on_button_clicked(self, widget):
        self.label.null_func()

class TestApplication(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(self, application_id='org.suzuki.sv')

    def do_activate(self):
        w = TestWindow(self)
        w.present()

app = TestApplication()
app.run()

うん、これなら例外になってもどうにでもできるぞ。
もっといい方法があるかもしれないのでとりあえずということで。

GtkVideo and GtkPicture

GTK4 には GtkVideo というものが追加された。
早速試してみよう、使えるなら Y901x をコレにしよう。

#!/usr/bin/env python3

import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk, Gio

FILENAME = '[ヤマガラ] セミうめぇ.mp4'

class TestWindow(Gtk.ApplicationWindow):
    def __init__(self, app):
        Gtk.ApplicationWindow.__init__(self, application=app, title=FILENAME)
        #
        f = Gio.file_new_for_path(FILENAME)
        video = Gtk.Video(file=f)
        self.set_child(video)
        self.set_default_size(960, 540)
        self.present()

class TestApplication(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(self, application_id='org.suzuki.address')

    def do_activate(self):
        TestWindow(self)

app = TestApplication()
app.run()

semiumee

なんとまあ、ボタン類やシークバーまで付属なのね。
しかもマウスオーバーで上に被さるオーバーレイタイプだぞ。
これを非表示にするプロパティは無いのか、なんじゃそりゃ。

それとなんというか、WPF の MediaElement みたいなものだね。
デコーダーを入れ Totem で再生できるメディアが再生可能。
動画の元サイズやアスペクト比情報をコイツから得ることはできない。
スマホの縦動画を回転してくれるみたいなことなんてしない。

ダメだこりゃ、使い物にならない。

せっかくなので GtkPicture も試してみる。

#!/usr/bin/env python3

import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk, Gio

FILENAME = 'cbr01.jpg'

class TestWindow(Gtk.ApplicationWindow):
    def __init__(self, app):
        Gtk.ApplicationWindow.__init__(self, application=app, title=FILENAME)
        #
        f = Gio.file_new_for_path(FILENAME)
        pic = Gtk.Picture(file=f)
        self.set_child(pic)
        self.set_default_size(500, 300)
        self.present()

class TestApplication(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(self, application_id='org.suzuki.burgman')

    def do_activate(self):
        TestWindow(self)

app = TestApplication()
app.run()

cbr

やはりスマホの縦写真を回転してくれない。
Nautilus のサムネイル等どんな環境でも縦に表示されるけどさ。
アレはアプリが Exif 情報を見て回転表示しているんだからね。

しかもコレら、回転表示させるプロパティすら無いのかよ。
スマホ全盛期にこんなウイジェットを出されてもなぁ、って感じ。

Kawarahiwa?

macOS Big Sur を 11.3 に更新。
おぉ、今回は Command Line Tools が削除されないぞ。
httpd.conf を初期化するのもいいかげんやめて。

実は Command Line Tools は 12.5 に先日更新した。
削除されると思ったから最初からインストーラで落としたのに。
まあまだワカラン、次の更新も大丈夫とはいえないし。

ところで、昨日五条川で撮影したカワラヒワなんだけど。

1

デカいし嘴が黒いし腹に斑点があるような。。。。。
オオカワラヒワかなと思ったけどなんか違うみたい。

2

今日別の場所で撮影した典型的なカワラヒワ。
羽色は完全にカワラヒワなんだけど。
もしかして新種を見つけたのか、単なるデブなのか。

3

ヒバリ、美空ひばりのおかげで名前は有名だけどお初です。
ヒバリのオスってトサカみたいな頭の羽があるんだね。

4

モズと黄金葉、こういうのもいいじゃないか。
Google レンズでレンギョウって出たけど合ってるかな?
なんか綺麗な葉っぱのほうが気になって。
このアプリ便利だね、ヒバリもコレで解ったし。

GTK4 Python 001

そろそろ GTK4 を使ってみることにする。
筆者はもちろん Gir で PyGObject です。

The GTK Project – A free and open-source cross-platform widget toolkit

GTK 公式サイトに基本サンプルコードがある。
c js py vala は解るけど pl や rs なんて誰が使うんだろう?

GTK 4 Reference Manual: GTK 4 Reference Manual

ドキュメントは現状 Web で見る必要があり。
gtk4-devel-docs を dnf で探したけど見つからない。

Widget Gallery: GTK 4 Reference Manual

廃止されたのはツールバーくらいか。
ツリービューは無くなると思ったけど残したようで。
GtkVideo とか GtkPicture とか、まあいいんじゃない。

Stop using GtkWidget::draw

変更点でコレが一番気になる、まさか draw シグナルを無くすとは。
gtk_main が無くなったのは嬉しい、今でもコレ書くジジイは皆殺しだ。

説明を見ているだけじゃよくワカラン。
とっとと筆者がよく使うサンプルコードで確認。

#!/usr/bin/env python3

import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk

class TestWindow(Gtk.ApplicationWindow):
    def __init__(self, app):
        Gtk.ApplicationWindow.__init__(self, application=app)
        ''' widget '''
        btn = Gtk.Button(label='SUZUKI')
        btn.connect('clicked', self.on_button_clicked)
        self.label = Gtk.Label(label='Motor Cycle')
        ''' pack '''
        box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        #box.pack_start(btn, False, False, 0) # v3
        box.append(btn)
        box.append(self.label)
        #
        #self.add(box) # v3
        self.set_child(box)
        #self.show_all() # v3
        self.present()

    def on_button_clicked(self, widget):
        self.label.set_text('かっこいい!' * 5)

class TestApplication(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(self, application_id='org.suzuki.katana')

    def do_activate(self):
        TestWindow(self)

app = TestApplication()
app.run()

gtk4_1

GtkBox はパッキング情報をコンテナ側に指定ではなくなった。
引き伸ばすか等の情報は挿入する Widget 側のプロパティで指定する。

hexpand|vexpand はデフォルトで FALSE。
これは hexpand-set|vexpand-set を TRUE にしないと変更できない。
halign|valign はデフォルトで GTK_ARIGN_FILL。
margin-* はデフォルトで全部ゼロ、以上で調節する。

gtk_widget_add は GtkWidget の関数だったけど無くなった。
gtk_window_get_child と GtkWindow の関数になった。
普通に UI を作っている人は名前が変わっただけに見えるね。

present は show_all の代わりではない。
GtkWidget のプロパティ visible のデフォルトが TRUE になった。
ただし present しないとウインドウは表示されない。
でこうなったみたい、今までの非表示がデフォルトって変だったもん。

clicked 等のシグナルは変わっていない。
draw が気になるので早々に試してみる。

#!/usr/bin/env python3

import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk, Gio, GLib

class TestWindow(Gtk.ApplicationWindow):
    def __init__(self, app):
        Gtk.ApplicationWindow.__init__(self, application=app)
        da = Gtk.DrawingArea()
        da.set_draw_func(self.da_draw_func)
        self.set_child(da)
        #self.resize(400, 150) # v3
        self.set_default_size(400, 150)
        self.present()

    def da_draw_func(self, da, cr, width, height):
        cr.set_source_rgb(0.5, 0.5, 0.5)
        cr.set_line_width(5.0)
        cr.move_to(0, 0)
        cr.line_to(width, height)
        cr.stroke()

class TestApplication(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(self, application_id='org.suzuki.hayabusa')

    def do_activate(self):
        TestWindow(self)

app = TestApplication()
app.run()

gtk4_2

なんだシグナルではなく関数登録になっただけで同様に使えるヤン。
全 Widget で draw シグナルが使えるのを変えたかったのかな。
GtkSnapshot がどうとか書いているけど今はよく解っていない。

ついでに、set_size_request は適さないのでコッチ使えだそうです。
いや gtk_window_resize って関数があったやろと少し思うけど。

それより、困ったぞ。
Gedit でスクリプトを debug – Paepoi
コレをやると例外になった時に勝手に死んでくれなくなっている。
端末から ps ax で探して kill するしかなくなる。
でも端末から起動なら Gjs 同様に Ctrl+C が使えるようになった。
けどやはり不便だ、別の手段を考えなければ。