summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKent Hansen <khansen@trolltech.com>2009-09-29 09:59:01 (GMT)
committerKent Hansen <khansen@trolltech.com>2009-09-29 10:02:09 (GMT)
commit39604894946c3c0d623c0073ccf027a8e6df120a (patch)
treecb6fa13f922365d151cbc5597343560a56f19037
parentd557d6e5dc73c88f9de26bf2e3dd2c6955400467 (diff)
downloadQt-39604894946c3c0d623c0073ccf027a8e6df120a.zip
Qt-39604894946c3c0d623c0073ccf027a8e6df120a.tar.gz
Qt-39604894946c3c0d623c0073ccf027a8e6df120a.tar.bz2
Do synchronous processing of events in state machine if possible
Avoid delayed scheduling in the cases where there's no need to delay it (e.g. when the state machine intercepts a signal or event). Task-number: QTBUG-4491 Reviewed-by: Eskil Abrahamsen Blomfeldt
-rw-r--r--src/corelib/statemachine/qstatemachine.cpp46
-rw-r--r--src/corelib/statemachine/qstatemachine_p.h7
-rw-r--r--tests/auto/qstatemachine/tst_qstatemachine.cpp33
3 files changed, 73 insertions, 13 deletions
diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp
index 503eec0..8d50870c 100644
--- a/src/corelib/statemachine/qstatemachine.cpp
+++ b/src/corelib/statemachine/qstatemachine.cpp
@@ -804,6 +804,14 @@ void QStateMachinePrivate::applyProperties(const QList<QAbstractTransition*> &tr
}
if (hasValidEndValue) {
+ if (anim->state() == QAbstractAnimation::Running) {
+ // The animation is still running. This can happen if the
+ // animation is a group, and one of its children just finished,
+ // and that caused a state to emit its polished() signal, and
+ // that triggered a transition in the machine.
+ // Just stop the animation so it is correctly restarted again.
+ anim->stop();
+ }
anim->start();
}
}
@@ -1268,12 +1276,19 @@ void QStateMachinePrivate::_q_process()
}
}
-void QStateMachinePrivate::scheduleProcess()
+void QStateMachinePrivate::processEvents(EventProcessingMode processingMode)
{
if ((state != Running) || processing || processingScheduled)
return;
- processingScheduled = true;
- QMetaObject::invokeMethod(q_func(), "_q_process", Qt::QueuedConnection);
+ switch (processingMode) {
+ case DirectProcessing:
+ _q_process();
+ break;
+ case QueuedProcessing:
+ processingScheduled = true;
+ QMetaObject::invokeMethod(q_func(), "_q_process", Qt::QueuedConnection);
+ break;
+ }
}
namespace {
@@ -1335,7 +1350,7 @@ void QStateMachinePrivate::goToState(QAbstractState *targetState)
trans->setTargetState(targetState);
}
- scheduleProcess();
+ processEvents(QueuedProcessing);
}
void QStateMachinePrivate::registerTransitions(QAbstractState *state)
@@ -1512,6 +1527,15 @@ void QStateMachinePrivate::unregisterEventTransition(QEventTransition *transitio
}
QEventTransitionPrivate::get(transition)->registered = false;
}
+
+void QStateMachinePrivate::handleFilteredEvent(QObject *watched, QEvent *event)
+{
+ Q_ASSERT(qobjectEvents.contains(watched));
+ if (qobjectEvents[watched].contains(event->type())) {
+ internalEventQueue.append(new QStateMachine::WrappedEvent(watched, handler->cloneEvent(event)));
+ processEvents(DirectProcessing);
+ }
+}
#endif
void QStateMachinePrivate::handleTransitionSignal(QObject *sender, int signalIndex,
@@ -1533,7 +1557,7 @@ void QStateMachinePrivate::handleTransitionSignal(QObject *sender, int signalInd
<< ", signal =" << sender->metaObject()->method(signalIndex).signature() << ')';
#endif
internalEventQueue.append(new QStateMachine::SignalEvent(sender, signalIndex, vargs));
- scheduleProcess();
+ processEvents(DirectProcessing);
}
/*!
@@ -1768,7 +1792,7 @@ void QStateMachine::stop()
break;
case QStateMachinePrivate::Running:
d->stop = true;
- d->scheduleProcess();
+ d->processEvents(QStateMachinePrivate::QueuedProcessing);
break;
}
}
@@ -1798,7 +1822,7 @@ void QStateMachine::postEvent(QEvent *event, int delay)
d->delayedEvents[tid] = event;
} else {
d->externalEventQueue.append(event);
- d->scheduleProcess();
+ d->processEvents(QStateMachinePrivate::QueuedProcessing);
}
}
@@ -1814,7 +1838,7 @@ void QStateMachine::postInternalEvent(QEvent *event)
qDebug() << this << ": posting internal event" << event;
#endif
d->internalEventQueue.append(event);
- d->scheduleProcess();
+ d->processEvents(QStateMachinePrivate::QueuedProcessing);
}
/*!
@@ -1862,7 +1886,7 @@ bool QStateMachine::event(QEvent *e)
killTimer(tid);
QEvent *ee = d->delayedEvents.take(tid);
d->externalEventQueue.append(ee);
- d->scheduleProcess();
+ d->processEvents(QStateMachinePrivate::DirectProcessing);
return true;
}
}
@@ -1876,9 +1900,7 @@ bool QStateMachine::event(QEvent *e)
bool QStateMachine::eventFilter(QObject *watched, QEvent *event)
{
Q_D(QStateMachine);
- Q_ASSERT(d->qobjectEvents.contains(watched));
- if (d->qobjectEvents[watched].contains(event->type()))
- postEvent(new QStateMachine::WrappedEvent(watched, d->handler->cloneEvent(event)));
+ d->handleFilteredEvent(watched, event);
return false;
}
#endif
diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h
index a1b6de2..141bc5c 100644
--- a/src/corelib/statemachine/qstatemachine_p.h
+++ b/src/corelib/statemachine/qstatemachine_p.h
@@ -88,6 +88,10 @@ public:
Starting,
Running
};
+ enum EventProcessingMode {
+ DirectProcessing,
+ QueuedProcessing
+ };
enum StopProcessingReason {
EventQueueEmpty,
Finished,
@@ -149,12 +153,13 @@ public:
#ifndef QT_NO_STATEMACHINE_EVENTFILTER
void registerEventTransition(QEventTransition *transition);
void unregisterEventTransition(QEventTransition *transition);
+ void handleFilteredEvent(QObject *watched, QEvent *event);
#endif
void unregisterTransition(QAbstractTransition *transition);
void unregisterAllTransitions();
void handleTransitionSignal(QObject *sender, int signalIndex,
void **args);
- void scheduleProcess();
+ void processEvents(EventProcessingMode processingMode);
#ifndef QT_NO_PROPERTIES
typedef QPair<QObject *, QByteArray> RestorableId;
diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp
index 7244d72..37b34bf 100644
--- a/tests/auto/qstatemachine/tst_qstatemachine.cpp
+++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp
@@ -176,6 +176,7 @@ private slots:
void twoAnimatedTransitions();
void playAnimationTwice();
void nestedTargetStateForAnimation();
+ void polishedSignalTransitionsReuseAnimationGroup();
void animatedGlobalRestoreProperty();
void specificTargetValueOfAnimation();
@@ -3115,6 +3116,38 @@ void tst_QStateMachine::nestedTargetStateForAnimation()
QCOMPARE(counter.counter, 2);
}
+void tst_QStateMachine::polishedSignalTransitionsReuseAnimationGroup()
+{
+ QStateMachine machine;
+ QObject *object = new QObject(&machine);
+ object->setProperty("foo", 0);
+
+ QState *s1 = new QState(&machine);
+ s1->assignProperty(object, "foo", 123);
+ QState *s2 = new QState(&machine);
+ s2->assignProperty(object, "foo", 456);
+ QState *s3 = new QState(&machine);
+ s3->assignProperty(object, "foo", 789);
+ QFinalState *s4 = new QFinalState(&machine);
+
+ QParallelAnimationGroup animationGroup;
+ animationGroup.addAnimation(new QPropertyAnimation(object, "foo"));
+ QSignalSpy animationFinishedSpy(&animationGroup, SIGNAL(finished()));
+ s1->addTransition(s1, SIGNAL(polished()), s2)->addAnimation(&animationGroup);
+ s2->addTransition(s2, SIGNAL(polished()), s3)->addAnimation(&animationGroup);
+ s3->addTransition(s3, SIGNAL(polished()), s4);
+
+ machine.setInitialState(s1);
+ QSignalSpy machineFinishedSpy(&machine, SIGNAL(finished()));
+ machine.start();
+ QTRY_COMPARE(machineFinishedSpy.count(), 1);
+ QCOMPARE(machine.configuration().size(), 1);
+ QVERIFY(machine.configuration().contains(s4));
+ QCOMPARE(object->property("foo").toInt(), 789);
+
+ QCOMPARE(animationFinishedSpy.count(), 2);
+}
+
void tst_QStateMachine::animatedGlobalRestoreProperty()
{
QStateMachine machine;