33#define KDSME_QML_MODULE "QtQml.StateMachine"
34#define KDSME_QML_MODULE_VERSION "1.0"
39 explicit LevelIncrementer(
int *level)
54QString elementToComponent(
Element *element)
56 QString customType = element->property(
"com.kdab.KDSME.DSMExporter.customType").toString();
57 if (!customType.isEmpty())
63 return QStringLiteral(
"StateMachine");
65 return QStringLiteral(
"FinalState");
67 return QStringLiteral(
"HistoryState");
69 return QStringLiteral(
"State");
72 return QStringLiteral(
"SignalTransition");
74 return QStringLiteral(
"TimeoutTransition");
85QString toQmlId(
const QString &input)
92 out.begin(), out.end(),
94 return !(c.isLetterOrNumber() || c == u
'_');
98 out[0] = out.at(0).toLower();
104struct QmlExporter::Private
106 explicit Private(QByteArray *array);
107 explicit Private(QIODevice *device);
110 bool writeState(
State *state);
111 bool writeStateInner(
State *state);
113 void writeAttribute(
Element *element,
const QString &name,
const QString &value);
115 [[nodiscard]] QString indention()
const;
118 int m_indent, m_level;
121QmlExporter::Private::Private(QByteArray *array)
128QmlExporter::Private::Private(QIODevice *device)
136 : d(new Private(array))
142 : d(new Private(device))
171 if (d->m_out.status() != QTextStream::Ok) {
172 setErrorString(QStringLiteral(
"Invalid QTextStream status: %1").arg(d->m_out.status()));
176 const bool success = d->writeStateMachine(machine);
181bool QmlExporter::Private::writeStateMachine(
StateMachine *machine)
186 m_out << indention() << importStmt;
188 const QStringList customImports = machine->property(
"com.kdab.KDSME.DSMExporter.customImports").toStringList();
189 for (
const QString &customImport : customImports)
190 m_out << customImport <<
'\n';
193 const QString qmlComponent = elementToComponent(machine);
194 m_out << indention() << QStringLiteral(
"%1 {\n").arg(qmlComponent);
195 if (!writeStateInner(machine))
197 m_out << indention() << QStringLiteral(
"}\n");
201bool QmlExporter::Private::writeState(
State *state)
205 if (qobject_cast<PseudoState *>(state))
208 if (!state->property(
"com.kdab.KDSME.DSMExporter.externalSource").isNull())
211 const QString qmlComponent = elementToComponent(state);
212 m_out << indention() << QStringLiteral(
"%1 {\n").arg(qmlComponent);
213 if (!writeStateInner(state))
215 m_out << indention() << QStringLiteral(
"}\n");
219void QmlExporter::Private::writeAttribute(
Element *element,
const QString &name,
const QString &value)
224 const QVariant implBindingNames = element->property(
"com.kdab.KDSME.DSMExporter.implBindingNames");
225 if (!implBindingNames.isNull()) {
226 const QString v = implBindingNames.toMap().value(name).toString();
232 m_out << indention() << QStringLiteral(
"%1: %2\n").arg(name).arg(value);
235bool QmlExporter::Private::writeStateInner(
State *state)
239 const LevelIncrementer levelinc(&m_level);
242 writeAttribute(state, QStringLiteral(
"id"), toQmlId(state->
label()));
244 if (
auto *stateMachine = qobject_cast<StateMachine *>(state)) {
245 const QString running = stateMachine->property(
"com.kdab.KDSME.DSMExporter.running").toString();
246 writeAttribute(state, QStringLiteral(
"running"), running);
250 writeAttribute(state, QStringLiteral(
"childMode"), QStringLiteral(
"State.ParallelStates"));
254 writeAttribute(state, QStringLiteral(
"initialState"), toQmlId(initial->label()));
257 if (
auto *historyState = qobject_cast<HistoryState *>(state)) {
258 if (
const State *defaultState = historyState->defaultState())
259 writeAttribute(state, QStringLiteral(
"defaultState"), toQmlId(defaultState->label()));
261 writeAttribute(state, QStringLiteral(
"historyType"), QStringLiteral(
"HistoryState.DeepHistory"));
264 writeAttribute(state, QStringLiteral(
"onEntered"), state->
onEntry());
265 writeAttribute(state, QStringLiteral(
"onExited"), state->
onExit());
268 if (std::any_of(childStates.begin(), childStates.end(),
269 [
this](
State *child) { return !writeState(child); })) {
273 const auto stateTransitions = state->
transitions();
274 return std::all_of(stateTransitions.begin(), stateTransitions.end(),
275 [
this](
Transition *child) { return writeTransition(child); });
278bool QmlExporter::Private::writeTransition(
Transition *transition)
280 Q_ASSERT(transition);
281 m_out << indention() << QStringLiteral(
"%1 {\n").arg(elementToComponent(transition));
283 const LevelIncrementer levelinc(&m_level);
286 writeAttribute(transition, QStringLiteral(
"id"), toQmlId(transition->
label()));
289 writeAttribute(transition, QStringLiteral(
"targetState"), toQmlId(transition->
targetState()->
label()));
293 auto t = qobject_cast<SignalTransition *>(transition);
294 writeAttribute(transition, QStringLiteral(
"signal"), t->signal());
298 auto t = qobject_cast<TimeoutTransition *>(transition);
299 if (t->timeout() != -1) {
300 writeAttribute(transition, QStringLiteral(
"timeout"), QString::number(t->timeout()));
304 writeAttribute(transition, QStringLiteral(
"guard"), transition->
guard());
306 m_out << indention() << QStringLiteral(
"}\n");
310QString QmlExporter::Private::indention()
const
312 return QString { m_indent * m_level, u
' ' };
void setErrorString(const QString &errorString)
void setIndent(int indent)
virtual bool exportMachine(StateMachine *machine) override
QmlExporter(QByteArray *array)
QList< Transition * > transitions() const
QList< State * > childStates() const
Type type() const override
KDSME::State * targetState
KDSME_CORE_EXPORT State * findInitialState(const State *state)
#define KDSME_QML_MODULE_VERSION