summaryrefslogtreecommitdiffstats
path: root/src/libs/installer/componentselectionpage_p.cpp
diff options
context:
space:
mode:
authorArttu Tarkiainen <arttu.tarkiainen@qt.io>2021-09-09 16:50:45 +0300
committerArttu Tarkiainen <arttu.tarkiainen@qt.io>2021-10-28 12:40:02 +0300
commit3ad787d0dd580a8cfb37f4e56b55f1889e24727b (patch)
tree39cf797e89b96e0c119c55ca0d2196416f853975 /src/libs/installer/componentselectionpage_p.cpp
parentf64011e117e759754f7b4f2885f9bf335a6596ff (diff)
Add possibility to search for components in ComponentSelectionPage
Introduce ComponentSortFilterProxyModel, that compared to its base class QSortFilterProxyModel, accepts also child indexes of a source model index which is directly accepted by the filter. Also remove emitting of QAbstractItemModel::dataChanged() for each item in the ComponentModel, which was done regardless of if data at index was changed or not, after reset or when check state or data for any item was changed. If the ComponentModel acts as a source model for a proxy model with 'dynamicSortFilter' property set to true, the extra emits hurt the performance as the model gets filtered again for each source model change. Actual changes done to the ComponentModel are still notified. Task-number: QTIFW-1404 Change-Id: Iea696f8b9abf79d877fb2568488b09dc3cb061be Reviewed-by: Katja Marttila <katja.marttila@qt.io>
Diffstat (limited to 'src/libs/installer/componentselectionpage_p.cpp')
-rw-r--r--src/libs/installer/componentselectionpage_p.cpp91
1 files changed, 80 insertions, 11 deletions
diff --git a/src/libs/installer/componentselectionpage_p.cpp b/src/libs/installer/componentselectionpage_p.cpp
index a180888d1..7717f4cf3 100644
--- a/src/libs/installer/componentselectionpage_p.cpp
+++ b/src/libs/installer/componentselectionpage_p.cpp
@@ -50,6 +50,7 @@
#include <QStackedLayout>
#include <QStackedWidget>
#include <QToolBox>
+#include <QLineEdit>
namespace QInstaller {
@@ -71,8 +72,11 @@ ComponentSelectionPagePrivate::ComponentSelectionPagePrivate(ComponentSelectionP
, m_descriptionBaseWidget(nullptr)
, m_categoryWidget(Q_NULLPTR)
, m_categoryLayoutVisible(false)
+ , m_proxyModel(new ComponentSortFilterProxyModel(q))
{
m_treeView->setObjectName(QLatin1String("ComponentsTreeView"));
+ m_proxyModel->setRecursiveFilteringEnabled(true);
+ m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
m_descriptionBaseWidget = new QWidget(q);
m_descriptionBaseWidget->setObjectName(QLatin1String("DescriptionBaseWidget"));
@@ -155,9 +159,18 @@ ComponentSelectionPagePrivate::ComponentSelectionPagePrivate(ComponentSelectionP
metaLayout->addWidget(m_progressBar);
metaLayout->addSpacerItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding));
+ m_searchLineEdit = new QLineEdit(q);
+ m_searchLineEdit->setObjectName(QLatin1String("SearchLineEdit"));
+ m_searchLineEdit->setPlaceholderText(ComponentSelectionPage::tr("Search"));
+ m_searchLineEdit->setClearButtonEnabled(true);
+ connect(m_searchLineEdit, &QLineEdit::textChanged,
+ this, &ComponentSelectionPagePrivate::setSearchPattern);
+ connect(q, &ComponentSelectionPage::entered, m_searchLineEdit, &QLineEdit::clear);
+
QVBoxLayout *treeViewVLayout = new QVBoxLayout;
treeViewVLayout->setObjectName(QLatin1String("TreeviewLayout"));
treeViewVLayout->addWidget(m_treeView, 3);
+ treeViewVLayout->addWidget(m_searchLineEdit);
QWidget *mainStackedWidget = new QWidget();
m_mainGLayout = new QGridLayout(mainStackedWidget);
@@ -292,15 +305,11 @@ void ComponentSelectionPagePrivate::updateTreeView()
this, &ComponentSelectionPagePrivate::currentSelectedChanged);
}
+ m_searchLineEdit->setVisible(!m_core->isUpdater());
m_currentModel = m_core->isUpdater() ? m_updaterModel : m_allModel;
- m_treeView->setModel(m_currentModel);
- m_treeView->setExpanded(m_currentModel->index(0, 0), true);
- foreach (Component *component, m_core->components(PackageManagerCore::ComponentType::All)) {
- if (component->isExpandedByDefault()) {
- const QModelIndex index = m_currentModel->indexFromComponentName(component->treeName());
- m_treeView->setExpanded(index, true);
- }
- }
+ m_proxyModel->setSourceModel(m_currentModel);
+ m_treeView->setModel(m_proxyModel);
+ expandDefault();
const bool installActionColumnVisible = m_core->settings().installActionColumnVisible();
if (!installActionColumnVisible)
@@ -341,7 +350,44 @@ void ComponentSelectionPagePrivate::updateTreeView()
connect(m_treeView->selectionModel(), &QItemSelectionModel::currentChanged,
this, &ComponentSelectionPagePrivate::currentSelectedChanged);
- m_treeView->setCurrentIndex(m_currentModel->index(0, 0));
+ m_treeView->setCurrentIndex(m_proxyModel->index(0, 0));
+}
+
+/*!
+ Expands components that should be expanded by default.
+*/
+void ComponentSelectionPagePrivate::expandDefault()
+{
+ m_treeView->setExpanded(m_proxyModel->index(0, 0), true);
+ foreach (auto *component, m_core->components(PackageManagerCore::ComponentType::All)) {
+ if (component->isExpandedByDefault()) {
+ const QModelIndex index = m_proxyModel->mapFromSource(
+ m_currentModel->indexFromComponentName(component->treeName()));
+ m_treeView->setExpanded(index, true);
+ }
+ }
+}
+
+/*!
+ Expands components that were accepted by proxy models filter.
+*/
+void ComponentSelectionPagePrivate::expandSearchResults()
+{
+ // Expand parents of root indexes accepted by filter
+ const QVector<QModelIndex> acceptedIndexes = m_proxyModel->directlyAcceptedIndexes();
+ for (auto proxyModelIndex : acceptedIndexes) {
+ if (!proxyModelIndex.isValid())
+ continue;
+
+ QModelIndex index = proxyModelIndex.parent();
+ while (index.isValid()) {
+ if (m_treeView->isExpanded(index))
+ break; // Multiple direct matches in a branch, can be skipped
+
+ m_treeView->expand(index);
+ index = index.parent();
+ }
+ }
}
void ComponentSelectionPagePrivate::currentSelectedChanged(const QModelIndex &current)
@@ -351,12 +397,12 @@ void ComponentSelectionPagePrivate::currentSelectedChanged(const QModelIndex &cu
m_sizeLabel->setText(QString());
- QString description = m_currentModel->data(m_currentModel->index(current.row(),
+ QString description = m_proxyModel->data(m_proxyModel->index(current.row(),
ComponentModelHelper::NameColumn, current.parent()), Qt::ToolTipRole).toString();
m_descriptionLabel->setText(description);
- Component *component = m_currentModel->componentFromIndex(current);
+ Component *component = m_currentModel->componentFromIndex(m_proxyModel->mapToSource(current));
if ((m_core->isUninstaller()) || (!component))
return;
@@ -429,6 +475,7 @@ void ComponentSelectionPagePrivate::fetchRepositoryCategories()
QLatin1String("FailToFetchPackages"), tr("Error"), m_core->error());
}
updateWidgetVisibility(false);
+ m_searchLineEdit->text().isEmpty() ? expandDefault() : expandSearchResults();
}
void ComponentSelectionPagePrivate::customButtonClicked(int which)
@@ -507,4 +554,26 @@ void ComponentSelectionPagePrivate::onModelStateChanged(QInstaller::ComponentMod
currentSelectedChanged(m_treeView->selectionModel()->currentIndex());
}
+/*!
+ Sets the new filter pattern to \a text and expands the tree nodes.
+*/
+void ComponentSelectionPagePrivate::setSearchPattern(const QString &text)
+{
+ m_proxyModel->setFilterWildcard(text);
+
+ m_treeView->collapseAll();
+ if (text.isEmpty()) {
+ // Expand user selection and default expanded, ensure selected is visible
+ QModelIndex index = m_treeView->selectionModel()->currentIndex();
+ while (index.isValid()) {
+ m_treeView->expand(index);
+ index = index.parent();
+ }
+ expandDefault();
+ m_treeView->scrollTo(m_treeView->selectionModel()->currentIndex());
+ } else {
+ expandSearchResults();
+ }
+}
+
} // namespace QInstaller