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>
72 #include <qpa/qwindowsysteminterface.h>
76 static QWindowSystemInterface::TouchPoint touchPoint(const QTouchEvent::TouchPoint& pt)
78 QWindowSystemInterface::TouchPoint p;
81 p.normalPosition = pt.normalizedPos();
82 p.area = pt.screenRect();
83 p.pressure = pt.pressure();
85 p.velocity = pt.velocity();
86 p.rawPositions = pt.rawScreenPositions();
90 static QList<struct QWindowSystemInterface::TouchPoint> touchPointList(const QList<QTouchEvent::TouchPoint>& pointList)
92 QList<struct QWindowSystemInterface::TouchPoint> newList;
94 Q_FOREACH (QTouchEvent::TouchPoint p, pointList)
96 newList.append(touchPoint(p));
103 extern bool Q_GUI_EXPORT qt_tab_all_widgets; // from qapplication.cpp
106 class tst_QApplication : public QObject
112 virtual ~tst_QApplication();
119 void sendEventsOnProcessEvents(); // this must be the first test
124 void multiple_data();
136 void lastWindowClosed();
137 void quitOnLastWindowClosed();
138 void closeAllWindows();
139 void testDeleteLater();
140 void testDeleteLaterProcessEvents();
143 void libraryPaths_qt_plugin_path();
144 void libraryPaths_qt_plugin_path_2();
146 void sendPostedEvents();
149 void desktopSettingsAware();
151 void setActiveWindow();
156 void execAfterExit();
158 void wheelScrollLines();
165 void topLevelWidgets();
169 void windowsCommandLine_data();
170 void windowsCommandLine();
172 void touchEventPropagation();
177 void globalStaticObjectDestruction(); // run this last
179 void abortQuitOnShow();
182 class EventSpy : public QObject
187 QList<int> recordedEvents;
188 bool eventFilter(QObject *, QEvent *event)
190 recordedEvents.append(event->type());
195 void tst_QApplication::initTestCase()
197 // chdir to our testdata path and execute helper apps relative to that.
198 const QString testdataDir = QFileInfo(QFINDTESTDATA("desktopsettingsaware")).absolutePath();
199 QVERIFY2(QDir::setCurrent(testdataDir), qPrintable("Could not chdir to " + testdataDir));
202 void tst_QApplication::sendEventsOnProcessEvents()
205 QApplication app(argc, 0, QApplication::GuiServer);
208 app.installEventFilter(&spy);
210 QCoreApplication::postEvent(&app, new QEvent(QEvent::Type(QEvent::User + 1)));
211 QCoreApplication::processEvents();
212 QVERIFY(spy.recordedEvents.contains(QEvent::User + 1));
216 class CloseEventTestWindow : public QWidget
219 CloseEventTestWindow(QWidget *parent = 0)
224 void closeEvent(QCloseEvent *event)
236 tst_QApplication::tst_QApplication()
239 // Clean up environment previously to launching test
240 qputenv("QT_PLUGIN_PATH", QByteArray());
244 tst_QApplication::~tst_QApplication()
249 void tst_QApplication::init()
251 // TODO: Add initialization code here.
252 // This will be executed immediately before each test is run.
255 void tst_QApplication::cleanup()
257 // TODO: Add cleanup code here.
258 // This will be executed immediately after each test is run.
261 void tst_QApplication::staticSetup()
265 QStyle *style = QStyleFactory::create(QLatin1String("Windows"));
267 QApplication::setStyle(style);
270 QApplication::setPalette(pal);
273 QApplication::setFont(font);*/
276 QApplication app(argc, 0, QApplication::GuiServer);
280 // QApp subclass that exits the event loop after 150ms
281 class TestApplication : public QApplication
284 TestApplication( int &argc, char **argv )
285 : QApplication( argc, argv, QApplication::GuiServer )
290 void timerEvent( QTimerEvent * )
296 void tst_QApplication::alert()
299 QApplication app(argc, 0, QApplication::GuiServer);
304 app.alert(&widget, 100);
307 QVERIFY(QTest::qWaitForWindowExposed(&widget));
308 QVERIFY(QTest::qWaitForWindowExposed(&widget2));
310 app.alert(&widget, -1);
311 app.alert(&widget, 250);
312 widget2.activateWindow();
313 QApplication::setActiveWindow(&widget2);
314 app.alert(&widget, 0);
315 widget.activateWindow();
316 QApplication::setActiveWindow(&widget);
317 app.alert(&widget, 200);
321 void tst_QApplication::multiple_data()
323 QTest::addColumn<QStringList>("features");
325 // return a list of things to try
326 QTest::newRow( "data0" ) << QStringList( "" );
327 QTest::newRow( "data1" ) << QStringList( "QFont" );
328 QTest::newRow( "data2" ) << QStringList( "QPixmap" );
329 QTest::newRow( "data3" ) << QStringList( "QWidget" );
332 void tst_QApplication::multiple()
334 QFETCH(QStringList,features);
339 TestApplication app( argc, 0 );
341 if ( features.contains( "QFont" ) ) {
342 // create font and force loading
343 QFont font( "Arial", 12 );
344 QFontInfo finfo( font );
347 if ( features.contains( "QPixmap" ) ) {
348 QPixmap pix( 100, 100 );
349 pix.fill( Qt::black );
351 if ( features.contains( "QWidget" ) ) {
355 QVERIFY(!app.exec());
359 void tst_QApplication::nonGui()
362 // ### This is only to allow us to generate a test report for now.
363 QSKIP("This test shuts down the window manager on HP-UX.");
367 QApplication app(argc, 0, false);
368 QCOMPARE(qApp, &app);
371 void tst_QApplication::setFont_data()
373 QTest::addColumn<QString>("family");
374 QTest::addColumn<int>("pointsize");
375 QTest::addColumn<bool>("beforeAppConstructor");
378 QApplication app(argc, 0, QApplication::GuiServer); // Needed for QFontDatabase
382 QStringList families = fdb.families();
383 for (QStringList::const_iterator itr = families.begin();
384 itr != families.end();
387 QString family = *itr;
388 QStringList styles = fdb.styles(family);
389 if (styles.size() > 0) {
390 QString style = styles.first();
391 QList<int> sizes = fdb.pointSizes(family, style);
393 sizes = fdb.standardSizes();
394 if (sizes.size() > 0) {
395 QTest::newRow(QString("data%1a").arg(cnt).toLatin1().constData())
399 QTest::newRow(QString("data%1b").arg(cnt).toLatin1().constData())
409 QTest::newRow("nonexistingfont after") << "nosuchfont_probably_quiteunlikely"
411 QTest::newRow("nonexistingfont before") << "nosuchfont_probably_quiteunlikely"
414 QTest::newRow("largescaleable after") << "smoothtimes" << 100 << false;
415 QTest::newRow("largescaleable before") << "smoothtimes" << 100 << true;
417 QTest::newRow("largeunscaleale after") << "helvetica" << 100 << false;
418 QTest::newRow("largeunscaleale before") << "helvetica" << 100 << true;
421 void tst_QApplication::setFont()
423 QFETCH( QString, family );
424 QFETCH( int, pointsize );
425 QFETCH( bool, beforeAppConstructor );
427 QFont font( family, pointsize );
428 if (beforeAppConstructor) {
429 QApplication::setFont( font );
430 QCOMPARE(QApplication::font(), font);
434 QApplication app( argc, 0, QApplication::GuiServer );
435 if (!beforeAppConstructor)
436 QApplication::setFont( font );
438 QCOMPARE( app.font(), font );
441 void tst_QApplication::args_data()
443 QTest::addColumn<int>("argc_in");
444 QTest::addColumn<QString>("args_in");
445 QTest::addColumn<int>("argc_out");
446 QTest::addColumn<QString>("args_out");
448 QTest::newRow( "App name" ) << 1 << "/usr/bin/appname" << 1 << "/usr/bin/appname";
449 QTest::newRow( "No arguments" ) << 0 << QString() << 0 << QString();
450 QTest::newRow( "App name, style" ) << 3 << "/usr/bin/appname -style motif" << 1 << "/usr/bin/appname";
451 QTest::newRow( "App name, style, arbitrary, reverse" ) << 5 << "/usr/bin/appname -style motif -arbitrary -reverse"
452 << 2 << "/usr/bin/appname -arbitrary";
455 void tst_QApplication::task109149()
458 QApplication app(argc, 0, QApplication::GuiServer);
459 QApplication::setFont(QFont("helvetica", 100));
462 w.setWindowTitle("hello");
468 static char ** QString2cstrings( const QString &args )
470 static QList<QByteArray> cache;
474 QStringList list = args.split(' ');;
475 argarray = new char*[list.count()+1];
477 for (i = 0; i < (int)list.count(); ++i ) {
478 QByteArray l1 = list[i].toLatin1();
479 argarray[i] = l1.data();
487 static QString cstrings2QString( char **args )
503 void tst_QApplication::args()
505 QFETCH( int, argc_in );
506 QFETCH( QString, args_in );
507 QFETCH( int, argc_out );
508 QFETCH( QString, args_out );
510 char **argv = QString2cstrings( args_in );
512 QApplication app( argc_in, argv, QApplication::GuiServer );
513 QString argv_out = cstrings2QString(argv);
515 QCOMPARE( argc_in, argc_out );
516 QCOMPARE( argv_out, args_out );
521 void tst_QApplication::appName()
523 char argv0[] = "tst_qapplication";
524 char *argv[] = { argv0, 0 };
526 QApplication app(argc, argv);
527 QCOMPARE(::qAppName(), QString::fromLatin1("tst_qapplication"));
528 QCOMPARE(QCoreApplication::applicationName(), QString::fromLatin1("tst_qapplication"));
531 class CloseWidget : public QWidget
541 void timerEvent(QTimerEvent *)
548 void tst_QApplication::lastWindowClosed()
551 QApplication app(argc, 0, QApplication::GuiServer);
553 QSignalSpy spy(&app, SIGNAL(lastWindowClosed()));
555 QPointer<QDialog> dialog = new QDialog;
556 QVERIFY(dialog->testAttribute(Qt::WA_QuitOnClose));
557 QTimer::singleShot(1000, dialog, SLOT(accept()));
560 QCOMPARE(spy.count(), 0);
562 QPointer<CloseWidget>widget = new CloseWidget;
563 QVERIFY(widget->testAttribute(Qt::WA_QuitOnClose));
565 QObject::connect(&app, SIGNAL(lastWindowClosed()), widget, SLOT(deleteLater()));
568 QCOMPARE(spy.count(), 1);
573 // show 3 windows, close them, should only get lastWindowClosed once
581 QTimer::singleShot(1000, &app, SLOT(closeAllWindows()));
583 QCOMPARE(spy.count(), 1);
586 class QuitOnLastWindowClosedDialog : public QDialog
590 QPushButton *okButton;
592 QuitOnLastWindowClosedDialog()
594 QHBoxLayout *hbox = new QHBoxLayout(this);
595 okButton = new QPushButton("&ok", this);
597 hbox->addWidget(okButton);
598 connect(okButton, SIGNAL(clicked()), this, SLOT(accept()));
599 connect(okButton, SIGNAL(clicked()), this, SLOT(ok_clicked()));
608 connect(&timer, SIGNAL(timeout()), &other, SLOT(accept()));
609 QSignalSpy spy(&timer, SIGNAL(timeout()));
610 QSignalSpy appSpy(qApp, SIGNAL(lastWindowClosed()));
615 // verify that the eventloop ran and let the timer fire
616 QCOMPARE(spy.count(), 1);
617 QCOMPARE(appSpy.count(), 1);
621 class QuitOnLastWindowClosedWindow : public QWidget
626 QuitOnLastWindowClosedWindow()
630 void execDialogThenShow()
634 connect(&timer1, SIGNAL(timeout()), &dialog, SLOT(accept()));
635 QSignalSpy spy1(&timer1, SIGNAL(timeout()));
636 timer1.setSingleShot(true);
639 QCOMPARE(spy1.count(), 1);
645 void tst_QApplication::quitOnLastWindowClosed()
649 QApplication app(argc, 0, QApplication::GuiServer);
651 QuitOnLastWindowClosedDialog d;
653 QTimer::singleShot(1000, d.okButton, SLOT(animateClick()));
655 QSignalSpy appSpy(&app, SIGNAL(lastWindowClosed()));
658 // lastWindowClosed() signal should only be sent after the last dialog is closed
659 QCOMPARE(appSpy.count(), 2);
663 QApplication app(argc, 0, QApplication::GuiServer);
664 QSignalSpy appSpy(&app, SIGNAL(lastWindowClosed()));
668 connect(&timer1, SIGNAL(timeout()), &dialog, SLOT(accept()));
669 QSignalSpy spy1(&timer1, SIGNAL(timeout()));
670 timer1.setSingleShot(true);
673 QCOMPARE(spy1.count(), 1);
674 QCOMPARE(appSpy.count(), 0);
677 connect(&timer2, SIGNAL(timeout()), &app, SLOT(quit()));
678 QSignalSpy spy2(&timer2, SIGNAL(timeout()));
679 timer2.setSingleShot(true);
681 int returnValue = app.exec();
682 QCOMPARE(returnValue, 0);
683 QCOMPARE(spy2.count(), 1);
684 QCOMPARE(appSpy.count(), 0);
688 QApplication app(argc, 0, QApplication::GuiServer);
690 timer.setInterval(100);
692 QSignalSpy spy(&app, SIGNAL(aboutToQuit()));
693 QSignalSpy spy2(&timer, SIGNAL(timeout()));
695 QPointer<QMainWindow> mainWindow = new QMainWindow;
696 QPointer<QDialog> dialog = new QDialog(mainWindow);
698 QVERIFY(app.quitOnLastWindowClosed());
699 QVERIFY(mainWindow->testAttribute(Qt::WA_QuitOnClose));
700 QVERIFY(dialog->testAttribute(Qt::WA_QuitOnClose));
706 QTimer::singleShot(1000, mainWindow, SLOT(close())); // This should quit the application
707 QTimer::singleShot(2000, &app, SLOT(quit())); // This makes sure we quit even if it didn't
711 QCOMPARE(spy.count(), 1);
712 QVERIFY(spy2.count() < 15); // Should be around 10 if closing caused the quit
716 QApplication app(argc, 0, QApplication::GuiServer);
718 timer.setInterval(100);
720 QSignalSpy spy(&app, SIGNAL(aboutToQuit()));
721 QSignalSpy spy2(&timer, SIGNAL(timeout()));
723 QPointer<CloseEventTestWindow> mainWindow = new CloseEventTestWindow;
725 QVERIFY(app.quitOnLastWindowClosed());
726 QVERIFY(mainWindow->testAttribute(Qt::WA_QuitOnClose));
731 QTimer::singleShot(1000, mainWindow, SLOT(close())); // This should quit the application
732 QTimer::singleShot(2000, &app, SLOT(quit())); // This makes sure we quit even if it didn't
736 QCOMPARE(spy.count(), 1);
737 QVERIFY(spy2.count() > 15); // Should be around 20 if closing did not caused the quit
741 QApplication app(argc, 0, QApplication::GuiServer);
742 QSignalSpy appSpy(&app, SIGNAL(lastWindowClosed()));
744 // exec a dialog for 1 second, then show the window
745 QuitOnLastWindowClosedWindow window;
746 QTimer::singleShot(0, &window, SLOT(execDialogThenShow()));
749 QSignalSpy timerSpy(&timer, SIGNAL(timeout()));
750 connect(&timer, SIGNAL(timeout()), &window, SLOT(close()));
751 timer.setSingleShot(true);
753 int returnValue = app.exec();
754 QCOMPARE(returnValue, 0);
755 // failure here means the timer above didn't fire, and the
756 // quit was caused the the dialog being closed (not the window)
757 QCOMPARE(timerSpy.count(), 1);
758 QCOMPARE(appSpy.count(), 2);
762 QApplication app(argc, 0, QApplication::GuiServer);
763 QVERIFY(app.quitOnLastWindowClosed());
766 timer.setInterval(100);
767 QSignalSpy timerSpy(&timer, SIGNAL(timeout()));
776 QTimer::singleShot(1000, &wid, SLOT(close())); // This should NOT quit the application because the
777 // QWindow is still there.
778 QTimer::singleShot(2000, &app, SLOT(quit())); // This causes the quit.
782 QVERIFY(timerSpy.count() > 15); // Should be around 20 if closing did not caused the quit
786 class PromptOnCloseWidget : public QWidget
789 void closeEvent(QCloseEvent *event)
791 QMessageBox *messageBox = new QMessageBox(this);
792 messageBox->setWindowTitle("Unsaved data");
793 messageBox->setText("Would you like to save or discard your current data?");
794 messageBox->setStandardButtons(QMessageBox::Save|QMessageBox::Discard|QMessageBox::Cancel);
795 messageBox->setDefaultButton(QMessageBox::Save);
798 QVERIFY(QTest::qWaitForWindowExposed(messageBox));
800 // verify that all windows are visible
801 foreach (QWidget *w, qApp->topLevelWidgets())
802 QVERIFY(w->isVisible());
804 qApp->processEvents();
806 qApp->closeAllWindows();
808 if (messageBox->standardButton(messageBox->clickedButton()) == QMessageBox::Cancel)
817 void tst_QApplication::closeAllWindows()
820 QApplication app(argc, 0, QApplication::GuiServer);
822 // create some windows
828 foreach (QWidget *w, app.topLevelWidgets()) {
830 QVERIFY(QTest::qWaitForWindowExposed(w));
832 // verify that they are visible
833 foreach (QWidget *w, app.topLevelWidgets())
834 QVERIFY(w->isVisible());
838 app.closeAllWindows();
839 // all windows should no longer be visible
840 foreach (QWidget *w, app.topLevelWidgets())
841 QVERIFY(!w->isVisible());
843 // add a window that prompts the user when closed
844 PromptOnCloseWidget *promptOnCloseWidget = new PromptOnCloseWidget;
846 foreach (QWidget *w, app.topLevelWidgets()) {
848 QVERIFY(QTest::qWaitForWindowExposed(w));
850 // close the last window to open the prompt (eventloop recurses)
851 promptOnCloseWidget->close();
852 // all windows should not be visible, except the one that opened the prompt
853 foreach (QWidget *w, app.topLevelWidgets()) {
854 if (w == promptOnCloseWidget)
855 QVERIFY(w->isVisible());
857 QVERIFY(!w->isVisible());
860 qDeleteAll(app.topLevelWidgets());
863 bool isPathListIncluded(const QStringList &l, const QStringList &r)
865 int size = r.count();
866 if (size > l.count())
868 #if defined (Q_OS_WIN)
869 Qt::CaseSensitivity cs = Qt::CaseInsensitive;
871 Qt::CaseSensitivity cs = Qt::CaseSensitive;
874 for ( ; i < l.count() && j < r.count(); ++i) {
875 if (QDir::toNativeSeparators(l[i]).compare(QDir::toNativeSeparators(r[j]), cs) == 0) {
880 return j == r.count();
883 #define QT_TST_QAPP_DEBUG
884 void tst_QApplication::libraryPaths()
888 QString testDir = QFileInfo(QFINDTESTDATA("test/test.pro")).absolutePath();
890 // On Windows CE we need QApplication object to have valid
891 // current Path. Therefore we need to identify it ourselves
892 // here for the test.
894 wchar_t module_name[MAX_PATH];
895 GetModuleFileName(0, module_name, MAX_PATH);
896 filePath = QString::fromWCharArray(module_name);
897 QString testDir = filePath.path() + "/test";
899 QApplication::setLibraryPaths(QStringList() << testDir);
900 QCOMPARE(QApplication::libraryPaths(), (QStringList() << testDir));
902 // creating QApplication adds the applicationDirPath to the libraryPath
904 QApplication app(argc, &argv0, QApplication::GuiServer);
905 QString appDirPath = QDir(app.applicationDirPath()).canonicalPath();
907 QStringList actual = QApplication::libraryPaths();
909 QStringList expected = QSet<QString>::fromList((QStringList() << testDir << appDirPath)).toList();
912 QVERIFY2(isPathListIncluded(actual, expected),
913 qPrintable("actual:\n - " + actual.join("\n - ") +
914 "\nexpected:\n - " + expected.join("\n - ")));
917 // creating QApplication adds the applicationDirPath and plugin install path to the libraryPath
919 QApplication app(argc, &argv0, QApplication::GuiServer);
920 QString appDirPath = app.applicationDirPath();
921 QString installPathPlugins = QLibraryInfo::location(QLibraryInfo::PluginsPath);
923 QStringList actual = QApplication::libraryPaths();
926 QStringList expected = QSet<QString>::fromList((QStringList() << installPathPlugins << appDirPath)).toList();
929 QVERIFY2(isPathListIncluded(actual, expected),
930 qPrintable("actual:\n - " + actual.join("\n - ") +
931 "\nexpected:\n - " + expected.join("\n - ")));
933 // setting the library paths overrides everything
934 QString testDir = QFileInfo(QFINDTESTDATA("test/test.pro")).absolutePath();
935 QApplication::setLibraryPaths(QStringList() << testDir);
936 QVERIFY2(isPathListIncluded(QApplication::libraryPaths(), (QStringList() << testDir)),
937 qPrintable("actual:\n - " + QApplication::libraryPaths().join("\n - ") +
938 "\nexpected:\n - " + testDir));
941 #ifdef QT_TST_QAPP_DEBUG
942 qDebug() << "Initial library path:" << QApplication::libraryPaths();
945 int count = QApplication::libraryPaths().count();
947 // this test doesn't work if KDE 4 is installed
948 QCOMPARE(count, 1); // before creating QApplication, only the PluginsPath is in the libraryPaths()
950 QString installPathPlugins = QLibraryInfo::location(QLibraryInfo::PluginsPath);
951 QApplication::addLibraryPath(installPathPlugins);
952 #ifdef QT_TST_QAPP_DEBUG
953 qDebug() << "installPathPlugins" << installPathPlugins;
954 qDebug() << "After adding plugins path:" << QApplication::libraryPaths();
956 QCOMPARE(QApplication::libraryPaths().count(), count);
957 QString testDir = QFileInfo(QFINDTESTDATA("test/test.pro")).absolutePath();
958 QApplication::addLibraryPath(testDir);
959 QCOMPARE(QApplication::libraryPaths().count(), count + 1);
961 // creating QApplication adds the applicationDirPath to the libraryPath
963 QApplication app(argc, &argv0, QApplication::GuiServer);
964 QString appDirPath = app.applicationDirPath();
965 qDebug() << QApplication::libraryPaths();
966 // On Windows CE these are identical and might also be the case for other
968 if (appDirPath != installPathPlugins)
969 QCOMPARE(QApplication::libraryPaths().count(), count + 2);
973 QApplication app(argc, &argv0, QApplication::GuiServer);
975 #ifdef QT_TST_QAPP_DEBUG
976 qDebug() << "Initial library path:" << app.libraryPaths();
978 int count = app.libraryPaths().count();
979 QString installPathPlugins = QLibraryInfo::location(QLibraryInfo::PluginsPath);
980 app.addLibraryPath(installPathPlugins);
981 #ifdef QT_TST_QAPP_DEBUG
982 qDebug() << "installPathPlugins" << installPathPlugins;
983 qDebug() << "After adding plugins path:" << app.libraryPaths();
985 QCOMPARE(app.libraryPaths().count(), count);
987 QString appDirPath = app.applicationDirPath();
989 app.addLibraryPath(appDirPath);
991 app.addLibraryPath(appDirPath + "/../..");
993 app.addLibraryPath(appDirPath + "/..");
995 #ifdef QT_TST_QAPP_DEBUG
996 qDebug() << "appDirPath" << appDirPath;
997 qDebug() << "After adding appDirPath && appDirPath + /..:" << app.libraryPaths();
999 QCOMPARE(app.libraryPaths().count(), count + 1);
1001 app.addLibraryPath(appDirPath + "/../MacOS");
1003 app.addLibraryPath(appDirPath + "/tmp/..");
1005 #ifdef QT_TST_QAPP_DEBUG
1006 qDebug() << "After adding appDirPath + /tmp/..:" << app.libraryPaths();
1008 QCOMPARE(app.libraryPaths().count(), count + 1);
1012 void tst_QApplication::libraryPaths_qt_plugin_path()
1016 QApplication app(argc, &argv0, QApplication::GuiServer);
1017 QString appDirPath = app.applicationDirPath();
1019 // Our hook into libraryPaths() initialization: Set the QT_PLUGIN_PATH environment variable
1020 QString installPathPluginsDeCanon = appDirPath + QString::fromLatin1("/tmp/..");
1021 QByteArray ascii = QFile::encodeName(installPathPluginsDeCanon);
1022 qputenv("QT_PLUGIN_PATH", ascii);
1024 QVERIFY(!app.libraryPaths().contains(appDirPath + QString::fromLatin1("/tmp/..")));
1027 void tst_QApplication::libraryPaths_qt_plugin_path_2()
1030 QByteArray validPath = QDir("/tmp").canonicalPath().toLatin1();
1031 QByteArray nonExistentPath = "/nonexistent";
1032 QByteArray pluginPath = validPath + ":" + nonExistentPath;
1033 #elif defined(Q_OS_WIN)
1035 QByteArray validPath = "/Temp";
1036 QByteArray nonExistentPath = "/nonexistent";
1037 QByteArray pluginPath = validPath + ";" + nonExistentPath;
1039 QByteArray validPath = "C:\\windows";
1040 QByteArray nonExistentPath = "Z:\\nonexistent";
1041 QByteArray pluginPath = validPath + ";" + nonExistentPath;
1046 // Our hook into libraryPaths() initialization: Set the QT_PLUGIN_PATH environment variable
1047 qputenv("QT_PLUGIN_PATH", pluginPath);
1051 QApplication app(argc, &argv0, QApplication::GuiServer);
1053 // library path list should contain the default plus the one valid path
1054 QStringList expected =
1056 << QLibraryInfo::location(QLibraryInfo::PluginsPath)
1057 << QDir(app.applicationDirPath()).canonicalPath()
1058 << QDir(QDir::fromNativeSeparators(QString::fromLatin1(validPath))).canonicalPath();
1060 expected = QSet<QString>::fromList(expected).toList();
1062 QVERIFY2(isPathListIncluded(app.libraryPaths(), expected),
1063 qPrintable("actual:\n - " + app.libraryPaths().join("\n - ") +
1064 "\nexpected:\n - " + expected.join("\n - ")));
1070 QApplication app(argc, &argv0, QApplication::GuiServer);
1072 // library paths are initialized by the QApplication, setting
1073 // the environment variable here doesn't work
1074 qputenv("QT_PLUGIN_PATH", pluginPath);
1076 // library path list should contain the default
1077 QStringList expected =
1079 << QLibraryInfo::location(QLibraryInfo::PluginsPath)
1080 << app.applicationDirPath();
1082 expected = QSet<QString>::fromList(expected).toList();
1084 QVERIFY(isPathListIncluded(app.libraryPaths(), expected));
1086 qputenv("QT_PLUGIN_PATH", QByteArray());
1090 class SendPostedEventsTester : public QObject
1094 QList<int> eventSpy;
1095 bool event(QEvent *e);
1100 bool SendPostedEventsTester::event(QEvent *e)
1102 eventSpy.append(e->type());
1103 return QObject::event(e);
1106 void SendPostedEventsTester::doTest()
1108 QPointer<SendPostedEventsTester> p = this;
1109 QApplication::postEvent(this, new QEvent(QEvent::User));
1110 // DeferredDelete should not be delivered until returning from this function
1111 QApplication::postEvent(this, new QDeferredDeleteEvent());
1113 QEventLoop eventLoop;
1114 QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
1118 QCOMPARE(eventSpy.count(), 2);
1119 QCOMPARE(eventSpy.at(0), int(QEvent::MetaCall));
1120 QCOMPARE(eventSpy.at(1), int(QEvent::User));
1124 void tst_QApplication::sendPostedEvents()
1127 QApplication app(argc, 0, QApplication::GuiServer);
1128 SendPostedEventsTester *tester = new SendPostedEventsTester;
1129 QMetaObject::invokeMethod(tester, "doTest", Qt::QueuedConnection);
1130 QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
1131 QPointer<SendPostedEventsTester> p = tester;
1136 void tst_QApplication::thread()
1138 QThread *currentThread = QThread::currentThread();
1139 // no app, but still have a valid thread
1140 QVERIFY(currentThread != 0);
1142 // the thread should be running and not finished
1143 QVERIFY(currentThread->isRunning());
1144 QVERIFY(!currentThread->isFinished());
1146 // this should probably be in the tst_QObject::thread() test, but
1147 // we put it here since we want to make sure that objects created
1148 // *before* the QApplication has a thread
1150 QObject child(&object);
1151 QVERIFY(object.thread() == currentThread);
1152 QVERIFY(child.thread() == currentThread);
1156 QApplication app(argc, 0, QApplication::GuiServer);
1158 // current thread still valid
1159 QVERIFY(QThread::currentThread() != 0);
1160 // thread should be the same as before
1161 QCOMPARE(QThread::currentThread(), currentThread);
1163 // app's thread should be the current thread
1164 QCOMPARE(app.thread(), currentThread);
1166 // the thread should still be running and not finished
1167 QVERIFY(currentThread->isRunning());
1168 QVERIFY(!currentThread->isFinished());
1170 QTestEventLoop::instance().enterLoop(1);
1173 // app dead, current thread still valid
1174 QVERIFY(QThread::currentThread() != 0);
1175 QCOMPARE(QThread::currentThread(), currentThread);
1177 // the thread should still be running and not finished
1178 QVERIFY(currentThread->isRunning());
1179 QVERIFY(!currentThread->isFinished());
1181 // should still have a thread
1182 QVERIFY(object.thread() == currentThread);
1183 QVERIFY(child.thread() == currentThread);
1185 // do the test again, making sure that the thread is the same as
1189 QApplication app(argc, 0, QApplication::GuiServer);
1191 // current thread still valid
1192 QVERIFY(QThread::currentThread() != 0);
1193 // thread should be the same as before
1194 QCOMPARE(QThread::currentThread(), currentThread);
1196 // app's thread should be the current thread
1197 QCOMPARE(app.thread(), currentThread);
1199 // the thread should be running and not finished
1200 QVERIFY(currentThread->isRunning());
1201 QVERIFY(!currentThread->isFinished());
1203 // should still have a thread
1204 QVERIFY(object.thread() == currentThread);
1205 QVERIFY(child.thread() == currentThread);
1207 QTestEventLoop::instance().enterLoop(1);
1210 // app dead, current thread still valid
1211 QVERIFY(QThread::currentThread() != 0);
1212 QCOMPARE(QThread::currentThread(), currentThread);
1214 // the thread should still be running and not finished
1215 QVERIFY(currentThread->isRunning());
1216 QVERIFY(!currentThread->isFinished());
1218 // should still have a thread
1219 QVERIFY(object.thread() == currentThread);
1220 QVERIFY(child.thread() == currentThread);
1223 class DeleteLaterWidget : public QWidget
1227 DeleteLaterWidget(QApplication *_app, QWidget *parent = 0)
1228 : QWidget(parent) { app = _app; child_deleted = false; }
1235 void checkDeleteLater();
1236 void childDeleted() { child_deleted = true; }
1240 void DeleteLaterWidget::runTest()
1242 QObject *stillAlive = qFindChild<QObject*>(this, "deleteLater");
1244 QWidget *w = new QWidget(this);
1245 connect(w, SIGNAL(destroyed()), this, SLOT(childDeleted()));
1248 QVERIFY(!child_deleted);
1251 QTimer::singleShot(500, &dlg, SLOT(reject()));
1254 QVERIFY(!child_deleted);
1255 app->processEvents();
1256 QVERIFY(!child_deleted);
1258 QTimer::singleShot(500, this, SLOT(checkDeleteLater()));
1260 app->processEvents();
1262 QVERIFY(!stillAlive); // verify at the end to make test terminate
1265 void DeleteLaterWidget::checkDeleteLater()
1267 QVERIFY(child_deleted);
1272 void tst_QApplication::testDeleteLater()
1275 QSKIP("This test fails and then hangs on Mac OS X, see QTBUG-24318");
1278 QApplication app(argc, 0, QApplication::GuiServer);
1279 connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit()));
1281 DeleteLaterWidget *wgt = new DeleteLaterWidget(&app);
1282 QTimer::singleShot(500, wgt, SLOT(runTest()));
1284 QObject *object = new QObject(wgt);
1285 object->setObjectName("deleteLater");
1286 object->deleteLater();
1288 QObject *stillAlive = qFindChild<QObject*>(wgt, "deleteLater");
1289 QVERIFY(stillAlive);
1297 class EventLoopNester : public QObject
1301 void deleteLaterAndEnterLoop()
1303 QEventLoop eventLoop;
1304 QPointer<QObject> p(this);
1307 DeferredDelete events are compressed, meaning this second
1308 deleteLater() will *not* delete the object in the nested
1311 QMetaObject::invokeMethod(this, "deleteLater", Qt::QueuedConnection);
1312 QTimer::singleShot(1000, &eventLoop, SLOT(quit()));
1316 void deleteLaterAndExitLoop()
1318 // Check that 'p' is not deleted before exec returns, since the call
1319 // to QEventLoop::quit() should stop 'eventLoop' from processing
1320 // any more events (that is, delete later) until we return to the
1321 // _current_ event loop:
1322 QEventLoop eventLoop;
1323 QPointer<QObject> p(this);
1324 QMetaObject::invokeMethod(this, "deleteLater", Qt::QueuedConnection);
1325 QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
1327 QVERIFY(p); // not dead yet
1330 void processEventsOnly()
1332 QApplication::processEvents();
1334 void sendPostedEventsWithDeferredDelete()
1336 QApplication::sendPostedEvents(0, QEvent::DeferredDelete);
1339 void deleteLaterAndProcessEvents()
1341 QEventLoop eventLoop;
1343 QPointer<QObject> p = this;
1346 // trying to delete this object in a deeper eventloop just won't work
1347 QMetaObject::invokeMethod(this,
1348 "processEventsOnly",
1349 Qt::QueuedConnection);
1350 QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
1353 QMetaObject::invokeMethod(this,
1354 "sendPostedEventsWithDeferredDelete",
1355 Qt::QueuedConnection);
1356 QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
1360 // trying to delete it from this eventloop still doesn't work
1361 QApplication::processEvents();
1364 // however, it *will* work with this magic incantation
1365 QApplication::sendPostedEvents(0, QEvent::DeferredDelete);
1370 void tst_QApplication::testDeleteLaterProcessEvents()
1374 // Calling processEvents() with no event dispatcher does nothing.
1375 QObject *object = new QObject;
1376 QPointer<QObject> p(object);
1377 object->deleteLater();
1378 QApplication::processEvents();
1383 QApplication app(argc, 0, QApplication::GuiServer);
1384 // If you call processEvents() with an event dispatcher present, but
1385 // outside any event loops, deferred deletes are not processed unless
1386 // sendPostedEvents(0, DeferredDelete) is called.
1387 object = new QObject;
1389 object->deleteLater();
1390 app.processEvents();
1392 QApplication::sendPostedEvents(0, QEvent::DeferredDelete);
1395 // If you call deleteLater() on an object when there is no parent
1396 // event loop, and then enter an event loop, the object will get
1398 object = new QObject;
1400 object->deleteLater();
1402 QTimer::singleShot(1000, &loop, SLOT(quit()));
1407 // When an object is in an event loop, then calls deleteLater() and enters
1408 // an event loop recursively, it should not die until the parent event
1410 QApplication app(argc, 0, QApplication::GuiServer);
1412 EventLoopNester *nester = new EventLoopNester;
1414 QTimer::singleShot(3000, &loop, SLOT(quit()));
1415 QTimer::singleShot(0, nester, SLOT(deleteLaterAndEnterLoop()));
1422 // When the event loop that calls deleteLater() is exited
1423 // immediately, the object should die when returning to the
1424 // parent event loop
1425 QApplication app(argc, 0, QApplication::GuiServer);
1427 EventLoopNester *nester = new EventLoopNester;
1429 QTimer::singleShot(3000, &loop, SLOT(quit()));
1430 QTimer::singleShot(0, nester, SLOT(deleteLaterAndExitLoop()));
1437 // when the event loop that calls deleteLater() also calls
1438 // processEvents() immediately afterwards, the object should
1439 // not die until the parent loop continues
1440 QApplication app(argc, 0, QApplication::GuiServer);
1442 EventLoopNester *nester = new EventLoopNester();
1444 QTimer::singleShot(3000, &loop, SLOT(quit()));
1445 QTimer::singleShot(0, nester, SLOT(deleteLaterAndProcessEvents()));
1453 Test for crash with QApplication::setDesktopSettingsAware(false).
1455 void tst_QApplication::desktopSettingsAware()
1457 #ifndef QT_NO_PROCESS
1460 // We need an application object for QFINDTESTDATA to work
1461 // properly in all cases.
1463 QCoreApplication app(argc, 0);
1464 path = QFINDTESTDATA("desktopsettingsaware/");
1466 QVERIFY2(!path.isEmpty(), "Cannot locate desktopsettingsaware helper application");
1467 path += "desktopsettingsaware";
1470 QApplication tmpApp(argc, 0, QApplication::GuiServer);
1472 QProcess testProcess;
1473 testProcess.start(path);
1474 QVERIFY2(testProcess.waitForStarted(),
1475 qPrintable(QString::fromLatin1("Cannot start '%1': %2").arg(path, testProcess.errorString())));
1476 QVERIFY(testProcess.waitForFinished(10000));
1477 QCOMPARE(int(testProcess.state()), int(QProcess::NotRunning));
1478 QVERIFY(int(testProcess.error()) != int(QProcess::Crashed));
1482 void tst_QApplication::setActiveWindow()
1485 QApplication MyApp(argc, 0, QApplication::GuiServer);
1487 QWidget* w = new QWidget;
1488 QVBoxLayout* layout = new QVBoxLayout(w);
1490 QLineEdit* pb1 = new QLineEdit("Testbutton1", w);
1491 QLineEdit* pb2 = new QLineEdit("Test Line Edit", w);
1493 layout->addWidget(pb1);
1494 layout->addWidget(pb2);
1501 QApplication::setActiveWindow(w); // needs this on twm (focus follows mouse)
1502 QVERIFY(pb1->hasFocus());
1507 /* This might fail on some X11 window managers? */
1508 void tst_QApplication::focusChanged()
1511 QApplication app(argc, 0, QApplication::GuiServer);
1513 QSignalSpy spy(&app, SIGNAL(focusChanged(QWidget *, QWidget *)));
1518 QHBoxLayout hbox1(&parent1);
1519 QLabel lb1(&parent1);
1520 QLineEdit le1(&parent1);
1521 QPushButton pb1(&parent1);
1522 hbox1.addWidget(&lb1);
1523 hbox1.addWidget(&le1);
1524 hbox1.addWidget(&pb1);
1526 QCOMPARE(spy.count(), 0);
1529 QApplication::setActiveWindow(&parent1); // needs this on twm (focus follows mouse)
1530 QCOMPARE(spy.count(), 1);
1531 QCOMPARE(spy.at(0).count(), 2);
1532 old = qvariant_cast<QWidget*>(spy.at(0).at(0));
1533 now = qvariant_cast<QWidget*>(spy.at(0).at(1));
1534 QVERIFY(now == &le1);
1535 QVERIFY(now == QApplication::focusWidget());
1538 QCOMPARE(spy.count(), 0);
1541 QCOMPARE(spy.count(), 1);
1542 old = qvariant_cast<QWidget*>(spy.at(0).at(0));
1543 now = qvariant_cast<QWidget*>(spy.at(0).at(1));
1544 QVERIFY(now == &pb1);
1545 QVERIFY(now == QApplication::focusWidget());
1546 QVERIFY(old == &le1);
1550 QCOMPARE(spy.count(), 1);
1551 old = qvariant_cast<QWidget*>(spy.at(0).at(0));
1552 now = qvariant_cast<QWidget*>(spy.at(0).at(1));
1553 QVERIFY(now == &lb1);
1554 QVERIFY(now == QApplication::focusWidget());
1555 QVERIFY(old == &pb1);
1559 QCOMPARE(spy.count(), 1);
1560 old = qvariant_cast<QWidget*>(spy.at(0).at(0));
1561 now = qvariant_cast<QWidget*>(spy.at(0).at(1));
1563 QVERIFY(now == QApplication::focusWidget());
1564 QVERIFY(old == &lb1);
1568 QHBoxLayout hbox2(&parent2);
1569 QLabel lb2(&parent2);
1570 QLineEdit le2(&parent2);
1571 QPushButton pb2(&parent2);
1572 hbox2.addWidget(&lb2);
1573 hbox2.addWidget(&le2);
1574 hbox2.addWidget(&pb2);
1577 QApplication::setActiveWindow(&parent2); // needs this on twm (focus follows mouse)
1578 QVERIFY(spy.count() > 0); // one for deactivation, one for activation on Windows
1579 old = qvariant_cast<QWidget*>(spy.at(spy.count()-1).at(0));
1580 now = qvariant_cast<QWidget*>(spy.at(spy.count()-1).at(1));
1581 QVERIFY(now == &le2);
1582 QVERIFY(now == QApplication::focusWidget());
1586 QTestKeyEvent tab(QTest::Press, Qt::Key_Tab, 0, 0);
1587 QTestKeyEvent backtab(QTest::Press, Qt::Key_Backtab, 0, 0);
1588 QTestMouseEvent click(QTest::MouseClick, Qt::LeftButton, 0, QPoint(5, 5), 0);
1590 bool tabAllControls = true;
1592 // Mac has two modes, one where you tab to everything, one where you can
1593 // only tab to input controls, here's what we get. Determine which ones we
1595 QSettings appleSettings(QLatin1String("apple.com"));
1596 QVariant appleValue = appleSettings.value(QLatin1String("AppleKeyboardUIMode"), 0);
1597 tabAllControls = (appleValue.toInt() & 0x2);
1598 if (!tabAllControls) {
1599 QEXPECT_FAIL("", "QTBUG-24372 Mac tab key \"Text boxes and lists only\" vs "
1600 "\"All controls\" setting is not respected in Qt5", Abort);
1604 // make sure Qt's idea of tabbing between widgets matches what we think it should
1605 QCOMPARE(qt_tab_all_widgets, tabAllControls);
1608 if (!tabAllControls) {
1609 QVERIFY(spy.count() == 0);
1610 QVERIFY(now == QApplication::focusWidget());
1612 QVERIFY(spy.count() > 0);
1613 old = qvariant_cast<QWidget*>(spy.at(0).at(0));
1614 now = qvariant_cast<QWidget*>(spy.at(0).at(1));
1615 QVERIFY(now == &pb2);
1616 QVERIFY(now == QApplication::focusWidget());
1617 QVERIFY(old == &le2);
1621 if (!tabAllControls) {
1622 QVERIFY(spy.count() == 0);
1623 QVERIFY(now == QApplication::focusWidget());
1626 QVERIFY(spy.count() > 0);
1627 old = qvariant_cast<QWidget*>(spy.at(0).at(0));
1628 now = qvariant_cast<QWidget*>(spy.at(0).at(1));
1629 QVERIFY(now == &le2);
1630 QVERIFY(now == QApplication::focusWidget());
1631 QVERIFY(old == &pb2);
1635 if (!tabAllControls) {
1636 QVERIFY(spy.count() == 0);
1637 QVERIFY(now == QApplication::focusWidget());
1639 backtab.simulate(now);
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 == &pb2);
1644 QVERIFY(now == QApplication::focusWidget());
1645 QVERIFY(old == &le2);
1650 if (!tabAllControls) {
1651 QVERIFY(spy.count() == 0);
1652 QVERIFY(now == QApplication::focusWidget());
1655 backtab.simulate(now);
1656 QVERIFY(spy.count() > 0);
1657 old = qvariant_cast<QWidget*>(spy.at(0).at(0));
1658 now = qvariant_cast<QWidget*>(spy.at(0).at(1));
1659 QVERIFY(now == &le2);
1660 QVERIFY(now == QApplication::focusWidget());
1661 QVERIFY(old == &pb2);
1665 click.simulate(old);
1666 if (!(pb2.focusPolicy() & Qt::ClickFocus)) {
1667 QVERIFY(spy.count() == 0);
1668 QVERIFY(now == QApplication::focusWidget());
1670 QVERIFY(spy.count() > 0);
1671 old = qvariant_cast<QWidget*>(spy.at(0).at(0));
1672 now = qvariant_cast<QWidget*>(spy.at(0).at(1));
1673 QVERIFY(now == &pb2);
1674 QVERIFY(now == QApplication::focusWidget());
1675 QVERIFY(old == &le2);
1678 click.simulate(old);
1679 QVERIFY(spy.count() > 0);
1680 old = qvariant_cast<QWidget*>(spy.at(0).at(0));
1681 now = qvariant_cast<QWidget*>(spy.at(0).at(1));
1682 QVERIFY(now == &le2);
1683 QVERIFY(now == QApplication::focusWidget());
1684 QVERIFY(old == &pb2);
1688 parent1.activateWindow();
1689 QApplication::setActiveWindow(&parent1); // needs this on twm (focus follows mouse)
1690 QVERIFY(spy.count() == 1 || spy.count() == 2); // one for deactivation, one for activation on Windows
1692 //on windows, the change of focus is made in 2 steps
1693 //(the focusChanged SIGNAL is emitted twice)
1695 old = qvariant_cast<QWidget*>(spy.at(spy.count()-1).at(0));
1697 old = qvariant_cast<QWidget*>(spy.at(spy.count()-2).at(0));
1698 now = qvariant_cast<QWidget*>(spy.at(spy.count()-1).at(1));
1699 QVERIFY(now == &le1);
1700 QVERIFY(now == QApplication::focusWidget());
1701 QVERIFY(old == &le2);
1705 class LineEdit : public QLineEdit
1708 LineEdit(QWidget *parent = 0) : QLineEdit(parent) { }
1711 void focusOutEvent(QFocusEvent *e) {
1712 QLineEdit::focusOutEvent(e);
1713 if (objectName() == "le1")
1717 void focusInEvent(QFocusEvent *e) {
1718 QLineEdit::focusInEvent(e);
1719 if (objectName() == "le2")
1724 void tst_QApplication::focusOut()
1727 QApplication app(argc, &argv0, QApplication::GuiServer);
1729 // Tests the case where the style pointer changes when on focus in/out
1730 // (the above is the case when the stylesheet changes)
1732 QLineEdit *le1 = new LineEdit(&w);
1733 le1->setObjectName("le1");
1734 le1->setStyleSheet("background: #fee");
1737 QLineEdit *le2 = new LineEdit(&w);
1738 le2->setObjectName("le2");
1739 le2->setStyleSheet("background: #fee");
1740 le2->move(100, 100);
1748 void tst_QApplication::execAfterExit()
1751 QApplication app(argc, &argv0, QApplication::GuiServer);
1752 QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
1753 // this should be ignored, as exec() will reset the exitCode
1754 QApplication::exit(1);
1755 int exitCode = app.exec();
1756 QCOMPARE(exitCode, 0);
1758 // the quitNow flag should have been reset, so we can spin an
1759 // eventloop after QApplication::exec() returns
1760 QEventLoop eventLoop;
1761 QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
1762 exitCode = eventLoop.exec();
1763 QCOMPARE(exitCode, 0);
1766 void tst_QApplication::wheelScrollLines()
1769 QApplication app(argc, &argv0, QApplication::GuiServer);
1770 // If wheelScrollLines returns 0, the mose wheel will be disabled.
1771 QVERIFY(app.wheelScrollLines() > 0);
1774 void tst_QApplication::style()
1779 QApplication app(argc, &argv0, QApplication::GuiServer);
1780 QPointer<QStyle> style = app.style();
1781 app.setStyle(new QWindowsStyle);
1782 QVERIFY(style.isNull());
1785 QApplication app(argc, &argv0, QApplication::GuiServer);
1787 // qApp style can never be 0
1788 QVERIFY(QApplication::style() != 0);
1791 void tst_QApplication::allWidgets()
1794 QApplication app(argc, &argv0, QApplication::GuiServer);
1795 QWidget *w = new QWidget;
1796 QVERIFY(app.allWidgets().contains(w)); // uncreate widget test
1797 QVERIFY(app.allWidgets().contains(w)); // created widget test
1800 QVERIFY(!app.allWidgets().contains(w)); // removal test
1803 void tst_QApplication::topLevelWidgets()
1806 QApplication app(argc, &argv0, QApplication::GuiServer);
1807 QWidget *w = new QWidget;
1809 #ifndef QT_NO_CLIPBOARD
1810 QClipboard *clipboard = QApplication::clipboard();
1811 QString originalText = clipboard->text();
1812 clipboard->setText(QString("newText"));
1814 app.processEvents();
1815 QVERIFY(QApplication::topLevelWidgets().contains(w));
1816 QCOMPARE(QApplication::topLevelWidgets().count(), 1);
1819 app.processEvents();
1820 QCOMPARE(QApplication::topLevelWidgets().count(), 0);
1825 void tst_QApplication::setAttribute()
1828 QApplication app(argc, &argv0, QApplication::GuiServer);
1829 QVERIFY(!QApplication::testAttribute(Qt::AA_ImmediateWidgetCreation));
1830 QWidget *w = new QWidget;
1831 QVERIFY(!w->testAttribute(Qt::WA_WState_Created));
1834 QApplication::setAttribute(Qt::AA_ImmediateWidgetCreation);
1835 QVERIFY(QApplication::testAttribute(Qt::AA_ImmediateWidgetCreation));
1837 QVERIFY(w->testAttribute(Qt::WA_WState_Created));
1838 QWidget *w2 = new QWidget(w);
1840 QVERIFY(w2->testAttribute(Qt::WA_WState_Created));
1844 QApplication::setAttribute(Qt::AA_ImmediateWidgetCreation, false);
1845 QVERIFY(!QApplication::testAttribute(Qt::AA_ImmediateWidgetCreation));
1847 QVERIFY(!w->testAttribute(Qt::WA_WState_Created));
1851 void tst_QApplication::windowsCommandLine_data()
1853 #if defined(Q_OS_WIN)
1854 QTest::addColumn<QString>("args");
1855 QTest::addColumn<QString>("expected");
1857 QTest::newRow("hello world")
1858 << QString("Hello \"World\"")
1859 << QString("Hello \"World\"");
1860 QTest::newRow("sql")
1861 << QString("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'PNR' AND TABLE_TYPE = 'VIEW' ORDER BY TABLE_NAME")
1862 << QString("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'PNR' AND TABLE_TYPE = 'VIEW' ORDER BY TABLE_NAME");
1866 void tst_QApplication::windowsCommandLine()
1868 #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
1869 QFETCH(QString, args);
1870 QFETCH(QString, expected);
1872 QProcess testProcess;
1873 const QString path = QStringLiteral("wincmdline/wincmdline");
1874 testProcess.start(path, QStringList(args));
1875 QVERIFY2(testProcess.waitForStarted(),
1876 qPrintable(QString::fromLatin1("Cannot start '%1': %2").arg(path, testProcess.errorString())));
1877 QVERIFY(testProcess.waitForFinished(10000));
1878 QByteArray error = testProcess.readAllStandardError();
1879 QString procError(error);
1880 QCOMPARE(procError, expected);
1884 class TouchEventPropagationTestWidget : public QWidget
1889 bool seenTouchEvent, acceptTouchEvent, seenMouseEvent, acceptMouseEvent;
1891 TouchEventPropagationTestWidget(QWidget *parent = 0)
1892 : QWidget(parent), seenTouchEvent(false), acceptTouchEvent(false), seenMouseEvent(false), acceptMouseEvent(false)
1897 seenTouchEvent = acceptTouchEvent = seenMouseEvent = acceptMouseEvent = false;
1900 bool event(QEvent *event)
1902 switch (event->type()) {
1903 case QEvent::MouseButtonPress:
1904 case QEvent::MouseMove:
1905 case QEvent::MouseButtonRelease:
1906 // qDebug() << objectName() << "seenMouseEvent = true";
1907 seenMouseEvent = true;
1908 event->setAccepted(acceptMouseEvent);
1910 case QEvent::TouchBegin:
1911 case QEvent::TouchUpdate:
1912 case QEvent::TouchEnd:
1913 // qDebug() << objectName() << "seenTouchEvent = true";
1914 seenTouchEvent = true;
1915 event->setAccepted(acceptTouchEvent);
1918 return QWidget::event(event);
1924 void tst_QApplication::touchEventPropagation()
1927 QApplication app(argc, &argv0, QApplication::GuiServer);
1929 QList<QTouchEvent::TouchPoint> pressedTouchPoints;
1930 QTouchEvent::TouchPoint press(0);
1931 press.setState(Qt::TouchPointPressed);
1932 pressedTouchPoints << press;
1934 QList<QTouchEvent::TouchPoint> releasedTouchPoints;
1935 QTouchEvent::TouchPoint release(0);
1936 release.setState(Qt::TouchPointReleased);
1937 releasedTouchPoints << release;
1939 QTouchDevice *device = new QTouchDevice;
1940 device->setType(QTouchDevice::TouchScreen);
1941 QWindowSystemInterface::registerTouchDevice(device);
1944 // touch event behavior on a window
1945 TouchEventPropagationTestWidget window;
1946 window.setObjectName("1. window");
1947 window.show(); // Must have an explicitly specified QWindow for handleTouchEvent,
1948 // passing 0 would result in using topLevelAt() which is not ok in this case
1949 // as the screen position in the point is bogus.
1950 QVERIFY(QTest::qWaitForWindowExposed(&window));
1951 // QPA always takes screen positions and since we map the TouchPoint back to QPA's structure first,
1952 // we must ensure there is a screen position in the TouchPoint that maps to a local 0, 0.
1953 pressedTouchPoints[0].setScreenPos(window.mapToGlobal(QPoint(0, 0)));
1954 releasedTouchPoints[0].setScreenPos(window.mapToGlobal(QPoint(0, 0)));
1956 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
1959 touchPointList(pressedTouchPoints));
1960 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
1963 touchPointList(releasedTouchPoints));
1964 QCoreApplication::processEvents();
1965 QVERIFY(!window.seenTouchEvent);
1966 QVERIFY(window.seenMouseEvent); // Since QApplication transforms ignored touch events in mouse events
1969 window.setAttribute(Qt::WA_AcceptTouchEvents);
1970 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
1973 touchPointList(pressedTouchPoints));
1974 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
1977 touchPointList(releasedTouchPoints));
1978 QCoreApplication::processEvents();
1979 QVERIFY(window.seenTouchEvent);
1980 QVERIFY(window.seenMouseEvent);
1983 window.acceptTouchEvent = true;
1984 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
1987 touchPointList(pressedTouchPoints));
1988 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
1991 touchPointList(releasedTouchPoints));
1992 QCoreApplication::processEvents();
1993 QVERIFY(window.seenTouchEvent);
1994 QVERIFY(!window.seenMouseEvent);
1998 // touch event behavior on a window with a child widget
1999 TouchEventPropagationTestWidget window;
2000 window.setObjectName("2. window");
2001 TouchEventPropagationTestWidget widget(&window);
2002 widget.setObjectName("2. widget");
2004 QVERIFY(QTest::qWaitForWindowExposed(&window));
2005 pressedTouchPoints[0].setScreenPos(window.mapToGlobal(QPoint(0, 0)));
2006 releasedTouchPoints[0].setScreenPos(window.mapToGlobal(QPoint(0, 0)));
2008 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2011 touchPointList(pressedTouchPoints));
2012 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2015 touchPointList(releasedTouchPoints));
2016 QCoreApplication::processEvents();
2017 QVERIFY(!widget.seenTouchEvent);
2018 QVERIFY(widget.seenMouseEvent);
2019 QVERIFY(!window.seenTouchEvent);
2020 QVERIFY(window.seenMouseEvent);
2024 widget.setAttribute(Qt::WA_AcceptTouchEvents);
2025 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2028 touchPointList(pressedTouchPoints));
2029 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2032 touchPointList(releasedTouchPoints));
2033 QCoreApplication::processEvents();
2034 QVERIFY(widget.seenTouchEvent);
2035 QVERIFY(widget.seenMouseEvent);
2036 QVERIFY(!window.seenTouchEvent);
2037 QVERIFY(window.seenMouseEvent);
2041 widget.acceptMouseEvent = true;
2042 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2045 touchPointList(pressedTouchPoints));
2046 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2049 touchPointList(releasedTouchPoints));
2050 QCoreApplication::processEvents();
2051 QVERIFY(widget.seenTouchEvent);
2052 QVERIFY(widget.seenMouseEvent);
2053 QVERIFY(!window.seenTouchEvent);
2054 QVERIFY(!window.seenMouseEvent);
2058 widget.acceptTouchEvent = true;
2059 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2062 touchPointList(pressedTouchPoints));
2063 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2066 touchPointList(releasedTouchPoints));
2067 QCoreApplication::processEvents();
2068 QVERIFY(widget.seenTouchEvent);
2069 QVERIFY(!widget.seenMouseEvent);
2070 QVERIFY(!window.seenTouchEvent);
2071 QVERIFY(!window.seenMouseEvent);
2075 widget.setAttribute(Qt::WA_AcceptTouchEvents, false);
2076 window.setAttribute(Qt::WA_AcceptTouchEvents);
2077 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2080 touchPointList(pressedTouchPoints));
2081 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2084 touchPointList(releasedTouchPoints));
2085 QCoreApplication::processEvents();
2086 QVERIFY(!widget.seenTouchEvent);
2087 QVERIFY(widget.seenMouseEvent);
2088 QVERIFY(window.seenTouchEvent);
2089 QVERIFY(window.seenMouseEvent);
2093 window.acceptTouchEvent = true;
2094 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2097 touchPointList(pressedTouchPoints));
2098 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2101 touchPointList(releasedTouchPoints));
2102 QCoreApplication::processEvents();
2103 QVERIFY(!widget.seenTouchEvent);
2104 QVERIFY(widget.seenMouseEvent);
2105 QVERIFY(window.seenTouchEvent);
2106 QVERIFY(!window.seenMouseEvent);
2110 widget.acceptMouseEvent = true; // it matters, touch events are propagated in parallel to synthesized mouse events
2111 window.acceptTouchEvent = true;
2112 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2115 touchPointList(pressedTouchPoints));
2116 QWindowSystemInterface::handleTouchEvent(window.windowHandle(),
2119 touchPointList(releasedTouchPoints));
2120 QCoreApplication::processEvents();
2121 QVERIFY(!widget.seenTouchEvent);
2122 QVERIFY(widget.seenMouseEvent);
2123 QVERIFY(!window.seenTouchEvent);
2124 QVERIFY(!window.seenMouseEvent);
2128 void tst_QApplication::qtbug_12673()
2132 // We need an application object for QFINDTESTDATA to work
2133 // properly in all cases.
2135 QCoreApplication app(argc, 0);
2136 path = QFINDTESTDATA("modal/");
2138 QVERIFY2(!path.isEmpty(), "Cannot locate modal helper application");
2141 QProcess testProcess;
2142 QStringList arguments;
2143 testProcess.start(path, arguments);
2144 QVERIFY2(testProcess.waitForStarted(),
2145 qPrintable(QString::fromLatin1("Cannot start '%1': %2").arg(path, testProcess.errorString())));
2146 QVERIFY(testProcess.waitForFinished(20000));
2147 QCOMPARE(testProcess.exitStatus(), QProcess::NormalExit);
2150 class NoQuitOnHideWidget : public QWidget
2154 explicit NoQuitOnHideWidget(QWidget *parent = 0)
2157 QTimer::singleShot(0, this, SLOT(hide()));
2158 QTimer::singleShot(500, this, SLOT(exitApp()));
2167 void tst_QApplication::noQuitOnHide()
2170 QApplication app(argc, 0);
2171 QWidget *window1 = new NoQuitOnHideWidget;
2173 QCOMPARE(app.exec(), 1);
2176 class ShowCloseShowWidget : public QWidget
2180 ShowCloseShowWidget(bool showAgain, QWidget *parent = 0)
2181 : QWidget(parent), showAgain(showAgain)
2183 QTimer::singleShot(0, this, SLOT(doClose()));
2184 QTimer::singleShot(500, this, SLOT(exitApp()));
2202 void tst_QApplication::abortQuitOnShow()
2205 QApplication app(argc, 0);
2206 QWidget *window1 = new ShowCloseShowWidget(false);
2208 QCOMPARE(app.exec(), 0);
2210 QWidget *window2 = new ShowCloseShowWidget(true);
2212 QCOMPARE(app.exec(), 1);
2216 This test is meant to ensure that certain objects (public & commonly used)
2217 can safely be used in a Q_GLOBAL_STATIC such that their destructors are
2218 executed *after* the destruction of QApplication.
2220 Q_GLOBAL_STATIC(QLocale, tst_qapp_locale);
2221 Q_GLOBAL_STATIC(QProcess, tst_qapp_process);
2222 Q_GLOBAL_STATIC(QFileSystemWatcher, tst_qapp_fileSystemWatcher);
2223 #ifndef QT_NO_SHAREDMEMORY
2224 Q_GLOBAL_STATIC(QSharedMemory, tst_qapp_sharedMemory);
2226 Q_GLOBAL_STATIC(QElapsedTimer, tst_qapp_elapsedTimer);
2227 Q_GLOBAL_STATIC(QMutex, tst_qapp_mutex);
2228 Q_GLOBAL_STATIC(QWidget, tst_qapp_widget);
2229 Q_GLOBAL_STATIC(QPixmap, tst_qapp_pixmap);
2230 Q_GLOBAL_STATIC(QFont, tst_qapp_font);
2231 Q_GLOBAL_STATIC(QRegion, tst_qapp_region);
2232 Q_GLOBAL_STATIC(QFontDatabase, tst_qapp_fontDatabase);
2233 Q_GLOBAL_STATIC(QCursor, tst_qapp_cursor);
2235 void tst_QApplication::globalStaticObjectDestruction()
2238 QApplication app(argc, &argv0, QApplication::GuiServer);
2239 QVERIFY(tst_qapp_locale());
2240 QVERIFY(tst_qapp_process());
2241 QVERIFY(tst_qapp_fileSystemWatcher());
2242 #ifndef QT_NO_SHAREDMEMORY
2243 QVERIFY(tst_qapp_sharedMemory());
2245 QVERIFY(tst_qapp_elapsedTimer());
2246 QVERIFY(tst_qapp_mutex());
2247 QVERIFY(tst_qapp_widget());
2248 QVERIFY(tst_qapp_pixmap());
2249 QVERIFY(tst_qapp_font());
2250 QVERIFY(tst_qapp_region());
2251 QVERIFY(tst_qapp_fontDatabase());
2252 QVERIFY(tst_qapp_cursor());
2255 //QTEST_APPLESS_MAIN(tst_QApplication)
2256 int main(int argc, char *argv[])
2258 tst_QApplication tc;
2260 return QTest::qExec(&tc, argc, argv);
2263 #include "tst_qapplication.moc"