10 #include <QMetaMethod>
22 BaseHookInterconnector::~BaseHookInterconnector ()
28 bool IsHookMethod (
const QMetaMethod& method)
30 return method.parameterTypes ().value (0) ==
"LC::IHookProxy_ptr";
33 auto BuildHookSlots (
const QObject *obj)
35 const auto objMo = obj->metaObject ();
37 QHash<QByteArray, QList<QMetaMethod>> hookSlots;
38 for (
int i = 0, size = objMo->methodCount (); i < size; ++i)
40 const auto& method = objMo->method (i);
41 if (IsHookMethod (method))
42 hookSlots [method.name ()] << method;
48 bool ShouldBeVerbose ()
50 static bool result = qEnvironmentVariableIsSet (
"LC_VERBOSE_HOOK_CHECKS");
54 void CheckMatchingSigs (
const QObject *snd,
const QObject *rcv)
56 if (!ShouldBeVerbose ())
59 const auto& hookSlots = BuildHookSlots (snd);
61 const auto rcvMo = rcv->metaObject ();
63 for (
int i = 0, size = rcvMo->methodCount (); i < size; ++i)
65 const auto& rcvMethod = rcvMo->method (i);
66 if (!IsHookMethod (rcvMethod))
69 const auto& rcvName = rcvMethod.name ();
70 if (!hookSlots.contains (rcvName))
72 qWarning () << Q_FUNC_INFO
73 <<
"no method matching method"
77 <<
") in sender object"
82 const auto& sndMethods = hookSlots [rcvName];
83 if (std::none_of (sndMethods.begin (), sndMethods.end (),
84 [&rcvMethod] (
const QMetaMethod& sndMethod)
86 return QMetaObject::checkConnectArgs (sndMethod, rcvMethod);
88 qWarning () << Q_FUNC_INFO
89 <<
"incompatible signatures for hook"
98 #define LC_N(a) (QMetaObject::normalizedSignature(a))
99 #define LC_TOSLOT(a) ('1' + QByteArray(a))
100 #define LC_TOSIGNAL(a) ('2' + QByteArray(a))
101 void ConnectHookSignals (QObject *sender, QObject *receiver,
bool destSlot)
104 CheckMatchingSigs (sender, receiver);
106 const QMetaObject *mo = sender->metaObject ();
107 for (
int i = 0, size = mo->methodCount (); i < size; ++i)
109 QMetaMethod method = mo->method (i);
110 if (method.methodType () != QMetaMethod::Signal)
113 if (!IsHookMethod (method))
116 const auto& signature = method.methodSignature ();
117 if (receiver->metaObject ()->indexOfMethod (
LC_N (signature)) == -1)
121 qWarning () << Q_FUNC_INFO
122 <<
"not found meta method for"
124 <<
"in receiver object"
130 if (!QObject::connect (sender,
134 Qt::UniqueConnection))
135 qWarning () << Q_FUNC_INFO
143 else if (ShouldBeVerbose ())
144 qDebug () << Q_FUNC_INFO
158 void BaseHookInterconnector::AddPlugin (QObject *plugin)
160 Plugins_.push_back (plugin);
162 ConnectHookSignals (
this, plugin,
true);
165 void BaseHookInterconnector::RegisterHookable (QObject *
object)
167 ConnectHookSignals (
object,
this,
false);