sigproxy: Actually rename SyncableObjects when requested
authorManuel Nickschas <sputnick@quassel-irc.org>
Wed, 17 Oct 2018 20:14:24 +0000 (22:14 +0200)
committerManuel Nickschas <sputnick@quassel-irc.org>
Sun, 18 Nov 2018 10:06:43 +0000 (11:06 +0100)
Until now, renaming a SyncableObject would properly update the maps
in SignalProxy, but it would not actually update the objectName
property on the client side. Fix this.

Remove the renameObject() method in SyncableObject in favor of
using setObjectName() and listening to the notifier signal emitted
by Qt for triggering the update. This ensures that the actual object
name and the expected one stay in sync. Also change places where
we unnecessarily rename right after construction to use the
appropriate constructor instead.

Extend the test case to cover the renaming of SyncableObject.

src/common/dccconfig.cpp
src/common/identity.cpp
src/common/ircuser.cpp
src/common/signalproxy.cpp
src/common/syncableobject.cpp
src/common/syncableobject.h
src/common/transfer.cpp
src/common/transfermanager.cpp
src/core/coreidentity.cpp
tests/common/signalproxytest.cpp

index ae9a0e0..811db52 100644 (file)
@@ -25,7 +25,7 @@
 #include "types.h"
 
 DccConfig::DccConfig(QObject* parent)
 #include "types.h"
 
 DccConfig::DccConfig(QObject* parent)
-    : SyncableObject(parent)
+    : SyncableObject("DccConfig", parent)
 {
     static auto regTypes = []() -> bool {
         qRegisterMetaTypeStreamOperators<IpDetectionMode>("DccConfig::IpDetectionMode");
 {
     static auto regTypes = []() -> bool {
         qRegisterMetaTypeStreamOperators<IpDetectionMode>("DccConfig::IpDetectionMode");
@@ -34,7 +34,6 @@ DccConfig::DccConfig(QObject* parent)
     }();
     Q_UNUSED(regTypes);
 
     }();
     Q_UNUSED(regTypes);
 
-    renameObject("DccConfig");
     setAllowClientUpdates(true);
 }
 
     setAllowClientUpdates(true);
 }
 
index 4b78cfd..9fcd4a0 100644 (file)
@@ -195,7 +195,7 @@ void Identity::setId(IdentityId _id)
     _identityId = _id;
     SYNC(ARG(_id))
     emit idSet(_id);
     _identityId = _id;
     SYNC(ARG(_id))
     emit idSet(_id);
-    renameObject(QString::number(id().toInt()));
+    setObjectName(QString::number(id().toInt()));
 }
 
 void Identity::setIdentityName(const QString& identityName)
 }
 
 void Identity::setIdentityName(const QString& identityName)
index a952ec0..e0bcc78 100644 (file)
@@ -262,7 +262,7 @@ void IrcUser::setEncrypted(bool encrypted)
 
 void IrcUser::updateObjectName()
 {
 
 void IrcUser::updateObjectName()
 {
-    renameObject(QString::number(network()->networkId().toInt()) + "/" + _nick);
+    setObjectName(QString::number(network()->networkId().toInt()) + "/" + _nick);
 }
 
 void IrcUser::updateHostmask(const QString& mask)
 }
 
 void IrcUser::updateHostmask(const QString& mask)
index 9e47dd3..7434ea5 100644 (file)
@@ -372,9 +372,12 @@ void SignalProxy::renameObject(const SyncableObject* obj, const QString& newname
 
 void SignalProxy::objectRenamed(const QByteArray& classname, const QString& newname, const QString& oldname)
 {
 
 void SignalProxy::objectRenamed(const QByteArray& classname, const QString& newname, const QString& oldname)
 {
-    if (_syncSlave.contains(classname) && _syncSlave[classname].contains(oldname) && oldname != newname) {
-        SyncableObject* obj = _syncSlave[classname][newname] = _syncSlave[classname].take(oldname);
-        requestInit(obj);
+    if (newname != oldname) {
+        if (_syncSlave.contains(classname) && _syncSlave[classname].contains(oldname)) {
+            SyncableObject* obj = _syncSlave[classname][newname] = _syncSlave[classname].take(oldname);
+            obj->setObjectName(newname);
+            requestInit(obj);
+        }
     }
 }
 
     }
 }
 
index 9fd7704..695ab91 100644 (file)
 #include "util.h"
 
 SyncableObject::SyncableObject(QObject* parent)
 #include "util.h"
 
 SyncableObject::SyncableObject(QObject* parent)
-    : QObject(parent)
+    : SyncableObject(QString{}, parent)
 {}
 
 SyncableObject::SyncableObject(const QString& objectName, QObject* parent)
     : QObject(parent)
 {
 {}
 
 SyncableObject::SyncableObject(const QString& objectName, QObject* parent)
     : QObject(parent)
 {
+    _objectName = objectName;
     setObjectName(objectName);
     setObjectName(objectName);
+
+    connect(this, &QObject::objectNameChanged, this, [this](auto&& newName) {
+        for (auto&& proxy : _signalProxies) {
+            proxy->renameObject(this, newName, _objectName);
+        }
+        _objectName = newName;
+    });
 }
 
 SyncableObject::SyncableObject(const SyncableObject& other, QObject* parent)
 }
 
 SyncableObject::SyncableObject(const SyncableObject& other, QObject* parent)
-    : QObject(parent)
-    , _initialized(other._initialized)
-    , _allowClientUpdates(other._allowClientUpdates)
-{}
+    : SyncableObject(QString{}, parent)
+{
+    _initialized = other._initialized;
+    _allowClientUpdates = other._allowClientUpdates;
+}
 
 SyncableObject::~SyncableObject()
 {
 
 SyncableObject::~SyncableObject()
 {
@@ -156,17 +165,6 @@ bool SyncableObject::setInitValue(const QString& property, const QVariant& value
     return QMetaObject::invokeMethod(this, handlername.toLatin1(), param);
 }
 
     return QMetaObject::invokeMethod(this, handlername.toLatin1(), param);
 }
 
-void SyncableObject::renameObject(const QString& newName)
-{
-    const QString oldName = objectName();
-    if (oldName != newName) {
-        setObjectName(newName);
-        foreach (SignalProxy* proxy, _signalProxies) {
-            proxy->renameObject(this, newName, oldName);
-        }
-    }
-}
-
 void SyncableObject::update(const QVariantMap& properties)
 {
     fromVariantMap(properties);
 void SyncableObject::update(const QVariantMap& properties)
 {
     fromVariantMap(properties);
index 7d5242b..f1687d9 100644 (file)
@@ -94,7 +94,6 @@ public slots:
 protected:
     void sync_call__(SignalProxy::ProxyMode modeType, const char* funcname, ...) const;
 
 protected:
     void sync_call__(SignalProxy::ProxyMode modeType, const char* funcname, ...) const;
 
-    void renameObject(const QString& newName);
     SyncableObject& operator=(const SyncableObject& other);
 
 signals:
     SyncableObject& operator=(const SyncableObject& other);
 
 signals:
@@ -108,6 +107,8 @@ private:
 
     bool setInitValue(const QString& property, const QVariant& value);
 
 
     bool setInitValue(const QString& property, const QVariant& value);
 
+private:
+    QString _objectName;
     bool _initialized{false};
     bool _allowClientUpdates{false};
 
     bool _initialized{false};
     bool _allowClientUpdates{false};
 
index d33a9a3..3a9bd52 100644 (file)
@@ -59,7 +59,7 @@ void Transfer::init()
     }();
     Q_UNUSED(regTypes);
 
     }();
     Q_UNUSED(regTypes);
 
-    renameObject(QString("Transfer/%1").arg(_uuid.toString()));
+    setObjectName(QString("Transfer/%1").arg(_uuid.toString()));
     setAllowClientUpdates(true);
 }
 
     setAllowClientUpdates(true);
 }
 
index 4df5589..d8b11e3 100644 (file)
 #include "transfer.h"
 
 TransferManager::TransferManager(QObject* parent)
 #include "transfer.h"
 
 TransferManager::TransferManager(QObject* parent)
-    : SyncableObject(parent)
+    : SyncableObject("TransferManager", parent)
 {
     static auto regTypes = []() -> bool {
         qRegisterMetaTypeStreamOperators<TransferIdList>("TransferManager::TransferIdList");
         return true;
     }();
     Q_UNUSED(regTypes);
 {
     static auto regTypes = []() -> bool {
         qRegisterMetaTypeStreamOperators<TransferIdList>("TransferManager::TransferIdList");
         return true;
     }();
     Q_UNUSED(regTypes);
-
-    renameObject("TransferManager");
 }
 
 Transfer* TransferManager::transfer(const QUuid& uuid) const
 }
 
 Transfer* TransferManager::transfer(const QUuid& uuid) const
index f0b75b0..91b6519 100644 (file)
@@ -110,7 +110,7 @@ CoreCertManager::CoreCertManager(CoreIdentity& identity)
 
 void CoreCertManager::setId(IdentityId id)
 {
 
 void CoreCertManager::setId(IdentityId id)
 {
-    renameObject(QString::number(id.toInt()));
+    setObjectName(QString::number(id.toInt()));
 }
 
 void CoreCertManager::setSslKey(const QByteArray& encoded)
 }
 
 void CoreCertManager::setSslKey(const QByteArray& encoded)
index 18b71e1..a6b91fa 100644 (file)
@@ -141,7 +141,6 @@ class SyncObj : public SyncableObject
     Q_PROPERTY(double doubleProperty READ doubleProperty WRITE setDoubleProperty)
 
 public:
     Q_PROPERTY(double doubleProperty READ doubleProperty WRITE setDoubleProperty)
 
 public:
-
     int intProperty() const
     {
         return _intProperty;
     int intProperty() const
     {
         return _intProperty;
@@ -271,6 +270,10 @@ TEST_F(SignalProxyTest, syncableObject)
                                                              {"intProperty", 17},
                                                              {"doubleProperty", 2.3}
                                                          }))));
                                                              {"intProperty", 17},
                                                              {"doubleProperty", 2.3}
                                                          }))));
+
+        // Rename object
+        EXPECT_CALL(*_serverPeer, Dispatches(RpcCall(Eq("__objectRenamed__"), ElementsAre("SyncObj", "Bar", "Foo"))));
+        EXPECT_CALL(*_serverPeer, Dispatches(SyncMessage(Eq("SyncObj"), Eq("Bar"), Eq("setStringProperty"), ElementsAre("Hi Universe"))));
     }
 
     SignalSpy spy;
     }
 
     SignalSpy spy;
@@ -346,6 +349,14 @@ TEST_F(SignalProxyTest, syncableObject)
     EXPECT_EQ(17, clientObject.intProperty());
     EXPECT_EQ("Quassel", clientObject.stringProperty());
     EXPECT_EQ(2.3, clientObject.doubleProperty());
     EXPECT_EQ(17, clientObject.intProperty());
     EXPECT_EQ("Quassel", clientObject.stringProperty());
     EXPECT_EQ(2.3, clientObject.doubleProperty());
+
+    // -- Rename object
+    spy.connect(&clientObject, &SyncObj::stringPropertyChanged);
+    serverObject.setObjectName("Bar");
+    serverObject.setStringProperty("Hi Universe");
+    ASSERT_TRUE(spy.wait());
+    EXPECT_EQ("Bar", clientObject.objectName());
+    EXPECT_EQ("Hi Universe", clientObject.stringProperty());
 }
 
 #include "signalproxytest.moc"
 }
 
 #include "signalproxytest.moc"