+void SignalProxy::updateSecureState() {
+ bool wasSecure = _secure;
+
+ _secure = !_peers.isEmpty();
+ PeerHash::const_iterator peerIter;
+ for(peerIter = _peers.constBegin(); peerIter != _peers.constEnd(); peerIter++) {
+ _secure &= (*peerIter)->isSecure();
+ }
+
+ if(wasSecure != _secure)
+ emit secureStateChanged(_secure);
+}
+
+
+// ==================================================
+// ExtendedMetaObject
+// ==================================================
+SignalProxy::ExtendedMetaObject::ExtendedMetaObject(const QMetaObject *meta)
+ : _meta(meta),
+ _updatedRemotelyId(-1)
+{
+}
+
+const QList<int> &SignalProxy::ExtendedMetaObject::argTypes(int methodId) {
+ if(!_argTypes.contains(methodId)) {
+ QList<QByteArray> paramTypes = _meta->method(methodId).parameterTypes();
+ QList<int> argTypes;
+ for(int i = 0; i < paramTypes.count(); i++) {
+ argTypes.append(QMetaType::type(paramTypes[i]));
+ }
+ _argTypes[methodId] = argTypes;
+ }
+ return _argTypes[methodId];
+}
+
+const 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) {
+ if(!_minArgCount.contains(methodId)) {
+ QString signature(_meta->method(methodId).signature());
+ _minArgCount[methodId] = _meta->method(methodId).parameterTypes().count() - signature.count("=");
+ }
+ return _minArgCount[methodId];
+}
+
+const QByteArray &SignalProxy::ExtendedMetaObject::methodName(int methodId) {
+ if(!_methodNames.contains(methodId)) {
+ _methodNames[methodId] = methodName(_meta->method(methodId));
+ }
+ return _methodNames[methodId];
+}
+
+const QHash<QByteArray, int> &SignalProxy::ExtendedMetaObject::syncMap() {
+ if(_syncMap.isEmpty()) {
+ QHash<QByteArray, int> syncMap;
+
+ QList<int> slotIndexes;
+ for(int i = 0; i < _meta->methodCount(); i++) {
+ if(_meta->method(i).methodType() == QMetaMethod::Slot)
+ slotIndexes << i;
+ }
+
+ // we're faking sync pairs for sync replies
+ // --> we deliver to every slot starting with "receive"
+ QByteArray slotSignature;
+ QList<int>::iterator slotIter = slotIndexes.begin();
+ while(slotIter != slotIndexes.end()) {
+ slotSignature = QByteArray(_meta->method(*slotIter).signature());
+ if(slotSignature.startsWith("receive")) {
+ syncMap[slotSignature] = *slotIter;
+ slotIter = slotIndexes.erase(slotIter);
+ } else {
+ slotIter++;
+ }
+ }
+
+ // find the proper sig -> slot matches
+ QMetaMethod signal, slot;
+ int matchIdx;
+ for(int signalIdx = 0; signalIdx < _meta->methodCount(); signalIdx++) {
+ signal = _meta->method(signalIdx);
+ if(signal.methodType() != QMetaMethod::Signal)
+ continue;
+
+ matchIdx = -1;
+ foreach(int slotIdx, slotIndexes) {
+ slot = _meta->method(slotIdx);
+ if(methodsMatch(signal, slot)) {
+ matchIdx = slotIdx;
+ break;
+ }
+ }
+ if(matchIdx != -1) {
+ slotIndexes.removeAll(matchIdx);
+ syncMap[QByteArray(signal.signature())] = matchIdx;
+ }
+ }
+ _syncMap = syncMap;
+ }
+ return _syncMap;
+}
+
+const QHash<int, int> &SignalProxy::ExtendedMetaObject::receiveMap() {
+ if(_receiveMap.isEmpty()) {
+ QHash<int, int> receiveMap;
+
+ QMetaMethod requestSlot;
+ QByteArray returnTypeName;
+ QByteArray signature;
+ QByteArray methodName;
+ QByteArray params;
+ int paramsPos;
+ int receiverId;
+ const int methodCount = _meta->methodCount();
+ for(int i = 0; i < methodCount; i++) {
+ requestSlot = _meta->method(i);
+ if(requestSlot.methodType() != QMetaMethod::Slot)
+ continue;
+
+ returnTypeName = requestSlot.typeName();
+ if(QMetaType::Void == (QMetaType::Type)returnType(i))
+ continue;
+
+ signature = QByteArray(requestSlot.signature());
+ if(!signature.startsWith("request"))
+ continue;
+
+ paramsPos = signature.indexOf('(');
+ if(paramsPos == -1)
+ continue;
+
+ methodName = signature.left(paramsPos);
+ params = signature.mid(paramsPos);
+
+ methodName = methodName.replace("request", "receive");
+ params = params.left(params.count() - 1) + ", " + returnTypeName + ")";
+
+ signature = QMetaObject::normalizedSignature(methodName + params);
+ receiverId = _meta->indexOfSlot(signature);
+
+ if(receiverId == -1) {
+ signature = QMetaObject::normalizedSignature(methodName + "(" + returnTypeName + ")");
+ receiverId = _meta->indexOfSlot(signature);
+ }
+
+ if(receiverId != -1)
+ receiveMap[i] = receiverId;
+ }
+ _receiveMap = receiveMap;
+ }
+ return _receiveMap;
+}
+
+int SignalProxy::ExtendedMetaObject::updatedRemotelyId() {
+ if(_updatedRemotelyId == -1) {
+ _updatedRemotelyId = _meta->indexOfSignal("updatedRemotely()");
+ }
+ return _updatedRemotelyId;
+}
+
+QByteArray SignalProxy::ExtendedMetaObject::methodName(const QMetaMethod &method) {
+ QByteArray sig(method.signature());
+ return sig.left(sig.indexOf("("));
+}
+
+bool SignalProxy::ExtendedMetaObject::methodsMatch(const QMetaMethod &signal, const QMetaMethod &slot) {
+ // if we don't even have the same basename it's a sure NO
+ QString baseName = methodBaseName(signal);
+ if(baseName != methodBaseName(slot))
+ return false;
+
+ // are the signatures compatible?
+ if(!QObject::staticMetaObject.checkConnectArgs(signal.signature(), slot.signature()))
+ return false;
+
+ // we take an educated guess if the signals and slots match
+ QString signalsuffix = methodName(signal);
+ QString slotprefix = methodName(slot);
+ if(!baseName.isEmpty()) {
+ signalsuffix = signalsuffix.mid(baseName.count()).toLower();
+ slotprefix = slotprefix.left(slotprefix.count() - baseName.count()).toLower();
+ }
+
+ uint sizediff = qAbs(slotprefix.size() - signalsuffix.size());
+ int ratio = editingDistance(slotprefix, signalsuffix) - sizediff;
+ return (ratio < 2);
+}
+
+QString SignalProxy::ExtendedMetaObject::methodBaseName(const QMetaMethod &method) {
+ QString methodname = QString(method.signature()).section("(", 0, 0);
+
+ // determine where we have to chop:
+ int upperCharPos;
+ if(method.methodType() == QMetaMethod::Slot) {
+ // we take evertyhing from the first uppercase char if it's slot
+ upperCharPos = methodname.indexOf(QRegExp("[A-Z]"));
+ if(upperCharPos == -1)
+ return QString();
+ methodname = methodname.mid(upperCharPos);
+ } else {
+ // and if it's a signal we discard everything from the last uppercase char
+ upperCharPos = methodname.lastIndexOf(QRegExp("[A-Z]"));
+ if(upperCharPos == -1)
+ return QString();
+ methodname = methodname.left(upperCharPos);
+ }
+
+ methodname[0] = methodname[0].toUpper();
+
+ return methodname;
+}