diff options
Diffstat (limited to 'src/libs/modelinglib/qmt/model_widgets_ui/addrelatedelementsdialog.cpp')
-rw-r--r-- | src/libs/modelinglib/qmt/model_widgets_ui/addrelatedelementsdialog.cpp | 378 |
1 files changed, 378 insertions, 0 deletions
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 00000000000..35bfeda6c7d --- /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 |