From 4c469e0111e903c4ff692af0e81e3f63ca2192f9 Mon Sep 17 00:00:00 2001 From: Jochen Becher Date: Sat, 15 Jul 2017 15:37:19 +0200 Subject: [PATCH] ModelEditor: Introduce swimlanes Change-Id: I9ac9c51eabc00c6912fd47fbf51b50b2938846ae Reviewed-by: Leena Miettinen Reviewed-by: Tobias Hunger --- share/qtcreator/modeleditor/standard.def | 15 +- src/libs/modelinglib/modelinglib.qbs | 4 + .../qmt/config/stereotypedefinitionparser.cpp | 4 +- .../modelinglib/qmt/diagram/dconstvisitor.h | 2 + .../modelinglib/qmt/diagram/dswimlane.cpp | 86 ++++++ src/libs/modelinglib/qmt/diagram/dswimlane.h | 58 ++++ src/libs/modelinglib/qmt/diagram/dvisitor.h | 2 + .../qmt/diagram_controller/dclonevisitor.cpp | 16 ++ .../qmt/diagram_controller/dclonevisitor.h | 2 + .../dflatassignmentvisitor.cpp | 11 + .../dflatassignmentvisitor.h | 1 + .../qmt/diagram_controller/dvoidvisitor.cpp | 11 + .../qmt/diagram_controller/dvoidvisitor.h | 2 + .../diagram_scene/capabilities/selectable.h | 4 + .../qmt/diagram_scene/diagramsceneconstants.h | 1 + .../qmt/diagram_scene/diagramscenemodel.cpp | 41 ++- .../qmt/diagram_scene/diagramscenemodel.h | 2 + .../diagramscenemodelitemvisitors.cpp | 19 ++ .../diagramscenemodelitemvisitors.h | 2 + .../diagram_scene/items/annotationitem.cpp | 15 ++ .../qmt/diagram_scene/items/annotationitem.h | 2 + .../qmt/diagram_scene/items/boundaryitem.cpp | 15 ++ .../qmt/diagram_scene/items/boundaryitem.h | 2 + .../qmt/diagram_scene/items/objectitem.cpp | 15 ++ .../qmt/diagram_scene/items/objectitem.h | 2 + .../qmt/diagram_scene/items/relationitem.cpp | 12 + .../qmt/diagram_scene/items/relationitem.h | 2 + .../qmt/diagram_scene/items/swimlaneitem.cpp | 250 ++++++++++++++++++ .../qmt/diagram_scene/items/swimlaneitem.h | 87 ++++++ .../qmt/diagram_ui/diagram_mime_types.h | 1 + .../qmt/diagram_widgets_ui/diagramview.cpp | 22 +- .../qmt/diagram_widgets_ui/diagramview.h | 2 + .../model_widgets_ui/propertiesviewmview.cpp | 7 + .../model_widgets_ui/propertiesviewmview.h | 1 + src/libs/modelinglib/qmt/qmt.pri | 4 + .../qmt/resources/48x48/swimlane.png | Bin 0 -> 191 bytes .../modelinglib/qmt/resources/resources.qrc | 1 + .../qmt/serializer/diagramserializer.cpp | 20 ++ .../qmt/style/defaultstyleengine.cpp | 53 +++- .../qmt/style/defaultstyleengine.h | 5 + .../modelinglib/qmt/style/stylecontroller.cpp | 6 + .../modelinglib/qmt/style/stylecontroller.h | 1 + src/libs/modelinglib/qmt/style/styleengine.h | 6 +- .../qmt/tasks/alignonrastervisitor.cpp | 8 + .../qmt/tasks/alignonrastervisitor.h | 1 + .../qmt/tasks/diagramscenecontroller.cpp | 14 +- .../qmt/tasks/diagramscenecontroller.h | 2 +- src/plugins/modeleditor/modeleditor.cpp | 7 + .../modeleditor/openelementvisitor.cpp | 5 + src/plugins/modeleditor/openelementvisitor.h | 29 +- 50 files changed, 852 insertions(+), 28 deletions(-) create mode 100644 src/libs/modelinglib/qmt/diagram/dswimlane.cpp create mode 100644 src/libs/modelinglib/qmt/diagram/dswimlane.h create mode 100644 src/libs/modelinglib/qmt/diagram_scene/items/swimlaneitem.cpp create mode 100644 src/libs/modelinglib/qmt/diagram_scene/items/swimlaneitem.h create mode 100644 src/libs/modelinglib/qmt/resources/48x48/swimlane.png diff --git a/share/qtcreator/modeleditor/standard.def b/share/qtcreator/modeleditor/standard.def index 319473340e7..662bee8e487 100644 --- a/share/qtcreator/modeleditor/standard.def +++ b/share/qtcreator/modeleditor/standard.def @@ -119,9 +119,18 @@ // Toolbar { // id: // title: +// element: // priority: // Tools { -// Tool { title: ; element: ; stereotype: } +// Tool { +// title: ; +// element: ; +// stereotype: +// } // Separator // } // } @@ -465,6 +474,7 @@ Toolbar { Separator Tool { title: "Annotation"; element: annotation } Tool { title: "Boundary"; element: boundary } + Tool { title: "Swimlane"; element: swimlane } } } @@ -477,6 +487,7 @@ Toolbar { Separator Tool { title: "Annotation"; element: annotation } Tool { title: "Boundary"; element: boundary } + Tool { title: "Swimlane"; element: swimlane } } } @@ -489,6 +500,7 @@ Toolbar { Separator Tool { title: "Annotation"; element: annotation } Tool { title: "Boundary"; element: boundary } + Tool { title: "Swimlane"; element: swimlane } } } @@ -504,5 +516,6 @@ Toolbar { Separator Tool { title: "Annotation"; element: annotation } Tool { title: "Boundary"; element: boundary } + Tool { title: "Swimlane"; element: swimlane } } } diff --git a/src/libs/modelinglib/modelinglib.qbs b/src/libs/modelinglib/modelinglib.qbs index 305bf6afdc5..b9ee382bbdf 100644 --- a/src/libs/modelinglib/modelinglib.qbs +++ b/src/libs/modelinglib/modelinglib.qbs @@ -74,6 +74,8 @@ QtcLibrary { "diagram/dpackage.h", "diagram/drelation.cpp", "diagram/drelation.h", + "diagram/dswimlane.cpp", + "diagram/dswimlane.h", "diagram/dvisitor.h", "diagram_controller/dclonevisitor.cpp", "diagram_controller/dclonevisitor.h", @@ -130,6 +132,8 @@ QtcLibrary { "diagram_scene/items/relationitem.h", "diagram_scene/items/stereotypedisplayvisitor.cpp", "diagram_scene/items/stereotypedisplayvisitor.h", + "diagram_scene/items/swimlaneitem.cpp", + "diagram_scene/items/swimlaneitem.h", "diagram_scene/latchcontroller.cpp", "diagram_scene/latchcontroller.h", "diagram_scene/parts/alignbuttonsitem.cpp", diff --git a/src/libs/modelinglib/qmt/config/stereotypedefinitionparser.cpp b/src/libs/modelinglib/qmt/config/stereotypedefinitionparser.cpp index dedf029d950..b80252f4755 100644 --- a/src/libs/modelinglib/qmt/config/stereotypedefinitionparser.cpp +++ b/src/libs/modelinglib/qmt/config/stereotypedefinitionparser.cpp @@ -36,7 +36,6 @@ #include #include #include -#include namespace qmt { @@ -884,7 +883,8 @@ void StereotypeDefinitionParser::parseToolbarTool(const Toolbar *toolbar, Toolba << QStringLiteral("class") << QStringLiteral("item") << QStringLiteral("annotation") - << QStringLiteral("boundary"); + << QStringLiteral("boundary") + << QStringLiteral("swimlane"); QString elementName = element.toLower(); if (!elementNames.contains(elementName)) throw StereotypeDefinitionParserError(QString(QStringLiteral("Unexpected value \"%1\" for element.")).arg(element), token.sourcePos()); diff --git a/src/libs/modelinglib/qmt/diagram/dconstvisitor.h b/src/libs/modelinglib/qmt/diagram/dconstvisitor.h index 4637bd767c4..a8f6032aa57 100644 --- a/src/libs/modelinglib/qmt/diagram/dconstvisitor.h +++ b/src/libs/modelinglib/qmt/diagram/dconstvisitor.h @@ -41,6 +41,7 @@ class DAssociation; class DConnection; class DAnnotation; class DBoundary; +class DSwimlane; class DConstVisitor { @@ -61,6 +62,7 @@ public: virtual void visitDConnection(const DConnection *connection) = 0; virtual void visitDAnnotation(const DAnnotation *annotation) = 0; virtual void visitDBoundary(const DBoundary *boundary) = 0; + virtual void visitDSwimlane(const DSwimlane *swimlane) = 0; }; } // namespace qmt diff --git a/src/libs/modelinglib/qmt/diagram/dswimlane.cpp b/src/libs/modelinglib/qmt/diagram/dswimlane.cpp new file mode 100644 index 00000000000..41d29a32b88 --- /dev/null +++ b/src/libs/modelinglib/qmt/diagram/dswimlane.cpp @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Jochen Becher +** 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 "dswimlane.h" + +#include "dvisitor.h" +#include "dconstvisitor.h" + +namespace qmt { + +DSwimlane::DSwimlane() + : DElement() +{ +} + +DSwimlane::DSwimlane(const DSwimlane &rhs) + : DElement(rhs), + m_text(rhs.m_text), + m_horizontal(rhs.m_horizontal), + m_pos(rhs.m_pos) +{ +} + +DSwimlane::~DSwimlane() +{ +} + +DSwimlane &DSwimlane::operator=(const DSwimlane &rhs) +{ + if (this != &rhs) { + DElement::operator=(rhs); + m_text = rhs.m_text; + m_horizontal = rhs.m_horizontal; + m_pos = rhs.m_pos; + } + return *this; +} + +void DSwimlane::setText(const QString &text) +{ + m_text = text; +} + +void DSwimlane::setHorizontal(bool horizontal) +{ + m_horizontal = horizontal; +} + +void DSwimlane::setPos(qreal pos) +{ + m_pos = pos; +} + +void DSwimlane::accept(DVisitor *visitor) +{ + visitor->visitDSwimlane(this); +} + +void DSwimlane::accept(DConstVisitor *visitor) const +{ + visitor->visitDSwimlane(this); +} + +} // namespoace qmt diff --git a/src/libs/modelinglib/qmt/diagram/dswimlane.h b/src/libs/modelinglib/qmt/diagram/dswimlane.h new file mode 100644 index 00000000000..c1b87960638 --- /dev/null +++ b/src/libs/modelinglib/qmt/diagram/dswimlane.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Jochen Becher +** 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 "delement.h" + +namespace qmt { + +class QMT_EXPORT DSwimlane : public DElement +{ +public: + DSwimlane(); + DSwimlane(const DSwimlane &rhs); + ~DSwimlane(); + + DSwimlane &operator=(const DSwimlane &rhs); + + Uid modelUid() const override { return Uid::invalidUid(); } + QString text() const { return m_text; } + void setText(const QString &text); + bool isHorizontal() const { return m_horizontal; } + void setHorizontal(bool horizontal); + qreal pos() const { return m_pos; } + void setPos(qreal pos); + + void accept(DVisitor *visitor) override; + void accept(DConstVisitor *visitor) const override; + +private: + QString m_text; + bool m_horizontal = false; // false: vertical, true: horizontal + qreal m_pos = 0.0; +}; + +} // namespace qmt diff --git a/src/libs/modelinglib/qmt/diagram/dvisitor.h b/src/libs/modelinglib/qmt/diagram/dvisitor.h index 919aa532330..01adf15b704 100644 --- a/src/libs/modelinglib/qmt/diagram/dvisitor.h +++ b/src/libs/modelinglib/qmt/diagram/dvisitor.h @@ -41,6 +41,7 @@ class DAssociation; class DConnection; class DAnnotation; class DBoundary; +class DSwimlane; class DVisitor { @@ -61,6 +62,7 @@ public: virtual void visitDConnection(DConnection *connection) = 0; virtual void visitDAnnotation(DAnnotation *annotation) = 0; virtual void visitDBoundary(DBoundary *boundary) = 0; + virtual void visitDSwimlane(DSwimlane *swimlane) = 0; }; } // namespace qmt diff --git a/src/libs/modelinglib/qmt/diagram_controller/dclonevisitor.cpp b/src/libs/modelinglib/qmt/diagram_controller/dclonevisitor.cpp index c440d80378e..b2d685e0e5f 100644 --- a/src/libs/modelinglib/qmt/diagram_controller/dclonevisitor.cpp +++ b/src/libs/modelinglib/qmt/diagram_controller/dclonevisitor.cpp @@ -39,6 +39,7 @@ #include "qmt/diagram/dconnection.h" #include "qmt/diagram/dannotation.h" #include "qmt/diagram/dboundary.h" +#include "qmt/diagram/dswimlane.h" #include "qmt/infrastructure/qmtassert.h" namespace qmt { @@ -144,6 +145,14 @@ void DCloneVisitor::visitDBoundary(const DBoundary *boundary) visitDElement(boundary); } +void DCloneVisitor::visitDSwimlane(const DSwimlane *swimlane) +{ + if (!m_cloned) + m_cloned = new DSwimlane(*swimlane); + visitDElement(swimlane); +} + + DCloneDeepVisitor::DCloneDeepVisitor() : m_cloned(0) { @@ -244,4 +253,11 @@ void DCloneDeepVisitor::visitDBoundary(const DBoundary *boundary) visitDElement(boundary); } +void DCloneDeepVisitor::visitDSwimlane(const DSwimlane *swimlane) +{ + if (!m_cloned) + m_cloned = new DSwimlane(*swimlane); + visitDElement(swimlane); +} + } // namespace qmt diff --git a/src/libs/modelinglib/qmt/diagram_controller/dclonevisitor.h b/src/libs/modelinglib/qmt/diagram_controller/dclonevisitor.h index b373f632f18..5531717c951 100644 --- a/src/libs/modelinglib/qmt/diagram_controller/dclonevisitor.h +++ b/src/libs/modelinglib/qmt/diagram_controller/dclonevisitor.h @@ -51,6 +51,7 @@ public: void visitDConnection(const DConnection *connection) override; void visitDAnnotation(const DAnnotation *annotation) override; void visitDBoundary(const DBoundary *boundary) override; + void visitDSwimlane(const DSwimlane *swimlane) override; private: DElement *m_cloned; @@ -77,6 +78,7 @@ public: void visitDConnection(const DConnection *connection) override; void visitDAnnotation(const DAnnotation *annotation) override; void visitDBoundary(const DBoundary *boundary) override; + void visitDSwimlane(const DSwimlane *swimlane) override; private: DElement *m_cloned; diff --git a/src/libs/modelinglib/qmt/diagram_controller/dflatassignmentvisitor.cpp b/src/libs/modelinglib/qmt/diagram_controller/dflatassignmentvisitor.cpp index b90e987217b..20531bb85c4 100644 --- a/src/libs/modelinglib/qmt/diagram_controller/dflatassignmentvisitor.cpp +++ b/src/libs/modelinglib/qmt/diagram_controller/dflatassignmentvisitor.cpp @@ -39,6 +39,7 @@ #include "qmt/diagram/dconnection.h" #include "qmt/diagram/dannotation.h" #include "qmt/diagram/dboundary.h" +#include "qmt/diagram/dswimlane.h" #include "qmt/infrastructure/qmtassert.h" namespace qmt { @@ -178,4 +179,14 @@ void DFlatAssignmentVisitor::visitDBoundary(const DBoundary *boundary) target->setRect(boundary->rect()); } +void DFlatAssignmentVisitor::visitDSwimlane(const DSwimlane *swimlane) +{ + visitDElement(swimlane); + auto target = dynamic_cast(m_target); + QMT_ASSERT(target, return); + target->setText(swimlane->text()); + target->setHorizontal(swimlane->isHorizontal()); + target->setPos(swimlane->pos()); +} + } // namespace qmt diff --git a/src/libs/modelinglib/qmt/diagram_controller/dflatassignmentvisitor.h b/src/libs/modelinglib/qmt/diagram_controller/dflatassignmentvisitor.h index 7aedfc5d8bf..219174faae7 100644 --- a/src/libs/modelinglib/qmt/diagram_controller/dflatassignmentvisitor.h +++ b/src/libs/modelinglib/qmt/diagram_controller/dflatassignmentvisitor.h @@ -49,6 +49,7 @@ public: void visitDConnection(const DConnection *connection) override; void visitDAnnotation(const DAnnotation *annotation) override; void visitDBoundary(const DBoundary *boundary) override; + void visitDSwimlane(const DSwimlane *swimlane) override; private: DElement *m_target; diff --git a/src/libs/modelinglib/qmt/diagram_controller/dvoidvisitor.cpp b/src/libs/modelinglib/qmt/diagram_controller/dvoidvisitor.cpp index a51f0e03357..56fdfe2cb47 100644 --- a/src/libs/modelinglib/qmt/diagram_controller/dvoidvisitor.cpp +++ b/src/libs/modelinglib/qmt/diagram_controller/dvoidvisitor.cpp @@ -39,6 +39,7 @@ #include "qmt/diagram/dconnection.h" #include "qmt/diagram/dannotation.h" #include "qmt/diagram/dboundary.h" +#include "qmt/diagram/dswimlane.h" namespace qmt { @@ -116,6 +117,11 @@ void DVoidVisitor::visitDBoundary(DBoundary *boundary) visitDElement(boundary); } +void DVoidVisitor::visitDSwimlane(DSwimlane *swimlane) +{ + visitDElement(swimlane); +} + DConstVoidVisitor::DConstVoidVisitor() { } @@ -190,4 +196,9 @@ void DConstVoidVisitor::visitDBoundary(const DBoundary *boundary) visitDElement(boundary); } +void DConstVoidVisitor::visitDSwimlane(const DSwimlane *swimlane) +{ + visitDElement(swimlane); +} + } // namespace qmt diff --git a/src/libs/modelinglib/qmt/diagram_controller/dvoidvisitor.h b/src/libs/modelinglib/qmt/diagram_controller/dvoidvisitor.h index f1f1a23f561..7050b7adbf7 100644 --- a/src/libs/modelinglib/qmt/diagram_controller/dvoidvisitor.h +++ b/src/libs/modelinglib/qmt/diagram_controller/dvoidvisitor.h @@ -50,6 +50,7 @@ public: void visitDConnection(DConnection *connection) override; void visitDAnnotation(DAnnotation *annotation) override; void visitDBoundary(DBoundary *boundary) override; + void visitDSwimlane(DSwimlane *swimlane) override; }; class QMT_EXPORT DConstVoidVisitor : public DConstVisitor @@ -71,6 +72,7 @@ public: void visitDConnection(const DConnection *connection) override; void visitDAnnotation(const DAnnotation *annotation) override; void visitDBoundary(const DBoundary *boundary) override; + void visitDSwimlane(const DSwimlane *swimlane) override; }; } // namespace qmt diff --git a/src/libs/modelinglib/qmt/diagram_scene/capabilities/selectable.h b/src/libs/modelinglib/qmt/diagram_scene/capabilities/selectable.h index 5afcf64efdb..8da587bc56f 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/capabilities/selectable.h +++ b/src/libs/modelinglib/qmt/diagram_scene/capabilities/selectable.h @@ -25,6 +25,8 @@ #pragma once +#include + namespace qmt { class ISelectable @@ -36,6 +38,8 @@ public: virtual void setSecondarySelected(bool secondarySelected) = 0; virtual bool isFocusSelected() const = 0; virtual void setFocusSelected(bool focusSelected) = 0; + virtual QRectF getSecondarySelectionBoundary() = 0; + virtual void setBoundarySelected(const QRectF &boundary, bool secondary) = 0; }; } // namespace qmt diff --git a/src/libs/modelinglib/qmt/diagram_scene/diagramsceneconstants.h b/src/libs/modelinglib/qmt/diagram_scene/diagramsceneconstants.h index 6f7d0a89e27..c91e62725b3 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/diagramsceneconstants.h +++ b/src/libs/modelinglib/qmt/diagram_scene/diagramsceneconstants.h @@ -27,6 +27,7 @@ namespace qmt { +const int SWIMLANE_ITEMS_ZVALUE = -1100; const int BOUNDARY_ITEMS_ZVALUE = -1000; // all model objects have z-values from -500 to 500 depending on their depth in the model tree const int RELATION_ITEMS_ZVALUE = 1000; diff --git a/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodel.cpp b/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodel.cpp index f26c31cc6b1..426926b9b35 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodel.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodel.cpp @@ -39,6 +39,7 @@ #include "qmt/diagram_controller/diagramcontroller.h" #include "qmt/diagram_controller/dselection.h" #include "qmt/diagram_scene/items/objectitem.h" +#include "qmt/diagram_scene/items/swimlaneitem.h" #include "qmt/model/mdiagram.h" #include "qmt/model/mobject.h" #include "qmt/model/mpackage.h" @@ -48,6 +49,8 @@ #include "qmt/tasks/diagramscenecontroller.h" #include "qmt/tasks/ielementtasks.h" +#include "utils/asconst.h" + #include #include #include @@ -241,7 +244,7 @@ ObjectItem *DiagramSceneModel::findTopmostObjectItem(const QPointF &scenePos) co { // fetch affected items from scene in correct drawing order to find topmost element const QList items = m_graphicsScene->items(scenePos); - for (QGraphicsItem *item : items) { + for (QGraphicsItem *item : Utils::asConst(items)) { if (m_graphicsItems.contains(item)) { DObject *object = dynamic_cast(m_itemToElementMap.value(item)); if (object) @@ -705,6 +708,7 @@ void DiagramSceneModel::onEndResetDiagram(const MDiagram *diagram) // update graphics items again so every item gets a correct list of colliding items foreach (DElement *element, diagram->diagramElements()) updateGraphicsItem(m_elementToItemMap.value(element), element); + recalcSceneRectSize(); } m_busyState = NotBusy; } @@ -724,6 +728,7 @@ void DiagramSceneModel::onEndUpdateElement(int row, const MDiagram *diagram) if (diagram == m_diagram) { QGraphicsItem *item = m_graphicsItems.at(row); updateGraphicsItem(item, diagram->diagramElements().at(row)); + recalcSceneRectSize(); } m_busyState = NotBusy; } @@ -747,6 +752,7 @@ void DiagramSceneModel::onEndInsertElement(int row, const MDiagram *diagram) updateGraphicsItem(item, element); m_graphicsScene->invalidate(); updateGraphicsItem(item, element); + recalcSceneRectSize(); } m_busyState = NotBusy; } @@ -757,6 +763,7 @@ void DiagramSceneModel::onBeginRemoveElement(int row, const MDiagram *diagram) if (diagram == m_diagram) { QGraphicsItem *item = m_graphicsItems.takeAt(row); deleteGraphicsItem(item, diagram->diagramElements().at(row)); + recalcSceneRectSize(); } m_busyState = RemoveElement; } @@ -807,6 +814,27 @@ void DiagramSceneModel::onSelectionChanged() } } + // select more items secondarily + for (QGraphicsItem *selectedItem : Utils::asConst(m_selectedItems)) { + if (auto selectable = dynamic_cast(selectedItem)) { + QRectF boundary = selectable->getSecondarySelectionBoundary(); + if (!boundary.isEmpty()) { + for (QGraphicsItem *item : Utils::asConst(m_graphicsItems)) { + if (auto secondarySelectable = dynamic_cast(item)) { + if (!item->isSelected() && !secondarySelectable->isSecondarySelected()) { + secondarySelectable->setBoundarySelected(boundary, true); + QMT_CHECK(!m_selectedItems.contains(item)); + QMT_CHECK(!m_secondarySelectedItems.contains(item)); + if (secondarySelectable->isSecondarySelected()) + newSecondarySelectedItems.insert(item); + } + } + } + } + } + } + + // select all relations where both ends are primary or secondary selected foreach (DElement *element, m_diagram->diagramElements()) { auto relation = dynamic_cast(element); @@ -882,6 +910,17 @@ void DiagramSceneModel::addExtraSceneItems() m_latchController->addToGraphicsScene(m_graphicsScene); } +void DiagramSceneModel::recalcSceneRectSize() +{ + QRectF sceneRect = m_originItem->mapRectToScene(m_originItem->boundingRect()); + for (QGraphicsItem *item : Utils::asConst(m_graphicsItems)) { + // TODO use an interface to update sceneRect by item + if (!dynamic_cast(item)) + sceneRect |= item->mapRectToScene(item->boundingRect()); + } + emit sceneRectChanged(sceneRect); +} + QGraphicsItem *DiagramSceneModel::createGraphicsItem(DElement *element) { QMT_ASSERT(element, return nullptr); diff --git a/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodel.h b/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodel.h index 1a5b0c64ea0..7c11c799da8 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodel.h +++ b/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodel.h @@ -80,6 +80,7 @@ public: signals: void diagramSceneActivated(const MDiagram *diagram); void selectionHasChanged(const MDiagram *diagram); + void sceneRectChanged(const QRectF &sceneRect); public: DiagramController *diagramController() const { return m_diagramController; } @@ -152,6 +153,7 @@ private: void clearGraphicsScene(); void removeExtraSceneItems(); void addExtraSceneItems(); + void recalcSceneRectSize(); QGraphicsItem *createGraphicsItem(DElement *element); void updateGraphicsItem(QGraphicsItem *item, DElement *element); void deleteGraphicsItem(QGraphicsItem *item, DElement *element); diff --git a/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodelitemvisitors.cpp b/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodelitemvisitors.cpp index 540d8879412..55ff3fd9e26 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodelitemvisitors.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodelitemvisitors.cpp @@ -35,6 +35,7 @@ #include "items/connectionitem.h" #include "items/annotationitem.h" #include "items/boundaryitem.h" +#include "items/swimlaneitem.h" #include "qmt/diagram/delement.h" #include "qmt/diagram/dobject.h" @@ -50,6 +51,7 @@ #include "qmt/diagram/dconnection.h" #include "qmt/diagram/dannotation.h" #include "qmt/diagram/dboundary.h" +#include "qmt/diagram/dswimlane.h" #include "qmt/infrastructure/qmtassert.h" namespace qmt { @@ -142,6 +144,12 @@ void DiagramSceneModel::CreationVisitor::visitDBoundary(DBoundary *boundary) m_graphicsItem = new BoundaryItem(boundary, m_diagramSceneModel); } +void DiagramSceneModel::CreationVisitor::visitDSwimlane(DSwimlane *swimlane) +{ + QMT_CHECK(!m_graphicsItem); + m_graphicsItem = new SwimlaneItem(swimlane, m_diagramSceneModel); +} + DiagramSceneModel::UpdateVisitor::UpdateVisitor(QGraphicsItem *item, DiagramSceneModel *diagramSceneModel, DElement *relatedElement) : m_graphicsItem(item), @@ -297,4 +305,15 @@ void DiagramSceneModel::UpdateVisitor::visitDBoundary(DBoundary *boundary) boundaryItem->update(); } +void DiagramSceneModel::UpdateVisitor::visitDSwimlane(DSwimlane *swimlane) +{ + Q_UNUSED(swimlane); // avoid warning in release mode + QMT_ASSERT(m_graphicsItem, return); + + SwimlaneItem *swimlaneItem = qgraphicsitem_cast(m_graphicsItem); + QMT_ASSERT(swimlaneItem, return); + QMT_CHECK(swimlaneItem->swimlane() == swimlane); + swimlaneItem->update(); +} + } // namespace qmt diff --git a/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodelitemvisitors.h b/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodelitemvisitors.h index 193f30223bf..09ed4e11815 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodelitemvisitors.h +++ b/src/libs/modelinglib/qmt/diagram_scene/diagramscenemodelitemvisitors.h @@ -52,6 +52,7 @@ public: void visitDConnection(DConnection *connection) override; void visitDAnnotation(DAnnotation *annotation) override; void visitDBoundary(DBoundary *boundary) override; + void visitDSwimlane(DSwimlane *swimlane) override; private: DiagramSceneModel *m_diagramSceneModel; @@ -78,6 +79,7 @@ public: void visitDConnection(DConnection *connection) override; void visitDAnnotation(DAnnotation *annotation) override; void visitDBoundary(DBoundary *boundary) override; + void visitDSwimlane(DSwimlane *swimlane) override; private: QGraphicsItem *m_graphicsItem; diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/annotationitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/annotationitem.cpp index 1fda615ab9c..990876f6d7e 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/annotationitem.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/items/annotationitem.cpp @@ -213,6 +213,21 @@ void AnnotationItem::setFocusSelected(bool focusSelected) } } +QRectF AnnotationItem::getSecondarySelectionBoundary() +{ + return QRectF(); +} + +void AnnotationItem::setBoundarySelected(const QRectF &boundary, bool secondary) +{ + if (boundary.contains(mapRectToScene(boundingRect()))) { + if (secondary) + setSecondarySelected(true); + else + setSelected(true); + } +} + bool AnnotationItem::isEditable() const { return true; diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/annotationitem.h b/src/libs/modelinglib/qmt/diagram_scene/items/annotationitem.h index 29e16224ecd..69b77670de2 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/annotationitem.h +++ b/src/libs/modelinglib/qmt/diagram_scene/items/annotationitem.h @@ -77,6 +77,8 @@ public: void setSecondarySelected(bool secondarySelected) override; bool isFocusSelected() const override; void setFocusSelected(bool focusSelected) override; + QRectF getSecondarySelectionBoundary() override; + void setBoundarySelected(const QRectF &boundary, bool secondary) override; bool isEditable() const override; void edit() override; diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/boundaryitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/boundaryitem.cpp index ce696c61014..63a085465bc 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/boundaryitem.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/items/boundaryitem.cpp @@ -264,6 +264,21 @@ void BoundaryItem::setFocusSelected(bool focusSelected) } } +QRectF BoundaryItem::getSecondarySelectionBoundary() +{ + return QRectF(); +} + +void BoundaryItem::setBoundarySelected(const QRectF &boundary, bool secondary) +{ + if (boundary.contains(mapRectToScene(boundingRect()))) { + if (secondary) + setSecondarySelected(true); + else + setSelected(true); + } +} + bool BoundaryItem::isEditable() const { return true; diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/boundaryitem.h b/src/libs/modelinglib/qmt/diagram_scene/items/boundaryitem.h index b6b3380bebc..78843a3a5ce 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/boundaryitem.h +++ b/src/libs/modelinglib/qmt/diagram_scene/items/boundaryitem.h @@ -76,6 +76,8 @@ public: void setSecondarySelected(bool secondarySelected) override; bool isFocusSelected() const override; void setFocusSelected(bool focusSelected) override; + QRectF getSecondarySelectionBoundary() override; + void setBoundarySelected(const QRectF &boundary, bool secondary) override; bool isEditable() const override; void edit() override; diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.cpp index 351c102747d..5adc3e5eabb 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.cpp @@ -208,6 +208,21 @@ void ObjectItem::setFocusSelected(bool focusSelected) } } +QRectF ObjectItem::getSecondarySelectionBoundary() +{ + return QRectF(); +} + +void ObjectItem::setBoundarySelected(const QRectF &boundary, bool secondary) +{ + if (boundary.contains(mapRectToScene(boundingRect()))) { + if (secondary) + setSecondarySelected(true); + else + setSelected(true); + } +} + ILatchable::Action ObjectItem::horizontalLatchAction() const { if (!m_selectionMarker) diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.h b/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.h index 04bf6e81d01..c0eb6cc574e 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.h +++ b/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.h @@ -113,6 +113,8 @@ public: void setSecondarySelected(bool secondarySelected) override; bool isFocusSelected() const override; void setFocusSelected(bool focusSelected) override; + QRectF getSecondarySelectionBoundary() override; + void setBoundarySelected(const QRectF &boundary, bool secondary) override; Action horizontalLatchAction() const override; Action verticalLatchAction() const override; diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/relationitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/relationitem.cpp index 3a3428b4e7b..1058d45e19c 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/relationitem.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/items/relationitem.cpp @@ -316,6 +316,18 @@ void RelationItem::setFocusSelected(bool focusSelected) } } +QRectF RelationItem::getSecondarySelectionBoundary() +{ + return QRectF(); +} + +void RelationItem::setBoundarySelected(const QRectF &boundary, bool secondary) +{ + // TODO make individual intermediate points selectable + Q_UNUSED(boundary) + Q_UNUSED(secondary) +} + QPointF RelationItem::grabHandle(int index) { if (index == 0) { diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/relationitem.h b/src/libs/modelinglib/qmt/diagram_scene/items/relationitem.h index 983d480fbc3..faecc330f61 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/relationitem.h +++ b/src/libs/modelinglib/qmt/diagram_scene/items/relationitem.h @@ -70,6 +70,8 @@ public: void setSecondarySelected(bool secondarySelected) override; bool isFocusSelected() const override; void setFocusSelected(bool focusSelected) override; + QRectF getSecondarySelectionBoundary() override; + void setBoundarySelected(const QRectF &boundary, bool secondary) override; QPointF grabHandle(int index) override; void insertHandle(int beforeIndex, const QPointF &pos, double rasterWidth, double rasterHeight) override; diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/swimlaneitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/swimlaneitem.cpp new file mode 100644 index 00000000000..ee8b791f6aa --- /dev/null +++ b/src/libs/modelinglib/qmt/diagram_scene/items/swimlaneitem.cpp @@ -0,0 +1,250 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Jochen Becher +** 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 "swimlaneitem.h" + +#include "qmt/diagram_controller/diagramcontroller.h" +#include "qmt/diagram/dswimlane.h" +#include "qmt/diagram_scene/diagramsceneconstants.h" +#include "qmt/diagram_scene/diagramscenemodel.h" +#include "qmt/infrastructure/qmtassert.h" +#include "qmt/style/stylecontroller.h" +#include "qmt/style/style.h" + +#include +#include +#include +#include +#include + +namespace qmt { + +static const qreal SWIMLANE_LENGTH = 100000; +static const qreal SWIMLANE_WIDTH = 16; +static const qreal SWIMLANE_MARKER_WIDTH = 8; + +SwimlaneItem::SwimlaneItem(DSwimlane *swimlane, DiagramSceneModel *diagramSceneModel, + QGraphicsItem *parent) + : QGraphicsItem (parent), + m_swimlane(swimlane), + m_diagramSceneModel(diagramSceneModel) +{ + setFlags(QGraphicsItem::ItemIsSelectable); +} + +SwimlaneItem::~SwimlaneItem() +{ +} + +QRectF SwimlaneItem::boundingRect() const +{ + if (m_swimlane->isHorizontal()) + return QRectF(-SWIMLANE_LENGTH/2, -SWIMLANE_WIDTH/2, SWIMLANE_LENGTH, SWIMLANE_WIDTH); + else + return QRectF(-SWIMLANE_WIDTH/2, -SWIMLANE_LENGTH/2, SWIMLANE_WIDTH, SWIMLANE_LENGTH); +} + +void SwimlaneItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(painter); + Q_UNUSED(option); + Q_UNUSED(widget); +} + +void SwimlaneItem::update() +{ + QMT_CHECK(!m_isUpdating); + m_isUpdating = true; + + prepareGeometryChange(); + + const Style *style = adaptedStyle(); + Q_UNUSED(style); + + // swimline line + if (!m_lineItem) + m_lineItem = new QGraphicsLineItem(this); + m_lineItem->setPen(QPen(QBrush(Qt::black), 1, Qt::DashLine)); + + updateSelectionMarker(); + updateGeometry(); + setZValue(SWIMLANE_ITEMS_ZVALUE); + + m_isUpdating = false; +} + +void SwimlaneItem::moveDelta(const QPointF &delta) +{ + m_diagramSceneModel->diagramController()->startUpdateElement(m_swimlane, m_diagramSceneModel->diagram(), + DiagramController::UpdateGeometry); + if (m_swimlane->isHorizontal()) + m_swimlane->setPos(m_swimlane->pos() + delta.y()); + else + m_swimlane->setPos(m_swimlane->pos() + delta.x()); + m_diagramSceneModel->diagramController()->finishUpdateElement(m_swimlane, m_diagramSceneModel->diagram(), false); +} + +void SwimlaneItem::alignItemPositionToRaster(double rasterWidth, double rasterHeight) +{ + if (m_swimlane->isHorizontal()) { + qreal yDelta = qRound(m_swimlane->pos() / rasterHeight) * rasterHeight - m_swimlane->pos(); + moveDelta(QPointF(0, yDelta)); + } else { + qreal xDelta = qRound(m_swimlane->pos() / rasterWidth) * rasterWidth - m_swimlane->pos(); + moveDelta(QPointF(xDelta, 0)); + } +} + +bool SwimlaneItem::isSecondarySelected() const +{ + return m_secondarySelected; +} + +void SwimlaneItem::setSecondarySelected(bool secondarySelected) +{ + if (m_secondarySelected != secondarySelected) { + m_secondarySelected = secondarySelected; + update(); + } +} + +bool SwimlaneItem::isFocusSelected() const +{ + return false; +} + +void SwimlaneItem::setFocusSelected(bool focusSelected) +{ + Q_UNUSED(focusSelected); +} + +QRectF SwimlaneItem::getSecondarySelectionBoundary() +{ + QRectF boundary; + if (m_swimlane->isHorizontal()) + boundary = QRectF(-SWIMLANE_LENGTH/2, pos().y(), SWIMLANE_LENGTH, SWIMLANE_LENGTH); + else + boundary = QRectF(pos().x(), -SWIMLANE_LENGTH/2, SWIMLANE_LENGTH, SWIMLANE_LENGTH); + return boundary; +} + +void SwimlaneItem::setBoundarySelected(const QRectF &boundary, bool secondary) +{ + qreal pos = m_swimlane->pos(); + bool c; + + if (m_swimlane->isHorizontal()) + c = pos >= boundary.top() && pos <= boundary.bottom() && boundary.top() > -SWIMLANE_LENGTH/2; + else + c = pos >= boundary.left() && pos <= boundary.right() && boundary.left() > -SWIMLANE_LENGTH/2; + if (c) { + if (secondary) + setSecondarySelected(true); + else + setSelected(true); + } +} + +void SwimlaneItem::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + if (event->button() == Qt::LeftButton || event->button() == Qt::RightButton) { + bool multiSelect = (event->modifiers() & Qt::ControlModifier) != 0; + m_diagramSceneModel->selectItem(this, multiSelect); + } +} + +void SwimlaneItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + if (event->buttons() & Qt::LeftButton) { + QPointF delta = event->scenePos() - event->lastScenePos(); + if (m_swimlane->isHorizontal()) + delta.setX(0.0); + else + delta.setY(0.0); + m_diagramSceneModel->moveSelectedItems(this, delta); + } +} + +void SwimlaneItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) { + if (event->scenePos() != event->buttonDownScenePos(Qt::LeftButton)) + m_diagramSceneModel->alignSelectedItemsPositionOnRaster(); + } +} + +void SwimlaneItem::updateSelectionMarker() +{ + if (isSelected() || m_secondarySelected) { + if (!m_selectionMarker) + m_selectionMarker = new QGraphicsRectItem(this); + m_selectionMarker->setBrush(isSelected() ? Qt::lightGray : Qt::transparent); + m_selectionMarker->setPen(isSelected() ? Qt::NoPen : QPen(Qt::lightGray)); + m_selectionMarker->setZValue(-1); + } else if (m_selectionMarker) { + if (m_selectionMarker->scene()) + m_selectionMarker->scene()->removeItem(m_selectionMarker); + delete m_selectionMarker; + m_selectionMarker = nullptr; + } +} + +const Style *SwimlaneItem::adaptedStyle() +{ + return m_diagramSceneModel->styleController()->adaptSwimlaneStyle(m_swimlane); +} + +QSizeF SwimlaneItem::calcMinimumGeometry() const +{ + if (m_swimlane->isHorizontal()) + return QSizeF(SWIMLANE_LENGTH, SWIMLANE_WIDTH); + else + return QSizeF(SWIMLANE_WIDTH, SWIMLANE_LENGTH); +} + +void SwimlaneItem::updateGeometry() +{ + prepareGeometryChange(); + + QSizeF geometry = calcMinimumGeometry(); + qreal width = geometry.width(); + qreal height = geometry.height(); + + if (m_swimlane->isHorizontal()) { + setPos(0, m_swimlane->pos()); + if (m_lineItem) + m_lineItem->setLine(-width / 2, 0, width / 2, 0); + if (m_selectionMarker) + m_selectionMarker->setRect(-width / 2, -SWIMLANE_MARKER_WIDTH / 2, width, SWIMLANE_MARKER_WIDTH); + } else { + setPos(m_swimlane->pos(), 0); + if (m_lineItem) + m_lineItem->setLine(0, -height / 2, 0, height / 2); + if (m_selectionMarker) + m_selectionMarker->setRect(-SWIMLANE_MARKER_WIDTH / 2, -height / 2, SWIMLANE_MARKER_WIDTH, height); + } +} + +} // namespace qmt diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/swimlaneitem.h b/src/libs/modelinglib/qmt/diagram_scene/items/swimlaneitem.h new file mode 100644 index 00000000000..bae23feaf11 --- /dev/null +++ b/src/libs/modelinglib/qmt/diagram_scene/items/swimlaneitem.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Jochen Becher +** 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 + +#include "qmt/diagram_scene/capabilities/moveable.h" +#include "qmt/diagram_scene/capabilities/selectable.h" + +namespace qmt { + +class DSwimlane; +class DiagramSceneModel; +class Style; + +class SwimlaneItem : + public QGraphicsItem, + public IMoveable, + public ISelectable +{ +public: + SwimlaneItem(DSwimlane *swimlane, DiagramSceneModel *diagramSceneModel, + QGraphicsItem *parent = nullptr); + ~SwimlaneItem() override; + + DSwimlane *swimlane() const { return m_swimlane; } + DiagramSceneModel *diagramSceneModel() const { return m_diagramSceneModel; } + + QRectF boundingRect() const override; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; + + virtual void update(); + + void moveDelta(const QPointF &delta) override; + void alignItemPositionToRaster(double rasterWidth, double rasterHeight) override; + + bool isSecondarySelected() const override; + void setSecondarySelected(bool secondarySelected) override; + bool isFocusSelected() const override; + void setFocusSelected(bool focusSelected) override; + QRectF getSecondarySelectionBoundary() override; + void setBoundarySelected(const QRectF &boundary, bool secondary) override; + +protected: + void mousePressEvent(QGraphicsSceneMouseEvent *event) override; + void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override; + void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; + + void updateSelectionMarker(); + const Style *adaptedStyle(); + +private: + QSizeF calcMinimumGeometry() const; + void updateGeometry(); + + DSwimlane *m_swimlane = nullptr; + DiagramSceneModel *m_diagramSceneModel = nullptr; + QGraphicsLineItem *m_lineItem = nullptr; + QGraphicsRectItem *m_selectionMarker = nullptr; + bool m_isUpdating = false; + bool m_secondarySelected = false; +}; + +} // namespace qmt diff --git a/src/libs/modelinglib/qmt/diagram_ui/diagram_mime_types.h b/src/libs/modelinglib/qmt/diagram_ui/diagram_mime_types.h index 5926f07ba18..f1f56bfe74b 100644 --- a/src/libs/modelinglib/qmt/diagram_ui/diagram_mime_types.h +++ b/src/libs/modelinglib/qmt/diagram_ui/diagram_mime_types.h @@ -38,5 +38,6 @@ static const char ELEMENT_TYPE_CLASS[] = "class"; static const char ELEMENT_TYPE_ITEM[] = "item"; static const char ELEMENT_TYPE_ANNOTATION[] = "annotation"; static const char ELEMENT_TYPE_BOUNDARY[] = "boundary"; +static const char ELEMENT_TYPE_SWIMLANE[] = "swimlane"; } // namespace qmt diff --git a/src/libs/modelinglib/qmt/diagram_widgets_ui/diagramview.cpp b/src/libs/modelinglib/qmt/diagram_widgets_ui/diagramview.cpp index 16f361a1ea8..ad361c63c13 100644 --- a/src/libs/modelinglib/qmt/diagram_widgets_ui/diagramview.cpp +++ b/src/libs/modelinglib/qmt/diagram_widgets_ui/diagramview.cpp @@ -62,8 +62,11 @@ void DiagramView::setDiagramSceneModel(DiagramSceneModel *diagramSceneModel) { setScene(0); m_diagramSceneModel = diagramSceneModel; - if (diagramSceneModel) + if (diagramSceneModel) { setScene(m_diagramSceneModel->graphicsScene()); + connect(m_diagramSceneModel, &DiagramSceneModel::sceneRectChanged, + this, &DiagramView::onSceneRectChanged, Qt::QueuedConnection); + } } void DiagramView::dragEnterEvent(QDragEnterEvent *event) @@ -110,14 +113,17 @@ void DiagramView::dragMoveEvent(QDragMoveEvent *event) void DiagramView::dropEvent(QDropEvent *event) { event->setDropAction(Qt::MoveAction); + DiagramSceneController *diagramSceneController = m_diagramSceneModel->diagramSceneController(); if (event->mimeData()->hasFormat(QLatin1String(MIME_TYPE_MODEL_ELEMENTS))) { QDataStream dataStream(event->mimeData()->data(QLatin1String(MIME_TYPE_MODEL_ELEMENTS))); while (dataStream.status() == QDataStream::Ok) { QString key; dataStream >> key; if (!key.isEmpty()) { - if (m_diagramSceneModel->diagramSceneController()->isAddingAllowed(Uid(key), m_diagramSceneModel->diagram())) - m_diagramSceneModel->diagramSceneController()->addExistingModelElement(Uid(key), mapToScene(event->pos()), m_diagramSceneModel->diagram()); + if (diagramSceneController->isAddingAllowed(Uid(key), m_diagramSceneModel->diagram())) { + diagramSceneController->addExistingModelElement(Uid(key), mapToScene(event->pos()), + m_diagramSceneModel->diagram()); + } } } event->accept(); @@ -130,7 +136,9 @@ void DiagramView::dropEvent(QDropEvent *event) dataStream >> newElementId >> name >> stereotype; if (!newElementId.isEmpty()) { QPointF pos = mapToScene(event->pos()); - m_diagramSceneModel->diagramSceneController()->dropNewElement(newElementId, name, stereotype, m_diagramSceneModel->findTopmostElement(pos), pos, m_diagramSceneModel->diagram()); + diagramSceneController->dropNewElement( + newElementId, name, stereotype, m_diagramSceneModel->findTopmostElement(pos), + pos, m_diagramSceneModel->diagram(), event->pos(), size()); } } event->accept(); @@ -139,4 +147,10 @@ void DiagramView::dropEvent(QDropEvent *event) } } +void DiagramView::onSceneRectChanged(const QRectF &sceneRect) +{ + // TODO add some adjustment to all 4 sides? + setSceneRect(sceneRect); +} + } // namespace qmt diff --git a/src/libs/modelinglib/qmt/diagram_widgets_ui/diagramview.h b/src/libs/modelinglib/qmt/diagram_widgets_ui/diagramview.h index 3ddc1951b1a..c4a01b76d30 100644 --- a/src/libs/modelinglib/qmt/diagram_widgets_ui/diagramview.h +++ b/src/libs/modelinglib/qmt/diagram_widgets_ui/diagramview.h @@ -51,6 +51,8 @@ protected: void dropEvent(QDropEvent *event) override; private: + void onSceneRectChanged(const QRectF &sceneRect); + QPointer m_diagramSceneModel; }; diff --git a/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.cpp b/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.cpp index dd299b3bb78..af47417aaab 100644 --- a/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.cpp +++ b/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.cpp @@ -59,6 +59,7 @@ #include "qmt/diagram/dconnection.h" #include "qmt/diagram/dannotation.h" #include "qmt/diagram/dboundary.h" +#include "qmt/diagram/dswimlane.h" // TODO move into better place #include "qmt/diagram_scene/items/stereotypedisplayvisitor.h" @@ -1183,6 +1184,12 @@ void PropertiesView::MView::visitDBoundary(const DBoundary *boundary) visitDElement(boundary); } +void PropertiesView::MView::visitDSwimlane(const DSwimlane *swimlane) +{ + setTitle(m_diagramElements, tr("Swimlane"), tr("Swimlanes")); + visitDElement(swimlane); +} + void PropertiesView::MView::onStereotypesChanged(const QString &stereotypes) { QList set = m_stereotypesController->fromString(stereotypes); diff --git a/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.h b/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.h index 4c6794fb7f4..98c3f61c66c 100644 --- a/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.h +++ b/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.h @@ -94,6 +94,7 @@ public: void visitDConnection(const DConnection *connection) override; void visitDAnnotation(const DAnnotation *annotation) override; void visitDBoundary(const DBoundary *boundary) override; + void visitDSwimlane(const DSwimlane *swimlane) override; void update(QList &modelElements); void update(QList &diagramElements, MDiagram *diagram); diff --git a/src/libs/modelinglib/qmt/qmt.pri b/src/libs/modelinglib/qmt/qmt.pri index 8d27d4e9e9c..14f38f69918 100644 --- a/src/libs/modelinglib/qmt/qmt.pri +++ b/src/libs/modelinglib/qmt/qmt.pri @@ -160,6 +160,8 @@ HEADERS += \ $$PWD/tasks/isceneinspector.h \ $$PWD/tasks/voidelementtasks.h \ $$PWD/infrastructure/qmtassert.h \ + $$PWD/diagram_scene/items/swimlaneitem.h \ + $$PWD/diagram/dswimlane.h SOURCES += \ $$PWD/config/configcontroller.cpp \ @@ -286,6 +288,8 @@ SOURCES += \ $$PWD/tasks/finddiagramvisitor.cpp \ $$PWD/tasks/findrootdiagramvisitor.cpp \ $$PWD/tasks/voidelementtasks.cpp \ + $$PWD/diagram_scene/items/swimlaneitem.cpp \ + $$PWD/diagram/dswimlane.cpp RESOURCES += \ $$PWD/resources/resources.qrc diff --git a/src/libs/modelinglib/qmt/resources/48x48/swimlane.png b/src/libs/modelinglib/qmt/resources/48x48/swimlane.png new file mode 100644 index 0000000000000000000000000000000000000000..ae2b89fb24091d72362fe03ec6883201caf3392b GIT binary patch literal 191 zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4mJh`hH$2z?F42N{x=9SGJLt{HkV_= tu7bTRFBbJ$2{Jgy=U(Y#VEB;F{!&?u<9UePBL)Tr22WQ%mvv4FO#rlJLCydG literal 0 HcmV?d00001 diff --git a/src/libs/modelinglib/qmt/resources/resources.qrc b/src/libs/modelinglib/qmt/resources/resources.qrc index 896e41c050e..f6ff6af1198 100644 --- a/src/libs/modelinglib/qmt/resources/resources.qrc +++ b/src/libs/modelinglib/qmt/resources/resources.qrc @@ -21,5 +21,6 @@ 48x48/inheritance.png 48x48/item.png 48x48/package.png + 48x48/swimlane.png diff --git a/src/libs/modelinglib/qmt/serializer/diagramserializer.cpp b/src/libs/modelinglib/qmt/serializer/diagramserializer.cpp index 01d02d87291..893d2008304 100644 --- a/src/libs/modelinglib/qmt/serializer/diagramserializer.cpp +++ b/src/libs/modelinglib/qmt/serializer/diagramserializer.cpp @@ -45,6 +45,7 @@ #include "qmt/diagram/dannotation.h" #include "qmt/diagram/dboundary.h" +#include "qmt/diagram/dswimlane.h" #include "qark/qxmloutarchive.h" #include "qark/qxmlinarchive.h" @@ -403,4 +404,23 @@ inline void Access::serialize(Archive &archive, DBoundary &b QARK_ACCESS_SPECIALIZE(QXmlInArchive, QXmlOutArchive, DBoundary) +// DSwimlane + +QARK_REGISTER_TYPE_NAME(DSwimlane, "DSwimlane") +QARK_REGISTER_DERIVED_CLASS(QXmlInArchive, QXmlOutArchive, DSwimlane, DElement) +QARK_ACCESS_SERIALIZE(DSwimlane) + +template +inline void Access::serialize(Archive &archive, DSwimlane &swimlane) +{ + archive || tag(swimlane) + || base(swimlane) + || attr(QStringLiteral("text"), swimlane, &DSwimlane::text, &DSwimlane::setText) + || attr(QStringLiteral("horizontal"), swimlane, &DSwimlane::isHorizontal, &DSwimlane::setHorizontal) + || attr(QStringLiteral("pos"), swimlane, &DSwimlane::pos, &DSwimlane::setPos) + || end; +} + +QARK_ACCESS_SPECIALIZE(QXmlInArchive, QXmlOutArchive, DSwimlane) + } // namespace qark diff --git a/src/libs/modelinglib/qmt/style/defaultstyleengine.cpp b/src/libs/modelinglib/qmt/style/defaultstyleengine.cpp index b268ee59cd3..7f69962c677 100644 --- a/src/libs/modelinglib/qmt/style/defaultstyleengine.cpp +++ b/src/libs/modelinglib/qmt/style/defaultstyleengine.cpp @@ -40,7 +40,6 @@ #include #include -#include namespace { @@ -158,6 +157,26 @@ bool operator==(const BoundaryStyleKey &lhs, const BoundaryStyleKey &rhs) return true; } +// TODO remove class if no attributes needed even with future extensions +class SwimlaneStyleKey +{ +}; + +uint qHash(const SwimlaneStyleKey &styleKey) +{ + Q_UNUSED(styleKey); + + return 1; +} + +bool operator==(const SwimlaneStyleKey &lhs, const SwimlaneStyleKey &rhs) +{ + Q_UNUSED(lhs); + Q_UNUSED(rhs); + + return true; +} + DefaultStyleEngine::DefaultStyleEngine() { } @@ -190,6 +209,8 @@ const Style *DefaultStyleEngine::applyStyle(const Style *baseStyle, StyleEngine: parameters); case TypeOther: break; + case TypeSwimlane: + return applySwimlaneStyle(baseStyle, parameters); } return baseStyle; } @@ -371,6 +392,13 @@ const Style *DefaultStyleEngine::applyBoundaryStyle(const Style *baseStyle, cons return applyBoundaryStyle(baseStyle, parameters); } +const Style *DefaultStyleEngine::applySwimlaneStyle(const Style *baseStyle, const DSwimlane *swimlane, const StyleEngine::Parameters *parameters) +{ + Q_UNUSED(swimlane); + + return applySwimlaneStyle(baseStyle, parameters); +} + const Style *DefaultStyleEngine::applyAnnotationStyle(const Style *baseStyle, DAnnotation::VisualRole visualRole, const StyleEngine::Parameters *parameters) { @@ -429,6 +457,22 @@ const Style *DefaultStyleEngine::applyBoundaryStyle(const Style *baseStyle, cons return derivedStyle; } +const Style *DefaultStyleEngine::applySwimlaneStyle(const Style *baseStyle, const StyleEngine::Parameters *parameters) +{ + Q_UNUSED(parameters); + + SwimlaneStyleKey key; + const Style *derivedStyle = m_swimlaneStyleMap.value(key); + if (!derivedStyle) { + auto style = new Style(baseStyle->type()); + style->setNormalFont(baseStyle->normalFont()); + style->setTextBrush(baseStyle->textBrush()); + m_swimlaneStyleMap.insert(key, style); + derivedStyle = style; + } + return derivedStyle; +} + DefaultStyleEngine::ElementType DefaultStyleEngine::objectType(const DObject *object) { ElementType elementType; @@ -459,7 +503,6 @@ bool DefaultStyleEngine::areStackingRoles(DObject::VisualPrimaryRole rhsPrimaryR case DObject::SecondaryRoleLighter: case DObject::SecondaryRoleDarker: return lhsPrimaryRole == rhsPrimaryRole; - break; case DObject::SecondaryRoleSoften: case DObject::SecondaryRoleOutline: return false; @@ -495,7 +538,11 @@ QColor DefaultStyleEngine::baseColor(ElementType elementType, ObjectVisuals obje case TypeItem: baseColor = QColor("#B995C6"); break; - default: + case TypeRelation: + case TypeAnnotation: + case TypeBoundary: + case TypeSwimlane: + case TypeOther: baseColor = QColor("#BF7D65"); break; } diff --git a/src/libs/modelinglib/qmt/style/defaultstyleengine.h b/src/libs/modelinglib/qmt/style/defaultstyleengine.h index 792b9247a09..6f73b72b3fe 100644 --- a/src/libs/modelinglib/qmt/style/defaultstyleengine.h +++ b/src/libs/modelinglib/qmt/style/defaultstyleengine.h @@ -42,6 +42,7 @@ class ObjectStyleKey; class RelationStyleKey; class AnnotationStyleKey; class BoundaryStyleKey; +class SwimlaneStyleKey; class QMT_EXPORT DefaultStyleEngine : public StyleEngine { @@ -64,11 +65,14 @@ public: const Parameters *parameters) override; const Style *applyBoundaryStyle(const Style *baseStyle, const DBoundary *boundary, const Parameters *parameters) override; + const Style *applySwimlaneStyle(const Style *baseStyle, const DSwimlane *swimlane, + const Parameters *parameters) override; private: const Style *applyAnnotationStyle(const Style *baseStyle, DAnnotation::VisualRole visualRole, const Parameters *parameters); const Style *applyBoundaryStyle(const Style *baseStyle, const Parameters *parameters); + const Style *applySwimlaneStyle(const Style *baseStyle, const Parameters *parameters); ElementType objectType(const DObject *object); @@ -87,6 +91,7 @@ private: QHash m_relationStyleMap; QHash m_annotationStyleMap; QHash m_boundaryStyleMap; + QHash m_swimlaneStyleMap; }; } // namespace qmt diff --git a/src/libs/modelinglib/qmt/style/stylecontroller.cpp b/src/libs/modelinglib/qmt/style/stylecontroller.cpp index 89a6fd243cb..2a194aaf3a5 100644 --- a/src/libs/modelinglib/qmt/style/stylecontroller.cpp +++ b/src/libs/modelinglib/qmt/style/stylecontroller.cpp @@ -104,6 +104,12 @@ const Style *StyleController::adaptBoundaryStyle(const DBoundary *boundary) return m_defaultStyleEngine->applyBoundaryStyle(m_defaultStyle.data(), boundary, ¶meters); } +const Style *StyleController::adaptSwimlaneStyle(const DSwimlane *swimlane) +{ + Parameters parameters(this); + return m_defaultStyleEngine->applySwimlaneStyle(m_defaultStyle.data(), swimlane, ¶meters); +} + const Style *StyleController::relationStarterStyle() { return m_relationStarterStyle.data(); diff --git a/src/libs/modelinglib/qmt/style/stylecontroller.h b/src/libs/modelinglib/qmt/style/stylecontroller.h index 344409e9415..9163a6b0b6a 100644 --- a/src/libs/modelinglib/qmt/style/stylecontroller.h +++ b/src/libs/modelinglib/qmt/style/stylecontroller.h @@ -60,6 +60,7 @@ public: const Style *adaptRelationStyle(const StyledRelation &relation); const Style *adaptAnnotationStyle(const DAnnotation *annotation); const Style *adaptBoundaryStyle(const DBoundary *boundary); + const Style *adaptSwimlaneStyle(const DSwimlane *swimlane); const Style *relationStarterStyle(); private: diff --git a/src/libs/modelinglib/qmt/style/styleengine.h b/src/libs/modelinglib/qmt/style/styleengine.h index 2da52b429a2..1b2828ceb25 100644 --- a/src/libs/modelinglib/qmt/style/styleengine.h +++ b/src/libs/modelinglib/qmt/style/styleengine.h @@ -40,6 +40,7 @@ class StyledRelation; class DAnnotation; class DBoundary; +class DSwimlane; class QMT_EXPORT StyleEngine { @@ -52,7 +53,8 @@ public: TypeItem, TypeRelation, TypeAnnotation, - TypeBoundary + TypeBoundary, + TypeSwimlane }; class Parameters @@ -77,6 +79,8 @@ public: const Parameters *) = 0; virtual const Style *applyBoundaryStyle(const Style *baseStyle, const DBoundary *, const Parameters *) = 0; + virtual const Style *applySwimlaneStyle(const Style *baseStyle, const DSwimlane *, + const Parameters *) = 0; }; } // namespace qmt diff --git a/src/libs/modelinglib/qmt/tasks/alignonrastervisitor.cpp b/src/libs/modelinglib/qmt/tasks/alignonrastervisitor.cpp index eeef4c866b6..f02646dbd91 100644 --- a/src/libs/modelinglib/qmt/tasks/alignonrastervisitor.cpp +++ b/src/libs/modelinglib/qmt/tasks/alignonrastervisitor.cpp @@ -40,6 +40,7 @@ #include "qmt/diagram/dobject.h" #include "qmt/diagram/dpackage.h" #include "qmt/diagram/drelation.h" +#include "qmt/diagram/dswimlane.h" #include "qmt/diagram_scene/capabilities/moveable.h" #include "qmt/diagram_scene/capabilities/resizable.h" #include "qmt/diagram_scene/diagramsceneconstants.h" @@ -159,4 +160,11 @@ void AlignOnRasterVisitor::visitDBoundary(DBoundary *boundary) moveable->alignItemPositionToRaster(RASTER_WIDTH, RASTER_HEIGHT); } +void AlignOnRasterVisitor::visitDSwimlane(DSwimlane *swimlane) +{ + IMoveable *moveable = m_sceneInspector->moveable(swimlane, m_diagram); + if (moveable) + moveable->alignItemPositionToRaster(RASTER_WIDTH, RASTER_HEIGHT); +} + } // namespace qmt diff --git a/src/libs/modelinglib/qmt/tasks/alignonrastervisitor.h b/src/libs/modelinglib/qmt/tasks/alignonrastervisitor.h index 42f9565ebdd..690ae88129e 100644 --- a/src/libs/modelinglib/qmt/tasks/alignonrastervisitor.h +++ b/src/libs/modelinglib/qmt/tasks/alignonrastervisitor.h @@ -58,6 +58,7 @@ public: void visitDConnection(DConnection *connection) override; void visitDAnnotation(DAnnotation *annotation) override; void visitDBoundary(DBoundary *boundary) override; + void visitDSwimlane(DSwimlane *swimlane) override; private: DiagramController *m_diagramController; diff --git a/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.cpp b/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.cpp index b241418f57b..21fef7500bd 100644 --- a/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.cpp +++ b/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.cpp @@ -38,6 +38,7 @@ #include "qmt/diagram/drelation.h" #include "qmt/diagram/dassociation.h" #include "qmt/diagram/dconnection.h" +#include "qmt/diagram/dswimlane.h" #include "qmt/diagram_ui/diagram_mime_types.h" #include "qmt/model_controller/modelcontroller.h" #include "qmt/model_controller/mselection.h" @@ -339,7 +340,8 @@ void DiagramSceneController::addExistingModelElement(const Uid &modelElementKey, } void DiagramSceneController::dropNewElement(const QString &newElementId, const QString &name, const QString &stereotype, - DElement *topMostElementAtPos, const QPointF &pos, MDiagram *diagram) + DElement *topMostElementAtPos, const QPointF &pos, MDiagram *diagram, + const QPoint &viewPos, const QSize &viewSize) { if (newElementId == QLatin1String(ELEMENT_TYPE_ANNOTATION)) { auto annotation = new DAnnotation(); @@ -354,6 +356,16 @@ void DiagramSceneController::dropNewElement(const QString &newElementId, const Q m_diagramController->addElement(boundary, diagram); alignOnRaster(boundary, diagram); emit newElementCreated(boundary, diagram); + } else if (newElementId == QLatin1String(ELEMENT_TYPE_SWIMLANE)) { + auto swimlane = new DSwimlane(); + qreal x = static_cast(viewPos.x()) / viewSize.width(); + qreal y = static_cast(viewPos.y()) / viewSize.height(); + bool horizontal = (y > x && (1-y) > x) || (y <= x && (1-y) <= x); + swimlane->setHorizontal(horizontal); + swimlane->setPos(horizontal ? pos.y() : pos.x()); + m_diagramController->addElement(swimlane, diagram); + alignOnRaster(swimlane, diagram); + emit newElementCreated(swimlane, diagram); } else { MPackage *parentPackage = findSuitableParentPackage(topMostElementAtPos, diagram); MObject *newObject = 0; diff --git a/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.h b/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.h index a30e9926a71..3a37791e1e0 100644 --- a/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.h +++ b/src/libs/modelinglib/qmt/tasks/diagramscenecontroller.h @@ -97,7 +97,7 @@ public: bool isAddingAllowed(const Uid &modelElementKey, MDiagram *diagram); void addExistingModelElement(const Uid &modelElementKey, const QPointF &pos, MDiagram *diagram); void dropNewElement(const QString &newElementId, const QString &name, const QString &stereotype, - DElement *topMostElementAtPos, const QPointF &pos, MDiagram *diagram); + DElement *topMostElementAtPos, const QPointF &pos, MDiagram *diagram, const QPoint &viewPos, const QSize &viewSize); void dropNewModelElement(MObject *modelObject, MPackage *parentPackage, const QPointF &pos, MDiagram *diagram); diff --git a/src/plugins/modeleditor/modeleditor.cpp b/src/plugins/modeleditor/modeleditor.cpp index 51715059059..b65117011ec 100644 --- a/src/plugins/modeleditor/modeleditor.cpp +++ b/src/plugins/modeleditor/modeleditor.cpp @@ -1046,6 +1046,9 @@ void ModelEditor::initToolbars() } else if (tool.m_elementType == QLatin1String(qmt::ELEMENT_TYPE_BOUNDARY)) { iconPath = QStringLiteral(":/modelinglib/48x48/boundary.png"); styleEngineElementType = qmt::StyleEngine::TypeBoundary; + } else if (tool.m_elementType == QLatin1String(qmt::ELEMENT_TYPE_SWIMLANE)) { + iconPath = QStringLiteral(":/modelinglib/48x48/swimlane.png"); + styleEngineElementType = qmt::StyleEngine::TypeSwimlane; } QIcon icon; if (!tool.m_stereotype.isEmpty() && stereotypeIconElement != qmt::StereotypeIcon::ElementAny) { @@ -1110,6 +1113,10 @@ void ModelEditor::initToolbars() new DragTool(QIcon(QStringLiteral(":/modelinglib/48x48/boundary.png")), tr("Boundary"), QLatin1String(qmt::ELEMENT_TYPE_BOUNDARY), QString(), toolBar)); + toolBarLayout->addWidget( + new DragTool(QIcon(QStringLiteral(":/modelinglib/48x48/swimlane.png")), + tr("Swimlane"), QLatin1String(qmt::ELEMENT_TYPE_SWIMLANE), + QString(), toolBar)); } // add stretch to all layouts and calculate width of tool bar diff --git a/src/plugins/modeleditor/openelementvisitor.cpp b/src/plugins/modeleditor/openelementvisitor.cpp index 312a67376a7..24292975281 100644 --- a/src/plugins/modeleditor/openelementvisitor.cpp +++ b/src/plugins/modeleditor/openelementvisitor.cpp @@ -137,6 +137,11 @@ void OpenDiagramElementVisitor::visitDBoundary(const qmt::DBoundary *boundary) Q_UNUSED(boundary); } +void OpenDiagramElementVisitor::visitDSwimlane(const qmt::DSwimlane *swimlane) +{ + Q_UNUSED(swimlane); +} + void OpenModelElementVisitor::setElementTasks(ElementTasks *elementTasks) { m_elementTasks = elementTasks; diff --git a/src/plugins/modeleditor/openelementvisitor.h b/src/plugins/modeleditor/openelementvisitor.h index 4848afa2e3b..5c07e07c317 100644 --- a/src/plugins/modeleditor/openelementvisitor.h +++ b/src/plugins/modeleditor/openelementvisitor.h @@ -42,20 +42,21 @@ public: void setModelController(qmt::ModelController *modelController); void setElementTasks(ElementTasks *elementTasks); - void visitDElement(const qmt::DElement *element); - void visitDObject(const qmt::DObject *object); - void visitDPackage(const qmt::DPackage *package); - void visitDClass(const qmt::DClass *klass); - void visitDComponent(const qmt::DComponent *component); - void visitDDiagram(const qmt::DDiagram *diagram); - void visitDItem(const qmt::DItem *item); - void visitDRelation(const qmt::DRelation *relation); - void visitDInheritance(const qmt::DInheritance *inheritance); - void visitDDependency(const qmt::DDependency *dependency); - void visitDAssociation(const qmt::DAssociation *association); - void visitDConnection(const qmt::DConnection *connection); - void visitDAnnotation(const qmt::DAnnotation *annotation); - void visitDBoundary(const qmt::DBoundary *boundary); + void visitDElement(const qmt::DElement *element) override; + void visitDObject(const qmt::DObject *object) override; + void visitDPackage(const qmt::DPackage *package) override; + void visitDClass(const qmt::DClass *klass) override; + void visitDComponent(const qmt::DComponent *component) override; + void visitDDiagram(const qmt::DDiagram *diagram) override; + void visitDItem(const qmt::DItem *item) override; + void visitDRelation(const qmt::DRelation *relation) override; + void visitDInheritance(const qmt::DInheritance *inheritance) override; + void visitDDependency(const qmt::DDependency *dependency) override; + void visitDAssociation(const qmt::DAssociation *association) override; + void visitDConnection(const qmt::DConnection *connection) override; + void visitDAnnotation(const qmt::DAnnotation *annotation) override; + void visitDBoundary(const qmt::DBoundary *boundary) override; + void visitDSwimlane(const qmt::DSwimlane *swimlane) override; private: qmt::ModelController *m_modelController = 0;