From: Marcus Eggenberger Date: Sun, 9 Aug 2009 16:21:07 +0000 (+0200) Subject: Testing a new concept for the SyncableObjects. X-Git-Tag: 0.5-rc1~41 X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=commitdiff_plain;h=e89cfe68c0b4d117ce79d0d38fcc085de77a3083;hp=dfac7b1b66005a76a10a2aa2d64d551d4e11ae94 Testing a new concept for the SyncableObjects. --- diff --git a/src/common/ircuser.cpp b/src/common/ircuser.cpp index 173f99f6..fa206989 100644 --- a/src/common/ircuser.cpp +++ b/src/common/ircuser.cpp @@ -171,6 +171,7 @@ void IrcUser::setLastAwayMessage(const int &lastAwayMessage) { } void IrcUser::setHost(const QString &host) { + so_sync(so_arg_cast(host)); if(!host.isEmpty() && _host != host) { _host = host; emit hostSet(host); diff --git a/src/common/signalproxy.cpp b/src/common/signalproxy.cpp index 058e3cd8..d7d2c5c7 100644 --- a/src/common/signalproxy.cpp +++ b/src/common/signalproxy.cpp @@ -583,6 +583,8 @@ void SignalProxy::synchronize(SyncableObject *obj) { else requestInit(obj); } + + obj->synchronize(this); } 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 &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); @@ -1168,14 +1195,14 @@ const QList &SignalProxy::ExtendedMetaObject::argTypes(int 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]; } -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("="); @@ -1190,6 +1217,21 @@ const QByteArray &SignalProxy::ExtendedMetaObject::methodName(int 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 &SignalProxy::ExtendedMetaObject::syncMap() { if(_syncMap.isEmpty()) { QHash syncMap; diff --git a/src/common/signalproxy.h b/src/common/signalproxy.h index bac48db8..4cbaf220 100644 --- a/src/common/signalproxy.h +++ b/src/common/signalproxy.h @@ -118,6 +118,7 @@ public slots: protected: void customEvent(QEvent *event); + void syncCall(const SyncableObject *obj, ProxyMode modeType, const char *funcname, va_list ap); 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; + friend class SyncableObject; }; @@ -213,9 +215,10 @@ public: ExtendedMetaObject(const QMetaObject *meta); const QList &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); + int methodId(const QByteArray &methodName); const QHash &syncMap(); const QHash &receiveMap(); int updatedRemotelyId(); @@ -229,12 +232,14 @@ public: private: typedef QHash > ArgHash; typedef QHash MethodNameHash; + typedef QHash MethodIdHash; const QMetaObject *_meta; ArgHash _argTypes; QHash _returnType; QHash _minArgCount; MethodNameHash _methodNames; + MethodIdHash _methodIds; int _updatedRemotelyId; // id of the updatedRemotely() signal - makes things faster QHash _syncMap; QHash _receiveMap; diff --git a/src/common/syncableobject.cpp b/src/common/syncableobject.cpp index 526e47a1..aab2857c 100644 --- a/src/common/syncableobject.cpp +++ b/src/common/syncableobject.cpp @@ -58,6 +58,12 @@ SyncableObject &SyncableObject::operator=(const SyncableObject &other) { return *this; } +void SyncableObject::synchronize(SignalProxy *proxy) { + if(_signalProxies.contains(proxy)) + return; + _signalProxies << proxy; +} + bool SyncableObject::isInitialized() const { return _initialized; } @@ -155,3 +161,13 @@ void SyncableObject::requestUpdate(const QVariantMap &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); + } +} diff --git a/src/common/syncableobject.h b/src/common/syncableobject.h index fbcdbbcd..201c002c 100644 --- a/src/common/syncableobject.h +++ b/src/common/syncableobject.h @@ -26,6 +26,8 @@ #include #include +#include "signalproxy.h" + 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); + 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 @@ -65,6 +69,8 @@ public slots: 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); @@ -81,6 +87,12 @@ private: bool _initialized; bool _allowClientUpdates; + QList _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(reinterpret_cast(&x)) + + #endif