summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2018-02-06 12:38:51 +0100
committerTor Arne Vestbø <tor.arne.vestbo@qt.io>2018-02-10 15:55:52 +0100
commit32b506d1db1f8cee748a27b548ba8208f2928058 (patch)
tree2d5b23baafe22ccc3518719f8f5d19bb846b2b61 /src
parent2cb1db64370989fffeec313c196fe573c479e6aa (diff)
parentc0948d508e7179e2e23c893ba6152c40400de060 (diff)
Merge remote-tracking branch 'origin/dev' into 5.11
Conflicts: src/corelib/tools/qvarlengtharray.qdoc src/corelib/tools/qvector.qdoc Resolved documentation changes in favor of 017569f702b6dd0, which keeps the move overloads along with its const-ref sibling. Change-Id: I0835b0b3211a418e5e50defc4cf315f0964fab79
Diffstat (limited to 'src')
-rw-r--r--src/corelib/configure.json36
-rw-r--r--src/corelib/corelib.pro6
-rw-r--r--src/corelib/global/qconfig-bootstrapped.h2
-rw-r--r--src/corelib/global/qfloat16.cpp2
-rw-r--r--src/corelib/global/qglobal.h5
-rw-r--r--src/corelib/global/qnumeric_p.h277
-rw-r--r--src/corelib/global/qtrace_p.h126
-rw-r--r--src/corelib/io/io.pri6
-rw-r--r--src/corelib/json/json.pri17
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp10
-rw-r--r--src/corelib/kernel/qeventdispatcher_cf.mm87
-rw-r--r--src/corelib/kernel/qeventdispatcher_cf_p.h20
-rw-r--r--src/corelib/kernel/qvariant.cpp13
-rw-r--r--src/corelib/kernel/qvariant.h19
-rw-r--r--src/corelib/mimetypes/qmimetype.cpp2
-rw-r--r--src/corelib/plugin/qfactoryloader.cpp5
-rw-r--r--src/corelib/plugin/qlibrary.cpp6
-rw-r--r--src/corelib/plugin/quuid.cpp4
-rw-r--r--src/corelib/plugin/quuid.h4
-rw-r--r--src/corelib/qtcore.tracepoints5
-rw-r--r--src/corelib/serialization/.gitignore (renamed from src/corelib/xml/.gitignore)0
-rwxr-xr-xsrc/corelib/serialization/make-xml-parser.sh (renamed from src/corelib/xml/make-parser.sh)0
-rw-r--r--src/corelib/serialization/qdatastream.cpp (renamed from src/corelib/io/qdatastream.cpp)0
-rw-r--r--src/corelib/serialization/qdatastream.h (renamed from src/corelib/io/qdatastream.h)0
-rw-r--r--src/corelib/serialization/qdatastream_p.h (renamed from src/corelib/io/qdatastream_p.h)0
-rw-r--r--src/corelib/serialization/qjson.cpp (renamed from src/corelib/json/qjson.cpp)0
-rw-r--r--src/corelib/serialization/qjson_p.h (renamed from src/corelib/json/qjson_p.h)9
-rw-r--r--src/corelib/serialization/qjsonarray.cpp (renamed from src/corelib/json/qjsonarray.cpp)0
-rw-r--r--src/corelib/serialization/qjsonarray.h (renamed from src/corelib/json/qjsonarray.h)0
-rw-r--r--src/corelib/serialization/qjsondocument.cpp (renamed from src/corelib/json/qjsondocument.cpp)0
-rw-r--r--src/corelib/serialization/qjsondocument.h (renamed from src/corelib/json/qjsondocument.h)0
-rw-r--r--src/corelib/serialization/qjsonobject.cpp (renamed from src/corelib/json/qjsonobject.cpp)0
-rw-r--r--src/corelib/serialization/qjsonobject.h (renamed from src/corelib/json/qjsonobject.h)0
-rw-r--r--src/corelib/serialization/qjsonparser.cpp (renamed from src/corelib/json/qjsonparser.cpp)0
-rw-r--r--src/corelib/serialization/qjsonparser_p.h (renamed from src/corelib/json/qjsonparser_p.h)0
-rw-r--r--src/corelib/serialization/qjsonvalue.cpp (renamed from src/corelib/json/qjsonvalue.cpp)0
-rw-r--r--src/corelib/serialization/qjsonvalue.h (renamed from src/corelib/json/qjsonvalue.h)0
-rw-r--r--src/corelib/serialization/qjsonwriter.cpp (renamed from src/corelib/json/qjsonwriter.cpp)0
-rw-r--r--src/corelib/serialization/qjsonwriter_p.h (renamed from src/corelib/json/qjsonwriter_p.h)0
-rw-r--r--src/corelib/serialization/qtextstream.cpp (renamed from src/corelib/io/qtextstream.cpp)0
-rw-r--r--src/corelib/serialization/qtextstream.h (renamed from src/corelib/io/qtextstream.h)0
-rw-r--r--src/corelib/serialization/qtextstream_p.h (renamed from src/corelib/io/qtextstream_p.h)0
-rw-r--r--src/corelib/serialization/qxmlstream.cpp (renamed from src/corelib/xml/qxmlstream.cpp)20
-rw-r--r--src/corelib/serialization/qxmlstream.g (renamed from src/corelib/xml/qxmlstream.g)0
-rw-r--r--src/corelib/serialization/qxmlstream.h (renamed from src/corelib/xml/qxmlstream.h)0
-rw-r--r--src/corelib/serialization/qxmlstream_p.h (renamed from src/corelib/xml/qxmlstream_p.h)0
-rw-r--r--src/corelib/serialization/qxmlutils.cpp (renamed from src/corelib/xml/qxmlutils.cpp)0
-rw-r--r--src/corelib/serialization/qxmlutils_p.h (renamed from src/corelib/xml/qxmlutils_p.h)0
-rw-r--r--src/corelib/serialization/serialization.pri30
-rw-r--r--src/corelib/thread/qthread_unix.cpp19
-rw-r--r--src/corelib/tools/qbitarray.cpp40
-rw-r--r--src/corelib/tools/qbitarray.h3
-rw-r--r--src/corelib/tools/qsimd_p.h96
-rw-r--r--src/corelib/tools/qstring.cpp188
-rw-r--r--src/corelib/tools/qstring.h7
-rw-r--r--src/corelib/tools/qstringalgorithms.h5
-rw-r--r--src/corelib/tools/qvarlengtharray.qdoc3
-rw-r--r--src/corelib/tools/qvector.qdoc3
-rw-r--r--src/corelib/xml/xml.pri10
-rw-r--r--src/gui/gui.pro3
-rw-r--r--src/gui/itemmodels/qstandarditemmodel.cpp33
-rw-r--r--src/gui/itemmodels/qstandarditemmodel.h1
-rw-r--r--src/gui/itemmodels/qstandarditemmodel_p.h2
-rw-r--r--src/gui/kernel/qevent.cpp19
-rw-r--r--src/gui/kernel/qguiapplication.cpp10
-rw-r--r--src/gui/kernel/qplatformintegration.cpp2
-rw-r--r--src/gui/kernel/qplatformintegration.h1
-rw-r--r--src/gui/kernel/qplatformtheme.cpp2
-rw-r--r--src/gui/kernel/qplatformtheme.h3
-rw-r--r--src/gui/kernel/qstylehints.cpp36
-rw-r--r--src/gui/kernel/qstylehints.h4
-rw-r--r--src/gui/painting/qdrawhelper.cpp112
-rw-r--r--src/gui/painting/qdrawhelper_avx2.cpp4
-rw-r--r--src/gui/painting/qdrawhelper_p.h18
-rw-r--r--src/gui/qtgui.tracepoints8
-rw-r--r--src/gui/text/qfontdatabase.cpp10
-rw-r--r--src/network/access/qnetworkrequest.cpp2
-rw-r--r--src/network/ssl/qsslconfiguration.cpp56
-rw-r--r--src/network/ssl/qsslconfiguration.h5
-rw-r--r--src/network/ssl/qsslconfiguration_p.h3
-rw-r--r--src/network/ssl/qsslcontext_openssl.cpp71
-rw-r--r--src/network/ssl/qsslcontext_openssl11.cpp4
-rw-r--r--src/network/ssl/qsslcontext_openssl_p.h1
-rw-r--r--src/network/ssl/qsslcontext_opensslpre11.cpp4
-rw-r--r--src/network/ssl/qsslsocket.cpp2
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols.cpp16
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols_p.h8
-rw-r--r--src/platformsupport/linuxaccessibility/atspiadaptor.cpp8
-rw-r--r--src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm2
-rw-r--r--src/plugins/platforms/ios/qioseventdispatcher.mm39
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.cpp56
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp12
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp13
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h2
-rw-r--r--src/plugins/platformthemes/flatpak/qflatpakfiledialog.cpp115
-rw-r--r--src/plugins/platformthemes/flatpak/qflatpakfiledialog_p.h1
-rw-r--r--src/plugins/printsupport/cups/qcupsprintengine.cpp32
-rw-r--r--src/plugins/printsupport/cups/qcupsprintengine_p.h1
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac.mm85
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac_p_p.h7
-rw-r--r--src/plugins/styles/windowsvista/qwindowsvistastyle.cpp49
-rw-r--r--src/plugins/styles/windowsvista/qwindowsxpstyle.cpp23
-rw-r--r--src/printsupport/dialogs/qprintdialog_unix.cpp4
-rw-r--r--src/printsupport/kernel/qcups.cpp5
-rw-r--r--src/printsupport/kernel/qcups_p.h1
-rw-r--r--src/printsupport/kernel/qplatformprintersupport.cpp5
-rw-r--r--src/printsupport/kernel/qplatformprintersupport.h1
-rw-r--r--src/src.pro16
-rw-r--r--src/tools/bootstrap/bootstrap.pro22
-rw-r--r--src/tools/tracegen/etw.cpp228
-rw-r--r--src/tools/tracegen/etw.h48
-rw-r--r--src/tools/tracegen/helpers.cpp92
-rw-r--r--src/tools/tracegen/helpers.h57
-rw-r--r--src/tools/tracegen/lttng.cpp215
-rw-r--r--src/tools/tracegen/lttng.h48
-rw-r--r--src/tools/tracegen/panic.cpp59
-rw-r--r--src/tools/tracegen/panic.h45
-rw-r--r--src/tools/tracegen/provider.cpp304
-rw-r--r--src/tools/tracegen/provider.h95
-rw-r--r--src/tools/tracegen/qtheaders.cpp51
-rw-r--r--src/tools/tracegen/qtheaders.h45
-rw-r--r--src/tools/tracegen/tracegen.cpp109
-rw-r--r--src/tools/tracegen/tracegen.pro21
-rw-r--r--src/widgets/accessible/simplewidgets.cpp2
-rw-r--r--src/widgets/dialogs/qfileinfogatherer_p.h7
-rw-r--r--src/widgets/dialogs/qfilesystemmodel.cpp93
-rw-r--r--src/widgets/dialogs/qfilesystemmodel_p.h8
-rw-r--r--src/widgets/doc/snippets/common-table-model/model.cpp12
-rw-r--r--src/widgets/doc/snippets/common-table-model/model.h22
-rw-r--r--src/widgets/doc/snippets/stringlistmodel/model.cpp6
-rw-r--r--src/widgets/doc/snippets/stringlistmodel/model.h16
-rw-r--r--src/widgets/graphicsview/qgraphicsscene.h6
-rw-r--r--src/widgets/itemviews/qheaderview.cpp14
-rw-r--r--src/widgets/itemviews/qlistwidget.cpp17
-rw-r--r--src/widgets/itemviews/qlistwidget.h1
-rw-r--r--src/widgets/itemviews/qlistwidget_p.h2
-rw-r--r--src/widgets/kernel/qaction.cpp2
-rw-r--r--src/widgets/kernel/qlayout.h4
-rw-r--r--src/widgets/styles/qcommonstyle.cpp27
-rw-r--r--src/widgets/styles/qfusionstyle.cpp5
-rw-r--r--src/widgets/styles/qwindowsstyle.cpp144
-rw-r--r--src/widgets/widgets/qlineedit.cpp14
-rw-r--r--src/widgets/widgets/qlineedit_p.cpp8
-rw-r--r--src/widgets/widgets/qlineedit_p.h4
-rw-r--r--src/widgets/widgets/qmenubar.cpp4
-rw-r--r--src/xml/sax/qxml.h6
147 files changed, 3046 insertions, 821 deletions
diff --git a/src/corelib/configure.json b/src/corelib/configure.json
index 8cd73d6ce4..9f9512942a 100644
--- a/src/corelib/configure.json
+++ b/src/corelib/configure.json
@@ -15,7 +15,8 @@
"posix-ipc": { "type": "boolean", "name": "ipc_posix" },
"pps": { "type": "boolean", "name": "qqnx_pps" },
"slog2": "boolean",
- "syslog": "boolean"
+ "syslog": "boolean",
+ "trace": { "type": "optionalString", "values": [ "etw", "lttng", "no", "yes" ] }
}
},
@@ -147,6 +148,18 @@
"-lrt"
]
},
+ "lttng-ust": {
+ "label": "lttng-ust",
+ "test": {
+ "include": "lttng/ust-events.h",
+ "main": "lttng_session_destroy(nullptr);"
+ },
+ "sources": [
+ { "type": "pkgConfig", "args": "lttng-ust" },
+ "-llttng-ust"
+ ],
+ "use": "libdl"
+ },
"pcre2": {
"label": "PCRE2",
"test": {
@@ -858,6 +871,22 @@
"section": "Utilities",
"output": [ "publicFeature" ]
},
+ "lttng": {
+ "label": "LTTNG",
+ "autoDetect": false,
+ "enable": "input.trace == 'lttng' || (input.trace =='yes' && config.linux)",
+ "disable": "input.trace == 'etw' || input.trace =='no'",
+ "condition": "config.linux && libs.lttng-ust",
+ "output": [ "privateFeature" ]
+ },
+ "etw": {
+ "label": "ETW",
+ "autoDetect": false,
+ "enable": "input.trace == 'etw' || (input.trace == 'yes' && config.win32)",
+ "disable": "input.trace == 'lttng' || input.trace == 'no'",
+ "condition": "config.win32",
+ "output": [ "privateFeature" ]
+ },
"topleveldomain": {
"label": "QUrl::topLevelDomain()",
"purpose": "Provides support for extracting the top level domain from URLs.
@@ -908,6 +937,11 @@ Please apply the patch corresponding to your Standard Library vendor, found in
"iconv",
"icu",
{
+ "message": "Tracing backend",
+ "type": "firstAvailableFeature",
+ "args": "etw lttng"
+ },
+ {
"section": "Logging backends",
"entries": [
"journald", "syslog", "slog2"
diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro
index 6dc4af1bfe..2079d2117f 100644
--- a/src/corelib/corelib.pro
+++ b/src/corelib/corelib.pro
@@ -6,6 +6,9 @@ MODULE = core # not corelib, as per project file
MODULE_CONFIG = moc resources
!isEmpty(QT_NAMESPACE): MODULE_DEFINES = QT_NAMESPACE=$$QT_NAMESPACE
+TRACEPOINT_PROVIDER = $$PWD/qtcore.tracepoints
+CONFIG += qt_tracepoints
+
CONFIG += $$MODULE_CONFIG
DEFINES += $$MODULE_DEFINES
DEFINES += QT_NO_USING_NAMESPACE QT_NO_FOREACH
@@ -35,13 +38,12 @@ include(thread/thread.pri)
include(tools/tools.pri)
include(io/io.pri)
include(itemmodels/itemmodels.pri)
-include(json/json.pri)
include(plugin/plugin.pri)
include(kernel/kernel.pri)
include(codecs/codecs.pri)
+include(serialization/serialization.pri)
include(statemachine/statemachine.pri)
include(mimetypes/mimetypes.pri)
-include(xml/xml.pri)
win32 {
LIBS_PRIVATE += -lws2_32
diff --git a/src/corelib/global/qconfig-bootstrapped.h b/src/corelib/global/qconfig-bootstrapped.h
index 0df593941d..86ef1a2613 100644
--- a/src/corelib/global/qconfig-bootstrapped.h
+++ b/src/corelib/global/qconfig-bootstrapped.h
@@ -78,6 +78,7 @@
#define QT_FEATURE_cxx11_random (QT_HAS_INCLUDE(<random>) ? 1 : -1)
#define QT_NO_DATASTREAM
#define QT_FEATURE_datetimeparser -1
+#define QT_FEATURE_etw -1
#define QT_FEATURE_getauxval (QT_HAS_INCLUDE(<sys/auxv.h>) ? 1 : -1)
#define QT_FEATURE_getentropy -1
#define QT_NO_GEOM_VARIANT
@@ -92,6 +93,7 @@
#else
# define QT_FEATURE_linkat -1
#endif
+#define QT_FEATURE_lttng -1
#define QT_NO_QOBJECT
#define QT_FEATURE_process -1
#define QT_FEATURE_regularexpression -1
diff --git a/src/corelib/global/qfloat16.cpp b/src/corelib/global/qfloat16.cpp
index 3046a47292..fd608efe55 100644
--- a/src/corelib/global/qfloat16.cpp
+++ b/src/corelib/global/qfloat16.cpp
@@ -178,6 +178,7 @@ static void qFloatFromFloat16_fast(float *, const quint16 *, qsizetype) Q_DECL_N
#endif
/*!
\since 5.11
+ \relates <QFloat16>
Converts \a len floats from \a in to qfloat16 and stores them in \a out.
Both \a in and \a out must have \a len allocated entries.
@@ -193,6 +194,7 @@ Q_CORE_EXPORT void qFloatToFloat16(qfloat16 *out, const float *in, qsizetype len
/*!
\since 5.11
+ \relates <QFloat16>
Converts \a len qfloat16 from \a in to floats and stores them in \a out.
Both \a in and \a out must have \a len allocated entries.
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 7764707de0..aa9446221b 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -88,6 +88,11 @@
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
# define QT_NO_UNSHARABLE_CONTAINERS
+# define QT6_VIRTUAL virtual
+# define QT6_NOT_VIRTUAL
+#else
+# define QT6_VIRTUAL
+# define QT6_NOT_VIRTUAL virtual
#endif
/* These two macros makes it possible to turn the builtin line expander into a
diff --git a/src/corelib/global/qnumeric_p.h b/src/corelib/global/qnumeric_p.h
index a352e39ef0..9b86a16516 100644
--- a/src/corelib/global/qnumeric_p.h
+++ b/src/corelib/global/qnumeric_p.h
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -58,8 +58,6 @@
#if defined(Q_CC_MSVC)
# include <intrin.h>
-#elif defined(Q_CC_INTEL)
-# include <immintrin.h> // for _addcarry_u<nn>
#endif
#if defined(Q_CC_MSVC)
@@ -164,10 +162,33 @@ Q_DECL_CONST_FUNCTION static inline bool qt_is_finite(float f)
}
#ifndef Q_CLANG_QDOC
-//
-// Unsigned overflow math
-//
namespace {
+// Overflow math.
+// This provides efficient implementations for int, unsigned, qsizetype and
+// size_t. Implementations for 8- and 16-bit types will work but may not be as
+// efficient. Implementations for 64-bit may be missing on 32-bit platforms.
+
+#if (defined(Q_CC_GNU) && (Q_CC_GNU >= 500) || defined(Q_CC_INTEL)) || QT_HAS_BUILTIN(__builtin_add_overflowx)
+// GCC 5, ICC 18, and Clang 3.8 have builtins to detect overflows
+
+template <typename T> inline
+typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type
+add_overflow(T v1, T v2, T *r)
+{ return __builtin_add_overflow(v1, v2, r); }
+
+template <typename T> inline
+typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type
+sub_overflow(T v1, T v2, T *r)
+{ return __builtin_sub_overflow(v1, v2, r); }
+
+template <typename T> inline
+typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type
+mul_overflow(T v1, T v2, T *r)
+{ return __builtin_mul_overflow(v1, v2, r); }
+
+#else
+// Generic implementations
+
template <typename T> inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type
add_overflow(T v1, T v2, T *r)
{
@@ -176,69 +197,92 @@ add_overflow(T v1, T v2, T *r)
return v1 > T(v1 + v2);
}
+template <typename T> inline typename std::enable_if<std::is_signed<T>::value, bool>::type
+add_overflow(T v1, T v2, T *r)
+{
+ // Here's how we calculate the overflow:
+ // 1) unsigned addition is well-defined, so we can always execute it
+ // 2) conversion from unsigned back to signed is implementation-
+ // defined and in the implementations we use, it's a no-op.
+ // 3) signed integer overflow happens if the sign of the two input operands
+ // is the same but the sign of the result is different. In other words,
+ // the sign of the result must be the same as the sign of either
+ // operand.
+
+ using U = typename std::make_unsigned<T>::type;
+ *r = T(U(v1) + U(v2));
+
+ // If int is two's complement, assume all integer types are too.
+ if (std::is_same<int32_t, int>::value) {
+ // Two's complement equivalent (generates slightly shorter code):
+ // x ^ y is negative if x and y have different signs
+ // x & y is negative if x and y are negative
+ // (x ^ z) & (y ^ z) is negative if x and z have different signs
+ // AND y and z have different signs
+ return ((v1 ^ *r) & (v2 ^ *r)) < 0;
+ }
+
+ bool s1 = (v1 < 0);
+ bool s2 = (v2 < 0);
+ bool sr = (*r < 0);
+ return s1 != sr && s2 != sr;
+ // also: return s1 == s2 && s1 != sr;
+}
+
template <typename T> inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type
+sub_overflow(T v1, T v2, T *r)
+{
+ // unsigned subtractions are well-defined
+ *r = v1 - v2;
+ return v1 < v2;
+}
+
+template <typename T> inline typename std::enable_if<std::is_signed<T>::value, bool>::type
+sub_overflow(T v1, T v2, T *r)
+{
+ // See above for explanation. This is the same with some signs reversed.
+ // We can't use add_overflow(v1, -v2, r) because it would be UB if
+ // v2 == std::numeric_limits<T>::min().
+
+ using U = typename std::make_unsigned<T>::type;
+ *r = T(U(v1) - U(v2));
+
+ if (std::is_same<int32_t, int>::value)
+ return ((v1 ^ *r) & (~v2 ^ *r)) < 0;
+
+ bool s1 = (v1 < 0);
+ bool s2 = !(v2 < 0);
+ bool sr = (*r < 0);
+ return s1 != sr && s2 != sr;
+ // also: return s1 == s2 && s1 != sr;
+}
+
+template <typename T> inline
+typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type
mul_overflow(T v1, T v2, T *r)
{
// use the next biggest type
// Note: for 64-bit systems where __int128 isn't supported, this will cause an error.
- // A fallback is present below.
- typedef typename QIntegerForSize<sizeof(T) * 2>::Unsigned Larger;
+ using LargerInt = QIntegerForSize<sizeof(T) * 2>;
+ using Larger = typename std::conditional<std::is_signed<T>::value,
+ typename LargerInt::Signed, typename LargerInt::Unsigned>::type;
Larger lr = Larger(v1) * Larger(v2);
*r = T(lr);
- return lr > std::numeric_limits<T>::max();
+ return lr > std::numeric_limits<T>::max() || lr < std::numeric_limits<T>::min();
}
-#if defined(__SIZEOF_INT128__)
-# define HAVE_MUL64_OVERFLOW
-#endif
-
-// GCC 5 and Clang have builtins to detect overflows
-#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_uadd_overflow)
+# if defined(Q_CC_MSVC) && defined(Q_PROCESSOR_X86)
+// We can use intrinsics for the unsigned operations with MSVC
template <> inline bool add_overflow(unsigned v1, unsigned v2, unsigned *r)
-{ return __builtin_uadd_overflow(v1, v2, r); }
-#endif
-#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_uaddl_overflow)
-template <> inline bool add_overflow(unsigned long v1, unsigned long v2, unsigned long *r)
-{ return __builtin_uaddl_overflow(v1, v2, r); }
-#endif
-#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_uaddll_overflow)
-template <> inline bool add_overflow(unsigned long long v1, unsigned long long v2, unsigned long long *r)
-{ return __builtin_uaddll_overflow(v1, v2, r); }
-#endif
+{ return _addcarry_u32(0, v1, v2, r); }
-#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_umul_overflow)
-template <> inline bool mul_overflow(unsigned v1, unsigned v2, unsigned *r)
-{ return __builtin_umul_overflow(v1, v2, r); }
-#endif
-#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_umull_overflow)
-template <> inline bool mul_overflow(unsigned long v1, unsigned long v2, unsigned long *r)
-{ return __builtin_umull_overflow(v1, v2, r); }
-#endif
-#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_umulll_overflow)
-template <> inline bool mul_overflow(unsigned long long v1, unsigned long long v2, unsigned long long *r)
-{ return __builtin_umulll_overflow(v1, v2, r); }
-# define HAVE_MUL64_OVERFLOW
-#endif
+// 32-bit mul_overflow is fine with the generic code above
-#if (defined(Q_CC_MSVC) || defined(Q_CC_INTEL)) && defined(Q_PROCESSOR_X86) && !QT_HAS_BUILTIN(__builtin_uadd_overflow)
-template <> inline bool add_overflow(unsigned v1, unsigned v2, unsigned *r)
-{ return _addcarry_u32(0, v1, v2, r); }
-# ifdef Q_CC_MSVC // longs are 32-bit
-template <> inline bool add_overflow(unsigned long v1, unsigned long v2, unsigned long *r)
-{ return _addcarry_u32(0, v1, v2, reinterpret_cast<unsigned *>(r)); }
-# endif
-#endif
-#if (defined(Q_CC_MSVC) || defined(Q_CC_INTEL)) && defined(Q_PROCESSOR_X86_64) && !QT_HAS_BUILTIN(__builtin_uadd_overflow)
+# if defined(Q_PROCESSOR_X86_64)
template <> inline bool add_overflow(quint64 v1, quint64 v2, quint64 *r)
{ return _addcarry_u64(0, v1, v2, reinterpret_cast<unsigned __int64 *>(r)); }
-# ifndef Q_CC_MSVC // longs are 64-bit
-template <> inline bool add_overflow(unsigned long v1, unsigned long v2, unsigned long *r)
-{ return _addcarry_u64(0, v1, v2, reinterpret_cast<unsigned __int64 *>(r)); }
-# endif
-#endif
-#if defined(Q_CC_MSVC) && (defined(Q_PROCESSOR_X86_64) || defined(Q_PROCESSOR_IA64)) && !QT_HAS_BUILTIN(__builtin_uadd_overflow)
-#pragma intrinsic(_umul128)
+# pragma intrinsic(_umul128)
template <> inline bool mul_overflow(quint64 v1, quint64 v2, quint64 *r)
{
// use 128-bit multiplication with the _umul128 intrinsic
@@ -247,117 +291,30 @@ template <> inline bool mul_overflow(quint64 v1, quint64 v2, quint64 *r)
*r = _umul128(v1, v2, &high);
return high;
}
-# define HAVE_MUL64_OVERFLOW
-#endif
-
-#if !defined(HAVE_MUL64_OVERFLOW) && defined(__LP64__)
-// no 128-bit multiplication, we need to figure out with a slow division
-template <> inline bool mul_overflow(quint64 v1, quint64 v2, quint64 *r)
-{
- if (v2 && v1 > std::numeric_limits<quint64>::max() / v2)
- return true;
- *r = v1 * v2;
- return false;
-}
-template <> inline bool mul_overflow(unsigned long v1, unsigned long v2, unsigned long *r)
-{
- return mul_overflow<quint64>(v1, v2, reinterpret_cast<quint64 *>(r));
-}
-#else
-# undef HAVE_MUL64_OVERFLOW
-#endif
-
-//
-// Signed overflow math
-//
-// In C++, signed overflow math is Undefined Behavior. However, many CPUs do implement some way to
-// check for overflow. Some compilers expose intrinsics to use this functionality. If the no
-// intrinsic is exposed, overflow checking can be done by widening the result type and "manually"
-// checking for overflow. Or, alternatively, by using inline assembly to use the CPU features.
-//
-// Only int overflow checking is implemented, because it's the only one used.
-#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_sadd_overflow)
-inline bool add_overflow(int v1, int v2, int *r)
-{ return __builtin_sadd_overflow(v1, v2, r); }
-#elif defined(Q_CC_GNU) && defined(Q_PROCESSOR_X86)
-inline bool add_overflow(int v1, int v2, int *r)
-{
- quint8 overflow = 0;
- int res = v1;
-
- asm ("addl %2, %1\n"
- "seto %0"
- : "=q" (overflow), "=r" (res)
- : "r" (v2), "1" (res)
- : "cc"
- );
- *r = res;
- return overflow;
-}
-#else
-inline bool add_overflow(int v1, int v2, int *r)
-{
- qint64 t = qint64(v1) + v2;
- *r = static_cast<int>(t);
- return t > std::numeric_limits<int>::max() || t < std::numeric_limits<int>::min();
-}
-#endif
-#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_ssub_overflow)
-inline bool sub_overflow(int v1, int v2, int *r)
-{ return __builtin_ssub_overflow(v1, v2, r); }
-#elif defined(Q_CC_GNU) && defined(Q_PROCESSOR_X86)
-inline bool sub_overflow(int v1, int v2, int *r)
+# pragma intrinsic(_mul128)
+template <> inline bool mul_overflow(qint64 v1, qint64 v2, qint64 *r)
{
- quint8 overflow = 0;
- int res = v1;
-
- asm ("subl %2, %1\n"
- "seto %0"
- : "=q" (overflow), "=r" (res)
- : "r" (v2), "1" (res)
- : "cc"
- );
- *r = res;
- return overflow;
+ // Use 128-bit multiplication with the _mul128 intrinsic
+ // https://msdn.microsoft.com/en-us/library/82cxdw50.aspx
+
+ // This is slightly more complex than the unsigned case above: the sign bit
+ // of 'low' must be replicated as the entire 'high', so the only valid
+ // values for 'high' are 0 and -1.
+
+ qint64 high;
+ *r = _mul128(v1, v2, &high);
+ if (high == 0)
+ return *r < 0;
+ if (high == -1)
+ return *r >= 0;
+ return true;
}
-#else
-inline bool sub_overflow(int v1, int v2, int *r)
-{
- qint64 t = qint64(v1) - v2;
- *r = static_cast<int>(t);
- return t > std::numeric_limits<int>::max() || t < std::numeric_limits<int>::min();
+# endif // x86-64
+# endif // MSVC x86
+#endif // !GCC
}
-#endif
-
-#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_smul_overflow)
-inline bool mul_overflow(int v1, int v2, int *r)
-{ return __builtin_smul_overflow(v1, v2, r); }
-#elif defined(Q_CC_GNU) && defined(Q_PROCESSOR_X86)
-inline bool mul_overflow(int v1, int v2, int *r)
-{
- quint8 overflow = 0;
- int res = v1;
-
- asm ("imul %2, %1\n"
- "seto %0"
- : "=q" (overflow), "=r" (res)
- : "r" (v2), "1" (res)
- : "cc"
- );
- *r = res;
- return overflow;
-}
-#else
-inline bool mul_overflow(int v1, int v2, int *r)
-{
- qint64 t = qint64(v1) * v2;
- *r = static_cast<int>(t);
- return t > std::numeric_limits<int>::max() || t < std::numeric_limits<int>::min();
-}
-#endif
#endif // Q_CLANG_QDOC
-}
QT_END_NAMESPACE
diff --git a/src/corelib/global/qtrace_p.h b/src/corelib/global/qtrace_p.h
new file mode 100644
index 0000000000..ab8fc14af5
--- /dev/null
+++ b/src/corelib/global/qtrace_p.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTRACE_P_H
+#define QTRACE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+/*
+ * The Qt tracepoints API consists of only three macros:
+ *
+ * - Q_TRACE(tracepoint, args...)
+ * Fires 'tracepoint' if it is enabled.
+ *
+ * - Q_UNCONDITIONAL_TRACE(tracepoint, args...)
+ * Fires 'tracepoint' unconditionally: no check is performed to query
+ * whether 'tracepoint' is enabled.
+ *
+ * - Q_TRACE_ENABLED(tracepoint)
+ * Returns 'true' if 'tracepoint' is enabled; false otherwise.
+ *
+ * When using LTTNG, Q_TRACE, Q_UNCONDITIONAL_TRACE and Q_TRACE_ENABLED map
+ * ultimately to tracepoint(), do_tracepoint() and tracepoint_enabled(),
+ * respectively, described on the lttng-ust manpage (man 3 lttng-ust).
+ *
+ * On ETW, Q_TRACE() and Q_UNCONDITIONAL_TRACE() are equivalent, ultimately
+ * amounting to a call to TraceLoggingWrite(), whereas Q_TRACE_ENABLED()
+ * wraps around TraceLoggingProviderEnabled().
+ *
+ * A tracepoint provider is defined in a separate file, that follows the
+ * following format:
+ *
+ * tracepoint_name(arg_type arg_name, ...)
+ *
+ * For instance:
+ *
+ * qcoreapplication_ctor(int argc, const char * const argv)
+ * qcoreapplication_foo(int argc, const char[10] argv)
+ * qcoreapplication_baz(const char[len] some_string, unsigned int len)
+ * qcoreapplication_qstring(const QString &foo)
+ * qcoreapplication_qrect(const QRect &rect)
+ *
+ * The provider file is then parsed by src/tools/tracegen, which can be
+ * switched to output either ETW or LTTNG tracepoint definitions. The provider
+ * name is deduced to be basename(provider_file).
+ *
+ * To use the above (inside qtcore), you need to include
+ * <providername_tracepoints_p.h>. After that, the following call becomes
+ * possible:
+ *
+ * Q_TRACE(qcoreapplication_qrect, myRect);
+ *
+ * Currently, all C++ primitive non-pointer types are supported for
+ * arguments. Additionally, char * is supported, and is assumed to
+ * be a NULL-terminated string. Finally, the following subset of Qt types also
+ * currently supported:
+ *
+ * - QString
+ * - QByteArray
+ * - QUrl
+ * - QRect
+ *
+ * Dynamic arrays are supported using the syntax illustrated by
+ * qcoreapplication_baz above.
+ */
+
+QT_BEGIN_NAMESPACE
+
+#if defined(Q_TRACEPOINT) && !defined(QT_BOOTSTRAPPED)
+# define Q_TRACE(x, ...) QtPrivate::trace_ ## x(__VA_ARGS__)
+# define Q_UNCONDITIONAL_TRACE(x, ...) QtPrivate::do_trace_ ## x(__VA_ARGS__)
+# define Q_TRACE_ENABLED(x) QtPrivate::trace_ ## x ## _enabled()
+#else
+# define Q_TRACE(x, ...)
+# define Q_UNCONDITIONAL_TRACE(x, ...)
+# define Q_TRACE_ENABLED(x) false
+#endif // defined(Q_TRACEPOINT) && !defined(QT_BOOTSTRAPPED)
+
+QT_END_NAMESPACE
+
+#endif // QTRACE_P_H
diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri
index 4614fe2a6b..c6a5973306 100644
--- a/src/corelib/io/io.pri
+++ b/src/corelib/io/io.pri
@@ -3,8 +3,6 @@
HEADERS += \
io/qabstractfileengine_p.h \
io/qbuffer.h \
- io/qdatastream.h \
- io/qdatastream_p.h \
io/qdataurl_p.h \
io/qdebug.h \
io/qdebug_p.h \
@@ -22,8 +20,6 @@ HEADERS += \
io/qlockfile.h \
io/qlockfile_p.h \
io/qnoncontiguousbytedevice_p.h \
- io/qtextstream.h \
- io/qtextstream_p.h \
io/qtemporarydir.h \
io/qtemporaryfile.h \
io/qtemporaryfile_p.h \
@@ -57,7 +53,6 @@ HEADERS += \
SOURCES += \
io/qabstractfileengine.cpp \
io/qbuffer.cpp \
- io/qdatastream.cpp \
io/qdataurl.cpp \
io/qtldurl.cpp \
io/qdebug.cpp \
@@ -71,7 +66,6 @@ SOURCES += \
io/qlockfile.cpp \
io/qnoncontiguousbytedevice.cpp \
io/qstorageinfo.cpp \
- io/qtextstream.cpp \
io/qtemporarydir.cpp \
io/qtemporaryfile.cpp \
io/qresource.cpp \
diff --git a/src/corelib/json/json.pri b/src/corelib/json/json.pri
deleted file mode 100644
index 1a4e2a72bf..0000000000
--- a/src/corelib/json/json.pri
+++ /dev/null
@@ -1,17 +0,0 @@
-HEADERS += \
- json/qjson_p.h \
- json/qjsondocument.h \
- json/qjsonobject.h \
- json/qjsonvalue.h \
- json/qjsonarray.h \
- json/qjsonwriter_p.h \
- json/qjsonparser_p.h
-
-SOURCES += \
- json/qjson.cpp \
- json/qjsondocument.cpp \
- json/qjsonobject.cpp \
- json/qjsonarray.cpp \
- json/qjsonvalue.cpp \
- json/qjsonwriter.cpp \
- json/qjsonparser.cpp
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index e93a14c116..4bab0b9f01 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -116,6 +116,12 @@
# include <taskLib.h>
#endif
+#ifdef QT_BOOTSTRAPPED
+#include <private/qtrace_p.h>
+#else
+#include <qtcore_tracepoints_p.h>
+#endif
+
#include <algorithm>
QT_BEGIN_NAMESPACE
@@ -790,6 +796,8 @@ QCoreApplication::QCoreApplication(int &argc, char **argv
void QCoreApplicationPrivate::init()
{
+ Q_TRACE(qcoreapplicationprivate_init_entry);
+
#if defined(Q_OS_MACOS)
QMacAutoReleasePool pool;
#endif
@@ -873,6 +881,8 @@ void QCoreApplicationPrivate::init()
#ifndef QT_NO_QOBJECT
is_app_running = true; // No longer starting up.
#endif
+
+ Q_TRACE(qcoreapplicationprivate_init_exit);
}
/*!
diff --git a/src/corelib/kernel/qeventdispatcher_cf.mm b/src/corelib/kernel/qeventdispatcher_cf.mm
index 608dea5426..8499b3fd57 100644
--- a/src/corelib/kernel/qeventdispatcher_cf.mm
+++ b/src/corelib/kernel/qeventdispatcher_cf.mm
@@ -112,14 +112,15 @@ static CFStringRef runLoopMode(NSDictionary *dictionary)
if (CFStringRef mode = runLoopMode(notification.userInfo))
m_runLoopModes.push(mode);
else
- qWarning("Encountered run loop push notification without run loop mode!");
+ qCWarning(lcEventDispatcher) << "Encountered run loop push notification without run loop mode!";
} else if (CFStringHasSuffix((CFStringRef)notification.name, CFSTR("RunLoopModePopNotification"))) {
CFStringRef mode = runLoopMode(notification.userInfo);
if (CFStringCompare(mode, [self currentMode], 0) == kCFCompareEqualTo)
m_runLoopModes.pop();
else
- qWarning("Tried to pop run loop mode '%s' that was never pushed!", qPrintable(QString::fromCFString(mode)));
+ qCWarning(lcEventDispatcher) << "Tried to pop run loop mode"
+ << qPrintable(QString::fromCFString(mode)) << "that was never pushed!";
Q_ASSERT(m_runLoopModes.size() >= 1);
}
@@ -134,6 +135,9 @@ static CFStringRef runLoopMode(NSDictionary *dictionary)
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher");
+Q_LOGGING_CATEGORY(lcEventDispatcherTimers, "qt.eventdispatcher.timers");
+
class RunLoopDebugger : public QObject
{
Q_OBJECT
@@ -177,10 +181,6 @@ QDebug operator<<(QDebug s, timespec tv)
return s;
}
-#if DEBUG_EVENT_DISPATCHER
-uint g_eventDispatcherIndentationLevel = 0;
-#endif
-
static const CFTimeInterval kCFTimeIntervalMinimum = 0;
static const CFTimeInterval kCFTimeIntervalDistantFuture = std::numeric_limits<CFTimeInterval>::max();
@@ -190,13 +190,7 @@ QEventDispatcherCoreFoundation::QEventDispatcherCoreFoundation(QObject *parent)
: QAbstractEventDispatcher(parent)
, m_processEvents(QEventLoop::EventLoopExec)
, m_postedEventsRunLoopSource(this, &QEventDispatcherCoreFoundation::processPostedEvents)
- , m_runLoopActivityObserver(this, &QEventDispatcherCoreFoundation::handleRunLoopActivity,
-#if DEBUG_EVENT_DISPATCHER
- kCFRunLoopAllActivities
-#else
- kCFRunLoopBeforeWaiting | kCFRunLoopAfterWaiting
-#endif
- )
+ , m_runLoopActivityObserver(this, &QEventDispatcherCoreFoundation::handleRunLoopActivity, kCFRunLoopAllActivities)
, m_runLoopModeTracker([[RunLoopModeTracker alloc] init])
, m_runLoopTimer(0)
, m_blockedRunLoopTimer(0)
@@ -247,14 +241,14 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag
bool eventsProcessed = false;
if (flags & (QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers))
- qWarning() << "processEvents() flags" << flags << "not supported on iOS";
+ qCWarning(lcEventDispatcher) << "processEvents() flags" << flags << "not supported on iOS";
- qEventDispatcherDebug() << "Entering with " << flags; qIndent();
+ qCDebug(lcEventDispatcher) << "Processing events with flags" << flags;
if (m_blockedRunLoopTimer) {
Q_ASSERT(m_blockedRunLoopTimer == m_runLoopTimer);
- qEventDispatcherDebug() << "Recursing from blocked timer " << m_blockedRunLoopTimer;
+ qCDebug(lcEventDispatcher) << "Recursing from blocked timer" << m_blockedRunLoopTimer;
m_runLoopTimer = 0; // Unset current timer to force creation of new timer
updateTimers();
}
@@ -266,7 +260,7 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag
m_postedEventsRunLoopSource.signal();
m_processEvents.deferredWakeUp = false;
- qEventDispatcherDebug() << "Processed deferred wake-up";
+ qCDebug(lcEventDispatcher) << "Processed deferred wake-up";
}
// The documentation states that this signal is emitted after the event
@@ -287,12 +281,12 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag
CFTimeInterval duration = (m_processEvents.flags & QEventLoop::WaitForMoreEvents) ?
kCFTimeIntervalDistantFuture : kCFTimeIntervalMinimum;
- qEventDispatcherDebug() << "Calling CFRunLoopRunInMode = " << qPrintable(QString::fromCFString(mode))
- << " for " << duration << " ms, processing single source = " << returnAfterSingleSourceHandled; qIndent();
+ qCDebug(lcEventDispatcher) << "Calling CFRunLoopRunInMode =" << qPrintable(QString::fromCFString(mode))
+ << "for" << duration << "ms, processing single source =" << returnAfterSingleSourceHandled;
SInt32 result = CFRunLoopRunInMode(mode, duration, returnAfterSingleSourceHandled);
- qUnIndent(); qEventDispatcherDebug() << "result = " << qPrintableResult(result);
+ qCDebug(lcEventDispatcher) << "result =" << qPrintableResult(result);
eventsProcessed |= (result == kCFRunLoopRunHandledSource
|| m_processEvents.processedPostedEvents
@@ -316,15 +310,15 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag
// immediately, since it has already been exited.
if (!currentEventLoop()->isRunning()) {
- qEventDispatcherDebug() << "Top level event loop was exited";
+ qCDebug(lcEventDispatcher) << "Top level event loop was exited";
break;
} else {
- qEventDispatcherDebug() << "Top level event loop still running, making another pass";
+ qCDebug(lcEventDispatcher) << "Top level event loop still running, making another pass";
}
} else {
// We were called manually, through processEvents(), and should stop processing
// events, even if we didn't finish processing all the queued events.
- qEventDispatcherDebug() << "Top level processEvents was interrupted";
+ qCDebug(lcEventDispatcher) << "Top level processEvents was interrupted";
break;
}
}
@@ -353,7 +347,7 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag
// date in the past (overdue) will fire on the next run loop pass. The Qt
// APIs on the other hand document eg. zero-interval timers to always be
// handled after processing all available window-system events.
- qEventDispatcherDebug() << "Manually processing timers due to overdue timer";
+ qCDebug(lcEventDispatcher) << "Manually processing timers due to overdue timer";
processTimers(0);
eventsProcessed = true;
}
@@ -372,7 +366,7 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag
if (m_processEvents.deferredWakeUp) {
m_postedEventsRunLoopSource.signal();
- qEventDispatcherDebug() << "Processed deferred wake-up";
+ qCDebug(lcEventDispatcher) << "Processed deferred wake-up";
}
bool wasInterrupted = m_processEvents.wasInterrupted;
@@ -385,11 +379,11 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag
// others below it (eg, in the case of nested event loops). We need to trigger
// another interrupt so that the parent processEvents call has a chance to check
// if it should continue.
- qEventDispatcherDebug() << "Forwarding interrupt in case of nested processEvents";
+ qCDebug(lcEventDispatcher) << "Forwarding interrupt in case of nested processEvents";
interrupt();
}
- qEventDispatcherDebug() << "Returning with eventsProcessed = " << eventsProcessed; qUnIndent();
+ qCDebug(lcEventDispatcher) << "Returning with eventsProcessed =" << eventsProcessed;
return eventsProcessed;
}
@@ -397,15 +391,14 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag
bool QEventDispatcherCoreFoundation::processPostedEvents()
{
if (m_processEvents.processedPostedEvents && !(m_processEvents.flags & QEventLoop::EventLoopExec)) {
- qEventDispatcherDebug() << "Already processed events this pass";
+ qCDebug(lcEventDispatcher) << "Already processed events this pass";
return false;
}
m_processEvents.processedPostedEvents = true;
- qEventDispatcherDebug() << "Sending posted events for " << m_processEvents.flags; qIndent();
+ qCDebug(lcEventDispatcher) << "Sending posted events for" << m_processEvents.flags;
QCoreApplication::sendPostedEvents();
- qUnIndent();
return true;
}
@@ -413,12 +406,12 @@ bool QEventDispatcherCoreFoundation::processPostedEvents()
void QEventDispatcherCoreFoundation::processTimers(CFRunLoopTimerRef timer)
{
if (m_processEvents.processedTimers && !(m_processEvents.flags & QEventLoop::EventLoopExec)) {
- qEventDispatcherDebug() << "Already processed timers this pass";
+ qCDebug(lcEventDispatcher) << "Already processed timers this pass";
m_processEvents.deferredUpdateTimers = true;
return;
}
- qEventDispatcherDebug() << "CFRunLoopTimer " << timer << " fired, activating Qt timers"; qIndent();
+ qCDebug(lcEventDispatcher) << "CFRunLoopTimer" << timer << "fired, activating Qt timers";
// Activating Qt timers might recurse into processEvents() if a timer-callback
// brings up a new event-loop or tries to processes events manually. Although
@@ -436,15 +429,15 @@ void QEventDispatcherCoreFoundation::processTimers(CFRunLoopTimerRef timer)
m_blockedRunLoopTimer = previouslyBlockedRunLoopTimer;
m_processEvents.processedTimers = true;
- qUnIndent();
-
// Now that the timer source is unblocked we may need to schedule it again
updateTimers();
}
+Q_LOGGING_CATEGORY(lcEventDispatcherActivity, "qt.eventdispatcher.activity")
+
void QEventDispatcherCoreFoundation::handleRunLoopActivity(CFRunLoopActivity activity)
{
- qEventDispatcherDebug() << qPrintableActivity(activity);
+ qCDebug(lcEventDispatcherActivity) << "Runloop entered activity" << qPrintableActivity(activity);
switch (activity) {
case kCFRunLoopBeforeWaiting:
@@ -463,13 +456,11 @@ void QEventDispatcherCoreFoundation::handleRunLoopActivity(CFRunLoopActivity act
case kCFRunLoopAfterWaiting:
emit awake();
break;
-#if DEBUG_EVENT_DISPATCHER
case kCFRunLoopEntry:
case kCFRunLoopBeforeTimers:
case kCFRunLoopBeforeSources:
case kCFRunLoopExit:
break;
-#endif
default:
Q_UNREACHABLE();
}
@@ -502,19 +493,19 @@ void QEventDispatcherCoreFoundation::wakeUp()
// posted event gets processed on the next processEvents() call, so we flag the
// need to do a deferred wake-up.
m_processEvents.deferredWakeUp = true;
- qEventDispatcherDebug() << "Already processed posted events, deferring wakeUp";
+ qCDebug(lcEventDispatcher) << "Already processed posted events, deferring wakeUp";
return;
}
m_postedEventsRunLoopSource.signal();
CFRunLoopWakeUp(CFRunLoopGetMain());
- qEventDispatcherDebug() << "Signaled posted event run-loop source";
+ qCDebug(lcEventDispatcher) << "Signaled posted event run-loop source";
}
void QEventDispatcherCoreFoundation::interrupt()
{
- qEventDispatcherDebug() << "Marking current processEvent as interrupted";
+ qCDebug(lcEventDispatcher) << "Marking current processEvent as interrupted";
m_processEvents.wasInterrupted = true;
CFRunLoopStop(CFRunLoopGetMain());
}
@@ -540,8 +531,8 @@ void QEventDispatcherCoreFoundation::unregisterSocketNotifier(QSocketNotifier *n
void QEventDispatcherCoreFoundation::registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object)
{
- qEventDispatcherDebug() << "id = " << timerId << ", interval = " << interval
- << ", type = " << timerType << ", object = " << object;
+ qCDebug(lcEventDispatcherTimers) << "Registering timer with id =" << timerId << "interval =" << interval
+ << "type =" << timerType << "object =" << object;
Q_ASSERT(timerId > 0 && interval >= 0 && object);
Q_ASSERT(object->thread() == thread() && thread() == QThread::currentThread());
@@ -557,7 +548,7 @@ bool QEventDispatcherCoreFoundation::unregisterTimer(int timerId)
bool returnValue = m_timerInfoList.unregisterTimer(timerId);
- qEventDispatcherDebug() << "id = " << timerId << ", timers left: " << m_timerInfoList.size();
+ qCDebug(lcEventDispatcherTimers) << "Unegistered timer with id =" << timerId << "Timers left:" << m_timerInfoList.size();
updateTimers();
return returnValue;
@@ -569,7 +560,7 @@ bool QEventDispatcherCoreFoundation::unregisterTimers(QObject *object)
bool returnValue = m_timerInfoList.unregisterTimers(object);
- qEventDispatcherDebug() << "object = " << object << ", timers left: " << m_timerInfoList.size();
+ qCDebug(lcEventDispatcherTimers) << "Unegistered timers for object =" << object << "Timers left:" << m_timerInfoList.size();
updateTimers();
return returnValue;
@@ -612,16 +603,16 @@ void QEventDispatcherCoreFoundation::updateTimers()
});
CFRunLoopAddTimer(CFRunLoopGetMain(), m_runLoopTimer, kCFRunLoopCommonModes);
- qEventDispatcherDebug() << "Created new CFRunLoopTimer " << m_runLoopTimer;
+ qCDebug(lcEventDispatcherTimers) << "Created new CFRunLoopTimer" << m_runLoopTimer;
} else {
CFRunLoopTimerSetNextFireDate(m_runLoopTimer, timeToFire);
- qEventDispatcherDebug() << "Re-scheduled CFRunLoopTimer " << m_runLoopTimer;
+ qCDebug(lcEventDispatcherTimers) << "Re-scheduled CFRunLoopTimer" << m_runLoopTimer;
}
m_overdueTimerScheduled = !timespecToSeconds(tv);
- qEventDispatcherDebug() << "Next timeout in " << tv << " seconds";
+ qCDebug(lcEventDispatcherTimers) << "Next timeout in" << tv << "seconds";
} else {
// No Qt timers are registered, so make sure we're not running any CF timers
@@ -637,7 +628,7 @@ void QEventDispatcherCoreFoundation::invalidateTimer()
return;
CFRunLoopTimerInvalidate(m_runLoopTimer);
- qEventDispatcherDebug() << "Invalidated CFRunLoopTimer " << m_runLoopTimer;
+ qCDebug(lcEventDispatcherTimers) << "Invalidated CFRunLoopTimer" << m_runLoopTimer;
CFRelease(m_runLoopTimer);
m_runLoopTimer = 0;
diff --git a/src/corelib/kernel/qeventdispatcher_cf_p.h b/src/corelib/kernel/qeventdispatcher_cf_p.h
index 8a234ebc40..a607ab7a15 100644
--- a/src/corelib/kernel/qeventdispatcher_cf_p.h
+++ b/src/corelib/kernel/qeventdispatcher_cf_p.h
@@ -85,19 +85,22 @@
// We mean it.
//
-#define DEBUG_EVENT_DISPATCHER 0
-
#include <QtCore/qabstracteventdispatcher.h>
#include <QtCore/private/qtimerinfo_unix_p.h>
#include <QtCore/private/qcfsocketnotifier_p.h>
#include <QtCore/private/qcore_mac_p.h>
#include <QtCore/qdebug.h>
+#include <QtCore/qloggingcategory.h>
+
#include <CoreFoundation/CoreFoundation.h>
Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(RunLoopModeTracker));
QT_BEGIN_NAMESPACE
+Q_DECLARE_LOGGING_CATEGORY(lcEventDispatcher);
+Q_DECLARE_LOGGING_CATEGORY(lcEventDispatcherTimers)
+
class QEventDispatcherCoreFoundation;
template <class T = QEventDispatcherCoreFoundation>
@@ -269,17 +272,4 @@ private:
QT_END_NAMESPACE
-#if DEBUG_EVENT_DISPATCHER
-extern uint g_eventDispatcherIndentationLevel;
-#define qEventDispatcherDebug() qDebug().nospace() \
- << qPrintable(QString(QLatin1String("| ")).repeated(g_eventDispatcherIndentationLevel)) \
- << __FUNCTION__ << "(): "
-#define qIndent() ++g_eventDispatcherIndentationLevel
-#define qUnIndent() --g_eventDispatcherIndentationLevel
-#else
-#define qEventDispatcherDebug() QT_NO_QDEBUG_MACRO()
-#define qIndent()
-#define qUnIndent()
-#endif
-
#endif // QEVENTDISPATCHER_CF_P_H
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index 6fcc6b8d30..7ccacd883f 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -3892,6 +3892,19 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p)
\sa setValue(), value()
*/
+/*! \fn static inline QVariant fromStdVariant(const std::variant<T, Types...> &value)
+ \since 5.11
+
+ Returns a QVariant with the type and value of the active variant of \a value. If
+ the active type is std::monostate a default QVariant is returned.
+
+ \note With this method you do not need to register the variant as a Qt metatype,
+ since the std::variant is resolved before being stored. The component types
+ should be registered however.
+
+ \sa fromValue()
+*/
+
/*!
\fn template<typename T> QVariant qVariantFromValue(const T &value)
\relates QVariant
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index 29e67e9dd8..fe1ef1bdfc 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -53,6 +53,10 @@
#include <QtCore/qbytearraylist.h>
#endif
+#if QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L
+#include <variant>
+#endif
+
QT_BEGIN_NAMESPACE
@@ -355,6 +359,16 @@ class Q_CORE_EXPORT QVariant
static inline QVariant fromValue(const T &value)
{ return qVariantFromValue(value); }
+#if QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L
+ template<typename... Types>
+ static inline QVariant fromStdVariant(const std::variant<Types...> &value)
+ {
+ if (value.valueless_by_exception())
+ return QVariant();
+ return std::visit([](const auto &arg) { return fromValue(arg); }, value);
+ }
+#endif
+
template<typename T>
bool canConvert() const
{ return canConvert(qMetaTypeId<T>()); }
@@ -503,6 +517,11 @@ inline QVariant qVariantFromValue(const T &t)
template <>
inline QVariant qVariantFromValue(const QVariant &t) { return t; }
+#if QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L
+template <>
+inline QVariant qVariantFromValue(const std::monostate &) { return QVariant(); }
+#endif
+
template <typename T>
inline void qVariantSetValue(QVariant &v, const T &t)
{
diff --git a/src/corelib/mimetypes/qmimetype.cpp b/src/corelib/mimetypes/qmimetype.cpp
index 8f6237c1cb..d7590ecf1f 100644
--- a/src/corelib/mimetypes/qmimetype.cpp
+++ b/src/corelib/mimetypes/qmimetype.cpp
@@ -466,6 +466,8 @@ QStringList QMimeType::suffixes() const
*/
QString QMimeType::preferredSuffix() const
{
+ if (isDefault()) // workaround for unwanted *.bin suffix for octet-stream, https://bugs.freedesktop.org/show_bug.cgi?id=101667, fixed upstream in 1.10
+ return QString();
const QStringList suffixList = suffixes();
return suffixList.isEmpty() ? QString() : suffixList.at(0);
}
diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp
index 0cc193c325..a4be18a67f 100644
--- a/src/corelib/plugin/qfactoryloader.cpp
+++ b/src/corelib/plugin/qfactoryloader.cpp
@@ -54,6 +54,8 @@
#include "qjsonobject.h"
#include "qjsonarray.h"
+#include <qtcore_tracepoints_p.h>
+
QT_BEGIN_NAMESPACE
class QFactoryLoaderPrivate : public QObjectPrivate
@@ -142,6 +144,9 @@ void QFactoryLoader::update()
if (qt_debug_component()) {
qDebug() << "QFactoryLoader::QFactoryLoader() looking at" << fileName;
}
+
+ Q_TRACE(qfactoryloader_update, fileName);
+
library = QLibraryPrivate::findOrCreate(QFileInfo(fileName).canonicalFilePath());
if (!library->isPlugin()) {
if (qt_debug_component()) {
diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp
index ebad7f1751..bca6918b4a 100644
--- a/src/corelib/plugin/qlibrary.cpp
+++ b/src/corelib/plugin/qlibrary.cpp
@@ -64,6 +64,8 @@
#include "qelfparser_p.h"
#include "qmachparser_p.h"
+#include <qtcore_tracepoints_p.h>
+
QT_BEGIN_NAMESPACE
#ifdef QT_NO_DEBUG
@@ -535,6 +537,8 @@ bool QLibraryPrivate::load()
if (fileName.isEmpty())
return false;
+ Q_TRACE(qlibraryprivate_load_entry, fileName);
+
bool ret = load_sys();
if (qt_debug_component()) {
if (ret) {
@@ -551,6 +555,8 @@ bool QLibraryPrivate::load()
installCoverageTool(this);
}
+ Q_TRACE(qlibraryprivate_load_exit, ret);
+
return ret;
}
diff --git a/src/corelib/plugin/quuid.cpp b/src/corelib/plugin/quuid.cpp
index 4d658e064c..b113ca13ce 100644
--- a/src/corelib/plugin/quuid.cpp
+++ b/src/corelib/plugin/quuid.cpp
@@ -149,7 +149,6 @@ static QUuid _q_uuidFromHex(const char *src)
return QUuid();
}
-#ifndef QT_BOOTSTRAPPED
static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCryptographicHash::Algorithm algorithm, int version)
{
QByteArray hashResult;
@@ -172,7 +171,6 @@ static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCrypto
return result;
}
-#endif
/*!
\class QUuid
@@ -510,12 +508,12 @@ QUuid QUuid::createUuidV3(const QUuid &ns, const QByteArray &baseData)
{
return createFromName(ns, baseData, QCryptographicHash::Md5, 3);
}
+#endif
QUuid QUuid::createUuidV5(const QUuid &ns, const QByteArray &baseData)
{
return createFromName(ns, baseData, QCryptographicHash::Sha1, 5);
}
-#endif
/*!
Creates a QUuid object from the binary representation of the UUID, as
diff --git a/src/corelib/plugin/quuid.h b/src/corelib/plugin/quuid.h
index 27a84b4e01..08a1843640 100644
--- a/src/corelib/plugin/quuid.h
+++ b/src/corelib/plugin/quuid.h
@@ -201,18 +201,20 @@ public:
static QUuid createUuid();
#ifndef QT_BOOTSTRAPPED
static QUuid createUuidV3(const QUuid &ns, const QByteArray &baseData);
+#endif
static QUuid createUuidV5(const QUuid &ns, const QByteArray &baseData);
+#ifndef QT_BOOTSTRAPPED
static inline QUuid createUuidV3(const QUuid &ns, const QString &baseData)
{
return QUuid::createUuidV3(ns, baseData.toUtf8());
}
+#endif
static inline QUuid createUuidV5(const QUuid &ns, const QString &baseData)
{
return QUuid::createUuidV5(ns, baseData.toUtf8());
}
-#endif
QUuid::Variant variant() const Q_DECL_NOTHROW;
QUuid::Version version() const Q_DECL_NOTHROW;
diff --git a/src/corelib/qtcore.tracepoints b/src/corelib/qtcore.tracepoints
new file mode 100644
index 0000000000..e6b666ac74
--- /dev/null
+++ b/src/corelib/qtcore.tracepoints
@@ -0,0 +1,5 @@
+qcoreapplicationprivate_init_entry()
+qcoreapplicationprivate_init_exit()
+qfactoryloader_update(const QString &fileName)
+qlibraryprivate_load_entry(const QString &fileName)
+qlibraryprivate_load_exit(bool success)
diff --git a/src/corelib/xml/.gitignore b/src/corelib/serialization/.gitignore
index 89f9ac04aa..89f9ac04aa 100644
--- a/src/corelib/xml/.gitignore
+++ b/src/corelib/serialization/.gitignore
diff --git a/src/corelib/xml/make-parser.sh b/src/corelib/serialization/make-xml-parser.sh
index 0296e4c22b..0296e4c22b 100755
--- a/src/corelib/xml/make-parser.sh
+++ b/src/corelib/serialization/make-xml-parser.sh
diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/serialization/qdatastream.cpp
index 8f419a4a46..8f419a4a46 100644
--- a/src/corelib/io/qdatastream.cpp
+++ b/src/corelib/serialization/qdatastream.cpp
diff --git a/src/corelib/io/qdatastream.h b/src/corelib/serialization/qdatastream.h
index 1f1b13686c..1f1b13686c 100644
--- a/src/corelib/io/qdatastream.h
+++ b/src/corelib/serialization/qdatastream.h
diff --git a/src/corelib/io/qdatastream_p.h b/src/corelib/serialization/qdatastream_p.h
index 3ca0ae840e..3ca0ae840e 100644
--- a/src/corelib/io/qdatastream_p.h
+++ b/src/corelib/serialization/qdatastream_p.h
diff --git a/src/corelib/json/qjson.cpp b/src/corelib/serialization/qjson.cpp
index e4bca3bcd0..e4bca3bcd0 100644
--- a/src/corelib/json/qjson.cpp
+++ b/src/corelib/serialization/qjson.cpp
diff --git a/src/corelib/json/qjson_p.h b/src/corelib/serialization/qjson_p.h
index 131528376b..7743382806 100644
--- a/src/corelib/json/qjson_p.h
+++ b/src/corelib/serialization/qjson_p.h
@@ -154,14 +154,7 @@ static inline bool useCompressed(const QString &s)
{
if (s.length() >= 0x8000)
return false;
- const ushort *uc = (const ushort *)s.constData();
- const ushort *e = uc + s.length();
- while (uc < e) {
- if (*uc > 0xff)
- return false;
- ++uc;
- }
- return true;
+ return QtPrivate::isLatin1(s);
}
static inline int qStringSize(const QString &string, bool compress)
diff --git a/src/corelib/json/qjsonarray.cpp b/src/corelib/serialization/qjsonarray.cpp
index c5a5aaf39d..c5a5aaf39d 100644
--- a/src/corelib/json/qjsonarray.cpp
+++ b/src/corelib/serialization/qjsonarray.cpp
diff --git a/src/corelib/json/qjsonarray.h b/src/corelib/serialization/qjsonarray.h
index 8d41138c97..8d41138c97 100644
--- a/src/corelib/json/qjsonarray.h
+++ b/src/corelib/serialization/qjsonarray.h
diff --git a/src/corelib/json/qjsondocument.cpp b/src/corelib/serialization/qjsondocument.cpp
index 9794bca60d..9794bca60d 100644
--- a/src/corelib/json/qjsondocument.cpp
+++ b/src/corelib/serialization/qjsondocument.cpp
diff --git a/src/corelib/json/qjsondocument.h b/src/corelib/serialization/qjsondocument.h
index b784890c54..b784890c54 100644
--- a/src/corelib/json/qjsondocument.h
+++ b/src/corelib/serialization/qjsondocument.h
diff --git a/src/corelib/json/qjsonobject.cpp b/src/corelib/serialization/qjsonobject.cpp
index 4a316c8a6f..4a316c8a6f 100644
--- a/src/corelib/json/qjsonobject.cpp
+++ b/src/corelib/serialization/qjsonobject.cpp
diff --git a/src/corelib/json/qjsonobject.h b/src/corelib/serialization/qjsonobject.h
index 610bce694c..610bce694c 100644
--- a/src/corelib/json/qjsonobject.h
+++ b/src/corelib/serialization/qjsonobject.h
diff --git a/src/corelib/json/qjsonparser.cpp b/src/corelib/serialization/qjsonparser.cpp
index 39738b90a8..39738b90a8 100644
--- a/src/corelib/json/qjsonparser.cpp
+++ b/src/corelib/serialization/qjsonparser.cpp
diff --git a/src/corelib/json/qjsonparser_p.h b/src/corelib/serialization/qjsonparser_p.h
index 379256847f..379256847f 100644
--- a/src/corelib/json/qjsonparser_p.h
+++ b/src/corelib/serialization/qjsonparser_p.h
diff --git a/src/corelib/json/qjsonvalue.cpp b/src/corelib/serialization/qjsonvalue.cpp
index 33707b6ec3..33707b6ec3 100644
--- a/src/corelib/json/qjsonvalue.cpp
+++ b/src/corelib/serialization/qjsonvalue.cpp
diff --git a/src/corelib/json/qjsonvalue.h b/src/corelib/serialization/qjsonvalue.h
index 96538ebbf9..96538ebbf9 100644
--- a/src/corelib/json/qjsonvalue.h
+++ b/src/corelib/serialization/qjsonvalue.h
diff --git a/src/corelib/json/qjsonwriter.cpp b/src/corelib/serialization/qjsonwriter.cpp
index 12ce20ef09..12ce20ef09 100644
--- a/src/corelib/json/qjsonwriter.cpp
+++ b/src/corelib/serialization/qjsonwriter.cpp
diff --git a/src/corelib/json/qjsonwriter_p.h b/src/corelib/serialization/qjsonwriter_p.h
index 76a8460449..76a8460449 100644
--- a/src/corelib/json/qjsonwriter_p.h
+++ b/src/corelib/serialization/qjsonwriter_p.h
diff --git a/src/corelib/io/qtextstream.cpp b/src/corelib/serialization/qtextstream.cpp
index ee3cb4efcb..ee3cb4efcb 100644
--- a/src/corelib/io/qtextstream.cpp
+++ b/src/corelib/serialization/qtextstream.cpp
diff --git a/src/corelib/io/qtextstream.h b/src/corelib/serialization/qtextstream.h
index ee0b09419d..ee0b09419d 100644
--- a/src/corelib/io/qtextstream.h
+++ b/src/corelib/serialization/qtextstream.h
diff --git a/src/corelib/io/qtextstream_p.h b/src/corelib/serialization/qtextstream_p.h
index a642beddc4..a642beddc4 100644
--- a/src/corelib/io/qtextstream_p.h
+++ b/src/corelib/serialization/qtextstream_p.h
diff --git a/src/corelib/xml/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp
index 9b5295a17e..a92dd71df5 100644
--- a/src/corelib/xml/qxmlstream.cpp
+++ b/src/corelib/serialization/qxmlstream.cpp
@@ -409,6 +409,11 @@ QXmlStreamReader::QXmlStreamReader(const QByteArray &data)
/*!
Creates a new stream reader that reads from \a data.
+ This function should only be used if the XML header either says the encoding
+ is "UTF-8" or lacks any encoding information (the latter is the case of
+ QXmlStreamWriter writing to a QString). Any other encoding is likely going to
+ cause data corruption ("mojibake").
+
\sa addData(), clear(), setDevice()
*/
QXmlStreamReader::QXmlStreamReader(const QString &data)
@@ -3268,6 +3273,9 @@ QXmlStreamWriter::QXmlStreamWriter(QByteArray *array)
/*! Constructs a stream writer that writes into \a string.
+ *
+ * Note that when writing to QString, QXmlStreamWriter ignores the codec set
+ * with setCodec(). See that function for more information.
*/
QXmlStreamWriter::QXmlStreamWriter(QString *string)
: d_ptr(new QXmlStreamWriterPrivate(this))
@@ -3326,6 +3334,12 @@ QIODevice *QXmlStreamWriter::device() const
gets written when you call writeStartDocument(). Call this
function before calling writeStartDocument().
+ \note When writing the XML to a QString, the codec information is ignored
+ and the XML header will not include any encoding information, since all
+ QStrings are UTF-16. If you later convert the QString to an 8-bit format,
+ you must arrange for the encoding information to be transmitted
+ out-of-band.
+
\sa codec()
*/
void QXmlStreamWriter::setCodec(QTextCodec *codec)
@@ -3345,6 +3359,12 @@ void QXmlStreamWriter::setCodec(QTextCodec *codec)
"ISO 8859-1", "UTF-8", and "UTF-16". If the encoding isn't
recognized, nothing happens.
+ \note When writing the XML to a QString, the codec information is ignored
+ and the XML header will not include any encoding information, since all
+ QStrings are UTF-16. If you later convert the QString to an 8-bit format,
+ you must arrange for the encoding information to be transmitted
+ out-of-band.
+
\sa QTextCodec::codecForName()
*/
void QXmlStreamWriter::setCodec(const char *codecName)
diff --git a/src/corelib/xml/qxmlstream.g b/src/corelib/serialization/qxmlstream.g
index fd69a6e4af..fd69a6e4af 100644
--- a/src/corelib/xml/qxmlstream.g
+++ b/src/corelib/serialization/qxmlstream.g
diff --git a/src/corelib/xml/qxmlstream.h b/src/corelib/serialization/qxmlstream.h
index 2350d12dd6..2350d12dd6 100644
--- a/src/corelib/xml/qxmlstream.h
+++ b/src/corelib/serialization/qxmlstream.h
diff --git a/src/corelib/xml/qxmlstream_p.h b/src/corelib/serialization/qxmlstream_p.h
index 5645d812eb..5645d812eb 100644
--- a/src/corelib/xml/qxmlstream_p.h
+++ b/src/corelib/serialization/qxmlstream_p.h
diff --git a/src/corelib/xml/qxmlutils.cpp b/src/corelib/serialization/qxmlutils.cpp
index 01c84251fd..01c84251fd 100644
--- a/src/corelib/xml/qxmlutils.cpp
+++ b/src/corelib/serialization/qxmlutils.cpp
diff --git a/src/corelib/xml/qxmlutils_p.h b/src/corelib/serialization/qxmlutils_p.h
index db6bddd5be..db6bddd5be 100644
--- a/src/corelib/xml/qxmlutils_p.h
+++ b/src/corelib/serialization/qxmlutils_p.h
diff --git a/src/corelib/serialization/serialization.pri b/src/corelib/serialization/serialization.pri
new file mode 100644
index 0000000000..3d039dc30f
--- /dev/null
+++ b/src/corelib/serialization/serialization.pri
@@ -0,0 +1,30 @@
+# Qt data formats core module
+
+HEADERS += \
+ serialization/qdatastream.h \
+ serialization/qdatastream_p.h \
+ serialization/qjson_p.h \
+ serialization/qjsondocument.h \
+ serialization/qjsonobject.h \
+ serialization/qjsonvalue.h \
+ serialization/qjsonarray.h \
+ serialization/qjsonwriter_p.h \
+ serialization/qjsonparser_p.h \
+ serialization/qtextstream.h \
+ serialization/qtextstream_p.h \
+ serialization/qxmlstream.h \
+ serialization/qxmlstream_p.h \
+ serialization/qxmlutils_p.h
+
+SOURCES += \
+ serialization/qdatastream.cpp \
+ serialization/qjson.cpp \
+ serialization/qjsondocument.cpp \
+ serialization/qjsonobject.cpp \
+ serialization/qjsonarray.cpp \
+ serialization/qjsonvalue.cpp \
+ serialization/qjsonwriter.cpp \
+ serialization/qjsonparser.cpp \
+ serialization/qtextstream.cpp \
+ serialization/qxmlstream.cpp \
+ serialization/qxmlutils.cpp
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp
index fb5c9fd770..1bb8e613e0 100644
--- a/src/corelib/thread/qthread_unix.cpp
+++ b/src/corelib/thread/qthread_unix.cpp
@@ -311,16 +311,14 @@ void QThreadPrivate::createEventDispatcher(QThreadData *data)
#ifndef QT_NO_THREAD
#if (defined(Q_OS_LINUX) || defined(Q_OS_MAC) || defined(Q_OS_QNX))
-static void setCurrentThreadName(pthread_t threadId, const char *name)
+static void setCurrentThreadName(const char *name)
{
# if defined(Q_OS_LINUX) && !defined(QT_LINUXBASE)
- Q_UNUSED(threadId);
prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0);
# elif defined(Q_OS_MAC)
- Q_UNUSED(threadId);
pthread_setname_np(name);
# elif defined(Q_OS_QNX)
- pthread_setname_np(threadId, name);
+ pthread_setname_np(pthread_self(), name);
# endif
}
#endif
@@ -361,14 +359,13 @@ void *QThreadPrivate::start(void *arg)
#if (defined(Q_OS_LINUX) || defined(Q_OS_MAC) || defined(Q_OS_QNX))
{
- // sets the name of the current thread.
- QString objectName = thr->objectName();
-
- pthread_t thread_id = from_HANDLE<pthread_t>(data->threadId.load());
- if (Q_LIKELY(objectName.isEmpty()))
- setCurrentThreadName(thread_id, thr->metaObject()->className());
+ // Sets the name of the current thread. We can only do this
+ // when the thread is starting, as we don't have a cross
+ // platform way of setting the name of an arbitrary thread.
+ if (Q_LIKELY(thr->objectName().isEmpty()))
+ setCurrentThreadName(thr->metaObject()->className());
else
- setCurrentThreadName(thread_id, objectName.toLocal8Bit());
+ setCurrentThreadName(thr->objectName().toLocal8Bit());
}
#endif
diff --git a/src/corelib/tools/qbitarray.cpp b/src/corelib/tools/qbitarray.cpp
index 12e4687b3c..f68a807203 100644
--- a/src/corelib/tools/qbitarray.cpp
+++ b/src/corelib/tools/qbitarray.cpp
@@ -300,6 +300,46 @@ void QBitArray::fill(bool value, int begin, int end)
setBit(begin++, value);
}
+/*!
+ \fn const char *QBitArray::bits() const
+ \since 5.11
+
+ Returns a pointer to a dense bit array for this QBitArray. Bits are counted
+ upwards from the least significant bit in each byte. The the number of bits
+ relevant in the last byte is given by \c{size() % 8}.
+
+ \sa fromBits(), size()
+ */
+
+/*!
+ \since 5.11
+
+ Creates a QBitArray with the dense bit array located at \a data, with \a
+ len bits. The byte array at \a data must be at least \a size / 8 (rounded up)
+ bytes long.
+
+ If \a size is not a multiple of 8, this function will include the lowest
+ \a size % 8 bits from the last byte in \a data.
+
+ \sa bits()
+ */
+QBitArray QBitArray::fromBits(const char *data, qsizetype size)
+{
+ QBitArray result;
+ qsizetype nbytes = (size + 7) / 8;
+
+ result.d = QByteArray(nbytes + 1, Qt::Uninitialized);
+ char *bits = result.d.data();
+ memcpy(bits + 1, data, nbytes);
+
+ // clear any unused bits from the last byte
+ if (size & 7)
+ bits[nbytes] &= 0xffU >> (size & 7);
+
+ *bits = result.d.size() * 8 - size;
+ return result;
+}
+
/*! \fn bool QBitArray::isDetached() const
\internal
diff --git a/src/corelib/tools/qbitarray.h b/src/corelib/tools/qbitarray.h
index 8fa5323127..ff40bf5654 100644
--- a/src/corelib/tools/qbitarray.h
+++ b/src/corelib/tools/qbitarray.h
@@ -104,6 +104,9 @@ public:
inline void truncate(int pos) { if (pos < size()) resize(pos); }
+ const char *bits() const { return isEmpty() ? nullptr : d.constData() + 1; }
+ static QBitArray fromBits(const char *data, qsizetype len);
+
public:
typedef QByteArray::DataPtr DataPtr;
inline DataPtr &data_ptr() { return d.data_ptr(); }
diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h
index fafc3e37b0..eb56b31348 100644
--- a/src/corelib/tools/qsimd_p.h
+++ b/src/corelib/tools/qsimd_p.h
@@ -177,55 +177,37 @@
# define QT_FUNCTION_TARGET(x)
#endif
-#if defined(Q_CC_MSVC) && (defined(_M_AVX) || defined(__AVX__))
-// Visual Studio defines __AVX__ when /arch:AVX is passed, but not the earlier macros
-// See: https://msdn.microsoft.com/en-us/library/b0084kay.aspx
-// SSE2 is handled by _M_IX86_FP below
-# define __SSE3__ 1
-# define __SSSE3__ 1
-// no Intel CPU supports SSE4a, so don't define it
-# define __SSE4_1__ 1
-# define __SSE4_2__ 1
-# ifndef __AVX__
-# define __AVX__ 1
-# endif
-#endif
-
-// SSE intrinsics
-#if defined(__SSE2__) || (defined(QT_COMPILER_SUPPORTS_SSE2) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS))
-#if defined(QT_LINUXBASE)
-/// this is an evil hack - the posix_memalign declaration in LSB
-/// is wrong - see http://bugs.linuxbase.org/show_bug.cgi?id=2431
-# define posix_memalign _lsb_hack_posix_memalign
-# include <emmintrin.h>
-# undef posix_memalign
-#else
-# include <emmintrin.h>
-#endif
-#if defined(Q_CC_MSVC) && (defined(_M_X64) || _M_IX86_FP >= 2)
-# define __SSE__ 1
-# define __SSE2__ 1
-#endif
-#endif
+#ifdef Q_PROCESSOR_X86
+/* -- x86 intrinsic support -- */
-// SSE3 intrinsics
-#if defined(__SSE3__) || (defined(QT_COMPILER_SUPPORTS_SSE3) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS))
-#include <pmmintrin.h>
-#endif
+# if defined(Q_CC_MSVC) && (defined(_M_X64) || _M_IX86_FP >= 2)
+// MSVC doesn't define __SSE2__, so do it ourselves
+# define __SSE__ 1
+# define __SSE2__ 1
+# endif
-// SSSE3 intrinsics
-#if defined(__SSSE3__) || (defined(QT_COMPILER_SUPPORTS_SSSE3) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS))
-#include <tmmintrin.h>
-#endif
+# ifdef __SSE2__
+// #include the intrinsics
+# include <immintrin.h>
+# endif
-// SSE4.1 intrinsics
-#if defined(__SSE4_1__) || (defined(QT_COMPILER_SUPPORTS_SSE4_1) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS))
-#include <smmintrin.h>
-#endif
+# if defined(Q_CC_GNU) && !defined(Q_CC_INTEL)
+// GCC 4.4 and Clang 2.8 added a few more intrinsics there
+# include <x86intrin.h>
+# endif
-// SSE4.2 intrinsics
-#if defined(__SSE4_2__) || (defined(QT_COMPILER_SUPPORTS_SSE4_2) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS))
-#include <nmmintrin.h>
+# if defined(Q_CC_MSVC) && (defined(_M_AVX) || defined(__AVX__))
+// Visual Studio defines __AVX__ when /arch:AVX is passed, but not the earlier macros
+// See: https://msdn.microsoft.com/en-us/library/b0084kay.aspx
+# define __SSE3__ 1
+# define __SSSE3__ 1
+// no Intel CPU supports SSE4a, so don't define it
+# define __SSE4_1__ 1
+# define __SSE4_2__ 1
+# ifndef __AVX__
+# define __AVX__ 1
+# endif
+# endif
# if defined(__SSE4_2__) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS) && (defined(Q_CC_INTEL) || defined(Q_CC_MSVC))
// POPCNT instructions:
@@ -233,13 +215,8 @@
// (but neither MSVC nor the Intel compiler define this macro)
# define __POPCNT__ 1
# endif
-#endif
// AVX intrinsics
-#if defined(__AVX__) || (defined(QT_COMPILER_SUPPORTS_AVX) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS))
-// immintrin.h is the ultimate header, we don't need anything else after this
-#include <immintrin.h>
-
# if defined(__AVX__) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS) && (defined(Q_CC_INTEL) || defined(Q_CC_MSVC))
// AES, PCLMULQDQ instructions:
// All processors that support AVX support AES, PCLMULQDQ
@@ -255,11 +232,6 @@
# define __F16C__ 1
# define __RDRND__ 1
# endif
-#endif
-
-#if defined(__AES__) || defined(__PCLMUL__) || (defined(QT_COMPILER_SUPPORTS_AES) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS))
-# include <wmmintrin.h>
-#endif
#define QT_FUNCTION_TARGET_STRING_SSE2 "sse2"
#define QT_FUNCTION_TARGET_STRING_SSE3 "sse3"
@@ -288,19 +260,7 @@
#define QT_FUNCTION_TARGET_STRING_RDSEED "rdseed"
#define QT_FUNCTION_TARGET_STRING_SHA "sha"
-// other x86 intrinsics
-#if defined(Q_PROCESSOR_X86) && ((defined(Q_CC_GNU) && (Q_CC_GNU >= 404)) \
- || (defined(Q_CC_CLANG) && (Q_CC_CLANG >= 208)) \
- || defined(Q_CC_INTEL))
-# define QT_COMPILER_SUPPORTS_X86INTRIN
-# ifdef Q_CC_INTEL
-// The Intel compiler has no <x86intrin.h> -- all intrinsics are in <immintrin.h>;
-# include <immintrin.h>
-# else
-// GCC 4.4 and Clang 2.8 added a few more intrinsics there
-# include <x86intrin.h>
-# endif
-#endif
+#endif /* Q_PROCESSOR_X86 */
// Clang compiler fix, see http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20160222/151168.html
// This should be tweaked with an "upper version" of clang once we know which release fixes the
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 5eeaa2a2a8..4040d59b0a 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
+** Copyright (C) 2018 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -251,6 +251,151 @@ inline RetType UnrollTailLoop<0>::exec(Number, RetType returnIfExited, Functor1,
}
#endif
+#ifdef __SSE2__
+static bool simdTestMask(const char *&ptr, const char *end, quint32 maskval)
+{
+# if defined(__AVX2__)
+ // AVX2 implementation: test 32 bytes at a time
+ const __m256i mask256 = _mm256_broadcastd_epi32(_mm_cvtsi32_si128(maskval));
+ while (ptr + 32 < end) {
+ __m256i data = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(ptr));
+ if (!_mm256_testz_si256(mask256, data))
+ return false;
+ ptr += 32;
+ }
+
+ const __m128i mask = _mm256_castsi256_si128(mask256);
+# elif defined(__SSE4_1__)
+ // SSE 4.1 implementation: test 32 bytes at a time (two 16-byte
+ // comparisons, unrolled)
+ const __m128i mask = _mm_set1_epi32(maskval);
+ while (ptr + 32 < end) {
+ __m128i data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr));
+ __m128i data2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr + 16));
+ if (!_mm_testz_si128(mask, data1))
+ return false;
+ if (!_mm_testz_si128(mask, data2))
+ return false;
+ ptr += 32;
+ }
+# endif
+# if defined(__SSE4_1__)
+ // AVX2 and SSE4.1: final 16-byte comparison
+ if (ptr + 16 < end) {
+ __m128i data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr));
+ if (!_mm_testz_si128(mask, data1))
+ return false;
+ ptr += 16;
+ }
+# else
+ // SSE2 implementation: test 16 bytes at a time.
+ const __m128i mask = _mm_set1_epi32(maskval);
+ while (ptr + 16 < end) {
+ __m128i data = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr));
+ __m128i masked = _mm_andnot_si128(mask, data);
+ __m128i comparison = _mm_cmpeq_epi16(masked, _mm_setzero_si128());
+ if (quint16(_mm_movemask_epi8(comparison)) != 0xffff)
+ return false;
+ ptr += 16;
+ }
+# endif
+
+ return true;
+}
+#endif
+
+bool QtPrivate::isAscii(QLatin1String s) Q_DECL_NOTHROW
+{
+ const char *ptr = s.begin();
+ const char *end = s.end();
+
+#if defined(__AVX2__)
+ if (!simdTestMask(ptr, end, 0x80808080))
+ return false;
+#elif defined(__SSE2__)
+ // Testing for the high bit can be done efficiently with just PMOVMSKB
+ while (ptr + 16 < end) {
+ __m128i data = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr));
+ quint32 mask = _mm_movemask_epi8(data);
+ if (mask)
+ return false;
+ ptr += 16;
+ }
+#endif
+
+ while (ptr + 4 < end) {
+ quint32 data = qFromUnaligned<quint32>(ptr);
+ if (data & 0x80808080U)
+ return false;
+ ptr += 4;
+ }
+
+ while (ptr != end) {
+ if (quint8(*ptr++) & 0x80)
+ return false;
+ }
+ return true;
+}
+
+bool QtPrivate::isAscii(QStringView s) Q_DECL_NOTHROW
+{
+ const QChar *ptr = s.begin();
+ const QChar *end = s.end();
+
+#ifdef __SSE2__
+ const char *ptr8 = reinterpret_cast<const char *>(ptr);
+ const char *end8 = reinterpret_cast<const char *>(end);
+ if (!simdTestMask(ptr8, end8, 0xff80ff80))
+ return false;
+ ptr = reinterpret_cast<const QChar *>(ptr8);
+#endif
+
+ while (ptr != end) {
+ if ((*ptr++).unicode() & 0xff80)
+ return false;
+ }
+ return true;
+}
+
+bool QtPrivate::isLatin1(QStringView s) Q_DECL_NOTHROW
+{
+ const QChar *ptr = s.begin();
+ const QChar *end = s.end();
+
+#if defined(__SSE4_1__)
+ const char *ptr8 = reinterpret_cast<const char *>(ptr);
+ const char *end8 = reinterpret_cast<const char *>(end);
+ if (!simdTestMask(ptr8, end8, 0xff00ff00))
+ return false;
+ ptr = reinterpret_cast<const QChar *>(ptr8);
+#elif defined(__SSE2__)
+ // Testing if every other byte is non-zero can be done efficiently by
+ // using PUNPCKHBW (unpack high order bytes) and comparing that to zero.
+ while (ptr + 32 < end) {
+ __m128i data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr));
+ __m128i data2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr + 16));
+ __m128i high = _mm_unpackhi_epi8(data1, data2);
+ __m128i comparison = _mm_cmpeq_epi16(high, _mm_setzero_si128());
+ if (_mm_movemask_epi8(comparison))
+ return false;
+ ptr += 16;
+ }
+ if (ptr + 16 < end) {
+ __m128i data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr));
+ __m128i high = _mm_unpackhi_epi8(data1, data1);
+ __m128i comparison = _mm_cmpeq_epi16(high, _mm_setzero_si128());
+ if (_mm_movemask_epi8(comparison))
+ return false;
+ }
+#endif
+
+ while (ptr != end) {
+ if ((*ptr++).unicode() > 0xff)
+ return false;
+ }
+ return true;
+}
+
// conversion between Latin 1 and UTF-16
void qt_from_latin1(ushort *dst, const char *str, size_t size) Q_DECL_NOTHROW
{
@@ -2441,6 +2586,21 @@ QString &QString::remove(int pos, int len)
return *this;
}
+template<typename T>
+static void removeStringImpl(QString &s, const T &needle, Qt::CaseSensitivity cs)
+{
+ const int needleSize = needle.size();
+ if (needleSize) {
+ if (needleSize == 1) {
+ s.remove(needle.front(), cs);
+ } else {
+ int i = 0;
+ while ((i = s.indexOf(needle, i, cs)) != -1)
+ s.remove(i, needleSize);
+ }
+ }
+}
+
/*!
Removes every occurrence of the given \a str string in this
string, and returns a reference to this string.
@@ -2454,11 +2614,27 @@ QString &QString::remove(int pos, int len)
*/
QString &QString::remove(const QString &str, Qt::CaseSensitivity cs)
{
- if (str.d->size) {
- int i = 0;
- while ((i = indexOf(str, i, cs)) != -1)
- remove(i, str.d->size);
- }
+ removeStringImpl(*this, str, cs);
+ return *this;
+}
+
+/*!
+ \since 5.11
+ \overload
+
+ Removes every occurrence of the given \a str string in this
+ string, and returns a reference to this string.
+
+ If \a cs is Qt::CaseSensitive (default), the search is
+ case sensitive; otherwise the search is case insensitive.
+
+ This is the same as \c replace(str, "", cs).
+
+ \sa replace()
+*/
+QString &QString::remove(QLatin1String str, Qt::CaseSensitivity cs)
+{
+ removeStringImpl(*this, str, cs);
return *this;
}
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index 808f388c89..0138ae4098 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ -202,6 +202,12 @@ Q_DECLARE_TYPEINFO(QLatin1String, Q_MOVABLE_TYPE);
typedef QLatin1String QLatin1Literal;
//
+// QLatin1String inline implementations
+//
+inline bool QtPrivate::isLatin1(QLatin1String) Q_DECL_NOTHROW
+{ return true; }
+
+//
// QStringView members that require QLatin1String:
//
bool QStringView::startsWith(QLatin1String s, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
@@ -477,6 +483,7 @@ public:
QString &remove(int i, int len);
QString &remove(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive);
+ QString &remove(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive);
QString &remove(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive);
QString &replace(int i, int len, QChar after);
QString &replace(int i, int len, const QChar *s, int slen);
diff --git a/src/corelib/tools/qstringalgorithms.h b/src/corelib/tools/qstringalgorithms.h
index 6146e525d9..8446d85239 100644
--- a/src/corelib/tools/qstringalgorithms.h
+++ b/src/corelib/tools/qstringalgorithms.h
@@ -82,6 +82,11 @@ Q_REQUIRED_RESULT Q_CORE_EXPORT QByteArray convertToLocal8Bit(QStringView str);
Q_REQUIRED_RESULT Q_CORE_EXPORT QVector<uint> convertToUcs4(QStringView str);
Q_REQUIRED_RESULT Q_CORE_EXPORT bool isRightToLeft(QStringView string);
+Q_REQUIRED_RESULT Q_CORE_EXPORT bool isAscii(QLatin1String s) Q_DECL_NOTHROW;
+Q_REQUIRED_RESULT Q_CORE_EXPORT bool isAscii(QStringView s) Q_DECL_NOTHROW;
+Q_REQUIRED_RESULT bool isLatin1(QLatin1String s) Q_DECL_NOTHROW; // in qstring.h
+Q_REQUIRED_RESULT Q_CORE_EXPORT bool isLatin1(QStringView s) Q_DECL_NOTHROW;
+
} // namespace QtPRivate
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qvarlengtharray.qdoc b/src/corelib/tools/qvarlengtharray.qdoc
index aff2f986e6..336f2afaca 100644
--- a/src/corelib/tools/qvarlengtharray.qdoc
+++ b/src/corelib/tools/qvarlengtharray.qdoc
@@ -725,8 +725,7 @@
vector.
*/
-/*!
- \fn template<class T, int Prealloc> QVarLengthArray<T, Prealloc>::iterator QVarLengthArray<T, Prealloc>::insert(const_iterator before, const T &value)
+/*! \fn template<class T, int Prealloc> QVarLengthArray<T, Prealloc>::iterator QVarLengthArray<T, Prealloc>::insert(const_iterator before, const T &value)
\fn template<class T, int Prealloc> QVarLengthArray<T, Prealloc>::iterator QVarLengthArray<T, Prealloc>::insert(const_iterator before, T &&value)
\overload
diff --git a/src/corelib/tools/qvector.qdoc b/src/corelib/tools/qvector.qdoc
index 173bdb5abf..cc250b72a5 100644
--- a/src/corelib/tools/qvector.qdoc
+++ b/src/corelib/tools/qvector.qdoc
@@ -607,8 +607,7 @@
\sa append(), insert()
*/
-/*!
- \fn template <typename T> void QVector<T>::insert(int i, const T &value)
+/*! \fn template <typename T> void QVector<T>::insert(int i, const T &value)
\fn template <typename T> void QVector<T>::insert(int i, T &&value)
Inserts \a value at index position \a i in the vector. If \a i is
diff --git a/src/corelib/xml/xml.pri b/src/corelib/xml/xml.pri
deleted file mode 100644
index 2401c09ab7..0000000000
--- a/src/corelib/xml/xml.pri
+++ /dev/null
@@ -1,10 +0,0 @@
-# Qt xml core module
-
-HEADERS += \
- xml/qxmlstream.h \
- xml/qxmlstream_p.h \
- xml/qxmlutils_p.h
-
-SOURCES += \
- xml/qxmlstream.cpp \
- xml/qxmlutils.cpp
diff --git a/src/gui/gui.pro b/src/gui/gui.pro
index f8cec00b82..759d6f3cbf 100644
--- a/src/gui/gui.pro
+++ b/src/gui/gui.pro
@@ -95,3 +95,6 @@ qtConfig(angle) {
qtConfig(egl): CMAKE_EGL_INCDIRS = $$cmakePortablePaths($$QMAKE_INCDIR_EGL)
QMAKE_DYNAMIC_LIST_FILE = $$PWD/QtGui.dynlist
+
+TRACEPOINT_PROVIDER = $$PWD/qtgui.tracepoints
+CONFIG += qt_tracepoints
diff --git a/src/gui/itemmodels/qstandarditemmodel.cpp b/src/gui/itemmodels/qstandarditemmodel.cpp
index 519995e82a..d1e0604caf 100644
--- a/src/gui/itemmodels/qstandarditemmodel.cpp
+++ b/src/gui/itemmodels/qstandarditemmodel.cpp
@@ -278,8 +278,24 @@ void QStandardItemPrivate::setItemData(const QMap<int, QVariant> &roles)
if (newValues != values) {
values.swap(newValues);
- if (model)
- model->d_func()->itemChanged(q);
+ if (model) {
+ QVector<int> roleKeys;
+ roleKeys.reserve(roles.size() + 1);
+ bool hasEditRole = false;
+ bool hasDisplayRole = false;
+ for (auto it = roles.keyBegin(); it != roles.keyEnd(); ++it) {
+ roleKeys.push_back(*it);
+ if (*it == Qt::EditRole)
+ hasEditRole = true;
+ else if (*it == Qt::DisplayRole)
+ hasDisplayRole = true;
+ }
+ if (hasEditRole && !hasDisplayRole)
+ roleKeys.push_back(Qt::DisplayRole);
+ else if (!hasEditRole && hasDisplayRole)
+ roleKeys.push_back(Qt::EditRole);
+ model->d_func()->itemChanged(q, roleKeys);
+ }
}
}
@@ -554,7 +570,7 @@ bool QStandardItemPrivate::insertColumns(int column, int count, const QList<QSta
/*!
\internal
*/
-void QStandardItemModelPrivate::itemChanged(QStandardItem *item)
+void QStandardItemModelPrivate::itemChanged(QStandardItem *item, const QVector<int> &roles)
{
Q_Q(QStandardItemModel);
Q_ASSERT(item);
@@ -570,8 +586,8 @@ void QStandardItemModelPrivate::itemChanged(QStandardItem *item)
}
} else {
// Normal item
- QModelIndex index = q->indexFromItem(item);
- emit q->dataChanged(index, index);
+ const QModelIndex index = q->indexFromItem(item);
+ emit q->dataChanged(index, index, roles);
}
}
@@ -885,6 +901,9 @@ void QStandardItem::setData(const QVariant &value, int role)
{
Q_D(QStandardItem);
role = (role == Qt::EditRole) ? Qt::DisplayRole : role;
+ const QVector<int> roles((role == Qt::DisplayRole) ?
+ QVector<int>({Qt::DisplayRole, Qt::EditRole}) :
+ QVector<int>({role}));
QVector<QStandardItemData>::iterator it;
for (it = d->values.begin(); it != d->values.end(); ++it) {
if ((*it).role == role) {
@@ -896,13 +915,13 @@ void QStandardItem::setData(const QVariant &value, int role)
d->values.erase(it);
}
if (d->model)
- d->model->d_func()->itemChanged(this);
+ d->model->d_func()->itemChanged(this, roles);
return;
}
}
d->values.append(QStandardItemData(role, value));
if (d->model)
- d->model->d_func()->itemChanged(this);
+ d->model->d_func()->itemChanged(this, roles);
}
/*!
diff --git a/src/gui/itemmodels/qstandarditemmodel.h b/src/gui/itemmodels/qstandarditemmodel.h
index c54e7b27d9..d8f06b629a 100644
--- a/src/gui/itemmodels/qstandarditemmodel.h
+++ b/src/gui/itemmodels/qstandarditemmodel.h
@@ -419,6 +419,7 @@ public:
bool dropMimeData (const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
Q_SIGNALS:
+ // ### Qt 6: add changed roles
void itemChanged(QStandardItem *item);
protected:
diff --git a/src/gui/itemmodels/qstandarditemmodel_p.h b/src/gui/itemmodels/qstandarditemmodel_p.h
index caee3ea34c..bd28ec3029 100644
--- a/src/gui/itemmodels/qstandarditemmodel_p.h
+++ b/src/gui/itemmodels/qstandarditemmodel_p.h
@@ -200,7 +200,7 @@ public:
}
void sort(QStandardItem *parent, int column, Qt::SortOrder order);
- void itemChanged(QStandardItem *item);
+ void itemChanged(QStandardItem *item, const QVector<int> &roles = QVector<int>());
void rowsAboutToBeInserted(QStandardItem *parent, int start, int end);
void columnsAboutToBeInserted(QStandardItem *parent, int start, int end);
void rowsAboutToBeRemoved(QStandardItem *parent, int start, int end);
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index be8ce1a011..50d9bbb2cc 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -3761,14 +3761,25 @@ static inline void formatInputMethodEvent(QDebug d, const QInputMethodEvent *e)
static inline void formatInputMethodQueryEvent(QDebug d, const QInputMethodQueryEvent *e)
{
+ QDebugStateSaver saver(d);
+ d.noquote();
const Qt::InputMethodQueries queries = e->queries();
d << "QInputMethodQueryEvent(queries=" << showbase << hex << int(queries)
<< noshowbase << dec << ", {";
- for (unsigned mask = 1; mask <= Qt::ImTextAfterCursor; mask<<=1) {
+ for (unsigned mask = 1; mask <= Qt::ImInputItemClipRectangle; mask<<=1) {
if (queries & mask) {
- const QVariant value = e->value(static_cast<Qt::InputMethodQuery>(mask));
- if (value.isValid())
- d << '[' << showbase << hex << mask << noshowbase << dec << '=' << value << "],";
+ const Qt::InputMethodQuery query = static_cast<Qt::InputMethodQuery>(mask);
+ const QVariant value = e->value(query);
+ if (value.isValid()) {
+ d << '[';
+ QtDebugUtils::formatQEnum(d, query);
+ d << '=';
+ if (query == Qt::ImHints)
+ QtDebugUtils::formatQFlags(d, Qt::InputMethodHints(value.toInt()));
+ else
+ d << value.toString();
+ d << "],";
+ }
}
}
d << "})";
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 5f4a1a0236..055347500b 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -111,6 +111,8 @@
# include <QtCore/QLibraryInfo>
#endif // Q_OS_WIN
+#include <qtgui_tracepoints_p.h>
+
#include <ctype.h>
QT_BEGIN_NAMESPACE
@@ -1360,6 +1362,8 @@ void QGuiApplicationPrivate::eventDispatcherReady()
void QGuiApplicationPrivate::init()
{
+ Q_TRACE(qguiapplicationprivate_init_entry);
+
#if defined(Q_OS_MACOS)
QMacAutoReleasePool pool;
#endif
@@ -1522,6 +1526,8 @@ void QGuiApplicationPrivate::init()
if (!QGuiApplicationPrivate::displayName)
QObject::connect(q, &QGuiApplication::applicationNameChanged,
q, &QGuiApplication::applicationDisplayNameChanged);
+
+ Q_TRACE(qguiapplicationprivate_init_exit);
}
extern void qt_cleanupFontDatabase();
@@ -1756,6 +1762,8 @@ bool QGuiApplicationPrivate::processNativeEvent(QWindow *window, const QByteArra
void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e)
{
+ Q_TRACE(qguiapplicationprivate_processwsevents_entry, e->type);
+
switch(e->type) {
case QWindowSystemInterfacePrivate::Mouse:
QGuiApplicationPrivate::processMouseEvent(static_cast<QWindowSystemInterfacePrivate::MouseEvent *>(e));
@@ -1864,6 +1872,8 @@ void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePriv
qWarning() << "Unknown user input event type:" << e->type;
break;
}
+
+ Q_TRACE(qguiapplicationprivate_processwsevents_exit, e->type);
}
/*! \internal
diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp
index 151151de23..448d670209 100644
--- a/src/gui/kernel/qplatformintegration.cpp
+++ b/src/gui/kernel/qplatformintegration.cpp
@@ -418,6 +418,8 @@ QVariant QPlatformIntegration::styleHint(StyleHint hint) const
return QPlatformTheme::defaultThemeHint(QPlatformTheme::UiEffects);
case WheelScrollLines:
return QPlatformTheme::defaultThemeHint(QPlatformTheme::WheelScrollLines);
+ case MouseQuickSelectionThreshold:
+ return QPlatformTheme::defaultThemeHint(QPlatformTheme::MouseQuickSelectionThreshold);
}
return 0;
diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h
index a7d9a87502..37884e1f78 100644
--- a/src/gui/kernel/qplatformintegration.h
+++ b/src/gui/kernel/qplatformintegration.h
@@ -164,6 +164,7 @@ public:
UiEffects,
WheelScrollLines,
ShowShortcutsInContextMenus,
+ MouseQuickSelectionThreshold
};
virtual QVariant styleHint(StyleHint hint) const;
diff --git a/src/gui/kernel/qplatformtheme.cpp b/src/gui/kernel/qplatformtheme.cpp
index 1856952805..277d976dde 100644
--- a/src/gui/kernel/qplatformtheme.cpp
+++ b/src/gui/kernel/qplatformtheme.cpp
@@ -559,6 +559,8 @@ QVariant QPlatformTheme::defaultThemeHint(ThemeHint hint)
dist = defaultThemeHint(MouseDoubleClickDistance).toInt(&ok) * 2;
return QVariant(ok ? dist : 10);
}
+ case MouseQuickSelectionThreshold:
+ return QVariant(10);
}
return QVariant();
}
diff --git a/src/gui/kernel/qplatformtheme.h b/src/gui/kernel/qplatformtheme.h
index 87873d446f..1d6049a98d 100644
--- a/src/gui/kernel/qplatformtheme.h
+++ b/src/gui/kernel/qplatformtheme.h
@@ -117,7 +117,8 @@ public:
WheelScrollLines,
TouchDoubleTapDistance,
ShowShortcutsInContextMenus,
- IconFallbackSearchPaths
+ IconFallbackSearchPaths,
+ MouseQuickSelectionThreshold
};
enum DialogType {
diff --git a/src/gui/kernel/qstylehints.cpp b/src/gui/kernel/qstylehints.cpp
index 0850228ee5..b2d968c046 100644
--- a/src/gui/kernel/qstylehints.cpp
+++ b/src/gui/kernel/qstylehints.cpp
@@ -79,6 +79,7 @@ public:
, m_tabFocusBehavior(-1)
, m_uiEffects(-1)
, m_wheelScrollLines(-1)
+ , m_mouseQuickSelectionThreshold(-1)
{}
int m_mouseDoubleClickInterval;
@@ -90,6 +91,7 @@ public:
int m_tabFocusBehavior;
int m_uiEffects;
int m_wheelScrollLines;
+ int m_mouseQuickSelectionThreshold;
};
/*!
@@ -537,4 +539,38 @@ void QStyleHints::setWheelScrollLines(int scrollLines)
emit wheelScrollLinesChanged(scrollLines);
}
+/*!
+ Sets the mouse quick selection threshold.
+ \internal
+ \sa mouseQuickSelectionThreshold()
+ \since 5.11
+*/
+void QStyleHints::setMouseQuickSelectionThreshold(int threshold)
+{
+ Q_D(QStyleHints);
+ if (d->m_mouseQuickSelectionThreshold == threshold)
+ return;
+ d->m_mouseQuickSelectionThreshold = threshold;
+ emit mouseDoubleClickIntervalChanged(threshold);
+}
+
+/*!
+ \property QStyleHints::mouseQuickSelectionThreshold
+ \brief Quick selection mouse threshold in QLineEdit.
+
+ This property defines how much the mouse cursor should be moved along the y axis
+ to trigger a quick selection during a normal QLineEdit text selection.
+
+ If the property value is less than or equal to 0, the quick selection feature is disabled.
+
+ \since 5.11
+*/
+int QStyleHints::mouseQuickSelectionThreshold() const
+{
+ Q_D(const QStyleHints);
+ if (d->m_mouseQuickSelectionThreshold >= 0)
+ return d->m_mouseQuickSelectionThreshold;
+ return themeableHint(QPlatformTheme::MouseQuickSelectionThreshold, QPlatformIntegration::MouseQuickSelectionThreshold).toInt();
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qstylehints.h b/src/gui/kernel/qstylehints.h
index 2c2e048b15..7b0683e9b1 100644
--- a/src/gui/kernel/qstylehints.h
+++ b/src/gui/kernel/qstylehints.h
@@ -73,6 +73,7 @@ class Q_GUI_EXPORT QStyleHints : public QObject
Q_PROPERTY(bool singleClickActivation READ singleClickActivation STORED false CONSTANT FINAL)
Q_PROPERTY(bool useHoverEffects READ useHoverEffects WRITE setUseHoverEffects NOTIFY useHoverEffectsChanged FINAL)
Q_PROPERTY(int wheelScrollLines READ wheelScrollLines NOTIFY wheelScrollLinesChanged FINAL)
+ Q_PROPERTY(int mouseQuickSelectionThreshold READ mouseQuickSelectionThreshold WRITE setMouseQuickSelectionThreshold NOTIFY mouseQuickSelectionThresholdChanged FINAL)
public:
void setMouseDoubleClickInterval(int mouseDoubleClickInterval);
@@ -104,6 +105,8 @@ public:
void setUseHoverEffects(bool useHoverEffects);
int wheelScrollLines() const;
void setWheelScrollLines(int scrollLines);
+ void setMouseQuickSelectionThreshold(int threshold);
+ int mouseQuickSelectionThreshold() const;
Q_SIGNALS:
void cursorFlashTimeChanged(int cursorFlashTime);
@@ -115,6 +118,7 @@ Q_SIGNALS:
void tabFocusBehaviorChanged(Qt::TabFocusBehavior tabFocusBehavior);
void useHoverEffectsChanged(bool useHoverEffects);
void wheelScrollLinesChanged(int scrollLines);
+ void mouseQuickSelectionThresholdChanged(int threshold);
private:
friend class QGuiApplication;
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 6ddfcdfaf4..23c8e42ded 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -174,29 +174,31 @@ template<QImage::Format Format>
static const uint *QT_FASTCALL convertToRGB32(uint *buffer, const uint *src, int count,
const QVector<QRgb> *, QDitherInfo *)
{
- Q_CONSTEXPR uint redMask = ((1 << redWidth<Format>()) - 1);
- Q_CONSTEXPR uint greenMask = ((1 << greenWidth<Format>()) - 1);
- Q_CONSTEXPR uint blueMask = ((1 << blueWidth<Format>()) - 1);
+ auto conversion = [](uint s) {
+ // MSVC needs these constexpr defined in here otherwise it will create a capture.
+ Q_CONSTEXPR uint redMask = ((1 << redWidth<Format>()) - 1);
+ Q_CONSTEXPR uint greenMask = ((1 << greenWidth<Format>()) - 1);
+ Q_CONSTEXPR uint blueMask = ((1 << blueWidth<Format>()) - 1);
- Q_CONSTEXPR uchar redLeftShift = 8 - redWidth<Format>();
- Q_CONSTEXPR uchar greenLeftShift = 8 - greenWidth<Format>();
- Q_CONSTEXPR uchar blueLeftShift = 8 - blueWidth<Format>();
+ Q_CONSTEXPR uchar redLeftShift = 8 - redWidth<Format>();
+ Q_CONSTEXPR uchar greenLeftShift = 8 - greenWidth<Format>();
+ Q_CONSTEXPR uchar blueLeftShift = 8 - blueWidth<Format>();
- Q_CONSTEXPR uchar redRightShift = 2 * redWidth<Format>() - 8;
- Q_CONSTEXPR uchar greenRightShift = 2 * greenWidth<Format>() - 8;
- Q_CONSTEXPR uchar blueRightShift = 2 * blueWidth<Format>() - 8;
+ Q_CONSTEXPR uchar redRightShift = 2 * redWidth<Format>() - 8;
+ Q_CONSTEXPR uchar greenRightShift = 2 * greenWidth<Format>() - 8;
+ Q_CONSTEXPR uchar blueRightShift = 2 * blueWidth<Format>() - 8;
- for (int i = 0; i < count; ++i) {
- uint red = (src[i] >> redShift<Format>()) & redMask;
- uint green = (src[i] >> greenShift<Format>()) & greenMask;
- uint blue = (src[i] >> blueShift<Format>()) & blueMask;
+ uint red = (s >> redShift<Format>()) & redMask;
+ uint green = (s >> greenShift<Format>()) & greenMask;
+ uint blue = (s >> blueShift<Format>()) & blueMask;
red = ((red << redLeftShift) | (red >> redRightShift)) << 16;
green = ((green << greenLeftShift) | (green >> greenRightShift)) << 8;
blue = (blue << blueLeftShift) | (blue >> blueRightShift);
- buffer[i] = 0xff000000 | red | green | blue;
- }
+ return 0xff000000 | red | green | blue;
+ };
+ UNALIASED_CONVERSION_LOOP(buffer, src, count, conversion);
return buffer;
}
@@ -348,21 +350,21 @@ static const uint *QT_FASTCALL convertRGBFromARGB32PM(uint *buffer, const uint *
// RGB32 -> RGB888 is not a precision loss.
if (!dither || (rWidth == 8 && gWidth == 8 && bWidth == 8)) {
- Q_CONSTEXPR uint rMask = (1 << rWidth) - 1;
- Q_CONSTEXPR uint gMask = (1 << gWidth) - 1;
- Q_CONSTEXPR uint bMask = (1 << bWidth) - 1;
+ auto conversion = [](uint s) {
+ const uint c = fromRGB ? s : qUnpremultiply(s);
+ Q_CONSTEXPR uint rMask = (1 << redWidth<Format>()) - 1;
+ Q_CONSTEXPR uint gMask = (1 << greenWidth<Format>()) - 1;
+ Q_CONSTEXPR uint bMask = (1 << blueWidth<Format>()) - 1;
+ Q_CONSTEXPR uchar rRightShift = 24 - redWidth<Format>();
+ Q_CONSTEXPR uchar gRightShift = 16 - greenWidth<Format>();
+ Q_CONSTEXPR uchar bRightShift = 8 - blueWidth<Format>();
- Q_CONSTEXPR uchar rRightShift = 24 - rWidth;
- Q_CONSTEXPR uchar gRightShift = 16 - gWidth;
- Q_CONSTEXPR uchar bRightShift = 8 - bWidth;
-
- for (int i = 0; i < count; ++i) {
- const uint c = fromRGB ? src[i] : qUnpremultiply(src[i]);
const uint r = ((c >> rRightShift) & rMask) << redShift<Format>();
const uint g = ((c >> gRightShift) & gMask) << greenShift<Format>();
const uint b = ((c >> bRightShift) & bMask) << blueShift<Format>();
- buffer[i] = r | g | b;
- }
+ return r | g | b;
+ };
+ UNALIASED_CONVERSION_LOOP(buffer, src, count, conversion);
} else {
// We do ordered dither by using a rounding conversion, but instead of
// adding half of input precision, we add the adjusted result from the
@@ -394,32 +396,32 @@ template<QImage::Format Format, bool fromRGB>
static const uint *QT_FASTCALL convertARGBPMFromARGB32PM(uint *buffer, const uint *src, int count,
const QVector<QRgb> *, QDitherInfo *dither)
{
- Q_CONSTEXPR uchar aWidth = alphaWidth<Format>();
- Q_CONSTEXPR uchar rWidth = redWidth<Format>();
- Q_CONSTEXPR uchar gWidth = greenWidth<Format>();
- Q_CONSTEXPR uchar bWidth = blueWidth<Format>();
-
if (!dither) {
- Q_CONSTEXPR uint aMask = (1 << aWidth) - 1;
- Q_CONSTEXPR uint rMask = (1 << rWidth) - 1;
- Q_CONSTEXPR uint gMask = (1 << gWidth) - 1;
- Q_CONSTEXPR uint bMask = (1 << bWidth) - 1;
-
- Q_CONSTEXPR uchar aRightShift = 32 - aWidth;
- Q_CONSTEXPR uchar rRightShift = 24 - rWidth;
- Q_CONSTEXPR uchar gRightShift = 16 - gWidth;
- Q_CONSTEXPR uchar bRightShift = 8 - bWidth;
-
- Q_CONSTEXPR uint aOpaque = aMask << alphaShift<Format>();
- for (int i = 0; i < count; ++i) {
- const uint c = src[i];
+ auto conversion = [](uint c) {
+ Q_CONSTEXPR uint aMask = (1 << alphaWidth<Format>()) - 1;
+ Q_CONSTEXPR uint rMask = (1 << redWidth<Format>()) - 1;
+ Q_CONSTEXPR uint gMask = (1 << greenWidth<Format>()) - 1;
+ Q_CONSTEXPR uint bMask = (1 << blueWidth<Format>()) - 1;
+
+ Q_CONSTEXPR uchar aRightShift = 32 - alphaWidth<Format>();
+ Q_CONSTEXPR uchar rRightShift = 24 - redWidth<Format>();
+ Q_CONSTEXPR uchar gRightShift = 16 - greenWidth<Format>();
+ Q_CONSTEXPR uchar bRightShift = 8 - blueWidth<Format>();
+
+ Q_CONSTEXPR uint aOpaque = aMask << alphaShift<Format>();
const uint a = fromRGB ? aOpaque : (((c >> aRightShift) & aMask) << alphaShift<Format>());
const uint r = ((c >> rRightShift) & rMask) << redShift<Format>();
const uint g = ((c >> gRightShift) & gMask) << greenShift<Format>();
const uint b = ((c >> bRightShift) & bMask) << blueShift<Format>();
- buffer[i] = a | r | g | b;
- }
+ return a | r | g | b;
+ };
+ UNALIASED_CONVERSION_LOOP(buffer, src, count, conversion);
} else {
+ Q_CONSTEXPR uchar aWidth = alphaWidth<Format>();
+ Q_CONSTEXPR uchar rWidth = redWidth<Format>();
+ Q_CONSTEXPR uchar gWidth = greenWidth<Format>();
+ Q_CONSTEXPR uchar bWidth = blueWidth<Format>();
+
const uint *bayer_line = qt_bayer_matrix[dither->y & 15];
for (int i = 0; i < count; ++i) {
const uint c = src[i];
@@ -514,8 +516,7 @@ static const uint *QT_FASTCALL convertARGB32ToARGB32PM(uint *buffer, const uint
static const uint *QT_FASTCALL convertRGBA8888PMToARGB32PM(uint *buffer, const uint *src, int count,
const QVector<QRgb> *, QDitherInfo *)
{
- for (int i = 0; i < count; ++i)
- buffer[i] = RGBA2ARGB(src[i]);
+ UNALIASED_CONVERSION_LOOP(buffer, src, count, RGBA2ARGB);
return buffer;
}
@@ -568,8 +569,7 @@ static const uint *QT_FASTCALL convertARGB32FromARGB32PM(uint *buffer, const uin
static const uint *QT_FASTCALL convertRGBA8888PMFromARGB32PM(uint *buffer, const uint *src, int count,
const QVector<QRgb> *, QDitherInfo *)
{
- for (int i = 0; i < count; ++i)
- buffer[i] = ARGB2RGBA(src[i]);
+ UNALIASED_CONVERSION_LOOP(buffer, src, count, ARGB2RGBA);
return buffer;
}
@@ -695,8 +695,7 @@ static const uint *QT_FASTCALL convertRGBA8888FromARGB32PM(uint *buffer, const u
static const uint *QT_FASTCALL convertRGBXFromRGB32(uint *buffer, const uint *src, int count,
const QVector<QRgb> *, QDitherInfo *)
{
- for (int i = 0; i < count; ++i)
- buffer[i] = ARGB2RGBA(0xff000000 | src[i]);
+ UNALIASED_CONVERSION_LOOP(buffer, src, count, [](uint c) { return ARGB2RGBA(0xff000000 | c); });
return buffer;
}
@@ -713,8 +712,7 @@ static const uint *QT_FASTCALL convertA2RGB30PMToARGB32PM(uint *buffer, const ui
const QVector<QRgb> *, QDitherInfo *dither)
{
if (!dither) {
- for (int i = 0; i < count; ++i)
- buffer[i] = qConvertA2rgb30ToArgb32<PixelOrder>(src[i]);
+ UNALIASED_CONVERSION_LOOP(buffer, src, count, qConvertA2rgb30ToArgb32<PixelOrder>);
} else {
for (int i = 0; i < count; ++i) {
const uint c = src[i];
@@ -796,8 +794,7 @@ template<QtPixelOrder PixelOrder>
static const uint *QT_FASTCALL convertA2RGB30PMFromARGB32PM(uint *buffer, const uint *src, int count,
const QVector<QRgb> *, QDitherInfo *)
{
- for (int i = 0; i < count; ++i)
- buffer[i] = qConvertArgb32ToA2rgb30<PixelOrder>(src[i]);
+ UNALIASED_CONVERSION_LOOP(buffer, src, count, qConvertArgb32ToA2rgb30<PixelOrder>);
return buffer;
}
@@ -814,8 +811,7 @@ template<QtPixelOrder PixelOrder>
static const uint *QT_FASTCALL convertRGB30FromARGB32PM(uint *buffer, const uint *src, int count,
const QVector<QRgb> *, QDitherInfo *)
{
- for (int i = 0; i < count; ++i)
- buffer[i] = qConvertRgb32ToRgb30<PixelOrder>(qUnpremultiply(src[i]));
+ UNALIASED_CONVERSION_LOOP(buffer, src, count, qConvertRgb32ToRgb30<PixelOrder>);
return buffer;
}
diff --git a/src/gui/painting/qdrawhelper_avx2.cpp b/src/gui/painting/qdrawhelper_avx2.cpp
index cf89f408b5..3a70524a9d 100644
--- a/src/gui/painting/qdrawhelper_avx2.cpp
+++ b/src/gui/painting/qdrawhelper_avx2.cpp
@@ -427,7 +427,7 @@ void QT_FASTCALL comp_func_Source_rgb64_avx2(QRgba64 *dst, const QRgba64 *src, i
::memcpy(dst, src, length * sizeof(QRgba64));
} else {
const uint ca = const_alpha | (const_alpha << 8); // adjust to [0-65535]
- const uint cia = 65535 - const_alpha;
+ const uint cia = 65535 - ca;
int x = 0;
@@ -493,7 +493,7 @@ void QT_FASTCALL comp_func_solid_SourceOver_rgb64_avx2(QRgba64 *destPixels, int
if (const_alpha != 255)
color = multiplyAlpha255(color, const_alpha);
- const uint minusAlphaOfColor = ~ushort(color.alpha());
+ const uint minusAlphaOfColor = 65535 - color.alpha();
int x = 0;
quint64 *dst = (quint64 *) destPixels;
const __m256i colorVector = _mm256_set1_epi64x(color);
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index 4c2fe87355..ebf215a3eb 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -1104,22 +1104,30 @@ inline int qBlue565(quint16 rgb) {
return (b << 3) | (b >> 2);
}
+// We manually unalias the variables to make sure the compiler
+// fully optimizes both aliased and unaliased cases.
+#define UNALIASED_CONVERSION_LOOP(buffer, src, count, conversion) \
+ if (src == buffer) { \
+ for (int i = 0; i < count; ++i) \
+ buffer[i] = conversion(buffer[i]); \
+ } else { \
+ for (int i = 0; i < count; ++i) \
+ buffer[i] = conversion(src[i]); \
+ }
+
static Q_ALWAYS_INLINE const uint *qt_convertARGB32ToARGB32PM(uint *buffer, const uint *src, int count)
{
- for (int i = 0; i < count; ++i)
- buffer[i] = qPremultiply(src[i]);
+ UNALIASED_CONVERSION_LOOP(buffer, src, count, qPremultiply);
return buffer;
}
static Q_ALWAYS_INLINE const uint *qt_convertRGBA8888ToARGB32PM(uint *buffer, const uint *src, int count)
{
- for (int i = 0; i < count; ++i)
- buffer[i] = qPremultiply(RGBA2ARGB(src[i]));
+ UNALIASED_CONVERSION_LOOP(buffer, src, count, [](uint s) { return qPremultiply(RGBA2ARGB(s));});
return buffer;
}
-
const uint qt_bayer_matrix[16][16] = {
{ 0x1, 0xc0, 0x30, 0xf0, 0xc, 0xcc, 0x3c, 0xfc,
0x3, 0xc3, 0x33, 0xf3, 0xf, 0xcf, 0x3f, 0xff},
diff --git a/src/gui/qtgui.tracepoints b/src/gui/qtgui.tracepoints
new file mode 100644
index 0000000000..aa8a8ede57
--- /dev/null
+++ b/src/gui/qtgui.tracepoints
@@ -0,0 +1,8 @@
+qfontdatabase_addapplicationfont(const QString &filename)
+qfontdatabase_load(const QString &family, int pointSize)
+qfontdatabase_loadengine(const QString &family, int pointSize)
+qfontdatabaseprivate_addappfont(const QString &fileName)
+qguiapplicationprivate_init_entry()
+qguiapplicationprivate_init_exit()
+qguiapplicationprivate_processwsevents_entry(int type)
+qguiapplicationprivate_processwsevents_exit(int type)
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index 4be2197c68..404a722e29 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -74,6 +74,7 @@
# define FM_DEBUG if (false) qDebug
#endif
+#include <qtgui_tracepoints_p.h>
QT_BEGIN_NAMESPACE
@@ -1009,6 +1010,8 @@ QFontEngine *loadEngine(int script, const QFontDef &request,
QFontEngine *engine = loadSingleEngine(script, request, family, foundry, style, size);
if (engine && !(request.styleStrategy & QFont::NoFontMerging) && !engine->symbol) {
+ Q_TRACE(qfontdatabase_loadengine, request.family, request.pointSize);
+
QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase();
QFontEngineMulti *pfMultiEngine = pfdb->fontEngineMulti(engine, QChar::Script(script));
if (!request.fallBackFamilies.isEmpty()) {
@@ -2439,6 +2442,8 @@ int QFontDatabasePrivate::addAppFont(const QByteArray &fontData, const QString &
font.data = fontData;
font.fileName = fileName;
+ Q_TRACE(qfontdatabaseprivate_addappfont, fileName);
+
int i;
for (i = 0; i < applicationFonts.count(); ++i)
if (applicationFonts.at(i).families.isEmpty())
@@ -2494,6 +2499,9 @@ int QFontDatabase::addApplicationFont(const QString &fileName)
QFile f(fileName);
if (!f.open(QIODevice::ReadOnly))
return -1;
+
+ Q_TRACE(qfontdatabase_addapplicationfont, fileName);
+
data = f.readAll();
}
QMutexLocker locker(fontDatabaseMutex());
@@ -2792,6 +2800,8 @@ void QFontDatabase::load(const QFontPrivate *d, int script)
QFontEngine *fe = nullptr;
+ Q_TRACE(qfontdatabase_load, req.family, req.pointSize);
+
req.fallBackFamilies = fallBackFamilies;
if (!req.fallBackFamilies.isEmpty())
req.family = req.fallBackFamilies.takeFirst();
diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp
index 99f72a7955..1d7c5bec51 100644
--- a/src/network/access/qnetworkrequest.cpp
+++ b/src/network/access/qnetworkrequest.cpp
@@ -308,7 +308,7 @@ QT_BEGIN_NAMESPACE
was specified, QNetworkAccessManager gives up, without attempting to
fall back to HTTP/1.1. If both HTTP2AllowedAttribute and
Http2DirectAttribute are set, Http2DirectAttribute takes priority.
- (This value was introduced in 5.10.)
+ (This value was introduced in 5.11.)
\omitvalue ResourceTypeAttribute
diff --git a/src/network/ssl/qsslconfiguration.cpp b/src/network/ssl/qsslconfiguration.cpp
index 75a880f115..cbbbac85fe 100644
--- a/src/network/ssl/qsslconfiguration.cpp
+++ b/src/network/ssl/qsslconfiguration.cpp
@@ -221,6 +221,7 @@ bool QSslConfiguration::operator==(const QSslConfiguration &other) const
d->peerVerifyMode == other.d->peerVerifyMode &&
d->peerVerifyDepth == other.d->peerVerifyDepth &&
d->allowRootCertOnDemandLoading == other.d->allowRootCertOnDemandLoading &&
+ d->backendConfig == other.d->backendConfig &&
d->sslOptions == other.d->sslOptions &&
d->sslSession == other.d->sslSession &&
d->sslSessionTicketLifeTimeHint == other.d->sslSessionTicketLifeTimeHint &&
@@ -263,6 +264,7 @@ bool QSslConfiguration::isNull() const
d->privateKey.isNull() &&
d->peerCertificate.isNull() &&
d->peerCertificateChain.count() == 0 &&
+ d->backendConfig.isEmpty() &&
d->sslOptions == QSslConfigurationPrivate::defaultSslOptions &&
d->sslSession.isNull() &&
d->sslSessionTicketLifeTimeHint == -1 &&
@@ -870,6 +872,60 @@ void QSslConfiguration::setDiffieHellmanParameters(const QSslDiffieHellmanParame
}
/*!
+ \since 5.11
+
+ Returns the backend-specific configuration.
+
+ Only options set by addBackendConfig() or setBackendConfig() will be
+ returned. The internal standard configuration of the backend is not reported.
+
+ \sa setBackendConfigOption(), setBackendConfig()
+ */
+QMap<QByteArray, QVariant> QSslConfiguration::backendConfig() const
+{
+ return d->backendConfig;
+}
+
+/*!
+ \since 5.11
+
+ Sets an option in the backend-specific configuration.
+
+ Options supported by the OpenSSL (>= 1.0.2) backend are available in the \l
+ {https://www.openssl.org/docs/manmaster/man3/SSL_CONF_cmd.html#SUPPORTED-CONFIGURATION-FILE-COMMANDS}
+ {supported configuration file commands} documentation. The expected type for
+ the \a value parameter is a QByteArray for all options. The \l
+ {https://www.openssl.org/docs/manmaster/man3/SSL_CONF_cmd.html#EXAMPLES}{examples}
+ show how to use some of the options.
+
+ \note The backend-specific configuration will be applied after the general
+ configuration. Using the backend-specific configuration to set a general
+ configuration option again will overwrite the general configuration option.
+
+ \sa backendConfig(), setBackendConfig()
+ */
+void QSslConfiguration::setBackendConfigOption(const QByteArray &name, const QVariant &value)
+{
+ d->backendConfig[name] = value;
+}
+
+/*!
+ \since 5.11
+
+ Sets or clears the backend-specific configuration.
+
+ Without a \a backendConfig parameter this function will clear the
+ backend-specific configuration. More information about the supported
+ options is available in the documentation of addBackendConfig().
+
+ \sa backendConfig(), setBackendConfigOption()
+ */
+void QSslConfiguration::setBackendConfig(const QMap<QByteArray, QVariant> &backendConfig)
+{
+ d->backendConfig = backendConfig;
+}
+
+/*!
\since 5.3
This function returns the protocol negotiated with the server
diff --git a/src/network/ssl/qsslconfiguration.h b/src/network/ssl/qsslconfiguration.h
index 1c57bebd65..b3264126dd 100644
--- a/src/network/ssl/qsslconfiguration.h
+++ b/src/network/ssl/qsslconfiguration.h
@@ -57,6 +57,7 @@
#define QSSLCONFIGURATION_H
#include <QtNetwork/qtnetworkglobal.h>
+#include <QtCore/qmap.h>
#include <QtCore/qshareddata.h>
#include <QtNetwork/qsslsocket.h>
#include <QtNetwork/qssl.h>
@@ -149,6 +150,10 @@ public:
QSslDiffieHellmanParameters diffieHellmanParameters() const;
void setDiffieHellmanParameters(const QSslDiffieHellmanParameters &dhparams);
+ QMap<QByteArray, QVariant> backendConfig() const;
+ void setBackendConfigOption(const QByteArray &name, const QVariant &value);
+ void setBackendConfig(const QMap<QByteArray, QVariant> &backendConfig = QMap<QByteArray, QVariant>());
+
static QSslConfiguration defaultConfiguration();
static void setDefaultConfiguration(const QSslConfiguration &configuration);
diff --git a/src/network/ssl/qsslconfiguration_p.h b/src/network/ssl/qsslconfiguration_p.h
index 6adf2c9b54..38a98239db 100644
--- a/src/network/ssl/qsslconfiguration_p.h
+++ b/src/network/ssl/qsslconfiguration_p.h
@@ -67,6 +67,7 @@
// We mean it.
//
+#include <QtCore/qmap.h>
#include <QtNetwork/private/qtnetworkglobal_p.h>
#include "qsslconfiguration.h"
#include "qlist.h"
@@ -123,6 +124,8 @@ public:
QSslDiffieHellmanParameters dhParams;
+ QMap<QByteArray, QVariant> backendConfig;
+
QByteArray sslSession;
int sslSessionTicketLifeTimeHint;
diff --git a/src/network/ssl/qsslcontext_openssl.cpp b/src/network/ssl/qsslcontext_openssl.cpp
index cef503710c..386c280659 100644
--- a/src/network/ssl/qsslcontext_openssl.cpp
+++ b/src/network/ssl/qsslcontext_openssl.cpp
@@ -49,6 +49,11 @@
QT_BEGIN_NAMESPACE
+static inline QString msgErrorSettingBackendConfig(const QString &why)
+{
+ return QSslSocket::tr("Error when setting the OpenSSL configuration (%1)").arg(why);
+}
+
QSslContext::QSslContext()
: ctx(0),
pkey(0),
@@ -237,4 +242,70 @@ QString QSslContext::errorString() const
return errorStr;
}
+// static
+void QSslContext::applyBackendConfig(QSslContext *sslContext)
+{
+ if (sslContext->sslConfiguration.backendConfig().isEmpty())
+ return;
+
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+ if (QSslSocket::sslLibraryVersionNumber() >= 0x10002000L) {
+ QSharedPointer<SSL_CONF_CTX> cctx(q_SSL_CONF_CTX_new(), &q_SSL_CONF_CTX_free);
+ if (cctx) {
+ q_SSL_CONF_CTX_set_ssl_ctx(cctx.data(), sslContext->ctx);
+ q_SSL_CONF_CTX_set_flags(cctx.data(), SSL_CONF_FLAG_FILE);
+
+ const auto &backendConfig = sslContext->sslConfiguration.backendConfig();
+ for (auto i = backendConfig.constBegin(); i != backendConfig.constEnd(); ++i) {
+ if (!i.value().canConvert(QMetaType::QByteArray)) {
+ sslContext->errorCode = QSslError::UnspecifiedError;
+ sslContext->errorStr = msgErrorSettingBackendConfig(
+ QSslSocket::tr("Expecting QByteArray for %1").arg(
+ QString::fromUtf8(i.key())));
+ return;
+ }
+
+ const QByteArray &value = i.value().toByteArray();
+ const int result = q_SSL_CONF_cmd(cctx.data(), i.key().constData(), value.constData());
+ if (result == 2)
+ continue;
+
+ sslContext->errorCode = QSslError::UnspecifiedError;
+ switch (result) {
+ case 0:
+ sslContext->errorStr = msgErrorSettingBackendConfig(
+ QSslSocket::tr("An error occurred attempting to set %1 to %2").arg(
+ QString::fromUtf8(i.key()), QString::fromUtf8(value)));
+ return;
+ case 1:
+ sslContext->errorStr = msgErrorSettingBackendConfig(
+ QSslSocket::tr("Wrong value for %1 (%2)").arg(
+ QString::fromUtf8(i.key()), QString::fromUtf8(value)));
+ return;
+ default:
+ sslContext->errorStr = msgErrorSettingBackendConfig(
+ QSslSocket::tr("Unrecognized command %1 = %2").arg(
+ QString::fromUtf8(i.key()), QString::fromUtf8(value)));
+ return;
+ }
+ }
+
+ if (q_SSL_CONF_CTX_finish(cctx.data()) == 0) {
+ sslContext->errorStr = msgErrorSettingBackendConfig(QSslSocket::tr("SSL_CONF_finish() failed"));
+ sslContext->errorCode = QSslError::UnspecifiedError;
+ }
+ } else {
+ sslContext->errorStr = msgErrorSettingBackendConfig(QSslSocket::tr("SSL_CONF_CTX_new() failed"));
+ sslContext->errorCode = QSslError::UnspecifiedError;
+ }
+ } else
+#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
+ {
+ // specific algorithms requested, but not possible to set
+ sslContext->errorCode = QSslError::UnspecifiedError;
+ sslContext->errorStr = msgErrorSettingBackendConfig(
+ QSslSocket::tr("OpenSSL version too old, need at least v1.0.2"));
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/network/ssl/qsslcontext_openssl11.cpp b/src/network/ssl/qsslcontext_openssl11.cpp
index 787b6ae3f5..7be7be46b8 100644
--- a/src/network/ssl/qsslcontext_openssl11.cpp
+++ b/src/network/ssl/qsslcontext_openssl11.cpp
@@ -260,6 +260,7 @@ init_context:
#ifdef OPENSSL_NO_EC
sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocket::tr("OpenSSL version with disabled elliptic curves"));
sslContext->errorCode = QSslError::UnspecifiedError;
+ return;
#else
// Set the curves to be used.
std::vector<int> curves;
@@ -269,9 +270,12 @@ init_context:
if (!q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_SET_CURVES, long(curves.size()), &curves[0])) {
sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
sslContext->errorCode = QSslError::UnspecifiedError;
+ return;
}
#endif
}
+
+ applyBackendConfig(sslContext);
}
QT_END_NAMESPACE
diff --git a/src/network/ssl/qsslcontext_openssl_p.h b/src/network/ssl/qsslcontext_openssl_p.h
index 06a31af5e5..48beebf134 100644
--- a/src/network/ssl/qsslcontext_openssl_p.h
+++ b/src/network/ssl/qsslcontext_openssl_p.h
@@ -107,6 +107,7 @@ protected:
private:
static void initSslContext(QSslContext* sslContext, QSslSocket::SslMode mode, const QSslConfiguration &configuration,
bool allowRootCertOnDemandLoading);
+ static void applyBackendConfig(QSslContext *sslContext);
private:
SSL_CTX* ctx;
diff --git a/src/network/ssl/qsslcontext_opensslpre11.cpp b/src/network/ssl/qsslcontext_opensslpre11.cpp
index 9c01c2f2dc..eea821804f 100644
--- a/src/network/ssl/qsslcontext_opensslpre11.cpp
+++ b/src/network/ssl/qsslcontext_opensslpre11.cpp
@@ -340,6 +340,7 @@ init_context:
const_cast<int *>(reinterpret_cast<const int *>(qcurves.data())))) {
sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
sslContext->errorCode = QSslError::UnspecifiedError;
+ return;
}
} else
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_EC)
@@ -347,8 +348,11 @@ init_context:
// specific curves requested, but not possible to set -> error
sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocket::tr("OpenSSL version too old, need at least v1.0.2"));
sslContext->errorCode = QSslError::UnspecifiedError;
+ return;
}
}
+
+ applyBackendConfig(sslContext);
}
QT_END_NAMESPACE
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index 9f07b53e4b..833d676192 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -922,6 +922,7 @@ void QSslSocket::setSslConfiguration(const QSslConfiguration &configuration)
d->configuration.peerVerifyDepth = configuration.peerVerifyDepth();
d->configuration.peerVerifyMode = configuration.peerVerifyMode();
d->configuration.protocol = configuration.protocol();
+ d->configuration.backendConfig = configuration.backendConfig();
d->configuration.sslOptions = configuration.d->sslOptions;
d->configuration.sslSession = configuration.sessionTicket();
d->configuration.sslSessionTicketLifeTimeHint = configuration.sessionTicketLifeTimeHint();
@@ -2256,6 +2257,7 @@ void QSslConfigurationPrivate::deepCopyDefaultConfiguration(QSslConfigurationPri
ptr->peerVerifyDepth = global->peerVerifyDepth;
ptr->sslOptions = global->sslOptions;
ptr->ellipticCurves = global->ellipticCurves;
+ ptr->backendConfig = global->backendConfig;
}
/*!
diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp
index 1b73135935..9bb67771fd 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols.cpp
+++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp
@@ -402,6 +402,14 @@ DEFINEFUNC2(int, SSL_CTX_use_PrivateKey, SSL_CTX *a, a, EVP_PKEY *b, b, return -
DEFINEFUNC2(int, SSL_CTX_use_RSAPrivateKey, SSL_CTX *a, a, RSA *b, b, return -1, return)
DEFINEFUNC3(int, SSL_CTX_use_PrivateKey_file, SSL_CTX *a, a, const char *b, b, int c, c, return -1, return)
DEFINEFUNC(X509_STORE *, SSL_CTX_get_cert_store, const SSL_CTX *a, a, return 0, return)
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+DEFINEFUNC(SSL_CONF_CTX *, SSL_CONF_CTX_new, DUMMYARG, DUMMYARG, return 0, return);
+DEFINEFUNC(void, SSL_CONF_CTX_free, SSL_CONF_CTX *a, a, return ,return);
+DEFINEFUNC2(void, SSL_CONF_CTX_set_ssl_ctx, SSL_CONF_CTX *a, a, SSL_CTX *b, b, return, return);
+DEFINEFUNC2(unsigned int, SSL_CONF_CTX_set_flags, SSL_CONF_CTX *a, a, unsigned int b, b, return 0, return);
+DEFINEFUNC(int, SSL_CONF_CTX_finish, SSL_CONF_CTX *a, a, return 0, return);
+DEFINEFUNC3(int, SSL_CONF_cmd, SSL_CONF_CTX *a, a, const char *b, b, const char *c, c, return 0, return);
+#endif
DEFINEFUNC(void, SSL_free, SSL *a, a, return, DUMMYARG)
DEFINEFUNC(STACK_OF(SSL_CIPHER) *, SSL_get_ciphers, const SSL *a, a, return 0, return)
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
@@ -1105,6 +1113,14 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(SSL_CTX_use_RSAPrivateKey)
RESOLVEFUNC(SSL_CTX_use_PrivateKey_file)
RESOLVEFUNC(SSL_CTX_get_cert_store);
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+ RESOLVEFUNC(SSL_CONF_CTX_new);
+ RESOLVEFUNC(SSL_CONF_CTX_free);
+ RESOLVEFUNC(SSL_CONF_CTX_set_ssl_ctx);
+ RESOLVEFUNC(SSL_CONF_CTX_set_flags);
+ RESOLVEFUNC(SSL_CONF_CTX_finish);
+ RESOLVEFUNC(SSL_CONF_cmd);
+#endif
RESOLVEFUNC(SSL_accept)
RESOLVEFUNC(SSL_clear)
RESOLVEFUNC(SSL_connect)
diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h
index 4cad0231cd..be67f38b64 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols_p.h
+++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h
@@ -352,6 +352,14 @@ int q_SSL_CTX_use_PrivateKey(SSL_CTX *a, EVP_PKEY *b);
int q_SSL_CTX_use_RSAPrivateKey(SSL_CTX *a, RSA *b);
int q_SSL_CTX_use_PrivateKey_file(SSL_CTX *a, const char *b, int c);
X509_STORE *q_SSL_CTX_get_cert_store(const SSL_CTX *a);
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+SSL_CONF_CTX *q_SSL_CONF_CTX_new();
+void q_SSL_CONF_CTX_free(SSL_CONF_CTX *a);
+void q_SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *a, SSL_CTX *b);
+unsigned int q_SSL_CONF_CTX_set_flags(SSL_CONF_CTX *a, unsigned int b);
+int q_SSL_CONF_CTX_finish(SSL_CONF_CTX *a);
+int q_SSL_CONF_cmd(SSL_CONF_CTX *a, const char *b, const char *c);
+#endif
void q_SSL_free(SSL *a);
STACK_OF(SSL_CIPHER) *q_SSL_get_ciphers(const SSL *a);
#if OPENSSL_VERSION_NUMBER >= 0x10000000L
diff --git a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp
index a936ec7aad..580cf0e31d 100644
--- a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp
+++ b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp
@@ -1601,7 +1601,13 @@ bool AtSpiAdaptor::componentInterface(QAccessibleInterface *interface, const QSt
int x = message.arguments().at(0).toInt();
int y = message.arguments().at(1).toInt();
uint coordType = message.arguments().at(2).toUInt();
- Q_UNUSED (coordType) // FIXME
+ if (coordType == ATSPI_COORD_TYPE_WINDOW) {
+ QWindow * window = interface->window();
+ if (window) {
+ x += window->position().x();
+ y += window->position().y();
+ }
+ }
QAccessibleInterface * childInterface(interface->childAt(x, y));
QAccessibleInterface * iface = 0;
diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
index 7ea3d130f7..98b9f7c9ba 100644
--- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
@@ -198,7 +198,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSOpenSavePanelDelegate);
static QString strippedText(QString s)
{
- s.remove( QString::fromLatin1("...") );
+ s.remove(QLatin1String("..."));
return QPlatformTheme::removeMnemonics(s).trimmed();
}
diff --git a/src/plugins/platforms/ios/qioseventdispatcher.mm b/src/plugins/platforms/ios/qioseventdispatcher.mm
index de2c30cdfb..a6f6a7aac9 100644
--- a/src/plugins/platforms/ios/qioseventdispatcher.mm
+++ b/src/plugins/platforms/ios/qioseventdispatcher.mm
@@ -228,7 +228,7 @@ extern "C" int qt_main_wrapper(int argc, char *argv[])
}
}
- qEventDispatcherDebug() << "Running UIApplicationMain"; qIndent();
+ qCDebug(lcEventDispatcher) << "Running UIApplicationMain";
return UIApplicationMain(argc, argv, nil, NSStringFromClass([QIOSApplicationDelegate class]));
}
}
@@ -263,7 +263,7 @@ static void __attribute__((noinline, noreturn)) user_main_trampoline()
int exitCode = main(argc, argv);
delete[] argv;
- qEventDispatcherDebug() << "Returned from main with exit code " << exitCode;
+ qCDebug(lcEventDispatcher) << "Returned from main with exit code " << exitCode;
if (Q_UNLIKELY(debugStackUsage))
userMainStack.printUsage();
@@ -322,7 +322,7 @@ static bool rootLevelRunLoopIntegration()
+ (void)applicationDidFinishLaunching:(NSNotification *)notification
{
- qCDebug(lcQpaApplication) << "Application launched with options" << notification.userInfo;
+ qCDebug(lcEventDispatcher) << "Application launched with options" << notification.userInfo;
if (!isQtApplication())
return;
@@ -331,7 +331,7 @@ static bool rootLevelRunLoopIntegration()
// We schedule the main-redirection for the next run-loop pass, so that we
// can return from this function and let UIApplicationMain finish its job.
// This results in running Qt's application eventloop as a nested runloop.
- qCDebug(lcQpaApplication) << "Scheduling main() on next run-loop pass";
+ qCDebug(lcEventDispatcher) << "Scheduling main() on next run-loop pass";
CFRunLoopTimerRef userMainTimer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault,
CFAbsoluteTimeGetCurrent(), 0, 0, 0, ^(CFRunLoopTimerRef) { user_main_trampoline(); });
CFRunLoopAddTimer(CFRunLoopGetMain(), userMainTimer, kCFRunLoopCommonModes);
@@ -339,10 +339,10 @@ static bool rootLevelRunLoopIntegration()
return;
}
+
switch (setjmp(processEventEnterJumpPoint)) {
case kJumpPointSetSuccessfully:
- qCDebug(lcQpaApplication) << "Running main() on separate stack"; qIndent();
-
+ qCDebug(lcEventDispatcher) << "Running main() on separate stack";
// Redirect the stack pointer to the start of the reserved stack. This ensures
// that when we longjmp out of the event dispatcher and continue execution, the
// 'Qt main' call-stack will not be smashed, as it lives in a part of the stack
@@ -360,7 +360,7 @@ static bool rootLevelRunLoopIntegration()
case kJumpedFromEventDispatcherProcessEvents:
// We've returned from the longjmp in the event dispatcher,
// and the stack has been restored to its old self.
- qUnIndent(); qCDebug(lcQpaApplication) << "Returned from processEvents";
+ qCDebug(lcEventDispatcher) << "↳ Jumped from processEvents due to exec";
if (Q_UNLIKELY(debugStackUsage))
userMainStack.printUsage();
@@ -396,18 +396,18 @@ static const char kApplicationWillTerminateExitCode = char(SIGTERM | 0x80);
applicationAboutToTerminate = true;
switch (setjmp(applicationWillTerminateJumpPoint)) {
case kJumpPointSetSuccessfully:
- qEventDispatcherDebug() << "Exiting qApp with SIGTERM exit code"; qIndent();
+ qCDebug(lcEventDispatcher) << "Exiting qApp with SIGTERM exit code";
qApp->exit(kApplicationWillTerminateExitCode);
// The runloop will not exit when the application is about to terminate,
// so we'll never see the exit activity and have a chance to return from
// QEventLoop::exec(). We initiate the return manually as a workaround.
- qEventDispatcherDebug() << "Manually triggering return from event loop exec";
+ qCDebug(lcEventDispatcher) << "Manually triggering return from event loop exec";
static_cast<QIOSEventDispatcher *>(qApp->eventDispatcher())->interruptEventLoopExec();
break;
case kJumpedFromUserMainTrampoline:
// The user's main has returned, so we're ready to let iOS terminate the application
- qUnIndent(); qEventDispatcherDebug() << "kJumpedFromUserMainTrampoline, allowing iOS to terminate";
+ qCDebug(lcEventDispatcher) << "kJumpedFromUserMainTrampoline, allowing iOS to terminate";
break;
default:
qFatal("Unexpected jump result in event loop integration");
@@ -434,13 +434,15 @@ bool __attribute__((returns_twice)) QIOSEventDispatcher::processEvents(QEventLoo
return QEventDispatcherCoreFoundation::processEvents(flags);
if (applicationAboutToTerminate) {
- qEventDispatcherDebug() << "Detected QEventLoop exec after application termination";
+ qCDebug(lcEventDispatcher) << "Detected QEventLoop exec after application termination";
// Re-issue exit, and return immediately
qApp->exit(kApplicationWillTerminateExitCode);
return false;
}
if (!m_processEventLevel && (flags & QEventLoop::EventLoopExec)) {
+ qCDebug(lcEventDispatcher) << "Processing events with flags" << flags;
+
++m_processEventLevel;
m_runLoopExitObserver.addToMode(kCFRunLoopCommonModes);
@@ -449,7 +451,7 @@ bool __attribute__((returns_twice)) QIOSEventDispatcher::processEvents(QEventLoo
// is asked to exit, so that we can return from QEventLoop::exec().
switch (setjmp(processEventExitJumpPoint)) {
case kJumpPointSetSuccessfully:
- qEventDispatcherDebug() << "QEventLoop exec detected, jumping back to native runloop";
+ qCDebug(lcEventDispatcher) << "QEventLoop exec detected, jumping back to system runloop ↵";
longjmp(processEventEnterJumpPoint, kJumpedFromEventDispatcherProcessEvents);
break;
case kJumpedFromEventLoopExecInterrupt:
@@ -457,7 +459,7 @@ bool __attribute__((returns_twice)) QIOSEventDispatcher::processEvents(QEventLoo
// signal), and we jumped back though processEventExitJumpPoint. We return from processEvents,
// which will emit aboutToQuit if it's QApplication's event loop, and then return to the user's
// main, which can do whatever it wants, including calling exec() on the application again.
- qEventDispatcherDebug() << "kJumpedFromEventLoopExecInterrupt, returning with eventsProcessed = true";
+ qCDebug(lcEventDispatcher) << "⇢ System runloop exited, returning with eventsProcessed = true";
return true;
default:
qFatal("Unexpected jump result in event loop integration");
@@ -485,9 +487,8 @@ bool QIOSEventDispatcher::processPostedEvents()
if (!QEventDispatcherCoreFoundation::processPostedEvents())
return false;
- qEventDispatcherDebug() << "Sending window system events for " << m_processEvents.flags; qIndent();
+ qCDebug(lcEventDispatcher) << "Sending window system events for" << m_processEvents.flags;
QWindowSystemInterface::sendWindowSystemEvents(m_processEvents.flags);
- qUnIndent();
return true;
}
@@ -497,10 +498,8 @@ void QIOSEventDispatcher::handleRunLoopExit(CFRunLoopActivity activity)
Q_UNUSED(activity);
Q_ASSERT(activity == kCFRunLoopExit);
- if (m_processEventLevel == 1 && !currentEventLoop()->isRunning()) {
- qEventDispatcherDebug() << "Root runloop level exited";
+ if (m_processEventLevel == 1 && !currentEventLoop()->isRunning())
interruptEventLoopExec();
- }
}
void QIOSEventDispatcher::interruptEventLoopExec()
@@ -516,12 +515,12 @@ void QIOSEventDispatcher::interruptEventLoopExec()
// processEvents, instead of back in didFinishLaunchingWithOptions.
switch (setjmp(processEventEnterJumpPoint)) {
case kJumpPointSetSuccessfully:
- qEventDispatcherDebug() << "Jumping back to processEvents";
+ qCDebug(lcEventDispatcher) << "Jumping into processEvents due to system runloop exit ⇢";
longjmp(processEventExitJumpPoint, kJumpedFromEventLoopExecInterrupt);
break;
case kJumpedFromEventDispatcherProcessEvents:
// QEventLoop was re-executed
- qEventDispatcherDebug() << "kJumpedFromEventDispatcherProcessEvents";
+ qCDebug(lcEventDispatcher) << "↳ Jumped from processEvents due to re-exec";
break;
default:
qFatal("Unexpected jump result in event loop integration");
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
index d989761297..22d90d6ac2 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
@@ -673,4 +673,60 @@ void *QXcbNativeInterface::handlerNativeResourceForBackingStore(const QByteArray
return nullptr;
}
+static void dumpNativeWindowsRecursion(const QXcbConnection *connection, xcb_window_t window,
+ int level, QTextStream &str)
+{
+ if (level)
+ str << QByteArray(2 * level, ' ');
+
+ xcb_connection_t *conn = connection->xcb_connection();
+ auto geomReply = Q_XCB_REPLY(xcb_get_geometry, conn, window);
+ if (!geomReply)
+ return;
+ const QRect geom(geomReply->x, geomReply->y, geomReply->width, geomReply->height);
+ if (!geom.isValid() || (geom.width() <= 3 && geom.height() <= 3))
+ return; // Skip helper/dummy windows.
+ str << "0x";
+ const int oldFieldWidth = str.fieldWidth();
+ const QChar oldPadChar =str.padChar();
+ str.setFieldWidth(8);
+ str.setPadChar(QLatin1Char('0'));
+ str << hex << window;
+ str.setFieldWidth(oldFieldWidth);
+ str.setPadChar(oldPadChar);
+ str << dec << " \""
+ << QXcbWindow::windowTitle(connection, window) << "\" "
+ << geom.width() << 'x' << geom.height() << forcesign << geom.x() << geom.y()
+ << noforcesign << '\n';
+
+ auto reply = Q_XCB_REPLY(xcb_query_tree, conn, window);
+ if (reply) {
+ const int count = xcb_query_tree_children_length(reply.get());
+ const xcb_window_t *children = xcb_query_tree_children(reply.get());
+ for (int i = 0; i < count; ++i)
+ dumpNativeWindowsRecursion(connection, children[i], level + 1, str);
+ }
+}
+
+QString QXcbNativeInterface::dumpConnectionNativeWindows(const QXcbConnection *connection, WId root) const
+{
+ QString result;
+ QTextStream str(&result);
+ if (root) {
+ dumpNativeWindowsRecursion(connection, xcb_window_t(root), 0, str);
+ } else {
+ for (const QXcbScreen *screen : connection->screens()) {
+ str << "Screen: \"" << screen->name() << "\"\n";
+ dumpNativeWindowsRecursion(connection, screen->root(), 0, str);
+ str << '\n';
+ }
+ }
+ return result;
+}
+
+QString QXcbNativeInterface::dumpNativeWindows(WId root) const
+{
+ return dumpConnectionNativeWindows(QXcbIntegration::instance()->defaultConnection(), root);
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.h b/src/plugins/platforms/xcb/qxcbnativeinterface.h
index fb0db727aa..6a752c68ca 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.h
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.h
@@ -127,6 +127,8 @@ public:
Q_INVOKABLE bool systrayVisualHasAlphaChannel();
Q_INVOKABLE bool requestSystemTrayWindowDock(const QWindow *window);
Q_INVOKABLE QRect systemTrayWindowGlobalGeometry(const QWindow *window);
+ Q_INVOKABLE QString dumpConnectionNativeWindows(const QXcbConnection *connection, WId root) const;
+ Q_INVOKABLE QString dumpNativeWindows(WId root = 0) const;
void addHandler(QXcbNativeInterfaceHandler *handler);
void removeHandler(QXcbNativeInterfaceHandler *handler);
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index e3d9bc7a3d..49bf5181cc 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -91,16 +91,8 @@ QXcbVirtualDesktop::QXcbVirtualDesktop(QXcbConnection *connection, xcb_screen_t
if (reply && reply->format == 32 && reply->type == XCB_ATOM_WINDOW) {
xcb_window_t windowManager = *((xcb_window_t *)xcb_get_property_value(reply.get()));
- if (windowManager != XCB_WINDOW_NONE) {
- auto windowManagerReply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(),
- false, windowManager,
- atom(QXcbAtom::_NET_WM_NAME),
- atom(QXcbAtom::UTF8_STRING), 0, 1024);
- if (windowManagerReply && windowManagerReply->format == 8 && windowManagerReply->type == atom(QXcbAtom::UTF8_STRING)) {
- m_windowManagerName = QString::fromUtf8((const char *)xcb_get_property_value(windowManagerReply.get()),
- xcb_get_property_value_length(windowManagerReply.get()));
- }
- }
+ if (windowManager != XCB_WINDOW_NONE)
+ m_windowManagerName = QXcbWindow::windowTitle(connection, windowManager);
}
const xcb_query_extension_reply_t *sync_reply = xcb_get_extension_data(xcb_connection(), &xcb_sync_id);
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 44b337f555..5b05a230e4 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -2849,5 +2849,18 @@ QXcbScreen *QXcbWindow::xcbScreen() const
return static_cast<QXcbScreen *>(screen());
}
+QString QXcbWindow::windowTitle(const QXcbConnection *conn, xcb_window_t window)
+{
+ const xcb_atom_t utf8Atom = conn->atom(QXcbAtom::UTF8_STRING);
+ auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, conn->xcb_connection(),
+ false, window, conn->atom(QXcbAtom::_NET_WM_NAME),
+ utf8Atom, 0, 1024);
+ if (reply && reply->format == 8 && reply->type == utf8Atom) {
+ const char *name = reinterpret_cast<const char *>(xcb_get_property_value(reply.get()));
+ return QString::fromUtf8(name);
+ }
+ return QString();
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index f506d7dd6f..957c4e9cbd 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -184,6 +184,8 @@ public:
virtual void create();
virtual void destroy();
+ static QString windowTitle(const QXcbConnection *conn, xcb_window_t window);
+
public Q_SLOTS:
void updateSyncRequestCounter();
diff --git a/src/plugins/platformthemes/flatpak/qflatpakfiledialog.cpp b/src/plugins/platformthemes/flatpak/qflatpakfiledialog.cpp
index c51223186e..1a24015ce5 100644
--- a/src/plugins/platformthemes/flatpak/qflatpakfiledialog.cpp
+++ b/src/plugins/platformthemes/flatpak/qflatpakfiledialog.cpp
@@ -147,61 +147,7 @@ void QFlatpakFileDialog::initializeDialog()
setDirectory(options()->initialDirectory());
}
-bool QFlatpakFileDialog::defaultNameFilterDisables() const
-{
- return false;
-}
-
-void QFlatpakFileDialog::setDirectory(const QUrl &directory)
-{
- Q_D(QFlatpakFileDialog);
-
- d->directory = directory.path();
-}
-
-QUrl QFlatpakFileDialog::directory() const
-{
- Q_D(const QFlatpakFileDialog);
-
- return d->directory;
-}
-
-void QFlatpakFileDialog::selectFile(const QUrl &filename)
-{
- Q_D(QFlatpakFileDialog);
-
- d->selectedFiles << filename.path();
-}
-
-QList<QUrl> QFlatpakFileDialog::selectedFiles() const
-{
- Q_D(const QFlatpakFileDialog);
-
- QList<QUrl> files;
- for (const QString &file : d->selectedFiles) {
- files << QUrl(file);
- }
- return files;
-}
-
-void QFlatpakFileDialog::setFilter()
-{
- // TODO
-}
-
-void QFlatpakFileDialog::selectNameFilter(const QString &filter)
-{
- Q_UNUSED(filter);
- // TODO
-}
-
-QString QFlatpakFileDialog::selectedNameFilter() const
-{
- // TODO
- return QString();
-}
-
-void QFlatpakFileDialog::exec()
+void QFlatpakFileDialog::openPortal()
{
Q_D(const QFlatpakFileDialog);
@@ -305,7 +251,64 @@ void QFlatpakFileDialog::exec()
SLOT(gotResponse(uint,QVariantMap)));
}
});
+}
+bool QFlatpakFileDialog::defaultNameFilterDisables() const
+{
+ return false;
+}
+
+void QFlatpakFileDialog::setDirectory(const QUrl &directory)
+{
+ Q_D(QFlatpakFileDialog);
+
+ d->directory = directory.path();
+}
+
+QUrl QFlatpakFileDialog::directory() const
+{
+ Q_D(const QFlatpakFileDialog);
+
+ return d->directory;
+}
+
+void QFlatpakFileDialog::selectFile(const QUrl &filename)
+{
+ Q_D(QFlatpakFileDialog);
+
+ d->selectedFiles << filename.path();
+}
+
+QList<QUrl> QFlatpakFileDialog::selectedFiles() const
+{
+ Q_D(const QFlatpakFileDialog);
+
+ QList<QUrl> files;
+ for (const QString &file : d->selectedFiles) {
+ files << QUrl(file);
+ }
+ return files;
+}
+
+void QFlatpakFileDialog::setFilter()
+{
+ // TODO
+}
+
+void QFlatpakFileDialog::selectNameFilter(const QString &filter)
+{
+ Q_UNUSED(filter);
+ // TODO
+}
+
+QString QFlatpakFileDialog::selectedNameFilter() const
+{
+ // TODO
+ return QString();
+}
+
+void QFlatpakFileDialog::exec()
+{
// HACK we have to avoid returning until we emit that the dialog was accepted or rejected
QEventLoop loop;
loop.connect(this, SIGNAL(accept()), SLOT(quit()));
@@ -327,6 +330,8 @@ bool QFlatpakFileDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality wi
d->modal = windowModality != Qt::NonModal;
d->winId = parent ? parent->winId() : 0;
+ openPortal();
+
return true;
}
diff --git a/src/plugins/platformthemes/flatpak/qflatpakfiledialog_p.h b/src/plugins/platformthemes/flatpak/qflatpakfiledialog_p.h
index 8f65d07e62..f3e195faa0 100644
--- a/src/plugins/platformthemes/flatpak/qflatpakfiledialog_p.h
+++ b/src/plugins/platformthemes/flatpak/qflatpakfiledialog_p.h
@@ -90,6 +90,7 @@ private Q_SLOTS:
private:
void initializeDialog();
+ void openPortal();
QScopedPointer<QFlatpakFileDialogPrivate> d_ptr;
};
diff --git a/src/plugins/printsupport/cups/qcupsprintengine.cpp b/src/plugins/printsupport/cups/qcupsprintengine.cpp
index 763f676e41..bd0d641e79 100644
--- a/src/plugins/printsupport/cups/qcupsprintengine.cpp
+++ b/src/plugins/printsupport/cups/qcupsprintengine.cpp
@@ -250,38 +250,6 @@ void QCupsPrintEnginePrivate::closePrintDevice()
}
}
-void QCupsPrintEnginePrivate::setupDefaultPrinter()
-{
- // Should never have reached here if no plugin available, but check just in case
- QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get();
- if (!ps)
- return;
-
- // Get default printer id, if no default then use the first available
- // TODO Find way to remove printerName from base class?
- printerName = ps->defaultPrintDeviceId();
- if (printerName.isEmpty()) {
- QStringList list = ps->availablePrintDeviceIds();
- if (list.size() > 0)
- printerName = list.at(0);
- }
-
- // Should never have reached here if no printers available, but check just in case
- if (printerName.isEmpty())
- return;
-
- m_printDevice = ps->createPrintDevice(printerName);
- if (!m_printDevice.isValid())
- return;
-
- // Setup the printer defaults
- duplex = m_printDevice.defaultDuplexMode();
- grayscale = m_printDevice.defaultColorMode() == QPrint::GrayScale;
- // CUPS server always supports collation, even if individual m_printDevice doesn't
- collate = true;
- setPageSize(m_printDevice.defaultPageSize());
-}
-
void QCupsPrintEnginePrivate::changePrinter(const QString &newPrinter)
{
// Don't waste time if same printer name
diff --git a/src/plugins/printsupport/cups/qcupsprintengine_p.h b/src/plugins/printsupport/cups/qcupsprintengine_p.h
index c99c48c7ea..d5363bb8cc 100644
--- a/src/plugins/printsupport/cups/qcupsprintengine_p.h
+++ b/src/plugins/printsupport/cups/qcupsprintengine_p.h
@@ -93,7 +93,6 @@ public:
private:
Q_DISABLE_COPY(QCupsPrintEnginePrivate)
- void setupDefaultPrinter();
void changePrinter(const QString &newPrinter);
void setPageSize(const QPageSize &pageSize);
diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm
index 1041187407..10fe3f6f0e 100644
--- a/src/plugins/styles/mac/qmacstyle_mac.mm
+++ b/src/plugins/styles/mac/qmacstyle_mac.mm
@@ -237,6 +237,19 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QIndeterminateProgressIndicator);
@end
+@interface QT_MANGLE_NAMESPACE(QVerticalSplitView) : NSSplitView
+- (BOOL)isVertical;
+@end
+
+QT_NAMESPACE_ALIAS_OBJC_CLASS(QVerticalSplitView);
+
+@implementation QVerticalSplitView
+- (BOOL)isVertical
+{
+ return YES;
+}
+@end
+
QT_BEGIN_NAMESPACE
// The following constants are used for adjusting the size
@@ -2002,6 +2015,15 @@ NSView *QMacStylePrivate::cocoaControl(CocoaControl widget) const
// at construction time, and it cannot be changed later.
bv = [[NSSlider alloc] initWithFrame:NSMakeRect(0, 0, 20, 200)];
break;
+ case SplitView_Horizontal:
+ bv = [[NSSplitView alloc] init];
+ break;
+ case SplitView_Vertical:
+ bv = [[QVerticalSplitView alloc] init];
+ break;
+ case TextField:
+ bv = [[NSTextField alloc] init];
+ break;
default:
break;
}
@@ -2076,7 +2098,7 @@ NSCell *QMacStylePrivate::cocoaCell(CocoaControl widget) const
return cell;
}
-void QMacStylePrivate::drawNSViewInRect(CocoaControl widget, NSView *view, const QRect &qtRect, QPainter *p, bool isQWidget, DrawRectBlock drawRectBlock) const
+void QMacStylePrivate::drawNSViewInRect(CocoaControl widget, NSView *view, const QRect &qtRect, QPainter *p, bool isQWidget, __attribute__((noescape)) DrawRectBlock drawRectBlock) const
{
QPoint offset;
if (widget == CocoaControl(Button_PopupButton, QStyleHelper::SizeSmall))
@@ -3444,35 +3466,21 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
case PE_FrameLineEdit:
if (const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
if (frame->state & State_Sunken) {
- QColor baseColor(frame->palette.background().color());
- HIThemeFrameDrawInfo fdi;
- fdi.version = qt_mac_hitheme_version;
- fdi.state = tds;
- int frame_size;
- fdi.kind = frame->features & QStyleOptionFrame::Rounded ? kHIThemeFrameTextFieldRound :
- kHIThemeFrameTextFieldSquare;
- frame_size = qt_mac_aqua_get_metric(EditTextFrameOutset);
- if ((frame->state & State_ReadOnly) || !(frame->state & State_Enabled))
- fdi.state = kThemeStateInactive;
- else if (fdi.state == kThemeStatePressed)
- // This pressed state doesn't make sense for a line edit frame.
- // And Yosemite agrees with us. Otherwise it starts showing yellow pixels.
- fdi.state = kThemeStateActive;
- fdi.isFocused = (frame->state & State_HasFocus);
- int lw = frame->lineWidth;
- if (lw <= 0)
- lw = proxy()->pixelMetric(PM_DefaultFrameWidth, frame, w);
- { //clear to base color
- p->save();
- p->setPen(QPen(baseColor, lw));
- p->setBrush(Qt::NoBrush);
- p->drawRect(frame->rect);
- p->restore();
- }
- const auto frameMargins = QMargins(frame_size, frame_size, frame_size, frame_size);
- const CGRect cgRect = frame->rect.marginsRemoved(frameMargins).toCGRect();
-
- HIThemeDrawFrame(&cgRect, &fdi, cg, kHIThemeOrientationNormal);
+ const bool isEnabled = opt->state & State_Enabled;
+ const bool isReadOnly = opt->state & State_ReadOnly;
+ const bool isRounded = frame->features & QStyleOptionFrame::Rounded;
+ const auto cs = d->effectiveAquaSizeConstrain(opt, w, CT_LineEdit);
+ const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::TextField, cs);
+ auto *tf = static_cast<NSTextField *>(d->cocoaControl(cw));
+ tf.enabled = isEnabled;
+ tf.editable = !isReadOnly;
+ tf.bezeled = YES;
+ static_cast<NSTextFieldCell *>(tf.cell).bezelStyle = isRounded ? NSTextFieldRoundedBezel : NSTextFieldSquareBezel;
+ tf.frame = opt->rect.toCGRect();
+ d->drawNSViewInRect(cw, tf, opt->rect, p, w != nullptr, ^(CGContextRef ctx, const CGRect &rect) {
+ Q_UNUSED(ctx);
+ [tf.cell drawWithFrame:rect inView:tf];
+ });
} else {
QCommonStyle::drawPrimitive(pe, opt, p, w);
}
@@ -4498,13 +4506,16 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
break;
}
case CE_Splitter:
- if (opt->rect.width() > 1 && opt->rect.height() > 1){
- HIThemeSplitterDrawInfo sdi;
- sdi.version = qt_mac_hitheme_version;
- sdi.state = tds;
- sdi.adornment = kHIThemeSplitterAdornmentMetal;
- CGRect cgRect = opt->rect.toCGRect();
- HIThemeDrawPaneSplitter(&cgRect, &sdi, cg, kHIThemeOrientationNormal);
+ if (opt->rect.width() > 1 && opt->rect.height() > 1) {
+ const bool isVertical = !(opt->state & QStyle::State_Horizontal);
+ // Qt refers to the layout orientation, while Cocoa refers to the divider's.
+ const auto ct = isVertical ? QMacStylePrivate::SplitView_Horizontal : QMacStylePrivate::SplitView_Vertical;
+ const auto cw = QMacStylePrivate::CocoaControl(ct, QStyleHelper::SizeLarge);
+ auto *sv = static_cast<NSSplitView *>(d->cocoaControl(cw));
+ sv.frame = opt->rect.toCGRect();
+ d->drawNSViewInRect(cw, sv, opt->rect, p, w != nullptr, ^(CGContextRef ctx, const CGRect &rect) {
+ [sv drawDividerInRect:rect];
+ });
} else {
QPen oldPen = p->pen();
p->setPen(opt->palette.dark().color());
diff --git a/src/plugins/styles/mac/qmacstyle_mac_p_p.h b/src/plugins/styles/mac/qmacstyle_mac_p_p.h
index cf2609e9ec..00dc8a9b53 100644
--- a/src/plugins/styles/mac/qmacstyle_mac_p_p.h
+++ b/src/plugins/styles/mac/qmacstyle_mac_p_p.h
@@ -200,7 +200,10 @@ public:
Scroller_Vertical,
Slider_Horizontal,
Slider_Vertical,
- Stepper // QSpinBox buttons
+ SplitView_Horizontal,
+ SplitView_Vertical,
+ Stepper, // QSpinBox buttons
+ TextField
};
typedef QPair<CocoaControlType, QStyleHelper::WidgetSizePolicy> CocoaControl;
@@ -270,7 +273,7 @@ public:
void setupVerticalInvertedXform(CGContextRef cg, bool reverse, bool vertical, const CGRect &rect) const;
- void drawNSViewInRect(CocoaControl widget, NSView *view, const QRect &rect, QPainter *p, bool isQWidget = true, DrawRectBlock drawRectBlock = nil) const;
+ void drawNSViewInRect(CocoaControl widget, NSView *view, const QRect &rect, QPainter *p, bool isQWidget = true, __attribute__((noescape)) DrawRectBlock drawRectBlock = nil) const;
void resolveCurrentNSView(QWindow *window) const;
void drawFocusRing(QPainter *p, const QRect &targetRect, int hMargin, int vMargin, qreal radius = 0) const;
diff --git a/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp b/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp
index 078875033f..6add110249 100644
--- a/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp
+++ b/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp
@@ -990,7 +990,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ToolBarTheme,
TP_DROPDOWNBUTTON);
if (theme.isValid()) {
- const QSizeF size = theme.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget);
+ const QSizeF size = theme.size() * QStyleHelper::dpiScaled(1);
if (!size.isEmpty()) {
mbiw = qRound(size.width());
mbih = qRound(size.height());
@@ -1513,7 +1513,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
if (d->transitionsEnabled() && canAnimate(option))
{
- if (control == CC_ScrollBar || control == CC_SpinBox ) {
+ if (control == CC_ScrollBar || control == CC_SpinBox || control == CC_ComboBox) {
QObject *styleObject = option->styleObject; // Can be widget or qquickitem
@@ -1643,12 +1643,28 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
} else {
if (sub & SC_ComboBoxFrame) {
- QStyleOptionButton btn;
- btn.QStyleOption::operator=(*option);
- btn.rect = option->rect.adjusted(-1, -1, 1, 1);
- if (sub & SC_ComboBoxArrow)
- btn.features = QStyleOptionButton::HasMenu;
- proxy()->drawControl(QStyle::CE_PushButton, &btn, painter, widget);
+ XPThemeData theme(widget, painter, QWindowsXPStylePrivate::ComboboxTheme);
+ theme.rect = option->rect;
+ theme.partId = CP_READONLY;
+ if (!(cmb->state & State_Enabled))
+ theme.stateId = CBXS_DISABLED;
+ else if (cmb->state & State_Sunken || cmb->state & State_On)
+ theme.stateId = CBXS_PRESSED;
+ else if (cmb->state & State_MouseOver)
+ theme.stateId = CBXS_HOT;
+ else
+ theme.stateId = CBXS_NORMAL;
+ d->drawBackground(theme);
+ }
+ if (sub & SC_ComboBoxArrow) {
+ XPThemeData theme(widget, painter, QWindowsXPStylePrivate::ComboboxTheme);
+ theme.rect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget);
+ theme.partId = option->direction == Qt::RightToLeft ? CP_DROPDOWNBUTTONLEFT : CP_DROPDOWNBUTTONRIGHT;
+ if (!(cmb->state & State_Enabled))
+ theme.stateId = CBXS_DISABLED;
+ else
+ theme.stateId = CBXS_NORMAL;
+ d->drawBackground(theme);
}
}
}
@@ -2123,15 +2139,12 @@ QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOpt
#if QT_CONFIG(combobox)
case CC_ComboBox:
if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
- int x = cb->rect.x(),
- y = cb->rect.y(),
- wi = cb->rect.width(),
- he = cb->rect.height();
- int xpos = x;
- int margin = cb->frame ? 3 : 0;
- int bmarg = cb->frame ? 2 : 0;
- int arrowButtonWidth = bmarg + 16;
- xpos += wi - arrowButtonWidth;
+ const int x = cb->rect.x(), y = cb->rect.y(), wi = cb->rect.width(), he = cb->rect.height();
+ const int margin = cb->frame ? 3 : 0;
+ const int bmarg = cb->frame ? 2 : 0;
+ const int arrowWidth = qRound(QStyleHelper::dpiScaled(16));
+ const int arrowButtonWidth = bmarg + arrowWidth;
+ const int xpos = x + wi - arrowButtonWidth;
switch (subControl) {
case SC_ComboBoxFrame:
@@ -2141,7 +2154,7 @@ QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOpt
rect.setRect(xpos, y , arrowButtonWidth, he);
break;
case SC_ComboBoxEditField:
- rect.setRect(x + margin, y + margin, wi - 2 * margin - 16, he - 2 * margin);
+ rect.setRect(x + margin, y + margin, wi - 2 * margin - arrowWidth, he - 2 * margin);
break;
case SC_ComboBoxListBoxPopup:
rect = cb->rect;
diff --git a/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp
index cf344c8f88..ff27cab98a 100644
--- a/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp
+++ b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp
@@ -887,6 +887,7 @@ bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa
PROPERTYORIGIN origin = PO_NOTFOUND;
GetThemePropertyOrigin(themeData.handle(), themeData.partId, themeData.stateId, TMT_BORDERSIZE, &origin);
GetThemeInt(themeData.handle(), themeData.partId, themeData.stateId, TMT_BORDERSIZE, &borderSize);
+ borderSize *= additionalDevicePixelRatio;
// Clip away border region
if ((origin == PO_CLASS || origin == PO_PART || origin == PO_STATE) && borderSize > 0) {
@@ -996,7 +997,7 @@ bool QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa
}
if (addBorderContentClipping)
- painter->setClipRegion(extraClip, Qt::IntersectClip);
+ painter->setClipRegion(scaleRegion(extraClip, 1.0 / additionalDevicePixelRatio), Qt::IntersectClip);
if (!themeData.mirrorHorizontally && !themeData.mirrorVertically && !themeData.rotate) {
if (!haveCachedPixmap)
@@ -1479,11 +1480,12 @@ case PE_Frame:
// GetThemeInt(theme.handle(), partId, stateId, TMT_BORDERCOLOR, &borderSize);
// Inner white border
- p->setPen(QPen(option->palette.base().color(), 1));
- p->drawRect(option->rect.adjusted(1, 1, -2, -2));
+ p->setPen(QPen(option->palette.base().color(), 0));
+ p->drawRect(QRectF(option->rect).adjusted(QStyleHelper::dpiScaled(0.5), QStyleHelper::dpiScaled(0.5),
+ QStyleHelper::dpiScaled(-1), QStyleHelper::dpiScaled(-1)));
// Outer dark border
- p->setPen(QPen(bordercolor, 1));
- p->drawRect(option->rect.adjusted(0, 0, -1, -1));
+ p->setPen(QPen(bordercolor, 0));
+ p->drawRect(QRectF(option->rect).adjusted(0, 0, QStyleHelper::dpiScaled(-0.5), QStyleHelper::dpiScaled(-0.5)));
p->setPen(oldPen);
return;
} else if (fillType == BT_NONE) {
@@ -3511,9 +3513,8 @@ QRect QWindowsXPStyle::subControlRect(ComplexControl cc, const QStyleOptionCompl
case CC_ComboBox:
if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
- int x = cmb->rect.x(), y = cmb->rect.y(), wi = cmb->rect.width(), he = cmb->rect.height();
- int xpos = x;
- xpos += wi - 1 - 16;
+ const int x = cmb->rect.x(), y = cmb->rect.y(), wi = cmb->rect.width(), he = cmb->rect.height();
+ const int xpos = x + wi - qRound(QStyleHelper::dpiScaled(1 + 16));
switch (subControl) {
case SC_ComboBoxFrame:
@@ -3521,11 +3522,13 @@ QRect QWindowsXPStyle::subControlRect(ComplexControl cc, const QStyleOptionCompl
break;
case SC_ComboBoxArrow:
- rect = QRect(xpos, y+1, 16, he-2);
+ rect = QRect(xpos, y + qRound(QStyleHelper::dpiScaled(1)),
+ qRound(QStyleHelper::dpiScaled(16)), he - qRound(QStyleHelper::dpiScaled(2)));
break;
case SC_ComboBoxEditField:
- rect = QRect(x+2, y+2, wi-3-16, he-4);
+ rect = QRect(x + qRound(QStyleHelper::dpiScaled(2)), y + qRound(QStyleHelper::dpiScaled(2)),
+ wi - qRound(QStyleHelper::dpiScaled(3 + 16)), he - qRound(QStyleHelper::dpiScaled(4)));
break;
case SC_ComboBoxListBoxPopup:
diff --git a/src/printsupport/dialogs/qprintdialog_unix.cpp b/src/printsupport/dialogs/qprintdialog_unix.cpp
index 2cc5bfbb8c..caab7867dc 100644
--- a/src/printsupport/dialogs/qprintdialog_unix.cpp
+++ b/src/printsupport/dialogs/qprintdialog_unix.cpp
@@ -403,6 +403,10 @@ QPrintPropertiesDialog::~QPrintPropertiesDialog()
void QPrintPropertiesDialog::setupPrinter() const
{
+#if QT_CONFIG(cups)
+ QCUPSSupport::clearCupsOptions(m_printer);
+#endif
+
widget.pageSetup->setupPrinter();
#if QT_CONFIG(cupsjobwidget)
m_jobOptions->setupPrinter();
diff --git a/src/printsupport/kernel/qcups.cpp b/src/printsupport/kernel/qcups.cpp
index be170ed619..7e8e1707b2 100644
--- a/src/printsupport/kernel/qcups.cpp
+++ b/src/printsupport/kernel/qcups.cpp
@@ -77,6 +77,11 @@ void QCUPSSupport::clearCupsOption(QPrinter *printer, const QString &option)
}
}
+void QCUPSSupport::clearCupsOptions(QPrinter *printer)
+{
+ setCupsOptions(printer, QStringList());
+}
+
static inline QString jobHoldToString(const QCUPSSupport::JobHoldUntil jobHold, const QTime holdUntilTime)
{
switch (jobHold) {
diff --git a/src/printsupport/kernel/qcups_p.h b/src/printsupport/kernel/qcups_p.h
index da2b087d5b..9a71483bb9 100644
--- a/src/printsupport/kernel/qcups_p.h
+++ b/src/printsupport/kernel/qcups_p.h
@@ -132,6 +132,7 @@ public:
static void setCupsOption(QPrinter *printer, const QString &option, const QString &value);
static void clearCupsOption(QPrinter *printer, const QString &option);
+ static void clearCupsOptions(QPrinter *printer);
static void setJobHold(QPrinter *printer, const JobHoldUntil jobHold = NoHold, const QTime &holdUntilTime = QTime());
static void setJobBilling(QPrinter *printer, const QString &jobBilling = QString());
diff --git a/src/printsupport/kernel/qplatformprintersupport.cpp b/src/printsupport/kernel/qplatformprintersupport.cpp
index e12a292aec..a25dc6d45c 100644
--- a/src/printsupport/kernel/qplatformprintersupport.cpp
+++ b/src/printsupport/kernel/qplatformprintersupport.cpp
@@ -89,11 +89,6 @@ QPrintDevice QPlatformPrinterSupport::createPrintDevice(const QString &id)
return QPrintDevice();
}
-QPrintDevice QPlatformPrinterSupport::createDefaultPrintDevice()
-{
- return createPrintDevice(defaultPrintDeviceId());
-}
-
QStringList QPlatformPrinterSupport::availablePrintDeviceIds() const
{
return QStringList();
diff --git a/src/printsupport/kernel/qplatformprintersupport.h b/src/printsupport/kernel/qplatformprintersupport.h
index 6a4246adc0..413c1067c2 100644
--- a/src/printsupport/kernel/qplatformprintersupport.h
+++ b/src/printsupport/kernel/qplatformprintersupport.h
@@ -76,7 +76,6 @@ public:
virtual QPaintEngine *createPaintEngine(QPrintEngine *, QPrinter::PrinterMode printerMode);
virtual QPrintDevice createPrintDevice(const QString &id);
- virtual QPrintDevice createDefaultPrintDevice();
virtual QStringList availablePrintDeviceIds() const;
virtual QString defaultPrintDeviceId() const;
diff --git a/src/src.pro b/src/src.pro
index a2064b1362..3b93b1a9d8 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -1,6 +1,6 @@
TEMPLATE = subdirs
-QT_FOR_CONFIG += gui-private
+QT_FOR_CONFIG += core-private gui-private
include($$OUT_PWD/corelib/qtcore-config.pri)
include($$OUT_PWD/gui/qtgui-config.pri)
@@ -30,6 +30,10 @@ src_tools_qlalr.target = sub-qlalr
force_bootstrap: src_tools_qlalr.depends = src_tools_bootstrap
else: src_tools_qlalr.depends = src_corelib
+src_tools_tracegen.subdir = tools/tracegen
+src_tools_tracegen.target = sub-tracegen
+src_tools_tracegen.depends = src_tools_bootstrap
+
src_tools_uic.subdir = tools/uic
src_tools_uic.target = sub-uic
force_bootstrap: src_tools_uic.depends = src_tools_bootstrap
@@ -152,8 +156,13 @@ qtConfig(regularexpression):pcre2 {
SUBDIRS += src_3rdparty_pcre2
src_corelib.depends += src_3rdparty_pcre2
}
-SUBDIRS += src_corelib src_tools_qlalr
TOOLS = src_tools_moc src_tools_rcc src_tools_qlalr src_tools_qfloat16_tables
+!force_bootstrap:if(qtConfig(lttng)|qtConfig(etw)) {
+ SUBDIRS += src_tools_tracegen
+ src_corelib.depends += src_tools_tracegen
+ TOOLS += src_tools_tracegen
+}
+SUBDIRS += src_corelib src_tools_qlalr
win32:SUBDIRS += src_winmain
qtConfig(network) {
SUBDIRS += src_network
@@ -220,7 +229,8 @@ android: SUBDIRS += src_android src_3rdparty_gradle
TR_EXCLUDE = \
src_tools_bootstrap src_tools_moc src_tools_rcc src_tools_uic src_tools_qlalr \
src_tools_bootstrap_dbus src_tools_qdbusxml2cpp src_tools_qdbuscpp2xml \
- src_3rdparty_pcre2 src_3rdparty_harfbuzzng src_3rdparty_freetype
+ src_3rdparty_pcre2 src_3rdparty_harfbuzzng src_3rdparty_freetype \
+ src_tools_tracegen
sub-tools.depends = $$TOOLS
QMAKE_EXTRA_TARGETS = sub-tools
diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro
index a88333f03a..a45382106a 100644
--- a/src/tools/bootstrap/bootstrap.pro
+++ b/src/tools/bootstrap/bootstrap.pro
@@ -32,7 +32,6 @@ SOURCES += \
../../corelib/global/qrandom.cpp \
../../corelib/io/qabstractfileengine.cpp \
../../corelib/io/qbuffer.cpp \
- ../../corelib/io/qdatastream.cpp \
../../corelib/io/qdebug.cpp \
../../corelib/io/qdir.cpp \
../../corelib/io/qdiriterator.cpp \
@@ -47,7 +46,6 @@ SOURCES += \
../../corelib/io/qresource.cpp \
../../corelib/io/qtemporarydir.cpp \
../../corelib/io/qtemporaryfile.cpp \
- ../../corelib/io/qtextstream.cpp \
../../corelib/io/qsavefile.cpp \
../../corelib/io/qstandardpaths.cpp \
../../corelib/io/qloggingcategory.cpp \
@@ -58,6 +56,17 @@ SOURCES += \
../../corelib/kernel/qvariant.cpp \
../../corelib/kernel/qsystemerror.cpp \
../../corelib/plugin/quuid.cpp \
+ ../../corelib/serialization/qdatastream.cpp \
+ ../../corelib/serialization/qjson.cpp \
+ ../../corelib/serialization/qjsondocument.cpp \
+ ../../corelib/serialization/qjsonobject.cpp \
+ ../../corelib/serialization/qjsonarray.cpp \
+ ../../corelib/serialization/qjsonvalue.cpp \
+ ../../corelib/serialization/qjsonparser.cpp \
+ ../../corelib/serialization/qjsonwriter.cpp \
+ ../../corelib/serialization/qtextstream.cpp \
+ ../../corelib/serialization/qxmlutils.cpp \
+ ../../corelib/serialization/qxmlstream.cpp \
../../corelib/tools/qbitarray.cpp \
../../corelib/tools/qbytearray.cpp \
../../corelib/tools/qarraydata.cpp \
@@ -84,15 +93,6 @@ SOURCES += \
../../corelib/tools/qstringlist.cpp \
../../corelib/tools/qversionnumber.cpp \
../../corelib/tools/qvsnprintf.cpp \
- ../../corelib/xml/qxmlutils.cpp \
- ../../corelib/xml/qxmlstream.cpp \
- ../../corelib/json/qjson.cpp \
- ../../corelib/json/qjsondocument.cpp \
- ../../corelib/json/qjsonobject.cpp \
- ../../corelib/json/qjsonarray.cpp \
- ../../corelib/json/qjsonvalue.cpp \
- ../../corelib/json/qjsonparser.cpp \
- ../../corelib/json/qjsonwriter.cpp \
../../xml/dom/qdom.cpp \
../../xml/sax/qxml.cpp
diff --git a/src/tools/tracegen/etw.cpp b/src/tools/tracegen/etw.cpp
new file mode 100644
index 0000000000..07f2d114b6
--- /dev/null
+++ b/src/tools/tracegen/etw.cpp
@@ -0,0 +1,228 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "etw.h"
+#include "provider.h"
+#include "helpers.h"
+#include "qtheaders.h"
+
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qtextstream.h>
+#include <qregexp.h>
+#include <quuid.h>
+
+static inline QString providerVar(const QString &providerName)
+{
+ return providerName + QLatin1String("_provider");
+}
+
+static void writeEtwMacro(QTextStream &stream, const Tracepoint::Field &field)
+{
+ const QString &name = field.name;
+
+ switch (field.backendType) {
+ case Tracepoint::Field::QtString:
+ stream << "TraceLoggingCountedWideString(reinterpret_cast<LPCWSTR>("
+ << name << ".utf16()), " << name << ".size(), \"" << name << "\")";
+ return;
+ case Tracepoint::Field::QtByteArray:
+ stream << "TraceLoggingBinary(" << name << ".constData(), "
+ << name << ".size(), \"" << name << "\")";
+ return;
+ case Tracepoint::Field::QtUrl:
+ stream << "TraceLoggingValue(" << name << ".toEncoded().constData(), \"" << name << "\")";
+ return;
+ case Tracepoint::Field::QtRect:
+ stream << "TraceLoggingValue(" << name << ".x(), \"x\"), "
+ << "TraceLoggingValue(" << name << ".y(), \"y\"), "
+ << "TraceLoggingValue(" << name << ".width(), \"width\"), "
+ << "TraceLoggingValue(" << name << ".height(), \"height\")";
+ return;
+ default:
+ break;
+ }
+
+ stream << "TraceLoggingValue(" << name << ", \"" << name << "\")";
+}
+
+static QString createGuid(const QUuid &uuid)
+{
+ QString guid;
+
+ QTextStream stream(&guid);
+
+ hex(stream);
+
+ stream << "("
+ << "0x" << uuid.data1 << ", "
+ << "0x" << uuid.data2 << ", "
+ << "0x" << uuid.data3 << ", "
+ << "0x" << uuid.data4[0] << ", "
+ << "0x" << uuid.data4[1] << ", "
+ << "0x" << uuid.data4[2] << ", "
+ << "0x" << uuid.data4[3] << ", "
+ << "0x" << uuid.data4[4] << ", "
+ << "0x" << uuid.data4[5] << ", "
+ << "0x" << uuid.data4[6] << ", "
+ << "0x" << uuid.data4[7]
+ << ")";
+
+ return guid;
+}
+
+static void writePrologue(QTextStream &stream, const QString &fileName, const QString &providerName)
+{
+ QUuid uuid = QUuid::createUuidV5(QUuid(), providerName.toLocal8Bit());
+
+ const QString provider = providerVar(providerName);
+ const QString guard = includeGuard(fileName);
+ const QString guid = createGuid(uuid);
+ const QString guidString = uuid.toString();
+
+ stream << "#ifndef " << guard << "\n"
+ << "#define " << guard << "\n"
+ << "#include <windows.h>\n"
+ << "#include <TraceLoggingProvider.h>\n";
+
+ /* TraceLogging API macros cannot deal with UTF8
+ * source files, so we work around it like this
+ */
+ stream << "#undef _TlgPragmaUtf8Begin\n"
+ "#undef _TlgPragmaUtf8End\n"
+ "#define _TlgPragmaUtf8Begin\n"
+ "#define _TlgPragmaUtf8End\n";
+
+ stream << qtHeaders();
+
+ stream << "\n";
+
+ stream << "#ifdef TRACEPOINT_DEFINE\n"
+ << "/* " << guidString << " */\n"
+ << "TRACELOGGING_DEFINE_PROVIDER(" << provider << ", \""
+ << providerName <<"\", " << guid << ");\n\n";
+
+ stream << "static inline void registerProvider()\n"
+ << "{\n"
+ << " TraceLoggingRegister(" << provider << ");\n"
+ << "}\n\n";
+
+ stream << "static inline void unregisterProvider()\n"
+ << "{\n"
+ << " TraceLoggingUnregister(" << provider << ");\n"
+ << "}\n";
+
+ stream << "Q_CONSTRUCTOR_FUNCTION(registerProvider)\n"
+ << "Q_DESTRUCTOR_FUNCTION(unregisterProvider)\n\n";
+
+ stream << "#else\n"
+ << "TRACELOGGING_DECLARE_PROVIDER(" << provider << ");\n"
+ << "#endif // TRACEPOINT_DEFINE\n\n";
+}
+
+static void writeEpilogue(QTextStream &stream, const QString &fileName)
+{
+ stream << "\n#endif // " << includeGuard(fileName) << "\n"
+ << "#include <private/qtrace_p.h>\n";
+}
+
+static void writeWrapper(QTextStream &stream, const Tracepoint &tracepoint,
+ const QString &providerName)
+{
+ const QString argList = formatFunctionSignature(tracepoint.args);
+ const QString paramList = formatParameterList(tracepoint.args, ETW);
+ const QString &name = tracepoint.name;
+ const QString includeGuard = QStringLiteral("TP_%1_%2").arg(providerName).arg(name).toUpper();
+ const QString provider = providerVar(providerName);
+
+ stream << "\n";
+
+ stream << "inline void trace_" << name << "(" << argList << ")\n"
+ << "{\n"
+ << " TraceLoggingWrite(" << provider << ", \"" << name << "\"";
+
+ for (const Tracepoint::Field &field : tracepoint.fields) {
+ stream << ",\n";
+ stream << " ";
+ writeEtwMacro(stream, field);
+ }
+
+ stream << ");\n"
+ << "}\n\n";
+
+ stream << "inline void do_trace_" << name << "(" << argList << ")\n"
+ << "{\n"
+ << " trace_" << name << "(" << paramList << ");\n"
+ << "}\n";
+
+ stream << "inline bool trace_" << name << "_enabled()\n"
+ << "{\n"
+ << " return TraceLoggingProviderEnabled(" << provider << ", 0, 0);\n"
+ << "}\n";
+}
+
+static void writeTracepoints(QTextStream &stream, const Provider &provider)
+{
+ if (provider.tracepoints.isEmpty())
+ return;
+
+ const QString includeGuard = QStringLiteral("TP_%1_PROVIDER").arg(provider.name).toUpper();
+
+ stream << "#if !defined(" << includeGuard << ") && !defined(TRACEPOINT_DEFINE)\n"
+ << "#define " << includeGuard << "\n"
+ << "namespace QtPrivate {\n";
+
+ for (const Tracepoint &t : provider.tracepoints)
+ writeWrapper(stream, t, provider.name);
+
+ stream << "} // namespace QtPrivate\n"
+ << "#endif // " << includeGuard << "\n\n";
+}
+
+void writeEtw(QFile &file, const Provider &provider)
+{
+ QTextStream stream(&file);
+
+ const QString fileName = QFileInfo(file.fileName()).fileName();
+
+ writePrologue(stream, fileName, provider.name);
+ writeTracepoints(stream, provider);
+ writeEpilogue(stream, fileName);
+}
+
diff --git a/src/tools/tracegen/etw.h b/src/tools/tracegen/etw.h
new file mode 100644
index 0000000000..5fc9b57eaa
--- /dev/null
+++ b/src/tools/tracegen/etw.h
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ETW_H
+#define ETW_H
+
+struct Provider;
+class QFile;
+
+void writeEtw(QFile &device, const Provider &p);
+
+#endif // ETW_H
diff --git a/src/tools/tracegen/helpers.cpp b/src/tools/tracegen/helpers.cpp
new file mode 100644
index 0000000000..f0ac7ed47f
--- /dev/null
+++ b/src/tools/tracegen/helpers.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "helpers.h"
+#include <qdebug.h>
+
+QString includeGuard(const QString &filename)
+{
+ QString guard = filename.toUpper();
+
+ for (int i = 0; i < guard.size(); ++i) {
+ if (!guard.at(i).isLetterOrNumber())
+ guard[i] = QChar('_');
+ }
+
+ return guard;
+}
+
+template <typename T>
+static QString joinArguments(const QVector<Tracepoint::Argument> &args, T joinFunction)
+{
+ QString ret;
+ bool first = true;
+
+ for (const Tracepoint::Argument &arg : args) {
+ if (!first)
+ ret += QLatin1String(", ");
+
+ ret += joinFunction(arg);
+
+ first = false;
+ }
+
+ return ret;
+}
+
+QString formatFunctionSignature(const QVector<Tracepoint::Argument> &args)
+{
+ return joinArguments(args, [](const Tracepoint::Argument &arg) {
+ return QStringLiteral("%1 %2").arg(arg.type).arg(arg.name);
+ });
+}
+
+QString formatParameterList(const QVector<Tracepoint::Argument> &args, ParamType type)
+{
+ if (type == LTTNG) {
+ QString ret;
+
+ for (const Tracepoint::Argument &arg : args)
+ ret += QLatin1String(", ") + arg.name;
+
+ return ret;
+ }
+
+ return joinArguments(args, [](const Tracepoint::Argument &arg) { return arg.name; });
+}
diff --git a/src/tools/tracegen/helpers.h b/src/tools/tracegen/helpers.h
new file mode 100644
index 0000000000..77f16a0da6
--- /dev/null
+++ b/src/tools/tracegen/helpers.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef HELPERS_H
+#define HELPERS_H
+
+#include "provider.h"
+
+#include <qvector.h>
+#include <qstring.h>
+
+enum ParamType {
+ LTTNG,
+ ETW
+};
+
+QString includeGuard(const QString &filename);
+QString formatFunctionSignature(const QVector<Tracepoint::Argument> &args);
+QString formatParameterList(const QVector<Tracepoint::Argument> &args, ParamType type);
+
+#endif // HELPERS_H
diff --git a/src/tools/tracegen/lttng.cpp b/src/tools/tracegen/lttng.cpp
new file mode 100644
index 0000000000..6c0d8cc88b
--- /dev/null
+++ b/src/tools/tracegen/lttng.cpp
@@ -0,0 +1,215 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "lttng.h"
+#include "provider.h"
+#include "helpers.h"
+#include "panic.h"
+#include "qtheaders.h"
+
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qtextstream.h>
+#include <qregexp.h>
+#include <qdebug.h>
+
+static void writeCtfMacro(QTextStream &stream, const Tracepoint::Field &field)
+{
+ const QString &paramType = field.paramType;
+ const QString &name = field.name;
+ const QString &seqLen = field.seqLen;
+ const int arrayLen = field.arrayLen;
+
+ switch (field.backendType) {
+ case Tracepoint::Field::Array:
+ stream << "ctf_array(" <<paramType << ", "
+ << name << ", " << name << ", " << arrayLen << ")";
+ return;
+ case Tracepoint::Field::Sequence:
+ stream << "ctf_sequence(" << paramType
+ << ", " << name << ", " << name
+ << ", unsigned int, " << seqLen << ")";
+ return;
+ case Tracepoint::Field::Integer:
+ stream << "ctf_integer(" << paramType << ", " << name << ", " << name << ")";
+ return;
+ case Tracepoint::Field::Float:
+ stream << "ctf_float(" << paramType << ", " << name << ", " << name << ")";
+ return;
+ case Tracepoint::Field::String:
+ stream << "ctf_string(" << name << ", " << name << ")";
+ return;
+ case Tracepoint::Field::QtString:
+ stream << "ctf_sequence(const ushort, " << name << ", "
+ << name << ".utf16(), unsigned int, " << name << ".size())";
+ return;
+ case Tracepoint::Field::QtByteArray:
+ stream << "ctf_sequence(const char, " << name << ", "
+ << name << ".constData(), unsigned int, " << name << ".size())";
+ return;
+ case Tracepoint::Field::QtUrl:
+ stream << "ctf_sequence(const char, " << name << ", "
+ << name << ".toEncoded().constData(), unsigned int, "
+ << name << ".toEncoded().size())";
+ return;
+ case Tracepoint::Field::QtRect:
+ stream << "ctf_integer(int, x, " << name << ".x()) "
+ << "ctf_integer(int, y, " << name << ".y()) "
+ << "ctf_integer(int, width, " << name << ".width()) "
+ << "ctf_integer(int, height, " << name << ".height()) ";
+ return;
+ case Tracepoint::Field::Unknown:
+ panic("Cannot deduce CTF type for '%s %s", qPrintable(paramType), qPrintable(name));
+ break;
+ }
+}
+
+static void writePrologue(QTextStream &stream, const QString &fileName, const QString &providerName)
+{
+ stream << "#undef TRACEPOINT_PROVIDER\n";
+ stream << "#define TRACEPOINT_PROVIDER " << providerName << "\n\n";
+
+ stream << qtHeaders();
+
+ const QString guard = includeGuard(fileName);
+
+ stream << "\n";
+
+ /* the first guard is the usual one, the second is required
+ * by LTTNG to force the re-evaluation of TRACEPOINT_* macros
+ */
+ stream << "#if !defined(" << guard << ") || defined(TRACEPOINT_HEADER_MULTI_READ)\n";
+
+ stream << "#define " << guard << "\n\n"
+ << "#undef TRACEPOINT_INCLUDE\n"
+ << "#define TRACEPOINT_INCLUDE \"" << fileName << "\"\n\n";
+
+ stream << "#include <lttng/tracepoint.h>\n\n";
+}
+
+static void writeEpilogue(QTextStream &stream, const QString &fileName)
+{
+ stream << "\n";
+ stream << "#endif // " << includeGuard(fileName) << "\n"
+ << "#include <lttng/tracepoint-event.h>\n"
+ << "#include <private/qtrace_p.h>\n";
+}
+
+static void writeWrapper(QTextStream &stream,
+ const Tracepoint &tracepoint, const QString &providerName)
+{
+ const QString argList = formatFunctionSignature(tracepoint.args);
+ const QString paramList = formatParameterList(tracepoint.args, LTTNG);
+ const QString &name = tracepoint.name;
+ const QString includeGuard = QStringLiteral("TP_%1_%2").arg(providerName).arg(name).toUpper();
+
+ /* prevents the redefinion of the inline wrapper functions
+ * once LTTNG recursively includes this header file
+ */
+ stream << "\n"
+ << "#ifndef " << includeGuard << "\n"
+ << "#define " << includeGuard << "\n"
+ << "namespace QtPrivate {\n";
+
+ stream << "inline void trace_" << name << "(" << argList << ")\n"
+ << "{\n"
+ << " tracepoint(" << providerName << ", " << name << paramList << ");\n"
+ << "}\n";
+
+ stream << "inline void do_trace_" << name << "(" << argList << ")\n"
+ << "{\n"
+ << " do_tracepoint(" << providerName << ", " << name << paramList << ");\n"
+ << "}\n";
+
+ stream << "inline bool trace_" << name << "_enabled()\n"
+ << "{\n"
+ << " return tracepoint_enabled(" << providerName << ", " << name << ");\n"
+ << "}\n";
+
+ stream << "} // namespace QtPrivate\n"
+ << "#endif // " << includeGuard << "\n\n";
+}
+
+static void writeTracepoint(QTextStream &stream,
+ const Tracepoint &tracepoint, const QString &providerName)
+{
+ stream << "TRACEPOINT_EVENT(\n"
+ << " " << providerName << ",\n"
+ << " " << tracepoint.name << ",\n"
+ << " TP_ARGS(";
+
+ const char *comma = nullptr;
+
+ for (const Tracepoint::Argument &arg : tracepoint.args) {
+ stream << comma << arg.type << ", " << arg.name;
+ comma = ", ";
+ }
+
+ stream << "),\n"
+ << " TP_FIELDS(";
+
+ const char *newline = nullptr;
+
+ for (const Tracepoint::Field &f : tracepoint.fields) {
+ stream << newline;
+ writeCtfMacro(stream, f);
+ newline = "\n ";
+ }
+
+ stream << ")\n)\n\n";
+}
+
+static void writeTracepoints(QTextStream &stream, const Provider &provider)
+{
+ for (const Tracepoint &t : provider.tracepoints) {
+ writeTracepoint(stream, t, provider.name);
+ writeWrapper(stream, t, provider.name);
+ }
+}
+
+void writeLttng(QFile &file, const Provider &provider)
+{
+ QTextStream stream(&file);
+
+ const QString fileName = QFileInfo(file.fileName()).fileName();
+
+ writePrologue(stream, fileName, provider.name);
+ writeTracepoints(stream, provider);
+ writeEpilogue(stream, fileName);
+}
diff --git a/src/tools/tracegen/lttng.h b/src/tools/tracegen/lttng.h
new file mode 100644
index 0000000000..0307b375bc
--- /dev/null
+++ b/src/tools/tracegen/lttng.h
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef LTTNG_H
+#define LTTNG_H
+
+struct Provider;
+class QFile;
+
+void writeLttng(QFile &device, const Provider &p);
+
+#endif // LTTNG_H
diff --git a/src/tools/tracegen/panic.cpp b/src/tools/tracegen/panic.cpp
new file mode 100644
index 0000000000..d1e207764e
--- /dev/null
+++ b/src/tools/tracegen/panic.cpp
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "panic.h"
+
+#include <cstdarg>
+#include <cstdio>
+#include <cstdlib>
+
+void panic(const char *fmt, ...)
+{
+ va_list ap;
+
+ fprintf(stderr, "tracegen: fatal: ");
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+
+ fputc('\n', stderr);
+
+ exit(EXIT_FAILURE);
+}
diff --git a/src/tools/tracegen/panic.h b/src/tools/tracegen/panic.h
new file mode 100644
index 0000000000..c6b195af00
--- /dev/null
+++ b/src/tools/tracegen/panic.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PANIC_H
+#define PANIC_H
+
+void panic(const char *fmt, ...);
+
+#endif // PANIC_H
diff --git a/src/tools/tracegen/provider.cpp b/src/tools/tracegen/provider.cpp
new file mode 100644
index 0000000000..00e105377e
--- /dev/null
+++ b/src/tools/tracegen/provider.cpp
@@ -0,0 +1,304 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "provider.h"
+#include "panic.h"
+
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qtextstream.h>
+#include <qregexp.h>
+#include <qstring.h>
+
+#ifdef TRACEGEN_DEBUG
+#include <qdebug.h>
+
+static void dumpTracepoint(const Tracepoint &t)
+{
+ qDebug() << "=== BEGIN TRACEPOINT ===";
+ qDebug() << "name:" << t.name;
+ qDebug() << "ARGS\n";
+
+ int j = 0;
+
+ for (auto i = t.args.constBegin(); i != t.args.constEnd(); ++i) {
+ qDebug() << "ARG[" << j << "] type:" << i->type;
+ qDebug() << "ARG[" << j << "] name:" << i->name;
+ qDebug() << "ARG[" << j << "] arrayLen:" << i->arrayLen;
+ ++j;
+ }
+
+ qDebug() << "\nFIELDS\n";
+
+ j = 0;
+
+ for (auto i = t.fields.constBegin(); i != t.fields.constEnd(); ++i) {
+ qDebug() << "FIELD[" << j << "] backend_type" << static_cast<int>(i->backendType);
+ qDebug() << "FIELD[" << j << "] param_type" << i->paramType;
+ qDebug() << "FIELD[" << j << "] name" << i->name;
+ qDebug() << "FIELD[" << j << "] arrayLen" << i->arrayLen;
+ qDebug() << "FIELD[" << j << "] seqLen" << i->seqLen;
+ ++j;
+ }
+
+ qDebug() << "=== END TRACEPOINT ===\n";
+
+}
+#endif
+
+static inline int arrayLength(const QString &rawType)
+{
+ /* matches the length of an ordinary array type
+ * Ex: foo[10] yields '10'
+ */
+ static const QRegExp rx(QStringLiteral(".*\\[([0-9]+)\\].*"));
+
+ if (!rx.exactMatch(rawType.trimmed()))
+ return 0;
+
+ return rx.cap(1).toInt();
+}
+
+static inline QString sequenceLength(const QString &rawType)
+{
+ /* matches the identifier pointing to length of a CTF sequence type, which is
+ * a dynamic sized array.
+ * Ex: in qcoreapplication_foo(const char[len], some_string, unsigned int, * len)
+ * it will match the 'len' part of 'const char[len]')
+ */
+ static const QRegExp rx(QStringLiteral(".*\\[([A-Za-z_][A-Za-z_0-9]*)\\].*"));
+
+ if (!rx.exactMatch(rawType.trimmed()))
+ return QString();
+
+ return rx.cap(1);
+}
+
+static QString decayArrayToPointer(QString type)
+{
+ /* decays an array to a pointer, i.e., if 'type' holds int[10],
+ * this function returns 'int *'
+ */
+ static QRegExp rx(QStringLiteral("\\[(.+)\\]"));
+
+ rx.setMinimal(true);
+ return type.replace(rx, QStringLiteral("*"));
+}
+
+static QString removeBraces(QString type)
+{
+ static const QRegExp rx(QStringLiteral("\\[.*\\]"));
+
+ return type.remove(rx);
+}
+
+static Tracepoint::Field::BackendType backendType(QString rawType)
+{
+ static const struct {
+ const char *type;
+ Tracepoint::Field::BackendType backendType;
+ } typeTable[] = {
+ { "bool", Tracepoint::Field::Integer },
+ { "short_int", Tracepoint::Field::Integer },
+ { "signed_short", Tracepoint::Field::Integer },
+ { "signed_short_int", Tracepoint::Field::Integer },
+ { "unsigned_short", Tracepoint::Field::Integer },
+ { "unsigned_short_int", Tracepoint::Field::Integer },
+ { "int", Tracepoint::Field::Integer },
+ { "signed", Tracepoint::Field::Integer },
+ { "signed_int", Tracepoint::Field::Integer },
+ { "unsigned", Tracepoint::Field::Integer },
+ { "unsigned_int", Tracepoint::Field::Integer },
+ { "long", Tracepoint::Field::Integer },
+ { "long_int", Tracepoint::Field::Integer },
+ { "signed_long", Tracepoint::Field::Integer },
+ { "signed_long_int", Tracepoint::Field::Integer },
+ { "unsigned_long", Tracepoint::Field::Integer },
+ { "unsigned_long_int", Tracepoint::Field::Integer },
+ { "long_long", Tracepoint::Field::Integer },
+ { "long_long_int", Tracepoint::Field::Integer },
+ { "signed_long_long", Tracepoint::Field::Integer },
+ { "signed_long_long_int", Tracepoint::Field::Integer },
+ { "unsigned_long_long", Tracepoint::Field::Integer },
+ { "char", Tracepoint::Field::Integer },
+ { "float", Tracepoint::Field::Float },
+ { "double", Tracepoint::Field::Float },
+ { "long_double", Tracepoint::Field::Float },
+ { "char_ptr", Tracepoint::Field::String },
+ { "QString", Tracepoint::Field::QtString },
+ { "QByteArray", Tracepoint::Field::QtByteArray },
+ { "QUrl", Tracepoint::Field::QtUrl },
+ { "QRect", Tracepoint::Field::QtRect }
+ };
+
+ auto backendType = [](const QString &rawType) {
+
+ static const size_t tableSize = sizeof (typeTable) / sizeof (typeTable[0]);
+
+ for (size_t i = 0; i < tableSize; ++i) {
+ if (rawType == QLatin1String(typeTable[i].type))
+ return typeTable[i].backendType;
+ }
+
+ return Tracepoint::Field::Unknown;
+ };
+
+ if (arrayLength(rawType) > 0)
+ return Tracepoint::Field::Array;
+
+ if (!sequenceLength(rawType).isNull())
+ return Tracepoint::Field::Sequence;
+
+ static const QRegExp constMatch(QStringLiteral("\\bconst\\b"));
+ rawType.remove(constMatch);
+ rawType.remove(QLatin1Char('&'));
+
+ static const QRegExp ptrMatch(QStringLiteral("\\s*\\*\\s*"));
+ rawType.replace(ptrMatch, QStringLiteral("_ptr"));
+ rawType = rawType.trimmed();
+ rawType.replace(QStringLiteral(" "), QStringLiteral("_"));
+
+ return backendType(rawType.trimmed());
+}
+
+static Tracepoint parseTracepoint(const QString &name, const QStringList &args,
+ const QString &fileName, const int lineNumber)
+{
+ Tracepoint t;
+ t.name = name;
+
+ if (args.isEmpty())
+ return t;
+
+ auto i = args.constBegin();
+ auto end = args.constEnd();
+ int argc = 0;
+
+ static const QRegExp rx(QStringLiteral("(.*)\\b([A-Za-z_][A-Za-z0-9_]*)$"));
+
+ while (i != end) {
+ rx.exactMatch(*i);
+
+ const QString type = rx.cap(1).trimmed();
+
+ if (type.isNull()) {
+ panic("Missing parameter type for argument %d of %s (%s:%d)",
+ argc, qPrintable(name), qPrintable(fileName), lineNumber);
+ }
+
+ const QString name = rx.cap(2).trimmed();
+
+ if (name.isNull()) {
+ panic("Missing parameter name for argument %d of %s (%s:%d)",
+ argc, qPrintable(name), qPrintable(fileName), lineNumber);
+ }
+
+ int arrayLen = arrayLength(type);
+
+ Tracepoint::Argument a;
+ a.arrayLen = arrayLen;
+ a.name = name;
+ a.type = decayArrayToPointer(type);
+
+ t.args << std::move(a);
+
+ Tracepoint::Field f;
+ f.backendType = backendType(type);
+ f.paramType = removeBraces(type);
+ f.name = name;
+ f.arrayLen = arrayLen;
+ f.seqLen = sequenceLength(type);
+
+ t.fields << std::move(f);
+
+ ++i;
+ }
+
+ return t;
+}
+
+Provider parseProvider(const QString &filename)
+{
+ QFile f(filename);
+
+ if (!f.open(QIODevice::ReadOnly | QIODevice::Text))
+ panic("Cannot open %s: %s", qPrintable(filename), qPrintable(f.errorString()));
+
+ QTextStream s(&f);
+
+ static const QRegExp tracedef(QStringLiteral("([A-Za-z][A-Za-z0-9_]*)\\((.*)\\)"));
+
+ int lineNumber = 0;
+
+ Provider provider;
+ provider.name = QFileInfo(filename).baseName();
+
+ for (;;) {
+ QString line = s.readLine().trimmed();
+
+ if (line.isNull())
+ break;
+
+ if (line.isEmpty() || line.startsWith(QStringLiteral("#"))) {
+ ++lineNumber;
+ continue;
+ }
+
+ if (tracedef.exactMatch(line)) {
+ const QString name = tracedef.cap(1);
+ QStringList args = tracedef.cap(2).split(QStringLiteral(","), QString::SkipEmptyParts);
+
+ if (args.at(0).isNull())
+ args.clear();
+
+ provider.tracepoints << parseTracepoint(name, args, filename, lineNumber);
+ } else {
+ panic("Syntax error whilre processing %s on line %d", qPrintable(filename), lineNumber);
+ }
+
+ ++lineNumber;
+ }
+
+#ifdef TRACEGEN_DEBUG
+ for (auto i = provider.tracepoints.constBegin(); i != provider.tracepoints.constEnd(); ++i)
+ dumpTracepoint(*i);
+#endif
+
+ return provider;
+}
diff --git a/src/tools/tracegen/provider.h b/src/tools/tracegen/provider.h
new file mode 100644
index 0000000000..d8cbd2662d
--- /dev/null
+++ b/src/tools/tracegen/provider.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PROVIDER_H
+#define PROVIDER_H
+
+#include <qvector.h>
+#include <qstring.h>
+#include <qtypeinfo.h>
+
+struct Tracepoint
+{
+ struct Argument
+ {
+ QString type;
+ QString name;
+ int arrayLen;
+ };
+
+ struct Field
+ {
+ enum BackendType {
+ Array,
+ Sequence,
+ Integer,
+ Float,
+ String,
+ QtString,
+ QtByteArray,
+ QtUrl,
+ QtRect,
+ Unknown
+ };
+
+ BackendType backendType;
+ QString paramType;
+ QString name;
+ int arrayLen;
+ QString seqLen;
+ };
+
+ QString name;
+ QVector<Argument> args;
+ QVector<Field> fields;
+};
+
+struct Provider
+{
+ QString name;
+ QVector<Tracepoint> tracepoints;
+};
+
+Provider parseProvider(const QString &filename);
+
+Q_DECLARE_TYPEINFO(Tracepoint::Argument, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(Tracepoint::Field, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(Tracepoint, Q_MOVABLE_TYPE);
+
+#endif // PROVIDER_H
diff --git a/src/tools/tracegen/qtheaders.cpp b/src/tools/tracegen/qtheaders.cpp
new file mode 100644
index 0000000000..eec3488a6d
--- /dev/null
+++ b/src/tools/tracegen/qtheaders.cpp
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtheaders.h"
+
+const char *qtHeaders()
+{
+ static const char headers[] = ""
+ "#include <QString>\n"
+ "#include <QByteArray>\n"
+ "#include <QUrl>\n"
+ "#include <QRect>\n";
+
+ return headers;
+}
diff --git a/src/tools/tracegen/qtheaders.h b/src/tools/tracegen/qtheaders.h
new file mode 100644
index 0000000000..b80d374ca8
--- /dev/null
+++ b/src/tools/tracegen/qtheaders.h
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTHEADERS_H
+#define QTHEADERS_H
+
+const char *qtHeaders();
+
+#endif // QTHEADERS_H
diff --git a/src/tools/tracegen/tracegen.cpp b/src/tools/tracegen/tracegen.cpp
new file mode 100644
index 0000000000..978fe406d0
--- /dev/null
+++ b/src/tools/tracegen/tracegen.cpp
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "provider.h"
+#include "lttng.h"
+#include "etw.h"
+#include "panic.h"
+
+#include <qstring.h>
+#include <qfile.h>
+
+enum class Target
+{
+ LTTNG,
+ ETW
+};
+
+static inline void usage(int status)
+{
+ printf("Usage: tracegen <lttng|etw> <input file> <output file>\n");
+ exit(status);
+}
+
+static void parseArgs(int argc, char *argv[], Target *target, QString *inFile, QString *outFile)
+{
+ if (argc == 1)
+ usage(EXIT_SUCCESS);
+ if (argc != 4)
+ usage(EXIT_FAILURE);
+
+ const char *targetString = argv[1];
+
+ if (qstrcmp(targetString, "lttng") == 0) {
+ *target = Target::LTTNG;
+ } else if (qstrcmp(targetString, "etw") == 0) {
+ *target = Target::ETW;
+ } else {
+ fprintf(stderr, "Invalid target: %s\n", targetString);
+ usage(EXIT_FAILURE);
+ }
+
+ *inFile = QLatin1String(argv[2]);
+ *outFile = QLatin1String(argv[3]);
+}
+
+int main(int argc, char *argv[])
+{
+ Target target = Target::LTTNG;
+ QString inFile;
+ QString outFile;
+
+ parseArgs(argc, argv, &target, &inFile, &outFile);
+
+ Provider p = parseProvider(inFile);
+
+ QFile out(outFile);
+
+ if (!out.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+ panic("Cannot open '%s' for writing: %s",
+ qPrintable(outFile), qPrintable(out.errorString()));
+ }
+
+ switch (target) {
+ case Target::LTTNG:
+ writeLttng(out, p);
+ break;
+ case Target::ETW:
+ writeEtw(out, p);
+ break;
+ }
+
+ return 0;
+}
diff --git a/src/tools/tracegen/tracegen.pro b/src/tools/tracegen/tracegen.pro
new file mode 100644
index 0000000000..20f0bb2914
--- /dev/null
+++ b/src/tools/tracegen/tracegen.pro
@@ -0,0 +1,21 @@
+option(host_build)
+CONFIG += force_bootstrap
+
+SOURCES += \
+ etw.cpp \
+ helpers.cpp \
+ lttng.cpp \
+ panic.cpp \
+ provider.cpp \
+ qtheaders.cpp \
+ tracegen.cpp
+
+HEADERS += \
+ etw.h \
+ helpers.h \
+ lttng.h \
+ panic.h \
+ provider.h \
+ qtheaders.h
+
+load(qt_tool)
diff --git a/src/widgets/accessible/simplewidgets.cpp b/src/widgets/accessible/simplewidgets.cpp
index f0423ca825..efcf4cdc8b 100644
--- a/src/widgets/accessible/simplewidgets.cpp
+++ b/src/widgets/accessible/simplewidgets.cpp
@@ -704,6 +704,8 @@ QString QAccessibleLineEdit::text(QAccessible::Text t) const
}
if (str.isEmpty())
str = QAccessibleWidget::text(t);
+ if (str.isEmpty() && t == QAccessible::Description)
+ str = lineEdit()->placeholderText();
return str;
}
diff --git a/src/widgets/dialogs/qfileinfogatherer_p.h b/src/widgets/dialogs/qfileinfogatherer_p.h
index bb13d4eb01..cc82f42850 100644
--- a/src/widgets/dialogs/qfileinfogatherer_p.h
+++ b/src/widgets/dialogs/qfileinfogatherer_p.h
@@ -167,6 +167,13 @@ public:
explicit QFileInfoGatherer(QObject *parent = 0);
~QFileInfoGatherer();
+#if QT_CONFIG(filesystemwatcher) && defined(Q_OS_WIN)
+ QStringList watchedFiles() const { return watcher->files(); }
+ QStringList watchedDirectories() const { return watcher->directories(); }
+ void watchPaths(const QStringList &paths) { watcher->addPaths(paths); }
+ void unwatchPaths(const QStringList &paths) { watcher->removePaths(paths); }
+#endif // filesystemwatcher && Q_OS_WIN
+
// only callable from this->thread():
void clear();
void removePath(const QString &path);
diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp
index 14ac6ad31b..33b8b51216 100644
--- a/src/widgets/dialogs/qfilesystemmodel.cpp
+++ b/src/widgets/dialogs/qfilesystemmodel.cpp
@@ -207,14 +207,17 @@ bool QFileSystemModel::remove(const QModelIndex &aindex)
const QString path = d->filePath(aindex);
const QFileInfo fileInfo(path);
+#if QT_CONFIG(filesystemwatcher) && defined(Q_OS_WIN)
+ // QTBUG-65683: Remove file system watchers prior to deletion to prevent
+ // failure due to locked files on Windows.
+ const QStringList watchedPaths = d->unwatchPathsAt(aindex);
+#endif // filesystemwatcher && Q_OS_WIN
const bool success = (fileInfo.isFile() || fileInfo.isSymLink())
? QFile::remove(path) : QDir(path).removeRecursively();
-#ifndef QT_NO_FILESYSTEMWATCHER
- if (success) {
- QFileSystemModelPrivate * d = const_cast<QFileSystemModelPrivate*>(d_func());
- d->fileInfoGatherer.removePath(path);
- }
-#endif
+#if QT_CONFIG(filesystemwatcher) && defined(Q_OS_WIN)
+ if (!success)
+ d->watchPaths(watchedPaths);
+#endif // filesystemwatcher && Q_OS_WIN
return success;
}
@@ -851,6 +854,20 @@ QIcon QFileSystemModelPrivate::icon(const QModelIndex &index) const
return node(index)->icon();
}
+static void displayRenameFailedMessage(const QString &newName)
+{
+#if QT_CONFIG(messagebox)
+ const QString message =
+ QFileSystemModel::tr("<b>The name \"%1\" cannot be used.</b>"
+ "<p>Try using another name, with fewer characters or no punctuation marks.")
+ .arg(newName);
+ QMessageBox::information(nullptr, QFileSystemModel::tr("Invalid filename"),
+ message, QMessageBox::Ok);
+#else
+ Q_UNUSED(newName)
+#endif // QT_CONFIG(messagebox)
+}
+
/*!
\reimp
*/
@@ -871,15 +888,21 @@ bool QFileSystemModel::setData(const QModelIndex &idx, const QVariant &value, in
const QString parentPath = filePath(parent(idx));
- if (newName.isEmpty()
- || QDir::toNativeSeparators(newName).contains(QDir::separator())
- || !QDir(parentPath).rename(oldName, newName)) {
-#if QT_CONFIG(messagebox)
- QMessageBox::information(0, QFileSystemModel::tr("Invalid filename"),
- QFileSystemModel::tr("<b>The name \"%1\" can not be used.</b><p>Try using another name, with fewer characters or no punctuations marks.")
- .arg(newName),
- QMessageBox::Ok);
-#endif // QT_CONFIG(messagebox)
+ if (newName.isEmpty() || QDir::toNativeSeparators(newName).contains(QDir::separator())) {
+ displayRenameFailedMessage(newName);
+ return false;
+ }
+
+#if QT_CONFIG(filesystemwatcher) && defined(Q_OS_WIN)
+ // QTBUG-65683: Remove file system watchers prior to renaming to prevent
+ // failure due to locked files on Windows.
+ const QStringList watchedPaths = d->unwatchPathsAt(idx);
+#endif // filesystemwatcher && Q_OS_WIN
+ if (!QDir(parentPath).rename(oldName, newName)) {
+#if QT_CONFIG(filesystemwatcher) && defined(Q_OS_WIN)
+ d->watchPaths(watchedPaths);
+#endif
+ displayRenameFailedMessage(newName);
return false;
} else {
/*
@@ -1882,6 +1905,46 @@ void QFileSystemModelPrivate::_q_resolvedName(const QString &fileName, const QSt
resolvedSymLinks[fileName] = resolvedName;
}
+#if QT_CONFIG(filesystemwatcher) && defined(Q_OS_WIN)
+// Remove file system watchers at/below the index and return a list of previously
+// watched files. This should be called prior to operations like rename/remove
+// which might fail due to watchers on platforms like Windows. The watchers
+// should be restored on failure.
+QStringList QFileSystemModelPrivate::unwatchPathsAt(const QModelIndex &index)
+{
+ const QFileSystemModelPrivate::QFileSystemNode *indexNode = node(index);
+ if (indexNode == nullptr)
+ return QStringList();
+ const Qt::CaseSensitivity caseSensitivity = indexNode->caseSensitive()
+ ? Qt::CaseSensitive : Qt::CaseInsensitive;
+ const QString path = indexNode->fileInfo().absoluteFilePath();
+
+ QStringList result;
+ const auto filter = [path, caseSensitivity] (const QString &watchedPath)
+ {
+ const int pathSize = path.size();
+ if (pathSize == watchedPath.size()) {
+ return path.compare(watchedPath, caseSensitivity) == 0;
+ } else if (watchedPath.size() > pathSize) {
+ return watchedPath.at(pathSize) == QLatin1Char('/')
+ && watchedPath.startsWith(path, caseSensitivity);
+ }
+ return false;
+ };
+
+ const QStringList &watchedFiles = fileInfoGatherer.watchedFiles();
+ std::copy_if(watchedFiles.cbegin(), watchedFiles.cend(),
+ std::back_inserter(result), filter);
+
+ const QStringList &watchedDirectories = fileInfoGatherer.watchedDirectories();
+ std::copy_if(watchedDirectories.cbegin(), watchedDirectories.cend(),
+ std::back_inserter(result), filter);
+
+ fileInfoGatherer.unwatchPaths(result);
+ return result;
+}
+#endif // filesystemwatcher && Q_OS_WIN
+
/*!
\internal
*/
diff --git a/src/widgets/dialogs/qfilesystemmodel_p.h b/src/widgets/dialogs/qfilesystemmodel_p.h
index e8bae4f659..a2a02e2d41 100644
--- a/src/widgets/dialogs/qfilesystemmodel_p.h
+++ b/src/widgets/dialogs/qfilesystemmodel_p.h
@@ -297,9 +297,13 @@ public:
static int naturalCompare(const QString &s1, const QString &s2, Qt::CaseSensitivity cs);
QDir rootDir;
-#ifndef QT_NO_FILESYSTEMWATCHER
+#if QT_CONFIG(filesystemwatcher)
+# ifdef Q_OS_WIN
+ QStringList unwatchPathsAt(const QModelIndex &);
+ void watchPaths(const QStringList &paths) { fileInfoGatherer.watchPaths(paths); }
+# endif // Q_OS_WIN
QFileInfoGatherer fileInfoGatherer;
-#endif
+#endif // filesystemwatcher
QTimer delayedSortTimer;
bool forceSort;
int sortColumn;
diff --git a/src/widgets/doc/snippets/common-table-model/model.cpp b/src/widgets/doc/snippets/common-table-model/model.cpp
index 96df100f26..2f6e9f1144 100644
--- a/src/widgets/doc/snippets/common-table-model/model.cpp
+++ b/src/widgets/doc/snippets/common-table-model/model.cpp
@@ -68,7 +68,7 @@ TableModel::TableModel(int rows, int columns, QObject *parent)
QStringList newList;
for (int column = 0; column < qMax(1, columns); ++column) {
- newList.append("");
+ newList.append(QString());
}
for (int row = 0; row < qMax(1, rows); ++row) {
@@ -129,9 +129,9 @@ QVariant TableModel::headerData(int section, Qt::Orientation orientation,
return QVariant();
if (orientation == Qt::Horizontal)
- return QString("Column %1").arg(section);
+ return QStringLiteral("Column %1").arg(section);
else
- return QString("Row %1").arg(section);
+ return QStringLiteral("Row %1").arg(section);
}
/*!
@@ -164,7 +164,7 @@ bool TableModel::setData(const QModelIndex &index,
return false;
rowList[index.row()][index.column()] = value.toString();
- emit dataChanged(index, index);
+ emit dataChanged(index, index, {role});
return true;
}
@@ -180,7 +180,7 @@ bool TableModel::insertRows(int position, int rows, const QModelIndex &parent)
for (int row = 0; row < rows; ++row) {
QStringList items;
for (int column = 0; column < columns; ++column)
- items.append("");
+ items.append(QString());
rowList.insert(position, items);
}
@@ -202,7 +202,7 @@ bool TableModel::insertColumns(int position, int columns,
for (int row = 0; row < rows; ++row) {
for (int column = position; column < columns; ++column) {
- rowList[row].insert(position, "");
+ rowList[row].insert(position, QString());
}
}
diff --git a/src/widgets/doc/snippets/common-table-model/model.h b/src/widgets/doc/snippets/common-table-model/model.h
index 68e6c00702..5f152e0e78 100644
--- a/src/widgets/doc/snippets/common-table-model/model.h
+++ b/src/widgets/doc/snippets/common-table-model/model.h
@@ -60,22 +60,22 @@ class TableModel : public QAbstractTableModel
Q_OBJECT
public:
- TableModel(int rows = 1, int columns = 1, QObject *parent = 0);
+ TableModel(int rows = 1, int columns = 1, QObject *parent = nullptr);
- int rowCount(const QModelIndex &parent = QModelIndex()) const;
- int columnCount(const QModelIndex &parent = QModelIndex()) const;
- QVariant data(const QModelIndex &index, int role) const;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const override;
+ QVariant data(const QModelIndex &index, int role) const override;
QVariant headerData(int section, Qt::Orientation orientation,
- int role = Qt::DisplayRole) const;
+ int role = Qt::DisplayRole) const override;
- Qt::ItemFlags flags(const QModelIndex &index) const;
+ Qt::ItemFlags flags(const QModelIndex &index) const override;
bool setData(const QModelIndex &index, const QVariant &value,
- int role = Qt::EditRole);
+ int role = Qt::EditRole) override;
- bool insertRows(int position, int rows, const QModelIndex &parent = QModelIndex());
- bool insertColumns(int position, int columns, const QModelIndex &parent = QModelIndex());
- bool removeRows(int position, int rows, const QModelIndex &parent = QModelIndex());
- bool removeColumns(int position, int columns, const QModelIndex &parent = QModelIndex());
+ bool insertRows(int position, int rows, const QModelIndex &parent = QModelIndex()) override;
+ bool insertColumns(int position, int columns, const QModelIndex &parent = QModelIndex()) override;
+ bool removeRows(int position, int rows, const QModelIndex &parent = QModelIndex()) override;
+ bool removeColumns(int position, int columns, const QModelIndex &parent = QModelIndex()) override;
private:
QList<QStringList> rowList;
diff --git a/src/widgets/doc/snippets/stringlistmodel/model.cpp b/src/widgets/doc/snippets/stringlistmodel/model.cpp
index f07f6b254f..52e78847d2 100644
--- a/src/widgets/doc/snippets/stringlistmodel/model.cpp
+++ b/src/widgets/doc/snippets/stringlistmodel/model.cpp
@@ -135,9 +135,9 @@ QVariant StringListModel::headerData(int section, Qt::Orientation orientation,
return QVariant();
if (orientation == Qt::Horizontal)
- return QString("Column %1").arg(section);
+ return QStringLiteral("Column %1").arg(section);
else
- return QString("Row %1").arg(section);
+ return QStringLiteral("Row %1").arg(section);
}
//! [2]
@@ -174,7 +174,7 @@ bool StringListModel::setData(const QModelIndex &index,
if (index.isValid() && role == Qt::EditRole) {
stringList.replace(index.row(), value.toString());
- emit dataChanged(index, index);
+ emit dataChanged(index, index, {role});
return true;
}
//! [4] //! [5]
diff --git a/src/widgets/doc/snippets/stringlistmodel/model.h b/src/widgets/doc/snippets/stringlistmodel/model.h
index 50769ef67f..7012152b27 100644
--- a/src/widgets/doc/snippets/stringlistmodel/model.h
+++ b/src/widgets/doc/snippets/stringlistmodel/model.h
@@ -61,26 +61,26 @@ class StringListModel : public QAbstractListModel
Q_OBJECT
public:
- StringListModel(const QStringList &strings, QObject *parent = 0)
+ StringListModel(const QStringList &strings, QObject *parent = nullptr)
: QAbstractListModel(parent), stringList(strings) {}
- int rowCount(const QModelIndex &parent = QModelIndex()) const;
- QVariant data(const QModelIndex &index, int role) const;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ QVariant data(const QModelIndex &index, int role) const override;
QVariant headerData(int section, Qt::Orientation orientation,
//! [0] //! [1]
- int role = Qt::DisplayRole) const;
+ int role = Qt::DisplayRole) const override;
//! [1]
//! [2]
- Qt::ItemFlags flags(const QModelIndex &index) const;
+ Qt::ItemFlags flags(const QModelIndex &index) const override;
bool setData(const QModelIndex &index, const QVariant &value,
//! [2] //! [3]
- int role = Qt::EditRole);
+ int role = Qt::EditRole) override;
//! [3]
//! [4]
- bool insertRows(int position, int rows, const QModelIndex &index = QModelIndex());
- bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex());
+ bool insertRows(int position, int rows, const QModelIndex &index = QModelIndex()) override;
+ bool removeRows(int position, int rows, const QModelIndex &index = QModelIndex()) override;
//! [4]
//! [5]
diff --git a/src/widgets/graphicsview/qgraphicsscene.h b/src/widgets/graphicsview/qgraphicsscene.h
index 5ecd2baab8..8efbcd273e 100644
--- a/src/widgets/graphicsview/qgraphicsscene.h
+++ b/src/widgets/graphicsview/qgraphicsscene.h
@@ -288,11 +288,7 @@ protected:
QWidget *widget = nullptr);
protected Q_SLOTS:
- // ### Qt 6: make unconditional
-#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
- virtual
-#endif
- bool focusNextPrevChild(bool next);
+ QT6_VIRTUAL bool focusNextPrevChild(bool next);
Q_SIGNALS:
void changed(const QList<QRectF> &region);
diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp
index 50287df6e0..585cfddff5 100644
--- a/src/widgets/itemviews/qheaderview.cpp
+++ b/src/widgets/itemviews/qheaderview.cpp
@@ -2848,14 +2848,18 @@ void QHeaderView::paintSection(QPainter *painter, const QRect &rect, int logical
if (isSortIndicatorShown() && sortIndicatorSection() == logicalIndex && isHeaderArrowOnTheSide)
margin += style()->pixelMetric(QStyle::PM_HeaderMarkSize, 0, this);
- if (d->textElideMode != Qt::ElideNone)
- opt.text = opt.fontMetrics.elidedText(opt.text, d->textElideMode , rect.width() - margin);
-
- QVariant variant = d->model->headerData(logicalIndex, d->orientation,
- Qt::DecorationRole);
+ const QVariant variant = d->model->headerData(logicalIndex, d->orientation,
+ Qt::DecorationRole);
opt.icon = qvariant_cast<QIcon>(variant);
if (opt.icon.isNull())
opt.icon = qvariant_cast<QPixmap>(variant);
+ if (!opt.icon.isNull()) // see CT_HeaderSection
+ margin += style()->pixelMetric(QStyle::PM_SmallIconSize, 0, this) +
+ style()->pixelMetric(QStyle::PM_HeaderMargin, 0, this);
+
+ if (d->textElideMode != Qt::ElideNone)
+ opt.text = opt.fontMetrics.elidedText(opt.text, d->textElideMode , rect.width() - margin);
+
QVariant foregroundBrush = d->model->headerData(logicalIndex, d->orientation,
Qt::ForegroundRole);
if (foregroundBrush.canConvert<QBrush>())
diff --git a/src/widgets/itemviews/qlistwidget.cpp b/src/widgets/itemviews/qlistwidget.cpp
index ad8aac1415..1fedad80aa 100644
--- a/src/widgets/itemviews/qlistwidget.cpp
+++ b/src/widgets/itemviews/qlistwidget.cpp
@@ -412,10 +412,10 @@ QList<QListWidgetItem*>::iterator QListModel::sortedInsertionIterator(
return std::lower_bound(begin, end, item, QListModelGreaterThan());
}
-void QListModel::itemChanged(QListWidgetItem *item)
+void QListModel::itemChanged(QListWidgetItem *item, const QVector<int> &roles)
{
- QModelIndex idx = index(item);
- emit dataChanged(idx, idx);
+ const QModelIndex idx = index(item);
+ emit dataChanged(idx, idx, roles);
}
QStringList QListModel::mimeTypes() const
@@ -711,8 +711,12 @@ void QListWidgetItem::setData(int role, const QVariant &value)
}
if (!found)
d->values.append(QWidgetItemData(role, value));
- if (QListModel *model = (view ? qobject_cast<QListModel*>(view->model()) : 0))
- model->itemChanged(this);
+ if (QListModel *model = (view ? qobject_cast<QListModel*>(view->model()) : nullptr)) {
+ const QVector<int> roles((role == Qt::DisplayRole) ?
+ QVector<int>({Qt::DisplayRole, Qt::EditRole}) :
+ QVector<int>({role}));
+ model->itemChanged(this, roles);
+ }
}
/*!
@@ -954,7 +958,8 @@ QDataStream &operator>>(QDataStream &in, QListWidgetItem &item)
\sa Qt::ItemFlags
*/
-void QListWidgetItem::setFlags(Qt::ItemFlags aflags) {
+void QListWidgetItem::setFlags(Qt::ItemFlags aflags)
+{
itemFlags = aflags;
if (QListModel *model = (view ? qobject_cast<QListModel*>(view->model()) : 0))
model->itemChanged(this);
diff --git a/src/widgets/itemviews/qlistwidget.h b/src/widgets/itemviews/qlistwidget.h
index 3caa5ce6f2..8a31411429 100644
--- a/src/widgets/itemviews/qlistwidget.h
+++ b/src/widgets/itemviews/qlistwidget.h
@@ -269,6 +269,7 @@ Q_SIGNALS:
void itemDoubleClicked(QListWidgetItem *item);
void itemActivated(QListWidgetItem *item);
void itemEntered(QListWidgetItem *item);
+ // ### Qt 6: add changed roles
void itemChanged(QListWidgetItem *item);
void currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous);
diff --git a/src/widgets/itemviews/qlistwidget_p.h b/src/widgets/itemviews/qlistwidget_p.h
index 492b05ff07..30b5016db6 100644
--- a/src/widgets/itemviews/qlistwidget_p.h
+++ b/src/widgets/itemviews/qlistwidget_p.h
@@ -119,7 +119,7 @@ public:
const QList<QListWidgetItem*>::iterator &end,
Qt::SortOrder order, QListWidgetItem *item);
- void itemChanged(QListWidgetItem *item);
+ void itemChanged(QListWidgetItem *item, const QVector<int> &roles = QVector<int>());
// dnd
QStringList mimeTypes() const override;
diff --git a/src/widgets/kernel/qaction.cpp b/src/widgets/kernel/qaction.cpp
index 853e27cd6e..967b0b8dde 100644
--- a/src/widgets/kernel/qaction.cpp
+++ b/src/widgets/kernel/qaction.cpp
@@ -66,7 +66,7 @@ QT_BEGIN_NAMESPACE
*/
static QString qt_strippedText(QString s)
{
- s.remove(QStringLiteral("..."));
+ s.remove(QLatin1String("..."));
for (int i = 0; i < s.size(); ++i) {
if (s.at(i) == QLatin1Char('&'))
s.remove(i, 1);
diff --git a/src/widgets/kernel/qlayout.h b/src/widgets/kernel/qlayout.h
index abadf2e69d..bcc33a0811 100644
--- a/src/widgets/kernel/qlayout.h
+++ b/src/widgets/kernel/qlayout.h
@@ -126,8 +126,8 @@ public:
bool isEmpty() const override;
QSizePolicy::ControlTypes controlTypes() const override;
- // ### Qt 6 make this function virtual
- QLayoutItem *replaceWidget(QWidget *from, QWidget *to, Qt::FindChildOptions options = Qt::FindChildrenRecursively);
+ QT6_VIRTUAL QLayoutItem *replaceWidget(QWidget *from, QWidget *to,
+ Qt::FindChildOptions options = Qt::FindChildrenRecursively);
int totalHeightForWidth(int w) const;
QSize totalMinimumSize() const;
diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp
index 12b60c634c..670a23e78f 100644
--- a/src/widgets/styles/qcommonstyle.cpp
+++ b/src/widgets/styles/qcommonstyle.cpp
@@ -743,8 +743,9 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
% QLatin1String(metaObject()->className()), opt, QSize(size, size))
% HexString<uint>(pe);
if (!QPixmapCache::find(pixmapName, pixmap)) {
- int border = size/5;
- int sqsize = 2*(size/2);
+ qreal pixelRatio = p->device()->devicePixelRatioF();
+ int border = qRound(pixelRatio*(size/5));
+ int sqsize = qRound(pixelRatio*(2*(size/2)));
QImage image(sqsize, sqsize, QImage::Format_ARGB32_Premultiplied);
image.fill(0);
QPainter imagePainter(&image);
@@ -796,6 +797,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
imagePainter.drawPolygon(a);
imagePainter.end();
pixmap = QPixmap::fromImage(image);
+ pixmap.setDevicePixelRatio(pixelRatio);
QPixmapCache::insert(pixmapName, pixmap);
}
int xOffset = r.x() + (r.width() - size)/2;
@@ -1581,10 +1583,11 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
aligned.width() * pixmap.devicePixelRatio(),
pixmap.height() * pixmap.devicePixelRatio());
+ const int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, opt, widget);
if (header->direction == Qt::LeftToRight)
- rect.setLeft(rect.left() + pixw + 2);
+ rect.setLeft(rect.left() + pixw + margin);
else
- rect.setRight(rect.right() - pixw - 2);
+ rect.setRight(rect.right() - pixw - margin);
}
if (header->state & QStyle::State_On) {
QFont fnt = p->font();
@@ -4165,14 +4168,10 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex
#if QT_CONFIG(combobox)
case CC_ComboBox:
if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
- int x = cb->rect.x(),
- y = cb->rect.y(),
- wi = cb->rect.width(),
- he = cb->rect.height();
- int xpos = x;
- int margin = cb->frame ? 3 : 0;
- int bmarg = cb->frame ? 2 : 0;
- xpos += wi - bmarg - 16;
+ const int x = cb->rect.x(), y = cb->rect.y(), wi = cb->rect.width(), he = cb->rect.height();
+ const int margin = cb->frame ? qRound(QStyleHelper::dpiScaled(3)) : 0;
+ const int bmarg = cb->frame ? qRound(QStyleHelper::dpiScaled(2)) : 0;
+ const int xpos = x + wi - bmarg - qRound(QStyleHelper::dpiScaled(16));
switch (sc) {
@@ -4180,10 +4179,10 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex
ret = cb->rect;
break;
case SC_ComboBoxArrow:
- ret.setRect(xpos, y + bmarg, 16, he - 2*bmarg);
+ ret.setRect(xpos, y + bmarg, qRound(QStyleHelper::dpiScaled(16)), he - 2*bmarg);
break;
case SC_ComboBoxEditField:
- ret.setRect(x + margin, y + margin, wi - 2 * margin - 16, he - 2 * margin);
+ ret.setRect(x + margin, y + margin, wi - 2 * margin - qRound(QStyleHelper::dpiScaled(16)), he - 2 * margin);
break;
case SC_ComboBoxListBoxPopup:
ret = cb->rect;
diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp
index a2b94d59d4..26f651906a 100644
--- a/src/widgets/styles/qfusionstyle.cpp
+++ b/src/widgets/styles/qfusionstyle.cpp
@@ -2737,6 +2737,8 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
pixmapName += QLatin1String("-editable");
if (isEnabled)
pixmapName += QLatin1String("-enabled");
+ if (!comboBox->frame)
+ pixmapName += QLatin1String("-frameless");
if (!QPixmapCache::find(pixmapName, cache)) {
cache = styleCachePixmap(comboBox->rect.size());
@@ -2762,7 +2764,8 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
buttonOption.state &= ~State_MouseOver;
}
- proxy()->drawPrimitive(PE_FrameLineEdit, &buttonOption, &cachePainter, widget);
+ if (comboBox->frame)
+ proxy()->drawPrimitive(PE_FrameLineEdit, &buttonOption, &cachePainter, widget);
// Draw button clipped
cachePainter.save();
diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp
index 7a84a4dcf8..89011350ec 100644
--- a/src/widgets/styles/qwindowsstyle.cpp
+++ b/src/widgets/styles/qwindowsstyle.cpp
@@ -798,9 +798,10 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt,
break;
case PE_FrameDefaultButton: {
QPen oldPen = p->pen();
- p->setPen(opt->palette.shadow().color());
- QRect rect = opt->rect;
- rect.adjust(0, 0, -1, -1);
+ p->setPen(QPen(opt->palette.shadow().color(), 0));
+ QRectF rect = opt->rect;
+ rect.adjust(QStyleHelper::dpiScaled(0.5), QStyleHelper::dpiScaled(0.5),
+ QStyleHelper::dpiScaled(-1.5), QStyleHelper::dpiScaled(-1.5));
p->drawRect(rect);
p->setPen(oldPen);
break;
@@ -843,22 +844,16 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt,
}
#endif // QT_CONFIG(itemviews)
if (!(opt->state & State_Off)) {
- QLineF lines[7];
- int i, xx, yy;
- xx = opt->rect.x() + 3;
- yy = opt->rect.y() + 5;
- for (i = 0; i < 3; ++i) {
- lines[i] = QLineF(xx, yy, xx, yy + 2);
- ++xx;
- ++yy;
- }
- yy -= 2;
- for (i = 3; i < 7; ++i) {
- lines[i] = QLineF(xx, yy, xx, yy + 2);
- ++xx;
- --yy;
- }
- p->drawLines(lines, 7);
+ QPointF points[6];
+ points[0] = { opt->rect.x() + QStyleHelper::dpiScaled(3.5), opt->rect.y() + QStyleHelper::dpiScaled(5.5) };
+ points[1] = { points[0].x(), points[0].y() + QStyleHelper::dpiScaled(2) };
+ points[2] = { points[1].x() + QStyleHelper::dpiScaled(2), points[1].y() + QStyleHelper::dpiScaled(2) };
+ points[3] = { points[2].x() + QStyleHelper::dpiScaled(4), points[2].y() - QStyleHelper::dpiScaled(4) };
+ points[4] = { points[3].x(), points[3].y() - QStyleHelper::dpiScaled(2) };
+ points[5] = { points[4].x() - QStyleHelper::dpiScaled(4), points[4].y() + QStyleHelper::dpiScaled(4) };
+ p->setPen(QPen(opt->palette.text().color(), 0));
+ p->setBrush(opt->palette.text().color());
+ p->drawPolygon(points, 6);
}
if (doRestore)
p->restore();
@@ -890,86 +885,57 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt,
break;
case PE_IndicatorRadioButton:
{
-#define PTSARRLEN(x) sizeof(x)/(sizeof(QPoint))
- static const QPoint pts1[] = { // dark lines
- QPoint(1, 9), QPoint(1, 8), QPoint(0, 7), QPoint(0, 4), QPoint(1, 3), QPoint(1, 2),
- QPoint(2, 1), QPoint(3, 1), QPoint(4, 0), QPoint(7, 0), QPoint(8, 1), QPoint(9, 1)
- };
- static const QPoint pts2[] = { // black lines
- QPoint(2, 8), QPoint(1, 7), QPoint(1, 4), QPoint(2, 3), QPoint(2, 2), QPoint(3, 2),
- QPoint(4, 1), QPoint(7, 1), QPoint(8, 2), QPoint(9, 2)
- };
- static const QPoint pts3[] = { // background lines
- QPoint(2, 9), QPoint(3, 9), QPoint(4, 10), QPoint(7, 10), QPoint(8, 9), QPoint(9, 9),
- QPoint(9, 8), QPoint(10, 7), QPoint(10, 4), QPoint(9, 3)
- };
- static const QPoint pts4[] = { // white lines
- QPoint(2, 10), QPoint(3, 10), QPoint(4, 11), QPoint(7, 11), QPoint(8, 10),
- QPoint(9, 10), QPoint(10, 9), QPoint(10, 8), QPoint(11, 7), QPoint(11, 4),
- QPoint(10, 3), QPoint(10, 2)
- };
- static const QPoint pts5[] = { // inner fill
- QPoint(4, 2), QPoint(7, 2), QPoint(9, 4), QPoint(9, 7), QPoint(7, 9), QPoint(4, 9),
- QPoint(2, 7), QPoint(2, 4)
- };
-
- // make sure the indicator is square
- QRect ir = opt->rect;
-
- if (opt->rect.width() < opt->rect.height()) {
- ir.setTop(opt->rect.top() + (opt->rect.height() - opt->rect.width()) / 2);
- ir.setHeight(opt->rect.width());
- } else if (opt->rect.height() < opt->rect.width()) {
- ir.setLeft(opt->rect.left() + (opt->rect.width() - opt->rect.height()) / 2);
- ir.setWidth(opt->rect.height());
- }
-
+ QRect r = opt->rect;
p->save();
- p->setRenderHint(QPainter::Qt4CompatiblePainting);
- bool down = opt->state & State_Sunken;
- bool enabled = opt->state & State_Enabled;
- bool on = opt->state & State_On;
- QPolygon a;
-
- //center when rect is larger than indicator size
- int xOffset = 0;
- int yOffset = 0;
- int indicatorWidth = proxy()->pixelMetric(PM_ExclusiveIndicatorWidth);
- int indicatorHeight = proxy()->pixelMetric(PM_ExclusiveIndicatorHeight);
- if (ir.width() > indicatorWidth)
- xOffset += (ir.width() - indicatorWidth)/2;
- if (ir.height() > indicatorHeight)
- yOffset += (ir.height() - indicatorHeight)/2;
- p->translate(xOffset, yOffset);
-
- p->translate(ir.x(), ir.y());
-
+ p->setRenderHint(QPainter::Antialiasing, true);
+
+ QPointF circleCenter = r.center() + QPoint(1, 1);
+ qreal radius = (r.width() + (r.width() + 1) % 2) / 2.0 - 1;
+
+ QPainterPath path1;
+ path1.addEllipse(circleCenter, radius, radius);
+ radius *= 0.85;
+ QPainterPath path2;
+ path2.addEllipse(circleCenter, radius, radius);
+ radius *= 0.85;
+ QPainterPath path3;
+ path3.addEllipse(circleCenter, radius, radius);
+ radius *= 0.5;
+ QPainterPath path4;
+ path4.addEllipse(circleCenter, radius, radius);
+
+ QPolygon topLeftPol, bottomRightPol;
+ topLeftPol.setPoints(3, r.x(), r.y(), r.x(), r.y() + r.height(), r.x() + r.width(), r.y());
+ bottomRightPol.setPoints(3, r.x(), r.y() + r.height(), r.x() + r.width(), r.y() + r.height(), r.x() + r.width(), r.y());
+
+ p->setClipRegion(QRegion(topLeftPol));
p->setPen(opt->palette.dark().color());
- p->drawPolyline(pts1, PTSARRLEN(pts1));
-
+ p->setBrush(opt->palette.dark().color());
+ p->drawPath(path1);
p->setPen(opt->palette.shadow().color());
- p->drawPolyline(pts2, PTSARRLEN(pts2));
+ p->setBrush(opt->palette.shadow().color());
+ p->drawPath(path2);
+ p->setClipRegion(QRegion(bottomRightPol));
+ p->setPen(opt->palette.light().color());
+ p->setBrush(opt->palette.light().color());
+ p->drawPath(path1);
p->setPen(opt->palette.midlight().color());
- p->drawPolyline(pts3, PTSARRLEN(pts3));
+ p->setBrush(opt->palette.midlight().color());
+ p->drawPath(path2);
- p->setPen(opt->palette.light().color());
- p->drawPolyline(pts4, PTSARRLEN(pts4));
+ QColor fillColor = ((opt->state & State_Sunken) || !(opt->state & State_Enabled)) ?
+ opt->palette.button().color() : opt->palette.base().color();
- QColor fillColor = (down || !enabled)
- ? opt->palette.button().color()
- : opt->palette.base().color();
+ p->setClipping(false);
p->setPen(fillColor);
- p->setBrush(fillColor) ;
- p->drawPolygon(pts5, PTSARRLEN(pts5));
+ p->setBrush(fillColor);
+ p->drawPath(path3);
- p->translate(-ir.x(), -ir.y()); // restore translate
-
- if (on) {
- p->setPen(Qt::NoPen);
+ if (opt->state & State_On) {
+ p->setPen(opt->palette.text().color());
p->setBrush(opt->palette.text());
- p->drawRect(ir.x() + 5, ir.y() + 4, 2, 4);
- p->drawRect(ir.x() + 4, ir.y() + 5, 4, 2);
+ p->drawPath(path4);
}
p->restore();
break;
diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp
index 156b0e331c..e3b348f0ef 100644
--- a/src/widgets/widgets/qlineedit.cpp
+++ b/src/widgets/widgets/qlineedit.cpp
@@ -1466,6 +1466,8 @@ bool QLineEdit::event(QEvent * e)
#endif
} else if (e->type() == QEvent::Resize) {
d->positionSideWidgets();
+ } else if (e->type() == QEvent::StyleChange) {
+ d->initMouseYThreshold();
}
#ifdef QT_KEYPAD_NAVIGATION
if (QApplication::keypadNavigationEnabled()) {
@@ -1546,7 +1548,17 @@ void QLineEdit::mouseMoveEvent(QMouseEvent * e)
const bool select = (d->imHints & Qt::ImhNoPredictiveText);
#endif
#ifndef QT_NO_IM
- if (d->control->composeMode() && select) {
+ if (d->mouseYThreshold > 0 && e->pos().y() > d->mousePressPos.y() + d->mouseYThreshold) {
+ if (layoutDirection() == Qt::RightToLeft)
+ d->control->home(select);
+ else
+ d->control->end(select);
+ } else if (d->mouseYThreshold > 0 && e->pos().y() + d->mouseYThreshold < d->mousePressPos.y()) {
+ if (layoutDirection() == Qt::RightToLeft)
+ d->control->end(select);
+ else
+ d->control->home(select);
+ } else if (d->control->composeMode() && select) {
int startPos = d->xToPos(d->mousePressPos.x());
int currentPos = d->xToPos(e->pos().x());
if (startPos != currentPos)
diff --git a/src/widgets/widgets/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp
index c66b842223..6a8af53c97 100644
--- a/src/widgets/widgets/qlineedit_p.cpp
+++ b/src/widgets/widgets/qlineedit_p.cpp
@@ -56,6 +56,7 @@
#endif
#include <qpainter.h>
#include <qpropertyanimation.h>
+#include <qstylehints.h>
#include <qvalidator.h>
QT_BEGIN_NAMESPACE
@@ -232,6 +233,13 @@ void QLineEditPrivate::init(const QString& txt)
q->setAcceptDrops(true);
q->setAttribute(Qt::WA_MacShowFocusRect);
+
+ initMouseYThreshold();
+}
+
+void QLineEditPrivate::initMouseYThreshold()
+{
+ mouseYThreshold = QGuiApplication::styleHints()->mouseQuickSelectionThreshold();
}
QRect QLineEditPrivate::adjustedContentsRect() const
diff --git a/src/widgets/widgets/qlineedit_p.h b/src/widgets/widgets/qlineedit_p.h
index a3f549ad31..39f670b0b0 100644
--- a/src/widgets/widgets/qlineedit_p.h
+++ b/src/widgets/widgets/qlineedit_p.h
@@ -141,7 +141,7 @@ public:
dragEnabled(0), clickCausedFocus(0), hscroll(0), vscroll(0),
alignment(Qt::AlignLeading | Qt::AlignVCenter),
leftTextMargin(0), topTextMargin(0), rightTextMargin(0), bottomTextMargin(0),
- lastTextSize(0)
+ lastTextSize(0), mouseYThreshold(0)
{
}
@@ -155,6 +155,7 @@ public:
QPointer<QAction> selectAllAction;
#endif
void init(const QString&);
+ void initMouseYThreshold();
QRect adjustedControlRect(const QRect &) const;
@@ -253,6 +254,7 @@ private:
SideWidgetEntryList leadingSideWidgets;
SideWidgetEntryList trailingSideWidgets;
int lastTextSize;
+ int mouseYThreshold;
};
Q_DECLARE_TYPEINFO(QLineEditPrivate::SideWidgetEntry, Q_PRIMITIVE_TYPE);
Q_DECLARE_TYPEINFO(QLineEditPrivate::SideWidgetLocation, Q_PRIMITIVE_TYPE);
diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp
index 0c11afdc61..b0a75288e8 100644
--- a/src/widgets/widgets/qmenubar.cpp
+++ b/src/widgets/widgets/qmenubar.cpp
@@ -1080,6 +1080,10 @@ void QMenuBar::mouseReleaseEvent(QMouseEvent *e)
d->mouseDown = false;
QAction *action = d->actionAt(e->pos());
+
+ // do noting if the action is hidden
+ if (!d->isVisible(action))
+ return;
if((d->closePopupMode && action == d->currentAction) || !action || !action->menu()) {
//we set the current action before activating
//so that we let the leave event set the current back to 0
diff --git a/src/xml/sax/qxml.h b/src/xml/sax/qxml.h
index 7c5b5fe204..94dc8dfb8e 100644
--- a/src/xml/sax/qxml.h
+++ b/src/xml/sax/qxml.h
@@ -122,10 +122,8 @@ public:
QXmlAttributes &operator=(const QXmlAttributes &) = default;
QXmlAttributes &operator=(QXmlAttributes &&) Q_DECL_NOTHROW = default;
#endif // default members
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- virtual // ### Qt 6: this value class don't need no virtual dtor
-#endif
- ~QXmlAttributes();
+
+ QT6_NOT_VIRTUAL ~QXmlAttributes();
void swap(QXmlAttributes &other) Q_DECL_NOTHROW
{