KDStateMachineEditor API Documentation 2.1
Loading...
Searching...
No Matches
layoutimportexport.cpp
Go to the documentation of this file.
1/*
2 This file is part of the KDAB State Machine Editor Library.
3
4 SPDX-FileCopyrightText: 2014 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
5 Author: Kevin Funk <kevin.funk@kdab.com>
6
7 SPDX-License-Identifier: LGPL-2.1-only OR LicenseRef-KDAB-KDStateMachineEditor
8
9 Licensees holding valid commercial KDAB State Machine Editor Library
10 licenses may use this file in accordance with the KDAB State Machine Editor
11 Library License Agreement provided with the Software.
12
13 Contact info@kdab.com if any conditions of this licensing are not clear to you.
14*/
15
16#include "layoutimportexport.h"
17
18#include "element.h"
19#include "state.h"
20#include "transition.h"
21
22#include "debug.h"
23
24#include <QIODevice>
25#include <QJsonArray>
26#include <QJsonObject>
27#include <QPainterPath>
28#include <QPointF>
29#include <QRectF>
30
31using namespace KDSME;
32
33namespace {
34
35QJsonObject stateLayoutToJson(const State *state)
36{
37 QJsonObject res;
38 res[u"label"] = state->label();
39 res[u"x"] = state->pos().x();
40 res[u"y"] = state->pos().y();
41 res[u"width"] = state->width();
42 res[u"height"] = state->height();
43 return res;
44}
45
46QJsonObject transitionLayoutToJson(const Transition *transition)
47{
48 QJsonObject res;
49 res[u"label"] = transition->label();
50 res[u"x"] = transition->pos().x();
51 res[u"y"] = transition->pos().y();
52 const QRectF labelRect = transition->labelBoundingRect();
53 QJsonObject lbr;
54 lbr[u"x"] = labelRect.x();
55 lbr[u"y"] = labelRect.y();
56 lbr[u"width"] = labelRect.width();
57 lbr[u"height"] = labelRect.height();
58 res[u"labelBoundingRect"] = lbr;
59 QByteArray shapeData;
60 QDataStream ds(&shapeData, QIODevice::WriteOnly);
61 ds << transition->shape();
62 res[u"shape"] = QLatin1String(shapeData.toBase64());
63 return res;
64}
65
66void importStateLayout(const QJsonObject &data, State *state)
67{
68 const auto x = data.find(u"x");
69 if (x == data.end())
70 return;
71
72 const auto y = data.find(u"y");
73 if (y == data.end())
74 return;
75
76 const auto width = data.find(u"width");
77 if (width == data.end())
78 return;
79
80 const auto height = data.find(u"height");
81 if (height == data.end())
82 return;
83
84 state->setPos(QPointF((*x).toDouble(), (*y).toDouble()));
85 state->setWidth((*width).toDouble());
86 state->setHeight((*height).toDouble());
87}
88
89bool isValidState(const QJsonObject &data, const State *state)
90{
91 return data.value(u"label") == state->label() && data.contains(u"x") && data.contains(u"y") && data.contains(u"width") && data.contains(u"height");
92}
93
94bool isValidTransition(const QJsonObject &data, const Transition *state)
95{
96 return data.value(u"label") == state->label() && data.contains(u"x") && data.contains(u"y") && data.contains(u"labelBoundingRect") && data.contains(u"shape");
97}
98
99void importTransitionLayout(const QJsonObject &data, Transition *transition)
100{
101 const auto x = data.find(u"x");
102 if (x == data.end())
103 return;
104
105 const auto y = data.find(u"y");
106 if (y == data.end())
107 return;
108
109 const auto lbrIt = data.find(u"labelBoundingRect");
110 if (lbrIt == data.end())
111 return;
112
113 const auto shape = data.find(u"shape");
114 if (shape == data.end())
115 return;
116
117 transition->setPos(QPointF((*x).toDouble(), (*y).toDouble()));
118 QJsonObject lbr = (*lbrIt).toObject();
119 transition->setLabelBoundingRect(QRectF(lbr[u"x"].toDouble(),
120 lbr[u"y"].toDouble(),
121 lbr[u"width"].toDouble(),
122 lbr[u"height"].toDouble()));
123 QByteArray shapeData = QByteArray::fromBase64((*shape).toString().toLatin1());
124 QPainterPath shapePath;
125 QDataStream ds(&shapeData, QIODevice::ReadOnly);
126 ds >> shapePath;
127 transition->setShape(shapePath);
128}
129
130} // anonymous namespace
131
132void LayoutImportExport::importLayout(const QJsonObject &data, State *state)
133{
134 importStateLayout(data, state);
135
136 const QJsonArray states = data.value(u"childStates").toArray();
137 for (int i = 0; i < states.size() && i < state->childStates().size(); ++i) {
138 State *child = state->childStates().at(i);
139 importLayout(states.at(i).toObject(), child);
140 }
141
142 const QJsonArray transitions = data.value(u"transitions").toArray();
143 for (int i = 0; i < transitions.size() && i < state->transitions().size(); ++i) {
144 Transition *child = state->transitions().at(i);
145 importTransitionLayout(transitions.at(i).toObject(), child);
146 }
147}
148
150{
151 QJsonObject res = stateLayoutToJson(state);
152
153 QJsonArray states;
154 const auto childStates = state->childStates();
155 for (const State *child : childStates) {
156 states.push_back(exportLayout(child)); // cppcheck-suppress useStlAlgorithm
157 }
158 res[u"childStates"] = states;
159
160 QJsonArray transitions;
161 const auto stateTransitions = state->transitions();
162 for (const Transition *child : stateTransitions) {
163 transitions.push_back(transitionLayoutToJson(child)); // cppcheck-suppress useStlAlgorithm
164 }
165 res[u"transitions"] = transitions;
166
167 return res;
168}
169
170bool LayoutImportExport::matches(const QJsonObject &data, State *state) // cppcheck-suppress constParameterPointer
171{
172 if (!isValidState(data, state))
173 return false;
174
175 const QJsonArray states = data.value(u"childStates").toArray();
176 if (states.size() != state->childStates().size())
177 return false;
178
179 for (int i = 0; i < states.size(); ++i) {
180 State *child = state->childStates().at(i);
181 if (!matches(states.at(i).toObject(), child))
182 return false;
183 }
184
185 const QJsonArray transitions = data.value(u"transitions").toArray();
186 if (transitions.size() != state->transitions().size())
187 return false;
188
189 for (int i = 0; i < transitions.size(); ++i) {
190 const Transition *child = state->transitions().at(i);
191 if (!isValidTransition(transitions.at(i).toObject(), child))
192 return false;
193 }
194
195 return true;
196}
qreal width
Definition element.h:43
void setPos(const QPointF &pos)
Definition element.cpp:97
qreal height
Definition element.h:44
QPointF pos
The position of the element from the top-left corner.
Definition element.h:42
void setWidth(qreal width)
Definition element.cpp:111
QString label
Definition element.h:40
void setHeight(qreal height)
Definition element.cpp:125
QList< Transition * > transitions() const
Definition state.cpp:98
QList< State * > childStates() const
Definition state.cpp:93
void setShape(const QPainterPath &shape)
void setLabelBoundingRect(const QRectF &rect)
QRectF labelBoundingRect
Definition transition.h:31
QPainterPath shape
The exact shape of this transition.
Definition transition.h:30
KDSME_CORE_EXPORT void importLayout(const QJsonObject &data, State *state)
Import layout data to set properties of state and its children.
KDSME_CORE_EXPORT QJsonObject exportLayout(const State *state)
Export layout of state into a machine-parsable JSON format.
KDSME_CORE_EXPORT bool matches(const QJsonObject &data, State *state)
Check if the ids in data still match the ids from the object tree represented by state.

© Klarälvdalens Datakonsult AB (KDAB)
"The Qt, C++ and OpenGL Experts"
https://www.kdab.com/
KDStateMachineEditor
Create Qt State Machine metacode using a graphical user interface
https://github.com/KDAB/KDStateMachineEditor
Generated on Tue Jul 15 2025 15:21:47 for KDStateMachineEditor API Documentation by doxygen 1.9.8