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