31 #include <QMetaMethod>
49 bool IsHookMethod (
const QMetaMethod& method)
51 return method.parameterTypes ().value (0) ==
"LeechCraft::IHookProxy_ptr";
54 #if QT_VERSION >= 0x050000
55 auto BuildHookSlots (
const QObject *obj)
57 const auto objMo = obj->metaObject ();
59 QHash<QByteArray, QList<QMetaMethod>> hookSlots;
60 for (
int i = 0, size = objMo->methodCount (); i < size; ++i)
62 const auto& method = objMo->method (i);
63 if (IsHookMethod (method))
64 hookSlots [method.name ()] << method;
71 void CheckMatchingSigs (
const QObject *snd,
const QObject *rcv)
73 #if QT_VERSION >= 0x050000
74 if (!qEnvironmentVariableIsSet (
"LC_VERBOSE_HOOK_CHECKS"))
77 const auto& hookSlots = BuildHookSlots (snd);
79 const auto rcvMo = rcv->metaObject ();
81 for (
int i = 0, size = rcvMo->methodCount (); i < size; ++i)
83 const auto& rcvMethod = rcvMo->method (i);
84 if (!IsHookMethod (rcvMethod))
87 const auto& rcvName = rcvMethod.name ();
88 if (!hookSlots.contains (rcvName))
90 qWarning () << Q_FUNC_INFO
91 <<
"no method matching method"
95 <<
") in sender object"
100 const auto& sndMethods = hookSlots [rcvName];
101 if (std::none_of (sndMethods.begin (), sndMethods.end (),
102 [&rcvMethod] (
const QMetaMethod& sndMethod)
104 return QMetaObject::checkConnectArgs (sndMethod, rcvMethod);
106 qWarning () << Q_FUNC_INFO
107 <<
"incompatible signatures for hook"
120 #define LC_N(a) (QMetaObject::normalizedSignature(a))
121 #define LC_TOSLOT(a) ('1' + QByteArray(a))
122 #define LC_TOSIGNAL(a) ('2' + QByteArray(a))
123 void ConnectHookSignals (QObject *sender, QObject *receiver,
bool destSlot)
126 CheckMatchingSigs (sender, receiver);
128 const QMetaObject *mo = sender->metaObject ();
129 for (
int i = 0, size = mo->methodCount (); i < size; ++i)
131 QMetaMethod method = mo->method (i);
132 if (method.methodType () != QMetaMethod::Signal)
135 if (!IsHookMethod (method))
138 #if QT_VERSION >= 0x050000
139 const auto& signature = method.methodSignature ();
141 const auto& signature = method.signature ();
144 if (receiver->metaObject ()->indexOfMethod (
LC_N (signature)) == -1)
148 qWarning () << Q_FUNC_INFO
149 <<
"not found meta method for"
151 <<
"in receiver object"
157 if (!QObject::connect (sender,
161 Qt::UniqueConnection))
163 qWarning () << Q_FUNC_INFO
181 ConnectHookSignals (
this, plugin,
true);
186 ConnectHookSignals (
object,
this,
false);
BaseHookInterconnector(QObject *parent=0)
Creates the interconnector with the given parent.
virtual ~BaseHookInterconnector()
Virtual destructor.
void RegisterHookable(QObject *hookable)
Adds a hookable object from the root plugin.
QList< QObject * > Plugins_
virtual void AddPlugin(QObject *plugin)
Adds a subplugin to this interconnector.