LeechCraft 0.6.70-17335-ge406ffdcaf
Modular cross-platform feature rich live environment.
Loading...
Searching...
No Matches
basehookinterconnector.cpp
Go to the documentation of this file.
1/**********************************************************************
2 * LeechCraft - modular cross-platform feature rich internet client.
3 * Copyright (C) 2006-2014 Georg Rudoy
4 *
5 * Distributed under the Boost Software License, Version 1.0.
6 * (See accompanying file LICENSE or copy at https://www.boost.org/LICENSE_1_0.txt)
7 **********************************************************************/
8
10#include <QMetaMethod>
11#include <QtDebug>
12
13namespace LC
14{
15namespace Util
16{
18 : QObject (parent)
19 {
20 }
21
25
26 namespace
27 {
28 bool IsHookMethod (const QMetaMethod& method)
29 {
30 return method.parameterTypes ().value (0) == "LC::IHookProxy_ptr";
31 }
32
33 auto BuildHookSlots (const QObject *obj)
34 {
35 const auto objMo = obj->metaObject ();
36
37 QHash<QByteArray, QList<QMetaMethod>> hookSlots;
38 for (int i = 0, size = objMo->methodCount (); i < size; ++i)
39 {
40 const auto& method = objMo->method (i);
41 if (IsHookMethod (method))
42 hookSlots [method.name ()] << method;
43 }
44
45 return hookSlots;
46 }
47
48 bool ShouldBeVerbose ()
49 {
50 static bool result = qEnvironmentVariableIsSet ("LC_VERBOSE_HOOK_CHECKS");
51 return result;
52 }
53
54 void CheckMatchingSigs (const QObject *snd, const QObject *rcv)
55 {
56 if (!ShouldBeVerbose ())
57 return;
58
59 const auto& hookSlots = BuildHookSlots (snd);
60
61 const auto rcvMo = rcv->metaObject ();
62
63 for (int i = 0, size = rcvMo->methodCount (); i < size; ++i)
64 {
65 const auto& rcvMethod = rcvMo->method (i);
66 if (!IsHookMethod (rcvMethod))
67 continue;
68
69 const auto& rcvName = rcvMethod.name ();
70 if (!hookSlots.contains (rcvName))
71 {
72 qWarning () << Q_FUNC_INFO
73 << "no method matching method"
74 << rcvName
75 << "(receiver"
76 << rcv
77 << ") in sender object"
78 << snd;
79 continue;
80 }
81
82 const auto& sndMethods = hookSlots [rcvName];
83 if (std::none_of (sndMethods.begin (), sndMethods.end (),
84 [&rcvMethod] (const QMetaMethod& sndMethod)
85 {
86 return QMetaObject::checkConnectArgs (sndMethod, rcvMethod);
87 }))
88 qWarning () << Q_FUNC_INFO
89 << "incompatible signatures for hook"
90 << rcvName
91 << "in"
92 << snd
93 << "and"
94 << rcv;
95 }
96 }
97
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)
102 {
103 if (destSlot)
104 CheckMatchingSigs (sender, receiver);
105
106 const QMetaObject *mo = sender->metaObject ();
107 for (int i = 0, size = mo->methodCount (); i < size; ++i)
108 {
109 QMetaMethod method = mo->method (i);
110 if (method.methodType () != QMetaMethod::Signal)
111 continue;
112
113 if (!IsHookMethod (method))
114 continue;
115
116 const auto& signature = method.methodSignature ();
117 if (receiver->metaObject ()->indexOfMethod (LC_N (signature)) == -1)
118 {
119 if (!destSlot)
120 {
121 qWarning () << Q_FUNC_INFO
122 << "not found meta method for"
123 << signature
124 << "in receiver object"
125 << receiver;
126 }
127 continue;
128 }
129
130 if (!QObject::connect (sender,
131 LC_TOSIGNAL (signature),
132 receiver,
133 destSlot ? LC_TOSLOT (signature) : LC_TOSIGNAL (signature),
134 Qt::UniqueConnection))
135 qWarning () << Q_FUNC_INFO
136 << "connect for"
137 << sender
138 << "->"
139 << receiver
140 << ":"
141 << signature
142 << "failed";
143 else if (ShouldBeVerbose ())
144 qDebug () << Q_FUNC_INFO
145 << "connecting"
146 << sender
147 << "->"
148 << receiver
149 << "for"
150 << signature;
151 }
152 }
153#undef LC_TOSIGNAL
154#undef LC_TOSLOT
155#undef LC_N
156 }
157
159 {
160 Plugins_.push_back (plugin);
161
162 ConnectHookSignals (this, plugin, true);
163 }
164
166 {
167 ConnectHookSignals (object, this, false);
168 }
169}
170}
#define LC_TOSIGNAL(a)
#define LC_TOSLOT(a)
#define LC_N(a)
virtual ~BaseHookInterconnector()
Virtual destructor.
virtual void AddPlugin(QObject *plugin)
Adds a subplugin to this interconnector.
void RegisterHookable(QObject *hookable)
Adds a hookable object from the root plugin.
BaseHookInterconnector(QObject *parent=0)
Creates the interconnector with the given parent.
Definition constants.h:15