1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtTest/QtTest>
44 #include <qcoreapplication.h>
48 #include <qmetaobject.h>
54 #include <QWaitCondition>
58 #ifdef QT_BUILD_INTERNAL
59 #include <private/qobject_p.h>
64 class tst_QObject : public QObject
71 void connectSignalsToSignalsWithDefaultArguments();
74 void qobject_castTemplate();
76 void connectDisconnectNotify_data();
77 void connectDisconnectNotify();
78 void emitInDefinedOrder();
80 void streamCustomTypes();
83 void threadSignalEmissionCrash();
88 void declareInterface();
89 void qpointerResetBeforeDestroyedSignal();
91 void childDeletesItsSibling();
92 void dynamicProperties();
97 void recursiveSignalEmission();
99 void blockingQueuedConnection();
101 void installEventFilter();
102 void deleteSelfInSlot();
103 void disconnectSelfInSlotAndDeleteAfterEmit();
104 void dumpObjectInfo();
105 void connectToSender();
106 void qobjectConstCast();
107 void uniqConnection();
108 void uniqConnectionPtr();
110 void deleteQObjectWhenDeletingEvent();
112 void isSignalConnected();
113 void qMetaObjectConnect();
114 void qMetaObjectDisconnectOne();
116 void connectByMetaMethods();
117 void connectByMetaMethodSlotInsteadOfSignal();
118 void connectConstructorByMetaMethod();
119 void disconnectByMetaMethod();
120 void disconnectNotSignalMetaMethod();
121 void autoConnectionBehavior();
122 void baseDestroyed();
123 void pointerConnect();
124 void pointerDisconnect();
125 void emitInDefinedOrderPointer();
126 void customTypesPointer();
128 void connectToStaticCxx0x();
129 void connectCxx0xTypeMatching();
130 void connectConvert();
131 void connectWithReference();
132 void connectManyArguments();
133 void returnValue_data();
135 void returnValue2_data();
139 class SenderObject : public QObject
144 SenderObject() : aPublicSlotCalled(0), recursionCount(0) {}
146 void emitSignal1AfterRecursion()
148 if (recursionCount++ < 100)
149 emitSignal1AfterRecursion();
154 void emitSignal1() { emit signal1(); }
155 void emitSignal2() { emit signal2(); }
156 void emitSignal3() { emit signal3(); }
157 void emitSignal4() { emit signal4(); }
164 QT_MOC_COMPAT void signal5();
167 void aPublicSlot() { aPublicSlotCalled++; }
170 Q_INVOKABLE void invoke1(){}
171 Q_SCRIPTABLE void sinvoke1(){}
172 int aPublicSlotCalled;
174 Q_INVOKABLE QT_MOC_COMPAT void invoke2(){}
175 Q_INVOKABLE QT_MOC_COMPAT void invoke2(int){}
176 Q_SCRIPTABLE QT_MOC_COMPAT void sinvoke2(){}
178 Q_INVOKABLE void invoke3(int hinz = 0, int kunz = 0){Q_UNUSED(hinz) Q_UNUSED(kunz)}
179 Q_SCRIPTABLE void sinvoke3(){}
184 class ReceiverObject : public QObject
190 : sequence_slot1( 0 )
191 , sequence_slot2( 0 )
192 , sequence_slot3( 0 )
193 , sequence_slot4( 0 )
217 bool called(int slot)
220 case 1: return sequence_slot1;
221 case 2: return sequence_slot2;
222 case 3: return sequence_slot3;
223 case 4: return sequence_slot4;
224 default: return false;
231 void slot1() { sequence_slot1 = ++sequence; count_slot1++; }
232 void slot2() { sequence_slot2 = ++sequence; count_slot2++; }
233 void slot3() { sequence_slot3 = ++sequence; count_slot3++; }
234 void slot4() { sequence_slot4 = ++sequence; count_slot4++; }
238 int ReceiverObject::sequence = 0;
240 void tst_QObject::initTestCase()
242 const QString testDataDir = QFileInfo(QFINDTESTDATA("signalbug")).absolutePath();
243 QVERIFY2(QDir::setCurrent(testDataDir), qPrintable("Could not chdir to " + testDataDir));
246 void tst_QObject::disconnect()
248 SenderObject *s = new SenderObject;
249 ReceiverObject *r1 = new ReceiverObject;
250 ReceiverObject *r2 = new ReceiverObject;
252 connect( s, SIGNAL( signal1() ), r1, SLOT( slot1() ) );
254 connect( s, SIGNAL( signal2() ), r1, SLOT( slot2() ) );
255 connect( s, SIGNAL( signal3() ), r1, SLOT( slot3() ) );
256 connect( s, SIGNAL( signal4() ), r1, SLOT( slot4() ) );
263 QVERIFY(r1->called(1));
264 QVERIFY(r1->called(2));
265 QVERIFY(r1->called(3));
266 QVERIFY(r1->called(4));
269 // usual disconnect with all parameters given
270 bool ret = QObject::disconnect( s, SIGNAL( signal1() ), r1, SLOT( slot1() ) );
274 QVERIFY(!r1->called(1));
278 ret = QObject::disconnect( s, SIGNAL( signal1() ), r1, SLOT( slot1() ) );
281 // disconnect all signals from s from all slots from r1
282 QObject::disconnect( s, 0, r1, 0 );
288 QVERIFY(!r1->called(2));
289 QVERIFY(!r1->called(3));
290 QVERIFY(!r1->called(4));
293 connect( s, SIGNAL( signal1() ), r1, SLOT( slot1() ) );
294 connect( s, SIGNAL( signal1() ), r1, SLOT( slot2() ) );
295 connect( s, SIGNAL( signal1() ), r1, SLOT( slot3() ) );
296 connect( s, SIGNAL( signal2() ), r1, SLOT( slot4() ) );
298 // disconnect s's signal1() from all slots of r1
299 QObject::disconnect( s, SIGNAL( signal1() ), r1, 0 );
304 QVERIFY(!r1->called(1));
305 QVERIFY(!r1->called(2));
306 QVERIFY(!r1->called(3));
307 QVERIFY(r1->called(4));
309 // make sure all is disconnected again
310 QObject::disconnect( s, 0, r1, 0 );
312 connect( s, SIGNAL( signal1() ), r1, SLOT( slot1() ) );
313 connect( s, SIGNAL( signal1() ), r2, SLOT( slot1() ) );
314 connect( s, SIGNAL( signal2() ), r1, SLOT( slot2() ) );
315 connect( s, SIGNAL( signal2() ), r2, SLOT( slot2() ) );
316 connect( s, SIGNAL( signal3() ), r1, SLOT( slot3() ) );
317 connect( s, SIGNAL( signal3() ), r2, SLOT( slot3() ) );
319 // disconnect signal1() from all receivers
320 QObject::disconnect( s, SIGNAL( signal1() ), 0, 0 );
325 QVERIFY(!r1->called(1));
326 QVERIFY(!r2->called(1));
327 QVERIFY(r1->called(2));
328 QVERIFY(r2->called(2));
329 QVERIFY(r1->called(2));
330 QVERIFY(r2->called(2));
335 // disconnect all signals of s from all receivers
336 QObject::disconnect( s, 0, 0, 0 );
338 QVERIFY(!r1->called(2));
339 QVERIFY(!r2->called(2));
340 QVERIFY(!r1->called(2));
341 QVERIFY(!r2->called(2));
348 class AutoConnectSender : public QObject
353 AutoConnectSender(QObject *parent)
357 void emitSignalNoParams() { emit signalNoParams(); }
358 void emitSignalWithParams(int i) { emit signalWithParams(i); }
359 void emitSignalWithParams(int i, QString string) { emit signalWithParams(i, string); }
360 void emitSignalManyParams(int i1, int i2, int i3, QString string, bool onoff) { emit signalManyParams(i1, i2, i3, string, onoff); }
361 void emitSignalManyParams2(int i1, int i2, int i3, QString string, bool onoff) { emit signalManyParams2(i1, i2, i3, string, onoff); }
362 void emitSignalLoopBack() { emit signalLoopBack(); }
365 void signalNoParams();
366 void signalWithParams(int i);
367 void signalWithParams(int i, QString string);
368 void signalManyParams(int i1, int i2, int i3, QString string, bool onoff);
369 void signalManyParams(int i1, int i2, int i3, QString string, bool onoff, bool);
370 void signalManyParams2(int i1, int i2, int i3, QString string, bool onoff);
371 void signalLoopBack();
374 class AutoConnectReceiver : public QObject
379 AutoConnectReceiver()
383 connect(this, SIGNAL(on_Sender_signalLoopBack()), this, SLOT(slotLoopBack()));
410 bool called(int slot) {
412 case 1: return called_slot1;
413 case 2: return called_slot2;
414 case 3: return called_slot3;
415 case 4: return called_slot4;
416 case 5: return called_slot5;
417 case 6: return called_slot6;
418 case 7: return called_slot7;
419 case 8: return called_slot8;
420 case 9: return called_slot9;
421 case 10: return called_slot10;
422 default: return false;
427 void on_Sender_signalNoParams() { ++called_slot1; }
428 void on_Sender_signalWithParams(int i = 0) { ++called_slot2; Q_UNUSED(i); }
429 void on_Sender_signalWithParams(int i, QString string) { ++called_slot3; Q_UNUSED(i);Q_UNUSED(string); }
430 void on_Sender_signalManyParams() { ++called_slot4; }
431 void on_Sender_signalManyParams(int i1, int i2, int i3, QString string, bool onoff) { ++called_slot5; Q_UNUSED(i1);Q_UNUSED(i2);Q_UNUSED(i3);Q_UNUSED(string);Q_UNUSED(onoff); }
432 void on_Sender_signalManyParams(int i1, int i2, int i3, QString string, bool onoff, bool dummy)
433 { ++called_slot6; Q_UNUSED(i1);Q_UNUSED(i2);Q_UNUSED(i3);Q_UNUSED(string);Q_UNUSED(onoff); Q_UNUSED(dummy);}
434 void on_Sender_signalManyParams2(int i1, int i2, int i3, QString string, bool onoff)
435 { ++called_slot7; Q_UNUSED(i1);Q_UNUSED(i2);Q_UNUSED(i3);Q_UNUSED(string);Q_UNUSED(onoff); }
436 void slotLoopBack() { ++called_slot8; }
439 void o() { ++called_slot9; }
440 void on() { ++called_slot10; }
443 void on_Sender_signalLoopBack();
446 void tst_QObject::connectByName()
448 AutoConnectReceiver receiver;
449 AutoConnectSender sender(&receiver);
450 sender.setObjectName("Sender");
452 QMetaObject::connectSlotsByName(&receiver);
454 sender.emitSignalNoParams();
455 QCOMPARE(receiver.called(1), true);
456 QCOMPARE(receiver.called(2), false);
457 QCOMPARE(receiver.called(3), false);
458 QCOMPARE(receiver.called(4), false);
459 QCOMPARE(receiver.called(5), false);
460 QCOMPARE(receiver.called(6), false);
461 QCOMPARE(receiver.called(7), false);
462 QCOMPARE(receiver.called(8), false);
463 QCOMPARE(receiver.called(9), false);
464 QCOMPARE(receiver.called(10), false);
467 sender.emitSignalWithParams(0);
468 QCOMPARE(receiver.called(1), false);
469 QCOMPARE(receiver.called(2), true);
470 QCOMPARE(receiver.called(3), false);
471 QCOMPARE(receiver.called(4), false);
472 QCOMPARE(receiver.called(5), false);
473 QCOMPARE(receiver.called(6), false);
474 QCOMPARE(receiver.called(7), false);
475 QCOMPARE(receiver.called(8), false);
476 QCOMPARE(receiver.called(9), false);
477 QCOMPARE(receiver.called(10), false);
480 sender.emitSignalWithParams(0, "string");
481 QCOMPARE(receiver.called(1), false);
482 QCOMPARE(receiver.called(2), false);
483 QCOMPARE(receiver.called(3), true);
484 QCOMPARE(receiver.called(4), false);
485 QCOMPARE(receiver.called(5), false);
486 QCOMPARE(receiver.called(6), false);
487 QCOMPARE(receiver.called(7), false);
488 QCOMPARE(receiver.called(8), false);
489 QCOMPARE(receiver.called(9), false);
490 QCOMPARE(receiver.called(10), false);
493 sender.emitSignalManyParams(1, 2, 3, "string", true);
494 QCOMPARE(receiver.called(1), false);
495 QCOMPARE(receiver.called(2), false);
496 QCOMPARE(receiver.called(3), false);
497 QCOMPARE(receiver.called(4), true);
498 QCOMPARE(receiver.called(5), true);
499 QCOMPARE(receiver.called(6), false);
500 QCOMPARE(receiver.called(7), false);
501 QCOMPARE(receiver.called(8), false);
502 QCOMPARE(receiver.called(9), false);
503 QCOMPARE(receiver.called(10), false);
506 sender.emitSignalManyParams2(1, 2, 3, "string", true);
507 QCOMPARE(receiver.called(1), false);
508 QCOMPARE(receiver.called(2), false);
509 QCOMPARE(receiver.called(3), false);
510 QCOMPARE(receiver.called(4), false);
511 QCOMPARE(receiver.called(5), false);
512 QCOMPARE(receiver.called(6), false);
513 QCOMPARE(receiver.called(7), true);
514 QCOMPARE(receiver.called(8), false);
515 QCOMPARE(receiver.called(9), false);
516 QCOMPARE(receiver.called(10), false);
519 sender.emitSignalLoopBack();
520 QCOMPARE(receiver.called(1), false);
521 QCOMPARE(receiver.called(2), false);
522 QCOMPARE(receiver.called(3), false);
523 QCOMPARE(receiver.called(4), false);
524 QCOMPARE(receiver.called(5), false);
525 QCOMPARE(receiver.called(6), false);
526 QCOMPARE(receiver.called(7), false);
527 QCOMPARE(receiver.called(8), true);
528 QCOMPARE(receiver.called(9), false);
529 QCOMPARE(receiver.called(10), false);
533 void tst_QObject::qobject_castTemplate()
536 QVERIFY( !::qobject_cast<QObject*>(o) );
538 o = new SenderObject;
539 QVERIFY( ::qobject_cast<SenderObject*>(o) );
540 QVERIFY( ::qobject_cast<QObject*>(o) );
541 QVERIFY( !::qobject_cast<ReceiverObject*>(o) );
545 void tst_QObject::findChildren()
556 QTimer emptyname(&o);
558 o.setObjectName("o");
559 o1.setObjectName("o1");
560 o2.setObjectName("o2");
561 o11.setObjectName("o11");
562 o12.setObjectName("o12");
563 o111.setObjectName("o111");
564 t1.setObjectName("t1");
565 t121.setObjectName("t121");
566 emptyname.setObjectName("");
570 op = qFindChild<QObject*>(&o, "o1");
572 op = qFindChild<QObject*>(&o, "o2");
574 op = qFindChild<QObject*>(&o, "o11");
576 op = qFindChild<QObject*>(&o, "o12");
578 op = qFindChild<QObject*>(&o, "o111");
580 op = qFindChild<QObject*>(&o, "t1");
581 QCOMPARE(op, static_cast<QObject *>(&t1));
582 op = qFindChild<QObject*>(&o, "t121");
583 QCOMPARE(op, static_cast<QObject *>(&t121));
584 op = qFindChild<QTimer*>(&o, "t1");
585 QCOMPARE(op, static_cast<QObject *>(&t1));
586 op = qFindChild<QTimer*>(&o, "t121");
587 QCOMPARE(op, static_cast<QObject *>(&t121));
588 op = qFindChild<QTimer*>(&o, "o12");
589 QCOMPARE(op, static_cast<QObject *>(0));
590 op = qFindChild<QObject*>(&o, "o");
591 QCOMPARE(op, static_cast<QObject *>(0));
592 op = qFindChild<QObject*>(&o, "harry");
593 QCOMPARE(op, static_cast<QObject *>(0));
594 op = qFindChild<QObject*>(&o, "o1");
600 l = qFindChildren<QObject*>(&o, "o1");
601 QCOMPARE(l.size(), 1);
602 QCOMPARE(l.at(0), &o1);
603 l = qFindChildren<QObject*>(&o, "o2");
604 QCOMPARE(l.size(), 1);
605 QCOMPARE(l.at(0), &o2);
606 l = qFindChildren<QObject*>(&o, "o11");
607 QCOMPARE(l.size(), 1);
608 QCOMPARE(l.at(0), &o11);
609 l = qFindChildren<QObject*>(&o, "o12");
610 QCOMPARE(l.size(), 1);
611 QCOMPARE(l.at(0), &o12);
612 l = qFindChildren<QObject*>(&o, "o111");
613 QCOMPARE(l.size(), 1);
614 QCOMPARE(l.at(0), &o111);
615 l = qFindChildren<QObject*>(&o, "t1");
616 QCOMPARE(l.size(), 1);
617 QCOMPARE(l.at(0), static_cast<QObject *>(&t1));
618 l = qFindChildren<QObject*>(&o, "t121");
619 QCOMPARE(l.size(), 1);
620 QCOMPARE(l.at(0), static_cast<QObject *>(&t121));
621 tl = qFindChildren<QTimer*>(&o, "t1");
622 QCOMPARE(tl.size(), 1);
623 QCOMPARE(tl.at(0), &t1);
624 tl = qFindChildren<QTimer*>(&o, "t121");
625 QCOMPARE(tl.size(), 1);
626 QCOMPARE(tl.at(0), &t121);
627 l = qFindChildren<QObject*>(&o, "o");
628 QCOMPARE(l.size(), 0);
629 l = qFindChildren<QObject*>(&o, "harry");
630 QCOMPARE(l.size(), 0);
631 tl = qFindChildren<QTimer*>(&o, "o12");
632 QCOMPARE(tl.size(), 0);
633 l = qFindChildren<QObject*>(&o, "o1");
634 QCOMPARE(l.size(), 1);
635 QCOMPARE(l.at(0), &o1);
637 l = qFindChildren<QObject*>(&o, QRegExp("o.*"));
638 QCOMPARE(l.size(), 5);
639 QVERIFY(l.contains(&o1));
640 QVERIFY(l.contains(&o2));
641 QVERIFY(l.contains(&o11));
642 QVERIFY(l.contains(&o12));
643 QVERIFY(l.contains(&o111));
644 l = qFindChildren<QObject*>(&o, QRegExp("t.*"));
645 QCOMPARE(l.size(), 2);
646 QVERIFY(l.contains(&t1));
647 QVERIFY(l.contains(&t121));
648 tl = qFindChildren<QTimer*>(&o, QRegExp(".*"));
649 QCOMPARE(tl.size(), 3);
650 QVERIFY(tl.contains(&t1));
651 QVERIFY(tl.contains(&t121));
652 tl = qFindChildren<QTimer*>(&o, QRegExp("o.*"));
653 QCOMPARE(tl.size(), 0);
654 l = qFindChildren<QObject*>(&o, QRegExp("harry"));
655 QCOMPARE(l.size(), 0);
657 // empty and null string check
658 op = qFindChild<QObject*>(&o);
660 op = qFindChild<QObject*>(&o, "");
661 QCOMPARE(op, &unnamed);
662 op = qFindChild<QObject*>(&o, "unnamed");
663 QCOMPARE(op, static_cast<QObject *>(0));
665 l = qFindChildren<QObject*>(&o);
666 QCOMPARE(l.size(), 9);
667 l = qFindChildren<QObject*>(&o, "");
668 QCOMPARE(l.size(), 2);
669 l = qFindChildren<QObject*>(&o, "unnamed");
670 QCOMPARE(l.size(), 0);
672 tl = o.findChildren<QTimer *>("t1");
673 QCOMPARE(tl.size(), 1);
674 QCOMPARE(tl.at(0), &t1);
676 // Find direct child/children
678 op = o.findChild<QObject*>("o1", Qt::FindDirectChildrenOnly);
680 op = o.findChild<QObject*>("o2", Qt::FindDirectChildrenOnly);
682 op = o.findChild<QObject*>("o11", Qt::FindDirectChildrenOnly);
683 QCOMPARE(op, static_cast<QObject *>(0));
684 op = o.findChild<QObject*>("o12", Qt::FindDirectChildrenOnly);
685 QCOMPARE(op, static_cast<QObject *>(0));
686 op = o.findChild<QObject*>("o111", Qt::FindDirectChildrenOnly);
687 QCOMPARE(op, static_cast<QObject *>(0));
688 op = o.findChild<QObject*>("t1", Qt::FindDirectChildrenOnly);
689 QCOMPARE(op, static_cast<QObject *>(&t1));
690 op = o.findChild<QObject*>("t121", Qt::FindDirectChildrenOnly);
691 QCOMPARE(op, static_cast<QObject *>(0));
692 op = o.findChild<QTimer*>("t1", Qt::FindDirectChildrenOnly);
693 QCOMPARE(op, static_cast<QObject *>(&t1));
694 op = o.findChild<QTimer*>("t121", Qt::FindDirectChildrenOnly);
695 QCOMPARE(op, static_cast<QObject *>(0));
696 op = o.findChild<QTimer*>("o12", Qt::FindDirectChildrenOnly);
697 QCOMPARE(op, static_cast<QObject *>(0));
698 op = o.findChild<QObject*>("o", Qt::FindDirectChildrenOnly);
699 QCOMPARE(op, static_cast<QObject *>(0));
700 op = o.findChild<QObject*>("harry", Qt::FindDirectChildrenOnly);
701 QCOMPARE(op, static_cast<QObject *>(0));
702 op = o.findChild<QObject*>("o1", Qt::FindDirectChildrenOnly);
705 l = o.findChildren<QObject*>("o1", Qt::FindDirectChildrenOnly);
706 QCOMPARE(l.size(), 1);
707 QCOMPARE(l.at(0), &o1);
708 l = o.findChildren<QObject*>("o2", Qt::FindDirectChildrenOnly);
709 QCOMPARE(l.size(), 1);
710 QCOMPARE(l.at(0), &o2);
711 l = o.findChildren<QObject*>("o11", Qt::FindDirectChildrenOnly);
712 QCOMPARE(l.size(), 0);
713 l = o.findChildren<QObject*>("o12", Qt::FindDirectChildrenOnly);
714 QCOMPARE(l.size(), 0);
715 l = o.findChildren<QObject*>("o111", Qt::FindDirectChildrenOnly);
716 QCOMPARE(l.size(), 0);
717 l = o.findChildren<QObject*>("t1", Qt::FindDirectChildrenOnly);
718 QCOMPARE(l.size(), 1);
719 QCOMPARE(l.at(0), static_cast<QObject *>(&t1));
720 l = o.findChildren<QObject*>("t121", Qt::FindDirectChildrenOnly);
721 QCOMPARE(l.size(), 0);
722 tl = o.findChildren<QTimer*>("t1", Qt::FindDirectChildrenOnly);
723 QCOMPARE(tl.size(), 1);
724 QCOMPARE(tl.at(0), &t1);
725 tl = o.findChildren<QTimer*>("t121", Qt::FindDirectChildrenOnly);
726 QCOMPARE(tl.size(), 0);
727 l = o.findChildren<QObject*>("o", Qt::FindDirectChildrenOnly);
728 QCOMPARE(l.size(), 0);
729 l = o.findChildren<QObject*>("harry", Qt::FindDirectChildrenOnly);
730 QCOMPARE(l.size(), 0);
731 tl = o.findChildren<QTimer*>("o12", Qt::FindDirectChildrenOnly);
732 QCOMPARE(tl.size(), 0);
733 l = o.findChildren<QObject*>("o1", Qt::FindDirectChildrenOnly);
734 QCOMPARE(l.size(), 1);
735 QCOMPARE(l.at(0), &o1);
737 l = o.findChildren<QObject*>(QRegExp("o.*"), Qt::FindDirectChildrenOnly);
738 QCOMPARE(l.size(), 2);
739 QVERIFY(l.contains(&o1));
740 QVERIFY(l.contains(&o2));
741 l = o.findChildren<QObject*>(QRegExp("t.*"), Qt::FindDirectChildrenOnly);
742 QCOMPARE(l.size(), 1);
743 QVERIFY(l.contains(&t1));
744 tl = o.findChildren<QTimer*>(QRegExp(".*"), Qt::FindDirectChildrenOnly);
745 QCOMPARE(tl.size(), 2);
746 QVERIFY(tl.contains(&t1));
747 tl = o.findChildren<QTimer*>(QRegExp("o.*"), Qt::FindDirectChildrenOnly);
748 QCOMPARE(tl.size(), 0);
749 l = o.findChildren<QObject*>(QRegExp("harry"), Qt::FindDirectChildrenOnly);
750 QCOMPARE(l.size(), 0);
752 // empty and null string check
753 op = o.findChild<QObject*>(QString(), Qt::FindDirectChildrenOnly);
755 op = o.findChild<QObject*>("", Qt::FindDirectChildrenOnly);
756 QCOMPARE(op, &unnamed);
757 op = o.findChild<QObject*>("unnamed", Qt::FindDirectChildrenOnly);
758 QCOMPARE(op, static_cast<QObject *>(0));
760 l = o.findChildren<QObject*>(QString(), Qt::FindDirectChildrenOnly);
761 QCOMPARE(l.size(), 5);
762 l = o.findChildren<QObject*>("", Qt::FindDirectChildrenOnly);
763 QCOMPARE(l.size(), 2);
764 l = o.findChildren<QObject*>("unnamed", Qt::FindDirectChildrenOnly);
765 QCOMPARE(l.size(), 0);
767 tl = o.findChildren<QTimer *>("t1", Qt::FindDirectChildrenOnly);
768 QCOMPARE(tl.size(), 1);
769 QCOMPARE(tl.at(0), &t1);
773 class NotifyObject : public SenderObject, public ReceiverObject
776 NotifyObject() : SenderObject(), ReceiverObject()
783 void connectNotify( const char *signal )
786 nw_signal = QMetaObject::normalizedSignature(signal);
788 void disconnectNotify( const char *signal )
791 nw_signal = QMetaObject::normalizedSignature(signal);
795 void tst_QObject::connectDisconnectNotify_data()
797 QTest::addColumn<QString>("a_signal");
798 QTest::addColumn<QString>("a_slot");
800 QTest::newRow("combo1") << SIGNAL( signal1() ) << SLOT( slot1() );
801 QTest::newRow("combo2") << SIGNAL( signal2(void) ) << SLOT( slot2( ) );
802 QTest::newRow("combo3") << SIGNAL( signal3( ) ) << SLOT( slot3(void) );
803 QTest::newRow("combo4") << SIGNAL( signal4( void ) )<< SLOT( slot4( void ) );
806 void tst_QObject::connectDisconnectNotify()
808 NotifyObject *s = new NotifyObject;
809 NotifyObject *r = new NotifyObject;
811 QFETCH(QString, a_signal);
812 QFETCH(QString, a_slot);
814 // Test connectNotify
815 connect( (SenderObject*)s, a_signal.toLatin1(), (ReceiverObject*)r, a_slot.toLatin1() );
816 QCOMPARE( s->org_signal, s->nw_signal );
817 QCOMPARE( s->org_signal.toLatin1(), QMetaObject::normalizedSignature(a_signal.toLatin1().constData()) );
819 // Test disconnectNotify
820 QObject::disconnect( (SenderObject*)s, a_signal.toLatin1(), (ReceiverObject*)r, a_slot.toLatin1() );
821 QCOMPARE( s->org_signal, s->nw_signal );
822 QCOMPARE( s->org_signal.toLatin1(), QMetaObject::normalizedSignature(a_signal.toLatin1().constData()) );
825 connect( (SenderObject*)s, a_signal.toLatin1(), (ReceiverObject*)r, a_slot.toLatin1() );
826 // Test disconnectNotify for a complete disconnect
827 ((SenderObject*)s)->disconnect((ReceiverObject*)r);
829 // Obtaining meta methods
830 int signalIndx = ((SenderObject*)s)->metaObject()->indexOfSignal(
831 QMetaObject::normalizedSignature(a_signal.toLatin1().constData()+1).constData());
832 int methodIndx = ((ReceiverObject*)r)->metaObject()->indexOfMethod(
833 QMetaObject::normalizedSignature(a_slot.toLatin1().constData()+1).constData());
834 QMetaMethod signal = ((SenderObject*)s)->metaObject()->method(signalIndx);
835 QMetaMethod method = ((ReceiverObject*)r)->metaObject()->method(methodIndx);
837 // Test connectNotify when connecting by QMetaMethod
838 connect( (SenderObject*)s, signal, (ReceiverObject*)r, method );
839 QCOMPARE( s->org_signal, s->nw_signal );
840 QCOMPARE( s->org_signal.toLatin1(), QMetaObject::normalizedSignature(a_signal.toLatin1().constData()) );
842 // Test disconnectNotify when disconnecting by QMetaMethod
843 QObject::disconnect( (SenderObject*)s, signal, (ReceiverObject*)r, method );
844 QCOMPARE( s->org_signal, s->nw_signal );
845 QCOMPARE( s->org_signal.toLatin1(), QMetaObject::normalizedSignature(a_signal.toLatin1().constData()) );
851 class SequenceObject : public ReceiverObject
857 SequenceObject() : next(0) { }
860 void slot1_disconnectThis()
863 disconnect(sender(), SIGNAL(signal1()), this, SLOT(slot1_disconnectThis()));
866 void slot2_reconnectThis()
870 const QObject *s = sender();
871 disconnect(s, SIGNAL(signal1()), this, SLOT(slot2_reconnectThis()));
872 connect(s, SIGNAL(signal1()), this, SLOT(slot2_reconnectThis()));
875 void slot1_disconnectNext()
878 disconnect(sender(), SIGNAL(signal1()), next, SLOT(slot1()));
881 void slot2_reconnectNext()
885 // modify the connection list in 'this'
886 disconnect(sender(), SIGNAL(signal1()), next, SLOT(slot2()));
887 connect(sender(), SIGNAL(signal1()), next, SLOT(slot2()));
889 // modify the sender list in 'this'
890 connect(next, SIGNAL(destroyed()), this, SLOT(deleteLater()));
891 connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(deleteLater()));
892 disconnect(next, SIGNAL(destroyed()), this, SLOT(deleteLater()));
893 disconnect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(deleteLater()));
896 void slot1_deleteNext()
902 void slot2_deleteSender()
909 void tst_QObject::emitInDefinedOrder()
912 ReceiverObject receiver1, receiver2, receiver3, receiver4;
914 connect(&sender, SIGNAL(signal1()), &receiver1, SLOT(slot1()));
915 connect(&sender, SIGNAL(signal1()), &receiver2, SLOT(slot1()));
916 connect(&sender, SIGNAL(signal1()), &receiver3, SLOT(slot1()));
917 connect(&sender, SIGNAL(signal1()), &receiver4, SLOT(slot1()));
918 connect(&sender, SIGNAL(signal1()), &receiver1, SLOT(slot2()));
919 connect(&sender, SIGNAL(signal1()), &receiver2, SLOT(slot2()));
920 connect(&sender, SIGNAL(signal1()), &receiver3, SLOT(slot2()));
921 connect(&sender, SIGNAL(signal1()), &receiver4, SLOT(slot2()));
924 ReceiverObject::sequence = sequence = 0;
925 sender.emitSignal1();
926 QCOMPARE(receiver1.sequence_slot1, ++sequence);
927 QCOMPARE(receiver2.sequence_slot1, ++sequence);
928 QCOMPARE(receiver3.sequence_slot1, ++sequence);
929 QCOMPARE(receiver4.sequence_slot1, ++sequence);
930 QCOMPARE(receiver1.sequence_slot2, ++sequence);
931 QCOMPARE(receiver2.sequence_slot2, ++sequence);
932 QCOMPARE(receiver3.sequence_slot2, ++sequence);
933 QCOMPARE(receiver4.sequence_slot2, ++sequence);
935 QObject::disconnect(&sender, SIGNAL(signal1()), &receiver2, SLOT(slot1()));
936 connect(&sender, SIGNAL(signal1()), &receiver2, SLOT(slot1()));
938 ReceiverObject::sequence = sequence = 0;
939 sender.emitSignal1();
940 QCOMPARE(receiver1.sequence_slot1, ++sequence);
941 QCOMPARE(receiver3.sequence_slot1, ++sequence);
942 QCOMPARE(receiver4.sequence_slot1, ++sequence);
943 QCOMPARE(receiver1.sequence_slot2, ++sequence);
944 QCOMPARE(receiver2.sequence_slot2, ++sequence);
945 QCOMPARE(receiver3.sequence_slot2, ++sequence);
946 QCOMPARE(receiver4.sequence_slot2, ++sequence);
947 QCOMPARE(receiver2.sequence_slot1, ++sequence);
949 QObject::disconnect(&sender, SIGNAL(signal1()), &receiver1, SLOT(slot1()));
950 connect(&sender, SIGNAL(signal1()), &receiver1, SLOT(slot1()));
952 ReceiverObject::sequence = sequence = 0;
953 sender.emitSignal1();
954 QCOMPARE(receiver3.sequence_slot1, ++sequence);
955 QCOMPARE(receiver4.sequence_slot1, ++sequence);
956 QCOMPARE(receiver1.sequence_slot2, ++sequence);
957 QCOMPARE(receiver2.sequence_slot2, ++sequence);
958 QCOMPARE(receiver3.sequence_slot2, ++sequence);
959 QCOMPARE(receiver4.sequence_slot2, ++sequence);
960 QCOMPARE(receiver2.sequence_slot1, ++sequence);
961 QCOMPARE(receiver1.sequence_slot1, ++sequence);
963 // ensure emission order even if the connections change during emission
964 SenderObject *sender2 = new SenderObject;
965 SequenceObject seq1, seq2, *seq3 = new SequenceObject, seq4;
971 connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot1_disconnectThis()));
972 connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot1_disconnectNext()));
973 connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot1()));
974 connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot1()));
975 connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot2_reconnectThis()));
976 connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot2_reconnectNext()));
977 connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot2()));
978 connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot2()));
980 SequenceObject::sequence = sequence = 0;
981 sender2->emitSignal1();
982 QVERIFY(seq1.called(1));
983 QVERIFY(seq2.called(1));
984 QVERIFY(!seq3->called(1));
985 QVERIFY(seq4.called(1));
986 QVERIFY(seq1.called(2));
987 QVERIFY(seq2.called(2));
988 QVERIFY(!seq3->called(2));
989 QVERIFY(seq4.called(2));
990 QCOMPARE(seq1.sequence_slot1, ++sequence);
991 QCOMPARE(seq2.sequence_slot1, ++sequence);
992 QCOMPARE(seq4.sequence_slot1, ++sequence);
993 QCOMPARE(seq1.sequence_slot2, ++sequence);
994 QCOMPARE(seq2.sequence_slot2, ++sequence);
995 QCOMPARE(seq4.sequence_slot2, ++sequence);
997 QObject::disconnect(sender2, 0, &seq1, 0);
998 QObject::disconnect(sender2, 0, &seq2, 0);
999 QObject::disconnect(sender2, 0, seq3, 0);
1000 QObject::disconnect(sender2, 0, &seq4, 0);
1007 connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot2_reconnectThis()));
1008 connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot2_reconnectNext()));
1009 connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot2()));
1010 connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot2()));
1011 connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot1_disconnectThis()));
1012 connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot1_disconnectNext()));
1013 connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot1()));
1014 connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot1()));
1016 SequenceObject::sequence = sequence = 0;
1017 sender2->emitSignal1();
1018 QVERIFY(seq1.called(2));
1019 QVERIFY(seq2.called(2));
1020 QVERIFY(!seq3->called(2));
1021 QVERIFY(seq4.called(2));
1022 QVERIFY(seq1.called(1));
1023 QVERIFY(seq2.called(1));
1024 QVERIFY(!seq3->called(1));
1025 QVERIFY(seq4.called(1));
1026 QCOMPARE(seq1.sequence_slot2, ++sequence);
1027 QCOMPARE(seq2.sequence_slot2, ++sequence);
1028 QCOMPARE(seq4.sequence_slot2, ++sequence);
1029 QCOMPARE(seq1.sequence_slot1, ++sequence);
1030 QCOMPARE(seq2.sequence_slot1, ++sequence);
1031 QCOMPARE(seq4.sequence_slot1, ++sequence);
1033 QObject::disconnect(sender2, 0, &seq1, 0);
1034 QObject::disconnect(sender2, 0, &seq2, 0);
1035 QObject::disconnect(sender2, 0, seq3, 0);
1036 QObject::disconnect(sender2, 0, &seq4, 0);
1043 connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot1()));
1044 connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot1_disconnectNext()));
1045 connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot1()));
1046 connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot1()));
1047 connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot2()));
1048 connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot2_reconnectNext()));
1049 connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot2()));
1050 connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot2()));
1052 SequenceObject::sequence = sequence = 0;
1053 sender2->emitSignal1();
1054 QVERIFY(seq1.called(1));
1055 QVERIFY(seq2.called(1));
1056 QVERIFY(!seq3->called(1));
1057 QVERIFY(seq4.called(1));
1058 QVERIFY(seq1.called(2));
1059 QVERIFY(seq2.called(2));
1060 QVERIFY(!seq3->called(2));
1061 QVERIFY(seq4.called(2));
1062 QCOMPARE(seq1.sequence_slot1, ++sequence);
1063 QCOMPARE(seq2.sequence_slot1, ++sequence);
1064 QCOMPARE(seq4.sequence_slot1, ++sequence);
1065 QCOMPARE(seq1.sequence_slot2, ++sequence);
1066 QCOMPARE(seq2.sequence_slot2, ++sequence);
1067 QCOMPARE(seq4.sequence_slot2, ++sequence);
1069 // ensure emission order even if objects are destroyed during emission
1070 QObject::disconnect(sender2, 0, &seq1, 0);
1071 QObject::disconnect(sender2, 0, &seq2, 0);
1072 QObject::disconnect(sender2, 0, seq3, 0);
1073 QObject::disconnect(sender2, 0, &seq4, 0);
1079 connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot1()));
1080 connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot1_deleteNext()));
1081 connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot1()));
1082 connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot1()));
1083 connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot2()));
1084 connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot2_deleteSender()));
1085 connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot2()));
1086 connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot2()));
1088 QPointer<SenderObject> psender = sender2;
1089 QPointer<SequenceObject> pseq3 = seq3;
1091 SequenceObject::sequence = sequence = 0;
1092 sender2->emitSignal1();
1093 QCOMPARE(static_cast<QObject *>(psender), static_cast<QObject *>(0));
1094 QCOMPARE(static_cast<QObject *>(pseq3), static_cast<QObject *>(0));
1095 QVERIFY(seq1.called(1));
1096 QVERIFY(seq2.called(1));
1097 QVERIFY(seq4.called(1));
1098 QVERIFY(seq1.called(2));
1099 QVERIFY(seq2.called(2));
1100 QVERIFY(!seq4.called(2));
1101 QCOMPARE(seq1.sequence_slot1, ++sequence);
1102 QCOMPARE(seq2.sequence_slot1, ++sequence);
1103 QCOMPARE(seq4.sequence_slot1, ++sequence);
1104 QCOMPARE(seq1.sequence_slot2, ++sequence);
1105 QCOMPARE(seq2.sequence_slot2, ++sequence);
1107 QPointer<SenderObject> psender3 = new SenderObject;
1108 connect(psender3, SIGNAL(signal1()), psender3, SIGNAL(signal2()));
1109 connect(psender3, SIGNAL(signal2()), &seq1, SLOT(slot2_deleteSender()));
1110 psender3->emitSignal1();
1114 static int instanceCount = 0;
1116 struct CheckInstanceCount
1119 CheckInstanceCount() : saved(instanceCount) {}
1120 ~CheckInstanceCount() { QCOMPARE(saved, instanceCount); }
1126 CustomType(int l1 = 0, int l2 = 0, int l3 = 0): i1(l1), i2(l2), i3(l3)
1127 { ++instanceCount; }
1128 CustomType(const CustomType &other): i1(other.i1), i2(other.i2), i3(other.i3)
1129 { ++instanceCount; }
1130 ~CustomType() { --instanceCount; }
1133 int value() { return i1 + i2 + i3; }
1136 Q_DECLARE_METATYPE(CustomType*)
1137 Q_DECLARE_METATYPE(CustomType)
1139 class QCustomTypeChecker: public QObject
1144 QCustomTypeChecker(QObject *parent = 0): QObject(parent) {}
1145 void doEmit(CustomType ct)
1146 { emit signal1(ct); }
1149 void slot1(CustomType ct);
1152 void signal1(CustomType ct);
1155 CustomType received;
1158 void QCustomTypeChecker::slot1(CustomType ct)
1162 void tst_QObject::customTypes()
1165 CustomType t1(1, 2, 3);
1166 CustomType t2(2, 3, 4);
1169 QCustomTypeChecker checker;
1170 QCOMPARE(instanceCount, 4);
1172 connect(&checker, SIGNAL(signal1(CustomType)), &checker, SLOT(slot1(CustomType)),
1173 Qt::DirectConnection);
1174 QCOMPARE(checker.received.value(), 0);
1176 QCOMPARE(checker.received.value(), t1.value());
1177 checker.received = t0;
1179 int idx = qRegisterMetaType<CustomType>("CustomType");
1180 QCOMPARE(QMetaType::type("CustomType"), idx);
1182 checker.disconnect();
1183 connect(&checker, SIGNAL(signal1(CustomType)), &checker, SLOT(slot1(CustomType)),
1184 Qt::QueuedConnection);
1185 QCOMPARE(instanceCount, 4);
1187 QCOMPARE(instanceCount, 5);
1188 QCOMPARE(checker.received.value(), t0.value());
1190 QCoreApplication::processEvents();
1191 QCOMPARE(checker.received.value(), t2.value());
1192 QCOMPARE(instanceCount, 4);
1194 QVERIFY(QMetaType::isRegistered(idx));
1195 QCOMPARE(qRegisterMetaType<CustomType>("CustomType"), idx);
1196 QCOMPARE(QMetaType::type("CustomType"), idx);
1197 QVERIFY(QMetaType::isRegistered(idx));
1199 QCOMPARE(instanceCount, 3);
1202 QDataStream &operator<<(QDataStream &stream, const CustomType &ct)
1204 stream << ct.i1 << ct.i2 << ct.i3;
1208 QDataStream &operator>>(QDataStream &stream, CustomType &ct)
1216 void tst_QObject::streamCustomTypes()
1220 int idx = qRegisterMetaType<CustomType>("CustomType");
1221 qRegisterMetaTypeStreamOperators<CustomType>("CustomType");
1224 CustomType t1(1, 2, 3);
1225 QCOMPARE(instanceCount, 1);
1226 QDataStream stream(&ba, (QIODevice::OpenMode)QIODevice::WriteOnly);
1227 QMetaType::save(stream, idx, &t1);
1230 QCOMPARE(instanceCount, 0);
1234 QCOMPARE(instanceCount, 1);
1235 QDataStream stream(&ba, (QIODevice::OpenMode)QIODevice::ReadOnly);
1236 QMetaType::load(stream, idx, &t2);
1237 QCOMPARE(instanceCount, 1);
1242 QCOMPARE(instanceCount, 0);
1245 typedef QString CustomString;
1247 class PropertyObject : public QObject
1250 Q_ENUMS(Alpha Priority)
1252 Q_PROPERTY(Alpha alpha READ alpha WRITE setAlpha)
1253 Q_PROPERTY(Priority priority READ priority WRITE setPriority)
1254 Q_PROPERTY(int number READ number WRITE setNumber)
1255 Q_PROPERTY(QString string READ string WRITE setString)
1256 Q_PROPERTY(QVariant variant READ variant WRITE setVariant)
1257 Q_PROPERTY(CustomType* custom READ custom WRITE setCustom)
1258 Q_PROPERTY(float myFloat READ myFloat WRITE setMyFloat)
1259 Q_PROPERTY(qreal myQReal READ myQReal WRITE setMyQReal)
1260 Q_PROPERTY(CustomString customString READ customString WRITE setCustomString )
1269 enum Priority { High, Low, VeryHigh, VeryLow };
1272 : m_alpha(Alpha0), m_priority(High), m_number(0), m_custom(0), m_float(42)
1275 Alpha alpha() const { return m_alpha; }
1276 void setAlpha(Alpha alpha) { m_alpha = alpha; }
1278 Priority priority() const { return m_priority; }
1279 void setPriority(Priority priority) { m_priority = priority; }
1281 int number() const { return m_number; }
1282 void setNumber(int number) { m_number = number; }
1284 QString string() const { return m_string; }
1285 void setString(const QString &string) { m_string = string; }
1287 QVariant variant() const { return m_variant; }
1288 void setVariant(const QVariant &variant) { m_variant = variant; }
1290 CustomType *custom() const { return m_custom; }
1291 void setCustom(CustomType *custom) { m_custom = custom; }
1293 void setMyFloat(float value) { m_float = value; }
1294 inline float myFloat() const { return m_float; }
1296 void setMyQReal(qreal value) { m_qreal = value; }
1297 qreal myQReal() const { return m_qreal; }
1299 CustomString customString() const { return m_customString; }
1300 void setCustomString(const QString &string) { m_customString = string; }
1304 Priority m_priority;
1308 CustomType *m_custom;
1311 CustomString m_customString;
1314 Q_DECLARE_METATYPE(PropertyObject::Priority)
1316 void tst_QObject::threadSignalEmissionCrash()
1318 #if defined(Q_OS_WINCE)
1319 int loopCount = 100;
1321 int loopCount = 1000;
1323 for (int i = 0; i < loopCount; ++i) {
1325 socket.connectToHost("localhost", 80);
1329 class TestThread : public QThread
1335 *object = new QObject;
1336 *child = new QObject(*object);
1343 QObject **object, **child;
1345 QWaitCondition cond;
1348 void tst_QObject::thread()
1350 QThread *currentThread = QThread::currentThread();
1351 // the current thread is the same as the QApplication
1352 // thread... see tst_QApplication::thread()
1356 // thread affinity for objects with no parent should be the
1358 QVERIFY(object.thread() != 0);
1359 QCOMPARE(object.thread(), currentThread);
1360 // children inherit their parent's thread
1361 QObject child(&object);
1362 QCOMPARE(child.thread(), object.thread());
1365 QObject *object = 0;
1370 QVERIFY(thr.thread() != 0);
1371 QCOMPARE(thr.thread(), currentThread);
1373 thr.object = &object;
1378 thr.cond.wait(&thr.mutex);
1380 // thread affinity for an object with no parent should be the
1381 // thread in which the object was created
1382 QCOMPARE(object->thread(), (QThread *)&thr);
1383 // children inherit their parent's thread
1384 QCOMPARE(child->thread(), object->thread());
1390 // even though the thread is no longer running, the affinity
1391 // should not change
1392 QCOMPARE(object->thread(), (QThread *)&thr);
1393 QCOMPARE(child->thread(), object->thread());
1396 // the thread has been destroyed, thread affinity should
1397 // automatically reset to no thread
1398 QCOMPARE(object->thread(), (QThread *)0);
1399 QCOMPARE(child->thread(), object->thread());
1404 class MoveToThreadObject : public QObject
1408 QThread *timerEventThread;
1409 QThread *customEventThread;
1410 QThread *slotThread;
1412 MoveToThreadObject(QObject *parent = 0)
1413 : QObject(parent), timerEventThread(0), customEventThread(0), slotThread(0)
1416 void customEvent(QEvent *)
1418 if (customEventThread)
1419 qFatal("%s: customEventThread should be null", Q_FUNC_INFO);
1420 customEventThread = QThread::currentThread();
1424 void timerEvent(QTimerEvent *)
1426 if (timerEventThread)
1427 qFatal("%s: timerEventThread should be null", Q_FUNC_INFO);
1428 timerEventThread = QThread::currentThread();
1436 qFatal("%s: slotThread should be null", Q_FUNC_INFO);
1437 slotThread = QThread::currentThread();
1445 class MoveToThreadThread : public QThread
1448 ~MoveToThreadThread()
1457 QEventLoop eventLoop;
1458 connect(this, SIGNAL(started()), &eventLoop, SLOT(quit()), Qt::QueuedConnection);
1460 // wait for thread to start
1461 (void) eventLoop.exec();
1467 void tst_QObject::thread0()
1469 QObject *object = new QObject;
1470 object->moveToThread(0);
1471 QObject *child = new QObject(object);
1472 QCOMPARE(child->parent(), object);
1473 QCOMPARE(child->thread(), (QThread *)0);
1476 // We don't support moving children into a parent that has no thread
1478 QObject *child2 = new QObject;
1479 child2->moveToThread(0);
1480 child2->setParent(object);
1481 QCOMPARE(child2->parent(), object);
1482 QCOMPARE(child2->thread(), (QThread *)0);
1488 void tst_QObject::moveToThread()
1490 QThread *currentThread = QThread::currentThread();
1493 QObject *object = new QObject;
1494 QObject *child = new QObject(object);
1495 QCOMPARE(object->thread(), currentThread);
1496 QCOMPARE(child->thread(), currentThread);
1497 object->moveToThread(0);
1498 QCOMPARE(object->thread(), (QThread *)0);
1499 QCOMPARE(child->thread(), (QThread *)0);
1500 object->moveToThread(currentThread);
1501 QCOMPARE(object->thread(), currentThread);
1502 QCOMPARE(child->thread(), currentThread);
1503 object->moveToThread(0);
1504 QCOMPARE(object->thread(), (QThread *)0);
1505 QCOMPARE(child->thread(), (QThread *)0);
1506 // can delete an object with no thread anywhere
1511 MoveToThreadThread thread;
1514 QObject *object = new QObject;
1515 QObject *child = new QObject(object);
1516 QPointer<QObject> opointer = object;
1517 QPointer<QObject> cpointer = object;
1519 QCOMPARE(object->thread(), currentThread);
1520 QCOMPARE(child->thread(), currentThread);
1521 object->moveToThread(&thread);
1522 QCOMPARE(object->thread(), (QThread *)&thread);
1523 QCOMPARE(child->thread(), (QThread *)&thread);
1525 connect(object, SIGNAL(destroyed()), &thread, SLOT(quit()), Qt::DirectConnection);
1526 QMetaObject::invokeMethod(object, "deleteLater", Qt::QueuedConnection);
1529 QVERIFY(opointer == 0);
1530 QVERIFY(cpointer == 0);
1534 // make sure posted events are moved with the object
1535 MoveToThreadThread thread;
1538 MoveToThreadObject *object = new MoveToThreadObject;
1539 MoveToThreadObject *child = new MoveToThreadObject(object);
1541 connect(object, SIGNAL(theSignal()), &thread, SLOT(quit()), Qt::DirectConnection);
1542 QCoreApplication::postEvent(child, new QEvent(QEvent::User));
1543 QCoreApplication::postEvent(object, new QEvent(QEvent::User));
1545 QCOMPARE(object->thread(), currentThread);
1546 QCOMPARE(child->thread(), currentThread);
1547 object->moveToThread(&thread);
1548 QCOMPARE(object->thread(), (QThread *)&thread);
1549 QCOMPARE(child->thread(), (QThread *)&thread);
1553 QCOMPARE(object->customEventThread, (QThread *)&thread);
1554 QCOMPARE(child->customEventThread, (QThread *)&thread);
1557 connect(object, SIGNAL(destroyed()), &thread, SLOT(quit()), Qt::DirectConnection);
1558 QMetaObject::invokeMethod(object, "deleteLater", Qt::QueuedConnection);
1563 // make sure timers are moved with the object
1564 MoveToThreadThread thread;
1567 MoveToThreadObject *object = new MoveToThreadObject;
1568 MoveToThreadObject *child = new MoveToThreadObject(object);
1570 connect(object, SIGNAL(theSignal()), &thread, SLOT(quit()), Qt::DirectConnection);
1572 child->startTimer(90);
1573 object->startTimer(100);
1575 QCOMPARE(object->thread(), currentThread);
1576 QCOMPARE(child->thread(), currentThread);
1577 object->moveToThread(&thread);
1578 QCOMPARE(object->thread(), (QThread *)&thread);
1579 QCOMPARE(child->thread(), (QThread *)&thread);
1583 QCOMPARE(object->timerEventThread, (QThread *)&thread);
1584 QCOMPARE(child->timerEventThread, (QThread *)&thread);
1587 connect(object, SIGNAL(destroyed()), &thread, SLOT(quit()), Qt::DirectConnection);
1588 QMetaObject::invokeMethod(object, "deleteLater", Qt::QueuedConnection);
1593 // make sure socket notifiers are moved with the object
1594 MoveToThreadThread thread;
1598 QVERIFY(server.listen(QHostAddress::LocalHost, 0));
1599 QTcpSocket *socket = new QTcpSocket;
1600 MoveToThreadObject *child = new MoveToThreadObject(socket);
1601 connect(socket, SIGNAL(disconnected()), child, SLOT(theSlot()), Qt::DirectConnection);
1602 connect(child, SIGNAL(theSignal()), &thread, SLOT(quit()), Qt::DirectConnection);
1604 socket->connectToHost(server.serverAddress(), server.serverPort());
1606 QVERIFY(server.waitForNewConnection(1000));
1607 QTcpSocket *serverSocket = server.nextPendingConnection();
1608 QVERIFY(serverSocket);
1610 socket->waitForConnected();
1612 QCOMPARE(socket->thread(), currentThread);
1613 socket->moveToThread(&thread);
1614 QCOMPARE(socket->thread(), (QThread *)&thread);
1616 serverSocket->close();
1618 QVERIFY(thread.wait(10000));
1620 QCOMPARE(child->slotThread, (QThread *)&thread);
1623 connect(socket, SIGNAL(destroyed()), &thread, SLOT(quit()), Qt::DirectConnection);
1624 QMetaObject::invokeMethod(socket, "deleteLater", Qt::QueuedConnection);
1630 void tst_QObject::property()
1632 PropertyObject object;
1633 const QMetaObject *mo = object.metaObject();
1634 QMetaProperty property;
1637 QVERIFY(mo->indexOfProperty("alpha") != -1);
1638 property = mo->property(mo->indexOfProperty("alpha"));
1639 QVERIFY(property.isEnumType());
1640 QCOMPARE(property.typeName(), "Alpha");
1641 QCOMPARE(property.type(), QVariant::Int);
1643 QVariant var = object.property("alpha");
1644 QVERIFY(!var.isNull());
1645 QCOMPARE(var.toInt(), int(PropertyObject::Alpha0));
1646 object.setAlpha(PropertyObject::Alpha1);
1647 QCOMPARE(object.property("alpha").toInt(), int(PropertyObject::Alpha1));
1648 QVERIFY(object.setProperty("alpha", PropertyObject::Alpha2));
1649 QCOMPARE(object.property("alpha").toInt(), int(PropertyObject::Alpha2));
1650 QVERIFY(object.setProperty("alpha", "Alpha1"));
1651 QCOMPARE(object.property("alpha").toInt(), int(PropertyObject::Alpha1));
1652 QVERIFY(!object.setProperty("alpha", QVariant()));
1654 QVERIFY(mo->indexOfProperty("number") != -1);
1655 QCOMPARE(object.property("number").toInt(), 0);
1656 object.setNumber(24);
1657 QCOMPARE(object.property("number"), QVariant(24));
1658 QVERIFY(object.setProperty("number", 12));
1659 QCOMPARE(object.property("number"), QVariant(12));
1660 QVERIFY(object.setProperty("number", "42"));
1661 QCOMPARE(object.property("number"), QVariant(42));
1663 QVERIFY(mo->indexOfProperty("string") != -1);
1664 QCOMPARE(object.property("string").toString(), QString());
1665 object.setString("String1");
1666 QCOMPARE(object.property("string"), QVariant("String1"));
1667 QVERIFY(object.setProperty("string", "String2"));
1668 QCOMPARE(object.property("string"), QVariant("String2"));
1669 QVERIFY(!object.setProperty("string", QVariant()));
1671 const int idx = mo->indexOfProperty("variant");
1673 QVERIFY(mo->property(idx).type() == QVariant::LastType);
1674 QCOMPARE(object.property("variant"), QVariant());
1675 QVariant variant1(42);
1676 QVariant variant2("string");
1677 object.setVariant(variant1);
1678 QCOMPARE(object.property("variant"), variant1);
1679 QVERIFY(object.setProperty("variant", variant2));
1680 QCOMPARE(object.variant(), QVariant(variant2));
1681 QCOMPARE(object.property("variant"), variant2);
1682 QVERIFY(object.setProperty("variant", QVariant()));
1683 QCOMPARE(object.property("variant"), QVariant());
1685 QVERIFY(mo->indexOfProperty("custom") != -1);
1686 property = mo->property(mo->indexOfProperty("custom"));
1687 QVERIFY(property.isValid());
1688 QVERIFY(property.isWritable());
1689 QVERIFY(!property.isEnumType());
1690 QCOMPARE(property.typeName(), "CustomType*");
1691 QCOMPARE(property.type(), QVariant::UserType);
1693 CustomType *customPointer = 0;
1694 QVariant customVariant = object.property("custom");
1695 customPointer = qVariantValue<CustomType *>(customVariant);
1696 QCOMPARE(customPointer, object.custom());
1699 customPointer = &custom;
1700 qVariantSetValue(customVariant, customPointer);
1702 property = mo->property(mo->indexOfProperty("custom"));
1703 QVERIFY(property.isWritable());
1704 QCOMPARE(property.typeName(), "CustomType*");
1705 QCOMPARE(property.type(), QVariant::UserType);
1707 QVERIFY(object.setProperty("custom", customVariant));
1708 QCOMPARE(object.custom(), customPointer);
1710 customVariant = object.property("custom");
1711 customPointer = qVariantValue<CustomType *>(customVariant);
1712 QCOMPARE(object.custom(), customPointer);
1714 // this enum property has a meta type, but it's not yet registered, so we know this fails
1715 QVERIFY(mo->indexOfProperty("priority") != -1);
1716 property = mo->property(mo->indexOfProperty("priority"));
1717 QVERIFY(property.isEnumType());
1718 QCOMPARE(property.typeName(), "Priority");
1719 QCOMPARE(property.type(), QVariant::Int);
1721 var = object.property("priority");
1722 QVERIFY(!var.isNull());
1723 QCOMPARE(var.toInt(), int(PropertyObject::High));
1724 object.setPriority(PropertyObject::Low);
1725 QCOMPARE(object.property("priority").toInt(), int(PropertyObject::Low));
1726 QVERIFY(object.setProperty("priority", PropertyObject::VeryHigh));
1727 QCOMPARE(object.property("priority").toInt(), int(PropertyObject::VeryHigh));
1728 QVERIFY(object.setProperty("priority", "High"));
1729 QCOMPARE(object.property("priority").toInt(), int(PropertyObject::High));
1730 QVERIFY(!object.setProperty("priority", QVariant()));
1732 // now it's registered, so it works as expected
1733 int priorityMetaTypeId = qRegisterMetaType<PropertyObject::Priority>("PropertyObject::Priority");
1735 QVERIFY(mo->indexOfProperty("priority") != -1);
1736 property = mo->property(mo->indexOfProperty("priority"));
1737 QVERIFY(property.isEnumType());
1738 QCOMPARE(property.typeName(), "Priority");
1739 QCOMPARE(property.type(), QVariant::UserType);
1740 QCOMPARE(property.userType(), priorityMetaTypeId);
1742 var = object.property("priority");
1743 QVERIFY(!var.isNull());
1744 QVERIFY(qVariantCanConvert<PropertyObject::Priority>(var));
1745 QCOMPARE(qVariantValue<PropertyObject::Priority>(var), PropertyObject::High);
1746 object.setPriority(PropertyObject::Low);
1747 QCOMPARE(qVariantValue<PropertyObject::Priority>(object.property("priority")), PropertyObject::Low);
1748 QVERIFY(object.setProperty("priority", PropertyObject::VeryHigh));
1749 QCOMPARE(qVariantValue<PropertyObject::Priority>(object.property("priority")), PropertyObject::VeryHigh);
1750 QVERIFY(object.setProperty("priority", "High"));
1751 QCOMPARE(qVariantValue<PropertyObject::Priority>(object.property("priority")), PropertyObject::High);
1752 QVERIFY(!object.setProperty("priority", QVariant()));
1754 var = object.property("priority");
1755 QCOMPARE(qVariantValue<PropertyObject::Priority>(var), PropertyObject::High);
1756 object.setPriority(PropertyObject::Low);
1757 QCOMPARE(qVariantValue<PropertyObject::Priority>(object.property("priority")), PropertyObject::Low);
1758 object.setProperty("priority", var);
1759 QCOMPARE(qVariantValue<PropertyObject::Priority>(object.property("priority")), PropertyObject::High);
1761 qRegisterMetaType<CustomString>("CustomString");
1762 QVERIFY(mo->indexOfProperty("customString") != -1);
1763 QCOMPARE(object.property("customString").toString(), QString());
1764 object.setCustomString("String1");
1765 QCOMPARE(object.property("customString"), QVariant("String1"));
1766 QVERIFY(object.setProperty("customString", "String2"));
1767 QCOMPARE(object.property("customString"), QVariant("String2"));
1768 QVERIFY(!object.setProperty("customString", QVariant()));
1771 void tst_QObject::metamethod()
1774 const QMetaObject *mobj = obj.metaObject();
1777 m = mobj->method(mobj->indexOfMethod("invoke1()"));
1778 QVERIFY(QByteArray(m.signature()) == "invoke1()");
1779 QVERIFY(m.methodType() == QMetaMethod::Method);
1780 QVERIFY(m.access() == QMetaMethod::Public);
1781 QVERIFY(!(m.attributes() & QMetaMethod::Scriptable));
1782 QVERIFY(!(m.attributes() & QMetaMethod::Compatibility));
1784 m = mobj->method(mobj->indexOfMethod("sinvoke1()"));
1785 QVERIFY(QByteArray(m.signature()) == "sinvoke1()");
1786 QVERIFY(m.methodType() == QMetaMethod::Method);
1787 QVERIFY(m.access() == QMetaMethod::Public);
1788 QVERIFY((m.attributes() & QMetaMethod::Scriptable));
1789 QVERIFY(!(m.attributes() & QMetaMethod::Compatibility));
1791 m = mobj->method(mobj->indexOfMethod("invoke2()"));
1792 QVERIFY(QByteArray(m.signature()) == "invoke2()");
1793 QVERIFY(m.methodType() == QMetaMethod::Method);
1794 QVERIFY(m.access() == QMetaMethod::Protected);
1795 QVERIFY(!(m.attributes() & QMetaMethod::Scriptable));
1796 QVERIFY((m.attributes() & QMetaMethod::Compatibility));
1798 m = mobj->method(mobj->indexOfMethod("sinvoke2()"));
1799 QVERIFY(QByteArray(m.signature()) == "sinvoke2()");
1800 QVERIFY(m.methodType() == QMetaMethod::Method);
1801 QVERIFY(m.access() == QMetaMethod::Protected);
1802 QVERIFY((m.attributes() & QMetaMethod::Scriptable));
1803 QVERIFY((m.attributes() & QMetaMethod::Compatibility));
1805 m = mobj->method(mobj->indexOfMethod("invoke3()"));
1806 QVERIFY(QByteArray(m.signature()) == "invoke3()");
1807 QVERIFY(m.methodType() == QMetaMethod::Method);
1808 QVERIFY(m.access() == QMetaMethod::Private);
1809 QVERIFY(!(m.attributes() & QMetaMethod::Scriptable));
1810 QVERIFY(!(m.attributes() & QMetaMethod::Compatibility));
1812 m = mobj->method(mobj->indexOfMethod("sinvoke3()"));
1813 QVERIFY(QByteArray(m.signature()) == "sinvoke3()");
1814 QVERIFY(m.methodType() == QMetaMethod::Method);
1815 QVERIFY(m.access() == QMetaMethod::Private);
1816 QVERIFY((m.attributes() & QMetaMethod::Scriptable));
1817 QVERIFY(!(m.attributes() & QMetaMethod::Compatibility));
1819 m = mobj->method(mobj->indexOfMethod("signal5()"));
1820 QVERIFY(QByteArray(m.signature()) == "signal5()");
1821 QVERIFY(m.methodType() == QMetaMethod::Signal);
1822 QVERIFY(m.access() == QMetaMethod::Protected);
1823 QVERIFY(!(m.attributes() & QMetaMethod::Scriptable));
1824 QVERIFY((m.attributes() & QMetaMethod::Compatibility));
1826 m = mobj->method(mobj->indexOfMethod("aPublicSlot()"));
1827 QVERIFY(QByteArray(m.signature()) == "aPublicSlot()");
1828 QVERIFY(m.methodType() == QMetaMethod::Slot);
1829 QVERIFY(m.access() == QMetaMethod::Public);
1830 QVERIFY(!(m.attributes() & QMetaMethod::Scriptable));
1831 QVERIFY(!(m.attributes() & QMetaMethod::Compatibility));
1833 m = mobj->method(mobj->indexOfMethod("invoke1()"));
1834 QCOMPARE(m.parameterNames().count(), 0);
1835 QCOMPARE(m.parameterTypes().count(), 0);
1837 m = mobj->method(mobj->indexOfMethod("invoke2(int)"));
1838 QCOMPARE(m.parameterNames().count(), 1);
1839 QCOMPARE(m.parameterTypes().count(), 1);
1840 QCOMPARE(m.parameterTypes().at(0), QByteArray("int"));
1841 QVERIFY(m.parameterNames().at(0).isEmpty());
1843 m = mobj->method(mobj->indexOfMethod("invoke3(int,int)"));
1844 QCOMPARE(m.parameterNames().count(), 2);
1845 QCOMPARE(m.parameterTypes().count(), 2);
1846 QCOMPARE(m.parameterTypes().at(0), QByteArray("int"));
1847 QCOMPARE(m.parameterNames().at(0), QByteArray("hinz"));
1848 QCOMPARE(m.parameterTypes().at(1), QByteArray("int"));
1849 QCOMPARE(m.parameterNames().at(1), QByteArray("kunz"));
1853 namespace QObjectTest
1855 class TestObject: public QObject
1859 TestObject(): QObject(), i(0) {}
1860 void doEmit() { emit aSignal(); }
1863 void aSlot() { ++i; }
1869 void tst_QObject::namespaces()
1871 QObjectTest::TestObject obj;
1873 QVERIFY(connect(&obj, SIGNAL(aSignal()), &obj, SLOT(aSlot())));
1878 class SuperObject : public QObject
1891 friend class tst_QObject;
1893 using QObject::sender;
1896 void rememberSender()
1898 theSender = sender();
1899 theSignalId = senderSignalIndex();
1902 void deleteAndRememberSender()
1908 void anotherSignal();
1912 void tst_QObject::sender()
1916 SuperObject receiver;
1917 connect(&sender, SIGNAL(anotherSignal()),
1918 &receiver, SLOT(rememberSender()));
1919 connect(&sender, SIGNAL(theSignal()),
1920 &receiver, SLOT(rememberSender()));
1921 QCOMPARE(receiver.sender(), (QObject *)0);
1922 QCOMPARE(receiver.senderSignalIndex(), -1);
1923 emit sender.theSignal();
1924 QCOMPARE(receiver.theSender, (QObject *)&sender);
1925 QCOMPARE(receiver.sender(), (QObject *)0);
1926 QCOMPARE(receiver.theSignalId,
1927 sender.metaObject()->indexOfSignal("theSignal()"));
1928 QCOMPARE(receiver.senderSignalIndex(), -1);
1930 emit sender.anotherSignal();
1931 QCOMPARE(receiver.theSignalId,
1932 sender.metaObject()->indexOfSignal("anotherSignal()"));
1933 QCOMPARE(receiver.senderSignalIndex(), -1);
1937 SuperObject *sender = new SuperObject;
1938 SuperObject *receiver = new SuperObject;
1939 connect(sender, SIGNAL(theSignal()),
1940 receiver, SLOT(rememberSender()),
1941 Qt::BlockingQueuedConnection);
1944 receiver->moveToThread(&thread);
1945 connect(sender, SIGNAL(theSignal()),
1946 &thread, SLOT(quit()),
1947 Qt::DirectConnection);
1949 QCOMPARE(receiver->sender(), (QObject *)0);
1950 QCOMPARE(receiver->senderSignalIndex(), -1);
1951 receiver->theSender = 0;
1952 receiver->theSignalId = -1;
1954 emit sender->theSignal();
1955 QCOMPARE(receiver->theSender, (QObject *) sender);
1956 QCOMPARE(receiver->sender(), (QObject *)0);
1957 QCOMPARE(receiver->theSignalId,
1958 sender->metaObject()->indexOfSignal("theSignal()"));
1959 QCOMPARE(receiver->senderSignalIndex(), -1);
1961 QVERIFY(thread.wait(10000));
1967 SuperObject *sender = new SuperObject;
1968 SuperObject receiver;
1969 connect(sender, SIGNAL(theSignal()),
1970 &receiver, SLOT(deleteAndRememberSender()));
1971 QCOMPARE(receiver.sender(), (QObject *)0);
1972 receiver.theSender = sender;
1973 emit sender->theSignal();
1974 QCOMPARE(receiver.theSender, (QObject *)0);
1975 QCOMPARE(receiver.sender(), (QObject *)0);
1979 SuperObject *sender = new SuperObject;
1980 SuperObject *receiver = new SuperObject;
1981 connect(sender, SIGNAL(theSignal()),
1982 receiver, SLOT(deleteAndRememberSender()),
1983 Qt::BlockingQueuedConnection);
1986 receiver->moveToThread(&thread);
1987 connect(sender, SIGNAL(destroyed()),
1988 &thread, SLOT(quit()),
1989 Qt::DirectConnection);
1991 QCOMPARE(receiver->sender(), (QObject *)0);
1992 receiver->theSender = sender;
1994 emit sender->theSignal();
1995 QCOMPARE(receiver->theSender, (QObject *)0);
1996 QCOMPARE(receiver->sender(), (QObject *)0);
1998 QVERIFY(thread.wait(10000));
2008 virtual int rtti() const = 0;
2014 virtual int rtti() const = 0;
2019 Q_DECLARE_INTERFACE(Foo::Bar, "com.qtest.foobar")
2022 #define Bleh_iid "com.qtest.bleh"
2024 Q_DECLARE_INTERFACE(Foo::Bleh, Bleh_iid)
2027 class FooObject: public QObject, public Foo::Bar
2030 Q_INTERFACES(Foo::Bar)
2032 int rtti() const { return 42; }
2035 class BlehObject : public QObject, public Foo::Bleh
2038 Q_INTERFACES(Foo::Bleh)
2040 int rtti() const { return 43; }
2043 void tst_QObject::declareInterface()
2047 Foo::Bar *bar = qobject_cast<Foo::Bar *>(&obj);
2049 QCOMPARE(bar->rtti(), 42);
2050 QCOMPARE(static_cast<Foo::Bar *>(&obj), bar);
2054 bar = qobject_cast<Foo::Bar *>(&bleh);
2056 Foo::Bleh *b = qobject_cast<Foo::Bleh *>(&bleh);
2057 QCOMPARE(b->rtti(), 43);
2058 QCOMPARE(static_cast<Foo::Bleh *>(&bleh), b);
2062 class CustomData : public QObjectUserData
2068 void tst_QObject::testUserData()
2070 const int USER_DATA_COUNT = 100;
2071 int user_data_ids[USER_DATA_COUNT];
2074 for (int i=0; i<USER_DATA_COUNT; ++i) {
2075 user_data_ids[i] = QObject::registerUserData();
2078 // Randomize the table a bit
2079 for (int i=0; i<100; ++i) {
2080 int p1 = rand() % USER_DATA_COUNT;
2081 int p2 = rand() % USER_DATA_COUNT;
2083 int tmp = user_data_ids[p1];
2084 user_data_ids[p1] = user_data_ids[p2];
2085 user_data_ids[p2] = tmp;
2088 // insert the user data into an object
2089 QObject my_test_object;
2090 for (int i=0; i<USER_DATA_COUNT; ++i) {
2091 CustomData *data = new CustomData;
2092 data->id = user_data_ids[i];
2093 my_test_object.setUserData(data->id, data);
2096 // verify that all ids and positions are matching
2097 for (int i=0; i<USER_DATA_COUNT; ++i) {
2098 int id = user_data_ids[i];
2099 CustomData *data = static_cast<CustomData *>(my_test_object.userData(id));
2101 QVERIFY(data->id == id);
2105 class DestroyedListener : public QObject
2109 inline DestroyedListener() : pointerWasZero(false) {}
2111 QPointer<QObject> pointer;
2112 bool pointerWasZero;
2115 inline void otherObjectDestroyed()
2116 { pointerWasZero = pointer.isNull(); }
2119 void tst_QObject::qpointerResetBeforeDestroyedSignal()
2121 QObject *obj = new QObject;
2122 DestroyedListener listener;
2123 listener.pointer = obj;
2124 listener.pointerWasZero = false;
2125 connect(obj, SIGNAL(destroyed()), &listener, SLOT(otherObjectDestroyed()));
2127 QVERIFY(listener.pointerWasZero);
2128 QVERIFY(listener.pointer.isNull());
2131 class DefaultArguments : public QObject
2137 void theSlot(const QString &s) { result = s; }
2140 void theOriginalSignal();
2141 void theSecondSignal(const QString &s = QString("secondDefault"));
2145 void emitTheOriginalSignal() { emit theOriginalSignal(); }
2146 void emitTheSecondSignal() { emit theSecondSignal(); }
2150 void tst_QObject::connectSignalsToSignalsWithDefaultArguments()
2153 connect(&o, SIGNAL(theOriginalSignal()), &o, SIGNAL(theSecondSignal()));
2154 connect(&o, SIGNAL(theSecondSignal(QString)), &o, SLOT(theSlot(QString)));
2155 QVERIFY( o.result.isEmpty() );
2156 o.emitTheSecondSignal();
2157 QCOMPARE(o.result, QString("secondDefault"));
2158 o.result = "Not called";
2159 o.emitTheOriginalSignal();
2160 QCOMPARE(o.result, QString("secondDefault"));
2164 void tst_QObject::receivers()
2166 class Object : public QObject
2169 int receivers(const char* signal) const
2170 { return QObject::receivers(signal); }
2174 QCOMPARE(object.receivers(SIGNAL(destroyed())), 0);
2175 object.connect(&object, SIGNAL(destroyed()), SLOT(deleteLater()));
2176 QCOMPARE(object.receivers(SIGNAL(destroyed())), 1);
2177 object.connect(&object, SIGNAL(destroyed()), SLOT(deleteLater()));
2178 QCOMPARE(object.receivers(SIGNAL(destroyed())), 2);
2179 object.disconnect(SIGNAL(destroyed()), &object, SLOT(deleteLater()));
2180 QCOMPARE(object.receivers(SIGNAL(destroyed())), 0);
2187 template <typename T> class Template { };
2189 class NormalizeObject : public QObject
2196 void uintPointerSignal(uint *);
2197 void ulongPointerSignal(ulong *);
2198 void constUintPointerSignal(const uint *);
2199 void constUlongPointerSignal(const ulong *);
2201 void structSignal(Struct s);
2202 void classSignal(Class c);
2203 void enumSignal(Enum e);
2205 void structPointerSignal(Struct *s);
2206 void classPointerSignal(Class *c);
2207 void enumPointerSignal(Enum *e);
2209 void constStructPointerSignal(const Struct *s);
2210 void constClassPointerSignal(const Class *c);
2211 void constEnumPointerSignal(const Enum *e);
2213 void constStructPointerConstPointerSignal(const Struct * const *s);
2214 void constClassPointerConstPointerSignal(const Class * const *c);
2215 void constEnumPointerConstPointerSignal(const Enum * const *e);
2217 void unsignedintSignal(unsigned int);
2218 void unsignedSignal(unsigned);
2219 void unsignedlongSignal(unsigned long);
2220 void unsignedlonglongSignal(quint64);
2221 void unsignedlongintSignal(unsigned long int);
2222 void unsignedshortSignal(unsigned short);
2223 void unsignedcharSignal(unsigned char);
2225 void typeRefSignal(Template<Class &> &ref);
2226 void constTypeRefSignal(const Template<Class const &> &ref);
2227 void typeConstRefSignal(Template<Class const &> const &ref);
2229 void typePointerConstRefSignal(Class * const &);
2231 void constTemplateSignal1( Template<int > );
2232 void constTemplateSignal2( Template< const int >);
2235 void uintPointerSlot(uint *) { }
2236 void ulongPointerSlot(ulong *) { }
2237 void constUintPointerSlot(const uint *) { }
2238 void constUlongPointerSlot(const ulong *) { }
2240 void structSlot(Struct s) { Q_UNUSED(s); }
2241 void classSlot(Class c) { Q_UNUSED(c); }
2242 void enumSlot(Enum e) { Q_UNUSED(e); }
2244 void structPointerSlot(Struct *s) { Q_UNUSED(s); }
2245 void classPointerSlot(Class *c) { Q_UNUSED(c); }
2246 void enumPointerSlot(Enum *e) { Q_UNUSED(e); }
2248 void constStructPointerSlot(const Struct *s) { Q_UNUSED(s); }
2249 void constClassPointerSlot(const Class *c) { Q_UNUSED(c); }
2250 void constEnumPointerSlot(const Enum *e) { Q_UNUSED(e); }
2252 void constStructPointerConstPointerSlot(const Struct * const *s) { Q_UNUSED(s); }
2253 void constClassPointerConstPointerSlot(const Class * const *c) { Q_UNUSED(c); }
2254 void constEnumPointerConstPointerSlot(const Enum * const *e) { Q_UNUSED(e); }
2256 void uintSlot(uint) {};
2257 void unsignedintSlot(unsigned int) {};
2258 void unsignedSlot(unsigned) {};
2259 void unsignedlongSlot(unsigned long) {};
2260 void unsignedlonglongSlot(quint64) {};
2261 void unsignedlongintSlot(unsigned long int) {};
2262 void unsignedshortSlot(unsigned short) {};
2263 void unsignedcharSlot(unsigned char) {};
2265 void typeRefSlot(Template<Class &> &) {}
2266 void constTypeRefSlot(const Template<const Class &> &) {}
2267 void typeConstRefSlot(Template<Class const &> const &) {}
2269 void typePointerConstRefSlot(Class * const &) {}
2271 void constTemplateSlot1(Template<int > const) {}
2272 void constTemplateSlot2(const Template<int > ) {}
2273 void constTemplateSlot3(const Template< const int >) {}
2276 #include "oldnormalizeobject.h"
2278 void tst_QObject::normalize()
2280 NormalizeObject object;
2282 // unsigned int -> uint, unsigned long -> ulong
2283 QVERIFY(object.connect(&object,
2284 SIGNAL(uintPointerSignal(uint *)),
2285 SLOT(uintPointerSlot(uint *))));
2286 QVERIFY(object.connect(&object,
2287 SIGNAL(uintPointerSignal(unsigned int *)),
2288 SLOT(uintPointerSlot(uint *))));
2289 QVERIFY(object.connect(&object,
2290 SIGNAL(uintPointerSignal(uint *)),
2291 SLOT(uintPointerSlot(unsigned int *))));
2293 QVERIFY(object.connect(&object,
2294 SIGNAL(constUintPointerSignal(const uint *)),
2295 SLOT(constUintPointerSlot(const uint *))));
2296 QVERIFY(object.connect(&object,
2297 SIGNAL(constUintPointerSignal(const unsigned int *)),
2298 SLOT(constUintPointerSlot(const uint *))));
2299 QVERIFY(object.connect(&object,
2300 SIGNAL(constUintPointerSignal(const uint *)),
2301 SLOT(constUintPointerSlot(const unsigned int *))));
2303 QVERIFY(object.connect(&object,
2304 SIGNAL(ulongPointerSignal(ulong *)),
2305 SLOT(ulongPointerSlot(ulong *))));
2306 QVERIFY(object.connect(&object,
2307 SIGNAL(ulongPointerSignal(unsigned long *)),
2308 SLOT(ulongPointerSlot(ulong *))));
2309 QVERIFY(object.connect(&object,
2310 SIGNAL(ulongPointerSignal(ulong *)),
2311 SLOT(ulongPointerSlot(unsigned long *))));
2313 QVERIFY(object.connect(&object,
2314 SIGNAL(constUlongPointerSignal(const ulong *)),
2315 SLOT(constUlongPointerSlot(const ulong *))));
2316 QVERIFY(object.connect(&object,
2317 SIGNAL(constUlongPointerSignal(const unsigned long *)),
2318 SLOT(constUlongPointerSlot(const ulong *))));
2319 QVERIFY(object.connect(&object,
2320 SIGNAL(constUlongPointerSignal(const ulong *)),
2321 SLOT(constUlongPointerSlot(const unsigned long *))));
2323 // struct, class, and enum are optional
2324 QVERIFY(object.connect(&object,
2325 SIGNAL(structSignal(struct Struct)),
2326 SLOT(structSlot(struct Struct))));
2327 QVERIFY(object.connect(&object,
2328 SIGNAL(structSignal(Struct)),
2329 SLOT(structSlot(struct Struct))));
2330 QVERIFY(object.connect(&object,
2331 SIGNAL(structSignal(struct Struct)),
2332 SLOT(structSlot(Struct))));
2333 QVERIFY(object.connect(&object,
2334 SIGNAL(classSignal(class Class)),
2335 SLOT(classSlot(class Class))));
2336 QVERIFY(object.connect(&object,
2337 SIGNAL(classSignal(Class)),
2338 SLOT(classSlot(class Class))));
2339 QVERIFY(object.connect(&object,
2340 SIGNAL(classSignal(class Class)),
2341 SLOT(classSlot(Class))));
2342 QVERIFY(object.connect(&object,
2343 SIGNAL(enumSignal(enum Enum)),
2344 SLOT(enumSlot(enum Enum))));
2345 QVERIFY(object.connect(&object,
2346 SIGNAL(enumSignal(Enum)),
2347 SLOT(enumSlot(enum Enum))));
2348 QVERIFY(object.connect(&object,
2349 SIGNAL(enumSignal(enum Enum)),
2350 SLOT(enumSlot(Enum))));
2352 QVERIFY(object.connect(&object,
2353 SIGNAL(structPointerSignal(struct Struct *)),
2354 SLOT(structPointerSlot(struct Struct *))));
2355 QVERIFY(object.connect(&object,
2356 SIGNAL(structPointerSignal(Struct *)),
2357 SLOT(structPointerSlot(struct Struct *))));
2358 QVERIFY(object.connect(&object,
2359 SIGNAL(structPointerSignal(struct Struct *)),
2360 SLOT(structPointerSlot(Struct *))));
2361 QVERIFY(object.connect(&object,
2362 SIGNAL(classPointerSignal(class Class *)),
2363 SLOT(classPointerSlot(class Class *))));
2364 QVERIFY(object.connect(&object,
2365 SIGNAL(classPointerSignal(Class *)),
2366 SLOT(classPointerSlot(class Class *))));
2367 QVERIFY(object.connect(&object,
2368 SIGNAL(classPointerSignal(class Class *)),
2369 SLOT(classPointerSlot(Class *))));
2370 QVERIFY(object.connect(&object,
2371 SIGNAL(enumPointerSignal(enum Enum *)),
2372 SLOT(enumPointerSlot(enum Enum *))));
2373 QVERIFY(object.connect(&object,
2374 SIGNAL(enumPointerSignal(Enum *)),
2375 SLOT(enumPointerSlot(enum Enum *))));
2376 QVERIFY(object.connect(&object,
2377 SIGNAL(enumPointerSignal(enum Enum *)),
2378 SLOT(enumPointerSlot(Enum *))));
2380 QVERIFY(object.connect(&object,
2381 SIGNAL(constStructPointerSignal(const struct Struct *)),
2382 SLOT(constStructPointerSlot(const struct Struct *))));
2383 QVERIFY(object.connect(&object,
2384 SIGNAL(constStructPointerSignal(const Struct *)),
2385 SLOT(constStructPointerSlot(const struct Struct *))));
2386 QVERIFY(object.connect(&object,
2387 SIGNAL(constStructPointerSignal(const struct Struct *)),
2388 SLOT(constStructPointerSlot(const Struct *))));
2389 QVERIFY(object.connect(&object,
2390 SIGNAL(constClassPointerSignal(const class Class *)),
2391 SLOT(constClassPointerSlot(const class Class *))));
2392 QVERIFY(object.connect(&object,
2393 SIGNAL(constClassPointerSignal(const Class *)),
2394 SLOT(constClassPointerSlot(const class Class *))));
2395 QVERIFY(object.connect(&object,
2396 SIGNAL(constClassPointerSignal(const class Class *)),
2397 SLOT(constClassPointerSlot(const Class *))));
2398 QVERIFY(object.connect(&object,
2399 SIGNAL(constEnumPointerSignal(const enum Enum *)),
2400 SLOT(constEnumPointerSlot(const enum Enum *))));
2401 QVERIFY(object.connect(&object,
2402 SIGNAL(constEnumPointerSignal(const Enum *)),
2403 SLOT(constEnumPointerSlot(const enum Enum *))));
2404 QVERIFY(object.connect(&object,
2405 SIGNAL(constEnumPointerSignal(const enum Enum *)),
2406 SLOT(constEnumPointerSlot(const Enum *))));
2408 QVERIFY(object.connect(&object,
2409 SIGNAL(constStructPointerSignal(struct Struct const *)),
2410 SLOT(constStructPointerSlot(struct Struct const *))));
2411 QVERIFY(object.connect(&object,
2412 SIGNAL(constStructPointerSignal(Struct const *)),
2413 SLOT(constStructPointerSlot(struct Struct const *))));
2414 QVERIFY(object.connect(&object,
2415 SIGNAL(constStructPointerSignal(struct Struct const *)),
2416 SLOT(constStructPointerSlot(Struct const *))));
2417 QVERIFY(object.connect(&object,
2418 SIGNAL(constClassPointerSignal(class Class const *)),
2419 SLOT(constClassPointerSlot(class Class const *))));
2420 QVERIFY(object.connect(&object,
2421 SIGNAL(constClassPointerSignal(Class const *)),
2422 SLOT(constClassPointerSlot(class Class const *))));
2423 QVERIFY(object.connect(&object,
2424 SIGNAL(constClassPointerSignal(class Class const *)),
2425 SLOT(constClassPointerSlot(Class const *))));
2426 QVERIFY(object.connect(&object,
2427 SIGNAL(constEnumPointerSignal(enum Enum const *)),
2428 SLOT(constEnumPointerSlot(enum Enum const *))));
2429 QVERIFY(object.connect(&object,
2430 SIGNAL(constEnumPointerSignal(Enum const *)),
2431 SLOT(constEnumPointerSlot(enum Enum const *))));
2432 QVERIFY(object.connect(&object,
2433 SIGNAL(constEnumPointerSignal(enum Enum const *)),
2434 SLOT(constEnumPointerSlot(Enum const *))));
2436 QVERIFY(object.connect(&object,
2437 SIGNAL(constStructPointerConstPointerSignal(const struct Struct * const *)),
2438 SLOT(constStructPointerConstPointerSlot(const struct Struct * const *))));
2439 QVERIFY(object.connect(&object,
2440 SIGNAL(constStructPointerConstPointerSignal(const Struct * const *)),
2441 SLOT(constStructPointerConstPointerSlot(const struct Struct * const *))));
2442 QVERIFY(object.connect(&object,
2443 SIGNAL(constStructPointerConstPointerSignal(const struct Struct * const *)),
2444 SLOT(constStructPointerConstPointerSlot(const Struct * const *))));
2445 QVERIFY(object.connect(&object,
2446 SIGNAL(constClassPointerConstPointerSignal(const class Class * const *)),
2447 SLOT(constClassPointerConstPointerSlot(const class Class * const *))));
2448 QVERIFY(object.connect(&object,
2449 SIGNAL(constClassPointerConstPointerSignal(const Class * const *)),
2450 SLOT(constClassPointerConstPointerSlot(const class Class * const *))));
2451 QVERIFY(object.connect(&object,
2452 SIGNAL(constClassPointerConstPointerSignal(const class Class * const *)),
2453 SLOT(constClassPointerConstPointerSlot(const Class * const *))));
2454 QVERIFY(object.connect(&object,
2455 SIGNAL(constEnumPointerConstPointerSignal(const enum Enum * const *)),
2456 SLOT(constEnumPointerConstPointerSlot(const enum Enum * const *))));
2457 QVERIFY(object.connect(&object,
2458 SIGNAL(constEnumPointerConstPointerSignal(const Enum * const *)),
2459 SLOT(constEnumPointerConstPointerSlot(const enum Enum * const *))));
2460 QVERIFY(object.connect(&object,
2461 SIGNAL(constEnumPointerConstPointerSignal(const enum Enum * const *)),
2462 SLOT(constEnumPointerConstPointerSlot(const Enum * const *))));
2464 QVERIFY(object.connect(&object,
2465 SIGNAL(constStructPointerConstPointerSignal(struct Struct const * const *)),
2466 SLOT(constStructPointerConstPointerSlot(struct Struct const * const *))));
2467 QVERIFY(object.connect(&object,
2468 SIGNAL(constStructPointerConstPointerSignal(Struct const * const *)),
2469 SLOT(constStructPointerConstPointerSlot(struct Struct const * const *))));
2470 QVERIFY(object.connect(&object,
2471 SIGNAL(constStructPointerConstPointerSignal(struct Struct const * const *)),
2472 SLOT(constStructPointerConstPointerSlot(Struct const * const *))));
2473 QVERIFY(object.connect(&object,
2474 SIGNAL(constClassPointerConstPointerSignal(class Class const * const *)),
2475 SLOT(constClassPointerConstPointerSlot(class Class const * const *))));
2476 QVERIFY(object.connect(&object,
2477 SIGNAL(constClassPointerConstPointerSignal(Class const * const *)),
2478 SLOT(constClassPointerConstPointerSlot(class Class const * const *))));
2479 QVERIFY(object.connect(&object,
2480 SIGNAL(constClassPointerConstPointerSignal(class Class const * const *)),
2481 SLOT(constClassPointerConstPointerSlot(Class const * const *))));
2482 QVERIFY(object.connect(&object,
2483 SIGNAL(constEnumPointerConstPointerSignal(enum Enum const * const *)),
2484 SLOT(constEnumPointerConstPointerSlot(enum Enum const * const *))));
2485 QVERIFY(object.connect(&object,
2486 SIGNAL(constEnumPointerConstPointerSignal(Enum const * const *)),
2487 SLOT(constEnumPointerConstPointerSlot(enum Enum const * const *))));
2488 QVERIFY(object.connect(&object,
2489 SIGNAL(constEnumPointerConstPointerSignal(enum Enum const * const *)),
2490 SLOT(constEnumPointerConstPointerSlot(Enum const * const *))));
2492 QVERIFY(object.connect(&object,
2493 SIGNAL(unsignedintSignal(unsigned int)),
2494 SLOT(unsignedintSlot(unsigned int))));
2495 QVERIFY(object.connect(&object,
2496 SIGNAL(unsignedSignal(unsigned)),
2497 SLOT(unsignedSlot(unsigned))));
2498 QVERIFY(object.connect(&object,
2499 SIGNAL(unsignedSignal(unsigned)),
2500 SLOT(uintSlot(uint))));
2501 QVERIFY(object.connect(&object,
2502 SIGNAL(unsignedlongSignal(unsigned long)),
2503 SLOT(unsignedlongSlot(unsigned long))));
2504 QVERIFY(object.connect(&object,
2505 SIGNAL(unsignedlonglongSignal(quint64)),
2506 SLOT(unsignedlonglongSlot(quint64))));
2507 QVERIFY(object.connect(&object,
2508 SIGNAL(unsignedlongintSignal(unsigned long int)),
2509 SLOT(unsignedlongintSlot(unsigned long int))));
2510 QVERIFY(object.connect(&object,
2511 SIGNAL(unsignedshortSignal(unsigned short)),
2512 SLOT(unsignedshortSlot(unsigned short))));
2513 QVERIFY(object.connect(&object,
2514 SIGNAL(unsignedcharSignal(unsigned char)),
2515 SLOT(unsignedcharSlot(unsigned char))));
2517 // connect when original template signature and mixed usage of 'T<C const &> const &',
2518 // 'const T<const C &> &', and 'T<const C &>'
2520 QVERIFY(object.connect(&object,
2521 SIGNAL(typeRefSignal(Template<Class &> &)),
2522 SLOT(typeRefSlot(Template<Class &> &))));
2524 QVERIFY(object.connect(&object,
2525 SIGNAL(constTypeRefSignal(const Template<const Class &> &)),
2526 SLOT(constTypeRefSlot(const Template<const Class &> &))));
2527 QVERIFY(object.connect(&object,
2528 SIGNAL(constTypeRefSignal(const Template<const Class &> &)),
2529 SLOT(constTypeRefSlot(const Template<Class const &> &))));
2530 QVERIFY(object.connect(&object,
2531 SIGNAL(constTypeRefSignal(const Template<const Class &> &)),
2532 SLOT(constTypeRefSlot(Template<Class const &> const &))));
2533 QVERIFY(object.connect(&object,
2534 SIGNAL(constTypeRefSignal(Template<const Class &> const &)),
2535 SLOT(constTypeRefSlot(Template<Class const &> const &))));
2536 QVERIFY(object.connect(&object,
2537 SIGNAL(constTypeRefSignal(Template<Class const &> const &)),
2538 SLOT(constTypeRefSlot(Template<Class const &> const &))));
2540 QVERIFY(object.connect(&object,
2541 SIGNAL(constTypeRefSignal(const Template<const Class &> &)),
2542 SLOT(typeConstRefSlot(const Template<const Class &> &))));
2543 QVERIFY(object.connect(&object,
2544 SIGNAL(constTypeRefSignal(const Template<const Class &> &)),
2545 SLOT(typeConstRefSlot(const Template<Class const &> &))));
2546 QVERIFY(object.connect(&object,
2547 SIGNAL(constTypeRefSignal(const Template<const Class &> &)),
2548 SLOT(typeConstRefSlot(Template<Class const &> const &))));
2549 QVERIFY(object.connect(&object,
2550 SIGNAL(constTypeRefSignal(Template<const Class &> const &)),
2551 SLOT(typeConstRefSlot(Template<Class const &> const &))));
2552 QVERIFY(object.connect(&object,
2553 SIGNAL(constTypeRefSignal(Template<Class const &> const &)),
2554 SLOT(typeConstRefSlot(Template<Class const &> const &))));
2556 QVERIFY(object.connect(&object,
2557 SIGNAL(typeConstRefSignal(const Template<const Class &> &)),
2558 SLOT(constTypeRefSlot(const Template<const Class &> &))));
2559 QVERIFY(object.connect(&object,
2560 SIGNAL(typeConstRefSignal(const Template<const Class &> &)),
2561 SLOT(constTypeRefSlot(const Template<Class const &> &))));
2562 QVERIFY(object.connect(&object,
2563 SIGNAL(typeConstRefSignal(const Template<const Class &> &)),
2564 SLOT(constTypeRefSlot(Template<Class const &> const &))));
2565 QVERIFY(object.connect(&object,
2566 SIGNAL(typeConstRefSignal(Template<const Class &> const &)),
2567 SLOT(constTypeRefSlot(Template<Class const &> const &))));
2568 QVERIFY(object.connect(&object,
2569 SIGNAL(typeConstRefSignal(Template<Class const &> const &)),
2570 SLOT(constTypeRefSlot(Template<Class const &> const &))));
2572 QVERIFY(object.connect(&object,
2573 SIGNAL(typeConstRefSignal(const Template<const Class &> &)),
2574 SLOT(typeConstRefSlot(const Template<const Class &> &))));
2575 QVERIFY(object.connect(&object,
2576 SIGNAL(typeConstRefSignal(const Template<const Class &> &)),
2577 SLOT(typeConstRefSlot(const Template<Class const &> &))));
2578 QVERIFY(object.connect(&object,
2579 SIGNAL(typeConstRefSignal(const Template<const Class &> &)),
2580 SLOT(typeConstRefSlot(Template<Class const &> const &))));
2581 QVERIFY(object.connect(&object,
2582 SIGNAL(typeConstRefSignal(Template<const Class &> const &)),
2583 SLOT(typeConstRefSlot(Template<Class const &> const &))));
2584 QVERIFY(object.connect(&object,
2585 SIGNAL(typeConstRefSignal(Template<Class const &> const &)),
2586 SLOT(typeConstRefSlot(Template<Class const &> const &))));
2588 // same test again, this time with an object compiled with old moc output... we know that
2589 // it is not possible to connect everything, whic is the purpose for this test
2590 OldNormalizeObject oldobject;
2592 QVERIFY(oldobject.connect(&oldobject,
2593 SIGNAL(constTypeRefSignal(const Template<const Class &> &)),
2594 SLOT(constTypeRefSlot(const Template<const Class &> &))));
2595 QVERIFY(oldobject.connect(&oldobject,
2596 SIGNAL(constTypeRefSignal(const Template<const Class &> &)),
2597 SLOT(constTypeRefSlot(const Template<Class const &> &))));
2598 // this fails in older versions, but passes now due to proper normalizing
2599 QVERIFY(oldobject.connect(&oldobject,
2600 SIGNAL(constTypeRefSignal(const Template<const Class &> &)),
2601 SLOT(constTypeRefSlot(Template<Class const &> const &))));
2602 // this fails in older versions, but passes now due to proper normalizing
2603 QVERIFY(oldobject.connect(&oldobject,
2604 SIGNAL(constTypeRefSignal(Template<const Class &> const &)),
2605 SLOT(constTypeRefSlot(Template<Class const &> const &))));
2606 // this fails in older versions, but passes now due to proper normalizing
2607 QVERIFY(oldobject.connect(&oldobject,
2608 SIGNAL(constTypeRefSignal(Template<Class const &> const &)),
2609 SLOT(constTypeRefSlot(Template<Class const &> const &))));
2611 // these fail in older Qt versions, but pass now due to proper normalizing
2612 QVERIFY(oldobject.connect(&oldobject,
2613 SIGNAL(constTypeRefSignal(const Template<const Class &> &)),
2614 SLOT(typeConstRefSlot(const Template<const Class &> &))));
2615 QVERIFY(oldobject.connect(&oldobject,
2616 SIGNAL(constTypeRefSignal(const Template<const Class &> &)),
2617 SLOT(typeConstRefSlot(const Template<Class const &> &))));
2618 QVERIFY(oldobject.connect(&oldobject,
2619 SIGNAL(constTypeRefSignal(const Template<const Class &> &)),
2620 SLOT(typeConstRefSlot(Template<Class const &> const &))));
2621 QVERIFY(oldobject.connect(&oldobject,
2622 SIGNAL(constTypeRefSignal(Template<const Class &> const &)),
2623 SLOT(typeConstRefSlot(Template<Class const &> const &))));
2624 QVERIFY(oldobject.connect(&oldobject,
2625 SIGNAL(constTypeRefSignal(Template<Class const &> const &)),
2626 SLOT(typeConstRefSlot(Template<Class const &> const &))));
2628 // these also fail in older Qt versions, but pass now due to proper normalizing
2629 QVERIFY(oldobject.connect(&oldobject,
2630 SIGNAL(typeConstRefSignal(const Template<const Class &> &)),
2631 SLOT(constTypeRefSlot(const Template<const Class &> &))));
2632 QVERIFY(oldobject.connect(&oldobject,
2633 SIGNAL(typeConstRefSignal(const Template<const Class &> &)),
2634 SLOT(constTypeRefSlot(const Template<Class const &> &))));
2635 QVERIFY(oldobject.connect(&oldobject,
2636 SIGNAL(typeConstRefSignal(const Template<const Class &> &)),
2637 SLOT(constTypeRefSlot(Template<Class const &> const &))));
2638 QVERIFY(oldobject.connect(&oldobject,
2639 SIGNAL(typeConstRefSignal(Template<const Class &> const &)),
2640 SLOT(constTypeRefSlot(Template<Class const &> const &))));
2641 QVERIFY(oldobject.connect(&oldobject,
2642 SIGNAL(typeConstRefSignal(Template<Class const &> const &)),
2643 SLOT(constTypeRefSlot(Template<Class const &> const &))));
2645 // this fails in older versions, but passes now due to proper normalizing
2646 QVERIFY(oldobject.connect(&oldobject,
2647 SIGNAL(typeConstRefSignal(const Template<const Class &> &)),
2648 SLOT(typeConstRefSlot(const Template<const Class &> &))));
2649 // this fails in older versions, but passes now due to proper normalizing
2650 QVERIFY(oldobject.connect(&oldobject,
2651 SIGNAL(typeConstRefSignal(const Template<const Class &> &)),
2652 SLOT(typeConstRefSlot(const Template<Class const &> &))));
2653 // this fails in older versions, but passes now due to proper normalizing
2654 QVERIFY(oldobject.connect(&oldobject,
2655 SIGNAL(typeConstRefSignal(const Template<const Class &> &)),
2656 SLOT(typeConstRefSlot(Template<Class const &> const &))));
2657 QVERIFY(oldobject.connect(&oldobject,
2658 SIGNAL(typeConstRefSignal(Template<const Class &> const &)),
2659 SLOT(typeConstRefSlot(Template<Class const &> const &))));
2660 QVERIFY(oldobject.connect(&oldobject,
2661 SIGNAL(typeConstRefSignal(Template<Class const &> const &)),
2662 SLOT(typeConstRefSlot(Template<Class const &> const &))));
2664 QVERIFY(object.connect(&object,
2665 SIGNAL(typePointerConstRefSignal(Class*const&)),
2666 SLOT(typePointerConstRefSlot(Class*const&))));
2667 QVERIFY(object.connect(&object,
2668 SIGNAL(typePointerConstRefSignal(Class*const&)),
2669 SLOT(typePointerConstRefSlot(Class*))));
2670 QVERIFY(object.connect(&object,
2671 SIGNAL(typePointerConstRefSignal(Class*)),
2672 SLOT(typePointerConstRefSlot(Class*const&))));
2673 QVERIFY(object.connect(&object,
2674 SIGNAL(typePointerConstRefSignal(Class*)),
2675 SLOT(typePointerConstRefSlot(Class*))));
2677 QVERIFY( connect(&object, SIGNAL(constTemplateSignal1(Template <int>)),
2678 &object , SLOT(constTemplateSlot1 (Template<int > ) ) ));
2679 QVERIFY( connect(&object, SIGNAL(constTemplateSignal1(Template <int>)),
2680 &object , SLOT(constTemplateSlot2 (Template<int > ) ) ));
2681 QVERIFY( connect(&object, SIGNAL(constTemplateSignal2(Template <const int>)),
2682 &object , SLOT(constTemplateSlot3(Template<int const > ) ) ));
2684 //type does not match
2685 QTest::ignoreMessage(QtWarningMsg, "QObject::connect: Incompatible sender/receiver arguments\n"
2686 " NormalizeObject::constTemplateSignal1(Template<int>) --> NormalizeObject::constTemplateSlot3(Template<const int>)");
2687 QVERIFY(!connect(&object, SIGNAL(constTemplateSignal1(Template <int>)),
2688 &object , SLOT(constTemplateSlot3(Template<int const> ) ) ));
2691 class SiblingDeleter : public QObject
2694 inline SiblingDeleter(QObject *sibling, QObject *parent)
2695 : QObject(parent), sibling(sibling) {}
2696 inline virtual ~SiblingDeleter() { delete sibling; }
2699 QPointer<QObject> sibling;
2703 void tst_QObject::childDeletesItsSibling()
2705 QObject *commonParent = new QObject(0);
2706 QPointer<QObject> child = new QObject(0);
2707 QPointer<QObject> siblingDeleter = new SiblingDeleter(child, commonParent);
2708 child->setParent(commonParent);
2709 delete commonParent; // don't crash
2711 QVERIFY(!siblingDeleter);
2714 void tst_QObject::floatProperty()
2717 const int idx = obj.metaObject()->indexOfProperty("myFloat");
2719 QMetaProperty prop = obj.metaObject()->property(idx);
2720 QVERIFY(prop.isValid());
2721 QVERIFY(prop.type() == uint(QMetaType::type("float")));
2722 QVERIFY(!prop.write(&obj, QVariant("Hello")));
2723 QVERIFY(prop.write(&obj, qVariantFromValue(128.0f)));
2724 QVariant v = prop.read(&obj);
2725 QVERIFY(int(v.userType()) == QMetaType::Float);
2726 QVERIFY(qVariantValue<float>(v) == 128.0f);
2729 void tst_QObject::qrealProperty()
2732 const int idx = obj.metaObject()->indexOfProperty("myQReal");
2734 QMetaProperty prop = obj.metaObject()->property(idx);
2735 QVERIFY(prop.isValid());
2736 QVERIFY(prop.type() == uint(QMetaType::type("qreal")));
2737 QVERIFY(!prop.write(&obj, QVariant("Hello")));
2739 QVERIFY(prop.write(&obj, qVariantFromValue(128.0f)));
2740 QVariant v = prop.read(&obj);
2741 QCOMPARE(v.userType(), qMetaTypeId<qreal>());
2742 QVERIFY(qVariantValue<qreal>(v) == 128.0);
2744 QVERIFY(prop.write(&obj, qVariantFromValue(double(127))));
2745 v = prop.read(&obj);
2746 QCOMPARE(v.userType(), qMetaTypeId<qreal>());
2747 QVERIFY(qVariantValue<qreal>(v) == 127.0);
2750 class DynamicPropertyObject : public PropertyObject
2753 inline DynamicPropertyObject() {}
2755 inline virtual bool event(QEvent *e) {
2756 if (e->type() == QEvent::DynamicPropertyChange) {
2757 changedDynamicProperties.append(static_cast<QDynamicPropertyChangeEvent *>(e)->propertyName());
2759 return QObject::event(e);
2762 QList<QByteArray> changedDynamicProperties;
2765 void tst_QObject::dynamicProperties()
2767 DynamicPropertyObject obj;
2769 QVERIFY(obj.dynamicPropertyNames().isEmpty());
2771 QVERIFY(obj.setProperty("number", 42));
2772 QVERIFY(obj.changedDynamicProperties.isEmpty());
2773 QCOMPARE(obj.property("number").toInt(), 42);
2775 QVERIFY(!obj.setProperty("number", "invalid string"));
2776 QVERIFY(obj.changedDynamicProperties.isEmpty());
2778 QVERIFY(!obj.setProperty("myuserproperty", "Hello"));
2779 QCOMPARE(obj.changedDynamicProperties.count(), 1);
2780 QCOMPARE(obj.changedDynamicProperties.first(), QByteArray("myuserproperty"));
2781 obj.changedDynamicProperties.clear();
2783 QCOMPARE(obj.property("myuserproperty").toString(), QString("Hello"));
2785 QCOMPARE(obj.dynamicPropertyNames().count(), 1);
2786 QCOMPARE(obj.dynamicPropertyNames().first(), QByteArray("myuserproperty"));
2788 QVERIFY(!obj.setProperty("myuserproperty", QVariant()));
2790 QCOMPARE(obj.changedDynamicProperties.count(), 1);
2791 QCOMPARE(obj.changedDynamicProperties.first(), QByteArray("myuserproperty"));
2792 obj.changedDynamicProperties.clear();
2794 QVERIFY(obj.property("myuserproperty").isNull());
2796 QVERIFY(obj.dynamicPropertyNames().isEmpty());
2799 #ifndef QT_NO_PROCESS
2800 void tst_QObject::recursiveSignalEmission()
2803 // signalbug helper app should always be next to this test binary
2804 const QString path = QStringLiteral("signalbug/signalbug");
2806 QVERIFY2(proc.waitForStarted(), qPrintable(QString::fromLatin1("Cannot start '%1': %2").arg(path, proc.errorString())));
2807 QVERIFY(proc.waitForFinished());
2808 QVERIFY(proc.exitStatus() == QProcess::NormalExit);
2809 QCOMPARE(proc.exitCode(), 0);
2813 void tst_QObject::blockingQueuedConnection()
2816 SenderObject sender;
2818 MoveToThreadThread thread;
2819 ReceiverObject receiver;
2820 receiver.moveToThread(&thread);
2823 receiver.connect(&sender, SIGNAL(signal1()), SLOT(slot1()), Qt::BlockingQueuedConnection);
2824 sender.emitSignal1();
2825 QVERIFY(receiver.called(1));
2828 QVERIFY(QMetaObject::invokeMethod(&receiver, "slot1", Qt::BlockingQueuedConnection));
2829 QVERIFY(receiver.called(1));
2831 connect(&sender, &SenderObject::signal2, &receiver, &ReceiverObject::slot2, Qt::BlockingQueuedConnection);
2832 sender.emitSignal2();
2833 QVERIFY(receiver.called(2));
2836 QVERIFY(thread.wait());
2840 class EventSpy : public QObject
2845 typedef QList<QPair<QObject *, QEvent::Type> > EventList;
2847 EventSpy(QObject *parent = 0)
2851 EventList eventList()
2861 bool eventFilter(QObject *object, QEvent *event)
2863 events.append(qMakePair(object, event->type()));
2871 void tst_QObject::childEvents()
2873 EventSpy::EventList expected;
2876 // no children created, so we expect no events
2879 object.installEventFilter(&spy);
2881 QCoreApplication::postEvent(&object, new QEvent(QEvent::Type(QEvent::User + 1)));
2883 QCoreApplication::processEvents();
2886 EventSpy::EventList()
2887 << qMakePair(&object, QEvent::Type(QEvent::User + 1));
2888 QCOMPARE(spy.eventList(), expected);
2892 // 2 children, so we expect 2 ChildAdded events
2895 object.installEventFilter(&spy);
2897 QCoreApplication::postEvent(&object, new QEvent(QEvent::Type(QEvent::User + 1)));
2899 QObject child1(&object);
2901 child2.setParent(&object);
2903 QCoreApplication::postEvent(&object, new QEvent(QEvent::Type(QEvent::User + 2)));
2906 EventSpy::EventList()
2907 << qMakePair(&object, QEvent::ChildAdded)
2908 << qMakePair(&object, QEvent::ChildAdded);
2909 QCOMPARE(spy.eventList(), expected);
2912 QCoreApplication::processEvents();
2915 EventSpy::EventList()
2916 << qMakePair(&object, QEvent::Type(QEvent::User + 1))
2917 << qMakePair(&object, QEvent::Type(QEvent::User + 2));
2918 QCOMPARE(spy.eventList(), expected);
2922 // 2 children, but one is reparented away, so we expect:
2923 // 2 ChildAdded, 1 ChildRemoved
2926 object.installEventFilter(&spy);
2928 QCoreApplication::postEvent(&object, new QEvent(QEvent::Type(QEvent::User + 1)));
2930 QObject child1(&object);
2932 child2.setParent(&object);
2933 child2.setParent(0);
2935 QCoreApplication::postEvent(&object, new QEvent(QEvent::Type(QEvent::User + 2)));
2938 EventSpy::EventList()
2939 << qMakePair(&object, QEvent::ChildAdded)
2940 << qMakePair(&object, QEvent::ChildAdded)
2941 << qMakePair(&object, QEvent::ChildRemoved);
2942 QCOMPARE(spy.eventList(), expected);
2945 QCoreApplication::processEvents();
2948 EventSpy::EventList()
2949 << qMakePair(&object, QEvent::Type(QEvent::User + 1))
2950 << qMakePair(&object, QEvent::Type(QEvent::User + 2));
2951 QCOMPARE(spy.eventList(), expected);
2955 void tst_QObject::installEventFilter()
2957 QEvent event(QEvent::User);
2958 EventSpy::EventList expected;
2962 object.installEventFilter(&spy);
2964 // nothing special, should just work
2965 QCoreApplication::sendEvent(&object, &event);
2967 EventSpy::EventList()
2968 << qMakePair(&object, QEvent::User);
2969 QCOMPARE(spy.eventList(), expected);
2972 // moving the filter causes QCoreApplication to skip the filter
2973 spy.moveToThread(0);
2974 QTest::ignoreMessage(QtWarningMsg, "QCoreApplication: Object event filter cannot be in a different thread.");
2975 QCoreApplication::sendEvent(&object, &event);
2976 QVERIFY(spy.eventList().isEmpty());
2978 // move it back, and the filter works again
2979 spy.moveToThread(object.thread());
2980 QCoreApplication::sendEvent(&object, &event);
2982 EventSpy::EventList()
2983 << qMakePair(&object, QEvent::User);
2984 QCOMPARE(spy.eventList(), expected);
2987 // cannot install an event filter that lives in a different thread
2988 object.removeEventFilter(&spy);
2989 spy.moveToThread(0);
2990 QTest::ignoreMessage(QtWarningMsg, "QObject::installEventFilter(): Cannot filter events for objects in a different thread.");
2991 object.installEventFilter(&spy);
2992 QCoreApplication::sendEvent(&object, &event);
2993 QVERIFY(spy.eventList().isEmpty());
2996 class EmitThread : public QThread
3006 namespace QObjectTest { // Do not clash with WinAPI 'DeleteObject'
3007 class DeleteObject : public QObject
3017 void relaySignalAndProcessEvents()
3019 emit relayedSignal();
3020 QCoreApplication::processEvents();
3024 void relayedSignal();
3026 } // namespace QObjectTest
3028 void tst_QObject::deleteSelfInSlot()
3031 SenderObject sender;
3032 QObjectTest::DeleteObject *receiver = new QObjectTest::DeleteObject();
3033 receiver->connect(&sender,
3036 Qt::BlockingQueuedConnection);
3039 receiver->moveToThread(&thread);
3040 thread.connect(receiver, SIGNAL(destroyed()), SLOT(quit()), Qt::DirectConnection);
3043 QPointer<QObjectTest::DeleteObject> p = receiver;
3044 sender.emitSignal1();
3045 QVERIFY(p.isNull());
3047 QVERIFY(thread.wait(10000));
3051 SenderObject sender;
3052 QObjectTest::DeleteObject *receiver = new QObjectTest::DeleteObject();
3053 receiver->connect(&sender,
3055 SLOT(relaySignalAndProcessEvents()),
3056 Qt::BlockingQueuedConnection);
3057 receiver->connect(receiver,
3058 SIGNAL(relayedSignal()),
3060 Qt::QueuedConnection);
3063 receiver->moveToThread(&thread);
3064 thread.connect(receiver, SIGNAL(destroyed()), SLOT(quit()), Qt::DirectConnection);
3067 QPointer<QObjectTest::DeleteObject> p = receiver;
3068 sender.emitSignal1();
3069 QVERIFY(p.isNull());
3071 QVERIFY(thread.wait(10000));
3076 QObjectTest::DeleteObject *receiver = new QObjectTest::DeleteObject();
3077 connect(&sender, SIGNAL(work()), receiver, SLOT(deleteSelf()), Qt::DirectConnection);
3078 QPointer<QObjectTest::DeleteObject> p = receiver;
3080 QVERIFY(sender.wait(10000));
3081 QVERIFY(p.isNull());
3085 class DisconnectObject : public QObject
3090 void disconnectSelf()
3092 disconnect(sender(), 0, this, 0);
3095 void relaySignalAndProcessEvents()
3097 emit relayedSignal();
3098 QCoreApplication::processEvents();
3102 void relayedSignal();
3105 void tst_QObject::disconnectSelfInSlotAndDeleteAfterEmit()
3108 SenderObject sender;
3109 DisconnectObject *receiver = new DisconnectObject();
3110 receiver->connect(&sender, SIGNAL(signal1()), SLOT(disconnectSelf()));
3111 sender.emitSignal1AfterRecursion();
3116 SenderObject sender;
3117 DisconnectObject *receiver = new DisconnectObject();
3118 receiver->connect(&sender,
3120 SLOT(disconnectSelf()),
3121 Qt::BlockingQueuedConnection);
3124 receiver->moveToThread(&thread);
3125 thread.connect(receiver, SIGNAL(destroyed()), SLOT(quit()), Qt::DirectConnection);
3128 QPointer<DisconnectObject> p = receiver;
3129 sender.emitSignal1();
3130 QVERIFY(!p.isNull());
3132 receiver->deleteLater();
3134 QVERIFY(thread.wait(10000));
3135 QVERIFY(p.isNull());
3139 SenderObject sender;
3140 DisconnectObject *receiver = new DisconnectObject();
3141 receiver->connect(&sender,
3143 SLOT(relaySignalAndProcessEvents()),
3144 Qt::BlockingQueuedConnection);
3145 receiver->connect(receiver,
3146 SIGNAL(relayedSignal()),
3147 SLOT(disconnectSelf()),
3148 Qt::QueuedConnection);
3151 receiver->moveToThread(&thread);
3152 thread.connect(receiver, SIGNAL(destroyed()), SLOT(quit()), Qt::DirectConnection);
3155 QPointer<DisconnectObject> p = receiver;
3156 sender.emitSignal1();
3157 QVERIFY(!p.isNull());
3159 receiver->deleteLater();
3161 QVERIFY(thread.wait(10000));
3162 QVERIFY(p.isNull());
3166 void tst_QObject::dumpObjectInfo()
3169 QObject::connect(&a, SIGNAL(destroyed(QObject *)), &b, SLOT(deleteLater()));
3171 a.dumpObjectInfo(); // should not crash
3174 class ConnectToSender : public QObject
3177 void uselessSlot() { count++; }
3179 void harmfullSlot() {
3180 //this used to crash
3181 connect(sender(), SIGNAL(signal4()), this, SLOT(uselessSlot()));
3182 //play a little bit with the memory in order to really get a segfault.
3183 connect(sender(), SIGNAL(signal1()), this, SLOT(uselessSlot()));
3184 QList<double>() << 45 << 78 << 65 << 121 << 45 << 78 << 12;
3190 void tst_QObject::connectToSender()
3195 QObject::connect(&s, SIGNAL(signal1()), &r, SLOT(harmfullSlot()));
3196 QObject::connect(&s, SIGNAL(signal1()), &r, SLOT(uselessSlot()));
3200 QCOMPARE(r.count, 1);
3202 QCOMPARE(r.count, 2);
3205 void tst_QObject::qobjectConstCast()
3209 QObject *ptr = &obj;
3210 const QObject *cptr = &obj;
3212 QVERIFY(qobject_cast<FooObject *>(ptr));
3213 QVERIFY(qobject_cast<const FooObject *>(cptr));
3216 void tst_QObject::uniqConnection()
3218 SenderObject *s = new SenderObject;
3219 ReceiverObject *r1 = new ReceiverObject;
3220 ReceiverObject *r2 = new ReceiverObject;
3223 ReceiverObject::sequence = 0;
3225 QVERIFY( connect( s, SIGNAL( signal1() ), r1, SLOT( slot1() ) , Qt::UniqueConnection) );
3226 QVERIFY( connect( s, SIGNAL( signal1() ), r2, SLOT( slot1() ) , Qt::UniqueConnection) );
3227 QVERIFY( connect( s, SIGNAL( signal1() ), r1, SLOT( slot3() ) , Qt::UniqueConnection) );
3228 QVERIFY( connect( s, SIGNAL( signal3() ), r1, SLOT( slot3() ) , Qt::UniqueConnection) );
3235 QCOMPARE( r1->count_slot1, 1 );
3236 QCOMPARE( r1->count_slot2, 0 );
3237 QCOMPARE( r1->count_slot3, 2 );
3238 QCOMPARE( r1->count_slot4, 0 );
3239 QCOMPARE( r2->count_slot1, 1 );
3240 QCOMPARE( r2->count_slot2, 0 );
3241 QCOMPARE( r2->count_slot3, 0 );
3242 QCOMPARE( r2->count_slot4, 0 );
3243 QCOMPARE( r1->sequence_slot1, 1 );
3244 QCOMPARE( r2->sequence_slot1, 2 );
3245 QCOMPARE( r1->sequence_slot3, 4 );
3249 ReceiverObject::sequence = 0;
3251 QVERIFY( connect( s, SIGNAL( signal4() ), r1, SLOT( slot4() ) , Qt::UniqueConnection) );
3252 QVERIFY( connect( s, SIGNAL( signal4() ), r2, SLOT( slot4() ) , Qt::UniqueConnection) );
3253 QVERIFY(!connect( s, SIGNAL( signal4() ), r2, SLOT( slot4() ) , Qt::UniqueConnection) );
3254 QVERIFY( connect( s, SIGNAL( signal1() ), r2, SLOT( slot4() ) , Qt::UniqueConnection) );
3255 QVERIFY(!connect( s, SIGNAL( signal4() ), r1, SLOT( slot4() ) , Qt::UniqueConnection) );
3258 QCOMPARE( r1->count_slot4, 1 );
3259 QCOMPARE( r2->count_slot4, 1 );
3260 QCOMPARE( r1->sequence_slot4, 1 );
3261 QCOMPARE( r2->sequence_slot4, 2 );
3265 ReceiverObject::sequence = 0;
3267 connect( s, SIGNAL( signal4() ), r1, SLOT( slot4() ) );
3270 QCOMPARE( r1->count_slot4, 2 );
3271 QCOMPARE( r2->count_slot4, 1 );
3272 QCOMPARE( r1->sequence_slot4, 3 );
3273 QCOMPARE( r2->sequence_slot4, 2 );
3280 void tst_QObject::uniqConnectionPtr()
3282 SenderObject *s = new SenderObject;
3283 ReceiverObject *r1 = new ReceiverObject;
3284 ReceiverObject *r2 = new ReceiverObject;
3287 ReceiverObject::sequence = 0;
3289 QVERIFY( connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 , Qt::UniqueConnection) );
3290 QVERIFY( connect( s, &SenderObject::signal1, r2, &ReceiverObject::slot1 , Qt::UniqueConnection) );
3291 QVERIFY( connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot3 , Qt::UniqueConnection) );
3292 QVERIFY( connect( s, &SenderObject::signal3, r1, &ReceiverObject::slot3 , Qt::UniqueConnection) );
3299 QCOMPARE( r1->count_slot1, 1 );
3300 QCOMPARE( r1->count_slot2, 0 );
3301 QCOMPARE( r1->count_slot3, 2 );
3302 QCOMPARE( r1->count_slot4, 0 );
3303 QCOMPARE( r2->count_slot1, 1 );
3304 QCOMPARE( r2->count_slot2, 0 );
3305 QCOMPARE( r2->count_slot3, 0 );
3306 QCOMPARE( r2->count_slot4, 0 );
3307 QCOMPARE( r1->sequence_slot1, 1 );
3308 QCOMPARE( r2->sequence_slot1, 2 );
3309 QCOMPARE( r1->sequence_slot3, 4 );
3313 ReceiverObject::sequence = 0;
3315 QVERIFY( connect( s, &SenderObject::signal4, r1, &ReceiverObject::slot4 , Qt::UniqueConnection) );
3316 QVERIFY( connect( s, &SenderObject::signal4, r2, &ReceiverObject::slot4 , Qt::UniqueConnection) );
3317 QVERIFY(!connect( s, &SenderObject::signal4, r2, &ReceiverObject::slot4 , Qt::UniqueConnection) );
3318 QVERIFY( connect( s, &SenderObject::signal1, r2, &ReceiverObject::slot4 , Qt::UniqueConnection) );
3319 QVERIFY(!connect( s, &SenderObject::signal4, r1, &ReceiverObject::slot4 , Qt::UniqueConnection) );
3322 QCOMPARE( r1->count_slot4, 1 );
3323 QCOMPARE( r2->count_slot4, 1 );
3324 QCOMPARE( r1->sequence_slot4, 1 );
3325 QCOMPARE( r2->sequence_slot4, 2 );
3329 ReceiverObject::sequence = 0;
3331 connect( s, &SenderObject::signal4, r1, &ReceiverObject::slot4 );
3334 QCOMPARE( r1->count_slot4, 2 );
3335 QCOMPARE( r2->count_slot4, 1 );
3336 QCOMPARE( r1->sequence_slot4, 3 );
3337 QCOMPARE( r2->sequence_slot4, 2 );
3344 void tst_QObject::interfaceIid()
3346 QCOMPARE(QByteArray(qobject_interface_iid<Foo::Bleh *>()),
3347 QByteArray(Bleh_iid));
3348 QCOMPARE(QByteArray(qobject_interface_iid<Foo::Bar *>()),
3349 QByteArray("com.qtest.foobar"));
3350 QCOMPARE(QByteArray(qobject_interface_iid<FooObject *>()),
3354 void tst_QObject::deleteQObjectWhenDeletingEvent()
3356 // This is a regression test for an old bug that used to deadlock
3357 // when the QObject from the event was destroyed.
3359 struct MyEvent : public QEvent
3361 MyEvent() : QEvent(QEvent::User) { }
3366 QGuiApplication::postEvent(&o, new MyEvent);
3367 QCoreApplication::removePostedEvents(&o); // here you would get a deadlock
3370 class OverloadObject : public QObject
3372 friend class tst_QObject;
3375 void sig(int i, char c, qreal m = 12);
3376 void sig(int i, int j = 12);
3377 void sig(QObject *o, QObject *p, QObject *q = 0, QObject *r = 0) const;
3378 void other(int a = 0);
3379 void sig(QObject *o, OverloadObject *p = 0, QObject *q = 0, QObject *r = 0);
3380 void sig(double r = 0.5);
3382 void slo(int i, int j = 43)
3388 void slo(QObject *o, QObject *p = qApp, QObject *q = qApp, QObject *r = qApp)
3411 void tst_QObject::overloads()
3413 OverloadObject obj1;
3414 OverloadObject obj2;
3419 connect (&obj1, SIGNAL(sig(int)) , &obj1, SLOT(slo(int)));
3420 connect (&obj1, SIGNAL(sig(QObject *, QObject *, QObject *)) , &obj1, SLOT(slo(QObject * , QObject *, QObject *)));
3422 connect (&obj1, SIGNAL(sig(QObject *, QObject *, QObject *, QObject *)) , &obj2, SLOT(slo(QObject * , QObject *, QObject *)));
3423 connect (&obj1, SIGNAL(sig(QObject *)) , &obj2, SLOT(slo()));
3424 connect (&obj1, SIGNAL(sig(int, int)) , &obj2, SLOT(slo(int, int)));
3426 emit obj1.sig(0.5); //connected to nothing
3427 emit obj1.sig(1, 'a'); //connected to nothing
3428 QCOMPARE(obj1.s_num, 0);
3429 QCOMPARE(obj2.s_num, 0);
3431 emit obj1.sig(1); //this signal is connected
3432 QCOMPARE(obj1.s_num, 1);
3433 QCOMPARE(obj1.i1_num, 1);
3434 QCOMPARE(obj1.i2_num, 43); //default argument of the slot
3436 QCOMPARE(obj2.s_num, 1);
3437 QCOMPARE(obj2.i1_num, 1);
3438 QCOMPARE(obj2.i2_num, 12); //default argument of the signal
3441 emit obj1.sig(&obj2); //this signal is conencted to obj2
3442 QCOMPARE(obj1.s_num, 1);
3443 QCOMPARE(obj2.s_num, 101);
3444 emit obj1.sig(&obj2, &obj3); //this signal is connected
3445 QCOMPARE(obj1.s_num, 11);
3446 QCOMPARE(obj1.o1_obj, (QObject *)&obj2);
3447 QCOMPARE(obj1.o2_obj, &obj3);
3448 QCOMPARE(obj1.o3_obj, (QObject *)0); //default arg of the signal
3449 QCOMPARE(obj1.o4_obj, (QObject *)qApp); //default arg of the slot
3451 QCOMPARE(obj2.s_num, 111);
3452 QCOMPARE(obj2.o1_obj, (QObject *)&obj2);
3453 QCOMPARE(obj2.o2_obj, &obj3);
3454 QCOMPARE(obj2.o3_obj, (QObject *)0); //default arg of the signal
3455 QCOMPARE(obj2.o4_obj, (QObject *)qApp); //default arg of the slot
3458 class ManySignals : public QObject
3460 friend class tst_QObject;
3462 void sig00(); void sig01(); void sig02(); void sig03(); void sig04();
3463 void sig05(); void sig06(); void sig07(); void sig08(); void sig09();
3464 void sig10(); void sig11(); void sig12(); void sig13(); void sig14();
3465 void sig15(); void sig16(); void sig17(); void sig18(); void sig19();
3466 void sig20(); void sig21(); void sig22(); void sig23(); void sig24();
3467 void sig25(); void sig26(); void sig27(); void sig28(); void sig29();
3468 void sig30(); void sig31(); void sig32(); void sig33(); void sig34();
3469 void sig35(); void sig36(); void sig37(); void sig38(); void sig39();
3470 void sig40(); void sig41(); void sig42(); void sig43(); void sig44();
3471 void sig45(); void sig46(); void sig47(); void sig48(); void sig49();
3472 void sig50(); void sig51(); void sig52(); void sig53(); void sig54();
3473 void sig55(); void sig56(); void sig57(); void sig58(); void sig59();
3474 void sig60(); void sig61(); void sig62(); void sig63(); void sig64();
3475 void sig65(); void sig66(); void sig67(); void sig68(); void sig69();
3478 void received() { rec++; }
3484 void tst_QObject::isSignalConnected()
3488 #ifdef QT_BUILD_INTERNAL
3489 QObjectPrivate *priv = QObjectPrivate::get(&o);
3490 QVERIFY(!priv->isSignalConnected(priv->signalIndex("destroyed()")));
3491 QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig00()")));
3492 QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig05()")));
3493 QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig15()")));
3494 QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig29()")));
3495 QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig60()")));
3498 QObject::connect(&o, SIGNAL(sig00()), &o, SIGNAL(sig69()));
3499 QObject::connect(&o, SIGNAL(sig34()), &o, SIGNAL(sig03()));
3500 QObject::connect(&o, SIGNAL(sig69()), &o, SIGNAL(sig34()));
3501 QObject::connect(&o, SIGNAL(sig03()), &o, SIGNAL(sig18()));
3503 #ifdef QT_BUILD_INTERNAL
3504 QVERIFY(!priv->isSignalConnected(priv->signalIndex("destroyed()")));
3505 QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig05()")));
3506 QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig15()")));
3507 QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig29()")));
3509 QVERIFY(priv->isSignalConnected(priv->signalIndex("sig00()")));
3510 QVERIFY(priv->isSignalConnected(priv->signalIndex("sig03()")));
3511 QVERIFY(priv->isSignalConnected(priv->signalIndex("sig34()")));
3512 QVERIFY(priv->isSignalConnected(priv->signalIndex("sig69()")));
3513 QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig18()")));
3516 QObject::connect(&o, SIGNAL(sig18()), &o, SIGNAL(sig29()));
3517 QObject::connect(&o, SIGNAL(sig29()), &o, SIGNAL(sig62()));
3518 QObject::connect(&o, SIGNAL(sig62()), &o, SIGNAL(sig28()));
3519 QObject::connect(&o, SIGNAL(sig28()), &o, SIGNAL(sig27()));
3521 #ifdef QT_BUILD_INTERNAL
3522 QVERIFY(priv->isSignalConnected(priv->signalIndex("sig18()")));
3523 QVERIFY(priv->isSignalConnected(priv->signalIndex("sig62()")));
3524 QVERIFY(priv->isSignalConnected(priv->signalIndex("sig28()")));
3525 QVERIFY(priv->isSignalConnected(priv->signalIndex("sig69()")));
3526 QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig27()")));
3534 QObject::connect(&o, SIGNAL(sig27()), &o, SLOT(received()));
3536 #ifdef QT_BUILD_INTERNAL
3537 QVERIFY(priv->isSignalConnected(priv->signalIndex("sig00()")));
3538 QVERIFY(priv->isSignalConnected(priv->signalIndex("sig03()")));
3539 QVERIFY(priv->isSignalConnected(priv->signalIndex("sig34()")));
3540 QVERIFY(priv->isSignalConnected(priv->signalIndex("sig18()")));
3541 QVERIFY(priv->isSignalConnected(priv->signalIndex("sig62()")));
3542 QVERIFY(priv->isSignalConnected(priv->signalIndex("sig28()")));
3543 QVERIFY(priv->isSignalConnected(priv->signalIndex("sig69()")));
3544 QVERIFY(priv->isSignalConnected(priv->signalIndex("sig27()")));
3546 QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig04()")));
3547 QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig21()")));
3548 QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig25()")));
3549 QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig55()")));
3560 void tst_QObject::qMetaObjectConnect()
3562 SenderObject *s = new SenderObject;
3563 ReceiverObject *r1 = new ReceiverObject;
3564 ReceiverObject *r2 = new ReceiverObject;
3567 ReceiverObject::sequence = 0;
3569 int signal1Index = s->metaObject()->indexOfSignal("signal1()");
3570 int signal3Index = s->metaObject()->indexOfSignal("signal3()");
3571 int slot1Index = r1->metaObject()->indexOfSlot("slot1()");
3572 int slot2Index = r1->metaObject()->indexOfSlot("slot2()");
3573 int slot3Index = r1->metaObject()->indexOfSlot("slot3()");
3575 QVERIFY(slot1Index > 0);
3576 QVERIFY(slot2Index > 0);
3577 QVERIFY(slot3Index > 0);
3579 QVERIFY( QMetaObject::connect( s, signal1Index, r1, slot1Index) );
3580 QVERIFY( QMetaObject::connect( s, signal3Index, r2, slot3Index) );
3581 QVERIFY( QMetaObject::connect( s, -1, r2, slot2Index) );
3583 QCOMPARE( r1->count_slot1, 0 );
3584 QCOMPARE( r1->count_slot2, 0 );
3585 QCOMPARE( r1->count_slot3, 0 );
3586 QCOMPARE( r2->count_slot1, 0 );
3587 QCOMPARE( r2->count_slot2, 0 );
3588 QCOMPARE( r2->count_slot3, 0 );
3592 QCOMPARE( r1->count_slot1, 1 );
3593 QCOMPARE( r1->count_slot2, 0 );
3594 QCOMPARE( r1->count_slot3, 0 );
3595 QCOMPARE( r2->count_slot1, 0 );
3596 QCOMPARE( r2->count_slot2, 1 );
3597 QCOMPARE( r2->count_slot3, 0 );
3603 QCOMPARE( r1->count_slot1, 1 );
3604 QCOMPARE( r1->count_slot2, 0 );
3605 QCOMPARE( r1->count_slot3, 0 );
3606 QCOMPARE( r2->count_slot1, 0 );
3607 QCOMPARE( r2->count_slot2, 4 );
3608 QCOMPARE( r2->count_slot3, 1 );
3610 QVERIFY( QMetaObject::disconnect( s, signal1Index, r1, slot1Index) );
3611 QVERIFY( QMetaObject::disconnect( s, signal3Index, r2, slot3Index) );
3612 QVERIFY( QMetaObject::disconnect( s, -1, r2, slot2Index) );
3619 QCOMPARE( r1->count_slot1, 1 );
3620 QCOMPARE( r1->count_slot2, 0 );
3621 QCOMPARE( r1->count_slot3, 0 );
3622 QCOMPARE( r2->count_slot1, 0 );
3623 QCOMPARE( r2->count_slot2, 4 );
3624 QCOMPARE( r2->count_slot3, 1 );
3626 //some "dynamic" signal
3627 QVERIFY( QMetaObject::connect( s, s->metaObject()->methodOffset() + 20, r1, slot3Index) );
3628 QVERIFY( QMetaObject::connect( s, s->metaObject()->methodOffset() + 35, r2, slot1Index) );
3629 QVERIFY( QMetaObject::connect( s, -1, r1, slot2Index) );
3634 void *args[] = { 0 , 0 };
3635 QMetaObject::activate(s, s->metaObject()->methodOffset() + 20, args);
3636 QMetaObject::activate(s, s->metaObject()->methodOffset() + 48, args);
3637 QCOMPARE( r1->count_slot1, 0 );
3638 QCOMPARE( r1->count_slot2, 2 );
3639 QCOMPARE( r1->count_slot3, 1 );
3640 QCOMPARE( r2->count_slot1, 0 );
3641 QCOMPARE( r2->count_slot2, 0 );
3642 QCOMPARE( r2->count_slot3, 0 );
3644 QMetaObject::activate(s, s->metaObject()->methodOffset() + 35, args);
3648 QCOMPARE( r1->count_slot1, 0 );
3649 QCOMPARE( r1->count_slot2, 5 );
3650 QCOMPARE( r1->count_slot3, 1 );
3651 QCOMPARE( r2->count_slot1, 1 );
3652 QCOMPARE( r2->count_slot2, 0 );
3653 QCOMPARE( r2->count_slot3, 0 );
3659 #define SIGNAL_INDEX(S) obj1.metaObject()->indexOfSignal(QMetaObject::normalizedSignature(#S))
3660 OverloadObject obj1;
3663 QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(int)) , r1, slot1Index);
3664 QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(QObject *, QObject *, QObject *)) , r2, slot1Index);
3666 QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(QObject *, QObject *, QObject *, QObject *)) , r1, slot2Index);
3667 QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(QObject *)) , r2, slot2Index);
3668 QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(int, int)) , r1, slot3Index);
3670 emit obj1.sig(0.5); //connected to nothing
3671 emit obj1.sig(1, 'a'); //connected to nothing
3672 QCOMPARE( r1->count_slot1, 0 );
3673 QCOMPARE( r1->count_slot2, 0 );
3674 QCOMPARE( r1->count_slot3, 0 );
3675 QCOMPARE( r2->count_slot1, 0 );
3676 QCOMPARE( r2->count_slot2, 0 );
3677 QCOMPARE( r2->count_slot3, 0 );
3679 emit obj1.sig(1); //this signal is connected
3680 emit obj1.sig(&obj2);
3682 QCOMPARE( r1->count_slot1, 1 );
3683 QCOMPARE( r1->count_slot2, 0 );
3684 QCOMPARE( r1->count_slot3, 1 );
3685 QCOMPARE( r2->count_slot1, 0 );
3686 QCOMPARE( r2->count_slot2, 1 );
3687 QCOMPARE( r2->count_slot3, 0 );
3689 emit obj1.sig(&obj2, &obj3); //this signal is connected
3691 QCOMPARE( r1->count_slot1, 1 );
3692 QCOMPARE( r1->count_slot2, 1 );
3693 QCOMPARE( r1->count_slot3, 1 );
3694 QCOMPARE( r2->count_slot1, 1 );
3695 QCOMPARE( r2->count_slot2, 1 );
3696 QCOMPARE( r2->count_slot3, 0 );
3703 void tst_QObject::qMetaObjectDisconnectOne()
3705 SenderObject *s = new SenderObject;
3706 ReceiverObject *r1 = new ReceiverObject;
3708 int signal1Index = s->metaObject()->indexOfSignal("signal1()");
3709 int signal3Index = s->metaObject()->indexOfSignal("signal3()");
3710 int slot1Index = r1->metaObject()->indexOfSlot("slot1()");
3711 int slot2Index = r1->metaObject()->indexOfSlot("slot2()");
3713 QVERIFY(signal1Index > 0);
3714 QVERIFY(signal3Index > 0);
3715 QVERIFY(slot1Index > 0);
3716 QVERIFY(slot2Index > 0);
3718 QVERIFY( QMetaObject::connect(s, signal1Index, r1, slot1Index) );
3719 QVERIFY( QMetaObject::connect(s, signal3Index, r1, slot2Index) );
3720 QVERIFY( QMetaObject::connect(s, signal3Index, r1, slot2Index) );
3721 QVERIFY( QMetaObject::connect(s, signal3Index, r1, slot2Index) );
3724 QCOMPARE( r1->count_slot1, 0 );
3725 QCOMPARE( r1->count_slot2, 0 );
3728 QCOMPARE( r1->count_slot1, 1 );
3729 QCOMPARE( r1->count_slot2, 0 );
3732 QCOMPARE( r1->count_slot1, 1 );
3733 QCOMPARE( r1->count_slot2, 3 );
3736 QVERIFY( QMetaObject::disconnectOne(s, signal1Index, r1, slot1Index) );
3737 QVERIFY( QMetaObject::disconnectOne(s, signal3Index, r1, slot2Index) );
3740 QCOMPARE( r1->count_slot1, 0 );
3741 QCOMPARE( r1->count_slot2, 0 );
3744 QCOMPARE( r1->count_slot1, 0 );
3745 QCOMPARE( r1->count_slot2, 2 );
3748 QVERIFY( false == QMetaObject::disconnectOne(s, signal1Index, r1, slot1Index) );
3749 QVERIFY( QMetaObject::disconnectOne(s, signal3Index, r1, slot2Index) );
3752 QCOMPARE( r1->count_slot1, 0 );
3753 QCOMPARE( r1->count_slot2, 0 );
3756 QCOMPARE( r1->count_slot1, 0 );
3757 QCOMPARE( r1->count_slot2, 1 );
3760 QVERIFY( false == QMetaObject::disconnectOne(s, signal1Index, r1, slot1Index) );
3761 QVERIFY( QMetaObject::disconnectOne(s, signal3Index, r1, slot2Index) );
3764 QCOMPARE( r1->count_slot1, 0 );
3765 QCOMPARE( r1->count_slot2, 0 );
3768 QCOMPARE( r1->count_slot1, 0 );
3769 QCOMPARE( r1->count_slot2, 0 );
3775 class ConfusingObject : public SenderObject
3778 void signal1() { s++; }
3783 ConfusingObject() : s(0) {}
3784 friend class tst_QObject;
3787 void tst_QObject::sameName()
3789 ConfusingObject c1, c2;
3790 QVERIFY(connect(&c1, SIGNAL(signal1()), &c1, SLOT(signal1())));
3794 QVERIFY(connect(&c2, SIGNAL(signal1()), &c1, SIGNAL(signal1())));
3798 QVERIFY(connect(&c2, SIGNAL(aPublicSlot()), &c1, SLOT(signal1())));
3800 QCOMPARE(c2.aPublicSlotCalled, 0);
3801 QCOMPARE(c1.aPublicSlotCalled, 0);
3804 QVERIFY(connect(&c2, SIGNAL(aPublicSlot()), &c1, SLOT(aPublicSlot())));
3806 QCOMPARE(c2.aPublicSlotCalled, 0);
3807 QCOMPARE(c1.aPublicSlotCalled, 1);
3811 void tst_QObject::connectByMetaMethods()
3815 const QMetaObject *smeta = s.metaObject();
3816 const QMetaObject *rmeta = r.metaObject();
3817 int sigIndx = smeta->indexOfSignal(QMetaObject::normalizedSignature("signal1()"));
3818 int slotIndx = rmeta->indexOfSlot(QMetaObject::normalizedSignature("slot1()"));
3819 QVERIFY( sigIndx != -1 );
3820 QVERIFY( slotIndx != -1 );
3821 QMetaMethod signal = smeta->method(sigIndx);
3822 QMetaMethod slot = rmeta->method(slotIndx);
3824 QVERIFY(connect(&s,signal, &r,slot));
3826 QVERIFY(!r.called(1));
3828 QVERIFY(r.called(1));
3831 void tst_QObject::connectByMetaMethodSlotInsteadOfSignal()
3835 const QMetaObject *smeta = s.metaObject();
3836 const QMetaObject *rmeta = r.metaObject();
3837 int badIndx = smeta->indexOfSlot(QMetaObject::normalizedSignature("aPublicSlot()"));
3838 int slotIndx = rmeta->indexOfSlot(QMetaObject::normalizedSignature("slot1()"));
3839 QVERIFY( badIndx != -1 );
3840 QVERIFY( slotIndx != -1 );
3841 QMetaMethod badMethod = smeta->method(badIndx);
3842 QMetaMethod slot = rmeta->method(slotIndx);
3844 QTest::ignoreMessage(QtWarningMsg,"QObject::connect: Cannot connect SenderObject::aPublicSlot() to ReceiverObject::slot1()");
3845 QVERIFY(!connect(&s,badMethod, &r,slot));
3848 class Constructable: public QObject
3853 Q_INVOKABLE Constructable(){}
3857 void tst_QObject::connectConstructorByMetaMethod()
3864 const QMetaObject cmeta = Constructable::staticMetaObject;
3865 const QMetaObject *smeta = s.metaObject();
3866 const QMetaObject *rmeta = r.metaObject();
3867 int constructorIndx = cmeta.indexOfConstructor(QMetaObject::normalizedSignature("Constructable()"));
3868 int sigIndx = smeta->indexOfSignal(QMetaObject::normalizedSignature("signal1()"));
3869 int slotIndx = rmeta->indexOfSlot(QMetaObject::normalizedSignature("slot1()"));
3870 QVERIFY( constructorIndx != -1 );
3871 QVERIFY( sigIndx != -1 );
3872 QVERIFY( slotIndx != -1 );
3874 QMetaMethod constructor = cmeta.constructor(constructorIndx);
3875 QMetaMethod signal = smeta->method(sigIndx);
3876 QMetaMethod slot = rmeta->method(slotIndx);
3878 QTest::ignoreMessage(QtWarningMsg,"QObject::connect: Cannot connect Constructable::Constructable() to ReceiverObject::slot1()");
3879 QVERIFY(!connect(&sc,constructor, &r,slot));
3880 QTest::ignoreMessage(QtWarningMsg,"QObject::connect: Cannot connect SenderObject::signal1() to Constructable::Constructable()");
3881 QVERIFY(!connect(&s,signal, &rc,constructor));
3882 QTest::ignoreMessage(QtWarningMsg,"QObject::connect: Cannot connect Constructable::Constructable() to Constructable::Constructable()");
3883 QVERIFY(!connect(&sc,constructor, &rc,constructor));
3886 void tst_QObject::disconnectByMetaMethod()
3888 SenderObject *s = new SenderObject;
3889 ReceiverObject *r1 = new ReceiverObject;
3890 ReceiverObject *r2 = new ReceiverObject;
3892 QMetaMethod signal1 = s->metaObject()->method(
3893 s->metaObject()->indexOfMethod("signal1()"));
3894 QMetaMethod signal2 = s->metaObject()->method(
3895 s->metaObject()->indexOfMethod("signal2()"));
3896 QMetaMethod signal3 = s->metaObject()->method(
3897 s->metaObject()->indexOfMethod("signal3()"));
3899 QMetaMethod slot1 = r1->metaObject()->method(
3900 r1->metaObject()->indexOfMethod("slot1()"));
3901 QMetaMethod slot2 = r1->metaObject()->method(
3902 r1->metaObject()->indexOfMethod("slot2()"));
3903 QMetaMethod slot3 = r1->metaObject()->method(
3904 r1->metaObject()->indexOfMethod("slot3()"));
3905 QMetaMethod slot4 = r1->metaObject()->method(
3906 r1->metaObject()->indexOfMethod("slot4()"));
3908 connect(s, signal1, r1, slot1);
3912 QVERIFY(r1->called(1));
3915 // usual disconnect with all parameters given
3916 bool ret = QObject::disconnect(s, signal1, r1, slot1);
3920 QVERIFY(!r1->called(1));
3924 ret = QObject::disconnect(s, signal1, r1, slot1);
3929 connect( s, signal1, r1, slot1 );
3930 connect( s, signal1, r1, slot2 );
3931 connect( s, signal1, r1, slot3 );
3932 connect( s, signal2, r1, slot4 );
3934 // disconnect s's signal1() from all slots of r1
3935 QObject::disconnect(s, signal1, r1, QMetaMethod());
3940 QVERIFY(!r1->called(1));
3941 QVERIFY(!r1->called(2));
3942 QVERIFY(!r1->called(3));
3943 QVERIFY(r1->called(4));
3945 // make sure all is disconnected again
3946 QObject::disconnect(s, 0, r1, 0);
3948 connect(s, signal1, r1, slot1);
3949 connect(s, signal1, r2, slot1);
3950 connect(s, signal2, r1, slot2);
3951 connect(s, signal2, r2, slot2);
3952 connect(s, signal3, r1, slot3);
3953 connect(s, signal3, r2, slot3);
3955 // disconnect signal1() from all receivers
3956 QObject::disconnect(s, signal1, 0, QMetaMethod());
3961 QVERIFY(!r1->called(1));
3962 QVERIFY(!r2->called(1));
3963 QVERIFY(r1->called(2));
3964 QVERIFY(r2->called(2));
3965 QVERIFY(r1->called(2));
3966 QVERIFY(r2->called(2));
3971 // disconnect all signals of s from all receivers
3972 QObject::disconnect( s, 0, 0, 0 );
3974 connect( s, signal1, r1, slot1 );
3975 connect( s, signal1, r2, slot1 );
3977 // disconnect all signals from slot1 of r1
3978 QObject::disconnect(s, QMetaMethod(), r1, slot1);
3982 QVERIFY(!r1->called(1));
3983 QVERIFY(r2->called(1));
3990 void tst_QObject::disconnectNotSignalMetaMethod()
3995 connect(&s, SIGNAL(signal1()), &r, SLOT(slot1()));
3997 QMetaMethod slot = s.metaObject()->method(
3998 s.metaObject()->indexOfMethod("aPublicSlot()"));
4000 QTest::ignoreMessage(QtWarningMsg,"QObject::disconnect: Attempt to unbind non-signal SenderObject::aPublicSlot()");
4001 QVERIFY(!QObject::disconnect(&s, slot, &r, QMetaMethod()));
4004 class ThreadAffinityThread : public QThread
4007 SenderObject *sender;
4009 ThreadAffinityThread(SenderObject *sender)
4014 sender->emitSignal1();
4018 void tst_QObject::autoConnectionBehavior()
4020 SenderObject *sender = new SenderObject;
4021 ReceiverObject *receiver = new ReceiverObject;
4022 connect(sender, SIGNAL(signal1()), receiver, SLOT(slot1()));
4024 // at emit, currentThread == sender->thread(), currentThread == receiver->thread(), sender->thread() == receiver->thread()
4025 QVERIFY(!receiver->called(1));
4026 sender->emitSignal1();
4027 QVERIFY(receiver->called(1));
4030 // at emit, currentThread != sender->thread(), currentThread != receiver->thread(), sender->thread() == receiver->thread()
4031 ThreadAffinityThread emitThread1(sender);
4032 QVERIFY(!receiver->called(1));
4033 emitThread1.start();
4034 QVERIFY(emitThread1.wait(30000));
4035 QVERIFY(!receiver->called(1));
4036 QCoreApplication::sendPostedEvents(receiver, QEvent::MetaCall);
4037 QVERIFY(receiver->called(1));
4040 // at emit, currentThread == sender->thread(), currentThread != receiver->thread(), sender->thread() != receiver->thread()
4041 sender->moveToThread(&emitThread1);
4042 QVERIFY(!receiver->called(1));
4043 emitThread1.start();
4044 QVERIFY(emitThread1.wait(30000));
4045 QVERIFY(!receiver->called(1));
4046 QCoreApplication::sendPostedEvents(receiver, QEvent::MetaCall);
4047 QVERIFY(receiver->called(1));
4050 // at emit, currentThread != sender->thread(), currentThread == receiver->thread(), sender->thread() != receiver->thread()
4051 QVERIFY(!receiver->called(1));
4052 sender->emitSignal1();
4053 QVERIFY(receiver->called(1));
4056 // at emit, currentThread != sender->thread(), currentThread != receiver->thread(), sender->thread() != receiver->thread()
4057 ThreadAffinityThread emitThread2(sender);
4058 QThread receiverThread;
4059 QTimer *timer = new QTimer;
4060 timer->setSingleShot(true);
4061 timer->setInterval(100);
4062 connect(&receiverThread, SIGNAL(started()), timer, SLOT(start()));
4063 connect(timer, SIGNAL(timeout()), &receiverThread, SLOT(quit()), Qt::DirectConnection);
4064 connect(&receiverThread, SIGNAL(finished()), timer, SLOT(deleteLater()));
4065 timer->moveToThread(&receiverThread);
4067 receiver->moveToThread(&receiverThread);
4068 QVERIFY(!receiver->called(1));
4069 emitThread2.start();
4070 QVERIFY(emitThread2.wait(30000));
4071 QVERIFY(!receiver->called(1));
4072 receiverThread.start();
4073 QVERIFY(receiverThread.wait(30000));
4074 QVERIFY(receiver->called(1));
4081 class BaseDestroyed : public QObject
4083 QList<QString> fooList;
4086 BaseDestroyed() : destroyed(false)
4087 { fooList << "a" << "b"; }
4090 QVERIFY(!destroyed);
4097 QVERIFY(!destroyed);
4098 fooList << "c" << "d";
4102 static void processEvents()
4104 qApp->processEvents();
4107 void tst_QObject::baseDestroyed()
4111 connect(&d, SIGNAL(destroyed()), &d, SLOT(slotUseList()));
4112 //When d goes out of scope, slotUseList should not be called as the BaseDestroyed has
4113 // already been destroyed while ~QObject emit destroyed
4117 connect(&d, &QObject::destroyed, processEvents);
4118 QMetaObject::invokeMethod(&d, "slotUseList", Qt::QueuedConnection);
4119 //the destructor will call processEvents, that should not call the slotUseList
4123 void tst_QObject::pointerConnect()
4125 SenderObject *s = new SenderObject;
4126 ReceiverObject *r1 = new ReceiverObject;
4127 ReceiverObject *r2 = new ReceiverObject;
4130 ReceiverObject::sequence = 0;
4132 QVERIFY( connect( s, &SenderObject::signal1 , r1, &ReceiverObject::slot1 ) );
4133 QVERIFY( connect( s, &SenderObject::signal1 , r2, &ReceiverObject::slot1 ) );
4134 QVERIFY( connect( s, &SenderObject::signal1 , r1, &ReceiverObject::slot3 ) );
4135 QVERIFY( connect( s, &SenderObject::signal3 , r1, &ReceiverObject::slot3 ) );
4142 QCOMPARE( r1->count_slot1, 1 );
4143 QCOMPARE( r1->count_slot2, 0 );
4144 QCOMPARE( r1->count_slot3, 2 );
4145 QCOMPARE( r1->count_slot4, 0 );
4146 QCOMPARE( r2->count_slot1, 1 );
4147 QCOMPARE( r2->count_slot2, 0 );
4148 QCOMPARE( r2->count_slot3, 0 );
4149 QCOMPARE( r2->count_slot4, 0 );
4150 QCOMPARE( r1->sequence_slot1, 1 );
4151 QCOMPARE( r2->sequence_slot1, 2 );
4152 QCOMPARE( r1->sequence_slot3, 4 );
4156 ReceiverObject::sequence = 0;
4158 QVERIFY( connect( s, &SenderObject::signal4, r1, &ReceiverObject::slot4 ) );
4159 QVERIFY( connect( s, &SenderObject::signal4, r2, &ReceiverObject::slot4 ) );
4160 QVERIFY( connect( s, &SenderObject::signal1, r2, &ReceiverObject::slot4 ) );
4163 QCOMPARE( r1->count_slot4, 1 );
4164 QCOMPARE( r2->count_slot4, 1 );
4165 QCOMPARE( r1->sequence_slot4, 1 );
4166 QCOMPARE( r2->sequence_slot4, 2 );
4170 ReceiverObject::sequence = 0;
4172 connect( s, &SenderObject::signal4 , r1, &ReceiverObject::slot4 );
4175 QCOMPARE( r1->count_slot4, 2 );
4176 QCOMPARE( r2->count_slot4, 1 );
4177 QCOMPARE( r1->sequence_slot4, 3 );
4178 QCOMPARE( r2->sequence_slot4, 2 );
4180 QMetaObject::Connection con;
4182 QVERIFY(!QObject::disconnect(con));
4184 //connect a slot to a signal (== error)
4185 QTest::ignoreMessage(QtWarningMsg, "QObject::connect: signal not found in ReceiverObject");
4186 con = connect(r1, &ReceiverObject::slot4 , s, &SenderObject::signal4 );
4188 QVERIFY(!QObject::disconnect(con));
4195 void tst_QObject::pointerDisconnect()
4197 SenderObject *s = new SenderObject;
4198 ReceiverObject *r1 = new ReceiverObject;
4199 ReceiverObject *r2 = new ReceiverObject;
4201 connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 );
4203 connect( s, &SenderObject::signal2, r1, &ReceiverObject::slot2 );
4204 connect( s, &SenderObject::signal3, r1, &ReceiverObject::slot3 );
4205 connect( s, &SenderObject::signal4, r1, &ReceiverObject::slot4 );
4212 QVERIFY(r1->called(1));
4213 QVERIFY(r1->called(2));
4214 QVERIFY(r1->called(3));
4215 QVERIFY(r1->called(4));
4218 // usual disconnect with all parameters given
4219 bool ret = QObject::disconnect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 );
4223 QVERIFY(!r1->called(1));
4227 ret = QObject::disconnect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 );
4230 // disconnect all signals from s from all slots from r1
4231 QObject::disconnect( s, 0, r1, 0 );
4237 QVERIFY(!r1->called(2));
4238 QVERIFY(!r1->called(3));
4239 QVERIFY(!r1->called(4));
4242 connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 );
4243 connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot2 );
4244 connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot3 );
4245 connect( s, &SenderObject::signal2, r1, &ReceiverObject::slot4 );
4247 // disconnect s's signal1() from all slots of r1
4248 QObject::disconnect( s, &SenderObject::signal1, r1, 0 );
4253 QVERIFY(!r1->called(1));
4254 QVERIFY(!r1->called(2));
4255 QVERIFY(!r1->called(3));
4256 QVERIFY(r1->called(4));
4258 // make sure all is disconnected again
4259 QObject::disconnect( s, 0, r1, 0 );
4261 connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 );
4262 connect( s, &SenderObject::signal1, r2, &ReceiverObject::slot1 );
4263 connect( s, &SenderObject::signal2, r1, &ReceiverObject::slot2 );
4264 connect( s, &SenderObject::signal2, r2, &ReceiverObject::slot2 );
4265 connect( s, &SenderObject::signal3, r1, &ReceiverObject::slot3 );
4266 connect( s, &SenderObject::signal3, r2, &ReceiverObject::slot3 );
4268 // disconnect signal1() from all receivers
4269 QObject::disconnect( s, &SenderObject::signal1, 0, 0 );
4274 QVERIFY(!r1->called(1));
4275 QVERIFY(!r2->called(1));
4276 QVERIFY(r1->called(2));
4277 QVERIFY(r2->called(2));
4278 QVERIFY(r1->called(2));
4279 QVERIFY(r2->called(2));
4284 // disconnect all signals of s from all receivers
4285 QObject::disconnect( s, 0, 0, 0 );
4287 QVERIFY(!r1->called(2));
4288 QVERIFY(!r2->called(2));
4289 QVERIFY(!r1->called(2));
4290 QVERIFY(!r2->called(2));
4299 void tst_QObject::emitInDefinedOrderPointer()
4301 SenderObject sender;
4302 ReceiverObject receiver1, receiver2, receiver3, receiver4;
4304 QMetaObject::Connection h0 = connect(&sender, &SenderObject::signal1, &receiver1, &SequenceObject::slot1);
4305 QMetaObject::Connection h1 = connect(&sender, &SenderObject::signal1, &receiver2, &SequenceObject::slot1);
4308 connect(&sender, &SenderObject::signal1, &receiver3, &SequenceObject::slot1);
4309 connect(&sender, &SenderObject::signal1, &receiver4, &SequenceObject::slot1);
4310 connect(&sender, &SenderObject::signal1, &receiver1, &SequenceObject::slot2);
4311 connect(&sender, &SenderObject::signal1, &receiver2, &SequenceObject::slot2);
4312 connect(&sender, &SenderObject::signal1, &receiver3, &SequenceObject::slot2);
4313 connect(&sender, &SenderObject::signal1, &receiver4, &SequenceObject::slot2);
4316 ReceiverObject::sequence = sequence = 0;
4317 sender.emitSignal1();
4318 QCOMPARE(receiver1.sequence_slot1, ++sequence);
4319 QCOMPARE(receiver2.sequence_slot1, ++sequence);
4320 QCOMPARE(receiver3.sequence_slot1, ++sequence);
4321 QCOMPARE(receiver4.sequence_slot1, ++sequence);
4322 QCOMPARE(receiver1.sequence_slot2, ++sequence);
4323 QCOMPARE(receiver2.sequence_slot2, ++sequence);
4324 QCOMPARE(receiver3.sequence_slot2, ++sequence);
4325 QCOMPARE(receiver4.sequence_slot2, ++sequence);
4327 QObject::disconnect(h1);
4328 h1 = connect(&sender, &SenderObject::signal1, &receiver2, &SequenceObject::slot1);
4330 ReceiverObject::sequence = sequence = 0;
4331 sender.emitSignal1();
4332 QCOMPARE(receiver1.sequence_slot1, ++sequence);
4333 QCOMPARE(receiver3.sequence_slot1, ++sequence);
4334 QCOMPARE(receiver4.sequence_slot1, ++sequence);
4335 QCOMPARE(receiver1.sequence_slot2, ++sequence);
4336 QCOMPARE(receiver2.sequence_slot2, ++sequence);
4337 QCOMPARE(receiver3.sequence_slot2, ++sequence);
4338 QCOMPARE(receiver4.sequence_slot2, ++sequence);
4339 QCOMPARE(receiver2.sequence_slot1, ++sequence);
4341 QObject::disconnect(h0);
4342 h0 = connect(&sender, &SenderObject::signal1, &receiver1, &SequenceObject::slot1);
4344 ReceiverObject::sequence = sequence = 0;
4345 sender.emitSignal1();
4346 QCOMPARE(receiver3.sequence_slot1, ++sequence);
4347 QCOMPARE(receiver4.sequence_slot1, ++sequence);
4348 QCOMPARE(receiver1.sequence_slot2, ++sequence);
4349 QCOMPARE(receiver2.sequence_slot2, ++sequence);
4350 QCOMPARE(receiver3.sequence_slot2, ++sequence);
4351 QCOMPARE(receiver4.sequence_slot2, ++sequence);
4352 QCOMPARE(receiver2.sequence_slot1, ++sequence);
4353 QCOMPARE(receiver1.sequence_slot1, ++sequence);
4355 QVERIFY(QObject::disconnect(h0));
4356 QVERIFY(!QObject::disconnect(h0));
4360 void tst_QObject::customTypesPointer()
4363 CustomType t1(1, 2, 3);
4364 CustomType t2(2, 3, 4);
4367 QCustomTypeChecker checker;
4368 QCOMPARE(instanceCount, 4);
4370 connect(&checker, &QCustomTypeChecker::signal1, &checker, &QCustomTypeChecker::slot1,
4371 Qt::DirectConnection);
4372 QCOMPARE(checker.received.value(), 0);
4374 QCOMPARE(checker.received.value(), t1.value());
4375 checker.received = t0;
4378 checker.disconnect();
4380 int idx = qRegisterMetaType<CustomType>("CustomType");
4381 QCOMPARE(QMetaType::type("CustomType"), idx);
4383 connect(&checker, &QCustomTypeChecker::signal1, &checker, &QCustomTypeChecker::slot1,
4384 Qt::QueuedConnection);
4385 QCOMPARE(instanceCount, 4);
4387 QCOMPARE(instanceCount, 5);
4388 QCOMPARE(checker.received.value(), t0.value());
4390 QCoreApplication::processEvents();
4391 QCOMPARE(checker.received.value(), t2.value());
4392 QCOMPARE(instanceCount, 4);
4394 QVERIFY(QMetaType::isRegistered(idx));
4395 QCOMPARE(qRegisterMetaType<CustomType>("CustomType"), idx);
4396 QCOMPARE(QMetaType::type("CustomType"), idx);
4397 QVERIFY(QMetaType::isRegistered(idx));
4399 QCOMPARE(instanceCount, 3);
4402 void tst_QObject::connectCxx0x()
4404 SenderObject *s = new SenderObject;
4405 ReceiverObject *r1 = new ReceiverObject;
4407 QObject::connect(s, &SenderObject::signal1, r1, &ReceiverObject::slot1);
4408 QObject::connect(s, &SenderObject::signal3, r1, &ReceiverObject::slot2);
4409 QObject::connect(s, &SenderObject::signal3, r1, &ReceiverObject::slot2);
4410 QObject::connect(s, &SenderObject::signal3, r1, &ReceiverObject::slot2);
4413 QCOMPARE( r1->count_slot1, 0 );
4414 QCOMPARE( r1->count_slot2, 0 );
4417 QCOMPARE( r1->count_slot1, 1 );
4418 QCOMPARE( r1->count_slot2, 0 );
4421 QCOMPARE( r1->count_slot1, 1 );
4422 QCOMPARE( r1->count_slot2, 3 );
4424 // connect signal to signal
4425 QObject::connect(s, &SenderObject::signal2, s, &SenderObject::signal1);
4429 QCOMPARE( r1->count_slot1, 1 );
4436 void receiverFunction() { ++receivedCount; }
4438 void tst_QObject::connectToStaticCxx0x()
4440 SenderObject *s = new SenderObject;
4442 void (*receiver)() = receiverFunction;
4444 QObject::connect(s, &SenderObject::signal1, receiver);
4447 QCOMPARE(receivedCount, 1);
4449 QObject::connect(s, &SenderObject::signal1, receiver);
4452 QCOMPARE(receivedCount, 2);
4457 class LotsOfSignalsAndSlots: public QObject
4460 typedef void (*fptr)();
4464 void slot_vi(int) {}
4465 void slot_vii(int, int) {}
4466 void slot_viii(int, int, int) {}
4467 int slot_i() { return 0; }
4468 int slot_ii(int) { return 0; }
4469 int slot_iii(int, int) { return 0; }
4470 int slot_iiii(int, int, int) { return 0; }
4471 void slot_vRi(int &) {}
4472 void slot_vs(short) {}
4473 void slot_vRs(short&) {}
4474 /* #ifdef Q_COMPILER_RVALUE_REFS
4475 void slot_vOi(int &&) {}
4476 void slot_vOs(short &&) {}
4478 void slot_vPFvvE(fptr) {}
4480 static void static_slot_v() {}
4481 static void static_slot_vi(int) {}
4482 static void static_slot_vii(int, int) {}
4483 static void static_slot_viii(int, int, int) {}
4484 static int static_slot_i() { return 0; }
4485 static int static_slot_ii(int) { return 0; }
4486 static int static_slot_iii(int, int) { return 0; }
4487 static int static_slot_iiii(int, int, int) { return 0; }
4488 static void static_slot_vRi(int &) {}
4489 static void static_slot_vs(short) {}
4490 static void static_slot_vRs(short&) {}
4491 /* #if defined(Q_COMPILER_RVALUE_REFS) || defined(QT_ENABLE_CXX0X)
4492 static void static_slot_vOi(int &&) {}
4493 static void static_slot_vOs(short &&) {}
4495 static void static_slot_vPFvvE(fptr) {}
4499 void signal_vi(int);
4500 void signal_vii(int, int);
4501 void signal_viii(int, int, int);
4502 void signal_vRi(int &);
4503 void signal_vs(short);
4504 void signal_vRs(short &);
4505 /* #if defined(Q_COMPILER_RVALUE_REFS) || defined(QT_ENABLE_CXX0X)
4506 void signal_vOi(int &&);
4507 void signal_vOs(short &&);
4509 void signal_vPFvvE(fptr);
4511 void signal(short&, short, long long, short);
4512 void otherSignal(const char *);
4515 void tst_QObject::connectCxx0xTypeMatching()
4517 // this is just about connecting the signals to the slots
4518 // if this fails, this will be a compiler failure
4519 typedef LotsOfSignalsAndSlots Foo;
4523 QObject::connect(&obj, &Foo::signal_v, &obj, &Foo::slot_v);
4524 QObject::connect(&obj, &Foo::signal_v, &obj, &Foo::slot_i);
4526 QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::slot_v);
4527 QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::slot_i);
4528 QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::slot_vi);
4529 QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::slot_ii);
4531 QObject::connect(&obj, &Foo::signal_vii, &obj, &Foo::slot_v);
4532 QObject::connect(&obj, &Foo::signal_vii, &obj, &Foo::slot_i);
4533 QObject::connect(&obj, &Foo::signal_vii, &obj, &Foo::slot_vi);
4534 QObject::connect(&obj, &Foo::signal_vii, &obj, &Foo::slot_ii);
4535 QObject::connect(&obj, &Foo::signal_vii, &obj, &Foo::slot_vii);
4536 QObject::connect(&obj, &Foo::signal_vii, &obj, &Foo::slot_iii);
4538 QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_v);
4539 QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_i);
4540 QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_vi);
4541 QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_ii);
4542 QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_vii);
4543 QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_iii);
4544 QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_viii);
4545 QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_iiii);
4547 QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::slot_vi); // repeated from above
4548 QObject::connect(&obj, &Foo::signal_vRi, &obj, &Foo::slot_vi);
4549 QObject::connect(&obj, &Foo::signal_vRi, &obj, &Foo::slot_vRi);
4550 /*#if defined(Q_COMPILER_RVALUE_REFS) || defined(QT_ENABLE_CXX0X)
4551 QObject::connect(&obj, &Foo::signal_vOi, &obj, &Foo::slot_vi);
4552 QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::slot_vOi);
4553 QObject::connect(&obj, &Foo::signal_vRi, &obj, &Foo::slot_vOi);
4554 QObject::connect(&obj, &Foo::signal_vOi, &obj, &Foo::slot_vOi);
4556 // these are not supposed to compile:
4557 //QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::slot_vRi);
4558 //QObject::connect(&obj, &Foo::signal_vOi, &obj, &Foo::slot_vRi);
4560 QObject::connect(&obj, &Foo::signal_vs, &obj, &Foo::slot_vi);
4561 QObject::connect(&obj, &Foo::signal_vRs, &obj, &Foo::slot_vi);
4562 /*#if defined(Q_COMPILER_RVALUE_REFS) || defined(QT_ENABLE_CXX0X)
4563 QObject::connect(&obj, &Foo::signal_vOs, &obj, &Foo::slot_vi);
4564 QObject::connect(&obj, &Foo::signal_vRs, &obj, &Foo::slot_vOi);
4565 QObject::connect(&obj, &Foo::signal_vOs, &obj, &Foo::slot_vOi);
4566 // these are not supposed to compile:
4567 //QObject::connect(&obj, &Foo::signal_vOs, &obj, &Foo::slot_vRi);
4568 //QObject::connect(&obj, &Foo::signal_vRs, &obj, &Foo::slot_vRi);
4571 QObject::connect(&obj, &Foo::signal_vPFvvE, &obj, &Foo::slot_v);
4572 QObject::connect(&obj, &Foo::signal_vPFvvE, &obj, &Foo::slot_i);
4573 QObject::connect(&obj, &Foo::signal_vPFvvE, &obj, &Foo::slot_vPFvvE);
4575 QObject::connect(&obj, &Foo::signal_v, &Foo::static_slot_v);
4576 QObject::connect(&obj, &Foo::signal_v, &Foo::static_slot_i);
4578 QObject::connect(&obj, &Foo::signal_vi, &Foo::static_slot_v);
4579 QObject::connect(&obj, &Foo::signal_vi, &Foo::static_slot_i);
4580 QObject::connect(&obj, &Foo::signal_vi, &Foo::static_slot_vi);
4581 QObject::connect(&obj, &Foo::signal_vi, &Foo::static_slot_ii);
4583 QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_v);
4584 QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_i);
4585 QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_vi);
4586 QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_ii);
4587 QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_vii);
4588 QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_iii);
4590 QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_v);
4591 QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_i);
4592 QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_vi);
4593 QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_ii);
4594 QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_vii);
4595 QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_iii);
4596 QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_viii);
4597 QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_iiii);
4599 /*#if defined(Q_COMPILER_RVALUE_REFS) && defined(QT_ENABLE_CXX0X)
4600 QObject::connect(&obj, &Foo::signal_vi, &Foo::static_slot_vOi);
4601 QObject::connect(&obj, &Foo::signal_vRi, &Foo::static_slot_vi);
4602 QObject::connect(&obj, &Foo::signal_vRi, &Foo::static_slot_vRi);
4603 QObject::connect(&obj, &Foo::signal_vRi, &Foo::static_slot_vOi);
4604 QObject::connect(&obj, &Foo::signal_vOi, &Foo::static_slot_vi);
4605 QObject::connect(&obj, &Foo::signal_vOi, &Foo::static_slot_vOi);
4606 //QObject::connect(&obj, &Foo::signal_vi, &Foo::static_slot_vRi);
4607 //QObject::connect(&obj, &Foo::signal_vOi, &Foo::static_slot_vRi);
4610 QObject::connect(&obj, &Foo::signal_vs, &Foo::static_slot_vi);
4611 QObject::connect(&obj, &Foo::signal_vRs, &Foo::static_slot_vi);
4612 /*#if defined(Q_COMPILER_RVALUE_REFS) && defined(QT_ENABLE_CXX0X)
4613 QObject::connect(&obj, &Foo::signal_vOs, &Foo::static_slot_vi);
4614 QObject::connect(&obj, &Foo::signal_vRs, &Foo::static_slot_vOi);
4615 QObject::connect(&obj, &Foo::signal_vOs, &Foo::static_slot_vOi);
4616 //QObject::connect(&obj, &Foo::signal_vOs, &Foo::static_slot_vRi);
4617 //QObject::connect(&obj, &Foo::signal_vRs, &Foo::static_slot_vRi);
4619 QObject::connect(&obj, &Foo::signal_vPFvvE, &Foo::static_slot_v);
4620 QObject::connect(&obj, &Foo::signal_vPFvvE, &Foo::static_slot_i);
4621 QObject::connect(&obj, &Foo::signal_vPFvvE, &Foo::static_slot_vPFvvE);
4622 QVERIFY(true); //compilation only test
4625 class StringVariant : public QObject
4628 void stringSignal(const QString &str);
4630 void variantSlot(const QVariant &v) { var = v; }
4633 friend class tst_QObject;
4638 void operator() (const QVariant &v) {
4643 void tst_QObject::connectConvert()
4646 QVERIFY(connect(&obj, &StringVariant::stringSignal, &obj, &StringVariant::variantSlot));
4647 QString s = QString::fromLatin1("Hello World");
4648 emit obj.stringSignal(s);
4649 QCOMPARE(obj.var.toString(), s);
4650 QVERIFY(obj.var.toString().isSharedWith(s));
4655 QVERIFY(connect(&obj, &StringVariant::stringSignal, f));
4656 s = QString::fromLatin1("GoodBye");
4657 emit obj.stringSignal(s);
4658 QCOMPARE(obj.var.toString(), s);
4659 QVERIFY(obj.var.toString().isSharedWith(s));
4660 QCOMPARE(var, obj.var);
4663 class ConnectWithReferenceObject : public QObject {
4665 friend class tst_QObject;
4667 void boolRef(bool &, bool);
4668 void stringRef(QString &, const QString &);
4669 void boolPtr(bool *, bool);
4670 void stringPtr(QString *, const QString &);
4672 void boolRefSlot(bool &b1, bool b2) { b1 = b2; }
4673 void stringRefSlot(QString &s1, const QString &s2) { s1 = s2; }
4674 void boolPtrSlot(bool *b1, bool b2) { *b1 = b2; }
4675 void stringPtrSlot(QString *s1, const QString &s2) { *s1 = s2; }
4677 void stringSlot1(QString s) { last = s; }
4678 void stringSlot2(const QString &s) { last = s; }
4679 void stringSlot3(QString &s) { last = s; }
4684 void tst_QObject::connectWithReference()
4686 ConnectWithReferenceObject o;
4688 QString s1 = QString::fromLatin1("str1");
4689 const QString s2 = QString::fromLatin1("str2");
4690 const QString s3 = QString::fromLatin1("str3");
4691 o.boolRef(b1, false);
4692 o.stringRef(s1, s2);
4694 QCOMPARE(s1, QString::fromLatin1("str1"));
4695 o.boolPtr(&b1, false);
4696 o.stringPtr(&s1, s2);
4698 QCOMPARE(s1, QString::fromLatin1("str1"));
4700 QVERIFY(connect(&o, &ConnectWithReferenceObject::boolRef, &o, &ConnectWithReferenceObject::boolRefSlot));
4701 QVERIFY(connect(&o, &ConnectWithReferenceObject::stringRef, &o, &ConnectWithReferenceObject::stringRefSlot));
4702 QVERIFY(connect(&o, &ConnectWithReferenceObject::boolPtr, &o, &ConnectWithReferenceObject::boolPtrSlot));
4703 QVERIFY(connect(&o, &ConnectWithReferenceObject::stringPtr, &o, &ConnectWithReferenceObject::stringPtrSlot));
4704 o.boolRef(b1, false);
4705 o.stringRef(s1, s2);
4706 QCOMPARE(b1, false);
4707 QCOMPARE(s1, QString::fromLatin1("str2"));
4709 o.boolPtr(&b1, true);
4710 o.stringPtr(&s1, s3);
4712 QCOMPARE(s1, QString::fromLatin1("str3"));
4715 ConnectWithReferenceObject o2;
4716 QVERIFY(connect(&o2, &ConnectWithReferenceObject::stringRef, &o2, &ConnectWithReferenceObject::stringSlot1));
4717 o2.stringRef(s1, s2);
4719 QCOMPARE(o2.last, s3);
4722 ConnectWithReferenceObject o2;
4723 QVERIFY(connect(&o2, &ConnectWithReferenceObject::stringRef, &o2, &ConnectWithReferenceObject::stringSlot2));
4724 o2.stringRef(s1, s2);
4726 QCOMPARE(o2.last, s3);
4729 ConnectWithReferenceObject o2;
4730 QVERIFY(connect(&o2, &ConnectWithReferenceObject::stringRef, &o2, &ConnectWithReferenceObject::stringSlot3));
4731 o2.stringRef(s1, s2);
4733 QCOMPARE(o2.last, s3);
4737 class ManyArgumentObject : public QObject {
4740 void signal1(const QString &);
4741 void signal2(const QString &, const QString &);
4742 void signal3(const QString &, const QString &, const QString &);
4743 void signal4(const QString &, const QString &, const QString &, const QString&);
4744 void signal5(const QString &, const QString &, const QString &, const QString&, const QString&);
4745 void signal6(const QString &, const QString &, const QString &, const QString&, const QString&, const QString&);
4748 #define MANYARGUMENT_COMPARE(L) QCOMPARE(L, QString(#L))
4749 void slot1(const QString &a) {
4750 MANYARGUMENT_COMPARE(a);
4753 void slot2(const QString &a, const QString &b) {
4754 MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b);
4757 void slot3(const QString &a, const QString &b, const QString &c) {
4758 MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c);
4761 void slot4(const QString &a, const QString &b, const QString &c, const QString&d) {
4762 MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c);
4763 MANYARGUMENT_COMPARE(d);
4766 void slot5(const QString &a, const QString &b, const QString &c, const QString&d, const QString&e) {
4767 MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c);
4768 MANYARGUMENT_COMPARE(d); MANYARGUMENT_COMPARE(e);
4771 void slot6(const QString &a, const QString &b, const QString &c, const QString&d, const QString&e, const QString&f) {
4772 MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c);
4773 MANYARGUMENT_COMPARE(d); MANYARGUMENT_COMPARE(e); MANYARGUMENT_COMPARE(f);
4781 namespace ManyArgumentNamespace {
4783 void slot1(const QString &a) {
4784 MANYARGUMENT_COMPARE(a);
4787 void slot2(const QString &a, const QString &b) {
4788 MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b);
4791 void slot3(const QString &a, const QString &b, const QString &c) {
4792 MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c);
4795 void slot4(const QString &a, const QString &b, const QString &c, const QString&d) {
4796 MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c);
4797 MANYARGUMENT_COMPARE(d);
4800 void slot5(const QString &a, const QString &b, const QString &c, const QString&d, const QString&e) {
4801 MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c);
4802 MANYARGUMENT_COMPARE(d); MANYARGUMENT_COMPARE(e);
4805 void slot6(const QString &a, const QString &b, const QString &c, const QString&d, const QString&e, const QString&f) {
4806 MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c);
4807 MANYARGUMENT_COMPARE(d); MANYARGUMENT_COMPARE(e); MANYARGUMENT_COMPARE(f);
4812 void tst_QObject::connectManyArguments()
4814 ManyArgumentObject ob;
4816 ManyArgumentNamespace::count = 0;
4817 connect(&ob, &ManyArgumentObject::signal1, &ob, &ManyArgumentObject::slot1);
4818 connect(&ob, &ManyArgumentObject::signal2, &ob, &ManyArgumentObject::slot2);
4819 connect(&ob, &ManyArgumentObject::signal3, &ob, &ManyArgumentObject::slot3);
4820 connect(&ob, &ManyArgumentObject::signal4, &ob, &ManyArgumentObject::slot4);
4821 connect(&ob, &ManyArgumentObject::signal5, &ob, &ManyArgumentObject::slot5);
4822 connect(&ob, &ManyArgumentObject::signal6, &ob, &ManyArgumentObject::slot6);
4823 connect(&ob, &ManyArgumentObject::signal1, ManyArgumentNamespace::slot1);
4824 connect(&ob, &ManyArgumentObject::signal2, ManyArgumentNamespace::slot2);
4825 connect(&ob, &ManyArgumentObject::signal3, ManyArgumentNamespace::slot3);
4826 connect(&ob, &ManyArgumentObject::signal4, ManyArgumentNamespace::slot4);
4827 connect(&ob, &ManyArgumentObject::signal5, ManyArgumentNamespace::slot5);
4828 connect(&ob, &ManyArgumentObject::signal6, ManyArgumentNamespace::slot6);
4831 connect(&ob, &ManyArgumentObject::signal6, &ob, &ManyArgumentObject::signal5);
4832 connect(&ob, &ManyArgumentObject::signal5, &ob, &ManyArgumentObject::signal4);
4833 connect(&ob, &ManyArgumentObject::signal4, &ob, &ManyArgumentObject::signal3);
4834 connect(&ob, &ManyArgumentObject::signal3, &ob, &ManyArgumentObject::signal2);
4835 connect(&ob, &ManyArgumentObject::signal2, &ob, &ManyArgumentObject::signal1);
4837 emit ob.signal6("a", "b", "c", "d", "e", "f");
4838 QCOMPARE(ob.count, 6);
4839 QCOMPARE(ManyArgumentNamespace::count, 6);
4842 ManyArgumentObject ob2;
4844 ManyArgumentNamespace::count = 0;
4845 connect(&ob2, &ManyArgumentObject::signal6, &ob2, &ManyArgumentObject::slot1);
4846 connect(&ob2, &ManyArgumentObject::signal6, &ob2, &ManyArgumentObject::slot2);
4847 connect(&ob2, &ManyArgumentObject::signal6, &ob2, &ManyArgumentObject::slot3);
4848 connect(&ob2, &ManyArgumentObject::signal6, &ob2, &ManyArgumentObject::slot4);
4849 connect(&ob2, &ManyArgumentObject::signal6, &ob2, &ManyArgumentObject::slot5);
4850 connect(&ob2, &ManyArgumentObject::signal6, &ob2, &ManyArgumentObject::slot6);
4851 connect(&ob2, &ManyArgumentObject::signal6, ManyArgumentNamespace::slot1);
4852 connect(&ob2, &ManyArgumentObject::signal6, ManyArgumentNamespace::slot2);
4853 connect(&ob2, &ManyArgumentObject::signal6, ManyArgumentNamespace::slot3);
4854 connect(&ob2, &ManyArgumentObject::signal6, ManyArgumentNamespace::slot4);
4855 connect(&ob2, &ManyArgumentObject::signal6, ManyArgumentNamespace::slot5);
4856 connect(&ob2, &ManyArgumentObject::signal6, ManyArgumentNamespace::slot6);
4858 emit ob2.signal6("a", "b", "c", "d", "e", "f");
4859 QCOMPARE(ob2.count, 6);
4860 QCOMPARE(ManyArgumentNamespace::count, 6);
4863 class ReturnValue : public QObject {
4864 friend class tst_QObject;
4867 QVariant returnVariant(int);
4868 QString returnString(int);
4870 void returnVoid(int);
4871 CustomType returnCustomType(int);
4873 QVariant returnVariantSlot(int i) { return i; }
4874 QString returnStringSlot(int i) { return QString::number(i); }
4875 int returnIntSlot(int i) { return i; }
4876 CustomType returnCustomTypeSlot(int i) { return CustomType(i); }
4877 void returnVoidSlot() {}
4878 int return23() { return 23; }
4879 QString returnHello() { return QStringLiteral("hello"); }
4881 struct VariantFunctor {
4882 QVariant operator()(int i) { return i; }
4884 struct CustomTypeFunctor {
4885 CustomType operator()(int i) { return CustomType(i); }
4887 struct StringFunctor {
4888 QString operator()(int i) { return QString::number(i); }
4891 int operator()(int i) { return i; }
4893 struct VoidFunctor {
4894 void operator()(int) {}
4898 QString someFunctionReturningString(int i) {
4899 return '\'' + QString::number(i) + '\'';
4902 void tst_QObject::returnValue_data()
4904 QTest::addColumn<bool>("isBlockingQueued");
4906 QTest::newRow("DirectConnection") << false;
4907 QTest::newRow("BlockingQueuedConnection") << true;
4910 void tst_QObject::returnValue()
4912 CheckInstanceCount checker;
4914 QFETCH(bool, isBlockingQueued);
4916 ReturnValue receiver;
4917 Qt::ConnectionType type = Qt::DirectConnection;
4918 if (isBlockingQueued) {
4920 receiver.moveToThread(&thread);
4921 type = Qt::BlockingQueuedConnection;
4924 { // connected to nothing
4925 CheckInstanceCount checker;
4927 QCOMPARE(emit r.returnVariant(45), QVariant());
4928 QCOMPARE(emit r.returnString(45), QString());
4929 QCOMPARE(emit r.returnInt(45), int());
4930 emit r.returnVoid(45);
4931 QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value());
4933 { // connected to a slot returning the same type
4934 CheckInstanceCount checker;
4936 QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnVariantSlot, type));
4937 QCOMPARE(emit r.returnVariant(45), QVariant(45));
4938 QVERIFY(connect(&r, &ReturnValue::returnString, &receiver, &ReturnValue::returnStringSlot, type));
4939 QCOMPARE(emit r.returnString(45), QString::fromLatin1("45"));
4940 QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::returnIntSlot, type));
4941 QCOMPARE(emit r.returnInt(45), int(45));
4942 QVERIFY(connect(&r, &ReturnValue::returnCustomType, &receiver, &ReturnValue::returnCustomTypeSlot, type));
4943 QCOMPARE((emit r.returnCustomType(45)).value(), CustomType(45).value());
4945 if (!isBlockingQueued) { // connected to simple functions or functor
4946 CheckInstanceCount checker;
4948 QVERIFY(connect(&r, &ReturnValue::returnString, someFunctionReturningString));
4949 QCOMPARE(emit r.returnString(49), QString::fromLatin1("'49'"));
4951 ReturnValue::CustomTypeFunctor customTypeFunctor;
4952 QVERIFY(connect(&r, &ReturnValue::returnCustomType, customTypeFunctor));
4953 QCOMPARE((emit r.returnCustomType(49)).value(), CustomType(49).value());
4955 ReturnValue::VariantFunctor variantFunctor;
4956 QVERIFY(connect(&r, &ReturnValue::returnVariant, variantFunctor));
4957 QCOMPARE(emit r.returnVariant(45), QVariant(45));
4959 ReturnValue::IntFunctor intFunctor;
4960 QVERIFY(connect(&r, &ReturnValue::returnInt, intFunctor));
4961 QCOMPARE(emit r.returnInt(45), int(45));
4963 { // connected to a slot with different type
4964 CheckInstanceCount checker;
4966 QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnStringSlot, type));
4967 QCOMPARE(emit r.returnVariant(48), QVariant(QString::fromLatin1("48")));
4968 QVERIFY(connect(&r, &ReturnValue::returnCustomType, &receiver, &ReturnValue::returnIntSlot, type));
4969 QCOMPARE((emit r.returnCustomType(48)).value(), CustomType(48).value());
4970 QVERIFY(connect(&r, &ReturnValue::returnVoid, &receiver, &ReturnValue::returnCustomTypeSlot, type));
4971 emit r.returnVoid(48);
4973 if (!isBlockingQueued) { // connected to functor with different type
4974 CheckInstanceCount checker;
4977 ReturnValue::CustomTypeFunctor customTypeFunctor;
4978 QVERIFY(connect(&r, &ReturnValue::returnCustomType, customTypeFunctor));
4979 QCOMPARE((emit r.returnCustomType(49)).value(), CustomType(49).value());
4981 ReturnValue::StringFunctor stringFunctor;
4982 QVERIFY(connect(&r, &ReturnValue::returnVariant, stringFunctor));
4983 QCOMPARE(emit r.returnVariant(45), QVariant(QString::fromLatin1("45")));
4985 { // connected to a void
4986 CheckInstanceCount checker;
4988 QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnVoidSlot, type));
4989 QCOMPARE(emit r.returnVariant(45), QVariant());
4990 QVERIFY(connect(&r, &ReturnValue::returnString, &receiver, &ReturnValue::returnVoidSlot, type));
4991 QCOMPARE(emit r.returnString(45), QString());
4992 QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::returnVoidSlot, type));
4993 QCOMPARE(emit r.returnInt(45), int());
4994 QVERIFY(connect(&r, &ReturnValue::returnCustomType, &receiver, &ReturnValue::returnVoidSlot, type));
4995 QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value());
4997 if (!isBlockingQueued) {
4998 // queued connection should not forward the return value
4999 CheckInstanceCount checker;
5001 QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnVariantSlot, Qt::QueuedConnection));
5002 QCOMPARE(emit r.returnVariant(45), QVariant());
5003 QVERIFY(connect(&r, &ReturnValue::returnString, &receiver, &ReturnValue::returnStringSlot, Qt::QueuedConnection));
5004 QCOMPARE(emit r.returnString(45), QString());
5005 QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::returnIntSlot, Qt::QueuedConnection));
5006 QCOMPARE(emit r.returnInt(45), int());
5007 QVERIFY(connect(&r, &ReturnValue::returnCustomType, &receiver, &ReturnValue::returnCustomTypeSlot, Qt::QueuedConnection));
5008 QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value());
5009 QCoreApplication::processEvents();
5011 QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnStringSlot, Qt::QueuedConnection));
5012 QCOMPARE(emit r.returnVariant(48), QVariant());
5013 QVERIFY(connect(&r, &ReturnValue::returnCustomType, &receiver, &ReturnValue::returnIntSlot, Qt::QueuedConnection));
5014 QCOMPARE((emit r.returnCustomType(48)).value(), CustomType().value());
5015 QVERIFY(connect(&r, &ReturnValue::returnVoid, &receiver, &ReturnValue::returnCustomTypeSlot, Qt::QueuedConnection));
5016 emit r.returnVoid(48);
5017 QCoreApplication::processEvents();
5020 { // connected to many slots
5021 ReturnValue::VoidFunctor voidFunctor;
5022 ReturnValue::IntFunctor intFunctor;
5024 QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnVariantSlot, type));
5025 QCOMPARE(emit r.returnVariant(45), QVariant(45));
5026 QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::return23, type));
5027 QCOMPARE(emit r.returnVariant(45), QVariant(23));
5028 QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnVoidSlot, type));
5029 QCOMPARE(emit r.returnVariant(45), QVariant(23));
5030 QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnHello, type));
5031 QCOMPARE(emit r.returnVariant(45), QVariant(QStringLiteral("hello")));
5032 QVERIFY(connect(&r, &ReturnValue::returnVariant, voidFunctor));
5033 QCOMPARE(emit r.returnVariant(45), QVariant(QStringLiteral("hello")));
5034 QVERIFY(connect(&r, &ReturnValue::returnVariant, intFunctor));
5035 QCOMPARE(emit r.returnVariant(45), QVariant(45));
5036 QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::return23, Qt::QueuedConnection));
5037 QCOMPARE(emit r.returnVariant(45), QVariant(45));
5039 QCOMPARE(emit r.returnInt(45), int());
5040 QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::returnVoidSlot, type));
5041 QCOMPARE(emit r.returnInt(45), int());
5042 QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::returnIntSlot, type));
5043 QCOMPARE(emit r.returnInt(45), int(45));
5044 QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::return23, type));
5045 QCOMPARE(emit r.returnInt(45), int(23));
5046 QVERIFY(connect(&r, &ReturnValue::returnInt, voidFunctor));
5047 QCOMPARE(emit r.returnInt(45), int(23));
5048 QVERIFY(connect(&r, &ReturnValue::returnInt, intFunctor));
5049 QCOMPARE(emit r.returnInt(45), int(45));
5050 QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::return23, Qt::QueuedConnection));
5051 QCOMPARE(emit r.returnInt(45), int(45));
5053 QCoreApplication::processEvents();
5056 if (isBlockingQueued) {
5062 void tst_QObject::returnValue2_data()
5063 { returnValue_data(); }
5065 //String based syntax
5066 void tst_QObject::returnValue2()
5068 CheckInstanceCount checker;
5070 QFETCH(bool, isBlockingQueued);
5072 ReturnValue receiver;
5073 Qt::ConnectionType type = Qt::DirectConnection;
5074 if (isBlockingQueued) {
5076 receiver.moveToThread(&thread);
5077 type = Qt::BlockingQueuedConnection;
5080 { // connected to a simple slot
5081 CheckInstanceCount checker;
5083 QVERIFY(connect(&r, SIGNAL(returnVariant(int)), &receiver, SLOT(returnVariantSlot(int)), type));
5084 QCOMPARE(emit r.returnVariant(45), QVariant(45));
5085 QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnStringSlot(int)), type));
5086 QCOMPARE(emit r.returnString(45), QString(QStringLiteral("45")));
5087 QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnIntSlot(int)), type));
5088 QCOMPARE(emit r.returnInt(45), int(45));
5089 QVERIFY(connect(&r, SIGNAL(returnCustomType(int)), &receiver, SLOT(returnCustomTypeSlot(int)), type));
5090 QCOMPARE((emit r.returnCustomType(45)).value(), CustomType(45).value());
5092 { // connected to a slot returning void
5093 CheckInstanceCount checker;
5095 QVERIFY(connect(&r, SIGNAL(returnVariant(int)), &receiver, SLOT(returnVoidSlot()), type));
5096 QCOMPARE(emit r.returnVariant(45), QVariant());
5097 QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnVoidSlot()), type));
5098 QCOMPARE(emit r.returnString(45), QString());
5099 QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnVoidSlot()), type));
5100 QCOMPARE(emit r.returnInt(45), int());
5101 QVERIFY(connect(&r, SIGNAL(returnCustomType(int)), &receiver, SLOT(returnVoidSlot()), type));
5102 QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value());
5104 if (!isBlockingQueued) {
5105 // queued connection should not forward the return value
5106 CheckInstanceCount checker;
5108 QVERIFY(connect(&r, SIGNAL(returnVariant(int)), &receiver, SLOT(returnVariantSlot(int)), Qt::QueuedConnection));
5109 QCOMPARE(emit r.returnVariant(45), QVariant());
5110 QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnStringSlot(int)), Qt::QueuedConnection));
5111 QCOMPARE(emit r.returnString(45), QString());
5112 QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnIntSlot(int)), Qt::QueuedConnection));
5113 QCOMPARE(emit r.returnInt(45), int());
5114 QVERIFY(connect(&r, SIGNAL(returnCustomType(int)), &receiver, SLOT(returnCustomTypeSlot(int)), Qt::QueuedConnection));
5115 QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value());
5116 QCoreApplication::processEvents();
5118 //Queued conneciton with different return type should be safe
5119 QVERIFY(connect(&r, SIGNAL(returnVariant(int)), &receiver, SLOT(returnStringSlot(int)), Qt::QueuedConnection));
5120 QCOMPARE(emit r.returnVariant(48), QVariant());
5121 QVERIFY(connect(&r, SIGNAL(returnCustomType(int)), &receiver, SLOT(returnIntSlot(int)), Qt::QueuedConnection));
5122 QCOMPARE((emit r.returnCustomType(48)).value(), CustomType().value());
5123 QVERIFY(connect(&r, SIGNAL(returnVoid(int)), &receiver, SLOT(returnCustomTypeSlot(int)), Qt::QueuedConnection));
5124 emit r.returnVoid(48);
5125 QCoreApplication::processEvents();
5127 { // connected to many slots
5129 QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnIntSlot(int)), type));
5130 QCOMPARE(emit r.returnInt(45), int(45));
5131 QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnVoidSlot()), type));
5132 QCOMPARE(emit r.returnInt(45), int(45));
5133 QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(return23()), type));
5134 QCOMPARE(emit r.returnInt(45), int(23));
5135 QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnIntSlot(int)), Qt::QueuedConnection));
5136 QCOMPARE(emit r.returnInt(45), int(23));
5138 QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnStringSlot(int)), type));
5139 QCOMPARE(emit r.returnString(45), QString(QStringLiteral("45")));
5140 QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnVoidSlot()), type));
5141 QCOMPARE(emit r.returnString(45), QString(QStringLiteral("45")));
5142 QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnHello()), type));
5143 QCOMPARE(emit r.returnString(45), QString(QStringLiteral("hello")));
5144 QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnStringSlot(int)), Qt::QueuedConnection));
5145 QCOMPARE(emit r.returnString(45), QString(QStringLiteral("hello")));
5147 if (isBlockingQueued) {
5154 QTEST_MAIN(tst_QObject)
5155 #include "tst_qobject.moc"