ツリーモデル補完の例
ピリオドを区切り文字として使用し、Child、GrandChild、GrandGrandChild レベルのオブジェクトにアクセスします。
Completer Example と同様に、QComboBox オブジェクトを提供し、補完モードと大文字小文字の区別、およびラップ補完のためのQCheckBox を選択できるようにしています。
リソースファイル
TreeModelCompleter の内容はtreemodel.txt から読み込まれます。このファイルはtreemodelcompleter.qrcリソースファイル内に埋め込まれ、以下の内容を含んでいます:
<!DOCTYPE RCC><RCC version="1.0"> <qresource prefix="/"> <file>resources/treemodel.txt</file> </qresource> </RCC>
TreeModelCompleter クラス定義
TreeModelCompleter
はQCompleter のサブクラスで、parent を引数とするコンストラクタと、parent とmodel を引数とするコンストラクタを持ちます。
class TreeModelCompleter : public QCompleter { Q_OBJECT Q_PROPERTY(QString separator READ separator WRITE setSeparator) public: explicit TreeModelCompleter(QObject *parent = nullptr); explicit TreeModelCompleter(QAbstractItemModel *model, QObject *parent = nullptr); QString separator() const; public slots: void setSeparator(const QString &separator); protected: QStringList splitPath(const QString &path) const override; QString pathFromIndex(const QModelIndex &index) const override; private: QString sep; };
このクラスは、splitPath() とpathFromIndex() という protected 関数を、ツリー・モデルに合うように再実装しています。ツリー・モデルに合わせてQCompleter をカスタマイズする方法については、Handling Tree Models を参照してください。
TreeModelCompleter
また、 () マクロを使用して宣言される separator プロパティもあります。separator には READ 属性と WRITE 属性があり、対応する関数は と です。 () の詳細については、Q_PROPERTY separator()
setSeparator()
Q_PROPERTYQt's Property System を参照してください。
TreeModelCompleter クラスの実装
最初のコンストラクタは、親を持つTreeModelCompleter
オブジェクトを構築し、2 番目のコンストラクタは、親とQAbstractItemModel,model を持つオブジェクトを構築します。
TreeModelCompleter::TreeModelCompleter(QObject *parent) : QCompleter(parent) { } TreeModelCompleter::TreeModelCompleter(QAbstractItemModel *model, QObject *parent) : QCompleter(model, parent) { }
separator()
関数はセパレーター文字列を返すゲッター関数です。
QString TreeModelCompleter::separator() const { return sep; }
前述のように、splitPath()
関数は再実装されています。これは、デフォルトの実装がQFileSystemModel やリスト・モデルに適しているためです。QCompleter 、パスを各レベルでマッチする文字列のリストに分割するために、sep
をセパレーターとして、QString::split() を使って分割しています。
QStringList TreeModelCompleter::splitPath(const QString &path) const { return (sep.isNull() ? QCompleter::splitPath(path) : path.split(sep)); }
pathFromIndex()
関数は、ツリーモデルの completionRole() のデータを返します。この関数は、デフォルトの実装がリストモデルに適しているため、再実装されています。セパレータがない場合は、QCompleter'のデフォルト実装を使用します。そうでない場合は、prepend() 関数を使用して上方に移動し、データを蓄積します。この関数は、セパレータを使用して異なるレベルのオブジェクトを結合し、QStringList 、dataList
を返します。
QString TreeModelCompleter::pathFromIndex(const QModelIndex &index) const { if (sep.isNull()) return QCompleter::pathFromIndex(index); // navigate up and accumulate data QStringList dataList; for (QModelIndex i = index; i.isValid(); i = i.parent()) dataList.prepend(model()->data(i, completionRole()).toString()); return dataList.join(sep); }
MainWindowクラスの定義
MainWindow
クラスはQMainWindow のサブクラスで、5つのカスタム・スロットを実装しています:about()
changeCase()
、changeMode()
、highlight()
、updateContentsLabel()
の5つのカスタム・スロットを実装しています。
class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); private slots: void about(); void changeCase(int); void changeMode(int); void highlight(const QModelIndex &index); void updateContentsLabel(const QString &sep);
さらに、このクラスはcreateMenu()
とmodelFromFile()
の2つのプライベート関数と、QTreeView 、QComboBox 、QLabel 、TreeModelCompleter
、QLineEdit のプライベート・インスタンスを持っています。
private: void createMenu(); QAbstractItemModel *modelFromFile(const QString &fileName); QTreeView *treeView = nullptr; QComboBox *caseCombo = nullptr; QComboBox *modeCombo = nullptr; QLabel *contentsLabel = nullptr; TreeModelCompleter *completer = nullptr; QLineEdit *lineEdit = nullptr; };
MainWindow クラスの実装
MainWindow
のコンストラクタは、親を持つMainWindow
オブジェクトを作成し、completer
とlineEdit
を初期化します。createMenu()
関数が呼び出され、"File" メニューと "Help" メニューが設定されます。completer
のモデルはmodelFromFile()
から取得したQAbstractItemModel に設定され、highlighted() シグナルはMainWindow
のhighlight()
スロットに接続される。
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { createMenu(); completer = new TreeModelCompleter(this); completer->setModel(modelFromFile(":/resources/treemodel.txt")); completer->setSeparator(QLatin1String(".")); QObject::connect(completer, QOverload<const QModelIndex &>::of(&TreeModelCompleter::highlighted), this, &MainWindow::highlight); QWidget *centralWidget = new QWidget; QLabel *modelLabel = new QLabel; modelLabel->setText(tr("Tree Model<br>(Double click items to edit)")); QLabel *modeLabel = new QLabel; modeLabel->setText(tr("Completion Mode")); modeCombo = new QComboBox; modeCombo->addItem(tr("Inline")); modeCombo->addItem(tr("Filtered Popup")); modeCombo->addItem(tr("Unfiltered Popup")); modeCombo->setCurrentIndex(1); QLabel *caseLabel = new QLabel; caseLabel->setText(tr("Case Sensitivity")); caseCombo = new QComboBox; caseCombo->addItem(tr("Case Insensitive")); caseCombo->addItem(tr("Case Sensitive")); caseCombo->setCurrentIndex(0);
QLabel オブジェクトmodelLabel
、modeLabel
、caseLabel
がインスタンス化される。また、QComboBox オブジェクト、modeCombo
およびcaseCombo
がインスタンス化され、入力される。デフォルトでは、completer
のモードは "Filtered Popup "で、大文字と小文字は区別されません。
QLabel *separatorLabel = new QLabel; separatorLabel->setText(tr("Tree Separator")); QLineEdit *separatorLineEdit = new QLineEdit; separatorLineEdit->setText(completer->separator()); connect(separatorLineEdit, &QLineEdit::textChanged, completer, &TreeModelCompleter::setSeparator); QCheckBox *wrapCheckBox = new QCheckBox; wrapCheckBox->setText(tr("Wrap around completions")); wrapCheckBox->setChecked(completer->wrapAround()); connect(wrapCheckBox, &QAbstractButton::clicked, completer, &QCompleter::setWrapAround); contentsLabel = new QLabel; contentsLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); connect(separatorLineEdit, &QLineEdit::textChanged, this, &MainWindow::updateContentsLabel); treeView = new QTreeView; treeView->setModel(completer->model()); treeView->header()->hide(); treeView->expandAll(); connect(modeCombo, &QComboBox::activated, this, &MainWindow::changeMode); connect(caseCombo, &QComboBox::activated, this, &MainWindow::changeMode); lineEdit = new QLineEdit; lineEdit->setCompleter(completer);
MainWindow
にすべてのオブジェクトを配置するためにQGridLayout を使用します。
QGridLayout *layout = new QGridLayout; layout->addWidget(modelLabel, 0, 0); layout->addWidget(treeView, 0, 1); layout->addWidget(modeLabel, 1, 0); layout->addWidget(modeCombo, 1, 1); layout->addWidget(caseLabel, 2, 0); layout->addWidget(caseCombo, 2, 1); layout->addWidget(separatorLabel, 3, 0); layout->addWidget(separatorLineEdit, 3, 1); layout->addWidget(wrapCheckBox, 4, 0); layout->addWidget(contentsLabel, 5, 0, 1, 2); layout->addWidget(lineEdit, 6, 0, 1, 2); centralWidget->setLayout(layout); setCentralWidget(centralWidget); changeCase(caseCombo->currentIndex()); changeMode(modeCombo->currentIndex()); setWindowTitle(tr("Tree Model Completer")); lineEdit->setFocus(); }
createMenu()
関数は必要なQAction オブジェクトを設定し、「ファイル」メニューと「ヘルプ」メニューに追加します。これらのアクションからのtriggered() シグナルは、それぞれのスロットに接続されます。
void MainWindow::createMenu() { QAction *exitAction = new QAction(tr("Exit"), this); QAction *aboutAct = new QAction(tr("About"), this); QAction *aboutQtAct = new QAction(tr("About Qt"), this); connect(exitAction, &QAction::triggered, qApp, &QApplication::quit); connect(aboutAct, &QAction::triggered, this, &MainWindow::about); connect(aboutQtAct, &QAction::triggered, qApp, &QApplication::aboutQt); QMenu *fileMenu = menuBar()->addMenu(tr("File")); fileMenu->addAction(exitAction); QMenu *helpMenu = menuBar()->addMenu(tr("About")); helpMenu->addAction(aboutAct); helpMenu->addAction(aboutQtAct); }
changeMode()
関数は、ユーザーが選択した完了モードに対応するindex を受け取り、それに応じてcompleter
のモードを変更します。
void MainWindow::changeMode(int index) { QCompleter::CompletionMode mode; if (index == 0) mode = QCompleter::InlineCompletion; else if (index == 1) mode = QCompleter::PopupCompletion; else mode = QCompleter::UnfilteredPopupCompletion; completer->setCompletionMode(mode); }
about()
関数は、ツリーモデル・コンプリターの例に関する簡単な説明を提供する。
void MainWindow::about() { QMessageBox::about(this, tr("About"), tr("This example demonstrates how " "to use a QCompleter with a custom tree model.")); }
changeCase()
関数は、cs の値に応じて、Case Sensitive とCase Insensitive のモードを交互に切り替える。
void MainWindow::changeCase(int cs) { completer->setCaseSensitivity(cs ? Qt::CaseSensitive : Qt::CaseInsensitive); }
main()
関数
main()
関数は、MainWindow
をインスタンス化し、show() 関数を呼び出して表示します。
int main(int argc, char *argv[]) { QApplication app(argc, argv); MainWindow window; window.show(); return app.exec(); }
©2024 The Qt Company Ltd. 本書に含まれる文書の著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。