[Ktutorial-commits] SF.net SVN: ktutorial:[304] trunk/ktutorial/ktutorial-library
Status: Alpha
Brought to you by:
danxuliu
|
From: <dan...@us...> - 2011-05-08 15:16:18
|
Revision: 304
http://ktutorial.svn.sourceforge.net/ktutorial/?rev=304&view=rev
Author: danxuliu
Date: 2011-05-08 15:16:11 +0000 (Sun, 08 May 2011)
Log Message:
-----------
Modify the internal behavior of Tutorial when changing to the next step. Until now, when nextStep(Step*) was called it just changed to the next step, which could cause recursive changes and wrong results when called from the setup method of a Step. Now, the steps to change to are queued and the changes are done one after the other.
Modified Paths:
--------------
trunk/ktutorial/ktutorial-library/src/Tutorial.cpp
trunk/ktutorial/ktutorial-library/src/Tutorial.h
trunk/ktutorial/ktutorial-library/tests/TutorialTest.cpp
Modified: trunk/ktutorial/ktutorial-library/src/Tutorial.cpp
===================================================================
--- trunk/ktutorial/ktutorial-library/src/Tutorial.cpp 2011-05-06 12:49:50 UTC (rev 303)
+++ trunk/ktutorial/ktutorial-library/src/Tutorial.cpp 2011-05-08 15:16:11 UTC (rev 304)
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2008-2010 by Daniel Calviño Sánchez *
+ * Copyright (C) 2008-2011 by Daniel Calviño Sánchez *
* dan...@gm... *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -65,6 +65,38 @@
}
void Tutorial::nextStep(Step* step) {
+ mQueuedSteps.append(step);
+
+ if (mQueuedSteps.count() > 1) {
+ //Nested call to nextStep(Step*) (that is, something called by
+ //nextStep(Step*) caused the method to be called again before its
+ //previous execution ended). Once that previous call continues its
+ //execution it will change to the next queued step.
+ return;
+ }
+
+ while (mQueuedSteps.count() > 0) {
+ changeToStep(mQueuedSteps[0]);
+ mQueuedSteps.removeFirst();
+ }
+}
+
+//public slots:
+
+void Tutorial::finish() {
+ if (mCurrentStep != 0) {
+ mCurrentStep->setActive(false);
+ mCurrentStep = 0;
+ }
+
+ tearDown();
+
+ emit finished(this);
+}
+
+//private:
+
+void Tutorial::changeToStep(Step* step) {
if (mSteps.key(step).isEmpty()) {
kError() << "Activate step " << step->id()
<< " which doesn't belong to tutorial "
@@ -84,16 +116,3 @@
emit stepActivated(step);
}
-
-//public slots:
-
-void Tutorial::finish() {
- if (mCurrentStep != 0) {
- mCurrentStep->setActive(false);
- mCurrentStep = 0;
- }
-
- tearDown();
-
- emit finished(this);
-}
Modified: trunk/ktutorial/ktutorial-library/src/Tutorial.h
===================================================================
--- trunk/ktutorial/ktutorial-library/src/Tutorial.h 2011-05-06 12:49:50 UTC (rev 303)
+++ trunk/ktutorial/ktutorial-library/src/Tutorial.h 2011-05-08 15:16:11 UTC (rev 304)
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2008-2010 by Daniel Calviño Sánchez *
+ * Copyright (C) 2008-2011 by Daniel Calviño Sánchez *
* dan...@gm... *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -208,6 +208,20 @@
*/
Step* mCurrentStep;
+ /**
+ * The steps to change to that were not activated yet.
+ */
+ QList<Step*> mQueuedSteps;
+
+ /**
+ * Activates the given step.
+ * When calling nextStep(Step*), the tutorial queues the steps to change to.
+ * The real activation of the step is done by this method.
+ *
+ * @param step The Step to activate.
+ */
+ void changeToStep(Step* step);
+
};
#endif
Modified: trunk/ktutorial/ktutorial-library/tests/TutorialTest.cpp
===================================================================
--- trunk/ktutorial/ktutorial-library/tests/TutorialTest.cpp 2011-05-06 12:49:50 UTC (rev 303)
+++ trunk/ktutorial/ktutorial-library/tests/TutorialTest.cpp 2011-05-08 15:16:11 UTC (rev 304)
@@ -1,5 +1,5 @@
/***************************************************************************
- * Copyright (C) 2009-2010 by Daniel Calviño Sánchez *
+ * Copyright (C) 2009-2011 by Daniel Calviño Sánchez *
* dan...@gm... *
* *
* This program is free software; you can redistribute it and/or modify *
@@ -55,6 +55,8 @@
void testNextStepStep();
void testNextStepStepWithInvalidStep();
+ void testNextStepFromStepSetup();
+
void testFinish();
};
@@ -71,6 +73,46 @@
};
+class StepToSetNextStepInSetup: public Step {
+public:
+
+ Tutorial* mTutorial;
+ Step* mNextStep;
+ bool mDuringSetup;
+
+ StepToSetNextStepInSetup(const QString& id): Step(id),
+ mTutorial(0),
+ mNextStep(0),
+ mDuringSetup(false) {
+ }
+
+protected:
+
+ void setup() {
+ mDuringSetup = true;
+ mTutorial->nextStep(mNextStep);
+ mDuringSetup = false;
+ }
+
+};
+
+class StepToAssertNoRecursiveStepActivation: public Step {
+public:
+
+ StepToSetNextStepInSetup* mPreviousStep;
+
+ StepToAssertNoRecursiveStepActivation(const QString& id): Step(id),
+ mPreviousStep(0) {
+ }
+
+protected:
+
+ void setup() {
+ QVERIFY(!mPreviousStep->mDuringSetup);
+ }
+
+};
+
class MockTutorial: public Tutorial {
public:
@@ -408,6 +450,54 @@
QVERIFY(step1->isActive());
}
+//Ensure that if some step calls Tutorial::nextStep from its setup (that is,
+//when the step is being activated), the next step is not activated until the
+//activation of the previous one ended (that is, steps are not activated
+//recursively, but sequentially).
+void TutorialTest::testNextStepFromStepSetup() {
+ Tutorial tutorial(new TutorialInformation("pearlOrientation"));
+
+ Step* stepStart = new Step("start");
+ tutorial.addStep(stepStart);
+
+ StepToSetNextStepInSetup* step1 = new StepToSetNextStepInSetup("record");
+ tutorial.addStep(step1);
+
+ StepToAssertNoRecursiveStepActivation* step2 =
+ new StepToAssertNoRecursiveStepActivation("roll");
+ tutorial.addStep(step2);
+
+ step1->mTutorial = &tutorial;
+ step1->mNextStep = step2;
+ step2->mPreviousStep = step1;
+
+ tutorial.addStep(new Step("send"));
+
+ tutorial.start();
+
+ //Step* must be registered in order to be used with QSignalSpy
+ int stepStarType = qRegisterMetaType<Step*>("Step*");
+ QSignalSpy stepActivatedSpy(&tutorial, SIGNAL(stepActivated(Step*)));
+
+ //Ensure that the step is already active when the signal is emitted
+ connect(&tutorial, SIGNAL(stepActivated(Step*)),
+ this, SLOT(assertStepActive(Step*)));
+
+ tutorial.nextStep(step1);
+
+ QCOMPARE(stepActivatedSpy.count(), 2);
+ QVariant argument = stepActivatedSpy.at(0).at(0);
+ QCOMPARE(argument.userType(), stepStarType);
+ QCOMPARE(qvariant_cast<Step*>(argument), step1);
+ argument = stepActivatedSpy.at(1).at(0);
+ QCOMPARE(argument.userType(), stepStarType);
+ QCOMPARE(qvariant_cast<Step*>(argument), step2);
+ QCOMPARE(tutorial.mCurrentStep, step2);
+ QVERIFY(!stepStart->isActive());
+ QVERIFY(!step1->isActive());
+ QVERIFY(step2->isActive());
+}
+
void TutorialTest::testFinish() {
MockTutorial tutorial(new TutorialInformation("pearlOrientation"));
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|