| 1 | /**************************************************************************** | 
| 2 | ** | 
| 3 | ** Copyright (C) 2016 The Qt Company Ltd. | 
| 4 | ** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com> | 
| 5 | ** Contact: https://www.qt.io/licensing/ | 
| 6 | ** | 
| 7 | ** This file is part of the test suite of the Qt Toolkit. | 
| 8 | ** | 
| 9 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ | 
| 10 | ** Commercial License Usage | 
| 11 | ** Licensees holding valid commercial Qt licenses may use this file in | 
| 12 | ** accordance with the commercial license agreement provided with the | 
| 13 | ** Software or, alternatively, in accordance with the terms contained in | 
| 14 | ** a written agreement between you and The Qt Company. For licensing terms | 
| 15 | ** and conditions see https://www.qt.io/terms-conditions. For further | 
| 16 | ** information use the contact form at https://www.qt.io/contact-us. | 
| 17 | ** | 
| 18 | ** GNU General Public License Usage | 
| 19 | ** Alternatively, this file may be used under the terms of the GNU | 
| 20 | ** General Public License version 3 as published by the Free Software | 
| 21 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT | 
| 22 | ** included in the packaging of this file. Please review the following | 
| 23 | ** information to ensure the GNU General Public License requirements will | 
| 24 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. | 
| 25 | ** | 
| 26 | ** $QT_END_LICENSE$ | 
| 27 | ** | 
| 28 | ****************************************************************************/ | 
| 29 |  | 
| 30 | #include <QtTest/QtTest> | 
| 31 |  | 
| 32 | #include <qcoreapplication.h> | 
| 33 | #include <qpointer.h> | 
| 34 | #include <qtimer.h> | 
| 35 | #include <qregularexpression.h> | 
| 36 | #include <qmetaobject.h> | 
| 37 | #include <qvariant.h> | 
| 38 | #include <QTcpServer> | 
| 39 | #include <QTcpSocket> | 
| 40 | #include <QThread> | 
| 41 | #include <QMutex> | 
| 42 | #include <QWaitCondition> | 
| 43 | #include <QScopedPointer> | 
| 44 | #if QT_CONFIG(process) | 
| 45 | # include <QProcess> | 
| 46 | #endif | 
| 47 | #include "qobject.h" | 
| 48 | #ifdef QT_BUILD_INTERNAL | 
| 49 | #include <private/qobject_p.h> | 
| 50 | #endif | 
| 51 |  | 
| 52 | #include <math.h> | 
| 53 |  | 
| 54 | class tst_QObject : public QObject | 
| 55 | { | 
| 56 |     Q_OBJECT | 
| 57 | private slots: | 
| 58 |     void disconnect(); | 
| 59 |     void connectSlotsByName(); | 
| 60 |     void connectSignalsToSignalsWithDefaultArguments(); | 
| 61 |     void receivers(); | 
| 62 |     void normalize(); | 
| 63 |     void qobject_castTemplate(); | 
| 64 |     void findChildren(); | 
| 65 |     void connectDisconnectNotify_data(); | 
| 66 |     void connectDisconnectNotify(); | 
| 67 |     void connectDisconnectNotifyPMF(); | 
| 68 |     void disconnectNotify_receiverDestroyed(); | 
| 69 |     void disconnectNotify_metaObjConnection(); | 
| 70 |     void connectNotify_connectSlotsByName(); | 
| 71 |     void connectDisconnectNotify_shadowing(); | 
| 72 |     void emitInDefinedOrder(); | 
| 73 |     void customTypes(); | 
| 74 |     void streamCustomTypes(); | 
| 75 |     void metamethod(); | 
| 76 |     void namespaces(); | 
| 77 |     void threadSignalEmissionCrash(); | 
| 78 |     void thread(); | 
| 79 |     void thread0(); | 
| 80 |     void moveToThread(); | 
| 81 |     void senderTest(); | 
| 82 |     void declareInterface(); | 
| 83 |     void qpointerResetBeforeDestroyedSignal(); | 
| 84 | #ifndef QT_NO_USERDATA | 
| 85 |     void testUserData(); | 
| 86 | #endif | 
| 87 |     void childDeletesItsSibling(); | 
| 88 |     void dynamicProperties(); | 
| 89 |     void floatProperty(); | 
| 90 |     void qrealProperty(); | 
| 91 |     void property(); | 
| 92 |     void recursiveSignalEmission(); | 
| 93 |     void signalBlocking(); | 
| 94 |     void blockingQueuedConnection(); | 
| 95 |     void childEvents(); | 
| 96 |     void installEventFilter(); | 
| 97 |     void deleteSelfInSlot(); | 
| 98 |     void disconnectSelfInSlotAndDeleteAfterEmit(); | 
| 99 |     void dumpObjectInfo(); | 
| 100 |     void connectToSender(); | 
| 101 |     void qobjectConstCast(); | 
| 102 |     void uniqConnection(); | 
| 103 |     void uniqConnectionPtr(); | 
| 104 |     void interfaceIid(); | 
| 105 |     void deleteQObjectWhenDeletingEvent(); | 
| 106 |     void overloads(); | 
| 107 |     void isSignalConnected(); | 
| 108 |     void isSignalConnectedAfterDisconnection(); | 
| 109 |     void qMetaObjectConnect(); | 
| 110 |     void qMetaObjectDisconnectOne(); | 
| 111 |     void sameName(); | 
| 112 |     void connectByMetaMethods(); | 
| 113 |     void connectByMetaMethodSlotInsteadOfSignal(); | 
| 114 |     void connectConstructorByMetaMethod(); | 
| 115 |     void disconnectByMetaMethod(); | 
| 116 |     void disconnectNotSignalMetaMethod(); | 
| 117 |     void autoConnectionBehavior(); | 
| 118 |     void baseDestroyed(); | 
| 119 |     void pointerConnect(); | 
| 120 |     void pointerDisconnect(); | 
| 121 |     void emitInDefinedOrderPointer(); | 
| 122 |     void customTypesPointer(); | 
| 123 |     void connectCxx0x(); | 
| 124 |     void connectToStaticCxx0x(); | 
| 125 |     void connectCxx0xTypeMatching(); | 
| 126 |     void connectCxx17Noexcept(); | 
| 127 |     void connectConvert(); | 
| 128 |     void connectWithReference(); | 
| 129 |     void connectManyArguments(); | 
| 130 |     void connectForwardDeclare(); | 
| 131 |     void connectNoDefaultConstructorArg(); | 
| 132 |     void returnValue_data(); | 
| 133 |     void returnValue(); | 
| 134 |     void returnValue2_data(); | 
| 135 |     void returnValue2(); | 
| 136 |     void connectVirtualSlots(); | 
| 137 |     void connectSlotsVMIClass();  // VMI = Virtual or Multiple Inheritance | 
| 138 |     void connectPrivateSlots(); | 
| 139 |     void connectFunctorArgDifference(); | 
| 140 |     void connectFunctorOverloads(); | 
| 141 |     void connectFunctorQueued(); | 
| 142 |     void connectFunctorWithContext(); | 
| 143 |     void connectFunctorWithContextUnique(); | 
| 144 |     void connectFunctorDeadlock(); | 
| 145 |     void connectFunctorMoveOnly(); | 
| 146 |     void connectStaticSlotWithObject(); | 
| 147 |     void disconnectDoesNotLeakFunctor(); | 
| 148 |     void contextDoesNotLeakFunctor(); | 
| 149 |     void connectBase(); | 
| 150 |     void connectWarnings(); | 
| 151 |     void qmlConnect(); | 
| 152 |     void qmlConnectToQObjectReceiver(); | 
| 153 |     void exceptions(); | 
| 154 |     void noDeclarativeParentChangedOnDestruction(); | 
| 155 |     void deleteLaterInAboutToBlockHandler(); | 
| 156 |     void mutableFunctor(); | 
| 157 |     void checkArgumentsForNarrowing(); | 
| 158 |     void nullReceiver(); | 
| 159 |     void functorReferencesConnection(); | 
| 160 |     void disconnectDisconnects(); | 
| 161 | }; | 
| 162 |  | 
| 163 | struct QObjectCreatedOnShutdown | 
| 164 | { | 
| 165 |     QObjectCreatedOnShutdown() {} | 
| 166 |     ~QObjectCreatedOnShutdown() | 
| 167 |     { | 
| 168 |         QObject(); | 
| 169 |     } | 
| 170 | }; | 
| 171 | static QObjectCreatedOnShutdown s_qobjectCreatedOnShutdown; | 
| 172 |  | 
| 173 | class SenderObject : public QObject | 
| 174 | { | 
| 175 |     Q_OBJECT | 
| 176 |  | 
| 177 | public: | 
| 178 |     SenderObject() : aPublicSlotCalled(0), recursionCount(0) {} | 
| 179 |  | 
| 180 |     void emitSignal1AfterRecursion() | 
| 181 |     { | 
| 182 |         if (recursionCount++ < 100) | 
| 183 |             emitSignal1AfterRecursion(); | 
| 184 |         else | 
| 185 |             emitSignal1(); | 
| 186 |     } | 
| 187 |  | 
| 188 |     void emitSignal1() { emit signal1(); } | 
| 189 |     void emitSignal2() { emit signal2(); } | 
| 190 |     void emitSignal3() { emit signal3(); } | 
| 191 |     void emitSignal4() { emit signal4(); } | 
| 192 |  | 
| 193 | signals: | 
| 194 |     void signal1(); | 
| 195 |     void signal2(); | 
| 196 |     void signal3(); | 
| 197 |     void signal4(); | 
| 198 |     QT_MOC_COMPAT void signal5(); | 
| 199 |     void signal6(void); | 
| 200 |     void signal7(int, const QString &); | 
| 201 |  | 
| 202 | public slots: | 
| 203 |     void aPublicSlot() { aPublicSlotCalled++; } | 
| 204 |  | 
| 205 | public: | 
| 206 |     Q_INVOKABLE void invoke1(){} | 
| 207 |     Q_SCRIPTABLE void sinvoke1(){} | 
| 208 |     int aPublicSlotCalled; | 
| 209 | protected: | 
| 210 |     Q_INVOKABLE QT_MOC_COMPAT void invoke2(){} | 
| 211 |     Q_INVOKABLE QT_MOC_COMPAT void invoke2(int){} | 
| 212 |     Q_SCRIPTABLE QT_MOC_COMPAT void sinvoke2(){} | 
| 213 | private: | 
| 214 |     Q_INVOKABLE void invoke3(int hinz = 0, int kunz = 0){Q_UNUSED(hinz) Q_UNUSED(kunz)} | 
| 215 |     Q_SCRIPTABLE void sinvoke3(){} | 
| 216 |  | 
| 217 |     int recursionCount; | 
| 218 | }; | 
| 219 |  | 
| 220 | class ReceiverObject : public QObject | 
| 221 | { | 
| 222 |     Q_OBJECT | 
| 223 |  | 
| 224 | public: | 
| 225 |     ReceiverObject() | 
| 226 |         : sequence_slot1( 0 ) | 
| 227 |         , sequence_slot2( 0 ) | 
| 228 |         , sequence_slot3( 0 ) | 
| 229 |         , sequence_slot4( 0 ) | 
| 230 |     {} | 
| 231 |  | 
| 232 |     void reset() | 
| 233 |     { | 
| 234 |         sequence_slot4 = 0; | 
| 235 |         sequence_slot3 = 0; | 
| 236 |         sequence_slot2 = 0; | 
| 237 |         sequence_slot1 = 0; | 
| 238 |         count_slot1 = 0; | 
| 239 |         count_slot2 = 0; | 
| 240 |         count_slot3 = 0; | 
| 241 |         count_slot4 = 0; | 
| 242 |     } | 
| 243 |  | 
| 244 |     int sequence_slot1; | 
| 245 |     int sequence_slot2; | 
| 246 |     int sequence_slot3; | 
| 247 |     int sequence_slot4; | 
| 248 |     int count_slot1; | 
| 249 |     int count_slot2; | 
| 250 |     int count_slot3; | 
| 251 |     int count_slot4; | 
| 252 |  | 
| 253 |     bool called(int slot) | 
| 254 |     { | 
| 255 |         switch (slot) { | 
| 256 |         case 1: return sequence_slot1; | 
| 257 |         case 2: return sequence_slot2; | 
| 258 |         case 3: return sequence_slot3; | 
| 259 |         case 4: return sequence_slot4; | 
| 260 |         default: return false; | 
| 261 |         } | 
| 262 |     } | 
| 263 |  | 
| 264 |     static int sequence; | 
| 265 |  | 
| 266 | public slots: | 
| 267 |     void slot1() { sequence_slot1 = ++sequence; count_slot1++; } | 
| 268 |     void slot2() { sequence_slot2 = ++sequence; count_slot2++; } | 
| 269 |     void slot3() { sequence_slot3 = ++sequence; count_slot3++; } | 
| 270 |     void slot4() { sequence_slot4 = ++sequence; count_slot4++; } | 
| 271 |  | 
| 272 | }; | 
| 273 |  | 
| 274 | int ReceiverObject::sequence = 0; | 
| 275 |  | 
| 276 | static void playWithObjects() | 
| 277 | { | 
| 278 |     // Do operations that will lock the internal signalSlotLock mutex on many QObjects. | 
| 279 |     // The more QObjects, the higher the chance that the signalSlotLock mutex used | 
| 280 |     // is already in use. If the number of objects is higher than the number of mutexes in | 
| 281 |     // the pool (currently 131), the deadlock should always trigger. Use an even higher number | 
| 282 |     // to be on the safe side. | 
| 283 |     const int objectCount = 1024; | 
| 284 |     SenderObject lotsOfObjects[objectCount]; | 
| 285 |     for (int i = 0; i < objectCount; ++i) { | 
| 286 |         QObject::connect(sender: &lotsOfObjects[i], signal: &SenderObject::signal1, | 
| 287 |                          receiver: &lotsOfObjects[i], slot: &SenderObject::aPublicSlot); | 
| 288 |     } | 
| 289 | } | 
| 290 |  | 
| 291 | void tst_QObject::disconnect() | 
| 292 | { | 
| 293 |     SenderObject s; | 
| 294 |     ReceiverObject r1; | 
| 295 |     ReceiverObject r2; | 
| 296 |  | 
| 297 |     connect(sender: &s, SIGNAL(signal1()), receiver: &r1, SLOT(slot1())); | 
| 298 |  | 
| 299 |     connect(sender: &s, SIGNAL(signal2()), receiver: &r1, SLOT(slot2())); | 
| 300 |     connect(sender: &s, SIGNAL(signal3()), receiver: &r1, SLOT(slot3())); | 
| 301 |     connect(sender: &s, SIGNAL(signal4()), receiver: &r1, SLOT(slot4())); | 
| 302 |  | 
| 303 |     s.emitSignal1(); | 
| 304 |     s.emitSignal2(); | 
| 305 |     s.emitSignal3(); | 
| 306 |     s.emitSignal4(); | 
| 307 |  | 
| 308 |     QVERIFY(r1.called(1)); | 
| 309 |     QVERIFY(r1.called(2)); | 
| 310 |     QVERIFY(r1.called(3)); | 
| 311 |     QVERIFY(r1.called(4)); | 
| 312 |     r1.reset(); | 
| 313 |  | 
| 314 |     // usual disconnect with all parameters given | 
| 315 |     bool ret = QObject::disconnect(sender: &s, SIGNAL(signal1()), receiver: &r1, SLOT(slot1())); | 
| 316 |  | 
| 317 |     s.emitSignal1(); | 
| 318 |  | 
| 319 |     QVERIFY(!r1.called(1)); | 
| 320 |     r1.reset(); | 
| 321 |  | 
| 322 |     QVERIFY(ret); | 
| 323 |     ret = QObject::disconnect(sender: &s, SIGNAL(signal1()), receiver: &r1, SLOT(slot1())); | 
| 324 |     QVERIFY(!ret); | 
| 325 |  | 
| 326 |     // disconnect all signals from s from all slots from r1 | 
| 327 |     QObject::disconnect(sender: &s, signal: 0, receiver: &r1, member: 0); | 
| 328 |  | 
| 329 |     s.emitSignal2(); | 
| 330 |     s.emitSignal3(); | 
| 331 |     s.emitSignal4(); | 
| 332 |  | 
| 333 |     QVERIFY(!r1.called(2)); | 
| 334 |     QVERIFY(!r1.called(3)); | 
| 335 |     QVERIFY(!r1.called(4)); | 
| 336 |     r1.reset(); | 
| 337 |  | 
| 338 |     connect(sender: &s, SIGNAL(signal1()), receiver: &r1, SLOT(slot1())); | 
| 339 |     connect(sender: &s, SIGNAL(signal1()), receiver: &r1, SLOT(slot2())); | 
| 340 |     connect(sender: &s, SIGNAL(signal1()), receiver: &r1, SLOT(slot3())); | 
| 341 |     connect(sender: &s, SIGNAL(signal2()), receiver: &r1, SLOT(slot4())); | 
| 342 |  | 
| 343 |     // disconnect s's signal1() from all slots of r1 | 
| 344 |     QObject::disconnect(sender: &s, SIGNAL(signal1()), receiver: &r1, member: 0); | 
| 345 |  | 
| 346 |     s.emitSignal1(); | 
| 347 |     s.emitSignal2(); | 
| 348 |  | 
| 349 |     QVERIFY(!r1.called(1)); | 
| 350 |     QVERIFY(!r1.called(2)); | 
| 351 |     QVERIFY(!r1.called(3)); | 
| 352 |     QVERIFY(r1.called(4)); | 
| 353 |     r1.reset(); | 
| 354 |     // make sure all is disconnected again | 
| 355 |     QObject::disconnect(sender: &s, signal: 0, receiver: &r1, member: 0); | 
| 356 |  | 
| 357 |     connect(sender: &s, SIGNAL(signal1()), receiver: &r1, SLOT(slot1())); | 
| 358 |     connect(sender: &s, SIGNAL(signal1()), receiver: &r2, SLOT(slot1())); | 
| 359 |     connect(sender: &s, SIGNAL(signal2()), receiver: &r1, SLOT(slot2())); | 
| 360 |     connect(sender: &s, SIGNAL(signal2()), receiver: &r2, SLOT(slot2())); | 
| 361 |     connect(sender: &s, SIGNAL(signal3()), receiver: &r1, SLOT(slot3())); | 
| 362 |     connect(sender: &s, SIGNAL(signal3()), receiver: &r2, SLOT(slot3())); | 
| 363 |  | 
| 364 |     // disconnect signal1() from all receivers | 
| 365 |     QObject::disconnect(sender: &s, SIGNAL(signal1()), receiver: 0, member: 0); | 
| 366 |     s.emitSignal1(); | 
| 367 |     s.emitSignal2(); | 
| 368 |     s.emitSignal3(); | 
| 369 |  | 
| 370 |     QVERIFY(!r1.called(1)); | 
| 371 |     QVERIFY(!r2.called(1)); | 
| 372 |     QVERIFY(r1.called(2)); | 
| 373 |     QVERIFY(r2.called(2)); | 
| 374 |     QVERIFY(r1.called(2)); | 
| 375 |     QVERIFY(r2.called(2)); | 
| 376 |  | 
| 377 |     r1.reset(); | 
| 378 |     r2.reset(); | 
| 379 |  | 
| 380 |     // disconnect all signals of s from all receivers | 
| 381 |     QObject::disconnect(sender: &s, signal: 0, receiver: 0, member: 0); | 
| 382 |  | 
| 383 |     QVERIFY(!r1.called(2)); | 
| 384 |     QVERIFY(!r2.called(2)); | 
| 385 |     QVERIFY(!r1.called(2)); | 
| 386 |     QVERIFY(!r2.called(2)); | 
| 387 | } | 
| 388 |  | 
| 389 | class AutoConnectSender : public QObject | 
| 390 | { | 
| 391 |     Q_OBJECT | 
| 392 |  | 
| 393 | public: | 
| 394 |     AutoConnectSender(QObject *parent) | 
| 395 |         : QObject(parent) | 
| 396 |     {} | 
| 397 |  | 
| 398 |     void emitSignalNoParams() { emit signalNoParams(); } | 
| 399 |     void emitSignalWithParams(int i) { emit signalWithParams(i); } | 
| 400 |     void emitSignalWithParams(int i, QString string) { emit signalWithParams(i, string); } | 
| 401 |     void emitSignalManyParams(int i1, int i2, int i3, QString string, bool onoff) { emit signalManyParams(i1, i2, i3, string, onoff); } | 
| 402 |     void emitSignalManyParams(int i1, int i2, int i3, QString string, bool onoff, bool dummy) { emit signalManyParams(i1, i2, i3, string, onoff, dummy); } | 
| 403 |     void emitSignalManyParams2(int i1, int i2, int i3, QString string, bool onoff) { emit signalManyParams2(i1, i2, i3, string, onoff); } | 
| 404 |     void emitSignalLoopBack() { emit signalLoopBack(); } | 
| 405 |  | 
| 406 | signals: | 
| 407 |     void signalNoParams(); | 
| 408 |     void signalWithParams(int i); | 
| 409 |     void signalWithParams(int i, QString string); | 
| 410 |     void signalManyParams(int i1, int i2, int i3, QString string, bool onoff); | 
| 411 |     void signalManyParams(int i1, int i2, int i3, QString string, bool onoff, bool); | 
| 412 |     void signalManyParams2(int i1, int i2, int i3, QString string, bool onoff); | 
| 413 |     void signalLoopBack(); | 
| 414 | }; | 
| 415 |  | 
| 416 | class AutoConnectReceiver : public QObject | 
| 417 | { | 
| 418 |     Q_OBJECT | 
| 419 |  | 
| 420 | public: | 
| 421 |     QList<int> called_slots; | 
| 422 |  | 
| 423 |     AutoConnectReceiver() | 
| 424 |     { | 
| 425 |         connect(sender: this, SIGNAL(on_Sender_signalLoopBack()), receiver: this, SLOT(slotLoopBack())); | 
| 426 |     } | 
| 427 |  | 
| 428 |     void emitSignalNoParams() { emit signalNoParams(); } | 
| 429 |     void emit_signal_with_underscore() { emit signal_with_underscore(); } | 
| 430 |  | 
| 431 | public slots: | 
| 432 |     void on_Sender_signalNoParams() { called_slots << 1; } | 
| 433 |     void on_Sender_signalWithParams(int i = 0) { called_slots << 2; Q_UNUSED(i); } | 
| 434 |     void on_Sender_signalWithParams(int i, QString string) { called_slots << 3; Q_UNUSED(i);Q_UNUSED(string); } | 
| 435 |     void on_Sender_signalManyParams() { called_slots << 4; } | 
| 436 |     void on_Sender_signalManyParams(int i1, int i2, int i3, QString string, bool onoff) | 
| 437 |     { called_slots << 5; Q_UNUSED(i1);Q_UNUSED(i2);Q_UNUSED(i3);Q_UNUSED(string);Q_UNUSED(onoff); } | 
| 438 |     void on_Sender_signalManyParams(int i1, int i2, int i3, QString string, bool onoff, bool dummy) | 
| 439 |     { called_slots << 6; Q_UNUSED(i1);Q_UNUSED(i2);Q_UNUSED(i3);Q_UNUSED(string);Q_UNUSED(onoff); Q_UNUSED(dummy);} | 
| 440 |     void on_Sender_signalManyParams2(int i1, int i2, int i3, QString string, bool onoff) | 
| 441 |     { called_slots << 7; Q_UNUSED(i1);Q_UNUSED(i2);Q_UNUSED(i3);Q_UNUSED(string);Q_UNUSED(onoff); } | 
| 442 |     void slotLoopBack() { called_slots << 8; } | 
| 443 |     void on_Receiver_signalNoParams() { called_slots << 9; } | 
| 444 |     void on_Receiver_signal_with_underscore() { called_slots << 10; } | 
| 445 |  | 
| 446 | protected slots: | 
| 447 |     void o() { called_slots << -1; } | 
| 448 |     void on() { called_slots << -1; } | 
| 449 |     void on_() { called_slots << -1; } | 
| 450 |     void on_something() { called_slots << -1; } | 
| 451 |     void on_child_signal() { called_slots << -1; } | 
| 452 |  | 
| 453 | signals: | 
| 454 |     void on_Sender_signalLoopBack(); | 
| 455 |     void signalNoParams(); | 
| 456 |     void signal_with_underscore(); | 
| 457 | }; | 
| 458 |  | 
| 459 | void tst_QObject::connectSlotsByName() | 
| 460 | { | 
| 461 |     AutoConnectReceiver receiver; | 
| 462 |     receiver.setObjectName("Receiver" ); | 
| 463 |     AutoConnectSender sender(&receiver); | 
| 464 |     sender.setObjectName("Sender" ); | 
| 465 |  | 
| 466 |     QTest::ignoreMessage(type: QtWarningMsg, message: "QMetaObject::connectSlotsByName: No matching signal for on_child_signal()" ); | 
| 467 |     QTest::ignoreMessage(type: QtWarningMsg, message: "QMetaObject::connectSlotsByName: Connecting slot on_Sender_signalManyParams() with the first of the following compatible signals: (\"signalManyParams(int,int,int,QString,bool)\", \"signalManyParams(int,int,int,QString,bool,bool)\")" ); | 
| 468 |     QMetaObject::connectSlotsByName(o: &receiver); | 
| 469 |  | 
| 470 |     receiver.called_slots.clear(); | 
| 471 |     sender.emitSignalNoParams(); | 
| 472 |     QCOMPARE(receiver.called_slots, QList<int>() << 1); | 
| 473 |  | 
| 474 |     receiver.called_slots.clear(); | 
| 475 |     sender.emitSignalWithParams(i: 0); | 
| 476 |     QCOMPARE(receiver.called_slots, QList<int>() << 2); | 
| 477 |  | 
| 478 |     receiver.called_slots.clear(); | 
| 479 |     sender.emitSignalWithParams(i: 0, string: "string" ); | 
| 480 |     QCOMPARE(receiver.called_slots, QList<int>() << 3); | 
| 481 |  | 
| 482 |     receiver.called_slots.clear(); | 
| 483 |     sender.emitSignalManyParams(i1: 1, i2: 2, i3: 3, string: "string" , onoff: true); | 
| 484 |     sender.emitSignalManyParams(i1: 1, i2: 2, i3: 3, string: "string" , onoff: true, dummy: false); | 
| 485 |     // the slot '4' (signalManyParams()) will get connected | 
| 486 |     // to either of the two signalManyParams(...) overloads | 
| 487 |     QCOMPARE(receiver.called_slots, QList<int>() << 4 << 5 << 6); | 
| 488 |  | 
| 489 |     receiver.called_slots.clear(); | 
| 490 |     sender.emitSignalManyParams2(i1: 1, i2: 2, i3: 3, string: "string" , onoff: true); | 
| 491 |     QCOMPARE(receiver.called_slots, QList<int>() << 7); | 
| 492 |  | 
| 493 |     receiver.called_slots.clear(); | 
| 494 |     sender.emitSignalLoopBack(); | 
| 495 |     QCOMPARE(receiver.called_slots, QList<int>() << 8); | 
| 496 |  | 
| 497 |     receiver.called_slots.clear(); | 
| 498 |     receiver.emitSignalNoParams(); | 
| 499 |     QCOMPARE(receiver.called_slots, QList<int>() << 9); | 
| 500 |  | 
| 501 |     receiver.called_slots.clear(); | 
| 502 |     receiver.emit_signal_with_underscore(); | 
| 503 |     QCOMPARE(receiver.called_slots, QList<int>() << 10); | 
| 504 | } | 
| 505 |  | 
| 506 | void tst_QObject::qobject_castTemplate() | 
| 507 | { | 
| 508 |     QScopedPointer<QObject> o; | 
| 509 |     QVERIFY(!::qobject_cast<QObject*>(o.data())); | 
| 510 |  | 
| 511 |     o.reset(other: new SenderObject); | 
| 512 |     QVERIFY(::qobject_cast<SenderObject*>(o.data())); | 
| 513 |     QVERIFY(::qobject_cast<QObject*>(o.data())); | 
| 514 |     QVERIFY(!::qobject_cast<ReceiverObject*>(o.data())); | 
| 515 | } | 
| 516 |  | 
| 517 | void tst_QObject::findChildren() | 
| 518 | { | 
| 519 |     QObject o; | 
| 520 |     QObject o1(&o); | 
| 521 |     QObject o2(&o); | 
| 522 |     QObject o11(&o1); | 
| 523 |     QObject o12(&o1); | 
| 524 |     QObject o111(&o11); | 
| 525 |     QObject unnamed(&o); | 
| 526 |     QTimer t1(&o); | 
| 527 |     QTimer t121(&o12); | 
| 528 |     QTimer emptyname(&o); | 
| 529 |  | 
| 530 |     Q_SET_OBJECT_NAME(o); | 
| 531 |     Q_SET_OBJECT_NAME(o1); | 
| 532 |     Q_SET_OBJECT_NAME(o2); | 
| 533 |     Q_SET_OBJECT_NAME(o11); | 
| 534 |     Q_SET_OBJECT_NAME(o12); | 
| 535 |     Q_SET_OBJECT_NAME(o111); | 
| 536 |     Q_SET_OBJECT_NAME(t1); | 
| 537 |     Q_SET_OBJECT_NAME(t121); | 
| 538 |     emptyname.setObjectName("" ); | 
| 539 |  | 
| 540 |     QObject *op = 0; | 
| 541 |  | 
| 542 |     op = o.findChild<QObject*>(aName: "o1" ); | 
| 543 |     QCOMPARE(op, &o1); | 
| 544 |     op = o.findChild<QObject*>(aName: "o2" ); | 
| 545 |     QCOMPARE(op, &o2); | 
| 546 |     op = o.findChild<QObject*>(aName: "o11" ); | 
| 547 |     QCOMPARE(op, &o11); | 
| 548 |     op = o.findChild<QObject*>(aName: "o12" ); | 
| 549 |     QCOMPARE(op, &o12); | 
| 550 |     op = o.findChild<QObject*>(aName: "o111" ); | 
| 551 |     QCOMPARE(op, &o111); | 
| 552 |     op = o.findChild<QObject*>(aName: "t1" ); | 
| 553 |     QCOMPARE(op, static_cast<QObject *>(&t1)); | 
| 554 |     op = o.findChild<QObject*>(aName: "t121" ); | 
| 555 |     QCOMPARE(op, static_cast<QObject *>(&t121)); | 
| 556 |     op = o.findChild<QTimer*>(aName: "t1" ); | 
| 557 |     QCOMPARE(op, static_cast<QObject *>(&t1)); | 
| 558 |     op = o.findChild<QTimer*>(aName: "t121" ); | 
| 559 |     QCOMPARE(op, static_cast<QObject *>(&t121)); | 
| 560 |     op = o.findChild<QTimer*>(aName: "o12" ); | 
| 561 |     QCOMPARE(op, static_cast<QObject *>(0)); | 
| 562 |     op = o.findChild<QObject*>(aName: "o" ); | 
| 563 |     QCOMPARE(op, static_cast<QObject *>(0)); | 
| 564 |     op = o.findChild<QObject*>(aName: "harry" ); | 
| 565 |     QCOMPARE(op, static_cast<QObject *>(0)); | 
| 566 |     op = o.findChild<QObject*>(aName: "o1" ); | 
| 567 |     QCOMPARE(op, &o1); | 
| 568 |  | 
| 569 |     QList<QObject*> l; | 
| 570 |     QList<QTimer*> tl; | 
| 571 |  | 
| 572 |     l = o.findChildren<QObject*>(aName: "o1" ); | 
| 573 |     QCOMPARE(l.size(), 1); | 
| 574 |     QCOMPARE(l.at(0), &o1); | 
| 575 |     l = o.findChildren<QObject*>(aName: "o2" ); | 
| 576 |     QCOMPARE(l.size(), 1); | 
| 577 |     QCOMPARE(l.at(0), &o2); | 
| 578 |     l = o.findChildren<QObject*>(aName: "o11" ); | 
| 579 |     QCOMPARE(l.size(), 1); | 
| 580 |     QCOMPARE(l.at(0), &o11); | 
| 581 |     l = o.findChildren<QObject*>(aName: "o12" ); | 
| 582 |     QCOMPARE(l.size(), 1); | 
| 583 |     QCOMPARE(l.at(0), &o12); | 
| 584 |     l = o.findChildren<QObject*>(aName: "o111" ); | 
| 585 |     QCOMPARE(l.size(), 1); | 
| 586 |     QCOMPARE(l.at(0), &o111); | 
| 587 |     l = o.findChildren<QObject*>(aName: "t1" ); | 
| 588 |     QCOMPARE(l.size(), 1); | 
| 589 |     QCOMPARE(l.at(0), static_cast<QObject *>(&t1)); | 
| 590 |     l = o.findChildren<QObject*>(aName: "t121" ); | 
| 591 |     QCOMPARE(l.size(), 1); | 
| 592 |     QCOMPARE(l.at(0), static_cast<QObject *>(&t121)); | 
| 593 |     tl = o.findChildren<QTimer*>(aName: "t1" ); | 
| 594 |     QCOMPARE(tl.size(), 1); | 
| 595 |     QCOMPARE(tl.at(0), &t1); | 
| 596 |     tl = o.findChildren<QTimer*>(aName: "t121" ); | 
| 597 |     QCOMPARE(tl.size(), 1); | 
| 598 |     QCOMPARE(tl.at(0), &t121); | 
| 599 |     l = o.findChildren<QObject*>(aName: "o" ); | 
| 600 |     QCOMPARE(l.size(), 0); | 
| 601 |     l = o.findChildren<QObject*>(aName: "harry" ); | 
| 602 |     QCOMPARE(l.size(), 0); | 
| 603 |     tl = o.findChildren<QTimer*>(aName: "o12" ); | 
| 604 |     QCOMPARE(tl.size(), 0); | 
| 605 |     l = o.findChildren<QObject*>(aName: "o1" ); | 
| 606 |     QCOMPARE(l.size(), 1); | 
| 607 |     QCOMPARE(l.at(0), &o1); | 
| 608 |  | 
| 609 |     l = o.findChildren<QObject*>(re: QRegularExpression("^o.*$" )); | 
| 610 |     QCOMPARE(l.size(), 5); | 
| 611 |     QVERIFY(l.contains(&o1)); | 
| 612 |     QVERIFY(l.contains(&o2)); | 
| 613 |     QVERIFY(l.contains(&o11)); | 
| 614 |     QVERIFY(l.contains(&o12)); | 
| 615 |     QVERIFY(l.contains(&o111)); | 
| 616 |     l = o.findChildren<QObject*>(re: QRegularExpression("t.*" )); | 
| 617 |     QCOMPARE(l.size(), 2); | 
| 618 |     QVERIFY(l.contains(&t1)); | 
| 619 |     QVERIFY(l.contains(&t121)); | 
| 620 |     tl = o.findChildren<QTimer*>(re: QRegularExpression("^.*$" )); | 
| 621 |     QCOMPARE(tl.size(), 3); | 
| 622 |     QVERIFY(tl.contains(&t1)); | 
| 623 |     QVERIFY(tl.contains(&t121)); | 
| 624 |     tl = o.findChildren<QTimer*>(re: QRegularExpression("^o.*$" )); | 
| 625 |     QCOMPARE(tl.size(), 0); | 
| 626 |     l = o.findChildren<QObject*>(re: QRegularExpression("^harry$" )); | 
| 627 |     QCOMPARE(l.size(), 0); | 
| 628 |  | 
| 629 |     l = o.findChildren<QObject*>(re: QRegularExpression("o.*" )); | 
| 630 |     QCOMPARE(l.size(), 5); | 
| 631 |     QVERIFY(l.contains(&o1)); | 
| 632 |     QVERIFY(l.contains(&o2)); | 
| 633 |     QVERIFY(l.contains(&o11)); | 
| 634 |     QVERIFY(l.contains(&o12)); | 
| 635 |     QVERIFY(l.contains(&o111)); | 
| 636 |     l = o.findChildren<QObject*>(re: QRegularExpression("t.*" )); | 
| 637 |     QCOMPARE(l.size(), 2); | 
| 638 |     QVERIFY(l.contains(&t1)); | 
| 639 |     QVERIFY(l.contains(&t121)); | 
| 640 |     tl = o.findChildren<QTimer*>(re: QRegularExpression(".*" )); | 
| 641 |     QCOMPARE(tl.size(), 3); | 
| 642 |     QVERIFY(tl.contains(&t1)); | 
| 643 |     QVERIFY(tl.contains(&t121)); | 
| 644 |     tl = o.findChildren<QTimer*>(re: QRegularExpression("o.*" )); | 
| 645 |     QCOMPARE(tl.size(), 0); | 
| 646 |     l = o.findChildren<QObject*>(re: QRegularExpression("harry" )); | 
| 647 |     QCOMPARE(l.size(), 0); | 
| 648 |  | 
| 649 |     // empty and null string check | 
| 650 |     op = o.findChild<QObject*>(); | 
| 651 |     QCOMPARE(op, &o1); | 
| 652 |     op = o.findChild<QObject*>(aName: "" ); | 
| 653 |     QCOMPARE(op, &unnamed); | 
| 654 |     op = o.findChild<QObject*>(aName: "unnamed" ); | 
| 655 |     QCOMPARE(op, static_cast<QObject *>(0)); | 
| 656 |  | 
| 657 |     l = o.findChildren<QObject*>(); | 
| 658 |     QCOMPARE(l.size(), 9); | 
| 659 |     l = o.findChildren<QObject*>(aName: "" ); | 
| 660 |     QCOMPARE(l.size(), 2); | 
| 661 |     l = o.findChildren<QObject*>(aName: "unnamed" ); | 
| 662 |     QCOMPARE(l.size(), 0); | 
| 663 |  | 
| 664 |     tl = o.findChildren<QTimer *>(aName: "t1" ); | 
| 665 |     QCOMPARE(tl.size(), 1); | 
| 666 |     QCOMPARE(tl.at(0), &t1); | 
| 667 |  | 
| 668 |     // Find direct child/children | 
| 669 |  | 
| 670 |     op = o.findChild<QObject*>(aName: "o1" , options: Qt::FindDirectChildrenOnly); | 
| 671 |     QCOMPARE(op, &o1); | 
| 672 |     op = o.findChild<QObject*>(aName: "o2" , options: Qt::FindDirectChildrenOnly); | 
| 673 |     QCOMPARE(op, &o2); | 
| 674 |     op = o.findChild<QObject*>(aName: "o11" , options: Qt::FindDirectChildrenOnly); | 
| 675 |     QCOMPARE(op, static_cast<QObject *>(0)); | 
| 676 |     op = o.findChild<QObject*>(aName: "o12" , options: Qt::FindDirectChildrenOnly); | 
| 677 |     QCOMPARE(op, static_cast<QObject *>(0)); | 
| 678 |     op = o.findChild<QObject*>(aName: "o111" , options: Qt::FindDirectChildrenOnly); | 
| 679 |     QCOMPARE(op, static_cast<QObject *>(0)); | 
| 680 |     op = o.findChild<QObject*>(aName: "t1" , options: Qt::FindDirectChildrenOnly); | 
| 681 |     QCOMPARE(op, static_cast<QObject *>(&t1)); | 
| 682 |     op = o.findChild<QObject*>(aName: "t121" , options: Qt::FindDirectChildrenOnly); | 
| 683 |     QCOMPARE(op, static_cast<QObject *>(0)); | 
| 684 |     op = o.findChild<QTimer*>(aName: "t1" , options: Qt::FindDirectChildrenOnly); | 
| 685 |     QCOMPARE(op, static_cast<QObject *>(&t1)); | 
| 686 |     op = o.findChild<QTimer*>(aName: "t121" , options: Qt::FindDirectChildrenOnly); | 
| 687 |     QCOMPARE(op, static_cast<QObject *>(0)); | 
| 688 |     op = o.findChild<QTimer*>(aName: "o12" , options: Qt::FindDirectChildrenOnly); | 
| 689 |     QCOMPARE(op, static_cast<QObject *>(0)); | 
| 690 |     op = o.findChild<QObject*>(aName: "o" , options: Qt::FindDirectChildrenOnly); | 
| 691 |     QCOMPARE(op, static_cast<QObject *>(0)); | 
| 692 |     op = o.findChild<QObject*>(aName: "harry" , options: Qt::FindDirectChildrenOnly); | 
| 693 |     QCOMPARE(op, static_cast<QObject *>(0)); | 
| 694 |     op = o.findChild<QObject*>(aName: "o1" , options: Qt::FindDirectChildrenOnly); | 
| 695 |     QCOMPARE(op, &o1); | 
| 696 |  | 
| 697 |     l = o.findChildren<QObject*>(aName: "o1" , options: Qt::FindDirectChildrenOnly); | 
| 698 |     QCOMPARE(l.size(), 1); | 
| 699 |     QCOMPARE(l.at(0), &o1); | 
| 700 |     l = o.findChildren<QObject*>(aName: "o2" , options: Qt::FindDirectChildrenOnly); | 
| 701 |     QCOMPARE(l.size(), 1); | 
| 702 |     QCOMPARE(l.at(0), &o2); | 
| 703 |     l = o.findChildren<QObject*>(aName: "o11" , options: Qt::FindDirectChildrenOnly); | 
| 704 |     QCOMPARE(l.size(), 0); | 
| 705 |     l = o.findChildren<QObject*>(aName: "o12" , options: Qt::FindDirectChildrenOnly); | 
| 706 |     QCOMPARE(l.size(), 0); | 
| 707 |     l = o.findChildren<QObject*>(aName: "o111" , options: Qt::FindDirectChildrenOnly); | 
| 708 |     QCOMPARE(l.size(), 0); | 
| 709 |     l = o.findChildren<QObject*>(aName: "t1" , options: Qt::FindDirectChildrenOnly); | 
| 710 |     QCOMPARE(l.size(), 1); | 
| 711 |     QCOMPARE(l.at(0), static_cast<QObject *>(&t1)); | 
| 712 |     l = o.findChildren<QObject*>(aName: "t121" , options: Qt::FindDirectChildrenOnly); | 
| 713 |     QCOMPARE(l.size(), 0); | 
| 714 |     tl = o.findChildren<QTimer*>(aName: "t1" , options: Qt::FindDirectChildrenOnly); | 
| 715 |     QCOMPARE(tl.size(), 1); | 
| 716 |     QCOMPARE(tl.at(0), &t1); | 
| 717 |     tl = o.findChildren<QTimer*>(aName: "t121" , options: Qt::FindDirectChildrenOnly); | 
| 718 |     QCOMPARE(tl.size(), 0); | 
| 719 |     l = o.findChildren<QObject*>(aName: "o" , options: Qt::FindDirectChildrenOnly); | 
| 720 |     QCOMPARE(l.size(), 0); | 
| 721 |     l = o.findChildren<QObject*>(aName: "harry" , options: Qt::FindDirectChildrenOnly); | 
| 722 |     QCOMPARE(l.size(), 0); | 
| 723 |     tl = o.findChildren<QTimer*>(aName: "o12" , options: Qt::FindDirectChildrenOnly); | 
| 724 |     QCOMPARE(tl.size(), 0); | 
| 725 |     l = o.findChildren<QObject*>(aName: "o1" , options: Qt::FindDirectChildrenOnly); | 
| 726 |     QCOMPARE(l.size(), 1); | 
| 727 |     QCOMPARE(l.at(0), &o1); | 
| 728 |  | 
| 729 |     l = o.findChildren<QObject*>(re: QRegularExpression("^o.*$" ), options: Qt::FindDirectChildrenOnly); | 
| 730 |     QCOMPARE(l.size(), 2); | 
| 731 |     QVERIFY(l.contains(&o1)); | 
| 732 |     QVERIFY(l.contains(&o2)); | 
| 733 |     l = o.findChildren<QObject*>(re: QRegularExpression("^t.*$" ), options: Qt::FindDirectChildrenOnly); | 
| 734 |     QCOMPARE(l.size(), 1); | 
| 735 |     QVERIFY(l.contains(&t1)); | 
| 736 |     tl = o.findChildren<QTimer*>(re: QRegularExpression("^.*$" ), options: Qt::FindDirectChildrenOnly); | 
| 737 |     QCOMPARE(tl.size(), 2); | 
| 738 |     QVERIFY(tl.contains(&t1)); | 
| 739 |     tl = o.findChildren<QTimer*>(re: QRegularExpression("^o.*$" ), options: Qt::FindDirectChildrenOnly); | 
| 740 |     QCOMPARE(tl.size(), 0); | 
| 741 |     l = o.findChildren<QObject*>(re: QRegularExpression("^harry$" ), options: Qt::FindDirectChildrenOnly); | 
| 742 |     QCOMPARE(l.size(), 0); | 
| 743 |  | 
| 744 |     // empty and null string check | 
| 745 |     op = o.findChild<QObject*>(aName: QString(), options: Qt::FindDirectChildrenOnly); | 
| 746 |     QCOMPARE(op, &o1); | 
| 747 |     op = o.findChild<QObject*>(aName: "" , options: Qt::FindDirectChildrenOnly); | 
| 748 |     QCOMPARE(op, &unnamed); | 
| 749 |     op = o.findChild<QObject*>(aName: "unnamed" , options: Qt::FindDirectChildrenOnly); | 
| 750 |     QCOMPARE(op, static_cast<QObject *>(0)); | 
| 751 |  | 
| 752 |     l = o.findChildren<QObject*>(aName: QString(), options: Qt::FindDirectChildrenOnly); | 
| 753 |     QCOMPARE(l.size(), 5); | 
| 754 |     l = o.findChildren<QObject*>(aName: "" , options: Qt::FindDirectChildrenOnly); | 
| 755 |     QCOMPARE(l.size(), 2); | 
| 756 |     l = o.findChildren<QObject*>(aName: "unnamed" , options: Qt::FindDirectChildrenOnly); | 
| 757 |     QCOMPARE(l.size(), 0); | 
| 758 |  | 
| 759 |     tl = o.findChildren<QTimer *>(aName: "t1" , options: Qt::FindDirectChildrenOnly); | 
| 760 |     QCOMPARE(tl.size(), 1); | 
| 761 |     QCOMPARE(tl.at(0), &t1); | 
| 762 | } | 
| 763 |  | 
| 764 |  | 
| 765 | class NotifyObject : public SenderObject, public ReceiverObject | 
| 766 | { | 
| 767 | public: | 
| 768 |     NotifyObject() : SenderObject(), ReceiverObject() | 
| 769 |     {} | 
| 770 |  | 
| 771 |     QList<QMetaMethod> connectedSignals; | 
| 772 |     QList<QMetaMethod> disconnectedSignals; | 
| 773 |     void clearNotifications() | 
| 774 |     { | 
| 775 |         connectedSignals.clear(); | 
| 776 |         disconnectedSignals.clear(); | 
| 777 |     } | 
| 778 | protected: | 
| 779 |     void connectNotify(const QMetaMethod &signal) | 
| 780 |     { connectedSignals.append(t: signal); } | 
| 781 |     void disconnectNotify(const QMetaMethod &signal) | 
| 782 |     { disconnectedSignals.append(t: signal); } | 
| 783 | }; | 
| 784 |  | 
| 785 | void tst_QObject::connectDisconnectNotify_data() | 
| 786 | { | 
| 787 |     QTest::addColumn<QString>(name: "a_signal" ); | 
| 788 |     QTest::addColumn<QString>(name: "a_slot" ); | 
| 789 |  | 
| 790 |     QTest::newRow(dataTag: "combo1" ) << SIGNAL( signal1() )        << SLOT( slot1() ); | 
| 791 |     QTest::newRow(dataTag: "combo2" ) << SIGNAL( signal2(void) )    << SLOT( slot2(  ) ); | 
| 792 |     QTest::newRow(dataTag: "combo3" ) << SIGNAL( signal3(  ) )      << SLOT( slot3(void) ); | 
| 793 |     QTest::newRow(dataTag: "combo4" ) << SIGNAL(  signal4( void )  )<< SLOT(  slot4( void )  ); | 
| 794 |     QTest::newRow(dataTag: "combo5" ) << SIGNAL( signal6( void ) )  << SLOT( slot4() ); | 
| 795 |     QTest::newRow(dataTag: "combo6" ) << SIGNAL( signal6() )        << SLOT( slot4() ); | 
| 796 |     QTest::newRow(dataTag: "combo7" ) << SIGNAL( signal7( int , const QString & ) ) << SLOT( slot4() ); | 
| 797 | } | 
| 798 |  | 
| 799 | void tst_QObject::connectDisconnectNotify() | 
| 800 | { | 
| 801 |     NotifyObject s; | 
| 802 |     NotifyObject r; | 
| 803 |  | 
| 804 |     QFETCH(QString, a_signal); | 
| 805 |     QFETCH(QString, a_slot); | 
| 806 |  | 
| 807 |     // Obtaining meta methods | 
| 808 |     int signalIndx = ((SenderObject &)s).metaObject()->indexOfSignal( | 
| 809 |             signal: QMetaObject::normalizedSignature(method: a_signal.toLatin1().constData()+1).constData()); | 
| 810 |     int methodIndx = ((ReceiverObject &)r).metaObject()->indexOfMethod( | 
| 811 |             method: QMetaObject::normalizedSignature(method: a_slot.toLatin1().constData()+1).constData()); | 
| 812 |     QMetaMethod signal = ((SenderObject &)s).metaObject()->method(index: signalIndx); | 
| 813 |     QMetaMethod method = ((ReceiverObject &)r).metaObject()->method(index: methodIndx); | 
| 814 |     QVERIFY(signal.isValid()); | 
| 815 |     QVERIFY(method.isValid()); | 
| 816 |  | 
| 817 |     // Test connectNotify | 
| 818 |     QVERIFY(QObject::connect((SenderObject *)&s, a_signal.toLatin1(), | 
| 819 |                              (ReceiverObject *)&r, a_slot.toLatin1())); | 
| 820 |     QCOMPARE(s.connectedSignals.size(), 1); | 
| 821 |     QCOMPARE(s.connectedSignals.at(0), signal); | 
| 822 |     QVERIFY(s.disconnectedSignals.isEmpty()); | 
| 823 |  | 
| 824 |     // Test disconnectNotify | 
| 825 |     QVERIFY(QObject::disconnect((SenderObject *)&s, a_signal.toLatin1(), | 
| 826 |                                 (ReceiverObject *)&r, a_slot.toLatin1())); | 
| 827 |     QCOMPARE(s.disconnectedSignals.size(), 1); | 
| 828 |     QCOMPARE(s.disconnectedSignals.at(0), signal); | 
| 829 |     QCOMPARE(s.connectedSignals.size(), 1); | 
| 830 |  | 
| 831 |     // Reconnect | 
| 832 |     s.clearNotifications(); | 
| 833 |     QVERIFY(QObject::connect((SenderObject *)&s, a_signal.toLatin1(), | 
| 834 |                              (ReceiverObject *)&r, a_slot.toLatin1())); | 
| 835 |     QCOMPARE(s.connectedSignals.size(), 1); | 
| 836 |     QCOMPARE(s.connectedSignals.at(0), signal); | 
| 837 |     QVERIFY(s.disconnectedSignals.isEmpty()); | 
| 838 |  | 
| 839 |     // Test disconnectNotify for a complete disconnect | 
| 840 |     QVERIFY(((SenderObject *)&s)->disconnect((ReceiverObject *)&r)); | 
| 841 |     QCOMPARE(s.disconnectedSignals.size(), 1); | 
| 842 |     QCOMPARE(s.disconnectedSignals.at(0), QMetaMethod()); | 
| 843 |     QCOMPARE(s.connectedSignals.size(), 1); | 
| 844 |  | 
| 845 |     // Test connectNotify when connecting by QMetaMethod | 
| 846 |     s.clearNotifications(); | 
| 847 |     QVERIFY(QObject::connect((SenderObject *)&s, signal, (ReceiverObject *)&r, method)); | 
| 848 |     QCOMPARE(s.connectedSignals.size(), 1); | 
| 849 |     QCOMPARE(s.connectedSignals.at(0), signal); | 
| 850 |     QVERIFY(s.disconnectedSignals.isEmpty()); | 
| 851 |  | 
| 852 |     // Test disconnectNotify when disconnecting by QMetaMethod | 
| 853 |     QVERIFY(QObject::disconnect((SenderObject *)&s, signal, (ReceiverObject *)&r, method)); | 
| 854 |     QCOMPARE(s.disconnectedSignals.size(), 1); | 
| 855 |     QCOMPARE(s.disconnectedSignals.at(0), signal); | 
| 856 |     QCOMPARE(s.connectedSignals.size(), 1); | 
| 857 |  | 
| 858 |     // Reconnect | 
| 859 |     s.clearNotifications(); | 
| 860 |     QVERIFY(QObject::connect((SenderObject *)&s, a_signal.toLatin1(), | 
| 861 |                              (ReceiverObject *)&r, a_slot.toLatin1())); | 
| 862 |  | 
| 863 |     // Test disconnectNotify for a complete disconnect by QMetaMethod | 
| 864 |     QVERIFY(QObject::disconnect((SenderObject *)&s, QMetaMethod(), 0, QMetaMethod())); | 
| 865 |     QCOMPARE(s.disconnectedSignals.size(), 1); | 
| 866 |     QCOMPARE(s.disconnectedSignals.at(0), QMetaMethod()); | 
| 867 |     QCOMPARE(s.connectedSignals.size(), 1); | 
| 868 |  | 
| 869 |     // Test connectNotify when connecting by index | 
| 870 |     s.clearNotifications(); | 
| 871 |     QVERIFY(QMetaObject::connect((SenderObject *)&s, signalIndx, (ReceiverObject *)&r, methodIndx)); | 
| 872 |     QCOMPARE(s.connectedSignals.size(), 1); | 
| 873 |     QCOMPARE(s.connectedSignals.at(0), signal); | 
| 874 |     QVERIFY(s.disconnectedSignals.isEmpty()); | 
| 875 |  | 
| 876 |     // Test disconnectNotify when disconnecting by index | 
| 877 |     QVERIFY(QMetaObject::disconnect((SenderObject *)&s, signalIndx, | 
| 878 |                                     (ReceiverObject *)&r, methodIndx)); | 
| 879 |     QCOMPARE(s.disconnectedSignals.size(), 1); | 
| 880 |     QCOMPARE(s.disconnectedSignals.at(0), signal); | 
| 881 |     QCOMPARE(s.connectedSignals.size(), 1); | 
| 882 | } | 
| 883 |  | 
| 884 | static void connectDisconnectNotifyTestSlot() {} | 
| 885 |  | 
| 886 | void tst_QObject::connectDisconnectNotifyPMF() | 
| 887 | { | 
| 888 |     NotifyObject s; | 
| 889 |     NotifyObject r; | 
| 890 |  | 
| 891 |     QMetaMethod signal = QMetaMethod::fromSignal(signal: &SenderObject::signal1); | 
| 892 |  | 
| 893 |     // Test connectNotify | 
| 894 |     QVERIFY(QObject::connect((SenderObject *)&s, &SenderObject::signal1, | 
| 895 |                              (ReceiverObject *)&r, &ReceiverObject::slot1)); | 
| 896 |     QCOMPARE(s.connectedSignals.size(), 1); | 
| 897 |     QCOMPARE(s.connectedSignals.at(0), signal); | 
| 898 |     QVERIFY(s.disconnectedSignals.isEmpty()); | 
| 899 |  | 
| 900 |     // Test disconnectNotify | 
| 901 |     QVERIFY(QObject::disconnect((SenderObject *)&s, &SenderObject::signal1, | 
| 902 |                                 (ReceiverObject *)&r, &ReceiverObject::slot1)); | 
| 903 |     QCOMPARE(s.disconnectedSignals.size(), 1); | 
| 904 |     QCOMPARE(s.disconnectedSignals.at(0), signal); | 
| 905 |     QCOMPARE(s.connectedSignals.size(), 1); | 
| 906 |  | 
| 907 |     // Reconnect | 
| 908 |     s.clearNotifications(); | 
| 909 |     QVERIFY(QObject::connect((SenderObject *)&s, &SenderObject::signal1, | 
| 910 |                              (ReceiverObject *)&r, &ReceiverObject::slot1)); | 
| 911 |     QCOMPARE(s.connectedSignals.size(), 1); | 
| 912 |     QCOMPARE(s.connectedSignals.at(0), signal); | 
| 913 |     QVERIFY(s.disconnectedSignals.isEmpty()); | 
| 914 |  | 
| 915 |     // Test disconnectNotify with wildcard slot | 
| 916 |     QVERIFY(QObject::disconnect((SenderObject *)&s, &SenderObject::signal1, | 
| 917 |                                 (ReceiverObject *)&r, 0)); | 
| 918 |     QCOMPARE(s.disconnectedSignals.size(), 1); | 
| 919 |     QCOMPARE(s.disconnectedSignals.at(0), signal); | 
| 920 |     QCOMPARE(s.connectedSignals.size(), 1); | 
| 921 |  | 
| 922 |     // Reconnect | 
| 923 |     s.clearNotifications(); | 
| 924 |     QMetaObject::Connection conn = connect(sender: (SenderObject *)&s, signal: &SenderObject::signal1, | 
| 925 |                                            receiver: (ReceiverObject *)&r, slot: &ReceiverObject::slot1); | 
| 926 |  | 
| 927 |     QVERIFY(conn); | 
| 928 |  | 
| 929 |     // Test disconnectNotify when disconnecting by QMetaObject::Connection | 
| 930 |     QVERIFY(QObject::disconnect(conn)); | 
| 931 |     QVERIFY(!s.disconnectedSignals.isEmpty()); | 
| 932 |  | 
| 933 |     // Test connectNotify when connecting by function pointer | 
| 934 |     s.clearNotifications(); | 
| 935 |     QVERIFY(QObject::connect((SenderObject *)&s, &SenderObject::signal1, | 
| 936 |                              connectDisconnectNotifyTestSlot)); | 
| 937 |     QCOMPARE(s.connectedSignals.size(), 1); | 
| 938 |     QCOMPARE(s.connectedSignals.at(0), signal); | 
| 939 |     QVERIFY(s.disconnectedSignals.isEmpty()); | 
| 940 | } | 
| 941 |  | 
| 942 | void tst_QObject::disconnectNotify_receiverDestroyed() | 
| 943 | { | 
| 944 |     NotifyObject s; | 
| 945 |  | 
| 946 |     { | 
| 947 |         NotifyObject r; | 
| 948 |         QVERIFY(QObject::connect((SenderObject *)&s, SIGNAL(signal1()), | 
| 949 |                                  (ReceiverObject *)&r, SLOT(slot1()))); | 
| 950 |     } | 
| 951 |     QCOMPARE(s.disconnectedSignals.count(), 1); | 
| 952 |     QCOMPARE(s.disconnectedSignals.at(0), QMetaMethod::fromSignal(&SenderObject::signal1)); | 
| 953 |  | 
| 954 |     s.disconnectedSignals.clear(); | 
| 955 |  | 
| 956 |     { | 
| 957 |         NotifyObject r; | 
| 958 |         QVERIFY(QObject::connect((SenderObject *)&s, SIGNAL(signal3()), | 
| 959 |                                  (ReceiverObject *)&r, SLOT(slot3()))); | 
| 960 |     } | 
| 961 |  | 
| 962 |     QCOMPARE(s.disconnectedSignals.count(), 1); | 
| 963 |     QCOMPARE(s.disconnectedSignals.at(0), QMetaMethod::fromSignal(&SenderObject::signal3)); | 
| 964 |  | 
| 965 |     s.disconnectedSignals.clear(); | 
| 966 |  | 
| 967 |     { | 
| 968 |         NotifyObject r; | 
| 969 |         QVERIFY(QObject::connect((SenderObject *)&s, SIGNAL(destroyed()), (ReceiverObject *)&r, SLOT(slot3()))); | 
| 970 |     } | 
| 971 |  | 
| 972 |     QCOMPARE(s.disconnectedSignals.count(), 1); | 
| 973 |     QCOMPARE(s.disconnectedSignals.at(0), QMetaMethod::fromSignal(&QObject::destroyed)); | 
| 974 | } | 
| 975 |  | 
| 976 | void tst_QObject::disconnectNotify_metaObjConnection() | 
| 977 | { | 
| 978 |     NotifyObject s; | 
| 979 |     { | 
| 980 |         NotifyObject r; | 
| 981 |  | 
| 982 |         QMetaObject::Connection c = QObject::connect(sender: (SenderObject *)&s, SIGNAL(signal1()), | 
| 983 |                                                      receiver: (ReceiverObject *)&r, SLOT(slot1())); | 
| 984 |         QVERIFY(c); | 
| 985 |         QVERIFY(QObject::disconnect(c)); | 
| 986 |  | 
| 987 |         QCOMPARE(s.disconnectedSignals.count(), 1); | 
| 988 |         QCOMPARE(s.disconnectedSignals.at(0), QMetaMethod::fromSignal(&SenderObject::signal1)); | 
| 989 |  | 
| 990 |         QCOMPARE(s.disconnectedSignals.count(), 1); | 
| 991 |     } | 
| 992 | } | 
| 993 |  | 
| 994 | class ConnectByNameNotifySenderObject : public QObject | 
| 995 | { | 
| 996 |     Q_OBJECT | 
| 997 | public: | 
| 998 |     QList<QMetaMethod> connectedSignals; | 
| 999 |     QList<QMetaMethod> disconnectedSignals; | 
| 1000 |     void clearNotifications() | 
| 1001 |     { | 
| 1002 |         connectedSignals.clear(); | 
| 1003 |         disconnectedSignals.clear(); | 
| 1004 |     } | 
| 1005 | protected: | 
| 1006 |     void connectNotify(const QMetaMethod &signal) | 
| 1007 |     { connectedSignals.append(t: signal); } | 
| 1008 |     void disconnectNotify(const QMetaMethod &signal) | 
| 1009 |     { disconnectedSignals.append(t: signal); } | 
| 1010 | Q_SIGNALS: | 
| 1011 |     void signal1(); | 
| 1012 | }; | 
| 1013 |  | 
| 1014 | class ConnectByNameNotifyReceiverObject : public QObject | 
| 1015 | { | 
| 1016 |     Q_OBJECT | 
| 1017 |     void createNotifyChild(const char *name) | 
| 1018 |     { | 
| 1019 |         QObject *o = new ConnectByNameNotifySenderObject; | 
| 1020 |         o->setParent(this); | 
| 1021 |         o->setObjectName(QString::fromLatin1(str: name)); | 
| 1022 |     } | 
| 1023 | public: | 
| 1024 |     ConnectByNameNotifyReceiverObject() | 
| 1025 |     { | 
| 1026 |         createNotifyChild(name: "foo" ); | 
| 1027 |         createNotifyChild(name: "bar" ); | 
| 1028 |         createNotifyChild(name: "baz" ); | 
| 1029 |     }; | 
| 1030 |  | 
| 1031 | public Q_SLOTS: | 
| 1032 |     void on_foo_signal1() {} | 
| 1033 |     void on_bar_signal1() {} | 
| 1034 |     void on_baz_signal1() {} | 
| 1035 | }; | 
| 1036 |  | 
| 1037 | void tst_QObject::connectNotify_connectSlotsByName() | 
| 1038 | { | 
| 1039 |     ConnectByNameNotifyReceiverObject testObject; | 
| 1040 |     const QList<ConnectByNameNotifySenderObject *> senders = | 
| 1041 |             testObject.findChildren<ConnectByNameNotifySenderObject *>(); | 
| 1042 |     for (ConnectByNameNotifySenderObject *o : senders) { | 
| 1043 |         QVERIFY(o->connectedSignals.isEmpty()); | 
| 1044 |         QVERIFY(o->disconnectedSignals.isEmpty()); | 
| 1045 |     } | 
| 1046 |  | 
| 1047 |     QMetaObject::connectSlotsByName(o: &testObject); | 
| 1048 |  | 
| 1049 |     for (ConnectByNameNotifySenderObject *o : senders) { | 
| 1050 |         QCOMPARE(o->connectedSignals.size(), 1); | 
| 1051 |         QCOMPARE(o->connectedSignals.at(0), QMetaMethod::fromSignal(&ConnectByNameNotifySenderObject::signal1)); | 
| 1052 |         QVERIFY(o->disconnectedSignals.isEmpty()); | 
| 1053 |     } | 
| 1054 | } | 
| 1055 |  | 
| 1056 | class ConnectDisconnectNotifyShadowObject | 
| 1057 |         : public ConnectByNameNotifySenderObject | 
| 1058 | { | 
| 1059 |     Q_OBJECT | 
| 1060 | public Q_SLOTS: | 
| 1061 |     void slot1() {} | 
| 1062 | Q_SIGNALS: | 
| 1063 |     void signal1(); | 
| 1064 | }; | 
| 1065 |  | 
| 1066 | void tst_QObject::connectDisconnectNotify_shadowing() | 
| 1067 | { | 
| 1068 |     ConnectDisconnectNotifyShadowObject s; | 
| 1069 |     // Obtain QMetaMethods | 
| 1070 |     QMetaMethod shadowedSignal1 = QMetaMethod::fromSignal(signal: &ConnectByNameNotifySenderObject::signal1); | 
| 1071 |     QMetaMethod redefinedSignal1 = QMetaMethod::fromSignal(signal: &ConnectDisconnectNotifyShadowObject::signal1); | 
| 1072 |     QVERIFY(shadowedSignal1 != redefinedSignal1); | 
| 1073 |     int slot1Index = s.metaObject()->indexOfSlot(slot: "slot1()" ); | 
| 1074 |     QVERIFY(slot1Index != -1); | 
| 1075 |     QMetaMethod slot1 = s.metaObject()->method(index: slot1Index); | 
| 1076 |  | 
| 1077 |     // Test connectNotify | 
| 1078 | #ifndef QT_NO_DEBUG | 
| 1079 |     const char *warning = "QMetaObject::indexOfSignal: signal signal1() from "  | 
| 1080 |                           "ConnectByNameNotifySenderObject redefined in "  | 
| 1081 |                           "ConnectDisconnectNotifyShadowObject" ; | 
| 1082 |     QTest::ignoreMessage(type: QtWarningMsg, message: warning); | 
| 1083 | #endif | 
| 1084 |     QVERIFY(QObject::connect(&s, SIGNAL(signal1()), &s, SLOT(slot1()))); | 
| 1085 |     QCOMPARE(s.connectedSignals.size(), 1); | 
| 1086 |     QCOMPARE(s.connectedSignals.at(0), redefinedSignal1); | 
| 1087 |     QVERIFY(s.disconnectedSignals.isEmpty()); | 
| 1088 |  | 
| 1089 |     // Test disconnectNotify | 
| 1090 | #ifndef QT_NO_DEBUG | 
| 1091 |     QTest::ignoreMessage(type: QtWarningMsg, message: warning); | 
| 1092 | #endif | 
| 1093 |     QVERIFY(QObject::disconnect(&s, SIGNAL(signal1()), &s, SLOT(slot1()))); | 
| 1094 |     QCOMPARE(s.disconnectedSignals.size(), 1); | 
| 1095 |     QCOMPARE(s.disconnectedSignals.at(0), redefinedSignal1); | 
| 1096 |     QCOMPARE(s.connectedSignals.size(), 1); | 
| 1097 |  | 
| 1098 |     // Test connectNotify when connecting by shadowed QMetaMethod | 
| 1099 |     s.clearNotifications(); | 
| 1100 |     QVERIFY(QObject::connect(&s, shadowedSignal1, &s, slot1)); | 
| 1101 |     QCOMPARE(s.connectedSignals.size(), 1); | 
| 1102 |     QCOMPARE(s.connectedSignals.at(0), shadowedSignal1); | 
| 1103 |     QVERIFY(s.disconnectedSignals.isEmpty()); | 
| 1104 |  | 
| 1105 |     // Test disconnectNotify when disconnecting by shadowed QMetaMethod | 
| 1106 |     QVERIFY(QObject::disconnect(&s, shadowedSignal1, &s, slot1)); | 
| 1107 |     QCOMPARE(s.disconnectedSignals.size(), 1); | 
| 1108 |     QCOMPARE(s.disconnectedSignals.at(0), shadowedSignal1); | 
| 1109 |     QCOMPARE(s.connectedSignals.size(), 1); | 
| 1110 |  | 
| 1111 |     // Test connectNotify when connecting by redefined QMetaMethod | 
| 1112 |     s.clearNotifications(); | 
| 1113 |     QVERIFY(QObject::connect(&s, redefinedSignal1, &s, slot1)); | 
| 1114 |     QCOMPARE(s.connectedSignals.size(), 1); | 
| 1115 |     QCOMPARE(s.connectedSignals.at(0), redefinedSignal1); | 
| 1116 |     QVERIFY(s.disconnectedSignals.isEmpty()); | 
| 1117 |  | 
| 1118 |     // Test disconnectNotify when disconnecting by redefined QMetaMethod | 
| 1119 |     QVERIFY(QObject::disconnect(&s, redefinedSignal1, &s, slot1)); | 
| 1120 |     QCOMPARE(s.disconnectedSignals.size(), 1); | 
| 1121 |     QCOMPARE(s.disconnectedSignals.at(0), redefinedSignal1); | 
| 1122 |     QCOMPARE(s.connectedSignals.size(), 1); | 
| 1123 | } | 
| 1124 |  | 
| 1125 | class SequenceObject : public ReceiverObject | 
| 1126 | { | 
| 1127 |     Q_OBJECT | 
| 1128 |  | 
| 1129 | public: | 
| 1130 |     QObject *next; | 
| 1131 |     SequenceObject() : next(0) { } | 
| 1132 |  | 
| 1133 | public slots: | 
| 1134 |     void slot1_disconnectThis() | 
| 1135 |     { | 
| 1136 |         slot1(); | 
| 1137 |         disconnect(sender: sender(), SIGNAL(signal1()), receiver: this, SLOT(slot1_disconnectThis())); | 
| 1138 |     } | 
| 1139 |  | 
| 1140 |     void slot2_reconnectThis() | 
| 1141 |     { | 
| 1142 |         slot2(); | 
| 1143 |  | 
| 1144 |         const QObject *s = sender(); | 
| 1145 |         disconnect(sender: s, SIGNAL(signal1()), receiver: this, SLOT(slot2_reconnectThis())); | 
| 1146 |         connect(sender: s, SIGNAL(signal1()), receiver: this, SLOT(slot2_reconnectThis())); | 
| 1147 |     } | 
| 1148 |  | 
| 1149 |     void slot1_disconnectNext() | 
| 1150 |     { | 
| 1151 |         slot1(); | 
| 1152 |         disconnect(sender: sender(), SIGNAL(signal1()), receiver: next, SLOT(slot1())); | 
| 1153 |     } | 
| 1154 |  | 
| 1155 |     void slot2_reconnectNext() | 
| 1156 |     { | 
| 1157 |         slot2(); | 
| 1158 |  | 
| 1159 |         // modify the connection list in 'this' | 
| 1160 |         disconnect(sender: sender(), SIGNAL(signal1()), receiver: next, SLOT(slot2())); | 
| 1161 |         connect(sender: sender(), SIGNAL(signal1()), receiver: next, SLOT(slot2())); | 
| 1162 |  | 
| 1163 |         // modify the sender list in 'this' | 
| 1164 |         connect(sender: next, SIGNAL(destroyed()), receiver: this, SLOT(deleteLater())); | 
| 1165 |         connect(sender: QCoreApplication::instance(), SIGNAL(aboutToQuit()), receiver: this, SLOT(deleteLater())); | 
| 1166 |         disconnect(sender: next, SIGNAL(destroyed()), receiver: this, SLOT(deleteLater())); | 
| 1167 |         disconnect(sender: QCoreApplication::instance(), SIGNAL(aboutToQuit()), receiver: this, SLOT(deleteLater())); | 
| 1168 |     } | 
| 1169 |  | 
| 1170 |     void slot1_deleteNext() | 
| 1171 |     { | 
| 1172 |         slot1(); | 
| 1173 |         delete next; | 
| 1174 |     } | 
| 1175 |  | 
| 1176 |     void slot2_deleteSender() | 
| 1177 |     { | 
| 1178 |         slot2(); | 
| 1179 |         delete sender(); | 
| 1180 |     } | 
| 1181 | }; | 
| 1182 |  | 
| 1183 | void tst_QObject::emitInDefinedOrder() | 
| 1184 | { | 
| 1185 |     SenderObject sender; | 
| 1186 |     ReceiverObject receiver1, receiver2, receiver3, receiver4; | 
| 1187 |  | 
| 1188 |     connect(sender: &sender, SIGNAL(signal1()), receiver: &receiver1, SLOT(slot1())); | 
| 1189 |     connect(sender: &sender, SIGNAL(signal1()), receiver: &receiver2, SLOT(slot1())); | 
| 1190 |     connect(sender: &sender, SIGNAL(signal1()), receiver: &receiver3, SLOT(slot1())); | 
| 1191 |     connect(sender: &sender, SIGNAL(signal1()), receiver: &receiver4, SLOT(slot1())); | 
| 1192 |     connect(sender: &sender, SIGNAL(signal1()), receiver: &receiver1, SLOT(slot2())); | 
| 1193 |     connect(sender: &sender, SIGNAL(signal1()), receiver: &receiver2, SLOT(slot2())); | 
| 1194 |     connect(sender: &sender, SIGNAL(signal1()), receiver: &receiver3, SLOT(slot2())); | 
| 1195 |     connect(sender: &sender, SIGNAL(signal1()), receiver: &receiver4, SLOT(slot2())); | 
| 1196 |  | 
| 1197 |     int sequence; | 
| 1198 |     ReceiverObject::sequence = sequence = 0; | 
| 1199 |     sender.emitSignal1(); | 
| 1200 |     QCOMPARE(receiver1.sequence_slot1, ++sequence); | 
| 1201 |     QCOMPARE(receiver2.sequence_slot1, ++sequence); | 
| 1202 |     QCOMPARE(receiver3.sequence_slot1, ++sequence); | 
| 1203 |     QCOMPARE(receiver4.sequence_slot1, ++sequence); | 
| 1204 |     QCOMPARE(receiver1.sequence_slot2, ++sequence); | 
| 1205 |     QCOMPARE(receiver2.sequence_slot2, ++sequence); | 
| 1206 |     QCOMPARE(receiver3.sequence_slot2, ++sequence); | 
| 1207 |     QCOMPARE(receiver4.sequence_slot2, ++sequence); | 
| 1208 |  | 
| 1209 |     QObject::disconnect(sender: &sender, SIGNAL(signal1()), receiver: &receiver2, SLOT(slot1())); | 
| 1210 |     connect(sender: &sender, SIGNAL(signal1()), receiver: &receiver2, SLOT(slot1())); | 
| 1211 |  | 
| 1212 |     ReceiverObject::sequence = sequence =  0; | 
| 1213 |     sender.emitSignal1(); | 
| 1214 |     QCOMPARE(receiver1.sequence_slot1, ++sequence); | 
| 1215 |     QCOMPARE(receiver3.sequence_slot1, ++sequence); | 
| 1216 |     QCOMPARE(receiver4.sequence_slot1, ++sequence); | 
| 1217 |     QCOMPARE(receiver1.sequence_slot2, ++sequence); | 
| 1218 |     QCOMPARE(receiver2.sequence_slot2, ++sequence); | 
| 1219 |     QCOMPARE(receiver3.sequence_slot2, ++sequence); | 
| 1220 |     QCOMPARE(receiver4.sequence_slot2, ++sequence); | 
| 1221 |     QCOMPARE(receiver2.sequence_slot1, ++sequence); | 
| 1222 |  | 
| 1223 |     QObject::disconnect(sender: &sender, SIGNAL(signal1()), receiver: &receiver1, SLOT(slot1())); | 
| 1224 |     connect(sender: &sender, SIGNAL(signal1()), receiver: &receiver1, SLOT(slot1())); | 
| 1225 |  | 
| 1226 |     ReceiverObject::sequence = sequence =  0; | 
| 1227 |     sender.emitSignal1(); | 
| 1228 |     QCOMPARE(receiver3.sequence_slot1, ++sequence); | 
| 1229 |     QCOMPARE(receiver4.sequence_slot1, ++sequence); | 
| 1230 |     QCOMPARE(receiver1.sequence_slot2, ++sequence); | 
| 1231 |     QCOMPARE(receiver2.sequence_slot2, ++sequence); | 
| 1232 |     QCOMPARE(receiver3.sequence_slot2, ++sequence); | 
| 1233 |     QCOMPARE(receiver4.sequence_slot2, ++sequence); | 
| 1234 |     QCOMPARE(receiver2.sequence_slot1, ++sequence); | 
| 1235 |     QCOMPARE(receiver1.sequence_slot1, ++sequence); | 
| 1236 |  | 
| 1237 |     // ensure emission order even if the connections change during emission | 
| 1238 |     SenderObject *sender2 = new SenderObject; | 
| 1239 |     SequenceObject seq1, seq2, *seq3 = new SequenceObject, seq4; | 
| 1240 |     seq1.next = &seq2; | 
| 1241 |     seq2.next = seq3; | 
| 1242 |     seq3->next = &seq4; | 
| 1243 |  | 
| 1244 |     // try 1 | 
| 1245 |     connect(sender: sender2, SIGNAL(signal1()), receiver: &seq1, SLOT(slot1_disconnectThis())); | 
| 1246 |     connect(sender: sender2, SIGNAL(signal1()), receiver: &seq2, SLOT(slot1_disconnectNext())); | 
| 1247 |     connect(sender: sender2, SIGNAL(signal1()), receiver: seq3, SLOT(slot1())); | 
| 1248 |     connect(sender: sender2, SIGNAL(signal1()), receiver: &seq4, SLOT(slot1())); | 
| 1249 |     connect(sender: sender2, SIGNAL(signal1()), receiver: &seq1, SLOT(slot2_reconnectThis())); | 
| 1250 |     connect(sender: sender2, SIGNAL(signal1()), receiver: &seq2, SLOT(slot2_reconnectNext())); | 
| 1251 |     connect(sender: sender2, SIGNAL(signal1()), receiver: seq3, SLOT(slot2())); | 
| 1252 |     connect(sender: sender2, SIGNAL(signal1()), receiver: &seq4, SLOT(slot2())); | 
| 1253 |  | 
| 1254 |     SequenceObject::sequence = sequence = 0; | 
| 1255 |     sender2->emitSignal1(); | 
| 1256 |     QVERIFY(seq1.called(1)); | 
| 1257 |     QVERIFY(seq2.called(1)); | 
| 1258 |     QVERIFY(!seq3->called(1)); | 
| 1259 |     QVERIFY(seq4.called(1)); | 
| 1260 |     QVERIFY(seq1.called(2)); | 
| 1261 |     QVERIFY(seq2.called(2)); | 
| 1262 |     QVERIFY(!seq3->called(2)); | 
| 1263 |     QVERIFY(seq4.called(2)); | 
| 1264 |     QCOMPARE(seq1.sequence_slot1, ++sequence); | 
| 1265 |     QCOMPARE(seq2.sequence_slot1, ++sequence); | 
| 1266 |     QCOMPARE(seq4.sequence_slot1, ++sequence); | 
| 1267 |     QCOMPARE(seq1.sequence_slot2, ++sequence); | 
| 1268 |     QCOMPARE(seq2.sequence_slot2, ++sequence); | 
| 1269 |     QCOMPARE(seq4.sequence_slot2, ++sequence); | 
| 1270 |  | 
| 1271 |     QObject::disconnect(sender: sender2, signal: 0, receiver: &seq1, member: 0); | 
| 1272 |     QObject::disconnect(sender: sender2, signal: 0, receiver: &seq2, member: 0); | 
| 1273 |     QObject::disconnect(sender: sender2, signal: 0, receiver: seq3, member: 0); | 
| 1274 |     QObject::disconnect(sender: sender2, signal: 0, receiver: &seq4, member: 0); | 
| 1275 |     seq1.reset(); | 
| 1276 |     seq2.reset(); | 
| 1277 |     seq3->reset(); | 
| 1278 |     seq4.reset(); | 
| 1279 |  | 
| 1280 |     // try 2 | 
| 1281 |     connect(sender: sender2, SIGNAL(signal1()), receiver: &seq1, SLOT(slot2_reconnectThis())); | 
| 1282 |     connect(sender: sender2, SIGNAL(signal1()), receiver: &seq2, SLOT(slot2_reconnectNext())); | 
| 1283 |     connect(sender: sender2, SIGNAL(signal1()), receiver: seq3, SLOT(slot2())); | 
| 1284 |     connect(sender: sender2, SIGNAL(signal1()), receiver: &seq4, SLOT(slot2())); | 
| 1285 |     connect(sender: sender2, SIGNAL(signal1()), receiver: &seq1, SLOT(slot1_disconnectThis())); | 
| 1286 |     connect(sender: sender2, SIGNAL(signal1()), receiver: &seq2, SLOT(slot1_disconnectNext())); | 
| 1287 |     connect(sender: sender2, SIGNAL(signal1()), receiver: seq3, SLOT(slot1())); | 
| 1288 |     connect(sender: sender2, SIGNAL(signal1()), receiver: &seq4, SLOT(slot1())); | 
| 1289 |  | 
| 1290 |     SequenceObject::sequence = sequence = 0; | 
| 1291 |     sender2->emitSignal1(); | 
| 1292 |     QVERIFY(seq1.called(2)); | 
| 1293 |     QVERIFY(seq2.called(2)); | 
| 1294 |     QVERIFY(!seq3->called(2)); | 
| 1295 |     QVERIFY(seq4.called(2)); | 
| 1296 |     QVERIFY(seq1.called(1)); | 
| 1297 |     QVERIFY(seq2.called(1)); | 
| 1298 |     QVERIFY(!seq3->called(1)); | 
| 1299 |     QVERIFY(seq4.called(1)); | 
| 1300 |     QCOMPARE(seq1.sequence_slot2, ++sequence); | 
| 1301 |     QCOMPARE(seq2.sequence_slot2, ++sequence); | 
| 1302 |     QCOMPARE(seq4.sequence_slot2, ++sequence); | 
| 1303 |     QCOMPARE(seq1.sequence_slot1, ++sequence); | 
| 1304 |     QCOMPARE(seq2.sequence_slot1, ++sequence); | 
| 1305 |     QCOMPARE(seq4.sequence_slot1, ++sequence); | 
| 1306 |  | 
| 1307 |     QObject::disconnect(sender: sender2, signal: 0, receiver: &seq1, member: 0); | 
| 1308 |     QObject::disconnect(sender: sender2, signal: 0, receiver: &seq2, member: 0); | 
| 1309 |     QObject::disconnect(sender: sender2, signal: 0, receiver: seq3, member: 0); | 
| 1310 |     QObject::disconnect(sender: sender2, signal: 0, receiver: &seq4, member: 0); | 
| 1311 |     seq1.reset(); | 
| 1312 |     seq2.reset(); | 
| 1313 |     seq3->reset(); | 
| 1314 |     seq4.reset(); | 
| 1315 |  | 
| 1316 |     // try 3 | 
| 1317 |     connect(sender: sender2, SIGNAL(signal1()), receiver: &seq1, SLOT(slot1())); | 
| 1318 |     connect(sender: sender2, SIGNAL(signal1()), receiver: &seq2, SLOT(slot1_disconnectNext())); | 
| 1319 |     connect(sender: sender2, SIGNAL(signal1()), receiver: seq3, SLOT(slot1())); | 
| 1320 |     connect(sender: sender2, SIGNAL(signal1()), receiver: &seq4, SLOT(slot1())); | 
| 1321 |     connect(sender: sender2, SIGNAL(signal1()), receiver: &seq1, SLOT(slot2())); | 
| 1322 |     connect(sender: sender2, SIGNAL(signal1()), receiver: &seq2, SLOT(slot2_reconnectNext())); | 
| 1323 |     connect(sender: sender2, SIGNAL(signal1()), receiver: seq3, SLOT(slot2())); | 
| 1324 |     connect(sender: sender2, SIGNAL(signal1()), receiver: &seq4, SLOT(slot2())); | 
| 1325 |  | 
| 1326 |     SequenceObject::sequence = sequence = 0; | 
| 1327 |     sender2->emitSignal1(); | 
| 1328 |     QVERIFY(seq1.called(1)); | 
| 1329 |     QVERIFY(seq2.called(1)); | 
| 1330 |     QVERIFY(!seq3->called(1)); | 
| 1331 |     QVERIFY(seq4.called(1)); | 
| 1332 |     QVERIFY(seq1.called(2)); | 
| 1333 |     QVERIFY(seq2.called(2)); | 
| 1334 |     QVERIFY(!seq3->called(2)); | 
| 1335 |     QVERIFY(seq4.called(2)); | 
| 1336 |     QCOMPARE(seq1.sequence_slot1, ++sequence); | 
| 1337 |     QCOMPARE(seq2.sequence_slot1, ++sequence); | 
| 1338 |     QCOMPARE(seq4.sequence_slot1, ++sequence); | 
| 1339 |     QCOMPARE(seq1.sequence_slot2, ++sequence); | 
| 1340 |     QCOMPARE(seq2.sequence_slot2, ++sequence); | 
| 1341 |     QCOMPARE(seq4.sequence_slot2, ++sequence); | 
| 1342 |  | 
| 1343 |     // ensure emission order even if objects are destroyed during emission | 
| 1344 |     QObject::disconnect(sender: sender2, signal: 0, receiver: &seq1, member: 0); | 
| 1345 |     QObject::disconnect(sender: sender2, signal: 0, receiver: &seq2, member: 0); | 
| 1346 |     QObject::disconnect(sender: sender2, signal: 0, receiver: seq3, member: 0); | 
| 1347 |     QObject::disconnect(sender: sender2, signal: 0, receiver: &seq4, member: 0); | 
| 1348 |     seq1.reset(); | 
| 1349 |     seq2.reset(); | 
| 1350 |     seq3->reset(); | 
| 1351 |     seq4.reset(); | 
| 1352 |  | 
| 1353 |     connect(sender: sender2, SIGNAL(signal1()), receiver: &seq1, SLOT(slot1())); | 
| 1354 |     connect(sender: sender2, SIGNAL(signal1()), receiver: &seq2, SLOT(slot1_deleteNext())); | 
| 1355 |     connect(sender: sender2, SIGNAL(signal1()), receiver: seq3, SLOT(slot1())); | 
| 1356 |     connect(sender: sender2, SIGNAL(signal1()), receiver: &seq4, SLOT(slot1())); | 
| 1357 |     connect(sender: sender2, SIGNAL(signal1()), receiver: &seq1, SLOT(slot2())); | 
| 1358 |     connect(sender: sender2, SIGNAL(signal1()), receiver: &seq2, SLOT(slot2_deleteSender())); | 
| 1359 |     connect(sender: sender2, SIGNAL(signal1()), receiver: seq3, SLOT(slot2())); | 
| 1360 |     connect(sender: sender2, SIGNAL(signal1()), receiver: &seq4, SLOT(slot2())); | 
| 1361 |  | 
| 1362 |     QPointer<SenderObject> psender = sender2; | 
| 1363 |     QPointer<SequenceObject> pseq3 = seq3; | 
| 1364 |  | 
| 1365 |     SequenceObject::sequence = sequence = 0; | 
| 1366 |     sender2->emitSignal1(); | 
| 1367 |     QCOMPARE(static_cast<QObject *>(psender), static_cast<QObject *>(0)); | 
| 1368 |     QCOMPARE(static_cast<QObject *>(pseq3), static_cast<QObject *>(0)); | 
| 1369 |     QVERIFY(seq1.called(1)); | 
| 1370 |     QVERIFY(seq2.called(1)); | 
| 1371 |     QVERIFY(seq4.called(1)); | 
| 1372 |     QVERIFY(seq1.called(2)); | 
| 1373 |     QVERIFY(seq2.called(2)); | 
| 1374 |     QVERIFY(!seq4.called(2)); | 
| 1375 |     QCOMPARE(seq1.sequence_slot1, ++sequence); | 
| 1376 |     QCOMPARE(seq2.sequence_slot1, ++sequence); | 
| 1377 |     QCOMPARE(seq4.sequence_slot1, ++sequence); | 
| 1378 |     QCOMPARE(seq1.sequence_slot2, ++sequence); | 
| 1379 |     QCOMPARE(seq2.sequence_slot2, ++sequence); | 
| 1380 |  | 
| 1381 |     QPointer<SenderObject> psender3 = new SenderObject; | 
| 1382 |     connect(sender: psender3, SIGNAL(signal1()), receiver: psender3, SIGNAL(signal2())); | 
| 1383 |     connect(sender: psender3, SIGNAL(signal2()), receiver: &seq1, SLOT(slot2_deleteSender())); | 
| 1384 |     psender3->emitSignal1(); | 
| 1385 |     QVERIFY(!psender3); | 
| 1386 | } | 
| 1387 |  | 
| 1388 | static int instanceCount = 0; | 
| 1389 |  | 
| 1390 | struct CheckInstanceCount | 
| 1391 | { | 
| 1392 |     const int saved; | 
| 1393 |     CheckInstanceCount() : saved(instanceCount) {} | 
| 1394 |     ~CheckInstanceCount() { QCOMPARE(saved, instanceCount); } | 
| 1395 | }; | 
| 1396 |  | 
| 1397 |  | 
| 1398 | struct CustomType | 
| 1399 | { | 
| 1400 |     CustomType(int l1 = 0, int l2 = 0, int l3 = 0): i1(l1), i2(l2), i3(l3) | 
| 1401 |     { ++instanceCount; playWithObjects(); } | 
| 1402 |     CustomType(const CustomType &other): i1(other.i1), i2(other.i2), i3(other.i3) | 
| 1403 |     { ++instanceCount; playWithObjects(); } | 
| 1404 |     ~CustomType() { --instanceCount; playWithObjects(); } | 
| 1405 |     CustomType &operator=(const CustomType &) = default; | 
| 1406 |  | 
| 1407 |     int i1, i2, i3; | 
| 1408 |     int value() { return i1 + i2 + i3; } | 
| 1409 | }; | 
| 1410 |  | 
| 1411 | Q_DECLARE_METATYPE(CustomType*) | 
| 1412 | Q_DECLARE_METATYPE(CustomType) | 
| 1413 |  | 
| 1414 | class QCustomTypeChecker: public QObject | 
| 1415 | { | 
| 1416 |     Q_OBJECT | 
| 1417 |  | 
| 1418 | public: | 
| 1419 |     QCustomTypeChecker(QObject *parent = 0): QObject(parent) {} | 
| 1420 |     void doEmit(CustomType ct) | 
| 1421 |     { emit signal1(ct); } | 
| 1422 |  | 
| 1423 | public slots: | 
| 1424 |     void slot1(CustomType ct); | 
| 1425 |     void slot2(const QList<CustomType> &ct); | 
| 1426 |  | 
| 1427 | signals: | 
| 1428 |     void signal1(CustomType ct); | 
| 1429 |     void signal2(const QList<CustomType> &ct); | 
| 1430 |  | 
| 1431 | public: | 
| 1432 |     CustomType received; | 
| 1433 | }; | 
| 1434 |  | 
| 1435 | void QCustomTypeChecker::slot1(CustomType ct) | 
| 1436 | { received = ct; } | 
| 1437 |  | 
| 1438 | void QCustomTypeChecker::slot2(const QList< CustomType >& ct) | 
| 1439 | { received = ct[0]; } | 
| 1440 |  | 
| 1441 | void tst_QObject::customTypes() | 
| 1442 | { | 
| 1443 |     CustomType t0; | 
| 1444 |     CustomType t1(1, 2, 3); | 
| 1445 |     CustomType t2(2, 3, 4); | 
| 1446 |  | 
| 1447 |     { | 
| 1448 |         QCustomTypeChecker checker; | 
| 1449 |         QCOMPARE(instanceCount, 4); | 
| 1450 |  | 
| 1451 |         connect(sender: &checker, SIGNAL(signal1(CustomType)), receiver: &checker, SLOT(slot1(CustomType)), | 
| 1452 |                 Qt::DirectConnection); | 
| 1453 |         QCOMPARE(checker.received.value(), 0); | 
| 1454 |         checker.doEmit(ct: t1); | 
| 1455 |         QCOMPARE(checker.received.value(), t1.value()); | 
| 1456 |         checker.received = t0; | 
| 1457 |  | 
| 1458 |         int idx = qRegisterMetaType<CustomType>(typeName: "CustomType" ); | 
| 1459 |         QCOMPARE(QMetaType::type("CustomType" ), idx); | 
| 1460 |  | 
| 1461 |         checker.disconnect(); | 
| 1462 |         connect(sender: &checker, SIGNAL(signal1(CustomType)), receiver: &checker, SLOT(slot1(CustomType)), | 
| 1463 |                 Qt::QueuedConnection); | 
| 1464 |         QCOMPARE(instanceCount, 4); | 
| 1465 |         checker.doEmit(ct: t2); | 
| 1466 |         QCOMPARE(instanceCount, 5); | 
| 1467 |         QCOMPARE(checker.received.value(), t0.value()); | 
| 1468 |  | 
| 1469 |         QCoreApplication::processEvents(); | 
| 1470 |         QCOMPARE(checker.received.value(), t2.value()); | 
| 1471 |         QCOMPARE(instanceCount, 4); | 
| 1472 |  | 
| 1473 |         QVERIFY(QMetaType::isRegistered(idx)); | 
| 1474 |         QCOMPARE(qRegisterMetaType<CustomType>("CustomType" ), idx); | 
| 1475 |         QCOMPARE(QMetaType::type("CustomType" ), idx); | 
| 1476 |         QVERIFY(QMetaType::isRegistered(idx)); | 
| 1477 |     } | 
| 1478 |     QCOMPARE(instanceCount, 3); | 
| 1479 | } | 
| 1480 |  | 
| 1481 | QDataStream &operator<<(QDataStream &stream, const CustomType &ct) | 
| 1482 | { | 
| 1483 |     stream << ct.i1 << ct.i2 << ct.i3; | 
| 1484 |     return stream; | 
| 1485 | } | 
| 1486 |  | 
| 1487 | QDataStream &operator>>(QDataStream &stream, CustomType &ct) | 
| 1488 | { | 
| 1489 |     stream >> ct.i1; | 
| 1490 |     stream >> ct.i2; | 
| 1491 |     stream >> ct.i3; | 
| 1492 |     return stream; | 
| 1493 | } | 
| 1494 |  | 
| 1495 | void tst_QObject::streamCustomTypes() | 
| 1496 | { | 
| 1497 |     QByteArray ba; | 
| 1498 |  | 
| 1499 |     int idx = qRegisterMetaType<CustomType>(typeName: "CustomType" ); | 
| 1500 |     qRegisterMetaTypeStreamOperators<CustomType>(typeName: "CustomType" ); | 
| 1501 |  | 
| 1502 |     { | 
| 1503 |         CustomType t1(1, 2, 3); | 
| 1504 |         QCOMPARE(instanceCount, 1); | 
| 1505 |         QDataStream stream(&ba, (QIODevice::OpenMode)QIODevice::WriteOnly); | 
| 1506 |         QMetaType::save(stream, type: idx, data: &t1); | 
| 1507 |     } | 
| 1508 |  | 
| 1509 |     QCOMPARE(instanceCount, 0); | 
| 1510 |  | 
| 1511 |     { | 
| 1512 |         CustomType t2; | 
| 1513 |         QCOMPARE(instanceCount, 1); | 
| 1514 |         QDataStream stream(&ba, (QIODevice::OpenMode)QIODevice::ReadOnly); | 
| 1515 |         QMetaType::load(stream, type: idx, data: &t2); | 
| 1516 |         QCOMPARE(instanceCount, 1); | 
| 1517 |         QCOMPARE(t2.i1, 1); | 
| 1518 |         QCOMPARE(t2.i2, 2); | 
| 1519 |         QCOMPARE(t2.i3, 3); | 
| 1520 |     } | 
| 1521 |     QCOMPARE(instanceCount, 0); | 
| 1522 | } | 
| 1523 |  | 
| 1524 | typedef QString CustomString; | 
| 1525 |  | 
| 1526 | class PropertyObject : public QObject | 
| 1527 | { | 
| 1528 |     Q_OBJECT | 
| 1529 |  | 
| 1530 |     Q_PROPERTY(Alpha alpha READ alpha WRITE setAlpha) | 
| 1531 |     Q_PROPERTY(Priority priority READ priority WRITE setPriority) | 
| 1532 |     Q_PROPERTY(int number READ number WRITE setNumber) | 
| 1533 |     Q_PROPERTY(QString string READ string WRITE setString) | 
| 1534 |     Q_PROPERTY(QVariant variant READ variant WRITE setVariant) | 
| 1535 |     Q_PROPERTY(CustomType* custom READ custom WRITE setCustom) | 
| 1536 |     Q_PROPERTY(float myFloat READ myFloat WRITE setMyFloat) | 
| 1537 |     Q_PROPERTY(qreal myQReal READ myQReal WRITE setMyQReal) | 
| 1538 |     Q_PROPERTY(CustomString customString READ customString WRITE setCustomString ) | 
| 1539 |  | 
| 1540 | public: | 
| 1541 |     enum Alpha { | 
| 1542 |         Alpha0, | 
| 1543 |         Alpha1, | 
| 1544 |         Alpha2 | 
| 1545 |     }; | 
| 1546 |  | 
| 1547 |     enum Priority { High, Low, VeryHigh, VeryLow }; | 
| 1548 |  | 
| 1549 |     PropertyObject() | 
| 1550 |         : m_alpha(Alpha0), m_priority(High), m_number(0), m_custom(0), m_float(42) | 
| 1551 |     {} | 
| 1552 |  | 
| 1553 |     Alpha alpha() const { return m_alpha; } | 
| 1554 |     void setAlpha(Alpha alpha) { m_alpha = alpha; } | 
| 1555 |  | 
| 1556 |     Priority priority() const { return m_priority; } | 
| 1557 |     void setPriority(Priority priority) { m_priority = priority; } | 
| 1558 |  | 
| 1559 |     int number() const { return m_number; } | 
| 1560 |     void setNumber(int number) { m_number = number; } | 
| 1561 |  | 
| 1562 |     QString string() const { return m_string; } | 
| 1563 |     void setString(const QString &string) { m_string = string; } | 
| 1564 |  | 
| 1565 |     QVariant variant() const { return m_variant; } | 
| 1566 |     void setVariant(const QVariant &variant) { m_variant = variant; } | 
| 1567 |  | 
| 1568 |     CustomType *custom() const { return m_custom; } | 
| 1569 |     void setCustom(CustomType *custom) { m_custom = custom; } | 
| 1570 |  | 
| 1571 |     void setMyFloat(float value) { m_float = value; } | 
| 1572 |     inline float myFloat() const { return m_float; } | 
| 1573 |  | 
| 1574 |     void setMyQReal(qreal value) { m_qreal = value; } | 
| 1575 |     qreal myQReal() const { return m_qreal; } | 
| 1576 |  | 
| 1577 |     CustomString customString() const { return m_customString; } | 
| 1578 |     void setCustomString(const QString &string) { m_customString = string; } | 
| 1579 |  | 
| 1580 | private: | 
| 1581 |     Alpha m_alpha; | 
| 1582 |     Priority m_priority; | 
| 1583 |     int m_number; | 
| 1584 |     QString m_string; | 
| 1585 |     QVariant m_variant; | 
| 1586 |     CustomType *m_custom; | 
| 1587 |     float m_float; | 
| 1588 |     qreal m_qreal; | 
| 1589 |     CustomString m_customString; | 
| 1590 |  | 
| 1591 |     Q_ENUM(Alpha) | 
| 1592 |     Q_ENUM(Priority) | 
| 1593 | }; | 
| 1594 |  | 
| 1595 | Q_DECLARE_METATYPE(PropertyObject::Priority) | 
| 1596 |  | 
| 1597 | void tst_QObject::threadSignalEmissionCrash() | 
| 1598 | { | 
| 1599 |     int loopCount = 1000; | 
| 1600 |     for (int i = 0; i < loopCount; ++i) { | 
| 1601 |         QTcpSocket socket; | 
| 1602 |         socket.connectToHost(hostName: "localhost" , port: 80); | 
| 1603 |     } | 
| 1604 | } | 
| 1605 |  | 
| 1606 | class TestThread : public QThread | 
| 1607 | { | 
| 1608 |     Q_OBJECT | 
| 1609 | public: | 
| 1610 |     inline void run() | 
| 1611 |     { | 
| 1612 |         *object = new QObject; | 
| 1613 |         *child = new QObject(*object); | 
| 1614 |         mutex.lock(); | 
| 1615 |         cond.wakeOne(); | 
| 1616 |         cond.wait(lockedMutex: &mutex); | 
| 1617 |         mutex.unlock(); | 
| 1618 |     } | 
| 1619 |  | 
| 1620 |     QObject **object, **child; | 
| 1621 |     QMutex mutex; | 
| 1622 |     QWaitCondition cond; | 
| 1623 | }; | 
| 1624 |  | 
| 1625 | void tst_QObject::thread() | 
| 1626 | { | 
| 1627 |     QThread *currentThread = QThread::currentThread(); | 
| 1628 |     // the current thread is the same as the QApplication | 
| 1629 |     // thread... see tst_QApplication::thread() | 
| 1630 |  | 
| 1631 |     { | 
| 1632 |         QObject object; | 
| 1633 |         // thread affinity for objects with no parent should be the | 
| 1634 |         // current thread | 
| 1635 |         QVERIFY(object.thread() != nullptr); | 
| 1636 |         QCOMPARE(object.thread(), currentThread); | 
| 1637 |         // children inherit their parent's thread | 
| 1638 |         QObject child(&object); | 
| 1639 |         QCOMPARE(child.thread(), object.thread()); | 
| 1640 |     } | 
| 1641 |  | 
| 1642 |     QObject *object = 0; | 
| 1643 |     QObject *child = 0; | 
| 1644 |  | 
| 1645 |     { | 
| 1646 |         TestThread thr; | 
| 1647 |         QVERIFY(thr.thread() != nullptr); | 
| 1648 |         QCOMPARE(thr.thread(), currentThread); | 
| 1649 |  | 
| 1650 |         thr.object = &object; | 
| 1651 |         thr.child = &child; | 
| 1652 |  | 
| 1653 |         thr.mutex.lock(); | 
| 1654 |         thr.start(); | 
| 1655 |         thr.cond.wait(lockedMutex: &thr.mutex); | 
| 1656 |  | 
| 1657 |         // thread affinity for an object with no parent should be the | 
| 1658 |         // thread in which the object was created | 
| 1659 |         QCOMPARE(object->thread(), (QThread *)&thr); | 
| 1660 |         // children inherit their parent's thread | 
| 1661 |         QCOMPARE(child->thread(), object->thread()); | 
| 1662 |  | 
| 1663 |         thr.cond.wakeOne(); | 
| 1664 |         thr.mutex.unlock(); | 
| 1665 |         thr.wait(); | 
| 1666 |  | 
| 1667 |         // even though the thread is no longer running, the affinity | 
| 1668 |         // should not change | 
| 1669 |         QCOMPARE(object->thread(), (QThread *)&thr); | 
| 1670 |         QCOMPARE(child->thread(), object->thread()); | 
| 1671 |     } | 
| 1672 |  | 
| 1673 |     // the thread has been destroyed, thread affinity should | 
| 1674 |     // automatically reset to no thread | 
| 1675 |     QCOMPARE(object->thread(), (QThread *)0); | 
| 1676 |     QCOMPARE(child->thread(), object->thread()); | 
| 1677 |  | 
| 1678 |     delete object; | 
| 1679 | } | 
| 1680 |  | 
| 1681 | class MoveToThreadObject : public QObject | 
| 1682 | { | 
| 1683 |     Q_OBJECT | 
| 1684 | public: | 
| 1685 |     QThread *timerEventThread; | 
| 1686 |     QThread *customEventThread; | 
| 1687 |     QThread *slotThread; | 
| 1688 |  | 
| 1689 |     MoveToThreadObject(QObject *parent = 0) | 
| 1690 |         : QObject(parent), timerEventThread(0), customEventThread(0), slotThread(0) | 
| 1691 |     { } | 
| 1692 |  | 
| 1693 |     void customEvent(QEvent *) | 
| 1694 |     { | 
| 1695 |         if (customEventThread) | 
| 1696 |             qFatal(msg: "%s: customEventThread should be null" , Q_FUNC_INFO); | 
| 1697 |         customEventThread = QThread::currentThread(); | 
| 1698 |         emit theSignal(); | 
| 1699 |     } | 
| 1700 |  | 
| 1701 |     void timerEvent(QTimerEvent *) | 
| 1702 |     { | 
| 1703 |         if (timerEventThread) | 
| 1704 |             qFatal(msg: "%s: timerEventThread should be null" , Q_FUNC_INFO); | 
| 1705 |         timerEventThread = QThread::currentThread(); | 
| 1706 |         emit theSignal(); | 
| 1707 |     } | 
| 1708 |  | 
| 1709 | public slots: | 
| 1710 |     void theSlot() | 
| 1711 |     { | 
| 1712 |         if (slotThread) | 
| 1713 |             qFatal(msg: "%s: slotThread should be null" , Q_FUNC_INFO); | 
| 1714 |         slotThread = QThread::currentThread(); | 
| 1715 |         emit theSignal(); | 
| 1716 |     } | 
| 1717 |  | 
| 1718 | signals: | 
| 1719 |     void theSignal(); | 
| 1720 | }; | 
| 1721 |  | 
| 1722 | class MoveToThreadThread : public QThread | 
| 1723 | { | 
| 1724 | public: | 
| 1725 |     ~MoveToThreadThread() | 
| 1726 |     { | 
| 1727 |         if (isRunning()) { | 
| 1728 |             terminate(); | 
| 1729 |             wait(); | 
| 1730 |         } | 
| 1731 |     } | 
| 1732 |     void start() | 
| 1733 |     { | 
| 1734 |         QEventLoop eventLoop; | 
| 1735 |         connect(sender: this, SIGNAL(started()), receiver: &eventLoop, SLOT(quit()), Qt::QueuedConnection); | 
| 1736 |         QThread::start(); | 
| 1737 |         // wait for thread to start | 
| 1738 |         (void) eventLoop.exec(); | 
| 1739 |     } | 
| 1740 |     void run() | 
| 1741 |     { (void) exec(); } | 
| 1742 | }; | 
| 1743 |  | 
| 1744 | void tst_QObject::thread0() | 
| 1745 | { | 
| 1746 |     QObject *object = new QObject; | 
| 1747 |     object->moveToThread(thread: 0); | 
| 1748 |     QObject *child = new QObject(object); | 
| 1749 |     QCOMPARE(child->parent(), object); | 
| 1750 |     QCOMPARE(child->thread(), (QThread *)0); | 
| 1751 |  | 
| 1752 | #if 0 | 
| 1753 |     // We don't support moving children into a parent that has no thread | 
| 1754 |     // affinity (yet?). | 
| 1755 |     QObject *child2 = new QObject; | 
| 1756 |     child2->moveToThread(0); | 
| 1757 |     child2->setParent(object); | 
| 1758 |     QCOMPARE(child2->parent(), object); | 
| 1759 |     QCOMPARE(child2->thread(), (QThread *)0); | 
| 1760 | #endif | 
| 1761 |  | 
| 1762 |     delete object; | 
| 1763 | } | 
| 1764 |  | 
| 1765 | void tst_QObject::moveToThread() | 
| 1766 | { | 
| 1767 |     QThread *currentThread = QThread::currentThread(); | 
| 1768 |  | 
| 1769 |     { | 
| 1770 |         QObject *object = new QObject; | 
| 1771 |         QObject *child = new QObject(object); | 
| 1772 |         QCOMPARE(object->thread(), currentThread); | 
| 1773 |         QCOMPARE(child->thread(), currentThread); | 
| 1774 |         object->moveToThread(thread: 0); | 
| 1775 |         QCOMPARE(object->thread(), (QThread *)0); | 
| 1776 |         QCOMPARE(child->thread(), (QThread *)0); | 
| 1777 |         object->moveToThread(thread: currentThread); | 
| 1778 |         QCOMPARE(object->thread(), currentThread); | 
| 1779 |         QCOMPARE(child->thread(), currentThread); | 
| 1780 |         object->moveToThread(thread: 0); | 
| 1781 |         QCOMPARE(object->thread(), (QThread *)0); | 
| 1782 |         QCOMPARE(child->thread(), (QThread *)0); | 
| 1783 |         // can delete an object with no thread anywhere | 
| 1784 |         delete object; | 
| 1785 |     } | 
| 1786 |  | 
| 1787 |     { | 
| 1788 |         MoveToThreadThread thread; | 
| 1789 |         thread.start(); | 
| 1790 |  | 
| 1791 |         QObject *object = new QObject; | 
| 1792 |         QObject *child = new QObject(object); | 
| 1793 |         QPointer<QObject> opointer = object; | 
| 1794 |         QPointer<QObject> cpointer = object; | 
| 1795 |  | 
| 1796 |         QCOMPARE(object->thread(), currentThread); | 
| 1797 |         QCOMPARE(child->thread(), currentThread); | 
| 1798 |         object->moveToThread(thread: &thread); | 
| 1799 |         QCOMPARE(object->thread(), (QThread *)&thread); | 
| 1800 |         QCOMPARE(child->thread(), (QThread *)&thread); | 
| 1801 |  | 
| 1802 |         connect(sender: object, SIGNAL(destroyed()), receiver: &thread, SLOT(quit()), Qt::DirectConnection); | 
| 1803 |         QMetaObject::invokeMethod(obj: object, member: "deleteLater" , type: Qt::QueuedConnection); | 
| 1804 |         thread.wait(); | 
| 1805 |  | 
| 1806 |         QVERIFY(opointer == nullptr); | 
| 1807 |         QVERIFY(cpointer == nullptr); | 
| 1808 |     } | 
| 1809 |  | 
| 1810 |     { | 
| 1811 |         // make sure posted events are moved with the object | 
| 1812 |         MoveToThreadThread thread; | 
| 1813 |         thread.start(); | 
| 1814 |  | 
| 1815 |         MoveToThreadObject *object = new MoveToThreadObject; | 
| 1816 |         MoveToThreadObject *child = new MoveToThreadObject(object); | 
| 1817 |  | 
| 1818 |         connect(sender: object, SIGNAL(theSignal()), receiver: &thread, SLOT(quit()), Qt::DirectConnection); | 
| 1819 |         QCoreApplication::postEvent(receiver: child, event: new QEvent(QEvent::User)); | 
| 1820 |         QCoreApplication::postEvent(receiver: object, event: new QEvent(QEvent::User)); | 
| 1821 |  | 
| 1822 |         QCOMPARE(object->thread(), currentThread); | 
| 1823 |         QCOMPARE(child->thread(), currentThread); | 
| 1824 |         object->moveToThread(thread: &thread); | 
| 1825 |         QCOMPARE(object->thread(), (QThread *)&thread); | 
| 1826 |         QCOMPARE(child->thread(), (QThread *)&thread); | 
| 1827 |  | 
| 1828 |         thread.wait(); | 
| 1829 |  | 
| 1830 |         QCOMPARE(object->customEventThread, (QThread *)&thread); | 
| 1831 |         QCOMPARE(child->customEventThread, (QThread *)&thread); | 
| 1832 |  | 
| 1833 |         thread.start(); | 
| 1834 |         connect(sender: object, SIGNAL(destroyed()), receiver: &thread, SLOT(quit()), Qt::DirectConnection); | 
| 1835 |         QMetaObject::invokeMethod(obj: object, member: "deleteLater" , type: Qt::QueuedConnection); | 
| 1836 |         thread.wait(); | 
| 1837 |     } | 
| 1838 |  | 
| 1839 |     { | 
| 1840 |         // make sure timers are moved with the object | 
| 1841 |         MoveToThreadThread thread; | 
| 1842 |         thread.start(); | 
| 1843 |  | 
| 1844 |         MoveToThreadObject *object = new MoveToThreadObject; | 
| 1845 |         MoveToThreadObject *child = new MoveToThreadObject(object); | 
| 1846 |  | 
| 1847 |         connect(sender: object, SIGNAL(theSignal()), receiver: &thread, SLOT(quit()), Qt::DirectConnection); | 
| 1848 |  | 
| 1849 |         child->startTimer(interval: 90); | 
| 1850 |         object->startTimer(interval: 100); | 
| 1851 |  | 
| 1852 |         QCOMPARE(object->thread(), currentThread); | 
| 1853 |         QCOMPARE(child->thread(), currentThread); | 
| 1854 |         object->moveToThread(thread: &thread); | 
| 1855 |         QCOMPARE(object->thread(), (QThread *)&thread); | 
| 1856 |         QCOMPARE(child->thread(), (QThread *)&thread); | 
| 1857 |  | 
| 1858 |         thread.wait(); | 
| 1859 |  | 
| 1860 |         QCOMPARE(object->timerEventThread, (QThread *)&thread); | 
| 1861 |         QCOMPARE(child->timerEventThread, (QThread *)&thread); | 
| 1862 |  | 
| 1863 |         thread.start(); | 
| 1864 |         connect(sender: object, SIGNAL(destroyed()), receiver: &thread, SLOT(quit()), Qt::DirectConnection); | 
| 1865 |         QMetaObject::invokeMethod(obj: object, member: "deleteLater" , type: Qt::QueuedConnection); | 
| 1866 |         thread.wait(); | 
| 1867 |     } | 
| 1868 |  | 
| 1869 |     // WinRT does not allow connection to localhost | 
| 1870 | #ifndef Q_OS_WINRT | 
| 1871 |     { | 
| 1872 |         // make sure socket notifiers are moved with the object | 
| 1873 |         MoveToThreadThread thread; | 
| 1874 |         thread.start(); | 
| 1875 |  | 
| 1876 |         QTcpServer server; | 
| 1877 |         QVERIFY(server.listen(QHostAddress::LocalHost, 0)); | 
| 1878 |         QTcpSocket *socket = new QTcpSocket; | 
| 1879 |         MoveToThreadObject *child = new MoveToThreadObject(socket); | 
| 1880 |         connect(sender: socket, SIGNAL(disconnected()), receiver: child, SLOT(theSlot()), Qt::DirectConnection); | 
| 1881 |         connect(sender: child, SIGNAL(theSignal()), receiver: &thread, SLOT(quit()), Qt::DirectConnection); | 
| 1882 |  | 
| 1883 |         socket->connectToHost(address: server.serverAddress(), port: server.serverPort()); | 
| 1884 |  | 
| 1885 |         QVERIFY(server.waitForNewConnection(1000)); | 
| 1886 |         QTcpSocket *serverSocket = server.nextPendingConnection(); | 
| 1887 |         QVERIFY(serverSocket); | 
| 1888 |  | 
| 1889 |         socket->waitForConnected(); | 
| 1890 |  | 
| 1891 |         QCOMPARE(socket->thread(), currentThread); | 
| 1892 |         socket->moveToThread(thread: &thread); | 
| 1893 |         QCOMPARE(socket->thread(), (QThread *)&thread); | 
| 1894 |  | 
| 1895 |         serverSocket->close(); | 
| 1896 |  | 
| 1897 |         QVERIFY(thread.wait(10000)); | 
| 1898 |  | 
| 1899 |         QCOMPARE(child->slotThread, (QThread *)&thread); | 
| 1900 |  | 
| 1901 |         thread.start(); | 
| 1902 |         connect(sender: socket, SIGNAL(destroyed()), receiver: &thread, SLOT(quit()), Qt::DirectConnection); | 
| 1903 |         QMetaObject::invokeMethod(obj: socket, member: "deleteLater" , type: Qt::QueuedConnection); | 
| 1904 |         thread.wait(); | 
| 1905 |     } | 
| 1906 | #endif | 
| 1907 | } | 
| 1908 |  | 
| 1909 |  | 
| 1910 | void tst_QObject::property() | 
| 1911 | { | 
| 1912 |     PropertyObject object; | 
| 1913 |     const QMetaObject *mo = object.metaObject(); | 
| 1914 |     QMetaProperty property; | 
| 1915 |     QVERIFY(mo); | 
| 1916 |  | 
| 1917 |     QVERIFY(mo->indexOfProperty("alpha" ) != -1); | 
| 1918 |     property = mo->property(index: mo->indexOfProperty(name: "alpha" )); | 
| 1919 |     QVERIFY(property.isEnumType()); | 
| 1920 |     QCOMPARE(property.typeName(), "Alpha" ); | 
| 1921 |     QCOMPARE(property.type(), QVariant::Int); | 
| 1922 |  | 
| 1923 |     QVariant var = object.property(name: "alpha" ); | 
| 1924 |     QVERIFY(!var.isNull()); | 
| 1925 |     QCOMPARE(var.toInt(), int(PropertyObject::Alpha0)); | 
| 1926 |     object.setAlpha(PropertyObject::Alpha1); | 
| 1927 |     QCOMPARE(object.property("alpha" ).toInt(), int(PropertyObject::Alpha1)); | 
| 1928 |     QVERIFY(object.setProperty("alpha" , PropertyObject::Alpha2)); | 
| 1929 |     QCOMPARE(object.property("alpha" ).toInt(), int(PropertyObject::Alpha2)); | 
| 1930 |     QVERIFY(object.setProperty("alpha" , "Alpha1" )); | 
| 1931 |     QCOMPARE(object.property("alpha" ).toInt(), int(PropertyObject::Alpha1)); | 
| 1932 |     QVERIFY(!object.setProperty("alpha" , QVariant())); | 
| 1933 |  | 
| 1934 |     QVERIFY(mo->indexOfProperty("number" ) != -1); | 
| 1935 |     QCOMPARE(object.property("number" ).toInt(), 0); | 
| 1936 |     object.setNumber(24); | 
| 1937 |     QCOMPARE(object.property("number" ), QVariant(24)); | 
| 1938 |     QVERIFY(object.setProperty("number" , 12)); | 
| 1939 |     QCOMPARE(object.property("number" ), QVariant(12)); | 
| 1940 |     QVERIFY(object.setProperty("number" , "42" )); | 
| 1941 |     QCOMPARE(object.property("number" ), QVariant(42)); | 
| 1942 |  | 
| 1943 |     QVERIFY(mo->indexOfProperty("string" ) != -1); | 
| 1944 |     QCOMPARE(object.property("string" ).toString(), QString()); | 
| 1945 |     object.setString("String1" ); | 
| 1946 |     QCOMPARE(object.property("string" ), QVariant("String1" )); | 
| 1947 |     QVERIFY(object.setProperty("string" , "String2" )); | 
| 1948 |     QCOMPARE(object.property("string" ), QVariant("String2" )); | 
| 1949 |     QVERIFY(object.setProperty("string" , QVariant())); | 
| 1950 |  | 
| 1951 |     const int idx = mo->indexOfProperty(name: "variant" ); | 
| 1952 |     QVERIFY(idx != -1); | 
| 1953 |     QCOMPARE(QMetaType::Type(mo->property(idx).type()), QMetaType::QVariant); | 
| 1954 |     QCOMPARE(object.property("variant" ), QVariant()); | 
| 1955 |     QVariant variant1(42); | 
| 1956 |     QVariant variant2("string" ); | 
| 1957 |     object.setVariant(variant1); | 
| 1958 |     QCOMPARE(object.property("variant" ), variant1); | 
| 1959 |     QVERIFY(object.setProperty("variant" , variant2)); | 
| 1960 |     QCOMPARE(object.variant(), QVariant(variant2)); | 
| 1961 |     QCOMPARE(object.property("variant" ), variant2); | 
| 1962 |     QVERIFY(object.setProperty("variant" , QVariant())); | 
| 1963 |     QCOMPARE(object.property("variant" ), QVariant()); | 
| 1964 |  | 
| 1965 |     QVERIFY(mo->indexOfProperty("custom" ) != -1); | 
| 1966 |     property = mo->property(index: mo->indexOfProperty(name: "custom" )); | 
| 1967 |     QVERIFY(property.isValid()); | 
| 1968 |     QVERIFY(property.isWritable()); | 
| 1969 |     QVERIFY(!property.isEnumType()); | 
| 1970 |     QCOMPARE(property.typeName(), "CustomType*" ); | 
| 1971 |     qRegisterMetaType<CustomType*>(); | 
| 1972 |     QCOMPARE(property.type(), QVariant::UserType); | 
| 1973 |     QCOMPARE(property.userType(), qMetaTypeId<CustomType*>()); | 
| 1974 |  | 
| 1975 |     CustomType *customPointer = 0; | 
| 1976 |     QVariant customVariant = object.property(name: "custom" ); | 
| 1977 |     customPointer = qvariant_cast<CustomType *>(v: customVariant); | 
| 1978 |     QCOMPARE(customPointer, object.custom()); | 
| 1979 |  | 
| 1980 |     CustomType custom; | 
| 1981 |     customPointer = &custom; | 
| 1982 |     customVariant.setValue(customPointer); | 
| 1983 |  | 
| 1984 |     property = mo->property(index: mo->indexOfProperty(name: "custom" )); | 
| 1985 |     QVERIFY(property.isWritable()); | 
| 1986 |     QCOMPARE(property.typeName(), "CustomType*" ); | 
| 1987 |     QCOMPARE(property.type(), QVariant::UserType); | 
| 1988 |     QCOMPARE(property.userType(), qMetaTypeId<CustomType*>()); | 
| 1989 |  | 
| 1990 |     QVERIFY(object.setProperty("custom" , customVariant)); | 
| 1991 |     QCOMPARE(object.custom(), customPointer); | 
| 1992 |  | 
| 1993 |     customVariant = object.property(name: "custom" ); | 
| 1994 |     customPointer = qvariant_cast<CustomType *>(v: customVariant); | 
| 1995 |     QCOMPARE(object.custom(), customPointer); | 
| 1996 |  | 
| 1997 |     // this enum property has a meta type, but it's not yet registered, so we know this fails | 
| 1998 |     QVERIFY(mo->indexOfProperty("priority" ) != -1); | 
| 1999 |     property = mo->property(index: mo->indexOfProperty(name: "priority" )); | 
| 2000 |     QVERIFY(property.isEnumType()); | 
| 2001 |     QCOMPARE(property.typeName(), "Priority" ); | 
| 2002 |     QCOMPARE(property.type(), QVariant::Int); | 
| 2003 |  | 
| 2004 |     var = object.property(name: "priority" ); | 
| 2005 |     QVERIFY(!var.isNull()); | 
| 2006 |     QCOMPARE(var.toInt(), int(PropertyObject::High)); | 
| 2007 |     object.setPriority(PropertyObject::Low); | 
| 2008 |     QCOMPARE(object.property("priority" ).toInt(), int(PropertyObject::Low)); | 
| 2009 |     QVERIFY(object.setProperty("priority" , PropertyObject::VeryHigh)); | 
| 2010 |     QCOMPARE(object.property("priority" ).toInt(), int(PropertyObject::VeryHigh)); | 
| 2011 |     QVERIFY(object.setProperty("priority" , "High" )); | 
| 2012 |     QCOMPARE(object.property("priority" ).toInt(), int(PropertyObject::High)); | 
| 2013 |     QVERIFY(!object.setProperty("priority" , QVariant())); | 
| 2014 |  | 
| 2015 |     // now it's registered, so it works as expected | 
| 2016 |     int priorityMetaTypeId = qRegisterMetaType<PropertyObject::Priority>(typeName: "PropertyObject::Priority" ); | 
| 2017 |  | 
| 2018 |     QVERIFY(mo->indexOfProperty("priority" ) != -1); | 
| 2019 |     property = mo->property(index: mo->indexOfProperty(name: "priority" )); | 
| 2020 |     QVERIFY(property.isEnumType()); | 
| 2021 |     QCOMPARE(property.typeName(), "Priority" ); | 
| 2022 |     QCOMPARE(property.type(), QVariant::UserType); | 
| 2023 |     QCOMPARE(property.userType(), priorityMetaTypeId); | 
| 2024 |  | 
| 2025 |     var = object.property(name: "priority" ); | 
| 2026 |     QVERIFY(!var.isNull()); | 
| 2027 |     QVERIFY(var.canConvert<PropertyObject::Priority>()); | 
| 2028 |     QCOMPARE(qvariant_cast<PropertyObject::Priority>(var), PropertyObject::High); | 
| 2029 |     object.setPriority(PropertyObject::Low); | 
| 2030 |     QCOMPARE(qvariant_cast<PropertyObject::Priority>(object.property("priority" )), PropertyObject::Low); | 
| 2031 |     QVERIFY(object.setProperty("priority" , PropertyObject::VeryHigh)); | 
| 2032 |     QCOMPARE(qvariant_cast<PropertyObject::Priority>(object.property("priority" )), PropertyObject::VeryHigh); | 
| 2033 |     QVERIFY(object.setProperty("priority" , "High" )); | 
| 2034 |     QCOMPARE(qvariant_cast<PropertyObject::Priority>(object.property("priority" )), PropertyObject::High); | 
| 2035 |     QVERIFY(!object.setProperty("priority" , QVariant())); | 
| 2036 |  | 
| 2037 |     var = object.property(name: "priority" ); | 
| 2038 |     QCOMPARE(qvariant_cast<PropertyObject::Priority>(var), PropertyObject::High); | 
| 2039 |     object.setPriority(PropertyObject::Low); | 
| 2040 |     QCOMPARE(qvariant_cast<PropertyObject::Priority>(object.property("priority" )), PropertyObject::Low); | 
| 2041 |     object.setProperty(name: "priority" , value: var); | 
| 2042 |     QCOMPARE(qvariant_cast<PropertyObject::Priority>(object.property("priority" )), PropertyObject::High); | 
| 2043 |  | 
| 2044 |     qRegisterMetaType<CustomString>(typeName: "CustomString" ); | 
| 2045 |     QVERIFY(mo->indexOfProperty("customString" ) != -1); | 
| 2046 |     QCOMPARE(object.property("customString" ).toString(), QString()); | 
| 2047 |     object.setCustomString("String1" ); | 
| 2048 |     QCOMPARE(object.property("customString" ), QVariant("String1" )); | 
| 2049 |     QVERIFY(object.setProperty("customString" , "String2" )); | 
| 2050 |     QCOMPARE(object.property("customString" ), QVariant("String2" )); | 
| 2051 |     QVERIFY(object.setProperty("customString" , QVariant())); | 
| 2052 | } | 
| 2053 |  | 
| 2054 | void tst_QObject::metamethod() | 
| 2055 | { | 
| 2056 |     SenderObject obj; | 
| 2057 |     const QMetaObject *mobj = obj.metaObject(); | 
| 2058 |     QMetaMethod m; | 
| 2059 |  | 
| 2060 |     m = mobj->method(index: mobj->indexOfMethod(method: "invoke1()" )); | 
| 2061 |     QVERIFY(m.methodSignature() == "invoke1()" ); | 
| 2062 |     QCOMPARE(m.methodType(), QMetaMethod::Method); | 
| 2063 |     QCOMPARE(m.access(), QMetaMethod::Public); | 
| 2064 |     QVERIFY(!(m.attributes() & QMetaMethod::Scriptable)); | 
| 2065 |     QVERIFY(!(m.attributes() & QMetaMethod::Compatibility)); | 
| 2066 |  | 
| 2067 |     m = mobj->method(index: mobj->indexOfMethod(method: "sinvoke1()" )); | 
| 2068 |     QVERIFY(m.methodSignature() == "sinvoke1()" ); | 
| 2069 |     QCOMPARE(m.methodType(), QMetaMethod::Method); | 
| 2070 |     QCOMPARE(m.access(), QMetaMethod::Public); | 
| 2071 |     QVERIFY((m.attributes() & QMetaMethod::Scriptable)); | 
| 2072 |     QVERIFY(!(m.attributes() & QMetaMethod::Compatibility)); | 
| 2073 |  | 
| 2074 |     m = mobj->method(index: mobj->indexOfMethod(method: "invoke2()" )); | 
| 2075 |     QVERIFY(m.methodSignature() == "invoke2()" ); | 
| 2076 |     QCOMPARE(m.methodType(), QMetaMethod::Method); | 
| 2077 |     QCOMPARE(m.access(), QMetaMethod::Protected); | 
| 2078 |     QVERIFY(!(m.attributes() & QMetaMethod::Scriptable)); | 
| 2079 |     QVERIFY((m.attributes() & QMetaMethod::Compatibility)); | 
| 2080 |  | 
| 2081 |     m = mobj->method(index: mobj->indexOfMethod(method: "sinvoke2()" )); | 
| 2082 |     QVERIFY(m.methodSignature() == "sinvoke2()" ); | 
| 2083 |     QCOMPARE(m.methodType(), QMetaMethod::Method); | 
| 2084 |     QCOMPARE(m.access(), QMetaMethod::Protected); | 
| 2085 |     QVERIFY((m.attributes() & QMetaMethod::Scriptable)); | 
| 2086 |     QVERIFY((m.attributes() & QMetaMethod::Compatibility)); | 
| 2087 |  | 
| 2088 |     m = mobj->method(index: mobj->indexOfMethod(method: "invoke3()" )); | 
| 2089 |     QVERIFY(m.methodSignature() == "invoke3()" ); | 
| 2090 |     QCOMPARE(m.methodType(), QMetaMethod::Method); | 
| 2091 |     QCOMPARE(m.access(), QMetaMethod::Private); | 
| 2092 |     QVERIFY(!(m.attributes() & QMetaMethod::Scriptable)); | 
| 2093 |     QVERIFY(!(m.attributes() & QMetaMethod::Compatibility)); | 
| 2094 |  | 
| 2095 |     m = mobj->method(index: mobj->indexOfMethod(method: "sinvoke3()" )); | 
| 2096 |     QVERIFY(m.methodSignature() == "sinvoke3()" ); | 
| 2097 |     QCOMPARE(m.methodType(), QMetaMethod::Method); | 
| 2098 |     QCOMPARE(m.access(), QMetaMethod::Private); | 
| 2099 |     QVERIFY((m.attributes() & QMetaMethod::Scriptable)); | 
| 2100 |     QVERIFY(!(m.attributes() & QMetaMethod::Compatibility)); | 
| 2101 |  | 
| 2102 |     m = mobj->method(index: mobj->indexOfMethod(method: "signal5()" )); | 
| 2103 |     QVERIFY(m.methodSignature() == "signal5()" ); | 
| 2104 |     QCOMPARE(m.methodType(), QMetaMethod::Signal); | 
| 2105 |     QCOMPARE(m.access(), QMetaMethod::Public); | 
| 2106 |     QVERIFY(!(m.attributes() & QMetaMethod::Scriptable)); | 
| 2107 |     QVERIFY((m.attributes() & QMetaMethod::Compatibility)); | 
| 2108 |  | 
| 2109 |     m = mobj->method(index: mobj->indexOfMethod(method: "aPublicSlot()" )); | 
| 2110 |     QVERIFY(m.methodSignature() == "aPublicSlot()" ); | 
| 2111 |     QCOMPARE(m.methodType(), QMetaMethod::Slot); | 
| 2112 |     QCOMPARE(m.access(), QMetaMethod::Public); | 
| 2113 |     QVERIFY(!(m.attributes() & QMetaMethod::Scriptable)); | 
| 2114 |     QVERIFY(!(m.attributes() & QMetaMethod::Compatibility)); | 
| 2115 |  | 
| 2116 |     m = mobj->method(index: mobj->indexOfMethod(method: "invoke1()" )); | 
| 2117 |     QCOMPARE(m.parameterNames().count(), 0); | 
| 2118 |     QCOMPARE(m.parameterTypes().count(), 0); | 
| 2119 |  | 
| 2120 |     m = mobj->method(index: mobj->indexOfMethod(method: "invoke2(int)" )); | 
| 2121 |     QCOMPARE(m.parameterNames().count(), 1); | 
| 2122 |     QCOMPARE(m.parameterTypes().count(), 1); | 
| 2123 |     QCOMPARE(m.parameterTypes().at(0), QByteArray("int" )); | 
| 2124 |     QVERIFY(m.parameterNames().at(0).isEmpty()); | 
| 2125 |  | 
| 2126 |     m = mobj->method(index: mobj->indexOfMethod(method: "invoke3(int,int)" )); | 
| 2127 |     QCOMPARE(m.parameterNames().count(), 2); | 
| 2128 |     QCOMPARE(m.parameterTypes().count(), 2); | 
| 2129 |     QCOMPARE(m.parameterTypes().at(0), QByteArray("int" )); | 
| 2130 |     QCOMPARE(m.parameterNames().at(0), QByteArray("hinz" )); | 
| 2131 |     QCOMPARE(m.parameterTypes().at(1), QByteArray("int" )); | 
| 2132 |     QCOMPARE(m.parameterNames().at(1), QByteArray("kunz" )); | 
| 2133 |  | 
| 2134 | } | 
| 2135 |  | 
| 2136 | namespace QObjectTest | 
| 2137 | { | 
| 2138 |     class TestObject: public QObject | 
| 2139 |     { | 
| 2140 |     Q_OBJECT | 
| 2141 |     public: | 
| 2142 |         TestObject(): QObject(), i(0) {} | 
| 2143 |         void doEmit() { emit aSignal(); } | 
| 2144 |         int i; | 
| 2145 |     public slots: | 
| 2146 |         void aSlot() { ++i; } | 
| 2147 |     signals: | 
| 2148 |         void aSignal(); | 
| 2149 |     }; | 
| 2150 | } | 
| 2151 |  | 
| 2152 | void tst_QObject::namespaces() | 
| 2153 | { | 
| 2154 |     QObjectTest::TestObject obj; | 
| 2155 |  | 
| 2156 |     QVERIFY(connect(&obj, SIGNAL(aSignal()), &obj, SLOT(aSlot()))); | 
| 2157 |     obj.doEmit(); | 
| 2158 |     QCOMPARE(obj.i, 1); | 
| 2159 | } | 
| 2160 |  | 
| 2161 | class SuperObject : public QObject | 
| 2162 | { | 
| 2163 |     Q_OBJECT | 
| 2164 | public: | 
| 2165 |     QObject *theSender; | 
| 2166 |     int theSignalId; | 
| 2167 |  | 
| 2168 |     SuperObject() | 
| 2169 |     { | 
| 2170 |         theSender = 0; | 
| 2171 |         theSignalId = 0; | 
| 2172 |     } | 
| 2173 |  | 
| 2174 |     friend class tst_QObject; | 
| 2175 |  | 
| 2176 |     using QObject::sender; | 
| 2177 |  | 
| 2178 | public slots: | 
| 2179 |     void rememberSender() | 
| 2180 |     { | 
| 2181 |         theSender = sender(); | 
| 2182 |         theSignalId = senderSignalIndex(); | 
| 2183 |     } | 
| 2184 |  | 
| 2185 |     void deleteAndRememberSender() | 
| 2186 |     { | 
| 2187 |         delete theSender; | 
| 2188 |         rememberSender(); | 
| 2189 |     } | 
| 2190 | signals: | 
| 2191 |     void anotherSignal(); | 
| 2192 |     void theSignal(); | 
| 2193 | }; | 
| 2194 |  | 
| 2195 | void tst_QObject::senderTest() | 
| 2196 | { | 
| 2197 |     { | 
| 2198 |         SuperObject sender; | 
| 2199 |         SuperObject receiver; | 
| 2200 |         connect(sender: &sender, SIGNAL(anotherSignal()), | 
| 2201 |                 receiver: &receiver, SLOT(rememberSender())); | 
| 2202 |         connect(sender: &sender, SIGNAL(theSignal()), | 
| 2203 |                 receiver: &receiver, SLOT(rememberSender())); | 
| 2204 |         QCOMPARE(receiver.sender(), (QObject *)0); | 
| 2205 |         QCOMPARE(receiver.senderSignalIndex(), -1); | 
| 2206 |         emit sender.theSignal(); | 
| 2207 |         QCOMPARE(receiver.theSender, (QObject *)&sender); | 
| 2208 |         QCOMPARE(receiver.sender(), (QObject *)0); | 
| 2209 |         QCOMPARE(receiver.theSignalId, | 
| 2210 |                  sender.metaObject()->indexOfSignal("theSignal()" )); | 
| 2211 |         QCOMPARE(receiver.senderSignalIndex(), -1); | 
| 2212 |  | 
| 2213 |         emit sender.anotherSignal(); | 
| 2214 |         QCOMPARE(receiver.theSignalId, | 
| 2215 |                  sender.metaObject()->indexOfSignal("anotherSignal()" )); | 
| 2216 |         QCOMPARE(receiver.senderSignalIndex(), -1); | 
| 2217 |     } | 
| 2218 |  | 
| 2219 |     { | 
| 2220 |         SuperObject *sender = new SuperObject; | 
| 2221 |         SuperObject *receiver = new SuperObject; | 
| 2222 |         connect(sender, SIGNAL(theSignal()), | 
| 2223 |                 receiver, SLOT(rememberSender()), | 
| 2224 |                 Qt::BlockingQueuedConnection); | 
| 2225 |  | 
| 2226 |         QThread thread; | 
| 2227 |         receiver->moveToThread(thread: &thread); | 
| 2228 |         connect(sender, SIGNAL(theSignal()), | 
| 2229 |                 receiver: &thread, SLOT(quit()), | 
| 2230 |                 Qt::DirectConnection); | 
| 2231 |  | 
| 2232 |         QCOMPARE(receiver->sender(), (QObject *)0); | 
| 2233 |         QCOMPARE(receiver->senderSignalIndex(), -1); | 
| 2234 |         receiver->theSender = 0; | 
| 2235 |         receiver->theSignalId = -1; | 
| 2236 |         thread.start(); | 
| 2237 |         emit sender->theSignal(); | 
| 2238 |         QCOMPARE(receiver->theSender, (QObject *) sender); | 
| 2239 |         QCOMPARE(receiver->sender(), (QObject *)0); | 
| 2240 |         QCOMPARE(receiver->theSignalId, | 
| 2241 |                  sender->metaObject()->indexOfSignal("theSignal()" )); | 
| 2242 |         QCOMPARE(receiver->senderSignalIndex(), -1); | 
| 2243 |  | 
| 2244 |         QVERIFY(thread.wait(10000)); | 
| 2245 |         delete receiver; | 
| 2246 |         delete sender; | 
| 2247 |     } | 
| 2248 |  | 
| 2249 |     { | 
| 2250 |         SuperObject *sender = new SuperObject; | 
| 2251 |         SuperObject receiver; | 
| 2252 |         connect(sender, SIGNAL(theSignal()), | 
| 2253 |                 receiver: &receiver, SLOT(deleteAndRememberSender())); | 
| 2254 |         QCOMPARE(receiver.sender(), (QObject *)0); | 
| 2255 |         receiver.theSender = sender; | 
| 2256 |         emit sender->theSignal(); | 
| 2257 |         QCOMPARE(receiver.theSender, (QObject *)0); | 
| 2258 |         QCOMPARE(receiver.sender(), (QObject *)0); | 
| 2259 |     } | 
| 2260 |  | 
| 2261 |     { | 
| 2262 |         SuperObject *sender = new SuperObject; | 
| 2263 |         SuperObject *receiver = new SuperObject; | 
| 2264 |         connect(sender, SIGNAL(theSignal()), | 
| 2265 |                 receiver, SLOT(deleteAndRememberSender()), | 
| 2266 |                 Qt::BlockingQueuedConnection); | 
| 2267 |  | 
| 2268 |         QThread thread; | 
| 2269 |         receiver->moveToThread(thread: &thread); | 
| 2270 |         connect(sender, SIGNAL(destroyed()), | 
| 2271 |                 receiver: &thread, SLOT(quit()), | 
| 2272 |                 Qt::DirectConnection); | 
| 2273 |  | 
| 2274 |         QCOMPARE(receiver->sender(), (QObject *)0); | 
| 2275 |         receiver->theSender = sender; | 
| 2276 |         thread.start(); | 
| 2277 |         emit sender->theSignal(); | 
| 2278 |         QCOMPARE(receiver->theSender, (QObject *)0); | 
| 2279 |         QCOMPARE(receiver->sender(), (QObject *)0); | 
| 2280 |  | 
| 2281 |         QVERIFY(thread.wait(10000)); | 
| 2282 |         delete receiver; | 
| 2283 |     } | 
| 2284 | } | 
| 2285 |  | 
| 2286 | namespace Foo | 
| 2287 | { | 
| 2288 |     struct Bar | 
| 2289 |     { | 
| 2290 |         virtual ~Bar() {} | 
| 2291 |         virtual int rtti() const = 0; | 
| 2292 |     }; | 
| 2293 |  | 
| 2294 |     struct Bleh | 
| 2295 |     { | 
| 2296 |         virtual ~Bleh() {} | 
| 2297 |         virtual int rtti() const = 0; | 
| 2298 |     }; | 
| 2299 | } | 
| 2300 |  | 
| 2301 | QT_BEGIN_NAMESPACE | 
| 2302 | Q_DECLARE_INTERFACE(Foo::Bar, "com.qtest.foobar" ) | 
| 2303 | QT_END_NAMESPACE | 
| 2304 |  | 
| 2305 | #define Bleh_iid "com.qtest.bleh" | 
| 2306 | QT_BEGIN_NAMESPACE | 
| 2307 | Q_DECLARE_INTERFACE(Foo::Bleh, Bleh_iid) | 
| 2308 | QT_END_NAMESPACE | 
| 2309 |  | 
| 2310 | class FooObject: public QObject, public Foo::Bar | 
| 2311 | { | 
| 2312 |     Q_OBJECT | 
| 2313 |     Q_INTERFACES(Foo::Bar) | 
| 2314 | public: | 
| 2315 |     int rtti() const { return 42; } | 
| 2316 | }; | 
| 2317 |  | 
| 2318 | class BlehObject : public QObject, public Foo::Bleh | 
| 2319 | { | 
| 2320 |     Q_OBJECT | 
| 2321 |     Q_INTERFACES(Foo::Bleh) | 
| 2322 | public: | 
| 2323 |     int rtti() const { return 43; } | 
| 2324 | }; | 
| 2325 |  | 
| 2326 | void tst_QObject::declareInterface() | 
| 2327 | { | 
| 2328 |     FooObject obj; | 
| 2329 |  | 
| 2330 |     Foo::Bar *bar = qobject_cast<Foo::Bar *>(object: &obj); | 
| 2331 |     QVERIFY(bar); | 
| 2332 |     QCOMPARE(bar->rtti(), 42); | 
| 2333 |     QCOMPARE(static_cast<Foo::Bar *>(&obj), bar); | 
| 2334 |  | 
| 2335 |     BlehObject bleh; | 
| 2336 |  | 
| 2337 |     bar = qobject_cast<Foo::Bar *>(object: &bleh); | 
| 2338 |     QVERIFY(!bar); | 
| 2339 |     Foo::Bleh *b = qobject_cast<Foo::Bleh *>(object: &bleh); | 
| 2340 |     QCOMPARE(b->rtti(), 43); | 
| 2341 |     QCOMPARE(static_cast<Foo::Bleh *>(&bleh), b); | 
| 2342 |  | 
| 2343 | } | 
| 2344 |  | 
| 2345 | #ifndef QT_NO_USERDATA | 
| 2346 | class CustomData : public QObjectUserData | 
| 2347 | { | 
| 2348 | public: | 
| 2349 |     int id; | 
| 2350 | }; | 
| 2351 |  | 
| 2352 | void tst_QObject::testUserData() | 
| 2353 | { | 
| 2354 |     const int USER_DATA_COUNT = 100; | 
| 2355 |     int user_data_ids[USER_DATA_COUNT]; | 
| 2356 |  | 
| 2357 |     // Register a few | 
| 2358 |     for (int i=0; i<USER_DATA_COUNT; ++i) { | 
| 2359 |         user_data_ids[i] = QObject::registerUserData(); | 
| 2360 |     } | 
| 2361 |  | 
| 2362 |     // Randomize the table a bit | 
| 2363 |     for (int i=0; i<100; ++i) { | 
| 2364 |         int p1 = QRandomGenerator::global()->bounded(highest: USER_DATA_COUNT); | 
| 2365 |         int p2 = QRandomGenerator::global()->bounded(highest: USER_DATA_COUNT); | 
| 2366 |  | 
| 2367 |         int tmp = user_data_ids[p1]; | 
| 2368 |         user_data_ids[p1] = user_data_ids[p2]; | 
| 2369 |         user_data_ids[p2] = tmp; | 
| 2370 |     } | 
| 2371 |  | 
| 2372 |     // insert the user data into an object | 
| 2373 |     QObject my_test_object; | 
| 2374 |     for (int i=0; i<USER_DATA_COUNT; ++i) { | 
| 2375 |         CustomData *data = new CustomData; | 
| 2376 |         data->id = user_data_ids[i]; | 
| 2377 |         my_test_object.setUserData(id: data->id, data); | 
| 2378 |     } | 
| 2379 |  | 
| 2380 |     // verify that all ids and positions are matching | 
| 2381 |     for (int i=0; i<USER_DATA_COUNT; ++i) { | 
| 2382 |         int id = user_data_ids[i]; | 
| 2383 |         CustomData *data = static_cast<CustomData *>(my_test_object.userData(id)); | 
| 2384 |         QVERIFY(data != nullptr); | 
| 2385 |         QCOMPARE(data->id, id); | 
| 2386 |     } | 
| 2387 | } | 
| 2388 | #endif // QT_NO_USERDATA | 
| 2389 |  | 
| 2390 | class DestroyedListener : public QObject | 
| 2391 | { | 
| 2392 |     Q_OBJECT | 
| 2393 | public: | 
| 2394 |     inline DestroyedListener() : pointerWasZero(false) {} | 
| 2395 |  | 
| 2396 |     QPointer<QObject> pointer; | 
| 2397 |     bool pointerWasZero; | 
| 2398 |  | 
| 2399 | private slots: | 
| 2400 |     inline void otherObjectDestroyed() | 
| 2401 |     { pointerWasZero = pointer.isNull(); } | 
| 2402 | }; | 
| 2403 |  | 
| 2404 | void tst_QObject::qpointerResetBeforeDestroyedSignal() | 
| 2405 | { | 
| 2406 |     QObject *obj = new QObject; | 
| 2407 |     DestroyedListener listener; | 
| 2408 |     listener.pointer = obj; | 
| 2409 |     listener.pointerWasZero = false; | 
| 2410 |     connect(sender: obj, SIGNAL(destroyed()), receiver: &listener, SLOT(otherObjectDestroyed())); | 
| 2411 |     delete obj; | 
| 2412 |     QVERIFY(listener.pointerWasZero); | 
| 2413 |     QVERIFY(listener.pointer.isNull()); | 
| 2414 | } | 
| 2415 |  | 
| 2416 | class DefaultArguments : public QObject | 
| 2417 | { | 
| 2418 |     Q_OBJECT | 
| 2419 |  | 
| 2420 | public slots: | 
| 2421 |  | 
| 2422 |     void theSlot(const QString &s) { result = s; } | 
| 2423 |  | 
| 2424 | signals: | 
| 2425 |     void theOriginalSignal(); | 
| 2426 |     void theSecondSignal(const QString &s = QString("secondDefault" )); | 
| 2427 |  | 
| 2428 | public: | 
| 2429 |  | 
| 2430 |     void emitTheOriginalSignal() { emit theOriginalSignal(); } | 
| 2431 |     void emitTheSecondSignal() { emit theSecondSignal(); } | 
| 2432 |     QString result; | 
| 2433 | }; | 
| 2434 |  | 
| 2435 | void tst_QObject::connectSignalsToSignalsWithDefaultArguments() | 
| 2436 | { | 
| 2437 |     DefaultArguments o; | 
| 2438 |     connect(sender: &o, SIGNAL(theOriginalSignal()), receiver: &o, SIGNAL(theSecondSignal())); | 
| 2439 |     connect(sender: &o, SIGNAL(theSecondSignal(QString)), receiver: &o, SLOT(theSlot(QString))); | 
| 2440 |     QVERIFY( o.result.isEmpty() ); | 
| 2441 |     o.emitTheSecondSignal(); | 
| 2442 |     QCOMPARE(o.result, QString("secondDefault" )); | 
| 2443 |     o.result = "Not called" ; | 
| 2444 |     o.emitTheOriginalSignal(); | 
| 2445 |     QCOMPARE(o.result, QString("secondDefault" )); | 
| 2446 |  | 
| 2447 | } | 
| 2448 |  | 
| 2449 | void tst_QObject::receivers() | 
| 2450 | { | 
| 2451 |     class Object : public QObject | 
| 2452 |     { | 
| 2453 |     public: | 
| 2454 |         int receivers(const char* signal) const | 
| 2455 |         { return QObject::receivers(signal); } | 
| 2456 |     }; | 
| 2457 |  | 
| 2458 |     Object object; | 
| 2459 |     QCOMPARE(object.receivers(SIGNAL(destroyed())), 0); | 
| 2460 |     object.connect(asender: &object, SIGNAL(destroyed()), SLOT(deleteLater())); | 
| 2461 |     QCOMPARE(object.receivers(SIGNAL(destroyed())), 1); | 
| 2462 |     object.connect(asender: &object, SIGNAL(destroyed()), SLOT(deleteLater())); | 
| 2463 |     QCOMPARE(object.receivers(SIGNAL(destroyed())), 2); | 
| 2464 |     object.disconnect(SIGNAL(destroyed()), receiver: &object, SLOT(deleteLater())); | 
| 2465 |     QCOMPARE(object.receivers(SIGNAL(destroyed())), 0); | 
| 2466 | } | 
| 2467 |  | 
| 2468 | enum Enum { }; | 
| 2469 |  | 
| 2470 | struct Struct { }; | 
| 2471 | class Class { }; | 
| 2472 | template <typename T> class Template { }; | 
| 2473 |  | 
| 2474 | class NormalizeObject : public QObject | 
| 2475 | { | 
| 2476 |     Q_OBJECT | 
| 2477 |  | 
| 2478 | public: | 
| 2479 |  | 
| 2480 | signals: | 
| 2481 |     void uintPointerSignal(uint *); | 
| 2482 |     void ulongPointerSignal(ulong *); | 
| 2483 |     void constUintPointerSignal(const uint *); | 
| 2484 |     void constUlongPointerSignal(const ulong *); | 
| 2485 |  | 
| 2486 |     void structSignal(Struct s); | 
| 2487 |     void classSignal(Class c); | 
| 2488 |     void enumSignal(Enum e); | 
| 2489 |  | 
| 2490 |     void structPointerSignal(Struct *s); | 
| 2491 |     void classPointerSignal(Class *c); | 
| 2492 |     void enumPointerSignal(Enum *e); | 
| 2493 |  | 
| 2494 |     void constStructPointerSignal(const Struct *s); | 
| 2495 |     void constClassPointerSignal(const Class *c); | 
| 2496 |     void constEnumPointerSignal(const Enum *e); | 
| 2497 |  | 
| 2498 |     void constStructPointerConstPointerSignal(const Struct * const *s); | 
| 2499 |     void constClassPointerConstPointerSignal(const Class * const *c); | 
| 2500 |     void constEnumPointerConstPointerSignal(const Enum * const *e); | 
| 2501 |  | 
| 2502 |     void unsignedintSignal(unsigned int); | 
| 2503 |     void unsignedSignal(unsigned); | 
| 2504 |     void unsignedlongSignal(unsigned long); | 
| 2505 |     void unsignedlonglongSignal(quint64); | 
| 2506 |     void unsignedlongintSignal(unsigned long int); | 
| 2507 |     void unsignedshortSignal(unsigned short); | 
| 2508 |     void unsignedcharSignal(unsigned char); | 
| 2509 |  | 
| 2510 |     void typeRefSignal(Template<Class &> &ref); | 
| 2511 |     void constTypeRefSignal(const Template<Class const &> &ref); | 
| 2512 |     void typeConstRefSignal(Template<Class const &> const &ref); | 
| 2513 |  | 
| 2514 |     void typePointerConstRefSignal(Class * const &); | 
| 2515 |  | 
| 2516 |     void constTemplateSignal1( Template<int > ); | 
| 2517 |     void constTemplateSignal2( Template< const int >); | 
| 2518 |  | 
| 2519 | public slots: | 
| 2520 |     void uintPointerSlot(uint *) { } | 
| 2521 |     void ulongPointerSlot(ulong *) { } | 
| 2522 |     void constUintPointerSlot(const uint *) { } | 
| 2523 |     void constUlongPointerSlot(const ulong *) { } | 
| 2524 |  | 
| 2525 |     void structSlot(Struct s) { Q_UNUSED(s); } | 
| 2526 |     void classSlot(Class c) { Q_UNUSED(c); } | 
| 2527 |     void enumSlot(Enum e) { Q_UNUSED(e); } | 
| 2528 |  | 
| 2529 |     void structPointerSlot(Struct *s) { Q_UNUSED(s); } | 
| 2530 |     void classPointerSlot(Class *c) { Q_UNUSED(c); } | 
| 2531 |     void enumPointerSlot(Enum *e) { Q_UNUSED(e); } | 
| 2532 |  | 
| 2533 |     void constStructPointerSlot(const Struct *s) { Q_UNUSED(s); } | 
| 2534 |     void constClassPointerSlot(const Class *c) { Q_UNUSED(c); } | 
| 2535 |     void constEnumPointerSlot(const Enum *e) { Q_UNUSED(e); } | 
| 2536 |  | 
| 2537 |     void constStructPointerConstPointerSlot(const Struct * const *s) { Q_UNUSED(s); } | 
| 2538 |     void constClassPointerConstPointerSlot(const Class * const *c) { Q_UNUSED(c); } | 
| 2539 |     void constEnumPointerConstPointerSlot(const Enum * const *e) { Q_UNUSED(e); } | 
| 2540 |  | 
| 2541 |     void uintSlot(uint) {}; | 
| 2542 |     void unsignedintSlot(unsigned int) {}; | 
| 2543 |     void unsignedSlot(unsigned) {}; | 
| 2544 |     void unsignedlongSlot(unsigned long) {}; | 
| 2545 |     void unsignedlonglongSlot(quint64) {}; | 
| 2546 |     void unsignedlongintSlot(unsigned long int) {}; | 
| 2547 |     void unsignedshortSlot(unsigned short) {}; | 
| 2548 |     void unsignedcharSlot(unsigned char) {}; | 
| 2549 |  | 
| 2550 |     void typeRefSlot(Template<Class &> &) {} | 
| 2551 |     void constTypeRefSlot(const Template<const Class &> &) {} | 
| 2552 |     void typeConstRefSlot(Template<Class const &> const &) {} | 
| 2553 |  | 
| 2554 |     void typePointerConstRefSlot(Class * const &) {} | 
| 2555 |  | 
| 2556 |     void constTemplateSlot1(Template<int > const) {} | 
| 2557 |     void constTemplateSlot2(const Template<int > ) {} | 
| 2558 |     void constTemplateSlot3(const Template< const int >) {} | 
| 2559 | }; | 
| 2560 |  | 
| 2561 | void tst_QObject::normalize() | 
| 2562 | { | 
| 2563 |     NormalizeObject object; | 
| 2564 |  | 
| 2565 |     // unsigned int -> uint, unsigned long -> ulong | 
| 2566 |     QVERIFY(object.connect(&object, | 
| 2567 |                            SIGNAL(uintPointerSignal(uint *)), | 
| 2568 |                            SLOT(uintPointerSlot(uint *)))); | 
| 2569 |     QVERIFY(object.connect(&object, | 
| 2570 |                            SIGNAL(uintPointerSignal(unsigned int *)), | 
| 2571 |                            SLOT(uintPointerSlot(uint *)))); | 
| 2572 |     QVERIFY(object.connect(&object, | 
| 2573 |                            SIGNAL(uintPointerSignal(uint *)), | 
| 2574 |                            SLOT(uintPointerSlot(unsigned int *)))); | 
| 2575 |  | 
| 2576 |     QVERIFY(object.connect(&object, | 
| 2577 |                            SIGNAL(constUintPointerSignal(const uint *)), | 
| 2578 |                            SLOT(constUintPointerSlot(const uint *)))); | 
| 2579 |     QVERIFY(object.connect(&object, | 
| 2580 |                            SIGNAL(constUintPointerSignal(const unsigned int *)), | 
| 2581 |                            SLOT(constUintPointerSlot(const uint *)))); | 
| 2582 |     QVERIFY(object.connect(&object, | 
| 2583 |                            SIGNAL(constUintPointerSignal(const uint *)), | 
| 2584 |                            SLOT(constUintPointerSlot(const unsigned int *)))); | 
| 2585 |  | 
| 2586 |     QVERIFY(object.connect(&object, | 
| 2587 |                            SIGNAL(ulongPointerSignal(ulong *)), | 
| 2588 |                            SLOT(ulongPointerSlot(ulong *)))); | 
| 2589 |     QVERIFY(object.connect(&object, | 
| 2590 |                            SIGNAL(ulongPointerSignal(unsigned long *)), | 
| 2591 |                            SLOT(ulongPointerSlot(ulong *)))); | 
| 2592 |     QVERIFY(object.connect(&object, | 
| 2593 |                            SIGNAL(ulongPointerSignal(ulong *)), | 
| 2594 |                            SLOT(ulongPointerSlot(unsigned long *)))); | 
| 2595 |  | 
| 2596 |     QVERIFY(object.connect(&object, | 
| 2597 |                            SIGNAL(constUlongPointerSignal(const ulong *)), | 
| 2598 |                            SLOT(constUlongPointerSlot(const ulong *)))); | 
| 2599 |     QVERIFY(object.connect(&object, | 
| 2600 |                            SIGNAL(constUlongPointerSignal(const unsigned long *)), | 
| 2601 |                            SLOT(constUlongPointerSlot(const ulong *)))); | 
| 2602 |     QVERIFY(object.connect(&object, | 
| 2603 |                            SIGNAL(constUlongPointerSignal(const ulong *)), | 
| 2604 |                            SLOT(constUlongPointerSlot(const unsigned long *)))); | 
| 2605 |  | 
| 2606 |     // struct, class, and enum are optional | 
| 2607 |     QVERIFY(object.connect(&object, | 
| 2608 |                            SIGNAL(structSignal(struct Struct)), | 
| 2609 |                            SLOT(structSlot(struct Struct)))); | 
| 2610 |     QVERIFY(object.connect(&object, | 
| 2611 |                            SIGNAL(structSignal(Struct)), | 
| 2612 |                            SLOT(structSlot(struct Struct)))); | 
| 2613 |     QVERIFY(object.connect(&object, | 
| 2614 |                            SIGNAL(structSignal(struct Struct)), | 
| 2615 |                            SLOT(structSlot(Struct)))); | 
| 2616 |     QVERIFY(object.connect(&object, | 
| 2617 |                            SIGNAL(classSignal(class Class)), | 
| 2618 |                            SLOT(classSlot(class Class)))); | 
| 2619 |     QVERIFY(object.connect(&object, | 
| 2620 |                            SIGNAL(classSignal(Class)), | 
| 2621 |                            SLOT(classSlot(class Class)))); | 
| 2622 |     QVERIFY(object.connect(&object, | 
| 2623 |                            SIGNAL(classSignal(class Class)), | 
| 2624 |                            SLOT(classSlot(Class)))); | 
| 2625 |     QVERIFY(object.connect(&object, | 
| 2626 |                            SIGNAL(enumSignal(enum Enum)), | 
| 2627 |                            SLOT(enumSlot(enum Enum)))); | 
| 2628 |     QVERIFY(object.connect(&object, | 
| 2629 |                            SIGNAL(enumSignal(Enum)), | 
| 2630 |                            SLOT(enumSlot(enum Enum)))); | 
| 2631 |     QVERIFY(object.connect(&object, | 
| 2632 |                            SIGNAL(enumSignal(enum Enum)), | 
| 2633 |                            SLOT(enumSlot(Enum)))); | 
| 2634 |  | 
| 2635 |     QVERIFY(object.connect(&object, | 
| 2636 |                            SIGNAL(structPointerSignal(struct Struct *)), | 
| 2637 |                            SLOT(structPointerSlot(struct Struct *)))); | 
| 2638 |     QVERIFY(object.connect(&object, | 
| 2639 |                            SIGNAL(structPointerSignal(Struct *)), | 
| 2640 |                            SLOT(structPointerSlot(struct Struct *)))); | 
| 2641 |     QVERIFY(object.connect(&object, | 
| 2642 |                            SIGNAL(structPointerSignal(struct Struct *)), | 
| 2643 |                            SLOT(structPointerSlot(Struct *)))); | 
| 2644 |     QVERIFY(object.connect(&object, | 
| 2645 |                            SIGNAL(classPointerSignal(class Class *)), | 
| 2646 |                            SLOT(classPointerSlot(class Class *)))); | 
| 2647 |     QVERIFY(object.connect(&object, | 
| 2648 |                            SIGNAL(classPointerSignal(Class *)), | 
| 2649 |                            SLOT(classPointerSlot(class Class *)))); | 
| 2650 |     QVERIFY(object.connect(&object, | 
| 2651 |                            SIGNAL(classPointerSignal(class Class *)), | 
| 2652 |                            SLOT(classPointerSlot(Class *)))); | 
| 2653 |     QVERIFY(object.connect(&object, | 
| 2654 |                            SIGNAL(enumPointerSignal(enum Enum *)), | 
| 2655 |                            SLOT(enumPointerSlot(enum Enum *)))); | 
| 2656 |     QVERIFY(object.connect(&object, | 
| 2657 |                            SIGNAL(enumPointerSignal(Enum *)), | 
| 2658 |                            SLOT(enumPointerSlot(enum Enum *)))); | 
| 2659 |     QVERIFY(object.connect(&object, | 
| 2660 |                            SIGNAL(enumPointerSignal(enum Enum *)), | 
| 2661 |                            SLOT(enumPointerSlot(Enum *)))); | 
| 2662 |  | 
| 2663 |     QVERIFY(object.connect(&object, | 
| 2664 |                            SIGNAL(constStructPointerSignal(const struct Struct *)), | 
| 2665 |                            SLOT(constStructPointerSlot(const struct Struct *)))); | 
| 2666 |     QVERIFY(object.connect(&object, | 
| 2667 |                            SIGNAL(constStructPointerSignal(const Struct *)), | 
| 2668 |                            SLOT(constStructPointerSlot(const struct Struct *)))); | 
| 2669 |     QVERIFY(object.connect(&object, | 
| 2670 |                            SIGNAL(constStructPointerSignal(const struct Struct *)), | 
| 2671 |                            SLOT(constStructPointerSlot(const Struct *)))); | 
| 2672 |     QVERIFY(object.connect(&object, | 
| 2673 |                            SIGNAL(constClassPointerSignal(const class Class *)), | 
| 2674 |                            SLOT(constClassPointerSlot(const class Class *)))); | 
| 2675 |     QVERIFY(object.connect(&object, | 
| 2676 |                            SIGNAL(constClassPointerSignal(const Class *)), | 
| 2677 |                            SLOT(constClassPointerSlot(const class Class *)))); | 
| 2678 |     QVERIFY(object.connect(&object, | 
| 2679 |                            SIGNAL(constClassPointerSignal(const class Class *)), | 
| 2680 |                            SLOT(constClassPointerSlot(const Class *)))); | 
| 2681 |     QVERIFY(object.connect(&object, | 
| 2682 |                            SIGNAL(constEnumPointerSignal(const enum Enum *)), | 
| 2683 |                            SLOT(constEnumPointerSlot(const enum Enum *)))); | 
| 2684 |     QVERIFY(object.connect(&object, | 
| 2685 |                            SIGNAL(constEnumPointerSignal(const Enum *)), | 
| 2686 |                            SLOT(constEnumPointerSlot(const enum Enum *)))); | 
| 2687 |     QVERIFY(object.connect(&object, | 
| 2688 |                            SIGNAL(constEnumPointerSignal(const enum Enum *)), | 
| 2689 |                            SLOT(constEnumPointerSlot(const Enum *)))); | 
| 2690 |  | 
| 2691 |     QVERIFY(object.connect(&object, | 
| 2692 |                            SIGNAL(constStructPointerSignal(struct Struct const *)), | 
| 2693 |                            SLOT(constStructPointerSlot(struct Struct const *)))); | 
| 2694 |     QVERIFY(object.connect(&object, | 
| 2695 |                            SIGNAL(constStructPointerSignal(Struct const *)), | 
| 2696 |                            SLOT(constStructPointerSlot(struct Struct const *)))); | 
| 2697 |     QVERIFY(object.connect(&object, | 
| 2698 |                            SIGNAL(constStructPointerSignal(struct Struct const *)), | 
| 2699 |                            SLOT(constStructPointerSlot(Struct const *)))); | 
| 2700 |     QVERIFY(object.connect(&object, | 
| 2701 |                            SIGNAL(constClassPointerSignal(class Class const *)), | 
| 2702 |                            SLOT(constClassPointerSlot(class Class const *)))); | 
| 2703 |     QVERIFY(object.connect(&object, | 
| 2704 |                            SIGNAL(constClassPointerSignal(Class const *)), | 
| 2705 |                            SLOT(constClassPointerSlot(class Class const *)))); | 
| 2706 |     QVERIFY(object.connect(&object, | 
| 2707 |                            SIGNAL(constClassPointerSignal(class Class const *)), | 
| 2708 |                            SLOT(constClassPointerSlot(Class const *)))); | 
| 2709 |     QVERIFY(object.connect(&object, | 
| 2710 |                            SIGNAL(constEnumPointerSignal(enum Enum const *)), | 
| 2711 |                            SLOT(constEnumPointerSlot(enum Enum const *)))); | 
| 2712 |     QVERIFY(object.connect(&object, | 
| 2713 |                            SIGNAL(constEnumPointerSignal(Enum const *)), | 
| 2714 |                            SLOT(constEnumPointerSlot(enum Enum const *)))); | 
| 2715 |     QVERIFY(object.connect(&object, | 
| 2716 |                            SIGNAL(constEnumPointerSignal(enum Enum const *)), | 
| 2717 |                            SLOT(constEnumPointerSlot(Enum const *)))); | 
| 2718 |  | 
| 2719 |     QVERIFY(object.connect(&object, | 
| 2720 |                            SIGNAL(constStructPointerConstPointerSignal(const struct Struct * const *)), | 
| 2721 |                            SLOT(constStructPointerConstPointerSlot(const struct Struct * const *)))); | 
| 2722 |     QVERIFY(object.connect(&object, | 
| 2723 |                            SIGNAL(constStructPointerConstPointerSignal(const Struct * const *)), | 
| 2724 |                            SLOT(constStructPointerConstPointerSlot(const struct Struct * const *)))); | 
| 2725 |     QVERIFY(object.connect(&object, | 
| 2726 |                            SIGNAL(constStructPointerConstPointerSignal(const struct Struct * const *)), | 
| 2727 |                            SLOT(constStructPointerConstPointerSlot(const Struct * const *)))); | 
| 2728 |     QVERIFY(object.connect(&object, | 
| 2729 |                            SIGNAL(constClassPointerConstPointerSignal(const class Class * const *)), | 
| 2730 |                            SLOT(constClassPointerConstPointerSlot(const class Class * const *)))); | 
| 2731 |     QVERIFY(object.connect(&object, | 
| 2732 |                            SIGNAL(constClassPointerConstPointerSignal(const Class * const *)), | 
| 2733 |                            SLOT(constClassPointerConstPointerSlot(const class Class * const *)))); | 
| 2734 |     QVERIFY(object.connect(&object, | 
| 2735 |                            SIGNAL(constClassPointerConstPointerSignal(const class Class * const *)), | 
| 2736 |                            SLOT(constClassPointerConstPointerSlot(const Class * const *)))); | 
| 2737 |     QVERIFY(object.connect(&object, | 
| 2738 |                            SIGNAL(constEnumPointerConstPointerSignal(const enum Enum * const *)), | 
| 2739 |                            SLOT(constEnumPointerConstPointerSlot(const enum Enum * const *)))); | 
| 2740 |     QVERIFY(object.connect(&object, | 
| 2741 |                            SIGNAL(constEnumPointerConstPointerSignal(const Enum * const *)), | 
| 2742 |                            SLOT(constEnumPointerConstPointerSlot(const enum Enum * const *)))); | 
| 2743 |     QVERIFY(object.connect(&object, | 
| 2744 |                            SIGNAL(constEnumPointerConstPointerSignal(const enum Enum * const *)), | 
| 2745 |                            SLOT(constEnumPointerConstPointerSlot(const Enum * const *)))); | 
| 2746 |  | 
| 2747 |     QVERIFY(object.connect(&object, | 
| 2748 |                            SIGNAL(constStructPointerConstPointerSignal(struct Struct const * const *)), | 
| 2749 |                            SLOT(constStructPointerConstPointerSlot(struct Struct const * const *)))); | 
| 2750 |     QVERIFY(object.connect(&object, | 
| 2751 |                            SIGNAL(constStructPointerConstPointerSignal(Struct const * const *)), | 
| 2752 |                            SLOT(constStructPointerConstPointerSlot(struct Struct const * const *)))); | 
| 2753 |     QVERIFY(object.connect(&object, | 
| 2754 |                            SIGNAL(constStructPointerConstPointerSignal(struct Struct const * const *)), | 
| 2755 |                            SLOT(constStructPointerConstPointerSlot(Struct const * const *)))); | 
| 2756 |     QVERIFY(object.connect(&object, | 
| 2757 |                            SIGNAL(constClassPointerConstPointerSignal(class Class const * const *)), | 
| 2758 |                            SLOT(constClassPointerConstPointerSlot(class Class const * const *)))); | 
| 2759 |     QVERIFY(object.connect(&object, | 
| 2760 |                            SIGNAL(constClassPointerConstPointerSignal(Class const * const *)), | 
| 2761 |                            SLOT(constClassPointerConstPointerSlot(class Class const * const *)))); | 
| 2762 |     QVERIFY(object.connect(&object, | 
| 2763 |                            SIGNAL(constClassPointerConstPointerSignal(class Class const * const *)), | 
| 2764 |                            SLOT(constClassPointerConstPointerSlot(Class const * const *)))); | 
| 2765 |     QVERIFY(object.connect(&object, | 
| 2766 |                            SIGNAL(constEnumPointerConstPointerSignal(enum Enum const * const *)), | 
| 2767 |                            SLOT(constEnumPointerConstPointerSlot(enum Enum const * const *)))); | 
| 2768 |     QVERIFY(object.connect(&object, | 
| 2769 |                            SIGNAL(constEnumPointerConstPointerSignal(Enum const * const *)), | 
| 2770 |                            SLOT(constEnumPointerConstPointerSlot(enum Enum const * const *)))); | 
| 2771 |     QVERIFY(object.connect(&object, | 
| 2772 |                            SIGNAL(constEnumPointerConstPointerSignal(enum Enum const * const *)), | 
| 2773 |                            SLOT(constEnumPointerConstPointerSlot(Enum const * const *)))); | 
| 2774 |  | 
| 2775 |     QVERIFY(object.connect(&object, | 
| 2776 |                            SIGNAL(unsignedintSignal(unsigned int)), | 
| 2777 |                            SLOT(unsignedintSlot(unsigned int)))); | 
| 2778 |     QVERIFY(object.connect(&object, | 
| 2779 |                            SIGNAL(unsignedSignal(unsigned)), | 
| 2780 |                            SLOT(unsignedSlot(unsigned)))); | 
| 2781 |     QVERIFY(object.connect(&object, | 
| 2782 |                            SIGNAL(unsignedSignal(unsigned)), | 
| 2783 |                            SLOT(uintSlot(uint)))); | 
| 2784 |     QVERIFY(object.connect(&object, | 
| 2785 |                            SIGNAL(unsignedlongSignal(unsigned long)), | 
| 2786 |                            SLOT(unsignedlongSlot(unsigned long)))); | 
| 2787 |     QVERIFY(object.connect(&object, | 
| 2788 |                            SIGNAL(unsignedlonglongSignal(quint64)), | 
| 2789 |                            SLOT(unsignedlonglongSlot(quint64)))); | 
| 2790 |     QVERIFY(object.connect(&object, | 
| 2791 |                            SIGNAL(unsignedlongintSignal(unsigned long int)), | 
| 2792 |                            SLOT(unsignedlongintSlot(unsigned long int)))); | 
| 2793 |     QVERIFY(object.connect(&object, | 
| 2794 |                            SIGNAL(unsignedshortSignal(unsigned short)), | 
| 2795 |                            SLOT(unsignedshortSlot(unsigned short)))); | 
| 2796 |     QVERIFY(object.connect(&object, | 
| 2797 |                            SIGNAL(unsignedcharSignal(unsigned char)), | 
| 2798 |                            SLOT(unsignedcharSlot(unsigned char)))); | 
| 2799 |  | 
| 2800 |     // connect when original template signature and mixed usage of 'T<C const &> const &', | 
| 2801 |     // 'const T<const C &> &', and 'T<const C &>' | 
| 2802 |  | 
| 2803 |     QVERIFY(object.connect(&object, | 
| 2804 |                            SIGNAL(typeRefSignal(Template<Class &> &)), | 
| 2805 |                            SLOT(typeRefSlot(Template<Class &> &)))); | 
| 2806 |  | 
| 2807 |     QVERIFY(object.connect(&object, | 
| 2808 |                            SIGNAL(constTypeRefSignal(const Template<const Class &> &)), | 
| 2809 |                            SLOT(constTypeRefSlot(const Template<const Class &> &)))); | 
| 2810 |     QVERIFY(object.connect(&object, | 
| 2811 |                            SIGNAL(constTypeRefSignal(const Template<const Class &> &)), | 
| 2812 |                            SLOT(constTypeRefSlot(const Template<Class const &> &)))); | 
| 2813 |     QVERIFY(object.connect(&object, | 
| 2814 |                            SIGNAL(constTypeRefSignal(const Template<const Class &> &)), | 
| 2815 |                            SLOT(constTypeRefSlot(Template<Class const &> const &)))); | 
| 2816 |     QVERIFY(object.connect(&object, | 
| 2817 |                            SIGNAL(constTypeRefSignal(Template<const Class &> const &)), | 
| 2818 |                            SLOT(constTypeRefSlot(Template<Class const &> const &)))); | 
| 2819 |     QVERIFY(object.connect(&object, | 
| 2820 |                            SIGNAL(constTypeRefSignal(Template<Class const &> const &)), | 
| 2821 |                            SLOT(constTypeRefSlot(Template<Class const &> const &)))); | 
| 2822 |  | 
| 2823 |     QVERIFY(object.connect(&object, | 
| 2824 |                            SIGNAL(constTypeRefSignal(const Template<const Class &> &)), | 
| 2825 |                            SLOT(typeConstRefSlot(const Template<const Class &> &)))); | 
| 2826 |     QVERIFY(object.connect(&object, | 
| 2827 |                            SIGNAL(constTypeRefSignal(const Template<const Class &> &)), | 
| 2828 |                            SLOT(typeConstRefSlot(const Template<Class const &> &)))); | 
| 2829 |     QVERIFY(object.connect(&object, | 
| 2830 |                            SIGNAL(constTypeRefSignal(const Template<const Class &> &)), | 
| 2831 |                            SLOT(typeConstRefSlot(Template<Class const &> const &)))); | 
| 2832 |     QVERIFY(object.connect(&object, | 
| 2833 |                            SIGNAL(constTypeRefSignal(Template<const Class &> const &)), | 
| 2834 |                            SLOT(typeConstRefSlot(Template<Class const &> const &)))); | 
| 2835 |     QVERIFY(object.connect(&object, | 
| 2836 |                            SIGNAL(constTypeRefSignal(Template<Class const &> const &)), | 
| 2837 |                            SLOT(typeConstRefSlot(Template<Class const &> const &)))); | 
| 2838 |  | 
| 2839 |     QVERIFY(object.connect(&object, | 
| 2840 |                            SIGNAL(typeConstRefSignal(const Template<const Class &> &)), | 
| 2841 |                            SLOT(constTypeRefSlot(const Template<const Class &> &)))); | 
| 2842 |     QVERIFY(object.connect(&object, | 
| 2843 |                            SIGNAL(typeConstRefSignal(const Template<const Class &> &)), | 
| 2844 |                            SLOT(constTypeRefSlot(const Template<Class const &> &)))); | 
| 2845 |     QVERIFY(object.connect(&object, | 
| 2846 |                            SIGNAL(typeConstRefSignal(const Template<const Class &> &)), | 
| 2847 |                            SLOT(constTypeRefSlot(Template<Class const &> const &)))); | 
| 2848 |     QVERIFY(object.connect(&object, | 
| 2849 |                            SIGNAL(typeConstRefSignal(Template<const Class &> const &)), | 
| 2850 |                            SLOT(constTypeRefSlot(Template<Class const &> const &)))); | 
| 2851 |     QVERIFY(object.connect(&object, | 
| 2852 |                            SIGNAL(typeConstRefSignal(Template<Class const &> const &)), | 
| 2853 |                            SLOT(constTypeRefSlot(Template<Class const &> const &)))); | 
| 2854 |  | 
| 2855 |     QVERIFY(object.connect(&object, | 
| 2856 |                            SIGNAL(typeConstRefSignal(const Template<const Class &> &)), | 
| 2857 |                            SLOT(typeConstRefSlot(const Template<const Class &> &)))); | 
| 2858 |     QVERIFY(object.connect(&object, | 
| 2859 |                            SIGNAL(typeConstRefSignal(const Template<const Class &> &)), | 
| 2860 |                            SLOT(typeConstRefSlot(const Template<Class const &> &)))); | 
| 2861 |     QVERIFY(object.connect(&object, | 
| 2862 |                            SIGNAL(typeConstRefSignal(const Template<const Class &> &)), | 
| 2863 |                            SLOT(typeConstRefSlot(Template<Class const &> const &)))); | 
| 2864 |     QVERIFY(object.connect(&object, | 
| 2865 |                            SIGNAL(typeConstRefSignal(Template<const Class &> const &)), | 
| 2866 |                            SLOT(typeConstRefSlot(Template<Class const &> const &)))); | 
| 2867 |     QVERIFY(object.connect(&object, | 
| 2868 |                            SIGNAL(typeConstRefSignal(Template<Class const &> const &)), | 
| 2869 |                            SLOT(typeConstRefSlot(Template<Class const &> const &)))); | 
| 2870 |  | 
| 2871 |     QVERIFY(object.connect(&object, | 
| 2872 |                            SIGNAL(typePointerConstRefSignal(Class*const&)), | 
| 2873 |                            SLOT(typePointerConstRefSlot(Class*const&)))); | 
| 2874 |     QVERIFY(object.connect(&object, | 
| 2875 |                            SIGNAL(typePointerConstRefSignal(Class*const&)), | 
| 2876 |                            SLOT(typePointerConstRefSlot(Class*)))); | 
| 2877 |     QVERIFY(object.connect(&object, | 
| 2878 |                            SIGNAL(typePointerConstRefSignal(Class*)), | 
| 2879 |                            SLOT(typePointerConstRefSlot(Class*const&)))); | 
| 2880 |     QVERIFY(object.connect(&object, | 
| 2881 |                            SIGNAL(typePointerConstRefSignal(Class*)), | 
| 2882 |                            SLOT(typePointerConstRefSlot(Class*)))); | 
| 2883 |  | 
| 2884 |     QVERIFY( connect(&object, SIGNAL(constTemplateSignal1(Template <int>)), | 
| 2885 |                      &object , SLOT(constTemplateSlot1 (Template<int > )  ) )); | 
| 2886 |     QVERIFY( connect(&object, SIGNAL(constTemplateSignal1(Template <int>)), | 
| 2887 |                      &object , SLOT(constTemplateSlot2 (Template<int > )  ) )); | 
| 2888 |     QVERIFY( connect(&object, SIGNAL(constTemplateSignal2(Template <const int>)), | 
| 2889 |                      &object , SLOT(constTemplateSlot3(Template<int const > ) ) )); | 
| 2890 |  | 
| 2891 |     //type does not match | 
| 2892 |     QTest::ignoreMessage(type: QtWarningMsg, message: "QObject::connect: Incompatible sender/receiver arguments\n"  | 
| 2893 |                     "        NormalizeObject::constTemplateSignal1(Template<int>) --> NormalizeObject::constTemplateSlot3(Template<const int>)" ); | 
| 2894 |     QVERIFY(!connect(&object, SIGNAL(constTemplateSignal1(Template <int>)), | 
| 2895 |                      &object , SLOT(constTemplateSlot3(Template<int const> ) ) )); | 
| 2896 | } | 
| 2897 |  | 
| 2898 | class SiblingDeleter : public QObject | 
| 2899 | { | 
| 2900 | public: | 
| 2901 |     inline SiblingDeleter(QObject *sibling, QObject *parent) | 
| 2902 |         : QObject(parent), sibling(sibling) {} | 
| 2903 |     inline virtual ~SiblingDeleter() { delete sibling; } | 
| 2904 |  | 
| 2905 | private: | 
| 2906 |     QPointer<QObject> sibling; | 
| 2907 | }; | 
| 2908 |  | 
| 2909 |  | 
| 2910 | void tst_QObject::childDeletesItsSibling() | 
| 2911 | { | 
| 2912 |     QObject *commonParent = new QObject(0); | 
| 2913 |     QPointer<QObject> child = new QObject(0); | 
| 2914 |     QPointer<QObject> siblingDeleter = new SiblingDeleter(child, commonParent); | 
| 2915 |     child->setParent(commonParent); | 
| 2916 |     delete commonParent; // don't crash | 
| 2917 |     QVERIFY(!child); | 
| 2918 |     QVERIFY(!siblingDeleter); | 
| 2919 | } | 
| 2920 |  | 
| 2921 | void tst_QObject::floatProperty() | 
| 2922 | { | 
| 2923 |     PropertyObject obj; | 
| 2924 |     const int idx = obj.metaObject()->indexOfProperty(name: "myFloat" ); | 
| 2925 |     QVERIFY(idx > 0); | 
| 2926 |     QMetaProperty prop = obj.metaObject()->property(index: idx); | 
| 2927 |     QVERIFY(prop.isValid()); | 
| 2928 |     QCOMPARE(int(prop.type()), QMetaType::type("float" )); | 
| 2929 |     QVERIFY(!prop.write(&obj, QVariant("Hello" ))); | 
| 2930 |     QVERIFY(prop.write(&obj, QVariant::fromValue(128.0f))); | 
| 2931 |     QVariant v = prop.read(obj: &obj); | 
| 2932 |     QCOMPARE(v.userType(), int(QMetaType::Float)); | 
| 2933 |     QCOMPARE(qvariant_cast<float>(v), 128.0f); | 
| 2934 | } | 
| 2935 |  | 
| 2936 | void tst_QObject::qrealProperty() | 
| 2937 | { | 
| 2938 |     PropertyObject obj; | 
| 2939 |     const int idx = obj.metaObject()->indexOfProperty(name: "myQReal" ); | 
| 2940 |     QVERIFY(idx > 0); | 
| 2941 |     QMetaProperty prop = obj.metaObject()->property(index: idx); | 
| 2942 |     QVERIFY(prop.isValid()); | 
| 2943 |     QCOMPARE(int(prop.type()), QMetaType::type("qreal" )); | 
| 2944 |     QVERIFY(!prop.write(&obj, QVariant("Hello" ))); | 
| 2945 |  | 
| 2946 |     QVERIFY(prop.write(&obj, QVariant::fromValue(128.0f))); | 
| 2947 |     QVariant v = prop.read(obj: &obj); | 
| 2948 |     QCOMPARE(v.userType(), qMetaTypeId<qreal>()); | 
| 2949 |     QCOMPARE(qvariant_cast<qreal>(v), 128.0); | 
| 2950 |  | 
| 2951 |     QVERIFY(prop.write(&obj, QVariant::fromValue(double(127)))); | 
| 2952 |     v = prop.read(obj: &obj); | 
| 2953 |     QCOMPARE(v.userType(), qMetaTypeId<qreal>()); | 
| 2954 |     QCOMPARE(qvariant_cast<qreal>(v), 127.0); | 
| 2955 | } | 
| 2956 |  | 
| 2957 | class DynamicPropertyObject : public PropertyObject | 
| 2958 | { | 
| 2959 | public: | 
| 2960 |     inline DynamicPropertyObject() {} | 
| 2961 |  | 
| 2962 |     inline virtual bool event(QEvent *e) { | 
| 2963 |         if (e->type() == QEvent::DynamicPropertyChange) { | 
| 2964 |             changedDynamicProperties.append(t: static_cast<QDynamicPropertyChangeEvent *>(e)->propertyName()); | 
| 2965 |         } | 
| 2966 |         return QObject::event(event: e); | 
| 2967 |     } | 
| 2968 |  | 
| 2969 |     QList<QByteArray> changedDynamicProperties; | 
| 2970 | }; | 
| 2971 |  | 
| 2972 | void tst_QObject::dynamicProperties() | 
| 2973 | { | 
| 2974 |     DynamicPropertyObject obj; | 
| 2975 |  | 
| 2976 |     QVERIFY(obj.dynamicPropertyNames().isEmpty()); | 
| 2977 |  | 
| 2978 |     // set a non-dynamic property | 
| 2979 |     QVERIFY(obj.setProperty("number" , 42)); | 
| 2980 |     QVERIFY(obj.changedDynamicProperties.isEmpty()); | 
| 2981 |     QCOMPARE(obj.property("number" ).toInt(), 42); | 
| 2982 |  | 
| 2983 |     QVERIFY(!obj.setProperty("number" , "invalid string" )); | 
| 2984 |     QVERIFY(obj.changedDynamicProperties.isEmpty()); | 
| 2985 |  | 
| 2986 |     // set a dynamic property | 
| 2987 |     QVERIFY(!obj.setProperty("myuserproperty" , "Hello" )); | 
| 2988 |     QCOMPARE(obj.changedDynamicProperties.count(), 1); | 
| 2989 |     QCOMPARE(obj.changedDynamicProperties.first(), QByteArray("myuserproperty" )); | 
| 2990 |     //check if there is no redundant DynamicPropertyChange events | 
| 2991 |     QVERIFY(!obj.setProperty("myuserproperty" , "Hello" )); | 
| 2992 |     QCOMPARE(obj.changedDynamicProperties.count(), 1); | 
| 2993 |  | 
| 2994 |     QCOMPARE(obj.property("myuserproperty" ).type(), QVariant::String); | 
| 2995 |     QCOMPARE(obj.property("myuserproperty" ).toString(), QString("Hello" )); | 
| 2996 |  | 
| 2997 |     QCOMPARE(obj.dynamicPropertyNames().count(), 1); | 
| 2998 |     QCOMPARE(obj.dynamicPropertyNames().first(), QByteArray("myuserproperty" )); | 
| 2999 |  | 
| 3000 |     // change type of the dynamic property | 
| 3001 |     obj.changedDynamicProperties.clear(); | 
| 3002 |     QVERIFY(!obj.setProperty("myuserproperty" , QByteArray("Hello" ))); | 
| 3003 |     QCOMPARE(obj.changedDynamicProperties.count(), 1); | 
| 3004 |     QCOMPARE(obj.changedDynamicProperties.first(), QByteArray("myuserproperty" )); | 
| 3005 |     QCOMPARE(obj.property("myuserproperty" ).type(), QVariant::ByteArray); | 
| 3006 |     QCOMPARE(obj.property("myuserproperty" ).toString(), QByteArray("Hello" )); | 
| 3007 |  | 
| 3008 |     // unset the property | 
| 3009 |     obj.changedDynamicProperties.clear(); | 
| 3010 |     QVERIFY(!obj.setProperty("myuserproperty" , QVariant())); | 
| 3011 |  | 
| 3012 |     QCOMPARE(obj.changedDynamicProperties.count(), 1); | 
| 3013 |     QCOMPARE(obj.changedDynamicProperties.first(), QByteArray("myuserproperty" )); | 
| 3014 |     obj.changedDynamicProperties.clear(); | 
| 3015 |  | 
| 3016 |     QVERIFY(obj.property("myuserproperty" ).isNull()); | 
| 3017 |  | 
| 3018 |     QVERIFY(obj.dynamicPropertyNames().isEmpty()); | 
| 3019 | } | 
| 3020 |  | 
| 3021 | void tst_QObject::recursiveSignalEmission() | 
| 3022 | { | 
| 3023 | #if !QT_CONFIG(process) | 
| 3024 |     QSKIP("No qprocess support" , SkipAll); | 
| 3025 | #else | 
| 3026 |     QProcess proc; | 
| 3027 |  | 
| 3028 |     // Add the executable's directory to path so that we can find the test helper next to it | 
| 3029 |     // in a cross-platform way. We must do this because the CWD is not pointing to this directory | 
| 3030 |     // in debug-and-release builds. | 
| 3031 |     QByteArray pathEnv = qgetenv(varName: "PATH" ); | 
| 3032 |     qputenv(varName: "PATH" , | 
| 3033 |             value: pathEnv + QDir::listSeparator().toLatin1() | 
| 3034 |                     + QCoreApplication::applicationDirPath().toLocal8Bit()); | 
| 3035 |     auto restore = qScopeGuard(f: [&] { qputenv(varName: "PATH" , value: pathEnv); }); | 
| 3036 |  | 
| 3037 |     // signalbug helper app should always be next to this test binary | 
| 3038 |     const QString path = QStringLiteral("signalbug_helper" ); | 
| 3039 |     proc.start(command: path); | 
| 3040 |     QVERIFY2(proc.waitForStarted(), qPrintable(QString::fromLatin1("Cannot start '%1': %2" ).arg(path, proc.errorString()))); | 
| 3041 |     QVERIFY(proc.waitForFinished()); | 
| 3042 |     QCOMPARE(proc.exitStatus(), QProcess::NormalExit); | 
| 3043 |     QCOMPARE(proc.exitCode(), 0); | 
| 3044 | #endif | 
| 3045 | } | 
| 3046 |  | 
| 3047 | void tst_QObject::signalBlocking() | 
| 3048 | { | 
| 3049 |     SenderObject sender; | 
| 3050 |     ReceiverObject receiver; | 
| 3051 |  | 
| 3052 |     receiver.connect(asender: &sender, SIGNAL(signal1()), SLOT(slot1())); | 
| 3053 |  | 
| 3054 |     sender.emitSignal1(); | 
| 3055 |     QVERIFY(receiver.called(1)); | 
| 3056 |     receiver.reset(); | 
| 3057 |  | 
| 3058 |     sender.blockSignals(b: true); | 
| 3059 |  | 
| 3060 |     sender.emitSignal1(); | 
| 3061 |     QVERIFY(!receiver.called(1)); | 
| 3062 |     receiver.reset(); | 
| 3063 |  | 
| 3064 |     sender.blockSignals(b: false); | 
| 3065 |  | 
| 3066 |     sender.emitSignal1(); | 
| 3067 |     QVERIFY(receiver.called(1)); | 
| 3068 |     receiver.reset(); | 
| 3069 | } | 
| 3070 |  | 
| 3071 | void tst_QObject::blockingQueuedConnection() | 
| 3072 | { | 
| 3073 |     { | 
| 3074 |         SenderObject sender; | 
| 3075 |  | 
| 3076 |         MoveToThreadThread thread; | 
| 3077 |         ReceiverObject receiver; | 
| 3078 |         receiver.moveToThread(thread: &thread); | 
| 3079 |         thread.start(); | 
| 3080 |  | 
| 3081 |         receiver.connect(asender: &sender, SIGNAL(signal1()), SLOT(slot1()), atype: Qt::BlockingQueuedConnection); | 
| 3082 |         sender.emitSignal1(); | 
| 3083 |         QVERIFY(receiver.called(1)); | 
| 3084 |  | 
| 3085 |         receiver.reset(); | 
| 3086 |         QVERIFY(QMetaObject::invokeMethod(&receiver, "slot1" , Qt::BlockingQueuedConnection)); | 
| 3087 |         QVERIFY(receiver.called(1)); | 
| 3088 |  | 
| 3089 |         connect(sender: &sender, signal: &SenderObject::signal2, receiver: &receiver, slot: &ReceiverObject::slot2, type: Qt::BlockingQueuedConnection); | 
| 3090 |         sender.emitSignal2(); | 
| 3091 |         QVERIFY(receiver.called(2)); | 
| 3092 |  | 
| 3093 |         thread.quit(); | 
| 3094 |         QVERIFY(thread.wait()); | 
| 3095 |     } | 
| 3096 | } | 
| 3097 |  | 
| 3098 | class EventSpy : public QObject | 
| 3099 | { | 
| 3100 |     Q_OBJECT | 
| 3101 |  | 
| 3102 | public: | 
| 3103 |     typedef QList<QPair<QObject *, QEvent::Type> > EventList; | 
| 3104 |  | 
| 3105 |     EventSpy(QObject *parent = 0) | 
| 3106 |         : QObject(parent) | 
| 3107 |     { } | 
| 3108 |  | 
| 3109 |     EventList eventList() | 
| 3110 |     { | 
| 3111 |         return events; | 
| 3112 |     } | 
| 3113 |  | 
| 3114 |     void clear() | 
| 3115 |     { | 
| 3116 |         events.clear(); | 
| 3117 |     } | 
| 3118 |  | 
| 3119 |     bool eventFilter(QObject *object, QEvent *event) | 
| 3120 |     { | 
| 3121 |         events.append(t: qMakePair(x: object, y: event->type())); | 
| 3122 |         return false; | 
| 3123 |     } | 
| 3124 |  | 
| 3125 | private: | 
| 3126 |     EventList events; | 
| 3127 | }; | 
| 3128 |  | 
| 3129 | void tst_QObject::childEvents() | 
| 3130 | { | 
| 3131 |     EventSpy::EventList expected; | 
| 3132 |  | 
| 3133 |     { | 
| 3134 |         // no children created, so we expect no events | 
| 3135 |         QObject object; | 
| 3136 |         EventSpy spy; | 
| 3137 |         object.installEventFilter(filterObj: &spy); | 
| 3138 |  | 
| 3139 |         QCoreApplication::postEvent(receiver: &object, event: new QEvent(QEvent::Type(QEvent::User + 1))); | 
| 3140 |  | 
| 3141 |         QCoreApplication::processEvents(); | 
| 3142 |  | 
| 3143 |         expected = | 
| 3144 |             EventSpy::EventList() | 
| 3145 |             << qMakePair(x: &object, y: QEvent::Type(QEvent::User + 1)); | 
| 3146 |         QCOMPARE(spy.eventList(), expected); | 
| 3147 |     } | 
| 3148 |  | 
| 3149 |     { | 
| 3150 |         // 2 children, so we expect 2 ChildAdded events | 
| 3151 |         QObject object; | 
| 3152 |         EventSpy spy; | 
| 3153 |         object.installEventFilter(filterObj: &spy); | 
| 3154 |  | 
| 3155 |         QCoreApplication::postEvent(receiver: &object, event: new QEvent(QEvent::Type(QEvent::User + 1))); | 
| 3156 |  | 
| 3157 |         QObject child1(&object); | 
| 3158 |         QObject child2; | 
| 3159 |         child2.setParent(&object); | 
| 3160 |  | 
| 3161 |         QCoreApplication::postEvent(receiver: &object, event: new QEvent(QEvent::Type(QEvent::User + 2))); | 
| 3162 |  | 
| 3163 |         expected = | 
| 3164 |             EventSpy::EventList() | 
| 3165 |             << qMakePair(x: &object, y: QEvent::ChildAdded) | 
| 3166 |             << qMakePair(x: &object, y: QEvent::ChildAdded); | 
| 3167 |         QCOMPARE(spy.eventList(), expected); | 
| 3168 |         spy.clear(); | 
| 3169 |  | 
| 3170 |         QCoreApplication::processEvents(); | 
| 3171 |  | 
| 3172 |         expected = | 
| 3173 |             EventSpy::EventList() | 
| 3174 |             << qMakePair(x: &object, y: QEvent::Type(QEvent::User + 1)) | 
| 3175 |             << qMakePair(x: &object, y: QEvent::Type(QEvent::User + 2)); | 
| 3176 |         QCOMPARE(spy.eventList(), expected); | 
| 3177 |     } | 
| 3178 |  | 
| 3179 |     { | 
| 3180 |         // 2 children, but one is reparented away, so we expect: | 
| 3181 |         // 2 ChildAdded, 1 ChildRemoved | 
| 3182 |         QObject object; | 
| 3183 |         EventSpy spy; | 
| 3184 |         object.installEventFilter(filterObj: &spy); | 
| 3185 |  | 
| 3186 |         QCoreApplication::postEvent(receiver: &object, event: new QEvent(QEvent::Type(QEvent::User + 1))); | 
| 3187 |  | 
| 3188 |         QObject child1(&object); | 
| 3189 |         QObject child2; | 
| 3190 |         child2.setParent(&object); | 
| 3191 |         child2.setParent(0); | 
| 3192 |  | 
| 3193 |         QCoreApplication::postEvent(receiver: &object, event: new QEvent(QEvent::Type(QEvent::User + 2))); | 
| 3194 |  | 
| 3195 |         expected = | 
| 3196 |             EventSpy::EventList() | 
| 3197 |             << qMakePair(x: &object, y: QEvent::ChildAdded) | 
| 3198 |             << qMakePair(x: &object, y: QEvent::ChildAdded) | 
| 3199 |             << qMakePair(x: &object, y: QEvent::ChildRemoved); | 
| 3200 |         QCOMPARE(spy.eventList(), expected); | 
| 3201 |         spy.clear(); | 
| 3202 |  | 
| 3203 |         QCoreApplication::processEvents(); | 
| 3204 |  | 
| 3205 |         expected = | 
| 3206 |             EventSpy::EventList() | 
| 3207 |             << qMakePair(x: &object, y: QEvent::Type(QEvent::User + 1)) | 
| 3208 |             << qMakePair(x: &object, y: QEvent::Type(QEvent::User + 2)); | 
| 3209 |         QCOMPARE(spy.eventList(), expected); | 
| 3210 |     } | 
| 3211 | } | 
| 3212 |  | 
| 3213 | void tst_QObject::installEventFilter() | 
| 3214 | { | 
| 3215 |     QEvent event(QEvent::User); | 
| 3216 |     EventSpy::EventList expected; | 
| 3217 |  | 
| 3218 |     QObject object; | 
| 3219 |     EventSpy spy; | 
| 3220 |     object.installEventFilter(filterObj: &spy); | 
| 3221 |  | 
| 3222 |     // nothing special, should just work | 
| 3223 |     QCoreApplication::sendEvent(receiver: &object, event: &event); | 
| 3224 |     expected = | 
| 3225 |         EventSpy::EventList() | 
| 3226 |         << qMakePair(x: &object, y: QEvent::User); | 
| 3227 |     QCOMPARE(spy.eventList(), expected); | 
| 3228 |     spy.clear(); | 
| 3229 |  | 
| 3230 |     // moving the filter causes QCoreApplication to skip the filter | 
| 3231 |     spy.moveToThread(thread: 0); | 
| 3232 |     QTest::ignoreMessage(type: QtWarningMsg, message: "QCoreApplication: Object event filter cannot be in a different thread." ); | 
| 3233 |     QCoreApplication::sendEvent(receiver: &object, event: &event); | 
| 3234 |     QVERIFY(spy.eventList().isEmpty()); | 
| 3235 |  | 
| 3236 |     // move it back, and the filter works again | 
| 3237 |     spy.moveToThread(thread: object.thread()); | 
| 3238 |     QCoreApplication::sendEvent(receiver: &object, event: &event); | 
| 3239 |     expected = | 
| 3240 |         EventSpy::EventList() | 
| 3241 |         << qMakePair(x: &object, y: QEvent::User); | 
| 3242 |     QCOMPARE(spy.eventList(), expected); | 
| 3243 |     spy.clear(); | 
| 3244 |  | 
| 3245 |     // cannot install an event filter that lives in a different thread | 
| 3246 |     object.removeEventFilter(obj: &spy); | 
| 3247 |     spy.moveToThread(thread: 0); | 
| 3248 |     QTest::ignoreMessage(type: QtWarningMsg, message: "QObject::installEventFilter(): Cannot filter events for objects in a different thread." ); | 
| 3249 |     object.installEventFilter(filterObj: &spy); | 
| 3250 |     QCoreApplication::sendEvent(receiver: &object, event: &event); | 
| 3251 |     QVERIFY(spy.eventList().isEmpty()); | 
| 3252 | } | 
| 3253 |  | 
| 3254 | class EmitThread : public QThread | 
| 3255 | {   Q_OBJECT | 
| 3256 | public: | 
| 3257 |     void run(void) { | 
| 3258 |         emit work(); | 
| 3259 |     } | 
| 3260 | signals: | 
| 3261 |     void work(); | 
| 3262 | }; | 
| 3263 |  | 
| 3264 | namespace QObjectTest { // Do not clash with WinAPI 'DeleteObject' | 
| 3265 | class DeleteObject : public QObject | 
| 3266 | { | 
| 3267 |     Q_OBJECT | 
| 3268 |  | 
| 3269 | public slots: | 
| 3270 |     void deleteSelf() | 
| 3271 |     { | 
| 3272 |         delete this; | 
| 3273 |     } | 
| 3274 |  | 
| 3275 |     void relaySignalAndProcessEvents() | 
| 3276 |     { | 
| 3277 |         emit relayedSignal(); | 
| 3278 |         QCoreApplication::processEvents(); | 
| 3279 |     } | 
| 3280 |  | 
| 3281 | signals: | 
| 3282 |     void relayedSignal(); | 
| 3283 | }; | 
| 3284 | } // namespace QObjectTest | 
| 3285 |  | 
| 3286 | void tst_QObject::deleteSelfInSlot() | 
| 3287 | { | 
| 3288 |     { | 
| 3289 |         SenderObject sender; | 
| 3290 |         QObjectTest::DeleteObject *receiver = new QObjectTest::DeleteObject(); | 
| 3291 |         receiver->connect(asender: &sender, | 
| 3292 |                           SIGNAL(signal1()), | 
| 3293 |                           SLOT(deleteSelf()), | 
| 3294 |                           atype: Qt::BlockingQueuedConnection); | 
| 3295 |  | 
| 3296 |         QThread thread; | 
| 3297 |         receiver->moveToThread(thread: &thread); | 
| 3298 |         thread.connect(asender: receiver, SIGNAL(destroyed()), SLOT(quit()), atype: Qt::DirectConnection); | 
| 3299 |         thread.start(); | 
| 3300 |  | 
| 3301 |         QPointer<QObjectTest::DeleteObject> p = receiver; | 
| 3302 |         sender.emitSignal1(); | 
| 3303 |         QVERIFY(p.isNull()); | 
| 3304 |  | 
| 3305 |         QVERIFY(thread.wait(10000)); | 
| 3306 |     } | 
| 3307 |  | 
| 3308 |     { | 
| 3309 |         SenderObject sender; | 
| 3310 |         QObjectTest::DeleteObject *receiver = new QObjectTest::DeleteObject(); | 
| 3311 |         receiver->connect(asender: &sender, | 
| 3312 |                           SIGNAL(signal1()), | 
| 3313 |                           SLOT(relaySignalAndProcessEvents()), | 
| 3314 |                           atype: Qt::BlockingQueuedConnection); | 
| 3315 |         receiver->connect(asender: receiver, | 
| 3316 |                           SIGNAL(relayedSignal()), | 
| 3317 |                           SLOT(deleteSelf()), | 
| 3318 |                           atype: Qt::QueuedConnection); | 
| 3319 |  | 
| 3320 |         QThread thread; | 
| 3321 |         receiver->moveToThread(thread: &thread); | 
| 3322 |         thread.connect(asender: receiver, SIGNAL(destroyed()), SLOT(quit()), atype: Qt::DirectConnection); | 
| 3323 |         thread.start(); | 
| 3324 |  | 
| 3325 |         QPointer<QObjectTest::DeleteObject> p = receiver; | 
| 3326 |         sender.emitSignal1(); | 
| 3327 |         QVERIFY(p.isNull()); | 
| 3328 |  | 
| 3329 |         QVERIFY(thread.wait(10000)); | 
| 3330 |     } | 
| 3331 |  | 
| 3332 |     { | 
| 3333 |         EmitThread sender; | 
| 3334 |         QObjectTest::DeleteObject *receiver = new QObjectTest::DeleteObject(); | 
| 3335 |         connect(sender: &sender, SIGNAL(work()), receiver, SLOT(deleteSelf()), Qt::DirectConnection); | 
| 3336 |         QPointer<QObjectTest::DeleteObject> p = receiver; | 
| 3337 |         sender.start(); | 
| 3338 |         QVERIFY(sender.wait(10000)); | 
| 3339 |         QVERIFY(p.isNull()); | 
| 3340 |     } | 
| 3341 | } | 
| 3342 |  | 
| 3343 | class DisconnectObject : public QObject | 
| 3344 | { | 
| 3345 |     Q_OBJECT | 
| 3346 |  | 
| 3347 | public slots: | 
| 3348 |     void disconnectSelf() | 
| 3349 |     { | 
| 3350 |         disconnect(sender: sender(), signal: 0, receiver: this, member: 0); | 
| 3351 |     } | 
| 3352 |  | 
| 3353 |     void relaySignalAndProcessEvents() | 
| 3354 |     { | 
| 3355 |         emit relayedSignal(); | 
| 3356 |         QCoreApplication::processEvents(); | 
| 3357 |     } | 
| 3358 |  | 
| 3359 | signals: | 
| 3360 |     void relayedSignal(); | 
| 3361 | }; | 
| 3362 |  | 
| 3363 | void tst_QObject::disconnectSelfInSlotAndDeleteAfterEmit() | 
| 3364 | { | 
| 3365 |     { | 
| 3366 |         SenderObject sender; | 
| 3367 |         DisconnectObject *receiver = new DisconnectObject(); | 
| 3368 |         receiver->connect(asender: &sender, SIGNAL(signal1()), SLOT(disconnectSelf())); | 
| 3369 |         sender.emitSignal1AfterRecursion(); | 
| 3370 |         delete receiver; | 
| 3371 |     } | 
| 3372 |  | 
| 3373 |     { | 
| 3374 |         SenderObject sender; | 
| 3375 |         DisconnectObject *receiver = new DisconnectObject(); | 
| 3376 |         receiver->connect(asender: &sender, | 
| 3377 |                           SIGNAL(signal1()), | 
| 3378 |                           SLOT(disconnectSelf()), | 
| 3379 |                           atype: Qt::BlockingQueuedConnection); | 
| 3380 |  | 
| 3381 |         QThread thread; | 
| 3382 |         receiver->moveToThread(thread: &thread); | 
| 3383 |         thread.connect(asender: receiver, SIGNAL(destroyed()), SLOT(quit()), atype: Qt::DirectConnection); | 
| 3384 |         thread.start(); | 
| 3385 |  | 
| 3386 |         QPointer<DisconnectObject> p = receiver; | 
| 3387 |         sender.emitSignal1(); | 
| 3388 |         QVERIFY(!p.isNull()); | 
| 3389 |  | 
| 3390 |         receiver->deleteLater(); | 
| 3391 |  | 
| 3392 |         QVERIFY(thread.wait(10000)); | 
| 3393 |         QVERIFY(p.isNull()); | 
| 3394 |     } | 
| 3395 |  | 
| 3396 |     { | 
| 3397 |         SenderObject sender; | 
| 3398 |         DisconnectObject *receiver = new DisconnectObject(); | 
| 3399 |         receiver->connect(asender: &sender, | 
| 3400 |                           SIGNAL(signal1()), | 
| 3401 |                           SLOT(relaySignalAndProcessEvents()), | 
| 3402 |                           atype: Qt::BlockingQueuedConnection); | 
| 3403 |         receiver->connect(asender: receiver, | 
| 3404 |                           SIGNAL(relayedSignal()), | 
| 3405 |                           SLOT(disconnectSelf()), | 
| 3406 |                           atype: Qt::QueuedConnection); | 
| 3407 |  | 
| 3408 |         QThread thread; | 
| 3409 |         receiver->moveToThread(thread: &thread); | 
| 3410 |         thread.connect(asender: receiver, SIGNAL(destroyed()), SLOT(quit()), atype: Qt::DirectConnection); | 
| 3411 |         thread.start(); | 
| 3412 |  | 
| 3413 |         QPointer<DisconnectObject> p = receiver; | 
| 3414 |         sender.emitSignal1(); | 
| 3415 |         QVERIFY(!p.isNull()); | 
| 3416 |  | 
| 3417 |         receiver->deleteLater(); | 
| 3418 |  | 
| 3419 |         QVERIFY(thread.wait(10000)); | 
| 3420 |         QVERIFY(p.isNull()); | 
| 3421 |     } | 
| 3422 | } | 
| 3423 |  | 
| 3424 | void tst_QObject::dumpObjectInfo() | 
| 3425 | { | 
| 3426 |     QObject a, b; | 
| 3427 |     QObject::connect(sender: &a, signal: &QObject::destroyed, receiver: &b, slot: &QObject::deleteLater); | 
| 3428 |     QTest::ignoreMessage(type: QtDebugMsg, message: "OBJECT QObject::unnamed" ); | 
| 3429 |     QTest::ignoreMessage(type: QtDebugMsg, message: "  SIGNALS OUT" ); | 
| 3430 |     QTest::ignoreMessage(type: QtDebugMsg, message: "        signal: destroyed(QObject*)" ); | 
| 3431 |     QTest::ignoreMessage(type: QtDebugMsg, message: "          <functor or function pointer>" ); | 
| 3432 |     QTest::ignoreMessage(type: QtDebugMsg, message: "  SIGNALS IN" ); | 
| 3433 |     QTest::ignoreMessage(type: QtDebugMsg, message: "        <None>" ); | 
| 3434 |     a.dumpObjectInfo(); // should not crash | 
| 3435 | } | 
| 3436 |  | 
| 3437 | class ConnectToSender : public QObject | 
| 3438 | { Q_OBJECT | 
| 3439 |     public slots: | 
| 3440 |         void uselessSlot() { count++; } | 
| 3441 |  | 
| 3442 |         void harmfullSlot() { | 
| 3443 |             //this used to crash | 
| 3444 |             connect(sender: sender(), SIGNAL(signal4()), receiver: this, SLOT(uselessSlot())); | 
| 3445 |             //play a little bit with the memory in order to really get a segfault. | 
| 3446 |             connect(sender: sender(), SIGNAL(signal1()), receiver: this, SLOT(uselessSlot())); | 
| 3447 |             QList<double>() << 45 << 78 << 65 << 121 << 45 << 78 << 12; | 
| 3448 |         } | 
| 3449 |     public: | 
| 3450 |         int count; | 
| 3451 | }; | 
| 3452 |  | 
| 3453 | void tst_QObject::connectToSender() | 
| 3454 | { | 
| 3455 |     SenderObject s; | 
| 3456 |     ConnectToSender r; | 
| 3457 |     r.count = 0; | 
| 3458 |     QObject::connect(sender: &s, SIGNAL(signal1()), receiver: &r, SLOT(harmfullSlot())); | 
| 3459 |     QObject::connect(sender: &s, SIGNAL(signal1()), receiver: &r, SLOT(uselessSlot())); | 
| 3460 |  | 
| 3461 |     s.emitSignal1(); | 
| 3462 |  | 
| 3463 |     QCOMPARE(r.count, 1); | 
| 3464 |     s.emitSignal4(); | 
| 3465 |     QCOMPARE(r.count, 2); | 
| 3466 | } | 
| 3467 |  | 
| 3468 | void tst_QObject::qobjectConstCast() | 
| 3469 | { | 
| 3470 |     FooObject obj; | 
| 3471 |  | 
| 3472 |     QObject *ptr = &obj; | 
| 3473 |     const QObject *cptr = &obj; | 
| 3474 |  | 
| 3475 |     QVERIFY(qobject_cast<FooObject *>(ptr)); | 
| 3476 |     QVERIFY(qobject_cast<const FooObject *>(cptr)); | 
| 3477 | } | 
| 3478 |  | 
| 3479 | void tst_QObject::uniqConnection() | 
| 3480 | { | 
| 3481 |     SenderObject s; | 
| 3482 |     ReceiverObject r1; | 
| 3483 |     ReceiverObject r2; | 
| 3484 |     r1.reset(); | 
| 3485 |     r2.reset(); | 
| 3486 |     ReceiverObject::sequence = 0; | 
| 3487 |  | 
| 3488 |     QVERIFY(connect(&s, SIGNAL(signal1()), &r1, SLOT(slot1()) , Qt::UniqueConnection) ); | 
| 3489 |     QVERIFY(connect(&s, SIGNAL(signal1()), &r2, SLOT(slot1()) , Qt::UniqueConnection) ); | 
| 3490 |     QVERIFY(connect(&s, SIGNAL(signal1()), &r1, SLOT(slot3()) , Qt::UniqueConnection) ); | 
| 3491 |     QVERIFY(connect(&s, SIGNAL(signal3()), &r1, SLOT(slot3()) , Qt::UniqueConnection) ); | 
| 3492 |  | 
| 3493 |     s.emitSignal1(); | 
| 3494 |     s.emitSignal2(); | 
| 3495 |     s.emitSignal3(); | 
| 3496 |     s.emitSignal4(); | 
| 3497 |  | 
| 3498 |     QCOMPARE(r1.count_slot1, 1); | 
| 3499 |     QCOMPARE(r1.count_slot2, 0); | 
| 3500 |     QCOMPARE(r1.count_slot3, 2); | 
| 3501 |     QCOMPARE(r1.count_slot4, 0); | 
| 3502 |     QCOMPARE(r2.count_slot1, 1); | 
| 3503 |     QCOMPARE(r2.count_slot2, 0); | 
| 3504 |     QCOMPARE(r2.count_slot3, 0); | 
| 3505 |     QCOMPARE(r2.count_slot4, 0); | 
| 3506 |     QCOMPARE(r1.sequence_slot1, 1); | 
| 3507 |     QCOMPARE(r2.sequence_slot1, 2); | 
| 3508 |     QCOMPARE(r1.sequence_slot3, 4); | 
| 3509 |  | 
| 3510 |     r1.reset(); | 
| 3511 |     r2.reset(); | 
| 3512 |     ReceiverObject::sequence = 0; | 
| 3513 |  | 
| 3514 |     QVERIFY( connect(&s, SIGNAL(signal4()), &r1, SLOT(slot4()) , Qt::UniqueConnection)); | 
| 3515 |     QVERIFY( connect(&s, SIGNAL(signal4()), &r2, SLOT(slot4()) , Qt::UniqueConnection)); | 
| 3516 |     QVERIFY(!connect(&s, SIGNAL(signal4()), &r2, SLOT(slot4()) , Qt::UniqueConnection)); | 
| 3517 |     QVERIFY( connect(&s, SIGNAL(signal1()), &r2, SLOT(slot4()) , Qt::UniqueConnection)); | 
| 3518 |     QVERIFY(!connect(&s, SIGNAL(signal4()), &r1, SLOT(slot4()) , Qt::UniqueConnection)); | 
| 3519 |  | 
| 3520 |     s.emitSignal4(); | 
| 3521 |     QCOMPARE(r1.count_slot4, 1); | 
| 3522 |     QCOMPARE(r2.count_slot4, 1); | 
| 3523 |     QCOMPARE(r1.sequence_slot4, 1); | 
| 3524 |     QCOMPARE(r2.sequence_slot4, 2); | 
| 3525 |  | 
| 3526 |     r1.reset(); | 
| 3527 |     r2.reset(); | 
| 3528 |     ReceiverObject::sequence = 0; | 
| 3529 |  | 
| 3530 |     connect(sender: &s, SIGNAL(signal4()), receiver: &r1, SLOT(slot4())); | 
| 3531 |  | 
| 3532 |     s.emitSignal4(); | 
| 3533 |     QCOMPARE(r1.count_slot4, 2); | 
| 3534 |     QCOMPARE(r2.count_slot4, 1); | 
| 3535 |     QCOMPARE(r1.sequence_slot4, 3); | 
| 3536 |     QCOMPARE(r2.sequence_slot4, 2); | 
| 3537 | } | 
| 3538 |  | 
| 3539 | void tst_QObject::uniqConnectionPtr() | 
| 3540 | { | 
| 3541 |     SenderObject s; | 
| 3542 |     ReceiverObject r1; | 
| 3543 |     ReceiverObject r2; | 
| 3544 |     r1.reset(); | 
| 3545 |     r2.reset(); | 
| 3546 |     ReceiverObject::sequence = 0; | 
| 3547 |  | 
| 3548 |     QVERIFY(connect(&s, &SenderObject::signal1, &r1, &ReceiverObject::slot1 , | 
| 3549 |                     Qt::UniqueConnection)); | 
| 3550 |     QVERIFY(connect(&s, &SenderObject::signal1, &r2, &ReceiverObject::slot1 , | 
| 3551 |                     Qt::UniqueConnection)); | 
| 3552 |     QVERIFY(connect(&s, &SenderObject::signal1, &r1, &ReceiverObject::slot3 , | 
| 3553 |                     Qt::UniqueConnection)); | 
| 3554 |     QVERIFY(connect(&s, &SenderObject::signal3, &r1, &ReceiverObject::slot3 , | 
| 3555 |                     Qt::UniqueConnection)); | 
| 3556 |  | 
| 3557 |     s.emitSignal1(); | 
| 3558 |     s.emitSignal2(); | 
| 3559 |     s.emitSignal3(); | 
| 3560 |     s.emitSignal4(); | 
| 3561 |  | 
| 3562 |     QCOMPARE(r1.count_slot1, 1); | 
| 3563 |     QCOMPARE(r1.count_slot2, 0); | 
| 3564 |     QCOMPARE(r1.count_slot3, 2); | 
| 3565 |     QCOMPARE(r1.count_slot4, 0); | 
| 3566 |     QCOMPARE(r2.count_slot1, 1); | 
| 3567 |     QCOMPARE(r2.count_slot2, 0); | 
| 3568 |     QCOMPARE(r2.count_slot3, 0); | 
| 3569 |     QCOMPARE(r2.count_slot4, 0); | 
| 3570 |     QCOMPARE(r1.sequence_slot1, 1); | 
| 3571 |     QCOMPARE(r2.sequence_slot1, 2); | 
| 3572 |     QCOMPARE(r1.sequence_slot3, 4); | 
| 3573 |  | 
| 3574 |     r1.reset(); | 
| 3575 |     r2.reset(); | 
| 3576 |     ReceiverObject::sequence = 0; | 
| 3577 |  | 
| 3578 |     QVERIFY( connect(&s, &SenderObject::signal4, &r1, &ReceiverObject::slot4 , | 
| 3579 |                      Qt::UniqueConnection)); | 
| 3580 |     QVERIFY( connect(&s, &SenderObject::signal4, &r2, &ReceiverObject::slot4 , | 
| 3581 |                      Qt::UniqueConnection)); | 
| 3582 |     QVERIFY(!connect(&s, &SenderObject::signal4, &r2, &ReceiverObject::slot4 , | 
| 3583 |                      Qt::UniqueConnection)); | 
| 3584 |     QVERIFY( connect(&s, &SenderObject::signal1, &r2, &ReceiverObject::slot4 , | 
| 3585 |                      Qt::UniqueConnection)); | 
| 3586 |     QVERIFY(!connect(&s, &SenderObject::signal4, &r1, &ReceiverObject::slot4 , | 
| 3587 |                      Qt::UniqueConnection)); | 
| 3588 |  | 
| 3589 |     s.emitSignal4(); | 
| 3590 |     QCOMPARE(r1.count_slot4, 1); | 
| 3591 |     QCOMPARE(r2.count_slot4, 1); | 
| 3592 |     QCOMPARE(r1.sequence_slot4, 1); | 
| 3593 |     QCOMPARE(r2.sequence_slot4, 2); | 
| 3594 |  | 
| 3595 |     r1.reset(); | 
| 3596 |     r2.reset(); | 
| 3597 |     ReceiverObject::sequence = 0; | 
| 3598 |  | 
| 3599 |     connect(sender: &s, signal: &SenderObject::signal4, receiver: &r1, slot: &ReceiverObject::slot4); | 
| 3600 |  | 
| 3601 |     s.emitSignal4(); | 
| 3602 |     QCOMPARE(r1.count_slot4, 2); | 
| 3603 |     QCOMPARE(r2.count_slot4, 1); | 
| 3604 |     QCOMPARE(r1.sequence_slot4, 3); | 
| 3605 |     QCOMPARE(r2.sequence_slot4, 2); | 
| 3606 | } | 
| 3607 |  | 
| 3608 | void tst_QObject::interfaceIid() | 
| 3609 | { | 
| 3610 |     QCOMPARE(QByteArray(qobject_interface_iid<Foo::Bleh *>()), | 
| 3611 |              QByteArray(Bleh_iid)); | 
| 3612 |     QCOMPARE(QByteArray(qobject_interface_iid<Foo::Bar *>()), | 
| 3613 |              QByteArray("com.qtest.foobar" )); | 
| 3614 |     QCOMPARE(QByteArray(qobject_interface_iid<FooObject *>()), | 
| 3615 |              QByteArray()); | 
| 3616 | } | 
| 3617 |  | 
| 3618 | void tst_QObject::deleteQObjectWhenDeletingEvent() | 
| 3619 | { | 
| 3620 |     // This is a regression test for an old bug that used to deadlock | 
| 3621 |     // when the QObject from the event was destroyed. | 
| 3622 |  | 
| 3623 |     struct MyEvent : public QEvent | 
| 3624 |     { | 
| 3625 |         MyEvent() : QEvent(QEvent::User) { } | 
| 3626 |         QObject obj; | 
| 3627 |     }; | 
| 3628 |  | 
| 3629 |     QObject o; | 
| 3630 |     QCoreApplication::postEvent(receiver: &o, event: new MyEvent); | 
| 3631 |     QCoreApplication::removePostedEvents(receiver: &o); // here you would get a deadlock | 
| 3632 | } | 
| 3633 |  | 
| 3634 | class OverloadObject : public QObject | 
| 3635 | { | 
| 3636 |     friend class tst_QObject; | 
| 3637 |     Q_OBJECT | 
| 3638 |     signals: | 
| 3639 |         void sig(int i, char c, qreal m = 12); | 
| 3640 |         void sig(int i, int j = 12); | 
| 3641 |         void sig(QObject *o, QObject *p, QObject *q = 0, QObject *r = 0) const; | 
| 3642 |         void other(int a = 0); | 
| 3643 |         void sig(QObject *o, OverloadObject *p = 0, QObject *q = 0, QObject *r = nullptr); | 
| 3644 |         void sig(double r = 0.5); | 
| 3645 |     public slots: | 
| 3646 |         void slo(int i, int j = 43) | 
| 3647 |         { | 
| 3648 |             s_num += 1; | 
| 3649 |             i1_num = i; | 
| 3650 |             i2_num = j; | 
| 3651 |         } | 
| 3652 |         void slo(QObject *o, QObject *p = qApp, QObject *q = qApp, QObject *r = qApp) | 
| 3653 |         { | 
| 3654 |             s_num += 10; | 
| 3655 |             o1_obj = o; | 
| 3656 |             o2_obj = p; | 
| 3657 |             o3_obj = q; | 
| 3658 |             o4_obj = r; | 
| 3659 |         } | 
| 3660 |         void slo() | 
| 3661 |         { | 
| 3662 |             s_num += 100; | 
| 3663 |         } | 
| 3664 |  | 
| 3665 |     public: | 
| 3666 |         int s_num; | 
| 3667 |         int i1_num; | 
| 3668 |         int i2_num; | 
| 3669 |         QObject *o1_obj; | 
| 3670 |         QObject *o2_obj; | 
| 3671 |         QObject *o3_obj; | 
| 3672 |         QObject *o4_obj; | 
| 3673 | }; | 
| 3674 |  | 
| 3675 | void tst_QObject::overloads() | 
| 3676 | { | 
| 3677 |     OverloadObject obj1; | 
| 3678 |     OverloadObject obj2; | 
| 3679 |     QObject obj3; | 
| 3680 |     obj1.s_num = 0; | 
| 3681 |     obj2.s_num = 0; | 
| 3682 |  | 
| 3683 |     connect (sender: &obj1, SIGNAL(sig(int)) , receiver: &obj1, SLOT(slo(int))); | 
| 3684 |     connect (sender: &obj1, SIGNAL(sig(QObject*,QObject*,QObject*)) , receiver: &obj1, SLOT(slo(QObject*,QObject*,QObject*))); | 
| 3685 |  | 
| 3686 |     connect (sender: &obj1, SIGNAL(sig(QObject*,QObject*,QObject*,QObject*)) , receiver: &obj2, SLOT(slo(QObject*,QObject*,QObject*))); | 
| 3687 |     connect (sender: &obj1, SIGNAL(sig(QObject*)) , receiver: &obj2, SLOT(slo())); | 
| 3688 |     connect (sender: &obj1, SIGNAL(sig(int,int)) , receiver: &obj2, SLOT(slo(int,int))); | 
| 3689 |  | 
| 3690 |     emit obj1.sig(r: 0.5); //connected to nothing | 
| 3691 |     emit obj1.sig(i: 1, c: 'a'); //connected to nothing | 
| 3692 |     QCOMPARE(obj1.s_num, 0); | 
| 3693 |     QCOMPARE(obj2.s_num, 0); | 
| 3694 |  | 
| 3695 |     emit obj1.sig(i: 1); //this signal is connected | 
| 3696 |     QCOMPARE(obj1.s_num, 1); | 
| 3697 |     QCOMPARE(obj1.i1_num, 1); | 
| 3698 |     QCOMPARE(obj1.i2_num, 43); //default argument of the slot | 
| 3699 |  | 
| 3700 |     QCOMPARE(obj2.s_num, 1); | 
| 3701 |     QCOMPARE(obj2.i1_num, 1); | 
| 3702 |     QCOMPARE(obj2.i2_num, 12); //default argument of the signal | 
| 3703 |  | 
| 3704 |  | 
| 3705 |     emit obj1.sig(o: &obj2); //this signal is conencted to obj2 | 
| 3706 |     QCOMPARE(obj1.s_num, 1); | 
| 3707 |     QCOMPARE(obj2.s_num, 101); | 
| 3708 |     emit obj1.sig(o: &obj2, p: &obj3); //this signal is connected | 
| 3709 |     QCOMPARE(obj1.s_num, 11); | 
| 3710 |     QCOMPARE(obj1.o1_obj, (QObject *)&obj2); | 
| 3711 |     QCOMPARE(obj1.o2_obj, &obj3); | 
| 3712 |     QCOMPARE(obj1.o3_obj, (QObject *)0); //default arg of the signal | 
| 3713 |     QCOMPARE(obj1.o4_obj, (QObject *)qApp); //default arg of the slot | 
| 3714 |  | 
| 3715 |     QCOMPARE(obj2.s_num, 111); | 
| 3716 |     QCOMPARE(obj2.o1_obj, (QObject *)&obj2); | 
| 3717 |     QCOMPARE(obj2.o2_obj, &obj3); | 
| 3718 |     QCOMPARE(obj2.o3_obj, (QObject *)0); //default arg of the signal | 
| 3719 |     QCOMPARE(obj2.o4_obj, (QObject *)qApp); //default arg of the slot | 
| 3720 | } | 
| 3721 |  | 
| 3722 | class ManySignals : public QObject | 
| 3723 | {   Q_OBJECT | 
| 3724 |     friend class tst_QObject; | 
| 3725 | signals: | 
| 3726 |     void sig00(); void sig01(); void sig02(); void sig03(); void sig04(); | 
| 3727 |     void sig05(); void sig06(); void sig07(); void sig08(); void sig09(); | 
| 3728 |     void sig10(); void sig11(); void sig12(); void sig13(); void sig14(); | 
| 3729 |     void sig15(); void sig16(); void sig17(); void sig18(); void sig19(); | 
| 3730 |     void sig20(); void sig21(); void sig22(); void sig23(); void sig24(); | 
| 3731 |     void sig25(); void sig26(); void sig27(); void sig28(); void sig29(); | 
| 3732 |     void sig30(); void sig31(); void sig32(); void sig33(); void sig34(); | 
| 3733 |     void sig35(); void sig36(); void sig37(); void sig38(); void sig39(); | 
| 3734 |     void sig40(); void sig41(); void sig42(); void sig43(); void sig44(); | 
| 3735 |     void sig45(); void sig46(); void sig47(); void sig48(); void sig49(); | 
| 3736 |     void sig50(); void sig51(); void sig52(); void sig53(); void sig54(); | 
| 3737 |     void sig55(); void sig56(); void sig57(); void sig58(); void sig59(); | 
| 3738 |     void sig60(); void sig61(); void sig62(); void sig63(); void sig64(); | 
| 3739 |     void sig65(); void sig66(); void sig67(); void sig68(); void sig69(); | 
| 3740 |  | 
| 3741 | public slots: | 
| 3742 |     void received() { rec++; } | 
| 3743 | public: | 
| 3744 |     int rec; | 
| 3745 | }; | 
| 3746 |  | 
| 3747 |  | 
| 3748 | void tst_QObject::isSignalConnected() | 
| 3749 | { | 
| 3750 |     ManySignals o; | 
| 3751 |     const QMetaObject *meta = o.metaObject(); | 
| 3752 |     o.rec = 0; | 
| 3753 | #ifdef QT_BUILD_INTERNAL | 
| 3754 |     QObjectPrivate *priv = QObjectPrivate::get(o: &o); | 
| 3755 |     QVERIFY(!priv->isSignalConnected(priv->signalIndex("destroyed()" ))); | 
| 3756 |     QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig00()" ))); | 
| 3757 |     QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig05()" ))); | 
| 3758 |     QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig15()" ))); | 
| 3759 |     QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig29()" ))); | 
| 3760 |     QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig60()" ))); | 
| 3761 | #endif | 
| 3762 |     QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("destroyed()" )))); | 
| 3763 |     QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig00()" )))); | 
| 3764 |     QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig05()" )))); | 
| 3765 |     QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig15()" )))); | 
| 3766 |     QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig29()" )))); | 
| 3767 |     QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig60()" )))); | 
| 3768 |     QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig69()" )))); | 
| 3769 |  | 
| 3770 |     QObject::connect(sender: &o, SIGNAL(sig00()), receiver: &o, SIGNAL(sig69())); | 
| 3771 |     QObject::connect(sender: &o, SIGNAL(sig34()), receiver: &o, SIGNAL(sig03())); | 
| 3772 |     QObject::connect(sender: &o, SIGNAL(sig69()), receiver: &o, SIGNAL(sig34())); | 
| 3773 |     QObject::connect(sender: &o, SIGNAL(sig03()), receiver: &o, SIGNAL(sig18())); | 
| 3774 |  | 
| 3775 | #ifdef QT_BUILD_INTERNAL | 
| 3776 |     QVERIFY(!priv->isSignalConnected(priv->signalIndex("destroyed()" ))); | 
| 3777 |     QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig05()" ))); | 
| 3778 |     QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig15()" ))); | 
| 3779 |     QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig29()" ))); | 
| 3780 |  | 
| 3781 |     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig00()" ))); | 
| 3782 |     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig03()" ))); | 
| 3783 |     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig34()" ))); | 
| 3784 |     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig69()" ))); | 
| 3785 |     QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig18()" ))); | 
| 3786 | #endif | 
| 3787 |     QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("destroyed()" )))); | 
| 3788 |     QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("destroyed(QObject*)" )))); | 
| 3789 |     QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig05()" )))); | 
| 3790 |     QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig15()" )))); | 
| 3791 |     QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig29()" )))); | 
| 3792 |  | 
| 3793 |     QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig00()" )))); | 
| 3794 |     QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig03()" )))); | 
| 3795 |     QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig34()" )))); | 
| 3796 |     QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig69()" )))); | 
| 3797 |     QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig18()" )))); | 
| 3798 |  | 
| 3799 |  | 
| 3800 |     QObject::connect(sender: &o, SIGNAL(sig18()), receiver: &o, SIGNAL(sig29())); | 
| 3801 |     QObject::connect(sender: &o, SIGNAL(sig29()), receiver: &o, SIGNAL(sig62())); | 
| 3802 |     QObject::connect(sender: &o, SIGNAL(sig62()), receiver: &o, SIGNAL(sig28())); | 
| 3803 |     QObject::connect(sender: &o, SIGNAL(sig28()), receiver: &o, SIGNAL(sig27())); | 
| 3804 |  | 
| 3805 | #ifdef QT_BUILD_INTERNAL | 
| 3806 |     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig18()" ))); | 
| 3807 |     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig62()" ))); | 
| 3808 |     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig28()" ))); | 
| 3809 |     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig69()" ))); | 
| 3810 |     QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig27()" ))); | 
| 3811 | #endif | 
| 3812 |     QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig18()" )))); | 
| 3813 |     QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig62()" )))); | 
| 3814 |     QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig28()" )))); | 
| 3815 |     QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig69()" )))); | 
| 3816 |     QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig27()" )))); | 
| 3817 |  | 
| 3818 |     QCOMPARE(o.rec, 0); | 
| 3819 |     emit o.sig01(); | 
| 3820 |     emit o.sig34(); | 
| 3821 |     QCOMPARE(o.rec, 0); | 
| 3822 |  | 
| 3823 |     QObject::connect(sender: &o, SIGNAL(sig27()), receiver: &o, SLOT(received())); | 
| 3824 |  | 
| 3825 | #ifdef QT_BUILD_INTERNAL | 
| 3826 |     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig00()" ))); | 
| 3827 |     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig03()" ))); | 
| 3828 |     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig34()" ))); | 
| 3829 |     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig18()" ))); | 
| 3830 |     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig62()" ))); | 
| 3831 |     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig28()" ))); | 
| 3832 |     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig69()" ))); | 
| 3833 |     QVERIFY(priv->isSignalConnected(priv->signalIndex("sig27()" ))); | 
| 3834 |  | 
| 3835 |     QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig04()" ))); | 
| 3836 |     QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig21()" ))); | 
| 3837 |     QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig25()" ))); | 
| 3838 |     QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig55()" ))); | 
| 3839 | #endif | 
| 3840 |  | 
| 3841 |     emit o.sig00(); | 
| 3842 |     QCOMPARE(o.rec, 1); | 
| 3843 |     emit o.sig69(); | 
| 3844 |     QCOMPARE(o.rec, 2); | 
| 3845 |     emit o.sig36(); | 
| 3846 |     QCOMPARE(o.rec, 2); | 
| 3847 |  | 
| 3848 |     QObject::connect(sender: &o, signal: &QObject::destroyed, slot: qt_noop); | 
| 3849 |     QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("destroyed()" )))); | 
| 3850 |     QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("destroyed(QObject*)" )))); | 
| 3851 |  | 
| 3852 |     QVERIFY(!o.isSignalConnected(QMetaMethod())); | 
| 3853 | } | 
| 3854 |  | 
| 3855 | void tst_QObject::isSignalConnectedAfterDisconnection() | 
| 3856 | { | 
| 3857 |     ManySignals o; | 
| 3858 |     const QMetaObject *meta = o.metaObject(); | 
| 3859 |  | 
| 3860 |     const QMetaMethod sig00 = meta->method(index: meta->indexOfSignal(signal: "sig00()" )); | 
| 3861 |     QVERIFY(!o.isSignalConnected(sig00)); | 
| 3862 |     QObject::connect(sender: &o, signal: &ManySignals::sig00, slot: qt_noop); | 
| 3863 |     QVERIFY(o.isSignalConnected(sig00)); | 
| 3864 |     QVERIFY(QObject::disconnect(&o, &ManySignals::sig00, 0, 0)); | 
| 3865 |     QVERIFY(!o.isSignalConnected(sig00)); | 
| 3866 |  | 
| 3867 |     const QMetaMethod sig69 = meta->method(index: meta->indexOfSignal(signal: "sig69()" )); | 
| 3868 |     QVERIFY(!o.isSignalConnected(sig69)); | 
| 3869 |     QObject::connect(sender: &o, signal: &ManySignals::sig69, slot: qt_noop); | 
| 3870 |     QVERIFY(o.isSignalConnected(sig69)); | 
| 3871 |     QVERIFY(QObject::disconnect(&o, &ManySignals::sig69, 0, 0)); | 
| 3872 |     QVERIFY(!o.isSignalConnected(sig69)); | 
| 3873 |  | 
| 3874 |     { | 
| 3875 |         ManySignals o2; | 
| 3876 |         QObject::connect(sender: &o, signal: &ManySignals::sig00, receiver: &o2, slot: &ManySignals::sig00); | 
| 3877 |         QVERIFY(o.isSignalConnected(sig00)); | 
| 3878 |         // o2 is destructed | 
| 3879 |     } | 
| 3880 |     QVERIFY(!o.isSignalConnected(sig00)); | 
| 3881 |  | 
| 3882 |     const QMetaMethod sig01 = meta->method(index: meta->indexOfSignal(signal: "sig01()" )); | 
| 3883 |     QObject::connect(sender: &o, signal: &ManySignals::sig00, slot: qt_noop); | 
| 3884 |     QObject::connect(sender: &o, signal: &ManySignals::sig01, slot: qt_noop); | 
| 3885 |     QObject::connect(sender: &o, signal: &ManySignals::sig69, slot: qt_noop); | 
| 3886 |     QVERIFY(o.isSignalConnected(sig00)); | 
| 3887 |     QVERIFY(o.isSignalConnected(sig01)); | 
| 3888 |     QVERIFY(o.isSignalConnected(sig69)); | 
| 3889 |     QVERIFY(QObject::disconnect(&o, &ManySignals::sig69, 0, 0)); | 
| 3890 |     QVERIFY(o.isSignalConnected(sig00)); | 
| 3891 |     QVERIFY(o.isSignalConnected(sig01)); | 
| 3892 |     QVERIFY(!o.isSignalConnected(sig69)); | 
| 3893 |     QVERIFY(QObject::disconnect(&o, &ManySignals::sig00, 0, 0)); | 
| 3894 |     QVERIFY(!o.isSignalConnected(sig00)); | 
| 3895 |     QVERIFY(o.isSignalConnected(sig01)); | 
| 3896 |     QVERIFY(!o.isSignalConnected(sig69)); | 
| 3897 |     QObject::connect(sender: &o, signal: &ManySignals::sig69, slot: qt_noop); | 
| 3898 |     QVERIFY(!o.isSignalConnected(sig00)); | 
| 3899 |     QVERIFY(o.isSignalConnected(sig01)); | 
| 3900 |     QVERIFY(o.isSignalConnected(sig69)); | 
| 3901 |     QVERIFY(QObject::disconnect(&o, &ManySignals::sig01, 0, 0)); | 
| 3902 |     QVERIFY(!o.isSignalConnected(sig00)); | 
| 3903 |     QVERIFY(!o.isSignalConnected(sig01)); | 
| 3904 |     QVERIFY(o.isSignalConnected(sig69)); | 
| 3905 | } | 
| 3906 |  | 
| 3907 | void tst_QObject::qMetaObjectConnect() | 
| 3908 | { | 
| 3909 |     ReceiverObject r1; | 
| 3910 |     ReceiverObject r2; | 
| 3911 |     int slot1Index, slot2Index, slot3Index; | 
| 3912 |     { | 
| 3913 |         SenderObject s; | 
| 3914 |         r1.reset(); | 
| 3915 |         r2.reset(); | 
| 3916 |         ReceiverObject::sequence = 0; | 
| 3917 |  | 
| 3918 |         int signal1Index = s.metaObject()->indexOfSignal(signal: "signal1()" ); | 
| 3919 |         int signal3Index = s.metaObject()->indexOfSignal(signal: "signal3()" ); | 
| 3920 |         slot1Index = r1.metaObject()->indexOfSlot(slot: "slot1()" ); | 
| 3921 |         slot2Index = r1.metaObject()->indexOfSlot(slot: "slot2()" ); | 
| 3922 |         slot3Index = r1.metaObject()->indexOfSlot(slot: "slot3()" ); | 
| 3923 |  | 
| 3924 |         QVERIFY(slot1Index > 0); | 
| 3925 |         QVERIFY(slot2Index > 0); | 
| 3926 |         QVERIFY(slot3Index > 0); | 
| 3927 |  | 
| 3928 |         QVERIFY(QMetaObject::connect(&s, signal1Index, &r1, slot1Index)); | 
| 3929 |         QVERIFY(QMetaObject::connect(&s, signal3Index, &r2, slot3Index)); | 
| 3930 |         QVERIFY(QMetaObject::connect(&s, -1, &r2, slot2Index)); | 
| 3931 |  | 
| 3932 |         QCOMPARE(r1.count_slot1, 0); | 
| 3933 |         QCOMPARE(r1.count_slot2, 0); | 
| 3934 |         QCOMPARE(r1.count_slot3, 0); | 
| 3935 |         QCOMPARE(r2.count_slot1, 0); | 
| 3936 |         QCOMPARE(r2.count_slot2, 0); | 
| 3937 |         QCOMPARE(r2.count_slot3, 0); | 
| 3938 |  | 
| 3939 |         s.emitSignal1(); | 
| 3940 |  | 
| 3941 |         QCOMPARE(r1.count_slot1, 1); | 
| 3942 |         QCOMPARE(r1.count_slot2, 0); | 
| 3943 |         QCOMPARE(r1.count_slot3, 0); | 
| 3944 |         QCOMPARE(r2.count_slot1, 0); | 
| 3945 |         QCOMPARE(r2.count_slot2, 1); | 
| 3946 |         QCOMPARE(r2.count_slot3, 0); | 
| 3947 |  | 
| 3948 |         s.emitSignal2(); | 
| 3949 |         s.emitSignal3(); | 
| 3950 |         s.emitSignal4(); | 
| 3951 |  | 
| 3952 |         QCOMPARE(r1.count_slot1, 1); | 
| 3953 |         QCOMPARE(r1.count_slot2, 0); | 
| 3954 |         QCOMPARE(r1.count_slot3, 0); | 
| 3955 |         QCOMPARE(r2.count_slot1, 0); | 
| 3956 |         QCOMPARE(r2.count_slot2, 4); | 
| 3957 |         QCOMPARE(r2.count_slot3, 1); | 
| 3958 |  | 
| 3959 |         QVERIFY(QMetaObject::disconnect(&s, signal1Index, &r1, slot1Index)); | 
| 3960 |         QVERIFY(QMetaObject::disconnect(&s, signal3Index, &r2, slot3Index)); | 
| 3961 |         QVERIFY(QMetaObject::disconnect(&s, -1, &r2, slot2Index)); | 
| 3962 |  | 
| 3963 |         s.emitSignal1(); | 
| 3964 |         s.emitSignal2(); | 
| 3965 |         s.emitSignal3(); | 
| 3966 |         s.emitSignal4(); | 
| 3967 |  | 
| 3968 |         QCOMPARE(r1.count_slot1, 1); | 
| 3969 |         QCOMPARE(r1.count_slot2, 0); | 
| 3970 |         QCOMPARE(r1.count_slot3, 0); | 
| 3971 |         QCOMPARE(r2.count_slot1, 0); | 
| 3972 |         QCOMPARE(r2.count_slot2, 4); | 
| 3973 |         QCOMPARE(r2.count_slot3, 1); | 
| 3974 |  | 
| 3975 |         //some "dynamic" signal | 
| 3976 |         QVERIFY(QMetaObject::connect(&s, s.metaObject()->methodOffset() + 20, &r1, slot3Index)); | 
| 3977 |         QVERIFY(QMetaObject::connect(&s, s.metaObject()->methodOffset() + 35, &r2, slot1Index)); | 
| 3978 |         QVERIFY(QMetaObject::connect(&s, -1, &r1, slot2Index)); | 
| 3979 |  | 
| 3980 |         r1.reset(); | 
| 3981 |         r2.reset(); | 
| 3982 |  | 
| 3983 |         void *args[] = { 0 , 0 }; | 
| 3984 |         QMetaObject::activate(sender: &s, signal_index: s.metaObject()->methodOffset() + 20, argv: args); | 
| 3985 |         QMetaObject::activate(sender: &s, signal_index: s.metaObject()->methodOffset() + 48, argv: args); | 
| 3986 |         QCOMPARE(r1.count_slot1, 0); | 
| 3987 |         QCOMPARE(r1.count_slot2, 2); | 
| 3988 |         QCOMPARE(r1.count_slot3, 1); | 
| 3989 |         QCOMPARE(r2.count_slot1, 0); | 
| 3990 |         QCOMPARE(r2.count_slot2, 0); | 
| 3991 |         QCOMPARE(r2.count_slot3, 0); | 
| 3992 |  | 
| 3993 |         QMetaObject::activate(sender: &s, signal_index: s.metaObject()->methodOffset() + 35, argv: args); | 
| 3994 |         s.emitSignal1(); | 
| 3995 |         s.emitSignal2(); | 
| 3996 |  | 
| 3997 |         QCOMPARE(r1.count_slot1, 0); | 
| 3998 |         QCOMPARE(r1.count_slot2, 5); | 
| 3999 |         QCOMPARE(r1.count_slot3, 1); | 
| 4000 |         QCOMPARE(r2.count_slot1, 1); | 
| 4001 |         QCOMPARE(r2.count_slot2, 0); | 
| 4002 |         QCOMPARE(r2.count_slot3, 0); | 
| 4003 |     } | 
| 4004 |  | 
| 4005 |     r1.reset(); | 
| 4006 |     r2.reset(); | 
| 4007 |  | 
| 4008 | #define SIGNAL_INDEX(S)  obj1.metaObject()->indexOfSignal(QMetaObject::normalizedSignature(#S)) | 
| 4009 |     OverloadObject obj1; | 
| 4010 |     QObject obj2, obj3; | 
| 4011 |  | 
| 4012 |     QMetaObject::connect(sender: &obj1, SIGNAL_INDEX(sig(int)) , receiver: &r1, method_index: slot1Index); | 
| 4013 |     QMetaObject::connect(sender: &obj1, SIGNAL_INDEX(sig(QObject *, QObject *, QObject *)) , | 
| 4014 |                          receiver: &r2, method_index: slot1Index); | 
| 4015 |  | 
| 4016 |     QMetaObject::connect(sender: &obj1, SIGNAL_INDEX(sig(QObject *, QObject *, QObject *, QObject *)) , | 
| 4017 |                          receiver: &r1, method_index: slot2Index); | 
| 4018 |     QMetaObject::connect(sender: &obj1, SIGNAL_INDEX(sig(QObject *)) , receiver: &r2, method_index: slot2Index); | 
| 4019 |     QMetaObject::connect(sender: &obj1, SIGNAL_INDEX(sig(int, int)) , receiver: &r1, method_index: slot3Index); | 
| 4020 |  | 
| 4021 |     emit obj1.sig(r: 0.5); //connected to nothing | 
| 4022 |     emit obj1.sig(i: 1, c: 'a'); //connected to nothing | 
| 4023 |     QCOMPARE(r1.count_slot1, 0); | 
| 4024 |     QCOMPARE(r1.count_slot2, 0); | 
| 4025 |     QCOMPARE(r1.count_slot3, 0); | 
| 4026 |     QCOMPARE(r2.count_slot1, 0); | 
| 4027 |     QCOMPARE(r2.count_slot2, 0); | 
| 4028 |     QCOMPARE(r2.count_slot3, 0); | 
| 4029 |  | 
| 4030 |     emit obj1.sig(i: 1); //this signal is connected | 
| 4031 |     emit obj1.sig(o: &obj2); | 
| 4032 |  | 
| 4033 |     QCOMPARE(r1.count_slot1, 1); | 
| 4034 |     QCOMPARE(r1.count_slot2, 0); | 
| 4035 |     QCOMPARE(r1.count_slot3, 1); | 
| 4036 |     QCOMPARE(r2.count_slot1, 0); | 
| 4037 |     QCOMPARE(r2.count_slot2, 1); | 
| 4038 |     QCOMPARE(r2.count_slot3, 0); | 
| 4039 |  | 
| 4040 |     emit obj1.sig(o: &obj2, p: &obj3); //this signal is connected | 
| 4041 |  | 
| 4042 |     QCOMPARE(r1.count_slot1, 1); | 
| 4043 |     QCOMPARE(r1.count_slot2, 1); | 
| 4044 |     QCOMPARE(r1.count_slot3, 1); | 
| 4045 |     QCOMPARE(r2.count_slot1, 1); | 
| 4046 |     QCOMPARE(r2.count_slot2, 1); | 
| 4047 |     QCOMPARE(r2.count_slot3, 0); | 
| 4048 | } | 
| 4049 |  | 
| 4050 | void tst_QObject::qMetaObjectDisconnectOne() | 
| 4051 | { | 
| 4052 |     SenderObject s; | 
| 4053 |     ReceiverObject r1; | 
| 4054 |  | 
| 4055 |     int signal1Index = s.metaObject()->indexOfSignal(signal: "signal1()" ); | 
| 4056 |     int signal3Index = s.metaObject()->indexOfSignal(signal: "signal3()" ); | 
| 4057 |     int slot1Index = r1.metaObject()->indexOfSlot(slot: "slot1()" ); | 
| 4058 |     int slot2Index = r1.metaObject()->indexOfSlot(slot: "slot2()" ); | 
| 4059 |  | 
| 4060 |     QVERIFY(signal1Index > 0); | 
| 4061 |     QVERIFY(signal3Index > 0); | 
| 4062 |     QVERIFY(slot1Index > 0); | 
| 4063 |     QVERIFY(slot2Index > 0); | 
| 4064 |  | 
| 4065 |     QVERIFY(QMetaObject::connect(&s, signal1Index, &r1, slot1Index)); | 
| 4066 |     QVERIFY(QMetaObject::connect(&s, signal3Index, &r1, slot2Index)); | 
| 4067 |     QVERIFY(QMetaObject::connect(&s, signal3Index, &r1, slot2Index)); | 
| 4068 |     QVERIFY(QMetaObject::connect(&s, signal3Index, &r1, slot2Index)); | 
| 4069 |  | 
| 4070 |     r1.reset(); | 
| 4071 |     QCOMPARE(r1.count_slot1, 0); | 
| 4072 |     QCOMPARE(r1.count_slot2, 0); | 
| 4073 |  | 
| 4074 |     s.emitSignal1(); | 
| 4075 |     QCOMPARE(r1.count_slot1, 1); | 
| 4076 |     QCOMPARE(r1.count_slot2, 0); | 
| 4077 |  | 
| 4078 |     s.emitSignal3(); | 
| 4079 |     QCOMPARE(r1.count_slot1, 1); | 
| 4080 |     QCOMPARE(r1.count_slot2, 3); | 
| 4081 |  | 
| 4082 |     r1.reset(); | 
| 4083 |     QVERIFY(QMetaObject::disconnectOne(&s, signal1Index, &r1, slot1Index)); | 
| 4084 |     QVERIFY(QMetaObject::disconnectOne(&s, signal3Index, &r1, slot2Index)); | 
| 4085 |  | 
| 4086 |     s.emitSignal1(); | 
| 4087 |     QCOMPARE(r1.count_slot1, 0); | 
| 4088 |     QCOMPARE(r1.count_slot2, 0); | 
| 4089 |  | 
| 4090 |     s.emitSignal3(); | 
| 4091 |     QCOMPARE(r1.count_slot1, 0); | 
| 4092 |     QCOMPARE(r1.count_slot2, 2); | 
| 4093 |  | 
| 4094 |     r1.reset(); | 
| 4095 |     QVERIFY(!QMetaObject::disconnectOne(&s, signal1Index, &r1, slot1Index)); | 
| 4096 |     QVERIFY( QMetaObject::disconnectOne(&s, signal3Index, &r1, slot2Index)); | 
| 4097 |  | 
| 4098 |     s.emitSignal1(); | 
| 4099 |     QCOMPARE(r1.count_slot1, 0); | 
| 4100 |     QCOMPARE(r1.count_slot2, 0); | 
| 4101 |  | 
| 4102 |     s.emitSignal3(); | 
| 4103 |     QCOMPARE(r1.count_slot1, 0); | 
| 4104 |     QCOMPARE(r1.count_slot2, 1); | 
| 4105 |  | 
| 4106 |     r1.reset(); | 
| 4107 |     QVERIFY(!QMetaObject::disconnectOne(&s, signal1Index, &r1, slot1Index)); | 
| 4108 |     QVERIFY( QMetaObject::disconnectOne(&s, signal3Index, &r1, slot2Index)); | 
| 4109 |  | 
| 4110 |     s.emitSignal1(); | 
| 4111 |     QCOMPARE(r1.count_slot1, 0); | 
| 4112 |     QCOMPARE(r1.count_slot2, 0); | 
| 4113 |  | 
| 4114 |     s.emitSignal3(); | 
| 4115 |     QCOMPARE(r1.count_slot1, 0); | 
| 4116 |     QCOMPARE(r1.count_slot2, 0); | 
| 4117 | } | 
| 4118 |  | 
| 4119 | class ConfusingObject : public SenderObject | 
| 4120 | { Q_OBJECT | 
| 4121 | public slots: | 
| 4122 |     void signal1() { s++; } | 
| 4123 | signals: | 
| 4124 |     void aPublicSlot(); | 
| 4125 | public: | 
| 4126 |     int s; | 
| 4127 |     ConfusingObject() : s(0) {} | 
| 4128 |     friend class tst_QObject; | 
| 4129 | }; | 
| 4130 |  | 
| 4131 | void tst_QObject::sameName() | 
| 4132 | { | 
| 4133 |     ConfusingObject c1, c2; | 
| 4134 |     QVERIFY(connect(&c1, SIGNAL(signal1()), &c1, SLOT(signal1()))); | 
| 4135 |     c1.emitSignal1(); | 
| 4136 |     QCOMPARE(c1.s, 1); | 
| 4137 |  | 
| 4138 |     QVERIFY(connect(&c2, SIGNAL(signal1()), &c1, SIGNAL(signal1()))); | 
| 4139 |     c2.emitSignal1(); | 
| 4140 |     QCOMPARE(c1.s, 2); | 
| 4141 |  | 
| 4142 | #ifndef QT_NO_DEBUG | 
| 4143 |     QTest::ignoreMessage(type: QtWarningMsg, message: "QMetaObject::indexOfSignal: signal aPublicSlot() from SenderObject redefined in ConfusingObject" ); | 
| 4144 | #endif | 
| 4145 |     QVERIFY(connect(&c2, SIGNAL(aPublicSlot()), &c1, SLOT(signal1()))); | 
| 4146 |     c2.aPublicSlot(); | 
| 4147 |     QCOMPARE(c2.aPublicSlotCalled, 0); | 
| 4148 |     QCOMPARE(c1.aPublicSlotCalled, 0); | 
| 4149 |     QCOMPARE(c1.s, 3); | 
| 4150 |  | 
| 4151 | #ifndef QT_NO_DEBUG | 
| 4152 |     QTest::ignoreMessage(type: QtWarningMsg, message: "QMetaObject::indexOfSignal: signal aPublicSlot() from SenderObject redefined in ConfusingObject" ); | 
| 4153 | #endif | 
| 4154 |     QVERIFY(connect(&c2, SIGNAL(aPublicSlot()), &c1, SLOT(aPublicSlot()))); | 
| 4155 |     c2.aPublicSlot(); | 
| 4156 |     QCOMPARE(c2.aPublicSlotCalled, 0); | 
| 4157 |     QCOMPARE(c1.aPublicSlotCalled, 1); | 
| 4158 |     QCOMPARE(c1.s, 4); | 
| 4159 | } | 
| 4160 |  | 
| 4161 | void tst_QObject::connectByMetaMethods() | 
| 4162 | { | 
| 4163 |     SenderObject s; | 
| 4164 |     ReceiverObject r; | 
| 4165 |     const QMetaObject *smeta = s.metaObject(); | 
| 4166 |     const QMetaObject *rmeta = r.metaObject(); | 
| 4167 |     int sigIndx = smeta->indexOfSignal(signal: QMetaObject::normalizedSignature(method: "signal1()" )); | 
| 4168 |     int slotIndx = rmeta->indexOfSlot(slot: QMetaObject::normalizedSignature(method: "slot1()" )); | 
| 4169 |     QVERIFY( sigIndx != -1 ); | 
| 4170 |     QVERIFY( slotIndx != -1 ); | 
| 4171 |     QMetaMethod signal = smeta->method(index: sigIndx); | 
| 4172 |     QMetaMethod slot = rmeta->method(index: slotIndx); | 
| 4173 |  | 
| 4174 |     QVERIFY(connect(&s,signal, &r,slot)); | 
| 4175 |  | 
| 4176 |     QVERIFY(!r.called(1)); | 
| 4177 |     s.emitSignal1(); | 
| 4178 |     QVERIFY(r.called(1)); | 
| 4179 | } | 
| 4180 |  | 
| 4181 | void tst_QObject::connectByMetaMethodSlotInsteadOfSignal() | 
| 4182 | { | 
| 4183 |     SenderObject s; | 
| 4184 |     ReceiverObject r; | 
| 4185 |     const QMetaObject *smeta = s.metaObject(); | 
| 4186 |     const QMetaObject *rmeta = r.metaObject(); | 
| 4187 |     int badIndx = smeta->indexOfSlot(slot: QMetaObject::normalizedSignature(method: "aPublicSlot()" )); | 
| 4188 |     int slotIndx = rmeta->indexOfSlot(slot: QMetaObject::normalizedSignature(method: "slot1()" )); | 
| 4189 |     QVERIFY( badIndx != -1 ); | 
| 4190 |     QVERIFY( slotIndx != -1 ); | 
| 4191 |     QMetaMethod badMethod = smeta->method(index: badIndx); | 
| 4192 |     QMetaMethod slot = rmeta->method(index: slotIndx); | 
| 4193 |  | 
| 4194 |     QTest::ignoreMessage(type: QtWarningMsg,message: "QObject::connect: Cannot connect SenderObject::aPublicSlot() to ReceiverObject::slot1()" ); | 
| 4195 |     QVERIFY(!connect(&s,badMethod, &r,slot)); | 
| 4196 | } | 
| 4197 |  | 
| 4198 | class Constructable: public QObject | 
| 4199 | { | 
| 4200 |     Q_OBJECT | 
| 4201 |  | 
| 4202 | public: | 
| 4203 |     Q_INVOKABLE Constructable(){} | 
| 4204 |  | 
| 4205 | }; | 
| 4206 |  | 
| 4207 | void tst_QObject::connectConstructorByMetaMethod() | 
| 4208 | { | 
| 4209 |     Constructable sc; | 
| 4210 |     Constructable rc; | 
| 4211 |     SenderObject s; | 
| 4212 |     ReceiverObject r; | 
| 4213 |  | 
| 4214 |     const QMetaObject cmeta = Constructable::staticMetaObject; | 
| 4215 |     const QMetaObject *smeta = s.metaObject(); | 
| 4216 |     const QMetaObject *rmeta = r.metaObject(); | 
| 4217 |     int constructorIndx = cmeta.indexOfConstructor(constructor: QMetaObject::normalizedSignature(method: "Constructable()" )); | 
| 4218 |     int sigIndx = smeta->indexOfSignal(signal: QMetaObject::normalizedSignature(method: "signal1()" )); | 
| 4219 |     int slotIndx = rmeta->indexOfSlot(slot: QMetaObject::normalizedSignature(method: "slot1()" )); | 
| 4220 |     QVERIFY( constructorIndx != -1 ); | 
| 4221 |     QVERIFY( sigIndx != -1 ); | 
| 4222 |     QVERIFY( slotIndx != -1 ); | 
| 4223 |  | 
| 4224 |     QMetaMethod constructor = cmeta.constructor(index: constructorIndx); | 
| 4225 |     QMetaMethod signal = smeta->method(index: sigIndx); | 
| 4226 |     QMetaMethod slot = rmeta->method(index: slotIndx); | 
| 4227 |  | 
| 4228 |     QTest::ignoreMessage(type: QtWarningMsg,message: "QObject::connect: Cannot connect Constructable::Constructable() to ReceiverObject::slot1()" ); | 
| 4229 |     QVERIFY(!connect(&sc,constructor, &r,slot)); | 
| 4230 |     QTest::ignoreMessage(type: QtWarningMsg,message: "QObject::connect: Cannot connect SenderObject::signal1() to Constructable::Constructable()" ); | 
| 4231 |     QVERIFY(!connect(&s,signal, &rc,constructor)); | 
| 4232 |     QTest::ignoreMessage(type: QtWarningMsg,message: "QObject::connect: Cannot connect Constructable::Constructable() to Constructable::Constructable()" ); | 
| 4233 |     QVERIFY(!connect(&sc,constructor, &rc,constructor)); | 
| 4234 | } | 
| 4235 |  | 
| 4236 | void tst_QObject::disconnectByMetaMethod() | 
| 4237 | { | 
| 4238 |     SenderObject s; | 
| 4239 |     ReceiverObject r1; | 
| 4240 |     ReceiverObject r2; | 
| 4241 |  | 
| 4242 |     QMetaMethod signal1 = s.metaObject()->method(index: s.metaObject()->indexOfMethod(method: "signal1()" )); | 
| 4243 |     QMetaMethod signal2 = s.metaObject()->method(index: s.metaObject()->indexOfMethod(method: "signal2()" )); | 
| 4244 |     QMetaMethod signal3 = s.metaObject()->method(index: s.metaObject()->indexOfMethod(method: "signal3()" )); | 
| 4245 |  | 
| 4246 |     QMetaMethod slot1 = r1.metaObject()->method(index: r1.metaObject()->indexOfMethod(method: "slot1()" )); | 
| 4247 |     QMetaMethod slot2 = r1.metaObject()->method(index: r1.metaObject()->indexOfMethod(method: "slot2()" )); | 
| 4248 |     QMetaMethod slot3 = r1.metaObject()->method(index: r1.metaObject()->indexOfMethod(method: "slot3()" )); | 
| 4249 |     QMetaMethod slot4 = r1.metaObject()->method(index: r1.metaObject()->indexOfMethod(method: "slot4()" )); | 
| 4250 |  | 
| 4251 |     connect(sender: &s, signal: signal1, receiver: &r1, method: slot1); | 
| 4252 |  | 
| 4253 |     s.emitSignal1(); | 
| 4254 |  | 
| 4255 |     QVERIFY(r1.called(1)); | 
| 4256 |     r1.reset(); | 
| 4257 |  | 
| 4258 |     // usual disconnect with all parameters given | 
| 4259 |     bool ret = QObject::disconnect(sender: &s, signal: signal1, receiver: &r1, member: slot1); | 
| 4260 |  | 
| 4261 |     s.emitSignal1(); | 
| 4262 |  | 
| 4263 |     QVERIFY(!r1.called(1)); | 
| 4264 |     r1.reset(); | 
| 4265 |  | 
| 4266 |     QVERIFY(ret); | 
| 4267 |     ret = QObject::disconnect(sender: &s, signal: signal1, receiver: &r1, member: slot1); | 
| 4268 |     QVERIFY(!ret); | 
| 4269 |  | 
| 4270 |     r1.reset(); | 
| 4271 |  | 
| 4272 |     connect(sender: &s, signal: signal1, receiver: &r1, method: slot1); | 
| 4273 |     connect(sender: &s, signal: signal1, receiver: &r1, method: slot2); | 
| 4274 |     connect(sender: &s, signal: signal1, receiver: &r1, method: slot3); | 
| 4275 |     connect(sender: &s, signal: signal2, receiver: &r1, method: slot4); | 
| 4276 |  | 
| 4277 |     // disconnect s's signal1() from all slots of r1 | 
| 4278 |     QObject::disconnect(sender: &s, signal: signal1, receiver: &r1, member: QMetaMethod()); | 
| 4279 |  | 
| 4280 |     s.emitSignal1(); | 
| 4281 |     s.emitSignal2(); | 
| 4282 |  | 
| 4283 |     QVERIFY(!r1.called(1)); | 
| 4284 |     QVERIFY(!r1.called(2)); | 
| 4285 |     QVERIFY(!r1.called(3)); | 
| 4286 |     QVERIFY(r1.called(4)); | 
| 4287 |     r1.reset(); | 
| 4288 |     // make sure all is disconnected again | 
| 4289 |     QObject::disconnect(sender: &s, signal: 0, receiver: &r1, member: 0); | 
| 4290 |  | 
| 4291 |     connect(sender: &s, signal: signal1, receiver: &r1, method: slot1); | 
| 4292 |     connect(sender: &s, signal: signal1, receiver: &r2, method: slot1); | 
| 4293 |     connect(sender: &s, signal: signal2, receiver: &r1, method: slot2); | 
| 4294 |     connect(sender: &s, signal: signal2, receiver: &r2, method: slot2); | 
| 4295 |     connect(sender: &s, signal: signal3, receiver: &r1, method: slot3); | 
| 4296 |     connect(sender: &s, signal: signal3, receiver: &r2, method: slot3); | 
| 4297 |  | 
| 4298 |     // disconnect signal1() from all receivers | 
| 4299 |     QObject::disconnect(sender: &s, signal: signal1, receiver: 0, member: QMetaMethod()); | 
| 4300 |     s.emitSignal1(); | 
| 4301 |     s.emitSignal2(); | 
| 4302 |     s.emitSignal3(); | 
| 4303 |  | 
| 4304 |     QVERIFY(!r1.called(1)); | 
| 4305 |     QVERIFY(!r2.called(1)); | 
| 4306 |     QVERIFY(r1.called(2)); | 
| 4307 |     QVERIFY(r2.called(2)); | 
| 4308 |     QVERIFY(r1.called(2)); | 
| 4309 |     QVERIFY(r2.called(2)); | 
| 4310 |  | 
| 4311 |     r1.reset(); | 
| 4312 |     r2.reset(); | 
| 4313 |  | 
| 4314 |     // disconnect all signals of s from all receivers | 
| 4315 |     QObject::disconnect(sender: &s, signal: 0, receiver: 0, member: 0); | 
| 4316 |  | 
| 4317 |     connect(sender: &s, signal: signal1, receiver: &r1, method: slot1); | 
| 4318 |     connect(sender: &s, signal: signal1, receiver: &r2, method: slot1); | 
| 4319 |  | 
| 4320 |     // disconnect all signals from slot1 of r1 | 
| 4321 |     QObject::disconnect(sender: &s, signal: QMetaMethod(), receiver: &r1, member: slot1); | 
| 4322 |  | 
| 4323 |     s.emitSignal1(); | 
| 4324 |  | 
| 4325 |     QVERIFY(!r1.called(1)); | 
| 4326 |     QVERIFY(r2.called(1)); | 
| 4327 | } | 
| 4328 |  | 
| 4329 | void tst_QObject::disconnectNotSignalMetaMethod() | 
| 4330 | { | 
| 4331 |     SenderObject s; | 
| 4332 |     ReceiverObject r; | 
| 4333 |  | 
| 4334 |     connect(sender: &s, SIGNAL(signal1()), receiver: &r, SLOT(slot1())); | 
| 4335 |  | 
| 4336 |     QMetaMethod slot = s.metaObject()->method( | 
| 4337 |             index: s.metaObject()->indexOfMethod(method: "aPublicSlot()" )); | 
| 4338 |  | 
| 4339 |     QTest::ignoreMessage(type: QtWarningMsg,message: "QObject::disconnect: Attempt to unbind non-signal SenderObject::aPublicSlot()" ); | 
| 4340 |     QVERIFY(!QObject::disconnect(&s, slot, &r, QMetaMethod())); | 
| 4341 | } | 
| 4342 |  | 
| 4343 | class ThreadAffinityThread : public QThread | 
| 4344 | { | 
| 4345 | public: | 
| 4346 |     SenderObject *sender; | 
| 4347 |  | 
| 4348 |     ThreadAffinityThread(SenderObject *sender) | 
| 4349 |         : sender(sender) | 
| 4350 |     { } | 
| 4351 |     void run() | 
| 4352 |     { | 
| 4353 |         sender->emitSignal1(); | 
| 4354 |     } | 
| 4355 | }; | 
| 4356 |  | 
| 4357 | void tst_QObject::autoConnectionBehavior() | 
| 4358 | { | 
| 4359 |     SenderObject *sender = new SenderObject; | 
| 4360 |     ReceiverObject *receiver = new ReceiverObject; | 
| 4361 |     connect(sender, SIGNAL(signal1()), receiver, SLOT(slot1())); | 
| 4362 |  | 
| 4363 |     // at emit, currentThread == sender->thread(), currentThread == receiver->thread(), sender->thread() == receiver->thread() | 
| 4364 |     QVERIFY(!receiver->called(1)); | 
| 4365 |     sender->emitSignal1(); | 
| 4366 |     QVERIFY(receiver->called(1)); | 
| 4367 |     receiver->reset(); | 
| 4368 |  | 
| 4369 |     // at emit, currentThread != sender->thread(), currentThread != receiver->thread(), sender->thread() == receiver->thread() | 
| 4370 |     ThreadAffinityThread emitThread1(sender); | 
| 4371 |     QVERIFY(!receiver->called(1)); | 
| 4372 |     emitThread1.start(); | 
| 4373 |     QVERIFY(emitThread1.wait(30000)); | 
| 4374 |     QVERIFY(!receiver->called(1)); | 
| 4375 |     QCoreApplication::sendPostedEvents(receiver, event_type: QEvent::MetaCall); | 
| 4376 |     QVERIFY(receiver->called(1)); | 
| 4377 |     receiver->reset(); | 
| 4378 |  | 
| 4379 |     // at emit, currentThread == sender->thread(), currentThread != receiver->thread(), sender->thread() != receiver->thread() | 
| 4380 |     sender->moveToThread(thread: &emitThread1); | 
| 4381 |     QVERIFY(!receiver->called(1)); | 
| 4382 |     emitThread1.start(); | 
| 4383 |     QVERIFY(emitThread1.wait(30000)); | 
| 4384 |     QVERIFY(!receiver->called(1)); | 
| 4385 |     QCoreApplication::sendPostedEvents(receiver, event_type: QEvent::MetaCall); | 
| 4386 |     QVERIFY(receiver->called(1)); | 
| 4387 |     receiver->reset(); | 
| 4388 |  | 
| 4389 |     // at emit, currentThread != sender->thread(), currentThread == receiver->thread(), sender->thread() != receiver->thread() | 
| 4390 |     QVERIFY(!receiver->called(1)); | 
| 4391 |     sender->emitSignal1(); | 
| 4392 |     QVERIFY(receiver->called(1)); | 
| 4393 |     receiver->reset(); | 
| 4394 |  | 
| 4395 |     // at emit, currentThread != sender->thread(), currentThread != receiver->thread(), sender->thread() != receiver->thread() | 
| 4396 |     ThreadAffinityThread emitThread2(sender); | 
| 4397 |     QThread receiverThread; | 
| 4398 |     QTimer *timer = new QTimer; | 
| 4399 |     timer->setSingleShot(true); | 
| 4400 |     timer->setInterval(100); | 
| 4401 |     connect(sender: &receiverThread, SIGNAL(started()), receiver: timer, SLOT(start())); | 
| 4402 |     connect(sender: timer, SIGNAL(timeout()), receiver: &receiverThread, SLOT(quit()), Qt::DirectConnection); | 
| 4403 |     connect(sender: &receiverThread, SIGNAL(finished()), receiver: timer, SLOT(deleteLater())); | 
| 4404 |     timer->moveToThread(thread: &receiverThread); | 
| 4405 |  | 
| 4406 |     receiver->moveToThread(thread: &receiverThread); | 
| 4407 |     QVERIFY(!receiver->called(1)); | 
| 4408 |     emitThread2.start(); | 
| 4409 |     QVERIFY(emitThread2.wait(30000)); | 
| 4410 |     QVERIFY(!receiver->called(1)); | 
| 4411 |     receiverThread.start(); | 
| 4412 |     QVERIFY(receiverThread.wait(30000)); | 
| 4413 |     QVERIFY(receiver->called(1)); | 
| 4414 |     receiver->reset(); | 
| 4415 |  | 
| 4416 |     delete sender; | 
| 4417 |     delete receiver; | 
| 4418 | } | 
| 4419 |  | 
| 4420 | class BaseDestroyed : public QObject | 
| 4421 | { Q_OBJECT | 
| 4422 |     QList<QString> fooList; | 
| 4423 |     bool destroyed; | 
| 4424 | public: | 
| 4425 |     BaseDestroyed() : destroyed(false) | 
| 4426 |     { fooList << "a"  << "b" ; } | 
| 4427 |     ~BaseDestroyed() | 
| 4428 |     { | 
| 4429 |         QVERIFY(!destroyed); | 
| 4430 |         destroyed = true; | 
| 4431 |     } | 
| 4432 |  | 
| 4433 | public slots: | 
| 4434 |     void slotUseList() | 
| 4435 |     { | 
| 4436 |         QVERIFY(!destroyed); | 
| 4437 |         fooList << "c"  << "d" ; | 
| 4438 |     } | 
| 4439 | }; | 
| 4440 |  | 
| 4441 | static void processEvents() | 
| 4442 | { | 
| 4443 |     qApp->processEvents(); | 
| 4444 | } | 
| 4445 |  | 
| 4446 | void tst_QObject::baseDestroyed() | 
| 4447 | { | 
| 4448 |     { | 
| 4449 |         BaseDestroyed d; | 
| 4450 |         connect(sender: &d, SIGNAL(destroyed()), receiver: &d, SLOT(slotUseList())); | 
| 4451 |         //When d goes out of scope, slotUseList should not be called as the BaseDestroyed has | 
| 4452 |         // already been destroyed while ~QObject emit destroyed | 
| 4453 |     } | 
| 4454 |     { | 
| 4455 |         BaseDestroyed d; | 
| 4456 |         connect(sender: &d, signal: &QObject::destroyed, slot: processEvents); | 
| 4457 |         QMetaObject::invokeMethod(obj: &d, member: "slotUseList" , type: Qt::QueuedConnection); | 
| 4458 |         //the destructor will call processEvents, that should not call the slotUseList | 
| 4459 |     } | 
| 4460 | } | 
| 4461 |  | 
| 4462 | void tst_QObject::pointerConnect() | 
| 4463 | { | 
| 4464 |     SenderObject s; | 
| 4465 |     ReceiverObject r1; | 
| 4466 |     ReceiverObject r2; | 
| 4467 |     r1.reset(); | 
| 4468 |     r2.reset(); | 
| 4469 |     ReceiverObject::sequence = 0; | 
| 4470 |     QTimer timer; | 
| 4471 |  | 
| 4472 |     QVERIFY(connect(&s, &SenderObject::signal1 , &r1, &ReceiverObject::slot1)); | 
| 4473 |     QVERIFY(connect(&s, &SenderObject::signal1 , &r2, &ReceiverObject::slot1)); | 
| 4474 |     QVERIFY(connect(&s, &SenderObject::signal1 , &r1, &ReceiverObject::slot3)); | 
| 4475 |     QVERIFY(connect(&s, &SenderObject::signal3 , &r1, &ReceiverObject::slot3)); | 
| 4476 |     QVERIFY2(connect(&timer, &QTimer::timeout, &r1, &ReceiverObject::deleteLater), | 
| 4477 |              "Signal connection failed most likely due to failing comparison of pointers to member "  | 
| 4478 |              "functions caused by problems with -reduce-relocations on this platform." ); | 
| 4479 |  | 
| 4480 |     s.emitSignal1(); | 
| 4481 |     s.emitSignal2(); | 
| 4482 |     s.emitSignal3(); | 
| 4483 |     s.emitSignal4(); | 
| 4484 |  | 
| 4485 |     QCOMPARE(r1.count_slot1, 1); | 
| 4486 |     QCOMPARE(r1.count_slot2, 0); | 
| 4487 |     QCOMPARE(r1.count_slot3, 2); | 
| 4488 |     QCOMPARE(r1.count_slot4, 0); | 
| 4489 |     QCOMPARE(r2.count_slot1, 1); | 
| 4490 |     QCOMPARE(r2.count_slot2, 0); | 
| 4491 |     QCOMPARE(r2.count_slot3, 0); | 
| 4492 |     QCOMPARE(r2.count_slot4, 0); | 
| 4493 |     QCOMPARE(r1.sequence_slot1, 1); | 
| 4494 |     QCOMPARE(r2.sequence_slot1, 2); | 
| 4495 |     QCOMPARE(r1.sequence_slot3, 4); | 
| 4496 |  | 
| 4497 |     r1.reset(); | 
| 4498 |     r2.reset(); | 
| 4499 |     ReceiverObject::sequence = 0; | 
| 4500 |  | 
| 4501 |     QVERIFY(connect(&s, &SenderObject::signal4, &r1, &ReceiverObject::slot4)); | 
| 4502 |     QVERIFY(connect(&s, &SenderObject::signal4, &r2, &ReceiverObject::slot4)); | 
| 4503 |     QVERIFY(connect(&s, &SenderObject::signal1, &r2, &ReceiverObject::slot4)); | 
| 4504 |  | 
| 4505 |     s.emitSignal4(); | 
| 4506 |     QCOMPARE(r1.count_slot4, 1); | 
| 4507 |     QCOMPARE(r2.count_slot4, 1); | 
| 4508 |     QCOMPARE(r1.sequence_slot4, 1); | 
| 4509 |     QCOMPARE(r2.sequence_slot4, 2); | 
| 4510 |  | 
| 4511 |     r1.reset(); | 
| 4512 |     r2.reset(); | 
| 4513 |     ReceiverObject::sequence = 0; | 
| 4514 |  | 
| 4515 |     connect(sender: &s, signal: &SenderObject::signal4 , receiver: &r1, slot: &ReceiverObject::slot4); | 
| 4516 |  | 
| 4517 |     s.emitSignal4(); | 
| 4518 |     QCOMPARE(r1.count_slot4, 2); | 
| 4519 |     QCOMPARE(r2.count_slot4, 1); | 
| 4520 |     QCOMPARE(r1.sequence_slot4, 3); | 
| 4521 |     QCOMPARE(r2.sequence_slot4, 2); | 
| 4522 |  | 
| 4523 |     QMetaObject::Connection con; | 
| 4524 |     QVERIFY(!con); | 
| 4525 |     QVERIFY(!QObject::disconnect(con)); | 
| 4526 |  | 
| 4527 |     //connect a slot to a signal (== error) | 
| 4528 |     QTest::ignoreMessage(type: QtWarningMsg, message: "QObject::connect: signal not found in ReceiverObject" ); | 
| 4529 |     con = connect(sender: &r1, signal: &ReceiverObject::slot4 , receiver: &s, slot: &SenderObject::signal4); | 
| 4530 |     QVERIFY(!con); | 
| 4531 |     QVERIFY(!QObject::disconnect(con)); | 
| 4532 | } | 
| 4533 |  | 
| 4534 | void tst_QObject::pointerDisconnect() | 
| 4535 | { | 
| 4536 |     SenderObject s; | 
| 4537 |     ReceiverObject r1; | 
| 4538 |     ReceiverObject r2; | 
| 4539 |  | 
| 4540 |     connect(sender: &s, signal: &SenderObject::signal1, receiver: &r1, slot: &ReceiverObject::slot1); | 
| 4541 |  | 
| 4542 |     connect(sender: &s, signal: &SenderObject::signal2, receiver: &r1, slot: &ReceiverObject::slot2); | 
| 4543 |     connect(sender: &s, signal: &SenderObject::signal3, receiver: &r1, slot: &ReceiverObject::slot3); | 
| 4544 |     connect(sender: &s, signal: &SenderObject::signal4, receiver: &r1, slot: &ReceiverObject::slot4); | 
| 4545 |  | 
| 4546 |     s.emitSignal1(); | 
| 4547 |     s.emitSignal2(); | 
| 4548 |     s.emitSignal3(); | 
| 4549 |     s.emitSignal4(); | 
| 4550 |  | 
| 4551 |     QVERIFY(r1.called(1)); | 
| 4552 |     QVERIFY(r1.called(2)); | 
| 4553 |     QVERIFY(r1.called(3)); | 
| 4554 |     QVERIFY(r1.called(4)); | 
| 4555 |     r1.reset(); | 
| 4556 |  | 
| 4557 |     // usual disconnect with all parameters given | 
| 4558 |     bool ret = QObject::disconnect(sender: &s, signal: &SenderObject::signal1, receiver: &r1, slot: &ReceiverObject::slot1); | 
| 4559 |  | 
| 4560 |     s.emitSignal1(); | 
| 4561 |  | 
| 4562 |     QVERIFY(!r1.called(1)); | 
| 4563 |     r1.reset(); | 
| 4564 |  | 
| 4565 |     QVERIFY(ret); | 
| 4566 |     ret = QObject::disconnect(sender: &s, signal: &SenderObject::signal1, receiver: &r1, slot: &ReceiverObject::slot1); | 
| 4567 |     QVERIFY(!ret); | 
| 4568 |  | 
| 4569 |     // disconnect all signals from s from all slots from r1 | 
| 4570 |     QObject::disconnect(sender: &s, signal: 0, receiver: &r1, member: 0); | 
| 4571 |  | 
| 4572 |     s.emitSignal2(); | 
| 4573 |     s.emitSignal3(); | 
| 4574 |     s.emitSignal4(); | 
| 4575 |  | 
| 4576 |     QVERIFY(!r1.called(2)); | 
| 4577 |     QVERIFY(!r1.called(3)); | 
| 4578 |     QVERIFY(!r1.called(4)); | 
| 4579 |     r1.reset(); | 
| 4580 |  | 
| 4581 |     connect(sender: &s, signal: &SenderObject::signal1, receiver: &r1, slot: &ReceiverObject::slot1); | 
| 4582 |     connect(sender: &s, signal: &SenderObject::signal1, receiver: &r1, slot: &ReceiverObject::slot2); | 
| 4583 |     connect(sender: &s, signal: &SenderObject::signal1, receiver: &r1, slot: &ReceiverObject::slot3); | 
| 4584 |     connect(sender: &s, signal: &SenderObject::signal2, receiver: &r1, slot: &ReceiverObject::slot4); | 
| 4585 |  | 
| 4586 |     // disconnect s's signal1() from all slots of r1 | 
| 4587 |     QObject::disconnect(sender: &s, signal: &SenderObject::signal1, receiver: &r1, zero: 0); | 
| 4588 |  | 
| 4589 |     s.emitSignal1(); | 
| 4590 |     s.emitSignal2(); | 
| 4591 |  | 
| 4592 |     QVERIFY(!r1.called(1)); | 
| 4593 |     QVERIFY(!r1.called(2)); | 
| 4594 |     QVERIFY(!r1.called(3)); | 
| 4595 |     QVERIFY(r1.called(4)); | 
| 4596 |     r1.reset(); | 
| 4597 |     // make sure all is disconnected again | 
| 4598 |     QObject::disconnect(sender: &s, signal: 0, receiver: &r1, member: 0); | 
| 4599 |  | 
| 4600 |     connect(sender: &s, signal: &SenderObject::signal1, receiver: &r1, slot: &ReceiverObject::slot1); | 
| 4601 |     connect(sender: &s, signal: &SenderObject::signal1, receiver: &r2, slot: &ReceiverObject::slot1); | 
| 4602 |     connect(sender: &s, signal: &SenderObject::signal2, receiver: &r1, slot: &ReceiverObject::slot2); | 
| 4603 |     connect(sender: &s, signal: &SenderObject::signal2, receiver: &r2, slot: &ReceiverObject::slot2); | 
| 4604 |     connect(sender: &s, signal: &SenderObject::signal3, receiver: &r1, slot: &ReceiverObject::slot3); | 
| 4605 |     connect(sender: &s, signal: &SenderObject::signal3, receiver: &r2, slot: &ReceiverObject::slot3); | 
| 4606 |  | 
| 4607 |     // disconnect signal1() from all receivers | 
| 4608 |     QObject::disconnect(sender: &s, signal: &SenderObject::signal1, receiver: 0, zero: 0); | 
| 4609 |     s.emitSignal1(); | 
| 4610 |     s.emitSignal2(); | 
| 4611 |     s.emitSignal3(); | 
| 4612 |  | 
| 4613 |     QVERIFY(!r1.called(1)); | 
| 4614 |     QVERIFY(!r2.called(1)); | 
| 4615 |     QVERIFY(r1.called(2)); | 
| 4616 |     QVERIFY(r2.called(2)); | 
| 4617 |     QVERIFY(r1.called(2)); | 
| 4618 |     QVERIFY(r2.called(2)); | 
| 4619 |  | 
| 4620 |     r1.reset(); | 
| 4621 |     r2.reset(); | 
| 4622 |  | 
| 4623 |     // disconnect all signals of s from all receivers | 
| 4624 |     QObject::disconnect(sender: &s, signal: 0, receiver: 0, member: 0); | 
| 4625 |  | 
| 4626 |     QVERIFY(!r1.called(2)); | 
| 4627 |     QVERIFY(!r2.called(2)); | 
| 4628 |     QVERIFY(!r1.called(2)); | 
| 4629 |     QVERIFY(!r2.called(2)); | 
| 4630 | } | 
| 4631 |  | 
| 4632 |  | 
| 4633 | void tst_QObject::emitInDefinedOrderPointer() | 
| 4634 | { | 
| 4635 |     SenderObject sender; | 
| 4636 |     ReceiverObject receiver1, receiver2, receiver3, receiver4; | 
| 4637 |  | 
| 4638 |     QMetaObject::Connection h0 = connect(sender: &sender, signal: &SenderObject::signal1, receiver: &receiver1, slot: &SequenceObject::slot1); | 
| 4639 |     QMetaObject::Connection h1 = connect(sender: &sender, signal: &SenderObject::signal1, receiver: &receiver2, slot: &SequenceObject::slot1); | 
| 4640 |     QVERIFY(h0); | 
| 4641 |     QVERIFY(h1); | 
| 4642 |     connect(sender: &sender, signal: &SenderObject::signal1, receiver: &receiver3, slot: &SequenceObject::slot1); | 
| 4643 |     connect(sender: &sender, signal: &SenderObject::signal1, receiver: &receiver4, slot: &SequenceObject::slot1); | 
| 4644 |     connect(sender: &sender, signal: &SenderObject::signal1, receiver: &receiver1, slot: &SequenceObject::slot2); | 
| 4645 |     connect(sender: &sender, signal: &SenderObject::signal1, receiver: &receiver2, slot: &SequenceObject::slot2); | 
| 4646 |     connect(sender: &sender, signal: &SenderObject::signal1, receiver: &receiver3, slot: &SequenceObject::slot2); | 
| 4647 |     connect(sender: &sender, signal: &SenderObject::signal1, receiver: &receiver4, slot: &SequenceObject::slot2); | 
| 4648 |  | 
| 4649 |     int sequence; | 
| 4650 |     ReceiverObject::sequence = sequence = 0; | 
| 4651 |     sender.emitSignal1(); | 
| 4652 |     QCOMPARE(receiver1.sequence_slot1, ++sequence); | 
| 4653 |     QCOMPARE(receiver2.sequence_slot1, ++sequence); | 
| 4654 |     QCOMPARE(receiver3.sequence_slot1, ++sequence); | 
| 4655 |     QCOMPARE(receiver4.sequence_slot1, ++sequence); | 
| 4656 |     QCOMPARE(receiver1.sequence_slot2, ++sequence); | 
| 4657 |     QCOMPARE(receiver2.sequence_slot2, ++sequence); | 
| 4658 |     QCOMPARE(receiver3.sequence_slot2, ++sequence); | 
| 4659 |     QCOMPARE(receiver4.sequence_slot2, ++sequence); | 
| 4660 |  | 
| 4661 |     QObject::disconnect(h1); | 
| 4662 |     h1 = connect(sender: &sender, signal: &SenderObject::signal1, receiver: &receiver2, slot: &SequenceObject::slot1); | 
| 4663 |  | 
| 4664 |     ReceiverObject::sequence = sequence =  0; | 
| 4665 |     sender.emitSignal1(); | 
| 4666 |     QCOMPARE(receiver1.sequence_slot1, ++sequence); | 
| 4667 |     QCOMPARE(receiver3.sequence_slot1, ++sequence); | 
| 4668 |     QCOMPARE(receiver4.sequence_slot1, ++sequence); | 
| 4669 |     QCOMPARE(receiver1.sequence_slot2, ++sequence); | 
| 4670 |     QCOMPARE(receiver2.sequence_slot2, ++sequence); | 
| 4671 |     QCOMPARE(receiver3.sequence_slot2, ++sequence); | 
| 4672 |     QCOMPARE(receiver4.sequence_slot2, ++sequence); | 
| 4673 |     QCOMPARE(receiver2.sequence_slot1, ++sequence); | 
| 4674 |  | 
| 4675 |     QObject::disconnect(h0); | 
| 4676 |     h0 = connect(sender: &sender, signal: &SenderObject::signal1, receiver: &receiver1, slot: &SequenceObject::slot1); | 
| 4677 |  | 
| 4678 |     ReceiverObject::sequence = sequence =  0; | 
| 4679 |     sender.emitSignal1(); | 
| 4680 |     QCOMPARE(receiver3.sequence_slot1, ++sequence); | 
| 4681 |     QCOMPARE(receiver4.sequence_slot1, ++sequence); | 
| 4682 |     QCOMPARE(receiver1.sequence_slot2, ++sequence); | 
| 4683 |     QCOMPARE(receiver2.sequence_slot2, ++sequence); | 
| 4684 |     QCOMPARE(receiver3.sequence_slot2, ++sequence); | 
| 4685 |     QCOMPARE(receiver4.sequence_slot2, ++sequence); | 
| 4686 |     QCOMPARE(receiver2.sequence_slot1, ++sequence); | 
| 4687 |     QCOMPARE(receiver1.sequence_slot1, ++sequence); | 
| 4688 |  | 
| 4689 |     QVERIFY(QObject::disconnect(h0)); | 
| 4690 |     QVERIFY(!QObject::disconnect(h0)); | 
| 4691 | } | 
| 4692 |  | 
| 4693 |  | 
| 4694 | void tst_QObject::customTypesPointer() | 
| 4695 | { | 
| 4696 |     CustomType t0; | 
| 4697 |     CustomType t1(1, 2, 3); | 
| 4698 |     CustomType t2(2, 3, 4); | 
| 4699 |  | 
| 4700 |     { | 
| 4701 |         QCustomTypeChecker checker; | 
| 4702 |         QCOMPARE(instanceCount, 4); | 
| 4703 |  | 
| 4704 |         connect(sender: &checker, signal: &QCustomTypeChecker::signal1, receiver: &checker, slot: &QCustomTypeChecker::slot1, | 
| 4705 |                 type: Qt::DirectConnection); | 
| 4706 |         QCOMPARE(checker.received.value(), 0); | 
| 4707 |         checker.doEmit(ct: t1); | 
| 4708 |         QCOMPARE(checker.received.value(), t1.value()); | 
| 4709 |         checker.received = t0; | 
| 4710 |  | 
| 4711 |  | 
| 4712 |         checker.disconnect(); | 
| 4713 |  | 
| 4714 |         int idx = qRegisterMetaType<CustomType>(typeName: "CustomType" ); | 
| 4715 |         QCOMPARE(QMetaType::type("CustomType" ), idx); | 
| 4716 |  | 
| 4717 |         connect(sender: &checker, signal: &QCustomTypeChecker::signal1, receiver: &checker, slot: &QCustomTypeChecker::slot1, | 
| 4718 |                 type: Qt::QueuedConnection); | 
| 4719 |         QCOMPARE(instanceCount, 4); | 
| 4720 |         checker.doEmit(ct: t2); | 
| 4721 |         QCOMPARE(instanceCount, 5); | 
| 4722 |         QCOMPARE(checker.received.value(), t0.value()); | 
| 4723 |  | 
| 4724 |         QCoreApplication::processEvents(); | 
| 4725 |         QCOMPARE(checker.received.value(), t2.value()); | 
| 4726 |         QCOMPARE(instanceCount, 4); | 
| 4727 |  | 
| 4728 |         QVERIFY(QMetaType::isRegistered(idx)); | 
| 4729 |         QCOMPARE(qRegisterMetaType<CustomType>("CustomType" ), idx); | 
| 4730 |         QCOMPARE(QMetaType::type("CustomType" ), idx); | 
| 4731 |         QVERIFY(QMetaType::isRegistered(idx)); | 
| 4732 |  | 
| 4733 |         // Test auto registered type  (QList<CustomType>) | 
| 4734 |         QList<CustomType> list; | 
| 4735 |         QCOMPARE(instanceCount, 4); | 
| 4736 |         list.append(t: t1); | 
| 4737 |         QCOMPARE(instanceCount, 5); | 
| 4738 |         QVERIFY(connect(&checker, &QCustomTypeChecker::signal2, | 
| 4739 |                         &checker, &QCustomTypeChecker::slot2, Qt::QueuedConnection)); | 
| 4740 |         emit checker.signal2(ct: list); | 
| 4741 |         QCOMPARE(instanceCount, 5); //because the list is implicitly shared. | 
| 4742 |         list.clear(); | 
| 4743 |         QCOMPARE(instanceCount, 5); | 
| 4744 |         QCoreApplication::processEvents(); | 
| 4745 |         QCOMPARE(checker.received.value(), t1.value()); | 
| 4746 |         QCOMPARE(instanceCount, 4); | 
| 4747 |     } | 
| 4748 |     QCOMPARE(instanceCount, 3); | 
| 4749 | } | 
| 4750 |  | 
| 4751 | void tst_QObject::connectCxx0x() | 
| 4752 | { | 
| 4753 |     SenderObject s; | 
| 4754 |     ReceiverObject r1; | 
| 4755 |  | 
| 4756 |     QObject::connect(sender: &s, signal: &SenderObject::signal1, receiver: &r1, slot: &ReceiverObject::slot1); | 
| 4757 |     QObject::connect(sender: &s, signal: &SenderObject::signal3, receiver: &r1, slot: &ReceiverObject::slot2); | 
| 4758 |     QObject::connect(sender: &s, signal: &SenderObject::signal3, receiver: &r1, slot: &ReceiverObject::slot2); | 
| 4759 |     QObject::connect(sender: &s, signal: &SenderObject::signal3, receiver: &r1, slot: &ReceiverObject::slot2); | 
| 4760 |  | 
| 4761 |     r1.reset(); | 
| 4762 |     QCOMPARE(r1.count_slot1, 0); | 
| 4763 |     QCOMPARE(r1.count_slot2, 0); | 
| 4764 |  | 
| 4765 |     s.emitSignal1(); | 
| 4766 |     QCOMPARE(r1.count_slot1, 1); | 
| 4767 |     QCOMPARE(r1.count_slot2, 0); | 
| 4768 |  | 
| 4769 |     s.emitSignal3(); | 
| 4770 |     QCOMPARE(r1.count_slot1, 1); | 
| 4771 |     QCOMPARE(r1.count_slot2, 3); | 
| 4772 |  | 
| 4773 |     // connect signal to signal | 
| 4774 |     QObject::connect(sender: &s, signal: &SenderObject::signal2, receiver: &s, slot: &SenderObject::signal1); | 
| 4775 |  | 
| 4776 |     r1.reset(); | 
| 4777 |     s.emitSignal2(); | 
| 4778 |     QCOMPARE(r1.count_slot1, 1); | 
| 4779 | } | 
| 4780 |  | 
| 4781 | int receivedCount; | 
| 4782 | void receiverFunction() { ++receivedCount; } | 
| 4783 |  | 
| 4784 | void tst_QObject::connectToStaticCxx0x() | 
| 4785 | { | 
| 4786 |     SenderObject *s = new SenderObject; | 
| 4787 |  | 
| 4788 |     void (*receiver)() = receiverFunction; | 
| 4789 |  | 
| 4790 |     QObject::connect(sender: s, signal: &SenderObject::signal1, slot: receiver); | 
| 4791 |     receivedCount = 0; | 
| 4792 |     s->emitSignal1(); | 
| 4793 |     QCOMPARE(receivedCount, 1); | 
| 4794 |  | 
| 4795 |     QObject::connect(sender: s, signal: &SenderObject::signal1, slot: receiver); | 
| 4796 |     receivedCount = 0; | 
| 4797 |     s->emitSignal1(); | 
| 4798 |     QCOMPARE(receivedCount, 2); | 
| 4799 |  | 
| 4800 |     delete s; | 
| 4801 | } | 
| 4802 |  | 
| 4803 | class LotsOfSignalsAndSlots: public QObject | 
| 4804 | { | 
| 4805 |     Q_OBJECT | 
| 4806 |     typedef void (*fptr)(); | 
| 4807 |  | 
| 4808 |     public slots: | 
| 4809 |         void slot_v() {} | 
| 4810 |         void slot_v_noexcept() noexcept {} | 
| 4811 |         void slot_vi(int) {} | 
| 4812 |         void slot_vi_noexcept() noexcept {} | 
| 4813 |         void slot_vii(int, int) {} | 
| 4814 |         void slot_viii(int, int, int) {} | 
| 4815 |         int slot_i() { return 0; } | 
| 4816 |         int slot_i_noexcept() noexcept { return 0; } | 
| 4817 |         int slot_ii(int) { return 0; } | 
| 4818 |         int slot_iii(int, int) { return 0; } | 
| 4819 |         int slot_iiii(int, int, int) { return 0; } | 
| 4820 |         void slot_vRi(int &) {} | 
| 4821 |         void slot_vs(short) {} | 
| 4822 |         void slot_vRs(short&) {} | 
| 4823 |    /*     #ifdef Q_COMPILER_RVALUE_REFS | 
| 4824 |         void slot_vOi(int &&) {} | 
| 4825 |         void slot_vOs(short &&) {} | 
| 4826 |         #endif*/ | 
| 4827 |         void slot_vPFvvE(fptr) {} | 
| 4828 |  | 
| 4829 |         void const_slot_v() const {}; | 
| 4830 |         void const_slot_v_noexcept() const noexcept {} | 
| 4831 |         void const_slot_vi(int) const {}; | 
| 4832 |         void const_slot_vi_noexcept(int) const noexcept {} | 
| 4833 |  | 
| 4834 |         static void static_slot_v() {} | 
| 4835 |         static void static_slot_v_noexcept() noexcept {} | 
| 4836 |         static void static_slot_vi(int) {} | 
| 4837 |         static void static_slot_vi_noexcept(int) noexcept {} | 
| 4838 |         static void static_slot_vii(int, int) {} | 
| 4839 |         static void static_slot_viii(int, int, int) {} | 
| 4840 |         static int static_slot_i() { return 0; } | 
| 4841 |         static int static_slot_i_noexcept() noexcept { return 0; } | 
| 4842 |         static int static_slot_ii(int) { return 0; } | 
| 4843 |         static int static_slot_iii(int, int) { return 0; } | 
| 4844 |         static int static_slot_iiii(int, int, int) { return 0; } | 
| 4845 |         static void static_slot_vRi(int &) {} | 
| 4846 |         static void static_slot_vs(short) {} | 
| 4847 |         static void static_slot_vRs(short&) {} | 
| 4848 | /*        #if defined(Q_COMPILER_RVALUE_REFS) || defined(QT_ENABLE_CXX0X) | 
| 4849 |         static void static_slot_vOi(int &&) {} | 
| 4850 |         static void static_slot_vOs(short &&) {} | 
| 4851 |         #endif*/ | 
| 4852 |         static void static_slot_vPFvvE(fptr) {} | 
| 4853 |  | 
| 4854 |         void slot_vcRQObject(const QObject &) {} | 
| 4855 |         void slot_vRQObject(QObject &) {} | 
| 4856 |  | 
| 4857 |     signals: | 
| 4858 |         void signal_v(); | 
| 4859 |         void signal_vi(int); | 
| 4860 |         void signal_vii(int, int); | 
| 4861 |         void signal_viii(int, int, int); | 
| 4862 |         void signal_vRi(int &); | 
| 4863 |         void signal_vs(short); | 
| 4864 |         void signal_vRs(short &); | 
| 4865 | /*        #if defined(Q_COMPILER_RVALUE_REFS) || defined(QT_ENABLE_CXX0X) | 
| 4866 |         void signal_vOi(int &&); | 
| 4867 |         void signal_vOs(short &&); | 
| 4868 |         #endif*/ | 
| 4869 |         void signal_vPFvvE(fptr); | 
| 4870 |  | 
| 4871 |         void const_signal_v() const; | 
| 4872 |         void const_signal_vi(int) const; | 
| 4873 |  | 
| 4874 |         void signal_vcRQObject(const QObject &); | 
| 4875 |         void signal_vRQObject(QObject &); | 
| 4876 |  | 
| 4877 |         void signal(short&, short, long long, short); | 
| 4878 |         void otherSignal(const char *); | 
| 4879 | }; | 
| 4880 |  | 
| 4881 | void tst_QObject::connectCxx0xTypeMatching() | 
| 4882 | { | 
| 4883 |     // this is just about connecting the signals to the slots | 
| 4884 |     // if this fails, this will be a compiler failure | 
| 4885 |     typedef LotsOfSignalsAndSlots Foo; | 
| 4886 |     Foo obj; | 
| 4887 |  | 
| 4888 |     // member connects | 
| 4889 |     QObject::connect(sender: &obj, signal: &Foo::signal_v, receiver: &obj, slot: &Foo::slot_v); | 
| 4890 |     QObject::connect(sender: &obj, signal: &Foo::signal_v, receiver: &obj, slot: &Foo::slot_i); | 
| 4891 |  | 
| 4892 |     QObject::connect(sender: &obj, signal: &Foo::signal_vi, receiver: &obj, slot: &Foo::slot_v); | 
| 4893 |     QObject::connect(sender: &obj, signal: &Foo::signal_vi, receiver: &obj, slot: &Foo::slot_i); | 
| 4894 |     QObject::connect(sender: &obj, signal: &Foo::signal_vi, receiver: &obj, slot: &Foo::slot_vi); | 
| 4895 |     QObject::connect(sender: &obj, signal: &Foo::signal_vi, receiver: &obj, slot: &Foo::slot_ii); | 
| 4896 |  | 
| 4897 |     QObject::connect(sender: &obj, signal: &Foo::signal_vii, receiver: &obj, slot: &Foo::slot_v); | 
| 4898 |     QObject::connect(sender: &obj, signal: &Foo::signal_vii, receiver: &obj, slot: &Foo::slot_i); | 
| 4899 |     QObject::connect(sender: &obj, signal: &Foo::signal_vii, receiver: &obj, slot: &Foo::slot_vi); | 
| 4900 |     QObject::connect(sender: &obj, signal: &Foo::signal_vii, receiver: &obj, slot: &Foo::slot_ii); | 
| 4901 |     QObject::connect(sender: &obj, signal: &Foo::signal_vii, receiver: &obj, slot: &Foo::slot_vii); | 
| 4902 |     QObject::connect(sender: &obj, signal: &Foo::signal_vii, receiver: &obj, slot: &Foo::slot_iii); | 
| 4903 |  | 
| 4904 |     QObject::connect(sender: &obj, signal: &Foo::signal_viii, receiver: &obj, slot: &Foo::slot_v); | 
| 4905 |     QObject::connect(sender: &obj, signal: &Foo::signal_viii, receiver: &obj, slot: &Foo::slot_i); | 
| 4906 |     QObject::connect(sender: &obj, signal: &Foo::signal_viii, receiver: &obj, slot: &Foo::slot_vi); | 
| 4907 |     QObject::connect(sender: &obj, signal: &Foo::signal_viii, receiver: &obj, slot: &Foo::slot_ii); | 
| 4908 |     QObject::connect(sender: &obj, signal: &Foo::signal_viii, receiver: &obj, slot: &Foo::slot_vii); | 
| 4909 |     QObject::connect(sender: &obj, signal: &Foo::signal_viii, receiver: &obj, slot: &Foo::slot_iii); | 
| 4910 |     QObject::connect(sender: &obj, signal: &Foo::signal_viii, receiver: &obj, slot: &Foo::slot_viii); | 
| 4911 |     QObject::connect(sender: &obj, signal: &Foo::signal_viii, receiver: &obj, slot: &Foo::slot_iiii); | 
| 4912 |  | 
| 4913 |     QObject::connect(sender: &obj, signal: &Foo::signal_vi, receiver: &obj, slot: &Foo::slot_vi); // repeated from above | 
| 4914 |     QObject::connect(sender: &obj, signal: &Foo::signal_vRi, receiver: &obj, slot: &Foo::slot_vi); | 
| 4915 |     QObject::connect(sender: &obj, signal: &Foo::signal_vRi, receiver: &obj, slot: &Foo::slot_vRi); | 
| 4916 | /*#if defined(Q_COMPILER_RVALUE_REFS) || defined(QT_ENABLE_CXX0X) | 
| 4917 |     QObject::connect(&obj, &Foo::signal_vOi, &obj, &Foo::slot_vi); | 
| 4918 |     QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::slot_vOi); | 
| 4919 |     QObject::connect(&obj, &Foo::signal_vRi, &obj, &Foo::slot_vOi); | 
| 4920 |     QObject::connect(&obj, &Foo::signal_vOi, &obj, &Foo::slot_vOi); | 
| 4921 | #endif*/ | 
| 4922 |     // these are not supposed to compile: | 
| 4923 |     //QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::slot_vRi); | 
| 4924 |     //QObject::connect(&obj, &Foo::signal_vOi, &obj, &Foo::slot_vRi); | 
| 4925 |  | 
| 4926 |     QObject::connect(sender: &obj, signal: &Foo::signal_vs, receiver: &obj, slot: &Foo::slot_vi); | 
| 4927 |     QObject::connect(sender: &obj, signal: &Foo::signal_vRs, receiver: &obj, slot: &Foo::slot_vi); | 
| 4928 | /*#if defined(Q_COMPILER_RVALUE_REFS) || defined(QT_ENABLE_CXX0X) | 
| 4929 |     QObject::connect(&obj, &Foo::signal_vOs, &obj, &Foo::slot_vi); | 
| 4930 |     QObject::connect(&obj, &Foo::signal_vRs, &obj, &Foo::slot_vOi); | 
| 4931 |     QObject::connect(&obj, &Foo::signal_vOs, &obj, &Foo::slot_vOi); | 
| 4932 |     // these are not supposed to compile: | 
| 4933 |     //QObject::connect(&obj, &Foo::signal_vOs, &obj, &Foo::slot_vRi); | 
| 4934 |     //QObject::connect(&obj, &Foo::signal_vRs, &obj, &Foo::slot_vRi); | 
| 4935 | #endif*/ | 
| 4936 |  | 
| 4937 |     QObject::connect(sender: &obj, signal: &Foo::signal_vPFvvE, receiver: &obj, slot: &Foo::slot_v); | 
| 4938 |     QObject::connect(sender: &obj, signal: &Foo::signal_vPFvvE, receiver: &obj, slot: &Foo::slot_i); | 
| 4939 |     QObject::connect(sender: &obj, signal: &Foo::signal_vPFvvE, receiver: &obj, slot: &Foo::slot_vPFvvE); | 
| 4940 |  | 
| 4941 |     QObject::connect(sender: &obj, signal: &Foo::signal_v, slot: &Foo::static_slot_v); | 
| 4942 |     QObject::connect(sender: &obj, signal: &Foo::signal_v, slot: &Foo::static_slot_i); | 
| 4943 |  | 
| 4944 |     QObject::connect(sender: &obj, signal: &Foo::signal_vi, slot: &Foo::static_slot_v); | 
| 4945 |     QObject::connect(sender: &obj, signal: &Foo::signal_vi, slot: &Foo::static_slot_i); | 
| 4946 |     QObject::connect(sender: &obj, signal: &Foo::signal_vi, slot: &Foo::static_slot_vi); | 
| 4947 |     QObject::connect(sender: &obj, signal: &Foo::signal_vi, slot: &Foo::static_slot_ii); | 
| 4948 |  | 
| 4949 |     QObject::connect(sender: &obj, signal: &Foo::signal_vii, slot: &Foo::static_slot_v); | 
| 4950 |     QObject::connect(sender: &obj, signal: &Foo::signal_vii, slot: &Foo::static_slot_i); | 
| 4951 |     QObject::connect(sender: &obj, signal: &Foo::signal_vii, slot: &Foo::static_slot_vi); | 
| 4952 |     QObject::connect(sender: &obj, signal: &Foo::signal_vii, slot: &Foo::static_slot_ii); | 
| 4953 |     QObject::connect(sender: &obj, signal: &Foo::signal_vii, slot: &Foo::static_slot_vii); | 
| 4954 |     QObject::connect(sender: &obj, signal: &Foo::signal_vii, slot: &Foo::static_slot_iii); | 
| 4955 |  | 
| 4956 |     QObject::connect(sender: &obj, signal: &Foo::signal_viii, slot: &Foo::static_slot_v); | 
| 4957 |     QObject::connect(sender: &obj, signal: &Foo::signal_viii, slot: &Foo::static_slot_i); | 
| 4958 |     QObject::connect(sender: &obj, signal: &Foo::signal_viii, slot: &Foo::static_slot_vi); | 
| 4959 |     QObject::connect(sender: &obj, signal: &Foo::signal_viii, slot: &Foo::static_slot_ii); | 
| 4960 |     QObject::connect(sender: &obj, signal: &Foo::signal_viii, slot: &Foo::static_slot_vii); | 
| 4961 |     QObject::connect(sender: &obj, signal: &Foo::signal_viii, slot: &Foo::static_slot_iii); | 
| 4962 |     QObject::connect(sender: &obj, signal: &Foo::signal_viii, slot: &Foo::static_slot_viii); | 
| 4963 |     QObject::connect(sender: &obj, signal: &Foo::signal_viii, slot: &Foo::static_slot_iiii); | 
| 4964 |  | 
| 4965 | /*#if defined(Q_COMPILER_RVALUE_REFS) && defined(QT_ENABLE_CXX0X) | 
| 4966 |     QObject::connect(&obj, &Foo::signal_vi, &Foo::static_slot_vOi); | 
| 4967 |     QObject::connect(&obj, &Foo::signal_vRi, &Foo::static_slot_vi); | 
| 4968 |     QObject::connect(&obj, &Foo::signal_vRi, &Foo::static_slot_vRi); | 
| 4969 |     QObject::connect(&obj, &Foo::signal_vRi, &Foo::static_slot_vOi); | 
| 4970 |     QObject::connect(&obj, &Foo::signal_vOi, &Foo::static_slot_vi); | 
| 4971 |     QObject::connect(&obj, &Foo::signal_vOi, &Foo::static_slot_vOi); | 
| 4972 |     //QObject::connect(&obj, &Foo::signal_vi, &Foo::static_slot_vRi); | 
| 4973 |     //QObject::connect(&obj, &Foo::signal_vOi, &Foo::static_slot_vRi); | 
| 4974 | #endif*/ | 
| 4975 |  | 
| 4976 |     QObject::connect(sender: &obj, signal: &Foo::signal_vs, slot: &Foo::static_slot_vi); | 
| 4977 |     QObject::connect(sender: &obj, signal: &Foo::signal_vRs, slot: &Foo::static_slot_vi); | 
| 4978 | /*#if defined(Q_COMPILER_RVALUE_REFS) && defined(QT_ENABLE_CXX0X) | 
| 4979 |     QObject::connect(&obj, &Foo::signal_vOs, &Foo::static_slot_vi); | 
| 4980 |     QObject::connect(&obj, &Foo::signal_vRs, &Foo::static_slot_vOi); | 
| 4981 |     QObject::connect(&obj, &Foo::signal_vOs, &Foo::static_slot_vOi); | 
| 4982 |     //QObject::connect(&obj, &Foo::signal_vOs, &Foo::static_slot_vRi); | 
| 4983 |     //QObject::connect(&obj, &Foo::signal_vRs, &Foo::static_slot_vRi); | 
| 4984 | #endif*/ | 
| 4985 |     QObject::connect(sender: &obj, signal: &Foo::signal_vPFvvE, slot: &Foo::static_slot_v); | 
| 4986 |     QObject::connect(sender: &obj, signal: &Foo::signal_vPFvvE, slot: &Foo::static_slot_i); | 
| 4987 |     QObject::connect(sender: &obj, signal: &Foo::signal_vPFvvE, slot: &Foo::static_slot_vPFvvE); | 
| 4988 |  | 
| 4989 |     QVERIFY(QObject::connect(&obj, &Foo::const_signal_v, &obj, &Foo::const_slot_v)); | 
| 4990 |     QVERIFY(QObject::connect(&obj, &Foo::const_signal_vi, &obj, &Foo::const_slot_v)); | 
| 4991 |     QVERIFY(QObject::connect(&obj, &Foo::const_signal_vi, &obj, &Foo::slot_vi)); | 
| 4992 |     QVERIFY(QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::const_slot_vi)); | 
| 4993 |     QVERIFY(QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::const_slot_v)); | 
| 4994 |  | 
| 4995 |     QVERIFY(QObject::connect(&obj, &Foo::signal_vcRQObject, &obj, &Foo::slot_vcRQObject)); | 
| 4996 |     QVERIFY(QObject::connect(&obj, &Foo::signal_vRQObject, &obj, &Foo::slot_vRQObject)); | 
| 4997 |     QVERIFY(QObject::connect(&obj, &Foo::signal_vRQObject, &obj, &Foo::slot_vcRQObject)); | 
| 4998 |     // QVERIFY(QObject::connect(&obj, &Foo::signal_vcRQObject, &obj, &Foo::slot_vRQObject)); // Should be an error  (const& -> &) | 
| 4999 |  | 
| 5000 |     QVERIFY(QObject::connect(&obj, &Foo::signal_vRi, &obj, &Foo::slot_vs)); | 
| 5001 |  | 
| 5002 | } | 
| 5003 |  | 
| 5004 | void receiverFunction_noexcept() noexcept {} | 
| 5005 | struct Functor_noexcept { void operator()() noexcept {} }; | 
| 5006 | void tst_QObject::connectCxx17Noexcept() | 
| 5007 | { | 
| 5008 |     // this is about connecting signals to slots with the noexcept qualifier | 
| 5009 |     // as semantics changed due to http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0012r1.html | 
| 5010 |     typedef LotsOfSignalsAndSlots Foo; | 
| 5011 |     Foo obj; | 
| 5012 |  | 
| 5013 |     QObject::connect(sender: &obj, signal: &Foo::signal_v, receiver: &obj, slot: &Foo::slot_v_noexcept); | 
| 5014 |     QObject::connect(sender: &obj, signal: &Foo::signal_v, receiver: &obj, slot: &Foo::slot_i_noexcept); | 
| 5015 |     QObject::connect(sender: &obj, signal: &Foo::signal_v, receiver: &obj, slot: &Foo::slot_vi_noexcept); | 
| 5016 |  | 
| 5017 |     QObject::connect(sender: &obj, signal: &Foo::signal_vii, slot: &Foo::static_slot_v_noexcept); | 
| 5018 |     QObject::connect(sender: &obj, signal: &Foo::signal_vii, slot: &Foo::static_slot_i_noexcept); | 
| 5019 |     QObject::connect(sender: &obj, signal: &Foo::signal_vii, slot: &Foo::static_slot_vi_noexcept); | 
| 5020 |  | 
| 5021 |     QVERIFY(QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::const_slot_vi_noexcept)); | 
| 5022 |     QVERIFY(QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::const_slot_v_noexcept)); | 
| 5023 |  | 
| 5024 |     QObject::connect(sender: &obj, signal: &Foo::signal_v, slot: receiverFunction_noexcept); | 
| 5025 |  | 
| 5026 |     Functor_noexcept fn; | 
| 5027 |     QObject::connect(sender: &obj, signal: &Foo::signal_v, slot: fn); | 
| 5028 | } | 
| 5029 |  | 
| 5030 | class StringVariant : public QObject | 
| 5031 | { Q_OBJECT | 
| 5032 | signals: | 
| 5033 |     void stringSignal(const QString &str); | 
| 5034 | public slots: | 
| 5035 |     void variantSlot(const QVariant &v) { var = v; } | 
| 5036 | public: | 
| 5037 |     QVariant var; | 
| 5038 |     friend class tst_QObject; | 
| 5039 | }; | 
| 5040 |  | 
| 5041 | struct Functor { | 
| 5042 |     QVariant *var; | 
| 5043 |     void operator() (const QVariant &v) { | 
| 5044 |         *var = v; | 
| 5045 |     } | 
| 5046 | }; | 
| 5047 |  | 
| 5048 | void tst_QObject::connectConvert() | 
| 5049 | { | 
| 5050 |     StringVariant obj; | 
| 5051 |     QVERIFY(connect(&obj, &StringVariant::stringSignal, &obj, &StringVariant::variantSlot)); | 
| 5052 |     QString s = QString::fromLatin1(str: "Hello World" ); | 
| 5053 |     emit obj.stringSignal(str: s); | 
| 5054 |     QCOMPARE(obj.var.toString(), s); | 
| 5055 |     QVERIFY(obj.var.toString().isSharedWith(s)); | 
| 5056 |  | 
| 5057 |     QVariant var; | 
| 5058 |     Functor f; | 
| 5059 |     f.var = &var; | 
| 5060 |     QVERIFY(connect(&obj, &StringVariant::stringSignal, f)); | 
| 5061 |     s = QString::fromLatin1(str: "GoodBye" ); | 
| 5062 |     emit obj.stringSignal(str: s); | 
| 5063 |     QCOMPARE(obj.var.toString(), s); | 
| 5064 |     QVERIFY(obj.var.toString().isSharedWith(s)); | 
| 5065 |     QCOMPARE(var, obj.var); | 
| 5066 | } | 
| 5067 |  | 
| 5068 | class ConnectWithReferenceObject : public QObject { | 
| 5069 |     Q_OBJECT | 
| 5070 |     friend class tst_QObject; | 
| 5071 | signals: | 
| 5072 |     void boolRef(bool &, bool); | 
| 5073 |     void stringRef(QString &, const QString &); | 
| 5074 |     void boolPtr(bool *, bool); | 
| 5075 |     void stringPtr(QString *, const QString &); | 
| 5076 | public slots: | 
| 5077 |     void boolRefSlot(bool &b1, bool b2) {  b1 = b2; } | 
| 5078 |     void stringRefSlot(QString &s1, const QString &s2) {  s1 = s2; } | 
| 5079 |     void boolPtrSlot(bool *b1, bool b2) {  *b1 = b2; } | 
| 5080 |     void stringPtrSlot(QString *s1, const QString &s2) {  *s1 = s2; } | 
| 5081 |  | 
| 5082 |     void stringSlot1(QString s) { last = s; } | 
| 5083 |     void stringSlot2(const QString &s) { last = s; } | 
| 5084 |     void stringSlot3(QString &s) { last = s; } | 
| 5085 | public: | 
| 5086 |     QString last; | 
| 5087 | }; | 
| 5088 |  | 
| 5089 | void tst_QObject::connectWithReference() | 
| 5090 | { | 
| 5091 |     ConnectWithReferenceObject o; | 
| 5092 |     bool b1 = true; | 
| 5093 |     QString s1 = QString::fromLatin1(str: "str1" ); | 
| 5094 |     const QString s2 = QString::fromLatin1(str: "str2" ); | 
| 5095 |     const QString s3 = QString::fromLatin1(str: "str3" ); | 
| 5096 |     o.boolRef(b1, false); | 
| 5097 |     o.stringRef(s1, s2); | 
| 5098 |     QCOMPARE(b1, true); | 
| 5099 |     QCOMPARE(s1, QString::fromLatin1("str1" )); | 
| 5100 |     o.boolPtr(&b1, false); | 
| 5101 |     o.stringPtr(&s1, s2); | 
| 5102 |     QCOMPARE(b1, true); | 
| 5103 |     QCOMPARE(s1, QString::fromLatin1("str1" )); | 
| 5104 |  | 
| 5105 |     QVERIFY(connect(&o, &ConnectWithReferenceObject::boolRef, &o, &ConnectWithReferenceObject::boolRefSlot)); | 
| 5106 |     QVERIFY(connect(&o, &ConnectWithReferenceObject::stringRef, &o, &ConnectWithReferenceObject::stringRefSlot)); | 
| 5107 |     QVERIFY(connect(&o, &ConnectWithReferenceObject::boolPtr, &o, &ConnectWithReferenceObject::boolPtrSlot)); | 
| 5108 |     QVERIFY(connect(&o, &ConnectWithReferenceObject::stringPtr, &o, &ConnectWithReferenceObject::stringPtrSlot)); | 
| 5109 |     o.boolRef(b1, false); | 
| 5110 |     o.stringRef(s1, s2); | 
| 5111 |     QCOMPARE(b1, false); | 
| 5112 |     QCOMPARE(s1, QString::fromLatin1("str2" )); | 
| 5113 |  | 
| 5114 |     o.boolPtr(&b1, true); | 
| 5115 |     o.stringPtr(&s1, s3); | 
| 5116 |     QCOMPARE(b1, true); | 
| 5117 |     QCOMPARE(s1, QString::fromLatin1("str3" )); | 
| 5118 |  | 
| 5119 |     { | 
| 5120 |         ConnectWithReferenceObject o2; | 
| 5121 |         QVERIFY(connect(&o2, &ConnectWithReferenceObject::stringRef, &o2, &ConnectWithReferenceObject::stringSlot1)); | 
| 5122 |         o2.stringRef(s1, s2); | 
| 5123 |         QCOMPARE(s1, s3); | 
| 5124 |         QCOMPARE(o2.last, s3); | 
| 5125 |     } | 
| 5126 |     { | 
| 5127 |         ConnectWithReferenceObject o2; | 
| 5128 |         QVERIFY(connect(&o2, &ConnectWithReferenceObject::stringRef, &o2, &ConnectWithReferenceObject::stringSlot2)); | 
| 5129 |         o2.stringRef(s1, s2); | 
| 5130 |         QCOMPARE(s1, s3); | 
| 5131 |         QCOMPARE(o2.last, s3); | 
| 5132 |     } | 
| 5133 |     { | 
| 5134 |         ConnectWithReferenceObject o2; | 
| 5135 |         QVERIFY(connect(&o2, &ConnectWithReferenceObject::stringRef, &o2, &ConnectWithReferenceObject::stringSlot3)); | 
| 5136 |         o2.stringRef(s1, s2); | 
| 5137 |         QCOMPARE(s1, s3); | 
| 5138 |         QCOMPARE(o2.last, s3); | 
| 5139 |     } | 
| 5140 | } | 
| 5141 |  | 
| 5142 | class ManyArgumentObject : public QObject { | 
| 5143 |     Q_OBJECT | 
| 5144 | signals: | 
| 5145 |     void signal1(const QString &); | 
| 5146 |     void signal2(const QString &, const QString &); | 
| 5147 |     void signal3(const QString &, const QString &, const QString &); | 
| 5148 |     void signal4(const QString &, const QString &, const QString &, const QString&); | 
| 5149 |     void signal5(const QString &, const QString &, const QString &, const QString&, const QString&); | 
| 5150 |     void signal6(const QString &, const QString &, const QString &, const QString&, const QString&, const QString&); | 
| 5151 |  | 
| 5152 | public slots: | 
| 5153 | #define MANYARGUMENT_COMPARE(L) QCOMPARE(L, QString(#L)) | 
| 5154 |     void slot1(const QString &a) { | 
| 5155 |         MANYARGUMENT_COMPARE(a); | 
| 5156 |         count++; | 
| 5157 |     } | 
| 5158 |     void slot2(const QString &a, const QString &b) { | 
| 5159 |         MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); | 
| 5160 |         count++; | 
| 5161 |     } | 
| 5162 |     void slot3(const QString &a, const QString &b, const QString &c) { | 
| 5163 |         MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c); | 
| 5164 |         count++; | 
| 5165 |     } | 
| 5166 |     void slot4(const QString &a, const QString &b, const QString &c, const QString&d) { | 
| 5167 |         MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c); | 
| 5168 |         MANYARGUMENT_COMPARE(d); | 
| 5169 |         count++; | 
| 5170 |     } | 
| 5171 |     void slot5(const QString &a, const QString &b, const QString &c, const QString&d, const QString&e) { | 
| 5172 |         MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c); | 
| 5173 |         MANYARGUMENT_COMPARE(d); MANYARGUMENT_COMPARE(e); | 
| 5174 |         count++; | 
| 5175 |     } | 
| 5176 |     void slot6(const QString &a, const QString &b, const QString &c, const QString&d, const QString&e, const QString&f) { | 
| 5177 |         MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c); | 
| 5178 |         MANYARGUMENT_COMPARE(d); MANYARGUMENT_COMPARE(e); MANYARGUMENT_COMPARE(f); | 
| 5179 |         count++; | 
| 5180 |     } | 
| 5181 | public: | 
| 5182 |     int count; | 
| 5183 |  | 
| 5184 | }; | 
| 5185 |  | 
| 5186 | namespace ManyArgumentNamespace { | 
| 5187 |     int count; | 
| 5188 |     void slot1(const QString &a) { | 
| 5189 |         MANYARGUMENT_COMPARE(a); | 
| 5190 |         count++; | 
| 5191 |     } | 
| 5192 |     void slot2(const QString &a, const QString &b) { | 
| 5193 |         MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); | 
| 5194 |         count++; | 
| 5195 |     } | 
| 5196 |     void slot3(const QString &a, const QString &b, const QString &c) { | 
| 5197 |         MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c); | 
| 5198 |         count++; | 
| 5199 |     } | 
| 5200 |     void slot4(const QString &a, const QString &b, const QString &c, const QString&d) { | 
| 5201 |         MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c); | 
| 5202 |         MANYARGUMENT_COMPARE(d); | 
| 5203 |         count++; | 
| 5204 |     } | 
| 5205 |     void slot5(const QString &a, const QString &b, const QString &c, const QString&d, const QString&e) { | 
| 5206 |         MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c); | 
| 5207 |         MANYARGUMENT_COMPARE(d); MANYARGUMENT_COMPARE(e); | 
| 5208 |         count++; | 
| 5209 |     } | 
| 5210 |     void slot6(const QString &a, const QString &b, const QString &c, const QString&d, const QString&e, const QString&f) { | 
| 5211 |         MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c); | 
| 5212 |         MANYARGUMENT_COMPARE(d); MANYARGUMENT_COMPARE(e); MANYARGUMENT_COMPARE(f); | 
| 5213 |         count++; | 
| 5214 |     } | 
| 5215 |  | 
| 5216 |     struct Funct1 { | 
| 5217 |         void operator()(const QString &a) { | 
| 5218 |             MANYARGUMENT_COMPARE(a); | 
| 5219 |             count++; | 
| 5220 |         } | 
| 5221 |     }; | 
| 5222 |  | 
| 5223 |     struct Funct2 { | 
| 5224 |         void operator()(const QString &a, const QString &b) { | 
| 5225 |             MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); | 
| 5226 |             count++; | 
| 5227 |         } | 
| 5228 |     }; | 
| 5229 |  | 
| 5230 |     struct Funct3 { | 
| 5231 |         void operator()(const QString &a, const QString &b, const QString &c) { | 
| 5232 |             MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c); | 
| 5233 |             count++; | 
| 5234 |         } | 
| 5235 |     }; | 
| 5236 |  | 
| 5237 |     struct Funct4 { | 
| 5238 |         void operator()(const QString &a, const QString &b, const QString &c, const QString&d) { | 
| 5239 |             MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c); | 
| 5240 |             MANYARGUMENT_COMPARE(d); | 
| 5241 |             count++; | 
| 5242 |         } | 
| 5243 |     }; | 
| 5244 |  | 
| 5245 |     struct Funct5 { | 
| 5246 |         void operator()(const QString &a, const QString &b, const QString &c, const QString&d, const QString&e) { | 
| 5247 |             MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c); | 
| 5248 |             MANYARGUMENT_COMPARE(d); MANYARGUMENT_COMPARE(e); | 
| 5249 |             count++; | 
| 5250 |         } | 
| 5251 |     }; | 
| 5252 |  | 
| 5253 |     struct Funct6 { | 
| 5254 |         void operator()(const QString &a, const QString &b, const QString &c, const QString&d, const QString&e, const QString&f) { | 
| 5255 |             MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c); | 
| 5256 |             MANYARGUMENT_COMPARE(d); MANYARGUMENT_COMPARE(e); MANYARGUMENT_COMPARE(f); | 
| 5257 |             count++; | 
| 5258 |         } | 
| 5259 |     }; | 
| 5260 | } | 
| 5261 |  | 
| 5262 | void tst_QObject::connectManyArguments() | 
| 5263 | { | 
| 5264 |     ManyArgumentObject ob; | 
| 5265 |     ob.count = 0; | 
| 5266 |     ManyArgumentNamespace::count = 0; | 
| 5267 |     connect(sender: &ob, signal: &ManyArgumentObject::signal1, receiver: &ob, slot: &ManyArgumentObject::slot1); | 
| 5268 |     connect(sender: &ob, signal: &ManyArgumentObject::signal2, receiver: &ob, slot: &ManyArgumentObject::slot2); | 
| 5269 |     connect(sender: &ob, signal: &ManyArgumentObject::signal3, receiver: &ob, slot: &ManyArgumentObject::slot3); | 
| 5270 |     connect(sender: &ob, signal: &ManyArgumentObject::signal4, receiver: &ob, slot: &ManyArgumentObject::slot4); | 
| 5271 |     connect(sender: &ob, signal: &ManyArgumentObject::signal5, receiver: &ob, slot: &ManyArgumentObject::slot5); | 
| 5272 |     connect(sender: &ob, signal: &ManyArgumentObject::signal6, receiver: &ob, slot: &ManyArgumentObject::slot6); | 
| 5273 |     connect(sender: &ob, signal: &ManyArgumentObject::signal1, slot: ManyArgumentNamespace::slot1); | 
| 5274 |     connect(sender: &ob, signal: &ManyArgumentObject::signal2, slot: ManyArgumentNamespace::slot2); | 
| 5275 |     connect(sender: &ob, signal: &ManyArgumentObject::signal3, slot: ManyArgumentNamespace::slot3); | 
| 5276 |     connect(sender: &ob, signal: &ManyArgumentObject::signal4, slot: ManyArgumentNamespace::slot4); | 
| 5277 |     connect(sender: &ob, signal: &ManyArgumentObject::signal5, slot: ManyArgumentNamespace::slot5); | 
| 5278 |     connect(sender: &ob, signal: &ManyArgumentObject::signal6, slot: ManyArgumentNamespace::slot6); | 
| 5279 |  | 
| 5280 |  | 
| 5281 |     connect(sender: &ob, signal: &ManyArgumentObject::signal6, receiver: &ob, slot: &ManyArgumentObject::signal5); | 
| 5282 |     connect(sender: &ob, signal: &ManyArgumentObject::signal5, receiver: &ob, slot: &ManyArgumentObject::signal4); | 
| 5283 |     connect(sender: &ob, signal: &ManyArgumentObject::signal4, receiver: &ob, slot: &ManyArgumentObject::signal3); | 
| 5284 |     connect(sender: &ob, signal: &ManyArgumentObject::signal3, receiver: &ob, slot: &ManyArgumentObject::signal2); | 
| 5285 |     connect(sender: &ob, signal: &ManyArgumentObject::signal2, receiver: &ob, slot: &ManyArgumentObject::signal1); | 
| 5286 |  | 
| 5287 |     emit ob.signal6("a" , "b" , "c" , "d" , "e" , "f" ); | 
| 5288 |     QCOMPARE(ob.count, 6); | 
| 5289 |     QCOMPARE(ManyArgumentNamespace::count, 6); | 
| 5290 |  | 
| 5291 |  | 
| 5292 |     ManyArgumentObject ob2; | 
| 5293 |     ob2.count = 0; | 
| 5294 |     ManyArgumentNamespace::count = 0; | 
| 5295 |     connect(sender: &ob2, signal: &ManyArgumentObject::signal6, receiver: &ob2, slot: &ManyArgumentObject::slot1); | 
| 5296 |     connect(sender: &ob2, signal: &ManyArgumentObject::signal6, receiver: &ob2, slot: &ManyArgumentObject::slot2); | 
| 5297 |     connect(sender: &ob2, signal: &ManyArgumentObject::signal6, receiver: &ob2, slot: &ManyArgumentObject::slot3); | 
| 5298 |     connect(sender: &ob2, signal: &ManyArgumentObject::signal6, receiver: &ob2, slot: &ManyArgumentObject::slot4); | 
| 5299 |     connect(sender: &ob2, signal: &ManyArgumentObject::signal6, receiver: &ob2, slot: &ManyArgumentObject::slot5); | 
| 5300 |     connect(sender: &ob2, signal: &ManyArgumentObject::signal6, receiver: &ob2, slot: &ManyArgumentObject::slot6); | 
| 5301 |     connect(sender: &ob2, signal: &ManyArgumentObject::signal6, slot: ManyArgumentNamespace::slot1); | 
| 5302 |     connect(sender: &ob2, signal: &ManyArgumentObject::signal6, slot: ManyArgumentNamespace::slot2); | 
| 5303 |     connect(sender: &ob2, signal: &ManyArgumentObject::signal6, slot: ManyArgumentNamespace::slot3); | 
| 5304 |     connect(sender: &ob2, signal: &ManyArgumentObject::signal6, slot: ManyArgumentNamespace::slot4); | 
| 5305 |     connect(sender: &ob2, signal: &ManyArgumentObject::signal6, slot: ManyArgumentNamespace::slot5); | 
| 5306 |     connect(sender: &ob2, signal: &ManyArgumentObject::signal6, slot: ManyArgumentNamespace::slot6); | 
| 5307 |     connect(sender: &ob2, signal: &ManyArgumentObject::signal6, slot: ManyArgumentNamespace::Funct1()); | 
| 5308 |     connect(sender: &ob2, signal: &ManyArgumentObject::signal6, slot: ManyArgumentNamespace::Funct2()); | 
| 5309 |     connect(sender: &ob2, signal: &ManyArgumentObject::signal6, slot: ManyArgumentNamespace::Funct3()); | 
| 5310 |     connect(sender: &ob2, signal: &ManyArgumentObject::signal6, slot: ManyArgumentNamespace::Funct4()); | 
| 5311 |     connect(sender: &ob2, signal: &ManyArgumentObject::signal6, slot: ManyArgumentNamespace::Funct5()); | 
| 5312 |     connect(sender: &ob2, signal: &ManyArgumentObject::signal6, slot: ManyArgumentNamespace::Funct6()); | 
| 5313 |  | 
| 5314 |     emit ob2.signal6("a" , "b" , "c" , "d" , "e" , "f" ); | 
| 5315 |     QCOMPARE(ob2.count, 6); | 
| 5316 |     QCOMPARE(ManyArgumentNamespace::count, 12); | 
| 5317 | } | 
| 5318 |  | 
| 5319 | class ForwardDeclared; | 
| 5320 |  | 
| 5321 | class ForwardDeclareArguments : public QObject | 
| 5322 | { | 
| 5323 |     Q_OBJECT | 
| 5324 | signals: | 
| 5325 |     void mySignal(const ForwardDeclared&); | 
| 5326 | public slots: | 
| 5327 |     void mySlot(const ForwardDeclared&) {} | 
| 5328 | }; | 
| 5329 |  | 
| 5330 | void tst_QObject::connectForwardDeclare() | 
| 5331 | { | 
| 5332 |     ForwardDeclareArguments ob; | 
| 5333 |     // it should compile | 
| 5334 |     QVERIFY(connect(&ob, &ForwardDeclareArguments::mySignal, &ob, &ForwardDeclareArguments::mySlot, Qt::QueuedConnection)); | 
| 5335 | } | 
| 5336 |  | 
| 5337 | class NoDefaultConstructor | 
| 5338 | { | 
| 5339 |     Q_GADGET | 
| 5340 | public: | 
| 5341 |     NoDefaultConstructor(int) {} | 
| 5342 | }; | 
| 5343 |  | 
| 5344 | class NoDefaultContructorArguments : public QObject | 
| 5345 | { | 
| 5346 |     Q_OBJECT | 
| 5347 | signals: | 
| 5348 |     void mySignal(const NoDefaultConstructor&); | 
| 5349 | public slots: | 
| 5350 |     void mySlot(const NoDefaultConstructor&) {} | 
| 5351 | }; | 
| 5352 |  | 
| 5353 | void tst_QObject::connectNoDefaultConstructorArg() | 
| 5354 | { | 
| 5355 |     NoDefaultContructorArguments ob; | 
| 5356 |     // it should compile | 
| 5357 |     QVERIFY(connect(&ob, &NoDefaultContructorArguments::mySignal, &ob, &NoDefaultContructorArguments::mySlot, Qt::QueuedConnection)); | 
| 5358 | } | 
| 5359 |  | 
| 5360 | struct MoveOnly | 
| 5361 | { | 
| 5362 |     int value; | 
| 5363 |     explicit MoveOnly(int v = 1) : value(v) {} | 
| 5364 |     MoveOnly(MoveOnly &&o) : value(o.value) { o.value = -1; } | 
| 5365 |     MoveOnly &operator=(MoveOnly &&o) { value = o.value; o.value = -1; return *this;  } | 
| 5366 |     Q_DISABLE_COPY(MoveOnly); | 
| 5367 | }; | 
| 5368 |  | 
| 5369 | class ReturnValue : public QObject { | 
| 5370 | friend class tst_QObject; | 
| 5371 | Q_OBJECT | 
| 5372 | signals: | 
| 5373 |     QVariant returnVariant(int); | 
| 5374 |     QString returnString(int); | 
| 5375 |     int returnInt(int); | 
| 5376 |     void returnVoid(int); | 
| 5377 |     CustomType returnCustomType(int); | 
| 5378 |     MoveOnly returnMoveOnly(int); | 
| 5379 |  | 
| 5380 |     QObject *returnPointer(); | 
| 5381 | public slots: | 
| 5382 |     QVariant returnVariantSlot(int i) { return i; } | 
| 5383 |     QString returnStringSlot(int i) { return QString::number(i); } | 
| 5384 |     int returnIntSlot(int i) { return i; } | 
| 5385 |     CustomType returnCustomTypeSlot(int i) { return CustomType(i); } | 
| 5386 |     void returnVoidSlot() {} | 
| 5387 |     int return23() { return 23; } | 
| 5388 |     QString returnHello() { return QStringLiteral("hello" ); } | 
| 5389 |     QObject *returnThisSlot1() { return this; } | 
| 5390 |     ReturnValue *returnThisSlot2() { return this; } | 
| 5391 |     MoveOnly returnMoveOnlySlot(int i) { return MoveOnly(i); } | 
| 5392 | public: | 
| 5393 |     struct VariantFunctor { | 
| 5394 |         QVariant operator()(int i) { return i; } | 
| 5395 |     }; | 
| 5396 |     struct CustomTypeFunctor { | 
| 5397 |         CustomType operator()(int i) { return CustomType(i); } | 
| 5398 |     }; | 
| 5399 |     struct StringFunctor { | 
| 5400 |         QString operator()(int i) { return QString::number(i); } | 
| 5401 |     }; | 
| 5402 |     struct IntFunctor { | 
| 5403 |         int operator()(int i) { return i; } | 
| 5404 |     }; | 
| 5405 |     struct VoidFunctor { | 
| 5406 |         void operator()(int) {} | 
| 5407 |     }; | 
| 5408 |     struct MoveOnlyFunctor { | 
| 5409 |         MoveOnly operator()(int i) { return MoveOnly(i); } | 
| 5410 |     }; | 
| 5411 | }; | 
| 5412 |  | 
| 5413 | QString someFunctionReturningString(int i) { | 
| 5414 |     return '\'' + QString::number(i) + '\''; | 
| 5415 | } | 
| 5416 |  | 
| 5417 | void tst_QObject::returnValue_data() | 
| 5418 | { | 
| 5419 |     QTest::addColumn<bool>(name: "isBlockingQueued" ); | 
| 5420 |  | 
| 5421 |     QTest::newRow(dataTag: "DirectConnection" ) << false; | 
| 5422 |     QTest::newRow(dataTag: "BlockingQueuedConnection" ) << true; | 
| 5423 | } | 
| 5424 |  | 
| 5425 | void tst_QObject::returnValue() | 
| 5426 | { | 
| 5427 |     CheckInstanceCount checker; | 
| 5428 |  | 
| 5429 |     QFETCH(bool, isBlockingQueued); | 
| 5430 |     QThread thread; | 
| 5431 |     ReturnValue receiver; | 
| 5432 |     Qt::ConnectionType type = Qt::DirectConnection; | 
| 5433 |     if (isBlockingQueued) { | 
| 5434 |         thread.start(); | 
| 5435 |         receiver.moveToThread(thread: &thread); | 
| 5436 |         type = Qt::BlockingQueuedConnection; | 
| 5437 |     } | 
| 5438 |  | 
| 5439 |     { // connected to nothing | 
| 5440 |         CheckInstanceCount checker; | 
| 5441 |         ReturnValue r; | 
| 5442 |         QCOMPARE(emit r.returnVariant(45), QVariant()); | 
| 5443 |         QCOMPARE(emit r.returnString(45), QString()); | 
| 5444 |         QCOMPARE(emit r.returnInt(45), int()); | 
| 5445 |         emit r.returnVoid(45); | 
| 5446 |         QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value()); | 
| 5447 |         QCOMPARE((emit r.returnPointer()), static_cast<QObject *>(0)); | 
| 5448 |         QCOMPARE((emit r.returnMoveOnly(666)).value, MoveOnly().value); | 
| 5449 |     } | 
| 5450 |     { // connected to a slot returning the same type | 
| 5451 |         CheckInstanceCount checker; | 
| 5452 |         ReturnValue r; | 
| 5453 |         QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnVariantSlot, type)); | 
| 5454 |         QCOMPARE(emit r.returnVariant(45), QVariant(45)); | 
| 5455 |         QVERIFY(connect(&r, &ReturnValue::returnString, &receiver, &ReturnValue::returnStringSlot, type)); | 
| 5456 |         QCOMPARE(emit r.returnString(45), QString::fromLatin1("45" )); | 
| 5457 |         QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::returnIntSlot, type)); | 
| 5458 |         QCOMPARE(emit r.returnInt(45), int(45)); | 
| 5459 |         QVERIFY(connect(&r, &ReturnValue::returnCustomType, &receiver, &ReturnValue::returnCustomTypeSlot, type)); | 
| 5460 |         QCOMPARE((emit r.returnCustomType(45)).value(), CustomType(45).value()); | 
| 5461 |         QVERIFY(connect(&r, &ReturnValue::returnPointer, &receiver, &ReturnValue::returnThisSlot1, type)); | 
| 5462 |         QCOMPARE((emit r.returnPointer()), static_cast<QObject *>(&receiver)); | 
| 5463 |         QVERIFY(connect(&r, &ReturnValue::returnMoveOnly, &receiver, &ReturnValue::returnMoveOnlySlot, type)); | 
| 5464 |         QCOMPARE((emit r.returnMoveOnly(666)).value, 666); | 
| 5465 |     } | 
| 5466 |     if (!isBlockingQueued) { // connected to simple functions or functor | 
| 5467 |         CheckInstanceCount checker; | 
| 5468 |         ReturnValue r; | 
| 5469 |         QVERIFY(connect(&r, &ReturnValue::returnString, someFunctionReturningString)); | 
| 5470 |         QCOMPARE(emit r.returnString(49), QString::fromLatin1("'49'" )); | 
| 5471 |  | 
| 5472 |         ReturnValue::CustomTypeFunctor customTypeFunctor; | 
| 5473 |         QVERIFY(connect(&r, &ReturnValue::returnCustomType, customTypeFunctor)); | 
| 5474 |         QCOMPARE((emit r.returnCustomType(49)).value(), CustomType(49).value()); | 
| 5475 |  | 
| 5476 |         ReturnValue::VariantFunctor variantFunctor; | 
| 5477 |         QVERIFY(connect(&r, &ReturnValue::returnVariant, variantFunctor)); | 
| 5478 |         QCOMPARE(emit r.returnVariant(45), QVariant(45)); | 
| 5479 |  | 
| 5480 |         ReturnValue::IntFunctor intFunctor; | 
| 5481 |         QVERIFY(connect(&r, &ReturnValue::returnInt, intFunctor)); | 
| 5482 |         QCOMPARE(emit r.returnInt(45), int(45)); | 
| 5483 |  | 
| 5484 |         ReturnValue::MoveOnlyFunctor moveOnlyFunctor; | 
| 5485 |         QVERIFY(connect(&r, &ReturnValue::returnMoveOnly, moveOnlyFunctor)); | 
| 5486 |         QCOMPARE((emit r.returnMoveOnly(666)).value, 666); | 
| 5487 |     } | 
| 5488 |     { // connected to a slot with different type | 
| 5489 |         CheckInstanceCount checker; | 
| 5490 |         ReturnValue r; | 
| 5491 |         QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnStringSlot, type)); | 
| 5492 |         QCOMPARE(emit r.returnVariant(48), QVariant(QString::fromLatin1("48" ))); | 
| 5493 |         QVERIFY(connect(&r, &ReturnValue::returnCustomType, &receiver, &ReturnValue::returnIntSlot, type)); | 
| 5494 |         QCOMPARE((emit r.returnCustomType(48)).value(), CustomType(48).value()); | 
| 5495 |         QVERIFY(connect(&r, &ReturnValue::returnVoid, &receiver, &ReturnValue::returnCustomTypeSlot, type)); | 
| 5496 |         emit r.returnVoid(48); | 
| 5497 |         QVERIFY(connect(&r, &ReturnValue::returnPointer, &receiver, &ReturnValue::returnThisSlot2, type)); | 
| 5498 |         QCOMPARE((emit r.returnPointer()), static_cast<QObject *>(&receiver)); | 
| 5499 |     } | 
| 5500 |     if (!isBlockingQueued) { // connected to functor with different type | 
| 5501 |         CheckInstanceCount checker; | 
| 5502 |         ReturnValue r; | 
| 5503 |  | 
| 5504 |         ReturnValue::CustomTypeFunctor customTypeFunctor; | 
| 5505 |         QVERIFY(connect(&r, &ReturnValue::returnCustomType, customTypeFunctor)); | 
| 5506 |         QCOMPARE((emit r.returnCustomType(49)).value(), CustomType(49).value()); | 
| 5507 |  | 
| 5508 |         ReturnValue::StringFunctor stringFunctor; | 
| 5509 |         QVERIFY(connect(&r, &ReturnValue::returnVariant, stringFunctor)); | 
| 5510 |         QCOMPARE(emit r.returnVariant(45), QVariant(QString::fromLatin1("45" ))); | 
| 5511 |     } | 
| 5512 |     { // connected to a void | 
| 5513 |         CheckInstanceCount checker; | 
| 5514 |         ReturnValue r; | 
| 5515 |         QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnVoidSlot, type)); | 
| 5516 |         QCOMPARE(emit r.returnVariant(45), QVariant()); | 
| 5517 |         QVERIFY(connect(&r, &ReturnValue::returnString, &receiver, &ReturnValue::returnVoidSlot, type)); | 
| 5518 |         QCOMPARE(emit r.returnString(45), QString()); | 
| 5519 |         QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::returnVoidSlot, type)); | 
| 5520 |         QCOMPARE(emit r.returnInt(45), int()); | 
| 5521 |         QVERIFY(connect(&r, &ReturnValue::returnCustomType, &receiver, &ReturnValue::returnVoidSlot, type)); | 
| 5522 |         QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value()); | 
| 5523 |         QVERIFY(connect(&r, &ReturnValue::returnPointer, &receiver, &ReturnValue::returnVoidSlot, type)); | 
| 5524 |         QCOMPARE((emit r.returnPointer()), static_cast<QObject *>(0)); | 
| 5525 |         QVERIFY(connect(&r, &ReturnValue::returnMoveOnly, &receiver, &ReturnValue::returnVoidSlot, type)); | 
| 5526 |         QCOMPARE((emit r.returnMoveOnly(666)).value, MoveOnly().value); | 
| 5527 |     } | 
| 5528 |     if (!isBlockingQueued) { | 
| 5529 |         // queued connection should not forward the return value | 
| 5530 |         CheckInstanceCount checker; | 
| 5531 |         ReturnValue r; | 
| 5532 |         QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnVariantSlot, Qt::QueuedConnection)); | 
| 5533 |         QCOMPARE(emit r.returnVariant(45), QVariant()); | 
| 5534 |         QVERIFY(connect(&r, &ReturnValue::returnString, &receiver, &ReturnValue::returnStringSlot, Qt::QueuedConnection)); | 
| 5535 |         QCOMPARE(emit r.returnString(45), QString()); | 
| 5536 |         QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::returnIntSlot, Qt::QueuedConnection)); | 
| 5537 |         QCOMPARE(emit r.returnInt(45), int()); | 
| 5538 |         QVERIFY(connect(&r, &ReturnValue::returnCustomType, &receiver, &ReturnValue::returnCustomTypeSlot, Qt::QueuedConnection)); | 
| 5539 |         QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value()); | 
| 5540 |         QVERIFY(connect(&r, &ReturnValue::returnPointer, &receiver, &ReturnValue::returnThisSlot1, Qt::QueuedConnection)); | 
| 5541 |         QCOMPARE((emit r.returnPointer()), static_cast<QObject *>(0)); | 
| 5542 |         QVERIFY(connect(&r, &ReturnValue::returnMoveOnly, &receiver, &ReturnValue::returnMoveOnlySlot, Qt::QueuedConnection)); | 
| 5543 |         QCOMPARE((emit r.returnMoveOnly(666)).value, MoveOnly().value); | 
| 5544 |  | 
| 5545 |         QCoreApplication::processEvents(); | 
| 5546 |  | 
| 5547 |         QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnStringSlot, Qt::QueuedConnection)); | 
| 5548 |         QCOMPARE(emit r.returnVariant(48), QVariant()); | 
| 5549 |         QVERIFY(connect(&r, &ReturnValue::returnCustomType, &receiver, &ReturnValue::returnIntSlot, Qt::QueuedConnection)); | 
| 5550 |         QCOMPARE((emit r.returnCustomType(48)).value(), CustomType().value()); | 
| 5551 |         QVERIFY(connect(&r, &ReturnValue::returnVoid, &receiver, &ReturnValue::returnCustomTypeSlot, Qt::QueuedConnection)); | 
| 5552 |         emit r.returnVoid(48); | 
| 5553 |         QCoreApplication::processEvents(); | 
| 5554 |     } | 
| 5555 |  | 
| 5556 |     { // connected to many slots | 
| 5557 |         ReturnValue::VoidFunctor voidFunctor; | 
| 5558 |         ReturnValue::IntFunctor intFunctor; | 
| 5559 |         ReturnValue r; | 
| 5560 |         QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnVariantSlot, type)); | 
| 5561 |         QCOMPARE(emit r.returnVariant(45), QVariant(45)); | 
| 5562 |         QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::return23, type)); | 
| 5563 |         QCOMPARE(emit r.returnVariant(45), QVariant(23)); | 
| 5564 |         QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnVoidSlot, type)); | 
| 5565 |         QCOMPARE(emit r.returnVariant(45), QVariant(23)); | 
| 5566 |         QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnHello, type)); | 
| 5567 |         QCOMPARE(emit r.returnVariant(45), QVariant(QStringLiteral("hello" ))); | 
| 5568 |         QVERIFY(connect(&r, &ReturnValue::returnVariant, voidFunctor)); | 
| 5569 |         QCOMPARE(emit r.returnVariant(45), QVariant(QStringLiteral("hello" ))); | 
| 5570 |         QVERIFY(connect(&r, &ReturnValue::returnVariant, intFunctor)); | 
| 5571 |         QCOMPARE(emit r.returnVariant(45), QVariant(45)); | 
| 5572 |         QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::return23, Qt::QueuedConnection)); | 
| 5573 |         QCOMPARE(emit r.returnVariant(45), QVariant(45)); | 
| 5574 |  | 
| 5575 |         QCOMPARE(emit r.returnInt(45), int()); | 
| 5576 |         QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::returnVoidSlot, type)); | 
| 5577 |         QCOMPARE(emit r.returnInt(45), int()); | 
| 5578 |         QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::returnIntSlot, type)); | 
| 5579 |         QCOMPARE(emit r.returnInt(45), int(45)); | 
| 5580 |         QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::return23, type)); | 
| 5581 |         QCOMPARE(emit r.returnInt(45), int(23)); | 
| 5582 |         QVERIFY(connect(&r, &ReturnValue::returnInt, voidFunctor)); | 
| 5583 |         QCOMPARE(emit r.returnInt(45), int(23)); | 
| 5584 |         QVERIFY(connect(&r, &ReturnValue::returnInt, intFunctor)); | 
| 5585 |         QCOMPARE(emit r.returnInt(45), int(45)); | 
| 5586 |         QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::return23, Qt::QueuedConnection)); | 
| 5587 |         QCOMPARE(emit r.returnInt(45), int(45)); | 
| 5588 |  | 
| 5589 |         QCoreApplication::processEvents(); | 
| 5590 |     } | 
| 5591 |  | 
| 5592 |     if (isBlockingQueued) { | 
| 5593 |         thread.quit(); | 
| 5594 |         thread.wait(); | 
| 5595 |     } | 
| 5596 | } | 
| 5597 |  | 
| 5598 | void tst_QObject::returnValue2_data() | 
| 5599 | { returnValue_data(); } | 
| 5600 |  | 
| 5601 | //String based syntax | 
| 5602 | void tst_QObject::returnValue2() | 
| 5603 | { | 
| 5604 |     CheckInstanceCount checker; | 
| 5605 |  | 
| 5606 |     QFETCH(bool, isBlockingQueued); | 
| 5607 |     QThread thread; | 
| 5608 |     ReturnValue receiver; | 
| 5609 |     Qt::ConnectionType type = Qt::DirectConnection; | 
| 5610 |     if (isBlockingQueued) { | 
| 5611 |         thread.start(); | 
| 5612 |         receiver.moveToThread(thread: &thread); | 
| 5613 |         type = Qt::BlockingQueuedConnection; | 
| 5614 |     } | 
| 5615 |  | 
| 5616 |     { // connected to a simple slot | 
| 5617 |         CheckInstanceCount checker; | 
| 5618 |         ReturnValue r; | 
| 5619 |         QVERIFY(connect(&r, SIGNAL(returnVariant(int)), &receiver, SLOT(returnVariantSlot(int)), type)); | 
| 5620 |         QCOMPARE(emit r.returnVariant(45), QVariant(45)); | 
| 5621 |         QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnStringSlot(int)), type)); | 
| 5622 |         QCOMPARE(emit r.returnString(45), QString(QStringLiteral("45" ))); | 
| 5623 |         QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnIntSlot(int)), type)); | 
| 5624 |         QCOMPARE(emit r.returnInt(45), int(45)); | 
| 5625 |         QVERIFY(connect(&r, SIGNAL(returnCustomType(int)), &receiver, SLOT(returnCustomTypeSlot(int)), type)); | 
| 5626 |         QCOMPARE((emit r.returnCustomType(45)).value(), CustomType(45).value()); | 
| 5627 |         QVERIFY(connect(&r, SIGNAL(returnMoveOnly(int)), &receiver, SLOT(returnMoveOnlySlot(int)), type)); | 
| 5628 |         QCOMPARE((emit r.returnMoveOnly(45)).value, 45); | 
| 5629 |     } | 
| 5630 |     { // connected to a slot returning void | 
| 5631 |         CheckInstanceCount checker; | 
| 5632 |         ReturnValue r; | 
| 5633 |         QVERIFY(connect(&r, SIGNAL(returnVariant(int)), &receiver, SLOT(returnVoidSlot()), type)); | 
| 5634 |         QCOMPARE(emit r.returnVariant(45), QVariant()); | 
| 5635 |         QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnVoidSlot()), type)); | 
| 5636 |         QCOMPARE(emit r.returnString(45), QString()); | 
| 5637 |         QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnVoidSlot()), type)); | 
| 5638 |         QCOMPARE(emit r.returnInt(45), int()); | 
| 5639 |         QVERIFY(connect(&r, SIGNAL(returnCustomType(int)), &receiver, SLOT(returnVoidSlot()), type)); | 
| 5640 |         QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value()); | 
| 5641 |         QVERIFY(connect(&r, SIGNAL(returnMoveOnly(int)), &receiver, SLOT(returnVoidSlot()), type)); | 
| 5642 |         QCOMPARE((emit r.returnMoveOnly(45)).value, MoveOnly().value); | 
| 5643 |     } | 
| 5644 |     if (!isBlockingQueued) { | 
| 5645 |         // queued connection should not forward the return value | 
| 5646 |         CheckInstanceCount checker; | 
| 5647 |         ReturnValue r; | 
| 5648 |         QVERIFY(connect(&r, SIGNAL(returnVariant(int)), &receiver, SLOT(returnVariantSlot(int)), Qt::QueuedConnection)); | 
| 5649 |         QCOMPARE(emit r.returnVariant(45), QVariant()); | 
| 5650 |         QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnStringSlot(int)), Qt::QueuedConnection)); | 
| 5651 |         QCOMPARE(emit r.returnString(45), QString()); | 
| 5652 |         QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnIntSlot(int)), Qt::QueuedConnection)); | 
| 5653 |         QCOMPARE(emit r.returnInt(45), int()); | 
| 5654 |         QVERIFY(connect(&r, SIGNAL(returnCustomType(int)), &receiver, SLOT(returnCustomTypeSlot(int)), Qt::QueuedConnection)); | 
| 5655 |         QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value()); | 
| 5656 |         QVERIFY(connect(&r, SIGNAL(returnMoveOnly(int)), &receiver, SLOT(returnMoveOnlySlot(int)), Qt::QueuedConnection)); | 
| 5657 |         QCOMPARE((emit r.returnMoveOnly(45)).value, MoveOnly().value); | 
| 5658 |  | 
| 5659 |         QCoreApplication::processEvents(); | 
| 5660 |  | 
| 5661 |         //Queued conneciton with different return type should be safe | 
| 5662 |         QVERIFY(connect(&r, SIGNAL(returnVariant(int)), &receiver, SLOT(returnStringSlot(int)), Qt::QueuedConnection)); | 
| 5663 |         QCOMPARE(emit r.returnVariant(48), QVariant()); | 
| 5664 |         QVERIFY(connect(&r, SIGNAL(returnCustomType(int)), &receiver, SLOT(returnIntSlot(int)), Qt::QueuedConnection)); | 
| 5665 |         QCOMPARE((emit r.returnCustomType(48)).value(), CustomType().value()); | 
| 5666 |         QVERIFY(connect(&r, SIGNAL(returnVoid(int)), &receiver, SLOT(returnCustomTypeSlot(int)), Qt::QueuedConnection)); | 
| 5667 |         emit r.returnVoid(48); | 
| 5668 |         QCoreApplication::processEvents(); | 
| 5669 |     } | 
| 5670 |     { // connected to many slots | 
| 5671 |         ReturnValue r; | 
| 5672 |         QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnIntSlot(int)), type)); | 
| 5673 |         QCOMPARE(emit r.returnInt(45), int(45)); | 
| 5674 |         QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnVoidSlot()), type)); | 
| 5675 |         QCOMPARE(emit r.returnInt(45), int(45)); | 
| 5676 |         QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(return23()), type)); | 
| 5677 |         QCOMPARE(emit r.returnInt(45), int(23)); | 
| 5678 |         QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnIntSlot(int)), Qt::QueuedConnection)); | 
| 5679 |         QCOMPARE(emit r.returnInt(45), int(23)); | 
| 5680 |  | 
| 5681 |         QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnStringSlot(int)), type)); | 
| 5682 |         QCOMPARE(emit r.returnString(45), QString(QStringLiteral("45" ))); | 
| 5683 |         QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnVoidSlot()), type)); | 
| 5684 |         QCOMPARE(emit r.returnString(45), QString(QStringLiteral("45" ))); | 
| 5685 |         QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnHello()), type)); | 
| 5686 |         QCOMPARE(emit r.returnString(45), QString(QStringLiteral("hello" ))); | 
| 5687 |         QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnStringSlot(int)), Qt::QueuedConnection)); | 
| 5688 |         QCOMPARE(emit r.returnString(45), QString(QStringLiteral("hello" ))); | 
| 5689 |     } | 
| 5690 |     if (isBlockingQueued) { | 
| 5691 |         thread.quit(); | 
| 5692 |         thread.wait(); | 
| 5693 |     } | 
| 5694 | } | 
| 5695 |  | 
| 5696 | class VirtualSlotsObjectBase : public QObject { | 
| 5697 |     Q_OBJECT | 
| 5698 | public slots: | 
| 5699 |     virtual void slot1() { | 
| 5700 |         base_counter1++; | 
| 5701 |     } | 
| 5702 | public: | 
| 5703 |     VirtualSlotsObjectBase() : base_counter1(0) {} | 
| 5704 |     int base_counter1; | 
| 5705 | signals: | 
| 5706 |     void signal1(); | 
| 5707 | }; | 
| 5708 |  | 
| 5709 | class VirtualSlotsObject : public VirtualSlotsObjectBase { | 
| 5710 |     Q_OBJECT | 
| 5711 | public slots: | 
| 5712 |     virtual void slot1() { | 
| 5713 |         derived_counter1++; | 
| 5714 |     } | 
| 5715 | public: | 
| 5716 |     VirtualSlotsObject() : derived_counter1(0) {} | 
| 5717 |     int derived_counter1; | 
| 5718 | }; | 
| 5719 |  | 
| 5720 | void tst_QObject::connectVirtualSlots() | 
| 5721 | { | 
| 5722 |     VirtualSlotsObject obj; | 
| 5723 |     QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1, Qt::UniqueConnection)); | 
| 5724 |     QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1, Qt::UniqueConnection)); | 
| 5725 |  | 
| 5726 |     emit obj.signal1(); | 
| 5727 |     QCOMPARE(obj.base_counter1, 0); | 
| 5728 |     QCOMPARE(obj.derived_counter1, 1); | 
| 5729 |  | 
| 5730 |     QVERIFY(QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1)); | 
| 5731 |     QVERIFY(!QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1)); | 
| 5732 |  | 
| 5733 |     emit obj.signal1(); | 
| 5734 |     QCOMPARE(obj.base_counter1, 0); | 
| 5735 |     QCOMPARE(obj.derived_counter1, 1); | 
| 5736 |  | 
| 5737 |     /* the C++ standard say the comparison between pointer to virtual member function is unspecified | 
| 5738 |     QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1, Qt::UniqueConnection)); | 
| 5739 |     QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObject::slot1, Qt::UniqueConnection)); | 
| 5740 |     */ | 
| 5741 | } | 
| 5742 |  | 
| 5743 | struct VirtualBase | 
| 5744 | { | 
| 5745 |     int virtual_base_count; | 
| 5746 |     VirtualBase() : virtual_base_count(0) {} | 
| 5747 |     virtual ~VirtualBase() {} | 
| 5748 |     virtual void slot2() = 0; | 
| 5749 | }; | 
| 5750 |  | 
| 5751 | class ObjectWithVirtualBase : public VirtualSlotsObject, public virtual VirtualBase | 
| 5752 | { | 
| 5753 |     Q_OBJECT | 
| 5754 | public: | 
| 5755 |     ObjectWithVirtualBase() : regular_call_count(0), derived_counter2(0) {} | 
| 5756 |     int regular_call_count; | 
| 5757 |     int derived_counter2; | 
| 5758 |  | 
| 5759 | public slots: | 
| 5760 |     void regularSlot() { ++regular_call_count; } | 
| 5761 |     virtual void slot1() { ++derived_counter2; } | 
| 5762 |     virtual void slot2() { ++virtual_base_count; } | 
| 5763 | }; | 
| 5764 |  | 
| 5765 | struct NormalBase | 
| 5766 | { | 
| 5767 |     QByteArray lastCalled; | 
| 5768 |     virtual ~NormalBase() {} | 
| 5769 |     virtual void virtualBaseSlot() { lastCalled = "virtualBaseSlot" ; } | 
| 5770 |     void normalBaseSlot() { lastCalled = "normalBaseSlot" ; } | 
| 5771 | }; | 
| 5772 |  | 
| 5773 | class ObjectWithMultiInheritance : public VirtualSlotsObject, public NormalBase | 
| 5774 | { | 
| 5775 |     Q_OBJECT | 
| 5776 | }; | 
| 5777 |  | 
| 5778 | // Normally, the class that inherit QObject always must go first, because of the way qobject_cast | 
| 5779 | // work, and moc checks for that. But if we don't use Q_OBJECT, this should work | 
| 5780 | class ObjectWithMultiInheritance2 : public NormalBase, public VirtualSlotsObject | 
| 5781 | { | 
| 5782 |     // no QObject as QObject always must go first | 
| 5783 |     // Q_OBJECT | 
| 5784 | }; | 
| 5785 |  | 
| 5786 | // VMI = Virtual or Multiple Inheritance | 
| 5787 | // (in this case, both) | 
| 5788 | void tst_QObject::connectSlotsVMIClass() | 
| 5789 | { | 
| 5790 |     // test connecting by the base | 
| 5791 |     { | 
| 5792 |         ObjectWithVirtualBase obj; | 
| 5793 |         QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1, Qt::UniqueConnection)); | 
| 5794 |         QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1, Qt::UniqueConnection)); | 
| 5795 |  | 
| 5796 |         emit obj.signal1(); | 
| 5797 |         QCOMPARE(obj.base_counter1, 0); | 
| 5798 |         QCOMPARE(obj.derived_counter1, 0); | 
| 5799 |         QCOMPARE(obj.derived_counter2, 1); | 
| 5800 |         QCOMPARE(obj.virtual_base_count, 0); | 
| 5801 |  | 
| 5802 |         QVERIFY(QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1)); | 
| 5803 |         QVERIFY(!QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1)); | 
| 5804 |  | 
| 5805 |         emit obj.signal1(); | 
| 5806 |         QCOMPARE(obj.base_counter1, 0); | 
| 5807 |         QCOMPARE(obj.derived_counter1, 0); | 
| 5808 |         QCOMPARE(obj.derived_counter2, 1); | 
| 5809 |         QCOMPARE(obj.virtual_base_count, 0); | 
| 5810 |     } | 
| 5811 |  | 
| 5812 |     // test connecting with the actual class | 
| 5813 |     { | 
| 5814 |         ObjectWithVirtualBase obj; | 
| 5815 |         QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::regularSlot, Qt::UniqueConnection)); | 
| 5816 |         QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::regularSlot, Qt::UniqueConnection)); | 
| 5817 |         QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot1, Qt::UniqueConnection)); | 
| 5818 |         QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot1, Qt::UniqueConnection)); | 
| 5819 |  | 
| 5820 |         emit obj.signal1(); | 
| 5821 |         QCOMPARE(obj.base_counter1, 0); | 
| 5822 |         QCOMPARE(obj.derived_counter1, 0); | 
| 5823 |         QCOMPARE(obj.derived_counter2, 1); | 
| 5824 |         QCOMPARE(obj.regular_call_count, 1); | 
| 5825 |         QCOMPARE(obj.virtual_base_count, 0); | 
| 5826 |  | 
| 5827 |         QVERIFY( QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::regularSlot)); | 
| 5828 |         QVERIFY(!QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::regularSlot)); | 
| 5829 |         QVERIFY( QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot1)); | 
| 5830 |         QVERIFY(!QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot1)); | 
| 5831 |  | 
| 5832 |         emit obj.signal1(); | 
| 5833 |         QCOMPARE(obj.base_counter1, 0); | 
| 5834 |         QCOMPARE(obj.derived_counter1, 0); | 
| 5835 |         QCOMPARE(obj.derived_counter2, 1); | 
| 5836 |         QCOMPARE(obj.regular_call_count, 1); | 
| 5837 |         QCOMPARE(obj.virtual_base_count, 0); | 
| 5838 |  | 
| 5839 |         /* the C++ standard say the comparison between pointer to virtual member function is unspecified | 
| 5840 |         QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1, Qt::UniqueConnection)); | 
| 5841 |         QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot1, Qt::UniqueConnection)); | 
| 5842 |         */ | 
| 5843 |     } | 
| 5844 |  | 
| 5845 |     // test connecting a slot that is virtual from the virtual base | 
| 5846 |     { | 
| 5847 |         ObjectWithVirtualBase obj; | 
| 5848 |         QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot2, Qt::UniqueConnection)); | 
| 5849 |         QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot2, Qt::UniqueConnection)); | 
| 5850 |  | 
| 5851 |         emit obj.signal1(); | 
| 5852 |         QCOMPARE(obj.base_counter1, 0); | 
| 5853 |         QCOMPARE(obj.derived_counter1, 0); | 
| 5854 |         QCOMPARE(obj.derived_counter2, 0); | 
| 5855 |         QCOMPARE(obj.virtual_base_count, 1); | 
| 5856 |         QCOMPARE(obj.regular_call_count, 0); | 
| 5857 |  | 
| 5858 |         QVERIFY( QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot2)); | 
| 5859 |         QVERIFY(!QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot2)); | 
| 5860 |  | 
| 5861 |         emit obj.signal1(); | 
| 5862 |         QCOMPARE(obj.base_counter1, 0); | 
| 5863 |         QCOMPARE(obj.derived_counter1, 0); | 
| 5864 |         QCOMPARE(obj.derived_counter2, 0); | 
| 5865 |         QCOMPARE(obj.virtual_base_count, 1); | 
| 5866 |         QCOMPARE(obj.regular_call_count, 0); | 
| 5867 |     } | 
| 5868 |  | 
| 5869 |     // test connecting a slot that is virtual within the second base | 
| 5870 |     { | 
| 5871 |         ObjectWithMultiInheritance obj; | 
| 5872 |         void (ObjectWithMultiInheritance::*slot)() = &ObjectWithMultiInheritance::virtualBaseSlot; | 
| 5873 |         QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot, Qt::UniqueConnection)); | 
| 5874 |         QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot, Qt::UniqueConnection)); | 
| 5875 |  | 
| 5876 |         emit obj.signal1(); | 
| 5877 |         QCOMPARE(obj.base_counter1, 0); | 
| 5878 |         QCOMPARE(obj.derived_counter1, 0); | 
| 5879 |         QCOMPARE(obj.lastCalled, QByteArray("virtualBaseSlot" )); | 
| 5880 |         obj.lastCalled.clear(); | 
| 5881 |  | 
| 5882 |         QVERIFY( QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot)); | 
| 5883 |         QVERIFY(!QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot)); | 
| 5884 |  | 
| 5885 |         emit obj.signal1(); | 
| 5886 |         QCOMPARE(obj.base_counter1, 0); | 
| 5887 |         QCOMPARE(obj.derived_counter1, 0); | 
| 5888 |         QCOMPARE(obj.lastCalled, QByteArray()); | 
| 5889 |     } | 
| 5890 |  | 
| 5891 |     // test connecting a slot that is not virtual within the second base | 
| 5892 |     { | 
| 5893 |         ObjectWithMultiInheritance obj; | 
| 5894 |         void (ObjectWithMultiInheritance::*slot)() = &ObjectWithMultiInheritance::normalBaseSlot; | 
| 5895 |         QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot, Qt::UniqueConnection)); | 
| 5896 |         QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot, Qt::UniqueConnection)); | 
| 5897 |  | 
| 5898 |         emit obj.signal1(); | 
| 5899 |         QCOMPARE(obj.base_counter1, 0); | 
| 5900 |         QCOMPARE(obj.derived_counter1, 0); | 
| 5901 |         QCOMPARE(obj.lastCalled, QByteArray("normalBaseSlot" )); | 
| 5902 |         obj.lastCalled.clear(); | 
| 5903 |  | 
| 5904 |         QVERIFY( QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot)); | 
| 5905 |         QVERIFY(!QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot)); | 
| 5906 |  | 
| 5907 |         emit obj.signal1(); | 
| 5908 |         QCOMPARE(obj.base_counter1, 0); | 
| 5909 |         QCOMPARE(obj.derived_counter1, 0); | 
| 5910 |         QCOMPARE(obj.lastCalled, QByteArray()); | 
| 5911 |     } | 
| 5912 |  | 
| 5913 |     // test connecting a slot within the first non-QObject base | 
| 5914 |     { | 
| 5915 |         ObjectWithMultiInheritance2 obj; | 
| 5916 |         void (ObjectWithMultiInheritance2::*slot)() = &ObjectWithMultiInheritance2::normalBaseSlot; | 
| 5917 |         QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot, Qt::UniqueConnection)); | 
| 5918 |         QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot, Qt::UniqueConnection)); | 
| 5919 |  | 
| 5920 |         emit obj.signal1(); | 
| 5921 |         QCOMPARE(obj.base_counter1, 0); | 
| 5922 |         QCOMPARE(obj.derived_counter1, 0); | 
| 5923 |         QCOMPARE(obj.lastCalled, QByteArray("normalBaseSlot" )); | 
| 5924 |         obj.lastCalled.clear(); | 
| 5925 |  | 
| 5926 |         QVERIFY( QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot)); | 
| 5927 |         QVERIFY(!QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot)); | 
| 5928 |  | 
| 5929 |         emit obj.signal1(); | 
| 5930 |         QCOMPARE(obj.base_counter1, 0); | 
| 5931 |         QCOMPARE(obj.derived_counter1, 0); | 
| 5932 |         QCOMPARE(obj.lastCalled, QByteArray()); | 
| 5933 |     } | 
| 5934 |  | 
| 5935 |     // test connecting a slot within the second QObject base | 
| 5936 |     { | 
| 5937 |         ObjectWithMultiInheritance2 obj; | 
| 5938 |         void (ObjectWithMultiInheritance2::*slot)() = &ObjectWithMultiInheritance2::slot1; | 
| 5939 |         QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot, Qt::UniqueConnection)); | 
| 5940 |         QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot, Qt::UniqueConnection)); | 
| 5941 |  | 
| 5942 |         emit obj.signal1(); | 
| 5943 |         QCOMPARE(obj.base_counter1, 0); | 
| 5944 |         QCOMPARE(obj.derived_counter1, 1); | 
| 5945 |         QCOMPARE(obj.lastCalled, QByteArray()); | 
| 5946 |  | 
| 5947 |         QVERIFY( QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot)); | 
| 5948 |         QVERIFY(!QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot)); | 
| 5949 |  | 
| 5950 |         emit obj.signal1(); | 
| 5951 |         QCOMPARE(obj.base_counter1, 0); | 
| 5952 |         QCOMPARE(obj.derived_counter1, 1); | 
| 5953 |         QCOMPARE(obj.lastCalled, QByteArray()); | 
| 5954 |     } | 
| 5955 | } | 
| 5956 |  | 
| 5957 | #ifndef QT_BUILD_INTERNAL | 
| 5958 | void tst_QObject::connectPrivateSlots() | 
| 5959 | {QSKIP("Needs QT_BUILD_INTERNAL" );} | 
| 5960 | #else | 
| 5961 | class ConnectToPrivateSlotPrivate; | 
| 5962 |  | 
| 5963 | class ConnectToPrivateSlot :public QObject { | 
| 5964 |     Q_OBJECT | 
| 5965 | public: | 
| 5966 |     ConnectToPrivateSlot(); | 
| 5967 |     void test(SenderObject *obj1) ; | 
| 5968 |     Q_DECLARE_PRIVATE(ConnectToPrivateSlot) | 
| 5969 | }; | 
| 5970 |  | 
| 5971 | class ConnectToPrivateSlotPrivate : public QObjectPrivate { | 
| 5972 |     Q_DECLARE_PUBLIC(ConnectToPrivateSlot) | 
| 5973 | public: | 
| 5974 |     int receivedCount; | 
| 5975 |     QVariant receivedValue; | 
| 5976 |  | 
| 5977 |     void thisIsAPrivateSlot() { | 
| 5978 |         receivedCount++; | 
| 5979 |     }; | 
| 5980 |  | 
| 5981 |     void thisIsAPrivateSlotWithArg(const QVariant &v) { | 
| 5982 |         receivedCount++; | 
| 5983 |         receivedValue = v; | 
| 5984 |     }; | 
| 5985 | }; | 
| 5986 |  | 
| 5987 | ConnectToPrivateSlot::ConnectToPrivateSlot(): QObject(*new ConnectToPrivateSlotPrivate) {} | 
| 5988 |  | 
| 5989 | void ConnectToPrivateSlot::test(SenderObject* obj1) { | 
| 5990 |     Q_D(ConnectToPrivateSlot); | 
| 5991 |     d->receivedCount = 0; | 
| 5992 |     QVERIFY(QObjectPrivate::connect(obj1, &SenderObject::signal1, d, &ConnectToPrivateSlotPrivate::thisIsAPrivateSlot)); | 
| 5993 |     QVERIFY(QObjectPrivate::connect(obj1, &SenderObject::signal7, d, &ConnectToPrivateSlotPrivate::thisIsAPrivateSlotWithArg)); | 
| 5994 |     QCOMPARE(d->receivedCount, 0); | 
| 5995 |     obj1->signal1(); | 
| 5996 |     QCOMPARE(d->receivedCount, 1); | 
| 5997 |     QCOMPARE(d->receivedValue, QVariant()); | 
| 5998 |     obj1->signal7(666, QLatin1String("_" )); | 
| 5999 |     QCOMPARE(d->receivedCount, 2); | 
| 6000 |     QCOMPARE(d->receivedValue, QVariant(666)); | 
| 6001 |     QVERIFY(QObjectPrivate::connect(obj1, &SenderObject::signal2, d, &ConnectToPrivateSlotPrivate::thisIsAPrivateSlot, Qt::UniqueConnection)); | 
| 6002 |     QVERIFY(!QObjectPrivate::connect(obj1, &SenderObject::signal2, d, &ConnectToPrivateSlotPrivate::thisIsAPrivateSlot, Qt::UniqueConnection)); | 
| 6003 |     obj1->signal2(); | 
| 6004 |     QCOMPARE(d->receivedCount, 3); | 
| 6005 |     QVERIFY(QObjectPrivate::disconnect(obj1, &SenderObject::signal2, d, &ConnectToPrivateSlotPrivate::thisIsAPrivateSlot)); | 
| 6006 |     obj1->signal2(); | 
| 6007 |     QCOMPARE(d->receivedCount, 3); | 
| 6008 |     QVERIFY(!QObjectPrivate::disconnect(obj1, &SenderObject::signal2, d, &ConnectToPrivateSlotPrivate::thisIsAPrivateSlot)); | 
| 6009 | } | 
| 6010 |  | 
| 6011 | void tst_QObject::connectPrivateSlots() | 
| 6012 | { | 
| 6013 |     SenderObject sender; | 
| 6014 |     { | 
| 6015 |         ConnectToPrivateSlot o; | 
| 6016 |         o.test(obj1: &sender); | 
| 6017 |     } | 
| 6018 |     sender.signal7(777, QLatin1String("check that deleting the object properly disconnected" )); | 
| 6019 |     sender.signal1(); | 
| 6020 | } | 
| 6021 | #endif | 
| 6022 |  | 
| 6023 | struct SlotFunctor | 
| 6024 | { | 
| 6025 |     void operator()() {} | 
| 6026 | }; | 
| 6027 |  | 
| 6028 | struct SlotFunctorString | 
| 6029 | { | 
| 6030 |     void operator()(const QString &) {} | 
| 6031 | }; | 
| 6032 |  | 
| 6033 | void tst_QObject::connectFunctorArgDifference() | 
| 6034 | { | 
| 6035 |     QTimer timer; | 
| 6036 |     // Compile-time tests that the connection is successful. | 
| 6037 |     connect(sender: &timer, signal: &QTimer::timeout, slot: SlotFunctor()); | 
| 6038 |     connect(sender: &timer, signal: &QTimer::objectNameChanged, slot: SlotFunctorString()); | 
| 6039 |     connect(qApp, signal: &QCoreApplication::aboutToQuit, slot: SlotFunctor()); | 
| 6040 |  | 
| 6041 |     connect(sender: &timer, signal: &QTimer::objectNameChanged, slot: SlotFunctor()); | 
| 6042 |     QStringListModel model; | 
| 6043 |     connect(sender: &model, signal: &QStringListModel::rowsInserted, slot: SlotFunctor()); | 
| 6044 |  | 
| 6045 |     connect(sender: &timer, signal: &QTimer::timeout, slot: [=](){}); | 
| 6046 |     connect(sender: &timer, signal: &QTimer::objectNameChanged, slot: [=](const QString &){}); | 
| 6047 |     connect(qApp, signal: &QCoreApplication::aboutToQuit, slot: [=](){}); | 
| 6048 |  | 
| 6049 |     connect(sender: &timer, signal: &QTimer::objectNameChanged, slot: [=](){}); | 
| 6050 |     connect(sender: &model, signal: &QStringListModel::rowsInserted, slot: [=](){}); | 
| 6051 |     connect(sender: &model, signal: &QStringListModel::rowsInserted, slot: [=](const QModelIndex &){}); | 
| 6052 |  | 
| 6053 |     QVERIFY(true); | 
| 6054 | } | 
| 6055 |  | 
| 6056 | class ContextObject : public QObject | 
| 6057 | { | 
| 6058 |     Q_OBJECT | 
| 6059 | public: | 
| 6060 |     void compareSender(QObject *s) { QCOMPARE(s, sender()); } | 
| 6061 | }; | 
| 6062 |  | 
| 6063 | struct SlotArgFunctor | 
| 6064 | { | 
| 6065 |     SlotArgFunctor(int *s) : status(s), context(nullptr), sender(nullptr) {} | 
| 6066 |     SlotArgFunctor(ContextObject *context, QObject *sender, int *s) : status(s), context(context), sender(sender) {} | 
| 6067 |     void operator()() { *status = 2; if (context) context->compareSender(s: sender); } | 
| 6068 |  | 
| 6069 | protected: | 
| 6070 |     int *status; | 
| 6071 |     ContextObject *context; | 
| 6072 |     QObject *sender; | 
| 6073 | }; | 
| 6074 |  | 
| 6075 | void tst_QObject::connectFunctorQueued() | 
| 6076 | { | 
| 6077 |     int status = 1; | 
| 6078 |     SenderObject obj; | 
| 6079 |     QEventLoop e; | 
| 6080 |  | 
| 6081 |     connect(sender: &obj, signal: &SenderObject::signal1, context: this, slot: SlotArgFunctor(&status), type: Qt::QueuedConnection); | 
| 6082 |     connect(sender: &obj, signal: &SenderObject::signal1, receiver: &e, slot: &QEventLoop::quit, type: Qt::QueuedConnection); | 
| 6083 |  | 
| 6084 |     obj.emitSignal1(); | 
| 6085 |     QCOMPARE(status, 1); | 
| 6086 |     e.exec(); | 
| 6087 |     QCOMPARE(status, 2); | 
| 6088 |  | 
| 6089 |     status = 1; | 
| 6090 |     connect(sender: &obj, signal: &SenderObject::signal1, context: this, slot: [&status] { status = 2; }, type: Qt::QueuedConnection); | 
| 6091 |  | 
| 6092 |     obj.emitSignal1(); | 
| 6093 |     QCOMPARE(status, 1); | 
| 6094 |     e.exec(); | 
| 6095 |     QCOMPARE(status, 2); | 
| 6096 | } | 
| 6097 |  | 
| 6098 | void tst_QObject::connectFunctorWithContext() | 
| 6099 | { | 
| 6100 |     int status = 1; | 
| 6101 |     SenderObject obj; | 
| 6102 |     ContextObject *context = new ContextObject; | 
| 6103 |     QEventLoop e; | 
| 6104 |  | 
| 6105 |     connect(sender: &obj, signal: &SenderObject::signal1, context, slot: SlotArgFunctor(&status)); | 
| 6106 |     connect(sender: &obj, signal: &SenderObject::signal1, receiver: &e, slot: &QEventLoop::quit, type: Qt::QueuedConnection); | 
| 6107 |  | 
| 6108 |     // When the context gets deleted, the connection should decay and the signal shouldn't trigger | 
| 6109 |     // The connection is queued to make sure the destroyed signal propagates correctly and | 
| 6110 |     // cuts the connection. | 
| 6111 |     connect(sender: context, signal: &QObject::destroyed, receiver: &obj, slot: &SenderObject::signal1, type: Qt::QueuedConnection); | 
| 6112 |     context->deleteLater(); | 
| 6113 |  | 
| 6114 |     QCOMPARE(status, 1); | 
| 6115 |     e.exec(); | 
| 6116 |     QCOMPARE(status, 1); | 
| 6117 |  | 
| 6118 |     // Check the sender arg is set correctly in the context | 
| 6119 |     context = new ContextObject; | 
| 6120 |  | 
| 6121 |     connect(sender: &obj, signal: &SenderObject::signal1, context, | 
| 6122 |             slot: SlotArgFunctor(context, &obj, &status), type: Qt::QueuedConnection); | 
| 6123 |  | 
| 6124 |     obj.emitSignal1(); | 
| 6125 |     QCOMPARE(status, 1); | 
| 6126 |     e.exec(); | 
| 6127 |     QCOMPARE(status, 2); | 
| 6128 |  | 
| 6129 |     status = 1; | 
| 6130 |     connect(sender: &obj, signal: &SenderObject::signal1, context: this, slot: [this, &status, &obj] { status = 2; QCOMPARE(sender(), &obj); }, type: Qt::QueuedConnection); | 
| 6131 |  | 
| 6132 |     obj.emitSignal1(); | 
| 6133 |     QCOMPARE(status, 1); | 
| 6134 |     e.exec(); | 
| 6135 |     QCOMPARE(status, 2); | 
| 6136 |  | 
| 6137 |     // Free | 
| 6138 |     context->deleteLater(); | 
| 6139 | } | 
| 6140 |  | 
| 6141 | class StatusChanger : public QObject | 
| 6142 | { | 
| 6143 |     Q_OBJECT | 
| 6144 | public: | 
| 6145 |     StatusChanger(int *status) : m_status(status) | 
| 6146 |     { | 
| 6147 |     } | 
| 6148 |     ~StatusChanger() | 
| 6149 |     { | 
| 6150 |         *m_status = 2; | 
| 6151 |     } | 
| 6152 | private: | 
| 6153 |     int *m_status; | 
| 6154 | }; | 
| 6155 |  | 
| 6156 | class DispatcherWatcher : public QObject | 
| 6157 | { | 
| 6158 |     Q_OBJECT | 
| 6159 | public: | 
| 6160 |     DispatcherWatcher(QEventLoop &e, int *statusAwake, int *statusAboutToBlock) : | 
| 6161 |         m_eventLoop(&e), | 
| 6162 |         m_statusAwake(statusAwake), | 
| 6163 |         m_statusAboutToBlock(statusAboutToBlock), | 
| 6164 |         m_aboutToBlocks(0), | 
| 6165 |         m_awakes(0) | 
| 6166 |     { | 
| 6167 |         awake = new StatusChanger(statusAwake); | 
| 6168 |         abouttoblock = new StatusChanger(statusAboutToBlock); | 
| 6169 |         QCOMPARE(*statusAwake, 1); | 
| 6170 |         QCOMPARE(*statusAboutToBlock, 1); | 
| 6171 |         connect(sender: QAbstractEventDispatcher::instance(), SIGNAL(awake()), receiver: this, SLOT(onAwake())); | 
| 6172 |         connect(sender: QAbstractEventDispatcher::instance(), SIGNAL(aboutToBlock()), receiver: this, SLOT(onAboutToBlock())); | 
| 6173 |  | 
| 6174 |     } | 
| 6175 |  | 
| 6176 |     ~DispatcherWatcher() | 
| 6177 |     { | 
| 6178 |         if (awake) | 
| 6179 |             awake->deleteLater(); | 
| 6180 |         if (abouttoblock) | 
| 6181 |             abouttoblock->deleteLater(); | 
| 6182 |     } | 
| 6183 |  | 
| 6184 | public slots: | 
| 6185 |     // The order of these 2 handlers differs on different event dispatchers | 
| 6186 |     void onAboutToBlock() | 
| 6187 |     { | 
| 6188 |         if (abouttoblock) { | 
| 6189 |             abouttoblock->deleteLater(); | 
| 6190 |             abouttoblock = 0; | 
| 6191 |         } | 
| 6192 |         ++m_aboutToBlocks; | 
| 6193 |     } | 
| 6194 |     void onAwake() | 
| 6195 |     { | 
| 6196 |         if (awake) { | 
| 6197 |             awake->deleteLater(); | 
| 6198 |             awake = 0; | 
| 6199 |         } | 
| 6200 |         ++m_awakes; | 
| 6201 |  | 
| 6202 |     } | 
| 6203 |     void onSignal1() | 
| 6204 |     { | 
| 6205 |         // Status check. At this point the event loop should have spinned enough to delete all the objects. | 
| 6206 |         QCOMPARE(*m_statusAwake, 2); | 
| 6207 |         QCOMPARE(*m_statusAboutToBlock, 2); | 
| 6208 |         QMetaObject::invokeMethod(obj: m_eventLoop, member: "quit" , type: Qt::QueuedConnection); | 
| 6209 |     } | 
| 6210 |  | 
| 6211 | private: | 
| 6212 |     StatusChanger *awake; | 
| 6213 |     StatusChanger *abouttoblock; | 
| 6214 |     QEventLoop    *m_eventLoop; | 
| 6215 |     int *m_statusAwake; | 
| 6216 |     int *m_statusAboutToBlock; | 
| 6217 |     int m_aboutToBlocks; | 
| 6218 |     int m_awakes; | 
| 6219 | }; | 
| 6220 |  | 
| 6221 |  | 
| 6222 | void tst_QObject::deleteLaterInAboutToBlockHandler() | 
| 6223 | { | 
| 6224 |     int statusAwake        = 1; | 
| 6225 |     int statusAboutToBlock = 1; | 
| 6226 |     QEventLoop e; | 
| 6227 |     DispatcherWatcher dw(e, &statusAwake, &statusAboutToBlock); | 
| 6228 |     QTimer::singleShot(interval: 2000, receiver: &dw, slot: &DispatcherWatcher::onSignal1); | 
| 6229 |  | 
| 6230 |     QCOMPARE(statusAwake, 1); | 
| 6231 |     QCOMPARE(statusAboutToBlock, 1); | 
| 6232 |     e.exec(); | 
| 6233 |     QCOMPARE(statusAwake, 2); | 
| 6234 |     QCOMPARE(statusAboutToBlock, 2); | 
| 6235 | } | 
| 6236 |  | 
| 6237 | void tst_QObject::connectFunctorWithContextUnique() | 
| 6238 | { | 
| 6239 |     // Qt::UniqueConnections currently don't work for functors, but we need to | 
| 6240 |     // be sure that they don't crash. If that is implemented, change this test. | 
| 6241 |  | 
| 6242 |     SenderObject sender; | 
| 6243 |     ReceiverObject receiver; | 
| 6244 |     QObject::connect(sender: &sender, signal: &SenderObject::signal1, receiver: &receiver, slot: &ReceiverObject::slot1); | 
| 6245 |     receiver.count_slot1 = 0; | 
| 6246 |  | 
| 6247 |     QObject::connect(sender: &sender, signal: &SenderObject::signal1, context: &receiver, slot: SlotFunctor(), type: Qt::UniqueConnection); | 
| 6248 |  | 
| 6249 |     sender.emitSignal1(); | 
| 6250 |     QCOMPARE(receiver.count_slot1, 1); | 
| 6251 | } | 
| 6252 |  | 
| 6253 | class MyFunctor | 
| 6254 | { | 
| 6255 | public: | 
| 6256 |     explicit MyFunctor(QObject *objectToDisconnect) | 
| 6257 |         : m_objectToDisconnect(objectToDisconnect) | 
| 6258 |     {} | 
| 6259 |  | 
| 6260 |     ~MyFunctor() { | 
| 6261 |         playWithObjects(); | 
| 6262 |     } | 
| 6263 |  | 
| 6264 |     void operator()() { | 
| 6265 |         // This will cause the slot object associated with this functor to be destroyed after | 
| 6266 |         // this function returns. That in turn will destroy this functor. | 
| 6267 |         // If our dtor runs with the signalSlotLock held, the bunch of connect() | 
| 6268 |         // performed there will deadlock trying to lock that lock again. | 
| 6269 |         m_objectToDisconnect->disconnect(); | 
| 6270 |     } | 
| 6271 |  | 
| 6272 | private: | 
| 6273 |     QObject *m_objectToDisconnect; | 
| 6274 | }; | 
| 6275 |  | 
| 6276 | void tst_QObject::connectFunctorDeadlock() | 
| 6277 | { | 
| 6278 |     SenderObject sender; | 
| 6279 |     MyFunctor functor(&sender); | 
| 6280 |     QObject::connect(sender: &sender, signal: &SenderObject::signal1, slot: functor); | 
| 6281 |     sender.emitSignal1(); | 
| 6282 | } | 
| 6283 |  | 
| 6284 | void tst_QObject::connectFunctorMoveOnly() | 
| 6285 | { | 
| 6286 |     struct MoveOnlyFunctor { | 
| 6287 |         Q_DISABLE_COPY(MoveOnlyFunctor) | 
| 6288 |         MoveOnlyFunctor(int *status) : status(status) {} | 
| 6289 |         MoveOnlyFunctor(MoveOnlyFunctor &&o) : status(o.status) { o.status = nullptr; }; | 
| 6290 |         void operator()(int i) { *status = i; } | 
| 6291 |         void operator()() { *status = -8; } | 
| 6292 |         int *status; | 
| 6293 |     }; | 
| 6294 |  | 
| 6295 |     int status = 1; | 
| 6296 |     SenderObject obj; | 
| 6297 |     QEventLoop e; | 
| 6298 |  | 
| 6299 |     connect(sender: &obj, signal: &SenderObject::signal1, slot: MoveOnlyFunctor(&status)); | 
| 6300 |     QCOMPARE(status, 1); | 
| 6301 |     obj.signal1(); | 
| 6302 |     QCOMPARE(status, -8); | 
| 6303 |  | 
| 6304 |     connect(sender: &obj, signal: &SenderObject::signal7, slot: MoveOnlyFunctor(&status)); | 
| 6305 |     QCOMPARE(status, -8); | 
| 6306 |     obj.signal7(7888, "Hello" ); | 
| 6307 |     QCOMPARE(status, 7888); | 
| 6308 |  | 
| 6309 |     // With a context | 
| 6310 |     status = 1; | 
| 6311 |     connect(sender: &obj, signal: &SenderObject::signal2, context: this, slot: MoveOnlyFunctor(&status)); | 
| 6312 |     QCOMPARE(status, 1); | 
| 6313 |     obj.signal2(); | 
| 6314 |     QCOMPARE(status, -8); | 
| 6315 |  | 
| 6316 |     // QueuedConnection | 
| 6317 |     status = 1; | 
| 6318 |     connect(sender: &obj, signal: &SenderObject::signal3, context: this, slot: MoveOnlyFunctor(&status), type: Qt::QueuedConnection); | 
| 6319 |     obj.signal3(); | 
| 6320 |     QCOMPARE(status, 1); | 
| 6321 |     QCoreApplication::processEvents(); | 
| 6322 |     QCOMPARE(status, -8); | 
| 6323 | } | 
| 6324 |  | 
| 6325 | static int s_static_slot_checker = 1; | 
| 6326 |  | 
| 6327 | class StaticSlotChecker : public QObject | 
| 6328 | { | 
| 6329 |     Q_OBJECT | 
| 6330 | public Q_SLOTS: | 
| 6331 |     static void staticSlot() { s_static_slot_checker = 2; } | 
| 6332 | }; | 
| 6333 |  | 
| 6334 | void tst_QObject::connectStaticSlotWithObject() | 
| 6335 | { | 
| 6336 |     SenderObject sender; | 
| 6337 |     StaticSlotChecker *receiver = new StaticSlotChecker; | 
| 6338 |     QEventLoop e; | 
| 6339 |  | 
| 6340 |     QVERIFY(connect(&sender, &SenderObject::signal1, receiver, &StaticSlotChecker::staticSlot, Qt::QueuedConnection)); | 
| 6341 |     connect(sender: &sender, signal: &SenderObject::signal1, receiver: &e, slot: &QEventLoop::quit, type: Qt::QueuedConnection); | 
| 6342 |  | 
| 6343 |     sender.emitSignal1(); | 
| 6344 |     QCOMPARE(s_static_slot_checker, 1); | 
| 6345 |     e.exec(); | 
| 6346 |     QCOMPARE(s_static_slot_checker, 2); | 
| 6347 |  | 
| 6348 |     s_static_slot_checker = 1; | 
| 6349 |  | 
| 6350 |     connect(sender: receiver, signal: &QObject::destroyed, receiver: &sender, slot: &SenderObject::signal1, type: Qt::QueuedConnection); | 
| 6351 |     receiver->deleteLater(); | 
| 6352 |  | 
| 6353 |     QCOMPARE(s_static_slot_checker, 1); | 
| 6354 |     e.exec(); | 
| 6355 |     QCOMPARE(s_static_slot_checker, 1); | 
| 6356 | } | 
| 6357 |  | 
| 6358 | struct ComplexFunctor { | 
| 6359 |     ComplexFunctor(int &overload, QList<QVariant> &result) : overload(overload), result(result) {} | 
| 6360 |     void operator()(int a, int b) { | 
| 6361 |         overload = 1; | 
| 6362 |         result << a << b; | 
| 6363 |     } | 
| 6364 |     void operator()(double a, double b) { | 
| 6365 |         overload = 2; | 
| 6366 |         result << a << b; | 
| 6367 |     } | 
| 6368 |     void operator()(const QString &s) { | 
| 6369 |         overload = 3; | 
| 6370 |         result << s; | 
| 6371 |     } | 
| 6372 |     void operator()(const QString &) const { | 
| 6373 |         Q_ASSERT(!"Should not be called because the non-const one should" ); | 
| 6374 |         overload = -1; | 
| 6375 |     } | 
| 6376 |     template<typename T1, typename T2, typename T3, typename T4> | 
| 6377 |     void operator()(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4) { | 
| 6378 |         overload = 4; | 
| 6379 |         result << QVariant::fromValue(t1) << QVariant::fromValue(t2) << QVariant::fromValue(t3) << QVariant::fromValue(t4); | 
| 6380 |     } | 
| 6381 |     int &overload; | 
| 6382 |     QList<QVariant> &result; | 
| 6383 | protected: | 
| 6384 |     void operator()() const { | 
| 6385 |         Q_ASSERT(!"Should not be called because it is protected" ); | 
| 6386 |         overload = -1; | 
| 6387 |     } | 
| 6388 | }; | 
| 6389 |  | 
| 6390 | struct ComplexFunctorDeriv : ComplexFunctor { | 
| 6391 |     ComplexFunctorDeriv(int &overload, QList<QVariant> &result) : ComplexFunctor(overload, result) {} | 
| 6392 |  | 
| 6393 |     void operator()() const { | 
| 6394 |         overload = 10; | 
| 6395 |     } | 
| 6396 |     void operator()(int a, int b) { | 
| 6397 |         overload = 11; | 
| 6398 |         result << a << b; | 
| 6399 |     } | 
| 6400 |     using ComplexFunctor::operator(); | 
| 6401 | private: | 
| 6402 |     void operator()(int) { | 
| 6403 |         Q_ASSERT(!"Should not be called because it is private" ); | 
| 6404 |         overload = -1; | 
| 6405 |     } | 
| 6406 | }; | 
| 6407 |  | 
| 6408 | class FunctorArgDifferenceObject : public QObject | 
| 6409 | { | 
| 6410 |     Q_OBJECT | 
| 6411 | signals: | 
| 6412 |     void signal_ii(int,int); | 
| 6413 |     void signal_iiS(int,int, const QString &); | 
| 6414 |     void signal_dd(double,double); | 
| 6415 |     void signal_ddS(double,double, const QString &); | 
| 6416 |     void signal_S(const QString &); | 
| 6417 |     void signal_SSSS(const QString &, const QString &, const QString &, const QString &); | 
| 6418 |     void signal_iiSS(int, int, const QString &, const QString &); | 
| 6419 |     void signal_VV(const QVariant &, const QVariant &); | 
| 6420 | }; | 
| 6421 |  | 
| 6422 | template<typename Functor, typename Signal> | 
| 6423 | void connectFunctorOverload_impl(Signal signal, int expOverload, QList<QVariant> expResult) | 
| 6424 | { | 
| 6425 |     FunctorArgDifferenceObject obj; | 
| 6426 |     int overload; | 
| 6427 |     QList<QVariant> result; | 
| 6428 |     QVERIFY(QObject::connect(&obj, signal, Functor(overload, result))); | 
| 6429 |  | 
| 6430 |     obj.signal_ii(1,2); | 
| 6431 |     obj.signal_iiS(3,4,"5" ); | 
| 6432 |     obj.signal_dd(6.6,7.7); | 
| 6433 |     obj.signal_ddS(8.8,9.9,"10" ); | 
| 6434 |     obj.signal_S("11" ); | 
| 6435 |     obj.signal_SSSS("12" , "13" , "14" , "15" ); | 
| 6436 |     obj.signal_iiSS(16, 17, "18" , "19" ); | 
| 6437 |     obj.signal_VV(20,21); | 
| 6438 |  | 
| 6439 |     QCOMPARE(overload, expOverload); | 
| 6440 |     QCOMPARE(result, expResult); | 
| 6441 | } | 
| 6442 |  | 
| 6443 | void tst_QObject::connectFunctorOverloads() | 
| 6444 | { | 
| 6445 | #if defined (Q_COMPILER_VARIADIC_TEMPLATES) | 
| 6446 |     connectFunctorOverload_impl<ComplexFunctor>(signal: &FunctorArgDifferenceObject::signal_ii, expOverload: 1, | 
| 6447 |                                 expResult: (QList<QVariant>() << 1 << 2)); | 
| 6448 |     connectFunctorOverload_impl<ComplexFunctor>(signal: &FunctorArgDifferenceObject::signal_iiS, expOverload: 1, | 
| 6449 |                                 expResult: (QList<QVariant>() << 3 << 4)); | 
| 6450 |     connectFunctorOverload_impl<ComplexFunctor>(signal: &FunctorArgDifferenceObject::signal_dd, expOverload: 2, | 
| 6451 |                                 expResult: (QList<QVariant>() << 6.6 << 7.7)); | 
| 6452 |     connectFunctorOverload_impl<ComplexFunctor>(signal: &FunctorArgDifferenceObject::signal_ddS, expOverload: 2, | 
| 6453 |                                 expResult: (QList<QVariant>() << 8.8 << 9.9)); | 
| 6454 |     connectFunctorOverload_impl<ComplexFunctor>(signal: &FunctorArgDifferenceObject::signal_S, expOverload: 3, | 
| 6455 |                                 expResult: (QList<QVariant>() << QString("11" ))); | 
| 6456 |     connectFunctorOverload_impl<ComplexFunctor>(signal: &FunctorArgDifferenceObject::signal_SSSS, expOverload: 4, | 
| 6457 |                                 expResult: (QList<QVariant>() << QString("12" ) << QString("13" ) << QString("14" ) << QString("15" ))); | 
| 6458 |     connectFunctorOverload_impl<ComplexFunctor>(signal: &FunctorArgDifferenceObject::signal_iiSS, expOverload: 4, | 
| 6459 |                                 expResult: (QList<QVariant>() << 16 << 17 << QString("18" ) << QString("19" ))); | 
| 6460 |     connectFunctorOverload_impl<ComplexFunctorDeriv>(signal: &FunctorArgDifferenceObject::signal_ii, expOverload: 11, | 
| 6461 |                                 expResult: (QList<QVariant>() << 1 << 2)); | 
| 6462 |     connectFunctorOverload_impl<ComplexFunctorDeriv>(signal: &FunctorArgDifferenceObject::signal_iiS, expOverload: 11, | 
| 6463 |                                 expResult: (QList<QVariant>() << 3 << 4)); | 
| 6464 |     connectFunctorOverload_impl<ComplexFunctorDeriv>(signal: &FunctorArgDifferenceObject::signal_dd, expOverload: 2, | 
| 6465 |                                 expResult: (QList<QVariant>() << 6.6 << 7.7)); | 
| 6466 |     connectFunctorOverload_impl<ComplexFunctorDeriv>(signal: &FunctorArgDifferenceObject::signal_ddS, expOverload: 2, | 
| 6467 |                                 expResult: (QList<QVariant>() << 8.8 << 9.9)); | 
| 6468 |     connectFunctorOverload_impl<ComplexFunctorDeriv>(signal: &FunctorArgDifferenceObject::signal_S, expOverload: 3, | 
| 6469 |                                 expResult: (QList<QVariant>() << QString("11" ))); | 
| 6470 |     connectFunctorOverload_impl<ComplexFunctorDeriv>(signal: &FunctorArgDifferenceObject::signal_SSSS, expOverload: 4, | 
| 6471 |                                 expResult: (QList<QVariant>() << QString("12" ) << QString("13" ) << QString("14" ) << QString("15" ))); | 
| 6472 |     connectFunctorOverload_impl<ComplexFunctorDeriv>(signal: &FunctorArgDifferenceObject::signal_iiSS, expOverload: 4, | 
| 6473 |                                 expResult: (QList<QVariant>() << 16 << 17 << QString("18" ) << QString("19" ))); | 
| 6474 |     connectFunctorOverload_impl<ComplexFunctorDeriv>(signal: &FunctorArgDifferenceObject::signal_VV, expOverload: 10, | 
| 6475 |                                 expResult: (QList<QVariant>())); | 
| 6476 |  | 
| 6477 |  | 
| 6478 | #else | 
| 6479 |     QSKIP("Does not compile without C++11 variadic template" ); | 
| 6480 | #endif | 
| 6481 | } | 
| 6482 |  | 
| 6483 | class GetSenderObject : public QObject | 
| 6484 | { | 
| 6485 |     Q_OBJECT | 
| 6486 | public: | 
| 6487 |     using QObject::sender; // make public | 
| 6488 |  | 
| 6489 | public Q_SLOTS: | 
| 6490 |     void triggerSignal() { Q_EMIT aSignal(); } | 
| 6491 |  | 
| 6492 | Q_SIGNALS: | 
| 6493 |     void aSignal(); | 
| 6494 | }; | 
| 6495 |  | 
| 6496 | static int countedStructObjectsCount = 0; | 
| 6497 | struct CountedStruct | 
| 6498 | { | 
| 6499 |     CountedStruct() : sender(nullptr) { ++countedStructObjectsCount; } | 
| 6500 |     CountedStruct(GetSenderObject *sender) : sender(sender) { ++countedStructObjectsCount; } | 
| 6501 |     CountedStruct(const CountedStruct &o) : sender(o.sender) { ++countedStructObjectsCount; } | 
| 6502 |     CountedStruct &operator=(const CountedStruct &) { return *this; } | 
| 6503 |     // calling sender() here allows us to check if there's a deadlock | 
| 6504 |     ~CountedStruct() { --countedStructObjectsCount; if (sender) (void)sender->sender(); } | 
| 6505 |     void operator()() const { } | 
| 6506 |  | 
| 6507 |     GetSenderObject *sender; | 
| 6508 | }; | 
| 6509 |  | 
| 6510 | void tst_QObject::disconnectDoesNotLeakFunctor() | 
| 6511 | { | 
| 6512 |     QCOMPARE(countedStructObjectsCount, 0); | 
| 6513 |     { | 
| 6514 |         GetSenderObject obj; | 
| 6515 |         QMetaObject::Connection c; | 
| 6516 |         { | 
| 6517 |             CountedStruct s(&obj); | 
| 6518 |             QCOMPARE(countedStructObjectsCount, 1); | 
| 6519 |  | 
| 6520 |             c = connect(sender: &obj, signal: &GetSenderObject::aSignal, slot: s); | 
| 6521 |             QVERIFY(c); | 
| 6522 |             QCOMPARE(countedStructObjectsCount, 2); | 
| 6523 |             QVERIFY(QObject::disconnect(c)); | 
| 6524 |             QCOMPARE(countedStructObjectsCount, 1); | 
| 6525 |         } | 
| 6526 |         QCOMPARE(countedStructObjectsCount, 0); | 
| 6527 |     } | 
| 6528 |     QCOMPARE(countedStructObjectsCount, 0); | 
| 6529 |     { | 
| 6530 |         GetSenderObject obj; | 
| 6531 |         QMetaObject::Connection c; | 
| 6532 |         { | 
| 6533 |             CountedStruct s(&obj); | 
| 6534 |             QObject context; | 
| 6535 |             QCOMPARE(countedStructObjectsCount, 1); | 
| 6536 |  | 
| 6537 |             c = connect(sender: &obj, signal: &GetSenderObject::aSignal, context: &context, slot: s); | 
| 6538 |             QVERIFY(c); | 
| 6539 |             QCOMPARE(countedStructObjectsCount, 2); | 
| 6540 |             QVERIFY(QObject::disconnect(c)); | 
| 6541 |             QCOMPARE(countedStructObjectsCount, 1); | 
| 6542 |         } | 
| 6543 |         QCOMPARE(countedStructObjectsCount, 0); | 
| 6544 |     } | 
| 6545 |     QCOMPARE(countedStructObjectsCount, 0); | 
| 6546 |     { | 
| 6547 |         QMetaObject::Connection c1, c2; | 
| 6548 |         { | 
| 6549 |             CountedStruct s; | 
| 6550 |             QCOMPARE(countedStructObjectsCount, 1); | 
| 6551 |             QTimer timer; | 
| 6552 |  | 
| 6553 |             c1 = connect(sender: &timer, signal: &QTimer::timeout, slot: s); | 
| 6554 |             QVERIFY(c1); | 
| 6555 |             c2 = c1; | 
| 6556 |             QVERIFY(c2); | 
| 6557 |             QCOMPARE(countedStructObjectsCount, 2); | 
| 6558 |             QVERIFY(QObject::disconnect(c1)); | 
| 6559 |             QVERIFY(!c1); | 
| 6560 |             QVERIFY(!c2); | 
| 6561 |             // functor object has been destroyed | 
| 6562 |             QCOMPARE(countedStructObjectsCount, 1); | 
| 6563 |             QVERIFY(!QObject::disconnect(c2)); | 
| 6564 |             QCOMPARE(countedStructObjectsCount, 1); | 
| 6565 |         } | 
| 6566 |         QCOMPARE(countedStructObjectsCount, 0); | 
| 6567 |     } | 
| 6568 |     QCOMPARE(countedStructObjectsCount, 0); | 
| 6569 |     { | 
| 6570 |         CountedStruct s; | 
| 6571 |         QCOMPARE(countedStructObjectsCount, 1); | 
| 6572 |         QTimer timer; | 
| 6573 |  | 
| 6574 |         QMetaObject::Connection c = connect(sender: &timer, signal: &QTimer::timeout, slot: s); | 
| 6575 |         QVERIFY(c); | 
| 6576 |         QCOMPARE(countedStructObjectsCount, 2); | 
| 6577 |         QVERIFY(QObject::disconnect(c)); | 
| 6578 |         QCOMPARE(countedStructObjectsCount, 1); | 
| 6579 |     } | 
| 6580 |     QCOMPARE(countedStructObjectsCount, 0); | 
| 6581 |     { | 
| 6582 |         QTimer timer; | 
| 6583 |  | 
| 6584 |         QMetaObject::Connection c = connect(sender: &timer, signal: &QTimer::timeout, slot: CountedStruct()); | 
| 6585 |         QVERIFY(c); | 
| 6586 |         QCOMPARE(countedStructObjectsCount, 1); // only one instance, in Qt internals | 
| 6587 |         QVERIFY(QObject::disconnect(c)); | 
| 6588 |         QCOMPARE(countedStructObjectsCount, 0); // functor being destroyed | 
| 6589 |     } | 
| 6590 |     QCOMPARE(countedStructObjectsCount, 0); | 
| 6591 |     { | 
| 6592 |         QTimer *timer = new QTimer; | 
| 6593 |         QEventLoop e; | 
| 6594 |  | 
| 6595 |         connect(sender: timer, signal: &QTimer::timeout, slot: CountedStruct()); | 
| 6596 |         QCOMPARE(countedStructObjectsCount, 1); // only one instance, in Qt internals | 
| 6597 |         timer->deleteLater(); | 
| 6598 |         connect(sender: timer, signal: &QObject::destroyed, receiver: &e, slot: &QEventLoop::quit, type: Qt::QueuedConnection); | 
| 6599 |         e.exec(); | 
| 6600 |         QCOMPARE(countedStructObjectsCount, 0); // functor being destroyed | 
| 6601 |     } | 
| 6602 |     QCOMPARE(countedStructObjectsCount, 0); | 
| 6603 |     { | 
| 6604 |         GetSenderObject obj; | 
| 6605 |  | 
| 6606 |         connect(sender: &obj, signal: &GetSenderObject::aSignal, slot: CountedStruct(&obj)); | 
| 6607 |         QCOMPARE(countedStructObjectsCount, 1); | 
| 6608 |     } | 
| 6609 |     QCOMPARE(countedStructObjectsCount, 0); | 
| 6610 |     { | 
| 6611 |         GetSenderObject obj; | 
| 6612 |  | 
| 6613 |         connect(sender: &obj, signal: &GetSenderObject::aSignal, slot: CountedStruct(&obj)); | 
| 6614 |         QCOMPARE(countedStructObjectsCount, 1); | 
| 6615 |         QObject::disconnect(sender: &obj, signal: &GetSenderObject::aSignal, receiver: 0, zero: 0); | 
| 6616 |     } | 
| 6617 |     QCOMPARE(countedStructObjectsCount, 0); | 
| 6618 |     { | 
| 6619 |         CountedStruct s; | 
| 6620 |         QCOMPARE(countedStructObjectsCount, 1); | 
| 6621 |         QTimer timer; | 
| 6622 |  | 
| 6623 |         QMetaObject::Connection c = connect(sender: &timer, signal: &QTimer::timeout, slot: [s](){}); | 
| 6624 |         QVERIFY(c); | 
| 6625 |         QCOMPARE(countedStructObjectsCount, 2); | 
| 6626 |         QVERIFY(QObject::disconnect(c)); | 
| 6627 |         QCOMPARE(countedStructObjectsCount, 1); | 
| 6628 |     } | 
| 6629 |     QCOMPARE(countedStructObjectsCount, 0); | 
| 6630 | } | 
| 6631 |  | 
| 6632 | void tst_QObject::contextDoesNotLeakFunctor() | 
| 6633 | { | 
| 6634 |     QCOMPARE(countedStructObjectsCount, 0); | 
| 6635 |     { | 
| 6636 |         QMetaObject::Connection c; | 
| 6637 |         { | 
| 6638 |             QEventLoop e; | 
| 6639 |             ContextObject *context = new ContextObject; | 
| 6640 |             SenderObject obj; | 
| 6641 |  | 
| 6642 |             connect(sender: &obj, signal: &SenderObject::signal1, context, slot: CountedStruct()); | 
| 6643 |             connect(sender: context, signal: &QObject::destroyed, receiver: &e, slot: &QEventLoop::quit, type: Qt::QueuedConnection); | 
| 6644 |             context->deleteLater(); | 
| 6645 |  | 
| 6646 |             QCOMPARE(countedStructObjectsCount, 1); | 
| 6647 |             e.exec(); | 
| 6648 |             QCOMPARE(countedStructObjectsCount, 0); | 
| 6649 |         } | 
| 6650 |         QCOMPARE(countedStructObjectsCount, 0); | 
| 6651 |     } | 
| 6652 |     QCOMPARE(countedStructObjectsCount, 0); | 
| 6653 |     { | 
| 6654 |         GetSenderObject obj; | 
| 6655 |         QMetaObject::Connection c; | 
| 6656 |         { | 
| 6657 |             CountedStruct s(&obj); | 
| 6658 |             QEventLoop e; | 
| 6659 |             ContextObject *context = new ContextObject; | 
| 6660 |             QCOMPARE(countedStructObjectsCount, 1); | 
| 6661 |  | 
| 6662 |             connect(sender: &obj, signal: &GetSenderObject::aSignal, context, slot: s); | 
| 6663 |             QCOMPARE(countedStructObjectsCount, 2); | 
| 6664 |  | 
| 6665 |             connect(sender: context, signal: &QObject::destroyed, receiver: &e, slot: &QEventLoop::quit, type: Qt::QueuedConnection); | 
| 6666 |             context->deleteLater(); | 
| 6667 |  | 
| 6668 |             e.exec(); | 
| 6669 |             QCOMPARE(countedStructObjectsCount, 1); | 
| 6670 |         } | 
| 6671 |         QCOMPARE(countedStructObjectsCount, 0); | 
| 6672 |     } | 
| 6673 |     QCOMPARE(countedStructObjectsCount, 0); | 
| 6674 |     { | 
| 6675 |         CountedStruct s; | 
| 6676 |         QEventLoop e; | 
| 6677 |         ContextObject *context = new ContextObject; | 
| 6678 |         QCOMPARE(countedStructObjectsCount, 1); | 
| 6679 |         QTimer timer; | 
| 6680 |  | 
| 6681 |         connect(sender: &timer, signal: &QTimer::timeout, context, slot: [s](){}); | 
| 6682 |         QCOMPARE(countedStructObjectsCount, 2); | 
| 6683 |         connect(sender: context, signal: &QObject::destroyed, receiver: &e, slot: &QEventLoop::quit, type: Qt::QueuedConnection); | 
| 6684 |         context->deleteLater(); | 
| 6685 |         e.exec(); | 
| 6686 |         QCOMPARE(countedStructObjectsCount, 1); | 
| 6687 |     } | 
| 6688 |     QCOMPARE(countedStructObjectsCount, 0); | 
| 6689 | } | 
| 6690 |  | 
| 6691 | class SubSender : public SenderObject { | 
| 6692 |     Q_OBJECT | 
| 6693 | }; | 
| 6694 |  | 
| 6695 | void tst_QObject::connectBase() | 
| 6696 | { | 
| 6697 |     SubSender sub; | 
| 6698 |     ReceiverObject r1; | 
| 6699 |     r1.reset(); | 
| 6700 |  | 
| 6701 |     QVERIFY( connect( &sub, &SubSender::signal1 , &r1, &ReceiverObject::slot1 ) ); | 
| 6702 |     QVERIFY( connect( &sub, static_cast<void (SenderObject::*)()>(&SubSender::signal2) , &r1, &ReceiverObject::slot2 ) ); | 
| 6703 |     QVERIFY( connect( &sub, static_cast<void (SubSender::*)()>(&SubSender::signal3) , &r1, &ReceiverObject::slot3 ) ); | 
| 6704 |  | 
| 6705 |     sub.emitSignal1(); | 
| 6706 |     sub.emitSignal2(); | 
| 6707 |     sub.emitSignal3(); | 
| 6708 |  | 
| 6709 |     QCOMPARE( r1.count_slot1, 1 ); | 
| 6710 |     QCOMPARE( r1.count_slot2, 1 ); | 
| 6711 |     QCOMPARE( r1.count_slot3, 1 ); | 
| 6712 |  | 
| 6713 |     QVERIFY( QObject::disconnect( &sub, &SubSender::signal1 , &r1, &ReceiverObject::slot1 ) ); | 
| 6714 |     QVERIFY( QObject::disconnect( &sub, static_cast<void (SenderObject::*)()>(&SubSender::signal2) , &r1, &ReceiverObject::slot2 ) ); | 
| 6715 |     QVERIFY( QObject::disconnect( &sub, static_cast<void (SubSender::*)()>(&SubSender::signal3) , &r1, &ReceiverObject::slot3 ) ); | 
| 6716 |  | 
| 6717 |     sub.emitSignal1(); | 
| 6718 |     sub.emitSignal2(); | 
| 6719 |     sub.emitSignal3(); | 
| 6720 |  | 
| 6721 |     QCOMPARE( r1.count_slot1, 1 ); | 
| 6722 |     QCOMPARE( r1.count_slot2, 1 ); | 
| 6723 |     QCOMPARE( r1.count_slot3, 1 ); | 
| 6724 | } | 
| 6725 |  | 
| 6726 | void tst_QObject::connectWarnings() | 
| 6727 | { | 
| 6728 |     SubSender sub; | 
| 6729 |     SenderObject obj; | 
| 6730 |     ReceiverObject r1; | 
| 6731 |     r1.reset(); | 
| 6732 |  | 
| 6733 |     QTest::ignoreMessage(type: QtWarningMsg, message: "QObject::connect(SenderObject, ReceiverObject): invalid nullptr parameter" ); | 
| 6734 |     connect(sender: static_cast<const SenderObject *>(nullptr), signal: &SubSender::signal1, receiver: &r1, slot: &ReceiverObject::slot1); | 
| 6735 |  | 
| 6736 |     QTest::ignoreMessage(type: QtWarningMsg, message: "QObject::connect(SubSender, Unknown): invalid nullptr parameter" ); | 
| 6737 |     connect(sender: &sub, signal: &SubSender::signal1, receiver: static_cast<ReceiverObject *>(nullptr), slot: &ReceiverObject::slot1); | 
| 6738 |  | 
| 6739 |     QTest::ignoreMessage(type: QtWarningMsg, message: "QObject::connect(SenderObject, ReceiverObject): invalid nullptr parameter" ); | 
| 6740 |     connect(sender: static_cast<const SenderObject *>(nullptr), signal: &SenderObject::signal1, receiver: &r1, slot: &ReceiverObject::slot1); | 
| 6741 |  | 
| 6742 |     QTest::ignoreMessage(type: QtWarningMsg, message: "QObject::connect(SenderObject, Unknown): invalid nullptr parameter" ); | 
| 6743 |     connect(sender: &obj, signal: &SenderObject::signal1, receiver: static_cast<ReceiverObject *>(nullptr), slot: &ReceiverObject::slot1); | 
| 6744 | } | 
| 6745 |  | 
| 6746 | struct QmlReceiver : public QtPrivate::QSlotObjectBase | 
| 6747 | { | 
| 6748 |     int callCount; | 
| 6749 |     void *magic; | 
| 6750 |  | 
| 6751 |     QmlReceiver() | 
| 6752 |         : QtPrivate::QSlotObjectBase(&impl) | 
| 6753 |         , callCount(0) | 
| 6754 |         , magic(0) | 
| 6755 |     {} | 
| 6756 |  | 
| 6757 |     static void impl(int which, QSlotObjectBase *this_, QObject *, void **metaArgs, bool *ret) | 
| 6758 |     { | 
| 6759 |         switch (which) { | 
| 6760 |         case Destroy: delete static_cast<QmlReceiver*>(this_); return; | 
| 6761 |         case Call: static_cast<QmlReceiver*>(this_)->callCount++; return; | 
| 6762 |         case Compare: *ret = static_cast<QmlReceiver*>(this_)->magic == metaArgs[0]; return; | 
| 6763 |         case NumOperations: break; | 
| 6764 |         } | 
| 6765 |     } | 
| 6766 | }; | 
| 6767 |  | 
| 6768 | void tst_QObject::qmlConnect() | 
| 6769 | { | 
| 6770 | #ifdef QT_BUILD_INTERNAL | 
| 6771 |     SenderObject sender; | 
| 6772 |     QmlReceiver *receiver = new QmlReceiver; | 
| 6773 |     receiver->magic = receiver; | 
| 6774 |     receiver->ref(); | 
| 6775 |  | 
| 6776 |     QVERIFY(QObjectPrivate::connect(&sender, sender.metaObject()->indexOfSignal("signal1()" ), | 
| 6777 |                                     receiver, Qt::AutoConnection)); | 
| 6778 |  | 
| 6779 |     QCOMPARE(receiver->callCount, 0); | 
| 6780 |     sender.emitSignal1(); | 
| 6781 |     QCOMPARE(receiver->callCount, 1); | 
| 6782 |  | 
| 6783 |     void *a[] = { | 
| 6784 |         receiver | 
| 6785 |     }; | 
| 6786 |     QVERIFY(QObjectPrivate::disconnect(&sender, sender.metaObject()->indexOfSignal("signal1()" ), reinterpret_cast<void**>(&a))); | 
| 6787 |  | 
| 6788 |     sender.emitSignal1(); | 
| 6789 |     QCOMPARE(receiver->callCount, 1); | 
| 6790 |  | 
| 6791 |     receiver->destroyIfLastRef(); | 
| 6792 | #else | 
| 6793 |     QSKIP("Needs QT_BUILD_INTERNAL" ); | 
| 6794 | #endif | 
| 6795 | } | 
| 6796 |  | 
| 6797 | void tst_QObject::qmlConnectToQObjectReceiver() | 
| 6798 | { | 
| 6799 | #ifdef QT_BUILD_INTERNAL | 
| 6800 |     SenderObject sender; | 
| 6801 |     QScopedPointer<QObject> receiver(new QObject); | 
| 6802 |     QmlReceiver *slotObject = new QmlReceiver; | 
| 6803 |     slotObject->magic = slotObject; | 
| 6804 |     slotObject->ref(); // extra ref so that slot object is not implicitly deleted | 
| 6805 |  | 
| 6806 |     QVERIFY(QObjectPrivate::connect(&sender, sender.metaObject()->indexOfSignal("signal1()" ), | 
| 6807 |                                     receiver.get(), slotObject, Qt::AutoConnection)); | 
| 6808 |  | 
| 6809 |     QCOMPARE(slotObject->callCount, 0); | 
| 6810 |     sender.emitSignal1(); | 
| 6811 |     QCOMPARE(slotObject->callCount, 1); | 
| 6812 |  | 
| 6813 |     receiver.reset(); // this should disconnect the slotObject | 
| 6814 |  | 
| 6815 |     sender.emitSignal1(); | 
| 6816 |     QCOMPARE(slotObject->callCount, 1); | 
| 6817 |  | 
| 6818 |     slotObject->destroyIfLastRef(); | 
| 6819 | #else | 
| 6820 |     QSKIP("Needs QT_BUILD_INTERNAL" ); | 
| 6821 | #endif | 
| 6822 | } | 
| 6823 |  | 
| 6824 | #ifndef QT_NO_EXCEPTIONS | 
| 6825 | class ObjectException : public std::exception { }; | 
| 6826 |  | 
| 6827 | struct ThrowFunctor | 
| 6828 | { | 
| 6829 |     CountedStruct operator()(const CountedStruct &, CountedStruct s2) const | 
| 6830 |     { | 
| 6831 |         throw ObjectException(); | 
| 6832 |         return s2; | 
| 6833 |     } | 
| 6834 |     CountedStruct s; | 
| 6835 | }; | 
| 6836 | #endif | 
| 6837 |  | 
| 6838 | class ExceptionThrower : public QObject | 
| 6839 | { | 
| 6840 |   Q_OBJECT | 
| 6841 | public slots: | 
| 6842 |     CountedStruct throwException(const CountedStruct &, CountedStruct s2) | 
| 6843 |     { | 
| 6844 | #ifndef QT_NO_EXCEPTIONS | 
| 6845 |         throw ObjectException(); | 
| 6846 | #endif | 
| 6847 |         return s2; | 
| 6848 |     } | 
| 6849 | signals: | 
| 6850 |     CountedStruct mySignal(const CountedStruct &s1, CountedStruct s2); | 
| 6851 | }; | 
| 6852 |  | 
| 6853 | class CountedExceptionThrower : public QObject | 
| 6854 | { | 
| 6855 |     Q_OBJECT | 
| 6856 |  | 
| 6857 | public: | 
| 6858 |     explicit CountedExceptionThrower(bool throwException, QObject *parent = nullptr) | 
| 6859 |         : QObject(parent) | 
| 6860 |     { | 
| 6861 |         if (throwException) | 
| 6862 |             throw ObjectException(); | 
| 6863 |         ++counter; | 
| 6864 |     } | 
| 6865 |  | 
| 6866 |     ~CountedExceptionThrower() | 
| 6867 |     { | 
| 6868 |         --counter; | 
| 6869 |     } | 
| 6870 |  | 
| 6871 |     static int counter; | 
| 6872 | }; | 
| 6873 |  | 
| 6874 | int CountedExceptionThrower::counter = 0; | 
| 6875 |  | 
| 6876 | void tst_QObject::exceptions() | 
| 6877 | { | 
| 6878 | #ifndef QT_NO_EXCEPTIONS | 
| 6879 |     ReceiverObject receiver; | 
| 6880 |  | 
| 6881 |     // String based syntax | 
| 6882 |     { | 
| 6883 |         QCOMPARE(countedStructObjectsCount, 0); | 
| 6884 |         ExceptionThrower thrower; | 
| 6885 |         receiver.reset(); | 
| 6886 |  | 
| 6887 |         connect(sender: &thrower, SIGNAL(mySignal(CountedStruct,CountedStruct)), receiver: &receiver, SLOT(slot1())); | 
| 6888 |         connect(sender: &thrower, SIGNAL(mySignal(CountedStruct,CountedStruct)), receiver: &thrower, SLOT(throwException(CountedStruct,CountedStruct))); | 
| 6889 |         connect(sender: &thrower, SIGNAL(mySignal(CountedStruct,CountedStruct)), receiver: &receiver, SLOT(slot2())); | 
| 6890 |         try { | 
| 6891 |             CountedStruct s; | 
| 6892 |             emit thrower.mySignal(s1: s, s2: s); | 
| 6893 |             QFAIL("Exception not thrown?" ); | 
| 6894 |         } catch (ObjectException&) {} | 
| 6895 |         QCOMPARE(receiver.count_slot1, 1); | 
| 6896 |         QCOMPARE(receiver.count_slot2, 0); | 
| 6897 |         QCOMPARE(countedStructObjectsCount, 0); | 
| 6898 |     } | 
| 6899 |     // Pointer to member function | 
| 6900 |     { | 
| 6901 |         QCOMPARE(countedStructObjectsCount, 0); | 
| 6902 |         ExceptionThrower thrower; | 
| 6903 |         receiver.reset(); | 
| 6904 |  | 
| 6905 |         connect(sender: &thrower, signal: &ExceptionThrower::mySignal, receiver: &receiver, slot: &ReceiverObject::slot1); | 
| 6906 |         connect(sender: &thrower, signal: &ExceptionThrower::mySignal, receiver: &thrower, slot: &ExceptionThrower::throwException); | 
| 6907 |         connect(sender: &thrower, signal: &ExceptionThrower::mySignal, receiver: &receiver, slot: &ReceiverObject::slot2); | 
| 6908 |         try { | 
| 6909 |             CountedStruct s; | 
| 6910 |             emit thrower.mySignal(s1: s, s2: s); | 
| 6911 |             QFAIL("Exception not thrown?" ); | 
| 6912 |         } catch (ObjectException&) {} | 
| 6913 |         QCOMPARE(receiver.count_slot1, 1); | 
| 6914 |         QCOMPARE(receiver.count_slot2, 0); | 
| 6915 |         QCOMPARE(countedStructObjectsCount, 0); | 
| 6916 |     } | 
| 6917 |     // Functor | 
| 6918 |     { | 
| 6919 |         QCOMPARE(countedStructObjectsCount, 0); | 
| 6920 |         ExceptionThrower thrower; | 
| 6921 |         receiver.reset(); | 
| 6922 |  | 
| 6923 |         connect(sender: &thrower, signal: &ExceptionThrower::mySignal, receiver: &receiver, slot: &ReceiverObject::slot1); | 
| 6924 |         connect(sender: &thrower, signal: &ExceptionThrower::mySignal, slot: ThrowFunctor()); | 
| 6925 |         connect(sender: &thrower, signal: &ExceptionThrower::mySignal, receiver: &receiver, slot: &ReceiverObject::slot2); | 
| 6926 |         try { | 
| 6927 |             CountedStruct s; | 
| 6928 |             emit thrower.mySignal(s1: s, s2: s); | 
| 6929 |             QFAIL("Exception not thrown?" ); | 
| 6930 |         } catch (ObjectException&) {} | 
| 6931 |         QCOMPARE(receiver.count_slot1, 1); | 
| 6932 |         QCOMPARE(receiver.count_slot2, 0); | 
| 6933 |         QCOMPARE(countedStructObjectsCount, 1); // the Functor | 
| 6934 |     } | 
| 6935 |     QCOMPARE(countedStructObjectsCount, 0); | 
| 6936 |  | 
| 6937 |     // Child object reaping in case of exceptions thrown by constructors | 
| 6938 |     { | 
| 6939 |         QCOMPARE(CountedExceptionThrower::counter, 0); | 
| 6940 |  | 
| 6941 |         try { | 
| 6942 |             class ParentObject : public QObject { | 
| 6943 |             public: | 
| 6944 |                 explicit ParentObject(QObject *parent = nullptr) | 
| 6945 |                     : QObject(parent) | 
| 6946 |                 { | 
| 6947 |                     new CountedExceptionThrower(false, this); | 
| 6948 |                     new CountedExceptionThrower(false, this); | 
| 6949 |                     new CountedExceptionThrower(true, this); // throws | 
| 6950 |                 } | 
| 6951 |             }; | 
| 6952 |  | 
| 6953 |             ParentObject p; | 
| 6954 |             QFAIL("Exception not thrown" ); | 
| 6955 |         } catch (const ObjectException &) { | 
| 6956 |         } catch (...) { | 
| 6957 |             QFAIL("Wrong exception thrown" ); | 
| 6958 |         } | 
| 6959 |  | 
| 6960 |         QCOMPARE(CountedExceptionThrower::counter, 0); | 
| 6961 |  | 
| 6962 |         try { | 
| 6963 |             QObject o; | 
| 6964 |             new CountedExceptionThrower(false, &o); | 
| 6965 |             new CountedExceptionThrower(false, &o); | 
| 6966 |             new CountedExceptionThrower(true, &o); // throws | 
| 6967 |  | 
| 6968 |             QFAIL("Exception not thrown" ); | 
| 6969 |         } catch (const ObjectException &) { | 
| 6970 |         } catch (...) { | 
| 6971 |             QFAIL("Wrong exception thrown" ); | 
| 6972 |         } | 
| 6973 |  | 
| 6974 |         QCOMPARE(CountedExceptionThrower::counter, 0); | 
| 6975 |  | 
| 6976 |         try { | 
| 6977 |             QObject o; | 
| 6978 |             CountedExceptionThrower c1(false, &o); | 
| 6979 |             CountedExceptionThrower c2(false, &o); | 
| 6980 |             CountedExceptionThrower c3(true, &o); // throws | 
| 6981 |  | 
| 6982 |             QFAIL("Exception not thrown" ); | 
| 6983 |         } catch (const ObjectException &) { | 
| 6984 |         } catch (...) { | 
| 6985 |             QFAIL("Wrong exception thrown" ); | 
| 6986 |         } | 
| 6987 |  | 
| 6988 |         QCOMPARE(CountedExceptionThrower::counter, 0); | 
| 6989 |     } | 
| 6990 |  | 
| 6991 | #else | 
| 6992 |     QSKIP("Needs exceptions" ); | 
| 6993 | #endif | 
| 6994 | } | 
| 6995 |  | 
| 6996 | #ifdef QT_BUILD_INTERNAL | 
| 6997 | static bool parentChangeCalled = false; | 
| 6998 |  | 
| 6999 | static void testParentChanged(QAbstractDeclarativeData *, QObject *, QObject *) | 
| 7000 | { | 
| 7001 |     parentChangeCalled = true; | 
| 7002 | } | 
| 7003 | #endif | 
| 7004 |  | 
| 7005 | void tst_QObject::noDeclarativeParentChangedOnDestruction() | 
| 7006 | { | 
| 7007 | #ifdef QT_BUILD_INTERNAL | 
| 7008 |     typedef void (*ParentChangedCallback)(QAbstractDeclarativeData *, QObject *, QObject *); | 
| 7009 |     QScopedValueRollback<ParentChangedCallback> rollback(QAbstractDeclarativeData::parentChanged); | 
| 7010 |     QAbstractDeclarativeData::parentChanged = testParentChanged; | 
| 7011 |  | 
| 7012 |     QObject *parent = new QObject; | 
| 7013 |     QObject *child = new QObject; | 
| 7014 |  | 
| 7015 |     QAbstractDeclarativeDataImpl dummy; | 
| 7016 |     dummy.ownedByQml1 = false; | 
| 7017 |     QObjectPrivate::get(o: child)->declarativeData = &dummy; | 
| 7018 |  | 
| 7019 |     parentChangeCalled = false; | 
| 7020 |     child->setParent(parent); | 
| 7021 |  | 
| 7022 |     QVERIFY(parentChangeCalled); | 
| 7023 |     parentChangeCalled = false; | 
| 7024 |  | 
| 7025 |     delete child; | 
| 7026 |     QVERIFY(!parentChangeCalled); | 
| 7027 |  | 
| 7028 |     delete parent; | 
| 7029 | #else | 
| 7030 |     QSKIP("Needs QT_BUILD_INTERNAL" ); | 
| 7031 | #endif | 
| 7032 | } | 
| 7033 |  | 
| 7034 | struct MutableFunctor { | 
| 7035 |     int count; | 
| 7036 |     MutableFunctor() : count(0) {} | 
| 7037 |     int operator()() { return ++count; } | 
| 7038 | }; | 
| 7039 |  | 
| 7040 | void tst_QObject::mutableFunctor() | 
| 7041 | { | 
| 7042 |     ReturnValue o; | 
| 7043 |     MutableFunctor functor; | 
| 7044 |     QCOMPARE(functor.count, 0); | 
| 7045 |     connect(sender: &o, signal: &ReturnValue::returnInt, slot: functor); | 
| 7046 |     QCOMPARE(emit o.returnInt(0), 1); | 
| 7047 |     QCOMPARE(emit o.returnInt(0), 2); // each emit should increase the internal count | 
| 7048 |  | 
| 7049 |     QCOMPARE(functor.count, 0); // but the original object should have been copied at connect time | 
| 7050 | } | 
| 7051 |  | 
| 7052 | void tst_QObject::checkArgumentsForNarrowing() | 
| 7053 | { | 
| 7054 |     enum UnscopedEnum {}; | 
| 7055 |     enum SignedUnscopedEnum { SignedUnscopedEnumV1 = -1, SignedUnscopedEnumV2 = 1 }; | 
| 7056 |  | 
| 7057 |     // a constexpr would suffice, but MSVC2013 RTM doesn't support them... | 
| 7058 | #define IS_UNSCOPED_ENUM_SIGNED (std::is_signed<typename std::underlying_type<UnscopedEnum>::type>::value) | 
| 7059 |  | 
| 7060 | #define NARROWS_IF(x, y, test) Q_STATIC_ASSERT((QtPrivate::AreArgumentsNarrowedBase<x, y>::value) == (test)) | 
| 7061 | #define FITS_IF(x, y, test)    Q_STATIC_ASSERT((QtPrivate::AreArgumentsNarrowedBase<x, y>::value) != (test)) | 
| 7062 | #define NARROWS(x, y)          NARROWS_IF(x, y, true) | 
| 7063 | #define FITS(x, y)             FITS_IF(x, y, true) | 
| 7064 |  | 
| 7065 |     Q_STATIC_ASSERT(sizeof(UnscopedEnum) <= sizeof(int)); | 
| 7066 |     Q_STATIC_ASSERT(sizeof(SignedUnscopedEnum) <= sizeof(int)); | 
| 7067 |  | 
| 7068 |     // floating point to integral | 
| 7069 |     NARROWS(float, bool); | 
| 7070 |     NARROWS(double, bool); | 
| 7071 |     NARROWS(long double, bool); | 
| 7072 |  | 
| 7073 |     NARROWS(float, char); | 
| 7074 |     NARROWS(double, char); | 
| 7075 |     NARROWS(long double, char); | 
| 7076 |  | 
| 7077 |     NARROWS(float, short); | 
| 7078 |     NARROWS(double, short); | 
| 7079 |     NARROWS(long double, short); | 
| 7080 |  | 
| 7081 |     NARROWS(float, int); | 
| 7082 |     NARROWS(double, int); | 
| 7083 |     NARROWS(long double, int); | 
| 7084 |  | 
| 7085 |     NARROWS(float, long); | 
| 7086 |     NARROWS(double, long); | 
| 7087 |     NARROWS(long double, long); | 
| 7088 |  | 
| 7089 |     NARROWS(float, long long); | 
| 7090 |     NARROWS(double, long long); | 
| 7091 |     NARROWS(long double, long long); | 
| 7092 |  | 
| 7093 |  | 
| 7094 |     // floating point to a smaller floating point | 
| 7095 |     NARROWS_IF(double, float, (sizeof(double) > sizeof(float))); | 
| 7096 |     NARROWS_IF(long double, float, (sizeof(long double) > sizeof(float))); | 
| 7097 |     FITS(float, double); | 
| 7098 |     FITS(float, long double); | 
| 7099 |  | 
| 7100 |     NARROWS_IF(long double, double, (sizeof(long double) > sizeof(double))); | 
| 7101 |     FITS(double, long double); | 
| 7102 |  | 
| 7103 |  | 
| 7104 |     // integral to floating point | 
| 7105 |     NARROWS(bool, float); | 
| 7106 |     NARROWS(bool, double); | 
| 7107 |     NARROWS(bool, long double); | 
| 7108 |  | 
| 7109 |     NARROWS(char, float); | 
| 7110 |     NARROWS(char, double); | 
| 7111 |     NARROWS(char, long double); | 
| 7112 |  | 
| 7113 |     NARROWS(short, float); | 
| 7114 |     NARROWS(short, double); | 
| 7115 |     NARROWS(short, long double); | 
| 7116 |  | 
| 7117 |     NARROWS(int, float); | 
| 7118 |     NARROWS(int, double); | 
| 7119 |     NARROWS(int, long double); | 
| 7120 |  | 
| 7121 |     NARROWS(long, float); | 
| 7122 |     NARROWS(long, double); | 
| 7123 |     NARROWS(long, long double); | 
| 7124 |  | 
| 7125 |     NARROWS(long long, float); | 
| 7126 |     NARROWS(long long, double); | 
| 7127 |     NARROWS(long long, long double); | 
| 7128 |  | 
| 7129 |  | 
| 7130 |     // enum to floating point | 
| 7131 |     NARROWS(UnscopedEnum, float); | 
| 7132 |     NARROWS(UnscopedEnum, double); | 
| 7133 |     NARROWS(UnscopedEnum, long double); | 
| 7134 |  | 
| 7135 |     NARROWS(SignedUnscopedEnum, float); | 
| 7136 |     NARROWS(SignedUnscopedEnum, double); | 
| 7137 |     NARROWS(SignedUnscopedEnum, long double); | 
| 7138 |  | 
| 7139 |  | 
| 7140 |     // integral to smaller integral | 
| 7141 |     FITS(bool, bool); | 
| 7142 |     FITS(char, char); | 
| 7143 |     FITS(signed char, signed char); | 
| 7144 |     FITS(signed char, short); | 
| 7145 |     FITS(signed char, int); | 
| 7146 |     FITS(signed char, long); | 
| 7147 |     FITS(signed char, long long); | 
| 7148 |     FITS(unsigned char, unsigned char); | 
| 7149 |     FITS(unsigned char, unsigned short); | 
| 7150 |     FITS(unsigned char, unsigned int); | 
| 7151 |     FITS(unsigned char, unsigned long); | 
| 7152 |     FITS(unsigned char, unsigned long long); | 
| 7153 |  | 
| 7154 |     NARROWS_IF(bool, unsigned char, (sizeof(bool) > sizeof(char) || std::is_signed<bool>::value)); | 
| 7155 |     NARROWS_IF(bool, unsigned short, (sizeof(bool) > sizeof(short) || std::is_signed<bool>::value)); | 
| 7156 |     NARROWS_IF(bool, unsigned int, (sizeof(bool) > sizeof(int) || std::is_signed<bool>::value)); | 
| 7157 |     NARROWS_IF(bool, unsigned long, (sizeof(bool) > sizeof(long) || std::is_signed<bool>::value)); | 
| 7158 |     NARROWS_IF(bool, unsigned long long, (sizeof(bool) > sizeof(long long) || std::is_signed<bool>::value)); | 
| 7159 |  | 
| 7160 |     NARROWS_IF(short, char, (sizeof(short) > sizeof(char) || std::is_unsigned<char>::value)); | 
| 7161 |     NARROWS_IF(short, unsigned char, (sizeof(short) > sizeof(char))); | 
| 7162 |     NARROWS_IF(short, signed char, (sizeof(short) > sizeof(char))); | 
| 7163 |  | 
| 7164 |     NARROWS_IF(unsigned short, char, (sizeof(short) > sizeof(char) || std::is_signed<char>::value)); | 
| 7165 |     NARROWS_IF(unsigned short, unsigned char, (sizeof(short) > sizeof(char))); | 
| 7166 |     NARROWS_IF(unsigned short, signed char, (sizeof(short) > sizeof(char))); | 
| 7167 |  | 
| 7168 |     FITS(short, short); | 
| 7169 |     FITS(short, int); | 
| 7170 |     FITS(short, long); | 
| 7171 |     FITS(short, long long); | 
| 7172 |  | 
| 7173 |     FITS(unsigned short, unsigned short); | 
| 7174 |     FITS(unsigned short, unsigned int); | 
| 7175 |     FITS(unsigned short, unsigned long); | 
| 7176 |     FITS(unsigned short, unsigned long long); | 
| 7177 |  | 
| 7178 |     NARROWS_IF(int, char, (sizeof(int) > sizeof(char) || std::is_unsigned<char>::value)); | 
| 7179 |     NARROWS(int, unsigned char); | 
| 7180 |     NARROWS_IF(int, signed char, (sizeof(int) > sizeof(char))); | 
| 7181 |     NARROWS_IF(int, short, (sizeof(int) > sizeof(short))); | 
| 7182 |     NARROWS(int, unsigned short); | 
| 7183 |  | 
| 7184 |     NARROWS_IF(unsigned int, char, (sizeof(int) > sizeof(char) || std::is_signed<char>::value)); | 
| 7185 |     NARROWS_IF(unsigned int, unsigned char, (sizeof(int) > sizeof(char))); | 
| 7186 |     NARROWS(unsigned int, signed char); | 
| 7187 |     NARROWS(unsigned int, short); | 
| 7188 |     NARROWS_IF(unsigned int, unsigned short, (sizeof(int) > sizeof(short))); | 
| 7189 |  | 
| 7190 |     FITS(int, int); | 
| 7191 |     FITS(int, long); | 
| 7192 |     FITS(int, long long); | 
| 7193 |  | 
| 7194 |     FITS(unsigned int, unsigned int); | 
| 7195 |     FITS(unsigned int, unsigned long); | 
| 7196 |     FITS(unsigned int, unsigned long long); | 
| 7197 |  | 
| 7198 |     NARROWS_IF(long, char, (sizeof(long) > sizeof(char) || std::is_unsigned<char>::value)); | 
| 7199 |     NARROWS(long, unsigned char); | 
| 7200 |     NARROWS_IF(long, signed char, (sizeof(long) > sizeof(char))); | 
| 7201 |     NARROWS_IF(long, short, (sizeof(long) > sizeof(short))); | 
| 7202 |     NARROWS(long, unsigned short); | 
| 7203 |     NARROWS_IF(long, int, (sizeof(long) > sizeof(int))); | 
| 7204 |     NARROWS(long, unsigned int); | 
| 7205 |  | 
| 7206 |     NARROWS_IF(unsigned long, char, (sizeof(long) > sizeof(char) || std::is_signed<char>::value)); | 
| 7207 |     NARROWS_IF(unsigned long, unsigned char, (sizeof(long) > sizeof(char))); | 
| 7208 |     NARROWS(unsigned long, signed char); | 
| 7209 |     NARROWS(unsigned long, short); | 
| 7210 |     NARROWS_IF(unsigned long, unsigned short, (sizeof(long) > sizeof(short))); | 
| 7211 |     NARROWS(unsigned long, int); | 
| 7212 |     NARROWS_IF(unsigned long, unsigned int, (sizeof(long) > sizeof(int))); | 
| 7213 |  | 
| 7214 |     FITS(long, long); | 
| 7215 |     FITS(long, long long); | 
| 7216 |  | 
| 7217 |     FITS(unsigned long, unsigned long); | 
| 7218 |     FITS(unsigned long, unsigned long long); | 
| 7219 |  | 
| 7220 |     NARROWS_IF(long long, char, (sizeof(long long) > sizeof(char) || std::is_unsigned<char>::value)); | 
| 7221 |     NARROWS(long long, unsigned char); | 
| 7222 |     NARROWS_IF(long long, signed char, (sizeof(long long) > sizeof(char))); | 
| 7223 |     NARROWS_IF(long long, short, (sizeof(long long) > sizeof(short))); | 
| 7224 |     NARROWS(long long, unsigned short); | 
| 7225 |     NARROWS_IF(long long, int, (sizeof(long long) > sizeof(int))); | 
| 7226 |     NARROWS(long long, unsigned int); | 
| 7227 |     NARROWS_IF(long long, long, (sizeof(long long) > sizeof(long))); | 
| 7228 |     NARROWS(long long, unsigned long); | 
| 7229 |  | 
| 7230 |     NARROWS_IF(unsigned long long, char, (sizeof(long long) > sizeof(char) || std::is_signed<char>::value)); | 
| 7231 |     NARROWS_IF(unsigned long long, unsigned char, (sizeof(long long) > sizeof(char))); | 
| 7232 |     NARROWS(unsigned long long, signed char); | 
| 7233 |     NARROWS(unsigned long long, short); | 
| 7234 |     NARROWS_IF(unsigned long long, unsigned short, (sizeof(long long) > sizeof(short))); | 
| 7235 |     NARROWS(unsigned long long, int); | 
| 7236 |     NARROWS_IF(unsigned long long, unsigned int, (sizeof(long long) > sizeof(int))); | 
| 7237 |     NARROWS(unsigned long long, long); | 
| 7238 |     NARROWS_IF(unsigned long long, unsigned long, (sizeof(long long) > sizeof(long))); | 
| 7239 |  | 
| 7240 |     FITS(long long, long long); | 
| 7241 |     FITS(unsigned long long, unsigned long long); | 
| 7242 |  | 
| 7243 |  | 
| 7244 |     // integral to integral with different signedness. smaller ones tested above | 
| 7245 |     NARROWS(signed char, unsigned char); | 
| 7246 |     NARROWS(signed char, unsigned short); | 
| 7247 |     NARROWS(signed char, unsigned int); | 
| 7248 |     NARROWS(signed char, unsigned long); | 
| 7249 |     NARROWS(signed char, unsigned long long); | 
| 7250 |  | 
| 7251 |     NARROWS(unsigned char, signed char); | 
| 7252 |     FITS(unsigned char, short); | 
| 7253 |     FITS(unsigned char, int); | 
| 7254 |     FITS(unsigned char, long); | 
| 7255 |     FITS(unsigned char, long long); | 
| 7256 |  | 
| 7257 |     NARROWS(short, unsigned short); | 
| 7258 |     NARROWS(short, unsigned int); | 
| 7259 |     NARROWS(short, unsigned long); | 
| 7260 |     NARROWS(short, unsigned long long); | 
| 7261 |  | 
| 7262 |     NARROWS(unsigned short, short); | 
| 7263 |     FITS(unsigned short, int); | 
| 7264 |     FITS(unsigned short, long); | 
| 7265 |     FITS(unsigned short, long long); | 
| 7266 |  | 
| 7267 |     NARROWS(int, unsigned int); | 
| 7268 |     NARROWS(int, unsigned long); | 
| 7269 |     NARROWS(int, unsigned long long); | 
| 7270 |  | 
| 7271 |     NARROWS(unsigned int, int); | 
| 7272 |     NARROWS_IF(unsigned int, long, (sizeof(int) >= sizeof(long))); | 
| 7273 |     FITS(unsigned int, long long); | 
| 7274 |  | 
| 7275 |     NARROWS(long, unsigned long); | 
| 7276 |     NARROWS(long, unsigned long long); | 
| 7277 |  | 
| 7278 |     NARROWS(unsigned long, long); | 
| 7279 |     NARROWS_IF(unsigned long, long long, (sizeof(long) >= sizeof(long long))); | 
| 7280 |  | 
| 7281 |     NARROWS(long long, unsigned long long); | 
| 7282 |     NARROWS(unsigned long long, long long); | 
| 7283 |  | 
| 7284 |     // enum to smaller integral | 
| 7285 |     // (note that we know that sizeof(UnscopedEnum) <= sizeof(int) | 
| 7286 |     FITS(UnscopedEnum, UnscopedEnum); | 
| 7287 |     FITS(SignedUnscopedEnum, SignedUnscopedEnum); | 
| 7288 |  | 
| 7289 |     NARROWS_IF(UnscopedEnum, char, ((sizeof(UnscopedEnum) > sizeof(char)) || (sizeof(UnscopedEnum) == sizeof(char) && IS_UNSCOPED_ENUM_SIGNED == std::is_signed<char>::value))); | 
| 7290 |     NARROWS_IF(UnscopedEnum, signed char, ((sizeof(UnscopedEnum) > sizeof(char)) || (sizeof(UnscopedEnum) == sizeof(char) && !IS_UNSCOPED_ENUM_SIGNED))); | 
| 7291 |     NARROWS_IF(UnscopedEnum, unsigned char, ((sizeof(UnscopedEnum) > sizeof(char)) || IS_UNSCOPED_ENUM_SIGNED)); | 
| 7292 |  | 
| 7293 |     NARROWS_IF(UnscopedEnum, short, ((sizeof(UnscopedEnum) > sizeof(short)) || (sizeof(UnscopedEnum) == sizeof(short) && !IS_UNSCOPED_ENUM_SIGNED))); | 
| 7294 |     NARROWS_IF(UnscopedEnum, unsigned short, ((sizeof(UnscopedEnum) > sizeof(short)) || IS_UNSCOPED_ENUM_SIGNED)); | 
| 7295 |  | 
| 7296 |     NARROWS_IF(UnscopedEnum, int, (sizeof(UnscopedEnum) == sizeof(int) && !IS_UNSCOPED_ENUM_SIGNED)); | 
| 7297 |     NARROWS_IF(UnscopedEnum, unsigned int, IS_UNSCOPED_ENUM_SIGNED); | 
| 7298 |  | 
| 7299 |     NARROWS_IF(UnscopedEnum, long, (sizeof(UnscopedEnum) == sizeof(long) && !IS_UNSCOPED_ENUM_SIGNED)); | 
| 7300 |     NARROWS_IF(UnscopedEnum, unsigned long, IS_UNSCOPED_ENUM_SIGNED); | 
| 7301 |  | 
| 7302 |     NARROWS_IF(UnscopedEnum, long long, (sizeof(UnscopedEnum) == sizeof(long long) && !IS_UNSCOPED_ENUM_SIGNED)); | 
| 7303 |     NARROWS_IF(UnscopedEnum, unsigned long long, IS_UNSCOPED_ENUM_SIGNED); | 
| 7304 |  | 
| 7305 |     Q_STATIC_ASSERT(std::is_signed<typename std::underlying_type<SignedUnscopedEnum>::type>::value); | 
| 7306 |  | 
| 7307 |     NARROWS_IF(SignedUnscopedEnum, signed char, (sizeof(SignedUnscopedEnum) > sizeof(char))); | 
| 7308 |     NARROWS_IF(SignedUnscopedEnum, short, (sizeof(SignedUnscopedEnum) > sizeof(short))); | 
| 7309 |     FITS(SignedUnscopedEnum, int); | 
| 7310 |     FITS(SignedUnscopedEnum, long); | 
| 7311 |     FITS(SignedUnscopedEnum, long long); | 
| 7312 |  | 
| 7313 |  | 
| 7314 |     enum class ScopedEnumBackedBySChar : signed char { A }; | 
| 7315 |     enum class ScopedEnumBackedByUChar : unsigned char { A }; | 
| 7316 |     enum class ScopedEnumBackedByShort : short { A }; | 
| 7317 |     enum class ScopedEnumBackedByUShort : unsigned short { A }; | 
| 7318 |     enum class ScopedEnumBackedByInt : int { A }; | 
| 7319 |     enum class ScopedEnumBackedByUInt : unsigned int { A }; | 
| 7320 |     enum class ScopedEnumBackedByLong : long { A }; | 
| 7321 |     enum class ScopedEnumBackedByULong : unsigned long { A }; | 
| 7322 |     enum class ScopedEnumBackedByLongLong : long long { A }; | 
| 7323 |     enum class ScopedEnumBackedByULongLong : unsigned long long { A }; | 
| 7324 |  | 
| 7325 |     FITS(ScopedEnumBackedBySChar, ScopedEnumBackedBySChar); | 
| 7326 |     FITS(ScopedEnumBackedByUChar, ScopedEnumBackedByUChar); | 
| 7327 |     FITS(ScopedEnumBackedByShort, ScopedEnumBackedByShort); | 
| 7328 |     FITS(ScopedEnumBackedByUShort, ScopedEnumBackedByUShort); | 
| 7329 |     FITS(ScopedEnumBackedByInt, ScopedEnumBackedByInt); | 
| 7330 |     FITS(ScopedEnumBackedByUInt, ScopedEnumBackedByUInt); | 
| 7331 |     FITS(ScopedEnumBackedByLong, ScopedEnumBackedByLong); | 
| 7332 |     FITS(ScopedEnumBackedByULong, ScopedEnumBackedByULong); | 
| 7333 |     FITS(ScopedEnumBackedByLongLong, ScopedEnumBackedByLongLong); | 
| 7334 |     FITS(ScopedEnumBackedByULongLong, ScopedEnumBackedByULongLong); | 
| 7335 |  | 
| 7336 |     FITS(ScopedEnumBackedBySChar, signed char); | 
| 7337 |     FITS(ScopedEnumBackedByUChar, unsigned char); | 
| 7338 |     FITS(ScopedEnumBackedByShort, short); | 
| 7339 |     FITS(ScopedEnumBackedByUShort, unsigned short); | 
| 7340 |     FITS(ScopedEnumBackedByInt, int); | 
| 7341 |     FITS(ScopedEnumBackedByUInt, unsigned int); | 
| 7342 |     FITS(ScopedEnumBackedByLong, long); | 
| 7343 |     FITS(ScopedEnumBackedByULong, unsigned long); | 
| 7344 |     FITS(ScopedEnumBackedByLongLong, long long); | 
| 7345 |     FITS(ScopedEnumBackedByULongLong, unsigned long long); | 
| 7346 |  | 
| 7347 |     FITS(ScopedEnumBackedBySChar, signed char); | 
| 7348 |     FITS(ScopedEnumBackedBySChar, short); | 
| 7349 |     FITS(ScopedEnumBackedBySChar, int); | 
| 7350 |     FITS(ScopedEnumBackedBySChar, long); | 
| 7351 |     FITS(ScopedEnumBackedBySChar, long long); | 
| 7352 |  | 
| 7353 |     FITS(ScopedEnumBackedByUChar, unsigned char); | 
| 7354 |     FITS(ScopedEnumBackedByUChar, unsigned short); | 
| 7355 |     FITS(ScopedEnumBackedByUChar, unsigned int); | 
| 7356 |     FITS(ScopedEnumBackedByUChar, unsigned long); | 
| 7357 |     FITS(ScopedEnumBackedByUChar, unsigned long long); | 
| 7358 |  | 
| 7359 |     NARROWS_IF(ScopedEnumBackedByShort, char, (sizeof(short) > sizeof(char) || std::is_unsigned<char>::value)); | 
| 7360 |     NARROWS_IF(ScopedEnumBackedByUShort, char, (sizeof(short) > sizeof(char) || std::is_signed<char>::value)); | 
| 7361 |     NARROWS_IF(ScopedEnumBackedByInt, char, (sizeof(int) > sizeof(char) || std::is_unsigned<char>::value)); | 
| 7362 |     NARROWS_IF(ScopedEnumBackedByUInt, char, (sizeof(int) > sizeof(char) || std::is_signed<char>::value)); | 
| 7363 |     NARROWS_IF(ScopedEnumBackedByLong, char, (sizeof(long) > sizeof(char) || std::is_unsigned<char>::value)); | 
| 7364 |     NARROWS_IF(ScopedEnumBackedByULong, char, (sizeof(long) > sizeof(char) || std::is_signed<char>::value)); | 
| 7365 |     NARROWS_IF(ScopedEnumBackedByLongLong, char, (sizeof(long long) > sizeof(char) || std::is_unsigned<char>::value)); | 
| 7366 |     NARROWS_IF(ScopedEnumBackedByULongLong, char, (sizeof(long long) > sizeof(char) || std::is_signed<char>::value)); | 
| 7367 |  | 
| 7368 |     NARROWS_IF(ScopedEnumBackedByShort, signed char, (sizeof(short) > sizeof(char))); | 
| 7369 |     NARROWS(ScopedEnumBackedByUShort, signed char); | 
| 7370 |     NARROWS_IF(ScopedEnumBackedByInt, signed char, (sizeof(int) > sizeof(char))); | 
| 7371 |     NARROWS(ScopedEnumBackedByUInt, signed char); | 
| 7372 |     NARROWS_IF(ScopedEnumBackedByLong, signed char, (sizeof(long) > sizeof(char))); | 
| 7373 |     NARROWS(ScopedEnumBackedByULong, signed char); | 
| 7374 |     NARROWS_IF(ScopedEnumBackedByLongLong, signed char, (sizeof(long long) > sizeof(char))); | 
| 7375 |     NARROWS(ScopedEnumBackedByULongLong, signed char); | 
| 7376 |  | 
| 7377 |     NARROWS(ScopedEnumBackedByShort, unsigned char); | 
| 7378 |     NARROWS_IF(ScopedEnumBackedByUShort, unsigned char, (sizeof(short) > sizeof(char))); | 
| 7379 |     NARROWS(ScopedEnumBackedByInt, unsigned char); | 
| 7380 |     NARROWS_IF(ScopedEnumBackedByUInt, unsigned char, (sizeof(int) > sizeof(char))); | 
| 7381 |     NARROWS(ScopedEnumBackedByLong, unsigned char); | 
| 7382 |     NARROWS_IF(ScopedEnumBackedByULong, unsigned char, (sizeof(long) > sizeof(char))); | 
| 7383 |     NARROWS(ScopedEnumBackedByLongLong, unsigned char); | 
| 7384 |     NARROWS_IF(ScopedEnumBackedByULongLong, unsigned char, (sizeof(long long) > sizeof(char))); | 
| 7385 |  | 
| 7386 |     NARROWS_IF(ScopedEnumBackedByInt, short, (sizeof(int) > sizeof(short))); | 
| 7387 |     NARROWS(ScopedEnumBackedByUInt, short); | 
| 7388 |     NARROWS_IF(ScopedEnumBackedByLong, short, (sizeof(long) > sizeof(short))); | 
| 7389 |     NARROWS(ScopedEnumBackedByULong, short); | 
| 7390 |     NARROWS_IF(ScopedEnumBackedByLongLong, short, (sizeof(long long) > sizeof(short))); | 
| 7391 |     NARROWS(ScopedEnumBackedByULongLong, short); | 
| 7392 |  | 
| 7393 |     NARROWS(ScopedEnumBackedByInt, unsigned short); | 
| 7394 |     NARROWS_IF(ScopedEnumBackedByUInt, unsigned short, (sizeof(int) > sizeof(short))); | 
| 7395 |     NARROWS(ScopedEnumBackedByLong, unsigned short); | 
| 7396 |     NARROWS_IF(ScopedEnumBackedByULong, unsigned short, (sizeof(long) > sizeof(short))); | 
| 7397 |     NARROWS(ScopedEnumBackedByLongLong, unsigned short); | 
| 7398 |     NARROWS_IF(ScopedEnumBackedByULongLong, unsigned short, (sizeof(long long) > sizeof(short))); | 
| 7399 |  | 
| 7400 |     NARROWS_IF(ScopedEnumBackedByLong, int, (sizeof(long) > sizeof(int))); | 
| 7401 |     NARROWS(ScopedEnumBackedByULong, int); | 
| 7402 |     NARROWS_IF(ScopedEnumBackedByLongLong, int, (sizeof(long long) > sizeof(int))); | 
| 7403 |     NARROWS(ScopedEnumBackedByULongLong, int); | 
| 7404 |  | 
| 7405 |     NARROWS(ScopedEnumBackedByLong, unsigned int); | 
| 7406 |     NARROWS_IF(ScopedEnumBackedByULong, unsigned int, (sizeof(long) > sizeof(int))); | 
| 7407 |     NARROWS(ScopedEnumBackedByLongLong, unsigned int); | 
| 7408 |     NARROWS_IF(ScopedEnumBackedByULongLong, unsigned int, (sizeof(long long) > sizeof(int))); | 
| 7409 |  | 
| 7410 |     NARROWS_IF(ScopedEnumBackedByLongLong, long, (sizeof(long long) > sizeof(long))); | 
| 7411 |     NARROWS(ScopedEnumBackedByULongLong, long); | 
| 7412 |  | 
| 7413 |     NARROWS(ScopedEnumBackedByLongLong, unsigned long); | 
| 7414 |     NARROWS_IF(ScopedEnumBackedByULongLong, unsigned long, (sizeof(long long) > sizeof(long))); | 
| 7415 |  | 
| 7416 |     // different signedness of the underlying type | 
| 7417 |     NARROWS(SignedUnscopedEnum, unsigned char); | 
| 7418 |     NARROWS(SignedUnscopedEnum, unsigned short); | 
| 7419 |     NARROWS(SignedUnscopedEnum, unsigned int); | 
| 7420 |     NARROWS(SignedUnscopedEnum, unsigned long); | 
| 7421 |     NARROWS(SignedUnscopedEnum, unsigned long long); | 
| 7422 |  | 
| 7423 |     NARROWS(ScopedEnumBackedBySChar, unsigned char); | 
| 7424 |     NARROWS(ScopedEnumBackedBySChar, unsigned short); | 
| 7425 |     NARROWS(ScopedEnumBackedBySChar, unsigned int); | 
| 7426 |     NARROWS(ScopedEnumBackedBySChar, unsigned long); | 
| 7427 |     NARROWS(ScopedEnumBackedBySChar, unsigned long long); | 
| 7428 |  | 
| 7429 |     NARROWS(ScopedEnumBackedByShort, unsigned char); | 
| 7430 |     NARROWS(ScopedEnumBackedByShort, unsigned short); | 
| 7431 |     NARROWS(ScopedEnumBackedByShort, unsigned int); | 
| 7432 |     NARROWS(ScopedEnumBackedByShort, unsigned long); | 
| 7433 |     NARROWS(ScopedEnumBackedByShort, unsigned long long); | 
| 7434 |  | 
| 7435 |     NARROWS(ScopedEnumBackedByInt, unsigned char); | 
| 7436 |     NARROWS(ScopedEnumBackedByInt, unsigned short); | 
| 7437 |     NARROWS(ScopedEnumBackedByInt, unsigned int); | 
| 7438 |     NARROWS(ScopedEnumBackedByInt, unsigned long); | 
| 7439 |     NARROWS(ScopedEnumBackedByInt, unsigned long long); | 
| 7440 |  | 
| 7441 |     NARROWS(ScopedEnumBackedByLong, unsigned char); | 
| 7442 |     NARROWS(ScopedEnumBackedByLong, unsigned short); | 
| 7443 |     NARROWS(ScopedEnumBackedByLong, unsigned int); | 
| 7444 |     NARROWS(ScopedEnumBackedByLong, unsigned long); | 
| 7445 |     NARROWS(ScopedEnumBackedByLong, unsigned long long); | 
| 7446 |  | 
| 7447 |     NARROWS(ScopedEnumBackedByLongLong, unsigned char); | 
| 7448 |     NARROWS(ScopedEnumBackedByLongLong, unsigned short); | 
| 7449 |     NARROWS(ScopedEnumBackedByLongLong, unsigned int); | 
| 7450 |     NARROWS(ScopedEnumBackedByLongLong, unsigned long); | 
| 7451 |     NARROWS(ScopedEnumBackedByLongLong, unsigned long long); | 
| 7452 |  | 
| 7453 |     NARROWS(ScopedEnumBackedByUChar, signed char); | 
| 7454 |     FITS_IF(ScopedEnumBackedByUChar, short, (sizeof(char) < sizeof(short))); | 
| 7455 |     FITS_IF(ScopedEnumBackedByUChar, int, (sizeof(char) < sizeof(int))); | 
| 7456 |     FITS_IF(ScopedEnumBackedByUChar, long, (sizeof(char) < sizeof(long))); | 
| 7457 |     FITS_IF(ScopedEnumBackedByUChar, long long, (sizeof(char) < sizeof(long long))); | 
| 7458 |  | 
| 7459 |     NARROWS(ScopedEnumBackedByUShort, signed char); | 
| 7460 |     NARROWS(ScopedEnumBackedByUShort, short); | 
| 7461 |     FITS_IF(ScopedEnumBackedByUShort, int, (sizeof(short) < sizeof(int))); | 
| 7462 |     FITS_IF(ScopedEnumBackedByUShort, long, (sizeof(short) < sizeof(long))); | 
| 7463 |     FITS_IF(ScopedEnumBackedByUShort, long long, (sizeof(short) < sizeof(long long))); | 
| 7464 |  | 
| 7465 |     NARROWS(ScopedEnumBackedByUInt, signed char); | 
| 7466 |     NARROWS(ScopedEnumBackedByUInt, short); | 
| 7467 |     NARROWS(ScopedEnumBackedByUInt, int); | 
| 7468 |     FITS_IF(ScopedEnumBackedByUInt, long, (sizeof(ScopedEnumBackedByUInt) < sizeof(long))); | 
| 7469 |     FITS(ScopedEnumBackedByUInt, long long); | 
| 7470 |  | 
| 7471 |     NARROWS(ScopedEnumBackedByULong, signed char); | 
| 7472 |     NARROWS(ScopedEnumBackedByULong, short); | 
| 7473 |     NARROWS(ScopedEnumBackedByULong, int); | 
| 7474 |     NARROWS(ScopedEnumBackedByULong, long); | 
| 7475 |     FITS_IF(ScopedEnumBackedByULong, long long, (sizeof(ScopedEnumBackedByULong) < sizeof(long long))); | 
| 7476 |  | 
| 7477 |     NARROWS(ScopedEnumBackedByULongLong, signed char); | 
| 7478 |     NARROWS(ScopedEnumBackedByULongLong, short); | 
| 7479 |     NARROWS(ScopedEnumBackedByULongLong, int); | 
| 7480 |     NARROWS(ScopedEnumBackedByULongLong, long); | 
| 7481 |     NARROWS(ScopedEnumBackedByULongLong, long long); | 
| 7482 |  | 
| 7483 |     // other types which should be always unaffected | 
| 7484 |     FITS(void *, void *); | 
| 7485 |  | 
| 7486 |     FITS(QString, QString); | 
| 7487 |     FITS(QString &, QString &); | 
| 7488 |     FITS(const QString &, const QString &); | 
| 7489 |  | 
| 7490 |     FITS(QObject, QObject); | 
| 7491 |     FITS(QObject *, QObject *); | 
| 7492 |     FITS(const QObject *, const QObject *); | 
| 7493 |  | 
| 7494 |     FITS(std::nullptr_t, std::nullptr_t); | 
| 7495 |  | 
| 7496 |     FITS(QString, QObject); | 
| 7497 |     FITS(QString, QVariant); | 
| 7498 |     FITS(QString, void *); | 
| 7499 |     FITS(QString, long long); | 
| 7500 |     FITS(bool, const QObject *&); | 
| 7501 |     FITS(int (*)(bool), void (QObject::*)()); | 
| 7502 |  | 
| 7503 |     { | 
| 7504 |         // wg21.link/P1957 | 
| 7505 |         NARROWS(char*, bool); | 
| 7506 |         NARROWS(void (QObject::*)(), bool); | 
| 7507 |     } | 
| 7508 |  | 
| 7509 | #undef IS_UNSCOPED_ENUM_SIGNED | 
| 7510 |  | 
| 7511 | #undef NARROWS_IF | 
| 7512 | #undef FITS_IF | 
| 7513 | #undef NARROWS | 
| 7514 | #undef FITS | 
| 7515 | } | 
| 7516 |  | 
| 7517 | void tst_QObject::nullReceiver() | 
| 7518 | { | 
| 7519 |     QObject o; | 
| 7520 |     QObject *nullObj = nullptr; // Passing nullptr directly doesn't compile with gcc 4.8 | 
| 7521 |     QVERIFY(!connect(&o, &QObject::destroyed, nullObj, &QObject::deleteLater)); | 
| 7522 |     QVERIFY(!connect(&o, &QObject::destroyed, nullObj, [] {})); | 
| 7523 |     QVERIFY(!connect(&o, &QObject::destroyed, nullObj, Functor_noexcept())); | 
| 7524 |     QVERIFY(!connect(&o, SIGNAL(destroyed()), nullObj, SLOT(deleteLater()))); | 
| 7525 | } | 
| 7526 |  | 
| 7527 | void tst_QObject::functorReferencesConnection() | 
| 7528 | { | 
| 7529 |     countedStructObjectsCount = 0; | 
| 7530 |     QMetaObject::Connection globalCon; | 
| 7531 |     { | 
| 7532 |         GetSenderObject obj; | 
| 7533 |         CountedStruct counted(&obj); | 
| 7534 |         QCOMPARE(countedStructObjectsCount, 1); | 
| 7535 |         auto c = QSharedPointer<QMetaObject::Connection>::create(); | 
| 7536 |         int slotCalled = 0; | 
| 7537 |         *c = connect(sender: &obj, signal: &GetSenderObject::aSignal, context: &obj, slot: [&slotCalled, c, counted] { | 
| 7538 |             QObject::disconnect(*c); | 
| 7539 |             slotCalled++; | 
| 7540 |         }); | 
| 7541 |         globalCon = *c; // keep a handle to the connection somewhere; | 
| 7542 |         QVERIFY(globalCon); | 
| 7543 |         QCOMPARE(countedStructObjectsCount, 2); | 
| 7544 |         obj.triggerSignal(); | 
| 7545 |         QCOMPARE(slotCalled, 1); | 
| 7546 |         QCOMPARE(countedStructObjectsCount, 1); | 
| 7547 |         QVERIFY(!globalCon); | 
| 7548 |         obj.triggerSignal(); | 
| 7549 |         QCOMPARE(slotCalled, 1); | 
| 7550 |         QCOMPARE(countedStructObjectsCount, 1); | 
| 7551 |     } | 
| 7552 |     QCOMPARE(countedStructObjectsCount, 0); | 
| 7553 |  | 
| 7554 |     { | 
| 7555 |         GetSenderObject obj; | 
| 7556 |         CountedStruct counted(&obj); | 
| 7557 |         QCOMPARE(countedStructObjectsCount, 1); | 
| 7558 |         auto *rec = new QObject; | 
| 7559 |         int slotCalled = 0; | 
| 7560 |         globalCon = connect(sender: &obj, signal: &GetSenderObject::aSignal, context: rec, slot: [&slotCalled, rec, counted] { | 
| 7561 |             delete rec; | 
| 7562 |             slotCalled++; | 
| 7563 |         }); | 
| 7564 |         QCOMPARE(countedStructObjectsCount, 2); | 
| 7565 |         obj.triggerSignal(); | 
| 7566 |         QCOMPARE(slotCalled, 1); | 
| 7567 |         QCOMPARE(countedStructObjectsCount, 1); | 
| 7568 |         QVERIFY(!globalCon); | 
| 7569 |         obj.triggerSignal(); | 
| 7570 |         QCOMPARE(slotCalled, 1); | 
| 7571 |         QCOMPARE(countedStructObjectsCount, 1); | 
| 7572 |     } | 
| 7573 |     QCOMPARE(countedStructObjectsCount, 0); | 
| 7574 |     { | 
| 7575 |         int slotCalled = 0; | 
| 7576 |         QEventLoop eventLoop; | 
| 7577 |         { | 
| 7578 |             // Sender will be destroyed when the labda goes out of scope lambda, so it will exit the event loop | 
| 7579 |             auto sender = QSharedPointer<GetSenderObject>::create(); | 
| 7580 |             connect(sender: sender.data(), signal: &QObject::destroyed, receiver: &eventLoop, slot: &QEventLoop::quit, type: Qt::QueuedConnection); | 
| 7581 |             globalCon = connect(sender: sender.data(), signal: &GetSenderObject::aSignal, context: this, slot: [&slotCalled, sender, &globalCon, this] { | 
| 7582 |                 ++slotCalled; | 
| 7583 |                 // This signal will be connected, but should never be called as the sender will be destroyed before | 
| 7584 |                 auto c2 = connect(sender: sender.data(), signal: &GetSenderObject::aSignal, slot: [] { QFAIL("Should not be called" ); }); | 
| 7585 |                 QVERIFY(c2); | 
| 7586 |                 QVERIFY(QObject::disconnect(sender.data(), nullptr, this, nullptr)); | 
| 7587 |                 QVERIFY(!globalCon); // this connection has been disconnected | 
| 7588 |                 QVERIFY(c2); // sender should not have been deleted yet, only after the emission is done | 
| 7589 |             }); | 
| 7590 |             QMetaObject::invokeMethod(object: sender.data(), function: &GetSenderObject::triggerSignal, type: Qt::QueuedConnection); | 
| 7591 |             QMetaObject::invokeMethod(object: sender.data(), function: &GetSenderObject::triggerSignal, type: Qt::QueuedConnection); | 
| 7592 |             QMetaObject::invokeMethod(object: sender.data(), function: &GetSenderObject::triggerSignal, type: Qt::QueuedConnection); | 
| 7593 |         } | 
| 7594 |         eventLoop.exec(); | 
| 7595 |         QCOMPARE(slotCalled, 1); | 
| 7596 |     } | 
| 7597 |  | 
| 7598 |     { | 
| 7599 |         GetSenderObject obj; | 
| 7600 |         CountedStruct counted(&obj); | 
| 7601 |         QCOMPARE(countedStructObjectsCount, 1); | 
| 7602 |         auto c1 = QSharedPointer<QMetaObject::Connection>::create(); | 
| 7603 |         auto c2 = QSharedPointer<QMetaObject::Connection>::create(); | 
| 7604 |         int slot1Called = 0; | 
| 7605 |         int slot3Called = 0; | 
| 7606 |         *c1 = connect(sender: &obj, signal: &GetSenderObject::aSignal, context: &obj, slot: [&slot1Called, &slot3Called, &obj, c1, c2, counted] { | 
| 7607 |             auto c3 = connect(sender: &obj, signal: &GetSenderObject::aSignal, slot: [counted, &slot3Called] { | 
| 7608 |                 slot3Called++; | 
| 7609 |             }); | 
| 7610 |             // top-level + the one in the 3 others lambdas | 
| 7611 |             QCOMPARE(countedStructObjectsCount, 4); | 
| 7612 |             QObject::disconnect(*c2); | 
| 7613 |             slot1Called++; | 
| 7614 |         }); | 
| 7615 |         connect(sender: &obj, signal: &GetSenderObject::aSignal, slot: [] {}); // just a dummy signal to fill the connection list | 
| 7616 |         *c2 = connect(sender: &obj, signal: &GetSenderObject::aSignal, slot: [counted, c2] { QFAIL("should not be called" ); }); | 
| 7617 |         QVERIFY(c1 && c2); | 
| 7618 |         QCOMPARE(countedStructObjectsCount, 3); // top-level + c1 + c2 | 
| 7619 |         obj.triggerSignal(); | 
| 7620 |         QCOMPARE(slot1Called, 1); | 
| 7621 |         QCOMPARE(slot3Called, 0); | 
| 7622 |         QCOMPARE(countedStructObjectsCount, 3); // top-level + c1 + c3 | 
| 7623 |         QObject::disconnect(*c1); | 
| 7624 |         QCOMPARE(countedStructObjectsCount, 2); // top-level + c3 | 
| 7625 |         obj.triggerSignal(); | 
| 7626 |         QCOMPARE(slot1Called, 1); | 
| 7627 |         QCOMPARE(slot3Called, 1); | 
| 7628 |     } | 
| 7629 |     { | 
| 7630 |         struct DestroyEmit { | 
| 7631 |             Q_DISABLE_COPY(DestroyEmit); | 
| 7632 |             explicit DestroyEmit(SenderObject *obj) : obj(obj) {} | 
| 7633 |             SenderObject *obj; | 
| 7634 |             ~DestroyEmit() { | 
| 7635 |                 obj->emitSignal1(); | 
| 7636 |             } | 
| 7637 |         }; | 
| 7638 |         SenderObject obj; | 
| 7639 |         int slot1Called = 0; | 
| 7640 |         int slot2Called = 0; | 
| 7641 |         int slot3Called = 0; | 
| 7642 |         auto c1 = QSharedPointer<QMetaObject::Connection>::create(); | 
| 7643 |         auto de = QSharedPointer<DestroyEmit>::create(arguments: &obj); | 
| 7644 |         *c1 = connect(sender: &obj, signal: &SenderObject::signal1, slot: [&slot1Called, &slot3Called, de, c1, &obj] { | 
| 7645 |             connect(sender: &obj, signal: &SenderObject::signal1, slot: [&slot3Called] { slot3Called++; }); | 
| 7646 |             slot1Called++; | 
| 7647 |             QObject::disconnect(*c1); | 
| 7648 |         }); | 
| 7649 |         de.clear(); | 
| 7650 |         connect(sender: &obj, signal: &SenderObject::signal1, slot: [&slot2Called] { slot2Called++; }); | 
| 7651 |         obj.emitSignal1(); | 
| 7652 |         QCOMPARE(slot1Called, 1); | 
| 7653 |         QCOMPARE(slot2Called, 2); // because also called from ~DestroyEmit | 
| 7654 |         QCOMPARE(slot3Called, 1); | 
| 7655 |     } | 
| 7656 | } | 
| 7657 |  | 
| 7658 | void tst_QObject::disconnectDisconnects() | 
| 7659 | { | 
| 7660 |     // Test what happens if the destructor of an functor slot also disconnects more slot; | 
| 7661 |  | 
| 7662 |     SenderObject s1; | 
| 7663 |     QScopedPointer<QObject> receiver(new QObject); | 
| 7664 |  | 
| 7665 |     auto s2 = QSharedPointer<SenderObject>::create(); | 
| 7666 |     QPointer<QObject> s2_tracker = s2.data(); | 
| 7667 |     int count = 0; | 
| 7668 |     connect(sender: &s1, signal: &SenderObject::signal1, slot: [&count] { count++; }); // α | 
| 7669 |     connect(sender: &s1, signal: &SenderObject::signal1, context: receiver.data(), slot: [s2] { QFAIL("!!" ); }); // β | 
| 7670 |     connect(sender: s2.data(), signal: &SenderObject::signal1, context: receiver.data(), slot: [] { QFAIL("!!" ); }); | 
| 7671 |     connect(sender: &s1, signal: &SenderObject::signal2, context: receiver.data(), slot: [] { QFAIL("!!" ); }); | 
| 7672 |     connect(sender: s2.data(), signal: &SenderObject::signal2, context: receiver.data(), slot: [] { QFAIL("!!" ); }); | 
| 7673 |     connect(sender: &s1, signal: &SenderObject::signal1, slot: [&count] { count++; }); // γ | 
| 7674 |     connect(sender: &s1, signal: &SenderObject::signal2, slot: [&count] { count++; }); // δ | 
| 7675 |     s2.clear(); | 
| 7676 |  | 
| 7677 |     QVERIFY(s2_tracker); | 
| 7678 |     receiver | 
| 7679 |         .reset(); // this will delete the receiver which must also delete s2 as β is disconnected | 
| 7680 |     QVERIFY(!s2_tracker); | 
| 7681 |     // test that the data structures are still in order | 
| 7682 |     s1.emitSignal1(); | 
| 7683 |     QCOMPARE(count, 2); // α + γ | 
| 7684 |     s1.emitSignal2(); | 
| 7685 |     QCOMPARE(count, 3); // + δ | 
| 7686 | } | 
| 7687 |  | 
| 7688 | // Test for QtPrivate::HasQ_OBJECT_Macro | 
| 7689 | Q_STATIC_ASSERT(QtPrivate::HasQ_OBJECT_Macro<tst_QObject>::Value); | 
| 7690 | Q_STATIC_ASSERT(!QtPrivate::HasQ_OBJECT_Macro<SiblingDeleter>::Value); | 
| 7691 |  | 
| 7692 | QTEST_MAIN(tst_QObject) | 
| 7693 | #include "tst_qobject.moc" | 
| 7694 |  |