From 47e576528e4f61c1e387e7ee89bc6b18b7ce3d94 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 27 Mar 2020 11:56:25 +0100 Subject: [PATCH] Port QtCreator over to use filterRegularExpression QSortFilterProxyModel::filterRegExp is going to go away in Qt6, so port over to use QRegularExpression instead. This required some changes where setFilterWildcard/FixedString() was being used, as those would instantiate QRegExp based filters in Qt 5, and will use QRegularExpression in Qt 6. Use the generic setFilterRegularExpression here, to keep things portable between 5 and 6. Change-Id: I6379be781aa3821b10ba783c088f82c1a0970911 Reviewed-by: Eike Ziller --- README.md | 4 +-- qtcreator.pro | 4 +-- src/libs/utils/categorysortfiltermodel.cpp | 4 +-- .../clangtools/clangselectablefilesdialog.cpp | 24 ----------------- .../coreplugin/dialogs/ioptionspage.cpp | 7 ++--- src/plugins/coreplugin/dialogs/ioptionspage.h | 4 +-- .../coreplugin/dialogs/settingsdialog.cpp | 27 +++++++++++-------- src/plugins/coreplugin/variablechooser.cpp | 6 ++--- src/plugins/designer/settingspage.cpp | 4 +-- src/plugins/designer/settingspage.h | 2 +- src/plugins/git/branchview.cpp | 2 +- .../projectexplorer/addrunconfigdialog.cpp | 2 +- .../devicesupport/deviceprocessesdialog.cpp | 4 +-- src/plugins/todo/todooutputpane.cpp | 2 +- .../callgrind/callgrindproxymodel.cpp | 2 +- src/plugins/valgrind/callgrindtool.cpp | 4 +-- src/shared/help/bookmarkmanager.cpp | 11 ++++---- src/shared/help/bookmarkmanager.h | 2 +- 18 files changed, 48 insertions(+), 67 deletions(-) diff --git a/README.md b/README.md index 896d2e8b71a..c4f892626bb 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ https://doc-snapshots.qt.io/qtcreator-extending/coding-style.html Prerequisites: -* Qt 5.11.0 or later +* Qt 5.12.0 or later * Qt WebEngine module for QtWebEngine based help viewer * On Windows: * ActiveState Active Perl @@ -89,7 +89,7 @@ For detailed information on the supported compilers, see for example, `c:\work`. If you plan to use MinGW and Microsoft Visual Studio simultaneously or mix different Qt versions, we recommend creating a directory structure which reflects that. For example: - `C:\work\qt5.11.0-vs15, C:\work\qt5.11.0-mingw`. + `C:\work\qt5.12.0-vs15, C:\work\qt5.12.0-mingw`. 4. Download and install Perl from and check that perl.exe is added to the path. Run `perl -v` to verify diff --git a/qtcreator.pro b/qtcreator.pro index f59ec0a3320..ff0b5464597 100644 --- a/qtcreator.pro +++ b/qtcreator.pro @@ -1,9 +1,9 @@ include(qtcreator.pri) #version check qt -!minQtVersion(5, 11, 0) { +!minQtVersion(5, 12, 0) { message("Cannot build $$IDE_DISPLAY_NAME with Qt version $${QT_VERSION}.") - error("Use at least Qt 5.11.0.") + error("Use at least Qt 5.12.0.") } include(doc/doc.pri) diff --git a/src/libs/utils/categorysortfiltermodel.cpp b/src/libs/utils/categorysortfiltermodel.cpp index ab1769f8bd1..0e5493c9f46 100644 --- a/src/libs/utils/categorysortfiltermodel.cpp +++ b/src/libs/utils/categorysortfiltermodel.cpp @@ -37,9 +37,9 @@ bool CategorySortFilterModel::filterAcceptsRow(int source_row, { if (!source_parent.isValid()) { // category items should be visible if any of its children match - const QRegExp ®exp = filterRegExp(); + const QRegularExpression ®exp = filterRegularExpression(); const QModelIndex &categoryIndex = sourceModel()->index(source_row, 0, source_parent); - if (regexp.indexIn(sourceModel()->data(categoryIndex, filterRole()).toString()) != -1) + if (regexp.match(sourceModel()->data(categoryIndex, filterRole()).toString()).hasMatch()) return true; const int rowCount = sourceModel()->rowCount(categoryIndex); for (int row = 0; row < rowCount; ++row) { diff --git a/src/plugins/clangtools/clangselectablefilesdialog.cpp b/src/plugins/clangtools/clangselectablefilesdialog.cpp index f879e5099d2..6fa105e896f 100644 --- a/src/plugins/clangtools/clangselectablefilesdialog.cpp +++ b/src/plugins/clangtools/clangselectablefilesdialog.cpp @@ -264,30 +264,6 @@ private: } }; -class FileFilterModel : public QSortFilterProxyModel -{ - Q_OBJECT - -public: - FileFilterModel(QObject *parent = nullptr) - : QSortFilterProxyModel(parent) - {} - -private: - bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override - { - QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); - const int rowCount = sourceModel()->rowCount(index); - if (rowCount == 0) // No children -> file node! - return sourceModel()->data(index).toString().contains(filterRegExp()); - for (int row = 0; row < rowCount; ++row) { - if (filterAcceptsRow(row, index)) - return true; - } - return false; - } -}; - SelectableFilesDialog::SelectableFilesDialog(const ProjectInfo &projectInfo, const FileInfoProviders &fileInfoProviders, int initialProviderIndex) diff --git a/src/plugins/coreplugin/dialogs/ioptionspage.cpp b/src/plugins/coreplugin/dialogs/ioptionspage.cpp index be700875ad4..80ce45d6521 100644 --- a/src/plugins/coreplugin/dialogs/ioptionspage.cpp +++ b/src/plugins/coreplugin/dialogs/ioptionspage.cpp @@ -36,6 +36,7 @@ #include #include #include +#include using namespace Utils; @@ -227,11 +228,11 @@ const QList Core::IOptionsPage::allOptionsPages() } /*! - Is used by the \uicontrol Options dialog search filter to match \a searchKeyWord to this options + Is used by the \uicontrol Options dialog search filter to match \a regexp to this options page. This defaults to take the widget and then looks for all child labels, check boxes, push buttons, and group boxes. Should return \c true when a match is found. */ -bool Core::IOptionsPage::matches(const QString &searchKeyWord) const +bool Core::IOptionsPage::matches(const QRegularExpression ®exp) const { if (!m_keywordsInitialized) { auto that = const_cast(this); @@ -251,7 +252,7 @@ bool Core::IOptionsPage::matches(const QString &searchKeyWord) const m_keywordsInitialized = true; } foreach (const QString &keyword, m_keywords) - if (keyword.contains(searchKeyWord, Qt::CaseInsensitive)) + if (keyword.contains(regexp)) return true; return false; } diff --git a/src/plugins/coreplugin/dialogs/ioptionspage.h b/src/plugins/coreplugin/dialogs/ioptionspage.h index e3ceab0fd0c..bef965628dd 100644 --- a/src/plugins/coreplugin/dialogs/ioptionspage.h +++ b/src/plugins/coreplugin/dialogs/ioptionspage.h @@ -64,7 +64,7 @@ public: using WidgetCreator = std::function; void setWidgetCreator(const WidgetCreator &widgetCreator); - virtual bool matches(const QString &searchKeyWord) const; + virtual bool matches(const QRegularExpression ®exp) const; virtual QWidget *widget(); virtual void apply(); virtual void finish(); @@ -112,7 +112,7 @@ public: QIcon categoryIcon() const; virtual QList pages() const = 0; - virtual bool matches(const QString & /* searchKeyWord*/) const = 0; + virtual bool matches(const QRegularExpression ®exp) const = 0; protected: void setCategory(Id category) { m_category = category; } diff --git a/src/plugins/coreplugin/dialogs/settingsdialog.cpp b/src/plugins/coreplugin/dialogs/settingsdialog.cpp index 459af08a4ae..192d0843ede 100644 --- a/src/plugins/coreplugin/dialogs/settingsdialog.cpp +++ b/src/plugins/coreplugin/dialogs/settingsdialog.cpp @@ -262,19 +262,18 @@ bool CategoryFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sou if (QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent)) return true; - const QString pattern = filterRegExp().pattern(); + const QRegularExpression regex = filterRegularExpression(); const CategoryModel *cm = static_cast(sourceModel()); const Category *category = cm->categories().at(sourceRow); for (const IOptionsPage *page : category->pages) { - if (page->displayCategory().contains(pattern, Qt::CaseInsensitive) - || page->displayName().contains(pattern, Qt::CaseInsensitive) - || page->matches(pattern)) + if (page->displayCategory().contains(regex) || page->displayName().contains(regex) + || page->matches(regex)) return true; } if (!category->providerPagesCreated) { for (const IOptionsPageProvider *provider : category->providers) { - if (provider->matches(pattern)) + if (provider->matches(regex)) return true; } } @@ -469,8 +468,14 @@ SettingsDialog::SettingsDialog(QWidget *parent) : // The order of the slot connection matters here, the filter slot // opens the matching page after the model has filtered. - connect(m_filterLineEdit, &Utils::FancyLineEdit::filterChanged, - &m_proxyModel, &QSortFilterProxyModel::setFilterFixedString); + connect(m_filterLineEdit, + &Utils::FancyLineEdit::filterChanged, + &m_proxyModel, + [this](const QString &filter) { + m_proxyModel.setFilterRegularExpression( + QRegularExpression(QRegularExpression::escape(filter), + QRegularExpression::CaseInsensitiveOption)); + }); connect(m_filterLineEdit, &Utils::FancyLineEdit::filterChanged, this, &SettingsDialog::filter); m_categoryList->setFocus(); @@ -631,12 +636,12 @@ void SettingsDialog::disconnectTabWidgets() void SettingsDialog::updateEnabledTabs(Category *category, const QString &searchText) { int firstEnabledTab = -1; + const QRegularExpression regex(QRegularExpression::escape(searchText), + QRegularExpression::CaseInsensitiveOption); for (int i = 0; i < category->pages.size(); ++i) { const IOptionsPage *page = category->pages.at(i); - const bool enabled = searchText.isEmpty() - || page->category().toString().contains(searchText, Qt::CaseInsensitive) - || page->displayName().contains(searchText, Qt::CaseInsensitive) - || page->matches(searchText); + const bool enabled = searchText.isEmpty() || page->category().toString().contains(regex) + || page->displayName().contains(regex) || page->matches(regex); category->tabWidget->setTabEnabled(i, enabled); if (enabled && firstEnabledTab < 0) firstEnabledTab = i; diff --git a/src/plugins/coreplugin/variablechooser.cpp b/src/plugins/coreplugin/variablechooser.cpp index 57668180295..f196dabb373 100644 --- a/src/plugins/coreplugin/variablechooser.cpp +++ b/src/plugins/coreplugin/variablechooser.cpp @@ -90,8 +90,8 @@ public: if (!index.isValid()) return false; - const QRegExp regexp = filterRegExp(); - if (regexp.isEmpty() || sourceModel()->rowCount(index) > 0) + const QRegularExpression regexp = filterRegularExpression(); + if (regexp.pattern().isEmpty() || sourceModel()->rowCount(index) > 0) return true; const QString displayText = index.data(Qt::DisplayRole).toString(); @@ -548,7 +548,7 @@ void VariableChooserPrivate::updatePositionAndShow(bool) void VariableChooserPrivate::updateFilter(const QString &filterText) { - m_sortModel->setFilterWildcard(filterText); + m_sortModel->setFilterRegularExpression(QRegularExpression::wildcardToRegularExpression(filterText)); m_variableTree->expandAll(); } diff --git a/src/plugins/designer/settingspage.cpp b/src/plugins/designer/settingspage.cpp index f038b7a4db5..0c51d80ab32 100644 --- a/src/plugins/designer/settingspage.cpp +++ b/src/plugins/designer/settingspage.cpp @@ -85,7 +85,7 @@ QList SettingsPageProvider::pages() const return FormEditorW::optionsPages(); } -bool SettingsPageProvider::matches(const QString &searchKeyWord) const +bool SettingsPageProvider::matches(const QRegularExpression ®ex) const { // to avoid fully initializing designer when typing something in the options' filter edit // we hardcode matching of UI text from the designer pages, which are taken if the designer pages @@ -119,7 +119,7 @@ bool SettingsPageProvider::matches(const QString &searchKeyWord) const m_keywords << Utils::stripAccelerator(QCoreApplication::translate(uitext[i].context, uitext[i].value)); } for (const QString &key : qAsConst(m_keywords)) { - if (key.contains(searchKeyWord, Qt::CaseInsensitive)) + if (key.contains(regex)) return true; } return false; diff --git a/src/plugins/designer/settingspage.h b/src/plugins/designer/settingspage.h index 13de3c2808a..5086a879d61 100644 --- a/src/plugins/designer/settingspage.h +++ b/src/plugins/designer/settingspage.h @@ -63,7 +63,7 @@ public: SettingsPageProvider(); QList pages() const override; - bool matches(const QString &searchKeyWord) const override; + bool matches(const QRegularExpression ®ex) const override; private: mutable bool m_initialized = false; diff --git a/src/plugins/git/branchview.cpp b/src/plugins/git/branchview.cpp index 87c4e097537..c9bc67cb6b2 100644 --- a/src/plugins/git/branchview.cpp +++ b/src/plugins/git/branchview.cpp @@ -106,7 +106,7 @@ BranchView::BranchView() : auto filterEdit = new Utils::FancyLineEdit(this); filterEdit->setFiltering(true); connect(filterEdit, &Utils::FancyLineEdit::textChanged, - m_filterModel, QOverload::of(&BranchFilterModel::setFilterRegExp)); + m_filterModel, QOverload::of(&BranchFilterModel::setFilterRegularExpression)); auto layout = new QVBoxLayout(this); layout->addWidget(filterEdit); layout->addWidget(m_repositoryLabel); diff --git a/src/plugins/projectexplorer/addrunconfigdialog.cpp b/src/plugins/projectexplorer/addrunconfigdialog.cpp index 647959eb15c..bc57e1c5448 100644 --- a/src/plugins/projectexplorer/addrunconfigdialog.cpp +++ b/src/plugins/projectexplorer/addrunconfigdialog.cpp @@ -154,7 +154,7 @@ AddRunConfigDialog::AddRunConfigDialog(Target *target, QWidget *parent) buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Create")); connect(filterEdit, &QLineEdit::textChanged, this, [proxyModel](const QString &text) { - proxyModel->setFilterRegExp(QRegExp(text, Qt::CaseInsensitive)); + proxyModel->setFilterRegularExpression(QRegularExpression(text, QRegularExpression::CaseInsensitiveOption)); }); connect(m_view, &TreeView::doubleClicked, this, [this] { accept(); }); const auto updateOkButton = [buttonBox, this] { diff --git a/src/plugins/projectexplorer/devicesupport/deviceprocessesdialog.cpp b/src/plugins/projectexplorer/devicesupport/deviceprocessesdialog.cpp index 3734977c4b3..bef4f16974c 100644 --- a/src/plugins/projectexplorer/devicesupport/deviceprocessesdialog.cpp +++ b/src/plugins/projectexplorer/devicesupport/deviceprocessesdialog.cpp @@ -182,10 +182,10 @@ DeviceProcessesDialogPrivate::DeviceProcessesDialogPrivate(KitChooser *chooser, // line->setFrameShape(QFrame::HLine); // line->setFrameShadow(QFrame::Sunken); - proxyModel.setFilterRegExp(processFilterLineEdit->text()); + proxyModel.setFilterRegularExpression(processFilterLineEdit->text()); connect(processFilterLineEdit, QOverload::of(&FancyLineEdit::textChanged), - &proxyModel, QOverload::of(&ProcessListFilterModel::setFilterRegExp)); + &proxyModel, QOverload::of(&ProcessListFilterModel::setFilterRegularExpression)); connect(procView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &DeviceProcessesDialogPrivate::updateButtons); connect(updateListButton, &QAbstractButton::clicked, diff --git a/src/plugins/todo/todooutputpane.cpp b/src/plugins/todo/todooutputpane.cpp index 940f6e97f23..a4a3fa1cce4 100644 --- a/src/plugins/todo/todooutputpane.cpp +++ b/src/plugins/todo/todooutputpane.cpp @@ -202,7 +202,7 @@ void TodoOutputPane::updateKeywordFilter() int sortColumn = m_todoTreeView->header()->sortIndicatorSection(); Qt::SortOrder sortOrder = m_todoTreeView->header()->sortIndicatorOrder(); - m_filteredTodoItemsModel->setFilterRegExp(pattern); + m_filteredTodoItemsModel->setFilterRegularExpression(pattern); m_filteredTodoItemsModel->sort(sortColumn, sortOrder); updateTodoCount(); diff --git a/src/plugins/valgrind/callgrind/callgrindproxymodel.cpp b/src/plugins/valgrind/callgrind/callgrindproxymodel.cpp index 13809a83d43..66a362f4956 100644 --- a/src/plugins/valgrind/callgrind/callgrindproxymodel.cpp +++ b/src/plugins/valgrind/callgrind/callgrindproxymodel.cpp @@ -109,7 +109,7 @@ bool DataProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_ return false; // if the filter regexp is a non-empty string, ignore our filters - if (!filterRegExp().isEmpty()) + if (!filterRegularExpression().pattern().isEmpty()) return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent); // check max rows diff --git a/src/plugins/valgrind/callgrindtool.cpp b/src/plugins/valgrind/callgrindtool.cpp index 92ed908ac96..867b77f49ee 100644 --- a/src/plugins/valgrind/callgrindtool.cpp +++ b/src/plugins/valgrind/callgrindtool.cpp @@ -554,7 +554,7 @@ void CallgrindToolPrivate::doClear(bool clearParseData) m_proxyModel.setFilterBaseDir(QString()); if (m_searchFilter) m_searchFilter->clear(); - m_proxyModel.setFilterFixedString(QString()); + m_proxyModel.setFilterRegularExpression(QRegularExpression()); } void CallgrindToolPrivate::setBusyCursor(bool busy) @@ -609,7 +609,7 @@ void CallgrindToolPrivate::stackBrowserChanged() void CallgrindToolPrivate::updateFilterString() { - m_proxyModel.setFilterFixedString(m_searchFilter->text()); + m_proxyModel.setFilterRegularExpression(QRegularExpression::escape(m_searchFilter->text())); } void CallgrindToolPrivate::setCostFormat(CostDelegate::CostFormat format) diff --git a/src/shared/help/bookmarkmanager.cpp b/src/shared/help/bookmarkmanager.cpp index e67f910e9c0..788bf6a714a 100644 --- a/src/shared/help/bookmarkmanager.cpp +++ b/src/shared/help/bookmarkmanager.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include @@ -76,8 +77,7 @@ BookmarkDialog::BookmarkDialog(BookmarkManager *manager, const QString &title, proxyModel->setDynamicSortFilter(true); proxyModel->setFilterRole(Qt::UserRole + 10); proxyModel->setSourceModel(bookmarkManager->treeBookmarkModel()); - proxyModel->setFilterRegExp(QRegExp(QLatin1String("Folder"), - Qt::CaseSensitive, QRegExp::FixedString)); + proxyModel->setFilterRegularExpression(QRegularExpression(QLatin1String("Folder"))); ui.treeView->setModel(proxyModel); ui.treeView->expandAll(); @@ -320,14 +320,14 @@ void BookmarkWidget::filterChanged() { bool searchBookmarks = searchField->text().isEmpty(); if (!searchBookmarks) { - regExp.setPattern(searchField->text()); + regExp.setPattern(QRegularExpression::escape(searchField->text())); filterBookmarkModel->setSourceModel(bookmarkManager->listBookmarkModel()); } else { regExp.setPattern(QString()); filterBookmarkModel->setSourceModel(bookmarkManager->treeBookmarkModel()); } - filterBookmarkModel->setFilterRegExp(regExp); + filterBookmarkModel->setFilterRegularExpression(regExp); const QModelIndex &index = treeView->indexAt(QPoint(1, 1)); if (index.isValid()) @@ -408,8 +408,7 @@ void BookmarkWidget::customContextMenuRequested(const QPoint &point) void BookmarkWidget::setup() { - regExp.setPatternSyntax(QRegExp::FixedString); - regExp.setCaseSensitivity(Qt::CaseInsensitive); + regExp.setPatternOptions(QRegularExpression::CaseInsensitiveOption); QLayout *vlayout = new QVBoxLayout(this); vlayout->setContentsMargins(0, 0, 0, 0); diff --git a/src/shared/help/bookmarkmanager.h b/src/shared/help/bookmarkmanager.h index c11cc5e9bb1..0339bbf315e 100644 --- a/src/shared/help/bookmarkmanager.h +++ b/src/shared/help/bookmarkmanager.h @@ -122,7 +122,7 @@ private: void expandItems(); bool eventFilter(QObject *object, QEvent *event); - QRegExp regExp; + QRegularExpression regExp; TreeView *treeView; Utils::FancyLineEdit *searchField; BookmarkManager *bookmarkManager;