覚書ページをなんとかしたい

Y901x 0.1.3 公開しました。

結局トグルボタンとラジオボタンの同期は自前で行った。
どうやったかはソースコードを見てください、我ながらナイスなシグナルの逃し方だ。
本当はラジオボタンも同じメニュー選択で解除にしたいけど一般的な動作じゃないし。

boko

ツールバーにしてみたら上のようにボッコリするのと右寄せができないので気に入らなかった。
ソースコードにコメントアウトして残しています、XML のトコも外してね。

まだやることはあるけど、とにかくこれでしばらくは落ち着けるかもしれない。

プレイヤーが作りたいというより PyGtk で何か作ったものを公開したい。
Python で GUI アプリが簡単に作れ環境もデフォルトで揃っているコトを知らない人が多すぎる。
ウチへの検索ワードにヤケに mono が多い理由はソレだと思うので知ってもらいたい。
という感じでやっているのであまり複雑にしたくないし。

つか、そろそろ覚書ページをなんとかしたいんだが今やっているコトを解説は難しいぞ。
GtkUIManager はどう考えたってプログラミング初心者には敷居が高いんだが…
恐ろしく楽ができるウイジェットだけど事前知識がかなり必要になる。

かと思えば Glade もとても初心者には勧められないようなシロモノになっちまった。
個別ウイジェットの解説から始めてゼロから作り直ししたほうが良さげな感じ。

それはそうと、いいかげんに違うアプリを作りたいものだ。
Y901x のリネーム機能を Eye of GNOME のプラグインにしようかと企んでいる。
需要はシラネ、本日はお知らせのみ。

ラジオメニューとトグルボタンの同期

Y901x 0.1.2 公開しました。
こんな Windows 用のノリでやっていても良いものかと思い始めた今日この頃。

っっって…指定倍率変更の計算が間違えているのに今気がついた!
せっかくまとめて listbox クラスにしたのにセパレータサイズを足していた。
あーあ明日もごまかすために更新だ、更新が特定期間に集中する原因はコレです。

ところで。

ラジオメニューとトグルボタンは UIManager から同期させられないっぽい。
と以前書いたけどツールバーならあっさりできるようで。

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

import gtk

ui_str = """<ui>
    <menubar name="MenuBar">
        <menu action="Rep">
            <menuitem action="non"/>
            <menuitem action="one"/>
            <menuitem action="all"/>
            <menuitem action="rdm"/>
        </menu>
    </menubar>
    <toolbar name="Toolbar">
        <toolitem action="one"/>
        <toolitem action="all"/>
        <toolitem action="rdm"/>
    </toolbar>
</ui>"""

class BtnBox(gtk.Window):
    def __init__(self):
        gtk.Window.__init__(self)
        #
        # GtkUIManager 作成
        self.uimanager = gtk.UIManager()
        #
        # GtkActionGroup 作成
        self.actiongroup = gtk.ActionGroup("sasakimamenu")
        #
        # GtkAccelGroup を得てウインドウに突っ込む
        # 何もグループを作らなくてもコレやらないと後のアクセラレータ指定が効かない
        accelgroup = self.uimanager.get_accel_group()
        self.add_accel_group(accelgroup)
        #
        # GtkActionEntry を作成して突っ込む
        # 得にグループにしないものはココでまとめて作成
        # name, stock_id, label, accelerator, tooltip, callback
        self.ac0 = [("Rep", None, "リピート(_R)")]
        self.actiongroup.add_actions(self.ac0)
        #
        # GtkRadioActionEntry の List を作成
        # name, stock_id, label, accelerator, tooltip, value
        self.ac1 = [("non", None, "無し", "0", "無し", 0),
                    ("one", None, "シングル", "1", "シングル", 1),
                    ("all", None, "オール", "2", "オール", 2),
                    ("rdm", None, "ランダム", "3", "ランダム", 3) ]
        # GtkRadioAction を突っ込む
        # entries, value=0, on_change=None, user_data=None
        self.actiongroup.add_radio_actions(self.ac1, 0, self.on_loop_change)
        #
        # GtkUIManager の更新
        self.uimanager.insert_action_group(self.actiongroup, 0)
        self.uimanager.add_ui_from_string(ui_str)
        self.uimanager.ensure_update()
        # menubar を抜き出す
        menubar = self.uimanager.get_widget("/MenuBar")
        # toolbar を抜き出す
        toolbar = self.uimanager.get_widget('/Toolbar')
        # pack
        vbox = gtk.VBox()
        vbox.pack_start(menubar, False)
        vbox.pack_start(toolbar, False,False)
        self.add(vbox)
        self.connect("delete-event", gtk.main_quit)
        self.resize(320, 150)
        self.show_all()
        self.val = 0

    def on_loop_change(self, action, current):
        # コレは無理だった
        num = action.get_current_value()
        if num == self.val:
            action.set_current_value(0)
        else:
            self.val = num

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

repeat

得に何をするわけでもなく action を共通にすれば同期してくれるわ。
だけどアクティブなボタンを再度押すとオフにするといった処理は無理か。
ボタンオブジェクトを抜いて clicked シグナルを処理すればよさげだけど。

コレ上手く使えないかな?いまここ。

Linux のゴミ箱

Y901x 0.1.1 バグ修正を公開しました。
ココにリネーム方法を書いたのに少し書き換えた私がアホだった…

ところで

何を今頃気がついたが os.remove でファイル削除するとゴミ箱に入らずに消滅する。
そういえば UNIX には元々ゴミ箱なんて無かった、つーか rm で削除すると消滅ですがな。

何か Nautilus に慣れてしまってゴミ箱に入るものだとうっかりしていた。
Windows ShellAPI の SHFileOperation みたいな方法は無いのだろうか?

ちなみに Ubuntu のゴミ箱に捨てたファイルは以下にある。

~/.local/share/Trash/files

しかし調べてみるとディストリビューションによって下記もあるようで。

~/.Trash
~/.Trash-0

ゴミ箱 – Wikipedia

規格の範囲でファイルマネージャ毎に決めているっぽい。
FreeDesktop.org での規格なら xdg-trash とか、無いか…

Ubuntu — Details of package xdg-utils in jaunty

ついでに、メニューのインストールには xdg-desktop-menu を本当は使わなきゃいけないのね。
make や dpkg は勝手にそれをやってくれるということでいいのかな。
Y901x のインストールスクリプトは言うまでもなく直で突っ込んでいる、知らなかったよ。
Ubuntu 限定に近いから別にイイんだが真似しないほうがいいよあの方法は。

Ubuntu日本語フォーラム / HOWTO: CLIからゴミ箱を使う

こういうのがあるのか。
端末からゴミ箱利用はかなり微妙だけど保険にはなるかも。
間違えて Blog の画像を全部消したコトがある私はそう思う。
でもレンタルサーバーで FTP ソフトを使ったら全く意味が無いとも。

コレをインストールしてもらえば…だからソレはやりたくない。
よし決めた、面倒だから当面は消滅のままでいいや!これが私の(略

GTK+ はキーの長押しを認識できないようで

Y901 というアプリは上下矢印キーの長押しでリスト選択位置の移動のみを行っていた。
キーを離し WM_KEYUP メッセージを捕まえた所で選択位置のファイルを再生開始していた。
当然 Y901x でもそうしたいわけだ。

しかし…とにかくコレを動かして上下どちらかの矢印キーを押しっ放しにしてみる。

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

import gtk

class KeyUpDown(gtk.Window):
    def __init__(self):
        gtk.Window.__init__(self)
        self.tv = gtk.TextView()
        sw = gtk.ScrolledWindow()
        sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
        sw.add(self.tv)
        self.add(sw)
        # GDK イベントの有効化を行っておく
        self.set_events(gtk.gdk.KEY_PRESS_MASK | gtk.gdk.KEY_RELEASE_MASK)
        self.connect("key_press_event", self.on_key_press)
        self.connect("key_release_event", self.on_key_release)
        self.connect("delete-event", gtk.main_quit)
        self.resize(300, 400)
        self.show_all()

    def on_key_press(self, widget, event):
        if event.keyval == 65362 or event.keyval == 65364:
            buf = self.tv.get_buffer()
            s = "押した\n"
            it = buf.get_end_iter()
            buf.insert(it, s, len(s))

    def on_key_release(self, widget, event):
        if event.keyval == 65362 or event.keyval == 65364:
            buf = self.tv.get_buffer()
            s = "離した\n"
            it = buf.get_end_iter()
            buf.insert(it, s, len(s))

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

updown

つまり key_press_event シグナルは必ず key_release_event シグナルと交互に発生する。
Windows のように WM_KEYDOWN イベントのみが起こるというわけではないようだ。
キーを離し WM_KEYUP メッセージを捕まえるように key_release_event を…

できない!

まいった、何か方法を見つけるまで今までどうり一つ上下移動のみにするしかない。
つーかこの現実が解るまで「あれぇ?なんで???」と苦しんだ私であった。

それとラジオメニューとトグルボタンは UIManager から同期させられないっぽい。
しかたがないのでリピート用のトグルボタンを排除するという暴挙で解決!
パッと見て状態が解ればいいんだからステータスバーに表示、これが私のクオリティ。

追記、長押し判定する方法がありました
GTK+ Cancel Long Keypress | PaePoi

PopupMenu と MouseGesture の同居に困った

PopupMenu と MouseGesture の同居に困った

GTK+ のアプリは基本的にマウスの右ボタンダウンでポップアップメニューが出る。
しかしもはや Linux 標準アプリになった Firefox はボタンアップで出る。
マウスジェスチャ機能があるからだ、当然 Opera も同様。

ということで違和感が無い人も多いと思うので遠慮なくボタンアップでポップアップを実装
…しようとしたんだけど完全な振り分け方法を思いつけなくてココだけで半日使った。

popup

まあとにかくここは上手くいったと思う、やはりデカいので入れ子にしたのは妥協だ。

しかし困った、入れ子のメニューは何故か右クリック時しかシグナルを吐いてくれない。
入れ子にしていないメニューは左クリックでもキチンとシグナルを吐くのにどういうこと?

GTK+ 製である Firefox はどうだ…ってコイツの右メニューには入れ子が無かったわ。
Totem で試すとしっかり右クリックで入れ子にも反応する、ますます解らなくなったぞ。
実装方法が変わると違うかも…何か方法があるはずだがよく解らない。

そうそう、試しに右ボタンダウンで出すように実装したら普通にシグナルを吐く。
どういうことかはバックアップしているのを試すと解ると思う。

それと画面 W クリックでフルスクリーンだが。
右メニューやダイアログを出しフォーカスが移ると GNOME メニューがコンニチハ。
これはどうすれば防げるか、Totem はそんなの出ないんだよなぁ…

gtk.gdk.Window

GDK にも何故か fullscreen メソッドがあるんだがもう何がなんだか解らん。
試しに入れてみたけど違いが無いみたいだけど。

せっかくリピートメニューと RadioAction を作ったのに実装する時間がなかったわい。
バックアップを置いておきますんで、くそぉ進まなかった。

y901x-buckup2.zip