25#include <QPainterPath>
31QLineF::IntersectionType intersects(
const QLineF &line1,
const QLineF &line2, QPointF *intersectionPoint)
33 return line1.intersects(line2, intersectionPoint);
39QPointF intersected(
const QLineF &line,
const QRectF &rect)
42 if (intersects(line, QLineF(rect.topLeft(), rect.topRight()), &point) == QLineF::BoundedIntersection)
44 if (intersects(line, QLineF(rect.topRight(), rect.bottomRight()), &point) == QLineF::BoundedIntersection)
46 if (intersects(line, QLineF(rect.bottomRight(), rect.bottomLeft()), &point) == QLineF::BoundedIntersection)
48 if (intersects(line, QLineF(rect.bottomLeft(), rect.topLeft()), &point) == QLineF::BoundedIntersection)
61 setAcceptHoverEvents(
true);
62 setAcceptedMouseButtons(Qt::AllButtons);
72 auto model = qobject_cast<ObjectTreeModel *>(
scene()->model());
73 auto index = model->indexForObject(
element);
74 Q_ASSERT(index.isValid());
77 auto sceneItem = qobject_cast<QQuickItem *>(
object);
96 Q_ASSERT(!m_scene ||
scene == m_scene);
113 if (m_shape ==
shape) {
128 if (event->button() == Qt::RightButton) {
137 QContextMenuEvent::Mouse,
138#
if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
139 event->pos(), event->globalPosition().toPoint(), event->modifiers(),
141 event->pos(), event->globalPos(), event->modifiers(),
144 QCoreApplication::sendEvent(
scene(), &contextMenuEvent);
150 if (m_shape.isEmpty()) {
151 return QQuickItem::contains(point);
154 return m_shape.contains(point);
163 m_element->disconnect(
this);
169 setWidth(m_element->
width());
170 setHeight(m_element->
height());
175 connect(
this, &QQuickItem::opacityChanged, m_element, [=]() {
213 auto transition = qobject_cast<Transition *>(
element);
215 qCWarning(KDSME_VIEW) <<
"Set invalid element on QuickEdgeItem:" <<
element;
219 if (
auto previousTransition = toTransition()) {
220 previousTransition->sourceState()->disconnect(
this);
221 previousTransition->targetState()->disconnect(
this);
222 previousTransition->disconnect(
this);
229 this, &QuickTransitionItem::updateSource);
231 this, &QuickTransitionItem::updateTarget);
238void QuickTransitionItem::updatePosition()
240 if (
scene()->viewState() == StateMachineScene::RefreshState) {
244 auto transition = toTransition();
245 Q_ASSERT(transition);
246 const auto sourceState = transition->sourceState();
247 const auto targetState = transition->targetState();
248 if (sourceState == targetState)
254 const QRectF startRect(mapFromItem(sourceStateItem, QPointF(0, 0)),
255 QSizeF(sourceStateItem->width(), sourceStateItem->height()));
256 const QRectF endRect(mapFromItem(targetStateItem, QPointF(0, 0)),
257 QSizeF(targetStateItem->width(), targetStateItem->height()));
260 const auto labelBoundingRect = transition->labelBoundingRect();
262 const auto preliminaryEdge = QLineF(startRect.center(), endRect.center());
263 const auto startPoint = intersected(preliminaryEdge, startRect);
264 Q_ASSERT(!startPoint.isNull());
265 const auto endPoint = intersected(preliminaryEdge, endRect);
266 Q_ASSERT(!endPoint.isNull());
268 QPainterPath newShape(startPoint);
269 newShape.lineTo(endPoint);
270 transition->setShape(newShape);
272 const auto midPoint = newShape.pointAtPercent(0.5);
273 const qreal angle = newShape.angleAtPercent(0.5);
274 QRectF newLabelBoundingRect(labelBoundingRect);
276 newLabelBoundingRect.moveTopLeft(midPoint);
277 }
else if (angle < 180) {
278 newLabelBoundingRect.moveBottomLeft(midPoint);
279 }
else if (angle < 270) {
280 newLabelBoundingRect.moveBottomRight(midPoint);
282 newLabelBoundingRect.moveTopRight(midPoint);
284 transition->setLabelBoundingRect(newLabelBoundingRect);
287void QuickTransitionItem::updateSource()
289 const auto *transition = toTransition();
293 disconnect(m_sourceStateConnection);
294 if (
const auto *source = toTransition()->sourceState()) {
296 this, &QuickTransitionItem::updatePosition);
300void QuickTransitionItem::updateTarget()
302 const auto *transition = toTransition();
306 disconnect(m_targetStateConnection);
307 if (
const auto *targetState = toTransition()->targetState()) {
309 this, &QuickTransitionItem::updatePosition);
313Transition *QuickTransitionItem::toTransition()
const
QObject * itemForIndex(const QModelIndex &index) const
void visibleChanged(bool visible)
void heightChanged(qreal height)
void posChanged(const QPointF &pos)
void setVisible(bool visible)
void widthChanged(qreal width)
void setCurrentItem(KDSME::Element *item)
void sourceStateChanged(KDSME::State *sourceState)
void targetStateChanged(KDSME::State *targetState)
bool contains(const QPointF &point) const override
void setShape(const QPainterPath &shape)
virtual void setScene(KDSME::StateMachineScene *scene)
KDSME::StateMachineScene * scene
void activenessChanged(qreal activeness)
QuickSceneItem(QQuickItem *parent=nullptr)
QQuickItem * itemForElement(KDSME::Element *element) const
void setActiveness(qreal activeness)
void shapeChanged(const QPainterPath &shape)
void elementChanged(KDSME::Element *element)
void mouseReleaseEvent(QMouseEvent *event) override
void mousePressEvent(QMouseEvent *event) override
Q_INVOKABLE void sendClickEvent()
virtual void setElement(KDSME::Element *element)
QuickStateItem(QQuickItem *parent=nullptr)
QuickTransitionItem(QQuickItem *parent=nullptr)
void setElement(KDSME::Element *element) override