Fedora」タグアーカイブ

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 プラグインの更新ができないよ、まいった。

Fedora 15 007

Fedora 15 (GNOME 3) 64bit 生活七日目。
Ubuntu から Fedora へ乗り換えの覚書日記フィナーレ。

※ samba

Ubuntu でやっていてまだやっていないのは Windows との接続だ。

Ubuntu と Windows でファイル共有 – L’Isola di Niente
と同じように簡単ではない、つか共有なんてプロパティタブは Fedora 15 には無い。

とにかく「追加/削除」から samba 導入。
chkconfig コマンドを root で使って起動時にサービスが立ち上がるように。
ついでに先日導入した Apache も、Ubuntu は導入すれば全自動でやってくれたけど。

$ su
# chkconfig httpd on
# chkconfig smb on

ファイアーウォールの設定で Samba の項目にチェックを入れて適用。

ついでだが、 dconf-editor で workgroup を書き込んでおいたほうがよさそう。

再起動、Nautilus の「移動」メニューから「ネットワーク」に移動。
ひたすらクリックしていくと私のノート PC が見つかった。

これで Windows ノートからファイルをコピーできるようになった。
だけどこれだけでは fedora のファイルは Windows にはコピーできない。
SELinux を弄くる必要があるみたい。

Apache を動かしているのでとりあえず http で今回がお茶を濁した。
ifconfig コマンドで自分の ip アドレスを調べる。
ファイアーウォールで www を有効にする。
コピーしたいファイルを www ディレクトリにコピーする。
んで Windows のブラウザに ip アドレスを打ち込んでダウンロード。
面倒くさいけどコレなら SELinux に左右されないようだ。
以上多分誰もやらない Tips でした。

**********

で、一週間ほど x86_64 の Fedora を利用してみた結果。
問題無さそうだということで半年間継続利用することにします。

来週あたりに 8 GByte 以上のメモリを買ってきてみるか。
今まで仮想 Vista を使っている時にホストで何もできなかったもの。

追記

FTP のほうが簡単だった…

vsftpd を導入
SELinux の FTP 設定変更 # setsebool -P ftp_home_dir 1
使いたい時だけ FTP 有効 # /etc/init.d/vsftpd start
ファイアーウォールの FTP ポートを開ける。
Windows Explorer で ftp://Linux ユーザー名@IPアドレス/ホーム以下で FTP したい場所
例 ftp://sasakima-nao@192.168.1.21/_temp
Explorer がダイアログを出すので Linux のログインパスワード

終わったらファイアーウォールのポートを閉じればセキュリティもばっちり、と思う。
SELinux 自体はあまり弄くりたくないんでコレでいこうかと。

Fedora 15 006

Fedora 15 (GNOME 3) 64bit 生活六日目。

※ Gedit Plugin

Gedit/PythonPluginHowTo – GNOME Live!

Gedit 3 のプラグインは妙に複雑になった感じだけどやってみると簡単。
Gedit プラグインの作り方 – L’Isola di Niente
私の公開しているこのページを Gedit 3 用に改造してみる。

*.gedit-plugin 拡張子であったファイルは *.plugin と拡張子を変更。
セクション名を [Plugin] に、IAge を 3 に変更、v2 との違いはコレだけだ。

肝心のコード

#-*- coding:utf-8 -*-

import gedit
import gtk

class TestPligin(gedit.Plugin):
    def __init__(self):
        gedit.Plugin.__init__(self)

    def activate(self, window):
        self.window = window

    def deactivate(self, window):
        pass

    def update_ui(self, window):
        pass

#-*- coding:utf-8 -*-

from gi.repository import GObject, Gedit, Gtk

class TestPligin(GObject.Object, Gedit.WindowActivatable):
    __gtype_name__ = "TestPligin"
    window = GObject.property(type=Gedit.Window)
    def __init__(self):
        GObject.Object.__init__(self)

    def do_activate(self):
        pass
        
    def do_deactivate(self):
        pass

    def do_update_state(self):
        pass

ということみたい、コールバックに引数は無くなったんだね。
__gtype_name__ は class 名と同じにしなければいけないみたい。

多重継承の敬称元を Gedit.AppActivatable とか3つから選べになっている。
普通なら Gedit.WindowActivatable だけでいいだろう。
下のほうにあるサンプルコードは継承元を書き忘れているじゃん…

後は self.window のメソッドを辿って弄くっていく。
v2 のコードから gtk → Gtk に全置換する必要がある。
それと activate のコールバックは引数を3つにしておく必要があった。
user_data を指定しなくても None が送られてくるみたい、注意ね。

ついでに GtkMessageDialog の引数は enum 形式に変更されていた。
指定がよく解らない人は dir() で辿って(私はそうやった)

testtest.plugin

[Plugin]
Loader=python
Module=testtest
IAge=3
Name=testtest
Name[ja]=テストテスト
Description=plugin test
Description[ja]=プラグインのテスト
Authors=sasakima-nao 
Copyright=Copyright © 2011 sasakima-nao 
Website=http://palepoli.skr.jp/

testtest.py

#-*- coding:utf-8 -*-

from gi.repository import GObject, Gedit, Gtk

ui_str = """<ui>
  <menubar name="MenuBar">
    <menu name="EditMenu" action="Edit">
      <placeholder name="EditOps_3">
        <menuitem name="testtest" action="testtest"/>
      </placeholder>
    </menu>
  </menubar>
</ui>
"""

class TestTest(GObject.Object, Gedit.WindowActivatable):
    __gtype_name__ = "TestTest"
    window = GObject.property(type=Gedit.Window)
    def __init__(self):
        GObject.Object.__init__(self)

    def do_activate(self):
        # GtkUIManager を得る
        manager = self.window.get_ui_manager()
        # GtkActionGroup を新規で作成
        self._action_group = Gtk.ActionGroup("TestTestActions")
        # GtkActionEntry を作成
        # name, stock_id, label, accelerator, tooltip, callback
        actions = [("testtest", None, "引用に変換", None, "すてーたすばー", self.on_testtest_activate)]
        # GtkActionGroup に挿入
        self._action_group.add_actions(actions)
        # GtkUIManager に追加
        manager.insert_action_group(self._action_group, -1)
        self._ui_id = manager.add_ui_from_string(ui_str)
        
    def do_deactivate(self):
        manager = self.window.get_ui_manager()
        manager.remove_ui(self._ui_id)
        manager.remove_action_group(self._action_group)
        manager.ensure_update()
        

    def do_update_state(self):
        pass
    
    def on_testtest_activate(self, action, data=None):
        view = self.window.get_active_view()
        buf = view.get_buffer()
        try:
            begin, end = buf.get_selection_bounds()
        except:
            self.messagebox("変換したいテキストを選択してください")
            return
        text = begin.get_text(end)
        lines = text.split("\n")
        # list の join に変更
        result = []
        for line in lines:
            result.append("> {0}".format(line))
        buf.delete_selection(True, True)
        buf.insert_at_cursor("\n".join(result))
            
        
    def messagebox(self, text):
        dlg = Gtk.MessageDialog(
                self.window,  
                Gtk.DialogFlags.MODAL,  
                Gtk.MessageType.WARNING, 
                Gtk.ButtonsType.OK,  
                text)  
        r = dlg.run()  
        dlg.destroy()

と2つのファイルを作成して ~/.local/share/gedit/plugins に置く。
Gedit を再起動して設定からこのプラグインを選択。

GtkUIManager のメソッドや XML UI 指定は v2 と変わっていないようだ。
これで Gedit 3 のプラグイン作りはなんとかなりそう。

ついでに、外部ツールで実行前にファイルを保存するように指定すると動作しない。
gedit って更新毎に必ず一ヶ所はおかしな所があるよね。