/***************************************************************************
- * 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);
private:
struct Signal {
- QObject *sender;
- int signalId;
+ QObject *sender{nullptr};
+ int signalId{-1};
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() = default;
};
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;
qWarning("SignalProxy: only one peer allowed in client mode!");
return false;
}
- connect(peer, SIGNAL(lagUpdated(int)), SIGNAL(lagUpdated(int)));
+ connect(peer, &Peer::lagUpdated, this, &SignalProxy::lagUpdated);
}
- connect(peer, SIGNAL(disconnected()), SLOT(removePeerBySender()));
- connect(peer, SIGNAL(secureStateChanged(bool)), SLOT(updateSecureState()));
+ connect(peer, &Peer::disconnected, this, &SignalProxy::removePeerBySender);
+ connect(peer, &Peer::secureStateChanged, this, &SignalProxy::updateSecureState);
if (!peer->parent())
peer->setParent(this);
return;
}
- disconnect(peer, 0, this, 0);
- peer->setSignalProxy(0);
+ disconnect(peer, nullptr, this, nullptr);
+ peer->setSignalProxy(nullptr);
_peerMap.remove(peer->id());
emit peerRemoved(peer);
const QMetaObject *SignalProxy::metaObject(const QObject *obj)
{
- if (const SyncableObject *syncObject = qobject_cast<const SyncableObject *>(obj))
+ if (const auto *syncObject = qobject_cast<const SyncableObject *>(obj))
return syncObject->syncMetaObject();
else
return obj->metaObject();
if (_extendedMetaObjects.contains(meta))
return _extendedMetaObjects[meta];
else
- return 0;
+ return nullptr;
}
createExtendedMetaObject(meta);
_signalRelay->attachSignal(sender, methodId, sigName);
- disconnect(sender, SIGNAL(destroyed(QObject *)), this, SLOT(detachObject(QObject *)));
- connect(sender, SIGNAL(destroyed(QObject *)), this, SLOT(detachObject(QObject *)));
+ disconnect(sender, &QObject::destroyed, this, &SignalProxy::detachObject);
+ connect(sender, &QObject::destroyed, this, &SignalProxy::detachObject);
return true;
}
QByteArray funcName = QMetaObject::normalizedSignature(sigName.constData());
_attachedSlots.insert(funcName, qMakePair(recv, methodId));
- disconnect(recv, SIGNAL(destroyed(QObject *)), this, SLOT(detachObject(QObject *)));
- connect(recv, SIGNAL(destroyed(QObject *)), this, SLOT(detachObject(QObject *)));
+ disconnect(recv, &QObject::destroyed, this, &SignalProxy::detachObject);
+ connect(recv, &QObject::destroyed, this, &SignalProxy::detachObject);
return true;
}
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;
}
{
switch ((int)event->type()) {
case RemovePeerEvent: {
- ::RemovePeerEvent *e = static_cast< ::RemovePeerEvent *>(event);
+ auto *e = static_cast< ::RemovePeerEvent *>(event);
removePeer(e->peer);
event->accept();
break;
{
if (!reason.isEmpty())
qWarning() << qPrintable(reason);
- QAbstractSocket *sock = qobject_cast<QAbstractSocket *>(dev);
+ auto *sock = qobject_cast<QAbstractSocket *>(dev);
if (sock)
qWarning() << qPrintable(tr("Disconnecting")) << qPrintable(sock->peerAddress().toString());
dev->close();
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"))