Qt/E,Qtopia用のソフトウェア開発で培ったTIPS等
qcopメッセージ送信
プログラムからのqcopメッセージの送信
- 使用するクラス
- QCopEnvelope
- 必要なヘッダ
- qpe/qcopenvelope_qws.h
QCopEnvelope クラスはデストラクタに実際のメッセージ送信の処理が
記述されているので、オブジェクトの解放時に実際のメッセージ送信の処理が行われます。
#変数のスコープから外れる時です。
ですので、狭いスコープで変数を宣言して使用した方が間違いが少なくなると思います。
ごちゃごちゃ説明書くより多分例を見てもらった方が早いと思うので…
↓のコードは必要な部分だけを記述したコードです。
(実際に動かしてないのでもしかしたら微妙に間違ってるかも?)
例)
#include <qpe/qcopenvelope_qws.h> { QCopEnvelope e("QPE/TaskBar", "showInputMethod()"); } { QCopEnvelope e("QPE/System", "execute(QString,QString)"); e << "textedit" << "/home/zaurus/Document/memo.txt"; } /* パラメータ無しならこれでもいけたかな? */ { QCopEnvelope("QPE/TaskBar", "showInputMethod()"); }
起動時の引数
メインのWidgetクラスで下記のスロットを実装。
引数の文字列が渡されてきます。
スロットのスコープはprivateで大丈夫です。
void setDocument(const QString&);
このスロットはファイルタイプをアプリケーションに関連付けした時に
ファイル名が渡されてくるスロットにもなっているので
関連付けにも対応させたい場合にはそれに対応した実装をする必要があります。
引数を渡してQtopiaアプリケーションを起動する方法には下記の方法があります。
いずれの実行方法でも上記スロットが呼ばれて引数が文字列として渡されます。
Global::execute(const QString& c, const QString& document); [staic]
AppLnk::execute(const QStringList& args);
qcop QPE/System 'execute(QString,QString)' appname argument
※AppLnk::execute()の引数はQStringListですがリストの最初の文字列しか使用されません。
execute(args); -> invoke(args); -> Global::execute(exec(), args[0]);
実装はこのような感じになっています。
また、Qtopiaアプリケーションには高速起動という仕組みもあるため、
main()関数の引数はアプリケーションの処理には使用出来ないと思った方が良いと思います。
コンソール等から起動をすれば処理する事も可能だと思いますが、
これはQtopiaアプリケーションの通常の起動方法ではないため、同じアプリケーションが
2つ起動出来てしまったりいろいろと不具合が出てくると思います。
終了時の処理
メインのWidgetクラスで下記のメソッドをオーバーライド。
void closeEvent(QCloseEvent *e);
終了を取り消したい場合は
e->ignore();
終了を受け入れる場合は
e->accept();
補足:奈々氏
これ、単純に
void hogehoge::closeEvent(QCloseEvent *e){ e->ignore(); }
とかやっちゃうと、ソフトが落とせなくなりますのでご注意を。
つかりリース前に気づけよ>自分(ぉぃ
OKキーが押された時の処理
setWState(WState_Reserved1);
しておいて下記のスロットを実装
void accept();
QDir::FilterSpec
日本語訳のマニュアルを見ててはまりました。
System - システムファイルを一覧する (Unix では何もしない)
Qt/Eのソースをハックして解決したんですけど、本家のマニュアルを見たら
ちゃんとこう書いてありました…(^^;>ソース読むより先にマニュアル読めよ>自分
System - List system files (on unix, FIFOs, sockets and device files)
GUIクラスの作成
ベースクラスがHogeBase、実装クラスがHogeとすると
1. designerでUI作ってHogeBase.uiで保存
2. 実装クラスのヘッダファイル生成
uic -subdecl Hoge HogeBase.h HogeBase.ui -o Hoge.h
3. 実装クラスのソースファイル生成
uic -subimpl Hoge Hoge.h HogeBase.ui -o Hoge.cpp
4. プロジェクトファイル生成
progen -o hoge.pro
5. メイクファイル生成
tmake -o makefile hoge.pro
6. メイク
make
Fepの状態の検出
QPE/KeyboardチャンネルにstatChanged()ってメッセージがきてるみたい。
この時に$HOME/Settings/fepmode.ja.confを読めば状態が取れそう。
fepmonappletがこの方法でFepの状態を取得しているみたい。
fepIn %d, InpMode %d, HenMode %d
int型のデータ3つかなぁ?
QDataStreamで読み込めそうな予感。
fepinterface.hで定義されてる値を使ってそうな感じなんだけどなあ〜。
何となくな感じでクラスを作ってみた。多分こんな感じだと思うんだよな〜。
fepmode.ja.confが64バイトでFModeNo_MAX=16だから多分int型のデータが16個なんだと思う。
ほとんど未使用っぽい&使い方はよく分からないけど(笑)
Fep状態監視クラス
#ifndef _FEPMONITOR_H_ #define _FEPMONITOR_H_ #include <qstring.h> #include <qfile.h> #include <qcopchannel_qws.h> #define QT_QWS_SHARP #include <sl/fepinterface.h> #include <stdlib.h> class FepMonitor : public QObject { Q_OBJECT public: FepMonitor(QObject* parent=0, const char* name=0) : QObject(parent, name){ m_fepconf = QString(getenv("HOME")) + "/Settings/" + FepConfigFileName + ".conf"; m_fepchannel = new QCopChannel("QPE/Keyboard", this); connect(m_fepchannel, SIGNAL(received(const QCString&, const QByteArray&)), this, SLOT(fepMessage(const QCString&, const QByteArray&))); loadFepMode(); } /* FModeNo is FModeNo_XXX in <sl/fepinterface.h> */ int getFepMode(int FModeNo){ if(FModeNo < FModeNo_MAX){ return m_fepmode[FModeNo]; } else { return -1; } } bool isActive(){ return getFepMode(FModeNo_KeyOnOff); } signals: void statChanged(); private: int m_fepmode[FModeNo_MAX]; QString m_fepconf; QCopChannel* m_fepchannel; void loadFepMode(){ QFile f(m_fepconf); if(f.open(IO_ReadOnly)){ f.readBlock((char*)m_fepmode, sizeof(m_fepmode)); f.close(); } } private slots: void fepMessage(const QCString& msg, const QByteArray& /*data*/){ if(msg == "statChanged()"){ loadFepMode(); emit statChanged(); } } }; #endif /* _FEPMONITOR_H_ */
FModeNo の意味
定数 | 値 | 意味 |
FModeNo_KeyOnOff | 0 | キー入力時に IM が On のとき 1 |
FModeNo_KeyInp | 1 | キー入力のモード(CIM_*/CZM_* の or をとったもの) |
FModeNo_KeyHen | 2 | 変換中は 1 -> IMStatusModeの値っぽい |
FModeNo_PadInp | 3 | 入力パッドのモード(?) 50音パッドとかかな? (CIM_*/CZM_* の or をとったもの) |
FModeNo_CRimOnOff | 4 | 手書き入力パッド が表示されているとき 1 |
FModeNo_FepOffDisable | 5 | FEP が Off にできないとき 1。50音パッドが表示されているときは1だった |
入力モード
定数 | 値 | 意味 |
CIM_None | 0x01 | ? |
CIM_Hiragana | 0x02 | ひらがな |
CIM_Katakana | 0x04 | カタカナ |
CIM_Alpanum | 0x08 | 英数 |
CZM_Hankaku | 0x40 | 半角 |
CZM_Zenkaku | 0x80 | 全角 |
IMStatusMode
定数 | 値 | 意味 |
NON_ACTIVE | 0 | IM Off |
WAIT_INPUT | 1 | 入力待ち |
INPUT_STATUS | 2 | 入力中 |
COMPOSITION_STATUS | 3 | 変換中 |
CANDIDATE_STATUS | 4 | 変換候補ウィンドウ表示中 |
ONKUN_STATUS | 5 | 音訓変換モード |
TANSYUKU_STATUS | 6 | ? |
SYNSYUKU_STATUS | 7 | 変換対象文字列変更中(Shift+左右) |
PARTINPUT_STATUS | 8 | ? |
IM_OTHER_STATUS | 100 | ? |
コメント
情報求む!
[[#rcomment]]
- 2003-12-17 (Wed) 10:22:26 yakty : Hi, Please try this. emit key(unicode, 0, 0, true, false); emit key(unicode, 0, 0, false, false); I think that it is necessary to generate the event of both Press and Release.
- 2003-12-16 (Tue) 18:54:53 david? : Hi there. I have one question. How can i using the methode of input to 2byte unicode character in Zaurus original IME(already IME ON)? emit key(1, 0xXXXX, 0, 1, 0)... this is not work. :) Thanks your advice.
- 2003-07-24 (Thu) 23:42:52 yakty : 自分でも試してみて分かったことを追記。でも色々調べても結局はFepのOn/Offくらいしか見ない気がする…(笑)
- 2003-07-24 (Thu) 22:29:31 yakty : おおーっすばらしい!ソースの使用はGPLでご自由にどうぞー。
- 2003-07-24 (Thu) 22:24:38 ひだか : ところで、fepmonitor.h としてQPOBox に含めた形で GPL で配布してもよいですか?
- 2003-07-24 (Thu) 22:06:06 ひだか : こんなかんじでしょうか(?)
- 2003-07-24 (Thu) 15:04:39 ひだか : とりあえず QPOBox は CVS HEAD で対応しました。QDataStream から Q_INT32 で読むとエンディアンが違うのか、0x0100000 が読めてしまったので、Q_INT8 で読むようにしました。とりあえず QPE/Keyboard は開きっぱなしで statChanged() を拾ってメンバ変数に状態を保存しています。FEP状態クラスを作ろうかとも思ったのですが面倒だったのでひとまずパスw
- 2003-07-24 (Thu) 09:47:49 yakty : ださださ…と言われてしまった…(^^;確かに。qcopメッセージ使ってるならfepmode.ja.confなんかに書かずに直接メッセージに乗せた方が絶対速いのに。なんでこんな実装にしたんだろう…?
QTextStream::readLine()は遅い?
下記の様な処理をするとめちゃめちゃ遅いです。
QFile f(filename); if(f.open(IO_ReadOnly)){ QTextStream stream(&f); while(!stream.atEnd()){ const QString& s = stream.readLine(); } f.close(); }
ファイル内容を一気に読み込むのでメモリは食うと思いますが
下記のような処理の方が断然早いです。
ファイルサイズがあまり大きくないファイルを処理する場合には
下記のようにした方が良いと思われます。
QFile f(filename); if(f.open(IO_ReadOnly)){ QTestStream stream(&f); const QStringList& list = QStringList::split('\n', stream.read()); f.close(); for(QStringList::ConstIterator it=list.begin(); it!=list.end(); ++it){ const QString& s = *it; } }
大きなファイルを読み込みたいときも、例えば下記のような方法が使えます。(inue)
QFile f(filename); if(f.open(IO_ReadOnly)){ QTextCodec* codec = QTextCodec::codecForName("SJIS"); char buf[1000]; while(!f.atEnd()){ int sz = f.readLine(buf,sizeof(buf)); const QString& s = codec->toUnicode(buf,sz-1); } f.close(); }
codecは用途に合ったものを設定してください。
なお、このコードでは、改行コードは\nのみ、一行が1000バイトに収まることが前提です。
実際に使うコードには、一行がそれ以上になる場合の考慮なども必要です。
でも、元が圧倒的に高速になる(10倍どころではない)ので、多少余分な処理を追加しても誤差の範囲です。
コメント
Qt/E, Qtopia開発関連で質問があればどうぞ。私の分かる範囲であればまとめます。
[[#rcomment]]
- 2004-02-28 (Sat) 08:29:16 yakty : それは初耳です…(^_^;私が作ってるのは高速起動を意識しないものがほとんどなんで…。シャープ独自の機能ですかね?だとしたらわかんないだろうけど今度ソース見てみようっと。preinstスクリプトとかでqcopコマンド使っちゃうと、root権限でqcopコマンドが動いちゃうからイマイチですしねぇ。高速起動なんだからCanFastload見てくれればいいのに…。
- 2004-02-28 (Sat) 00:44:05 inue : (も)さんのところでの高速起動の話題で思い出したのですが、高速起動設定されているアプリのアンインストール時に、インストーラがアプリに'quitIfInvisible()'メッセージを送る条件ってご存知でしょうか? たとえばZEditorやFreeNoteQtをアンインストールするとそれが送られていて、きれいに入れ替わるのですが、ほかの多くのアプリは(私のも含め(^^;)、インストーラが出してくれないので、そのまま旧バージョンが常駐し続けるんですよね。見た目、違うのはdesktopファイルにmimetypeが設定されているかどうか、くらいなのですが。
- 2003-11-24 (Mon) 16:00:32 inue : jojo3さんがfgetsを直接使うパターンも含めてA300とC760でテストした結果を、私のBBSの方に書き込みいただいたのですが、なんとA300ではQTextStream::readLine()とQTextStream::read()で、2倍ちょっとしか開きがないそうです。Cシリーズ(多分B500も?)固有の問題なのかも。
- 2003-11-21 (Fri) 00:33:08 inue : 見てみると、さすがに、Qtopiaのライブラリではほとんど使ってないんですね(^^;。configとかはread()してsplit()のパターンですし。わかってるなら直しておいてくれればいいのにという感じですが(^^;。
- 2003-11-20 (Thu) 22:28:57 yakty : どうもありがとうございます〜。50KB程度のファイルの読み込みでも数秒違うんですよね…(^_^; 絶対使っちゃダメですね(苦笑) はてな消してQTextStream::readLine()は遅い!にしようかな…(笑)
- 2003-11-20 (Thu) 21:08:23 inue : とりあえず、追加してみました。例のような長さ決めうちパターンだと、10倍どころか30倍くらい違います(^^;.
- 2003-11-20 (Thu) 09:11:54 yakty : なんであんなに遅いんでしょうね…?(^^;ところでひとつお願いがあるんですが、QFile::readLine()してQTextCodec::toUnicode()するパターンのコードを追記しておいてもらえませんか?こうだろうなぁってのは分かるんですが、私は実際に確認していないので…(^^;
- 2003-11-20 (Thu) 00:47:18 inue : コード変換するから遅いのかと思ってたんですが、全然違ってたんですね(^^;。これほどの差があるとは、Qt/E開発で必須のTIPSと言えるかも。
- 2003-11-19 (Wed) 22:41:06 yakty : でしょ?でしょ?!私も最初かなり驚きました(笑) だって全然違うんですもん。 QFile::readLine()でも早いってのも書いておいた方が良かったですね。(QTextCodec::toUnicode()までやって検証しなかったので書いてませんでしたが、QFile::readLine()が圧倒的に早いのは知っていたので…) あとはQTextCodec::codecForName()なんかも結構遅い関数だったりします。他にもあったかなぁ…?
- 2003-11-19 (Wed) 21:43:59 inue : ぐわーん。↑を見たときに、「でも扱うファイルサイズが巨大だから仕方ないか」と思ってそのままにしていたのですが、今日試しに、「QFile::readLine()してQTextCodec::toUnicode()でQString化、のループ」をやってみたら、5〜10倍は速くなりました。まさかそこまで違うとは…。書き直したら、今までは何だったんだとかえって怒られそう(^^;。
- 2003-10-22 (Wed) 08:19:09 masaya : 修正版が届きまして、直ってました。ただし、他からメッセージが届くと消えますね。ソースが来ていないのでどうしたかは不明なんですが。
- 2003-10-22 (Wed) 08:15:55 masaya : そうかも?始めの頃のソースに私がいろいろ案をだしてぐちゃぐちゃになったみたいで・・・。私のコードがきたないってのもありそうですが(~_~;)。本人も気づいたようで作り直しています。
- 2003-10-21 (Tue) 18:34:11 yakty : っていうかソース読んでて思ったんですけど、プログラムのつくりはお世辞にも良いとは言えないですね、Qazoo…(^_^;;;
- 2003-10-21 (Tue) 18:32:17 yakty : 問題はもっと単純でした。一応修正案を考えてみました。
- 2003-10-20 (Mon) 22:14:20 yakty : 今簡単なサンプルを書いて試してみたんですが、QTextBrowserにデータを入れる際に日本語入力がキャンセルされるわけでは無いみたいです。推測ですがsignal/slotを使っていないのが原因かも?暇なときにちょっとソースをいじってみます。
- 2003-10-20 (Mon) 07:08:41 masaya : Y!MのQazooで日本語入力中(確定前)の状態でメッセージが届くと入力した文字が消えてしまいます。メモリエリアが共通な為かと考えていますが、対策は無いですかね? IMStatusModeで2・3の時にメッセージを受け取らないようにすればいいのかな? 何かいい案があったら教えていただけませんか。
- 2003-04-19 (Sat) 03:19:27 奈々氏? : お疲れ様です。eedit(eediter)、だいぶ機能向上しました。おかげさまで関連付けとかもOKっす。今週末こそなんとかマスコットに手を入れられるかな?と思うので、何か有ったらよろしくお願いしますです。
- 2003-04-06 (Sun) 23:50:40 yakty : 私の分かる範囲であればなんでもどうぞ。KeyHelperAppletの開発でQt/E,Qtopiaのソースは大分ハックしたんでいろいろ知ってるかも?
- 2003-04-06 (Sun) 23:46:50 奈々氏? : あ、もうひとつ。アプレット製作時ので、再起動かからないようにするやり方とかKeyHelperApplet の処理読んでわからないとき、教えてもらっていいですか?エディタも片付きかけてるのでそろそろマスコットも何とかしたいし。
- 2003-04-06 (Sun) 23:41:36 奈々氏? : う・・・・、やりたくて調べてたことがかなり書いてありまつ(汗 終了のは知ってた(というかYeditのソース読んだ)のですが、なんか一生懸命調べたのがいかに効率悪かったかがわかってちょっとへこみました(汗 でも、ありがとうございます。