diff options
Diffstat (limited to 'tests')
33 files changed, 1379 insertions, 23 deletions
diff --git a/tests/auto/corelib/io/qurl/tst_qurl.cpp b/tests/auto/corelib/io/qurl/tst_qurl.cpp index 5b5161e24a..6d801f75c1 100644 --- a/tests/auto/corelib/io/qurl/tst_qurl.cpp +++ b/tests/auto/corelib/io/qurl/tst_qurl.cpp @@ -1179,6 +1179,12 @@ void tst_QUrl::toLocalFile_data() QTest::newRow("data0") << QString::fromLatin1("file:/a.txt") << QString::fromLatin1("/a.txt"); QTest::newRow("data4") << QString::fromLatin1("file:///a.txt") << QString::fromLatin1("/a.txt"); + QTest::newRow("data4a") << QString::fromLatin1("webdavs://somewebdavhost/somedir/somefile") +#ifdef Q_OS_WIN // QTBUG-42346, WebDAV is visible as local file on Windows only. + << QString::fromLatin1("//somewebdavhost@SSL/somedir/somefile"); +#else + << QString(); +#endif #ifdef Q_OS_WIN QTest::newRow("data5") << QString::fromLatin1("file:///c:/a.txt") << QString::fromLatin1("c:/a.txt"); #else @@ -1227,6 +1233,9 @@ void tst_QUrl::fromLocalFile_data() QTest::newRow("data3") << QString::fromLatin1("c:/a.txt") << QString::fromLatin1("file:///c:/a.txt") << QString::fromLatin1("/c:/a.txt"); QTest::newRow("data4") << QString::fromLatin1("//somehost/somedir/somefile") << QString::fromLatin1("file://somehost/somedir/somefile") << QString::fromLatin1("/somedir/somefile"); + QTest::newRow("data4a") << QString::fromLatin1("//somewebdavhost@SSL/somedir/somefile") + << QString::fromLatin1("webdavs://somewebdavhost/somedir/somefile") + << QString::fromLatin1("/somedir/somefile"); QTest::newRow("data5") << QString::fromLatin1("//somehost") << QString::fromLatin1("file://somehost") << QString::fromLatin1(""); QTest::newRow("data6") << QString::fromLatin1("//somehost/") << QString::fromLatin1("file://somehost/") diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp index ed84c111c6..38a274947f 100644 --- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp +++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp @@ -95,6 +95,7 @@ private slots: void changeFilter(); void changeSourceData_data(); void changeSourceData(); + void changeSourceDataKeepsStableSorting_qtbug1548(); void sortFilterRole(); void selectionFilteredOut(); void match_data(); @@ -2009,6 +2010,79 @@ void tst_QSortFilterProxyModel::changeSourceData() } } +// Checks that the model is a table, and that each and every row is like this: +// i-th row: ( rows.at(i), i ) +static void checkSortedTableModel(const QAbstractItemModel *model, const QStringList &rows) +{ + QCOMPARE(model->rowCount(), rows.length()); + QCOMPARE(model->columnCount(), 2); + + for (int row = 0; row < model->rowCount(); ++row) { + const QString column0 = model->index(row, 0).data().toString(); + const int column1 = model->index(row, 1).data().toString().toInt(); + + QCOMPARE(column0, rows.at(row)); + QCOMPARE(column1, row); + } +} + +void tst_QSortFilterProxyModel::changeSourceDataKeepsStableSorting_qtbug1548() +{ + // Check that emitting dataChanged from the source model + // for a change of a role which is not the sorting role + // doesn't alter the sorting. In this case, we sort on the DisplayRole, + // and play with other roles. + + static const QStringList rows + = QStringList() << "a" << "b" << "b" << "b" << "c" << "c" << "x"; + + // Build a table of pairs (string, #row) in each row + QStandardItemModel model(0, 2); + + for (int rowNumber = 0; rowNumber < rows.length(); ++rowNumber) { + QStandardItem *column0 = new QStandardItem(rows.at(rowNumber)); + column0->setCheckable(true); + column0->setCheckState(Qt::Unchecked); + + QStandardItem *column1 = new QStandardItem(QString::number(rowNumber)); + + const QList<QStandardItem *> row + = QList<QStandardItem *>() << column0 << column1; + + model.appendRow(row); + } + + checkSortedTableModel(&model, rows); + + // Build the proxy model + QSortFilterProxyModel proxy; + proxy.setSourceModel(&model); + proxy.setDynamicSortFilter(true); + proxy.sort(0); + + // The proxy is now sorted by the first column, check that the sorting + // * is correct (the input is already sorted, so it must not have changed) + // * was stable (by looking at the second column) + checkSortedTableModel(&model, rows); + + // Change the check status of an item. That must not break the stable sorting + // changes the middle "b" + model.item(2)->setCheckState(Qt::Checked); + checkSortedTableModel(&model, rows); + + // changes the starting "a" + model.item(0)->setCheckState(Qt::Checked); + checkSortedTableModel(&model, rows); + + // change the background color of the first "c" + model.item(4)->setBackground(Qt::red); + checkSortedTableModel(&model, rows); + + // change the background color of the second "c" + model.item(5)->setBackground(Qt::red); + checkSortedTableModel(&model, rows); +} + void tst_QSortFilterProxyModel::sortFilterRole() { QStandardItemModel model; diff --git a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp index 78c75b44e8..5833123dfe 100644 --- a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp +++ b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp @@ -642,18 +642,25 @@ struct CountedStruct QThread *thread; }; -static QEventLoop _e; +static QScopedPointer<QEventLoop> _e; static QThread *_t = Q_NULLPTR; class StaticEventLoop { public: - static void quitEventLoop() { _e.quit(); if (_t) QCOMPARE(QThread::currentThread(), _t); } + static void quitEventLoop() + { + QVERIFY(!_e.isNull()); + _e->quit(); + if (_t) + QCOMPARE(QThread::currentThread(), _t); + } }; void tst_QTimer::singleShotToFunctors() { int count = 0; + _e.reset(new QEventLoop); QEventLoop e; QTimer::singleShot(0, CountedStruct(&count)); @@ -661,7 +668,7 @@ void tst_QTimer::singleShotToFunctors() QCOMPARE(count, 1); QTimer::singleShot(0, &StaticEventLoop::quitEventLoop); - QCOMPARE(_e.exec(), 0); + QCOMPARE(_e->exec(), 0); QThread t1; QObject c1; @@ -687,7 +694,7 @@ void tst_QTimer::singleShotToFunctors() QCOMPARE(e.exec(), 0); QTimer::singleShot(0, &c2, &StaticEventLoop::quitEventLoop); - QCOMPARE(_e.exec(), 0); + QCOMPARE(_e->exec(), 0); _t->quit(); _t->wait(); @@ -721,8 +728,10 @@ void tst_QTimer::singleShotToFunctors() thread.quit(); thread.wait(); #endif -} + _e.reset(); + _t = Q_NULLPTR; +} class DontBlockEvents : public QObject { diff --git a/tests/auto/corelib/kernel/qvariant/qvariant.pro b/tests/auto/corelib/kernel/qvariant/qvariant.pro index f8d054f70c..39178ba9e6 100644 --- a/tests/auto/corelib/kernel/qvariant/qvariant.pro +++ b/tests/auto/corelib/kernel/qvariant/qvariant.pro @@ -6,3 +6,4 @@ INCLUDEPATH += $$PWD/../../../other/qvariant_common SOURCES = tst_qvariant.cpp RESOURCES += qvariant.qrc DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 +contains(QT_CONFIG, c++11): CONFIG += c++11 diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/tools/qstring/tst_qstring.cpp index 3edc9cc965..ea40c64c89 100644 --- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/tools/qstring/tst_qstring.cpp @@ -4389,6 +4389,28 @@ void tst_QString::section_data() << QString("o") << 1 << 2 << int(QString::SectionIncludeLeadingSep|QString::SectionIncludeTrailingSep) << QString("o1o2o") << false; + QTest::newRow( "range1" ) << QString("o1o2o") + << QString("o") << -5 << -5 + << int(QString::SectionIncludeLeadingSep|QString::SectionIncludeTrailingSep) + << QString() << false; + QTest::newRow( "range2" ) << QString("oo1o2o") + << QString("o") << -5 << 1 + << int(QString::SectionIncludeLeadingSep|QString::SectionIncludeTrailingSep + |QString::SectionSkipEmpty) + << QString("oo1o2o") << false; + QTest::newRow( "range3" ) << QString("o1o2o") + << QString("o") << 2 << 1 + << int(QString::SectionIncludeLeadingSep|QString::SectionIncludeTrailingSep) + << QString() << false; + QTest::newRow( "range4" ) << QString("o1o2o") + << QString("o") << 4 << 4 + << int(QString::SectionIncludeLeadingSep|QString::SectionIncludeTrailingSep) + << QString() << false; + QTest::newRow( "range5" ) << QString("o1oo2o") + << QString("o") << -2 << -1 + << int(QString::SectionIncludeLeadingSep|QString::SectionIncludeTrailingSep + |QString::SectionSkipEmpty) + << QString("o1oo2o") << false; QTest::newRow( "rx1" ) << QString("o1o2o") << QString("[a-z]") << 0 << 0 << int(QString::SectionIncludeLeadingSep|QString::SectionIncludeTrailingSep) diff --git a/tests/auto/gui/util/qdoublevalidator/tst_qdoublevalidator.cpp b/tests/auto/gui/util/qdoublevalidator/tst_qdoublevalidator.cpp index e08af2491d..a63183e5fc 100644 --- a/tests/auto/gui/util/qdoublevalidator/tst_qdoublevalidator.cpp +++ b/tests/auto/gui/util/qdoublevalidator/tst_qdoublevalidator.cpp @@ -59,30 +59,39 @@ void tst_QDoubleValidator::validateThouSep_data() { QTest::addColumn<QString>("localeName"); QTest::addColumn<QString>("value"); + QTest::addColumn<bool>("rejectGroupSeparator"); QTest::addColumn<QValidator::State>("result"); - QTest::newRow("1,000C") << "C" << QString("1,000") << ACC; - QTest::newRow("1.000C") << "C" << QString("1.000") << ACC; + QTest::newRow("1,000C") << "C" << QString("1,000") << false << ACC; + QTest::newRow("1,000.1C") << "C" << QString("1,000.1") << false << ACC; + QTest::newRow("1,000.1C_reject") << "C" << QString("1,000.1") << true << INV; + QTest::newRow("1.000C") << "C" << QString("1.000") << false << ACC; - QTest::newRow("1,000de") << "de" << QString("1,000") << ACC; - QTest::newRow("1.000de") << "de" << QString("1.000") << ACC; + QTest::newRow("1,000de") << "de" << QString("1,000") << false << ACC; + QTest::newRow("1.000de") << "de" << QString("1.000") << false << ACC; - QTest::newRow(".C") << "C" << QString(".") << ITM; - QTest::newRow(".de") << "de" << QString(".") << INV; - QTest::newRow(",C") << "C" << QString(",") << INV; - QTest::newRow(",de") << "de" << QString(",") << ITM; + QTest::newRow(".C") << "C" << QString(".") << false << ITM; + QTest::newRow(".de") << "de" << QString(".") << false << INV; + QTest::newRow("1.000,1de") << "de" << QString("1.000,1") << false << ACC; + QTest::newRow("1.000,1de_reject") << "de" << QString("1.000,1") << true << INV; + QTest::newRow(",C") << "C" << QString(",") << false << INV; + QTest::newRow(",de") << "de" << QString(",") << false << ITM; } void tst_QDoubleValidator::validateThouSep() { QFETCH(QString, localeName); QFETCH(QString, value); + QFETCH(bool, rejectGroupSeparator); QFETCH(QValidator::State, result); int dummy = 0; QDoubleValidator iv(-10000, 10000, 3, 0); iv.setNotation(QDoubleValidator::ScientificNotation); - iv.setLocale(QLocale(localeName)); + QLocale locale(localeName); + if (rejectGroupSeparator) + locale.setNumberOptions(QLocale::RejectGroupSeparator); + iv.setLocale(locale); QCOMPARE(iv.validate(value, dummy), result); } diff --git a/tests/auto/gui/util/qregularexpressionvalidator/tst_qregularexpressionvalidator.cpp b/tests/auto/gui/util/qregularexpressionvalidator/tst_qregularexpressionvalidator.cpp index 31853f7015..eff07ad07f 100644 --- a/tests/auto/gui/util/qregularexpressionvalidator/tst_qregularexpressionvalidator.cpp +++ b/tests/auto/gui/util/qregularexpressionvalidator/tst_qregularexpressionvalidator.cpp @@ -74,6 +74,9 @@ void tst_QRegularExpressionValidator::validate_data() QTest::newRow("data14") << QRegularExpression("\\w\\d\\d") << QString("E5") << QValidator::Intermediate; QTest::newRow("data15") << QRegularExpression("\\w\\d\\d") << QString("+9") << QValidator::Invalid; + QTest::newRow("emptystr1") << QRegularExpression("[T][e][s][t]") << QString("") << QValidator::Intermediate; + QTest::newRow("emptystr2") << QRegularExpression("[T][e][s][t]") << QString() << QValidator::Intermediate; + QTest::newRow("empty01") << QRegularExpression() << QString() << QValidator::Acceptable; QTest::newRow("empty02") << QRegularExpression() << QString("test") << QValidator::Acceptable; } diff --git a/tests/auto/network/access/qnetworkreply/BLACKLIST b/tests/auto/network/access/qnetworkreply/BLACKLIST index fbd72492d8..7792e05e0f 100644 --- a/tests/auto/network/access/qnetworkreply/BLACKLIST +++ b/tests/auto/network/access/qnetworkreply/BLACKLIST @@ -7,3 +7,6 @@ osx [SslHandshakeFailedError] osx [httpAbort] +* +[backgroundRequestInterruption:ftp, bg, nobg] +* diff --git a/tests/auto/network/socket/qsocks5socketengine/BLACKLIST b/tests/auto/network/socket/qsocks5socketengine/BLACKLIST new file mode 100644 index 0000000000..bf4afa8c45 --- /dev/null +++ b/tests/auto/network/socket/qsocks5socketengine/BLACKLIST @@ -0,0 +1,4 @@ +[udpTest] +* +[passwordAuth] +* diff --git a/tests/auto/network/ssl/ssl.pro b/tests/auto/network/ssl/ssl.pro index 0cf910df73..4e30a9cded 100644 --- a/tests/auto/network/ssl/ssl.pro +++ b/tests/auto/network/ssl/ssl.pro @@ -5,19 +5,21 @@ SUBDIRS=\ qsslerror \ qsslkey \ -contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked): +contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked) { contains(QT_CONFIG, private_tests) { SUBDIRS += \ qsslsocket \ qsslsocket_onDemandCertificates_member \ qsslsocket_onDemandCertificates_static \ } +} winrt: SUBDIRS -= \ qsslsocket_onDemandCertificates_member \ qsslsocket_onDemandCertificates_static \ -contains(QT_CONFIG, ssl) | contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked): +contains(QT_CONFIG, ssl) | contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked) { contains(QT_CONFIG, private_tests) { - SUBDIRS += qasn1element + SUBDIRS += qasn1element + } } diff --git a/tests/auto/opengl/qgl/tst_qgl.cpp b/tests/auto/opengl/qgl/tst_qgl.cpp index 0ba464a82c..56198ceb65 100644 --- a/tests/auto/opengl/qgl/tst_qgl.cpp +++ b/tests/auto/opengl/qgl/tst_qgl.cpp @@ -42,6 +42,8 @@ #include <qglcolormap.h> #include <qpaintengine.h> #include <qopenglfunctions.h> +#include <qopenglframebufferobject.h> +#include <qopenglpaintdevice.h> #include <QGraphicsView> #include <QGraphicsProxyWidget> @@ -78,6 +80,7 @@ private slots: void glWidgetRendering(); void glFBOSimpleRendering(); void glFBORendering(); + void currentFboSync(); void multipleFBOInterleavedRendering(); void glFBOUseInGLWidget(); void glPBufferRendering(); @@ -1138,6 +1141,93 @@ void tst_QGL::glFBORendering() qt_opengl_check_test_pattern(fb); } +class QOpenGLFramebufferObjectPaintDevice : public QOpenGLPaintDevice +{ +public: + QOpenGLFramebufferObjectPaintDevice(int width, int height) + : QOpenGLPaintDevice(width, height) + , m_fbo(width, height, QOpenGLFramebufferObject::CombinedDepthStencil) + { + } + + void ensureActiveTarget() + { + m_fbo.bind(); + } + + QImage toImage() const + { + return m_fbo.toImage(); + } + +private: + QOpenGLFramebufferObject m_fbo; +}; + +void tst_QGL::currentFboSync() +{ + if (!QGLFramebufferObject::hasOpenGLFramebufferObjects()) + QSKIP("QGLFramebufferObject not supported on this platform"); + +#if defined(Q_OS_QNX) + QSKIP("Reading the QGLFramebufferObject is unsupported on this platform"); +#endif + + QGLWidget glw; + glw.makeCurrent(); + + { + QGLFramebufferObject fbo1(256, 256, QGLFramebufferObject::CombinedDepthStencil); + + QOpenGLFramebufferObjectPaintDevice fbo2(256, 256); + + QImage sourceImage(256, 256, QImage::Format_ARGB32_Premultiplied); + QPainter sourcePainter(&sourceImage); + qt_opengl_draw_test_pattern(&sourcePainter, 256, 256); + + QPainter fbo1Painter(&fbo1); + + QPainter fbo2Painter(&fbo2); + fbo2Painter.drawImage(0, 0, sourceImage); + fbo2Painter.end(); + + QImage fbo2Image = fbo2.toImage(); + + fbo1Painter.drawImage(0, 0, sourceImage); + fbo1Painter.end(); + + QGLFramebufferObject::bindDefault(); + + QCOMPARE(fbo1.toImage(), fbo2Image); + } + + { + QGLFramebufferObject fbo1(512, 512, QGLFramebufferObject::CombinedDepthStencil); + + QOpenGLFramebufferObjectPaintDevice fbo2(256, 256); + + QImage sourceImage(256, 256, QImage::Format_ARGB32_Premultiplied); + QPainter sourcePainter(&sourceImage); + qt_opengl_draw_test_pattern(&sourcePainter, 256, 256); + + QPainter fbo2Painter(&fbo2); + fbo2Painter.drawImage(0, 0, sourceImage); + QImage fbo2Image1 = fbo2.toImage(); + fbo2Painter.fillRect(0, 0, 256, 256, Qt::white); + + QPainter fbo1Painter(&fbo1); + fbo1Painter.drawImage(0, 0, sourceImage); + fbo1Painter.end(); + + // check that the OpenGL paint engine now knows it needs to sync + fbo2Painter.drawImage(0, 0, sourceImage); + QImage fbo2Image2 = fbo2.toImage(); + + fbo2Painter.end(); + + QCOMPARE(fbo2Image1, fbo2Image2); + } +} // Tests multiple QPainters active on different FBOs at the same time, with // interleaving painting. Performance-wise, this is sub-optimal, but it still diff --git a/tests/auto/widgets/dialogs/qfiledialog2/qfiledialog2.pro b/tests/auto/widgets/dialogs/qfiledialog2/qfiledialog2.pro index 5239614fc7..fb432a7d21 100644 --- a/tests/auto/widgets/dialogs/qfiledialog2/qfiledialog2.pro +++ b/tests/auto/widgets/dialogs/qfiledialog2/qfiledialog2.pro @@ -20,4 +20,3 @@ wince* { DEFINES += SRCDIR=\\\"$$PWD/\\\" } -macx:CONFIG += insignificant_test # QTBUG-39183 diff --git a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp index 2ffb81a751..241e6d0e7e 100644 --- a/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp +++ b/tests/auto/widgets/dialogs/qfiledialog2/tst_qfiledialog2.cpp @@ -448,6 +448,8 @@ void tst_QFileDialog2::task180459_lastDirectory_data() void tst_QFileDialog2::task180459_lastDirectory() { + if (qApp->platformName().toLower() == QStringLiteral("cocoa")) + QSKIP("Insignificant on OSX"); //QTBUG-39183 //first visit the temp directory and close the dialog QNonNativeFileDialog *dlg = new QNonNativeFileDialog(0, "", tempDir.path()); QFileSystemModel *model = dlg->findChild<QFileSystemModel*>("qt_filesystem_model"); diff --git a/tests/auto/widgets/gestures/qgesturerecognizer/tst_qgesturerecognizer.cpp b/tests/auto/widgets/gestures/qgesturerecognizer/tst_qgesturerecognizer.cpp index 833494f25e..bdf610e426 100644 --- a/tests/auto/widgets/gestures/qgesturerecognizer/tst_qgesturerecognizer.cpp +++ b/tests/auto/widgets/gestures/qgesturerecognizer/tst_qgesturerecognizer.cpp @@ -71,6 +71,7 @@ tst_QGestureRecognizer::tst_QGestureRecognizer() : m_fingerDistance(qRound(QGuiApplication::primaryScreen()->physicalDotsPerInch() / 2.0)) , m_touchDevice(new QTouchDevice) { + qputenv("QT_PAN_TOUCHPOINTS", "2"); // Prevent device detection of pan touch point count. } void tst_QGestureRecognizer::initTestCase() diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/qgraphicsview.pro b/tests/auto/widgets/graphicsview/qgraphicsview/qgraphicsview.pro index 201085aecd..d1f9bede0b 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsview/qgraphicsview.pro +++ b/tests/auto/widgets/graphicsview/qgraphicsview/qgraphicsview.pro @@ -9,5 +9,4 @@ SOURCES += tst_qgraphicsview.cpp tst_qgraphicsview_2.cpp HEADERS += tst_qgraphicsview.h DEFINES += QT_NO_CAST_TO_ASCII -mac:CONFIG+=insignificant_test # QTBUG-26580 DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp index afd8be71e8..250790d9fa 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp @@ -143,6 +143,10 @@ class tst_QGraphicsView : public QObject { Q_OBJECT +public: + tst_QGraphicsView() + : platformName(qApp->platformName().toLower()) + { } private slots: void initTestCase(); void cleanup(); @@ -272,6 +276,7 @@ private: #if defined Q_OS_BLACKBERRY QScopedPointer<QWidget> rootWindow; #endif + QString platformName; }; void tst_QGraphicsView::initTestCase() @@ -2828,6 +2833,8 @@ void tst_QGraphicsView::scrollBarRanges() if (style == QLatin1String("GTK+") && useStyledPanel) QSKIP("GTK + style test skipped, see QTBUG-29002"); + if (useStyledPanel && style == QStringLiteral("Macintosh") && platformName == QStringLiteral("cocoa")) + QSKIP("Insignificant on OSX"); QGraphicsScene scene; QGraphicsView view(&scene); view.setRenderHint(QPainter::Antialiasing); @@ -4734,6 +4741,8 @@ public: void tst_QGraphicsView::hoverLeave() { + if (platformName == QStringLiteral("cocoa")) + QSKIP("Insignificant on OSX"); const QRect availableGeometry = QGuiApplication::primaryScreen()->availableGeometry(); QGraphicsScene scene; QGraphicsView view(&scene); diff --git a/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp b/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp index 766065acda..f000907e0e 100644 --- a/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp +++ b/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp @@ -782,10 +782,8 @@ void tst_QItemDelegate::dateTimeEditor() widget.setFocus(); widget.editItem(item2); - QTestEventLoop::instance().enterLoop(1); - + QTRY_VERIFY(widget.viewport()->findChild<QDateEdit *>()); QDateEdit *dateEditor = widget.viewport()->findChild<QDateEdit *>(); - QVERIFY(dateEditor); QCOMPARE(dateEditor->date(), date); dateEditor->setDate(date.addDays(60)); diff --git a/tests/auto/widgets/kernel/qaction/tst_qaction.cpp b/tests/auto/widgets/kernel/qaction/tst_qaction.cpp index 7904848faf..4b7e2a7198 100644 --- a/tests/auto/widgets/kernel/qaction/tst_qaction.cpp +++ b/tests/auto/widgets/kernel/qaction/tst_qaction.cpp @@ -61,6 +61,7 @@ private slots: void setText(); void setIconText_data() { setText_data(); } void setIconText(); + void setUnknownFont(); void actionEvent(); void setStandardKeys(); void alternateShortcuts(); @@ -184,6 +185,15 @@ void tst_QAction::setIconText() QCOMPARE(action.text(), textFromIconText); } +void tst_QAction::setUnknownFont() // QTBUG-42728 +{ + QAction action(0); + QFont font("DoesNotExist", 11); + action.setFont(font); + + QMenu menu; + menu.addAction(&action); // should not crash +} void tst_QAction::updateState(QActionEvent *e) { diff --git a/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp b/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp index 27c803b43d..751a16c59d 100644 --- a/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp +++ b/tests/auto/widgets/widgets/qmainwindow/tst_qmainwindow.cpp @@ -104,6 +104,7 @@ public: tst_QMainWindow(); private slots: + void cleanup(); void getSetCheck(); void constructor(); void iconSize(); @@ -147,6 +148,12 @@ private slots: void QTBUG21378_animationFinished(); }; + +void tst_QMainWindow::cleanup() +{ + QVERIFY(QApplication::topLevelWidgets().isEmpty()); +} + // Testing get/set functions void tst_QMainWindow::getSetCheck() { @@ -854,6 +861,7 @@ void tst_QMainWindow::takeCentralWidget() { QVERIFY(!w2.isNull()); QCOMPARE(w2.data(), hopefullyW2); + delete w2; } void tst_QMainWindow::corner() diff --git a/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp b/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp index f457955657..ff9bc7c4a2 100644 --- a/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp +++ b/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp @@ -104,7 +104,7 @@ static bool tabBetweenSubWindowsIn(QMdiArea *mdiArea, int tabCount = -1, bool re if (tabCount > 1) QTest::qWait(500); if (walkThrough) { - QRubberBand *rubberBand = mdiArea->viewport()->findChild<QRubberBand *>(); + QRubberBand *rubberBand = mdiArea->findChild<QRubberBand *>(); if (!rubberBand) { qWarning("No rubber band"); return false; diff --git a/tests/manual/diaglib/README.txt b/tests/manual/diaglib/README.txt new file mode 100644 index 0000000000..13387f5a2a --- /dev/null +++ b/tests/manual/diaglib/README.txt @@ -0,0 +1,34 @@ +This is a collection of functions and classes helpful for diagnosing bugs +in Qt 4 and Qt 5. It can be included in the application's .pro file by +adding: + +include([path to Qt sources]/tests/manual/diaglib/diaglib.pri) + +For Qt 4, the environment variable QTDIR may be used: +include($$(QTDIR)/tests/manual/diaglib/diaglib.pri) + +The .pri file adds the define QT_DIAG_LIB, so, diagnostic +code can be enlosed within #ifdef to work without it as well. + +All functions and classes are in the QtDiag namespace. + +class EventFilter (eventfilter.h): + An event filter that logs Qt events to qDebug() depending on + configured categories (for example mouse, keyboard, etc). + +function glInfo() (glinfo.h): + Returns a string describing the Open GL configuration (obtained + by querying GL_VENDOR and GL_RENDERER). Available only + when the QT qmake variable contains opengl. + +functions dumpNativeWindows(), dumpNativeQtTopLevels(): + These functions du,p out the hierarchy of native Windows. Currently + implemented for Windows only. + +function dumpAllWidgets() (qwidgetdump.h): + Dumps the hierarchy of QWidgets including information about flags, + visibility, geometry, etc. + +function dumpAllWindows() (qwindowdump.h): + Dumps the hierarchy of QWindows including information about flags, + visibility, geometry, etc. diff --git a/tests/manual/diaglib/diaglib.pri b/tests/manual/diaglib/diaglib.pri new file mode 100644 index 0000000000..138660f85e --- /dev/null +++ b/tests/manual/diaglib/diaglib.pri @@ -0,0 +1,43 @@ +INCLUDEPATH += $$PWD +SOURCES += \ + $$PWD/eventfilter.cpp \ + $$PWD/qwindowdump.cpp \ + +HEADERS += \ + $$PWD/eventfilter.h \ + $$PWD/qwindowdump.h \ + $$PWD/nativewindowdump.h + +win32 { + SOURCES += $$PWD/nativewindowdump_win.cpp + LIBS *= -luser32 +} else { + SOURCES += $$PWD/nativewindowdump.cpp +} + +greaterThan(QT_MAJOR_VERSION, 4) { + QT += gui-private core-private + contains(QT, widgets) { + HEADERS += \ + $$PWD/$$PWD/qwidgetdump.h + + SOURCES += \ + $$PWD/qwidgetdump.cpp + } +} else { + HEADERS += \ + $$PWD/$$PWD/qwidgetdump.h + + SOURCES += \ + $$PWD/qwidgetdump.cpp +} + +contains(QT, opengl) { +HEADERS += \ + $$PWD/glinfo.h + +SOURCES += \ + $$PWD/glinfo.cpp +} + +DEFINES += QT_DIAG_LIB diff --git a/tests/manual/diaglib/eventfilter.cpp b/tests/manual/diaglib/eventfilter.cpp new file mode 100644 index 0000000000..f0573975f6 --- /dev/null +++ b/tests/manual/diaglib/eventfilter.cpp @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "eventfilter.h" +#include <QtGui/QMouseEvent> +#include <QtCore/QDebug> +#include <QtCore/QTextStream> + +namespace QtDiag { + +EventFilter::EventFilter(EventCategories eventCategories, QObject *p) + : QObject(p) +{ + init(eventCategories); +} + +EventFilter::EventFilter(QObject *p) + : QObject(p) +{ + init(EventCategories(0xFFFFFFF)); +} + +void EventFilter::init(EventCategories eventCategories) +{ + if (eventCategories & MouseEvents) { + m_eventTypes << QEvent::MouseButtonPress << QEvent::MouseButtonRelease + << QEvent::MouseButtonDblClick << QEvent::NonClientAreaMouseButtonPress + << QEvent::NonClientAreaMouseButtonRelease + << QEvent::NonClientAreaMouseButtonDblClick + << QEvent::Enter << QEvent::Leave; + } + if (eventCategories & MouseMoveEvents) + m_eventTypes << QEvent::MouseMove << QEvent::NonClientAreaMouseMove; + if (eventCategories & TouchEvents) { + m_eventTypes << QEvent::TouchBegin << QEvent::TouchUpdate << QEvent::TouchEnd; +#if QT_VERSION >= 0x050000 + m_eventTypes << QEvent::TouchCancel; +#endif + } + if (eventCategories & TabletEvents) { + m_eventTypes << QEvent::TabletEnterProximity << QEvent::TabletLeaveProximity + << QEvent::TabletMove << QEvent::TabletPress << QEvent::TabletRelease; + } + if (eventCategories & DragAndDropEvents) { + m_eventTypes << QEvent::DragEnter << QEvent::DragMove << QEvent::DragLeave + << QEvent::Drop << QEvent::DragResponse; + } + if (eventCategories & KeyEvents) { + m_eventTypes << QEvent::KeyPress << QEvent::KeyRelease << QEvent::ShortcutOverride + << QEvent::Shortcut; + } + if (eventCategories & GeometryEvents) + m_eventTypes << QEvent::Move << QEvent::Resize; + if (eventCategories & PaintEvents) { + m_eventTypes << QEvent::UpdateRequest << QEvent::Paint + << QEvent::Show << QEvent::Hide; +#if QT_VERSION >= 0x050000 + m_eventTypes << QEvent::Expose; +#endif + } + if (eventCategories & TimerEvents) + m_eventTypes << QEvent::Timer << QEvent::ZeroTimerEvent; + if (eventCategories & ObjectEvents) { + m_eventTypes << QEvent::ChildAdded << QEvent::ChildPolished + << QEvent::ChildRemoved << QEvent::Create << QEvent::Destroy; + } +} + +bool EventFilter::eventFilter(QObject *o, QEvent *e) +{ + static int n = 0; + if (m_eventTypes.contains(e->type())) { + QDebug debug = qDebug().nospace(); + const QString on = o->objectName(); + debug << '#' << n++ << ' ' << o->metaObject()->className(); + if (!on.isEmpty()) + debug << '/' << on; + debug << ' ' << e; + } + return false; +} + +} // namespace QtDiag diff --git a/tests/manual/diaglib/eventfilter.h b/tests/manual/diaglib/eventfilter.h new file mode 100644 index 0000000000..d87ac68b07 --- /dev/null +++ b/tests/manual/diaglib/eventfilter.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef _EVENTFILTER_ +#define _EVENTFILTER_ + +#include <QtCore/QObject> +#include <QtCore/QEvent> +#include <QtCore/QList> + +namespace QtDiag { + +// Event filter that can for example be installed on QApplication +// to log relevant events. + +class EventFilter : public QObject { +public: + enum EventCategory { + MouseEvents = 0x00001, + MouseMoveEvents = 0x00002, + TouchEvents = 0x00004, + TabletEvents = 0x00008, + DragAndDropEvents = 0x00010, + KeyEvents = 0x00020, + GeometryEvents = 0x00040, + PaintEvents = 0x00080, + TimerEvents = 0x00100, + ObjectEvents = 0x00200 + }; + Q_DECLARE_FLAGS(EventCategories, EventCategory) + + explicit EventFilter(EventCategories eventCategories, QObject *p = 0); + explicit EventFilter(QObject *p = 0); + + bool eventFilter(QObject *, QEvent *); + +private: + void init(EventCategories eventCategories); + + QList<QEvent::Type> m_eventTypes; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(EventFilter::EventCategories) + +} // namespace QtDiag + +#endif diff --git a/tests/manual/diaglib/glinfo.cpp b/tests/manual/diaglib/glinfo.cpp new file mode 100644 index 0000000000..cd30e46b45 --- /dev/null +++ b/tests/manual/diaglib/glinfo.cpp @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "glinfo.h" + +#include <QtOpenGL/QGLFunctions> +#include <QtOpenGL/QGLWidget> +#if QT_VERSION > 0x050000 +# if QT_VERSION >= 0x050400 +# include <QtWidgets/QOpenGLWidget> +# include <QtGui/QOpenGLWindow> +# else // 5.4 +# include <QtGui/QWindow> +# endif // 5.0..5.4 +# include <QtGui/QOpenGLContext> +# include <QtGui/QOpenGLFunctions> +# include <QtGui/QWindow> +#endif +#include <QtCore/QDebug> +#include <QtCore/QString> +#include <QtCore/QTimer> + +namespace QtDiag { + +#if QT_VERSION > 0x050000 + +static QString getGlString(const QOpenGLContext *ctx, GLenum name) +{ + if (const GLubyte *p = ctx->functions()->glGetString(name)) + return QString::fromLatin1(reinterpret_cast<const char *>(p)); + return QString(); +} + +static QString glInfo(const QOpenGLContext *ctx) +{ + return getGlString(ctx, GL_VENDOR) + + QLatin1Char('\n') + + getGlString(ctx, GL_RENDERER); +} + +static QString glInfo(const QGLContext *ctx) +{ + return glInfo(ctx->contextHandle()); +} + +QString glInfo(const QObject *o) +{ +# if QT_VERSION >= 0x050400 + if (o->isWindowType()) { + if (const QOpenGLWindow *oglw = qobject_cast<const QOpenGLWindow *>(o)) + return glInfo(oglw->context()); + return QString(); + } +# endif // 5.4 + if (o->isWidgetType()) { + if (const QGLWidget *g = qobject_cast<const QGLWidget *>(o)) + return glInfo(g->context()); +# if QT_VERSION >= 0x050400 + if (const QOpenGLWidget *g = qobject_cast<const QOpenGLWidget *>(o)) + return glInfo(g->context()); +# endif // 5.4 + } + return QString(); +} + +#else // Qt4: + +static QString getGlString(GLenum name) +{ + if (const GLubyte *p = glGetString(name)) + return QString::fromLatin1(reinterpret_cast<const char *>(p)); + return QString(); +} + +QString glInfo(const QWidget *) +{ + return getGlString(GL_VENDOR) + QLatin1Char('\n') + getGlString(GL_RENDERER); +} + +#endif + +} // namespace QtDiag diff --git a/tests/manual/diaglib/glinfo.h b/tests/manual/diaglib/glinfo.h new file mode 100644 index 0000000000..1f515267f2 --- /dev/null +++ b/tests/manual/diaglib/glinfo.h @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef _GLINFO_ +#define _GLINFO_ + +#include <QtCore/QtGlobal> + +QT_FORWARD_DECLARE_CLASS(QObject) +QT_FORWARD_DECLARE_CLASS(QString) + +namespace QtDiag { + +QString glInfo(const QObject *o); + +} // namespace QtDiag + +#endif diff --git a/tests/manual/diaglib/nativewindowdump.cpp b/tests/manual/diaglib/nativewindowdump.cpp new file mode 100644 index 0000000000..a6c741a085 --- /dev/null +++ b/tests/manual/diaglib/nativewindowdump.cpp @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "nativewindowdump.h" + +namespace QtDiag { + +void dumpNativeWindows(WId) +{ +} + +void dumpNativeQtTopLevels() +{ +} + +} // namespace QtDiag diff --git a/tests/manual/diaglib/nativewindowdump.h b/tests/manual/diaglib/nativewindowdump.h new file mode 100644 index 0000000000..405998feea --- /dev/null +++ b/tests/manual/diaglib/nativewindowdump.h @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef _NATIVEWINDOWDUMP_ +#define _NATIVEWINDOWDUMP_ + +#include <QtGui/qwindowdefs.h> + +namespace QtDiag { + +void dumpNativeWindows(WId root = 0); +void dumpNativeQtTopLevels(); + +} // namespace QtDiag + +#endif diff --git a/tests/manual/diaglib/nativewindowdump_win.cpp b/tests/manual/diaglib/nativewindowdump_win.cpp new file mode 100644 index 0000000000..814b580f4b --- /dev/null +++ b/tests/manual/diaglib/nativewindowdump_win.cpp @@ -0,0 +1,207 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "nativewindowdump.h" +#include "qwindowdump.h" + +#include <QtCore/QTextStream> +#include <QtCore/QSharedPointer> +#include <QtCore/QDebug> +#include <QtCore/QVector> + +#include <QtCore/qt_windows.h> + +namespace QtDiag { + +struct DumpContext { + DumpContext() : indentation(0) {} + + int indentation; + QSharedPointer<QTextStream> stream; +}; + +#define debugWinStyle(str, style, styleConstant) \ +if (style & styleConstant) \ + str << ' ' << #styleConstant; + +static void formatNativeWindow(HWND hwnd, QTextStream &str) +{ + str << hex << showbase << quintptr(hwnd) << noshowbase << dec; + RECT rect; + if (GetWindowRect(hwnd, &rect)) { + str << ' ' << (rect.right - rect.left) << 'x' << (rect.bottom - rect.top) + << '+' << rect.left << '+' << rect.top; + } + if (IsWindowVisible(hwnd)) + str << " [visible]"; + + str << hex << showbase; + if (const LONG_PTR style = GetWindowLongPtr(hwnd, GWL_STYLE)) { + str << " style=" << style; + debugWinStyle(str, style, WS_OVERLAPPED) + debugWinStyle(str, style, WS_POPUP) + debugWinStyle(str, style, WS_MINIMIZE) + debugWinStyle(str, style, WS_CHILD) + debugWinStyle(str, style, WS_VISIBLE) + debugWinStyle(str, style, WS_DISABLED) + debugWinStyle(str, style, WS_CLIPSIBLINGS) + debugWinStyle(str, style, WS_CLIPCHILDREN) + debugWinStyle(str, style, WS_MAXIMIZE) + debugWinStyle(str, style, WS_CAPTION) + debugWinStyle(str, style, WS_BORDER) + debugWinStyle(str, style, WS_DLGFRAME) + debugWinStyle(str, style, WS_VSCROLL) + debugWinStyle(str, style, WS_HSCROLL) + debugWinStyle(str, style, WS_SYSMENU) + debugWinStyle(str, style, WS_THICKFRAME) + debugWinStyle(str, style, WS_GROUP) + debugWinStyle(str, style, WS_TABSTOP) + debugWinStyle(str, style, WS_MINIMIZEBOX) + debugWinStyle(str, style, WS_MAXIMIZEBOX) + } + if (const LONG_PTR exStyle = GetWindowLongPtr(hwnd, GWL_EXSTYLE)) { + str << " exStyle=" << exStyle; + debugWinStyle(str, exStyle, WS_EX_DLGMODALFRAME) + debugWinStyle(str, exStyle, WS_EX_NOPARENTNOTIFY) + debugWinStyle(str, exStyle, WS_EX_TOPMOST) + debugWinStyle(str, exStyle, WS_EX_ACCEPTFILES) + debugWinStyle(str, exStyle, WS_EX_TRANSPARENT) + debugWinStyle(str, exStyle, WS_EX_MDICHILD) + debugWinStyle(str, exStyle, WS_EX_TOOLWINDOW) + debugWinStyle(str, exStyle, WS_EX_WINDOWEDGE) + debugWinStyle(str, exStyle, WS_EX_CLIENTEDGE) + debugWinStyle(str, exStyle, WS_EX_CONTEXTHELP) + debugWinStyle(str, exStyle, WS_EX_RIGHT) + debugWinStyle(str, exStyle, WS_EX_LEFT) + debugWinStyle(str, exStyle, WS_EX_RTLREADING) + debugWinStyle(str, exStyle, WS_EX_LTRREADING) + debugWinStyle(str, exStyle, WS_EX_LEFTSCROLLBAR) + debugWinStyle(str, exStyle, WS_EX_RIGHTSCROLLBAR) + debugWinStyle(str, exStyle, WS_EX_CONTROLPARENT) + debugWinStyle(str, exStyle, WS_EX_STATICEDGE) + debugWinStyle(str, exStyle, WS_EX_APPWINDOW) + debugWinStyle(str, exStyle, WS_EX_LAYERED) + debugWinStyle(str, exStyle, WS_EX_NOINHERITLAYOUT) + debugWinStyle(str, exStyle, WS_EX_NOREDIRECTIONBITMAP) + debugWinStyle(str, exStyle, WS_EX_LAYOUTRTL) + debugWinStyle(str, exStyle, WS_EX_COMPOSITED) + debugWinStyle(str, exStyle, WS_EX_NOACTIVATE) + } + str << noshowbase << dec; + + wchar_t buf[512]; + if (GetWindowText(hwnd, buf, sizeof(buf)/sizeof(buf[0]))) + str << " title=\"" << QString::fromWCharArray(buf) << '"'; + if (GetClassName(hwnd, buf, sizeof(buf)/sizeof(buf[0]))) + str << " class=\"" << QString::fromWCharArray(buf) << '"'; + str << '\n'; +} + +static void dumpNativeWindowRecursion(HWND hwnd, DumpContext *dc); + +BOOL CALLBACK dumpWindowEnumChildProc(HWND hwnd, LPARAM lParam) +{ + dumpNativeWindowRecursion(hwnd, reinterpret_cast<DumpContext *>(lParam)); + return TRUE; +} + +static void dumpNativeWindowRecursion(HWND hwnd, DumpContext *dc) +{ + indentStream(*dc->stream, dc->indentation); + formatNativeWindow(hwnd, *dc->stream); + DumpContext nextLevel = *dc; + nextLevel.indentation += 2; + EnumChildWindows(hwnd, dumpWindowEnumChildProc, reinterpret_cast<LPARAM>(&nextLevel)); +} + +/* recurse by Z order, same result */ +static void dumpNativeWindowRecursionByZ(HWND hwnd, DumpContext *dc) +{ + indentStream(*dc->stream, dc->indentation); + formatNativeWindow(hwnd, *dc->stream); + if (const HWND topChild = GetTopWindow(hwnd)) { + DumpContext nextLevel = *dc; + nextLevel.indentation += 2; + for (HWND child = topChild; child ; child = GetNextWindow(child, GW_HWNDNEXT)) + dumpNativeWindowRecursionByZ(child, &nextLevel); + } +} + +typedef QVector<WId> WIdVector; + +static void dumpNativeWindows(const WIdVector& wins) +{ + DumpContext dc; + QString s; + dc.stream = QSharedPointer<QTextStream>(new QTextStream(&s)); + foreach (WId win, wins) + dumpNativeWindowRecursion(reinterpret_cast<HWND>(win), &dc); +#if QT_VERSION > 0x050000 + qDebug().noquote() << s; +#else + qDebug("%s", qPrintable(s)); +#endif +} + +void dumpNativeWindows(WId rootIn) +{ + const WId root = rootIn ? rootIn : reinterpret_cast<WId>(GetDesktopWindow()); + dumpNativeWindows(WIdVector(1, root)); +} + +BOOL CALLBACK findQtTopLevelEnumChildProc(HWND hwnd, LPARAM lParam) +{ + WIdVector *v = reinterpret_cast<WIdVector *>(lParam); + wchar_t buf[512]; + if (GetClassName(hwnd, buf, sizeof(buf)/sizeof(buf[0]))) { + if (wcsstr(buf, L"Qt")) + v->append(reinterpret_cast<WId>(hwnd)); + } + return TRUE; +} + +static WIdVector findQtTopLevels() +{ + WIdVector result; + EnumChildWindows(GetDesktopWindow(), + findQtTopLevelEnumChildProc, + reinterpret_cast<LPARAM>(&result)); + return result; +} + +void dumpNativeQtTopLevels() +{ + dumpNativeWindows(findQtTopLevels()); +} + +} // namespace QtDiag diff --git a/tests/manual/diaglib/qwidgetdump.cpp b/tests/manual/diaglib/qwidgetdump.cpp new file mode 100644 index 0000000000..d4f985c7c8 --- /dev/null +++ b/tests/manual/diaglib/qwidgetdump.cpp @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwidgetdump.h" + +#include <QWidget> +#if QT_VERSION > 0x050000 +# include <QtGui/QScreen> +# include <QtGui/QWindow> +#endif +#include <QApplication> +#include <QtCore/QMetaObject> +#include <QtCore/QDebug> +#include <QtCore/QTextStream> + +namespace QtDiag { + +static void dumpWidgetRecursion(QTextStream &str, const QWidget *w, + FormatWindowOptions options, int depth = 0) +{ + indentStream(str, 2 * depth); + formatObject(str, w); + str << ' ' << (w->isVisible() ? "[visible] " : "[hidden] "); + if (const WId nativeWinId = w->internalWinId()) + str << "[native: " << hex << showbase << nativeWinId << dec << noshowbase << "] "; + if (w->isWindow()) + str << "[top] "; + str << (w->testAttribute(Qt::WA_Mapped) ? "[mapped] " : "[not mapped] "); + if (w->testAttribute(Qt::WA_DontCreateNativeAncestors)) + str << "[NoNativeAncestors] "; + formatRect(str, w->geometry()); + if (!(options & DontPrintWindowFlags)) { + str << ' '; + formatWindowFlags(str, w->windowFlags()); + } + str << '\n'; +#if QT_VERSION > 0x050000 + if (const QWindow *win = w->windowHandle()) { + indentStream(str, 2 * (1 + depth)); + formatWindow(str, win, options); + str << '\n'; + } +#endif // Qt 5 + foreach (const QObject *co, w->children()) { + if (co->isWidgetType()) + dumpWidgetRecursion(str, static_cast<const QWidget *>(co), options, depth + 1); + } +} + +void dumpAllWidgets(FormatWindowOptions options) +{ + QString d; + QTextStream str(&d); + str << "### QWidgets:\n"; + foreach (QWidget *tw, QApplication::topLevelWidgets()) + dumpWidgetRecursion(str, tw, options); +#if QT_VERSION > 0x050000 + qDebug().noquote() << d; +#else + qDebug("%s", qPrintable(d)); +#endif +} + +} // namespace QtDiag diff --git a/tests/manual/diaglib/qwidgetdump.h b/tests/manual/diaglib/qwidgetdump.h new file mode 100644 index 0000000000..f9615b5d2f --- /dev/null +++ b/tests/manual/diaglib/qwidgetdump.h @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef _WIDGETDUMP_ +#define _WIDGETDUMP_ + +#include "qwindowdump.h" + +namespace QtDiag { + +void dumpAllWidgets(FormatWindowOptions options = 0); + +} // namespace QtDiag + +#endif diff --git a/tests/manual/diaglib/qwindowdump.cpp b/tests/manual/diaglib/qwindowdump.cpp new file mode 100644 index 0000000000..2ecc52ca77 --- /dev/null +++ b/tests/manual/diaglib/qwindowdump.cpp @@ -0,0 +1,176 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwindowdump.h" + +#if QT_VERSION > 0x050000 +# include <QtGui/QGuiApplication> +# include <QtGui/QScreen> +# include <QtGui/QWindow> +# include <qpa/qplatformwindow.h> +#endif +#include <QtCore/QMetaObject> +#include <QtCore/QRect> +#include <QtCore/QDebug> +#include <QtCore/QTextStream> + +namespace QtDiag { + +void indentStream(QTextStream &s, int indent) +{ + for (int i = 0; i < indent; ++i) + s << ' '; +} + +void formatObject(QTextStream &str, const QObject *o) +{ + str << o->metaObject()->className(); + const QString on = o->objectName(); + if (!on.isEmpty()) + str << "/\"" << on << '"'; +} + +void formatRect(QTextStream &str, const QRect &geom) +{ + str << geom.width() << 'x' << geom.height() + << forcesign << geom.x() << geom.y() << noforcesign; +} + +#define debugType(s, type, typeConstant) \ +if ((type & typeConstant) == typeConstant) \ + s << ' ' << #typeConstant; + +#define debugFlag(s, flags, flagConstant) \ +if (flags & flagConstant) \ + s << ' ' << #flagConstant; + +void formatWindowFlags(QTextStream &str, const Qt::WindowFlags flags) +{ + str << showbase << hex << unsigned(flags) << dec << noshowbase; + const Qt::WindowFlags windowType = flags & Qt::WindowType_Mask; + debugFlag(str, flags, Qt::Window) + debugType(str, windowType, Qt::Dialog) + debugType(str, windowType, Qt::Sheet) + debugType(str, windowType, Qt::Drawer) + debugType(str, windowType, Qt::Popup) + debugType(str, windowType, Qt::Tool) + debugType(str, windowType, Qt::ToolTip) + debugType(str, windowType, Qt::SplashScreen) + debugType(str, windowType, Qt::Desktop) + debugType(str, windowType, Qt::SubWindow) +#if QT_VERSION > 0x050000 + debugType(str, windowType, Qt::ForeignWindow) + debugType(str, windowType, Qt::CoverWindow) +#endif + debugFlag(str, flags, Qt::MSWindowsFixedSizeDialogHint) + debugFlag(str, flags, Qt::MSWindowsOwnDC) + debugFlag(str, flags, Qt::X11BypassWindowManagerHint) + debugFlag(str, flags, Qt::FramelessWindowHint) + debugFlag(str, flags, Qt::WindowTitleHint) + debugFlag(str, flags, Qt::WindowSystemMenuHint) + debugFlag(str, flags, Qt::WindowMinimizeButtonHint) + debugFlag(str, flags, Qt::WindowMaximizeButtonHint) + debugFlag(str, flags, Qt::WindowContextHelpButtonHint) + debugFlag(str, flags, Qt::WindowShadeButtonHint) + debugFlag(str, flags, Qt::WindowStaysOnTopHint) + debugFlag(str, flags, Qt::CustomizeWindowHint) +#if QT_VERSION > 0x050000 + debugFlag(str, flags, Qt::WindowTransparentForInput) + debugFlag(str, flags, Qt::WindowOverridesSystemGestures) + debugFlag(str, flags, Qt::WindowDoesNotAcceptFocus) + debugFlag(str, flags, Qt::NoDropShadowWindowHint) + debugFlag(str, flags, Qt::WindowFullscreenButtonHint) +#endif + debugFlag(str, flags, Qt::WindowStaysOnBottomHint) + debugFlag(str, flags, Qt::MacWindowToolBarButtonHint) + debugFlag(str, flags, Qt::BypassGraphicsProxyWidget) + debugFlag(str, flags, Qt::WindowOkButtonHint) + debugFlag(str, flags, Qt::WindowCancelButtonHint) +} + +#if QT_VERSION > 0x050000 + +void formatWindow(QTextStream &str, const QWindow *w, FormatWindowOptions options) +{ + const QPlatformWindow *pw = w->handle(); + formatObject(str, w); + str << ' ' << (w->isVisible() ? "[visible] " : "[hidden] "); + if (const WId nativeWinId = pw ? pw->winId() : WId(0)) + str << "[native: " << hex << showbase << nativeWinId << dec << noshowbase << "] "; + if (w->isTopLevel()) + str << "[top] "; + if (w->isExposed()) + str << "[exposed] "; + formatRect(str, w->geometry()); + if (!(options & DontPrintWindowFlags)) { + str << ' '; + formatWindowFlags(str, w->flags()); + } + str << '\n'; +} + +static void dumpWindowRecursion(QTextStream &str, const QWindow *w, + FormatWindowOptions options = 0, int depth = 0) +{ + indentStream(str, 2 * depth); + formatWindow(str, w); + foreach (const QObject *co, w->children()) { + if (co->isWindowType()) + dumpWindowRecursion(str, static_cast<const QWindow *>(co), options, depth + 1); + } +} + +void dumpAllWindows(FormatWindowOptions options) +{ + QString d; + QTextStream str(&d); + str << "### QWindows:\n"; + foreach (QWindow *w, QGuiApplication::topLevelWindows()) + dumpWindowRecursion(str, w, options); + qDebug().noquote() << d; +} + +#else // Qt 5 +class QWindow {}; + +void formatWindow(QTextStream &, const QWindow *, FormatWindowOptions) +{ +} + +void dumpAllWindows(FormatWindowOptions options) +{ +} + +#endif // Qt 4 + +} // namespace QtDiag diff --git a/tests/manual/diaglib/qwindowdump.h b/tests/manual/diaglib/qwindowdump.h new file mode 100644 index 0000000000..ab7c0243e9 --- /dev/null +++ b/tests/manual/diaglib/qwindowdump.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef _WINDOWDUMP_ +#define _WINDOWDUMP_ + +#include <QtCore/qnamespace.h> + +QT_FORWARD_DECLARE_CLASS(QRect) +QT_FORWARD_DECLARE_CLASS(QObject) +QT_FORWARD_DECLARE_CLASS(QWindow) +QT_FORWARD_DECLARE_CLASS(QTextStream) + +namespace QtDiag { + +enum FormatWindowOption { + DontPrintWindowFlags = 0x001 +}; + +Q_DECLARE_FLAGS(FormatWindowOptions, FormatWindowOption) +Q_DECLARE_OPERATORS_FOR_FLAGS(FormatWindowOptions) + +void indentStream(QTextStream &s, int indent); +void formatObject(QTextStream &str, const QObject *o); +void formatRect(QTextStream &str, const QRect &geom); +void formatWindowFlags(QTextStream &str, const Qt::WindowFlags flags); + +void formatWindow(QTextStream &str, const QWindow *w, FormatWindowOptions options = 0); +void dumpAllWindows(FormatWindowOptions options = 0); + +} // namespace QtDiag + +#endif |