forked from qt-creator/qt-creator
ModelEditor: Allow relocation of ends of relations in diagrams
Change-Id: I8dbf536731cb24819f70dc6acacc4658fd257259 Reviewed-by: Tobias Hunger <tobias.hunger@theqtcompany.com>
This commit is contained in:
@@ -156,6 +156,39 @@ void DUpdateVisitor::visitMRelation(const MRelation *relation)
|
|||||||
drelation->setStereotypes(relation->stereotypes());
|
drelation->setStereotypes(relation->stereotypes());
|
||||||
if (isUpdating(relation->name() != drelation->name()))
|
if (isUpdating(relation->name() != drelation->name()))
|
||||||
drelation->setName(relation->name());
|
drelation->setName(relation->name());
|
||||||
|
// TODO improve performance of MDiagram::findDiagramElement
|
||||||
|
DObject *endAObject = dynamic_cast<DObject *>(m_diagram->findDiagramElement(drelation->endAUid()));
|
||||||
|
if (!endAObject || relation->endAUid() != endAObject->modelUid()) {
|
||||||
|
isUpdating(true);
|
||||||
|
endAObject = 0;
|
||||||
|
// TODO use DiagramController::findDelegate (and improve performance of that method)
|
||||||
|
foreach (DElement *diagramElement, m_diagram->diagramElements()) {
|
||||||
|
if (diagramElement->modelUid().isValid() && diagramElement->modelUid() == relation->endAUid()) {
|
||||||
|
endAObject = dynamic_cast<DObject *>(diagramElement);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (endAObject)
|
||||||
|
drelation->setEndAUid(endAObject->uid());
|
||||||
|
else
|
||||||
|
drelation->setEndAUid(Uid::invalidUid());
|
||||||
|
}
|
||||||
|
DObject *endBObject = dynamic_cast<DObject *>(m_diagram->findDiagramElement(drelation->endBUid()));
|
||||||
|
if (!endBObject || relation->endBUid() != endBObject->modelUid()) {
|
||||||
|
isUpdating(true);
|
||||||
|
endBObject = 0;
|
||||||
|
// TODO use DiagramController::findDelegate
|
||||||
|
foreach (DElement *diagramElement, m_diagram->diagramElements()) {
|
||||||
|
if (diagramElement->modelUid().isValid() && diagramElement->modelUid() == relation->endBUid()) {
|
||||||
|
endBObject = dynamic_cast<DObject *>(diagramElement);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (endBObject)
|
||||||
|
drelation->setEndBUid(endBObject->uid());
|
||||||
|
else
|
||||||
|
drelation->setEndBUid(Uid::invalidUid());
|
||||||
|
}
|
||||||
visitMElement(relation);
|
visitMElement(relation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -44,11 +44,11 @@ class IWindable
|
|||||||
public:
|
public:
|
||||||
virtual ~IWindable() { }
|
virtual ~IWindable() { }
|
||||||
|
|
||||||
virtual QPointF handlePos(int index) = 0;
|
virtual QPointF grabHandle(int index) = 0;
|
||||||
virtual void insertHandle(int beforeIndex, const QPointF &pos) = 0;
|
virtual void insertHandle(int beforeIndex, const QPointF &pos, double rasterWidth, double rasterHeight) = 0;
|
||||||
virtual void deleteHandle(int index) = 0;
|
virtual void deleteHandle(int index) = 0;
|
||||||
virtual void setHandlePos(int index, const QPointF &pos) = 0;
|
virtual void setHandlePos(int index, const QPointF &pos) = 0;
|
||||||
virtual void alignHandleToRaster(int index, double rasterWidth, double rasterHeight) = 0;
|
virtual void dropHandle(int index, double rasterWidth, double rasterHeight) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace qmt
|
} // namespace qmt
|
||||||
|
@@ -232,6 +232,20 @@ DElement *DiagramSceneModel::findTopmostElement(const QPointF &scenePos) const
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DObject *DiagramSceneModel::findTopmostObject(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) {
|
||||||
|
if (m_graphicsItems.contains(item)) {
|
||||||
|
DObject *object = dynamic_cast<DObject *>(m_itemToElementMap.value(item));
|
||||||
|
if (object)
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
QGraphicsItem *DiagramSceneModel::graphicsItem(DElement *element) const
|
QGraphicsItem *DiagramSceneModel::graphicsItem(DElement *element) const
|
||||||
{
|
{
|
||||||
return m_elementToItemMap.value(element);
|
return m_elementToItemMap.value(element);
|
||||||
|
@@ -102,6 +102,7 @@ public:
|
|||||||
bool hasMultiObjectsSelection() const;
|
bool hasMultiObjectsSelection() const;
|
||||||
DSelection selectedElements() const;
|
DSelection selectedElements() const;
|
||||||
DElement *findTopmostElement(const QPointF &scenePos) const;
|
DElement *findTopmostElement(const QPointF &scenePos) const;
|
||||||
|
DObject *findTopmostObject(const QPointF &scenePos) const;
|
||||||
|
|
||||||
QList<QGraphicsItem *> graphicsItems() const { return m_graphicsItems; }
|
QList<QGraphicsItem *> graphicsItems() const { return m_graphicsItems; }
|
||||||
QGraphicsItem *graphicsItem(DElement *element) const;
|
QGraphicsItem *graphicsItem(DElement *element) const;
|
||||||
|
@@ -174,6 +174,10 @@ private:
|
|||||||
QList<QPointF> m_points;
|
QList<QPointF> m_points;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool RelationItem::m_grabbedEndA = false;
|
||||||
|
bool RelationItem::m_grabbedEndB = false;
|
||||||
|
QPointF RelationItem::m_grabbedEndPos;
|
||||||
|
|
||||||
RelationItem::RelationItem(DRelation *relation, DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent)
|
RelationItem::RelationItem(DRelation *relation, DiagramSceneModel *diagramSceneModel, QGraphicsItem *parent)
|
||||||
: QGraphicsItem(parent),
|
: QGraphicsItem(parent),
|
||||||
m_relation(relation),
|
m_relation(relation),
|
||||||
@@ -271,14 +275,19 @@ void RelationItem::setFocusSelected(bool focusSelected)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QPointF RelationItem::handlePos(int index)
|
QPointF RelationItem::grabHandle(int index)
|
||||||
{
|
{
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
// TODO implement
|
m_grabbedEndA = true;
|
||||||
return QPointF(0,0);
|
QPointF endBPos = calcEndPoint(m_relation->endBUid(), m_relation->endAUid(), m_relation->intermediatePoints().size() - 1);
|
||||||
|
QPointF endAPos = calcEndPoint(m_relation->endAUid(), endBPos, 0);
|
||||||
|
m_grabbedEndPos = endAPos;
|
||||||
|
return endAPos;
|
||||||
} else if (index == m_relation->intermediatePoints().size() + 1) {
|
} else if (index == m_relation->intermediatePoints().size() + 1) {
|
||||||
// TODO implement
|
m_grabbedEndB = true;
|
||||||
return QPointF(0,0);
|
QPointF endBPos = calcEndPoint(m_relation->endBUid(), m_relation->endAUid(), m_relation->intermediatePoints().size() - 1);
|
||||||
|
m_grabbedEndPos = endBPos;
|
||||||
|
return endBPos;
|
||||||
} else {
|
} else {
|
||||||
QList<DRelation::IntermediatePoint> intermediatePoints = m_relation->intermediatePoints();
|
QList<DRelation::IntermediatePoint> intermediatePoints = m_relation->intermediatePoints();
|
||||||
--index;
|
--index;
|
||||||
@@ -287,11 +296,15 @@ QPointF RelationItem::handlePos(int index)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RelationItem::insertHandle(int beforeIndex, const QPointF &pos)
|
void RelationItem::insertHandle(int beforeIndex, const QPointF &pos, double rasterWidth, double rasterHeight)
|
||||||
{
|
{
|
||||||
|
if (beforeIndex == 0)
|
||||||
|
++beforeIndex;
|
||||||
if (beforeIndex >= 1 && beforeIndex <= m_relation->intermediatePoints().size() + 1) {
|
if (beforeIndex >= 1 && beforeIndex <= m_relation->intermediatePoints().size() + 1) {
|
||||||
QList<DRelation::IntermediatePoint> intermediatePoints = m_relation->intermediatePoints();
|
QList<DRelation::IntermediatePoint> intermediatePoints = m_relation->intermediatePoints();
|
||||||
intermediatePoints.insert(beforeIndex - 1, DRelation::IntermediatePoint(pos));
|
double x = qRound(pos.x() / rasterWidth) * rasterWidth;
|
||||||
|
double y = qRound(pos.y() / rasterHeight) * rasterHeight;
|
||||||
|
intermediatePoints.insert(beforeIndex - 1, DRelation::IntermediatePoint(QPointF(x, y)));
|
||||||
|
|
||||||
m_diagramSceneModel->diagramController()->startUpdateElement(m_relation, m_diagramSceneModel->diagram(), DiagramController::UpdateMajor);
|
m_diagramSceneModel->diagramController()->startUpdateElement(m_relation, m_diagramSceneModel->diagram(), DiagramController::UpdateMajor);
|
||||||
m_relation->setIntermediatePoints(intermediatePoints);
|
m_relation->setIntermediatePoints(intermediatePoints);
|
||||||
@@ -301,6 +314,10 @@ void RelationItem::insertHandle(int beforeIndex, const QPointF &pos)
|
|||||||
|
|
||||||
void RelationItem::deleteHandle(int index)
|
void RelationItem::deleteHandle(int index)
|
||||||
{
|
{
|
||||||
|
if (index == 0)
|
||||||
|
++index;
|
||||||
|
else if (index == m_relation->intermediatePoints().size() + 1)
|
||||||
|
--index;
|
||||||
if (index >= 1 && index <= m_relation->intermediatePoints().size()) {
|
if (index >= 1 && index <= m_relation->intermediatePoints().size()) {
|
||||||
QList<DRelation::IntermediatePoint> intermediatePoints = m_relation->intermediatePoints();
|
QList<DRelation::IntermediatePoint> intermediatePoints = m_relation->intermediatePoints();
|
||||||
intermediatePoints.removeAt(index - 1);
|
intermediatePoints.removeAt(index - 1);
|
||||||
@@ -314,9 +331,11 @@ void RelationItem::deleteHandle(int index)
|
|||||||
void RelationItem::setHandlePos(int index, const QPointF &pos)
|
void RelationItem::setHandlePos(int index, const QPointF &pos)
|
||||||
{
|
{
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
// TODO implement
|
m_grabbedEndPos = pos;
|
||||||
|
update();
|
||||||
} else if (index == m_relation->intermediatePoints().size() + 1) {
|
} else if (index == m_relation->intermediatePoints().size() + 1) {
|
||||||
// TODO implement
|
m_grabbedEndPos = pos;
|
||||||
|
update();
|
||||||
} else {
|
} else {
|
||||||
QList<DRelation::IntermediatePoint> intermediatePoints = m_relation->intermediatePoints();
|
QList<DRelation::IntermediatePoint> intermediatePoints = m_relation->intermediatePoints();
|
||||||
--index;
|
--index;
|
||||||
@@ -329,12 +348,18 @@ void RelationItem::setHandlePos(int index, const QPointF &pos)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RelationItem::alignHandleToRaster(int index, double rasterWidth, double rasterHeight)
|
void RelationItem::dropHandle(int index, double rasterWidth, double rasterHeight)
|
||||||
{
|
{
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
// TODO implement
|
m_grabbedEndA = false;
|
||||||
} else if (index ==m_relation->intermediatePoints().size() + 1) {
|
DObject *targetObject = m_diagramSceneModel->findTopmostObject(m_grabbedEndPos);
|
||||||
// TODO implement
|
if (!m_diagramSceneModel->diagramSceneController()->relocateRelationEndA(m_relation, targetObject))
|
||||||
|
update();
|
||||||
|
} else if (index == m_relation->intermediatePoints().size() + 1) {
|
||||||
|
m_grabbedEndB = false;
|
||||||
|
DObject *targetObject = m_diagramSceneModel->findTopmostObject(m_grabbedEndPos);
|
||||||
|
if (!m_diagramSceneModel->diagramSceneController()->relocateRelationEndB(m_relation, targetObject))
|
||||||
|
update();
|
||||||
} else {
|
} else {
|
||||||
QList<DRelation::IntermediatePoint> intermediatePoints = m_relation->intermediatePoints();
|
QList<DRelation::IntermediatePoint> intermediatePoints = m_relation->intermediatePoints();
|
||||||
--index;
|
--index;
|
||||||
@@ -365,8 +390,19 @@ void RelationItem::update()
|
|||||||
|
|
||||||
void RelationItem::update(const Style *style)
|
void RelationItem::update(const Style *style)
|
||||||
{
|
{
|
||||||
QPointF endBPos = calcEndPoint(m_relation->endBUid(), m_relation->endAUid(), m_relation->intermediatePoints().size() - 1);
|
QPointF endAPos;
|
||||||
QPointF endAPos = calcEndPoint(m_relation->endAUid(), endBPos, 0);
|
QPointF endBPos;
|
||||||
|
|
||||||
|
if (m_grabbedEndA) {
|
||||||
|
endAPos = m_grabbedEndPos;
|
||||||
|
endBPos = calcEndPoint(m_relation->endBUid(), endAPos, m_relation->intermediatePoints().size() - 1);
|
||||||
|
} else if (m_grabbedEndB) {
|
||||||
|
endBPos = m_grabbedEndPos;
|
||||||
|
endAPos = calcEndPoint(m_relation->endAUid(), endBPos, 0);
|
||||||
|
} else {
|
||||||
|
endBPos = calcEndPoint(m_relation->endBUid(), m_relation->endAUid(), m_relation->intermediatePoints().size() - 1);
|
||||||
|
endAPos = calcEndPoint(m_relation->endAUid(), endBPos, 0);
|
||||||
|
}
|
||||||
|
|
||||||
setPos(endAPos);
|
setPos(endAPos);
|
||||||
|
|
||||||
|
@@ -77,11 +77,11 @@ public:
|
|||||||
bool isFocusSelected() const override;
|
bool isFocusSelected() const override;
|
||||||
void setFocusSelected(bool focusSelected) override;
|
void setFocusSelected(bool focusSelected) override;
|
||||||
|
|
||||||
QPointF handlePos(int index) override;
|
QPointF grabHandle(int index) override;
|
||||||
void insertHandle(int beforeIndex, const QPointF &pos) override;
|
void insertHandle(int beforeIndex, const QPointF &pos, double rasterWidth, double rasterHeight) override;
|
||||||
void deleteHandle(int index) override;
|
void deleteHandle(int index) override;
|
||||||
void setHandlePos(int index, const QPointF &pos) override;
|
void setHandlePos(int index, const QPointF &pos) override;
|
||||||
void alignHandleToRaster(int index, double rasterWidth, double rasterHeight) override;
|
void dropHandle(int index, double rasterWidth, double rasterHeight) override;
|
||||||
|
|
||||||
virtual void update();
|
virtual void update();
|
||||||
|
|
||||||
@@ -108,6 +108,9 @@ protected:
|
|||||||
QGraphicsSimpleTextItem *m_name = 0;
|
QGraphicsSimpleTextItem *m_name = 0;
|
||||||
StereotypesItem *m_stereotypes = 0;
|
StereotypesItem *m_stereotypes = 0;
|
||||||
PathSelectionItem *m_selectionHandles = 0;
|
PathSelectionItem *m_selectionHandles = 0;
|
||||||
|
static bool m_grabbedEndA;
|
||||||
|
static bool m_grabbedEndB;
|
||||||
|
static QPointF m_grabbedEndPos;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace qmt
|
} // namespace qmt
|
||||||
|
@@ -33,12 +33,14 @@
|
|||||||
#include "qmt/diagram_scene/capabilities/windable.h"
|
#include "qmt/diagram_scene/capabilities/windable.h"
|
||||||
#include "qmt/diagram_scene/diagramsceneconstants.h"
|
#include "qmt/diagram_scene/diagramsceneconstants.h"
|
||||||
#include "qmt/infrastructure/geometryutilities.h"
|
#include "qmt/infrastructure/geometryutilities.h"
|
||||||
|
#include "qmt/infrastructure/qmtassert.h"
|
||||||
|
|
||||||
#include <QGraphicsScene>
|
#include <QGraphicsScene>
|
||||||
#include <QGraphicsSceneMouseEvent>
|
#include <QGraphicsSceneMouseEvent>
|
||||||
#include <QBrush>
|
#include <QBrush>
|
||||||
#include <QLineF>
|
#include <QLineF>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
#include <QKeyEvent>
|
||||||
|
|
||||||
namespace qmt {
|
namespace qmt {
|
||||||
|
|
||||||
@@ -58,6 +60,12 @@ public:
|
|||||||
m_owner(parent),
|
m_owner(parent),
|
||||||
m_pointIndex(pointIndex)
|
m_pointIndex(pointIndex)
|
||||||
{
|
{
|
||||||
|
setFlag(QGraphicsItem::ItemIsFocusable);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPointIndex(int pointIndex)
|
||||||
|
{
|
||||||
|
m_pointIndex = pointIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setPointSize(const QSizeF &pointSize)
|
void setPointSize(const QSizeF &pointSize)
|
||||||
@@ -79,21 +87,31 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
void mousePressEvent(QGraphicsSceneMouseEvent *event)
|
void mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||||
{
|
{
|
||||||
m_startPos = mapToScene(event->pos());
|
m_startPos = event->scenePos();
|
||||||
|
m_lastPos = m_startPos;
|
||||||
m_qualifier = event->modifiers() & Qt::ControlModifier ? DeleteHandle : None;
|
m_qualifier = event->modifiers() & Qt::ControlModifier ? DeleteHandle : None;
|
||||||
m_owner->moveHandle(m_pointIndex, QPointF(0.0, 0.0), Press, m_qualifier);
|
m_owner->moveHandle(m_pointIndex, QPointF(0.0, 0.0), Press, m_qualifier);
|
||||||
|
setFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
void mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
void mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||||
{
|
{
|
||||||
QPointF delta = mapToScene(event->pos()) - m_startPos;
|
m_lastPos = event->scenePos();
|
||||||
|
QPointF delta = m_lastPos - m_startPos;
|
||||||
m_owner->moveHandle(m_pointIndex, delta, Move, m_qualifier);
|
m_owner->moveHandle(m_pointIndex, delta, Move, m_qualifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||||
{
|
{
|
||||||
QPointF delta = mapToScene(event->pos()) - m_startPos;
|
m_lastPos = event->scenePos();
|
||||||
|
QPointF delta = m_lastPos - m_startPos;
|
||||||
m_owner->moveHandle(m_pointIndex, delta, Release, m_qualifier);
|
m_owner->moveHandle(m_pointIndex, delta, Release, m_qualifier);
|
||||||
|
clearFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyPressEvent(QKeyEvent *event)
|
||||||
|
{
|
||||||
|
m_owner->keyPressed(m_pointIndex, event, m_lastPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -122,6 +140,7 @@ private:
|
|||||||
QSizeF m_pointSize;
|
QSizeF m_pointSize;
|
||||||
Selection m_selection = NotSelected;
|
Selection m_selection = NotSelected;
|
||||||
QPointF m_startPos;
|
QPointF m_startPos;
|
||||||
|
QPointF m_lastPos;
|
||||||
PathSelectionItem::HandleQualifier m_qualifier = PathSelectionItem::None;
|
PathSelectionItem::HandleQualifier m_qualifier = PathSelectionItem::None;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -193,11 +212,23 @@ QList<QPointF> PathSelectionItem::points() const
|
|||||||
|
|
||||||
void PathSelectionItem::setPoints(const QList<QPointF> &points)
|
void PathSelectionItem::setPoints(const QList<QPointF> &points)
|
||||||
{
|
{
|
||||||
|
QMT_CHECK(points.size() >= 2);
|
||||||
prepareGeometryChange();
|
prepareGeometryChange();
|
||||||
|
|
||||||
|
GraphicsHandleItem *focusEndBItem = 0;
|
||||||
|
if (!m_handles.isEmpty() && m_focusHandleItem == m_handles.last()) {
|
||||||
|
focusEndBItem = m_focusHandleItem;
|
||||||
|
m_handles.removeLast();
|
||||||
|
}
|
||||||
int pointIndex = 0;
|
int pointIndex = 0;
|
||||||
foreach (const QPointF &point, points) {
|
foreach (const QPointF &point, points) {
|
||||||
GraphicsHandleItem *handle;
|
GraphicsHandleItem *handle;
|
||||||
if (pointIndex >= m_handles.size()) {
|
if (focusEndBItem && pointIndex == points.size() - 1) {
|
||||||
|
handle = focusEndBItem;
|
||||||
|
handle->setPointIndex(pointIndex);
|
||||||
|
m_handles.insert(pointIndex, handle);
|
||||||
|
focusEndBItem = 0;
|
||||||
|
} else if (pointIndex >= m_handles.size()) {
|
||||||
handle = new GraphicsHandleItem(pointIndex, this);
|
handle = new GraphicsHandleItem(pointIndex, this);
|
||||||
handle->setPointSize(m_pointSize);
|
handle->setPointSize(m_pointSize);
|
||||||
m_handles.append(handle);
|
m_handles.append(handle);
|
||||||
@@ -207,6 +238,7 @@ void PathSelectionItem::setPoints(const QList<QPointF> &points)
|
|||||||
handle->setPos(point);
|
handle->setPos(point);
|
||||||
++pointIndex;
|
++pointIndex;
|
||||||
}
|
}
|
||||||
|
QMT_CHECK(!focusEndBItem);
|
||||||
while (m_handles.size() > pointIndex) {
|
while (m_handles.size() > pointIndex) {
|
||||||
m_handles.last()->scene()->removeItem(m_handles.last());
|
m_handles.last()->scene()->removeItem(m_handles.last());
|
||||||
delete m_handles.last();
|
delete m_handles.last();
|
||||||
@@ -229,7 +261,7 @@ void PathSelectionItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
|||||||
for (int i = 0; i < m_handles.size() - 1; ++i) {
|
for (int i = 0; i < m_handles.size() - 1; ++i) {
|
||||||
qreal distance = GeometryUtilities::calcDistancePointToLine(event->pos(), QLineF(m_handles.at(i)->pos(), m_handles.at(i+1)->pos()));
|
qreal distance = GeometryUtilities::calcDistancePointToLine(event->pos(), QLineF(m_handles.at(i)->pos(), m_handles.at(i+1)->pos()));
|
||||||
if (distance < MAX_SELECTION_DISTANCE_FROM_PATH) {
|
if (distance < MAX_SELECTION_DISTANCE_FROM_PATH) {
|
||||||
m_windable->insertHandle(i + 1, event->scenePos());
|
m_windable->insertHandle(i + 1, event->scenePos(), RASTER_WIDTH, RASTER_HEIGHT);
|
||||||
event->accept();
|
event->accept();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -239,15 +271,19 @@ void PathSelectionItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PathSelectionItem::isEndHandle(int pointIndex) const
|
||||||
|
{
|
||||||
|
return pointIndex == 0 || pointIndex == m_handles.size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
void PathSelectionItem::update()
|
void PathSelectionItem::update()
|
||||||
{
|
{
|
||||||
prepareGeometryChange();
|
prepareGeometryChange();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
foreach (GraphicsHandleItem *handle, m_handles) {
|
foreach (GraphicsHandleItem *handle, m_handles) {
|
||||||
handle->setPointSize(m_pointSize);
|
handle->setPointSize(m_pointSize);
|
||||||
bool isEndPoint = (i == 0 || i == m_handles.size() - 1);
|
|
||||||
handle->setSelection(m_isSecondarySelected
|
handle->setSelection(m_isSecondarySelected
|
||||||
? (isEndPoint ? GraphicsHandleItem::NotSelected : GraphicsHandleItem::SecondarySelected)
|
? (isEndHandle(i) ? GraphicsHandleItem::NotSelected : GraphicsHandleItem::SecondarySelected)
|
||||||
: GraphicsHandleItem::Selected);
|
: GraphicsHandleItem::Selected);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
@@ -258,12 +294,16 @@ void PathSelectionItem::moveHandle(int pointIndex, const QPointF &deltaMove, Han
|
|||||||
switch (handleQualifier) {
|
switch (handleQualifier) {
|
||||||
case None:
|
case None:
|
||||||
{
|
{
|
||||||
if (handleStatus == Press)
|
if (handleStatus == Press) {
|
||||||
m_originalHandlePos = m_windable->handlePos(pointIndex);
|
m_focusHandleItem = m_handles.at(pointIndex);
|
||||||
|
m_originalHandlePos = m_windable->grabHandle(pointIndex);
|
||||||
|
}
|
||||||
QPointF newPos = m_originalHandlePos + deltaMove;
|
QPointF newPos = m_originalHandlePos + deltaMove;
|
||||||
m_windable->setHandlePos(pointIndex, newPos);
|
m_windable->setHandlePos(pointIndex, newPos);
|
||||||
if (handleStatus == Release)
|
if (handleStatus == Release) {
|
||||||
m_windable->alignHandleToRaster(pointIndex, RASTER_WIDTH, RASTER_HEIGHT);
|
m_windable->dropHandle(pointIndex, RASTER_WIDTH, RASTER_HEIGHT);
|
||||||
|
m_focusHandleItem = 0;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DeleteHandle:
|
case DeleteHandle:
|
||||||
@@ -273,4 +313,14 @@ void PathSelectionItem::moveHandle(int pointIndex, const QPointF &deltaMove, Han
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PathSelectionItem::keyPressed(int pointIndex, QKeyEvent *event, const QPointF &pos)
|
||||||
|
{
|
||||||
|
if (isEndHandle(pointIndex)) {
|
||||||
|
if (event->key() == Qt::Key_Shift)
|
||||||
|
m_windable->insertHandle(pointIndex, pos, RASTER_WIDTH, RASTER_HEIGHT);
|
||||||
|
else if (event->key() == Qt::Key_Control)
|
||||||
|
m_windable->deleteHandle(pointIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace qmt
|
} // namespace qmt
|
||||||
|
@@ -72,14 +72,17 @@ protected:
|
|||||||
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
|
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool isEndHandle(int pointIndex) const;
|
||||||
void update();
|
void update();
|
||||||
void moveHandle(int pointIndex, const QPointF &deltaMove, HandleStatus handleStatus,
|
void moveHandle(int pointIndex, const QPointF &deltaMove, HandleStatus handleStatus,
|
||||||
HandleQualifier handleQualifier);
|
HandleQualifier handleQualifier);
|
||||||
|
void keyPressed(int pointIndex, QKeyEvent *event, const QPointF &pos);
|
||||||
|
|
||||||
IWindable *m_windable = 0;
|
IWindable *m_windable = 0;
|
||||||
QSizeF m_pointSize;
|
QSizeF m_pointSize;
|
||||||
bool m_isSecondarySelected = false;
|
bool m_isSecondarySelected = false;
|
||||||
QList<GraphicsHandleItem *> m_handles;
|
QList<GraphicsHandleItem *> m_handles;
|
||||||
|
GraphicsHandleItem *m_focusHandleItem = 0;
|
||||||
QPointF m_originalHandlePos;
|
QPointF m_originalHandlePos;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -109,6 +109,8 @@ void MFlatAssignmentVisitor::visitMRelation(const MRelation *relation)
|
|||||||
auto targetRelation = dynamic_cast<MRelation *>(m_target);
|
auto targetRelation = dynamic_cast<MRelation *>(m_target);
|
||||||
QMT_CHECK(targetRelation);
|
QMT_CHECK(targetRelation);
|
||||||
targetRelation->setName(relation->name());
|
targetRelation->setName(relation->name());
|
||||||
|
targetRelation->setEndAUid(relation->endAUid());
|
||||||
|
targetRelation->setEndBUid(relation->endBUid());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MFlatAssignmentVisitor::visitMDependency(const MDependency *dependency)
|
void MFlatAssignmentVisitor::visitMDependency(const MDependency *dependency)
|
||||||
|
@@ -44,6 +44,7 @@
|
|||||||
#include "qmt/diagram_ui/diagram_mime_types.h"
|
#include "qmt/diagram_ui/diagram_mime_types.h"
|
||||||
#include "qmt/model_controller/modelcontroller.h"
|
#include "qmt/model_controller/modelcontroller.h"
|
||||||
#include "qmt/model_controller/mselection.h"
|
#include "qmt/model_controller/mselection.h"
|
||||||
|
#include "qmt/model_controller/mvoidvisitor.h"
|
||||||
#include "qmt/model/massociation.h"
|
#include "qmt/model/massociation.h"
|
||||||
#include "qmt/model/mcanvasdiagram.h"
|
#include "qmt/model/mcanvasdiagram.h"
|
||||||
#include "qmt/model/mclass.h"
|
#include "qmt/model/mclass.h"
|
||||||
@@ -71,6 +72,35 @@ namespace {
|
|||||||
static VoidElementTasks dummyElementTasks;
|
static VoidElementTasks dummyElementTasks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class DiagramSceneController::AcceptRelationVisitor : public MVoidConstVisitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AcceptRelationVisitor(const MRelation *relation)
|
||||||
|
: m_relation(relation)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isAccepted() const { return m_accepted; }
|
||||||
|
|
||||||
|
void visitMObject(const MObject *object) override
|
||||||
|
{
|
||||||
|
Q_UNUSED(object);
|
||||||
|
m_accepted = dynamic_cast<const MDependency *>(m_relation) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void visitMClass(const MClass *klass) override
|
||||||
|
{
|
||||||
|
Q_UNUSED(klass);
|
||||||
|
m_accepted = dynamic_cast<const MDependency *>(m_relation) != 0
|
||||||
|
|| dynamic_cast<const MInheritance *>(m_relation) != 0
|
||||||
|
|| dynamic_cast<const MAssociation *>(m_relation) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const MRelation *m_relation = 0;
|
||||||
|
bool m_accepted = false;
|
||||||
|
};
|
||||||
|
|
||||||
DiagramSceneController::DiagramSceneController(QObject *parent)
|
DiagramSceneController::DiagramSceneController(QObject *parent)
|
||||||
: QObject(parent),
|
: QObject(parent),
|
||||||
m_modelController(0),
|
m_modelController(0),
|
||||||
@@ -225,6 +255,16 @@ void DiagramSceneController::createAssociation(DClass *endAClass, DClass *endBCl
|
|||||||
emit newElementCreated(relation, diagram);
|
emit newElementCreated(relation, diagram);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DiagramSceneController::relocateRelationEndA(DRelation *relation, DObject *targetObject)
|
||||||
|
{
|
||||||
|
return relocateRelationEnd(relation, targetObject, &MRelation::endAUid, &MRelation::setEndAUid);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DiagramSceneController::relocateRelationEndB(DRelation *relation, DObject *targetObject)
|
||||||
|
{
|
||||||
|
return relocateRelationEnd(relation, targetObject, &MRelation::endBUid, &MRelation::setEndBUid);
|
||||||
|
}
|
||||||
|
|
||||||
bool DiagramSceneController::isAddingAllowed(const Uid &modelElementKey, MDiagram *diagram)
|
bool DiagramSceneController::isAddingAllowed(const Uid &modelElementKey, MDiagram *diagram)
|
||||||
{
|
{
|
||||||
MElement *modelElement = m_modelController->findElement(modelElementKey);
|
MElement *modelElement = m_modelController->findElement(modelElementKey);
|
||||||
@@ -673,4 +713,32 @@ DRelation *DiagramSceneController::addRelation(MRelation *modelRelation, const Q
|
|||||||
return diagramRelation;
|
return diagramRelation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DiagramSceneController::relocateRelationEnd(DRelation *relation, DObject *targetObject,
|
||||||
|
Uid (MRelation::*endUid)() const,
|
||||||
|
void (MRelation::*setEndUid)(const Uid &))
|
||||||
|
{
|
||||||
|
QMT_CHECK(relation);
|
||||||
|
if (targetObject && targetObject->uid() != relation->endAUid()) {
|
||||||
|
MRelation *modelRelation = m_modelController->findRelation(relation->modelUid());
|
||||||
|
QMT_CHECK(modelRelation);
|
||||||
|
MObject *targetMObject = m_modelController->findObject(targetObject->modelUid());
|
||||||
|
QMT_CHECK(targetMObject);
|
||||||
|
AcceptRelationVisitor visitor(modelRelation);
|
||||||
|
targetMObject->accept(&visitor);
|
||||||
|
if (visitor.isAccepted()) {
|
||||||
|
MObject *currentTargetMObject = m_modelController->findObject((modelRelation->*endUid)());
|
||||||
|
QMT_CHECK(currentTargetMObject);
|
||||||
|
m_modelController->undoController()->beginMergeSequence(tr("Relocate Relation"));
|
||||||
|
if (currentTargetMObject == modelRelation->owner())
|
||||||
|
m_modelController->moveRelation(targetMObject, modelRelation);
|
||||||
|
m_modelController->startUpdateRelation(modelRelation);
|
||||||
|
(modelRelation->*setEndUid)(targetMObject->uid());
|
||||||
|
m_modelController->finishUpdateRelation(modelRelation, false);
|
||||||
|
m_modelController->undoController()->endMergeSequence();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace qmt
|
} // namespace qmt
|
||||||
|
@@ -59,6 +59,8 @@ class QMT_EXPORT DiagramSceneController : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
class AcceptRelationVisitor;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit DiagramSceneController(QObject *parent = 0);
|
explicit DiagramSceneController(QObject *parent = 0);
|
||||||
~DiagramSceneController() override;
|
~DiagramSceneController() override;
|
||||||
@@ -85,6 +87,8 @@ public:
|
|||||||
const QList<QPointF> &intermediatePoints, MDiagram *diagram);
|
const QList<QPointF> &intermediatePoints, MDiagram *diagram);
|
||||||
void createAssociation(DClass *endAClass, DClass *endBClass,
|
void createAssociation(DClass *endAClass, DClass *endBClass,
|
||||||
const QList<QPointF> &intermediatePoints, MDiagram *diagram);
|
const QList<QPointF> &intermediatePoints, MDiagram *diagram);
|
||||||
|
bool relocateRelationEndA(DRelation *relation, DObject *targetObject);
|
||||||
|
bool relocateRelationEndB(DRelation *relation, DObject *targetObject);
|
||||||
|
|
||||||
bool isAddingAllowed(const Uid &modelElementKey, MDiagram *diagram);
|
bool isAddingAllowed(const Uid &modelElementKey, MDiagram *diagram);
|
||||||
void addExistingModelElement(const Uid &modelElementKey, const QPointF &pos, MDiagram *diagram);
|
void addExistingModelElement(const Uid &modelElementKey, const QPointF &pos, MDiagram *diagram);
|
||||||
@@ -124,6 +128,8 @@ private:
|
|||||||
DObject *addObject(MObject *modelObject, const QPointF &pos, MDiagram *diagram);
|
DObject *addObject(MObject *modelObject, const QPointF &pos, MDiagram *diagram);
|
||||||
DRelation *addRelation(MRelation *modelRelation, const QList<QPointF> &intermediatePoints,
|
DRelation *addRelation(MRelation *modelRelation, const QList<QPointF> &intermediatePoints,
|
||||||
MDiagram *diagram);
|
MDiagram *diagram);
|
||||||
|
bool relocateRelationEnd(DRelation *relation, DObject *targetObject, Uid (MRelation::*endUid)() const,
|
||||||
|
void (MRelation::*setEndUid)(const Uid &));
|
||||||
|
|
||||||
ModelController *m_modelController;
|
ModelController *m_modelController;
|
||||||
DiagramController *m_diagramController;
|
DiagramController *m_diagramController;
|
||||||
|
Reference in New Issue
Block a user