aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/modelinglib
diff options
context:
space:
mode:
authorJochen Becher <jochen_becher@gmx.de>2024-04-16 13:17:14 +0200
committerJochen Becher <jochen_becher@gmx.de>2024-04-16 12:13:03 +0000
commita296157f58a5fa31861daa359b2ef8998d06c8a6 (patch)
treeeea64fb53d725e960226b7ea8a868020eed3c768 /src/libs/modelinglib
parent5b9f2d5b3efcc118c6c313d7f65ce69d036d682b (diff)
ModelEditor: Add dialog for adding related elements
Change-Id: Iae832885278472bb42a588fc97967ae5ffad6b71 Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io> Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
Diffstat (limited to 'src/libs/modelinglib')
-rw-r--r--src/libs/modelinglib/CMakeLists.txt2
-rw-r--r--src/libs/modelinglib/modelinglib.qbs3
-rw-r--r--src/libs/modelinglib/qmt/diagram_scene/items/objectitem.cpp6
-rw-r--r--src/libs/modelinglib/qmt/model_widgets_ui/addrelatedelementsdialog.cpp378
-rw-r--r--src/libs/modelinglib/qmt/model_widgets_ui/addrelatedelementsdialog.h48
-rw-r--r--src/libs/modelinglib/qmt/model_widgets_ui/addrelatedelementsdialog.ui190
-rw-r--r--src/libs/modelinglib/qmt/tasks/diagramscenecontroller.cpp54
-rw-r--r--src/libs/modelinglib/qmt/tasks/diagramscenecontroller.h7
8 files changed, 678 insertions, 10 deletions
diff --git a/src/libs/modelinglib/CMakeLists.txt b/src/libs/modelinglib/CMakeLists.txt
index dcc810eb21..afea6c1699 100644
--- a/src/libs/modelinglib/CMakeLists.txt
+++ b/src/libs/modelinglib/CMakeLists.txt
@@ -131,6 +131,8 @@ add_qtc_library(Modeling
qmt/model_ui/stereotypescontroller.cpp qmt/model_ui/stereotypescontroller.h
qmt/model_ui/treemodel.cpp qmt/model_ui/treemodel.h
qmt/model_ui/treemodelmanager.cpp qmt/model_ui/treemodelmanager.h
+ 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/modeltreeview.cpp qmt/model_widgets_ui/modeltreeview.h
qmt/model_widgets_ui/palettebox.cpp qmt/model_widgets_ui/palettebox.h
diff --git a/src/libs/modelinglib/modelinglib.qbs b/src/libs/modelinglib/modelinglib.qbs
index 409928d3cb..d4edfadf09 100644
--- a/src/libs/modelinglib/modelinglib.qbs
+++ b/src/libs/modelinglib/modelinglib.qbs
@@ -247,6 +247,9 @@ QtcLibrary {
"model_ui/treemodel.h",
"model_ui/treemodelmanager.cpp",
"model_ui/treemodelmanager.h",
+ "model_widgets_ui/addrelatedelementsdialog.h",
+ "model_widgets_ui/addrelatedelementsdialog.cpp",
+ "model_widgets_ui/addrelatedelementsdialog.ui",
"model_widgets_ui/classmembersedit.cpp",
"model_widgets_ui/classmembersedit.h",
"model_widgets_ui/modeltreeview.cpp",
diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.cpp
index 5d747a6391..60009e5f50 100644
--- a/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.cpp
+++ b/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.cpp
@@ -1092,7 +1092,6 @@ void ObjectItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
layoutMenu.addAction(new ContextMenuAction(Tr::tr("Equal Vertical Space"), "sameVBorderDistance", &alignMenu));
layoutMenu.setEnabled(m_diagramSceneModel->hasMultiObjectsSelection());
menu.addMenu(&layoutMenu);
- menu.addAction(new ContextMenuAction(Tr::tr("Add Related Elements"), "addRelatedElements", &menu));
QAction *selectedAction = menu.exec(event->screenPos());
if (selectedAction) {
@@ -1145,11 +1144,6 @@ void ObjectItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
align(IAlignable::AlignHeight, "height");
} else if (action->id() == "sameSize") {
align(IAlignable::AlignSize, "size");
- } else if (action->id() == "addRelatedElements") {
- DSelection selection = m_diagramSceneModel->selectedElements();
- if (selection.isEmpty())
- selection.append(m_object->uid(), m_diagramSceneModel->diagram()->uid());
- m_diagramSceneModel->diagramSceneController()->addRelatedElements(selection, m_diagramSceneModel->diagram());
}
}
}
diff --git a/src/libs/modelinglib/qmt/model_widgets_ui/addrelatedelementsdialog.cpp b/src/libs/modelinglib/qmt/model_widgets_ui/addrelatedelementsdialog.cpp
new file mode 100644
index 0000000000..35bfeda6c7
--- /dev/null
+++ b/src/libs/modelinglib/qmt/model_widgets_ui/addrelatedelementsdialog.cpp
@@ -0,0 +1,378 @@
+// Copyright (C) 2018 Jochen Becher
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include "addrelatedelementsdialog.h"
+#include "ui_addrelatedelementsdialog.h"
+
+#include <qmt/tasks/diagramscenecontroller.h>
+#include <qmt/diagram_controller/dselection.h>
+#include <qmt/model/mdiagram.h>
+#include <qmt/model/mrelation.h>
+#include <qmt/model/mdependency.h>
+#include <qmt/model/minheritance.h>
+#include <qmt/model/massociation.h>
+#include <qmt/model/mconnection.h>
+#include <qmt/model_controller/modelcontroller.h>
+#include <qmt/model_controller/mvoidvisitor.h>
+
+#include <QStringListModel>
+
+
+namespace qmt {
+
+namespace {
+
+enum class RelationType {
+ Any,
+ Dependency,
+ Association,
+ Inheritance,
+ Connection
+};
+
+enum class RelationDirection {
+ Any,
+ Outgoing,
+ Incoming,
+ Bidirectional
+};
+
+enum class ElementType {
+ Any,
+ Package,
+ Component,
+ Class,
+ Diagram,
+ Item,
+};
+
+class Filter : public qmt::MVoidConstVisitor {
+public:
+
+ void setRelationType(RelationType newRelationType)
+ {
+ m_relationType = newRelationType;
+ }
+
+ void setRelationTypeId(const QString &newRelationTypeId)
+ {
+ m_relationTypeId = newRelationTypeId;
+ }
+
+ void setRelationDirection(RelationDirection newRelationDirection)
+ {
+ m_relationDirection = newRelationDirection;
+ }
+
+ void setRelationStereotypes(const QStringList &newRelationStereotypes)
+ {
+ m_relationStereotypes = newRelationStereotypes;
+ }
+
+ void setElementType(ElementType newElementType)
+ {
+ m_elementType = newElementType;
+ }
+
+ void setElementStereotypes(const QStringList &newElementStereotypes)
+ {
+ m_elementStereotypes = newElementStereotypes;
+ }
+
+ void setObject(const qmt::DObject *dobject, const qmt::MObject *mobject)
+ {
+ m_dobject = dobject;
+ m_mobject = mobject;
+ }
+
+ void setRelation(const qmt::MRelation *relation)
+ {
+ m_relation = relation;
+ }
+
+ bool keep() const { return m_keep; }
+
+ void reset()
+ {
+ m_dobject = nullptr;
+ m_mobject = nullptr;
+ m_relation = nullptr;
+ m_keep = true;
+ }
+
+ // MConstVisitor interface
+ void visitMObject(const qmt::MObject *object) override
+ {
+ if (!m_elementStereotypes.isEmpty()) {
+ const QStringList stereotypes = object->stereotypes();
+ bool containsElementStereotype = std::any_of(
+ stereotypes.constBegin(), stereotypes.constEnd(),
+ [&](const QString &s) { return m_elementStereotypes.contains(s); });
+ if (!containsElementStereotype) {
+ m_keep = false;
+ return;
+ }
+ }
+ }
+
+ void visitMPackage(const qmt::MPackage *package) override
+ {
+ if (m_elementType == ElementType::Any || m_elementType == ElementType::Package)
+ qmt::MVoidConstVisitor::visitMPackage(package);
+ else
+ m_keep = false;
+ }
+
+ void visitMClass(const qmt::MClass *klass) override
+ {
+ if (m_elementType == ElementType::Any || m_elementType == ElementType::Class)
+ qmt::MVoidConstVisitor::visitMClass(klass);
+ else
+ m_keep = false;
+ }
+
+ void visitMComponent(const qmt::MComponent *component) override
+ {
+ if (m_elementType == ElementType::Any || m_elementType == ElementType::Component)
+ qmt::MVoidConstVisitor::visitMComponent(component);
+ else
+ m_keep = false;
+ }
+
+ void visitMDiagram(const qmt::MDiagram *diagram) override
+ {
+ if (m_elementType == ElementType::Any || m_elementType == ElementType::Diagram)
+ qmt::MVoidConstVisitor::visitMDiagram(diagram);
+ else
+ m_keep = false;
+ }
+
+ void visitMItem(const qmt::MItem *item) override
+ {
+ if (m_elementType == ElementType::Any || m_elementType == ElementType::Item)
+ qmt::MVoidConstVisitor::visitMItem(item);
+ else
+ m_keep = false;
+ }
+
+ void visitMRelation(const qmt::MRelation *relation) override
+ {
+ if (!m_relationStereotypes.isEmpty()) {
+ const QStringList relationStereotypes = relation->stereotypes();
+ bool containsRelationStereotype = std::any_of(
+ relationStereotypes.constBegin(), relationStereotypes.constEnd(),
+ [&](const QString &s) { return m_relationStereotypes.contains(s); });
+ if (!containsRelationStereotype) {
+ m_keep = false;
+ return;
+ }
+ }
+ }
+
+ void visitMDependency(const qmt::MDependency *dependency) override
+ {
+ if (m_relationDirection != RelationDirection::Any) {
+ bool keep = false;
+ if (m_relationDirection == RelationDirection::Outgoing) {
+ if (dependency->direction() == qmt::MDependency::AToB && dependency->endAUid() == m_mobject->uid())
+ keep = true;
+ else if (dependency->direction() == qmt::MDependency::BToA && dependency->endBUid() == m_mobject->uid())
+ keep = true;
+ } else if (m_relationDirection == RelationDirection::Incoming) {
+ if (dependency->direction() == qmt::MDependency::AToB && dependency->endBUid() == m_mobject->uid())
+ keep = true;
+ else if (dependency->direction() == qmt::MDependency::BToA && dependency->endAUid() == m_mobject->uid())
+ keep = true;
+ } else if (m_relationDirection == RelationDirection::Bidirectional) {
+ if (dependency->direction() == qmt::MDependency::Bidirectional)
+ keep = true;
+ }
+ m_keep = keep;
+ if (!keep)
+ return;
+ }
+ if (m_relationType == RelationType::Any || m_relationType == RelationType::Dependency)
+ qmt::MVoidConstVisitor::visitMDependency(dependency);
+ else
+ m_keep = false;
+ }
+
+ bool testDirection(const qmt::MRelation *relation)
+ {
+ if (m_relationDirection != RelationDirection::Any) {
+ bool keep = false;
+ if (m_relationDirection == RelationDirection::Outgoing) {
+ if (relation->endAUid() == m_mobject->uid())
+ keep = true;
+ } else if (m_relationDirection == RelationDirection::Incoming) {
+ if (relation->endBUid() == m_mobject->uid())
+ keep = true;
+ }
+ m_keep = keep;
+ if (!keep)
+ return false;
+ }
+ return true;
+ }
+
+ void visitMInheritance(const qmt::MInheritance *inheritance) override
+ {
+ if (!testDirection(inheritance))
+ return;
+ if (m_relationType == RelationType::Any || m_relationType == RelationType::Inheritance)
+ qmt::MVoidConstVisitor::visitMInheritance(inheritance);
+ else
+ m_keep = false;
+ }
+
+ void visitMAssociation(const qmt::MAssociation *association) override
+ {
+ if (!testDirection(association))
+ return;
+ if (m_relationType == RelationType::Any || m_relationType == RelationType::Association)
+ qmt::MVoidConstVisitor::visitMAssociation(association);
+ else
+ m_keep = false;
+ }
+
+ void visitMConnection(const qmt::MConnection *connection) override
+ {
+ if (!testDirection(connection))
+ return;
+ if (m_relationType == RelationType::Any || m_relationType == RelationType::Connection)
+ qmt::MVoidConstVisitor::visitMConnection(connection);
+ else
+ m_keep = false;
+ }
+
+private:
+ RelationType m_relationType = RelationType::Any;
+ QString m_relationTypeId;
+ RelationDirection m_relationDirection = RelationDirection::Any;
+ QStringList m_relationStereotypes;
+ ElementType m_elementType = ElementType::Any;
+ QStringList m_elementStereotypes;
+ const qmt::DObject *m_dobject = nullptr;
+ const qmt::MObject *m_mobject = nullptr;
+ const qmt::MRelation *m_relation = nullptr;
+ bool m_keep = true;
+};
+} // namespace
+
+class AddRelatedElementsDialog::Private {
+public:
+ qmt::DiagramSceneController *m_diagramSceneController = nullptr;
+ qmt::DSelection m_selection;
+ qmt::Uid m_diagramUid;
+ QStringListModel m_relationTypeModel;
+ QStringListModel m_relationDirectionModel;
+ QStringListModel m_relationStereotypesModel;
+ QStringListModel m_elementTypeModel;
+ QStringListModel m_elementStereotypesModel;
+ Filter m_filter;
+};
+
+AddRelatedElementsDialog::AddRelatedElementsDialog(QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::AddRelatedElementsDialog),
+ d(new Private)
+{
+ ui->setupUi(this);
+ connect(ui->RelationTypeCombobox, &QComboBox::currentIndexChanged, this, &AddRelatedElementsDialog::updateNumberOfElements);
+ connect(ui->DirectionCombobox, &QComboBox::currentIndexChanged, this, &AddRelatedElementsDialog::updateNumberOfElements);
+ connect(ui->StereotypesCombobox, &QComboBox::currentTextChanged, this, &AddRelatedElementsDialog::updateNumberOfElements);
+ connect(ui->ElementTypeComboBox, &QComboBox::currentIndexChanged, this, &AddRelatedElementsDialog::updateNumberOfElements);
+ connect(ui->ElementStereotypesCombobox, &QComboBox::currentTextChanged, this, &AddRelatedElementsDialog::updateNumberOfElements);
+ connect(this, &QDialog::accepted, this, &AddRelatedElementsDialog::onAccepted);
+}
+
+AddRelatedElementsDialog::~AddRelatedElementsDialog()
+{
+ delete d;
+ delete ui;
+}
+
+void AddRelatedElementsDialog::setDiagramSceneController(qmt::DiagramSceneController *diagramSceneController)
+{
+ d->m_diagramSceneController = diagramSceneController;
+}
+
+void AddRelatedElementsDialog::setElements(const qmt::DSelection &selection, qmt::MDiagram *diagram)
+{
+ d->m_selection = selection;
+ d->m_diagramUid = diagram->uid();
+ QStringList relationTypes = {"Any", "Dependency", "Association", "Inheritance"};
+ d->m_relationTypeModel.setStringList(relationTypes);
+ ui->RelationTypeCombobox->setModel(&d->m_relationTypeModel);
+ QStringList relationDirections = {"Any", "Outgoing (->)", "Incoming (<-)", "Bidirectional (<->)"};
+ d->m_relationDirectionModel.setStringList(relationDirections);
+ ui->DirectionCombobox->setModel(&d->m_relationDirectionModel);
+ QStringList relationStereotypes = { };
+ d->m_relationStereotypesModel.setStringList(relationStereotypes);
+ ui->StereotypesCombobox->setModel(&d->m_relationStereotypesModel);
+ QStringList elementTypes = {"Any", "Package", "Component", "Class", "Diagram", "Item"};
+ d->m_elementTypeModel.setStringList(elementTypes);
+ ui->ElementTypeComboBox->setModel(&d->m_elementTypeModel);
+ QStringList elementStereotypes = { };
+ d->m_elementStereotypesModel.setStringList(elementStereotypes);
+ ui->ElementStereotypesCombobox->setModel(&d->m_elementStereotypesModel);
+ updateNumberOfElements();
+}
+
+void AddRelatedElementsDialog::onAccepted()
+{
+ qmt::MDiagram *diagram = d->m_diagramSceneController->modelController()->findElement<qmt::MDiagram>(d->m_diagramUid);
+ if (diagram) {
+ updateFilter();
+ d->m_diagramSceneController->addRelatedElements(
+ d->m_selection, diagram,
+ [this](qmt::DObject *dobject, qmt::MObject *mobject, qmt::MRelation *relation) -> bool
+ {
+ return this->filter(dobject, mobject, relation);
+ });
+ }
+}
+
+void AddRelatedElementsDialog::updateFilter()
+{
+ d->m_filter.setRelationType((RelationType) ui->RelationTypeCombobox->currentIndex());
+ d->m_filter.setRelationDirection((RelationDirection) ui->DirectionCombobox->currentIndex());
+ d->m_filter.setRelationStereotypes(ui->StereotypesCombobox->currentText().split(',', Qt::SkipEmptyParts));
+ d->m_filter.setElementType((ElementType) ui->ElementTypeComboBox->currentIndex());
+ d->m_filter.setElementStereotypes(ui->ElementStereotypesCombobox->currentText().split(',', Qt::SkipEmptyParts));
+}
+
+bool AddRelatedElementsDialog::filter(qmt::DObject *dobject, qmt::MObject *mobject, qmt::MRelation *relation)
+{
+ d->m_filter.reset();
+ d->m_filter.setObject(dobject, mobject);
+ d->m_filter.setRelation(relation);
+ relation->accept(&d->m_filter);
+ if (!d->m_filter.keep())
+ return false;
+ qmt::MObject *targetObject = nullptr;
+ if (relation->endAUid() != mobject->uid())
+ targetObject = d->m_diagramSceneController->modelController()->findObject(relation->endAUid());
+ else if (relation->endBUid() != mobject->uid())
+ targetObject = d->m_diagramSceneController->modelController()->findObject(relation->endBUid());
+ if (!targetObject)
+ return false;
+ targetObject->accept(&d->m_filter);
+ return d->m_filter.keep();
+}
+
+void AddRelatedElementsDialog::updateNumberOfElements()
+{
+ qmt::MDiagram *diagram = d->m_diagramSceneController->modelController()->findElement<qmt::MDiagram>(d->m_diagramUid);
+ if (diagram) {
+ updateFilter();
+ ui->NumberOfMatchingElementsValue->setText(QString::number(d->m_diagramSceneController->countRelatedElements(
+ d->m_selection, diagram,
+ [this](qmt::DObject *dobject, qmt::MObject *mobject, qmt::MRelation *relation) -> bool
+ {
+ return this->filter(dobject, mobject, relation);
+ })));
+ }
+}
+
+} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/model_widgets_ui/addrelatedelementsdialog.h b/src/libs/modelinglib/qmt/model_widgets_ui/addrelatedelementsdialog.h
new file mode 100644
index 0000000000..1c7edb1d57
--- /dev/null
+++ b/src/libs/modelinglib/qmt/model_widgets_ui/addrelatedelementsdialog.h
@@ -0,0 +1,48 @@
+// 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 <QDialog>
+
+namespace qmt {
+
+class DSelection;
+class DObject;
+class MObject;
+class MDiagram;
+class MRelation;
+class DiagramSceneController;
+}
+
+namespace Ui {
+class AddRelatedElementsDialog;
+}
+
+namespace qmt {
+
+class QMT_EXPORT AddRelatedElementsDialog : public QDialog
+{
+ Q_OBJECT
+ class Private;
+
+public:
+ explicit AddRelatedElementsDialog(QWidget *parent = nullptr);
+ ~AddRelatedElementsDialog();
+
+ void setDiagramSceneController(qmt::DiagramSceneController *diagramSceneController);
+ void setElements(const qmt::DSelection &selection, qmt::MDiagram *diagram);
+
+private:
+ void onAccepted();
+ void updateFilter();
+ bool filter(qmt::DObject *dobject, qmt::MObject *mobject, qmt::MRelation *relation);
+ void updateNumberOfElements();
+
+ Ui::AddRelatedElementsDialog *ui = nullptr;
+ Private *d = nullptr;
+};
+
+} // namespace qmt
diff --git a/src/libs/modelinglib/qmt/model_widgets_ui/addrelatedelementsdialog.ui b/src/libs/modelinglib/qmt/model_widgets_ui/addrelatedelementsdialog.ui
new file mode 100644
index 0000000000..0dc2cf04ca
--- /dev/null
+++ b/src/libs/modelinglib/qmt/model_widgets_ui/addrelatedelementsdialog.ui
@@ -0,0 +1,190 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AddRelatedElementsDialog</class>
+ <widget class="QDialog" name="AddRelatedElementsDialog">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>500</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <widget class="QGroupBox" name="relationBox">
+ <property name="title">
+ <string>Relation Attributes</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="RelationTypeLabel">
+ <property name="text">
+ <string>Type</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="RelationTypeCombobox"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="DirectionLabel">
+ <property name="text">
+ <string>Direction</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="DirectionCombobox"/>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="StereotypesLabel">
+ <property name="text">
+ <string>Stereotypes</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QComboBox" name="StereotypesCombobox">
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="elementBox">
+ <property name="title">
+ <string>Other Element Attributes</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <layout class="QFormLayout" name="formLayout_2">
+ <item row="1" column="0">
+ <widget class="QLabel" name="ElementTypeLabel">
+ <property name="text">
+ <string>Type</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="ElementStereotypesLabel">
+ <property name="text">
+ <string>Stereotypes</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QComboBox" name="ElementStereotypesCombobox">
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="ElementTypeComboBox">
+ <property name="editable">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <layout class="QFormLayout" name="formLayout_3">
+ <item row="0" column="0">
+ <widget class="QLabel" name="NumberOfMatchingElementsLabel">
+ <property name="text">
+ <string>Number of matching elements: </string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="NumberOfMatchingElementsValue">
+ <property name="text">
+ <string>0</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::MinimumExpanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>AddRelatedElementsDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>AddRelatedElementsDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.cpp b/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.cpp
index 00aacf9c82..51f414f66e 100644
--- a/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.cpp
+++ b/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.cpp
@@ -421,7 +421,44 @@ void DiagramSceneController::dropNewModelElement(MObject *modelObject, MPackage
emit newElementCreated(element, diagram);
}
-void DiagramSceneController::addRelatedElements(const DSelection &selection, MDiagram *diagram)
+int DiagramSceneController::countRelatedElements(const DSelection &selection, MDiagram *diagram, std::function<bool (qmt::DObject *, qmt::MObject *, qmt::MRelation *)> filter)
+{
+ int counter = 0;
+ const QList<DSelection::Index> indices = selection.indices();
+ for (const DSelection::Index &index : indices) {
+ DElement *delement = m_diagramController->findElement(index.elementKey(), diagram);
+ QMT_ASSERT(delement, return 0);
+ DObject *dobject = dynamic_cast<DObject *>(delement);
+ if (dobject && dobject->modelUid().isValid()) {
+ MObject *mobject = m_modelController->findElement<MObject>(delement->modelUid());
+ if (mobject) {
+ const QList<MRelation *> relations = m_modelController->findRelationsOfObject(mobject);
+ QList<MRelation *> filteredRelations;
+ const QList<MRelation *> *relationsList = nullptr;
+ if (filter) {
+ for (MRelation *relation : relations) {
+ if (filter(dobject, mobject, relation))
+ filteredRelations.append(relation);
+ }
+ relationsList = &filteredRelations;
+ } else {
+ relationsList = &relations;
+ }
+ for (MRelation *relation : *relationsList) {
+ if (relation->endAUid() != mobject->uid())
+ ++counter;
+ else if (relation->endBUid() != mobject->uid())
+ ++counter;
+ }
+ }
+ }
+ }
+ return counter;
+}
+
+void DiagramSceneController::addRelatedElements(
+ const DSelection &selection, MDiagram *diagram,
+ std::function<bool (qmt::DObject *dobject, qmt::MObject *mobject, qmt::MRelation *relation)> filter)
{
m_diagramController->undoController()->beginMergeSequence(Tr::tr("Add Related Element"));
const QList<DSelection::Index> indices = selection.indices();
@@ -435,8 +472,19 @@ void DiagramSceneController::addRelatedElements(const DSelection &selection, MDi
qreal dAngle = 360.0 / 11.5;
qreal dRadius = 100.0;
const QList<MRelation *> relations = m_modelController->findRelationsOfObject(mobject);
+ QList<MRelation *> filteredRelations;
+ const QList<MRelation *> *relationsList = nullptr;
+ if (filter) {
+ for (MRelation *relation : relations) {
+ if (filter(dobject, mobject, relation))
+ filteredRelations.append(relation);
+ }
+ relationsList = &filteredRelations;
+ } else {
+ relationsList = &relations;
+ }
int count = 0;
- for (MRelation *relation : relations) {
+ for (MRelation *relation : *relationsList) {
if (relation->endAUid() != mobject->uid() || relation->endBUid() != mobject->uid())
++count;
}
@@ -446,7 +494,7 @@ void DiagramSceneController::addRelatedElements(const DSelection &selection, MDi
}
qreal radius = 200.0;
qreal angle = 0.0;
- for (MRelation *relation : relations) {
+ for (MRelation *relation : *relationsList) {
QPointF pos(dobject->pos());
pos += QPointF(radius * sin(angle / 180 * M_PI), -radius * cos(angle / 180 * M_PI));
bool added = false;
diff --git a/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.h b/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.h
index a062fa10c4..14e704a192 100644
--- a/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.h
+++ b/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.h
@@ -86,7 +86,12 @@ public:
DElement *topMostElementAtPos, const QPointF &pos, MDiagram *diagram, const QPoint &viewPos, const QSize &viewSize);
void dropNewModelElement(MObject *modelObject, MPackage *parentPackage, const QPointF &pos,
MDiagram *diagram);
- void addRelatedElements(const DSelection &selection, MDiagram *diagram);
+ int countRelatedElements(
+ const DSelection &selection, MDiagram *diagram,
+ std::function<bool (qmt::DObject *dobject, qmt::MObject *mobject, qmt::MRelation *relation)> filter);
+ void addRelatedElements(
+ const DSelection &selection, MDiagram *diagram,
+ std::function<bool (qmt::DObject *dobject, qmt::MObject *mobject, qmt::MRelation *relation)> filter);
MPackage *findSuitableParentPackage(DElement *topmostDiagramElement, MDiagram *diagram);
MDiagram *findDiagramBySearchId(MPackage *package, const QString &diagramName);