/***************************************************************************
- * 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 *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
+#include <utility>
+
#include <QCoreApplication>
#include <QHostAddress>
#include <QMetaMethod>
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);
QObject *sender;
int signalId;
QByteArray signature;
- Signal(QObject *sender, int sigId, const QByteArray &signature) : sender(sender), signalId(sigId), signature(signature) {}
- Signal() : sender(0), signalId(-1) {}
+ Signal(QObject *sender, int sigId, QByteArray signature) : sender(sender), signalId(sigId), signature(std::move(signature)) {}
+ Signal() : sender(nullptr), signalId(-1) {}
};
SignalProxy *_proxy;
}
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);
const QList<int> &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;
}
// ==================================================
// SignalProxy
// ==================================================
+
+namespace {
+thread_local SignalProxy *_current{nullptr};
+}
+
SignalProxy::SignalProxy(QObject *parent)
: QObject(parent)
{
_syncSlave.clear();
removeAllPeers();
+
+ _current = nullptr;
+}
+
+
+SignalProxy *SignalProxy::current()
+{
+ return _current;
}
initClient();
}
-thread_local SignalProxy *SignalProxy::_current;
-
-
void SignalProxy::init()
{
_heartBeatInterval = 0;
return;
}
- disconnect(peer, 0, this, 0);
- peer->setSignalProxy(0);
+ disconnect(peer, nullptr, this, nullptr);
+ peer->setSignalProxy(nullptr);
_peerMap.remove(peer->id());
emit peerRemoved(peer);
if (_extendedMetaObjects.contains(meta))
return _extendedMetaObjects[meta];
else
- return 0;
+ return nullptr;
}
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);
+ }
}
template<class T>
void SignalProxy::dispatch(const T &protoMessage)
{
- for (auto peer : _peerMap.values()) {
- _targetPeer = peer;
-
- if (peer->isOpen())
- peer->dispatch(protoMessage);
- else
- QCoreApplication::postEvent(this, new ::RemovePeerEvent(peer));
+ for (auto&& peer : _peerMap.values()) {
+ dispatch(peer, protoMessage);
}
- _targetPeer = nullptr;
}
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;
}
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();
data["remoteAddress"] = peer->address();
data["connectedSince"] = peer->connectedSince();
data["secure"] = peer->isSecure();
+ data["features"] = static_cast<quint32>(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<Peer*> peers, std::function<void()> closure)
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));
}
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;
}
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;
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;
_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"))