Testing a new concept for the SyncableObjects.
authorMarcus Eggenberger <egs@quassel-irc.org>
Sun, 9 Aug 2009 16:21:07 +0000 (18:21 +0200)
committerMarcus Eggenberger <egs@quassel-irc.org>
Mon, 24 Aug 2009 19:54:06 +0000 (21:54 +0200)
src/common/ircuser.cpp
src/common/signalproxy.cpp
src/common/signalproxy.h
src/common/syncableobject.cpp
src/common/syncableobject.h

index 173f99f..fa20698 100644 (file)
@@ -171,6 +171,7 @@ void IrcUser::setLastAwayMessage(const int &lastAwayMessage) {
 }
 
 void IrcUser::setHost(const QString &host) {
 }
 
 void IrcUser::setHost(const QString &host) {
+  so_sync(so_arg_cast(host));
   if(!host.isEmpty() && _host != host) {
     _host = host;
     emit hostSet(host);
   if(!host.isEmpty() && _host != host) {
     _host = host;
     emit hostSet(host);
index 058e3cd..d7d2c5c 100644 (file)
@@ -583,6 +583,8 @@ void SignalProxy::synchronize(SyncableObject *obj) {
     else
       requestInit(obj);
   }
     else
       requestInit(obj);
   }
+
+  obj->synchronize(this);
 }
 
 void SignalProxy::detachObject(QObject *obj) {
 }
 
 void SignalProxy::detachObject(QObject *obj) {
@@ -1080,6 +1082,31 @@ void SignalProxy::customEvent(QEvent *event) {
   }
 }
 
   }
 }
 
+void SignalProxy::syncCall(const SyncableObject *obj, SignalProxy::ProxyMode modeType, const char *funcname, va_list ap) {
+  if(modeType != _proxyMode)
+    return;
+
+  ExtendedMetaObject *eMeta = extendedMetaObject(obj);
+
+  QVariantList params;
+
+  params << eMeta->metaObject()->className()
+         << obj->objectName()
+         << QByteArray(funcname);
+
+
+  const QList<int> &argTypes = eMeta->argTypes(eMeta->methodId(QByteArray(funcname)));
+
+  for(int i = 0; i < argTypes.size(); i++) {
+    if(argTypes[i] == 0) {
+      qWarning() << Q_FUNC_INFO << "received invalid data for argument number" << i << "of signal" << QString("%1::%2").arg(eMeta->metaObject()->className()).arg(funcname);
+      qWarning() << "        - make sure all your data types are known by the Qt MetaSystem";
+      return;
+    }
+    params << QVariant(argTypes[i], va_arg(ap, void *));
+  }
+}
+
 void SignalProxy::disconnectDevice(QIODevice *dev, const QString &reason) {
   if(!reason.isEmpty())
     qWarning() << qPrintable(reason);
 void SignalProxy::disconnectDevice(QIODevice *dev, const QString &reason) {
   if(!reason.isEmpty())
     qWarning() << qPrintable(reason);
@@ -1168,14 +1195,14 @@ const QList<int> &SignalProxy::ExtendedMetaObject::argTypes(int methodId) {
   return _argTypes[methodId];
 }
 
   return _argTypes[methodId];
 }
 
-const int &SignalProxy::ExtendedMetaObject::returnType(int methodId) {
+int SignalProxy::ExtendedMetaObject::returnType(int methodId) {
   if(!_returnType.contains(methodId)) {
     _returnType[methodId] = QMetaType::type(_meta->method(methodId).typeName());
   }
   return _returnType[methodId];
 }
 
   if(!_returnType.contains(methodId)) {
     _returnType[methodId] = QMetaType::type(_meta->method(methodId).typeName());
   }
   return _returnType[methodId];
 }
 
-const int &SignalProxy::ExtendedMetaObject::minArgCount(int methodId) {
+int SignalProxy::ExtendedMetaObject::minArgCount(int methodId) {
   if(!_minArgCount.contains(methodId)) {
     QString signature(_meta->method(methodId).signature());
     _minArgCount[methodId] = _meta->method(methodId).parameterTypes().count() - signature.count("=");
   if(!_minArgCount.contains(methodId)) {
     QString signature(_meta->method(methodId).signature());
     _minArgCount[methodId] = _meta->method(methodId).parameterTypes().count() - signature.count("=");
@@ -1190,6 +1217,21 @@ const QByteArray &SignalProxy::ExtendedMetaObject::methodName(int methodId) {
   return _methodNames[methodId];
 }
 
   return _methodNames[methodId];
 }
 
+int SignalProxy::ExtendedMetaObject::methodId(const QByteArray &methodName) {
+  if(_methodIds.contains(methodName)) {
+    return _methodIds[methodName];
+  } else {
+    for(int i = _meta->methodOffset(); i < _meta->methodCount(); i++) {
+      if(ExtendedMetaObject::methodName(_meta->method(i)) == methodName) {
+        _methodIds[methodName] = i;
+        return i;
+      }
+    }
+  }
+  Q_ASSERT(false);
+  return -1;
+}
+
 const QHash<QByteArray, int> &SignalProxy::ExtendedMetaObject::syncMap() {
   if(_syncMap.isEmpty()) {
     QHash<QByteArray, int> syncMap;
 const QHash<QByteArray, int> &SignalProxy::ExtendedMetaObject::syncMap() {
   if(_syncMap.isEmpty()) {
     QHash<QByteArray, int> syncMap;
index bac48db..4cbaf22 100644 (file)
@@ -118,6 +118,7 @@ public slots:
 
 protected:
   void customEvent(QEvent *event);
 
 protected:
   void customEvent(QEvent *event);
+  void syncCall(const SyncableObject *obj, ProxyMode modeType, const char *funcname, va_list ap);
 
 private slots:
   void dataAvailable();
 
 private slots:
   void dataAvailable();
@@ -202,6 +203,7 @@ private:
   bool _secure; // determines if all connections are in a secured state (using ssl or internal connections)
 
   friend class SignalRelay;
   bool _secure; // determines if all connections are in a secured state (using ssl or internal connections)
 
   friend class SignalRelay;
+  friend class SyncableObject;
 };
 
 
 };
 
 
@@ -213,9 +215,10 @@ public:
   ExtendedMetaObject(const QMetaObject *meta);
 
   const QList<int> &argTypes(int methodId);
   ExtendedMetaObject(const QMetaObject *meta);
 
   const QList<int> &argTypes(int methodId);
-  const int &returnType(int methodId);
-  const int &minArgCount(int methodId);
+  int returnType(int methodId);
+  int minArgCount(int methodId);
   const QByteArray &methodName(int methodId);
   const QByteArray &methodName(int methodId);
+  int methodId(const QByteArray &methodName);
   const QHash<QByteArray, int> &syncMap();
   const QHash<int, int> &receiveMap();
   int updatedRemotelyId();
   const QHash<QByteArray, int> &syncMap();
   const QHash<int, int> &receiveMap();
   int updatedRemotelyId();
@@ -229,12 +232,14 @@ public:
 private:
   typedef QHash<int, QList<int> > ArgHash;
   typedef QHash<int, QByteArray> MethodNameHash;
 private:
   typedef QHash<int, QList<int> > ArgHash;
   typedef QHash<int, QByteArray> MethodNameHash;
+  typedef QHash<QByteArray, int> MethodIdHash;
 
   const QMetaObject *_meta;
   ArgHash _argTypes;
   QHash<int, int> _returnType;
   QHash<int, int> _minArgCount;
   MethodNameHash _methodNames;
 
   const QMetaObject *_meta;
   ArgHash _argTypes;
   QHash<int, int> _returnType;
   QHash<int, int> _minArgCount;
   MethodNameHash _methodNames;
+  MethodIdHash _methodIds;
   int _updatedRemotelyId; // id of the updatedRemotely() signal - makes things faster
   QHash<QByteArray, int> _syncMap;
   QHash<int, int> _receiveMap;
   int _updatedRemotelyId; // id of the updatedRemotely() signal - makes things faster
   QHash<QByteArray, int> _syncMap;
   QHash<int, int> _receiveMap;
index 526e47a..aab2857 100644 (file)
@@ -58,6 +58,12 @@ SyncableObject &SyncableObject::operator=(const SyncableObject &other) {
   return *this;
 }
 
   return *this;
 }
 
+void SyncableObject::synchronize(SignalProxy *proxy) {
+  if(_signalProxies.contains(proxy))
+    return;
+  _signalProxies << proxy;
+}
+
 bool SyncableObject::isInitialized() const {
   return _initialized;
 }
 bool SyncableObject::isInitialized() const {
   return _initialized;
 }
@@ -155,3 +161,13 @@ void SyncableObject::requestUpdate(const QVariantMap &properties) {
   }
   emit updateRequested(properties);
 }
   }
   emit updateRequested(properties);
 }
+
+void SyncableObject::sync_call__(SignalProxy::ProxyMode modeType, const char *funcname, ...) {
+  qDebug() << Q_FUNC_INFO << modeType << funcname;
+  foreach(SignalProxy *proxy, _signalProxies) {
+    va_list ap;
+    va_start(ap, funcname);
+    proxy->syncCall(this, modeType, funcname, ap);
+    va_end(ap);
+  }
+}
index fbcdbbc..201c002 100644 (file)
@@ -26,6 +26,8 @@
 #include <QObject>
 #include <QVariantMap>
 
 #include <QObject>
 #include <QVariantMap>
 
+#include "signalproxy.h"
+
 class SyncableObject : public QObject {
   Q_OBJECT
 
 class SyncableObject : public QObject {
   Q_OBJECT
 
@@ -34,6 +36,8 @@ public:
   SyncableObject(const QString &objectName, QObject *parent = 0);
   SyncableObject(const SyncableObject &other, QObject *parent = 0);
 
   SyncableObject(const QString &objectName, QObject *parent = 0);
   SyncableObject(const SyncableObject &other, QObject *parent = 0);
 
+  void synchronize(SignalProxy *proxy);
+
   //! Stores the object's state into a QVariantMap.
   /** The default implementation takes dynamic properties as well as getters that have
    *  names starting with "init" and stores them in a QVariantMap. Override this method in
   //! Stores the object's state into a QVariantMap.
   /** The default implementation takes dynamic properties as well as getters that have
    *  names starting with "init" and stores them in a QVariantMap. Override this method in
@@ -65,6 +69,8 @@ public slots:
   virtual void update(const QVariantMap &properties);
 
 protected:
   virtual void update(const QVariantMap &properties);
 
 protected:
+  void sync_call__(SignalProxy::ProxyMode modeType, const char *funcname, ...);
+
   void renameObject(const QString &newName);
   SyncableObject &operator=(const SyncableObject &other);
 
   void renameObject(const QString &newName);
   SyncableObject &operator=(const SyncableObject &other);
 
@@ -81,6 +87,12 @@ private:
   bool _initialized;
   bool _allowClientUpdates;
 
   bool _initialized;
   bool _allowClientUpdates;
 
+  QList<SignalProxy *> _signalProxies;
 };
 
 };
 
+#define so_sync(...) sync_call__(SignalProxy::Server, __func__, __VA_ARGS__);
+#define so_request(...) sync_call__(SignalProxy::Client, __func__, __VA_ARGS__);
+#define so_arg_cast(x) const_cast<void *>(reinterpret_cast<const void*>(&x))
+
+
 #endif
 #endif