diff options
Diffstat (limited to 'src/libs/modelinglib')
29 files changed, 552 insertions, 343 deletions
diff --git a/src/libs/modelinglib/qmt/diagram/dobject.cpp b/src/libs/modelinglib/qmt/diagram/dobject.cpp index 4e0e5cb6423..68e954b8572 100644 --- a/src/libs/modelinglib/qmt/diagram/dobject.cpp +++ b/src/libs/modelinglib/qmt/diagram/dobject.cpp @@ -25,7 +25,10 @@ DObject::DObject(const DObject &rhs) m_visualSecondaryRole(rhs.m_visualSecondaryRole), m_stereotypeDisplay(rhs.m_stereotypeDisplay), m_isAutoSized(rhs.m_isAutoSized), - m_isVisualEmphasized(rhs.m_isVisualEmphasized) + m_isVisualEmphasized(rhs.m_isVisualEmphasized), + m_hasLinkedFile(rhs.m_hasLinkedFile), + m_imagePath(rhs.m_imagePath), + m_image(rhs.m_image) { } @@ -49,6 +52,9 @@ DObject &DObject::operator =(const DObject &rhs) m_stereotypeDisplay = rhs.m_stereotypeDisplay; m_isAutoSized = rhs.m_isAutoSized; m_isVisualEmphasized = rhs.m_isVisualEmphasized; + m_hasLinkedFile = rhs.m_hasLinkedFile; + m_imagePath = rhs.m_imagePath; + m_image = rhs.m_image; } return *this; } @@ -113,6 +119,26 @@ void DObject::setVisualEmphasized(bool visualEmphasized) m_isVisualEmphasized = visualEmphasized; } +void DObject::setLinkedFile(bool linkedFile) +{ + m_hasLinkedFile = linkedFile; +} + +bool DObject::hasImage() const +{ + return !m_image.isNull(); +} + +void DObject::setImagePath(const QString &path) +{ + m_imagePath = path; +} + +void DObject::setImage(const QImage &image) +{ + m_image = image; +} + void DObject::accept(DVisitor *visitor) { visitor->visitDObject(this); diff --git a/src/libs/modelinglib/qmt/diagram/dobject.h b/src/libs/modelinglib/qmt/diagram/dobject.h index c8cf2b0e4dd..bf43edea12e 100644 --- a/src/libs/modelinglib/qmt/diagram/dobject.h +++ b/src/libs/modelinglib/qmt/diagram/dobject.h @@ -7,6 +7,7 @@ #include "qmt/infrastructure/uid.h" +#include <QImage> #include <QList> #include <QPointF> #include <QRectF> @@ -78,6 +79,13 @@ public: void setAutoSized(bool autoSized); bool isVisualEmphasized() const { return m_isVisualEmphasized; } void setVisualEmphasized(bool visualEmphasized); + bool hasLinkedFile() const { return m_hasLinkedFile; } + void setLinkedFile(bool linkedFile); + QString imagePath() const { return m_imagePath; } + void setImagePath(const QString &path); + bool hasImage() const; + QImage image() const { return m_image; } + void setImage(const QImage &image); void accept(DVisitor *visitor) override; void accept(DConstVisitor *visitor) const override; @@ -95,6 +103,9 @@ private: StereotypeDisplay m_stereotypeDisplay = StereotypeSmart; bool m_isAutoSized = true; bool m_isVisualEmphasized = false; + bool m_hasLinkedFile = false; + QString m_imagePath; + QImage m_image; }; } // namespace qmt diff --git a/src/libs/modelinglib/qmt/diagram_controller/dflatassignmentvisitor.cpp b/src/libs/modelinglib/qmt/diagram_controller/dflatassignmentvisitor.cpp index 205c8fbb4db..5e4c0725885 100644 --- a/src/libs/modelinglib/qmt/diagram_controller/dflatassignmentvisitor.cpp +++ b/src/libs/modelinglib/qmt/diagram_controller/dflatassignmentvisitor.cpp @@ -49,7 +49,10 @@ void DFlatAssignmentVisitor::visitDObject(const DObject *object) target->setVisualPrimaryRole(object->visualPrimaryRole()); target->setVisualSecondaryRole(object->visualSecondaryRole()); target->setVisualEmphasized(object->isVisualEmphasized()); + target->setLinkedFile(object->hasLinkedFile()); target->setStereotypeDisplay(object->stereotypeDisplay()); + target->setImagePath(object->imagePath()); + target->setImage(object->image()); } void DFlatAssignmentVisitor::visitDPackage(const DPackage *package) diff --git a/src/libs/modelinglib/qmt/diagram_controller/dupdatevisitor.cpp b/src/libs/modelinglib/qmt/diagram_controller/dupdatevisitor.cpp index 0866e6d9f5d..2dd079e1bcb 100644 --- a/src/libs/modelinglib/qmt/diagram_controller/dupdatevisitor.cpp +++ b/src/libs/modelinglib/qmt/diagram_controller/dupdatevisitor.cpp @@ -65,6 +65,9 @@ void DUpdateVisitor::visitMObject(const MObject *object) } if (isUpdating(object->name() != dobject->name())) dobject->setName(object->name()); + bool hasLinkedFile = !object->linkedFileName().isEmpty(); + if (isUpdating(hasLinkedFile != dobject->hasLinkedFile())) + dobject->setLinkedFile(hasLinkedFile); // TODO unlikely that this is called for all objects if hierarchy is modified // PERFORM remove loop int depth = 1; diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/classitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/classitem.cpp index 14ad25b2c1d..23a9c524a2b 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/classitem.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/items/classitem.cpp @@ -85,29 +85,16 @@ void ClassItem::update() m_methodsText.clear(); } - // custom icon - if (stereotypeIconDisplay() == StereotypeIcon::DisplayIcon) { - if (!m_customIcon) - m_customIcon = new CustomIconItem(diagramSceneModel(), this); - m_customIcon->setStereotypeIconId(stereotypeIconId()); - m_customIcon->setBaseSize(stereotypeIconMinimumSize(m_customIcon->stereotypeIcon(), CUSTOM_ICON_MINIMUM_AUTO_WIDTH, CUSTOM_ICON_MINIMUM_AUTO_HEIGHT)); - m_customIcon->setBrush(style->fillBrush()); - m_customIcon->setPen(style->outerLinePen()); - m_customIcon->setZValue(SHAPE_ZVALUE); - } else if (m_customIcon) { - m_customIcon->scene()->removeItem(m_customIcon); - delete m_customIcon; - m_customIcon = nullptr; - } + updateCustomIcon(style); // shape - if (!m_customIcon) { + if (!customIconItem()) { if (!m_shape) m_shape = new QGraphicsRectItem(this); m_shape->setBrush(style->fillBrush()); m_shape->setPen(style->outerLinePen()); m_shape->setZValue(SHAPE_ZVALUE); - } else if (m_shape){ + } else if (m_shape) { m_shape->scene()->removeItem(m_shape); delete m_shape; m_shape = nullptr; @@ -259,7 +246,7 @@ void ClassItem::update() m_templateParameterBox = nullptr; } - updateSelectionMarker(m_customIcon); + updateSelectionMarker(customIconItem()); updateRelationStarter(); updateAlignmentButtons(); updateGeometry(); @@ -267,8 +254,8 @@ void ClassItem::update() bool ClassItem::intersectShapeWithLine(const QLineF &line, QPointF *intersectionPoint, QLineF *intersectionLine) const { - if (m_customIcon) { - QList<QPolygonF> polygons = m_customIcon->outline(); + if (customIconItem()) { + QList<QPolygonF> polygons = customIconItem()->outline(); for (int i = 0; i < polygons.size(); ++i) polygons[i].translate(object()->pos() + object()->rect().topLeft()); if (shapeIcon().textAlignment() == qmt::StereotypeIcon::TextalignBelow) { @@ -508,7 +495,7 @@ DClass::TemplateDisplay ClassItem::templateDisplay() const DClass::TemplateDisplay templateDisplay = diagramClass->templateDisplay(); if (templateDisplay == DClass::TemplateSmart) { - if (m_customIcon) + if (customIconItem()) templateDisplay = DClass::TemplateName; else templateDisplay = DClass::TemplateBox; @@ -521,8 +508,8 @@ QSizeF ClassItem::calcMinimumGeometry() const double width = 0.0; double height = 0.0; - if (m_customIcon) { - QSizeF sz = stereotypeIconMinimumSize(m_customIcon->stereotypeIcon(), + if (customIconItem()) { + QSizeF sz = customIconItemMinimumSize(customIconItem(), CUSTOM_ICON_MINIMUM_AUTO_WIDTH, CUSTOM_ICON_MINIMUM_AUTO_HEIGHT); if (shapeIcon().textAlignment() != qmt::StereotypeIcon::TextalignTop && shapeIcon().textAlignment() != qmt::StereotypeIcon::TextalignCenter) @@ -589,12 +576,7 @@ void ClassItem::updateGeometry() height = geometry.height(); if (object()->isAutoSized()) { - if (!m_customIcon) { - if (width < MINIMUM_AUTO_WIDTH) - width = MINIMUM_AUTO_WIDTH; - if (height < MINIMUM_AUTO_HEIGHT) - height = MINIMUM_AUTO_HEIGHT; - } + correctAutoSize(customIconItem(), width, height, MINIMUM_AUTO_WIDTH, MINIMUM_AUTO_HEIGHT); } else { QRectF rect = object()->rect(); if (rect.width() > width) @@ -619,15 +601,15 @@ void ClassItem::updateGeometry() // a backup for the graphics item used for manual resized and persistency. object()->setRect(rect); - if (m_customIcon) { - m_customIcon->setPos(left, top); - m_customIcon->setActualSize(QSizeF(width, height)); + if (customIconItem()) { + customIconItem()->setPos(left, top); + customIconItem()->setActualSize(QSizeF(width, height)); } if (m_shape) m_shape->setRect(rect); - if (m_customIcon) { + if (customIconItem()) { switch (shapeIcon().textAlignment()) { case qmt::StereotypeIcon::TextalignBelow: y += height + BODY_VERT_BORDER; @@ -679,7 +661,7 @@ void ClassItem::updateGeometry() y += nameItem()->boundingRect().height(); } if (m_contextLabel) { - if (m_customIcon) + if (customIconItem()) m_contextLabel->resetMaxWidth(); else m_contextLabel->setMaxWidth(width - 2 * BODY_HORIZ_BORDER); @@ -692,7 +674,7 @@ void ClassItem::updateGeometry() y += 8.0; } if (m_attributes) { - if (m_customIcon) + if (customIconItem()) m_attributes->setPos(-m_attributes->boundingRect().width() / 2.0, y); else m_attributes->setPos(left + BODY_HORIZ_BORDER, y); @@ -704,7 +686,7 @@ void ClassItem::updateGeometry() y += 8.0; } if (m_methods) { - if (m_customIcon) + if (customIconItem()) m_methods->setPos(-m_methods->boundingRect().width() / 2.0, y); else m_methods->setPos(left + BODY_HORIZ_BORDER, y); @@ -765,21 +747,22 @@ void ClassItem::updateMembers(const Style *style) break; } + bool needBr = false; if (text && !text->isEmpty()) - *text += "<br/>"; + needBr = true; - bool addNewline = false; - bool addSpace = false; if (currentVisibility) *currentVisibility = member.visibility(); if (currentGroup && member.group() != *currentGroup) { - *text += QString("[%1]").arg(member.group()); - addNewline = true; + needBr = false; + *text += QString("<p style=\"padding:0;margin-top:6;margin-bottom:0;\"><b>[%1]</b></p>").arg(member.group()); *currentGroup = member.group(); } - if (addNewline) + + if (needBr) *text += "<br/>"; + bool addSpace = false; bool haveSignal = false; bool haveSlot = false; if (member.visibility() != MClassMember::VisibilityUndefined) { diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/classitem.h b/src/libs/modelinglib/qmt/diagram_scene/items/classitem.h index 83ce0a9a5a0..cc92ab1ff53 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/classitem.h +++ b/src/libs/modelinglib/qmt/diagram_scene/items/classitem.h @@ -53,7 +53,6 @@ private: void updateGeometry(); void updateMembers(const Style *style); - CustomIconItem *m_customIcon = nullptr; QGraphicsRectItem *m_shape = nullptr; QGraphicsSimpleTextItem *m_baseClasses = nullptr; QGraphicsSimpleTextItem *m_namespace = nullptr; diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/componentitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/componentitem.cpp index 6a54a001e5f..e7fffcbf9a3 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/componentitem.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/items/componentitem.cpp @@ -53,24 +53,11 @@ void ComponentItem::update() const Style *style = adaptedStyle(stereotypeIconId()); - // custom icon - if (stereotypeIconDisplay() == StereotypeIcon::DisplayIcon) { - if (!m_customIcon) - m_customIcon = new CustomIconItem(diagramSceneModel(), this); - m_customIcon->setStereotypeIconId(stereotypeIconId()); - m_customIcon->setBaseSize(stereotypeIconMinimumSize(m_customIcon->stereotypeIcon(), CUSTOM_ICON_MINIMUM_AUTO_WIDTH, CUSTOM_ICON_MINIMUM_AUTO_HEIGHT)); - m_customIcon->setBrush(style->fillBrush()); - m_customIcon->setPen(style->outerLinePen()); - m_customIcon->setZValue(SHAPE_ZVALUE); - } else if (m_customIcon) { - m_customIcon->scene()->removeItem(m_customIcon); - delete m_customIcon; - m_customIcon = nullptr; - } + updateCustomIcon(style); // shape bool deleteRects = false; - if (!m_customIcon) { + if (!customIconItem()) { if (!m_shape) m_shape = new QGraphicsRectItem(this); m_shape->setBrush(style->fillBrush()); @@ -130,7 +117,7 @@ void ComponentItem::update() m_contextLabel = nullptr; } - updateSelectionMarker(m_customIcon); + updateSelectionMarker(customIconItem()); updateRelationStarter(); updateAlignmentButtons(); updateGeometry(); @@ -138,8 +125,8 @@ void ComponentItem::update() bool ComponentItem::intersectShapeWithLine(const QLineF &line, QPointF *intersectionPoint, QLineF *intersectionLine) const { - if (m_customIcon) { - QList<QPolygonF> polygons = m_customIcon->outline(); + if (customIconItem()) { + QList<QPolygonF> polygons = customIconItem()->outline(); for (int i = 0; i < polygons.size(); ++i) polygons[i].translate(object()->pos() + object()->rect().topLeft()); if (shapeIcon().textAlignment() == qmt::StereotypeIcon::TextalignBelow) { @@ -207,14 +194,16 @@ QSizeF ComponentItem::calcMinimumGeometry() const { double width = 0.0; double height = 0.0; + double customMinHeight = 0.0; - if (m_customIcon) { - QSizeF sz = stereotypeIconMinimumSize(m_customIcon->stereotypeIcon(), + if (customIconItem()) { + QSizeF sz = customIconItemMinimumSize(customIconItem(), CUSTOM_ICON_MINIMUM_AUTO_WIDTH, CUSTOM_ICON_MINIMUM_AUTO_HEIGHT); if (shapeIcon().textAlignment() != qmt::StereotypeIcon::TextalignTop && shapeIcon().textAlignment() != qmt::StereotypeIcon::TextalignCenter) return sz; width = sz.width(); + customMinHeight = sz.height(); } height += BODY_VERT_BORDER; @@ -234,7 +223,7 @@ QSizeF ComponentItem::calcMinimumGeometry() const height += m_contextLabel->height(); height += BODY_VERT_BORDER; - if (!hasPlainShape()) { + if (!customIconItem() && !hasPlainShape()) { width = RECT_WIDTH * 0.5 + BODY_HORIZ_BORDER + width + BODY_HORIZ_BORDER + RECT_WIDTH * 0.5; double minHeight = UPPER_RECT_Y + RECT_HEIGHT + RECT_Y_DISTANCE + RECT_HEIGHT + LOWER_RECT_MIN_Y; if (height < minHeight) @@ -243,6 +232,9 @@ QSizeF ComponentItem::calcMinimumGeometry() const width = BODY_HORIZ_BORDER + width + BODY_HORIZ_BORDER; } + if (height < customMinHeight) + height = customMinHeight; + return GeometryUtilities::ensureMinimumRasterSize(QSizeF(width, height), 2 * RASTER_WIDTH, 2 * RASTER_HEIGHT); } @@ -259,7 +251,7 @@ void ComponentItem::updateGeometry() height = geometry.height(); if (object()->isAutoSized()) { - // nothing + correctAutoSize(customIconItem(), width, height, 0, 0); } else { QRectF rect = object()->rect(); if (rect.width() > width) @@ -283,9 +275,9 @@ void ComponentItem::updateGeometry() // a backup for the graphics item used for manual resized and persistency. object()->setRect(rect); - if (m_customIcon) { - m_customIcon->setPos(left, top); - m_customIcon->setActualSize(QSizeF(width, height)); + if (customIconItem()) { + customIconItem()->setPos(left, top); + customIconItem()->setActualSize(QSizeF(width, height)); } if (m_shape) @@ -303,7 +295,7 @@ void ComponentItem::updateGeometry() m_lowerRect->setPos(left - RECT_WIDTH * 0.5, top + UPPER_RECT_Y + RECT_HEIGHT + RECT_Y_DISTANCE); } - if (m_customIcon) { + if (customIconItem()) { switch (shapeIcon().textAlignment()) { case qmt::StereotypeIcon::TextalignBelow: y += height + BODY_VERT_BORDER; @@ -345,7 +337,7 @@ void ComponentItem::updateGeometry() y += nameItem()->boundingRect().height(); } if (m_contextLabel) { - if (m_customIcon) { + if (customIconItem()) { m_contextLabel->resetMaxWidth(); } else { double maxContextWidth = width - 2 * BODY_HORIZ_BORDER - (hasPlainShape() ? 0 : RECT_WIDTH); diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/componentitem.h b/src/libs/modelinglib/qmt/diagram_scene/items/componentitem.h index f00fbf30eb4..f4910f53ce2 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/componentitem.h +++ b/src/libs/modelinglib/qmt/diagram_scene/items/componentitem.h @@ -41,7 +41,6 @@ private: QSizeF calcMinimumGeometry() const; void updateGeometry(); - CustomIconItem *m_customIcon = nullptr; QGraphicsRectItem *m_shape = nullptr; QGraphicsRectItem *m_upperRect = nullptr; QGraphicsRectItem *m_lowerRect = nullptr; diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/diagramitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/diagramitem.cpp index c37c38b3bb8..951d6f3b1ad 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/diagramitem.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/items/diagramitem.cpp @@ -47,23 +47,10 @@ void DiagramItem::update() const Style *style = adaptedStyle(stereotypeIconId()); - // custom icon - if (stereotypeIconDisplay() == StereotypeIcon::DisplayIcon) { - if (!m_customIcon) - m_customIcon = new CustomIconItem(diagramSceneModel(), this); - m_customIcon->setStereotypeIconId(stereotypeIconId()); - m_customIcon->setBaseSize(stereotypeIconMinimumSize(m_customIcon->stereotypeIcon(), CUSTOM_ICON_MINIMUM_AUTO_WIDTH, CUSTOM_ICON_MINIMUM_AUTO_HEIGHT)); - m_customIcon->setBrush(style->fillBrush()); - m_customIcon->setPen(style->outerLinePen()); - m_customIcon->setZValue(SHAPE_ZVALUE); - } else if (m_customIcon) { - m_customIcon->scene()->removeItem(m_customIcon); - delete m_customIcon; - m_customIcon = nullptr; - } + updateCustomIcon(style); // shape - if (!m_customIcon) { + if (!customIconItem()) { if (!m_body) m_body = new QGraphicsPolygonItem(this); m_body->setBrush(style->fillBrush()); @@ -93,15 +80,15 @@ void DiagramItem::update() // diagram name updateNameItem(style); - updateSelectionMarker(m_customIcon); + updateSelectionMarker(customIconItem()); updateAlignmentButtons(); updateGeometry(); } bool DiagramItem::intersectShapeWithLine(const QLineF &line, QPointF *intersectionPoint, QLineF *intersectionLine) const { - if (m_customIcon) { - QList<QPolygonF> polygons = m_customIcon->outline(); + if (customIconItem()) { + QList<QPolygonF> polygons = customIconItem()->outline(); for (int i = 0; i < polygons.size(); ++i) polygons[i].translate(object()->pos() + object()->rect().topLeft()); if (shapeIcon().textAlignment() == qmt::StereotypeIcon::TextalignBelow) { @@ -131,8 +118,8 @@ QSizeF DiagramItem::calcMinimumGeometry() const double width = MINIMUM_WIDTH; double height = 0.0; - if (m_customIcon) { - QSizeF sz = stereotypeIconMinimumSize(m_customIcon->stereotypeIcon(), + if (customIconItem()) { + QSizeF sz = customIconItemMinimumSize(customIconItem(), CUSTOM_ICON_MINIMUM_AUTO_WIDTH, CUSTOM_ICON_MINIMUM_AUTO_HEIGHT); if (shapeIcon().textAlignment() != qmt::StereotypeIcon::TextalignTop && shapeIcon().textAlignment() != qmt::StereotypeIcon::TextalignCenter) @@ -175,12 +162,7 @@ void DiagramItem::updateGeometry() height = geometry.height(); if (object()->isAutoSized()) { - if (!m_customIcon) { - if (width < MINIMUM_AUTO_WIDTH) - width = MINIMUM_AUTO_WIDTH; - if (height < MINIMUM_AUTO_HEIGHT) - height = MINIMUM_AUTO_HEIGHT; - } + correctAutoSize(customIconItem(), width, height, MINIMUM_AUTO_WIDTH, MINIMUM_AUTO_HEIGHT); } else { QRectF rect = object()->rect(); if (rect.width() > width) @@ -203,9 +185,9 @@ void DiagramItem::updateGeometry() // a backup for the graphics item used for manual resized and persistency. object()->setRect(rect); - if (m_customIcon) { - m_customIcon->setPos(left, top); - m_customIcon->setActualSize(QSizeF(width, height)); + if (customIconItem()) { + customIconItem()->setPos(left, top); + customIconItem()->setActualSize(QSizeF(width, height)); } if (m_body) { @@ -227,7 +209,7 @@ void DiagramItem::updateGeometry() m_fold->setPolygon(foldPolygon); } - if (m_customIcon) { + if (customIconItem()) { switch (shapeIcon().textAlignment()) { case qmt::StereotypeIcon::TextalignBelow: y += height + BODY_VERT_BORDER; diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/diagramitem.h b/src/libs/modelinglib/qmt/diagram_scene/items/diagramitem.h index 81012b04a18..88d9f9a7a83 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/diagramitem.h +++ b/src/libs/modelinglib/qmt/diagram_scene/items/diagramitem.h @@ -29,7 +29,6 @@ private: QSizeF calcMinimumGeometry() const; void updateGeometry(); - CustomIconItem *m_customIcon = nullptr; QGraphicsPolygonItem *m_body = nullptr; QGraphicsPolygonItem *m_fold = nullptr; }; diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/itemitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/itemitem.cpp index 97a1b337fc8..9855889b084 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/itemitem.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/items/itemitem.cpp @@ -52,22 +52,10 @@ void ItemItem::update() const Style *style = adaptedStyle(shapeIconId()); - if (!shapeIconId().isEmpty()) { - if (!m_customIcon) - m_customIcon = new CustomIconItem(diagramSceneModel(), this); - m_customIcon->setStereotypeIconId(shapeIconId()); - m_customIcon->setBaseSize(stereotypeIconMinimumSize(m_customIcon->stereotypeIcon(), CUSTOM_ICON_MINIMUM_AUTO_WIDTH, CUSTOM_ICON_MINIMUM_AUTO_HEIGHT)); - m_customIcon->setBrush(style->fillBrush()); - m_customIcon->setPen(style->outerLinePen()); - m_customIcon->setZValue(SHAPE_ZVALUE); - } else if (m_customIcon) { - m_customIcon->scene()->removeItem(m_customIcon); - delete m_customIcon; - m_customIcon = nullptr; - } + updateCustomIcon(style); // shape - if (!m_customIcon) { + if (!customIconItem()) { if (!m_shape) m_shape = new QGraphicsRectItem(this); m_shape->setBrush(style->fillBrush()); @@ -100,7 +88,7 @@ void ItemItem::update() m_contextLabel = nullptr; } - updateSelectionMarker(m_customIcon); + updateSelectionMarker(customIconItem()); updateRelationStarter(); updateAlignmentButtons(); updateGeometry(); @@ -108,8 +96,8 @@ void ItemItem::update() bool ItemItem::intersectShapeWithLine(const QLineF &line, QPointF *intersectionPoint, QLineF *intersectionLine) const { - if (m_customIcon) { - QList<QPolygonF> polygons = m_customIcon->outline(); + if (customIconItem()) { + QList<QPolygonF> polygons = customIconItem()->outline(); for (int i = 0; i < polygons.size(); ++i) polygons[i].translate(object()->pos() + object()->rect().topLeft()); if (shapeIcon().textAlignment() == qmt::StereotypeIcon::TextalignBelow) { @@ -152,14 +140,16 @@ QSizeF ItemItem::calcMinimumGeometry() const { double width = 0.0; double height = 0.0; + double customMinHeight = 0.0; - if (m_customIcon) { - QSizeF sz = stereotypeIconMinimumSize(m_customIcon->stereotypeIcon(), + if (customIconItem()) { + QSizeF sz = customIconItemMinimumSize(customIconItem(), CUSTOM_ICON_MINIMUM_AUTO_WIDTH, CUSTOM_ICON_MINIMUM_AUTO_HEIGHT); if (shapeIcon().textAlignment() != qmt::StereotypeIcon::TextalignTop && shapeIcon().textAlignment() != qmt::StereotypeIcon::TextalignCenter) return sz; width = sz.width(); + customMinHeight = sz.height(); } height += BODY_VERT_BORDER; @@ -181,6 +171,9 @@ QSizeF ItemItem::calcMinimumGeometry() const width = BODY_HORIZ_BORDER + width + BODY_HORIZ_BORDER; + if (height < customMinHeight) + height = customMinHeight; + return GeometryUtilities::ensureMinimumRasterSize(QSizeF(width, height), 2 * RASTER_WIDTH, 2 * RASTER_HEIGHT); } @@ -197,7 +190,7 @@ void ItemItem::updateGeometry() height = geometry.height(); if (object()->isAutoSized()) { - // nothing + correctAutoSize(customIconItem(), width, height, 0, 0); } else { QRectF rect = object()->rect(); if (rect.width() > width) @@ -221,15 +214,15 @@ void ItemItem::updateGeometry() // a backup for the graphics item used for manual resized and persistency. object()->setRect(rect); - if (m_customIcon) { - m_customIcon->setPos(left, top); - m_customIcon->setActualSize(QSizeF(width, height)); + if (customIconItem()) { + customIconItem()->setPos(left, top); + customIconItem()->setActualSize(QSizeF(width, height)); } if (m_shape) m_shape->setRect(rect); - if (m_customIcon) { + if (customIconItem()) { switch (shapeIcon().textAlignment()) { case qmt::StereotypeIcon::TextalignBelow: y += height + BODY_VERT_BORDER; @@ -271,7 +264,7 @@ void ItemItem::updateGeometry() y += nameItem()->boundingRect().height(); } if (m_contextLabel) { - if (m_customIcon) { + if (customIconItem()) { m_contextLabel->resetMaxWidth(); } else { double maxContextWidth = width - 2 * BODY_HORIZ_BORDER; diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/itemitem.h b/src/libs/modelinglib/qmt/diagram_scene/items/itemitem.h index 327b3799ac1..de091a2bc72 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/itemitem.h +++ b/src/libs/modelinglib/qmt/diagram_scene/items/itemitem.h @@ -39,7 +39,6 @@ private: QSizeF calcMinimumGeometry() const; void updateGeometry(); - CustomIconItem *m_customIcon = nullptr; QGraphicsRectItem *m_shape = nullptr; ContextLabelItem *m_contextLabel = nullptr; }; diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.cpp index 0fe32080cfe..5d747a6391f 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.cpp @@ -498,6 +498,7 @@ void ObjectItem::updateStereotypes(const QString &stereotypeIconId, StereotypeIc m_stereotypeIcon = new CustomIconItem(m_diagramSceneModel, this); m_stereotypeIcon->setStereotypeIconId(stereotypeIconId); m_stereotypeIcon->setBaseSize(QSizeF(m_stereotypeIcon->shapeWidth(), m_stereotypeIcon->shapeHeight())); + m_stereotypeIcon->setActualSize(QSizeF(m_stereotypeIcon->shapeWidth(), m_stereotypeIcon->shapeHeight())); m_stereotypeIcon->setBrush(style->fillBrush()); m_stereotypeIcon->setPen(style->innerLinePen()); } else if (m_stereotypeIcon) { @@ -518,45 +519,92 @@ void ObjectItem::updateStereotypes(const QString &stereotypeIconId, StereotypeIc } } -QSizeF ObjectItem::stereotypeIconMinimumSize(const StereotypeIcon &stereotypeIcon, +QSizeF ObjectItem::customIconItemMinimumSize(const CustomIconItem *customIconItem, qreal minimumWidth, qreal minimumHeight) const { Q_UNUSED(minimumWidth) qreal width = 0.0; qreal height = 0.0; - if (stereotypeIcon.hasMinWidth() && !stereotypeIcon.hasMinHeight()) { - width = stereotypeIcon.minWidth(); - if (stereotypeIcon.sizeLock() == StereotypeIcon::LockHeight || stereotypeIcon.sizeLock() == StereotypeIcon::LockSize) - height = stereotypeIcon.minHeight(); - else - height = width * stereotypeIcon.height() / stereotypeIcon.width(); - } else if (!stereotypeIcon.hasMinWidth() && stereotypeIcon.hasMinHeight()) { - height = stereotypeIcon.minHeight(); - if (stereotypeIcon.sizeLock() == StereotypeIcon::LockWidth || stereotypeIcon.sizeLock() == StereotypeIcon::LockSize) - width = stereotypeIcon.minWidth(); - else - width = height * stereotypeIcon.width() / stereotypeIcon.height(); - } else if (stereotypeIcon.hasMinWidth() && stereotypeIcon.hasMinHeight()) { - if (stereotypeIcon.sizeLock() == StereotypeIcon::LockRatio) { + if (customIconItem->hasImage()) { + const QImage &image = customIconItem->image(); + width = minimumWidth; + height = image.height() * width / image.width(); + if (height < minimumHeight) { + height = minimumHeight; + width = image.width() * height / image.height(); + } + } else { + const StereotypeIcon &stereotypeIcon = customIconItem->stereotypeIcon(); + if (stereotypeIcon.hasMinWidth() && !stereotypeIcon.hasMinHeight()) { width = stereotypeIcon.minWidth(); - height = width * stereotypeIcon.height() / stereotypeIcon.width(); - if (height < stereotypeIcon.minHeight()) { + if (stereotypeIcon.sizeLock() == StereotypeIcon::LockHeight || stereotypeIcon.sizeLock() == StereotypeIcon::LockSize) height = stereotypeIcon.minHeight(); + else + height = width * stereotypeIcon.height() / stereotypeIcon.width(); + } else if (!stereotypeIcon.hasMinWidth() && stereotypeIcon.hasMinHeight()) { + height = stereotypeIcon.minHeight(); + if (stereotypeIcon.sizeLock() == StereotypeIcon::LockWidth || stereotypeIcon.sizeLock() == StereotypeIcon::LockSize) + width = stereotypeIcon.minWidth(); + else width = height * stereotypeIcon.width() / stereotypeIcon.height(); - QMT_CHECK(width <= stereotypeIcon.minWidth()); + } else if (stereotypeIcon.hasMinWidth() && stereotypeIcon.hasMinHeight()) { + if (stereotypeIcon.sizeLock() == StereotypeIcon::LockRatio) { + width = stereotypeIcon.minWidth(); + height = width * stereotypeIcon.height() / stereotypeIcon.width(); + if (height < stereotypeIcon.minHeight()) { + height = stereotypeIcon.minHeight(); + width = height * stereotypeIcon.width() / stereotypeIcon.height(); + QMT_CHECK(width <= stereotypeIcon.minWidth()); + } + } else { + width = stereotypeIcon.minWidth(); + height = stereotypeIcon.minHeight(); } } else { - width = stereotypeIcon.minWidth(); - height = stereotypeIcon.minHeight(); + height = minimumHeight; + width = height * stereotypeIcon.width() / stereotypeIcon.height(); } - } else { - height = minimumHeight; - width = height * stereotypeIcon.width() / stereotypeIcon.height(); } return QSizeF(width, height); } +void ObjectItem::correctAutoSize(const CustomIconItem* customIconItem, qreal &width, qreal &height, qreal minimumWidth, qreal minimumHeight) const +{ + if (customIconItem) { + if (customIconItem->hasImage()) { + width = customIconItem->image().width(); + height = customIconItem->image().height(); + } + } else { + if (width < minimumWidth) + width = minimumWidth; + if (height < minimumHeight) + height = minimumHeight; + } +} + +void ObjectItem::updateCustomIcon(const Style *style) +{ + if (object()->hasImage()) { + if (!m_customIcon) + m_customIcon = new CustomIconItem(diagramSceneModel(), this); + m_customIcon->setImage(object()->image()); + m_customIcon->setZValue(SHAPE_ZVALUE); + } else if (!shapeIconId().isEmpty()) { + if (!m_customIcon) + m_customIcon = new CustomIconItem(diagramSceneModel(), this); + m_customIcon->setStereotypeIconId(shapeIconId()); + m_customIcon->setBrush(style->fillBrush()); + m_customIcon->setPen(style->outerLinePen()); + m_customIcon->setZValue(SHAPE_ZVALUE); + } else if (m_customIcon) { + m_customIcon->scene()->removeItem(m_customIcon); + delete m_customIcon; + m_customIcon = nullptr; + } +} + bool ObjectItem::suppressTextDisplay() const { return m_shapeIcon.textAlignment() == StereotypeIcon::TextalignNone; @@ -564,6 +612,7 @@ bool ObjectItem::suppressTextDisplay() const void ObjectItem::updateNameItem(const Style *style) { + QString display_name = buildDisplayName(); if (!suppressTextDisplay()) { if (!m_nameItem) { m_nameItem = new EditableTextItem(this); @@ -582,16 +631,18 @@ void ObjectItem::updateNameItem(const Style *style) QObject::connect(m_nameItem, &EditableTextItem::returnKeyPressed, m_nameItem, [this] { this->m_nameItem->clearFocus(); }); } - if (style->headerFont() != m_nameItem->font()) - m_nameItem->setFont(style->headerFont()); + QFont font = style->headerFont(); + if (object()->hasLinkedFile()) + font.setUnderline(true); + if (font != m_nameItem->font()) + m_nameItem->setFont(font); if (style->textBrush().color() != m_nameItem->defaultTextColor()) m_nameItem->setDefaultTextColor(style->textBrush().color()); if (!m_nameItem->hasFocus()) { - QString name = buildDisplayName(); - if (name != m_nameItem->toPlainText()) - m_nameItem->setPlainText(name); + if (display_name != m_nameItem->toPlainText()) + m_nameItem->setPlainText(display_name); } - } else if (m_nameItem ){ + } else if (m_nameItem) { m_nameItem->scene()->removeItem(m_nameItem); delete m_nameItem; m_nameItem = nullptr; @@ -621,30 +672,45 @@ void ObjectItem::setObjectName(const QString &objectName) void ObjectItem::updateDepth() { - setZValue(m_object->depth()); + int depth_delta = 0; + switch (m_shapeIcon.depthLayer()) { + case StereotypeIcon::DepthBehindItems: + depth_delta = -1; + break; + case StereotypeIcon::DepthAmongItems: + depth_delta = 0; + break; + case StereotypeIcon::DepthBeforeItems: + depth_delta = 1; + break; + } + setZValue(m_object->depth() + depth_delta); } -void ObjectItem::updateSelectionMarker(CustomIconItem *customIconItem) +void ObjectItem::updateSelectionMarker(const CustomIconItem *customIconItem) { if (customIconItem) { - StereotypeIcon stereotypeIcon = customIconItem->stereotypeIcon(); ResizeFlags resizeFlags = ResizeUnlocked; - switch (stereotypeIcon.sizeLock()) { - case StereotypeIcon::LockNone: - resizeFlags = ResizeUnlocked; - break; - case StereotypeIcon::LockWidth: - resizeFlags = ResizeLockedWidth; - break; - case StereotypeIcon::LockHeight: - resizeFlags = ResizeLockedHeight; - break; - case StereotypeIcon::LockSize: - resizeFlags = ResizeLockedSize; - break; - case StereotypeIcon::LockRatio: + if (customIconItem->hasImage()) { resizeFlags = ResizeLockedRatio; - break; + } else { + switch (customIconItem->stereotypeIcon().sizeLock()) { + case StereotypeIcon::LockNone: + resizeFlags = ResizeUnlocked; + break; + case StereotypeIcon::LockWidth: + resizeFlags = ResizeLockedWidth; + break; + case StereotypeIcon::LockHeight: + resizeFlags = ResizeLockedHeight; + break; + case StereotypeIcon::LockSize: + resizeFlags = ResizeLockedSize; + break; + case StereotypeIcon::LockRatio: + resizeFlags = ResizeLockedRatio; + break; + } } updateSelectionMarker(resizeFlags); } else { @@ -990,6 +1056,10 @@ void ObjectItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) addSeparator = true; if (element_tasks->extendContextMenu(object(), diagramSceneModel()->diagram(), &menu)) addSeparator = true; + if (element_tasks->hasLinkedFile(m_object, m_diagramSceneModel->diagram())) { + menu.addAction(new ContextMenuAction(Tr::tr("Open Linked File"), "openLinkedFile", &menu)); + addSeparator = true; + } if (addSeparator) menu.addSeparator(); menu.addAction(new ContextMenuAction(Tr::tr("Remove"), "remove", @@ -1000,12 +1070,12 @@ void ObjectItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) QMenu alignMenu; alignMenu.setTitle(Tr::tr("Align Objects")); alignMenu.addAction(new ContextMenuAction(Tr::tr("Align Left"), "alignLeft", &alignMenu)); - alignMenu.addAction(new ContextMenuAction(Tr::tr("Center Vertically"), "centerVertically", + alignMenu.addAction(new ContextMenuAction(Tr::tr("Center Horizontally"), "centerHorizontally", &alignMenu)); alignMenu.addAction(new ContextMenuAction(Tr::tr("Align Right"), "alignRight", &alignMenu)); alignMenu.addSeparator(); alignMenu.addAction(new ContextMenuAction(Tr::tr("Align Top"), "alignTop", &alignMenu)); - alignMenu.addAction(new ContextMenuAction(Tr::tr("Center Horizontally"), "centerHorizontally", + alignMenu.addAction(new ContextMenuAction(Tr::tr("Center Vertically"), "centerVertically", &alignMenu)); alignMenu.addAction(new ContextMenuAction(Tr::tr("Align Bottom"), "alignBottom", &alignMenu)); alignMenu.addSeparator(); @@ -1035,6 +1105,8 @@ void ObjectItem::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) m_diagramSceneModel->diagramSceneController()->elementTasks()->openDiagram(m_object, m_diagramSceneModel->diagram()); } else if (action->id() == "createDiagram") { m_diagramSceneModel->diagramSceneController()->elementTasks()->createAndOpenDiagram(m_object, m_diagramSceneModel->diagram()); + } else if (action->id() == "openLinkedFile") { + m_diagramSceneModel->diagramSceneController()->elementTasks()->openLinkedFile(m_object, m_diagramSceneModel->diagram()); } else if (action->id() == "remove") { DSelection selection = m_diagramSceneModel->selectedElements(); if (selection.isEmpty()) diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.h b/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.h index e7acd5705ca..254ef215caa 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.h +++ b/src/libs/modelinglib/qmt/diagram_scene/items/objectitem.h @@ -120,8 +120,12 @@ protected: StereotypeIcon::Display stereotypeDisplay, const Style *style); StereotypesItem *stereotypesItem() const { return m_stereotypesItem; } CustomIconItem *stereotypeIconItem() const { return m_stereotypeIcon; } - QSizeF stereotypeIconMinimumSize(const StereotypeIcon &stereotypeIcon, qreal minimumWidth, + CustomIconItem *customIconItem() const { return m_customIcon; } + QSizeF customIconItemMinimumSize(const CustomIconItem* customIconItem, qreal minimumWidth, qreal minimumHeight) const; + void correctAutoSize(const CustomIconItem *customIconItem, qreal& width, qreal& height, + qreal minimumWidth, qreal minimumHeight) const; + void updateCustomIcon(const Style* style); bool suppressTextDisplay() const; void updateNameItem(const Style *style); EditableTextItem *nameItem() const { return m_nameItem; } @@ -130,7 +134,7 @@ protected: void setObjectName(const QString &objectName); void updateDepth(); - void updateSelectionMarker(CustomIconItem *customIconItem); + void updateSelectionMarker(const CustomIconItem* customIconItem); void updateSelectionMarker(ResizeFlags resizeFlags); void updateSelectionMarkerGeometry(const QRectF &objectRect); void updateRelationStarter(); @@ -169,6 +173,7 @@ private: StereotypeIcon::Display m_stereotypeIconDisplay = StereotypeIcon::DisplayLabel; StereotypesItem *m_stereotypesItem = nullptr; CustomIconItem *m_stereotypeIcon = nullptr; + CustomIconItem *m_customIcon = nullptr; EditableTextItem *m_nameItem = nullptr; RectangularSelectionItem *m_selectionMarker = nullptr; RelationStarter *m_relationStarter = nullptr; diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/packageitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/packageitem.cpp index b473d17ec8e..03e6d8d0f5d 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/packageitem.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/items/packageitem.cpp @@ -64,23 +64,10 @@ void PackageItem::update() const Style *style = adaptedStyle(stereotypeIconId()); - // custom icon - if (stereotypeIconDisplay() == StereotypeIcon::DisplayIcon) { - if (!m_customIcon) - m_customIcon = new CustomIconItem(diagramSceneModel(), this); - m_customIcon->setStereotypeIconId(stereotypeIconId()); - m_customIcon->setBaseSize(stereotypeIconMinimumSize(m_customIcon->stereotypeIcon(), CUSTOM_ICON_MINIMUM_AUTO_WIDTH, CUSTOM_ICON_MINIMUM_AUTO_HEIGHT)); - m_customIcon->setBrush(style->fillBrush()); - m_customIcon->setPen(style->outerLinePen()); - m_customIcon->setZValue(SHAPE_ZVALUE); - } else if (m_customIcon) { - m_customIcon->scene()->removeItem(m_customIcon); - delete m_customIcon; - m_customIcon = nullptr; - } + updateCustomIcon(style); // shape - if (!m_customIcon) { + if (!customIconItem()) { if (!m_shape) m_shape = new QGraphicsPolygonItem(this); m_shape->setBrush(style->fillBrush()); @@ -111,7 +98,7 @@ void PackageItem::update() m_contextLabel = nullptr; } - updateSelectionMarker(m_customIcon); + updateSelectionMarker(customIconItem()); updateRelationStarter(); updateAlignmentButtons(); updateGeometry(); @@ -119,8 +106,8 @@ void PackageItem::update() bool PackageItem::intersectShapeWithLine(const QLineF &line, QPointF *intersectionPoint, QLineF *intersectionLine) const { - if (m_customIcon) { - QList<QPolygonF> polygons = m_customIcon->outline(); + if (customIconItem()) { + QList<QPolygonF> polygons = customIconItem()->outline(); for (int i = 0; i < polygons.size(); ++i) polygons[i].translate(object()->pos() + object()->rect().topLeft()); if (shapeIcon().textAlignment() == qmt::StereotypeIcon::TextalignBelow) { @@ -169,8 +156,8 @@ PackageItem::ShapeGeometry PackageItem::calcMinimumGeometry() const double width = 0.0; double height = 0.0; - if (m_customIcon) { - QSizeF sz = stereotypeIconMinimumSize(m_customIcon->stereotypeIcon(), + if (customIconItem()) { + QSizeF sz = customIconItemMinimumSize(customIconItem(), CUSTOM_ICON_MINIMUM_AUTO_WIDTH, CUSTOM_ICON_MINIMUM_AUTO_HEIGHT); if (shapeIcon().textAlignment() != qmt::StereotypeIcon::TextalignTop && shapeIcon().textAlignment() != qmt::StereotypeIcon::TextalignCenter) @@ -244,12 +231,7 @@ void PackageItem::updateGeometry() // calc width and height if (object()->isAutoSized()) { - if (!m_customIcon) { - if (width < MINIMUM_AUTO_WIDTH) - width = MINIMUM_AUTO_WIDTH; - if (height < MINIMUM_AUTO_HEIGHT) - height = MINIMUM_AUTO_HEIGHT; - } + correctAutoSize(customIconItem(), width, height, MINIMUM_AUTO_WIDTH, MINIMUM_AUTO_HEIGHT); } else { QRectF rect = object()->rect(); if (rect.width() > width) @@ -273,9 +255,9 @@ void PackageItem::updateGeometry() // a backup for the graphics item used for manual resized and persistency. object()->setRect(rect); - if (m_customIcon) { - m_customIcon->setPos(left, top); - m_customIcon->setActualSize(QSizeF(width, height)); + if (customIconItem()) { + customIconItem()->setPos(left, top); + customIconItem()->setActualSize(QSizeF(width, height)); switch (shapeIcon().textAlignment()) { case qmt::StereotypeIcon::TextalignBelow: diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/packageitem.h b/src/libs/modelinglib/qmt/diagram_scene/items/packageitem.h index 19c2fe54abc..f87af2fa354 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/packageitem.h +++ b/src/libs/modelinglib/qmt/diagram_scene/items/packageitem.h @@ -40,7 +40,6 @@ private: ShapeGeometry calcMinimumGeometry() const; void updateGeometry(); - CustomIconItem *m_customIcon = nullptr; QGraphicsPolygonItem *m_shape = nullptr; ContextLabelItem *m_contextLabel = nullptr; }; diff --git a/src/libs/modelinglib/qmt/diagram_scene/items/stereotypedisplayvisitor.cpp b/src/libs/modelinglib/qmt/diagram_scene/items/stereotypedisplayvisitor.cpp index ad668f6bee3..9313327c87a 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/items/stereotypedisplayvisitor.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/items/stereotypedisplayvisitor.cpp @@ -57,7 +57,9 @@ void StereotypeDisplayVisitor::visitDObject(const DObject *object) DObject::StereotypeDisplay stereotypeDisplay = object->stereotypeDisplay(); m_stereotypeIconId = m_stereotypeController->findStereotypeIconId(m_stereotypeIconElement, object->stereotypes()); - if (m_stereotypeIconId.isEmpty() && stereotypeDisplay == DObject::StereotypeIcon) { + if (object->hasImage() && stereotypeDisplay == DObject::StereotypeSmart) { + stereotypeDisplay = DObject::StereotypeLabel; + } else if (m_stereotypeIconId.isEmpty() && stereotypeDisplay == DObject::StereotypeIcon) { stereotypeDisplay = DObject::StereotypeLabel; } else if (!m_stereotypeIconId.isEmpty() && stereotypeDisplay == DObject::StereotypeSmart) { StereotypeIcon stereotypeIcon = m_stereotypeController->findStereotypeIcon(m_stereotypeIconId); diff --git a/src/libs/modelinglib/qmt/diagram_scene/parts/customiconitem.cpp b/src/libs/modelinglib/qmt/diagram_scene/parts/customiconitem.cpp index 066f9b78751..36e4c4f7895 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/parts/customiconitem.cpp +++ b/src/libs/modelinglib/qmt/diagram_scene/parts/customiconitem.cpp @@ -57,55 +57,97 @@ void CustomIconItem::setPen(const QPen &pen) m_pen = pen; } +void CustomIconItem::setImage(const QImage &image) +{ + m_image = image; +} + double CustomIconItem::shapeWidth() const { - return m_stereotypeIcon.width(); + if (!m_image.isNull()) + return m_image.width(); + return m_stereotypeIcon.hasIconWidth() ? m_stereotypeIcon.iconWidth() + : m_stereotypeIcon.width(); } double CustomIconItem::shapeHeight() const { - return m_stereotypeIcon.height(); + if (!m_image.isNull()) + return m_image.height(); + return m_stereotypeIcon.hasIconHeight() ? m_stereotypeIcon.iconHeight() + : m_stereotypeIcon.height(); } QRectF CustomIconItem::boundingRect() const { - ShapeSizeVisitor visitor(QPointF(0.0, 0.0), QSizeF(m_stereotypeIcon.width(), m_stereotypeIcon.height()), m_baseSize, m_actualSize); + if (!m_image.isNull()) + return QRectF(QPointF(0.0, 0.0), m_actualSize) | childrenBoundingRect(); + ShapeSizeVisitor visitor(QPointF(0.0, 0.0), + QSizeF(m_stereotypeIcon.width(), m_stereotypeIcon.height()), + m_baseSize, + m_actualSize); m_stereotypeIcon.iconShape().visitShapes(&visitor); return visitor.boundingRect() | childrenBoundingRect(); } -void CustomIconItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +void CustomIconItem::paint(QPainter *painter, + const QStyleOptionGraphicsItem *option, + QWidget *widget) { Q_UNUSED(option) Q_UNUSED(widget) painter->save(); - painter->setBrush(m_brush); - painter->setPen(m_pen); + if (!m_image.isNull()) { + painter->drawImage(QRectF(QPointF(0.0, 0.0), m_actualSize), m_image); + } else { + painter->setBrush(m_brush); + painter->setPen(m_pen); #ifdef DEBUG_OUTLINE - ShapePolygonVisitor visitor(QPointF(0.0, 0.0), QSizeF(m_stereotypeIcon.width(), m_stereotypeIcon.height()), m_baseSize, m_actualSize); - IconShape shape = m_stereotypeIcon.outlineShape(); - if (shape.isEmpty()) - shape = m_stereotypeIcon.iconShape(); - shape.visitShapes(&visitor); - painter->drawPath(visitor.path()); - ShapePaintVisitor visitor1(painter, QPointF(0.0, 0.0), QSizeF(m_stereotypeIcon.width(), m_stereotypeIcon.height()), m_baseSize, m_actualSize); - m_stereotypeIcon.iconShape().visitShapes(&visitor1); + ShapePolygonVisitor visitor(QPointF(0.0, 0.0), + QSizeF(m_stereotypeIcon.width(), m_stereotypeIcon.height()), + m_baseSize, + m_actualSize); + IconShape shape = m_stereotypeIcon.outlineShape(); + if (shape.isEmpty()) + shape = m_stereotypeIcon.iconShape(); + shape.visitShapes(&visitor); + painter->drawPath(visitor.path()); + ShapePaintVisitor visitor1(painter, + QPointF(0.0, 0.0), + QSizeF(m_stereotypeIcon.width(), m_stereotypeIcon.height()), + m_baseSize, + m_actualSize); + m_stereotypeIcon.iconShape().visitShapes(&visitor1); #else - ShapePaintVisitor visitor(painter, QPointF(0.0, 0.0), QSizeF(m_stereotypeIcon.width(), m_stereotypeIcon.height()), m_baseSize, m_actualSize); - m_stereotypeIcon.iconShape().visitShapes(&visitor); + ShapePaintVisitor visitor(painter, + QPointF(0.0, 0.0), + QSizeF(m_stereotypeIcon.width(), m_stereotypeIcon.height()), + m_baseSize, + m_actualSize); + m_stereotypeIcon.iconShape().visitShapes(&visitor); #endif + } painter->restore(); } QList<QPolygonF> CustomIconItem::outline() const { - ShapePolygonVisitor visitor(QPointF(0.0, 0.0), QSizeF(m_stereotypeIcon.width(), m_stereotypeIcon.height()), m_baseSize, m_actualSize); - IconShape shape = m_stereotypeIcon.outlineShape(); - if (shape.isEmpty()) - shape = m_stereotypeIcon.iconShape(); - shape.visitShapes(&visitor); - return visitor.toPolygons(); + if (!m_image.isNull()) { + QList<QPolygonF> polygons; + polygons.append(QPolygonF(QRectF(QPointF(0.0, 0.0), m_actualSize))); + return polygons; + } else { + ShapePolygonVisitor visitor(QPointF(0.0, 0.0), + QSizeF(m_stereotypeIcon.width(), m_stereotypeIcon.height()), + m_baseSize, + m_actualSize); + IconShape shape = m_stereotypeIcon.outlineShape(); + if (shape.isEmpty()) + shape = m_stereotypeIcon.iconShape(); + shape.visitShapes(&visitor); + return visitor.toPolygons(); + } } } // namespace qmt diff --git a/src/libs/modelinglib/qmt/diagram_scene/parts/customiconitem.h b/src/libs/modelinglib/qmt/diagram_scene/parts/customiconitem.h index 7f85e875164..f61db552ac9 100644 --- a/src/libs/modelinglib/qmt/diagram_scene/parts/customiconitem.h +++ b/src/libs/modelinglib/qmt/diagram_scene/parts/customiconitem.h @@ -9,6 +9,7 @@ #include "qmt/stereotype/stereotypeicon.h" #include <QBrush> +#include <QImage> #include <QPen> namespace qmt { @@ -26,6 +27,9 @@ public: void setActualSize(const QSizeF &actualSize); void setBrush(const QBrush &brush); void setPen(const QPen &pen); + QImage image() const { return m_image; } + bool hasImage() const { return !m_image.isNull(); } + void setImage(const QImage &image); StereotypeIcon stereotypeIcon() const { return m_stereotypeIcon; } double shapeWidth() const; double shapeHeight() const; @@ -43,6 +47,7 @@ private: QSizeF m_actualSize; QBrush m_brush; QPen m_pen; + QImage m_image; }; } // namespace qmt diff --git a/src/libs/modelinglib/qmt/model/mobject.cpp b/src/libs/modelinglib/qmt/model/mobject.cpp index 734be135673..1e6bf8d0b35 100644 --- a/src/libs/modelinglib/qmt/model/mobject.cpp +++ b/src/libs/modelinglib/qmt/model/mobject.cpp @@ -20,6 +20,7 @@ MObject::MObject() MObject::MObject(const MObject &rhs) : MElement(rhs), m_name(rhs.m_name), + m_linkedfilename(rhs.m_linkedfilename), m_children(true), m_relations(true) { @@ -34,6 +35,7 @@ MObject &MObject::operator =(const MObject &rhs) if (this != &rhs) { MElement::operator=(rhs); m_name = rhs.m_name; + m_linkedfilename = rhs.m_linkedfilename; // no deep copy; list of children remains unchanged } return *this; @@ -44,6 +46,11 @@ void MObject::setName(const QString &name) m_name = name; } +void MObject::setLinkedFileName(const QString &linkedfilename) +{ + m_linkedfilename = linkedfilename; +} + void MObject::setChildren(const Handles<MObject> &children) { m_children = children; diff --git a/src/libs/modelinglib/qmt/model/mobject.h b/src/libs/modelinglib/qmt/model/mobject.h index 1dc95887d9a..33a475ed6ee 100644 --- a/src/libs/modelinglib/qmt/model/mobject.h +++ b/src/libs/modelinglib/qmt/model/mobject.h @@ -23,6 +23,8 @@ public: QString name() const { return m_name; } void setName(const QString &name); + QString linkedFileName() const { return m_linkedfilename; } + void setLinkedFileName(const QString &linkedfilename); const Handles<MObject> &children() const { return m_children; } void setChildren(const Handles<MObject> &children); @@ -48,6 +50,7 @@ public: private: QString m_name; + QString m_linkedfilename; Handles<MObject> m_children; Handles<MRelation> m_relations; }; diff --git a/src/libs/modelinglib/qmt/model_controller/mflatassignmentvisitor.cpp b/src/libs/modelinglib/qmt/model_controller/mflatassignmentvisitor.cpp index deb458e4bc6..66cfb4576fc 100644 --- a/src/libs/modelinglib/qmt/model_controller/mflatassignmentvisitor.cpp +++ b/src/libs/modelinglib/qmt/model_controller/mflatassignmentvisitor.cpp @@ -35,6 +35,7 @@ void MFlatAssignmentVisitor::visitMObject(const MObject *object) auto targetObject = dynamic_cast<MObject *>(m_target); QMT_ASSERT(targetObject, return); targetObject->setName(object->name()); + targetObject->setLinkedFileName(object->linkedFileName()); } void MFlatAssignmentVisitor::visitMPackage(const MPackage *package) diff --git a/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.cpp b/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.cpp index 28566d07ce3..11df24188db 100644 --- a/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.cpp +++ b/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.cpp @@ -454,6 +454,7 @@ void PropertiesView::MView::visitMPackage(const MPackage *package) else setTitle<MPackage>(m_modelElements, Tr::tr("Package"), Tr::tr("Packages")); visitMObject(package); + visitMObjectBehind(package); } void PropertiesView::MView::visitMClass(const MClass *klass) @@ -528,12 +529,14 @@ void PropertiesView::MView::visitMClass(const MClass *klass) } if (m_classMembersEdit->isEnabled() != isSingleSelection) m_classMembersEdit->setEnabled(isSingleSelection); + visitMObjectBehind(klass); } void PropertiesView::MView::visitMComponent(const MComponent *component) { setTitle<MComponent>(m_modelElements, Tr::tr("Component"), Tr::tr("Components")); visitMObject(component); + visitMObjectBehind(component); } void PropertiesView::MView::visitMDiagram(const MDiagram *diagram) @@ -553,6 +556,7 @@ void PropertiesView::MView::visitMCanvasDiagram(const MCanvasDiagram *diagram) { setTitle<MCanvasDiagram>(m_modelElements, Tr::tr("Canvas Diagram"), Tr::tr("Canvas Diagrams")); visitMDiagram(diagram); + visitMDiagramBehind(diagram); } void PropertiesView::MView::visitMItem(const MItem *item) @@ -577,6 +581,7 @@ void PropertiesView::MView::visitMItem(const MItem *item) if (m_itemVarietyEdit->isEnabled() != isSingleSelection) m_itemVarietyEdit->setEnabled(isSingleSelection); } + visitMObjectBehind(item); } void PropertiesView::MView::visitMRelation(const MRelation *relation) @@ -906,6 +911,7 @@ void PropertiesView::MView::visitDElement(const DElement *element) void PropertiesView::MView::visitDObject(const DObject *object) { visitDElement(object); + visitDObjectBefore(object); #ifdef SHOW_DEBUG_PROPERTIES if (!m_posRectLabel) { m_posRectLabel = new QLabel(m_topWidget); @@ -1247,6 +1253,26 @@ void PropertiesView::MView::visitDSwimlane(const DSwimlane *swimlane) visitDElement(swimlane); } +void PropertiesView::MView::visitMElementBehind(const MElement *element) +{ + Q_UNUSED(element) +} + +void PropertiesView::MView::visitMObjectBehind(const MObject *object) +{ + visitMElementBehind(object); +} + +void PropertiesView::MView::visitMDiagramBehind(const MDiagram *diagram) +{ + visitMObjectBehind(diagram); +} + +void PropertiesView::MView::visitDObjectBefore(const DObject *object) +{ + Q_UNUSED(object); +} + void PropertiesView::MView::onStereotypesChanged(const QString &stereotypes) { QList<QString> set = m_stereotypesController->fromString(stereotypes); @@ -1744,112 +1770,4 @@ void PropertiesView::MView::setRelationPrimaryRolePalette(StyleEngine::ElementTy m_relationVisualPrimaryRoleSelector->setLinePen(index, style->linePen()); } -template<class T, class V> -QList<T *> PropertiesView::MView::filter(const QList<V *> &elements) -{ - QList<T *> filtered; - for (V *element : elements) { - auto t = dynamic_cast<T *>(element); - if (t) - filtered.append(t); - } - return filtered; -} - -template<class T, class V, class BASE> -bool PropertiesView::MView::haveSameValue(const QList<BASE *> &baseElements, V (T::*getter)() const, V *value) -{ - const QList<T *> elements = filter<T>(baseElements); - QMT_CHECK(!elements.isEmpty()); - V candidate = V(); // avoid warning of reading uninitialized variable - bool haveCandidate = false; - for (T *element : elements) { - if (!haveCandidate) { - candidate = ((*element).*getter)(); - haveCandidate = true; - } else { - if (candidate != ((*element).*getter)()) - return false; - } - } - QMT_CHECK(haveCandidate); - if (!haveCandidate) - return false; - if (value) - *value = candidate; - return true; -} - -template<class T, class V, class BASE> -void PropertiesView::MView::assignModelElement(const QList<BASE *> &baseElements, SelectionType selectionType, - const V &value, V (T::*getter)() const, void (T::*setter)(const V &)) -{ - const QList<T *> elements = filter<T>(baseElements); - if ((selectionType == SelectionSingle && elements.size() == 1) || selectionType == SelectionMulti) { - for (T *element : elements) { - if (value != ((*element).*getter)()) { - m_propertiesView->beginUpdate(element); - ((*element).*setter)(value); - m_propertiesView->endUpdate(element, false); - } - } - } -} - -template<class T, class V, class BASE> -void PropertiesView::MView::assignModelElement(const QList<BASE *> &baseElements, SelectionType selectionType, - const V &value, V (T::*getter)() const, void (T::*setter)(V)) -{ - const QList<T *> elements = filter<T>(baseElements); - if ((selectionType == SelectionSingle && elements.size() == 1) || selectionType == SelectionMulti) { - for (T *element : elements) { - if (value != ((*element).*getter)()) { - m_propertiesView->beginUpdate(element); - ((*element).*setter)(value); - m_propertiesView->endUpdate(element, false); - } - } - } -} - -template<class T, class E, class V, class BASE> -void PropertiesView::MView::assignEmbeddedModelElement(const QList<BASE *> &baseElements, SelectionType selectionType, - const V &value, E (T::*getter)() const, - void (T::*setter)(const E &), - V (E::*vGetter)() const, void (E::*vSetter)(const V &)) -{ - const QList<T *> elements = filter<T>(baseElements); - if ((selectionType == SelectionSingle && elements.size() == 1) || selectionType == SelectionMulti) { - for (T *element : elements) { - E embedded = ((*element).*getter)(); - if (value != (embedded.*vGetter)()) { - m_propertiesView->beginUpdate(element); - (embedded.*vSetter)(value); - ((*element).*setter)(embedded); - m_propertiesView->endUpdate(element, false); - } - } - } -} - -template<class T, class E, class V, class BASE> -void PropertiesView::MView::assignEmbeddedModelElement(const QList<BASE *> &baseElements, SelectionType selectionType, - const V &value, E (T::*getter)() const, - void (T::*setter)(const E &), - V (E::*vGetter)() const, void (E::*vSetter)(V)) -{ - const QList<T *> elements = filter<T>(baseElements); - if ((selectionType == SelectionSingle && elements.size() == 1) || selectionType == SelectionMulti) { - for (T *element : elements) { - E embedded = ((*element).*getter)(); - if (value != (embedded.*vGetter)()) { - m_propertiesView->beginUpdate(element); - (embedded.*vSetter)(value); - ((*element).*setter)(embedded); - m_propertiesView->endUpdate(element, false); - } - } - } -} - } // namespace qmt diff --git a/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.h b/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.h index 026f4f68578..8fa9f0d1374 100644 --- a/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.h +++ b/src/libs/modelinglib/qmt/model_widgets_ui/propertiesviewmview.h @@ -78,6 +78,11 @@ public: void edit(); protected: + virtual void visitMElementBehind(const MElement *element); + virtual void visitMObjectBehind(const MObject *object); + virtual void visitMDiagramBehind(const MDiagram *diagram); + virtual void visitDObjectBefore(const DObject *object); + void onStereotypesChanged(const QString &stereotypes); void onObjectNameChanged(const QString &name); void onNamespaceChanged(const QString ¨Namespace); @@ -251,4 +256,126 @@ protected: QLabel *m_pointsLabel = nullptr; }; +template<class T, class V> +QList<T *> PropertiesView::MView::filter(const QList<V *> &elements) +{ + QList<T *> filtered; + for (auto *element : elements) { + auto t = dynamic_cast<T *>(element); + if (t) + filtered.append(t); + } + return filtered; +} + +template<class T, class V, class BASE> +inline bool PropertiesView::MView::haveSameValue(const QList<BASE *> &baseElements, V (T::*getter)() const, V *value) +{ + QList<T *> elements = filter<T>(baseElements); + QMT_CHECK(!elements.isEmpty()); + V candidate = V(); // avoid warning of reading uninitialized variable + bool haveCandidate = false; + for (const auto *element : elements) { + if (!haveCandidate) { + candidate = ((*element).*getter)(); + haveCandidate = true; + } else { + if (candidate != ((*element).*getter)()) + return false; + } + } + QMT_CHECK(haveCandidate); + if (!haveCandidate) + return false; + if (value) + *value = candidate; + return true; +} + +template<class T, class V, class BASE> +inline bool PropertiesView::MView::isValueChanged(const QList<BASE *> &baseElements, SelectionType selectionType, + const V &value, V (T::*getter)() const) +{ + QList<T *> elements = filter<T>(baseElements); + if ((selectionType == SelectionSingle && elements.size() == 1) || selectionType == SelectionMulti) { + for (const auto *element : elements) { + if (value != ((*element).*getter)()) + return true; + } + } + return false; +} + +template<class T, class V, class BASE> +inline void PropertiesView::MView::assignModelElement(const QList<BASE *> &baseElements, SelectionType selectionType, + const V &value, V (T::*getter)() const, void (T::*setter)(const V &)) +{ + QList<T *> elements = filter<T>(baseElements); + if ((selectionType == SelectionSingle && elements.size() == 1) || selectionType == SelectionMulti) { + for (auto *element : elements) { + if (value != ((*element).*getter)()) { + m_propertiesView->beginUpdate(element); + ((*element).*setter)(value); + m_propertiesView->endUpdate(element, false); + } + } + } +} + +template<class T, class V, class BASE> +inline void PropertiesView::MView::assignModelElement(const QList<BASE *> &baseElements, SelectionType selectionType, + const V &value, V (T::*getter)() const, void (T::*setter)(V)) +{ + QList<T *> elements = filter<T>(baseElements); + if ((selectionType == SelectionSingle && elements.size() == 1) || selectionType == SelectionMulti) { + for (auto *element : elements) { + if (value != ((*element).*getter)()) { + m_propertiesView->beginUpdate(element); + ((*element).*setter)(value); + m_propertiesView->endUpdate(element, false); + } + } + } +} + +template<class T, class E, class V, class BASE> +inline void PropertiesView::MView::assignEmbeddedModelElement(const QList<BASE *> &baseElements, SelectionType selectionType, + const V &value, E (T::*getter)() const, + void (T::*setter)(const E &), + V (E::*vGetter)() const, void (E::*vSetter)(const V &)) +{ + QList<T *> elements = filter<T>(baseElements); + if ((selectionType == SelectionSingle && elements.size() == 1) || selectionType == SelectionMulti) { + for (auto *element : elements) { + E embedded = ((*element).*getter)(); + if (value != (embedded.*vGetter)()) { + m_propertiesView->beginUpdate(element); + (embedded.*vSetter)(value); + ((*element).*setter)(embedded); + m_propertiesView->endUpdate(element, false); + } + } + } +} + +template<class T, class E, class V, class BASE> +inline void PropertiesView::MView::assignEmbeddedModelElement(const QList<BASE *> &baseElements, SelectionType selectionType, + const V &value, E (T::*getter)() const, + void (T::*setter)(const E &), + V (E::*vGetter)() const, void (E::*vSetter)(V)) +{ + QList<T *> elements = filter<T>(baseElements); + if ((selectionType == SelectionSingle && elements.size() == 1) || selectionType == SelectionMulti) { + for (auto *element : elements) { + E embedded = ((*element).*getter)(); + if (value != (embedded.*vGetter)()) { + m_propertiesView->beginUpdate(element); + (embedded.*vSetter)(value); + ((*element).*setter)(embedded); + m_propertiesView->endUpdate(element, false); + } + } + } +} + } // namespace qmt diff --git a/src/libs/modelinglib/qmt/serializer/diagramserializer.cpp b/src/libs/modelinglib/qmt/serializer/diagramserializer.cpp index 5121a51f3d2..2d68862c32f 100644 --- a/src/libs/modelinglib/qmt/serializer/diagramserializer.cpp +++ b/src/libs/modelinglib/qmt/serializer/diagramserializer.cpp @@ -29,10 +29,35 @@ #include "qark/qxmlinarchive.h" #include "qark/serialize.h" +#include <QBuffer> + using namespace qmt; namespace qark { +template<class Archive> +inline void save(Archive &archive, const QImage &image) +{ + QByteArray a; + QBuffer buffer(&a); + buffer.open(QIODevice::WriteOnly); + image.save(&buffer, "PNG"); + // TODO add write(const QByteArray &) + archive.write(QString::fromLatin1(a.toBase64())); +} + +template<class Archive> +inline void load(Archive &archive, QImage &image) +{ + QString s; + // TODO add read(QByteArray &) + archive.read(&s); + QByteArray a = QByteArray::fromBase64(s.toLatin1()); + QBuffer buffer(&a); + buffer.open(QIODevice::ReadOnly); + image.load(&buffer, "PNG"); +} + // DElement QARK_REGISTER_TYPE_NAME(DElement, "DElement") @@ -102,7 +127,10 @@ inline void Access<Archive, DObject>::serialize(Archive &archive, DObject &objec || attr("visual-role", object, &visualRole, &setVisualRole) || attr("visual-role2", object, &DObject::visualSecondaryRole, &DObject::setVisualSecondaryRole) || attr("visual-emphasized", object, &DObject::isVisualEmphasized, &DObject::setVisualEmphasized) + || attr("linkedfile", object, &DObject::hasLinkedFile, &DObject::setLinkedFile) || attr("stereotype-display", object, &DObject::stereotypeDisplay, &DObject::setStereotypeDisplay) + || attr("image-path", object, &DObject::imagePath, &DObject::setImagePath) + || attr("image", object, &DObject::image, &DObject::setImage) // depth is not persistent || end; } diff --git a/src/libs/modelinglib/qmt/serializer/modelserializer.cpp b/src/libs/modelinglib/qmt/serializer/modelserializer.cpp index 115eba08d0e..935a825ab27 100644 --- a/src/libs/modelinglib/qmt/serializer/modelserializer.cpp +++ b/src/libs/modelinglib/qmt/serializer/modelserializer.cpp @@ -95,6 +95,7 @@ inline void Access<Archive, MObject>::serialize(Archive &archive, MObject &objec archive || tag(object) || base<MElement>(object) || attr("name", object, &MObject::name, &MObject::setName) + || attr("linkedfilename", object, &MObject::linkedFileName, &MObject::setLinkedFileName) || attr("children", object, &MObject::children, &MObject::setChildren) || attr("relations", object, &MObject::relations, &MObject::setRelations) || end; diff --git a/src/libs/modelinglib/qmt/tasks/ielementtasks.h b/src/libs/modelinglib/qmt/tasks/ielementtasks.h index a40277d8749..8c226327626 100644 --- a/src/libs/modelinglib/qmt/tasks/ielementtasks.h +++ b/src/libs/modelinglib/qmt/tasks/ielementtasks.h @@ -59,8 +59,13 @@ public: virtual void createAndOpenDiagram(const MElement *) = 0; virtual void createAndOpenDiagram(const DElement *, const MDiagram *) = 0; + virtual bool hasLinkedFile(const MElement *) const = 0; + virtual bool hasLinkedFile(const DElement *, const MDiagram *) const = 0; + virtual void openLinkedFile(const MElement *) = 0; + virtual void openLinkedFile(const DElement *, const MDiagram *) = 0; + virtual bool extendContextMenu(const DElement *, const MDiagram *, QMenu *) = 0; - virtual bool handleContextMenuAction(const DElement *, const MDiagram *, const QString &) = 0; + virtual bool handleContextMenuAction(DElement *, MDiagram *, const QString &) = 0; }; } // namespace qmt diff --git a/src/libs/modelinglib/qmt/tasks/voidelementtasks.cpp b/src/libs/modelinglib/qmt/tasks/voidelementtasks.cpp index 2bd7fbe0499..fdc2e24bd4e 100644 --- a/src/libs/modelinglib/qmt/tasks/voidelementtasks.cpp +++ b/src/libs/modelinglib/qmt/tasks/voidelementtasks.cpp @@ -147,12 +147,30 @@ void VoidElementTasks::createAndOpenDiagram(const DElement *, const MDiagram *) { } +bool VoidElementTasks::hasLinkedFile(const MElement *) const +{ + return false; +} + +bool VoidElementTasks::hasLinkedFile(const DElement *, const MDiagram *) const +{ + return false; +} + +void VoidElementTasks::openLinkedFile(const MElement *) +{ +} + +void VoidElementTasks::openLinkedFile(const DElement *, const MDiagram *) +{ +} + bool VoidElementTasks::extendContextMenu(const DElement *, const MDiagram *, QMenu *) { return false; } -bool VoidElementTasks::handleContextMenuAction(const DElement *, const MDiagram *, const QString &) +bool VoidElementTasks::handleContextMenuAction(DElement *, MDiagram *, const QString &) { return false; } diff --git a/src/libs/modelinglib/qmt/tasks/voidelementtasks.h b/src/libs/modelinglib/qmt/tasks/voidelementtasks.h index 3e3d483d9ae..9e8753b71e0 100644 --- a/src/libs/modelinglib/qmt/tasks/voidelementtasks.h +++ b/src/libs/modelinglib/qmt/tasks/voidelementtasks.h @@ -51,8 +51,13 @@ public: void createAndOpenDiagram(const MElement *) override; void createAndOpenDiagram(const DElement *, const MDiagram *) override; + bool hasLinkedFile(const qmt::MElement *) const override; + bool hasLinkedFile(const qmt::DElement *, const qmt::MDiagram *) const override; + void openLinkedFile(const qmt::MElement *) override; + void openLinkedFile(const qmt::DElement *, const qmt::MDiagram *) override; + bool extendContextMenu(const DElement *, const MDiagram *, QMenu *) override; - bool handleContextMenuAction(const DElement *, const MDiagram *, const QString &) override; + bool handleContextMenuAction(DElement *, MDiagram *, const QString &) override; }; } // namespace qmt |