QStateMachine QML / enums
-
Following this example, I am trying to use a C++ QStateMachine in QML, exposing the current state as property:
My property is an enum, as I need to use many more states in the real application.class Application : public QObject { public: Q_OBJECT //QML_ELEMENT // prevents from using the State in when clause of QML states at all QML_NAMED_ELEMENT(App) // ok, but emits an error in QML enum State { OFF, ON, }; // using enum class doesn't make a difference Q_ENUM(State) Q_PROPERTY(Application::State state READ state NOTIFY stateChanged) Application() { auto offState = new QState(&m_stateMachine); offState->assignProperty(&m_stateMachine, g_state_id, State::OFF); QObject::connect(offState, &QState::entered, this, &Application::setState); auto onState = new QState(&m_stateMachine); onState->assignProperty(&m_stateMachine, g_state_id, State::ON); QObject::connect(onState, &QState::entered, this, &Application::setState); offState->addTransition(this, &Application::toggle, onState); onState->addTransition(this, &Application::toggle, offState); m_stateMachine.setInitialState(offState); m_stateMachine.start(); } Application::State state() const { return static_cast<Application::State> (m_stateMachine.property("state").toInt()); } bool isState(Application::State theState) const { return state() == theState; } signals: void stateChanged(); void toggle(); private: QStateMachine m_stateMachine; State m_state; void Application::setState() { if (state() == m_state) return; m_state = state(); emit stateChanged(); } };In my RowLayout element, I want to use the state like so:
// ... inside some RowLayout target onOffBtn is a simple Button states : [ State { name: "off" //when: app.state === 0 // Ok //when: app.isState(App.OFF) // not working at all (0 in all cases) when: app.state === App.OFF // TypeError: Cannot read property 'state' of null PropertyChanges { target: onOffBtn; text: "turn ON"; } }, State { name: "on" //when: app.state === 1 // Ok //when: app.isState(App.ON) // not working at all when: app.state === App.ON PropertyChanges { target: onOffBtn; text: "turn OFF"; } } ]Using the enum state from the registered type App, I get an error about the property state being null. But the code is working, the when part is evaluated correctly.
Using the enum in another context (QML Button), likeonClicked : { if (app.isState(App.OFF)) console.log("app.isState(App.OFF)") else if (app.isState(App.ON)) console.log("app.isState(App.ON)") if (app.state === App.OFF) console.log("app.state === App.OFF") else if (app.state === App.ON) console.log("app.state === App.ON") }onClicked produces the expected outputs without errors or warnings.
I expected a much better way coupling the C++ SM with QML, one without using enums to react on the current state in QML (not using the QML StateMachine type).
Am I using the states / property binding the wrong way? What is the suggested way to handle the current C++ SM state in QML?