31 #include <QMetaMethod> 49 bool IsHookMethod (
const QMetaMethod& method)
51 return method.parameterTypes ().value (0) ==
"LeechCraft::IHookProxy_ptr";
54 auto BuildHookSlots (
const QObject *obj)
56 const auto objMo = obj->metaObject ();
58 QHash<QByteArray, QList<QMetaMethod>> hookSlots;
59 for (
int i = 0, size = objMo->methodCount (); i < size; ++i)
61 const auto& method = objMo->method (i);
62 if (IsHookMethod (method))
63 hookSlots [method.name ()] << method;
69 void CheckMatchingSigs (
const QObject *snd,
const QObject *rcv)
71 if (!qEnvironmentVariableIsSet (
"LC_VERBOSE_HOOK_CHECKS"))
74 const auto& hookSlots = BuildHookSlots (snd);
76 const auto rcvMo = rcv->metaObject ();
78 for (
int i = 0, size = rcvMo->methodCount (); i < size; ++i)
80 const auto& rcvMethod = rcvMo->method (i);
81 if (!IsHookMethod (rcvMethod))
84 const auto& rcvName = rcvMethod.name ();
85 if (!hookSlots.contains (rcvName))
87 qWarning () << Q_FUNC_INFO
88 <<
"no method matching method" 92 <<
") in sender object" 97 const auto& sndMethods = hookSlots [rcvName];
98 if (std::none_of (sndMethods.begin (), sndMethods.end (),
99 [&rcvMethod] (
const QMetaMethod& sndMethod)
101 return QMetaObject::checkConnectArgs (sndMethod, rcvMethod);
103 qWarning () << Q_FUNC_INFO
104 <<
"incompatible signatures for hook" 113 #define LC_N(a) (QMetaObject::normalizedSignature(a)) 114 #define LC_TOSLOT(a) ('1' + QByteArray(a)) 115 #define LC_TOSIGNAL(a) ('2' + QByteArray(a)) 116 void ConnectHookSignals (QObject *sender, QObject *receiver,
bool destSlot)
119 CheckMatchingSigs (sender, receiver);
121 const QMetaObject *mo = sender->metaObject ();
122 for (
int i = 0, size = mo->methodCount (); i < size; ++i)
124 QMetaMethod method = mo->method (i);
125 if (method.methodType () != QMetaMethod::Signal)
128 if (!IsHookMethod (method))
131 const auto& signature = method.methodSignature ();
132 if (receiver->metaObject ()->indexOfMethod (
LC_N (signature)) == -1)
136 qWarning () << Q_FUNC_INFO
137 <<
"not found meta method for" 139 <<
"in receiver object" 145 if (!QObject::connect (sender,
149 Qt::UniqueConnection))
151 qWarning () << Q_FUNC_INFO
169 ConnectHookSignals (
this, plugin,
true);
174 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.