forked from qt-creator/qt-creator
ModelEditor: Support custom relations in configuration files
Change-Id: I87338f290bd1ea729682236df8b017516a18e7bb Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
This commit is contained in:
@@ -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;
|
||||
|
@@ -30,6 +30,7 @@
|
||||
#include "qmt/infrastructure/qmtassert.h"
|
||||
#include "qmt/stereotype/stereotypeicon.h"
|
||||
#include "qmt/stereotype/shapevalue.h"
|
||||
#include "qmt/stereotype/customrelation.h"
|
||||
#include "qmt/stereotype/toolbar.h"
|
||||
|
||||
#include <QHash>
|
||||
@@ -89,6 +90,40 @@ static const int KEYWORD_TOOL = 73;
|
||||
static const int KEYWORD_ELEMENT = 74;
|
||||
static const int KEYWORD_SEPARATOR = 75;
|
||||
|
||||
// Relation Definition
|
||||
static const int KEYWORD_RELATION = 100;
|
||||
static const int KEYWORD_DEPENDENCY = 101;
|
||||
static const int KEYWORD_INHERITANCE = 102;
|
||||
static const int KEYWORD_ASSOCIATION = 103;
|
||||
static const int KEYWORD_NAME = 104;
|
||||
static const int KEYWORD_DIRECTION = 105;
|
||||
static const int KEYWORD_ATOB = 106;
|
||||
static const int KEYWORD_BTOA = 107;
|
||||
static const int KEYWORD_BI = 108;
|
||||
static const int KEYWORD_END = 109;
|
||||
static const int KEYWORD_A = 110;
|
||||
static const int KEYWORD_B = 111;
|
||||
static const int KEYWORD_ROLE = 112;
|
||||
static const int KEYWORD_CARDINALITY = 113;
|
||||
static const int KEYWORD_NAVIGABLE = 114;
|
||||
static const int KEYWORD_RELATIONSHIP = 115;
|
||||
static const int KEYWORD_AGGREGATION = 116;
|
||||
static const int KEYWORD_COMPOSITION = 117;
|
||||
static const int KEYWORD_SHAFT = 118;
|
||||
static const int KEYWORD_HEAD = 119;
|
||||
|
||||
// Relation Shapes
|
||||
static const int KEYWORD_DIAMOND = 130;
|
||||
static const int KEYWORD_TRIANGLE = 131;
|
||||
static const int KEYWORD_FILLED = 132;
|
||||
static const int KEYWORD_PATTERN = 133;
|
||||
static const int KEYWORD_SOLID = 134;
|
||||
static const int KEYWORD_DOT = 135;
|
||||
static const int KEYWORD_DASH = 136;
|
||||
static const int KEYWORD_DASHDOT = 137;
|
||||
static const int KEYWORD_DASHDOTDOT = 138;
|
||||
static const int KEYWORD_COLOR = 139;
|
||||
|
||||
// Operatoren
|
||||
static const int OPERATOR_SEMICOLON = 1;
|
||||
static const int OPERATOR_BRACE_OPEN = 2;
|
||||
@@ -124,18 +159,61 @@ public:
|
||||
class StereotypeDefinitionParser::IconCommandParameter
|
||||
{
|
||||
public:
|
||||
enum Type {
|
||||
ShapeValue,
|
||||
Boolean
|
||||
};
|
||||
|
||||
IconCommandParameter() = default;
|
||||
|
||||
IconCommandParameter(int keyword, ShapeValueF::Unit unit, ShapeValueF::Origin origin = ShapeValueF::OriginSmart)
|
||||
: m_keyword(keyword),
|
||||
m_type(ShapeValue),
|
||||
m_unit(unit),
|
||||
m_origin(origin)
|
||||
{
|
||||
}
|
||||
|
||||
IconCommandParameter(int keyword, Type type)
|
||||
: m_keyword(keyword),
|
||||
m_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
operator ShapeValueF() const { return m_shapeValue; }
|
||||
|
||||
Type type() const { return m_type; }
|
||||
ShapeValueF::Unit unit() const { return m_unit; }
|
||||
ShapeValueF::Origin origin() const { return m_origin; }
|
||||
ShapeValueF shapeValue() const { return m_shapeValue; }
|
||||
void setShapeValue(const ShapeValueF &shapeValue) { m_shapeValue = shapeValue; }
|
||||
bool boolean() const { return m_boolean; }
|
||||
void setBoolean(bool boolean) { m_boolean = boolean; }
|
||||
|
||||
private:
|
||||
int m_keyword = -1;
|
||||
Type m_type = ShapeValue;
|
||||
ShapeValueF::Unit m_unit = ShapeValueF::UnitAbsolute;
|
||||
ShapeValueF::Origin m_origin = ShapeValueF::OriginCenter;
|
||||
ShapeValueF::Origin m_origin = ShapeValueF::OriginSmart;
|
||||
ShapeValueF m_shapeValue;
|
||||
bool m_boolean = false;
|
||||
};
|
||||
|
||||
class StereotypeDefinitionParser::Value
|
||||
{
|
||||
public:
|
||||
Value(StereotypeDefinitionParser::Type type, QVariant value)
|
||||
: m_type(type),
|
||||
m_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
StereotypeDefinitionParser::Type type() const { return m_type; }
|
||||
QVariant value() const { return m_value; }
|
||||
|
||||
private:
|
||||
StereotypeDefinitionParser::Type m_type = StereotypeDefinitionParser::Void;
|
||||
QVariant m_value;
|
||||
};
|
||||
|
||||
StereotypeDefinitionParser::StereotypeDefinitionParser(QObject *parent)
|
||||
@@ -196,6 +274,36 @@ void StereotypeDefinitionParser::parse(ITextSource *source)
|
||||
<< qMakePair(QString(QStringLiteral("tool")), KEYWORD_TOOL)
|
||||
<< qMakePair(QString(QStringLiteral("element")), KEYWORD_ELEMENT)
|
||||
<< qMakePair(QString(QStringLiteral("separator")), KEYWORD_SEPARATOR)
|
||||
<< qMakePair(QString(QStringLiteral("relation")), KEYWORD_RELATION)
|
||||
<< qMakePair(QString(QStringLiteral("dependency")), KEYWORD_DEPENDENCY)
|
||||
<< qMakePair(QString(QStringLiteral("inheritance")), KEYWORD_INHERITANCE)
|
||||
<< qMakePair(QString(QStringLiteral("association")), KEYWORD_ASSOCIATION)
|
||||
<< qMakePair(QString(QStringLiteral("name")), KEYWORD_NAME)
|
||||
<< qMakePair(QString(QStringLiteral("direction")), KEYWORD_DIRECTION)
|
||||
<< qMakePair(QString(QStringLiteral("atob")), KEYWORD_ATOB)
|
||||
<< qMakePair(QString(QStringLiteral("btoa")), KEYWORD_BTOA)
|
||||
<< qMakePair(QString(QStringLiteral("bi")), KEYWORD_BI)
|
||||
<< qMakePair(QString(QStringLiteral("end")), KEYWORD_END)
|
||||
<< qMakePair(QString(QStringLiteral("a")), KEYWORD_A)
|
||||
<< qMakePair(QString(QStringLiteral("b")), KEYWORD_B)
|
||||
<< qMakePair(QString(QStringLiteral("role")), KEYWORD_ROLE)
|
||||
<< qMakePair(QString(QStringLiteral("cardinality")), KEYWORD_CARDINALITY)
|
||||
<< qMakePair(QString(QStringLiteral("navigable")), KEYWORD_NAVIGABLE)
|
||||
<< qMakePair(QString(QStringLiteral("relationship")), KEYWORD_RELATIONSHIP)
|
||||
<< qMakePair(QString(QStringLiteral("aggregation")), KEYWORD_AGGREGATION)
|
||||
<< qMakePair(QString(QStringLiteral("composition")), KEYWORD_COMPOSITION)
|
||||
<< qMakePair(QString(QStringLiteral("shaft")), KEYWORD_SHAFT)
|
||||
<< qMakePair(QString(QStringLiteral("head")), KEYWORD_HEAD)
|
||||
<< qMakePair(QString(QStringLiteral("diamond")), KEYWORD_DIAMOND)
|
||||
<< qMakePair(QString(QStringLiteral("triangle")), KEYWORD_TRIANGLE)
|
||||
<< qMakePair(QString(QStringLiteral("filled")), KEYWORD_FILLED)
|
||||
<< qMakePair(QString(QStringLiteral("pattern")), KEYWORD_PATTERN)
|
||||
<< qMakePair(QString(QStringLiteral("solid")), KEYWORD_SOLID)
|
||||
<< qMakePair(QString(QStringLiteral("dot")), KEYWORD_DOT)
|
||||
<< qMakePair(QString(QStringLiteral("dash")), KEYWORD_DASH)
|
||||
<< qMakePair(QString(QStringLiteral("dashdot")), KEYWORD_DASHDOT)
|
||||
<< qMakePair(QString(QStringLiteral("dashdotdot")), KEYWORD_DASHDOTDOT)
|
||||
<< qMakePair(QString(QStringLiteral("color")), KEYWORD_COLOR)
|
||||
);
|
||||
textScanner.setOperators(
|
||||
QList<QPair<QString, int> >()
|
||||
@@ -229,8 +337,16 @@ void StereotypeDefinitionParser::parseFile()
|
||||
parseIcon();
|
||||
else if (token.type() == Token::TokenKeyword && token.subtype() == KEYWORD_TOOLBAR)
|
||||
parseToolbar();
|
||||
else if (token.type() == Token::TokenKeyword && token.subtype() == KEYWORD_RELATION)
|
||||
parseRelation(CustomRelation::Element::Relation);
|
||||
else if (token.type() == Token::TokenKeyword && token.subtype() == KEYWORD_DEPENDENCY)
|
||||
parseRelation(CustomRelation::Element::Dependency);
|
||||
else if (token.type() == Token::TokenKeyword && token.subtype() == KEYWORD_INHERITANCE)
|
||||
parseRelation(CustomRelation::Element::Inheritance);
|
||||
else if (token.type() == Token::TokenKeyword && token.subtype() == KEYWORD_ASSOCIATION)
|
||||
parseRelation(CustomRelation::Element::Association);
|
||||
else
|
||||
throw StereotypeDefinitionParserError(QStringLiteral("Expected 'Icon' or 'Toolbar'."), token.sourcePos());
|
||||
throw StereotypeDefinitionParserError(QStringLiteral("Expected 'Icon', 'Toolbar', 'Relation', 'Dependency', 'Inheritance' or 'Association'."), token.sourcePos());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,19 +367,15 @@ void StereotypeDefinitionParser::parseIcon()
|
||||
break;
|
||||
case KEYWORD_ELEMENTS:
|
||||
{
|
||||
QList<QString> identifiers = parseIdentifierListProperty();
|
||||
foreach (const QString &identifier, identifiers) {
|
||||
static QHash<QString, StereotypeIcon::Element> elementNames = QHash<QString, StereotypeIcon::Element>()
|
||||
<< qMakePair(QString(QStringLiteral("package")), StereotypeIcon::ElementPackage)
|
||||
<< qMakePair(QString(QStringLiteral("component")), StereotypeIcon::ElementComponent)
|
||||
<< qMakePair(QString(QStringLiteral("class")), StereotypeIcon::ElementClass)
|
||||
<< qMakePair(QString(QStringLiteral("diagram")), StereotypeIcon::ElementDiagram)
|
||||
<< qMakePair(QString(QStringLiteral("item")), StereotypeIcon::ElementItem);
|
||||
QString elementName = identifier.toLower();
|
||||
if (!elementNames.contains(elementName))
|
||||
throw StereotypeDefinitionParserError(QString(QStringLiteral("Unexpected value \"%1\" for element.")).arg(identifier), token.sourcePos());
|
||||
elements.insert(elementNames.value(elementName));
|
||||
}
|
||||
const static QHash<QString, StereotypeIcon::Element> elementNames = QHash<QString, StereotypeIcon::Element>()
|
||||
<< qMakePair(QString(QStringLiteral("package")), StereotypeIcon::ElementPackage)
|
||||
<< qMakePair(QString(QStringLiteral("component")), StereotypeIcon::ElementComponent)
|
||||
<< qMakePair(QString(QStringLiteral("class")), StereotypeIcon::ElementClass)
|
||||
<< qMakePair(QString(QStringLiteral("diagram")), StereotypeIcon::ElementDiagram)
|
||||
<< qMakePair(QString(QStringLiteral("item")), StereotypeIcon::ElementItem);
|
||||
parseEnums<StereotypeIcon::Element>(
|
||||
parseIdentifierListProperty(), elementNames, token.sourcePos(),
|
||||
[&](StereotypeIcon::Element element) { elements.insert(element); });
|
||||
break;
|
||||
}
|
||||
case KEYWORD_STEREOTYPE:
|
||||
@@ -283,61 +395,46 @@ void StereotypeDefinitionParser::parseIcon()
|
||||
break;
|
||||
case KEYWORD_LOCK_SIZE:
|
||||
{
|
||||
QString lockValue = parseIdentifierProperty();
|
||||
QString lockName = lockValue.toLower();
|
||||
static QHash<QString, StereotypeIcon::SizeLock> lockNames = QHash<QString, StereotypeIcon::SizeLock>()
|
||||
const static QHash<QString, StereotypeIcon::SizeLock> lockNames = QHash<QString, StereotypeIcon::SizeLock>()
|
||||
<< qMakePair(QString(QStringLiteral("none")), StereotypeIcon::LockNone)
|
||||
<< qMakePair(QString(QStringLiteral("width")), StereotypeIcon::LockWidth)
|
||||
<< qMakePair(QString(QStringLiteral("height")), StereotypeIcon::LockHeight)
|
||||
<< qMakePair(QString(QStringLiteral("size")), StereotypeIcon::LockSize)
|
||||
<< qMakePair(QString(QStringLiteral("ratio")), StereotypeIcon::LockRatio);
|
||||
if (lockNames.contains(lockName)) {
|
||||
StereotypeIcon::SizeLock sizeLock = lockNames.value(lockName);
|
||||
stereotypeIcon.setSizeLock(sizeLock);
|
||||
} else {
|
||||
throw StereotypeDefinitionParserError(QString(QStringLiteral("Unexpected value \"%1\" for size lock.")).arg(lockValue), token.sourcePos());
|
||||
}
|
||||
parseEnum<StereotypeIcon::SizeLock>(
|
||||
parseIdentifierProperty(), lockNames, token.sourcePos(),
|
||||
[&](StereotypeIcon::SizeLock lock) { stereotypeIcon.setSizeLock(lock); });
|
||||
break;
|
||||
}
|
||||
case KEYWORD_DISPLAY:
|
||||
{
|
||||
QString displayValue = parseIdentifierProperty();
|
||||
QString displayName = displayValue.toLower();
|
||||
static QHash<QString, StereotypeIcon::Display> displayNames = QHash<QString, StereotypeIcon::Display>()
|
||||
const static QHash<QString, StereotypeIcon::Display> displayNames = QHash<QString, StereotypeIcon::Display>()
|
||||
<< qMakePair(QString(QStringLiteral("none")), StereotypeIcon::DisplayNone)
|
||||
<< qMakePair(QString(QStringLiteral("label")), StereotypeIcon::DisplayLabel)
|
||||
<< qMakePair(QString(QStringLiteral("decoration")), StereotypeIcon::DisplayDecoration)
|
||||
<< qMakePair(QString(QStringLiteral("icon")), StereotypeIcon::DisplayIcon)
|
||||
<< qMakePair(QString(QStringLiteral("smart")), StereotypeIcon::DisplaySmart);
|
||||
if (displayNames.contains(displayName)) {
|
||||
StereotypeIcon::Display display = displayNames.value(displayName);
|
||||
stereotypeIcon.setDisplay(display);
|
||||
} else {
|
||||
throw StereotypeDefinitionParserError(QString(QStringLiteral("Unexpected value \"%1\" for stereotype display.")).arg(displayValue), token.sourcePos());
|
||||
}
|
||||
parseEnum<StereotypeIcon::Display>(
|
||||
parseIdentifierProperty(), displayNames, token.sourcePos(),
|
||||
[&](StereotypeIcon::Display display) { stereotypeIcon.setDisplay(display); });
|
||||
break;
|
||||
}
|
||||
case KEYWORD_TEXTALIGN:
|
||||
{
|
||||
QString alignValue = parseIdentifierProperty();
|
||||
QString alignName = alignValue.toLower();
|
||||
static QHash<QString, StereotypeIcon::TextAlignment> alignNames = QHash<QString, StereotypeIcon::TextAlignment>()
|
||||
const static QHash<QString, StereotypeIcon::TextAlignment> alignNames = QHash<QString, StereotypeIcon::TextAlignment>()
|
||||
<< qMakePair(QString(QStringLiteral("below")), StereotypeIcon::TextalignBelow)
|
||||
<< qMakePair(QString(QStringLiteral("center")), StereotypeIcon::TextalignCenter)
|
||||
<< qMakePair(QString(QStringLiteral("none")), StereotypeIcon::TextalignNone);
|
||||
if (alignNames.contains(alignName)) {
|
||||
StereotypeIcon::TextAlignment textAlignment = alignNames.value(alignName);
|
||||
stereotypeIcon.setTextAlignment(textAlignment);
|
||||
} else {
|
||||
throw StereotypeDefinitionParserError(QString(QStringLiteral("Unexpected value \"%1\" for text alignment.")).arg(alignValue), token.sourcePos());
|
||||
}
|
||||
parseEnum<StereotypeIcon::TextAlignment>(
|
||||
parseIdentifierProperty(), alignNames, token.sourcePos(),
|
||||
[&](StereotypeIcon::TextAlignment align) { stereotypeIcon.setTextAlignment(align); });
|
||||
break;
|
||||
}
|
||||
case KEYWORD_BASECOLOR:
|
||||
stereotypeIcon.setBaseColor(parseColorProperty());
|
||||
break;
|
||||
case KEYWORD_SHAPE:
|
||||
parseIconShape(&stereotypeIcon);
|
||||
stereotypeIcon.setIconShape(parseIconShape());
|
||||
break;
|
||||
default:
|
||||
throwUnknownPropertyError(token);
|
||||
@@ -367,10 +464,15 @@ QPair<int, StereotypeDefinitionParser::IconCommandParameter> StereotypeDefinitio
|
||||
return qMakePair(keyword, IconCommandParameter(keyword, ShapeValueF::UnitAbsolute));
|
||||
}
|
||||
|
||||
void StereotypeDefinitionParser::parseIconShape(StereotypeIcon *stereotypeIcon)
|
||||
QPair<int, StereotypeDefinitionParser::IconCommandParameter> StereotypeDefinitionParser::BOOLEAN(int keyword)
|
||||
{
|
||||
return qMakePair(keyword, IconCommandParameter(keyword, IconCommandParameter::Boolean));
|
||||
}
|
||||
|
||||
IconShape StereotypeDefinitionParser::parseIconShape()
|
||||
{
|
||||
IconShape iconShape;
|
||||
QHash<int, ShapeValueF> values;
|
||||
QHash<int, IconCommandParameter> values;
|
||||
typedef QHash<int, IconCommandParameter> Parameters;
|
||||
expectBlockBegin();
|
||||
Token token;
|
||||
@@ -458,26 +560,50 @@ void StereotypeDefinitionParser::parseIconShape(StereotypeIcon *stereotypeIcon)
|
||||
iconShape.closePath();
|
||||
skipOptionalEmptyBlock();
|
||||
break;
|
||||
case KEYWORD_DIAMOND:
|
||||
values = parseIconShapeProperties(
|
||||
Parameters() << SCALED(KEYWORD_X) << SCALED(KEYWORD_Y)
|
||||
<< SCALED(KEYWORD_WIDTH) << SCALED(KEYWORD_HEIGHT)
|
||||
<< BOOLEAN(KEYWORD_FILLED));
|
||||
iconShape.addDiamond(ShapePointF(values.value(KEYWORD_X), values.value(KEYWORD_Y)),
|
||||
ShapeSizeF(values.value(KEYWORD_WIDTH), values.value(KEYWORD_HEIGHT)),
|
||||
values.value(KEYWORD_FILLED).boolean());
|
||||
break;
|
||||
case KEYWORD_TRIANGLE:
|
||||
values = parseIconShapeProperties(
|
||||
Parameters() << SCALED(KEYWORD_X) << SCALED(KEYWORD_Y)
|
||||
<< SCALED(KEYWORD_WIDTH) << SCALED(KEYWORD_HEIGHT)
|
||||
<< BOOLEAN(KEYWORD_FILLED));
|
||||
iconShape.addTriangle(ShapePointF(values.value(KEYWORD_X), values.value(KEYWORD_Y)),
|
||||
ShapeSizeF(values.value(KEYWORD_WIDTH), values.value(KEYWORD_HEIGHT)),
|
||||
values.value(KEYWORD_FILLED).boolean());
|
||||
break;
|
||||
default:
|
||||
throwUnknownPropertyError(token);
|
||||
}
|
||||
if (!expectPropertySeparatorOrBlockEnd())
|
||||
break;
|
||||
}
|
||||
stereotypeIcon->setIconShape(iconShape);
|
||||
return iconShape;
|
||||
}
|
||||
|
||||
QHash<int, ShapeValueF> StereotypeDefinitionParser::parseIconShapeProperties(const QHash<int, IconCommandParameter> ¶meters)
|
||||
QHash<int, StereotypeDefinitionParser::IconCommandParameter> StereotypeDefinitionParser::parseIconShapeProperties(const QHash<int, IconCommandParameter> ¶meters)
|
||||
{
|
||||
expectBlockBegin();
|
||||
QHash<int, ShapeValueF> values;
|
||||
QHash<int, IconCommandParameter> values;
|
||||
Token token;
|
||||
while (readProperty(&token)) {
|
||||
if (parameters.contains(token.subtype())) {
|
||||
IconCommandParameter parameter = parameters.value(token.subtype());
|
||||
if (values.contains(token.subtype()))
|
||||
throw StereotypeDefinitionParserError(QStringLiteral("Property givent twice."), token.sourcePos());
|
||||
values.insert(token.subtype(), ShapeValueF(parseFloatProperty(), parameter.m_unit, parameter.m_origin));
|
||||
throw StereotypeDefinitionParserError(QStringLiteral("Property given twice."), token.sourcePos());
|
||||
IconCommandParameter parameter = parameters.value(token.subtype());
|
||||
if (parameter.type() == IconCommandParameter::ShapeValue)
|
||||
parameter.setShapeValue(ShapeValueF(parseFloatProperty(), parameter.unit(), parameter.origin()));
|
||||
else if (parameter.type() == IconCommandParameter::Boolean)
|
||||
parameter.setBoolean(parseBoolProperty());
|
||||
else
|
||||
throw StereotypeDefinitionParserError("Unexpected type of property.", token.sourcePos());
|
||||
values.insert(token.subtype(), parameter);
|
||||
} else {
|
||||
throwUnknownPropertyError(token);
|
||||
}
|
||||
@@ -491,6 +617,192 @@ QHash<int, ShapeValueF> StereotypeDefinitionParser::parseIconShapeProperties(con
|
||||
return values;
|
||||
}
|
||||
|
||||
void StereotypeDefinitionParser::parseRelation(CustomRelation::Element element)
|
||||
{
|
||||
CustomRelation relation;
|
||||
relation.setElement(element);
|
||||
QSet<QString> stereotypes;
|
||||
expectBlockBegin();
|
||||
Token token;
|
||||
while (readProperty(&token)) {
|
||||
switch (token.subtype()) {
|
||||
case KEYWORD_ID:
|
||||
relation.setId(parseIdentifierProperty());
|
||||
break;
|
||||
case KEYWORD_TITLE:
|
||||
relation.setTitle(parseStringProperty());
|
||||
break;
|
||||
case KEYWORD_ELEMENTS:
|
||||
relation.setEndItems(parseIdentifierListProperty());
|
||||
break;
|
||||
case KEYWORD_STEREOTYPE:
|
||||
stereotypes.insert(parseStringProperty());
|
||||
break;
|
||||
case KEYWORD_NAME:
|
||||
relation.setName(parseStringProperty());
|
||||
break;
|
||||
case KEYWORD_DIRECTION:
|
||||
{
|
||||
const static QHash<QString, CustomRelation::Direction> directionNames = QHash<QString, CustomRelation::Direction>()
|
||||
<< qMakePair(QString(QStringLiteral("atob")), CustomRelation::Direction::AtoB)
|
||||
<< qMakePair(QString(QStringLiteral("btoa")), CustomRelation::Direction::BToA)
|
||||
<< qMakePair(QString(QStringLiteral("bi")), CustomRelation::Direction::Bi);
|
||||
if (element != CustomRelation::Element::Dependency)
|
||||
throwUnknownPropertyError(token);
|
||||
parseEnum<CustomRelation::Direction>(
|
||||
parseIdentifierProperty(), directionNames, token.sourcePos(),
|
||||
[&](CustomRelation::Direction direction) { relation.setDirection(direction); });
|
||||
break;
|
||||
}
|
||||
case KEYWORD_PATTERN:
|
||||
{
|
||||
const static QHash<QString, CustomRelation::ShaftPattern> patternNames = QHash<QString, CustomRelation::ShaftPattern>()
|
||||
<< qMakePair(QString(QStringLiteral("solid")), CustomRelation::ShaftPattern::Solid)
|
||||
<< qMakePair(QString(QStringLiteral("dash")), CustomRelation::ShaftPattern::Dash)
|
||||
<< qMakePair(QString(QStringLiteral("dot")), CustomRelation::ShaftPattern::Dot)
|
||||
<< qMakePair(QString(QStringLiteral("dashdot")), CustomRelation::ShaftPattern::DashDot)
|
||||
<< qMakePair(QString(QStringLiteral("dashdotdot")), CustomRelation::ShaftPattern::DashDotDot);
|
||||
if (element != CustomRelation::Element::Relation)
|
||||
throwUnknownPropertyError(token);
|
||||
parseEnum<CustomRelation::ShaftPattern>(
|
||||
parseIdentifierProperty(), patternNames, token.sourcePos(),
|
||||
[&](CustomRelation::ShaftPattern pattern) { relation.setShaftPattern(pattern); });
|
||||
break;
|
||||
}
|
||||
case KEYWORD_COLOR:
|
||||
{
|
||||
if (element != CustomRelation::Element::Relation)
|
||||
throwUnknownPropertyError(token);
|
||||
Value expression = parseProperty();
|
||||
if (expression.type() == Color) {
|
||||
relation.setColorType(CustomRelation::ColorType::Custom);
|
||||
relation.setColor(expression.value().value<QColor>());
|
||||
} else if (expression.type() == Identifier) {
|
||||
QString colorValue = expression.value().toString();
|
||||
QString colorName = colorValue.toLower();
|
||||
if (colorName == "a") {
|
||||
relation.setColorType(CustomRelation::ColorType::EndA);
|
||||
} else if (colorName == "b") {
|
||||
relation.setColorType(CustomRelation::ColorType::EndB);
|
||||
} else if (QColor::isValidColor(colorName)) {
|
||||
relation.setColorType(CustomRelation::ColorType::Custom);
|
||||
relation.setColor(QColor(colorName));
|
||||
} else {
|
||||
throw StereotypeDefinitionParserError(QString(QStringLiteral("Unexpected value \"%1\" for color.")).arg(colorValue), token.sourcePos());
|
||||
}
|
||||
} else {
|
||||
throw StereotypeDefinitionParserError(QStringLiteral("Unexpected value for color."), token.sourcePos());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case KEYWORD_END:
|
||||
parseRelationEnd(&relation);
|
||||
break;
|
||||
default:
|
||||
throwUnknownPropertyError(token);
|
||||
}
|
||||
if (!expectPropertySeparatorOrBlockEnd())
|
||||
break;
|
||||
}
|
||||
relation.setStereotypes(stereotypes);
|
||||
if (relation.id().isEmpty())
|
||||
throw StereotypeDefinitionParserError(QStringLiteral("Missing id in Relation definition."), d->m_scanner->sourcePos());
|
||||
emit relationParsed(relation);
|
||||
}
|
||||
|
||||
void StereotypeDefinitionParser::parseRelationEnd(CustomRelation *relation)
|
||||
{
|
||||
CustomRelation::End relationEnd;
|
||||
bool isEndB = false;
|
||||
expectBlockBegin();
|
||||
Token token;
|
||||
while (readProperty(&token)) {
|
||||
switch (token.subtype()) {
|
||||
case KEYWORD_END:
|
||||
{
|
||||
QString endValue = parseIdentifierProperty();
|
||||
QString endName = endValue.toLower();
|
||||
if (endName == "a")
|
||||
isEndB = false;
|
||||
else if (endName == "b")
|
||||
isEndB = true;
|
||||
else
|
||||
throw StereotypeDefinitionParserError(QString(QStringLiteral("Unexpected value \"%1\" for end.")).arg(endValue), token.sourcePos());
|
||||
break;
|
||||
}
|
||||
case KEYWORD_ELEMENTS:
|
||||
if (relation->element() != CustomRelation::Element::Relation)
|
||||
throwUnknownPropertyError(token);
|
||||
relationEnd.setEndItems(parseIdentifierListProperty());
|
||||
break;
|
||||
case KEYWORD_ROLE:
|
||||
if (relation->element() != CustomRelation::Element::Relation && relation->element() != CustomRelation::Element::Association)
|
||||
throwUnknownPropertyError(token);
|
||||
relationEnd.setRole(parseStringProperty());
|
||||
break;
|
||||
case KEYWORD_CARDINALITY:
|
||||
{
|
||||
if (relation->element() != CustomRelation::Element::Relation && relation->element() != CustomRelation::Element::Association)
|
||||
throwUnknownPropertyError(token);
|
||||
Value expression = parseProperty();
|
||||
if (expression.type() == Int || expression.type() == String)
|
||||
relationEnd.setCardinality(expression.value().toString());
|
||||
else
|
||||
throw StereotypeDefinitionParserError("Wrong type for cardinality.", token.sourcePos());
|
||||
break;
|
||||
}
|
||||
case KEYWORD_NAVIGABLE:
|
||||
if (relation->element() != CustomRelation::Element::Relation && relation->element() != CustomRelation::Element::Association)
|
||||
throwUnknownPropertyError(token);
|
||||
relationEnd.setNavigable(parseBoolProperty());
|
||||
break;
|
||||
case KEYWORD_RELATIONSHIP:
|
||||
{
|
||||
if (relation->element() != CustomRelation::Element::Association)
|
||||
throwUnknownPropertyError(token);
|
||||
const static QHash<QString, CustomRelation::Relationship> relationshipNames = QHash<QString, CustomRelation::Relationship>()
|
||||
<< qMakePair(QString(QStringLiteral("association")), CustomRelation::Relationship::Association)
|
||||
<< qMakePair(QString(QStringLiteral("aggregation")), CustomRelation::Relationship::Aggregation)
|
||||
<< qMakePair(QString(QStringLiteral("composition")), CustomRelation::Relationship::Composition);
|
||||
parseEnum<CustomRelation::Relationship>(
|
||||
parseIdentifierProperty(), relationshipNames, token.sourcePos(),
|
||||
[&](CustomRelation::Relationship relationship) { relationEnd.setRelationship(relationship); });
|
||||
break;
|
||||
}
|
||||
case KEYWORD_HEAD:
|
||||
{
|
||||
if (relation->element() != CustomRelation::Element::Relation)
|
||||
throwUnknownPropertyError(token);
|
||||
const static QHash<QString, CustomRelation::Head> headNames = QHash<QString, CustomRelation::Head>()
|
||||
<< qMakePair(QString(QStringLiteral("none")), CustomRelation::Head::None)
|
||||
<< qMakePair(QString(QStringLiteral("arrow")), CustomRelation::Head::Arrow)
|
||||
<< qMakePair(QString(QStringLiteral("triangle")), CustomRelation::Head::Triangle)
|
||||
<< qMakePair(QString(QStringLiteral("filledtriangle")), CustomRelation::Head::FilledTriangle)
|
||||
<< qMakePair(QString(QStringLiteral("diamond")), CustomRelation::Head::Diamond)
|
||||
<< qMakePair(QString(QStringLiteral("filleddiamond")), CustomRelation::Head::FilledDiamond);
|
||||
parseEnum<CustomRelation::Head>(
|
||||
parseIdentifierProperty(), headNames, token.sourcePos(),
|
||||
[&](CustomRelation::Head head) { relationEnd.setHead(head); });
|
||||
break;
|
||||
}
|
||||
case KEYWORD_SHAPE:
|
||||
if (relation->element() != CustomRelation::Element::Relation)
|
||||
throwUnknownPropertyError(token);
|
||||
relationEnd.setHead(CustomRelation::Head::Shape);
|
||||
relationEnd.setShape(parseIconShape());
|
||||
break;
|
||||
default:
|
||||
throwUnknownPropertyError(token);
|
||||
}
|
||||
if (!expectPropertySeparatorOrBlockEnd())
|
||||
break;
|
||||
}
|
||||
if (isEndB)
|
||||
relation->setEndB(relationEnd);
|
||||
else
|
||||
relation->setEndA(relationEnd);
|
||||
}
|
||||
|
||||
void StereotypeDefinitionParser::parseToolbar()
|
||||
{
|
||||
Toolbar toolbar;
|
||||
@@ -507,6 +819,10 @@ void StereotypeDefinitionParser::parseToolbar()
|
||||
case KEYWORD_PRIORITY:
|
||||
toolbar.setPriority(parseIntProperty());
|
||||
break;
|
||||
case KEYWORD_ELEMENT:
|
||||
toolbar.setElementTypes(parseIdentifierListProperty());
|
||||
toolbar.setToolbarType(toolbar.elementTypes().isEmpty() ? Toolbar::ObjectToolbar : Toolbar::RelationToolbar);
|
||||
break;
|
||||
case KEYWORD_TOOLS:
|
||||
parseToolbarTools(&toolbar);
|
||||
break;
|
||||
@@ -532,7 +848,7 @@ void StereotypeDefinitionParser::parseToolbarTools(Toolbar *toolbar)
|
||||
{
|
||||
Toolbar::Tool tool;
|
||||
tool.m_toolType = Toolbar::TooltypeTool;
|
||||
parseToolbarTool(&tool);
|
||||
parseToolbarTool(toolbar, &tool);
|
||||
tools.append(tool);
|
||||
break;
|
||||
}
|
||||
@@ -549,7 +865,7 @@ void StereotypeDefinitionParser::parseToolbarTools(Toolbar *toolbar)
|
||||
toolbar->setTools(tools);
|
||||
}
|
||||
|
||||
void StereotypeDefinitionParser::parseToolbarTool(Toolbar::Tool *tool)
|
||||
void StereotypeDefinitionParser::parseToolbarTool(const Toolbar *toolbar, Toolbar::Tool *tool)
|
||||
{
|
||||
expectBlockBegin();
|
||||
Token token;
|
||||
@@ -561,17 +877,29 @@ void StereotypeDefinitionParser::parseToolbarTool(Toolbar::Tool *tool)
|
||||
case KEYWORD_ELEMENT:
|
||||
{
|
||||
QString element = parseIdentifierProperty();
|
||||
static QSet<QString> elementNames = QSet<QString>()
|
||||
<< QStringLiteral("package")
|
||||
<< QStringLiteral("component")
|
||||
<< QStringLiteral("class")
|
||||
<< QStringLiteral("item")
|
||||
<< QStringLiteral("annotation")
|
||||
<< QStringLiteral("boundary");
|
||||
QString elementName = element.toLower();
|
||||
if (!elementNames.contains(elementName))
|
||||
throw StereotypeDefinitionParserError(QString(QStringLiteral("Unexpected value \"%1\" for element.")).arg(element), token.sourcePos());
|
||||
tool->m_elementType = elementName;
|
||||
if (toolbar->toolbarType() == Toolbar::ObjectToolbar) {
|
||||
static QSet<QString> elementNames = QSet<QString>()
|
||||
<< QStringLiteral("package")
|
||||
<< QStringLiteral("component")
|
||||
<< QStringLiteral("class")
|
||||
<< QStringLiteral("item")
|
||||
<< QStringLiteral("annotation")
|
||||
<< QStringLiteral("boundary");
|
||||
QString elementName = element.toLower();
|
||||
if (!elementNames.contains(elementName))
|
||||
throw StereotypeDefinitionParserError(QString(QStringLiteral("Unexpected value \"%1\" for element.")).arg(element), token.sourcePos());
|
||||
tool->m_elementType = elementName;
|
||||
} else {
|
||||
static QSet<QString> relationNames = QSet<QString>()
|
||||
<< "dependency"
|
||||
<< "inheritance"
|
||||
<< "association";
|
||||
QString relationName = element.toLower();
|
||||
if (relationNames.contains(relationName))
|
||||
tool->m_elementType = relationName;
|
||||
else
|
||||
tool->m_elementType = element;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case KEYWORD_STEREOTYPE:
|
||||
@@ -585,6 +913,28 @@ void StereotypeDefinitionParser::parseToolbarTool(Toolbar::Tool *tool)
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void StereotypeDefinitionParser::parseEnums(const QList<QString> &identifiers,
|
||||
const QHash<QString, T> &identifierNames,
|
||||
const SourcePos &sourcePos,
|
||||
std::function<void (T)> setter)
|
||||
{
|
||||
for (const QString &identifier : identifiers)
|
||||
parseEnum(identifier, identifierNames, sourcePos, setter);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void StereotypeDefinitionParser::parseEnum(const QString &identifier,
|
||||
const QHash<QString, T> &identifierNames,
|
||||
const SourcePos &sourcePos,
|
||||
std::function<void (T)> setter)
|
||||
{
|
||||
const QString name = identifier.toLower();
|
||||
if (!identifierNames.contains(name))
|
||||
throw StereotypeDefinitionParserError(QString(QStringLiteral("Unexpected value \"%1\".")).arg(identifier), sourcePos);
|
||||
setter(identifierNames.value(name));
|
||||
}
|
||||
|
||||
QString StereotypeDefinitionParser::parseStringProperty()
|
||||
{
|
||||
expectColon();
|
||||
@@ -640,6 +990,12 @@ QColor StereotypeDefinitionParser::parseColorProperty()
|
||||
return parseColorExpression();
|
||||
}
|
||||
|
||||
StereotypeDefinitionParser::Value StereotypeDefinitionParser::parseProperty()
|
||||
{
|
||||
expectColon();
|
||||
return parseExpression();
|
||||
}
|
||||
|
||||
QString StereotypeDefinitionParser::parseStringExpression()
|
||||
{
|
||||
Token token = d->m_scanner->read();
|
||||
@@ -723,6 +1079,50 @@ QColor StereotypeDefinitionParser::parseColorExpression()
|
||||
throw StereotypeDefinitionParserError(QStringLiteral("Expected color name."), token.sourcePos());
|
||||
}
|
||||
|
||||
StereotypeDefinitionParser::Value StereotypeDefinitionParser::parseExpression()
|
||||
{
|
||||
Token token = d->m_scanner->read();
|
||||
if (token.type() == Token::TokenString) {
|
||||
return Value(String, QVariant(token.text()));
|
||||
} else if (token.type() == Token::TokenOperator && token.subtype() == OPERATOR_MINUS) {
|
||||
Value v = parseExpression();
|
||||
if (v.type() == Int)
|
||||
return Value(Int, QVariant(-v.value().toInt()));
|
||||
else if (v.type() == Float)
|
||||
return Value(Float, QVariant(-v.value().toDouble()));
|
||||
else
|
||||
throw StereotypeDefinitionParserError(QStringLiteral("Illegal number expression."), token.sourcePos());
|
||||
} else if (token.type() == Token::TokenInteger) {
|
||||
bool ok = false;
|
||||
int value = token.text().toInt(&ok);
|
||||
QMT_CHECK(ok);
|
||||
return Value(Int, QVariant(value));
|
||||
} else if (token.type() == Token::TokenFloat) {
|
||||
bool ok = false;
|
||||
qreal value = token.text().toDouble(&ok);
|
||||
QMT_CHECK(ok);
|
||||
return Value(Float, QVariant(value));
|
||||
} else if (token.type() == Token::TokenColor) {
|
||||
QString value = token.text().toLower();
|
||||
QColor color;
|
||||
if (QColor::isValidColor(value)) {
|
||||
color.setNamedColor(value);
|
||||
return Value(Color, QVariant(color));
|
||||
} else {
|
||||
throw StereotypeDefinitionParserError(QStringLiteral("Invalid color."), token.sourcePos());
|
||||
}
|
||||
} else if (token.type() == Token::TokenIdentifier || token.type() == Token::TokenKeyword) {
|
||||
QString value = token.text().toLower();
|
||||
if (value == QStringLiteral("yes") || value == QStringLiteral("true"))
|
||||
return Value(Boolean, QVariant(true));
|
||||
else if (value == QStringLiteral("no") || value == QStringLiteral("false"))
|
||||
return Value(Boolean, QVariant(false));
|
||||
else
|
||||
return Value(Identifier, QVariant(token.text()));
|
||||
}
|
||||
throw StereotypeDefinitionParserError(QStringLiteral("Syntax error in expression."), token.sourcePos());
|
||||
}
|
||||
|
||||
void StereotypeDefinitionParser::expectBlockBegin()
|
||||
{
|
||||
skipEOLTokens();
|
||||
|
@@ -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> ¶meters);
|
||||
static QPair<int, IconCommandParameter> BOOLEAN(int keyword);
|
||||
IconShape parseIconShape();
|
||||
QHash<int, IconCommandParameter> parseIconShapeProperties(const QHash<int, IconCommandParameter> ¶meters);
|
||||
|
||||
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
|
||||
|
139
src/libs/modelinglib/qmt/stereotype/customrelation.cpp
Normal file
139
src/libs/modelinglib/qmt/stereotype/customrelation.cpp
Normal file
@@ -0,0 +1,139 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** 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
|
166
src/libs/modelinglib/qmt/stereotype/customrelation.h
Normal file
166
src/libs/modelinglib/qmt/stereotype/customrelation.h
Normal file
@@ -0,0 +1,166 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** 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 ¢er, const ShapeSizeF &radius)
|
||||
d->m_shapes.append(new EllipseShape(center, radius));
|
||||
}
|
||||
|
||||
void IconShape::addDiamond(const ShapePointF ¢er, const ShapeSizeF &size, bool filled)
|
||||
{
|
||||
d->m_shapes.append(new DiamondShape(center, size, filled));
|
||||
}
|
||||
|
||||
void IconShape::addTriangle(const ShapePointF ¢er, const ShapeSizeF &size, bool filled)
|
||||
{
|
||||
d->m_shapes.append(new TriangleShape(center, size, filled));
|
||||
}
|
||||
|
||||
void IconShape::addArc(const ShapePointF ¢er, 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 ¢er, const ShapeValueF &radius);
|
||||
void addEllipse(const ShapePointF ¢er, const ShapeSizeF &radius);
|
||||
void addDiamond(const ShapePointF ¢er, const ShapeSizeF &size, bool filled);
|
||||
void addTriangle(const ShapePointF ¢er, const ShapeSizeF &size, bool filled);
|
||||
void addArc(const ShapePointF ¢er, const ShapeSizeF &radius,
|
||||
qreal startAngle, qreal spanAngle);
|
||||
|
||||
|
@@ -35,7 +35,7 @@ class IShape
|
||||
public:
|
||||
virtual ~IShape() { }
|
||||
|
||||
virtual IShape *Clone() const = 0;
|
||||
virtual IShape *clone() const = 0;
|
||||
virtual void accept(ShapeVisitor *visitor) = 0;
|
||||
virtual void accept(ShapeConstVisitor *visitor) const = 0;
|
||||
};
|
||||
|
@@ -75,6 +75,37 @@ void ShapePaintVisitor::visitEllipse(const EllipseShape *shapeEllipse)
|
||||
radius.width(), radius.height());
|
||||
}
|
||||
|
||||
void ShapePaintVisitor::visitDiamond(const DiamondShape *shapeDiamond)
|
||||
{
|
||||
m_painter->save();
|
||||
m_painter->setRenderHint(QPainter::Antialiasing, true);
|
||||
QPainterPath path;
|
||||
QPointF center = shapeDiamond->center().mapScaledTo(m_scaledOrigin, m_originalSize, m_baseSize, m_size);
|
||||
QSizeF size = shapeDiamond->size().mapScaledTo(m_scaledOrigin, m_originalSize, m_baseSize, m_size);
|
||||
path.moveTo(center + QPointF(0.0, size.height() / 2.0));
|
||||
path.lineTo(center + QPointF(-size.width() / 2.0, 0.0));
|
||||
path.lineTo(center + QPointF(0.0, -size.height() / 2.0));
|
||||
path.lineTo(center + QPointF(size.width() / 2.0, 0.0));
|
||||
path.closeSubpath();
|
||||
m_painter->drawPath(path);
|
||||
m_painter->restore();
|
||||
}
|
||||
|
||||
void ShapePaintVisitor::visitTriangle(const TriangleShape *shapeTriangle)
|
||||
{
|
||||
m_painter->save();
|
||||
m_painter->setRenderHint(QPainter::Antialiasing, true);
|
||||
QPainterPath path;
|
||||
QPointF center = shapeTriangle->center().mapScaledTo(m_scaledOrigin, m_originalSize, m_baseSize, m_size);
|
||||
QSizeF size = shapeTriangle->size().mapScaledTo(m_scaledOrigin, m_originalSize, m_baseSize, m_size);
|
||||
path.moveTo(center + QPointF(size.width() / 2.0, size.height() / 2.0));
|
||||
path.lineTo(center + QPointF(-size.width() / 2.0, size.height() / 2.0));
|
||||
path.lineTo(center + QPointF(0.0, -size.height() / 2.0));
|
||||
path.closeSubpath();
|
||||
m_painter->drawPath(path);
|
||||
m_painter->restore();
|
||||
}
|
||||
|
||||
void ShapePaintVisitor::visitArc(const ArcShape *shapeArc)
|
||||
{
|
||||
QSizeF radius = shapeArc->radius().mapScaledTo(m_scaledOrigin, m_originalSize, m_baseSize, m_size);
|
||||
@@ -160,6 +191,31 @@ void ShapeSizeVisitor::visitEllipse(const EllipseShape *shapeEllipse)
|
||||
m_boundingRect |= QRectF(shapeEllipse->center().mapScaledTo(m_scaledOrigin, m_originalSize, m_baseSize, m_size) - QPointF(radius.width(), radius.height()), radius * 2.0);
|
||||
}
|
||||
|
||||
void ShapeSizeVisitor::visitDiamond(const DiamondShape *shapeDiamond)
|
||||
{
|
||||
QPainterPath path;
|
||||
QPointF center = shapeDiamond->center().mapScaledTo(m_scaledOrigin, m_originalSize, m_baseSize, m_size);
|
||||
QSizeF size = shapeDiamond->size().mapScaledTo(m_scaledOrigin, m_originalSize, m_baseSize, m_size);
|
||||
path.moveTo(center + QPointF(0.0, size.height() / 2.0));
|
||||
path.lineTo(center + QPointF(-size.width() / 2.0, 0.0));
|
||||
path.lineTo(center + QPointF(0.0, -size.height() / 2.0));
|
||||
path.lineTo(center + QPointF(size.width() / 2.0, 0.0));
|
||||
path.closeSubpath();
|
||||
m_boundingRect |= path.boundingRect();
|
||||
}
|
||||
|
||||
void ShapeSizeVisitor::visitTriangle(const TriangleShape *shapeTriangle)
|
||||
{
|
||||
QPainterPath path;
|
||||
QPointF center = shapeTriangle->center().mapScaledTo(m_scaledOrigin, m_originalSize, m_baseSize, m_size);
|
||||
QSizeF size = shapeTriangle->size().mapScaledTo(m_scaledOrigin, m_originalSize, m_baseSize, m_size);
|
||||
path.moveTo(center + QPointF(size.width() / 2.0, size.height() / 2.0));
|
||||
path.lineTo(center + QPointF(-size.width() / 2.0, size.height() / 2.0));
|
||||
path.lineTo(center + QPointF(0.0, -size.height() / 2.0));
|
||||
path.closeSubpath();
|
||||
m_boundingRect |= path.boundingRect();
|
||||
}
|
||||
|
||||
void ShapeSizeVisitor::visitArc(const ArcShape *shapeArc)
|
||||
{
|
||||
// TODO this is the max bound rect; not the minimal one
|
||||
|
@@ -45,6 +45,8 @@ public:
|
||||
void visitRoundedRect(const RoundedRectShape *shapeRoundedRect) override;
|
||||
void visitCircle(const CircleShape *shapeCircle) override;
|
||||
void visitEllipse(const EllipseShape *shapeEllipse) override;
|
||||
void visitDiamond(const DiamondShape *shapeDiamond) override;
|
||||
void visitTriangle(const TriangleShape *shapeTriangle) override;
|
||||
void visitArc(const ArcShape *shapeArc) override;
|
||||
void visitPath(const PathShape *shapePath) override;
|
||||
|
||||
@@ -69,6 +71,8 @@ public:
|
||||
void visitRoundedRect(const RoundedRectShape *shapeRoundedRect) override;
|
||||
void visitCircle(const CircleShape *shapeCircle) override;
|
||||
void visitEllipse(const EllipseShape *shapeEllipse) override;
|
||||
void visitDiamond(const DiamondShape *shapeDiamond) override;
|
||||
void visitTriangle(const TriangleShape *shapeTriangle) override;
|
||||
void visitArc(const ArcShape *shapeArc) override;
|
||||
void visitPath(const PathShape *shapePath) override;
|
||||
|
||||
|
@@ -27,7 +27,7 @@
|
||||
|
||||
namespace qmt {
|
||||
|
||||
IShape *LineShape::Clone() const
|
||||
IShape *LineShape::clone() const
|
||||
{
|
||||
return new LineShape(*this);
|
||||
}
|
||||
@@ -42,7 +42,7 @@ void LineShape::accept(ShapeConstVisitor *visitor) const
|
||||
visitor->visitLine(this);
|
||||
}
|
||||
|
||||
IShape *RectShape::Clone() const
|
||||
IShape *RectShape::clone() const
|
||||
{
|
||||
return new RectShape(*this);
|
||||
}
|
||||
@@ -57,7 +57,7 @@ void RectShape::accept(ShapeConstVisitor *visitor) const
|
||||
visitor->visitRect(this);
|
||||
}
|
||||
|
||||
IShape *RoundedRectShape::Clone() const
|
||||
IShape *RoundedRectShape::clone() const
|
||||
{
|
||||
return new RoundedRectShape(*this);
|
||||
}
|
||||
@@ -72,7 +72,7 @@ void RoundedRectShape::accept(ShapeConstVisitor *visitor) const
|
||||
visitor->visitRoundedRect(this);
|
||||
}
|
||||
|
||||
IShape *CircleShape::Clone() const
|
||||
IShape *CircleShape::clone() const
|
||||
{
|
||||
return new CircleShape(*this);
|
||||
}
|
||||
@@ -87,7 +87,7 @@ void CircleShape::accept(ShapeConstVisitor *visitor) const
|
||||
visitor->visitCircle(this);
|
||||
}
|
||||
|
||||
IShape *EllipseShape::Clone() const
|
||||
IShape *EllipseShape::clone() const
|
||||
{
|
||||
return new EllipseShape(*this);
|
||||
}
|
||||
@@ -102,7 +102,37 @@ void EllipseShape::accept(ShapeConstVisitor *visitor) const
|
||||
visitor->visitEllipse(this);
|
||||
}
|
||||
|
||||
IShape *ArcShape::Clone() const
|
||||
IShape *DiamondShape::clone() const
|
||||
{
|
||||
return new DiamondShape(*this);
|
||||
}
|
||||
|
||||
void DiamondShape::accept(ShapeVisitor *visitor)
|
||||
{
|
||||
visitor->visitDiamond(this);
|
||||
}
|
||||
|
||||
void DiamondShape::accept(ShapeConstVisitor *visitor) const
|
||||
{
|
||||
visitor->visitDiamond(this);
|
||||
}
|
||||
|
||||
IShape *TriangleShape::clone() const
|
||||
{
|
||||
return new TriangleShape(*this);
|
||||
}
|
||||
|
||||
void TriangleShape::accept(ShapeVisitor *visitor)
|
||||
{
|
||||
visitor->visitTriangle(this);
|
||||
}
|
||||
|
||||
void TriangleShape::accept(ShapeConstVisitor *visitor) const
|
||||
{
|
||||
visitor->visitTriangle(this);
|
||||
}
|
||||
|
||||
IShape *ArcShape::clone() const
|
||||
{
|
||||
return new ArcShape(*this);
|
||||
}
|
||||
@@ -125,7 +155,7 @@ PathShape::~PathShape()
|
||||
{
|
||||
}
|
||||
|
||||
IShape *PathShape::Clone() const
|
||||
IShape *PathShape::clone() const
|
||||
{
|
||||
return new PathShape(*this);
|
||||
}
|
||||
|
@@ -49,7 +49,7 @@ public:
|
||||
ShapePointF pos1() const { return m_pos1; }
|
||||
ShapePointF pos2() const { return m_pos2; }
|
||||
|
||||
IShape *Clone() const override;
|
||||
IShape *clone() const override;
|
||||
void accept(ShapeVisitor *visitor) override;
|
||||
void accept(ShapeConstVisitor *visitor) const override;
|
||||
|
||||
@@ -72,7 +72,7 @@ public:
|
||||
ShapePointF pos() const { return m_pos; }
|
||||
ShapeSizeF size() const { return m_size; }
|
||||
|
||||
IShape *Clone() const override;
|
||||
IShape *clone() const override;
|
||||
void accept(ShapeVisitor *visitor) override;
|
||||
void accept(ShapeConstVisitor *visitor) const override;
|
||||
|
||||
@@ -97,7 +97,7 @@ public:
|
||||
ShapeSizeF size() const { return m_size; }
|
||||
ShapeValueF radius() const { return m_radius; }
|
||||
|
||||
IShape *Clone() const override;
|
||||
IShape *clone() const override;
|
||||
void accept(ShapeVisitor *visitor) override;
|
||||
void accept(ShapeConstVisitor *visitor) const override;
|
||||
|
||||
@@ -121,7 +121,7 @@ public:
|
||||
ShapePointF center() const { return m_center; }
|
||||
ShapeValueF radius() const { return m_radius; }
|
||||
|
||||
IShape *Clone() const override;
|
||||
IShape *clone() const override;
|
||||
void accept(ShapeVisitor *visitor) override;
|
||||
void accept(ShapeConstVisitor *visitor) const override;
|
||||
|
||||
@@ -144,7 +144,7 @@ public:
|
||||
ShapePointF center() const { return m_center; }
|
||||
ShapeSizeF radius() const { return m_radius; }
|
||||
|
||||
IShape *Clone() const override;
|
||||
IShape *clone() const override;
|
||||
void accept(ShapeVisitor *visitor) override;
|
||||
void accept(ShapeConstVisitor *visitor) const override;
|
||||
|
||||
@@ -153,6 +153,58 @@ private:
|
||||
ShapeSizeF m_radius;
|
||||
};
|
||||
|
||||
class QMT_EXPORT DiamondShape : public IShape
|
||||
{
|
||||
public:
|
||||
DiamondShape() = default;
|
||||
|
||||
DiamondShape(const ShapePointF ¢er, const ShapeSizeF &size, bool filled)
|
||||
: m_center(center),
|
||||
m_size(size),
|
||||
m_filled(filled)
|
||||
{
|
||||
}
|
||||
|
||||
ShapePointF center() const { return m_center; }
|
||||
ShapeSizeF size() const { return m_size; }
|
||||
bool filled() const { return m_filled; }
|
||||
|
||||
IShape *clone() const override;
|
||||
void accept(ShapeVisitor *visitor) override;
|
||||
void accept(ShapeConstVisitor *visitor) const override;
|
||||
|
||||
private:
|
||||
ShapePointF m_center;
|
||||
ShapeSizeF m_size;
|
||||
bool m_filled = false;
|
||||
};
|
||||
|
||||
class QMT_EXPORT TriangleShape : public IShape
|
||||
{
|
||||
public:
|
||||
TriangleShape() = default;
|
||||
|
||||
TriangleShape(const ShapePointF ¢er, const ShapeSizeF &size, bool filled)
|
||||
: m_center(center),
|
||||
m_size(size),
|
||||
m_filled(filled)
|
||||
{
|
||||
}
|
||||
|
||||
ShapePointF center() const { return m_center; }
|
||||
ShapeSizeF size() const { return m_size; }
|
||||
bool filled() const { return m_filled; }
|
||||
|
||||
IShape *clone() const override;
|
||||
void accept(ShapeVisitor *visitor) override;
|
||||
void accept(ShapeConstVisitor *visitor) const override;
|
||||
|
||||
private:
|
||||
ShapePointF m_center;
|
||||
ShapeSizeF m_size;
|
||||
bool m_filled = false;
|
||||
};
|
||||
|
||||
class QMT_EXPORT ArcShape : public IShape
|
||||
{
|
||||
public:
|
||||
@@ -171,7 +223,7 @@ public:
|
||||
qreal startAngle() const { return m_startAngle; }
|
||||
qreal spanAngle() const { return m_spanAngle; }
|
||||
|
||||
IShape *Clone() const override;
|
||||
IShape *clone() const override;
|
||||
void accept(ShapeVisitor *visitor) override;
|
||||
void accept(ShapeConstVisitor *visitor) const override;
|
||||
|
||||
@@ -214,7 +266,7 @@ public:
|
||||
|
||||
QList<Element> elements() const { return m_elements; }
|
||||
|
||||
IShape *Clone() const override;
|
||||
IShape *clone() const override;
|
||||
void accept(ShapeVisitor *visitor) override;
|
||||
void accept(ShapeConstVisitor *visitor) const override;
|
||||
|
||||
|
@@ -32,6 +32,8 @@ class RectShape;
|
||||
class RoundedRectShape;
|
||||
class CircleShape;
|
||||
class EllipseShape;
|
||||
class DiamondShape;
|
||||
class TriangleShape;
|
||||
class ArcShape;
|
||||
class PathShape;
|
||||
|
||||
@@ -45,6 +47,8 @@ public:
|
||||
virtual void visitRoundedRect(RoundedRectShape *shapeRoundedRect) = 0;
|
||||
virtual void visitCircle(CircleShape *shapeCircle) = 0;
|
||||
virtual void visitEllipse(EllipseShape *shapeEllipse) = 0;
|
||||
virtual void visitDiamond(DiamondShape *shapeDiamond) = 0;
|
||||
virtual void visitTriangle(TriangleShape *shapeDiamond) = 0;
|
||||
virtual void visitArc(ArcShape *shapeArc) = 0;
|
||||
virtual void visitPath(PathShape *shapePath) = 0;
|
||||
};
|
||||
@@ -59,6 +63,8 @@ public:
|
||||
virtual void visitRoundedRect(const RoundedRectShape *shapeRoundedRect) = 0;
|
||||
virtual void visitCircle(const CircleShape *shapeCircle) = 0;
|
||||
virtual void visitEllipse(const EllipseShape *shapeEllipse) = 0;
|
||||
virtual void visitDiamond(const DiamondShape *shapeDiamond) = 0;
|
||||
virtual void visitTriangle(const TriangleShape *shapeDiamond) = 0;
|
||||
virtual void visitArc(const ArcShape *shapeArc) = 0;
|
||||
virtual void visitPath(const PathShape *shapePath) = 0;
|
||||
};
|
||||
|
@@ -25,12 +25,14 @@
|
||||
|
||||
#include "stereotypecontroller.h"
|
||||
|
||||
#include "customrelation.h"
|
||||
#include "stereotypeicon.h"
|
||||
#include "shapepaintvisitor.h"
|
||||
#include "toolbar.h"
|
||||
|
||||
#include "qmt/infrastructure/qmtassert.h"
|
||||
#include "qmt/style/style.h"
|
||||
#include "utils/algorithm.h"
|
||||
|
||||
#include <QHash>
|
||||
#include <QPainter>
|
||||
@@ -46,7 +48,9 @@ class StereotypeController::StereotypeControllerPrivate
|
||||
public:
|
||||
QHash<QPair<StereotypeIcon::Element, QString>, QString> m_stereotypeToIconIdMap;
|
||||
QHash<QString, StereotypeIcon> m_iconIdToStereotypeIconsMap;
|
||||
QHash<QString, CustomRelation> m_relationIdToCustomRelationMap;
|
||||
QList<Toolbar> m_toolbars;
|
||||
QList<Toolbar> m_elementToolbars;
|
||||
};
|
||||
|
||||
StereotypeController::StereotypeController(QObject *parent) :
|
||||
@@ -70,6 +74,13 @@ QList<Toolbar> StereotypeController::toolbars() const
|
||||
return d->m_toolbars;
|
||||
}
|
||||
|
||||
QList<Toolbar> StereotypeController::findToolbars(const QString &elementType) const
|
||||
{
|
||||
return Utils::filtered(d->m_elementToolbars, [&elementType](const Toolbar &tb) {
|
||||
return tb.elementTypes().contains(elementType);
|
||||
});
|
||||
}
|
||||
|
||||
QList<QString> StereotypeController::knownStereotypes(StereotypeIcon::Element stereotypeElement) const
|
||||
{
|
||||
QSet<QString> stereotypes;
|
||||
@@ -105,12 +116,17 @@ QList<QString> StereotypeController::filterStereotypesByIconId(const QString &st
|
||||
return filteredStereotypes;
|
||||
}
|
||||
|
||||
StereotypeIcon StereotypeController::findStereotypeIcon(const QString &stereotypeIconId)
|
||||
StereotypeIcon StereotypeController::findStereotypeIcon(const QString &stereotypeIconId) const
|
||||
{
|
||||
QMT_CHECK(d->m_iconIdToStereotypeIconsMap.contains(stereotypeIconId));
|
||||
return d->m_iconIdToStereotypeIconsMap.value(stereotypeIconId);
|
||||
}
|
||||
|
||||
CustomRelation StereotypeController::findCustomRelation(const QString &customRelationId) const
|
||||
{
|
||||
return d->m_relationIdToCustomRelationMap.value(customRelationId);
|
||||
}
|
||||
|
||||
QIcon StereotypeController::createIcon(StereotypeIcon::Element element, const QList<QString> &stereotypes,
|
||||
const QString &defaultIconPath, const Style *style, const QSize &size,
|
||||
const QMarginsF &margins)
|
||||
@@ -180,9 +196,17 @@ void StereotypeController::addStereotypeIcon(const StereotypeIcon &stereotypeIco
|
||||
d->m_iconIdToStereotypeIconsMap.insert(stereotypeIcon.id(), stereotypeIcon);
|
||||
}
|
||||
|
||||
void StereotypeController::addCustomRelation(const CustomRelation &customRelation)
|
||||
{
|
||||
d->m_relationIdToCustomRelationMap.insert(customRelation.id(), customRelation);
|
||||
}
|
||||
|
||||
void StereotypeController::addToolbar(const Toolbar &toolbar)
|
||||
{
|
||||
d->m_toolbars.append(toolbar);
|
||||
if (toolbar.elementTypes().isEmpty())
|
||||
d->m_toolbars.append(toolbar);
|
||||
else
|
||||
d->m_elementToolbars.append(toolbar);
|
||||
}
|
||||
|
||||
} // namespace qmt
|
||||
|
@@ -33,6 +33,7 @@
|
||||
|
||||
namespace qmt {
|
||||
|
||||
class CustomRelation;
|
||||
class Toolbar;
|
||||
class Style;
|
||||
|
||||
@@ -47,18 +48,21 @@ public:
|
||||
|
||||
QList<StereotypeIcon> stereotypeIcons() const;
|
||||
QList<Toolbar> toolbars() const;
|
||||
QList<Toolbar> findToolbars(const QString &elementType) const;
|
||||
QList<QString> knownStereotypes(StereotypeIcon::Element stereotypeElement) const;
|
||||
|
||||
QString findStereotypeIconId(StereotypeIcon::Element element,
|
||||
const QList<QString> &stereotypes) const;
|
||||
QList<QString> filterStereotypesByIconId(const QString &stereotypeIconId,
|
||||
const QList<QString> &stereotypes) const;
|
||||
StereotypeIcon findStereotypeIcon(const QString &stereotypeIconId);
|
||||
StereotypeIcon findStereotypeIcon(const QString &stereotypeIconId) const;
|
||||
CustomRelation findCustomRelation(const QString &customRelationId) const;
|
||||
QIcon createIcon(StereotypeIcon::Element element, const QList<QString> &stereotypes,
|
||||
const QString &defaultIconPath, const Style *style,
|
||||
const QSize &size, const QMarginsF &margins);
|
||||
|
||||
void addStereotypeIcon(const StereotypeIcon &stereotypeIcon);
|
||||
void addCustomRelation(const CustomRelation &customRelation);
|
||||
void addToolbar(const Toolbar &toolbar);
|
||||
|
||||
private:
|
||||
|
@@ -28,7 +28,6 @@
|
||||
namespace qmt {
|
||||
|
||||
Toolbar::Toolbar()
|
||||
: m_priority(-1)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -36,6 +35,11 @@ Toolbar::~Toolbar()
|
||||
{
|
||||
}
|
||||
|
||||
void Toolbar::setToolbarType(Toolbar::ToolbarType toolbarType)
|
||||
{
|
||||
m_toolbarType = toolbarType;
|
||||
}
|
||||
|
||||
void Toolbar::setId(const QString &id)
|
||||
{
|
||||
m_id = id;
|
||||
@@ -46,6 +50,11 @@ void Toolbar::setPriority(int priority)
|
||||
m_priority = priority;
|
||||
}
|
||||
|
||||
void Toolbar::setElementTypes(const QStringList &elementTypes)
|
||||
{
|
||||
m_elementTypes = elementTypes;
|
||||
}
|
||||
|
||||
void Toolbar::setTools(const QList<Toolbar::Tool> &tools)
|
||||
{
|
||||
m_tools = tools;
|
||||
|
@@ -35,6 +35,11 @@ namespace qmt {
|
||||
class QMT_EXPORT Toolbar
|
||||
{
|
||||
public:
|
||||
enum ToolbarType {
|
||||
ObjectToolbar,
|
||||
RelationToolbar
|
||||
};
|
||||
|
||||
enum ToolType {
|
||||
TooltypeTool,
|
||||
TooltypeSeparator
|
||||
@@ -65,16 +70,22 @@ public:
|
||||
Toolbar();
|
||||
~Toolbar();
|
||||
|
||||
ToolbarType toolbarType() const { return m_toolbarType; }
|
||||
void setToolbarType(ToolbarType toolbarType);
|
||||
QString id() const { return m_id; }
|
||||
void setId(const QString &id);
|
||||
int priority() const { return m_priority; }
|
||||
void setPriority(int priority);
|
||||
QStringList elementTypes() const { return m_elementTypes; }
|
||||
void setElementTypes(const QStringList &elementTypes);
|
||||
QList<Tool> tools() const { return m_tools; }
|
||||
void setTools(const QList<Tool> &tools);
|
||||
|
||||
private:
|
||||
ToolbarType m_toolbarType = ObjectToolbar;
|
||||
QString m_id;
|
||||
int m_priority;
|
||||
int m_priority = -1;
|
||||
QStringList m_elementTypes;
|
||||
QList<Tool> m_tools;
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user