PyGObject CSS

PyGObject 覚書ページの更新状況。
CSS 関連が色々と変更されていてワケワカメになっている。
y901x 1.1 の時に解っていて放置していたけどそろそろキチンと調べることに。

#!/usr/bin/env python3
 
import sys, gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
 
OLD_CSS = '''
GtkLabel {
    color: blue;
}'''
NEW_CSS = '''
#MyLabel {
    color: red;
}'''
 
class Win(Gtk.ApplicationWindow):
    '''
        Font Set
    '''
    def __init__(self, app):
        Gtk.ApplicationWindow.__init__(self, application=app, title='Py')
        # set the Widget Name
        label = Gtk.Label(label='ABCDEFG', name='MyLabel')
        self.add(label)
        # GtkCssProvider
        provider = Gtk.CssProvider()
        #provider.load_from_data(OLD_CSS.encode('utf-8'))
        provider.load_from_data(NEW_CSS.encode('utf-8'))
        label.get_style_context().add_provider(provider, Gtk.STYLE_PROVIDER_PRIORITY_USER)
        #
        self.show_all()

class App(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(self)

    def do_startup(self):
        Gtk.Application.do_startup(self)
        Win(self)

    def do_activate(self):
        self.props.active_window.present()

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

と。

GtkWidget に名前を付けて # の接頭子でなんとか適用された。
GtkEntry や .entry という以前の指定は無視される、全部名前を付けてねと。
他にも手段があるのだろうけどコレが一番確実みたい。

GTK+ CSS Properties: GTK+ 3 Reference Manual

が指定できる CSS だけど、解り辛いったらありゃしない。
手探りで色々書きまくって覚えるしかない、Linux の世界はそういうものだ。

ところで GtkTextView のフォントを変更するにも CSS しか手段が無いようだ。
探しても探しても古い手段しか出てこない、適用できない。
こんな時は、Gedit のソースコードを見るのが一番、GPL 万歳。
gedit-view.c と gedit-pango.c を解析、ってほど難しいコードではないけど。

Fonts: Pango Reference Manual

PangoFontDescription を得て個別に CSS 文字列に変換していた。
Gedit のソースをよく見ると Italic かどうかを調べていない、あれ?
試したら Gedit は Italic 表示できないジャン、使わないとはいえ初めて知った!

PangoFontDescription には Italic かを調べる手段があるようだ。
それならということで。

#!/usr/bin/env python3

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

TPL = '''
#MyTextView {{
    font: {0}pt "{1}";
    font-weight: {2};
    font-style: {3};
}}'''

class Win(Gtk.ApplicationWindow):
    '''
        Font Set
    '''
    def __init__(self, app):
        Gtk.ApplicationWindow.__init__(self, application=app, title='Py')
        # GtkTextView
        self.view = Gtk.TextView(name='MyTextView')
        # deprecated
        #font_desc = Pango.font_description_from_string('Monospace 10')
        #view.override_font(font_desc)
        #
        # read the this script file
        with open(__file__) as f:
            s = f.read()
            self.view.get_buffer().set_text(s)
        # GtkFontButton
        button = Gtk.FontButton()
        button.connect('font-set', self.on_font_set)
        # GtkScrolledWindow
        sw = Gtk.ScrolledWindow(child=self.view)
        vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        vbox.pack_start(button, False, False, 0)
        vbox.pack_start(sw, True, True, 0)
        self.add(vbox)
        self.resize(300, 300)
        self.show_all()

    def on_font_set(self, button):
        '''
        font = button.get_font()
        n = font.rfind(' ')
        name = font[:n]
        size = font[n+1:]
        css = '#MyTextView {{ font: {0}pt "{1}"; }}'.format(size, name)
        '''
        desc = button.get_font_desc()
        size = desc.get_size() // Pango.SCALE
        name = desc.get_family()
        weight = desc.get_weight() // 1 # enum to int
        if weight == Pango.Weight.NORMAL:
            w = 'normal'
        elif weight == Pango.Weight.BOLD:
            w = 'bold'
        else:
            w = weight
        style = desc.get_style()
        if style == Pango.Style.OBLIQUE:
            s = 'oblique'
        elif style == Pango.Style.ITALIC:
            s = 'italic'
        else:
            s = 'normal'
        self.props.title = f'{size}|{name}|{w}|{s}'
        css = TPL.format(size, name, w, s)
        # GtkCssProvider
        provider = Gtk.CssProvider()
        provider.load_from_data(css.encode('utf-8'))
        self.view.get_style_context().add_provider(provider, Gtk.STYLE_PROVIDER_PRIORITY_USER)
        #'''

class App(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(self)

    def do_startup(self):
        Gtk.Application.do_startup(self)
        Win(self)

    def do_activate(self):
        self.props.active_window.present()

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

よし bold も italic も適用されるようになったぞと。
コメントアウト部分だけでイケるかなと思ったけど駄目だった。
しかし GUI アプリなのに CSS でフォント指定って、時代の流れなんでしょうか。
とにかくコレで覚書ページの更新が進む、はず。