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

register_sinkfunc

Y901x を機動すると以下の推奨メッセージが出るようになった。

** Message: pygobject_register_sinkfunc is deprecated (GstObject)

問題なく動くからあまり気にしていなかったけどそろっそろ…
海外を探しても関係ないバグ情報ばかりで困っていたのだが…

ふと思いついて rhythmbox で試してみても同じだった。

どうせ見つからないと思うけど日本語で探してみた。
んー、これはもしかしなくても ATI なのが悪いのかな。

Ubuntu日本語フォーラム / Moovidaメディアセンターが起動できません

ということで GStreamer がおかしいのだろう。
お手上げだ。

ついでに発見。
Y901x のフルスクリーンは全体サイズをフルスクリーンにしていた。
けど GDK だけフルスクリーンでもイケたと何を今更知った。
GtkBox に配置しているパーツは hide しなきゃいけないみたいだけど。

def change_fullscreen(self):
    if self.p_filename == "":
        return
    if self.fullscreen:
        self.fullscreen = False
        self.w.window.unfullscreen()
        #self.w.unfullscreen()
        self.fullobj.destroy()
        self.fullobj = None
        self.menubar.show()
        if self.full_list:
            self.listbox.show()
        #self.w.resize(self.fullsize.width, self.fullsize.height)
    else:
        self.fullscreen = True
        #cx, cy = self.w.get_size()
        #self.fullsize.width = cx
        #self.fullsize.height = cy
        self.full_list = self.listbox.get_property("visible")
        if self.full_list:
            self.listbox.hide()
        self.menubar.hide()
        self.fullobj = CFullCtrl(
                self.hbox_ctrl,
                self.toolbox,
                self.vbox_main,
                self.statusbar
            )
        #self.w.fullscreen()
        self.w.window.fullscreen()

つまり gtk.Window.window.fullscreen() 処理だけでよかった。
全体をフルスクリーンにして後でサイズを戻す処理は必要ないんだね。

コレならフルスクリーン中にリストを出す処理も簡単に実装できるかな?
そういえばリストを下に移動する処理を入れるって前書いたっけな。
ユーザーは多分自分だけだと思うからどうするのも勝手だけど。

WebKit for Python

Ubuntu 10.10 のアップデート、61MB もあるんかい!
ってよく見たら libwebkit なんてのがあるんだけど…

WebKit な Epiphany は GNOME 標準だけど Ubuntu では除かれているのに。
ライブラリだけは存在しますということなのかな?
まてよ、そういうことならデフォルト状態で Python から使えるかも。

>>>import webkit

10.10 はデフォルトで利用できるようです、てゆーか
/usr/share/doc/python-webkit/examples/browser.py
にサンプルコードがあるわな。

このサンプルコードを試してもいいけど最小限のコードを書いてみる。

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

import gtk
import webkit

class WebKitTest(gtk.Window):
    """
        WebKit test for Python
        from Ubuntu 10.10
    """
    def __init__(self):
        # Window
        gtk.Window.__init__(self)
        self.connect("delete-event", gtk.main_quit)
        self.resize(640, 480)
        # WebKit
        w = webkit.WebView()
        w.load_uri("http://google.co.jp/")
        # ScrollWindow
        sw = gtk.ScrolledWindow()
        sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        # add
        sw.add(w)
        self.add(sw)
        self.show_all()

if __name__ == "__main__":
    w = WebKitTest()
    gtk.main()

おぉ、コレだけで使えるのか。
GtkScrolledWindow を噛まさないと縦長のページで悲惨になるので注意ね。
後はサンプルコードを見ながらチマチマ弄くれば立派な自作ブラウザになりそう。

とにかく Python だけで何でも作れてしまう。
デフォルト状態でも作って遊べるというのはやはり素晴らしい。
Windows ではこんなこと考えられないものなぁ。

Linux Trash GVfs

十月、Linux 関連は毎度のごとく半年に一度のバージョンアップ時期。
新しい環境を半年に一度楽しめる、何がどう進化したのか確認するのが楽しい。
グチャグチャになりかけた HDD 内データを整理するよい機会だから必ず別 HDD に新規インスコ。
その時点までの HDD バックアップができるオマケ付き、半年毎の OS 入れ替えはマジお勧め。
しかし…

GNOME 2.32 リリース・ノート

GNOME 3.0 で libgnomevfs が使えなくなるのをそろそろなんとかしなくては。
だって Y901x でしっかり利用しているんだもの。

ぱぇぽぃ2 ? Blog Archive ? Get MIME Type and Description

コレを使わずに MIME Type 取得か、どうやるのだ?
海外を探すと GObject や GIO を使えと出てくる。
色々探すと関係ないんだけど GVFS なんてものを見つけた。

GNOME には gvfs-trash なんてコマンドがあるのか。
もしかして…

$ gvfs-trash ファイル名

これでゴミ箱移動ができたのね…
トップページで公開している trash コマンドはどうしよう…

text in liststore

そろそろ Y901x に機能追加をしようと先日より少しづつ弄くっております。
作った本人以外に使っている人がいないかもしれないがイイじゃないか。
少なくとも作っている本人は使っているんだから。

とりあえずファイルリストを Y901 と同様な下に位置変更できるようにしたい。
変更方法は Y901 と同じリストの右クリックメニューと Ctrl+F12 でいいだろう。
ということでリストに右クリックメニューを付けて上手く動くか実験中。
位置変更は空の GtkBox を配置してパレント変更するだけなので難しくないと思う。

そういえば現行では辞書で保持している設定を __slots__ 付き class に変更したい。
そうしておいたほうが後々の変更で凡ミスを防げる確率が高くなるはず。

self.setting = {"mimes": mimes,
                "position": False,
                "init_size_on": False,
                "init_size_val": 0,
                "esc_exit": False,
                "mem_rep": False,
                "mem_aspect": False,
                "loop": False,
                "severity": 25,
                "aspect_rate": [1,1],
                "set_size": [[320,240],[640,480],[1280,720]]}

# ↓

class CSetting(object):
    __slots__ = [
            "mimes", "position", "init_size_on", "init_size_val", "esc_exit",
            "mem_rep", "mem_aspect", "endressloop", "severity", "aspect_rate",
            "set_size"]
    def __init__(self):
        self.mimes = MIMES
        self.position = False
        self.init_size_on = False
        self.init_size_val = 0
        self.esc_exit = False
        self.mem_rep = False
        self.mem_aspect = False
        self.endressloop = False
        self.severity = 25
        self.aspect_rate = [1,1]
        self.set_size = [[320,240],[640,480],[1280,720]]

定数扱いなのに小文字だった mimes とかはキチンと大文字に変えて…
loop とか自分でもドレに相当するか解りにくい変数名は解りやすく変えて…
今になって見ると我ながら初心者丸出しで切ないよ。

setting[

で検索して地味に手書きで書き換えたけどドットを忘れるとかで間違えまくる。
ドット忘れだと動的言語は新規変数と扱ってしまうから間違いを見つけるのが大変。
問題なく動いている所をわざわざ書き換えてバグを作っているような気がするわな。

ところでリスト中にファイル名が存在するかを調べるのに

class CListBox(gtk.HBox):
    def __init__(self, window):
        self.sw = gtk.ScrolledWindow()
        self.view = gtk.TreeView()
        self.sw.add(self.view)
        self.liststore = gtk.ListStore(str)
        self.view.set_model(self.liststore)
        # etc...

    def is_text(self, text):
        # text in ListStore ?
        model = self.view.get_model()
        it = model.get_iter_first()
        while it:
            if model.get_value(it, 0) == text:
                return True
            it = model.iter_next(it)
        return False

こんな is_text というメソッドを作っていたのですが

def is_text(self, text):
    return text in [ r[0] for r in self.liststore ]

コレだけでイケたのね…
PyGtk って知れば知るほど親切な仕様だ。

とにかく書き換え箇所が多いので当面は自分でバグ探しになりそう。
ということでいつものようにバックアップ。
y901x-0.3.2b1.tar.gz

SeeMe 5.0.1 and 1.0.5

GtkSharp TreeView Tutorial – Mono

まだ SeeMe for Linux を GTK# で作っていた頃の参考にしたトコ。
よく見ると自作クラスを型として GtkListStore を作成しているコードがあった。
Controlling how the model is used 以下のところね。

こういう型指定って PyGtk でもできるのかな?
可能であればもっと本体のコード量を減らすことができるんだが。
とりあえず Python で同じように SeeMe コードを書きかえてみた。

class Engine():
    def __init__(self, deleted=True, name="New Item", key="", url="", query="",
                post=False, endsp=False, encode="utf8", stype=0, pos=0,
                nameid=0, verb=0, icon="", unique="", usetld=0):
        self.delete = deleted
        self.name = name
        self.key = key
        self.url = url
        self.query = query
        self.post = post
        self.endsep = endsp
        self.encode = encode
        self.stype = stype
        self.pos = pos
        self.nameid = nameid
        self.verb = verb
        self.icon = icon
        self.unique = unique
        self.usetld = usetld

class SeeMe4(gtk.Window):
    def __init__(self, sset):
        gtk.Window.__init__(self)
        #...
        #self.default_liststore = gtk.ListStore(bool, str, str, str, str, bool, bool, str, int, int, int, int, str, str, int)
        self.custome_liststore = gtk.ListStore(Engine)

型指定の時点で駄目ジャン…
property にしてみたり小細工してみたりしたけど無駄な努力だった。
Python では変数宣言しただけでは型が決まっていないので当然なのかも。

gtk.ListStore

ま、公式の Constructor 解説には C 言語と同じ型を全部書く方法しか書かれていない。
できないことは素直に諦めて、せめて GtkListStore への append をもう少し簡単にやれないか?

てか、そうしておかないと後々のメンテで沢山書き換えを行わなければいけなくなる。
後で書き換えが必要だろう箇所が少なければ少ないほどミスが減るのよね。
というかソレがオブジェクト指向最大のメリットなのだし。

よく考えたら SeeMe で GtkListStore の型は一つしか無い。
だったら GtkListStore サブクラスを作ってコンストラクタでとっとと型を指定。
ついでに Engine クラスを受け取る add メソッドを作れば簡単になるかな?

class Engine():
    def __init__(self, deleted=True, name="New Item", key="", url="", query="",
                post=False, endsp=False, encode="utf8", stype=0, pos=0,
                nameid=0, verb=0, icon="", unique="", usetld=0):
        self.delete = deleted
        self.name = name
        self.key = key
        self.url = url
        self.query = query
        self.post = post
        self.endsep = endsp
        self.encode = encode
        self.stype = stype
        self.pos = pos
        self.nameid = nameid
        self.verb = verb
        self.icon = icon
        self.unique = unique
        self.usetld = usetld

class CreateListStore(gtk.ListStore):
    def __init__(self):
        gtk.ListStore.__init__(self, bool, str, str, str, str, bool, bool, str, int, int, int, int, str, str, int)

    def add(self, en):
        return self.append( [en.delete, en.name, en.key, en.url, en.query,
                en.post, en.endsep, en.encode, en.stype, en.pos,
                en.nameid, en.verb, en.icon, en.unique, en.usetld] )

class SeeMe4(gtk.Window):
    def __init__(self, sset):
        gtk.Window.__init__(self)
        #...
        self.custome_liststore = CreateListStore()
        #...

    def read_default_searchini(self):
        self.default_liststore.clear()
        inipath = self.sset.default_path
        lngpath = self.sset.lang_path
        if os.path.exists(inipath):
            ini = inifile8.Inifile(inipath)
            lng = inifile8.InifileReader(lngpath)
            try:
                self.iniver = ini.read_int("Version", "File Version", 0)
                i = 0
                while 1:
                    i += 1
                    s = "Search Engine %i" % i
                    if not ini.section_exists(s):
                        break
                    t = ini.read_str(s, "Key", "")
                    if t == "":
                        continue
                    en = Engine();
                    en.nameid = ini.read_int(s, "Nameid", 0);
                    if en.nameid != 0:
                        # Get View Name from *.lng
                        if en.nameid == 17171:
                            en.name = lng.read_str("Translation", "1632215285", "")
                        elif en.nameid == 17183:
                            en.name = lng.read_str("Translation", "-1971470391", "")
                        elif en.nameid == 71103:
                            en.name = lng.read_str("Translation", "-1453429782", "")
                        else:
                            en.name = lng.read_str("Translation", str(en.nameid), "")
                        if en.name == "":
                            n = -1752227277 - en.nameid;
                            en.name = lng.read_str("Translation", str(n), "")
                    else:
                        en.name = ini.read_str(s, "Name", "")
                    en.key = t
                    en.url = ini.read_str(s, "URL", "")
                    en.query = ini.read_str(s, "Query", "")
                    en.post = ini.read_bool(s, "Is post", False)
                    en.endsep = ini.read_bool(s, "Has endseparator", False)
                    en.encode = ini.read_str(s, "Encoding", "utf-8")
                    en.stype = ini.read_int(s, "Search Type", 0)
                    en.pos = ini.read_int(s, "Position", -1)
                    en.verb = ini.read_int(s, "Verbtext", 0)
                    en.delete = True #!
                    en.unique = ini.read_str(s, "UNIQUEID", "")
                    en.icon = ini.read_str(s, "ICON", "")
                    en.usetld = ini.read_int(s, "UseTLD", 0)
                    """self.default_liststore.append( [
                            en.delete, en.name, en.key, en.url, en.query,
                            en.post, en.endsep, en.encode, en.type, en.pos,
                            en.nameid, en.verb, en.icon, en.unique, en.usetld] )"""
                    self.default_liststore.add(en)

    def on_item_new(self, widget, event=None):
        uid = self.create_uuid()
        num = self.deditor.get_radio_num()
        if num == 2:
            num = -1988219522
        else:
            num = 0
        en = Engine(verb=num, unique= uid)
        #it = self.custome_liststore.append( [True, "", "", "", "", False, False, "utf-8", 0, -1, 0, num, "", uid, 0] )
        it = self.custome_liststore.add(en)

コードは全然短くならないけど Engine を直で渡して展開できるようになった。
デフォルト引数によってアトリビュートの型も大半が気にしないでいいという。
読み込みや新規アイテムで順番を気にする必要が無くなったのはデカい。
これなら後々で順番の入れ替えや追加の必要があっても型側で調節できる。

ただこのコードでは展開するために for ループにすると

for row in self.default_liststore:
    if row[0] == False:
        i += 1
        s = "Search Engine %i" % i
        ini.write_str(s, "UNIQUEID", row[13])

添字アクセスにするしか無いんだなぁこれが、意味ネェ。
イテレーターは整数による順番という概念を使わないことに意義があるのだが。
この部分については WPF は徹底的にやっている感じ、よく考えて作られているよ。
ここをアトリビュートで取り出すサブクラスをどうすれば作れるか考え中。

ということで重複キーチェック追加や不具合修正で Linux 版更新。
キーボードショートカットを増やしたり不具合修正で Windows 版も更新。

「こんなことができると楽」
な方法を考えている時がアプリケーション作りで一番楽しいです。