forked from qt-creator/qt-creator
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:
@@ -276,6 +276,7 @@ extend_qtc_plugin(QmlDesigner
|
|||||||
nameitemdelegate.cpp nameitemdelegate.h
|
nameitemdelegate.cpp nameitemdelegate.h
|
||||||
navigator.qrc
|
navigator.qrc
|
||||||
navigatormodelinterface.h
|
navigatormodelinterface.h
|
||||||
|
navigatorsearchwidget.cpp navigatorsearchwidget.h
|
||||||
navigatortreemodel.cpp navigatortreemodel.h
|
navigatortreemodel.cpp navigatortreemodel.h
|
||||||
navigatortreeview.cpp navigatortreeview.h
|
navigatortreeview.cpp navigatortreeview.h
|
||||||
navigatorview.cpp navigatorview.h
|
navigatorview.cpp navigatorview.h
|
||||||
|
@@ -45,6 +45,7 @@ public:
|
|||||||
virtual void notifyModelNodesMoved(const QList<ModelNode> &modelNodes) = 0;
|
virtual void notifyModelNodesMoved(const QList<ModelNode> &modelNodes) = 0;
|
||||||
virtual void notifyIconsChanged() = 0;
|
virtual void notifyIconsChanged() = 0;
|
||||||
virtual void setFilter(bool showObjects) = 0;
|
virtual void setFilter(bool showObjects) = 0;
|
||||||
|
virtual void setNameFilter(const QString &filter) = 0;
|
||||||
virtual void setOrder(bool reverse) = 0;
|
virtual void setOrder(bool reverse) = 0;
|
||||||
virtual void resetModel() = 0;
|
virtual void resetModel() = 0;
|
||||||
};
|
};
|
||||||
|
@@ -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
|
@@ -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
|
@@ -324,14 +324,25 @@ QList<ModelNode> NavigatorTreeModel::filteredList(const NodeListProperty &proper
|
|||||||
return it.value();
|
return it.value();
|
||||||
|
|
||||||
QList<ModelNode> list;
|
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) {
|
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();
|
const bool value = QmlItemNode::isValidQmlItemNode(arg) || NodeHints::fromModelNode(arg).visibleInNavigator();
|
||||||
return value;
|
return value;
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
list = property.toModelNodeList();
|
list = nameFilteredList;
|
||||||
}
|
}
|
||||||
|
|
||||||
appendForcedNodes(property, list);
|
appendForcedNodes(property, list);
|
||||||
@@ -1222,6 +1233,35 @@ void NavigatorTreeModel::setFilter(bool showOnlyVisibleItems)
|
|||||||
resetModel();
|
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)
|
void NavigatorTreeModel::setOrder(bool reverseItemOrder)
|
||||||
{
|
{
|
||||||
m_reverseItemOrder = reverseItemOrder;
|
m_reverseItemOrder = reverseItemOrder;
|
||||||
|
@@ -101,6 +101,7 @@ public:
|
|||||||
void notifyModelNodesMoved(const QList<ModelNode> &modelNodes) override;
|
void notifyModelNodesMoved(const QList<ModelNode> &modelNodes) override;
|
||||||
void notifyIconsChanged() override;
|
void notifyIconsChanged() override;
|
||||||
void setFilter(bool showOnlyVisibleItems) override;
|
void setFilter(bool showOnlyVisibleItems) override;
|
||||||
|
void setNameFilter(const QString &filter) override;
|
||||||
void setOrder(bool reverseItemOrder) override;
|
void setOrder(bool reverseItemOrder) override;
|
||||||
void resetModel() override;
|
void resetModel() override;
|
||||||
|
|
||||||
@@ -140,6 +141,8 @@ private:
|
|||||||
bool m_showOnlyVisibleItems = true;
|
bool m_showOnlyVisibleItems = true;
|
||||||
bool m_reverseItemOrder = false;
|
bool m_reverseItemOrder = false;
|
||||||
DesignerActionManager *m_actionManager = nullptr;
|
DesignerActionManager *m_actionManager = nullptr;
|
||||||
|
QString m_nameFilter;
|
||||||
|
QList<ModelNode> m_nameFilteredList;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
@@ -152,6 +152,8 @@ void NavigatorView::modelAttached(Model *model)
|
|||||||
treeView->setIndentation(20);
|
treeView->setIndentation(20);
|
||||||
|
|
||||||
m_currentModelInterface->setFilter(false);
|
m_currentModelInterface->setFilter(false);
|
||||||
|
m_currentModelInterface->setNameFilter("");
|
||||||
|
m_widget->clearSearch();
|
||||||
|
|
||||||
QTimer::singleShot(0, this, [this, treeView]() {
|
QTimer::singleShot(0, this, [this, treeView]() {
|
||||||
m_currentModelInterface->setFilter(
|
m_currentModelInterface->setFilter(
|
||||||
@@ -576,6 +578,12 @@ void NavigatorView::reverseOrderToggled(bool flag)
|
|||||||
DesignerSettings::setValue(DesignerSettingsKey::NAVIGATOR_REVERSE_ITEM_ORDER, 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*/)
|
void NavigatorView::changeSelection(const QItemSelection & /*newSelection*/, const QItemSelection &/*deselected*/)
|
||||||
{
|
{
|
||||||
if (m_blockSelectionChangedSignal)
|
if (m_blockSelectionChangedSignal)
|
||||||
@@ -704,6 +712,8 @@ void NavigatorView::setupWidget()
|
|||||||
connect(m_widget.data(), &NavigatorWidget::filterToggled, this, &NavigatorView::filterToggled);
|
connect(m_widget.data(), &NavigatorWidget::filterToggled, this, &NavigatorView::filterToggled);
|
||||||
connect(m_widget.data(), &NavigatorWidget::reverseOrderToggled, this, &NavigatorView::reverseOrderToggled);
|
connect(m_widget.data(), &NavigatorWidget::reverseOrderToggled, this, &NavigatorView::reverseOrderToggled);
|
||||||
|
|
||||||
|
connect(m_widget.data(), &NavigatorWidget::textFilterChanged, this, &NavigatorView::textFilterChanged);
|
||||||
|
|
||||||
#ifndef QMLDESIGNER_TEST
|
#ifndef QMLDESIGNER_TEST
|
||||||
const QString fontName = "qtds_propertyIconFont.ttf";
|
const QString fontName = "qtds_propertyIconFont.ttf";
|
||||||
const QSize size = QSize(28, 28);
|
const QSize size = QSize(28, 28);
|
||||||
|
@@ -118,6 +118,8 @@ private:
|
|||||||
void filterToggled(bool);
|
void filterToggled(bool);
|
||||||
void reverseOrderToggled(bool);
|
void reverseOrderToggled(bool);
|
||||||
|
|
||||||
|
void textFilterChanged(const QString &text);
|
||||||
|
|
||||||
protected: //functions
|
protected: //functions
|
||||||
QTreeView *treeWidget() const;
|
QTreeView *treeWidget() const;
|
||||||
NavigatorTreeModel *treeModel();
|
NavigatorTreeModel *treeModel();
|
||||||
|
@@ -23,6 +23,7 @@
|
|||||||
**
|
**
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "navigatorsearchwidget.h"
|
||||||
#include "navigatorwidget.h"
|
#include "navigatorwidget.h"
|
||||||
#include "navigatorview.h"
|
#include "navigatorview.h"
|
||||||
|
|
||||||
@@ -160,6 +161,10 @@ QToolBar *NavigatorWidget::createToolBar()
|
|||||||
for (auto toolButton : buttons)
|
for (auto toolButton : buttons)
|
||||||
toolBar->addWidget(toolButton);
|
toolBar->addWidget(toolButton);
|
||||||
|
|
||||||
|
m_searchWidget = new NavigatorSearchWidget();
|
||||||
|
connect(m_searchWidget, &NavigatorSearchWidget::textChanged, this, &NavigatorWidget::textFilterChanged);
|
||||||
|
toolBar->addWidget(m_searchWidget);
|
||||||
|
|
||||||
return toolBar;
|
return toolBar;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,4 +216,9 @@ QByteArray NavigatorWidget::dragType() const
|
|||||||
return m_dragType;
|
return m_dragType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NavigatorWidget::clearSearch()
|
||||||
|
{
|
||||||
|
m_searchWidget->clear();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -39,6 +39,7 @@ QT_FORWARD_DECLARE_CLASS(QAbstractItemModel)
|
|||||||
namespace QmlDesigner {
|
namespace QmlDesigner {
|
||||||
|
|
||||||
class NavigatorView;
|
class NavigatorView;
|
||||||
|
class NavigatorSearchWidget;
|
||||||
|
|
||||||
class NavigatorWidget: public QFrame
|
class NavigatorWidget: public QFrame
|
||||||
{
|
{
|
||||||
@@ -59,6 +60,8 @@ public:
|
|||||||
void setDragType(const QByteArray &type);
|
void setDragType(const QByteArray &type);
|
||||||
QByteArray dragType() const;
|
QByteArray dragType() const;
|
||||||
|
|
||||||
|
void clearSearch();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void leftButtonClicked();
|
void leftButtonClicked();
|
||||||
void rightButtonClicked();
|
void rightButtonClicked();
|
||||||
@@ -66,6 +69,7 @@ signals:
|
|||||||
void downButtonClicked();
|
void downButtonClicked();
|
||||||
void filterToggled(bool);
|
void filterToggled(bool);
|
||||||
void reverseOrderToggled(bool);
|
void reverseOrderToggled(bool);
|
||||||
|
void textFilterChanged(const QString &name);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void dragEnterEvent(QDragEnterEvent *dragEnterEvent) override;
|
void dragEnterEvent(QDragEnterEvent *dragEnterEvent) override;
|
||||||
@@ -77,6 +81,7 @@ private:
|
|||||||
NavigatorTreeView *m_treeView;
|
NavigatorTreeView *m_treeView;
|
||||||
QPointer<NavigatorView> m_navigatorView;
|
QPointer<NavigatorView> m_navigatorView;
|
||||||
QByteArray m_dragType;
|
QByteArray m_dragType;
|
||||||
|
NavigatorSearchWidget *m_searchWidget;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -680,6 +680,8 @@ Project {
|
|||||||
"navigator/nameitemdelegate.cpp",
|
"navigator/nameitemdelegate.cpp",
|
||||||
"navigator/nameitemdelegate.h",
|
"navigator/nameitemdelegate.h",
|
||||||
"navigator/navigator.qrc",
|
"navigator/navigator.qrc",
|
||||||
|
"navigator/navigatorsearchwidget.cpp",
|
||||||
|
"navigator/navigatorsearchwidget.h",
|
||||||
"navigator/navigatortreemodel.cpp",
|
"navigator/navigatortreemodel.cpp",
|
||||||
"navigator/navigatortreemodel.h",
|
"navigator/navigatortreemodel.h",
|
||||||
"navigator/navigatortreeview.cpp",
|
"navigator/navigatortreeview.cpp",
|
||||||
|
Reference in New Issue
Block a user