X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=src%2Fcommon%2Fsignalproxy.cpp;h=f0711f16dfda7585be4192bc4651c8d35839e335;hp=db4a675835e733d4a616d14f6404c9ed2a391b1d;hb=e8a39b4c3c92e193ab861a3fea84a261bb6fbd24;hpb=28cee4568aeb1ce3014d11234e40f19e7aeae5bd diff --git a/src/common/signalproxy.cpp b/src/common/signalproxy.cpp index db4a6758..f0711f16 100644 --- a/src/common/signalproxy.cpp +++ b/src/common/signalproxy.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2005-2016 by the Quassel Project * + * Copyright (C) 2005-2018 by the Quassel Project * * devel@quassel-irc.org * * * * This program is free software; you can redistribute it and/or modify * @@ -59,7 +59,7 @@ public: SignalRelay(SignalProxy *parent) : QObject(parent), _proxy(parent) {} inline SignalProxy *proxy() const { return _proxy; } - int qt_metacall(QMetaObject::Call _c, int _id, void **_a); + int qt_metacall(QMetaObject::Call _c, int _id, void **_a) override; void attachSignal(QObject *sender, int signalId, const QByteArray &funcName); void detachSignal(QObject *sender, int signalId = -1); @@ -70,7 +70,7 @@ private: int signalId; QByteArray signature; Signal(QObject *sender, int sigId, const QByteArray &signature) : sender(sender), signalId(sigId), signature(signature) {} - Signal() : sender(0), signalId(-1) {} + Signal() : sender(nullptr), signalId(-1) {} }; SignalProxy *_proxy; @@ -96,11 +96,7 @@ void SignalProxy::SignalRelay::attachSignal(QObject *sender, int signalId, const } else { fn = SIGNAL(fakeMethodSignature()); -#if QT_VERSION >= 0x050000 fn = fn.replace("fakeMethodSignature()", sender->metaObject()->method(signalId).methodSignature()); -#else - fn = fn.replace("fakeMethodSignature()", sender->metaObject()->method(signalId).signature()); -#endif } _slots[slotId] = Signal(sender, signalId, fn); @@ -145,11 +141,7 @@ int SignalProxy::SignalRelay::qt_metacall(QMetaObject::Call _c, int _id, void ** const QList &argTypes = eMeta->argTypes(signal.signalId); for (int i = 0; i < argTypes.size(); i++) { if (argTypes[i] == 0) { -#if QT_VERSION >= 0x050000 qWarning() << "SignalRelay::qt_metacall(): received invalid data for argument number" << i << "of signal" << QString("%1::%2").arg(caller->metaObject()->className()).arg(caller->metaObject()->method(signal.signalId).methodSignature().constData()); -#else - qWarning() << "SignalRelay::qt_metacall(): received invalid data for argument number" << i << "of signal" << QString("%1::%2").arg(caller->metaObject()->className()).arg(caller->metaObject()->method(signal.signalId).signature()); -#endif qWarning() << " - make sure all your data types are known by the Qt MetaSystem"; return _id; } @@ -173,6 +165,11 @@ int SignalProxy::SignalRelay::qt_metacall(QMetaObject::Call _c, int _id, void ** // ================================================== // SignalProxy // ================================================== + +namespace { +thread_local SignalProxy *_current{nullptr}; +} + SignalProxy::SignalProxy(QObject *parent) : QObject(parent) { @@ -204,6 +201,14 @@ SignalProxy::~SignalProxy() _syncSlave.clear(); removeAllPeers(); + + _current = nullptr; +} + + +SignalProxy *SignalProxy::current() +{ + return _current; } @@ -221,7 +226,6 @@ void SignalProxy::setProxyMode(ProxyMode mode) initClient(); } - void SignalProxy::init() { _heartBeatInterval = 0; @@ -230,6 +234,7 @@ void SignalProxy::init() setHeartBeatInterval(30); setMaxHeartBeatCount(2); _secure = false; + _current = this; updateSecureState(); } @@ -335,8 +340,8 @@ void SignalProxy::removePeer(Peer *peer) return; } - disconnect(peer, 0, this, 0); - peer->setSignalProxy(0); + disconnect(peer, nullptr, this, nullptr); + peer->setSignalProxy(nullptr); _peerMap.remove(peer->id()); emit peerRemoved(peer); @@ -393,7 +398,7 @@ SignalProxy::ExtendedMetaObject *SignalProxy::extendedMetaObject(const QMetaObje if (_extendedMetaObjects.contains(meta)) return _extendedMetaObjects[meta]; else - return 0; + return nullptr; } @@ -470,8 +475,11 @@ void SignalProxy::synchronize(SyncableObject *obj) void SignalProxy::detachObject(QObject *obj) { - detachSignals(obj); - detachSlots(obj); + // Don't try to connect SignalProxy from itself on shutdown + if (obj != this) { + detachSignals(obj); + detachSlots(obj); + } } @@ -513,11 +521,8 @@ void SignalProxy::stopSynchronize(SyncableObject *obj) template void SignalProxy::dispatch(const T &protoMessage) { - for (auto peer : _peerMap.values()) { - if (peer->isOpen()) - peer->dispatch(protoMessage); - else - QCoreApplication::postEvent(this, new ::RemovePeerEvent(peer)); + for (auto&& peer : _peerMap.values()) { + dispatch(peer, protoMessage); } } @@ -525,10 +530,14 @@ void SignalProxy::dispatch(const T &protoMessage) template void SignalProxy::dispatch(Peer *peer, const T &protoMessage) { + _targetPeer = peer; + if (peer && peer->isOpen()) peer->dispatch(protoMessage); else QCoreApplication::postEvent(this, new ::RemovePeerEvent(peer)); + + _targetPeer = nullptr; } @@ -571,7 +580,9 @@ void SignalProxy::handle(Peer *peer, const SyncMessage &syncMessage) if (eMeta->argTypes(receiverId).count() > 1) returnParams << syncMessage.params; returnParams << returnValue; + _targetPeer = peer; peer->dispatch(SyncMessage(syncMessage.className, syncMessage.objectName, eMeta->methodName(receiverId), returnParams)); + _targetPeer = nullptr; } // send emit update signal @@ -594,7 +605,9 @@ void SignalProxy::handle(Peer *peer, const InitRequest &initRequest) } SyncableObject *obj = _syncSlave[initRequest.className][initRequest.objectName]; + _targetPeer = peer; peer->dispatch(InitData(initRequest.className, initRequest.objectName, initData(obj))); + _targetPeer = nullptr; } @@ -649,18 +662,14 @@ bool SignalProxy::invokeSlot(QObject *receiver, int methodId, const QVariantList 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 }; + void *_a[] = { nullptr, // return type... + nullptr, nullptr, nullptr, nullptr, nullptr, // and 10 args - that's the max size qt can handle with signals and slots + nullptr, nullptr, nullptr, nullptr, nullptr }; // check for argument compatibility and build params array for (int i = 0; i < numArgs; i++) { if (!params[i].isValid()) { -#if QT_VERSION >= 0x050000 qWarning() << "SignalProxy::invokeSlot(): received invalid data for argument number" << i << "of method" << QString("%1::%2()").arg(receiver->metaObject()->className()).arg(receiver->metaObject()->method(methodId).methodSignature().constData()); -#else - 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()); -#endif qWarning() << " - make sure all your data types are known by the Qt MetaSystem"; return false; } @@ -819,7 +828,7 @@ void SignalProxy::updateSecureState() QVariantList SignalProxy::peerData() { QVariantList result; - for (auto peer : _peerMap.values()) { + for (auto &&peer : _peerMap.values()) { QVariantMap data; data["id"] = peer->id(); data["clientVersion"] = peer->clientVersion(); @@ -829,13 +838,18 @@ QVariantList SignalProxy::peerData() { data["remoteAddress"] = peer->address(); data["connectedSince"] = peer->connectedSince(); data["secure"] = peer->isSecure(); + data["features"] = static_cast(peer->features().toLegacyFeatures()); + data["featureList"] = peer->features().toStringList(); result << data; } return result; } Peer *SignalProxy::peerById(int peerId) { - return _peerMap[peerId]; + // We use ::value() here instead of the [] operator because the latter has the side-effect + // of automatically inserting a null value with the passed key into the map. See + // https://doc.qt.io/qt-5/qhash.html#operator-5b-5d and https://doc.qt.io/qt-5/qhash.html#value. + return _peerMap.value(peerId); } void SignalProxy::restrictTargetPeers(QSet peers, std::function closure) @@ -851,6 +865,22 @@ void SignalProxy::restrictTargetPeers(QSet peers, std::function c _restrictedTargets = previousRestrictedTargets; } +Peer *SignalProxy::sourcePeer() { + return _sourcePeer; +} + +void SignalProxy::setSourcePeer(Peer *sourcePeer) { + _sourcePeer = sourcePeer; +} + +Peer *SignalProxy::targetPeer() { + return _targetPeer; +} + +void SignalProxy::setTargetPeer(Peer *targetPeer) { + _targetPeer = targetPeer; +} + // ================================================== // ExtendedMetaObject // ================================================== @@ -862,11 +892,7 @@ SignalProxy::ExtendedMetaObject::ExtendedMetaObject(const QMetaObject *meta, boo if (_meta->method(i).methodType() != QMetaMethod::Slot) continue; -#if QT_VERSION >= 0x050000 if (_meta->method(i).methodSignature().contains('*')) -#else - if (QByteArray(_meta->method(i).signature()).contains('*')) -#endif continue; // skip methods with ptr params QByteArray method = methodName(_meta->method(i)); @@ -895,11 +921,7 @@ SignalProxy::ExtendedMetaObject::ExtendedMetaObject(const QMetaObject *meta, boo } if (checkConflicts) { qWarning() << "class" << meta->className() << "contains overloaded methods which is currently not supported!"; -#if QT_VERSION >= 0x050000 qWarning() << " - " << _meta->method(i).methodSignature() << "conflicts with" << _meta->method(_methodIds[method]).methodSignature(); -#else - qWarning() << " - " << _meta->method(i).signature() << "conflicts with" << _meta->method(_methodIds[method]).signature(); -#endif } continue; } @@ -939,11 +961,7 @@ const QHash &SignalProxy::ExtendedMetaObject::receiveMap() if (QMetaType::Void == (QMetaType::Type)returnType(i)) continue; -#if QT_VERSION >= 0x050000 signature = requestSlot.methodSignature(); -#else - signature = QByteArray(requestSlot.signature()); -#endif if (!signature.startsWith("request")) continue; @@ -977,22 +995,14 @@ const QHash &SignalProxy::ExtendedMetaObject::receiveMap() QByteArray SignalProxy::ExtendedMetaObject::methodName(const QMetaMethod &method) { -#if QT_VERSION >= 0x050000 QByteArray sig(method.methodSignature()); -#else - QByteArray sig(method.signature()); -#endif return sig.left(sig.indexOf("(")); } QString SignalProxy::ExtendedMetaObject::methodBaseName(const QMetaMethod &method) { -#if QT_VERSION >= 0x050000 QString methodname = QString(method.methodSignature()).section("(", 0, 0); -#else - QString methodname = QString(method.signature()).section("(", 0, 0); -#endif // determine where we have to chop: int upperCharPos; @@ -1030,11 +1040,7 @@ SignalProxy::ExtendedMetaObject::MethodDescriptor::MethodDescriptor(const QMetaM _argTypes = argTypes; // determine minArgCount -#if QT_VERSION >= 0x050000 QString signature(method.methodSignature()); -#else - QString signature(method.signature()); -#endif _minArgCount = method.parameterTypes().count() - signature.count("="); _receiverMode = (_methodName.startsWith("request"))