summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2019-12-11 01:00:10 +0100
committerEdward Welbourne <edward.welbourne@qt.io>2019-12-11 14:50:53 +0100
commita4a7c1bcf7595e2645c570d9c824532acf524fdf (patch)
treec57de9a148d02529836e74c50e308a7ac50d8550
parentbef74b6c3a0a9c8649ea8eb333d80015f76863e4 (diff)
parente6de661a8aa96b5905ea7ba4cd5d76bd06da3f93 (diff)
Merge remote-tracking branch 'origin/5.15' into dev
Conflicts: tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp Change-Id: I6b82507bf9a80a374c40393e72f4843f1557de89
-rw-r--r--examples/widgets/doc/src/shapedclock.qdoc52
-rw-r--r--examples/widgets/widgets/shapedclock/shapedclock.cpp7
-rw-r--r--mkspecs/features/wasm/wasm.prf2
-rw-r--r--mkspecs/wasm-emscripten/qmake.conf2
-rw-r--r--qmake/main.cpp2
-rw-r--r--src/corelib/global/qcompilerdetection.h77
-rw-r--r--src/corelib/global/qconfig-bootstrapped.h4
-rw-r--r--src/corelib/global/qendian.h4
-rw-r--r--src/corelib/global/qglobal.cpp4
-rw-r--r--src/corelib/global/qglobal.h2
-rw-r--r--src/corelib/global/qglobal_p.h4
-rw-r--r--src/corelib/global/qlogging.cpp8
-rw-r--r--src/corelib/global/qnumeric_p.h2
-rw-r--r--src/corelib/io/qfilesystemengine_unix.cpp2
-rw-r--r--src/corelib/io/qprocess.cpp2
-rw-r--r--src/corelib/io/qstandardpaths.cpp2
-rw-r--r--src/corelib/io/qstorageinfo_unix.cpp2
-rw-r--r--src/corelib/kernel/qdeadlinetimer.h4
-rw-r--r--src/corelib/kernel/qobject.h4
-rw-r--r--src/corelib/kernel/qtimer.h6
-rw-r--r--src/corelib/kernel/qvariant.h6
-rw-r--r--src/corelib/serialization/qcborarray.h2
-rw-r--r--src/corelib/serialization/qcbormap.h2
-rw-r--r--src/corelib/serialization/qcborvalue.h6
-rw-r--r--src/corelib/serialization/qcborvalue_p.h3
-rw-r--r--src/corelib/text/qbytearray.cpp2
-rw-r--r--src/corelib/text/qbytearray.h2
-rw-r--r--src/corelib/text/qstring.cpp7
-rw-r--r--src/corelib/text/qstring.h2
-rw-r--r--src/corelib/thread/qfutex_p.h4
-rw-r--r--src/corelib/thread/qmutex.h10
-rw-r--r--src/corelib/time/qdatetime.cpp100
-rw-r--r--src/corelib/time/qdatetimeparser.cpp2
-rw-r--r--src/corelib/time/qtimezoneprivate.cpp13
-rw-r--r--src/corelib/tools/qalgorithms.h4
-rw-r--r--src/corelib/tools/qscopeguard.h4
-rw-r--r--src/gui/kernel/qplatformcursor.cpp8
-rw-r--r--src/gui/kernel/qplatformcursor.h1
-rw-r--r--src/gui/painting/qcolorspace.cpp10
-rw-r--r--src/gui/rhi/qrhigles2.cpp77
-rw-r--r--src/gui/rhi/qrhigles2_p_p.h9
-rw-r--r--src/gui/rhi/qrhimetal.mm5
-rw-r--r--src/gui/text/qtextcursor.cpp1
-rw-r--r--src/gui/text/qtextdocument.cpp14
-rw-r--r--src/plugins/platforms/cocoa/qcocoaclipboard.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoacursor.h3
-rw-r--r--src/plugins/platforms/cocoa/qcocoacursor.mm25
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm22
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.h4
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.mm20
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm5
-rw-r--r--src/plugins/platforms/cocoa/qmacclipboard.mm8
-rw-r--r--src/plugins/platforms/qnx/qqnxscreeneventthread.cpp24
-rw-r--r--src/plugins/platforms/qnx/qqnxscreeneventthread.h2
-rw-r--r--src/plugins/platforms/wasm/qwasmscreen.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.cpp25
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.h2
-rw-r--r--src/plugins/platforms/windows/qwindowssystemtrayicon.cpp10
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp3
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp11
-rw-r--r--src/plugins/sqldrivers/psql/qsql_psql.cpp1
-rw-r--r--src/testlib/doc/snippets/code/doc_src_cmakelists.txt14
-rw-r--r--src/testlib/doc/src/qttestlib-manual.qdoc43
-rw-r--r--src/widgets/accessible/qaccessiblemenu.cpp2
-rw-r--r--src/widgets/dialogs/qprogressdialog.cpp17
-rw-r--r--src/widgets/itemviews/qabstractitemview.cpp11
-rw-r--r--src/widgets/itemviews/qlistview.cpp4
-rw-r--r--src/widgets/kernel/qtooltip.cpp43
-rw-r--r--src/widgets/kernel/qwidget.cpp17
-rw-r--r--src/widgets/styles/qcommonstyle.cpp22
-rw-r--r--src/widgets/styles/qfusionstyle.cpp57
-rw-r--r--src/widgets/styles/qstylesheetstyle.cpp10
-rw-r--r--src/widgets/widgets/qdatetimeedit.cpp200
-rw-r--r--src/widgets/widgets/qlineedit.cpp4
-rw-r--r--src/widgets/widgets/qmenu.cpp2
-rw-r--r--src/widgets/widgets/qmenubar.cpp3
-rw-r--r--src/widgets/widgets/qplaintextedit.cpp1
-rw-r--r--src/widgets/widgets/qwidgetlinecontrol.cpp2
-rw-r--r--src/widgets/widgets/qwidgettextcontrol.cpp6
-rw-r--r--tests/auto/corelib/global/qglobal/qglobal.c2
-rw-r--r--tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp4
-rw-r--r--tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp45
-rw-r--r--tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp6
-rw-r--r--tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp4
-rw-r--r--tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp30
-rw-r--r--tests/auto/corelib/thread/qmutex/tst_qmutex.cpp14
-rw-r--r--tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp65
-rw-r--r--tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp2
-rw-r--r--tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp27
-rw-r--r--tests/auto/network/kernel/qnetworkinterface/BLACKLIST3
-rw-r--r--tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp48
-rw-r--r--tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp76
-rw-r--r--tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp1
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp54
-rw-r--r--tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp3
-rw-r--r--tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp46
-rw-r--r--tests/benchmarks/corelib/thread/qreadwritelock/tst_qreadwritelock.cpp2
-rw-r--r--tests/manual/highdpi/main.cpp137
-rw-r--r--tests/testserver/docker-compose-bridge-network.yml37
-rw-r--r--tests/testserver/docker-compose-host-network.yml21
101 files changed, 1234 insertions, 507 deletions
diff --git a/examples/widgets/doc/src/shapedclock.qdoc b/examples/widgets/doc/src/shapedclock.qdoc
index 2e5d8b1496..732820cdc8 100644
--- a/examples/widgets/doc/src/shapedclock.qdoc
+++ b/examples/widgets/doc/src/shapedclock.qdoc
@@ -29,16 +29,18 @@
\example widgets/shapedclock
\title Shaped Clock Example
\ingroup examples-widgets
- \brief The Shaped Clock example shows how to apply a widget mask to a top-level
- widget to produce a shaped window.
+ \brief The Shaped Clock example shows how to apply a translucent background
+ and a widget mask to a top-level widget to produce a shaped window.
\borderedimage shapedclock-example.png
- Widget masks are used to customize the shapes of top-level widgets by restricting
- the available area for painting. On some window systems, setting certain window flags
- will cause the window decoration (title bar, window frame, buttons) to be disabled,
- allowing specially-shaped windows to be created. In this example, we use this feature
- to create a circular window containing an analog clock.
+ Widget masks are used to customize the shapes of top-level widgets by
+ restricting the area available for painting and mouse input. Using a
+ translucent background facilitates partially transparent windows and smooth
+ edges. On most window systems, setting certain window flags will cause the
+ window decoration (title bar, window frame, buttons) to be disabled,
+ allowing specially-shaped windows to be created. In this example, we use
+ this feature to create a circular window containing an analog clock.
Since this example's window does not provide a \uicontrol File menu or a close
button, we provide a context menu with an \uicontrol Exit entry so that the example
@@ -52,8 +54,10 @@
\snippet widgets/shapedclock/shapedclock.h 0
- The \l{QWidget::paintEvent()}{paintEvent()} implementation is the same as that found
- in the \c AnalogClock class. We implement \l{QWidget::sizeHint()}{sizeHint()}
+ The \l{QWidget::paintEvent()}{paintEvent()} implementation is the same as
+ that found in the \c AnalogClock class, with one important exception: we
+ now must also draw background (the clock face) ourselves, since the widget
+ background is just transparent. We implement \l{QWidget::sizeHint()}{sizeHint()}
so that we don't have to resize the widget explicitly. We also provide an event
handler for resize events. This allows us to update the mask if the clock is resized.
@@ -70,9 +74,11 @@
\snippet widgets/shapedclock/shapedclock.cpp 0
- We inform the window manager that the widget is not to be decorated with a window
- frame by setting the Qt::FramelessWindowHint flag on the widget. As a result, we need
- to provide a way for the user to move the clock around the screen.
+ We request a transparent window by setting the Qt::WA_TranslucentBackground
+ widget attribute. We inform the window manager that the widget is not to be
+ decorated with a window frame by setting the Qt::FramelessWindowHint flag
+ on the widget. As a result, we need to provide a way for the user to move
+ the clock around the screen.
Mouse button events are delivered to the \c mousePressEvent() handler:
@@ -94,14 +100,20 @@
widget is moved to the point given by subtracting the \c dragPosition from the current
cursor position in global coordinates. If we drag the widget, we also accept the event.
- The \c paintEvent() function is given for completeness. See the
- \l{Analog Clock Example}{Analog Clock} example for a description of the process used
- to render the clock.
+ The \c paintEvent() function is mainly the same as described in the
+ \l{Analog Clock Example}{Analog Clock} example. The one addition is that we
+ use QPainter::drawEllipse() to draw a round clock face with the current
+ palette's default background color. We make the clock face a bit smaller
+ than the widget mask, so that the anti-aliased, semi-transparent pixels on
+ the edge are not clipped away by the widget mask. This gives the shaped
+ window smooth edges on the screen.
\snippet widgets/shapedclock/shapedclock.cpp 3
- In the \c resizeEvent() handler, we re-use some of the code from the \c paintEvent()
- to determine the region of the widget that is visible to the user:
+ In the \c resizeEvent() handler, we re-use some of the code from the \c
+ paintEvent() to determine the region of the widget that is visible to the
+ user. This tells the system the area where mouse clicks should go to us,
+ and not to whatever window is behind us:
\snippet widgets/shapedclock/shapedclock.cpp 4
@@ -121,6 +133,12 @@
\section1 Notes on Widget Masks
+ Widget masks are used to hint to the window system that the application
+ does not want mouse events for areas outside the mask. On most systems,
+ they also result in coarse visual clipping. To get smooth window edges, one
+ should use translucent background and anti-aliased painting, as shown in
+ this example.
+
Since QRegion allows arbitrarily complex regions to be created, widget masks can be
made to suit the most unconventionally-shaped windows, and even allow widgets to be
displayed with holes in them.
diff --git a/examples/widgets/widgets/shapedclock/shapedclock.cpp b/examples/widgets/widgets/shapedclock/shapedclock.cpp
index 3c78f4da89..673d1a218f 100644
--- a/examples/widgets/widgets/shapedclock/shapedclock.cpp
+++ b/examples/widgets/widgets/shapedclock/shapedclock.cpp
@@ -61,6 +61,7 @@
ShapedClock::ShapedClock(QWidget *parent)
: QWidget(parent, Qt::FramelessWindowHint | Qt::WindowSystemMenuHint)
{
+ setAttribute(Qt::WA_TranslucentBackground);
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, QOverload<>::of(&ShapedClock::update));
timer->start(1000);
@@ -123,6 +124,10 @@ void ShapedClock::paintEvent(QPaintEvent *)
painter.scale(side / 200.0, side / 200.0);
painter.setPen(Qt::NoPen);
+ painter.setBrush(palette().window());
+ painter.drawEllipse(QPoint(0, 0), 98, 98);
+
+ painter.setPen(Qt::NoPen);
painter.setBrush(hourColor);
painter.save();
@@ -168,6 +173,6 @@ void ShapedClock::resizeEvent(QResizeEvent * /* event */)
//! [5]
QSize ShapedClock::sizeHint() const
{
- return QSize(100, 100);
+ return QSize(200, 200);
}
//! [5]
diff --git a/mkspecs/features/wasm/wasm.prf b/mkspecs/features/wasm/wasm.prf
index 25413d7470..5773e58010 100644
--- a/mkspecs/features/wasm/wasm.prf
+++ b/mkspecs/features/wasm/wasm.prf
@@ -71,7 +71,7 @@ contains(TEMPLATE, .*app) {
# replacing the app name placeholder with the actual app name.
apphtml.name = application main html file
apphtml.output = $$DESTDIR/$$TARGET_HTML
- apphtml.commands = sed -e s/@APPNAME@/$$TARGET_BASE/g $$WASM_PLUGIN_PATH/wasm_shell.html > $$DESTDIR/$$TARGET_HTML
+ apphtml.commands = $$QMAKE_STREAM_EDITOR -e s/@APPNAME@/$$TARGET_BASE/g $$WASM_PLUGIN_PATH/wasm_shell.html > $$DESTDIR/$$TARGET_HTML
apphtml.input = $$WASM_PLUGIN_PATH/wasm_shell.html
apphtml.depends = $$apphtml.input
QMAKE_EXTRA_COMPILERS += apphtml
diff --git a/mkspecs/wasm-emscripten/qmake.conf b/mkspecs/wasm-emscripten/qmake.conf
index c69ed9af79..919dcfb214 100644
--- a/mkspecs/wasm-emscripten/qmake.conf
+++ b/mkspecs/wasm-emscripten/qmake.conf
@@ -25,7 +25,7 @@ EMTERP_FLAGS = \
-s ASSERTIONS=1 \
--profiling-funcs
-EMCC_COMMON_LFLAGS = \
+EMCC_COMMON_LFLAGS += \
-s WASM=1 \
-s FULL_ES2=1 \
-s FULL_ES3=1 \
diff --git a/qmake/main.cpp b/qmake/main.cpp
index dd1cca9633..86f91031df 100644
--- a/qmake/main.cpp
+++ b/qmake/main.cpp
@@ -154,7 +154,7 @@ static int doSed(int argc, char **argv)
FILE *f;
if (!strcmp(inFile, "-")) {
f = stdin;
- } else if (!(f = fopen(inFile, "r"))) {
+ } else if (!(f = fopen(inFile, "rb"))) {
perror(inFile);
return 1;
}
diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h
index 7cfbe1273f..fedf08301f 100644
--- a/src/corelib/global/qcompilerdetection.h
+++ b/src/corelib/global/qcompilerdetection.h
@@ -493,6 +493,39 @@
#endif
/*
+ * SG10's SD-6 feature detection and some useful extensions from Clang and GCC
+ * https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations
+ * http://clang.llvm.org/docs/LanguageExtensions.html#feature-checking-macros
+ * Not using wrapper macros, per http://eel.is/c++draft/cpp.cond#7.sentence-2
+ */
+#ifndef __has_builtin
+# define __has_builtin(x) 0
+#endif
+#ifndef __has_feature
+# define __has_feature(x) 0
+#endif
+#ifndef __has_attribute
+# define __has_attribute(x) 0
+#endif
+#ifndef __has_cpp_attribute
+# define __has_cpp_attribute(x) 0
+#endif
+#ifndef __has_include
+# define __has_include(x) 0
+#endif
+#ifndef __has_include_next
+# define __has_include_next(x) 0
+#endif
+
+// Kept around until all submodules have transitioned
+#define QT_HAS_BUILTIN(x) __has_builtin(x)
+#define QT_HAS_FEATURE(x) __has_feature(x)
+#define QT_HAS_ATTRIBUTE(x) __has_attribute(x)
+#define QT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
+#define QT_HAS_INCLUDE(x) __has_include(x)
+#define QT_HAS_INCLUDE_NEXT(x) __has_include_next(x)
+
+/*
* C++11 support
*
* Paper Macro SD-6 macro
@@ -1019,37 +1052,6 @@
#endif
/*
- * SG10's SD-6 feature detection and some useful extensions from Clang and GCC
- * https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations
- * http://clang.llvm.org/docs/LanguageExtensions.html#feature-checking-macros
- */
-#ifdef __has_builtin
-# define QT_HAS_BUILTIN(x) __has_builtin(x)
-#else
-# define QT_HAS_BUILTIN(x) 0
-#endif
-#ifdef __has_attribute
-# define QT_HAS_ATTRIBUTE(x) __has_attribute(x)
-#else
-# define QT_HAS_ATTRIBUTE(x) 0
-#endif
-#ifdef __has_cpp_attribute
-# define QT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
-#else
-# define QT_HAS_CPP_ATTRIBUTE(x) 0
-#endif
-#ifdef __has_include
-# define QT_HAS_INCLUDE(x) __has_include(x)
-#else
-# define QT_HAS_INCLUDE(x) 0
-#endif
-#ifdef __has_include_next
-# define QT_HAS_INCLUDE_NEXT(x) __has_include_next(x)
-#else
-# define QT_HAS_INCLUDE_NEXT(x) 0
-#endif
-
-/*
* C++11 keywords and expressions
*/
#ifdef Q_COMPILER_NULLPTR
@@ -1123,7 +1125,7 @@
# define Q_DECL_ALIGN(n) alignas(n)
#endif
-#if QT_HAS_CPP_ATTRIBUTE(nodiscard) && !defined(Q_CC_CLANG) // P0188R1
+#if __has_cpp_attribute(nodiscard) && !defined(Q_CC_CLANG) // P0188R1
// Can't use [[nodiscard]] with Clang, see https://bugs.llvm.org/show_bug.cgi?id=33518
# undef Q_REQUIRED_RESULT
# define Q_REQUIRED_RESULT [[nodiscard]]
@@ -1225,11 +1227,6 @@
#ifndef QT_MAKE_CHECKED_ARRAY_ITERATOR
# define QT_MAKE_CHECKED_ARRAY_ITERATOR(x, N) (x)
#endif
-#ifdef __has_feature
-# define QT_HAS_FEATURE(x) __has_feature(x)
-#else
-# define QT_HAS_FEATURE(x) 0
-#endif
/*
* Warning/diagnostic handling
@@ -1320,11 +1317,11 @@
} while (false)
#if defined(__cplusplus)
-#if QT_HAS_CPP_ATTRIBUTE(clang::fallthrough)
+#if __has_cpp_attribute(clang::fallthrough)
# define Q_FALLTHROUGH() [[clang::fallthrough]]
-#elif QT_HAS_CPP_ATTRIBUTE(gnu::fallthrough)
+#elif __has_cpp_attribute(gnu::fallthrough)
# define Q_FALLTHROUGH() [[gnu::fallthrough]]
-#elif QT_HAS_CPP_ATTRIBUTE(fallthrough)
+#elif __has_cpp_attribute(fallthrough)
# define Q_FALLTHROUGH() [[fallthrough]]
#endif
#endif
diff --git a/src/corelib/global/qconfig-bootstrapped.h b/src/corelib/global/qconfig-bootstrapped.h
index c58dc56c42..2e6c3fbb20 100644
--- a/src/corelib/global/qconfig-bootstrapped.h
+++ b/src/corelib/global/qconfig-bootstrapped.h
@@ -77,13 +77,13 @@
#define QT_FEATURE_binaryjson -1
#define QT_FEATURE_cborstream -1
#define QT_CRYPTOGRAPHICHASH_ONLY_SHA1
-#define QT_FEATURE_cxx11_random (QT_HAS_INCLUDE(<random>) ? 1 : -1)
+#define QT_FEATURE_cxx11_random (__has_include(<random>) ? 1 : -1)
#define QT_NO_DATASTREAM
#define QT_FEATURE_datestring 1
#define QT_FEATURE_datetimeparser -1
#define QT_FEATURE_easingcurve -1
#define QT_FEATURE_etw -1
-#define QT_FEATURE_getauxval (QT_HAS_INCLUDE(<sys/auxv.h>) ? 1 : -1)
+#define QT_FEATURE_getauxval (__has_include(<sys/auxv.h>) ? 1 : -1)
#define QT_FEATURE_getentropy -1
#define QT_NO_GEOM_VARIANT
#define QT_FEATURE_hijricalendar -1
diff --git a/src/corelib/global/qendian.h b/src/corelib/global/qendian.h
index 5cd9d3160b..257efbbdbe 100644
--- a/src/corelib/global/qendian.h
+++ b/src/corelib/global/qendian.h
@@ -66,7 +66,7 @@ template <typename T> Q_ALWAYS_INLINE void qToUnaligned(const T src, void *dest)
// Using sizeof(T) inside memcpy function produces internal compiler error with
// MSVC2008/ARM in tst_endian -> use extra indirection to resolve size of T.
const size_t size = sizeof(T);
-#if QT_HAS_BUILTIN(__builtin_memcpy)
+#if __has_builtin(__builtin_memcpy)
__builtin_memcpy
#else
memcpy
@@ -78,7 +78,7 @@ template <typename T> Q_ALWAYS_INLINE T qFromUnaligned(const void *src)
{
T dest;
const size_t size = sizeof(T);
-#if QT_HAS_BUILTIN(__builtin_memcpy)
+#if __has_builtin(__builtin_memcpy)
__builtin_memcpy
#else
memcpy
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index 554c24356b..c2c91df756 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -92,7 +92,7 @@
# include <sys/systeminfo.h>
#endif
-#if defined(Q_OS_DARWIN) && QT_HAS_INCLUDE(<IOKit/IOKitLib.h>)
+#if defined(Q_OS_DARWIN) && __has_include(<IOKit/IOKitLib.h>)
# include <IOKit/IOKitLib.h>
# include <private/qcore_mac_p.h>
#endif
@@ -3067,7 +3067,7 @@ enum {
*/
QByteArray QSysInfo::machineUniqueId()
{
-#if defined(Q_OS_DARWIN) && QT_HAS_INCLUDE(<IOKit/IOKitLib.h>)
+#if defined(Q_OS_DARWIN) && __has_include(<IOKit/IOKitLib.h>)
char uuid[UuidStringLen + 1];
io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOPlatformExpertDevice"));
QCFString stringRef = (CFStringRef)IORegistryEntryCreateCFProperty(service, CFSTR(kIOPlatformUUIDKey), kCFAllocatorDefault, 0);
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 4dc63cae5e..80433ebeff 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -717,7 +717,7 @@ inline void qt_noop(void) {}
#if !defined(QT_NO_EXCEPTIONS)
# if !defined(Q_MOC_RUN)
-# if (defined(Q_CC_CLANG) && !defined(Q_CC_INTEL) && !QT_HAS_FEATURE(cxx_exceptions)) || \
+# if (defined(Q_CC_CLANG) && !defined(Q_CC_INTEL) && !__has_feature(cxx_exceptions)) || \
(defined(Q_CC_GNU) && !defined(__EXCEPTIONS))
# define QT_NO_EXCEPTIONS
# endif
diff --git a/src/corelib/global/qglobal_p.h b/src/corelib/global/qglobal_p.h
index 58bc8b7bf3..5ab84fa8be 100644
--- a/src/corelib/global/qglobal_p.h
+++ b/src/corelib/global/qglobal_p.h
@@ -74,7 +74,7 @@ Q_CORE_EXPORT time_t qMkTime(struct tm *when);
QT_END_NAMESPACE
-#if !QT_HAS_BUILTIN(__builtin_available)
+#if !__has_builtin(__builtin_available)
#include <initializer_list>
#include <QtCore/qoperatingsystemversion.h>
#include <QtCore/qversionnumber.h>
@@ -142,7 +142,7 @@ QT_END_NAMESPACE
QT_BUILTIN_AVAILABLE1, \
QT_BUILTIN_AVAILABLE0, )
#define __builtin_available(...) QT_BUILTIN_AVAILABLE_CHOOSER(__VA_ARGS__)(__VA_ARGS__)
-#endif // !QT_HAS_BUILTIN(__builtin_available)
+#endif // !__has_builtin(__builtin_available)
#endif // defined(__cplusplus)
#endif // QGLOBAL_P_H
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index e011645605..ca4d8dbd11 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -70,7 +70,7 @@
#if QT_CONFIG(slog2)
#include <sys/slog2.h>
#endif
-#if QT_HAS_INCLUDE(<paths.h>)
+#if __has_include(<paths.h>)
#include <paths.h>
#endif
@@ -106,7 +106,7 @@
# if __UCLIBC_HAS_BACKTRACE__
# define QLOGGING_HAVE_BACKTRACE
# endif
-# elif (defined(__GLIBC__) && defined(__GLIBCXX__)) || (QT_HAS_INCLUDE(<cxxabi.h>) && QT_HAS_INCLUDE(<execinfo.h>))
+# elif (defined(__GLIBC__) && defined(__GLIBCXX__)) || (__has_include(<cxxabi.h>) && __has_include(<execinfo.h>))
# define QLOGGING_HAVE_BACKTRACE
# endif
#endif
@@ -116,7 +116,7 @@ extern char *__progname;
#endif
#ifndef QT_BOOTSTRAPPED
-#if defined(Q_OS_LINUX) && (defined(__GLIBC__) || QT_HAS_INCLUDE(<sys/syscall.h>))
+#if defined(Q_OS_LINUX) && (defined(__GLIBC__) || __has_include(<sys/syscall.h>))
# include <sys/syscall.h>
# if defined(Q_OS_ANDROID) && !defined(SYS_gettid)
@@ -1276,7 +1276,7 @@ void QMessagePattern::setPattern(const QString &pattern)
#if defined(QLOGGING_HAVE_BACKTRACE) && !defined(QT_BOOTSTRAPPED)
// make sure the function has "Message" in the name so the function is removed
-#if ((defined(Q_CC_GNU) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS)) || QT_HAS_ATTRIBUTE(optimize)) \
+#if ((defined(Q_CC_GNU) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS)) || __has_attribute(optimize)) \
&& !defined(Q_CC_INTEL) && !defined(Q_CC_CLANG)
// force skipping the frame pointer, to save the backtrace() function some work
__attribute__((optimize("omit-frame-pointer")))
diff --git a/src/corelib/global/qnumeric_p.h b/src/corelib/global/qnumeric_p.h
index c006296b3d..376da66e31 100644
--- a/src/corelib/global/qnumeric_p.h
+++ b/src/corelib/global/qnumeric_p.h
@@ -253,7 +253,7 @@ QT_WARNING_POP
// 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) && !defined(Q_OS_WIN))) || QT_HAS_BUILTIN(__builtin_add_overflow)
+#if (defined(Q_CC_GNU) && (Q_CC_GNU >= 500) || (defined(Q_CC_INTEL) && !defined(Q_OS_WIN))) || __has_builtin(__builtin_add_overflow)
// GCC 5, ICC 18, and Clang 3.8 have builtins to detect overflows
template <typename T> inline
diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp
index 2e81f93bcf..3bbebc7fe9 100644
--- a/src/corelib/io/qfilesystemengine_unix.cpp
+++ b/src/corelib/io/qfilesystemengine_unix.cpp
@@ -55,7 +55,7 @@
#include <stdio.h>
#include <errno.h>
-#if QT_HAS_INCLUDE(<paths.h>)
+#if __has_include(<paths.h>)
# include <paths.h>
#endif
#ifndef _PATH_TMP // from <paths.h>
diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp
index ad2e7fb6b8..816026a36c 100644
--- a/src/corelib/io/qprocess.cpp
+++ b/src/corelib/io/qprocess.cpp
@@ -100,7 +100,7 @@ QT_END_NAMESPACE
#include <private/qcore_unix_p.h>
#endif
-#if QT_HAS_INCLUDE(<paths.h>)
+#if __has_include(<paths.h>)
#include <paths.h>
#endif
diff --git a/src/corelib/io/qstandardpaths.cpp b/src/corelib/io/qstandardpaths.cpp
index b62dc24b47..a5128a868b 100644
--- a/src/corelib/io/qstandardpaths.cpp
+++ b/src/corelib/io/qstandardpaths.cpp
@@ -48,7 +48,7 @@
#include <qcoreapplication.h>
#endif
-#if QT_HAS_INCLUDE(<paths.h>)
+#if __has_include(<paths.h>)
#include <paths.h>
#endif
diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp
index 1e72241e68..37b8a60c37 100644
--- a/src/corelib/io/qstorageinfo_unix.cpp
+++ b/src/corelib/io/qstorageinfo_unix.cpp
@@ -108,7 +108,7 @@
# endif // QT_LARGEFILE_SUPPORT
#endif // Q_OS_BSD4
-#if QT_HAS_INCLUDE(<paths.h>)
+#if __has_include(<paths.h>)
# include <paths.h>
#endif
#ifndef _PATH_MOUNTED
diff --git a/src/corelib/kernel/qdeadlinetimer.h b/src/corelib/kernel/qdeadlinetimer.h
index 9dd92481d2..99e09eb31f 100644
--- a/src/corelib/kernel/qdeadlinetimer.h
+++ b/src/corelib/kernel/qdeadlinetimer.h
@@ -52,7 +52,7 @@
#include <limits>
-#if QT_HAS_INCLUDE(<chrono>)
+#if __has_include(<chrono>)
# include <chrono>
#endif
@@ -120,7 +120,7 @@ public:
QDeadlineTimer &operator-=(qint64 msecs)
{ *this = *this + (-msecs); return *this; }
-#if QT_HAS_INCLUDE(<chrono>) || defined(Q_CLANG_QDOC)
+#if __has_include(<chrono>) || defined(Q_CLANG_QDOC)
template <class Clock, class Duration>
QDeadlineTimer(std::chrono::time_point<Clock, Duration> deadline_,
Qt::TimerType type_ = Qt::CoarseTimer) : t2(0)
diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h
index ca5275a3ac..8d9cc3ab83 100644
--- a/src/corelib/kernel/qobject.h
+++ b/src/corelib/kernel/qobject.h
@@ -55,7 +55,7 @@
#include <QtCore/qobject_impl.h>
-#if QT_HAS_INCLUDE(<chrono>)
+#if __has_include(<chrono>)
# include <chrono>
#endif
@@ -154,7 +154,7 @@ public:
void moveToThread(QThread *thread);
int startTimer(int interval, Qt::TimerType timerType = Qt::CoarseTimer);
-#if QT_HAS_INCLUDE(<chrono>)
+#if __has_include(<chrono>)
Q_ALWAYS_INLINE
int startTimer(std::chrono::milliseconds time, Qt::TimerType timerType = Qt::CoarseTimer)
{
diff --git a/src/corelib/kernel/qtimer.h b/src/corelib/kernel/qtimer.h
index eb7185c12d..6bbfd741d9 100644
--- a/src/corelib/kernel/qtimer.h
+++ b/src/corelib/kernel/qtimer.h
@@ -47,7 +47,7 @@
#include <QtCore/qbasictimer.h> // conceptual inheritance
#include <QtCore/qobject.h>
-#if QT_HAS_INCLUDE(<chrono>)
+#if __has_include(<chrono>)
# include <chrono>
#endif
@@ -177,7 +177,7 @@ Q_SIGNALS:
void timeout(QPrivateSignal);
public:
-#if QT_HAS_INCLUDE(<chrono>) || defined(Q_QDOC)
+#if __has_include(<chrono>) || defined(Q_QDOC)
void setInterval(std::chrono::milliseconds value)
{
setInterval(int(value.count()));
@@ -223,7 +223,7 @@ private:
static void singleShotImpl(int msec, Qt::TimerType timerType,
const QObject *receiver, QtPrivate::QSlotObjectBase *slotObj);
-#if QT_HAS_INCLUDE(<chrono>)
+#if __has_include(<chrono>)
static Qt::TimerType defaultTypeFor(std::chrono::milliseconds interval)
{ return defaultTypeFor(int(interval.count())); }
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index 0457b6fbad..24c7bd44dd 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -53,7 +53,7 @@
#include <QtCore/qbytearraylist.h>
#endif
-#if QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L
+#if __has_include(<variant>) && __cplusplus >= 201703L
#include <variant>
#elif defined(Q_CLANG_QDOC)
namespace std { template<typename...> struct variant; }
@@ -372,7 +372,7 @@ class Q_CORE_EXPORT QVariant
static inline QVariant fromValue(const T &value)
{ return QVariant(qMetaTypeId<T>(), &value, QTypeInfo<T>::isPointer); }
-#if (QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L) || defined(Q_CLANG_QDOC)
+#if (__has_include(<variant>) && __cplusplus >= 201703L) || defined(Q_CLANG_QDOC)
template<typename... Types>
static inline QVariant fromStdVariant(const std::variant<Types...> &value)
{
@@ -538,7 +538,7 @@ inline QVariant QVariant::fromValue(const QVariant &value)
return value;
}
-#if QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L
+#if __has_include(<variant>) && __cplusplus >= 201703L
template<>
inline QVariant QVariant::fromValue(const std::monostate &)
{
diff --git a/src/corelib/serialization/qcborarray.h b/src/corelib/serialization/qcborarray.h
index e06544f245..fe06b8630f 100644
--- a/src/corelib/serialization/qcborarray.h
+++ b/src/corelib/serialization/qcborarray.h
@@ -214,7 +214,7 @@ public:
bool contains(const QCborValue &value) const;
int compare(const QCborArray &other) const noexcept Q_DECL_PURE_FUNCTION;
-#if 0 && QT_HAS_INCLUDE(<compare>)
+#if 0 && __has_include(<compare>)
std::strong_ordering operator<=>(const QCborArray &other) const
{
int c = compare(other);
diff --git a/src/corelib/serialization/qcbormap.h b/src/corelib/serialization/qcbormap.h
index 4aea901eef..6636ce776a 100644
--- a/src/corelib/serialization/qcbormap.h
+++ b/src/corelib/serialization/qcbormap.h
@@ -245,7 +245,7 @@ public:
{ const_iterator it = find(key); return it != end(); }
int compare(const QCborMap &other) const noexcept Q_DECL_PURE_FUNCTION;
-#if 0 && QT_HAS_INCLUDE(<compare>)
+#if 0 && __has_include(<compare>)
std::strong_ordering operator<=>(const QCborMap &other) const
{
int c = compare(other);
diff --git a/src/corelib/serialization/qcborvalue.h b/src/corelib/serialization/qcborvalue.h
index 9c613dfcfb..071213e83a 100644
--- a/src/corelib/serialization/qcborvalue.h
+++ b/src/corelib/serialization/qcborvalue.h
@@ -59,7 +59,7 @@
# undef False
#endif
-#if 0 && QT_HAS_INCLUDE(<compare>)
+#if 0 && __has_include(<compare>)
# include <compare>
#endif
@@ -265,7 +265,7 @@ public:
QCborValueRef operator[](const QString & key);
int compare(const QCborValue &other) const;
-#if 0 && QT_HAS_INCLUDE(<compare>)
+#if 0 && __has_include(<compare>)
std::strong_ordering operator<=>(const QCborValue &other) const
{
int c = compare(other);
@@ -421,7 +421,7 @@ public:
int compare(const QCborValue &other) const
{ return concrete().compare(other); }
-#if 0 && QT_HAS_INCLUDE(<compare>)
+#if 0 && __has_include(<compare>)
std::strong_ordering operator<=>(const QCborValue &other) const
{
int c = compare(other);
diff --git a/src/corelib/serialization/qcborvalue_p.h b/src/corelib/serialization/qcborvalue_p.h
index b5d3de74fe..53ba81fa18 100644
--- a/src/corelib/serialization/qcborvalue_p.h
+++ b/src/corelib/serialization/qcborvalue_p.h
@@ -196,8 +196,7 @@ public:
if (value.container)
return replaceAt_complex(e, value, disp);
- e.value = value.value_helper();
- e.type = value.type();
+ e = { value.value_helper(), value.type() };
if (value.isContainer())
e.container = nullptr;
}
diff --git a/src/corelib/text/qbytearray.cpp b/src/corelib/text/qbytearray.cpp
index 83182dbd93..23296896b2 100644
--- a/src/corelib/text/qbytearray.cpp
+++ b/src/corelib/text/qbytearray.cpp
@@ -334,7 +334,7 @@ int qstricmp(const char *str1, const char *str2)
return int(Incomplete);
};
-#if defined(__SSE4_1__) && !(defined(__SANITIZE_ADDRESS__) || QT_HAS_FEATURE(address_sanitizer))
+#if defined(__SSE4_1__) && !(defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer))
enum { PageSize = 4096, PageMask = PageSize - 1 };
const __m128i zero = _mm_setzero_si128();
forever {
diff --git a/src/corelib/text/qbytearray.h b/src/corelib/text/qbytearray.h
index fa87ebf058..863898f7e2 100644
--- a/src/corelib/text/qbytearray.h
+++ b/src/corelib/text/qbytearray.h
@@ -243,7 +243,7 @@ public:
void chop(int n);
#if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(QT_COMPILING_QSTRING_COMPAT_CPP) && !defined(Q_CLANG_QDOC)
-# if defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && !defined(Q_CC_INTEL) && !QT_HAS_CPP_ATTRIBUTE(nodiscard)
+# if defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && !defined(Q_CC_INTEL) && !__has_cpp_attribute(nodiscard)
// required due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61941
# pragma push_macro("Q_REQUIRED_RESULT")
# undef Q_REQUIRED_RESULT
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp
index 0f313e21ed..e8ce637453 100644
--- a/src/corelib/text/qstring.cpp
+++ b/src/corelib/text/qstring.cpp
@@ -146,6 +146,9 @@ qsizetype qFindStringBoyerMoore(QStringView haystack, qsizetype from, QStringVie
static inline qsizetype qFindChar(QStringView str, QChar ch, qsizetype from, Qt::CaseSensitivity cs) noexcept;
template <typename Haystack>
static inline qsizetype qLastIndexOf(Haystack haystack, QChar needle, qsizetype from, Qt::CaseSensitivity cs) noexcept;
+template <>
+inline qsizetype qLastIndexOf(QString haystack, QChar needle,
+ qsizetype from, Qt::CaseSensitivity cs) noexcept = delete; // unwanted, would detach
static inline qsizetype qt_string_count(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs);
static inline qsizetype qt_string_count(QStringView haystack, QChar needle, Qt::CaseSensitivity cs);
@@ -3813,7 +3816,7 @@ int QString::indexOf(const QStringRef &str, int from, Qt::CaseSensitivity cs) co
int QString::lastIndexOf(const QString &str, int from, Qt::CaseSensitivity cs) const
{
// ### Qt6: qsizetype
- return int(QtPrivate::lastIndexOf(*this, from, str, cs));
+ return int(QtPrivate::lastIndexOf(QStringView(*this), from, str, cs));
}
#endif // QT_STRINGVIEW_LEVEL < 2
@@ -3852,7 +3855,7 @@ int QString::lastIndexOf(QLatin1String str, int from, Qt::CaseSensitivity cs) co
int QString::lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
{
// ### Qt6: qsizetype
- return int(qLastIndexOf(*this, ch, from, cs));
+ return int(qLastIndexOf(QStringView(*this), ch, from, cs));
}
#if QT_STRINGVIEW_LEVEL < 2
diff --git a/src/corelib/text/qstring.h b/src/corelib/text/qstring.h
index 27dc99b2e5..391e4788f2 100644
--- a/src/corelib/text/qstring.h
+++ b/src/corelib/text/qstring.h
@@ -485,7 +485,7 @@ public:
Q_REQUIRED_RESULT QString rightJustified(int width, QChar fill = QLatin1Char(' '), bool trunc = false) const;
#if defined(Q_COMPILER_REF_QUALIFIERS) && !defined(QT_COMPILING_QSTRING_COMPAT_CPP) && !defined(Q_CLANG_QDOC)
-# if defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && !defined(Q_CC_INTEL) && !QT_HAS_CPP_ATTRIBUTE(nodiscard)
+# if defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && !defined(Q_CC_INTEL) && !__has_cpp_attribute(nodiscard)
// required due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61941
# pragma push_macro("Q_REQUIRED_RESULT")
# undef Q_REQUIRED_RESULT
diff --git a/src/corelib/thread/qfutex_p.h b/src/corelib/thread/qfutex_p.h
index 7bec4554b7..f287b752d7 100644
--- a/src/corelib/thread/qfutex_p.h
+++ b/src/corelib/thread/qfutex_p.h
@@ -81,7 +81,7 @@ QT_END_NAMESPACE
// if not defined in linux/futex.h
# define FUTEX_PRIVATE_FLAG 128 // added in v2.6.22
-# if QT_HAS_FEATURE(thread_sanitizer) || defined(__SANITIZE_THREAD__)
+# if __has_feature(thread_sanitizer) || defined(__SANITIZE_THREAD__)
# include <sanitizer/tsan_interface.h>
inline void _q_tsan_acquire(void *addr, void *addr2)
{
@@ -98,7 +98,7 @@ inline void _q_tsan_release(void *addr, void *addr2)
# else
inline void _q_tsan_acquire(void *, void *) {}
inline void _q_tsan_release(void *, void *) {}
-# endif // QT_HAS_FEATURE(thread_sanitizer) || defined(__SANITIZE_THREAD__)
+# endif // __has_feature(thread_sanitizer) || defined(__SANITIZE_THREAD__)
QT_BEGIN_NAMESPACE
namespace QtLinuxFutex {
diff --git a/src/corelib/thread/qmutex.h b/src/corelib/thread/qmutex.h
index c693ff65d8..93c4bf23e8 100644
--- a/src/corelib/thread/qmutex.h
+++ b/src/corelib/thread/qmutex.h
@@ -44,7 +44,7 @@
#include <QtCore/qatomic.h>
#include <new>
-#if QT_HAS_INCLUDE(<chrono>)
+#if __has_include(<chrono>)
# include <chrono>
# include <limits>
#endif
@@ -147,7 +147,7 @@ public:
// Lockable concept
bool try_lock() QT_MUTEX_LOCK_NOEXCEPT { return tryLock(); }
-#if QT_HAS_INCLUDE(<chrono>) || defined(Q_CLANG_QDOC)
+#if __has_include(<chrono>) || defined(Q_CLANG_QDOC)
// TimedLockable concept
template <class Rep, class Period>
bool try_lock_for(std::chrono::duration<Rep, Period> duration)
@@ -175,7 +175,7 @@ private:
friend class QRecursiveMutex;
friend class ::tst_QMutex;
-#if QT_HAS_INCLUDE(<chrono>)
+#if __has_include(<chrono>)
template<class Rep, class Period>
static int convertToMilliseconds(std::chrono::duration<Rep, Period> duration)
{
@@ -213,7 +213,7 @@ public:
using QMutex::tryLock;
using QMutex::unlock;
using QMutex::try_lock;
-#if QT_HAS_INCLUDE(<chrono>)
+#if __has_include(<chrono>)
using QMutex::try_lock_for;
using QMutex::try_lock_until;
#endif
@@ -295,7 +295,7 @@ public:
inline void unlock() noexcept {}
inline bool isRecursive() const noexcept { return true; }
-#if QT_HAS_INCLUDE(<chrono>)
+#if __has_include(<chrono>)
template <class Rep, class Period>
inline bool try_lock_for(std::chrono::duration<Rep, Period> duration) noexcept
{
diff --git a/src/corelib/time/qdatetime.cpp b/src/corelib/time/qdatetime.cpp
index 979b8c9aeb..d2d09ceee6 100644
--- a/src/corelib/time/qdatetime.cpp
+++ b/src/corelib/time/qdatetime.cpp
@@ -127,7 +127,7 @@ static const char qt_shortMonthNames[][4] = {
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
-static int qt_monthNumberFromShortName(QStringRef shortName)
+static int qt_monthNumberFromShortName(QStringView shortName)
{
for (unsigned int i = 0; i < sizeof(qt_shortMonthNames) / sizeof(qt_shortMonthNames[0]); ++i) {
if (shortName == QLatin1String(qt_shortMonthNames[i], 3))
@@ -136,9 +136,9 @@ static int qt_monthNumberFromShortName(QStringRef shortName)
return -1;
}
static int qt_monthNumberFromShortName(const QString &shortName)
-{ return qt_monthNumberFromShortName(QStringRef(&shortName)); }
+{ return qt_monthNumberFromShortName(QStringView(shortName)); }
-static int fromShortMonthName(const QStringRef &monthName, int year)
+static int fromShortMonthName(QStringView monthName, int year)
{
// Assume that English monthnames are the default
int month = qt_monthNumberFromShortName(monthName);
@@ -207,7 +207,7 @@ static QString toOffsetString(Qt::DateFormat format, int offset)
#if QT_CONFIG(datestring)
// Parse offset in [+-]HH[[:]mm] format
-static int fromOffsetString(const QStringRef &offsetString, bool *valid) noexcept
+static int fromOffsetString(QStringView offsetString, bool *valid) noexcept
{
*valid = false;
@@ -228,22 +228,23 @@ static int fromOffsetString(const QStringRef &offsetString, bool *valid) noexcep
return 0;
// Split the hour and minute parts
- const QStringRef time = offsetString.mid(1);
- int hhLen = time.indexOf(QLatin1Char(':'));
- int mmIndex;
+ const QStringView time = offsetString.mid(1);
+ qsizetype hhLen = time.indexOf(QLatin1Char(':'));
+ qsizetype mmIndex;
if (hhLen == -1)
mmIndex = hhLen = 2; // [+-]HHmm or [+-]HH format
else
mmIndex = hhLen + 1;
- const QStringRef hhRef = time.left(hhLen);
+ const QLocale C = QLocale::c();
+ const QStringView hhRef = time.left(qMin(hhLen, time.size()));
bool ok = false;
- const int hour = hhRef.toInt(&ok);
+ const int hour = C.toInt(hhRef, &ok);
if (!ok)
return 0;
- const QStringRef mmRef = time.mid(mmIndex);
- const int minute = mmRef.isEmpty() ? 0 : mmRef.toInt(&ok);
+ const QStringView mmRef = time.mid(qMin(mmIndex, time.size()));
+ const int minute = mmRef.isEmpty() ? 0 : C.toInt(mmRef, &ok);
if (!ok || minute < 0 || minute > 59)
return 0;
@@ -2324,7 +2325,7 @@ int QTime::msecsTo(const QTime &t) const
#if QT_CONFIG(datestring)
-static QTime fromIsoTimeString(const QStringRef &string, Qt::DateFormat format, bool *isMidnight24)
+static QTime fromIsoTimeString(QStringView string, Qt::DateFormat format, bool *isMidnight24)
{
if (isMidnight24)
*isMidnight24 = false;
@@ -2333,11 +2334,12 @@ static QTime fromIsoTimeString(const QStringRef &string, Qt::DateFormat format,
if (size < 5)
return QTime();
+ const QLocale C(QLocale::c());
bool ok = false;
- int hour = string.mid(0, 2).toInt(&ok);
+ int hour = C.toInt(string.mid(0, 2), &ok);
if (!ok)
return QTime();
- const int minute = string.mid(3, 2).toInt(&ok);
+ const int minute = C.toInt(string.mid(3, 2), &ok);
if (!ok)
return QTime();
int second = 0;
@@ -2358,11 +2360,11 @@ static QTime fromIsoTimeString(const QStringRef &string, Qt::DateFormat format,
// seconds is 4. E.g. 12:34,99999 will expand to 12:34:59.9994. The milliseconds
// will then be rounded up AND clamped to 999.
- const QStringRef minuteFractionStr = string.mid(6, 5);
- const long minuteFractionInt = minuteFractionStr.toLong(&ok);
+ const QStringView minuteFractionStr = string.mid(6, qMin(qsizetype(5), string.size() - 6));
+ const long minuteFractionInt = C.toLong(minuteFractionStr, &ok);
if (!ok)
return QTime();
- const float minuteFraction = double(minuteFractionInt) / (std::pow(double(10), minuteFractionStr.count()));
+ const float minuteFraction = double(minuteFractionInt) / (std::pow(double(10), minuteFractionStr.size()));
const float secondWithMs = minuteFraction * 60;
const float secondNoMs = std::floor(secondWithMs);
@@ -2371,15 +2373,20 @@ static QTime fromIsoTimeString(const QStringRef &string, Qt::DateFormat format,
msec = qMin(qRound(secondFraction * 1000.0), 999);
} else {
// HH:mm:ss or HH:mm:ss.zzz
- second = string.mid(6, 2).toInt(&ok);
+ second = C.toInt(string.mid(6, qMin(qsizetype(2), string.size() - 6)), &ok);
if (!ok)
return QTime();
if (size > 8 && (string.at(8) == QLatin1Char(',') || string.at(8) == QLatin1Char('.'))) {
- const QStringRef msecStr(string.mid(9, 4));
- int msecInt = msecStr.isEmpty() ? 0 : msecStr.toInt(&ok);
+ QStringView msecStr(string.mid(9, qMin(qsizetype(4), string.size() - 9)));
+ // toInt() ignores leading spaces, so catch them before calling it
+ if (!msecStr.isEmpty() && !msecStr.at(0).isDigit())
+ return QTime();
+ // We do, however, want to ignore *trailing* spaces.
+ msecStr = msecStr.trimmed();
+ int msecInt = msecStr.isEmpty() ? 0 : C.toInt(msecStr, &ok);
if (!ok)
return QTime();
- const double secondFraction(msecInt / (std::pow(double(10), msecStr.count())));
+ const double secondFraction(msecInt / (std::pow(double(10), msecStr.size())));
msec = qMin(qRound(secondFraction * 1000.0), 999);
}
}
@@ -2428,7 +2435,7 @@ QTime QTime::fromString(const QString &string, Qt::DateFormat format)
case Qt::ISODateWithMs:
case Qt::TextDate:
default:
- return fromIsoTimeString(QStringRef(&string), format, nullptr);
+ return fromIsoTimeString(QStringView(string), format, nullptr);
}
}
@@ -3410,6 +3417,7 @@ inline qint64 QDateTimePrivate::zoneMSecsToEpochMSecs(qint64 zoneMSecs, const QT
DaylightStatus hint,
QDate *zoneDate, QTime *zoneTime)
{
+ Q_ASSERT(zone.isValid());
// Get the effective data from QTimeZone
QTimeZonePrivate::Data data = zone.d->dataForLocalTime(zoneMSecs, int(hint));
// Docs state any time before 1970-01-01 will *not* have any DST applied
@@ -3799,8 +3807,9 @@ QTimeZone QDateTime::timeZone() const
case Qt::OffsetFromUTC:
return QTimeZone(d->m_offsetFromUtc);
case Qt::TimeZone:
- Q_ASSERT(d->m_timeZone.isValid());
- return d->m_timeZone;
+ if (d->m_timeZone.isValid())
+ return d->m_timeZone;
+ break;
case Qt::LocalTime:
return QTimeZone::systemTimeZone();
}
@@ -3884,6 +3893,7 @@ QString QDateTime::timeZoneAbbreviation() const
#if !QT_CONFIG(timezone)
break;
#else
+ Q_ASSERT(d->m_timeZone.isValid());
return d->m_timeZone.d->abbreviation(toMSecsSinceEpoch());
#endif // timezone
case Qt::LocalTime: {
@@ -3920,6 +3930,7 @@ bool QDateTime::isDaylightTime() const
#if !QT_CONFIG(timezone)
break;
#else
+ Q_ASSERT(d->m_timeZone.isValid());
return d->m_timeZone.d->isDaylightTime(toMSecsSinceEpoch());
#endif // timezone
case Qt::LocalTime: {
@@ -4044,6 +4055,10 @@ void QDateTime::setTimeZone(const QTimeZone &toZone)
*/
qint64 QDateTime::toMSecsSinceEpoch() const
{
+ // Note: QDateTimeParser relies on this producing a useful result, even when
+ // !isValid(), at least when the invalidity is a time in a fall-back (that
+ // we'll have adjusted to lie outside it, but marked invalid because it's
+ // not what was asked for). Other things may be doing similar.
switch (getSpec(d)) {
case Qt::UTC:
return getMSecs(d);
@@ -4058,12 +4073,13 @@ qint64 QDateTime::toMSecsSinceEpoch() const
}
case Qt::TimeZone:
-#if !QT_CONFIG(timezone)
- return 0;
-#else
- return QDateTimePrivate::zoneMSecsToEpochMSecs(d->m_msecs, d->m_timeZone,
- extractDaylightStatus(getStatus(d)));
+#if QT_CONFIG(timezone)
+ if (d->m_timeZone.isValid()) {
+ return QDateTimePrivate::zoneMSecsToEpochMSecs(d->m_msecs, d->m_timeZone,
+ extractDaylightStatus(getStatus(d)));
+ }
#endif
+ return 0;
}
Q_UNREACHABLE();
return 0;
@@ -4158,9 +4174,11 @@ void QDateTime::setMSecsSinceEpoch(qint64 msecs)
case Qt::TimeZone:
Q_ASSERT(!d.isShort());
#if QT_CONFIG(timezone)
+ d.detach();
+ if (!d->m_timeZone.isValid())
+ break;
// Docs state any LocalTime before 1970-01-01 will *not* have any DST applied
// but all affected times afterwards will have DST applied.
- d.detach();
if (msecs >= 0) {
status = mergeDaylightStatus(status,
d->m_timeZone.d->isDaylightTime(msecs)
@@ -4433,7 +4451,7 @@ static inline void massageAdjustedDateTime(const QDateTimeData &d, QDate *date,
QDateTimePrivate::DaylightStatus status = QDateTimePrivate::UnknownDaylightTime;
localMSecsToEpochMSecs(timeToMSecs(*date, *time), &status, date, time);
#if QT_CONFIG(timezone)
- } else if (spec == Qt::TimeZone) {
+ } else if (spec == Qt::TimeZone && d->m_timeZone.isValid()) {
QDateTimePrivate::zoneMSecsToEpochMSecs(timeToMSecs(*date, *time),
d->m_timeZone,
QDateTimePrivate::UnknownDaylightTime,
@@ -5094,7 +5112,8 @@ QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs, const QTimeZone &timeZone
{
QDateTime dt;
dt.setTimeZone(timeZone);
- dt.setMSecsSinceEpoch(msecs);
+ if (timeZone.isValid())
+ dt.setMSecsSinceEpoch(msecs);
return dt;
}
@@ -5197,16 +5216,17 @@ QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format)
if (!date.isValid())
return QDateTime();
if (size == 10)
- return QDateTime(date);
+ return date.startOfDay();
Qt::TimeSpec spec = Qt::LocalTime;
- QStringRef isoString(&string);
- isoString = isoString.mid(10); // trim "yyyy-MM-dd"
+ QStringView isoString = QStringView(string).mid(10); // trim "yyyy-MM-dd"
- // Must be left with T and at least one digit for the hour:
+ // Must be left with T (or space) and at least one digit for the hour:
if (isoString.size() < 2
- || !(isoString.startsWith(QLatin1Char('T'))
- // FIXME: QSql relies on QVariant::toDateTime() accepting a space here:
+ || !(isoString.startsWith(QLatin1Char('T'), Qt::CaseInsensitive)
+ // RFC 3339 (section 5.6) allows a space here. (It actually
+ // allows any separator one considers more readable, merely
+ // giving space as an example - but let's not go wild !)
|| isoString.startsWith(QLatin1Char(' ')))) {
return QDateTime();
}
@@ -5214,7 +5234,7 @@ QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format)
int offset = 0;
// Check end of string for Time Zone definition, either Z for UTC or [+-]HH:mm for Offset
- if (isoString.endsWith(QLatin1Char('Z'))) {
+ if (isoString.endsWith(QLatin1Char('Z'), Qt::CaseInsensitive)) {
spec = Qt::UTC;
isoString.chop(1); // trim 'Z'
} else {
@@ -5345,7 +5365,7 @@ QDateTime QDateTime::fromString(const QString &string, Qt::DateFormat format)
if (parts.count() == 5)
return QDateTime(date, time, Qt::LocalTime);
- QStringRef tz = parts.at(5);
+ QStringView tz = parts.at(5);
if (!tz.startsWith(QLatin1String("GMT"), Qt::CaseInsensitive))
return QDateTime();
tz = tz.mid(3);
diff --git a/src/corelib/time/qdatetimeparser.cpp b/src/corelib/time/qdatetimeparser.cpp
index a487534528..fa0884c827 100644
--- a/src/corelib/time/qdatetimeparser.cpp
+++ b/src/corelib/time/qdatetimeparser.cpp
@@ -1363,7 +1363,7 @@ QDateTimeParser::scanString(const QDateTime &defaultValue,
// given date (which might be a spring-forward, skipping an hour).
if (parserType == QVariant::DateTime && !(isSet & HourSectionMask) && !when.isValid()) {
qint64 msecs = when.toMSecsSinceEpoch();
- // Fortunately, that gets a useful answer ...
+ // Fortunately, that gets a useful answer, even though when is invalid ...
const QDateTime replace =
#if QT_CONFIG(timezone)
tspec == Qt::TimeZone
diff --git a/src/corelib/time/qtimezoneprivate.cpp b/src/corelib/time/qtimezoneprivate.cpp
index 7d6ef0a404..facdf6661d 100644
--- a/src/corelib/time/qtimezoneprivate.cpp
+++ b/src/corelib/time/qtimezoneprivate.cpp
@@ -381,18 +381,15 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs,
On the first pass, the case we consider is what hint told us to expect
(except when hint was -1 and didn't actually tell us what to expect),
so it's likely right. We only get a second pass if the first failed,
- by which time the second case, that we're trying, is likely right. If
- an overwhelming majority of calls have hint == -1, the Q_LIKELY here
- shall be wrong half the time; otherwise, its errors shall be rarer
- than that.
+ by which time the second case, that we're trying, is likely right.
*/
if (nextFirst ? i == 0 : i) {
Q_ASSERT(nextStart != invalidMSecs());
- if (Q_LIKELY(nextStart <= nextTran.atMSecsSinceEpoch))
+ if (nextStart <= nextTran.atMSecsSinceEpoch)
return nextTran;
} else {
// If next is invalid, nextFirst is false, to route us here first:
- if (nextStart == invalidMSecs() || Q_LIKELY(nextStart > tran.atMSecsSinceEpoch))
+ if (nextStart == invalidMSecs() || nextStart > tran.atMSecsSinceEpoch)
return tran;
}
}
@@ -421,7 +418,7 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs,
int early = offsetFromUtc(recent);
int late = offsetFromUtc(imminent);
- if (Q_LIKELY(early == late)) { // > 99% of the time
+ if (early == late) { // > 99% of the time
utcEpochMSecs = forLocalMSecs - early * 1000;
} else {
// Close to a DST transition: early > late is near a fall-back,
@@ -433,7 +430,7 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs,
const qint64 forStd = forLocalMSecs - offsetInStd * 1000;
// Best guess at the answer:
const qint64 hinted = hint > 0 ? forDst : forStd;
- if (Q_LIKELY(offsetFromUtc(hinted) == (hint > 0 ? offsetInDst : offsetInStd))) {
+ if (offsetFromUtc(hinted) == (hint > 0 ? offsetInDst : offsetInStd)) {
utcEpochMSecs = hinted;
} else if (hint <= 0 && offsetFromUtc(forDst) == offsetInDst) {
utcEpochMSecs = forDst;
diff --git a/src/corelib/tools/qalgorithms.h b/src/corelib/tools/qalgorithms.h
index b01ce0db58..aa79e0d4a9 100644
--- a/src/corelib/tools/qalgorithms.h
+++ b/src/corelib/tools/qalgorithms.h
@@ -535,7 +535,7 @@ QT_DEPRECATED_X("Use std::binary_search") Q_OUTOFLINE_TEMPLATE RandomAccessItera
# define QT_HAS_BUILTIN_CTZS
Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_ctzs(quint16 v) noexcept
{
-# if QT_HAS_BUILTIN(__builtin_ctzs)
+# if __has_builtin(__builtin_ctzs)
return __builtin_ctzs(v);
# else
return __builtin_ctz(v);
@@ -544,7 +544,7 @@ Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_ctzs(quint16 v) noexcept
#define QT_HAS_BUILTIN_CLZS
Q_DECL_CONSTEXPR Q_ALWAYS_INLINE uint qt_builtin_clzs(quint16 v) noexcept
{
-# if QT_HAS_BUILTIN(__builtin_clzs)
+# if __has_builtin(__builtin_clzs)
return __builtin_clzs(v);
# else
return __builtin_clz(v) - 16U;
diff --git a/src/corelib/tools/qscopeguard.h b/src/corelib/tools/qscopeguard.h
index 45c3f93da4..40d2747b1d 100644
--- a/src/corelib/tools/qscopeguard.h
+++ b/src/corelib/tools/qscopeguard.h
@@ -51,7 +51,7 @@ template <typename F> QScopeGuard<F> qScopeGuard(F f);
template <typename F>
class
-#if QT_HAS_CPP_ATTRIBUTE(nodiscard)
+#if __has_cpp_attribute(nodiscard)
// Q_REQUIRED_RESULT can be defined as __warn_unused_result__ or as [[nodiscard]]
// but the 1st one has some limitations for example can be placed only on functions.
Q_REQUIRED_RESULT
@@ -91,7 +91,7 @@ private:
template <typename F>
-#if QT_HAS_CPP_ATTRIBUTE(nodiscard)
+#if __has_cpp_attribute(nodiscard)
Q_REQUIRED_RESULT
#endif
QScopeGuard<F> qScopeGuard(F f)
diff --git a/src/gui/kernel/qplatformcursor.cpp b/src/gui/kernel/qplatformcursor.cpp
index 12065078c1..5a438a54a2 100644
--- a/src/gui/kernel/qplatformcursor.cpp
+++ b/src/gui/kernel/qplatformcursor.cpp
@@ -131,6 +131,14 @@ void QPlatformCursor::setPos(const QPoint &pos)
QWindowSystemInterface::handleMouseEvent(nullptr, pos, pos, Qt::NoButton, Qt::NoButton, QEvent::MouseMove);
}
+/*!
+ Returns the size of the cursor, in native pixels.
+*/
+QSize QPlatformCursor::size() const
+{
+ return QSize(16, 16);
+}
+
// End of display and pointer event handling code
// Beginning of built-in cursor graphics
// from src/gui/embedded/QGraphicsSystemCursorImage_qws.cpp
diff --git a/src/gui/kernel/qplatformcursor.h b/src/gui/kernel/qplatformcursor.h
index f36a73c861..f3871d8780 100644
--- a/src/gui/kernel/qplatformcursor.h
+++ b/src/gui/kernel/qplatformcursor.h
@@ -96,6 +96,7 @@ public:
#endif // QT_NO_CURSOR
virtual QPoint pos() const;
virtual void setPos(const QPoint &pos);
+ virtual QSize size() const;
static Capabilities capabilities() { return m_capabilities; }
static void setCapabilities(Capabilities c) { m_capabilities = c; }
diff --git a/src/gui/painting/qcolorspace.cpp b/src/gui/painting/qcolorspace.cpp
index 937bb505c9..9631fdb416 100644
--- a/src/gui/painting/qcolorspace.cpp
+++ b/src/gui/painting/qcolorspace.cpp
@@ -784,10 +784,12 @@ QDebug operator<<(QDebug dbg, const QColorSpace &colorSpace)
QDebugStateSaver saver(dbg);
dbg.nospace();
dbg << "QColorSpace(";
- if (colorSpace.d_ptr->namedColorSpace)
- dbg << colorSpace.d_ptr->namedColorSpace << ", ";
- dbg << colorSpace.primaries() << ", " << colorSpace.transferFunction();
- dbg << ", gamma=" << colorSpace.gamma();
+ if (colorSpace.d_ptr) {
+ if (colorSpace.d_ptr->namedColorSpace)
+ dbg << colorSpace.d_ptr->namedColorSpace << ", ";
+ dbg << colorSpace.primaries() << ", " << colorSpace.transferFunction();
+ dbg << ", gamma=" << colorSpace.gamma();
+ }
dbg << ')';
return dbg;
}
diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp
index 563d59b318..3fb2ec38a7 100644
--- a/src/gui/rhi/qrhigles2.cpp
+++ b/src/gui/rhi/qrhigles2.cpp
@@ -2428,7 +2428,15 @@ void QRhiGles2::bindShaderResources(QRhiGraphicsPipeline *maybeGraphicsPs, QRhiC
f->glUniformMatrix2fv(uniform.glslLocation, 1, GL_FALSE, reinterpret_cast<const float *>(src));
break;
case QShaderDescription::Mat3:
- f->glUniformMatrix3fv(uniform.glslLocation, 1, GL_FALSE, reinterpret_cast<const float *>(src));
+ {
+ // 4 floats per column (or row, if row-major)
+ float mat[9];
+ const float *srcMat = reinterpret_cast<const float *>(src);
+ memcpy(mat, srcMat, 3 * sizeof(float));
+ memcpy(mat + 3, srcMat + 4, 3 * sizeof(float));
+ memcpy(mat + 6, srcMat + 8, 3 * sizeof(float));
+ f->glUniformMatrix3fv(uniform.glslLocation, 1, GL_FALSE, mat);
+ }
break;
case QShaderDescription::Mat4:
f->glUniformMatrix4fv(uniform.glslLocation, 1, GL_FALSE, reinterpret_cast<const float *>(src));
@@ -2919,21 +2927,64 @@ bool QRhiGles2::linkProgram(GLuint program)
return true;
}
-void QRhiGles2::gatherUniforms(GLuint program, const QShaderDescription::UniformBlock &ub,
+void QRhiGles2::registerUniformIfActive(const QShaderDescription::BlockVariable &var,
+ const QByteArray &namePrefix,
+ int binding,
+ int baseOffset,
+ GLuint program,
+ QVector<QGles2UniformDescription> *dst)
+{
+ if (var.type == QShaderDescription::Struct) {
+ qWarning("Nested structs are not supported at the moment. '%s' ignored.",
+ qPrintable(var.name));
+ return;
+ }
+ QGles2UniformDescription uniform;
+ uniform.type = var.type;
+ const QByteArray name = namePrefix + var.name.toUtf8();
+ uniform.glslLocation = f->glGetUniformLocation(program, name.constData());
+ if (uniform.glslLocation >= 0) {
+ uniform.binding = binding;
+ uniform.offset = uint(baseOffset + var.offset);
+ uniform.size = var.size;
+ dst->append(uniform);
+ }
+}
+
+void QRhiGles2::gatherUniforms(GLuint program,
+ const QShaderDescription::UniformBlock &ub,
QVector<QGles2UniformDescription> *dst)
{
- const QByteArray prefix = ub.structName.toUtf8() + '.';
+ QByteArray prefix = ub.structName.toUtf8() + '.';
for (const QShaderDescription::BlockVariable &blockMember : ub.members) {
- // ### no array support for now
- QGles2UniformDescription uniform;
- uniform.type = blockMember.type;
- const QByteArray name = prefix + blockMember.name.toUtf8();
- uniform.glslLocation = f->glGetUniformLocation(program, name.constData());
- if (uniform.glslLocation >= 0) {
- uniform.binding = ub.binding;
- uniform.offset = uint(blockMember.offset);
- uniform.size = blockMember.size;
- dst->append(uniform);
+ if (blockMember.type == QShaderDescription::Struct) {
+ prefix += blockMember.name.toUtf8();
+ const int baseOffset = blockMember.offset;
+ if (blockMember.arrayDims.isEmpty()) {
+ for (const QShaderDescription::BlockVariable &structMember : blockMember.structMembers)
+ registerUniformIfActive(structMember, prefix, ub.binding, baseOffset, program, dst);
+ } else {
+ if (blockMember.arrayDims.count() > 1) {
+ qWarning("Array of struct '%s' has more than one dimension. Only the first dimension is used.",
+ qPrintable(blockMember.name));
+ }
+ const int dim = blockMember.arrayDims.first();
+ const int elemSize = blockMember.size / dim;
+ int elemOffset = baseOffset;
+ for (int di = 0; di < dim; ++di) {
+ const QByteArray arrayPrefix = prefix + '[' + QByteArray::number(di) + ']' + '.';
+ for (const QShaderDescription::BlockVariable &structMember : blockMember.structMembers)
+ registerUniformIfActive(structMember, arrayPrefix, ub.binding, elemOffset, program, dst);
+ elemOffset += elemSize;
+ }
+ }
+ } else {
+ if (!blockMember.arrayDims.isEmpty()) {
+ qWarning("Arrays are only supported for structs at the moment. '%s' ignored.",
+ qPrintable(blockMember.name));
+ continue;
+ }
+ registerUniformIfActive(blockMember, prefix, ub.binding, 0, program, dst);
}
}
}
diff --git a/src/gui/rhi/qrhigles2_p_p.h b/src/gui/rhi/qrhigles2_p_p.h
index 0283fadb4e..4a98011d3d 100644
--- a/src/gui/rhi/qrhigles2_p_p.h
+++ b/src/gui/rhi/qrhigles2_p_p.h
@@ -706,7 +706,14 @@ public:
QByteArray shaderSource(const QRhiShaderStage &shaderStage, int *glslVersion);
bool compileShader(GLuint program, const QRhiShaderStage &shaderStage, int *glslVersion);
bool linkProgram(GLuint program);
- void gatherUniforms(GLuint program, const QShaderDescription::UniformBlock &ub,
+ void registerUniformIfActive(const QShaderDescription::BlockVariable &var,
+ const QByteArray &namePrefix,
+ int binding,
+ int baseOffset,
+ GLuint program,
+ QVector<QGles2UniformDescription> *dst);
+ void gatherUniforms(GLuint program,
+ const QShaderDescription::UniformBlock &ub,
QVector<QGles2UniformDescription> *dst);
void gatherSamplers(GLuint program, const QShaderDescription::InOutVariable &v,
QVector<QGles2SamplerDescription> *dst);
diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm
index 555ed5e79f..3aa68db585 100644
--- a/src/gui/rhi/qrhimetal.mm
+++ b/src/gui/rhi/qrhimetal.mm
@@ -3215,7 +3215,10 @@ id<MTLLibrary> QRhiMetalData::createMetalLib(const QShader &shader, QShader::Var
[opts release];
// src is autoreleased
- if (err) {
+ // if lib is null and err is non-null, we had errors (fail)
+ // if lib is non-null and err is non-null, we had warnings (success)
+ // if lib is non-null and err is null, there were no errors or warnings (success)
+ if (!lib) {
const QString msg = QString::fromNSString(err.localizedDescription);
*error = msg;
return nil;
diff --git a/src/gui/text/qtextcursor.cpp b/src/gui/text/qtextcursor.cpp
index b69b94d4e7..fa323ef4bd 100644
--- a/src/gui/text/qtextcursor.cpp
+++ b/src/gui/text/qtextcursor.cpp
@@ -2261,6 +2261,7 @@ void QTextCursor::insertFragment(const QTextDocumentFragment &fragment)
d->remove();
fragment.d->insert(*this);
d->priv->endEditBlock();
+ d->setX();
if (fragment.d && fragment.d->doc)
d->priv->mergeCachedResources(fragment.d->doc->docHandle());
diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp
index 3382ec0b69..1d27cc30eb 100644
--- a/src/gui/text/qtextdocument.cpp
+++ b/src/gui/text/qtextdocument.cpp
@@ -347,7 +347,19 @@ QTextDocument *QTextDocument::clone(QObject *parent) const
{
Q_D(const QTextDocument);
QTextDocument *doc = new QTextDocument(parent);
- QTextCursor(doc).insertFragment(QTextDocumentFragment(this));
+ if (isEmpty()) {
+ const QTextCursor thisCursor(const_cast<QTextDocument *>(this));
+
+ const auto blockFormat = thisCursor.blockFormat();
+ if (blockFormat.isValid() && !blockFormat.isEmpty())
+ QTextCursor(doc).setBlockFormat(blockFormat);
+
+ const auto blockCharFormat = thisCursor.blockCharFormat();
+ if (blockCharFormat.isValid() && !blockCharFormat.isEmpty())
+ QTextCursor(doc).setBlockCharFormat(blockCharFormat);
+ } else {
+ QTextCursor(doc).insertFragment(QTextDocumentFragment(this));
+ }
doc->rootFrame()->setFrameFormat(rootFrame()->frameFormat());
QTextDocumentPrivate *priv = doc->d_func();
priv->title = d->title;
diff --git a/src/plugins/platforms/cocoa/qcocoaclipboard.mm b/src/plugins/platforms/cocoa/qcocoaclipboard.mm
index a35c153084..141940cc50 100644
--- a/src/plugins/platforms/cocoa/qcocoaclipboard.mm
+++ b/src/plugins/platforms/cocoa/qcocoaclipboard.mm
@@ -67,7 +67,7 @@ void QCocoaClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode)
}
pasteBoard->sync();
- pasteBoard->setMimeData(data);
+ pasteBoard->setMimeData(data, QMacPasteboard::LazyRequest);
emitChanged(mode);
}
}
diff --git a/src/plugins/platforms/cocoa/qcocoacursor.h b/src/plugins/platforms/cocoa/qcocoacursor.h
index 58b9ef2151..5b008eff35 100644
--- a/src/plugins/platforms/cocoa/qcocoacursor.h
+++ b/src/plugins/platforms/cocoa/qcocoacursor.h
@@ -56,6 +56,9 @@ public:
void changeCursor(QCursor *cursor, QWindow *window) override;
QPoint pos() const override;
void setPos(const QPoint &position) override;
+
+ QSize size() const override;
+
private:
QHash<Qt::CursorShape, NSCursor *> m_cursors;
NSCursor *convertCursor(QCursor *cursor);
diff --git a/src/plugins/platforms/cocoa/qcocoacursor.mm b/src/plugins/platforms/cocoa/qcocoacursor.mm
index 87a57c78c8..e0d623fc4c 100644
--- a/src/plugins/platforms/cocoa/qcocoacursor.mm
+++ b/src/plugins/platforms/cocoa/qcocoacursor.mm
@@ -85,6 +85,31 @@ void QCocoaCursor::setPos(const QPoint &position)
CFRelease(e);
}
+
+QSize QCocoaCursor::size() const
+{
+ NSCursor *cocoaCursor = NSCursor.currentSystemCursor;
+ if (!cocoaCursor)
+ return QPlatformCursor::size();
+ NSImage *cursorImage = cocoaCursor.image;
+ if (!cursorImage)
+ return QPlatformCursor::size();
+
+ QSizeF size = QSizeF::fromCGSize(cursorImage.size);
+ NSUserDefaults *defaults = NSUserDefaults.standardUserDefaults;
+ NSDictionary *accessSettings = [defaults persistentDomainForName:@"com.apple.universalaccess"];
+ if (accessSettings == nil)
+ return size.toSize();
+
+ float sizeScale = [accessSettings[@"mouseDriverCursorSize"] floatValue];
+ if (sizeScale > 0) {
+ size.rwidth() *= sizeScale;
+ size.rheight() *= sizeScale;
+ }
+
+ return size.toSize();
+}
+
NSCursor *QCocoaCursor::convertCursor(QCursor *cursor)
{
if (!cursor)
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
index 69587a24be..b8d2532b8e 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
@@ -186,6 +186,7 @@ public:
QAtomicInt serialNumber;
int lastSerial;
bool interrupt;
+ bool propagateInterrupt = false;
static void postedEventsSourceCallback(void *info);
static void waitingObserverCallback(CFRunLoopObserverRef observer,
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
index 110c82bf1f..94b9e62eab 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
@@ -84,13 +84,12 @@
#include "private/qthread_p.h"
#include "private/qguiapplication_p.h"
#include <qdebug.h>
+#include <qscopeguard.h>
#include <AppKit/AppKit.h>
QT_BEGIN_NAMESPACE
-QT_USE_NAMESPACE
-
static inline CFRunLoopRef mainRunLoop()
{
return CFRunLoopGetMain();
@@ -348,6 +347,16 @@ static inline void qt_mac_waitForMoreEvents(NSString *runLoopMode = NSDefaultRun
bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
{
Q_D(QCocoaEventDispatcher);
+
+ // In rare rather corner cases a user's application messes with
+ // QEventLoop::exec()/exit() and QCoreApplication::processEvents(),
+ // we have to undo what bool blocker normally does.
+ d->propagateInterrupt = false;
+ const auto boolBlockerUndo = qScopeGuard([d](){
+ if (d->propagateInterrupt)
+ d->interrupt = true;
+ d->propagateInterrupt = false;
+ });
QBoolBlocker interruptBlocker(d->interrupt, false);
bool interruptLater = false;
@@ -496,7 +505,16 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
if ((d->processEventsFlags & QEventLoop::EventLoopExec) == 0) {
// When called "manually", always process posted events and timers
+ bool oldInterrupt = d->interrupt;
d->processPostedEvents();
+ if (!oldInterrupt && d->interrupt && !d->currentModalSession()) {
+ // We had direct processEvent call, coming not from QEventLoop::exec().
+ // One of the posted events triggered an application to interrupt the loop.
+ // But bool blocker will reset d->interrupt to false, so the real event
+ // loop will never notice it was interrupted. Now we'll have to fix it by
+ // enforcing the value of d->interrupt.
+ d->propagateInterrupt = true;
+ }
retVal = d->processTimers() || retVal;
}
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.h b/src/plugins/platforms/cocoa/qcocoaglcontext.h
index 4210a4ed3f..238067568b 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.h
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.h
@@ -86,6 +86,10 @@ private:
QSurfaceFormat m_format;
QVarLengthArray<QMacNotificationObserver, 3> m_updateObservers;
QAtomicInt m_needsUpdate = false;
+
+#ifndef QT_NO_DEBUG_STREAM
+ friend QDebug operator<<(QDebug debug, const QCocoaGLContext *screen);
+#endif
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
index b312e033cd..6db4bdb9fd 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
@@ -158,6 +158,8 @@ void QCocoaGLContext::initialize()
[m_context setValues:&order forParameter:NSOpenGLCPSurfaceOrder];
updateSurfaceFormat();
+
+ qCDebug(lcQpaOpenGLContext).verbosity(3) << "Created" << this << "based on requested" << context()->format();
}
NSOpenGLPixelFormat *QCocoaGLContext::pixelFormatForSurfaceFormat(const QSurfaceFormat &format)
@@ -355,7 +357,7 @@ QCocoaGLContext::~QCocoaGLContext()
bool QCocoaGLContext::makeCurrent(QPlatformSurface *surface)
{
- qCDebug(lcQpaOpenGLContext) << "Making" << m_context << "current"
+ qCDebug(lcQpaOpenGLContext) << "Making" << this << "current"
<< "in" << QThread::currentThread() << "for" << surface;
Q_ASSERT(surface->surface()->supportsOpenGL());
@@ -555,4 +557,20 @@ QFunctionPointer QCocoaGLContext::getProcAddress(const char *procName)
return (QFunctionPointer)dlsym(RTLD_DEFAULT, procName);
}
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug debug, const QCocoaGLContext *context)
+{
+ QDebugStateSaver saver(debug);
+ debug.nospace();
+ debug << "QCocoaGLContext(" << (const void *)context;
+ if (context) {
+ if (debug.verbosity() > QDebug::DefaultVerbosity)
+ debug << ", " << context->format();
+ debug << ", " << context->nativeContext();
+ }
+ debug << ')';
+ return debug;
+}
+#endif // !QT_NO_DEBUG_STREAM
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 643eac1e92..ad232d6d80 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -559,7 +559,10 @@ void QCocoaWindow::setWindowFlags(Qt::WindowFlags flags)
Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask));
if ((type & Qt::Popup) != Qt::Popup && (type & Qt::Dialog) != Qt::Dialog) {
NSWindowCollectionBehavior behavior = m_view.window.collectionBehavior;
- if ((flags & Qt::WindowFullscreenButtonHint) || m_view.window.qt_fullScreen) {
+ const bool enableFullScreen = m_view.window.qt_fullScreen
+ || !(flags & Qt::CustomizeWindowHint)
+ || (flags & Qt::WindowFullscreenButtonHint);
+ if (enableFullScreen) {
behavior |= NSWindowCollectionBehaviorFullScreenPrimary;
behavior &= ~NSWindowCollectionBehaviorFullScreenAuxiliary;
} else {
diff --git a/src/plugins/platforms/cocoa/qmacclipboard.mm b/src/plugins/platforms/cocoa/qmacclipboard.mm
index 358a6b49fd..654647b35a 100644
--- a/src/plugins/platforms/cocoa/qmacclipboard.mm
+++ b/src/plugins/platforms/cocoa/qmacclipboard.mm
@@ -138,8 +138,12 @@ QMacPasteboard::QMacPasteboard(CFStringRef name, uchar mt)
QMacPasteboard::~QMacPasteboard()
{
- // commit all promises for paste after exit close
- resolvingBeforeDestruction = true;
+ /*
+ Commit all promises for paste when shutting down,
+ unless we are the stack-allocated clipboard used by QCocoaDrag.
+ */
+ if (mime_type == QMacInternalPasteboardMime::MIME_DND)
+ resolvingBeforeDestruction = true;
PasteboardResolvePromises(paste);
if (paste)
CFRelease(paste);
diff --git a/src/plugins/platforms/qnx/qqnxscreeneventthread.cpp b/src/plugins/platforms/qnx/qqnxscreeneventthread.cpp
index 1b5f3b4954..491c314488 100644
--- a/src/plugins/platforms/qnx/qqnxscreeneventthread.cpp
+++ b/src/plugins/platforms/qnx/qqnxscreeneventthread.cpp
@@ -60,6 +60,18 @@ static const int c_screenCode = _PULSE_CODE_MINAVAIL + 0;
static const int c_armCode = _PULSE_CODE_MINAVAIL + 1;
static const int c_quitCode = _PULSE_CODE_MINAVAIL + 2;
+#if !defined(screen_register_event)
+int screen_register_event(screen_context_t, struct sigevent *event)
+{
+ return MsgRegisterEvent(event, -1);
+}
+
+int screen_unregister_event(struct sigevent *event)
+{
+ return MsgUnregisterEvent(event);
+}
+#endif
+
QQnxScreenEventThread::QQnxScreenEventThread(screen_context_t context)
: QThread()
, m_screenContext(context)
@@ -75,10 +87,14 @@ QQnxScreenEventThread::QQnxScreenEventThread(screen_context_t context)
qFatal("QQnxScreenEventThread: Can't continue without a channel connection");
}
- struct sigevent screenEvent;
- SIGEV_PULSE_INIT(&screenEvent, m_connectionId, SIGEV_PULSE_PRIO_INHERIT, c_screenCode, 0);
+ SIGEV_PULSE_INIT(&m_screenEvent, m_connectionId, SIGEV_PULSE_PRIO_INHERIT, c_screenCode, 0);
+ if (screen_register_event(m_screenContext, &m_screenEvent) == -1) {
+ ConnectDetach(m_connectionId);
+ ChannelDestroy(m_channelId);
+ qFatal("QQnxScreenEventThread: Can't continue without a registered event");
+ }
- screen_notify(m_screenContext, SCREEN_NOTIFY_EVENT, nullptr, &screenEvent);
+ screen_notify(m_screenContext, SCREEN_NOTIFY_EVENT, nullptr, &m_screenEvent);
}
QQnxScreenEventThread::~QQnxScreenEventThread()
@@ -86,6 +102,8 @@ QQnxScreenEventThread::~QQnxScreenEventThread()
// block until thread terminates
shutdown();
+ screen_notify(m_screenContext, SCREEN_NOTIFY_EVENT, nullptr, nullptr);
+ screen_unregister_event(&m_screenEvent);
ConnectDetach(m_connectionId);
ChannelDestroy(m_channelId);
}
diff --git a/src/plugins/platforms/qnx/qqnxscreeneventthread.h b/src/plugins/platforms/qnx/qqnxscreeneventthread.h
index 3c8d197545..e5b762369c 100644
--- a/src/plugins/platforms/qnx/qqnxscreeneventthread.h
+++ b/src/plugins/platforms/qnx/qqnxscreeneventthread.h
@@ -45,6 +45,7 @@
#include <QtCore/QMutex>
#include <screen/screen.h>
+#include <sys/siginfo.h>
QT_BEGIN_NAMESPACE
@@ -73,6 +74,7 @@ private:
int m_channelId;
int m_connectionId;
+ struct sigevent m_screenEvent;
screen_context_t m_screenContext;
bool m_emitNeededOnNextScreenPulse = true;
int m_screenPulsesSinceLastArmPulse = 0;
diff --git a/src/plugins/platforms/wasm/qwasmscreen.cpp b/src/plugins/platforms/wasm/qwasmscreen.cpp
index 37f1ea832a..b6c9b9e377 100644
--- a/src/plugins/platforms/wasm/qwasmscreen.cpp
+++ b/src/plugins/platforms/wasm/qwasmscreen.cpp
@@ -54,6 +54,8 @@ QWasmScreen::QWasmScreen(const QString &canvasId)
m_compositor = new QWasmCompositor(this);
m_eventTranslator = new QWasmEventTranslator(this);
updateQScreenAndCanvasRenderSize();
+ emscripten::val canvas = emscripten::val::global(m_canvasId.toUtf8().constData());
+ canvas.call<void>("focus");
}
QWasmScreen::~QWasmScreen()
diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp
index 17e8cffb76..59457f1720 100644
--- a/src/plugins/platforms/windows/qwindowscursor.cpp
+++ b/src/plugins/platforms/windows/qwindowscursor.cpp
@@ -50,6 +50,7 @@
#include <QtGui/qscreen.h>
#include <QtGui/private/qguiapplication_p.h> // getPixmapCursor()
#include <QtGui/private/qhighdpiscaling_p.h>
+#include <QtCore/private/qwinregistry_p.h>
#include <QtCore/qdebug.h>
#include <QtCore/qscopedpointer.h>
@@ -686,6 +687,30 @@ void QWindowsCursor::setPos(const QPoint &pos)
SetCursorPos(pos.x() , pos.y());
}
+/*
+ The standard size is 32x32, even though the cursor is actually just
+ 16 pixels large. If a large cursor is set in the accessibility settings,
+ then the cursor increases with 8 pixels for each step.
+*/
+QSize QWindowsCursor::size() const
+{
+ const QPair<DWORD,bool> cursorSizeSetting =
+ QWinRegistryKey(HKEY_CURRENT_USER, LR"(Control Panel\Cursors)")
+ .dwordValue(L"CursorBaseSize");
+ const int baseSize = screenCursorSize(m_screen).width() / 2;
+ if (!cursorSizeSetting.second)
+ return QSize(baseSize / 2, baseSize / 2);
+
+ // The registry values are dpi-independent, so we need to scale the result.
+ int cursorSizeValue = cursorSizeSetting.first * m_screen->logicalDpi().first
+ / m_screen->logicalBaseDpi().first;
+
+ // map from registry value 32-256 to 0-14, and from there to pixels
+ cursorSizeValue = (cursorSizeValue - 2 * baseSize) / baseSize;
+ const int cursorSize = baseSize + cursorSizeValue * (baseSize / 2);
+ return QSize(cursorSize, cursorSize);
+}
+
QPixmap QWindowsCursor::dragDefaultCursor(Qt::DropAction action) const
{
switch (action) {
diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h
index b896f4c7a9..cf3635bd6b 100644
--- a/src/plugins/platforms/windows/qwindowscursor.h
+++ b/src/plugins/platforms/windows/qwindowscursor.h
@@ -113,6 +113,8 @@ public:
QPoint pos() const override;
void setPos(const QPoint &pos) override;
+ QSize size() const override;
+
static HCURSOR createPixmapCursor(QPixmap pixmap, const QPoint &hotSpot, qreal scaleFactor = 1);
static HCURSOR createPixmapCursor(const PixmapCursor &pc, qreal scaleFactor = 1) { return createPixmapCursor(pc.pixmap, pc.hotSpot, scaleFactor); }
static PixmapCursor customCursor(Qt::CursorShape cursorShape, const QPlatformScreen *screen = nullptr);
diff --git a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp
index f2dba4d06b..ab830e1461 100644
--- a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp
+++ b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp
@@ -57,11 +57,13 @@
#include "qwindowsmenu.h"
#include "qwindowsscreen.h"
+#include <QtGui/qguiapplication.h>
#include <QtGui/qpixmap.h>
#include <QtCore/qdebug.h>
#include <QtCore/qrect.h>
#include <QtCore/qvector.h>
#include <QtCore/qsettings.h>
+#include <qpa/qwindowsysteminterface.h>
#include <qt_windows.h>
#include <commctrl.h>
@@ -134,9 +136,12 @@ static int indexOfHwnd(HWND hwnd)
extern "C" LRESULT QT_WIN_CALLBACK qWindowsTrayIconWndProc(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
+ // QTBUG-79248: Trigger screen update if there are no other windows.
+ if (message == WM_DPICHANGED && QGuiApplication::topLevelWindows().isEmpty())
+ QWindowsContext::instance()->screenManager().handleScreenChanges();
if (message == MYWM_TASKBARCREATED || message == MYWM_NOTIFYICON
|| message == WM_INITMENU || message == WM_INITMENUPOPUP
- || message == WM_COMMAND) {
+ || message == WM_CLOSE || message == WM_COMMAND) {
const int index = indexOfHwnd(hwnd);
if (index >= 0) {
MSG msg;
@@ -439,6 +444,9 @@ bool QWindowsSystemTrayIcon::winEvent(const MSG &message, long *result)
case WM_INITMENUPOPUP:
QWindowsPopupMenu::notifyAboutToShow(reinterpret_cast<HMENU>(message.wParam));
break;
+ case WM_CLOSE:
+ QWindowSystemInterface::handleApplicationTermination<QWindowSystemInterface::SynchronousDelivery>();
+ break;
case WM_COMMAND:
QWindowsPopupMenu::notifyTriggered(LOWORD(message.wParam));
break;
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
index e5a9f275ae..cc293b777c 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
@@ -289,7 +289,8 @@ HRESULT QWindowsUiaMainProvider::GetPatternProvider(PATTERNID idPattern, IUnknow
break;
case UIA_TogglePatternId:
// Checkbox controls.
- if (accessible->role() == QAccessible::CheckBox) {
+ if (accessible->role() == QAccessible::CheckBox
+ || (accessible->role() == QAccessible::MenuItem && accessible->state().checkable)) {
*pRetVal = new QWindowsUiaToggleProvider(id());
}
break;
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index 8bcaa78122..cc84e836b4 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -41,6 +41,7 @@
#include "qxcbwindow.h"
#include "qxcbcursor.h"
#include "qxcbimage.h"
+#include "qxcbintegration.h"
#include "qnamespace.h"
#include "qxcbxsettings.h"
@@ -49,6 +50,7 @@
#include <QDebug>
#include <QtAlgorithms>
+#include <qpa/qplatformservices.h>
#include <qpa/qwindowsysteminterface.h>
#include <private/qmath_p.h>
#include <QtGui/private/qhighdpiscaling_p.h>
@@ -356,6 +358,15 @@ static QFontEngine::SubpixelAntialiasingType parseXftRgba(const QByteArray& stri
void QXcbVirtualDesktop::readXResources()
{
+ const QPlatformServices *services = QXcbIntegration::instance()->services();
+ bool useXftConf = false;
+ if (services) {
+ const QList<QByteArray> desktopEnv = services->desktopEnvironment().split(':');
+ useXftConf = desktopEnv.contains("GNOME") || desktopEnv.contains("UNITY") || desktopEnv.contains("XFCE");
+ }
+ if (!useXftConf)
+ return;
+
int offset = 0;
QByteArray resources;
while (true) {
diff --git a/src/plugins/sqldrivers/psql/qsql_psql.cpp b/src/plugins/sqldrivers/psql/qsql_psql.cpp
index 68313b7ff0..3d8ed29b54 100644
--- a/src/plugins/sqldrivers/psql/qsql_psql.cpp
+++ b/src/plugins/sqldrivers/psql/qsql_psql.cpp
@@ -838,6 +838,7 @@ QSqlRecord QPSQLResult::record() const
}
int ptype = PQftype(d->result, i);
f.setType(qDecodePSQLType(ptype));
+ f.setValue(QVariant(f.type())); // only set in setType() when it's invalid before
int len = PQfsize(d->result, i);
int precision = PQfmod(d->result, i);
diff --git a/src/testlib/doc/snippets/code/doc_src_cmakelists.txt b/src/testlib/doc/snippets/code/doc_src_cmakelists.txt
new file mode 100644
index 0000000000..96dbe1acee
--- /dev/null
+++ b/src/testlib/doc/snippets/code/doc_src_cmakelists.txt
@@ -0,0 +1,14 @@
+project(mytest LANGUAGES CXX)
+
+find_package(Qt5Test REQUIRED)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(CMAKE_AUTOMOC ON)
+
+enable_testing(true)
+
+add_executable(mytest tst_mytest.cpp)
+add_test(NAME mytest COMMAND mytest)
+
+target_link_libraries(mytest PRIVATE Qt5::Test)
diff --git a/src/testlib/doc/src/qttestlib-manual.qdoc b/src/testlib/doc/src/qttestlib-manual.qdoc
index 19d871d404..688cc2f2f6 100644
--- a/src/testlib/doc/src/qttestlib-manual.qdoc
+++ b/src/testlib/doc/src/qttestlib-manual.qdoc
@@ -83,6 +83,10 @@
\li Custom types can easily be added to the test data and test output.
\endtable
+ You can use a Qt Creator wizard to create a project that contains Qt tests
+ and build and run them directly from Qt Creator. For more information, see
+ \l {Running Autotests}.
+
\section1 Creating a Test
To create a test, subclass QObject and add one or more private slots to it. Each
@@ -133,6 +137,41 @@
\if !defined(qtforpython)
\section1 Building a Test
+ You can build an executable that contains one test class that typically
+ tests one class of production code. However, usually you would want to
+ test several classes in a project by running one command.
+
+ See \l {Chapter 1: Writing a Unit Test}{Writing a Unit Test} for a step by
+ step explanation.
+
+ \section2 Building with CMake and CTest
+
+ You can use \l {CMake and CTest} to create a test.
+ \l{https://cmake.org/cmake/help/latest/manual/ctest.1.html}{CTest} enables
+ you to include or exclude tests based on a regular expression that is
+ matched against the test name. You can further apply the \c LABELS property
+ to a test and CTest can then include or exclude tests based on those labels.
+ All labeled targets will be run when \c {test} target is called on the
+ command line.
+
+ There are several other advantages with CMake. For example, the result of
+ a test run can be published on a web server using CDash with virtually no
+ effort.
+
+ CTest scales to very different unit test frameworks, and works out of the
+ box with QTest.
+
+ The following is an example of a CMakeLists.txt file that specifies the
+ project name and the language used (here, \e mytest and C++), the Qt
+ modules required for building the test (Qt5Test), and the files that are
+ included in the test (\e tst_mytest.cpp).
+
+ \quotefile code/doc_src_cmakelists.txt
+
+ For more information about the options you have, see \l {Build with CMake}.
+
+ \section2 Building with qmake
+
If you are using \c qmake as your build tool, just add the
following to your project file:
@@ -146,14 +185,14 @@
See the \l{Building a Testcase}{qmake manual} for
more information about \c{make check}.
+ \section2 Building with Other Tools
+
If you are using other build tools, make sure that you add the location
of the Qt Test header files to your include path (usually \c{include/QtTest}
under your Qt installation directory). If you are using a release build
of Qt, link your test to the \c QtTest library. For debug builds, use
\c{QtTest_debug}.
- See \l {Chapter 1: Writing a Unit Test}{Writing a Unit Test} for a step by
- step explanation.
\endif
\section1 Qt Test Command Line Arguments
diff --git a/src/widgets/accessible/qaccessiblemenu.cpp b/src/widgets/accessible/qaccessiblemenu.cpp
index 51ba0adaa6..99a9444ff1 100644
--- a/src/widgets/accessible/qaccessiblemenu.cpp
+++ b/src/widgets/accessible/qaccessiblemenu.cpp
@@ -299,6 +299,8 @@ QAccessible::State QAccessibleMenuItem::state() const
s.disabled = true;
if (m_action->isChecked())
s.checked = true;
+ if (m_action->isCheckable())
+ s.checkable = true;
return s;
}
diff --git a/src/widgets/dialogs/qprogressdialog.cpp b/src/widgets/dialogs/qprogressdialog.cpp
index 42a24239a3..aaa4430c39 100644
--- a/src/widgets/dialogs/qprogressdialog.cpp
+++ b/src/widgets/dialogs/qprogressdialog.cpp
@@ -710,14 +710,17 @@ void QProgressDialog::setValue(int progress)
QSize QProgressDialog::sizeHint() const
{
Q_D(const QProgressDialog);
- QSize sh = d->label ? d->label->sizeHint() : QSize(0, 0);
- QSize bh = d->bar->sizeHint();
- int margin = style()->pixelMetric(QStyle::PM_DefaultTopLevelMargin);
- int spacing = style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing);
- int h = margin * 2 + bh.height() + sh.height() + spacing;
+ QSize labelSize = d->label ? d->label->sizeHint() : QSize(0, 0);
+ QSize barSize = d->bar->sizeHint();
+ int marginBottom = style()->pixelMetric(QStyle::PM_LayoutBottomMargin, 0, this);
+ int spacing = style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing, 0, this);
+ int marginLeft = style()->pixelMetric(QStyle::PM_LayoutLeftMargin, 0, this);
+ int marginRight = style()->pixelMetric(QStyle::PM_LayoutRightMargin, 0, this);
+
+ int height = marginBottom * 2 + barSize.height() + labelSize.height() + spacing;
if (d->cancel)
- h += d->cancel->sizeHint().height() + spacing;
- return QSize(qMax(200, sh.width() + 2 * margin), h);
+ height += d->cancel->sizeHint().height() + spacing;
+ return QSize(qMax(200, labelSize.width() + marginLeft + marginRight), height);
}
/*!\reimp
diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp
index 67c01adea7..0e54cf235f 100644
--- a/src/widgets/itemviews/qabstractitemview.cpp
+++ b/src/widgets/itemviews/qabstractitemview.cpp
@@ -3074,9 +3074,10 @@ void QAbstractItemView::keyboardSearch(const QString &search)
QSize QAbstractItemView::sizeHintForIndex(const QModelIndex &index) const
{
Q_D(const QAbstractItemView);
- if (!d->isIndexValid(index) || !d->itemDelegate)
+ if (!d->isIndexValid(index))
return QSize();
- return d->delegateForIndex(index)->sizeHint(d->viewOptionsV1(), index);
+ const auto delegate = d->delegateForIndex(index);
+ return delegate ? delegate->sizeHint(d->viewOptionsV1(), index) : QSize();
}
/*!
@@ -3318,6 +3319,8 @@ void QAbstractItemView::update(const QModelIndex &index)
The \a roles which have been changed can either be an empty container (meaning everything
has changed), or a non-empty container with the subset of roles which have changed.
+
+ \note: Qt::ToolTipRole is not honored by dataChanged() in the views provided by Qt.
*/
void QAbstractItemView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles)
{
@@ -4451,7 +4454,9 @@ QItemViewPaintPairs QAbstractItemViewPrivate::draggablePaintPairs(const QModelIn
rect |= current;
}
}
- rect &= viewportRect;
+ QRect clipped = rect & viewportRect;
+ rect.setLeft(clipped.left());
+ rect.setRight(clipped.right());
return ret;
}
diff --git a/src/widgets/itemviews/qlistview.cpp b/src/widgets/itemviews/qlistview.cpp
index de32082b5a..ec01922746 100644
--- a/src/widgets/itemviews/qlistview.cpp
+++ b/src/widgets/itemviews/qlistview.cpp
@@ -664,7 +664,9 @@ QItemViewPaintPairs QListViewPrivate::draggablePaintPairs(const QModelIndexList
rect |= current;
}
}
- rect &= viewportRect;
+ QRect clipped = rect & viewportRect;
+ rect.setLeft(clipped.left());
+ rect.setRight(clipped.right());
return ret;
}
diff --git a/src/widgets/kernel/qtooltip.cpp b/src/widgets/kernel/qtooltip.cpp
index b290713440..33dd3e59b6 100644
--- a/src/widgets/kernel/qtooltip.cpp
+++ b/src/widgets/kernel/qtooltip.cpp
@@ -53,11 +53,14 @@
#endif
#include <qtextdocument.h>
#include <qdebug.h>
+#include <qpa/qplatformscreen.h>
+#include <qpa/qplatformcursor.h>
#include <private/qstylesheetstyle_p.h>
#ifndef QT_NO_TOOLTIP
#include <qlabel.h>
#include <QtWidgets/private/qlabel_p.h>
+#include <QtGui/private/qhighdpiscaling_p.h>
#include <qtooltip.h>
QT_BEGIN_NAMESPACE
@@ -398,24 +401,34 @@ void QTipLabel::placeTip(const QPoint &pos, QWidget *w)
}
#endif //QT_NO_STYLE_STYLESHEET
-
- QRect screen = QDesktopWidgetPrivate::screenGeometry(getTipScreen(pos, w));
-
QPoint p = pos;
- p += QPoint(2, 16);
-
- if (p.x() + this->width() > screen.x() + screen.width())
+ int screenNumber = getTipScreen(pos, w);
+ QScreen *screen = QGuiApplication::screens().at(screenNumber);
+ if (screen) {
+ const QPlatformScreen *platformScreen = screen->handle();
+ const QSize cursorSize = QHighDpi::fromNativePixels(platformScreen->cursor()->size(),
+ platformScreen);
+ QPoint offset(2, cursorSize.height());
+ // assuming an arrow shape, we can just move to the side for very large cursors
+ if (cursorSize.height() > 2 * this->height())
+ offset = QPoint(cursorSize.width() / 2, 0);
+
+ p += offset;
+
+ QRect screenRect = screen->geometry();
+ if (p.x() + this->width() > screenRect.x() + screenRect.width())
p.rx() -= 4 + this->width();
- if (p.y() + this->height() > screen.y() + screen.height())
+ if (p.y() + this->height() > screenRect.y() + screenRect.height())
p.ry() -= 24 + this->height();
- if (p.y() < screen.y())
- p.setY(screen.y());
- if (p.x() + this->width() > screen.x() + screen.width())
- p.setX(screen.x() + screen.width() - this->width());
- if (p.x() < screen.x())
- p.setX(screen.x());
- if (p.y() + this->height() > screen.y() + screen.height())
- p.setY(screen.y() + screen.height() - this->height());
+ if (p.y() < screenRect.y())
+ p.setY(screenRect.y());
+ if (p.x() + this->width() > screenRect.x() + screenRect.width())
+ p.setX(screenRect.x() + screenRect.width() - this->width());
+ if (p.x() < screenRect.x())
+ p.setX(screenRect.x());
+ if (p.y() + this->height() > screenRect.y() + screenRect.height())
+ p.setY(screenRect.y() + screenRect.height() - this->height());
+ }
this->move(p);
}
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index f507745e1e..ecea94c66a 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -8621,6 +8621,23 @@ bool QWidget::event(QEvent *event)
}
}
switch (event->type()) {
+ case QEvent::PlatformSurface: {
+ // Sync up QWidget's view of whether or not the widget has been created
+ switch (static_cast<QPlatformSurfaceEvent*>(event)->surfaceEventType()) {
+ case QPlatformSurfaceEvent::SurfaceCreated:
+ if (!testAttribute(Qt::WA_WState_Created))
+ create();
+ break;
+ case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed:
+ if (testAttribute(Qt::WA_WState_Created)) {
+ // Child windows have already been destroyed by QWindow,
+ // so we skip them here.
+ destroy(false, false);
+ }
+ break;
+ }
+ break;
+ }
case QEvent::MouseMove:
mouseMoveEvent((QMouseEvent*)event);
break;
diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp
index 6b3e3679ae..03081658bb 100644
--- a/src/widgets/styles/qcommonstyle.cpp
+++ b/src/widgets/styles/qcommonstyle.cpp
@@ -1363,7 +1363,6 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
if (!button->icon.isNull()) {
//Center both icon and text
- QRect iconRect;
QIcon::Mode mode = button->state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
if (mode == QIcon::Normal && button->state & State_HasFocus)
mode = QIcon::Active;
@@ -1372,28 +1371,29 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
state = QIcon::On;
QPixmap pixmap = button->icon.pixmap(qt_getWindow(widget), button->iconSize, mode, state);
-
int pixmapWidth = pixmap.width() / pixmap.devicePixelRatio();
int pixmapHeight = pixmap.height() / pixmap.devicePixelRatio();
int labelWidth = pixmapWidth;
int labelHeight = pixmapHeight;
int iconSpacing = 4;//### 4 is currently hardcoded in QPushButton::sizeHint()
- int textWidth = button->fontMetrics.boundingRect(opt->rect, tf, button->text).width();
- if (!button->text.isEmpty())
+ if (!button->text.isEmpty()) {
+ int textWidth = button->fontMetrics.boundingRect(opt->rect, tf, button->text).width();
labelWidth += (textWidth + iconSpacing);
+ }
- iconRect = QRect(textRect.x() + (textRect.width() - labelWidth) / 2,
- textRect.y() + (textRect.height() - labelHeight) / 2,
- pixmapWidth, pixmapHeight);
+ QRect iconRect = QRect(textRect.x() + (textRect.width() - labelWidth) / 2,
+ textRect.y() + (textRect.height() - labelHeight) / 2,
+ pixmapWidth, pixmapHeight);
iconRect = visualRect(button->direction, textRect, iconRect);
- tf |= Qt::AlignLeft; //left align, we adjust the text-rect instead
-
- if (button->direction == Qt::RightToLeft)
+ if (button->direction == Qt::RightToLeft) {
+ tf |= Qt::AlignRight;
textRect.setRight(iconRect.left() - iconSpacing);
- else
+ } else {
+ tf |= Qt::AlignLeft; //left align, we adjust the text-rect instead
textRect.setLeft(iconRect.left() + iconRect.width() + iconSpacing);
+ }
if (button->state & (State_On | State_Sunken))
iconRect.translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, opt, widget),
diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp
index a732d59e48..0c668913e9 100644
--- a/src/widgets/styles/qfusionstyle.cpp
+++ b/src/widgets/styles/qfusionstyle.cpp
@@ -1770,59 +1770,10 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
break;
case CE_PushButtonLabel:
if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(option)) {
- QRect ir = button->rect;
- uint tf = Qt::AlignVCenter;
- if (styleHint(SH_UnderlineShortcut, button, widget))
- tf |= Qt::TextShowMnemonic;
- else
- tf |= Qt::TextHideMnemonic;
-
- if (!button->icon.isNull()) {
- //Center both icon and text
- QPoint point;
-
- QIcon::Mode mode = button->state & State_Enabled ? QIcon::Normal
- : QIcon::Disabled;
- if (mode == QIcon::Normal && button->state & State_HasFocus)
- mode = QIcon::Active;
- QIcon::State state = QIcon::Off;
- if (button->state & State_On)
- state = QIcon::On;
-
- QPixmap pixmap = button->icon.pixmap(qt_getWindow(widget), button->iconSize, mode, state);
- int w = pixmap.width() / pixmap.devicePixelRatio();
- int h = pixmap.height() / pixmap.devicePixelRatio();
-
- if (!button->text.isEmpty())
- w += button->fontMetrics.boundingRect(option->rect, tf, button->text).width() + 2;
-
- point = QPoint(ir.x() + ir.width() / 2 - w / 2,
- ir.y() + ir.height() / 2 - h / 2);
-
- w = pixmap.width() / pixmap.devicePixelRatio();
-
- if (button->direction == Qt::RightToLeft)
- point.rx() += w;
-
- painter->drawPixmap(visualPos(button->direction, button->rect, point), pixmap);
-
- if (button->direction == Qt::RightToLeft)
- ir.translate(-point.x() - 2, 0);
- else
- ir.translate(point.x() + w, 0);
-
- // left-align text if there is
- if (!button->text.isEmpty())
- tf |= Qt::AlignLeft;
-
- } else {
- tf |= Qt::AlignHCenter;
- }
-
- if (button->features & QStyleOptionButton::HasMenu)
- ir = ir.adjusted(0, 0, -proxy()->pixelMetric(PM_MenuButtonIndicator, button, widget), 0);
- proxy()->drawItemText(painter, ir, tf, button->palette, (button->state & State_Enabled),
- button->text, QPalette::ButtonText);
+ QStyleOptionButton b(*button);
+ // no PM_ButtonShiftHorizontal and PM_ButtonShiftVertical for fusion style
+ b.state &= ~(State_On | State_Sunken);
+ QCommonStyle::drawControl(element, &b, painter, widget);
}
break;
case CE_MenuBarEmptyArea:
diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp
index c40bbbc96c..7e8c9a6050 100644
--- a/src/widgets/styles/qstylesheetstyle.cpp
+++ b/src/widgets/styles/qstylesheetstyle.cpp
@@ -3501,6 +3501,7 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
} else {
QWindowsStyle::drawControl(ce, &btnOpt, p, w);
}
+ rule.drawImage(p, rule.contentsRect(opt->rect));
if (!customMenu)
return;
} else {
@@ -3730,6 +3731,7 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
bool dis = !(opt->state & QStyle::State_Enabled),
act = opt->state & QStyle::State_Selected;
+ int textRectOffset = m->maxIconWidth;
if (!mi.icon.isNull()) {
QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal;
if (act && !dis)
@@ -3755,19 +3757,21 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
p->drawPixmap(pmr.topLeft(), pixmap);
} else if (checkable) {
QRenderRule subSubRule = renderRule(w, opt, PseudoElement_MenuCheckMark);
+ const QRect cmRect = positionRect(w, subRule, subSubRule, PseudoElement_MenuCheckMark, opt->rect, opt->direction);
if (subSubRule.hasDrawable() || checked) {
QStyleOptionMenuItem newMi = mi;
if (!dis)
newMi.state |= State_Enabled;
- if (act)
+ if (mi.checked)
newMi.state |= State_On;
- newMi.rect = positionRect(w, subRule, subSubRule, PseudoElement_MenuCheckMark, opt->rect, opt->direction);
+ newMi.rect = cmRect;
drawPrimitive(PE_IndicatorMenuCheckMark, &newMi, p, w);
}
+ textRectOffset = std::max(textRectOffset, cmRect.width());
}
QRect textRect = subRule.contentsRect(opt->rect);
- textRect.setLeft(textRect.left() + m->maxIconWidth);
+ textRect.setLeft(textRect.left() + textRectOffset);
textRect.setWidth(textRect.width() - mi.tabWidth);
const QRect vTextRect = visualRect(opt->direction, m->rect, textRect);
diff --git a/src/widgets/widgets/qdatetimeedit.cpp b/src/widgets/widgets/qdatetimeedit.cpp
index b0689d0b9e..3d6716666d 100644
--- a/src/widgets/widgets/qdatetimeedit.cpp
+++ b/src/widgets/widgets/qdatetimeedit.cpp
@@ -90,12 +90,10 @@ QT_BEGIN_NAMESPACE
today's date, and restricted the valid date range to today plus or
minus 365 days. We've set the order to month, day, year.
- The minimum value for QDateTimeEdit is 14 September 1752. You can
- change this by calling setMinimumDate(), taking into account that
- the minimum value for QDate is 2 January 4713BC.
-
- Other useful functions are setMaximumDate(), setMinimumTime()
- and setMaximumTime().
+ The range of valid values for a QDateTimeEdit is controlled by the properties
+ \l minimumDateTime, \l maximumDateTime, and their respective date and time
+ components. By default, any date-time from the start of 100 CE to the end of
+ 9999 CE is valid.
\section1 Using a Pop-up Calendar Widget
@@ -223,10 +221,16 @@ QDateTimeEdit::~QDateTimeEdit()
When setting this property the timespec of the QDateTimeEdit remains the same
and the timespec of the new QDateTime is ignored.
- By default, this property contains a date that refers to January 1,
- 2000 and a time of 00:00:00 and 0 milliseconds.
+ By default, this property is set to the start of 2000 CE. It can only be set
+ to a valid QDateTime value. If any operation causes this property to have an
+ invalid date-time as value, it is reset to the value of the \l minimumDateTime
+ property.
+
+ If the QDateTimeEdit has no date fields, setting this property sets the
+ widget's date-range to start and end on the date of the new value of this
+ property.
- \sa date, time
+ \sa date, time, minimumDateTime, maximumDateTime
*/
QDateTime QDateTimeEdit::dateTime() const
@@ -329,25 +333,23 @@ void QDateTimeEdit::setCalendar(QCalendar calendar)
}
/*!
- \property QDateTimeEdit::minimumDateTime
\since 4.4
+ \property QDateTimeEdit::minimumDateTime
\brief the minimum datetime of the date time edit
- When setting this property the \l maximumDateTime() is adjusted if
- necessary to ensure that the range remains valid. If the datetime is
- not a valid QDateTime object, this function does nothing.
-
- The default minimumDateTime can be restored with
- clearMinimumDateTime()
+ Changing this property implicitly updates the \l minimumDate and \l
+ minimumTime properties to the date and time parts of this property,
+ respectively. When setting this property, the \l maximumDateTime is adjusted,
+ if necessary, to ensure that the range remains valid. Otherwise, changing this
+ property preserves the \l minimumDateTime property.
- By default, this property contains a date that refers to September 14,
- 1752 and a time of 00:00:00 and 0 milliseconds.
+ This property can only be set to a valid QDateTime value. The earliest
+ date-time that setMinimumDateTime() accepts is the start of 100 CE. The
+ property's default is the start of September 14, 1752 CE. This default can be
+ restored with clearMinimumDateTime().
- \sa maximumDateTime(), minimumTime(), maximumTime(), minimumDate(),
- maximumDate(), setDateTimeRange(), setDateRange(), setTimeRange(),
- clearMaximumDateTime(), clearMinimumDate(),
- clearMaximumDate(), clearMinimumTime(), clearMaximumTime()
+ \sa maximumDateTime, minimumTime, minimumDate, setDateTimeRange(), QDateTime::isValid()
*/
QDateTime QDateTimeEdit::minimumDateTime() const
@@ -372,25 +374,23 @@ void QDateTimeEdit::setMinimumDateTime(const QDateTime &dt)
}
/*!
- \property QDateTimeEdit::maximumDateTime
\since 4.4
+ \property QDateTimeEdit::maximumDateTime
\brief the maximum datetime of the date time edit
- When setting this property the \l minimumDateTime() is adjusted if
- necessary to ensure that the range remains valid. If the datetime is
- not a valid QDateTime object, this function does nothing.
+ Changing this property implicitly updates the \l maximumDate and \l
+ maximumTime properties to the date and time parts of this property,
+ respectively. When setting this property, the \l minimumDateTime is adjusted,
+ if necessary, to ensure that the range remains valid. Otherwise, changing this
+ property preserves the \l minimumDateTime property.
- The default maximumDateTime can be restored with
+ This property can only be set to a valid QDateTime value. The latest
+ date-time that setMaximumDateTime() accepts is the end of 9999 CE. This is the
+ default for this property. This default can be restored with
clearMaximumDateTime().
- By default, this property contains a date that refers to 31 December,
- 9999 and a time of 23:59:59 and 999 milliseconds.
-
- \sa minimumDateTime(), minimumTime(), maximumTime(), minimumDate(),
- maximumDate(), setDateTimeRange(), setDateRange(), setTimeRange(),
- clearMinimumDateTime(), clearMinimumDate(),
- clearMaximumDate(), clearMinimumTime(), clearMaximumTime()
+ \sa minimumDateTime, maximumTime, maximumDate(), setDateTimeRange(), QDateTime::isValid()
*/
QDateTime QDateTimeEdit::maximumDateTime() const
@@ -414,11 +414,12 @@ void QDateTimeEdit::setMaximumDateTime(const QDateTime &dt)
}
}
-
/*!
- Convenience function to set minimum and maximum date time with one
- function call.
\since 4.4
+ \brief Set the range of allowed date-times for the date time edit.
+
+ This convenience function sets the \l minimumDateTime and \l maximumDateTime
+ properties.
\snippet code/src_gui_widgets_qdatetimeedit.cpp 1
@@ -426,21 +427,18 @@ void QDateTimeEdit::setMaximumDateTime(const QDateTime &dt)
\snippet code/src_gui_widgets_qdatetimeedit.cpp 2
- If either \a min or \a max are not valid, this function does
- nothing.
+ If either \a min or \a max is invalid, this function does nothing. If \a max
+ is less than \a min, \a min is used also as \a max.
- \sa setMinimumDate(), maximumDate(), setMaximumDate(),
- clearMinimumDate(), setMinimumTime(), maximumTime(),
- setMaximumTime(), clearMinimumTime(), QDateTime::isValid()
+ \sa minimumDateTime, maximumDateTime, setDateRange(), setTimeRange(), QDateTime::isValid()
*/
void QDateTimeEdit::setDateTimeRange(const QDateTime &min, const QDateTime &max)
{
Q_D(QDateTimeEdit);
+ // FIXME: does none of the range checks applied to setMin/setMax methods !
const QDateTime minimum = min.toTimeSpec(d->spec);
- QDateTime maximum = max.toTimeSpec(d->spec);
- if (min > max)
- maximum = minimum;
+ const QDateTime maximum = (min > max ? minimum : max.toTimeSpec(d->spec));
d->setRange(minimum, maximum);
}
@@ -449,15 +447,20 @@ void QDateTimeEdit::setDateTimeRange(const QDateTime &min, const QDateTime &max)
\brief the minimum date of the date time edit
- When setting this property the \l maximumDate is adjusted if
- necessary, to ensure that the range remains valid. If the date is
- not a valid QDate object, this function does nothing.
+ Changing this property updates the date of the \l minimumDateTime property
+ while preserving the \l minimumTime property. When setting this property,
+ the \l maximumDate is adjusted, if necessary, to ensure that the range remains
+ valid. When this happens, the \l maximumTime property is also adjusted if it
+ is less than the \l minimumTime property. Otherwise, changes to this property
+ preserve the \l maximumDateTime property.
- By default, this property contains a date that refers to September 14, 1752.
- The minimum date must be at least the first day in year 100, otherwise
- setMinimumDate() has no effect.
+ This property can only be set to a valid QDate object describing a date on
+ which the current \l minimumTime property makes a valid QDateTime object. The
+ earliest date that setMinimumDate() accepts is the start of 100 CE. The
+ default for this property is September 14, 1752 CE. This default can be
+ restored with clearMinimumDateTime().
- \sa minimumTime(), maximumTime(), setDateRange()
+ \sa maximumDate, minimumTime, minimumDateTime, setDateRange(), QDate::isValid()
*/
QDate QDateTimeEdit::minimumDate() const
@@ -484,13 +487,20 @@ void QDateTimeEdit::clearMinimumDate()
\brief the maximum date of the date time edit
- When setting this property the \l minimumDate is adjusted if
- necessary to ensure that the range remains valid. If the date is
- not a valid QDate object, this function does nothing.
-
- By default, this property contains a date that refers to December 31, 9999.
+ Changing this property updates the date of the \l maximumDateTime property
+ while preserving the \l maximumTime property. When setting this property, the
+ \l minimumDate is adjusted, if necessary, to ensure that the range remains
+ valid. When this happens, the \l minimumTime property is also adjusted if it
+ is greater than the \l maximumTime property. Otherwise, changes to this
+ property preserve the \l minimumDateTime property.
+
+ This property can only be set to a valid QDate object describing a date on
+ which the current \l maximumTime property makes a valid QDateTime object. The
+ latest date that setMaximumDate() accepts is the end of 9999 CE. This is the
+ default for this property. This default can be restored with
+ clearMaximumDateTime().
- \sa minimumDate, minimumTime, maximumTime, setDateRange()
+ \sa minimumDate, maximumTime, maximumDateTime, setDateRange(), QDate::isValid()
*/
QDate QDateTimeEdit::maximumDate() const
@@ -502,9 +512,8 @@ QDate QDateTimeEdit::maximumDate() const
void QDateTimeEdit::setMaximumDate(const QDate &max)
{
Q_D(QDateTimeEdit);
- if (max.isValid()) {
+ if (max.isValid())
setMaximumDateTime(QDateTime(max, d->maximum.toTime(), d->spec));
- }
}
void QDateTimeEdit::clearMaximumDate()
@@ -517,13 +526,18 @@ void QDateTimeEdit::clearMaximumDate()
\brief the minimum time of the date time edit
- When setting this property the \l maximumTime is adjusted if
- necessary, to ensure that the range remains valid. If the time is
- not a valid QTime object, this function does nothing.
+ Changing this property updates the time of the \l minimumDateTime property
+ while preserving the \l minimumDate and \l maximumDate properties. If those
+ date properties coincide, when setting this property, the \l maximumTime
+ property is adjusted, if necessary, to ensure that the range remains
+ valid. Otherwise, changing this property preserves the \l maximumDateTime
+ property.
- By default, this property contains a time of 00:00:00 and 0 milliseconds.
+ This property can be set to any valid QTime value. By default, this property
+ contains a time of 00:00:00 and 0 milliseconds. This default can be restored
+ with clearMinimumTime().
- \sa maximumTime, minimumDate, maximumDate, setTimeRange()
+ \sa maximumTime, minimumDate, minimumDateTime, setTimeRange(), QTime::isValid()
*/
QTime QDateTimeEdit::minimumTime() const
@@ -551,13 +565,18 @@ void QDateTimeEdit::clearMinimumTime()
\brief the maximum time of the date time edit
- When setting this property, the \l minimumTime is adjusted if
- necessary to ensure that the range remains valid. If the time is
- not a valid QTime object, this function does nothing.
+ Changing this property updates the time of the \l maximumDateTime property
+ while preserving the \l minimumDate and \l maximumDate properties. If those
+ date properties coincide, when setting this property, the \l minimumTime
+ property is adjusted, if necessary, to ensure that the range remains
+ valid. Otherwise, changing this property preserves the \l minimumDateTime
+ property.
- By default, this property contains a time of 23:59:59 and 999 milliseconds.
+ This property can be set to any valid QTime value. By default, this property
+ contains a time of 23:59:59 and 999 milliseconds. This default can be restored
+ with clearMaximumTime().
- \sa minimumTime, minimumDate, maximumDate, setTimeRange()
+ \sa minimumTime, maximumDate, maximumDateTime, setTimeRange(), QTime::isValid()
*/
QTime QDateTimeEdit::maximumTime() const
{
@@ -580,8 +599,10 @@ void QDateTimeEdit::clearMaximumTime()
}
/*!
- Convenience function to set minimum and maximum date with one
- function call.
+ \brief Set the range of allowed dates for the date time edit.
+
+ This convenience function sets the \l minimumDate and \l maximumDate
+ properties.
\snippet code/src_gui_widgets_qdatetimeedit.cpp 3
@@ -589,12 +610,14 @@ void QDateTimeEdit::clearMaximumTime()
\snippet code/src_gui_widgets_qdatetimeedit.cpp 4
- If either \a min or \a max are not valid, this function does
- nothing.
+ If either \a min or \a max is invalid, this function does nothing. This
+ function preserves the \l minimumTime property. If \a max is less than \a min,
+ the new maximumDateTime property shall be the new minimumDateTime property. If
+ \a max is equal to \a min and the \l maximumTime property was less then the \l
+ minimumTime property, the \l maximumTime property is set to the \l minimumTime
+ property. Otherwise, this preserves the \l maximumTime property.
- \sa setMinimumDate(), maximumDate(), setMaximumDate(),
- clearMinimumDate(), setMinimumTime(), maximumTime(),
- setMaximumTime(), clearMinimumTime(), QDate::isValid()
+ \sa minimumDate, maximumDate, setDateTimeRange(), QDate::isValid()
*/
void QDateTimeEdit::setDateRange(const QDate &min, const QDate &max)
@@ -607,8 +630,16 @@ void QDateTimeEdit::setDateRange(const QDate &min, const QDate &max)
}
/*!
- Convenience function to set minimum and maximum time with one
- function call.
+ \brief Set the range of allowed times for the date time edit.
+
+ This convenience function sets the \l minimumTime and \l maximumTime
+ properties.
+
+ Note that these only constrain the date time edit's value on,
+ respectively, the \l minimumDate and \l maximumDate. When these date
+ properties do not coincide, times after \a maximumTime are allowed on dates
+ before \l maximumDate and times before \a minimumTime are allowed on dates
+ after \l minimumDate.
\snippet code/src_gui_widgets_qdatetimeedit.cpp 5
@@ -616,12 +647,11 @@ void QDateTimeEdit::setDateRange(const QDate &min, const QDate &max)
\snippet code/src_gui_widgets_qdatetimeedit.cpp 6
- If either \a min or \a max are not valid, this function does
- nothing.
+ If either \a min or \a max is invalid, this function does nothing. This
+ function preserves the \l minimumDate and \l maximumDate properties. If those
+ properties coincide and max is \a less than \a min, \a min is used as \a max.
- \sa setMinimumDate(), maximumDate(), setMaximumDate(),
- clearMinimumDate(), setMinimumTime(), maximumTime(),
- setMaximumTime(), clearMinimumTime(), QTime::isValid()
+ \sa minimumTime, maximumTime, setDateTimeRange(), QTime::isValid()
*/
void QDateTimeEdit::setTimeRange(const QTime &min, const QTime &max)
@@ -865,7 +895,7 @@ QString QDateTimeEdit::sectionText(Section section) const
Note that if you specify a two digit year, it will be interpreted
to be in the century in which the date time edit was initialized.
- The default century is the 21 (2000-2099).
+ The default century is the 21st (2000-2099).
If you specify an invalid format the format will not be set.
diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp
index 0d2568b85d..bd5e0b047e 100644
--- a/src/widgets/widgets/qlineedit.cpp
+++ b/src/widgets/widgets/qlineedit.cpp
@@ -1216,8 +1216,8 @@ QMargins QLineEdit::textMargins() const
\row \li \c a \li ASCII alphabetic character permitted but not required.
\row \li \c N \li ASCII alphanumeric character required. A-Z, a-z, 0-9.
\row \li \c n \li ASCII alphanumeric character permitted but not required.
- \row \li \c X \li Any character required.
- \row \li \c x \li Any character permitted but not required.
+ \row \li \c X \li Any non-blank character required.
+ \row \li \c x \li Any non-blank character permitted but not required.
\row \li \c 9 \li ASCII digit required. 0-9.
\row \li \c 0 \li ASCII digit permitted but not required.
\row \li \c D \li ASCII digit required. 1-9.
diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp
index ddcd022fb6..fc7e2dbbcb 100644
--- a/src/widgets/widgets/qmenu.cpp
+++ b/src/widgets/widgets/qmenu.cpp
@@ -792,6 +792,8 @@ void QMenuSloppyState::setSubMenuPopup(const QRect &actionRect, QAction *resetAc
m_use_reset_action = true;
m_time.stop();
m_action_rect = actionRect;
+ if (m_sub_menu)
+ QMenuPrivate::get(m_sub_menu)->sloppyState.m_parent = nullptr;
m_sub_menu = subMenu;
QMenuPrivate::get(subMenu)->sloppyState.m_parent = this;
m_reset_action = resetAction;
diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp
index a50068b5a0..59c8af30b4 100644
--- a/src/widgets/widgets/qmenubar.cpp
+++ b/src/widgets/widgets/qmenubar.cpp
@@ -846,7 +846,8 @@ QMenu *QMenuBar::addMenu(const QIcon &icon, const QString &title)
}
/*!
- Appends \a menu to the menu bar. Returns the menu's menuAction().
+ Appends \a menu to the menu bar. Returns the menu's menuAction(). The menu bar
+ does not take ownership of the menu.
\note The returned QAction object can be used to hide the corresponding
menu.
diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp
index 1856f0296b..0bfaa767c6 100644
--- a/src/widgets/widgets/qplaintextedit.cpp
+++ b/src/widgets/widgets/qplaintextedit.cpp
@@ -2328,6 +2328,7 @@ void QPlainTextEdit::changeEvent(QEvent *e)
d->autoScrollTimer.stop();
} else if (e->type() == QEvent::EnabledChange) {
e->setAccepted(isEnabled());
+ d->control->setPalette(palette());
d->sendControlEvent(e);
} else if (e->type() == QEvent::PaletteChange) {
d->control->setPalette(palette());
diff --git a/src/widgets/widgets/qwidgetlinecontrol.cpp b/src/widgets/widgets/qwidgetlinecontrol.cpp
index a242947c11..9dd61c2c6a 100644
--- a/src/widgets/widgets/qwidgetlinecontrol.cpp
+++ b/src/widgets/widgets/qwidgetlinecontrol.cpp
@@ -1090,7 +1090,7 @@ bool QWidgetLineControl::isValidInput(QChar key, QChar mask) const
return true;
break;
case 'X':
- if (key.isPrint())
+ if (key.isPrint() && key != m_blank)
return true;
break;
case 'x':
diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp
index ce807c9f75..49a1a02867 100644
--- a/src/widgets/widgets/qwidgettextcontrol.cpp
+++ b/src/widgets/widgets/qwidgettextcontrol.cpp
@@ -1283,6 +1283,8 @@ void QWidgetTextControlPrivate::keyPressEvent(QKeyEvent *e)
} else {
QTextCursor localCursor = cursor;
localCursor.deletePreviousChar();
+ if (cursor.d)
+ cursor.d->setX();
}
goto accept;
}
@@ -1322,9 +1324,13 @@ void QWidgetTextControlPrivate::keyPressEvent(QKeyEvent *e)
else if (e == QKeySequence::Delete) {
QTextCursor localCursor = cursor;
localCursor.deleteChar();
+ if (cursor.d)
+ cursor.d->setX();
} else if (e == QKeySequence::Backspace) {
QTextCursor localCursor = cursor;
localCursor.deletePreviousChar();
+ if (cursor.d)
+ cursor.d->setX();
}else if (e == QKeySequence::DeleteEndOfWord) {
if (!cursor.hasSelection())
cursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor);
diff --git a/tests/auto/corelib/global/qglobal/qglobal.c b/tests/auto/corelib/global/qglobal/qglobal.c
index c7124454d0..7a2266ae94 100644
--- a/tests/auto/corelib/global/qglobal/qglobal.c
+++ b/tests/auto/corelib/global/qglobal/qglobal.c
@@ -28,7 +28,7 @@
#include <QtCore/qglobal.h>
-#if QT_HAS_INCLUDE(<stdbool.h>) || __STDC_VERSION__ >= 199901L
+#if __has_include(<stdbool.h>) || __STDC_VERSION__ >= 199901L
# include <stdbool.h>
#else
# undef true
diff --git a/tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp b/tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp
index 4ca68550b9..4e105d7dc7 100644
--- a/tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp
+++ b/tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp
@@ -32,7 +32,7 @@
#include <QtCore/QElapsedTimer>
#include <QtTest/QtTest>
-#if QT_HAS_INCLUDE(<chrono>)
+#if __has_include(<chrono>)
# include <chrono>
#endif
@@ -519,7 +519,7 @@ void tst_QDeadlineTimer::expire()
void tst_QDeadlineTimer::stdchrono()
{
-#if !QT_HAS_INCLUDE(<chrono>)
+#if !__has_include(<chrono>)
QSKIP("std::chrono not found on this system");
#else
using namespace std::chrono;
diff --git a/tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp b/tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp
index 49c10c6a24..365508024b 100644
--- a/tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp
+++ b/tests/auto/corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp
@@ -67,6 +67,7 @@ private slots:
void sendPostedEvents_data();
void sendPostedEvents();
void processEventsOnlySendsQueuedEvents();
+ void eventLoopExit();
};
bool tst_QEventDispatcher::event(QEvent *e)
@@ -314,5 +315,49 @@ void tst_QEventDispatcher::processEventsOnlySendsQueuedEvents()
QCOMPARE(object.eventsReceived, 4);
}
+void tst_QEventDispatcher::eventLoopExit()
+{
+ // This test was inspired by QTBUG-79477. A particular
+ // implementation detail in QCocoaEventDispatcher allowed
+ // QEventLoop::exit() to fail to really exit the event loop.
+ // Thus this test is a part of the dispatcher auto-test.
+
+ // Imitates QApplication::exec():
+ QEventLoop mainLoop;
+ // The test itself is a lambda:
+ QTimer::singleShot(0, [&mainLoop]() {
+ // Two more single shots, both will be posted as events
+ // (zero timeout) and supposed to be processes by the
+ // mainLoop:
+
+ QTimer::singleShot(0, [&mainLoop]() {
+ // wakeUp triggers QCocoaEventDispatcher into incrementing
+ // its 'serialNumber':
+ mainLoop.wakeUp();
+ // QCocoaEventDispatcher::processEvents() will process
+ // posted events and execute the second lambda defined below:
+ QCoreApplication::processEvents();
+ });
+
+ QTimer::singleShot(0, [&mainLoop]() {
+ // With QCocoaEventDispatcher this is executed while in the
+ // processEvents (see above) and would fail to actually
+ // interrupt the loop.
+ mainLoop.exit();
+ });
+ });
+
+ bool timeoutObserved = false;
+ QTimer::singleShot(500, [&timeoutObserved, &mainLoop]() {
+ // In case the QEventLoop::exit above failed, we have to bail out
+ // early, not wasting time:
+ mainLoop.exit();
+ timeoutObserved = true;
+ });
+
+ mainLoop.exec();
+ QVERIFY(!timeoutObserved);
+}
+
QTEST_MAIN(tst_QEventDispatcher)
#include "tst_qeventdispatcher.moc"
diff --git a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
index 8e0bdac520..1bd27cd0ce 100644
--- a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
+++ b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
@@ -223,7 +223,7 @@ void tst_QTimer::remainingTimeDuringActivation()
namespace {
-#if QT_HAS_INCLUDE(<chrono>)
+#if __has_include(<chrono>)
template <typename T>
std::chrono::milliseconds to_ms(T t)
{ return std::chrono::duration_cast<std::chrono::milliseconds>(t); }
@@ -233,7 +233,7 @@ namespace {
void tst_QTimer::basic_chrono()
{
-#if !QT_HAS_INCLUDE(<chrono>)
+#if !__has_include(<chrono>)
QSKIP("This test requires C++11 <chrono> support");
#else
// duplicates zeroTimer, singleShotTimeout, interval and remainingTime
@@ -871,7 +871,7 @@ void tst_QTimer::singleShotToFunctors()
void tst_QTimer::singleShot_chrono()
{
-#if !QT_HAS_INCLUDE(<chrono>)
+#if !__has_include(<chrono>)
QSKIP("This test requires C++11 <chrono> support");
#else
// duplicates singleShotStaticFunctionZeroTimeout and singleShotToFunctors
diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
index c4af2267a8..8db28c7c71 100644
--- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
+++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
@@ -45,7 +45,7 @@
#include <limits.h>
#include <float.h>
#include <cmath>
-#if QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L
+#if __has_include(<variant>) && __cplusplus >= 201703L
#include <variant>
#endif
#include <QLinkedList>
@@ -4568,7 +4568,7 @@ void tst_QVariant::accessSequentialContainerKey()
void tst_QVariant::fromStdVariant()
{
-#if QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L
+#if __has_include(<variant>) && __cplusplus >= 201703L
{
typedef std::variant<int, bool> intorbool_t;
intorbool_t stdvar = 5;
diff --git a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp
index 47ad328d64..d5a9012f9f 100644
--- a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp
+++ b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp
@@ -384,7 +384,7 @@ void tst_QCborValue::copyCompare()
QCOMPARE(v, other);
QVERIFY(!(v != other));
QVERIFY(!(v < other));
-#if 0 && QT_HAS_INCLUDE(<compare>)
+#if 0 && __has_include(<compare>)
QVERIFY(v <= other);
QVERIFY(v >= other);
QVERIFY(!(v > other));
@@ -821,9 +821,37 @@ void tst_QCborValue::mapMutation()
QVERIFY(v.isUndefined());
// now mutate the list
+ // simple -> HasByteData
+ const QString strValue = QStringLiteral("value");
+ v = strValue;
+ QVERIFY(v.isString());
+ QCOMPARE(v, QCborValue(strValue));
+ QCOMPARE(m, QCborMap({{42, strValue}}));
+
+ // HasByteData -> HasByteData
+ const QLatin1String otherStrValue("othervalue");
+ v = otherStrValue;
+ QVERIFY(v.isString());
+ QCOMPARE(v, QCborValue(otherStrValue));
+ QCOMPARE(m, QCborMap({{42, otherStrValue}}));
+
+ // HasByteData -> simple
+ v = 42;
+ QVERIFY(v.isInteger());
+ QCOMPARE(v, QCborValue(42));
+ QCOMPARE(m, QCborMap({{42, 42}}));
+
+ // simple -> container
+ v = QCborArray{1, 2, 3};
+ QVERIFY(v.isArray());
+ QCOMPARE(v, QCborArray({1, 2, 3}));
+ QCOMPARE(m, QCborMap({{42, QCborArray{1, 2, 3}}}));
+
+ // container -> simple
v = true;
QVERIFY(v.isBool());
QVERIFY(v.isTrue());
+ QCOMPARE(m, QCborMap({{42, true}}));
QVERIFY(m.begin()->isTrue());
QVERIFY(m.begin().value() == v);
QVERIFY(v == m.begin().value());
diff --git a/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp b/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp
index 749aa45916..11f34343ab 100644
--- a/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp
+++ b/tests/auto/corelib/thread/qmutex/tst_qmutex.cpp
@@ -89,7 +89,7 @@ enum {
waitTime = 100
};
-#if QT_HAS_INCLUDE(<chrono>)
+#if __has_include(<chrono>)
static Q_CONSTEXPR std::chrono::milliseconds waitTimeAsDuration(waitTime);
#endif
@@ -100,7 +100,7 @@ void tst_QMutex::convertToMilliseconds_data()
QTest::addColumn<qint64>("intValue");
QTest::addColumn<qint64>("expected");
-#if !QT_HAS_INCLUDE(<chrono>)
+#if !__has_include(<chrono>)
QSKIP("This test requires <chrono>");
#endif
@@ -156,7 +156,7 @@ void tst_QMutex::convertToMilliseconds_data()
void tst_QMutex::convertToMilliseconds()
{
-#if !QT_HAS_INCLUDE(<chrono>)
+#if !__has_include(<chrono>)
QSKIP("This test requires <chrono>");
#else
QFETCH(TimeUnit, unit);
@@ -325,7 +325,7 @@ void tst_QMutex::tryLock_non_recursive()
}
void tst_QMutex::try_lock_for_non_recursive() {
-#if !QT_HAS_INCLUDE(<chrono>)
+#if !__has_include(<chrono>)
QSKIP("This test requires <chrono>");
#else
class Thread : public QThread
@@ -454,7 +454,7 @@ void tst_QMutex::try_lock_for_non_recursive() {
void tst_QMutex::try_lock_until_non_recursive()
{
-#if !QT_HAS_INCLUDE(<chrono>)
+#if !__has_include(<chrono>)
QSKIP("This test requires <chrono>");
#else
class Thread : public QThread
@@ -707,7 +707,7 @@ void tst_QMutex::tryLock_recursive()
void tst_QMutex::try_lock_for_recursive()
{
-#if !QT_HAS_INCLUDE(<chrono>)
+#if !__has_include(<chrono>)
QSKIP("This test requires <chrono>");
#else
class Thread : public QThread
@@ -836,7 +836,7 @@ void tst_QMutex::try_lock_for_recursive()
void tst_QMutex::try_lock_until_recursive()
{
-#if !QT_HAS_INCLUDE(<chrono>)
+#if !__has_include(<chrono>)
QSKIP("This test requires <chrono>");
#else
class Thread : public QThread
diff --git a/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp
index 7f13fd0aa5..7778542736 100644
--- a/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp
+++ b/tests/auto/corelib/time/qdatetime/tst_qdatetime.cpp
@@ -150,6 +150,7 @@ private slots:
void timeZones() const;
void systemTimeZoneChange() const;
+ void invalid_data() const;
void invalid() const;
void range() const;
@@ -2209,6 +2210,13 @@ void tst_QDateTime::fromStringDateFormat_data()
<< Qt::TextDate << QDateTime(QDate(2013, 5, 6), QTime(1, 2, 3, 456));
// Test Qt::ISODate format.
+ QTest::newRow("trailing space") // QTBUG-80445
+ << QString("2000-01-02 03:04:05.678 ")
+ << Qt::ISODate << QDateTime(QDate(2000, 1, 2), QTime(3, 4, 5, 678));
+ QTest::newRow("space before millis")
+ << QString("2000-01-02 03:04:05. 678") << Qt::ISODate << QDateTime();
+
+ // Normal usage:
QTest::newRow("ISO +01:00") << QString::fromLatin1("1987-02-13T13:24:51+01:00")
<< Qt::ISODate << QDateTime(QDate(1987, 2, 13), QTime(12, 24, 51), Qt::UTC);
QTest::newRow("ISO +00:01") << QString::fromLatin1("1987-02-13T13:24:51+00:01")
@@ -2229,11 +2237,17 @@ void tst_QDateTime::fromStringDateFormat_data()
<< Qt::ISODate << QDateTime(QDate(2014, 12, 15), QTime(15, 37, 9), Qt::UTC);
QTest::newRow("ISO zzz-3") << QString::fromLatin1("2014-12-15T12:37:09.745-3")
<< Qt::ISODate << QDateTime(QDate(2014, 12, 15), QTime(15, 37, 9, 745), Qt::UTC);
+ QTest::newRow("ISO lower-case") << QString::fromLatin1("2005-06-28T07:57:30.002z")
+ << Qt::ISODate << QDateTime(QDate(2005, 6, 28), QTime(7, 57, 30, 2), Qt::UTC);
// No time specified - defaults to Qt::LocalTime.
QTest::newRow("ISO data3") << QString::fromLatin1("2002-10-01")
<< Qt::ISODate << QDateTime(QDate(2002, 10, 1), QTime(0, 0, 0, 0), Qt::LocalTime);
+ // Excess digits in milliseconds, round correctly:
QTest::newRow("ISO") << QString::fromLatin1("2005-06-28T07:57:30.0010000000Z")
<< Qt::ISODate << QDateTime(QDate(2005, 6, 28), QTime(7, 57, 30, 1), Qt::UTC);
+ QTest::newRow("ISO rounding") << QString::fromLatin1("2005-06-28T07:57:30.0015Z")
+ << Qt::ISODate << QDateTime(QDate(2005, 6, 28), QTime(7, 57, 30, 2), Qt::UTC);
+ // ... and accept comma as separator:
QTest::newRow("ISO with comma 1") << QString::fromLatin1("2005-06-28T07:57:30,0040000000Z")
<< Qt::ISODate << QDateTime(QDate(2005, 6, 28), QTime(7, 57, 30, 4), Qt::UTC);
QTest::newRow("ISO with comma 2") << QString::fromLatin1("2005-06-28T07:57:30,0015Z")
@@ -2458,6 +2472,7 @@ void tst_QDateTime::fromStringStringFormat_data()
if (southBrazil.isValid()) {
QTest::newRow("spring-forward-midnight")
<< QString("2008-10-19 23:45.678 America/Sao_Paulo") << QString("yyyy-MM-dd mm:ss.zzz t")
+ // That's in the hour skipped - expect the matching time after the spring-forward, in DST:
<< QDateTime(QDate(2008, 10, 19), QTime(1, 23, 45, 678), southBrazil);
}
#endif
@@ -3359,6 +3374,9 @@ void tst_QDateTime::timeZones() const
QCOMPARE(utc.date(), utcDst.date());
QCOMPARE(utc.time(), utcDst.time());
+ // Crash test, QTBUG-80146:
+ QVERIFY(!nzStd.toTimeZone(QTimeZone()).isValid());
+
// Sydney is 2 hours behind New Zealand
QTimeZone ausTz = QTimeZone("Australia/Sydney");
QDateTime aus = nzStd.toTimeZone(ausTz);
@@ -3528,23 +3546,42 @@ void tst_QDateTime::systemTimeZoneChange() const
QCOMPARE(tzDate.toMSecsSinceEpoch(), tzMsecs);
}
-void tst_QDateTime::invalid() const
+void tst_QDateTime::invalid_data() const
{
- QDateTime invalidDate = QDateTime(QDate(0, 0, 0), QTime(-1, -1, -1));
- QCOMPARE(invalidDate.isValid(), false);
- QCOMPARE(invalidDate.timeSpec(), Qt::LocalTime);
+ QTest::addColumn<QDateTime>("when");
+ QTest::addColumn<Qt::TimeSpec>("spec");
+ QTest::addColumn<bool>("goodZone");
+ QTest::newRow("default") << QDateTime() << Qt::LocalTime << true;
- QDateTime utcDate = invalidDate.toUTC();
- QCOMPARE(utcDate.isValid(), false);
- QCOMPARE(utcDate.timeSpec(), Qt::UTC);
-
- QDateTime offsetDate = invalidDate.toOffsetFromUtc(3600);
- QCOMPARE(offsetDate.isValid(), false);
- QCOMPARE(offsetDate.timeSpec(), Qt::OffsetFromUTC);
+ QDateTime invalidDate = QDateTime(QDate(0, 0, 0), QTime(-1, -1, -1));
+ QTest::newRow("simple") << invalidDate << Qt::LocalTime << true;
+ QTest::newRow("UTC") << invalidDate.toUTC() << Qt::UTC << true;
+ QTest::newRow("offset")
+ << invalidDate.toOffsetFromUtc(3600) << Qt::OffsetFromUTC << true;
+ QTest::newRow("CET")
+ << invalidDate.toTimeZone(QTimeZone("Europe/Oslo")) << Qt::TimeZone << true;
+
+ // Crash tests, QTBUG-80146:
+ QTest::newRow("nozone+construct")
+ << QDateTime(QDate(1970, 1, 1), QTime(12, 0), QTimeZone()) << Qt::TimeZone << false;
+ QTest::newRow("nozone+fromMSecs")
+ << QDateTime::fromMSecsSinceEpoch(42, QTimeZone()) << Qt::TimeZone << false;
+ QDateTime valid(QDate(1970, 1, 1), QTime(12, 0), Qt::UTC);
+ QTest::newRow("tonozone") << valid.toTimeZone(QTimeZone()) << Qt::TimeZone << false;
+}
- QDateTime tzDate = invalidDate.toTimeZone(QTimeZone("Europe/Oslo"));
- QCOMPARE(tzDate.isValid(), false);
- QCOMPARE(tzDate.timeSpec(), Qt::TimeZone);
+void tst_QDateTime::invalid() const
+{
+ QFETCH(QDateTime, when);
+ QFETCH(Qt::TimeSpec, spec);
+ QFETCH(bool, goodZone);
+ QVERIFY(!when.isValid());
+ QCOMPARE(when.timeSpec(), spec);
+ QCOMPARE(when.timeZoneAbbreviation(), QString());
+ if (!goodZone)
+ QCOMPARE(when.toMSecsSinceEpoch(), 0);
+ QVERIFY(!when.isDaylightTime());
+ QCOMPARE(when.timeZone().isValid(), goodZone);
}
void tst_QDateTime::range() const
diff --git a/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp b/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp
index f6f10e9642..0e4517e740 100644
--- a/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp
+++ b/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp
@@ -51,7 +51,7 @@
#ifdef Q_CC_MSVC
#define COMPILER_HAS_STDLIB_INCLUDE(x) 1
#else
-#define COMPILER_HAS_STDLIB_INCLUDE(x) QT_HAS_INCLUDE(x)
+#define COMPILER_HAS_STDLIB_INCLUDE(x) __has_include(x)
#endif
#if COMPILER_HAS_STDLIB_INCLUDE(<forward_list>)
diff --git a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
index 0e9f94ab2b..3917c859cc 100644
--- a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
+++ b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
@@ -125,6 +125,7 @@ private slots:
void clonePreservesResources();
void clonePreservesUserStates();
void clonePreservesIndentWidth();
+ void clonePreservesFormatsWhenEmpty();
void blockCount();
void defaultStyleSheet();
@@ -2348,6 +2349,32 @@ void tst_QTextDocument::clonePreservesIndentWidth()
delete clone;
}
+void tst_QTextDocument::clonePreservesFormatsWhenEmpty()
+{
+ QTextDocument document;
+ QTextCursor cursor(&document);
+
+ // Change a few char format attributes
+ QTextCharFormat charFormat;
+ charFormat.setFontPointSize(charFormat.fontPointSize() + 1);
+ charFormat.setFontWeight(charFormat.fontWeight() + 1);
+ cursor.setBlockCharFormat(charFormat);
+
+ // Change a few block format attributes
+ QTextBlockFormat blockFormat;
+ blockFormat.setAlignment(Qt::AlignRight); // The default is Qt::AlignLeft
+ blockFormat.setIndent(blockFormat.indent() + 1);
+ cursor.setBlockFormat(blockFormat);
+
+ auto clone = document.clone();
+ QTextCursor cloneCursor(clone);
+
+ QCOMPARE(cloneCursor.blockCharFormat().fontPointSize(), charFormat.fontPointSize());
+ QCOMPARE(cloneCursor.blockCharFormat().fontWeight(), charFormat.fontWeight());
+ QCOMPARE(cloneCursor.blockFormat().alignment(), blockFormat.alignment());
+ QCOMPARE(cloneCursor.blockFormat().indent(), blockFormat.indent());
+}
+
void tst_QTextDocument::blockCount()
{
QCOMPARE(doc->blockCount(), 1);
diff --git a/tests/auto/network/kernel/qnetworkinterface/BLACKLIST b/tests/auto/network/kernel/qnetworkinterface/BLACKLIST
deleted file mode 100644
index e28cc38ee0..0000000000
--- a/tests/auto/network/kernel/qnetworkinterface/BLACKLIST
+++ /dev/null
@@ -1,3 +0,0 @@
-# QTBUG-65667
-[localAddress:linklocal-ipv4]
-windows ci
diff --git a/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp b/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp
index 0c7ba99be5..bc6e5435df 100644
--- a/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp
+++ b/tests/auto/network/kernel/qnetworkinterface/tst_qnetworkinterface.cpp
@@ -215,31 +215,45 @@ void tst_QNetworkInterface::loopbackIPv6()
}
void tst_QNetworkInterface::localAddress_data()
{
+ bool ipv6 = isIPv6Working();
QTest::addColumn<QHostAddress>("target");
QTest::newRow("localhost-ipv4") << QHostAddress(QHostAddress::LocalHost);
- if (isIPv6Working())
+ if (ipv6)
QTest::newRow("localhost-ipv6") << QHostAddress(QHostAddress::LocalHostIPv6);
QTest::newRow("test-server") << QtNetworkSettings::serverIP();
- // Since we don't actually transmit anything, we can list any IPv4 address
- // and it should work. But we're using a linklocal address so that this
- // test can pass even machines that failed to reach a DHCP server.
- QTest::newRow("linklocal-ipv4") << QHostAddress("169.254.0.1");
-
- if (isIPv6Working()) {
- // On the other hand, we can't list just any IPv6 here. It's very
- // likely that this machine has not received a route via ICMPv6-RA or
- // DHCPv6, so it won't have a global route. On some OSes, IPv6 may be
- // enabled per interface, so we need to know which ones work.
- const QList<QHostAddress> addrs = QNetworkInterface::allAddresses();
- for (const QHostAddress &addr : addrs) {
- QString scope = addr.scopeId();
- if (scope.isEmpty())
+ QSet<QHostAddress> added;
+ const QList<QNetworkInterface> ifaces = QNetworkInterface::allInterfaces();
+ for (const QNetworkInterface &iface : ifaces) {
+ if ((iface.flags() & QNetworkInterface::IsUp) == 0)
+ continue;
+ const QList<QNetworkAddressEntry> addrs = iface.addressEntries();
+ for (const QNetworkAddressEntry &entry : addrs) {
+ QHostAddress addr = entry.ip();
+ if (addr.isLoopback())
+ continue; // added above
+
+ if (addr.protocol() == QAbstractSocket::IPv4Protocol) {
+ // add an IPv4 address with bits in the host portion of the address flipped
+ quint32 ip4 = entry.ip().toIPv4Address();
+ addr.setAddress(ip4 ^ ~entry.netmask().toIPv4Address());
+ } else if (!ipv6 || entry.prefixLength() != 64) {
+ continue;
+ } else {
+ // add a random node in this IPv6 network
+ quint64 randomid = qFromBigEndian(Q_UINT64_C(0x8f41f072e5733caa));
+ QIPv6Address ip6 = addr.toIPv6Address();
+ memcpy(&ip6[8], &randomid, sizeof(randomid));
+ addr.setAddress(ip6);
+ }
+
+ if (added.contains(addr))
continue;
- QTest::addRow("linklocal-ipv6-%s", qPrintable(scope))
- << QHostAddress("fe80::1234%" + scope);
+ added.insert(addr);
+
+ QTest::addRow("%s-%s", qPrintable(iface.name()), qPrintable(addr.toString())) << addr;
}
}
}
diff --git a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
index 4c3749eaee..4533284a0f 100644
--- a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
+++ b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
@@ -965,9 +965,7 @@ void tst_QSqlQuery::blob()
//don' make it too big otherwise sybase and mysql will complain
QByteArray ba( BLOBSIZE, 0 );
- int i;
-
- for ( i = 0; i < ( int )ba.size(); ++i )
+ for (int i = 0; i < ba.size(); ++i)
ba[i] = i % 256;
QSqlQuery q( db );
@@ -980,7 +978,7 @@ void tst_QSqlQuery::blob()
QVERIFY_SQL(q, prepare("insert into " + qTableName("qtest_blob", __FILE__, db) + " (id, t_blob) values (?, ?)"));
- for ( i = 0; i < BLOBCOUNT; ++i ) {
+ for (int i = 0; i < BLOBCOUNT; ++i) {
q.addBindValue( i );
q.addBindValue( ba );
QVERIFY_SQL( q, exec() );
@@ -988,13 +986,13 @@ void tst_QSqlQuery::blob()
QVERIFY_SQL(q, exec("select * from " + qTableName("qtest_blob", __FILE__, db)));
- for ( i = 0; i < BLOBCOUNT; ++i ) {
+ for (int i = 0; i < BLOBCOUNT; ++i) {
QVERIFY( q.next() );
QByteArray res = q.value( 1 ).toByteArray();
QVERIFY2( res.size() >= ba.size(),
QString( "array sizes differ, expected %1, got %2" ).arg( ba.size() ).arg( res.size() ).toLatin1() );
- for ( int i2 = 0; i2 < ( int )ba.size(); ++i2 ) {
+ for (int i2 = 0; i2 < ba.size(); ++i2) {
if ( res[i2] != ba[i2] )
QFAIL( QString( "ByteArrays differ at position %1, expected %2, got %3" ).arg(
i2 ).arg(( int )( unsigned char )ba[i2] ).arg(( int )( unsigned char )res[i2] ).toLatin1() );
@@ -1834,7 +1832,7 @@ void tst_QSqlQuery::oci_rawField()
}
// test whether we can fetch values with more than DOUBLE precision
-// note that MySQL's 3.x highest precision is that of a double, although
+// note that SQLite highest precision is that of a double, although
// you can define field with higher precision
void tst_QSqlQuery::precision()
{
@@ -1845,46 +1843,41 @@ void tst_QSqlQuery::precision()
if (dbType == QSqlDriver::Interbase)
QSKIP("DB unable to store high precision");
+ const auto oldPrecision = db.driver()->numericalPrecisionPolicy();
+ db.driver()->setNumericalPrecisionPolicy(QSql::HighPrecision);
const QString qtest_precision(qTableName("qtest_precision", __FILE__, db));
- static const char precStr[] = "1.2345678901234567891";
- const int precStrLen = sizeof(precStr);
+ static const QLatin1String precStr("1.2345678901234567891");
{
// need a new scope for SQLITE
QSqlQuery q( db );
q.exec("drop table " + qtest_precision);
- if ( tst_Databases::isMSAccess( db ) )
- QVERIFY_SQL( q, exec( "create table " + qtest_precision + " (col1 number)" ) );
+ if (tst_Databases::isMSAccess(db))
+ QVERIFY_SQL(q, exec("CREATE TABLE " + qtest_precision + " (col1 number)"));
else
- QVERIFY_SQL( q, exec( "create table " + qtest_precision + " (col1 numeric(21, 20))" ) );
-
- QVERIFY_SQL( q, exec( "insert into " + qtest_precision + " (col1) values (1.2345678901234567891)" ) );
-
- QVERIFY_SQL( q, exec( "select * from " + qtest_precision ) );
- QVERIFY( q.next() );
+ QVERIFY_SQL(q, exec("CREATE TABLE " + qtest_precision + " (col1 numeric(21, 20))"));
- QString val = q.value( 0 ).toString();
-
- if ( !val.startsWith( "1.2345678901234567891" ) ) {
+ QVERIFY_SQL(q, exec("INSERT INTO " + qtest_precision + " (col1) VALUES (" + precStr + ")"));
+ QVERIFY_SQL(q, exec("SELECT * FROM " + qtest_precision));
+ QVERIFY(q.next());
+ const QString val = q.value(0).toString();
+ if (!val.startsWith(precStr)) {
int i = 0;
-
- while ( i < precStrLen && i < val.size() && precStr[i] != 0 && *( precStr + i ) == val[i].toLatin1() )
+ while (i < val.size() && precStr[i] != 0 && precStr[i] == val[i].toLatin1())
i++;
- // MySQL and TDS have crappy precisions by default
- if (dbType == QSqlDriver::MySqlServer) {
- if ( i < 17 )
- QWARN( "MySQL didn't return the right precision" );
- } else if (dbType == QSqlDriver::Sybase) {
- if ( i < 18 )
- QWARN( "TDS didn't return the right precision" );
+ // TDS has crappy precisions by default
+ if (dbType == QSqlDriver::Sybase) {
+ if (i < 18)
+ QWARN("TDS didn't return the right precision");
} else {
- QWARN( QString( tst_Databases::dbToString( db ) + " didn't return the right precision (" +
- QString::number( i ) + " out of 21), " + val ).toLatin1() );
+ QWARN(QString(tst_Databases::dbToString(db) + " didn't return the right precision (" +
+ QString::number(i) + " out of 21), " + val).toUtf8());
}
}
} // SQLITE scope
+ db.driver()->setNumericalPrecisionPolicy(oldPrecision);
}
void tst_QSqlQuery::nullResult()
@@ -2840,10 +2833,11 @@ void tst_QSqlQuery::psql_bindWithDoubleColonCastOperator()
QVERIFY_SQL( q, exec() );
QVERIFY_SQL( q, next() );
- if ( db.driver()->hasFeature( QSqlDriver::PreparedQueries ) )
- QCOMPARE( q.executedQuery(), QString( "select sum((fld1 - fld2)::int) from " + tablename + " where id1 = ? and id2 =? and id3=?" ) );
+ // the positional placeholders are converted to named placeholders in executedQuery()
+ if (db.driver()->hasFeature(QSqlDriver::PreparedQueries))
+ QCOMPARE(q.executedQuery(), QString("select sum((fld1 - fld2)::int) from " + tablename + " where id1 = :myid1 and id2 =:myid2 and id3=:myid3"));
else
- QCOMPARE( q.executedQuery(), QString( "select sum((fld1 - fld2)::int) from " + tablename + " where id1 = 1 and id2 =2 and id3=3" ) );
+ QCOMPARE(q.executedQuery(), QString("select sum((fld1 - fld2)::int) from " + tablename + " where id1 = 1 and id2 =2 and id3=3"));
}
void tst_QSqlQuery::psql_specialFloatValues()
@@ -4003,8 +3997,8 @@ void tst_QSqlQuery::QTBUG_2192()
// Check if retrieved value preserves reported precision
int precision = qMax(0, q.record().field("dt").precision());
- int diff = qAbs(q.value(0).toDateTime().msecsTo(dt));
- int keep = qMin(1000, (int)qPow(10.0, precision));
+ qint64 diff = qAbs(q.value(0).toDateTime().msecsTo(dt));
+ qint64 keep = qMin(1000LL, qRound64(qPow(10.0, precision)));
QVERIFY(diff <= 1000 - keep);
}
}
@@ -4021,8 +4015,10 @@ void tst_QSqlQuery::QTBUG_36211()
QSqlQuery q(db);
QVERIFY_SQL(q, exec(QString("CREATE TABLE %1 (dtwtz timestamptz, dtwotz timestamp)").arg(tableName)));
- QTimeZone l_tzBrazil("BRT");
- QTimeZone l_tzChina("CST");
+ QTimeZone l_tzBrazil("America/Sao_Paulo");
+ QTimeZone l_tzChina("Asia/Shanghai");
+ QVERIFY(l_tzBrazil.isValid());
+ QVERIFY(l_tzChina.isValid());
QDateTime dt = QDateTime(QDate(2014, 10, 30), QTime(14, 12, 02, 357));
QVERIFY_SQL(q, prepare("INSERT INTO " + tableName + " (dtwtz, dtwotz) VALUES (:dt, :dt)"));
q.bindValue(":dt", dt);
@@ -4040,8 +4036,8 @@ void tst_QSqlQuery::QTBUG_36211()
for (int j = 0; j < 2; ++j) {
// Check if retrieved value preserves reported precision
int precision = qMax(0, q.record().field(j).precision());
- int diff = qAbs(q.value(j).toDateTime().msecsTo(dt));
- int keep = qMin(1000, (int)qPow(10.0, precision));
+ qint64 diff = qAbs(q.value(j).toDateTime().msecsTo(dt));
+ qint64 keep = qMin(1000LL, qRound64(qPow(10.0, precision)));
QVERIFY(diff <= 1000 - keep);
}
}
diff --git a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
index 029738652e..afb24bc528 100644
--- a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
+++ b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
@@ -1380,6 +1380,7 @@ void tst_QFiledialog::clearLineEdit()
fd.setFileMode(QFileDialog::AnyFile);
fd.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&fd));
QLineEdit *lineEdit = fd.findChild<QLineEdit*>("fileNameEdit");
QVERIFY(lineEdit);
QCOMPARE(lineEdit->text(), QLatin1String("foo"));
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
index 6f8fd5dcbe..dd747a8616 100644
--- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
@@ -60,6 +60,7 @@
#include <QtGui/qpaintengine.h>
#include <QtGui/qbackingstore.h>
#include <QtGui/qguiapplication.h>
+#include <QtGui/qpa/qplatformwindow.h>
#include <QtGui/qscreen.h>
#include <qmenubar.h>
#include <qcompleter.h>
@@ -227,6 +228,7 @@ private slots:
void setFixedSize();
void ensureCreated();
+ void createAndDestroy();
void winIdChangeEvent();
void persistentWinId();
void showNativeChild();
@@ -4250,6 +4252,58 @@ public:
int winIdChangeEventCount() const { return m_winIdList.count(); }
};
+class CreateDestroyWidget : public WinIdChangeWidget
+{
+public:
+ void create() { QWidget::create(); }
+ void destroy() { QWidget::destroy(); }
+};
+
+void tst_QWidget::createAndDestroy()
+{
+ CreateDestroyWidget widget;
+
+ // Create and destroy via QWidget
+ widget.create();
+ QVERIFY(widget.testAttribute(Qt::WA_WState_Created));
+ QCOMPARE(widget.winIdChangeEventCount(), 1);
+ QVERIFY(widget.internalWinId());
+
+ widget.destroy();
+ QVERIFY(!widget.testAttribute(Qt::WA_WState_Created));
+ QCOMPARE(widget.winIdChangeEventCount(), 2);
+ QVERIFY(!widget.internalWinId());
+
+ // Create via QWidget, destroy via QWindow
+ widget.create();
+ QVERIFY(widget.testAttribute(Qt::WA_WState_Created));
+ QCOMPARE(widget.winIdChangeEventCount(), 3);
+ QVERIFY(widget.internalWinId());
+
+ widget.windowHandle()->destroy();
+ QVERIFY(!widget.testAttribute(Qt::WA_WState_Created));
+ QCOMPARE(widget.winIdChangeEventCount(), 4);
+ QVERIFY(!widget.internalWinId());
+
+ // Create via QWidget again
+ widget.create();
+ QVERIFY(widget.testAttribute(Qt::WA_WState_Created));
+ QCOMPARE(widget.winIdChangeEventCount(), 5);
+ QVERIFY(widget.internalWinId());
+
+ // Destroy via QWindow, create via QWindow
+ widget.windowHandle()->destroy();
+ QVERIFY(widget.windowHandle());
+ QVERIFY(!widget.testAttribute(Qt::WA_WState_Created));
+ QCOMPARE(widget.winIdChangeEventCount(), 6);
+ QVERIFY(!widget.internalWinId());
+
+ widget.windowHandle()->create();
+ QVERIFY(widget.testAttribute(Qt::WA_WState_Created));
+ QCOMPARE(widget.winIdChangeEventCount(), 7);
+ QVERIFY(widget.internalWinId());
+}
+
void tst_QWidget::winIdChangeEvent()
{
{
diff --git a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
index c2475be8b4..bf31f12958 100644
--- a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
+++ b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
@@ -885,9 +885,6 @@ void tst_QLineEdit::hasAcceptableInputMask()
qApp->sendEvent(testWidget, &lostFocus);
QVERIFY(validInput);
- // at the moment we don't strip the blank character if it is valid input, this makes the test between x vs X useless
- QEXPECT_FAIL( "Any optional and required", "To eat blanks or not? Known issue. Task 43172", Abort);
-
// test requiredMask
testWidget->setInputMask(requiredMask);
validInput = true;
diff --git a/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp b/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp
index 336b6ebfd5..a86784f2ec 100644
--- a/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp
+++ b/tests/auto/widgets/widgets/qplaintextedit/tst_qplaintextedit.cpp
@@ -155,6 +155,7 @@ private slots:
#if QT_CONFIG(scrollbar)
void updateAfterChangeCenterOnScroll();
#endif
+ void updateCursorPositionAfterEdit();
private:
void createSelection();
@@ -1802,5 +1803,50 @@ void tst_QPlainTextEdit::updateAfterChangeCenterOnScroll()
#endif
+void tst_QPlainTextEdit::updateCursorPositionAfterEdit()
+{
+ QPlainTextEdit plaintextEdit;
+ plaintextEdit.setPlainText("some text some text\nsome text some text");
+
+ const auto initialPosition = 1;
+
+ // select some text
+ auto cursor = plaintextEdit.textCursor();
+ cursor.setPosition(initialPosition, QTextCursor::MoveAnchor);
+ cursor.setPosition(initialPosition + 3, QTextCursor::KeepAnchor);
+ plaintextEdit.setTextCursor(cursor);
+ QVERIFY(plaintextEdit.textCursor().hasSelection());
+
+ QTest::keyClick(&plaintextEdit, Qt::Key_Delete);
+ QTest::keyClick(&plaintextEdit, Qt::Key_Down);
+ QTest::keyClick(&plaintextEdit, Qt::Key_Up);
+
+ // Moving the cursor down and up should bring it to the initial position
+ QCOMPARE(plaintextEdit.textCursor().position(), initialPosition);
+
+ // Test the same with backspace
+ cursor = plaintextEdit.textCursor();
+ cursor.setPosition(initialPosition + 3, QTextCursor::KeepAnchor);
+ plaintextEdit.setTextCursor(cursor);
+ QVERIFY(plaintextEdit.textCursor().hasSelection());
+
+ QTest::keyClick(&plaintextEdit, Qt::Key_Backspace);
+ QTest::keyClick(&plaintextEdit, Qt::Key_Down);
+ QTest::keyClick(&plaintextEdit, Qt::Key_Up);
+
+ // Moving the cursor down and up should bring it to the initial position
+ QCOMPARE(plaintextEdit.textCursor().position(), initialPosition);
+
+ // Test insertion
+ const QString txt("txt");
+ QApplication::clipboard()->setText(txt);
+ plaintextEdit.paste();
+ QTest::keyClick(&plaintextEdit, Qt::Key_Down);
+ QTest::keyClick(&plaintextEdit, Qt::Key_Up);
+
+ // The curser should move back to the end of the copied text
+ QCOMPARE(plaintextEdit.textCursor().position(), initialPosition + txt.length());
+}
+
QTEST_MAIN(tst_QPlainTextEdit)
#include "tst_qplaintextedit.moc"
diff --git a/tests/benchmarks/corelib/thread/qreadwritelock/tst_qreadwritelock.cpp b/tests/benchmarks/corelib/thread/qreadwritelock/tst_qreadwritelock.cpp
index 1d47d98657..8f8e8300a1 100644
--- a/tests/benchmarks/corelib/thread/qreadwritelock/tst_qreadwritelock.cpp
+++ b/tests/benchmarks/corelib/thread/qreadwritelock/tst_qreadwritelock.cpp
@@ -30,7 +30,7 @@
#include <QtTest/QtTest>
#include <QtCore/private/qmemory_p.h>
#include <mutex>
-#if QT_HAS_INCLUDE(<shared_mutex>)
+#if __has_include(<shared_mutex>)
#if __cplusplus > 201103L
#include <shared_mutex>
#endif
diff --git a/tests/manual/highdpi/main.cpp b/tests/manual/highdpi/main.cpp
index c025f251a2..2a9fb6aa0c 100644
--- a/tests/manual/highdpi/main.cpp
+++ b/tests/manual/highdpi/main.cpp
@@ -39,6 +39,7 @@
#include <QButtonGroup>
#include <QLineEdit>
#include <QPlainTextEdit>
+#include <QTabWidget>
#include <QScrollBar>
#include <QSlider>
#include <QSpinBox>
@@ -51,12 +52,14 @@
#include <QGraphicsView>
#include <QGraphicsTextItem>
#include <QFile>
+#include <QFontMetrics>
#include <QMouseEvent>
#include <QTemporaryDir>
#include <QTimer>
#include <QCommandLineParser>
#include <QCommandLineOption>
#include <QDebug>
+#include <QElapsedTimer>
#include <private/qhighdpiscaling_p.h>
#include <qpa/qplatformscreen.h>
@@ -64,6 +67,12 @@
#include <utility>
+static QTextStream &operator<<(QTextStream &str, const QSizeF &s)
+{
+ str << s.width() << 'x' << s.height();
+ return str;
+}
+
static QTextStream &operator<<(QTextStream &str, const QRect &r)
{
str << r.width() << 'x' << r.height() << Qt::forcesign << r.x() << r.y() << Qt::noforcesign;
@@ -1241,7 +1250,7 @@ public:
}
};
-class MetricsTest : public QWidget
+class MetricsTest : public QTabWidget
{
Q_OBJECT
public:
@@ -1258,14 +1267,25 @@ QT_SCREEN_SCALE_FACTORS=N;N;N or QT_SCREEN_SCALE_FACTORS=name:N
QT_SCALE_FACTOR_ROUNDING_POLICY=Round|Ceil|Floor|RoundPreferFloor|PassThrough
QT_DPI_ADJUSTMENT_POLICY=AdjustDpi|DontAdjustDpi|AdjustUpOnly)";
- resize(480, 360);
+ m_textEdit = addTextPage("Parameters");
+ m_logEdit = addTextPage("Screen Change Log");
- auto layout = new QVBoxLayout(this);
+ const auto screens = QGuiApplication::screens();
+ for (auto screen : screens)
+ connectScreenChangeSignals(screen);
+ connect(qApp, &QGuiApplication::screenAdded, this, &MetricsTest::slotScreenAdded);
+ connect(qApp, &QGuiApplication::primaryScreenChanged, this, &MetricsTest::slotPrimaryScreenChanged);
+ connect(qApp, &QGuiApplication::screenRemoved, this, &MetricsTest::slotScreenRemoved);
- m_textEdit = new QPlainTextEdit;
- m_textEdit->setReadOnly(true);
- layout->addWidget(m_textEdit);
setWindowTitle(formatWindowTitle("Screens"));
+ m_logTimer.start();
+ logMessage(briefFormatScreens());
+
+ // Resize to roughly match the metrics text.
+ const auto metrics = QFontMetrics(m_textEdit->font(), m_textEdit);
+ const int width = 10 + metrics.horizontalAdvance(QStringLiteral("X")) * 50;
+ const int height = 40 + metrics.height() * (10 + 8 * screens.size());
+ resize(width, height);
}
void setVisible(bool visible) override
@@ -1323,15 +1343,118 @@ QT_DPI_ADJUSTMENT_POLICY=AdjustDpi|DontAdjustDpi|AdjustUpOnly)";
private slots:
void screenChanged()
{
- qDebug().noquote() << __FUNCTION__ << windowHandle()->screen()->name();
+ const QString message = QLatin1String("screenChanged ") + windowHandle()->screen()->name();
+ qInfo("%s", qPrintable(message));
+ logMessage(message);
updateMetrics();
}
+ void slotScreenAdded(QScreen *);
+ void slotScreenRemoved(QScreen *);
+ void slotPrimaryScreenChanged(QScreen *);
+ void slotScreenGeometryChanged(const QRect &geometry)
+ { logScreenChangeSignal(sender(), "geometry", geometry); }
+ void slotScreenAvailableGeometryChanged(const QRect &geometry)
+ { logScreenChangeSignal(sender(), "availableGeometry", geometry); }
+ void slotScreenPhysicalSizeChanged(const QSizeF &size)
+ { logScreenChangeSignal(sender(), "physicalSize", size); }
+ void slotScreenPhysicalDotsPerInchChanged(qreal dpi)
+ { logScreenChangeSignal(sender(), "physicalDotsPerInch", dpi); }
+ void slotScreenLogicalDotsPerInchChanged(qreal dpi)
+ { logScreenChangeSignal(sender(), "logicalDotsPerInch", dpi); }
+ void slotScreenVirtualGeometryChanged(const QRect &rect)
+ { logScreenChangeSignal(sender(), "virtualGeometry", rect); }
+ void slotScreenPrimaryOrientationChanged(Qt::ScreenOrientation orientation)
+ { logScreenChangeSignal(sender(), "primaryOrientation", orientation); }
+ void slotScreenOrientationChanged(Qt::ScreenOrientation orientation)
+ { logScreenChangeSignal(sender(), "orientation", orientation); }
+ void slotScreenRefreshRateChanged(qreal refreshRate)
+ { logScreenChangeSignal(sender(), "refreshRate", refreshRate); }
+
private:
+ QPlainTextEdit *addTextPage(const QString &title);
+ void logMessage(const QString &);
+ void connectScreenChangeSignals(QScreen *s);
+ static QString briefFormatScreens();
+ template <class T>
+ void logScreenChangeSignal(const QObject *o, const char *name, const T &value);
+
QPlainTextEdit *m_textEdit;
+ QPlainTextEdit *m_logEdit;
+ QElapsedTimer m_logTimer;
bool m_screenChangedConnected = false;
};
+void MetricsTest::slotScreenAdded(QScreen *screen)
+{
+ logMessage(QLatin1String("Added ") + screen->name() + QLatin1Char(' ')
+ + briefFormatScreens());
+ connectScreenChangeSignals(screen);
+}
+
+void MetricsTest::slotScreenRemoved(QScreen *screen)
+{
+ logMessage(QLatin1String("Removed ") + screen->name() + QLatin1Char(' ')
+ + briefFormatScreens());
+}
+
+void MetricsTest::slotPrimaryScreenChanged(QScreen *screen)
+{
+ logMessage(QLatin1String("PrimaryScreenChanged ") + screen->name() + QLatin1Char(' ')
+ + briefFormatScreens());
+}
+
+QPlainTextEdit *MetricsTest::addTextPage(const QString &title)
+{
+ auto result = new QPlainTextEdit(this);
+ result->setReadOnly(true);
+ result->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
+ addTab(result, title);
+ return result;
+}
+
+void MetricsTest::logMessage(const QString &m)
+{
+ const QString timeStamp =
+ QStringLiteral("%1ms: %2").arg(m_logTimer.elapsed(), 6, 10, QLatin1Char('0')).arg(m);
+ m_logEdit->appendPlainText(timeStamp);
+}
+
+void MetricsTest::connectScreenChangeSignals(QScreen *s)
+{
+ connect(s, &QScreen::geometryChanged, this, &MetricsTest::slotScreenGeometryChanged);
+ connect(s, &QScreen::availableGeometryChanged, this, &MetricsTest::slotScreenAvailableGeometryChanged);
+ connect(s, &QScreen::physicalSizeChanged, this, &MetricsTest::slotScreenPhysicalSizeChanged);
+ connect(s, &QScreen::physicalDotsPerInchChanged, this, &MetricsTest::slotScreenPhysicalDotsPerInchChanged);
+ connect(s, &QScreen::logicalDotsPerInchChanged, this, &MetricsTest::slotScreenLogicalDotsPerInchChanged);
+ connect(s, &QScreen::virtualGeometryChanged, this, &MetricsTest::slotScreenVirtualGeometryChanged);
+ connect(s, &QScreen::primaryOrientationChanged, this, &MetricsTest::slotScreenPrimaryOrientationChanged);
+ connect(s, &QScreen::orientationChanged, this, &MetricsTest::slotScreenOrientationChanged);
+ connect(s, &QScreen::refreshRateChanged, this, &MetricsTest::slotScreenRefreshRateChanged);
+}
+
+QString MetricsTest::briefFormatScreens()
+{
+ QString message;
+ QTextStream str(&message);
+ const auto screens = QGuiApplication::screens();
+ for (int i = 0, size = screens.size(); i < size; ++i) {
+ str << (i ? ", " : "(");
+ str << screens.at(i)->name() << " " << screens.at(i)->geometry();
+ }
+ str << ')';
+ return message;
+}
+
+template <class T>
+void MetricsTest::logScreenChangeSignal(const QObject *o, const char *name, const T &value)
+{
+ auto screen = qobject_cast<const QScreen *>(o);
+ QString message;
+ QTextStream(&message) << (screen ? screen->name() : QString()) << ' ' << name << " changed: " << value;
+ logMessage(message);
+}
+
int main(int argc, char **argv)
{
#define NOSCALINGOPTION "noscaling"
diff --git a/tests/testserver/docker-compose-bridge-network.yml b/tests/testserver/docker-compose-bridge-network.yml
index 2cabeee1dc..8054d631f8 100644
--- a/tests/testserver/docker-compose-bridge-network.yml
+++ b/tests/testserver/docker-compose-bridge-network.yml
@@ -1,11 +1,20 @@
version: '2.1'
-# The tag of images is used by docker compose file to launch the corresponding
-# docker containers. The value of tag comes from the provisioning script
-# (coin/provisioning/.../testserver/docker_testserver.sh). The script gets SHA-1
-# of each server context as the tag of docker images. If one of the server
-# contexts gets changes, please make sure to update this compose file as well.
-# You can run command 'docker images' to list all the tags of test server images.
+# The tag of images is used by docker compose file to launch the correct
+# docker containers. By default we always launch the "latest" tag.
+#
+# But in the "docker build" phase, we also tag the images with a unique tag,
+# the SHA1 hash of all files used for "docker build" - see sha1tree() in
+# provisioning.
+#
+# So if you want to update the docker image at a specific time, make sure that
+# 1. you modify this file to run the specific image's SHA1 tag, instead of
+# "latest"
+# 2. you build two docker images in provisioning, the currently used one,
+# plus the new one that you tag as "latest"
+# 3. you switch this file to the "latest" tag when ready
+
+# You can run `docker images` to list all the tags of available images:
# For example:
# REPOSITORY TAG
# qt-test-server-apache2 537fe302f61851d1663f41495230d8e3554a4a13
@@ -20,7 +29,7 @@ services:
build:
context: .
args:
- provisioningImage: qt-test-server-apache2:537fe302f61851d1663f41495230d8e3554a4a13
+ provisioningImage: qt-test-server-apache2:latest
shareDir: ./common
serviceDir: ./apache2
entrypoint: service/startup.sh
@@ -43,7 +52,7 @@ services:
build:
context: .
args:
- provisioningImage: qt-test-server-squid:9c32f41b19aca3d778733c4d8fb0ecc5955e893c
+ provisioningImage: qt-test-server-squid:latest
shareDir: ./common
serviceDir: ./squid
entrypoint: service/startup.sh
@@ -58,7 +67,7 @@ services:
build:
context: .
args:
- provisioningImage: qt-test-server-vsftpd:f3a9c8d793a77cc007c0e4e481bec01f9e3eeb7e
+ provisioningImage: qt-test-server-vsftpd:latest
shareDir: ./common
serviceDir: ./vsftpd
entrypoint: service/startup.sh
@@ -77,7 +86,7 @@ services:
build:
context: .
args:
- provisioningImage: qt-test-server-ftp-proxy:d7de8b28392d173db512a558ccc84ead8bece2ae
+ provisioningImage: qt-test-server-ftp-proxy:latest
shareDir: ./common
serviceDir: ./ftp-proxy
entrypoint: service/startup.sh
@@ -102,7 +111,7 @@ services:
build:
context: .
args:
- provisioningImage: qt-test-server-danted:35607f9b790524cf9690c7d12a9a401696b7b6b5
+ provisioningImage: qt-test-server-danted:latest
shareDir: ./common
serviceDir: ./danted
entrypoint: service/startup.sh
@@ -117,7 +126,7 @@ services:
build:
context: .
args:
- provisioningImage: qt-test-server-cyrus:c8d72754abc0e501afd624ce838e4df35505abc9
+ provisioningImage: qt-test-server-cyrus:latest
shareDir: ./common
serviceDir: ./cyrus
entrypoint: service/startup.sh
@@ -132,7 +141,7 @@ services:
build:
context: .
args:
- provisioningImage: qt-test-server-iptables:cb7a8bd6d28602085a88c8ced7d67e28e75781e2
+ provisioningImage: qt-test-server-iptables:latest
shareDir: ./common
serviceDir: ./iptables
entrypoint: service/startup.sh
@@ -150,7 +159,7 @@ services:
build:
context: .
args:
- provisioningImage: qt-test-server-echo:b29ad409e746a834c1055fd0f7a55fd5056da6ea
+ provisioningImage: qt-test-server-echo:latest
shareDir: ./common
serviceDir: ./echo
entrypoint: service/startup.sh
diff --git a/tests/testserver/docker-compose-host-network.yml b/tests/testserver/docker-compose-host-network.yml
index 4b2e1ebdab..aedd94cf73 100644
--- a/tests/testserver/docker-compose-host-network.yml
+++ b/tests/testserver/docker-compose-host-network.yml
@@ -1,14 +1,7 @@
version: '2.1'
-# The tag of images is used by docker compose file to launch the corresponding
-# docker containers. The value of tag comes from the provisioning script
-# (coin/provisioning/.../testserver/docker_testserver.sh). The script gets SHA-1
-# of each server context as the tag of docker images. If one of the server
-# contexts gets changes, please make sure to update this compose file as well.
-# You can run command 'docker images' to list all the tags of test server images.
-# For example:
-# REPOSITORY TAG
-# qt-test-server-apache2 537fe302f61851d1663f41495230d8e3554a4a13
+# For details about the "latest" tag used in the images here, see comments in
+# docker-compose-bridge-network.yml
services:
apache2:
@@ -20,7 +13,7 @@ services:
build:
context: .
args:
- provisioningImage: qt-test-server-apache2:537fe302f61851d1663f41495230d8e3554a4a13
+ provisioningImage: qt-test-server-apache2:latest
shareDir: ./common
serviceDir: ./apache2
entrypoint: service/startup.sh
@@ -39,7 +32,7 @@ services:
build:
context: .
args:
- provisioningImage: qt-test-server-squid:9c32f41b19aca3d778733c4d8fb0ecc5955e893c
+ provisioningImage: qt-test-server-squid:latest
shareDir: ./common
serviceDir: ./squid
entrypoint: service/startup.sh
@@ -54,7 +47,7 @@ services:
build:
context: .
args:
- provisioningImage: qt-test-server-vsftpd:f3a9c8d793a77cc007c0e4e481bec01f9e3eeb7e
+ provisioningImage: qt-test-server-vsftpd:latest
shareDir: ./common
serviceDir: ./vsftpd
entrypoint: service/startup.sh
@@ -71,7 +64,7 @@ services:
build:
context: .
args:
- provisioningImage: qt-test-server-ftp-proxy:d7de8b28392d173db512a558ccc84ead8bece2ae
+ provisioningImage: qt-test-server-ftp-proxy:latest
shareDir: ./common
serviceDir: ./ftp-proxy
entrypoint: service/startup.sh
@@ -90,7 +83,7 @@ services:
build:
context: .
args:
- provisioningImage: qt-test-server-danted:35607f9b790524cf9690c7d12a9a401696b7b6b5
+ provisioningImage: qt-test-server-danted:latest
shareDir: ./common
serviceDir: ./danted
entrypoint: service/startup.sh