ModelEditor: Introduce custom relation type "Connection"

Change-Id: Iddd45508dcb2de1fa2b6d9b2b881b54a73172caf
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
This commit is contained in:
Jochen Becher
2016-08-23 21:47:12 +02:00
parent 82cb2b248e
commit ffb5dc756a
47 changed files with 1252 additions and 73 deletions

View File

@@ -64,13 +64,13 @@
// role: <The role of the end. A string that defaults to nothing.>
// cardinality: <An integer or a string defining the cardinality of the end. Defaults to nothing.>
// navigable: <If the end is navigable. One of Yes, No, True, False. Defaults to nothing.>
// Shape {
// }
// head: <Predefined shapes. One of none, arrow, triangle, filledtriangle, diamond, filleddiamond.
// Defaults to none.>
// }
// }
//
//
// A Dependency defines a number of settings of a dependency specialization:
// A Dependency defines settings of a dependency specialization:
//
// Dependency {
// id: <id>
@@ -183,24 +183,24 @@ Icon {
}
Association {
id: AggregationOne
title: "Aggregation (?:1)"
id: Aggregation
title: "Aggregation"
End {
end: A
cardinality: 1
cardinality: "*"
navigable: yes
relationship: aggregation
}
}
Association {
id: AggregationMany
title: "Aggregation (?:N)"
id: Composition
title: "Composition"
End {
end: A
cardinality: "*"
cardinality: "1"
navigable: yes
relationship: aggregation
relationship: composition
}
}
@@ -215,8 +215,8 @@ Toolbar {
Tool { element: dependency }
Tool { element: inheritance }
Tool { element: association }
Tool { element: AggregationOne }
Tool { element: AggregationMany }
Tool { element: Aggregation }
Tool { element: Composition }
}
}
@@ -304,6 +304,29 @@ Icon {
}
}
Relation {
id: Communication
elements: UseCase, Actor
pattern: solid
color: A
End {
end: A
}
End {
end: B
}
}
Toolbar {
id: UseCaseToolbar
element: UseCase, Actor
Tools {
Tool { element: Communication }
Tool { element: dependency }
}
}
// ****************
// ** Activities **
// ****************
@@ -409,15 +432,11 @@ Relation {
End {
end: A
elements: Start, Activity, Condition, HorizontalBar, VerticalBar
role: ""
}
End {
end: B
elements: Activity, Condition, HorizontalBar, VerticalBar, Termination
head: filledtriangle
//Shape {
// Triangle { x: 6; y: 5.2; width: 12; height: 10.4; filled: yes }
//}
head: arrow
}
}

View File

@@ -55,6 +55,8 @@ QtcLibrary {
"diagram/dclass.h",
"diagram/dcomponent.cpp",
"diagram/dcomponent.h",
"diagram/dconnection.cpp",
"diagram/dconnection.h",
"diagram/dconstvisitor.h",
"diagram/ddependency.cpp",
"diagram/ddependency.h",
@@ -114,6 +116,8 @@ QtcLibrary {
"diagram_scene/items/classitem.h",
"diagram_scene/items/componentitem.cpp",
"diagram_scene/items/componentitem.h",
"diagram_scene/items/connectionitem.cpp",
"diagram_scene/items/connectionitem.h",
"diagram_scene/items/diagramitem.cpp",
"diagram_scene/items/diagramitem.h",
"diagram_scene/items/itemitem.cpp",
@@ -188,6 +192,8 @@ QtcLibrary {
"model/mclassmember.h",
"model/mcomponent.cpp",
"model/mcomponent.h",
"model/mconnection.cpp",
"model/mconnection.h",
"model/mconstvisitor.h",
"model/mdependency.cpp",
"model/mdependency.h",

View File

@@ -0,0 +1,103 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "dconnection.h"
#include "dvisitor.h"
#include "dconstvisitor.h"
namespace qmt {
DConnectionEnd::DConnectionEnd()
{
}
DConnectionEnd::~DConnectionEnd()
{
}
void DConnectionEnd::setName(const QString &name)
{
m_name = name;
}
void DConnectionEnd::setCardinatlity(const QString &cardinality)
{
m_cardinality = cardinality;
}
void DConnectionEnd::setNavigable(bool navigable)
{
m_isNavigable = navigable;
}
bool operator==(const DConnectionEnd &lhs, const DConnectionEnd &rhs)
{
if (&lhs == &rhs)
return true;
return lhs.name() == rhs.name()
&& lhs.cardinality() == rhs.cardinality()
&& lhs.isNavigable() == rhs.isNavigable();
}
bool operator!=(const DConnectionEnd &lhs, const DConnectionEnd &rhs)
{
return !operator==(lhs, rhs);
}
DConnection::DConnection()
{
}
DConnection::~DConnection()
{
}
void DConnection::setCustomRelationId(const QString &customRelationId)
{
m_customRelationId = customRelationId;
}
void DConnection::setEndA(const DConnectionEnd &endA)
{
m_endA = endA;
}
void DConnection::setEndB(const DConnectionEnd &endB)
{
m_endB = endB;
}
void DConnection::accept(DVisitor *visitor)
{
visitor->visitDConnection(this);
}
void DConnection::accept(DConstVisitor *visitor) const
{
visitor->visitDConnection(this);
}
} // namespace qmt

View File

@@ -0,0 +1,78 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "drelation.h"
#include "qmt/model/mconnection.h"
namespace qmt {
class QMT_EXPORT DConnectionEnd
{
public:
DConnectionEnd();
~DConnectionEnd();
QString name() const { return m_name; }
void setName(const QString &name);
QString cardinality() const { return m_cardinality; }
void setCardinatlity(const QString &cardinality);
bool isNavigable() const { return m_isNavigable; }
void setNavigable(bool navigable);
private:
QString m_name;
QString m_cardinality;
bool m_isNavigable = false;
};
bool operator==(const DConnectionEnd &lhs, const DConnectionEnd &rhs);
bool operator!=(const DConnectionEnd &lhs, const DConnectionEnd &rhs);
class QMT_EXPORT DConnection : public DRelation
{
public:
DConnection();
~DConnection() override;
QString customRelationId() const { return m_customRelationId; }
void setCustomRelationId(const QString &customRelationId);
DConnectionEnd endA() const { return m_endA; }
void setEndA(const DConnectionEnd &endA);
DConnectionEnd endB() const { return m_endB; }
void setEndB(const DConnectionEnd &endB);
void accept(DVisitor *visitor) override;
void accept(DConstVisitor *visitor) const override;
private:
QString m_customRelationId;
DConnectionEnd m_endA;
DConnectionEnd m_endB;
};
} // namespace qmt

View File

@@ -38,6 +38,7 @@ class DRelation;
class DInheritance;
class DDependency;
class DAssociation;
class DConnection;
class DAnnotation;
class DBoundary;
@@ -57,6 +58,7 @@ public:
virtual void visitDInheritance(const DInheritance *inheritance) = 0;
virtual void visitDDependency(const DDependency *dependency) = 0;
virtual void visitDAssociation(const DAssociation *association) = 0;
virtual void visitDConnection(const DConnection *connection) = 0;
virtual void visitDAnnotation(const DAnnotation *annotation) = 0;
virtual void visitDBoundary(const DBoundary *boundary) = 0;
};

View File

@@ -38,6 +38,7 @@ class DRelation;
class DInheritance;
class DDependency;
class DAssociation;
class DConnection;
class DAnnotation;
class DBoundary;
@@ -57,6 +58,7 @@ public:
virtual void visitDInheritance(DInheritance *inheritance) = 0;
virtual void visitDDependency(DDependency *dependency) = 0;
virtual void visitDAssociation(DAssociation *association) = 0;
virtual void visitDConnection(DConnection *connection) = 0;
virtual void visitDAnnotation(DAnnotation *annotation) = 0;
virtual void visitDBoundary(DBoundary *boundary) = 0;
};

View File

@@ -36,6 +36,7 @@
#include "qmt/diagram/dinheritance.h"
#include "qmt/diagram/ddependency.h"
#include "qmt/diagram/dassociation.h"
#include "qmt/diagram/dconnection.h"
#include "qmt/diagram/dannotation.h"
#include "qmt/diagram/dboundary.h"
#include "qmt/infrastructure/qmtassert.h"
@@ -122,6 +123,13 @@ void DCloneVisitor::visitDAssociation(const DAssociation *association)
visitDRelation(association);
}
void DCloneVisitor::visitDConnection(const DConnection *connection)
{
if (!m_cloned)
m_cloned = new DConnection(*connection);
visitDRelation(connection);
}
void DCloneVisitor::visitDAnnotation(const DAnnotation *annotation)
{
if (!m_cloned)
@@ -215,6 +223,13 @@ void DCloneDeepVisitor::visitDAssociation(const DAssociation *association)
visitDRelation(association);
}
void DCloneDeepVisitor::visitDConnection(const DConnection *connection)
{
if (!m_cloned)
m_cloned = new DConnection(*connection);
visitDRelation(connection);
}
void DCloneDeepVisitor::visitDAnnotation(const DAnnotation *annotation)
{
if (!m_cloned)

View File

@@ -48,6 +48,7 @@ public:
void visitDInheritance(const DInheritance *inheritance) override;
void visitDDependency(const DDependency *dependency) override;
void visitDAssociation(const DAssociation *association) override;
void visitDConnection(const DConnection *connection) override;
void visitDAnnotation(const DAnnotation *annotation) override;
void visitDBoundary(const DBoundary *boundary) override;
@@ -73,6 +74,7 @@ public:
void visitDInheritance(const DInheritance *inheritance) override;
void visitDDependency(const DDependency *dependency) override;
void visitDAssociation(const DAssociation *association) override;
void visitDConnection(const DConnection *connection) override;
void visitDAnnotation(const DAnnotation *annotation) override;
void visitDBoundary(const DBoundary *boundary) override;

View File

@@ -36,6 +36,7 @@
#include "qmt/diagram/dinheritance.h"
#include "qmt/diagram/ddependency.h"
#include "qmt/diagram/dassociation.h"
#include "qmt/diagram/dconnection.h"
#include "qmt/model/melement.h"
#include "qmt/model/mobject.h"
@@ -149,4 +150,12 @@ void DFactory::visitMAssociation(const MAssociation *association)
visitMRelation(association);
}
void DFactory::visitMConnection(const MConnection *connection)
{
QMT_CHECK(!m_product);
auto diagramConnection = new DConnection();
m_product = diagramConnection;
visitMRelation(connection);
}
} // namespace qmt

View File

@@ -51,6 +51,7 @@ public:
void visitMDependency(const MDependency *dependency) override;
void visitMInheritance(const MInheritance *inheritance) override;
void visitMAssociation(const MAssociation *association) override;
void visitMConnection(const MConnection *connection) override;
private:
DElement *m_product;

View File

@@ -36,6 +36,7 @@
#include "qmt/diagram/dinheritance.h"
#include "qmt/diagram/ddependency.h"
#include "qmt/diagram/dassociation.h"
#include "qmt/diagram/dconnection.h"
#include "qmt/diagram/dannotation.h"
#include "qmt/diagram/dboundary.h"
#include "qmt/infrastructure/qmtassert.h"
@@ -142,6 +143,17 @@ void DFlatAssignmentVisitor::visitDAssociation(const DAssociation *association)
QMT_ASSERT(target, return);
target->setEndA(association->endA());
target->setEndB(association->endB());
// TODO assign assoziation class?
}
void DFlatAssignmentVisitor::visitDConnection(const DConnection *connection)
{
visitDRelation(connection);
auto target = dynamic_cast<DConnection *>(m_target);
QMT_CHECK(target);
target->setCustomRelationId(connection->customRelationId());
target->setEndA(connection->endA());
target->setEndB(connection->endB());
}
void DFlatAssignmentVisitor::visitDAnnotation(const DAnnotation *annotation)

View File

@@ -46,6 +46,7 @@ public:
void visitDInheritance(const DInheritance *inheritance) override;
void visitDDependency(const DDependency *dependency) override;
void visitDAssociation(const DAssociation *association) override;
void visitDConnection(const DConnection *connection) override;
void visitDAnnotation(const DAnnotation *annotation) override;
void visitDBoundary(const DBoundary *boundary) override;

View File

@@ -32,6 +32,7 @@
#include "qmt/diagram/drelation.h"
#include "qmt/diagram/ddependency.h"
#include "qmt/diagram/dassociation.h"
#include "qmt/diagram/dconnection.h"
#include "qmt/model/melement.h"
#include "qmt/model/mobject.h"
@@ -222,6 +223,27 @@ void DUpdateVisitor::visitMAssociation(const MAssociation *association)
visitMRelation(association);
}
void DUpdateVisitor::visitMConnection(const MConnection *connection)
{
auto dconnection = dynamic_cast<DConnection *>(m_target);
QMT_CHECK(dconnection);
if (isUpdating(connection->customRelationId() != dconnection->customRelationId()))
dconnection->setCustomRelationId(connection->customRelationId());
DConnectionEnd endA;
endA.setName(connection->endA().name());
endA.setCardinatlity(connection->endA().cardinality());
endA.setNavigable(connection->endA().isNavigable());
if (isUpdating(endA != dconnection->endA()))
dconnection->setEndA(endA);
DConnectionEnd endB;
endB.setName(connection->endB().name());
endB.setCardinatlity(connection->endB().cardinality());
endB.setNavigable(connection->endB().isNavigable());
if (isUpdating(endB != dconnection->endB()))
dconnection->setEndB(endB);
visitMRelation(connection);
}
bool DUpdateVisitor::isUpdating(bool valueChanged)
{
if (m_checkNeedsUpdate) {

View File

@@ -52,6 +52,7 @@ public:
void visitMDependency(const MDependency *dependency) override;
void visitMInheritance(const MInheritance *inheritance) override;
void visitMAssociation(const MAssociation *association) override;
void visitMConnection(const MConnection *connection) override;
private:
bool isUpdating(bool valueChanged);

View File

@@ -36,6 +36,7 @@
#include "qmt/diagram/dinheritance.h"
#include "qmt/diagram/ddependency.h"
#include "qmt/diagram/dassociation.h"
#include "qmt/diagram/dconnection.h"
#include "qmt/diagram/dannotation.h"
#include "qmt/diagram/dboundary.h"
@@ -100,6 +101,11 @@ void DVoidVisitor::visitDAssociation(DAssociation *association)
visitDRelation(association);
}
void DVoidVisitor::visitDConnection(DConnection *connection)
{
visitDRelation(connection);
}
void DVoidVisitor::visitDAnnotation(DAnnotation *annotation)
{
visitDElement(annotation);
@@ -169,6 +175,11 @@ void DConstVoidVisitor::visitDAssociation(const DAssociation *association)
visitDRelation(association);
}
void DConstVoidVisitor::visitDConnection(const DConnection *connection)
{
visitDRelation(connection);
}
void DConstVoidVisitor::visitDAnnotation(const DAnnotation *annotation)
{
visitDElement(annotation);

View File

@@ -47,6 +47,7 @@ public:
void visitDInheritance(DInheritance *inheritance) override;
void visitDDependency(DDependency *dependency) override;
void visitDAssociation(DAssociation *association) override;
void visitDConnection(DConnection *connection) override;
void visitDAnnotation(DAnnotation *annotation) override;
void visitDBoundary(DBoundary *boundary) override;
};
@@ -67,6 +68,7 @@ public:
void visitDInheritance(const DInheritance *inheritance) override;
void visitDDependency(const DDependency *dependency) override;
void visitDAssociation(const DAssociation *association) override;
void visitDConnection(const DConnection *connection) override;
void visitDAnnotation(const DAnnotation *annotation) override;
void visitDBoundary(const DBoundary *boundary) override;
};

View File

@@ -32,6 +32,7 @@
#include "items/itemitem.h"
#include "items/relationitem.h"
#include "items/associationitem.h"
#include "items/connectionitem.h"
#include "items/annotationitem.h"
#include "items/boundaryitem.h"
@@ -46,6 +47,7 @@
#include "qmt/diagram/dinheritance.h"
#include "qmt/diagram/ddependency.h"
#include "qmt/diagram/dassociation.h"
#include "qmt/diagram/dconnection.h"
#include "qmt/diagram/dannotation.h"
#include "qmt/diagram/dboundary.h"
#include "qmt/infrastructure/qmtassert.h"
@@ -122,6 +124,12 @@ void DiagramSceneModel::CreationVisitor::visitDAssociation(DAssociation *associa
m_graphicsItem = new AssociationItem(association, m_diagramSceneModel);
}
void DiagramSceneModel::CreationVisitor::visitDConnection(DConnection *connection)
{
QMT_CHECK(!m_graphicsItem);
m_graphicsItem = new ConnectionItem(connection, m_diagramSceneModel);
}
void DiagramSceneModel::CreationVisitor::visitDAnnotation(DAnnotation *annotation)
{
QMT_CHECK(!m_graphicsItem);
@@ -262,6 +270,11 @@ void DiagramSceneModel::UpdateVisitor::visitDAssociation(DAssociation *associati
visitDRelation(association);
}
void DiagramSceneModel::UpdateVisitor::visitDConnection(DConnection *connection)
{
visitDRelation(connection);
}
void DiagramSceneModel::UpdateVisitor::visitDAnnotation(DAnnotation *annotation)
{
Q_UNUSED(annotation); // avoid warning in release mode

View File

@@ -49,6 +49,7 @@ public:
void visitDInheritance(DInheritance *inheritance) override;
void visitDDependency(DDependency *dependency) override;
void visitDAssociation(DAssociation *association) override;
void visitDConnection(DConnection *connection) override;
void visitDAnnotation(DAnnotation *annotation) override;
void visitDBoundary(DBoundary *boundary) override;
@@ -74,6 +75,7 @@ public:
void visitDInheritance(DInheritance *inheritance) override;
void visitDDependency(DDependency *dependency) override;
void visitDAssociation(DAssociation *association) override;
void visitDConnection(DConnection *connection) override;
void visitDAnnotation(DAnnotation *annotation) override;
void visitDBoundary(DBoundary *boundary) override;

View File

@@ -0,0 +1,170 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "connectionitem.h"
#include "qmt/diagram_controller/diagramcontroller.h"
#include "qmt/diagram/dconnection.h"
#include "qmt/diagram_scene/capabilities/intersectionable.h"
#include "qmt/diagram_scene/diagramscenemodel.h"
#include "qmt/diagram_scene/parts/arrowitem.h"
#include "qmt/infrastructure/geometryutilities.h"
#include "qmt/infrastructure/qmtassert.h"
#include "qmt/style/style.h"
#include <QGraphicsScene>
#include <QFont>
#include <QPen>
#include <QBrush>
#include <QVector2D>
#include <QPair>
namespace qmt {
ConnectionItem::ConnectionItem(DConnection *connection, DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent)
: RelationItem(connection, diagramSceneModel, parent),
m_connection(connection)
{
}
ConnectionItem::~ConnectionItem()
{
}
void ConnectionItem::update(const Style *style)
{
RelationItem::update(style);
updateEndLabels(m_connection->endA(), m_connection->endB(), &m_endAName, &m_endACardinality, style);
updateEndLabels(m_connection->endB(), m_connection->endA(), &m_endBName, &m_endBCardinality, style);
QMT_CHECK(m_arrow);
QGraphicsItem *endAItem = m_diagramSceneModel->graphicsItem(m_connection->endAUid());
if (!endAItem)
return;
placeEndLabels(m_arrow->firstLineSegment(), m_endAName, m_endACardinality, endAItem, m_arrow->startHeadLength());
QGraphicsItem *endBItem = m_diagramSceneModel->graphicsItem(m_connection->endBUid());
if (!endBItem)
return;
placeEndLabels(m_arrow->lastLineSegment(), m_endBName, m_endBCardinality, endBItem, m_arrow->endHeadLength());
}
void ConnectionItem::updateEndLabels(const DConnectionEnd &end, const DConnectionEnd &otherEnd,
QGraphicsSimpleTextItem **endName, QGraphicsSimpleTextItem **endCardinality,
const Style *style)
{
Q_UNUSED(end);
if (!otherEnd.name().isEmpty()) {
if (!*endName)
*endName = new QGraphicsSimpleTextItem(this);
(*endName)->setFont(style->smallFont());
(*endName)->setBrush(style->textBrush());
(*endName)->setText(otherEnd.name());
} else if (*endName) {
(*endName)->scene()->removeItem(*endName);
delete *endName;
*endName = 0;
}
if (!otherEnd.cardinality().isEmpty()) {
if (!*endCardinality)
*endCardinality = new QGraphicsSimpleTextItem(this);
(*endCardinality)->setFont(style->smallFont());
(*endCardinality)->setBrush(style->textBrush());
(*endCardinality)->setText(otherEnd.cardinality());
} else if (*endCardinality) {
(*endCardinality)->scene()->removeItem(*endCardinality);
delete *endCardinality;
*endCardinality = 0;
}
}
void ConnectionItem::placeEndLabels(const QLineF &lineSegment, QGraphicsItem *endName, QGraphicsItem *endCardinality,
QGraphicsItem *endItem, double headLength)
{
const double HEAD_OFFSET = headLength + 6.0;
const double SIDE_OFFSET = 4.0;
QPointF headOffset = QPointF(HEAD_OFFSET, 0);
QPointF sideOffset = QPointF(0.0, SIDE_OFFSET);
double angle = GeometryUtilities::calcAngle(lineSegment);
if (angle >= -5 && angle <= 5) {
if (endName)
endName->setPos(lineSegment.p1() + headOffset + sideOffset);
if (endCardinality)
endCardinality->setPos(lineSegment.p1() + headOffset - sideOffset
- endCardinality->boundingRect().bottomLeft());
} else if (angle <= -175 || angle >= 175) {
if (endName)
endName->setPos(lineSegment.p1() - headOffset + sideOffset - endName->boundingRect().topRight());
if (endCardinality)
endCardinality->setPos(lineSegment.p1() - headOffset
- sideOffset - endCardinality->boundingRect().bottomRight());
} else {
QRectF rect;
if (endCardinality)
rect = endCardinality->boundingRect();
if (endName)
rect = rect.united(endName->boundingRect().translated(rect.bottomLeft()));
QPointF rectPlacement;
GeometryUtilities::Side alignedSide = GeometryUtilities::SideUnspecified;
if (auto objectItem = dynamic_cast<IIntersectionable *>(endItem)) {
QPointF intersectionPoint;
QLineF intersectionLine;
if (objectItem->intersectShapeWithLine(GeometryUtilities::stretch(lineSegment.translated(pos()), 2.0, 0.0),
&intersectionPoint, &intersectionLine)) {
if (!GeometryUtilities::placeRectAtLine(rect, lineSegment, HEAD_OFFSET, SIDE_OFFSET,
intersectionLine, &rectPlacement, &alignedSide)) {
rectPlacement = intersectionPoint;
}
} else {
rectPlacement = lineSegment.p1();
}
} else {
rectPlacement = endItem->pos();
}
if (endCardinality) {
if (alignedSide == GeometryUtilities::SideRight)
endCardinality->setPos(rectPlacement
+ QPointF(rect.width() - endCardinality->boundingRect().width(), 0.0));
else
endCardinality->setPos(rectPlacement);
rectPlacement += endCardinality->boundingRect().bottomLeft();
}
if (endName) {
if (alignedSide == GeometryUtilities::SideRight)
endName->setPos(rectPlacement + QPointF(rect.width() - endName->boundingRect().width(), 0.0));
else
endName->setPos(rectPlacement);
}
}
}
} // namespace qmt

View File

@@ -0,0 +1,64 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "relationitem.h"
QT_BEGIN_NAMESPACE
class QGraphicsSimpleTextItem;
QT_END_NAMESPACE
namespace qmt {
class DConnection;
class DConnectionEnd;
class ConnectionItem : public RelationItem
{
public:
ConnectionItem(DConnection *connection, DiagramSceneModel *diagramSceneModel,
QGraphicsItem *parent = 0);
~ConnectionItem() override;
protected:
void update(const Style *style) override;
private:
void updateEndLabels(const DConnectionEnd &end, const DConnectionEnd &otherEnd,
QGraphicsSimpleTextItem **endName,
QGraphicsSimpleTextItem **endCardinality, const Style *style);
void placeEndLabels(const QLineF &lineSegment, QGraphicsItem *endName,
QGraphicsItem *endCardinality,
QGraphicsItem *endItem, double headLength);
DConnection *m_connection = 0;
QGraphicsSimpleTextItem *m_endAName = 0;
QGraphicsSimpleTextItem *m_endACardinality = 0;
QGraphicsSimpleTextItem *m_endBName = 0;
QGraphicsSimpleTextItem *m_endBCardinality = 0;
};
} // namespace qmt

View File

@@ -360,6 +360,8 @@ void ObjectItem::relationDrawn(const QString &id, ObjectItem *targetItem, const
return;
}
// create relation
diagramSceneController->createConnection(id, object(), relatedObject, intermediatePoints,
diagramSceneModel()->diagram());
}
break;
}

View File

@@ -28,6 +28,7 @@
#include "qmt/diagram_controller/diagramcontroller.h"
#include "qmt/diagram_controller/dvoidvisitor.h"
#include "qmt/diagram/dassociation.h"
#include "qmt/diagram/dconnection.h"
#include "qmt/diagram/ddependency.h"
#include "qmt/diagram/dinheritance.h"
#include "qmt/diagram/dobject.h"
@@ -41,6 +42,8 @@
#include "qmt/diagram_scene/parts/stereotypesitem.h"
#include "qmt/infrastructure/geometryutilities.h"
#include "qmt/infrastructure/qmtassert.h"
#include "qmt/stereotype/customrelation.h"
#include "qmt/stereotype/stereotypecontroller.h"
#include "qmt/style/stylecontroller.h"
#include "qmt/style/styledrelation.h"
#include "qmt/style/style.h"
@@ -166,6 +169,46 @@ public:
m_arrow->setPoints(m_points);
}
void visitDConnection(const DConnection *connection)
{
ArrowItem::Shaft shaft = ArrowItem::ShaftSolid;
ArrowItem::Head endAHead = ArrowItem::HeadNone;
ArrowItem::Head endBHead = ArrowItem::HeadNone;
CustomRelation customRelation = m_diagramSceneModel->stereotypeController()->findCustomRelation(connection->customRelationId());
if (!customRelation.isNull()) {
// TODO support custom shapes
static const QHash<CustomRelation::ShaftPattern, ArrowItem::Shaft> shaft2shaft = {
{ CustomRelation::ShaftPattern::Solid, ArrowItem::ShaftSolid },
{ CustomRelation::ShaftPattern::Dash, ArrowItem::ShaftDashed },
{ CustomRelation::ShaftPattern::Dot, ArrowItem::ShaftDot },
{ CustomRelation::ShaftPattern::DashDot, ArrowItem::ShaftDashDot },
{ CustomRelation::ShaftPattern::DashDotDot, ArrowItem::ShaftDashDotDot },
};
static const QHash<CustomRelation::Head, ArrowItem::Head> head2head = {
{ CustomRelation::Head::None, ArrowItem::HeadNone },
{ CustomRelation::Head::Shape, ArrowItem::HeadNone },
{ CustomRelation::Head::Arrow, ArrowItem::HeadOpen },
{ CustomRelation::Head::Triangle, ArrowItem::HeadTriangle },
{ CustomRelation::Head::FilledTriangle, ArrowItem::HeadFilledTriangle },
{ CustomRelation::Head::Diamond, ArrowItem::HeadDiamond },
{ CustomRelation::Head::FilledDiamond, ArrowItem::HeadFilledDiamond },
};
shaft = shaft2shaft.value(customRelation.shaftPattern());
endAHead = head2head.value(customRelation.endA().head());
endBHead = head2head.value(customRelation.endB().head());
// TODO color
}
m_arrow->setShaft(shaft);
m_arrow->setArrowSize(12.0);
m_arrow->setDiamondSize(12.0);
m_arrow->setStartHead(endAHead);
m_arrow->setEndHead(endBHead);
m_arrow->setPoints(m_points);
}
private:
DiagramSceneModel *m_diagramSceneModel = 0;
ArrowItem *m_arrow = 0;

View File

@@ -81,8 +81,7 @@ void RelationStarter::addArrow(const QString &id, ArrowItem::Shaft shaft,
arrow->setShaft(shaft);
arrow->setStartHead(startHead);
arrow->setEndHead(endHead);
if (!toolTip.isEmpty())
arrow->setToolTip(toolTip);
arrow->setToolTip(toolTip.isEmpty() ? id : toolTip);
arrow->setPoints(QList<QPointF>() << QPointF(0.0, 10.0) << QPointF(15.0, 0.0));
arrow->setPos(6.0, m_arrows.size() * 20.0 + 8.0);
arrow->update(m_diagramSceneModel->styleController()->relationStarterStyle());

View File

@@ -0,0 +1,114 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "mconnection.h"
#include "mvisitor.h"
#include "mconstvisitor.h"
namespace qmt {
MConnectionEnd::MConnectionEnd()
{
}
MConnectionEnd::MConnectionEnd(const MConnectionEnd &rhs)
: m_name(rhs.name()),
m_cardinality(rhs.m_cardinality),
m_isNavigable(rhs.m_isNavigable)
{
}
MConnectionEnd::~MConnectionEnd()
{
}
MConnectionEnd &MConnectionEnd::operator=(const MConnectionEnd &rhs)
{
if (this != &rhs) {
m_name = rhs.m_name;
m_cardinality = rhs.m_cardinality;
m_isNavigable = rhs.m_isNavigable;
}
return *this;
}
void MConnectionEnd::setName(const QString &name)
{
m_name = name;
}
void MConnectionEnd::setCardinality(const QString &cardinality)
{
m_cardinality = cardinality;
}
void MConnectionEnd::setNavigable(bool navigable)
{
m_isNavigable = navigable;
}
bool operator==(const MConnectionEnd &lhs, const MConnectionEnd &rhs)
{
return lhs.name() == rhs.name()
&& lhs.cardinality() == rhs.cardinality()
&& lhs.isNavigable() == rhs.isNavigable();
}
MConnection::MConnection()
: MRelation()
{
}
MConnection::~MConnection()
{
}
void MConnection::setCustomRelationId(const QString &customRelationId)
{
m_customRelationId = customRelationId;
}
void MConnection::setEndA(const MConnectionEnd &end)
{
m_endA = end;
}
void MConnection::setEndB(const MConnectionEnd &end)
{
m_endB = end;
}
void MConnection::accept(MVisitor *visitor)
{
visitor->visitMConnection(this);
}
void MConnection::accept(MConstVisitor *visitor) const
{
visitor->visitMConnection(this);
}
} // namespace qmt

View File

@@ -0,0 +1,85 @@
/****************************************************************************
**
** Copyright (C) 2016 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 "mrelation.h"
#include "qmt/infrastructure/handle.h"
#include <QString>
namespace qmt {
class QMT_EXPORT MConnectionEnd
{
public:
MConnectionEnd();
MConnectionEnd(const MConnectionEnd &rhs);
~MConnectionEnd();
MConnectionEnd &operator=(const MConnectionEnd &rhs);
QString name() const { return m_name; }
void setName(const QString &name);
QString cardinality() const { return m_cardinality; }
void setCardinality(const QString &cardinality);
bool isNavigable() const { return m_isNavigable; }
void setNavigable(bool navigable);
private:
QString m_name;
QString m_cardinality;
bool m_isNavigable = false;
};
bool operator==(const MConnectionEnd &lhs, const MConnectionEnd &rhs);
inline bool operator!=(const MConnectionEnd &lhs, const MConnectionEnd &rhs)
{
return !(lhs == rhs);
}
class QMT_EXPORT MConnection : public MRelation
{
public:
MConnection();
~MConnection() override;
QString customRelationId() const { return m_customRelationId; }
void setCustomRelationId(const QString &customRelationId);
MConnectionEnd endA() const { return m_endA; }
void setEndA(const MConnectionEnd &end);
MConnectionEnd endB() const { return m_endB; }
void setEndB(const MConnectionEnd &end);
void accept(MVisitor *visitor) override;
void accept(MConstVisitor *visitor) const override;
private:
QString m_customRelationId;
MConnectionEnd m_endA;
MConnectionEnd m_endB;
};
} // namespace qmt

View File

@@ -41,6 +41,7 @@ class MRelation;
class MDependency;
class MInheritance;
class MAssociation;
class MConnection;
class MConstVisitor
{
@@ -59,6 +60,7 @@ public:
virtual void visitMDependency(const MDependency *dependency) = 0;
virtual void visitMInheritance(const MInheritance *inheritance) = 0;
virtual void visitMAssociation(const MAssociation *association) = 0;
virtual void visitMConnection(const MConnection *connection) = 0;
};
} // namespace qmt

View File

@@ -41,6 +41,7 @@ class MRelation;
class MDependency;
class MInheritance;
class MAssociation;
class MConnection;
class MVisitor
{
@@ -59,6 +60,7 @@ public:
virtual void visitMDependency(MDependency *dependency) = 0;
virtual void visitMInheritance(MInheritance *inheritance) = 0;
virtual void visitMAssociation(MAssociation *association) = 0;
virtual void visitMConnection(MConnection *connection) = 0;
};
} // namespace qmt

View File

@@ -34,6 +34,7 @@
#include "qmt/model/mdependency.h"
#include "qmt/model/minheritance.h"
#include "qmt/model/massociation.h"
#include "qmt/model/mconnection.h"
namespace qmt {
@@ -102,4 +103,9 @@ void MChildrenVisitor::visitMAssociation(MAssociation *association)
visitMRelation(association);
}
void MChildrenVisitor::visitMConnection(MConnection *connection)
{
visitMRelation(connection);
}
} // namespace qmt

View File

@@ -45,6 +45,7 @@ public:
void visitMDependency(MDependency *dependency) override;
void visitMInheritance(MInheritance *inheritance) override;
void visitMAssociation(MAssociation *association) override;
void visitMConnection(MConnection *connection) override;
};
} // namespace qmt

View File

@@ -35,6 +35,7 @@
#include "qmt/model/mitem.h"
#include "qmt/model/mrelation.h"
#include "qmt/model/massociation.h"
#include "qmt/model/mconnection.h"
#include "qmt/model/mdependency.h"
#include "qmt/model/minheritance.h"
@@ -136,6 +137,13 @@ void MCloneVisitor::visitMAssociation(const MAssociation *association)
visitMRelation(association);
}
void MCloneVisitor::visitMConnection(const MConnection *connection)
{
if (!m_cloned)
m_cloned = new MConnection(*connection);
visitMRelation(connection);
}
MCloneDeepVisitor::MCloneDeepVisitor()
: m_cloned(0)
{
@@ -257,4 +265,11 @@ void MCloneDeepVisitor::visitMAssociation(const MAssociation *association)
visitMRelation(association);
}
void MCloneDeepVisitor::visitMConnection(const MConnection *connection)
{
if (!m_cloned)
m_cloned = new MConnection(*connection);
visitMRelation(connection);
}
} // namespace qmt

View File

@@ -51,6 +51,7 @@ public:
void visitMDependency(const MDependency *dependency) override;
void visitMInheritance(const MInheritance *inheritance) override;
void visitMAssociation(const MAssociation *association) override;
void visitMConnection(const MConnection *connection) override;
private:
MElement *m_cloned;
@@ -75,6 +76,7 @@ public:
void visitMDependency(const MDependency *dependency) override;
void visitMInheritance(const MInheritance *inheritance) override;
void visitMAssociation(const MAssociation *association) override;
void visitMConnection(const MConnection *connection) override;
private:
MElement *m_cloned;

View File

@@ -34,6 +34,7 @@
#include "qmt/model/mdependency.h"
#include "qmt/model/minheritance.h"
#include "qmt/model/massociation.h"
#include "qmt/model/mconnection.h"
namespace qmt {
@@ -131,6 +132,17 @@ void MFlatAssignmentVisitor::visitMAssociation(const MAssociation *association)
QMT_ASSERT(targetAssociation, return);
targetAssociation->setEndA(association->endA());
targetAssociation->setEndB(association->endB());
// TODO assign association class UID?
}
void MFlatAssignmentVisitor::visitMConnection(const MConnection *connection)
{
visitMRelation(connection);
auto targetConnection = dynamic_cast<MConnection *>(m_target);
QMT_CHECK(targetConnection);
targetConnection->setCustomRelationId(connection->customRelationId());
targetConnection->setEndA(connection->endA());
targetConnection->setEndB(connection->endB());
}
} // namespace qmt

View File

@@ -49,6 +49,7 @@ public:
void visitMDependency(const MDependency *dependency) override;
void visitMInheritance(const MInheritance *inheritance) override;
void visitMAssociation(const MAssociation *association) override;
void visitMConnection(const MConnection *connection) override;
private:
MElement *m_target;

View File

@@ -35,6 +35,7 @@
#include "qmt/model/mitem.h"
#include "qmt/model/mrelation.h"
#include "qmt/model/massociation.h"
#include "qmt/model/mconnection.h"
#include "qmt/model/mdependency.h"
#include "qmt/model/minheritance.h"
@@ -102,6 +103,11 @@ void MVoidVisitor::visitMAssociation(MAssociation *association)
visitMRelation(association);
}
void MVoidVisitor::visitMConnection(MConnection *connection)
{
visitMRelation(connection);
}
void MVoidConstVisitor::visitMElement(const MElement *element)
{
Q_UNUSED(element);
@@ -162,4 +168,9 @@ void MVoidConstVisitor::visitMAssociation(const MAssociation *association)
visitMRelation(association);
}
void MVoidConstVisitor::visitMConnection(const MConnection *connection)
{
visitMRelation(connection);
}
} // namespace qmt

View File

@@ -46,6 +46,7 @@ public:
void visitMDependency(MDependency *dependency) override;
void visitMInheritance(MInheritance *inheritance) override;
void visitMAssociation(MAssociation *association) override;
void visitMConnection(MConnection *connection) override;
};
class QMT_EXPORT MVoidConstVisitor : public MConstVisitor
@@ -63,6 +64,7 @@ public:
void visitMDependency(const MDependency *dependency) override;
void visitMInheritance(const MInheritance *inheritance) override;
void visitMAssociation(const MAssociation *association) override;
void visitMConnection(const MConnection *connection) override;
};
} // namespace qmt

View File

@@ -36,6 +36,7 @@
#include "qmt/model/mitem.h"
#include "qmt/model/mrelation.h"
#include "qmt/model/massociation.h"
#include "qmt/model/mconnection.h"
#include "qmt/model/mdependency.h"
#include "qmt/model/minheritance.h"
@@ -188,6 +189,15 @@ public:
visitMRelation(association);
}
void visitMConnection(const MConnection *connection)
{
QMT_CHECK(!m_item);
static QIcon icon(QStringLiteral(":modelinglib/48x48/connection.ong"));
m_item = new ModelItem(icon, m_treeModel->createRelationLabel(connection));
visitMRelation(connection);
}
private:
TreeModel *m_treeModel = 0;
TreeModel::ModelItem *m_item = 0;
@@ -285,6 +295,11 @@ public:
visitMRelation(association);
}
void visitMConnection(const MConnection *connection)
{
visitMRelation(connection);
}
private:
void updateObjectLabel(const MObject *object);
void updateRelationLabel(const MRelation *relation);

View File

@@ -43,6 +43,7 @@
#include "qmt/model/mdependency.h"
#include "qmt/model/minheritance.h"
#include "qmt/model/massociation.h"
#include "qmt/model/mconnection.h"
#include "qmt/diagram/delement.h"
#include "qmt/diagram/dobject.h"
@@ -55,12 +56,14 @@
#include "qmt/diagram/dinheritance.h"
#include "qmt/diagram/ddependency.h"
#include "qmt/diagram/dassociation.h"
#include "qmt/diagram/dconnection.h"
#include "qmt/diagram/dannotation.h"
#include "qmt/diagram/dboundary.h"
// TODO move into better place
#include "qmt/diagram_scene/items/stereotypedisplayvisitor.h"
#include "qmt/stereotype/stereotypecontroller.h"
#include "qmt/stereotype/customrelation.h"
#include "qmt/style/stylecontroller.h"
#include "qmt/style/style.h"
#include "qmt/style/objectvisuals.h"
@@ -380,7 +383,7 @@ void PropertiesView::MView::visitMElement(const MElement *element)
Q_UNUSED(element);
prepare();
if (m_stereotypeComboBox == 0) {
if (!m_stereotypeComboBox) {
m_stereotypeComboBox = new QComboBox(m_topWidget);
m_stereotypeComboBox->setEditable(true);
m_stereotypeComboBox->setInsertPolicy(QComboBox::NoInsert);
@@ -404,7 +407,7 @@ void PropertiesView::MView::visitMElement(const MElement *element)
}
}
#ifdef SHOW_DEBUG_PROPERTIES
if (m_reverseEngineeredLabel == 0) {
if (!m_reverseEngineeredLabel) {
m_reverseEngineeredLabel = new QLabel(m_topWidget);
addRow(tr("Reverse engineered:"), m_reverseEngineeredLabel, "reverse engineered");
}
@@ -418,7 +421,7 @@ void PropertiesView::MView::visitMObject(const MObject *object)
visitMElement(object);
QList<MObject *> selection = filter<MObject>(m_modelElements);
bool isSingleSelection = selection.size() == 1;
if (m_elementNameLineEdit == 0) {
if (!m_elementNameLineEdit) {
m_elementNameLineEdit = new QLineEdit(m_topWidget);
addRow(tr("Name:"), m_elementNameLineEdit, "name");
connect(m_elementNameLineEdit, &QLineEdit::textChanged,
@@ -434,12 +437,12 @@ void PropertiesView::MView::visitMObject(const MObject *object)
m_elementNameLineEdit->setEnabled(isSingleSelection);
#ifdef SHOW_DEBUG_PROPERTIES
if (m_childrenLabel == 0) {
if (!m_childrenLabel) {
m_childrenLabel = new QLabel(m_topWidget);
addRow(tr("Children:"), m_childrenLabel, "children");
}
m_childrenLabel->setText(QString::number(object->children().size()));
if (m_relationsLabel == 0) {
if (!m_relationsLabel) {
m_relationsLabel = new QLabel(m_topWidget);
addRow(tr("Relations:"), m_relationsLabel, "relations");
}
@@ -462,7 +465,7 @@ void PropertiesView::MView::visitMClass(const MClass *klass)
visitMObject(klass);
QList<MClass *> selection = filter<MClass>(m_modelElements);
bool isSingleSelection = selection.size() == 1;
if (m_namespaceLineEdit == 0) {
if (!m_namespaceLineEdit) {
m_namespaceLineEdit = new QLineEdit(m_topWidget);
addRow(tr("Namespace:"), m_namespaceLineEdit, "namespace");
connect(m_namespaceLineEdit, &QLineEdit::textEdited,
@@ -479,7 +482,7 @@ void PropertiesView::MView::visitMClass(const MClass *klass)
m_namespaceLineEdit->setEnabled(false);
}
}
if (m_templateParametersLineEdit == 0) {
if (!m_templateParametersLineEdit) {
m_templateParametersLineEdit = new QLineEdit(m_topWidget);
addRow(tr("Template:"), m_templateParametersLineEdit, "template");
connect(m_templateParametersLineEdit, &QLineEdit::textChanged,
@@ -496,7 +499,7 @@ void PropertiesView::MView::visitMClass(const MClass *klass)
}
if (m_templateParametersLineEdit->isEnabled() != isSingleSelection)
m_templateParametersLineEdit->setEnabled(isSingleSelection);
if (m_classMembersStatusLabel == 0) {
if (!m_classMembersStatusLabel) {
QMT_CHECK(!m_classMembersParseButton);
m_classMembersStatusLabel = new QLabel(m_topWidget);
m_classMembersParseButton = new QPushButton(tr("Clean Up"), m_topWidget);
@@ -511,7 +514,7 @@ void PropertiesView::MView::visitMClass(const MClass *klass)
}
if (m_classMembersParseButton->isEnabled() != isSingleSelection)
m_classMembersParseButton->setEnabled(isSingleSelection);
if (m_classMembersEdit == 0) {
if (!m_classMembersEdit) {
m_classMembersEdit = new ClassMembersEdit(m_topWidget);
m_classMembersEdit->setLineWrapMode(QPlainTextEdit::NoWrap);
addRow(tr("Members:"), m_classMembersEdit, "members");
@@ -541,7 +544,7 @@ void PropertiesView::MView::visitMDiagram(const MDiagram *diagram)
setTitle<MDiagram>(m_modelElements, tr("Diagram"), tr("Diagrams"));
visitMObject(diagram);
#ifdef SHOW_DEBUG_PROPERTIES
if (m_diagramsLabel == 0) {
if (!m_diagramsLabel) {
m_diagramsLabel = new QLabel(m_topWidget);
addRow(tr("Elements:"), m_diagramsLabel, "elements");
}
@@ -562,7 +565,7 @@ void PropertiesView::MView::visitMItem(const MItem *item)
QList<MItem *> selection = filter<MItem>(m_modelElements);
bool isSingleSelection = selection.size() == 1;
if (item->isVarietyEditable()) {
if (m_itemVarietyEdit == 0) {
if (!m_itemVarietyEdit) {
m_itemVarietyEdit = new QLineEdit(m_topWidget);
addRow(tr("Variety:"), m_itemVarietyEdit, "variety");
connect(m_itemVarietyEdit, &QLineEdit::textChanged,
@@ -584,7 +587,7 @@ void PropertiesView::MView::visitMRelation(const MRelation *relation)
visitMElement(relation);
QList<MRelation *> selection = filter<MRelation>(m_modelElements);
bool isSingleSelection = selection.size() == 1;
if (m_elementNameLineEdit == 0) {
if (!m_elementNameLineEdit) {
m_elementNameLineEdit = new QLineEdit(m_topWidget);
addRow(tr("Name:"), m_elementNameLineEdit, "name");
connect(m_elementNameLineEdit, &QLineEdit::textChanged,
@@ -612,7 +615,7 @@ void PropertiesView::MView::visitMDependency(const MDependency *dependency)
visitMRelation(dependency);
QList<MDependency *> selection = filter<MDependency>(m_modelElements);
bool isSingleSelection = selection.size() == 1;
if (m_directionSelector == 0) {
if (!m_directionSelector) {
m_directionSelector = new QComboBox(m_topWidget);
m_directionSelector->addItems(QStringList({ "->", "<-", "<->" }));
addRow(tr("Direction:"), m_directionSelector, "direction");
@@ -650,11 +653,11 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
visitMRelation(association);
QList<MAssociation *> selection = filter<MAssociation>(m_modelElements);
bool isSingleSelection = selection.size() == 1;
if (m_endALabel == 0) {
if (!m_endALabel) {
m_endALabel = new QLabel(QStringLiteral("<b>") + m_endAName + QStringLiteral("</b>"));
addRow(m_endALabel, "end a");
}
if (m_endAEndName == 0) {
if (!m_endAEndName) {
m_endAEndName = new QLineEdit(m_topWidget);
addRow(tr("Role:"), m_endAEndName, "role a");
connect(m_endAEndName, &QLineEdit::textChanged,
@@ -668,7 +671,7 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
}
if (m_endAEndName->isEnabled() != isSingleSelection)
m_endAEndName->setEnabled(isSingleSelection);
if (m_endACardinality == 0) {
if (!m_endACardinality) {
m_endACardinality = new QLineEdit(m_topWidget);
addRow(tr("Cardinality:"), m_endACardinality, "cardinality a");
connect(m_endACardinality, &QLineEdit::textChanged,
@@ -682,7 +685,7 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
}
if (m_endACardinality->isEnabled() != isSingleSelection)
m_endACardinality->setEnabled(isSingleSelection);
if (m_endANavigable == 0) {
if (!m_endANavigable) {
m_endANavigable = new QCheckBox(tr("Navigable"), m_topWidget);
addRow(QString(), m_endANavigable, "navigable a");
connect(m_endANavigable, &QAbstractButton::clicked,
@@ -696,7 +699,7 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
}
if (m_endANavigable->isEnabled() != isSingleSelection)
m_endANavigable->setEnabled(isSingleSelection);
if (m_endAKind == 0) {
if (!m_endAKind) {
m_endAKind = new QComboBox(m_topWidget);
m_endAKind->addItems({ tr("Association"), tr("Aggregation"), tr("Composition") });
addRow(tr("Relationship:"), m_endAKind, "relationship a");
@@ -715,11 +718,11 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
if (m_endAKind->isEnabled() != isSingleSelection)
m_endAKind->setEnabled(isSingleSelection);
if (m_endBLabel == 0) {
if (!m_endBLabel) {
m_endBLabel = new QLabel(QStringLiteral("<b>") + m_endBName + QStringLiteral("</b>"));
addRow(m_endBLabel, "end b");
}
if (m_endBEndName == 0) {
if (!m_endBEndName) {
m_endBEndName = new QLineEdit(m_topWidget);
addRow(tr("Role:"), m_endBEndName, "role b");
connect(m_endBEndName, &QLineEdit::textChanged,
@@ -733,7 +736,7 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
}
if (m_endBEndName->isEnabled() != isSingleSelection)
m_endBEndName->setEnabled(isSingleSelection);
if (m_endBCardinality == 0) {
if (!m_endBCardinality) {
m_endBCardinality = new QLineEdit(m_topWidget);
addRow(tr("Cardinality:"), m_endBCardinality, "cardinality b");
connect(m_endBCardinality, &QLineEdit::textChanged,
@@ -747,7 +750,7 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
}
if (m_endBCardinality->isEnabled() != isSingleSelection)
m_endBCardinality->setEnabled(isSingleSelection);
if (m_endBNavigable == 0) {
if (!m_endBNavigable) {
m_endBNavigable = new QCheckBox(tr("Navigable"), m_topWidget);
addRow(QString(), m_endBNavigable, "navigable b");
connect(m_endBNavigable, &QAbstractButton::clicked,
@@ -761,7 +764,7 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
}
if (m_endBNavigable->isEnabled() != isSingleSelection)
m_endBNavigable->setEnabled(isSingleSelection);
if (m_endBKind == 0) {
if (!m_endBKind) {
m_endBKind = new QComboBox(m_topWidget);
m_endBKind->addItems({ tr("Association"), tr("Aggregation"), tr("Composition") });
addRow(tr("Relationship:"), m_endBKind, "relationship b");
@@ -781,6 +784,107 @@ void PropertiesView::MView::visitMAssociation(const MAssociation *association)
m_endBKind->setEnabled(isSingleSelection);
}
void PropertiesView::MView::visitMConnection(const MConnection *connection)
{
setTitle<MConnection>(connection, m_modelElements, tr("Connection"), tr("Connections"));
visitMRelation(connection);
QList<MConnection *> selection = filter<MConnection>(m_modelElements);
const bool isSingleSelection = selection.size() == 1;
if (!m_endALabel) {
m_endALabel = new QLabel(QStringLiteral("<b>") + m_endAName + QStringLiteral("</b>"));
addRow(m_endALabel, "end a");
}
if (!m_endAEndName) {
m_endAEndName = new QLineEdit(m_topWidget);
addRow(tr("Role:"), m_endAEndName, "role a");
connect(m_endAEndName, &QLineEdit::textChanged,
this, &PropertiesView::MView::onConnectionEndANameChanged);
}
if (isSingleSelection) {
if (connection->endA().name() != m_endAEndName->text() && !m_endAEndName->hasFocus())
m_endAEndName->setText(connection->endA().name());
} else {
m_endAEndName->clear();
}
if (m_endAEndName->isEnabled() != isSingleSelection)
m_endAEndName->setEnabled(isSingleSelection);
if (!m_endACardinality) {
m_endACardinality = new QLineEdit(m_topWidget);
addRow(tr("Cardinality:"), m_endACardinality, "cardinality a");
connect(m_endACardinality, &QLineEdit::textChanged,
this, &PropertiesView::MView::onConnectionEndACardinalityChanged);
}
if (isSingleSelection) {
if (connection->endA().cardinality() != m_endACardinality->text() && !m_endACardinality->hasFocus())
m_endACardinality->setText(connection->endA().cardinality());
} else {
m_endACardinality->clear();
}
if (m_endACardinality->isEnabled() != isSingleSelection)
m_endACardinality->setEnabled(isSingleSelection);
if (!m_endANavigable) {
m_endANavigable = new QCheckBox(tr("Navigable"), m_topWidget);
addRow(QString(), m_endANavigable, "navigable a");
connect(m_endANavigable, &QAbstractButton::clicked,
this, &PropertiesView::MView::onConnectionEndANavigableChanged);
}
if (isSingleSelection) {
if (connection->endA().isNavigable() != m_endANavigable->isChecked())
m_endANavigable->setChecked(connection->endA().isNavigable());
} else {
m_endANavigable->setChecked(false);
}
if (m_endANavigable->isEnabled() != isSingleSelection)
m_endANavigable->setEnabled(isSingleSelection);
if (!m_endBLabel) {
m_endBLabel = new QLabel(QStringLiteral("<b>") + m_endBName + QStringLiteral("</b>"));
addRow(m_endBLabel, "end b");
}
if (!m_endBEndName) {
m_endBEndName = new QLineEdit(m_topWidget);
addRow(tr("Role:"), m_endBEndName, "role b");
connect(m_endBEndName, &QLineEdit::textChanged,
this, &PropertiesView::MView::onConnectionEndBNameChanged);
}
if (isSingleSelection) {
if (connection->endB().name() != m_endBEndName->text() && !m_endBEndName->hasFocus())
m_endBEndName->setText(connection->endB().name());
} else {
m_endBEndName->clear();
}
if (m_endBEndName->isEnabled() != isSingleSelection)
m_endBEndName->setEnabled(isSingleSelection);
if (!m_endBCardinality) {
m_endBCardinality = new QLineEdit(m_topWidget);
addRow(tr("Cardinality:"), m_endBCardinality, "cardinality b");
connect(m_endBCardinality, &QLineEdit::textChanged,
this, &PropertiesView::MView::onConnectionEndBCardinalityChanged);
}
if (isSingleSelection) {
if (connection->endB().cardinality() != m_endBCardinality->text() && !m_endBCardinality->hasFocus())
m_endBCardinality->setText(connection->endB().cardinality());
} else {
m_endBCardinality->clear();
}
if (m_endBCardinality->isEnabled() != isSingleSelection)
m_endBCardinality->setEnabled(isSingleSelection);
if (!m_endBNavigable) {
m_endBNavigable = new QCheckBox(tr("Navigable"), m_topWidget);
addRow(QString(), m_endBNavigable, "navigable b");
connect(m_endBNavigable, &QAbstractButton::clicked,
this, &PropertiesView::MView::onConnectionEndBNavigableChanged);
}
if (isSingleSelection) {
if (connection->endB().isNavigable() != m_endBNavigable->isChecked())
m_endBNavigable->setChecked(connection->endB().isNavigable());
} else {
m_endBNavigable->setChecked(false);
}
if (m_endBNavigable->isEnabled() != isSingleSelection)
m_endBNavigable->setEnabled(isSingleSelection);
}
void PropertiesView::MView::visitDElement(const DElement *element)
{
Q_UNUSED(element);
@@ -789,7 +893,7 @@ void PropertiesView::MView::visitDElement(const DElement *element)
m_propertiesTitle.clear();
m_modelElements.at(0)->accept(this);
#ifdef SHOW_DEBUG_PROPERTIES
if (m_separatorLine == 0) {
if (!m_separatorLine) {
m_separatorLine = new QFrame(m_topWidget);
m_separatorLine->setFrameShape(QFrame::StyledPanel);
m_separatorLine->setLineWidth(2);
@@ -806,7 +910,7 @@ void PropertiesView::MView::visitDObject(const DObject *object)
{
visitDElement(object);
#ifdef SHOW_DEBUG_PROPERTIES
if (m_posRectLabel == 0) {
if (!m_posRectLabel) {
m_posRectLabel = new QLabel(m_topWidget);
addRow(tr("Position and size:"), m_posRectLabel, "position and size");
}
@@ -818,7 +922,7 @@ void PropertiesView::MView::visitDObject(const DObject *object)
.arg(object->rect().right())
.arg(object->rect().bottom()));
#endif
if (m_autoSizedCheckbox == 0) {
if (!m_autoSizedCheckbox) {
m_autoSizedCheckbox = new QCheckBox(tr("Auto sized"), m_topWidget);
addRow(QString(), m_autoSizedCheckbox, "auto size");
connect(m_autoSizedCheckbox, &QAbstractButton::clicked,
@@ -831,7 +935,7 @@ void PropertiesView::MView::visitDObject(const DObject *object)
else
m_autoSizedCheckbox->setChecked(false);
}
if (m_visualPrimaryRoleSelector == 0) {
if (!m_visualPrimaryRoleSelector) {
m_visualPrimaryRoleSelector = new PaletteBox(m_topWidget);
setPrimaryRolePalette(m_styleElementType, DObject::PrimaryRoleCustom1, QColor());
setPrimaryRolePalette(m_styleElementType, DObject::PrimaryRoleCustom2, QColor());
@@ -860,7 +964,7 @@ void PropertiesView::MView::visitDObject(const DObject *object)
else
m_visualPrimaryRoleSelector->setCurrentIndex(-1);
}
if (m_visualSecondaryRoleSelector == 0) {
if (!m_visualSecondaryRoleSelector) {
m_visualSecondaryRoleSelector = new QComboBox(m_topWidget);
m_visualSecondaryRoleSelector->addItems({ tr("Normal"), tr("Lighter"), tr("Darker"),
tr("Soften"), tr("Outline") });
@@ -875,7 +979,7 @@ void PropertiesView::MView::visitDObject(const DObject *object)
else
m_visualSecondaryRoleSelector->setCurrentIndex(-1);
}
if (m_visualEmphasizedCheckbox == 0) {
if (!m_visualEmphasizedCheckbox) {
m_visualEmphasizedCheckbox = new QCheckBox(tr("Emphasized"), m_topWidget);
addRow(QString(), m_visualEmphasizedCheckbox, "emphasized");
connect(m_visualEmphasizedCheckbox, &QAbstractButton::clicked,
@@ -888,7 +992,7 @@ void PropertiesView::MView::visitDObject(const DObject *object)
else
m_visualEmphasizedCheckbox->setChecked(false);
}
if (m_stereotypeDisplaySelector == 0) {
if (!m_stereotypeDisplaySelector) {
m_stereotypeDisplaySelector = new QComboBox(m_topWidget);
m_stereotypeDisplaySelector->addItems({ tr("Smart"), tr("None"), tr("Label"),
tr("Decoration"), tr("Icon") });
@@ -904,7 +1008,7 @@ void PropertiesView::MView::visitDObject(const DObject *object)
m_stereotypeDisplaySelector->setCurrentIndex(-1);
}
#ifdef SHOW_DEBUG_PROPERTIES
if (m_depthLabel == 0) {
if (!m_depthLabel) {
m_depthLabel = new QLabel(m_topWidget);
addRow(tr("Depth:"), m_depthLabel, "depth");
}
@@ -926,7 +1030,7 @@ void PropertiesView::MView::visitDClass(const DClass *klass)
setStereotypeIconElement(StereotypeIcon::ElementClass);
setStyleElementType(StyleEngine::TypeClass);
visitDObject(klass);
if (m_templateDisplaySelector == 0) {
if (!m_templateDisplaySelector) {
m_templateDisplaySelector = new QComboBox(m_topWidget);
m_templateDisplaySelector->addItems({ tr("Smart"), tr("Box"), tr("Angle Brackets") });
addRow(tr("Template display:"), m_templateDisplaySelector, "template display");
@@ -940,7 +1044,7 @@ void PropertiesView::MView::visitDClass(const DClass *klass)
else
m_templateDisplaySelector->setCurrentIndex(-1);
}
if (m_showAllMembersCheckbox == 0) {
if (!m_showAllMembersCheckbox) {
m_showAllMembersCheckbox = new QCheckBox(tr("Show members"), m_topWidget);
addRow(QString(), m_showAllMembersCheckbox, "show members");
connect(m_showAllMembersCheckbox, &QAbstractButton::clicked,
@@ -961,7 +1065,7 @@ void PropertiesView::MView::visitDComponent(const DComponent *component)
setStereotypeIconElement(StereotypeIcon::ElementComponent);
setStyleElementType(StyleEngine::TypeComponent);
visitDObject(component);
if (m_plainShapeCheckbox == 0) {
if (!m_plainShapeCheckbox) {
m_plainShapeCheckbox = new QCheckBox(tr("Plain shape"), m_topWidget);
addRow(QString(), m_plainShapeCheckbox, "plain shape");
connect(m_plainShapeCheckbox, &QAbstractButton::clicked,
@@ -992,7 +1096,7 @@ void PropertiesView::MView::visitDItem(const DItem *item)
QList<DItem *> selection = filter<DItem>(m_diagramElements);
bool isSingleSelection = selection.size() == 1;
if (item->isShapeEditable()) {
if (m_itemShapeEdit == 0) {
if (!m_itemShapeEdit) {
m_itemShapeEdit = new QLineEdit(m_topWidget);
addRow(tr("Shape:"), m_itemShapeEdit, "shape");
connect(m_itemShapeEdit, &QLineEdit::textChanged,
@@ -1032,11 +1136,17 @@ void PropertiesView::MView::visitDAssociation(const DAssociation *association)
visitDRelation(association);
}
void PropertiesView::MView::visitDConnection(const DConnection *connection)
{
setTitle<DConnection>(m_diagramElements, tr("Connection"), tr("Connections"));
visitDRelation(connection);
}
void PropertiesView::MView::visitDAnnotation(const DAnnotation *annotation)
{
setTitle<DAnnotation>(m_diagramElements, tr("Annotation"), tr("Annotations"));
visitDElement(annotation);
if (m_annotationAutoWidthCheckbox == 0) {
if (!m_annotationAutoWidthCheckbox) {
m_annotationAutoWidthCheckbox = new QCheckBox(tr("Auto width"), m_topWidget);
addRow(QString(), m_annotationAutoWidthCheckbox, "auto width");
connect(m_annotationAutoWidthCheckbox, &QAbstractButton::clicked,
@@ -1049,7 +1159,7 @@ void PropertiesView::MView::visitDAnnotation(const DAnnotation *annotation)
else
m_annotationAutoWidthCheckbox->setChecked(false);
}
if (m_annotationVisualRoleSelector == 0) {
if (!m_annotationVisualRoleSelector) {
m_annotationVisualRoleSelector = new QComboBox(m_topWidget);
m_annotationVisualRoleSelector->addItems(QStringList({ tr("Normal"), tr("Title"),
tr("Subtitle"), tr("Emphasized"),
@@ -1207,6 +1317,48 @@ void PropertiesView::MView::onAssociationEndBKindChanged(int kindIndex)
&MAssociationEnd::kind, &MAssociationEnd::setKind);
}
void PropertiesView::MView::onConnectionEndANameChanged(const QString &name)
{
assignEmbeddedModelElement<MConnection, MConnectionEnd, QString>(
m_modelElements, SelectionSingle, name, &MConnection::endA, &MConnection::setEndA,
&MConnectionEnd::name, &MConnectionEnd::setName);
}
void PropertiesView::MView::onConnectionEndACardinalityChanged(const QString &cardinality)
{
assignEmbeddedModelElement<MConnection, MConnectionEnd, QString>(
m_modelElements, SelectionSingle, cardinality, &MConnection::endA, &MConnection::setEndA,
&MConnectionEnd::cardinality, &MConnectionEnd::setCardinality);
}
void PropertiesView::MView::onConnectionEndANavigableChanged(bool navigable)
{
assignEmbeddedModelElement<MConnection, MConnectionEnd, bool>(
m_modelElements, SelectionSingle, navigable, &MConnection::endA, &MConnection::setEndA,
&MConnectionEnd::isNavigable, &MConnectionEnd::setNavigable);
}
void PropertiesView::MView::onConnectionEndBNameChanged(const QString &name)
{
assignEmbeddedModelElement<MConnection, MConnectionEnd, QString>(
m_modelElements, SelectionSingle, name, &MConnection::endB, &MConnection::setEndB,
&MConnectionEnd::name, &MConnectionEnd::setName);
}
void PropertiesView::MView::onConnectionEndBCardinalityChanged(const QString &cardinality)
{
assignEmbeddedModelElement<MConnection, MConnectionEnd, QString>(
m_modelElements, SelectionSingle, cardinality, &MConnection::endB, &MConnection::setEndB,
&MConnectionEnd::cardinality, &MConnectionEnd::setCardinality);
}
void PropertiesView::MView::onConnectionEndBNavigableChanged(bool navigable)
{
assignEmbeddedModelElement<MConnection, MConnectionEnd, bool>(
m_modelElements, SelectionSingle, navigable, &MConnection::endB, &MConnection::setEndB,
&MConnectionEnd::isNavigable, &MConnectionEnd::setNavigable);
}
void PropertiesView::MView::onAutoSizedChanged(bool autoSized)
{
assignModelElement<DObject, bool>(m_diagramElements, SelectionMulti, autoSized,
@@ -1284,12 +1436,12 @@ void PropertiesView::MView::onAnnotationVisualRoleChanged(int visualRoleIndex)
void PropertiesView::MView::prepare()
{
QMT_CHECK(!m_propertiesTitle.isEmpty());
if (m_topWidget == 0) {
if (!m_topWidget) {
m_topWidget = new QWidget();
m_topLayout = new QFormLayout(m_topWidget);
m_topWidget->setLayout(m_topLayout);
}
if (m_classNameLabel == 0) {
if (!m_classNameLabel) {
m_classNameLabel = new QLabel();
m_topLayout->addRow(m_classNameLabel);
m_rowToId.append("title");
@@ -1372,7 +1524,8 @@ template<typename T, typename V>
void PropertiesView::MView::setTitle(const MItem *item, const QList<V *> &elements,
const QString &singularTitle, const QString &pluralTitle)
{
if (m_propertiesTitle.isEmpty()) {
if (!m_propertiesTitle.isEmpty())
return;
QList<T *> filtered = filter<T>(elements);
if (filtered.size() == elements.size()) {
if (elements.size() == 1) {
@@ -1393,6 +1546,33 @@ void PropertiesView::MView::setTitle(const MItem *item, const QList<V *> &elemen
m_propertiesTitle = QCoreApplication::translate("qmt::PropertiesView::MView", "Multi-Selection");
}
}
template<typename T, typename V>
void PropertiesView::MView::setTitle(const MConnection *connection, const QList<V *> &elements,
const QString &singularTitle, const QString &pluralTitle)
{
if (!m_propertiesTitle.isEmpty())
return;
QList<T *> filtered = filter<T>(elements);
if (filtered.size() == elements.size()) {
if (elements.size() == 1) {
if (connection) {
CustomRelation customRelation = m_propertiesView->stereotypeController()
->findCustomRelation(connection->customRelationId());
if (!customRelation.isNull()) {
m_propertiesTitle = customRelation.title();
if (m_propertiesTitle.isEmpty())
m_propertiesTitle = connection->customRelationId();
}
}
if (m_propertiesTitle.isEmpty())
m_propertiesTitle = singularTitle;
} else {
m_propertiesTitle = pluralTitle;
}
} else {
m_propertiesTitle = QCoreApplication::translate("qmt::PropertiesView::MView", "Multi-Selection");
}
}
void PropertiesView::MView::setStereotypeIconElement(StereotypeIcon::Element stereotypeElement)

View File

@@ -78,6 +78,7 @@ public:
void visitMDependency(const MDependency *dependency) override;
void visitMInheritance(const MInheritance *inheritance) override;
void visitMAssociation(const MAssociation *association) override;
void visitMConnection(const MConnection *connection) override;
void visitDElement(const DElement *element) override;
void visitDObject(const DObject *object) override;
@@ -90,6 +91,7 @@ public:
void visitDInheritance(const DInheritance *inheritance) override;
void visitDDependency(const DDependency *dependency) override;
void visitDAssociation(const DAssociation *association) override;
void visitDConnection(const DConnection *connection) override;
void visitDAnnotation(const DAnnotation *annotation) override;
void visitDBoundary(const DBoundary *boundary) override;
@@ -116,6 +118,12 @@ protected:
void onAssociationEndBCardinalityChanged(const QString &cardinality);
void onAssociationEndBNavigableChanged(bool navigable);
void onAssociationEndBKindChanged(int kindIndex);
void onConnectionEndANameChanged(const QString &name);
void onConnectionEndACardinalityChanged(const QString &cardinality);
void onConnectionEndANavigableChanged(bool navigable);
void onConnectionEndBNameChanged(const QString &name);
void onConnectionEndBCardinalityChanged(const QString &cardinality);
void onConnectionEndBNavigableChanged(bool navigable);
void onAutoSizedChanged(bool autoSized);
void onVisualPrimaryRoleChanged(int visualRoleIndex);
void onVisualSecondaryRoleChanged(int visualRoleIndex);
@@ -141,6 +149,9 @@ protected:
template<typename T, typename V>
void setTitle(const MItem *item, const QList<V *> &elements,
const QString &singularTitle, const QString &pluralTitle);
template<typename T, typename V>
void setTitle(const MConnection *connection, const QList<V *> &elements,
const QString &singularTitle, const QString &pluralTitle);
void setStereotypeIconElement(StereotypeIcon::Element stereotypeElement);
void setStyleElementType(StyleEngine::ElementType elementType);
void setPrimaryRolePalette(StyleEngine::ElementType elementType,

View File

@@ -27,6 +27,7 @@ HEADERS += \
$$PWD/diagram/dboundary.h \
$$PWD/diagram/dclass.h \
$$PWD/diagram/dcomponent.h \
$$PWD/diagram/dconnection.h \
$$PWD/diagram/dconstvisitor.h \
$$PWD/diagram/ddependency.h \
$$PWD/diagram/ddiagram.h \
@@ -55,6 +56,7 @@ HEADERS += \
$$PWD/diagram_scene/items/boundaryitem.h \
$$PWD/diagram_scene/items/classitem.h \
$$PWD/diagram_scene/items/componentitem.h \
$$PWD/diagram_scene/items/connectionitem.h \
$$PWD/diagram_scene/items/diagramitem.h \
$$PWD/diagram_scene/items/itemitem.h \
$$PWD/diagram_scene/items/objectitem.h \
@@ -103,6 +105,7 @@ HEADERS += \
$$PWD/model/mclass.h \
$$PWD/model/mclassmember.h \
$$PWD/model/mcomponent.h \
$$PWD/model/mconnection.h \
$$PWD/model/mconstvisitor.h \
$$PWD/model/mdependency.h \
$$PWD/model/mdiagram.h \
@@ -180,6 +183,7 @@ SOURCES += \
$$PWD/diagram/dboundary.cpp \
$$PWD/diagram/dclass.cpp \
$$PWD/diagram/dcomponent.cpp \
$$PWD/diagram/dconnection.cpp \
$$PWD/diagram/ddependency.cpp \
$$PWD/diagram/ddiagram.cpp \
$$PWD/diagram/delement.cpp \
@@ -196,6 +200,7 @@ SOURCES += \
$$PWD/diagram_scene/items/boundaryitem.cpp \
$$PWD/diagram_scene/items/classitem.cpp \
$$PWD/diagram_scene/items/componentitem.cpp \
$$PWD/diagram_scene/items/connectionitem.cpp \
$$PWD/diagram_scene/items/diagramitem.cpp \
$$PWD/diagram_scene/items/itemitem.cpp \
$$PWD/diagram_scene/items/objectitem.cpp \
@@ -235,6 +240,7 @@ SOURCES += \
$$PWD/model/mclass.cpp \
$$PWD/model/mclassmember.cpp \
$$PWD/model/mcomponent.cpp \
$$PWD/model/mconnection.cpp \
$$PWD/model/mdependency.cpp \
$$PWD/model/mdiagram.cpp \
$$PWD/model/melement.cpp \

View File

@@ -41,6 +41,7 @@
#include "qmt/diagram/dinheritance.h"
#include "qmt/diagram/ddependency.h"
#include "qmt/diagram/dassociation.h"
#include "qmt/diagram/dconnection.h"
#include "qmt/diagram/dannotation.h"
#include "qmt/diagram/dboundary.h"
@@ -329,6 +330,39 @@ inline void Access<Archive, DAssociation>::serialize(Archive &archive, DAssociat
QARK_ACCESS_SPECIALIZE(QXmlInArchive, QXmlOutArchive, DAssociation)
// DConnection
QARK_REGISTER_TYPE_NAME(DConnectionEnd, "DConnectionEnd")
QARK_ACCESS_SERIALIZE(DConnectionEnd)
template<class Archive>
inline void Access<Archive, DConnectionEnd>::serialize(Archive &archive, DConnectionEnd &connectionEnd)
{
archive || tag(connectionEnd)
|| attr(QStringLiteral("name"), connectionEnd, &DConnectionEnd::name, &DConnectionEnd::setName)
|| attr(QStringLiteral("cradinality"), connectionEnd, &DConnectionEnd::cardinality, &DConnectionEnd::setCardinatlity)
|| attr(QStringLiteral("navigable"), connectionEnd, &DConnectionEnd::isNavigable, &DConnectionEnd::setNavigable)
|| end;
}
QARK_REGISTER_TYPE_NAME(DConnection, "DConnection")
QARK_REGISTER_DERIVED_CLASS(QXmlInArchive, QXmlOutArchive, DConnection, DElement)
QARK_REGISTER_DERIVED_CLASS(QXmlInArchive, QXmlOutArchive, DConnection, DRelation)
QARK_ACCESS_SERIALIZE(DConnection)
template<class Archive>
inline void Access<Archive, DConnection>::serialize(Archive &archive, DConnection &connection)
{
archive || tag(connection)
|| base<DRelation>(connection)
|| attr(QStringLiteral("custom-relation"), connection, &DConnection::customRelationId, &DConnection::setCustomRelationId)
|| attr(QStringLiteral("a"), connection, &DConnection::endA, &DConnection::setEndA)
|| attr(QStringLiteral("b"), connection, &DConnection::endB, &DConnection::setEndB)
|| end;
}
QARK_ACCESS_SPECIALIZE(QXmlInArchive, QXmlOutArchive, DConnection)
// DAnnotation
QARK_REGISTER_TYPE_NAME(DAnnotation, "DAnnotation")

View File

@@ -41,6 +41,7 @@
#include "qmt/model/mdependency.h"
#include "qmt/model/massociation.h"
#include "qmt/model/minheritance.h"
#include "qmt/model/mconnection.h"
#include "qmt/diagram/delement.h"
@@ -344,4 +345,37 @@ inline void Access<Archive, MAssociation>::serialize(Archive &archive, MAssociat
QARK_ACCESS_SPECIALIZE(QXmlInArchive, QXmlOutArchive, MAssociation)
// MConnection
QARK_REGISTER_TYPE_NAME(MConnectionEnd, "MConnectionEnd")
QARK_ACCESS_SERIALIZE(MConnectionEnd)
template<class Archive>
inline void Access<Archive, MConnectionEnd>::serialize(Archive &archive, MConnectionEnd &connectionEnd)
{
archive || tag(connectionEnd)
|| attr(QStringLiteral("name"), connectionEnd, &MConnectionEnd::name, &MConnectionEnd::setName)
|| attr(QStringLiteral("cardinality"), connectionEnd, &MConnectionEnd::cardinality, &MConnectionEnd::setCardinality)
|| attr(QStringLiteral("navigable"), connectionEnd, &MConnectionEnd::isNavigable, &MConnectionEnd::setNavigable)
|| end;
}
QARK_REGISTER_TYPE_NAME(MConnection, "MConnection")
QARK_REGISTER_DERIVED_CLASS(QXmlInArchive, QXmlOutArchive, MConnection, MElement)
QARK_REGISTER_DERIVED_CLASS(QXmlInArchive, QXmlOutArchive, MConnection, MRelation)
QARK_ACCESS_SERIALIZE(MConnection)
template<class Archive>
inline void Access<Archive, MConnection>::serialize(Archive &archive, MConnection &connection)
{
archive || tag(connection)
|| base<MRelation>(connection)
|| attr(QStringLiteral("custom-relation"), connection, &MConnection::customRelationId, &MConnection::setCustomRelationId)
|| attr(QStringLiteral("a"), connection, &MConnection::endA, &MConnection::setEndA)
|| attr(QStringLiteral("b"), connection, &MConnection::endB, &MConnection::setEndB)
|| end;
}
QARK_ACCESS_SPECIALIZE(QXmlInArchive, QXmlOutArchive, MConnection)
} // namespace qark

View File

@@ -31,6 +31,7 @@
#include "qmt/diagram/dboundary.h"
#include "qmt/diagram/dclass.h"
#include "qmt/diagram/dcomponent.h"
#include "qmt/diagram/dconnection.h"
#include "qmt/diagram/ddependency.h"
#include "qmt/diagram/ddiagram.h"
#include "qmt/diagram/ditem.h"
@@ -135,6 +136,11 @@ void AlignOnRasterVisitor::visitDAssociation(DAssociation *association)
visitDRelation(association);
}
void AlignOnRasterVisitor::visitDConnection(DConnection *connection)
{
visitDRelation(connection);
}
void AlignOnRasterVisitor::visitDAnnotation(DAnnotation *annotation)
{
IMoveable *moveable = m_sceneInspector->moveable(annotation, m_diagram);

View File

@@ -55,6 +55,7 @@ public:
void visitDInheritance(DInheritance *inheritance) override;
void visitDDependency(DDependency *dependency) override;
void visitDAssociation(DAssociation *association) override;
void visitDConnection(DConnection *connection) override;
void visitDAnnotation(DAnnotation *annotation) override;
void visitDBoundary(DBoundary *boundary) override;

View File

@@ -37,6 +37,7 @@
#include "qmt/diagram/ditem.h"
#include "qmt/diagram/drelation.h"
#include "qmt/diagram/dassociation.h"
#include "qmt/diagram/dconnection.h"
#include "qmt/diagram_ui/diagram_mime_types.h"
#include "qmt/model_controller/modelcontroller.h"
#include "qmt/model_controller/mselection.h"
@@ -45,6 +46,7 @@
#include "qmt/model/mcanvasdiagram.h"
#include "qmt/model/mclass.h"
#include "qmt/model/mcomponent.h"
#include "qmt/model/mconnection.h"
#include "qmt/model/mdependency.h"
#include "qmt/model/mdiagram.h"
#include "qmt/model/minheritance.h"
@@ -81,12 +83,14 @@ public:
void visitMObject(const MObject *object) override
{
Q_UNUSED(object);
// TODO enhance with handling MConnection
m_accepted = dynamic_cast<const MDependency *>(m_relation) != 0;
}
void visitMClass(const MClass *klass) override
{
Q_UNUSED(klass);
// TODO enhance with handling MConnection
m_accepted = dynamic_cast<const MDependency *>(m_relation) != 0
|| dynamic_cast<const MInheritance *>(m_relation) != 0
|| dynamic_cast<const MAssociation *>(m_relation) != 0;
@@ -257,6 +261,44 @@ void DiagramSceneController::createAssociation(DClass *endAClass, DClass *endBCl
emit newElementCreated(relation, diagram);
}
void DiagramSceneController::createConnection(const QString &customRelationId,
DObject *endAObject, DObject *endBObject,
const QList<QPointF> &intermediatePoints, MDiagram *diagram,
std::function<void (MConnection *, DConnection *)> custom)
{
m_diagramController->undoController()->beginMergeSequence(tr("Create Connection"));
MObject *endAModelObject = m_modelController->findObject<MObject>(endAObject->modelUid());
QMT_CHECK(endAModelObject);
MObject *endBModelObject = m_modelController->findObject<MObject>(endBObject->modelUid());
QMT_CHECK(endBModelObject);
// TODO allow self assignment with just one intermediate point and a nice round arrow
if (endAModelObject == endBModelObject && intermediatePoints.count() < 2)
return;
auto modelConnection = new MConnection();
modelConnection->setCustomRelationId(customRelationId);
modelConnection->setEndAUid(endAModelObject->uid());
MConnectionEnd endA = modelConnection->endA();
endA.setNavigable(true);
modelConnection->setEndA(endA);
modelConnection->setEndBUid(endBModelObject->uid());
m_modelController->addRelation(endAModelObject, modelConnection);
DRelation *relation = addRelation(modelConnection, intermediatePoints, diagram);
DConnection *diagramConnection = dynamic_cast<DConnection *>(relation);
QMT_CHECK(diagramConnection);
if (custom)
custom(modelConnection, diagramConnection);
m_diagramController->undoController()->endMergeSequence();
if (relation)
emit newElementCreated(relation, diagram);
}
bool DiagramSceneController::relocateRelationEndA(DRelation *relation, DObject *targetObject)
{
return relocateRelationEnd(relation, targetObject, &MRelation::endAUid, &MRelation::setEndAUid);

View File

@@ -44,11 +44,13 @@ class MPackage;
class MDiagram;
class MRelation;
class MAssociation;
class MConnection;
class DElement;
class DObject;
class DClass;
class DRelation;
class DAssociation;
class DConnection;
class DSelection;
class IElementTasks;
class ISceneInspector;
@@ -86,6 +88,9 @@ public:
void createAssociation(DClass *endAClass, DClass *endBClass,
const QList<QPointF> &intermediatePoints, MDiagram *diagram,
std::function<void (MAssociation*, DAssociation*)> custom = 0);
void createConnection(const QString &customRelationId, DObject *endAObject, DObject *endBObject,
const QList<QPointF> &intermediatePoints, MDiagram *diagram,
std::function<void (MConnection*, DConnection*)> custom = 0);
bool relocateRelationEndA(DRelation *relation, DObject *targetObject);
bool relocateRelationEndB(DRelation *relation, DObject *targetObject);

View File

@@ -37,6 +37,7 @@
#include "qmt/diagram/ddependency.h"
#include "qmt/diagram/dinheritance.h"
#include "qmt/diagram/dassociation.h"
#include "qmt/diagram/dconnection.h"
#include "qmt/model/melement.h"
#include "qmt/model/mpackage.h"
@@ -121,6 +122,11 @@ void OpenDiagramElementVisitor::visitDAssociation(const qmt::DAssociation *assoc
visitDRelation(association);
}
void OpenDiagramElementVisitor::visitDConnection(const qmt::DConnection *connection)
{
visitDRelation(connection);
}
void OpenDiagramElementVisitor::visitDAnnotation(const qmt::DAnnotation *annotation)
{
Q_UNUSED(annotation);
@@ -199,5 +205,10 @@ void OpenModelElementVisitor::visitMAssociation(const qmt::MAssociation *associa
Q_UNUSED(association);
}
void OpenModelElementVisitor::visitMConnection(const qmt::MConnection *connection)
{
Q_UNUSED(connection);
}
} // namespace Internal
} // namespace ModelEditor

View File

@@ -53,6 +53,7 @@ public:
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);
@@ -79,6 +80,7 @@ public:
void visitMDependency(const qmt::MDependency *dependency) override;
void visitMInheritance(const qmt::MInheritance *inheritance) override;
void visitMAssociation(const qmt::MAssociation *association) override;
void visitMConnection(const qmt::MConnection *connection) override;
private:
ElementTasks *m_elementTasks = 0;