diff options
author | Jochen Becher <jochen_becher@gmx.de> | 2024-04-16 15:22:23 +0200 |
---|---|---|
committer | Jochen Becher <jochen_becher@gmx.de> | 2024-04-17 07:41:45 +0000 |
commit | f057c1af70d7d54cd03182b2831bd3a61f01f42b (patch) | |
tree | b16ef839d8e8a5b18ac8bdde3abae348dfadc88f /src/libs/modelinglib | |
parent | db52bf779ce614789015423cc2cab52f2e58e0fb (diff) |
ModelEditor: Add model tree filter
A new button in the top bar opens a filter for the model tree which
allows quick search for model elements
Change-Id: Ibfe229890cb79e64fdbbe62f74681add102b5ccf
Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io>
Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
Diffstat (limited to 'src/libs/modelinglib')
11 files changed, 850 insertions, 0 deletions
diff --git a/src/libs/modelinglib/CMakeLists.txt b/src/libs/modelinglib/CMakeLists.txt index afea6c1699..1189ed35b3 100644 --- a/src/libs/modelinglib/CMakeLists.txt +++ b/src/libs/modelinglib/CMakeLists.txt @@ -126,6 +126,7 @@ add_qtc_library(Modeling qmt/model/mrelation.cpp qmt/model/mrelation.h qmt/model/msourceexpansion.cpp qmt/model/msourceexpansion.h qmt/model/mvisitor.h + qmt/model_ui/modeltreefilterdata.h qmt/model_ui/modeltreefilterdata.cpp qmt/model_ui/modeltreeviewinterface.h qmt/model_ui/sortedtreemodel.cpp qmt/model_ui/sortedtreemodel.h qmt/model_ui/stereotypescontroller.cpp qmt/model_ui/stereotypescontroller.h @@ -134,6 +135,8 @@ add_qtc_library(Modeling qmt/model_widgets_ui/addrelatedelementsdialog.h qmt/model_widgets_ui/addrelatedelementsdialog.cpp qmt/model_widgets_ui/addrelatedelementsdialog.ui qmt/model_widgets_ui/classmembersedit.cpp qmt/model_widgets_ui/classmembersedit.h + qmt/model_widgets_ui/modeltreefilter.h qmt/model_widgets_ui/modeltreefilter.cpp + qmt/model_widgets_ui/modeltreefilter.ui qmt/model_widgets_ui/modeltreeview.cpp qmt/model_widgets_ui/modeltreeview.h qmt/model_widgets_ui/palettebox.cpp qmt/model_widgets_ui/palettebox.h qmt/model_widgets_ui/propertiesview.cpp qmt/model_widgets_ui/propertiesview.h diff --git a/src/libs/modelinglib/modelinglib.qbs b/src/libs/modelinglib/modelinglib.qbs index d4edfadf09..fd137e603d 100644 --- a/src/libs/modelinglib/modelinglib.qbs +++ b/src/libs/modelinglib/modelinglib.qbs @@ -238,6 +238,8 @@ QtcLibrary { "model_controller/mselection.h", "model_controller/mvoidvisitor.cpp", "model_controller/mvoidvisitor.h", + "model_ui/modeltreefilterdata.cpp", + "model_ui/modeltreefilterdata.h", "model_ui/modeltreeviewinterface.h", "model_ui/sortedtreemodel.cpp", "model_ui/sortedtreemodel.h", @@ -252,6 +254,9 @@ QtcLibrary { "model_widgets_ui/addrelatedelementsdialog.ui", "model_widgets_ui/classmembersedit.cpp", "model_widgets_ui/classmembersedit.h", + "model_widgets_ui/modeltreefilter.cpp", + "model_widgets_ui/modeltreefilter.h", + "model_widgets_ui/modeltreefilter.ui", "model_widgets_ui/modeltreeview.cpp", "model_widgets_ui/modeltreeview.h", "model_widgets_ui/palettebox.cpp", diff --git a/src/libs/modelinglib/qmt/model_ui/modeltreefilterdata.cpp b/src/libs/modelinglib/qmt/model_ui/modeltreefilterdata.cpp new file mode 100644 index 0000000000..ba411690f5 --- /dev/null +++ b/src/libs/modelinglib/qmt/model_ui/modeltreefilterdata.cpp @@ -0,0 +1,43 @@ +// Copyright (C) 2018 Jochen Becher +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "modeltreefilterdata.h" + +namespace qmt { + +void ModelTreeViewData::setShowRelations(bool newShowRelations) +{ + m_showRelations = newShowRelations; +} + +void ModelTreeViewData::setShowDiagramElements(bool newShowDiagramElements) +{ + m_showDiagramElements = newShowDiagramElements; +} + +void ModelTreeFilterData::setType(Type newType) +{ + m_type = newType; +} + +void ModelTreeFilterData::setCustomId(const QString &newCustomId) +{ + m_customId = newCustomId; +} + +void ModelTreeFilterData::setStereotypes(const QStringList &newStereotypes) +{ + m_stereotypes = newStereotypes; +} + +void ModelTreeFilterData::setName(const QString &newName) +{ + m_name = newName; +} + +void ModelTreeFilterData::setDirection(Direction newDirection) +{ + m_direction = newDirection; +} + +} // namespace qmt diff --git a/src/libs/modelinglib/qmt/model_ui/modeltreefilterdata.h b/src/libs/modelinglib/qmt/model_ui/modeltreefilterdata.h new file mode 100644 index 0000000000..3af018fefd --- /dev/null +++ b/src/libs/modelinglib/qmt/model_ui/modeltreefilterdata.h @@ -0,0 +1,72 @@ +// Copyright (C) 2018 Jochen Becher +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#pragma once + +#include <QString> +#include <QStringList> + +namespace qmt { + +class ModelTreeViewData +{ +public: + + bool showRelations() const { return m_showRelations; } + void setShowRelations(bool newShowRelations); + + bool showDiagramElements() const { return m_showDiagramElements; } + void setShowDiagramElements(bool newShowDiagramElements); + +private: + bool m_showRelations = true; + bool m_showDiagramElements = false; +}; + +class ModelTreeFilterData +{ +public: + enum class Type { + Any, + Package, + Component, + Class, + Diagram, + Item, + Dependency, + Association, + Inheritance, + Connection + }; + + enum class Direction { + Any, + Outgoing, + Incoming, + Bidirectional + }; + + Type type() const { return m_type; } + void setType(Type newType); + + QString customId() const { return m_customId; } + void setCustomId(const QString &newCustomId); + + QStringList stereotypes() const { return m_stereotypes; } + void setStereotypes(const QStringList &newStereotypes); + + QString name() const { return m_name; } + void setName(const QString &newName); + + Direction direction() const { return m_direction; } + void setDirection(Direction newDirection); + +private: + Type m_type = Type::Any; + QString m_customId; + QStringList m_stereotypes; + QString m_name; + Direction m_direction = Direction::Any; +}; + +} // namespace qmt diff --git a/src/libs/modelinglib/qmt/model_ui/sortedtreemodel.cpp b/src/libs/modelinglib/qmt/model_ui/sortedtreemodel.cpp index 972c2f9c00..e69e1635a7 100644 --- a/src/libs/modelinglib/qmt/model_ui/sortedtreemodel.cpp +++ b/src/libs/modelinglib/qmt/model_ui/sortedtreemodel.cpp @@ -3,14 +3,203 @@ #include "sortedtreemodel.h" +#include "qmt/model/massociation.h" +#include "qmt/model/mcanvasdiagram.h" +#include "qmt/model/mclass.h" +#include "qmt/model/mcomponent.h" +#include "qmt/model/mconnection.h" +#include "qmt/model/mdependency.h" +#include "qmt/model/minheritance.h" +#include "qmt/model/mitem.h" +#include "qmt/model/mpackage.h" +#include "qmt/model/mconstvisitor.h" #include "treemodel.h" namespace qmt { +namespace { + +class Filter : public MConstVisitor { +public: + + void setModelTreeViewData(const ModelTreeViewData *viewData) + { + m_viewData = viewData; + } + + void setModelTreeFilterData(const ModelTreeFilterData *filterData) + { + m_filterData = filterData; + } + + bool keep() const { return m_keep; } + + void visitMElement(const MElement *element) override + { + if (!m_filterData->stereotypes().isEmpty()) { + const QStringList stereotypes = element->stereotypes(); + bool containsElementStereotype = std::any_of( + stereotypes.constBegin(), stereotypes.constEnd(), + [&](const QString &s) { return m_filterData->stereotypes().contains(s); }); + if (!containsElementStereotype) { + m_keep = false; + return; + } + } + } + + void visitMObject(const MObject *object) override + { + if (!m_filterData->name().isEmpty() && m_filterData->name() != object->name()) + m_keep = false; + else + visitMElement(object); + } + + void visitMPackage(const MPackage *package) override + { + if (m_filterData->type() != ModelTreeFilterData::Type::Any + && m_filterData->type() != ModelTreeFilterData::Type::Package) + { + m_keep = false; + } else { + visitMObject(package); + } + } + + void visitMClass(const MClass *klass) override + { + if (m_filterData->type() != ModelTreeFilterData::Type::Any + && m_filterData->type() != ModelTreeFilterData::Type::Class) + { + m_keep = false; + } else { + visitMObject(klass); + } + } + + void visitMComponent(const MComponent *component) override + { + if (m_filterData->type() != ModelTreeFilterData::Type::Any + && m_filterData->type() != ModelTreeFilterData::Type::Component) + { + m_keep = false; + } else { + visitMObject(component); + } + } + + void visitMDiagram(const MDiagram *diagram) override + { + if (m_filterData->type() != ModelTreeFilterData::Type::Any + && m_filterData->type() != ModelTreeFilterData::Type::Diagram) + { + m_keep = false; + } else { + visitMObject(diagram); + } + } + + void visitMCanvasDiagram(const MCanvasDiagram *diagram) override + { + visitMDiagram(diagram); + } + + void visitMItem(const MItem *item) override + { + if (m_filterData->type() != ModelTreeFilterData::Type::Any + && m_filterData->type() != ModelTreeFilterData::Type::Item) + { + m_keep = false; + } else { + visitMObject(item); + } + } + + void visitMRelation(const MRelation *relation) override + { + if (!m_viewData->showRelations()) + m_keep = false; + else if (!m_filterData->name().isEmpty() && m_filterData->name() != relation->name()) + m_keep = false; + else + visitMElement(relation); + } + + void visitMDependency(const MDependency *dependency) override + { + if (m_filterData->type() != ModelTreeFilterData::Type::Any + && m_filterData->type() != ModelTreeFilterData::Type::Dependency) + { + m_keep = false; + } else { + switch (m_filterData->direction()) { + case ModelTreeFilterData::Direction::Any: + break; + case ModelTreeFilterData::Direction::Outgoing: + if (dependency->direction() != MDependency::AToB) + m_keep = false; + break; + case ModelTreeFilterData::Direction::Incoming: + if (dependency->direction() != MDependency::BToA) + m_keep = false; + break; + case ModelTreeFilterData::Direction::Bidirectional: + if (dependency->direction() != MDependency::Bidirectional) + m_keep = false; + break; + } + if (m_keep) + visitMRelation(dependency); + } + } + + void visitMInheritance(const MInheritance *inheritance) override + { + if (m_filterData->type() != ModelTreeFilterData::Type::Any + && m_filterData->type() != ModelTreeFilterData::Type::Inheritance) + { + m_keep = false; + } else { + visitMRelation(inheritance); + } + } + + void visitMAssociation(const MAssociation *association) override + { + if (m_filterData->type() != ModelTreeFilterData::Type::Any + && m_filterData->type() != ModelTreeFilterData::Type::Association) + { + m_keep = false; + } else { + visitMRelation(association); + } + } + + void visitMConnection(const MConnection *connection) override + { + if (m_filterData->type() != ModelTreeFilterData::Type::Any + && m_filterData->type() != ModelTreeFilterData::Type::Connection) + { + m_keep = false; + } else { + visitMRelation(connection); + } + } + +private: + const ModelTreeViewData *m_viewData = nullptr; + const ModelTreeFilterData *m_filterData = nullptr; + bool m_keep = true; +}; + +} + SortedTreeModel::SortedTreeModel(QObject *parent) : QSortFilterProxyModel(parent) { setDynamicSortFilter(false); + setRecursiveFilteringEnabled(true); setSortCaseSensitivity(Qt::CaseInsensitive); m_delayedSortTimer.setSingleShot(true); @@ -33,6 +222,37 @@ void SortedTreeModel::setTreeModel(TreeModel *treeModel) startDelayedSortTimer(); } +void SortedTreeModel::setModelTreeViewData(const ModelTreeViewData &viewData) +{ + m_modelTreeViewData = viewData; + beginResetModel(); + endResetModel(); + startDelayedSortTimer(); +} + +void SortedTreeModel::setModelTreeFilterData(const ModelTreeFilterData &filterData) +{ + m_modelTreeViewFilterData = filterData; + beginResetModel(); + endResetModel(); + startDelayedSortTimer(); +} + +bool SortedTreeModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const +{ + QModelIndex index = sourceModel()->index(source_row, 0, source_parent); + MElement *element = m_treeModel->element(index); + if (element) { + Filter filter; + filter.setModelTreeViewData(&m_modelTreeViewData); + filter.setModelTreeFilterData(&m_modelTreeViewFilterData); + element->accept(&filter); + if (!filter.keep()) + return false; + } + return true; +} + bool SortedTreeModel::lessThan(const QModelIndex &left, const QModelIndex &right) const { TreeModel::ItemType leftItemType = TreeModel::ItemType(sourceModel()->data(left, TreeModel::RoleItemType).toInt()); diff --git a/src/libs/modelinglib/qmt/model_ui/sortedtreemodel.h b/src/libs/modelinglib/qmt/model_ui/sortedtreemodel.h index 0c01cf7de7..797a321132 100644 --- a/src/libs/modelinglib/qmt/model_ui/sortedtreemodel.h +++ b/src/libs/modelinglib/qmt/model_ui/sortedtreemodel.h @@ -4,6 +4,7 @@ #pragma once #include "qmt/infrastructure/qmt_global.h" +#include "qmt/model_ui/modeltreefilterdata.h" #include <QSortFilterProxyModel> #include <QTimer> @@ -21,7 +22,11 @@ public: TreeModel *treeModel() const { return m_treeModel; } void setTreeModel(TreeModel *treeModel); + void setModelTreeViewData(const ModelTreeViewData &viewData); + void setModelTreeFilterData(const ModelTreeFilterData &filterData); + protected: + bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; bool lessThan(const QModelIndex &left, const QModelIndex &right) const override; private: @@ -32,6 +37,8 @@ private: void startDelayedSortTimer(); TreeModel *m_treeModel = nullptr; + ModelTreeViewData m_modelTreeViewData; + ModelTreeFilterData m_modelTreeViewFilterData; QTimer m_delayedSortTimer; }; diff --git a/src/libs/modelinglib/qmt/model_widgets_ui/modeltreefilter.cpp b/src/libs/modelinglib/qmt/model_widgets_ui/modeltreefilter.cpp new file mode 100644 index 0000000000..59a61df3c4 --- /dev/null +++ b/src/libs/modelinglib/qmt/model_widgets_ui/modeltreefilter.cpp @@ -0,0 +1,100 @@ +// Copyright (C) 2018 Jochen Becher +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "modeltreefilter.h" +#include "ui_modeltreefilter.h" + +#include <QStringListModel> + +namespace qmt { + +class ModelTreeFilter::Private { +public: + QStringListModel m_typeModel; + QStringListModel m_stereotypesModel; + QStringListModel m_directionModel; +}; + +ModelTreeFilter::ModelTreeFilter(QWidget *parent) : + QWidget(parent), + ui(new Ui::ModelTreeFilter), + d(new Private) +{ + ui->setupUi(this); + connect(ui->resetViewButton, &QPushButton::clicked, this, &ModelTreeFilter::resetView); + connect(ui->relationsCheckBox, &QCheckBox::clicked, this, &ModelTreeFilter::onViewChanged); + connect(ui->diagramElementsCheckBox, &QCheckBox::clicked, this, &ModelTreeFilter::onViewChanged); + connect(ui->clearFilterButton, &QPushButton::clicked, this, &ModelTreeFilter::clearFilter); + connect(ui->typeComboBox, &QComboBox::currentIndexChanged, this, [this](int index) { + ui->directionComboBox->setDisabled(index != (int) ModelTreeFilterData::Type::Dependency); + }); + connect(ui->typeComboBox, &QComboBox::currentIndexChanged, this, &ModelTreeFilter::onFilterChanged); + connect(ui->stereotypesComboBox, &QComboBox::currentTextChanged, this, &ModelTreeFilter::onFilterChanged); + connect(ui->nameLineEdit, &QLineEdit::textChanged, this, &ModelTreeFilter::onFilterChanged); + connect(ui->directionComboBox, &QComboBox::currentTextChanged, this, &ModelTreeFilter::onFilterChanged); + setupFilter(); + resetView(); + clearFilter(); +} + +ModelTreeFilter::~ModelTreeFilter() +{ + delete d; + delete ui; +} + +void ModelTreeFilter::setupFilter() +{ + QStringList types = {"Any", "Package", "Component", "Class", "Diagram", "Item", + "Dependency", "Association", "Inheritance", "Connection"}; + d->m_typeModel.setStringList(types); + ui->typeComboBox->setModel(&d->m_typeModel); + + QStringList stereotypes = { }; + d->m_stereotypesModel.setStringList(stereotypes); + ui->stereotypesComboBox->setModel(&d->m_stereotypesModel); + + QStringList directions = {"Any", "Outgoing (->)", "Incoming (<-)", "Bidirectional (<->)"}; + d->m_directionModel.setStringList(directions); + ui->directionComboBox->setModel(&d->m_directionModel); +} + +void ModelTreeFilter::resetView() +{ + ui->relationsCheckBox->setChecked(true); + ui->diagramElementsCheckBox->setChecked(false); + onViewChanged(); +} + +void ModelTreeFilter::clearFilter() +{ + ui->typeComboBox->setCurrentIndex(0); + ui->stereotypesComboBox->clearEditText(); + ui->nameLineEdit->clear(); + ui->directionComboBox->setCurrentIndex(0); + onFilterChanged(); +} + +void ModelTreeFilter::onViewChanged() +{ + ModelTreeViewData modelTreeViewData; + modelTreeViewData.setShowRelations(ui->relationsCheckBox->isChecked()); + modelTreeViewData.setShowDiagramElements(ui->diagramElementsCheckBox->isChecked()); + emit viewDataChanged(modelTreeViewData); +} + +void ModelTreeFilter::onFilterChanged() +{ + ModelTreeFilterData modelTreeFilterData; + modelTreeFilterData.setType((ModelTreeFilterData::Type) ui->typeComboBox->currentIndex()); + modelTreeFilterData.setCustomId(QString()); + modelTreeFilterData.setStereotypes(ui->stereotypesComboBox->currentText().split(',', Qt::SkipEmptyParts)); + modelTreeFilterData.setName(ui->nameLineEdit->text().trimmed()); + if (modelTreeFilterData.type() == ModelTreeFilterData::Type::Dependency) + modelTreeFilterData.setDirection((ModelTreeFilterData::Direction) ui->directionComboBox->currentIndex()); + else + modelTreeFilterData.setDirection(ModelTreeFilterData::Direction::Any); + emit filterDataChanged(modelTreeFilterData); +} + +} // namespace qmt diff --git a/src/libs/modelinglib/qmt/model_widgets_ui/modeltreefilter.h b/src/libs/modelinglib/qmt/model_widgets_ui/modeltreefilter.h new file mode 100644 index 0000000000..323a75f17f --- /dev/null +++ b/src/libs/modelinglib/qmt/model_widgets_ui/modeltreefilter.h @@ -0,0 +1,44 @@ +// Copyright (C) 2018 Jochen Becher +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#pragma once + +#include "qmt/infrastructure/qmt_global.h" +#include "qmt/model_ui/modeltreefilterdata.h" + +#include <QWidget> + +namespace qmt { + +namespace Ui { +class ModelTreeFilter; +} + +class QMT_EXPORT ModelTreeFilter : public QWidget +{ + Q_OBJECT + class Private; + +public: + explicit ModelTreeFilter(QWidget *parent = nullptr); + ~ModelTreeFilter(); + +signals: + void viewDataChanged(const ModelTreeViewData &modelTreeViewData); + void filterDataChanged(const ModelTreeFilterData &modelTreeFilterData); + +private: + + void setupFilter(); + void resetView(); + void clearFilter(); + void onViewChanged(); + void onFilterChanged(); + +private: + Ui::ModelTreeFilter *ui = nullptr; + Private *d = nullptr; +}; + + +} // namespace qmt diff --git a/src/libs/modelinglib/qmt/model_widgets_ui/modeltreefilter.ui b/src/libs/modelinglib/qmt/model_widgets_ui/modeltreefilter.ui new file mode 100644 index 0000000000..15cdd4437b --- /dev/null +++ b/src/libs/modelinglib/qmt/model_widgets_ui/modeltreefilter.ui @@ -0,0 +1,312 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>qmt::ModelTreeFilter</class> + <widget class="QWidget" name="qmt::ModelTreeFilter"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>307</width> + <height>370</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,0,0,1,0"> + <property name="spacing"> + <number>6</number> + </property> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>9</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <widget class="QWidget" name="viewWidget" native="true"> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <property name="leftMargin"> + <number>9</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>9</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QLabel" name="viewLabel"> + <property name="font"> + <font> + <bold>true</bold> + </font> + </property> + <property name="text"> + <string>View</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="resetViewButton"> + <property name="font"> + <font> + <bold>false</bold> + </font> + </property> + <property name="text"> + <string>Reset</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QCheckBox" name="relationsCheckBox"> + <property name="font"> + <font> + <bold>false</bold> + </font> + </property> + <property name="text"> + <string>Relations</string> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="diagramElementsCheckBox"> + <property name="maximumSize"> + <size> + <width>16777215</width> + <height>0</height> + </size> + </property> + <property name="font"> + <font> + <bold>false</bold> + </font> + </property> + <property name="text"> + <string>Diagram Elements</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <spacer name="verticalSpacer_3"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>0</width> + <height>10</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="Line" name="line"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="frameShadow"> + <enum>QFrame::Plain</enum> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + <item> + <widget class="QWidget" name="filterWidget" native="true"> + <layout class="QVBoxLayout" name="verticalLayout_3" stretch="0,0,1"> + <property name="leftMargin"> + <number>9</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>9</number> + </property> + <property name="bottomMargin"> + <number>0</number> + </property> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QLabel" name="filterLabel"> + <property name="font"> + <font> + <bold>true</bold> + </font> + </property> + <property name="text"> + <string>Filter</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="clearFilterButton"> + <property name="font"> + <font> + <bold>false</bold> + </font> + </property> + <property name="text"> + <string>Clear</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <spacer name="verticalSpacer_4"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>0</width> + <height>10</height> + </size> + </property> + </spacer> + </item> + <item> + <layout class="QFormLayout" name="filterGroup"> + <item row="0" column="0"> + <widget class="QLabel" name="typeLabel"> + <property name="font"> + <font> + <bold>false</bold> + </font> + </property> + <property name="text"> + <string>Type:</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="stereotypesLabel"> + <property name="font"> + <font> + <bold>false</bold> + </font> + </property> + <property name="text"> + <string>Stereotypes:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QComboBox" name="typeComboBox"/> + </item> + <item row="1" column="1"> + <widget class="QComboBox" name="stereotypesComboBox"> + <property name="editable"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="nameLabel"> + <property name="text"> + <string>Name:</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLineEdit" name="nameLineEdit"/> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="directionLabel"> + <property name="font"> + <font> + <bold>false</bold> + </font> + </property> + <property name="text"> + <string>Direction:</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QComboBox" name="directionComboBox"/> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="Line" name="line_2"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="frameShadow"> + <enum>QFrame::Plain</enum> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.cpp b/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.cpp index dbcdd9fcc0..875b1fa105 100644 --- a/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.cpp +++ b/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.cpp @@ -71,6 +71,46 @@ void ModelTreeView::setElementTasks(IElementTasks *elementTasks) m_elementTasks = elementTasks; } +static void StoreStatus(QTreeView *view, QSortFilterProxyModel *model, const QModelIndex &parent, QVector<QModelIndex> &expanded_items) +{ + for (int index = 0; index < model->rowCount(parent); ++index) { + auto proxy_index = model->index(index, 0, parent); + if (view->isExpanded(proxy_index)) { + auto source_index = model->mapToSource(proxy_index); + expanded_items.append(source_index); + } + StoreStatus(view, model, proxy_index, expanded_items); + } +} + +static void ApplyStatus(QTreeView *view, QSortFilterProxyModel *model, QVector<QModelIndex> &expanded_items) +{ + for (auto source_index : expanded_items) { + auto proxy_index = model->mapFromSource(source_index); + view->setExpanded(proxy_index, true); + } +} + +void ModelTreeView::setModelTreeViewData(const ModelTreeViewData &viewData) +{ + if (m_sortedTreeModel) { + QVector<QModelIndex> expanded_items; + StoreStatus(this, m_sortedTreeModel, QModelIndex(), expanded_items); + m_sortedTreeModel->setModelTreeViewData(viewData); + ApplyStatus(this, m_sortedTreeModel, expanded_items); + } +} + +void ModelTreeView::setModelTreeFilterData(const ModelTreeFilterData &filterData) +{ + if (m_sortedTreeModel) { + QVector<QModelIndex> expanded_items; + StoreStatus(this, m_sortedTreeModel, QModelIndex(), expanded_items); + m_sortedTreeModel->setModelTreeFilterData(filterData); + ApplyStatus(this, m_sortedTreeModel, expanded_items); + } +} + QModelIndex ModelTreeView::mapToSourceModelIndex(const QModelIndex &index) const { return m_sortedTreeModel->mapToSource(index); diff --git a/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.h b/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.h index 0c07cb0372..e5537644a3 100644 --- a/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.h +++ b/src/libs/modelinglib/qmt/model_widgets_ui/modeltreeview.h @@ -5,6 +5,7 @@ #include "qmt/infrastructure/qmt_global.h" #include "qmt/model_ui/modeltreeviewinterface.h" +#include "qmt/model_ui/modeltreefilterdata.h" #include <QElapsedTimer> #include <QTreeView> @@ -32,6 +33,9 @@ public: void setTreeModel(SortedTreeModel *model); void setElementTasks(IElementTasks *elementTasks); + void setModelTreeViewData(const ModelTreeViewData &viewData); + void setModelTreeFilterData(const ModelTreeFilterData &filterData); + QModelIndex mapToSourceModelIndex(const QModelIndex &index) const; void selectFromSourceModelIndex(const QModelIndex &index); |