예제 #1
0
void IoModule::logic_init_lamp_machinestat()
{
	pMachine = new QStateMachine(this);
	m_pTimer = new QTimer(this);
	m_pTimer->setSingleShot(true);
	QState *pInitS = new QState();
	QState *pInitS1 = new QState(pInitS);
	QState *pInitS2 = new QState(pInitS);
	QState *pInitS3 = new QState(pInitS);
	QState *pInitS4 = new QState(pInitS);
	pInitS->setInitialState(pInitS1);
	pInitS1->addTransition(m_pTimer, SIGNAL(timeout()), pInitS2);
	pInitS2->addTransition(m_pTimer, SIGNAL(timeout()), pInitS3);
	pInitS3->addTransition(m_pTimer, SIGNAL(timeout()), pInitS4);
	pInitS4->addTransition(this, SIGNAL(resetMachine()), pInitS1);

	QState *pOperationS = new QState();
	//pInitS->addTransition(this, SIGNAL(initLampSuccess()),pOperationS);
	pMachine->addState(pInitS);//³õʼ»¯×´Ì¬;
	pMachine->addState(pOperationS);//²Ù×÷״̬;
	pMachine->setInitialState(pInitS);

	connect(pInitS1, SIGNAL(entered()), this, SLOT(init_s1()));
	connect(pInitS2, SIGNAL(entered()), this, SLOT(init_s2()));
	connect(pInitS3, SIGNAL(entered()), this, SLOT(init_s3()));
	connect(pInitS4, SIGNAL(entered()), this, SLOT(init_s4()));
	connect(pOperationS, SIGNAL(entered()), this, SLOT(operation_s()));
	
}
예제 #2
0
ExampleView::ExampleView(QWidget* parent)
   : QFrame(parent)
      {
      _score = 0;
      setAcceptDrops(true);
      setFocusPolicy(Qt::StrongFocus);
      resetMatrix();
      _fgPixmap = nullptr;
      if (preferences.getBool(PREF_UI_CANVAS_FG_USECOLOR))
            _fgColor = preferences.getColor(PREF_UI_CANVAS_FG_COLOR);
      else {
            _fgPixmap = new QPixmap(preferences.getString(PREF_UI_CANVAS_FG_WALLPAPER));
            if (_fgPixmap == 0 || _fgPixmap->isNull())
                  qDebug("no valid pixmap %s", qPrintable(preferences.getString(PREF_UI_CANVAS_FG_WALLPAPER)));
            }
      // setup drag canvas state
      sm          = new QStateMachine(this);
      QState* stateActive = new QState;

      QState* s1 = new QState(stateActive);
      s1->setObjectName("example-normal");
      s1->assignProperty(this, "cursor", QCursor(Qt::ArrowCursor));

      QState* s = new QState(stateActive);
      s->setObjectName("example-drag");
      s->assignProperty(this, "cursor", QCursor(Qt::SizeAllCursor));
      QEventTransition* cl = new QEventTransition(this, QEvent::MouseButtonRelease);
      cl->setTargetState(s1);
      s->addTransition(cl);
      s1->addTransition(new DragTransitionExampleView(this));


      sm->addState(stateActive);
      stateActive->setInitialState(s1);
      sm->setInitialState(stateActive);

      sm->start();
      }
예제 #3
0
//! [0]
PadNavigator::PadNavigator(const QSize &size, QWidget *parent)
    : QGraphicsView(parent)
{
//! [0]
//! [1]
    // Splash item
    SplashItem *splash = new SplashItem;
    splash->setZValue(1);
//! [1]

//! [2]
    // Pad item
    FlippablePad *pad = new FlippablePad(size);
    QGraphicsRotation *flipRotation = new QGraphicsRotation(pad);
    QGraphicsRotation *xRotation = new QGraphicsRotation(pad);
    QGraphicsRotation *yRotation = new QGraphicsRotation(pad);
    flipRotation->setAxis(Qt::YAxis);
    xRotation->setAxis(Qt::YAxis);
    yRotation->setAxis(Qt::XAxis);
    pad->setTransformations(QList<QGraphicsTransform *>()
                            << flipRotation
                            << xRotation << yRotation);
//! [2]

//! [3]
    // Back (proxy widget) item
    QGraphicsProxyWidget *backItem = new QGraphicsProxyWidget(pad);
    QWidget *widget = new QWidget;
    form.setupUi(widget);
    form.hostName->setFocus();
    backItem->setWidget(widget);
    backItem->setVisible(false);
    backItem->setFocus();
    backItem->setCacheMode(QGraphicsItem::ItemCoordinateCache);
    const QRectF r = backItem->rect();
    backItem->setTransform(QTransform()
                           .rotate(180, Qt::YAxis)
                           .translate(-r.width()/2, -r.height()/2));
//! [3]

//! [4]
    // Selection item
    RoundRectItem *selectionItem = new RoundRectItem(QRectF(-60, -60, 120, 120), Qt::gray, pad);
    selectionItem->setZValue(0.5);
//! [4]

//! [5]
    // Splash animations
    QPropertyAnimation *smoothSplashMove = new QPropertyAnimation(splash, "y");
    QPropertyAnimation *smoothSplashOpacity = new QPropertyAnimation(splash, "opacity");
    smoothSplashMove->setEasingCurve(QEasingCurve::InQuad);
    smoothSplashMove->setDuration(250);
    smoothSplashOpacity->setDuration(250);
//! [5]

//! [6]
    // Selection animation
    QPropertyAnimation *smoothXSelection = new QPropertyAnimation(selectionItem, "x");
    QPropertyAnimation *smoothYSelection = new QPropertyAnimation(selectionItem, "y");
    QPropertyAnimation *smoothXRotation = new QPropertyAnimation(xRotation, "angle");
    QPropertyAnimation *smoothYRotation = new QPropertyAnimation(yRotation, "angle");
    smoothXSelection->setDuration(125);
    smoothYSelection->setDuration(125);
    smoothXRotation->setDuration(125);
    smoothYRotation->setDuration(125);
    smoothXSelection->setEasingCurve(QEasingCurve::InOutQuad);
    smoothYSelection->setEasingCurve(QEasingCurve::InOutQuad);
    smoothXRotation->setEasingCurve(QEasingCurve::InOutQuad);
    smoothYRotation->setEasingCurve(QEasingCurve::InOutQuad);
//! [6]

//! [7]
    // Flip animation setup
    QPropertyAnimation *smoothFlipRotation = new QPropertyAnimation(flipRotation, "angle");
    QPropertyAnimation *smoothFlipScale = new QPropertyAnimation(pad, "scale");
    QPropertyAnimation *smoothFlipXRotation = new QPropertyAnimation(xRotation, "angle");
    QPropertyAnimation *smoothFlipYRotation = new QPropertyAnimation(yRotation, "angle");
    QParallelAnimationGroup *flipAnimation = new QParallelAnimationGroup(this);
    smoothFlipScale->setDuration(500);
    smoothFlipRotation->setDuration(500);
    smoothFlipXRotation->setDuration(500);
    smoothFlipYRotation->setDuration(500);
    smoothFlipScale->setEasingCurve(QEasingCurve::InOutQuad);
    smoothFlipRotation->setEasingCurve(QEasingCurve::InOutQuad);
    smoothFlipXRotation->setEasingCurve(QEasingCurve::InOutQuad);
    smoothFlipYRotation->setEasingCurve(QEasingCurve::InOutQuad);
    smoothFlipScale->setKeyValueAt(0, qvariant_cast<qreal>(1.0));
    smoothFlipScale->setKeyValueAt(0.5, qvariant_cast<qreal>(0.7));
    smoothFlipScale->setKeyValueAt(1, qvariant_cast<qreal>(1.0));
    flipAnimation->addAnimation(smoothFlipRotation);
    flipAnimation->addAnimation(smoothFlipScale);
    flipAnimation->addAnimation(smoothFlipXRotation);
    flipAnimation->addAnimation(smoothFlipYRotation);
//! [7]

//! [8]
    // Flip animation delayed property assignment
    QSequentialAnimationGroup *setVariablesSequence = new QSequentialAnimationGroup;
    QPropertyAnimation *setFillAnimation = new QPropertyAnimation(pad, "fill");
    QPropertyAnimation *setBackItemVisibleAnimation = new QPropertyAnimation(backItem, "visible");
    QPropertyAnimation *setSelectionItemVisibleAnimation = new QPropertyAnimation(selectionItem, "visible");
    setFillAnimation->setDuration(0);
    setBackItemVisibleAnimation->setDuration(0);
    setSelectionItemVisibleAnimation->setDuration(0);
    setVariablesSequence->addPause(250);
    setVariablesSequence->addAnimation(setBackItemVisibleAnimation);
    setVariablesSequence->addAnimation(setSelectionItemVisibleAnimation);
    setVariablesSequence->addAnimation(setFillAnimation);
    flipAnimation->addAnimation(setVariablesSequence);
//! [8]

//! [9]
    // Build the state machine
    QStateMachine *stateMachine = new QStateMachine(this);
    QState *splashState = new QState(stateMachine);
    QState *frontState = new QState(stateMachine);
    QHistoryState *historyState = new QHistoryState(frontState);
    QState *backState = new QState(stateMachine);
//! [9]
//! [10]
    frontState->assignProperty(pad, "fill", false);
    frontState->assignProperty(splash, "opacity", 0.0);
    frontState->assignProperty(backItem, "visible", false);
    frontState->assignProperty(flipRotation, "angle", qvariant_cast<qreal>(0.0));
    frontState->assignProperty(selectionItem, "visible", true);
    backState->assignProperty(pad, "fill", true);
    backState->assignProperty(backItem, "visible", true);
    backState->assignProperty(xRotation, "angle", qvariant_cast<qreal>(0.0));
    backState->assignProperty(yRotation, "angle", qvariant_cast<qreal>(0.0));
    backState->assignProperty(flipRotation, "angle", qvariant_cast<qreal>(180.0));
    backState->assignProperty(selectionItem, "visible", false);
    stateMachine->addDefaultAnimation(smoothXRotation);
    stateMachine->addDefaultAnimation(smoothYRotation);
    stateMachine->addDefaultAnimation(smoothXSelection);
    stateMachine->addDefaultAnimation(smoothYSelection);
    stateMachine->setInitialState(splashState);
//! [10]

//! [11]
    // Transitions
    QEventTransition *anyKeyTransition = new QEventTransition(this, QEvent::KeyPress, splashState);
    anyKeyTransition->setTargetState(frontState);
    anyKeyTransition->addAnimation(smoothSplashMove);
    anyKeyTransition->addAnimation(smoothSplashOpacity);
//! [11]

//! [12]
    QKeyEventTransition *enterTransition = new QKeyEventTransition(this, QEvent::KeyPress,
                                                                   Qt::Key_Enter, backState);
    QKeyEventTransition *returnTransition = new QKeyEventTransition(this, QEvent::KeyPress,
                                                                    Qt::Key_Return, backState);
    QKeyEventTransition *backEnterTransition = new QKeyEventTransition(this, QEvent::KeyPress,
                                                                       Qt::Key_Enter, frontState);
    QKeyEventTransition *backReturnTransition = new QKeyEventTransition(this, QEvent::KeyPress,
                                                                        Qt::Key_Return, frontState);
    enterTransition->setTargetState(historyState);
    returnTransition->setTargetState(historyState);
    backEnterTransition->setTargetState(backState);
    backReturnTransition->setTargetState(backState);
    enterTransition->addAnimation(flipAnimation);
    returnTransition->addAnimation(flipAnimation);
    backEnterTransition->addAnimation(flipAnimation);
    backReturnTransition->addAnimation(flipAnimation);
//! [12]

//! [13]
    // Create substates for each icon; store in temporary grid.
    int columns = size.width();
    int rows = size.height();
    QVector< QVector< QState * > > stateGrid;
    stateGrid.resize(rows);
    for (int y = 0; y < rows; ++y) {
        stateGrid[y].resize(columns);
        for (int x = 0; x < columns; ++x)
            stateGrid[y][x] = new QState(frontState);
    }
    frontState->setInitialState(stateGrid[0][0]);
    selectionItem->setPos(pad->iconAt(0, 0)->pos());
//! [13]

//! [14]
    // Enable key navigation using state transitions
    for (int y = 0; y < rows; ++y) {
        for (int x = 0; x < columns; ++x) {
            QState *state = stateGrid[y][x];
            QKeyEventTransition *rightTransition = new QKeyEventTransition(this, QEvent::KeyPress,
                                                                           Qt::Key_Right, state);
            QKeyEventTransition *leftTransition = new QKeyEventTransition(this, QEvent::KeyPress,
                                                                          Qt::Key_Left, state);
            QKeyEventTransition *downTransition = new QKeyEventTransition(this, QEvent::KeyPress,
                                                                          Qt::Key_Down, state);
            QKeyEventTransition *upTransition = new QKeyEventTransition(this, QEvent::KeyPress,
                                                                        Qt::Key_Up, state);
            rightTransition->setTargetState(stateGrid[y][(x + 1) % columns]);
            leftTransition->setTargetState(stateGrid[y][((x - 1) + columns) % columns]);
            downTransition->setTargetState(stateGrid[(y + 1) % rows][x]);
            upTransition->setTargetState(stateGrid[((y - 1) + rows) % rows][x]);
//! [14]
//! [15]
            RoundRectItem *icon = pad->iconAt(x, y);
            state->assignProperty(xRotation, "angle", -icon->x() / 6.0);
            state->assignProperty(yRotation, "angle", icon->y() / 6.0);
            state->assignProperty(selectionItem, "x", icon->x());
            state->assignProperty(selectionItem, "y", icon->y());
            frontState->assignProperty(icon, "visible", true);
            backState->assignProperty(icon, "visible", false);

            QPropertyAnimation *setIconVisibleAnimation = new QPropertyAnimation(icon, "visible");
            setIconVisibleAnimation->setDuration(0);
            setVariablesSequence->addAnimation(setIconVisibleAnimation);
        }
    }
//! [15]

//! [16]
    // Scene
    QGraphicsScene *scene = new QGraphicsScene(this);
    scene->setBackgroundBrush(QPixmap(":/images/blue_angle_swirl.jpg"));
    scene->setItemIndexMethod(QGraphicsScene::NoIndex);
    scene->addItem(pad);
    scene->setSceneRect(scene->itemsBoundingRect());
    setScene(scene);
//! [16]

//! [17]
    // Adjust splash item to scene contents
    const QRectF sbr = splash->boundingRect();
    splash->setPos(-sbr.width() / 2, scene->sceneRect().top() - 2);
    frontState->assignProperty(splash, "y", splash->y() - 100.0);
    scene->addItem(splash);
//! [17]

//! [18]
    // View
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setMinimumSize(50, 50);
    setViewportUpdateMode(FullViewportUpdate);
    setCacheMode(CacheBackground);
    setRenderHints(QPainter::Antialiasing
                   | QPainter::SmoothPixmapTransform
                   | QPainter::TextAntialiasing);
#ifndef QT_NO_OPENGL
    setViewport(new QOpenGLWidget);
#endif

    stateMachine->start();
//! [18]
}
예제 #4
0
        void Protocol::prepareStateMachine(){
            qDebug() << "Protocol: Initialising Protocol State";
            QStateMachine *machine = new QStateMachine(this);

            /**
             *  Main states are connected, disconnected and done, we start disconnected
             *  and turn to connected when the socket is operational.
             *  All the other states are part of the connected state
             */
            QState *disconnected = new QState();
            QState *connected = new QState();
            QFinalState *done = new QFinalState();

            /**
             *  When first connected, we need to know the protocol version,
             *  then request authentication. We then either turn to the authenticated
             *  state or flee to *done
             */
            QState *waitingproto = new QState(connected);
            QState *waitingauthrequest = new QState(connected);
            QState *waitingauthstatus = new QState(connected);
            QState *authenticated = new QState(connected);
            connected->setInitialState(waitingproto);

            /**
             * When authenticated, the user must provide some information about himself
             * (nickname, status, planet picture, user picture, attack picture)
             * Then the user can request to join the chat room, get the list of games and users
             * join a game or create a game
             * In the chat room, the user sends and receives messages, and can eventually exit
             */
            QState *waitinguserdetails = new QState(authenticated);
            QState *waitingcommand = new QState(authenticated);
            QState *inchat = new QState(authenticated);
            QState *waitinggamecreation = new QState(authenticated);
            QState *waitinggamelist = new QState(authenticated);
            QState *waitinguserlist = new QState(authenticated);
            QState *joinedgame = new QState(authenticated);
            authenticated->setInitialState(waitinguserdetails);

            /**
             * When entering the game, we wait for the users to show up
             * then receive the game map
             * we then wait for the game to unpause, and the game progresses till
             * there's a winner or cancellation
             */
            QState *waitinguser = new QState(joinedgame);
            QState *waitingmap = new QState(joinedgame);
            QState *paused = new QState(joinedgame);
            QState *ingame = new QState(joinedgame);
            joinedgame->setInitialState(waitinguser);

            qDebug() << "Protocol: Connecting Protocol Signals";
            disconnected->addTransition(this, SIGNAL(connected()), connected);
            connected->addTransition(this, SIGNAL(closed()), done);
            waitingproto->addTransition(this, SIGNAL(protocol(QString)), waitingauthrequest);
            waitingauthrequest->addTransition(this, SIGNAL(authrequest(QString,QString)), waitingauthstatus);
            waitingauthstatus->addTransition(this, SIGNAL(authenticated()), authenticated);
            waitingauthstatus->addTransition(this, SIGNAL(protocolError(QString)), done);

            machine->addState(disconnected);
            machine->addState(connected);
            machine->setInitialState(disconnected);

            qDebug() << "Protocol: Starting State Machine";
            machine->start();
        }
Creation_FromState::Creation_FromState(
        const ToolPalette& stateMachine,
        const Path<ScenarioModel>& scenarioPath,
        iscore::CommandStack& stack,
        QState* parent):
    CreationState{stateMachine, stack, std::move(scenarioPath), parent}
{
    using namespace Scenario::Command;
    auto finalState = new QFinalState{this};
    connect(finalState, &QState::entered, [&] ()
    {
        clearCreatedIds();
    });

    QState* mainState = new QState{this};
    {
        auto pressed = new QState{mainState};
        auto released = new QState{mainState};
        auto move_nothing = new StrongQState<ScenarioElement::Nothing + Modifier::Move_tag::value>{mainState};
        auto move_state = new StrongQState<ScenarioElement::State + Modifier::Move_tag::value>{mainState};
        auto move_event = new StrongQState<ScenarioElement::Event + Modifier::Move_tag::value>{mainState};
        auto move_timenode = new StrongQState<ScenarioElement::TimeNode + Modifier::Move_tag::value>{mainState};

        // General setup
        mainState->setInitialState(pressed);
        released->addTransition(finalState);

        // Release
        make_transition<ReleaseOnAnything_Transition>(mainState, released);

        // Pressed -> ...
        make_transition<MoveOnNothing_Transition>(pressed, move_state, *this);
        make_transition<MoveOnNothing_Transition>(pressed, move_nothing, *this);

        /// MoveOnNothing -> ...
        // MoveOnNothing -> MoveOnNothing.
        make_transition<MoveOnNothing_Transition>(move_nothing, move_nothing, *this);

        // MoveOnNothing -> MoveOnState.
        add_transition(move_nothing, move_state,
                       [&] () { rollback(); createToState(); });

        // MoveOnNothing -> MoveOnEvent.
        add_transition(move_nothing, move_event,
                       [&] () { rollback(); createToEvent(); });

        // MoveOnNothing -> MoveOnTimeNode
        add_transition(move_nothing, move_timenode,
                       [&] () { rollback(); createToTimeNode(); });


        /// MoveOnState -> ...
        // MoveOnState -> MoveOnNothing
        add_transition(move_state, move_nothing,
                       [&] () { rollback(); createToNothing(); });

        // MoveOnState -> MoveOnState
        // We don't do anything, the constraint should not move.

        // MoveOnState -> MoveOnEvent
        add_transition(move_state, move_event,
                       [&] () { rollback(); createToEvent(); });

        // MoveOnState -> MoveOnTimeNode
        add_transition(move_state, move_timenode,
                       [&] () { rollback(); createToTimeNode(); });

        /// MoveOnEvent -> ...
        // MoveOnEvent -> MoveOnNothing
        add_transition(move_event, move_nothing,
                       [&] () { rollback(); createToNothing(); });

        // MoveOnEvent -> MoveOnState
        add_transition(move_event, move_state,
                       [&] () {
            if(m_parentSM.model().state(clickedState).eventId() != m_parentSM.model().state(hoveredState).eventId())
            {
                rollback();
                createToState();
            }
        });

        // MoveOnEvent -> MoveOnEvent
        make_transition<MoveOnEvent_Transition>(move_event, move_event, *this);

        // MoveOnEvent -> MoveOnTimeNode
        add_transition(move_event, move_timenode,
                       [&] () { rollback(); createToTimeNode(); });


        /// MoveOnTimeNode -> ...
        // MoveOnTimeNode -> MoveOnNothing
        add_transition(move_timenode, move_nothing,
                       [&] () { rollback(); createToNothing(); });

        // MoveOnTimeNode -> MoveOnState
        add_transition(move_timenode, move_state,
                       [&] () { rollback(); createToState(); });

        // MoveOnTimeNode -> MoveOnEvent
        add_transition(move_timenode, move_event,
                       [&] () { rollback(); createToEvent(); });

        // MoveOnTimeNode -> MoveOnTimeNode
        make_transition<MoveOnTimeNode_Transition>(move_timenode , move_timenode , *this);



        // What happens in each state.
        QObject::connect(pressed, &QState::entered,
                         [&] ()
        {
            m_clickedPoint = currentPoint;
            createToNothing();
        });

        QObject::connect(move_nothing, &QState::entered, [&] ()
        {
            if(createdConstraints.empty() || createdEvents.empty())
            {
                rollback();
                return;
            }

            if(m_parentSM.editionSettings().sequence())
            {
                const auto&  st = m_parentSM.model().state(clickedState);
                currentPoint.y = st.heightPercentage();
            }

            m_dispatcher.submitCommand<MoveNewEvent>(
                        Path<ScenarioModel>{m_scenarioPath},
                        createdConstraints.last(),
                        createdEvents.last(),
                        currentPoint.date,
                        currentPoint.y,
                        stateMachine.editionSettings().sequence());

        });

        QObject::connect(move_event, &QState::entered, [&] ()
        {
            if(createdStates.empty())
            {
                rollback();
                return;
            }

            m_dispatcher.submitCommand<MoveNewState>(
                        Path<ScenarioModel>{m_scenarioPath},
                        createdStates.last(),
                        currentPoint.y);
        });

        QObject::connect(move_timenode, &QState::entered, [&] ()
        {
            if(createdStates.empty())
            {
                rollback();
                return;
            }

            m_dispatcher.submitCommand<MoveNewState>(
                        Path<ScenarioModel>{m_scenarioPath},
                        createdStates.last(),
                        currentPoint.y);
        });

        QObject::connect(released, &QState::entered, [&] ()
        {
            this->makeSnapshot();
            m_dispatcher.commit<Scenario::Command::CreationMetaCommand>();
        });
    }

    QState* rollbackState = new QState{this};
    make_transition<Cancel_Transition>(mainState, rollbackState);
    rollbackState->addTransition(finalState);
    QObject::connect(rollbackState, &QState::entered, [&] ()
    {
        rollback();
    });

    setInitialState(mainState);
}
ScenarioCreation_FromEvent::ScenarioCreation_FromEvent(
        const ScenarioStateMachine& stateMachine,
        ObjectPath &&scenarioPath,
        iscore::CommandStack& stack,
        QState* parent):
    ScenarioCreationState{stateMachine, stack, std::move(scenarioPath), parent}
{
    using namespace Scenario::Command;
    auto finalState = new QFinalState{this};
    connect(finalState, &QState::entered, [&] ()
    {
        clearCreatedIds();
    });

    QState* mainState = new QState{this};
    mainState->setObjectName("Main state");
    {
        auto pressed = new QState{mainState};
        auto released = new QState{mainState};
        auto move_nothing = new StrongQState<ScenarioElement::Nothing + Modifier::Move_tag::value>{mainState};
        auto move_state = new StrongQState<ScenarioElement::State + Modifier::Move_tag::value>{mainState};
        auto move_event = new StrongQState<ScenarioElement::Event + Modifier::Move_tag::value>{mainState};
        auto move_timenode = new StrongQState<ScenarioElement::TimeNode + Modifier::Move_tag::value>{mainState};

        pressed->setObjectName("Pressed");
        released->setObjectName("Released");
        move_nothing->setObjectName("Move on Nothing");
        move_state->setObjectName("Move on State");
        move_event->setObjectName("Move on Event");
        move_timenode->setObjectName("Move on TimeNode");

        // General setup
        mainState->setInitialState(pressed);
        released->addTransition(finalState);

        // Release
        make_transition<ReleaseOnAnything_Transition>(mainState, released);

        // Pressed -> ...
        make_transition<MoveOnNothing_Transition>(pressed, move_nothing, *this);

        /// MoveOnNothing -> ...
        // MoveOnNothing -> MoveOnNothing.
        make_transition<MoveOnNothing_Transition>(move_nothing, move_nothing, *this);

        // MoveOnNothing -> MoveOnState.
        add_transition(move_nothing, move_state,
                       [&] () { rollback(); createToState(); });

        // MoveOnNothing -> MoveOnEvent.
        add_transition(move_nothing, move_event,
                       [&] () { rollback(); createToEvent(); });

        // MoveOnNothing -> MoveOnTimeNode
        add_transition(move_nothing, move_timenode,
                       [&] () { rollback(); createToTimeNode(); });


        /// MoveOnState -> ...
        // MoveOnState -> MoveOnNothing
        add_transition(move_state, move_nothing,
                       [&] () { rollback(); createToNothing(); });

        // MoveOnState -> MoveOnState
        // We don't do anything, the constraint should not move.

        // MoveOnState -> MoveOnEvent
        add_transition(move_state, move_event,
                       [&] () { rollback(); createToEvent(); });

        // MoveOnState -> MoveOnTimeNode
        add_transition(move_state, move_timenode,
                       [&] () { rollback(); createToTimeNode(); });


        /// MoveOnEvent -> ...
        // MoveOnEvent -> MoveOnNothing
        add_transition(move_event, move_nothing,
                       [&] () { rollback(); createToNothing(); });

        // MoveOnEvent -> MoveOnState
        add_transition(move_event, move_state,
                       [&] () { rollback(); createToState(); });

        // MoveOnEvent -> MoveOnEvent
        make_transition<MoveOnEvent_Transition>(move_event, move_event, *this);

        // MoveOnEvent -> MoveOnTimeNode
        add_transition(move_event, move_timenode,
                       [&] () { rollback(); createToTimeNode(); });


        /// MoveOnTimeNode -> ...
        // MoveOnTimeNode -> MoveOnNothing
        add_transition(move_timenode, move_nothing,
                       [&] () { rollback(); createToNothing(); });

        // MoveOnTimeNode -> MoveOnState
        add_transition(move_timenode, move_state,
                       [&] () { rollback(); createToState(); });

        // MoveOnTimeNode -> MoveOnEvent
        add_transition(move_timenode, move_event,
                       [&] () { rollback(); createToEvent(); });

        // MoveOnTimeNode -> MoveOnTimeNode
        make_transition<MoveOnTimeNode_Transition>(move_timenode , move_timenode , *this);

        // What happens in each state.
        QObject::connect(pressed, &QState::entered,
                         [&] ()
        {
            m_clickedPoint = currentPoint;
            // Create a simple state where we are

            createInitialState();
            //createToNothing();
        });

        QObject::connect(move_nothing, &QState::entered, [&] ()
        {
            // Move the timenode
            m_dispatcher.submitCommand<MoveNewEvent>(
                        ObjectPath{m_scenarioPath},
                        createdConstraints.last(), // TODO CheckMe
                        createdEvents.last(),// TODO CheckMe
                        currentPoint.date,
                        currentPoint.y,
                        !stateMachine.isShiftPressed());
        });

        QObject::connect(move_timenode , &QState::entered, [&] ()
        {
            // TODO why ?
            m_dispatcher.submitCommand<MoveNewState>(
                        ObjectPath{m_scenarioPath},
                        createdStates.last(),
                        currentPoint.y);
        });

        QObject::connect(move_event, &QState::entered, [&] ()
        {
            m_dispatcher.submitCommand<MoveNewState>(
                        ObjectPath{m_scenarioPath},
                        createdStates.last(),
                        currentPoint.y);
        });

        QObject::connect(released, &QState::entered, [&] ()
        {
            m_dispatcher.commit<Scenario::Command::CreationMetaCommand>();
        });
    }

    QState* rollbackState = new QState{this};
    rollbackState->setObjectName("Rollback");
    make_transition<Cancel_Transition>(mainState, rollbackState);
    rollbackState->addTransition(finalState);
    QObject::connect(rollbackState, &QState::entered, [&] ()
    {
        rollback();
    });

    setInitialState(mainState);
}
SmoozikSimplestClientWindow::SmoozikSimplestClientWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::SmoozikSimplestClientWindow)
{
    ui->setupUi(this);

    // Initialize SmoozikManager
    smoozikManager = new SmoozikManager(APIKEY, SECRET, SmoozikManager::XML, false, this);
    smoozikPlaylist = new SmoozikPlaylist;
    connect(smoozikManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(processNetworkReply(QNetworkReply*)));

    // Initialize music directory
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
    _dirName = QDesktopServices::storageLocation(QDesktopServices::MusicLocation);
#else
    _dirName = QStandardPaths::writableLocation(QStandardPaths::MusicLocation);
#endif

    // Initialize playlist filler
    ui->setupUi(this);
    smoozikPlaylistFillerThread = new QThread();
    smoozikPlaylistFiller = new SmoozikPlaylistFiller(smoozikPlaylist);
    smoozikPlaylistFiller->moveToThread(smoozikPlaylistFillerThread);
    connect(smoozikPlaylistFiller, SIGNAL(trackFound(QString,QString,QString,QString,uint)), this, SLOT(addTrackToPlaylist(QString,QString,QString,QString,uint)));
    connect(smoozikPlaylistFiller, SIGNAL(tracksRetrieved()), this, SIGNAL(tracksRetrieved()));
    connect(smoozikPlaylistFiller, SIGNAL(noTrackRetrieved()), this, SLOT(noTrackRetrievedMessage()));
    connect(smoozikPlaylistFiller, SIGNAL(maxPlaylistSizeReached()), this, SLOT(maxPlaylistSizeReachedMessage()));
    connect(smoozikPlaylistFillerThread, SIGNAL(started()), smoozikPlaylistFiller, SLOT(fillPlaylist()));
    connect(smoozikPlaylistFiller, SIGNAL(finished()), smoozikPlaylistFillerThread, SLOT(quit()), Qt::DirectConnection);

    // Initialize player
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
    player = new Phonon::MediaObject(this);
    Phonon::AudioOutput *audioOutput = new Phonon::AudioOutput(Phonon::MusicCategory, this);
    Phonon::createPath(player, audioOutput);
    connect(player, SIGNAL(currentSourceChanged(Phonon::MediaSource)), this, SLOT(updateTrackLabels()));
    connect(player, SIGNAL(stateChanged(Phonon::State,Phonon::State)), this, SLOT(playerStateChanged()));
#else
    player = new QMediaPlayer(this);
    player->setPlaylist(new QMediaPlaylist(player));
    player->playlist()->setPlaybackMode(QMediaPlaylist::Sequential);
    connect(player, SIGNAL(currentMediaChanged(QMediaContent)), this, SLOT(updateTrackLabels()));
    connect(player, SIGNAL(stateChanged(QMediaPlayer::State)), this, SLOT(playerStateChanged()));
#endif
    connect(ui->playButton, SIGNAL(clicked()), player, SLOT(play()));
    connect(ui->pauseButton, SIGNAL(clicked()), player, SLOT(pause()));
    connect(this, SIGNAL(currentTrackSet()), this, SLOT(updateTrackLabels()));
    connect(this, SIGNAL(nextTrackSet()), this, SLOT(updateTrackLabels()));

    // Initialize main state machine which controls what is displayed
    QStateMachine *mainStateMachine = new QStateMachine(this);
    QState *mainState = new QState(mainStateMachine);
    QState *loginState = new QState(mainState);
    QState *startPartyState = new QState(mainState);
    QState *connectedState = new QState(mainState);
    QState *retrieveTracksState = new QState(connectedState);
    QState *sendPlaylistState = new QState(connectedState);
    QState *getTopTracksState = new QState(connectedState);
    QState *partyState = new QState(connectedState);
    QState *waitingState = new QState(partyState);
    QState *sendCurrentTrackState = new QState(partyState);
    QState *sendNextTrackState = new QState(partyState);

    QStateMachine *playerStateMachine = new QStateMachine(this);
    QState *playerState = new QState(playerStateMachine);
    QState *playingState = new QState(playerState);
    QState *pausedState = new QState(playerState);

    // Define state initial states and transitions
    mainStateMachine->setInitialState(mainState);
    mainState->setInitialState(loginState);
    connectedState->setInitialState(retrieveTracksState);
    partyState->setInitialState(waitingState);
    playerStateMachine->setInitialState(playerState);
    playerState->setInitialState(pausedState);

    mainState->addTransition(this, SIGNAL(disconnected()), loginState);
    loginState->addTransition(this, SIGNAL(loggedIn()), startPartyState);
    startPartyState->addTransition(this, SIGNAL(partyStarted()), connectedState);
    connectedState->addTransition(ui->changePlaylistButton, SIGNAL(clicked()), retrieveTracksState);
    retrieveTracksState->addTransition(this, SIGNAL(tracksRetrieved()), sendPlaylistState);
    sendPlaylistState->addTransition(this, SIGNAL(playlistSent()), getTopTracksState);
    getTopTracksState->addTransition(this, SIGNAL(currentTrackSet()), sendCurrentTrackState);
    sendCurrentTrackState->addTransition(this, SIGNAL(currentTrackSent()), getTopTracksState);
    getTopTracksState->addTransition(this, SIGNAL(nextTrackSet()), sendNextTrackState);
    sendNextTrackState->addTransition(this, SIGNAL(nextTrackSent()), waitingState);
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
    waitingState->addTransition(player, SIGNAL(currentSourceChanged(Phonon::MediaSource)), sendCurrentTrackState);
#else
    waitingState->addTransition(player, SIGNAL(currentMediaChanged(QMediaContent)), sendCurrentTrackState);
#endif

    playerState->addTransition(this, SIGNAL(playing()), playingState);
    playerState->addTransition(this, SIGNAL(paused()), pausedState);

    // Define state properties
    loginState->assignProperty(this, "state", Login);
    loginState->assignProperty(ui->stackedWidget, "currentIndex", ui->stackedWidget->indexOf(ui->loginPage));
    loginState->assignProperty(ui->loginButton, "enabled", true);
    loginState->assignProperty(ui->disconnectButton, "visible", false);
    loginState->assignProperty(ui->changePlaylistButton, "visible", false);
    loginState->assignProperty(ui->usernameLineEdit, "enabled", true);
    loginState->assignProperty(ui->passwordLineEdit, "enabled", true);
    loginState->assignProperty(ui->loginStateLabel, "text", QString());

    startPartyState->assignProperty(this, "state", StartParty);
    startPartyState->assignProperty(ui->loginStateLabel, "text", tr("Starting party..."));
    startPartyState->assignProperty(ui->disconnectButton, "visible", false);
    startPartyState->assignProperty(ui->changePlaylistButton, "visible", false);

    connectedState->assignProperty(ui->disconnectButton, "visible", true);

    retrieveTracksState->assignProperty(ui->stackedWidget, "currentIndex", ui->stackedWidget->indexOf(ui->loadingPage));
    retrieveTracksState->assignProperty(ui->loginStateLabel, "text", tr("Connected"));
    retrieveTracksState->assignProperty(ui->loadingLabel, "text", tr("Retrieving tracks..."));
    retrieveTracksState->assignProperty(ui->changePlaylistButton, "visible", false);

    sendPlaylistState->assignProperty(this, "state", SendPlaylist);
    sendPlaylistState->assignProperty(ui->loadingLabel, "text", tr("Sending playlist..."));
    sendPlaylistState->assignProperty(ui->changePlaylistButton, "visible", true);

    getTopTracksState->assignProperty(this, "state", GetTopTracks);
    getTopTracksState->assignProperty(ui->loadingLabel, "text", tr("Get top tracks..."));
    getTopTracksState->assignProperty(ui->nextButton, "enabled", false);
    getTopTracksState->assignProperty(ui->changePlaylistButton, "visible", true);

    partyState->assignProperty(ui->stackedWidget, "currentIndex", ui->stackedWidget->indexOf(ui->playerPage));
    partyState->assignProperty(ui->changePlaylistButton, "visible", true);

    sendCurrentTrackState->assignProperty(this, "state", SendCurrentTrack);
    sendCurrentTrackState->assignProperty(ui->nextButton, "enabled", false);

    sendNextTrackState->assignProperty(this, "state", SendNextTrack);
    sendNextTrackState->assignProperty(ui->nextButton, "enabled", false);

    waitingState->assignProperty(ui->nextButton, "enabled", true);

    playingState->assignProperty(ui->playButton, "visible", false);
    playingState->assignProperty(ui->pauseButton, "visible", true);

    pausedState->assignProperty(ui->playButton, "visible", true);
    pausedState->assignProperty(ui->pauseButton, "visible", false);

    // Connect states and actions
    connect(startPartyState, SIGNAL(entered()), this, SLOT(startParty()));
    connect(retrieveTracksState, SIGNAL(entered()), this, SLOT(retrieveTracksDialog()));
    connect(sendPlaylistState, SIGNAL(entered()), this, SLOT(sendPlaylist()));
    connect(getTopTracksState, SIGNAL(entered()), this, SLOT(getTopTracks()));
    connect(sendCurrentTrackState, SIGNAL(entered()), this, SLOT(sendCurrentTrack()));
    connect(sendNextTrackState, SIGNAL(entered()), this, SLOT(sendNextTrack()));

    // Connect gui and actions
    connect(ui->usernameLineEdit, SIGNAL(returnPressed()), this, SLOT(submitLogin()));
    connect(ui->passwordLineEdit, SIGNAL(returnPressed()), this, SLOT(submitLogin()));
    connect(ui->loginButton, SIGNAL(clicked()), this, SLOT(submitLogin()));
    connect(ui->nextButton, SIGNAL(clicked()), this, SLOT(nextTrack()));
    connect(ui->disconnectButton, SIGNAL(clicked()), this, SLOT(disconnect()));

    // Start state machine
    mainStateMachine->start();
    playerStateMachine->start();
}
예제 #8
0
PadNavigator::PadNavigator( QWidget *parent)
    : QGraphicsView(parent)
{
    QSize size(6,2);

    // Pad item
    this->pad = new FlippablePad(size);

    // Selection item
    RoundRectItem *selectionItem = new RoundRectItem(QRectF(-110, -110, 220, 220),
                                                     Qt::gray, pad);
    selectionItem->setZValue(0.5);

    // Selection animation
    QPropertyAnimation *smoothXSelection = new QPropertyAnimation(selectionItem, "x");
    QPropertyAnimation *smoothYSelection = new QPropertyAnimation(selectionItem, "y");
    smoothXSelection->setDuration(100);
    smoothYSelection->setDuration(100);
    smoothXSelection->setEasingCurve(QEasingCurve::InCurve);
    smoothYSelection->setEasingCurve(QEasingCurve::InCurve);

    // Build the state machine
    QStateMachine *stateMachine = new QStateMachine(this);

    QState *frontState = new QState(stateMachine);

    frontState->assignProperty(pad, "fill", false);

    frontState->assignProperty(selectionItem, "visible", true);

    stateMachine->addDefaultAnimation(smoothXSelection);
    stateMachine->addDefaultAnimation(smoothYSelection);
    stateMachine->setInitialState(frontState);

    // Create substates for each icon; store in temporary grid.
    int columns = size.width();
    int rows = size.height();
    QVector< QVector< QState * > > stateGrid;
    stateGrid.resize(rows);
    for (int y = 0; y < rows; ++y) {
        stateGrid[y].resize(columns);
        for (int x = 0; x < columns; ++x)
            stateGrid[y][x] = new QState(frontState);
    }
    frontState->setInitialState(stateGrid[0][0]);
    selectionItem->setPos(pad->iconAt(0, 0)->pos());

    // Enable key navigation using state transitions
    for (int y = 0; y < rows; ++y) {
        for (int x = 0; x < columns; ++x) {
            QState *state = stateGrid[y][x];
            QKeyEventTransition *rightTransition = new QKeyEventTransition(this, QEvent::KeyPress,
                                                                           Qt::Key_Right, state);
            QKeyEventTransition *leftTransition = new QKeyEventTransition(this, QEvent::KeyPress,
                                                                          Qt::Key_Left, state);
            QKeyEventTransition *downTransition = new QKeyEventTransition(this, QEvent::KeyPress,
                                                                          Qt::Key_Down, state);
            QKeyEventTransition *upTransition = new QKeyEventTransition(this, QEvent::KeyPress,
                                                                        Qt::Key_Up, state);

            rightTransition->setTargetState(stateGrid[y][(x + 1) % columns]);
            leftTransition->setTargetState(stateGrid[y][((x - 1) + columns) % columns]);
            downTransition->setTargetState(stateGrid[(y + 1) % rows][x]);
            upTransition->setTargetState(stateGrid[((y - 1) + rows) % rows][x]);

            RoundRectItem *icon = pad->iconAt(x, y);

            state->assignProperty(selectionItem, "x", icon->x());
            state->assignProperty(selectionItem, "y", icon->y());

        }
    }
    // Scene
    QGraphicsScene *scene = new QGraphicsScene(this);
    scene->setItemIndexMethod(QGraphicsScene::NoIndex);
    scene->addItem(pad);
    scene->setSceneRect(scene->itemsBoundingRect());
    setScene(scene);

    // View
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setMinimumSize(50, 50);
    setCacheMode(CacheBackground);
    setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing);

    stateMachine->start();

}
ScenarioCreation_FromTimeNode::ScenarioCreation_FromTimeNode(
        const ScenarioStateMachine& stateMachine,
        ObjectPath &&scenarioPath,
        iscore::CommandStack& stack,
        QState* parent):
    ScenarioCreationState{stateMachine, stack, std::move(scenarioPath), parent}
{
    using namespace Scenario::Command;
    auto finalState = new QFinalState{this};
    connect(finalState, &QState::entered, [&] ()
    {
        clearCreatedIds();
    });

    QState* mainState = new QState{this};
    {
        auto pressed = new QState{mainState};
        auto released = new QState{mainState};
        auto move_nothing = new StrongQState<ScenarioElement::Nothing + Modifier::Move_tag::value>{mainState};
        auto move_state = new StrongQState<ScenarioElement::State + Modifier::Move_tag::value>{mainState};
        auto move_event = new StrongQState<ScenarioElement::Event + Modifier::Move_tag::value>{mainState};
        auto move_timenode = new StrongQState<ScenarioElement::TimeNode + Modifier::Move_tag::value>{mainState};

        // General setup
        mainState->setInitialState(pressed);
        released->addTransition(finalState);

        // Release
        make_transition<ReleaseOnAnything_Transition>(mainState, released);

        // Pressed -> ...
        auto t_pressed_moving_nothing =
                make_transition<MoveOnNothing_Transition>(
                    pressed, move_nothing, *this);

        connect(t_pressed_moving_nothing, &QAbstractTransition::triggered,
                [&] ()
        {
            rollback();
            createToNothing();
        });


        /// MoveOnNothing -> ...
        // MoveOnNothing -> MoveOnNothing.
        make_transition<MoveOnNothing_Transition>(move_nothing, move_nothing, *this);

        // MoveOnNothing -> MoveOnState.
        add_transition(move_nothing, move_state,
                       [&] () { rollback(); ISCORE_TODO });

        // MoveOnNothing -> MoveOnEvent.
        add_transition(move_nothing, move_event,
                       [&] () {
            if(createdEvents.contains(hoveredEvent))
            {
                return;
            }
            rollback();

            createToEvent();
        });

        // MoveOnNothing -> MoveOnTimeNode
        add_transition(move_nothing, move_timenode,
                       [&] () {
            if(createdTimeNodes.contains(hoveredTimeNode))
            {
                return;
            }
            rollback();
            createToTimeNode();
        });


        /// MoveOnState -> ...
        // MoveOnState -> MoveOnNothing
        add_transition(move_state, move_nothing,
                       [&] () { rollback(); ISCORE_TODO });
예제 #10
0
MoveEventState::MoveEventState(const ToolPalette& stateMachine,
                               const Path<ScenarioModel>& scenarioPath,
                               iscore::CommandStack& stack,
                               iscore::ObjectLocker& locker,
                               QState* parent):
    StateBase{scenarioPath, parent},
    m_dispatcher{stack}
{
    this->setObjectName("MoveEventState");
    using namespace Scenario::Command ;
    auto finalState = new QFinalState{this};

    QState* mainState = new QState{this};
    {
        QState* pressed = new QState{mainState};
        QState* released = new QState{mainState};
        QState* moving = new QState{mainState};

        // General setup
        mainState->setInitialState(pressed);
        released->addTransition(finalState);

        make_transition<MoveOnAnything_Transition>(
                    pressed, moving, *this);
        make_transition<ReleaseOnAnything_Transition>(
                    pressed, finalState);
        make_transition<MoveOnAnything_Transition>(
                    moving, moving, *this);
        make_transition<ReleaseOnAnything_Transition>(
                    moving, released);

        // What happens in each state.
        QObject::connect(moving, &QState::entered, [&] ()
        {
            Id<EventModel> evId{clickedEvent};
            if(!bool(evId) && bool(clickedState))
            {
                auto& scenar = m_scenarioPath.find();
                evId = scenar.state(clickedState).eventId();
            }

            m_dispatcher.submitCommand(
                            Path<ScenarioModel>{m_scenarioPath},
                            evId,
                            currentPoint.date,
                            stateMachine.editionSettings().expandMode());
        });

        QObject::connect(released, &QState::entered, [&] ()
        {
            m_dispatcher.commit();
        });
    }

    QState* rollbackState = new QState{this};
    make_transition<Cancel_Transition>(mainState, rollbackState);
    rollbackState->addTransition(finalState);
    QObject::connect(rollbackState, &QState::entered, [&] ()
    {
        m_dispatcher.rollback();
    });

    setInitialState(mainState);
}
예제 #11
0
MoveConstraintState::MoveConstraintState(const ToolPalette& stateMachine,
                                         const Path<ScenarioModel>& scenarioPath,
                                         iscore::CommandStack& stack,
                                         iscore::ObjectLocker& locker,
                                         QState* parent):
    StateBase{scenarioPath, parent},
    m_dispatcher{stack}
{
    this->setObjectName("MoveConstraintState");
    using namespace Scenario::Command ;
    auto finalState = new QFinalState{this};

    QState* mainState = new QState{this};
    {
        QState* pressed = new QState{mainState};
        QState* released = new QState{mainState};
        QState* moving = new QState{mainState};

        // General setup
        mainState->setInitialState(pressed);
        released->addTransition(finalState);

        auto t_pressed =
                make_transition<MoveOnAnything_Transition>(
                    pressed, moving , *this);
        connect(t_pressed, &QAbstractTransition::triggered, [&] ()
        {
            auto& scenar = m_scenarioPath.find();
            m_constraintInitialStartDate= scenar.constraints.at(clickedConstraint).startDate();
            m_constraintInitialClickDate = currentPoint.date;
        });

        make_transition<ReleaseOnAnything_Transition>(
                    pressed, finalState);
        make_transition<MoveOnAnything_Transition>(
                    moving , moving , *this);
        make_transition<ReleaseOnAnything_Transition>(
                    moving , released);

        QObject::connect(moving, &QState::entered, [&] ()
        {
            m_dispatcher.submitCommand(
                            Path<ScenarioModel>{m_scenarioPath},
                            clickedConstraint,
                            m_constraintInitialStartDate + (currentPoint.date - m_constraintInitialClickDate),
                            currentPoint.y);
        });

        QObject::connect(released, &QState::entered, [&] ()
        {
            m_dispatcher.commit();
        });
    }

    QState* rollbackState = new QState{this};
    make_transition<Cancel_Transition>(mainState, rollbackState);
    rollbackState->addTransition(finalState);
    QObject::connect(rollbackState, &QState::entered, [&] ()
    {
        m_dispatcher.rollback();
    });

    setInitialState(mainState);
}
예제 #12
0
MoveTimeNodeState::MoveTimeNodeState(const ToolPalette &stateMachine,
                                     const Path<ScenarioModel>& scenarioPath,
                                     iscore::CommandStack& stack,
                                     iscore::ObjectLocker& locker,
                                     QState* parent):
    StateBase{scenarioPath, parent},
    m_dispatcher{stack}
{
    this->setObjectName("MoveTimeNodeState");
    using namespace Scenario::Command ;
    auto finalState = new QFinalState{this};

    QState* mainState = new QState{this};
    {
        QState* pressed = new QState{mainState};
        QState* released = new QState{mainState};
        QState* moving = new QState{mainState};
        mainState->setInitialState(pressed);

        // General setup
        released->addTransition(finalState);

        make_transition<MoveOnAnything_Transition>(
                    pressed, moving, *this);
        make_transition<ReleaseOnAnything_Transition>(
                    pressed, finalState);
        make_transition<MoveOnAnything_Transition>(
                    moving, moving, *this);
        make_transition<ReleaseOnAnything_Transition>(
                    moving, released);

        // What happens in each state.
        QObject::connect(moving, &QState::entered, [&] ()
        {
            // Get the 1st event on the timenode.
            auto& scenar = m_scenarioPath.find();
            auto& tn = scenar.timeNodes.at(clickedTimeNode);
            const auto& ev_id = tn.events().first();
            auto date = currentPoint.date;

            if (!stateMachine.editionSettings().sequence())
                date = tn.date();

            m_dispatcher.submitCommand(
                            Path<ScenarioModel>{m_scenarioPath},
                            ev_id,
                            date,
                            stateMachine.editionSettings().expandMode());
        });

        QObject::connect(released, &QState::entered, [&] ()
        {
            m_dispatcher.commit();
        });
    }

    QState* rollbackState = new QState{this};
    make_transition<Cancel_Transition>(mainState, rollbackState);
    rollbackState->addTransition(finalState);
    QObject::connect(rollbackState, &QState::entered, [&] ()
    {
        m_dispatcher.rollback();
    });

    setInitialState(mainState);
}