[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. |