[Ktutorial-commits] SF.net SVN: ktutorial:[257] trunk/ktutorial/ktutorial-library
Status: Alpha
Brought to you by:
danxuliu
From: <dan...@us...> - 2010-09-25 20:16:10
|
Revision: 257 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=257&view=rev Author: danxuliu Date: 2010-09-25 20:16:03 +0000 (Sat, 25 Sep 2010) Log Message: ----------- Add WaitForWindow to wait for a specific window (identified by its object name) to be shown. Modified Paths: -------------- trunk/ktutorial/ktutorial-library/src/CMakeLists.txt trunk/ktutorial/ktutorial-library/src/scripting/ScriptingModule.cpp trunk/ktutorial/ktutorial-library/tests/CMakeLists.txt trunk/ktutorial/ktutorial-library/tests/scripting/ScriptingModuleTest.cpp Added Paths: ----------- trunk/ktutorial/ktutorial-library/src/WaitForWindow.cpp trunk/ktutorial/ktutorial-library/src/WaitForWindow.h trunk/ktutorial/ktutorial-library/tests/WaitForWindowTest.cpp Modified: trunk/ktutorial/ktutorial-library/src/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-library/src/CMakeLists.txt 2010-09-25 14:39:08 UTC (rev 256) +++ trunk/ktutorial/ktutorial-library/src/CMakeLists.txt 2010-09-25 20:16:03 UTC (rev 257) @@ -29,6 +29,7 @@ WaitForNot.cpp WaitForOr.cpp WaitForSignal.cpp + WaitForWindow.cpp ) kde4_add_library(ktutorial SHARED ${ktutorial_LIB_SRCS}) @@ -58,6 +59,7 @@ WaitForNot.h WaitForOr.h WaitForSignal.h + WaitForWindow.h ) # Hack to make headers available to other ktutorial modules (like Added: trunk/ktutorial/ktutorial-library/src/WaitForWindow.cpp =================================================================== --- trunk/ktutorial/ktutorial-library/src/WaitForWindow.cpp (rev 0) +++ trunk/ktutorial/ktutorial-library/src/WaitForWindow.cpp 2010-09-25 20:16:03 UTC (rev 257) @@ -0,0 +1,78 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include "WaitForWindow.h" +#include "KTutorial.h" +#include "common/WindowVisibilitySpy.h" + +using common::WindowVisibilitySpy; + +//public: + +WaitForWindow::WaitForWindow(): WaitFor(), + mConditionMet(false) { + + WindowVisibilitySpy* spy = new WindowVisibilitySpy(this); + spy->addWidgetToSpy(KTutorial::self()->parentWidget()); + connect(spy, SIGNAL(windowShown(QWidget*)), + this, SLOT(checkWindowShown(QWidget*))); +} + +WaitForWindow::WaitForWindow(const QString& objectName): WaitFor(), + mConditionMet(false) { + + WindowVisibilitySpy* spy = new WindowVisibilitySpy(this); + spy->addWidgetToSpy(KTutorial::self()->parentWidget()); + connect(spy, SIGNAL(windowShown(QWidget*)), + this, SLOT(checkWindowShown(QWidget*))); + + setWindowObjectName(objectName); +} + +void WaitForWindow::setWindowObjectName(const QString& objectName) { + mWindowObjectName = objectName; +} + +bool WaitForWindow::conditionMet() const { + return mConditionMet; +} + +void WaitForWindow::setActive(bool active) { + WaitFor::setActive(active); + + if (active) { + mConditionMet = false; + } +} + +//private slots: + +void WaitForWindow::checkWindowShown(QWidget* window) { + if (!isActive()) { + return; + } + + if (window->objectName() != mWindowObjectName) { + return; + } + + mConditionMet = true; + emit waitEnded(this); +} + +#include "WaitForWindow.moc" Property changes on: trunk/ktutorial/ktutorial-library/src/WaitForWindow.cpp ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/ktutorial/ktutorial-library/src/WaitForWindow.h =================================================================== --- trunk/ktutorial/ktutorial-library/src/WaitForWindow.h (rev 0) +++ trunk/ktutorial/ktutorial-library/src/WaitForWindow.h 2010-09-25 20:16:03 UTC (rev 257) @@ -0,0 +1,120 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifndef WAITFORWINDOW_H +#define WAITFORWINDOW_H + +#include "ktutorial_export.h" + +#include "WaitFor.h" + +/** + * Waits for a specific window to be shown. + * When the window with the expected object name is shown and the WaitForEvent + * is active, the wait ends. + * + * Note that if the window is shown while the WaitFor isn't active, it won't + * be registered and the condition won't be met. In order to met the condition, + * the window must be shown while the WaitForEvent is active. + * + * The term "window" is used here in a general sense: WaitForWindow can wait + * either for true windows or for dialogs. In fact, WaitForWindow must be used + * whenever there is a modal dialog; waiting for the user to click a button that + * causes a modal dialog to appear will not work, as the modal dialog will + * halt further processing of the clicked() signal until it is closed (if the + * modal dialog was created in a slot connected to the clicked() signal, which + * is very likely). + */ +class KTUTORIAL_EXPORT WaitForWindow: public WaitFor { +Q_OBJECT +public: + + /** + * Creates a new WaitForWindow. + * This constructor is needed to dynamically create WaitForWindow objects in + * scripts using ScriptingModule::newWaitFor(const QString&). Method + * setWindowObjectName(const QString&) must be called to finish setting up + * the object. For C++ tutorials, use WaitForWindow(const QString&) + * constructor instead of this one. + */ + Q_INVOKABLE WaitForWindow(); + + /** + * Creates a new WaitForWindow. + * Note that the name is the object name, not the window title. + * + * @param windowObjectName The object name of the window to wait for. + */ + WaitForWindow(const QString& windowObjectName); + + /** + * Sets the object name of the window to wait for. + * Note that the name is the object name, not the window title. + * This method can be invoked from a script. + * + * In fact, you should only invoke this method from a script, and only once, + * to set up the object. For C++ tutorials, use + * WaitForWindow(const QString&) constructor when creating this + * WaitForWindow. + * + * @param windowObjectName The object name of the window to wait for. + */ + Q_INVOKABLE void setWindowObjectName(const QString& windowObjectName); + + /** + * Returns true if the window was shown while active, false otherwise. + * + * @return True if the window was shown while active, false otherwise. + */ + virtual bool conditionMet() const; + + /** + * Sets this WaitForWindow active or inactive. + * Activating it resets its condition. + * + * @param active True to set it active, false otherwise. + */ + virtual void setActive(bool active); + +private: + + /** + * Whether the window with the expected object name was shown when active or + * not. + */ + bool mConditionMet; + + /** + * The object name of the window to wait for. + */ + QString mWindowObjectName; + +private Q_SLOTS: + + /** + * Checks whether the window that has been shown is the expected one. + * If the WaitFor is active and the object name of the window is the + * expected one, the condition is met and the wait ended. + * + * @param window A window that has been shown. + */ + void checkWindowShown(QWidget* window); + +}; + +#endif Property changes on: trunk/ktutorial/ktutorial-library/src/WaitForWindow.h ___________________________________________________________________ Added: svn:eol-style + native Modified: trunk/ktutorial/ktutorial-library/src/scripting/ScriptingModule.cpp =================================================================== --- trunk/ktutorial/ktutorial-library/src/scripting/ScriptingModule.cpp 2010-09-25 14:39:08 UTC (rev 256) +++ trunk/ktutorial/ktutorial-library/src/scripting/ScriptingModule.cpp 2010-09-25 20:16:03 UTC (rev 257) @@ -28,6 +28,7 @@ #include "../WaitForNot.h" #include "../WaitForOr.h" #include "../WaitForSignal.h" +#include "../WaitForWindow.h" namespace scripting { @@ -39,6 +40,7 @@ sSelf->registerWaitForMetaObject(WaitForNot::staticMetaObject); sSelf->registerWaitForMetaObject(WaitForOr::staticMetaObject); sSelf->registerWaitForMetaObject(WaitForSignal::staticMetaObject); + sSelf->registerWaitForMetaObject(WaitForWindow::staticMetaObject); } return sSelf; Modified: trunk/ktutorial/ktutorial-library/tests/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-library/tests/CMakeLists.txt 2010-09-25 14:39:08 UTC (rev 256) +++ trunk/ktutorial/ktutorial-library/tests/CMakeLists.txt 2010-09-25 20:16:03 UTC (rev 257) @@ -12,6 +12,11 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR} ${ktutorial-library_SOURCE_DIR}/src ${KDE4_INCLUDES}) +# Since Qt 4.6.0, this definition is needed for GUI testing. +# It is backwards compatible with previous Qt versions, unlike the alternative +# which is to add #include <QTestGui> in the test files. +add_definitions(-DQT_GUI_LIB) + MACRO(UNIT_TESTS) FOREACH(_className ${ARGN}) set(_testName ${_className}Test) @@ -33,6 +38,7 @@ WaitForNot WaitForOr WaitForSignal + WaitForWindow ) MACRO(MEM_TESTS) @@ -54,4 +60,5 @@ WaitForNot WaitForOr WaitForSignal + WaitForWindow ) Added: trunk/ktutorial/ktutorial-library/tests/WaitForWindowTest.cpp =================================================================== --- trunk/ktutorial/ktutorial-library/tests/WaitForWindowTest.cpp (rev 0) +++ trunk/ktutorial/ktutorial-library/tests/WaitForWindowTest.cpp 2010-09-25 20:16:03 UTC (rev 257) @@ -0,0 +1,252 @@ +/*************************************************************************** + * Copyright (C) 2010 by Daniel Calviño Sánchez * + * dan...@gm... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include <QtTest> + +#include <QDialog> + +#include <KXmlGuiWindow> + +#define protected public +#define private public +#include "WaitForWindow.h" +#undef private +#undef protected + +#include "KTutorial.h" + +class WaitForWindowTest: public QObject { +Q_OBJECT +private slots: + + void initTestCase(); + + void testConstructor(); + void testConstructorDefault(); + + void testSetActive(); + + void testWaitEnded(); + void testWaitEndedByModalDialog(); + void testWaitEndedWithDefaultConstructor(); + void testWaitEndedNotActive(); + +private: + + KXmlGuiWindow* mMainWindow; + + void queueAssertConditionMet(WaitForWindow* waitForWindow, + QSignalSpy* waitEndedSpy, + int timeToWait); + +}; + +void WaitForWindowTest::initTestCase() { + mMainWindow = new KXmlGuiWindow(); + KTutorial::self()->setup(mMainWindow); +} + +void WaitForWindowTest::testConstructor() { + WaitForWindow waitForWindow("theName"); + + QVERIFY(!waitForWindow.isActive()); + QVERIFY(!waitForWindow.conditionMet()); +} + +void WaitForWindowTest::testConstructorDefault() { + WaitForWindow waitForWindow; + waitForWindow.setWindowObjectName("theName"); + + QVERIFY(!waitForWindow.isActive()); + QVERIFY(!waitForWindow.conditionMet()); +} + +void WaitForWindowTest::testSetActive() { + WaitForWindow waitForWindow("theName"); + waitForWindow.mConditionMet = true; + + waitForWindow.setActive(true); + + QVERIFY(waitForWindow.isActive()); + QVERIFY(!waitForWindow.conditionMet()); +} + +//WaitFor* must be declared as a metatype to be used in qvariant_cast +Q_DECLARE_METATYPE(WaitFor*); + +void WaitForWindowTest::testWaitEnded() { + WaitForWindow waitForWindow("theName"); + waitForWindow.setActive(true); + + //WaitFor* must be registered in order to be used with QSignalSpy + int waitForStarType = qRegisterMetaType<WaitFor*>("WaitFor*"); + QSignalSpy waitEndedSpy(&waitForWindow, SIGNAL(waitEnded(WaitFor*))); + + QWidget* otherWindow = new QWidget(mMainWindow); + otherWindow->setObjectName("otherName"); + otherWindow->setWindowFlags(Qt::Window); + otherWindow->show(); + + otherWindow->deleteLater(); + + QVERIFY(!waitForWindow.conditionMet()); + QCOMPARE(waitEndedSpy.count(), 0); + + QWidget* window = new QWidget(mMainWindow); + window->setObjectName("theName"); + window->setWindowFlags(Qt::Window); + window->show(); + + window->deleteLater(); + + QVERIFY(waitForWindow.conditionMet()); + QCOMPARE(waitEndedSpy.count(), 1); + QVariant argument = waitEndedSpy.at(0).at(0); + QCOMPARE(argument.userType(), waitForStarType); + QCOMPARE(qvariant_cast<WaitFor*>(argument), &waitForWindow); +} + +void WaitForWindowTest::testWaitEndedByModalDialog() { + WaitForWindow waitForWindow("theName"); + waitForWindow.setActive(true); + + //WaitFor* must be registered in order to be used with QSignalSpy + int waitForStarType = qRegisterMetaType<WaitFor*>("WaitFor*"); + QSignalSpy waitEndedSpy(&waitForWindow, SIGNAL(waitEnded(WaitFor*))); + + QDialog* modalDialog = new QDialog(mMainWindow); + modalDialog->setObjectName("theName"); + + QTimer timerAccept; + timerAccept.setSingleShot(true); + timerAccept.setInterval(1500); + connect(&timerAccept, SIGNAL(timeout()), modalDialog, SLOT(accept())); + + //Check that the condition was met before closing the modal dialog to ensure + //that the processing of events or signals is not halted due to being modal. + queueAssertConditionMet(&waitForWindow, &waitEndedSpy, 500); + + timerAccept.start(); + modalDialog->exec(); + + modalDialog->deleteLater(); + + QVERIFY(waitForWindow.conditionMet()); + QCOMPARE(waitEndedSpy.count(), 1); + QVariant argument = waitEndedSpy.at(0).at(0); + QCOMPARE(argument.userType(), waitForStarType); + QCOMPARE(qvariant_cast<WaitFor*>(argument), &waitForWindow); +} + +void WaitForWindowTest::testWaitEndedWithDefaultConstructor() { + WaitForWindow waitForWindow; + waitForWindow.setWindowObjectName("theName"); + waitForWindow.setActive(true); + + //WaitFor* must be registered in order to be used with QSignalSpy + int waitForStarType = qRegisterMetaType<WaitFor*>("WaitFor*"); + QSignalSpy waitEndedSpy(&waitForWindow, SIGNAL(waitEnded(WaitFor*))); + + QWidget* otherWindow = new QWidget(mMainWindow); + otherWindow->setObjectName("otherName"); + otherWindow->setWindowFlags(Qt::Window); + otherWindow->show(); + + otherWindow->deleteLater(); + + QVERIFY(!waitForWindow.conditionMet()); + QCOMPARE(waitEndedSpy.count(), 0); + + QWidget* window = new QWidget(mMainWindow); + window->setObjectName("theName"); + window->setWindowFlags(Qt::Window); + window->show(); + + window->deleteLater(); + + QVERIFY(waitForWindow.conditionMet()); + QCOMPARE(waitEndedSpy.count(), 1); + QVariant argument = waitEndedSpy.at(0).at(0); + QCOMPARE(argument.userType(), waitForStarType); + QCOMPARE(qvariant_cast<WaitFor*>(argument), &waitForWindow); +} + +void WaitForWindowTest::testWaitEndedNotActive() { + WaitForWindow waitForWindow("theName"); + + qRegisterMetaType<WaitFor*>("WaitFor*"); + QSignalSpy waitEndedSpy(&waitForWindow, SIGNAL(waitEnded(WaitFor*))); + + QWidget* window = new QWidget(mMainWindow); + window->setObjectName("theName"); + window->setWindowFlags(Qt::Window); + window->show(); + + window->deleteLater(); + + QVERIFY(!waitForWindow.conditionMet()); + QCOMPARE(waitEndedSpy.count(), 0); +} + +/////////////////////////////////// Helpers //////////////////////////////////// + +//Modal dialogs don't return to the test code until they are closed. Thus, the +//actions or asserts to be performed while a modal dialog is being shown (like +//checking if a wait for condition was met) must be "queued". +class QueuedActionsHelper: public QObject { +Q_OBJECT +public: + + QueuedActionsHelper(QObject* object = 0): QObject(object) { + } + + void setWaitForWindow(WaitForWindow* waitForWindow) { + mWaitForWindow = waitForWindow; + } + + void setWaitEndedSpy(QSignalSpy* waitEndedSpy) { + mWaitEndedSpy = waitEndedSpy; + } + +public slots: + + void assertConditionMet() { + QVERIFY(mWaitForWindow->conditionMet()); + QCOMPARE(mWaitEndedSpy->count(), 1); + } + +private: + + WaitForWindow* mWaitForWindow; + QSignalSpy* mWaitEndedSpy; + +}; + +void WaitForWindowTest::queueAssertConditionMet(WaitForWindow* waitForWindow, + QSignalSpy* waitEndedSpy, + int timeToWait) { + QueuedActionsHelper* helper = new QueuedActionsHelper(); + helper->setWaitForWindow(waitForWindow); + helper->setWaitEndedSpy(waitEndedSpy); + QTimer::singleShot(timeToWait, helper, SLOT(assertConditionMet())); + QTimer::singleShot(timeToWait, helper, SLOT(deleteLater())); +} + +QTEST_MAIN(WaitForWindowTest) + +#include "WaitForWindowTest.moc" Property changes on: trunk/ktutorial/ktutorial-library/tests/WaitForWindowTest.cpp ___________________________________________________________________ Added: svn:eol-style + native Modified: trunk/ktutorial/ktutorial-library/tests/scripting/ScriptingModuleTest.cpp =================================================================== --- trunk/ktutorial/ktutorial-library/tests/scripting/ScriptingModuleTest.cpp 2010-09-25 14:39:08 UTC (rev 256) +++ trunk/ktutorial/ktutorial-library/tests/scripting/ScriptingModuleTest.cpp 2010-09-25 20:16:03 UTC (rev 257) @@ -34,6 +34,7 @@ #include "../WaitForNot.h" #include "../WaitForOr.h" #include "../WaitForSignal.h" +#include "../WaitForWindow.h" class MockWaitForDefaultNamespace: public WaitFor { Q_OBJECT @@ -171,6 +172,10 @@ QVERIFY(containsMetaObject(scriptingModule, "WaitForSignal")); type = metaObject(scriptingModule, "WaitForSignal"); QCOMPARE(type.className(), WaitForSignal::staticMetaObject.className()); + + QVERIFY(containsMetaObject(scriptingModule, "WaitForWindow")); + type = metaObject(scriptingModule, "WaitForWindow"); + QCOMPARE(type.className(), WaitForWindow::staticMetaObject.className()); } void ScriptingModuleTest::testRegisterWaitForMetaObject() { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |