GTK4: GridView

GTK4 は TreeView の他に IconView も廃止なんだね。
GlidView が後継のようで、Nautilus 43 のもコレっぽい。

Gtk.GridView

GtkDemo にサンプルが無い、自力で試してみよう。

#!/usr/bin/env python3

import gi, sys
gi.require_version('Adw', '1')
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk, Gio, GObject, Adw

class Items(GObject.Object):
    def __init__(self, items):
        self.items = items
        super(Items, self).__init__()

class TestWindow(Gtk.ApplicationWindow):
    def __init__(self, app):
        # Set Adwaita Style
        manager = Adw.StyleManager.get_default()
        manager.set_color_scheme(Adw.ColorScheme.DEFAULT)
        # init
        Gtk.ApplicationWindow.__init__(self, application=app, title='GridView')
        #
        model = Gio.ListStore()
        model.append(Items(['OM SYSTEM', 'pen']))
        model.append(Items(['LUMIX', 'GH6']))
        #
        #sel_model = Gtk.SingleSelection(model=model)
        sel_model = Gtk.MultiSelection(model=model)
        #
        factory1 = Gtk.SignalListItemFactory()
        factory1.connect('setup', self.on_listitem_setup)
        factory1.connect('bind', self.on_listitem_bind1)
        #
        listnview = Gtk.GridView(model=sel_model, factory=factory1)
        listnview.connect('activate', self.on_columnview_activate)
        #
        self.set_child(listnview)
        self.set_default_size(200, 200)

    def on_listitem_setup(self, factory, item):
        label = Gtk.Label(label='oman')
        item.set_child(label)

    def on_listitem_bind1(self, factory, item):
        l = item.get_item()
        label = item.get_child()
        label.props.label = l.items[0]

    def on_columnview_activate(self, list, pos):
        print(1)

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

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

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

grid

ちょっと驚いた、という不正確な日本語での表現にしておくけどナルホドなぁ。
完全に GTK4 の ListView と同様の手順、いや当然狙ってそうしたのだろう。
Box を使ってレイアウトすれば Nautilus 43 の見た目にはできるね。

ついでに。
init 直後に書いた Adw 用途の命令って GTK4 全部に影響するのね。
上記のまま全体の DarkMode にしてみたら。

grid

あぁ macOS や iOS の DarkMode は開発者に丸投げだったもんな。
GNOME はこうしたんですね、いや勘違いかもしれないけれど。

Python: open r+

Fedora 37 で今頃気がついたけど。
Anthy の辞書がまた PageDown でページ送りができなくなっているじゃん。

/usr/share/ibus-anthy/engine/engine.py は八月に更新されているな。
バッチは当ててくれなかったのか、気がつかなかったようで。
do_page_down なんてメソッドは定義されていないよメンテナさん。
しかたがない、今回も自前バッチを。

#!/usr/bin/env python3

'''
    Fedora 37 の Anthy で PageUp(Down) にて辞書送りできないのを修正
    コピペして sudo で実行しログインのやりなおし
    万が一失敗したら gnome-softwere から入れ直しで元通り
'''

import os

os.chdir('/usr/share/ibus-anthy/engine')

with open('engine.py') as f:
    src = f.read()
    dst = src.replace('do_page_up()', '__page_up(0)', 1).replace('do_page_down()', '__page_down(0)', 1)
    with open('engine.py', 'w') as g:
        g.write(dst)

今回は replace で。

いや Python の open には r+ という読み書きモードがあるんだけど?
と思うかもだけど r+ は使わないほうがいいよ。

#!/usr/bin/env python3

import os

with open('rw.txt', 'w') as f:
    f.write('ABCDEFG')

with open('rw.txt', 'r+') as f:
    src = f.read()
    #
    # 巻き戻すのを忘れずに
    f.seek(0)
    #
    # r+ での書き込みは以前の内容が残る
    dst = src.replace('ABCDE', 'a', 1)
    f.write(dst)
    #
    # 確認
    f.seek(0)
    print(f.read())
    #
    #=> 'aFGDEFG'

ね。
書き出しが短いと最初の語尾が残ってしまうんです。
文字数を合わせる、又はそれ以上なら問題ないんですけど。
ただ文字数を合わせても日本語だと以下のように。

#!/usr/bin/env python3

import os

with open('rw2.txt', 'w') as f:
    f.write('あいうえお')

with open('rw2.txt', 'r+') as f:
    src = f.read()
    f.seek(0)
    #
    # write は UTF-8 で書き出す
    dst = src.replace('あいう', 'aiu', 1)
    f.write(dst)
    #
    # 確認
    f.seek(0)
    print(f.read())
    #
    #=> 'aiuえおえお'

日本語はほぼ 3byte なので。
対策はあるんだろうけど、一番の対策は使わないことですよね。

ところで Nautilus 43 のリネームで入力メソッド切り替えが初回が無視される。
いやこれ US 配列キーボード愛用者以外には関係ないといえばそうなんですけど。
Ctrl+J のほうを使えばいいんだけど macOS と同じコッチを使ってしまうし。

Fedora とは関係ないけど GTK4 になった GHex もなんかおかしいな。

ghex font

Source Code Pro 以外のフォントだとはみ出すんだが。
なにがどうしてこうなるのか全然わからん。

GTK4: ListView and ColumnView

前回は少し勘違いをしてました。
GtkListView を GtkListBox だと思い込んでいた、反省。

ListView は GTK4 で追加された新規のリストビューでした。
ただし 1 カラム限定、それいったい何に使うんだろう?は置いておいて。
複数カラムにするには ColumnView を使う、ということらしい。

Gtk.ListView

Gtk.ColumnView

ListView のほうにはサンプルコードがある。
でも create_application_list って関数何よ、これじゃよくワカンネェよ。
model は GListModel 派生なので Gio.ListStore にすればいいようです。

ただ ListStore には GObject.Object 派生しか append できないみたいなんですが。
GObject.TYPE_STRING 等を指定しても例外、丁度いい class も見つからない。
PyGObject の制限なのかどうかは知らないけど文字列のリストを入れたいんですけど。
ということでちょっぴり手抜きな Item class を作ってサンプルコードを書いてみた。

#!/usr/bin/env python3

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

class Items(GObject.Object):
    def __init__(self, items):
        self.items = items
        super(Items, self).__init__()

class TestWindow(Gtk.ApplicationWindow):
    def __init__(self, app):
        Gtk.ApplicationWindow.__init__(self, application=app, title='ListView')
        #
        model = Gio.ListStore()
        model.append(Items(['OM SYSTEM', 'pen']))
        model.append(Items(['LUMIX', 'GH6']))
        #
        sel_model = Gtk.SingleSelection(model=model)
        #
        factory1 = Gtk.SignalListItemFactory()
        factory1.connect('setup', self.on_listitem_setup)
        factory1.connect('bind', self.on_listitem_bind1)
        #
        listnview = Gtk.ListView(model=sel_model, factory=factory1)
        listnview.connect('activate', self.on_columnview_activate)
        #
        self.set_child(listnview)

    def on_listitem_setup(self, factory, item):
        label = Gtk.Label(label='sexxx')
        item.set_child(label)

    def on_listitem_bind1(self, factory, item):
        l = item.get_item()
        label = item.get_child()
        label.props.label = l.items[0]

    def on_columnview_activate(self, list, pos):
        print(1)

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

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

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

表示はレンダラではなく Widget を使うようになりました。

リストビューらしい複数カラム表示にするなら ColumnView を使う。
ほとんど同じ手段です、ListView は単なるベースクラスなのかな。
カラムの数だけ ColumnViewColumn を追加して使います。

#!/usr/bin/env python3

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

class Items(GObject.Object):
    def __init__(self, items):
        self.items = items
        super(Items, self).__init__()

class TestWindow(Gtk.ApplicationWindow):
    def __init__(self, app):
        Gtk.ApplicationWindow.__init__(self, application=app, title='ColumnView')
        #
        model = Gio.ListStore()
        model.append(Items(['OM SYSTEM', 'pen']))
        model.append(Items(['LUMIX', 'GH6']))
        #
        sel_model = Gtk.SingleSelection(model=model)
        #
        factory1 = Gtk.SignalListItemFactory()
        factory1.connect('setup', self.on_listitem_setup)
        factory1.connect('bind', self.on_listitem_bind1)
        #
        factory2 = Gtk.SignalListItemFactory()
        factory2.connect('setup', self.on_listitem_setup)
        factory2.connect('bind', self.on_listitem_bind2)
        #
        columnview = Gtk.ColumnView(model=sel_model)
        columnview.connect('activate', self.on_columnview_activate)
        #
        column1 = Gtk.ColumnViewColumn(title='Camera', factory=factory1)
        columnview.append_column(column1)
        column2 = Gtk.ColumnViewColumn(title='Model', factory=factory2)
        columnview.append_column(column2)
        #
        self.set_child(columnview)

    def on_listitem_setup(self, factory, item):
        label = Gtk.Label(label='sexxx')
        item.set_child(label)

    def on_listitem_bind1(self, factory, item):
        l = item.get_item()
        label = item.get_child()
        label.props.label = l.items[0]

    def on_listitem_bind2(self, factory, item):
        l = item.get_item()
        label = item.get_child()
        label.props.label = l.items[1]

    def on_columnview_activate(self, list, pos):
        print(1)

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

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

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

で。

column

解り辛いですよね、でも表示が Widget なので GTK3 以前よりはマシ。
チェックボックスや画像を入れたくなっても Widget の知識でやれますんで。
以前はレンダラという専用のものを使う必要がありました。

Gtk(PyGObject) Tips | レンダラ – Paepoi

しかし Nautilus 43 みたくモダンな選択表示にするにはどうすればいいんだろう?
メッセージが Adw.ToastOverlay になったので Adw だと思ったけど無いんだよな。
それは今後の課題ということで、最後に。

jyoubitaki

本日はジョウビタキが綺麗に撮れました。

GTK4: GtkInscription

そういえば GTK4 に GtkInscription が追加されるんだっけ。
Gtk.Inscription

特殊用途に使う Widget なので通常は GtkLabel を使ってくれ。
ということらしいけど、つまり文字列がはみ出すラベルってことね。

#!/usr/bin/env python3

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

class TestWindow(Gtk.ApplicationWindow):
    def __init__(self, app):
        try:
            Gtk.ApplicationWindow.__init__(self, application=app)
            # Label and Inscription
            label = Gtk.Label(label='文字列に合わせて拡大されます')
            inscription = Gtk.Inscription(text='文字列に合わせて拡大されません、はみ出します')
            # pack
            vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
            vbox.append(label)
            vbox.append(inscription)
            self.set_child(vbox)
        except Exception as e:
            print(e, file=sys.stderr)
            app.quit()

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

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

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

inscription

なんだそれだけだったのか。
カラム部分とかコンテナが拡大されたら困る場所に使うってことですね。

ところで、GTK4 のドキュメントが親切になっている。
deprecated つまり廃止予定を明確にしてくれています。

Gtk ? 4.0

TreeView がやっと廃止、マウス必須な時代遅れ UI ですからね。
TreeStore だけでなく ListStore も廃止、リストビュー表示もできなくなる。
一応、GtkListView は昔ながらのリストビューではなくスマホの設定画面みたいな UI です。
あれ、Nautilus 43 のリストビュー表示は?
と思うかもだけどアレは ColumnView なんですね、いや今知ったんだけど。

伴ってあの解り辛いレンダラ関連が全面廃止。
あぁ、それで Inscription という Widget が必要になったということか。

ダイアログ関連を全面見直し。
いやそれ何故 GTK4 の最初でやらなかったのか。

ComboBox も廃止。いや困るだろと思ったけど Popover があったわ。
Nautilus 43 の設定もそうなっていた、はよ移行しろってことですね。

StyleContext も廃止。
CSS の適用は今後どうするんだろう?調べなきゃ。

GTK4 の方向性が見えてきましたね。
次は GtkColumnView あたりを調べてみるかな。

kgx

Fedora 37 への更新通知が来た。
今回は Nautilus の GTK4 化と新規な端末エミュレーター以外はあまり興味が無い。
ということでクリーンインストールによる検証はヤメてアップグレード、いつも面倒だし。
問題なく数分でアップグレード完了。

あれ、gnome-terminal のままなんですけど?
探しても新規ターミナルエミュレーターアプリが見つからないんですけど。
デフォルトでは入らない、クリーンインストールなら入るのか?
いや、Nautilus はしっかり GTK4 化されているし。

What’s new in Fedora Workstation 37 – Fedora Magazine

書いていないね、Fedora 37 では gnome-terminal 継続だったのか。
gnome-softwere を開いて「コンソール」というアプリを見つけた。
コレが GNOME 43 本来の新規端末エミュレーターのようです、

console

kgx が実名、gnome-console とかそれっぽい名前じゃないんかい。
とにかくインストールして色々やってみる。

bash:tip_colors_and_formatting – FLOZz’ MISC

256color

問題なく 256 色表示できますね。
ショートカットは gnome-terminal から変わっていない。
bash 自体を Ctrl+D で終了させると終了するのも変わっていない。

タイトルバーにサブタイトルにて現在位置を表示、Gedit 等と同じ。
GTK4 のはずなのに DarkMode 全体設定には反応しない。
個別 DarkMode 以外の設定が何もない、いらないけど。
コンテキストメニューから現在位置にて Nautilus を起動が可能に。
Nautilus から「端末で開く」は導入しても gnome-terminal が開きます。

あ、Nautilus って「ファイル」の実名ね、何故最近は実名を隠すようになったのか?
kgx も実名を見つけるのに苦労した。

GNOME / Console ? GitLab

src を覗くまでマジでワカンネエってばよ。
何も問題なく見えるけど採用を見送った理由があるんだろうな。

しかしアップグレードのせいか何も変わっていないように見えるな。