Qt Advent Calendar 2016 14日目の記事です。
QWidgetの階層構造を可視化するデバッグ支援ツールWidgetBrowserを作りました。
はじめに
大規模なアプリケーションの開発では、画面上に見えているウィジェットがどこで実装されているのかわからないということがしばしばあります。表示されている文字列で検索することもできますが、クラス名が分かればもっと効率よく該当ソースコードを探すことができます。
Qtでは、宣言中にQ_OBJECT
マクロを含むクラスであればクラス名を知ることができるので、例えばカーソル下にあるウィジェットのクラス名を調べるということが可能です。
そこで、ウィジェットの階層構造を辿ってクラス名を調べられるツールWidgetBrowserを開発しました。
インストール
基本的にアプリケーションに組み込んで使います。
WidgetBrowserをgit clone
してsrc/wb
ディレクトリをアプリケーション内にコピーし、ビルド対象に含めます。
起動するにはwb::WbDialog::exec()
を呼ぶだけでOKです。WbDialog
クラスが自動的にQApplication
オブジェクトから情報を集めて表示します。
#include <wb/dialog.h>
⋮
wb::WbDialog dialog;
dialog.exec();
また、イベントフィルター WbOpenListener
をQApplication
にインストールすることでショートカットキーで起動できます。
#include <QApplication>
#include <QKeySequence>
#include <wb/listener.h>
⋮
WbOpenListener listener;
listener.setKeySequenceToOpen(QKeySequence("Meta+F2"));
qApp->installEventfilter(&listener);
アプリケーションのソースコードを変更できない場合、WidgetBrowserを組み込んだQtのDLLを
ビルドして差し替えるという方法が使えます(対象がLGPL版Qtを使っていれば)。
使い方
起動すると、その時点のウィジェットの階層構造がキャプチャーされ、左側のツリーに表示されます。
トップレベルの要素は以下の5つです。
- Active Modal Widget
アクティブなモーダルウィジェット(QApplication::activeModalWidget()
の値) - Active Popup Widget
アクティブなポップアップウィジェット(QApplication::activePopupWidget()
の値) - Focus Widget
フォーカスを持つウィジェット(QApplication::focusWidget()
の値) - Widget at Cursor
カーソル下のウィジェット(QApplication::widgetAt(QCursor::pos())
の値) - Top Level Widgets
トップレベルウィジェット(QApplication::topLevelWidgets()
の値)
これらは起動した瞬間の値であり、更新されません。
ツリー上でウィジェットを選択すると右側にウィジェットのスクリーンショットが表示されます。
ツリー上ではコンテキストメニューからウィジェットのクラス名をコピーできます。
スクリーンショット上では画像を保存できます。
ダイアログを閉じるとアプリケーションに処理を返します。
作り方
ツリービューは、ウィジェットの階層構造を表すアイテムモデルを作成して使っています。
スクリーンショットは、QWidget::render
を呼ぶことで画像を取得しているため副作用があります。また、一度もshow()
されていないウィジェットは正しくない画像になることがあります。
QWidget* widget;
QLabel* label;
const QRect rectangle(QPoint(), widget->size());
QPixmap pixmap(rectangle.size());
widget->render(&pixmap, QPoint(), QRegion(rectangle));
label->setPixmap(pixmap);
クラス名をコピーする機能は以下のように実装しています。
void copyClassName(QWidget* widget) {
QApplication::clipboard()->setText(widget->metaObject()->className());
}
欲しい機能
週末にハッカソンで作ったツールなので現時点での機能は少ないです。
QtDesignerのプロパティエディタ的な機能を付けたい。
まとめ
大きなプロジェクトでは検索のキーワードとしてクラス名を知りたいことがあるのでツールを作りました(おまけでスクリーンショットも付けてみました)。