新型コロナの影響でいろいろと大変な一年だったかと思いますが、皆様おかわりないでしょうか。
@task_jp さんの初日のエントリーに気が付くまですっかり忘れていましたが、今年もアドベントカレンダーの季節がやってまいりました。
昨日は、Q_GADGET を活用したデータモデルの実装について ということで、QObjectを支えるメタオブジェクトを軽量に扱えるようにするための仕組みについて解説されています。
本日は、突発的に記事を書くことにしたので、色々悩んで、QCoreApplicationとその継承クラスについて触れてみようかと思います。突発的にざっくり調べて書きつけるので、誤りが含まれる可能性が多分にあります。特にイベント周りは色々複雑なので、後日別記事にまとめつつ、こちらの記事も修正する予定です。
QCoreApplication系クラスとは何か
Qtのドキュメントでは、UIのないアプリケーションにイベントループを提供するクラスと簡潔に説明されています。Qtを利用される多くの方は、GUIで利用されているでしょうから、古くからのWidgetを使われる方はQApplication、最近のQMLを利用される方はQGuiApplicationの方が見慣れていらっしゃるかと思います。
Qtを使い始めると、とりあえずおまじないのように書くようになってしまうこのクラスは、Qtアプリケーションの初期化・終了処理とアプリケーション全体に対する設定、OS側からのイベントも含め処理するメインイベントループの生成を担っています。
QCoreApplication
GUIアプリケーションを主に開発される方には耳慣れないかもしれませんが、QApplicationやQGuiApplicationの親クラスで、GUIを伴わないCUI向けのアプリケーション用の初期化・イベントループ生成クラスになります。QCoreApplicationが提供する機能は以下の通りです。
アプリケーション引数の保持
QCoreApplication(int &argc, char **argv);
static QStringList arguments();
UNIX系ではコンストラクタに渡された引数を、Windows系ではargc,argvを改変されていなければ、GetCommandLine() APIで取得したアプリケーション実行時引数をQStringListとして保持しており、arguments()関数で取得できます。
arguments().at(0)はプログラム名が、引数があれば、それ以降に引数が保持されています。
なお、あくまでシンプルなリストが作られるだけですので、複雑なオプションのパースやヘルプの生成をしたいのであれば、QCommandLineParser クラスを使う必要があります。
アプリケーションパスの取得
static QString applicationDirPath();
static QString applicationFilePath();
実行ファイル名までhあ含まないディレクトリパスと、実行ファイル名までを含むファイルパスを取得できます。なお、Linuxではパスの取得に/procを参照し、失敗した場合は、argv[0]とアプリケーションのカレントディレクトリから生成するので、カレントディレクトリを変えた場合など、正確な値が取れないケースがあるようです。
ライブラリパスの取得・操作
static QStringList libraryPaths();
static void setLibraryPaths(const QStringList &paths);
static void addLibraryPath(const QString &path);
static void removeLibraryPath(const QString &path);
QLibraryを使ったライブラリ読み込みに利用されるパスを取得、設定、追加、削除を行います。
アプリケーション情報の設定・取得
static QString applicationName();
static QString applicationVersion();
static QString organizationDomain();
static QString organizationName();
static void setApplicationName(const QString &application);
static void setApplicationVersion(const QString &version);
static void setOrganizationDomain(const QString &orgDomain);
static void setOrganizationName(const QString &orgName);
QSettingsやQCommandLineParserなどで使われるアプリケーション情報の取得・設定
- アプリケーション名(未設定時は実行ファイル名)
-
バージョン(未設定時は以下の通り)
アーキテクチャ 値 Windows(classic) VERSIONINFOリソースのPRODUCTVERSIONパラメーター Windows(Universal) アプリケーションパッケージマニフェストのバージョン属性 macOS、iOS、tvOS、watchOS CFBundleVersionプロパティ Android AndroidManifest.xmlのandroid:versionNameプロパティ 組織ドメイン
組織名
なお、この値が実行中に変更された際に通知するためのシグナルが提供されています。
void applicationNameChanged();
void applicationVersionChanged();
void organizationDomainChanged();
void organizationNameChanged();
アプリケーション全体の機能制御
static void setAttribute(Qt::ApplicationAttribute attribute, bool on = true);
static bool testAttribute(Qt::ApplicationAttribute attribute);
アプリケーションの挙動を制御します。ざっくりと一覧しておきますので、詳細はドキュメントを確認してください。QGuiApplicationのインスタンスが生成される前に指定しなくてはならない属性や、デフォルトでONのものもあります。
ApplicationAttribute | on=trueの場合 |
---|---|
Qt::AA_DontShowIconsInMenus | メニューへのアイコン表示を抑止する |
Qt::AA_DontShowShortcutsInContextMenus | コンテキストメニュー上のショートカットの表示を抑止する |
Qt::AA_NativeWindows | ネイティブウィンドウを使用する |
Qt::AA_DontCreateNativeWidgetSiblings | ネイティブウィンドウの兄弟を非ネイティブのままとする |
Qt::AA_PluginApplication | プラグインの作成に使用されることを指定し、不要な初期化を抑制する |
Qt::AA_DontUseNativeMenuBar | ネイティブメニューバーを使用しない(macOSの上部のメニューバー等) |
Qt::AA_MacDontSwapCtrlAndMeta | [macOS] commandキーとctrlキーの入れ替えを抑止する |
Qt::AA_Use96Dpi | OS指定の解像度ではなく、画面の解像度を96DPIであると想定する |
Qt::AA_SynthesizeTouchForUnhandledMouseEvents | アプリケーションで受け入れられないすべてのマウスイベンをタッチイベントに変換する |
Qt::AA_SynthesizeMouseForUnhandledTouchEvents | アプリケーションで受け入れられないすべてのタッチイベントを左ボタンのマウスイベントに変換する |
Qt::AA_UseHighDpiPixmaps | QIconで、高DPIのピックスマップを生成する |
Qt::AA_ForceRasterWidgets | トップレベルのウィジェットが純粋なラスターサーフェスを使用するようにし、非ネイティブのGLベースの子ウィジェットをサポートしない |
Qt::AA_UseDesktopOpenGL | OpenGL実装の動的ロードを使用するプラットフォームでデスクトップOpenGLを強制する |
Qt::AA_UseOpenGLES | OpenGL実装の動的ロードを使用するプラットフォームでOpenGLES2.0以降の使用を強制する |
Qt::AA_UseSoftwareOpenGLQt | OpenGL実装の動的ロードを使用するプラットフォームでソフトウェアベースのOpenGL実装の使用を強制する |
Qt::AA_ShareOpenGLContexts | QOpenGLWidgetやQQuickWidgetなどのクラスで使用されるOpenGLコンテキスト間のリソース共有を有効にし、テクスチャ等のリソース共有をする |
Qt::AA_SetPalette | QGuiApplicationでパレットが明示的に設定されているかどうか(test用?) |
Qt::AA_EnableHighDpiScaling | サポートされているプラットフォームでQtの高DPIスケーリングを有効にする |
Qt::AA_DisableHighDpiScaling | Qtで高DPIスケーリングを無効にする |
Qt::AA_UseStyleSheetPropagationInWidgetStyles | Widgetのスタイルに対するスタイルシートを継承する |
Qt::AA_DontUseNativeDialogs | ネイティブダイアログを使用しない |
Qt::AA_SynthesizeMouseForUnhandledTabletEvents | アプリケーションで受け入れられないすべてのタブレットイベントをマウスイベントに変換する |
Qt::AA_CompressHighFrequencyEvents | 特定の頻繁なイベントの圧縮を有効にする |
Qt::AA_CompressTabletEvents | タブレットデバイスからの入力イベントの圧縮を有効にする |
Qt::AA_DontCheckOpenGLContextThreadAffinity | QOpenGLContext::makeCurrentで生成する際、QObjectのスレッド親和性チェックをしない |
Qt::AA_DisableShaderDiskCache | シェーダーのディスクキャッシュを無効にする |
Qt::AA_DisableWindowContextHelpButton | Qt::SheetおよびQt::Dialogで、WindowContextHelpButtonHintを無効にする |
Qt::AA_DisableNativeVirtualKeyboard | [Windows] ネイティブの仮想キーボードを無効にする |
国際化対応
static bool installTranslator(QTranslator *translationFile);
static bool removeTranslator(QTranslator *translationFile);
static QString translate(const char *context, const char *sourceText, const char *disambiguation = nullptr, int n = -1)
翻訳ファイルのインストール・削除を行います。このあたりの使い方は、3年前のアドベントカレンダーで、@task_jp 会長が記事にしてくださっていますので、そちらをご確認ください。
translateは、インストールされている翻訳ファイルをクエリして、sourceTextの翻訳テキストを返します。
イベントループの開始と終了
static int exec();
QT_SIGNAL aboutToQuit();
メインイベントループを開始し、exitが呼び出されるまでイベント待機・処理します。終了時の返却値は、exitで指定されたreturnCodeになりますが、プラットフォームによってはexec()から返らずにそのままアプリケーションが終了されるケースがあるので注意が必要です。
イベントループから抜ける際には、aboutToQuit()シグナルを発行します。aboutToQuit()によりアプリケーションの最後に簡単な処理を実施できます。なお、イベントループは終了しようとしているので、ユーザーとの対話などはできないことに注意が必要です。
static void exit(int returnCode = 0);
Q_SIGNAL void quit();
exitは、メインイベントループをreturnCodeで終了するよう指示します。メインイベントループが実行されていない場合は何もしません。
quit()スロットは、exit(0)します。イベントループが実行される前のexitは何もしないため、exitの直接呼出しより、quitスロットへQueuedConnectionしたシグナルを発行する方が安全です。
static bool isQuitLockEnabled();
static void setQuitLockEnabled(bool enabled);
また、Qtには、イベントループが不要になった際終了させるためのQEventLoopLockerクラスがありますが、メインイベントループもquitlockするか否かの制御が用意されています。デフォルトでは有効になっています。
イベントディスパッチャー
static QAbstractEventDispatcher *eventDispatcher();
static void setEventDispatcher(QAbstractEventDispatcher *eventDispatcher);
Event Dispatcherは、ウィンドウシステムおよびその他のソースからイベントを受信・処理、QCoreApplicationに配信します。
通常プラットフォームごとに適切なディスパッチャーが用意されていますが、QCoreApplicationのインスタンス生成前であれば、独自のディスパッチャーを設定することも可能です。
ネイティブイベントフィルタ
void installNativeEventFilter(QAbstractNativeEventFilter * filterObj);
void removeNativeEventFilter(QAbstractNativeEventFilter * filterObject);
OS等のプラットフォーム側のイベントをフィルタするネイティブイベントフィルタのインストール・削除ができます。
プラットフォーム依存となるため移植性に注意が必要ですが、QPAプラットフォームプラグイン(Windowsの場合はディスパッチャー)レベルでネイティブのイベントをフィルタできます。
イベント通知処理関数
virtual bool notify(QObject *receiver, QEvent *event);
イベントループでイベント配信時に呼び出される関数で、オーバーライドすると任意のスレッドのレシーバーに送信される任意のイベントの通知処理を置き換え可能になります。
イベント操作
static void processEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents);
static void processEvents(QEventLoop::ProcessEventsFlags flags, int ms);
保留中イベントの処理。ms指定された時間か、すべてのイベントが処理できるまで、呼び出し元のスレッドのイベントを処理します。
bool sendEvent(QObject *receiver, QEvent *event);
receiver当てのeventをnotify関数を経由して即時送信します。eventのインスタンスは削除しません。
static void postEvent(QObject *receiver, QEvent *event, int priority = Qt::NormalEventPriority);
static void removePostedEvents(QObject *receiver, int eventType = 0);
static void sendPostedEvents(QObject *receiver = nullptr, int event_type = 0);
receiver当てのeventを配信用のキューに入れ保留します。このキューは、メインイベントループの処理によりnotify経由で対象に送信した後、eventのインスタンスを破棄(delete)します。また、remove/sendは、receiver向けのキューにあるイベントを削除、即時送信します。
setuid対策(セキュリティ)
static bool isSetuidAllowed();
static void setSetuidAllowed(bool allow);
Qt 5.3以降、デフォルトはsetuidを禁止してUIDとRUIDが異なる状態ではアプリケーションの起動を失敗するようになっています。歴史的な経緯でsetuidしなくてはならないアプリケーションでは、明示的に許可する必要があります。
その他
static QCoreApplication *instance();
インスタンスの取得
static qint64 applicationPid()
プロセスIDの取得
static bool startingUp()
static bool closingDown()
アプリケーションが起動処理中(application object生成前)か、終了処理中か(application objectのdestroyが開始しているか)の問い合わせ。
QGuiApplication
QGuiApplicationは、QCoreApplicationを継承したGUI向けのクラスで、Qt Widgetを使わないもの向けの初期化・イベントループ生成クラスになります。
イベントループ生成のexec()関数はオーバーライドされています。その他、QCoreApplicationの機能に加え、GUI向けに以下の機能が追加されています。
プロパティの取得、設定
static QString applicationDisplayName();
static setApplicationDisplayName(const QString& displayName);
Q_SIGNAL void applicationDisplayNameChanged();
ユーザーに表示される名前の取得、設定ができます。ウィンドウタイトルなのでユーザーに表示されます。
設定されていない場合は、applicationNameが利用されます。シグナルは変更通知となるます。
static QString desktopFileName();
static void setDesktopFileName(const QString& name);
freedesktopのデスクトップエントリのベース名の取得、設定ができます。
static Qt::LayoutDirection layoutDirection();
static void setLayoutDirection(Qt::LayoutDirection direction);
static bool isLeftToRight();
static bool isRightToLeft();
Q_SIGNAL void layoutDirectionChanged(Qt::LayoutDirection direction);
ウィジェットのレイアウト方向を設定、取得します。
static QString platformName();
基盤となるプラットフォームプラグインの名前の取得
static QScreen * primaryScreen()
Q_SIGNAL void primaryScreenChanged(QScreen *screen);
アプリケーションのプライマリ(またはデフォルト)画面の取得,変更通知
static bool quitOnLastWindowClosed();
static void setQuitOnLastWindowClosed(bool quit);
Q_SIGNAL void lastWindowClosed();
最終ウィンドウを閉じた際にQuitするかのフラグを取得、設定。
最後とウィンドウを閉じた際は、lastWindowClosed()シグナルを発行する。
static QIcon windowIcon();
static void setWindowIcon(const QIcon &icon);
ウィンドウアイコンの取得、設定
スタイルの取得、アプリケーションデフォルトフォント・パレットの取得設定
static QStyleHints * styleHints();
static QFont font();
static QPalette palette();
static void setFont(const QFont& font);
static void setPalette(const QPalette& pal);
Q_SIGNAL fontChanged(const QFont &font);
Q_SIGNAL fontDatabaseChanged();
Q_SIGNAL paletteChanged(const QPalette &palette);
オーバーライドカーソルの取得、設定、変更、リセット
static QCursor * overrideCursor();
static void setOverrideCursor(const QCursor &cursor);
static void changeOverrideCursor(const QCursor &cursor);
static void restoreOverrideCursor();
アプリケーションオーバーライドカーソルは、たとえば、操作中に時間がかかる場合のような、アプリケーションが特別な状態にあることをユーザーに示すことを目的としています。
高DPIスケールファクター丸めポリシーの取得、設定
static Qt::HighDpiScaleFactorRoundingPolicy highDpiScaleFactorRoundingPolicy();
static void setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy policy);
フォールバックセッション管理の有効・無効の確認、設定、セッション情報の取得
static bool isFallbackSessionManagementEnabled();
static void setFallbackSessionManagementEnabled(bool enabled);
Q_SIGNAL void saveStateRequest(QSessionManager &manager);
bool isSavingSession() const;
bool isSessionRestored() const;
QString sessionId() const;
QString sessionKey() const;
セッションマネージャがユーザーとの対話を許可している場合に、セッションマネージャーが特定の条件に応じてトップレベルウィンドウを閉じることを防ぎ、セッション管理を明示的に実装するために何もしない機能を有効とするかどうかを確認、設定する。
システム標準色、フォントを使用するかの設定、確認
static bool desktopSettingsAware();
static void setDesktopSettingsAware(bool on);
Window Systemとの同期
static void sync();
アプリケーション状態の取得
static Qt::ApplicationState applicationState();
Q_SIGNAL void applicationStateChanged(Qt::ApplicationState state);
アプリケーションの現在の状態,変更通知シグナル
ApplicationState | 概要 |
---|---|
Qt::ApplicationSuspended | 一時停止状態 |
Qt::ApplicationHidden | 非表示、バックグラウンド実行 |
Qt::ApplicationInactive | 非前面に表示中 |
Qt::ApplicationActive | 前面に表示中 |
ウィンドウの取得
static QWindowList allWindows();
static QWindowList topLevelWindows();
static QWindow * focusWindow();
static QWindow * modalWindow();
static QWindow * topLevelAt(const QPoint &pos);
スクリーンの取得
static QScreen * screenAt(const QPoint &point);
static QList<QScreen *> screens();
Q_SIGNAL void screenAdded(QScreen * screen);
Q_SIGNAL void screenRemoved(QScreen * screen);
マウス、キーボード修飾キーの取得
static Qt::MouseButtons mouseButtons();
static Qt::KeyboardModifiers keyboardModifiers();
static Qt::KeyboardModifiers queryKeyboardModifiers();
なお、keyboardModifiers()がイベントに応じて更新された値を返すのに対し、queryKeyboardModifiers()は呼び出し時に入力デバイスに保持されている実際のキーを返します。
platform plugin関数ポインタの取得
static QFunctionPointer platformFunction(const QByteArray &function);
その他、アプリケーション情報、機能へのアクセス
qreal devicePixelRatio()const;
static QClipboard * clipboard();
static QObject * focusObject();
static QInputMethod * inputMethod();
static QPlatformNativeInterface * platformNativeInterface();
QApplication
QApplicationは、QGuiApplicationを継承したGUI向けのクラスで、Qt Widgetを使うアプリケーション向けの初期化・イベントループ生成クラスになります。QGuiApplicationに類似したAPIのQWidget版が追加されています。
プロパティの取得、設定
Q_SLOT bool autoSipEnabled() const;
Q_SLOT void setAutoSipEnabled(const bool enabled);
自動SIP(ソフトウェア入力パネル)の可視性を設定、取得
static int cursorFlashTime();
static void setCursorFlashTime(int);
テキストカーソル点滅時間(ミリ秒単位)の取得、設定
static int doubleClickInterval();
static void setDoubleClickInterval(int);
ダブルクリックと2回の連続したマウスクリックを区別する時間制限(ミリ秒)の取得、設定
static int keyboardInputInterval();
static void setKeyboardInputInterval(int);
キーの押下と2つの連続したキーの押下を区別する制限時間(ミリ秒単位)の取得、設定
static int startDragDistance();
static void setStartDragDistance(int l);
ユーザーがボタンを押したままカーソルを移動した際、ドラッグと判断される移動距離。defaultは10ピクセル
static int startDragTime();
static void setStartDragTime(int ms);
ドラッグアンドドロップ操作を開始する前にマウスボタンを押し続ける必要がある時間(ミリ秒単位)の取得、設定
static int wheelScrollLines();
static void setWheelScrollLines(int);
マウスホイールが回転したときにウィジェットをスクロールするための行数の取得、設定
QString styleSheet() const;
Q_SLOT void setStyleSheet(const QString &sheet);
アプリケーションスタイルシートの取得、設定
スタイルの取得、設定アプリケーションデフォルトフォント・パレットの取得設定
static QStyle * style();
static void setStyle(QStyle *style);
static QStyle * setStyle(const QString &style);
static QFont font(const QWidget *widget);
static QFont font(const char *className);
static QFontMetrics fontMetrics();
static void setFont(const QFont &font, const char *className = nullptr);
static QPalette palette(const QWidget *widget);
static QPalette palette(const char *className);
static void setPalette(const QPalette &palette, const char *className = nullptr);
条件に合うウィジェットの取得、設定、変更通知、操作
static void setActiveWindow(QWidget *active);
static QWidget * activeModalWidget();
static QWidget * activePopupWidget();
static QWidget * activeWindow();
static QWidgetList allWidgets();
static QWidget * focusWidget();
static QWidget * topLevelAt(const QPoint &point);
static QWidget * topLevelAt(int x, int y)
static QWidgetList topLevelWidgets();
static QWidget * widgetAt(const QPoint &point);
static QWidget * widgetAt(int x, int y);
Q_SIGNAL focusChanged(QWidget * old、QWidget * now);
Q_SLOT closeAllWindows();
Q_SLOT aboutQt();
aboutQt()は、アプリケーションで使用されているQtのバージョン番号が含まれるダイアログを表示する。
その他の機能
static Qt::NavigationMode navigationMode();
static void setNavigationMode(Qt::NavigationMode mode);
フォーカスナビゲーション種類の取得、設定
static bool isEffectEnabled(Qt::UIEffect effect);
static void setEffectEnabled(Qt::UIEffect effect, bool enable = true);
UIエフェクト効果の有効・無効の検査、設定
static void alert(QWidget *widget, int msec = 0);
ウィジェットに対する警告ウィンドウ表示
static void beep();
Beep音を鳴らす
QCoreApplicationに関わるマクロ
qApp
qobject_cast QCoreApplication::instance() 相当
qGuiApp
qobject_cast QCoreApplication::instance() 相当
Q_COREAPP_STARTUP_FUNCTION(QtStartUpFunction ptr)
QCoreApplicationのコンストラクタ最後に呼び出される関数ポインタの設定
関連非メンバ関数
void qAddPostRoutine(QtCleanUpFunction ptr)
void qRemovePostRoutine(QtCleanUpFunction ptr)
QCoreApplicationのデストラクタからコールされる関数ポインタの追加、削除
QCoreApplication系のちょっとしたTips
TBD
まとめ
なんとなくQCoreApplication一族の機能と役割を見直すことができたでしょうか。割とおまじないチックに呼んだあと、あまり使う機会のないクラスではありますが、意外といろいろなAPIが実装されていることがわかるかと思います。ふっと何かでこれどうすれば情報取れるのだっけとか、どこで設定するのだっけみたいなものもあるので、一度ドキュメントを流し読みしておくのも良いものですよ。
ちょっと時間が無くてTBDな項目やTODOのまま残している個所がありますが、0時前までには登録したいので、とりあえず本日はここまでで登録させていただきます。ごめんなさい。
例年のように、相も変わらず適当な書きなぐり記事でしたが、何か少しでも皆さんのお役に立てれば幸いです。
明日3日目は、まだ誰も登録者がいません。今年はコロナの影響で勉強会も中止したままだいぶ時間が過ぎてしまいましたから、気が付いていない方もいらっしゃるのかもしれませんね。何か軽くかけることを思いついた方は、ぜひご登録ください。