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