Programming」カテゴリーアーカイブ

GtkBuilder

GtkBuilder を入れてみた。
見た目は凄い多機能に見える、どんな感じなんだろう。
ちなみに、コレも dnf コマンドからでないと入らない。

gnome_builder_install

あれ、clang 必須なのかな?
というかこの名前なのに Gtk+ ヘッダは依存関係にはないのかよ。
後で判るけど gcc でよかった、その他必要そうなものも導入しておこう。

早速新規プロジェクトを作ってみよう。
起動すると HDD 内の GPL プロジェクトを自動検索していた。
便利なんだか余計なお世話なのか、大半が参考用なのに。

あらかじめ作業用ディレクトリを作っておいく。
起動したら左上の [New] ボタン、フォルダアイコンのほうをクリック。
先程作ったディレクトリを指定し [Continue] する。

new_proj

configure.ac をプロジェクトファイルとして扱うようだ。
つまり autotools も必須ということみたい。
適当にコードを書いてプロジェクトを保存…

できなかった。

色々試したが autogen.sh 必須。
autotools にて自力で configure.ac を作った後に使うもののようだ。

というか、コイツのビルド機能は autogen.sh を実行するだけ。
そりゃコンパイラはどっちでもいいわ。

一応、autogen.sh は autotools のコマンドをまとめておくスクリプト。
最小限のサンプルを置いておくよ、README のとおりにやってね。
honda-0.0.1.tar.gz

そうそう、Build といっても configure スクリプトを作るまでです。
make 以降は自力。

小物を作って遊ぶには無駄すぎる。
デバッガもない、コレを IDE と言ってもいいのだろうか?
単なるテキストエディタだ。

コード補完や閉括弧自動挿入と初心者大喜びなエディタなのに。
私的に期待外れというかショボすぎて唖然とした。

うーん、今後に期待しとく。

g_filename_from_uri and GFile

iPhone と Linux の接続は AFC プロトコルで繋る。
この URI を Gio と GLib の関数でフルパスに変換してみる。

#!/usr/bin/env python3
 
from gi.repository import Gtk, Gdk, GLib, Gio
 
class DWin(Gtk.Window):
    def __init__(self):
        """
            DnD Window
        """
        Gtk.Window.__init__(self)
        self.connect("delete-event", Gtk.main_quit)
        # DnD
        dnd_list = Gtk.TargetEntry.new("image/jpeg", 0, 0)
        self.drag_dest_set(
                Gtk.DestDefaults.MOTION |
                Gtk.DestDefaults.HIGHLIGHT |
                Gtk.DestDefaults.DROP,
                [dnd_list],
                Gdk.DragAction.COPY )
        self.drag_dest_add_uri_targets()
        # GtkLabel
        self.label = Gtk.Label("Please drop your files")
        self.add(self.label)
        #
        self.show_all()
 
    def do_drag_data_received(self, context, x, y, data, info, time):
        """
            URI to FullPath
            Gio or GLib
        """
        uri = data.get_uris()[0]
        try:
            # GFile
            f = Gio.File.new_for_uri(uri)
            path = f.get_path()
            s = "{0}\n".format(path)
            # GLib
            afc = GLib.filename_from_uri(uri)[0]
            s += afc
        except Exception as e:
            # Error
            s += e.message
        self.label.set_text(s)
 
DWin()
Gtk.main()

seruria

一年で 8500yen しか課金していないのにセルリアを持っていてごめんよ!
いやそれは関係なくて、ウチ姫を知らないとワカンナイし。

g_filename_from_uri 関数は AFC の URI を変換できない。
この関数はファイルが存在するかどうかは関係ないからかな。

一手間増えても素直に GFile を使ったほうが良いようです。
実際にアクセスするか変換するだけかの違いがモロにでるのね。

ところで変換されたフルパスがナンジャコリャに見えるけど。

mount

普通にマウントされているんだなぁこれが。
なのに Shotwell ではインポートがエラーになるのは何故だろう?

まあ自分は Nautilus で DnD して保存で充分なんだけどne!

cairo RSVG

GtkPixBuf は SVG 画像をもそのまま扱えて普通に描写できる。
線や図形の描写 – L’Isola di Niente
上記コードで普通に表示できると確認できます。
しかし拡大すると…

airplane

eog は綺麗に引き伸ばしされているのに対し、コッチは超ギザギザ!
MComix で試してもギザギザ、Shotwell は表示すらできない。

eog ってショボイと見せかけて実はこんなに優秀だったのかよ…
ではなく。
どうすれば綺麗に表示できるか考えて調べて色々試してみよう。

ーーーーー

自前ソースがギザギザなのは少し考えれば当然だと解る。
なにせ svg を一度 Bitmap 化して引伸す工程にしているのである。
これではベクターデータである svg での曲線が滑らかという恩恵が無い。
結果 jpeg 画像等と何も変わらないギザギザになる。

つまりベクターデータのまま拡縮して直接描写する必要がある。
メタデータを直接編集すればなんとかなる。
って、だからベクターデータの加工には面倒が付き纏うんだよ。

もしコレが特定ライブラリを使えば Easy Mode になるのだったら…
なんて誰でも考え付くよね。
いきなりそのものズバリを見つけてしまった。

RSVG Libary Reference Manual
librsvg – Wikipedia

GtkDrawingArea は GTK3 から cairo で描写している。
なので cairo から rsvg を使う方法を探す。

Cairo: A Vector Graphics Library: Cairo: A Vector Graphics Library

Fedora 21 で rsvg モジュールはデフォルトでは入っていない。
だけど gir には Rsvg が最初からあった、コレを使おう。

cairo って PostScript や PDF も扱えるのか。
面白そうだけど今回は細かいことは置いておいて。
Python 用 cairo ライブラリから SVG を描写する方法を。

Surfaces ? Pycairo v1.10.0 documentation

サーフェス(面)のサイズを変更するには Matrix を使うのか。
1,4 番目引数で x,y のサイズということみたい。
ということで、サーフェスなので paint でなくレンダリングする。

#!/usr/bin/env python3
 
from gi.repository import Gtk, Gdk, Gio, Rsvg
import cairo, sys
 
class Win(Gtk.ApplicationWindow):
    def __init__(self, app):
        """
            DnD SVG Viewer
        """
        Gtk.Window.__init__(self, application=app)
        # svg
        self.svg = None
        # DrawingArea
        self.da = Gtk.DrawingArea()
        self.da.connect("draw", self.on_draw)
        self.add(self.da)
        # DnD
        dnd_list = Gtk.TargetEntry.new("text/uri-list", 0, 0)
        self.drag_dest_set(
                Gtk.DestDefaults.MOTION |
                Gtk.DestDefaults.HIGHLIGHT |
                Gtk.DestDefaults.DROP,
                [dnd_list],
                Gdk.DragAction.MOVE )
        self.drag_dest_add_uri_targets()
        # self
        self.set_title("DnD SVG Viewer")
        self.resize(200, 200)
        self.show_all()
 
    def do_drag_data_received(self, drag_context, x, y, data, info, time):
        """
            On Drop
        """
        uris = data.get_uris()
        f = Gio.File.new_for_uri(uris[0])
        path = f.get_path()
        # Recreate svg
        self.svg = Rsvg.Handle.new_from_file(path)
        # invalidate
        self.da.queue_draw()
 
    def on_draw(self, widget, cr):
        """
            Draw x5 SVG
        """
        if self.svg:
            # x5 size
            matrix = cairo.Matrix(5, 0, 0, 5, 0, 0)
            cr.transform (matrix)
            # Render
            self.svg.render_cairo(cr)
 
class App(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(self,
                application_id="apps.test.dnd",
                flags=Gio.ApplicationFlags.FLAGS_NONE)
         
    def do_activate(self):
        Win(app)

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

svg_5x

これならギザギザにならずに拡大することができる。
別途でインストールするものは何もないのに、Linux 恐るべし。
いやまあ全部 GNOME プロジェクトのおかげなんですけど。
結論、cairo って実はこんなに面白いんだyo!

file ext

前々回。
「g_content_type_guess だと ContentType は拡張子依存みたい」
と書いた手前、筆者的には当然の結果だけど一応試してみた。

#!/usr/bin/env python3

from gi.repository import Gio

# Doesn't exist a File.

ans = Gio.content_type_guess("Not Found.txt")
print(ans)
#=> ('text/plain', False)

# File Create (No Ext).

with open("found", "w") as f:
    f.write("#!/usr/bin/env python3\n")

# g_content_type_guess

ans = Gio.content_type_guess("found")
print(ans)
#=> ('application/octet-stream', False)

# Gio Query

obj = Gio.file_new_for_path("found")
info = obj.query_info(
    Gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
    Gio.FileQueryInfoFlags.NONE )
ans = info.get_content_type()
print(ans)
#=> text/x-python

やっぱり拡張子の有無で関数の違いが出るんですね。
Gtk, GLib と付き合いが長いので結果は解っていたけどこういうこと。

つまり面倒臭い手段を使えば予定通りな結果が得られる。
GNOME プロジェクトは計画的にやっているんだろうな、と思ってしまう。
何故こうなるかは割愛、これは GNOME 関連では単純なほうだyo!

Virtual Terminal Emulator

VTE といってもホンダのバイクじゃありません。
Virtual Terminal Emulator の略であります。

Gedit 標準プラグインに Python コンソールがありますが全然違う。
gnome-terminal そのものみたいなエミュレーターです。

GNOME wiki の VTE Terminal Widget Library ページ。
Apps/Terminal/VTE – GNOME Wiki!

バージョンがややこいけど 2.91=0.39 のようだ。
例によって GNOME プロジェクト作だから合わせたかったのかな。
vte291-devel-0.39.90-1.fc22.armv7hl.rpm | RPM Info | koji

vte01

Fedora にはしっかり gir で入っていますね。
多分 gnome-terminal 採用のディストリなら大抵あると思う。
2.91 は見当たらないので 0.39 のドキュメントを見ればいいだろう。
VTE Reference Manual: VTE Reference Manual

参考が欲しいのでサンプルコードを探す。

c – gtk+ vte scrollback not working – Stack Overflow
python – How to add vte terminal widget in GTK3? – Ask Ubuntu

C や Python から使う方法は海外でアッサリ見つかった。
日本語情報は今のところ皆無、いつものことだ。

しかし古いようで vte_terminal_fork_command 関数は 2.91 で使えない。
どうやら現行は vte_terminal_spawn_sync 関数を使うようだ。

ということで。
早速 Python バインディングにて書いてみよう。

#!/usr/bin/env python3

from gi.repository import Gtk, Vte, GLib

class VteWindow(Gtk.Window):
    """
        Vte Sample (v2.91)
    """
    def __init__(self):
        Gtk.Window.__init__(self)
        # Create a virtual terminal 
        terminal = Vte.Terminal.new()
        # Exit of Ctrl+D
        terminal.connect("child-exited", self.on_terminal_child_exited)
        # Sync
        terminal.spawn_sync(
                Vte.PtyFlags.DEFAULT,
                GLib.get_home_dir(),
                #["/bin/sh"], @ List of Execute Command
                ["/usr/bin/python3"],
                None,
                GLib.SpawnFlags.DO_NOT_REAP_CHILD,
                None,
                None,
                None)
        self.add(terminal)
        self.set_title("Virtual Terminal")
        self.connect("delete-event", Gtk.main_quit)
        self.show_all()

    def on_terminal_child_exited(self, vteterminal, status):
        Gtk.main_quit()

VteWindow()
Gtk.main()

vte02

spawn_sync の引数については devhelp で詳しく。
三番目引数を sh や perl に変更すれば当然それらが起動する。
それと上記は起動したコマンドの終了を検知して自分も終了させている。
後はお好みで弄ってみてください。
今後バージョンで変わると思うので 2.91 と念を押して。

/bin/sh で起動してソコから Python を始めるとかも可能。
Ctrl+D で Python を終了すると sh に戻る、マジで普通の端末。

しかし自分で試して驚いた、こんなにアッサリ実装できるとは。
自分好みに拡張したオリジナル端末を作るだけでも面白そう。
ただ一言、日本語の情報がまったく無いのはキビシイze!