diff --git a/dist/changes-5.12.0 b/dist/changes-5.12.0 index b5e664fc5a9..15b12b60ab3 100644 --- a/dist/changes-5.12.0 +++ b/dist/changes-5.12.0 @@ -48,6 +48,7 @@ information about a particular change. - The minimal required version of libxcb is now 1.9. Bundled xcb sources were updated to libxcb 1.9.1 built with xcb-proto 1.8. - [QTBUG-67654] Updated CLDR to version 33.1 + - [QTBUG-71144] Updated CLDR to version 34 - [QTBUG-66561][QTBUG-70008] double-conversion got updated to upstream version 3.1.1. - libjpeg-turbo was updated to version 2.0.0 diff --git a/mkspecs/features/mac/asset_catalogs.prf b/mkspecs/features/mac/asset_catalogs.prf index 123a0e0fcd3..58211c13a2f 100644 --- a/mkspecs/features/mac/asset_catalogs.prf +++ b/mkspecs/features/mac/asset_catalogs.prf @@ -110,7 +110,7 @@ # Backwards compatibility for (bundle_data, QMAKE_BUNDLE_DATA) { for (bundle_file, $${bundle_data}.files) { - !contains(bundle_file, .*\.xcassets$): next() + !contains(bundle_file, .*\\.xcassets$): next() warning("*.xcassets in QMAKE_BUNDLE_DATA is deprecated. Use QMAKE_ASSET_CATALOGS instead.") !exists($$absolute_path($$bundle_file/AppIcon.appiconset, $$_PRO_FILE_PWD_)): next() diff --git a/mkspecs/features/mac/default_post.prf b/mkspecs/features/mac/default_post.prf index c01e99fe8eb..3881b432ef6 100644 --- a/mkspecs/features/mac/default_post.prf +++ b/mkspecs/features/mac/default_post.prf @@ -21,7 +21,7 @@ contains(TEMPLATE, .*app) { !isEmpty($$list($$(QT_MAC_SDK_NO_VERSION_CHECK))): \ CONFIG += sdk_no_version_check - QMAKE_MAC_SDK_MAJOR_MINOR_VERSION = $$replace(QMAKE_MAC_SDK_VERSION, "(\d+)(\.\d+)(\.\d+)?", \1\2) + QMAKE_MAC_SDK_MAJOR_MINOR_VERSION = $$replace(QMAKE_MAC_SDK_VERSION, "(\\d+)(\\.\\d+)(\\.\\d+)?", \\1\\2) !sdk_no_version_check:!versionAtMost(QMAKE_MAC_SDK_MAJOR_MINOR_VERSION, $$QT_MAC_SDK_VERSION_MAX) { warning("Qt has only been tested with version $$QT_MAC_SDK_VERSION_MAX"\ diff --git a/mkspecs/features/moc.prf b/mkspecs/features/moc.prf index 5c7745e5bb6..d075183028b 100644 --- a/mkspecs/features/moc.prf +++ b/mkspecs/features/moc.prf @@ -38,7 +38,7 @@ if(gcc|intel_icl|msvc):!rim_qcc:!uikit:!no_moc_predefs:if(!macos|count(QMAKE_APP } else: error("Oops, I messed up") moc_predefs.output = $$MOC_DIR/moc_predefs.h moc_predefs.input = MOC_PREDEF_FILE - silent: moc_predefs.commands = @echo generating $$moc_predefs.output$$escape_expand(\n\t)@$$moc_predefs.commands + silent: moc_predefs.commands = @echo generating $$moc_predefs.output$$escape_expand(\\n\\t)@$$moc_predefs.commands QMAKE_EXTRA_COMPILERS += moc_predefs MOC_PREDEF_FILE = $$[QT_HOST_DATA/src]/mkspecs/features/data/dummy.cpp } diff --git a/mkspecs/features/qt_common.prf b/mkspecs/features/qt_common.prf index cc50f0dd1d8..669ac902a8f 100644 --- a/mkspecs/features/qt_common.prf +++ b/mkspecs/features/qt_common.prf @@ -89,6 +89,14 @@ clang { greaterThan(QT_GCC_MAJOR_VERSION, 5): QMAKE_CXXFLAGS_WARN_ON += -Wshift-overflow=2 -Wduplicated-cond # GCC 7 has a lot of false positives relating to this, so disable completely greaterThan(QT_GCC_MAJOR_VERSION, 6): QMAKE_CXXFLAGS_WARN_ON += -Wno-stringop-overflow + # GCC 9 has a lot of false positives relating to this, so disable completely + greaterThan(QT_GCC_MAJOR_VERSION, 8): QMAKE_CXXFLAGS_WARN_ON += -Wno-deprecated-copy + # GCC 9 introduced this + greaterThan(QT_GCC_MAJOR_VERSION, 8): QMAKE_CXXFLAGS_WARN_ON += -Wno-redundant-move + # GCC 9 introduced this + greaterThan(QT_GCC_MAJOR_VERSION, 8): QMAKE_CXXFLAGS_WARN_ON += -Wno-format-overflow + # GCC 9 introduced this + greaterThan(QT_GCC_MAJOR_VERSION, 8): QMAKE_CXXFLAGS_WARN_ON += -Wno-init-list-lifetime } warnings_are_errors:warning_clean { @@ -127,7 +135,14 @@ warnings_are_errors:warning_clean { # GCC 7 includes -Wimplicit-fallthrough in -Wextra, but Qt is not yet free of implicit fallthroughs. greaterThan(QT_GCC_MAJOR_VERSION, 6): QMAKE_CXXFLAGS_WARN_ON += -Wno-error=implicit-fallthrough - + # GCC 9 has a lot of false positives relating to this, so disable completely + greaterThan(QT_GCC_MAJOR_VERSION, 8): QMAKE_CXXFLAGS_WARN_ON += -Wno-deprecated-copy + # GCC 9 introduced this + greaterThan(QT_GCC_MAJOR_VERSION, 8): QMAKE_CXXFLAGS_WARN_ON += -Wno-redundant-move + # GCC 9 introduced this + greaterThan(QT_GCC_MAJOR_VERSION, 8): QMAKE_CXXFLAGS_WARN_ON += -Wno-format-overflow + # GCC 9 introduced this + greaterThan(QT_GCC_MAJOR_VERSION, 8): QMAKE_CXXFLAGS_WARN_ON += -Wno-init-list-lifetime # Work-around for bug https://code.google.com/p/android/issues/detail?id=58135 android: QMAKE_CXXFLAGS_WARN_ON += -Wno-error=literal-suffix } diff --git a/mkspecs/features/qt_configure.prf b/mkspecs/features/qt_configure.prf index d8f5af54045..e2e341770e2 100644 --- a/mkspecs/features/qt_configure.prf +++ b/mkspecs/features/qt_configure.prf @@ -378,6 +378,7 @@ defineReplace(qtConfFindInPathList) { defineReplace(qtConfFindInPath) { ensurePathEnv() + equals(QMAKE_HOST.os, Windows):!contains(1, .*\\.exe): 1 = $${1}.exe return($$qtConfFindInPathList($$1, $$2 $$QMAKE_PATH_ENV)) } @@ -1196,9 +1197,9 @@ defineTest(qtConfTest_files) { for(i, $${1}.files._KEYS_) { f = $$eval($${1}.files.$${i}) qtLog("Searching for file $${f}.") - contains(f, ".*\.h") { + contains(f, ".*\\.h") { file = $$qtConfFindInPathList($$f, $$EXTRA_INCLUDEPATH $$QMAKE_DEFAULT_INCDIRS) - } else: contains(f, ".*\.(lib|so|a)") { + } else: contains(f, ".*\\.(lib|so|a)") { file = $$qtConfFindInPathList($$f, $$EXTRA_LIBDIR $$QMAKE_DEFAULT_LIBDIRS) } else { # assume we're looking for an executable @@ -1399,7 +1400,7 @@ defineReplace(qtConfEvaluate) { 1 ~= s/$$escape_expand(\\n) */ /g expr = $${1} expr ~= s/&&/ && /g - expr ~= s/\|\|/ || /g + expr ~= s/\\|\\|/ || /g expr ~= s/!/ ! /g expr ~= s/\\(/ ( /g expr ~= s/\\)/ ) /g @@ -1422,7 +1423,7 @@ defineReplace(qtConfEvaluateSingleExpression) { } else: contains(e, "^'.*'$") { # quoted literals result = $$replace(e, "^'(.*)'$", "\\1") - } else: contains(e, "^tests\..*") { + } else: contains(e, "^tests\\..*") { !qt_conf_tests_allowed: \ error("Expression '$${1}' refers to a test, which is not allowed at this stage of configuring.") test = $$section(e, ".", 1, 1) @@ -1433,7 +1434,7 @@ defineReplace(qtConfEvaluateSingleExpression) { error("Unknown test object $${test} in expression '$${1}'.") qtRunSingleTest($$test) result = $$eval($${currentConfig}.tests.$${test}.$${var}) - } else: contains(e, "^libs\..*") { + } else: contains(e, "^libs\\..*") { !qt_conf_tests_allowed: \ error("Expression '$${1}' refers to a library, which is not allowed at this stage of configuring.") lib = $$section(e, ".", 1, 1) @@ -1446,7 +1447,7 @@ defineReplace(qtConfEvaluateSingleExpression) { !defined($${currentConfig}.libraries.$${lib}.$${var}, var): \ var = sources.$$eval($${currentConfig}.libraries.$${lib}.source).$$var result = $$eval($${currentConfig}.libraries.$${lib}.$${var}) - } else: contains(e, "^features\..*") { + } else: contains(e, "^features\\..*") { feature = $$section(e, ".", 1, 1) var = $$section(e, ".", 2, -1) isEmpty(var): \ @@ -1470,33 +1471,33 @@ defineReplace(qtConfEvaluateSingleExpression) { !qtConfCheckFeature($$feature): \ error("Expression '$$1' is accessing non-emitted feature $${feature}.") result = $$eval($${currentConfig}.features.$${feature}.$${var}) - } else: contains(e, "^config\..*") { - var = $$replace(e, "^config\.", "") + } else: contains(e, "^config\\..*") { + var = $$replace(e, "^config\\.", "") result = false contains(CONFIG, $$var): result = true - } else: contains(e, "^module\..*") { - var = $$replace(e, "^module\.", "") + } else: contains(e, "^module\\..*") { + var = $$replace(e, "^module\\.", "") result = false qtConfHaveModule($$var): result = true - } else: contains(e, "^arch\..*") { - var = $$replace(e, "^arch\.", "") + } else: contains(e, "^arch\\..*") { + var = $$replace(e, "^arch\\.", "") result = false isEmpty(QT_ARCH): \ qtConfCheckFeature(architecture) contains(QT_ARCH, $$var): result = true - } else: contains(e, "^subarch\..*") { - var = $$replace(e, "^subarch\.", "") + } else: contains(e, "^subarch\\..*") { + var = $$replace(e, "^subarch\\.", "") result = false isEmpty(QT_ARCH): \ qtConfCheckFeature(architecture) contains(QT_CPU_FEATURES.$$QT_ARCH, $$var): result = true - } else: contains(e, "^input\..*") { + } else: contains(e, "^input\\..*") { result = $$eval(config.$$e) - } else: contains(e, "^var\..*") { - var = $$replace(e, "^var\.", "") + } else: contains(e, "^var\\..*") { + var = $$replace(e, "^var\\.", "") result = $$eval($$var) - } else: contains(e, "^call\..*") { - call = $$replace(e, "^call\.", "qtConfFunc_") + } else: contains(e, "^call\\..*") { + call = $$replace(e, "^call\\.", "qtConfFunc_") !defined($$call, replace): \ error("Call $$call referenced in expression '$${1}' does not exist") eval(result = \$\$"$$call"()) diff --git a/mkspecs/features/qt_docs.prf b/mkspecs/features/qt_docs.prf index 3139c443c6f..3b74cd4dd5c 100644 --- a/mkspecs/features/qt_docs.prf +++ b/mkspecs/features/qt_docs.prf @@ -18,7 +18,7 @@ isEmpty(qtver.value): error("No version for documentation specified.") qtmver.name = QT_VER qtmver.value = $$replace(qtver.value, ^(\\d+\\.\\d+).*$, \\1) qtvertag.name = QT_VERSION_TAG -qtvertag.value = $$replace(qtver.value, \.,) +qtvertag.value = $$replace(qtver.value, \\.,) qtdocs.name = QT_INSTALL_DOCS qtdocs.value = $$[QT_INSTALL_DOCS/src] builddir.name = BUILDDIR diff --git a/mkspecs/features/qt_module_headers.prf b/mkspecs/features/qt_module_headers.prf index 70d3520e5c4..6b4b9143fa5 100644 --- a/mkspecs/features/qt_module_headers.prf +++ b/mkspecs/features/qt_module_headers.prf @@ -239,6 +239,14 @@ headersclean:!internal_module { gcc_ver = $${QT_GCC_MAJOR_VERSION}.$${QT_GCC_MINOR_VERSION} versionAtLeast(gcc_ver, 4.5): hcleanFLAGS += -Wdouble-promotion versionAtLeast(gcc_ver, 4.9): hcleanFLAGS += -Wfloat-conversion + # GCC 9 has a lot of false positives relating to this, so disable completely + greaterThan(QT_GCC_MAJOR_VERSION, 8): hcleanFLAGS += -Wno-deprecated-copy + # GCC 9 introduced this + greaterThan(QT_GCC_MAJOR_VERSION, 8): hcleanFLAGS += -Wno-redundant-move + # GCC 9 introduced this + greaterThan(QT_GCC_MAJOR_VERSION, 8): hcleanFLAGS += -Wno-format-overflow + # GCC 9 introduced this + greaterThan(QT_GCC_MAJOR_VERSION, 8): hcleanFLAGS += -Wno-init-list-lifetime c++11 { # only enabled for actual c++11 builds due to diff --git a/mkspecs/features/static_runtime.prf b/mkspecs/features/static_runtime.prf index 1af32361893..e20bfc42812 100644 --- a/mkspecs/features/static_runtime.prf +++ b/mkspecs/features/static_runtime.prf @@ -1,7 +1,7 @@ msvc { # -MD becomes -MT, -MDd becomes -MTd - QMAKE_CFLAGS ~= s,^-MD(d?)$,-MT\1,g - QMAKE_CXXFLAGS ~= s,^-MD(d?)$,-MT\1,g + QMAKE_CFLAGS ~= s,^-MD(d?)$,-MT\\1,g + QMAKE_CXXFLAGS ~= s,^-MD(d?)$,-MT\\1,g } else: mingw { QMAKE_LFLAGS += -static } diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc index 645422050b0..f99ebbec00c 100644 --- a/qmake/doc/src/qmake-manual.qdoc +++ b/qmake/doc/src/qmake-manual.qdoc @@ -3428,7 +3428,7 @@ \snippet code/doc_src_qmake-manual.pro 72 Like \l {qmake-cat}{$$cat()}, the \a mode argument takes \c blob, \c lines, - \c true, and \false as value. However, the legacy word splitting rules + \c true, and \c false as value. However, the legacy word splitting rules (i.e. empty or \c true, and \c false) differ subtly. If you pass \c stsvar, the command's exit status will be stored in that diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp index b38765070b2..5d47308d677 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp @@ -14,6 +14,10 @@ #include "libANGLE/histogram_macros.h" #include "third_party/trace_event/trace_event.h" +#ifndef QT_D3DCOMPILER_DLL +#define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL +#endif + #if ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED namespace { @@ -130,6 +134,27 @@ gl::Error HLSLCompiler::ensureInitialized() } #endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES + // Load the compiler DLL specified by the environment, or default to QT_D3DCOMPILER_DLL + const wchar_t *defaultCompiler = _wgetenv(L"QT_D3DCOMPILER_DLL"); + if (!defaultCompiler) + defaultCompiler = QT_D3DCOMPILER_DLL; + + const wchar_t *compilerDlls[] = { + defaultCompiler, + L"d3dcompiler_47.dll", + L"d3dcompiler_46.dll", + L"d3dcompiler_43.dll", + 0 + }; + + // Load the first available known compiler DLL + for (int i = 0; compilerDlls[i]; ++i) + { + mD3DCompilerModule = LoadLibrary(compilerDlls[i]); + if (mD3DCompilerModule) + break; + } + if (!mD3DCompilerModule) { // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with. diff --git a/src/angle/patches/0012-ANGLE-Dynamically-load-D3D-compiler-from-a-list.patch b/src/angle/patches/0012-ANGLE-Dynamically-load-D3D-compiler-from-a-list.patch new file mode 100644 index 00000000000..7009dec1ba9 --- /dev/null +++ b/src/angle/patches/0012-ANGLE-Dynamically-load-D3D-compiler-from-a-list.patch @@ -0,0 +1,59 @@ +From dff9676c60c51fa7af0749e1cb54305f112183e3 Mon Sep 17 00:00:00 2001 +From: Oliver Wolff +Date: Mon, 10 Dec 2018 08:33:14 +0100 +Subject: [PATCH] ANGLE: Dynamically load D3D compiler from a list + +If the default compiler cannot be found, load it from a list of DLL names, +including a non-versioned proxy DLL provided by Qt. On Desktop Windows, +the default compiler can also be specified by an environment variable, +QT_D3DCOMPILER_DLL. +--- + src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp | 25 +++++++++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp +index b38765070..5d47308d6 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp +@@ -14,6 +14,10 @@ + #include "libANGLE/histogram_macros.h" + #include "third_party/trace_event/trace_event.h" + ++#ifndef QT_D3DCOMPILER_DLL ++#define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL ++#endif ++ + #if ANGLE_APPEND_ASSEMBLY_TO_SHADER_DEBUG_INFO == ANGLE_ENABLED + namespace + { +@@ -130,6 +134,27 @@ gl::Error HLSLCompiler::ensureInitialized() + } + #endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES + ++ // Load the compiler DLL specified by the environment, or default to QT_D3DCOMPILER_DLL ++ const wchar_t *defaultCompiler = _wgetenv(L"QT_D3DCOMPILER_DLL"); ++ if (!defaultCompiler) ++ defaultCompiler = QT_D3DCOMPILER_DLL; ++ ++ const wchar_t *compilerDlls[] = { ++ defaultCompiler, ++ L"d3dcompiler_47.dll", ++ L"d3dcompiler_46.dll", ++ L"d3dcompiler_43.dll", ++ 0 ++ }; ++ ++ // Load the first available known compiler DLL ++ for (int i = 0; compilerDlls[i]; ++i) ++ { ++ mD3DCompilerModule = LoadLibrary(compilerDlls[i]); ++ if (mD3DCompilerModule) ++ break; ++ } ++ + if (!mD3DCompilerModule) + { + // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with. +-- +2.15.0.windows.1 + diff --git a/src/corelib/codecs/qwindowscodec.cpp b/src/corelib/codecs/qwindowscodec.cpp index 813d3c81535..6b703f75178 100644 --- a/src/corelib/codecs/qwindowscodec.cpp +++ b/src/corelib/codecs/qwindowscodec.cpp @@ -179,7 +179,7 @@ QString QWindowsLocalCodec::convertToUnicodeCharByChar(const char *chars, int le #else QString s; size_t size = mbstowcs(NULL, mb, length); - if (size < 0) { + if (size == size_t(-1)) { Q_ASSERT("Error in CE TextCodec"); return QString(); } diff --git a/src/corelib/tools/qcollator.cpp b/src/corelib/tools/qcollator.cpp index 1cf223aae60..4315d35a52f 100644 --- a/src/corelib/tools/qcollator.cpp +++ b/src/corelib/tools/qcollator.cpp @@ -79,7 +79,6 @@ QT_BEGIN_NAMESPACE QCollator::QCollator(const QLocale &locale) : d(new QCollatorPrivate(locale)) { - d->init(); } /*! @@ -323,6 +322,8 @@ bool QCollator::ignorePunctuation() const methods directly. But if the string is compared repeatedly (e.g. when sorting a whole list of strings), it's usually faster to create the sort keys for each string and then sort using the keys. + + \note Not supported with the C (a.k.a. POSIX) locale on Darwin. */ /*! diff --git a/src/corelib/tools/qcollator_icu.cpp b/src/corelib/tools/qcollator_icu.cpp index fd621983d34..ab45b9a1a13 100644 --- a/src/corelib/tools/qcollator_icu.cpp +++ b/src/corelib/tools/qcollator_icu.cpp @@ -55,6 +55,8 @@ QT_BEGIN_NAMESPACE void QCollatorPrivate::init() { cleanup(); + if (isC()) + return; UErrorCode status = U_ZERO_ERROR; QByteArray name = QLocalePrivate::get(locale)->bcp47Name('_'); @@ -140,6 +142,8 @@ QCollatorSortKey QCollator::sortKey(const QString &string) const { if (d->dirty) d->init(); + if (d->isC()) + return QCollatorSortKey(new QCollatorSortKeyPrivate(string.toUtf8())); if (d->collator) { QByteArray result(16 + string.size() + (string.size() >> 2), Qt::Uninitialized); diff --git a/src/corelib/tools/qcollator_macx.cpp b/src/corelib/tools/qcollator_macx.cpp index 9aa59a81dc8..42e67e0c125 100644 --- a/src/corelib/tools/qcollator_macx.cpp +++ b/src/corelib/tools/qcollator_macx.cpp @@ -55,6 +55,15 @@ QT_BEGIN_NAMESPACE void QCollatorPrivate::init() { cleanup(); + /* + LocaleRefFromLocaleString() will accept "POSIX" as the locale name, but + the locale it produces (named "pos") doesn't implement the [A-Z] < [a-z] + behavior we expect of the C locale. We can use QStringView to get round + that for collation, but this leaves no way to do a sort key. + */ + if (isC()) + return; + LocaleRef localeRef; int rc = LocaleRefFromLocaleString(QLocalePrivate::get(locale)->bcp47Name().constData(), &localeRef); if (rc != 0) @@ -92,6 +101,8 @@ int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) con { if (d->dirty) d->init(); + if (!d->collator) + return QStringView(s1, len1).compare(QStringView(s2, len2), caseSensitivity()); SInt32 result; Boolean equivalent; @@ -104,6 +115,7 @@ int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) con return 0; return result < 0 ? -1 : 1; } + int QCollator::compare(const QString &str1, const QString &str2) const { return compare(str1.constData(), str1.size(), str2.constData(), str2.size()); @@ -118,6 +130,11 @@ QCollatorSortKey QCollator::sortKey(const QString &string) const { if (d->dirty) d->init(); + if (!d->collator) { + // What should (or even *can*) we do here ? (See init()'s comment.) + qWarning("QCollator doesn't support sort keys for the C locale on Darwin"); + return QCollatorSortKey(nullptr); + } //Documentation recommends having it 5 times as big as the input QVector ret(string.size() * 5); @@ -136,6 +153,9 @@ QCollatorSortKey QCollator::sortKey(const QString &string) const int QCollatorSortKey::compare(const QCollatorSortKey &key) const { + if (!d.data()) + return 0; + SInt32 order; UCCompareCollationKeys(d->m_key.data(), d->m_key.size(), key.d->m_key.data(), key.d->m_key.size(), diff --git a/src/corelib/tools/qcollator_p.h b/src/corelib/tools/qcollator_p.h index 321e846884e..fc2d434a8da 100644 --- a/src/corelib/tools/qcollator_p.h +++ b/src/corelib/tools/qcollator_p.h @@ -110,6 +110,7 @@ class QCollatorPrivate QCollatorPrivate(const QLocale &locale) : locale(locale) {} ~QCollatorPrivate() { cleanup(); } + bool isC() { return locale.language() == QLocale::C; } void clear() { cleanup(); diff --git a/src/corelib/tools/qcollator_posix.cpp b/src/corelib/tools/qcollator_posix.cpp index 42413a4a82b..81f97a02e1c 100644 --- a/src/corelib/tools/qcollator_posix.cpp +++ b/src/corelib/tools/qcollator_posix.cpp @@ -48,10 +48,12 @@ QT_BEGIN_NAMESPACE void QCollatorPrivate::init() { - if (locale != QLocale()) - qWarning("Only default locale supported with the posix collation implementation"); - if (caseSensitivity != Qt::CaseSensitive) - qWarning("Case insensitive sorting unsupported in the posix collation implementation"); + if (!isC()) { + if (locale != QLocale()) + qWarning("Only C and default locale supported with the posix collation implementation"); + if (caseSensitivity != Qt::CaseSensitive) + qWarning("Case insensitive sorting unsupported in the posix collation implementation"); + } if (numericMode) qWarning("Numeric mode unsupported in the posix collation implementation"); if (ignorePunctuation) @@ -73,14 +75,16 @@ static void stringToWCharArray(QVarLengthArray &ret, const QString &str int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) const { - QVarLengthArray array1, array2; - stringToWCharArray(array1, QString(s1, len1)); - stringToWCharArray(array2, QString(s2, len2)); - return std::wcscoll(array1.constData(), array2.constData()); + return compare(QString::fromRawData(s1, len1), QString::fromRawData(s2, len2)); } int QCollator::compare(const QString &s1, const QString &s2) const { + if (d->isC()) + return s1.compare(s2, caseSensitivity()); + if (d->dirty) + d->init(); + QVarLengthArray array1, array2; stringToWCharArray(array1, s1); stringToWCharArray(array2, s2); @@ -89,10 +93,7 @@ int QCollator::compare(const QString &s1, const QString &s2) const int QCollator::compare(const QStringRef &s1, const QStringRef &s2) const { - if (d->dirty) - d->init(); - - return compare(s1.constData(), s1.size(), s2.constData(), s2.size()); + return compare(s1.toString(), s2.toString()); } QCollatorSortKey QCollator::sortKey(const QString &string) const @@ -102,14 +103,18 @@ QCollatorSortKey QCollator::sortKey(const QString &string) const QVarLengthArray original; stringToWCharArray(original, string); - QVector result(string.size()); - size_t size = std::wcsxfrm(result.data(), original.constData(), string.size()); - if (size > uint(result.size())) { + QVector result(original.size()); + if (d->isC()) { + std::copy(original.cbegin(), original.cend(), result.begin()); + } else { + size_t size = std::wcsxfrm(result.data(), original.constData(), string.size()); + if (size > uint(result.size())) { + result.resize(size+1); + size = std::wcsxfrm(result.data(), original.constData(), string.size()); + } result.resize(size+1); - size = std::wcsxfrm(result.data(), original.constData(), string.size()); + result[size] = 0; } - result.resize(size+1); - result[size] = 0; return QCollatorSortKey(new QCollatorSortKeyPrivate(std::move(result))); } diff --git a/src/corelib/tools/qcollator_win.cpp b/src/corelib/tools/qcollator_win.cpp index 5a838c1b500..35142bb8b86 100644 --- a/src/corelib/tools/qcollator_win.cpp +++ b/src/corelib/tools/qcollator_win.cpp @@ -60,6 +60,8 @@ extern LCID qt_inIsoNametoLCID(const char *name); void QCollatorPrivate::init() { collator = 0; + if (isC()) + return; #ifndef USE_COMPARESTRINGEX localeID = qt_inIsoNametoLCID(QLocalePrivate::get(locale)->bcp47Name().constData()); @@ -86,6 +88,9 @@ void QCollatorPrivate::cleanup() int QCollator::compare(const QChar *s1, int len1, const QChar *s2, int len2) const { + if (d->isC()) + return QString::compare_helper(s1, len1, s2, len2, d->caseSensitivity); + if (d->dirty) d->init(); @@ -119,6 +124,8 @@ QCollatorSortKey QCollator::sortKey(const QString &string) const { if (d->dirty) d->init(); + if (d->isC()) + return QCollatorSortKey(new QCollatorSortKeyPrivate(string)); #ifndef USE_COMPARESTRINGEX int size = LCMapStringW(d->localeID, LCMAP_SORTKEY | d->collator, diff --git a/src/gui/doc/snippets/code/src_gui_vulkan_qvulkaninstance.cpp b/src/gui/doc/snippets/code/src_gui_vulkan_qvulkaninstance.cpp index 50afe7c0ff2..c4dd9fea18b 100644 --- a/src/gui/doc/snippets/code/src_gui_vulkan_qvulkaninstance.cpp +++ b/src/gui/doc/snippets/code/src_gui_vulkan_qvulkaninstance.cpp @@ -102,7 +102,7 @@ } bool event(QEvent *e) { - if (e->type == QEvent::UpdateRequest) + if (e->type() == QEvent::UpdateRequest) render(); return QWindow::event(e); } diff --git a/src/gui/image/qpixmap_win.cpp b/src/gui/image/qpixmap_win.cpp index 68d204d76eb..3a2db74098b 100644 --- a/src/gui/image/qpixmap_win.cpp +++ b/src/gui/image/qpixmap_win.cpp @@ -422,8 +422,11 @@ static QImage imageFromWinHBITMAP_GetDiBits(HBITMAP bitmap, bool forceQuads, int if (info.bmiHeader.biHeight > 0) // Force top-down info.bmiHeader.biHeight = -info.bmiHeader.biHeight; info.bmiHeader.biCompression = BI_RGB; // Extract using no compression (can be BI_BITFIELD) - if (forceQuads) + size_t allocSize = info.bmiHeader.biSizeImage; + if (forceQuads) { info.bmiHeader.biBitCount = 32; + allocSize = info.bmiHeader.biWidth * qAbs(info.bmiHeader.biHeight) * 4; + } const QImage::Format imageFormat = imageFromWinHBITMAP_Format(info.bmiHeader, hbitmapFormat); if (imageFormat == QImage::Format_Invalid) { @@ -431,7 +434,7 @@ static QImage imageFromWinHBITMAP_GetDiBits(HBITMAP bitmap, bool forceQuads, int return QImage(); } - QScopedPointer data(new uchar[info.bmiHeader.biSizeImage]); + QScopedArrayPointer data(new uchar[allocSize]); if (!GetDIBits(displayDc, bitmap, 0, qAbs(info.bmiHeader.biHeight), data.data(), &info, DIB_RGB_COLORS)) { qErrnoWarning("%s: GetDIBits() failed to get data.", __FUNCTION__); return QImage(); diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 729029e233e..650fffbd760 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -997,6 +997,10 @@ void QRasterPaintEnginePrivate::drawImage(const QPointF &pt, { if (alpha == 0 || !clip.isValid()) return; + if (pt.x() > qreal(clip.right()) || pt.y() > qreal(clip.bottom())) + return; + if ((pt.x() + img.width()) < qreal(clip.left()) || (pt.y() + img.height()) < qreal(clip.top())) + return; Q_ASSERT(img.depth() >= 8); @@ -1063,6 +1067,10 @@ void QRasterPaintEnginePrivate::blitImage(const QPointF &pt, { if (!clip.isValid()) return; + if (pt.x() > qreal(clip.right()) || pt.y() > qreal(clip.bottom())) + return; + if ((pt.x() + img.width()) < qreal(clip.left()) || (pt.y() + img.height()) < qreal(clip.top())) + return; Q_ASSERT(img.depth() >= 8); diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration.cpp b/src/plugins/platforms/offscreen/qoffscreenintegration.cpp index 01cd2545014..9815be16a3f 100644 --- a/src/plugins/platforms/offscreen/qoffscreenintegration.cpp +++ b/src/plugins/platforms/offscreen/qoffscreenintegration.cpp @@ -45,6 +45,7 @@ #include #if defined(Q_OS_MAC) #include +#include #else #include #endif @@ -67,6 +68,8 @@ QT_BEGIN_NAMESPACE +class QCoreTextFontEngine; + template class QOffscreenEventDispatcher : public BaseEventDispatcher { @@ -101,7 +104,7 @@ QOffscreenIntegration::QOffscreenIntegration() { #if defined(Q_OS_UNIX) #if defined(Q_OS_MAC) - m_fontDatabase.reset(new QPlatformFontDatabase()); + m_fontDatabase.reset(new QCoreTextFontDatabaseEngineFactory); #else m_fontDatabase.reset(new QGenericUnixFontDatabase()); #endif diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index 69496dbd299..eb3479b3e0e 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -2866,7 +2866,11 @@ void QFileDialogPrivate::init(const QUrl &directory, const QString &nameFilter, q->setFileMode(QFileDialog::AnyFile); if (!nameFilter.isEmpty()) q->setNameFilter(nameFilter); + // QTBUG-70798, prevent the default blocking the restore logic. + const bool dontStoreDir = !directory.isValid() && !lastVisitedDir()->isValid(); q->setDirectoryUrl(workingDirectory(directory)); + if (dontStoreDir) + lastVisitedDir()->clear(); if (directory.isLocalFile()) q->selectFile(initialSelection(directory)); else diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 40b0af359ca..595bdf621d5 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -1064,8 +1064,10 @@ QStyle *QApplication::style() if (!QApplicationPrivate::styleOverride.isEmpty()) { const QString style = QApplicationPrivate::styleOverride.toLower(); app_style = QStyleFactory::create(style); - if (!app_style) - qWarning("QApplication: invalid style override passed, ignoring it."); + if (Q_UNLIKELY(!app_style)) { + qWarning("QApplication: invalid style override passed, ignoring it.\n" + " Available styles: %s", qPrintable(QStyleFactory::keys().join(QLatin1String(", ")))); + } } if (!app_style) app_style = QStyleFactory::create(QApplicationPrivate::desktopStyleKey()); diff --git a/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp b/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp index 2d65d3433fe..72f88a235de 100644 --- a/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp +++ b/tests/auto/corelib/tools/qcollator/tst_qcollator.cpp @@ -93,7 +93,7 @@ void tst_QCollator::compare_data() QTest::addColumn("caseInsensitiveResult"); QTest::addColumn("numericMode"); QTest::addColumn("ignorePunctuation"); - QTest::addColumn("punctuationResult"); + QTest::addColumn("punctuationResult"); // Test ignores punctuation *and case* /* It's hard to test English, because it's treated differently @@ -169,8 +169,12 @@ void tst_QCollator::compare_data() QTest::newRow("french6") << QString("fr_FR") << QString("Test 9") << QString("Test_19") << -1 << -1 << true << true << -1; QTest::newRow("french7") << QString("fr_FR") << QString("test_19") << QString("test 19") << 1 << 1 << true << false << 1; QTest::newRow("french8") << QString("fr_FR") << QString("test.19") << QString("test,19") << 1 << 1 << true << true << 0; -} + // C locale: case sensitive [A-Z] < [a-z] but case insensitive [Aa] < [Bb] <...< [Zz] + const QString C = QStringLiteral("C"); + QTest::newRow("C:ABBA:AaaA") << C << QStringLiteral("ABBA") << QStringLiteral("AaaA") << -1 << 1 << false << false << 1; + QTest::newRow("C:AZa:aAZ") << C << QStringLiteral("AZa") << QStringLiteral("aAZ") << -1 << 1 << false << false << 1; +} void tst_QCollator::compare() { @@ -184,6 +188,10 @@ void tst_QCollator::compare() QFETCH(int, punctuationResult); QCollator collator(locale); + // Need to canonicalize sign to -1, 0 or 1, as .compare() can produce any -ve for <, any +ve for >. + auto asSign = [](int compared) { + return compared < 0 ? -1 : compared > 0 ? 1 : 0; + }; #if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) if (collator.locale() != QLocale()) @@ -193,12 +201,12 @@ void tst_QCollator::compare() if (numericMode) collator.setNumericMode(true); - QCOMPARE(collator.compare(s1, s2), result); + QCOMPARE(asSign(collator.compare(s1, s2)), result); collator.setCaseSensitivity(Qt::CaseInsensitive); - QCOMPARE(collator.compare(s1, s2), caseInsensitiveResult); + QCOMPARE(asSign(collator.compare(s1, s2)), caseInsensitiveResult); #if !QT_CONFIG(iconv) collator.setIgnorePunctuation(ignorePunctuation); - QCOMPARE(collator.compare(s1, s2), punctuationResult); + QCOMPARE(asSign(collator.compare(s1, s2)), punctuationResult); #endif } diff --git a/tests/auto/gui/image/qimage/tst_qimage.cpp b/tests/auto/gui/image/qimage/tst_qimage.cpp index 5ffd75f931a..eded206d374 100644 --- a/tests/auto/gui/image/qimage/tst_qimage.cpp +++ b/tests/auto/gui/image/qimage/tst_qimage.cpp @@ -233,6 +233,7 @@ private slots: #if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) void toWinHBITMAP_data(); void toWinHBITMAP(); + void fromMonoHBITMAP(); #endif // Q_OS_WIN && !Q_OS_WINRT private: @@ -3635,6 +3636,19 @@ void tst_QImage::toWinHBITMAP() DeleteDC(bitmapDc); ReleaseDC(0, displayDc); } + +void tst_QImage::fromMonoHBITMAP() // QTBUG-72343, corruption for mono bitmaps +{ + enum : int { width = 32, height = 32, size = width * height / 8 }; // 32x32 mono bitmap + char bitmapData[size]; + memset(bitmapData, 0, size); + const HBITMAP hbitmap = CreateBitmap(width, height, /* planes */ 1, /* bitcount */ 1, bitmapData); + const QImage image = qt_imageFromWinHBITMAP(hbitmap); + QCOMPARE(image.size(), QSize(width, height)); + QCOMPARE(image.scanLine(0)[0], 0u); + DeleteObject(hbitmap); +} + #endif // Q_OS_WIN && !Q_OS_WINRT QTEST_GUILESS_MAIN(tst_QImage) diff --git a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp index 9bf9e99bf9b..bc0baed15c5 100644 --- a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp +++ b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp @@ -299,6 +299,8 @@ private slots: void fillPolygon(); + void drawImageAtPointF(); + private: void fillData(); void setPenColor(QPainter& p); @@ -5292,6 +5294,20 @@ void tst_QPainter::fillPolygon() } } +void tst_QPainter::drawImageAtPointF() +{ + // Just test we do not crash + QImage image1(10, 10, QImage::Format_RGB32); + QImage image2(200, 200, QImage::Format_RGB32); + + QPainter paint(&image2); + paint.setClipRect(97, 46, 14, 14); + paint.setCompositionMode(QPainter::CompositionMode_Source); + paint.drawImage(QPointF(96, std::numeric_limits::max()), image1); + paint.drawImage(QPointF(std::numeric_limits::min(), 48), image1); + paint.end(); +} + QTEST_MAIN(tst_QPainter) #include "tst_qpainter.moc" diff --git a/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp b/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp index 049468fd7c6..3b31a74adff 100644 --- a/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp +++ b/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp @@ -210,9 +210,9 @@ void tst_QMessageBox::button() { QMessageBox msgBox; msgBox.addButton("retry", QMessageBox::DestructiveRole); - QVERIFY(msgBox.button(QMessageBox::Ok) == 0); // not added yet + QVERIFY(msgBox.button(QMessageBox::Ok) == nullptr); // not added yet QPushButton *b1 = msgBox.addButton(QMessageBox::Ok); - QCOMPARE(msgBox.button(QMessageBox::Ok), (QAbstractButton *)b1); // just added + QCOMPARE(msgBox.button(QMessageBox::Ok), static_cast(b1)); // just added QCOMPARE(msgBox.standardButton(b1), QMessageBox::Ok); msgBox.addButton(QMessageBox::Cancel); QCOMPARE(msgBox.standardButtons(), QMessageBox::Ok | QMessageBox::Cancel); @@ -220,12 +220,12 @@ void tst_QMessageBox::button() // remove the cancel, should not exist anymore msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); QVERIFY(!msgBox.button(QMessageBox::Cancel)); - QVERIFY(msgBox.button(QMessageBox::Yes) != 0); + QVERIFY(msgBox.button(QMessageBox::Yes) != nullptr); // should not crash QPushButton *b4 = new QPushButton; msgBox.addButton(b4, QMessageBox::DestructiveRole); - msgBox.addButton(0, QMessageBox::ActionRole); + msgBox.addButton(nullptr, QMessageBox::ActionRole); } void tst_QMessageBox::defaultButton() @@ -237,7 +237,7 @@ void tst_QMessageBox::defaultButton() QVERIFY(!msgBox.defaultButton()); QPushButton pushButton; msgBox.setDefaultButton(&pushButton); - QVERIFY(msgBox.defaultButton() == 0); // we have not added it yet + QVERIFY(msgBox.defaultButton() == nullptr); // we have not added it yet QPushButton *retryButton = msgBox.addButton(QMessageBox::Retry); msgBox.setDefaultButton(retryButton); QCOMPARE(msgBox.defaultButton(), retryButton); @@ -248,11 +248,11 @@ void tst_QMessageBox::defaultButton() closeHelper.start(Qt::Key_Enter, &msgBox); msgBox.exec(); - QCOMPARE(msgBox.clickedButton(), (QAbstractButton *)retryButton); + QCOMPARE(msgBox.clickedButton(), static_cast(retryButton)); QAbstractButton *okButton = msgBox.button(QMessageBox::Ok); msgBox.setDefaultButton(QMessageBox::Ok); - QCOMPARE(msgBox.defaultButton(), (QPushButton *)okButton); + QCOMPARE(msgBox.defaultButton(), static_cast(okButton)); closeHelper.start(Qt::Key_Enter, &msgBox); msgBox.exec(); QCOMPARE(msgBox.clickedButton(), okButton); @@ -260,7 +260,7 @@ void tst_QMessageBox::defaultButton() QCOMPARE(msgBox.defaultButton(), okButton); msgBox.removeButton(okButton); delete okButton; - okButton = 0; + okButton = nullptr; QVERIFY(!msgBox.defaultButton()); msgBox.setDefaultButton(QMessageBox::Ok); QVERIFY(!msgBox.defaultButton()); @@ -287,7 +287,7 @@ void tst_QMessageBox::escapeButton() QVERIFY(msgBox.clickedButton() == msgBox.button(QMessageBox::Cancel)); // auto detected (cancel) msgBox.setEscapeButton(retryButton); - QCOMPARE(msgBox.escapeButton(), (QAbstractButton *)retryButton); + QCOMPARE(msgBox.escapeButton(), static_cast(retryButton)); // with escape closeHelper.start(Qt::Key_Escape, &msgBox); @@ -297,7 +297,7 @@ void tst_QMessageBox::escapeButton() // with close closeHelper.start(ExecCloseHelper::CloseWindow, &msgBox); msgBox.exec(); - QCOMPARE(msgBox.clickedButton(), (QAbstractButton *)retryButton); + QCOMPARE(msgBox.clickedButton(), static_cast(retryButton)); QAbstractButton *okButton = msgBox.button(QMessageBox::Ok); msgBox.setEscapeButton(QMessageBox::Ok); @@ -309,7 +309,7 @@ void tst_QMessageBox::escapeButton() QCOMPARE(msgBox.escapeButton(), okButton); msgBox.removeButton(okButton); delete okButton; - okButton = 0; + okButton = nullptr; QVERIFY(!msgBox.escapeButton()); msgBox.setEscapeButton(QMessageBox::Ok); QVERIFY(!msgBox.escapeButton()); @@ -353,28 +353,28 @@ void tst_QMessageBox::statics() ExecCloseHelper closeHelper; for (int i = 0; i < 4; i++) { closeHelper.start(Qt::Key_Escape); - QMessageBox::StandardButton sb = (*statics[i])(0, "caption", + QMessageBox::StandardButton sb = (*statics[i])(nullptr, "caption", "text", QMessageBox::Yes | QMessageBox::No | QMessageBox::Help | QMessageBox::Cancel, QMessageBox::NoButton); QCOMPARE(sb, QMessageBox::Cancel); QVERIFY(closeHelper.done()); closeHelper.start(ExecCloseHelper::CloseWindow); - sb = (*statics[i])(0, "caption", + sb = (*statics[i])(nullptr, "caption", "text", QMessageBox::Yes | QMessageBox::No | QMessageBox::Help | QMessageBox::Cancel, QMessageBox::NoButton); QCOMPARE(sb, QMessageBox::Cancel); QVERIFY(closeHelper.done()); closeHelper.start(Qt::Key_Enter); - sb = (*statics[i])(0, "caption", + sb = (*statics[i])(nullptr, "caption", "text", QMessageBox::Yes | QMessageBox::No | QMessageBox::Help, QMessageBox::Yes); QCOMPARE(sb, QMessageBox::Yes); QVERIFY(closeHelper.done()); closeHelper.start(Qt::Key_Enter); - sb = (*statics[i])(0, "caption", + sb = (*statics[i])(nullptr, "caption", "text", QMessageBox::Yes | QMessageBox::No | QMessageBox::Help, QMessageBox::No); QCOMPARE(sb, QMessageBox::No); @@ -400,7 +400,7 @@ void tst_QMessageBox::about() { ExecCloseHelper closeHelper; closeHelper.start(Qt::Key_Escape); - QMessageBox::about(0, "Caption", "This is an auto test"); + QMessageBox::about(nullptr, "Caption", "This is an auto test"); // On Mac, about and aboutQt are not modal, so we need to // explicitly run the event loop #ifdef Q_OS_MAC @@ -412,7 +412,7 @@ void tst_QMessageBox::about() const int keyToSend = Qt::Key_Enter; closeHelper.start(keyToSend); - QMessageBox::aboutQt(0, "Caption"); + QMessageBox::aboutQt(nullptr, "Caption"); #ifdef Q_OS_MAC QTRY_VERIFY(closeHelper.done()); #else @@ -427,7 +427,7 @@ void tst_QMessageBox::staticSourceCompat() // source compat tests for < 4.2 ExecCloseHelper closeHelper; closeHelper.start(Qt::Key_Enter); - ret = QMessageBox::information(0, "title", "text", QMessageBox::Yes, QMessageBox::No); + ret = QMessageBox::information(nullptr, "title", "text", QMessageBox::Yes, QMessageBox::No); int expectedButton = int(QMessageBox::Yes); if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) { const int dialogButtonBoxLayout = theme->themeHint(QPlatformTheme::DialogButtonBoxLayout).toInt(); @@ -439,39 +439,39 @@ void tst_QMessageBox::staticSourceCompat() QVERIFY(closeHelper.done()); closeHelper.start(Qt::Key_Enter); - ret = QMessageBox::information(0, "title", "text", QMessageBox::Yes | QMessageBox::Default, QMessageBox::No); + ret = QMessageBox::information(nullptr, "title", "text", QMessageBox::Yes | QMessageBox::Default, QMessageBox::No); QCOMPARE(ret, int(QMessageBox::Yes)); QVERIFY(closeHelper.done()); closeHelper.start(Qt::Key_Enter); - ret = QMessageBox::information(0, "title", "text", QMessageBox::Yes, QMessageBox::No | QMessageBox::Default); + ret = QMessageBox::information(nullptr, "title", "text", QMessageBox::Yes, QMessageBox::No | QMessageBox::Default); QCOMPARE(ret, int(QMessageBox::No)); QVERIFY(closeHelper.done()); closeHelper.start(Qt::Key_Enter); - ret = QMessageBox::information(0, "title", "text", QMessageBox::Yes | QMessageBox::Default, QMessageBox::No | QMessageBox::Escape); + ret = QMessageBox::information(nullptr, "title", "text", QMessageBox::Yes | QMessageBox::Default, QMessageBox::No | QMessageBox::Escape); QCOMPARE(ret, int(QMessageBox::Yes)); QVERIFY(closeHelper.done()); closeHelper.start(Qt::Key_Enter); - ret = QMessageBox::information(0, "title", "text", QMessageBox::Yes | QMessageBox::Escape, QMessageBox::No | QMessageBox::Default); + ret = QMessageBox::information(nullptr, "title", "text", QMessageBox::Yes | QMessageBox::Escape, QMessageBox::No | QMessageBox::Default); QCOMPARE(ret, int(QMessageBox::No)); QVERIFY(closeHelper.done()); // the button text versions closeHelper.start(Qt::Key_Enter); - ret = QMessageBox::information(0, "title", "text", "Yes", "No", QString(), 1); + ret = QMessageBox::information(nullptr, "title", "text", "Yes", "No", QString(), 1); QCOMPARE(ret, 1); QVERIFY(closeHelper.done()); if (0) { // don't run these tests since the dialog won't close! closeHelper.start(Qt::Key_Escape); - ret = QMessageBox::information(0, "title", "text", "Yes", "No", QString(), 1); + ret = QMessageBox::information(nullptr, "title", "text", "Yes", "No", QString(), 1); QCOMPARE(ret, -1); QVERIFY(closeHelper.done()); closeHelper.start(Qt::Key_Escape); - ret = QMessageBox::information(0, "title", "text", "Yes", "No", QString(), 0, 1); + ret = QMessageBox::information(nullptr, "title", "text", "Yes", "No", QString(), 0, 1); QCOMPARE(ret, 1); QVERIFY(closeHelper.done()); } @@ -618,9 +618,8 @@ void tst_QMessageBox::detailsButtonText() QDialogButtonBox* bb = box.findChild("qt_msgbox_buttonbox"); QVERIFY(bb); //get the detail button - QList list = bb->buttons(); - QAbstractButton* btn = NULL; - foreach(btn, list) { + auto list = bb->buttons(); + for (auto btn : list) { if (btn && (btn->inherits("QPushButton"))) { if (btn->text().remove(QLatin1Char('&')) != QMessageBox::tr("OK") && btn->text() != QMessageBox::tr("Show Details...")) { @@ -640,12 +639,12 @@ void tst_QMessageBox::expandDetails_QTBUG_32473() QDialogButtonBox* bb = box.findChild("qt_msgbox_buttonbox"); QVERIFY(bb); - QList list = bb->buttons(); - QAbstractButton* moreButton = NULL; - foreach (QAbstractButton* btn, list) - if (btn && bb->buttonRole(btn) == QDialogButtonBox::ActionRole) - moreButton = btn; - QVERIFY(moreButton); + auto list = bb->buttons(); + auto it = std::find_if(list.rbegin(), list.rend(), [&](QAbstractButton *btn) { + return btn && bb->buttonRole(btn) == QDialogButtonBox::ActionRole; }); + QVERIFY(it != list.rend()); + auto moreButton = *it; + QVERIFY(QTest::qWaitForWindowExposed(&box)); QRect geom = box.geometry(); box.resized = false; @@ -667,19 +666,19 @@ void tst_QMessageBox::incorrectDefaultButton() closeHelper.start(Qt::Key_Escape); //Do not crash here QTest::ignoreMessage(QtWarningMsg, "QDialogButtonBox::createButton: Invalid ButtonRole, button not added"); - QMessageBox::question( 0, "", "I've been hit!",QMessageBox::Ok | QMessageBox::Cancel,QMessageBox::Save ); + QMessageBox::question(nullptr, "", "I've been hit!",QMessageBox::Ok | QMessageBox::Cancel,QMessageBox::Save); QVERIFY(closeHelper.done()); closeHelper.start(Qt::Key_Escape); QTest::ignoreMessage(QtWarningMsg, "QDialogButtonBox::createButton: Invalid ButtonRole, button not added"); - QMessageBox::question( 0, "", "I've been hit!",QFlag(QMessageBox::Ok | QMessageBox::Cancel),QMessageBox::Save ); + QMessageBox::question(nullptr, "", "I've been hit!",QFlag(QMessageBox::Ok | QMessageBox::Cancel),QMessageBox::Save); QVERIFY(closeHelper.done()); closeHelper.start(Qt::Key_Escape); QTest::ignoreMessage(QtWarningMsg, "QDialogButtonBox::createButton: Invalid ButtonRole, button not added"); QTest::ignoreMessage(QtWarningMsg, "QDialogButtonBox::createButton: Invalid ButtonRole, button not added"); //do not crash here -> call old function of QMessageBox in this case - QMessageBox::question( 0, "", "I've been hit!",QMessageBox::Ok | QMessageBox::Cancel,QMessageBox::Save | QMessageBox::Cancel,QMessageBox::Ok); + QMessageBox::question(nullptr, "", "I've been hit!",QMessageBox::Ok | QMessageBox::Cancel,QMessageBox::Save | QMessageBox::Cancel,QMessageBox::Ok); QVERIFY(closeHelper.done()); } diff --git a/tests/manual/textrendering/nativetext/main.cpp b/tests/manual/textrendering/nativetext/main.cpp index 5c7621e61f7..3fb78858f05 100644 --- a/tests/manual/textrendering/nativetext/main.cpp +++ b/tests/manual/textrendering/nativetext/main.cpp @@ -101,7 +101,9 @@ class TextRenderer : public QWidget const int ascent = fontMetrics().ascent(); - p.setPen(Qt::magenta); + QPen metricsPen(Qt::magenta, 1.0); + metricsPen.setCosmetic(true); + p.setPen(metricsPen); p.drawLine(QPoint(0, ascent), QPoint(width(), ascent)); p.end(); @@ -152,13 +154,22 @@ class TextRenderer : public QWidget if (font().styleStrategy() & QFont::NoAntialias) CGContextSetShouldAntialias(ctx, false); - // Retain count already tracked by QMacCGContext above - NSGraphicsContext.currentContext = [NSGraphicsContext graphicsContextWithCGContext:ctx flipped:YES]; - [text().toNSString() drawAtPoint:CGPointZero withAttributes:@{ - NSFontAttributeName : (NSFont *)fontEngine->handle(), - NSForegroundColorAttributeName : nsColor - }]; - NSGraphicsContext.currentContext = nil; + // Flip to what CT expects + CGContextScaleCTM(ctx, 1, -1); + CGContextTranslateCTM(ctx, 0, -height()); + + // Set up baseline + CGContextSetTextPosition(ctx, 0, height() - fontMetrics().ascent()); + + auto *attributedString = [[NSAttributedString alloc] initWithString:text().toNSString() + attributes:@{ + NSFontAttributeName : (NSFont *)fontEngine->handle(), + NSForegroundColorAttributeName : nsColor + } + ]; + + QCFType line = CTLineCreateWithAttributedString(CFAttributedStringRef([attributedString autorelease])); + CTLineDraw(line, ctx); #endif }