1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the test suite of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
43 //#define QT_TST_QAPP_DEBUG
46 #include <QtTest/QtTest>
48 #include <QtCore/QAbstractEventDispatcher>
49 #include <QtCore/QFileInfo>
50 #include <QtCore/QDir>
51 #include <QtCore/QProcess>
52 #include <QtCore/private/qeventloop_p.h>
54 #include <QtGui/QFontDatabase>
55 #include <QtGui/QClipboard>
57 #include <QtWidgets/QApplication>
58 #include <QtWidgets/QMessageBox>
59 #include <QtWidgets/QStyleFactory>
60 #include <QtWidgets/QHBoxLayout>
61 #include <QtWidgets/QPushButton>
62 #include <QtWidgets/QLineEdit>
63 #include <QtWidgets/QLabel>
64 #include <QtWidgets/QMainWindow>
65 #include <QtWidgets/private/qapplication_p.h>
66 #include <QtWidgets/private/qstylesheetstyle_p.h>
73 extern bool Q_GUI_EXPORT qt_tab_all_widgets; // from qapplication.cpp
76 class tst_QApplication : public QObject
82 virtual ~tst_QApplication();
89 void sendEventsOnProcessEvents(); // this must be the first test
105 void lastWindowClosed();
106 void quitOnLastWindowClosed();
107 void closeAllWindows();
108 void testDeleteLater();
109 void testDeleteLaterProcessEvents();
112 void libraryPaths_qt_plugin_path();
113 void libraryPaths_qt_plugin_path_2();
115 void sendPostedEvents();
118 void desktopSettingsAware();
120 void setActiveWindow();
125 void execAfterExit();
127 void wheelScrollLines();
134 void topLevelWidgets();
138 void windowsCommandLine_data();
139 void windowsCommandLine();
141 void touchEventPropagation();
146 void globalStaticObjectDestruction(); // run this last
148 void abortQuitOnShow();
151 class EventSpy : public QObject
156 QList<int> recordedEvents;
157 bool eventFilter(QObject *, QEvent *event)
159 recordedEvents.append(event->type());
164 void tst_QApplication::initTestCase()
166 // chdir to our testdata path and execute helper apps relative to that.
167 const QString testdataDir = QFileInfo(QFINDTESTDATA("desktopsettingsaware")).absolutePath();
168 QVERIFY2(QDir::setCurrent(testdataDir), qPrintable("Could not chdir to " + testdataDir));
171 void tst_QApplication::sendEventsOnProcessEvents()
174 QApplication app(argc, 0, QApplication::GuiServer);
177 app.installEventFilter(&spy);
179 QCoreApplication::postEvent(&app, new QEvent(QEvent::Type(QEvent::User + 1)));
180 QCoreApplication::processEvents();
181 QVERIFY(spy.recordedEvents.contains(QEvent::User + 1));
185 class CloseEventTestWindow : public QWidget
188 CloseEventTestWindow(QWidget *parent = 0)
193 void closeEvent(QCloseEvent *event)
205 tst_QApplication::tst_QApplication()
208 // Clean up environment previously to launching test
209 qputenv("QT_PLUGIN_PATH", QByteArray());
213 tst_QApplication::~tst_QApplication()
218 void tst_QApplication::init()
220 // TODO: Add initialization code here.
221 // This will be executed immediately before each test is run.
224 void tst_QApplication::cleanup()
226 // TODO: Add cleanup code here.
227 // This will be executed immediately after each test is run.
230 void tst_QApplication::staticSetup()
234 QStyle *style = QStyleFactory::create(QLatin1String("Windows"));
236 QApplication::setStyle(style);
239 QApplication::setPalette(pal);
242 QApplication::setFont(font);*/
245 QApplication app(argc, 0, QApplication::GuiServer);
249 // QApp subclass that exits the event loop after 150ms
250 class TestApplication : public QApplication
253 TestApplication( int &argc, char **argv )
254 : QApplication( argc, argv, QApplication::GuiServer )
259 void timerEvent( QTimerEvent * )
265 void tst_QApplication::alert()
268 QApplication app(argc, 0, QApplication::GuiServer);
273 app.alert(&widget, 100);
277 qt_x11_wait_for_window_manager(&widget);
278 qt_x11_wait_for_window_manager(&widget2);
281 app.alert(&widget, -1);
282 app.alert(&widget, 250);
283 widget2.activateWindow();
284 QApplication::setActiveWindow(&widget2);
285 app.alert(&widget, 0);
286 widget.activateWindow();
287 QApplication::setActiveWindow(&widget);
288 app.alert(&widget, 200);
292 void tst_QApplication::multiple_data()
294 QTest::addColumn<QStringList>("features");
296 // return a list of things to try
297 QTest::newRow( "data0" ) << QStringList( "" );
298 QTest::newRow( "data1" ) << QStringList( "QFont" );
299 QTest::newRow( "data2" ) << QStringList( "QPixmap" );
300 QTest::newRow( "data3" ) << QStringList( "QWidget" );
303 void tst_QApplication::multiple()
305 QFETCH(QStringList,features);
310 TestApplication app( argc, 0 );
312 if ( features.contains( "QFont" ) ) {
313 // create font and force loading
314 QFont font( "Arial", 12 );
315 QFontInfo finfo( font );
318 if ( features.contains( "QPixmap" ) ) {
319 QPixmap pix( 100, 100 );
320 pix.fill( Qt::black );
322 if ( features.contains( "QWidget" ) ) {
326 QVERIFY(!app.exec());
330 void tst_QApplication::nonGui()
333 // ### This is only to allow us to generate a test report for now.
334 QSKIP("This test shuts down the window manager on HP-UX.");
338 QApplication app(argc, 0, false);
339 QCOMPARE(qApp, &app);
342 void tst_QApplication::setFont_data()
344 QTest::addColumn<QString>("family");
345 QTest::addColumn<int>("pointsize");
346 QTest::addColumn<bool>("beforeAppConstructor");
349 QApplication app(argc, 0, QApplication::GuiServer); // Needed for QFontDatabase
353 QStringList families = fdb.families();
354 for (QStringList::const_iterator itr = families.begin();
355 itr != families.end();
358 QString family = *itr;
359 QStringList styles = fdb.styles(family);
360 if (styles.size() > 0) {
361 QString style = styles.first();
362 QList<int> sizes = fdb.pointSizes(family, style);
364 sizes = fdb.standardSizes();
365 if (sizes.size() > 0) {
366 QTest::newRow(QString("data%1a").arg(cnt).toLatin1().constData())
370 QTest::newRow(QString("data%1b").arg(cnt).toLatin1().constData())
380 QTest::newRow("nonexistingfont after") << "nosuchfont_probably_quiteunlikely"
382 QTest::newRow("nonexistingfont before") << "nosuchfont_probably_quiteunlikely"
385 QTest::newRow("largescaleable after") << "smoothtimes" << 100 << false;
386 QTest::newRow("largescaleable before") << "smoothtimes" << 100 << true;
388 QTest::newRow("largeunscaleale after") << "helvetica" << 100 << false;
389 QTest::newRow("largeunscaleale before") << "helvetica" << 100 << true;
392 void tst_QApplication::setFont()
394 QFETCH( QString, family );
395 QFETCH( int, pointsize );
396 QFETCH( bool, beforeAppConstructor );
398 QFont font( family, pointsize );
399 if (beforeAppConstructor) {
400 QApplication::setFont( font );
401 QCOMPARE(QApplication::font(), font);
405 QApplication app( argc, 0, QApplication::GuiServer );
406 if (!beforeAppConstructor)
407 QApplication::setFont( font );
409 QCOMPARE( app.font(), font );
412 void tst_QApplication::args_data()
414 QTest::addColumn<int>("argc_in");
415 QTest::addColumn<QString>("args_in");
416 QTest::addColumn<int>("argc_out");
417 QTest::addColumn<QString>("args_out");
419 QTest::newRow( "App name" ) << 1 << "/usr/bin/appname" << 1 << "/usr/bin/appname";
420 QTest::newRow( "No arguments" ) << 0 << QString() << 0 << QString();
421 QTest::newRow( "App name, style" ) << 3 << "/usr/bin/appname -style motif" << 1 << "/usr/bin/appname";
422 QTest::newRow( "App name, style, arbitrary, reverse" ) << 5 << "/usr/bin/appname -style motif -arbitrary -reverse"
423 << 2 << "/usr/bin/appname -arbitrary";
426 void tst_QApplication::task109149()
429 QApplication app(argc, 0, QApplication::GuiServer);
430 QApplication::setFont(QFont("helvetica", 100));
433 w.setWindowTitle("hello");
439 static char ** QString2cstrings( const QString &args )
441 static QList<QByteArray> cache;
445 QStringList list = args.split(' ');;
446 argarray = new char*[list.count()+1];
448 for (i = 0; i < (int)list.count(); ++i ) {
449 QByteArray l1 = list[i].toLatin1();
450 argarray[i] = l1.data();
458 static QString cstrings2QString( char **args )
474 void tst_QApplication::args()
476 QFETCH( int, argc_in );
477 QFETCH( QString, args_in );
478 QFETCH( int, argc_out );
479 QFETCH( QString, args_out );
481 char **argv = QString2cstrings( args_in );
483 QApplication app( argc_in, argv, QApplication::GuiServer );
484 QString argv_out = cstrings2QString(argv);
486 QCOMPARE( argc_in, argc_out );
487 QCOMPARE( argv_out, args_out );
492 class CloseWidget : public QWidget
502 void timerEvent(QTimerEvent *)
509 void tst_QApplication::lastWindowClosed()
512 QApplication app(argc, 0, QApplication::GuiServer);
514 QSignalSpy spy(&app, SIGNAL(lastWindowClosed()));
516 QPointer<QDialog> dialog = new QDialog;
517 QVERIFY(dialog->testAttribute(Qt::WA_QuitOnClose));
518 QTimer::singleShot(1000, dialog, SLOT(accept()));
521 QCOMPARE(spy.count(), 0);
523 QPointer<CloseWidget>widget = new CloseWidget;
524 QVERIFY(widget->testAttribute(Qt::WA_QuitOnClose));
526 QObject::connect(&app, SIGNAL(lastWindowClosed()), widget, SLOT(deleteLater()));
529 QCOMPARE(spy.count(), 1);
534 // show 3 windows, close them, should only get lastWindowClosed once
542 QTimer::singleShot(1000, &app, SLOT(closeAllWindows()));
544 QCOMPARE(spy.count(), 1);
547 class QuitOnLastWindowClosedDialog : public QDialog
551 QPushButton *okButton;
553 QuitOnLastWindowClosedDialog()
555 QHBoxLayout *hbox = new QHBoxLayout(this);
556 okButton = new QPushButton("&ok", this);
558 hbox->addWidget(okButton);
559 connect(okButton, SIGNAL(clicked()), this, SLOT(accept()));
560 connect(okButton, SIGNAL(clicked()), this, SLOT(ok_clicked()));
569 connect(&timer, SIGNAL(timeout()), &other, SLOT(accept()));
570 QSignalSpy spy(&timer, SIGNAL(timeout()));
571 QSignalSpy appSpy(qApp, SIGNAL(lastWindowClosed()));
576 // verify that the eventloop ran and let the timer fire
577 QCOMPARE(spy.count(), 1);
578 QCOMPARE(appSpy.count(), 1);
582 class QuitOnLastWindowClosedWindow : public QWidget
587 QuitOnLastWindowClosedWindow()
591 void execDialogThenShow()
595 connect(&timer1, SIGNAL(timeout()), &dialog, SLOT(accept()));
596 QSignalSpy spy1(&timer1, SIGNAL(timeout()));
597 timer1.setSingleShot(true);
600 QCOMPARE(spy1.count(), 1);
606 void tst_QApplication::quitOnLastWindowClosed()
610 QApplication app(argc, 0, QApplication::GuiServer);
612 QuitOnLastWindowClosedDialog d;
614 QTimer::singleShot(1000, d.okButton, SLOT(animateClick()));
616 QSignalSpy appSpy(&app, SIGNAL(lastWindowClosed()));
619 // lastWindowClosed() signal should only be sent after the last dialog is closed
620 QCOMPARE(appSpy.count(), 2);
624 QApplication app(argc, 0, QApplication::GuiServer);
625 QSignalSpy appSpy(&app, SIGNAL(lastWindowClosed()));
629 connect(&timer1, SIGNAL(timeout()), &dialog, SLOT(accept()));
630 QSignalSpy spy1(&timer1, SIGNAL(timeout()));
631 timer1.setSingleShot(true);
634 QCOMPARE(spy1.count(), 1);
635 QCOMPARE(appSpy.count(), 0);
638 connect(&timer2, SIGNAL(timeout()), &app, SLOT(quit()));
639 QSignalSpy spy2(&timer2, SIGNAL(timeout()));
640 timer2.setSingleShot(true);
642 int returnValue = app.exec();
643 QCOMPARE(returnValue, 0);
644 QCOMPARE(spy2.count(), 1);
645 QCOMPARE(appSpy.count(), 0);
649 QApplication app(argc, 0, QApplication::GuiServer);
651 timer.setInterval(100);
653 QSignalSpy spy(&app, SIGNAL(aboutToQuit()));
654 QSignalSpy spy2(&timer, SIGNAL(timeout()));
656 QPointer<QMainWindow> mainWindow = new QMainWindow;
657 QPointer<QDialog> dialog = new QDialog(mainWindow);
659 QVERIFY(app.quitOnLastWindowClosed());
660 QVERIFY(mainWindow->testAttribute(Qt::WA_QuitOnClose));
661 QVERIFY(dialog->testAttribute(Qt::WA_QuitOnClose));
667 QTimer::singleShot(1000, mainWindow, SLOT(close())); // This should quit the application
668 QTimer::singleShot(2000, &app, SLOT(quit())); // This makes sure we quit even if it didn't
672 QCOMPARE(spy.count(), 1);
673 QVERIFY(spy2.count() < 15); // Should be around 10 if closing caused the quit
677 QApplication app(argc, 0, QApplication::GuiServer);
679 timer.setInterval(100);
681 QSignalSpy spy(&app, SIGNAL(aboutToQuit()));
682 QSignalSpy spy2(&timer, SIGNAL(timeout()));
684 QPointer<CloseEventTestWindow> mainWindow = new CloseEventTestWindow;
686 QVERIFY(app.quitOnLastWindowClosed());
687 QVERIFY(mainWindow->testAttribute(Qt::WA_QuitOnClose));
692 QTimer::singleShot(1000, mainWindow, SLOT(close())); // This should quit the application
693 QTimer::singleShot(2000, &app, SLOT(quit())); // This makes sure we quit even if it didn't
697 QCOMPARE(spy.count(), 1);
698 QVERIFY(spy2.count() > 15); // Should be around 20 if closing did not caused the quit
702 QApplication app(argc, 0, QApplication::GuiServer);
703 QSignalSpy appSpy(&app, SIGNAL(lastWindowClosed()));
705 // exec a dialog for 1 second, then show the window
706 QuitOnLastWindowClosedWindow window;
707 QTimer::singleShot(0, &window, SLOT(execDialogThenShow()));
710 QSignalSpy timerSpy(&timer, SIGNAL(timeout()));
711 connect(&timer, SIGNAL(timeout()), &window, SLOT(close()));
712 timer.setSingleShot(true);
714 int returnValue = app.exec();
715 QCOMPARE(returnValue, 0);
716 // failure here means the timer above didn't fire, and the
717 // quit was caused the the dialog being closed (not the window)
718 QCOMPARE(timerSpy.count(), 1);
719 QCOMPARE(appSpy.count(), 2);
723 QApplication app(argc, 0, QApplication::GuiServer);
724 QVERIFY(app.quitOnLastWindowClosed());
727 timer.setInterval(100);
728 QSignalSpy timerSpy(&timer, SIGNAL(timeout()));
737 QTimer::singleShot(1000, &wid, SLOT(close())); // This should NOT quit the application because the
738 // QWindow is still there.
739 QTimer::singleShot(2000, &app, SLOT(quit())); // This causes the quit.
743 QVERIFY(timerSpy.count() > 15); // Should be around 20 if closing did not caused the quit
747 class PromptOnCloseWidget : public QWidget
750 void closeEvent(QCloseEvent *event)
752 QMessageBox *messageBox = new QMessageBox(this);
753 messageBox->setWindowTitle("Unsaved data");
754 messageBox->setText("Would you like to save or discard your current data?");
755 messageBox->setStandardButtons(QMessageBox::Save|QMessageBox::Discard|QMessageBox::Cancel);
756 messageBox->setDefaultButton(QMessageBox::Save);
759 QTest::qWaitForWindowShown(messageBox);
761 // verify that all windows are visible
762 foreach (QWidget *w, qApp->topLevelWidgets())
763 QVERIFY(w->isVisible());
765 qApp->processEvents();
767 qApp->closeAllWindows();
769 if (messageBox->standardButton(messageBox->clickedButton()) == QMessageBox::Cancel)
778 void tst_QApplication::closeAllWindows()
781 QApplication app(argc, 0, QApplication::GuiServer);
783 // create some windows
789 foreach (QWidget *w, app.topLevelWidgets()) {
791 QTest::qWaitForWindowShown(w);
793 // verify that they are visible
794 foreach (QWidget *w, app.topLevelWidgets())
795 QVERIFY(w->isVisible());
799 app.closeAllWindows();
800 // all windows should no longer be visible
801 foreach (QWidget *w, app.topLevelWidgets())
802 QVERIFY(!w->isVisible());
804 // add a window that prompts the user when closed
805 PromptOnCloseWidget *promptOnCloseWidget = new PromptOnCloseWidget;
807 foreach (QWidget *w, app.topLevelWidgets()) {
809 QTest::qWaitForWindowShown(w);
811 // close the last window to open the prompt (eventloop recurses)
812 promptOnCloseWidget->close();
813 // all windows should not be visible, except the one that opened the prompt
814 foreach (QWidget *w, app.topLevelWidgets()) {
815 if (w == promptOnCloseWidget)
816 QVERIFY(w->isVisible());
818 QVERIFY(!w->isVisible());
821 qDeleteAll(app.topLevelWidgets());
824 bool isPathListIncluded(const QStringList &l, const QStringList &r)
826 int size = r.count();
827 if (size > l.count())
829 #if defined (Q_OS_WIN)
830 Qt::CaseSensitivity cs = Qt::CaseInsensitive;
832 Qt::CaseSensitivity cs = Qt::CaseSensitive;
835 for ( ; i < l.count() && j < r.count(); ++i) {
836 if (QDir::toNativeSeparators(l[i]).compare(QDir::toNativeSeparators(r[j]), cs) == 0) {
841 return j == r.count();
844 #define QT_TST_QAPP_DEBUG
845 void tst_QApplication::libraryPaths()
849 QString testDir = QFileInfo(QFINDTESTDATA("test/test.pro")).absolutePath();
851 // On Windows CE we need QApplication object to have valid
852 // current Path. Therefore we need to identify it ourselves
853 // here for the test.
855 wchar_t module_name[MAX_PATH];
856 GetModuleFileName(0, module_name, MAX_PATH);
857 filePath = QString::fromWCharArray(module_name);
858 QString testDir = filePath.path() + "/test";
860 QApplication::setLibraryPaths(QStringList() << testDir);
861 QCOMPARE(QApplication::libraryPaths(), (QStringList() << testDir));
863 // creating QApplication adds the applicationDirPath to the libraryPath
865 QApplication app(argc, &argv0, QApplication::GuiServer);
866 QString appDirPath = QDir(app.applicationDirPath()).canonicalPath();
868 QStringList actual = QApplication::libraryPaths();
870 QStringList expected = QSet<QString>::fromList((QStringList() << testDir << appDirPath)).toList();
873 QVERIFY2(isPathListIncluded(actual, expected),
874 qPrintable("actual:\n - " + actual.join("\n - ") +
875 "\nexpected:\n - " + expected.join("\n - ")));
878 // creating QApplication adds the applicationDirPath and plugin install path to the libraryPath
880 QApplication app(argc, &argv0, QApplication::GuiServer);
881 QString appDirPath = app.applicationDirPath();
882 QString installPathPlugins = QLibraryInfo::location(QLibraryInfo::PluginsPath);
884 QStringList actual = QApplication::libraryPaths();
887 QStringList expected = QSet<QString>::fromList((QStringList() << installPathPlugins << appDirPath)).toList();
890 QVERIFY2(isPathListIncluded(actual, expected),
891 qPrintable("actual:\n - " + actual.join("\n - ") +
892 "\nexpected:\n - " + expected.join("\n - ")));
894 // setting the library paths overrides everything
895 QString testDir = QFileInfo(QFINDTESTDATA("test/test.pro")).absolutePath();
896 QApplication::setLibraryPaths(QStringList() << testDir);
897 QVERIFY2(isPathListIncluded(QApplication::libraryPaths(), (QStringList() << testDir)),
898 qPrintable("actual:\n - " + QApplication::libraryPaths().join("\n - ") +
899 "\nexpected:\n - " + testDir));
902 #ifdef QT_TST_QAPP_DEBUG
903 qDebug() << "Initial library path:" << QApplication::libraryPaths();
906 int count = QApplication::libraryPaths().count();
908 // this test doesn't work if KDE 4 is installed
909 QCOMPARE(count, 1); // before creating QApplication, only the PluginsPath is in the libraryPaths()
911 QString installPathPlugins = QLibraryInfo::location(QLibraryInfo::PluginsPath);
912 QApplication::addLibraryPath(installPathPlugins);
913 #ifdef QT_TST_QAPP_DEBUG
914 qDebug() << "installPathPlugins" << installPathPlugins;
915 qDebug() << "After adding plugins path:" << QApplication::libraryPaths();
917 QCOMPARE(QApplication::libraryPaths().count(), count);
918 QString testDir = QFileInfo(QFINDTESTDATA("test/test.pro")).absolutePath();
919 QApplication::addLibraryPath(testDir);
920 QCOMPARE(QApplication::libraryPaths().count(), count + 1);
922 // creating QApplication adds the applicationDirPath to the libraryPath
924 QApplication app(argc, &argv0, QApplication::GuiServer);
925 QString appDirPath = app.applicationDirPath();
926 qDebug() << QApplication::libraryPaths();
927 // On Windows CE these are identical and might also be the case for other
929 if (appDirPath != installPathPlugins)
930 QCOMPARE(QApplication::libraryPaths().count(), count + 2);
934 QApplication app(argc, &argv0, QApplication::GuiServer);
936 #ifdef QT_TST_QAPP_DEBUG
937 qDebug() << "Initial library path:" << app.libraryPaths();
939 int count = app.libraryPaths().count();
940 QString installPathPlugins = QLibraryInfo::location(QLibraryInfo::PluginsPath);
941 app.addLibraryPath(installPathPlugins);
942 #ifdef QT_TST_QAPP_DEBUG
943 qDebug() << "installPathPlugins" << installPathPlugins;
944 qDebug() << "After adding plugins path:" << app.libraryPaths();
946 QCOMPARE(app.libraryPaths().count(), count);
948 QString appDirPath = app.applicationDirPath();
950 app.addLibraryPath(appDirPath);
952 app.addLibraryPath(appDirPath + "/../..");
954 app.addLibraryPath(appDirPath + "/..");
956 #ifdef QT_TST_QAPP_DEBUG
957 qDebug() << "appDirPath" << appDirPath;
958 qDebug() << "After adding appDirPath && appDirPath + /..:" << app.libraryPaths();
960 QCOMPARE(app.libraryPaths().count(), count + 1);
962 app.addLibraryPath(appDirPath + "/../MacOS");
964 app.addLibraryPath(appDirPath + "/tmp/..");
966 #ifdef QT_TST_QAPP_DEBUG
967 qDebug() << "After adding appDirPath + /tmp/..:" << app.libraryPaths();
969 QCOMPARE(app.libraryPaths().count(), count + 1);
973 void tst_QApplication::libraryPaths_qt_plugin_path()
977 QApplication app(argc, &argv0, QApplication::GuiServer);
978 QString appDirPath = app.applicationDirPath();
980 // Our hook into libraryPaths() initialization: Set the QT_PLUGIN_PATH environment variable
981 QString installPathPluginsDeCanon = appDirPath + QString::fromLatin1("/tmp/..");
982 QByteArray ascii = QFile::encodeName(installPathPluginsDeCanon);
983 qputenv("QT_PLUGIN_PATH", ascii);
985 QVERIFY(!app.libraryPaths().contains(appDirPath + QString::fromLatin1("/tmp/..")));
988 void tst_QApplication::libraryPaths_qt_plugin_path_2()
991 QByteArray validPath = QDir("/tmp").canonicalPath().toLatin1();
992 QByteArray nonExistentPath = "/nonexistent";
993 QByteArray pluginPath = validPath + ":" + nonExistentPath;
994 #elif defined(Q_OS_WIN)
996 QByteArray validPath = "/Temp";
997 QByteArray nonExistentPath = "/nonexistent";
998 QByteArray pluginPath = validPath + ";" + nonExistentPath;
1000 QByteArray validPath = "C:\\windows";
1001 QByteArray nonExistentPath = "Z:\\nonexistent";
1002 QByteArray pluginPath = validPath + ";" + nonExistentPath;
1007 // Our hook into libraryPaths() initialization: Set the QT_PLUGIN_PATH environment variable
1008 qputenv("QT_PLUGIN_PATH", pluginPath);
1012 QApplication app(argc, &argv0, QApplication::GuiServer);
1014 // library path list should contain the default plus the one valid path
1015 QStringList expected =
1017 << QLibraryInfo::location(QLibraryInfo::PluginsPath)
1018 << QDir(app.applicationDirPath()).canonicalPath()
1019 << QDir(QDir::fromNativeSeparators(QString::fromLatin1(validPath))).canonicalPath();
1021 expected = QSet<QString>::fromList(expected).toList();
1023 QVERIFY2(isPathListIncluded(app.libraryPaths(), expected),
1024 qPrintable("actual:\n - " + app.libraryPaths().join("\n - ") +
1025 "\nexpected:\n - " + expected.join("\n - ")));
1031 QApplication app(argc, &argv0, QApplication::GuiServer);
1033 // library paths are initialized by the QApplication, setting
1034 // the environment variable here doesn't work
1035 qputenv("QT_PLUGIN_PATH", pluginPath);
1037 // library path list should contain the default
1038 QStringList expected =
1040 << QLibraryInfo::location(QLibraryInfo::PluginsPath)
1041 << app.applicationDirPath();
1043 expected = QSet<QString>::fromList(expected).toList();
1045 QVERIFY(isPathListIncluded(app.libraryPaths(), expected));
1047 qputenv("QT_PLUGIN_PATH", QByteArray());
1051 class SendPostedEventsTester : public QObject
1055 QList<int> eventSpy;
1056 bool event(QEvent *e);
1061 bool SendPostedEventsTester::event(QEvent *e)
1063 eventSpy.append(e->type());
1064 return QObject::event(e);
1067 void SendPostedEventsTester::doTest()
1069 QPointer<SendPostedEventsTester> p = this;
1070 QApplication::postEvent(this, new QEvent(QEvent::User));
1071 // DeferredDelete should not be delivered until returning from this function
1072 QApplication::postEvent(this, new QDeferredDeleteEvent());
1074 QEventLoop eventLoop;
1075 QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
1079 QCOMPARE(eventSpy.count(), 2);
1080 QCOMPARE(eventSpy.at(0), int(QEvent::MetaCall));
1081 QCOMPARE(eventSpy.at(1), int(QEvent::User));
1085 void tst_QApplication::sendPostedEvents()
1088 QApplication app(argc, 0, QApplication::GuiServer);
1089 SendPostedEventsTester *tester = new SendPostedEventsTester;
1090 QMetaObject::invokeMethod(tester, "doTest", Qt::QueuedConnection);
1091 QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
1092 QPointer<SendPostedEventsTester> p = tester;
1097 void tst_QApplication::thread()
1099 QThread *currentThread = QThread::currentThread();
1100 // no app, but still have a valid thread
1101 QVERIFY(currentThread != 0);
1103 // the thread should be running and not finished
1104 QVERIFY(currentThread->isRunning());
1105 QVERIFY(!currentThread->isFinished());
1107 // this should probably be in the tst_QObject::thread() test, but
1108 // we put it here since we want to make sure that objects created
1109 // *before* the QApplication has a thread
1111 QObject child(&object);
1112 QVERIFY(object.thread() == currentThread);
1113 QVERIFY(child.thread() == currentThread);
1117 QApplication app(argc, 0, QApplication::GuiServer);
1119 // current thread still valid
1120 QVERIFY(QThread::currentThread() != 0);
1121 // thread should be the same as before
1122 QCOMPARE(QThread::currentThread(), currentThread);
1124 // app's thread should be the current thread
1125 QCOMPARE(app.thread(), currentThread);
1127 // the thread should still be running and not finished
1128 QVERIFY(currentThread->isRunning());
1129 QVERIFY(!currentThread->isFinished());
1131 QTestEventLoop::instance().enterLoop(1);
1134 // app dead, current thread still valid
1135 QVERIFY(QThread::currentThread() != 0);
1136 QCOMPARE(QThread::currentThread(), currentThread);
1138 // the thread should still be running and not finished
1139 QVERIFY(currentThread->isRunning());
1140 QVERIFY(!currentThread->isFinished());
1142 // should still have a thread
1143 QVERIFY(object.thread() == currentThread);
1144 QVERIFY(child.thread() == currentThread);
1146 // do the test again, making sure that the thread is the same as
1150 QApplication app(argc, 0, QApplication::GuiServer);
1152 // current thread still valid
1153 QVERIFY(QThread::currentThread() != 0);
1154 // thread should be the same as before
1155 QCOMPARE(QThread::currentThread(), currentThread);
1157 // app's thread should be the current thread
1158 QCOMPARE(app.thread(), currentThread);
1160 // the thread should be running and not finished
1161 QVERIFY(currentThread->isRunning());
1162 QVERIFY(!currentThread->isFinished());
1164 // should still have a thread
1165 QVERIFY(object.thread() == currentThread);
1166 QVERIFY(child.thread() == currentThread);
1168 QTestEventLoop::instance().enterLoop(1);
1171 // app dead, current thread still valid
1172 QVERIFY(QThread::currentThread() != 0);
1173 QCOMPARE(QThread::currentThread(), currentThread);
1175 // the thread should still be running and not finished
1176 QVERIFY(currentThread->isRunning());
1177 QVERIFY(!currentThread->isFinished());
1179 // should still have a thread
1180 QVERIFY(object.thread() == currentThread);
1181 QVERIFY(child.thread() == currentThread);
1184 class DeleteLaterWidget : public QWidget
1188 DeleteLaterWidget(QApplication *_app, QWidget *parent = 0)
1189 : QWidget(parent) { app = _app; child_deleted = false; }
1196 void checkDeleteLater();
1197 void childDeleted() { child_deleted = true; }
1201 void DeleteLaterWidget::runTest()
1203 QObject *stillAlive = qFindChild<QObject*>(this, "deleteLater");
1205 QWidget *w = new QWidget(this);
1206 connect(w, SIGNAL(destroyed()), this, SLOT(childDeleted()));
1209 QVERIFY(!child_deleted);
1212 QTimer::singleShot(500, &dlg, SLOT(reject()));
1215 QVERIFY(!child_deleted);
1216 app->processEvents();
1217 QVERIFY(!child_deleted);
1219 QTimer::singleShot(500, this, SLOT(checkDeleteLater()));
1221 app->processEvents();
1223 QVERIFY(!stillAlive); // verify at the end to make test terminate
1226 void DeleteLaterWidget::checkDeleteLater()
1228 QVERIFY(child_deleted);
1233 void tst_QApplication::testDeleteLater()
1236 QSKIP("This test fails and then hangs on Mac OS X, see QTBUG-24318");
1239 QApplication app(argc, 0, QApplication::GuiServer);
1240 connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit()));
1242 DeleteLaterWidget *wgt = new DeleteLaterWidget(&app);
1243 QTimer::singleShot(500, wgt, SLOT(runTest()));
1245 QObject *object = new QObject(wgt);
1246 object->setObjectName("deleteLater");
1247 object->deleteLater();
1249 QObject *stillAlive = qFindChild<QObject*>(wgt, "deleteLater");
1250 QVERIFY(stillAlive);
1258 class EventLoopNester : public QObject
1262 void deleteLaterAndEnterLoop()
1264 QEventLoop eventLoop;
1265 QPointer<QObject> p(this);
1268 DeferredDelete events are compressed, meaning this second
1269 deleteLater() will *not* delete the object in the nested
1272 QMetaObject::invokeMethod(this, "deleteLater", Qt::QueuedConnection);
1273 QTimer::singleShot(1000, &eventLoop, SLOT(quit()));
1277 void deleteLaterAndExitLoop()
1279 // Check that 'p' is not deleted before exec returns, since the call
1280 // to QEventLoop::quit() should stop 'eventLoop' from processing
1281 // any more events (that is, delete later) until we return to the
1282 // _current_ event loop:
1283 QEventLoop eventLoop;
1284 QPointer<QObject> p(this);
1285 QMetaObject::invokeMethod(this, "deleteLater", Qt::QueuedConnection);
1286 QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
1288 QVERIFY(p); // not dead yet
1291 void processEventsOnly()
1293 QApplication::processEvents();
1295 void sendPostedEventsWithDeferredDelete()
1297 QApplication::sendPostedEvents(0, QEvent::DeferredDelete);
1300 void deleteLaterAndProcessEvents()
1302 QEventLoop eventLoop;
1304 QPointer<QObject> p = this;
1307 // trying to delete this object in a deeper eventloop just won't work
1308 QMetaObject::invokeMethod(this,
1309 "processEventsOnly",
1310 Qt::QueuedConnection);
1311 QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
1314 QMetaObject::invokeMethod(this,
1315 "sendPostedEventsWithDeferredDelete",
1316 Qt::QueuedConnection);
1317 QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
1321 // trying to delete it from this eventloop still doesn't work
1322 QApplication::processEvents();
1325 // however, it *will* work with this magic incantation
1326 QApplication::sendPostedEvents(0, QEvent::DeferredDelete);
1331 void tst_QApplication::testDeleteLaterProcessEvents()
1335 // Calling processEvents() with no event dispatcher does nothing.
1336 QObject *object = new QObject;
1337 QPointer<QObject> p(object);
1338 object->deleteLater();
1339 QApplication::processEvents();
1344 QApplication app(argc, 0, QApplication::GuiServer);
1345 // If you call processEvents() with an event dispatcher present, but
1346 // outside any event loops, deferred deletes are not processed unless
1347 // sendPostedEvents(0, DeferredDelete) is called.
1348 object = new QObject;
1350 object->deleteLater();
1351 app.processEvents();
1353 QApplication::sendPostedEvents(0, QEvent::DeferredDelete);
1356 // If you call deleteLater() on an object when there is no parent
1357 // event loop, and then enter an event loop, the object will get
1359 object = new QObject;
1361 object->deleteLater();
1363 QTimer::singleShot(1000, &loop, SLOT(quit()));
1368 // When an object is in an event loop, then calls deleteLater() and enters
1369 // an event loop recursively, it should not die until the parent event
1371 QApplication app(argc, 0, QApplication::GuiServer);
1373 EventLoopNester *nester = new EventLoopNester;
1375 QTimer::singleShot(3000, &loop, SLOT(quit()));
1376 QTimer::singleShot(0, nester, SLOT(deleteLaterAndEnterLoop()));
1383 // When the event loop that calls deleteLater() is exited
1384 // immediately, the object should die when returning to the
1385 // parent event loop
1386 QApplication app(argc, 0, QApplication::GuiServer);
1388 EventLoopNester *nester = new EventLoopNester;
1390 QTimer::singleShot(3000, &loop, SLOT(quit()));
1391 QTimer::singleShot(0, nester, SLOT(deleteLaterAndExitLoop()));
1398 // when the event loop that calls deleteLater() also calls
1399 // processEvents() immediately afterwards, the object should
1400 // not die until the parent loop continues
1401 QApplication app(argc, 0, QApplication::GuiServer);
1403 EventLoopNester *nester = new EventLoopNester();
1405 QTimer::singleShot(3000, &loop, SLOT(quit()));
1406 QTimer::singleShot(0, nester, SLOT(deleteLaterAndProcessEvents()));
1414 Test for crash with QApplication::setDesktopSettingsAware(false).
1416 void tst_QApplication::desktopSettingsAware()
1418 #ifndef QT_NO_PROCESS
1421 // We need an application object for QFINDTESTDATA to work
1422 // properly in all cases.
1424 QCoreApplication app(argc, 0);
1425 path = QFINDTESTDATA("desktopsettingsaware/");
1427 QVERIFY2(!path.isEmpty(), "Cannot locate desktopsettingsaware helper application");
1428 path += "desktopsettingsaware";
1431 QApplication tmpApp(argc, 0, QApplication::GuiServer);
1433 QProcess testProcess;
1434 testProcess.start(path);
1435 QVERIFY2(testProcess.waitForStarted(),
1436 qPrintable(QString::fromLatin1("Cannot start '%1': %2").arg(path, testProcess.errorString())));
1437 QVERIFY(testProcess.waitForFinished(10000));
1438 QCOMPARE(int(testProcess.state()), int(QProcess::NotRunning));
1439 QVERIFY(int(testProcess.error()) != int(QProcess::Crashed));
1443 void tst_QApplication::setActiveWindow()
1446 QApplication MyApp(argc, 0, QApplication::GuiServer);
1448 QWidget* w = new QWidget;
1449 QVBoxLayout* layout = new QVBoxLayout(w);
1451 QLineEdit* pb1 = new QLineEdit("Testbutton1", w);
1452 QLineEdit* pb2 = new QLineEdit("Test Line Edit", w);
1454 layout->addWidget(pb1);
1455 layout->addWidget(pb2);
1462 QApplication::setActiveWindow(w); // needs this on twm (focus follows mouse)
1463 QVERIFY(pb1->hasFocus());
1468 /* This might fail on some X11 window managers? */
1469 void tst_QApplication::focusChanged()
1472 QApplication app(argc, 0, QApplication::GuiServer);
1474 QSignalSpy spy(&app, SIGNAL(focusChanged(QWidget *, QWidget *)));
1479 QHBoxLayout hbox1(&parent1);
1480 QLabel lb1(&parent1);
1481 QLineEdit le1(&parent1);
1482 QPushButton pb1(&parent1);
1483 hbox1.addWidget(&lb1);
1484 hbox1.addWidget(&le1);
1485 hbox1.addWidget(&pb1);
1487 QCOMPARE(spy.count(), 0);
1490 QApplication::setActiveWindow(&parent1); // needs this on twm (focus follows mouse)
1491 QCOMPARE(spy.count(), 1);
1492 QCOMPARE(spy.at(0).count(), 2);
1493 old = qvariant_cast<QWidget*>(spy.at(0).at(0));
1494 now = qvariant_cast<QWidget*>(spy.at(0).at(1));
1495 QVERIFY(now == &le1);
1496 QVERIFY(now == QApplication::focusWidget());
1499 QCOMPARE(spy.count(), 0);
1502 QCOMPARE(spy.count(), 1);
1503 old = qvariant_cast<QWidget*>(spy.at(0).at(0));
1504 now = qvariant_cast<QWidget*>(spy.at(0).at(1));
1505 QVERIFY(now == &pb1);
1506 QVERIFY(now == QApplication::focusWidget());
1507 QVERIFY(old == &le1);
1511 QCOMPARE(spy.count(), 1);
1512 old = qvariant_cast<QWidget*>(spy.at(0).at(0));
1513 now = qvariant_cast<QWidget*>(spy.at(0).at(1));
1514 QVERIFY(now == &lb1);
1515 QVERIFY(now == QApplication::focusWidget());
1516 QVERIFY(old == &pb1);
1520 QCOMPARE(spy.count(), 1);
1521 old = qvariant_cast<QWidget*>(spy.at(0).at(0));
1522 now = qvariant_cast<QWidget*>(spy.at(0).at(1));
1524 QVERIFY(now == QApplication::focusWidget());
1525 QVERIFY(old == &lb1);
1529 QHBoxLayout hbox2(&parent2);
1530 QLabel lb2(&parent2);
1531 QLineEdit le2(&parent2);
1532 QPushButton pb2(&parent2);
1533 hbox2.addWidget(&lb2);
1534 hbox2.addWidget(&le2);
1535 hbox2.addWidget(&pb2);
1538 QApplication::setActiveWindow(&parent2); // needs this on twm (focus follows mouse)
1539 QVERIFY(spy.count() > 0); // one for deactivation, one for activation on Windows
1540 old = qvariant_cast<QWidget*>(spy.at(spy.count()-1).at(0));
1541 now = qvariant_cast<QWidget*>(spy.at(spy.count()-1).at(1));
1542 QVERIFY(now == &le2);
1543 QVERIFY(now == QApplication::focusWidget());
1547 QTestKeyEvent tab(QTest::Press, Qt::Key_Tab, 0, 0);
1548 QTestKeyEvent backtab(QTest::Press, Qt::Key_Backtab, 0, 0);
1549 QTestMouseEvent click(QTest::MouseClick, Qt::LeftButton, 0, QPoint(5, 5), 0);
1551 bool tabAllControls = true;
1553 // Mac has two modes, one where you tab to everything, one where you can
1554 // only tab to input controls, here's what we get. Determine which ones we
1556 QSettings appleSettings(QLatin1String("apple.com"));
1557 QVariant appleValue = appleSettings.value(QLatin1String("AppleKeyboardUIMode"), 0);
1558 tabAllControls = (appleValue.toInt() & 0x2);
1559 if (!tabAllControls) {
1560 QEXPECT_FAIL("", "QTBUG-24372 Mac tab key \"Text boxes and lists only\" vs "
1561 "\"All controls\" setting is not respected in Qt5", Abort);
1565 // make sure Qt's idea of tabbing between widgets matches what we think it should
1566 QCOMPARE(qt_tab_all_widgets, tabAllControls);
1569 if (!tabAllControls) {
1570 QVERIFY(spy.count() == 0);
1571 QVERIFY(now == QApplication::focusWidget());
1573 QVERIFY(spy.count() > 0);
1574 old = qvariant_cast<QWidget*>(spy.at(0).at(0));
1575 now = qvariant_cast<QWidget*>(spy.at(0).at(1));
1576 QVERIFY(now == &pb2);
1577 QVERIFY(now == QApplication::focusWidget());
1578 QVERIFY(old == &le2);
1582 if (!tabAllControls) {
1583 QVERIFY(spy.count() == 0);
1584 QVERIFY(now == QApplication::focusWidget());
1587 QVERIFY(spy.count() > 0);
1588 old = qvariant_cast<QWidget*>(spy.at(0).at(0));
1589 now = qvariant_cast<QWidget*>(spy.at(0).at(1));
1590 QVERIFY(now == &le2);
1591 QVERIFY(now == QApplication::focusWidget());
1592 QVERIFY(old == &pb2);
1596 if (!tabAllControls) {
1597 QVERIFY(spy.count() == 0);
1598 QVERIFY(now == QApplication::focusWidget());
1600 backtab.simulate(now);
1601 QVERIFY(spy.count() > 0);
1602 old = qvariant_cast<QWidget*>(spy.at(0).at(0));
1603 now = qvariant_cast<QWidget*>(spy.at(0).at(1));
1604 QVERIFY(now == &pb2);
1605 QVERIFY(now == QApplication::focusWidget());
1606 QVERIFY(old == &le2);
1611 if (!tabAllControls) {
1612 QVERIFY(spy.count() == 0);
1613 QVERIFY(now == QApplication::focusWidget());
1616 backtab.simulate(now);
1617 QVERIFY(spy.count() > 0);
1618 old = qvariant_cast<QWidget*>(spy.at(0).at(0));
1619 now = qvariant_cast<QWidget*>(spy.at(0).at(1));
1620 QVERIFY(now == &le2);
1621 QVERIFY(now == QApplication::focusWidget());
1622 QVERIFY(old == &pb2);
1626 click.simulate(old);
1627 if (!(pb2.focusPolicy() & Qt::ClickFocus)) {
1628 QVERIFY(spy.count() == 0);
1629 QVERIFY(now == QApplication::focusWidget());
1631 QVERIFY(spy.count() > 0);
1632 old = qvariant_cast<QWidget*>(spy.at(0).at(0));
1633 now = qvariant_cast<QWidget*>(spy.at(0).at(1));
1634 QVERIFY(now == &pb2);
1635 QVERIFY(now == QApplication::focusWidget());
1636 QVERIFY(old == &le2);
1639 click.simulate(old);
1640 QVERIFY(spy.count() > 0);
1641 old = qvariant_cast<QWidget*>(spy.at(0).at(0));
1642 now = qvariant_cast<QWidget*>(spy.at(0).at(1));
1643 QVERIFY(now == &le2);
1644 QVERIFY(now == QApplication::focusWidget());
1645 QVERIFY(old == &pb2);
1649 parent1.activateWindow();
1650 QApplication::setActiveWindow(&parent1); // needs this on twm (focus follows mouse)
1651 QVERIFY(spy.count() == 1 || spy.count() == 2); // one for deactivation, one for activation on Windows
1653 //on windows, the change of focus is made in 2 steps
1654 //(the focusChanged SIGNAL is emitted twice)
1656 old = qvariant_cast<QWidget*>(spy.at(spy.count()-1).at(0));
1658 old = qvariant_cast<QWidget*>(spy.at(spy.count()-2).at(0));
1659 now = qvariant_cast<QWidget*>(spy.at(spy.count()-1).at(1));
1660 QVERIFY(now == &le1);
1661 QVERIFY(now == QApplication::focusWidget());
1662 QVERIFY(old == &le2);
1666 class LineEdit : public QLineEdit
1669 LineEdit(QWidget *parent = 0) : QLineEdit(parent) { }
1672 void focusOutEvent(QFocusEvent *e) {
1673 QLineEdit::focusOutEvent(e);
1674 if (objectName() == "le1")
1678 void focusInEvent(QFocusEvent *e) {
1679 QLineEdit::focusInEvent(e);
1680 if (objectName() == "le2")
1685 void tst_QApplication::focusOut()
1688 QApplication app(argc, &argv0, QApplication::GuiServer);
1690 // Tests the case where the style pointer changes when on focus in/out
1691 // (the above is the case when the stylesheet changes)
1693 QLineEdit *le1 = new LineEdit(&w);
1694 le1->setObjectName("le1");
1695 le1->setStyleSheet("background: #fee");
1698 QLineEdit *le2 = new LineEdit(&w);
1699 le2->setObjectName("le2");
1700 le2->setStyleSheet("background: #fee");
1701 le2->move(100, 100);
1709 void tst_QApplication::execAfterExit()
1712 QApplication app(argc, &argv0, QApplication::GuiServer);
1713 QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
1714 // this should be ignored, as exec() will reset the exitCode
1715 QApplication::exit(1);
1716 int exitCode = app.exec();
1717 QCOMPARE(exitCode, 0);
1719 // the quitNow flag should have been reset, so we can spin an
1720 // eventloop after QApplication::exec() returns
1721 QEventLoop eventLoop;
1722 QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
1723 exitCode = eventLoop.exec();
1724 QCOMPARE(exitCode, 0);
1727 void tst_QApplication::wheelScrollLines()
1730 QApplication app(argc, &argv0, QApplication::GuiServer);
1731 // If wheelScrollLines returns 0, the mose wheel will be disabled.
1732 QVERIFY(app.wheelScrollLines() > 0);
1735 void tst_QApplication::style()
1740 QApplication app(argc, &argv0, QApplication::GuiServer);
1741 QPointer<QStyle> style = app.style();
1742 app.setStyle(new QWindowsStyle);
1743 QVERIFY(style.isNull());
1746 QApplication app(argc, &argv0, QApplication::GuiServer);
1748 // qApp style can never be 0
1749 QVERIFY(QApplication::style() != 0);
1752 void tst_QApplication::allWidgets()
1755 QApplication app(argc, &argv0, QApplication::GuiServer);
1756 QWidget *w = new QWidget;
1757 QVERIFY(app.allWidgets().contains(w)); // uncreate widget test
1758 QVERIFY(app.allWidgets().contains(w)); // created widget test
1761 QVERIFY(!app.allWidgets().contains(w)); // removal test
1764 void tst_QApplication::topLevelWidgets()
1767 QApplication app(argc, &argv0, QApplication::GuiServer);
1768 QWidget *w = new QWidget;
1770 #ifndef QT_NO_CLIPBOARD
1771 QClipboard *clipboard = QApplication::clipboard();
1772 QString originalText = clipboard->text();
1773 clipboard->setText(QString("newText"));
1775 app.processEvents();
1776 QVERIFY(QApplication::topLevelWidgets().contains(w));
1777 QCOMPARE(QApplication::topLevelWidgets().count(), 1);
1780 app.processEvents();
1781 QCOMPARE(QApplication::topLevelWidgets().count(), 0);
1786 void tst_QApplication::setAttribute()
1789 QApplication app(argc, &argv0, QApplication::GuiServer);
1790 QVERIFY(!QApplication::testAttribute(Qt::AA_ImmediateWidgetCreation));
1791 QWidget *w = new QWidget;
1792 QVERIFY(!w->testAttribute(Qt::WA_WState_Created));
1795 QApplication::setAttribute(Qt::AA_ImmediateWidgetCreation);
1796 QVERIFY(QApplication::testAttribute(Qt::AA_ImmediateWidgetCreation));
1798 QVERIFY(w->testAttribute(Qt::WA_WState_Created));
1799 QWidget *w2 = new QWidget(w);
1801 QVERIFY(w2->testAttribute(Qt::WA_WState_Created));
1805 QApplication::setAttribute(Qt::AA_ImmediateWidgetCreation, false);
1806 QVERIFY(!QApplication::testAttribute(Qt::AA_ImmediateWidgetCreation));
1808 QVERIFY(!w->testAttribute(Qt::WA_WState_Created));
1812 void tst_QApplication::windowsCommandLine_data()
1814 #if defined(Q_OS_WIN)
1815 QTest::addColumn<QString>("args");
1816 QTest::addColumn<QString>("expected");
1818 QTest::newRow("hello world")
1819 << QString("Hello \"World\"")
1820 << QString("Hello \"World\"");
1821 QTest::newRow("sql")
1822 << QString("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'PNR' AND TABLE_TYPE = 'VIEW' ORDER BY TABLE_NAME")
1823 << QString("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'PNR' AND TABLE_TYPE = 'VIEW' ORDER BY TABLE_NAME");
1827 void tst_QApplication::windowsCommandLine()
1829 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
1830 QFETCH(QString, args);
1831 QFETCH(QString, expected);
1833 QProcess testProcess;
1834 const QString path = QStringLiteral("wincmdline/wincmdline");
1835 testProcess.start(path, QStringList(args));
1836 QVERIFY2(testProcess.waitForStarted(),
1837 qPrintable(QString::fromLatin1("Cannot start '%1': %2").arg(path, testProcess.errorString())));
1838 QVERIFY(testProcess.waitForFinished(10000));
1839 QByteArray error = testProcess.readAllStandardError();
1840 QString procError(error);
1841 QCOMPARE(procError, expected);
1845 class TouchEventPropagationTestWidget : public QWidget
1850 bool seenTouchEvent, acceptTouchEvent, seenMouseEvent, acceptMouseEvent;
1852 TouchEventPropagationTestWidget(QWidget *parent = 0)
1853 : QWidget(parent), seenTouchEvent(false), acceptTouchEvent(false), seenMouseEvent(false), acceptMouseEvent(false)
1858 seenTouchEvent = acceptTouchEvent = seenMouseEvent = acceptMouseEvent = false;
1861 bool event(QEvent *event)
1863 switch (event->type()) {
1864 case QEvent::MouseButtonPress:
1865 case QEvent::MouseMove:
1866 case QEvent::MouseButtonRelease:
1867 // qDebug() << objectName() << "seenMouseEvent = true";
1868 seenMouseEvent = true;
1869 event->setAccepted(acceptMouseEvent);
1871 case QEvent::TouchBegin:
1872 case QEvent::TouchUpdate:
1873 case QEvent::TouchEnd:
1874 // qDebug() << objectName() << "seenTouchEvent = true";
1875 seenTouchEvent = true;
1876 event->setAccepted(acceptTouchEvent);
1879 return QWidget::event(event);
1885 void tst_QApplication::touchEventPropagation()
1888 QApplication app(argc, &argv0, QApplication::GuiServer);
1890 QList<QTouchEvent::TouchPoint> pressedTouchPoints;
1891 QTouchEvent::TouchPoint press(0);
1892 press.setState(Qt::TouchPointPressed);
1893 pressedTouchPoints << press;
1895 QList<QTouchEvent::TouchPoint> releasedTouchPoints;
1896 QTouchEvent::TouchPoint release(0);
1897 release.setState(Qt::TouchPointReleased);
1898 releasedTouchPoints << release;
1900 QTouchDevice *device = new QTouchDevice;
1901 device->setType(QTouchDevice::TouchScreen);
1902 QWindowSystemInterface::registerTouchDevice(device);
1905 // touch event behavior on a window
1906 TouchEventPropagationTestWidget window;
1907 window.setObjectName("1. window");
1908 window.show(); // Must have an explicitly specified QWindow for handleTouchEvent,
1909 // passing 0 would result in using topLevelAt() which is not ok in this case
1910 // as the screen position in the point is bogus.
1911 QTest::qWaitForWindowShown(&window);
1912 // QPA always takes screen positions and since we map the TouchPoint back to QPA's structure first,
1913 // we must ensure there is a screen position in the TouchPoint that maps to a local 0, 0.
1914 pressedTouchPoints[0].setScreenPos(window.mapToGlobal(QPoint(0, 0)));
1915 releasedTouchPoints[0].setScreenPos(window.mapToGlobal(QPoint(0, 0)));
1917 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
1920 QTest::QTouchEventSequence::touchPointList(pressedTouchPoints));
1921 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
1924 QTest::QTouchEventSequence::touchPointList(releasedTouchPoints));
1925 QCoreApplication::processEvents();
1926 QVERIFY(!window.seenTouchEvent);
1927 QVERIFY(!window.seenMouseEvent);
1930 window.setAttribute(Qt::WA_AcceptTouchEvents);
1931 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
1934 QTest::QTouchEventSequence::touchPointList(pressedTouchPoints));
1935 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
1938 QTest::QTouchEventSequence::touchPointList(releasedTouchPoints));
1939 QCoreApplication::processEvents();
1940 QVERIFY(window.seenTouchEvent);
1941 QVERIFY(!window.seenMouseEvent);
1944 window.acceptTouchEvent = true;
1945 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
1948 QTest::QTouchEventSequence::touchPointList(pressedTouchPoints));
1949 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
1952 QTest::QTouchEventSequence::touchPointList(releasedTouchPoints));
1953 QCoreApplication::processEvents();
1954 QVERIFY(window.seenTouchEvent);
1955 QVERIFY(!window.seenMouseEvent);
1959 // touch event behavior on a window with a child widget
1960 TouchEventPropagationTestWidget window;
1961 window.setObjectName("2. window");
1962 TouchEventPropagationTestWidget widget(&window);
1963 widget.setObjectName("2. widget");
1965 QTest::qWaitForWindowShown(&window);
1966 pressedTouchPoints[0].setScreenPos(window.mapToGlobal(QPoint(0, 0)));
1967 releasedTouchPoints[0].setScreenPos(window.mapToGlobal(QPoint(0, 0)));
1969 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
1972 QTest::QTouchEventSequence::touchPointList(pressedTouchPoints));
1973 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
1976 QTest::QTouchEventSequence::touchPointList(releasedTouchPoints));
1977 QCoreApplication::processEvents();
1978 QVERIFY(!widget.seenTouchEvent);
1979 QVERIFY(!widget.seenMouseEvent);
1980 QVERIFY(!window.seenTouchEvent);
1981 QVERIFY(!window.seenMouseEvent);
1985 widget.setAttribute(Qt::WA_AcceptTouchEvents);
1986 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
1989 QTest::QTouchEventSequence::touchPointList(pressedTouchPoints));
1990 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
1993 QTest::QTouchEventSequence::touchPointList(releasedTouchPoints));
1994 QCoreApplication::processEvents();
1995 QVERIFY(widget.seenTouchEvent);
1996 QVERIFY(!widget.seenMouseEvent);
1997 QVERIFY(!window.seenTouchEvent);
1998 QVERIFY(!window.seenMouseEvent);
2002 widget.acceptMouseEvent = true;
2003 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2006 QTest::QTouchEventSequence::touchPointList(pressedTouchPoints));
2007 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2010 QTest::QTouchEventSequence::touchPointList(releasedTouchPoints));
2011 QCoreApplication::processEvents();
2012 QVERIFY(widget.seenTouchEvent);
2013 QVERIFY(!widget.seenMouseEvent);
2014 QVERIFY(!window.seenTouchEvent);
2015 QVERIFY(!window.seenMouseEvent);
2019 widget.acceptTouchEvent = true;
2020 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2023 QTest::QTouchEventSequence::touchPointList(pressedTouchPoints));
2024 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2027 QTest::QTouchEventSequence::touchPointList(releasedTouchPoints));
2028 QCoreApplication::processEvents();
2029 QVERIFY(widget.seenTouchEvent);
2030 QVERIFY(!widget.seenMouseEvent);
2031 QVERIFY(!window.seenTouchEvent);
2032 QVERIFY(!window.seenMouseEvent);
2036 widget.setAttribute(Qt::WA_AcceptTouchEvents, false);
2037 window.setAttribute(Qt::WA_AcceptTouchEvents);
2038 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2041 QTest::QTouchEventSequence::touchPointList(pressedTouchPoints));
2042 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2045 QTest::QTouchEventSequence::touchPointList(releasedTouchPoints));
2046 QCoreApplication::processEvents();
2047 QVERIFY(!widget.seenTouchEvent);
2048 QVERIFY(!widget.seenMouseEvent);
2049 QVERIFY(window.seenTouchEvent);
2050 QVERIFY(!window.seenMouseEvent);
2054 window.acceptTouchEvent = true;
2055 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2058 QTest::QTouchEventSequence::touchPointList(pressedTouchPoints));
2059 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2062 QTest::QTouchEventSequence::touchPointList(releasedTouchPoints));
2063 QCoreApplication::processEvents();
2064 QVERIFY(!widget.seenTouchEvent);
2065 QVERIFY(!widget.seenMouseEvent);
2066 QVERIFY(window.seenTouchEvent);
2067 QVERIFY(!window.seenMouseEvent);
2071 widget.acceptMouseEvent = true; // doesn't matter, touch events are propagated first
2072 window.acceptTouchEvent = true;
2073 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2076 QTest::QTouchEventSequence::touchPointList(pressedTouchPoints));
2077 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2080 QTest::QTouchEventSequence::touchPointList(releasedTouchPoints));
2081 QCoreApplication::processEvents();
2082 QVERIFY(!widget.seenTouchEvent);
2083 QVERIFY(!widget.seenMouseEvent);
2084 QVERIFY(window.seenTouchEvent);
2085 QVERIFY(!window.seenMouseEvent);
2089 void tst_QApplication::qtbug_12673()
2093 // We need an application object for QFINDTESTDATA to work
2094 // properly in all cases.
2096 QCoreApplication app(argc, 0);
2097 path = QFINDTESTDATA("modal/");
2099 QVERIFY2(!path.isEmpty(), "Cannot locate modal helper application");
2102 QProcess testProcess;
2103 QStringList arguments;
2104 testProcess.start(path, arguments);
2105 QVERIFY2(testProcess.waitForStarted(),
2106 qPrintable(QString::fromLatin1("Cannot start '%1': %2").arg(path, testProcess.errorString())));
2107 QVERIFY(testProcess.waitForFinished(20000));
2108 QCOMPARE(testProcess.exitStatus(), QProcess::NormalExit);
2111 class NoQuitOnHideWidget : public QWidget
2115 explicit NoQuitOnHideWidget(QWidget *parent = 0)
2118 QTimer::singleShot(0, this, SLOT(hide()));
2119 QTimer::singleShot(500, this, SLOT(exitApp()));
2128 void tst_QApplication::noQuitOnHide()
2131 QApplication app(argc, 0);
2132 QWidget *window1 = new NoQuitOnHideWidget;
2134 QCOMPARE(app.exec(), 1);
2137 class ShowCloseShowWidget : public QWidget
2141 ShowCloseShowWidget(bool showAgain, QWidget *parent = 0)
2142 : QWidget(parent), showAgain(showAgain)
2144 QTimer::singleShot(0, this, SLOT(doClose()));
2145 QTimer::singleShot(500, this, SLOT(exitApp()));
2163 void tst_QApplication::abortQuitOnShow()
2166 QApplication app(argc, 0);
2167 QWidget *window1 = new ShowCloseShowWidget(false);
2169 QCOMPARE(app.exec(), 0);
2171 QWidget *window2 = new ShowCloseShowWidget(true);
2173 QCOMPARE(app.exec(), 1);
2177 This test is meant to ensure that certain objects (public & commonly used)
2178 can safely be used in a Q_GLOBAL_STATIC such that their destructors are
2179 executed *after* the destruction of QApplication.
2181 Q_GLOBAL_STATIC(QLocale, tst_qapp_locale);
2182 Q_GLOBAL_STATIC(QProcess, tst_qapp_process);
2183 Q_GLOBAL_STATIC(QFileSystemWatcher, tst_qapp_fileSystemWatcher);
2184 #ifndef QT_NO_SHAREDMEMORY
2185 Q_GLOBAL_STATIC(QSharedMemory, tst_qapp_sharedMemory);
2187 Q_GLOBAL_STATIC(QElapsedTimer, tst_qapp_elapsedTimer);
2188 Q_GLOBAL_STATIC(QMutex, tst_qapp_mutex);
2189 Q_GLOBAL_STATIC(QWidget, tst_qapp_widget);
2190 Q_GLOBAL_STATIC(QPixmap, tst_qapp_pixmap);
2191 Q_GLOBAL_STATIC(QFont, tst_qapp_font);
2192 Q_GLOBAL_STATIC(QRegion, tst_qapp_region);
2193 Q_GLOBAL_STATIC(QFontDatabase, tst_qapp_fontDatabase);
2194 Q_GLOBAL_STATIC(QCursor, tst_qapp_cursor);
2196 void tst_QApplication::globalStaticObjectDestruction()
2199 QApplication app(argc, &argv0, QApplication::GuiServer);
2200 QVERIFY(tst_qapp_locale());
2201 QVERIFY(tst_qapp_process());
2202 QVERIFY(tst_qapp_fileSystemWatcher());
2203 #ifndef QT_NO_SHAREDMEMORY
2204 QVERIFY(tst_qapp_sharedMemory());
2206 QVERIFY(tst_qapp_elapsedTimer());
2207 QVERIFY(tst_qapp_mutex());
2208 QVERIFY(tst_qapp_widget());
2209 QVERIFY(tst_qapp_pixmap());
2210 QVERIFY(tst_qapp_font());
2211 QVERIFY(tst_qapp_region());
2212 QVERIFY(tst_qapp_fontDatabase());
2213 QVERIFY(tst_qapp_cursor());
2216 //QTEST_APPLESS_MAIN(tst_QApplication)
2217 int main(int argc, char *argv[])
2219 tst_QApplication tc;
2221 return QTest::qExec(&tc, argc, argv);
2224 #include "tst_qapplication.moc"