Qt5再入門: タブを動的に追加する
これまでに、ダイアログを除いて、ウィジェットペインの左側に「ブックマーク」、下側に「ログコンソール」を装備してきました。
右上がぽっかり空いていますが、ここはメインコンテンツの表示領域としていきます。複数のコンテンツ(ページ)を、タブによって切り替えていきます。
今回は、このタブの一つとして、ディレクトリ情報を表示してみたいと思います。Qt DesignerでMainWindowのUIファイルを開きます。
また、アクションエディタで次のようなアクションを追加しておきます。
編集内容を保存し、Qt Designerを閉じてQt Creator上のソースコードに戻り、MainWindowのコンストラクタに次のように追記します。
// ブックマーク追加アクションをビューに追加
ui_->bookmarksView->addAction(ui_->actionAppend_Bookmark);
// ブックマーク削除アクションをビューに追加
ui_->bookmarksView->addAction(ui_->actionRemove_a_bookmark);
// パスオープンアクションをビューに追加
ui_->bookmarksView->addAction(ui_->actionOpen_Path); // 追記!
// コンテキストメニューポリシーを設定(Qt Designerでも設定可)
ui_->bookmarksView->setContextMenuPolicy(Qt::ActionsContextMenu);
これにより、Open Pathアクションがブックマーク上で開くコンテキストメニューに表示されるようになります(翻訳済み)。
次に、同じコンストラクタ内で後述するOpen Pathアクションをスロットに接続します。
// パスオープンアクション時、パスオープンメソッド実行
connect(
ui_->actionOpen_Path, &QAction::triggered,
this, &MainWindow::openPath
);
次に、このスロットメソッドを作成します。
// MainWindowクラスのpublic slots内で定義
void MainWindow::openPath() {
// 現在ブックマークビューが指している場所を取得
auto index = ui_->bookmarksView->currentIndex();
// 現在の行からブックマークを取得
auto bookmark = pModel_->bookmark(index.row());
// すでに開いていないか確認
auto pageOpt = findFilePage(bookmark);
// まだ開いていなければ
if (!pageOpt) {
// ファイル用ページを作成
auto page = new FilePage(
toLmbcsQ(bookmark.path()),
toLmbcsQ(bookmark.server()),
this);
// シグナル/スロットを接続
connect(page, &BasicTabPage::consoleLog,
this, &MainWindow::consoleLog
);
connect(page, &BasicTabPage::showStatus,
ui_->statusbar, &QStatusBar::showMessage
);
// ページをタブとして追加
ui_->tabWidget->addTab(page, bookmark.pageName());
// 作成したページのタブに移動
ui_->tabWidget->setCurrentWidget(page);
// ページのコンテンツを書き込む
page->write();
}
// すでに開いていれば
else {
// そのページに移動する
ui_->tabWidget->setCurrentWidget(pageOpt.value());
}
}
まず、アクションが発行された時点で選択されている場所を特定し、ブックマークを取得します。
次に、後述するfindFilePageメソッドを使って、すでにそのページが開いていないか確認します。開いていればそのページがフォーカスするようにし、なければFilePageとして作成します。必要に応じてコンソールログ機能、ステータスバー表示機能を接続し、ページをタブウィジェットに追加します。ただ追加するだけではページが切り替わらないので、フォーカスするようにします。最後に、設定されていたブックマークに応じて、ページの内容を書き込むようにします。
findFilePageメソッドについて触れておきます。
std::optional<FilePage*> MainWindow::findFilePage(const Bookmark &bookmark) {
for (int i = 0; i < ui_->tabWidget->count(); ++i) {
auto page = qobject_cast<FilePage*>(ui_->tabWidget->widget(i));
if (page && page->equalsTo(
toLmbcsQ(bookmark.path()),
toLmbcsQ(bookmark.server()))) {
return page;
}
}
return std::nullopt;
}
機能としては、タブウィジェット内のタブを巡回し、各ウィジェットをFilePageとしてキャストできるか試します。今後、FilePage以外のページも装備する予定なので、ここは重要です。あとは、FilePageの設定とブックマークの設定が一致していれば、FilePageへのポインタを返します。見つからなければヌルを返します。
qobject_castはQt独自のキャストで、型情報などを見て目的のクラスにキャストできるか判断した上でキャストしてくれます。できなければヌルが返ってきます。
まとめ
次回は、FilePageクラスについて説明していきます。