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 event->pos(), event->globalPosition().toPoint(), event->modifiers(),
140 QCoreApplication::sendEvent(
scene(), &contextMenuEvent);
146 if (m_shape.isEmpty()) {
147 return QQuickItem::contains(point);
150 return m_shape.contains(point);
159 m_element->disconnect(
this);
165 setWidth(m_element->
width());
166 setHeight(m_element->
height());
171 connect(
this, &QQuickItem::opacityChanged, m_element, [=]() {
209 auto transition = qobject_cast<Transition *>(
element);
211 qCWarning(KDSME_VIEW) <<
"Set invalid element on QuickEdgeItem:" <<
element;
215 if (
auto previousTransition = toTransition()) {
216 previousTransition->sourceState()->disconnect(
this);
217 previousTransition->targetState()->disconnect(
this);
218 previousTransition->disconnect(
this);
225 this, &QuickTransitionItem::updateSource);
227 this, &QuickTransitionItem::updateTarget);
234void QuickTransitionItem::updatePosition()
236 if (
scene()->viewState() == StateMachineScene::RefreshState) {
240 auto transition = toTransition();
241 Q_ASSERT(transition);
242 const auto sourceState = transition->sourceState();
243 const auto targetState = transition->targetState();
244 if (sourceState == targetState)
250 const QRectF startRect(mapFromItem(sourceStateItem, QPointF(0, 0)),
251 QSizeF(sourceStateItem->width(), sourceStateItem->height()));
252 const QRectF endRect(mapFromItem(targetStateItem, QPointF(0, 0)),
253 QSizeF(targetStateItem->width(), targetStateItem->height()));
256 const auto labelBoundingRect = transition->labelBoundingRect();
258 const auto preliminaryEdge = QLineF(startRect.center(), endRect.center());
259 const auto startPoint = intersected(preliminaryEdge, startRect);
260 Q_ASSERT(!startPoint.isNull());
261 const auto endPoint = intersected(preliminaryEdge, endRect);
262 Q_ASSERT(!endPoint.isNull());
264 QPainterPath newShape(startPoint);
265 newShape.lineTo(endPoint);
266 transition->setShape(newShape);
268 const auto midPoint = newShape.pointAtPercent(0.5);
269 const qreal angle = newShape.angleAtPercent(0.5);
270 QRectF newLabelBoundingRect(labelBoundingRect);
272 newLabelBoundingRect.moveTopLeft(midPoint);
273 }
else if (angle < 180) {
274 newLabelBoundingRect.moveBottomLeft(midPoint);
275 }
else if (angle < 270) {
276 newLabelBoundingRect.moveBottomRight(midPoint);
278 newLabelBoundingRect.moveTopRight(midPoint);
280 transition->setLabelBoundingRect(newLabelBoundingRect);
283void QuickTransitionItem::updateSource()
285 const auto *transition = toTransition();
289 disconnect(m_sourceStateConnection);
290 if (
const auto *source = toTransition()->sourceState()) {
292 this, &QuickTransitionItem::updatePosition);
296void QuickTransitionItem::updateTarget()
298 const auto *transition = toTransition();
302 disconnect(m_targetStateConnection);
303 if (
const auto *targetState = toTransition()->targetState()) {
305 this, &QuickTransitionItem::updatePosition);
309Transition *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