diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2019-12-03 06:55:21 +0100 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2019-12-03 06:57:05 +0100 |
commit | e62d04b933a91c2bdd347aa97dc15ba210a04d2a (patch) | |
tree | 67c67af5f59d9b71522738da8a8d2d803e3ff44f | |
parent | f81f21151d30a37f955aa4af2398a96507626b15 (diff) | |
parent | 9ac156c90b92a981f70929e081c64083b14e9a57 (diff) |
Merge remote-tracking branch 'origin/5.14' into 5.15
Conflicts:
src/corelib/serialization/qcborvalue.cpp
Change-Id: I675a3029955c96e81a33ed9d98b72b55b6784b52
52 files changed, 762 insertions, 397 deletions
diff --git a/examples/widgets/doc/src/styles.qdoc b/examples/widgets/doc/src/styles.qdoc index 4fea8f3bfc..a3a02768c6 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 diff --git a/examples/widgets/widgets/styles/widgetgallery.cpp b/examples/widgets/widgets/styles/widgetgallery.cpp index fd8f0ec2d1..7e1616c6c0 100644 --- a/examples/widgets/widgets/styles/widgetgallery.cpp +++ b/examples/widgets/widgets/styles/widgetgallery.cpp @@ -65,6 +65,7 @@ #include <QRadioButton> #include <QScrollBar> #include <QSpinBox> +#include <QStyle> #include <QStyleFactory> #include <QTableWidget> #include <QTextEdit> @@ -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] diff --git a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in index 364c23e750..5077b8d8b4 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() diff --git a/mkspecs/features/qt_docs.prf b/mkspecs/features/qt_docs.prf index deb4ac2829..095bf15dac 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 diff --git a/mkspecs/features/testcase.prf b/mkspecs/features/testcase.prf index d4f08835f1..7e9903d663 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 { diff --git a/src/corelib/Qt5CoreMacros.cmake b/src/corelib/Qt5CoreMacros.cmake index 17cc19fc4e..84c75401b1 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}) diff --git a/src/corelib/codecs/qgb18030codec.cpp b/src/corelib/codecs/qgb18030codec.cpp index 4206eacb6f..ca15be1cea 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) { diff --git a/src/corelib/global/qfloat16.h b/src/corelib/global/qfloat16.h index 154b200475..f35eefd922 100644 --- a/src/corelib/global/qfloat16.h +++ b/src/corelib/global/qfloat16.h @@ -244,6 +244,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<float>(a) > static_cast<float>(b); } inline bool operator<(qfloat16 a, qfloat16 b) noexcept { return static_cast<float>(a) < static_cast<float>(b); } diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index 9896cf6e02..ef5f345e9c 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/io/qstandardpaths.cpp b/src/corelib/io/qstandardpaths.cpp index 6ebef3ee20..02adda3d6c 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; diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp index c2f670de06..61d61dd9ae 100644 --- a/src/corelib/serialization/qcborvalue.cpp +++ b/src/corelib/serialization/qcborvalue.cpp @@ -761,6 +761,85 @@ 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; + } + +#ifndef QT_BOOTSTRAPPED + 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; +#endif // QT_BOOTSTRAPPED + +#if QT_CONFIG(regularexpression) + case quint64(QCborKnownTags::RegularExpression): + if (e.type == QCborValue::String) { + // no normalization is necessary + return QCborValue::RegularExpression; + } + break; +#endif // QT_CONFIG(regularexpression) + + 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; +} + #if QT_CONFIG(cborstream) // in qcborstream.cpp extern void qt_cbor_stream_set_error(QCborStreamReaderPrivate *d, QCborError error); @@ -1390,77 +1469,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) { - d->data.clear(); - d->usedData = 0; - e.flags = Element::HasByteData | Element::StringIsAscii; - 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()); - 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; @@ -1724,21 +1736,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/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp index accaea988e..c833c18809 100644 --- a/src/corelib/time/qdatetime.cpp +++ b/src/corelib/time/qdatetime.cpp @@ -164,8 +164,8 @@ static ParsedRfcDateTime rfcDateImpl(const QString &s) { ParsedRfcDateTime result; - // Matches "Wdy, dd Mon yyyy HH:mm:ss ±hhmm" (Wdy, being optional) - 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))?")); + // Matches "[ddd,] dd MMM yyyy[ hh:mm[:ss]] [±hhmm]" - correct RFC 822, 2822, 5322 format + 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()); @@ -176,8 +176,8 @@ 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" - 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))?")); + // Matches "ddd MMM dd[ hh:mm:ss] yyyy [±hhmm]" - permissive RFC 850, 1036 (read only) + 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/src/corelib/time/qtimezoneprivate_android.cpp b/src/corelib/time/qtimezoneprivate_android.cpp index be4f374fdd..5cb8155dcc 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 <dparsons@emerall.com> ** Contact: https://www.qt.io/licensing/ ** @@ -53,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 @@ -76,32 +78,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<jstring>(jo_ianaId.object()) ); + const QString iana = QString::fromUtf8(ianaId); + androidTimeZone = QJNIObjectPrivate::callStaticObjectMethod( + "java.util.TimeZone", "getTimeZone", "(Ljava/lang/String;)Ljava/util/TimeZone;", + static_cast<jstring>(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 @@ -225,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<jstring>("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<jstring>("getID").toString().toUtf8(); } QList<QByteArray> QAndroidTimeZonePrivate::availableTimeZoneIds() const diff --git a/src/corelib/time/qtimezoneprivate_mac.mm b/src/corelib/time/qtimezoneprivate_mac.mm index d3c4fbe5da..4509e316f9 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 <jlayt@kde.org> ** 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/src/corelib/tools/qpoint.h b/src/corelib/tools/qpoint.h index fe952f95da..f0a91c4ff8 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 7aa2312f38..c6bfc1a50d 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 69c3510659..1439bfac59 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 cd0d746e55..f01fab679e 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 88d8bc199e..cbce94c199 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 1b49f3e7b9..d7ffb0bcc4 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 08cb423484..afcc71fa88 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/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp index 5d30891565..bb0dbdc9bd 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()); } diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp index 42186ace23..3e9eb3dd0a 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")) diff --git a/src/gui/painting/qtransform.h b/src/gui/painting/qtransform.h index b220770144..b2a634dd2a 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) { diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp index b0e9a149f1..b551980bb3 100644 --- a/src/gui/rhi/qrhigles2.cpp +++ b/src/gui/rhi/qrhigles2.cpp @@ -3142,8 +3142,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) { diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp index 25a85a5a17..49ca2326bc 100644 --- a/src/gui/rhi/qrhivulkan.cpp +++ b/src/gui/rhi/qrhivulkan.cpp @@ -48,7 +48,7 @@ #include <qmath.h> #include <QVulkanFunctions> -#include <QVulkanWindow> +#include <QtGui/qwindow.h> QT_BEGIN_NAMESPACE diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index 8cd0724d83..8fbbffcaca 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -92,6 +92,7 @@ #endif #include <algorithm> +#include <memory> #include <string.h> @@ -1957,6 +1958,7 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> & errors << QSslError(QSslError::UnspecifiedError); return errors; } + const std::unique_ptr<X509_STORE, decltype(&q_X509_STORE_free)> storeGuard(certStore, q_X509_STORE_free); if (s_loadRootCertsOnDemand) { setDefaultCaCertificates(defaultCaCertificates() + systemCaCertificates()); @@ -1997,7 +1999,6 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> & intermediates = (STACK_OF(X509) *) q_OPENSSL_sk_new_null(); if (!intermediates) { - q_X509_STORE_free(certStore); errors << QSslError(QSslError::UnspecifiedError); return errors; } @@ -2015,14 +2016,12 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> & 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<X509_STORE_CTX, decltype(&q_X509_STORE_CTX_free)> ctxGuard(storeContext, q_X509_STORE_CTX_free); if (!q_X509_STORE_CTX_init(storeContext, certStore, reinterpret_cast<X509 *>(certificateChain[0].handle()), intermediates)) { - q_X509_STORE_CTX_free(storeContext); - q_X509_STORE_free(certStore); errors << QSslError(QSslError::UnspecifiedError); return errors; } @@ -2031,8 +2030,7 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> & // 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 @@ -2054,8 +2052,6 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> & for (const auto &error : qAsConst(lastErrors)) errors << _q_OpenSSL_to_QSslError(error.code, certificateChain.value(error.depth)); - q_X509_STORE_free(certStore); - return errors; } diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index daa3dc94ea..894919a1c8 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -374,17 +374,6 @@ QFontEngine *QCoreTextFontDatabaseEngineFactory<QCoreTextFontEngine>::fontEngine QCFType<CTFontDescriptorRef> descriptor = QCFType<CTFontDescriptorRef>::constructFromGet( static_cast<CTFontDescriptorRef>(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<CFDictionaryRef> 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 diff --git a/src/platformsupport/platformsupport.pro b/src/platformsupport/platformsupport.pro index 6d4f1b93bd..877665ff06 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 } diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm index db4ec251ae..106c226adc 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; diff --git a/src/plugins/platforms/cocoa/qcocoadrag.mm b/src/plugins/platforms/cocoa/qcocoadrag.mm index 09433194a6..95808b8a11 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 diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 75d428c16f..61308d6bf9 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -200,16 +200,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(); diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 15329ca708..6e2d446898 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) diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index 396c769be8..1bc9744528 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<UIView *>(topLevel->winId()); diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp index 079c25f9eb..19d632dc10 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 f589fd6b10..e5a9f275ae 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: diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp index 034c1f4b4f..442369c2ec 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/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index e96e06d874..9099805cf8 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/src/widgets/styles/qstylehelper.cpp b/src/widgets/styles/qstylehelper.cpp index 4e61b2d1ec..9477ca86da 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 diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp index 92f43a309d..dc767cdae6 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 diff --git a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp index c6733205e5..47ad328d64 100644 --- a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp +++ b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp @@ -40,6 +40,7 @@ #include <QtCore/qcborvalue.h> #include <QtTest> +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<QCborValue>("extended"); - QTest::addColumn<QCborValue>("tagged"); + QTest::addColumn<QCborKnownTags>("tag"); + QTest::addColumn<QCborValue>("taggedValue"); + QTest::addColumn<QCborValue>("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)); @@ -1391,6 +1438,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=<a+b \xC2\xA9>&%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; diff --git a/tests/auto/corelib/time/qdate/tst_qdate.cpp b/tests/auto/corelib/time/qdate/tst_qdate.cpp index 73384c35f4..dd2cb3eea8 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); @@ -1153,38 +1159,56 @@ 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). + // 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); // 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 216ae1f79e..7f13fd0aa5 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() @@ -2310,8 +2311,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 +2331,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); @@ -2339,21 +2351,34 @@ 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). + // 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") @@ -2364,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 3403c5bf7f..d8de6e585d 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); @@ -636,36 +642,58 @@ 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). + // 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); // 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(); } diff --git a/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp b/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp index d0ef8023b9..332a00efb5 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(); @@ -317,6 +318,14 @@ void tst_QTimeZone::nullTest() QCOMPARE(data.daylightTimeOffset, std::numeric_limits<int>::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: diff --git a/tests/auto/network/ssl/qsslcertificate/BLACKLIST b/tests/auto/network/ssl/qsslcertificate/BLACKLIST deleted file mode 100644 index 9494ee2278..0000000000 --- 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 efc0c26076..14718ad373 100644 --- a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp +++ b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp @@ -33,6 +33,10 @@ #include <qsslsocket.h> #include <qsslcertificateextension.h> +#ifndef QT_NO_OPENSSL +#include <openssl/obj_mac.h> +#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() diff --git a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp index 23e2ec8516..8396fd4ec7 100644 --- a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp +++ b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp @@ -4922,13 +4922,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, {}, 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) diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 07f84595fd..6f8fd5dcbe 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -53,6 +53,7 @@ #include <qmainwindow.h> #include <qdockwidget.h> #include <qrandom.h> +#include <qstylehints.h> #include <qtoolbar.h> #include <qtoolbutton.h> #include <QtCore/qoperatingsystemversion.h> @@ -198,6 +199,7 @@ private slots: void hideWhenFocusWidgetIsChild(); void normalGeometry(); void setGeometry(); + void setGeometryHidden(); void windowOpacity(); void raise(); void lower(); @@ -2946,6 +2948,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; diff --git a/tests/manual/highdpi/dragwidget.cpp b/tests/manual/highdpi/dragwidget.cpp index 11bbc1d127..8ad3d3ca47 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<QWidget *>(child); + for (QObject *child : children()) { + if (child->isWidgetType()) { + auto widget = static_cast<QWidget *>(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 8b67b20410..06663fc74a 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 51a7026e85..0d4d3beef7 100644 --- a/tests/manual/highdpi/main.cpp +++ b/tests/manual/highdpi/main.cpp @@ -30,6 +30,7 @@ #include <QMenuBar> #include <QLabel> #include <QHBoxLayout> +#include <QFormLayout> #include <QApplication> #include <QAction> #include <QStyle> @@ -61,27 +62,38 @@ #include "dragwidget.h" +#include <utility> + static QTextStream &operator<<(QTextStream &str, const QRect &r) { str << r.width() << 'x' << r.height() << forcesign << r.x() << r.y() << noforcesign; 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: - 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<DemoContainerBase*> DemoContainerList ; - +using DemoContainerList = QVector<DemoContainerBase*>; template <class T> class DemoContainer : public DemoContainerBase @@ -93,16 +105,25 @@ 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; + 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) m_widget->setVisible(visible); } + private: QCommandLineOption m_option; }; @@ -134,12 +155,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 +173,10 @@ private slots: number.append(".0"); m_label->setText(number); } + signals: void valueChanged(int scaleFactor); + private: QSlider *m_slider; QLabel *m_label; @@ -172,31 +198,35 @@ 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"); + setWindowTitle(formatWindowTitle("Screen Scale Factors")); setObjectName("controller"); // make WindowScaleFactorSetter skip this window - QGridLayout *layout = new QGridLayout; - setLayout(layout); + 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; @@ -205,13 +235,13 @@ DemoController::DemoController(DemoContainerList *demos, QCommandLineParser *par }); // set up one scale control line per screen - QList<QScreen *> 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()) + 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 @@ -228,15 +258,18 @@ DemoController::DemoController(DemoContainerList *demos, QCommandLineParser *par }); } + 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()); + for (int i = 0; i < m_demos.size(); ++i) { + DemoContainerBase *demo = m_demos.at(i); + 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())) { @@ -244,19 +277,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<int,bool>::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 +302,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 +384,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 +442,7 @@ class Labels : public QWidget public: Labels(); +private: QPixmap pixmap1X; QPixmap pixmap2X; QPixmap pixmapLarge; @@ -419,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); @@ -454,18 +493,17 @@ 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"); qtIcon2x.addFile(":/qticon32.png"); setWindowIcon(qtIcon); - setWindowTitle("MainWindow"); + setWindowTitle(formatWindowTitle("MainWindow")); fileToolBar = addToolBar(tr("File")); // fileToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); @@ -484,7 +522,6 @@ MainWindow::MainWindow() addNewMenu("&Help", 2); } - QMenu *MainWindow::addNewMenu(const QString &title, int itemCount) { QMenu *menu = menuBar()->addMenu(title); @@ -516,7 +553,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 +575,7 @@ public: class Caching : public QWidget { public: - void paintEvent(QPaintEvent *) + void paintEvent(QPaintEvent *) override { QSize layoutSize(75, 75); @@ -576,16 +613,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 +634,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 +729,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 +821,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 +835,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<QPoint> linePoints; }; @@ -855,17 +895,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 +937,7 @@ public: } } - void mousePressEvent(QMouseEvent *e) + void mousePressEvent(QMouseEvent *e) override { if (moving) return; @@ -923,7 +961,7 @@ public: moveLabel->show(); } - void mouseReleaseEvent(QMouseEvent *) + void mouseReleaseEvent(QMouseEvent *) override { if (moveLabel) moveLabel->hide(); @@ -931,7 +969,7 @@ public: moving = false; } - void mouseMoveEvent(QMouseEvent *e) + void mouseMoveEvent(QMouseEvent *e) override { if (!moving) return; @@ -943,32 +981,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 +1016,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<QScreen*> 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 +1051,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 +1059,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 +1074,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 +1221,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); @@ -1187,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 @@ -1205,12 +1260,23 @@ 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); 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() @@ -1254,24 +1320,42 @@ QT_DPI_ADJUSTMENT_POLICY=AdjustDpi|DontAdjustDpi|AdjustUpOnly)"; m_textEdit->setPlainText(text); } - void paintEvent(QPaintEvent *ev) +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); - 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" @@ -1281,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<PixmapPainter>("pixmap", "Test pixmap painter"); @@ -1300,17 +1385,17 @@ int main(int argc, char **argv) demoList << new DemoContainer<ScreenDisplayer>("screens", "Test screen and window positioning"); demoList << new DemoContainer<PhysicalSizeTest>("physicalsize", "Test manual highdpi support using physicalDotsPerInch"); demoList << new DemoContainer<GraphicsViewCaching>("graphicsview", "Test QGraphicsView caching"); - demoList << new DemoContainer<MetricsTest>("metrics", "Show display metrics"); + demoList << new DemoContainer<MetricsTest>("metrics", "Show screen 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() - preAppOptionCount) <= 1) controller.show(); if (QApplication::topLevelWidgets().isEmpty()) |