The general approach is good, but instead of "directing" the QML side you provide data the QML side can react to.
Basically you combine two things:
* QML can easily and automatically react to changes in property values. This is a central concept in QML, called "property bindings"
* QStateMachine can assign values to properties when it enters state, see QState::assignProperty().
You combine that by having a mediator object, something that is known to both the state machine and the QML engine, carrying the properties that you want the state machine to control and the QML side to follow.
{
Q_OBJECT
// make this a QUrl type property if you need to pass the full URL
// here I assume that you pass a path relative to the QML that has the Loader
Q_PROPERTY(QString currentScreen MEMBER m_currentScreen NOTIFY currentScreenChanged
)
public:
explicit AppState
(QObject *parent
= 0);
signals:
void currentScreenChanged();
private:
};
class AppState : public QObject
{
Q_OBJECT
// make this a QUrl type property if you need to pass the full URL
// here I assume that you pass a path relative to the QML that has the Loader
Q_PROPERTY(QString currentScreen MEMBER m_currentScreen NOTIFY currentScreenChanged)
public:
explicit AppState(QObject *parent = 0);
signals:
void currentScreenChanged();
private:
QString m_currentScreen;
};
To copy to clipboard, switch view to plain text mode
An instance of that is passed to both QML engine setup and state machine setup
AppState *appState = new AppState();
qmlEngine->rootContext()->setContextProperty("_appState", appState);
createStateMachine(appState);
AppState *appState = new AppState();
qmlEngine->rootContext()->setContextProperty("_appState", appState);
createStateMachine(appState);
To copy to clipboard, switch view to plain text mode
The State machine can then do things like this
QState *startState = new QState(m_stateMachine);
startState->assignProperty(m_appState, "currentScreen", "screens/screen2/Screen2.qml");
QState *startState = new QState(m_stateMachine);
startState->assignProperty(m_appState, "currentScreen", "screens/screen2/Screen2.qml");
To copy to clipboard, switch view to plain text mode
The QML side can then do things like
Loader {
source: _appState.currentScreen
}
Loader {
source: _appState.currentScreen
}
To copy to clipboard, switch view to plain text mode
A very similar technique can be done for the other way aroound, when the QML side needs to trigger state transitions.
You either use an additional interface object or extend the AppState class.
public slots:
void reset() { emit triggerReset(); }
signals:
void triggerReset();
public slots:
void reset() { emit triggerReset(); }
signals:
void triggerReset();
To copy to clipboard, switch view to plain text mode
The state machine can use that as a source for transitions
runningState->addTranstion(m_appState, SIGNAL(triggerReset()), startState);
runningState->addTranstion(m_appState, SIGNAL(triggerReset()), startState);
To copy to clipboard, switch view to plain text mode
The QML side can ask for that
MouseArea {
onClicked: _appState.reset();
}
// or
Keys.onEscapePressed: _appState.reset()
MouseArea {
onClicked: _appState.reset();
}
// or
Keys.onEscapePressed: _appState.reset()
To copy to clipboard, switch view to plain text mode
Cheers,
_
Bookmarks