From 8027fb60dd1c1e4349eb1ac782d1197e784d6081 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 18 Nov 2019 13:26:13 +0100 Subject: [PATCH 01/45] Fix QCborValue::toCbor with non-ASCII URLs Found while fixing QTBUG-79196. Change-Id: Ia2aa807ffa8a4c798425fffd15d841657def99af Reviewed-by: Ulf Hermann --- src/corelib/serialization/qcborvalue.cpp | 10 +++++----- .../serialization/qcborvalue/tst_qcborvalue.cpp | 3 +++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp index 90536180149..0e3d317518f 100644 --- a/src/corelib/serialization/qcborvalue.cpp +++ b/src/corelib/serialization/qcborvalue.cpp @@ -1391,10 +1391,10 @@ static QCborValue taggedValueFromCbor(QCborStreamReader &reader) auto &e = d->elements[1]; const ByteData *b = d->byteData(e); - auto replaceByteData = [&](const char *buf, qsizetype len) { + auto replaceByteData = [&](const char *buf, qsizetype len, Element::ValueFlags f) { d->data.clear(); d->usedData = 0; - e.flags = Element::HasByteData | Element::StringIsAscii; + e.flags = Element::HasByteData | f; e.value = d->addByteData(buf, len); }; @@ -1414,7 +1414,7 @@ static QCborValue taggedValueFromCbor(QCborStreamReader &reader) } if (dt.isValid()) { QByteArray text = dt.toString(Qt::ISODateWithMs).toLatin1(); - replaceByteData(text, text.size()); + replaceByteData(text, text.size(), Element::StringIsAscii); e.type = QCborValue::String; d->elements[0].value = qint64(QCborKnownTags::DateTimeString); type = QCborValue::DateTime; @@ -1430,7 +1430,7 @@ static QCborValue taggedValueFromCbor(QCborStreamReader &reader) b->asQStringRaw() : b->toUtf8String()); QByteArray encoded = url.toString(QUrl::DecodeReserved).toUtf8(); - replaceByteData(encoded, encoded.size()); + replaceByteData(encoded, encoded.size(), {}); } type = QCborValue::Url; } @@ -1449,7 +1449,7 @@ static QCborValue taggedValueFromCbor(QCborStreamReader &reader) char buf[sizeof(QUuid)] = {}; if (b) memcpy(buf, b->byte(), qMin(sizeof(buf), size_t(b->len))); - replaceByteData(buf, sizeof(buf)); + replaceByteData(buf, sizeof(buf), {}); type = QCborValue::Uuid; } diff --git a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp index c6733205e5e..ffc22bc9a32 100644 --- a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp +++ b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp @@ -1391,6 +1391,9 @@ static void addCommonCborData() QTest::newRow("Url") << QCborValue(QUrl("HTTPS://example.com/{%30%31}?q=%3Ca+b%20%C2%A9%3E&%26")) << raw("\xd8\x20\x78\x27" "https://example.com/{01}?q=&%26") << noxfrm; + QTest::newRow("Url:NonAscii") << QCborValue(QUrl("https://example.com/\xc2\xa0")) + << raw("\xd8\x20\x76" "https://example.com/\xc2\xa0") + << noxfrm; QTest::newRow("Regex:Empty") << QCborValue(QRegularExpression()) << raw("\xd8\x23\x60") << noxfrm; QTest::newRow("Regex") << QCborValue(QRegularExpression("^.*$")) << raw("\xd8\x23\x64" "^.*$") << noxfrm; From bcbefcd6457adac9d92a410b1f7250ed5b0e8955 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 15 Oct 2019 16:37:52 -0700 Subject: [PATCH 02/45] QCborValue: Extend the constructor to also create extended types We already did that when parsing from CBOR binary data, so the code was already present. [ChangeLog][QtCore][QCborValue] The constructor taking a CBOR tag and a value to be tagged now attempts to convert to a QCborValue extended type. For example, if the tag is 0 (UnixTime_t) and the payload is a number, the resulting object will become tag 1 (DateTime) and the payload will be the the ISO-8601 date/time string. Fixes: QTBUG-79196 Change-Id: I6edce5101800424a8093fffd15cdf650fb2fc45c Reviewed-by: Ulf Hermann --- src/corelib/serialization/qcborvalue.cpp | 157 +++++++++--------- .../qcborvalue/tst_qcborvalue.cpp | 71 ++++++-- 2 files changed, 142 insertions(+), 86 deletions(-) diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp index 0e3d317518f..4052bfa22eb 100644 --- a/src/corelib/serialization/qcborvalue.cpp +++ b/src/corelib/serialization/qcborvalue.cpp @@ -758,6 +758,81 @@ QT_BEGIN_NAMESPACE using namespace QtCbor; +static QCborValue::Type convertToExtendedType(QCborContainerPrivate *d) +{ + qint64 tag = d->elements.at(0).value; + auto &e = d->elements[1]; + const ByteData *b = d->byteData(e); + + auto replaceByteData = [&](const char *buf, qsizetype len, Element::ValueFlags f) { + d->data.clear(); + d->usedData = 0; + e.flags = Element::HasByteData | f; + e.value = d->addByteData(buf, len); + }; + + switch (tag) { + case qint64(QCborKnownTags::DateTimeString): + case qint64(QCborKnownTags::UnixTime_t): { + QDateTime dt; + if (tag == qint64(QCborKnownTags::DateTimeString) && b && + e.type == QCborValue::String && (e.flags & Element::StringIsUtf16) == 0) { + // The data is supposed to be US-ASCII. If it isn't (contains UTF-8), + // QDateTime::fromString will fail anyway. + dt = QDateTime::fromString(b->asLatin1(), Qt::ISODateWithMs); + } else if (tag == qint64(QCborKnownTags::UnixTime_t) && e.type == QCborValue::Integer) { + dt = QDateTime::fromSecsSinceEpoch(e.value, Qt::UTC); + } else if (tag == qint64(QCborKnownTags::UnixTime_t) && e.type == QCborValue::Double) { + dt = QDateTime::fromMSecsSinceEpoch(qint64(e.fpvalue() * 1000), Qt::UTC); + } + if (dt.isValid()) { + QByteArray text = dt.toString(Qt::ISODateWithMs).toLatin1(); + replaceByteData(text, text.size(), Element::StringIsAscii); + e.type = QCborValue::String; + d->elements[0].value = qint64(QCborKnownTags::DateTimeString); + return QCborValue::DateTime; + } + break; + } + + case qint64(QCborKnownTags::Url): + if (e.type == QCborValue::String) { + if (b) { + // normalize to a short (decoded) form, so as to save space + QUrl url(e.flags & Element::StringIsUtf16 ? + b->asQStringRaw() : + b->toUtf8String()); + QByteArray encoded = url.toString(QUrl::DecodeReserved).toUtf8(); + replaceByteData(encoded, encoded.size(), {}); + } + return QCborValue::Url; + } + break; + + case quint64(QCborKnownTags::RegularExpression): + if (e.type == QCborValue::String) { + // no normalization is necessary + return QCborValue::RegularExpression; + } + break; + + case qint64(QCborKnownTags::Uuid): + if (e.type == QCborValue::ByteArray) { + // force the size to 16 + char buf[sizeof(QUuid)] = {}; + if (b) + memcpy(buf, b->byte(), qMin(sizeof(buf), size_t(b->len))); + replaceByteData(buf, sizeof(buf), {}); + + return QCborValue::Uuid; + } + break; + } + + // no enriching happened + return QCborValue::Tag; +} + // in qcborstream.cpp extern void qt_cbor_stream_set_error(QCborStreamReaderPrivate *d, QCborError error); @@ -1384,77 +1459,10 @@ static QCborValue taggedValueFromCbor(QCborStreamReader &reader) d->decodeValueFromCbor(reader); } - QCborValue::Type type = QCborValue::Tag; + QCborValue::Type type; if (reader.lastError() == QCborError::NoError) { // post-process to create our extended types - qint64 tag = d->elements.at(0).value; - auto &e = d->elements[1]; - const ByteData *b = d->byteData(e); - - auto replaceByteData = [&](const char *buf, qsizetype len, Element::ValueFlags f) { - d->data.clear(); - d->usedData = 0; - e.flags = Element::HasByteData | f; - e.value = d->addByteData(buf, len); - }; - - switch (tag) { - case qint64(QCborKnownTags::DateTimeString): - case qint64(QCborKnownTags::UnixTime_t): { - QDateTime dt; - if (tag == qint64(QCborKnownTags::DateTimeString) && b && - e.type == QCborValue::String && (e.flags & Element::StringIsUtf16) == 0) { - // The data is supposed to be US-ASCII. If it isn't, - // QDateTime::fromString will fail anyway. - dt = QDateTime::fromString(b->asLatin1(), Qt::ISODateWithMs); - } else if (tag == qint64(QCborKnownTags::UnixTime_t) && e.type == QCborValue::Integer) { - dt = QDateTime::fromSecsSinceEpoch(e.value, Qt::UTC); - } else if (tag == qint64(QCborKnownTags::UnixTime_t) && e.type == QCborValue::Double) { - dt = QDateTime::fromMSecsSinceEpoch(qint64(e.fpvalue() * 1000), Qt::UTC); - } - if (dt.isValid()) { - QByteArray text = dt.toString(Qt::ISODateWithMs).toLatin1(); - replaceByteData(text, text.size(), Element::StringIsAscii); - e.type = QCborValue::String; - d->elements[0].value = qint64(QCborKnownTags::DateTimeString); - type = QCborValue::DateTime; - } - break; - } - - case qint64(QCborKnownTags::Url): - if (e.type == QCborValue::String) { - if (b) { - // normalize to a short (decoded) form, so as to save space - QUrl url(e.flags & Element::StringIsUtf16 ? - b->asQStringRaw() : - b->toUtf8String()); - QByteArray encoded = url.toString(QUrl::DecodeReserved).toUtf8(); - replaceByteData(encoded, encoded.size(), {}); - } - type = QCborValue::Url; - } - break; - - case quint64(QCborKnownTags::RegularExpression): - if (e.type == QCborValue::String) { - // no normalization is necessary - type = QCborValue::RegularExpression; - } - break; - - case qint64(QCborKnownTags::Uuid): - if (e.type == QCborValue::ByteArray) { - // force the size to 16 - char buf[sizeof(QUuid)] = {}; - if (b) - memcpy(buf, b->byte(), qMin(sizeof(buf), size_t(b->len))); - replaceByteData(buf, sizeof(buf), {}); - - type = QCborValue::Uuid; - } - break; - } + type = convertToExtendedType(d); } else { // decoding error type = QCborValue::Invalid; @@ -1717,21 +1725,22 @@ QCborValue::QCborValue(const QCborMap &m) } /*! - \fn QCborValue::QCborValue(QCborTag t, const QCborValue &tv) - \fn QCborValue::QCborValue(QCborKnownTags t, const QCborValue &tv) + \fn QCborValue::QCborValue(QCborTag tag, const QCborValue &tv) + \fn QCborValue::QCborValue(QCborKnownTags tag, const QCborValue &tv) Creates a QCborValue for the extended type represented by the tag value \a - t, tagging value \a tv. The tag can later be retrieved using tag() and + tag, tagging value \a tv. The tag can later be retrieved using tag() and the tagged value using taggedValue(). \sa isTag(), tag(), taggedValue(), QCborKnownTags */ -QCborValue::QCborValue(QCborTag t, const QCborValue &tv) +QCborValue::QCborValue(QCborTag tag, const QCborValue &tv) : n(-1), container(new QCborContainerPrivate), t(Tag) { container->ref.storeRelaxed(1); - container->append(t); + container->append(tag); container->append(tv); + t = convertToExtendedType(container); } /*! diff --git a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp index ffc22bc9a32..47ad328d64f 100644 --- a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp +++ b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp @@ -40,6 +40,7 @@ #include #include +Q_DECLARE_METATYPE(QCborKnownTags) Q_DECLARE_METATYPE(QCborValue) Q_DECLARE_METATYPE(QCborValue::EncodingOptions) @@ -294,34 +295,77 @@ void tst_QCborValue::tagged() void tst_QCborValue::extendedTypes_data() { QTest::addColumn("extended"); - QTest::addColumn("tagged"); + QTest::addColumn("tag"); + QTest::addColumn("taggedValue"); + QTest::addColumn("correctedTaggedValue"); + QCborValue v(QCborValue::Invalid); QDateTime dt = QDateTime::currentDateTimeUtc(); + QDateTime dtTzOffset(dt.date(), dt.time(), Qt::OffsetFromUTC, dt.offsetFromUtc()); QUuid uuid = QUuid::createUuid(); + // non-correcting extended types (tagged value remains unchanged) QTest::newRow("DateTime") << QCborValue(dt) - << QCborValue(QCborKnownTags::DateTimeString, dt.toString(Qt::ISODateWithMs)); + << QCborKnownTags::DateTimeString << QCborValue(dt.toString(Qt::ISODateWithMs)) << v; + QTest::newRow("DateTime:TzOffset") << QCborValue(dtTzOffset) + << QCborKnownTags::DateTimeString << QCborValue(dtTzOffset.toString(Qt::ISODateWithMs)) << v; QTest::newRow("Url:Empty") << QCborValue(QUrl()) - << QCborValue(QCborKnownTags::Url, QString()); + << QCborKnownTags::Url << QCborValue(QString()) << v; QTest::newRow("Url:Authority") << QCborValue(QUrl("https://example.com")) - << QCborValue(QCborKnownTags::Url, "https://example.com"); + << QCborKnownTags::Url << QCborValue("https://example.com") << v; QTest::newRow("Url:Path") << QCborValue(QUrl("file:///tmp/none")) - << QCborValue(QCborKnownTags::Url, "file:///tmp/none"); + << QCborKnownTags::Url << QCborValue("file:///tmp/none") << v; QTest::newRow("Url:QueryFragment") << QCborValue(QUrl("whatever:?a=b&c=d#e")) - << QCborValue(QCborKnownTags::Url, "whatever:?a=b&c=d#e"); + << QCborKnownTags::Url << QCborValue("whatever:?a=b&c=d#e") << v; QTest::newRow("Regex:Empty") << QCborValue(QRegularExpression()) - << QCborValue(QCborKnownTags::RegularExpression, QString()); + << QCborKnownTags::RegularExpression << QCborValue(QString()) << v; QTest::newRow("Regex") << QCborValue(QRegularExpression("^.*$")) - << QCborValue(QCborKnownTags::RegularExpression, QString("^.*$")); + << QCborKnownTags::RegularExpression << QCborValue(QString("^.*$")) << v; QTest::newRow("Uuid") << QCborValue(uuid) - << QCborValue(QCborKnownTags::Uuid, uuid.toRfc4122()); + << QCborKnownTags::Uuid << QCborValue(uuid.toRfc4122()) << v; + + // correcting extended types + QDateTime dtNoMsecs = dt.fromSecsSinceEpoch(dt.toSecsSinceEpoch(), Qt::UTC); + QUrl url("https://example.com/\xc2\xa9 "); + QTest::newRow("UnixTime_t:Integer") << QCborValue(dtNoMsecs) << QCborKnownTags::UnixTime_t + << QCborValue(dtNoMsecs.toSecsSinceEpoch()) + << QCborValue(dtNoMsecs.toString(Qt::ISODateWithMs)); + QTest::newRow("UnixTime_t:Double") << QCborValue(dt) << QCborKnownTags::UnixTime_t + << QCborValue(dt.toMSecsSinceEpoch() / 1000.) + << QCborValue(dt.toString(Qt::ISODateWithMs)); + QTest::newRow("DateTime::JustDate") << QCborValue(QDateTime({2018, 1, 1}, {})) + << QCborKnownTags::DateTimeString + << QCborValue("2018-01-01") << QCborValue("2018-01-01T00:00:00.000"); + QTest::newRow("DateTime::TzOffset") << QCborValue(QDateTime({2018, 1, 1}, {9, 0, 0}, Qt::UTC)) + << QCborKnownTags::DateTimeString + << QCborValue("2018-01-01T09:00:00.000+00:00") + << QCborValue("2018-01-01T09:00:00.000Z"); + QTest::newRow("Url:NotNormalized") << QCborValue(url) << QCborKnownTags::Url + << QCborValue("HTTPS://EXAMPLE.COM/%c2%a9%20") + << QCborValue(url.toString()); + QTest::newRow("Uuid:Zero") << QCborValue(QUuid()) << QCborKnownTags::Uuid + << QCborValue(QByteArray()) + << QCborValue(QByteArray(sizeof(QUuid), 0)); + QTest::newRow("Uuid:TooShort") << QCborValue(QUuid(0x12345678, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) + << QCborKnownTags::Uuid + << QCborValue(raw("\x12\x34\x56\x78")) + << QCborValue(raw("\x12\x34\x56\x78" "\0\0\0\0" "\0\0\0\0" "\0\0\0\0")); + QTest::newRow("Uuid:TooLong") << QCborValue(uuid) << QCborKnownTags::Uuid + << QCborValue(uuid.toRfc4122() + "\1\2\3\4") << QCborValue(uuid.toRfc4122()); } void tst_QCborValue::extendedTypes() { QFETCH(QCborValue, extended); - QFETCH(QCborValue, tagged); + QFETCH(QCborKnownTags, tag); + QFETCH(QCborValue, taggedValue); + QFETCH(QCborValue, correctedTaggedValue); + if (correctedTaggedValue.isInvalid()) + correctedTaggedValue = taggedValue; + + QCborValue tagged(tag, taggedValue); QVERIFY(extended.isTag()); QVERIFY(tagged.isTag()); + QCOMPARE(tagged.taggedValue(), correctedTaggedValue); QVERIFY(extended == tagged); QVERIFY(tagged == extended); @@ -1224,8 +1268,11 @@ void tst_QCborValue::sorting() QCborValue va1(QCborValue::Array), va2(QCborArray{1}), va3(QCborArray{0, 0}); QCborValue vm1(QCborValue::Map), vm2(QCborMap{{1, 0}}), vm3(QCborMap{{0, 0}, {1, 0}}); QCborValue vdt1(QDateTime::fromMSecsSinceEpoch(0, Qt::UTC)), vdt2(QDateTime::currentDateTimeUtc()); - QCborValue vtagged1(QCborKnownTags::UnixTime_t, 0), vtagged2(QCborKnownTags::UnixTime_t, 0.0), - vtagged3(QCborKnownTags::Signature, 0), vtagged4(QCborTag(-2), 0), vtagged5(QCborTag(-1), 0); + QCborValue vtagged1(QCborKnownTags::PositiveBignum, QByteArray()), + vtagged2(QCborKnownTags::PositiveBignum, 0.0), // bignums are supposed to have byte arrays... + vtagged3(QCborKnownTags::Signature, 0), + vtagged4(QCborTag(-2), 0), + vtagged5(QCborTag(-1), 0); QCborValue vurl1(QUrl("https://example.net")), vurl2(QUrl("https://example.com/")); QCborValue vuuid1{QUuid()}, vuuid2(QUuid::createUuid()); QCborValue vsimple1(QCborSimpleType(1)), vsimple32(QCborSimpleType(32)), vsimple255(QCborSimpleType(255)); From 4ac850577834d680c0d2fe0280dc78cec0627e6e Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 22 Nov 2019 12:26:49 +0100 Subject: [PATCH 03/45] Show the styles example under 'gallery' on Qt Creator's example screen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add meta tag 'gallery'. Change-Id: I8d670d6eb7641bdc82944a85b7335eee26bcc573 Reviewed-by: Cristian Maureira-Fredes Reviewed-by: Topi Reiniö --- examples/widgets/doc/src/styles.qdoc | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/widgets/doc/src/styles.qdoc b/examples/widgets/doc/src/styles.qdoc index 4fea8f3bfc5..a3a02768c66 100644 --- a/examples/widgets/doc/src/styles.qdoc +++ b/examples/widgets/doc/src/styles.qdoc @@ -27,6 +27,7 @@ /*! \example widgets/styles + \meta {tag} {gallery} \title Styles Example \ingroup examples-widgets \brief The Styles example illustrates how to create custom widget From 2e7c83ea3882edd7bcc84c67c31fdc71be40e223 Mon Sep 17 00:00:00 2001 From: Jimi Huotari Date: Wed, 6 Nov 2019 00:54:57 +0200 Subject: [PATCH 04/45] Fix build with -xcb and -no-libinput Since a34e81ab [1], 'xkbcommon_support' is under 'src/platformsupport/input', and will not be defined when building with -no-libinput, and as such, 'xkbcommon_support-private' added in 'src/plugins/platforms/xcb/xcb_qpa_lib.pro' will be unknown. 1. https://code.qt.io/cgit/qt/qtbase.git/commit/?h=5.14&id=a34e81ab Change-Id: I79563b329623651b462b8fedcfb59ef5f2c2e52a Gentoo-bug: https://bugs.gentoo.org/699110 Suggested-by: Petr Zima Reviewed-by: Allan Sandfeld Jensen --- src/platformsupport/platformsupport.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platformsupport/platformsupport.pro b/src/platformsupport/platformsupport.pro index 6d4f1b93bd1..877665ff06b 100644 --- a/src/platformsupport/platformsupport.pro +++ b/src/platformsupport/platformsupport.pro @@ -11,7 +11,7 @@ SUBDIRS = \ qtConfig(freetype)|darwin|win32: \ SUBDIRS += fontdatabases -qtConfig(evdev)|qtConfig(tslib)|qtConfig(libinput)|qtConfig(integrityhid) { +qtConfig(evdev)|qtConfig(tslib)|qtConfig(libinput)|qtConfig(integrityhid)|qtConfig(xkbcommon) { SUBDIRS += input input.depends += devicediscovery } From 8c6824f2af79b6a094566d04d62a084e8448d333 Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Fri, 22 Nov 2019 17:49:06 +0100 Subject: [PATCH 05/45] CMake: Fix static build linkage with CMake version lower than 3.13 After appropriate link flags are determined, they are added to the INTERFACE_LINK_OPTIONS property. Unfortunately this property was added in 3.13, and thus static builds on Windows for instance failed with missing symbols due to missing system libraries on the link command line, when the CMake version was lower. When detecting a lower version, add the flags instead to INTERFACE_LINK_LIBRARIES, which is a property that is available in older CMake versions. To do this we have to strip the SHELL: prefix, which means that the added link flags might get deduplicated, and thus it can happen that the linking phase might still fail. Nevertheless, on Windows this improves the situation when using an older CMake version. Amends 44602224bfae7bea08e5883768cfeef6629ac503 Task-number: QTBUG-38913 Change-Id: Ib710b8ea691d4a9281dcd5f5b9700b11df0a5c10 Reviewed-by: Kyle Edwards Reviewed-by: Simon Hausmann --- .../data/cmake/Qt5BasicConfig.cmake.in | 34 ++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in index 364c23e750c..5077b8d8b46 100644 --- a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in +++ b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in @@ -173,11 +173,20 @@ macro(_populate_$${CMAKE_MODULE_NAME}_target_properties Configuration LIB_LOCATI endif() set(_static_link_flags \"${_Qt5$${CMAKE_MODULE_NAME}_STATIC_${Configuration}_LINK_FLAGS}\") - if(NOT CMAKE_VERSION VERSION_LESS \"3.13\" AND _static_link_flags) + if(_static_link_flags) set(_static_link_flags_genex \"$<${_genex_condition}:${_static_link_flags}>\") - set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} APPEND PROPERTY INTERFACE_LINK_OPTIONS - \"${_static_link_flags_genex}\" - ) + if(NOT CMAKE_VERSION VERSION_LESS \"3.13\") + set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} APPEND PROPERTY INTERFACE_LINK_OPTIONS + \"${_static_link_flags_genex}\" + ) + else() + # Abuse INTERFACE_LINK_LIBRARIES to add link flags when CMake version is too low. + # Strip out SHELL:, because it is not supported in this property. And hope for the best. + string(REPLACE \"SHELL:\" \"\" _static_link_flags_genex \"${_static_link_flags_genex}\") + set_property(TARGET Qt5::$${CMAKE_MODULE_NAME} APPEND PROPERTY INTERFACE_LINK_LIBRARIES + \"${_static_link_flags_genex}\" + ) + endif() endif() !!ENDIF @@ -546,11 +555,20 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME}) endif() set(_static_link_flags \"${_Qt5${Plugin}_STATIC_${Configuration}_LINK_FLAGS}\") - if(NOT CMAKE_VERSION VERSION_LESS \"3.13\" AND _static_link_flags) + if(_static_link_flags) set(_static_link_flags_genex \"$<${_genex_condition}:${_static_link_flags}>\") - set_property(TARGET Qt5::${Plugin} APPEND PROPERTY INTERFACE_LINK_OPTIONS - \"${_static_link_flags_genex}\" - ) + if(NOT CMAKE_VERSION VERSION_LESS \"3.13\") + set_property(TARGET Qt5::${Plugin} APPEND PROPERTY INTERFACE_LINK_OPTIONS + \"${_static_link_flags_genex}\" + ) + else() + # Abuse INTERFACE_LINK_LIBRARIES to add link flags when CMake version is too low. + # Strip out SHELL:, because it is not supported in this property. And hope for the best. + string(REPLACE \"SHELL:\" \"\" _static_link_flags_genex \"${_static_link_flags_genex}\") + set_property(TARGET Qt5::${Plugin} APPEND PROPERTY INTERFACE_LINK_LIBRARIES + \"${_static_link_flags_genex}\" + ) + endif() endif() !!ENDIF endmacro() From 84892e5e69e7e44cb1fb77b2ba2338114554a7d2 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Fri, 15 Nov 2019 11:29:02 +0100 Subject: [PATCH 06/45] Get make docs working better on macOS The system include paths need to be added to the include paths passed to Clang so it can find the standard types. Change-Id: I83e13e73a606130e3bc4762b01368bcd4a8bb0dc Reviewed-by: Paul Wicking --- mkspecs/features/qt_docs.prf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mkspecs/features/qt_docs.prf b/mkspecs/features/qt_docs.prf index deb4ac28292..095bf15dac9 100644 --- a/mkspecs/features/qt_docs.prf +++ b/mkspecs/features/qt_docs.prf @@ -45,6 +45,8 @@ isEmpty(WIN_INCLUDETEMP) { QDOC_INCLUDE_PATHS=@$$shell_quote($$WIN_INCLUDETEMP) } +macos: QDOC_INCLUDE_PATHS += $$join(QMAKE_DEFAULT_INCDIRS," -I","-I") + !build_online_docs: qtPrepareTool(QHELPGENERATOR, qhelpgenerator) qtPrepareTool(QTATTRIBUTIONSSCANNER, qtattributionsscanner) @@ -93,7 +95,6 @@ qtattributionsscanner.CONFIG += phony QMAKE_EXTRA_TARGETS += qtattributionsscanner doc_command = $$QDOC $$QMAKE_DOCS - prepare_docs { prepare_docs.commands += $$doc_command -prepare $$PREP_DOC_INDEXES -no-link-errors $$QDOC_INCLUDE_PATHS generate_docs.commands += $$doc_command -generate $$DOC_INDEXES $$QDOC_INCLUDE_PATHS From 3c90ac02d1a6dc383c21d3911f0db881f9341802 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Sun, 24 Nov 2019 21:40:13 +0100 Subject: [PATCH 07/45] macOS: Replace use of deprecated NSDragPboard enum Change-Id: I90128abe310f971a89ecb6551e31950211adda77 Reviewed-by: Timur Pocheptsov --- src/plugins/platforms/cocoa/qcocoadrag.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoadrag.mm b/src/plugins/platforms/cocoa/qcocoadrag.mm index 09433194a63..95808b8a111 100644 --- a/src/plugins/platforms/cocoa/qcocoadrag.mm +++ b/src/plugins/platforms/cocoa/qcocoadrag.mm @@ -134,7 +134,7 @@ Qt::DropAction QCocoaDrag::drag(QDrag *o) NSImage *nsimage = qt_mac_create_nsimage(pm); [nsimage setSize:NSSizeFromCGSize(pmDeviceIndependentSize.toCGSize())]; - QMacPasteboard dragBoard((CFStringRef) NSDragPboard, QMacInternalPasteboardMime::MIME_DND); + QMacPasteboard dragBoard(CFStringRef(NSPasteboardNameDrag), QMacInternalPasteboardMime::MIME_DND); m_drag->mimeData()->setData(QLatin1String("application/x-qt-mime-type-name"), QByteArray("dummy")); dragBoard.setMimeData(m_drag->mimeData(), QMacPasteboard::LazyRequest); @@ -145,7 +145,7 @@ Qt::DropAction QCocoaDrag::drag(QDrag *o) CGFloat flippedY = pmDeviceIndependentSize.height() - hotSpot.y(); event_location.y -= flippedY; NSSize mouseOffset_unused = NSMakeSize(0.0, 0.0); - NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSDragPboard]; + NSPasteboard *pboard = [NSPasteboard pasteboardWithName:NSPasteboardNameDrag]; [theWindow dragImage:nsimage at:event_location From 770a1d71560f7195fed0ada523884784bc89f791 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Sun, 24 Nov 2019 21:57:35 +0100 Subject: [PATCH 08/45] macOS: Replace use of deprecated acceptsTouchEvents API The equivalent of setting acceptsTouchEvents to YES is enabling indirect touches. Direct touches are enabled by default by AppKit, but can be explicitly disabled by clearing the NSTouchTypeMaskDirect bit. Change-Id: I5ba09d36f6ee2ce962e3ce21bab06537dd1fa5ad Reviewed-by: Timur Pocheptsov --- src/plugins/platforms/cocoa/qcocoawindow.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 15329ca7081..6e2d446898e 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -1692,9 +1692,9 @@ void QCocoaWindow::registerTouch(bool enable) { m_registerTouchCount += enable ? 1 : -1; if (enable && m_registerTouchCount == 1) - [m_view setAcceptsTouchEvents:YES]; + m_view.allowedTouchTypes |= NSTouchTypeMaskIndirect; else if (m_registerTouchCount == 0) - [m_view setAcceptsTouchEvents:NO]; + m_view.allowedTouchTypes &= ~NSTouchTypeMaskIndirect; } void QCocoaWindow::setContentBorderThickness(int topThickness, int bottomThickness) From b8cf3c35002affe9f1876dd3940d75171be43f64 Mon Sep 17 00:00:00 2001 From: Andre de la Rocha Date: Fri, 22 Nov 2019 19:44:48 +0100 Subject: [PATCH 09/45] Windows QPA: Disable the native Windows OSK if Qt Virtual Keyboard is in use This change detects that the Qt Virtual Keyboard is in use through the QT_IM_MODULE environment variable and disables the native Windows OSK accordingly, to avoid showing both virtual keyboards at the same time. Task-number: QTBUG-76088 Change-Id: I2715b337e6de729f0514ea1892b94b3c4f9cd984 Reviewed-by: Friedemann Kleint --- .../platforms/windows/qwindowsinputcontext.cpp | 7 +++++-- .../windows/uiautomation/qwindowsuiamainprovider.cpp | 12 +++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp index 079c25f9eb3..19d632dc105 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp @@ -283,8 +283,11 @@ void QWindowsInputContext::showInputPanel() // We only call ShowCaret() on Windows 10 after 1703 as in earlier versions // the caret would actually be visible (QTBUG-74492) and the workaround for // the Surface seems unnecessary there anyway. But leave it hidden for IME. - if (QOperatingSystemVersion::current() >= - QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 16299)) { + // Only trigger the native OSK if the Qt OSK is not in use. + static bool imModuleEmpty = qEnvironmentVariableIsEmpty("QT_IM_MODULE"); + if (imModuleEmpty + && QOperatingSystemVersion::current() + >= QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 16299)) { ShowCaret(platformWindow->handle()); } else { HideCaret(platformWindow->handle()); diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp index f589fd6b109..e5a9f275ae9 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp @@ -390,7 +390,17 @@ HRESULT QWindowsUiaMainProvider::GetPropertyValue(PROPERTYID idProp, VARIANT *pR setVariantI4(UIA_WindowControlTypeId, pRetVal); } else { // Control type converted from role. - setVariantI4(roleToControlTypeId(accessible->role()), pRetVal); + auto controlType = roleToControlTypeId(accessible->role()); + + // The native OSK should be disbled if the Qt OSK is in use. + static bool imModuleEmpty = qEnvironmentVariableIsEmpty("QT_IM_MODULE"); + + // If we want to disable the native OSK auto-showing + // we have to report text fields as non-editable. + if (controlType == UIA_EditControlTypeId && !imModuleEmpty) + controlType = UIA_TextControlTypeId; + + setVariantI4(controlType, pRetVal); } break; case UIA_HelpTextPropertyId: From 9a82a290001ff720a084f57b67663949d34d4c9a Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 21 Nov 2019 13:12:31 +0100 Subject: [PATCH 10/45] Styles example: Use system style per Default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The example is useful as a gallery for widgets in which case the custom Norwegian Wood style is not primarily interesting. Change-Id: I96e304f97edeb43da6e8f572e01a768b1317722c Reviewed-by: Topi Reiniö --- examples/widgets/widgets/styles/widgetgallery.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/examples/widgets/widgets/styles/widgetgallery.cpp b/examples/widgets/widgets/styles/widgetgallery.cpp index fd8f0ec2d16..7e1616c6c05 100644 --- a/examples/widgets/widgets/styles/widgetgallery.cpp +++ b/examples/widgets/widgets/styles/widgetgallery.cpp @@ -65,6 +65,7 @@ #include #include #include +#include #include #include #include @@ -77,8 +78,16 @@ WidgetGallery::WidgetGallery(QWidget *parent) originalPalette = QApplication::palette(); styleComboBox = new QComboBox; - styleComboBox->addItem("NorwegianWood"); - styleComboBox->addItems(QStyleFactory::keys()); + const QString defaultStyleName = QApplication::style()->objectName(); + QStringList styleNames = QStyleFactory::keys(); + styleNames.append("NorwegianWood"); + for (int i = 1, size = styleNames.size(); i < size; ++i) { + if (defaultStyleName.compare(styleNames.at(i), Qt::CaseInsensitive) == 0) { + styleNames.swapItemsAt(0, i); + break; + } + } + styleComboBox->addItems(styleNames); styleLabel = new QLabel(tr("&Style:")); styleLabel->setBuddy(styleComboBox); @@ -134,7 +143,6 @@ WidgetGallery::WidgetGallery(QWidget *parent) setLayout(mainLayout); setWindowTitle(tr("Styles")); - changeStyle("NorwegianWood"); } //! [4] From 31e94dc96cf372db27d9a064e770180178f70156 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sat, 23 Nov 2019 01:54:38 +0100 Subject: [PATCH 11/45] QGb18030Codec: fix out-of-bounds access when decoding surrogate pairs This is already the second surrogate of the pair, there's no need to + +i. Fixes: QTBUG-80268 Change-Id: Ia2aa807ffa8a4c798425fffd15d9a48ee0ca8ed7 Reviewed-by: Lars Knoll --- src/corelib/codecs/qgb18030codec.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/corelib/codecs/qgb18030codec.cpp b/src/corelib/codecs/qgb18030codec.cpp index 4206eacb6f8..ca15be1ceaf 100644 --- a/src/corelib/codecs/qgb18030codec.cpp +++ b/src/corelib/codecs/qgb18030codec.cpp @@ -107,7 +107,6 @@ QByteArray QGb18030Codec::convertFromUnicode(const QChar *uc, int len, Converter if (high >= 0) { if (uc[i].isLowSurrogate()) { // valid surrogate pair - ++i; uint u = QChar::surrogateToUcs4(high, uc[i].unicode()); len = qt_UnicodeToGb18030(u, buf); if (len >= 2) { From da0af1e21de6eda849dacf0283c78fbd36fd4f3f Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Thu, 21 Nov 2019 11:14:53 +0100 Subject: [PATCH 12/45] Doc: Improve explanation of QLineEdit input mask The explanation of the input mask syntax and behavior was somewhat unclear. Task-number: QTBUG-76320 Change-Id: I45dc4a883c491d3dc08125b0f7efad46f2a9a33f Reviewed-by: Friedemann Kleint Reviewed-by: Richard Moe Gustavsen --- src/widgets/widgets/qlineedit.cpp | 33 ++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp index fb679367689..658315028af 100644 --- a/src/widgets/widgets/qlineedit.cpp +++ b/src/widgets/widgets/qlineedit.cpp @@ -1198,12 +1198,18 @@ QMargins QLineEdit::textMargins() const Unset the mask and return to normal QLineEdit operation by passing an empty string (""). - The table below shows the characters that can be used in an input mask. - A space character, the default character for a blank, is needed for cases - where a character is \e{permitted but not required}. + The input mask is an input template string. It can contain the following elements: + \table + \row \li Mask Characters \li Defines the class of input characters that are + considered valid in this position + \row \li Meta Characters \li Various special meanings + \row \li Separators \li All other characters are regarded as immutable separators + \endtable + + The following table shows the mask and meta characters that can be used in an input mask. \table - \header \li Character \li Meaning + \header \li Mask Character \li Meaning \row \li \c A \li ASCII alphabetic character required. A-Z, a-z. \row \li \c a \li ASCII alphabetic character permitted but not required. \row \li \c N \li ASCII alphanumeric character required. A-Z, a-z, 0-9. @@ -1219,19 +1225,28 @@ QMargins QLineEdit::textMargins() const \row \li \c h \li Hexadecimal character permitted but not required. \row \li \c B \li Binary character required. 0-1. \row \li \c b \li Binary character permitted but not required. + \header \li Meta Character \li Meaning \row \li \c > \li All following alphabetic characters are uppercased. \row \li \c < \li All following alphabetic characters are lowercased. \row \li \c ! \li Switch off case conversion. + \row \li \c {;c} \li Terminates the input mask and sets the \e{blank} character to \e{c}. \row \li \c {[ ] { }} \li Reserved. \row \li \tt{\\} \li Use \tt{\\} to escape the special characters listed above to use them as separators. \endtable - The mask consists of a string of mask characters and separators, - optionally followed by a semicolon and the character used for - blanks. The blank characters are always removed from the text - after editing. + When created or cleared, the line edit will be filled with a copy of the + input mask string where the meta characters have been removed, and the mask + characters have been replaced with the \e{blank} character (by default, a + \c space). + + When an input mask is set, the text() method returns a modified copy of the + line edit content where all the \e{blank} characters have been removed. The + unmodified content can be read using displayText(). + + The hasAcceptableInput() method returns false if the current content of the + line edit does not fulfil the requirements of the input mask. Examples: \table @@ -1240,7 +1255,7 @@ QMargins QLineEdit::textMargins() const \row \li \c HH:HH:HH:HH:HH:HH;_ \li MAC address \row \li \c 0000-00-00 \li ISO Date; blanks are \c space \row \li \c >AAAAA-AAAAA-AAAAA-AAAAA-AAAAA;# \li License number; - blanks are \c - and all (alphabetic) characters are converted to + blanks are \c{#} and all (alphabetic) characters are converted to uppercase. \endtable From e1d173d3cac8d100e23ecfe2dd0556d3ff5ed1af Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 26 Nov 2019 14:35:14 +0100 Subject: [PATCH 13/45] Fix qdoc include paths for QStandardPaths Amends c30ffe1d33e6f48fa94e2003d7c9b17f4c83a6e9. Fix src/corelib/io/qstandardpaths.cpp:361: (qdoc) warning: Cannot find qdoc include file 'standardpath/functiondoc.qdocinc' src/corelib/io/qstandardpaths.cpp:368: (qdoc) warning: Cannot find qdoc include file 'standardpath/functiondoc.qdocinc' src/corelib/io/qstandardpaths.cpp:392: (qdoc) warning: Cannot find qdoc include file 'standardpath/functiondoc.qdocinc' src/corelib/io/qstandardpaths.cpp:406: (qdoc) warning: Cannot find qdoc include file 'standardpath/functiondoc.qdocinc' src/corelib/io/qstandardpaths.cpp:479: (qdoc) warning: Cannot find qdoc include file 'standardpath/functiondoc.qdocinc' src/corelib/io/qstandardpaths.cpp:537: (qdoc) warning: Cannot find qdoc include file 'standardpath/functiondoc.qdocinc' src/corelib/io/qstandardpaths.cpp:594: (qdoc) warning: Cannot find qdoc include file 'standardpath/functiondoc.qdocinc' Task-number: QTBUG-79827 Change-Id: I8eb0ae7bc167151979c729964d2dc3f171e10568 Reviewed-by: Paul Wicking --- src/corelib/io/qstandardpaths.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/corelib/io/qstandardpaths.cpp b/src/corelib/io/qstandardpaths.cpp index 6ebef3ee20b..02adda3d6cf 100644 --- a/src/corelib/io/qstandardpaths.cpp +++ b/src/corelib/io/qstandardpaths.cpp @@ -357,14 +357,14 @@ QT_BEGIN_NAMESPACE /*! \fn QString QStandardPaths::writableLocation(StandardLocation type) - \include standardpath/functiondoc.qdocinc writableLocation + \include standardpath/functiondocs.qdocinc writableLocation */ /*! \fn QStringList QStandardPaths::standardLocations(StandardLocation type) - \include standardpath/functiondoc.qdocinc standardLocations + \include standardpath/functiondocs.qdocinc standardLocations \sa writableLocation() */ @@ -388,7 +388,7 @@ static bool existsAsSpecified(const QString &path, QStandardPaths::LocateOptions } /*! - \include standardpath/functiondoc.qdocinc locate + \include standardpath/functiondocs.qdocinc locate */ QString QStandardPaths::locate(StandardLocation type, const QString &fileName, LocateOptions options) { @@ -402,7 +402,7 @@ QString QStandardPaths::locate(StandardLocation type, const QString &fileName, L } /*! - \include standardpath/functiondoc.qdocinc locateAll + \include standardpath/functiondocs.qdocinc locateAll */ QStringList QStandardPaths::locateAll(StandardLocation type, const QString &fileName, LocateOptions options) { @@ -475,7 +475,7 @@ static inline QString #endif // Q_OS_WIN /*! - \include standardpath/functiondoc.qdocinc findExecutable + \include standardpath/functiondocs.qdocinc findExecutable */ QString QStandardPaths::findExecutable(const QString &executableName, const QStringList &paths) { @@ -533,7 +533,7 @@ QString QStandardPaths::findExecutable(const QString &executableName, const QStr } /*! - \include standardpath/functiondoc.qdocinc displayName + \include standardpath/functiondocs.qdocinc displayName */ #if !defined(Q_OS_MAC) && !defined(QT_BOOTSTRAPPED) @@ -590,7 +590,7 @@ QString QStandardPaths::displayName(StandardLocation type) /*! \fn void QStandardPaths::setTestModeEnabled(bool testMode) - \include standardpath/functiondoc.qdocinc setTestModeEnabled + \include standardpath/functiondocs.qdocinc setTestModeEnabled */ static bool qsp_testMode = false; From cd3585ab159c3d0614f418fd148b7cea77ea6d12 Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Sun, 24 Nov 2019 12:40:17 +0100 Subject: [PATCH 14/45] QDial: use correct button color When the pixmap for the QDial was cached, the button color for the knob was not properly set Fixes: QTBUG-19855 Change-Id: Ib09ac12f0b11c47a0d05f01759fc6eeadbeab06c Reviewed-by: Friedemann Kleint Reviewed-by: Richard Moe Gustavsen --- src/widgets/styles/qstylehelper.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/widgets/styles/qstylehelper.cpp b/src/widgets/styles/qstylehelper.cpp index 4e61b2d1ecb..9477ca86da8 100644 --- a/src/widgets/styles/qstylehelper.cpp +++ b/src/widgets/styles/qstylehelper.cpp @@ -274,6 +274,12 @@ void drawDial(const QStyleOptionSlider *option, QPainter *painter) painter->drawLines(QStyleHelper::calcLines(option)); } + // setting color before BEGIN_STYLE_PIXMAPCACHE since + // otherwise it is not set when the image is in the cache + buttonColor.setHsv(buttonColor .hue(), + qMin(140, buttonColor .saturation()), + qMax(180, buttonColor.value())); + // Cache dial background BEGIN_STYLE_PIXMAPCACHE(QString::fromLatin1("qdial")); p->setRenderHint(QPainter::Antialiasing); @@ -285,9 +291,6 @@ void drawDial(const QStyleOptionSlider *option, QPainter *painter) QRectF br = QRectF(dx + 0.5, dy + 0.5, int(r * 2 - 2 * d_ - 2), int(r * 2 - 2 * d_ - 2)); - buttonColor.setHsv(buttonColor .hue(), - qMin(140, buttonColor .saturation()), - qMax(180, buttonColor.value())); if (enabled) { // Drop shadow From d5608ca43756ed62678e60215da71827dd26a900 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 24 May 2017 09:21:09 -0400 Subject: [PATCH 15/45] Qt5CoreMacros: properly check the CMake version The POSITION_INDEPENDENT_CODE property was introduced in 2.8.12, so use it in versions newer than 2.8.12. Fixes: QTBUG-79671 Change-Id: If7f023e80964f2e47edc35eee617b51aeecbf032 Reviewed-by: Kai Koehne --- src/corelib/Qt5CoreMacros.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/Qt5CoreMacros.cmake b/src/corelib/Qt5CoreMacros.cmake index 17cc19fc4e2..84c75401b1a 100644 --- a/src/corelib/Qt5CoreMacros.cmake +++ b/src/corelib/Qt5CoreMacros.cmake @@ -385,7 +385,7 @@ if (NOT CMAKE_VERSION VERSION_LESS 2.8.9) set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_RELWITHDEBINFO QT_NO_DEBUG) set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_MINSIZEREL QT_NO_DEBUG) if (Qt5_POSITION_INDEPENDENT_CODE - AND (CMAKE_VERSION VERSION_LESS 2.8.12 + AND (CMAKE_VERSION VERSION_GREATER_EQUAL 2.8.12 AND (NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0))) set_property(TARGET ${_target} PROPERTY POSITION_INDEPENDENT_CODE ${Qt5_POSITION_INDEPENDENT_CODE}) From 8a60244da8f34aaa4ba0f71ada5b87aee33e0715 Mon Sep 17 00:00:00 2001 From: Fredrik Orderud Date: Sun, 24 Nov 2019 21:45:46 +0100 Subject: [PATCH 16/45] Fix renderbufferStorageMultisample: invalid internalformat Chrome 78 is outputting "INVALID_ENUM: renderbufferStorageMultisample: invalid internalformat" when running a Qt application after building it for WebAssembly (WASM) against the Qt 5.13 branch using the Emscripten 1.39.3 (upstream) compiler. The problem appear to be caused by glRenderbufferStorageMultisample not supporting GL_DEPTH_STENCIL directly. Instead, GL_DEPTH24_STENCIL8 or GL_DEPTH32F_STENCIL8 should be passed. Keeping the glRenderbufferStorage call as-is. Change-Id: I777dbc26b1d989950525a434a25ed344389f5059 Reference: https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glRenderbufferStorageMultisample.xhtml Fixes: QTBUG-80286 Reviewed-by: Laszlo Agocs --- src/gui/opengl/qopenglframebufferobject.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp index 5d308915650..bb0dbdc9bdf 100644 --- a/src/gui/opengl/qopenglframebufferobject.cpp +++ b/src/gui/opengl/qopenglframebufferobject.cpp @@ -658,13 +658,11 @@ void QOpenGLFramebufferObjectPrivate::initDepthStencilAttachments(QOpenGLContext funcs.glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer); Q_ASSERT(funcs.glIsRenderbuffer(depth_buffer)); - GLenum storageFormat = GL_DEPTH_STENCIL; - if (samples != 0 ) { funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, - storageFormat, dsSize.width(), dsSize.height()); + GL_DEPTH24_STENCIL8, dsSize.width(), dsSize.height()); } else { - funcs.glRenderbufferStorage(GL_RENDERBUFFER, storageFormat, + funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL, dsSize.width(), dsSize.height()); } From 6566157df3c5a1352231be87c7b7d2705a46efe3 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 13 Nov 2019 18:42:00 +0100 Subject: [PATCH 17/45] Make Qt::RFC2822Date's doc match up with its implementation The qdatetime implementation's rfcDateImpl() uses regexes which did not match its comments; nor did either the regexes or the comments match what was documented. A review of relevant RFCs suggests we should revise this in future, probably at Qt 6. The documentation also only addressed the formats recognized when parsing a date-time, without indicating how they are serialised or how dates and times are handled separately. Added a note to the tests for the read-only formats, to remind the reader that the RFCs merely recommend recognising these - be permissive in what you expect and strict in what you deliver. Change-Id: I0f0bec752e7a50bde98cceceb7e0d11be15c6a6f Reviewed-by: Thiago Macieira --- src/corelib/global/qnamespace.qdoc | 16 ++++++++++++---- src/corelib/time/qdatetime.cpp | 4 ++-- tests/auto/corelib/time/qdate/tst_qdate.cpp | 2 +- .../corelib/time/qdatetime/tst_qdatetime.cpp | 2 +- tests/auto/corelib/time/qtime/tst_qtime.cpp | 2 +- 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index cce88782e95..bebe67be3f9 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the documentation of the Qt Toolkit. @@ -724,9 +724,17 @@ \value LocalDate \e{This enum value is deprecated.} Use Qt::SystemLocaleShortDate instead (or Qt::SystemLocaleLongDate if you want long dates). - \value RFC2822Date \l{RFC 2822}, \l{RFC 850} and \l{RFC 1036} format: either - \c{[ddd,] dd MMM yyyy hh:mm[:ss] +/-TZ} or \c{ddd MMM dd yyyy hh:mm[:ss] +/-TZ} - for combined dates and times. + \value RFC2822Date \l{RFC 2822}, \l{RFC 850} and \l{RFC 1036} format: + either \c{[ddd,] dd MMM yyyy [hh:mm[:ss]][ ±tzoff]} + or \c{ddd MMM dd[ hh:mm:ss] yyyy[ ±tzoff]} are recognized for combined dates + and times, where \c{tzoff} is a timezone offset in \c{hhmm} format. For + dates and times separately, the same formats are matched and the unwanted + parts are ignored. In particular, note that a time is not recognized without + an accompanying date. When converting dates to string form, + format \c{dd MMM yyyy} is used, for times the format is \c{hh:mm:ss}. For + combined date and time, these are combined + as \c{dd MMM yyyy hh:mm:ss ±tzoff} (omitting the optional leading day of the + week from the first format recognized). \note For \c ISODate formats, each \c Y, \c M and \c D represents a single digit of the year, month and day used to specify the date. Each \c H, \c M and \c S diff --git a/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp index 878a2c1e461..e6213c44c0b 100644 --- a/src/corelib/time/qdatetime.cpp +++ b/src/corelib/time/qdatetime.cpp @@ -164,7 +164,7 @@ static ParsedRfcDateTime rfcDateImpl(const QString &s) { ParsedRfcDateTime result; - // Matches "Wdy, dd Mon yyyy HH:mm:ss ±hhmm" (Wdy, being optional) + // Matches "[ddd,] dd MMM yyyy[ hh:mm[:ss]] [±hhmm]" - correct RFC 822, 2822, 5322 format QRegExp rex(QStringLiteral("^(?:[A-Z][a-z]+,)?[ \\t]*(\\d{1,2})[ \\t]+([A-Z][a-z]+)[ \\t]+(\\d\\d\\d\\d)(?:[ \\t]+(\\d\\d):(\\d\\d)(?::(\\d\\d))?)?[ \\t]*(?:([+-])(\\d\\d)(\\d\\d))?")); if (s.indexOf(rex) == 0) { const QStringList cap = rex.capturedTexts(); @@ -176,7 +176,7 @@ static ParsedRfcDateTime rfcDateImpl(const QString &s) const int minOffset = cap[9].toInt(); result.utcOffset = ((hourOffset * 60 + minOffset) * (positiveOffset ? 60 : -60)); } else { - // Matches "Wdy Mon dd HH:mm:ss yyyy" + // Matches "ddd MMM dd[ hh:mm:ss] yyyy [±hhmm]" - permissive RFC 850, 1036 (read only) QRegExp rex(QStringLiteral("^[A-Z][a-z]+[ \\t]+([A-Z][a-z]+)[ \\t]+(\\d\\d)(?:[ \\t]+(\\d\\d):(\\d\\d):(\\d\\d))?[ \\t]+(\\d\\d\\d\\d)[ \\t]*(?:([+-])(\\d\\d)(\\d\\d))?")); if (s.indexOf(rex) == 0) { const QStringList cap = rex.capturedTexts(); diff --git a/tests/auto/corelib/time/qdate/tst_qdate.cpp b/tests/auto/corelib/time/qdate/tst_qdate.cpp index 73384c35f46..0f2f55ef2e4 100644 --- a/tests/auto/corelib/time/qdate/tst_qdate.cpp +++ b/tests/auto/corelib/time/qdate/tst_qdate.cpp @@ -1165,7 +1165,7 @@ void tst_QDate::fromStringDateFormat_data() QTest::newRow("RFC 2822 invalid character 2 at front") << QString::fromLatin1("!!01 Jan 2012 08:00:00 +0000") << Qt::RFC2822Date << QDate(); - // Test Qt::RFC2822Date format (RFC 850 and 1036). + // Test Qt::RFC2822Date format (RFC 850 and 1036, permissive). QTest::newRow("RFC 850 and 1036") << QString::fromLatin1("Fri Feb 13 13:24:51 1987 +0100") << Qt::RFC2822Date << QDate(1987, 2, 13); // No timezone diff --git a/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp index 216ae1f79e9..a5482657aa0 100644 --- a/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp @@ -2351,7 +2351,7 @@ void tst_QDateTime::fromStringDateFormat_data() QTest::newRow("RFC 2822 invalid character 2 at front") << QString::fromLatin1("!!01 Jan 2012 08:00:00 +0000") << Qt::RFC2822Date << invalidDateTime(); - // Test Qt::RFC2822Date format (RFC 850 and 1036). + // Test Qt::RFC2822Date format (RFC 850 and 1036, permissive). QTest::newRow("RFC 850 and 1036 +0100") << QString::fromLatin1("Fri Feb 13 13:24:51 1987 +0100") << Qt::RFC2822Date << QDateTime(QDate(1987, 2, 13), QTime(12, 24, 51), Qt::UTC); QTest::newRow("RFC 850 and 1036 -0100") << QString::fromLatin1("Fri Feb 13 13:24:51 1987 -0100") diff --git a/tests/auto/corelib/time/qtime/tst_qtime.cpp b/tests/auto/corelib/time/qtime/tst_qtime.cpp index 3403c5bf7f8..b2bb5dbb24c 100644 --- a/tests/auto/corelib/time/qtime/tst_qtime.cpp +++ b/tests/auto/corelib/time/qtime/tst_qtime.cpp @@ -648,7 +648,7 @@ void tst_QTime::fromStringDateFormat_data() QTest::newRow("RFC 2822 invalid character 2 at front") << QString::fromLatin1("!!01 Jan 2012 08:00:00 +0000") << Qt::RFC2822Date << invalidTime(); - // Test Qt::RFC2822Date format (RFC 850 and 1036). + // Test Qt::RFC2822Date format (RFC 850 and 1036, permissive). QTest::newRow("RFC 850 and 1036") << QString::fromLatin1("Fri Feb 13 13:24:51 1987 +0100") << Qt::RFC2822Date << QTime(13, 24, 51); // No timezone From 0debb205b23a39b79650861de0e61cf4cf00286c Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Thu, 14 Nov 2019 16:40:21 +0100 Subject: [PATCH 18/45] Permit leading space at start of RFC 2822 Date format Relevant RFCs explicitly permit such space. Change-Id: I8eb444e96287368cbbf973c77513b43d1d36f972 Reviewed-by: Thiago Macieira --- src/corelib/time/qdatetime.cpp | 4 ++-- tests/auto/corelib/time/qdate/tst_qdate.cpp | 9 +++++++++ .../auto/corelib/time/qdatetime/tst_qdatetime.cpp | 14 ++++++++++++++ tests/auto/corelib/time/qtime/tst_qtime.cpp | 9 +++++++++ 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp index e6213c44c0b..9b0bc688c98 100644 --- a/src/corelib/time/qdatetime.cpp +++ b/src/corelib/time/qdatetime.cpp @@ -165,7 +165,7 @@ static ParsedRfcDateTime rfcDateImpl(const QString &s) ParsedRfcDateTime result; // Matches "[ddd,] dd MMM yyyy[ hh:mm[:ss]] [±hhmm]" - correct RFC 822, 2822, 5322 format - QRegExp rex(QStringLiteral("^(?:[A-Z][a-z]+,)?[ \\t]*(\\d{1,2})[ \\t]+([A-Z][a-z]+)[ \\t]+(\\d\\d\\d\\d)(?:[ \\t]+(\\d\\d):(\\d\\d)(?::(\\d\\d))?)?[ \\t]*(?:([+-])(\\d\\d)(\\d\\d))?")); + QRegExp rex(QStringLiteral("^[ \\t]*(?:[A-Z][a-z]+,)?[ \\t]*(\\d{1,2})[ \\t]+([A-Z][a-z]+)[ \\t]+(\\d\\d\\d\\d)(?:[ \\t]+(\\d\\d):(\\d\\d)(?::(\\d\\d))?)?[ \\t]*(?:([+-])(\\d\\d)(\\d\\d))?")); if (s.indexOf(rex) == 0) { const QStringList cap = rex.capturedTexts(); result.date = QDate(cap[3].toInt(), qt_monthNumberFromShortName(cap[2]), cap[1].toInt()); @@ -177,7 +177,7 @@ static ParsedRfcDateTime rfcDateImpl(const QString &s) result.utcOffset = ((hourOffset * 60 + minOffset) * (positiveOffset ? 60 : -60)); } else { // Matches "ddd MMM dd[ hh:mm:ss] yyyy [±hhmm]" - permissive RFC 850, 1036 (read only) - QRegExp rex(QStringLiteral("^[A-Z][a-z]+[ \\t]+([A-Z][a-z]+)[ \\t]+(\\d\\d)(?:[ \\t]+(\\d\\d):(\\d\\d):(\\d\\d))?[ \\t]+(\\d\\d\\d\\d)[ \\t]*(?:([+-])(\\d\\d)(\\d\\d))?")); + QRegExp rex(QStringLiteral("^[ \\t]*[A-Z][a-z]+[ \\t]+([A-Z][a-z]+)[ \\t]+(\\d\\d)(?:[ \\t]+(\\d\\d):(\\d\\d):(\\d\\d))?[ \\t]+(\\d\\d\\d\\d)[ \\t]*(?:([+-])(\\d\\d)(\\d\\d))?")); if (s.indexOf(rex) == 0) { const QStringList cap = rex.capturedTexts(); result.date = QDate(cap[6].toInt(), qt_monthNumberFromShortName(cap[1]), cap[2].toInt()); diff --git a/tests/auto/corelib/time/qdate/tst_qdate.cpp b/tests/auto/corelib/time/qdate/tst_qdate.cpp index 0f2f55ef2e4..63fdbbbe922 100644 --- a/tests/auto/corelib/time/qdate/tst_qdate.cpp +++ b/tests/auto/corelib/time/qdate/tst_qdate.cpp @@ -1136,8 +1136,14 @@ void tst_QDate::fromStringDateFormat_data() // Test Qt::RFC2822Date format (RFC 2822). QTest::newRow("RFC 2822") << QString::fromLatin1("13 Feb 1987 13:24:51 +0100") << Qt::RFC2822Date << QDate(1987, 2, 13); + QTest::newRow("RFC 2822 after space") + << QString::fromLatin1(" 13 Feb 1987 13:24:51 +0100") + << Qt::RFC2822Date << QDate(1987, 2, 13); QTest::newRow("RFC 2822 with day") << QString::fromLatin1("Thu, 01 Jan 1970 00:12:34 +0000") << Qt::RFC2822Date << QDate(1970, 1, 1); + QTest::newRow("RFC 2822 with day after space") + << QString::fromLatin1(" Thu, 01 Jan 1970 00:12:34 +0000") + << Qt::RFC2822Date << QDate(1970, 1, 1); // No timezone QTest::newRow("RFC 2822 no timezone") << QString::fromLatin1("01 Jan 1970 00:12:34") << Qt::RFC2822Date << QDate(1970, 1, 1); @@ -1168,6 +1174,9 @@ void tst_QDate::fromStringDateFormat_data() // Test Qt::RFC2822Date format (RFC 850 and 1036, permissive). QTest::newRow("RFC 850 and 1036") << QString::fromLatin1("Fri Feb 13 13:24:51 1987 +0100") << Qt::RFC2822Date << QDate(1987, 2, 13); + QTest::newRow("RFC 850 and 1036 after space") + << QString::fromLatin1(" Fri Feb 13 13:24:51 1987 +0100") + << Qt::RFC2822Date << QDate(1987, 2, 13); // No timezone QTest::newRow("RFC 850 and 1036 no timezone") << QString::fromLatin1("Thu Jan 01 00:12:34 1970") << Qt::RFC2822Date << QDate(1970, 1, 1); diff --git a/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp index a5482657aa0..2bb5d0a75d2 100644 --- a/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp @@ -2310,8 +2310,14 @@ void tst_QDateTime::fromStringDateFormat_data() // Test Qt::RFC2822Date format (RFC 2822). QTest::newRow("RFC 2822 +0100") << QString::fromLatin1("13 Feb 1987 13:24:51 +0100") << Qt::RFC2822Date << QDateTime(QDate(1987, 2, 13), QTime(12, 24, 51), Qt::UTC); + QTest::newRow("RFC 2822 after space +0100") + << QString::fromLatin1(" 13 Feb 1987 13:24:51 +0100") + << Qt::RFC2822Date << QDateTime(QDate(1987, 2, 13), QTime(12, 24, 51), Qt::UTC); QTest::newRow("RFC 2822 with day +0100") << QString::fromLatin1("Fri, 13 Feb 1987 13:24:51 +0100") << Qt::RFC2822Date << QDateTime(QDate(1987, 2, 13), QTime(12, 24, 51), Qt::UTC); + QTest::newRow("RFC 2822 with day after space +0100") + << QString::fromLatin1(" Fri, 13 Feb 1987 13:24:51 +0100") + << Qt::RFC2822Date << QDateTime(QDate(1987, 2, 13), QTime(12, 24, 51), Qt::UTC); QTest::newRow("RFC 2822 -0100") << QString::fromLatin1("13 Feb 1987 13:24:51 -0100") << Qt::RFC2822Date << QDateTime(QDate(1987, 2, 13), QTime(14, 24, 51), Qt::UTC); QTest::newRow("RFC 2822 with day -0100") << QString::fromLatin1("Fri, 13 Feb 1987 13:24:51 -0100") @@ -2324,6 +2330,11 @@ void tst_QDateTime::fromStringDateFormat_data() << Qt::RFC2822Date << QDateTime(QDate(1970, 1, 1), QTime(0, 12, 34), Qt::UTC); QTest::newRow("RFC 2822 with day +0000") << QString::fromLatin1("Thu, 01 Jan 1970 00:12:34 +0000") << Qt::RFC2822Date << QDateTime(QDate(1970, 1, 1), QTime(0, 12, 34), Qt::UTC); + // Should be invalid, but current implementation would just ignore the + // offset as trailing junk if we insist on the space: + QTest::newRow("RFC 2822 missing space before +0100") + << QString::fromLatin1("Thu, 01 Jan 1970 00:12:34+0100") << Qt::RFC2822Date + << QDateTime(QDate(1970, 1, 1), QTime(0, 12, 34), Qt::OffsetFromUTC, 3600); // No timezone assume UTC QTest::newRow("RFC 2822 no timezone") << QString::fromLatin1("01 Jan 1970 00:12:34") << Qt::RFC2822Date << QDateTime(QDate(1970, 1, 1), QTime(0, 12, 34), Qt::UTC); @@ -2354,6 +2365,9 @@ void tst_QDateTime::fromStringDateFormat_data() // Test Qt::RFC2822Date format (RFC 850 and 1036, permissive). QTest::newRow("RFC 850 and 1036 +0100") << QString::fromLatin1("Fri Feb 13 13:24:51 1987 +0100") << Qt::RFC2822Date << QDateTime(QDate(1987, 2, 13), QTime(12, 24, 51), Qt::UTC); + QTest::newRow("RFC 1036 after space +0100") + << QString::fromLatin1(" Fri Feb 13 13:24:51 1987 +0100") + << Qt::RFC2822Date << QDateTime(QDate(1987, 2, 13), QTime(12, 24, 51), Qt::UTC); QTest::newRow("RFC 850 and 1036 -0100") << QString::fromLatin1("Fri Feb 13 13:24:51 1987 -0100") << Qt::RFC2822Date << QDateTime(QDate(1987, 2, 13), QTime(14, 24, 51), Qt::UTC); QTest::newRow("RFC 850 and 1036 +0000") << QString::fromLatin1("Thu Jan 01 00:12:34 1970 +0000") diff --git a/tests/auto/corelib/time/qtime/tst_qtime.cpp b/tests/auto/corelib/time/qtime/tst_qtime.cpp index b2bb5dbb24c..ed8700d93fc 100644 --- a/tests/auto/corelib/time/qtime/tst_qtime.cpp +++ b/tests/auto/corelib/time/qtime/tst_qtime.cpp @@ -619,8 +619,14 @@ void tst_QTime::fromStringDateFormat_data() // Test Qt::RFC2822Date format (RFC 2822). QTest::newRow("RFC 2822") << QString::fromLatin1("13 Feb 1987 13:24:51 +0100") << Qt::RFC2822Date << QTime(13, 24, 51); + QTest::newRow("RFC 2822 after space") + << QString::fromLatin1(" 13 Feb 1987 13:24:51 +0100") + << Qt::RFC2822Date << QTime(13, 24, 51); QTest::newRow("RFC 2822 with day") << QString::fromLatin1("Thu, 01 Jan 1970 00:12:34 +0000") << Qt::RFC2822Date << QTime(0, 12, 34); + QTest::newRow("RFC 2822 with day after space") + << QString::fromLatin1(" Thu, 01 Jan 1970 00:12:34 +0000") + << Qt::RFC2822Date << QTime(0, 12, 34); // No timezone QTest::newRow("RFC 2822 no timezone") << QString::fromLatin1("01 Jan 1970 00:12:34") << Qt::RFC2822Date << QTime(0, 12, 34); @@ -651,6 +657,9 @@ void tst_QTime::fromStringDateFormat_data() // Test Qt::RFC2822Date format (RFC 850 and 1036, permissive). QTest::newRow("RFC 850 and 1036") << QString::fromLatin1("Fri Feb 13 13:24:51 1987 +0100") << Qt::RFC2822Date << QTime(13, 24, 51); + QTest::newRow("RFC 850 and 1036 after space") + << QString::fromLatin1(" Fri Feb 13 13:24:51 1987 +0100") + << Qt::RFC2822Date << QTime(13, 24, 51); // No timezone QTest::newRow("RFC 850 and 1036 no timezone") << QString::fromLatin1("Thu Jan 01 00:12:34 1970") << Qt::RFC2822Date << QTime(0, 12, 34); From 52affd322cad474efc9235e09f9f5e85f558b7a4 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Mon, 18 Nov 2019 12:06:19 +0100 Subject: [PATCH 19/45] Be consistent in the RFC2822Date invalid character tests The ones we reject used a zero offset while the one that does parse (though it shouldn't - revised comment) has a one hour offset. Made them all use that offset and added a partner test that has no invalid characters, so ensure the success of the invalid character tests isn't due to falsely rejecting the valid date/time text to which the invalid characters are added. Task-number: QTBUG-80038 Change-Id: I6e3dd79b981af6803e60877229c56599cfd719cb Reviewed-by: Thiago Macieira --- tests/auto/corelib/time/qdate/tst_qdate.cpp | 47 ++++++++++++------ .../corelib/time/qdatetime/tst_qdatetime.cpp | 49 +++++++++++++------ tests/auto/corelib/time/qtime/tst_qtime.cpp | 41 +++++++++++----- 3 files changed, 96 insertions(+), 41 deletions(-) diff --git a/tests/auto/corelib/time/qdate/tst_qdate.cpp b/tests/auto/corelib/time/qdate/tst_qdate.cpp index 63fdbbbe922..dd2cb3eea87 100644 --- a/tests/auto/corelib/time/qdate/tst_qdate.cpp +++ b/tests/auto/corelib/time/qdate/tst_qdate.cpp @@ -1159,17 +1159,23 @@ void tst_QDate::fromStringDateFormat_data() << Qt::RFC2822Date << QDate(); QTest::newRow("RFC 2822 invalid year") << QString::fromLatin1("13 Fev 0000 13:24:51 +0100") << Qt::RFC2822Date << QDate(); - // Test invalid characters (should ignore invalid characters at end of string). - QTest::newRow("RFC 2822 invalid character at end") << QString::fromLatin1("01 Jan 2012 08:00:00 +0100!") + // Test invalid characters (currently ignoring trailing junk, but see QTBUG-80038). + QTest::newRow("RFC 2822 invalid character at end") + << QString::fromLatin1("01 Jan 2012 08:00:00 +0100!") + << Qt::RFC2822Date << QDate(2012, 1, 1); + QTest::newRow("RFC 2822 invalid character at front") + << QString::fromLatin1("!01 Jan 2012 08:00:00 +0100") << Qt::RFC2822Date << QDate(); + QTest::newRow("RFC 2822 invalid character both ends") + << QString::fromLatin1("!01 Jan 2012 08:00:00 +0100!") << Qt::RFC2822Date << QDate(); + QTest::newRow("RFC 2822 invalid character at front, 2 at back") + << QString::fromLatin1("!01 Jan 2012 08:00:00 +0100..") << Qt::RFC2822Date << QDate(); + QTest::newRow("RFC 2822 invalid character 2 at front") + << QString::fromLatin1("!!01 Jan 2012 08:00:00 +0100") << Qt::RFC2822Date << QDate(); + // The common date text used by the "invalid character" tests, just to be + // sure *it's* not what's invalid: + QTest::newRow("RFC 2822 (not invalid)") + << QString::fromLatin1("01 Jan 2012 08:00:00 +0100") << Qt::RFC2822Date << QDate(2012, 1, 1); - QTest::newRow("RFC 2822 invalid character at front") << QString::fromLatin1("!01 Jan 2012 08:00:00 +0000") - << Qt::RFC2822Date << QDate(); - QTest::newRow("RFC 2822 invalid character both ends") << QString::fromLatin1("!01 Jan 2012 08:00:00 +0000!") - << Qt::RFC2822Date << QDate(); - QTest::newRow("RFC 2822 invalid character at front, 2 at back") << QString::fromLatin1("!01 Jan 2012 08:00:00 +0000..") - << Qt::RFC2822Date << QDate(); - QTest::newRow("RFC 2822 invalid character 2 at front") << QString::fromLatin1("!!01 Jan 2012 08:00:00 +0000") - << Qt::RFC2822Date << QDate(); // Test Qt::RFC2822Date format (RFC 850 and 1036, permissive). QTest::newRow("RFC 850 and 1036") << QString::fromLatin1("Fri Feb 13 13:24:51 1987 +0100") @@ -1183,17 +1189,26 @@ void tst_QDate::fromStringDateFormat_data() // No time specified QTest::newRow("RFC 850 and 1036 date only") << QString::fromLatin1("Fri Nov 01 2002") << Qt::RFC2822Date << QDate(2002, 11, 1); - // Test invalid characters (should ignore invalid characters at end of string). - QTest::newRow("RFC 850 and 1036 invalid character at end") << QString::fromLatin1("Sun Jan 01 08:00:00 2012 +0100!") + // Test invalid characters (currently ignoring trailing junk, but see QTBUG-80038). + QTest::newRow("RFC 850 and 1036 invalid character at end") + << QString::fromLatin1("Sun Jan 01 08:00:00 2012 +0100!") << Qt::RFC2822Date << QDate(2012, 1, 1); - QTest::newRow("RFC 850 and 1036 invalid character at front") << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0000") + QTest::newRow("RFC 850 and 1036 invalid character at front") + << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0100") << Qt::RFC2822Date << QDate(); - QTest::newRow("RFC 850 and 1036 invalid character both ends") << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0000!") + QTest::newRow("RFC 850 and 1036 invalid character both ends") + << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0100!") << Qt::RFC2822Date << QDate(); - QTest::newRow("RFC 850 and 1036 invalid character at front, 2 at back") << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0000..") + QTest::newRow("RFC 850 and 1036 invalid character at front, 2 at back") + << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0100..") << Qt::RFC2822Date << QDate(); - QTest::newRow("RFC 850 and 1036 invalid character 2 at front") << QString::fromLatin1("!!Sun Jan 01 08:00:00 2012 +0000") + QTest::newRow("RFC 850 and 1036 invalid character 2 at front") + << QString::fromLatin1("!!Sun Jan 01 08:00:00 2012 +0100") << Qt::RFC2822Date << QDate(); + // Again, check the text in the "invalid character" tests isn't the source of invalidity: + QTest::newRow("RFC 850 and 1036 (not invalid)") + << QString::fromLatin1("Sun Jan 01 08:00:00 2012 +0100") + << Qt::RFC2822Date << QDate(2012, 1, 1); QTest::newRow("RFC empty") << QString::fromLatin1("") << Qt::RFC2822Date << QDate(); } diff --git a/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp index 2bb5d0a75d2..7f13fd0aa59 100644 --- a/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp @@ -1003,8 +1003,9 @@ void tst_QDateTime::toString_rfcDate() // Set to non-English locale to confirm still uses English QLocale oldLocale; QLocale::setDefault(QLocale("de_DE")); - QCOMPARE(dt.toString(Qt::RFC2822Date), formatted); + QString actual(dt.toString(Qt::RFC2822Date)); QLocale::setDefault(oldLocale); + QCOMPARE(actual, formatted); } void tst_QDateTime::toString_enumformat() @@ -2350,17 +2351,27 @@ void tst_QDateTime::fromStringDateFormat_data() << Qt::RFC2822Date << invalidDateTime(); QTest::newRow("RFC 2822 invalid year") << QString::fromLatin1("13 Fev 0000 13:24:51 +0100") << Qt::RFC2822Date << invalidDateTime(); - // Test invalid characters (should ignore invalid characters at end of string). - QTest::newRow("RFC 2822 invalid character at end") << QString::fromLatin1("01 Jan 2012 08:00:00 +0100!") + // Test invalid characters (currently ignoring trailing junk, but see QTBUG-80038). + QTest::newRow("RFC 2822 invalid character at end") + << QString::fromLatin1("01 Jan 2012 08:00:00 +0100!") << Qt::RFC2822Date << QDateTime(QDate(2012, 1, 1), QTime(7, 0, 0, 0), Qt::UTC); - QTest::newRow("RFC 2822 invalid character at front") << QString::fromLatin1("!01 Jan 2012 08:00:00 +0000") + QTest::newRow("RFC 2822 invalid character at front") + << QString::fromLatin1("!01 Jan 2012 08:00:00 +0100") << Qt::RFC2822Date << invalidDateTime(); - QTest::newRow("RFC 2822 invalid character both ends") << QString::fromLatin1("!01 Jan 2012 08:00:00 +0000!") + QTest::newRow("RFC 2822 invalid character both ends") + << QString::fromLatin1("!01 Jan 2012 08:00:00 +0100!") << Qt::RFC2822Date << invalidDateTime(); - QTest::newRow("RFC 2822 invalid character at front, 2 at back") << QString::fromLatin1("!01 Jan 2012 08:00:00 +0000..") + QTest::newRow("RFC 2822 invalid character at front, 2 at back") + << QString::fromLatin1("!01 Jan 2012 08:00:00 +0100..") << Qt::RFC2822Date << invalidDateTime(); - QTest::newRow("RFC 2822 invalid character 2 at front") << QString::fromLatin1("!!01 Jan 2012 08:00:00 +0000") + QTest::newRow("RFC 2822 invalid character 2 at front") + << QString::fromLatin1("!!01 Jan 2012 08:00:00 +0100") << Qt::RFC2822Date << invalidDateTime(); + // The common date text used by the "invalid character" tests, just to be + // sure *it's* not what's invalid: + QTest::newRow("RFC 2822 (not invalid)") + << QString::fromLatin1("01 Jan 2012 08:00:00 +0100") + << Qt::RFC2822Date << QDateTime(QDate(2012, 1, 1), QTime(7, 0, 0, 0), Qt::UTC); // Test Qt::RFC2822Date format (RFC 850 and 1036, permissive). QTest::newRow("RFC 850 and 1036 +0100") << QString::fromLatin1("Fri Feb 13 13:24:51 1987 +0100") @@ -2378,19 +2389,29 @@ void tst_QDateTime::fromStringDateFormat_data() QTest::newRow("RFC 850 and 1036 no timezone") << QString::fromLatin1("Thu Jan 01 00:12:34 1970") << Qt::RFC2822Date << QDateTime(QDate(1970, 1, 1), QTime(0, 12, 34), Qt::UTC); // No time specified - QTest::newRow("RFC 850 and 1036 date only") << QString::fromLatin1("Fri Nov 01 2002") + QTest::newRow("RFC 850 and 1036 date only") + << QString::fromLatin1("Fri Nov 01 2002") << Qt::RFC2822Date << invalidDateTime(); - // Test invalid characters (should ignore invalid characters at end of string). - QTest::newRow("RFC 850 and 1036 invalid character at end") << QString::fromLatin1("Sun Jan 01 08:00:00 2012 +0100!") + // Test invalid characters (currently ignoring trailing junk, but see QTBUG-80038). + QTest::newRow("RFC 850 and 1036 invalid character at end") + << QString::fromLatin1("Sun Jan 01 08:00:00 2012 +0100!") << Qt::RFC2822Date << QDateTime(QDate(2012, 1, 1), QTime(7, 0, 0, 0), Qt::UTC); - QTest::newRow("RFC 850 and 1036 invalid character at front") << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0000") + QTest::newRow("RFC 850 and 1036 invalid character at front") + << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0100") << Qt::RFC2822Date << invalidDateTime(); - QTest::newRow("RFC 850 and 1036 invalid character both ends") << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0000!") + QTest::newRow("RFC 850 and 1036 invalid character both ends") + << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0100!") << Qt::RFC2822Date << invalidDateTime(); - QTest::newRow("RFC 850 and 1036 invalid character at front, 2 at back") << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0000..") + QTest::newRow("RFC 850 and 1036 invalid character at front, 2 at back") + << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0100..") << Qt::RFC2822Date << invalidDateTime(); - QTest::newRow("RFC 850 and 1036 invalid character 2 at front") << QString::fromLatin1("!!Sun Jan 01 08:00:00 2012 +0000") + QTest::newRow("RFC 850 and 1036 invalid character 2 at front") + << QString::fromLatin1("!!Sun Jan 01 08:00:00 2012 +0100") << Qt::RFC2822Date << invalidDateTime(); + // Again, check the text in the "invalid character" tests isn't the source of invalidity: + QTest::newRow("RFC 850 and 1036 (not invalid)") + << QString::fromLatin1("Sun Jan 01 08:00:00 2012 +0100") + << Qt::RFC2822Date << QDateTime(QDate(2012, 1, 1), QTime(7, 0, 0, 0), Qt::UTC); QTest::newRow("RFC empty") << QString::fromLatin1("") << Qt::RFC2822Date << invalidDateTime(); } diff --git a/tests/auto/corelib/time/qtime/tst_qtime.cpp b/tests/auto/corelib/time/qtime/tst_qtime.cpp index ed8700d93fc..d8de6e585d1 100644 --- a/tests/auto/corelib/time/qtime/tst_qtime.cpp +++ b/tests/auto/corelib/time/qtime/tst_qtime.cpp @@ -642,17 +642,27 @@ void tst_QTime::fromStringDateFormat_data() << Qt::RFC2822Date << QTime(13, 24, 51); QTest::newRow("RFC 2822 invalid year") << QString::fromLatin1("13 Fev 0000 13:24:51 +0100") << Qt::RFC2822Date << QTime(13, 24, 51); - // Test invalid characters (should ignore invalid characters at end of string). - QTest::newRow("RFC 2822 invalid character at end") << QString::fromLatin1("01 Jan 2012 08:00:00 +0100!") + // Test invalid characters (currently ignoring trailing junk, but see QTBUG-80038). + QTest::newRow("RFC 2822 invalid character at end") + << QString::fromLatin1("01 Jan 2012 08:00:00 +0100!") << Qt::RFC2822Date << QTime(8, 0, 0); - QTest::newRow("RFC 2822 invalid character at front") << QString::fromLatin1("!01 Jan 2012 08:00:00 +0000") + QTest::newRow("RFC 2822 invalid character at front") + << QString::fromLatin1("!01 Jan 2012 08:00:00 +0100") << Qt::RFC2822Date << invalidTime(); - QTest::newRow("RFC 2822 invalid character both ends") << QString::fromLatin1("!01 Jan 2012 08:00:00 +0000!") + QTest::newRow("RFC 2822 invalid character both ends") + << QString::fromLatin1("!01 Jan 2012 08:00:00 +0100!") << Qt::RFC2822Date << invalidTime(); - QTest::newRow("RFC 2822 invalid character at front, 2 at back") << QString::fromLatin1("!01 Jan 2012 08:00:00 +0000..") + QTest::newRow("RFC 2822 invalid character at front, 2 at back") + << QString::fromLatin1("!01 Jan 2012 08:00:00 +0100..") << Qt::RFC2822Date << invalidTime(); - QTest::newRow("RFC 2822 invalid character 2 at front") << QString::fromLatin1("!!01 Jan 2012 08:00:00 +0000") + QTest::newRow("RFC 2822 invalid character 2 at front") + << QString::fromLatin1("!!01 Jan 2012 08:00:00 +0100") << Qt::RFC2822Date << invalidTime(); + // The common date text used by the "invalid character" tests, just to be + // sure *it's* not what's invalid: + QTest::newRow("RFC 2822 invalid character at end") + << QString::fromLatin1("01 Jan 2012 08:00:00 +0100") + << Qt::RFC2822Date << QTime(8, 0, 0); // Test Qt::RFC2822Date format (RFC 850 and 1036, permissive). QTest::newRow("RFC 850 and 1036") << QString::fromLatin1("Fri Feb 13 13:24:51 1987 +0100") @@ -666,15 +676,24 @@ void tst_QTime::fromStringDateFormat_data() // No time specified QTest::newRow("RFC 850 and 1036 date only") << QString::fromLatin1("Fri Nov 01 2002") << Qt::RFC2822Date << invalidTime(); - // Test invalid characters (should ignore invalid characters at end of string). - QTest::newRow("RFC 850 and 1036 invalid character at end") << QString::fromLatin1("Sun Jan 01 08:00:00 2012 +0100!") + // Test invalid characters (currently ignoring trailing junk, but see QTBUG-80038). + QTest::newRow("RFC 850 and 1036 invalid character at end") + << QString::fromLatin1("Sun Jan 01 08:00:00 2012 +0100!") << Qt::RFC2822Date << QTime(8, 0, 0); - QTest::newRow("RFC 850 and 1036 invalid character at front") << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0000") + QTest::newRow("RFC 850 and 1036 invalid character at front") + << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0100") << Qt::RFC2822Date << invalidTime(); - QTest::newRow("RFC 850 and 1036 invalid character both ends") << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0000!") + QTest::newRow("RFC 850 and 1036 invalid character both ends") + << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0100!") << Qt::RFC2822Date << invalidTime(); - QTest::newRow("RFC 850 and 1036 invalid character at front, 2 at back") << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0000..") + QTest::newRow("RFC 850 and 1036 invalid character at front, 2 at back") + << QString::fromLatin1("!Sun Jan 01 08:00:00 2012 +0100..") << Qt::RFC2822Date << invalidTime(); + // The common date text used by the "invalid character" tests, just to be + // sure *it's* not what's invalid: + QTest::newRow("RFC 850 and 1036 invalid character at end") + << QString::fromLatin1("Sun Jan 01 08:00:00 2012 +0100") + << Qt::RFC2822Date << QTime(8, 0, 0); QTest::newRow("RFC empty") << QString::fromLatin1("") << Qt::RFC2822Date << invalidTime(); } From c20c7efea96046bebcb8ff7823d3a7e227f92e73 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 26 Nov 2019 12:22:31 +0100 Subject: [PATCH 20/45] Sanitize QAndroidTimeZonePrivate::init() It was setting the system zone ID if it somehow managed to find a match for an empty zone name; that makes no sense. A case-insensitive comparison seems reasonable for the "this isn't just a default zone object, used because the name I asked for isn't recognized" check. It set m_id after it had checked everything, where it could just as well have used m_id as the variable in which to record whether its check has succeeded already. It was using the name it was asked for, rather than the one this ended up being mapped to, which is probably a better name to use for it. (This should only differ in case.) Split a long line. Change-Id: I41a3b01ba99522ee68f3d7941c532019b9ebf946 Reviewed-by: Edward Welbourne --- src/corelib/time/qtimezoneprivate_android.cpp | 36 ++++++++++--------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/corelib/time/qtimezoneprivate_android.cpp b/src/corelib/time/qtimezoneprivate_android.cpp index be4f374fdd8..8de41ed3cea 100644 --- a/src/corelib/time/qtimezoneprivate_android.cpp +++ b/src/corelib/time/qtimezoneprivate_android.cpp @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2014 Drew Parsons ** Contact: https://www.qt.io/licensing/ ** @@ -76,32 +77,33 @@ QAndroidTimeZonePrivate::~QAndroidTimeZonePrivate() { } - void QAndroidTimeZonePrivate::init(const QByteArray &ianaId) { - QJNIObjectPrivate jo_ianaId = QJNIObjectPrivate::fromString( QString::fromUtf8(ianaId) ); - androidTimeZone = QJNIObjectPrivate::callStaticObjectMethod( "java.util.TimeZone", "getTimeZone", "(Ljava/lang/String;)Ljava/util/TimeZone;", static_cast(jo_ianaId.object()) ); + const QString iana = QString::fromUtf8(ianaId); + androidTimeZone = QJNIObjectPrivate::callStaticObjectMethod( + "java.util.TimeZone", "getTimeZone", "(Ljava/lang/String;)Ljava/util/TimeZone;", + static_cast(QJNIObjectPrivate::fromString(iana).object())); + + // The ID or display name of the zone we've got, if it looks like what we asked for: + const auto match = [iana](const QJNIObjectPrivate &jname) -> QByteArray { + const QString name = jname.toString(); + if (iana.compare(name, Qt::CaseInsensitive)) + return name.toUtf8(); + + return QByteArray(); + }; // Painfully, JNI gives us back a default zone object if it doesn't // recognize the name; so check for whether ianaId is a recognized name of // the zone object we got and ignore the zone if not. // Try checking ianaId against getID(), getDisplayName(): - QJNIObjectPrivate jname = androidTimeZone.callObjectMethod("getID", "()Ljava/lang/String;"); - bool found = (jname.toString().toUtf8() == ianaId); - for (int style = 1; !found && style-- > 0;) { - for (int dst = 1; !found && dst-- > 0;) { - jname = androidTimeZone.callObjectMethod("getDisplayName", "(ZI;)Ljava/lang/String;", - bool(dst), style); - found = (jname.toString().toUtf8() == ianaId); + m_id = match(androidTimeZone.callObjectMethod("getID", "()Ljava/lang/String;")); + for (int style = 1; m_id.isEmpty() && style-- > 0;) { + for (int dst = 1; m_id.isEmpty() && dst-- > 0;) { + m_id = match(androidTimeZone.callObjectMethod( + "getDisplayName", "(ZI;)Ljava/lang/String;", bool(dst), style)); } } - - if (!found) - m_id.clear(); - else if (ianaId.isEmpty()) - m_id = systemTimeZoneId(); - else - m_id = ianaId; } QAndroidTimeZonePrivate *QAndroidTimeZonePrivate::clone() const From 78cde1bfd94521bbe4972f31a79c959d0990ea77 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 26 Nov 2019 13:35:10 +0100 Subject: [PATCH 21/45] Fix mis-guided init() in default QAndroidTimeZonePrivate constructor It set the time-zone member sensibly to the default zone, but then called init("UTC"), which over-wrote that default with UTC. This had no visible effect (as the default-constructed object is only used to access methods that (though virtual) are effectively static), but was needlessly complicated. Tidied up systemTimeZoneId() at the same time. Change-Id: I897aff16855c28487a1029bef50c75ebc1ff5b55 Reviewed-by: Thiago Macieira --- src/corelib/time/qtimezoneprivate_android.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/corelib/time/qtimezoneprivate_android.cpp b/src/corelib/time/qtimezoneprivate_android.cpp index 8de41ed3cea..5cb8155dcc7 100644 --- a/src/corelib/time/qtimezoneprivate_android.cpp +++ b/src/corelib/time/qtimezoneprivate_android.cpp @@ -54,9 +54,10 @@ QT_BEGIN_NAMESPACE QAndroidTimeZonePrivate::QAndroidTimeZonePrivate() : QTimeZonePrivate() { - // start with system time zone - androidTimeZone = QJNIObjectPrivate::callStaticObjectMethod("java.util.TimeZone", "getDefault", "()Ljava/util/TimeZone;"); - init("UTC"); + // Keep in sync with systemTimeZoneId(): + androidTimeZone = QJNIObjectPrivate::callStaticObjectMethod( + "java.util.TimeZone", "getDefault", "()Ljava/util/TimeZone;"); + m_id = androidTimeZone.callObjectMethod("getID", "()Ljava/lang/String;").toString().toUtf8(); } // Create a named time zone @@ -227,11 +228,10 @@ QTimeZonePrivate::Data QAndroidTimeZonePrivate::previousTransition(qint64 before QByteArray QAndroidTimeZonePrivate::systemTimeZoneId() const { - QJNIObjectPrivate androidSystemTimeZone = QJNIObjectPrivate::callStaticObjectMethod("java.util.TimeZone", "getDefault", "()Ljava/util/TimeZone;"); - QJNIObjectPrivate systemTZIdAndroid = androidSystemTimeZone.callObjectMethod("getID"); - QByteArray systemTZid = systemTZIdAndroid.toString().toUtf8(); - - return systemTZid; + // Keep in sync with default constructor: + QJNIObjectPrivate androidSystemTimeZone = QJNIObjectPrivate::callStaticObjectMethod( + "java.util.TimeZone", "getDefault", "()Ljava/util/TimeZone;"); + return androidSystemTimeZone.callObjectMethod("getID").toString().toUtf8(); } QList QAndroidTimeZonePrivate::availableTimeZoneIds() const From 4422a9bd88602c8dfde8648ad39692d968295cfc Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Tue, 11 Jun 2019 08:54:34 +0200 Subject: [PATCH 22/45] QWidget: don't set WA_PendingMoveEvent when geometry does not change When the geometry of a hidden widget was set with setGeometry(), WA_PendingMoveEvent and WA_PendingResizeEvent were set unconditionally even if the crect already had the correct value. This lead to unneeded Move/Resize events within sendPendingMoveAndResizeEvents(). Fixes: QTBUG-75475 Fixes: QTBUG-79906 Change-Id: Ibbe03882f039948b6b7c04887420741ed2e9c0f7 Reviewed-by: Friedemann Kleint Reviewed-by: Shawn Rutledge Reviewed-by: Richard Moe Gustavsen --- src/widgets/kernel/qwidget.cpp | 11 ++++-- .../widgets/kernel/qwidget/tst_qwidget.cpp | 34 +++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index e9968e41b44..5a0ea58cf83 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -7005,8 +7005,10 @@ void QWidget::resize(const QSize &s) d->setGeometry_sys(geometry().x(), geometry().y(), s.width(), s.height(), false); d->setDirtyOpaqueRegion(); } else { + const auto oldRect = data->crect; data->crect.setSize(s.boundedTo(maximumSize()).expandedTo(minimumSize())); - setAttribute(Qt::WA_PendingResizeEvent); + if (oldRect != data->crect) + setAttribute(Qt::WA_PendingResizeEvent); } } @@ -7021,10 +7023,13 @@ void QWidget::setGeometry(const QRect &r) d->setGeometry_sys(r.x(), r.y(), r.width(), r.height(), true); d->setDirtyOpaqueRegion(); } else { + const auto oldRect = data->crect; data->crect.setTopLeft(r.topLeft()); data->crect.setSize(r.size().boundedTo(maximumSize()).expandedTo(minimumSize())); - setAttribute(Qt::WA_PendingMoveEvent); - setAttribute(Qt::WA_PendingResizeEvent); + if (oldRect != data->crect) { + setAttribute(Qt::WA_PendingMoveEvent); + setAttribute(Qt::WA_PendingResizeEvent); + } } if (d->extra && d->extra->hasWindowContainer) diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 882323ba4fb..67fdd136526 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -198,6 +199,7 @@ private slots: void hideWhenFocusWidgetIsChild(); void normalGeometry(); void setGeometry(); + void setGeometryHidden(); void windowOpacity(); void raise(); void lower(); @@ -2922,6 +2924,38 @@ void tst_QWidget::setGeometry() QCOMPARE(tlw.geometry(), tr); } +void tst_QWidget::setGeometryHidden() +{ + if (QGuiApplication::styleHints()->showIsMaximized()) + QSKIP("Platform does not support QWidget::setGeometry() - skipping"); + + QWidget tlw; + tlw.setWindowTitle(QLatin1String(QTest::currentTestFunction())); + QWidget child(&tlw); + + const QRect tr(m_availableTopLeft + QPoint(100, 100), 2 * m_testWidgetSize); + const QRect cr(QPoint(50, 50), m_testWidgetSize); + tlw.setGeometry(tr); + child.setGeometry(cr); + tlw.showNormal(); + + tlw.hide(); + QTRY_VERIFY(tlw.isHidden()); + tlw.setGeometry(cr); + QVERIFY(tlw.testAttribute(Qt::WA_PendingMoveEvent)); + QVERIFY(tlw.testAttribute(Qt::WA_PendingResizeEvent)); + QImage img(tlw.size(), QImage::Format_ARGB32); // just needed to call QWidget::render() + tlw.render(&img); + QVERIFY(!tlw.testAttribute(Qt::WA_PendingMoveEvent)); + QVERIFY(!tlw.testAttribute(Qt::WA_PendingResizeEvent)); + tlw.setGeometry(cr); + QVERIFY(!tlw.testAttribute(Qt::WA_PendingMoveEvent)); + QVERIFY(!tlw.testAttribute(Qt::WA_PendingResizeEvent)); + tlw.resize(cr.size()); + QVERIFY(!tlw.testAttribute(Qt::WA_PendingMoveEvent)); + QVERIFY(!tlw.testAttribute(Qt::WA_PendingResizeEvent)); +} + void tst_QWidget::windowOpacity() { QWidget widget; From 14ae88144521b9e3c22202c7967a19607fd91ff9 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Tue, 26 Nov 2019 13:35:59 +0100 Subject: [PATCH 23/45] QSslSocket (OpenSSL) fix a resource leak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduced by fe6e54fb1f5cda652b9489f740763f8d735621dd. The probability -> 0, meaning malloc must fail to trigger it, but it is still a leak. We now use std::unique_ptr which improves the code in general a bit and fixes a leak. Change-Id: I6c0fa36953196d3235fb60354dc9ad2396d8dfcb Reviewed-by: Mårten Nordheim --- src/network/ssl/qsslsocket_openssl.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index d4bad1b1a55..51510f1c60b 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -93,6 +93,7 @@ #endif #include +#include #include @@ -1763,6 +1764,7 @@ QList QSslSocketBackendPrivate::verify(const QList & errors << QSslError(QSslError::UnspecifiedError); return errors; } + const std::unique_ptr storeGuard(certStore, q_X509_STORE_free); if (s_loadRootCertsOnDemand) { setDefaultCaCertificates(defaultCaCertificates() + systemCaCertificates()); @@ -1811,7 +1813,6 @@ QList QSslSocketBackendPrivate::verify(const QList & intermediates = (STACK_OF(X509) *) q_OPENSSL_sk_new_null(); if (!intermediates) { - q_X509_STORE_free(certStore); errors << QSslError(QSslError::UnspecifiedError); return errors; } @@ -1829,14 +1830,12 @@ QList QSslSocketBackendPrivate::verify(const QList & X509_STORE_CTX *storeContext = q_X509_STORE_CTX_new(); if (!storeContext) { - q_X509_STORE_free(certStore); errors << QSslError(QSslError::UnspecifiedError); return errors; } + std::unique_ptr ctxGuard(storeContext, q_X509_STORE_CTX_free); if (!q_X509_STORE_CTX_init(storeContext, certStore, reinterpret_cast(certificateChain[0].handle()), intermediates)) { - q_X509_STORE_CTX_free(storeContext); - q_X509_STORE_free(certStore); errors << QSslError(QSslError::UnspecifiedError); return errors; } @@ -1845,8 +1844,7 @@ QList QSslSocketBackendPrivate::verify(const QList & // We ignore the result of this function since we process errors via the // callback. (void) q_X509_verify_cert(storeContext); - - q_X509_STORE_CTX_free(storeContext); + ctxGuard.reset(); q_OPENSSL_sk_free((OPENSSL_STACK *)intermediates); // Now process the errors @@ -1868,8 +1866,6 @@ QList QSslSocketBackendPrivate::verify(const QList & for (const auto &error : qAsConst(lastErrors)) errors << _q_OpenSSL_to_QSslError(error.code, certificateChain.value(error.depth)); - q_X509_STORE_free(certStore); - return errors; } From d60b71d635a038e3fe8b061b0ac3f2aad70227a5 Mon Sep 17 00:00:00 2001 From: Aaron Linville Date: Sun, 24 Nov 2019 09:36:11 -0500 Subject: [PATCH 24/45] Fix CONFIG += cmdline testcase creating app bundle paths in Makefiles Fix an issue where qmake on macOS will generate a Makefile with a path to a macOS bundle instead of a bundle-less executable in the Makefile's check rule if cmdline is specified before testcase in the CONFIG options. Fixes: QTBUG-80280 Change-Id: Icc9ee1355b0641981ce79526b36f29957e1afb00 Reviewed-by: Joerg Bornemann --- mkspecs/features/testcase.prf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mkspecs/features/testcase.prf b/mkspecs/features/testcase.prf index d4f08835f1b..7e9903d6637 100644 --- a/mkspecs/features/testcase.prf +++ b/mkspecs/features/testcase.prf @@ -9,6 +9,9 @@ testcase_exceptions: CONFIG += exceptions # Set in qt_build_config.prf testcase_no_bundle: CONFIG -= app_bundle +# cmdline may have been specified and not processed yet +cmdline: CONFIG -= app_bundle + # Allow testcases to mark themselves as not supporting high-DPI testcase_lowdpi { macos { From 2a4dd69499cb85695ede86ac7244fe6e1c274834 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 27 Nov 2019 12:49:37 +0100 Subject: [PATCH 25/45] CoreText: Fix getting system fonts on recent macOS/iOS versions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We introduced a work-around for iOS 11 which breaks on more recent OS versions because we try to request meta-fonts by name instead of using the special system font descriptors. This would cause warnings on the console and Times New Roman when requesting e.g. the system fixed width font. When testing on iOS 12 without the work-around, we are no longer able to reproduce the original issue, so the assumption is that this problem has been resolved. Since iOS 11 is not a supported target for Qt 5.14 we can remove the work-around entirely. [ChangeLog][macOS/iOS] Fixed a bug where QFontDatabase::systemFont() would return the wrong fonts on macOS 10.15 and iOS 13. Fixes: QTBUG-79900 Change-Id: Ie375c8c2ab877d6d66e3696662c4939f639a6e9e Reviewed-by: Tor Arne Vestbø --- .../fontdatabases/mac/qcoretextfontdatabase.mm | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index daa3dc94ea2..894919a1c8f 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -374,17 +374,6 @@ QFontEngine *QCoreTextFontDatabaseEngineFactory::fontEngine QCFType descriptor = QCFType::constructFromGet( static_cast(usrPtr)); - // CoreText will sometimes invalidate information in font descriptors that refer - // to system fonts in certain function calls or application states. While the descriptor - // looks the same from the outside, some internal plumbing is different, causing the results - // of creating CTFonts from those descriptors unreliable. The work-around for this - // is to copy the attributes of those descriptors each time we make a new CTFont - // from them instead of referring to the original, as that may trigger the CoreText bug. - if (m_systemFontDescriptors.contains(descriptor)) { - QCFType attributes = CTFontDescriptorCopyAttributes(descriptor); - descriptor = CTFontDescriptorCreateWithAttributes(attributes); - } - // Since we do not pass in the destination DPI to CoreText when making // the font, we need to pass in a point size which is scaled to include // the DPI. The default DPI for the screen is 72, thus the scale factor From cfd2f3c46eaefcaa8795a777d5e01fa85dd850a8 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 26 Nov 2019 13:44:30 +0100 Subject: [PATCH 26/45] Work around macOS's inconsistency in naming of India's time-zone MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit macOS fails to create a zone for the name its own systemTimeZone claims to have (see new comment). So make sure we do consistently recognize the name systemTimeZoneId() returns, using systemTimeZone from which we got its name. Add minimal testing of system time-zone. Fixes: QTBUG-80173 Change-Id: I42f21efbd7c439158fee954d555414bb180e7f8f Reviewed-by: Tor Arne Vestbø --- src/corelib/time/qtimezoneprivate_mac.mm | 11 +++++++++++ tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp | 9 +++++++++ 2 files changed, 20 insertions(+) diff --git a/src/corelib/time/qtimezoneprivate_mac.mm b/src/corelib/time/qtimezoneprivate_mac.mm index d3c4fbe5daf..4509e316f9e 100644 --- a/src/corelib/time/qtimezoneprivate_mac.mm +++ b/src/corelib/time/qtimezoneprivate_mac.mm @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2019 The Qt Company Ltd. ** Copyright (C) 2013 John Layt ** Contact: https://www.qt.io/licensing/ ** @@ -94,6 +95,16 @@ void QMacTimeZonePrivate::init(const QByteArray &ianaId) if (m_nstz) m_id = ianaId; } + if (!m_nstz) { + // macOS has been seen returning a systemTimeZone which reports its name + // as Asia/Kolkata, which doesn't appear in knownTimeZoneNames (which + // calls the zone Asia/Calcutta). So explicitly check for the name + // systemTimeZoneId() returns, and use systemTimeZone if we get it: + m_nstz = [NSTimeZone.systemTimeZone retain]; + Q_ASSERT(m_nstz); + if (QString::fromNSString(m_nstz.name).toUtf8() == ianaId) + m_id = ianaId; + } } QString QMacTimeZonePrivate::comment() const diff --git a/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp b/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp index f425691d9c9..4fdcbc78097 100644 --- a/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp +++ b/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp @@ -46,6 +46,7 @@ private slots: // Public class default system tests void createTest(); void nullTest(); + void systemZone(); void dataStreamTest(); void isTimeZoneIdAvailable(); void availableTimeZoneIds(); @@ -315,6 +316,14 @@ void tst_QTimeZone::nullTest() QCOMPARE(data.daylightTimeOffset, std::numeric_limits::min()); } +void tst_QTimeZone::systemZone() +{ + const QTimeZone zone = QTimeZone::systemTimeZone(); + QVERIFY(zone.isValid()); + QCOMPARE(zone.id(), QTimeZone::systemTimeZoneId()); + QCOMPARE(zone, QTimeZone(QTimeZone::systemTimeZoneId())); +} + void tst_QTimeZone::dataStreamTest() { // Test the OffsetFromUtc backend serialization. First with a custom timezone: From ee3e0ed751e8acdd5f1cefb430b0981c21f71f8e Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 25 Nov 2019 11:15:22 +0100 Subject: [PATCH 27/45] rhi: gl: Fix ms renderbuffer on WASM with WebGL2 Unlike renderbufferStorage, renderbufferStorageMultisample is not guaranteed to accept the unsized GL_DEPTH_STENCIL internalformat. For the former, WebGL 2 guarantees it for compatibility for WebGL 1, but the multisample version does not exist in WebGL 1, so from the specs it is not given at all that the unsized format would be accepted. So use the ES 3.0 sized format instead, like we would on a "real" ES 3.0 implementation. Fixes: QTBUG-80296 Change-Id: I822ae382097085c0a3279c16bb69a173dbf15093 Reviewed-by: Andy Nichols --- src/gui/rhi/qrhigles2.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp index abee843a74c..b3943547879 100644 --- a/src/gui/rhi/qrhigles2.cpp +++ b/src/gui/rhi/qrhigles2.cpp @@ -3147,8 +3147,7 @@ bool QGles2RenderBuffer::build() switch (m_type) { case QRhiRenderBuffer::DepthStencil: if (rhiD->caps.msaaRenderBuffer && samples > 1) { - const GLenum storage = rhiD->caps.needsDepthStencilCombinedAttach ? GL_DEPTH_STENCIL : GL_DEPTH24_STENCIL8; - rhiD->f->glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, storage, + rhiD->f->glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_DEPTH24_STENCIL8, size.width(), size.height()); stencilRenderbuffer = 0; } else if (rhiD->caps.packedDepthStencil || rhiD->caps.needsDepthStencilCombinedAttach) { From c94e756f01e30eb529e2c9d768c68d40fb9a0f19 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 27 Nov 2019 09:40:08 +0100 Subject: [PATCH 28/45] Polish the manual High DPI test - Use C++ constructs like range-based for, member initialization - Fix formatting in a few places - Silence clang warnings: - Add override - Make member variables private Task-number: QTBUG-80323 Change-Id: I5b0fda06acb6c8054aafa4dd934b763f8493a6b3 Reviewed-by: Shawn Rutledge --- tests/manual/highdpi/dragwidget.cpp | 15 +- tests/manual/highdpi/dragwidget.h | 5 +- tests/manual/highdpi/main.cpp | 239 ++++++++++++++++------------ 3 files changed, 145 insertions(+), 114 deletions(-) diff --git a/tests/manual/highdpi/dragwidget.cpp b/tests/manual/highdpi/dragwidget.cpp index 11bbc1d127c..8ad3d3ca471 100644 --- a/tests/manual/highdpi/dragwidget.cpp +++ b/tests/manual/highdpi/dragwidget.cpp @@ -42,7 +42,7 @@ public: }; DragWidget::DragWidget(QString text, QWidget *parent) - : QWidget(parent), otherWindow(nullptr) + : QWidget(parent) { int x = 5; int y = 5; @@ -52,9 +52,9 @@ DragWidget::DragWidget(QString text, QWidget *parent) text = "You can drag from this window and drop text here"; QStringList words = text.split(' '); - foreach (QString word, words) { + for (const QString &word : words) { if (!word.isEmpty()) { - FramedLabel *wordLabel = new FramedLabel(word, this); + auto wordLabel = new FramedLabel(word, this); wordLabel->move(x, y); wordLabel->show(); x += wordLabel->width() + 2; @@ -105,7 +105,6 @@ void DragWidget::dragLeaveEvent(QDragLeaveEvent *) update(); } - void DragWidget::dropEvent(QDropEvent *event) { if (event->mimeData()->hasText()) { @@ -141,9 +140,9 @@ void DragWidget::dropEvent(QDropEvent *event) } else { event->ignore(); } - foreach (QObject *child, children()) { - if (child->inherits("QWidget")) { - QWidget *widget = static_cast(child); + for (QObject *child : children()) { + if (child->isWidgetType()) { + auto widget = static_cast(child); if (!widget->isVisible()) widget->deleteLater(); } @@ -170,7 +169,7 @@ void DragWidget::mousePressEvent(QMouseEvent *event) pixmap.setDevicePixelRatio(dpr); child->render(&pixmap); - QDrag *drag = new QDrag(this); + auto drag = new QDrag(this); drag->setMimeData(mimeData); drag->setPixmap(pixmap); drag->setHotSpot(hotSpot); diff --git a/tests/manual/highdpi/dragwidget.h b/tests/manual/highdpi/dragwidget.h index 8b67b204102..06663fc74a4 100644 --- a/tests/manual/highdpi/dragwidget.h +++ b/tests/manual/highdpi/dragwidget.h @@ -40,7 +40,7 @@ QT_END_NAMESPACE class DragWidget : public QWidget { public: - DragWidget(QString text = QString(), QWidget *parent = 0); + DragWidget(QString text = QString(), QWidget *parent = nullptr); protected: void dragEnterEvent(QDragEnterEvent *event) override; @@ -52,12 +52,13 @@ protected: void timerEvent(QTimerEvent *event) override; void showEvent(QShowEvent *event) override; void hideEvent(QHideEvent *event) override; + private: QPoint dragPos; QPoint dropPos; QBasicTimer dragTimer; QBasicTimer dropTimer; - QWidget *otherWindow; + QWidget *otherWindow = nullptr; }; #endif // DRAGWIDGET_H diff --git a/tests/manual/highdpi/main.cpp b/tests/manual/highdpi/main.cpp index 51a7026e853..d764241d9be 100644 --- a/tests/manual/highdpi/main.cpp +++ b/tests/manual/highdpi/main.cpp @@ -61,6 +61,8 @@ #include "dragwidget.h" +#include + static QTextStream &operator<<(QTextStream &str, const QRect &r) { str << r.width() << 'x' << r.height() << forcesign << r.x() << r.y() << noforcesign; @@ -70,18 +72,18 @@ static QTextStream &operator<<(QTextStream &str, const QRect &r) class DemoContainerBase { public: - DemoContainerBase() : m_widget(nullptr) {} - virtual ~DemoContainerBase() {} - QString name() { return option().names().first(); } + DemoContainerBase() = default; + virtual ~DemoContainerBase() = default; + QString name() { return option().names().constFirst(); } virtual QCommandLineOption &option() = 0; virtual void makeVisible(bool visible, QWidget *parent) = 0; - QWidget *widget() { return m_widget; } + QWidget *widget() const { return m_widget; } + protected: - QWidget *m_widget; + QWidget *m_widget = nullptr; }; -typedef QList DemoContainerList ; - +using DemoContainerList = QVector; template class DemoContainer : public DemoContainerBase @@ -93,9 +95,10 @@ public: } ~DemoContainer() { delete m_widget; } - QCommandLineOption &option() { return m_option; } + QCommandLineOption &option() override { return m_option; } - void makeVisible(bool visible, QWidget *parent) { + void makeVisible(bool visible, QWidget *parent) override + { if (visible && !m_widget) { m_widget = new T; m_widget->installEventFilter(parent); @@ -103,6 +106,7 @@ public: if (m_widget) m_widget->setVisible(visible); } + private: QCommandLineOption m_option; }; @@ -134,12 +138,15 @@ public: connect(m_slider, &QSlider::sliderMoved, this, &LabelSlider::updateLabel); connect(m_slider, &QSlider::valueChanged, this, &LabelSlider::valueChanged); } - void setValue(int scaleFactor) { + void setValue(int scaleFactor) + { m_slider->setValue(scaleFactor); updateLabel(scaleFactor); } + private slots: - void updateLabel(int scaleFactor) { + void updateLabel(int scaleFactor) + { // slider value is scale factor times ten; qreal scalefactorF = qreal(scaleFactor) / 10.0; @@ -149,8 +156,10 @@ private slots: number.append(".0"); m_label->setText(number); } + signals: void valueChanged(int scaleFactor); + private: QSlider *m_slider; QLabel *m_label; @@ -172,28 +181,30 @@ static inline qreal getGlobalScaleFactor() class DemoController : public QWidget { -Q_OBJECT + Q_OBJECT public: - DemoController(DemoContainerList *demos, QCommandLineParser *parser); + DemoController(DemoContainerList demos, QCommandLineParser *parser); ~DemoController(); + protected: - bool eventFilter(QObject *object, QEvent *event); - void closeEvent(QCloseEvent *) { qApp->quit(); } + bool eventFilter(QObject *object, QEvent *event) override; + void closeEvent(QCloseEvent *) override { QCoreApplication::quit(); } + private slots: void handleButton(int id, bool toggled); + private: - DemoContainerList *m_demos; + DemoContainerList m_demos; QButtonGroup *m_group; }; -DemoController::DemoController(DemoContainerList *demos, QCommandLineParser *parser) - : m_demos(demos) +DemoController::DemoController(DemoContainerList demos, QCommandLineParser *parser) + : m_demos(std::move(demos)) { setWindowTitle("screen scale factors"); setObjectName("controller"); // make WindowScaleFactorSetter skip this window - QGridLayout *layout = new QGridLayout; - setLayout(layout); + auto layout = new QGridLayout(this); int layoutRow = 0; LabelSlider *globalScaleSlider = new LabelSlider(this, "Global scale factor", layout, layoutRow++); @@ -205,8 +216,8 @@ DemoController::DemoController(DemoContainerList *demos, QCommandLineParser *par }); // set up one scale control line per screen - QList screens = QGuiApplication::screens(); - foreach (QScreen *screen, screens) { + const auto screens = QGuiApplication::screens(); + for (QScreen *screen : screens) { // create scale control line QSize screenSize = screen->geometry().size(); QString screenId = screen->name() + QLatin1Char(' ') + QString::number(screenSize.width()) @@ -231,8 +242,8 @@ DemoController::DemoController(DemoContainerList *demos, QCommandLineParser *par m_group = new QButtonGroup(this); m_group->setExclusive(false); - for (int i = 0; i < m_demos->size(); ++i) { - DemoContainerBase *demo = m_demos->at(i); + for (int i = 0; i < m_demos.size(); ++i) { + DemoContainerBase *demo = m_demos.at(i); QPushButton *button = new QPushButton(demo->name()); button->setToolTip(demo->option().description()); button->setCheckable(true); @@ -244,19 +255,20 @@ DemoController::DemoController(DemoContainerList *demos, QCommandLineParser *par button->setChecked(true); } } - connect(m_group, SIGNAL(buttonToggled(int, bool)), this, SLOT(handleButton(int, bool))); + connect(m_group, QOverload::of(&QButtonGroup::buttonToggled), + this, &DemoController::handleButton); } DemoController::~DemoController() { - qDeleteAll(*m_demos); + qDeleteAll(m_demos); } bool DemoController::eventFilter(QObject *object, QEvent *event) { if (event->type() == QEvent::Close) { - for (int i = 0; i < m_demos->size(); ++i) { - DemoContainerBase *demo = m_demos->at(i); + for (int i = 0; i < m_demos.size(); ++i) { + DemoContainerBase *demo = m_demos.at(i); if (demo->widget() == object) { m_group->button(i)->setChecked(false); break; @@ -268,15 +280,17 @@ bool DemoController::eventFilter(QObject *object, QEvent *event) void DemoController::handleButton(int id, bool toggled) { - m_demos->at(id)->makeVisible(toggled, this); + m_demos.at(id)->makeVisible(toggled, this); } class PixmapPainter : public QWidget { public: PixmapPainter(); - void paintEvent(QPaintEvent *event); + void paintEvent(QPaintEvent *event) override; + +private: QPixmap pixmap1X; QPixmap pixmap2X; QPixmap pixmapLarge; @@ -348,12 +362,14 @@ void PixmapPainter::paintEvent(QPaintEvent *) class TiledPixmapPainter : public QWidget { public: + TiledPixmapPainter(); + + void paintEvent(QPaintEvent *event) override; + +private: QPixmap pixmap1X; QPixmap pixmap2X; QPixmap pixmapLarge; - - TiledPixmapPainter(); - void paintEvent(QPaintEvent *event); }; TiledPixmapPainter::TiledPixmapPainter() @@ -404,6 +420,7 @@ class Labels : public QWidget public: Labels(); +private: QPixmap pixmap1X; QPixmap pixmap2X; QPixmap pixmapLarge; @@ -454,12 +471,11 @@ private: QIcon qtIcon2x; QToolBar *fileToolBar; - int menuCount; QAction *m_maskAction; + int menuCount = 0; }; MainWindow::MainWindow() - :menuCount(0) { // beware that QIcon auto-loads the @2x versions. qtIcon1x.addFile(":/qticon16.png"); @@ -484,7 +500,6 @@ MainWindow::MainWindow() addNewMenu("&Help", 2); } - QMenu *MainWindow::addNewMenu(const QString &title, int itemCount) { QMenu *menu = menuBar()->addMenu(title); @@ -516,7 +531,7 @@ void MainWindow::maskActionToggled(bool t) class StandardIcons : public QWidget { public: - void paintEvent(QPaintEvent *) + void paintEvent(QPaintEvent *) override { int x = 10; int y = 10; @@ -538,7 +553,7 @@ public: class Caching : public QWidget { public: - void paintEvent(QPaintEvent *) + void paintEvent(QPaintEvent *) override { QSize layoutSize(75, 75); @@ -576,16 +591,12 @@ public: } }; -class Style : public QWidget { +class Style : public QWidget +{ public: - QPushButton *button; - QLineEdit *lineEdit; - QSlider *slider; - QHBoxLayout *row1; - - Style() { - row1 = new QHBoxLayout(); - setLayout(row1); + Style() + { + row1 = new QHBoxLayout(this); button = new QPushButton(); button->setText("Test Button"); @@ -601,17 +612,23 @@ public: row1->addWidget(new QSpinBox); row1->addWidget(new QScrollBar); - QTabBar *tab = new QTabBar(); + auto tab = new QTabBar(); tab->addTab("Foo"); tab->addTab("Bar"); row1->addWidget(tab); } + +private: + QPushButton *button; + QLineEdit *lineEdit; + QSlider *slider; + QHBoxLayout *row1; }; class Fonts : public QWidget { public: - void paintEvent(QPaintEvent *) + void paintEvent(QPaintEvent *) override { QPainter painter(this); @@ -690,7 +707,7 @@ public: iconNormalDpi.reset(new QIcon(path32_2)); // does not have a 2x version. } - void paintEvent(QPaintEvent *) + void paintEvent(QPaintEvent *) override { int x = 10; int y = 10; @@ -782,7 +799,7 @@ public: tab->move(10, 100); tab->show(); - QToolBar *toolBar = new QToolBar(this); + auto toolBar = new QToolBar(this); toolBar->addAction(QIcon(":/qticon16.png"), "16"); toolBar->addAction(QIcon(":/qticon16@2x.png"), "16@2x"); toolBar->addAction(QIcon(":/qticon32.png"), "32"); @@ -796,11 +813,12 @@ public: class LinePainter : public QWidget { public: - void paintEvent(QPaintEvent *event); - void mousePressEvent(QMouseEvent *event); - void mouseReleaseEvent(QMouseEvent *event); - void mouseMoveEvent(QMouseEvent *event); + void paintEvent(QPaintEvent *event) override; + void mousePressEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; +private: QPoint lastMousePoint; QVector linePoints; }; @@ -855,17 +873,15 @@ void LinePainter::mouseMoveEvent(QMouseEvent *event) class CursorTester : public QWidget { public: - CursorTester() - :moveLabel(nullptr), moving(false) - { - } + CursorTester() = default; inline QRect getRect(int idx) const { int h = height() / 2; return QRect(10, 10 + h * (idx - 1), width() - 20, h - 20); } - void paintEvent(QPaintEvent *) + + void paintEvent(QPaintEvent *) override { QPainter p(this); QRect r1 = getRect(1); @@ -899,7 +915,7 @@ public: } } - void mousePressEvent(QMouseEvent *e) + void mousePressEvent(QMouseEvent *e) override { if (moving) return; @@ -923,7 +939,7 @@ public: moveLabel->show(); } - void mouseReleaseEvent(QMouseEvent *) + void mouseReleaseEvent(QMouseEvent *) override { if (moveLabel) moveLabel->hide(); @@ -931,7 +947,7 @@ public: moving = false; } - void mouseMoveEvent(QMouseEvent *e) + void mouseMoveEvent(QMouseEvent *e) override { if (!moving) return; @@ -943,32 +959,32 @@ public: } private: - QLabel *moveLabel; - bool useCursorPos; - bool moving; + QLabel *moveLabel = nullptr; QPoint mousePos; + bool useCursorPos = false; + bool moving = false; }; - class ScreenDisplayer : public QWidget { public: - ScreenDisplayer() - : QWidget(), moveLabel(nullptr), scaleFactor(1.0) - { - } + ScreenDisplayer() = default; - void timerEvent(QTimerEvent *) { + void timerEvent(QTimerEvent *) override + { update(); } - void mousePressEvent(QMouseEvent *) { + void mousePressEvent(QMouseEvent *) override + { if (!moveLabel) moveLabel = new QLabel(this,Qt::BypassWindowManagerHint|Qt::FramelessWindowHint|Qt::Window ); moveLabel->setText("Hello, Qt this is a label\nwith some text"); moveLabel->show(); } - void mouseMoveEvent(QMouseEvent *e) { + + void mouseMoveEvent(QMouseEvent *e) override + { if (!moveLabel) return; moveLabel->move(e->pos() / scaleFactor); @@ -978,23 +994,30 @@ public: dbg << moveLabel->geometry(); moveLabel->setText(str); } - void mouseReleaseEvent(QMouseEvent *) { + + void mouseReleaseEvent(QMouseEvent *) override + { if (moveLabel) moveLabel->hide(); } - void showEvent(QShowEvent *) { + + void showEvent(QShowEvent *) override + { refreshTimer.start(300, this); } - void hideEvent(QHideEvent *) { + + void hideEvent(QHideEvent *) override + { refreshTimer.stop(); } - void paintEvent(QPaintEvent *) { + + void paintEvent(QPaintEvent *) override + { QPainter p(this); QRectF total; - QList screens = qApp->screens(); - foreach (QScreen *screen, screens) { + const auto screens = QGuiApplication::screens(); + for (const QScreen *screen : screens) total |= screen->geometry(); - } if (total.isEmpty()) return; @@ -1006,8 +1029,7 @@ public: p.setPen(QPen(Qt::white, 10)); p.setBrush(Qt::gray); - - foreach (QScreen *screen, screens) { + for (const QScreen *screen : screens) { p.drawRect(screen->geometry()); QFont f = font(); f.setPixelSize(screen->geometry().height() / 8); @@ -1015,7 +1037,9 @@ public: p.drawText(screen->geometry(), Qt::AlignCenter, screen->name()); } p.setBrush(QColor(200,220,255,127)); - foreach (QWidget *widget, QApplication::topLevelWidgets()) { + + const auto topLevels = QApplication::topLevelWidgets(); + for (QWidget *widget : topLevels) { if (!widget->isHidden()) p.drawRect(widget->geometry()); } @@ -1028,42 +1052,51 @@ public: cursorShape.translate(QCursor::pos()); p.drawPolygon(cursorShape); } + private: - QLabel *moveLabel; + QLabel *moveLabel = nullptr; + qreal scaleFactor = 1; QBasicTimer refreshTimer; - qreal scaleFactor; }; class PhysicalSizeTest : public QWidget { -Q_OBJECT + Q_OBJECT public: - PhysicalSizeTest() : QWidget(), m_ignoreResize(false) {} - void paintEvent(QPaintEvent *event); - void resizeEvent(QResizeEvent *) { + PhysicalSizeTest() = default; + + void paintEvent(QPaintEvent *event) override; + + void resizeEvent(QResizeEvent *) override + { qreal ppi = window()->windowHandle()->screen()->physicalDotsPerInchX(); QSizeF s = size(); if (!m_ignoreResize) m_physicalSize = s / ppi; } - bool event(QEvent *event) { + + bool event(QEvent *event) override + { if (event->type() == QEvent::ScreenChangeInternal) { // we will get resize events when the scale factor changes m_ignoreResize = true; - QTimer::singleShot(100, this, SLOT(handleScreenChange())); + QTimer::singleShot(100, this, &PhysicalSizeTest::handleScreenChange); } return QWidget::event(event); } + public slots: - void handleScreenChange() { + void handleScreenChange() + { qreal ppi = window()->windowHandle()->screen()->physicalDotsPerInchX(); QSizeF newSize = m_physicalSize * ppi; resize(newSize.toSize()); m_ignoreResize = false; } + private: QSizeF m_physicalSize; - bool m_ignoreResize; + bool m_ignoreResize = false; }; void PhysicalSizeTest::paintEvent(QPaintEvent *) @@ -1166,8 +1199,9 @@ void PhysicalSizeTest::paintEvent(QPaintEvent *) class GraphicsViewCaching : public QGraphicsView { public: - GraphicsViewCaching() { - QGraphicsScene *scene = new QGraphicsScene(0, 0, 400, 400); + GraphicsViewCaching() + { + auto scene = new QGraphicsScene(0, 0, 400, 400); QGraphicsTextItem *item = scene->addText("NoCache"); item->setCacheMode(QGraphicsItem::NoCache); @@ -1205,8 +1239,7 @@ QT_DPI_ADJUSTMENT_POLICY=AdjustDpi|DontAdjustDpi|AdjustUpOnly)"; resize(480, 360); - QVBoxLayout *layout = new QVBoxLayout(); - setLayout(layout); + auto layout = new QVBoxLayout(this); m_textEdit = new QPlainTextEdit; m_textEdit->setReadOnly(true); @@ -1254,7 +1287,7 @@ QT_DPI_ADJUSTMENT_POLICY=AdjustDpi|DontAdjustDpi|AdjustUpOnly)"; m_textEdit->setPlainText(text); } - void paintEvent(QPaintEvent *ev) + void paintEvent(QPaintEvent *ev) override { // We get a paint event on screen change, so this is a convenient place // to update the metrics, at the possible risk of doing something else @@ -1270,8 +1303,6 @@ int main(int argc, char **argv) QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); QCoreApplication::setApplicationVersion(QT_VERSION_STR); - int argumentCount = QCoreApplication::arguments().count(); - QCommandLineParser parser; parser.setApplicationDescription("High DPI tester. Pass one or more of the options to\n" "test various high-dpi aspects. \n" @@ -1302,15 +1333,15 @@ int main(int argc, char **argv) demoList << new DemoContainer("graphicsview", "Test QGraphicsView caching"); demoList << new DemoContainer("metrics", "Show display metrics"); - foreach (DemoContainerBase *demo, demoList) + for (DemoContainerBase *demo : qAsConst(demoList)) parser.addOption(demo->option()); parser.process(app); //controller takes ownership of all demos - DemoController controller(&demoList, &parser); + DemoController controller(demoList, &parser); - if (parser.isSet(controllerOption) || argumentCount <= 1) + if (parser.isSet(controllerOption) || QCoreApplication::arguments().count() <= 1) controller.show(); if (QApplication::topLevelWidgets().isEmpty()) From 43c8596be5e88a93b6743e95280e746e2ab5ae2d Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 27 Nov 2019 09:59:33 +0100 Subject: [PATCH 29/45] More polish of the manual High DPI test The aim is to make it suitable to test for High DPI bugs, ideally removing the need to provide bug report examples. - Add descriptive window titles/output - Add options to force scaling on/off - Change the updating of the text to be done in screenChanged() and log the signal. - Rearrange the layout and show the descriptions as labels Task-number: QTBUG-80323 Change-Id: Ia44c184c2b38cb18045c40b440fe785c6c17925f Reviewed-by: Shawn Rutledge --- tests/manual/highdpi/main.cpp | 98 +++++++++++++++++++++++++++-------- 1 file changed, 76 insertions(+), 22 deletions(-) diff --git a/tests/manual/highdpi/main.cpp b/tests/manual/highdpi/main.cpp index d764241d9be..0d4d3beef78 100644 --- a/tests/manual/highdpi/main.cpp +++ b/tests/manual/highdpi/main.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -69,6 +70,15 @@ static QTextStream &operator<<(QTextStream &str, const QRect &r) return str; } +static QString formatWindowTitle(const QString &title) +{ + QString result; + QTextStream(&result) << title << ' ' << QT_VERSION_STR << " (" + << QGuiApplication::platformName() + << '/' << QApplication::style()->objectName() << ')'; + return result; +} + class DemoContainerBase { public: @@ -101,6 +111,13 @@ public: { if (visible && !m_widget) { m_widget = new T; + if (m_widget->windowTitle().isEmpty()) { + QString title = m_option.description(); + if (title.startsWith("Test ", Qt::CaseInsensitive)) + title.remove(0, 5); + title[0] = title.at(0).toUpper(); + m_widget->setWindowTitle(formatWindowTitle(title)); + } m_widget->installEventFilter(parent); } if (m_widget) @@ -201,13 +218,15 @@ private: DemoController::DemoController(DemoContainerList demos, QCommandLineParser *parser) : m_demos(std::move(demos)) { - setWindowTitle("screen scale factors"); + setWindowTitle(formatWindowTitle("Screen Scale Factors")); setObjectName("controller"); // make WindowScaleFactorSetter skip this window - auto layout = new QGridLayout(this); + auto mainLayout = new QVBoxLayout(this); + auto scaleLayout = new QGridLayout; + mainLayout->addLayout(scaleLayout); int layoutRow = 0; - LabelSlider *globalScaleSlider = new LabelSlider(this, "Global scale factor", layout, layoutRow++); + LabelSlider *globalScaleSlider = new LabelSlider(this, "Global scale factor", scaleLayout, layoutRow++); globalScaleSlider->setValue(int(getGlobalScaleFactor() * 10)); connect(globalScaleSlider, &LabelSlider::valueChanged, [](int scaleFactor){ // slider value is scale factor times ten; @@ -222,7 +241,7 @@ DemoController::DemoController(DemoContainerList demos, QCommandLineParser *pars QSize screenSize = screen->geometry().size(); QString screenId = screen->name() + QLatin1Char(' ') + QString::number(screenSize.width()) + QLatin1Char(' ') + QString::number(screenSize.height()); - LabelSlider *slider = new LabelSlider(this, screenId, layout, layoutRow++); + LabelSlider *slider = new LabelSlider(this, screenId, scaleLayout, layoutRow++); slider->setValue(getScreenFactorWithoutPixelDensity(screen) * 10); // handle slider value change @@ -239,15 +258,18 @@ DemoController::DemoController(DemoContainerList demos, QCommandLineParser *pars }); } + auto demoLayout = new QFormLayout; + mainLayout->addLayout(demoLayout); m_group = new QButtonGroup(this); m_group->setExclusive(false); for (int i = 0; i < m_demos.size(); ++i) { DemoContainerBase *demo = m_demos.at(i); - QPushButton *button = new QPushButton(demo->name()); - button->setToolTip(demo->option().description()); + QString name = demo->name(); + name[0] = name.at(0).toUpper(); + auto button = new QPushButton(name); button->setCheckable(true); - layout->addWidget(button, layoutRow++, 0, 1, -1); + demoLayout->addRow(demo->option().description(), button); m_group->addButton(button, i); if (parser->isSet(demo->option())) { @@ -436,7 +458,7 @@ Labels::Labels() qtIcon.addFile(":/qticon32.png"); qtIcon.addFile(":/qticon32@2x.png"); setWindowIcon(qtIcon); - setWindowTitle("Labels"); + setWindowTitle(formatWindowTitle("Labels")); QLabel *label1x = new QLabel(); label1x->setPixmap(pixmap1X); @@ -481,7 +503,7 @@ MainWindow::MainWindow() qtIcon1x.addFile(":/qticon16.png"); qtIcon2x.addFile(":/qticon32.png"); setWindowIcon(qtIcon); - setWindowTitle("MainWindow"); + setWindowTitle(formatWindowTitle("MainWindow")); fileToolBar = addToolBar(tr("File")); // fileToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); @@ -1221,14 +1243,13 @@ public: class MetricsTest : public QWidget { - QPlainTextEdit *m_textEdit; - + Q_OBJECT public: MetricsTest() { - qDebug() << R"( -MetricsTest -Relevant environment variables are: + qDebug().noquote().nospace() << "MetricsTest " << QT_VERSION_STR + << ' ' << QGuiApplication::platformName() << '\n' +<< R"(Relevant environment variables are: QT_FONT_DPI=N QT_SCALE_FACTOR=n QT_ENABLE_HIGHDPI_SCALING=0|1 @@ -1244,6 +1265,18 @@ QT_DPI_ADJUSTMENT_POLICY=AdjustDpi|DontAdjustDpi|AdjustUpOnly)"; m_textEdit = new QPlainTextEdit; m_textEdit->setReadOnly(true); layout->addWidget(m_textEdit); + setWindowTitle(formatWindowTitle("Screens")); + } + + void setVisible(bool visible) override + { + QWidget::setVisible(visible); + if (visible && !m_screenChangedConnected) { + m_screenChangedConnected = true; + QObject::connect(windowHandle(), &QWindow::screenChanged, + this, &MetricsTest::screenChanged); + updateMetrics(); + } } void updateMetrics() @@ -1287,18 +1320,38 @@ QT_DPI_ADJUSTMENT_POLICY=AdjustDpi|DontAdjustDpi|AdjustUpOnly)"; m_textEdit->setPlainText(text); } - void paintEvent(QPaintEvent *ev) override +private slots: + void screenChanged() { - // We get a paint event on screen change, so this is a convenient place - // to update the metrics, at the possible risk of doing something else - // than painting in a paint event. + qDebug().noquote() << __FUNCTION__ << windowHandle()->screen()->name(); updateMetrics(); - QWidget::paintEvent(ev); } + +private: + QPlainTextEdit *m_textEdit; + bool m_screenChangedConnected = false; }; int main(int argc, char **argv) { +#define NOSCALINGOPTION "noscaling" +#define SCALINGOPTION "scaling" + + qInfo("High DPI tester %s", QT_VERSION_STR); + + int preAppOptionCount = 0; + for (int a = 1; a < argc; ++a) { + if (qstrcmp(argv[a], "--" NOSCALINGOPTION) == 0) { + QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling); + preAppOptionCount++; + qInfo("AA_DisableHighDpiScaling"); + } else if (qstrcmp(argv[a], "--" SCALINGOPTION) == 0) { + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + preAppOptionCount++; + qInfo("AA_EnableHighDpiScaling"); + } + } + QApplication app(argc, argv); QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); QCoreApplication::setApplicationVersion(QT_VERSION_STR); @@ -1312,7 +1365,8 @@ int main(int argc, char **argv) parser.addVersionOption(); QCommandLineOption controllerOption("interactive", "Show configuration window."); parser.addOption(controllerOption); - + parser.addOption(QCommandLineOption(NOSCALINGOPTION, "Set AA_DisableHighDpiScaling")); + parser.addOption(QCommandLineOption(SCALINGOPTION, "Set AA_EnableHighDpiScaling")); DemoContainerList demoList; demoList << new DemoContainer("pixmap", "Test pixmap painter"); @@ -1331,7 +1385,7 @@ int main(int argc, char **argv) demoList << new DemoContainer("screens", "Test screen and window positioning"); demoList << new DemoContainer("physicalsize", "Test manual highdpi support using physicalDotsPerInch"); demoList << new DemoContainer("graphicsview", "Test QGraphicsView caching"); - demoList << new DemoContainer("metrics", "Show display metrics"); + demoList << new DemoContainer("metrics", "Show screen metrics"); for (DemoContainerBase *demo : qAsConst(demoList)) parser.addOption(demo->option()); @@ -1341,7 +1395,7 @@ int main(int argc, char **argv) //controller takes ownership of all demos DemoController controller(demoList, &parser); - if (parser.isSet(controllerOption) || QCoreApplication::arguments().count() <= 1) + if (parser.isSet(controllerOption) || (QCoreApplication::arguments().count() - preAppOptionCount) <= 1) controller.show(); if (QApplication::topLevelWidgets().isEmpty()) From 9fd217e7467fa5f82340c30b1b6bb28557057919 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 27 Nov 2019 12:46:28 +0100 Subject: [PATCH 30/45] Silence intel compiler warning about float comparison Add the equivalent intel warning macro in public header where there was already the macro for -Wfloat-equal Change-Id: I8f20400f0b95c8f3857fa7a0a33464c8c34d5c0e Reviewed-by: Thiago Macieira --- src/corelib/global/qfloat16.h | 1 + src/corelib/tools/qpoint.h | 1 + src/corelib/tools/qrect.h | 1 + src/gui/math3d/qmatrix4x4.h | 1 + src/gui/math3d/qquaternion.h | 1 + src/gui/math3d/qvector2d.h | 1 + src/gui/math3d/qvector3d.h | 1 + src/gui/math3d/qvector4d.h | 1 + src/gui/painting/qtransform.h | 1 + 9 files changed, 9 insertions(+) diff --git a/src/corelib/global/qfloat16.h b/src/corelib/global/qfloat16.h index 9a4f1800a42..02fd2f03cc3 100644 --- a/src/corelib/global/qfloat16.h +++ b/src/corelib/global/qfloat16.h @@ -239,6 +239,7 @@ QF16_MAKE_ARITH_OP_INT(/) QT_WARNING_PUSH QT_WARNING_DISABLE_CLANG("-Wfloat-equal") QT_WARNING_DISABLE_GCC("-Wfloat-equal") +QT_WARNING_DISABLE_INTEL(1572) inline bool operator>(qfloat16 a, qfloat16 b) noexcept { return static_cast(a) > static_cast(b); } inline bool operator<(qfloat16 a, qfloat16 b) noexcept { return static_cast(a) < static_cast(b); } diff --git a/src/corelib/tools/qpoint.h b/src/corelib/tools/qpoint.h index fe952f95da4..f0a91c4ff8e 100644 --- a/src/corelib/tools/qpoint.h +++ b/src/corelib/tools/qpoint.h @@ -352,6 +352,7 @@ Q_DECL_RELAXED_CONSTEXPR inline QPointF &QPointF::operator*=(qreal c) QT_WARNING_PUSH QT_WARNING_DISABLE_CLANG("-Wfloat-equal") QT_WARNING_DISABLE_GCC("-Wfloat-equal") +QT_WARNING_DISABLE_INTEL(1572) Q_DECL_CONSTEXPR inline bool operator==(const QPointF &p1, const QPointF &p2) { diff --git a/src/corelib/tools/qrect.h b/src/corelib/tools/qrect.h index 7aa2312f38d..c6bfc1a50d1 100644 --- a/src/corelib/tools/qrect.h +++ b/src/corelib/tools/qrect.h @@ -665,6 +665,7 @@ Q_DECL_CONSTEXPR inline QRectF::QRectF(const QRect &r) noexcept QT_WARNING_PUSH QT_WARNING_DISABLE_CLANG("-Wfloat-equal") QT_WARNING_DISABLE_GCC("-Wfloat-equal") +QT_WARNING_DISABLE_INTEL(1572) Q_DECL_CONSTEXPR inline bool QRectF::isNull() const noexcept { return w == 0. && h == 0.; } diff --git a/src/gui/math3d/qmatrix4x4.h b/src/gui/math3d/qmatrix4x4.h index 69c3510659a..1439bfac597 100644 --- a/src/gui/math3d/qmatrix4x4.h +++ b/src/gui/math3d/qmatrix4x4.h @@ -215,6 +215,7 @@ private: QT_WARNING_PUSH QT_WARNING_DISABLE_CLANG("-Wfloat-equal") QT_WARNING_DISABLE_GCC("-Wfloat-equal") +QT_WARNING_DISABLE_INTEL(1572) Q_DECLARE_TYPEINFO(QMatrix4x4, Q_MOVABLE_TYPE); inline QMatrix4x4::QMatrix4x4 diff --git a/src/gui/math3d/qquaternion.h b/src/gui/math3d/qquaternion.h index cd0d746e55a..f01fab679e1 100644 --- a/src/gui/math3d/qquaternion.h +++ b/src/gui/math3d/qquaternion.h @@ -171,6 +171,7 @@ inline QQuaternion::QQuaternion(float aScalar, float xpos, float ypos, float zpo QT_WARNING_PUSH QT_WARNING_DISABLE_CLANG("-Wfloat-equal") QT_WARNING_DISABLE_GCC("-Wfloat-equal") +QT_WARNING_DISABLE_INTEL(1572) inline bool QQuaternion::isNull() const { return wp == 0.0f && xp == 0.0f && yp == 0.0f && zp == 0.0f; diff --git a/src/gui/math3d/qvector2d.h b/src/gui/math3d/qvector2d.h index 88d8bc199e2..cbce94c1999 100644 --- a/src/gui/math3d/qvector2d.h +++ b/src/gui/math3d/qvector2d.h @@ -207,6 +207,7 @@ inline QVector2D &QVector2D::operator/=(const QVector2D &vector) QT_WARNING_PUSH QT_WARNING_DISABLE_CLANG("-Wfloat-equal") QT_WARNING_DISABLE_GCC("-Wfloat-equal") +QT_WARNING_DISABLE_INTEL(1572) Q_DECL_CONSTEXPR inline bool operator==(const QVector2D &v1, const QVector2D &v2) { return v1.v[0] == v2.v[0] && v1.v[1] == v2.v[1]; diff --git a/src/gui/math3d/qvector3d.h b/src/gui/math3d/qvector3d.h index 1b49f3e7b93..d7ffb0bcc42 100644 --- a/src/gui/math3d/qvector3d.h +++ b/src/gui/math3d/qvector3d.h @@ -232,6 +232,7 @@ inline QVector3D &QVector3D::operator/=(const QVector3D &vector) QT_WARNING_PUSH QT_WARNING_DISABLE_CLANG("-Wfloat-equal") QT_WARNING_DISABLE_GCC("-Wfloat-equal") +QT_WARNING_DISABLE_INTEL(1572) Q_DECL_CONSTEXPR inline bool operator==(const QVector3D &v1, const QVector3D &v2) { return v1.v[0] == v2.v[0] && v1.v[1] == v2.v[1] && v1.v[2] == v2.v[2]; diff --git a/src/gui/math3d/qvector4d.h b/src/gui/math3d/qvector4d.h index 08cb423484a..afcc71fa882 100644 --- a/src/gui/math3d/qvector4d.h +++ b/src/gui/math3d/qvector4d.h @@ -232,6 +232,7 @@ inline QVector4D &QVector4D::operator/=(const QVector4D &vector) QT_WARNING_PUSH QT_WARNING_DISABLE_CLANG("-Wfloat-equal") QT_WARNING_DISABLE_GCC("-Wfloat-equal") +QT_WARNING_DISABLE_INTEL(1572) Q_DECL_CONSTEXPR inline bool operator==(const QVector4D &v1, const QVector4D &v2) { return v1.v[0] == v2.v[0] && v1.v[1] == v2.v[1] && v1.v[2] == v2.v[2] && v1.v[3] == v2.v[3]; diff --git a/src/gui/painting/qtransform.h b/src/gui/painting/qtransform.h index b2207701447..b2a634dd2a8 100644 --- a/src/gui/painting/qtransform.h +++ b/src/gui/painting/qtransform.h @@ -303,6 +303,7 @@ inline qreal QTransform::dy() const QT_WARNING_PUSH QT_WARNING_DISABLE_CLANG("-Wfloat-equal") QT_WARNING_DISABLE_GCC("-Wfloat-equal") +QT_WARNING_DISABLE_INTEL(1572) inline QTransform &QTransform::operator*=(qreal num) { From 5b1a4578f545d5181265d9120b48bc92753b63b9 Mon Sep 17 00:00:00 2001 From: Fredrik Orderud Date: Wed, 27 Nov 2019 20:27:19 +0100 Subject: [PATCH 31/45] wasm: Disable TextureSwizzle The WebGL 2.0 specification explicitly does not support texture swizzles. Therefore, disabling it when targeting WASM. This fixes "WebGL: INVALID_ENUM: texParameter: invalid parameter name" when running in Chrome or Firefox. Change-Id: Ic7e22e0f623095245274924095cb63fd0ff7e8c2 Reference: https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.19 Fixes: QTBUG-80287 Reviewed-by: Laszlo Agocs --- src/gui/opengl/qopenglfunctions.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp index 8ec814296a1..bc3a4f7c1d0 100644 --- a/src/gui/opengl/qopenglfunctions.cpp +++ b/src/gui/opengl/qopenglfunctions.cpp @@ -388,8 +388,12 @@ static int qt_gl_resolve_extensions() | QOpenGLExtensions::MapBufferRange | QOpenGLExtensions::FramebufferBlit | QOpenGLExtensions::FramebufferMultisample - | QOpenGLExtensions::Sized8Formats - | QOpenGLExtensions::TextureSwizzle; + | QOpenGLExtensions::Sized8Formats; +#ifndef Q_OS_WASM + // WebGL 2.0 specification explicitly does not support texture swizzles + // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.19 + extensions |= QOpenGLExtensions::TextureSwizzle; +#endif } else { // Recognize features by extension name. if (extensionMatcher.match("GL_OES_packed_depth_stencil")) From 67bbe28d67c99d99e752cd6054c9b576c7702358 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Thu, 28 Nov 2019 13:14:03 +0100 Subject: [PATCH 32/45] tst_qsslcertificate: fix subjectAndIssuerAttributes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of OID as string, OpenSSL returns a human-readable name. No need to fail then, use such a name in QVERIFY if OID not found. Fixes: QTBUG-80329 Change-Id: I4392fc9f37367f7c34c05d172db015b44e2a8497 Reviewed-by: Mårten Nordheim --- tests/auto/network/ssl/qsslcertificate/BLACKLIST | 13 ------------- .../ssl/qsslcertificate/tst_qsslcertificate.cpp | 10 +++++++++- 2 files changed, 9 insertions(+), 14 deletions(-) delete mode 100644 tests/auto/network/ssl/qsslcertificate/BLACKLIST diff --git a/tests/auto/network/ssl/qsslcertificate/BLACKLIST b/tests/auto/network/ssl/qsslcertificate/BLACKLIST deleted file mode 100644 index 9494ee22783..00000000000 --- a/tests/auto/network/ssl/qsslcertificate/BLACKLIST +++ /dev/null @@ -1,13 +0,0 @@ -# OpenSSL version is too new. Rich will fix :) -[subjectAndIssuerAttributes] -ubuntu-16.04 -rhel-7.6 -opensuse-leap -windows-7sp1 -ubuntu-18.04 -rhel-7.4 -b2qt -windows-10 msvc-2017 -windows-10 msvc-2015 -opensuse-42.3 - diff --git a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp index efc0c260768..14718ad373f 100644 --- a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp +++ b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp @@ -33,6 +33,10 @@ #include #include +#ifndef QT_NO_OPENSSL +#include +#endif + class tst_QSslCertificate : public QObject { Q_OBJECT @@ -960,8 +964,12 @@ void tst_QSslCertificate::subjectAndIssuerAttributes() certList = QSslCertificate::fromPath(testDataDir + "more-certificates/natwest-banking.pem"); QVERIFY(certList.count() > 0); + QByteArray shortName("1.3.6.1.4.1.311.60.2.1.3"); +#if !defined(QT_NO_OPENSSL) && defined(SN_jurisdictionCountryName) + shortName = SN_jurisdictionCountryName; +#endif attributes = certList[0].subjectInfoAttributes(); - QVERIFY(attributes.contains(QByteArray("1.3.6.1.4.1.311.60.2.1.3"))); + QVERIFY(attributes.contains(shortName)); } void tst_QSslCertificate::verify() From 985f4910249a0308b746695e64aa1a6205492421 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Mon, 25 Nov 2019 21:30:25 +0100 Subject: [PATCH 33/45] QTreeView: Reset the pressed index if the decoration was pressed on We need to reset the pressed index when the decoration was pressed on otherwise if the mouse ends up over an already selected item that was previously clicked on. This prevents it from thinking that the mouse has been released on this item right after pressing on it. Fixes: QTBUG-59067 Change-Id: Iab372ae20db3682ab0812661f86533079ba4083c Reviewed-by: Christian Ehrlicher --- src/widgets/itemviews/qtreeview.cpp | 2 ++ .../itemviews/qtreeview/tst_qtreeview.cpp | 18 ++++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp index 034c1f4b4f7..442369c2ec2 100644 --- a/src/widgets/itemviews/qtreeview.cpp +++ b/src/widgets/itemviews/qtreeview.cpp @@ -1892,6 +1892,8 @@ void QTreeView::mousePressEvent(QMouseEvent *event) handled = d->expandOrCollapseItemAtPos(event->pos()); if (!handled && d->itemDecorationAt(event->pos()) == -1) QAbstractItemView::mousePressEvent(event); + else + d->pressedIndex = QModelIndex(); } /*! diff --git a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp index 58ca924fe2c..b2ca62227f4 100644 --- a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp +++ b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp @@ -4875,13 +4875,27 @@ void tst_QTreeView::taskQTBUG_61476() const QPoint pos = rect.center(); QTest::mousePress(tv.viewport(), Qt::LeftButton, {}, pos); - if (tv.style()->styleHint(QStyle::SH_ListViewExpand_SelectMouseType, nullptr, &tv) == - QEvent::MouseButtonPress) + const bool expandsOnPress = + (tv.style()->styleHint(QStyle::SH_ListViewExpand_SelectMouseType, nullptr, &tv) == QEvent::MouseButtonPress); + if (expandsOnPress) QTRY_VERIFY(!tv.isExpanded(mi)); QTest::mouseRelease(tv.viewport(), Qt::LeftButton, nullptr, pos); QTRY_VERIFY(!tv.isExpanded(mi)); QCOMPARE(lastTopLevel->checkState(), Qt::Checked); + + // Test that it does not toggle the check state of a previously selected item when collapsing an + // item causes it to position the item under the mouse to be the decoration for the selected item + tv.expandAll(); + tv.verticalScrollBar()->setValue(tv.verticalScrollBar()->maximum()); + // It is not enough to programmatically select the item, we need to have it clicked on + QTest::mouseClick(tv.viewport(), Qt::LeftButton, {}, tv.visualRect(lastTopLevel->index()).center()); + QTest::mousePress(tv.viewport(), Qt::LeftButton, {}, pos); + if (expandsOnPress) + QTRY_VERIFY(!tv.isExpanded(mi)); + QTest::mouseRelease(tv.viewport(), Qt::LeftButton, nullptr, pos); + QTRY_VERIFY(!tv.isExpanded(mi)); + QCOMPARE(lastTopLevel->checkState(), Qt::Checked); } QTEST_MAIN(tst_QTreeView) From cc5c47d85f106356e290a95f2cca2c38b1b3c42d Mon Sep 17 00:00:00 2001 From: Peter Varga Date: Thu, 21 Nov 2019 16:37:06 +0100 Subject: [PATCH 34/45] macOS Accessibility: Fix role for comboboxes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise combobox with editable text field won't work. Change-Id: I135c3a63cf8fba66d724e140a5a63828853e154e Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoaaccessibility.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm index db4ec251aed..106c226adc6 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm @@ -133,7 +133,7 @@ static void populateRoleMap() roleMap[QAccessible::SpinBox] = NSAccessibilityIncrementorRole; roleMap[QAccessible::Slider] = NSAccessibilitySliderRole; roleMap[QAccessible::ProgressBar] = NSAccessibilityProgressIndicatorRole; - roleMap[QAccessible::ComboBox] = NSAccessibilityPopUpButtonRole; + roleMap[QAccessible::ComboBox] = NSAccessibilityComboBoxRole; roleMap[QAccessible::RadioButton] = NSAccessibilityRadioButtonRole; roleMap[QAccessible::CheckBox] = NSAccessibilityCheckBoxRole; roleMap[QAccessible::StaticText] = NSAccessibilityStaticTextRole; From 0f812db558df072a411ade3305b796d54bccd996 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 29 Nov 2019 10:43:20 +0100 Subject: [PATCH 35/45] rhi: vulkan: Remove unused include QVulkanWindow support has long been removed from the Vulkan backend. The include is a leftover from those times. Change-Id: Ie68ac3611b24310f2b6111a72dd0679adafdc74d Reviewed-by: Johan Helsing --- src/gui/rhi/qrhivulkan.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp index 103fea627a5..444a395ebcd 100644 --- a/src/gui/rhi/qrhivulkan.cpp +++ b/src/gui/rhi/qrhivulkan.cpp @@ -48,7 +48,6 @@ #include #include -#include QT_BEGIN_NAMESPACE From c0fb2a81737c07f213c3a8c36732149e0c58ed0d Mon Sep 17 00:00:00 2001 From: Elvis Angelaccio Date: Sun, 24 Nov 2019 21:11:25 +0100 Subject: [PATCH 36/45] QDBusInterface: mention QtDBus caching in documentation QtDBus caches well known interface objects when there is a non-emtpy interface name passed to the QDBusInterface constructor. This commit amends the constructor documentation to explain this behavior. Change-Id: Ic51836be6d833411500ea05fcc895cd4f6e96407 Reviewed-by: Thiago Macieira --- src/dbus/qdbusinterface.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/dbus/qdbusinterface.cpp b/src/dbus/qdbusinterface.cpp index 4dd02e8c764..b53c639b6d8 100644 --- a/src/dbus/qdbusinterface.cpp +++ b/src/dbus/qdbusinterface.cpp @@ -204,7 +204,9 @@ QDBusInterfacePrivate::~QDBusInterfacePrivate() interface \a interface on object at path \a path on service \a service, using the given \a connection. If \a interface is an empty string, the object created will refer to the merging of all - interfaces found in that object. + interfaces found by introspecting that object. Otherwise if + \a interface is not empty, the QDBusInterface object will be cached + to speedup further creations of the same interface. \a parent is passed to the base class constructor. From 7a55a984d8d0da6a6cf6fdc440d4cccf7fb42c3d Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Fri, 29 Nov 2019 13:08:17 +0100 Subject: [PATCH 37/45] Workaround warning in QHash::unite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The warning pragmas don't work in gcc due to the fact this is a template. I've been told that unite() will disappear but meanwhile i think it's better if we simply don't give a warning that people can't protect themselves against Change-Id: I358e629be86e0e675ef3e49a7fbc4f7f65ae97f6 Reviewed-by: Thiago Macieira Reviewed-by: Mårten Nordheim Reviewed-by: Christian Ehrlicher --- src/corelib/tools/qhash.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index 9108be4dc6f..42f8dbd155b 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -616,10 +616,7 @@ Q_INLINE_TEMPLATE QHash &QHash::unite(const QHash &other) QHash copy(other); const_iterator it = copy.constEnd(); while (it != copy.constBegin()) { - QT_WARNING_PUSH - QT_WARNING_DISABLE_DEPRECATED - --it; - QT_WARNING_POP + it.i = QHashData::previousNode(it.i); insertMulti(it.key(), it.value()); } #else From b63141fb1496e528e0e155513a5d4e954b0a1565 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 2 Dec 2019 09:14:19 +0100 Subject: [PATCH 38/45] RHI/Vulkan: Fix build Add missing include, fixing: rhi\qrhivulkan.cpp(6273): error C2027: use of undefined type 'QWindow' Amends 0f812db558df072a411ade3305b796d54bccd996. Change-Id: Ide61b713e958877f18a45a89b36a4e1330f75821 Reviewed-by: Laszlo Agocs --- src/gui/rhi/qrhivulkan.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp index 444a395ebcd..a200a6e271a 100644 --- a/src/gui/rhi/qrhivulkan.cpp +++ b/src/gui/rhi/qrhivulkan.cpp @@ -48,6 +48,7 @@ #include #include +#include QT_BEGIN_NAMESPACE From f81f21151d30a37f955aa4af2398a96507626b15 Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Mon, 2 Mar 2015 21:13:35 +0100 Subject: [PATCH 39/45] Session management for macOS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch aims to implement the session management available on macOS. Currently applicationShouldTerminate is just a go through that closes everything and ends the application. The new implementation calls first appCommitData and cancels the termination properly if required. This means that if a user wishes to logout, Qt applications can now cancel that like e.g. answering to Safari asking whether it is ok to close because of a number of opened tab/window. Fixes: QTBUG-33034 Change-Id: Id5d7416cb74c762c5424a77c9c7664f0749da7f6 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/cocoa.pro | 5 ++ .../cocoa/qcocoaapplicationdelegate.mm | 16 +++- .../platforms/cocoa/qcocoaintegration.h | 4 + .../platforms/cocoa/qcocoaintegration.mm | 10 +++ .../platforms/cocoa/qcocoasessionmanager.cpp | 88 +++++++++++++++++++ .../platforms/cocoa/qcocoasessionmanager.h | 81 +++++++++++++++++ .../sessionmanagement_macos.pro | 10 +++ .../tst_sessionmanagement_macos.mm | 61 +++++++++++++ 8 files changed, 274 insertions(+), 1 deletion(-) create mode 100644 src/plugins/platforms/cocoa/qcocoasessionmanager.cpp create mode 100644 src/plugins/platforms/cocoa/qcocoasessionmanager.h create mode 100644 tests/auto/other/sessionmanagement_macos/sessionmanagement_macos.pro create mode 100644 tests/auto/other/sessionmanagement_macos/tst_sessionmanagement_macos.mm diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro index 4cf9e644479..8f2956e7d41 100644 --- a/src/plugins/platforms/cocoa/cocoa.pro +++ b/src/plugins/platforms/cocoa/cocoa.pro @@ -87,6 +87,11 @@ qtConfig(accessibility) { qcocoaaccessibility.h } +qtConfig(sessionmanager) { + SOURCES += qcocoasessionmanager.cpp + HEADERS += qcocoasessionmanager.h +} + RESOURCES += qcocoaresources.qrc LIBS += -framework AppKit -framework CoreServices -framework Carbon -framework IOKit -framework QuartzCore -framework CoreVideo -framework Metal -framework IOSurface -lcups diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm index f1fe2aa98b9..3fb9e83d35d 100644 --- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm +++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm @@ -79,11 +79,14 @@ #include "qcocoamenuitem.h" #include "qcocoansmenu.h" +#if QT_CONFIG(sessionmanager) +# include "qcocoasessionmanager.h" +#endif + #include #include #include #include -#include #include "qt_mac_p.h" #include #include @@ -157,6 +160,17 @@ QT_USE_NAMESPACE return NSTerminateNow; } +#if QT_CONFIG(sessionmanager) + QCocoaSessionManager *cocoaSessionManager = QCocoaSessionManager::instance(); + cocoaSessionManager->resetCancellation(); + cocoaSessionManager->appCommitData(); + + if (cocoaSessionManager->wasCanceled()) { + qCDebug(lcQpaApplication) << "Session management canceled application termination"; + return NSTerminateCancel; + } +#endif + if (!QWindowSystemInterface::handleApplicationTermination()) { qCDebug(lcQpaApplication) << "Application termination canceled"; return NSTerminateCancel; diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h index bfc3bfe9de0..0c14e075518 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.h +++ b/src/plugins/platforms/cocoa/qcocoaintegration.h @@ -92,6 +92,10 @@ public: QCocoaVulkanInstance *getCocoaVulkanInstance() const; #endif +#if QT_CONFIG(sessionmanager) + QPlatformSessionManager *createPlatformSessionManager(const QString &id, const QString &key) const override; +#endif + QCoreTextFontDatabase *fontDatabase() const override; QCocoaNativeInterface *nativeInterface() const override; QPlatformInputContext *inputContext() const override; diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 9a2f19c2f2a..75d428c16ff 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -52,6 +52,9 @@ #include "qcocoamimetypes.h" #include "qcocoaaccessibility.h" #include "qcocoascreen.h" +#if QT_CONFIG(sessionmanager) +# include "qcocoasessionmanager.h" +#endif #include #include @@ -255,6 +258,13 @@ QCocoaIntegration::Options QCocoaIntegration::options() const return mOptions; } +#if QT_CONFIG(sessionmanager) +QPlatformSessionManager *QCocoaIntegration::createPlatformSessionManager(const QString &id, const QString &key) const +{ + return new QCocoaSessionManager(id, key); +} +#endif + bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) const { switch (cap) { diff --git a/src/plugins/platforms/cocoa/qcocoasessionmanager.cpp b/src/plugins/platforms/cocoa/qcocoasessionmanager.cpp new file mode 100644 index 00000000000..74e318b5be1 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoasessionmanager.cpp @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Samuel Gaist +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QT_NO_SESSIONMANAGER +#include +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +QCocoaSessionManager::QCocoaSessionManager(const QString &id, const QString &key) + : QPlatformSessionManager(id, key), + m_canceled(false) +{ +} + +QCocoaSessionManager::~QCocoaSessionManager() +{ +} + +bool QCocoaSessionManager::allowsInteraction() +{ + return false; +} + +void QCocoaSessionManager::resetCancellation() +{ + m_canceled = false; +} + +void QCocoaSessionManager::cancel() +{ + m_canceled = true; +} + +bool QCocoaSessionManager::wasCanceled() const +{ + return m_canceled; +} + +QCocoaSessionManager *QCocoaSessionManager::instance() +{ + auto *qGuiAppPriv = QGuiApplicationPrivate::instance(); + auto *managerPrivate = static_cast(QObjectPrivate::get(qGuiAppPriv->session_manager)); + return static_cast(managerPrivate->platformSessionManager); +} + +QT_END_NAMESPACE + +#endif // QT_NO_SESSIONMANAGER diff --git a/src/plugins/platforms/cocoa/qcocoasessionmanager.h b/src/plugins/platforms/cocoa/qcocoasessionmanager.h new file mode 100644 index 00000000000..89ab7bd157c --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoasessionmanager.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Samuel Gaist +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCOCOASESSIONMANAGER_H +#define QCOCOASESSIONMANAGER_H + +// +// W A R N I N G +// ------------- +// +// This file is part of the QPA API and is not meant to be used +// in applications. Usage of this API may make your code +// source and binary incompatible with future versions of Qt. +// + +#ifndef QT_NO_SESSIONMANAGER + +#include + +QT_BEGIN_NAMESPACE + +class QCocoaSessionManager : public QPlatformSessionManager +{ +public: + QCocoaSessionManager(const QString &id, const QString &key); + virtual ~QCocoaSessionManager(); + + bool allowsInteraction() override; + void cancel() override; + void resetCancellation(); + bool wasCanceled() const; + + static QCocoaSessionManager *instance(); + +private: + bool m_canceled; + + Q_DISABLE_COPY(QCocoaSessionManager) +}; + +QT_END_NAMESPACE + +#endif // QT_NO_SESSIONMANAGER + +#endif // QCOCOASESSIONMANAGER_H diff --git a/tests/auto/other/sessionmanagement_macos/sessionmanagement_macos.pro b/tests/auto/other/sessionmanagement_macos/sessionmanagement_macos.pro new file mode 100644 index 00000000000..cef53bdf283 --- /dev/null +++ b/tests/auto/other/sessionmanagement_macos/sessionmanagement_macos.pro @@ -0,0 +1,10 @@ +CONFIG += testcase +TARGET = tst_sessionmanagement_macos + +OBJECTIVE_SOURCES += tst_sessionmanagement_macos.mm + +QT = testlib gui core +LIBS += -framework AppKit + +requires(mac) +DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/other/sessionmanagement_macos/tst_sessionmanagement_macos.mm b/tests/auto/other/sessionmanagement_macos/tst_sessionmanagement_macos.mm new file mode 100644 index 00000000000..934b15ca44b --- /dev/null +++ b/tests/auto/other/sessionmanagement_macos/tst_sessionmanagement_macos.mm @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2019 Samuel Gaist +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** 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 https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include +#include +#include +#include + +// Q_DECLARE_METATYPE(QSessionManager) + +class tst_SessionManagement_macOS : public QObject +{ + Q_OBJECT + +private slots: + void stopApplication(); +}; + +/* + Test that session handling code is properly called +*/ +void tst_SessionManagement_macOS::stopApplication() +{ + int argc = 0; + QGuiApplication app(argc, nullptr); + QSignalSpy spy(&app, &QGuiApplication::commitDataRequest); + QTimer::singleShot(1000, []() { + [NSApp terminate:nil]; + }); + app.exec(); + QCOMPARE(spy.count(), 1); +} + +QTEST_APPLESS_MAIN(tst_SessionManagement_macOS) +#include "tst_sessionmanagement_macos.moc" From 438702ac5f592573dbb9ed5fac84b241eb2d767a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Sun, 24 Nov 2019 22:06:27 +0100 Subject: [PATCH 40/45] macOS: Don't tweak NSApp presentationOptions on startup AppKit will initialize NSScreens nowadays, so we don't need to manually trigger it. Task-number: QTBUG-80193 Change-Id: Ic0251a1b978b9d4ff53f20e67902787cf529fa87 Reviewed-by: Timur Pocheptsov Reviewed-by: Volker Hilsheimer --- src/plugins/platforms/cocoa/qcocoaintegration.mm | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 9a2f19c2f2a..b7f15a2bf12 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -197,16 +197,6 @@ QCocoaIntegration::QCocoaIntegration(const QStringList ¶mList) [cocoaApplication setMenu:[qtMenuLoader menu]]; } - // The presentation options such as whether or not the dock and/or menu bar is - // hidden (automatically by the system) affects the main screen's available - // geometry. Since we're initializing the screens synchronously at application - // startup we need to ensure that the presentation options have been propagated - // to the screen before we read out its properties. Normally OS X does this in - // an asynchronous callback, but that's too late for us. We force the propagation - // by explicitly setting the presentation option to the magic 'default value', - // which will resolve to an actual value and result in screen invalidation. - cocoaApplication.presentationOptions = NSApplicationPresentationDefault; - QCocoaScreen::initializeScreens(); QMacInternalPasteboardMime::initializeMimeTypes(); From 9ac156c90b92a981f70929e081c64083b14e9a57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 2 Dec 2019 13:33:30 +0100 Subject: [PATCH 41/45] iOS: Guard against request for textInputView without focus window Change-Id: I7b8df07fffef1cc948f6720685234540a20ccc81 Fixes: QTBUG-79316 Reviewed-by: Timur Pocheptsov --- src/plugins/platforms/ios/qiostextresponder.mm | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index 396c769be80..1bc97445282 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -781,12 +781,16 @@ - (UIView *)textInputView { + auto *focusWindow = QGuiApplication::focusWindow(); + if (!focusWindow) + return nil; + // iOS expects rects we return from other UITextInput methods // to be relative to the view this method returns. // Since QInputMethod returns rects relative to the top level // QWindow, that is also the view we need to return. - Q_ASSERT(qApp->focusWindow()->handle()); - QPlatformWindow *topLevel = qApp->focusWindow()->handle(); + Q_ASSERT(focusWindow->handle()); + QPlatformWindow *topLevel = focusWindow->handle(); while (QPlatformWindow *p = topLevel->parent()) topLevel = p; return reinterpret_cast(topLevel->winId()); From ad1810e3213c036555320eccd8aaada87a609f7c Mon Sep 17 00:00:00 2001 From: Heikki Halmet Date: Tue, 26 Nov 2019 08:48:15 +0200 Subject: [PATCH 42/45] Blacklist tst_QNetworkInterface::localAddress(linklocal-ipv4) on Windows This will blacklist this test for ci. Currently blocking enabling tests for MSVC2019 Task-number: QTBUG-65667 Task-number: QTQAINFRA-2875 Change-Id: I7198490b1529ce2f4409bfa7399031dad7644a06 Reviewed-by: Edward Welbourne Reviewed-by: Heikki Halmet Reviewed-by: Timur Pocheptsov --- tests/auto/network/kernel/qnetworkinterface/BLACKLIST | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/auto/network/kernel/qnetworkinterface/BLACKLIST b/tests/auto/network/kernel/qnetworkinterface/BLACKLIST index 33bdf540b6d..e28cc38ee0a 100644 --- a/tests/auto/network/kernel/qnetworkinterface/BLACKLIST +++ b/tests/auto/network/kernel/qnetworkinterface/BLACKLIST @@ -1,4 +1,3 @@ # QTBUG-65667 [localAddress:linklocal-ipv4] -msvc-2015 ci -msvc-2017 ci +windows ci From fea316cbe762768ccda25f02d68c2efed25f5b23 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Fri, 8 Nov 2019 17:24:30 +0100 Subject: [PATCH 43/45] CMake: Remove conditions for CMake < 3.1 We don't support anything older than CMake 3.1 Change-Id: I5425a2fddfe5416a6a127a81da669fb37ac4d81c Reviewed-by: Liang Qi --- src/corelib/Qt5CoreMacros.cmake | 85 ++++++++++++++++----------------- 1 file changed, 40 insertions(+), 45 deletions(-) diff --git a/src/corelib/Qt5CoreMacros.cmake b/src/corelib/Qt5CoreMacros.cmake index 84c75401b1a..f2a0d184039 100644 --- a/src/corelib/Qt5CoreMacros.cmake +++ b/src/corelib/Qt5CoreMacros.cmake @@ -343,56 +343,51 @@ endfunction() set(_Qt5_COMPONENT_PATH "${CMAKE_CURRENT_LIST_DIR}/..") -if (NOT CMAKE_VERSION VERSION_LESS 2.8.9) - macro(qt5_use_modules _target _link_type) - if(NOT CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.11) - if(CMAKE_WARN_DEPRECATED) - set(messageType WARNING) - endif() - if(CMAKE_ERROR_DEPRECATED) - set(messageType FATAL_ERROR) - endif() - if(messageType) - message(${messageType} "The qt5_use_modules macro is obsolete. Use target_link_libraries with IMPORTED targets instead.") - endif() - endif() +macro(qt5_use_modules _target _link_type) + if(CMAKE_WARN_DEPRECATED) + set(messageType WARNING) + endif() + if(CMAKE_ERROR_DEPRECATED) + set(messageType FATAL_ERROR) + endif() + if(messageType) + message(${messageType} "The qt5_use_modules macro is obsolete. Use target_link_libraries with IMPORTED targets instead.") + endif() - if (NOT TARGET ${_target}) - message(FATAL_ERROR "The first argument to qt5_use_modules must be an existing target.") - endif() - if ("${_link_type}" STREQUAL "LINK_PUBLIC" OR "${_link_type}" STREQUAL "LINK_PRIVATE" ) - set(_qt5_modules ${ARGN}) - set(_qt5_link_type ${_link_type}) - else() - set(_qt5_modules ${_link_type} ${ARGN}) - endif() + if (NOT TARGET ${_target}) + message(FATAL_ERROR "The first argument to qt5_use_modules must be an existing target.") + endif() + if ("${_link_type}" STREQUAL "LINK_PUBLIC" OR "${_link_type}" STREQUAL "LINK_PRIVATE" ) + set(_qt5_modules ${ARGN}) + set(_qt5_link_type ${_link_type}) + else() + set(_qt5_modules ${_link_type} ${ARGN}) + endif() - if ("${_qt5_modules}" STREQUAL "") - message(FATAL_ERROR "qt5_use_modules requires at least one Qt module to use.") - endif() + if ("${_qt5_modules}" STREQUAL "") + message(FATAL_ERROR "qt5_use_modules requires at least one Qt module to use.") + endif() - foreach(_module ${_qt5_modules}) + foreach(_module ${_qt5_modules}) + if (NOT Qt5${_module}_FOUND) + find_package(Qt5${_module} PATHS "${_Qt5_COMPONENT_PATH}" NO_DEFAULT_PATH) if (NOT Qt5${_module}_FOUND) - find_package(Qt5${_module} PATHS "${_Qt5_COMPONENT_PATH}" NO_DEFAULT_PATH) - if (NOT Qt5${_module}_FOUND) - message(FATAL_ERROR "Cannot use \"${_module}\" module which has not yet been found.") - endif() + message(FATAL_ERROR "Cannot use \"${_module}\" module which has not yet been found.") endif() - target_link_libraries(${_target} ${_qt5_link_type} ${Qt5${_module}_LIBRARIES}) - set_property(TARGET ${_target} APPEND PROPERTY INCLUDE_DIRECTORIES ${Qt5${_module}_INCLUDE_DIRS}) - set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS ${Qt5${_module}_COMPILE_DEFINITIONS}) - set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_RELEASE QT_NO_DEBUG) - set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_RELWITHDEBINFO QT_NO_DEBUG) - set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_MINSIZEREL QT_NO_DEBUG) - if (Qt5_POSITION_INDEPENDENT_CODE - AND (CMAKE_VERSION VERSION_GREATER_EQUAL 2.8.12 - AND (NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU" - OR CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0))) - set_property(TARGET ${_target} PROPERTY POSITION_INDEPENDENT_CODE ${Qt5_POSITION_INDEPENDENT_CODE}) - endif() - endforeach() - endmacro() -endif() + endif() + target_link_libraries(${_target} ${_qt5_link_type} ${Qt5${_module}_LIBRARIES}) + set_property(TARGET ${_target} APPEND PROPERTY INCLUDE_DIRECTORIES ${Qt5${_module}_INCLUDE_DIRS}) + set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS ${Qt5${_module}_COMPILE_DEFINITIONS}) + set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_RELEASE QT_NO_DEBUG) + set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_RELWITHDEBINFO QT_NO_DEBUG) + set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_MINSIZEREL QT_NO_DEBUG) + if (Qt5_POSITION_INDEPENDENT_CODE + AND (NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU" + OR CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0)) + set_property(TARGET ${_target} PROPERTY POSITION_INDEPENDENT_CODE ${Qt5_POSITION_INDEPENDENT_CODE}) + endif() + endforeach() +endmacro() function(QT5_IMPORT_PLUGINS TARGET_NAME) set(_doing "") From b6632443d4d5b657f25a123eb52cec9e8d2eefea Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Tue, 26 Nov 2019 15:48:29 +0100 Subject: [PATCH 44/45] CMake: Use lower-case macro/function names CMake is case-insensitive for macro and function names. Still, it is "strongly recommended to stay with the case chosen in the function definition." So let's make the function and macro definition lower-case, like we also recommend in the documentation. Change-Id: I1f64b18716f034cb696d2e19a2b380aaadd6cd07 Reviewed-by: Alexandru Croitor --- src/corelib/Qt5CoreMacros.cmake | 26 +++++++++++++------------- src/dbus/Qt5DBusMacros.cmake | 8 ++++---- src/widgets/Qt5WidgetsMacros.cmake | 2 +- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/corelib/Qt5CoreMacros.cmake b/src/corelib/Qt5CoreMacros.cmake index f2a0d184039..e298cf7de76 100644 --- a/src/corelib/Qt5CoreMacros.cmake +++ b/src/corelib/Qt5CoreMacros.cmake @@ -39,7 +39,7 @@ include(CMakeParseArguments) # macro used to create the names of output files preserving relative dirs -macro(QT5_MAKE_OUTPUT_FILE infile prefix ext outfile ) +macro(qt5_make_output_file infile prefix ext outfile ) string(LENGTH ${CMAKE_CURRENT_BINARY_DIR} _binlength) string(LENGTH ${infile} _infileLength) set(_checkinfile ${CMAKE_CURRENT_SOURCE_DIR}) @@ -65,7 +65,7 @@ macro(QT5_MAKE_OUTPUT_FILE infile prefix ext outfile ) endmacro() -macro(QT5_GET_MOC_FLAGS _moc_flags) +macro(qt5_get_moc_flags _moc_flags) set(${_moc_flags}) get_directory_property(_inc_DIRS INCLUDE_DIRECTORIES) @@ -97,7 +97,7 @@ endmacro() # helper macro to set up a moc rule -function(QT5_CREATE_MOC_COMMAND infile outfile moc_flags moc_options moc_target moc_depends) +function(qt5_create_moc_command infile outfile moc_flags moc_options moc_target moc_depends) # Pass the parameters in a file. Set the working directory to # be that containing the parameters file and reference it by # just the file name. This is necessary because the moc tool on @@ -143,7 +143,7 @@ function(QT5_CREATE_MOC_COMMAND infile outfile moc_flags moc_options moc_target endfunction() -function(QT5_GENERATE_MOC infile outfile ) +function(qt5_generate_moc infile outfile ) # get include dirs and flags qt5_get_moc_flags(moc_flags) get_filename_component(abs_infile ${infile} ABSOLUTE) @@ -160,7 +160,7 @@ endfunction() # qt5_wrap_cpp(outfiles inputfile ... ) -function(QT5_WRAP_CPP outfiles ) +function(qt5_wrap_cpp outfiles ) # get include dirs qt5_get_moc_flags(moc_flags) @@ -189,7 +189,7 @@ endfunction() # _qt5_parse_qrc_file(infile _out_depends _rc_depends) # internal -function(_QT5_PARSE_QRC_FILE infile _out_depends _rc_depends) +function(_qt5_parse_qrc_file infile _out_depends _rc_depends) get_filename_component(rc_path ${infile} PATH) if(EXISTS "${infile}") @@ -222,7 +222,7 @@ endfunction() # qt5_add_binary_resources(target inputfiles ... ) -function(QT5_ADD_BINARY_RESOURCES target ) +function(qt5_add_binary_resources target ) set(options) set(oneValueArgs DESTINATION) @@ -241,7 +241,7 @@ function(QT5_ADD_BINARY_RESOURCES target ) foreach(it ${rcc_files}) get_filename_component(infile ${it} ABSOLUTE) - _QT5_PARSE_QRC_FILE(${infile} _out_depends _rc_depends) + _qt5_parse_qrc_file(${infile} _out_depends _rc_depends) set_source_files_properties(${infile} PROPERTIES SKIP_AUTORCC ON) set(infiles ${infiles} ${infile}) set(out_depends ${out_depends} ${_out_depends}) @@ -258,7 +258,7 @@ endfunction() # qt5_add_resources(outfiles inputfile ... ) -function(QT5_ADD_RESOURCES outfiles ) +function(qt5_add_resources outfiles ) set(options) set(oneValueArgs) @@ -278,7 +278,7 @@ function(QT5_ADD_RESOURCES outfiles ) get_filename_component(infile ${it} ABSOLUTE) set(outfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${outfilename}.cpp) - _QT5_PARSE_QRC_FILE(${infile} _out_depends _rc_depends) + _qt5_parse_qrc_file(${infile} _out_depends _rc_depends) set_source_files_properties(${infile} PROPERTIES SKIP_AUTORCC ON) add_custom_command(OUTPUT ${outfile} @@ -295,7 +295,7 @@ endfunction() # qt5_add_big_resources(outfiles inputfile ... ) -function(QT5_ADD_BIG_RESOURCES outfiles ) +function(qt5_add_big_resources outfiles ) if (CMAKE_VERSION VERSION_LESS 3.9) message(FATAL_ERROR, "qt5_add_big_resources requires CMake 3.9 or newer") endif() @@ -319,7 +319,7 @@ function(QT5_ADD_BIG_RESOURCES outfiles ) set(tmpoutfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${outfilename}tmp.cpp) set(outfile ${CMAKE_CURRENT_BINARY_DIR}/qrc_${outfilename}.o) - _QT5_PARSE_QRC_FILE(${infile} _out_depends _rc_depends) + _qt5_parse_qrc_file(${infile} _out_depends _rc_depends) set_source_files_properties(${infile} PROPERTIES SKIP_AUTORCC ON) add_custom_command(OUTPUT ${tmpoutfile} COMMAND ${Qt5Core_RCC_EXECUTABLE} ${rcc_options} --name ${outfilename} --pass 1 --output ${tmpoutfile} ${infile} @@ -389,7 +389,7 @@ macro(qt5_use_modules _target _link_type) endforeach() endmacro() -function(QT5_IMPORT_PLUGINS TARGET_NAME) +function(qt5_import_plugins TARGET_NAME) set(_doing "") foreach(_arg ${ARGN}) if(_arg STREQUAL "INCLUDE") diff --git a/src/dbus/Qt5DBusMacros.cmake b/src/dbus/Qt5DBusMacros.cmake index b381ab0934e..9b69e77dc75 100644 --- a/src/dbus/Qt5DBusMacros.cmake +++ b/src/dbus/Qt5DBusMacros.cmake @@ -34,7 +34,7 @@ include(MacroAddFileDependencies) include(CMakeParseArguments) -function(QT5_ADD_DBUS_INTERFACE _sources _interface _basename) +function(qt5_add_dbus_interface _sources _interface _basename) get_filename_component(_infile ${_interface} ABSOLUTE) set(_header "${CMAKE_CURRENT_BINARY_DIR}/${_basename}.h") set(_impl "${CMAKE_CURRENT_BINARY_DIR}/${_basename}.cpp") @@ -71,7 +71,7 @@ function(QT5_ADD_DBUS_INTERFACE _sources _interface _basename) endfunction() -function(QT5_ADD_DBUS_INTERFACES _sources) +function(qt5_add_dbus_interfaces _sources) foreach(_current_FILE ${ARGN}) get_filename_component(_infile ${_current_FILE} ABSOLUTE) get_filename_component(_basename ${_current_FILE} NAME) @@ -84,7 +84,7 @@ function(QT5_ADD_DBUS_INTERFACES _sources) endfunction() -function(QT5_GENERATE_DBUS_INTERFACE _header) # _customName OPTIONS -some -options ) +function(qt5_generate_dbus_interface _header) # _customName OPTIONS -some -options ) set(options) set(oneValueArgs) set(multiValueArgs OPTIONS) @@ -117,7 +117,7 @@ function(QT5_GENERATE_DBUS_INTERFACE _header) # _customName OPTIONS -some -optio endfunction() -function(QT5_ADD_DBUS_ADAPTOR _sources _xml_file _include _parentClass) # _optionalBasename _optionalClassName) +function(qt5_add_dbus_adaptor _sources _xml_file _include _parentClass) # _optionalBasename _optionalClassName) get_filename_component(_infile ${_xml_file} ABSOLUTE) set(_optionalBasename "${ARGV4}") diff --git a/src/widgets/Qt5WidgetsMacros.cmake b/src/widgets/Qt5WidgetsMacros.cmake index 737371a5ade..21e73d4f0cc 100644 --- a/src/widgets/Qt5WidgetsMacros.cmake +++ b/src/widgets/Qt5WidgetsMacros.cmake @@ -41,7 +41,7 @@ include(CMakeParseArguments) # qt5_wrap_ui(outfiles inputfile ... ) -function(QT5_WRAP_UI outfiles ) +function(qt5_wrap_ui outfiles ) set(options) set(oneValueArgs) set(multiValueArgs OPTIONS) From 2ed59f0d42d2817a5855be167f5e3ccf23563e39 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Tue, 3 Dec 2019 11:25:27 +0100 Subject: [PATCH 45/45] QMdiArea: on macOS using tabs, render document icons next to the text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is closer to what titles of documents look like in macOS apps, even though MDI is not a well-defined concept on this platform. To implement this, the QCommonStylePrivate::tabLayout method had to be made virtual, as it is called by the QCommonStyle class. It was already reimplemented in QMacStylePrivate, but didn't get called in all cases. Now that it is called as an override, adjust the icon placement to include the padding so that we get identical results to 5.13 for normal tab widgets. Change-Id: I7a63f6d76891146ca713259096a7737a86584d81 Fixes: QTBUG-63445 Reviewed-by: Tor Arne Vestbø --- src/plugins/styles/mac/qmacstyle_mac.mm | 18 +++++++++++++----- src/plugins/styles/mac/qmacstyle_mac_p_p.h | 2 +- src/widgets/styles/qcommonstyle_p.h | 2 +- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index 603c6e93f3a..3c97db44ad9 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -1388,14 +1388,22 @@ void QMacStylePrivate::tabLayout(const QStyleOptionTab *opt, const QWidget *widg // High-dpi icons do not need adjustment; make sure tabIconSize is not larger than iconSize tabIconSize = QSize(qMin(tabIconSize.width(), iconSize.width()), qMin(tabIconSize.height(), iconSize.height())); - *iconRect = QRect(tr.left(), tr.center().y() - tabIconSize.height() / 2, - tabIconSize.width(), tabIconSize.height()); + const int stylePadding = proxyStyle->pixelMetric(QStyle::PM_TabBarTabHSpace, opt, widget) / 2 - hpadding; + + if (opt->documentMode) { + // documents show the icon as part of the the text + const int textWidth = + opt->fontMetrics.boundingRect(tr, Qt::AlignCenter | Qt::TextShowMnemonic, opt->text).width(); + *iconRect = QRect(tr.center().x() - textWidth / 2 - stylePadding - tabIconSize.width(), + tr.center().y() - tabIconSize.height() / 2, + tabIconSize.width(), tabIconSize.height()); + } else { + *iconRect = QRect(tr.left() + stylePadding, tr.center().y() - tabIconSize.height() / 2, + tabIconSize.width(), tabIconSize.height()); + } if (!verticalTabs) *iconRect = proxyStyle->visualRect(opt->direction, opt->rect, *iconRect); - int stylePadding = proxyStyle->pixelMetric(QStyle::PM_TabBarTabHSpace, opt, widget) / 2; - stylePadding -= hpadding; - tr.setLeft(tr.left() + stylePadding + tabIconSize.width() + 4); tr.setRight(tr.right() - stylePadding - tabIconSize.width() - 4); } diff --git a/src/plugins/styles/mac/qmacstyle_mac_p_p.h b/src/plugins/styles/mac/qmacstyle_mac_p_p.h index d6af18f01f2..274936bd79a 100644 --- a/src/plugins/styles/mac/qmacstyle_mac_p_p.h +++ b/src/plugins/styles/mac/qmacstyle_mac_p_p.h @@ -284,7 +284,7 @@ public: CocoaControlType windowButtonCocoaControl(QStyle::SubControl sc) const; #if QT_CONFIG(tabbar) - void tabLayout(const QStyleOptionTab *opt, const QWidget *widget, QRect *textRect, QRect *iconRect) const; + void tabLayout(const QStyleOptionTab *opt, const QWidget *widget, QRect *textRect, QRect *iconRect) const override; static Direction tabDirection(QTabBar::Shape shape); static bool verticalTabs(QMacStylePrivate::Direction tabDirection); #endif diff --git a/src/widgets/styles/qcommonstyle_p.h b/src/widgets/styles/qcommonstyle_p.h index 4860dfe4c97..6223a26a541 100644 --- a/src/widgets/styles/qcommonstyle_p.h +++ b/src/widgets/styles/qcommonstyle_p.h @@ -122,7 +122,7 @@ public: mutable QIcon tabBarcloseButtonIcon; #if QT_CONFIG(tabbar) - void tabLayout(const QStyleOptionTab *opt, const QWidget *widget, QRect *textRect, QRect *pixmapRect) const; + virtual void tabLayout(const QStyleOptionTab *opt, const QWidget *widget, QRect *textRect, QRect *pixmapRect) const; #endif int animationFps;