Navigator: Add search/filter to navigator

Task-number: QDS-6063
Change-Id: I922a04a46f673befe8811a62342cf2cdd9c61583
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Henning Gründl <henning.gruendl@qt.io>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Tapani Mattila
2022-03-22 16:45:43 +02:00
parent f0fc3926cb
commit f58add023a
11 changed files with 191 additions and 2 deletions

View File

@@ -276,6 +276,7 @@ extend_qtc_plugin(QmlDesigner
nameitemdelegate.cpp nameitemdelegate.h
navigator.qrc
navigatormodelinterface.h
navigatorsearchwidget.cpp navigatorsearchwidget.h
navigatortreemodel.cpp navigatortreemodel.h
navigatortreeview.cpp navigatortreeview.h
navigatorview.cpp navigatorview.h

View File

@@ -45,6 +45,7 @@ public:
virtual void notifyModelNodesMoved(const QList<ModelNode> &modelNodes) = 0;
virtual void notifyIconsChanged() = 0;
virtual void setFilter(bool showObjects) = 0;
virtual void setNameFilter(const QString &filter) = 0;
virtual void setOrder(bool reverse) = 0;
virtual void resetModel() = 0;
};

View File

@@ -0,0 +1,66 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "navigatorsearchwidget.h"
#include <utils/stylehelper.h>
#include <theme.h>
#include <QBoxLayout>
#include <QLabel>
#include <QPushButton>
namespace QmlDesigner {
NavigatorSearchWidget::NavigatorSearchWidget(QWidget *parent)
: QWidget(parent)
{
auto layout = new QBoxLayout(QBoxLayout::LeftToRight);
setLayout(layout);
const QString fontName = "qtds_propertyIconFont.ttf";
const int iconSize = 15;
const QColor iconColor(QmlDesigner::Theme::getColor(QmlDesigner::Theme::IconsBaseColor));
const QIcon searchIcon = Utils::StyleHelper::getIconFromIconFont(
fontName, QmlDesigner::Theme::getIconUnicode(QmlDesigner::Theme::Icon::search),
iconSize, iconSize, iconColor);
m_textField = new QLineEdit;
m_textField->setPlaceholderText(tr("Filter"));
m_textField->setFrame(false);
m_textField->setClearButtonEnabled(true);
m_textField->addAction(searchIcon, QLineEdit::LeadingPosition);
connect(m_textField, &QLineEdit::textChanged, this, &NavigatorSearchWidget::textChanged);
layout->addWidget(m_textField);
}
void NavigatorSearchWidget::clear()
{
m_textField->clear();
}
} // QmlDesigner

View File

@@ -0,0 +1,49 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <QLineEdit>
namespace QmlDesigner {
class NavigatorSearchWidget : public QWidget
{
Q_OBJECT
public:
NavigatorSearchWidget(QWidget *parent = nullptr);
void clear();
signals:
void textChanged(const QString &text);
private:
QLineEdit *m_textField;
};
} //QmlDesigner

View File

@@ -324,14 +324,25 @@ QList<ModelNode> NavigatorTreeModel::filteredList(const NodeListProperty &proper
return it.value();
QList<ModelNode> list;
QList<ModelNode> propertyNodes = property.toModelNodeList();
QList<ModelNode> nameFilteredList;
if (m_nameFilter.isEmpty()) {
nameFilteredList = propertyNodes;
} else {
nameFilteredList.append(Utils::filtered(propertyNodes, [&] (const ModelNode &arg){
const bool value = m_nameFilteredList.contains(arg);
return value;
}));
}
if (filter) {
list.append(Utils::filtered(property.toModelNodeList(), [] (const ModelNode &arg) {
list.append(Utils::filtered(nameFilteredList, [] (const ModelNode &arg) {
const bool value = QmlItemNode::isValidQmlItemNode(arg) || NodeHints::fromModelNode(arg).visibleInNavigator();
return value;
}));
} else {
list = property.toModelNodeList();
list = nameFilteredList;
}
appendForcedNodes(property, list);
@@ -1222,6 +1233,35 @@ void NavigatorTreeModel::setFilter(bool showOnlyVisibleItems)
resetModel();
}
void NavigatorTreeModel::setNameFilter(const QString &filter)
{
m_nameFilter = filter;
m_rowCache.clear();
ModelNode rootNode = m_view->rootModelNode();
QList<ModelNode> allNodes = rootNode.allSubModelNodes();
m_nameFilteredList.clear();
if (filter.isEmpty()) {
m_nameFilteredList = allNodes;
} else {
for (ModelNode &node : rootNode.allSubModelNodes()) {
if (node.displayName().contains(filter, Qt::CaseSensitivity::CaseInsensitive)) {
m_nameFilteredList.append(node);
ModelNode n = node;
while (n.hasParentProperty()) {
n = n.parentProperty().parentModelNode();
if (n.isRootNode() || m_nameFilteredList.contains(n))
break;
m_nameFilteredList.append(n);
}
}
}
}
resetModel();
}
void NavigatorTreeModel::setOrder(bool reverseItemOrder)
{
m_reverseItemOrder = reverseItemOrder;

View File

@@ -101,6 +101,7 @@ public:
void notifyModelNodesMoved(const QList<ModelNode> &modelNodes) override;
void notifyIconsChanged() override;
void setFilter(bool showOnlyVisibleItems) override;
void setNameFilter(const QString &filter) override;
void setOrder(bool reverseItemOrder) override;
void resetModel() override;
@@ -140,6 +141,8 @@ private:
bool m_showOnlyVisibleItems = true;
bool m_reverseItemOrder = false;
DesignerActionManager *m_actionManager = nullptr;
QString m_nameFilter;
QList<ModelNode> m_nameFilteredList;
};
} // namespace QmlDesigner

View File

@@ -152,6 +152,8 @@ void NavigatorView::modelAttached(Model *model)
treeView->setIndentation(20);
m_currentModelInterface->setFilter(false);
m_currentModelInterface->setNameFilter("");
m_widget->clearSearch();
QTimer::singleShot(0, this, [this, treeView]() {
m_currentModelInterface->setFilter(
@@ -576,6 +578,12 @@ void NavigatorView::reverseOrderToggled(bool flag)
DesignerSettings::setValue(DesignerSettingsKey::NAVIGATOR_REVERSE_ITEM_ORDER, flag);
}
void NavigatorView::textFilterChanged(const QString &text)
{
m_treeModel->setNameFilter(text);
treeWidget()->expandAll();
}
void NavigatorView::changeSelection(const QItemSelection & /*newSelection*/, const QItemSelection &/*deselected*/)
{
if (m_blockSelectionChangedSignal)
@@ -704,6 +712,8 @@ void NavigatorView::setupWidget()
connect(m_widget.data(), &NavigatorWidget::filterToggled, this, &NavigatorView::filterToggled);
connect(m_widget.data(), &NavigatorWidget::reverseOrderToggled, this, &NavigatorView::reverseOrderToggled);
connect(m_widget.data(), &NavigatorWidget::textFilterChanged, this, &NavigatorView::textFilterChanged);
#ifndef QMLDESIGNER_TEST
const QString fontName = "qtds_propertyIconFont.ttf";
const QSize size = QSize(28, 28);

View File

@@ -118,6 +118,8 @@ private:
void filterToggled(bool);
void reverseOrderToggled(bool);
void textFilterChanged(const QString &text);
protected: //functions
QTreeView *treeWidget() const;
NavigatorTreeModel *treeModel();

View File

@@ -23,6 +23,7 @@
**
****************************************************************************/
#include "navigatorsearchwidget.h"
#include "navigatorwidget.h"
#include "navigatorview.h"
@@ -160,6 +161,10 @@ QToolBar *NavigatorWidget::createToolBar()
for (auto toolButton : buttons)
toolBar->addWidget(toolButton);
m_searchWidget = new NavigatorSearchWidget();
connect(m_searchWidget, &NavigatorSearchWidget::textChanged, this, &NavigatorWidget::textFilterChanged);
toolBar->addWidget(m_searchWidget);
return toolBar;
}
@@ -211,4 +216,9 @@ QByteArray NavigatorWidget::dragType() const
return m_dragType;
}
void NavigatorWidget::clearSearch()
{
m_searchWidget->clear();
}
}

View File

@@ -39,6 +39,7 @@ QT_FORWARD_DECLARE_CLASS(QAbstractItemModel)
namespace QmlDesigner {
class NavigatorView;
class NavigatorSearchWidget;
class NavigatorWidget: public QFrame
{
@@ -59,6 +60,8 @@ public:
void setDragType(const QByteArray &type);
QByteArray dragType() const;
void clearSearch();
signals:
void leftButtonClicked();
void rightButtonClicked();
@@ -66,6 +69,7 @@ signals:
void downButtonClicked();
void filterToggled(bool);
void reverseOrderToggled(bool);
void textFilterChanged(const QString &name);
protected:
void dragEnterEvent(QDragEnterEvent *dragEnterEvent) override;
@@ -77,6 +81,7 @@ private:
NavigatorTreeView *m_treeView;
QPointer<NavigatorView> m_navigatorView;
QByteArray m_dragType;
NavigatorSearchWidget *m_searchWidget;
};
}

View File

@@ -680,6 +680,8 @@ Project {
"navigator/nameitemdelegate.cpp",
"navigator/nameitemdelegate.h",
"navigator/navigator.qrc",
"navigator/navigatorsearchwidget.cpp",
"navigator/navigatorsearchwidget.h",
"navigator/navigatortreemodel.cpp",
"navigator/navigatortreemodel.h",
"navigator/navigatortreeview.cpp",