月別アーカイブ: 2011年6月

pygtk3 Variable Parameter

いきなり本題だが、GtkTreeView の並び順を変更するコードを書いていた。
以前の PyGtk では GtkTreePath が単なるタプルだったけどそうではないようだ。

GtkTreeModel
とにかく C 言語と同じように書けばいいだろう。
やってみると凄く簡単にできた、しかし…

''' old
def on_item_up(self, widget, event=None):
    selection = self.custome_treeview.get_selection()
    model, it = selection.get_selected()
    if it:
        path = model.get_path(it)
        if path[0] > 0:
            path2 = (path[0]-1, )
            itprev = model.get_iter(path2)
            if itprev:
                model.swap(it, itprev)
                self.change()
    else:
        self.messagebox(MESSAGE_NON_SELECT)
'''
# new
def on_item_up(self, widget, event=None):
    selection = self.custome_treeview.get_selection()
    model, it = selection.get_selected()
    if it:
        itprev = it.copy()
        if model.iter_previous(itprev):
            model.swap(it, itprev)
            self.change()
    else:
        self.messagebox(MESSAGE_NON_SELECT)

Python なのに戻り値で代入ではなく引数の値が直接変更されている。
model.iter_previous(itprev) が bool 値しか戻さないのでしばし悩んだ。
もしかして、とやってみたらこの結果。

こんなの ctypes の byref 以外で見たことが無い。
IronPython でさえ out だったら戻り値とまとめてタプルで戻すというのに。

てゆーか可能だったんだ。
明示的な型宣言ができない Python では問題がでないだろうか心配。

**********

それより Opera 11.11 の search.ini はどうなっているんだ?
Default Search キーの UUID を手書きで書き換えても本体に適用できない。
書き換えるとたとえ非表示にしていても Google と Yahoo が復活するんだが。
並べ替えは何も問題なく行われるのですが。
わけがわからないよ。

コンボボックスで簡単に変更できるようにしたけどまったく無意味になった。
こんなの酷いよ、あんまりだよ…

しかも Deleted を 1 にして Opera 本体機能で編集するとそのセクションが消滅する。
こんなの絶対おかしいよ。

とにかく現状では Default Search を弄くらず deleted を利用しなければ多分問題ない。
需要ゼロに等しいアプリだからこんなんでいいよね、もう少し改造と Debug をするけど。

GNOME3 の雰囲気に合わせて激シンプルへと向かっている。
バックアップ
seeme-1.9.1.tar.gz

pygtk3 pack_start

自作 PyGtk アプリを Gtk3 に切り替えしたい。
よし、まずは SeeMe for Linux だ。
現行 Opera の仕様と合わないまま放置もどうかと思うし。

名前を SeeMe for Linux という無駄に長い名前から seemex に変更。
単純に打つのが面倒なだけです、バージョンは 2.0 でいいな。

まず gtk 名前空間の変更、面倒だから変名しちゃえ。
というか大文字の名前空間ってやっぱり変だよね。

#import pygtk
#pygtk.require("2.0")
#import gtk
from gi.repository import Gtk as gtk

定数の大半が列挙体名のアトリビュートに変わっているのは以前書いた。
gtk.FILL が Gtk.AttachOptions.FILL になったのを見つけるのに苦労したぞ。

pack_start の引数は expand, fill, padding を C 同様に全部指定する必要あり。
デフォルト引数は現行方式では用意されていない、バインディング方法が違うし。

# old pack_start(child, expand=True, fill=True, padding=0)
v = Gtk.VBox()
v.pack_start(widget, True, True, 0)
#v.pack_start(widget) Error

アイコンは GdkPixbuf を作らなくてもパスで良かったのね、前から…

path = os.path.join(os.path.dirname( __file__ ), "seeme.xpm")
#self.icon = gtk.gdk.pixbuf_new_from_file(path)
#self.set_icon(self.icon)
self.set_icon_from_file(path)

でも GdkPixbuf をファイルから作らないと Y901x のボタンが利用できない。
んー cairo を使うみたいなんだけど今はよく解らない。
seeme からやりはじめて助かった…

レンダラのコールバック引数とかに user_data が入って飛んでくる。
とにかく何をやるのも C 言語で書くのと同じようにしなきゃいけなくいなった。

GtkDialog に vbox アトリビュートなんかも当然無い。
C 言語同様に get_content_area で GtkBox を得る必要あり。
PyGtk だからこそ便利だった拡張が丸ごと利用できなくなった。

他 PyGtk2 との細かい差はここから辿って見つけて。
GTK+ 3 Reference Manual

GtkAboutDialog は set_url_hook せずともリンクボタンになる。

VERSION = "1.9.0"

class SeeMe4(gtk.Window):
    #...
    def on_about(self, widget, event=None):
        url = "http://palepoli.skr.jp/"
        w = gtk.AboutDialog()
        w.set_transient_for(self)
        w.set_program_name("seemex")
        w.set_version(VERSION)
        w.set_copyright("Copyright(C) 2009-2011 sasakima-nao")
        w.set_license("GPL")
        w.set_logo(self.get_icon())
        v = "GTK+ Version {0}.{1}.{2}".format(
                gtk.get_major_version(),
                gtk.get_minor_version(),
                gtk.get_micro_version())
        w.set_comments(v)
        w.set_website(url)
        w.set_website_label(url)
        w.run()
        w.destroy()

よし、とりあえず GTK+ 3.0 なアプリになったぞ。
Ubuntu 11.04 で動かしていないけど多分 Ubuntu では GTK2 になるはずだが。
後は現行 Opera で無意味になったセパレータ指定とかを消したり色々。

バックアップ
seeme-1.9.0.tar.gz

コイツが一段落したら Windows 版をどうしよう…

v1 とある理由から Delphi でチャチャッと作成
v2 動画プレイヤー作りが嫌になった反動で無意味にコレの製作を続ける
v3 WPF で何か作りたいという理由だけで C# 化
v4 インストーラを作ってみたいという理由だけでインストーラ化
v5 IronPython で何かを作りたいという理由だけで IronPython 化
v6 自分でビルドしろ第二段にしたい理由だけで C# に戻す、かも…

Windows 版は完全に作者のおもちゃ。
いやコレを作ったから私は十年も生き残っているのは間違いないんだが。

Linux shift-jis zip file

とある ZIP を展開しようと思ったら Shift-JIS ファイル名を使っていて展開できない。
Ubuntu 日本語 Remix 付属の /usr/bin/zip なら展開できるのだけど Fedora だし。
仮想マシンの Ubuntu から頂いて、と思ったけど我が Fedora は 64bit だった…

仮想マシンな Windows XP から共有を利用して展開。
とソレだけの理由で仮想 Windows を立ち上げるのも面倒だ。
そういえば Python には zipfile モジュールがある、作ってみよう。

とりあえず日本語のドキュメントを探してみた。
13.4. zipfile ? ZIP アーカイブの処理 ? Python v2.6.2 documentation
extractall なんて便利なメソッドがあるじゃん、これは簡単そうだ。
ということで Nautilus スクリプトにしてみた。

#!/usr/bin/env python
#-*- coding:utf-8 -*-

import zipfile
import os

filenames = os.environ["NAUTILUS_SCRIPT_SELECTED_FILE_PATHS"].split("\n")

for f in filenames:
    z = zipfile.ZipFile(f)
    z.extractall()
    z.close()

こんなに単純なコードでいいみたい。
ファイル名は見事に化けてしまいますが展開だけは成功する。

そういえばパスワード付きの場合もある。
GTK+ でダイアログでも出して入力すればいいかな。

#!/usr/bin/env python
#-*- coding:utf-8 -*-

import zipfile
import os
import gtk

filenames = os.environ["NAUTILUS_SCRIPT_SELECTED_FILE_PATHS"].split("\n")

for f in filenames:
    z = zipfile.ZipFile(f)
    dlg = gtk.Dialog("password", None, 0, (gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
    def dlg_ok(self):
        dlg.response(gtk.RESPONSE_ACCEPT)
    entry = gtk.Entry()
    entry.connect("activate", dlg_ok)
    dlg.vbox.pack_start(entry)
    dlg.show_all()
    dlg.run()
    p = entry.get_text()
    dlg.destroy()
    z.extractall(pwd=p)

展開が終了するまでダイアログが閉じないのは何故だろう…
それと展開は死ぬほど遅い…

せっかく作ったけど素直に仮想 Windows から展開するとかのほうが良さそう。
まあ使いたくなる場合もあるだろうからスクリプト登録だけはしておくか。

ところで今頃気がついた。
Nautilus スクリプト位置にディレクトリを作れば入れ子にできるんだね。

まだまだ増やしても大丈夫そうだ。

gi.repository GTK+ Version

Fedora 15 と Ubuntu 11.04 の PyGtk について。

その前に VirtualBox ose 上で Ubuntu を使っているけど \ や | が打てない。
Ubuntu日本語フォーラム / Virtualbox 4.0 で一部のキーが使えない?
VirtualBox ose の Update を待とう…
今回はホストの fedora からクリップボードコピペでなんとかした。

#!/usr/bin/env python
#-*- coding:utf-8 -*-

from gi.repository import Gtk

message = "「はい」を押すと終了"

while 1:
    dlg = Gtk.MessageDialog(
            None,  
            Gtk.DialogFlags.MODAL,  
            Gtk.MessageType.WARNING, 
            Gtk.ButtonsType.YES_NO,  
            message)  
    r = dlg.run()  
    dlg.destroy()
    if r == Gtk.ResponseType.YES:
        break
    elif r == Gtk.ResponseType.NO:
        message = "それは「いいえ」だろ!"
    elif r == Gtk.ResponseType.DELETE_EVENT:
        message = "閉じるボタンじゃネェ!"
    else:
        message = "不明な動作..."

このコードで Fedora 15, Ubuntu 11.04 のどちらでも動く。
Ubuntu 10.10 以前では例外になる、つか gi から無いわけで。
Fedora のダイアログは「閉じる」ボタンが出ないので右クリックで「閉じる」とやる。

import が変更になり gtk を Gtk に全置換。
以前は定数だったものの大半が enum 名のアトリビュートに変わっている。
それ以外はほとんど同様と思っていいみたい。

つまり Ubuntu 11.04 も GTK3 なのか。
と思ったけどインタラクティブシェル上でコレをやってみる。

from gi.repository import Gtk
Gtk._version

Ubuntu 11.04 の場合はこの形式で書いても GTK2 になるってことなのか。
/usr/lib64/python2.7/site-packages/gi/overrides/Gtk.py
がバージョン違いを振り分けているみたい、とにかくそういうこと。
ソースコードを見てもなんだかよくワカンネェ!

なんにしても早めにこの形式なコードへ書き換えしたほうがいいみたい。
API ドキュメントは既に GTK+ 3.0 になっているのだし。
PyGtk ドキュメントが遅いのはいつものこと。
GNOME 開発センター

ついでに

EyeOfGnome/Plugins – GNOME Live!

このとうりにやっても全然 eog が自作プラグインを認識しない…
~/.local/share/eog/plugins や ~/.local/lib64/eog/plugins
にも試しに置いてみたけど無意味だった。
/usr/lib64/eog/plugins に置くしか無いのだろうか。
ついでに IAge 指定が 2 のままじゃん、Gedit と違ってヤル気が無い感じ。
おかげで自作 eog プラグインの更新ができないよ、まいった。