Commit ffb5dc75 authored by Jochen Becher's avatar Jochen Becher

ModelEditor: Introduce custom relation type "Connection"

Change-Id: Iddd45508dcb2de1fa2b6d9b2b881b54a73172caf
Reviewed-by: Tobias Hunger's avatarTobias Hunger <tobias.hunger@qt.io>
parent 82cb2b24
......@@ -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
}
}
......
......@@ -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",
......
/****************************************************************************
**
** 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
/****************************************************************************
**
** 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
......@@ -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;
};
......
......@@ -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;
};
......
......@@ -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)
......
......@@ -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;
......
......@@ -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
......@@ -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;
......
......@@ -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)
......
......@@ -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;
......
......@@ -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) {
......
......@@ -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);
......
......@@ -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);
......
......@@ -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;
};
......
......@@ -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
......
......@@ -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;
......
/****************************************************************************
**
** 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) {