[Ktutorial-commits] SF.net SVN: ktutorial:[248] trunk/ktutorial/ktutorial-editor
Status: Alpha
Brought to you by:
danxuliu
From: <dan...@us...> - 2010-08-14 17:30:56
|
Revision: 248 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=248&view=rev Author: danxuliu Date: 2010-08-14 17:30:49 +0000 (Sat, 14 Aug 2010) Log Message: ----------- Show an information message box to tell the user that KTutorial editor windows will be hidden when the remote object is going to be chosen. Modified Paths: -------------- trunk/ktutorial/ktutorial-editor/src/targetapplication/TargetApplication.cpp trunk/ktutorial/ktutorial-editor/src/view/RemoteObjectChooser.cpp trunk/ktutorial/ktutorial-editor/src/view/RemoteObjectChooser.h trunk/ktutorial/ktutorial-editor/tests/unit/view/RemoteObjectChooserTest.cpp Modified: trunk/ktutorial/ktutorial-editor/src/targetapplication/TargetApplication.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/targetapplication/TargetApplication.cpp 2010-08-14 14:57:12 UTC (rev 247) +++ trunk/ktutorial/ktutorial-editor/src/targetapplication/TargetApplication.cpp 2010-08-14 17:30:49 UTC (rev 248) @@ -135,13 +135,20 @@ mServiceDiscoveryTimer.stop(); + //The bus must be disconnected before executing other code to ensure that + //no other services are handled, as when an application starts it can create + //more than one valid service: one like ":1.42" and another like + //"org.freedesktop.DBus". + //So this method could be called again before finishing its current + //execution if serviceRegistered(QSignal) is emitted, which could happen if + //other event loops are created (like in a message box). + disconnect(QDBusConnection::sessionBus().interface(), 0, this, 0); + mServiceName = service; mMapper = new RemoteObjectMapper(mServiceName); mRemoteEditorSupport = new RemoteEditorSupport(mServiceName, mMapper); emit started(); - - disconnect(QDBusConnection::sessionBus().interface(), 0, this, 0); } void TargetApplication::handleProcessError(QProcess::ProcessError error) { Modified: trunk/ktutorial/ktutorial-editor/src/view/RemoteObjectChooser.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/view/RemoteObjectChooser.cpp 2010-08-14 14:57:12 UTC (rev 247) +++ trunk/ktutorial/ktutorial-editor/src/view/RemoteObjectChooser.cpp 2010-08-14 17:30:49 UTC (rev 248) @@ -120,14 +120,41 @@ } } +void RemoteObjectChooser::warnAboutFinishedTargetApplicationBeforeClosing() { + QString text = i18nc("@label", "The target application has been closed, " +"but it must be running to be able to choose the objects."); + QString caption = i18nc("@title:window", "Target application closed"); + KMessageBox::sorry(this, text, caption); + + close(); +} + //private slots: void RemoteObjectChooser::handleTargetApplicationStarted() { - hideParentWindows(this); + QString text = i18nc("@label", "<para>The " +"<application>KTutorial editor</application> windows will be hidden and only " +"the list with the objects in the target application will be shown. It is made " +"to better view when a widget is highlighted in the target application.</para>" +"<para>The <application>KTutorial editor</application> windows will be shown " +"again once the selection list is closed.</para>"); + QString caption = i18nc("@title:window", "<application>KTutorial " +"editor</application> windows will be hidden"); + KMessageBox::information(this, text, caption, + "KTutorialEditorWindowsWillBeHidden"); RemoteEditorSupport* remoteEditorSupport = TargetApplication::self()->remoteEditorSupport(); + //The target application may have been closed while the message box was + //shown. + if (!remoteEditorSupport) { + warnAboutFinishedTargetApplicationBeforeClosing(); + return; + } + + hideParentWindows(this); + RemoteObject* mainWindow = remoteEditorSupport->mainWindow(); RemoteObjectTreeItem* rootItem = new RemoteObjectTreeItem(mainWindow); TreeModel* treeModel = new TreeModel(rootItem, this); @@ -167,12 +194,7 @@ return; } - QString text = i18nc("@label", "The target application has been closed, " -"but it must be running to be able to choose the objects."); - QString caption = i18nc("@title:window", "Target application closed"); - KMessageBox::sorry(this, text, caption); - - close(); + warnAboutFinishedTargetApplicationBeforeClosing(); } void RemoteObjectChooser::setCurrentRemoteObject(RemoteObject* remoteObject) { Modified: trunk/ktutorial/ktutorial-editor/src/view/RemoteObjectChooser.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/view/RemoteObjectChooser.h 2010-08-14 14:57:12 UTC (rev 247) +++ trunk/ktutorial/ktutorial-editor/src/view/RemoteObjectChooser.h 2010-08-14 17:30:49 UTC (rev 248) @@ -39,7 +39,8 @@ * When the target application is successfully started, the RemoteObjectChooser * hides all its parent dialogs and windows. Only the RemoteObjectChooser itself * is kept shown to avoid the rest of windows of KTutorial editor to get in the - * way of the user when he interacts with the target application. + * way of the user when he interacts with the target application. Before hiding + * the windows an information message is shown to the user explaining this. * * When the user selects a remote object in the list and that object represents * a widget, the widget is highlighted in the target application. @@ -132,11 +133,17 @@ */ void showParentWindows(QWidget* widget); + /** + * A warning is shown to the user explaining that the target application + * must be running and this RemoteObjectChooser is closed. + */ + void warnAboutFinishedTargetApplicationBeforeClosing(); + private Q_SLOTS: /** - * Hides the parent windows and dialogs and sets up the models for the tree - * view. + * Shows the information message about hiding the parent windows, hides the + * parent windows and dialogs, and sets up the models for the tree view. */ void handleTargetApplicationStarted(); Modified: trunk/ktutorial/ktutorial-editor/tests/unit/view/RemoteObjectChooserTest.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/view/RemoteObjectChooserTest.cpp 2010-08-14 14:57:12 UTC (rev 247) +++ trunk/ktutorial/ktutorial-editor/tests/unit/view/RemoteObjectChooserTest.cpp 2010-08-14 17:30:49 UTC (rev 248) @@ -58,6 +58,7 @@ void testTargetApplicationNotUsingKTutorial(); void testTargetApplicationStopped(); + void testTargetApplicationStoppedBeforeClosingInformationMessageBox(); void close(); //Closing with ALT+F4 can't be tested, as it depends on the window manager @@ -72,8 +73,11 @@ QString mPath; - void closeMessageBox(QWidget* widget, int timeToWait); + void closeInformationMessageBox(int timeToWait); + void closeSorryMessageBox(QWidget* widget, int timeToWait); + void killTargetApplication(int timeToWait); + QTreeView* remoteObjectsTreeView(RemoteObjectChooser* widget) const; QPushButton* okButton(RemoteObjectChooser* widget) const; @@ -120,6 +124,8 @@ QWidget* dialog = new QWidget(&window, Qt::Dialog); dialog->show(); + //Queue closing the information message box + closeInformationMessageBox(1000); RemoteObjectChooser* chooser = new RemoteObjectChooser(dialog); chooser->show(); @@ -147,6 +153,8 @@ QWidget* dialog = new QWidget(&window, Qt::Dialog); dialog->show(); + //Queue closing the information message box + closeInformationMessageBox(1000); RemoteObjectChooser* chooser = new RemoteObjectChooser(dialog); chooser->show(); @@ -170,8 +178,8 @@ QPointer<RemoteObjectChooser> chooser = new RemoteObjectChooser(dialog); chooser->show(); - //Queue closing the message box - closeMessageBox(chooser, 1000); + //Queue closing the sorry message box + closeSorryMessageBox(chooser, 1000); //Give the target application time to fail to start QTest::qWait(1000); @@ -197,8 +205,8 @@ QPointer<RemoteObjectChooser> chooser = new RemoteObjectChooser(dialog); chooser->show(); - //Queue closing the message box - closeMessageBox(chooser, 3500); + //Queue closing the sorry message box + closeSorryMessageBox(chooser, 3500); //Give the target application time to fail to start QTest::qWait(3500); @@ -219,14 +227,16 @@ QWidget* dialog = new QWidget(&window, Qt::Dialog); dialog->show(); + //Queue closing the information message box + closeInformationMessageBox(1000); QPointer<RemoteObjectChooser> chooser = new RemoteObjectChooser(dialog); chooser->show(); //Give the target application time to start QTest::qWait(1000); - //Queue closing the message box - closeMessageBox(chooser, 1000); + //Queue closing the sorry message box + closeSorryMessageBox(chooser, 1000); TargetApplication::self()->mProcess->kill(); @@ -241,6 +251,44 @@ QVERIFY(dialog->isVisible()); } +void RemoteObjectChooserTest:: +testTargetApplicationStoppedBeforeClosingInformationMessageBox() { + TargetApplication::self()->setTargetApplicationFilePath(mPath); + + QWidget window(0, Qt::Window); + window.show(); + QWidget* dialog = new QWidget(&window, Qt::Dialog); + dialog->show(); + + QPointer<RemoteObjectChooser> chooser = new RemoteObjectChooser(dialog); + chooser->show(); + + //All the queuing has to be done before the qWait, because the killing must + //be done once the information message is already shown, and the sorry + //message appears just after the information message is closed (and it may + //appear before the wait ends, so queuing it after the wait could not work). + + //Queue killing the target application + killTargetApplication(1000); + + //Queue closing the information message box + closeInformationMessageBox(2000); + + //Queue closing the sorry message box + closeSorryMessageBox(chooser, 3000); + + //Give the target application time to start and be killed, and to close the + //sorry message box + QTest::qWait(3000); + + //Process deleteLater() + QCoreApplication::sendPostedEvents(chooser, QEvent::DeferredDelete); + + QVERIFY(!chooser); + QVERIFY(window.isVisible()); + QVERIFY(dialog->isVisible()); +} + void RemoteObjectChooserTest::close() { TargetApplication::self()->setTargetApplicationFilePath(mPath); @@ -249,6 +297,8 @@ QWidget* dialog = new QWidget(&window, Qt::Dialog); dialog->show(); + //Queue closing the information message box + closeInformationMessageBox(1000); QPointer<RemoteObjectChooser> chooser = new RemoteObjectChooser(dialog); chooser->show(); @@ -269,6 +319,8 @@ TargetApplication::self()->setTargetApplicationFilePath(mPath); QWidget window(0, Qt::Window); + //Queue closing the information message box + closeInformationMessageBox(1000); RemoteObjectChooser* chooser = new RemoteObjectChooser(&window); chooser->show(); @@ -315,6 +367,8 @@ QWidget* dialog = new QWidget(&window, Qt::Dialog); dialog->show(); + //Queue closing the information message box + closeInformationMessageBox(1000); QPointer<RemoteObjectChooser> chooser = new RemoteObjectChooser(dialog); chooser->show(); @@ -358,6 +412,8 @@ QWidget* dialog = new QWidget(&window, Qt::Dialog); dialog->show(); + //Queue closing the information message box + closeInformationMessageBox(1000); QPointer<RemoteObjectChooser> chooser = new RemoteObjectChooser(dialog); chooser->show(); @@ -387,38 +443,78 @@ /////////////////////////////////// Helpers //////////////////////////////////// -class CloseMessageBoxHelper: public QObject { +//The message boxes are modal, so they won't return to the test code until they +//are closed. Thus, the actions to be performed while the message boxes are +//being shown (like closing the message boxes themselves) must be "queued". +class QueuedActionsHelper: public QObject { Q_OBJECT public: - CloseMessageBoxHelper(QWidget* widget): + QueuedActionsHelper(QWidget* widget = 0): QObject(widget), mWidget(widget) { } public slots: - void closeMessageBox() const { + void closeInformation() const { + //The information message box is created in the constructor itself of + //RemoteObjectChooser, so the RemoteObjectChooser can not be passed as + //an argument when this helper is created. It must be got when it is + //going to be destroyed. + QWidget* widget = findRemoteObjectChooser(); + QVERIFY(widget); + + KDialog* messageBox = widget->findChild<KDialog*>("information"); + QVERIFY(messageBox); + delete messageBox; + } + + void closeSorry() const { KDialog* messageBox = mWidget->findChild<KDialog*>("sorry"); QVERIFY(messageBox); delete messageBox; } + void killTargetApplication() const { + TargetApplication::self()->mProcess->kill(); + } + private: QWidget* mWidget; + QWidget* findRemoteObjectChooser() const { + foreach (QWidget* widget, QApplication::topLevelWidgets()) { + if (qobject_cast<RemoteObjectChooser*>(widget)) { + return widget; + } + } + + return 0; + } + }; -void RemoteObjectChooserTest::closeMessageBox(QWidget* widget, int timeToWait) { - CloseMessageBoxHelper* helper = new CloseMessageBoxHelper(widget); +void RemoteObjectChooserTest::closeInformationMessageBox(int timeToWait) { + QueuedActionsHelper* helper = new QueuedActionsHelper(); + QTimer::singleShot(timeToWait, helper, SLOT(closeInformation())); + QTimer::singleShot(timeToWait, helper, SLOT(deleteLater())); +} - //The message box is modal, so it won't return to the test code until it is - //closed. Thus, the commands to close the message box must be "queued", as - //deleting the message box after the qWait won't work. - QTimer::singleShot(timeToWait, helper, SLOT(closeMessageBox())); +void RemoteObjectChooserTest::closeSorryMessageBox(QWidget* widget, + int timeToWait) { + QueuedActionsHelper* helper = new QueuedActionsHelper(widget); + QTimer::singleShot(timeToWait, helper, SLOT(closeSorry())); + QTimer::singleShot(timeToWait, helper, SLOT(deleteLater())); } +void RemoteObjectChooserTest::killTargetApplication(int timeToWait) { + QueuedActionsHelper* helper = new QueuedActionsHelper(); + QTimer::singleShot(timeToWait, helper, SLOT(killTargetApplication())); + QTimer::singleShot(timeToWait, helper, SLOT(deleteLater())); +} + QTreeView* RemoteObjectChooserTest::remoteObjectsTreeView( RemoteObjectChooser* widget) const { return widget->findChild<QTreeView*>("remoteObjectsTreeView"); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |