Commit 81008125 authored by Jochen Becher's avatar Jochen Becher

ModelEditor: Support custom relations in configuration files

Change-Id: I87338f290bd1ea729682236df8b017516a18e7bb
Reviewed-by: Tobias Hunger's avatarTobias Hunger <tobias.hunger@qt.io>
parent 42844215
......@@ -2,6 +2,9 @@
//
// Language syntax and commands:
//
//
// An Icon defines an icon of an element selected by stereotype.
//
// Icon {
// id: <id>
// title: <a UI title. Defaults to the id of the icon.>
......@@ -29,6 +32,8 @@
// RoundedRect { x: <x>; y: <y>; width: <width>; height: <height>; radius: <radius> }
// Circle { x: <center_x>; y: <center_y>; radius: <radius> }
// Ellipse { x: <center_x>; y: <center_y>; radiusX: <radius_x>; radiusY: <radius_y> }
// Diamond { x: <center_x>; y: <center_y>; width: <width>; height: <height; filled: <yes or no or true or false> }
// Triangle { x: <center_x>; y: <center_y>; width: <width>; height: <height; filled: <yes or no or true or false> }
// Arc { x: <center_x>; y: <center_y>; radiusX: <radius_x>; radiusY: <radius_y>; start: <start_angle>; span: <span_angle> }
// MoveTo { x: <x>; y: <y> }
// LineTo { x: <x>; y: <y> }
......@@ -38,6 +43,79 @@
// }
// }
//
//
// A Relation defines a new relation between to items:
//
// Relation {
// id: <id>
// title: <a UI title. Defaults to the id of the icon.>
// elements: <A list of elements that may be the start or end element of the relation. Can be one of
// class, component, package, diagram, item or any id of an Icon definition. Must be given.>
// stereotype: <Stereotype as a string. Defaults to nothing.>
// name: <Name of the relation. Defaults to nothing.>
// direction: <One of AtoB, BtoA or Bi. Defaults to nothing.>
// pattern: <The pattern used for the relation shaft.
// One of solid, dash, dot, dashdot, dashdotdot. Defaults to solid>
// color: <The color of the relation. One of A or B (uses the color of the respective end element) or
// any valid color (#rrggbb or a color name). Defaults to A.>
// End {
// end: <One of A or B. Defines the settings of the relations end.>
// elements: <Overrides the elements property of parent.>
// 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 {
// }
// }
// }
//
//
// A Dependency defines a number of settings of a dependency specialization:
//
// Dependency {
// id: <id>
// title: <a UI title. Defaults to the id of the icon.>
// elements: <A list of elements that provides this specialization in its menu. Can be one of
// class, component, package, diagram, item or any id of an Icon definition. Must be given.>
// stereotype: <Stereotype as a string. Defaults to nothing.>
// name: <Name of the relation. Defaults to nothing.>
// direction: <One of AtoB, BtoA or Bi. Defaults to nothing.>
// }
//
//
// An Inheritance defines settings of an inheritance specialization:
//
// Inheritance {
// id: <id>
// title: <a UI title. Defaults to the id of the icon.>
// elements: <A list of elements that provides this specialization in its menu. Can be one of
// class or any id of an Icon definition for classes. Defaults to class.>
// stereotype: <Stereotype as a string. Defaults to nothing.>
// name: <Name of the relation. Defaults to nothing.>
// }
//
//
// An Association defines settings of an association specialization:
//
// Association {
// id: <id>
// title: <a UI title. Defaults to the id of the icon.>
// elements: <A list of elements that provides this specialization in its menu. Can be one of
// class or any id of an Icon definition for classes. Defaults to class.>
// stereotype: <Stereotype as a string. Defaults to nothing.>
// name: <Name of the relation. Defaults to nothing.>
// End {
// end: <One of A or B. Defines the settings of the relations end.>
// 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.>
// relationship: <One of Association, Aggregation, Composition. Defaults to Association.>
// }
// }
//
//
// A toolbar of icons. If no toolbar is defined the standard toolbar is shown.
//
// Toolbar {
// id: <id>
// title: <a Ui title. Defaults to the id of the toolbar>
......@@ -104,6 +182,54 @@ Icon {
}
}
Association {
id: AggregationOne
title: "Aggregation (?:1)"
End {
end: A
cardinality: 1
navigable: yes
relationship: aggregation
}
}
Association {
id: AggregationMany
title: "Aggregation (?:N)"
End {
end: A
cardinality: "*"
navigable: yes
relationship: aggregation
}
}
// ********************
// ** Class Toolbars **
// ********************
Toolbar {
id: ClassToolbar
element: class
Tools {
Tool { element: dependency }
Tool { element: inheritance }
Tool { element: association }
Tool { element: AggregationOne }
Tool { element: AggregationMany }
}
}
Toolbar {
id: InterfaceToolbar
element: Interface
Tools {
Tool { element: dependency }
Tool { element: inheritance }
}
}
// ****************
// ** Components **
// ****************
......@@ -276,6 +402,34 @@ Icon {
}
}
Relation {
id: Controlflow
pattern: solid
color: A
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 }
//}
}
}
Toolbar {
id: ActivityToolbar
element: Start, Activity, Condition, HorizontalBar, VerticalBar
Tools {
Tool { element: Controlflow }
Tool { element: dependency }
}
}
// **************
// ** Toolbars **
// **************
......
......@@ -252,6 +252,8 @@ QtcLibrary {
"serializer/modelserializer.h",
"serializer/projectserializer.cpp",
"serializer/projectserializer.h",
"stereotype/customrelation.cpp",
"stereotype/customrelation.h",
"stereotype/iconshape.cpp",
"stereotype/iconshape.h",
"stereotype/shape.h",
......
......@@ -71,6 +71,8 @@ void ConfigController::readStereotypeDefinitions(const QString &path)
StereotypeDefinitionParser parser;
connect(&parser, &StereotypeDefinitionParser::iconParsed,
this, &ConfigController::onStereotypeIconParsed);
connect(&parser, &StereotypeDefinitionParser::relationParsed,
this, &ConfigController::onRelationParsed);
connect(&parser, &StereotypeDefinitionParser::toolbarParsed,
this, &ConfigController::onToolbarParsed);
......@@ -116,6 +118,11 @@ void ConfigController::onStereotypeIconParsed(const StereotypeIcon &stereotypeIc
d->m_stereotypeController->addStereotypeIcon(stereotypeIcon);
}
void ConfigController::onRelationParsed(const CustomRelation &customRelation)
{
d->m_stereotypeController->addCustomRelation(customRelation);
}
void ConfigController::onToolbarParsed(const Toolbar &toolbar)
{
d->m_stereotypeController->addToolbar(toolbar);
......
......@@ -30,6 +30,7 @@
namespace qmt {
class CustomRelation;
class StereotypeController;
class StereotypeIcon;
class Toolbar;
......@@ -49,6 +50,7 @@ public:
private:
void onStereotypeIconParsed(const StereotypeIcon &stereotypeIcon);
void onRelationParsed(const CustomRelation &customRelation);
void onToolbarParsed(const Toolbar &toolbar);
ConfigControllerPrivate *d;
......
......@@ -27,12 +27,14 @@
#include <QObject>
#include "qmt/infrastructure/exceptions.h"
#include "qmt/stereotype/customrelation.h"
#include "qmt/stereotype/toolbar.h"
#include "sourcepos.h"
#include <QPair>
#include <QHash>
#include <functional>
namespace qmt {
......@@ -59,6 +61,17 @@ class QMT_EXPORT StereotypeDefinitionParser : public QObject
Q_OBJECT
class StereotypeDefinitionParserPrivate;
class IconCommandParameter;
class Value;
enum Type {
Void,
Identifier,
String,
Int,
Float,
Boolean,
Color
};
public:
explicit StereotypeDefinitionParser(QObject *parent = 0);
......@@ -66,6 +79,7 @@ public:
signals:
void iconParsed(const StereotypeIcon &stereotypeIcon);
void relationParsed(const CustomRelation &relation);
void toolbarParsed(const Toolbar &toolbar);
public:
......@@ -78,12 +92,24 @@ private:
static QPair<int, IconCommandParameter> SCALED(int keyword);
static QPair<int, IconCommandParameter> FIX(int keyword);
static QPair<int, IconCommandParameter> ABSOLUTE(int keyword);
void parseIconShape(StereotypeIcon *stereotypeIcon);
QHash<int, ShapeValueF> parseIconShapeProperties(const QHash<int, IconCommandParameter> &parameters);
static QPair<int, IconCommandParameter> BOOLEAN(int keyword);
IconShape parseIconShape();
QHash<int, IconCommandParameter> parseIconShapeProperties(const QHash<int, IconCommandParameter> &parameters);
void parseRelation(CustomRelation::Element element);
void parseRelationEnd(CustomRelation *relation);
void parseToolbar();
void parseToolbarTools(Toolbar *toolbar);
void parseToolbarTool(Toolbar::Tool *tool);
void parseToolbarTool(const Toolbar *toolbar, Toolbar::Tool *tool);
template<typename T>
void parseEnums(const QList<QString> &identifiers, const QHash<QString, T> &identifierNames,
const SourcePos &sourcePos, std::function<void(T)> setter);
template<typename T>
void parseEnum(const QString &identifier, const QHash<QString, T> &identifierNames,
const SourcePos &sourcePos, std::function<void(T)> setter);
QString parseStringProperty();
int parseIntProperty();
......@@ -92,6 +118,7 @@ private:
QList<QString> parseIdentifierListProperty();
bool parseBoolProperty();
QColor parseColorProperty();
Value parseProperty();
QString parseStringExpression();
qreal parseFloatExpression();
......@@ -99,6 +126,7 @@ private:
QString parseIdentifierExpression();
bool parseBoolExpression();
QColor parseColorExpression();
Value parseExpression();
void expectBlockBegin();
bool readProperty(Token *token);
......
......@@ -130,6 +130,7 @@ HEADERS += \
$$PWD/serializer/infrastructureserializer.h \
$$PWD/serializer/modelserializer.h \
$$PWD/serializer/projectserializer.h \
$$PWD/stereotype/customrelation.h \
$$PWD/stereotype/iconshape.h \
$$PWD/stereotype/shape.h \
$$PWD/stereotype/shapepaintvisitor.h \
......@@ -155,7 +156,7 @@ HEADERS += \
$$PWD/tasks/ielementtasks.h \
$$PWD/tasks/isceneinspector.h \
$$PWD/tasks/voidelementtasks.h \
$$PWD/infrastructure/qmtassert.h
$$PWD/infrastructure/qmtassert.h \
SOURCES += \
$$PWD/config/configcontroller.cpp \
......@@ -258,6 +259,7 @@ SOURCES += \
$$PWD/serializer/infrastructureserializer.cpp \
$$PWD/serializer/modelserializer.cpp \
$$PWD/serializer/projectserializer.cpp \
$$PWD/stereotype/customrelation.cpp \
$$PWD/stereotype/iconshape.cpp \
$$PWD/stereotype/shapepaintvisitor.cpp \
$$PWD/stereotype/shapes.cpp \
......@@ -277,7 +279,7 @@ SOURCES += \
$$PWD/tasks/diagramscenecontroller.cpp \
$$PWD/tasks/finddiagramvisitor.cpp \
$$PWD/tasks/findrootdiagramvisitor.cpp \
$$PWD/tasks/voidelementtasks.cpp
$$PWD/tasks/voidelementtasks.cpp \
RESOURCES += \
$$PWD/resources/resources.qrc
/****************************************************************************
**
** 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 "customrelation.h"
namespace qmt {
void CustomRelation::End::setEndItems(const QList<QString> &endItems)
{
m_endItems = endItems;
}
void CustomRelation::End::setRole(const QString &role)
{
m_role = role;
}
void CustomRelation::End::setCardinality(const QString &cardinality)
{
m_cardinality = cardinality;
}
void CustomRelation::End::setNavigable(bool navigable)
{
m_navigable = navigable;
}
void CustomRelation::End::setRelationship(CustomRelation::Relationship relationship)
{
m_relationship = relationship;
}
void CustomRelation::End::setHead(CustomRelation::Head head)
{
m_head = head;
}
void CustomRelation::End::setShape(const IconShape &shape)
{
m_shape = shape;
}
CustomRelation::CustomRelation()
{
}
CustomRelation::~CustomRelation()
{
}
bool CustomRelation::isNull() const
{
return m_id.isEmpty();
}
void CustomRelation::setElement(CustomRelation::Element element)
{
m_element = element;
}
void CustomRelation::setId(const QString &id)
{
m_id = id;
}
void CustomRelation::setTitle(const QString &title)
{
m_title = title;
}
void CustomRelation::setEndItems(const QList<QString> &endItems)
{
m_endItems = endItems;
}
void CustomRelation::setStereotypes(const QSet<QString> &stereotypes)
{
m_stereotypes = stereotypes;
}
void CustomRelation::setName(const QString &name)
{
m_name = name;
}
void CustomRelation::setDirection(CustomRelation::Direction direction)
{
m_direction = direction;
}
void CustomRelation::setEndA(const CustomRelation::End &end)
{
m_endA = end;
}
void CustomRelation::setEndB(const CustomRelation::End &end)
{
m_endB = end;
}
void CustomRelation::setShaftPattern(CustomRelation::ShaftPattern shaftPattern)
{
m_shaftPattern = shaftPattern;
}
void CustomRelation::setColorType(CustomRelation::ColorType colorType)
{
m_colorType = colorType;
}
void CustomRelation::setColor(const QColor &color)
{
m_color = color;
}
} // 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 "iconshape.h"
#include <QString>
#include <QList>
#include <QSet>
#include <QColor>
namespace qmt {
class QMT_EXPORT CustomRelation
{
public:
enum class Element {
Relation,
Dependency,
Inheritance,
Association
};
enum class Direction {
AtoB,
BToA,
Bi
};
enum class Relationship {
Association,
Aggregation,
Composition
};
enum class ShaftPattern {
Solid,
Dash,
Dot,
DashDot,
DashDotDot
};
enum class Head {
None,
Shape,
Arrow,
Triangle,
FilledTriangle,
Diamond,
FilledDiamond
};
enum class ColorType {
EndA,
EndB,
Custom
};
class End {
public:
QList<QString> endItems() const { return m_endItems; }
void setEndItems(const QList<QString> &endItems);
QString role() const { return m_role; }
void setRole(const QString &role);
QString cardinality() const { return m_cardinality; }
void setCardinality(const QString &cardinality);
bool navigable() const { return m_navigable; }
void setNavigable(bool navigable);
Relationship relationship() const { return m_relationship; }
void setRelationship(Relationship relationship);
Head head() const { return m_head; }
void setHead(Head head);
IconShape shape() const { return m_shape; }
void setShape(const IconShape &shape);
private:
QList<QString> m_endItems;
QString m_role;
QString m_cardinality;
bool m_navigable = false;
Relationship m_relationship = Relationship::Association;
Head m_head = Head::None;
IconShape m_shape;
};
CustomRelation();
~CustomRelation();
bool isNull() const;
Element element() const { return m_element; }
void setElement(Element element);
QString id() const { return m_id; }
void setId(const QString &id);
QString title() const { return m_title; }
void setTitle(const QString &title);
QList<QString> endItems() const { return m_endItems; }
void setEndItems(const QList<QString> &endItems);
QSet<QString> stereotypes() const { return m_stereotypes; }
void setStereotypes(const QSet<QString> &stereotypes);
QString name() const { return m_name; }
void setName(const QString &name);
Direction direction() const { return m_direction; }
void setDirection(Direction direction);
End endA() const { return m_endA; }
void setEndA(const End &end);
End endB() const { return m_endB; }
void setEndB(const End &end);
ShaftPattern shaftPattern() const { return m_shaftPattern; }
void setShaftPattern(ShaftPattern shaftPattern);
ColorType colorType() const { return m_colorType; }
void setColorType(ColorType colorType);
QColor color() const { return m_color; }
void setColor(const QColor &color);
private:
Element m_element = Element::Relation;
QString m_id;
QString m_title;
QList<QString> m_endItems;
QSet<QString> m_stereotypes;
QString m_name;
Direction m_direction = Direction::AtoB;
End m_endA;
End m_endB;
ShaftPattern m_shaftPattern = ShaftPattern::Solid;
ColorType m_colorType = ColorType::EndA;
QColor m_color;
};
inline uint qHash(CustomRelation::Relationship relationship) {
return ::qHash(static_cast<int>(relationship));
}
inline uint qHash(CustomRelation::ShaftPattern pattern) {
return ::qHash(static_cast<int>(pattern));
}
inline uint qHash(CustomRelation::Head head) {
return ::qHash(static_cast<int>(head));
}
} // namespace qmt
......@@ -34,11 +34,11 @@
#include <QPainter>
template<class T>
QList<T *> CloneAll(const QList<T *> &rhs)
QList<T *> cloneAll(const QList<T *> &rhs)
{
QList<T *> result;
foreach (T *t, rhs)
result.append(t != 0 ? t->Clone() : 0);
result.append(t != 0 ? t->clone() : 0);
return result;
}
......@@ -50,7 +50,7 @@ public:
IconShapePrivate() = default;
IconShapePrivate(const IconShapePrivate &rhs)
: m_shapes(CloneAll(rhs.m_shapes))
: m_shapes(cloneAll(rhs.m_shapes))
{
}
......@@ -63,7 +63,7 @@ public:
{
if (this != &rhs) {
qDeleteAll(m_shapes);
m_shapes = CloneAll(rhs.m_shapes);
m_shapes = cloneAll(rhs.m_shapes);
}
return *this;
}
......@@ -132,6 +132,16 @@ void IconShape::addEllipse(const ShapePointF &center, const ShapeSizeF &radius)
d->m_shapes.append(new EllipseShape(center, radius));
}
void IconShape::addDiamond(const ShapePointF &center, const ShapeSizeF &size, bool filled)
{
d->m_shapes.append(new DiamondShape(center, size, filled));
}
void IconShape::addTriangle(const ShapePointF &center, const ShapeSizeF &size, bool filled)
{
d->m_shapes.append(new TriangleShape(center, size, filled));
}
void IconShape::addArc(const ShapePointF &center, const ShapeSizeF &radius, qreal startAngle, qreal spanAngle)
{
d->m_shapes.append(new ArcShape(center, radius, startAngle, spanAngle));
......
......@@ -42,11 +42,9 @@ class QMT_EXPORT IconShape
public:
IconShape();
IconShape(const IconShape &rhs);
IconShape(const IconShape &&) = delete;
~IconShape();
IconShape &operator=(const IconShape &rhs);
IconShape &operator=(const IconShape &&) = delete;
QSizeF size() const;
void setSize(const QSizeF &size);
......@@ -56,6 +54,8 @@ public:
void addRoundedRect(const ShapePointF &pos, const ShapeSizeF &size, const ShapeValueF &radius);
void addCircle(const ShapePointF &center, const ShapeValueF &radius);
void addEllipse(const ShapePointF &center, const ShapeSizeF &radius);
void addDiamond(const ShapePointF &center, const ShapeSizeF &size, bool filled);