QtBase  v6.3.1
tst_qobject.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2021 The Qt Company Ltd.
4 ** Copyright (C) 2020 Olivier Goffart <ogoffart@woboq.com>
5 ** Copyright (C) 2021 Intel Corporation.
6 ** Contact: https://www.qt.io/licensing/
7 **
8 ** This file is part of the test suite of the Qt Toolkit.
9 **
10 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
11 ** Commercial License Usage
12 ** Licensees holding valid commercial Qt licenses may use this file in
13 ** accordance with the commercial license agreement provided with the
14 ** Software or, alternatively, in accordance with the terms contained in
15 ** a written agreement between you and The Qt Company. For licensing terms
16 ** and conditions see https://www.qt.io/terms-conditions. For further
17 ** information use the contact form at https://www.qt.io/contact-us.
18 **
19 ** GNU General Public License Usage
20 ** Alternatively, this file may be used under the terms of the GNU
21 ** General Public License version 3 as published by the Free Software
22 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
23 ** included in the packaging of this file. Please review the following
24 ** information to ensure the GNU General Public License requirements will
25 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
26 **
27 ** $QT_END_LICENSE$
28 **
29 ****************************************************************************/
30 
31 // This test actually wants to practice narrowing conditions, so never define this.
32 #ifdef QT_NO_NARROWING_CONVERSIONS_IN_CONNECT
33 #undef QT_NO_NARROWING_CONVERSIONS_IN_CONNECT
34 #endif
35 
36 #include <QTest>
37 #include <QtTest/private/qpropertytesthelper_p.h>
38 #include <QStringListModel>
39 #include <QAbstractEventDispatcher>
40 #include <QScopedValueRollback>
41 
42 #include <qcoreapplication.h>
43 #include <qpointer.h>
44 #include <qproperty.h>
45 #include <qtimer.h>
46 #include <qregularexpression.h>
47 #include <qmetaobject.h>
48 #include <qvariant.h>
49 #include <QTcpServer>
50 #include <QTcpSocket>
51 #include <QThread>
52 #include <QMutex>
53 #include <QWaitCondition>
54 #include <QScopedPointer>
55 #if QT_CONFIG(process)
56 # include <QProcess>
57 #endif
58 #include "qobject.h"
59 #ifdef QT_BUILD_INTERNAL
60 #include <private/qobject_p.h>
61 #endif
62 
63 #include <functional>
64 
65 #include <math.h>
66 
67 class tst_QObject : public QObject
68 {
69  Q_OBJECT
70 private slots:
71  void disconnect();
72  void connectSlotsByName();
73  void connectSignalsToSignalsWithDefaultArguments();
74  void receivers();
75  void normalize();
76  void qobject_castTemplate();
77  void findChildren();
78  void connectDisconnectNotify_data();
79  void connectDisconnectNotify();
80  void connectDisconnectNotifyPMF();
81  void disconnectNotify_receiverDestroyed();
82  void disconnectNotify_metaObjConnection();
83  void connectNotify_connectSlotsByName();
84  void connectDisconnectNotify_shadowing();
85  void connectReferenceToIncompleteTypes();
86  void emitInDefinedOrder();
87  void customTypes();
88  void streamCustomTypes();
89  void metamethod();
90  void namespaces();
91  void threadSignalEmissionCrash();
92  void thread();
93  void thread0();
94  void moveToThread();
95  void senderTest();
96  void declareInterface();
97  void qpointerResetBeforeDestroyedSignal();
98  void childDeletesItsSibling();
99  void dynamicProperties();
100  void floatProperty();
101  void qrealProperty();
102  void property();
103  void recursiveSignalEmission();
104  void signalBlocking();
105  void blockingQueuedConnection();
106  void childEvents();
107  void installEventFilter();
108  void deleteSelfInSlot();
109  void disconnectSelfInSlotAndDeleteAfterEmit();
110  void dumpObjectInfo();
111  void dumpObjectTree();
112  void connectToSender();
113  void qobjectConstCast();
114  void uniqConnection();
115  void uniqConnectionPtr();
116  void interfaceIid();
117  void deleteQObjectWhenDeletingEvent();
118  void overloads();
119  void isSignalConnected();
120  void isSignalConnectedAfterDisconnection();
121  void qMetaObjectConnect();
122  void qMetaObjectDisconnectOne();
123  void sameName();
124  void connectByMetaMethods();
125  void connectByMetaMethodSlotInsteadOfSignal();
126  void connectConstructorByMetaMethod();
127  void disconnectByMetaMethod();
128  void disconnectNotSignalMetaMethod();
129  void autoConnectionBehavior();
130  void baseDestroyed();
131  void pointerConnect();
132  void pointerDisconnect();
133  void emitInDefinedOrderPointer();
134  void customTypesPointer();
135  void connectCxx0x();
136  void connectToStaticCxx0x();
137  void connectCxx0xTypeMatching();
138  void connectCxx17Noexcept();
139  void connectConvert();
140  void connectWithReference();
141  void connectManyArguments();
142  void connectForwardDeclare();
143  void connectNoDefaultConstructorArg();
144  void returnValue_data();
145  void returnValue();
146  void returnValue2_data();
147  void returnValue2();
148  void connectVirtualSlots();
149  void connectSlotsVMIClass(); // VMI = Virtual or Multiple Inheritance
150  void connectPrivateSlots();
151  void connectFunctorArgDifference();
152  void connectFunctorOverloads();
153  void connectFunctorQueued();
154  void connectFunctorWithContext();
155  void connectFunctorWithContextUnique();
156  void connectFunctorDeadlock();
157  void connectFunctorMoveOnly();
158  void connectStaticSlotWithObject();
159  void disconnectDoesNotLeakFunctor();
160  void contextDoesNotLeakFunctor();
161  void connectBase();
162  void connectWarnings();
163  void qmlConnect();
164  void qmlConnectToQObjectReceiver();
165  void exceptions();
166  void deleteLaterInAboutToBlockHandler();
167  void mutableFunctor();
168  void checkArgumentsForNarrowing();
169  void nullReceiver();
170  void functorReferencesConnection();
171  void disconnectDisconnects();
172  void singleShotConnection();
173  void objectNameBinding();
174  void emitToDestroyedClass();
175 };
176 
178 {
181  {
182  QObject();
183  }
184 };
185 static QObjectCreatedOnShutdown s_qobjectCreatedOnShutdown;
186 
187 class SenderObject : public QObject
188 {
189  Q_OBJECT
190 
191 public:
192  SenderObject() : aPublicSlotCalled(0), recursionCount(0) {}
193 
195  {
196  if (recursionCount++ < 100)
198  else
199  emitSignal1();
200  }
201 
202  void emitSignal1() { emit signal1(); }
203  void emitSignal2() { emit signal2(); }
204  void emitSignal3() { emit signal3(); }
205  void emitSignal4() { emit signal4(); }
206 
207 signals:
208  void signal1();
209  void signal2();
210  void signal3();
211  void signal4();
212  QT_MOC_COMPAT void signal5();
213  void signal6(void);
214  void signal7(int, const QString &);
215 
216 public slots:
218 
219 public:
223 protected:
224  Q_INVOKABLE QT_MOC_COMPAT void invoke2(){}
225  Q_INVOKABLE QT_MOC_COMPAT void invoke2(int){}
226  Q_SCRIPTABLE QT_MOC_COMPAT void sinvoke2(){}
227 private:
228  Q_INVOKABLE void invoke3(int hinz = 0, int kunz = 0)
229  {
230  Q_UNUSED(hinz);
231  Q_UNUSED(kunz);
232  }
233  Q_SCRIPTABLE void sinvoke3(){}
234 
235  int recursionCount;
236 };
237 
238 class ReceiverObject : public QObject
239 {
240  Q_OBJECT
241 
242 public:
244  : sequence_slot1( 0 )
245  , sequence_slot2( 0 )
246  , sequence_slot3( 0 )
247  , sequence_slot4( 0 )
248  {}
249 
250  void reset()
251  {
252  sequence_slot4 = 0;
253  sequence_slot3 = 0;
254  sequence_slot2 = 0;
255  sequence_slot1 = 0;
256  count_slot1 = 0;
257  count_slot2 = 0;
258  count_slot3 = 0;
259  count_slot4 = 0;
260  }
261 
270 
271  bool called(int slot)
272  {
273  switch (slot) {
274  case 1: return sequence_slot1;
275  case 2: return sequence_slot2;
276  case 3: return sequence_slot3;
277  case 4: return sequence_slot4;
278  default: return false;
279  }
280  }
281 
282  static int sequence;
283 
284 public slots:
289 
290 };
291 
293 
294 static void playWithObjects()
295 {
296  // Do operations that will lock the internal signalSlotLock mutex on many QObjects.
297  // The more QObjects, the higher the chance that the signalSlotLock mutex used
298  // is already in use. If the number of objects is higher than the number of mutexes in
299  // the pool (currently 131), the deadlock should always trigger. Use an even higher number
300  // to be on the safe side.
301  const int objectCount = 1024;
302  SenderObject lotsOfObjects[objectCount];
303  for (int i = 0; i < objectCount; ++i) {
304  QObject::connect(&lotsOfObjects[i], &SenderObject::signal1,
305  &lotsOfObjects[i], &SenderObject::aPublicSlot);
306  }
307 }
308 
309 void tst_QObject::disconnect()
310 {
311  SenderObject s;
314 
315  connect(&s, SIGNAL(signal1()), &r1, SLOT(slot1()));
316 
317  connect(&s, SIGNAL(signal2()), &r1, SLOT(slot2()));
318  connect(&s, SIGNAL(signal3()), &r1, SLOT(slot3()));
319  connect(&s, SIGNAL(signal4()), &r1, SLOT(slot4()));
320 
321  s.emitSignal1();
322  s.emitSignal2();
323  s.emitSignal3();
324  s.emitSignal4();
325 
326  QVERIFY(r1.called(1));
327  QVERIFY(r1.called(2));
328  QVERIFY(r1.called(3));
329  QVERIFY(r1.called(4));
330  r1.reset();
331 
332  // usual disconnect with all parameters given
333  bool ret = QObject::disconnect(&s, SIGNAL(signal1()), &r1, SLOT(slot1()));
334 
335  s.emitSignal1();
336 
337  QVERIFY(!r1.called(1));
338  r1.reset();
339 
340  QVERIFY(ret);
341  ret = QObject::disconnect(&s, SIGNAL(signal1()), &r1, SLOT(slot1()));
342  QVERIFY(!ret);
343 
344  // disconnect all signals from s from all slots from r1
345  QObject::disconnect(&s, 0, &r1, 0);
346 
347  s.emitSignal2();
348  s.emitSignal3();
349  s.emitSignal4();
350 
351  QVERIFY(!r1.called(2));
352  QVERIFY(!r1.called(3));
353  QVERIFY(!r1.called(4));
354  r1.reset();
355 
356  connect(&s, SIGNAL(signal1()), &r1, SLOT(slot1()));
357  connect(&s, SIGNAL(signal1()), &r1, SLOT(slot2()));
358  connect(&s, SIGNAL(signal1()), &r1, SLOT(slot3()));
359  connect(&s, SIGNAL(signal2()), &r1, SLOT(slot4()));
360 
361  // disconnect s's signal1() from all slots of r1
362  QObject::disconnect(&s, SIGNAL(signal1()), &r1, 0);
363 
364  s.emitSignal1();
365  s.emitSignal2();
366 
367  QVERIFY(!r1.called(1));
368  QVERIFY(!r1.called(2));
369  QVERIFY(!r1.called(3));
370  QVERIFY(r1.called(4));
371  r1.reset();
372  // make sure all is disconnected again
373  QObject::disconnect(&s, 0, &r1, 0);
374 
375  connect(&s, SIGNAL(signal1()), &r1, SLOT(slot1()));
376  connect(&s, SIGNAL(signal1()), &r2, SLOT(slot1()));
377  connect(&s, SIGNAL(signal2()), &r1, SLOT(slot2()));
378  connect(&s, SIGNAL(signal2()), &r2, SLOT(slot2()));
379  connect(&s, SIGNAL(signal3()), &r1, SLOT(slot3()));
380  connect(&s, SIGNAL(signal3()), &r2, SLOT(slot3()));
381 
382  // disconnect signal1() from all receivers
383  QObject::disconnect(&s, SIGNAL(signal1()), 0, 0);
384  s.emitSignal1();
385  s.emitSignal2();
386  s.emitSignal3();
387 
388  QVERIFY(!r1.called(1));
389  QVERIFY(!r2.called(1));
390  QVERIFY(r1.called(2));
391  QVERIFY(r2.called(2));
392  QVERIFY(r1.called(2));
393  QVERIFY(r2.called(2));
394 
395  r1.reset();
396  r2.reset();
397 
398  // disconnect all signals of s from all receivers
399  QObject::disconnect(&s, 0, 0, 0);
400 
401  QVERIFY(!r1.called(2));
402  QVERIFY(!r2.called(2));
403  QVERIFY(!r1.called(2));
404  QVERIFY(!r2.called(2));
405 }
406 
408 {
409  Q_OBJECT
410 
411 public:
413  : QObject(parent)
414  {}
415 
418  void emitSignalWithParams(int i, QString string) { emit signalWithParams(i, string); }
419  void emitSignalManyParams(int i1, int i2, int i3, QString string, bool onoff) { emit signalManyParams(i1, i2, i3, string, onoff); }
420  void emitSignalManyParams(int i1, int i2, int i3, QString string, bool onoff, bool dummy) { emit signalManyParams(i1, i2, i3, string, onoff, dummy); }
421  void emitSignalManyParams2(int i1, int i2, int i3, QString string, bool onoff) { emit signalManyParams2(i1, i2, i3, string, onoff); }
423 
424 signals:
426  void signalWithParams(int i);
427  void signalWithParams(int i, QString string);
428  void signalManyParams(int i1, int i2, int i3, QString string, bool onoff);
429  void signalManyParams(int i1, int i2, int i3, QString string, bool onoff, bool);
430  void signalManyParams2(int i1, int i2, int i3, QString string, bool onoff);
432 };
433 
435 {
436  Q_OBJECT
437 
438 public:
440 
442  {
444  }
445 
448 
449 public slots:
451  void on_Sender_signalWithParams(int = 0) { called_slots << 2; }
454  void on_Sender_signalManyParams(int, int, int, QString, bool) { called_slots << 5; }
455  void on_Sender_signalManyParams(int, int, int, QString, bool, bool) { called_slots << 6; }
456  void on_Sender_signalManyParams2(int, int, int, QString, bool) { called_slots << 7; }
457  void slotLoopBack() { called_slots << 8; }
460 
461 protected slots:
462  void o() { called_slots << -1; }
463  void on() { called_slots << -1; }
464  void on_() { called_slots << -1; }
465  void on_something() { called_slots << -1; }
466  void on_child_signal() { called_slots << -1; }
467 
468 signals:
472 };
473 
474 void tst_QObject::connectSlotsByName()
475 {
476  AutoConnectReceiver receiver;
477  receiver.setObjectName("Receiver");
478  AutoConnectSender sender(&receiver);
479  sender.setObjectName("Sender");
480 
481  QTest::ignoreMessage(QtWarningMsg, "QMetaObject::connectSlotsByName: No matching signal for on_child_signal()");
482  QTest::ignoreMessage(QtWarningMsg, "QMetaObject::connectSlotsByName: Connecting slot on_Sender_signalManyParams() with the first of the following compatible signals: QList(\"signalManyParams(int,int,int,QString,bool)\", \"signalManyParams(int,int,int,QString,bool,bool)\")");
484 
485  receiver.called_slots.clear();
486  sender.emitSignalNoParams();
487  QCOMPARE(receiver.called_slots, QList<int>() << 1);
488 
489  receiver.called_slots.clear();
490  sender.emitSignalWithParams(0);
491  QCOMPARE(receiver.called_slots, QList<int>() << 2);
492 
493  receiver.called_slots.clear();
494  sender.emitSignalWithParams(0, "string");
495  QCOMPARE(receiver.called_slots, QList<int>() << 3);
496 
497  receiver.called_slots.clear();
498  sender.emitSignalManyParams(1, 2, 3, "string", true);
499  sender.emitSignalManyParams(1, 2, 3, "string", true, false);
500  // the slot '4' (signalManyParams()) will get connected
501  // to either of the two signalManyParams(...) overloads
502  QCOMPARE(receiver.called_slots, QList<int>() << 4 << 5 << 6);
503 
504  receiver.called_slots.clear();
505  sender.emitSignalManyParams2(1, 2, 3, "string", true);
506  QCOMPARE(receiver.called_slots, QList<int>() << 7);
507 
508  receiver.called_slots.clear();
509  sender.emitSignalLoopBack();
510  QCOMPARE(receiver.called_slots, QList<int>() << 8);
511 
512  receiver.called_slots.clear();
513  receiver.emitSignalNoParams();
514  QCOMPARE(receiver.called_slots, QList<int>() << 9);
515 
516  receiver.called_slots.clear();
517  receiver.emit_signal_with_underscore();
518  QCOMPARE(receiver.called_slots, QList<int>() << 10);
519 }
520 
521 void tst_QObject::qobject_castTemplate()
522 {
524  QVERIFY(!::qobject_cast<QObject*>(o.data()));
525 
526  o.reset(new SenderObject);
527  QVERIFY(::qobject_cast<SenderObject*>(o.data()));
528  QVERIFY(::qobject_cast<QObject*>(o.data()));
529  QVERIFY(!::qobject_cast<ReceiverObject*>(o.data()));
530 }
531 
532 void tst_QObject::findChildren()
533 {
534  QObject o;
535  QObject o1(&o);
536  QObject o2(&o);
537  QObject o11(&o1);
538  QObject o12(&o1);
539  QObject o111(&o11);
540  QObject unnamed(&o);
541  QTimer t1(&o);
542  QTimer t121(&o12);
543  QTimer emptyname(&o);
544 
546  Q_SET_OBJECT_NAME(o1);
547  Q_SET_OBJECT_NAME(o2);
548  Q_SET_OBJECT_NAME(o11);
549  Q_SET_OBJECT_NAME(o12);
550  Q_SET_OBJECT_NAME(o111);
552  Q_SET_OBJECT_NAME(t121);
553  emptyname.setObjectName("");
554 
555  QObject *op = nullptr;
556 
557  op = o.findChild<QObject*>("o1");
558  QCOMPARE(op, &o1);
559  op = o.findChild<QObject*>("o2");
560  QCOMPARE(op, &o2);
561  op = o.findChild<QObject*>("o11");
562  QCOMPARE(op, &o11);
563  op = o.findChild<QObject*>("o12");
564  QCOMPARE(op, &o12);
565  op = o.findChild<QObject*>("o111");
566  QCOMPARE(op, &o111);
567  op = o.findChild<QObject*>("t1");
568  QCOMPARE(op, static_cast<QObject *>(&t1));
569  op = o.findChild<QObject*>("t121");
570  QCOMPARE(op, static_cast<QObject *>(&t121));
571  op = o.findChild<QTimer*>("t1");
572  QCOMPARE(op, static_cast<QObject *>(&t1));
573  op = o.findChild<QTimer*>("t121");
574  QCOMPARE(op, static_cast<QObject *>(&t121));
575  op = o.findChild<QTimer*>("o12");
576  QCOMPARE(op, static_cast<QObject *>(0));
577  op = o.findChild<QObject*>("o");
578  QCOMPARE(op, static_cast<QObject *>(0));
579  op = o.findChild<QObject*>("harry");
580  QCOMPARE(op, static_cast<QObject *>(0));
581  op = o.findChild<QObject*>("o1");
582  QCOMPARE(op, &o1);
583 
585  QList<QTimer*> tl;
586 
587  l = o.findChildren<QObject*>("o1");
588  QCOMPARE(l.size(), 1);
589  QCOMPARE(l.at(0), &o1);
590  l = o.findChildren<QObject*>("o2");
591  QCOMPARE(l.size(), 1);
592  QCOMPARE(l.at(0), &o2);
593  l = o.findChildren<QObject*>("o11");
594  QCOMPARE(l.size(), 1);
595  QCOMPARE(l.at(0), &o11);
596  l = o.findChildren<QObject*>("o12");
597  QCOMPARE(l.size(), 1);
598  QCOMPARE(l.at(0), &o12);
599  l = o.findChildren<QObject*>("o111");
600  QCOMPARE(l.size(), 1);
601  QCOMPARE(l.at(0), &o111);
602  l = o.findChildren<QObject*>("t1");
603  QCOMPARE(l.size(), 1);
604  QCOMPARE(l.at(0), static_cast<QObject *>(&t1));
605  l = o.findChildren<QObject*>("t121");
606  QCOMPARE(l.size(), 1);
607  QCOMPARE(l.at(0), static_cast<QObject *>(&t121));
608  tl = o.findChildren<QTimer*>("t1");
609  QCOMPARE(tl.size(), 1);
610  QCOMPARE(tl.at(0), &t1);
611  tl = o.findChildren<QTimer*>("t121");
612  QCOMPARE(tl.size(), 1);
613  QCOMPARE(tl.at(0), &t121);
614  l = o.findChildren<QObject*>("o");
615  QCOMPARE(l.size(), 0);
616  l = o.findChildren<QObject*>("harry");
617  QCOMPARE(l.size(), 0);
618  tl = o.findChildren<QTimer*>("o12");
619  QCOMPARE(tl.size(), 0);
620  l = o.findChildren<QObject*>("o1");
621  QCOMPARE(l.size(), 1);
622  QCOMPARE(l.at(0), &o1);
623 
624  l = o.findChildren<QObject*>(QRegularExpression("^o.*$"));
625  QCOMPARE(l.size(), 5);
626  QVERIFY(l.contains(&o1));
627  QVERIFY(l.contains(&o2));
628  QVERIFY(l.contains(&o11));
629  QVERIFY(l.contains(&o12));
630  QVERIFY(l.contains(&o111));
631  l = o.findChildren<QObject*>(QRegularExpression("t.*"));
632  QCOMPARE(l.size(), 2);
633  QVERIFY(l.contains(&t1));
634  QVERIFY(l.contains(&t121));
635  tl = o.findChildren<QTimer*>(QRegularExpression("^.*$"));
636  QCOMPARE(tl.size(), 3);
637  QVERIFY(tl.contains(&t1));
638  QVERIFY(tl.contains(&t121));
639  tl = o.findChildren<QTimer*>(QRegularExpression("^o.*$"));
640  QCOMPARE(tl.size(), 0);
641  l = o.findChildren<QObject*>(QRegularExpression("^harry$"));
642  QCOMPARE(l.size(), 0);
643 
644  l = o.findChildren<QObject*>(QRegularExpression("o.*"));
645  QCOMPARE(l.size(), 5);
646  QVERIFY(l.contains(&o1));
647  QVERIFY(l.contains(&o2));
648  QVERIFY(l.contains(&o11));
649  QVERIFY(l.contains(&o12));
650  QVERIFY(l.contains(&o111));
651  l = o.findChildren<QObject*>(QRegularExpression("t.*"));
652  QCOMPARE(l.size(), 2);
653  QVERIFY(l.contains(&t1));
654  QVERIFY(l.contains(&t121));
655  tl = o.findChildren<QTimer*>(QRegularExpression(".*"));
656  QCOMPARE(tl.size(), 3);
657  QVERIFY(tl.contains(&t1));
658  QVERIFY(tl.contains(&t121));
659  tl = o.findChildren<QTimer*>(QRegularExpression("o.*"));
660  QCOMPARE(tl.size(), 0);
661  l = o.findChildren<QObject*>(QRegularExpression("harry"));
662  QCOMPARE(l.size(), 0);
663 
664  // empty and null string check
665  op = o.findChild<QObject*>();
666  QCOMPARE(op, &o1);
667  op = o.findChild<QObject*>("");
668  QCOMPARE(op, &unnamed);
669  op = o.findChild<QObject*>("unnamed");
670  QCOMPARE(op, static_cast<QObject *>(0));
671 
672  l = o.findChildren<QObject*>();
673  QCOMPARE(l.size(), 9);
674  l = o.findChildren<QObject*>("");
675  QCOMPARE(l.size(), 2);
676  l = o.findChildren<QObject*>("unnamed");
677  QCOMPARE(l.size(), 0);
678 
679  tl = o.findChildren<QTimer *>("t1");
680  QCOMPARE(tl.size(), 1);
681  QCOMPARE(tl.at(0), &t1);
682 
683  // Find direct child/children
684 
685  op = o.findChild<QObject*>("o1", Qt::FindDirectChildrenOnly);
686  QCOMPARE(op, &o1);
687  op = o.findChild<QObject*>("o2", Qt::FindDirectChildrenOnly);
688  QCOMPARE(op, &o2);
689  op = o.findChild<QObject*>("o11", Qt::FindDirectChildrenOnly);
690  QCOMPARE(op, static_cast<QObject *>(0));
691  op = o.findChild<QObject*>("o12", Qt::FindDirectChildrenOnly);
692  QCOMPARE(op, static_cast<QObject *>(0));
693  op = o.findChild<QObject*>("o111", Qt::FindDirectChildrenOnly);
694  QCOMPARE(op, static_cast<QObject *>(0));
695  op = o.findChild<QObject*>("t1", Qt::FindDirectChildrenOnly);
696  QCOMPARE(op, static_cast<QObject *>(&t1));
697  op = o.findChild<QObject*>("t121", Qt::FindDirectChildrenOnly);
698  QCOMPARE(op, static_cast<QObject *>(0));
699  op = o.findChild<QTimer*>("t1", Qt::FindDirectChildrenOnly);
700  QCOMPARE(op, static_cast<QObject *>(&t1));
701  op = o.findChild<QTimer*>("t121", Qt::FindDirectChildrenOnly);
702  QCOMPARE(op, static_cast<QObject *>(0));
703  op = o.findChild<QTimer*>("o12", Qt::FindDirectChildrenOnly);
704  QCOMPARE(op, static_cast<QObject *>(0));
705  op = o.findChild<QObject*>("o", Qt::FindDirectChildrenOnly);
706  QCOMPARE(op, static_cast<QObject *>(0));
707  op = o.findChild<QObject*>("harry", Qt::FindDirectChildrenOnly);
708  QCOMPARE(op, static_cast<QObject *>(0));
709  op = o.findChild<QObject*>("o1", Qt::FindDirectChildrenOnly);
710  QCOMPARE(op, &o1);
711 
712  l = o.findChildren<QObject*>("o1", Qt::FindDirectChildrenOnly);
713  QCOMPARE(l.size(), 1);
714  QCOMPARE(l.at(0), &o1);
715  l = o.findChildren<QObject*>("o2", Qt::FindDirectChildrenOnly);
716  QCOMPARE(l.size(), 1);
717  QCOMPARE(l.at(0), &o2);
718  l = o.findChildren<QObject*>("o11", Qt::FindDirectChildrenOnly);
719  QCOMPARE(l.size(), 0);
720  l = o.findChildren<QObject*>("o12", Qt::FindDirectChildrenOnly);
721  QCOMPARE(l.size(), 0);
722  l = o.findChildren<QObject*>("o111", Qt::FindDirectChildrenOnly);
723  QCOMPARE(l.size(), 0);
724  l = o.findChildren<QObject*>("t1", Qt::FindDirectChildrenOnly);
725  QCOMPARE(l.size(), 1);
726  QCOMPARE(l.at(0), static_cast<QObject *>(&t1));
727  l = o.findChildren<QObject*>("t121", Qt::FindDirectChildrenOnly);
728  QCOMPARE(l.size(), 0);
729  tl = o.findChildren<QTimer*>("t1", Qt::FindDirectChildrenOnly);
730  QCOMPARE(tl.size(), 1);
731  QCOMPARE(tl.at(0), &t1);
732  tl = o.findChildren<QTimer*>("t121", Qt::FindDirectChildrenOnly);
733  QCOMPARE(tl.size(), 0);
734  l = o.findChildren<QObject*>("o", Qt::FindDirectChildrenOnly);
735  QCOMPARE(l.size(), 0);
736  l = o.findChildren<QObject*>("harry", Qt::FindDirectChildrenOnly);
737  QCOMPARE(l.size(), 0);
738  tl = o.findChildren<QTimer*>("o12", Qt::FindDirectChildrenOnly);
739  QCOMPARE(tl.size(), 0);
740  l = o.findChildren<QObject*>("o1", Qt::FindDirectChildrenOnly);
741  QCOMPARE(l.size(), 1);
742  QCOMPARE(l.at(0), &o1);
743 
744  l = o.findChildren<QObject*>(QRegularExpression("^o.*$"), Qt::FindDirectChildrenOnly);
745  QCOMPARE(l.size(), 2);
746  QVERIFY(l.contains(&o1));
747  QVERIFY(l.contains(&o2));
748  l = o.findChildren<QObject*>(QRegularExpression("^t.*$"), Qt::FindDirectChildrenOnly);
749  QCOMPARE(l.size(), 1);
750  QVERIFY(l.contains(&t1));
751  tl = o.findChildren<QTimer*>(QRegularExpression("^.*$"), Qt::FindDirectChildrenOnly);
752  QCOMPARE(tl.size(), 2);
753  QVERIFY(tl.contains(&t1));
754  tl = o.findChildren<QTimer*>(QRegularExpression("^o.*$"), Qt::FindDirectChildrenOnly);
755  QCOMPARE(tl.size(), 0);
756  l = o.findChildren<QObject*>(QRegularExpression("^harry$"), Qt::FindDirectChildrenOnly);
757  QCOMPARE(l.size(), 0);
758 
759  // empty and null string check
760  op = o.findChild<QObject*>(QString(), Qt::FindDirectChildrenOnly);
761  QCOMPARE(op, &o1);
762  op = o.findChild<QObject*>("", Qt::FindDirectChildrenOnly);
763  QCOMPARE(op, &unnamed);
764  op = o.findChild<QObject*>("unnamed", Qt::FindDirectChildrenOnly);
765  QCOMPARE(op, static_cast<QObject *>(0));
766 
767  l = o.findChildren<QObject*>(Qt::FindDirectChildrenOnly);
768  QCOMPARE(l.size(), 5);
769  l = o.findChildren<QObject*>(QString(), Qt::FindDirectChildrenOnly);
770  QCOMPARE(l.size(), 5);
771  l = o.findChildren<QObject*>("", Qt::FindDirectChildrenOnly);
772  QCOMPARE(l.size(), 2);
773  l = o.findChildren<QObject*>("unnamed", Qt::FindDirectChildrenOnly);
774  QCOMPARE(l.size(), 0);
775 
776  tl = o.findChildren<QTimer *>("t1", Qt::FindDirectChildrenOnly);
777  QCOMPARE(tl.size(), 1);
778  QCOMPARE(tl.at(0), &t1);
779 }
780 
781 
783 {
784 public:
786  {}
787 
791  {
794  }
795 protected:
796  void connectNotify(const QMetaMethod &signal) override
798  void disconnectNotify(const QMetaMethod &signal) override
800 };
801 
802 void tst_QObject::connectDisconnectNotify_data()
803 {
804  QTest::addColumn<QString>("a_signal");
805  QTest::addColumn<QString>("a_slot");
806 
807  QTest::newRow("combo1") << SIGNAL( signal1() ) << SLOT( slot1() );
808  QTest::newRow("combo2") << SIGNAL( signal2(void) ) << SLOT( slot2( ) );
809  QTest::newRow("combo3") << SIGNAL( signal3( ) ) << SLOT( slot3(void) );
810  QTest::newRow("combo4") << SIGNAL( signal4( void ) )<< SLOT( slot4( void ) );
811  QTest::newRow("combo5") << SIGNAL( signal6( void ) ) << SLOT( slot4() );
812  QTest::newRow("combo6") << SIGNAL( signal6() ) << SLOT( slot4() );
813  QTest::newRow("combo7") << SIGNAL( signal7( int , const QString & ) ) << SLOT( slot4() );
814 }
815 
816 void tst_QObject::connectDisconnectNotify()
817 {
818  NotifyObject s;
819  NotifyObject r;
820 
821  QFETCH(QString, a_signal);
822  QFETCH(QString, a_slot);
823 
824  // Obtaining meta methods
825  int signalIndx = ((SenderObject &)s).metaObject()->indexOfSignal(
826  QMetaObject::normalizedSignature(a_signal.toLatin1().constData()+1).constData());
827  int methodIndx = ((ReceiverObject &)r).metaObject()->indexOfMethod(
828  QMetaObject::normalizedSignature(a_slot.toLatin1().constData()+1).constData());
829  QMetaMethod signal = ((SenderObject &)s).metaObject()->method(signalIndx);
830  QMetaMethod method = ((ReceiverObject &)r).metaObject()->method(methodIndx);
831  QVERIFY(signal.isValid());
832  QVERIFY(method.isValid());
833 
834  // Test connectNotify
835  QVERIFY(QObject::connect((SenderObject *)&s, a_signal.toLatin1(),
836  (ReceiverObject *)&r, a_slot.toLatin1()));
837  QCOMPARE(s.connectedSignals.size(), 1);
838  QCOMPARE(s.connectedSignals.at(0), signal);
839  QVERIFY(s.disconnectedSignals.isEmpty());
840 
841  // Test disconnectNotify
842  QVERIFY(QObject::disconnect((SenderObject *)&s, a_signal.toLatin1(),
843  (ReceiverObject *)&r, a_slot.toLatin1()));
844  QCOMPARE(s.disconnectedSignals.size(), 1);
845  QCOMPARE(s.disconnectedSignals.at(0), signal);
846  QCOMPARE(s.connectedSignals.size(), 1);
847 
848  // Reconnect
849  s.clearNotifications();
850  QVERIFY(QObject::connect((SenderObject *)&s, a_signal.toLatin1(),
851  (ReceiverObject *)&r, a_slot.toLatin1()));
852  QCOMPARE(s.connectedSignals.size(), 1);
853  QCOMPARE(s.connectedSignals.at(0), signal);
854  QVERIFY(s.disconnectedSignals.isEmpty());
855 
856  // Test disconnectNotify for a complete disconnect
857  QVERIFY(((SenderObject *)&s)->disconnect((ReceiverObject *)&r));
858  QCOMPARE(s.disconnectedSignals.size(), 1);
859  QCOMPARE(s.disconnectedSignals.at(0), QMetaMethod());
860  QCOMPARE(s.connectedSignals.size(), 1);
861 
862  // Test connectNotify when connecting by QMetaMethod
863  s.clearNotifications();
865  QCOMPARE(s.connectedSignals.size(), 1);
866  QCOMPARE(s.connectedSignals.at(0), signal);
867  QVERIFY(s.disconnectedSignals.isEmpty());
868 
869  // Test disconnectNotify when disconnecting by QMetaMethod
871  QCOMPARE(s.disconnectedSignals.size(), 1);
872  QCOMPARE(s.disconnectedSignals.at(0), signal);
873  QCOMPARE(s.connectedSignals.size(), 1);
874 
875  // Reconnect
876  s.clearNotifications();
877  QVERIFY(QObject::connect((SenderObject *)&s, a_signal.toLatin1(),
878  (ReceiverObject *)&r, a_slot.toLatin1()));
879 
880  // Test disconnectNotify for a complete disconnect by QMetaMethod
882  QCOMPARE(s.disconnectedSignals.size(), 1);
883  QCOMPARE(s.disconnectedSignals.at(0), QMetaMethod());
884  QCOMPARE(s.connectedSignals.size(), 1);
885 
886  // Test connectNotify when connecting by index
887  s.clearNotifications();
888  QVERIFY(QMetaObject::connect((SenderObject *)&s, signalIndx, (ReceiverObject *)&r, methodIndx));
889  QCOMPARE(s.connectedSignals.size(), 1);
890  QCOMPARE(s.connectedSignals.at(0), signal);
891  QVERIFY(s.disconnectedSignals.isEmpty());
892 
893  // Test disconnectNotify when disconnecting by index
895  (ReceiverObject *)&r, methodIndx));
896  QCOMPARE(s.disconnectedSignals.size(), 1);
897  QCOMPARE(s.disconnectedSignals.at(0), signal);
898  QCOMPARE(s.connectedSignals.size(), 1);
899 }
900 
901 struct Incomplete;
903  Q_OBJECT
904 
905 public:
907 signals:
908  void signalWithIncomplete(const Incomplete &);
909 public slots:
910  void slotWithIncomplete(const Incomplete &) {}
911 };
912 
913 void tst_QObject::connectReferenceToIncompleteTypes() {
914  QObjectWithIncomplete withIncomplete;
918 }
919 
920 static void connectDisconnectNotifyTestSlot() {}
921 
922 void tst_QObject::connectDisconnectNotifyPMF()
923 {
924  NotifyObject s;
925  NotifyObject r;
926 
928 
929  // Test connectNotify
932  QCOMPARE(s.connectedSignals.size(), 1);
933  QCOMPARE(s.connectedSignals.at(0), signal);
934  QVERIFY(s.disconnectedSignals.isEmpty());
935 
936  // Test disconnectNotify
939  QCOMPARE(s.disconnectedSignals.size(), 1);
940  QCOMPARE(s.disconnectedSignals.at(0), signal);
941  QCOMPARE(s.connectedSignals.size(), 1);
942 
943  // Reconnect
944  s.clearNotifications();
947  QCOMPARE(s.connectedSignals.size(), 1);
948  QCOMPARE(s.connectedSignals.at(0), signal);
949  QVERIFY(s.disconnectedSignals.isEmpty());
950 
951  // Test disconnectNotify with wildcard slot
953  (ReceiverObject *)&r, 0));
954  QCOMPARE(s.disconnectedSignals.size(), 1);
955  QCOMPARE(s.disconnectedSignals.at(0), signal);
956  QCOMPARE(s.connectedSignals.size(), 1);
957 
958  // Reconnect
959  s.clearNotifications();
962 
963  QVERIFY(conn);
964 
965  // Test disconnectNotify when disconnecting by QMetaObject::Connection
967  QVERIFY(!s.disconnectedSignals.isEmpty());
968 
969  // Test connectNotify when connecting by function pointer
970  s.clearNotifications();
972  connectDisconnectNotifyTestSlot));
973  QCOMPARE(s.connectedSignals.size(), 1);
974  QCOMPARE(s.connectedSignals.at(0), signal);
975  QVERIFY(s.disconnectedSignals.isEmpty());
976 }
977 
978 void tst_QObject::disconnectNotify_receiverDestroyed()
979 {
980  NotifyObject s;
981 
982  {
983  NotifyObject r;
984  QVERIFY(QObject::connect((SenderObject *)&s, SIGNAL(signal1()),
985  (ReceiverObject *)&r, SLOT(slot1())));
986  }
987  QCOMPARE(s.disconnectedSignals.count(), 1);
988  QCOMPARE(s.disconnectedSignals.at(0), QMetaMethod::fromSignal(&SenderObject::signal1));
989 
990  s.disconnectedSignals.clear();
991 
992  {
993  NotifyObject r;
994  QVERIFY(QObject::connect((SenderObject *)&s, SIGNAL(signal3()),
995  (ReceiverObject *)&r, SLOT(slot3())));
996  }
997 
998  QCOMPARE(s.disconnectedSignals.count(), 1);
999  QCOMPARE(s.disconnectedSignals.at(0), QMetaMethod::fromSignal(&SenderObject::signal3));
1000 
1001  s.disconnectedSignals.clear();
1002 
1003  {
1004  NotifyObject r;
1006  }
1007 
1008  QCOMPARE(s.disconnectedSignals.count(), 1);
1009  QCOMPARE(s.disconnectedSignals.at(0), QMetaMethod::fromSignal(&QObject::destroyed));
1010 }
1011 
1012 void tst_QObject::disconnectNotify_metaObjConnection()
1013 {
1014  NotifyObject s;
1015  {
1016  NotifyObject r;
1017 
1019  (ReceiverObject *)&r, SLOT(slot1()));
1020  QVERIFY(c);
1022 
1023  QCOMPARE(s.disconnectedSignals.count(), 1);
1024  QCOMPARE(s.disconnectedSignals.at(0), QMetaMethod::fromSignal(&SenderObject::signal1));
1025 
1026  QCOMPARE(s.disconnectedSignals.count(), 1);
1027  }
1028 }
1029 
1031 {
1032  Q_OBJECT
1033 public:
1037  {
1040  }
1041 protected:
1042  void connectNotify(const QMetaMethod &signal) override
1044  void disconnectNotify(const QMetaMethod &signal) override
1046 Q_SIGNALS:
1047  void signal1();
1048 };
1049 
1051 {
1052  Q_OBJECT
1053  void createNotifyChild(const char *name)
1054  {
1056  o->setParent(this);
1057  o->setObjectName(QString::fromLatin1(name));
1058  }
1059 public:
1061  {
1062  createNotifyChild("foo");
1063  createNotifyChild("bar");
1064  createNotifyChild("baz");
1065  };
1066 
1067 public Q_SLOTS:
1068  void on_foo_signal1() {}
1069  void on_bar_signal1() {}
1070  void on_baz_signal1() {}
1071 };
1072 
1073 void tst_QObject::connectNotify_connectSlotsByName()
1074 {
1077  testObject.findChildren<ConnectByNameNotifySenderObject *>();
1078  for (ConnectByNameNotifySenderObject *o : senders) {
1079  QVERIFY(o->connectedSignals.isEmpty());
1080  QVERIFY(o->disconnectedSignals.isEmpty());
1081  }
1082 
1084 
1085  for (ConnectByNameNotifySenderObject *o : senders) {
1086  QCOMPARE(o->connectedSignals.size(), 1);
1088  QVERIFY(o->disconnectedSignals.isEmpty());
1089  }
1090 }
1091 
1094 {
1095  Q_OBJECT
1096 public Q_SLOTS:
1097  void slot1() {}
1098 Q_SIGNALS:
1099  void signal1();
1100 };
1101 
1102 void tst_QObject::connectDisconnectNotify_shadowing()
1103 {
1105  // Obtain QMetaMethods
1108  QVERIFY(shadowedSignal1 != redefinedSignal1);
1109  int slot1Index = s.metaObject()->indexOfSlot("slot1()");
1110  QVERIFY(slot1Index != -1);
1111  QMetaMethod slot1 = s.metaObject()->method(slot1Index);
1112 
1113  // Test connectNotify
1114 #ifndef QT_NO_DEBUG
1115  const char *warning = "QMetaObject::indexOfSignal: signal signal1() from "
1116  "ConnectByNameNotifySenderObject redefined in "
1117  "ConnectDisconnectNotifyShadowObject";
1119 #endif
1120  QVERIFY(QObject::connect(&s, SIGNAL(signal1()), &s, SLOT(slot1())));
1121  QCOMPARE(s.connectedSignals.size(), 1);
1122  QCOMPARE(s.connectedSignals.at(0), redefinedSignal1);
1123  QVERIFY(s.disconnectedSignals.isEmpty());
1124 
1125  // Test disconnectNotify
1126 #ifndef QT_NO_DEBUG
1128 #endif
1129  QVERIFY(QObject::disconnect(&s, SIGNAL(signal1()), &s, SLOT(slot1())));
1130  QCOMPARE(s.disconnectedSignals.size(), 1);
1131  QCOMPARE(s.disconnectedSignals.at(0), redefinedSignal1);
1132  QCOMPARE(s.connectedSignals.size(), 1);
1133 
1134  // Test connectNotify when connecting by shadowed QMetaMethod
1135  s.clearNotifications();
1136  QVERIFY(QObject::connect(&s, shadowedSignal1, &s, slot1));
1137  QCOMPARE(s.connectedSignals.size(), 1);
1138  QCOMPARE(s.connectedSignals.at(0), shadowedSignal1);
1139  QVERIFY(s.disconnectedSignals.isEmpty());
1140 
1141  // Test disconnectNotify when disconnecting by shadowed QMetaMethod
1142  QVERIFY(QObject::disconnect(&s, shadowedSignal1, &s, slot1));
1143  QCOMPARE(s.disconnectedSignals.size(), 1);
1144  QCOMPARE(s.disconnectedSignals.at(0), shadowedSignal1);
1145  QCOMPARE(s.connectedSignals.size(), 1);
1146 
1147  // Test connectNotify when connecting by redefined QMetaMethod
1148  s.clearNotifications();
1149  QVERIFY(QObject::connect(&s, redefinedSignal1, &s, slot1));
1150  QCOMPARE(s.connectedSignals.size(), 1);
1151  QCOMPARE(s.connectedSignals.at(0), redefinedSignal1);
1152  QVERIFY(s.disconnectedSignals.isEmpty());
1153 
1154  // Test disconnectNotify when disconnecting by redefined QMetaMethod
1155  QVERIFY(QObject::disconnect(&s, redefinedSignal1, &s, slot1));
1156  QCOMPARE(s.disconnectedSignals.size(), 1);
1157  QCOMPARE(s.disconnectedSignals.at(0), redefinedSignal1);
1158  QCOMPARE(s.connectedSignals.size(), 1);
1159 }
1160 
1162 {
1163  Q_OBJECT
1164 
1165 public:
1168 
1169 public slots:
1171  {
1172  slot1();
1173  disconnect(sender(), SIGNAL(signal1()), this, SLOT(slot1_disconnectThis()));
1174  }
1175 
1177  {
1178  slot2();
1179 
1180  const QObject *s = sender();
1181  disconnect(s, SIGNAL(signal1()), this, SLOT(slot2_reconnectThis()));
1182  connect(s, SIGNAL(signal1()), this, SLOT(slot2_reconnectThis()));
1183  }
1184 
1186  {
1187  slot1();
1188  disconnect(sender(), SIGNAL(signal1()), next, SLOT(slot1()));
1189  }
1190 
1192  {
1193  slot2();
1194 
1195  // modify the connection list in 'this'
1196  disconnect(sender(), SIGNAL(signal1()), next, SLOT(slot2()));
1197  connect(sender(), SIGNAL(signal1()), next, SLOT(slot2()));
1198 
1199  // modify the sender list in 'this'
1200  connect(next, SIGNAL(destroyed()), this, SLOT(deleteLater()));
1201  connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(deleteLater()));
1203  disconnect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(deleteLater()));
1204  }
1205 
1207  {
1208  slot1();
1209  delete next;
1210  }
1211 
1213  {
1214  slot2();
1215  delete sender();
1216  }
1217 };
1218 
1219 void tst_QObject::emitInDefinedOrder()
1220 {
1222  ReceiverObject receiver1, receiver2, receiver3, receiver4;
1223 
1224  connect(&sender, SIGNAL(signal1()), &receiver1, SLOT(slot1()));
1225  connect(&sender, SIGNAL(signal1()), &receiver2, SLOT(slot1()));
1226  connect(&sender, SIGNAL(signal1()), &receiver3, SLOT(slot1()));
1227  connect(&sender, SIGNAL(signal1()), &receiver4, SLOT(slot1()));
1228  connect(&sender, SIGNAL(signal1()), &receiver1, SLOT(slot2()));
1229  connect(&sender, SIGNAL(signal1()), &receiver2, SLOT(slot2()));
1230  connect(&sender, SIGNAL(signal1()), &receiver3, SLOT(slot2()));
1231  connect(&sender, SIGNAL(signal1()), &receiver4, SLOT(slot2()));
1232 
1233  int sequence;
1234  ReceiverObject::sequence = sequence = 0;
1235  sender.emitSignal1();
1236  QCOMPARE(receiver1.sequence_slot1, ++sequence);
1237  QCOMPARE(receiver2.sequence_slot1, ++sequence);
1238  QCOMPARE(receiver3.sequence_slot1, ++sequence);
1239  QCOMPARE(receiver4.sequence_slot1, ++sequence);
1240  QCOMPARE(receiver1.sequence_slot2, ++sequence);
1241  QCOMPARE(receiver2.sequence_slot2, ++sequence);
1242  QCOMPARE(receiver3.sequence_slot2, ++sequence);
1243  QCOMPARE(receiver4.sequence_slot2, ++sequence);
1244 
1245  QObject::disconnect(&sender, SIGNAL(signal1()), &receiver2, SLOT(slot1()));
1246  connect(&sender, SIGNAL(signal1()), &receiver2, SLOT(slot1()));
1247 
1248  ReceiverObject::sequence = sequence = 0;
1249  sender.emitSignal1();
1250  QCOMPARE(receiver1.sequence_slot1, ++sequence);
1251  QCOMPARE(receiver3.sequence_slot1, ++sequence);
1252  QCOMPARE(receiver4.sequence_slot1, ++sequence);
1253  QCOMPARE(receiver1.sequence_slot2, ++sequence);
1254  QCOMPARE(receiver2.sequence_slot2, ++sequence);
1255  QCOMPARE(receiver3.sequence_slot2, ++sequence);
1256  QCOMPARE(receiver4.sequence_slot2, ++sequence);
1257  QCOMPARE(receiver2.sequence_slot1, ++sequence);
1258 
1259  QObject::disconnect(&sender, SIGNAL(signal1()), &receiver1, SLOT(slot1()));
1260  connect(&sender, SIGNAL(signal1()), &receiver1, SLOT(slot1()));
1261 
1262  ReceiverObject::sequence = sequence = 0;
1263  sender.emitSignal1();
1264  QCOMPARE(receiver3.sequence_slot1, ++sequence);
1265  QCOMPARE(receiver4.sequence_slot1, ++sequence);
1266  QCOMPARE(receiver1.sequence_slot2, ++sequence);
1267  QCOMPARE(receiver2.sequence_slot2, ++sequence);
1268  QCOMPARE(receiver3.sequence_slot2, ++sequence);
1269  QCOMPARE(receiver4.sequence_slot2, ++sequence);
1270  QCOMPARE(receiver2.sequence_slot1, ++sequence);
1271  QCOMPARE(receiver1.sequence_slot1, ++sequence);
1272 
1273  // ensure emission order even if the connections change during emission
1274  SenderObject *sender2 = new SenderObject;
1275  SequenceObject seq1, seq2, *seq3 = new SequenceObject, seq4;
1276  seq1.next = &seq2;
1277  seq2.next = seq3;
1278  seq3->next = &seq4;
1279 
1280  // try 1
1281  connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot1_disconnectThis()));
1282  connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot1_disconnectNext()));
1283  connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot1()));
1284  connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot1()));
1285  connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot2_reconnectThis()));
1286  connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot2_reconnectNext()));
1287  connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot2()));
1288  connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot2()));
1289 
1290  SequenceObject::sequence = sequence = 0;
1291  sender2->emitSignal1();
1292  QVERIFY(seq1.called(1));
1293  QVERIFY(seq2.called(1));
1294  QVERIFY(!seq3->called(1));
1295  QVERIFY(seq4.called(1));
1296  QVERIFY(seq1.called(2));
1297  QVERIFY(seq2.called(2));
1298  QVERIFY(!seq3->called(2));
1299  QVERIFY(seq4.called(2));
1300  QCOMPARE(seq1.sequence_slot1, ++sequence);
1301  QCOMPARE(seq2.sequence_slot1, ++sequence);
1302  QCOMPARE(seq4.sequence_slot1, ++sequence);
1303  QCOMPARE(seq1.sequence_slot2, ++sequence);
1304  QCOMPARE(seq2.sequence_slot2, ++sequence);
1305  QCOMPARE(seq4.sequence_slot2, ++sequence);
1306 
1307  QObject::disconnect(sender2, 0, &seq1, 0);
1308  QObject::disconnect(sender2, 0, &seq2, 0);
1309  QObject::disconnect(sender2, 0, seq3, 0);
1310  QObject::disconnect(sender2, 0, &seq4, 0);
1311  seq1.reset();
1312  seq2.reset();
1313  seq3->reset();
1314  seq4.reset();
1315 
1316  // try 2
1317  connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot2_reconnectThis()));
1318  connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot2_reconnectNext()));
1319  connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot2()));
1320  connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot2()));
1321  connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot1_disconnectThis()));
1322  connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot1_disconnectNext()));
1323  connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot1()));
1324  connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot1()));
1325 
1326  SequenceObject::sequence = sequence = 0;
1327  sender2->emitSignal1();
1328  QVERIFY(seq1.called(2));
1329  QVERIFY(seq2.called(2));
1330  QVERIFY(!seq3->called(2));
1331  QVERIFY(seq4.called(2));
1332  QVERIFY(seq1.called(1));
1333  QVERIFY(seq2.called(1));
1334  QVERIFY(!seq3->called(1));
1335  QVERIFY(seq4.called(1));
1336  QCOMPARE(seq1.sequence_slot2, ++sequence);
1337  QCOMPARE(seq2.sequence_slot2, ++sequence);
1338  QCOMPARE(seq4.sequence_slot2, ++sequence);
1339  QCOMPARE(seq1.sequence_slot1, ++sequence);
1340  QCOMPARE(seq2.sequence_slot1, ++sequence);
1341  QCOMPARE(seq4.sequence_slot1, ++sequence);
1342 
1343  QObject::disconnect(sender2, 0, &seq1, 0);
1344  QObject::disconnect(sender2, 0, &seq2, 0);
1345  QObject::disconnect(sender2, 0, seq3, 0);
1346  QObject::disconnect(sender2, 0, &seq4, 0);
1347  seq1.reset();
1348  seq2.reset();
1349  seq3->reset();
1350  seq4.reset();
1351 
1352  // try 3
1353  connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot1()));
1354  connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot1_disconnectNext()));
1355  connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot1()));
1356  connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot1()));
1357  connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot2()));
1358  connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot2_reconnectNext()));
1359  connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot2()));
1360  connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot2()));
1361 
1362  SequenceObject::sequence = sequence = 0;
1363  sender2->emitSignal1();
1364  QVERIFY(seq1.called(1));
1365  QVERIFY(seq2.called(1));
1366  QVERIFY(!seq3->called(1));
1367  QVERIFY(seq4.called(1));
1368  QVERIFY(seq1.called(2));
1369  QVERIFY(seq2.called(2));
1370  QVERIFY(!seq3->called(2));
1371  QVERIFY(seq4.called(2));
1372  QCOMPARE(seq1.sequence_slot1, ++sequence);
1373  QCOMPARE(seq2.sequence_slot1, ++sequence);
1374  QCOMPARE(seq4.sequence_slot1, ++sequence);
1375  QCOMPARE(seq1.sequence_slot2, ++sequence);
1376  QCOMPARE(seq2.sequence_slot2, ++sequence);
1377  QCOMPARE(seq4.sequence_slot2, ++sequence);
1378 
1379  // ensure emission order even if objects are destroyed during emission
1380  QObject::disconnect(sender2, 0, &seq1, 0);
1381  QObject::disconnect(sender2, 0, &seq2, 0);
1382  QObject::disconnect(sender2, 0, seq3, 0);
1383  QObject::disconnect(sender2, 0, &seq4, 0);
1384  seq1.reset();
1385  seq2.reset();
1386  seq3->reset();
1387  seq4.reset();
1388 
1389  connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot1()));
1390  connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot1_deleteNext()));
1391  connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot1()));
1392  connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot1()));
1393  connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot2()));
1394  connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot2_deleteSender()));
1395  connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot2()));
1396  connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot2()));
1397 
1398  QPointer<SenderObject> psender = sender2;
1399  QPointer<SequenceObject> pseq3 = seq3;
1400 
1401  SequenceObject::sequence = sequence = 0;
1402  sender2->emitSignal1();
1403  QCOMPARE(static_cast<QObject *>(psender), static_cast<QObject *>(0));
1404  QCOMPARE(static_cast<QObject *>(pseq3), static_cast<QObject *>(0));
1405  QVERIFY(seq1.called(1));
1406  QVERIFY(seq2.called(1));
1407  QVERIFY(seq4.called(1));
1408  QVERIFY(seq1.called(2));
1409  QVERIFY(seq2.called(2));
1410  QVERIFY(!seq4.called(2));
1411  QCOMPARE(seq1.sequence_slot1, ++sequence);
1412  QCOMPARE(seq2.sequence_slot1, ++sequence);
1413  QCOMPARE(seq4.sequence_slot1, ++sequence);
1414  QCOMPARE(seq1.sequence_slot2, ++sequence);
1415  QCOMPARE(seq2.sequence_slot2, ++sequence);
1416 
1417  QPointer<SenderObject> psender3 = new SenderObject;
1418  connect(psender3, SIGNAL(signal1()), psender3, SIGNAL(signal2()));
1419  connect(psender3, SIGNAL(signal2()), &seq1, SLOT(slot2_deleteSender()));
1420  psender3->emitSignal1();
1421  QVERIFY(!psender3);
1422 }
1423 
1424 static int instanceCount = 0;
1425 
1427 {
1428  const int saved;
1429  CheckInstanceCount() : saved(instanceCount) {}
1430  ~CheckInstanceCount() { QCOMPARE(saved, instanceCount); }
1431 };
1432 
1433 
1434 struct CustomType
1435 {
1436  CustomType(int l1 = 0, int l2 = 0, int l3 = 0): i1(l1), i2(l2), i3(l3)
1437  { ++instanceCount; playWithObjects(); }
1439  { ++instanceCount; playWithObjects(); }
1440  ~CustomType() { --instanceCount; playWithObjects(); }
1441  CustomType &operator=(const CustomType &) = default;
1442 
1443  int i1, i2, i3;
1444  int value() { return i1 + i2 + i3; }
1445 };
1446 
1448 {
1449  stream << ct.i1 << ct.i2 << ct.i3;
1450  return stream;
1451 }
1452 
1454 {
1455  stream >> ct.i1;
1456  stream >> ct.i2;
1457  stream >> ct.i3;
1458  return stream;
1459 }
1460 
1463 
1465 {
1466  Q_OBJECT
1467 
1468 public:
1471  { emit signal1(ct); }
1472 
1473 public slots:
1474  void slot1(CustomType ct);
1475  void slot2(const QList<CustomType> &ct);
1476 
1477 signals:
1479  void signal2(const QList<CustomType> &ct);
1480 
1481 public:
1482  CustomType received;
1483 };
1484 
1486 { received = ct; }
1487 
1489 { received = ct[0]; }
1490 
1491 void tst_QObject::customTypes()
1492 {
1493  CustomType t0;
1494  CustomType t1(1, 2, 3);
1495  CustomType t2(2, 3, 4);
1496 
1497  {
1498  QCustomTypeChecker checker;
1499  QCOMPARE(instanceCount, 4);
1500 
1501  connect(&checker, SIGNAL(signal1(CustomType)), &checker, SLOT(slot1(CustomType)),
1503  QCOMPARE(checker.received.value(), 0);
1504  checker.doEmit(t1);
1505  QCOMPARE(checker.received.value(), t1.value());
1506  checker.received = t0;
1507 
1508  int idx = qRegisterMetaType<CustomType>("CustomType");
1509  QCOMPARE(QMetaType::type("CustomType"), idx);
1510 
1511  checker.disconnect();
1512  connect(&checker, SIGNAL(signal1(CustomType)), &checker, SLOT(slot1(CustomType)),
1514  QCOMPARE(instanceCount, 4);
1515  checker.doEmit(t2);
1516  QCOMPARE(instanceCount, 5);
1517  QCOMPARE(checker.received.value(), t0.value());
1518 
1520  QCOMPARE(checker.received.value(), t2.value());
1521  QCOMPARE(instanceCount, 4);
1522 
1524  QCOMPARE(qRegisterMetaType<CustomType>("CustomType"), idx);
1525  QCOMPARE(QMetaType::type("CustomType"), idx);
1527  }
1528  QCOMPARE(instanceCount, 3);
1529 }
1530 
1531 void tst_QObject::streamCustomTypes()
1532 {
1533  QByteArray ba;
1534 
1535  int idx = qRegisterMetaType<CustomType>("CustomType");
1536 
1537  {
1538  CustomType t1(1, 2, 3);
1539  QCOMPARE(instanceCount, 1);
1540  QDataStream stream(&ba, (QIODevice::OpenMode)QIODevice::WriteOnly);
1542  }
1543 
1544  QCOMPARE(instanceCount, 0);
1545 
1546  {
1547  CustomType t2;
1548  QCOMPARE(instanceCount, 1);
1549  QDataStream stream(&ba, (QIODevice::OpenMode)QIODevice::ReadOnly);
1551  QCOMPARE(instanceCount, 1);
1552  QCOMPARE(t2.i1, 1);
1553  QCOMPARE(t2.i2, 2);
1554  QCOMPARE(t2.i3, 3);
1555  }
1556  QCOMPARE(instanceCount, 0);
1557 }
1558 
1560 
1561 class PropertyObject : public QObject
1562 {
1563  Q_OBJECT
1564 
1565  Q_PROPERTY(Alpha alpha READ alpha WRITE setAlpha)
1567  Q_PROPERTY(int number READ number WRITE setNumber)
1568  Q_PROPERTY(QString string READ string WRITE setString)
1571  Q_PROPERTY(float myFloat READ myFloat WRITE setMyFloat)
1574 
1575 public:
1576  enum Alpha {
1579  Alpha2
1580  };
1581 
1583 
1585  : m_alpha(Alpha0), m_priority(High), m_number(0), m_custom(0), m_float(42)
1586  {}
1587 
1588  Alpha alpha() const { return m_alpha; }
1589  void setAlpha(Alpha alpha) { m_alpha = alpha; }
1590 
1591  Priority priority() const { return m_priority; }
1592  void setPriority(Priority priority) { m_priority = priority; }
1593 
1594  int number() const { return m_number; }
1595  void setNumber(int number) { m_number = number; }
1596 
1597  QString string() const { return m_string; }
1598  void setString(const QString &string) { m_string = string; }
1599 
1600  QVariant variant() const { return m_variant; }
1601  void setVariant(const QVariant &variant) { m_variant = variant; }
1602 
1603  CustomType *custom() const { return m_custom; }
1604  void setCustom(CustomType *custom) { m_custom = custom; }
1605 
1606  void setMyFloat(float value) { m_float = value; }
1607  inline float myFloat() const { return m_float; }
1608 
1609  void setMyQReal(qreal value) { m_qreal = value; }
1610  qreal myQReal() const { return m_qreal; }
1611 
1612  CustomString customString() const { return m_customString; }
1613  void setCustomString(const QString &string) { m_customString = string; }
1614 
1615 private:
1616  Alpha m_alpha;
1617  Priority m_priority;
1618  int m_number;
1619  QString m_string;
1620  QVariant m_variant;
1621  CustomType *m_custom;
1622  float m_float;
1623  qreal m_qreal;
1624  CustomString m_customString;
1625 
1626  Q_ENUM(Alpha)
1627  Q_ENUM(Priority)
1628 };
1629 
1631 
1632 void tst_QObject::threadSignalEmissionCrash()
1633 {
1634  int loopCount = 1000;
1635  for (int i = 0; i < loopCount; ++i) {
1637  socket.connectToHost("localhost", 80);
1638  }
1639 }
1640 
1641 class TestThread : public QThread
1642 {
1643  Q_OBJECT
1644 public:
1645  inline void run() override
1646  {
1647  *object = new QObject;
1648  *child = new QObject(*object);
1649  mutex.lock();
1650  cond.wakeOne();
1651  cond.wait(&mutex);
1652  mutex.unlock();
1653  }
1654 
1658 };
1659 
1660 void tst_QObject::thread()
1661 {
1662  QThread *currentThread = QThread::currentThread();
1663  // the current thread is the same as the QApplication
1664  // thread... see tst_QApplication::thread()
1665 
1666  {
1667  QObject object;
1668  // thread affinity for objects with no parent should be the
1669  // current thread
1670  QVERIFY(object.thread() != nullptr);
1671  QCOMPARE(object.thread(), currentThread);
1672  // children inherit their parent's thread
1673  QObject child(&object);
1674  QCOMPARE(child.thread(), object.thread());
1675  }
1676 
1677  QObject *object = nullptr;
1678  QObject *child = nullptr;
1679 
1680  {
1681  TestThread thr;
1682  QVERIFY(thr.thread() != nullptr);
1683  QCOMPARE(thr.thread(), currentThread);
1684 
1685  thr.object = &object;
1686  thr.child = &child;
1687 
1688  thr.mutex.lock();
1689  thr.start();
1690  thr.cond.wait(&thr.mutex);
1691 
1692  // thread affinity for an object with no parent should be the
1693  // thread in which the object was created
1694  QCOMPARE(object->thread(), (QThread *)&thr);
1695  // children inherit their parent's thread
1696  QCOMPARE(child->thread(), object->thread());
1697 
1698  thr.cond.wakeOne();
1699  thr.mutex.unlock();
1700  thr.wait();
1701 
1702  // even though the thread is no longer running, the affinity
1703  // should not change
1704  QCOMPARE(object->thread(), (QThread *)&thr);
1705  QCOMPARE(child->thread(), object->thread());
1706  }
1707 
1708  // the thread has been destroyed, thread affinity should
1709  // automatically reset to no thread
1710  QCOMPARE(object->thread(), (QThread *)0);
1711  QCOMPARE(child->thread(), object->thread());
1712 
1713  delete object;
1714 }
1715 
1717 {
1718  Q_OBJECT
1719 public:
1722  QThread *slotThread = nullptr;
1723 
1725  : QObject(parent)
1726  { }
1727 
1728  void customEvent(QEvent *) override
1729  {
1730  if (customEventThread)
1731  qFatal("%s: customEventThread should be null", Q_FUNC_INFO);
1733  emit theSignal();
1734  }
1735 
1736  void timerEvent(QTimerEvent *) override
1737  {
1738  if (timerEventThread)
1739  qFatal("%s: timerEventThread should be null", Q_FUNC_INFO);
1741  emit theSignal();
1742  }
1743 
1744 public slots:
1745  void theSlot()
1746  {
1747  if (slotThread)
1748  qFatal("%s: slotThread should be null", Q_FUNC_INFO);
1750  emit theSignal();
1751  }
1752 
1753 signals:
1754  void theSignal();
1755 };
1756 
1758 {
1759 public:
1761  {
1762  if (isRunning()) {
1763  terminate();
1764  wait();
1765  }
1766  }
1767  void start()
1768  {
1769  QEventLoop eventLoop;
1770  connect(this, SIGNAL(started()), &eventLoop, SLOT(quit()), Qt::QueuedConnection);
1771  QThread::start();
1772  // wait for thread to start
1773  (void) eventLoop.exec();
1774  }
1775  void run() override
1776  { (void) exec(); }
1777 };
1778 
1779 void tst_QObject::thread0()
1780 {
1781  QObject *object = new QObject;
1782  object->moveToThread(0);
1783  QObject *child = new QObject(object);
1784  QCOMPARE(child->parent(), object);
1785  QCOMPARE(child->thread(), (QThread *)0);
1786 
1787 #if 0
1788  // We don't support moving children into a parent that has no thread
1789  // affinity (yet?).
1790  QObject *child2 = new QObject;
1791  child2->moveToThread(0);
1792  child2->setParent(object);
1793  QCOMPARE(child2->parent(), object);
1794  QCOMPARE(child2->thread(), (QThread *)0);
1795 #endif
1796 
1797  delete object;
1798 }
1799 
1800 void tst_QObject::moveToThread()
1801 {
1802  QThread *currentThread = QThread::currentThread();
1803 
1804  {
1805  QObject *object = new QObject;
1806  QObject *child = new QObject(object);
1807  QCOMPARE(object->thread(), currentThread);
1808  QCOMPARE(child->thread(), currentThread);
1809  object->moveToThread(0);
1810  QCOMPARE(object->thread(), (QThread *)0);
1811  QCOMPARE(child->thread(), (QThread *)0);
1812  object->moveToThread(currentThread);
1813  QCOMPARE(object->thread(), currentThread);
1814  QCOMPARE(child->thread(), currentThread);
1815  object->moveToThread(0);
1816  QCOMPARE(object->thread(), (QThread *)0);
1817  QCOMPARE(child->thread(), (QThread *)0);
1818  // can delete an object with no thread anywhere
1819  delete object;
1820  }
1821 
1822  {
1823  MoveToThreadThread thread;
1824  thread.start();
1825 
1826  QObject *object = new QObject;
1827  QObject *child = new QObject(object);
1828  QPointer<QObject> opointer = object;
1829  QPointer<QObject> cpointer = object;
1830 
1831  QCOMPARE(object->thread(), currentThread);
1832  QCOMPARE(child->thread(), currentThread);
1833  object->moveToThread(&thread);
1834  QCOMPARE(object->thread(), (QThread *)&thread);
1835  QCOMPARE(child->thread(), (QThread *)&thread);
1836 
1837  connect(object, SIGNAL(destroyed()), &thread, SLOT(quit()), Qt::DirectConnection);
1838  QMetaObject::invokeMethod(object, "deleteLater", Qt::QueuedConnection);
1839  thread.wait();
1840 
1841  QVERIFY(opointer == nullptr);
1842  QVERIFY(cpointer == nullptr);
1843  }
1844 
1845  {
1846  // make sure posted events are moved with the object
1847  MoveToThreadThread thread;
1848  thread.start();
1849 
1850  MoveToThreadObject *object = new MoveToThreadObject;
1852 
1853  connect(object, SIGNAL(theSignal()), &thread, SLOT(quit()), Qt::DirectConnection);
1856 
1857  QCOMPARE(object->thread(), currentThread);
1858  QCOMPARE(child->thread(), currentThread);
1859  object->moveToThread(&thread);
1860  QCOMPARE(object->thread(), (QThread *)&thread);
1861  QCOMPARE(child->thread(), (QThread *)&thread);
1862 
1863  thread.wait();
1864 
1865  QCOMPARE(object->customEventThread, (QThread *)&thread);
1866  QCOMPARE(child->customEventThread, (QThread *)&thread);
1867 
1868  thread.start();
1869  connect(object, SIGNAL(destroyed()), &thread, SLOT(quit()), Qt::DirectConnection);
1870  QMetaObject::invokeMethod(object, "deleteLater", Qt::QueuedConnection);
1871  thread.wait();
1872  }
1873 
1874  {
1875  // make sure timers are moved with the object
1876  MoveToThreadThread thread;
1877  thread.start();
1878 
1879  MoveToThreadObject *object = new MoveToThreadObject;
1881 
1882  connect(object, SIGNAL(theSignal()), &thread, SLOT(quit()), Qt::DirectConnection);
1883 
1884  child->startTimer(90);
1885  object->startTimer(100);
1886 
1887  QCOMPARE(object->thread(), currentThread);
1888  QCOMPARE(child->thread(), currentThread);
1889  object->moveToThread(&thread);
1890  QCOMPARE(object->thread(), (QThread *)&thread);
1891  QCOMPARE(child->thread(), (QThread *)&thread);
1892 
1893  thread.wait();
1894 
1895  QCOMPARE(object->timerEventThread, (QThread *)&thread);
1896  QCOMPARE(child->timerEventThread, (QThread *)&thread);
1897 
1898  thread.start();
1899  connect(object, SIGNAL(destroyed()), &thread, SLOT(quit()), Qt::DirectConnection);
1900  QMetaObject::invokeMethod(object, "deleteLater", Qt::QueuedConnection);
1901  thread.wait();
1902  }
1903 
1904  {
1905  // make sure socket notifiers are moved with the object
1906  MoveToThreadThread thread;
1907  thread.start();
1908 
1911  QTcpSocket *socket = new QTcpSocket;
1913  connect(socket, SIGNAL(disconnected()), child, SLOT(theSlot()), Qt::DirectConnection);
1914  connect(child, SIGNAL(theSignal()), &thread, SLOT(quit()), Qt::DirectConnection);
1915 
1916  socket->connectToHost(server.serverAddress(), server.serverPort());
1917 
1918  QVERIFY(server.waitForNewConnection(1000));
1919  QTcpSocket *serverSocket = server.nextPendingConnection();
1921 
1923 
1924  QCOMPARE(socket->thread(), currentThread);
1925  socket->moveToThread(&thread);
1926  QCOMPARE(socket->thread(), (QThread *)&thread);
1927 
1928  serverSocket->close();
1929 
1930  QVERIFY(thread.wait(10000));
1931 
1932  QCOMPARE(child->slotThread, (QThread *)&thread);
1933 
1934  thread.start();
1935  connect(socket, SIGNAL(destroyed()), &thread, SLOT(quit()), Qt::DirectConnection);
1937  thread.wait();
1938  }
1939 }
1940 
1941 
1942 void tst_QObject::property()
1943 {
1945  const QMetaObject *mo = object.metaObject();
1946  QMetaProperty property;
1947  QVERIFY(mo);
1948 
1949  QVERIFY(mo->indexOfProperty("alpha") != -1);
1950  property = mo->property(mo->indexOfProperty("alpha"));
1951  QVERIFY(property.isEnumType());
1952  QCOMPARE(property.typeName(), "PropertyObject::Alpha");
1953  QCOMPARE(property.userType(), QMetaType::fromType<PropertyObject::Alpha>().id());
1954 
1955  QVariant var = object.property("alpha");
1956  QVERIFY(!var.isNull());
1958  object.setAlpha(PropertyObject::Alpha1);
1959  QCOMPARE(object.property("alpha").toInt(), int(PropertyObject::Alpha1));
1960  QVERIFY(object.setProperty("alpha", PropertyObject::Alpha2));
1961  QCOMPARE(object.property("alpha").toInt(), int(PropertyObject::Alpha2));
1962  QVERIFY(object.setProperty("alpha", "Alpha1"));
1963  QCOMPARE(object.property("alpha").toInt(), int(PropertyObject::Alpha1));
1964  QVERIFY(object.setProperty("alpha", QVariant()));
1965  QCOMPARE(object.property("alpha").toInt(), 0);
1966 
1967  QVERIFY(mo->indexOfProperty("number") != -1);
1968  QCOMPARE(object.property("number").toInt(), 0);
1969  object.setNumber(24);
1970  QCOMPARE(object.property("number"), QVariant(24));
1971  QVERIFY(object.setProperty("number", 12));
1972  QCOMPARE(object.property("number"), QVariant(12));
1973  QVERIFY(object.setProperty("number", "42"));
1974  QCOMPARE(object.property("number"), QVariant(42));
1975 
1976  QVERIFY(mo->indexOfProperty("string") != -1);
1977  QCOMPARE(object.property("string").toString(), QString());
1978  object.setString("String1");
1979  QCOMPARE(object.property("string"), QVariant("String1"));
1980  QVERIFY(object.setProperty("string", "String2"));
1981  QCOMPARE(object.property("string"), QVariant("String2"));
1982  QVERIFY(object.setProperty("string", QVariant()));
1983 
1984  const int idx = mo->indexOfProperty("variant");
1985  QVERIFY(idx != -1);
1986  QCOMPARE(QMetaType::Type(mo->property(idx).type()), QMetaType::QVariant);
1987  QCOMPARE(object.property("variant"), QVariant());
1988  QVariant variant1(42);
1989  QVariant variant2("string");
1990  object.setVariant(variant1);
1991  QCOMPARE(object.property("variant"), variant1);
1992  QVERIFY(object.setProperty("variant", variant2));
1993  QCOMPARE(object.variant(), QVariant(variant2));
1994  QCOMPARE(object.property("variant"), variant2);
1995  QVERIFY(object.setProperty("variant", QVariant()));
1996  QCOMPARE(object.property("variant"), QVariant());
1997 
1998  QVERIFY(mo->indexOfProperty("custom") != -1);
1999  property = mo->property(mo->indexOfProperty("custom"));
2000  QVERIFY(property.isValid());
2001  QVERIFY(property.isWritable());
2002  QVERIFY(!property.isEnumType());
2003  QCOMPARE(property.typeName(), "CustomType*");
2004  qRegisterMetaType<CustomType*>();
2005  QCOMPARE(property.type(), QVariant::UserType);
2006  QCOMPARE(property.userType(), qMetaTypeId<CustomType*>());
2007 
2008  CustomType *customPointer = nullptr;
2009  QVariant customVariant = object.property("custom");
2010  customPointer = qvariant_cast<CustomType *>(customVariant);
2011  QCOMPARE(customPointer, object.custom());
2012 
2013  CustomType custom;
2014  customPointer = &custom;
2015  customVariant.setValue(customPointer);
2016 
2017  property = mo->property(mo->indexOfProperty("custom"));
2018  QVERIFY(property.isWritable());
2019  QCOMPARE(property.typeName(), "CustomType*");
2020  QCOMPARE(property.type(), QVariant::UserType);
2021  QCOMPARE(property.userType(), qMetaTypeId<CustomType*>());
2022 
2023  QVERIFY(object.setProperty("custom", customVariant));
2024  QCOMPARE(object.custom(), customPointer);
2025 
2026  customVariant = object.property("custom");
2027  customPointer = qvariant_cast<CustomType *>(customVariant);
2028  QCOMPARE(object.custom(), customPointer);
2029 
2030  // this enum property has a meta type, but it's not yet registered, so we know this fails
2031  QVERIFY(mo->indexOfProperty("priority") != -1);
2032  property = mo->property(mo->indexOfProperty("priority"));
2033  QVERIFY(property.isEnumType());
2034  QCOMPARE(property.typeName(), "PropertyObject::Priority");
2035  QCOMPARE(property.userType(), QMetaType::fromType<PropertyObject::Priority>().id());
2036 
2037  var = object.property("priority");
2038  QVERIFY(!var.isNull());
2040  object.setPriority(PropertyObject::Low);
2041  QCOMPARE(object.property("priority").toInt(), int(PropertyObject::Low));
2042  QVERIFY(object.setProperty("priority", PropertyObject::VeryHigh));
2043  QCOMPARE(object.property("priority").toInt(), int(PropertyObject::VeryHigh));
2044  QVERIFY(object.setProperty("priority", "High"));
2045  QCOMPARE(object.property("priority").toInt(), int(PropertyObject::High));
2046  QVERIFY(object.setProperty("priority", QVariant()));
2047  QCOMPARE(object.property("priority").toInt(), 0);
2048 
2049  // now it's registered, so it works as expected
2050  int priorityMetaTypeId = qRegisterMetaType<PropertyObject::Priority>("PropertyObject::Priority");
2051 
2052  QVERIFY(mo->indexOfProperty("priority") != -1);
2053  property = mo->property(mo->indexOfProperty("priority"));
2054  QVERIFY(property.isEnumType());
2055  QCOMPARE(property.typeName(), "PropertyObject::Priority");
2056  QCOMPARE(property.type(), QVariant::UserType);
2057  QCOMPARE(property.userType(), priorityMetaTypeId);
2058 
2059  var = object.property("priority");
2060  QVERIFY(!var.isNull());
2062  QCOMPARE(qvariant_cast<PropertyObject::Priority>(var), PropertyObject::High);
2063  object.setPriority(PropertyObject::Low);
2064  QCOMPARE(qvariant_cast<PropertyObject::Priority>(object.property("priority")), PropertyObject::Low);
2065  QVERIFY(object.setProperty("priority", PropertyObject::VeryHigh));
2066  QCOMPARE(qvariant_cast<PropertyObject::Priority>(object.property("priority")), PropertyObject::VeryHigh);
2067  QVERIFY(object.setProperty("priority", "High"));
2068  QCOMPARE(qvariant_cast<PropertyObject::Priority>(object.property("priority")), PropertyObject::High);
2069  QVERIFY(object.setProperty("priority", QVariant()));
2070  QCOMPARE(object.property("priority").toInt(), 0);
2071 
2072  var = object.property("priority");
2073  QCOMPARE(qvariant_cast<PropertyObject::Priority>(var), PropertyObject::High);
2074  object.setPriority(PropertyObject::Low);
2075  QCOMPARE(qvariant_cast<PropertyObject::Priority>(object.property("priority")), PropertyObject::Low);
2076  object.setProperty("priority", var);
2077  QCOMPARE(qvariant_cast<PropertyObject::Priority>(object.property("priority")), PropertyObject::High);
2078 
2079  qRegisterMetaType<CustomString>("CustomString");
2080  QVERIFY(mo->indexOfProperty("customString") != -1);
2081  QCOMPARE(object.property("customString").toString(), QString());
2082  object.setCustomString("String1");
2083  QCOMPARE(object.property("customString"), QVariant("String1"));
2084  QVERIFY(object.setProperty("customString", "String2"));
2085  QCOMPARE(object.property("customString"), QVariant("String2"));
2086  QVERIFY(object.setProperty("customString", QVariant()));
2087 }
2088 
2089 void tst_QObject::metamethod()
2090 {
2091  SenderObject obj;
2092  const QMetaObject *mobj = obj.metaObject();
2093  QMetaMethod m;
2094 
2095  m = mobj->method(mobj->indexOfMethod("invoke1()"));
2096  QVERIFY(m.methodSignature() == "invoke1()");
2097  QCOMPARE(m.methodType(), QMetaMethod::Method);
2098  QCOMPARE(m.access(), QMetaMethod::Public);
2099  QVERIFY(!(m.attributes() & QMetaMethod::Scriptable));
2100  QVERIFY(!(m.attributes() & QMetaMethod::Compatibility));
2101 
2102  m = mobj->method(mobj->indexOfMethod("sinvoke1()"));
2103  QVERIFY(m.methodSignature() == "sinvoke1()");
2104  QCOMPARE(m.methodType(), QMetaMethod::Method);
2105  QCOMPARE(m.access(), QMetaMethod::Public);
2106  QVERIFY((m.attributes() & QMetaMethod::Scriptable));
2107  QVERIFY(!(m.attributes() & QMetaMethod::Compatibility));
2108 
2109  m = mobj->method(mobj->indexOfMethod("invoke2()"));
2110  QVERIFY(m.methodSignature() == "invoke2()");
2111  QCOMPARE(m.methodType(), QMetaMethod::Method);
2112  QCOMPARE(m.access(), QMetaMethod::Protected);
2113  QVERIFY(!(m.attributes() & QMetaMethod::Scriptable));
2114  QVERIFY((m.attributes() & QMetaMethod::Compatibility));
2115 
2116  m = mobj->method(mobj->indexOfMethod("sinvoke2()"));
2117  QVERIFY(m.methodSignature() == "sinvoke2()");
2118  QCOMPARE(m.methodType(), QMetaMethod::Method);
2119  QCOMPARE(m.access(), QMetaMethod::Protected);
2120  QVERIFY((m.attributes() & QMetaMethod::Scriptable));
2121  QVERIFY((m.attributes() & QMetaMethod::Compatibility));
2122 
2123  m = mobj->method(mobj->indexOfMethod("invoke3()"));
2124  QVERIFY(m.methodSignature() == "invoke3()");
2125  QCOMPARE(m.methodType(), QMetaMethod::Method);
2126  QCOMPARE(m.access(), QMetaMethod::Private);
2127  QVERIFY(!(m.attributes() & QMetaMethod::Scriptable));
2128  QVERIFY(!(m.attributes() & QMetaMethod::Compatibility));
2129 
2130  m = mobj->method(mobj->indexOfMethod("sinvoke3()"));
2131  QVERIFY(m.methodSignature() == "sinvoke3()");
2132  QCOMPARE(m.methodType(), QMetaMethod::Method);
2133  QCOMPARE(m.access(), QMetaMethod::Private);
2134  QVERIFY((m.attributes() & QMetaMethod::Scriptable));
2135  QVERIFY(!(m.attributes() & QMetaMethod::Compatibility));
2136 
2137  m = mobj->method(mobj->indexOfMethod("signal5()"));
2138  QVERIFY(m.methodSignature() == "signal5()");
2139  QCOMPARE(m.methodType(), QMetaMethod::Signal);
2140  QCOMPARE(m.access(), QMetaMethod::Public);
2141  QVERIFY(!(m.attributes() & QMetaMethod::Scriptable));
2142  QVERIFY((m.attributes() & QMetaMethod::Compatibility));
2143 
2144  m = mobj->method(mobj->indexOfMethod("aPublicSlot()"));
2145  QVERIFY(m.methodSignature() == "aPublicSlot()");
2146  QCOMPARE(m.methodType(), QMetaMethod::Slot);
2147  QCOMPARE(m.access(), QMetaMethod::Public);
2148  QVERIFY(!(m.attributes() & QMetaMethod::Scriptable));
2149  QVERIFY(!(m.attributes() & QMetaMethod::Compatibility));
2150 
2151  m = mobj->method(mobj->indexOfMethod("invoke1()"));
2152  QCOMPARE(m.parameterNames().count(), 0);
2153  QCOMPARE(m.parameterTypes().count(), 0);
2154 
2155  m = mobj->method(mobj->indexOfMethod("invoke2(int)"));
2156  QCOMPARE(m.parameterNames().count(), 1);
2157  QCOMPARE(m.parameterTypes().count(), 1);
2158  QCOMPARE(m.parameterTypes().at(0), QByteArray("int"));
2159  QVERIFY(m.parameterNames().at(0).isEmpty());
2160 
2161  m = mobj->method(mobj->indexOfMethod("invoke3(int,int)"));
2162  QCOMPARE(m.parameterNames().count(), 2);
2163  QCOMPARE(m.parameterTypes().count(), 2);
2164  QCOMPARE(m.parameterTypes().at(0), QByteArray("int"));
2165  QCOMPARE(m.parameterNames().at(0), QByteArray("hinz"));
2166  QCOMPARE(m.parameterTypes().at(1), QByteArray("int"));
2167  QCOMPARE(m.parameterNames().at(1), QByteArray("kunz"));
2168 
2169 }
2170 
2171 namespace QObjectTest
2172 {
2173  class TestObject: public QObject
2174  {
2175  Q_OBJECT
2176  public:
2177  TestObject(): QObject(), i(0) {}
2178  void doEmit() { emit aSignal(); }
2179  int i;
2180  public slots:
2181  void aSlot() { ++i; }
2182  signals:
2183  void aSignal();
2184  };
2185 }
2186 
2187 void tst_QObject::namespaces()
2188 {
2190 
2191  QVERIFY(connect(&obj, SIGNAL(aSignal()), &obj, SLOT(aSlot())));
2192  obj.doEmit();
2193  QCOMPARE(obj.i, 1);
2194 }
2195 
2196 class SuperObject : public QObject
2197 {
2198  Q_OBJECT
2199 public:
2202 
2204  {
2205  theSender = nullptr;
2206  theSignalId = 0;
2207  }
2208 
2209  friend class tst_QObject;
2210 
2211  using QObject::sender;
2212 
2213 public slots:
2215  {
2216  theSender = sender();
2218  }
2219 
2221  {
2222  delete theSender;
2223  rememberSender();
2224  }
2225 signals:
2227  void theSignal();
2228 };
2229 
2230 void tst_QObject::senderTest()
2231 {
2232  {
2234  SuperObject receiver;
2235  connect(&sender, SIGNAL(anotherSignal()),
2236  &receiver, SLOT(rememberSender()));
2237  connect(&sender, SIGNAL(theSignal()),
2238  &receiver, SLOT(rememberSender()));
2239  QCOMPARE(receiver.sender(), (QObject *)0);
2240  QCOMPARE(receiver.senderSignalIndex(), -1);
2241  emit sender.theSignal();
2242  QCOMPARE(receiver.theSender, (QObject *)&sender);
2243  QCOMPARE(receiver.sender(), (QObject *)0);
2244  QCOMPARE(receiver.theSignalId,
2245  sender.metaObject()->indexOfSignal("theSignal()"));
2246  QCOMPARE(receiver.senderSignalIndex(), -1);
2247 
2248  emit sender.anotherSignal();
2249  QCOMPARE(receiver.theSignalId,
2250  sender.metaObject()->indexOfSignal("anotherSignal()"));
2251  QCOMPARE(receiver.senderSignalIndex(), -1);
2252  }
2253 
2254  {
2256  SuperObject *receiver = new SuperObject;
2257  connect(sender, SIGNAL(theSignal()),
2258  receiver, SLOT(rememberSender()),
2260 
2261  QThread thread;
2262  receiver->moveToThread(&thread);
2263  connect(sender, SIGNAL(theSignal()),
2264  &thread, SLOT(quit()),
2266 
2267  QCOMPARE(receiver->sender(), (QObject *)0);
2268  QCOMPARE(receiver->senderSignalIndex(), -1);
2269  receiver->theSender = nullptr;
2270  receiver->theSignalId = -1;
2271  thread.start();
2272  emit sender->theSignal();
2273  QCOMPARE(receiver->theSender, (QObject *) sender);
2274  QCOMPARE(receiver->sender(), (QObject *)0);
2275  QCOMPARE(receiver->theSignalId,
2276  sender->metaObject()->indexOfSignal("theSignal()"));
2277  QCOMPARE(receiver->senderSignalIndex(), -1);
2278 
2279  QVERIFY(thread.wait(10000));
2280  delete receiver;
2281  delete sender;
2282  }
2283 
2284  {
2286  SuperObject receiver;
2287  connect(sender, SIGNAL(theSignal()),
2288  &receiver, SLOT(deleteAndRememberSender()));
2289  QCOMPARE(receiver.sender(), (QObject *)0);
2290  receiver.theSender = sender;
2291  emit sender->theSignal();
2292  QCOMPARE(receiver.theSender, (QObject *)0);
2293  QCOMPARE(receiver.sender(), (QObject *)0);
2294  }
2295 
2296  {
2298  SuperObject *receiver = new SuperObject;
2299  connect(sender, SIGNAL(theSignal()),
2300  receiver, SLOT(deleteAndRememberSender()),
2302 
2303  QThread thread;
2304  receiver->moveToThread(&thread);
2306  &thread, SLOT(quit()),
2308 
2309  QCOMPARE(receiver->sender(), (QObject *)0);
2310  receiver->theSender = sender;
2311  thread.start();
2312  emit sender->theSignal();
2313  QCOMPARE(receiver->theSender, (QObject *)0);
2314  QCOMPARE(receiver->sender(), (QObject *)0);
2315 
2316  QVERIFY(thread.wait(10000));
2317  delete receiver;
2318  }
2319 }
2320 
2321 namespace Foo
2322 {
2323  struct Bar
2324  {
2325  virtual ~Bar() {}
2326  virtual int rtti() const = 0;
2327  };
2328 
2329  struct Bleh
2330  {
2331  virtual ~Bleh() {}
2332  virtual int rtti() const = 0;
2333  };
2334 }
2335 
2337 Q_DECLARE_INTERFACE(Foo::Bar, "com.qtest.foobar")
2339 
2340 #define Bleh_iid "com.qtest.bleh"
2344 
2345 class FooObject: public QObject, public Foo::Bar
2346 {
2347  Q_OBJECT
2349 public:
2350  int rtti() const override { return 42; }
2351 };
2352 
2353 class BlehObject : public QObject, public Foo::Bleh
2354 {
2355  Q_OBJECT
2357 public:
2358  int rtti() const override { return 43; }
2359 };
2360 
2361 void tst_QObject::declareInterface()
2362 {
2363  FooObject obj;
2364 
2365  Foo::Bar *bar = qobject_cast<Foo::Bar *>(&obj);
2366  QVERIFY(bar);
2367  QCOMPARE(bar->rtti(), 42);
2368  QCOMPARE(static_cast<Foo::Bar *>(&obj), bar);
2369 
2370  BlehObject bleh;
2371 
2372  bar = qobject_cast<Foo::Bar *>(&bleh);
2373  QVERIFY(!bar);
2374  Foo::Bleh *b = qobject_cast<Foo::Bleh *>(&bleh);
2375  QCOMPARE(b->rtti(), 43);
2376  QCOMPARE(static_cast<Foo::Bleh *>(&bleh), b);
2377 
2378 }
2379 
2381 {
2382  Q_OBJECT
2383 public:
2385 
2388 
2389 private slots:
2390  inline void otherObjectDestroyed()
2391  { pointerWasZero = pointer.isNull(); }
2392 };
2393 
2394 void tst_QObject::qpointerResetBeforeDestroyedSignal()
2395 {
2396  QObject *obj = new QObject;
2397  DestroyedListener listener;
2398  listener.pointer = obj;
2399  listener.pointerWasZero = false;
2400  connect(obj, SIGNAL(destroyed()), &listener, SLOT(otherObjectDestroyed()));
2401  delete obj;
2402  QVERIFY(listener.pointerWasZero);
2403  QVERIFY(listener.pointer.isNull());
2404 }
2405 
2407 {
2408  Q_OBJECT
2409 
2410 public slots:
2411 
2412  void theSlot(const QString &s) { result = s; }
2413 
2414 signals:
2416  void theSecondSignal(const QString &s = QString("secondDefault"));
2417 
2418 public:
2419 
2423 };
2424 
2425 void tst_QObject::connectSignalsToSignalsWithDefaultArguments()
2426 {
2428  connect(&o, SIGNAL(theOriginalSignal()), &o, SIGNAL(theSecondSignal()));
2429  connect(&o, SIGNAL(theSecondSignal(QString)), &o, SLOT(theSlot(QString)));
2430  QVERIFY( o.result.isEmpty() );
2431  o.emitTheSecondSignal();
2432  QCOMPARE(o.result, QString("secondDefault"));
2433  o.result = "Not called";
2434  o.emitTheOriginalSignal();
2435  QCOMPARE(o.result, QString("secondDefault"));
2436 
2437 }
2438 
2439 void tst_QObject::receivers()
2440 {
2441  class Object : public QObject
2442  {
2443  public:
2444  int receivers(const char* signal) const
2445  { return QObject::receivers(signal); }
2446  };
2447 
2448  Object object;
2449  QCOMPARE(object.receivers(SIGNAL(destroyed())), 0);
2450  object.connect(&object, SIGNAL(destroyed()), SLOT(deleteLater()));
2451  QCOMPARE(object.receivers(SIGNAL(destroyed())), 1);
2452  object.connect(&object, SIGNAL(destroyed()), SLOT(deleteLater()));
2453  QCOMPARE(object.receivers(SIGNAL(destroyed())), 2);
2454  object.disconnect(SIGNAL(destroyed()), &object, SLOT(deleteLater()));
2455  QCOMPARE(object.receivers(SIGNAL(destroyed())), 0);
2456 }
2457 
2458 enum Enum { };
2459 
2460 struct Struct { };
2461 class Class { };
2462 template <typename T> class Template { };
2463 
2464 class NormalizeObject : public QObject
2465 {
2466  Q_OBJECT
2467 
2468 public:
2469 
2470 signals:
2475 
2479 
2483 
2487 
2491 
2492  void unsignedintSignal(unsigned int);
2493  void unsignedSignal(unsigned);
2494  void unsignedlongSignal(unsigned long);
2496  void unsignedlongintSignal(unsigned long int);
2497  void unsignedshortSignal(unsigned short);
2498  void unsignedcharSignal(unsigned char);
2499 
2503 
2505 
2508 
2509 public slots:
2510  void uintPointerSlot(uint *) { }
2512  void constUintPointerSlot(const uint *) { }
2513  void constUlongPointerSlot(const ulong *) { }
2514 
2517  void enumSlot(Enum e) { Q_UNUSED(e); }
2518 
2522 
2525  void constEnumPointerSlot(const Enum *e) { Q_UNUSED(e); }
2526 
2529  void constEnumPointerConstPointerSlot(const Enum * const *e) { Q_UNUSED(e); }
2530 
2531  void uintSlot(uint) {};
2532  void unsignedintSlot(unsigned int) {};
2533  void unsignedSlot(unsigned) {};
2534  void unsignedlongSlot(unsigned long) {};
2536  void unsignedlongintSlot(unsigned long int) {};
2537  void unsignedshortSlot(unsigned short) {};
2538  void unsignedcharSlot(unsigned char) {};
2539 
2543 
2544  void typePointerConstRefSlot(Class * const &) {}
2545 
2549 };
2550 
2551 void tst_QObject::normalize()
2552 {
2554 
2555  // unsigned int -> uint, unsigned long -> ulong
2556  QVERIFY(object.connect(&object,
2557  SIGNAL(uintPointerSignal(uint *)),
2558  SLOT(uintPointerSlot(uint *))));
2559  QVERIFY(object.connect(&object,
2560  SIGNAL(uintPointerSignal(unsigned int *)),
2561  SLOT(uintPointerSlot(uint *))));
2562  QVERIFY(object.connect(&object,
2563  SIGNAL(uintPointerSignal(uint *)),
2564  SLOT(uintPointerSlot(unsigned int *))));
2565 
2566  QVERIFY(object.connect(&object,
2567  SIGNAL(constUintPointerSignal(const uint *)),
2568  SLOT(constUintPointerSlot(const uint *))));
2569  QVERIFY(object.connect(&object,
2570  SIGNAL(constUintPointerSignal(const unsigned int *)),
2571  SLOT(constUintPointerSlot(const uint *))));
2572  QVERIFY(object.connect(&object,
2573  SIGNAL(constUintPointerSignal(const uint *)),
2574  SLOT(constUintPointerSlot(const unsigned int *))));
2575 
2576  QVERIFY(object.connect(&object,
2577  SIGNAL(ulongPointerSignal(ulong *)),
2578  SLOT(ulongPointerSlot(ulong *))));
2579  QVERIFY(object.connect(&object,
2580  SIGNAL(ulongPointerSignal(unsigned long *)),
2581  SLOT(ulongPointerSlot(ulong *))));
2582  QVERIFY(object.connect(&object,
2583  SIGNAL(ulongPointerSignal(ulong *)),
2584  SLOT(ulongPointerSlot(unsigned long *))));
2585 
2586  QVERIFY(object.connect(&object,
2587  SIGNAL(constUlongPointerSignal(const ulong *)),
2588  SLOT(constUlongPointerSlot(const ulong *))));
2589  QVERIFY(object.connect(&object,
2590  SIGNAL(constUlongPointerSignal(const unsigned long *)),
2591  SLOT(constUlongPointerSlot(const ulong *))));
2592  QVERIFY(object.connect(&object,
2593  SIGNAL(constUlongPointerSignal(const ulong *)),
2594  SLOT(constUlongPointerSlot(const unsigned long *))));
2595 
2596  // struct, class, and enum are optional
2597  QVERIFY(object.connect(&object,
2598  SIGNAL(structSignal(struct Struct)),
2599  SLOT(structSlot(struct Struct))));
2600  QVERIFY(object.connect(&object,
2601  SIGNAL(structSignal(Struct)),
2602  SLOT(structSlot(struct Struct))));
2603  QVERIFY(object.connect(&object,
2604  SIGNAL(structSignal(struct Struct)),
2605  SLOT(structSlot(Struct))));
2606  QVERIFY(object.connect(&object,
2607  SIGNAL(classSignal(class Class)),
2608  SLOT(classSlot(class Class))));
2609  QVERIFY(object.connect(&object,
2610  SIGNAL(classSignal(Class)),
2611  SLOT(classSlot(class Class))));
2612  QVERIFY(object.connect(&object,
2613  SIGNAL(classSignal(class Class)),
2614  SLOT(classSlot(Class))));
2615  QVERIFY(object.connect(&object,
2616  SIGNAL(enumSignal(enum Enum)),
2617  SLOT(enumSlot(enum Enum))));
2618  QVERIFY(object.connect(&object,
2619  SIGNAL(enumSignal(Enum)),
2620  SLOT(enumSlot(enum Enum))));
2621  QVERIFY(object.connect(&object,
2622  SIGNAL(enumSignal(enum Enum)),
2623  SLOT(enumSlot(Enum))));
2624 
2625  QVERIFY(object.connect(&object,
2626  SIGNAL(structPointerSignal(struct Struct *)),
2627  SLOT(structPointerSlot(struct Struct *))));
2628  QVERIFY(object.connect(&object,
2629  SIGNAL(structPointerSignal(Struct *)),
2630  SLOT(structPointerSlot(struct Struct *))));
2631  QVERIFY(object.connect(&object,
2632  SIGNAL(structPointerSignal(struct Struct *)),
2633  SLOT(structPointerSlot(Struct *))));
2634  QVERIFY(object.connect(&object,
2635  SIGNAL(classPointerSignal(class Class *)),
2636  SLOT(classPointerSlot(class Class *))));
2637  QVERIFY(object.connect(&object,
2638  SIGNAL(classPointerSignal(Class *)),
2639  SLOT(classPointerSlot(class Class *))));
2640  QVERIFY(object.connect(&object,
2641  SIGNAL(classPointerSignal(class Class *)),
2642  SLOT(classPointerSlot(Class *))));
2643  QVERIFY(object.connect(&object,
2644  SIGNAL(enumPointerSignal(enum Enum *)),
2645  SLOT(enumPointerSlot(enum Enum *))));
2646  QVERIFY(object.connect(&object,
2647  SIGNAL(enumPointerSignal(Enum *)),
2648  SLOT(enumPointerSlot(enum Enum *))));
2649  QVERIFY(object.connect(&object,
2650  SIGNAL(enumPointerSignal(enum Enum *)),
2651  SLOT(enumPointerSlot(Enum *))));
2652 
2653  QVERIFY(object.connect(&object,
2654  SIGNAL(constStructPointerSignal(const struct Struct *)),
2655  SLOT(constStructPointerSlot(const struct Struct *))));
2656  QVERIFY(object.connect(&object,
2657  SIGNAL(constStructPointerSignal(const Struct *)),
2658  SLOT(constStructPointerSlot(const struct Struct *))));
2659  QVERIFY(object.connect(&object,
2660  SIGNAL(constStructPointerSignal(const struct Struct *)),
2661  SLOT(constStructPointerSlot(const Struct *))));
2662  QVERIFY(object.connect(&object,
2663  SIGNAL(constClassPointerSignal(const class Class *)),
2664  SLOT(constClassPointerSlot(const class Class *))));
2665  QVERIFY(object.connect(&object,
2666  SIGNAL(constClassPointerSignal(const Class *)),
2667  SLOT(constClassPointerSlot(const class Class *))));
2668  QVERIFY(object.connect(&object,
2669  SIGNAL(constClassPointerSignal(const class Class *)),
2670  SLOT(constClassPointerSlot(const Class *))));
2671  QVERIFY(object.connect(&object,
2672  SIGNAL(constEnumPointerSignal(const enum Enum *)),
2673  SLOT(constEnumPointerSlot(const enum Enum *))));
2674  QVERIFY(object.connect(&object,
2675  SIGNAL(constEnumPointerSignal(const Enum *)),
2676  SLOT(constEnumPointerSlot(const enum Enum *))));
2677  QVERIFY(object.connect(&object,
2678  SIGNAL(constEnumPointerSignal(const enum Enum *)),
2679  SLOT(constEnumPointerSlot(const Enum *))));
2680 
2681  QVERIFY(object.connect(&object,
2682  SIGNAL(constStructPointerSignal(struct Struct const *)),
2683  SLOT(constStructPointerSlot(struct Struct const *))));
2684  QVERIFY(object.connect(&object,
2685  SIGNAL(constStructPointerSignal(Struct const *)),
2686  SLOT(constStructPointerSlot(struct Struct const *))));
2687  QVERIFY(object.connect(&object,
2688  SIGNAL(constStructPointerSignal(struct Struct const *)),
2689  SLOT(constStructPointerSlot(Struct const *))));
2690  QVERIFY(object.connect(&object,
2691  SIGNAL(constClassPointerSignal(class Class const *)),
2692  SLOT(constClassPointerSlot(class Class const *))));
2693  QVERIFY(object.connect(&object,
2694  SIGNAL(constClassPointerSignal(Class const *)),
2695  SLOT(constClassPointerSlot(class Class const *))));
2696  QVERIFY(object.connect(&object,
2697  SIGNAL(constClassPointerSignal(class Class const *)),
2698  SLOT(constClassPointerSlot(Class const *))));
2699  QVERIFY(object.connect(&object,
2700  SIGNAL(constEnumPointerSignal(enum Enum const *)),
2701  SLOT(constEnumPointerSlot(enum Enum const *))));
2702  QVERIFY(object.connect(&object,
2703  SIGNAL(constEnumPointerSignal(Enum const *)),
2704  SLOT(constEnumPointerSlot(enum Enum const *))));
2705  QVERIFY(object.connect(&object,
2706  SIGNAL(constEnumPointerSignal(enum Enum const *)),
2707  SLOT(constEnumPointerSlot(Enum const *))));
2708 
2709  QVERIFY(object.connect(&object,
2710  SIGNAL(constStructPointerConstPointerSignal(const struct Struct * const *)),
2711  SLOT(constStructPointerConstPointerSlot(const struct Struct * const *))));
2712  QVERIFY(object.connect(&object,
2713  SIGNAL(constStructPointerConstPointerSignal(const Struct * const *)),
2714  SLOT(constStructPointerConstPointerSlot(const struct Struct * const *))));
2715  QVERIFY(object.connect(&object,
2716  SIGNAL(constStructPointerConstPointerSignal(const struct Struct * const *)),
2717  SLOT(constStructPointerConstPointerSlot(const Struct * const *))));
2718  QVERIFY(object.connect(&object,
2719  SIGNAL(constClassPointerConstPointerSignal(const class Class * const *)),
2720  SLOT(constClassPointerConstPointerSlot(const class Class * const *))));
2721  QVERIFY(object.connect(&object,
2722  SIGNAL(constClassPointerConstPointerSignal(const Class * const *)),
2723  SLOT(constClassPointerConstPointerSlot(const class Class * const *))));
2724  QVERIFY(object.connect(&object,
2725  SIGNAL(constClassPointerConstPointerSignal(const class Class * const *)),
2726  SLOT(constClassPointerConstPointerSlot(const Class * const *))));
2727  QVERIFY(object.connect(&object,
2728  SIGNAL(constEnumPointerConstPointerSignal(const enum Enum * const *)),
2729  SLOT(constEnumPointerConstPointerSlot(const enum Enum * const *))));
2730  QVERIFY(object.connect(&object,
2731  SIGNAL(constEnumPointerConstPointerSignal(const Enum * const *)),
2732  SLOT(constEnumPointerConstPointerSlot(const enum Enum * const *))));
2733  QVERIFY(object.connect(&object,
2734  SIGNAL(constEnumPointerConstPointerSignal(const enum Enum * const *)),
2735  SLOT(constEnumPointerConstPointerSlot(const Enum * const *))));
2736 
2737  QVERIFY(object.connect(&object,
2738  SIGNAL(constStructPointerConstPointerSignal(struct Struct const * const *)),
2739  SLOT(constStructPointerConstPointerSlot(struct Struct const * const *))));
2740  QVERIFY(object.connect(&object,
2741  SIGNAL(constStructPointerConstPointerSignal(Struct const * const *)),
2742  SLOT(constStructPointerConstPointerSlot(struct Struct const * const *))));
2743  QVERIFY(object.connect(&object,
2744  SIGNAL(constStructPointerConstPointerSignal(struct Struct const * const *)),
2745  SLOT(constStructPointerConstPointerSlot(Struct const * const *))));
2746  QVERIFY(object.connect(&object,
2747  SIGNAL(constClassPointerConstPointerSignal(class Class const * const *)),
2748  SLOT(constClassPointerConstPointerSlot(class Class const * const *))));
2749  QVERIFY(object.connect(&object,
2750  SIGNAL(constClassPointerConstPointerSignal(Class const * const *)),
2751  SLOT(constClassPointerConstPointerSlot(class Class const * const *))));
2752  QVERIFY(object.connect(&object,
2753  SIGNAL(constClassPointerConstPointerSignal(class Class const * const *)),
2754  SLOT(constClassPointerConstPointerSlot(Class const * const *))));
2755  QVERIFY(object.connect(&object,
2756  SIGNAL(constEnumPointerConstPointerSignal(enum Enum const * const *)),
2757  SLOT(constEnumPointerConstPointerSlot(enum Enum const * const *))));
2758  QVERIFY(object.connect(&object,
2759  SIGNAL(constEnumPointerConstPointerSignal(Enum const * const *)),
2760  SLOT(constEnumPointerConstPointerSlot(enum Enum const * const *))));
2761  QVERIFY(object.connect(&object,
2762  SIGNAL(constEnumPointerConstPointerSignal(enum Enum const * const *)),
2763  SLOT(constEnumPointerConstPointerSlot(Enum const * const *))));
2764 
2765  QVERIFY(object.connect(&object,
2766  SIGNAL(unsignedintSignal(unsigned int)),
2767  SLOT(unsignedintSlot(unsigned int))));
2768  QVERIFY(object.connect(&object,
2769  SIGNAL(unsignedSignal(unsigned)),
2770  SLOT(unsignedSlot(unsigned))));
2771  QVERIFY(object.connect(&object,
2772  SIGNAL(unsignedSignal(unsigned)),
2773  SLOT(uintSlot(uint))));
2774  QVERIFY(object.connect(&object,
2775  SIGNAL(unsignedlongSignal(unsigned long)),
2776  SLOT(unsignedlongSlot(unsigned long))));
2777  QVERIFY(object.connect(&object,
2778  SIGNAL(unsignedlonglongSignal(quint64)),
2779  SLOT(unsignedlonglongSlot(quint64))));
2780  QVERIFY(object.connect(&object,
2781  SIGNAL(unsignedlongintSignal(unsigned long int)),
2782  SLOT(unsignedlongintSlot(unsigned long int))));
2783  QVERIFY(object.connect(&object,
2784  SIGNAL(unsignedshortSignal(unsigned short)),
2785  SLOT(unsignedshortSlot(unsigned short))));
2786  QVERIFY(object.connect(&object,
2787  SIGNAL(unsignedcharSignal(unsigned char)),
2788  SLOT(unsignedcharSlot(unsigned char))));
2789 
2790  // connect when original template signature and mixed usage of 'T<C const &> const &',
2791  // 'const T<const C &> &', and 'T<const C &>'
2792 
2793  QVERIFY(object.connect(&object,
2794  SIGNAL(typeRefSignal(Template<Class &> &)),
2795  SLOT(typeRefSlot(Template<Class &> &))));
2796 
2797  QVERIFY(object.connect(&object,
2798  SIGNAL(constTypeRefSignal(const Template<const Class &> &)),
2799  SLOT(constTypeRefSlot(const Template<const Class &> &))));
2800  QVERIFY(object.connect(&object,
2801  SIGNAL(constTypeRefSignal(const Template<const Class &> &)),
2802  SLOT(constTypeRefSlot(const Template<Class const &> &))));
2803  QVERIFY(object.connect(&object,
2804  SIGNAL(constTypeRefSignal(const Template<const Class &> &)),
2805  SLOT(constTypeRefSlot(Template<Class const &> const &))));
2806  QVERIFY(object.connect(&object,
2807  SIGNAL(constTypeRefSignal(Template<const Class &> const &)),
2808  SLOT(constTypeRefSlot(Template<Class const &> const &))));
2809  QVERIFY(object.connect(&object,
2810  SIGNAL(constTypeRefSignal(Template<Class const &> const &)),
2811  SLOT(constTypeRefSlot(Template<Class const &> const &))));
2812 
2813  QVERIFY(object.connect(&object,
2814  SIGNAL(constTypeRefSignal(const Template<const Class &> &)),
2815  SLOT(typeConstRefSlot(const Template<const Class &> &))));
2816  QVERIFY(object.connect(&object,
2817  SIGNAL(constTypeRefSignal(const Template<const Class &> &)),
2818  SLOT(typeConstRefSlot(const Template<Class const &> &))));
2819  QVERIFY(object.connect(&object,
2820  SIGNAL(constTypeRefSignal(const Template<const Class &> &)),
2821  SLOT(typeConstRefSlot(Template<Class const &> const &))));
2822  QVERIFY(object.connect(&object,
2823  SIGNAL(constTypeRefSignal(Template<const Class &> const &)),
2824  SLOT(typeConstRefSlot(Template<Class const &> const &))));
2825  QVERIFY(object.connect(&object,
2826  SIGNAL(constTypeRefSignal(Template<Class const &> const &)),
2827  SLOT(typeConstRefSlot(Template<Class const &> const &))));
2828 
2829  QVERIFY(object.connect(&object,
2830  SIGNAL(typeConstRefSignal(const Template<const Class &> &)),
2831  SLOT(constTypeRefSlot(const Template<const Class &> &))));
2832  QVERIFY(object.connect(&object,
2833  SIGNAL(typeConstRefSignal(const Template<const Class &> &)),
2834  SLOT(constTypeRefSlot(const Template<Class const &> &))));
2835  QVERIFY(object.connect(&object,
2836  SIGNAL(typeConstRefSignal(const Template<const Class &> &)),
2837  SLOT(constTypeRefSlot(Template<Class const &> const &))));
2838  QVERIFY(object.connect(&object,
2839  SIGNAL(typeConstRefSignal(Template<const Class &> const &)),
2840  SLOT(constTypeRefSlot(Template<Class const &> const &))));
2841  QVERIFY(object.connect(&object,
2842  SIGNAL(typeConstRefSignal(Template<Class const &> const &)),
2843  SLOT(constTypeRefSlot(Template<Class const &> const &))));
2844 
2845  QVERIFY(object.connect(&object,
2846  SIGNAL(typeConstRefSignal(const Template<const Class &> &)),
2847  SLOT(typeConstRefSlot(const Template<const Class &> &))));
2848  QVERIFY(object.connect(&object,
2849  SIGNAL(typeConstRefSignal(const Template<const Class &> &)),
2850  SLOT(typeConstRefSlot(const Template<Class const &> &))));
2851  QVERIFY(object.connect(&object,
2852  SIGNAL(typeConstRefSignal(const Template<const Class &> &)),
2853  SLOT(typeConstRefSlot(Template<Class const &> const &))));
2854  QVERIFY(object.connect(&object,
2855  SIGNAL(typeConstRefSignal(Template<const Class &> const &)),
2856  SLOT(typeConstRefSlot(Template<Class const &> const &))));
2857  QVERIFY(object.connect(&object,
2858  SIGNAL(typeConstRefSignal(Template<Class const &> const &)),
2859  SLOT(typeConstRefSlot(Template<Class const &> const &))));
2860 
2861  QVERIFY(object.connect(&object,
2862  SIGNAL(typePointerConstRefSignal(Class*const&)),
2863  SLOT(typePointerConstRefSlot(Class*const&))));
2864  QVERIFY(object.connect(&object,
2865  SIGNAL(typePointerConstRefSignal(Class*const&)),
2866  SLOT(typePointerConstRefSlot(Class*))));
2867  QVERIFY(object.connect(&object,
2868  SIGNAL(typePointerConstRefSignal(Class*)),
2869  SLOT(typePointerConstRefSlot(Class*const&))));
2870  QVERIFY(object.connect(&object,
2871  SIGNAL(typePointerConstRefSignal(Class*)),
2872  SLOT(typePointerConstRefSlot(Class*))));
2873 
2874  QVERIFY( connect(&object, SIGNAL(constTemplateSignal1(Template <int>)),
2875  &object , SLOT(constTemplateSlot1 (Template<int > ) ) ));
2876  QVERIFY( connect(&object, SIGNAL(constTemplateSignal1(Template <int>)),
2877  &object , SLOT(constTemplateSlot2 (Template<int > ) ) ));
2878  QVERIFY( connect(&object, SIGNAL(constTemplateSignal2(Template <const int>)),
2879  &object , SLOT(constTemplateSlot3(Template<int const > ) ) ));
2880 
2881  //type does not match
2882  QTest::ignoreMessage(QtWarningMsg, "QObject::connect: Incompatible sender/receiver arguments\n"
2883  " NormalizeObject::constTemplateSignal1(Template<int>) --> NormalizeObject::constTemplateSlot3(Template<const int>)");
2884  QVERIFY(!connect(&object, SIGNAL(constTemplateSignal1(Template <int>)),
2885  &object , SLOT(constTemplateSlot3(Template<int const> ) ) ));
2886 }
2887 
2888 class SiblingDeleter : public QObject
2889 {
2890 public:
2892  : QObject(parent), sibling(sibling) {}
2893  inline virtual ~SiblingDeleter() { delete sibling; }
2894 
2895 private:
2896  QPointer<QObject> sibling;
2897 };
2898 
2899 
2900 void tst_QObject::childDeletesItsSibling()
2901 {
2902  QObject *commonParent = new QObject(0);
2903  QPointer<QObject> child = new QObject(0);
2904  QPointer<QObject> siblingDeleter = new SiblingDeleter(child, commonParent);
2905  child->setParent(commonParent);
2906  delete commonParent; // don't crash
2907  QVERIFY(!child);
2908  QVERIFY(!siblingDeleter);
2909 }
2910 
2911 void tst_QObject::floatProperty()
2912 {
2914  const int idx = obj.metaObject()->indexOfProperty("myFloat");
2915  QVERIFY(idx > 0);
2916  QMetaProperty prop = obj.metaObject()->property(idx);
2917  QVERIFY(prop.isValid());
2918  QCOMPARE(int(prop.type()), QMetaType::type("float"));
2919  QVERIFY(!prop.write(&obj, QVariant("Hello")));
2920  QVERIFY(prop.write(&obj, QVariant::fromValue(128.0f)));
2921  QVariant v = prop.read(&obj);
2922  QCOMPARE(v.userType(), int(QMetaType::Float));
2923  QCOMPARE(qvariant_cast<float>(v), 128.0f);
2924 }
2925 
2926 void tst_QObject::qrealProperty()
2927 {
2929  const int idx = obj.metaObject()->indexOfProperty("myQReal");
2930  QVERIFY(idx > 0);
2931  QMetaProperty prop = obj.metaObject()->property(idx);
2932  QVERIFY(prop.isValid());
2933  QCOMPARE(int(prop.type()), QMetaType::type("qreal"));
2934  QVERIFY(!prop.write(&obj, QVariant("Hello")));
2935 
2936  QVERIFY(prop.write(&obj, QVariant::fromValue(128.0f)));
2937  QVariant v = prop.read(&obj);
2938  QCOMPARE(v.userType(), qMetaTypeId<qreal>());
2939  QCOMPARE(qvariant_cast<qreal>(v), 128.0);
2940 
2941  QVERIFY(prop.write(&obj, QVariant::fromValue(double(127))));
2942  v = prop.read(&obj);
2943  QCOMPARE(v.userType(), qMetaTypeId<qreal>());
2944  QCOMPARE(qvariant_cast<qreal>(v), 127.0);
2945 }
2946 
2948 {
2949 public:
2951 
2952  inline virtual bool event(QEvent *e) override {
2953  if (e->type() == QEvent::DynamicPropertyChange) {
2954  changedDynamicProperties.append(static_cast<QDynamicPropertyChangeEvent *>(e)->propertyName());
2955  }
2956  return QObject::event(e);
2957  }
2958 
2960 };
2961 
2962 void tst_QObject::dynamicProperties()
2963 {
2965 
2966  QVERIFY(obj.dynamicPropertyNames().isEmpty());
2967 
2968  // set a non-dynamic property
2969  QVERIFY(obj.setProperty("number", 42));
2970  QVERIFY(obj.changedDynamicProperties.isEmpty());
2971  QCOMPARE(obj.property("number").toInt(), 42);
2972 
2973  QVERIFY(!obj.setProperty("number", "invalid string"));
2974  QVERIFY(obj.changedDynamicProperties.isEmpty());
2975 
2976  // set a dynamic property
2977  QVERIFY(!obj.setProperty("myuserproperty", "Hello"));
2978  QCOMPARE(obj.changedDynamicProperties.count(), 1);
2979  QCOMPARE(obj.changedDynamicProperties.first(), QByteArray("myuserproperty"));
2980  //check if there is no redundant DynamicPropertyChange events
2981  QVERIFY(!obj.setProperty("myuserproperty", "Hello"));
2982  QCOMPARE(obj.changedDynamicProperties.count(), 1);
2983 
2984  QCOMPARE(obj.property("myuserproperty").type(), QVariant::String);
2985  QCOMPARE(obj.property("myuserproperty").toString(), QString("Hello"));
2986 
2987  QCOMPARE(obj.dynamicPropertyNames().count(), 1);
2988  QCOMPARE(obj.dynamicPropertyNames().first(), QByteArray("myuserproperty"));
2989 
2990  // change type of the dynamic property
2991  obj.changedDynamicProperties.clear();
2992  QVERIFY(!obj.setProperty("myuserproperty", QByteArray("Hello")));
2993  QCOMPARE(obj.changedDynamicProperties.count(), 1);
2994  QCOMPARE(obj.changedDynamicProperties.first(), QByteArray("myuserproperty"));
2995  QCOMPARE(obj.property("myuserproperty").type(), QVariant::ByteArray);
2996  QCOMPARE(obj.property("myuserproperty").toString(), QByteArray("Hello"));
2997 
2998  // unset the property
2999  obj.changedDynamicProperties.clear();
3000  QVERIFY(!obj.setProperty("myuserproperty", QVariant()));
3001 
3002  QCOMPARE(obj.changedDynamicProperties.count(), 1);
3003  QCOMPARE(obj.changedDynamicProperties.first(), QByteArray("myuserproperty"));
3004  obj.changedDynamicProperties.clear();
3005 
3006  QVERIFY(obj.property("myuserproperty").isNull());
3007 
3008  QVERIFY(obj.dynamicPropertyNames().isEmpty());
3009 }
3010 
3011 void tst_QObject::recursiveSignalEmission()
3012 {
3013 #if !QT_CONFIG(process)
3014  QSKIP("No qprocess support", SkipAll);
3015 #else
3016  QProcess proc;
3017  // signalbug helper app should always be next to this test binary
3019  proc.start(path);
3020  QVERIFY2(proc.waitForStarted(), qPrintable(QString::fromLatin1("Cannot start '%1': %2").arg(path, proc.errorString())));
3021  QVERIFY(proc.waitForFinished());
3022  QCOMPARE(proc.exitStatus(), QProcess::NormalExit);
3023  QCOMPARE(proc.exitCode(), 0);
3024 #endif
3025 }
3026 
3027 void tst_QObject::signalBlocking()
3028 {
3030  ReceiverObject receiver;
3031 
3032  receiver.connect(&sender, SIGNAL(signal1()), SLOT(slot1()));
3033 
3034  sender.emitSignal1();
3035  QVERIFY(receiver.called(1));
3036  receiver.reset();
3037 
3038  sender.blockSignals(true);
3039 
3040  sender.emitSignal1();
3041  QVERIFY(!receiver.called(1));
3042  receiver.reset();
3043 
3044  sender.blockSignals(false);
3045 
3046  sender.emitSignal1();
3047  QVERIFY(receiver.called(1));
3048  receiver.reset();
3049 }
3050 
3051 void tst_QObject::blockingQueuedConnection()
3052 {
3053  {
3055 
3056  MoveToThreadThread thread;
3057  ReceiverObject receiver;
3058  receiver.moveToThread(&thread);
3059  thread.start();
3060 
3061  receiver.connect(&sender, SIGNAL(signal1()), SLOT(slot1()), Qt::BlockingQueuedConnection);
3062  sender.emitSignal1();
3063  QVERIFY(receiver.called(1));
3064 
3065  receiver.reset();
3067  QVERIFY(receiver.called(1));
3068 
3070  sender.emitSignal2();
3071  QVERIFY(receiver.called(2));
3072 
3073  thread.quit();
3074  QVERIFY(thread.wait());
3075  }
3076 }
3077 
3078 class EventSpy : public QObject
3079 {
3080  Q_OBJECT
3081 
3082 public:
3084 
3086  : QObject(parent)
3087  { }
3088 
3090  {
3091  return events;
3092  }
3093 
3094  void clear()
3095  {
3096  events.clear();
3097  }
3098 
3099  bool eventFilter(QObject *object, QEvent *event) override
3100  {
3101  events.append(qMakePair(object, event->type()));
3102  return false;
3103  }
3104 
3105 private:
3106  EventList events;
3107 };
3108 
3109 void tst_QObject::childEvents()
3110 {
3111  EventSpy::EventList expected;
3112 
3113  {
3114  // no children created, so we expect no events
3115  QObject object;
3116  EventSpy spy;
3117  object.installEventFilter(&spy);
3118 
3120 
3122 
3123  expected =
3125  << qMakePair(&object, QEvent::Type(QEvent::User + 1));
3126  QCOMPARE(spy.eventList(), expected);
3127  }
3128 
3129  {
3130  // 2 children, so we expect 2 ChildAdded events
3131  QObject object;
3132  EventSpy spy;
3133  object.installEventFilter(&spy);
3134 
3136 
3137  QObject child1(&object);
3138  QObject child2;
3139  child2.setParent(&object);
3140 
3142 
3143  expected =
3145  << qMakePair(&object, QEvent::ChildAdded)
3146  << qMakePair(&object, QEvent::ChildAdded);
3147  QCOMPARE(spy.eventList(), expected);
3148  spy.clear();
3149 
3151 
3152  expected =
3154  << qMakePair(&object, QEvent::Type(QEvent::User + 1))
3155  << qMakePair(&object, QEvent::Type(QEvent::User + 2));
3156  QCOMPARE(spy.eventList(), expected);
3157  }
3158 
3159  {
3160  // 2 children, but one is reparented away, so we expect:
3161  // 2 ChildAdded, 1 ChildRemoved
3162  QObject object;
3163  EventSpy spy;
3164  object.installEventFilter(&spy);
3165 
3167 
3168  QObject child1(&object);
3169  QObject child2;
3170  child2.setParent(&object);
3171  child2.setParent(0);
3172 
3174 
3175  expected =
3177  << qMakePair(&object, QEvent::ChildAdded)
3178  << qMakePair(&object, QEvent::ChildAdded)
3179  << qMakePair(&object, QEvent::ChildRemoved);
3180  QCOMPARE(spy.eventList(), expected);
3181  spy.clear();
3182 
3184 
3185  expected =
3187  << qMakePair(&object, QEvent::Type(QEvent::User + 1))
3188  << qMakePair(&object, QEvent::Type(QEvent::User + 2));
3189  QCOMPARE(spy.eventList(), expected);
3190  }
3191 }
3192 
3193 void tst_QObject::installEventFilter()
3194 {
3196  EventSpy::EventList expected;
3197 
3198  QObject object;
3199  EventSpy spy;
3200  object.installEventFilter(&spy);
3201 
3202  // nothing special, should just work
3204  expected =
3206  << qMakePair(&object, QEvent::User);
3207  QCOMPARE(spy.eventList(), expected);
3208  spy.clear();
3209 
3210  // moving the filter causes QCoreApplication to skip the filter
3211  spy.moveToThread(0);
3212  QTest::ignoreMessage(QtWarningMsg, "QCoreApplication: Object event filter cannot be in a different thread.");
3214  QVERIFY(spy.eventList().isEmpty());
3215 
3216  // move it back, and the filter works again
3217  spy.moveToThread(object.thread());
3219  expected =
3221  << qMakePair(&object, QEvent::User);
3222  QCOMPARE(spy.eventList(), expected);
3223  spy.clear();
3224 
3225  // cannot install an event filter that lives in a different thread
3226  object.removeEventFilter(&spy);
3227  spy.moveToThread(0);
3228  QTest::ignoreMessage(QtWarningMsg, "QObject::installEventFilter(): Cannot filter events for objects in a different thread.");
3229  object.installEventFilter(&spy);
3231  QVERIFY(spy.eventList().isEmpty());
3232 }
3233 
3234 class EmitThread : public QThread
3235 { Q_OBJECT
3236 public:
3237  void run(void) override {
3238  emit work();
3239  }
3240 signals:
3241  void work();
3242 };
3243 
3244 namespace QObjectTest { // Do not clash with WinAPI 'DeleteObject'
3245 class DeleteObject : public QObject
3246 {
3247  Q_OBJECT
3248 
3249 public slots:
3250  void deleteSelf()
3251  {
3252  delete this;
3253  }
3254 
3256  {
3257  emit relayedSignal();
3259  }
3260 
3261 signals:
3263 };
3264 } // namespace QObjectTest
3265 
3266 void tst_QObject::deleteSelfInSlot()
3267 {
3268  {
3271  receiver->connect(&sender,
3272  SIGNAL(signal1()),
3273  SLOT(deleteSelf()),
3275 
3276  QThread thread;
3277  receiver->moveToThread(&thread);
3278  thread.connect(receiver, SIGNAL(destroyed()), SLOT(quit()), Qt::DirectConnection);
3279  thread.start();
3280 
3282  sender.emitSignal1();
3283  QVERIFY(p.isNull());
3284 
3285  QVERIFY(thread.wait(10000));
3286  }
3287 
3288  {
3291  receiver->connect(&sender,
3292  SIGNAL(signal1()),
3293  SLOT(relaySignalAndProcessEvents()),
3295  receiver->connect(receiver,
3296  SIGNAL(relayedSignal()),
3297  SLOT(deleteSelf()),
3299 
3300  QThread thread;
3301  receiver->moveToThread(&thread);
3302  thread.connect(receiver, SIGNAL(destroyed()), SLOT(quit()), Qt::DirectConnection);
3303  thread.start();
3304 
3306  sender.emitSignal1();
3307  QVERIFY(p.isNull());
3308 
3309  QVERIFY(thread.wait(10000));
3310  }
3311 
3312  {
3315  connect(&sender, SIGNAL(work()), receiver, SLOT(deleteSelf()), Qt::DirectConnection);
3317  sender.start();
3318  QVERIFY(sender.wait(10000));
3319  QVERIFY(p.isNull());
3320  }
3321 }
3322 
3324 {
3325  Q_OBJECT
3326 
3327 public slots:
3329  {
3330  disconnect(sender(), 0, this, 0);
3331  }
3332 
3334  {
3335  emit relayedSignal();
3337  }
3338 
3339 signals:
3341 };
3342 
3343 void tst_QObject::disconnectSelfInSlotAndDeleteAfterEmit()
3344 {
3345  {
3347  DisconnectObject *receiver = new DisconnectObject();
3348  receiver->connect(&sender, SIGNAL(signal1()), SLOT(disconnectSelf()));
3349  sender.emitSignal1AfterRecursion();
3350  delete receiver;
3351  }
3352 
3353  {
3355  DisconnectObject *receiver = new DisconnectObject();
3356  receiver->connect(&sender,
3357  SIGNAL(signal1()),
3358  SLOT(disconnectSelf()),
3360 
3361  QThread thread;
3362  receiver->moveToThread(&thread);
3363  thread.connect(receiver, SIGNAL(destroyed()), SLOT(quit()), Qt::DirectConnection);
3364  thread.start();
3365 
3366  QPointer<DisconnectObject> p = receiver;
3367  sender.emitSignal1();
3368  QVERIFY(!p.isNull());
3369 
3370  receiver->deleteLater();
3371 
3372  QVERIFY(thread.wait(10000));
3373  QVERIFY(p.isNull());
3374  }
3375 
3376  {
3378  DisconnectObject *receiver = new DisconnectObject();
3379  receiver->connect(&sender,
3380  SIGNAL(signal1()),
3381  SLOT(relaySignalAndProcessEvents()),
3383  receiver->connect(receiver,
3384  SIGNAL(relayedSignal()),
3385  SLOT(disconnectSelf()),
3387 
3388  QThread thread;
3389  receiver->moveToThread(&thread);
3390  thread.connect(receiver, SIGNAL(destroyed()), SLOT(quit()), Qt::DirectConnection);
3391  thread.start();
3392 
3393  QPointer<DisconnectObject> p = receiver;
3394  sender.emitSignal1();
3395  QVERIFY(!p.isNull());
3396 
3397  receiver->deleteLater();
3398 
3399  QVERIFY(thread.wait(10000));
3400  QVERIFY(p.isNull());
3401  }
3402 }
3403 
3404 void tst_QObject::dumpObjectInfo()
3405 {
3406  QObject a, b;
3408  QTest::ignoreMessage(QtDebugMsg, "OBJECT QObject::unnamed");
3409  QTest::ignoreMessage(QtDebugMsg, " SIGNALS OUT");
3410  QTest::ignoreMessage(QtDebugMsg, " signal: destroyed(QObject*)");
3411  QTest::ignoreMessage(QtDebugMsg, " <functor or function pointer>");
3412  QTest::ignoreMessage(QtDebugMsg, " SIGNALS IN");
3413  QTest::ignoreMessage(QtDebugMsg, " <None>");
3414  a.dumpObjectInfo(); // should not crash
3415 }
3416 
3417 void tst_QObject::dumpObjectTree()
3418 {
3419  QObject a;
3421 
3422  QTimer b(&a);
3424 
3425  QObject c(&b);
3427 
3428  QFile f(&a);
3430 
3431  const char * const output[] = {
3432  "QObject::a ",
3433  " QTimer::b ",
3434  " QObject::c ",
3435  " QFile::f ",
3436  };
3437  for (const char *line : output)
3439 
3440  a.dumpObjectTree();
3441 }
3442 
3443 class ConnectToSender : public QObject
3444 { Q_OBJECT
3445  public slots:
3446  void uselessSlot() { count++; }
3447 
3448  void harmfullSlot() {
3449  //this used to crash
3450  connect(sender(), SIGNAL(signal4()), this, SLOT(uselessSlot()));
3451  //play a little bit with the memory in order to really get a segfault.
3452  connect(sender(), SIGNAL(signal1()), this, SLOT(uselessSlot()));
3453  QList<double>() << 45 << 78 << 65 << 121 << 45 << 78 << 12;
3454  }
3455  public:
3456  int count;
3457 };
3458 
3459 void tst_QObject::connectToSender()
3460 {
3461  SenderObject s;
3463  r.count = 0;
3464  QObject::connect(&s, SIGNAL(signal1()), &r, SLOT(harmfullSlot()));
3465  QObject::connect(&s, SIGNAL(signal1()), &r, SLOT(uselessSlot()));
3466 
3467  s.emitSignal1();
3468 
3469  QCOMPARE(r.count, 1);
3470  s.emitSignal4();
3471  QCOMPARE(r.count, 2);
3472 }
3473 
3474 void tst_QObject::qobjectConstCast()
3475 {
3476  FooObject obj;
3477 
3478  QObject *ptr = &obj;
3479  const QObject *cptr = &obj;
3480 
3481  QVERIFY(qobject_cast<FooObject *>(ptr));
3482  QVERIFY(qobject_cast<const FooObject *>(cptr));
3483 }
3484 
3485 void tst_QObject::uniqConnection()
3486 {
3487  SenderObject s;
3490  r1.reset();
3491  r2.reset();
3493 
3494  QVERIFY(connect(&s, SIGNAL(signal1()), &r1, SLOT(slot1()) , Qt::UniqueConnection) );
3495  QVERIFY(connect(&s, SIGNAL(signal1()), &r2, SLOT(slot1()) , Qt::UniqueConnection) );
3496  QVERIFY(connect(&s, SIGNAL(signal1()), &r1, SLOT(slot3()) , Qt::UniqueConnection) );
3497  QVERIFY(connect(&s, SIGNAL(signal3()), &r1, SLOT(slot3()) , Qt::UniqueConnection) );
3498 
3499  s.emitSignal1();
3500  s.emitSignal2();
3501  s.emitSignal3();
3502  s.emitSignal4();
3503 
3504  QCOMPARE(r1.count_slot1, 1);
3505  QCOMPARE(r1.count_slot2, 0);
3506  QCOMPARE(r1.count_slot3, 2);
3507  QCOMPARE(r1.count_slot4, 0);
3508  QCOMPARE(r2.count_slot1, 1);
3509  QCOMPARE(r2.count_slot2, 0);
3510  QCOMPARE(r2.count_slot3, 0);
3511  QCOMPARE(r2.count_slot4, 0);
3512  QCOMPARE(r1.sequence_slot1, 1);
3513  QCOMPARE(r2.sequence_slot1, 2);
3514  QCOMPARE(r1.sequence_slot3, 4);
3515 
3516  r1.reset();
3517  r2.reset();
3519 
3520  QVERIFY( connect(&s, SIGNAL(signal4()), &r1, SLOT(slot4()) , Qt::UniqueConnection));
3521  QVERIFY( connect(&s, SIGNAL(signal4()), &r2, SLOT(slot4()) , Qt::UniqueConnection));
3522  QVERIFY(!connect(&s, SIGNAL(signal4()), &r2, SLOT(slot4()) , Qt::UniqueConnection));
3523  QVERIFY( connect(&s, SIGNAL(signal1()), &r2, SLOT(slot4()) , Qt::UniqueConnection));
3524  QVERIFY(!connect(&s, SIGNAL(signal4()), &r1, SLOT(slot4()) , Qt::UniqueConnection));
3525 
3526  s.emitSignal4();
3527  QCOMPARE(r1.count_slot4, 1);
3528  QCOMPARE(r2.count_slot4, 1);
3529  QCOMPARE(r1.sequence_slot4, 1);
3530  QCOMPARE(r2.sequence_slot4, 2);
3531 
3532  r1.reset();
3533  r2.reset();
3535 
3536  connect(&s, SIGNAL(signal4()), &r1, SLOT(slot4()));
3537 
3538  s.emitSignal4();
3539  QCOMPARE(r1.count_slot4, 2);
3540  QCOMPARE(r2.count_slot4, 1);
3541  QCOMPARE(r1.sequence_slot4, 3);
3542  QCOMPARE(r2.sequence_slot4, 2);
3543 }
3544 
3545 void tst_QObject::uniqConnectionPtr()
3546 {
3547  SenderObject s;
3550  r1.reset();
3551  r2.reset();
3553 
3562 
3563  s.emitSignal1();
3564  s.emitSignal2();
3565  s.emitSignal3();
3566  s.emitSignal4();
3567 
3568  QCOMPARE(r1.count_slot1, 1);
3569  QCOMPARE(r1.count_slot2, 0);
3570  QCOMPARE(r1.count_slot3, 2);
3571  QCOMPARE(r1.count_slot4, 0);
3572  QCOMPARE(r2.count_slot1, 1);
3573  QCOMPARE(r2.count_slot2, 0);
3574  QCOMPARE(r2.count_slot3, 0);
3575  QCOMPARE(r2.count_slot4, 0);
3576  QCOMPARE(r1.sequence_slot1, 1);
3577  QCOMPARE(r2.sequence_slot1, 2);
3578  QCOMPARE(r1.sequence_slot3, 4);
3579 
3580  r1.reset();
3581  r2.reset();
3583 
3594 
3595  s.emitSignal4();
3596  QCOMPARE(r1.count_slot4, 1);
3597  QCOMPARE(r2.count_slot4, 1);
3598  QCOMPARE(r1.sequence_slot4, 1);
3599  QCOMPARE(r2.sequence_slot4, 2);
3600 
3601  r1.reset();
3602  r2.reset();
3604 
3606 
3607  s.emitSignal4();
3608  QCOMPARE(r1.count_slot4, 2);
3609  QCOMPARE(r2.count_slot4, 1);
3610  QCOMPARE(r1.sequence_slot4, 3);
3611  QCOMPARE(r2.sequence_slot4, 2);
3612 }
3613 
3614 void tst_QObject::interfaceIid()
3615 {
3616  QCOMPARE(QByteArray(qobject_interface_iid<Foo::Bleh *>()),
3617  QByteArray(Bleh_iid));
3618  QCOMPARE(QByteArray(qobject_interface_iid<Foo::Bar *>()),
3619  QByteArray("com.qtest.foobar"));
3620 }
3621 
3622 void tst_QObject::deleteQObjectWhenDeletingEvent()
3623 {
3624  // This is a regression test for an old bug that used to deadlock
3625  // when the QObject from the event was destroyed.
3626 
3627  struct MyEvent : public QEvent
3628  {
3629  MyEvent() : QEvent(QEvent::User) { }
3630  QObject obj;
3631  };
3632 
3633  QObject o;
3634  QCoreApplication::postEvent(&o, new MyEvent);
3635  QCoreApplication::removePostedEvents(&o); // here you would get a deadlock
3636 }
3637 
3638 class OverloadObject : public QObject
3639 {
3640  friend class tst_QObject;
3641  Q_OBJECT
3642  signals:
3643  void sig(int i, char c, qreal m = 12);
3644  void sig(int i, int j = 12);
3645  void sig(QObject *o, QObject *p, QObject *q = nullptr, QObject *r = nullptr) const;
3646  void other(int a = 0);
3647  void sig(QObject *o, OverloadObject *p = nullptr, QObject *q = nullptr, QObject *r = nullptr);
3648  void sig(double r = 0.5);
3649  public slots:
3650  void slo(int i, int j = 43)
3651  {
3652  s_num += 1;
3653  i1_num = i;
3654  i2_num = j;
3655  }
3657  {
3658  s_num += 10;
3659  o1_obj = o;
3660  o2_obj = p;
3661  o3_obj = q;
3662  o4_obj = r;
3663  }
3664  void slo()
3665  {
3666  s_num += 100;
3667  }
3668 
3669  public:
3670  int s_num;
3671  int i1_num;
3672  int i2_num;
3677 };
3678 
3679 void tst_QObject::overloads()
3680 {
3681  OverloadObject obj1;
3682  OverloadObject obj2;
3683  QObject obj3;
3684  obj1.s_num = 0;
3685  obj2.s_num = 0;
3686 
3687  connect (&obj1, SIGNAL(sig(int)) , &obj1, SLOT(slo(int)));
3688  connect (&obj1, SIGNAL(sig(QObject*,QObject*,QObject*)) , &obj1, SLOT(slo(QObject*,QObject*,QObject*)));
3689 
3690  connect (&obj1, SIGNAL(sig(QObject*,QObject*,QObject*,QObject*)) , &obj2, SLOT(slo(QObject*,QObject*,QObject*)));
3691  connect (&obj1, SIGNAL(sig(QObject*)) , &obj2, SLOT(slo()));
3692  connect (&obj1, SIGNAL(sig(int,int)) , &obj2, SLOT(slo(int,int)));
3693 
3694  emit obj1.sig(0.5); //connected to nothing
3695  emit obj1.sig(1, 'a'); //connected to nothing
3696  QCOMPARE(obj1.s_num, 0);
3697  QCOMPARE(obj2.s_num, 0);
3698 
3699  emit obj1.sig(1); //this signal is connected
3700  QCOMPARE(obj1.s_num, 1);
3701  QCOMPARE(obj1.i1_num, 1);
3702  QCOMPARE(obj1.i2_num, 43); //default argument of the slot
3703 
3704  QCOMPARE(obj2.s_num, 1);
3705  QCOMPARE(obj2.i1_num, 1);
3706  QCOMPARE(obj2.i2_num, 12); //default argument of the signal
3707 
3708 
3709  emit obj1.sig(&obj2); //this signal is conencted to obj2
3710  QCOMPARE(obj1.s_num, 1);
3711  QCOMPARE(obj2.s_num, 101);
3712  emit obj1.sig(&obj2, &obj3); //this signal is connected
3713  QCOMPARE(obj1.s_num, 11);
3714  QCOMPARE(obj1.o1_obj, (QObject *)&obj2);
3715  QCOMPARE(obj1.o2_obj, &obj3);
3716  QCOMPARE(obj1.o3_obj, (QObject *)0); //default arg of the signal
3717  QCOMPARE(obj1.o4_obj, (QObject *)qApp); //default arg of the slot
3718 
3719  QCOMPARE(obj2.s_num, 111);
3720  QCOMPARE(obj2.o1_obj, (QObject *)&obj2);
3721  QCOMPARE(obj2.o2_obj, &obj3);
3722  QCOMPARE(obj2.o3_obj, (QObject *)0); //default arg of the signal
3723  QCOMPARE(obj2.o4_obj, (QObject *)qApp); //default arg of the slot
3724 }
3725 
3726 class ManySignals : public QObject
3727 { Q_OBJECT
3728  friend class tst_QObject;
3729 signals:
3730  void sig00(); void sig01(); void sig02(); void sig03(); void sig04();
3731  void sig05(); void sig06(); void sig07(); void sig08(); void sig09();
3732  void sig10(); void sig11(); void sig12(); void sig13(); void sig14();
3733  void sig15(); void sig16(); void sig17(); void sig18(); void sig19();
3734  void sig20(); void sig21(); void sig22(); void sig23(); void sig24();
3735  void sig25(); void sig26(); void sig27(); void sig28(); void sig29();
3736  void sig30(); void sig31(); void sig32(); void sig33(); void sig34();
3737  void sig35(); void sig36(); void sig37(); void sig38(); void sig39();
3738  void sig40(); void sig41(); void sig42(); void sig43(); void sig44();
3739  void sig45(); void sig46(); void sig47(); void sig48(); void sig49();
3740  void sig50(); void sig51(); void sig52(); void sig53(); void sig54();
3741  void sig55(); void sig56(); void sig57(); void sig58(); void sig59();
3742  void sig60(); void sig61(); void sig62(); void sig63(); void sig64();
3743  void sig65(); void sig66(); void sig67(); void sig68(); void sig69();
3744 
3745 public slots:
3746  void received() { rec++; }
3747 public:
3748  int rec;
3749 };
3750 
3751 
3752 void tst_QObject::isSignalConnected()
3753 {
3754  ManySignals o;
3755  const QMetaObject *meta = o.metaObject();
3756  o.rec = 0;
3757 #ifdef QT_BUILD_INTERNAL
3759  QVERIFY(!priv->isSignalConnected(priv->signalIndex("destroyed()")));
3760  QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig00()")));
3761  QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig05()")));
3762  QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig15()")));
3763  QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig29()")));
3764  QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig60()")));
3765 #endif
3766  QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("destroyed()"))));
3767  QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig00()"))));
3768  QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig05()"))));
3769  QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig15()"))));
3770  QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig29()"))));
3771  QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig60()"))));
3772  QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig69()"))));
3773 
3774  QObject::connect(&o, SIGNAL(sig00()), &o, SIGNAL(sig69()));
3775  QObject::connect(&o, SIGNAL(sig34()), &o, SIGNAL(sig03()));
3776  QObject::connect(&o, SIGNAL(sig69()), &o, SIGNAL(sig34()));
3777  QObject::connect(&o, SIGNAL(sig03()), &o, SIGNAL(sig18()));
3778 
3779 #ifdef QT_BUILD_INTERNAL
3780  QVERIFY(!priv->isSignalConnected(priv->signalIndex("destroyed()")));
3781  QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig05()")));
3782  QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig15()")));
3783  QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig29()")));
3784 
3785  QVERIFY(priv->isSignalConnected(priv->signalIndex("sig00()")));
3786  QVERIFY(priv->isSignalConnected(priv->signalIndex("sig03()")));
3787  QVERIFY(priv->isSignalConnected(priv->signalIndex("sig34()")));
3788  QVERIFY(priv->isSignalConnected(priv->signalIndex("sig69()")));
3789  QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig18()")));
3790 #endif
3791  QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("destroyed()"))));
3792  QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("destroyed(QObject*)"))));
3793  QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig05()"))));
3794  QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig15()"))));
3795  QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig29()"))));
3796 
3797  QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig00()"))));
3798  QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig03()"))));
3799  QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig34()"))));
3800  QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig69()"))));
3801  QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig18()"))));
3802 
3803 
3804  QObject::connect(&o, SIGNAL(sig18()), &o, SIGNAL(sig29()));
3805  QObject::connect(&o, SIGNAL(sig29()), &o, SIGNAL(sig62()));
3806  QObject::connect(&o, SIGNAL(sig62()), &o, SIGNAL(sig28()));
3807  QObject::connect(&o, SIGNAL(sig28()), &o, SIGNAL(sig27()));
3808 
3809 #ifdef QT_BUILD_INTERNAL
3810  QVERIFY(priv->isSignalConnected(priv->signalIndex("sig18()")));
3811  QVERIFY(priv->isSignalConnected(priv->signalIndex("sig62()")));
3812  QVERIFY(priv->isSignalConnected(priv->signalIndex("sig28()")));
3813  QVERIFY(priv->isSignalConnected(priv->signalIndex("sig69()")));
3814  QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig27()")));
3815 #endif
3816  QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig18()"))));
3817  QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig62()"))));
3818  QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig28()"))));
3819  QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig69()"))));
3820  QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig27()"))));
3821 
3822  QCOMPARE(o.rec, 0);
3823  emit o.sig01();
3824  emit o.sig34();
3825  QCOMPARE(o.rec, 0);
3826 
3827  QObject::connect(&o, SIGNAL(sig27()), &o, SLOT(received()));
3828 
3829 #ifdef QT_BUILD_INTERNAL
3830  QVERIFY(priv->isSignalConnected(priv->signalIndex("sig00()")));
3831  QVERIFY(priv->isSignalConnected(priv->signalIndex("sig03()")));
3832  QVERIFY(priv->isSignalConnected(priv->signalIndex("sig34()")));
3833  QVERIFY(priv->isSignalConnected(priv->signalIndex("sig18()")));
3834  QVERIFY(priv->isSignalConnected(priv->signalIndex("sig62()")));
3835  QVERIFY(priv->isSignalConnected(priv->signalIndex("sig28()")));
3836  QVERIFY(priv->isSignalConnected(priv->signalIndex("sig69()")));
3837  QVERIFY(priv->isSignalConnected(priv->signalIndex("sig27()")));
3838 
3839  QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig04()")));
3840  QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig21()")));
3841  QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig25()")));
3842  QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig55()")));
3843 #endif
3844 
3845  emit o.sig00();
3846  QCOMPARE(o.rec, 1);
3847  emit o.sig69();
3848  QCOMPARE(o.rec, 2);
3849  emit o.sig36();
3850  QCOMPARE(o.rec, 2);
3851 
3852  QObject::connect(&o, &QObject::destroyed, qt_noop);
3853  QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("destroyed()"))));
3854  QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("destroyed(QObject*)"))));
3855 
3856  QVERIFY(!o.isSignalConnected(QMetaMethod()));
3857 }
3858 
3859 void tst_QObject::isSignalConnectedAfterDisconnection()
3860 {
3861  ManySignals o;
3862  const QMetaObject *meta = o.metaObject();
3863 
3864  const QMetaMethod sig00 = meta->method(meta->indexOfSignal("sig00()"));
3865  QVERIFY(!o.isSignalConnected(sig00));
3866  QObject::connect(&o, &ManySignals::sig00, qt_noop);
3867  QVERIFY(o.isSignalConnected(sig00));
3869  QVERIFY(!o.isSignalConnected(sig00));
3870 
3871  const QMetaMethod sig69 = meta->method(meta->indexOfSignal("sig69()"));
3872  QVERIFY(!o.isSignalConnected(sig69));
3873  QObject::connect(&o, &ManySignals::sig69, qt_noop);
3874  QVERIFY(o.isSignalConnected(sig69));
3876  QVERIFY(!o.isSignalConnected(sig69));
3877 
3878  {
3879  ManySignals o2;
3881  QVERIFY(o.isSignalConnected(sig00));
3882  // o2 is destructed
3883  }
3884  QVERIFY(!o.isSignalConnected(sig00));
3885 
3886  const QMetaMethod sig01 = meta->method(meta->indexOfSignal("sig01()"));
3887  QObject::connect(&o, &ManySignals::sig00, qt_noop);
3888  QObject::connect(&o, &ManySignals::sig01, qt_noop);
3889  QObject::connect(&o, &ManySignals::sig69, qt_noop);
3890  QVERIFY(o.isSignalConnected(sig00));
3891  QVERIFY(o.isSignalConnected(sig01));
3892  QVERIFY(o.isSignalConnected(sig69));
3894  QVERIFY(o.isSignalConnected(sig00));
3895  QVERIFY(o.isSignalConnected(sig01));
3896  QVERIFY(!o.isSignalConnected(sig69));
3898  QVERIFY(!o.isSignalConnected(sig00));
3899  QVERIFY(o.isSignalConnected(sig01));
3900  QVERIFY(!o.isSignalConnected(sig69));
3901  QObject::connect(&o, &ManySignals::sig69, qt_noop);
3902  QVERIFY(!o.isSignalConnected(sig00));
3903  QVERIFY(o.isSignalConnected(sig01));
3904  QVERIFY(o.isSignalConnected(sig69));
3906  QVERIFY(!o.isSignalConnected(sig00));
3907  QVERIFY(!o.isSignalConnected(sig01));
3908  QVERIFY(o.isSignalConnected(sig69));
3909 }
3910 
3911 void tst_QObject::qMetaObjectConnect()
3912 {
3915  int slot1Index, slot2Index, slot3Index;
3916  {
3917  SenderObject s;
3918  r1.reset();
3919  r2.reset();
3921 
3922  int signal1Index = s.metaObject()->indexOfSignal("signal1()");
3923  int signal3Index = s.metaObject()->indexOfSignal("signal3()");
3924  slot1Index = r1.metaObject()->indexOfSlot("slot1()");
3925  slot2Index = r1.metaObject()->indexOfSlot("slot2()");
3926  slot3Index = r1.metaObject()->indexOfSlot("slot3()");
3927 
3928  QVERIFY(slot1Index > 0);
3929  QVERIFY(slot2Index > 0);
3930  QVERIFY(slot3Index > 0);
3931 
3932  QVERIFY(QMetaObject::connect(&s, signal1Index, &r1, slot1Index));
3933  QVERIFY(QMetaObject::connect(&s, signal3Index, &r2, slot3Index));
3934  QVERIFY(QMetaObject::connect(&s, -1, &r2, slot2Index));
3935 
3936  QCOMPARE(r1.count_slot1, 0);
3937  QCOMPARE(r1.count_slot2, 0);
3938  QCOMPARE(r1.count_slot3, 0);
3939  QCOMPARE(r2.count_slot1, 0);
3940  QCOMPARE(r2.count_slot2, 0);
3941  QCOMPARE(r2.count_slot3, 0);
3942 
3943  s.emitSignal1();
3944 
3945  QCOMPARE(r1.count_slot1, 1);
3946  QCOMPARE(r1.count_slot2, 0);
3947  QCOMPARE(r1.count_slot3, 0);
3948  QCOMPARE(r2.count_slot1, 0);
3949  QCOMPARE(r2.count_slot2, 1);
3950  QCOMPARE(r2.count_slot3, 0);
3951 
3952  s.emitSignal2();
3953  s.emitSignal3();
3954  s.emitSignal4();
3955 
3956  QCOMPARE(r1.count_slot1, 1);
3957  QCOMPARE(r1.count_slot2, 0);
3958  QCOMPARE(r1.count_slot3, 0);
3959  QCOMPARE(r2.count_slot1, 0);
3960  QCOMPARE(r2.count_slot2, 4);
3961  QCOMPARE(r2.count_slot3, 1);
3962 
3963  QVERIFY(QMetaObject::disconnect(&s, signal1Index, &r1, slot1Index));
3964  QVERIFY(QMetaObject::disconnect(&s, signal3Index, &r2, slot3Index));
3965  QVERIFY(QMetaObject::disconnect(&s, -1, &r2, slot2Index));
3966 
3967  s.emitSignal1();
3968  s.emitSignal2();
3969  s.emitSignal3();
3970  s.emitSignal4();
3971 
3972  QCOMPARE(r1.count_slot1, 1);
3973  QCOMPARE(r1.count_slot2, 0);
3974  QCOMPARE(r1.count_slot3, 0);
3975  QCOMPARE(r2.count_slot1, 0);
3976  QCOMPARE(r2.count_slot2, 4);
3977  QCOMPARE(r2.count_slot3, 1);
3978 
3979  //some "dynamic" signal
3980  QVERIFY(QMetaObject::connect(&s, s.metaObject()->methodOffset() + 20, &r1, slot3Index));
3981  QVERIFY(QMetaObject::connect(&s, s.metaObject()->methodOffset() + 35, &r2, slot1Index));
3982  QVERIFY(QMetaObject::connect(&s, -1, &r1, slot2Index));
3983 
3984  r1.reset();
3985  r2.reset();
3986 
3987  void *args[] = { 0 , 0 };
3988  QMetaObject::activate(&s, s.metaObject()->methodOffset() + 20, args);
3989  QMetaObject::activate(&s, s.metaObject()->methodOffset() + 48, args);
3990  QCOMPARE(r1.count_slot1, 0);
3991  QCOMPARE(r1.count_slot2, 2);
3992  QCOMPARE(r1.count_slot3, 1);
3993  QCOMPARE(r2.count_slot1, 0);
3994  QCOMPARE(r2.count_slot2, 0);
3995  QCOMPARE(r2.count_slot3, 0);
3996 
3997  QMetaObject::activate(&s, s.metaObject()->methodOffset() + 35, args);
3998  s.emitSignal1();
3999  s.emitSignal2();
4000 
4001  QCOMPARE(r1.count_slot1, 0);
4002  QCOMPARE(r1.count_slot2, 5);
4003  QCOMPARE(r1.count_slot3, 1);
4004  QCOMPARE(r2.count_slot1, 1);
4005  QCOMPARE(r2.count_slot2, 0);
4006  QCOMPARE(r2.count_slot3, 0);
4007  }
4008 
4009  r1.reset();
4010  r2.reset();
4011 
4012 #define SIGNAL_INDEX(S) obj1.metaObject()->indexOfSignal(QMetaObject::normalizedSignature(#S))
4013  OverloadObject obj1;
4014  QObject obj2, obj3;
4015 
4016  QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(int)) , &r1, slot1Index);
4018  &r2, slot1Index);
4019 
4021  &r1, slot2Index);
4022  QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(QObject *)) , &r2, slot2Index);
4023  QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(int, int)) , &r1, slot3Index);
4024 
4025  emit obj1.sig(0.5); //connected to nothing
4026  emit obj1.sig(1, 'a'); //connected to nothing
4027  QCOMPARE(r1.count_slot1, 0);
4028  QCOMPARE(r1.count_slot2, 0);
4029  QCOMPARE(r1.count_slot3, 0);
4030  QCOMPARE(r2.count_slot1, 0);
4031  QCOMPARE(r2.count_slot2, 0);
4032  QCOMPARE(r2.count_slot3, 0);
4033 
4034  emit obj1.sig(1); //this signal is connected
4035  emit obj1.sig(&obj2);
4036 
4037  QCOMPARE(r1.count_slot1, 1);
4038  QCOMPARE(r1.count_slot2, 0);
4039  QCOMPARE(r1.count_slot3, 1);
4040  QCOMPARE(r2.count_slot1, 0);
4041  QCOMPARE(r2.count_slot2, 1);
4042  QCOMPARE(r2.count_slot3, 0);
4043 
4044  emit obj1.sig(&obj2, &obj3); //this signal is connected
4045 
4046  QCOMPARE(r1.count_slot1, 1);
4047  QCOMPARE(r1.count_slot2, 1);
4048  QCOMPARE(r1.count_slot3, 1);
4049  QCOMPARE(r2.count_slot1, 1);
4050  QCOMPARE(r2.count_slot2, 1);
4051  QCOMPARE(r2.count_slot3, 0);
4052 }
4053 
4054 void tst_QObject::qMetaObjectDisconnectOne()
4055 {
4056  SenderObject s;
4058 
4059  int signal1Index = s.metaObject()->indexOfSignal("signal1()");
4060  int signal3Index = s.metaObject()->indexOfSignal("signal3()");
4061  int slot1Index = r1.metaObject()->indexOfSlot("slot1()");
4062  int slot2Index = r1.metaObject()->indexOfSlot("slot2()");
4063 
4064  QVERIFY(signal1Index > 0);
4065  QVERIFY(signal3Index > 0);
4066  QVERIFY(slot1Index > 0);
4067  QVERIFY(slot2Index > 0);
4068 
4069  QVERIFY(QMetaObject::connect(&s, signal1Index, &r1, slot1Index));
4070  QVERIFY(QMetaObject::connect(&s, signal3Index, &r1, slot2Index));
4071  QVERIFY(QMetaObject::connect(&s, signal3Index, &r1, slot2Index));
4072  QVERIFY(QMetaObject::connect(&s, signal3Index, &r1, slot2Index));
4073 
4074  r1.reset();
4075  QCOMPARE(r1.count_slot1, 0);
4076  QCOMPARE(r1.count_slot2, 0);
4077 
4078  s.emitSignal1();
4079  QCOMPARE(r1.count_slot1, 1);
4080  QCOMPARE(r1.count_slot2, 0);
4081 
4082  s.emitSignal3();
4083  QCOMPARE(r1.count_slot1, 1);
4084  QCOMPARE(r1.count_slot2, 3);
4085 
4086  r1.reset();
4087  QVERIFY(QMetaObject::disconnectOne(&s, signal1Index, &r1, slot1Index));
4088  QVERIFY(QMetaObject::disconnectOne(&s, signal3Index, &r1, slot2Index));
4089 
4090  s.emitSignal1();
4091  QCOMPARE(r1.count_slot1, 0);
4092  QCOMPARE(r1.count_slot2, 0);
4093 
4094  s.emitSignal3();
4095  QCOMPARE(r1.count_slot1, 0);
4096  QCOMPARE(r1.count_slot2, 2);
4097 
4098  r1.reset();
4099  QVERIFY(!QMetaObject::disconnectOne(&s, signal1Index, &r1, slot1Index));
4100  QVERIFY( QMetaObject::disconnectOne(&s, signal3Index, &r1, slot2Index));
4101 
4102  s.emitSignal1();
4103  QCOMPARE(r1.count_slot1, 0);
4104  QCOMPARE(r1.count_slot2, 0);
4105 
4106  s.emitSignal3();
4107  QCOMPARE(r1.count_slot1, 0);
4108  QCOMPARE(r1.count_slot2, 1);
4109 
4110  r1.reset();
4111  QVERIFY(!QMetaObject::disconnectOne(&s, signal1Index, &r1, slot1Index));
4112  QVERIFY( QMetaObject::disconnectOne(&s, signal3Index, &r1, slot2Index));
4113 
4114  s.emitSignal1();
4115  QCOMPARE(r1.count_slot1, 0);
4116  QCOMPARE(r1.count_slot2, 0);
4117 
4118  s.emitSignal3();
4119  QCOMPARE(r1.count_slot1, 0);
4120  QCOMPARE(r1.count_slot2, 0);
4121 }
4122 
4124 { Q_OBJECT
4125 public slots:
4126  void signal1() { s++; }
4127 signals:
4128  void aPublicSlot();
4129 public:
4130  int s;
4131  ConfusingObject() : s(0) {}
4132  friend class tst_QObject;
4133 };
4134 
4135 void tst_QObject::sameName()
4136 {
4137  ConfusingObject c1, c2;
4138  QVERIFY(connect(&c1, SIGNAL(signal1()), &c1, SLOT(signal1())));
4139  c1.emitSignal1();
4140  QCOMPARE(c1.s, 1);
4141 
4142  QVERIFY(connect(&c2, SIGNAL(signal1()), &c1, SIGNAL(signal1())));
4143  c2.emitSignal1();
4144  QCOMPARE(c1.s, 2);
4145 
4146 #ifndef QT_NO_DEBUG
4147  QTest::ignoreMessage(QtWarningMsg, "QMetaObject::indexOfSignal: signal aPublicSlot() from SenderObject redefined in ConfusingObject");
4148 #endif
4149  QVERIFY(connect(&c2, SIGNAL(aPublicSlot()), &c1, SLOT(signal1())));
4150  c2.aPublicSlot();
4151  QCOMPARE(c2.aPublicSlotCalled, 0);
4152  QCOMPARE(c1.aPublicSlotCalled, 0);
4153  QCOMPARE(c1.s, 3);
4154 
4155 #ifndef QT_NO_DEBUG
4156  QTest::ignoreMessage(QtWarningMsg, "QMetaObject::indexOfSignal: signal aPublicSlot() from SenderObject redefined in ConfusingObject");
4157 #endif
4158  QVERIFY(connect(&c2, SIGNAL(aPublicSlot()), &c1, SLOT(aPublicSlot())));
4159  c2.aPublicSlot();
4160  QCOMPARE(c2.aPublicSlotCalled, 0);
4161  QCOMPARE(c1.aPublicSlotCalled, 1);
4162  QCOMPARE(c1.s, 4);
4163 }
4164 
4165 void tst_QObject::connectByMetaMethods()
4166 {
4167  SenderObject s;
4168  ReceiverObject r;
4169  const QMetaObject *smeta = s.metaObject();
4170  const QMetaObject *rmeta = r.metaObject();
4171  int sigIndx = smeta->indexOfSignal(QMetaObject::normalizedSignature("signal1()"));
4172  int slotIndx = rmeta->indexOfSlot(QMetaObject::normalizedSignature("slot1()"));
4173  QVERIFY( sigIndx != -1 );
4174  QVERIFY( slotIndx != -1 );
4175  QMetaMethod signal = smeta->method(sigIndx);
4176  QMetaMethod slot = rmeta->method(slotIndx);
4177 
4178  QVERIFY(connect(&s,signal, &r,slot));
4179 
4180  QVERIFY(!r.called(1));
4181  s.emitSignal1();
4182  QVERIFY(r.called(1));
4183 }
4184 
4185 void tst_QObject::connectByMetaMethodSlotInsteadOfSignal()
4186 {
4187  SenderObject s;
4188  ReceiverObject r;
4189  const QMetaObject *smeta = s.metaObject();
4190  const QMetaObject *rmeta = r.metaObject();
4191  int badIndx = smeta->indexOfSlot(QMetaObject::normalizedSignature("aPublicSlot()"));
4192  int slotIndx = rmeta->indexOfSlot(QMetaObject::normalizedSignature("slot1()"));
4193  QVERIFY( badIndx != -1 );
4194  QVERIFY( slotIndx != -1 );
4195  QMetaMethod badMethod = smeta->method(badIndx);
4196  QMetaMethod slot = rmeta->method(slotIndx);
4197 
4198  QTest::ignoreMessage(QtWarningMsg,"QObject::connect: Cannot connect SenderObject::aPublicSlot() to ReceiverObject::slot1()");
4199  QVERIFY(!connect(&s,badMethod, &r,slot));
4200 }
4201 
4202 class Constructable: public QObject
4203 {
4204  Q_OBJECT
4205 
4206 public:
4208 
4209 };
4210 
4211 void tst_QObject::connectConstructorByMetaMethod()
4212 {
4213  Constructable sc;
4214  Constructable rc;
4215  SenderObject s;
4216  ReceiverObject r;
4217 
4218  const QMetaObject cmeta = Constructable::staticMetaObject;
4219  const QMetaObject *smeta = s.metaObject();
4220  const QMetaObject *rmeta = r.metaObject();
4221  int constructorIndx = cmeta.indexOfConstructor(QMetaObject::normalizedSignature("Constructable()"));
4222  int sigIndx = smeta->indexOfSignal(QMetaObject::normalizedSignature("signal1()"));
4223  int slotIndx = rmeta->indexOfSlot(QMetaObject::normalizedSignature("slot1()"));
4224  QVERIFY( constructorIndx != -1 );
4225  QVERIFY( sigIndx != -1 );
4226  QVERIFY( slotIndx != -1 );
4227 
4228  QMetaMethod constructor = cmeta.constructor(constructorIndx);
4229  QMetaMethod signal = smeta->method(sigIndx);
4230  QMetaMethod slot = rmeta->method(slotIndx);
4231 
4232  QTest::ignoreMessage(QtWarningMsg,"QObject::connect: Cannot connect Constructable::Constructable() to ReceiverObject::slot1()");
4233  QVERIFY(!connect(&sc,constructor, &r,slot));
4234  QTest::ignoreMessage(QtWarningMsg,"QObject::connect: Cannot connect SenderObject::signal1() to Constructable::Constructable()");
4235  QVERIFY(!connect(&s,signal, &rc,constructor));
4236  QTest::ignoreMessage(QtWarningMsg,"QObject::connect: Cannot connect Constructable::Constructable() to Constructable::Constructable()");
4237  QVERIFY(!connect(&sc,constructor, &rc,constructor));
4238 }
4239 
4240 void tst_QObject::disconnectByMetaMethod()
4241 {
4242  SenderObject s;
4245 
4246  QMetaMethod signal1 = s.metaObject()->method(s.metaObject()->indexOfMethod("signal1()"));
4247  QMetaMethod signal2 = s.metaObject()->method(s.metaObject()->indexOfMethod("signal2()"));
4248  QMetaMethod signal3 = s.metaObject()->method(s.metaObject()->indexOfMethod("signal3()"));
4249 
4250  QMetaMethod slot1 = r1.metaObject()->method(r1.metaObject()->indexOfMethod("slot1()"));
4251  QMetaMethod slot2 = r1.metaObject()->method(r1.metaObject()->indexOfMethod("slot2()"));
4252  QMetaMethod slot3 = r1.metaObject()->method(r1.metaObject()->indexOfMethod("slot3()"));
4253  QMetaMethod slot4 = r1.metaObject()->method(r1.metaObject()->indexOfMethod("slot4()"));
4254 
4255  connect(&s, signal1, &r1, slot1);
4256 
4257  s.emitSignal1();
4258 
4259  QVERIFY(r1.called(1));
4260  r1.reset();
4261 
4262  // usual disconnect with all parameters given
4263  bool ret = QObject::disconnect(&s, signal1, &r1, slot1);
4264 
4265  s.emitSignal1();
4266 
4267  QVERIFY(!r1.called(1));
4268  r1.reset();
4269 
4270  QVERIFY(ret);
4271  ret = QObject::disconnect(&s, signal1, &r1, slot1);
4272  QVERIFY(!ret);
4273 
4274  r1.reset();
4275 
4276  connect(&s, signal1, &r1, slot1);
4277  connect(&s, signal1, &r1, slot2);
4278  connect(&s, signal1, &r1, slot3);
4279  connect(&s, signal2, &r1, slot4);
4280 
4281  // disconnect s's signal1() from all slots of r1
4282  QObject::disconnect(&s, signal1, &r1, QMetaMethod());
4283 
4284  s.emitSignal1();
4285  s.emitSignal2();
4286 
4287  QVERIFY(!r1.called(1));
4288  QVERIFY(!r1.called(2));
4289  QVERIFY(!r1.called(3));
4290  QVERIFY(r1.called(4));
4291  r1.reset();
4292  // make sure all is disconnected again
4293  QObject::disconnect(&s, 0, &r1, 0);
4294 
4295  connect(&s, signal1, &r1, slot1);
4296  connect(&s, signal1, &r2, slot1);
4297  connect(&s, signal2, &r1, slot2);
4298  connect(&s, signal2, &r2, slot2);
4299  connect(&s, signal3, &r1, slot3);
4300  connect(&s, signal3, &r2, slot3);
4301 
4302  // disconnect signal1() from all receivers
4303  QObject::disconnect(&s, signal1, 0, QMetaMethod());
4304  s.emitSignal1();
4305  s.emitSignal2();
4306  s.emitSignal3();
4307 
4308  QVERIFY(!r1.called(1));
4309  QVERIFY(!r2.called(1));
4310  QVERIFY(r1.called(2));
4311  QVERIFY(r2.called(2));
4312  QVERIFY(r1.called(2));
4313  QVERIFY(r2.called(2));
4314 
4315  r1.reset();
4316  r2.reset();
4317 
4318  // disconnect all signals of s from all receivers
4319  QObject::disconnect(&s, 0, 0, 0);
4320 
4321  connect(&s, signal1, &r1, slot1);
4322  connect(&s, signal1, &r2, slot1);
4323 
4324  // disconnect all signals from slot1 of r1
4326 
4327  s.emitSignal1();
4328 
4329  QVERIFY(!r1.called(1));
4330  QVERIFY(r2.called(1));
4331 }
4332 
4333 void tst_QObject::disconnectNotSignalMetaMethod()
4334 {
4335  SenderObject s;
4336  ReceiverObject r;
4337 
4338  connect(&s, SIGNAL(signal1()), &r, SLOT(slot1()));
4339 
4340  QMetaMethod slot = s.metaObject()->method(
4341  s.metaObject()->indexOfMethod("aPublicSlot()"));
4342 
4343  QTest::ignoreMessage(QtWarningMsg,"QObject::disconnect: Attempt to unbind non-signal SenderObject::aPublicSlot()");
4344  QVERIFY(!QObject::disconnect(&s, slot, &r, QMetaMethod()));
4345 }
4346 
4348 {
4349 public:
4351 
4353  : sender(sender)
4354  { }
4355  void run() override
4356  {
4357  sender->emitSignal1();
4358  }
4359 };
4360 
4361 void tst_QObject::autoConnectionBehavior()
4362 {
4364  ReceiverObject *receiver = new ReceiverObject;
4365  connect(sender, SIGNAL(signal1()), receiver, SLOT(slot1()));
4366 
4367  // at emit, currentThread == sender->thread(), currentThread == receiver->thread(), sender->thread() == receiver->thread()
4368  QVERIFY(!receiver->called(1));
4369  sender->emitSignal1();
4370  QVERIFY(receiver->called(1));
4371  receiver->reset();
4372 
4373  // at emit, currentThread != sender->thread(), currentThread != receiver->thread(), sender->thread() == receiver->thread()
4374  ThreadAffinityThread emitThread1(sender);
4375  QVERIFY(!receiver->called(1));
4376  emitThread1.start();
4377  QVERIFY(emitThread1.wait(30000));
4378  QVERIFY(!receiver->called(1));
4380  QVERIFY(receiver->called(1));
4381  receiver->reset();
4382 
4383  // at emit, currentThread == sender->thread(), currentThread != receiver->thread(), sender->thread() != receiver->thread()
4384  sender->moveToThread(&emitThread1);
4385  QVERIFY(!receiver->called(1));
4386  emitThread1.start();
4387  QVERIFY(emitThread1.wait(30000));
4388  QVERIFY(!receiver->called(1));
4390  QVERIFY(receiver->called(1));
4391  receiver->reset();
4392 
4393  // at emit, currentThread != sender->thread(), currentThread == receiver->thread(), sender->thread() != receiver->thread()
4394  QVERIFY(!receiver->called(1));
4395  sender->emitSignal1();
4396  QVERIFY(receiver->called(1));
4397  receiver->reset();
4398 
4399  // at emit, currentThread != sender->thread(), currentThread != receiver->thread(), sender->thread() != receiver->thread()
4400  ThreadAffinityThread emitThread2(sender);
4401  QThread receiverThread;
4402  QTimer *timer = new QTimer;
4403  timer->setSingleShot(true);
4404  timer->setInterval(100);
4405  connect(&receiverThread, SIGNAL(started()), timer, SLOT(start()));
4406  connect(timer, SIGNAL(timeout()), &receiverThread, SLOT(quit()), Qt::DirectConnection);
4407  connect(&receiverThread, SIGNAL(finished()), timer, SLOT(deleteLater()));
4408  timer->moveToThread(&receiverThread);
4409 
4410  receiver->moveToThread(&receiverThread);
4411  QVERIFY(!receiver->called(1));
4412  emitThread2.start();
4413  QVERIFY(emitThread2.wait(30000));
4414  QVERIFY(!receiver->called(1));
4415  receiverThread.start();
4416  QVERIFY(receiverThread.wait(30000));
4417  QVERIFY(receiver->called(1));
4418  receiver->reset();
4419 
4420  delete sender;
4421  delete receiver;
4422 }
4423 
4424 class BaseDestroyed : public QObject
4425 { Q_OBJECT
4426  QList<QString> fooList;
4427  bool destroyed;
4428 public:
4429  BaseDestroyed() : destroyed(false)
4430  { fooList << "a" << "b"; }
4432  {
4433  QVERIFY(!destroyed);
4434  destroyed = true;
4435  }
4436 
4437 public slots:
4439  {
4440  QVERIFY(!destroyed);
4441  fooList << "c" << "d";
4442  }
4443 };
4444 
4445 static void processEvents()
4446 {
4447  qApp->processEvents();
4448 }
4449 
4450 void tst_QObject::baseDestroyed()
4451 {
4452  {
4453  BaseDestroyed d;
4454  connect(&d, SIGNAL(destroyed()), &d, SLOT(slotUseList()));
4455  //When d goes out of scope, slotUseList should not be called as the BaseDestroyed has
4456  // already been destroyed while ~QObject emit destroyed
4457  }
4458  {
4459  BaseDestroyed d;
4460  connect(&d, &QObject::destroyed, processEvents);
4462  //the destructor will call processEvents, that should not call the slotUseList
4463  }
4464 }
4465 
4466 void tst_QObject::pointerConnect()
4467 {
4468  SenderObject s;
4471  r1.reset();
4472  r2.reset();
4474  QTimer timer;
4475 
4481  "Signal connection failed most likely due to failing comparison of pointers to member "
4482  "functions caused by problems with -reduce-relocations on this platform.");
4483 
4484  s.emitSignal1();
4485  s.emitSignal2();
4486  s.emitSignal3();
4487  s.emitSignal4();
4488 
4489  QCOMPARE(r1.count_slot1, 1);
4490  QCOMPARE(r1.count_slot2, 0);
4491  QCOMPARE(r1.count_slot3, 2);
4492  QCOMPARE(r1.count_slot4, 0);
4493  QCOMPARE(r2.count_slot1, 1);
4494  QCOMPARE(r2.count_slot2, 0);
4495  QCOMPARE(r2.count_slot3, 0);
4496  QCOMPARE(r2.count_slot4, 0);
4497  QCOMPARE(r1.sequence_slot1, 1);
4498  QCOMPARE(r2.sequence_slot1, 2);
4499  QCOMPARE(r1.sequence_slot3, 4);
4500 
4501  r1.reset();
4502  r2.reset();
4504 
4508 
4509  s.emitSignal4();
4510  QCOMPARE(r1.count_slot4, 1);
4511  QCOMPARE(r2.count_slot4, 1);
4512  QCOMPARE(r1.sequence_slot4, 1);
4513  QCOMPARE(r2.sequence_slot4, 2);
4514 
4515  r1.reset();
4516  r2.reset();
4518 
4520 
4521  s.emitSignal4();
4522  QCOMPARE(r1.count_slot4, 2);
4523  QCOMPARE(r2.count_slot4, 1);
4524  QCOMPARE(r1.sequence_slot4, 3);
4525  QCOMPARE(r2.sequence_slot4, 2);
4526 
4528  QVERIFY(!con);
4530 
4531  //connect a slot to a signal (== error)
4532  QTest::ignoreMessage(QtWarningMsg, "QObject::connect: signal not found in ReceiverObject");
4534  QVERIFY(!con);
4536 }
4537 
4538 void tst_QObject::pointerDisconnect()
4539 {
4540  SenderObject s;
4543 
4545 
4549 
4550  s.emitSignal1();
4551  s.emitSignal2();
4552  s.emitSignal3();
4553  s.emitSignal4();
4554 
4555  QVERIFY(r1.called(1));
4556  QVERIFY(r1.called(2));
4557  QVERIFY(r1.called(3));
4558  QVERIFY(r1.called(4));
4559  r1.reset();
4560 
4561  // usual disconnect with all parameters given
4563 
4564  s.emitSignal1();
4565 
4566  QVERIFY(!r1.called(1));
4567  r1.reset();
4568 
4569  QVERIFY(ret);
4571  QVERIFY(!ret);
4572 
4573  // disconnect all signals from s from all slots from r1
4574  QObject::disconnect(&s, 0, &r1, 0);
4575 
4576  s.emitSignal2();
4577  s.emitSignal3();
4578  s.emitSignal4();
4579 
4580  QVERIFY(!r1.called(2));
4581  QVERIFY(!r1.called(3));
4582  QVERIFY(!r1.called(4));
4583  r1.reset();
4584 
4589 
4590  // disconnect s's signal1() from all slots of r1
4592 
4593  s.emitSignal1();
4594  s.emitSignal2();
4595 
4596  QVERIFY(!r1.called(1));
4597  QVERIFY(!r1.called(2));
4598  QVERIFY(!r1.called(3));
4599  QVERIFY(r1.called(4));
4600  r1.reset();
4601  // make sure all is disconnected again
4602  QObject::disconnect(&s, 0, &r1, 0);
4603 
4610 
4611  // disconnect signal1() from all receivers
4613  s.emitSignal1();
4614  s.emitSignal2();
4615  s.emitSignal3();
4616 
4617  QVERIFY(!r1.called(1));
4618  QVERIFY(!r2.called(1));
4619  QVERIFY(r1.called(2));
4620  QVERIFY(r2.called(2));
4621  QVERIFY(r1.called(2));
4622  QVERIFY(r2.called(2));
4623 
4624  r1.reset();
4625  r2.reset();
4626 
4627  // disconnect all signals of s from all receivers
4628  QObject::disconnect(&s, 0, 0, 0);
4629 
4630  QVERIFY(!r1.called(2));
4631  QVERIFY(!r2.called(2));
4632  QVERIFY(!r1.called(2));
4633  QVERIFY(!r2.called(2));
4634 }
4635 
4636 
4637 void tst_QObject::emitInDefinedOrderPointer()
4638 {
4640  ReceiverObject receiver1, receiver2, receiver3, receiver4;
4641 
4644  QVERIFY(h0);
4645  QVERIFY(h1);
4652 
4653  int sequence;
4654  ReceiverObject::sequence = sequence = 0;
4655  sender.emitSignal1();
4656  QCOMPARE(receiver1.sequence_slot1, ++sequence);
4657  QCOMPARE(receiver2.sequence_slot1, ++sequence);
4658  QCOMPARE(receiver3.sequence_slot1, ++sequence);
4659  QCOMPARE(receiver4.sequence_slot1, ++sequence);
4660  QCOMPARE(receiver1.sequence_slot2, ++sequence);
4661  QCOMPARE(receiver2.sequence_slot2, ++sequence);
4662  QCOMPARE(receiver3.sequence_slot2, ++sequence);
4663  QCOMPARE(receiver4.sequence_slot2, ++sequence);
4664 
4665  QObject::disconnect(h1);
4667 
4668  ReceiverObject::sequence = sequence = 0;
4669  sender.emitSignal1();
4670  QCOMPARE(receiver1.sequence_slot1, ++sequence);
4671  QCOMPARE(receiver3.sequence_slot1, ++sequence);
4672  QCOMPARE(receiver4.sequence_slot1, ++sequence);
4673  QCOMPARE(receiver1.sequence_slot2, ++sequence);
4674  QCOMPARE(receiver2.sequence_slot2, ++sequence);
4675  QCOMPARE(receiver3.sequence_slot2, ++sequence);
4676  QCOMPARE(receiver4.sequence_slot2, ++sequence);
4677  QCOMPARE(receiver2.sequence_slot1, ++sequence);
4678 
4679  QObject::disconnect(h0);
4681 
4682  ReceiverObject::sequence = sequence = 0;
4683  sender.emitSignal1();
4684  QCOMPARE(receiver3.sequence_slot1, ++sequence);
4685  QCOMPARE(receiver4.sequence_slot1, ++sequence);
4686  QCOMPARE(receiver1.sequence_slot2, ++sequence);
4687  QCOMPARE(receiver2.sequence_slot2, ++sequence);
4688  QCOMPARE(receiver3.sequence_slot2, ++sequence);
4689  QCOMPARE(receiver4.sequence_slot2, ++sequence);
4690  QCOMPARE(receiver2.sequence_slot1, ++sequence);
4691  QCOMPARE(receiver1.sequence_slot1, ++sequence);
4692 
4695 }
4696 
4697 
4698 void tst_QObject::customTypesPointer()
4699 {
4700  CustomType t0;
4701  CustomType t1(1, 2, 3);
4702  CustomType t2(2, 3, 4);
4703 
4704  {
4705  QCustomTypeChecker checker;
4706  QCOMPARE(instanceCount, 4);
4707 
4710  QCOMPARE(checker.received.value(), 0);
4711  checker.doEmit(t1);
4712  QCOMPARE(checker.received.value(), t1.value());
4713  checker.received = t0;
4714 
4715 
4716  checker.disconnect();
4717 
4718  int idx = qRegisterMetaType<CustomType>("CustomType");
4719  QCOMPARE(QMetaType::type("CustomType"), idx);
4720 
4723  QCOMPARE(instanceCount, 4);
4724  checker.doEmit(t2);
4725  QCOMPARE(instanceCount, 5);
4726  QCOMPARE(checker.received.value(), t0.value());
4727 
4729  QCOMPARE(checker.received.value(), t2.value());
4730  QCOMPARE(instanceCount, 4);
4731 
4733  QCOMPARE(qRegisterMetaType<CustomType>("CustomType"), idx);
4734  QCOMPARE(QMetaType::type("CustomType"), idx);
4736 
4737  // Test auto registered type (QList<CustomType>)
4739  QCOMPARE(instanceCount, 4);
4740  list.append(t1);
4741  QCOMPARE(instanceCount, 5);
4744  emit checker.signal2(list);
4745  QCOMPARE(instanceCount, 5); //because the list is implicitly shared.
4746  list.clear();
4747  QCOMPARE(instanceCount, 5);
4749  QCOMPARE(checker.received.value(), t1.value());
4750  QCOMPARE(instanceCount, 4);
4751  }
4752  QCOMPARE(instanceCount, 3);
4753 }
4754 
4755 void tst_QObject::connectCxx0x()
4756 {
4757  SenderObject s;
4759 
4764 
4765  r1.reset();
4766  QCOMPARE(r1.count_slot1, 0);
4767  QCOMPARE(r1.count_slot2, 0);
4768 
4769  s.emitSignal1();
4770  QCOMPARE(r1.count_slot1, 1);
4771  QCOMPARE(r1.count_slot2, 0);
4772 
4773  s.emitSignal3();
4774  QCOMPARE(r1.count_slot1, 1);
4775  QCOMPARE(r1.count_slot2, 3);
4776 
4777  // connect signal to signal
4779 
4780  r1.reset();
4781  s.emitSignal2();
4782  QCOMPARE(r1.count_slot1, 1);
4783 }
4784 
4787 
4788 void tst_QObject::connectToStaticCxx0x()
4789 {
4790  SenderObject *s = new SenderObject;
4791 
4792  void (*receiver)() = receiverFunction;
4793 
4795  receivedCount = 0;
4796  s->emitSignal1();
4797  QCOMPARE(receivedCount, 1);
4798 
4800  receivedCount = 0;
4801  s->emitSignal1();
4802  QCOMPARE(receivedCount, 2);
4803 
4804  delete s;
4805 }
4806 
4808 {
4809  Q_OBJECT
4810  typedef void (*fptr)();
4811 
4812  public slots:
4813  void slot_v() {}
4814  void slot_v_noexcept() noexcept {}
4815  void slot_vi(int) {}
4816  void slot_vi_noexcept() noexcept {}
4817  void slot_vii(int, int) {}
4818  void slot_viii(int, int, int) {}
4819  int slot_i() { return 0; }
4820  int slot_i_noexcept() noexcept { return 0; }
4821  int slot_ii(int) { return 0; }
4822  int slot_iii(int, int) { return 0; }
4823  int slot_iiii(int, int, int) { return 0; }
4824  void slot_vRi(int &) {}
4825  void slot_vs(short) {}
4826  void slot_vRs(short&) {}
4827  /* #ifdef Q_COMPILER_RVALUE_REFS
4828  void slot_vOi(int &&) {}
4829  void slot_vOs(short &&) {}
4830  #endif*/
4831  void slot_vPFvvE(fptr) {}
4832 
4833  void const_slot_v() const {};
4834  void const_slot_v_noexcept() const noexcept {}
4835  void const_slot_vi(int) const {};
4836  void const_slot_vi_noexcept(int) const noexcept {}
4837 
4838  static void static_slot_v() {}
4839  static void static_slot_v_noexcept() noexcept {}
4840  static void static_slot_vi(int) {}
4841  static void static_slot_vi_noexcept(int) noexcept {}
4842  static void static_slot_vii(int, int) {}
4843  static void static_slot_viii(int, int, int) {}
4844  static int static_slot_i() { return 0; }
4845  static int static_slot_i_noexcept() noexcept { return 0; }
4846  static int static_slot_ii(int) { return 0; }
4847  static int static_slot_iii(int, int) { return 0; }
4848  static int static_slot_iiii(int, int, int) { return 0; }
4849  static void static_slot_vRi(int &) {}
4850  static void static_slot_vs(short) {}
4851  static void static_slot_vRs(short&) {}
4852 /* #if defined(Q_COMPILER_RVALUE_REFS) || defined(QT_ENABLE_CXX0X)
4853  static void static_slot_vOi(int &&) {}
4854  static void static_slot_vOs(short &&) {}
4855  #endif*/
4856  static void static_slot_vPFvvE(fptr) {}
4857 
4858  void slot_vcRQObject(const QObject &) {}
4860 
4861  signals:
4862  void signal_v();
4863  void signal_vi(int);
4864  void signal_vii(int, int);
4865  void signal_viii(int, int, int);
4866  void signal_vRi(int &);
4867  void signal_vs(short);
4868  void signal_vRs(short &);
4869 /* #if defined(Q_COMPILER_RVALUE_REFS) || defined(QT_ENABLE_CXX0X)
4870  void signal_vOi(int &&);
4871  void signal_vOs(short &&);
4872  #endif*/
4873  void signal_vPFvvE(fptr);
4874 
4875  void const_signal_v() const;
4876  void const_signal_vi(int) const;
4877 
4880 
4881  void signal(short&, short, long long, short);
4882  void otherSignal(const char *);
4883 };
4884 
4885 void tst_QObject::connectCxx0xTypeMatching()
4886 {
4887  // this is just about connecting the signals to the slots
4888  // if this fails, this will be a compiler failure
4889  typedef LotsOfSignalsAndSlots Foo;
4890  Foo obj;
4891 
4892  // member connects
4893  QObject::connect(&obj, &Foo::signal_v, &obj, &Foo::slot_v);
4894  QObject::connect(&obj, &Foo::signal_v, &obj, &Foo::slot_i);
4895 
4896  QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::slot_v);
4897  QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::slot_i);
4898  QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::slot_vi);
4899  QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::slot_ii);
4900 
4901  QObject::connect(&obj, &Foo::signal_vii, &obj, &Foo::slot_v);
4902  QObject::connect(&obj, &Foo::signal_vii, &obj, &Foo::slot_i);
4903  QObject::connect(&obj, &Foo::signal_vii, &obj, &Foo::slot_vi);
4904  QObject::connect(&obj, &Foo::signal_vii, &obj, &Foo::slot_ii);
4905  QObject::connect(&obj, &Foo::signal_vii, &obj, &Foo::slot_vii);
4906  QObject::connect(&obj, &Foo::signal_vii, &obj, &Foo::slot_iii);
4907 
4908  QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_v);
4909  QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_i);
4910  QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_vi);
4911  QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_ii);
4912  QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_vii);
4913  QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_iii);
4914  QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_viii);
4915  QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_iiii);
4916 
4917  QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::slot_vi); // repeated from above
4918  QObject::connect(&obj, &Foo::signal_vRi, &obj, &Foo::slot_vi);
4919  QObject::connect(&obj, &Foo::signal_vRi, &obj, &Foo::slot_vRi);
4920 /*#if defined(Q_COMPILER_RVALUE_REFS) || defined(QT_ENABLE_CXX0X)
4921  QObject::connect(&obj, &Foo::signal_vOi, &obj, &Foo::slot_vi);
4922  QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::slot_vOi);
4923  QObject::connect(&obj, &Foo::signal_vRi, &obj, &Foo::slot_vOi);
4924  QObject::connect(&obj, &Foo::signal_vOi, &obj, &Foo::slot_vOi);
4925 #endif*/
4926  // these are not supposed to compile:
4927  //QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::slot_vRi);
4928  //QObject::connect(&obj, &Foo::signal_vOi, &obj, &Foo::slot_vRi);
4929 
4930  QObject::connect(&obj, &Foo::signal_vs, &obj, &Foo::slot_vi);
4931  QObject::connect(&obj, &Foo::signal_vRs, &obj, &Foo::slot_vi);
4932 /*#if defined(Q_COMPILER_RVALUE_REFS) || defined(QT_ENABLE_CXX0X)
4933  QObject::connect(&obj, &Foo::signal_vOs, &obj, &Foo::slot_vi);
4934  QObject::connect(&obj, &Foo::signal_vRs, &obj, &Foo::slot_vOi);
4935  QObject::connect(&obj, &Foo::signal_vOs, &obj, &Foo::slot_vOi);
4936  // these are not supposed to compile:
4937  //QObject::connect(&obj, &Foo::signal_vOs, &obj, &Foo::slot_vRi);
4938  //QObject::connect(&obj, &Foo::signal_vRs, &obj, &Foo::slot_vRi);
4939 #endif*/
4940 
4941  QObject::connect(&obj, &Foo::signal_vPFvvE, &obj, &Foo::slot_v);
4942  QObject::connect(&obj, &Foo::signal_vPFvvE, &obj, &Foo::slot_i);
4943  QObject::connect(&obj, &Foo::signal_vPFvvE, &obj, &Foo::slot_vPFvvE);
4944 
4945  QObject::connect(&obj, &Foo::signal_v, &Foo::static_slot_v);
4946  QObject::connect(&obj, &Foo::signal_v, &Foo::static_slot_i);
4947 
4948  QObject::connect(&obj, &Foo::signal_vi, &Foo::static_slot_v);
4949  QObject::connect(&obj, &Foo::signal_vi, &Foo::static_slot_i);
4950  QObject::connect(&obj, &Foo::signal_vi, &Foo::static_slot_vi);
4951  QObject::connect(&obj, &Foo::signal_vi, &Foo::static_slot_ii);
4952 
4953  QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_v);
4954  QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_i);
4955  QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_vi);
4956  QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_ii);
4957  QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_vii);
4958  QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_iii);
4959 
4960  QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_v);
4961  QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_i);
4962  QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_vi);
4963  QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_ii);
4964  QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_vii);
4965  QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_iii);
4966  QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_viii);
4967  QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_iiii);
4968 
4969 /*#if defined(Q_COMPILER_RVALUE_REFS) && defined(QT_ENABLE_CXX0X)
4970  QObject::connect(&obj, &Foo::signal_vi, &Foo::static_slot_vOi);
4971  QObject::connect(&obj, &Foo::signal_vRi, &Foo::static_slot_vi);
4972  QObject::connect(&obj, &Foo::signal_vRi, &Foo::static_slot_vRi);
4973  QObject::connect(&obj, &Foo::signal_vRi, &Foo::static_slot_vOi);
4974  QObject::connect(&obj, &Foo::signal_vOi, &Foo::static_slot_vi);
4975  QObject::connect(&obj, &Foo::signal_vOi, &Foo::static_slot_vOi);
4976  //QObject::connect(&obj, &Foo::signal_vi, &Foo::static_slot_vRi);
4977  //QObject::connect(&obj, &Foo::signal_vOi, &Foo::static_slot_vRi);
4978 #endif*/
4979 
4980  QObject::connect(&obj, &Foo::signal_vs, &Foo::static_slot_vi);
4981  QObject::connect(&obj, &Foo::signal_vRs, &Foo::static_slot_vi);
4982 /*#if defined(Q_COMPILER_RVALUE_REFS) && defined(QT_ENABLE_CXX0X)
4983  QObject::connect(&obj, &Foo::signal_vOs, &Foo::static_slot_vi);
4984  QObject::connect(&obj, &Foo::signal_vRs, &Foo::static_slot_vOi);
4985  QObject::connect(&obj, &Foo::signal_vOs, &Foo::static_slot_vOi);
4986  //QObject::connect(&obj, &Foo::signal_vOs, &Foo::static_slot_vRi);
4987  //QObject::connect(&obj, &Foo::signal_vRs, &Foo::static_slot_vRi);
4988 #endif*/
4989  QObject::connect(&obj, &Foo::signal_vPFvvE, &Foo::static_slot_v);
4990  QObject::connect(&obj, &Foo::signal_vPFvvE, &Foo::static_slot_i);
4991  QObject::connect(&obj, &Foo::signal_vPFvvE, &Foo::static_slot_vPFvvE);
4992 
4993  QVERIFY(QObject::connect(&obj, &Foo::const_signal_v, &obj, &Foo::const_slot_v));
4994  QVERIFY(QObject::connect(&obj, &Foo::const_signal_vi, &obj, &Foo::const_slot_v));
4995  QVERIFY(QObject::connect(&obj, &Foo::const_signal_vi, &obj, &Foo::slot_vi));
4996  QVERIFY(QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::const_slot_vi));
4997  QVERIFY(QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::const_slot_v));
4998 
4999  QVERIFY(QObject::connect(&obj, &Foo::signal_vcRQObject, &obj, &Foo::slot_vcRQObject));
5000  QVERIFY(QObject::connect(&obj, &Foo::signal_vRQObject, &obj, &Foo::slot_vRQObject));
5001  QVERIFY(QObject::connect(&obj, &Foo::signal_vRQObject, &obj, &Foo::slot_vcRQObject));
5002  // QVERIFY(QObject::connect(&obj, &Foo::signal_vcRQObject, &obj, &Foo::slot_vRQObject)); // Should be an error (const& -> &)
5003 
5004  QVERIFY(QObject::connect(&obj, &Foo::signal_vRi, &obj, &Foo::slot_vs));
5005 
5006 }
5007 
5008 void receiverFunction_noexcept() noexcept {}
5009 struct Functor_noexcept { void operator()() noexcept {} };
5010 void tst_QObject::connectCxx17Noexcept()
5011 {
5012  // this is about connecting signals to slots with the noexcept qualifier
5013  // as semantics changed due to http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0012r1.html
5014  typedef LotsOfSignalsAndSlots Foo;
5015  Foo obj;
5016 
5017  QObject::connect(&obj, &Foo::signal_v, &obj, &Foo::slot_v_noexcept);
5018  QObject::connect(&obj, &Foo::signal_v, &obj, &Foo::slot_i_noexcept);
5019  QObject::connect(&obj, &Foo::signal_v, &obj, &Foo::slot_vi_noexcept);
5020 
5021  QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_v_noexcept);
5022  QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_i_noexcept);
5023  QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_vi_noexcept);
5024 
5025  QVERIFY(QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::const_slot_vi_noexcept));
5026  QVERIFY(QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::const_slot_v_noexcept));
5027 
5028  QObject::connect(&obj, &Foo::signal_v, receiverFunction_noexcept);
5029 
5031  QObject::connect(&obj, &Foo::signal_v, fn);
5032 }
5033 
5034 class StringVariant : public QObject
5035 { Q_OBJECT
5036 signals:
5037  void stringSignal(const QString &str);
5038 public slots:
5039  void variantSlot(const QVariant &v) { var = v; }
5040 public:
5042  friend class tst_QObject;
5043 };
5044 
5045 struct Functor {
5047  void operator() (const QVariant &v) {
5048  *var = v;
5049  }
5050 };
5051 
5052 void tst_QObject::connectConvert()
5053 {
5056  QString s = QString::fromLatin1("Hello World");
5057  emit obj.stringSignal(s);
5058  QCOMPARE(obj.var.toString(), s);
5059  QVERIFY(obj.var.toString().isSharedWith(s));
5060 
5061  QVariant var;
5062  Functor f;
5063  f.var = &var;
5065  s = QString::fromLatin1("GoodBye");
5066  emit obj.stringSignal(s);
5067  QCOMPARE(obj.var.toString(), s);
5068  QVERIFY(obj.var.toString().isSharedWith(s));
5069  QCOMPARE(var, obj.var);
5070 }
5071 
5073  Q_OBJECT
5074  friend class tst_QObject;
5075 signals:
5076  void boolRef(bool &, bool);
5077  void stringRef(QString &, const QString &);
5078  void boolPtr(bool *, bool);
5079  void stringPtr(QString *, const QString &);
5080 public slots:
5081  void boolRefSlot(bool &b1, bool b2) { b1 = b2; }
5082  void stringRefSlot(QString &s1, const QString &s2) { s1 = s2; }
5083  void boolPtrSlot(bool *b1, bool b2) { *b1 = b2; }
5084  void stringPtrSlot(QString *s1, const QString &s2) { *s1 = s2; }
5085 
5086  void stringSlot1(QString s) { last = s; }
5087  void stringSlot2(const QString &s) { last = s; }
5088  void stringSlot3(QString &s) { last = s; }
5089 public:
5091 };
5092 
5093 void tst_QObject::connectWithReference()
5094 {
5096  bool b1 = true;
5097  QString s1 = QString::fromLatin1("str1");
5098  const QString s2 = QString::fromLatin1("str2");
5099  const QString s3 = QString::fromLatin1("str3");
5100  o.boolRef(b1, false);
5101  o.stringRef(s1, s2);
5102  QCOMPARE(b1, true);
5103  QCOMPARE(s1, QString::fromLatin1("str1"));
5104  o.boolPtr(&b1, false);
5105  o.stringPtr(&s1, s2);
5106  QCOMPARE(b1, true);
5107  QCOMPARE(s1, QString::fromLatin1("str1"));
5108 
5113  o.boolRef(b1, false);
5114  o.stringRef(s1, s2);
5115  QCOMPARE(b1, false);
5116  QCOMPARE(s1, QString::fromLatin1("str2"));
5117 
5118  o.boolPtr(&b1, true);
5119  o.stringPtr(&s1, s3);
5120  QCOMPARE(b1, true);
5121  QCOMPARE(s1, QString::fromLatin1("str3"));
5122 
5123  {
5126  o2.stringRef(s1, s2);
5127  QCOMPARE(s1, s3);
5128  QCOMPARE(o2.last, s3);
5129  }
5130  {
5133  o2.stringRef(s1, s2);
5134  QCOMPARE(s1, s3);
5135  QCOMPARE(o2.last, s3);
5136  }
5137  {
5140  o2.stringRef(s1, s2);
5141  QCOMPARE(s1, s3);
5142  QCOMPARE(o2.last, s3);
5143  }
5144 }
5145 
5146 class ManyArgumentObject : public QObject {
5147  Q_OBJECT
5148 signals:
5149  void signal1(const QString &);
5150  void signal2(const QString &, const QString &);
5151  void signal3(const QString &, const QString &, const QString &);
5152  void signal4(const QString &, const QString &, const QString &, const QString&);
5153  void signal5(const QString &, const QString &, const QString &, const QString&, const QString&);
5154  void signal6(const QString &, const QString &, const QString &, const QString&, const QString&, const QString&);
5155 
5156 public slots:
5157 #define MANYARGUMENT_COMPARE(L) QCOMPARE(L, QString(#L))
5158  void slot1(const QString &a) {
5160  count++;
5161  }
5162  void slot2(const QString &a, const QString &b) {
5164  count++;
5165  }
5166  void slot3(const QString &a, const QString &b, const QString &c) {
5168  count++;
5169  }
5170  void slot4(const QString &a, const QString &b, const QString &c, const QString&d) {
5173  count++;
5174  }
5175  void slot5(const QString &a, const QString &b, const QString &c, const QString&d, const QString&e) {
5178  count++;
5179  }
5180  void slot6(const QString &a, const QString &b, const QString &c, const QString&d, const QString&e, const QString&f) {
5183  count++;
5184  }
5185 public:
5186  int count;
5187 
5188 };
5189 
5191  int count;
5192  void slot1(const QString &a) {
5194  count++;
5195  }
5196  void slot2(const QString &a, const QString &b) {
5198  count++;
5199  }
5200  void slot3(const QString &a, const QString &b, const QString &c) {
5202  count++;
5203  }
5204  void slot4(const QString &a, const QString &b, const QString &c, const QString&d) {
5207  count++;
5208  }
5209  void slot5(const QString &a, const QString &b, const QString &c, const QString&d, const QString&e) {
5212  count++;
5213  }
5214  void slot6(const QString &a, const QString &b, const QString &c, const QString&d, const QString&e, const QString&f) {
5217  count++;
5218  }
5219 
5220  struct Funct1 {
5221  void operator()(const QString &a) {
5223  count++;
5224  }
5225  };
5226 
5227  struct Funct2 {
5228  void operator()(const QString &a, const QString &b) {
5230  count++;
5231  }
5232  };
5233 
5234  struct Funct3 {
5235  void operator()(const QString &a, const QString &b, const QString &c) {
5237  count++;
5238  }
5239  };
5240 
5241  struct Funct4 {
5242  void operator()(const QString &a, const QString &b, const QString &c, const QString&d) {
5245  count++;
5246  }
5247  };
5248 
5249  struct Funct5 {
5250  void operator()(const QString &a, const QString &b, const QString &c, const QString&d, const QString&e) {
5253  count++;
5254  }
5255  };
5256 
5257  struct Funct6 final {
5258  void operator()(const QString &a, const QString &b, const QString &c, const QString&d, const QString&e, const QString&f) {
5261  count++;
5262  }
5263  };
5264 }
5265 
5266 void tst_QObject::connectManyArguments()
5267 {
5269  ob.count = 0;
5283 
5284 
5290 
5291  emit ob.signal6("a", "b", "c", "d", "e", "f");
5292  QCOMPARE(ob.count, 6);
5294 
5295 
5296  ManyArgumentObject ob2;
5297  ob2.count = 0;
5317 
5318  emit ob2.signal6("a", "b", "c", "d", "e", "f");
5319  QCOMPARE(ob2.count, 6);
5321 }
5322 
5323 class ForwardDeclared;
5324 
5326 {
5327  Q_OBJECT
5328 signals:
5330 public slots:
5331  void mySlot(const ForwardDeclared&) {}
5332 };
5333 
5334 void tst_QObject::connectForwardDeclare()
5335 {
5337  // it should compile
5339 }
5340 
5341 class ForwardDeclared {}; // complete definition for moc
5342 
5344 {
5345  Q_GADGET
5346 public:
5348 };
5349 
5351 {
5352  Q_OBJECT
5353 signals:
5355 public slots:
5357 };
5358 
5359 void tst_QObject::connectNoDefaultConstructorArg()
5360 {
5362  // it should compile
5364 }
5365 
5366 struct MoveOnly
5367 {
5368  int value;
5369  explicit MoveOnly(int v = 1) : value(v) {}
5370  MoveOnly(MoveOnly &&o) : value(o.value) { o.value = -1; }
5371  MoveOnly &operator=(MoveOnly &&o) { value = o.value; o.value = -1; return *this; }
5373 };
5374 
5375 class ReturnValue : public QObject {
5376 friend class tst_QObject;
5377 Q_OBJECT
5378 signals:
5381  int returnInt(int);
5382  void returnVoid(int);
5385 
5387 public slots:
5388  QVariant returnVariantSlot(int i) { return i; }
5390  int returnIntSlot(int i) { return i; }
5392  void returnVoidSlot() {}
5393  int return23() { return 23; }
5394  QString returnHello() { return QStringLiteral("hello"); }
5395  QObject *returnThisSlot1() { return this; }
5396  ReturnValue *returnThisSlot2() { return this; }
5398 public:
5400  QVariant operator()(int i) { return i; }
5401  };
5403  CustomType operator()(int i) { return CustomType(i); }
5404  };
5405  struct StringFunctor {
5407  };
5408  struct IntFunctor {
5409  int operator()(int i) { return i; }
5410  };
5411  struct VoidFunctor {
5412  void operator()(int) {}
5413  };
5415  MoveOnly operator()(int i) { return MoveOnly(i); }
5416  };
5417 };
5418 
5420  return '\'' + QString::number(i) + '\'';
5421 }
5422 
5423 void tst_QObject::returnValue_data()
5424 {
5425  QTest::addColumn<bool>("isBlockingQueued");
5426 
5427  QTest::newRow("DirectConnection") << false;
5428  QTest::newRow("BlockingQueuedConnection") << true;
5429 }
5430 
5431 void tst_QObject::returnValue()
5432 {
5433  CheckInstanceCount checker;
5434 
5435  QFETCH(bool, isBlockingQueued);
5436  QThread thread;
5437  ReturnValue receiver;
5439  if (isBlockingQueued) {
5440  thread.start();
5441  receiver.moveToThread(&thread);
5443  }
5444 
5445  { // connected to nothing
5446  CheckInstanceCount checker;
5447  ReturnValue r;
5448  QCOMPARE(emit r.returnVariant(45), QVariant());
5449  QCOMPARE(emit r.returnString(45), QString());
5450  QCOMPARE(emit r.returnInt(45), int());
5451  emit r.returnVoid(45);
5452  QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value());
5453  QCOMPARE((emit r.returnPointer()), static_cast<QObject *>(0));
5454  QCOMPARE((emit r.returnMoveOnly(666)).value, MoveOnly().value);
5455  }
5456  { // connected to a slot returning the same type
5457  CheckInstanceCount checker;
5458  ReturnValue r;
5460  QCOMPARE(emit r.returnVariant(45), QVariant(45));
5462  QCOMPARE(emit r.returnString(45), QString::fromLatin1("45"));
5464  QCOMPARE(emit r.returnInt(45), int(45));
5466  QCOMPARE((emit r.returnCustomType(45)).value(), CustomType(45).value());
5468  QCOMPARE((emit r.returnPointer()), static_cast<QObject *>(&receiver));
5470  QCOMPARE((emit r.returnMoveOnly(666)).value, 666);
5471  }
5472  if (!isBlockingQueued) { // connected to simple functions or functor
5473  CheckInstanceCount checker;
5474  ReturnValue r;
5476  QCOMPARE(emit r.returnString(49), QString::fromLatin1("'49'"));
5477 
5478  ReturnValue::CustomTypeFunctor customTypeFunctor;
5479  QVERIFY(connect(&r, &ReturnValue::returnCustomType, customTypeFunctor));
5480  QCOMPARE((emit r.returnCustomType(49)).value(), CustomType(49).value());
5481 
5482  ReturnValue::VariantFunctor variantFunctor;
5483  QVERIFY(connect(&r, &ReturnValue::returnVariant, variantFunctor));
5484  QCOMPARE(emit r.returnVariant(45), QVariant(45));
5485 
5486  ReturnValue::IntFunctor intFunctor;
5487  QVERIFY(connect(&r, &ReturnValue::returnInt, intFunctor));
5488  QCOMPARE(emit r.returnInt(45), int(45));
5489 
5490  ReturnValue::MoveOnlyFunctor moveOnlyFunctor;
5491  QVERIFY(connect(&r, &ReturnValue::returnMoveOnly, moveOnlyFunctor));
5492  QCOMPARE((emit r.returnMoveOnly(666)).value, 666);
5493  }
5494  { // connected to a slot with different type
5495  CheckInstanceCount checker;
5496  ReturnValue r;
5498  QCOMPARE(emit r.returnVariant(48), QVariant(QString::fromLatin1("48")));
5500  QCOMPARE((emit r.returnCustomType(48)).value(), CustomType(48).value());
5502  emit r.returnVoid(48);
5504  QCOMPARE((emit r.returnPointer()), static_cast<QObject *>(&receiver));
5505  }
5506  if (!isBlockingQueued) { // connected to functor with different type
5507  CheckInstanceCount checker;
5508  ReturnValue r;
5509 
5510  ReturnValue::CustomTypeFunctor customTypeFunctor;
5511  QVERIFY(connect(&r, &ReturnValue::returnCustomType, customTypeFunctor));
5512  QCOMPARE((emit r.returnCustomType(49)).value(), CustomType(49).value());
5513 
5514  ReturnValue::StringFunctor stringFunctor;
5515  QVERIFY(connect(&r, &ReturnValue::returnVariant, stringFunctor));
5516  QCOMPARE(emit r.returnVariant(45), QVariant(QString::fromLatin1("45")));
5517  }
5518  { // connected to a void
5519  CheckInstanceCount checker;
5520  ReturnValue r;
5522  QCOMPARE(emit r.returnVariant(45), QVariant());
5524  QCOMPARE(emit r.returnString(45), QString());
5526  QCOMPARE(emit r.returnInt(45), int());
5528  QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value());
5530  QCOMPARE((emit r.returnPointer()), static_cast<QObject *>(0));
5532  QCOMPARE((emit r.returnMoveOnly(666)).value, MoveOnly().value);
5533  }
5534  if (!isBlockingQueued) {
5535  // queued connection should not forward the return value
5536  CheckInstanceCount checker;
5537  ReturnValue r;
5539  QCOMPARE(emit r.returnVariant(45), QVariant());
5541  QCOMPARE(emit r.returnString(45), QString());
5543  QCOMPARE(emit r.returnInt(45), int());
5545  QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value());
5547  QCOMPARE((emit r.returnPointer()), static_cast<QObject *>(0));
5549  QCOMPARE((emit r.returnMoveOnly(666)).value, MoveOnly().value);
5550 
5552 
5554  QCOMPARE(emit r.returnVariant(48), QVariant());
5556  QCOMPARE((emit r.returnCustomType(48)).value(), CustomType().value());
5558  emit r.returnVoid(48);
5560  }
5561 
5562  { // connected to many slots
5563  ReturnValue::VoidFunctor voidFunctor;
5564  ReturnValue::IntFunctor intFunctor;
5565  ReturnValue r;
5567  QCOMPARE(emit r.returnVariant(45), QVariant(45));
5569  QCOMPARE(emit r.returnVariant(45), QVariant(23));
5571  QCOMPARE(emit r.returnVariant(45), QVariant(23));
5573  QCOMPARE(emit r.returnVariant(45), QVariant(QStringLiteral("hello")));
5574  QVERIFY(connect(&r, &ReturnValue::returnVariant, voidFunctor));
5575  QCOMPARE(emit r.returnVariant(45), QVariant(QStringLiteral("hello")));
5576  QVERIFY(connect(&r, &ReturnValue::returnVariant, intFunctor));
5577  QCOMPARE(emit r.returnVariant(45), QVariant(45));
5579  QCOMPARE(emit r.returnVariant(45), QVariant(45));
5580 
5581  QCOMPARE(emit r.returnInt(45), int());
5583  QCOMPARE(emit r.returnInt(45), int());
5585  QCOMPARE(emit r.returnInt(45), int(45));
5587  QCOMPARE(emit r.returnInt(45), int(23));
5588  QVERIFY(connect(&r, &ReturnValue::returnInt, voidFunctor));
5589  QCOMPARE(emit r.returnInt(45), int(23));
5590  QVERIFY(connect(&r, &ReturnValue::returnInt, intFunctor));
5591  QCOMPARE(emit r.returnInt(45), int(45));
5593  QCOMPARE(emit r.returnInt(45), int(45));
5594 
5596  }
5597 
5598  if (isBlockingQueued) {
5599  thread.quit();
5600  thread.wait();
5601  }
5602 }
5603 
5604 void tst_QObject::returnValue2_data()
5605 { returnValue_data(); }
5606 
5607 //String based syntax
5608 void tst_QObject::returnValue2()
5609 {
5610  CheckInstanceCount checker;
5611 
5612  QFETCH(bool, isBlockingQueued);
5613  QThread thread;
5614  ReturnValue receiver;
5616  if (isBlockingQueued) {
5617  thread.start();
5618  receiver.moveToThread(&thread);
5620  }
5621 
5622  { // connected to a simple slot
5623  CheckInstanceCount checker;
5624  ReturnValue r;
5625  QVERIFY(connect(&r, SIGNAL(returnVariant(int)), &receiver, SLOT(returnVariantSlot(int)), type));
5626  QCOMPARE(emit r.returnVariant(45), QVariant(45));
5627  QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnStringSlot(int)), type));
5628  QCOMPARE(emit r.returnString(45), QString(QStringLiteral("45")));
5629  QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnIntSlot(int)), type));
5630  QCOMPARE(emit r.returnInt(45), int(45));
5631  QVERIFY(connect(&r, SIGNAL(returnCustomType(int)), &receiver, SLOT(returnCustomTypeSlot(int)), type));
5632  QCOMPARE((emit r.returnCustomType(45)).value(), CustomType(45).value());
5633  QVERIFY(connect(&r, SIGNAL(returnMoveOnly(int)), &receiver, SLOT(returnMoveOnlySlot(int)), type));
5634  QCOMPARE((emit r.returnMoveOnly(45)).value, 45);
5635  }
5636  { // connected to a slot returning void
5637  CheckInstanceCount checker;
5638  ReturnValue r;
5639  QVERIFY(connect(&r, SIGNAL(returnVariant(int)), &receiver, SLOT(returnVoidSlot()), type));
5640  QCOMPARE(emit r.returnVariant(45), QVariant());
5641  QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnVoidSlot()), type));
5642  QCOMPARE(emit r.returnString(45), QString());
5643  QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnVoidSlot()), type));
5644  QCOMPARE(emit r.returnInt(45), int());
5645  QVERIFY(connect(&r, SIGNAL(returnCustomType(int)), &receiver, SLOT(returnVoidSlot()), type));
5646  QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value());
5647  QVERIFY(connect(&r, SIGNAL(returnMoveOnly(int)), &receiver, SLOT(returnVoidSlot()), type));
5648  QCOMPARE((emit r.returnMoveOnly(45)).value, MoveOnly().value);
5649  }
5650  if (!isBlockingQueued) {
5651  // queued connection should not forward the return value
5652  CheckInstanceCount checker;
5653  ReturnValue r;
5654  QVERIFY(connect(&r, SIGNAL(returnVariant(int)), &receiver, SLOT(returnVariantSlot(int)), Qt::QueuedConnection));
5655  QCOMPARE(emit r.returnVariant(45), QVariant());
5656  QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnStringSlot(int)), Qt::QueuedConnection));
5657  QCOMPARE(emit r.returnString(45), QString());
5658  QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnIntSlot(int)), Qt::QueuedConnection));
5659  QCOMPARE(emit r.returnInt(45), int());
5660  QVERIFY(connect(&r, SIGNAL(returnCustomType(int)), &receiver, SLOT(returnCustomTypeSlot(int)), Qt::QueuedConnection));
5661  QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value());
5662  QVERIFY(connect(&r, SIGNAL(returnMoveOnly(int)), &receiver, SLOT(returnMoveOnlySlot(int)), Qt::QueuedConnection));
5663  QCOMPARE((emit r.returnMoveOnly(45)).value, MoveOnly().value);
5664 
5666 
5667  //Queued conneciton with different return type should be safe
5668  QVERIFY(connect(&r, SIGNAL(returnVariant(int)), &receiver, SLOT(returnStringSlot(int)), Qt::QueuedConnection));
5669  QCOMPARE(emit r.returnVariant(48), QVariant());
5670  QVERIFY(connect(&r, SIGNAL(returnCustomType(int)), &receiver, SLOT(returnIntSlot(int)), Qt::QueuedConnection));
5671  QCOMPARE((emit r.returnCustomType(48)).value(), CustomType().value());
5672  QVERIFY(connect(&r, SIGNAL(returnVoid(int)), &receiver, SLOT(returnCustomTypeSlot(int)), Qt::QueuedConnection));
5673  emit r.returnVoid(48);
5675  }
5676  { // connected to many slots
5677  ReturnValue r;
5678  QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnIntSlot(int)), type));
5679  QCOMPARE(emit r.returnInt(45), int(45));
5680  QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnVoidSlot()), type));
5681  QCOMPARE(emit r.returnInt(45), int(45));
5682  QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(return23()), type));
5683  QCOMPARE(emit r.returnInt(45), int(23));
5684  QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnIntSlot(int)), Qt::QueuedConnection));
5685  QCOMPARE(emit r.returnInt(45), int(23));
5686 
5687  QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnStringSlot(int)), type));
5688  QCOMPARE(emit r.returnString(45), QString(QStringLiteral("45")));
5689  QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnVoidSlot()), type));
5690  QCOMPARE(emit r.returnString(45), QString(QStringLiteral("45")));
5691  QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnHello()), type));
5692  QCOMPARE(emit r.returnString(45), QString(QStringLiteral("hello")));
5693  QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnStringSlot(int)), Qt::QueuedConnection));
5694  QCOMPARE(emit r.returnString(45), QString(QStringLiteral("hello")));
5695  }
5696  if (isBlockingQueued) {
5697  thread.quit();
5698  thread.wait();
5699  }
5700 }
5701 
5703  Q_OBJECT
5704 public slots:
5705  virtual void slot1() {
5706  base_counter1++;
5707  }
5708 public:
5711 signals:
5712  void signal1();
5713 };
5714 
5716  Q_OBJECT
5717 public slots:
5718  virtual void slot1() override {
5719  derived_counter1++;
5720  }
5721 public:
5724 };
5725 
5726 void tst_QObject::connectVirtualSlots()
5727 {
5731 
5732  emit obj.signal1();
5733  QCOMPARE(obj.base_counter1, 0);
5734  QCOMPARE(obj.derived_counter1, 1);
5735 
5738 
5739  emit obj.signal1();
5740  QCOMPARE(obj.base_counter1, 0);
5741  QCOMPARE(obj.derived_counter1, 1);
5742 
5743  /* the C++ standard say the comparison between pointer to virtual member function is unspecified
5744  QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1, Qt::UniqueConnection));
5745  QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObject::slot1, Qt::UniqueConnection));
5746  */
5747 }
5748 
5750 {
5753  virtual ~VirtualBase() {}
5754  virtual void slot2() = 0;
5755 };
5756 
5758 {
5759  Q_OBJECT
5760 public:
5764 
5765 public slots:
5767  virtual void slot1() override { ++derived_counter2; }
5768  virtual void slot2() override { ++virtual_base_count; }
5769 };
5770 
5772 {
5774  virtual ~NormalBase() {}
5775  virtual void virtualBaseSlot() { lastCalled = "virtualBaseSlot"; }
5776  void normalBaseSlot() { lastCalled = "normalBaseSlot"; }
5777 };
5778 
5780 {
5781  Q_OBJECT
5782 };
5783 
5784 // Normally, the class that inherit QObject always must go first, because of the way qobject_cast
5785 // work, and moc checks for that. But if we don't use Q_OBJECT, this should work
5787 {
5788  // no QObject as QObject always must go first
5789  // Q_OBJECT
5790 };
5791 
5792 // VMI = Virtual or Multiple Inheritance
5793 // (in this case, both)
5794 void tst_QObject::connectSlotsVMIClass()
5795 {
5796  // test connecting by the base
5797  {
5801 
5802  emit obj.signal1();
5803  QCOMPARE(obj.base_counter1, 0);
5804  QCOMPARE(obj.derived_counter1, 0);
5805  QCOMPARE(obj.derived_counter2, 1);
5806  QCOMPARE(obj.virtual_base_count, 0);
5807 
5810 
5811  emit obj.signal1();
5812  QCOMPARE(obj.base_counter1, 0);
5813  QCOMPARE(obj.derived_counter1, 0);
5814  QCOMPARE(obj.derived_counter2, 1);
5815  QCOMPARE(obj.virtual_base_count, 0);
5816  }
5817 
5818  // test connecting with the actual class
5819  {
5825 
5826  emit obj.signal1();
5827  QCOMPARE(obj.base_counter1, 0);
5828  QCOMPARE(obj.derived_counter1, 0);
5829  QCOMPARE(obj.derived_counter2, 1);
5830  QCOMPARE(obj.regular_call_count, 1);
5831  QCOMPARE(obj.virtual_base_count, 0);
5832 
5837 
5838  emit obj.signal1();
5839  QCOMPARE(obj.base_counter1, 0);
5840  QCOMPARE(obj.derived_counter1, 0);
5841  QCOMPARE(obj.derived_counter2, 1);
5842  QCOMPARE(obj.regular_call_count, 1);
5843  QCOMPARE(obj.virtual_base_count, 0);
5844 
5845  /* the C++ standard say the comparison between pointer to virtual member function is unspecified
5846  QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1, Qt::UniqueConnection));
5847  QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot1, Qt::UniqueConnection));
5848  */
5849  }
5850 
5851  // test connecting a slot that is virtual from the virtual base
5852  {
5856 
5857  emit obj.signal1();
5858  QCOMPARE(obj.base_counter1, 0);
5859  QCOMPARE(obj.derived_counter1, 0);
5860  QCOMPARE(obj.derived_counter2, 0);
5861  QCOMPARE(obj.virtual_base_count, 1);
5862  QCOMPARE(obj.regular_call_count, 0);
5863 
5866 
5867  emit obj.signal1();
5868  QCOMPARE(obj.base_counter1, 0);
5869  QCOMPARE(obj.derived_counter1, 0);
5870  QCOMPARE(obj.derived_counter2, 0);
5871  QCOMPARE(obj.virtual_base_count, 1);
5872  QCOMPARE(obj.regular_call_count, 0);
5873  }
5874 
5875  // test connecting a slot that is virtual within the second base
5876  {
5881 
5882  emit obj.signal1();
5883  QCOMPARE(obj.base_counter1, 0);
5884  QCOMPARE(obj.derived_counter1, 0);
5885  QCOMPARE(obj.lastCalled, QByteArray("virtualBaseSlot"));
5886  obj.lastCalled.clear();
5887 
5890 
5891  emit obj.signal1();
5892  QCOMPARE(obj.base_counter1, 0);
5893  QCOMPARE(obj.derived_counter1, 0);
5894  QCOMPARE(obj.lastCalled, QByteArray());
5895  }
5896 
5897  // test connecting a slot that is not virtual within the second base
5898  {
5903 
5904  emit obj.signal1();
5905  QCOMPARE(obj.base_counter1, 0);
5906  QCOMPARE(obj.derived_counter1, 0);
5907  QCOMPARE(obj.lastCalled, QByteArray("normalBaseSlot"));
5908  obj.lastCalled.clear();
5909 
5912 
5913  emit obj.signal1();
5914  QCOMPARE(obj.base_counter1, 0);
5915  QCOMPARE(obj.derived_counter1, 0);
5916  QCOMPARE(obj.lastCalled, QByteArray());
5917  }
5918 
5919  // test connecting a slot within the first non-QObject base
5920  {
5925 
5926  emit obj.signal1();
5927  QCOMPARE(obj.base_counter1, 0);
5928  QCOMPARE(obj.derived_counter1, 0);
5929  QCOMPARE(obj.lastCalled, QByteArray("normalBaseSlot"));
5930  obj.lastCalled.clear();
5931 
5934 
5935  emit obj.signal1();
5936  QCOMPARE(obj.base_counter1, 0);
5937  QCOMPARE(obj.derived_counter1, 0);
5938  QCOMPARE(obj.lastCalled, QByteArray());
5939  }
5940 
5941  // test connecting a slot within the second QObject base
5942  {
5947 
5948  emit obj.signal1();
5949  QCOMPARE(obj.base_counter1, 0);
5950  QCOMPARE(obj.derived_counter1, 1);
5951  QCOMPARE(obj.lastCalled, QByteArray());
5952 
5955 
5956  emit obj.signal1();
5957  QCOMPARE(obj.base_counter1, 0);
5958  QCOMPARE(obj.derived_counter1, 1);
5959  QCOMPARE(obj.lastCalled, QByteArray());
5960  }
5961 }
5962 
5963 #ifndef QT_BUILD_INTERNAL
5964 void tst_QObject::connectPrivateSlots()
5965 {QSKIP("Needs QT_BUILD_INTERNAL");}
5966 #else
5967 class ConnectToPrivateSlotPrivate;
5968 
5969 class ConnectToPrivateSlot :public QObject {
5970  Q_OBJECT
5971 public:
5972  ConnectToPrivateSlot();
5973  void test(SenderObject *obj1) ;
5974  Q_DECLARE_PRIVATE(ConnectToPrivateSlot)
5975 };
5976 
5977 class ConnectToPrivateSlotPrivate : public QObjectPrivate {
5978 public:
5979  Q_DECLARE_PUBLIC(ConnectToPrivateSlot)
5980  int receivedCount;
5981  QVariant receivedValue;
5982 
5983  void thisIsAPrivateSlot() {
5984  receivedCount++;
5985  };
5986 
5987  void thisIsAPrivateSlotWithArg(const QVariant &v) {
5988  receivedCount++;
5989  receivedValue = v;
5990  };
5991 };
5992 
5993 ConnectToPrivateSlot::ConnectToPrivateSlot(): QObject(*new ConnectToPrivateSlotPrivate) {}
5994 
5995 void ConnectToPrivateSlot::test(SenderObject* obj1) {
5996  Q_D(ConnectToPrivateSlot);
5997  d->receivedCount = 0;
5998  QVERIFY(QObjectPrivate::connect(obj1, &SenderObject::signal1, d, &ConnectToPrivateSlotPrivate::thisIsAPrivateSlot));
5999  QVERIFY(QObjectPrivate::connect(obj1, &SenderObject::signal7, d, &ConnectToPrivateSlotPrivate::thisIsAPrivateSlotWithArg));
6000  QCOMPARE(d->receivedCount, 0);
6001  obj1->signal1();
6002  QCOMPARE(d->receivedCount, 1);
6003  QCOMPARE(d->receivedValue, QVariant());
6004  obj1->signal7(666, QLatin1String("_"));
6005  QCOMPARE(d->receivedCount, 2);
6006  QCOMPARE(d->receivedValue, QVariant(666));
6007  QVERIFY(QObjectPrivate::connect(obj1, &SenderObject::signal2, d, &ConnectToPrivateSlotPrivate::thisIsAPrivateSlot, Qt::UniqueConnection));
6008  QVERIFY(!QObjectPrivate::connect(obj1, &SenderObject::signal2, d, &ConnectToPrivateSlotPrivate::thisIsAPrivateSlot, Qt::UniqueConnection));
6009  obj1->signal2();
6010  QCOMPARE(d->receivedCount, 3);
6011  QVERIFY(QObjectPrivate::disconnect(obj1, &SenderObject::signal2, d, &ConnectToPrivateSlotPrivate::thisIsAPrivateSlot));
6012  obj1->signal2();
6013  QCOMPARE(d->receivedCount, 3);
6014  QVERIFY(!QObjectPrivate::disconnect(obj1, &SenderObject::signal2, d, &ConnectToPrivateSlotPrivate::thisIsAPrivateSlot));
6015 }
6016 
6017 void tst_QObject::connectPrivateSlots()
6018 {
6020  {
6021  ConnectToPrivateSlot o;
6022  o.test(&sender);
6023  }
6024  sender.signal7(777, QLatin1String("check that deleting the object properly disconnected"));
6025  sender.signal1();
6026 }
6027 #endif
6028 
6030 {
6031  void operator()() {}
6032 };
6033 
6035 {
6036  void operator()(const QString &) {}
6037 };
6038 
6039 void tst_QObject::connectFunctorArgDifference()
6040 {
6041  QTimer timer;
6042  // Compile-time tests that the connection is successful.
6046 
6050 
6051  connect(&timer, &QTimer::timeout, [=](){});
6052  connect(&timer, &QTimer::objectNameChanged, [=](const QString &){});
6054 
6058 
6059  QVERIFY(true);
6060 }
6061 
6062 class ContextObject : public QObject
6063 {
6064  Q_OBJECT
6065 public:
6067 };
6068 
6070 {
6074 
6075 protected:
6076  int *status;
6079 };
6080 
6081 void tst_QObject::connectFunctorQueued()
6082 {
6083  int status = 1;
6084  SenderObject obj;
6085  QEventLoop e;
6086 
6089 
6090  obj.emitSignal1();
6091  QCOMPARE(status, 1);
6092  e.exec();
6093  QCOMPARE(status, 2);
6094 
6095  status = 1;
6096  connect(&obj, &SenderObject::signal1, this, [&status] { status = 2; }, Qt::QueuedConnection);
6097 
6098  obj.emitSignal1();
6099  QCOMPARE(status, 1);
6100  e.exec();
6101  QCOMPARE(status, 2);
6102 }
6103 
6104 void tst_QObject::connectFunctorWithContext()
6105 {
6106  int status = 1;
6107  SenderObject obj;
6109  QEventLoop e;
6110 
6113 
6114  // When the context gets deleted, the connection should decay and the signal shouldn't trigger
6115  // The connection is queued to make sure the destroyed signal propagates correctly and
6116  // cuts the connection.
6118  context->deleteLater();
6119 
6120  obj.emitSignal1();
6121  QCOMPARE(status, 2);
6122  e.exec();
6123  QCOMPARE(status, 2);
6124 
6125  // Check disconnect with the context object as "receiver" argument, all signals
6126  context = new ContextObject;
6127  status = 1;
6129 
6130  obj.emitSignal1();
6131  QCOMPARE(status, 2);
6132  QObject::disconnect(&obj, nullptr, context, nullptr);
6133  obj.emitSignal1();
6134  QCOMPARE(status, 2);
6135 
6136  delete context;
6137 
6138  // Check disconnect with the context object as "receiver" argument, specific signal
6139  context = new ContextObject;
6140  status = 1;
6142 
6143  obj.emitSignal1();
6144  QCOMPARE(status, 2);
6146  obj.emitSignal1();
6147  QCOMPARE(status, 2);
6148 
6149  delete context;
6150 
6151  // Check the sender arg is set correctly in the context
6152  context = new ContextObject;
6153 
6154  status = 1;
6157 
6158  obj.emitSignal1();
6159  QCOMPARE(status, 1);
6160  e.exec();
6161  QCOMPARE(status, 2);
6162 
6163  status = 1;
6164  connect(&obj, &SenderObject::signal1, this, [this, &status, &obj] { status = 2; QCOMPARE(sender(), &obj); }, Qt::QueuedConnection);
6165 
6166  obj.emitSignal1();
6167  QCOMPARE(status, 1);
6168  e.exec();
6169  QCOMPARE(status, 2);
6170 
6171  delete context;
6172 }
6173 
6174 class StatusChanger : public QObject
6175 {
6176  Q_OBJECT
6177 public:
6178  StatusChanger(int *status) : m_status(status)
6179  {
6180  }
6182  {
6183  *m_status = 2;
6184  }
6185 private:
6186  int *m_status;
6187 };
6188 
6190 {
6191  Q_OBJECT
6192 public:
6193  DispatcherWatcher(QEventLoop &e, int *statusAwake, int *statusAboutToBlock) :
6194  m_eventLoop(&e),
6195  m_statusAwake(statusAwake),
6196  m_statusAboutToBlock(statusAboutToBlock),
6197  m_aboutToBlocks(0),
6198  m_awakes(0)
6199  {
6200  awake = new StatusChanger(statusAwake);
6201  abouttoblock = new StatusChanger(statusAboutToBlock);
6202  QCOMPARE(*statusAwake, 1);
6203  QCOMPARE(*statusAboutToBlock, 1);
6206 
6207  }
6208 
6210  {
6211  if (awake)
6212  awake->deleteLater();
6213  if (abouttoblock)
6214  abouttoblock->deleteLater();
6215  }
6216 
6217 public slots:
6218  // The order of these 2 handlers differs on different event dispatchers
6220  {
6221  if (abouttoblock) {
6222  abouttoblock->deleteLater();
6223  abouttoblock = nullptr;
6224  }
6225  ++m_aboutToBlocks;
6226  }
6227  void onAwake()
6228  {
6229  if (awake) {
6230  awake->deleteLater();
6231  awake = nullptr;
6232  }
6233  ++m_awakes;
6234 
6235  }
6236  void onSignal1()
6237  {
6238  // Status check. At this point the event loop should have spinned enough to delete all the objects.
6239  QCOMPARE(*m_statusAwake, 2);
6240  QCOMPARE(*m_statusAboutToBlock, 2);
6241  QMetaObject::invokeMethod(m_eventLoop, "quit", Qt::QueuedConnection);
6242  }
6243 
6244 private:
6245  StatusChanger *awake;
6246  StatusChanger *abouttoblock;
6247  QEventLoop *m_eventLoop;
6248  int *m_statusAwake;
6249  int *m_statusAboutToBlock;
6250  int m_aboutToBlocks;
6251  int m_awakes;
6252 };
6253 
6254 
6255 void tst_QObject::deleteLaterInAboutToBlockHandler()
6256 {
6257  int statusAwake = 1;
6258  int statusAboutToBlock = 1;
6259  QEventLoop e;
6260  DispatcherWatcher dw(e, &statusAwake, &statusAboutToBlock);
6262 
6263  QCOMPARE(statusAwake, 1);
6264  QCOMPARE(statusAboutToBlock, 1);
6265  e.exec();
6266  QCOMPARE(statusAwake, 2);
6267  QCOMPARE(statusAboutToBlock, 2);
6268 }
6269 
6270 void tst_QObject::connectFunctorWithContextUnique()
6271 {
6272  // Qt::UniqueConnections currently don't work for functors, but we need to
6273  // be sure that they don't crash. If that is implemented, change this test.
6274 
6276  ReceiverObject receiver;
6278  receiver.count_slot1 = 0;
6279 
6280  QTest::ignoreMessage(QtWarningMsg, "QObject::connect(SenderObject, ReceiverObject): unique connections require a pointer to member function of a QObject subclass");
6281  QVERIFY(!QObject::connect(&sender, &SenderObject::signal1, &receiver, [&](){ receiver.slot1(); }, Qt::UniqueConnection));
6282 
6283  sender.emitSignal1();
6284  QCOMPARE(receiver.count_slot1, 1);
6285 }
6286 
6288 {
6289 public:
6290  explicit MyFunctor(QObject *objectToDisconnect)
6291  : m_objectToDisconnect(objectToDisconnect)
6292  {}
6293 
6295  playWithObjects();
6296  }
6297 
6298  void operator()() {
6299  // This will cause the slot object associated with this functor to be destroyed after
6300  // this function returns. That in turn will destroy this functor.
6301  // If our dtor runs with the signalSlotLock held, the bunch of connect()
6302  // performed there will deadlock trying to lock that lock again.
6303  m_objectToDisconnect->disconnect();
6304  }
6305 
6306 private:
6307  QObject *m_objectToDisconnect;
6308 };
6309 
6310 void tst_QObject::connectFunctorDeadlock()
6311 {
6313  MyFunctor functor(&sender);
6315  sender.emitSignal1();
6316 }
6317 
6318 void tst_QObject::connectFunctorMoveOnly()
6319 {
6320  struct MoveOnlyFunctor {
6321  Q_DISABLE_COPY(MoveOnlyFunctor)
6322  MoveOnlyFunctor(int *status) : status(status) {}
6323  MoveOnlyFunctor(MoveOnlyFunctor &&o) : status(o.status) { o.status = nullptr; };
6324  void operator()(int i) { *status = i; }
6325  void operator()() { *status = -8; }
6326  int *status;
6327  };
6328 
6329  int status = 1;
6330  SenderObject obj;
6331  QEventLoop e;
6332 
6333  connect(&obj, &SenderObject::signal1, MoveOnlyFunctor(&status));
6334  QCOMPARE(status, 1);
6335  obj.signal1();
6336  QCOMPARE(status, -8);
6337 
6338  connect(&obj, &SenderObject::signal7, MoveOnlyFunctor(&status));
6339  QCOMPARE(status, -8);
6340  obj.signal7(7888, "Hello");
6341  QCOMPARE(status, 7888);
6342 
6343  // With a context
6344  status = 1;
6345  connect(&obj, &SenderObject::signal2, this, MoveOnlyFunctor(&status));
6346  QCOMPARE(status, 1);
6347  obj.signal2();
6348  QCOMPARE(status, -8);
6349 
6350  // QueuedConnection
6351  status = 1;
6352  connect(&obj, &SenderObject::signal3, this, MoveOnlyFunctor(&status), Qt::QueuedConnection);
6353  obj.signal3();
6354  QCOMPARE(status, 1);
6356  QCOMPARE(status, -8);
6357 }
6358 
6359 static int s_static_slot_checker = 1;
6360 
6362 {
6363  Q_OBJECT
6364 public Q_SLOTS:
6365  static void staticSlot() { s_static_slot_checker = 2; }
6366 };
6367 
6368 void tst_QObject::connectStaticSlotWithObject()
6369 {
6371  StaticSlotChecker *receiver = new StaticSlotChecker;
6372  QEventLoop e;
6373 
6376 
6377  sender.emitSignal1();
6378  QCOMPARE(s_static_slot_checker, 1);
6379  e.exec();
6380  QCOMPARE(s_static_slot_checker, 2);
6381 
6382  s_static_slot_checker = 1;
6383 
6385  receiver->deleteLater();
6386 
6387  QCOMPARE(s_static_slot_checker, 1);
6388  e.exec();
6389  QCOMPARE(s_static_slot_checker, 1);
6390 }
6391 
6394  void operator()(int a, int b) {
6395  overload = 1;
6396  result << a << b;
6397  }
6398  void operator()(double a, double b) {
6399  overload = 2;
6400  result << a << b;
6401  }
6402  void operator()(const QString &s) {
6403  overload = 3;
6404  result << s;
6405  }
6406  void operator()(const QString &) const {
6407  Q_ASSERT(!"Should not be called because the non-const one should");
6408  overload = -1;
6409  }
6410  template<typename T1, typename T2, typename T3, typename T4>
6411  void operator()(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4) {
6412  overload = 4;
6414  }
6415  int &overload;
6417 protected:
6418  void operator()() const {
6419  Q_ASSERT(!"Should not be called because it is protected");
6420  overload = -1;
6421  }
6422 };
6423 
6426 
6427  void operator()() const {
6428  overload = 10;
6429  }
6430  void operator()(int a, int b) {
6431  overload = 11;
6432  result << a << b;
6433  }
6434  using ComplexFunctor::operator();
6435 private:
6436  void operator()(int) {
6437  Q_ASSERT(!"Should not be called because it is private");
6438  overload = -1;
6439  }
6440 };
6441 
6443 {
6444  Q_OBJECT
6445 signals:
6446  void signal_ii(int,int);
6447  void signal_iiS(int,int, const QString &);
6448  void signal_dd(double,double);
6449  void signal_ddS(double,double, const QString &);
6450  void signal_S(const QString &);
6451  void signal_SSSS(const QString &, const QString &, const QString &, const QString &);
6452  void signal_iiSS(int, int, const QString &, const QString &);
6453  void signal_VV(const QVariant &, const QVariant &);
6454 };
6455 
6456 template<typename Functor, typename Signal>
6457 void connectFunctorOverload_impl(Signal signal, int expOverload, QList<QVariant> expResult)
6458 {
6460  int overload;
6462  QVERIFY(QObject::connect(&obj, signal, Functor(overload, result)));
6463 
6464  obj.signal_ii(1,2);
6465  obj.signal_iiS(3,4,"5");
6466  obj.signal_dd(6.6,7.7);
6467  obj.signal_ddS(8.8,9.9,"10");
6468  obj.signal_S("11");
6469  obj.signal_SSSS("12", "13", "14", "15");
6470  obj.signal_iiSS(16, 17, "18", "19");
6471  obj.signal_VV(20,21);
6472 
6473  QCOMPARE(overload, expOverload);
6474  QCOMPARE(result, expResult);
6475 }
6476 
6477 void tst_QObject::connectFunctorOverloads()
6478 {
6479 #if defined (Q_COMPILER_VARIADIC_TEMPLATES)
6480  connectFunctorOverload_impl<ComplexFunctor>(&FunctorArgDifferenceObject::signal_ii, 1,
6481  (QList<QVariant>() << 1 << 2));
6482  connectFunctorOverload_impl<ComplexFunctor>(&FunctorArgDifferenceObject::signal_iiS, 1,
6483  (QList<QVariant>() << 3 << 4));
6484  connectFunctorOverload_impl<ComplexFunctor>(&FunctorArgDifferenceObject::signal_dd, 2,
6485  (QList<QVariant>() << 6.6 << 7.7));
6486  connectFunctorOverload_impl<ComplexFunctor>(&FunctorArgDifferenceObject::signal_ddS, 2,
6487  (QList<QVariant>() << 8.8 << 9.9));
6488  connectFunctorOverload_impl<ComplexFunctor>(&FunctorArgDifferenceObject::signal_S, 3,
6489  (QList<QVariant>() << QString("11")));
6490  connectFunctorOverload_impl<ComplexFunctor>(&FunctorArgDifferenceObject::signal_SSSS, 4,
6491  (QList<QVariant>() << QString("12") << QString("13") << QString("14") << QString("15")));
6492  connectFunctorOverload_impl<ComplexFunctor>(&FunctorArgDifferenceObject::signal_iiSS, 4,
6493  (QList<QVariant>() << 16 << 17 << QString("18") << QString("19")));
6494  connectFunctorOverload_impl<ComplexFunctorDeriv>(&FunctorArgDifferenceObject::signal_ii, 11,
6495  (QList<QVariant>() << 1 << 2));
6496  connectFunctorOverload_impl<ComplexFunctorDeriv>(&FunctorArgDifferenceObject::signal_iiS, 11,
6497  (QList<QVariant>() << 3 << 4));
6498  connectFunctorOverload_impl<ComplexFunctorDeriv>(&FunctorArgDifferenceObject::signal_dd, 2,
6499  (QList<QVariant>() << 6.6 << 7.7));
6500  connectFunctorOverload_impl<ComplexFunctorDeriv>(&FunctorArgDifferenceObject::signal_ddS, 2,
6501  (QList<QVariant>() << 8.8 << 9.9));
6502  connectFunctorOverload_impl<ComplexFunctorDeriv>(&FunctorArgDifferenceObject::signal_S, 3,
6503  (QList<QVariant>() << QString("11")));
6504  connectFunctorOverload_impl<ComplexFunctorDeriv>(&FunctorArgDifferenceObject::signal_SSSS, 4,
6505  (QList<QVariant>() << QString("12") << QString("13") << QString("14") << QString("15")));
6506  connectFunctorOverload_impl<ComplexFunctorDeriv>(&FunctorArgDifferenceObject::signal_iiSS, 4,
6507  (QList<QVariant>() << 16 << 17 << QString("18") << QString("19")));
6508  connectFunctorOverload_impl<ComplexFunctorDeriv>(&FunctorArgDifferenceObject::signal_VV, 10,
6509  (QList<QVariant>()));
6510 
6511 
6512 #else
6513  QSKIP("Does not compile without C++11 variadic template");
6514 #endif
6515 }
6516 
6517 class GetSenderObject : public QObject
6518 {
6519  Q_OBJECT
6520 public:
6521  using QObject::sender; // make public
6522 
6523 public Q_SLOTS:
6525 
6526 Q_SIGNALS:
6527  void aSignal();
6528 };
6529 
6530 static int countedStructObjectsCount = 0;
6531 struct CountedStruct
6532 {
6533  CountedStruct() : sender(nullptr) { ++countedStructObjectsCount; }
6534  CountedStruct(GetSenderObject *sender) : sender(sender) { ++countedStructObjectsCount; }
6535  CountedStruct(const CountedStruct &o) : sender(o.sender) { ++countedStructObjectsCount; }
6536  CountedStruct &operator=(const CountedStruct &) { return *this; }
6537  // calling sender() here allows us to check if there's a deadlock
6538  ~CountedStruct() { --countedStructObjectsCount; if (sender) (void)sender->sender(); }
6539  void operator()() const { }
6540 
6542 };
6543 
6544 void tst_QObject::disconnectDoesNotLeakFunctor()
6545 {
6546  QCOMPARE(countedStructObjectsCount, 0);
6547  {
6550  {
6551  CountedStruct s(&obj);
6552  QCOMPARE(countedStructObjectsCount, 1);
6553 
6555  QVERIFY(c);
6556  QCOMPARE(countedStructObjectsCount, 2);
6558  QCOMPARE(countedStructObjectsCount, 1);
6559  }
6560  QCOMPARE(countedStructObjectsCount, 0);
6561  }
6562  QCOMPARE(countedStructObjectsCount, 0);
6563  {
6566  {
6567  CountedStruct s(&obj);
6568  QObject context;
6569  QCOMPARE(countedStructObjectsCount, 1);
6570 
6572  QVERIFY(c);
6573  QCOMPARE(countedStructObjectsCount, 2);
6575  QCOMPARE(countedStructObjectsCount, 1);
6576  }
6577  QCOMPARE(countedStructObjectsCount, 0);
6578  }
6579  QCOMPARE(countedStructObjectsCount, 0);
6580  {
6582  {
6583  CountedStruct s;
6584  QCOMPARE(countedStructObjectsCount, 1);
6585  QTimer timer;
6586 
6587  c1 = connect(&timer, &QTimer::timeout, s);
6588  QVERIFY(c1);
6589  c2 = c1;
6590  QVERIFY(c2);
6591  QCOMPARE(countedStructObjectsCount, 2);
6593  QVERIFY(!c1);
6594  QVERIFY(!c2);
6595  // functor object has been destroyed
6596  QCOMPARE(countedStructObjectsCount, 1);
6598  QCOMPARE(countedStructObjectsCount, 1);
6599  }
6600  QCOMPARE(countedStructObjectsCount, 0);
6601  }
6602  QCOMPARE(countedStructObjectsCount, 0);
6603  {
6604  CountedStruct s;
6605  QCOMPARE(countedStructObjectsCount, 1);
6606  QTimer timer;
6607 
6609  QVERIFY(c);
6610  QCOMPARE(countedStructObjectsCount, 2);
6612  QCOMPARE(countedStructObjectsCount, 1);
6613  }
6614  QCOMPARE(countedStructObjectsCount, 0);
6615  {
6616  QTimer timer;
6617 
6619  QVERIFY(c);
6620  QCOMPARE(countedStructObjectsCount, 1); // only one instance, in Qt internals
6622  QCOMPARE(countedStructObjectsCount, 0); // functor being destroyed
6623  }
6624  QCOMPARE(countedStructObjectsCount, 0);
6625  {
6626  QTimer *timer = new QTimer;
6627  QEventLoop e;
6628 
6630  QCOMPARE(countedStructObjectsCount, 1); // only one instance, in Qt internals
6631  timer->deleteLater();
6633  e.exec();
6634  QCOMPARE(countedStructObjectsCount, 0); // functor being destroyed
6635  }
6636  QCOMPARE(countedStructObjectsCount, 0);
6637  {
6639 
6641  QCOMPARE(countedStructObjectsCount, 1);
6642  }
6643  QCOMPARE(countedStructObjectsCount, 0);
6644  {
6646 
6648  QCOMPARE(countedStructObjectsCount, 1);
6650  }
6651  QCOMPARE(countedStructObjectsCount, 0);
6652  {
6653  CountedStruct s;
6654  QCOMPARE(countedStructObjectsCount, 1);
6655  QTimer timer;
6656 
6658  QVERIFY(c);
6659  QCOMPARE(countedStructObjectsCount, 2);
6661  QCOMPARE(countedStructObjectsCount, 1);
6662  }
6663  QCOMPARE(countedStructObjectsCount, 0);
6664 }
6665 
6666 void tst_QObject::contextDoesNotLeakFunctor()
6667 {
6668  QCOMPARE(countedStructObjectsCount, 0);
6669  {
6671  {
6672  QEventLoop e;
6674  SenderObject obj;
6675 
6678  context->deleteLater();
6679 
6680  QCOMPARE(countedStructObjectsCount, 1);
6681  e.exec();
6682  QCOMPARE(countedStructObjectsCount, 0);
6683  }
6684  QCOMPARE(countedStructObjectsCount, 0);
6685  }
6686  QCOMPARE(countedStructObjectsCount, 0);
6687  {
6690  {
6691  CountedStruct s(&obj);
6692  QEventLoop e;
6694  QCOMPARE(countedStructObjectsCount, 1);
6695 
6697  QCOMPARE(countedStructObjectsCount, 2);
6698 
6700  context->deleteLater();
6701 
6702  e.exec();
6703  QCOMPARE(countedStructObjectsCount, 1);
6704  }
6705  QCOMPARE(countedStructObjectsCount, 0);
6706  }
6707  QCOMPARE(countedStructObjectsCount, 0);
6708  {
6709  CountedStruct s;
6710  QEventLoop e;
6712  QCOMPARE(countedStructObjectsCount, 1);
6713  QTimer timer;
6714 
6715  connect(&timer, &QTimer::timeout, context, [s](){});
6716  QCOMPARE(countedStructObjectsCount, 2);
6718  context->deleteLater();
6719  e.exec();
6720  QCOMPARE(countedStructObjectsCount, 1);
6721  }
6722  QCOMPARE(countedStructObjectsCount, 0);
6723 }
6724 
6725 class SubSender : public SenderObject {
6726  Q_OBJECT
6727 };
6728 
6729 void tst_QObject::connectBase()
6730 {
6731  SubSender sub;
6733  r1.reset();
6734 
6736  QVERIFY( connect( &sub, static_cast<void (SenderObject::*)()>(&SubSender::signal2) , &r1, &ReceiverObject::slot2 ) );
6737  QVERIFY( connect( &sub, static_cast<void (SubSender::*)()>(&SubSender::signal3) , &r1, &ReceiverObject::slot3 ) );
6738 
6739  sub.emitSignal1();
6740  sub.emitSignal2();
6741  sub.emitSignal3();
6742 
6743  QCOMPARE( r1.count_slot1, 1 );
6744  QCOMPARE( r1.count_slot2, 1 );
6745  QCOMPARE( r1.count_slot3, 1 );
6746 
6748  QVERIFY( QObject::disconnect( &sub, static_cast<void (SenderObject::*)()>(&SubSender::signal2) , &r1, &ReceiverObject::slot2 ) );
6749  QVERIFY( QObject::disconnect( &sub, static_cast<void (SubSender::*)()>(&SubSender::signal3) , &r1, &ReceiverObject::slot3 ) );
6750 
6751  sub.emitSignal1();
6752  sub.emitSignal2();
6753  sub.emitSignal3();
6754 
6755  QCOMPARE( r1.count_slot1, 1 );
6756  QCOMPARE( r1.count_slot2, 1 );
6757  QCOMPARE( r1.count_slot3, 1 );
6758 }
6759 
6760 void tst_QObject::connectWarnings()
6761 {
6762  SubSender sub;
6763  SenderObject obj;
6765  r1.reset();
6766 
6767  QTest::ignoreMessage(QtWarningMsg, "QObject::connect(SenderObject, ReceiverObject): invalid nullptr parameter");
6768  connect(static_cast<const SenderObject *>(nullptr), &SubSender::signal1, &r1, &ReceiverObject::slot1);
6769 
6770  QTest::ignoreMessage(QtWarningMsg, "QObject::connect(SubSender, Unknown): invalid nullptr parameter");
6771  connect(&sub, &SubSender::signal1, static_cast<ReceiverObject *>(nullptr), &ReceiverObject::slot1);
6772 
6773  QTest::ignoreMessage(QtWarningMsg, "QObject::connect(SenderObject, ReceiverObject): invalid nullptr parameter");
6774  connect(static_cast<const SenderObject *>(nullptr), &SenderObject::signal1, &r1, &ReceiverObject::slot1);
6775 
6776  QTest::ignoreMessage(QtWarningMsg, "QObject::connect(SenderObject, Unknown): invalid nullptr parameter");
6777  connect(&obj, &SenderObject::signal1, static_cast<ReceiverObject *>(nullptr), &ReceiverObject::slot1);
6778 }
6779 
6781 {
6783  void *magic;
6784 
6787  , callCount(0)
6788  , magic(0)
6789  {}
6790 
6791  static void impl(int which, QSlotObjectBase *this_, QObject *, void **metaArgs, bool *ret)
6792  {
6793  switch (which) {
6794  case Destroy: delete static_cast<QmlReceiver*>(this_); return;
6795  case Call: static_cast<QmlReceiver*>(this_)->callCount++; return;
6796  case Compare: *ret = static_cast<QmlReceiver*>(this_)->magic == metaArgs[0]; return;
6797  case NumOperations: break;
6798  }
6799  }
6800 };
6801 
6802 void tst_QObject::qmlConnect()
6803 {
6804 #ifdef QT_BUILD_INTERNAL
6806  QmlReceiver *receiver = new QmlReceiver;
6807  receiver->magic = receiver;
6808  receiver->ref();
6809 
6810  QVERIFY(QObjectPrivate::connect(&sender, sender.metaObject()->indexOfSignal("signal1()"),
6811  receiver, Qt::AutoConnection));
6812 
6813  QCOMPARE(receiver->callCount, 0);
6814  sender.emitSignal1();
6815  QCOMPARE(receiver->callCount, 1);
6816 
6817  void *a[] = {
6818  receiver
6819  };
6820  QVERIFY(QObjectPrivate::disconnect(&sender, sender.metaObject()->indexOfSignal("signal1()"), reinterpret_cast<void**>(&a)));
6821 
6822  sender.emitSignal1();
6823  QCOMPARE(receiver->callCount, 1);
6824 
6825  receiver->destroyIfLastRef();
6826 #else
6827  QSKIP("Needs QT_BUILD_INTERNAL");
6828 #endif
6829 }
6830 
6831 void tst_QObject::qmlConnectToQObjectReceiver()
6832 {
6833 #ifdef QT_BUILD_INTERNAL
6835  QScopedPointer<QObject> receiver(new QObject);
6836  QmlReceiver *slotObject = new QmlReceiver;
6837  slotObject->magic = slotObject;
6838  slotObject->ref(); // extra ref so that slot object is not implicitly deleted
6839 
6840  QVERIFY(QObjectPrivate::connect(&sender, sender.metaObject()->indexOfSignal("signal1()"),
6841  receiver.get(), slotObject, Qt::AutoConnection));
6842 
6843  QCOMPARE(slotObject->callCount, 0);
6844  sender.emitSignal1();
6845  QCOMPARE(slotObject->callCount, 1);
6846 
6847  receiver.reset(); // this should disconnect the slotObject
6848 
6849  sender.emitSignal1();
6850  QCOMPARE(slotObject->callCount, 1);
6851 
6852  slotObject->destroyIfLastRef();
6853 #else
6854  QSKIP("Needs QT_BUILD_INTERNAL");
6855 #endif
6856 }
6857 
6858 #ifndef QT_NO_EXCEPTIONS
6859 class ObjectException : public std::exception { };
6860 
6862 {
6864  {
6865  throw ObjectException();
6866  return s2;
6867  }
6869 };
6870 #endif
6871 
6873 {
6874  Q_OBJECT
6875 public slots:
6877  {
6878 #ifndef QT_NO_EXCEPTIONS
6879  throw ObjectException();
6880 #endif
6881  return s2;
6882  }
6883 signals:
6885 };
6886 
6888 {
6889  Q_OBJECT
6890 
6891 public:
6892  explicit CountedExceptionThrower(bool throwException, QObject *parent = nullptr)
6893  : QObject(parent)
6894  {
6895  Q_UNUSED(throwException);
6896 #ifndef QT_NO_EXCEPTIONS
6897  if (throwException)
6898  throw ObjectException();
6899 #endif
6900  ++counter;
6901  }
6902 
6904  {
6905  --counter;
6906  }
6907 
6908  static int counter;
6909 };
6910 
6912 
6913 void tst_QObject::exceptions()
6914 {
6915 #ifndef QT_NO_EXCEPTIONS
6916  ReceiverObject receiver;
6917 
6918  // String based syntax
6919  {
6920  QCOMPARE(countedStructObjectsCount, 0);
6921  ExceptionThrower thrower;
6922  receiver.reset();
6923 
6924  connect(&thrower, SIGNAL(mySignal(CountedStruct,CountedStruct)), &receiver, SLOT(slot1()));
6925  connect(&thrower, SIGNAL(mySignal(CountedStruct,CountedStruct)), &thrower, SLOT(throwException(CountedStruct,CountedStruct)));
6926  connect(&thrower, SIGNAL(mySignal(CountedStruct,CountedStruct)), &receiver, SLOT(slot2()));
6927  try {
6928  CountedStruct s;
6929  emit thrower.mySignal(s, s);
6930  QFAIL("Exception not thrown?");
6931  } catch (ObjectException&) {}
6932  QCOMPARE(receiver.count_slot1, 1);
6933  QCOMPARE(receiver.count_slot2, 0);
6934  QCOMPARE(countedStructObjectsCount, 0);
6935  }
6936  // Pointer to member function
6937  {
6938  QCOMPARE(countedStructObjectsCount, 0);
6939  ExceptionThrower thrower;
6940  receiver.reset();
6941 
6942  connect(&thrower, &ExceptionThrower::mySignal, &receiver, &ReceiverObject::slot1);
6944  connect(&thrower, &ExceptionThrower::mySignal, &receiver, &ReceiverObject::slot2);
6945  try {
6946  CountedStruct s;
6947  emit thrower.mySignal(s, s);
6948  QFAIL("Exception not thrown?");
6949  } catch (ObjectException&) {}
6950  QCOMPARE(receiver.count_slot1, 1);
6951  QCOMPARE(receiver.count_slot2, 0);
6952  QCOMPARE(countedStructObjectsCount, 0);
6953  }
6954  // Functor
6955  {
6956  QCOMPARE(countedStructObjectsCount, 0);
6957  ExceptionThrower thrower;
6958  receiver.reset();
6959 
6960  connect(&thrower, &ExceptionThrower::mySignal, &receiver, &ReceiverObject::slot1);
6962  connect(&thrower, &ExceptionThrower::mySignal, &receiver, &ReceiverObject::slot2);
6963  try {
6964  CountedStruct s;
6965  emit thrower.mySignal(s, s);
6966  QFAIL("Exception not thrown?");
6967  } catch (ObjectException&) {}
6968  QCOMPARE(receiver.count_slot1, 1);
6969  QCOMPARE(receiver.count_slot2, 0);
6970  QCOMPARE(countedStructObjectsCount, 1); // the Functor
6971  }
6972  QCOMPARE(countedStructObjectsCount, 0);
6973 
6974  // Child object reaping in case of exceptions thrown by constructors
6975  {
6977 
6978  try {
6979  class ParentObject : public QObject {
6980  public:
6981  explicit ParentObject(QObject *parent = nullptr)
6982  : QObject(parent)
6983  {
6984  new CountedExceptionThrower(false, this);
6985  new CountedExceptionThrower(false, this);
6986  new CountedExceptionThrower(true, this); // throws
6987  }
6988  };
6989 
6990  ParentObject p;
6991  QFAIL("Exception not thrown");
6992  } catch (const ObjectException &) {
6993  } catch (...) {
6994  QFAIL("Wrong exception thrown");
6995  }
6996 
6998 
6999  try {
7000  QObject o;
7001  new CountedExceptionThrower(false, &o);
7002  new CountedExceptionThrower(false, &o);
7003  new CountedExceptionThrower(true, &o); // throws
7004 
7005  QFAIL("Exception not thrown");
7006  } catch (const ObjectException &) {
7007  } catch (...) {
7008  QFAIL("Wrong exception thrown");
7009  }
7010 
7012 
7013  try {
7014  QObject o;
7015  CountedExceptionThrower c1(false, &o);
7016  CountedExceptionThrower c2(false, &o);
7017  CountedExceptionThrower c3(true, &o); // throws
7018 
7019  QFAIL("Exception not thrown");
7020  } catch (const ObjectException &) {
7021  } catch (...) {
7022  QFAIL("Wrong exception thrown");
7023  }
7024 
7026  }
7027 
7028 #else
7029  QSKIP("Needs exceptions");
7030 #endif
7031 }
7032 
7033 
7035  int count;
7037  int operator()() { return ++count; }
7038 };
7039 
7040 void tst_QObject::mutableFunctor()
7041 {
7042  ReturnValue o;
7043  MutableFunctor functor;
7044  QCOMPARE(functor.count, 0);
7045  connect(&o, &ReturnValue::returnInt, functor);
7046  QCOMPARE(emit o.returnInt(0), 1);
7047  QCOMPARE(emit o.returnInt(0), 2); // each emit should increase the internal count
7048 
7049  QCOMPARE(functor.count, 0); // but the original object should have been copied at connect time
7050 }
7051 
7052 void tst_QObject::checkArgumentsForNarrowing()
7053 {
7054  // Clang and ICC masquerade as GCC, so introduce a more strict define
7055  // for exactly GCC (to exclude/include it from some tests).
7056 #if defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && !defined(Q_CC_INTEL)
7057 #define Q_CC_EXACTLY_GCC Q_CC_GNU
7058 #endif
7059 
7060  enum UnscopedEnum { UnscopedEnumV1 = INT_MAX, UnscopedEnumV2 };
7061  enum SignedUnscopedEnum { SignedUnscopedEnumV1 = INT_MIN, SignedUnscopedEnumV2 = INT_MAX };
7062 
7063  static constexpr bool IsUnscopedEnumSigned = std::is_signed_v<std::underlying_type_t<UnscopedEnum>>;
7064 
7065 #define NARROWS_IF(x, y, test) static_assert((QtPrivate::AreArgumentsConvertibleWithoutNarrowingBase<x, y>::value) != (test))
7066 #define FITS_IF(x, y, test) static_assert((QtPrivate::AreArgumentsConvertibleWithoutNarrowingBase<x, y>::value) == (test))
7067 #define NARROWS(x, y) NARROWS_IF(x, y, true)
7068 #define FITS(x, y) FITS_IF(x, y, true)
7069 
7070  static_assert(sizeof(UnscopedEnum) <= sizeof(int));
7071  static_assert(sizeof(SignedUnscopedEnum) <= sizeof(int));
7072 
7073  // floating point to integral
7074 
7075  // GCC < 9 does not consider floating point to bool to be narrowing,
7076  // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65043
7077 #if !defined(Q_CC_EXACTLY_GCC) || Q_CC_EXACTLY_GCC >= 900
7078  NARROWS(float, bool);
7079  NARROWS(double, bool);
7080  NARROWS(long double, bool);
7081 #endif
7082 
7083  NARROWS(float, char);
7084  NARROWS(double, char);
7085  NARROWS(long double, char);
7086 
7087  NARROWS(float, short);
7088  NARROWS(double, short);
7089  NARROWS(long double, short);
7090 
7091  NARROWS(float, int);
7092  NARROWS(double, int);
7093  NARROWS(long double, int);
7094 
7095  NARROWS(float, long);
7096  NARROWS(double, long);
7097  NARROWS(long double, long);
7098 
7099  NARROWS(float, long long);
7100  NARROWS(double, long long);
7101  NARROWS(long double, long long);
7102 
7103 
7104  // floating point to a smaller floating point
7105  NARROWS(double, float);
7106  NARROWS(long double, float);
7107  FITS(float, double);
7108  FITS(float, long double);
7109 
7110  // GCC < 11 thinks this is narrowing only on architectures where
7111  // sizeof(long double) > sizeof(double)
7112  // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94590
7113 #if defined(Q_CC_EXACTLY_GCC) && (Q_CC_EXACTLY_GCC < 1100)
7114  NARROWS_IF(long double, double, sizeof(long double) > sizeof(double));
7115 #else
7116  NARROWS(long double, double);
7117 #endif
7118  FITS(double, long double);
7119 
7120 
7121  // integral to floating point
7122  NARROWS(bool, float);
7123  NARROWS(bool, double);
7124  NARROWS(bool, long double);
7125 
7126  NARROWS(char, float);
7127  NARROWS(char, double);
7128  NARROWS(char, long double);
7129 
7130  NARROWS(short, float);
7131  NARROWS(short, double);
7132  NARROWS(short, long double);
7133 
7134  NARROWS(int, float);
7135  NARROWS(int, double);
7136  NARROWS(int, long double);
7137 
7138  NARROWS(long, float);
7139  NARROWS(long, double);
7140  NARROWS(long, long double);
7141 
7142  NARROWS(long long, float);
7143  NARROWS(long long, double);
7144  NARROWS(long long, long double);
7145 
7146 
7147  // enum to floating point
7148  NARROWS(UnscopedEnum, float);
7149  NARROWS(UnscopedEnum, double);
7150  NARROWS(UnscopedEnum, long double);
7151 
7152  NARROWS(SignedUnscopedEnum, float);
7153  NARROWS(SignedUnscopedEnum, double);
7154  NARROWS(SignedUnscopedEnum, long double);
7155 
7156 
7157  // integral to smaller integral
7158  FITS(bool, bool);
7159  FITS(char, char);
7160  FITS(signed char, signed char);
7161  FITS(signed char, short);
7162  FITS(signed char, int);
7163  FITS(signed char, long);
7164  FITS(signed char, long long);
7165  FITS(unsigned char, unsigned char);
7166  FITS(unsigned char, unsigned short);
7167  FITS(unsigned char, unsigned int);
7168  FITS(unsigned char, unsigned long);
7169  FITS(unsigned char, unsigned long long);
7170 
7171  NARROWS_IF(bool, unsigned char, (sizeof(bool) > sizeof(char) || std::is_signed<bool>::value));
7172  NARROWS_IF(bool, unsigned short, (sizeof(bool) > sizeof(short) || std::is_signed<bool>::value));
7173  NARROWS_IF(bool, unsigned int, (sizeof(bool) > sizeof(int) || std::is_signed<bool>::value));
7174  NARROWS_IF(bool, unsigned long, (sizeof(bool) > sizeof(long) || std::is_signed<bool>::value));
7175  NARROWS_IF(bool, unsigned long long, (sizeof(bool) > sizeof(long long) || std::is_signed<bool>::value));
7176 
7177  NARROWS_IF(short, char, (sizeof(short) > sizeof(char) || std::is_unsigned<char>::value));
7178  NARROWS_IF(short, unsigned char, (sizeof(short) > sizeof(char)));
7179  NARROWS_IF(short, signed char, (sizeof(short) > sizeof(char)));
7180 
7181  NARROWS_IF(unsigned short, char, (sizeof(short) > sizeof(char) || std::is_signed<char>::value));
7182  NARROWS_IF(unsigned short, unsigned char, (sizeof(short) > sizeof(char)));
7183  NARROWS_IF(unsigned short, signed char, (sizeof(short) > sizeof(char)));
7184 
7185  FITS(short, short);
7186  FITS(short, int);
7187  FITS(short, long);
7188  FITS(short, long long);
7189 
7190  FITS(unsigned short, unsigned short);
7191  FITS(unsigned short, unsigned int);
7192  FITS(unsigned short, unsigned long);
7193  FITS(unsigned short, unsigned long long);
7194 
7195  NARROWS_IF(int, char, (sizeof(int) > sizeof(char) || std::is_unsigned<char>::value));
7196  NARROWS(int, unsigned char);
7197  NARROWS_IF(int, signed char, (sizeof(int) > sizeof(char)));
7198  NARROWS_IF(int, short, (sizeof(int) > sizeof(short)));
7199  NARROWS(int, unsigned short);
7200 
7201  NARROWS_IF(unsigned int, char, (sizeof(int) > sizeof(char) || std::is_signed<char>::value));
7202  NARROWS_IF(unsigned int, unsigned char, (sizeof(int) > sizeof(char)));
7203  NARROWS(unsigned int, signed char);
7204  NARROWS(unsigned int, short);
7205  NARROWS_IF(unsigned int, unsigned short, (sizeof(int) > sizeof(short)));
7206 
7207  FITS(int, int);
7208  FITS(int, long);
7209  FITS(int, long long);
7210 
7211  FITS(unsigned int, unsigned int);
7212  FITS(unsigned int, unsigned long);
7213  FITS(unsigned int, unsigned long long);
7214 
7215  NARROWS_IF(long, char, (sizeof(long) > sizeof(char) || std::is_unsigned<char>::value));
7216  NARROWS(long, unsigned char);
7217  NARROWS_IF(long, signed char, (sizeof(long) > sizeof(char)));
7218  NARROWS_IF(long, short, (sizeof(long) > sizeof(short)));
7219  NARROWS(long, unsigned short);
7220  NARROWS_IF(long, int, (sizeof(long) > sizeof(int)));
7221  NARROWS(long, unsigned int);
7222 
7223  NARROWS_IF(unsigned long, char, (sizeof(long) > sizeof(char) || std::is_signed<char>::value));
7224  NARROWS_IF(unsigned long, unsigned char, (sizeof(long) > sizeof(char)));
7225  NARROWS(unsigned long, signed char);
7226  NARROWS(unsigned long, short);
7227  NARROWS_IF(unsigned long, unsigned short, (sizeof(long) > sizeof(short)));
7228  NARROWS(unsigned long, int);
7229  NARROWS_IF(unsigned long, unsigned int, (sizeof(long) > sizeof(int)));
7230 
7231  FITS(long, long);
7232  FITS(long, long long);
7233 
7234  FITS(unsigned long, unsigned long);
7235  FITS(unsigned long, unsigned long long);
7236 
7237  NARROWS_IF(long long, char, (sizeof(long long) > sizeof(char) || std::is_unsigned<char>::value));
7238  NARROWS(long long, unsigned char);
7239  NARROWS_IF(long long, signed char, (sizeof(long long) > sizeof(char)));
7240  NARROWS_IF(long long, short, (sizeof(long long) > sizeof(short)));
7241  NARROWS(long long, unsigned short);
7242  NARROWS_IF(long long, int, (sizeof(long long) > sizeof(int)));
7243  NARROWS(long long, unsigned int);
7244  NARROWS_IF(long long, long, (sizeof(long long) > sizeof(long)));
7245  NARROWS(long long, unsigned long);
7246 
7247  NARROWS_IF(unsigned long long, char, (sizeof(long long) > sizeof(char) || std::is_signed<char>::value));
7248  NARROWS_IF(unsigned long long, unsigned char, (sizeof(long long) > sizeof(char)));
7249  NARROWS(unsigned long long, signed char);
7250  NARROWS(unsigned long long, short);
7251  NARROWS_IF(unsigned long long, unsigned short, (sizeof(long long) > sizeof(short)));
7252  NARROWS(unsigned long long, int);
7253  NARROWS_IF(unsigned long long, unsigned int, (sizeof(long long) > sizeof(int)));
7254  NARROWS(unsigned long long, long);
7255  NARROWS_IF(unsigned long long, unsigned long, (sizeof(long long) > sizeof(long)));
7256 
7257  FITS(long long, long long);
7258  FITS(unsigned long long, unsigned long long);
7259 
7260 
7261  // integral to integral with different signedness. smaller ones tested above
7262  NARROWS(signed char, unsigned char);
7263 
7264  // Issue is reported to Green Hills, 2021-09-14.
7265 #if !defined(Q_CC_GHS)
7266  NARROWS(signed char, unsigned short);
7267  NARROWS(signed char, unsigned int);
7268  NARROWS(signed char, unsigned long);
7269  NARROWS(signed char, unsigned long long);
7270 #endif // Q_CC_GHS
7271  NARROWS(unsigned char, signed char);
7272  FITS(unsigned char, short);
7273  FITS(unsigned char, int);
7274  FITS(unsigned char, long);
7275  FITS(unsigned char, long long);
7276 
7277  NARROWS(short, unsigned short);
7278 #if !defined(Q_CC_GHS)
7279  NARROWS(short, unsigned int);
7280  NARROWS(short, unsigned long);
7281 
7282  NARROWS(short, unsigned long long);
7283 #endif // Q_CC_GHS
7284  NARROWS(unsigned short, short);
7285 
7286  FITS(unsigned short, int);
7287  FITS(unsigned short, long);
7288  FITS(unsigned short, long long);
7289 
7290  NARROWS(int, unsigned int);
7291 #if !defined(Q_CC_GHS)
7292  NARROWS(int, unsigned long);
7293  NARROWS(int, unsigned long long);
7294 #endif // Q_CC_GHS
7295  NARROWS(unsigned int, int);
7296  NARROWS_IF(unsigned int, long, (sizeof(int) >= sizeof(long)));
7297  FITS(unsigned int, long long);
7298 
7299  NARROWS(long, unsigned long);
7300  NARROWS(long, unsigned long long);
7301 
7302  NARROWS(unsigned long, long);
7303  NARROWS_IF(unsigned long, long long, (sizeof(long) >= sizeof(long long)));
7304 
7305  NARROWS(long long, unsigned long long);
7306  NARROWS(unsigned long long, long long);
7307 
7308  // enum to smaller integral
7309  // (note that we know that sizeof(UnscopedEnum) <= sizeof(int)
7310  FITS(UnscopedEnum, UnscopedEnum);
7311  FITS(SignedUnscopedEnum, SignedUnscopedEnum);
7312 
7313  NARROWS_IF(UnscopedEnum, char, ((sizeof(UnscopedEnum) > sizeof(char)) || (sizeof(UnscopedEnum) == sizeof(char) && IsUnscopedEnumSigned == std::is_signed<char>::value)));
7314  NARROWS_IF(UnscopedEnum, signed char, ((sizeof(UnscopedEnum) > sizeof(char)) || (sizeof(UnscopedEnum) == sizeof(char) && !IsUnscopedEnumSigned)));
7315  NARROWS_IF(UnscopedEnum, unsigned char, ((sizeof(UnscopedEnum) > sizeof(char)) || IsUnscopedEnumSigned));
7316 
7317  NARROWS_IF(UnscopedEnum, short, ((sizeof(UnscopedEnum) > sizeof(short)) || (sizeof(UnscopedEnum) == sizeof(short) && !IsUnscopedEnumSigned)));
7318  NARROWS_IF(UnscopedEnum, unsigned short, ((sizeof(UnscopedEnum) > sizeof(short)) || IsUnscopedEnumSigned));
7319 
7320  NARROWS_IF(UnscopedEnum, int, sizeof(UnscopedEnum) > sizeof(int) || (sizeof(UnscopedEnum) == sizeof(int) && !IsUnscopedEnumSigned));
7321  NARROWS_IF(UnscopedEnum, unsigned int, IsUnscopedEnumSigned);
7322 
7323  NARROWS_IF(UnscopedEnum, long, sizeof(UnscopedEnum) > sizeof(long) || (sizeof(UnscopedEnum) == sizeof(long) && !IsUnscopedEnumSigned));
7324  NARROWS_IF(UnscopedEnum, unsigned long, IsUnscopedEnumSigned);
7325 
7326  NARROWS_IF(UnscopedEnum, long long, sizeof(UnscopedEnum) > sizeof(long long) || (sizeof(UnscopedEnum) == sizeof(long long) && !IsUnscopedEnumSigned));
7327  NARROWS_IF(UnscopedEnum, unsigned long long, IsUnscopedEnumSigned);
7328 
7329  static_assert(std::is_signed<typename std::underlying_type<SignedUnscopedEnum>::type>::value);
7330 
7331  NARROWS_IF(SignedUnscopedEnum, signed char, (sizeof(SignedUnscopedEnum) > sizeof(char)));
7332  NARROWS_IF(SignedUnscopedEnum, short, (sizeof(SignedUnscopedEnum) > sizeof(short)));
7333  FITS(SignedUnscopedEnum, int);
7334  FITS(SignedUnscopedEnum, long);
7335  FITS(SignedUnscopedEnum, long long);
7336 
7337  // other types which should be always unaffected
7338  FITS(void *, void *);
7339 
7340  FITS(QString, QString);
7341  FITS(QObject, QObject);
7342  FITS(QObject *, QObject *);
7343  FITS(const QObject *, const QObject *);
7344 
7345  FITS(std::nullptr_t, std::nullptr_t);
7346 
7347  // classes with conversion operators undergoing implicit conversions
7348  struct ConvertingToDouble {
7349  /* implicit */ operator double() const { return 42.0; }
7350  };
7351 
7352 #if !defined(Q_CC_GHS)
7353  NARROWS(ConvertingToDouble, char);
7354  NARROWS(ConvertingToDouble, short);
7355  NARROWS(ConvertingToDouble, int);
7356  NARROWS(ConvertingToDouble, long);
7357  NARROWS(ConvertingToDouble, long long);
7358  NARROWS(ConvertingToDouble, float);
7359 #endif // Q_CC_GHS
7360  FITS(ConvertingToDouble, double);
7361  FITS(ConvertingToDouble, long double);
7362 
7363 
7364  // GCC, GHS and clang don't implement this properly yet:
7365  // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99625
7366  // https://bugs.llvm.org/show_bug.cgi?id=49676
7367 #if defined(Q_CC_MSVC) && !defined(Q_CC_CLANG) // at least since VS2017
7368  struct ConstructibleFromInt {
7369  /* implicit */ ConstructibleFromInt(int) {}
7370  };
7371 
7372  FITS(char, ConstructibleFromInt);
7373  FITS(short, ConstructibleFromInt);
7374  FITS(int, ConstructibleFromInt);
7375  NARROWS(unsigned int, ConstructibleFromInt);
7376  NARROWS_IF(long, ConstructibleFromInt, sizeof(long) > sizeof(int));
7377  NARROWS_IF(long long, ConstructibleFromInt, sizeof(long long) > sizeof(int));
7378  NARROWS(float, ConstructibleFromInt);
7379  NARROWS(double, ConstructibleFromInt);
7380 #endif
7381 
7382  // forward declared classes must work
7383  class ForwardDeclared;
7385 
7386 #if (defined(Q_CC_EXACTLY_GCC) && Q_CC_EXACTLY_GCC >= 1100) \
7387  || (defined(Q_CC_CLANG) && Q_CC_CLANG >= 1100) \
7388  || defined(Q_CC_MSVC) // at least since VS2017
7389  {
7390  // wg21.link/P1957
7391  NARROWS(char*, bool);
7392  NARROWS(void (QObject::*)(), bool);
7393  }
7394 #endif
7395 
7396 #undef NARROWS_IF
7397 #undef FITS_IF
7398 #undef NARROWS
7399 #undef FITS
7400 
7401 #ifdef Q_CC_EXACTLY_GCC
7402 #undef Q_CC_EXACTLY_GCC
7403 #endif
7404 }
7405 
7406 void tst_QObject::nullReceiver()
7407 {
7408  QObject o;
7409  QObject *nullObj = nullptr; // Passing nullptr directly doesn't compile with gcc 4.8
7411  QVERIFY(!connect(&o, &QObject::destroyed, nullObj, [] {}));
7413  QVERIFY(!connect(&o, SIGNAL(destroyed()), nullObj, SLOT(deleteLater())));
7414 }
7415 
7416 void tst_QObject::functorReferencesConnection()
7417 {
7418  countedStructObjectsCount = 0;
7419  QMetaObject::Connection globalCon;
7420  {
7422  CountedStruct counted(&obj);
7423  QCOMPARE(countedStructObjectsCount, 1);
7425  int slotCalled = 0;
7426  *c = connect(&obj, &GetSenderObject::aSignal, &obj, [&slotCalled, c, counted] {
7428  slotCalled++;
7429  });
7430  globalCon = *c; // keep a handle to the connection somewhere;
7431  QVERIFY(globalCon);
7432  QCOMPARE(countedStructObjectsCount, 2);
7433  obj.triggerSignal();
7434  QCOMPARE(slotCalled, 1);
7435  QCOMPARE(countedStructObjectsCount, 1);
7436  QVERIFY(!globalCon);
7437  obj.triggerSignal();
7438  QCOMPARE(slotCalled, 1);
7439  QCOMPARE(countedStructObjectsCount, 1);
7440  }
7441  QCOMPARE(countedStructObjectsCount, 0);
7442 
7443  {
7445  CountedStruct counted(&obj);
7446  QCOMPARE(countedStructObjectsCount, 1);
7447  auto *rec = new QObject;
7448  int slotCalled = 0;
7449  globalCon = connect(&obj, &GetSenderObject::aSignal, rec, [&slotCalled, rec, counted] {
7450  delete rec;
7451  slotCalled++;
7452  });
7453  QCOMPARE(countedStructObjectsCount, 2);
7454  obj.triggerSignal();
7455  QCOMPARE(slotCalled, 1);
7456  QCOMPARE(countedStructObjectsCount, 1);
7457  QVERIFY(!globalCon);
7458  obj.triggerSignal();
7459  QCOMPARE(slotCalled, 1);
7460  QCOMPARE(countedStructObjectsCount, 1);
7461  }
7462  QCOMPARE(countedStructObjectsCount, 0);
7463  {
7464  int slotCalled = 0;
7465  QEventLoop eventLoop;
7466  {
7467  // Sender will be destroyed when the labda goes out of scope lambda, so it will exit the event loop
7470  globalCon = connect(sender.data(), &GetSenderObject::aSignal, this, [&slotCalled, sender, &globalCon, this] {
7471  ++slotCalled;
7472  // This signal will be connected, but should never be called as the sender will be destroyed before
7473  auto c2 = connect(sender.data(), &GetSenderObject::aSignal, [] { QFAIL("Should not be called"); });
7474  QVERIFY(c2);
7475  QVERIFY(QObject::disconnect(sender.data(), nullptr, this, nullptr));
7476  QVERIFY(!globalCon); // this connection has been disconnected
7477  QVERIFY(c2); // sender should not have been deleted yet, only after the emission is done
7478  });
7482  }
7483  eventLoop.exec();
7484  QCOMPARE(slotCalled, 1);
7485  }
7486 
7487  {
7489  CountedStruct counted(&obj);
7490  QCOMPARE(countedStructObjectsCount, 1);
7493  int slot1Called = 0;
7494  int slot3Called = 0;
7495  *c1 = connect(&obj, &GetSenderObject::aSignal, &obj, [&slot1Called, &slot3Called, &obj, c1, c2, counted] {
7496  auto c3 = connect(&obj, &GetSenderObject::aSignal, [counted, &slot3Called] {
7497  slot3Called++;
7498  });
7499  // top-level + the one in the 3 others lambdas
7500  QCOMPARE(countedStructObjectsCount, 4);
7502  slot1Called++;
7503  });
7504  connect(&obj, &GetSenderObject::aSignal, [] {}); // just a dummy signal to fill the connection list
7505  *c2 = connect(&obj, &GetSenderObject::aSignal, [counted, c2] { QFAIL("should not be called"); });
7506  QVERIFY(c1 && c2);
7507  QCOMPARE(countedStructObjectsCount, 3); // top-level + c1 + c2
7508  obj.triggerSignal();
7509  QCOMPARE(slot1Called, 1);
7510  QCOMPARE(slot3Called, 0);
7511  QCOMPARE(countedStructObjectsCount, 3); // top-level + c1 + c3
7512  QObject::disconnect(*c1);
7513  QCOMPARE(countedStructObjectsCount, 2); // top-level + c3
7514  obj.triggerSignal();
7515  QCOMPARE(slot1Called, 1);
7516  QCOMPARE(slot3Called, 1);
7517  }
7518  {
7519  struct DestroyEmit {
7520  Q_DISABLE_COPY(DestroyEmit);
7521  explicit DestroyEmit(SenderObject *obj) : obj(obj) {}
7522  SenderObject *obj;
7523  ~DestroyEmit() {
7524  obj->emitSignal1();
7525  }
7526  };
7527  SenderObject obj;
7528  int slot1Called = 0;
7529  int slot2Called = 0;
7530  int slot3Called = 0;
7533  *c1 = connect(&obj, &SenderObject::signal1, [&slot1Called, &slot3Called, de, c1, &obj] {
7534  connect(&obj, &SenderObject::signal1, [&slot3Called] { slot3Called++; });
7535  slot1Called++;
7536  QObject::disconnect(*c1);
7537  });
7538  de.clear();
7539  connect(&obj, &SenderObject::signal1, [&slot2Called] { slot2Called++; });
7540  obj.emitSignal1();
7541  QCOMPARE(slot1Called, 1);
7542  QCOMPARE(slot2Called, 2); // because also called from ~DestroyEmit
7543  QCOMPARE(slot3Called, 1);
7544  }
7545 }
7546 
7547 void tst_QObject::disconnectDisconnects()
7548 {
7549  // Test what happens if the destructor of an functor slot also disconnects more slot;
7550 
7551  SenderObject s1;
7552  QScopedPointer<QObject> receiver(new QObject);
7553 
7555  QPointer<QObject> s2_tracker = s2.data();
7556  int count = 0;
7557  connect(&s1, &SenderObject::signal1, [&count] { count++; }); // α
7558  connect(&s1, &SenderObject::signal1, receiver.data(), [s2] { QFAIL("!!"); }); // β
7559  connect(s2.data(), &SenderObject::signal1, receiver.data(), [] { QFAIL("!!"); });
7560  connect(&s1, &SenderObject::signal2, receiver.data(), [] { QFAIL("!!"); });
7561  connect(s2.data(), &SenderObject::signal2, receiver.data(), [] { QFAIL("!!"); });
7562  connect(&s1, &SenderObject::signal1, [&count] { count++; }); // γ
7563  connect(&s1, &SenderObject::signal2, [&count] { count++; }); // δ
7564  s2.clear();
7565 
7566  QVERIFY(s2_tracker);
7567  receiver
7568  .reset(); // this will delete the receiver which must also delete s2 as β is disconnected
7569  QVERIFY(!s2_tracker);
7570  // test that the data structures are still in order
7571  s1.emitSignal1();
7572  QCOMPARE(count, 2); // α + γ
7573  s1.emitSignal2();
7574  QCOMPARE(count, 3); // + δ
7575 }
7576 
7578 {
7579  Q_OBJECT
7580 
7581 public:
7584 
7585 public slots:
7587  {
7588  ++slotCalledCount;
7589  QVERIFY(!disconnect(sender, SIGNAL(signal1()), this, SLOT(aSlotByName())));
7590  }
7591 
7592  void aSlotByPtr()
7593  {
7594  ++slotCalledCount;
7596  }
7597 };
7598 
7600 {
7601  Q_OBJECT
7602 
7603 public:
7604  static int counter;
7605 
7606 public slots:
7607  void deleteThis()
7608  {
7609  ++counter;
7610  delete this;
7611  }
7612 };
7613 
7615 
7616 void tst_QObject::singleShotConnection()
7617 {
7618  {
7619  // Non single shot behavior: slot called every time the signal is emitted
7623  QVERIFY(c);
7624  QCOMPARE(sender.aPublicSlotCalled, 0);
7625 
7626  sender.emitSignal1();
7627  QCOMPARE(sender.aPublicSlotCalled, 1);
7628 
7629  sender.emitSignal1();
7630  QCOMPARE(sender.aPublicSlotCalled, 2);
7631 
7632  sender.emitSignal1();
7633  QCOMPARE(sender.aPublicSlotCalled, 3);
7634  }
7635 
7636  {
7637  // Non single shot behavior: multiple connections cause multiple invocations
7641  QVERIFY(c);
7642  QCOMPARE(sender.aPublicSlotCalled, 0);
7643 
7644  sender.emitSignal1();
7645  QVERIFY(c);
7646  QCOMPARE(sender.aPublicSlotCalled, 1);
7647 
7648  sender.emitSignal1();
7649  QVERIFY(c);
7650  QCOMPARE(sender.aPublicSlotCalled, 2);
7651 
7654  QVERIFY(c);
7655  QVERIFY(c2);
7656  QCOMPARE(sender.aPublicSlotCalled, 2);
7657 
7658  sender.emitSignal1();
7659  QVERIFY(c);
7660  QVERIFY(c2);
7661  QCOMPARE(sender.aPublicSlotCalled, 4);
7662 
7663  sender.emitSignal1();
7664  QVERIFY(c);
7665  QVERIFY(c2);
7666  QCOMPARE(sender.aPublicSlotCalled, 6);
7667  }
7668 
7669  {
7670  // Single shot behavior: slot called only once
7675  QVERIFY(c);
7676  QCOMPARE(sender.aPublicSlotCalled, 0);
7677 
7678  sender.emitSignal1();
7679  QVERIFY(!c);
7680  QCOMPARE(sender.aPublicSlotCalled, 1);
7681 
7682  sender.emitSignal1();
7683  QVERIFY(!c);
7684  QCOMPARE(sender.aPublicSlotCalled, 1);
7685 
7686  sender.emitSignal1();
7687  QVERIFY(!c);
7688  QCOMPARE(sender.aPublicSlotCalled, 1);
7689  }
7690 
7691  {
7692  // Same, without holding a Connection object
7697  QVERIFY(ok);
7698  QCOMPARE(sender.aPublicSlotCalled, 0);
7699 
7700  sender.emitSignal1();
7701  QCOMPARE(sender.aPublicSlotCalled, 1);
7702 
7703  sender.emitSignal1();
7704  QCOMPARE(sender.aPublicSlotCalled, 1);
7705 
7706  sender.emitSignal1();
7707  QCOMPARE(sender.aPublicSlotCalled, 1);
7708  }
7709 
7710  {
7711  // Single shot, disconnect before emitting
7716  QVERIFY(c);
7717  QCOMPARE(sender.aPublicSlotCalled, 0);
7718 
7720  QVERIFY(!c);
7721 
7722  sender.emitSignal1();
7723  QVERIFY(!c);
7724  QCOMPARE(sender.aPublicSlotCalled, 0);
7725 
7726  sender.emitSignal1();
7727  QVERIFY(!c);
7728  QCOMPARE(sender.aPublicSlotCalled, 0);
7729  }
7730 
7731  {
7732  // Single shot together with another connection
7736  QCOMPARE(sender.aPublicSlotCalled, 0);
7737 
7738  sender.emitSignal1();
7739  QCOMPARE(sender.aPublicSlotCalled, 1);
7740 
7741  sender.emitSignal1();
7742  QCOMPARE(sender.aPublicSlotCalled, 2);
7743 
7747  QCOMPARE(sender.aPublicSlotCalled, 2);
7748 
7749  sender.emitSignal1();
7750  QCOMPARE(sender.aPublicSlotCalled, 4);
7751 
7752  sender.emitSignal1();
7753  QCOMPARE(sender.aPublicSlotCalled, 5);
7754  }
7755 
7756  {
7757  // Two single shot, from the same signal, to the same slot
7765 
7766  QCOMPARE(sender.aPublicSlotCalled, 0);
7767 
7768  sender.emitSignal1();
7769  QCOMPARE(sender.aPublicSlotCalled, 2);
7770 
7771  sender.emitSignal1();
7772  QCOMPARE(sender.aPublicSlotCalled, 2);
7773 
7774  sender.emitSignal1();
7775  QCOMPARE(sender.aPublicSlotCalled, 2);
7776  }
7777 
7778  {
7779  // Two single shot, from different signals, to the same slot
7787 
7788  QCOMPARE(sender.aPublicSlotCalled, 0);
7789 
7790  sender.emitSignal1();
7791  QCOMPARE(sender.aPublicSlotCalled, 1);
7792 
7793  sender.emitSignal1();
7794  QCOMPARE(sender.aPublicSlotCalled, 1);
7795 
7796  sender.emitSignal2();
7797  QCOMPARE(sender.aPublicSlotCalled, 2);
7798 
7799  sender.emitSignal2();
7800  QCOMPARE(sender.aPublicSlotCalled, 2);
7801 
7802  sender.emitSignal1();
7803  QCOMPARE(sender.aPublicSlotCalled, 2);
7804  }
7805 
7806  {
7807  // Same signal, different connections
7809  ReceiverObject receiver1, receiver2;
7810  receiver1.reset();
7811  receiver2.reset();
7812 
7814  &receiver1, &ReceiverObject::slot1));
7816  &receiver2, &ReceiverObject::slot1,
7818  QCOMPARE(receiver1.count_slot1, 0);
7819  QCOMPARE(receiver2.count_slot1, 0);
7820 
7821  sender.emitSignal1();
7822  QCOMPARE(receiver1.count_slot1, 1);
7823  QCOMPARE(receiver2.count_slot1, 1);
7824 
7825  sender.emitSignal1();
7826  QCOMPARE(receiver1.count_slot1, 2);
7827  QCOMPARE(receiver2.count_slot1, 1);
7828 
7829  sender.emitSignal1();
7830  QCOMPARE(receiver1.count_slot1, 3);
7831  QCOMPARE(receiver2.count_slot1, 1);
7832 
7833  // Reestablish a single shot
7835  &receiver2, &ReceiverObject::slot1,
7837  QCOMPARE(receiver1.count_slot1, 3);
7838  QCOMPARE(receiver2.count_slot1, 1);
7839 
7840  sender.emitSignal1();
7841  QCOMPARE(receiver1.count_slot1, 4);
7842  QCOMPARE(receiver2.count_slot1, 2);
7843 
7844  sender.emitSignal1();
7845  QCOMPARE(receiver1.count_slot1, 5);
7846  QCOMPARE(receiver2.count_slot1, 2);
7847  }
7848 
7849  {
7850  // Check that the slot is invoked with the connection already disconnected
7853  auto breakSlot = [&]() {
7854  QVERIFY(!c);
7855  ++sender.aPublicSlotCalled;
7856  };
7857 
7859  &sender, breakSlot,
7861 
7862  QVERIFY(c);
7863  QCOMPARE(sender.aPublicSlotCalled, 0);
7864 
7865  sender.emitSignal1();
7866  QCOMPARE(sender.aPublicSlotCalled, 1);
7867  QVERIFY(!c);
7868 
7869  sender.emitSignal1();
7870  QCOMPARE(sender.aPublicSlotCalled, 1);
7871  QVERIFY(!c);
7872 
7873  sender.emitSignal1();
7874  QCOMPARE(sender.aPublicSlotCalled, 1);
7875  QVERIFY(!c);
7876  }
7877 
7878  {
7879  // Same
7881  ReceiverDisconnecting receiver;
7882  receiver.sender = &sender;
7883  bool ok = connect(&sender, SIGNAL(signal1()),
7884  &receiver, SLOT(aSlotByName()),
7886  QVERIFY(ok);
7887  QCOMPARE(receiver.slotCalledCount, 0);
7888 
7889  sender.emitSignal1();
7890  QCOMPARE(receiver.slotCalledCount, 1);
7891 
7892  sender.emitSignal1();
7893  QCOMPARE(receiver.slotCalledCount, 1);
7894 
7895  // reconnect
7896  ok = connect(&sender, SIGNAL(signal1()),
7897  &receiver, SLOT(aSlotByName()),
7899  QVERIFY(ok);
7900  QCOMPARE(receiver.slotCalledCount, 1);
7901 
7902  sender.emitSignal1();
7903  QCOMPARE(receiver.slotCalledCount, 2);
7904 
7905  sender.emitSignal1();
7906  QCOMPARE(receiver.slotCalledCount, 2);
7907  }
7908 
7909  {
7910  // Same
7912  ReceiverDisconnecting receiver;
7913  receiver.sender = &sender;
7917 
7918  QVERIFY(ok);
7919  QCOMPARE(receiver.slotCalledCount, 0);
7920 
7921  sender.emitSignal1();
7922  QCOMPARE(receiver.slotCalledCount, 1);
7923 
7924  sender.emitSignal1();
7925  QCOMPARE(receiver.slotCalledCount, 1);
7926 
7927  // reconnect
7931  QVERIFY(ok);
7932  QCOMPARE(receiver.slotCalledCount, 1);
7933 
7934  sender.emitSignal1();
7935  QCOMPARE(receiver.slotCalledCount, 2);
7936 
7937  sender.emitSignal1();
7938  QCOMPARE(receiver.slotCalledCount, 2);
7939  }
7940 
7941  {
7942  // Reconnect from inside the slot
7944  std::function<void()> reconnectingSlot;
7945  bool reconnect = false;
7946  reconnectingSlot = [&]() {
7947  ++sender.aPublicSlotCalled;
7948  if (reconnect) {
7950  &sender, reconnectingSlot,
7952  }
7953  };
7954 
7956  &sender, reconnectingSlot,
7958  QVERIFY(ok);
7959  QCOMPARE(sender.aPublicSlotCalled, 0);
7960 
7961  sender.emitSignal1();
7962  QCOMPARE(sender.aPublicSlotCalled, 1);
7963 
7964  sender.emitSignal1();
7965  QCOMPARE(sender.aPublicSlotCalled, 1);
7966 
7967  reconnect = true;
7969  &sender, reconnectingSlot,
7971  QVERIFY(ok);
7972  QCOMPARE(sender.aPublicSlotCalled, 1);
7973 
7974  sender.emitSignal1();
7975  QCOMPARE(sender.aPublicSlotCalled, 2);
7976 
7977  sender.emitSignal1();
7978  QCOMPARE(sender.aPublicSlotCalled, 3);
7979 
7980  sender.emitSignal1();
7981  QCOMPARE(sender.aPublicSlotCalled, 4);
7982 
7983  reconnect = false;
7984  sender.emitSignal1();
7985  QCOMPARE(sender.aPublicSlotCalled, 5);
7986 
7987  sender.emitSignal1();
7988  QCOMPARE(sender.aPublicSlotCalled, 5);
7989  }
7990 
7991  {
7992  // Delete the receiver from inside the slot
7996 
8000 
8001  QVERIFY(p);
8003 
8004  sender.emitSignal1();
8006  QVERIFY(!p);
8007 
8008  sender.emitSignal1();
8010  QVERIFY(!p);
8011  }
8012 
8013  {
8014  // Queued, non single shot
8018  static_cast<Qt::ConnectionType>(Qt::QueuedConnection)));
8019  QCOMPARE(sender.aPublicSlotCalled, 0);
8020 
8021  sender.emitSignal1();
8022  QCOMPARE(sender.aPublicSlotCalled, 0);
8023 
8024  sender.emitSignal1();
8025  QCOMPARE(sender.aPublicSlotCalled, 0);
8026 
8027  sender.emitSignal1();
8028  QCOMPARE(sender.aPublicSlotCalled, 0);
8029 
8030  QTRY_COMPARE(sender.aPublicSlotCalled, 3);
8031 
8032  sender.emitSignal1();
8033  QCOMPARE(sender.aPublicSlotCalled, 3);
8034 
8035  QTRY_COMPARE(sender.aPublicSlotCalled, 4);
8036  }
8037 
8038  {
8039  // Queued, single shot
8044  QCOMPARE(sender.aPublicSlotCalled, 0);
8045 
8046  sender.emitSignal1();
8047  QCOMPARE(sender.aPublicSlotCalled, 0);
8048 
8049  sender.emitSignal1();
8050  QCOMPARE(sender.aPublicSlotCalled, 0);
8051 
8052  sender.emitSignal1();
8053  QCOMPARE(sender.aPublicSlotCalled, 0);
8054 
8055  QTRY_COMPARE(sender.aPublicSlotCalled, 1);
8056  QTest::qWait(0);
8057  QCOMPARE(sender.aPublicSlotCalled, 1);
8058  }
8059 
8060  {
8061  // Queued, single shot, checking the connection handle
8066  QVERIFY(c);
8067  QCOMPARE(sender.aPublicSlotCalled, 0);
8068 
8069  sender.emitSignal1();
8070  QVERIFY(!c);
8071  QCOMPARE(sender.aPublicSlotCalled, 0);
8072 
8073  sender.emitSignal1();
8074  QVERIFY(!c);
8075  QCOMPARE(sender.aPublicSlotCalled, 0);
8076 
8077  sender.emitSignal1();
8078  QVERIFY(!c);
8079  QCOMPARE(sender.aPublicSlotCalled, 0);
8080 
8081  QTRY_COMPARE(sender.aPublicSlotCalled, 1);
8082  QVERIFY(!c);
8083  QTest::qWait(0);
8084  QVERIFY(!c);
8085  QCOMPARE(sender.aPublicSlotCalled, 1);
8086  }
8087 
8088  {
8089  // Queued, single shot, disconnect before emitting
8094  QCOMPARE(sender.aPublicSlotCalled, 0);
8095 
8098 
8099  sender.emitSignal1();
8100  QCOMPARE(sender.aPublicSlotCalled, 0);
8101 
8102  sender.emitSignal1();
8103  QCOMPARE(sender.aPublicSlotCalled, 0);
8104 
8105  QTest::qWait(0);
8106  QCOMPARE(sender.aPublicSlotCalled, 0);
8107  }
8108 
8109  {
8110  // Queued, single shot, disconnect before emitting by using the connection handle
8115  QVERIFY(c);
8116  QCOMPARE(sender.aPublicSlotCalled, 0);
8117 
8119  QVERIFY(!c);
8120 
8121  sender.emitSignal1();
8122  QVERIFY(!c);
8123  QCOMPARE(sender.aPublicSlotCalled, 0);
8124 
8125  sender.emitSignal1();
8126  QVERIFY(!c);
8127  QCOMPARE(sender.aPublicSlotCalled, 0);
8128 
8129  QTest::qWait(0);
8130  QVERIFY(!c);
8131  QCOMPARE(sender.aPublicSlotCalled, 0);
8132  }
8133 
8134  {
8135  // Queued, single shot, delete the receiver from inside the slot
8139 
8144 
8145  sender.emitSignal1();
8146  QVERIFY(p);
8148 
8149  sender.emitSignal1();
8150  QVERIFY(p);
8152 
8153  sender.emitSignal1();
8154  QVERIFY(p);
8156 
8158  QVERIFY(!p);
8159  QTest::qWait(0);
8161  QVERIFY(!p);
8162  }
8163 }
8164 
8165 void tst_QObject::objectNameBinding()
8166 {
8167  QObject obj;
8168  QTestPrivate::testReadWritePropertyBasics<QObject, QString>(obj, "test1", "test2",
8169  "objectName");
8170 }
8171 
8173 static int assertionCallCount = 0;
8174 static int wouldHaveAssertedCount = 0;
8175 struct WouldAssert : std::exception {};
8176 class Base : public QObject
8177 {
8178  Q_OBJECT
8179 public:
8181  {
8182  try {
8183  emit theSignal();
8184  } catch (const WouldAssert &) {
8185  ++wouldHaveAssertedCount;
8186  }
8187  }
8188 
8189 signals:
8190  void theSignal();
8191 };
8192 
8193 class Derived : public Base
8194 {
8195  Q_OBJECT
8196 public:
8197  ~Derived() { }
8198 
8199 public slots:
8200  void doNothing() {}
8201 };
8202 } // namespace EmitToDestroyedClass
8203 
8205 namespace QtPrivate {
8206 template<> void assertObjectType<EmitToDestroyedClass::Derived>(QObject *o)
8207 {
8208  // override the assertion so we don't assert and so something does happen
8209  // when assertions are disabled. By throwing, we also prevent the UB from
8210  // happening.
8211  using namespace EmitToDestroyedClass;
8212  ++assertionCallCount;
8213  if (!qobject_cast<Derived *>(o))
8214  throw WouldAssert();
8215 }
8216 }
8218 
8219 void tst_QObject::emitToDestroyedClass()
8220 {
8221  using namespace EmitToDestroyedClass;
8222  std::unique_ptr ptr = std::make_unique<Derived>();
8223  QObject::connect(ptr.get(), &Base::theSignal, ptr.get(), &Derived::doNothing);
8224  QCOMPARE(assertionCallCount, 0);
8225  QCOMPARE(wouldHaveAssertedCount, 0);
8226 
8227  // confirm our replacement function did get called
8228  emit ptr->theSignal();
8229  QCOMPARE(assertionCallCount, 1);
8230  QCOMPARE(wouldHaveAssertedCount, 0);
8231 
8232  ptr.reset();
8233  QCOMPARE(assertionCallCount, 2);
8234  QCOMPARE(wouldHaveAssertedCount, 1);
8235 }
8236 
8237 // Test for QtPrivate::HasQ_OBJECT_Macro
8240 
8241 Q_DECLARE_SMART_POINTER_METATYPE(std::shared_ptr)
8242 Q_DECLARE_SMART_POINTER_METATYPE(std::unique_ptr)
8243 
8244 
8245 // QTBUG-103741: OK to use smart pointers to const QObject in signals/slots
8247 {
8248  Q_OBJECT
8249 
8250 signals:
8254  void aSignal4(const std::shared_ptr<const QObject> &);
8255  void aSignal5(const std::unique_ptr<const QObject> &);
8256 };
8257 
8259 #include "tst_qobject.moc"
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
#define value
[5]
@ Float
FT_UInt idx
Definition: cffcmap.c:135
void on_Sender_signalManyParams(int, int, int, QString, bool, bool)
void on_Sender_signalWithParams(int, QString)
void on_Sender_signalWithParams(int=0)
void on_Sender_signalManyParams()
void emit_signal_with_underscore()
void on_Receiver_signalNoParams()
void on_Sender_signalManyParams(int, int, int, QString, bool)
void on_Sender_signalNoParams()
void on_Sender_signalManyParams2(int, int, int, QString, bool)
QList< int > called_slots
void on_Receiver_signal_with_underscore()
void on_Sender_signalLoopBack()
void signal_with_underscore()
void emitSignalManyParams(int i1, int i2, int i3, QString string, bool onoff)
void emitSignalWithParams(int i, QString string)
void signalWithParams(int i, QString string)
void signalManyParams2(int i1, int i2, int i3, QString string, bool onoff)
void emitSignalWithParams(int i)
void signalManyParams(int i1, int i2, int i3, QString string, bool onoff)
void emitSignalManyParams2(int i1, int i2, int i3, QString string, bool onoff)
void emitSignalManyParams(int i1, int i2, int i3, QString string, bool onoff, bool dummy)
void signalManyParams(int i1, int i2, int i3, QString string, bool onoff, bool)
void signalWithParams(int i)
AutoConnectSender(QObject *parent)
int rtti() const override
void disconnectNotify(const QMetaMethod &signal) override
QList< QMetaMethod > connectedSignals
QList< QMetaMethod > disconnectedSignals
void connectNotify(const QMetaMethod &signal) override
void stringPtr(QString *, const QString &)
void stringSlot3(QString &s)
void boolPtr(bool *, bool)
void boolRefSlot(bool &b1, bool b2)
void stringRef(QString &, const QString &)
void stringSlot2(const QString &s)
void boolRef(bool &, bool)
void stringPtrSlot(QString *s1, const QString &s2)
void stringRefSlot(QString &s1, const QString &s2)
void boolPtrSlot(bool *b1, bool b2)
Q_INVOKABLE Constructable()
void compareSender(QObject *s)
CountedExceptionThrower(bool throwException, QObject *parent=nullptr)
CustomType(const CustomType &other)
CustomType & operator=(const CustomType &)=default
CustomType(int l1=0, int l2=0, int l3=0)
void theSecondSignal(const QString &s=QString("secondDefault"))
void theSlot(const QString &s)
void theOriginalSignal()
void emitTheOriginalSignal()
void emitTheSecondSignal()
QPointer< QObject > pointer
void relaySignalAndProcessEvents()
DispatcherWatcher(QEventLoop &e, int *statusAwake, int *statusAboutToBlock)
virtual bool event(QEvent *e) override
QList< QByteArray > changedDynamicProperties
void work()
void run(void) override
EventList eventList()
void clear()
QList< QPair< QObject *, QEvent::Type > > EventList
EventSpy(QObject *parent=nullptr)
bool eventFilter(QObject *object, QEvent *event) override
CountedStruct throwException(const CountedStruct &, CountedStruct s2)
CountedStruct mySignal(const CountedStruct &s1, CountedStruct s2)
int rtti() const override
void mySignal(const ForwardDeclared &)
void mySlot(const ForwardDeclared &)
void signal_VV(const QVariant &, const QVariant &)
void signal_ddS(double, double, const QString &)
void signal_iiS(int, int, const QString &)
void signal_S(const QString &)
void signal_SSSS(const QString &, const QString &, const QString &, const QString &)
void signal_dd(double, double)
void signal_iiSS(int, int, const QString &, const QString &)
QObject * sender() const
Definition: qobject.cpp:2472
void const_slot_vi(int) const
static int static_slot_ii(int)
void signal_viii(int, int, int)
void signal(short &, short, long long, short)
static void static_slot_vii(int, int)
int slot_iii(int, int)
void slot_v_noexcept() noexcept
void slot_viii(int, int, int)
static int static_slot_iii(int, int)
void slot_vRs(short &)
static void static_slot_vRi(int &)
void signal_vRQObject(QObject &)
void signal_vRs(short &)
void slot_vi_noexcept() noexcept
void otherSignal(const char *)
static int static_slot_iiii(int, int, int)
void const_slot_v_noexcept() const noexcept
void signal_vcRQObject(const QObject &)
static void static_slot_viii(int, int, int)
void const_signal_vi(int) const
static void static_slot_vPFvvE(fptr)
static void static_slot_vi(int)
void const_slot_v() const
void slot_vii(int, int)
static int static_slot_i_noexcept() noexcept
static void static_slot_v()
void signal_vii(int, int)
void slot_vcRQObject(const QObject &)
int slot_i_noexcept() noexcept
void signal_vPFvvE(fptr)
static void static_slot_vs(short)
void const_signal_v() const
static void static_slot_vRs(short &)
void signal_vRi(int &)
static void static_slot_vi_noexcept(int) noexcept
static void static_slot_v_noexcept() noexcept
void const_slot_vi_noexcept(int) const noexcept
int slot_iiii(int, int, int)
void slot_vRQObject(QObject &)
static int static_slot_i()
void signal2(const QString &, const QString &)
void signal4(const QString &, const QString &, const QString &, const QString &)
void slot4(const QString &a, const QString &b, const QString &c, const QString &d)
void slot3(const QString &a, const QString &b, const QString &c)
void slot5(const QString &a, const QString &b, const QString &c, const QString &d, const QString &e)
void slot6(const QString &a, const QString &b, const QString &c, const QString &d, const QString &e, const QString &f)
void signal1(const QString &)
void signal5(const QString &, const QString &, const QString &, const QString &, const QString &)
void slot1(const QString &a)
void signal3(const QString &, const QString &, const QString &)
void slot2(const QString &a, const QString &b)
void signal6(const QString &, const QString &, const QString &, const QString &, const QString &, const QString &)
void sig22()
void sig03()
void sig44()
void sig06()
void sig12()
void sig20()
void sig32()
void sig40()
void sig36()
void sig50()
void sig68()
void sig53()
void sig56()
void sig55()
void sig35()
void sig02()
void sig10()
void sig16()
void sig39()
void sig01()
void sig60()
void sig57()
void sig15()
void sig54()
void sig17()
void sig45()
void sig07()
void sig67()
void sig29()
void sig49()
void sig61()
void sig31()
void sig18()
void sig09()
void sig33()
void sig42()
void sig28()
void sig14()
void sig27()
void sig52()
void sig48()
void sig25()
void sig08()
void sig30()
void sig43()
void sig62()
void sig51()
void sig64()
void sig13()
void sig69()
void sig34()
void sig04()
void sig63()
void sig26()
void sig11()
void sig46()
void sig66()
void sig38()
void sig00()
void sig59()
void sig41()
void sig19()
void sig65()
void sig05()
void sig58()
void sig23()
void sig21()
void sig24()
void sig37()
void sig47()
QThread * timerEventThread
QThread * customEventThread
void customEvent(QEvent *) override
MoveToThreadObject(QObject *parent=nullptr)
void timerEvent(QTimerEvent *) override
void run() override
MyFunctor(QObject *objectToDisconnect)
void operator()()
void mySlot(const NoDefaultConstructor &)
void mySignal(const NoDefaultConstructor &)
void unsignedlongSlot(unsigned long)
void classPointerSlot(Class *c)
void constTemplateSlot1(Template< int > const)
void ulongPointerSlot(ulong *)
void typeRefSignal(Template< Class & > &ref)
void constEnumPointerSignal(const Enum *e)
void unsignedintSlot(unsigned int)
void constEnumPointerConstPointerSignal(const Enum *const *e)
void structSlot(Struct s)
void structSignal(Struct s)
void structPointerSlot(Struct *s)
void constStructPointerSignal(const Struct *s)
void unsignedlonglongSlot(quint64)
void enumPointerSignal(Enum *e)
void enumPointerSlot(Enum *e)
void classSlot(Class c)
void unsignedcharSlot(unsigned char)
void constEnumPointerConstPointerSlot(const Enum *const *e)
void constStructPointerSlot(const Struct *s)
void constUintPointerSignal(const uint *)
void ulongPointerSignal(ulong *)
void typePointerConstRefSignal(Class *const &)
void constTypeRefSignal(const Template< Class const & > &ref)
void typeConstRefSignal(Template< Class const & > const &ref)
void constUlongPointerSignal(const ulong *)
void enumSlot(Enum e)
void constUlongPointerSlot(const ulong *)
void constTemplateSlot2(const Template< int >)
void constClassPointerSignal(const Class *c)
void uintPointerSignal(uint *)
void unsignedlongSignal(unsigned long)
void unsignedSignal(unsigned)
void typeConstRefSlot(Template< Class const & > const &)
void constTemplateSignal1(Template< int >)
void classPointerSignal(Class *c)
void unsignedlonglongSignal(quint64)
void constClassPointerSlot(const Class *c)
void constClassPointerConstPointerSignal(const Class *const *c)
void constClassPointerConstPointerSlot(const Class *const *c)
void typePointerConstRefSlot(Class *const &)
void typeRefSlot(Template< Class & > &)
void constStructPointerConstPointerSignal(const Struct *const *s)
void classSignal(Class c)
void constTemplateSignal2(Template< const int >)
void unsignedlongintSignal(unsigned long int)
void constTemplateSlot3(const Template< const int >)
void unsignedshortSlot(unsigned short)
void unsignedcharSignal(unsigned char)
void unsignedshortSignal(unsigned short)
void unsignedSlot(unsigned)
void uintSlot(uint)
void constStructPointerConstPointerSlot(const Struct *const *s)
void enumSignal(Enum e)
void structPointerSignal(Struct *s)
void unsignedintSignal(unsigned int)
void uintPointerSlot(uint *)
void constEnumPointerSlot(const Enum *e)
void unsignedlongintSlot(unsigned long int)
void constTypeRefSlot(const Template< const Class & > &)
void constUintPointerSlot(const uint *)
void clearNotifications()
void connectNotify(const QMetaMethod &signal) override
void disconnectNotify(const QMetaMethod &signal) override
QList< QMetaMethod > disconnectedSignals
QList< QMetaMethod > connectedSignals
Definition: main.cpp:55
virtual void slot2() override
virtual void slot1() override
void slo(QObject *o, QObject *p=qApp, QObject *q=qApp, QObject *r=qApp)
void sig(QObject *o, QObject *p, QObject *q=nullptr, QObject *r=nullptr) const
void sig(double r=0.5)
void sig(int i, int j=12)
QObject * o3_obj
void other(int a=0)
QObject * o2_obj
void slo(int i, int j=43)
void sig(int i, char c, qreal m=12)
void sig(QObject *o, OverloadObject *p=nullptr, QObject *q=nullptr, QObject *r=nullptr)
QObject * o1_obj
QObject * o4_obj
void setString(const QString &string)
Priority priority() const
void setMyQReal(qreal value)
void setMyFloat(float value)
void setPriority(Priority priority)
void setNumber(int number)
QVariant variant() const
QString string() const
void setVariant(const QVariant &variant)
CustomString customString() const
void setCustom(CustomType *custom)
CustomType * custom
int number() const
qreal myQReal() const
Alpha alpha() const
float myFloat() const
CustomString customString
void setCustomString(const QString &string)
CustomType * custom() const
void setAlpha(Alpha alpha)
static QAbstractEventDispatcher * instance(QThread *thread=nullptr)
void rowsInserted(const QModelIndex &parent, int first, int last, QPrivateSignal)
virtual bool waitForConnected(int msecs=30000)
virtual void connectToHost(const QString &hostName, quint16 port, OpenMode mode=ReadWrite, NetworkLayerProtocol protocol=AnyIPProtocol)
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:85
static QCoreApplication * instance()
static bool sendEvent(QObject *receiver, QEvent *event)
static void removePostedEvents(QObject *receiver, int eventType=0)
static void processEvents(QEventLoop::ProcessEventsFlags flags=QEventLoop::AllEvents)
static void postEvent(QObject *receiver, QEvent *event, int priority=Qt::NormalEventPriority)
void aboutToQuit(QPrivateSignal)
static QString applicationDirPath()
static void sendPostedEvents(QObject *receiver=nullptr, int event_type=0)
void signal1(CustomType ct)
QCustomTypeChecker(QObject *parent=nullptr)
void slot2(const QList< CustomType > &ct)
void slot1(CustomType ct)
void signal2(const QList< CustomType > &ct)
void doEmit(CustomType ct)
The QDataStream class provides serialization of binary data to a QIODevice.
Definition: qdatastream.h:66
operator>>(QDataStream &ds, qfloat16 &f)
Definition: qfloat16.cpp:344
operator<<(QDataStream &ds, qfloat16 f)
Definition: qfloat16.cpp:327
static QChar separator()
Definition: qdir.h:234
The QDynamicPropertyChangeEvent class contains event parameters for dynamic property change events.
Definition: qcoreevent.h:400
The QEvent class is the base class of all event classes. Event objects contain event parameters.
Definition: qcoreevent.h:58
@ MetaCall
Definition: qcoreevent.h:110
@ ChildRemoved
Definition: qcoreevent.h:121
@ DynamicPropertyChange
Definition: qcoreevent.h:220
@ ChildAdded
Definition: qcoreevent.h:119
The QEventLoop class provides a means of entering and leaving an event loop.
Definition: qeventloop.h:50
int exec(ProcessEventsFlags flags=AllEvents)
Definition: qeventloop.cpp:162
void quit()
Definition: qeventloop.cpp:329
The QFile class provides an interface for reading from and writing to files.
Definition: qfile.h:94
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal.
Definition: qstring.h:84
qsizetype size() const noexcept
Definition: qlist.h:414
bool isEmpty() const noexcept
Definition: qlist.h:418
const_reference at(qsizetype i) const noexcept
Definition: qlist.h:457
void append(parameter_type t)
Definition: qlist.h:469
void clear()
Definition: qlist.h:445
The QMetaMethod class provides meta-data about a member function.
Definition: qmetaobject.h:54
static QMetaMethod fromSignal(PointerToMemberFunction signal)
Definition: qmetaobject.h:175
The QMetaProperty class provides meta-data about a property.
Definition: qmetaobject.h:277
bool write(QObject *obj, const QVariant &value) const
QVariant read(const QObject *obj) const
bool isValid() const
Definition: qmetaobject.h:331
bool isRegistered() const
Definition: qmetatype.cpp:521
bool load(QDataStream &stream, void *data) const
Definition: qmetatype.cpp:2740
bool save(QDataStream &stream, const void *data) const
Definition: qmetatype.cpp:2699
friend class QVariant
Definition: qmetatype.h:744
The QModelIndex class is used to locate data in a data model.
The QMutex class provides access serialization between threads.
Definition: qmutex.h:285
void unlock() noexcept
Definition: qmutex.h:293
void lock() noexcept
Definition: qmutex.h:290
The QObject class is the base class of all Qt objects.
Definition: qobject.h:125
int senderSignalIndex() const
Definition: qobject.cpp:2514
Q_INVOKABLE QObject(QObject *parent=nullptr)
Definition: qobject.cpp:913
void installEventFilter(QObject *filterObj)
Definition: qobject.cpp:2235
QObject * parent() const
Definition: qobject.h:409
void moveToThread(QThread *thread)
Definition: qobject.cpp:1572
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
Definition: qobject.cpp:2772
QObject * sender() const
Definition: qobject.cpp:2472
virtual bool event(QEvent *event)
Definition: qobject.cpp:1329
void setParent(QObject *parent)
Definition: qobject.cpp:2108
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
Definition: qobject.cpp:3048
QThread * thread() const
Definition: qobject.cpp:1527
bool blockSignals(bool b) noexcept
Definition: qobject.cpp:1514
int receivers(const char *signal) const
Definition: qobject.cpp:2554
void setObjectName(const QString &name)
Definition: qobject.cpp:1261
bool setProperty(const char *name, const QVariant &value)
Definition: qobject.cpp:4063
void objectNameChanged(const QString &objectName, QPrivateSignal)
void destroyed(QObject *=nullptr)
void deleteLater()
Definition: qobject.cpp:2319
bool isSignalConnected(uint signalIdx, bool checkDeclarative=true) const
Definition: qobject.cpp:460
static QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer< Func1 >::Object *sender, Func1 signal, const typename QtPrivate::FunctionPointer< Func2 >::Object *receiverPrivate, Func2 slot, Qt::ConnectionType type=Qt::AutoConnection)
Definition: qobject_p.h:533
static bool disconnect(const typename QtPrivate::FunctionPointer< Func1 >::Object *sender, Func1 signal, const typename QtPrivate::FunctionPointer< Func2 >::Object *receiverPrivate, Func2 slot)
Definition: qobject_p.h:562
int signalIndex(const char *signalName, const QMetaObject **meta=nullptr) const
Definition: qobject.cpp:4018
static QObjectPrivate * get(QObject *o)
Definition: qobject_p.h:368
void signalWithIncomplete(const Incomplete &)
QObjectWithIncomplete(QObject *parent=nullptr)
void slotWithIncomplete(const Incomplete &)
The QPointer class is a template class that provides guarded pointers to QObject.
Definition: qpointer.h:54
bool isNull() const
Definition: qpointer.h:87
The QRegularExpression class provides pattern matching using regular expressions.
The QScopedPointer class stores a pointer to a dynamically allocated object, and deletes it upon dest...
The QSharedPointer class holds a strong reference to a shared pointer.
static QSharedPointer create(Args &&...arguments)
The QString class provides a Unicode character string.
Definition: qstring.h:388
static QString fromLatin1(QByteArrayView ba)
Definition: qstring.cpp:5488
static QString number(int, int base=10)
Definition: qstring.cpp:7538
The QStringListModel class provides a model that supplies strings to views.
The QTcpServer class provides a TCP-based server.
Definition: qtcpserver.h:58
The QTcpSocket class provides a TCP socket.
Definition: qtcpsocket.h:54
void terminate()
Definition: qthread.cpp:843
void start(Priority=InheritPriority)
Definition: qthread.cpp:836
bool isRunning() const
Definition: qthread.cpp:899
static QThread * currentThread()
Definition: qthread.cpp:879
bool wait(QDeadlineTimer deadline=QDeadlineTimer(QDeadlineTimer::Forever))
Definition: qthread.cpp:863
int exec()
Definition: qthread.cpp:831
void quit()
Definition: qthread.cpp:848
void started(QPrivateSignal)
The QTimerEvent class contains parameters that describe a timer event.
Definition: qcoreevent.h:367
The QTimer class provides repetitive and single-shot timers.
Definition: qtimer.h:58
void setSingleShot(bool singleShot)
Definition: qtimer.cpp:730
void setInterval(int msec)
Definition: qtimer.cpp:757
bool singleShot
whether the timer is a single-shot timer
Definition: qtimer.h:60
void timeout(QPrivateSignal)
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:95
static auto fromValue(const T &value) -> std::enable_if_t< std::is_copy_constructible_v< T >, QVariant >
Definition: qvariant.h:391
int toInt(bool *ok=nullptr) const
Definition: qvariant.cpp:1833
bool isNull() const
Definition: qvariant.cpp:2483
bool canConvert(QMetaType targetType) const
Definition: qvariant.h:246
void setValue(T &&avalue)
Definition: qvariant.h:355
bool wait(QMutex *, QDeadlineTimer=QDeadlineTimer(QDeadlineTimer::Forever))
The QWeakPointer class holds a weak reference to a shared pointer.
void destroyIfLastRef() noexcept
SenderObject * sender
bool called(int slot)
static int sequence
QObject * returnPointer()
MoveOnly returnMoveOnlySlot(int i)
int returnIntSlot(int i)
int returnInt(int)
QString returnHello()
ReturnValue * returnThisSlot2()
QVariant returnVariant(int)
CustomType returnCustomType(int)
QString returnStringSlot(int i)
CustomType returnCustomTypeSlot(int i)
void returnVoidSlot()
void returnVoid(int)
MoveOnly returnMoveOnly(int)
QString returnString(int)
QObject * returnThisSlot1()
QVariant returnVariantSlot(int i)
void signal7(int, const QString &)
Q_INVOKABLE QT_MOC_COMPAT void invoke2(int)
void emitSignal1()
void signal6(void)
Q_INVOKABLE QT_MOC_COMPAT void invoke2()
void emitSignal3()
Q_INVOKABLE void invoke1()
void signal2()
Q_SCRIPTABLE QT_MOC_COMPAT void sinvoke2()
void emitSignal2()
QT_MOC_COMPAT void signal5()
void signal4()
Q_SCRIPTABLE void sinvoke1()
void emitSignal1AfterRecursion()
void emitSignal4()
void signal1()
void signal3()
void aPublicSlot()
void aSignal5(const std::unique_ptr< const QObject > &)
void aSignal4(const std::shared_ptr< const QObject > &)
void aSignal1(const QSharedPointer< const QObject > &)
void aSignal2(const QWeakPointer< const QObject > &)
void aSignal3(const QPointer< const QObject > &)
void slot2_deleteSender()
void slot1_disconnectThis()
void slot1_deleteNext()
void slot1_disconnectNext()
void slot2_reconnectNext()
void slot2_reconnectThis()
virtual ~SiblingDeleter()
SiblingDeleter(QObject *sibling, QObject *parent)
static void staticSlot()
StatusChanger(int *status)
void stringSignal(const QString &str)
void variantSlot(const QVariant &v)
void rememberSender()
void theSignal()
void deleteAndRememberSender()
QObject * sender() const
Definition: qobject.cpp:2472
void anotherSignal()
QObject * theSender
QObject ** child
QWaitCondition cond
void run() override
QObject ** object
void run() override
ThreadAffinityThread(SenderObject *sender)
SenderObject * sender
[user-class]
Definition: user.h:59
virtual void slot1() override
QString str
[2]
double e
auto signal
auto mo
[7]
QSignalSpy spy(myCustomObject, SIGNAL(mySignal(int, QString, double)))
[0]
QCOMPARE(spy.count(), 1)
constexpr T & operator()(T &v) const
Definition: hb-algs.hh:2
auto it unsigned count const
Definition: hb-iter.hh:848
void slot3(const QString &a, const QString &b, const QString &c)
void slot1(const QString &a)
void slot4(const QString &a, const QString &b, const QString &c, const QString &d)
void slot5(const QString &a, const QString &b, const QString &c, const QString &d, const QString &e)
void slot2(const QString &a, const QString &b)
void slot6(const QString &a, const QString &b, const QString &c, const QString &d, const QString &e, const QString &f)
void toString(QString &appendTo, IPv4Address address)
Definition: qipaddress.cpp:131
Q_TESTLIB_EXPORT QTestData & newRow(const char *dataTag)
Definition: qtestcase.cpp:2658
Q_TESTLIB_EXPORT void ignoreMessage(QtMsgType type, const char *message)
Definition: qtestcase.cpp:2292
Q_CORE_EXPORT void qWait(int ms)
@ FindDirectChildrenOnly
Definition: qnamespace.h:1479
ConnectionType
Definition: qnamespace.h:1304
@ SingleShotConnection
Definition: qnamespace.h:1310
@ AutoConnection
Definition: qnamespace.h:1305
@ BlockingQueuedConnection
Definition: qnamespace.h:1308
@ QueuedConnection
Definition: qnamespace.h:1307
@ UniqueConnection
Definition: qnamespace.h:1309
@ DirectConnection
Definition: qnamespace.h:1306
typing.Tuple[int, int] test(str binary_directory, *debug=False)
#define QString()
Definition: parse-defines.h:51
set set set set set set set macro pixldst1 op
void
Definition: png.h:1080
png_alloc_size_t ob
Definition: pngwrite.c:2169
#define Q_FUNC_INFO
#define qApp
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction function
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage return DBusPendingCall DBusPendingCall return DBusPendingCall return dbus_int32_t return DBusServer * server
DBusConnection * connection
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char * method
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter * sub
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLStreamKHR stream
EGLOutputLayerEXT EGLint EGLAttrib value
unsigned long ulong
Definition: qglobal.h:335
QT_END_INCLUDE_NAMESPACE typedef double qreal
Definition: qglobal.h:341
unsigned long long quint64
Definition: qglobal.h:299
unsigned int uint
Definition: qglobal.h:334
#define Q_DISABLE_COPY(Class)
Definition: qglobal.h:515
@ QtWarningMsg
Definition: qlogging.h:62
@ QtDebugMsg
Definition: qlogging.h:61
#define qFatal
Definition: qlogging.h:181
#define Q_DECLARE_METATYPE(TYPE)
Definition: qmetatype.h:1417
#define Q_DECLARE_SMART_POINTER_METATYPE(SMART_POINTER)
Definition: qmetatype.h:1539
#define Q_SET_OBJECT_NAME(obj)
Definition: qobject.h:606
#define Q_DECLARE_INTERFACE(IFace, IId)
Definition: qobject.h:504
#define SLOT(a)
Definition: qobjectdefs.h:87
#define SIGNAL(a)
Definition: qobjectdefs.h:88
GLenum type
Definition: qopengl.h:270
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
const GLfloat * m
GLboolean r
[2]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat s1
GLenum GLenum GLsizei count
GLuint object
[3]
GLbitfield GLuint64 timeout
[4]
GLfloat GLfloat f
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t1
[4]
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t0
GLuint start
GLint ref
GLuint name
struct _cl_event * event
Definition: qopenglext.h:2998
GLhandleARB obj
[2]
Definition: qopenglext.h:4164
const GLubyte * c
Definition: qopenglext.h:12701
GLsizei const void * pointer
Definition: qopenglext.h:384
GLdouble GLdouble GLdouble GLdouble q
Definition: qopenglext.h:259
GLsizei const GLchar *const * path
Definition: qopenglext.h:4283
GLuint64EXT * result
[6]
Definition: qopenglext.h:10932
GLdouble s
[6]
Definition: qopenglext.h:235
GLfloat GLfloat p
[1]
Definition: qopenglext.h:12698
GLfloat GLfloat GLfloat alpha
Definition: qopenglext.h:418
constexpr decltype(auto) qMakePair(T1 &&value1, T2 &&value2) noexcept(noexcept(std::make_pair(std::forward< T1 >(value1), std::forward< T2 >(value2))))
Definition: qpair.h:55
#define Q_ASSERT(cond)
Definition: qrandom.cpp:84
SSL_CTX int(*) void arg)
#define QStringLiteral(str)
#define s3
#define s2
#define t4
#define s1
#define t0
#define t1
#define QTEST_MAIN(TestObject)
Definition: qtest.h:664
#define QSKIP(statement,...)
Definition: qtestcase.h:222
#define QFETCH(Type, name)
Definition: qtestcase.h:230
#define QFAIL(message)
Definition: qtestcase.h:70
#define QTRY_COMPARE(expr, expected)
Definition: qtestcase.h:214
#define QVERIFY(statement)
Definition: qtestcase.h:64
#define QVERIFY2(statement, description)
Definition: qtestcase.h:76
#define Q_ENUM(x)
Definition: qtmetamacros.h:104
#define Q_PROPERTY(...)
Definition: qtmetamacros.h:92
#define Q_OBJECT
Definition: qtmetamacros.h:158
#define Q_SCRIPTABLE
Definition: qtmetamacros.h:111
#define Q_EMIT
Definition: qtmetamacros.h:83
#define Q_INVOKABLE
Definition: qtmetamacros.h:112
#define Q_INTERFACES(x)
Definition: qtmetamacros.h:91
#define Q_SLOTS
Definition: qtmetamacros.h:80
#define Q_GADGET
Definition: qtmetamacros.h:193
#define slots
Definition: qtmetamacros.h:76
#define signals
Definition: qtmetamacros.h:77
#define Q_SIGNALS
Definition: qtmetamacros.h:81
#define emit
Definition: qtmetamacros.h:85
const char property[13]
Definition: qwizard.cpp:136
QSqlQueryModel * model
[16]
Q_UNUSED(salary)
[21]
QByteArray ba
[0]
connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::QueuedConnection)
qRegisterMetaType< CustomString >("CustomString")
QObject::connect nullptr
QTcpSocket * socket
[1]
QTimer * timer
[3]
QVariant variant
[1]
MyCustomStruct c2
QRect r1(100, 200, 11, 16)
[0]
QRect r2(QPoint(100, 200), QSize(11, 16))
QScopedPointer< MyCustomClass, ScopedPointerCustomDeleter > customPointer(new MyCustomClass)
QSharedPointer< T > other(t)
[5]
QSize t3(10, 12)
QSize t2(10, 12)
QLayoutItem * child
[0]
serverDtls doHandshake & serverSocket
void testObject()
[11]
QStringList list
[0]
ComplexFunctorDeriv(int &overload, QList< QVariant > &result)
void operator()() const
void operator()(int a, int b)
void operator()(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4)
ComplexFunctor(int &overload, QList< QVariant > &result)
void operator()(int a, int b)
void operator()(const QString &) const
QList< QVariant > & result
void operator()(const QString &s)
void operator()() const
void operator()(double a, double b)
void operator()() const
CountedStruct & operator=(const CountedStruct &)
CountedStruct(GetSenderObject *sender)
GetSenderObject * sender
CountedStruct(const CountedStruct &o)
virtual int rtti() const =0
virtual ~Bar()
virtual int rtti() const =0
virtual ~Bleh()
void operator()() noexcept
QVariant * var
void operator()(const QString &a)
void operator()(const QString &a, const QString &b)
void operator()(const QString &a, const QString &b, const QString &c)
void operator()(const QString &a, const QString &b, const QString &c, const QString &d)
void operator()(const QString &a, const QString &b, const QString &c, const QString &d, const QString &e)
void operator()(const QString &a, const QString &b, const QString &c, const QString &d, const QString &e, const QString &f)
MoveOnly & operator=(MoveOnly &&o)
Q_DISABLE_COPY(MoveOnly)
MoveOnly(MoveOnly &&o)
MoveOnly(int v=1)
virtual void virtualBaseSlot()
void normalBaseSlot()
virtual ~NormalBase()
QByteArray lastCalled
bool contains(const AT &t) const noexcept
Definition: qlist.h:78
The QMetaObject class contains meta-information about Qt objects.
Definition: qobjectdefs.h:165
int indexOfSignal(const char *signal) const
static bool disconnectOne(const QObject *sender, int signal_index, const QObject *receiver, int method_index)
Definition: qobject.cpp:3464
static bool disconnect(const QObject *sender, int signal_index, const QObject *receiver, int method_index)
Definition: qobject.cpp:3448
int indexOfConstructor(const char *constructor) const
int indexOfSlot(const char *slot) const
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(nullptr), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
static QByteArray normalizedSignature(const char *method)
static void connectSlotsByName(QObject *o)
Definition: qobject.cpp:3614
static Connection connect(const QObject *sender, int signal_index, const QObject *receiver, int method_index, int type=0, int *types=nullptr)
Definition: qobject.cpp:3363
QMetaMethod constructor(int index) const
int indexOfMethod(const char *method) const
QMetaMethod method(int index) const
static void activate(QObject *sender, int signal_index, void **argv)
Definition: qobject.cpp:4001
static void impl(int which, QSlotObjectBase *this_, QObject *, void **metaArgs, bool *ret)
SlotArgFunctor(int *s)
ContextObject * context
QObject * sender
SlotArgFunctor(ContextObject *context, QObject *sender, int *s)
void operator()()
void operator()(const QString &)
CountedStruct s
CountedStruct operator()(const CountedStruct &, CountedStruct s2) const
virtual void slot2()=0
virtual ~VirtualBase()
int virtual_base_count
QThreadStorage< int * > dummy[8]
int receivedCount
void receiverFunction_noexcept() noexcept
void connectFunctorOverload_impl(Signal signal, int expOverload, QList< QVariant > expResult)
Enum
#define Bleh_iid
#define MANYARGUMENT_COMPARE(L)
void receiverFunction()
QString someFunctionReturningString(int i)
#define NARROWS_IF(x, y, test)
#define FITS(x, y)
#define SIGNAL_INDEX(S)
QString CustomString
#define NARROWS(x, y)
int fn(int &i)
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent