1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the test suite of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 |
|
43 //#define QT_TST_QAPP_DEBUG |
|
44 #include <qdebug.h> |
|
45 |
|
46 #include <QtTest/QtTest> |
|
47 |
|
48 #include "qabstracteventdispatcher.h" |
|
49 #include <QtGui> |
|
50 |
|
51 #include "private/qapplication_p.h" |
|
52 #include "private/qstylesheetstyle_p.h" |
|
53 #ifdef Q_OS_WINCE |
|
54 #include <windows.h> |
|
55 #endif |
|
56 #ifdef Q_OS_SYMBIAN |
|
57 #include <aknenv.h> |
|
58 #endif |
|
59 |
|
60 //TESTED_CLASS= |
|
61 //TESTED_FILES= |
|
62 |
|
63 #if defined(Q_OS_SYMBIAN) |
|
64 // In Symbian, the PluginsPath doesn't specify the only absolute path; just the dir that can be found on any drive |
|
65 /*static void addExpectedSymbianPluginsPath(QStringList& expected) |
|
66 { |
|
67 QString installPathPlugins = QDir::fromNativeSeparators(QLibraryInfo::location(QLibraryInfo::PluginsPath)); |
|
68 QFileInfoList driveList = QDir::drives(); |
|
69 QListIterator<QFileInfo> iter(driveList); |
|
70 while (iter.hasNext()) { |
|
71 QFileInfo testFi(iter.next().canonicalPath().append(installPathPlugins)); |
|
72 if (testFi.exists()) |
|
73 expected << testFi.canonicalFilePath(); |
|
74 } |
|
75 } |
|
76 */ |
|
77 #endif |
|
78 |
|
79 class tst_QApplication : public QObject |
|
80 { |
|
81 Q_OBJECT |
|
82 |
|
83 public: |
|
84 tst_QApplication(); |
|
85 virtual ~tst_QApplication(); |
|
86 |
|
87 public slots: |
|
88 void init(); |
|
89 void cleanup(); |
|
90 private slots: |
|
91 /*void sendEventsOnProcessEvents(); // this must be the first test |
|
92 void getSetCheck(); |
|
93 void staticSetup(); |
|
94 |
|
95 void alert(); |
|
96 |
|
97 void multiple_data(); |
|
98 void multiple(); |
|
99 |
|
100 void nonGui(); |
|
101 |
|
102 void setFont_data(); |
|
103 void setFont(); |
|
104 |
|
105 void args_data(); |
|
106 void args(); |
|
107 |
|
108 void lastWindowClosed(); |
|
109 void quitOnLastWindowClosed(); |
|
110 void testDeleteLater(); |
|
111 void testDeleteLaterProcessEvents(); |
|
112 |
|
113 void libraryPaths(); |
|
114 void libraryPaths_qt_plugin_path(); |
|
115 void libraryPaths_qt_plugin_path_2(); |
|
116 |
|
117 void sendPostedEvents(); |
|
118 |
|
119 void thread(); |
|
120 void desktopSettingsAware();*/ |
|
121 |
|
122 void setActiveWindow(); |
|
123 |
|
124 /*void focusChanged(); |
|
125 void focusOut(); |
|
126 |
|
127 void execAfterExit(); |
|
128 |
|
129 void wheelScrollLines(); |
|
130 |
|
131 void task109149(); |
|
132 |
|
133 void style(); |
|
134 |
|
135 void allWidgets(); |
|
136 void topLevelWidgets(); |
|
137 |
|
138 void setAttribute(); |
|
139 |
|
140 void windowsCommandLine_data(); |
|
141 void windowsCommandLine(); |
|
142 |
|
143 void touchEventPropagation(); |
|
144 |
|
145 void symbianNoApplicationPanes(); |
|
146 |
|
147 void symbianNeedForTraps(); |
|
148 void symbianLeaveThroughMain();*/ |
|
149 }; |
|
150 |
|
151 /*class EventSpy : public QObject |
|
152 { |
|
153 Q_OBJECT |
|
154 |
|
155 public: |
|
156 QList<int> recordedEvents; |
|
157 bool eventFilter(QObject *, QEvent *event) |
|
158 { |
|
159 recordedEvents.append(event->type()); |
|
160 return false; |
|
161 } |
|
162 }; |
|
163 */ |
|
164 |
|
165 /* |
|
166 void tst_QApplication::sendEventsOnProcessEvents() |
|
167 { |
|
168 int argc = 0; |
|
169 QApplication app(argc, 0, QApplication::GuiServer); |
|
170 |
|
171 EventSpy spy; |
|
172 app.installEventFilter(&spy); |
|
173 |
|
174 QCoreApplication::postEvent(&app, new QEvent(QEvent::Type(QEvent::User + 1))); |
|
175 QCoreApplication::processEvents(); |
|
176 QVERIFY(spy.recordedEvents.contains(QEvent::User + 1)); |
|
177 } |
|
178 |
|
179 class MyInputContext : public QInputContext |
|
180 { |
|
181 public: |
|
182 MyInputContext() : QInputContext() {} |
|
183 QString identifierName() { return QString("NoName"); } |
|
184 QString language() { return QString("NoLanguage"); } |
|
185 void reset() {} |
|
186 bool isComposing() const { return false; } |
|
187 }; |
|
188 |
|
189 // Testing get/set functions |
|
190 void tst_QApplication::getSetCheck() |
|
191 { |
|
192 int argc = 0; |
|
193 QApplication obj1(argc, 0, QApplication::GuiServer); |
|
194 // QInputContext * QApplication::inputContext() |
|
195 // void QApplication::setInputContext(QInputContext *) |
|
196 MyInputContext *var1 = new MyInputContext; |
|
197 obj1.setInputContext(var1); |
|
198 QCOMPARE((QInputContext *)var1, obj1.inputContext()); |
|
199 QTest::ignoreMessage(QtWarningMsg, "QApplication::setInputContext: called with 0 input context"); |
|
200 obj1.setInputContext((QInputContext *)0); |
|
201 QCOMPARE((QInputContext *)var1, obj1.inputContext()); |
|
202 // delete var1; // No delete, since QApplication takes ownership |
|
203 } |
|
204 |
|
205 class CloseEventTestWindow : public QWidget |
|
206 { |
|
207 public: |
|
208 CloseEventTestWindow(QWidget *parent = 0) |
|
209 : QWidget(parent) |
|
210 { |
|
211 } |
|
212 |
|
213 void closeEvent(QCloseEvent *event) |
|
214 { |
|
215 QWidget dialog; |
|
216 dialog.show(); |
|
217 dialog.close(); |
|
218 |
|
219 hide(); |
|
220 event->ignore(); |
|
221 } |
|
222 }; |
|
223 */ |
|
224 |
|
225 static char *argv0; |
|
226 |
|
227 tst_QApplication::tst_QApplication() |
|
228 { |
|
229 #ifdef Q_OS_WINCE |
|
230 // Clean up environment previously to launching test |
|
231 qputenv("QT_PLUGIN_PATH", QByteArray()); |
|
232 #endif |
|
233 } |
|
234 |
|
235 tst_QApplication::~tst_QApplication() |
|
236 { |
|
237 |
|
238 } |
|
239 |
|
240 void tst_QApplication::init() |
|
241 { |
|
242 // TODO: Add initialization code here. |
|
243 // This will be executed immediately before each test is run. |
|
244 } |
|
245 |
|
246 void tst_QApplication::cleanup() |
|
247 { |
|
248 // TODO: Add cleanup code here. |
|
249 // This will be executed immediately after each test is run. |
|
250 } |
|
251 |
|
252 /* |
|
253 void tst_QApplication::staticSetup() |
|
254 { |
|
255 QVERIFY(!qApp); |
|
256 |
|
257 QStyle *style = QStyleFactory::create(QLatin1String("Windows")); |
|
258 QVERIFY(style); |
|
259 QApplication::setStyle(style); |
|
260 |
|
261 QPalette pal; |
|
262 QApplication::setPalette(pal); |
|
263 |
|
264 //QFont font; |
|
265 //QApplication::setFont(font); |
|
266 |
|
267 int argc = 0; |
|
268 QApplication app(argc, 0, QApplication::GuiServer); |
|
269 } |
|
270 |
|
271 |
|
272 // QApp subclass that exits the event loop after 150ms |
|
273 class TestApplication : public QApplication |
|
274 { |
|
275 public: |
|
276 TestApplication( int &argc, char **argv ) |
|
277 : QApplication( argc, argv, QApplication::GuiServer ) |
|
278 { |
|
279 startTimer( 150 ); |
|
280 } |
|
281 |
|
282 void timerEvent( QTimerEvent * ) |
|
283 { |
|
284 quit(); |
|
285 } |
|
286 }; |
|
287 |
|
288 void tst_QApplication::alert() |
|
289 { |
|
290 int argc = 0; |
|
291 QApplication app(argc, 0, QApplication::GuiServer); |
|
292 app.alert(0, 0); |
|
293 |
|
294 QWidget widget; |
|
295 QWidget widget2; |
|
296 app.alert(&widget, 100); |
|
297 widget.show(); |
|
298 widget2.show(); |
|
299 #ifdef Q_WS_X11 |
|
300 qt_x11_wait_for_window_manager(&widget); |
|
301 qt_x11_wait_for_window_manager(&widget2); |
|
302 #endif |
|
303 QTest::qWait(100); |
|
304 app.alert(&widget, -1); |
|
305 app.alert(&widget, 250); |
|
306 widget2.activateWindow(); |
|
307 QApplication::setActiveWindow(&widget2); |
|
308 app.alert(&widget, 0); |
|
309 widget.activateWindow(); |
|
310 QApplication::setActiveWindow(&widget); |
|
311 app.alert(&widget, 200); |
|
312 app.syncX(); |
|
313 } |
|
314 |
|
315 void tst_QApplication::multiple_data() |
|
316 { |
|
317 QTest::addColumn<QStringList>("features"); |
|
318 |
|
319 // return a list of things to try |
|
320 QTest::newRow( "data0" ) << QStringList( "" ); |
|
321 QTest::newRow( "data1" ) << QStringList( "QFont" ); |
|
322 QTest::newRow( "data2" ) << QStringList( "QPixmap" ); |
|
323 QTest::newRow( "data3" ) << QStringList( "QWidget" ); |
|
324 } |
|
325 |
|
326 void tst_QApplication::multiple() |
|
327 { |
|
328 QFETCH(QStringList,features); |
|
329 |
|
330 int i = 0; |
|
331 int argc = 0; |
|
332 while ( i++ < 5 ) { |
|
333 TestApplication app( argc, 0 ); |
|
334 |
|
335 if ( features.contains( "QFont" ) ) { |
|
336 // create font and force loading |
|
337 QFont font( "Arial", 12 ); |
|
338 QFontInfo finfo( font ); |
|
339 finfo.exactMatch(); |
|
340 } |
|
341 if ( features.contains( "QPixmap" ) ) { |
|
342 QPixmap pix( 100, 100 ); |
|
343 pix.fill( Qt::black ); |
|
344 } |
|
345 if ( features.contains( "QWidget" ) ) { |
|
346 QWidget widget; |
|
347 } |
|
348 |
|
349 QVERIFY(!app.exec()); |
|
350 } |
|
351 } |
|
352 |
|
353 void tst_QApplication::nonGui() |
|
354 { |
|
355 #ifdef Q_OS_HPUX |
|
356 // ### This is only to allow us to generate a test report for now. |
|
357 QSKIP("This test shuts down the window manager on HP-UX.", SkipAll); |
|
358 #endif |
|
359 |
|
360 int argc = 0; |
|
361 QApplication app(argc, 0, false); |
|
362 QCOMPARE(qApp, &app); |
|
363 } |
|
364 |
|
365 void tst_QApplication::setFont_data() |
|
366 { |
|
367 QTest::addColumn<QString>("family"); |
|
368 QTest::addColumn<int>("pointsize"); |
|
369 QTest::addColumn<bool>("beforeAppConstructor"); |
|
370 |
|
371 int argc = 0; |
|
372 QApplication app(argc, 0, QApplication::GuiServer); // Needed for QFontDatabase |
|
373 |
|
374 int cnt = 0; |
|
375 QFontDatabase fdb; |
|
376 QStringList families = fdb.families(); |
|
377 for (QStringList::const_iterator itr = families.begin(); |
|
378 itr != families.end(); |
|
379 ++itr) { |
|
380 if (cnt < 3) { |
|
381 QString family = *itr; |
|
382 QStringList styles = fdb.styles(family); |
|
383 if (styles.size() > 0) { |
|
384 QString style = styles.first(); |
|
385 QList<int> sizes = fdb.pointSizes(family, style); |
|
386 if (!sizes.size()) |
|
387 sizes = fdb.standardSizes(); |
|
388 if (sizes.size() > 0) { |
|
389 QTest::newRow(QString("data%1a").arg(cnt).toLatin1().constData()) |
|
390 << family |
|
391 << sizes.first() |
|
392 << false; |
|
393 QTest::newRow(QString("data%1b").arg(cnt).toLatin1().constData()) |
|
394 << family |
|
395 << sizes.first() |
|
396 << true; |
|
397 } |
|
398 } |
|
399 } |
|
400 ++cnt; |
|
401 } |
|
402 |
|
403 QTest::newRow("nonexistingfont") << "nosuchfont_probably_quiteunlikely" |
|
404 << 0 << false; |
|
405 QTest::newRow("nonexistingfont") << "nosuchfont_probably_quiteunlikely" |
|
406 << 0 << true; |
|
407 |
|
408 QTest::newRow("largescaleable") << "smoothtimes" << 100 << false; |
|
409 QTest::newRow("largescaleable") << "smoothtimes" << 100 << true; |
|
410 |
|
411 QTest::newRow("largeunscaleale") << "helvetica" << 100 << false; |
|
412 QTest::newRow("largeunscaleale") << "helvetica" << 100 << true; |
|
413 } |
|
414 |
|
415 void tst_QApplication::setFont() |
|
416 { |
|
417 QFETCH( QString, family ); |
|
418 QFETCH( int, pointsize ); |
|
419 QFETCH( bool, beforeAppConstructor ); |
|
420 |
|
421 QFont font( family, pointsize ); |
|
422 if (beforeAppConstructor) { |
|
423 QApplication::setFont( font ); |
|
424 QCOMPARE(QApplication::font(), font); |
|
425 } |
|
426 |
|
427 int argc = 0; |
|
428 QApplication app( argc, 0, QApplication::GuiServer ); |
|
429 if (!beforeAppConstructor) |
|
430 QApplication::setFont( font ); |
|
431 |
|
432 QCOMPARE( app.font(), font ); |
|
433 } |
|
434 |
|
435 void tst_QApplication::args_data() |
|
436 { |
|
437 QTest::addColumn<int>("argc_in"); |
|
438 QTest::addColumn<QString>("args_in"); |
|
439 QTest::addColumn<int>("argc_out"); |
|
440 QTest::addColumn<QString>("args_out"); |
|
441 |
|
442 QTest::newRow( "App name" ) << 1 << "/usr/bin/appname" << 1 << "/usr/bin/appname"; |
|
443 QTest::newRow( "No arguments" ) << 0 << QString() << 0 << QString(); |
|
444 QTest::newRow( "App name, style" ) << 3 << "/usr/bin/appname -style motif" << 1 << "/usr/bin/appname"; |
|
445 QTest::newRow( "App name, style, arbitrary, reverse" ) << 5 << "/usr/bin/appname -style motif -arbitrary -reverse" |
|
446 << 2 << "/usr/bin/appname -arbitrary"; |
|
447 } |
|
448 |
|
449 void tst_QApplication::task109149() |
|
450 { |
|
451 int argc = 0; |
|
452 QApplication app(argc, 0, QApplication::GuiServer); |
|
453 QApplication::setFont(QFont("helvetica", 100)); |
|
454 |
|
455 QWidget w; |
|
456 w.setWindowTitle("hello"); |
|
457 w.show(); |
|
458 |
|
459 app.processEvents(); |
|
460 } |
|
461 |
|
462 static char ** QString2cstrings( const QString &args ) |
|
463 { |
|
464 static QList<QByteArray> cache; |
|
465 |
|
466 int i; |
|
467 char **argarray = 0; |
|
468 QStringList list = args.split(' ');; |
|
469 argarray = new char*[list.count()+1]; |
|
470 |
|
471 for (i = 0; i < (int)list.count(); ++i ) { |
|
472 QByteArray l1 = list[i].toLatin1(); |
|
473 argarray[i] = l1.data(); |
|
474 cache.append(l1); |
|
475 } |
|
476 argarray[i] = 0; |
|
477 |
|
478 return argarray; |
|
479 } |
|
480 |
|
481 static QString cstrings2QString( char **args ) |
|
482 { |
|
483 QString string; |
|
484 if ( !args ) |
|
485 return string; |
|
486 |
|
487 int i = 0; |
|
488 while ( args[i] ) { |
|
489 string += args[i]; |
|
490 if ( args[i+1] ) |
|
491 string += " "; |
|
492 ++i; |
|
493 } |
|
494 return string; |
|
495 } |
|
496 |
|
497 void tst_QApplication::args() |
|
498 { |
|
499 QFETCH( int, argc_in ); |
|
500 QFETCH( QString, args_in ); |
|
501 QFETCH( int, argc_out ); |
|
502 QFETCH( QString, args_out ); |
|
503 |
|
504 char **argv = QString2cstrings( args_in ); |
|
505 |
|
506 QApplication app( argc_in, argv, QApplication::GuiServer ); |
|
507 QString argv_out = cstrings2QString(argv); |
|
508 |
|
509 QCOMPARE( argc_in, argc_out ); |
|
510 QCOMPARE( argv_out, args_out ); |
|
511 |
|
512 delete [] argv; |
|
513 } |
|
514 |
|
515 class CloseWidget : public QWidget |
|
516 { |
|
517 Q_OBJECT |
|
518 public: |
|
519 CloseWidget() |
|
520 { |
|
521 startTimer(500); |
|
522 } |
|
523 |
|
524 protected: |
|
525 void timerEvent(QTimerEvent *) |
|
526 { |
|
527 close(); |
|
528 } |
|
529 |
|
530 }; |
|
531 |
|
532 void tst_QApplication::lastWindowClosed() |
|
533 { |
|
534 int argc = 0; |
|
535 QApplication app(argc, 0, QApplication::GuiServer); |
|
536 |
|
537 QSignalSpy spy(&app, SIGNAL(lastWindowClosed())); |
|
538 |
|
539 QPointer<QDialog> dialog = new QDialog; |
|
540 QVERIFY(dialog->testAttribute(Qt::WA_QuitOnClose)); |
|
541 QTimer::singleShot(1000, dialog, SLOT(accept())); |
|
542 dialog->exec(); |
|
543 QVERIFY(dialog); |
|
544 QCOMPARE(spy.count(), 0); |
|
545 |
|
546 QPointer<CloseWidget>widget = new CloseWidget; |
|
547 QVERIFY(widget->testAttribute(Qt::WA_QuitOnClose)); |
|
548 QObject::connect(&app, SIGNAL(lastWindowClosed()), widget, SLOT(deleteLater())); |
|
549 app.exec(); |
|
550 QVERIFY(!widget); |
|
551 QCOMPARE(spy.count(), 1); |
|
552 spy.clear(); |
|
553 |
|
554 #if 0 |
|
555 // everything is closed, so doing this should not emit lastWindowClosed() again |
|
556 QMetaObject::invokeMethod(dialog, "close", Qt::QueuedConnection); |
|
557 QTimer::singleShot(1000, &app, SLOT(quit())); |
|
558 app.exec(); |
|
559 QCOMPARE(spy.count(), 0); |
|
560 #endif |
|
561 |
|
562 delete dialog; |
|
563 |
|
564 // show 3 windows, close them, should only get lastWindowClosed once |
|
565 QWidget w1; |
|
566 QWidget w2; |
|
567 QWidget w3; |
|
568 w1.show(); |
|
569 w2.show(); |
|
570 w3.show(); |
|
571 |
|
572 QTimer::singleShot(1000, &app, SLOT(closeAllWindows())); |
|
573 app.exec(); |
|
574 QCOMPARE(spy.count(), 1); |
|
575 } |
|
576 |
|
577 class QuitOnLastWindowClosedDialog : public QDialog |
|
578 { |
|
579 Q_OBJECT |
|
580 public: |
|
581 QPushButton *okButton; |
|
582 |
|
583 QuitOnLastWindowClosedDialog() |
|
584 { |
|
585 QHBoxLayout *hbox = new QHBoxLayout(this); |
|
586 okButton = new QPushButton("&ok", this); |
|
587 |
|
588 hbox->addWidget(okButton); |
|
589 connect(okButton, SIGNAL(clicked()), this, SLOT(accept())); |
|
590 connect(okButton, SIGNAL(clicked()), this, SLOT(ok_clicked())); |
|
591 } |
|
592 |
|
593 public slots: |
|
594 void ok_clicked() |
|
595 { |
|
596 QDialog other; |
|
597 |
|
598 QTimer timer; |
|
599 connect(&timer, SIGNAL(timeout()), &other, SLOT(accept())); |
|
600 QSignalSpy spy(&timer, SIGNAL(timeout())); |
|
601 QSignalSpy appSpy(qApp, SIGNAL(lastWindowClosed())); |
|
602 |
|
603 timer.start(1000); |
|
604 other.exec(); |
|
605 |
|
606 // verify that the eventloop ran and let the timer fire |
|
607 QCOMPARE(spy.count(), 1); |
|
608 QCOMPARE(appSpy.count(), 1); |
|
609 } |
|
610 }; |
|
611 |
|
612 class QuitOnLastWindowClosedWindow : public QWidget |
|
613 { |
|
614 Q_OBJECT |
|
615 |
|
616 public: |
|
617 QuitOnLastWindowClosedWindow() |
|
618 { } |
|
619 |
|
620 public slots: |
|
621 void execDialogThenShow() |
|
622 { |
|
623 QDialog dialog; |
|
624 QTimer timer1; |
|
625 connect(&timer1, SIGNAL(timeout()), &dialog, SLOT(accept())); |
|
626 QSignalSpy spy1(&timer1, SIGNAL(timeout())); |
|
627 timer1.setSingleShot(true); |
|
628 timer1.start(1000); |
|
629 dialog.exec(); |
|
630 QCOMPARE(spy1.count(), 1); |
|
631 |
|
632 show(); |
|
633 } |
|
634 }; |
|
635 |
|
636 void tst_QApplication::quitOnLastWindowClosed() |
|
637 { |
|
638 { |
|
639 int argc = 0; |
|
640 QApplication app(argc, 0, QApplication::GuiServer); |
|
641 |
|
642 QuitOnLastWindowClosedDialog d; |
|
643 d.show(); |
|
644 QTimer::singleShot(1000, d.okButton, SLOT(animateClick())); |
|
645 |
|
646 QSignalSpy appSpy(&app, SIGNAL(lastWindowClosed())); |
|
647 app.exec(); |
|
648 |
|
649 // lastWindowClosed() signal should only be sent after the last dialog is closed |
|
650 QCOMPARE(appSpy.count(), 2); |
|
651 } |
|
652 { |
|
653 int argc = 0; |
|
654 QApplication app(argc, 0, QApplication::GuiServer); |
|
655 QSignalSpy appSpy(&app, SIGNAL(lastWindowClosed())); |
|
656 |
|
657 QDialog dialog; |
|
658 QTimer timer1; |
|
659 connect(&timer1, SIGNAL(timeout()), &dialog, SLOT(accept())); |
|
660 QSignalSpy spy1(&timer1, SIGNAL(timeout())); |
|
661 timer1.setSingleShot(true); |
|
662 timer1.start(1000); |
|
663 dialog.exec(); |
|
664 QCOMPARE(spy1.count(), 1); |
|
665 QCOMPARE(appSpy.count(), 0); |
|
666 |
|
667 QTimer timer2; |
|
668 connect(&timer2, SIGNAL(timeout()), &app, SLOT(quit())); |
|
669 QSignalSpy spy2(&timer2, SIGNAL(timeout())); |
|
670 timer2.setSingleShot(true); |
|
671 timer2.start(1000); |
|
672 int returnValue = app.exec(); |
|
673 QCOMPARE(returnValue, 0); |
|
674 QCOMPARE(spy2.count(), 1); |
|
675 QCOMPARE(appSpy.count(), 0); |
|
676 } |
|
677 { |
|
678 int argc = 0; |
|
679 QApplication app(argc, 0, QApplication::GuiServer); |
|
680 QTimer timer; |
|
681 timer.setInterval(100); |
|
682 |
|
683 QSignalSpy spy(&app, SIGNAL(aboutToQuit())); |
|
684 QSignalSpy spy2(&timer, SIGNAL(timeout())); |
|
685 |
|
686 QPointer<QMainWindow> mainWindow = new QMainWindow; |
|
687 QPointer<QDialog> dialog = new QDialog(mainWindow); |
|
688 |
|
689 QVERIFY(app.quitOnLastWindowClosed()); |
|
690 QVERIFY(mainWindow->testAttribute(Qt::WA_QuitOnClose)); |
|
691 QVERIFY(dialog->testAttribute(Qt::WA_QuitOnClose)); |
|
692 |
|
693 mainWindow->show(); |
|
694 dialog->show(); |
|
695 |
|
696 timer.start(); |
|
697 QTimer::singleShot(1000, mainWindow, SLOT(close())); // This should quit the application |
|
698 QTimer::singleShot(2000, &app, SLOT(quit())); // This makes sure we quit even if it didn't |
|
699 |
|
700 app.exec(); |
|
701 |
|
702 QCOMPARE(spy.count(), 1); |
|
703 QVERIFY(spy2.count() < 15); // Should be around 10 if closing caused the quit |
|
704 } |
|
705 { |
|
706 int argc = 0; |
|
707 QApplication app(argc, 0, QApplication::GuiServer); |
|
708 QTimer timer; |
|
709 timer.setInterval(100); |
|
710 |
|
711 QSignalSpy spy(&app, SIGNAL(aboutToQuit())); |
|
712 QSignalSpy spy2(&timer, SIGNAL(timeout())); |
|
713 |
|
714 QPointer<QMainWindow> mainWindow = new QMainWindow; |
|
715 QPointer<QWidget> invisibleTopLevelWidget = new QWidget; |
|
716 invisibleTopLevelWidget->setAttribute(Qt::WA_DontShowOnScreen); |
|
717 |
|
718 QVERIFY(app.quitOnLastWindowClosed()); |
|
719 QVERIFY(mainWindow->testAttribute(Qt::WA_QuitOnClose)); |
|
720 QVERIFY(invisibleTopLevelWidget->testAttribute(Qt::WA_QuitOnClose)); |
|
721 QVERIFY(invisibleTopLevelWidget->testAttribute(Qt::WA_DontShowOnScreen)); |
|
722 |
|
723 mainWindow->show(); |
|
724 invisibleTopLevelWidget->show(); |
|
725 |
|
726 timer.start(); |
|
727 QTimer::singleShot(1000, mainWindow, SLOT(close())); // This should quit the application |
|
728 QTimer::singleShot(2000, &app, SLOT(quit())); // This makes sure we quit even if it didn't |
|
729 |
|
730 app.exec(); |
|
731 |
|
732 QCOMPARE(spy.count(), 1); |
|
733 QVERIFY(spy2.count() < 15); // Should be around 10 if closing caused the quit |
|
734 } |
|
735 { |
|
736 int argc = 0; |
|
737 QApplication app(argc, 0, QApplication::GuiServer); |
|
738 QTimer timer; |
|
739 timer.setInterval(100); |
|
740 |
|
741 QSignalSpy spy(&app, SIGNAL(aboutToQuit())); |
|
742 QSignalSpy spy2(&timer, SIGNAL(timeout())); |
|
743 |
|
744 QPointer<CloseEventTestWindow> mainWindow = new CloseEventTestWindow; |
|
745 |
|
746 QVERIFY(app.quitOnLastWindowClosed()); |
|
747 QVERIFY(mainWindow->testAttribute(Qt::WA_QuitOnClose)); |
|
748 |
|
749 mainWindow->show(); |
|
750 |
|
751 timer.start(); |
|
752 QTimer::singleShot(1000, mainWindow, SLOT(close())); // This should quit the application |
|
753 QTimer::singleShot(2000, &app, SLOT(quit())); // This makes sure we quit even if it didn't |
|
754 |
|
755 app.exec(); |
|
756 |
|
757 QCOMPARE(spy.count(), 1); |
|
758 QVERIFY(spy2.count() > 15); // Should be around 20 if closing did not caused the quit |
|
759 } |
|
760 { |
|
761 int argc = 0; |
|
762 QApplication app(argc, 0, QApplication::GuiServer); |
|
763 QSignalSpy appSpy(&app, SIGNAL(lastWindowClosed())); |
|
764 |
|
765 // exec a dialog for 1 second, then show the window |
|
766 QuitOnLastWindowClosedWindow window; |
|
767 QTimer::singleShot(0, &window, SLOT(execDialogThenShow())); |
|
768 |
|
769 QTimer timer; |
|
770 QSignalSpy timerSpy(&timer, SIGNAL(timeout())); |
|
771 connect(&timer, SIGNAL(timeout()), &window, SLOT(close())); |
|
772 timer.setSingleShot(true); |
|
773 timer.start(2000); |
|
774 int returnValue = app.exec(); |
|
775 QCOMPARE(returnValue, 0); |
|
776 // failure here means the timer above didn't fire, and the |
|
777 // quit was caused the the dialog being closed (not the window) |
|
778 QCOMPARE(timerSpy.count(), 1); |
|
779 QCOMPARE(appSpy.count(), 2); |
|
780 } |
|
781 } |
|
782 |
|
783 bool isPathListIncluded(const QStringList &l, const QStringList &r) |
|
784 { |
|
785 int size = r.count(); |
|
786 if (size > l.count()) |
|
787 return false; |
|
788 #if defined (Q_OS_WIN) |
|
789 Qt::CaseSensitivity cs = Qt::CaseInsensitive; |
|
790 #else |
|
791 Qt::CaseSensitivity cs = Qt::CaseSensitive; |
|
792 #endif |
|
793 int i = 0, j = 0; |
|
794 for ( ; i < l.count() && j < r.count(); ++i) { |
|
795 if (QDir::toNativeSeparators(l[i]).compare(QDir::toNativeSeparators(r[j]), cs) == 0) { |
|
796 ++j; |
|
797 i = -1; |
|
798 } |
|
799 } |
|
800 return j == r.count(); |
|
801 } |
|
802 |
|
803 #define QT_TST_QAPP_DEBUG |
|
804 void tst_QApplication::libraryPaths() |
|
805 { |
|
806 { |
|
807 #ifndef Q_OS_WINCE |
|
808 QString testDir = QDir::current().canonicalPath() + "/test"; |
|
809 #else |
|
810 // On Windows CE we need QApplication object to have valid |
|
811 // current Path. Therefore we need to identify it ourselves |
|
812 // here for the test. |
|
813 QFileInfo filePath; |
|
814 wchar_t module_name[MAX_PATH]; |
|
815 GetModuleFileName(0, module_name, MAX_PATH); |
|
816 filePath = QString::fromWCharArray(module_name); |
|
817 QString testDir = filePath.path() + "/test"; |
|
818 #endif |
|
819 QApplication::setLibraryPaths(QStringList() << testDir); |
|
820 QCOMPARE(QApplication::libraryPaths(), (QStringList() << testDir)); |
|
821 |
|
822 // creating QApplication adds the applicationDirPath to the libraryPath |
|
823 int argc = 1; |
|
824 QApplication app(argc, &argv0, QApplication::GuiServer); |
|
825 QString appDirPath = QDir(app.applicationDirPath()).canonicalPath(); |
|
826 |
|
827 QStringList actual = QApplication::libraryPaths(); |
|
828 actual.sort(); |
|
829 QStringList expected = QSet<QString>::fromList((QStringList() << testDir << appDirPath)).toList(); |
|
830 expected.sort(); |
|
831 |
|
832 QVERIFY2(isPathListIncluded(actual, expected), |
|
833 qPrintable("actual:\n - " + actual.join("\n - ") + |
|
834 "\nexpected:\n - " + expected.join("\n - "))); |
|
835 } |
|
836 { |
|
837 // creating QApplication adds the applicationDirPath and plugin install path to the libraryPath |
|
838 int argc = 1; |
|
839 QApplication app(argc, &argv0, QApplication::GuiServer); |
|
840 QString appDirPath = app.applicationDirPath(); |
|
841 QString installPathPlugins = QLibraryInfo::location(QLibraryInfo::PluginsPath); |
|
842 |
|
843 QStringList actual = QApplication::libraryPaths(); |
|
844 actual.sort(); |
|
845 |
|
846 #if defined(Q_OS_SYMBIAN) |
|
847 QStringList expected; |
|
848 addExpectedSymbianPluginsPath(expected); |
|
849 expected << appDirPath; |
|
850 #else |
|
851 QStringList expected = QSet<QString>::fromList((QStringList() << installPathPlugins << appDirPath)).toList(); |
|
852 #endif |
|
853 expected.sort(); |
|
854 |
|
855 QVERIFY2(isPathListIncluded(actual, expected), |
|
856 qPrintable("actual:\n - " + actual.join("\n - ") + |
|
857 "\nexpected:\n - " + expected.join("\n - "))); |
|
858 |
|
859 // setting the library paths overrides everything |
|
860 QString testDir = QDir::currentPath() + "/test"; |
|
861 QApplication::setLibraryPaths(QStringList() << testDir); |
|
862 QVERIFY2(isPathListIncluded(QApplication::libraryPaths(), (QStringList() << testDir)), |
|
863 qPrintable("actual:\n - " + QApplication::libraryPaths().join("\n - ") + |
|
864 "\nexpected:\n - " + testDir)); |
|
865 } |
|
866 { |
|
867 #ifdef QT_TST_QAPP_DEBUG |
|
868 qDebug() << "Initial library path:" << QApplication::libraryPaths(); |
|
869 #endif |
|
870 |
|
871 int count = QApplication::libraryPaths().count(); |
|
872 #if 0 |
|
873 // this test doesn't work if KDE 4 is installed |
|
874 QCOMPARE(count, 1); // before creating QApplication, only the PluginsPath is in the libraryPaths() |
|
875 #endif |
|
876 QString installPathPlugins = QLibraryInfo::location(QLibraryInfo::PluginsPath); |
|
877 QApplication::addLibraryPath(installPathPlugins); |
|
878 #ifdef QT_TST_QAPP_DEBUG |
|
879 qDebug() << "installPathPlugins" << installPathPlugins; |
|
880 qDebug() << "After adding plugins path:" << QApplication::libraryPaths(); |
|
881 #endif |
|
882 QCOMPARE(QApplication::libraryPaths().count(), count); |
|
883 |
|
884 QApplication::addLibraryPath(QDir::currentPath() + "/test"); |
|
885 QCOMPARE(QApplication::libraryPaths().count(), count + 1); |
|
886 |
|
887 // creating QApplication adds the applicationDirPath to the libraryPath |
|
888 int argc = 1; |
|
889 QApplication app(argc, &argv0, QApplication::GuiServer); |
|
890 QString appDirPath = app.applicationDirPath(); |
|
891 qDebug() << QApplication::libraryPaths(); |
|
892 // On Windows CE these are identical and might also be the case for other |
|
893 // systems too |
|
894 if (appDirPath != installPathPlugins) |
|
895 QCOMPARE(QApplication::libraryPaths().count(), count + 2); |
|
896 } |
|
897 { |
|
898 int argc = 1; |
|
899 QApplication app(argc, &argv0, QApplication::GuiServer); |
|
900 |
|
901 #ifdef QT_TST_QAPP_DEBUG |
|
902 qDebug() << "Initial library path:" << app.libraryPaths(); |
|
903 #endif |
|
904 int count = app.libraryPaths().count(); |
|
905 QString installPathPlugins = QLibraryInfo::location(QLibraryInfo::PluginsPath); |
|
906 app.addLibraryPath(installPathPlugins); |
|
907 #ifdef QT_TST_QAPP_DEBUG |
|
908 qDebug() << "installPathPlugins" << installPathPlugins; |
|
909 qDebug() << "After adding plugins path:" << app.libraryPaths(); |
|
910 #endif |
|
911 QCOMPARE(app.libraryPaths().count(), count); |
|
912 |
|
913 QString appDirPath = app.applicationDirPath(); |
|
914 |
|
915 app.addLibraryPath(appDirPath); |
|
916 #ifdef Q_OS_WINCE |
|
917 app.addLibraryPath(appDirPath + "/../.."); |
|
918 #else |
|
919 app.addLibraryPath(appDirPath + "/.."); |
|
920 #endif |
|
921 #ifdef QT_TST_QAPP_DEBUG |
|
922 qDebug() << "appDirPath" << appDirPath; |
|
923 qDebug() << "After adding appDirPath && appDirPath + /..:" << app.libraryPaths(); |
|
924 #endif |
|
925 QCOMPARE(app.libraryPaths().count(), count + 1); |
|
926 #ifdef Q_OS_MAC |
|
927 app.addLibraryPath(appDirPath + "/../MacOS"); |
|
928 #else |
|
929 app.addLibraryPath(appDirPath + "/tmp/.."); |
|
930 #endif |
|
931 #ifdef QT_TST_QAPP_DEBUG |
|
932 qDebug() << "After adding appDirPath + /tmp/..:" << app.libraryPaths(); |
|
933 #endif |
|
934 QCOMPARE(app.libraryPaths().count(), count + 1); |
|
935 } |
|
936 } |
|
937 |
|
938 void tst_QApplication::libraryPaths_qt_plugin_path() |
|
939 { |
|
940 int argc = 1; |
|
941 |
|
942 QApplication app(argc, &argv0, QApplication::GuiServer); |
|
943 QString appDirPath = app.applicationDirPath(); |
|
944 |
|
945 // Our hook into libraryPaths() initialization: Set the QT_PLUGIN_PATH environment variable |
|
946 QString installPathPluginsDeCanon = appDirPath + QString::fromLatin1("/tmp/.."); |
|
947 QByteArray ascii = installPathPluginsDeCanon.toAscii(); |
|
948 qputenv("QT_PLUGIN_PATH", ascii); |
|
949 |
|
950 QVERIFY(!app.libraryPaths().contains(appDirPath + QString::fromLatin1("/tmp/.."))); |
|
951 } |
|
952 |
|
953 void tst_QApplication::libraryPaths_qt_plugin_path_2() |
|
954 { |
|
955 #ifdef Q_OS_SYMBIAN |
|
956 QByteArray validPath = "C:\\data"; |
|
957 QByteArray nonExistentPath = "Z:\\nonexistent"; |
|
958 QByteArray pluginPath = validPath + ";" + nonExistentPath; |
|
959 #elif defined(Q_OS_UNIX) |
|
960 QByteArray validPath = QDir("/tmp").canonicalPath().toLatin1(); |
|
961 QByteArray nonExistentPath = "/nonexistent"; |
|
962 QByteArray pluginPath = validPath + ":" + nonExistentPath; |
|
963 #elif defined(Q_OS_WIN) |
|
964 # ifdef Q_OS_WINCE |
|
965 QByteArray validPath = "/Temp"; |
|
966 QByteArray nonExistentPath = "/nonexistent"; |
|
967 QByteArray pluginPath = validPath + ";" + nonExistentPath; |
|
968 # else |
|
969 QByteArray validPath = "C:\\windows"; |
|
970 QByteArray nonExistentPath = "Z:\\nonexistent"; |
|
971 QByteArray pluginPath = validPath + ";" + nonExistentPath; |
|
972 # endif |
|
973 #endif |
|
974 |
|
975 { |
|
976 // Our hook into libraryPaths() initialization: Set the QT_PLUGIN_PATH environment variable |
|
977 qputenv("QT_PLUGIN_PATH", pluginPath); |
|
978 |
|
979 int argc = 1; |
|
980 |
|
981 QApplication app(argc, &argv0, QApplication::GuiServer); |
|
982 |
|
983 // library path list should contain the default plus the one valid path |
|
984 #if defined(Q_OS_SYMBIAN) |
|
985 // In Symbian, the PluginsPath doesn't specify the only absolute path; just the dir that can be found on any drive |
|
986 QStringList expected; |
|
987 addExpectedSymbianPluginsPath(expected); |
|
988 expected << QDir(app.applicationDirPath()).canonicalPath() |
|
989 << QDir(QDir::fromNativeSeparators(QString::fromLatin1(validPath))).canonicalPath(); |
|
990 #else |
|
991 QStringList expected = |
|
992 QStringList() |
|
993 << QLibraryInfo::location(QLibraryInfo::PluginsPath) |
|
994 << QDir(app.applicationDirPath()).canonicalPath() |
|
995 << QDir(QDir::fromNativeSeparators(QString::fromLatin1(validPath))).canonicalPath(); |
|
996 # ifdef Q_OS_WINCE |
|
997 expected = QSet<QString>::fromList(expected).toList(); |
|
998 # endif |
|
999 #endif |
|
1000 QVERIFY2(isPathListIncluded(app.libraryPaths(), expected), |
|
1001 qPrintable("actual:\n - " + app.libraryPaths().join("\n - ") + |
|
1002 "\nexpected:\n - " + expected.join("\n - "))); |
|
1003 } |
|
1004 |
|
1005 { |
|
1006 int argc = 1; |
|
1007 |
|
1008 QApplication app(argc, &argv0, QApplication::GuiServer); |
|
1009 |
|
1010 // library paths are initialized by the QApplication, setting |
|
1011 // the environment variable here doesn't work |
|
1012 qputenv("QT_PLUGIN_PATH", pluginPath); |
|
1013 |
|
1014 // library path list should contain the default |
|
1015 #if defined(Q_OS_SYMBIAN) |
|
1016 QStringList expected; |
|
1017 addExpectedSymbianPluginsPath(expected); |
|
1018 expected << app.applicationDirPath(); |
|
1019 #else |
|
1020 QStringList expected = |
|
1021 QStringList() |
|
1022 << QLibraryInfo::location(QLibraryInfo::PluginsPath) |
|
1023 << app.applicationDirPath(); |
|
1024 # ifdef Q_OS_WINCE |
|
1025 expected = QSet<QString>::fromList(expected).toList(); |
|
1026 # endif |
|
1027 #endif |
|
1028 QVERIFY(isPathListIncluded(app.libraryPaths(), expected)); |
|
1029 |
|
1030 qputenv("QT_PLUGIN_PATH", QByteArray()); |
|
1031 } |
|
1032 } |
|
1033 |
|
1034 class SendPostedEventsTester : public QObject |
|
1035 { |
|
1036 Q_OBJECT |
|
1037 public: |
|
1038 QList<int> eventSpy; |
|
1039 bool event(QEvent *e); |
|
1040 private slots: |
|
1041 void doTest(); |
|
1042 }; |
|
1043 |
|
1044 bool SendPostedEventsTester::event(QEvent *e) |
|
1045 { |
|
1046 eventSpy.append(e->type()); |
|
1047 return QObject::event(e); |
|
1048 } |
|
1049 |
|
1050 void SendPostedEventsTester::doTest() |
|
1051 { |
|
1052 QPointer<SendPostedEventsTester> p = this; |
|
1053 QApplication::postEvent(this, new QEvent(QEvent::User)); |
|
1054 // DeferredDelete should not be delivered until returning from this function |
|
1055 QApplication::postEvent(this, new QEvent(QEvent::DeferredDelete)); |
|
1056 |
|
1057 QEventLoop eventLoop; |
|
1058 QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection); |
|
1059 eventLoop.exec(); |
|
1060 QVERIFY(p != 0); |
|
1061 |
|
1062 QCOMPARE(eventSpy.count(), 2); |
|
1063 QCOMPARE(eventSpy.at(0), int(QEvent::MetaCall)); |
|
1064 QCOMPARE(eventSpy.at(1), int(QEvent::User)); |
|
1065 eventSpy.clear(); |
|
1066 } |
|
1067 |
|
1068 void tst_QApplication::sendPostedEvents() |
|
1069 { |
|
1070 int argc = 0; |
|
1071 QApplication app(argc, 0, QApplication::GuiServer); |
|
1072 SendPostedEventsTester *tester = new SendPostedEventsTester; |
|
1073 QMetaObject::invokeMethod(tester, "doTest", Qt::QueuedConnection); |
|
1074 QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection); |
|
1075 QPointer<SendPostedEventsTester> p = tester; |
|
1076 (void) app.exec(); |
|
1077 QVERIFY(p == 0); |
|
1078 } |
|
1079 |
|
1080 void tst_QApplication::thread() |
|
1081 { |
|
1082 QThread *currentThread = QThread::currentThread(); |
|
1083 // no app, but still have a valid thread |
|
1084 QVERIFY(currentThread != 0); |
|
1085 |
|
1086 // the thread should be running and not finished |
|
1087 QVERIFY(currentThread->isRunning()); |
|
1088 QVERIFY(!currentThread->isFinished()); |
|
1089 |
|
1090 // this should probably be in the tst_QObject::thread() test, but |
|
1091 // we put it here since we want to make sure that objects created |
|
1092 // *before* the QApplication has a thread |
|
1093 QObject object; |
|
1094 QObject child(&object); |
|
1095 QVERIFY(object.thread() == currentThread); |
|
1096 QVERIFY(child.thread() == currentThread); |
|
1097 |
|
1098 { |
|
1099 int argc = 0; |
|
1100 QApplication app(argc, 0, QApplication::GuiServer); |
|
1101 |
|
1102 // current thread still valid |
|
1103 QVERIFY(QThread::currentThread() != 0); |
|
1104 // thread should be the same as before |
|
1105 QCOMPARE(QThread::currentThread(), currentThread); |
|
1106 |
|
1107 // app's thread should be the current thread |
|
1108 QCOMPARE(app.thread(), currentThread); |
|
1109 |
|
1110 // the thread should still be running and not finished |
|
1111 QVERIFY(currentThread->isRunning()); |
|
1112 QVERIFY(!currentThread->isFinished()); |
|
1113 |
|
1114 QTestEventLoop::instance().enterLoop(1); |
|
1115 } |
|
1116 |
|
1117 // app dead, current thread still valid |
|
1118 QVERIFY(QThread::currentThread() != 0); |
|
1119 QCOMPARE(QThread::currentThread(), currentThread); |
|
1120 |
|
1121 // the thread should still be running and not finished |
|
1122 QVERIFY(currentThread->isRunning()); |
|
1123 QVERIFY(!currentThread->isFinished()); |
|
1124 |
|
1125 // should still have a thread |
|
1126 QVERIFY(object.thread() == currentThread); |
|
1127 QVERIFY(child.thread() == currentThread); |
|
1128 |
|
1129 // do the test again, making sure that the thread is the same as |
|
1130 // before |
|
1131 { |
|
1132 int argc = 0; |
|
1133 QApplication app(argc, 0, QApplication::GuiServer); |
|
1134 |
|
1135 // current thread still valid |
|
1136 QVERIFY(QThread::currentThread() != 0); |
|
1137 // thread should be the same as before |
|
1138 QCOMPARE(QThread::currentThread(), currentThread); |
|
1139 |
|
1140 // app's thread should be the current thread |
|
1141 QCOMPARE(app.thread(), currentThread); |
|
1142 |
|
1143 // the thread should be running and not finished |
|
1144 QVERIFY(currentThread->isRunning()); |
|
1145 QVERIFY(!currentThread->isFinished()); |
|
1146 |
|
1147 // should still have a thread |
|
1148 QVERIFY(object.thread() == currentThread); |
|
1149 QVERIFY(child.thread() == currentThread); |
|
1150 |
|
1151 QTestEventLoop::instance().enterLoop(1); |
|
1152 } |
|
1153 |
|
1154 // app dead, current thread still valid |
|
1155 QVERIFY(QThread::currentThread() != 0); |
|
1156 QCOMPARE(QThread::currentThread(), currentThread); |
|
1157 |
|
1158 // the thread should still be running and not finished |
|
1159 QVERIFY(currentThread->isRunning()); |
|
1160 QVERIFY(!currentThread->isFinished()); |
|
1161 |
|
1162 // should still have a thread |
|
1163 QVERIFY(object.thread() == currentThread); |
|
1164 QVERIFY(child.thread() == currentThread); |
|
1165 } |
|
1166 |
|
1167 class DeleteLaterWidget : public QWidget |
|
1168 { |
|
1169 Q_OBJECT |
|
1170 public: |
|
1171 DeleteLaterWidget(QApplication *_app, QWidget *parent = 0) |
|
1172 : QWidget(parent) { app = _app; child_deleted = false; } |
|
1173 |
|
1174 bool child_deleted; |
|
1175 QApplication *app; |
|
1176 |
|
1177 public slots: |
|
1178 void runTest(); |
|
1179 void checkDeleteLater(); |
|
1180 void childDeleted() { child_deleted = true; } |
|
1181 }; |
|
1182 |
|
1183 |
|
1184 void DeleteLaterWidget::runTest() |
|
1185 { |
|
1186 QObject *stillAlive = qFindChild<QObject*>(this, "deleteLater"); |
|
1187 |
|
1188 QWidget *w = new QWidget(this); |
|
1189 connect(w, SIGNAL(destroyed()), this, SLOT(childDeleted())); |
|
1190 |
|
1191 w->deleteLater(); |
|
1192 QVERIFY(!child_deleted); |
|
1193 |
|
1194 QDialog dlg; |
|
1195 QTimer::singleShot(500, &dlg, SLOT(reject())); |
|
1196 dlg.exec(); |
|
1197 |
|
1198 QVERIFY(!child_deleted); |
|
1199 app->processEvents(); |
|
1200 QVERIFY(!child_deleted); |
|
1201 |
|
1202 QTimer::singleShot(500, this, SLOT(checkDeleteLater())); |
|
1203 |
|
1204 app->processEvents(); |
|
1205 |
|
1206 QVERIFY(!stillAlive); // verify at the end to make test terminate |
|
1207 } |
|
1208 |
|
1209 void DeleteLaterWidget::checkDeleteLater() |
|
1210 { |
|
1211 QVERIFY(child_deleted); |
|
1212 |
|
1213 close(); |
|
1214 } |
|
1215 |
|
1216 void tst_QApplication::testDeleteLater() |
|
1217 { |
|
1218 int argc = 0; |
|
1219 QApplication app(argc, 0, QApplication::GuiServer); |
|
1220 connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit())); |
|
1221 |
|
1222 DeleteLaterWidget *wgt = new DeleteLaterWidget(&app); |
|
1223 QTimer::singleShot(500, wgt, SLOT(runTest())); |
|
1224 |
|
1225 QObject *object = new QObject(wgt); |
|
1226 object->setObjectName("deleteLater"); |
|
1227 object->deleteLater(); |
|
1228 |
|
1229 QObject *stillAlive = qFindChild<QObject*>(wgt, "deleteLater"); |
|
1230 QVERIFY(stillAlive); |
|
1231 |
|
1232 app.exec(); |
|
1233 |
|
1234 delete wgt; |
|
1235 |
|
1236 } |
|
1237 |
|
1238 class EventLoopNester : public QObject |
|
1239 { |
|
1240 Q_OBJECT |
|
1241 public slots: |
|
1242 void deleteLaterAndEnterLoop() |
|
1243 { |
|
1244 QEventLoop eventLoop; |
|
1245 QPointer<QObject> p(this); |
|
1246 deleteLater(); |
|
1247 |
|
1248 // DeferredDelete events are compressed, meaning this second |
|
1249 // deleteLater() will *not* delete the object in the nested |
|
1250 // event loop |
|
1251 QMetaObject::invokeMethod(this, "deleteLater", Qt::QueuedConnection); |
|
1252 QTimer::singleShot(1000, &eventLoop, SLOT(quit())); |
|
1253 eventLoop.exec(); |
|
1254 QVERIFY(p); |
|
1255 } |
|
1256 void deleteLaterAndExitLoop() |
|
1257 { |
|
1258 // Check that 'p' is not deleted before exec returns, since the call |
|
1259 // to QEventLoop::quit() should stop 'eventLoop' from processing |
|
1260 // any more events (that is, delete later) until we return to the |
|
1261 // _current_ event loop: |
|
1262 QEventLoop eventLoop; |
|
1263 QPointer<QObject> p(this); |
|
1264 QMetaObject::invokeMethod(this, "deleteLater", Qt::QueuedConnection); |
|
1265 QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection); |
|
1266 eventLoop.exec(); |
|
1267 QVERIFY(p); // not dead yet |
|
1268 } |
|
1269 |
|
1270 void processEventsOnly() |
|
1271 { |
|
1272 QApplication::processEvents(); |
|
1273 } |
|
1274 void processEventsWithDeferredDeletion() |
|
1275 { |
|
1276 QApplication::processEvents(QEventLoop::DeferredDeletion); |
|
1277 } |
|
1278 void sendPostedEventsWithDeferredDelete() |
|
1279 { |
|
1280 QApplication::sendPostedEvents(0, QEvent::DeferredDelete); |
|
1281 } |
|
1282 void deleteLaterAndProcessEvents1() |
|
1283 { |
|
1284 QEventLoop eventLoop; |
|
1285 |
|
1286 QPointer<QObject> p = this; |
|
1287 deleteLater(); |
|
1288 |
|
1289 // trying to delete this object in a deeper eventloop just won't work |
|
1290 QMetaObject::invokeMethod(this, |
|
1291 "processEventsOnly", |
|
1292 Qt::QueuedConnection); |
|
1293 QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection); |
|
1294 eventLoop.exec(); |
|
1295 QVERIFY(p); |
|
1296 QMetaObject::invokeMethod(this, |
|
1297 "processEventsWithDeferredDeletion", |
|
1298 Qt::QueuedConnection); |
|
1299 QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection); |
|
1300 eventLoop.exec(); |
|
1301 QVERIFY(p); |
|
1302 QMetaObject::invokeMethod(this, |
|
1303 "sendPostedEventsWithDeferredDelete", |
|
1304 Qt::QueuedConnection); |
|
1305 QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection); |
|
1306 eventLoop.exec(); |
|
1307 QVERIFY(p); |
|
1308 |
|
1309 // trying to delete it from this eventloop still doesn't work |
|
1310 QApplication::processEvents(); |
|
1311 QVERIFY(p); |
|
1312 |
|
1313 // however, it *will* work with this magic incantation |
|
1314 QApplication::processEvents(QEventLoop::DeferredDeletion); |
|
1315 QVERIFY(!p); |
|
1316 } |
|
1317 |
|
1318 void deleteLaterAndProcessEvents2() |
|
1319 { |
|
1320 QEventLoop eventLoop; |
|
1321 |
|
1322 QPointer<QObject> p = this; |
|
1323 deleteLater(); |
|
1324 |
|
1325 // trying to delete this object in a deeper eventloop just won't work |
|
1326 QMetaObject::invokeMethod(this, |
|
1327 "processEventsOnly", |
|
1328 Qt::QueuedConnection); |
|
1329 QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection); |
|
1330 eventLoop.exec(); |
|
1331 QVERIFY(p); |
|
1332 QMetaObject::invokeMethod(this, |
|
1333 "processEventsWithDeferredDeletion", |
|
1334 Qt::QueuedConnection); |
|
1335 QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection); |
|
1336 eventLoop.exec(); |
|
1337 QVERIFY(p); |
|
1338 QMetaObject::invokeMethod(this, |
|
1339 "sendPostedEventsWithDeferredDelete", |
|
1340 Qt::QueuedConnection); |
|
1341 QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection); |
|
1342 eventLoop.exec(); |
|
1343 QVERIFY(p); |
|
1344 |
|
1345 // trying to delete it from this eventloop still doesn't work |
|
1346 QApplication::processEvents(); |
|
1347 QVERIFY(p); |
|
1348 |
|
1349 // however, it *will* work with this magic incantation |
|
1350 QApplication::sendPostedEvents(0, QEvent::DeferredDelete); |
|
1351 QVERIFY(!p); |
|
1352 } |
|
1353 }; |
|
1354 |
|
1355 void tst_QApplication::testDeleteLaterProcessEvents() |
|
1356 { |
|
1357 int argc = 0; |
|
1358 |
|
1359 // Calling processEvents() with no event dispatcher does nothing. |
|
1360 QObject *object = new QObject; |
|
1361 QPointer<QObject> p(object); |
|
1362 object->deleteLater(); |
|
1363 QApplication::processEvents(); |
|
1364 QVERIFY(p); |
|
1365 delete object; |
|
1366 |
|
1367 { |
|
1368 QApplication app(argc, 0, QApplication::GuiServer); |
|
1369 // If you call processEvents() with an event dispatcher present, but |
|
1370 // outside any event loops, deferred deletes are not processed unless |
|
1371 // QEventLoop::DeferredDeletion is passed. |
|
1372 object = new QObject; |
|
1373 p = object; |
|
1374 object->deleteLater(); |
|
1375 app.processEvents(); |
|
1376 QVERIFY(p); |
|
1377 app.processEvents(QEventLoop::ProcessEventsFlag(0x10)); // 0x10 == QEventLoop::DeferredDeletion |
|
1378 QVERIFY(!p); |
|
1379 |
|
1380 // sendPostedEvents(0, DeferredDelete); also works |
|
1381 object = new QObject; |
|
1382 p = object; |
|
1383 object->deleteLater(); |
|
1384 app.processEvents(); |
|
1385 QVERIFY(p); |
|
1386 QApplication::sendPostedEvents(0, QEvent::DeferredDelete); |
|
1387 QVERIFY(!p); |
|
1388 |
|
1389 // If you call deleteLater() on an object when there is no parent |
|
1390 // event loop, and then enter an event loop, the object will get |
|
1391 // deleted. |
|
1392 object = new QObject; |
|
1393 p = object; |
|
1394 object->deleteLater(); |
|
1395 QEventLoop loop; |
|
1396 QTimer::singleShot(1000, &loop, SLOT(quit())); |
|
1397 loop.exec(); |
|
1398 QVERIFY(!p); |
|
1399 } |
|
1400 { |
|
1401 // When an object is in an event loop, then calls deleteLater() and enters |
|
1402 // an event loop recursively, it should not die until the parent event |
|
1403 // loop continues. |
|
1404 QApplication app(argc, 0, QApplication::GuiServer); |
|
1405 QEventLoop loop; |
|
1406 EventLoopNester *nester = new EventLoopNester; |
|
1407 p = nester; |
|
1408 QTimer::singleShot(3000, &loop, SLOT(quit())); |
|
1409 QTimer::singleShot(0, nester, SLOT(deleteLaterAndEnterLoop())); |
|
1410 |
|
1411 loop.exec(); |
|
1412 QVERIFY(!p); |
|
1413 } |
|
1414 |
|
1415 { |
|
1416 // When the event loop that calls deleteLater() is exited |
|
1417 // immediately, the object should die when returning to the |
|
1418 // parent event loop |
|
1419 QApplication app(argc, 0, QApplication::GuiServer); |
|
1420 QEventLoop loop; |
|
1421 EventLoopNester *nester = new EventLoopNester; |
|
1422 p = nester; |
|
1423 QTimer::singleShot(3000, &loop, SLOT(quit())); |
|
1424 QTimer::singleShot(0, nester, SLOT(deleteLaterAndExitLoop())); |
|
1425 |
|
1426 loop.exec(); |
|
1427 QVERIFY(!p); |
|
1428 } |
|
1429 |
|
1430 { |
|
1431 // when the event loop that calls deleteLater() also calls |
|
1432 // processEvents() immediately afterwards, the object should |
|
1433 // not die until the parent loop continues |
|
1434 QApplication app(argc, 0, QApplication::GuiServer); |
|
1435 QEventLoop loop; |
|
1436 EventLoopNester *nester = new EventLoopNester(); |
|
1437 p = nester; |
|
1438 QTimer::singleShot(3000, &loop, SLOT(quit())); |
|
1439 QTimer::singleShot(0, nester, SLOT(deleteLaterAndProcessEvents1())); |
|
1440 |
|
1441 loop.exec(); |
|
1442 QVERIFY(!p); |
|
1443 } |
|
1444 |
|
1445 { |
|
1446 // when the event loop that calls deleteLater() also calls |
|
1447 // processEvents() immediately afterwards, the object should |
|
1448 // not die until the parent loop continues |
|
1449 QApplication app(argc, 0, QApplication::GuiServer); |
|
1450 QEventLoop loop; |
|
1451 EventLoopNester *nester = new EventLoopNester(); |
|
1452 p = nester; |
|
1453 QTimer::singleShot(3000, &loop, SLOT(quit())); |
|
1454 QTimer::singleShot(0, nester, SLOT(deleteLaterAndProcessEvents2())); |
|
1455 |
|
1456 loop.exec(); |
|
1457 QVERIFY(!p); |
|
1458 } |
|
1459 } |
|
1460 |
|
1461 |
|
1462 // Test for crash whith QApplication::setDesktopSettingsAware(false). |
|
1463 |
|
1464 void tst_QApplication::desktopSettingsAware() |
|
1465 { |
|
1466 #ifndef QT_NO_PROCESS |
|
1467 QProcess testProcess; |
|
1468 #ifdef Q_OS_WINCE |
|
1469 int argc = 0; |
|
1470 QApplication tmpApp(argc, 0, QApplication::GuiServer); |
|
1471 testProcess.start("desktopsettingsaware/desktopsettingsaware"); |
|
1472 #else |
|
1473 #if defined(Q_OS_WIN) && defined(QT_DEBUG) |
|
1474 testProcess.start("desktopsettingsaware/debug/desktopsettingsaware"); |
|
1475 #elif defined(Q_OS_WIN) |
|
1476 testProcess.start("desktopsettingsaware/release/desktopsettingsaware"); |
|
1477 #elif defined(Q_OS_SYMBIAN) |
|
1478 testProcess.start("desktopsettingsaware"); |
|
1479 #if defined(Q_CC_NOKIAX86) |
|
1480 QEXPECT_FAIL("", "QProcess on Q_CC_NOKIAX86 cannot launch another Qt application, due to DLL conflicts.", Abort); |
|
1481 // TODO: Remove XFAIL, as soon as we can launch Qt applications from within Qt applications on Symbian |
|
1482 QVERIFY(testProcess.error() != QProcess::FailedToStart); |
|
1483 #endif // defined(Q_CC_NOKIAX86) |
|
1484 #else |
|
1485 testProcess.start("desktopsettingsaware/desktopsettingsaware"); |
|
1486 #endif |
|
1487 #endif |
|
1488 QVERIFY(testProcess.waitForFinished(10000)); |
|
1489 QCOMPARE(int(testProcess.state()), int(QProcess::NotRunning)); |
|
1490 QVERIFY(int(testProcess.error()) != int(QProcess::Crashed)); |
|
1491 #endif |
|
1492 } |
|
1493 */ |
|
1494 |
|
1495 void tst_QApplication::setActiveWindow() |
|
1496 { |
|
1497 int argc = 0; |
|
1498 QApplication MyApp(argc, 0, QApplication::GuiServer); |
|
1499 |
|
1500 QWidget* w = new QWidget; |
|
1501 QVBoxLayout* layout = new QVBoxLayout(w); |
|
1502 |
|
1503 QLineEdit* pb1 = new QLineEdit("Testbutton1", w); |
|
1504 QLineEdit* pb2 = new QLineEdit("Test Line Edit", w); |
|
1505 |
|
1506 layout->addWidget(pb1); |
|
1507 layout->addWidget(pb2); |
|
1508 |
|
1509 pb2->setFocus(); |
|
1510 pb2->setParent(0); |
|
1511 delete pb2; |
|
1512 |
|
1513 w->show(); |
|
1514 QApplication::setActiveWindow(w); // needs this on twm (focus follows mouse) |
|
1515 QVERIFY(pb1->hasFocus()); |
|
1516 delete w; |
|
1517 } |
|
1518 |
|
1519 |
|
1520 /* This might fail on some X11 window managers? */ |
|
1521 /* |
|
1522 void tst_QApplication::focusChanged() |
|
1523 { |
|
1524 int argc = 0; |
|
1525 QApplication app(argc, 0, QApplication::GuiServer); |
|
1526 |
|
1527 QSignalSpy spy(&app, SIGNAL(focusChanged(QWidget *, QWidget *))); |
|
1528 QWidget *now = 0; |
|
1529 QWidget *old = 0; |
|
1530 |
|
1531 QWidget parent1; |
|
1532 QHBoxLayout hbox1(&parent1); |
|
1533 QLabel lb1(&parent1); |
|
1534 QLineEdit le1(&parent1); |
|
1535 QPushButton pb1(&parent1); |
|
1536 hbox1.addWidget(&lb1); |
|
1537 hbox1.addWidget(&le1); |
|
1538 hbox1.addWidget(&pb1); |
|
1539 |
|
1540 QCOMPARE(spy.count(), 0); |
|
1541 |
|
1542 parent1.show(); |
|
1543 QApplication::setActiveWindow(&parent1); // needs this on twm (focus follows mouse) |
|
1544 QCOMPARE(spy.count(), 1); |
|
1545 QCOMPARE(spy.at(0).count(), 2); |
|
1546 old = qVariantValue<QWidget*>(spy.at(0).at(0)); |
|
1547 now = qVariantValue<QWidget*>(spy.at(0).at(1)); |
|
1548 QVERIFY(now == &le1); |
|
1549 QVERIFY(now == QApplication::focusWidget()); |
|
1550 QVERIFY(old == 0); |
|
1551 spy.clear(); |
|
1552 QCOMPARE(spy.count(), 0); |
|
1553 |
|
1554 pb1.setFocus(); |
|
1555 QCOMPARE(spy.count(), 1); |
|
1556 old = qVariantValue<QWidget*>(spy.at(0).at(0)); |
|
1557 now = qVariantValue<QWidget*>(spy.at(0).at(1)); |
|
1558 QVERIFY(now == &pb1); |
|
1559 QVERIFY(now == QApplication::focusWidget()); |
|
1560 QVERIFY(old == &le1); |
|
1561 spy.clear(); |
|
1562 |
|
1563 lb1.setFocus(); |
|
1564 QCOMPARE(spy.count(), 1); |
|
1565 old = qVariantValue<QWidget*>(spy.at(0).at(0)); |
|
1566 now = qVariantValue<QWidget*>(spy.at(0).at(1)); |
|
1567 QVERIFY(now == &lb1); |
|
1568 QVERIFY(now == QApplication::focusWidget()); |
|
1569 QVERIFY(old == &pb1); |
|
1570 spy.clear(); |
|
1571 |
|
1572 lb1.clearFocus(); |
|
1573 QCOMPARE(spy.count(), 1); |
|
1574 old = qVariantValue<QWidget*>(spy.at(0).at(0)); |
|
1575 now = qVariantValue<QWidget*>(spy.at(0).at(1)); |
|
1576 QVERIFY(now == 0); |
|
1577 QVERIFY(now == QApplication::focusWidget()); |
|
1578 QVERIFY(old == &lb1); |
|
1579 spy.clear(); |
|
1580 |
|
1581 QWidget parent2; |
|
1582 QHBoxLayout hbox2(&parent2); |
|
1583 QLabel lb2(&parent2); |
|
1584 QLineEdit le2(&parent2); |
|
1585 QPushButton pb2(&parent2); |
|
1586 hbox2.addWidget(&lb2); |
|
1587 hbox2.addWidget(&le2); |
|
1588 hbox2.addWidget(&pb2); |
|
1589 |
|
1590 parent2.show(); |
|
1591 QApplication::setActiveWindow(&parent2); // needs this on twm (focus follows mouse) |
|
1592 QVERIFY(spy.count() > 0); // one for deactivation, one for activation on Windows |
|
1593 old = qVariantValue<QWidget*>(spy.at(spy.count()-1).at(0)); |
|
1594 now = qVariantValue<QWidget*>(spy.at(spy.count()-1).at(1)); |
|
1595 QVERIFY(now == &le2); |
|
1596 QVERIFY(now == QApplication::focusWidget()); |
|
1597 QVERIFY(old == 0); |
|
1598 spy.clear(); |
|
1599 |
|
1600 QTestKeyEvent tab(QTest::Press, Qt::Key_Tab, 0, 0); |
|
1601 QTestKeyEvent backtab(QTest::Press, Qt::Key_Backtab, 0, 0); |
|
1602 QTestMouseEvent click(QTest::MouseClick, Qt::LeftButton, 0, QPoint(5, 5), 0); |
|
1603 |
|
1604 bool tabAllControls = true; |
|
1605 #ifdef Q_WS_MAC |
|
1606 // Mac has two modes, one where you tab to everything, one where you can |
|
1607 // only tab to input controls, here's what we get. Determine which ones we |
|
1608 // should get. |
|
1609 QSettings appleSettings(QLatin1String("apple.com")); |
|
1610 QVariant appleValue = appleSettings.value(QLatin1String("AppleKeyboardUIMode"), 0); |
|
1611 tabAllControls = (appleValue.toInt() & 0x2); |
|
1612 #endif |
|
1613 |
|
1614 tab.simulate(now); |
|
1615 if (!tabAllControls) { |
|
1616 QVERIFY(spy.count() == 0); |
|
1617 QVERIFY(now == QApplication::focusWidget()); |
|
1618 } else { |
|
1619 QVERIFY(spy.count() > 0); |
|
1620 old = qVariantValue<QWidget*>(spy.at(0).at(0)); |
|
1621 now = qVariantValue<QWidget*>(spy.at(0).at(1)); |
|
1622 QVERIFY(now == &pb2); |
|
1623 QVERIFY(now == QApplication::focusWidget()); |
|
1624 QVERIFY(old == &le2); |
|
1625 spy.clear(); |
|
1626 } |
|
1627 |
|
1628 if (!tabAllControls) { |
|
1629 QVERIFY(spy.count() == 0); |
|
1630 QVERIFY(now == QApplication::focusWidget()); |
|
1631 } else { |
|
1632 tab.simulate(now); |
|
1633 QVERIFY(spy.count() > 0); |
|
1634 old = qVariantValue<QWidget*>(spy.at(0).at(0)); |
|
1635 now = qVariantValue<QWidget*>(spy.at(0).at(1)); |
|
1636 QVERIFY(now == &le2); |
|
1637 QVERIFY(now == QApplication::focusWidget()); |
|
1638 QVERIFY(old == &pb2); |
|
1639 spy.clear(); |
|
1640 } |
|
1641 |
|
1642 if (!tabAllControls) { |
|
1643 QVERIFY(spy.count() == 0); |
|
1644 QVERIFY(now == QApplication::focusWidget()); |
|
1645 } else { |
|
1646 backtab.simulate(now); |
|
1647 QVERIFY(spy.count() > 0); |
|
1648 old = qVariantValue<QWidget*>(spy.at(0).at(0)); |
|
1649 now = qVariantValue<QWidget*>(spy.at(0).at(1)); |
|
1650 QVERIFY(now == &pb2); |
|
1651 QVERIFY(now == QApplication::focusWidget()); |
|
1652 QVERIFY(old == &le2); |
|
1653 spy.clear(); |
|
1654 } |
|
1655 |
|
1656 |
|
1657 if (!tabAllControls) { |
|
1658 QVERIFY(spy.count() == 0); |
|
1659 QVERIFY(now == QApplication::focusWidget()); |
|
1660 old = &pb2; |
|
1661 } else { |
|
1662 backtab.simulate(now); |
|
1663 QVERIFY(spy.count() > 0); |
|
1664 old = qVariantValue<QWidget*>(spy.at(0).at(0)); |
|
1665 now = qVariantValue<QWidget*>(spy.at(0).at(1)); |
|
1666 QVERIFY(now == &le2); |
|
1667 QVERIFY(now == QApplication::focusWidget()); |
|
1668 QVERIFY(old == &pb2); |
|
1669 spy.clear(); |
|
1670 } |
|
1671 |
|
1672 click.simulate(old); |
|
1673 if (!(pb2.focusPolicy() & Qt::ClickFocus)) { |
|
1674 QVERIFY(spy.count() == 0); |
|
1675 QVERIFY(now == QApplication::focusWidget()); |
|
1676 } else { |
|
1677 QVERIFY(spy.count() > 0); |
|
1678 old = qVariantValue<QWidget*>(spy.at(0).at(0)); |
|
1679 now = qVariantValue<QWidget*>(spy.at(0).at(1)); |
|
1680 QVERIFY(now == &pb2); |
|
1681 QVERIFY(now == QApplication::focusWidget()); |
|
1682 QVERIFY(old == &le2); |
|
1683 spy.clear(); |
|
1684 |
|
1685 click.simulate(old); |
|
1686 QVERIFY(spy.count() > 0); |
|
1687 old = qVariantValue<QWidget*>(spy.at(0).at(0)); |
|
1688 now = qVariantValue<QWidget*>(spy.at(0).at(1)); |
|
1689 QVERIFY(now == &le2); |
|
1690 QVERIFY(now == QApplication::focusWidget()); |
|
1691 QVERIFY(old == &pb2); |
|
1692 spy.clear(); |
|
1693 } |
|
1694 |
|
1695 parent1.activateWindow(); |
|
1696 QApplication::setActiveWindow(&parent1); // needs this on twm (focus follows mouse) |
|
1697 QVERIFY(spy.count() == 1 || spy.count() == 2); // one for deactivation, one for activation on Windows |
|
1698 |
|
1699 //on windows, the change of focus is made in 2 steps |
|
1700 //(the focusChanged SIGNAL is emitted twice) |
|
1701 if (spy.count()==1) |
|
1702 old = qVariantValue<QWidget*>(spy.at(spy.count()-1).at(0)); |
|
1703 else |
|
1704 old = qVariantValue<QWidget*>(spy.at(spy.count()-2).at(0)); |
|
1705 now = qVariantValue<QWidget*>(spy.at(spy.count()-1).at(1)); |
|
1706 QVERIFY(now == &le1); |
|
1707 QVERIFY(now == QApplication::focusWidget()); |
|
1708 QVERIFY(old == &le2); |
|
1709 spy.clear(); |
|
1710 } |
|
1711 |
|
1712 class LineEdit : public QLineEdit |
|
1713 { |
|
1714 public: |
|
1715 LineEdit(QWidget *parent = 0) : QLineEdit(parent) { } |
|
1716 |
|
1717 protected: |
|
1718 void focusOutEvent(QFocusEvent *e) { |
|
1719 QLineEdit::focusOutEvent(e); |
|
1720 if (objectName() == "le1") |
|
1721 setStyleSheet(""); |
|
1722 } |
|
1723 |
|
1724 void focusInEvent(QFocusEvent *e) { |
|
1725 QLineEdit::focusInEvent(e); |
|
1726 if (objectName() == "le2") |
|
1727 setStyleSheet(""); |
|
1728 } |
|
1729 }; |
|
1730 |
|
1731 void tst_QApplication::focusOut() |
|
1732 { |
|
1733 int argc = 1; |
|
1734 QApplication app(argc, &argv0, QApplication::GuiServer); |
|
1735 |
|
1736 // Tests the case where the style pointer changes when on focus in/out |
|
1737 // (the above is the case when the stylesheet changes) |
|
1738 QWidget w; |
|
1739 QLineEdit *le1 = new LineEdit(&w); |
|
1740 le1->setObjectName("le1"); |
|
1741 le1->setStyleSheet("background: #fee"); |
|
1742 le1->setFocus(); |
|
1743 |
|
1744 QLineEdit *le2 = new LineEdit(&w); |
|
1745 le2->setObjectName("le2"); |
|
1746 le2->setStyleSheet("background: #fee"); |
|
1747 le2->move(100, 100); |
|
1748 w.show(); |
|
1749 |
|
1750 QTest::qWait(2000); |
|
1751 le2->setFocus(); |
|
1752 QTest::qWait(2000); |
|
1753 } |
|
1754 |
|
1755 void tst_QApplication::execAfterExit() |
|
1756 { |
|
1757 int argc = 1; |
|
1758 QApplication app(argc, &argv0, QApplication::GuiServer); |
|
1759 QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection); |
|
1760 // this should be ignored, as exec() will reset the exitCode |
|
1761 QApplication::exit(1); |
|
1762 int exitCode = app.exec(); |
|
1763 QCOMPARE(exitCode, 0); |
|
1764 |
|
1765 // the quitNow flag should have been reset, so we can spin an |
|
1766 // eventloop after QApplication::exec() returns |
|
1767 QEventLoop eventLoop; |
|
1768 QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection); |
|
1769 exitCode = eventLoop.exec(); |
|
1770 QCOMPARE(exitCode, 0); |
|
1771 } |
|
1772 |
|
1773 void tst_QApplication::wheelScrollLines() |
|
1774 { |
|
1775 int argc = 1; |
|
1776 QApplication app(argc, &argv0, QApplication::GuiServer); |
|
1777 // If wheelScrollLines returns 0, the mose wheel will be disabled. |
|
1778 QVERIFY(app.wheelScrollLines() > 0); |
|
1779 } |
|
1780 |
|
1781 void tst_QApplication::style() |
|
1782 { |
|
1783 int argc = 1; |
|
1784 |
|
1785 { |
|
1786 QApplication app(argc, &argv0, QApplication::GuiServer); |
|
1787 QPointer<QStyle> style = app.style(); |
|
1788 app.setStyle(new QWindowsStyle); |
|
1789 QVERIFY(style.isNull()); |
|
1790 } |
|
1791 |
|
1792 QApplication app(argc, &argv0, QApplication::GuiServer); |
|
1793 |
|
1794 // qApp style can never be 0 |
|
1795 QVERIFY(QApplication::style() != 0); |
|
1796 } |
|
1797 |
|
1798 void tst_QApplication::allWidgets() |
|
1799 { |
|
1800 int argc = 1; |
|
1801 QApplication app(argc, &argv0, QApplication::GuiServer); |
|
1802 QWidget *w = new QWidget; |
|
1803 QVERIFY(app.allWidgets().contains(w)); // uncreate widget test |
|
1804 QVERIFY(app.allWidgets().contains(w)); // created widget test |
|
1805 delete w; |
|
1806 w = 0; |
|
1807 QVERIFY(!app.allWidgets().contains(w)); // removal test |
|
1808 } |
|
1809 |
|
1810 void tst_QApplication::topLevelWidgets() |
|
1811 { |
|
1812 int argc = 1; |
|
1813 QApplication app(argc, &argv0, QApplication::GuiServer); |
|
1814 QWidget *w = new QWidget; |
|
1815 w->show(); |
|
1816 #ifndef QT_NO_CLIPBOARD |
|
1817 QClipboard *clipboard = QApplication::clipboard(); |
|
1818 QString originalText = clipboard->text(); |
|
1819 clipboard->setText(QString("newText")); |
|
1820 #endif |
|
1821 app.processEvents(); |
|
1822 QVERIFY(QApplication::topLevelWidgets().contains(w)); |
|
1823 QCOMPARE(QApplication::topLevelWidgets().count(), 1); |
|
1824 delete w; |
|
1825 w = 0; |
|
1826 app.processEvents(); |
|
1827 QCOMPARE(QApplication::topLevelWidgets().count(), 0); |
|
1828 } |
|
1829 |
|
1830 |
|
1831 |
|
1832 void tst_QApplication::setAttribute() |
|
1833 { |
|
1834 int argc = 1; |
|
1835 QApplication app(argc, &argv0, QApplication::GuiServer); |
|
1836 QVERIFY(!QApplication::testAttribute(Qt::AA_ImmediateWidgetCreation)); |
|
1837 QWidget *w = new QWidget; |
|
1838 QVERIFY(!w->testAttribute(Qt::WA_WState_Created)); |
|
1839 delete w; |
|
1840 |
|
1841 QApplication::setAttribute(Qt::AA_ImmediateWidgetCreation); |
|
1842 QVERIFY(QApplication::testAttribute(Qt::AA_ImmediateWidgetCreation)); |
|
1843 w = new QWidget; |
|
1844 QVERIFY(w->testAttribute(Qt::WA_WState_Created)); |
|
1845 QWidget *w2 = new QWidget(w); |
|
1846 w2->setParent(0); |
|
1847 QVERIFY(w2->testAttribute(Qt::WA_WState_Created)); |
|
1848 delete w; |
|
1849 delete w2; |
|
1850 |
|
1851 QApplication::setAttribute(Qt::AA_ImmediateWidgetCreation, false); |
|
1852 QVERIFY(!QApplication::testAttribute(Qt::AA_ImmediateWidgetCreation)); |
|
1853 w = new QWidget; |
|
1854 QVERIFY(!w->testAttribute(Qt::WA_WState_Created)); |
|
1855 delete w; |
|
1856 } |
|
1857 |
|
1858 void tst_QApplication::windowsCommandLine_data() |
|
1859 { |
|
1860 #if defined(Q_OS_WIN) |
|
1861 QTest::addColumn<QString>("args"); |
|
1862 QTest::addColumn<QString>("expected"); |
|
1863 |
|
1864 QTest::newRow("hello world") |
|
1865 << QString("Hello \"World\"") |
|
1866 << QString("Hello \"World\""); |
|
1867 QTest::newRow("sql") |
|
1868 << QString("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'PNR' AND TABLE_TYPE = 'VIEW' ORDER BY TABLE_NAME") |
|
1869 << QString("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'PNR' AND TABLE_TYPE = 'VIEW' ORDER BY TABLE_NAME"); |
|
1870 #endif |
|
1871 } |
|
1872 |
|
1873 void tst_QApplication::windowsCommandLine() |
|
1874 { |
|
1875 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) |
|
1876 QFETCH(QString, args); |
|
1877 QFETCH(QString, expected); |
|
1878 |
|
1879 QProcess testProcess; |
|
1880 #if defined(QT_DEBUG) |
|
1881 testProcess.start("wincmdline/debug/wincmdline", QStringList(args)); |
|
1882 #else |
|
1883 testProcess.start("wincmdline/release/wincmdline", QStringList(args)); |
|
1884 #endif |
|
1885 QVERIFY(testProcess.waitForFinished(10000)); |
|
1886 QByteArray error = testProcess.readAllStandardError(); |
|
1887 QString procError(error); |
|
1888 QCOMPARE(procError, expected); |
|
1889 #endif |
|
1890 } |
|
1891 |
|
1892 class TouchEventPropagationTestWidget : public QWidget |
|
1893 { |
|
1894 Q_OBJECT |
|
1895 |
|
1896 public: |
|
1897 bool seenTouchEvent, acceptTouchEvent, seenMouseEvent, acceptMouseEvent; |
|
1898 |
|
1899 TouchEventPropagationTestWidget(QWidget *parent = 0) |
|
1900 : QWidget(parent), seenTouchEvent(false), acceptTouchEvent(false), seenMouseEvent(false), acceptMouseEvent(false) |
|
1901 { } |
|
1902 |
|
1903 void reset() |
|
1904 { |
|
1905 seenTouchEvent = acceptTouchEvent = seenMouseEvent = acceptMouseEvent = false; |
|
1906 } |
|
1907 |
|
1908 bool event(QEvent *event) |
|
1909 { |
|
1910 switch (event->type()) { |
|
1911 case QEvent::MouseButtonPress: |
|
1912 case QEvent::MouseMove: |
|
1913 case QEvent::MouseButtonRelease: |
|
1914 // qDebug() << objectName() << "seenMouseEvent = true"; |
|
1915 seenMouseEvent = true; |
|
1916 event->setAccepted(acceptMouseEvent); |
|
1917 break; |
|
1918 case QEvent::TouchBegin: |
|
1919 case QEvent::TouchUpdate: |
|
1920 case QEvent::TouchEnd: |
|
1921 // qDebug() << objectName() << "seenTouchEvent = true"; |
|
1922 seenTouchEvent = true; |
|
1923 event->setAccepted(acceptTouchEvent); |
|
1924 break; |
|
1925 default: |
|
1926 return QWidget::event(event); |
|
1927 } |
|
1928 return true; |
|
1929 } |
|
1930 }; |
|
1931 |
|
1932 void tst_QApplication::touchEventPropagation() |
|
1933 { |
|
1934 int argc = 1; |
|
1935 QApplication app(argc, &argv0, QApplication::GuiServer); |
|
1936 |
|
1937 QList<QTouchEvent::TouchPoint> pressedTouchPoints; |
|
1938 QTouchEvent::TouchPoint press(0); |
|
1939 press.setState(Qt::TouchPointPressed); |
|
1940 pressedTouchPoints << press; |
|
1941 |
|
1942 QList<QTouchEvent::TouchPoint> releasedTouchPoints; |
|
1943 QTouchEvent::TouchPoint release(0); |
|
1944 release.setState(Qt::TouchPointReleased); |
|
1945 releasedTouchPoints << release; |
|
1946 |
|
1947 { |
|
1948 // touch event behavior on a window |
|
1949 TouchEventPropagationTestWidget window; |
|
1950 window.setObjectName("1. window"); |
|
1951 |
|
1952 qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, pressedTouchPoints); |
|
1953 qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, releasedTouchPoints); |
|
1954 QVERIFY(!window.seenTouchEvent); |
|
1955 QVERIFY(!window.seenMouseEvent); |
|
1956 |
|
1957 window.reset(); |
|
1958 window.setAttribute(Qt::WA_AcceptTouchEvents); |
|
1959 qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, pressedTouchPoints); |
|
1960 qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, releasedTouchPoints); |
|
1961 QVERIFY(window.seenTouchEvent); |
|
1962 QVERIFY(!window.seenMouseEvent); |
|
1963 |
|
1964 window.reset(); |
|
1965 window.acceptTouchEvent = true; |
|
1966 qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, pressedTouchPoints); |
|
1967 qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, releasedTouchPoints); |
|
1968 QVERIFY(window.seenTouchEvent); |
|
1969 QVERIFY(!window.seenMouseEvent); |
|
1970 } |
|
1971 |
|
1972 { |
|
1973 // touch event behavior on a window with a child widget |
|
1974 TouchEventPropagationTestWidget window; |
|
1975 window.setObjectName("2. window"); |
|
1976 TouchEventPropagationTestWidget widget(&window); |
|
1977 widget.setObjectName("2. widget"); |
|
1978 |
|
1979 qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, pressedTouchPoints); |
|
1980 qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, releasedTouchPoints); |
|
1981 QVERIFY(!widget.seenTouchEvent); |
|
1982 QVERIFY(!widget.seenMouseEvent); |
|
1983 QVERIFY(!window.seenTouchEvent); |
|
1984 QVERIFY(!window.seenMouseEvent); |
|
1985 |
|
1986 window.reset(); |
|
1987 widget.reset(); |
|
1988 widget.setAttribute(Qt::WA_AcceptTouchEvents); |
|
1989 qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, pressedTouchPoints); |
|
1990 qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, releasedTouchPoints); |
|
1991 QVERIFY(widget.seenTouchEvent); |
|
1992 QVERIFY(!widget.seenMouseEvent); |
|
1993 QVERIFY(!window.seenTouchEvent); |
|
1994 QVERIFY(!window.seenMouseEvent); |
|
1995 |
|
1996 window.reset(); |
|
1997 widget.reset(); |
|
1998 widget.acceptMouseEvent = true; |
|
1999 qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, pressedTouchPoints); |
|
2000 qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, releasedTouchPoints); |
|
2001 QVERIFY(widget.seenTouchEvent); |
|
2002 QVERIFY(!widget.seenMouseEvent); |
|
2003 QVERIFY(!window.seenTouchEvent); |
|
2004 QVERIFY(!window.seenMouseEvent); |
|
2005 |
|
2006 window.reset(); |
|
2007 widget.reset(); |
|
2008 widget.acceptTouchEvent = true; |
|
2009 qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, pressedTouchPoints); |
|
2010 qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, releasedTouchPoints); |
|
2011 QVERIFY(widget.seenTouchEvent); |
|
2012 QVERIFY(!widget.seenMouseEvent); |
|
2013 QVERIFY(!window.seenTouchEvent); |
|
2014 QVERIFY(!window.seenMouseEvent); |
|
2015 |
|
2016 window.reset(); |
|
2017 widget.reset(); |
|
2018 widget.setAttribute(Qt::WA_AcceptTouchEvents, false); |
|
2019 window.setAttribute(Qt::WA_AcceptTouchEvents); |
|
2020 qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, pressedTouchPoints); |
|
2021 qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, releasedTouchPoints); |
|
2022 QVERIFY(!widget.seenTouchEvent); |
|
2023 QVERIFY(!widget.seenMouseEvent); |
|
2024 QVERIFY(window.seenTouchEvent); |
|
2025 QVERIFY(!window.seenMouseEvent); |
|
2026 |
|
2027 window.reset(); |
|
2028 widget.reset(); |
|
2029 window.acceptTouchEvent = true; |
|
2030 qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, pressedTouchPoints); |
|
2031 qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, releasedTouchPoints); |
|
2032 QVERIFY(!widget.seenTouchEvent); |
|
2033 QVERIFY(!widget.seenMouseEvent); |
|
2034 QVERIFY(window.seenTouchEvent); |
|
2035 QVERIFY(!window.seenMouseEvent); |
|
2036 |
|
2037 window.reset(); |
|
2038 widget.reset(); |
|
2039 widget.acceptMouseEvent = true; // doesn't matter, touch events are propagated first |
|
2040 window.acceptTouchEvent = true; |
|
2041 qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, pressedTouchPoints); |
|
2042 qt_translateRawTouchEvent(&window, QTouchEvent::TouchScreen, releasedTouchPoints); |
|
2043 QVERIFY(!widget.seenTouchEvent); |
|
2044 QVERIFY(!widget.seenMouseEvent); |
|
2045 QVERIFY(window.seenTouchEvent); |
|
2046 QVERIFY(!window.seenMouseEvent); |
|
2047 } |
|
2048 } |
|
2049 |
|
2050 void tst_QApplication::symbianNoApplicationPanes() |
|
2051 { |
|
2052 #ifndef Q_OS_SYMBIAN |
|
2053 QSKIP("This is a Symbian only test", SkipAll); |
|
2054 #else |
|
2055 QApplication::setAttribute(Qt::AA_S60DontConstructApplicationPanes); |
|
2056 |
|
2057 // Run in a block so that QApplication is destroyed before resetting the attribute. |
|
2058 { |
|
2059 // Actually I wasn't able to get the forced orientation change to work properly, |
|
2060 // but I'll leave the code here for the future in case we manage to test that |
|
2061 // later. If someone knows how to force an orientation switch in an autotest, do |
|
2062 // feel free to fix this testcase. |
|
2063 int argc = 0; |
|
2064 QApplication app(argc, 0); |
|
2065 QWidget *w; |
|
2066 |
|
2067 w = new QWidget; |
|
2068 w->show(); |
|
2069 QT_TRAP_THROWING(static_cast<CAknAppUi *>(CCoeEnv::Static()->AppUi()) |
|
2070 ->SetOrientationL(CAknAppUi::EAppUiOrientationLandscape)); |
|
2071 app.processEvents(); |
|
2072 delete w; |
|
2073 |
|
2074 w = new QWidget; |
|
2075 w->show(); |
|
2076 QT_TRAP_THROWING(static_cast<CAknAppUi *>(CCoeEnv::Static()->AppUi()) |
|
2077 ->SetOrientationL(CAknAppUi::EAppUiOrientationPortrait)); |
|
2078 app.processEvents(); |
|
2079 delete w; |
|
2080 |
|
2081 w = new QWidget; |
|
2082 w->showMaximized(); |
|
2083 QT_TRAP_THROWING(static_cast<CAknAppUi *>(CCoeEnv::Static()->AppUi()) |
|
2084 ->SetOrientationL(CAknAppUi::EAppUiOrientationLandscape)); |
|
2085 app.processEvents(); |
|
2086 delete w; |
|
2087 |
|
2088 w = new QWidget; |
|
2089 w->showMaximized(); |
|
2090 QT_TRAP_THROWING(static_cast<CAknAppUi *>(CCoeEnv::Static()->AppUi()) |
|
2091 ->SetOrientationL(CAknAppUi::EAppUiOrientationPortrait)); |
|
2092 app.processEvents(); |
|
2093 delete w; |
|
2094 |
|
2095 w = new QWidget; |
|
2096 w->showFullScreen(); |
|
2097 QT_TRAP_THROWING(static_cast<CAknAppUi *>(CCoeEnv::Static()->AppUi()) |
|
2098 ->SetOrientationL(CAknAppUi::EAppUiOrientationLandscape)); |
|
2099 app.processEvents(); |
|
2100 delete w; |
|
2101 |
|
2102 w = new QWidget; |
|
2103 w->showFullScreen(); |
|
2104 QT_TRAP_THROWING(static_cast<CAknAppUi *>(CCoeEnv::Static()->AppUi()) |
|
2105 ->SetOrientationL(CAknAppUi::EAppUiOrientationPortrait)); |
|
2106 app.processEvents(); |
|
2107 delete w; |
|
2108 |
|
2109 // These will have no effect, since there is no status pane, but they shouldn't |
|
2110 // crash either. |
|
2111 w = new QWidget; |
|
2112 w->show(); |
|
2113 w->setWindowTitle("Testing title"); |
|
2114 app.processEvents(); |
|
2115 delete w; |
|
2116 |
|
2117 w = new QWidget; |
|
2118 w->show(); |
|
2119 w->setWindowIcon(QIcon(QPixmap("heart.svg"))); |
|
2120 app.processEvents(); |
|
2121 delete w; |
|
2122 |
|
2123 QDesktopWidget desktop; |
|
2124 QCOMPARE(desktop.availableGeometry(), desktop.screenGeometry()); |
|
2125 } |
|
2126 |
|
2127 QApplication::setAttribute(Qt::AA_S60DontConstructApplicationPanes, false); |
|
2128 |
|
2129 // No other error condition. Program will crash if unsuccessful. |
|
2130 #endif |
|
2131 } |
|
2132 |
|
2133 #ifdef Q_OS_SYMBIAN |
|
2134 class CBaseDummy : public CBase |
|
2135 { |
|
2136 public: |
|
2137 CBaseDummy(int *numDestroyed) : numDestroyed(numDestroyed) |
|
2138 { |
|
2139 } |
|
2140 ~CBaseDummy() |
|
2141 { |
|
2142 (*numDestroyed)++; |
|
2143 } |
|
2144 |
|
2145 private: |
|
2146 int *numDestroyed; |
|
2147 }; |
|
2148 |
|
2149 static void fakeMain(int *numDestroyed) |
|
2150 { |
|
2151 // Push a few objects, just so that the cleanup stack has something to clean up. |
|
2152 CleanupStack::PushL(new (ELeave) CBaseDummy(numDestroyed)); |
|
2153 int argc = 0; |
|
2154 QApplication app(argc, 0); |
|
2155 CleanupStack::PushL(new (ELeave) CBaseDummy(numDestroyed)); |
|
2156 |
|
2157 User::Leave(KErrGeneral); // Fake error |
|
2158 } |
|
2159 #endif |
|
2160 |
|
2161 void tst_QApplication::symbianNeedForTraps() |
|
2162 { |
|
2163 #ifndef Q_OS_SYMBIAN |
|
2164 QSKIP("This is a Symbian-only test", SkipAll); |
|
2165 #else |
|
2166 int argc = 0; |
|
2167 QApplication app(argc, 0); |
|
2168 int numDestroyed = 0; |
|
2169 |
|
2170 // This next part should not require a trap. If it does, the test will crash. |
|
2171 CleanupStack::PushL(new (ELeave) CBaseDummy(&numDestroyed)); |
|
2172 CleanupStack::PopAndDestroy(); |
|
2173 |
|
2174 QCOMPARE(numDestroyed, 1); |
|
2175 |
|
2176 // No other failure condition. The program will crash if it does not pass. |
|
2177 #endif |
|
2178 } |
|
2179 |
|
2180 void tst_QApplication::symbianLeaveThroughMain() |
|
2181 { |
|
2182 #ifndef Q_OS_SYMBIAN |
|
2183 QSKIP("This is a Symbian-only test", SkipAll); |
|
2184 #else |
|
2185 int numDestroyed = 0; |
|
2186 TInt err; |
|
2187 TRAP(err, fakeMain(&numDestroyed)); |
|
2188 |
|
2189 QCOMPARE(numDestroyed, 2); |
|
2190 #endif |
|
2191 } |
|
2192 */ |
|
2193 |
|
2194 //QTEST_APPLESS_MAIN(tst_QApplication) |
|
2195 int main(int argc, char *argv[]) |
|
2196 { |
|
2197 tst_QApplication tc; |
|
2198 argv0 = argv[0]; |
|
2199 return QTest::qExec(&tc, argc, argv); |
|
2200 } |
|
2201 |
|
2202 #include "smoketest_qapplication.moc" |
|