diff options
author | Liang Qi <liang.qi@qt.io> | 2016-06-13 09:01:02 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2016-06-13 12:46:46 +0200 |
commit | 511790fd1af1e2886a0e2e8dd4308099705cd815 (patch) | |
tree | b42aee537a6103cd064f9f41ae2889b09b79fd23 /tests | |
parent | 1542d8881fc5ccbc5918cd4acbe4091ebbd24508 (diff) | |
parent | cbe332405aa22257d432f1797b325f5e57007c20 (diff) |
Merge remote-tracking branch 'origin/5.7' into dev
Conflicts:
config_help.txt
configure
mkspecs/features/uikit/sdk.prf
src/corelib/global/qhooks.cpp
src/corelib/io/qfilesystemwatcher.cpp
src/corelib/io/qlockfile_unix.cpp
src/corelib/tools/qalgorithms.h
src/gui/kernel/qwindowsysteminterface.h
src/gui/text/qtextdocument_p.cpp
src/network/access/access.pri
src/network/access/qnetworkaccessmanager.cpp
src/network/access/qnetworkreplynsurlconnectionimpl.mm
src/src.pro
src/testlib/qtestcase.cpp
src/widgets/kernel/qwidgetbackingstore_p.h
src/widgets/styles/qwindowscestyle.cpp
src/widgets/styles/qwindowsmobilestyle.cpp
tests/auto/corelib/io/qdiriterator/qdiriterator.pro
tests/auto/corelib/io/qfileinfo/qfileinfo.pro
tests/auto/gui/kernel/qwindow/BLACKLIST
tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp
tools/configure/configureapp.cpp
Change-Id: Ibf7fb9c8cf263a810ade82f821345d0725c57c67
Diffstat (limited to 'tests')
39 files changed, 995 insertions, 176 deletions
diff --git a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp index abec4e7aba..7147405f3b 100644 --- a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp +++ b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp @@ -359,14 +359,14 @@ void tst_QDebug::qDebugQChar() const MessageHandlerSetter mhs(myMessageHandler); { QDebug d = qDebug(); - d << QChar('f'); - d.nospace().noquote() << QChar('o') << QChar('o'); + d << QChar('f') << QChar(QLatin1Char('\xE4')); // f, ä + d.nospace().noquote() << QChar('o') << QChar('o') << QChar(QLatin1Char('\xC4')); // o, o, Ä } #ifndef QT_NO_MESSAGELOGCONTEXT file = __FILE__; line = __LINE__ - 5; function = Q_FUNC_INFO; #endif QCOMPARE(s_msgType, QtDebugMsg); - QCOMPARE(s_msg, QString::fromLatin1("'f' oo")); + QCOMPARE(s_msg, QString::fromLatin1("'f' '\\u00e4' oo\\u00c4")); QCOMPARE(QString::fromLatin1(s_file), file); QCOMPARE(s_line, line); QCOMPARE(QString::fromLatin1(s_function), function); diff --git a/tests/auto/corelib/io/qdir/qdir.pro b/tests/auto/corelib/io/qdir/qdir.pro index e5739f7e0a..4870922312 100644 --- a/tests/auto/corelib/io/qdir/qdir.pro +++ b/tests/auto/corelib/io/qdir/qdir.pro @@ -11,5 +11,3 @@ contains(CONFIG, builtin_testdata): DEFINES += BUILTIN_TESTDATA android { RESOURCES += android_testdata.qrc } - -win32: CONFIG += insignificant_test # Crashes on Windows in release builds diff --git a/tests/auto/corelib/io/qdir/tst_qdir.cpp b/tests/auto/corelib/io/qdir/tst_qdir.cpp index c450bad2de..294a53645e 100644 --- a/tests/auto/corelib/io/qdir/tst_qdir.cpp +++ b/tests/auto/corelib/io/qdir/tst_qdir.cpp @@ -207,6 +207,7 @@ private slots: void cdNonreadable(); + void cdBelowRoot_data(); void cdBelowRoot(); private: @@ -2220,31 +2221,37 @@ void tst_QDir::cdNonreadable() #endif } +void tst_QDir::cdBelowRoot_data() +{ + QTest::addColumn<QString>("rootPath"); + QTest::addColumn<QString>("cdInto"); + QTest::addColumn<QString>("targetPath"); + +#if defined(Q_OS_ANDROID) + QTest::newRow("android") << "/" << "system" << "/system"; +#elif defined(Q_OS_UNIX) + QTest::newRow("unix") << "/" << "tmp" << "/tmp"; +#elif defined(Q_OS_WINRT) + QTest::newRow("winrt") << QDir::rootPath() << QDir::rootPath() << QDir::rootPath(); +#else // Windows+CE + const QString systemDrive = QString::fromLocal8Bit(qgetenv("SystemDrive")) + QLatin1Char('/'); + const QString systemRoot = QString::fromLocal8Bit(qgetenv("SystemRoot")); + QTest::newRow("windows-drive") + << systemDrive << systemRoot.mid(3) << QDir::cleanPath(systemRoot); +#endif // Windows +} + void tst_QDir::cdBelowRoot() { -#if defined (Q_OS_ANDROID) -#define ROOT QString("/") -#define DIR QString("/system") -#define CD_INTO "system" -#elif defined (Q_OS_UNIX) -#define ROOT QString("/") -#define DIR QString("/tmp") -#define CD_INTO "tmp" -#elif defined (Q_OS_WINRT) -#define ROOT QDir::rootPath() -#define DIR QDir::rootPath() -#define CD_INTO QDir::rootPath() -#else -#define ROOT QString::fromLocal8Bit(qgetenv("SystemDrive"))+"/" -#define DIR QString::fromLocal8Bit(qgetenv("SystemRoot")).replace('\\', '/') -#define CD_INTO QString::fromLocal8Bit(qgetenv("SystemRoot")).mid(3) -#endif + QFETCH(QString, rootPath); + QFETCH(QString, cdInto); + QFETCH(QString, targetPath); - QDir root(ROOT); - QVERIFY(!root.cd("..")); - QCOMPARE(root.path(), ROOT); - QVERIFY(root.cd(CD_INTO)); - QCOMPARE(root.path(), DIR); + QDir root(rootPath); + QVERIFY2(!root.cd(".."), qPrintable(root.absolutePath())); + QCOMPARE(root.path(), rootPath); + QVERIFY(root.cd(cdInto)); + QCOMPARE(root.path(), targetPath); #ifdef Q_OS_UNIX if (::getuid() == 0) QSKIP("Running this test as root doesn't make sense"); @@ -2252,13 +2259,13 @@ void tst_QDir::cdBelowRoot() #ifdef Q_OS_WINRT QSKIP("WinRT has no concept of system root"); #endif - QDir dir(DIR); - QVERIFY(!dir.cd("../..")); - QCOMPARE(dir.path(), DIR); - QVERIFY(!dir.cd("../abs/../..")); - QCOMPARE(dir.path(), DIR); + QDir dir(targetPath); + QVERIFY2(!dir.cd("../.."), qPrintable(dir.absolutePath())); + QCOMPARE(dir.path(), targetPath); + QVERIFY2(!dir.cd("../abs/../.."), qPrintable(dir.absolutePath())); + QCOMPARE(dir.path(), targetPath); QVERIFY(dir.cd("..")); - QCOMPARE(dir.path(), ROOT); + QCOMPARE(dir.path(), rootPath); } QTEST_MAIN(tst_QDir) diff --git a/tests/auto/corelib/io/qdiriterator/qdiriterator.pro b/tests/auto/corelib/io/qdiriterator/qdiriterator.pro index b5ac614ad1..7c1f026bdb 100644 --- a/tests/auto/corelib/io/qdiriterator/qdiriterator.pro +++ b/tests/auto/corelib/io/qdiriterator/qdiriterator.pro @@ -6,5 +6,3 @@ RESOURCES += qdiriterator.qrc TESTDATA += entrylist contains(CONFIG, builtin_testdata): DEFINES += BUILTIN_TESTDATA - -win32: CONFIG += insignificant_test # Crashes on Windows in release builds diff --git a/tests/auto/corelib/io/qfileinfo/qfileinfo.pro b/tests/auto/corelib/io/qfileinfo/qfileinfo.pro index 8d443c27ec..48673b20a9 100644 --- a/tests/auto/corelib/io/qfileinfo/qfileinfo.pro +++ b/tests/auto/corelib/io/qfileinfo/qfileinfo.pro @@ -5,6 +5,4 @@ SOURCES = tst_qfileinfo.cpp RESOURCES += qfileinfo.qrc \ testdata.qrc -win32:!winrt:LIBS += -ladvapi32 -lnetapi32 - -win32: CONFIG += insignificant_test # Crashes on Windows in release builds +win32:!wince:!winrt:LIBS += -ladvapi32 -lnetapi32 diff --git a/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp b/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp index 921136e79b..9b46121981 100644 --- a/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp +++ b/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp @@ -29,6 +29,7 @@ #include <QtTest/QtTest> #include <qcoreapplication.h> #include <qstring.h> +#include <qtemporarydir.h> #include <qtemporaryfile.h> #include <qfile.h> #include <qdir.h> @@ -81,13 +82,15 @@ private slots: void QTBUG_4796(); void guaranteeUnique(); private: + QTemporaryDir m_temporaryDir; QString m_previousCurrent; }; void tst_QTemporaryFile::initTestCase() { + QVERIFY2(m_temporaryDir.isValid(), qPrintable(m_temporaryDir.errorString())); m_previousCurrent = QDir::currentPath(); - QDir::setCurrent(QDir::tempPath()); + QVERIFY(QDir::setCurrent(m_temporaryDir.path())); // For QTBUG_4796 QVERIFY(QDir("test-XXXXXX").exists() || QDir().mkdir("test-XXXXXX")); @@ -114,9 +117,6 @@ void tst_QTemporaryFile::initTestCase() void tst_QTemporaryFile::cleanupTestCase() { - // From QTBUG_4796 - QVERIFY(QDir().rmdir("test-XXXXXX")); - QDir::setCurrent(m_previousCurrent); } diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index d1d3738879..81d902ad20 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -129,11 +129,13 @@ private slots: void returnValue2_data(); void returnValue2(); void connectVirtualSlots(); + void connectSlotsVMIClass(); // VMI = Virtual or Multiple Inheritance void connectPrivateSlots(); void connectFunctorArgDifference(); void connectFunctorOverloads(); void connectFunctorQueued(); void connectFunctorWithContext(); + void connectFunctorWithContextUnique(); void connectFunctorDeadlock(); void connectStaticSlotWithObject(); void disconnectDoesNotLeakFunctor(); @@ -5602,6 +5604,112 @@ void tst_QObject::connectVirtualSlots() */ } +struct VirtualBase +{ + int virtual_base_count; + VirtualBase() : virtual_base_count(0) {} + virtual ~VirtualBase() {} + virtual void slot2() = 0; +}; + +class ObjectWithVirtualBase : public VirtualSlotsObject, public virtual VirtualBase +{ + Q_OBJECT +public: + ObjectWithVirtualBase() : regular_call_count(0), derived_counter2(0) {} + int regular_call_count; + int derived_counter2; + +public slots: + void regularSlot() { ++regular_call_count; } + virtual void slot1() { ++derived_counter2; } + virtual void slot2() { ++virtual_base_count; } +}; + +// VMI = Virtual or Multiple Inheritance +// (in this case, both) +void tst_QObject::connectSlotsVMIClass() +{ + // test connecting by the base + { + ObjectWithVirtualBase obj; + QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1, Qt::UniqueConnection)); + QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1, Qt::UniqueConnection)); + + emit obj.signal1(); + QCOMPARE(obj.base_counter1, 0); + QCOMPARE(obj.derived_counter1, 0); + QCOMPARE(obj.derived_counter2, 1); + QCOMPARE(obj.virtual_base_count, 0); + + QVERIFY(QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1)); + QVERIFY(!QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1)); + + emit obj.signal1(); + QCOMPARE(obj.base_counter1, 0); + QCOMPARE(obj.derived_counter1, 0); + QCOMPARE(obj.derived_counter2, 1); + QCOMPARE(obj.virtual_base_count, 0); + } + + // test connecting with the actual class + { + ObjectWithVirtualBase obj; + QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::regularSlot, Qt::UniqueConnection)); + QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::regularSlot, Qt::UniqueConnection)); + QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot1, Qt::UniqueConnection)); + QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot1, Qt::UniqueConnection)); + + emit obj.signal1(); + QCOMPARE(obj.base_counter1, 0); + QCOMPARE(obj.derived_counter1, 0); + QCOMPARE(obj.derived_counter2, 1); + QCOMPARE(obj.regular_call_count, 1); + QCOMPARE(obj.virtual_base_count, 0); + + QVERIFY( QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::regularSlot)); + QVERIFY(!QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::regularSlot)); + QVERIFY( QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot1)); + QVERIFY(!QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot1)); + + emit obj.signal1(); + QCOMPARE(obj.base_counter1, 0); + QCOMPARE(obj.derived_counter1, 0); + QCOMPARE(obj.derived_counter2, 1); + QCOMPARE(obj.regular_call_count, 1); + QCOMPARE(obj.virtual_base_count, 0); + + /* the C++ standard say the comparison between pointer to virtual member function is unspecified + QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1, Qt::UniqueConnection)); + QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot1, Qt::UniqueConnection)); + */ + } + + // test connecting a slot that is virtual from the virtual base + { + ObjectWithVirtualBase obj; + QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot2, Qt::UniqueConnection)); + QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot2, Qt::UniqueConnection)); + + emit obj.signal1(); + QCOMPARE(obj.base_counter1, 0); + QCOMPARE(obj.derived_counter1, 0); + QCOMPARE(obj.derived_counter2, 0); + QCOMPARE(obj.virtual_base_count, 1); + QCOMPARE(obj.regular_call_count, 0); + + QVERIFY( QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot2)); + QVERIFY(!QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot2)); + + emit obj.signal1(); + QCOMPARE(obj.base_counter1, 0); + QCOMPARE(obj.derived_counter1, 0); + QCOMPARE(obj.derived_counter2, 0); + QCOMPARE(obj.virtual_base_count, 1); + QCOMPARE(obj.regular_call_count, 0); + } +} + #ifndef QT_BUILD_INTERNAL void tst_QObject::connectPrivateSlots() {QSKIP("Needs QT_BUILD_INTERNAL");} @@ -5888,6 +5996,22 @@ void tst_QObject::deleteLaterInAboutToBlockHandler() QCOMPARE(statusAboutToBlock, 2); } +void tst_QObject::connectFunctorWithContextUnique() +{ + // Qt::UniqueConnections currently don't work for functors, but we need to + // be sure that they don't crash. If that is implemented, change this test. + + SenderObject sender; + ReceiverObject receiver; + QObject::connect(&sender, &SenderObject::signal1, &receiver, &ReceiverObject::slot1); + receiver.count_slot1 = 0; + + QObject::connect(&sender, &SenderObject::signal1, &receiver, SlotFunctor(), Qt::UniqueConnection); + + sender.emitSignal1(); + QCOMPARE(receiver.count_slot1, 1); +} + class MyFunctor { public: diff --git a/tests/auto/corelib/plugin/qplugin/qplugin.pro b/tests/auto/corelib/plugin/qplugin/qplugin.pro index 918ffb44bd..5283c2d52b 100644 --- a/tests/auto/corelib/plugin/qplugin/qplugin.pro +++ b/tests/auto/corelib/plugin/qplugin/qplugin.pro @@ -1,27 +1,17 @@ -QT = core TEMPLATE = subdirs +TESTPLUGINS = + win32 { - exists($$[QT_INSTALL_LIBS/get]/QtCore4.dll) { - SUBDIRS = releaseplugin - } - exists($$[QT_INSTALL_LIBS/get]/QtCored4.dll) { - SUBDIRS += debugplugin - } -} -mac { - CONFIG(debug, debug|release): { - SUBDIRS += debugplugin - tst_qplugin_pro.depends += debugplugin - } - CONFIG(release, debug|release): { - SUBDIRS += releaseplugin - tst_qplugin_pro.depends += releaseplugin - } + contains(QT_CONFIG, debug): TESTPLUGINS += debugplugin + contains(QT_CONFIG, release): TESTPLUGINS += releaseplugin +} else:osx { + CONFIG(debug, debug|release): TESTPLUGINS += debugplugin + CONFIG(release, debug|release): TESTPLUGINS += releaseplugin +} else { + TESTPLUGINS = debugplugin releaseplugin } -!win32:!mac:{ - SUBDIRS = debugplugin releaseplugin - tst_qplugin_pro.depends += debugplugin releaseplugin -} -SUBDIRS += tst_qplugin.pro +SUBDIRS += main $$TESTPLUGINS +main.file = tst_qplugin.pro +main.depends = $$TESTPLUGINS diff --git a/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp b/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp index 586a4446b4..88c505601a 100644 --- a/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp +++ b/tests/auto/corelib/tools/qbytearray/tst_qbytearray.cpp @@ -104,7 +104,7 @@ private slots: void number(); void toInt_data(); void toInt(); - void qAllocMore(); + void blockSizeCalculations(); void resizeAfterFromRawData(); void appendAfterFromRawData(); @@ -1334,28 +1334,80 @@ void tst_QByteArray::toULongLong() QCOMPARE(b, ok); } -// global function defined in qbytearray.cpp -void tst_QByteArray::qAllocMore() +static bool checkSize(size_t value, uint min) { - using QT_PREPEND_NAMESPACE(qAllocMore); + return value >= min && value <= INT_MAX; +} +// global functions defined in qbytearray.cpp +void tst_QByteArray::blockSizeCalculations() +{ // Not very important, but please behave :-) - QVERIFY(qAllocMore(0, 0) >= 0); - - for (int i = 1; i < 1 << 8; i <<= 1) - QVERIFY(qAllocMore(i, 0) >= i); - - for (int i = 1 << 8; i < 1 << 30; i <<= 1) { - const int alloc = qAllocMore(i, 0); + QCOMPARE(qCalculateBlockSize(0, 1), size_t(0)); + QVERIFY(qCalculateGrowingBlockSize(0, 1).size <= MaxAllocSize); + QVERIFY(qCalculateGrowingBlockSize(0, 1).elementCount <= MaxAllocSize); + + // boundary condition + QCOMPARE(qCalculateBlockSize(MaxAllocSize, 1), size_t(MaxAllocSize)); + QCOMPARE(qCalculateBlockSize(MaxAllocSize/2, 2), size_t(MaxAllocSize) - 1); + QCOMPARE(qCalculateBlockSize(MaxAllocSize/2, 2, 1), size_t(MaxAllocSize)); + QCOMPARE(qCalculateGrowingBlockSize(MaxAllocSize, 1).size, size_t(MaxAllocSize)); + QCOMPARE(qCalculateGrowingBlockSize(MaxAllocSize, 1).elementCount, size_t(MaxAllocSize)); + QCOMPARE(qCalculateGrowingBlockSize(MaxAllocSize/2, 2, 1).size, size_t(MaxAllocSize)); + QCOMPARE(qCalculateGrowingBlockSize(MaxAllocSize/2, 2, 1).elementCount, size_t(MaxAllocSize)/2); + + // error conditions + QCOMPARE(qCalculateBlockSize(uint(MaxAllocSize) + 1, 1), size_t(~0)); + QCOMPARE(qCalculateBlockSize(size_t(-1), 1), size_t(~0)); + QCOMPARE(qCalculateBlockSize(MaxAllocSize, 1, 1), size_t(~0)); + QCOMPARE(qCalculateBlockSize(MaxAllocSize/2 + 1, 2), size_t(~0)); + QCOMPARE(qCalculateGrowingBlockSize(uint(MaxAllocSize) + 1, 1).size, size_t(~0)); + QCOMPARE(qCalculateGrowingBlockSize(MaxAllocSize/2 + 1, 2).size, size_t(~0)); + + // overflow conditions + // on 32-bit platforms, (1 << 16) * (1 << 16) = (1 << 32) which is zero + QCOMPARE(qCalculateBlockSize(1 << 16, 1 << 16), size_t(~0)); + QCOMPARE(qCalculateBlockSize(MaxAllocSize/4, 16), size_t(~0)); + // on 32-bit platforms, (1 << 30) * 3 + (1 << 30) would overflow to zero + QCOMPARE(qCalculateBlockSize(1U << 30, 3, 1U << 30), size_t(~0)); + + // exact block sizes + for (int i = 1; i < 1 << 31; i <<= 1) { + QCOMPARE(qCalculateBlockSize(0, 1, i), size_t(i)); + QCOMPARE(qCalculateBlockSize(i, 1), size_t(i)); + QCOMPARE(qCalculateBlockSize(i + i/2, 1), size_t(i + i/2)); + } + for (int i = 1; i < 1 << 30; i <<= 1) { + QCOMPARE(qCalculateBlockSize(i, 2), 2 * size_t(i)); + QCOMPARE(qCalculateBlockSize(i, 2, 1), 2 * size_t(i) + 1); + QCOMPARE(qCalculateBlockSize(i, 2, 16), 2 * size_t(i) + 16); + } - QVERIFY(alloc >= i); - QCOMPARE(qAllocMore(i - 8, 8), alloc - 8); - QCOMPARE(qAllocMore(i - 16, 16), alloc - 16); - QCOMPARE(qAllocMore(i - 24, 24), alloc - 24); - QCOMPARE(qAllocMore(i - 32, 32), alloc - 32); + // growing sizes + for (int i = 1; i < 1 << 31; i <<= 1) { + QVERIFY(checkSize(qCalculateGrowingBlockSize(i, 1).size, i)); + QVERIFY(checkSize(qCalculateGrowingBlockSize(i, 1).elementCount, i)); + QVERIFY(checkSize(qCalculateGrowingBlockSize(i, 1, 16).size, i)); + QVERIFY(checkSize(qCalculateGrowingBlockSize(i, 1, 16).elementCount, i)); + QVERIFY(checkSize(qCalculateGrowingBlockSize(i, 1, 24).size, i)); + QVERIFY(checkSize(qCalculateGrowingBlockSize(i, 1, 16).elementCount, i)); + } - QVERIFY(qAllocMore(i - 1, 0) >= i - 1); - QVERIFY(qAllocMore(i + 1, 0) >= i + 1); + // growth should be limited + for (int elementSize = 1; elementSize < (1<<8); elementSize <<= 1) { + size_t alloc = 1; + forever { + QVERIFY(checkSize(qCalculateGrowingBlockSize(alloc, elementSize).size, alloc * elementSize)); + size_t newAlloc = qCalculateGrowingBlockSize(alloc, elementSize).elementCount; + QVERIFY(checkSize(newAlloc, alloc)); + if (newAlloc == alloc) + break; // no growth, we're at limit + alloc = newAlloc; + } + QVERIFY(checkSize(alloc, size_t(MaxAllocSize) / elementSize)); + + // the next allocation should be invalid + QCOMPARE(qCalculateGrowingBlockSize(alloc + 1, elementSize).size, size_t(~0)); } } diff --git a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp b/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp index 9fd418742c..c631b395f8 100644 --- a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp +++ b/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp @@ -842,6 +842,16 @@ void tst_QTimeZone::tzTest() QTzTimeZonePrivate::Data datatz2 = tztz2.data(std); QTzTimeZonePrivate::Data datautc2 = tzutc2.data(std); QCOMPARE(datatz2.offsetFromUtc, datautc2.offsetFromUtc); + + // Test a timezone with a name that isn't all letters + QTzTimeZonePrivate tzBarnaul("Asia/Barnaul"); + if (tzBarnaul.isValid()) { + QCOMPARE(tzBarnaul.data(std).abbreviation, QString("+07")); + + // first full day of the new rule (tzdata2016b) + QDateTime dt(QDate(2016, 3, 28), QTime(0, 0, 0), Qt::UTC); + QCOMPARE(tzBarnaul.data(dt.toMSecsSinceEpoch()).abbreviation, QString("+07")); + } #endif // Q_OS_UNIX } diff --git a/tests/auto/corelib/xml/qxmlstream/tst_qxmlstream.cpp b/tests/auto/corelib/xml/qxmlstream/tst_qxmlstream.cpp index 8a153a4599..26d443c2c6 100644 --- a/tests/auto/corelib/xml/qxmlstream/tst_qxmlstream.cpp +++ b/tests/auto/corelib/xml/qxmlstream/tst_qxmlstream.cpp @@ -556,6 +556,7 @@ private slots: void checkCommentIndentation() const; void checkCommentIndentation_data() const; void crashInXmlStreamReader() const; + void write8bitCodec() const; void hasError() const; private: @@ -1576,5 +1577,43 @@ void tst_QXmlStream::hasError() const } +void tst_QXmlStream::write8bitCodec() const +{ + QBuffer outBuffer; + QVERIFY(outBuffer.open(QIODevice::WriteOnly)); + QXmlStreamWriter writer(&outBuffer); + writer.setAutoFormatting(false); + + QTextCodec *codec = QTextCodec::codecForName("IBM500"); + if (!codec) { + QSKIP("Encoding IBM500 not available."); + } + writer.setCodec(codec); + + writer.writeStartDocument(); + writer.writeStartElement("root"); + writer.writeAttribute("attrib", "1"); + writer.writeEndElement(); + writer.writeEndDocument(); + outBuffer.close(); + + // test 8 bit encoding + QByteArray values = outBuffer.data(); + QVERIFY(values.size() > 1); + // check '<' + QCOMPARE(values[0] & 0x00FF, 0x4c); + // check '?' + QCOMPARE(values[1] & 0x00FF, 0x6F); + + // convert the start of the XML + const QString expected = ("<?xml version=\"1.0\" encoding=\"IBM500\"?>"); + QTextDecoder *decoder = codec->makeDecoder(); + QVERIFY(decoder); + QString decodedText = decoder->toUnicode(values); + delete decoder; + QVERIFY(decodedText.startsWith(expected)); +} + + #include "tst_qxmlstream.moc" // vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp index 851ef6cc1f..4a09dca544 100644 --- a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp +++ b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp @@ -35,6 +35,11 @@ #include <QtTest/QtTest> #include <QtDBus/QtDBus> +#ifdef Q_OS_UNIX +# include <sys/types.h> +# include <signal.h> +#endif + void MyObject::method(const QDBusMessage &msg) { path = msg.path(); @@ -1352,23 +1357,39 @@ void tst_QDBusConnection::callVirtualObjectLocal() void tst_QDBusConnection::pendingCallWhenDisconnected() { +#ifdef QT_NO_PROCESS + QSKIP("Test requires QProcess"); +#else if (!QCoreApplication::instance()) QSKIP("Test requires a QCoreApplication"); - QDBusServer *server = new QDBusServer; - QDBusConnection con = QDBusConnection::connectToPeer(server->address(), "disconnect"); - QTestEventLoop::instance().enterLoop(2); - QVERIFY(con.isConnected()); - QDBusMessage message = QDBusMessage::createMethodCall("", "/", QString(), "method"); - QDBusPendingCall reply = con.asyncCall(message); + QProcess daemon; + daemon.start("dbus-daemon", QStringList() << "--session" << "--nofork" << "--print-address"); + QVERIFY2(daemon.waitForReadyRead(2000), + "Daemon didn't print its address in time; error: \"" + daemon.errorString().toLocal8Bit() + + "\"; stderr:\n" + daemon.readAllStandardError()); - delete server; + QString address = QString::fromLocal8Bit(daemon.readAll().trimmed()); + QDBusConnection con = QDBusConnection::connectToBus(address, "disconnect"); + QVERIFY2(con.isConnected(), (con.lastError().name() + ": " + con.lastError().message()).toLocal8Bit()); - QTestEventLoop::instance().enterLoop(2); + // confirm we're connected and we're alone in this bus + QCOMPARE(con.baseService(), QString(":1.0")); + + // kill the bus + daemon.terminate(); + daemon.waitForFinished(); + + // send something, which we should get an error with + QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.DBus", "/", QString(), "ListNames"); + QDBusPendingCall reply = con.asyncCall(message); + + reply.waitForFinished(); QVERIFY(!con.isConnected()); QVERIFY(reply.isFinished()); QVERIFY(reply.isError()); - QVERIFY(reply.error().type() == QDBusError::Disconnected); + QCOMPARE(reply.error().type(), QDBusError::Disconnected); +#endif } QString MyObject::path; diff --git a/tests/auto/gui/image/qicon/tst_qicon.cpp b/tests/auto/gui/image/qicon/tst_qicon.cpp index b728d095d7..4218d0751f 100644 --- a/tests/auto/gui/image/qicon/tst_qicon.cpp +++ b/tests/auto/gui/image/qicon/tst_qicon.cpp @@ -709,6 +709,7 @@ void tst_QIcon::fromThemeCache() QIcon::setThemeSearchPaths(QStringList()); QSKIP("gtk-update-icon-cache not run (binary not found)"); } +#ifndef QT_NO_PROCESS QProcess process; process.start(gtkUpdateIconCache, QStringList() << QStringLiteral("-f") << QStringLiteral("-t") << (dir.path() + QLatin1String("/testcache"))); @@ -718,6 +719,7 @@ void tst_QIcon::fromThemeCache() QVERIFY(process.waitForFinished()); QCOMPARE(process.exitStatus(), QProcess::NormalExit); QCOMPARE(process.exitCode(), 0); +#endif // QT_NO_PROCESS QVERIFY(QFileInfo(cacheName).lastModified() >= QFileInfo(dir.path() + QLatin1String("/testcache/16x16/actions")).lastModified()); QIcon::setThemeSearchPaths(QStringList() << dir.path()); // reload themes QVERIFY(!QIcon::fromTheme("button-open").isNull()); diff --git a/tests/auto/gui/kernel/qwindow/BLACKLIST b/tests/auto/gui/kernel/qwindow/BLACKLIST index 9945c58122..bb7c408d60 100644 --- a/tests/auto/gui/kernel/qwindow/BLACKLIST +++ b/tests/auto/gui/kernel/qwindow/BLACKLIST @@ -11,3 +11,5 @@ ubuntu-14.04 [modalWindowEnterEventOnHide_QTBUG35109] ubuntu-14.04 ubuntu-16.04 +[modalDialogClosingOneOfTwoModal] +osx diff --git a/tests/auto/gui/text/qfontcache/tst_qfontcache.cpp b/tests/auto/gui/text/qfontcache/tst_qfontcache.cpp index 27796cda51..54bc802cf0 100644 --- a/tests/auto/gui/text/qfontcache/tst_qfontcache.cpp +++ b/tests/auto/gui/text/qfontcache/tst_qfontcache.cpp @@ -101,8 +101,6 @@ void tst_QFontCache::engineData() } if (req.pointSize < 0) req.pointSize = req.pixelSize*72.0/d->dpi; - if (req.weight == 0) - req.weight = QFont::Normal; if (req.stretch == 0) req.stretch = 100; diff --git a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp index 69cd5f00dd..4d5af44ff1 100644 --- a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp +++ b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp @@ -134,6 +134,7 @@ private slots: void xToCursorForLigatures(); void cursorInNonStopChars(); void nbsp(); + void noModificationOfInputString(); private: QFont testFont; @@ -2164,5 +2165,37 @@ void tst_QTextLayout::layoutWithCustomTabStops() QVERIFY(longWidth > shortWidth); } +void tst_QTextLayout::noModificationOfInputString() +{ + QString s = QString(QChar(QChar::LineSeparator)); + { + QTextLayout layout; + layout.setText(s); + + layout.beginLayout(); + layout.createLine(); + layout.endLayout(); + + QCOMPARE(s.size(), 1); + QCOMPARE(s.at(0), QChar(QChar::LineSeparator)); + } + + { + QTextLayout layout; + layout.setText(s); + + QTextOption option; + option.setFlags(QTextOption::ShowLineAndParagraphSeparators); + layout.setTextOption(option); + + layout.beginLayout(); + layout.createLine(); + layout.endLayout(); + + QCOMPARE(s.size(), 1); + QCOMPARE(s.at(0), QChar(QChar::LineSeparator)); + } +} + QTEST_MAIN(tst_QTextLayout) #include "tst_qtextlayout.moc" diff --git a/tests/auto/network/access/qnetworkreply/BLACKLIST b/tests/auto/network/access/qnetworkreply/BLACKLIST index efa9cb61a8..1d56c78bbc 100644 --- a/tests/auto/network/access/qnetworkreply/BLACKLIST +++ b/tests/auto/network/access/qnetworkreply/BLACKLIST @@ -1,3 +1,4 @@ +# See qtbase/src/testlib/qtestblacklist.cpp for format osx [ioGetFromBuiltinHttp:http+limited] ubuntu-14.04 @@ -7,9 +8,3 @@ ubuntu-14.04 * [backgroundRequestInterruption:ftp, bg, nobg] * -[authenticationCacheAfterCancel:http+socksauth] -rhel-7.1 -rhel-7.2 -[authenticationCacheAfterCancel:https+socksauth] -rhel-7.1 -rhel-7.2 diff --git a/tests/auto/network/ssl/qsslsocket/BLACKLIST b/tests/auto/network/ssl/qsslsocket/BLACKLIST index 4146a352e9..52c023b78f 100644 --- a/tests/auto/network/ssl/qsslsocket/BLACKLIST +++ b/tests/auto/network/ssl/qsslsocket/BLACKLIST @@ -1,3 +1,7 @@ windows [waitForConnectedEncryptedReadyRead:WithSocks5ProxyAuth] * +[protocolServerSide:ssl3-any] +rhel-7.2 +[protocolServerSide:tls1.0-any] +rhel-7.2 diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp index a23a924a01..c1ed865d02 100644 --- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp @@ -226,7 +226,6 @@ private slots: void ecdhServer(); void verifyClientCertificate_data(); void verifyClientCertificate(); - void setEmptyDefaultConfiguration(); // this test should be last #ifndef QT_NO_OPENSSL void simplePskConnect_data(); @@ -237,6 +236,10 @@ private slots: void pskServer(); #endif + void setEmptyDefaultConfiguration(); // this test should be last + +protected slots: + static void exitLoop() { // Safe exit - if we aren't in an event loop, don't @@ -247,7 +250,6 @@ private slots: } } -protected slots: void ignoreErrorSlot() { socket->ignoreSslErrors(); diff --git a/tests/auto/opengl/qgl/BLACKLIST b/tests/auto/opengl/qgl/BLACKLIST index fa7c829b30..a7aaa04900 100644 --- a/tests/auto/opengl/qgl/BLACKLIST +++ b/tests/auto/opengl/qgl/BLACKLIST @@ -10,6 +10,7 @@ windows windows [clipTest] windows +opensuse-13.1 [graphicsViewClipping] windows [glFBOUseInGLWidget] diff --git a/tests/auto/other/compiler/tst_compiler.cpp b/tests/auto/other/compiler/tst_compiler.cpp index 50cfe48cdf..55fab00156 100644 --- a/tests/auto/other/compiler/tst_compiler.cpp +++ b/tests/auto/other/compiler/tst_compiler.cpp @@ -631,9 +631,10 @@ void tst_Compiler::cxx11_alignas() #ifndef Q_COMPILER_ALIGNAS QSKIP("Compiler does not support C++11 feature"); #else - alignas(double) char c; - Q_UNUSED(c); - QCOMPARE(Q_ALIGNOF(c), Q_ALIGNOF(double)); + struct S { + alignas(double) char c; + }; + QCOMPARE(Q_ALIGNOF(S), Q_ALIGNOF(double)); #endif } diff --git a/tests/auto/tools/moc/no-keywords.h b/tests/auto/tools/moc/no-keywords.h index 56a906e6a9..d31063665b 100644 --- a/tests/auto/tools/moc/no-keywords.h +++ b/tests/auto/tools/moc/no-keywords.h @@ -70,9 +70,9 @@ private: double slots; }; -#define signals public -#define slots -#define emit +#define signals Q_SIGNALS +#define slots Q_SLOTS +#define emit Q_EMIT #undef QT_NO_KEYWORDS #endif // NO_KEYWORDS_H diff --git a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp index 5f314cddc4..00693ba6f7 100644 --- a/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp +++ b/tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp @@ -104,10 +104,6 @@ private slots: void caseSensitivity(); -#if defined(Q_OS_WIN) - void Win32LongFileName(); -#endif - void drives_data(); void drives(); void dirsBeforeFiles(); @@ -892,20 +888,6 @@ void tst_QFileSystemModel::caseSensitivity() } } -#if defined(Q_OS_WIN) -void tst_QFileSystemModel::Win32LongFileName() -{ - QString tmp = flatDirTestPath; - QStringList files; - files << "aaaaaaaaaa" << "bbbbbbbbbb" << "cccccccccc"; - QVERIFY(createFiles(tmp, files)); - QModelIndex root = model->setRootPath(tmp); - QTRY_VERIFY(model->index(tmp + QLatin1String("/aaaaaa~1")).isValid()); - QTRY_VERIFY(model->index(tmp + QLatin1String("/bbbbbb~1")).isValid()); - QTRY_VERIFY(model->index(tmp + QLatin1String("/cccccc~1")).isValid()); -} -#endif - void tst_QFileSystemModel::drives_data() { QTest::addColumn<QString>("path"); diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp index 2329db55e9..2ecc1120b9 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp @@ -49,6 +49,9 @@ #include <QtWidgets/QStyle> #include <QtWidgets/QPushButton> #include <QtWidgets/QDesktopWidget> +#ifndef QT_NO_OPENGL +#include <QtWidgets/QOpenGLWidget> +#endif #include <private/qgraphicsscene_p.h> #include <private/qgraphicsview_p.h> #include "../../../shared/platforminputcontext.h" @@ -154,6 +157,9 @@ private slots: void sceneRect_growing(); void setSceneRect(); void viewport(); +#ifndef QT_NO_OPENGL + void openGLViewport(); +#endif void dragMode_scrollHand(); void dragMode_rubberBand(); void rubberBandSelectionMode(); @@ -655,6 +661,45 @@ void tst_QGraphicsView::viewport() QTest::qWait(25); } +#ifndef QT_NO_OPENGL +void tst_QGraphicsView::openGLViewport() +{ + QGraphicsScene scene; + scene.setBackgroundBrush(Qt::white); + scene.addText("GraphicsView"); + scene.addEllipse(QRectF(400, 50, 50, 50)); + scene.addEllipse(QRectF(-100, -400, 50, 50)); + scene.addEllipse(QRectF(50, -100, 50, 50)); + scene.addEllipse(QRectF(-100, 50, 50, 50)); + + QGraphicsView view(&scene); + view.setSceneRect(-400, -400, 800, 800); + view.resize(400, 400); + + QOpenGLWidget *glw = new QOpenGLWidget; + QSignalSpy spy1(glw, SIGNAL(resized())); + QSignalSpy spy2(glw, SIGNAL(frameSwapped())); + + view.setViewport(glw); + + view.show(); + QTest::qWaitForWindowExposed(&view); + QTRY_VERIFY(spy1.count() > 0); + QTRY_VERIFY(spy2.count() >= spy1.count()); + spy1.clear(); + spy2.clear(); + + // Now test for resize (QTBUG-52419). This is special when the viewport is + // a QOpenGLWidget since the underlying FBO must also be maintained. + view.resize(300, 300); + QTRY_VERIFY(spy1.count() > 0); + QTRY_VERIFY(spy2.count() >= spy1.count()); + // There is no sane way to check if the framebuffer contents got updated + // (grabFramebuffer is no good for the viewport case as that does not go + // through paintGL). So skip the actual verification. +} +#endif + void tst_QGraphicsView::dragMode_scrollHand() { for (int j = 0; j < 2; ++j) { diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 3253d09bb8..e19e9e5bf1 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -326,7 +326,6 @@ private slots: void setMaskInResizeEvent(); void moveInResizeEvent(); - void immediateRepaintAfterShow(); void immediateRepaintAfterInvalidateBuffer(); void effectiveWinId(); @@ -7988,25 +7987,6 @@ void tst_QWidget::moveInResizeEvent() QTRY_COMPARE(testWidget.geometry(), expectedGeometry); } -void tst_QWidget::immediateRepaintAfterShow() -{ - if (m_platform == QStringLiteral("xcb")) - QSKIP("QTBUG-26424"); - if (m_platform != QStringLiteral("xcb") && m_platform != QStringLiteral("windows")) - QSKIP("We don't support immediate repaint right after show on other platforms."); - - UpdateWidget widget; - centerOnScreen(&widget); - widget.show(); - qApp->processEvents(); - // On X11 in particular, we are now waiting for a MapNotify event before - // syncing the backing store. However, if someone request a repaint() - // we must repaint immediately regardless of the current state. - widget.numPaintEvents = 0; - widget.repaint(); - QCOMPARE(widget.numPaintEvents, 1); -} - void tst_QWidget::immediateRepaintAfterInvalidateBuffer() { if (m_platform != QStringLiteral("xcb") && m_platform != QStringLiteral("windows")) diff --git a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp index 301ddf441e..a59dd8c80e 100644 --- a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp +++ b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp @@ -83,6 +83,7 @@ private slots: void tst_showWithoutActivating(); void tst_paintEventOnSecondShow(); + void tst_paintEventOnResize_QTBUG50796(); #ifndef QT_NO_DRAGANDDROP void tst_dnd(); @@ -365,6 +366,29 @@ void tst_QWidget_window::tst_paintEventOnSecondShow() QTRY_VERIFY(w.paintEventCount > 0); } +void tst_QWidget_window::tst_paintEventOnResize_QTBUG50796() +{ + const QRect availableGeo = QGuiApplication::primaryScreen()->availableGeometry(); + + QWidget root; + root.setGeometry(availableGeo.width()/2 - 100, availableGeo.height()/2 - 100, + 200, 200); + + PaintTestWidget *native = new PaintTestWidget(&root); + native->winId(); // We're testing native widgets + native->setGeometry(10, 10, 50, 50); + + root.show(); + QVERIFY(QTest::qWaitForWindowExposed(&root)); + QVERIFY(QTest::qWaitForWindowActive(&root)); + QVERIFY(native->isVisible()); + + native->paintEventCount = 0; + native->resize(native->width() + 10, native->height() + 10); + QTest::qWait(50); // Wait for paint events + QTRY_COMPARE(native->paintEventCount, 1); // Only one paint event must occur +} + #ifndef QT_NO_DRAGANDDROP /* DnD test for QWidgetWindow (handleDrag*Event() functions). diff --git a/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp b/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp index bafebc0dc6..5925b764dd 100644 --- a/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp +++ b/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp @@ -882,17 +882,14 @@ private: void tst_QStyle::testStyleOptionInit() { QStringList keys = QStyleFactory::keys(); - QVector<QStyle*> styles; - styles.reserve(keys.size() + 1); - - styles << new QCommonStyle(); + keys.prepend(QString()); // QCommonStyle marker - Q_FOREACH (QStyle *style, styles) { + Q_FOREACH (const QString &key, keys) { + QStyle* style = key.isEmpty() ? new QCommonStyle : QStyleFactory::create(key); TestStyleOptionInitProxy testStyle; testStyle.setBaseStyle(style); testAllFunctions(style); QVERIFY(!testStyle.invalidOptionsDetected); - delete style; } } diff --git a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp index 654e1899f0..cb7643d1ac 100644 --- a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp +++ b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp @@ -83,6 +83,7 @@ private slots: void widgetActionFocus(); void mouseActivation(); void tearOff(); + void submenuTearOffDontClose(); void layoutDirection(); void task208001_stylesheet(); @@ -648,6 +649,51 @@ void tst_QMenu::tearOff() #endif // QT_NO_CURSOR } +void tst_QMenu::submenuTearOffDontClose() +{ + QWidget widget; + QMenu *menu = new QMenu(&widget); + QVERIFY(!menu->isTearOffEnabled()); //default value + menu->setTearOffEnabled(true); + QVERIFY(menu->isTearOffEnabled()); + QMenu *submenu = new QMenu(&widget); + submenu->addAction("aaa"); + submenu->addAction("bbb"); + QVERIFY(!submenu->isTearOffEnabled()); //default value + submenu->setTearOffEnabled(true); + QVERIFY(submenu->isTearOffEnabled()); + menu->addMenu(submenu); + + widget.resize(300, 200); + centerOnScreen(&widget); + widget.show(); + widget.activateWindow(); + QVERIFY(QTest::qWaitForWindowActive(&widget)); + // Show parent menu + menu->popup(widget.geometry().topRight() + QPoint(50, 0)); + QVERIFY(QTest::qWaitForWindowActive(menu)); + // Then its submenu + const QRect submenuRect = menu->actionGeometry(menu->actions().at(0)); + const QPoint submenuPos(submenuRect.topLeft() + QPoint(3, 3)); + // Move then click to avoid the submenu moves from causing it to close + QTest::mouseMove(menu, submenuPos, 100); + QTest::mouseClick(menu, Qt::LeftButton, 0, submenuPos, 100); + QTRY_VERIFY(QTest::qWaitForWindowActive(submenu)); + // Make sure we enter the submenu frame directly on the tear-off area + QTest::mouseMove(submenu, QPoint(10, 3), 100); + if (submenu->style()->styleHint(QStyle::SH_Menu_SubMenuDontStartSloppyOnLeave)) { + qWarning("Sloppy menu timer disabled by the style: %s", qPrintable(QApplication::style()->objectName())); + // Submenu must get the enter event + QTRY_VERIFY(submenu->underMouse()); + } else { + const int closeTimeout = submenu->style()->styleHint(QStyle::SH_Menu_SubMenuSloppyCloseTimeout); + QTest::qWait(closeTimeout + 100); + // Menu must not disappear and it must get the enter event + QVERIFY(submenu->isVisible()); + QVERIFY(submenu->underMouse()); + } +} + void tst_QMenu::layoutDirection() { QMainWindow win; diff --git a/tests/auto/widgets/widgets/qopenglwidget/BLACKLIST b/tests/auto/widgets/widgets/qopenglwidget/BLACKLIST index 86c7141268..fa326a6ea5 100644 --- a/tests/auto/widgets/widgets/qopenglwidget/BLACKLIST +++ b/tests/auto/widgets/widgets/qopenglwidget/BLACKLIST @@ -12,3 +12,6 @@ windows msvc-2010 32bit developer-build #QTBUG-31611 [reparentToNotYetCreated] windows msvc-2010 32bit developer-build + +[stackWidgetOpaqueChildIsVisible] +windows diff --git a/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp b/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp index c76c4d927b..e3e26d612f 100644 --- a/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp +++ b/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp @@ -29,11 +29,14 @@ #include <QtWidgets/QOpenGLWidget> #include <QtGui/QOpenGLFunctions> #include <QtGui/QPainter> +#include <QtGui/QScreen> +#include <QtWidgets/QDesktopWidget> #include <QtWidgets/QGraphicsView> #include <QtWidgets/QGraphicsScene> #include <QtWidgets/QGraphicsRectItem> #include <QtWidgets/QVBoxLayout> #include <QtWidgets/QPushButton> +#include <QtWidgets/QStackedWidget> #include <QtTest/QtTest> #include <QSignalSpy> @@ -54,6 +57,7 @@ private slots: void fboRedirect(); void showHide(); void nativeWindow(); + void stackWidgetOpaqueChildIsVisible(); }; void tst_QOpenGLWidget::create() @@ -420,6 +424,135 @@ void tst_QOpenGLWidget::nativeWindow() QVERIFY(image.pixel(30, 40) == qRgb(0, 255, 0)); } +static inline QString msgRgbMismatch(unsigned actual, unsigned expected) +{ + return QString::asprintf("Color mismatch, %#010x != %#010x", actual, expected); +} + +static QPixmap grabWidgetWithoutRepaint(const QWidget *widget, QRect clipArea) +{ + const QWidget *targetWidget = widget; +#ifdef Q_OS_WIN + // OpenGL content is not properly grabbed on Windows when passing a top level widget window, + // because GDI functions can't grab OpenGL layer content. + // Instead the whole screen should be captured, with an adjusted clip area, which contains + // the final composited content. + QDesktopWidget *desktopWidget = QApplication::desktop(); + const QWidget *mainScreenWidget = desktopWidget->screen(); + targetWidget = mainScreenWidget; + clipArea = QRect(widget->mapToGlobal(clipArea.topLeft()), + widget->mapToGlobal(clipArea.bottomRight())); +#endif + + const QWindow *window = targetWidget->window()->windowHandle(); + Q_ASSERT(window); + WId windowId = window->winId(); + + QScreen *screen = window->screen(); + Q_ASSERT(screen); + + const QSize size = clipArea.size(); + const QPixmap result = screen->grabWindow(windowId, + clipArea.x(), + clipArea.y(), + size.width(), + size.height()); + return result; +} + +#define VERIFY_COLOR(child, region, color) verifyColor(child, region, color, __LINE__) + +bool verifyColor(const QWidget *widget, const QRect &clipArea, const QColor &color, int callerLine) +{ + for (int t = 0; t < 6; t++) { + const QPixmap pixmap = grabWidgetWithoutRepaint(widget, clipArea); + if (!QTest::qCompare(pixmap.size(), + clipArea.size(), + "pixmap.size()", + "rect.size()", + __FILE__, + callerLine)) + return false; + + + const QImage image = pixmap.toImage(); + QPixmap expectedPixmap(pixmap); /* ensure equal formats */ + expectedPixmap.detach(); + expectedPixmap.fill(color); + + uint alphaCorrection = image.format() == QImage::Format_RGB32 ? 0xff000000 : 0; + uint firstPixel = image.pixel(0,0) | alphaCorrection; + + // Retry a couple of times. Some window managers have transparency animation, or are + // just slow to render. + if (t < 5) { + if (firstPixel == QColor(color).rgb() + && image == expectedPixmap.toImage()) + return true; + else + QTest::qWait(200); + } else { + if (!QTest::qVerify(firstPixel == QColor(color).rgb(), + "firstPixel == QColor(color).rgb()", + qPrintable(msgRgbMismatch(firstPixel, QColor(color).rgb())), + __FILE__, callerLine)) { + return false; + } + if (!QTest::qVerify(image == expectedPixmap.toImage(), + "image == expectedPixmap.toImage()", + "grabbed pixmap differs from expected pixmap", + __FILE__, callerLine)) { + return false; + } + } + } + + return false; +} + +void tst_QOpenGLWidget::stackWidgetOpaqueChildIsVisible() +{ +#ifdef Q_OS_OSX + QSKIP("QScreen::grabWindow() doesn't work properly on OSX HighDPI screen: QTBUG-46803"); + return; +#endif + + QStackedWidget stack; + + QWidget* emptyWidget = new QWidget(&stack); + stack.addWidget(emptyWidget); + + // Create an opaque red QOpenGLWidget. + const int dimensionSize = 400; + ClearWidget* clearWidget = new ClearWidget(&stack, dimensionSize, dimensionSize); + clearWidget->setAttribute(Qt::WA_OpaquePaintEvent); + stack.addWidget(clearWidget); + + // Show initial QWidget. + stack.setCurrentIndex(0); + stack.resize(dimensionSize, dimensionSize); + stack.show(); + QTest::qWaitForWindowExposed(&stack); + QTest::qWaitForWindowActive(&stack); + + // Switch to the QOpenGLWidget. + stack.setCurrentIndex(1); + QTRY_COMPARE(clearWidget->m_paintCalled, true); + + // Resize the tested region to be half size in the middle, because some OSes make the widget + // have rounded corners (e.g. OSX), and the grabbed window pixmap will not coincide perfectly + // with what was actually painted. + QRect clipArea = stack.rect(); + clipArea.setSize(clipArea.size() / 2); + const int translationOffsetToMiddle = dimensionSize / 4; + clipArea.translate(translationOffsetToMiddle, translationOffsetToMiddle); + + // Verify that the QOpenGLWidget was actually painted AND displayed. + const QColor red(255, 0, 0, 255); + VERIFY_COLOR(&stack, clipArea, red); + #undef VERIFY_COLOR +} + QTEST_MAIN(tst_QOpenGLWidget) #include "tst_qopenglwidget.moc" diff --git a/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp b/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp index a6d3a84495..31bbcf9c7f 100644 --- a/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp +++ b/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp @@ -1161,12 +1161,19 @@ void tst_QPlainTextEdit::selectWordsFromStringsContainingSeparators_data() QTest::addColumn<QString>("testString"); QTest::addColumn<QString>("selectedWord"); - QStringList wordSeparators; - wordSeparators << "." << "," << "?" << "!" << ":" << ";" << "-" << "<" << ">" << "[" - << "]" << "(" << ")" << "{" << "}" << "=" << "\t"<< QString(QChar::Nbsp); - - foreach (QString s, wordSeparators) - QTest::newRow(QString("separator: " + s).toLocal8Bit()) << QString("foo") + s + QString("bar") << QString("foo"); + const ushort wordSeparators[] = + {'.', ',', '?', '!', ':', ';', '-', '<', '>', '[', ']', '(', ')', '{', '}', + '=', '\t', ushort(QChar::Nbsp)}; + + for (size_t i = 0, count = sizeof(wordSeparators) / sizeof(wordSeparators[0]); i < count; ++i) { + const ushort u = wordSeparators[i]; + QByteArray rowName = QByteArrayLiteral("separator: "); + if (u >= 32 && u < 128) + rowName += char(u); + else + rowName += QByteArrayLiteral("0x") + QByteArray::number(u, 16); + QTest::newRow(rowName.constData()) << QString("foo") + QChar(u) + QString("bar") << QString("foo"); + } } void tst_QPlainTextEdit::selectWordsFromStringsContainingSeparators() diff --git a/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp b/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp index 7b26489b39..cecec48113 100644 --- a/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp +++ b/tests/auto/widgets/widgets/qtextedit/tst_qtextedit.cpp @@ -1512,12 +1512,19 @@ void tst_QTextEdit::selectWordsFromStringsContainingSeparators_data() QTest::addColumn<QString>("testString"); QTest::addColumn<QString>("selectedWord"); - QStringList wordSeparators; - wordSeparators << "." << "," << "?" << "!" << ":" << ";" << "-" << "<" << ">" << "[" - << "]" << "(" << ")" << "{" << "}" << "=" << "\t"<< QString(QChar::Nbsp); - - foreach (QString s, wordSeparators) - QTest::newRow(QString("separator: " + s).toLocal8Bit()) << QString("foo") + s + QString("bar") << QString("foo"); + const ushort wordSeparators[] = + {'.', ',', '?', '!', ':', ';', '-', '<', '>', '[', ']', '(', ')', '{', '}', + '=', '\t', ushort(QChar::Nbsp)}; + + for (size_t i = 0, count = sizeof(wordSeparators) / sizeof(wordSeparators[0]); i < count; ++i) { + const ushort u = wordSeparators[i]; + QByteArray rowName = QByteArrayLiteral("separator: "); + if (u >= 32 && u < 128) + rowName += char(u); + else + rowName += QByteArrayLiteral("0x") + QByteArray::number(u, 16); + QTest::newRow(rowName.constData()) << QString("foo") + QChar(u) + QString("bar") << QString("foo"); + } } void tst_QTextEdit::selectWordsFromStringsContainingSeparators() diff --git a/tests/benchmarks/corelib/tools/qvector/outofline.cpp b/tests/benchmarks/corelib/tools/qvector/outofline.cpp index efd3df2308..76a4edaa10 100644 --- a/tests/benchmarks/corelib/tools/qvector/outofline.cpp +++ b/tests/benchmarks/corelib/tools/qvector/outofline.cpp @@ -97,5 +97,5 @@ void QVectorData::free(QVectorData *x, int alignment) int QVectorData::grow(int sizeOfHeader, int size, int sizeOfT) { - return qAllocMore(size * sizeOfT, sizeOfHeader) / sizeOfT; + return qCalculateGrowingBlockSize(size, sizeOfT, sizeOfHeader).elementCount; } diff --git a/tests/manual/diaglib/README.txt b/tests/manual/diaglib/README.txt index fd199d09cb..ab243da9ae 100644 --- a/tests/manual/diaglib/README.txt +++ b/tests/manual/diaglib/README.txt @@ -32,6 +32,17 @@ class DebugProxyStyle (debugproxystyle.h) the parameters and return values of its function calls, useful for debugging QStyle. +class LogWidget (logwidget.h) + A Log Widget inheriting QPlainTextEdit with convenience functions + to install as a message handler. + +class LogFunctionGuard + A guard class for use with LogWidget logging messages when a function + is entered/left (indenting the log messages). + Can be instantiated using: + LogFunctionGuard guard(__FUNCTION__) or + LogFunctionGuard guard(Q_FUNC_INFO) + function glInfo() (glinfo.h): Returns a string describing the Open GL configuration (obtained by querying GL_VENDOR and GL_RENDERER). Available only diff --git a/tests/manual/diaglib/diaglib.pri b/tests/manual/diaglib/diaglib.pri index a51d2f1201..9bcf0317a6 100644 --- a/tests/manual/diaglib/diaglib.pri +++ b/tests/manual/diaglib/diaglib.pri @@ -23,17 +23,21 @@ greaterThan(QT_MAJOR_VERSION, 4) { QT += gui-private core-private contains(QT, widgets) { HEADERS += \ - $$PWD/qwidgetdump.h + $$PWD/qwidgetdump.h \ + $$PWD/logwidget.h SOURCES += \ - $$PWD/qwidgetdump.cpp + $$PWD/qwidgetdump.cpp \ + $$PWD/logwidget.cpp } } else { HEADERS += \ - $$PWD/qwidgetdump.h + $$PWD/qwidgetdump.h \ + $$PWD/logwidget.h SOURCES += \ - $$PWD/qwidgetdump.cpp + $$PWD/qwidgetdump.cpp \ + $$PWD/logwidget.cpp } contains(QT, opengl) { diff --git a/tests/manual/diaglib/logwidget.cpp b/tests/manual/diaglib/logwidget.cpp new file mode 100644 index 0000000000..5dbefd8da9 --- /dev/null +++ b/tests/manual/diaglib/logwidget.cpp @@ -0,0 +1,164 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "logwidget.h" +#if QT_VERSION >= 0x050000 +# include <QtCore/qlogging.h> +# include <QtCore/QLibraryInfo> +#endif +#include <QApplication> +#include <QStyle> + +#include <QtCore/QDebug> +#include <QtCore/QVector> +#include <QtCore/QStringList> + +#include <iostream> + +LogWidget *LogWidget::m_instance = 0; +bool LogWidget::m_lineNumberingEnabled = true; +bool LogWidget::m_showMessageType = true; +int LogWidget::m_indent = 0; + +LogWidget::LogWidget(QWidget *parent) + : QPlainTextEdit(parent) +{ + LogWidget::m_instance = this; + setReadOnly(true); +} + +LogWidget::~LogWidget() +{ + LogWidget::m_instance = 0; +} + +QString LogWidget::startupMessage() +{ + QString result; +#if QT_VERSION >= 0x050300 + result += QLatin1String(QLibraryInfo::build()); +#else + result += QLatin1String("Qt ") + QLatin1String(QT_VERSION_STR); +#endif + + const QCoreApplication *coreApp = QCoreApplication::instance(); +#if QT_VERSION >= 0x050000 + if (qobject_cast<const QGuiApplication *>(coreApp)) { + result += QLatin1Char(' '); + result += QGuiApplication::platformName(); + } +#endif + if (qobject_cast<const QApplication *>(coreApp)) { + result += QLatin1Char(' '); + result += QApplication::style()->objectName(); + } + if (coreApp) { + QStringList arguments = QCoreApplication::arguments(); + arguments.pop_front(); + if (!arguments.isEmpty()) { + result += QLatin1Char('\n'); + result += arguments.join(QLatin1String(" ")); + } + } + return result; +} + +static const QVector<QString> &messageTypes() +{ + static QVector<QString> result; + if (result.isEmpty()) { + result << QLatin1String("debug") << QLatin1String("warn") + << QLatin1String("critical") << QLatin1String("fatal") + << QLatin1String("info"); + } + return result; +} + +static void messageHandler(QtMsgType type, const QString &text) +{ + static int n = 0; + QString message; + if (LogWidget::lineNumberingEnabled()) + message.append(QString::fromLatin1("%1 ").arg(n, 4, 10, QLatin1Char('0'))); + if (LogWidget::showMessageType()) { + message.append(messageTypes().at(type)); + message.append(QLatin1Char(' ')); + } + for (int i = 0, ie = LogWidget::indent(); i < ie; ++i) + message.append(QLatin1Char(' ')); + message.append(text); + if (LogWidget *logWindow = LogWidget::instance()) + logWindow->appendText(message); +#ifdef Q_OS_WIN + std::wcerr << reinterpret_cast<const wchar_t *>(message.utf16()) << L'\n'; +#else + std::cerr << qPrintable(message) << '\n'; +#endif + n++; +} + +#if QT_VERSION >= 0x050000 + +static void qt5MessageHandler(QtMsgType type, const QMessageLogContext &, const QString &text) +{ messageHandler(type, text); } + +void LogWidget::install() +{ + qInstallMessageHandler(qt5MessageHandler); + qInfo("%s", qPrintable(LogWidget::startupMessage())); +} + +void LogWidget::uninstall() { qInstallMessageHandler(Q_NULLPTR); } + +#else // Qt 5 + +static QtMsgHandler oldHandler = 0; + +static void qt4MessageHandler(QtMsgType type, const char *text) +{ messageHandler(type, QString::fromLocal8Bit(text)); } + +void LogWidget::install() +{ + oldHandler = qInstallMsgHandler(qt4MessageHandler); + qDebug("%s", qPrintable(LogWidget::startupMessage())); +} + +void LogWidget::uninstall() { qInstallMsgHandler(oldHandler); } + +#endif // Qt 4 + +void LogWidget::appendText(const QString &message) +{ + appendPlainText(message); + ensureCursorVisible(); +} diff --git a/tests/manual/diaglib/logwidget.h b/tests/manual/diaglib/logwidget.h new file mode 100644 index 0000000000..1a85cc143d --- /dev/null +++ b/tests/manual/diaglib/logwidget.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef LOGWIDGET_H +#define LOGWIDGET_H + +#include <QPlainTextEdit> + +// Instantiate as follows: LogFunctionGuard guard(Q_FUNC_INFO) +class LogFunctionGuard { + Q_DISABLE_COPY(LogFunctionGuard) +public: + explicit LogFunctionGuard(const char *name); + ~LogFunctionGuard(); + +private: + const char *m_name; +}; + +class LogWidget : public QPlainTextEdit +{ + Q_OBJECT +public: + explicit LogWidget(QWidget *parent = 0); + ~LogWidget(); + + static LogWidget *instance() { return m_instance; } + + static QString startupMessage(); + static void install(); + static void uninstall(); + + static int indent() { return m_indent; } + static void setIndent(int i) { m_indent = i; } + + static bool lineNumberingEnabled() { return m_lineNumberingEnabled; } + static void setLineNumberingEnabled(bool l) { m_lineNumberingEnabled = l; } + + static bool showMessageType() { return m_showMessageType; } + static void setShowMessageType(bool s) { m_showMessageType = s; } + +public slots: + void appendText(const QString &); + +private: + static int m_indent; + static bool m_lineNumberingEnabled; + static bool m_showMessageType; + static LogWidget *m_instance; +}; + +inline LogFunctionGuard::LogFunctionGuard(const char *name) : m_name(name) +{ + qDebug(">%s", m_name); + LogWidget::setIndent(LogWidget::indent() + 2); +} + +inline LogFunctionGuard::~LogFunctionGuard() +{ + LogWidget::setIndent(LogWidget::indent() - 2); + qDebug("<%s", m_name); +} + +#endif // LOGWIDGET_H diff --git a/tests/manual/diaglib/qwidgetdump.cpp b/tests/manual/diaglib/qwidgetdump.cpp index 0ccf109ebb..10cfde510d 100644 --- a/tests/manual/diaglib/qwidgetdump.cpp +++ b/tests/manual/diaglib/qwidgetdump.cpp @@ -40,11 +40,50 @@ namespace QtDiag { +static const char *qtWidgetClasses[] = { + "QAbstractItemView", "QAbstractScrollArea", "QAbstractSlider", "QAbstractSpinBox", + "QCalendarWidget", "QCheckBox", "QColorDialog", "QColumnView", "QComboBox", + "QCommandLinkButton", "QDateEdit", "QDateTimeEdit", "QDesktopWidget", "QDial", + "QDialog", "QDialogButtonBox", "QDockWidget", "QDoubleSpinBox", "QErrorMessage", + "QFileDialog", "QFontComboBox", "QFontDialog", "QFrame", "QGraphicsView", + "QGroupBox", "QHeaderView", "QInputDialog", "QLCDNumber", "QLabel", "QLineEdit", + "QListView", "QListWidget", "QMainWindow", "QMdiArea", "QMdiSubWindow", "QMenu", + "QMenuBar", "QMessageBox", "QOpenGLWidget", "QPlainTextEdit", "QProgressBar", + "QProgressDialog", "QPushButton", "QRadioButton", "QRubberBand", "QScrollArea", + "QScrollBar", "QSlider", "QSpinBox", "QSplashScreen", "QSplitter", + "QStackedWidget", "QStatusBar", "QTabBar", "QTabWidget", "QTableView", + "QTableWidget", "QTextBrowser", "QTextEdit", "QTimeEdit", "QToolBar", + "QToolBox", "QToolButton", "QTreeView", "QTreeWidget", "QWidget", + "QWizard", "QWizardPage" +}; + +static bool isQtWidget(const char *className) +{ + for (size_t i = 0, count = sizeof(qtWidgetClasses) / sizeof(qtWidgetClasses[0]); i < count; ++i) { + if (!qstrcmp(className, qtWidgetClasses[i])) + return true; + } + return false; +} + +static void formatWidgetClass(QTextStream &str, const QWidget *w) +{ + const QMetaObject *mo = w->metaObject(); + str << mo->className(); + while (!isQtWidget(mo->className())) { + mo = mo->superClass(); + str << ':' << mo->className(); + } + const QString on = w->objectName(); + if (!on.isEmpty()) + str << "/\"" << on << '"'; +} + static void dumpWidgetRecursion(QTextStream &str, const QWidget *w, FormatWindowOptions options, int depth = 0) { indentStream(str, 2 * depth); - formatObject(str, w); + formatWidgetClass(str, w); str << ' ' << (w->isVisible() ? "[visible] " : "[hidden] "); if (const WId nativeWinId = w->internalWinId()) str << "[native: " << hex << showbase << nativeWinId << dec << noshowbase << "] "; @@ -109,7 +148,10 @@ void dumpAllWidgets(FormatWindowOptions options, const QWidget *root) foreach (QWidget *tw, topLevels) dumpWidgetRecursion(str, tw, options); #if QT_VERSION >= 0x050400 - qDebug().noquote() << d; + { + foreach (const QString &line, d.split(QLatin1Char('\n'))) + qDebug().noquote() << line; + } #else qDebug("%s", qPrintable(d)); #endif diff --git a/tests/manual/shortcuts/main.cpp b/tests/manual/shortcuts/main.cpp index 91477d5146..55ade1040a 100644 --- a/tests/manual/shortcuts/main.cpp +++ b/tests/manual/shortcuts/main.cpp @@ -92,16 +92,20 @@ protected: QPushButton *b12 = new QPushButton(sq12.toString()); b12->setShortcut(sq12); - // LATIN SMALL LETTER O WITH STROKE - QKeySequence sq13(QString(QChar(ushort(0xf8)))); + QKeySequence sq13(Qt::ControlModifier + Qt::Key_BracketRight); QPushButton *b13 = new QPushButton(sq13.toString()); b13->setShortcut(sq13); - // CYRILLIC SMALL LETTER ZHE - QKeySequence sq14(QString(QChar(ushort(0x436)))); + // LATIN SMALL LETTER O WITH STROKE + QKeySequence sq14(QString(QChar(ushort(0xf8)))); QPushButton *b14 = new QPushButton(sq14.toString()); b14->setShortcut(sq14); + // CYRILLIC SMALL LETTER ZHE + QKeySequence sq15(QString(QChar(ushort(0x436)))); + QPushButton *b15 = new QPushButton(sq15.toString()); + b15->setShortcut(sq15); + QLabel *testPurpose = new QLabel(); testPurpose->setWordWrap(true); testPurpose->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Expanding); @@ -120,10 +124,11 @@ protected: layout->addWidget(b10); layout->addWidget(b11); layout->addWidget(b12); - layout->addWidget(new QLabel("Norwegian layout")); layout->addWidget(b13); - layout->addWidget(new QLabel("Russian layout")); + layout->addWidget(new QLabel("Norwegian layout")); layout->addWidget(b14); + layout->addWidget(new QLabel("Russian layout")); + layout->addWidget(b15); setLayout(layout); } |