[Ktutorial-commits] SF.net SVN: ktutorial:[296] trunk/ktutorial/ktutorial-editor
Status: Alpha
Brought to you by:
danxuliu
From: <dan...@us...> - 2011-04-05 02:11:14
|
Revision: 296 http://ktutorial.svn.sourceforge.net/ktutorial/?rev=296&view=rev Author: danxuliu Date: 2011-04-05 02:11:06 +0000 (Tue, 05 Apr 2011) Log Message: ----------- Add support for object paths instead of just object names in RemoteObjectNameWidget. Now, when choosing an object, the ancestor names are included if necessary to differentiate between several remote objects with the same name. Modified Paths: -------------- trunk/ktutorial/ktutorial-editor/src/view/CMakeLists.txt trunk/ktutorial/ktutorial-editor/src/view/RemoteObjectNameWidget.cpp trunk/ktutorial/ktutorial-editor/src/view/RemoteObjectNameWidget.h trunk/ktutorial/ktutorial-editor/tests/unit/view/CMakeLists.txt trunk/ktutorial/ktutorial-editor/tests/unit/view/RemoteObjectNameWidgetTest.cpp Added Paths: ----------- trunk/ktutorial/ktutorial-editor/src/view/RemoteObjectNameRegister.cpp trunk/ktutorial/ktutorial-editor/src/view/RemoteObjectNameRegister.h trunk/ktutorial/ktutorial-editor/tests/unit/view/RemoteObjectNameRegisterTest.cpp Modified: trunk/ktutorial/ktutorial-editor/src/view/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/src/view/CMakeLists.txt 2011-04-05 02:00:36 UTC (rev 295) +++ trunk/ktutorial/ktutorial-editor/src/view/CMakeLists.txt 2011-04-05 02:11:06 UTC (rev 296) @@ -38,6 +38,7 @@ ${ktutorial_editor_view_SRCS} RemoteObjectChooser.cpp RemoteObjectChooserFilterModel.cpp + RemoteObjectNameRegister.cpp RemoteObjectNameWidget.cpp RemoteObjectTreeItem.cpp RemoteObjectTreeItemUpdater.cpp Added: trunk/ktutorial/ktutorial-editor/src/view/RemoteObjectNameRegister.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/view/RemoteObjectNameRegister.cpp (rev 0) +++ trunk/ktutorial/ktutorial-editor/src/view/RemoteObjectNameRegister.cpp 2011-04-05 02:11:06 UTC (rev 296) @@ -0,0 +1,322 @@ +/*************************************************************************** + * Copyright (C) 2011 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 "RemoteObjectNameRegister.h" + +#include <KDebug> + +#include "../targetapplication/RemoteEditorSupport.h" +#include "../targetapplication/RemoteEventSpy.h" +#include "../targetapplication/RemoteObject.h" +#include "../targetapplication/TargetApplication.h" + +//public: + +RemoteObjectNameRegister::RemoteObjectNameRegister(QObject* parent /*= 0*/): + QObject(parent) { + if (TargetApplication::self()->remoteEditorSupport()) { + registerRemoteObjects(); + } + + connect(TargetApplication::self(), SIGNAL(started()), + this, SLOT(registerRemoteObjects())); + connect(TargetApplication::self(), SIGNAL(finished()), + this, SLOT(deregisterRemoteObjects())); +} + +RemoteObjectNameRegister::~RemoteObjectNameRegister() { + if (TargetApplication::self()->remoteEditorSupport()) { + TargetApplication::self()->remoteEditorSupport()->disableEventSpy(); + } +} + +QStringList RemoteObjectNameRegister::names() const { + return mRemoteObjectForName.keys(); +} + +QString RemoteObjectNameRegister::uniqueName(RemoteObject* remoteObject) const +throw (DBusException) { + QString name = remoteObject->name(); + if (name.isEmpty()) { + return ""; + } + + QList<QStringList> reversedPathsToHomonyms = + reversedPathsToHomonymsOf(remoteObject); + if (reversedPathsToHomonyms.count() == 0) { + return name; + } + + QStringList reversedFullPath = reversedPathTo(remoteObject); + + for (int i=1; i<reversedFullPath.size(); ++i) { + if (ancestorNotInPaths(reversedFullPath[i], reversedPathsToHomonyms)) { + return reversedFullPath[i] + "/" + reversedFullPath[0]; + } + } + + QStringList reversedUniquePath; + reversedUniquePath.append(reversedFullPath[0]); + + for (int i=1; i<reversedFullPath.size(); ++i) { + reversedUniquePath.append(reversedFullPath[i]); + + if (isUniquePath(reversedUniquePath, reversedPathsToHomonyms)) { + return reversedPathAsName(reversedUniquePath); + } + } + + return reversedPathAsName(reversedUniquePath); +} + +RemoteObject* RemoteObjectNameRegister::findRemoteObject(const QString& name) + const { + return findRemoteObject(name, 0); +} + +//private: + +void RemoteObjectNameRegister::registerRemoteObject(RemoteObject* remoteObject, + RemoteObject* parent) +throw (DBusException) { + Q_ASSERT(remoteObject); + + mRemoteObjectForParent.insert(parent, remoteObject); + + QString name = remoteObject->name(); + if (!name.isEmpty()) { + emit nameAdded(name); + + mRemoteObjectForName.insert(name, remoteObject); + } + + foreach (RemoteObject* child, remoteObject->children()) { + registerRemoteObject(child, remoteObject); + } +} + +void RemoteObjectNameRegister::deregisterRemoteObject( + RemoteObject* remoteObject, + RemoteObject* parent) +throw (DBusException) { + Q_ASSERT(remoteObject); + + //The remote object is no longer accessible, so name() can't be called + QString name = mRemoteObjectForName.key(remoteObject); + + emit nameRemoved(name); + + mRemoteObjectForName.remove(name, remoteObject); + mRemoteObjectForParent.remove(parent, remoteObject); + + foreach (RemoteObject* child, remoteObject->children()) { + deregisterRemoteObject(child, remoteObject); + } +} + +QStringList RemoteObjectNameRegister::reversedPathTo( + RemoteObject* remoteObject) const +throw (DBusException) { + QStringList reversedPath; + + RemoteObject* parent = remoteObject; + while (parent) { + QString name = parent->name(); + if (!name.isEmpty() && !name.startsWith("qt_")) { + reversedPath.append(name); + } + parent = mRemoteObjectForParent.key(parent); + } + + return reversedPath; +} + +QList<QStringList> RemoteObjectNameRegister::reversedPathsToHomonymsOf( + RemoteObject* remoteObject) const +throw (DBusException) { + QList<QStringList> reversedPaths; + + QList<RemoteObject*> homonymRemoteObjects = + mRemoteObjectForName.values(remoteObject->name()); + homonymRemoteObjects.removeOne(remoteObject); + + foreach (RemoteObject* homonymRemoteObject, homonymRemoteObjects) { + reversedPaths.append(reversedPathTo(homonymRemoteObject)); + } + + return reversedPaths; +} + +bool RemoteObjectNameRegister::ancestorNotInPaths(const QString& ancestor, + const QList<QStringList>& reversedPaths) const { + foreach (const QStringList& reversedPath, reversedPaths) { + if (reversedPath.contains(ancestor)) { + return false; + } + } + + return true; +} + +bool RemoteObjectNameRegister::isUniquePath( + const QStringList& reversedPathToCheck, + const QList<QStringList>& reversedPaths) const { + for (int i=0; i<reversedPaths.size(); ++i) { + if (!isUniquePath(reversedPathToCheck, reversedPaths[i])) { + return false; + } + } + + return true; +} + +bool RemoteObjectNameRegister::isUniquePath( + const QStringList& reversedPathToCheck, + const QStringList& reversedPath) const { + int commonAncestorIndex = -1; + for (int i=reversedPathToCheck.size()-1; i>0; --i) { + commonAncestorIndex = reversedPath.lastIndexOf(reversedPathToCheck[i], + commonAncestorIndex); + if (commonAncestorIndex == -1) { + return true; + } + } + + return false; +} + +QString RemoteObjectNameRegister::reversedPathAsName( + const QStringList& reversedPath) const { + QString name = reversedPath[0]; + for (int i=1; i<reversedPath.size(); ++i) { + name = reversedPath[i] + '/' + name; + } + + return name; +} + +RemoteObject* RemoteObjectNameRegister::findRemoteObject(const QString& name, + RemoteObject* ancestor) const { + if (name.indexOf('/') == -1) { + QList<RemoteObject*> remoteObjects = mRemoteObjectForName.values(name); + foreach (RemoteObject* remoteObject, remoteObjects) { + if (isDescendantOf(remoteObject, ancestor)) { + return remoteObject; + } + } + + return 0; + } + + QRegExp slashPattern("/+"); + QString ancestorName = name.left(name.indexOf(slashPattern)); + QString descendantName = name.mid(ancestorName.length() + + slashPattern.matchedLength()); + + QList<RemoteObject*> namedAncestors = + mRemoteObjectForName.values(ancestorName); + + foreach (RemoteObject* namedAncestor, namedAncestors) { + if (isDescendantOf(namedAncestor, ancestor)) { + RemoteObject* remoteObject = findRemoteObject(descendantName, + namedAncestor); + if (remoteObject) { + return remoteObject; + } + } + } + + return 0; +} + +bool RemoteObjectNameRegister::isDescendantOf(RemoteObject* remoteObject, + RemoteObject* ancestor) const { + if (!ancestor) { + return true; + } + + QList<RemoteObject*> children = mRemoteObjectForParent.values(ancestor); + foreach (RemoteObject* child, children) { + if (child == remoteObject || isDescendantOf(remoteObject, child)) { + return true; + } + } + + return false; +} + +//private slots: + +void RemoteObjectNameRegister::registerRemoteObjects() { + try { + registerRemoteObject(TargetApplication::self()-> + remoteEditorSupport()->mainWindow(), 0); + } catch (DBusException e) { + kWarning() << "The remote objects could not be registered to provide " + << "name completion (" << e.message() << ")."; + } + + try { + RemoteEventSpy* remoteEventSpy = + TargetApplication::self()->remoteEditorSupport()->enableEventSpy(); + connect(remoteEventSpy, SIGNAL(eventReceived(RemoteObject*,QString)), + this, SLOT(updateRemoteObjects(RemoteObject*,QString))); + } catch (DBusException e) { + kWarning() << "The remote event spy could not be connected to provide " + << "name completion updates (" << e.message() << ")."; + } +} + +void RemoteObjectNameRegister::deregisterRemoteObjects() { + mRemoteObjectForName.clear(); + mRemoteObjectForParent.clear(); +} + +void RemoteObjectNameRegister::updateRemoteObjects(RemoteObject* remoteObject, + const QString& eventType) { + if (eventType != "ChildAdded" && eventType != "ChildRemoved") { + return; + } + + try { + QList<RemoteObject*> children = remoteObject->children(); + + QList<RemoteObject*> knownChildren = + mRemoteObjectForParent.values(remoteObject); + + if (eventType == "ChildAdded") { + foreach (RemoteObject* child, children) { + if (!knownChildren.contains(child)) { + registerRemoteObject(child, remoteObject); + } + } + } + + if (eventType == "ChildRemoved") { + foreach (RemoteObject* child, knownChildren) { + if (!children.contains(child)) { + deregisterRemoteObject(child, remoteObject); + } + } + } + } catch (DBusException e) { + kWarning() << "There was a problem querying the remote objects, the " + << "name completion could not be updated (" + << e.message() << ")."; + } +} Property changes on: trunk/ktutorial/ktutorial-editor/src/view/RemoteObjectNameRegister.cpp ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/ktutorial/ktutorial-editor/src/view/RemoteObjectNameRegister.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/view/RemoteObjectNameRegister.h (rev 0) +++ trunk/ktutorial/ktutorial-editor/src/view/RemoteObjectNameRegister.h 2011-04-05 02:11:06 UTC (rev 296) @@ -0,0 +1,302 @@ +/*************************************************************************** + * Copyright (C) 2011 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 REMOTEOBJECTNAMEREGISTER_H +#define REMOTEOBJECTNAMEREGISTER_H + +#include <QMultiHash> +#include <QObject> + +#include "../targetapplication/DBusException.h" + +class RemoteObject; + +/** + * Provides information related to the names of the remote objects in the target + * application. + * RemoteObjectNameRegister can be used to know the names of all the remote + * objects accesible by KTutorial in the target application, and it also + * notifies the names of the remote objects added or removed in the target + * application through the signals nameAdded(QString) and nameRemoved(QString). + * + * However, sometimes two or more remote objects may have the same name. In that + * case, the names of one or more ancestors are required to differentiate + * between those remote objects. The compound name that identifies a remote + * object can be got using uniqueName(RemoteObject*). Also, given a name, the + * remote object that it represents can be got using findObject(QString). + * + * Note that a name and the remote object it represents depends on the state of + * the target application. For example, if there is a dialog named + * "Configuration dialog" with a button named "Ok button", its unique name could + * be just "Ok button". However, if another dialog named "File information + * dialog" were opened while the "Configuration dialog" was still opened, and + * "File information dialog" had a also button called "Ok button", now the + * unique name of the first button would be "Configuration dialog/Ok button". In + * this situation, "Ok button" would not represent a specific remote object. + */ +class RemoteObjectNameRegister: public QObject { +Q_OBJECT +public: + + /** + * Creates a new RemoteObjectNameRegister. + * + * @param parent The parent QObject. + */ + explicit RemoteObjectNameRegister(QObject* parent = 0); + + /** + * Destroys this RemoteObjectNameRegister. + * If necessary, disables the EventSpy used to update the remote object + * names. + */ + virtual ~RemoteObjectNameRegister(); + + /** + * Returns a list with all the names. + * + * @return A list with all the names. + */ + QStringList names() const; + + /** + * Returns a unique name for the given remote object. + * When the remote object name is unique by itself, its name is returned. + * When there are other remote objects with the same name as the given one, + * but it has an ancestor with a unique name, the returned name includes + * both names. The ancestor with a unique name used is the nearest one to + * the remote object (parent preferred to grandparent, grandparent preferred + * to great-grandparent and so on). + * When there are other remote objects with the same name as the given one, + * and no ancestor has a unique name, the returned name includes as many + * ancestor names as necessary to create a name unique to the given remote + * object. + * + * @param remoteObject The remote object to get its unique name. + * @return A unique name for the given remote object. + * @throws DBusException If a DBus error happens. + */ + QString uniqueName(RemoteObject* remoteObject) const throw (DBusException); + + /** + * Returns the remote object with the given name, if any. + * When the name of the desired remote object is not unique the name of some + * ancestor must be included. Ancestor names are separated using a "/". That + * is, "Ancestor name/The remote object with a repeated name". As many + * ancestor names as desired can be included, not just one. + * The name of the ancestors does not need to be unique either; what has to + * be unique is the full path to the remote object to find. For example, + * "Ancestor name not unique/The remote object to find" is valid if, among + * all the remote objects called "Ancestor name not unique", there is only + * one that has a descendant called "The remote object to find". + * + * @param name The name of the remote object to find. + * @return The remote object with the specified name, or a null pointer if + * there is none. + */ + RemoteObject* findRemoteObject(const QString& name) const; + +Q_SIGNALS: + + /** + * Emitted when the name of a remote object is added to the register. + * + * @param name The name added. + */ + void nameAdded(const QString& name); + + /** + * Emitted when the name of a remote object is removed from the register. + * + * @param name The name removed. + */ + void nameRemoved(const QString& name); + +private: + + /** + * The RemoteObjects with a name indexed by their name. + */ + QMultiHash<QString, RemoteObject*> mRemoteObjectForName; + + /** + * The known RemoteObjects (with and without name) indexed by their parent. + */ + QMultiHash<RemoteObject*, RemoteObject*> mRemoteObjectForParent; + + /** + * Registers the given RemoteObject and all its children. + * The objects are only registered if they have a name. + * + * @param remoteObject The RemoteObject to register. + * @param parent The parent of the RemoteObject to register. + * @throws DBusException If a DBus error happens. + */ + void registerRemoteObject(RemoteObject* remoteObject, RemoteObject* parent) + throw (DBusException); + + /** + * Deregisters the given RemoteObject and all its children. + * + * @param remoteObject The RemoteObject to deregister. + * @param parent The parent of the RemoteObject to deregister. + * @throws DBusException If a DBus error happens. + */ + void deregisterRemoteObject(RemoteObject* remoteObject, + RemoteObject* parent) + throw (DBusException); + + /** + * Returns the reversed path to the given remote object. + * The path contains the name of the remote object itself and all its named + * ancestors. The order of the items is reversed from the natural path, that + * is, the first item in the returned path is the remote object name, the + * second item is the name of its parent, the third is the name of its + * grandparent... + * Empty names and Qt default names (like "qt_scrollarea_viewport") are not + * included in the path. + * + * @param remoteObject The remote object to get its path. + * @return The reversed path to the given remote object. + * @throws DBusException If a DBus error happens. + */ + QStringList reversedPathTo(RemoteObject* remoteObject) const + throw (DBusException); + + /** + * Returns the reversed paths to the remote objects with the same name as + * the given one. + * + * @param remoteObject The remote object to get the paths to its homonyms. + * @return The reversed paths to the homonyms of the given remote object. + * @throws DBusException If a DBus error happens. + * @see reversedPathTo(RemoteObject*) + */ + QList<QStringList> reversedPathsToHomonymsOf(RemoteObject* remoteObject) + const + throw (DBusException); + + /** + * Checks if the ancestor is unique, that is, if the paths do not contain + * the given ancestor. + * + * @param ancestor The ancestor to check. + * @param reversedPaths The list with the paths to check. + * @return True if the paths do not contain the given ancestor, false + * otherwise. + */ + bool ancestorNotInPaths(const QString& ancestor, + const QList<QStringList>& reversedPaths) const; + + /** + * Checks if the path represents a remote object that is unique regarding + * the reference paths. + * + * @param reversedPathToCheck The path to check. + * @param reversedPaths The other paths to check against. + * @return True if the path is unique, false otherwise. + * @see isUniquePath(const QStringList&, const QStringList&) + */ + bool isUniquePath(const QStringList& reversedPathToCheck, + const QList<QStringList>& reversedPaths) const; + + /** + * Checks if the path represents a remote object that is unique regarding + * the reference path. + * Note that the argument order matters. The path to check can be unique + * regarding the reference path and, at the same time, the reference path + * can be used to find the same remote object as the path to check. Take, + * for example, "Common ancestor/Another ancestor/Duplicated object name" as + * the path to check and "Common ancestor/Duplicated object name" as the + * reference path. The reference path may represent a remote object named + * "Duplicated object name" that is child of the remote object named + * "Common ancestor", but when using that path to find the object it + * represents it would represent both that object and the one represented by + * the path to check (as ANY remote object named "Duplicated object name" + * that is descendant of the remote object named "Common ancestor" would + * match). The path to check, on the other hand, would represent only its + * own object thanks to its extra ancestor. + * + * @param reversedPathToCheck The path to check. + * @param reversedPath The reference path to check against. + * @return True if the path is unique, false otherwise. + */ + bool isUniquePath(const QStringList& reversedPathToCheck, + const QStringList& reversedPath) const; + + /** + * Returns the name equivalent to the given reversed path. + * The name contains all the items in the path separated by "/". The order + * of the items in the name is their natural order, that is, the last item + * is the first one, the penultimate is the second one... + * + * @param path The reversed path to get its equivalent name. + * @return The name equivalent to the given reversed path. + */ + QString reversedPathAsName(const QStringList& reversedPath) const; + + /** + * Returns the remote object with the given name, if any. + * The name can contain also the ancestor names, separated by "/". The + * first object that matches the whole path is returned (note that ancestor + * are not necessarily direct parents). + * + * @param name The name of the remote object to find. + * @param ancestor The ancestor to look the remote object in. + * @return The remote object with the specified name, or a null pointer if + * there is none. + */ + RemoteObject* findRemoteObject(const QString& name, RemoteObject* ancestor) + const; + + /** + * Returns true if remoteObject is descendant of ancestor, false otherwise. + * When ancestor is null, it always returns true. + * + * @param remoteObject The remote object to check. + * @param ancestor The ancestor to check. + * @return True if remoteObject is descendant of ancestor, false otherwise. + */ + bool isDescendantOf(RemoteObject* remoteObject, + RemoteObject* ancestor) const; + +private Q_SLOTS: + + /** + * Registers all the remote objects. + */ + void registerRemoteObjects(); + + /** + * Deregisters all the remote objects. + */ + void deregisterRemoteObjects(); + + /** + * Updates the registered remote objects if they received a ChildAdded or + * ChildRemoved event. + * + * @param remoteObject The RemoteObject that received the event. + * @param eventType The type of the event received. + */ + void updateRemoteObjects(RemoteObject* remoteObject, + const QString& eventType); + +}; + +#endif Property changes on: trunk/ktutorial/ktutorial-editor/src/view/RemoteObjectNameRegister.h ___________________________________________________________________ Added: svn:eol-style + native Modified: trunk/ktutorial/ktutorial-editor/src/view/RemoteObjectNameWidget.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/src/view/RemoteObjectNameWidget.cpp 2011-04-05 02:00:36 UTC (rev 295) +++ trunk/ktutorial/ktutorial-editor/src/view/RemoteObjectNameWidget.cpp 2011-04-05 02:11:06 UTC (rev 296) @@ -19,13 +19,10 @@ #include "RemoteObjectNameWidget.h" #include "ui_RemoteObjectNameWidget.h" -#include <KDebug> #include <KMessageBox> #include "RemoteObjectChooser.h" -#include "../targetapplication/RemoteEditorSupport.h" -#include "../targetapplication/RemoteEventSpy.h" -#include "../targetapplication/RemoteObject.h" +#include "RemoteObjectNameRegister.h" #include "../targetapplication/TargetApplication.h" //public: @@ -33,31 +30,33 @@ RemoteObjectNameWidget::RemoteObjectNameWidget(QWidget* parent): QWidget(parent) { + mRemoteObjectNameRegister = new RemoteObjectNameRegister(this); + ui = new Ui::RemoteObjectNameWidget(); ui->setupUi(this); - ui->objectNameLineEdit->completionObject()->setOrder(KCompletion::Sorted); connect(ui->objectNameLineEdit, SIGNAL(textChanged(QString)), this, SLOT(handleNameChanged(QString))); connect(ui->objectNamePushButton, SIGNAL(clicked(bool)), this, SLOT(showRemoteObjectChooser())); - if (TargetApplication::self()->remoteEditorSupport()) { - registerRemoteObjects(); + KCompletion* completion = ui->objectNameLineEdit->completionObject(); + completion->setOrder(KCompletion::Sorted); + + foreach (const QString& name, mRemoteObjectNameRegister->names()) { + completion->addItem(name); } - connect(TargetApplication::self(), SIGNAL(started()), - this, SLOT(registerRemoteObjects())); + connect(mRemoteObjectNameRegister, SIGNAL(nameAdded(QString)), + completion, SLOT(addItem(QString))); + connect(mRemoteObjectNameRegister, SIGNAL(nameRemoved(QString)), + completion, SLOT(removeItem(QString))); connect(TargetApplication::self(), SIGNAL(finished()), - this, SLOT(deregisterRemoteObjects())); + completion, SLOT(clear())); } RemoteObjectNameWidget::~RemoteObjectNameWidget() { - if (TargetApplication::self()->remoteEditorSupport()) { - TargetApplication::self()->remoteEditorSupport()->disableEventSpy(); - } - delete ui; } @@ -69,46 +68,6 @@ ui->objectNameLineEdit->setText(name); } -//private: - -void RemoteObjectNameWidget::registerRemoteObject(RemoteObject* remoteObject, - RemoteObject* parent) -throw (DBusException) { - Q_ASSERT(remoteObject); - - mRemoteObjectForParent.insert(parent, remoteObject); - - if (!remoteObject->name().isEmpty()) { - KCompletion* completion = ui->objectNameLineEdit->completionObject(); - completion->addItem(remoteObject->name()); - - mRemoteObjectForName.insert(remoteObject->name(), remoteObject); - } - - foreach (RemoteObject* child, remoteObject->children()) { - registerRemoteObject(child, remoteObject); - } -} - -void RemoteObjectNameWidget::deregisterRemoteObject(RemoteObject* remoteObject, - RemoteObject* parent) -throw (DBusException) { - Q_ASSERT(remoteObject); - - //The remote object is no longer accessible, so name() can't be called - QString name = mRemoteObjectForName.key(remoteObject); - - KCompletion* completion = ui->objectNameLineEdit->completionObject(); - completion->removeItem(name); - - mRemoteObjectForName.remove(name); - mRemoteObjectForParent.remove(parent, remoteObject); - - foreach (RemoteObject* child, remoteObject->children()) { - deregisterRemoteObject(child, remoteObject); - } -} - //private slots: void RemoteObjectNameWidget::showRemoteObjectChooser() { @@ -121,7 +80,8 @@ void RemoteObjectNameWidget::setChosenRemoteObject(RemoteObject* remoteObject) { try { - ui->objectNameLineEdit->setText(remoteObject->name()); + ui->objectNameLineEdit->setText( + mRemoteObjectNameRegister->uniqueName(remoteObject)); } catch (DBusException e) { QString text = i18nc("@label", "The object name can not be set, there " "was a problem getting the name from the target application: %1", e.message()); @@ -131,66 +91,6 @@ } } -void RemoteObjectNameWidget::registerRemoteObjects() { - try { - registerRemoteObject(TargetApplication::self()-> - remoteEditorSupport()->mainWindow(), 0); - } catch (DBusException e) { - kWarning() << "The remote objects could not be registered to provide " - << "name completion (" << e.message() << ")."; - } - - try { - RemoteEventSpy* remoteEventSpy = - TargetApplication::self()->remoteEditorSupport()->enableEventSpy(); - connect(remoteEventSpy, SIGNAL(eventReceived(RemoteObject*,QString)), - this, SLOT(updateRemoteObjects(RemoteObject*,QString))); - } catch (DBusException e) { - kWarning() << "The remote event spy could not be connected to provide " - << "name completion updates (" << e.message() << ")."; - } -} - -void RemoteObjectNameWidget::deregisterRemoteObjects() { - ui->objectNameLineEdit->completionObject()->clear(); - mRemoteObjectForName.clear(); - mRemoteObjectForParent.clear(); -} - -void RemoteObjectNameWidget::updateRemoteObjects(RemoteObject* remoteObject, - const QString& eventType) { - if (eventType != "ChildAdded" && eventType != "ChildRemoved") { - return; - } - - try { - QList<RemoteObject*> children = remoteObject->children(); - - QList<RemoteObject*> knownChildren = - mRemoteObjectForParent.values(remoteObject); - - if (eventType == "ChildAdded") { - foreach (RemoteObject* child, children) { - if (!knownChildren.contains(child)) { - registerRemoteObject(child, remoteObject); - } - } - } - - if (eventType == "ChildRemoved") { - foreach (RemoteObject* child, knownChildren) { - if (!children.contains(child)) { - deregisterRemoteObject(child, remoteObject); - } - } - } - } catch (DBusException e) { - kWarning() << "There was a problem querying the remote objects, the " - << "name completion could not be updated (" - << e.message() << ")."; - } -} - void RemoteObjectNameWidget::handleNameChanged(const QString& name) { - emit remoteObjectChosen(mRemoteObjectForName.value(name)); + emit remoteObjectChosen(mRemoteObjectNameRegister->findRemoteObject(name)); } Modified: trunk/ktutorial/ktutorial-editor/src/view/RemoteObjectNameWidget.h =================================================================== --- trunk/ktutorial/ktutorial-editor/src/view/RemoteObjectNameWidget.h 2011-04-05 02:00:36 UTC (rev 295) +++ trunk/ktutorial/ktutorial-editor/src/view/RemoteObjectNameWidget.h 2011-04-05 02:11:06 UTC (rev 296) @@ -19,12 +19,10 @@ #ifndef REMOTEOBJECTNAMEWIDGET_H #define REMOTEOBJECTNAMEWIDGET_H -#include <QHash> #include <QWidget> -#include "../targetapplication/DBusException.h" - class RemoteObject; +class RemoteObjectNameRegister; namespace Ui { class RemoteObjectNameWidget; @@ -89,43 +87,16 @@ private: /** - * The RemoteObjects with a name indexed by their name. + * The register that provides the names of the remote objects and finds them + * based on their name. */ - QHash<QString, RemoteObject*> mRemoteObjectForName; + RemoteObjectNameRegister* mRemoteObjectNameRegister; /** - * The known RemoteObjects (with and without name) indexed by their parent. - */ - QMultiHash<RemoteObject*, RemoteObject*> mRemoteObjectForParent; - - /** * The Ui Designer generated class. */ Ui::RemoteObjectNameWidget* ui; - /** - * Registers the given RemoteObject and all its children. - * The objects are only registered if they have a name. In that case, it is - * added to the completion of the name line edit. - * - * @param remoteObject The RemoteObject to register. - * @param parent The parent of the RemoteObject to register. - * @throws DBusException If a DBus error happens. - */ - void registerRemoteObject(RemoteObject* remoteObject, RemoteObject* parent) - throw (DBusException); - - /** - * Deregisters the given RemoteObject and all its children. - * - * @param remoteObject The RemoteObject to deregister. - * @param parent The parent of the RemoteObject to deregister. - * @throws DBusException If a DBus error happens. - */ - void deregisterRemoteObject(RemoteObject* remoteObject, - RemoteObject* parent) - throw (DBusException); - private Q_SLOTS: /** @@ -141,28 +112,6 @@ void setChosenRemoteObject(RemoteObject* remoteObject); /** - * Registers the remote objects and add their names to the line edit - * completion object. - */ - void registerRemoteObjects(); - - /** - * Deregisters the remote objects and removes their names from the line edit - * completion object. - */ - void deregisterRemoteObjects(); - - /** - * Updates the registered remote objects if they received a ChildAdded or - * ChildRemoved event. - * - * @param remoteObject The RemoteObject that received the event. - * @param eventType The type of the event received. - */ - void updateRemoteObjects(RemoteObject* remoteObject, - const QString& eventType); - - /** * Emits remoteObjectChosen(RemoteObject*) with the remote object with the * given name. * Modified: trunk/ktutorial/ktutorial-editor/tests/unit/view/CMakeLists.txt =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/view/CMakeLists.txt 2011-04-05 02:00:36 UTC (rev 295) +++ trunk/ktutorial/ktutorial-editor/tests/unit/view/CMakeLists.txt 2011-04-05 02:11:06 UTC (rev 296) @@ -55,6 +55,7 @@ unit_tests( RemoteObjectChooser RemoteObjectChooserFilterModel + RemoteObjectNameRegister RemoteObjectNameWidget RemoteObjectTreeItem RemoteObjectTreeItemUpdater Added: trunk/ktutorial/ktutorial-editor/tests/unit/view/RemoteObjectNameRegisterTest.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/view/RemoteObjectNameRegisterTest.cpp (rev 0) +++ trunk/ktutorial/ktutorial-editor/tests/unit/view/RemoteObjectNameRegisterTest.cpp 2011-04-05 02:11:06 UTC (rev 296) @@ -0,0 +1,380 @@ +/*************************************************************************** + * Copyright (C) 2011 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 "RemoteObjectNameRegister.h" + +#include <KProcess> + +#include "../targetapplication/RemoteEditorSupport.h" +#include "../targetapplication/RemoteObject.h" +#define protected public +#define private public +#include "../targetapplication/TargetApplication.h" +#undef private +#undef protected + +class RemoteObjectNameRegisterTest: public QObject { +Q_OBJECT + +private slots: + + void init(); + void cleanup(); + + void testConstructor(); + + void testTargetApplicationStartedAfterRegister(); + void testTargetApplicationStopped(); + + void testAddingOrRemovingRemoteObjects(); + + void testFindRemoteObject(); + void testFindRemoteObjectWithParentName(); + void testFindRemoteObjectWithGrandparentName(); + void testFindRemoteObjectWithParentAndGrandparentNames(); + void testFindRemoteObjectWithUnknownName(); + + void testUniqueName(); + void testUniqueNameWhenUniqueParent(); + void testUniqueNameWhenUniqueGrandparentAndEmptyParent(); + void testUniqueNameWhenUniqueGrandparentAndDuplicatedParent(); + void testUniqueNameWhenUniqueUnionOfGrandparentAndParent(); + void testUniqueNameWhenEmptyName(); + +private: + + QString mPath; + + void assertNames(const QStringList& names) const; + +}; + +void RemoteObjectNameRegisterTest::init() { + mPath = QApplication::applicationDirPath() + + "/../targetapplication/TargetApplicationStub"; + + //Avoid signals from previews tests to be delivered to the next ones + //setting a new TargetApplication + delete TargetApplication::sSelf; + TargetApplication::sSelf = new TargetApplication(); +} + +void RemoteObjectNameRegisterTest::cleanup() { + delete TargetApplication::sSelf; + TargetApplication::sSelf = 0; +} + +void RemoteObjectNameRegisterTest::testConstructor() { + TargetApplication::self()->setTargetApplicationFilePath(mPath); + TargetApplication::self()->start(); + + //Give the target application time to start + QTest::qWait(1000); + + RemoteObjectNameRegister remoteObjectNameRegister; + + assertNames(remoteObjectNameRegister.names()); +} + +void RemoteObjectNameRegisterTest::testTargetApplicationStartedAfterRegister() { + RemoteObjectNameRegister remoteObjectNameRegister; + QSignalSpy nameAddedSpy(&remoteObjectNameRegister, + SIGNAL(nameAdded(QString))); + QSignalSpy nameRemovedSpy(&remoteObjectNameRegister, + SIGNAL(nameRemoved(QString))); + + TargetApplication::self()->setTargetApplicationFilePath(mPath); + TargetApplication::self()->start(); + + //Give the target application time to start + QTest::qWait(1000); + + assertNames(remoteObjectNameRegister.names()); + QCOMPARE(nameAddedSpy.count(), 82); + QCOMPARE(nameAddedSpy.at(0).at(0).toString(), + QString("The object name 42")); + QCOMPARE(nameAddedSpy.at(1).at(0).toString(), + QString("The object name 420")); + QCOMPARE(nameAddedSpy.at(5).at(0).toString(), + QString("Duplicated grandparent")); + QCOMPARE(nameAddedSpy.at(6).at(0).toString(), + QString("The object name 50")); + QCOMPARE(nameAddedSpy.at(7).at(0).toString(), + QString("Duplicated object")); + QCOMPARE(nameAddedSpy.at(11).at(0).toString(), + QString("The object name 51")); + QCOMPARE(nameAddedSpy.at(26).at(0).toString(), + QString("Duplicated grandparent")); + QCOMPARE(nameAddedSpy.at(27).at(0).toString(), + QString("Duplicated parent")); + QCOMPARE(nameAddedSpy.at(28).at(0).toString(), + QString("Duplicated object")); + QCOMPARE(nameAddedSpy.at(68).at(0).toString(), + QString("The object name 8")); + QCOMPARE(nameAddedSpy.at(69).at(0).toString(), + QString("Duplicated object")); + QCOMPARE(nameAddedSpy.at(70).at(0).toString(), + QString("The object name 801")); + QCOMPARE(nameAddedSpy.at(71).at(0).toString(), + QString("The object name 803")); + QCOMPARE(nameRemovedSpy.count(), 0); +} + +void RemoteObjectNameRegisterTest::testTargetApplicationStopped() { + TargetApplication::self()->setTargetApplicationFilePath(mPath); + TargetApplication::self()->start(); + + //Give the target application time to start + QTest::qWait(1000); + + RemoteObjectNameRegister remoteObjectNameRegister; + + QSignalSpy nameAddedSpy(&remoteObjectNameRegister, + SIGNAL(nameAdded(QString))); + QSignalSpy nameRemovedSpy(&remoteObjectNameRegister, + SIGNAL(nameAdded(QString))); + + TargetApplication::self()->mProcess->kill(); + + //Give the target application time to stop + QTest::qWait(1000); + + QVERIFY(remoteObjectNameRegister.names().isEmpty()); + QCOMPARE(nameAddedSpy.count(), 0); + QCOMPARE(nameRemovedSpy.count(), 0); +} + +void RemoteObjectNameRegisterTest::testAddingOrRemovingRemoteObjects() { + QSKIP("Unfortunately, testing if the signals are emitted when an object is " + "added or removed in the target application is too burdensome so the " + "test must be done manually", SkipAll); +} + +void RemoteObjectNameRegisterTest::testFindRemoteObject() { + TargetApplication::self()->setTargetApplicationFilePath(mPath); + TargetApplication::self()->start(); + + //Give the target application time to start + QTest::qWait(1000); + + RemoteObjectNameRegister remoteObjectNameRegister; + + RemoteObject* mainWindow = + TargetApplication::self()->remoteEditorSupport()->mainWindow(); + + QCOMPARE(remoteObjectNameRegister.findRemoteObject("The object name 423"), + mainWindow->children()[3]); +} + +void RemoteObjectNameRegisterTest::testFindRemoteObjectWithParentName() { + TargetApplication::self()->setTargetApplicationFilePath(mPath); + TargetApplication::self()->start(); + + //Give the target application time to start + QTest::qWait(1000); + + RemoteObjectNameRegister remoteObjectNameRegister; + + RemoteObject* mainWindow = + TargetApplication::self()->remoteEditorSupport()->mainWindow(); + + QCOMPARE(remoteObjectNameRegister.findRemoteObject( + "The object name 50/Duplicated object"), + mainWindow->children()[4]->children()[0]->children()[0]); +} + +void RemoteObjectNameRegisterTest::testFindRemoteObjectWithGrandparentName() { + TargetApplication::self()->setTargetApplicationFilePath(mPath); + TargetApplication::self()->start(); + + //Give the target application time to start + QTest::qWait(1000); + + RemoteObjectNameRegister remoteObjectNameRegister; + + RemoteObject* mainWindow = + TargetApplication::self()->remoteEditorSupport()->mainWindow(); + + QCOMPARE(remoteObjectNameRegister.findRemoteObject( + "The object name 7/Duplicated object"), + mainWindow->children()[6]->children()[0]->children()[0]); +} + +void RemoteObjectNameRegisterTest:: + testFindRemoteObjectWithParentAndGrandparentNames() { + TargetApplication::self()->setTargetApplicationFilePath(mPath); + TargetApplication::self()->start(); + + //Give the target application time to start + QTest::qWait(1000); + + RemoteObjectNameRegister remoteObjectNameRegister; + + RemoteObject* mainWindow = + TargetApplication::self()->remoteEditorSupport()->mainWindow(); + + QCOMPARE(remoteObjectNameRegister.findRemoteObject( + "Duplicated grandparent/Duplicated parent/Duplicated object"), + mainWindow->children()[5]->children()[0]->children()[0]); +} + +void RemoteObjectNameRegisterTest::testFindRemoteObjectWithUnknownName() { + TargetApplication::self()->setTargetApplicationFilePath(mPath); + TargetApplication::self()->start(); + + //Give the target application time to start + QTest::qWait(1000); + + RemoteObjectNameRegister remoteObjectNameRegister; + + QCOMPARE(remoteObjectNameRegister.findRemoteObject("The object name 108"), + (RemoteObject*)0); +} + +void RemoteObjectNameRegisterTest::testUniqueName() { + TargetApplication::self()->setTargetApplicationFilePath(mPath); + TargetApplication::self()->start(); + + //Give the target application time to start + QTest::qWait(1000); + + RemoteObjectNameRegister remoteObjectNameRegister; + + RemoteObject* mainWindow = + TargetApplication::self()->remoteEditorSupport()->mainWindow(); + RemoteObject* remoteObject = + mainWindow->children()[4]->children()[0]->children()[1]; + + QCOMPARE(remoteObjectNameRegister.uniqueName(remoteObject), + QString("The object name 501")); +} + +void RemoteObjectNameRegisterTest::testUniqueNameWhenUniqueParent() { + TargetApplication::self()->setTargetApplicationFilePath(mPath); + TargetApplication::self()->start(); + + //Give the target application time to start + QTest::qWait(1000); + + RemoteObjectNameRegister remoteObjectNameRegister; + + RemoteObject* mainWindow = + TargetApplication::self()->remoteEditorSupport()->mainWindow(); + RemoteObject* remoteObject = + mainWindow->children()[4]->children()[0]->children()[0]; + + QCOMPARE(remoteObjectNameRegister.uniqueName(remoteObject), + QString("The object name 50/Duplicated object")); +} + +void RemoteObjectNameRegisterTest:: + testUniqueNameWhenUniqueGrandparentAndEmptyParent() { + TargetApplication::self()->setTargetApplicationFilePath(mPath); + TargetApplication::self()->start(); + + //Give the target application time to start + QTest::qWait(1000); + + RemoteObjectNameRegister remoteObjectNameRegister; + + RemoteObject* mainWindow = + TargetApplication::self()->remoteEditorSupport()->mainWindow(); + RemoteObject* remoteObject = + mainWindow->children()[7]->children()[0]->children()[0]; + + QCOMPARE(remoteObjectNameRegister.uniqueName(remoteObject), + QString("The object name 8/Duplicated object")); +} + +void RemoteObjectNameRegisterTest:: + testUniqueNameWhenUniqueGrandparentAndDuplicatedParent() { + TargetApplication::self()->setTargetApplicationFilePath(mPath); + TargetApplication::self()->start(); + + //Give the target application time to start + QTest::qWait(1000); + + RemoteObjectNameRegister remoteObjectNameRegister; + + RemoteObject* mainWindow = + TargetApplication::self()->remoteEditorSupport()->mainWindow(); + RemoteObject* remoteObject = + mainWindow->children()[6]->children()[0]->children()[0]; + + QCOMPARE(remoteObjectNameRegister.uniqueName(remoteObject), + QString("The object name 7/Duplicated object")); +} + +void RemoteObjectNameRegisterTest:: + testUniqueNameWhenUniqueUnionOfGrandparentAndParent() { + TargetApplication::self()->setTargetApplicationFilePath(mPath); + TargetApplication::self()->start(); + + //Give the target application time to start + QTest::qWait(1000); + + RemoteObjectNameRegister remoteObjectNameRegister; + + RemoteObject* mainWindow = + TargetApplication::self()->remoteEditorSupport()->mainWindow(); + RemoteObject* remoteObject = + mainWindow->children()[5]->children()[0]->children()[0]; + + QCOMPARE(remoteObjectNameRegister.uniqueName(remoteObject), + QString("Duplicated grandparent/Duplicated parent/" + "Duplicated object")); +} + +void RemoteObjectNameRegisterTest::testUniqueNameWhenEmptyName() { + TargetApplication::self()->setTargetApplicationFilePath(mPath); + TargetApplication::self()->start(); + + //Give the target application time to start + QTest::qWait(1000); + + RemoteObjectNameRegister remoteObjectNameRegister; + + RemoteObject* mainWindow = + TargetApplication::self()->remoteEditorSupport()->mainWindow(); + RemoteObject* remoteObject = mainWindow->children()[7]->children()[0]; + + QCOMPARE(remoteObjectNameRegister.uniqueName(remoteObject), QString("")); +} + +/////////////////////////////////// Helpers //////////////////////////////////// + +void RemoteObjectNameRegisterTest::assertNames(const QStringList& names) const { + QCOMPARE(names.count(), 82); + QVERIFY(names.contains("The object name 42")); + QVERIFY(names.contains("The object name 420")); + QVERIFY(names.contains("The object name 421")); + QVERIFY(names.contains("The object name 422")); + QVERIFY(names.contains("The object name 423")); + QVERIFY(names.contains("The object name 7")); + QVERIFY(names.contains("The object name 62")); + QVERIFY(names.contains("The object name 833")); + QVERIFY(names.contains("Duplicated object")); + QVERIFY(names.contains("Duplicated parent")); + QVERIFY(names.contains("Duplicated grandparent")); +} + +QTEST_MAIN(RemoteObjectNameRegisterTest) + +#include "RemoteObjectNameRegisterTest.moc" Property changes on: trunk/ktutorial/ktutorial-editor/tests/unit/view/RemoteObjectNameRegisterTest.cpp ___________________________________________________________________ Added: svn:eol-style + native Modified: trunk/ktutorial/ktutorial-editor/tests/unit/view/RemoteObjectNameWidgetTest.cpp =================================================================== --- trunk/ktutorial/ktutorial-editor/tests/unit/view/RemoteObjectNameWidgetTest.cpp 2011-04-05 02:00:36 UTC (rev 295) +++ trunk/ktutorial/ktutorial-editor/tests/unit/view/RemoteObjectNameWidgetTest.cpp 2011-04-05 02:11:06 UTC (rev 296) @@ -18,7 +18,11 @@ #include <QtTest> +#define protected public +#define private public #include "RemoteObjectNameWidget.h" +#undef private +#undef protected #include <QtDBus/QtDBus> @@ -46,8 +50,12 @@ void testConstructor(); void testSetName(); + void testSetNameWithPath(); void testSetNameWithUnknownRemoteObjectName(); + void testSetChosenRemoteObject(); + void testSetChosenRemoteObjectWithNameNotUnique(); + void testTargetApplicationStartedAfterWidget(); void testTargetApplicationStopped(); @@ -129,6 +137,28 @@ mainWindow->children()[3]); } +void RemoteObjectNameWidgetTest::testSetNameWithPath() { + TargetApplication::self()->setTargetApplicationFilePath(mPath); + TargetApplication::self()->start(); + + //Give the target application time to start + QTest::qWait(1000); + + RemoteObjectNameWidget widget; + QSignalSpy remoteObjectChosenSpy(&widget, + SIGNAL(remoteObjectChosen(RemoteObject*))); + + widget.setName("The object name 7/Duplicated object"); + + RemoteObject* mainWindow = + TargetApplication::self()->remoteEditorSupport()->mainWindow(); + + QCOMPARE(widget.name(), QString("The object name 7/Duplicated object")); + QCOMPARE(remoteObjectChosenSpy.count(), 1); + assertRemoteObjectSignal(remoteObjectChosenSpy, 0, + mainWindow->children()[6]->children()[0]->children()[0]); +} + void RemoteObjectNameWidgetTest::testSetNameWithUnknownRemoteObjectName() { TargetApplication::self()->setTargetApplicationFilePath(mPath); TargetApplication::self()->start(); @@ -147,6 +177,67 @@ assertRemoteObjectSignal(remoteObjectChosenSpy, 0, 0); } +void RemoteObjectNameWidgetTest::testSetChosenRemoteObject() { + TargetApplication::self()->setTargetApplicationFilePath(mPath); + TargetApplication::self()->start(); + + //Give the target application time to start + QTest::qWait(1000); + + RemoteObjectNameWidget widget; + QSignalSpy remoteObjectChosenSpy(&widget, + SIGNAL(remoteObjectChosen(RemoteObject*))); + + RemoteObject* mainWindow = + TargetApplication::self()->remoteEditorSupport()->mainWindow(); + RemoteObject* remoteObject = + mainWindow->children()[4]->children()[0]->children()[1]; + + widget.setChosenRemoteObject(remoteObject); + + QCOMPARE(widget.name(), QString("The object name 501")); + QCOMPARE(remoteObjectChosenSpy.count(), 1); + assertRemoteObjectSignal(remoteObjectChosenSpy, 0, remoteObject); +} + +void RemoteObjectNameWidgetTest::testSetChosenRemoteObjectWithNameNotUnique() { + TargetApplication::self()->setTargetApplicationFilePath(mPath); + TargetApplication::self()->start(); + + //Give the target application time to start + QTest::qWait(1000); + + RemoteObjectNameWidget widget; + QSignalSpy remoteObjectChosenSpy(&widget, + SIGNAL(remoteObjectChosen(RemoteObject*))); + + RemoteObject* mainWindow = + TargetApplication::self()->remoteEditorSupport()->mainWindow(); + + RemoteObject* remoteObject = + mainWindow->children()[4]->children()[0]->children()[0]; + widget.setChosenRemoteObject(remoteObject); + + QCOMPARE(widget.name(), QString("The object name 50/Duplicated object")); + QCOMPARE(remoteObjectChosenSpy.count(), 1); + assertRemoteObjectSignal(remoteObjectChosenSpy, 0, remoteObject); + + remoteObject = mainWindow->children()[5]->children()[0]->children()[0]; + widget.setChosenRemoteObject(remoteObject); + + QCOMPARE(widget.name(), QString("Duplicated grandparent/Duplicated parent/" + "Duplicated object")); + QCOMPARE(remoteObjectChosenSpy.count(), 2); + assertRemoteObjectSignal(remoteObjectChosenSpy, 1, remoteObject); + + remoteObject = mainWindow->children()[6]->children()[0]->children()[0]; + widget.setChosenRemoteObject(remoteObject); + + QCOMPARE(widget.name(), QString("The object name 7/Duplicated object")); + QCOMPARE(remoteObjectChosenSpy.count(), 3); + assertRemoteObjectSignal(remoteObjectChosenSpy, 2, remoteObject); +} + void RemoteObjectNameWidgetTest::testTargetApplicationStartedAfterWidget() { RemoteObjectNameWidget widget; QSignalSpy remoteObjectChosenSpy(&widget, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |