Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qeventspy.cpp
Go to the documentation of this file.
1
// Copyright (C) 2026 The Qt Company Ltd.
2
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4
#
include
"qeventspy.h"
5
6
#
include
<
QtCore
/
qobject
.
h
>
7
#
include
<
QtCore
/
qpointer
.
h
>
8
9
#
include
<
algorithm
>
10
#
include
<
vector
>
11
12
QT_BEGIN_NAMESPACE
13
14
class
QEventSpyPrivate :
public
QObject
15
{
16
public
:
17
QEventSpyPrivate(QObject *object, QEventSpy::Filter filter)
18
: object(object), filter(std::move(filter)), valid(object !=
nullptr
)
19
{
20
if
(object)
21
object->installEventFilter(
this
);
22
else
23
qWarning(
"QEventSpy: Cannot spy on a null object"
);
24
}
25
26
~QEventSpyPrivate() override
27
{
28
if
(object)
29
object->removeEventFilter(
this
);
30
}
31
32
bool
eventFilter(QObject *receiver, QEvent *event) override
33
{
34
if
(filter && !filter(receiver, event))
35
return
false
;
36
37
records.push_back({ receiver, std::unique_ptr<QEvent>(event->clone()) });
38
return
false
;
39
}
40
41
struct
Record
42
{
43
QObject *receiver;
44
std::unique_ptr<QEvent> event;
45
};
46
47
QPointer<QObject> object;
48
const
QEventSpy::Filter filter;
49
std::vector<Record> records;
50
const
bool
valid;
51
};
52
53
/*!
54
\class QEventSpy
55
\inmodule QtTest
56
\since 6.13
57
58
\brief The QEventSpy class enables introspection of event delivery.
59
60
QEventSpy installs itself as an event filter on a QObject and records
61
the events delivered to it, in the order they arrive. QEventSpy never
62
filters out or modifies the events it observes.
63
64
The following example verifies that showing a widget delivers a single
65
\l{QEvent::}{Show} event to it:
66
67
\code
68
QWidget widget;
69
QEventSpy spy(&widget, QEvent::Show);
70
widget.show();
71
QCOMPARE(spy.count(), 1);
72
\endcode
73
74
To record several event types, or all events, pass a list of types,
75
or an empty list:
76
77
\code
78
QEventSpy spy(&widget, { QEvent::FocusIn, QEvent::FocusOut });
79
...
80
QCOMPARE(spy.eventList(), QList({ QEvent::FocusIn, QEvent::FocusOut }));
81
\endcode
82
83
For more fine-grained control, pass a QEventSpy::Filter. This is
84
useful when spying on the application object, which sees the events
85
of all objects:
86
87
\code
88
QEventSpy spy(qApp, [&](QObject *receiver, const QEvent *event) {
89
return receiver == &widget && !event->spontaneous();
90
});
91
\endcode
92
93
QEventSpy stores a copy of each recorded event, made with
94
QEvent::clone() at the time the event filter sees it. The copy can be
95
inspected using at():
96
97
\code
98
QEventSpy spy(&widget, QEvent::MouseButtonPress);
99
QTest::mouseClick(&widget, Qt::LeftButton, {}, QPoint(10, 10));
100
QCOMPARE(spy.at<QMouseEvent>(0)->position(), QPointF(10, 10));
101
\endcode
102
103
Event types that do not reimplement QEvent::clone() are recorded as a
104
plain QEvent of the same type.
105
106
To wait for events that are delivered asynchronously, use one of the
107
QTRY_ macros, or QTest::qWaitFor(), with a condition that states what
108
the test is waiting for:
109
110
\code
111
QEventSpy spy(&window, QEvent::Expose);
112
window.show();
113
QTRY_VERIFY(spy.contains(QEvent::Expose));
114
\endcode
115
116
QEventSpy must be created in the thread of the object it spies on.
117
118
\sa QSignalSpy, QObject::installEventFilter()
119
*/
120
121
/*!
122
\typedef QEventSpy::Filter
123
124
A synonym for \c{std::function<bool(QObject *receiver, const QEvent *event)>}.
125
126
A filter returns \c true for each event that the spy should record.
127
*/
128
129
/*!
130
Constructs a QEventSpy that records all events delivered to \a object.
131
132
If \a object is \nullptr, a warning is output using qWarning()
133
and subsequent calls to isValid() return \c false.
134
*/
135
QEventSpy
::QEventSpy(QObject *object)
136
:
QEventSpy
(object, Filter{})
137
{
138
}
139
140
/*!
141
Constructs a QEventSpy that records events of the given \a type
142
delivered to \a object.
143
144
If \a object is \nullptr, a warning is output using qWarning()
145
and subsequent calls to isValid() return \c false.
146
*/
147
QEventSpy
::QEventSpy(QObject *object, QEvent::Type type)
148
:
QEventSpy
(object, [type](QObject *,
const
QEvent *event) {
149
return
event->type() == type;
150
})
151
{
152
}
153
154
/*!
155
Constructs a QEventSpy that records events of the given \a types
156
delivered to \a object. If \a types is empty, all events are recorded.
157
158
If \a object is \nullptr, a warning is output using qWarning()
159
and subsequent calls to isValid() return \c false.
160
*/
161
QEventSpy
::QEventSpy(QObject *object,
const
QList<QEvent::Type> &types)
162
:
QEventSpy
(object, types.isEmpty() ? Filter{} : Filter([types](QObject *,
const
QEvent *event) {
163
return
types.contains(event->type());
164
}))
165
{
166
}
167
168
/*!
169
Constructs a QEventSpy that records the events delivered to \a object
170
for which \a filter returns \c true. If \a filter is empty, all events
171
are recorded.
172
173
If \a object is \nullptr, a warning is output using qWarning()
174
and subsequent calls to isValid() return \c false.
175
*/
176
QEventSpy
::QEventSpy(QObject *object,
Filter
filter)
177
: d_ptr(std::make_unique<QEventSpyPrivate>(object, std::move(filter)))
178
{
179
}
180
181
/*!
182
Destroys the QEventSpy, and removes it as an event filter
183
from the spied-on object.
184
*/
185
QEventSpy
::~
QEventSpy
() =
default
;
186
187
/*!
188
Returns \c true if the spy was constructed with a valid object,
189
otherwise \c false.
190
191
The spy remains valid if the object is later destroyed.
192
*/
193
bool
QEventSpy
::
isValid
()
const
noexcept
194
{
195
return
d_ptr->valid;
196
}
197
198
/*!
199
Returns the object the spy was installed on, or \nullptr
200
if the object has been destroyed.
201
*/
202
QObject *
QEventSpy
::object()
const
203
{
204
return
d_ptr->object;
205
}
206
207
/*!
208
\fn qsizetype QEventSpy::size() const
209
210
Same as count().
211
*/
212
213
/*!
214
\fn bool QEventSpy::isEmpty() const
215
216
Returns \c true if the spy has not recorded any events,
217
otherwise \c false.
218
*/
219
220
/*!
221
Returns the number of recorded events.
222
*/
223
qsizetype
QEventSpy
::count()
const
noexcept
224
{
225
return
qsizetype(d_ptr->records.size());
226
}
227
228
/*!
229
\overload
230
231
Returns the number of recorded events of the given \a type.
232
*/
233
qsizetype
QEventSpy
::count(QEvent::Type type)
const
noexcept
234
{
235
return
std::count_if(d_ptr->records.cbegin(), d_ptr->records.cend(), [type](
const
auto
&record) {
236
return
record.event->type() == type;
237
});
238
}
239
240
/*!
241
\fn bool QEventSpy::contains(QEvent::Type type) const
242
243
Returns \c true if the spy has recorded at least one event
244
of the given \a type, otherwise \c false.
245
*/
246
247
/*!
248
Returns the types of the recorded events, in the order
249
the spy saw them, including repeated types.
250
251
\code
252
QCOMPARE(spy.eventList(), QList({ QEvent::ChildAdded, QEvent::ChildAdded }));
253
\endcode
254
*/
255
QList<QEvent::Type>
QEventSpy
::eventList()
const
256
{
257
QList<QEvent::Type> eventList;
258
eventList.reserve(count());
259
for
(
const
auto
&record : d_ptr->records)
260
eventList.append(record.event->type());
261
return
eventList;
262
}
263
264
/*!
265
Returns a copy of the recorded event at index position \a i.
266
267
\a i must be a valid index position (0 <= \a i < count()).
268
The returned pointer is valid until the event is removed from
269
the spy, or the spy is destroyed.
270
*/
271
const
QEvent *
QEventSpy
::at(qsizetype i)
const
272
{
273
Q_ASSERT_X(i >= 0 && i < count(),
"QEventSpy::at"
,
"index out of range"
);
274
return
d_ptr->records[size_t(i)].event.get();
275
}
276
277
/*!
278
\fn template <typename EventType> const EventType *QEventSpy::at(qsizetype i) const
279
\overload
280
281
Returns a copy of the recorded event at index position \a i,
282
cast to \c EventType.
283
284
The caller must ensure that the event is of type \c EventType,
285
for example by checking QEvent::type().
286
*/
287
288
/*!
289
Returns the object that the event at index position \a i
290
was delivered to.
291
292
\a i must be a valid index position (0 <= \a i < count()).
293
The object may have been destroyed since the event was recorded.
294
*/
295
QObject *
QEventSpy
::receiver(qsizetype i)
const
296
{
297
Q_ASSERT_X(i >= 0 && i < count(),
"QEventSpy::receiver"
,
"index out of range"
);
298
return
d_ptr->records[size_t(i)].receiver;
299
}
300
301
/*!
302
Removes all recorded events from the spy.
303
*/
304
void
QEventSpy
::
clear
()
305
{
306
d_ptr->records.clear();
307
}
308
309
QT_END_NAMESPACE
QEventSpy
\inmodule QtTest
Definition
qeventspy.h:20
QEventSpy::Filter
std::function< bool(QObject *receiver, const QEvent *event)> Filter
A synonym for {std::function<bool(QObject *receiver, const QEvent *event)>}.
Definition
qeventspy.h:22
QEventSpy::~QEventSpy
Q_TESTLIB_EXPORT ~QEventSpy()
Destroys the QEventSpy, and removes it as an event filter from the spied-on object.
QEventSpy::isValid
Q_TESTLIB_EXPORT bool isValid() const noexcept
Returns true if the spy was constructed with a valid object, otherwise false.
Definition
qeventspy.cpp:193
QEventSpy::clear
Q_TESTLIB_EXPORT void clear()
Removes all recorded events from the spy.
Definition
qeventspy.cpp:304
qtbase
src
testlib
qeventspy.cpp
Generated on
for Qt by
1.18.0