PerlQt移植ヒストリ(第9回)
PerlQt/Embeddedを2.105-p0.04に更新した。
ダウンロード
Perlライブラリ:lib-perl-qte_2.105-p0.04_arm.ipk
ソースファイル:perlqt-2.105-p0.04-src.tar.gz
更新内容
- 以下のソースコードにおいて、QStringをPerlの文字列に変換/逆変換する場合はUTF-8を使用するようにすることで、Qt::MultiLineEdit(複数行エディットクラス)やQt::Labelなどの日本語対応を行った(詳細は後述)。
- C++では定義されていない(メソッドではなく)仮想関数のinsertCharをQt::MultiLineEditから削除した。
- 引き数の型をcharからintに変更することで、Qt::MultiLineEditのinsertCharメソッドの日本語対応を行った。引き数の文字コードは2バイトのUNICODE(UTF-16)である。
- ASCII文字列として受け取っていたPerlの文字列を、QStringで受け取るようにすることで、後述の関数の日本語対応を行った。
詳細説明
Qt::MultiLineEditの日本語対応
Qt::MultiLineEditに対して日本語を入力をしたときの内部処理を以下に説明する(と言っても、自分用のメモだが)。
なお、「A ⇒ B」は「Aクラスの親のBクラス」を意味する。
また、C++のクラス、メソッドに相当するものをPerl上ではパッケージ、サブルーチンと表現する。
- keyPressEventの呼び出し
- QMultiLineEditクラスを継承したpig_enhanced_QMultiLineEditクラスのkeyPressEventメソッドがQtから呼び出される。入力された日本語は、メソッドの引き数であるQKeyEventオブジェクトにより伝搬される。
- pig_enhanced_QMultiLineEdit ⇒ pig_virtual_QMultiLineEdit ⇒ pig_virtual_QTableView ⇒ pig_virtual_QFrame ⇒ pig_virtual_QWidgetクラスのpig_virtual_keyPressEventメソッドを呼び出す。
- pig_import_Qt.hで定義されているインポートテーブル(各パッケージのC++による実装で定義されたエクスポートテーブルで初期化、詳細は後日)により間接的にpig_virtual_QWidget__keyPressEvent関数を呼び出す。
- Qt::MultiLineEditパッケージ(または、それを継承したパッケージ)のkeyPressEventサブルーチンを呼び出す。PerlQtでは同様の方法により全ての仮想関数をPerl上で実現している。
- keyPressEventサブルーチンが上書きされていなければ、そのサブルーチンにマッピングされているPIG_QMultiLineEdit_keyPressEvent関数が呼び出される。
- QMultiLineEditクラスのprotectedメソッドを外部から呼び出すために、継承して中継関数を定義したpig_alias_QMultiLineEditクラスのpig_alias_keyPressEventメソッドを呼び出す。
- QMultiLineEditクラスのkeyPressEventを呼び出す。パッケージの継承とサブルーチンの仮想化を実現するためなのだが、C++では(継承されていなければ)ここがスタート地点なので、Perl上では随分と複雑な処理を経ていると言える。
- ここまでは、QKeyEventオブジェクトによって入力された日本語が正しく伝搬されている。問題点は次の処理にある。入力された日本語は、QKeyEventクラスのtextメソッドにより、UTF-16のQStringオブジェクトとして得ることができる。
- insertの呼び出し
- QMultiLineEditクラスを継承したpig_enhanced_QMultiLineEditクラスのinsertメソッドが呼び出される。入力された日本語は、メソッドの引き数であるUTF-16のQStringオブジェクトにより伝搬される。
- pig_enhanced_QMultiLineEdit ⇒ pig_virtual_QMultiLineEditクラスのpig_virtual_insertメソッドを呼び出す。
- 前述のインポートテーブルにより間接的にpig_virtual_QMultiLineEdit__insert関数を呼び出す。
- Qt::MultiLineEditパッケージ(または、それを継承したパッケージ)のinsertサブルーチンを呼び出す。そのサブルーチンに渡すために、QStringオブジェクトで渡された日本語をPerlの文字列に変換する。しかし、変換元をQStringクラスのdataメソッド(結果的にlatin1メソッド)から得ているため、日本語は破棄されてしまうことが問題だった。この問題を解決するために、utf8メソッドでUTF-8に変換したQStringオブジェクトからPerlの文字列を作成するように修正した。
- insertサブルーチンが上書きされていなければ、そのサブルーチンにマッピングされているPIG_QMultiLineEdit_insert関数が呼び出される。
- QMultiLineEditクラスのinsertを呼び出す。
- insertAtの呼び出し
- QMultiLineEditクラスを継承したpig_enhanced_QMultiLineEditクラスのinsertAtメソッドが呼び出される。以降は前述の「insertの呼び出し」と同様なので、「insert」を「insertAt」に読み替えて欲しい。
日本語をQStringで受け取るようにした関数
ソース | 関数 |
---|---|
pig_QBitmap.c | PIG_QBitmap_new |
pig_QLabel.c | PIG_QLabel_setText |
PIG_QLabel_text | |
pig_virtual_QLabel__setText | |
pig_enhanced_QLabel::setText | |
pig_QLabel_v.h | pig_virtual_QLabel::pig_virtual_setText |
pig_QLineEdit.c | PIG_QLineEdit_validateAndSet |
pig_QListView.c | PIG_QListView_columnText |
pig_QPainter.c | PIG_QPainter_boundingRect |
pig_QPicture.c | PIG_QPicture_load |
PIG_QPicture_save | |
pig_QSpinBox.c | PIG_QSpinBox_valueChange |
pig_QTab.c | PIG_QTab_setLabel |
pig_QToolButton.c | PIG_QToolButton_setTextLabel |
pig_virtual_QToolButton__setTextLabel | |
pig_enhanced_QToolButton::setTextLabel | |
pig_QToolButton_v.h | pig_virtual_QToolButton::pig_virtual_setTextLabel |
pig_QToolTipGroup.c | PIG_QToolTipGroup_showTip |
pig_QWidget.c | PIG_QWidget_caption |
PIG_QWidget_drawText | |
PIG_QWidget_iconText |