From 8100812531417afb3d62dcc2905e4aebf29ff811 Mon Sep 17 00:00:00 2001 From: Jochen Becher Date: Sun, 12 Jun 2016 20:07:15 +0200 Subject: [PATCH] ModelEditor: Support custom relations in configuration files Change-Id: I87338f290bd1ea729682236df8b017516a18e7bb Reviewed-by: Tobias Hunger --- share/qtcreator/modeleditor/standard.def | 154 +++++ src/libs/modelinglib/modelinglib.qbs | 2 + .../qmt/config/configcontroller.cpp | 7 + .../modelinglib/qmt/config/configcontroller.h | 2 + .../qmt/config/stereotypedefinitionparser.cpp | 528 +++++++++++++++--- .../qmt/config/stereotypedefinitionparser.h | 34 +- src/libs/modelinglib/qmt/qmt.pri | 6 +- .../qmt/stereotype/customrelation.cpp | 139 +++++ .../qmt/stereotype/customrelation.h | 166 ++++++ .../modelinglib/qmt/stereotype/iconshape.cpp | 18 +- .../modelinglib/qmt/stereotype/iconshape.h | 4 +- src/libs/modelinglib/qmt/stereotype/shape.h | 2 +- .../qmt/stereotype/shapepaintvisitor.cpp | 56 ++ .../qmt/stereotype/shapepaintvisitor.h | 4 + .../modelinglib/qmt/stereotype/shapes.cpp | 44 +- src/libs/modelinglib/qmt/stereotype/shapes.h | 66 ++- .../modelinglib/qmt/stereotype/shapevisitor.h | 6 + .../qmt/stereotype/stereotypecontroller.cpp | 28 +- .../qmt/stereotype/stereotypecontroller.h | 6 +- .../modelinglib/qmt/stereotype/toolbar.cpp | 11 +- src/libs/modelinglib/qmt/stereotype/toolbar.h | 13 +- 21 files changed, 1201 insertions(+), 95 deletions(-) create mode 100644 src/libs/modelinglib/qmt/stereotype/customrelation.cpp create mode 100644 src/libs/modelinglib/qmt/stereotype/customrelation.h diff --git a/share/qtcreator/modeleditor/standard.def b/share/qtcreator/modeleditor/standard.def index 010ce382f5e..aa4afd04e28 100644 --- a/share/qtcreator/modeleditor/standard.def +++ b/share/qtcreator/modeleditor/standard.def @@ -2,6 +2,9 @@ // // Language syntax and commands: // +// +// An Icon defines an icon of an element selected by stereotype. +// // Icon { // id: // title: @@ -29,6 +32,8 @@ // RoundedRect { x: ; y: ; width: ; height: ; radius: } // Circle { x: ; y: ; radius: } // Ellipse { x: ; y: ; radiusX: ; radiusY: } +// Diamond { x: ; y: ; width: ; height: } +// Triangle { x: ; y: ; width: ; height: } // Arc { x: ; y: ; radiusX: ; radiusY: ; start: ; span: } // MoveTo { x: ; y: } // LineTo { x: ; y: } @@ -38,6 +43,79 @@ // } // } // +// +// A Relation defines a new relation between to items: +// +// Relation { +// id: +// title: +// elements: +// stereotype: +// name: +// direction: +// pattern: +// color: +// End { +// end: +// elements: +// role: +// cardinality: +// navigable: +// Shape { +// } +// } +// } +// +// +// A Dependency defines a number of settings of a dependency specialization: +// +// Dependency { +// id: +// title: +// elements: +// stereotype: +// name: +// direction: +// } +// +// +// An Inheritance defines settings of an inheritance specialization: +// +// Inheritance { +// id: +// title: +// elements: +// stereotype: +// name: +// } +// +// +// An Association defines settings of an association specialization: +// +// Association { +// id: +// title: +// elements: +// stereotype: +// name: +// End { +// end: +// role: +// cardinality: +// navigable: +// relationship: +// } +// } +// +// +// A toolbar of icons. If no toolbar is defined the standard toolbar is shown. +// // Toolbar { // id: // title: @@ -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 ** // ************** diff --git a/src/libs/modelinglib/modelinglib.qbs b/src/libs/modelinglib/modelinglib.qbs index ab79fcc1123..e4b26be8061 100644 --- a/src/libs/modelinglib/modelinglib.qbs +++ b/src/libs/modelinglib/modelinglib.qbs @@ -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", diff --git a/src/libs/modelinglib/qmt/config/configcontroller.cpp b/src/libs/modelinglib/qmt/config/configcontroller.cpp index cb31845e2ce..70cd4805746 100644 --- a/src/libs/modelinglib/qmt/config/configcontroller.cpp +++ b/src/libs/modelinglib/qmt/config/configcontroller.cpp @@ -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); diff --git a/src/libs/modelinglib/qmt/config/configcontroller.h b/src/libs/modelinglib/qmt/config/configcontroller.h index 34135bb4af3..3b715ec64cd 100644 --- a/src/libs/modelinglib/qmt/config/configcontroller.h +++ b/src/libs/modelinglib/qmt/config/configcontroller.h @@ -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; diff --git a/src/libs/modelinglib/qmt/config/stereotypedefinitionparser.cpp b/src/libs/modelinglib/qmt/config/stereotypedefinitionparser.cpp index 130da5800bd..dedf029d950 100644 --- a/src/libs/modelinglib/qmt/config/stereotypedefinitionparser.cpp +++ b/src/libs/modelinglib/qmt/config/stereotypedefinitionparser.cpp @@ -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 @@ -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 >() @@ -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 identifiers = parseIdentifierListProperty(); - foreach (const QString &identifier, identifiers) { - static QHash elementNames = QHash() - << 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 elementNames = QHash() + << 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( + 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 lockNames = QHash() + const static QHash lockNames = QHash() << 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( + parseIdentifierProperty(), lockNames, token.sourcePos(), + [&](StereotypeIcon::SizeLock lock) { stereotypeIcon.setSizeLock(lock); }); break; } case KEYWORD_DISPLAY: { - QString displayValue = parseIdentifierProperty(); - QString displayName = displayValue.toLower(); - static QHash displayNames = QHash() + const static QHash displayNames = QHash() << 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( + parseIdentifierProperty(), displayNames, token.sourcePos(), + [&](StereotypeIcon::Display display) { stereotypeIcon.setDisplay(display); }); break; } case KEYWORD_TEXTALIGN: { - QString alignValue = parseIdentifierProperty(); - QString alignName = alignValue.toLower(); - static QHash alignNames = QHash() + const static QHash alignNames = QHash() << 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( + 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 StereotypeDefinitio return qMakePair(keyword, IconCommandParameter(keyword, ShapeValueF::UnitAbsolute)); } -void StereotypeDefinitionParser::parseIconShape(StereotypeIcon *stereotypeIcon) +QPair StereotypeDefinitionParser::BOOLEAN(int keyword) +{ + return qMakePair(keyword, IconCommandParameter(keyword, IconCommandParameter::Boolean)); +} + +IconShape StereotypeDefinitionParser::parseIconShape() { IconShape iconShape; - QHash values; + QHash values; typedef QHash 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 StereotypeDefinitionParser::parseIconShapeProperties(const QHash ¶meters) +QHash StereotypeDefinitionParser::parseIconShapeProperties(const QHash ¶meters) { expectBlockBegin(); - QHash values; + QHash 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 StereotypeDefinitionParser::parseIconShapeProperties(con return values; } +void StereotypeDefinitionParser::parseRelation(CustomRelation::Element element) +{ + CustomRelation relation; + relation.setElement(element); + QSet 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 directionNames = QHash() + << 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( + parseIdentifierProperty(), directionNames, token.sourcePos(), + [&](CustomRelation::Direction direction) { relation.setDirection(direction); }); + break; + } + case KEYWORD_PATTERN: + { + const static QHash patternNames = QHash() + << 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( + 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()); + } 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 relationshipNames = QHash() + << qMakePair(QString(QStringLiteral("association")), CustomRelation::Relationship::Association) + << qMakePair(QString(QStringLiteral("aggregation")), CustomRelation::Relationship::Aggregation) + << qMakePair(QString(QStringLiteral("composition")), CustomRelation::Relationship::Composition); + parseEnum( + 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 headNames = QHash() + << 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( + 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 elementNames = QSet() - << 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 elementNames = QSet() + << 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 relationNames = QSet() + << "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 +void StereotypeDefinitionParser::parseEnums(const QList &identifiers, + const QHash &identifierNames, + const SourcePos &sourcePos, + std::function setter) +{ + for (const QString &identifier : identifiers) + parseEnum(identifier, identifierNames, sourcePos, setter); +} + +template +void StereotypeDefinitionParser::parseEnum(const QString &identifier, + const QHash &identifierNames, + const SourcePos &sourcePos, + std::function 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(); diff --git a/src/libs/modelinglib/qmt/config/stereotypedefinitionparser.h b/src/libs/modelinglib/qmt/config/stereotypedefinitionparser.h index 390ab4424e9..e132f2747d5 100644 --- a/src/libs/modelinglib/qmt/config/stereotypedefinitionparser.h +++ b/src/libs/modelinglib/qmt/config/stereotypedefinitionparser.h @@ -27,12 +27,14 @@ #include #include "qmt/infrastructure/exceptions.h" +#include "qmt/stereotype/customrelation.h" #include "qmt/stereotype/toolbar.h" #include "sourcepos.h" #include #include +#include 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 SCALED(int keyword); static QPair FIX(int keyword); static QPair ABSOLUTE(int keyword); - void parseIconShape(StereotypeIcon *stereotypeIcon); - QHash parseIconShapeProperties(const QHash ¶meters); + static QPair BOOLEAN(int keyword); + IconShape parseIconShape(); + QHash parseIconShapeProperties(const QHash ¶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 + void parseEnums(const QList &identifiers, const QHash &identifierNames, + const SourcePos &sourcePos, std::function setter); + + template + void parseEnum(const QString &identifier, const QHash &identifierNames, + const SourcePos &sourcePos, std::function setter); QString parseStringProperty(); int parseIntProperty(); @@ -92,6 +118,7 @@ private: QList 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); diff --git a/src/libs/modelinglib/qmt/qmt.pri b/src/libs/modelinglib/qmt/qmt.pri index d6f5e76a52c..ec98011fe2a 100644 --- a/src/libs/modelinglib/qmt/qmt.pri +++ b/src/libs/modelinglib/qmt/qmt.pri @@ -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 diff --git a/src/libs/modelinglib/qmt/stereotype/customrelation.cpp b/src/libs/modelinglib/qmt/stereotype/customrelation.cpp new file mode 100644 index 00000000000..b51abbe3672 --- /dev/null +++ b/src/libs/modelinglib/qmt/stereotype/customrelation.cpp @@ -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 &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 &endItems) +{ + m_endItems = endItems; +} + +void CustomRelation::setStereotypes(const QSet &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 diff --git a/src/libs/modelinglib/qmt/stereotype/customrelation.h b/src/libs/modelinglib/qmt/stereotype/customrelation.h new file mode 100644 index 00000000000..0b72be20fdf --- /dev/null +++ b/src/libs/modelinglib/qmt/stereotype/customrelation.h @@ -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 +#include +#include +#include + +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 endItems() const { return m_endItems; } + void setEndItems(const QList &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 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 endItems() const { return m_endItems; } + void setEndItems(const QList &endItems); + QSet stereotypes() const { return m_stereotypes; } + void setStereotypes(const QSet &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 m_endItems; + QSet 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(relationship)); +} + +inline uint qHash(CustomRelation::ShaftPattern pattern) { + return ::qHash(static_cast(pattern)); +} + +inline uint qHash(CustomRelation::Head head) { + return ::qHash(static_cast(head)); +} + +} // namespace qmt diff --git a/src/libs/modelinglib/qmt/stereotype/iconshape.cpp b/src/libs/modelinglib/qmt/stereotype/iconshape.cpp index d9a4be058be..2bf1d5fdbdf 100644 --- a/src/libs/modelinglib/qmt/stereotype/iconshape.cpp +++ b/src/libs/modelinglib/qmt/stereotype/iconshape.cpp @@ -34,11 +34,11 @@ #include template -QList CloneAll(const QList &rhs) +QList cloneAll(const QList &rhs) { QList 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)); diff --git a/src/libs/modelinglib/qmt/stereotype/iconshape.h b/src/libs/modelinglib/qmt/stereotype/iconshape.h index 59148ee03ec..215dc8adecf 100644 --- a/src/libs/modelinglib/qmt/stereotype/iconshape.h +++ b/src/libs/modelinglib/qmt/stereotype/iconshape.h @@ -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); diff --git a/src/libs/modelinglib/qmt/stereotype/shape.h b/src/libs/modelinglib/qmt/stereotype/shape.h index 467266b9614..9bf56bd5b28 100644 --- a/src/libs/modelinglib/qmt/stereotype/shape.h +++ b/src/libs/modelinglib/qmt/stereotype/shape.h @@ -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; }; diff --git a/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.cpp b/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.cpp index 552852c1e09..880835287ad 100644 --- a/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.cpp +++ b/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.cpp @@ -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 diff --git a/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.h b/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.h index 67a90ee6ac5..92e340e3e94 100644 --- a/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.h +++ b/src/libs/modelinglib/qmt/stereotype/shapepaintvisitor.h @@ -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; diff --git a/src/libs/modelinglib/qmt/stereotype/shapes.cpp b/src/libs/modelinglib/qmt/stereotype/shapes.cpp index 05f6e61e5a5..0ee04f9bb08 100644 --- a/src/libs/modelinglib/qmt/stereotype/shapes.cpp +++ b/src/libs/modelinglib/qmt/stereotype/shapes.cpp @@ -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); } diff --git a/src/libs/modelinglib/qmt/stereotype/shapes.h b/src/libs/modelinglib/qmt/stereotype/shapes.h index 88f4c6e392f..a9025a91fa8 100644 --- a/src/libs/modelinglib/qmt/stereotype/shapes.h +++ b/src/libs/modelinglib/qmt/stereotype/shapes.h @@ -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 elements() const { return m_elements; } - IShape *Clone() const override; + IShape *clone() const override; void accept(ShapeVisitor *visitor) override; void accept(ShapeConstVisitor *visitor) const override; diff --git a/src/libs/modelinglib/qmt/stereotype/shapevisitor.h b/src/libs/modelinglib/qmt/stereotype/shapevisitor.h index 6adbba12ba5..83f12ec5b83 100644 --- a/src/libs/modelinglib/qmt/stereotype/shapevisitor.h +++ b/src/libs/modelinglib/qmt/stereotype/shapevisitor.h @@ -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; }; diff --git a/src/libs/modelinglib/qmt/stereotype/stereotypecontroller.cpp b/src/libs/modelinglib/qmt/stereotype/stereotypecontroller.cpp index 8c7bbdbc26e..5e5e4b73fde 100644 --- a/src/libs/modelinglib/qmt/stereotype/stereotypecontroller.cpp +++ b/src/libs/modelinglib/qmt/stereotype/stereotypecontroller.cpp @@ -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 #include @@ -46,7 +48,9 @@ class StereotypeController::StereotypeControllerPrivate public: QHash, QString> m_stereotypeToIconIdMap; QHash m_iconIdToStereotypeIconsMap; + QHash m_relationIdToCustomRelationMap; QList m_toolbars; + QList m_elementToolbars; }; StereotypeController::StereotypeController(QObject *parent) : @@ -70,6 +74,13 @@ QList StereotypeController::toolbars() const return d->m_toolbars; } +QList StereotypeController::findToolbars(const QString &elementType) const +{ + return Utils::filtered(d->m_elementToolbars, [&elementType](const Toolbar &tb) { + return tb.elementTypes().contains(elementType); + }); +} + QList StereotypeController::knownStereotypes(StereotypeIcon::Element stereotypeElement) const { QSet stereotypes; @@ -105,12 +116,17 @@ QList 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 &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 diff --git a/src/libs/modelinglib/qmt/stereotype/stereotypecontroller.h b/src/libs/modelinglib/qmt/stereotype/stereotypecontroller.h index 990c2ae8b46..37d196d1010 100644 --- a/src/libs/modelinglib/qmt/stereotype/stereotypecontroller.h +++ b/src/libs/modelinglib/qmt/stereotype/stereotypecontroller.h @@ -33,6 +33,7 @@ namespace qmt { +class CustomRelation; class Toolbar; class Style; @@ -47,18 +48,21 @@ public: QList stereotypeIcons() const; QList toolbars() const; + QList findToolbars(const QString &elementType) const; QList knownStereotypes(StereotypeIcon::Element stereotypeElement) const; QString findStereotypeIconId(StereotypeIcon::Element element, const QList &stereotypes) const; QList filterStereotypesByIconId(const QString &stereotypeIconId, const QList &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 &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: diff --git a/src/libs/modelinglib/qmt/stereotype/toolbar.cpp b/src/libs/modelinglib/qmt/stereotype/toolbar.cpp index 9106d743603..95ae78a5948 100644 --- a/src/libs/modelinglib/qmt/stereotype/toolbar.cpp +++ b/src/libs/modelinglib/qmt/stereotype/toolbar.cpp @@ -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 &tools) { m_tools = tools; diff --git a/src/libs/modelinglib/qmt/stereotype/toolbar.h b/src/libs/modelinglib/qmt/stereotype/toolbar.h index b7422f408d7..ab3974ec2ec 100644 --- a/src/libs/modelinglib/qmt/stereotype/toolbar.h +++ b/src/libs/modelinglib/qmt/stereotype/toolbar.h @@ -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 tools() const { return m_tools; } void setTools(const QList &tools); private: + ToolbarType m_toolbarType = ObjectToolbar; QString m_id; - int m_priority; + int m_priority = -1; + QStringList m_elementTypes; QList m_tools; };