-// ==================================================
-// SignalRelay
-// ==================================================
-class SignalProxy::SignalRelay : public QObject
-{
- /* Q_OBJECT is not necessary or even allowed, because we implement
- qt_metacall ourselves (and don't use any other features of the meta
- object system)
- */
-public:
- SignalRelay(SignalProxy* parent)
- : QObject(parent)
- , _proxy(parent)
- {}
- inline SignalProxy* proxy() const { return _proxy; }
-
- 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{nullptr};
- int signalId{-1};
- QByteArray signature;
- Signal(QObject* sender, int sigId, QByteArray signature)
- : sender(sender)
- , signalId(sigId)
- , signature(std::move(signature))
- {}
- Signal() = default;
- };
-
- SignalProxy* _proxy;
- QHash<int, Signal> _slots;
-};
-
-void SignalProxy::SignalRelay::attachSignal(QObject* sender, int signalId, const QByteArray& funcName)
-{
- // we ride without safetybelts here... all checking for valid method etc pp has to be done by the caller
- // all connected methodIds are offset by the standard methodCount of QObject
- int slotId;
- for (int i = 0;; i++) {
- if (!_slots.contains(i)) {
- slotId = i;
- break;
- }
- }
-
- QByteArray fn;
- if (!funcName.isEmpty()) {
- fn = QMetaObject::normalizedSignature(funcName);
- }
- else {
- fn = SIGNAL(fakeMethodSignature());
- fn = fn.replace("fakeMethodSignature()", sender->metaObject()->method(signalId).methodSignature());
- }
-
- _slots[slotId] = Signal(sender, signalId, fn);
-
- QMetaObject::connect(sender, signalId, this, QObject::staticMetaObject.methodCount() + slotId);
-}
-
-void SignalProxy::SignalRelay::detachSignal(QObject* sender, int signalId)
-{
- QHash<int, Signal>::iterator slotIter = _slots.begin();
- while (slotIter != _slots.end()) {
- if (slotIter->sender == sender && (signalId == -1 || slotIter->signalId == signalId)) {
- slotIter = _slots.erase(slotIter);
- if (signalId != -1)
- break;
- }
- else {
- ++slotIter;
- }
- }
-}
-
-int SignalProxy::SignalRelay::qt_metacall(QMetaObject::Call _c, int _id, void** _a)
-{
- _id = QObject::qt_metacall(_c, _id, _a);
- if (_id < 0)
- return _id;
-
- if (_c == QMetaObject::InvokeMetaMethod) {
- if (_slots.contains(_id)) {
- QObject* caller = sender();
-
- SignalProxy::ExtendedMetaObject* eMeta = proxy()->extendedMetaObject(caller->metaObject());
- Q_ASSERT(eMeta);
-
- const Signal& signal = _slots[_id];
-
- QVariantList params;
-
- const QList<int>& argTypes = eMeta->argTypes(signal.signalId);
- for (int i = 0; i < argTypes.size(); i++) {
- if (argTypes[i] == 0) {
- 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());
- qWarning() << " - make sure all your data types are known by the Qt MetaSystem";
- return _id;
- }
- params << QVariant(argTypes[i], _a[i + 1]);
- }
-
- if (proxy()->_restrictMessageTarget) {
- for (auto peer : proxy()->_restrictedTargets) {
- if (peer != nullptr)
- proxy()->dispatch(peer, RpcCall(signal.signature, params));
- }
- }
- else
- proxy()->dispatch(RpcCall(signal.signature, params));
- }
- _id -= _slots.count();
- }
- return _id;
-}
-