forked from qt-creator/qt-creator
ModelEditor: Show relation templates in object toolbars
Change-Id: I06de22538e500c133693ff0c791ac8a2d3be3402 Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
This commit is contained in:
@@ -38,6 +38,7 @@
|
||||
#include "qmt/diagram/drelation.h"
|
||||
#include "qmt/diagram_controller/diagramcontroller.h"
|
||||
#include "qmt/diagram_controller/dselection.h"
|
||||
#include "qmt/diagram_scene/items/objectitem.h"
|
||||
#include "qmt/model/mdiagram.h"
|
||||
#include "qmt/model/mobject.h"
|
||||
#include "qmt/model/mpackage.h"
|
||||
@@ -229,17 +230,25 @@ DElement *DiagramSceneModel::findTopmostElement(const QPointF &scenePos) const
|
||||
}
|
||||
|
||||
DObject *DiagramSceneModel::findTopmostObject(const QPointF &scenePos) const
|
||||
{
|
||||
ObjectItem *item = findTopmostObjectItem(scenePos);
|
||||
if (!item)
|
||||
return nullptr;
|
||||
return item->object();
|
||||
}
|
||||
|
||||
ObjectItem *DiagramSceneModel::findTopmostObjectItem(const QPointF &scenePos) const
|
||||
{
|
||||
// fetch affected items from scene in correct drawing order to find topmost element
|
||||
QList<QGraphicsItem *> items = m_graphicsScene->items(scenePos);
|
||||
foreach (QGraphicsItem *item, items) {
|
||||
const QList<QGraphicsItem *> items = m_graphicsScene->items(scenePos);
|
||||
for (QGraphicsItem *item : items) {
|
||||
if (m_graphicsItems.contains(item)) {
|
||||
DObject *object = dynamic_cast<DObject *>(m_itemToElementMap.value(item));
|
||||
if (object)
|
||||
return object;
|
||||
return dynamic_cast<ObjectItem *>(item);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QGraphicsItem *DiagramSceneModel::graphicsItem(DElement *element) const
|
||||
|
@@ -54,6 +54,7 @@ class DSelection;
|
||||
class MDiagram;
|
||||
class DElement;
|
||||
class DObject;
|
||||
class ObjectItem;
|
||||
|
||||
class QMT_EXPORT DiagramSceneModel : public QObject
|
||||
{
|
||||
@@ -98,6 +99,7 @@ public:
|
||||
DSelection selectedElements() const;
|
||||
DElement *findTopmostElement(const QPointF &scenePos) const;
|
||||
DObject *findTopmostObject(const QPointF &scenePos) const;
|
||||
ObjectItem *findTopmostObjectItem(const QPointF &scenePos) const;
|
||||
|
||||
QList<QGraphicsItem *> graphicsItems() const { return m_graphicsItems; }
|
||||
QGraphicsItem *graphicsItem(DElement *element) const;
|
||||
|
@@ -40,6 +40,7 @@
|
||||
#include "qmt/infrastructure/qmtassert.h"
|
||||
#include "qmt/model/mclass.h"
|
||||
#include "qmt/model/mclassmember.h"
|
||||
#include "qmt/model/massociation.h"
|
||||
#include "qmt/model_controller/modelcontroller.h"
|
||||
#include "qmt/stereotype/stereotypecontroller.h"
|
||||
#include "qmt/stereotype/stereotypeicon.h"
|
||||
@@ -59,15 +60,20 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <qmt/stereotype/customrelation.h>
|
||||
|
||||
namespace qmt {
|
||||
|
||||
static const char ASSOCIATION[] = "association";
|
||||
static const char INHERITANCE[] = "inheritance";
|
||||
|
||||
static const qreal MINIMUM_AUTO_WIDTH = 80.0;
|
||||
static const qreal MINIMUM_AUTO_HEIGHT = 60.0;
|
||||
static const qreal BODY_VERT_BORDER = 4.0;
|
||||
static const qreal BODY_HORIZ_BORDER = 4.0;
|
||||
|
||||
ClassItem::ClassItem(DClass *klass, DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent)
|
||||
: ObjectItem(klass, diagramSceneModel, parent)
|
||||
: ObjectItem(QStringLiteral("class"), klass, diagramSceneModel, parent)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -247,30 +253,83 @@ QSizeF ClassItem::minimumSize() const
|
||||
return calcMinimumGeometry();
|
||||
}
|
||||
|
||||
void ClassItem::relationDrawn(const QString &id, const QPointF &toScenePos, const QList<QPointF> &intermediatePoints)
|
||||
void ClassItem::relationDrawn(const QString &id, ObjectItem *targetItem, const QList<QPointF> &intermediatePoints)
|
||||
{
|
||||
DElement *targetElement = diagramSceneModel()->findTopmostElement(toScenePos);
|
||||
if (targetElement) {
|
||||
if (id == QLatin1String("inheritance")) {
|
||||
auto baseClass = dynamic_cast<DClass *>(targetElement);
|
||||
if (baseClass) {
|
||||
auto derivedClass = dynamic_cast<DClass *>(object());
|
||||
QMT_ASSERT(derivedClass, return);
|
||||
diagramSceneModel()->diagramSceneController()->createInheritance(derivedClass, baseClass, intermediatePoints, diagramSceneModel()->diagram());
|
||||
DiagramSceneController *diagramSceneController = diagramSceneModel()->diagramSceneController();
|
||||
if (id == INHERITANCE) {
|
||||
auto baseClass = dynamic_cast<DClass *>(targetItem->object());
|
||||
if (baseClass) {
|
||||
auto derivedClass = dynamic_cast<DClass *>(object());
|
||||
QMT_ASSERT(derivedClass, return);
|
||||
diagramSceneController->createInheritance(derivedClass, baseClass, intermediatePoints, diagramSceneModel()->diagram());
|
||||
}
|
||||
return;
|
||||
} else if (id == ASSOCIATION) {
|
||||
auto associatedClass = dynamic_cast<DClass *>(targetItem->object());
|
||||
if (associatedClass) {
|
||||
auto derivedClass = dynamic_cast<DClass *>(object());
|
||||
QMT_ASSERT(derivedClass, return);
|
||||
diagramSceneController->createAssociation(derivedClass, associatedClass, intermediatePoints, diagramSceneModel()->diagram());
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
StereotypeController *stereotypeController = diagramSceneModel()->stereotypeController();
|
||||
CustomRelation customRelation = stereotypeController->findCustomRelation(id);
|
||||
if (!customRelation.isNull()) {
|
||||
switch (customRelation.element()) {
|
||||
case CustomRelation::Element::Inheritance:
|
||||
{
|
||||
auto baseClass = dynamic_cast<DClass *>(targetItem->object());
|
||||
if (baseClass) {
|
||||
auto derivedClass = dynamic_cast<DClass *>(object());
|
||||
QMT_ASSERT(derivedClass, return);
|
||||
diagramSceneController->createInheritance(derivedClass, baseClass, intermediatePoints, diagramSceneModel()->diagram());
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else if (id == QLatin1String("dependency")) {
|
||||
auto dependantObject = dynamic_cast<DObject *>(targetElement);
|
||||
if (dependantObject)
|
||||
diagramSceneModel()->diagramSceneController()->createDependency(object(), dependantObject, intermediatePoints, diagramSceneModel()->diagram());
|
||||
} else if (id == QLatin1String("association")) {
|
||||
auto assoziatedClass = dynamic_cast<DClass *>(targetElement);
|
||||
if (assoziatedClass) {
|
||||
auto derivedClass = dynamic_cast<DClass *>(object());
|
||||
QMT_ASSERT(derivedClass, return);
|
||||
diagramSceneModel()->diagramSceneController()->createAssociation(derivedClass, assoziatedClass, intermediatePoints, diagramSceneModel()->diagram());
|
||||
case CustomRelation::Element::Association:
|
||||
{
|
||||
auto assoziatedClass = dynamic_cast<DClass *>(targetItem->object());
|
||||
if (assoziatedClass) {
|
||||
auto derivedClass = dynamic_cast<DClass *>(object());
|
||||
QMT_ASSERT(derivedClass, return);
|
||||
diagramSceneController->createAssociation(
|
||||
derivedClass, assoziatedClass, intermediatePoints, diagramSceneModel()->diagram(),
|
||||
[=] (MAssociation *mAssociation, DAssociation *dAssociation) {
|
||||
if (mAssociation && dAssociation) {
|
||||
static const QHash<CustomRelation::Relationship, MAssociationEnd::Kind> relationship2KindMap = {
|
||||
{ CustomRelation::Relationship::Association, MAssociationEnd::Association },
|
||||
{ CustomRelation::Relationship::Aggregation, MAssociationEnd::Aggregation },
|
||||
{ CustomRelation::Relationship::Composition, MAssociationEnd::Composition } };
|
||||
diagramSceneController->modelController()->startUpdateRelation(mAssociation);
|
||||
mAssociation->setStereotypes(customRelation.stereotypes().toList());
|
||||
mAssociation->setName(customRelation.name());
|
||||
MAssociationEnd endA;
|
||||
endA.setCardinality(customRelation.endA().cardinality());
|
||||
endA.setKind(relationship2KindMap.value(customRelation.endA().relationship()));
|
||||
endA.setName(customRelation.endA().role());
|
||||
endA.setNavigable(customRelation.endA().navigable());
|
||||
mAssociation->setEndA(endA);
|
||||
MAssociationEnd endB;
|
||||
endB.setCardinality(customRelation.endB().cardinality());
|
||||
endB.setKind(relationship2KindMap.value(customRelation.endB().relationship()));
|
||||
endB.setName(customRelation.endB().role());
|
||||
endB.setNavigable(customRelation.endB().navigable());
|
||||
mAssociation->setEndB(endB);
|
||||
diagramSceneController->modelController()->finishUpdateRelation(mAssociation, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
case CustomRelation::Element::Dependency:
|
||||
case CustomRelation::Element::Relation:
|
||||
// fall thru
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ObjectItem::relationDrawn(id, targetItem, intermediatePoints);
|
||||
}
|
||||
|
||||
bool ClassItem::extendContextMenu(QMenu *menu)
|
||||
@@ -338,11 +397,64 @@ void ClassItem::setFromDisplayName(const QString &displayName)
|
||||
}
|
||||
}
|
||||
|
||||
void ClassItem::updateRelationStarterTools(RelationStarter *relationStarter)
|
||||
void ClassItem::addRelationStarterTool(const QString &id)
|
||||
{
|
||||
relationStarter->addArrow("dependency", ArrowItem::ShaftDashed, ArrowItem::HeadOpen);
|
||||
relationStarter->addArrow("inheritance", ArrowItem::ShaftSolid, ArrowItem::HeadTriangle);
|
||||
relationStarter->addArrow("association", ArrowItem::ShaftSolid, ArrowItem::HeadFilledTriangle);
|
||||
if (id == INHERITANCE)
|
||||
relationStarter()->addArrow(INHERITANCE, ArrowItem::ShaftSolid,
|
||||
ArrowItem::HeadNone, ArrowItem::HeadTriangle,
|
||||
tr("Inheritance"));
|
||||
else if (id == ASSOCIATION)
|
||||
relationStarter()->addArrow(ASSOCIATION, ArrowItem::ShaftSolid,
|
||||
ArrowItem::HeadNone, ArrowItem::HeadFilledTriangle,
|
||||
tr("Association"));
|
||||
else
|
||||
ObjectItem::addRelationStarterTool(id);
|
||||
}
|
||||
|
||||
void ClassItem::addRelationStarterTool(const CustomRelation &customRelation)
|
||||
{
|
||||
ArrowItem::Shaft shaft = ArrowItem::ShaftSolid;
|
||||
ArrowItem::Head headStart = ArrowItem::HeadNone;
|
||||
ArrowItem::Head headEnd = ArrowItem::HeadNone;
|
||||
switch (customRelation.element()) {
|
||||
case CustomRelation::Element::Inheritance:
|
||||
shaft = ArrowItem::ShaftSolid;
|
||||
headEnd = ArrowItem::HeadTriangle;
|
||||
break;
|
||||
case CustomRelation::Element::Association:
|
||||
switch (customRelation.endA().relationship()) {
|
||||
case CustomRelation::Relationship::Association:
|
||||
if (customRelation.endA().navigable() && customRelation.endB().navigable()) {
|
||||
headStart = ArrowItem::HeadNone;
|
||||
headEnd = ArrowItem::HeadNone;
|
||||
} else if (customRelation.endA().navigable()) {
|
||||
headStart = ArrowItem::HeadFilledTriangle;
|
||||
} else {
|
||||
headEnd = ArrowItem::HeadFilledTriangle;
|
||||
}
|
||||
break;
|
||||
case CustomRelation::Relationship::Aggregation:
|
||||
headStart = ArrowItem::HeadDiamond;
|
||||
break;
|
||||
case CustomRelation::Relationship::Composition:
|
||||
headStart = ArrowItem::HeadFilledDiamond;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case CustomRelation::Element::Dependency:
|
||||
case CustomRelation::Element::Relation:
|
||||
ObjectItem::addRelationStarterTool(customRelation);
|
||||
return;
|
||||
}
|
||||
relationStarter()->addArrow(customRelation.id(), shaft, headStart, headEnd,
|
||||
customRelation.title());
|
||||
}
|
||||
|
||||
void ClassItem::addStandardRelationStarterTools()
|
||||
{
|
||||
ObjectItem::addStandardRelationStarterTools();
|
||||
addRelationStarterTool(INHERITANCE);
|
||||
addRelationStarterTool(ASSOCIATION);
|
||||
}
|
||||
|
||||
DClass::TemplateDisplay ClassItem::templateDisplay() const
|
||||
|
@@ -59,7 +59,7 @@ public:
|
||||
|
||||
QSizeF minimumSize() const override;
|
||||
|
||||
void relationDrawn(const QString &id, const QPointF &toScenePos,
|
||||
void relationDrawn(const QString &id, ObjectItem *targetElement,
|
||||
const QList<QPointF> &intermediatePoints) override;
|
||||
|
||||
protected:
|
||||
@@ -67,7 +67,9 @@ protected:
|
||||
bool handleSelectedContextMenuAction(const QString &id) override;
|
||||
QString buildDisplayName() const override;
|
||||
void setFromDisplayName(const QString &displayName) override;
|
||||
void updateRelationStarterTools(RelationStarter *relationStarter) override;
|
||||
void addRelationStarterTool(const QString &id) override;
|
||||
void addRelationStarterTool(const CustomRelation &customRelation) override;
|
||||
void addStandardRelationStarterTools() override;
|
||||
|
||||
private:
|
||||
DClass::TemplateDisplay templateDisplay() const;
|
||||
|
@@ -32,7 +32,6 @@
|
||||
#include "qmt/diagram_scene/parts/contextlabelitem.h"
|
||||
#include "qmt/diagram_scene/parts/customiconitem.h"
|
||||
#include "qmt/diagram_scene/parts/editabletextitem.h"
|
||||
#include "qmt/diagram_scene/parts/relationstarter.h"
|
||||
#include "qmt/diagram_scene/parts/stereotypesitem.h"
|
||||
#include "qmt/infrastructure/geometryutilities.h"
|
||||
#include "qmt/infrastructure/qmtassert.h"
|
||||
@@ -61,7 +60,7 @@ static const qreal BODY_VERT_BORDER = 4.0;
|
||||
static const qreal BODY_HORIZ_BORDER = 4.0;
|
||||
|
||||
ComponentItem::ComponentItem(DComponent *component, DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent)
|
||||
: ObjectItem(component, diagramSceneModel, parent)
|
||||
: ObjectItem(QStringLiteral("component"), component, diagramSceneModel, parent)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -154,22 +153,7 @@ void ComponentItem::update()
|
||||
}
|
||||
|
||||
updateSelectionMarker(m_customIcon);
|
||||
|
||||
// relation starters
|
||||
if (isFocusSelected()) {
|
||||
if (!m_relationStarter && scene()) {
|
||||
m_relationStarter = new RelationStarter(this, diagramSceneModel(), 0);
|
||||
scene()->addItem(m_relationStarter);
|
||||
m_relationStarter->setZValue(RELATION_STARTER_ZVALUE);
|
||||
m_relationStarter->addArrow(QStringLiteral("dependency"), ArrowItem::ShaftDashed, ArrowItem::HeadOpen);
|
||||
}
|
||||
} else if (m_relationStarter) {
|
||||
if (m_relationStarter->scene())
|
||||
m_relationStarter->scene()->removeItem(m_relationStarter);
|
||||
delete m_relationStarter;
|
||||
m_relationStarter = 0;
|
||||
}
|
||||
|
||||
updateRelationStarter();
|
||||
updateAlignmentButtons();
|
||||
updateGeometry();
|
||||
}
|
||||
@@ -344,10 +328,7 @@ void ComponentItem::updateGeometry()
|
||||
}
|
||||
|
||||
updateSelectionMarkerGeometry(rect);
|
||||
|
||||
if (m_relationStarter)
|
||||
m_relationStarter->setPos(mapToScene(QPointF(right + 8.0, top)));
|
||||
|
||||
updateRelationStarterGeometry(rect);
|
||||
updateAlignmentButtonsGeometry(rect);
|
||||
updateDepth();
|
||||
}
|
||||
|
@@ -68,7 +68,6 @@ private:
|
||||
QGraphicsRectItem *m_upperRect = 0;
|
||||
QGraphicsRectItem *m_lowerRect = 0;
|
||||
ContextLabelItem *m_contextLabel = 0;
|
||||
RelationStarter *m_relationStarter = 0;
|
||||
};
|
||||
|
||||
} // namespace qmt
|
||||
|
@@ -54,7 +54,7 @@ static const qreal BODY_HORIZ_BORDER = 4.0;
|
||||
static const qreal BODY_VERT_BORDER = 4.0;
|
||||
|
||||
DiagramItem::DiagramItem(DDiagram *diagram, DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent)
|
||||
: ObjectItem(diagram, diagramSceneModel, parent)
|
||||
: ObjectItem(QStringLiteral("diagram"), diagram, diagramSceneModel, parent)
|
||||
{
|
||||
}
|
||||
|
||||
|
@@ -32,7 +32,6 @@
|
||||
#include "qmt/diagram_scene/parts/contextlabelitem.h"
|
||||
#include "qmt/diagram_scene/parts/customiconitem.h"
|
||||
#include "qmt/diagram_scene/parts/editabletextitem.h"
|
||||
#include "qmt/diagram_scene/parts/relationstarter.h"
|
||||
#include "qmt/diagram_scene/parts/stereotypesitem.h"
|
||||
#include "qmt/infrastructure/geometryutilities.h"
|
||||
#include "qmt/infrastructure/qmtassert.h"
|
||||
@@ -56,7 +55,7 @@ static const qreal BODY_VERT_BORDER = 4.0;
|
||||
static const qreal BODY_HORIZ_BORDER = 4.0;
|
||||
|
||||
ItemItem::ItemItem(DItem *item, DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent)
|
||||
: ObjectItem(item, diagramSceneModel, parent)
|
||||
: ObjectItem(QStringLiteral("item"), item, diagramSceneModel, parent)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -124,22 +123,7 @@ void ItemItem::update()
|
||||
}
|
||||
|
||||
updateSelectionMarker(m_customIcon);
|
||||
|
||||
// relation starters
|
||||
if (isFocusSelected()) {
|
||||
if (!m_relationStarter && scene()) {
|
||||
m_relationStarter = new RelationStarter(this, diagramSceneModel(), 0);
|
||||
scene()->addItem(m_relationStarter);
|
||||
m_relationStarter->setZValue(RELATION_STARTER_ZVALUE);
|
||||
m_relationStarter->addArrow(QStringLiteral("dependency"), ArrowItem::ShaftDashed, ArrowItem::HeadOpen);
|
||||
}
|
||||
} else if (m_relationStarter) {
|
||||
if (m_relationStarter->scene())
|
||||
m_relationStarter->scene()->removeItem(m_relationStarter);
|
||||
delete m_relationStarter;
|
||||
m_relationStarter = 0;
|
||||
}
|
||||
|
||||
updateRelationStarter();
|
||||
updateAlignmentButtons();
|
||||
updateGeometry();
|
||||
}
|
||||
@@ -277,10 +261,7 @@ void ItemItem::updateGeometry()
|
||||
}
|
||||
|
||||
updateSelectionMarkerGeometry(rect);
|
||||
|
||||
if (m_relationStarter)
|
||||
m_relationStarter->setPos(mapToScene(QPointF(right + 8.0, top)));
|
||||
|
||||
updateRelationStarterGeometry(rect);
|
||||
updateAlignmentButtonsGeometry(rect);
|
||||
updateDepth();
|
||||
}
|
||||
|
@@ -64,7 +64,6 @@ private:
|
||||
CustomIconItem *m_customIcon = 0;
|
||||
QGraphicsRectItem *m_shape = 0;
|
||||
ContextLabelItem *m_contextLabel = 0;
|
||||
RelationStarter *m_relationStarter = 0;
|
||||
};
|
||||
|
||||
} // namespace qmt
|
||||
|
@@ -42,7 +42,9 @@
|
||||
#include "qmt/model/mdiagram.h"
|
||||
#include "qmt/model/mobject.h"
|
||||
#include "qmt/model_controller/modelcontroller.h"
|
||||
#include "qmt/stereotype/customrelation.h"
|
||||
#include "qmt/stereotype/stereotypecontroller.h"
|
||||
#include "qmt/stereotype/toolbar.h"
|
||||
#include "qmt/style/style.h"
|
||||
#include "qmt/style/stylecontroller.h"
|
||||
#include "qmt/style/styledobject.h"
|
||||
@@ -58,8 +60,12 @@
|
||||
|
||||
namespace qmt {
|
||||
|
||||
ObjectItem::ObjectItem(DObject *object, DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent)
|
||||
static const char DEPENDENCY[] = "dependency";
|
||||
|
||||
|
||||
ObjectItem::ObjectItem(const QString &elementType, DObject *object, DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent)
|
||||
: QGraphicsItem(parent),
|
||||
m_elementType(elementType),
|
||||
m_object(object),
|
||||
m_diagramSceneModel(diagramSceneModel)
|
||||
{
|
||||
@@ -309,12 +315,58 @@ QPointF ObjectItem::relationStartPos() const
|
||||
|
||||
void ObjectItem::relationDrawn(const QString &id, const QPointF &toScenePos, const QList<QPointF> &intermediatePoints)
|
||||
{
|
||||
DElement *targetElement = diagramSceneModel()->findTopmostElement(toScenePos);
|
||||
if (targetElement) {
|
||||
if (id == QLatin1String("dependency")) {
|
||||
auto dependantObject = dynamic_cast<DObject *>(targetElement);
|
||||
if (dependantObject)
|
||||
diagramSceneModel()->diagramSceneController()->createDependency(object(), dependantObject, intermediatePoints, diagramSceneModel()->diagram());
|
||||
ObjectItem *targetItem = diagramSceneModel()->findTopmostObjectItem(toScenePos);
|
||||
if (targetItem)
|
||||
relationDrawn(id, targetItem, intermediatePoints);
|
||||
}
|
||||
|
||||
void ObjectItem::relationDrawn(const QString &id, ObjectItem *targetItem, const QList<QPointF> &intermediatePoints)
|
||||
{
|
||||
DiagramSceneController *diagramSceneController = diagramSceneModel()->diagramSceneController();
|
||||
if (id == DEPENDENCY) {
|
||||
DObject *dependantObject = targetItem->object();
|
||||
if (dependantObject)
|
||||
diagramSceneController->createDependency(object(), dependantObject, intermediatePoints,
|
||||
diagramSceneModel()->diagram());
|
||||
} else {
|
||||
StereotypeController *stereotypeController = diagramSceneModel()->stereotypeController();
|
||||
CustomRelation customRelation = stereotypeController->findCustomRelation(id);
|
||||
if (!customRelation.isNull()) {
|
||||
switch (customRelation.element()) {
|
||||
case CustomRelation::Element::Dependency:
|
||||
{
|
||||
DObject *dependantObject = targetItem->object();
|
||||
if (dependantObject)
|
||||
diagramSceneController->createDependency(object(), dependantObject, intermediatePoints,
|
||||
diagramSceneModel()->diagram());
|
||||
break;
|
||||
}
|
||||
case CustomRelation::Element::Relation:
|
||||
{
|
||||
DObject *relatedObject = targetItem->object();
|
||||
if (relatedObject) {
|
||||
// check if element is allowed as target
|
||||
QList<QString> endItems = customRelation.endB().endItems();
|
||||
if (endItems.isEmpty())
|
||||
endItems = customRelation.endItems();
|
||||
QString elementType;
|
||||
if (!targetItem->stereotypeIconId().isEmpty())
|
||||
elementType = targetItem->stereotypeIconId();
|
||||
else if (!targetItem->shapeIconId().isEmpty())
|
||||
elementType = targetItem->shapeIconId();
|
||||
else
|
||||
elementType = targetItem->elementType();
|
||||
if (!endItems.contains(elementType)) {
|
||||
return;
|
||||
}
|
||||
// create relation
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// ignore other elements
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -594,7 +646,29 @@ void ObjectItem::updateRelationStarter()
|
||||
m_relationStarter = new RelationStarter(this, diagramSceneModel(), 0);
|
||||
scene()->addItem(m_relationStarter);
|
||||
m_relationStarter->setZValue(RELATION_STARTER_ZVALUE);
|
||||
updateRelationStarterTools(m_relationStarter);
|
||||
QString elementType;
|
||||
if (!m_stereotypeIconId.isEmpty())
|
||||
elementType = m_stereotypeIconId;
|
||||
else if (!m_shapeIconId.isEmpty())
|
||||
elementType = m_shapeIconId;
|
||||
else
|
||||
elementType = m_elementType;
|
||||
StereotypeController *stereotypeController = diagramSceneModel()->stereotypeController();
|
||||
QList<Toolbar> toolbars = stereotypeController->findToolbars(elementType);
|
||||
if (!toolbars.isEmpty()) {
|
||||
foreach (const Toolbar &toolbar, toolbars) {
|
||||
foreach (const Toolbar::Tool &tool, toolbar.tools()) {
|
||||
CustomRelation customRelation =
|
||||
stereotypeController->findCustomRelation(tool.m_elementType);
|
||||
if (!customRelation.isNull())
|
||||
addRelationStarterTool(customRelation);
|
||||
else
|
||||
addRelationStarterTool(tool.m_elementType);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
addStandardRelationStarterTools();
|
||||
}
|
||||
}
|
||||
} else if (m_relationStarter) {
|
||||
scene()->removeItem(m_relationStarter);
|
||||
@@ -604,9 +678,71 @@ void ObjectItem::updateRelationStarter()
|
||||
|
||||
}
|
||||
|
||||
void ObjectItem::updateRelationStarterTools(RelationStarter *relationStarter)
|
||||
void ObjectItem::addRelationStarterTool(const QString &id)
|
||||
{
|
||||
relationStarter->addArrow(QLatin1String("dependency"), ArrowItem::ShaftDashed, ArrowItem::HeadOpen);
|
||||
if (id == DEPENDENCY)
|
||||
m_relationStarter->addArrow(DEPENDENCY, ArrowItem::ShaftDashed,
|
||||
ArrowItem::HeadNone, ArrowItem::HeadOpen,
|
||||
tr("Dependency"));
|
||||
}
|
||||
|
||||
void ObjectItem::addRelationStarterTool(const CustomRelation &customRelation)
|
||||
{
|
||||
ArrowItem::Shaft shaft = ArrowItem::ShaftSolid;
|
||||
ArrowItem::Head headStart = ArrowItem::HeadNone;
|
||||
ArrowItem::Head headEnd = ArrowItem::HeadNone;
|
||||
switch (customRelation.element()) {
|
||||
case CustomRelation::Element::Dependency:
|
||||
shaft = ArrowItem::ShaftDashed;
|
||||
switch (customRelation.direction()) {
|
||||
case CustomRelation::Direction::AtoB:
|
||||
headEnd = ArrowItem::HeadOpen;
|
||||
break;
|
||||
case CustomRelation::Direction::BToA:
|
||||
headStart = ArrowItem::HeadOpen;
|
||||
break;
|
||||
case CustomRelation::Direction::Bi:
|
||||
headStart = ArrowItem::HeadOpen;
|
||||
headEnd = ArrowItem::HeadOpen;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case CustomRelation::Element::Relation:
|
||||
{
|
||||
// TODO support custom shapes
|
||||
static const QHash<CustomRelation::ShaftPattern, ArrowItem::Shaft> shaft2shaft = {
|
||||
{ CustomRelation::ShaftPattern::Solid, ArrowItem::ShaftSolid },
|
||||
{ CustomRelation::ShaftPattern::Dash, ArrowItem::ShaftDashed },
|
||||
{ CustomRelation::ShaftPattern::Dot, ArrowItem::ShaftDot },
|
||||
{ CustomRelation::ShaftPattern::DashDot, ArrowItem::ShaftDashDot },
|
||||
{ CustomRelation::ShaftPattern::DashDotDot, ArrowItem::ShaftDashDotDot },
|
||||
};
|
||||
static const QHash<CustomRelation::Head, ArrowItem::Head> head2head = {
|
||||
{ CustomRelation::Head::None, ArrowItem::HeadNone },
|
||||
{ CustomRelation::Head::Shape, ArrowItem::HeadNone },
|
||||
{ CustomRelation::Head::Arrow, ArrowItem::HeadOpen },
|
||||
{ CustomRelation::Head::Triangle, ArrowItem::HeadTriangle },
|
||||
{ CustomRelation::Head::FilledTriangle, ArrowItem::HeadFilledTriangle },
|
||||
{ CustomRelation::Head::Diamond, ArrowItem::HeadDiamond },
|
||||
{ CustomRelation::Head::FilledDiamond, ArrowItem::HeadFilledDiamond },
|
||||
};
|
||||
shaft = shaft2shaft.value(customRelation.shaftPattern());
|
||||
headStart = head2head.value(customRelation.endA().head());
|
||||
headEnd = head2head.value(customRelation.endB().head());
|
||||
// TODO use color?
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
m_relationStarter->addArrow(customRelation.id(), shaft, headStart, headEnd,
|
||||
customRelation.title());
|
||||
|
||||
}
|
||||
|
||||
void ObjectItem::addStandardRelationStarterTools()
|
||||
{
|
||||
addRelationStarterTool(DEPENDENCY);
|
||||
}
|
||||
|
||||
void ObjectItem::updateRelationStarterGeometry(const QRectF &objectRect)
|
||||
|
@@ -46,10 +46,12 @@ QT_END_NAMESPACE
|
||||
|
||||
namespace qmt {
|
||||
|
||||
class DElement;
|
||||
class DObject;
|
||||
class DiagramSceneModel;
|
||||
class StereotypesItem;
|
||||
class CustomIconItem;
|
||||
class CustomRelation;
|
||||
class EditableTextItem;
|
||||
class RectangularSelectionItem;
|
||||
class RelationStarter;
|
||||
@@ -84,9 +86,10 @@ protected:
|
||||
};
|
||||
|
||||
public:
|
||||
ObjectItem(DObject *object, DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent = 0);
|
||||
ObjectItem(const QString &elementType, DObject *object, DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent = 0);
|
||||
~ObjectItem() override;
|
||||
|
||||
QString elementType() const { return m_elementType; }
|
||||
DObject *object() const { return m_object; }
|
||||
DiagramSceneModel *diagramSceneModel() const { return m_diagramSceneModel; }
|
||||
|
||||
@@ -119,6 +122,8 @@ public:
|
||||
QPointF relationStartPos() const override;
|
||||
void relationDrawn(const QString &id, const QPointF &toScenePos,
|
||||
const QList<QPointF> &intermediatePoints) override;
|
||||
virtual void relationDrawn(const QString &id, ObjectItem *targetElement,
|
||||
const QList<QPointF> &intermediatePoints);
|
||||
|
||||
void align(AlignType alignType, const QString &identifier) override;
|
||||
|
||||
@@ -147,7 +152,10 @@ protected:
|
||||
void updateSelectionMarker(ResizeFlags resizeFlags);
|
||||
void updateSelectionMarkerGeometry(const QRectF &objectRect);
|
||||
void updateRelationStarter();
|
||||
virtual void updateRelationStarterTools(RelationStarter *relationStarter);
|
||||
RelationStarter *relationStarter() const { return m_relationStarter; }
|
||||
virtual void addRelationStarterTool(const QString &id);
|
||||
virtual void addRelationStarterTool(const CustomRelation &customRelation);
|
||||
virtual void addStandardRelationStarterTools();
|
||||
void updateRelationStarterGeometry(const QRectF &objectRect);
|
||||
void updateAlignmentButtons();
|
||||
void updateAlignmentButtonsGeometry(const QRectF &objectRect);
|
||||
@@ -168,6 +176,7 @@ protected:
|
||||
private:
|
||||
QSizeF minimumSize(const QSet<QGraphicsItem *> &items) const;
|
||||
|
||||
QString m_elementType;
|
||||
DObject *m_object = 0;
|
||||
DiagramSceneModel *m_diagramSceneModel = 0;
|
||||
bool m_isSecondarySelected = false;
|
||||
|
@@ -32,7 +32,6 @@
|
||||
#include "qmt/diagram_scene/parts/contextlabelitem.h"
|
||||
#include "qmt/diagram_scene/parts/customiconitem.h"
|
||||
#include "qmt/diagram_scene/parts/editabletextitem.h"
|
||||
#include "qmt/diagram_scene/parts/relationstarter.h"
|
||||
#include "qmt/diagram_scene/parts/stereotypesitem.h"
|
||||
#include "qmt/infrastructure/geometryutilities.h"
|
||||
#include "qmt/stereotype/stereotypecontroller.h"
|
||||
@@ -72,7 +71,7 @@ public:
|
||||
};
|
||||
|
||||
PackageItem::PackageItem(DPackage *package, DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent)
|
||||
: ObjectItem(package, diagramSceneModel, parent)
|
||||
: ObjectItem(QStringLiteral("package"), package, diagramSceneModel, parent)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -135,21 +134,7 @@ void PackageItem::update()
|
||||
}
|
||||
|
||||
updateSelectionMarker(m_customIcon);
|
||||
|
||||
// relation starters
|
||||
if (isFocusSelected()) {
|
||||
if (!m_relationStarter) {
|
||||
m_relationStarter = new RelationStarter(this, diagramSceneModel(), 0);
|
||||
scene()->addItem(m_relationStarter);
|
||||
m_relationStarter->setZValue(RELATION_STARTER_ZVALUE);
|
||||
m_relationStarter->addArrow(QStringLiteral("dependency"), ArrowItem::ShaftDashed, ArrowItem::HeadOpen);
|
||||
}
|
||||
} else if (m_relationStarter) {
|
||||
scene()->removeItem(m_relationStarter);
|
||||
delete m_relationStarter;
|
||||
m_relationStarter = 0;
|
||||
}
|
||||
|
||||
updateRelationStarter();
|
||||
updateAlignmentButtons();
|
||||
updateGeometry();
|
||||
}
|
||||
@@ -326,10 +311,7 @@ void PackageItem::updateGeometry()
|
||||
}
|
||||
|
||||
updateSelectionMarkerGeometry(rect);
|
||||
|
||||
if (m_relationStarter)
|
||||
m_relationStarter->setPos(mapToScene(QPointF(right + 8.0, top)));
|
||||
|
||||
updateRelationStarterGeometry(rect);
|
||||
updateAlignmentButtonsGeometry(rect);
|
||||
updateDepth();
|
||||
}
|
||||
|
@@ -65,7 +65,6 @@ private:
|
||||
CustomIconItem *m_customIcon = 0;
|
||||
QGraphicsPolygonItem *m_shape = 0;
|
||||
ContextLabelItem *m_contextLabel = 0;
|
||||
RelationStarter *m_relationStarter = 0;
|
||||
};
|
||||
|
||||
} // namespace qmt
|
||||
|
@@ -38,6 +38,8 @@
|
||||
#include <QPainter>
|
||||
#include <QPen>
|
||||
|
||||
//#define DEBUG_PAINT_SHAPE
|
||||
|
||||
namespace qmt {
|
||||
|
||||
class ArrowItem::GraphicsHeadItem : public QGraphicsItem
|
||||
@@ -110,6 +112,7 @@ public:
|
||||
double length = 0.0;
|
||||
switch (m_head) {
|
||||
case ArrowItem::HeadNone:
|
||||
case ArrowItem::HeadCustom:
|
||||
break;
|
||||
case ArrowItem::HeadOpen:
|
||||
case ArrowItem::HeadTriangle:
|
||||
@@ -146,6 +149,7 @@ public:
|
||||
bool hasDiamond = false;
|
||||
switch (m_head) {
|
||||
case ArrowItem::HeadNone:
|
||||
case ArrowItem::HeadCustom:
|
||||
break;
|
||||
case ArrowItem::HeadOpen:
|
||||
case ArrowItem::HeadTriangle:
|
||||
@@ -236,7 +240,6 @@ public:
|
||||
|
||||
ArrowItem::ArrowItem(QGraphicsItem *parent)
|
||||
: QGraphicsItem(parent),
|
||||
m_shaft(ShaftSolid),
|
||||
m_shaftItem(new GraphicsShaftItem(this))
|
||||
{
|
||||
}
|
||||
@@ -248,9 +251,7 @@ ArrowItem::ArrowItem(const ArrowItem &rhs, QGraphicsItem *parent)
|
||||
m_arrowSize(rhs.m_arrowSize),
|
||||
m_diamondSize(rhs.m_diamondSize),
|
||||
m_startHead(rhs.m_startHead),
|
||||
m_startHeadItem(nullptr),
|
||||
m_endHead(rhs.m_endHead),
|
||||
m_endHeadItem(nullptr)
|
||||
m_endHead(rhs.m_endHead)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -278,14 +279,36 @@ void ArrowItem::setDiamondSize(double diamondSize)
|
||||
|
||||
void ArrowItem::setStartHead(ArrowItem::Head head)
|
||||
{
|
||||
if (m_startHead != head)
|
||||
m_startHead = head;
|
||||
m_startHead = head;
|
||||
}
|
||||
|
||||
void ArrowItem::setStartHead(QGraphicsItem *startHeadItem)
|
||||
{
|
||||
deleteHead(&m_startHeadItem);
|
||||
if (!startHeadItem) {
|
||||
m_startHead = HeadNone;
|
||||
} else {
|
||||
QTC_ASSERT(startHeadItem->parentItem() == this, return);
|
||||
m_startHead = HeadCustom;
|
||||
m_startHeadItem = startHeadItem;
|
||||
}
|
||||
}
|
||||
|
||||
void ArrowItem::setEndHead(ArrowItem::Head head)
|
||||
{
|
||||
if (m_endHead != head)
|
||||
m_endHead = head;
|
||||
m_endHead = head;
|
||||
}
|
||||
|
||||
void ArrowItem::setEndHead(QGraphicsItem *endHeadItem)
|
||||
{
|
||||
deleteHead(&m_endHeadItem);
|
||||
if (!endHeadItem) {
|
||||
m_endHead = HeadNone;
|
||||
} else {
|
||||
QTC_ASSERT(endHeadItem->parentItem() == this, return);
|
||||
m_endHead = HeadCustom;
|
||||
m_endHeadItem = endHeadItem;
|
||||
}
|
||||
}
|
||||
|
||||
void ArrowItem::setPoints(const QList<QPointF> &points)
|
||||
@@ -359,14 +382,14 @@ QLineF ArrowItem::lastLineSegment() const
|
||||
double ArrowItem::startHeadLength() const
|
||||
{
|
||||
if (m_startHeadItem)
|
||||
return m_startHeadItem->calcHeadLength();
|
||||
return calcHeadLength(m_startHeadItem);
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
double ArrowItem::endHeadLength() const
|
||||
{
|
||||
if (m_endHeadItem)
|
||||
return m_endHeadItem->calcHeadLength();
|
||||
return calcHeadLength(m_endHeadItem);
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@@ -383,43 +406,79 @@ void ArrowItem::updateShaft(const Style *style)
|
||||
QMT_ASSERT(m_shaftItem, return);
|
||||
|
||||
QPen pen(style->linePen());
|
||||
if (m_shaft == ShaftDashed)
|
||||
pen.setDashPattern(QVector<qreal>() << (4.0 / pen.widthF()) << (4.0 / pen.widthF()));
|
||||
switch (m_shaft) {
|
||||
case ShaftSolid:
|
||||
break;
|
||||
case ShaftDashed:
|
||||
pen.setDashPattern(QVector<qreal>()
|
||||
<< (4.0 / pen.widthF()) << (4.0 / pen.widthF()));
|
||||
break;
|
||||
case ShaftDot:
|
||||
pen.setDashPattern(QVector<qreal>()
|
||||
<< (2.0 / pen.widthF()) << (2.0 / pen.widthF()));
|
||||
break;
|
||||
case ShaftDashDot:
|
||||
pen.setDashPattern(QVector<qreal>()
|
||||
<< (4.0 / pen.widthF()) << (2.0 / pen.widthF())
|
||||
<< (2.0 / pen.widthF()) << (2.0 / pen.widthF()));
|
||||
break;
|
||||
case ShaftDashDotDot:
|
||||
pen.setDashPattern(QVector<qreal>()
|
||||
<< (4.0 / pen.widthF()) << (2.0 / pen.widthF())
|
||||
<< (2.0 / pen.widthF()) << (2.0 / pen.widthF())
|
||||
<< (2.0 / pen.widthF()) << (2.0 / pen.widthF()));
|
||||
break;
|
||||
}
|
||||
m_shaftItem->setPen(pen);
|
||||
}
|
||||
|
||||
void ArrowItem::updateHead(GraphicsHeadItem **headItem, Head head, const Style *style)
|
||||
void ArrowItem::deleteHead(QGraphicsItem **headItem)
|
||||
{
|
||||
if (head == HeadNone) {
|
||||
if (*headItem) {
|
||||
if ((*headItem)->scene())
|
||||
(*headItem)->scene()->removeItem(*headItem);
|
||||
delete *headItem;
|
||||
*headItem = 0;
|
||||
}
|
||||
return;
|
||||
if (*headItem) {
|
||||
if ((*headItem)->scene())
|
||||
(*headItem)->scene()->removeItem(*headItem);
|
||||
delete *headItem;
|
||||
*headItem = 0;
|
||||
}
|
||||
if (!*headItem)
|
||||
*headItem = new GraphicsHeadItem(this);
|
||||
(*headItem)->setArrowSize(m_arrowSize);
|
||||
(*headItem)->setDiamondSize(m_diamondSize);
|
||||
(*headItem)->setHead(head);
|
||||
(*headItem)->update(style);
|
||||
}
|
||||
|
||||
void ArrowItem::updateHeadGeometry(GraphicsHeadItem **headItem, const QPointF &pos, const QPointF &otherPos)
|
||||
void ArrowItem::updateHead(QGraphicsItem **headItem, Head head, const Style *style)
|
||||
{
|
||||
if (!*headItem)
|
||||
if (head == HeadNone) {
|
||||
deleteHead(headItem);
|
||||
} else if (head == HeadCustom) {
|
||||
// nothing to do
|
||||
} else {
|
||||
QTC_ASSERT(*headItem == 0 || dynamic_cast<GraphicsHeadItem *>(*headItem) != 0, return);
|
||||
GraphicsHeadItem *item;
|
||||
if (!*headItem) {
|
||||
item = new GraphicsHeadItem(this);
|
||||
*headItem = item;
|
||||
} else {
|
||||
item = dynamic_cast<GraphicsHeadItem *>(*headItem);
|
||||
if (!item)
|
||||
return;
|
||||
}
|
||||
item->setArrowSize(m_arrowSize);
|
||||
item->setDiamondSize(m_diamondSize);
|
||||
item->setHead(head);
|
||||
item->update(style);
|
||||
}
|
||||
}
|
||||
|
||||
void ArrowItem::updateHeadGeometry(QGraphicsItem *headItem, const QPointF &pos, const QPointF &otherPos)
|
||||
{
|
||||
if (!headItem)
|
||||
return;
|
||||
|
||||
(*headItem)->setPos(pos);
|
||||
headItem->setPos(pos);
|
||||
|
||||
QVector2D directionVector(pos - otherPos);
|
||||
directionVector.normalize();
|
||||
double angle = qAcos(directionVector.x()) * 180.0 / 3.1415926535;
|
||||
if (directionVector.y() > 0.0)
|
||||
angle = -angle;
|
||||
(*headItem)->setRotation(-angle);
|
||||
headItem->setRotation(-angle);
|
||||
}
|
||||
|
||||
void ArrowItem::updateGeometry()
|
||||
@@ -434,8 +493,8 @@ void ArrowItem::updateGeometry()
|
||||
if (m_startHeadItem) {
|
||||
QVector2D startDirectionVector(m_points.at(1) - m_points.at(0));
|
||||
startDirectionVector.normalize();
|
||||
startDirectionVector *= m_startHeadItem->calcHeadLength();
|
||||
path.moveTo(m_points.at(0) + startDirectionVector.toPointF());
|
||||
startDirectionVector *= calcHeadLength(m_startHeadItem);
|
||||
path.moveTo(m_points[0] + startDirectionVector.toPointF());
|
||||
} else {
|
||||
path.moveTo(m_points.at(0));
|
||||
}
|
||||
@@ -446,16 +505,24 @@ void ArrowItem::updateGeometry()
|
||||
if (m_endHeadItem) {
|
||||
QVector2D endDirectionVector(m_points.at(m_points.size() - 1) - m_points.at(m_points.size() - 2));
|
||||
endDirectionVector.normalize();
|
||||
endDirectionVector *= m_endHeadItem->calcHeadLength();
|
||||
path.lineTo(m_points.at(m_points.size() - 1) - endDirectionVector.toPointF());
|
||||
endDirectionVector *= calcHeadLength(m_endHeadItem);
|
||||
path.lineTo(m_points[m_points.size() - 1] - endDirectionVector.toPointF());
|
||||
} else {
|
||||
path.lineTo(m_points.at(m_points.size() - 1));
|
||||
}
|
||||
|
||||
m_shaftItem->setPath(path);
|
||||
|
||||
updateHeadGeometry(&m_startHeadItem, m_points.at(0), m_points.at(1));
|
||||
updateHeadGeometry(&m_endHeadItem, m_points.at(m_points.size() - 1), m_points.at(m_points.size() - 2));
|
||||
updateHeadGeometry(m_startHeadItem, m_points.at(0), m_points.at(1));
|
||||
updateHeadGeometry(m_endHeadItem, m_points.at(m_points.size() - 1), m_points.at(m_points.size() - 2));
|
||||
}
|
||||
|
||||
double ArrowItem::calcHeadLength(QGraphicsItem *headItem) const
|
||||
{
|
||||
// TODO use an interface
|
||||
if (GraphicsHeadItem *item = dynamic_cast<GraphicsHeadItem *>(headItem))
|
||||
return item->calcHeadLength();
|
||||
return 100.0;
|
||||
}
|
||||
|
||||
} // namespace qmt
|
||||
|
@@ -43,11 +43,15 @@ class ArrowItem : public QGraphicsItem
|
||||
public:
|
||||
enum Shaft {
|
||||
ShaftSolid,
|
||||
ShaftDashed
|
||||
ShaftDashed,
|
||||
ShaftDot,
|
||||
ShaftDashDot,
|
||||
ShaftDashDotDot
|
||||
};
|
||||
|
||||
enum Head {
|
||||
HeadNone,
|
||||
HeadCustom,
|
||||
HeadOpen,
|
||||
HeadTriangle,
|
||||
HeadFilledTriangle,
|
||||
@@ -65,7 +69,9 @@ public:
|
||||
void setArrowSize(double arrowSize);
|
||||
void setDiamondSize(double diamondSize);
|
||||
void setStartHead(Head head);
|
||||
void setStartHead(QGraphicsItem *startHeadItem);
|
||||
void setEndHead(Head head);
|
||||
void setEndHead(QGraphicsItem *endHeadItem);
|
||||
void setPoints(const QList<QPointF> &points);
|
||||
|
||||
QRectF boundingRect() const override;
|
||||
@@ -82,19 +88,21 @@ public:
|
||||
|
||||
private:
|
||||
void updateShaft(const Style *style);
|
||||
void updateHead(GraphicsHeadItem **headItem, Head head, const Style *style);
|
||||
void updateHeadGeometry(GraphicsHeadItem **headItem, const QPointF &pos,
|
||||
void deleteHead(QGraphicsItem **headItem);
|
||||
void updateHead(QGraphicsItem **headItem, Head head, const Style *style);
|
||||
void updateHeadGeometry(QGraphicsItem *headItem, const QPointF &pos,
|
||||
const QPointF &otherPos);
|
||||
void updateGeometry();
|
||||
double calcHeadLength(QGraphicsItem *headItem) const;
|
||||
|
||||
Shaft m_shaft = ShaftSolid;
|
||||
GraphicsShaftItem *m_shaftItem = nullptr;
|
||||
double m_arrowSize = 10.0;
|
||||
double m_diamondSize = 15.0;
|
||||
Head m_startHead = HeadNone;
|
||||
GraphicsHeadItem *m_startHeadItem = nullptr;
|
||||
QGraphicsItem *m_startHeadItem = nullptr;
|
||||
Head m_endHead = HeadNone;
|
||||
GraphicsHeadItem *m_endHeadItem = nullptr;
|
||||
QGraphicsItem *m_endHeadItem = nullptr;
|
||||
QList<QPointF> m_points;
|
||||
};
|
||||
|
||||
|
@@ -70,16 +70,19 @@ void RelationStarter::paint(QPainter *painter, const QStyleOptionGraphicsItem *o
|
||||
}
|
||||
|
||||
void RelationStarter::addArrow(const QString &id, ArrowItem::Shaft shaft,
|
||||
ArrowItem::Head endHead, ArrowItem::Head startHead)
|
||||
ArrowItem::Head startHead, ArrowItem::Head endHead,
|
||||
const QString &toolTip)
|
||||
{
|
||||
QMT_CHECK(!id.isEmpty());
|
||||
prepareGeometryChange();
|
||||
auto arrow = new ArrowItem(this);
|
||||
arrow->setArrowSize(10.0);
|
||||
arrow->setDiamondSize(15.0);
|
||||
arrow->setDiamondSize(8.0);
|
||||
arrow->setShaft(shaft);
|
||||
arrow->setStartHead(startHead);
|
||||
arrow->setEndHead(endHead);
|
||||
if (!toolTip.isEmpty())
|
||||
arrow->setToolTip(toolTip);
|
||||
arrow->setPoints(QList<QPointF>() << QPointF(0.0, 10.0) << QPointF(15.0, 0.0));
|
||||
arrow->setPos(6.0, m_arrows.size() * 20.0 + 8.0);
|
||||
arrow->update(m_diagramSceneModel->styleController()->relationStarterStyle());
|
||||
@@ -99,6 +102,9 @@ void RelationStarter::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||
m_currentPreviewArrowId = m_arrowIds.value(item);
|
||||
QMT_CHECK(!m_currentPreviewArrowId.isEmpty());
|
||||
m_currentPreviewArrow = new ArrowItem(*item);
|
||||
// TODO use constants for sizes (in relationitem.h also)
|
||||
m_currentPreviewArrow->setArrowSize(12.0);
|
||||
m_currentPreviewArrow->setDiamondSize(12.0);
|
||||
m_currentPreviewArrow->setPoints(QList<QPointF>() << m_owner->relationStartPos() << mapToScene(event->pos()));
|
||||
m_currentPreviewArrow->update(m_diagramSceneModel->styleController()->relationStarterStyle());
|
||||
m_currentPreviewArrow->setZValue(PREVIEW_RELATION_ZVALUE);
|
||||
|
@@ -47,8 +47,9 @@ public:
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
||||
QWidget *widget = 0) override;
|
||||
|
||||
void addArrow(const QString &id, ArrowItem::Shaft shaft, ArrowItem::Head endHead,
|
||||
ArrowItem::Head startHead = ArrowItem::HeadNone);
|
||||
void addArrow(const QString &id, ArrowItem::Shaft shaft, ArrowItem::Head startHead,
|
||||
ArrowItem::Head endHead,
|
||||
const QString &toolTip = QString());
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
|
@@ -36,6 +36,7 @@
|
||||
#include "qmt/diagram/dpackage.h"
|
||||
#include "qmt/diagram/ditem.h"
|
||||
#include "qmt/diagram/drelation.h"
|
||||
#include "qmt/diagram/dassociation.h"
|
||||
#include "qmt/diagram_ui/diagram_mime_types.h"
|
||||
#include "qmt/model_controller/modelcontroller.h"
|
||||
#include "qmt/model_controller/mselection.h"
|
||||
@@ -221,7 +222,8 @@ void DiagramSceneController::createInheritance(DClass *derivedClass, DClass *bas
|
||||
}
|
||||
|
||||
void DiagramSceneController::createAssociation(DClass *endAClass, DClass *endBClass,
|
||||
const QList<QPointF> &intermediatePoints, MDiagram *diagram)
|
||||
const QList<QPointF> &intermediatePoints, MDiagram *diagram,
|
||||
std::function<void (MAssociation*, DAssociation*)> custom)
|
||||
{
|
||||
m_diagramController->undoController()->beginMergeSequence(tr("Create Association"));
|
||||
|
||||
@@ -243,6 +245,11 @@ void DiagramSceneController::createAssociation(DClass *endAClass, DClass *endBCl
|
||||
m_modelController->addRelation(endAModelObject, modelAssociation);
|
||||
|
||||
DRelation *relation = addRelation(modelAssociation, intermediatePoints, diagram);
|
||||
DAssociation *diagramAssociation = dynamic_cast<DAssociation *>(relation);
|
||||
QMT_CHECK(diagramAssociation);
|
||||
|
||||
if (custom)
|
||||
custom(modelAssociation, diagramAssociation);
|
||||
|
||||
m_diagramController->undoController()->endMergeSequence();
|
||||
|
||||
|
@@ -28,6 +28,8 @@
|
||||
#include <QObject>
|
||||
#include "qmt/infrastructure/qmt_global.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QPointF;
|
||||
QT_END_NAMESPACE
|
||||
@@ -41,10 +43,12 @@ class MObject;
|
||||
class MPackage;
|
||||
class MDiagram;
|
||||
class MRelation;
|
||||
class MAssociation;
|
||||
class DElement;
|
||||
class DObject;
|
||||
class DClass;
|
||||
class DRelation;
|
||||
class DAssociation;
|
||||
class DSelection;
|
||||
class IElementTasks;
|
||||
class ISceneInspector;
|
||||
@@ -80,7 +84,8 @@ public:
|
||||
void createInheritance(DClass *derivedClass, DClass *baseClass,
|
||||
const QList<QPointF> &intermediatePoints, MDiagram *diagram);
|
||||
void createAssociation(DClass *endAClass, DClass *endBClass,
|
||||
const QList<QPointF> &intermediatePoints, MDiagram *diagram);
|
||||
const QList<QPointF> &intermediatePoints, MDiagram *diagram,
|
||||
std::function<void (MAssociation*, DAssociation*)> custom = 0);
|
||||
bool relocateRelationEndA(DRelation *relation, DObject *targetObject);
|
||||
bool relocateRelationEndB(DRelation *relation, DObject *targetObject);
|
||||
|
||||
|
Reference in New Issue
Block a user