+void SignalProxy::detachSignals(QObject *sender)
+{
+ _signalRelay->detachSignal(sender);
+}
+
+
+void SignalProxy::detachSlots(QObject *receiver)
+{
+ SlotHash::iterator slotIter = _attachedSlots.begin();
+ while (slotIter != _attachedSlots.end()) {
+ if (slotIter.value().first == receiver) {
+ slotIter = _attachedSlots.erase(slotIter);
+ }
+ else
+ slotIter++;
+ }
+}
+
+
+void SignalProxy::stopSynchronize(SyncableObject *obj)
+{
+ // we can't use a className here, since it might be effed up, if we receive the call as a result of a decon
+ // gladly the objectName() is still valid. So we have only to iterate over the classes not each instance! *sigh*
+ QHash<QByteArray, ObjectId>::iterator classIter = _syncSlave.begin();
+ while (classIter != _syncSlave.end()) {
+ if (classIter->contains(obj->objectName()) && classIter.value()[obj->objectName()] == obj) {
+ classIter->remove(obj->objectName());
+ break;
+ }
+ classIter++;
+ }
+ obj->stopSynchronize(this);
+}
+
+
+template<class T>
+void SignalProxy::dispatch(const T &protoMessage)
+{
+ foreach (Peer *peer, _peers) {
+ if (peer->isOpen())
+ peer->dispatch(protoMessage);
+ else
+ QCoreApplication::postEvent(this, new ::RemovePeerEvent(peer));
+ }
+}
+
+
+void SignalProxy::handle(Peer *peer, const SyncMessage &syncMessage)
+{
+ if (!_syncSlave.contains(syncMessage.className()) || !_syncSlave[syncMessage.className()].contains(syncMessage.objectName())) {
+ qWarning() << QString("no registered receiver for sync call: %1::%2 (objectName=\"%3\"). Params are:").arg(syncMessage.className(), syncMessage.slotName(), syncMessage.objectName())
+ << syncMessage.params();
+ return;
+ }
+
+ SyncableObject *receiver = _syncSlave[syncMessage.className()][syncMessage.objectName()];
+ ExtendedMetaObject *eMeta = extendedMetaObject(receiver);
+ if (!eMeta->slotMap().contains(syncMessage.slotName())) {
+ qWarning() << QString("no matching slot for sync call: %1::%2 (objectName=\"%3\"). Params are:").arg(syncMessage.className(), syncMessage.slotName(), syncMessage.objectName())
+ << syncMessage.params();
+ return;
+ }
+
+ int slotId = eMeta->slotMap()[syncMessage.slotName()];
+ if (proxyMode() != eMeta->receiverMode(slotId)) {
+ qWarning("SignalProxy::handleSync(): invokeMethod for \"%s\" failed. Wrong ProxyMode!", eMeta->methodName(slotId).constData());
+ return;
+ }
+
+ QVariant returnValue((QVariant::Type)eMeta->returnType(slotId));
+ if (!invokeSlot(receiver, slotId, syncMessage.params(), returnValue)) {
+ qWarning("SignalProxy::handleSync(): invokeMethod for \"%s\" failed ", eMeta->methodName(slotId).constData());
+ return;
+ }
+
+ if (returnValue.type() != QVariant::Invalid && eMeta->receiveMap().contains(slotId)) {
+ int receiverId = eMeta->receiveMap()[slotId];
+ QVariantList returnParams;
+ if (eMeta->argTypes(receiverId).count() > 1)
+ returnParams << syncMessage.params();
+ returnParams << returnValue;
+ peer->dispatch(SyncMessage(syncMessage.className(), syncMessage.objectName(), eMeta->methodName(receiverId), returnParams));
+ }
+
+ // send emit update signal
+ invokeSlot(receiver, eMeta->updatedRemotelyId());
+}
+
+
+void SignalProxy::handle(Peer *peer, const InitRequest &initRequest)
+{
+ if (!_syncSlave.contains(initRequest.className())) {
+ qWarning() << "SignalProxy::handleInitRequest() received initRequest for unregistered Class:"
+ << initRequest.className();
+ return;
+ }
+
+ if (!_syncSlave[initRequest.className()].contains(initRequest.objectName())) {
+ qWarning() << "SignalProxy::handleInitRequest() received initRequest for unregistered Object:"
+ << initRequest.className() << initRequest.objectName();
+ return;
+ }
+
+ SyncableObject *obj = _syncSlave[initRequest.className()][initRequest.objectName()];
+ peer->dispatch(InitData(initRequest.className(), initRequest.objectName(), initData(obj)));
+}
+
+
+void SignalProxy::handle(Peer *peer, const InitData &initData)
+{
+ Q_UNUSED(peer)
+
+ if (!_syncSlave.contains(initData.className())) {
+ qWarning() << "SignalProxy::handleInitData() received initData for unregistered Class:"
+ << initData.className();
+ return;
+ }
+
+ if (!_syncSlave[initData.className()].contains(initData.objectName())) {
+ qWarning() << "SignalProxy::handleInitData() received initData for unregistered Object:"
+ << initData.className() << initData.objectName();
+ return;
+ }
+
+ SyncableObject *obj = _syncSlave[initData.className()][initData.objectName()];
+ setInitData(obj, initData.initData());
+}
+
+
+void SignalProxy::handle(Peer *peer, const RpcCall &rpcCall)
+{
+ Q_UNUSED(peer)
+
+ QObject *receiver;
+ int methodId;
+ SlotHash::const_iterator slot = _attachedSlots.constFind(rpcCall.slotName());
+ while (slot != _attachedSlots.constEnd() && slot.key() == rpcCall.slotName()) {
+ receiver = (*slot).first;
+ methodId = (*slot).second;
+ if (!invokeSlot(receiver, methodId, rpcCall.params())) {
+ ExtendedMetaObject *eMeta = extendedMetaObject(receiver);
+ qWarning("SignalProxy::handleSignal(): invokeMethod for \"%s\" failed ", eMeta->methodName(methodId).constData());
+ }
+ ++slot;
+ }
+}
+
+
+bool SignalProxy::invokeSlot(QObject *receiver, int methodId, const QVariantList ¶ms, QVariant &returnValue)
+{
+ ExtendedMetaObject *eMeta = extendedMetaObject(receiver);
+ const QList<int> args = eMeta->argTypes(methodId);
+ const int numArgs = params.count() < args.count()
+ ? params.count()
+ : args.count();
+
+ if (eMeta->minArgCount(methodId) > params.count()) {
+ qWarning() << "SignalProxy::invokeSlot(): not enough params to invoke" << eMeta->methodName(methodId);
+ return false;
+ }
+
+ void *_a[] = { 0, // return type...
+ 0, 0, 0, 0, 0, // and 10 args - that's the max size qt can handle with signals and slots
+ 0, 0, 0, 0, 0 };
+
+ // check for argument compatibility and build params array
+ for (int i = 0; i < numArgs; i++) {
+ if (!params[i].isValid()) {
+ qWarning() << "SignalProxy::invokeSlot(): received invalid data for argument number" << i << "of method" << QString("%1::%2()").arg(receiver->metaObject()->className()).arg(receiver->metaObject()->method(methodId).signature());
+ qWarning() << " - make sure all your data types are known by the Qt MetaSystem";
+ return false;
+ }
+ if (args[i] != QMetaType::type(params[i].typeName())) {
+ qWarning() << "SignalProxy::invokeSlot(): incompatible param types to invoke" << eMeta->methodName(methodId);
+ return false;
+ }
+ _a[i+1] = const_cast<void *>(params[i].constData());
+ }
+
+ if (returnValue.type() != QVariant::Invalid)
+ _a[0] = const_cast<void *>(returnValue.constData());