Ruby/Qte普及委員会 RubyQpeApplet

XREAAD
Create  Edit  Diff  FrontPage  Index  Search  Changes  History  RSS  Login

実験室

RubyQpeApplet - アプレットもRubyで書こう

これは何か

タスクバーのアイコンをクリックして起動する「アプレット」を、Rubyで書けるようにするためのプラグインです。

まだ実験段階ですので、Ruby側のスクリプトの書き方などは、これから仕様が変わるかもしれません。

!!!危険!!!

アプレットプラグインはQtopiaの起動時に読み込まれます。もし読み込みに失敗すると、再起動を繰り返し、操作不能になります。

回復するには、シングルユーザーモードで起動し、コマンドラインで操作してプラグインのファイルを削除する作業を行う必要があります。

この作業に不安のある人は使用をお控えください。

シングルユーザーモードでの起動 (SL-C3000の場合)

  • バッテリーの蓋を開け、キーボードの [D] と [B] を押しながら、バッテリー付近の黒いリセットボタンをペンでタップする。
  • バッテリーの蓋を閉めてロックする。
  • On/Offボタンを押す。
  • しばらく待つとログインプロンプトが表示されるので、root でログインし、Password プロンプトには何も入力せず Enterキーを押す。

プラグインの削除

  • ディスクのマウント
 # mount -t ext3 /dev/hda2 /hdd2
  • プラグインの削除
 # rm /hdd2/QtPalmtop/plugins/applets/librubyqpeapplet.*
  • アンマウントとシャットダウン
 # umount /hdd2
 # shutdown -h now

マルチユーザーモードで再起動

  • バッテリーの蓋を開け、リセットボタンをペンでタップする。
  • 蓋を閉じ、ロックする。
  • On/Offボタンを押す。

ダウンロードとインストール

あらかじめ、Ruby 1.8.4 と Ruby/Qte 0.5.4 をインストールしておいてください。

RubyQpeApplet はまだ実験段階のため、ipkは提供していません。

上のファイルをダウンロードし、コマンドラインで展開してください。

ソースコード一式とプラグインのバイナリ、初期設定ファイル、サンプルスクリプトが入っています。

インストールは添付の inst.sh で行ってください。

 $ su
 # ./inst.sh

この後、Qtopiaのスタートボタンから再起動してください。

インストール後のファイル構成

  • /opt/QtPalmtop?/plugins/apps/librubyqpeapplet.so.1.0.0

プラグイン本体。

  • /opt/QtPalmtop?/bin/rqarun

アプレットを起動するコマンド。プラグインから呼び出される。

  • /opt/QtPalmtop?/pics/rubyqpeapplet.png

タスクバーに表示される 14x14 のアイコン。

  • /opt/QtPalmtop?/lib/ruby/site_ruby/1.8/qpeapplet.rb
  • /opt/QtPalmtop?/lib/ruby/site_ruby/1.8/qtedecl.rb

Applet用ウィジェットのためのRubyライブラリと、宣言的構文 でRuby/Qte スクリプトを簡潔に書くためのライブラリ。

  • /home/zaurus/Settings/rubyqpeapplet.conf

初期設定ファイル。アプレットとして登録するRubyスクリプトのファイル名とクラス名をここに記述します。また、[Log] セクションにはエラーログの出力先ファイル名を書きます。

 [Applet]
 file_name = /home/zaurus/Applications/rubyqpeapplet/hello.rb
 class_name = Hello
 [Log]
 file_name = /tmp/rubyqpeapplet.log
  • /home/zaurus/Applications/rubyqpeapplet/hello.rb

サンプルスクリプト。以下のような中身になっています。

 class Hello <Qpe::Applet::Base
   def user_interface
     self.caption = qs('Hello')
     lb = label 'Hello, world.'
     self.fixedSize = lb.sizeHint
   end
 end

アプレットの書き方

Qpe::Applet::Base クラスを継承したクラスを1つ定義し、user_interface メソッドを定義してください。

上記の hello.rb では qtedecl.rb (→宣言的構文) を使った書き方をしていますが、普通の Ruby/Qte の書き方でもかまいません。

また、他には何を書いてもかまいません。

ボタンのクリックなど、ユーザーの操作によって呼び出されるメソッドでは、定義の中身全体を begin ... rescue ... end ブロックで囲んで、例外を捕捉しなければなりません (後述)。

タスクバー上のアイコンをクリックすると、アプレットに対して clicked シグナルが送出されます。Qpe::Applet::Base クラスのコンストラクタでは、clicked シグナルに対して toggle_show_hide メソッドを connect しています。この動作を変更するには、toggle_show_hide メソッドをオーバーライドするか、アプレットのコンストラクタをオーバーライドして、別のメソッドに connect するかしてください。詳しくは lib/qpeapplet.rb を参照してください。

(必読) 例外の捕捉

アプレットで生じる例外は、begin ... rescue ... end ブロックを使って、コード内で捕捉することを勧めます。さもないと、Qtopiaが落ちます。(→0.4で一部解決。)

例:

 class Danger <Qpe::Applet::Base
   def user_interface
     pb = push_button 'Push'
     connect(pb, QSIGNAL('clicked()'), self, 'doit')
   end

   def doit
     begin
       # ...処理...
     rescue
       log_error($!)
     end
   end
 end

user_interface メソッドの中は begin ... rescue ... end で囲んでいませんが、これで大丈夫です。user_interface メソッドはコンストラクタから呼び出されますが、コンストラクタ呼び出しはプラグインライブラリ側で例外を捕捉しているためです。

また、捕捉した例外の情報をログファイルに記録するため、log_error という関数を定義してありますので、利用してください。

参考: ruby-gnome2-devel-jaの議論

例外が生じてアプレットが異常終了した場合、タスクバーのアイコンクリックに反応しなくなります。そうなったら、qcopメッセージによる再読み込み(後述)を試してください。

タイトルバーを非表示にする方法

次のようにアプレットのコンストラクタを定義して、その中で wflags を指定すると、タイトルバーが非表示になり、よりアプレットらしい外観になります。

 class Hello <Qpe::Applet::Base
   def initialize(parent = nil, name = '',
                  wflags = Qt::WType_Popup | Qt::WStyle_StaysOnTop)
     super(parent, name, wflags)
   end
 # ...
 end

Rubyスクリプトの再読み込み

コマンドラインで、

 qcop QPE/RubyQpeApplet 'reload()'

を実行することにより、初期設定ファイルを読み直し、子プロセスのrqarunコマンドを再起動して、指定されたRubyスクリプトを解釈・実行します。

rqarun

バージョン0.4から、rqarunコマンドが追加されました。これはプラグインから自動的に呼び出されるプログラムですが、アプレットのテストに利用することもできます。

コマンドライン書式:

 rqarun [-m] アプレットのファイル名 アプレットのクラス名 ログファイル名

"-m" オプションは、「メインウィジェット」モードを指定するものです。このオプションをつけると、起動時にアプレットを表示します。また、閉じる(×)ボタンを押すと終了します。

"-m" オプションをつけないと、アプレットのウィジェットは非表示のままで待機状態になります。アプレットを表示するには、端末ウィンドウ(ターミナル)でもう一つターミナルのタブを開き、

 qcop QPE/RubyQpeAppletRunner 'redirect_click()'

を実行してください。また、閉じる(×)ボタンを押しても終了しません。ps ax で PID を調べて kill してください。

内部構造

rqa_structure.png

通常のアプレットプラグインライブラリなら、librubyqpeapplet.so のところどまりですが、Rubyスクリプトが実行時エラーで落ちてもQtopia全体が落ちないように、また、スクリプトの再読み込みがQtopia全体を再起動しなくてもできるように、fork()して子プロセスでRubyインタプリタを実行しています (バージョン0.4より)。

 qcop QPE/RubyQpeApplet 'reload()'

というQCopメッセージは、AppletProxyが受け取ります。そして、子プロセスのrqarunをいったん終了し、初期設定ファイルを読み直して、再度rqarunを起動します。

タスクバーのアイコンタップも AppletProxy? が受け取り、mousePressEvent イベントハンドラが起動します。このイベントハンドラ内では、QPE/RubyQpeAppletRunner? に対して redirect_click() というメッセージを送っています。このメッセージを rqarun の AppletRunner? が受け取り、Rubyアプレット (Qpe::Applet::Base のサブクラス) の clicked シグナルを起動します。clicked シグナルはデフォルトでは toggle_show_hide というメソッドにつながれています。

既知の問題

  • アプレットのウィンドウのサイズや位置調整はRubyコード内で行う必要があります。
  • 初期設定ファイルの編集は手作業で行う必要があります。
  • qcopメッセージを送ってリロードした後、Qtopiaが落ちることがある (はけさん、ありがとうございます)。
  • 文字列を tr() で囲んでも文字化けする。…… QString::fromUtf8() の簡略表記 qs() を用意していますので、とりあえずそれを利用してください。

ライセンス

GNU General Public License Version 2 にしたがって使用できます。

更新履歴

2006-07-15
Version 0.4公開。
Rubyインタプリタを子プロセスで実行するように変更。
2006-07-14
Version 0.3公開。
アプレットのベースクラスを Qpe::Applet::Base に変更。
初期設定ファイルにはアプレットのファイル名だけでなくクラス名も明記。
begin ...; rescue; log_error($!); end でエラーログ出力。
2006-07-09
Version 0.2公開。qcopメッセージ対応。
2006-07-09
Version 0.1公開。

参考資料

コメント

ご意見をお待ちしております。

{{comment}}

トラックバック

{{trackback}}
Last modified:2012/10/17 07:34:11
Keyword(s):
References:[RubyQpeApplet] [実験室] [FrontPage]