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

GNOME Developer Platform Demos

GNOME Developer Platform Demos

ナイスなページ発見。
GNOME プロジェクトは何時の間かにこんなのを作っていた。

JavaScript はもう Gjs にしなさいみたい。
C, C++, Vala は Anjuta を使うのを前提にしているんだなぁ。

しかし Python だけ妙に詳しくて笑う。

インストールはこんな方法があるのか、autoreconf なんて知らなかった。
しかし print に括弧が無い、Python2 でまだいいよってことですか。
試したら本当にインストールできたけど…
先頭に #!/usr/bin/env python が無いので動かないwwwww
わざと?

Tutorial for beginners (Python)

アプリケーションメニュー(GMenu)はこうやればよかったのか。
GtkSwitch の notify::active なんて devhelp に載っていないんですけど…
とにかく参考になるわ、筆者はビギナー達の一人だったのか。

Python3 urllib

今日 Python3 で URI デコードをやろうとした。

Python 3 Porting Guide ? Porting to Python 3 v1 documentation
Python2 との違い一覧を作ってくれている人がいる、アリガトメルシー。
urllib.unquote は urllib.parse.unquote なのね。

#!/usr/bin/env python3

import urllib
print(dir(urllib))

''' output
['__builtins__', '__cached__', '__doc__', '__file__', '__initializing__', '__loader__', '__name__', '__package__', '__path__']
'''

import urllib.parse
print(dir(urllib))

''' output
['__builtins__', '__cached__', '__doc__', '__file__', '__initializing__', '__loader__', '__name__', '__package__', '__path__', 'parse']
'''

なんだこりゃ…

quote

当然そうなるよな、何故だ?
/usr/lib64/python3.3/urllib
を覗いてみると

urllib_zerobyte

__init__.py が 0 byte だとこういう動作になるってことなのか。
なるほど、多分どこかでこの知識が役に立つだろう。

#!/usr/bin/env python3

import urllib.parse
from gi.repository import GLib

uri = "file:///path/to/My%20Waifu.jpg"

path = urllib.parse.unquote(uri)
print(path) #=> file:///path/to/My Waifu.jpg

path, host = GLib.filename_from_uri(uri)
print(path) #=> /path/to/My Waifu.jpg

ただ unquote だと file:/// とかは普通に残るんだよな。
ホスト名があった場合(LAN 上ファイル等)も面倒だし。
Linux なら GLib を使ったほうがいいや。
こんな楽な手段を知っているので Python モジュールの知識が全然無いというのも考え物だな。

Gedit(GtkSourceView) Alt+Up/Down

Gedit で何気無く Alt+Up を叩いたら行が上下で入れ替わった。
複数行を選択して同様に叩いても動作するようだ。

GtkSourceView 3 Reference Manual: GtkSourceView

GtkSourceView の標準機能だった、GtkTextView ではできません。
本当にウイジェットだけで動作するかチト試してみる。

#!/usr/bin/env python3

from gi.repository import Gtk, GtkSource

TEXT = """

TextBlock

Press `Alt + Up`
Move the Selection Text
"""

class AltUpTest(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self)
        # Create GtkSourceView
        view = GtkSource.View()
        view.set_show_line_numbers(True)
        # buffer
        buf = view.get_buffer()
        buf.set_text(TEXT)
        # Select
        it = buf.get_iter_at_offset(13)
        itend = buf.get_end_iter()
        buf.select_range(it, itend)
        # self
        self.add(view)
        self.connect("delete-event", Gtk.main_quit)
        self.set_title("Test")
        self.show_all()

AltUpTest()
Gtk.main()

alt_up

マジだった。
つまり GtkSourceView 採用のアプリなら全部可能だということ。
DnD 編集が標準だったり GTK+ 便利すぎだろ。

Windows 用 Gedit 2.30 でも同様。
ただし Alt+Left/Right での英単語移動は GTK3 からなので使えない。

Gedit を五年以上使い続けているのに今頃気が付いた私って…

Vala etc…

昔書いた Vala コードをもう少しマシなサンプルコードに。
引数で指定したテキストファイルをシングルインスタンスで読み込むように。
多重起動防止処理に startup シグナルを利用してみたけど

startup_error

チェーンアップに失敗って何よ、Google 翻訳役に立たネェ。
一応多重起動防止処理は問題なく行なわれるけど気持ち悪い。
とにかく何かがマズいのだろうと色々検索して以下を見つける。

ApplicationWindow

protected override void startup () {
    base.startup ();
    //etc...
}

startup ハンドラで base.startup を呼ぶ必要があるようです。
何故だかよく解らないけどそういうもんだと納得しておこう。
とにかくそんなこんなでこんなコードを書いてみた。

using Gtk;

/**
 * Single Instance Window
 * valac --pkg gtk+-3.0 hoge.vala
 */
public class TextReader : Window {

    private Notebook _note;

    public TextReader () {
        // Property Set
        Object ( title: "Hoge", default_width: 500, default_height: 400 );
        _note = new Notebook ();
        this.add ( _note );
        this.show_all ();
    }
    public void create_tab ( File? file = null ) {
        if ( file == null ) {
            new_contents ( "New Document", "" );
        } else {
            try {
                var fstream = file.read();
                var dstream = new DataInputStream(fstream);
                var sb = new StringBuilder();
                string line;
                while ( (line = dstream.read_line_utf8(null)) != null ) {
                    sb.append( line );
                    sb.append_c( '\n' );
                }
                new_contents ( file.get_basename(), sb.str );
            } catch ( IOError e ) {
                 messagebox ( "IOError", e.message );
                 return;
            } catch ( Error e ) {
                messagebox ( "Error", e.message );
                return;
            } 
        }
    }
    private void new_contents ( string title, string text ) {
        var view = new TextView ();
        view.show ();
        var sw = new ScrolledWindow ( null, null );
        sw.add ( view );
        sw.show ();
        var label = new Label ( title );
        label.show ();
        if ( text != "" ) {
            var buf = view.get_buffer ();
            buf.set_text ( text );
        }
        var n = _note.append_page(sw, label);
        _note.set_current_page (n);
    }
    private void messagebox ( string title, string s ) {
        var dlg = new MessageDialog( this, DialogFlags.MODAL,
                    MessageType.WARNING, ButtonsType.OK, s );
        dlg.set_title ( title ) ;
        dlg.run ();
        dlg.destroy ();
    }
}

public class App : Gtk.Application {

    private TextReader _win;

    public App () {
        Object (application_id:"apps.test.textreader", flags:ApplicationFlags.HANDLES_OPEN );
    }
    protected override void startup () {
        base.startup ();
        _win = new TextReader ();
        add_window( _win );
    }
    protected override void activate () {
        _win.create_tab ();
        _win.present();
    }
    protected override void open ( File[] files, string hint ) {
        foreach ( var file in files ) {
            _win.create_tab ( file );
        }
        _win.present();
    }
    public static int main ( string[] args ) {
        Gtk.init ( ref args );
        var app = new App ();
        return app.run ( args );
    }
}

なかなか面白いことをみつけた。

public class ClassName : Window {
    public ClassName () {
        Object ( title: "Hoge", default_width: 500, default_height: 400 );

Python

class ClassName (Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self, title="Hoge", default_width=500, default_height=400):

Vala もこんな感じでプロパティセットが可能なんだね。
base ではなく Object なのか、何か凄く変です。
Python のほうが変という人のほうが多いという事実は置いておいて。

それより関数のパラメータをオブジェクトか NULL かで振り分けたい場合。
C ならポインタなのでそのまんま NULL かどうかを見分けできる、Python も同様。
型指定が厳密な C# の場合はオーバーロードを利用すると思います。

Vala は C に変換されるからそのままと思いきや C# と同じく型指定に厳密。
以下のようにすると見事にコンパイルエラーになってしまう。

public void create_tab ( File file ) {
    if ( file == null ) {
//etc...

// Compile Error
_win.create_tab (null);

最初は何故か全然解らず困ったけど多分 C# に合わせたということだろう。
しかし Vala はオーバーロードができないぞ、何か別の手段があるはずだ。
valadoc.org の cancellable 引数等の説明と同じように書いてみたらイケた。

public void create_tab ( File? file = null ) {
    if ( file == null ) {
//etc...

// OK
_win.create_tab ();

コレも凄く変です。
Python のほうが(以下略

後 GtkScrolledWindow は引数が必要だとか PyGI とは微妙に違うのね。
なんだかんだで勉強になった、実践的なコードを書くと色々気が付くものだ。
とにかく筆者は var と new と中括弧とセミコロンが面倒臭いです。

g_type_init

Vala の覚書ページを書き換えようとテスト。

init_error

なんだそりゃwww
警告が出るだけでビルドは問題なく行われるようだけど。

調べてみると GLib 2.36 からマジで g_type_init を廃止したようだ。
Fedora 19 の GLib はたしかに 2.36 だった。
Python ばかり使っているとこういうの気が付かないよね。

GIO入門 – ふとしの日記

#include <gio/gio.h>

/* gcc no_init.c `pkg-config --cflags --libs gio-2.0` */

gint
main (gint argc, gchar* argv[])
{
	GFile *gf;
	/* GLib >= 2.36 
	g_type_init ();*/
	gf = g_file_new_for_path ("sample.txt");
	return 0;
}

g_type_init は本当に不要になっているよふとしさん。
しかし Vala の場合はジェネレータが勝手に書き足すのだが…

[vala] codegen: Do not call g_type_init when targeting GLib >= 2.36

対策版は出ているのか、って Oct 2012 だから一年前かよ。
Fedora 19 パッケージの 0.20.1 は April 2013 のはずなのだが。

Lubuntu 13.10 の GLib は 2.38。
valac のパッケージを Synaptic で調べると同じ 0.20.1 か。
インストールしてみたけど、やはり症状は同じであった。

本家からソースを落として自力 make するか修正を待つか、うーん。
Vala のバージョンと GLib, GTK+ のバージョンは関係ってあるのか?
そのあたりがよく解らないから自力ビルドは避けたいのだが。

ビルドは可能なんだからこのままでもいいか、一番安全だし。

しかし `g_type_init vala` で検索しても日本語がまったく出てこない。
つまり日本人で Vala を使っている人はいないってことなのかも…