summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2016-06-13 09:01:02 +0200
committerLiang Qi <liang.qi@qt.io>2016-06-13 12:46:46 +0200
commit511790fd1af1e2886a0e2e8dd4308099705cd815 (patch)
treeb42aee537a6103cd064f9f41ae2889b09b79fd23 /src
parent1542d8881fc5ccbc5918cd4acbe4091ebbd24508 (diff)
parentcbe332405aa22257d432f1797b325f5e57007c20 (diff)
Merge remote-tracking branch 'origin/5.7' into dev
Conflicts: config_help.txt configure mkspecs/features/uikit/sdk.prf src/corelib/global/qhooks.cpp src/corelib/io/qfilesystemwatcher.cpp src/corelib/io/qlockfile_unix.cpp src/corelib/tools/qalgorithms.h src/gui/kernel/qwindowsysteminterface.h src/gui/text/qtextdocument_p.cpp src/network/access/access.pri src/network/access/qnetworkaccessmanager.cpp src/network/access/qnetworkreplynsurlconnectionimpl.mm src/src.pro src/testlib/qtestcase.cpp src/widgets/kernel/qwidgetbackingstore_p.h src/widgets/styles/qwindowscestyle.cpp src/widgets/styles/qwindowsmobilestyle.cpp tests/auto/corelib/io/qdiriterator/qdiriterator.pro tests/auto/corelib/io/qfileinfo/qfileinfo.pro tests/auto/gui/kernel/qwindow/BLACKLIST tests/auto/widgets/dialogs/qfilesystemmodel/tst_qfilesystemmodel.cpp tools/configure/configureapp.cpp Change-Id: Ibf7fb9c8cf263a810ade82f821345d0725c57c67
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/forkfd/forkfd.c46
-rw-r--r--src/3rdparty/freetype/freetype.pro9
-rw-r--r--src/3rdparty/libpng.pri21
-rw-r--r--src/3rdparty/libpng/libpng.pro31
-rw-r--r--src/3rdparty/png_dependency.pri3
-rw-r--r--src/concurrent/qtconcurrentiteratekernel.cpp2
-rw-r--r--src/corelib/Qt5CoreConfigExtras.cmake.in15
-rw-r--r--src/corelib/animation/qvariantanimation.cpp6
-rw-r--r--src/corelib/doc/src/animation.qdoc11
-rw-r--r--src/corelib/global/global.pri23
-rw-r--r--src/corelib/global/qcompilerdetection.h7
-rw-r--r--src/corelib/global/qendian.h24
-rw-r--r--src/corelib/global/qendian.qdoc23
-rw-r--r--src/corelib/global/qhooks.cpp2
-rw-r--r--src/corelib/global/qsystemdetection.h4
-rw-r--r--src/corelib/io/io.pri1
-rw-r--r--src/corelib/io/qdebug.cpp9
-rw-r--r--src/corelib/io/qfileinfo.cpp4
-rw-r--r--src/corelib/io/qfilesystemwatcher.cpp4
-rw-r--r--src/corelib/io/qfilesystemwatcher_kqueue.cpp2
-rw-r--r--src/corelib/io/qlockfile_unix.cpp43
-rw-r--r--src/corelib/io/qlockfile_win.cpp6
-rw-r--r--src/corelib/io/qprocess.cpp10
-rw-r--r--src/corelib/io/qstorageinfo_unix.cpp2
-rw-r--r--src/corelib/io/qwindowspipewriter.cpp2
-rw-r--r--src/corelib/json/qjson_p.h4
-rw-r--r--src/corelib/json/qjsonobject.cpp4
-rw-r--r--src/corelib/json/qjsonvalue.cpp24
-rw-r--r--src/corelib/kernel/qcore_unix.cpp10
-rw-r--r--src/corelib/kernel/qcore_unix_p.h10
-rw-r--r--src/corelib/kernel/qobject.cpp2
-rw-r--r--src/corelib/kernel/qobject.h29
-rw-r--r--src/corelib/kernel/qobject_impl.h29
-rw-r--r--src/corelib/kernel/qobjectdefs_impl.h381
-rw-r--r--src/corelib/mimetypes/qmimemagicrule.cpp3
-rw-r--r--src/corelib/thread/qmutex_linux.cpp2
-rw-r--r--src/corelib/tools/qarraydata.cpp34
-rw-r--r--src/corelib/tools/qbitarray.cpp26
-rw-r--r--src/corelib/tools/qbytearray.cpp112
-rw-r--r--src/corelib/tools/qcryptographichash.cpp20
-rw-r--r--src/corelib/tools/qdatetime.cpp2
-rw-r--r--src/corelib/tools/qdatetimeparser.cpp23
-rw-r--r--src/corelib/tools/qdatetimeparser_p.h14
-rw-r--r--src/corelib/tools/qhash.cpp9
-rw-r--r--src/corelib/tools/qlist.cpp29
-rw-r--r--src/corelib/tools/qmessageauthenticationcode.cpp20
-rw-r--r--src/corelib/tools/qsimd.cpp22
-rw-r--r--src/corelib/tools/qstring.cpp16
-rw-r--r--src/corelib/tools/qtimezoneprivate_tz.cpp214
-rw-r--r--src/corelib/tools/qtools_p.h14
-rw-r--r--src/corelib/tools/qvector.h8
-rw-r--r--src/corelib/xml/qxmlstream.cpp18
-rw-r--r--src/gui/doc/snippets/code/src_gui_kernel_qclipboard.cpp2
-rw-r--r--src/gui/image/qbmphandler.cpp16
-rw-r--r--src/gui/image/qicon.cpp2
-rw-r--r--src/gui/image/qiconloader.cpp2
-rw-r--r--src/gui/image/qimage.cpp55
-rw-r--r--src/gui/image/qimagepixmapcleanuphooks.cpp18
-rw-r--r--src/gui/image/qpnghandler.cpp2
-rw-r--r--src/gui/image/qxpmhandler.cpp2
-rw-r--r--src/gui/itemmodels/qstandarditemmodel.cpp9
-rw-r--r--src/gui/kernel/qclipboard.cpp8
-rw-r--r--src/gui/kernel/qevent.cpp3
-rw-r--r--src/gui/kernel/qguiapplication.cpp4
-rw-r--r--src/gui/kernel/qkeysequence.cpp13
-rw-r--r--src/gui/kernel/qopenglcontext.cpp4
-rw-r--r--src/gui/kernel/qplatformintegration.cpp4
-rw-r--r--src/gui/kernel/qplatformscreen.cpp2
-rw-r--r--src/gui/kernel/qwindow.cpp8
-rw-r--r--src/gui/kernel/qwindowsysteminterface.h4
-rw-r--r--src/gui/opengl/qopenglframebufferobject.cpp7
-rw-r--r--src/gui/opengl/qopenglgradientcache.cpp33
-rw-r--r--src/gui/painting/qpainter.cpp11
-rw-r--r--src/gui/painting/qpainterpath.cpp31
-rw-r--r--src/gui/painting/qpathclipper.cpp16
-rw-r--r--src/gui/painting/qpdf.cpp4
-rw-r--r--src/gui/text/qcssparser.cpp10
-rw-r--r--src/gui/text/qfont.cpp4
-rw-r--r--src/gui/text/qfontdatabase.cpp17
-rw-r--r--src/gui/text/qfontengine.cpp3
-rw-r--r--src/gui/text/qfragmentmap_p.h9
-rw-r--r--src/gui/text/qtextdocument.cpp15
-rw-r--r--src/gui/text/qtextdocument_p.cpp21
-rw-r--r--src/gui/text/qtextdocumentfragment.cpp6
-rw-r--r--src/gui/text/qtextdocumentlayout.cpp24
-rw-r--r--src/gui/text/qtextengine.cpp12
-rw-r--r--src/gui/text/qtextformat.cpp9
-rw-r--r--src/gui/text/qtextformat.h4
-rw-r--r--src/gui/text/qtexthtmlparser.cpp2
-rw-r--r--src/gui/text/qtextodfwriter.cpp8
-rw-r--r--src/gui/text/qtexttable.cpp20
-rw-r--r--src/gui/util/qgridlayoutengine.cpp19
-rw-r--r--src/network/access/access.pri10
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp2
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp10
-rw-r--r--src/network/access/qnetworkaccessmanager.h1
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp46
-rw-r--r--src/network/access/qnetworkreplyhttpimpl_p.h5
-rw-r--r--src/network/access/qnetworkreplyimpl.cpp40
-rw-r--r--src/network/access/qnetworkreplyimpl_p.h5
-rw-r--r--src/network/access/qnetworkreplynsurlconnectionimpl.mm454
-rw-r--r--src/network/access/qnetworkreplynsurlconnectionimpl_p.h87
-rw-r--r--src/network/kernel/qdnslookup_unix.cpp7
-rw-r--r--src/network/kernel/qhostaddress.cpp7
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp6
-rw-r--r--src/network/socket/qnativesocketengine_winrt.cpp30
-rw-r--r--src/network/socket/qnativesocketengine_winrt_p.h3
-rw-r--r--src/network/socket/qsocks5socketengine.cpp4
-rw-r--r--src/network/ssl/qsslsocket.cpp3
-rw-r--r--src/network/ssl/qsslsocket_openssl.cpp6
-rw-r--r--src/platformheaders/doc/src/qtplatformheaders.qdoc13
-rw-r--r--src/platformsupport/devicediscovery/devicediscovery.pri22
-rw-r--r--src/platformsupport/eglconvenience/qeglconvenience.cpp4
-rw-r--r--src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp15
-rw-r--r--src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h3
-rw-r--r--src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp13
-rw-r--r--src/platformsupport/platformsupport.pro6
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm8
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm18
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp2
-rw-r--r--src/plugins/platforms/ios/qiosinputcontext.h5
-rw-r--r--src/plugins/platforms/ios/qiosinputcontext.mm40
-rw-r--r--src/plugins/platforms/ios/qiostextinputoverlay.mm38
-rw-r--r--src/plugins/platforms/ios/qiostextresponder.mm1
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.mm9
-rw-r--r--src/plugins/platforms/minimal/minimal.pro1
-rw-r--r--src/plugins/platforms/platforms.pro4
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.cpp67
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsfontengine.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp4
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.cpp11
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp14
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h2
-rw-r--r--src/plugins/platforms/winrt/qwinrtdrag.cpp893
-rw-r--r--src/plugins/platforms/winrt/qwinrtdrag.h113
-rw-r--r--src/plugins/platforms/winrt/qwinrtintegration.cpp14
-rw-r--r--src/plugins/platforms/winrt/qwinrtintegration.h4
-rw-r--r--src/plugins/platforms/winrt/qwinrtscreen.cpp18
-rw-r--r--src/plugins/platforms/winrt/winrt.pro11
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp6
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp16
-rw-r--r--src/plugins/plugins.pro2
-rw-r--r--src/plugins/printsupport/windows/qwindowsprintdevice.cpp156
-rw-r--r--src/src.pro9
-rw-r--r--src/testlib/doc/qttestlib.qdocconf2
-rw-r--r--src/testlib/doc/src/qttestlib-manual.qdoc5
-rw-r--r--src/testlib/qtest.h2
-rw-r--r--src/testlib/qtestblacklist.cpp70
-rw-r--r--src/testlib/qtestcase.cpp2
-rw-r--r--src/widgets/dialogs/qdialog.cpp6
-rw-r--r--src/widgets/itemviews/qabstractitemview.cpp3
-rw-r--r--src/widgets/kernel/qdesktopwidget.cpp99
-rw-r--r--src/widgets/kernel/qdesktopwidget_p.h16
-rw-r--r--src/widgets/kernel/qopenglwidget.cpp4
-rw-r--r--src/widgets/kernel/qwidgetbackingstore.cpp22
-rw-r--r--src/widgets/kernel/qwidgetbackingstore_p.h2
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp8
-rw-r--r--src/widgets/styles/qfusionstyle.cpp3
-rw-r--r--src/widgets/styles/qmacstyle_mac.mm4
-rw-r--r--src/widgets/styles/qwindowsstyle.cpp3
-rw-r--r--src/widgets/styles/qwindowsvistastyle.cpp2
-rw-r--r--src/widgets/styles/qwindowsxpstyle.cpp3
-rw-r--r--src/widgets/widgets/qmenu.cpp13
-rw-r--r--src/widgets/widgets/qwidgetlinecontrol.cpp19
-rw-r--r--src/widgets/widgets/qwidgetlinecontrol_p.h5
167 files changed, 2499 insertions, 1904 deletions
diff --git a/src/3rdparty/forkfd/forkfd.c b/src/3rdparty/forkfd/forkfd.c
index ad05ab1a01..7b711e197b 100644
--- a/src/3rdparty/forkfd/forkfd.c
+++ b/src/3rdparty/forkfd/forkfd.c
@@ -30,6 +30,9 @@
#include "forkfd.h"
#include <sys/types.h>
+#if defined(__OpenBSD__) || defined(__NetBSD__)
+# include <sys/param.h>
+#endif
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/wait.h>
@@ -65,7 +68,9 @@
# undef HAVE_WAITID
#endif
-#if defined(__FreeBSD__) && defined(__FreeBSD_version) && __FreeBSD_version >= 1000032
+#if (defined(__FreeBSD__) && defined(__FreeBSD_version) && __FreeBSD_version >= 1000032) || \
+ (defined(__OpenBSD__) && OpenBSD >= 201505) || \
+ (defined(__NetBSD__) && __NetBSD_Version__ >= 600000000)
# define HAVE_PIPE2 1
#endif
#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) || \
@@ -410,6 +415,26 @@ chain_handler:
old_sigaction.sa_handler(signum);
}
+static void ignore_sigpipe()
+{
+#ifdef O_NOSIGPIPE
+ static ffd_atomic_int done = FFD_ATOMIC_INIT(0);
+ if (ffd_atomic_load(&done, FFD_ATOMIC_RELAXED))
+ return;
+#endif
+
+ struct sigaction action;
+ memset(&action, 0, sizeof action);
+ sigemptyset(&action.sa_mask);
+ action.sa_handler = SIG_IGN;
+ action.sa_flags = 0;
+ sigaction(SIGPIPE, &action, NULL);
+
+#ifdef O_NOSIGPIPE
+ ffd_atomic_store(&done, 1, FFD_ATOMIC_RELAXED);
+#endif
+}
+
static void forkfd_initialize()
{
#if defined(HAVE_BROKEN_WAITID)
@@ -446,6 +471,11 @@ static void forkfd_initialize()
*/
sigaction(SIGCHLD, &action, &old_sigaction);
+#ifndef O_NOSIGPIPE
+ /* disable SIGPIPE too */
+ ignore_sigpipe();
+#endif
+
#ifndef __GNUC__
atexit(cleanup);
#endif
@@ -486,13 +516,23 @@ static void cleanup()
static int create_pipe(int filedes[], int flags)
{
- int ret;
+ int ret = -1;
#ifdef HAVE_PIPE2
/* use pipe2(2) whenever possible, since it can thread-safely create a
* cloexec pair of pipes. Without it, we have a race condition setting
* FD_CLOEXEC
*/
- ret = pipe2(filedes, O_CLOEXEC);
+
+# ifdef O_NOSIGPIPE
+ /* try first with O_NOSIGPIPE */
+ ret = pipe2(filedes, O_CLOEXEC | O_NOSIGPIPE);
+ if (ret == -1) {
+ /* O_NOSIGPIPE not supported, ignore SIGPIPE */
+ ignore_sigpipe();
+ }
+# endif
+ if (ret == -1)
+ ret = pipe2(filedes, O_CLOEXEC);
if (ret == -1)
return ret;
diff --git a/src/3rdparty/freetype/freetype.pro b/src/3rdparty/freetype/freetype.pro
index e85ed1699b..41ca469576 100644
--- a/src/3rdparty/freetype/freetype.pro
+++ b/src/3rdparty/freetype/freetype.pro
@@ -68,12 +68,7 @@ DEFINES += FT2_BUILD_LIBRARY
DEFINES += FT_CONFIG_OPTION_SYSTEM_ZLIB
include(../zlib_dependency.pri)
-contains(QT_CONFIG, system-png) {
- DEFINES += FT_CONFIG_OPTION_USE_PNG
- include($$PWD/../png_dependency.pri)
-} else:!contains(QT_CONFIG, no-png):!win32 {
- DEFINES += FT_CONFIG_OPTION_USE_PNG
- include($$PWD/../libpng.pri)
-}
+DEFINES += FT_CONFIG_OPTION_USE_PNG
+include($$PWD/../png_dependency.pri)
DEFINES += TT_CONFIG_OPTION_SUBPIXEL_HINTING
diff --git a/src/3rdparty/libpng.pri b/src/3rdparty/libpng.pri
deleted file mode 100644
index a5fe32f867..0000000000
--- a/src/3rdparty/libpng.pri
+++ /dev/null
@@ -1,21 +0,0 @@
-DEFINES += PNG_ARM_NEON_OPT=0
-INCLUDEPATH += $$PWD/libpng
-SOURCES += $$PWD/libpng/png.c \
- $$PWD/libpng/pngerror.c \
- $$PWD/libpng/pngget.c \
- $$PWD/libpng/pngmem.c \
- $$PWD/libpng/pngpread.c \
- $$PWD/libpng/pngread.c \
- $$PWD/libpng/pngrio.c \
- $$PWD/libpng/pngrtran.c \
- $$PWD/libpng/pngrutil.c \
- $$PWD/libpng/pngset.c \
- $$PWD/libpng/pngtrans.c \
- $$PWD/libpng/pngwio.c \
- $$PWD/libpng/pngwrite.c \
- $$PWD/libpng/pngwtran.c \
- $$PWD/libpng/pngwutil.c
-
-TR_EXCLUDE += $$PWD/*
-
-include($$PWD/zlib_dependency.pri)
diff --git a/src/3rdparty/libpng/libpng.pro b/src/3rdparty/libpng/libpng.pro
new file mode 100644
index 0000000000..ab6dd51e2b
--- /dev/null
+++ b/src/3rdparty/libpng/libpng.pro
@@ -0,0 +1,31 @@
+TARGET = qtpng
+
+CONFIG += \
+ static \
+ hide_symbols \
+ exceptions_off rtti_off warn_off \
+ installed
+
+load(qt_helper_lib)
+
+DEFINES += PNG_ARM_NEON_OPT=0
+SOURCES += \
+ png.c \
+ pngerror.c \
+ pngget.c \
+ pngmem.c \
+ pngpread.c \
+ pngread.c \
+ pngrio.c \
+ pngrtran.c \
+ pngrutil.c \
+ pngset.c \
+ pngtrans.c \
+ pngwio.c \
+ pngwrite.c \
+ pngwtran.c \
+ pngwutil.c
+
+TR_EXCLUDE += $$PWD/*
+
+include(../zlib_dependency.pri)
diff --git a/src/3rdparty/png_dependency.pri b/src/3rdparty/png_dependency.pri
index 78da861f77..eb32432b49 100644
--- a/src/3rdparty/png_dependency.pri
+++ b/src/3rdparty/png_dependency.pri
@@ -2,5 +2,6 @@ contains(QT_CONFIG, system-png) {
unix|mingw: LIBS_PRIVATE += -lpng
else: LIBS += libpng.lib
} else: contains(QT_CONFIG, png) {
- include($$PWD/libpng.pri)
+ INCLUDEPATH += $$PWD/libpng
+ LIBS_PRIVATE += -L$$QT_BUILD_TREE/lib -lqtpng$$qtPlatformTargetSuffix()
}
diff --git a/src/concurrent/qtconcurrentiteratekernel.cpp b/src/concurrent/qtconcurrentiteratekernel.cpp
index a04f0d66cc..4b6ccc2810 100644
--- a/src/concurrent/qtconcurrentiteratekernel.cpp
+++ b/src/concurrent/qtconcurrentiteratekernel.cpp
@@ -77,7 +77,7 @@ static qint64 getticks()
static qint64 getticks()
{
-#if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
+#if (defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)) || defined(Q_OS_OPENBSD)
clockid_t clockId;
#ifndef _POSIX_THREAD_CPUTIME
diff --git a/src/corelib/Qt5CoreConfigExtras.cmake.in b/src/corelib/Qt5CoreConfigExtras.cmake.in
index a5ed8b2ea3..f492148a50 100644
--- a/src/corelib/Qt5CoreConfigExtras.cmake.in
+++ b/src/corelib/Qt5CoreConfigExtras.cmake.in
@@ -46,6 +46,21 @@ if (NOT TARGET Qt5::rcc)
)
endif()
+if (NOT TARGET Qt5::qdoc)
+ add_executable(Qt5::qdoc IMPORTED)
+
+!!IF isEmpty(CMAKE_BIN_DIR_IS_ABSOLUTE)
+ set(imported_location \"${_qt5Core_install_prefix}/$${CMAKE_BIN_DIR}qdoc$$CMAKE_BIN_SUFFIX\")
+!!ELSE
+ set(imported_location \"$${CMAKE_BIN_DIR}qdoc$$CMAKE_BIN_SUFFIX\")
+!!ENDIF
+ _qt5_Core_check_file_exists(${imported_location})
+
+ set_target_properties(Qt5::qdoc PROPERTIES
+ IMPORTED_LOCATION ${imported_location}
+ )
+endif()
+
set(Qt5Core_QMAKE_EXECUTABLE Qt5::qmake)
set(Qt5Core_MOC_EXECUTABLE Qt5::moc)
set(Qt5Core_RCC_EXECUTABLE Qt5::rcc)
diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp
index a783bcc31e..7117092c54 100644
--- a/src/corelib/animation/qvariantanimation.cpp
+++ b/src/corelib/animation/qvariantanimation.cpp
@@ -54,15 +54,13 @@ QT_BEGIN_NAMESPACE
\class QVariantAnimation
\inmodule QtCore
\ingroup animation
- \brief The QVariantAnimation class provides an abstract base class for animations.
+ \brief The QVariantAnimation class provides a base class for animations.
\since 4.6
This class is part of \l{The Animation Framework}. It serves as a
base class for property and item animations, with functions for
shared functionality.
- QVariantAnimation cannot be used directly as it is an abstract
- class; it has a pure virtual method called updateCurrentValue().
The class performs interpolation over
\l{QVariant}s, but leaves using the interpolated values to its
subclasses. Currently, Qt provides QPropertyAnimation, which
@@ -75,7 +73,7 @@ QT_BEGIN_NAMESPACE
start the animation. QVariantAnimation will interpolate the
property of the target object and emit valueChanged(). To react to
a change in the current value you have to reimplement the
- updateCurrentValue() virtual function.
+ updateCurrentValue() virtual function or connect to said signal.
It is also possible to set values at specified steps situated
between the start and end value. The interpolation will then
diff --git a/src/corelib/doc/src/animation.qdoc b/src/corelib/doc/src/animation.qdoc
index 02eb5a97c6..4e71ed4268 100644
--- a/src/corelib/doc/src/animation.qdoc
+++ b/src/corelib/doc/src/animation.qdoc
@@ -118,11 +118,12 @@
\section1 Animating Qt Properties
- As mentioned in the previous section, the QPropertyAnimation class
- can interpolate over Qt properties. It is this class that should
- be used for animation of values; in fact, its superclass,
- QVariantAnimation, is an abstract class, and cannot be used
- directly.
+ As mentioned in the previous section, the QPropertyAnimation class can
+ interpolate over Qt properties. It is often this class that should be used
+ for animation of values; in fact, its superclass, QVariantAnimation, has an
+ empty implementation of \l{QAbstractAnimation::}{updateCurrentValue()}, and
+ does not change any value unless we change it ourselves on the
+ \l{QVariantAnimation::valueChanged()}{valueChanged signal}.
A major reason we chose to animate Qt properties is that it
presents us with freedom to animate already existing classes in
diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri
index dd846955f6..6a8948822c 100644
--- a/src/corelib/global/global.pri
+++ b/src/corelib/global/global.pri
@@ -28,8 +28,9 @@ SOURCES += \
global/qmalloc.cpp \
global/qnumeric.cpp \
global/qlogging.cpp \
- global/qhooks.cpp \
- global/qversiontagging.cpp
+ global/qhooks.cpp
+
+VERSIONTAGGING_SOURCES = global/qversiontagging.cpp
# qlibraryinfo.cpp includes qconfig.cpp
INCLUDEPATH += $$QT_BUILD_TREE/src/corelib/global
@@ -63,3 +64,21 @@ journald {
syslog {
DEFINES += QT_USE_SYSLOG
}
+
+gcc:ltcg {
+ versiontagging_compiler.commands = $$QMAKE_CXX -c $(CXXFLAGS) $(INCPATH)
+
+ # Disable LTO, as the symbols disappear somehow under GCC
+ versiontagging_compiler.commands += -fno-lto
+
+ versiontagging_compiler.commands += -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_IN}
+ versiontagging_compiler.dependency_type = TYPE_C
+ versiontagging_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)}
+ versiontagging_compiler.input = VERSIONTAGGING_SOURCES
+ versiontagging_compiler.variable_out = OBJECTS
+ versiontagging_compiler.name = compiling[versiontagging] ${QMAKE_FILE_IN}
+ silent: versiontagging_compiler.commands = @echo compiling[versiontagging] ${QMAKE_FILE_IN} && $$versiontagging_compiler.commands
+ QMAKE_EXTRA_COMPILERS += versiontagging_compiler
+} else {
+ SOURCES += $$VERSIONTAGGING_SOURCES
+}
diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h
index 1ebf37d610..c5424be035 100644
--- a/src/corelib/global/qcompilerdetection.h
+++ b/src/corelib/global/qcompilerdetection.h
@@ -748,7 +748,9 @@
# define Q_COMPILER_TEMPLATE_ALIAS
# endif
# if __has_feature(cxx_thread_local)
-# define Q_COMPILER_THREAD_LOCAL
+# if !defined(__FreeBSD__) /* FreeBSD clang fails on __cxa_thread_atexit */
+# define Q_COMPILER_THREAD_LOCAL
+# endif
# endif
# if __has_feature(cxx_user_literals)
# define Q_COMPILER_UDL
@@ -1108,7 +1110,8 @@
# define Q_DECL_NOTHROW Q_DECL_NOEXCEPT
#endif
-#if defined(Q_COMPILER_ALIGNOF) && !defined(Q_ALIGNOF)
+#if defined(Q_COMPILER_ALIGNOF)
+# undef Q_ALIGNOF
# define Q_ALIGNOF(x) alignof(x)
#endif
diff --git a/src/corelib/global/qendian.h b/src/corelib/global/qendian.h
index c5ff82c10a..34bb015a2f 100644
--- a/src/corelib/global/qendian.h
+++ b/src/corelib/global/qendian.h
@@ -49,6 +49,11 @@
QT_BEGIN_NAMESPACE
+#ifdef __has_builtin
+# define QT_HAS_BUILTIN(x) __has_builtin(x)
+#else
+# define QT_HAS_BUILTIN(x) 0
+#endif
/*
* ENDIAN FUNCTIONS
@@ -71,18 +76,29 @@ template <typename T> inline void qbswap(const T src, uchar *dest)
// Used to implement a type-safe and alignment-safe copy operation
// If you want to avoid the memcpy, you must write specializations for these functions
-template <typename T> inline void qToUnaligned(const T src, uchar *dest)
+template <typename T> Q_ALWAYS_INLINE void qToUnaligned(const T src, uchar *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);
- memcpy(dest, &src, size);
+#if QT_HAS_BUILTIN(__builtin_memcpy)
+ __builtin_memcpy
+#else
+ memcpy
+#endif
+ (dest, &src, size);
}
-template <typename T> inline T qFromUnaligned(const uchar *src)
+
+template <typename T> Q_ALWAYS_INLINE T qFromUnaligned(const uchar *src)
{
T dest;
const size_t size = sizeof(T);
- memcpy(&dest, src, size);
+#if QT_HAS_BUILTIN(__builtin_memcpy)
+ __builtin_memcpy
+#else
+ memcpy
+#endif
+ (&dest, src, size);
return dest;
}
diff --git a/src/corelib/global/qendian.qdoc b/src/corelib/global/qendian.qdoc
index 63d924211f..3b22dcec87 100644
--- a/src/corelib/global/qendian.qdoc
+++ b/src/corelib/global/qendian.qdoc
@@ -34,6 +34,29 @@
*/
/*!
+ \internal
+ \fn T qFromUnaligned(const uchar *ptr)
+ \since 5.5
+
+ Loads a \c{T} from address \a ptr, which may be misaligned.
+
+ Use of this function avoids the undefined behavior that the C++ standard
+ otherwise attributes to unaligned loads.
+*/
+
+/*!
+ \internal
+ \fn void qToUnaligned(T t, uchar *ptr)
+ \since 4.5
+
+ Stores \a t to address \a ptr, which may be misaligned.
+
+ Use of this function avoids the undefined behavior that the C++ standard
+ otherwise attributes to unaligned stores.
+*/
+
+
+/*!
\fn T qFromBigEndian(const uchar *src)
\since 4.3
\relates <QtEndian>
diff --git a/src/corelib/global/qhooks.cpp b/src/corelib/global/qhooks.cpp
index 2ec1714cd2..7b9a3db30d 100644
--- a/src/corelib/global/qhooks.cpp
+++ b/src/corelib/global/qhooks.cpp
@@ -67,7 +67,7 @@ quintptr Q_CORE_EXPORT qtHookData[] = {
// The required sizes and offsets are tested in tests/auto/other/toolsupport.
// When this fails and the change was intentional, adjust the test and
// adjust this value here.
- 14
+ 15
};
Q_STATIC_ASSERT(QHooks::LastHookIndex == sizeof(qtHookData) / sizeof(qtHookData[0]));
diff --git a/src/corelib/global/qsystemdetection.h b/src/corelib/global/qsystemdetection.h
index 10f9068d0a..ccf5851d18 100644
--- a/src/corelib/global/qsystemdetection.h
+++ b/src/corelib/global/qsystemdetection.h
@@ -66,6 +66,7 @@
NETBSD - NetBSD
OPENBSD - OpenBSD
BSDI - BSD/OS
+ INTERIX - Interix
IRIX - SGI Irix
OSF - HP Tru64 UNIX
SCO - SCO OpenServer 5
@@ -172,6 +173,9 @@
#elif defined(__bsdi__)
# define Q_OS_BSDI
# define Q_OS_BSD4
+#elif defined(__INTERIX)
+# define Q_OS_INTERIX
+# define Q_OS_BSD4
#elif defined(__sgi)
# define Q_OS_IRIX
#elif defined(__osf__)
diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri
index eb9471b502..ab345e9aae 100644
--- a/src/corelib/io/io.pri
+++ b/src/corelib/io/io.pri
@@ -144,7 +144,6 @@ win32 {
!nacl:mac: {
SOURCES += io/qsettings_mac.cpp
}
- freebsd: LIBS_PRIVATE += -lutil # qlockfile_unix.cpp requires this
mac {
SOURCES += io/qstorageinfo_mac.cpp
OBJECTIVE_SOURCES += io/qstandardpaths_mac.mm
diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp
index 0d9fdb3453..fa919e9f10 100644
--- a/src/corelib/io/qdebug.cpp
+++ b/src/corelib/io/qdebug.cpp
@@ -166,16 +166,15 @@ void QDebug::putUcs4(uint ucs4)
{
maybeQuote('\'');
if (ucs4 < 0x20) {
- stream->ts << hex << "\\x" << ucs4 << reset;
+ stream->ts << "\\x" << hex << ucs4 << reset;
} else if (ucs4 < 0x80) {
stream->ts << char(ucs4);
} else {
- stream->ts << hex << qSetPadChar(QLatin1Char('0'));
if (ucs4 < 0x10000)
- stream->ts << qSetFieldWidth(4) << "\\u";
+ stream->ts << "\\u" << qSetFieldWidth(4);
else
- stream->ts << qSetFieldWidth(8) << "\\U";
- stream->ts << ucs4 << reset;
+ stream->ts << "\\U" << qSetFieldWidth(8);
+ stream->ts << hex << qSetPadChar(QLatin1Char('0')) << ucs4 << reset;
}
maybeQuote('\'');
}
diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp
index 76b56f4699..6366c5120c 100644
--- a/src/corelib/io/qfileinfo.cpp
+++ b/src/corelib/io/qfileinfo.cpp
@@ -820,7 +820,7 @@ QString QFileInfo::completeBaseName() const
}
/*!
- Returns the complete suffix of the file.
+ Returns the complete suffix (extension) of the file.
The complete suffix consists of all characters in the file after
(but not including) the first '.'.
@@ -839,7 +839,7 @@ QString QFileInfo::completeSuffix() const
}
/*!
- Returns the suffix of the file.
+ Returns the suffix (extension) of the file.
The suffix consists of all characters in the file after (but not
including) the last '.'.
diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp
index 1e22252217..55f4bddd17 100644
--- a/src/corelib/io/qfilesystemwatcher.cpp
+++ b/src/corelib/io/qfilesystemwatcher.cpp
@@ -58,7 +58,7 @@
# include "qfilesystemwatcher_win_p.h"
#elif defined(USE_INOTIFY)
# include "qfilesystemwatcher_inotify_p.h"
-#elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) || defined(QT_PLATFORM_UIKIT)
+#elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) || defined(Q_OS_OPENBSD) || defined(QT_PLATFORM_UIKIT)
# include "qfilesystemwatcher_kqueue_p.h"
#elif defined(Q_OS_OSX)
# include "qfilesystemwatcher_fsevents_p.h"
@@ -74,7 +74,7 @@ QFileSystemWatcherEngine *QFileSystemWatcherPrivate::createNativeEngine(QObject
// there is a chance that inotify may fail on Linux pre-2.6.13 (August
// 2005), so we can't just new inotify directly.
return QInotifyFileSystemWatcherEngine::create(parent);
-#elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) || defined(QT_PLATFORM_UIKIT)
+#elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) || defined(Q_OS_OPENBSD) || defined(QT_PLATFORM_UIKIT)
return QKqueueFileSystemWatcherEngine::create(parent);
#elif defined(Q_OS_OSX)
return QFseventsFileSystemWatcherEngine::create(parent);
diff --git a/src/corelib/io/qfilesystemwatcher_kqueue.cpp b/src/corelib/io/qfilesystemwatcher_kqueue.cpp
index 264973d556..4f6c83ebcf 100644
--- a/src/corelib/io/qfilesystemwatcher_kqueue.cpp
+++ b/src/corelib/io/qfilesystemwatcher_kqueue.cpp
@@ -172,7 +172,6 @@ QStringList QKqueueFileSystemWatcherEngine::removePaths(const QStringList &paths
QStringList *files,
QStringList *directories)
{
- bool isEmpty;
QStringList p = paths;
if (pathToID.isEmpty())
return p;
@@ -193,7 +192,6 @@ QStringList QKqueueFileSystemWatcherEngine::removePaths(const QStringList &paths
else
files->removeAll(path);
}
- isEmpty = pathToID.isEmpty();
return p;
}
diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp
index ba59ea8341..79141d1e8f 100644
--- a/src/corelib/io/qlockfile_unix.cpp
+++ b/src/corelib/io/qlockfile_unix.cpp
@@ -71,14 +71,12 @@
#elif defined(Q_OS_HAIKU)
# include <kernel/OS.h>
#elif defined(Q_OS_BSD4) && !defined(QT_PLATFORM_UIKIT)
+# if !defined(Q_OS_NETBSD)
# include <sys/user.h>
-# if defined(__GLIBC__) && defined(__FreeBSD_kernel__)
+# endif
# include <sys/cdefs.h>
# include <sys/param.h>
# include <sys/sysctl.h>
-# else
-# include <libutil.h>
-# endif
#endif
QT_BEGIN_NAMESPACE
@@ -286,30 +284,33 @@ QString QLockFilePrivate::processNameByPid(qint64 pid)
return QString();
return QFile::decodeName(info.name);
#elif defined(Q_OS_BSD4) && !defined(QT_PLATFORM_UIKIT)
-# if defined(__GLIBC__) && defined(__FreeBSD_kernel__)
- int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid };
- size_t len = 0;
- if (sysctl(mib, 4, NULL, &len, NULL, 0) < 0)
- return QString();
- kinfo_proc *proc = static_cast<kinfo_proc *>(malloc(len));
+# if defined(Q_OS_NETBSD)
+ struct kinfo_proc2 kp;
+ int mib[6] = { CTL_KERN, KERN_PROC2, KERN_PROC_PID, (int)pid, sizeof(struct kinfo_proc2), 1 };
+# elif defined(Q_OS_OPENBSD)
+ struct kinfo_proc kp;
+ int mib[6] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, (int)pid, sizeof(struct kinfo_proc), 1 };
# else
- kinfo_proc *proc = kinfo_getproc(pid);
+ struct kinfo_proc kp;
+ int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, (int)pid };
# endif
- if (!proc)
+ size_t len = sizeof(kp);
+ u_int mib_len = sizeof(mib)/sizeof(u_int);
+
+ if (sysctl(mib, mib_len, &kp, &len, NULL, 0) < 0)
return QString();
-# if defined(__GLIBC__) && defined(__FreeBSD_kernel__)
- if (sysctl(mib, 4, proc, &len, NULL, 0) < 0) {
- free(proc);
+
+# if defined(Q_OS_OPENBSD) || defined(Q_OS_NETBSD)
+ if (kp.p_pid != pid)
return QString();
- }
- if (proc->ki_pid != pid) {
- free(proc);
+ QString name = QFile::decodeName(kp.p_comm);
+# else
+ if (kp.ki_pid != pid)
return QString();
- }
+ QString name = QFile::decodeName(kp.ki_comm);
# endif
- QString name = QFile::decodeName(proc->ki_comm);
- free(proc);
return name;
+
#else
Q_UNUSED(pid);
return QString();
diff --git a/src/corelib/io/qlockfile_win.cpp b/src/corelib/io/qlockfile_win.cpp
index ba4a091965..baaff8da17 100644
--- a/src/corelib/io/qlockfile_win.cpp
+++ b/src/corelib/io/qlockfile_win.cpp
@@ -143,9 +143,11 @@ bool QLockFilePrivate::isApparentlyStale() const
if (!procHandle)
return true;
// We got a handle but check if process is still alive
- DWORD dwR = ::WaitForSingleObject(procHandle, 0);
+ DWORD exitCode = 0;
+ if (!::GetExitCodeProcess(procHandle, &exitCode))
+ exitCode = 0;
::CloseHandle(procHandle);
- if (dwR == WAIT_TIMEOUT)
+ if (exitCode != STILL_ACTIVE)
return true;
const QString processName = processNameByPid(pid);
if (!processName.isEmpty() && processName != appname)
diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp
index 227241b208..ebafd6b524 100644
--- a/src/corelib/io/qprocess.cpp
+++ b/src/corelib/io/qprocess.cpp
@@ -2087,10 +2087,7 @@ void QProcess::start(const QString &program, const QStringList &arguments, OpenM
return;
}
if (program.isEmpty()) {
- Q_D(QProcess);
- d->processError = QProcess::FailedToStart;
- setErrorString(tr("No program defined"));
- emit error(d->processError);
+ d->setErrorAndEmit(QProcess::FailedToStart, tr("No program defined"));
return;
}
@@ -2117,10 +2114,7 @@ void QProcess::start(OpenMode mode)
return;
}
if (d->program.isEmpty()) {
- Q_D(QProcess);
- d->processError = QProcess::FailedToStart;
- setErrorString(tr("No program defined"));
- emit error(d->processError);
+ d->setErrorAndEmit(QProcess::FailedToStart, tr("No program defined"));
return;
}
diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp
index 3a9f74bf59..0daf041954 100644
--- a/src/corelib/io/qstorageinfo_unix.cpp
+++ b/src/corelib/io/qstorageinfo_unix.cpp
@@ -84,7 +84,7 @@
# if !defined(ST_RDONLY)
# define ST_RDONLY MNT_RDONLY
# endif
-# if !defined(_STATFS_F_FLAGS)
+# if !defined(_STATFS_F_FLAGS) && !defined(Q_OS_NETBSD)
# define _STATFS_F_FLAGS 1
# endif
#elif defined(Q_OS_ANDROID)
diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp
index 64c9692e23..3ab2c70c75 100644
--- a/src/corelib/io/qwindowspipewriter.cpp
+++ b/src/corelib/io/qwindowspipewriter.cpp
@@ -205,6 +205,8 @@ bool QWindowsPipeWriter::write(const QByteArray &ba)
void QWindowsPipeWriter::stop()
{
stopped = true;
+ bytesWrittenPending = false;
+ pendingBytesWrittenValue = 0;
if (writeSequenceStarted) {
if (!CancelIoEx(handle, &overlapped)) {
const DWORD dwError = GetLastError();
diff --git a/src/corelib/json/qjson_p.h b/src/corelib/json/qjson_p.h
index d16b6e5b00..f2fcb767d5 100644
--- a/src/corelib/json/qjson_p.h
+++ b/src/corelib/json/qjson_p.h
@@ -410,7 +410,7 @@ public:
// pack with itself, we'll discard the high part anyway
chunk = _mm_packus_epi16(chunk, chunk);
// unaligned 64-bit store
- qUnalignedStore(l + i, _mm_cvtsi128_si64(chunk));
+ qToUnaligned(_mm_cvtsi128_si64(chunk), l + i);
i += 8;
}
# endif
@@ -684,6 +684,8 @@ public:
bool operator >=(const Entry &other) const;
};
+inline bool operator!=(const Entry &lhs, const Entry &rhs) { return !(lhs == rhs); }
+
inline bool Entry::operator >=(const QString &key) const
{
if (value.latinKey)
diff --git a/src/corelib/json/qjsonobject.cpp b/src/corelib/json/qjsonobject.cpp
index b5b6f36bc6..fb651f0f24 100644
--- a/src/corelib/json/qjsonobject.cpp
+++ b/src/corelib/json/qjsonobject.cpp
@@ -599,8 +599,8 @@ bool QJsonObject::operator==(const QJsonObject &other) const
for (uint i = 0; i < o->length; ++i) {
QJsonPrivate::Entry *e = o->entryAt(i);
- QJsonValue v(d, o, e->value);
- if (other.value(e->key()) != v)
+ QJsonPrivate::Entry *oe = other.o->entryAt(i);
+ if (*e != *oe || QJsonValue(d, o, e->value) != QJsonValue(other.d, other.o, oe->value))
return false;
}
diff --git a/src/corelib/json/qjsonvalue.cpp b/src/corelib/json/qjsonvalue.cpp
index b21f59ae35..718dfa43b3 100644
--- a/src/corelib/json/qjsonvalue.cpp
+++ b/src/corelib/json/qjsonvalue.cpp
@@ -275,25 +275,11 @@ QJsonValue::QJsonValue(const QJsonValue &other)
*/
QJsonValue &QJsonValue::operator =(const QJsonValue &other)
{
- if (t == String && stringData && !stringData->ref.deref())
- free(stringData);
-
- t = other.t;
- dbl = other.dbl;
-
- if (d != other.d) {
-
- if (d && !d->ref.deref())
- delete d;
- d = other.d;
- if (d)
- d->ref.ref();
-
- }
-
- if (t == String && stringData)
- stringData->ref.ref();
-
+ QJsonValue copy(other);
+ // swap(copy);
+ qSwap(dbl, copy.dbl);
+ qSwap(d, copy.d);
+ qSwap(t, copy.t);
return *this;
}
diff --git a/src/corelib/kernel/qcore_unix.cpp b/src/corelib/kernel/qcore_unix.cpp
index 93af957d95..2042964427 100644
--- a/src/corelib/kernel/qcore_unix.cpp
+++ b/src/corelib/kernel/qcore_unix.cpp
@@ -41,16 +41,6 @@
#include "qcore_unix_p.h"
#include "qelapsedtimer.h"
-#ifdef Q_OS_NACL
-#elif !defined (Q_OS_VXWORKS)
-# if !defined(Q_OS_HPUX) || defined(__ia64)
-# include <sys/select.h>
-# endif
-# include <sys/time.h>
-#else
-# include <selectLib.h>
-#endif
-
#include <stdlib.h>
#ifdef Q_OS_MAC
diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h
index b08571223f..6ed316254b 100644
--- a/src/corelib/kernel/qcore_unix_p.h
+++ b/src/corelib/kernel/qcore_unix_p.h
@@ -65,6 +65,16 @@
#include <sys/stat.h>
#include <unistd.h>
+#ifdef Q_OS_NACL
+#elif !defined (Q_OS_VXWORKS)
+# if !defined(Q_OS_HPUX) || defined(__ia64)
+# include <sys/select.h>
+# endif
+# include <sys/time.h>
+#else
+# include <selectLib.h>
+#endif
+
#include <sys/wait.h>
#include <errno.h>
#include <fcntl.h>
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 9b421d6a78..ffb50ddac3 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -4699,7 +4699,7 @@ QMetaObject::Connection QObjectPrivate::connectImpl(const QObject *sender, int s
QOrderedMutexLocker locker(signalSlotLock(sender),
signalSlotLock(receiver));
- if (type & Qt::UniqueConnection) {
+ if (type & Qt::UniqueConnection && slot) {
QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists;
if (connectionLists && connectionLists->count() > signal_index) {
const QObjectPrivate::Connection *c2 =
diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h
index 87d006bdc6..3cec9802dc 100644
--- a/src/corelib/kernel/qobject.h
+++ b/src/corelib/kernel/qobject.h
@@ -302,7 +302,6 @@ public:
connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, const QObject *context, Func2 slot,
Qt::ConnectionType type = Qt::AutoConnection)
{
-#if defined (Q_COMPILER_VARIADIC_TEMPLATES)
typedef QtPrivate::FunctionPointer<Func1> SignalType;
const int FunctorArgumentCount = QtPrivate::ComputeFunctorArgumentCount<Func2 , typename SignalType::Arguments>::Value;
@@ -310,28 +309,6 @@ public:
"Signal and slot arguments are not compatible.");
const int SlotArgumentCount = (FunctorArgumentCount >= 0) ? FunctorArgumentCount : 0;
typedef typename QtPrivate::FunctorReturnType<Func2, typename QtPrivate::List_Left<typename SignalType::Arguments, SlotArgumentCount>::Value>::Value SlotReturnType;
-#else
- // Without variadic template, we don't detect the best overload of operator(). We just
- // assume there is only one simple operator() and connect to &Func2::operator()
-
- /* If you get an error such as:
- couldn't deduce template parameter 'Func2Operator'
- or
- cannot resolve address of overloaded function
- It means the functor does not have a single operator().
- Functors with overloaded or templated operator() are only supported if the compiler supports
- C++11 variadic templates
- */
- typedef QtPrivate::FunctionPointer<decltype(&Func2::operator())> SlotType ;
- typedef QtPrivate::FunctionPointer<Func1> SignalType;
- typedef typename SlotType::ReturnType SlotReturnType;
- const int SlotArgumentCount = SlotType::ArgumentCount;
-
- Q_STATIC_ASSERT_X(int(SignalType::ArgumentCount) >= SlotArgumentCount,
- "The slot requires more arguments than the signal provides.");
- Q_STATIC_ASSERT_X((QtPrivate::CheckCompatibleArguments<typename SignalType::Arguments, typename SlotType::Arguments>::value),
- "Signal and slot arguments are not compatible.");
-#endif
Q_STATIC_ASSERT_X((QtPrivate::AreArgumentsCompatible<SlotReturnType, typename SignalType::ReturnType>::value),
"Return type of the slot is not compatible with the return type of the signal.");
@@ -446,8 +423,7 @@ protected:
QScopedPointer<QObjectData> d_ptr;
static const QMetaObject staticQtMetaObject;
- friend inline const QMetaObject *qt_getQtMetaObject() Q_DECL_NOEXCEPT
- { return &staticQtMetaObject; }
+ friend inline const QMetaObject *qt_getQtMetaObject() Q_DECL_NOEXCEPT;
friend struct QMetaObject;
friend struct QMetaObjectPrivate;
@@ -478,6 +454,9 @@ inline QMetaObject::Connection QObject::connect(const QObject *asender, const ch
const char *amember, Qt::ConnectionType atype) const
{ return connect(asender, asignal, this, amember, atype); }
+inline const QMetaObject *qt_getQtMetaObject() Q_DECL_NOEXCEPT
+{ return &QObject::staticQtMetaObject; }
+
#ifndef QT_NO_USERDATA
class Q_CORE_EXPORT QObjectUserData {
public:
diff --git a/src/corelib/kernel/qobject_impl.h b/src/corelib/kernel/qobject_impl.h
index b4091a4f1c..d7ae63a98c 100644
--- a/src/corelib/kernel/qobject_impl.h
+++ b/src/corelib/kernel/qobject_impl.h
@@ -62,34 +62,6 @@ namespace QtPrivate {
If one of the type is not declared, the function return 0 and the signal
cannot be used in queued connection.
*/
-#ifndef Q_COMPILER_VARIADIC_TEMPLATES
- template <typename ArgList> struct TypesAreDeclaredMetaType { enum { Value = false }; };
- template <> struct TypesAreDeclaredMetaType<void> { enum { Value = true }; };
- template <typename Arg, typename Tail> struct TypesAreDeclaredMetaType<List<Arg, Tail> > { enum { Value = QMetaTypeId2<Arg>::Defined && TypesAreDeclaredMetaType<Tail>::Value }; };
-
- template <typename ArgList, bool Declared = TypesAreDeclaredMetaType<ArgList>::Value > struct ConnectionTypes
- { static const int *types() { return 0; } };
- template <> struct ConnectionTypes<void, true>
- { static const int *types() { static const int t[1] = { 0 }; return t; } };
- template <typename Arg1> struct ConnectionTypes<List<Arg1, void>, true>
- { static const int *types() { static const int t[2] = { QtPrivate::QMetaTypeIdHelper<Arg1>::qt_metatype_id(), 0 }; return t; } };
- template <typename Arg1, typename Arg2> struct ConnectionTypes<List<Arg1, List<Arg2, void> >, true>
- { static const int *types() { static const int t[3] = { QtPrivate::QMetaTypeIdHelper<Arg1>::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper<Arg2>::qt_metatype_id(), 0 }; return t; } };
- template <typename Arg1, typename Arg2, typename Arg3> struct ConnectionTypes<List<Arg1, List<Arg2, List<Arg3, void> > >, true>
- { static const int *types() { static const int t[4] = { QtPrivate::QMetaTypeIdHelper<Arg1>::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper<Arg2>::qt_metatype_id(),
- QtPrivate::QMetaTypeIdHelper<Arg3>::qt_metatype_id(), 0 }; return t; } };
- template <typename Arg1, typename Arg2, typename Arg3, typename Arg4> struct ConnectionTypes<List<Arg1, List<Arg2, List<Arg3, List<Arg4, void> > > >, true>
- { static const int *types() { static const int t[5] = { QtPrivate::QMetaTypeIdHelper<Arg1>::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper<Arg2>::qt_metatype_id(),
- QtPrivate::QMetaTypeIdHelper<Arg3>::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper<Arg4>::qt_metatype_id(), 0 }; return t; } };
- template <typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> struct ConnectionTypes<List<Arg1, List<Arg2, List<Arg3, List<Arg4, List<Arg5, void> > > > >, true>
- { static const int *types() { static const int t[6] = { QtPrivate::QMetaTypeIdHelper<Arg1>::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper<Arg2>::qt_metatype_id(),
- QtPrivate::QMetaTypeIdHelper<Arg3>::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper<Arg4>::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper<Arg5>::qt_metatype_id(), 0 }; return t; } };
- template <typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6>
- struct ConnectionTypes<List<Arg1, List<Arg2, List<Arg3, List<Arg4, List<Arg5, List<Arg6, void> > > > > >, true>
- { static const int *types() { static const int t[7] = { QtPrivate::QMetaTypeIdHelper<Arg1>::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper<Arg2>::qt_metatype_id(),
- QtPrivate::QMetaTypeIdHelper<Arg3>::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper<Arg4>::qt_metatype_id(), QtPrivate::QMetaTypeIdHelper<Arg5>::qt_metatype_id(),
- QtPrivate::QMetaTypeIdHelper<Arg6>::qt_metatype_id(), 0 }; return t; } };
-#else
template <typename ArgList> struct TypesAreDeclaredMetaType { enum { Value = false }; };
template <> struct TypesAreDeclaredMetaType<List<>> { enum { Value = true }; };
template <typename Arg, typename... Tail> struct TypesAreDeclaredMetaType<List<Arg, Tail...> >
@@ -101,7 +73,6 @@ namespace QtPrivate {
{ static const int *types() { return Q_NULLPTR; } };
template <typename... Args> struct ConnectionTypes<List<Args...>, true>
{ static const int *types() { static const int t[sizeof...(Args) + 1] = { (QtPrivate::QMetaTypeIdHelper<Args>::qt_metatype_id())..., 0 }; return t; } };
-#endif
// internal base class (interface) containing functions required to call a slot managed by a pointer to function.
class QSlotObjectBase {
diff --git a/src/corelib/kernel/qobjectdefs_impl.h b/src/corelib/kernel/qobjectdefs_impl.h
index 6ef83a6eb5..5eae70ecc5 100644
--- a/src/corelib/kernel/qobjectdefs_impl.h
+++ b/src/corelib/kernel/qobjectdefs_impl.h
@@ -65,11 +65,6 @@ namespace QtPrivate {
List_Left<L,N> take a list and a number as a parameter and returns (via the Value typedef,
the list composed of the first N element of the list
*/
-#ifndef Q_COMPILER_VARIADIC_TEMPLATES
- template <typename Head, typename Tail> struct List { typedef Head Car; typedef Tail Cdr; };
- template <typename L, int N> struct List_Left { typedef List<typename L::Car, typename List_Left<typename L::Cdr, N - 1>::Value > Value; };
- template <typename L> struct List_Left<L,0> { typedef void Value; };
-#else
// With variadic template, lists are represented using a variadic template argument instead of the lisp way
template <typename...> struct List {};
template <typename Head, typename... Tail> struct List<Head, Tail...> { typedef Head Car; typedef List<Tail...> Cdr; };
@@ -79,7 +74,6 @@ namespace QtPrivate {
typedef typename List_Append<List<typename L::Car>,typename List_Left<typename L::Cdr, N - 1>::Value>::Value Value;
};
template <typename L> struct List_Left<L, 0> { typedef List<> Value; };
-#endif
// List_Select<L,N> returns (via typedef Value) the Nth element of the list L
template <typename L, int N> struct List_Select { typedef typename List_Select<typename L::Cdr, N - 1>::Value Value; };
template <typename L> struct List_Select<L,0> { typedef typename L::Car Value; };
@@ -100,13 +94,11 @@ namespace QtPrivate {
if (container.data)
*reinterpret_cast<U*>(container.data) = value;
}
-#ifdef Q_COMPILER_RVALUE_REFS
template<typename T, typename U>
void operator,(T &&value, const ApplyReturnValue<U> &container) {
if (container.data)
*reinterpret_cast<U*>(container.data) = value;
}
-#endif
template<typename T>
void operator,(T, const ApplyReturnValue<void> &) {}
@@ -127,364 +119,6 @@ namespace QtPrivate {
The Functor<Func,N> struct is the helper to call a functor of N argument.
its call function is the same as the FunctionPointer::call function.
*/
-#ifndef Q_COMPILER_VARIADIC_TEMPLATES
- template<typename Func> struct FunctionPointer { enum {ArgumentCount = -1, IsPointerToMemberFunction = false}; };
- //Pointers to member functions
- template<class Obj, typename Ret> struct FunctionPointer<Ret (Obj::*) ()>
- {
- typedef Obj Object;
- typedef void Arguments;
- typedef Ret ReturnType;
- typedef Ret (Obj::*Function) ();
- enum {ArgumentCount = 0, IsPointerToMemberFunction = true};
- template <typename Args, typename R>
- static void call(Function f, Obj *o, void **arg) { (o->*f)(), ApplyReturnValue<R>(arg[0]); }
- };
- template<class Obj, typename Ret, typename Arg1> struct FunctionPointer<Ret (Obj::*) (Arg1)>
- {
- typedef Obj Object;
- typedef List<Arg1, void> Arguments;
- typedef Ret ReturnType;
- typedef Ret (Obj::*Function) (Arg1);
- enum {ArgumentCount = 1, IsPointerToMemberFunction = true};
- template <typename Args, typename R>
- static void call(Function f, Obj *o, void **arg) {
- (o->*f)((*reinterpret_cast<typename RemoveRef<typename Args::Car>::Type *>(arg[1]))), ApplyReturnValue<R>(arg[0]);
- }
- };
- template<class Obj, typename Ret, typename Arg1, typename Arg2> struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2)>
- {
- typedef Obj Object;
- typedef List<Arg1, List<Arg2, void> > Arguments;
- typedef Ret ReturnType;
- typedef Ret (Obj::*Function) (Arg1, Arg2);
- enum {ArgumentCount = 2, IsPointerToMemberFunction = true};
- template <typename Args, typename R>
- static void call(Function f, Obj *o, void **arg) {
- (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2])), ApplyReturnValue<R>(arg[0]);
- }
- };
- template<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3> struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3)>
- {
- typedef Obj Object;
- typedef List<Arg1, List<Arg2, List<Arg3, void> > > Arguments;
- typedef Ret ReturnType;
- typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3);
- enum {ArgumentCount = 3, IsPointerToMemberFunction = true};
- template <typename Args, typename R>
- static void call(Function f, Obj *o, void **arg) {
- (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3])), ApplyReturnValue<R>(arg[0]);
- }
- };
- template<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4> struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3, Arg4)>
- {
- typedef Obj Object;
- typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, void> > > > Arguments;
- typedef Ret ReturnType;
- typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4);
- enum {ArgumentCount = 4, IsPointerToMemberFunction = true};
- template <typename Args, typename R>
- static void call(Function f, Obj *o, void **arg) {
- (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4])), ApplyReturnValue<R>(arg[0]);
- }
- };
- template<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3, Arg4, Arg5)>
- {
- typedef Obj Object;
- typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, List<Arg5, void> > > > > Arguments;
- typedef Ret ReturnType;
- typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5);
- enum {ArgumentCount = 5, IsPointerToMemberFunction = true};
- template <typename Args, typename R>
- static void call(Function f, Obj *o, void **arg) {
- (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5])), ApplyReturnValue<R>(arg[0]);
- }
- };
- template<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6>
- struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)>
- {
- typedef Obj Object;
- typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, List<Arg5, List<Arg6, void> > > > > > Arguments;
- typedef Ret ReturnType;
- typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6);
- enum {ArgumentCount = 6, IsPointerToMemberFunction = true};
- template <typename Args, typename R>
- static void call(Function f, Obj *o, void **arg) {
- (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 5>::Value>::Type *>(arg[6])), ApplyReturnValue<R>(arg[0]);
- }
- };
-
- //Pointers to const member functions
- template<class Obj, typename Ret> struct FunctionPointer<Ret (Obj::*) () const>
- {
- typedef Obj Object;
- typedef void Arguments;
- typedef Ret ReturnType;
- typedef Ret (Obj::*Function) () const;
- enum {ArgumentCount = 0, IsPointerToMemberFunction = true};
- template <typename Args, typename R>
- static void call(Function f, Obj *o, void **arg) { (o->*f)(), ApplyReturnValue<R>(arg[0]); }
- };
- template<class Obj, typename Ret, typename Arg1> struct FunctionPointer<Ret (Obj::*) (Arg1) const>
- {
- typedef Obj Object;
- typedef List<Arg1, void> Arguments;
- typedef Ret ReturnType;
- typedef Ret (Obj::*Function) (Arg1) const;
- enum {ArgumentCount = 1, IsPointerToMemberFunction = true};
- template <typename Args, typename R>
- static void call(Function f, Obj *o, void **arg) {
- (o->*f)((*reinterpret_cast<typename RemoveRef<typename Args::Car>::Type *>(arg[1]))), ApplyReturnValue<R>(arg[0]);
- }
- };
- template<class Obj, typename Ret, typename Arg1, typename Arg2> struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2) const>
- {
- typedef Obj Object;
- typedef List<Arg1, List<Arg2, void> > Arguments;
- typedef Ret ReturnType;
- typedef Ret (Obj::*Function) (Arg1, Arg2) const;
- enum {ArgumentCount = 2, IsPointerToMemberFunction = true};
- template <typename Args, typename R>
- static void call(Function f, Obj *o, void **arg) {
- (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2])), ApplyReturnValue<R>(arg[0]);
- }
- };
- template<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3> struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3) const>
- {
- typedef Obj Object;
- typedef List<Arg1, List<Arg2, List<Arg3, void> > > Arguments;
- typedef Ret ReturnType;
- typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3) const;
- enum {ArgumentCount = 3, IsPointerToMemberFunction = true};
- template <typename Args, typename R>
- static void call(Function f, Obj *o, void **arg) {
- (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3])), ApplyReturnValue<R>(arg[0]);
- }
- };
- template<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4> struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3, Arg4) const>
- {
- typedef Obj Object;
- typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, void> > > > Arguments;
- typedef Ret ReturnType;
- typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4) const;
- enum {ArgumentCount = 4, IsPointerToMemberFunction = true};
- template <typename Args, typename R>
- static void call(Function f, Obj *o, void **arg) {
- (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4])), ApplyReturnValue<R>(arg[0]);
- }
- };
- template<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3, Arg4, Arg5) const>
- {
- typedef Obj Object;
- typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, List<Arg5, void> > > > > Arguments;
- typedef Ret ReturnType;
- typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5) const;
- enum {ArgumentCount = 5, IsPointerToMemberFunction = true};
- template <typename Args, typename R>
- static void call(Function f, Obj *o, void **arg) {
- (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5])), ApplyReturnValue<R>(arg[0]);
- }
- };
- template<class Obj, typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6>
- struct FunctionPointer<Ret (Obj::*) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) const>
- {
- typedef Obj Object;
- typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, List<Arg5, List<Arg6, void> > > > > > Arguments;
- typedef Ret ReturnType;
- typedef Ret (Obj::*Function) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) const;
- enum {ArgumentCount = 6, IsPointerToMemberFunction = true};
- template <typename Args, typename R>
- static void call(Function f, Obj *o, void **arg) {
- (o->*f)( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 5>::Value>::Type *>(arg[6])), ApplyReturnValue<R>(arg[0]);
- }
- };
-
- //Static functions
- template<typename Ret> struct FunctionPointer<Ret (*) ()>
- {
- typedef void Arguments;
- typedef Ret (*Function) ();
- typedef Ret ReturnType;
- enum {ArgumentCount = 0, IsPointerToMemberFunction = false};
- template <typename Args, typename R>
- static void call(Function f, void *, void **arg) { f(), ApplyReturnValue<R>(arg[0]); }
- };
- template<typename Ret, typename Arg1> struct FunctionPointer<Ret (*) (Arg1)>
- {
- typedef List<Arg1, void> Arguments;
- typedef Ret ReturnType;
- typedef Ret (*Function) (Arg1);
- enum {ArgumentCount = 1, IsPointerToMemberFunction = false};
- template <typename Args, typename R>
- static void call(Function f, void *, void **arg)
- { f(*reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1])), ApplyReturnValue<R>(arg[0]); }
- };
- template<typename Ret, typename Arg1, typename Arg2> struct FunctionPointer<Ret (*) (Arg1, Arg2)>
- {
- typedef List<Arg1, List<Arg2, void> > Arguments;
- typedef Ret ReturnType;
- typedef Ret (*Function) (Arg1, Arg2);
- enum {ArgumentCount = 2, IsPointerToMemberFunction = false};
- template <typename Args, typename R>
- static void call(Function f, void *, void **arg) {
- f(*reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2])), ApplyReturnValue<R>(arg[0]); }
- };
- template<typename Ret, typename Arg1, typename Arg2, typename Arg3> struct FunctionPointer<Ret (*) (Arg1, Arg2, Arg3)>
- {
- typedef List<Arg1, List<Arg2, List<Arg3, void> > > Arguments;
- typedef Ret ReturnType;
- typedef Ret (*Function) (Arg1, Arg2, Arg3);
- enum {ArgumentCount = 3, IsPointerToMemberFunction = false};
- template <typename Args, typename R>
- static void call(Function f, void *, void **arg) {
- f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3])), ApplyReturnValue<R>(arg[0]);
- }
- };
- template<typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4> struct FunctionPointer<Ret (*) (Arg1, Arg2, Arg3, Arg4)>
- {
- typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, void> > > > Arguments;
- typedef Ret ReturnType;
- typedef Ret (*Function) (Arg1, Arg2, Arg3, Arg4);
- enum {ArgumentCount = 4, IsPointerToMemberFunction = false};
- template <typename Args, typename R>
- static void call(Function f, void *, void **arg) {
- f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4])), ApplyReturnValue<R>(arg[0]);
- }
- };
- template<typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> struct FunctionPointer<Ret (*) (Arg1, Arg2, Arg3, Arg4, Arg5)>
- {
- typedef List<Arg1, List<Arg2, List<Arg3,
- List<Arg4, List<Arg5, void > > > > > Arguments;
- typedef Ret ReturnType;
- typedef Ret (*Function) (Arg1, Arg2, Arg3, Arg4, Arg5);
- enum {ArgumentCount = 5, IsPointerToMemberFunction = false};
- template <typename Args, typename R>
- static void call(Function f, void *, void **arg) {
- f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5])), ApplyReturnValue<R>(arg[0]);
- }
- };
- template<typename Ret, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5, typename Arg6> struct FunctionPointer<Ret (*) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6)>
- {
- typedef List<Arg1, List<Arg2, List<Arg3, List<Arg4, List<Arg5, List<Arg6, void> > > > > > Arguments;
- typedef Ret ReturnType;
- typedef Ret (*Function) (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6);
- enum {ArgumentCount = 6, IsPointerToMemberFunction = false};
- template <typename Args, typename R>
- static void call(Function f, void *, void **arg) {
- f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 5>::Value>::Type *>(arg[6])), ApplyReturnValue<R>(arg[0]);
- }
- };
-
- //Functors
- template<typename F, int N> struct Functor;
- template<typename Function> struct Functor<Function, 0>
- {
- template <typename Args, typename R>
- static void call(Function &f, void *, void **arg) { f(), ApplyReturnValue<R>(arg[0]); }
- };
- template<typename Function> struct Functor<Function, 1>
- {
- template <typename Args, typename R>
- static void call(Function &f, void *, void **arg) {
- f(*reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1])), ApplyReturnValue<R>(arg[0]);
- }
- };
- template<typename Function> struct Functor<Function, 2>
- {
- template <typename Args, typename R>
- static void call(Function &f, void *, void **arg) {
- f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2])), ApplyReturnValue<R>(arg[0]);
- }
- };
- template<typename Function> struct Functor<Function, 3>
- {
- template <typename Args, typename R>
- static void call(Function &f, void *, void **arg) {
- f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3])), ApplyReturnValue<R>(arg[0]);
- }
- };
- template<typename Function> struct Functor<Function, 4>
- {
- template <typename Args, typename R>
- static void call(Function &f, void *, void **arg) {
- f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4])), ApplyReturnValue<R>(arg[0]);
- }
- };
- template<typename Function> struct Functor<Function, 5>
- {
- template <typename Args, typename R>
- static void call(Function &f, void *, void **arg) {
- f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5])), ApplyReturnValue<R>(arg[0]);
- }
- };
- template<typename Function> struct Functor<Function, 6>
- {
- template <typename Args, typename R>
- static void call(Function &f, void *, void **arg) {
- f( *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 0>::Value>::Type *>(arg[1]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 1>::Value>::Type *>(arg[2]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 2>::Value>::Type *>(arg[3]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 3>::Value>::Type *>(arg[4]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 4>::Value>::Type *>(arg[5]),
- *reinterpret_cast<typename RemoveRef<typename List_Select<Args, 5>::Value>::Type *>(arg[6])), ApplyReturnValue<R>(arg[0]);
- }
- };
-#else
template <int...> struct IndexesList {};
template <typename IndexList, int Right> struct IndexesAppend;
template <int... Left, int Right> struct IndexesAppend<IndexesList<Left...>, Right>
@@ -558,7 +192,6 @@ namespace QtPrivate {
FunctorCall<typename Indexes<N>::Value, SignalArgs, R, Function>::call(f, arg);
}
};
-#endif
/*
Logic that check if the arguments of the slot matches the argument of the signal.
@@ -578,16 +211,6 @@ namespace QtPrivate {
template<typename A> struct AreArgumentsCompatible<A, void> { enum { value = true }; };
template<> struct AreArgumentsCompatible<void, void> { enum { value = true }; };
-#ifndef Q_COMPILER_VARIADIC_TEMPLATES
- template <typename List1, typename List2> struct CheckCompatibleArguments { enum { value = false }; };
- template <> struct CheckCompatibleArguments<void, void> { enum { value = true }; };
- template <typename List1> struct CheckCompatibleArguments<List1, void> { enum { value = true }; };
- template <typename Arg1, typename Arg2, typename Tail1, typename Tail2> struct CheckCompatibleArguments<List<Arg1, Tail1>, List<Arg2, Tail2> >
- {
- enum { value = AreArgumentsCompatible<typename RemoveConstRef<Arg1>::Type, typename RemoveConstRef<Arg2>::Type>::value
- && CheckCompatibleArguments<Tail1, Tail2>::value };
- };
-#else
template <typename List1, typename List2> struct CheckCompatibleArguments { enum { value = false }; };
template <> struct CheckCompatibleArguments<List<>, List<>> { enum { value = true }; };
template <typename List1> struct CheckCompatibleArguments<List1, List<>> { enum { value = true }; };
@@ -597,9 +220,7 @@ namespace QtPrivate {
enum { value = AreArgumentsCompatible<typename RemoveConstRef<Arg1>::Type, typename RemoveConstRef<Arg2>::Type>::value
&& CheckCompatibleArguments<List<Tail1...>, List<Tail2...>>::value };
};
-#endif
-#if defined(Q_COMPILER_VARIADIC_TEMPLATES)
/*
Find the maximum number of arguments a functor object can take and be still compatible with
the arguments from the signal.
@@ -631,8 +252,6 @@ namespace QtPrivate {
template <typename D> static D dummy();
typedef decltype(dummy<Functor>().operator()((dummy<ArgList>())...)) Value;
};
-#endif
-
}
QT_END_NAMESPACE
diff --git a/src/corelib/mimetypes/qmimemagicrule.cpp b/src/corelib/mimetypes/qmimemagicrule.cpp
index 0db3407b7b..8461bf7130 100644
--- a/src/corelib/mimetypes/qmimemagicrule.cpp
+++ b/src/corelib/mimetypes/qmimemagicrule.cpp
@@ -48,7 +48,6 @@
#include <QtCore/QList>
#include <QtCore/QDebug>
#include <qendian.h>
-#include <private/qsimd_p.h> // for qUnalignedLoad
QT_BEGIN_NAMESPACE
@@ -164,7 +163,7 @@ bool QMimeMagicRule::matchNumber(const QByteArray &data) const
const char *p = data.constData() + m_startPos;
const char *e = data.constData() + qMin(data.size() - int(sizeof(T)), m_endPos + 1);
for ( ; p <= e; ++p) {
- if ((qUnalignedLoad<T>(p) & mask) == (value & mask))
+ if ((qFromUnaligned<T>(reinterpret_cast<const uchar *>(p)) & mask) == (value & mask))
return true;
}
diff --git a/src/corelib/thread/qmutex_linux.cpp b/src/corelib/thread/qmutex_linux.cpp
index 25444ffff6..17072f44d4 100644
--- a/src/corelib/thread/qmutex_linux.cpp
+++ b/src/corelib/thread/qmutex_linux.cpp
@@ -57,7 +57,7 @@
#endif
#ifndef FUTEX_PRIVATE_FLAG
-# define FUTEX_PRIVATE_FLAG 128
+# define FUTEX_PRIVATE_FLAG 0
#endif
diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp
index 36f1997a6c..55af7256be 100644
--- a/src/corelib/tools/qarraydata.cpp
+++ b/src/corelib/tools/qarraydata.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -87,29 +88,20 @@ QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment,
if (!(options & RawData))
headerSize += (alignment - Q_ALIGNOF(QArrayData));
- // Allocate additional space if array is growing
- if (options & Grow) {
-
- // Guard against integer overflow when multiplying.
- if (capacity > std::numeric_limits<size_t>::max() / objectSize)
- return 0;
-
- size_t alloc;
- if (mul_overflow(objectSize, capacity, &alloc))
- return 0;
-
- // Make sure qAllocMore won't overflow qAllocMore.
- if (headerSize > size_t(MaxAllocSize) || alloc > size_t(MaxAllocSize) - headerSize)
- return 0;
-
- capacity = qAllocMore(int(alloc), int(headerSize)) / int(objectSize);
- }
+ if (headerSize > size_t(MaxAllocSize))
+ return 0;
+ // Calculate the byte size
+ // allocSize = objectSize * capacity + headerSize, but checked for overflow
+ // plus padded to grow in size
size_t allocSize;
- if (mul_overflow(objectSize, capacity, &allocSize))
- return 0;
- if (add_overflow(allocSize, headerSize, &allocSize))
- return 0;
+ if (options & Grow) {
+ auto r = qCalculateGrowingBlockSize(capacity, objectSize, headerSize);
+ capacity = r.elementCount;
+ allocSize = r.size;
+ } else {
+ allocSize = qCalculateBlockSize(capacity, objectSize, headerSize);
+ }
QArrayData *header = static_cast<QArrayData *>(::malloc(allocSize));
if (header) {
diff --git a/src/corelib/tools/qbitarray.cpp b/src/corelib/tools/qbitarray.cpp
index 446e09b1c0..12e4687b3c 100644
--- a/src/corelib/tools/qbitarray.cpp
+++ b/src/corelib/tools/qbitarray.cpp
@@ -42,6 +42,7 @@
#include <qalgorithms.h>
#include <qdatastream.h>
#include <qdebug.h>
+#include <qendian.h>
#include <string.h>
QT_BEGIN_NAMESPACE
@@ -169,25 +170,6 @@ QBitArray::QBitArray(int size, bool value)
Same as size().
*/
-template <typename T> T qUnalignedLoad(const uchar *ptr)
-{
- /*
- * Testing with different compilers shows that they all optimize the memcpy
- * call away and replace with direct loads whenever possible. On x86 and PPC,
- * GCC does direct unaligned loads; on MIPS, it generates a pair of load-left
- * and load-right instructions. ICC and Clang do the same on x86. This is both
- * 32- and 64-bit.
- *
- * On ARM cores without unaligned loads, the compiler leaves a call to
- * memcpy.
- */
-
- T u;
- memcpy(&u, ptr, sizeof(u));
- return u;
-}
-
-
/*!
If \a on is true, this function returns the number of
1-bits stored in the bit array; otherwise the number
@@ -203,17 +185,17 @@ int QBitArray::count(bool on) const
const quint8 *const end = reinterpret_cast<const quint8 *>(d.end());
while (bits + 7 <= end) {
- quint64 v = qUnalignedLoad<quint64>(bits);
+ quint64 v = qFromUnaligned<quint64>(bits);
bits += 8;
numBits += int(qPopulationCount(v));
}
if (bits + 3 <= end) {
- quint32 v = qUnalignedLoad<quint32>(bits);
+ quint32 v = qFromUnaligned<quint32>(bits);
bits += 4;
numBits += int(qPopulationCount(v));
}
if (bits + 1 < end) {
- quint16 v = qUnalignedLoad<quint16>(bits);
+ quint16 v = qFromUnaligned<quint16>(bits);
bits += 2;
numBits += int(qPopulationCount(v));
}
diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp
index a256b44b1f..266c2e9b57 100644
--- a/src/corelib/tools/qbytearray.cpp
+++ b/src/corelib/tools/qbytearray.cpp
@@ -46,6 +46,7 @@
#include "qlocale.h"
#include "qlocale_p.h"
#include "qlocale_tools_p.h"
+#include "private/qnumeric_p.h"
#include "qstringalgorithms_p.h"
#include "qscopedpointer.h"
#include "qbytearray_p.h"
@@ -128,17 +129,104 @@ int qFindByteArray(
const char *haystack0, int haystackLen, int from,
const char *needle0, int needleLen);
+/*
+ * This pair of functions is declared in qtools_p.h and is used by the Qt
+ * containers to allocate memory and grow the memory block during append
+ * operations.
+ *
+ * They take size_t parameters and return size_t so they will change sizes
+ * according to the pointer width. However, knowing Qt containers store the
+ * container size and element indexes in ints, these functions never return a
+ * size larger than INT_MAX. This is done by casting the element count and
+ * memory block size to int in several comparisons: the check for negative is
+ * very fast on most platforms as the code only needs to check the sign bit.
+ *
+ * These functions return SIZE_MAX on overflow, which can be passed to malloc()
+ * and will surely cause a NULL return (there's no way you can allocate a
+ * memory block the size of your entire VM space).
+ */
+
+/*!
+ \internal
+ \since 5.7
-int qAllocMore(int alloc, int extra) Q_DECL_NOTHROW
+ Returns the memory block size for a container containing \a elementCount
+ elements, each of \a elementSize bytes, plus a header of \a headerSize
+ bytes. That is, this function returns \c
+ {elementCount * elementSize + headerSize}
+
+ but unlike the simple calculation, it checks for overflows during the
+ multiplication and the addition.
+
+ Both \a elementCount and \a headerSize can be zero, but \a elementSize
+ cannot.
+
+ This function returns SIZE_MAX (~0) on overflow or if the memory block size
+ would not fit an int.
+*/
+size_t qCalculateBlockSize(size_t elementCount, size_t elementSize, size_t headerSize) Q_DECL_NOTHROW
{
- Q_ASSERT(alloc >= 0 && extra >= 0 && extra <= MaxAllocSize);
- Q_ASSERT_X(alloc <= MaxAllocSize - extra, "qAllocMore", "Requested size is too large!");
+ unsigned count = unsigned(elementCount);
+ unsigned size = unsigned(elementSize);
+ unsigned header = unsigned(headerSize);
+ Q_ASSERT(elementSize);
+ Q_ASSERT(size == elementSize);
+ Q_ASSERT(header == headerSize);
+
+ if (Q_UNLIKELY(count != elementCount))
+ return std::numeric_limits<size_t>::max();
+
+ unsigned bytes;
+ if (Q_UNLIKELY(mul_overflow(size, count, &bytes)) ||
+ Q_UNLIKELY(add_overflow(bytes, header, &bytes)))
+ return std::numeric_limits<size_t>::max();
+ if (Q_UNLIKELY(int(bytes) < 0)) // catches bytes >= 2GB
+ return std::numeric_limits<size_t>::max();
+
+ return bytes;
+}
+
+/*!
+ \internal
+ \since 5.7
- unsigned nalloc = qNextPowerOfTwo(alloc + extra);
+ Returns the memory block size and the number of elements that will fit in
+ that block for a container containing \a elementCount elements, each of \a
+ elementSize bytes, plus a header of \a headerSize bytes. This function
+ assumes the container will grow and pre-allocates a growth factor.
- Q_ASSERT(nalloc > unsigned(alloc + extra));
+ Both \a elementCount and \a headerSize can be zero, but \a elementSize
+ cannot.
+
+ This function returns SIZE_MAX (~0) on overflow or if the memory block size
+ would not fit an int.
+
+ \note The memory block may contain up to \a elementSize - 1 bytes more than
+ needed.
+*/
+CalculateGrowingBlockSizeResult
+qCalculateGrowingBlockSize(size_t elementCount, size_t elementSize, size_t headerSize) Q_DECL_NOTHROW
+{
+ CalculateGrowingBlockSizeResult result = {
+ std::numeric_limits<size_t>::max(),std::numeric_limits<size_t>::max()
+ };
+
+ unsigned bytes = unsigned(qCalculateBlockSize(elementCount, elementSize, headerSize));
+ if (int(bytes) < 0) // catches std::numeric_limits<size_t>::max()
+ return result;
+
+ unsigned morebytes = qNextPowerOfTwo(bytes);
+ if (Q_UNLIKELY(int(morebytes) < 0)) {
+ // catches morebytes == 2GB
+ // grow by half the difference between bytes and morebytes
+ bytes += (morebytes - bytes) / 2;
+ } else {
+ bytes = morebytes;
+ }
- return nalloc - extra;
+ result.elementCount = (bytes - unsigned(headerSize)) / unsigned(elementSize);
+ result.size = bytes;
+ return result;
}
/*****************************************************************************
@@ -1618,12 +1706,16 @@ void QByteArray::reallocData(uint alloc, Data::AllocationOptions options)
Data::deallocate(d);
d = x;
} else {
+ size_t blockSize;
if (options & Data::Grow) {
- if (alloc > MaxByteArraySize)
- qBadAlloc();
- alloc = qAllocMore(alloc, sizeof(Data));
+ auto r = qCalculateGrowingBlockSize(alloc, sizeof(QChar), sizeof(Data));
+ blockSize = r.size;
+ alloc = uint(r.elementCount);
+ } else {
+ blockSize = qCalculateBlockSize(alloc, sizeof(QChar), sizeof(Data));
}
- Data *x = static_cast<Data *>(::realloc(d, sizeof(Data) + alloc));
+
+ Data *x = static_cast<Data *>(::realloc(d, blockSize));
Q_CHECK_PTR(x);
x->alloc = alloc;
x->capacityReserved = (options & Data::CapacityReserved) ? 1 : 0;
diff --git a/src/corelib/tools/qcryptographichash.cpp b/src/corelib/tools/qcryptographichash.cpp
index 3cb3606013..08f89d2f02 100644
--- a/src/corelib/tools/qcryptographichash.cpp
+++ b/src/corelib/tools/qcryptographichash.cpp
@@ -95,9 +95,29 @@ static SHA3Final * const sha3Final = Final;
available on all platforms (MSVC 2008, for example), we #define them to the
Qt equivalents.
*/
+
+#ifdef uint64_t
+#undef uint64_t
+#endif
+
#define uint64_t QT_PREPEND_NAMESPACE(quint64)
+
+#ifdef uint32_t
+#undef uint32_t
+#endif
+
#define uint32_t QT_PREPEND_NAMESPACE(quint32)
+
+#ifdef uint8_t
+#undef uint8_t
+#endif
+
#define uint8_t QT_PREPEND_NAMESPACE(quint8)
+
+#ifdef int_least16_t
+#undef int_least16_t
+#endif
+
#define int_least16_t QT_PREPEND_NAMESPACE(qint16)
// Header from rfc6234 with 1 modification:
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
index 02afacb861..2ebf7c7977 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/tools/qdatetime.cpp
@@ -2158,7 +2158,7 @@ static int qt_timezone()
// number of seconds west of UTC.
// - It also takes DST into account, so we need to adjust it to always
// get the Standard Time offset.
- return -t.tm_gmtoff + (t.tm_isdst ? SECS_PER_HOUR : 0L);
+ return -t.tm_gmtoff + (t.tm_isdst ? (long)SECS_PER_HOUR : 0L);
#elif defined(Q_OS_INTEGRITY)
return 0;
#else
diff --git a/src/corelib/tools/qdatetimeparser.cpp b/src/corelib/tools/qdatetimeparser.cpp
index cc8c08d5b1..9c9009d636 100644
--- a/src/corelib/tools/qdatetimeparser.cpp
+++ b/src/corelib/tools/qdatetimeparser.cpp
@@ -708,17 +708,18 @@ int QDateTimeParser::parseSection(const QDateTime &currentValue, int sectionInde
}
const int sectionmaxsize = sectionMaxSize(sectionIndex);
- QString sectiontext = text.mid(index, sectionmaxsize);
- int sectiontextSize = sectiontext.size();
+ QStringRef sectionTextRef = text.midRef(index, sectionmaxsize);
+ int sectiontextSize = sectionTextRef.size();
QDTPDEBUG << "sectionValue for" << sn.name()
- << "with text" << text << "and st" << sectiontext
+ << "with text" << text << "and st" << sectionTextRef
<< text.midRef(index, sectionmaxsize)
<< index;
int used = 0;
switch (sn.type) {
case AmPmSection: {
+ QString sectiontext = sectionTextRef.toString();
const int ampm = findAmPm(sectiontext, sectionIndex, &used);
switch (ampm) {
case AM: // sectiontext == AM
@@ -750,6 +751,7 @@ int QDateTimeParser::parseSection(const QDateTime &currentValue, int sectionInde
case DayOfWeekSectionShort:
case DayOfWeekSectionLong:
if (sn.count >= 3) {
+ QString sectiontext = sectionTextRef.toString();
if (sn.type == MonthSection) {
int min = 1;
const QDate minDate = getMinimum().date();
@@ -788,7 +790,7 @@ int QDateTimeParser::parseSection(const QDateTime &currentValue, int sectionInde
int last = -1;
used = -1;
- QString digitsStr(sectiontext);
+ QStringRef digitsStr = sectionTextRef;
for (int i = 0; i < sectiontextSize; ++i) {
if (digitsStr.at(i).isSpace()) {
sectiontextSize = i;
@@ -809,7 +811,7 @@ int QDateTimeParser::parseSection(const QDateTime &currentValue, int sectionInde
}
}
if (ok && tmp <= absMax) {
- QDTPDEBUG << sectiontext.leftRef(digits) << tmp << digits;
+ QDTPDEBUG << sectionTextRef.left(digits) << tmp << digits;
last = tmp;
used = digits;
break;
@@ -817,13 +819,13 @@ int QDateTimeParser::parseSection(const QDateTime &currentValue, int sectionInde
}
if (last == -1) {
- QChar first(sectiontext.at(0));
+ QChar first(sectionTextRef.at(0));
if (separators.at(sectionIndex + 1).startsWith(first)) {
used = 0;
state = Intermediate;
} else {
state = Invalid;
- QDTPDEBUG << "invalid because" << sectiontext << "can't become a uint" << last << ok;
+ QDTPDEBUG << "invalid because" << sectionTextRef << "can't become a uint" << last << ok;
}
} else {
num += last;
@@ -1565,7 +1567,7 @@ QString QDateTimeParser::SectionNode::format() const
number that is within min and max.
*/
-bool QDateTimeParser::potentialValue(const QString &str, int min, int max, int index,
+bool QDateTimeParser::potentialValue(const QStringRef &str, int min, int max, int index,
const QDateTime &currentValue, int insert) const
{
if (str.isEmpty()) {
@@ -1592,8 +1594,7 @@ bool QDateTimeParser::potentialValue(const QString &str, int min, int max, int i
if (potentialValue(str + QLatin1Char('0' + j), min, max, index, currentValue, insert)) {
return true;
} else if (insert >= 0) {
- QString tmp = str;
- tmp.insert(insert, QLatin1Char('0' + j));
+ const QString tmp = str.left(insert) + QLatin1Char('0' + j) + str.mid(insert);
if (potentialValue(tmp, min, max, index, currentValue, insert))
return true;
}
@@ -1603,7 +1604,7 @@ bool QDateTimeParser::potentialValue(const QString &str, int min, int max, int i
return false;
}
-bool QDateTimeParser::skipToNextSection(int index, const QDateTime &current, const QString &text) const
+bool QDateTimeParser::skipToNextSection(int index, const QDateTime &current, const QStringRef &text) const
{
Q_ASSERT(current >= getMinimum() && current <= getMaximum());
diff --git a/src/corelib/tools/qdatetimeparser_p.h b/src/corelib/tools/qdatetimeparser_p.h
index 9689d88616..01a2f20802 100644
--- a/src/corelib/tools/qdatetimeparser_p.h
+++ b/src/corelib/tools/qdatetimeparser_p.h
@@ -214,9 +214,19 @@ public:
QString *dayName = 0, int *used = 0) const;
#endif
AmPmFinder findAmPm(QString &str, int index, int *used = 0) const;
- bool potentialValue(const QString &str, int min, int max, int index,
+ bool potentialValue(const QStringRef &str, int min, int max, int index,
const QDateTime &currentValue, int insert) const;
- bool skipToNextSection(int section, const QDateTime &current, const QString &sectionText) const;
+ bool potentialValue(const QString &str, int min, int max, int index,
+ const QDateTime &currentValue, int insert) const
+ {
+ return potentialValue(QStringRef(&str), min, max, index, currentValue, insert);
+ }
+
+ bool skipToNextSection(int section, const QDateTime &current, const QStringRef &sectionText) const;
+ bool skipToNextSection(int section, const QDateTime &current, const QString &sectionText) const
+ {
+ return skipToNextSection(section, current, QStringRef(&sectionText));
+ }
QString stateName(State s) const;
diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp
index 2f0886edce..593a87e65d 100644
--- a/src/corelib/tools/qhash.cpp
+++ b/src/corelib/tools/qhash.cpp
@@ -58,6 +58,7 @@
#include <qbytearray.h>
#include <qdatetime.h>
#include <qbasicatomic.h>
+#include <qendian.h>
#include <private/qsimd_p.h>
#ifndef QT_BOOTSTRAPPED
@@ -112,24 +113,24 @@ static uint crc32(const Char *ptr, size_t len, uint h)
p += 8;
for ( ; p <= e; p += 8)
- h2 = _mm_crc32_u64(h2, qUnalignedLoad<qlonglong>(p - 8));
+ h2 = _mm_crc32_u64(h2, qFromUnaligned<qlonglong>(p - 8));
h = h2;
p -= 8;
len = e - p;
if (len & 4) {
- h = _mm_crc32_u32(h, qUnalignedLoad<uint>(p));
+ h = _mm_crc32_u32(h, qFromUnaligned<uint>(p));
p += 4;
}
# else
p += 4;
for ( ; p <= e; p += 4)
- h = _mm_crc32_u32(h, qUnalignedLoad<uint>(p - 4));
+ h = _mm_crc32_u32(h, qFromUnaligned<uint>(p - 4));
p -= 4;
len = e - p;
# endif
if (len & 2) {
- h = _mm_crc32_u16(h, qUnalignedLoad<ushort>(p));
+ h = _mm_crc32_u16(h, qFromUnaligned<ushort>(p));
p += 2;
}
if (sizeof(Char) == 1 && len & 1)
diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp
index 7dd02bf954..1762da2c8f 100644
--- a/src/corelib/tools/qlist.cpp
+++ b/src/corelib/tools/qlist.cpp
@@ -60,15 +60,6 @@ QT_BEGIN_NAMESPACE
const QListData::Data QListData::shared_null = { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0, { 0 } };
-static int grow(int size)
-{
- if (size_t(size) > (MaxAllocSize - QListData::DataHeaderSize) / sizeof(void *))
- qBadAlloc();
- // dear compiler: don't optimize me out.
- volatile int x = qAllocMore(size * sizeof(void *), QListData::DataHeaderSize) / sizeof(void *);
- return x;
-}
-
/*!
* Detaches the QListData by allocating new memory for a list which will be bigger
* than the copied one and is expected to grow further.
@@ -84,12 +75,12 @@ QListData::Data *QListData::detach_grow(int *idx, int num)
Data *x = d;
int l = x->end - x->begin;
int nl = l + num;
- int alloc = grow(nl);
- Data* t = static_cast<Data *>(::malloc(DataHeaderSize + alloc * sizeof(void *)));
+ auto blockInfo = qCalculateGrowingBlockSize(nl, sizeof(void *), DataHeaderSize);
+ Data* t = static_cast<Data *>(::malloc(blockInfo.size));
Q_CHECK_PTR(t);
+ t->alloc = int(uint(blockInfo.elementCount));
t->ref.initializeOwned();
- t->alloc = alloc;
// The space reservation algorithm's optimization is biased towards appending:
// Something which looks like an append will put the data at the beginning,
// while something which looks like a prepend will put it in the middle
@@ -99,12 +90,12 @@ QListData::Data *QListData::detach_grow(int *idx, int num)
int bg;
if (*idx < 0) {
*idx = 0;
- bg = (alloc - nl) >> 1;
+ bg = (t->alloc - nl) >> 1;
} else if (*idx > l) {
*idx = l;
bg = 0;
} else if (*idx < (l >> 1)) {
- bg = (alloc - nl) >> 1;
+ bg = (t->alloc - nl) >> 1;
} else {
bg = 0;
}
@@ -126,7 +117,7 @@ QListData::Data *QListData::detach_grow(int *idx, int num)
QListData::Data *QListData::detach(int alloc)
{
Data *x = d;
- Data* t = static_cast<Data *>(::malloc(DataHeaderSize + alloc * sizeof(void *)));
+ Data* t = static_cast<Data *>(::malloc(qCalculateBlockSize(alloc, sizeof(void*), DataHeaderSize)));
Q_CHECK_PTR(t);
t->ref.initializeOwned();
@@ -146,7 +137,7 @@ QListData::Data *QListData::detach(int alloc)
void QListData::realloc(int alloc)
{
Q_ASSERT(!d->ref.isShared());
- Data *x = static_cast<Data *>(::realloc(d, DataHeaderSize + alloc * sizeof(void *)));
+ Data *x = static_cast<Data *>(::realloc(d, qCalculateBlockSize(alloc, sizeof(void *), DataHeaderSize)));
Q_CHECK_PTR(x);
d = x;
@@ -158,12 +149,12 @@ void QListData::realloc(int alloc)
void QListData::realloc_grow(int growth)
{
Q_ASSERT(!d->ref.isShared());
- int alloc = grow(d->alloc + growth);
- Data *x = static_cast<Data *>(::realloc(d, DataHeaderSize + alloc * sizeof(void *)));
+ auto r = qCalculateGrowingBlockSize(d->alloc + growth, sizeof(void *), DataHeaderSize);
+ Data *x = static_cast<Data *>(::realloc(d, r.size));
Q_CHECK_PTR(x);
d = x;
- d->alloc = alloc;
+ d->alloc = int(uint(r.elementCount));
}
void QListData::dispose(Data *d)
diff --git a/src/corelib/tools/qmessageauthenticationcode.cpp b/src/corelib/tools/qmessageauthenticationcode.cpp
index 9b91474283..9a84191452 100644
--- a/src/corelib/tools/qmessageauthenticationcode.cpp
+++ b/src/corelib/tools/qmessageauthenticationcode.cpp
@@ -46,9 +46,29 @@
available on all platforms (MSVC 2008, for example), we #define them to the
Qt equivalents.
*/
+
+#ifdef uint64_t
+#undef uint64_t
+#endif
+
#define uint64_t QT_PREPEND_NAMESPACE(quint64)
+
+#ifdef uint32_t
+#undef uint32_t
+#endif
+
#define uint32_t QT_PREPEND_NAMESPACE(quint32)
+
+#ifdef uint8_t
+#undef uint8_t
+#endif
+
#define uint8_t QT_PREPEND_NAMESPACE(quint8)
+
+#ifdef int_least16_t
+#undef int_least16_t
+#endif
+
#define int_least16_t QT_PREPEND_NAMESPACE(qint16)
// Header from rfc6234 with 1 modification:
diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp
index 7b1d94c501..d4edf459de 100644
--- a/src/corelib/tools/qsimd.cpp
+++ b/src/corelib/tools/qsimd.cpp
@@ -724,26 +724,4 @@ void qDumpCPUFeatures()
puts("");
}
-/*!
- \internal
- \fn T qUnalignedLoad(const void *ptr)
- \since 5.6.1
-
- Loads a \c{T} from address \a ptr, which may be misaligned.
-
- Use of this function avoid the undefined behavior that the C++ standard
- otherwise attributes to unaligned loads.
-*/
-
-/*!
- \internal
- \fn void qUnalignedStore(void *ptr, T t)
- \since 5.6.1
-
- Stores \a t to address \a ptr, which may be misaligned.
-
- Use of this function avoid the undefined behavior that the C++ standard
- otherwise attributes to unaligned stores.
-*/
-
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 6c1ee25234..c79bced52e 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -581,7 +581,7 @@ static int ucstrncmp(const QChar *a, const uchar *c, int l)
// we'll read uc[offset..offset+7] (16 bytes) and c[offset..offset+7] (8 bytes)
if (uc + offset + 7 < e) {
// same, but we're using an 8-byte load
- __m128i chunk = _mm_cvtsi64_si128(qUnalignedLoad<long long>(c + offset));
+ __m128i chunk = _mm_cvtsi64_si128(qFromUnaligned<long long>(c + offset));
__m128i secondHalf = _mm_unpacklo_epi8(chunk, nullmask);
__m128i ucdata = _mm_loadu_si128((const __m128i*)(uc + offset));
@@ -1757,10 +1757,13 @@ void QString::resize(int size, QChar fillChar)
void QString::reallocData(uint alloc, bool grow)
{
+ size_t blockSize;
if (grow) {
- if (alloc > (uint(MaxAllocSize) - sizeof(Data)) / sizeof(QChar))
- qBadAlloc();
- alloc = qAllocMore(alloc * sizeof(QChar), sizeof(Data)) / sizeof(QChar);
+ auto r = qCalculateGrowingBlockSize(alloc, sizeof(QChar), sizeof(Data));
+ blockSize = r.size;
+ alloc = uint(r.elementCount);
+ } else {
+ blockSize = qCalculateBlockSize(alloc, sizeof(QChar), sizeof(Data));
}
if (d->ref.isShared() || IS_RAW_DATA(d)) {
@@ -1774,7 +1777,7 @@ void QString::reallocData(uint alloc, bool grow)
Data::deallocate(d);
d = x;
} else {
- Data *p = static_cast<Data *>(::realloc(d, sizeof(Data) + alloc * sizeof(QChar)));
+ Data *p = static_cast<Data *>(::realloc(d, blockSize));
Q_CHECK_PTR(p);
d = p;
d->alloc = alloc;
@@ -2343,8 +2346,7 @@ QString &QString::remove(QChar ch, Qt::CaseSensitivity cs)
*/
QString &QString::replace(int pos, int len, const QString &after)
{
- QString copy = after;
- return replace(pos, len, copy.constData(), copy.length());
+ return replace(pos, len, after.constData(), after.length());
}
/*!
diff --git a/src/corelib/tools/qtimezoneprivate_tz.cpp b/src/corelib/tools/qtimezoneprivate_tz.cpp
index 8040365581..c2630c8593 100644
--- a/src/corelib/tools/qtimezoneprivate_tz.cpp
+++ b/src/corelib/tools/qtimezoneprivate_tz.cpp
@@ -47,6 +47,8 @@
#include <qdebug.h>
+#include "qlocale_tools_p.h"
+
#include <algorithm>
QT_BEGIN_NAMESPACE
@@ -376,39 +378,126 @@ static QDate calculatePosixDate(const QByteArray &dateRule, int year)
}
}
-static QTime parsePosixTime(const QByteArray &timeRule)
+// returns the time in seconds, INT_MIN if we failed to parse
+static int parsePosixTime(const char *begin, const char *end)
{
- // Format "HH:mm:ss", put check parts count just in case
- QList<QByteArray> parts = timeRule.split(':');
- int count = parts.count();
- if (count == 3)
- return QTime(parts.at(0).toInt(), parts.at(1).toInt(), parts.at(2).toInt());
- else if (count == 2)
- return QTime(parts.at(0).toInt(), parts.at(1).toInt(), 0);
- else if (count == 1)
- return QTime(parts.at(0).toInt(), 0, 0);
- return QTime(2, 0, 0);
+ // Format "hh[:mm[:ss]]"
+ int hour, min = 0, sec = 0;
+
+ // Note that the calls to qstrtoll do *not* check the end pointer, which
+ // means they proceed until they find a non-digit. We check that we're
+ // still in range at the end, but we may have read from past end. It's the
+ // caller's responsibility to ensure that begin is part of a
+ // null-terminated string.
+
+ bool ok = false;
+ hour = qstrtoll(begin, &begin, 10, &ok);
+ if (!ok || hour < 0)
+ return INT_MIN;
+ if (begin < end && *begin == ':') {
+ // minutes
+ ++begin;
+ min = qstrtoll(begin, &begin, 10, &ok);
+ if (!ok || min < 0)
+ return INT_MIN;
+
+ if (begin < end && *begin == ':') {
+ // seconds
+ ++begin;
+ sec = qstrtoll(begin, &begin, 10, &ok);
+ if (!ok || sec < 0)
+ return INT_MIN;
+ }
+ }
+
+ // we must have consumed everything
+ if (begin != end)
+ return INT_MIN;
+
+ return (hour * 60 + min) * 60 + sec;
}
-static int parsePosixOffset(const QByteArray &timeRule)
+static QTime parsePosixTransitionTime(const QByteArray &timeRule)
+{
+ // Format "hh[:mm[:ss]]"
+ int value = parsePosixTime(timeRule.constBegin(), timeRule.constEnd());
+ if (value == INT_MIN) {
+ // if we failed to parse, return 02:00
+ return QTime(2, 0, 0);
+ }
+ return QTime::fromMSecsSinceStartOfDay(value * 1000);
+}
+
+static int parsePosixOffset(const char *begin, const char *end)
{
// Format "[+|-]hh[:mm[:ss]]"
- QList<QByteArray> parts = timeRule.split(':');
- int count = parts.count();
- if (count == 3) {
- int hour = parts.at(0).toInt();
- int sign = hour >= 0 ? -1 : 1;
- return sign * ((qAbs(hour) * 60 * 60) + (parts.at(1).toInt() * 60) + parts.at(2).toInt());
- } else if (count == 2) {
- int hour = parts.at(0).toInt();
- int sign = hour >= 0 ? -1 : 1;
- return sign * ((qAbs(hour) * 60 * 60) + (parts.at(1).toInt() * 60));
- } else if (count == 1) {
- int hour = parts.at(0).toInt();
- int sign = hour >= 0 ? -1 : 1;
- return sign * (qAbs(hour) * 60 * 60);
- }
- return 0;
+ // note that the sign is inverted because POSIX counts in hours West of GMT
+ bool negate = true;
+ if (*begin == '+') {
+ ++begin;
+ } else if (*begin == '-') {
+ negate = false;
+ ++begin;
+ }
+
+ int value = parsePosixTime(begin, end);
+ if (value == INT_MIN)
+ return value;
+ return negate ? -value : value;
+}
+
+static inline bool asciiIsLetter(char ch)
+{
+ ch |= 0x20; // lowercases if it is a letter, otherwise just corrupts ch
+ return ch >= 'a' && ch <= 'z';
+}
+
+// Returns the zone name, the offset (in seconds) and advances \a begin to
+// where the parsing ended. Returns a zone of INT_MIN in case an offset
+// couldn't be read.
+static QPair<QString, int> parsePosixZoneNameAndOffset(const char *&pos, const char *end)
+{
+ static const char offsetChars[] = "0123456789:";
+ QPair<QString, int> result = qMakePair(QString(), INT_MIN);
+
+ const char *nameBegin = pos;
+ const char *nameEnd;
+ Q_ASSERT(pos < end);
+
+ if (*pos == '<') {
+ nameBegin = pos + 1; // skip the '<'
+ nameEnd = nameBegin;
+ while (nameEnd < end && *nameEnd != '>') {
+ // POSIX says only alphanumeric, but we allow anything
+ ++nameEnd;
+ }
+ pos = nameEnd + 1; // skip the '>'
+ } else {
+ nameBegin = pos;
+ nameEnd = nameBegin;
+ while (nameEnd < end && asciiIsLetter(*nameEnd))
+ ++nameEnd;
+ pos = nameEnd;
+ }
+ if (nameEnd - nameBegin < 3)
+ return result; // name must be at least 3 characters long
+
+ // zone offset, form [+-]hh:mm:ss
+ const char *zoneBegin = pos;
+ const char *zoneEnd = pos;
+ if (zoneEnd < end && (zoneEnd[0] == '+' || zoneEnd[0] == '-'))
+ ++zoneEnd;
+ while (zoneEnd < end) {
+ if (strchr(offsetChars, char(*zoneEnd)) == NULL)
+ break;
+ ++zoneEnd;
+ }
+
+ result.first = QString::fromUtf8(nameBegin, nameEnd - nameBegin);
+ if (zoneEnd > zoneBegin)
+ result.second = parsePosixOffset(zoneBegin, zoneEnd);
+ pos = zoneEnd;
+ return result;
}
static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArray &posixRule,
@@ -425,58 +514,45 @@ static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArra
// POSIX Format is like "TZ=CST6CDT,M3.2.0/2:00:00,M11.1.0/2:00:00"
// i.e. "std offset dst [offset],start[/time],end[/time]"
- // See http://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html
+ // See the section about TZ at http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html
QList<QByteArray> parts = posixRule.split(',');
- QString name = QString::fromUtf8(parts.at(0));
- QString stdName;
- QString stdOffsetString;
- QString dstName;
- QString dstOffsetString;
- bool parsedStdName = false;
- bool parsedStdOffset = false;
- for (int i = 0; i < name.size(); ++i) {
- if (name.at(i).isLetter()) {
- if (parsedStdName) {
- parsedStdOffset = true;
- dstName.append(name.at(i));
- } else {
- stdName.append(name.at(i));
+ QPair<QString, int> stdZone, dstZone;
+ {
+ const QByteArray &zoneinfo = parts.at(0);
+ const char *begin = zoneinfo.constBegin();
+
+ stdZone = parsePosixZoneNameAndOffset(begin, zoneinfo.constEnd());
+ if (stdZone.second == INT_MIN) {
+ stdZone.second = 0; // reset to UTC if we failed to parse
+ } else if (begin < zoneinfo.constEnd()) {
+ dstZone = parsePosixZoneNameAndOffset(begin, zoneinfo.constEnd());
+ if (dstZone.second == INT_MIN) {
+ // if the dst offset isn't provided, it is 1 hour ahead of the standard offset
+ dstZone.second = stdZone.second + (60 * 60);
}
- } else {
- parsedStdName = true;
- if (parsedStdOffset)
- dstOffsetString.append(name.at(i));
- else
- stdOffsetString.append(name.at(i));
}
}
- int utcOffset = parsePosixOffset(stdOffsetString.toUtf8());
-
// If only the name part then no transitions
if (parts.count() == 1) {
QTimeZonePrivate::Data data;
data.atMSecsSinceEpoch = lastTranMSecs;
- data.offsetFromUtc = utcOffset;
- data.standardTimeOffset = utcOffset;
+ data.offsetFromUtc = stdZone.second;
+ data.standardTimeOffset = stdZone.second;
data.daylightTimeOffset = 0;
- data.abbreviation = stdName;
+ data.abbreviation = stdZone.first;
result << data;
return result;
}
- // If not populated the total dst offset is 1 hour
- int dstOffset = utcOffset + (60 * 60);
- if (!dstOffsetString.isEmpty())
- dstOffset = parsePosixOffset(dstOffsetString.toUtf8());
// Get the std to dst transtion details
QList<QByteArray> dstParts = parts.at(1).split('/');
QByteArray dstDateRule = dstParts.at(0);
QTime dstTime;
if (dstParts.count() > 1)
- dstTime = parsePosixTime(dstParts.at(1));
+ dstTime = parsePosixTransitionTime(dstParts.at(1));
else
dstTime = QTime(2, 0, 0);
@@ -485,25 +561,25 @@ static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArra
QByteArray stdDateRule = stdParts.at(0);
QTime stdTime;
if (stdParts.count() > 1)
- stdTime = parsePosixTime(stdParts.at(1));
+ stdTime = parsePosixTransitionTime(stdParts.at(1));
else
stdTime = QTime(2, 0, 0);
for (int year = startYear; year <= endYear; ++year) {
QTimeZonePrivate::Data dstData;
QDateTime dst(calculatePosixDate(dstDateRule, year), dstTime, Qt::UTC);
- dstData.atMSecsSinceEpoch = dst.toMSecsSinceEpoch() - (utcOffset * 1000);
- dstData.offsetFromUtc = dstOffset;
- dstData.standardTimeOffset = utcOffset;
- dstData.daylightTimeOffset = dstOffset - utcOffset;
- dstData.abbreviation = dstName;
+ dstData.atMSecsSinceEpoch = dst.toMSecsSinceEpoch() - (stdZone.second * 1000);
+ dstData.offsetFromUtc = dstZone.second;
+ dstData.standardTimeOffset = stdZone.second;
+ dstData.daylightTimeOffset = dstZone.second - stdZone.second;
+ dstData.abbreviation = dstZone.first;
QTimeZonePrivate::Data stdData;
QDateTime std(calculatePosixDate(stdDateRule, year), stdTime, Qt::UTC);
- stdData.atMSecsSinceEpoch = std.toMSecsSinceEpoch() - (dstOffset * 1000);
- stdData.offsetFromUtc = utcOffset;
- stdData.standardTimeOffset = utcOffset;
+ stdData.atMSecsSinceEpoch = std.toMSecsSinceEpoch() - (dstZone.second * 1000);
+ stdData.offsetFromUtc = stdZone.second;
+ stdData.standardTimeOffset = stdZone.second;
stdData.daylightTimeOffset = 0;
- stdData.abbreviation = stdName;
+ stdData.abbreviation = stdZone.first;
// Part of the high year will overflow
if (year == 292278994 && (dstData.atMSecsSinceEpoch < 0 || stdData.atMSecsSinceEpoch < 0)) {
if (dstData.atMSecsSinceEpoch > 0) {
diff --git a/src/corelib/tools/qtools_p.h b/src/corelib/tools/qtools_p.h
index 5ec153c818..09adee5586 100644
--- a/src/corelib/tools/qtools_p.h
+++ b/src/corelib/tools/qtools_p.h
@@ -52,7 +52,7 @@
//
#include "QtCore/qglobal.h"
-#include <limits>
+#include <limits.h>
QT_BEGIN_NAMESPACE
@@ -88,11 +88,19 @@ Q_DECL_CONSTEXPR inline int fromOct(uint c) Q_DECL_NOTHROW
// We typically need an extra bit for qNextPowerOfTwo when determining the next allocation size.
enum {
- MaxAllocSize = (1 << (std::numeric_limits<int>::digits - 1)) - 1
+ MaxAllocSize = INT_MAX
+};
+
+struct CalculateGrowingBlockSizeResult {
+ size_t size;
+ size_t elementCount;
};
// implemented in qbytearray.cpp
-int Q_CORE_EXPORT qAllocMore(int alloc, int extra) Q_DECL_NOTHROW;
+size_t Q_CORE_EXPORT Q_DECL_CONST_FUNCTION
+qCalculateBlockSize(size_t elementCount, size_t elementSize, size_t headerSize = 0) Q_DECL_NOTHROW;
+CalculateGrowingBlockSizeResult Q_CORE_EXPORT Q_DECL_CONST_FUNCTION
+qCalculateGrowingBlockSize(size_t elementCount, size_t elementSize, size_t headerSize = 0) Q_DECL_NOTHROW ;
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h
index fea50f4c34..b68ca87063 100644
--- a/src/corelib/tools/qvector.h
+++ b/src/corelib/tools/qvector.h
@@ -736,7 +736,7 @@ typename QVector<T>::iterator QVector<T>::erase(iterator abegin, iterator aend)
const int itemsUntouched = abegin - d->begin();
// FIXME we could do a proper realloc, which copy constructs only needed data.
- // FIXME we ara about to delete data maybe it is good time to shrink?
+ // FIXME we are about to delete data - maybe it is good time to shrink?
// FIXME the shrink is also an issue in removeLast, that is just a copy + reduce of this.
if (d->alloc) {
detach();
@@ -756,7 +756,11 @@ typename QVector<T>::iterator QVector<T>::erase(iterator abegin, iterator aend)
}
} else {
destruct(abegin, aend);
- memmove(abegin, aend, (d->size - itemsToErase - itemsUntouched) * sizeof(T));
+ // QTBUG-53605: static_cast<void *> masks clang errors of the form
+ // error: destination for this 'memmove' call is a pointer to class containing a dynamic class
+ // FIXME maybe use std::is_polymorphic (as soon as allowed) to avoid the memmove
+ memmove(static_cast<void *>(abegin), static_cast<void *>(aend),
+ (d->size - itemsToErase - itemsUntouched) * sizeof(T));
}
d->size -= itemsToErase;
}
diff --git a/src/corelib/xml/qxmlstream.cpp b/src/corelib/xml/qxmlstream.cpp
index 8e62804025..3949d2c3ac 100644
--- a/src/corelib/xml/qxmlstream.cpp
+++ b/src/corelib/xml/qxmlstream.cpp
@@ -3025,10 +3025,14 @@ void QXmlStreamWriterPrivate::checkIfASCIICompatibleCodec()
{
#ifndef QT_NO_TEXTCODEC
Q_ASSERT(encoder);
- // assumes ASCII-compatibility for all 8-bit encodings
- QChar space = QLatin1Char(' ');
- const QByteArray bytes = encoder->fromUnicode(&space, 1);
- isCodecASCIICompatible = (bytes.count() == 1);
+ // test ASCII-compatibility using the letter 'a'
+ QChar letterA = QLatin1Char('a');
+ const QByteArray bytesA = encoder->fromUnicode(&letterA, 1);
+ const bool isCodecASCIICompatibleA = (bytesA.count() == 1) && (bytesA[0] == 0x61) ;
+ QChar letterLess = QLatin1Char('<');
+ const QByteArray bytesLess = encoder->fromUnicode(&letterLess, 1);
+ const bool isCodecASCIICompatibleLess = (bytesLess.count() == 1) && (bytesLess[0] == 0x3C) ;
+ isCodecASCIICompatible = isCodecASCIICompatibleA && isCodecASCIICompatibleLess ;
#else
isCodecASCIICompatible = true;
#endif
@@ -3790,7 +3794,8 @@ void QXmlStreamWriter::writeStartDocument(const QString &version)
#ifdef QT_NO_TEXTCODEC
d->write("iso-8859-1");
#else
- d->write(d->codec->name().constData(), d->codec->name().length());
+ const QByteArray name = d->codec->name();
+ d->write(name.constData(), name.length());
#endif
}
d->write("\"?>");
@@ -3813,7 +3818,8 @@ void QXmlStreamWriter::writeStartDocument(const QString &version, bool standalon
#ifdef QT_NO_TEXTCODEC
d->write("iso-8859-1");
#else
- d->write(d->codec->name().constData(), d->codec->name().length());
+ const QByteArray name = d->codec->name();
+ d->write(name.constData(), name.length());
#endif
}
if (standalone)
diff --git a/src/gui/doc/snippets/code/src_gui_kernel_qclipboard.cpp b/src/gui/doc/snippets/code/src_gui_kernel_qclipboard.cpp
index d5f610cf28..8581510133 100644
--- a/src/gui/doc/snippets/code/src_gui_kernel_qclipboard.cpp
+++ b/src/gui/doc/snippets/code/src_gui_kernel_qclipboard.cpp
@@ -49,7 +49,7 @@
****************************************************************************/
//! [0]
-QClipboard *clipboard = QApplication::clipboard();
+QClipboard *clipboard = QGuiApplication::clipboard();
QString originalText = clipboard->text();
...
clipboard->setText(newText);
diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp
index b8290861af..9545abfd21 100644
--- a/src/gui/image/qbmphandler.cpp
+++ b/src/gui/image/qbmphandler.cpp
@@ -289,6 +289,12 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int
format = QImage::Format_Mono;
}
+ if (depth != 32) {
+ ncols = bi.biClrUsed ? bi.biClrUsed : 1 << nbits;
+ if (ncols < 1 || ncols > 256) // sanity check - don't run out of mem if color table is broken
+ return false;
+ }
+
if (bi.biHeight < 0)
h = -h; // support images with negative height
@@ -296,19 +302,15 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int
image = QImage(w, h, format);
if (image.isNull()) // could not create image
return false;
- }
-
- if (depth != 32) {
- ncols = bi.biClrUsed ? bi.biClrUsed : 1 << nbits;
- if (ncols < 1 || ncols > 256) // sanity check - don't run out of mem if color table is broken
- return false;
- image.setColorCount(ncols);
+ if (ncols)
+ image.setColorCount(ncols); // Ensure valid QImage
}
image.setDotsPerMeterX(bi.biXPelsPerMeter);
image.setDotsPerMeterY(bi.biYPelsPerMeter);
if (ncols > 0) { // read color table
+ image.setColorCount(ncols);
uchar rgb[4];
int rgb_len = t == BMP_OLD ? 3 : 4;
for (int i=0; i<ncols; i++) {
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index 620cbde25d..0dec4b512d 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -284,7 +284,7 @@ QPixmap QPixmapIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::St
if (pm.isNull()) {
int idx = pixmaps.count();
while (--idx >= 0) {
- if (pe == &pixmaps[idx]) {
+ if (pe == &pixmaps.at(idx)) {
pixmaps.remove(idx);
break;
}
diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp
index cc8337fcb9..38782ac0a0 100644
--- a/src/gui/image/qiconloader.cpp
+++ b/src/gui/image/qiconloader.cpp
@@ -296,7 +296,7 @@ QIconTheme::QIconTheme(const QString &themeName)
{
QFile themeIndex;
- QStringList iconDirs = QIcon::themeSearchPaths();
+ const QStringList iconDirs = QIcon::themeSearchPaths();
for ( int i = 0 ; i < iconDirs.size() ; ++i) {
QDir iconDir(iconDirs[i]);
QString themeDir = iconDir.path() + QLatin1Char('/') + themeName;
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 3238d83729..3a31af8645 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -176,6 +176,9 @@ QImageData::~QImageData()
data = 0;
}
+#if defined(_M_ARM)
+#pragma optimize("", off)
+#endif
bool QImageData::checkForAlphaPixels() const
{
@@ -193,74 +196,81 @@ bool QImageData::checkForAlphaPixels() const
break;
case QImage::Format_ARGB32:
case QImage::Format_ARGB32_Premultiplied: {
- uchar *bits = data;
+ const uchar *bits = data;
for (int y=0; y<height && !has_alpha_pixels; ++y) {
+ uint alphaAnd = 0xff000000;
for (int x=0; x<width; ++x)
- has_alpha_pixels |= (((uint *)bits)[x] & 0xff000000) != 0xff000000;
+ alphaAnd &= reinterpret_cast<const uint*>(bits)[x];
+ has_alpha_pixels = (alphaAnd != 0xff000000);
bits += bytes_per_line;
}
} break;
case QImage::Format_RGBA8888:
case QImage::Format_RGBA8888_Premultiplied: {
- uchar *bits = data;
+ const uchar *bits = data;
for (int y=0; y<height && !has_alpha_pixels; ++y) {
+ uchar alphaAnd = 0xff;
for (int x=0; x<width; ++x)
- has_alpha_pixels |= bits[x*4+3] != 0xff;
+ alphaAnd &= bits[x * 4+ 3];
+ has_alpha_pixels = (alphaAnd != 0xff);
bits += bytes_per_line;
}
} break;
case QImage::Format_A2BGR30_Premultiplied:
case QImage::Format_A2RGB30_Premultiplied: {
- uchar *bits = data;
+ const uchar *bits = data;
for (int y=0; y<height && !has_alpha_pixels; ++y) {
+ uint alphaAnd = 0xc0000000;
for (int x=0; x<width; ++x)
- has_alpha_pixels |= (((uint *)bits)[x] & 0xc0000000) != 0xc0000000;
+ alphaAnd &= reinterpret_cast<const uint*>(bits)[x];
+ has_alpha_pixels = (alphaAnd != 0xc0000000);
bits += bytes_per_line;
}
} break;
case QImage::Format_ARGB8555_Premultiplied:
case QImage::Format_ARGB8565_Premultiplied: {
- uchar *bits = data;
- uchar *end_bits = data + bytes_per_line;
+ const uchar *bits = data;
+ const uchar *end_bits = data + bytes_per_line;
for (int y=0; y<height && !has_alpha_pixels; ++y) {
+ uchar alphaAnd = 0xff;
while (bits < end_bits) {
- has_alpha_pixels |= bits[0] != 0;
+ alphaAnd &= bits[0];
bits += 3;
}
+ has_alpha_pixels = (alphaAnd != 0xff);
bits = end_bits;
end_bits += bytes_per_line;
}
} break;
case QImage::Format_ARGB6666_Premultiplied: {
- uchar *bits = data;
- uchar *end_bits = data + bytes_per_line;
+ const uchar *bits = data;
+ const uchar *end_bits = data + bytes_per_line;
for (int y=0; y<height && !has_alpha_pixels; ++y) {
+ uchar alphaAnd = 0xfc;
while (bits < end_bits) {
- has_alpha_pixels |= (bits[0] & 0xfc) != 0;
+ alphaAnd &= bits[0];
bits += 3;
}
+ has_alpha_pixels = (alphaAnd != 0xfc);
bits = end_bits;
end_bits += bytes_per_line;
}
} break;
case QImage::Format_ARGB4444_Premultiplied: {
- uchar *bits = data;
- uchar *end_bits = data + bytes_per_line;
-
+ const uchar *bits = data;
for (int y=0; y<height && !has_alpha_pixels; ++y) {
- while (bits < end_bits) {
- has_alpha_pixels |= (bits[0] & 0xf0) != 0;
- bits += 2;
- }
- bits = end_bits;
- end_bits += bytes_per_line;
+ ushort alphaAnd = 0xf000;
+ for (int x=0; x<width; ++x)
+ alphaAnd &= reinterpret_cast<const ushort*>(bits)[x];
+ has_alpha_pixels = (alphaAnd != 0xf000);
+ bits += bytes_per_line;
}
} break;
@@ -283,6 +293,9 @@ bool QImageData::checkForAlphaPixels() const
return has_alpha_pixels;
}
+#if defined(_M_ARM)
+#pragma optimize("", on)
+#endif
/*!
\class QImage
diff --git a/src/gui/image/qimagepixmapcleanuphooks.cpp b/src/gui/image/qimagepixmapcleanuphooks.cpp
index 10fa4303b2..f383e7a60e 100644
--- a/src/gui/image/qimagepixmapcleanuphooks.cpp
+++ b/src/gui/image/qimagepixmapcleanuphooks.cpp
@@ -84,38 +84,38 @@ void QImagePixmapCleanupHooks::removeImageHook(_qt_image_cleanup_hook_64 hook)
void QImagePixmapCleanupHooks::executePlatformPixmapModificationHooks(QPlatformPixmap* pmd)
{
- QImagePixmapCleanupHooks *h = qt_image_and_pixmap_cleanup_hooks();
+ const QImagePixmapCleanupHooks *h = qt_image_and_pixmap_cleanup_hooks();
// the global destructor for the pixmap and image hooks might have
// been called already if the app is "leaking" global
// pixmaps/images
if (!h)
return;
- for (int i = 0; i < h->pixmapModificationHooks.count(); ++i)
- h->pixmapModificationHooks[i](pmd);
+ for (auto hook : h->pixmapModificationHooks)
+ hook(pmd);
}
void QImagePixmapCleanupHooks::executePlatformPixmapDestructionHooks(QPlatformPixmap* pmd)
{
- QImagePixmapCleanupHooks *h = qt_image_and_pixmap_cleanup_hooks();
+ const QImagePixmapCleanupHooks *h = qt_image_and_pixmap_cleanup_hooks();
// the global destructor for the pixmap and image hooks might have
// been called already if the app is "leaking" global
// pixmaps/images
if (!h)
return;
- for (int i = 0; i < h->pixmapDestructionHooks.count(); ++i)
- h->pixmapDestructionHooks[i](pmd);
+ for (auto hook : h->pixmapDestructionHooks)
+ hook(pmd);
}
void QImagePixmapCleanupHooks::executeImageHooks(qint64 key)
{
- QImagePixmapCleanupHooks *h = qt_image_and_pixmap_cleanup_hooks();
+ const QImagePixmapCleanupHooks *h = qt_image_and_pixmap_cleanup_hooks();
// the global destructor for the pixmap and image hooks might have
// been called already if the app is "leaking" global
// pixmaps/images
if (!h)
return;
- for (int i = 0; i < h->imageHooks.count(); ++i)
- h->imageHooks[i](key);
+ for (auto hook : h->imageHooks)
+ hook(key);
}
diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp
index 7fbb498bbb..96d6be502d 100644
--- a/src/gui/image/qpnghandler.cpp
+++ b/src/gui/image/qpnghandler.cpp
@@ -749,7 +749,7 @@ static void set_text(const QImage &image, png_structp png_ptr, png_infop info_pt
QMap<QString, QString>::ConstIterator it = text.constBegin();
int i = 0;
while (it != text.constEnd()) {
- text_ptr[i].key = qstrdup(it.key().left(79).toLatin1().constData());
+ text_ptr[i].key = qstrdup(it.key().leftRef(79).toLatin1().constData());
bool noCompress = (it.value().length() < 40);
#ifdef PNG_iTXt_SUPPORTED
diff --git a/src/gui/image/qxpmhandler.cpp b/src/gui/image/qxpmhandler.cpp
index 5c8ff84929..756e31318f 100644
--- a/src/gui/image/qxpmhandler.cpp
+++ b/src/gui/image/qxpmhandler.cpp
@@ -1154,7 +1154,7 @@ static bool write_xpm_image(const QImage &sourceImage, QIODevice *device, const
int cc = 0;
for(x=0; x<w; x++) {
int color = (int)(*(yp + x));
- QByteArray chars(xpm_color_name(cpp, colorMap[color]));
+ const QByteArray chars(xpm_color_name(cpp, colorMap[color]));
line[cc++] = QLatin1Char(chars[0]);
if (cpp > 1) {
line[cc++] = QLatin1Char(chars[1]);
diff --git a/src/gui/itemmodels/qstandarditemmodel.cpp b/src/gui/itemmodels/qstandarditemmodel.cpp
index ff54602a5d..973e5c4333 100644
--- a/src/gui/itemmodels/qstandarditemmodel.cpp
+++ b/src/gui/itemmodels/qstandarditemmodel.cpp
@@ -3018,10 +3018,7 @@ QMimeData *QStandardItemModel::mimeData(const QModelIndexList &indexes) const
for (int i = 0; i < childList.count(); ++i) {
QStandardItem *chi = childList.at(i);
if (chi) {
- QSet<QStandardItem *>::iterator it = itemsSet.find(chi);
- if (it != itemsSet.end()) {
- itemsSet.erase(it);
- }
+ itemsSet.erase(itemsSet.constFind(chi));
stack.push(chi);
}
}
@@ -3130,13 +3127,13 @@ bool QStandardItemModel::dropMimeData(const QMimeData *data, Qt::DropAction acti
for (int i = 0; i < rows.count(); ++i)
rowsToInsert[rows.at(i)] = 1;
for (int i = 0; i < rowsToInsert.count(); ++i) {
- if (rowsToInsert[i] == 1){
+ if (rowsToInsert.at(i) == 1){
rowsToInsert[i] = dragRowCount;
++dragRowCount;
}
}
for (int i = 0; i < rows.count(); ++i)
- rows[i] = top + rowsToInsert[rows[i]];
+ rows[i] = top + rowsToInsert.at(rows.at(i));
QBitArray isWrittenTo(dragRowCount * dragColumnCount);
diff --git a/src/gui/kernel/qclipboard.cpp b/src/gui/kernel/qclipboard.cpp
index 7932b9a2dc..e9da36a42a 100644
--- a/src/gui/kernel/qclipboard.cpp
+++ b/src/gui/kernel/qclipboard.cpp
@@ -67,7 +67,7 @@ QT_BEGIN_NAMESPACE
Drop}.
There is a single QClipboard object in an application, accessible
- as QApplication::clipboard().
+ as QGuiApplication::clipboard().
Example:
\snippet code/src_gui_kernel_qclipboard.cpp 0
@@ -137,7 +137,7 @@ QT_BEGIN_NAMESPACE
\endlist
- \sa QApplication
+ \sa QGuiApplication
*/
/*!
@@ -147,7 +147,7 @@ QT_BEGIN_NAMESPACE
Do not call this function.
- Call QApplication::clipboard() instead to get a pointer to the
+ Call QGuiApplication::clipboard() instead to get a pointer to the
application's global clipboard object.
There is only one clipboard in the window system, and creating
@@ -165,7 +165,7 @@ QClipboard::QClipboard(QObject *parent)
Destroys the clipboard.
- You should never delete the clipboard. QApplication will do this
+ You should never delete the clipboard. QGuiApplication will do this
when the application terminates.
*/
QClipboard::~QClipboard()
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index 305ce5c82e..6adbea6da6 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -3904,6 +3904,9 @@ QDebug operator<<(QDebug dbg, const QEvent *e)
case QEvent::Expose:
dbg << "QExposeEvent(" << static_cast<const QExposeEvent *>(e)->region() << ')';
break;
+ case QEvent::Paint:
+ dbg << "QPaintEvent(" << static_cast<const QPaintEvent *>(e)->region() << ')';
+ break;
case QEvent::MouseButtonPress:
case QEvent::MouseMove:
case QEvent::MouseButtonRelease:
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index d0bfc7ff5f..7afeadcced 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -1035,7 +1035,7 @@ QWindow *QGuiApplication::topLevelAt(const QPoint &pos)
// may repeat. Find only when there is more than one virtual desktop.
if (!windowScreen && screens.count() != primaryScreens.count()) {
for (int i = 1; i < screens.size(); ++i) {
- QScreen *screen = screens[i];
+ QScreen *screen = screens.at(i);
if (screen->geometry().contains(pos)) {
windowScreen = screen;
break;
@@ -2641,7 +2641,7 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To
if (b == Qt::NoButton)
self->synthesizedMousePoints.clear();
- QList<QTouchEvent::TouchPoint> touchPoints = touchEvent.touchPoints();
+ const QList<QTouchEvent::TouchPoint> &touchPoints = touchEvent.touchPoints();
if (eventType == QEvent::TouchBegin)
m_fakeMouseSourcePointId = touchPoints.first().id();
diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp
index 8ccd85795b..e7b1f9e073 100644
--- a/src/gui/kernel/qkeysequence.cpp
+++ b/src/gui/kernel/qkeysequence.cpp
@@ -1154,21 +1154,22 @@ int QKeySequencePrivate::decodeString(const QString &str, QKeySequence::Sequence
}
int p = accel.lastIndexOf(QLatin1Char('+'), str.length() - 2); // -2 so that Ctrl++ works
+ QStringRef accelRef(&accel);
if(p > 0)
- accel = accel.mid(p + 1);
+ accelRef = accelRef.mid(p + 1);
int fnum = 0;
- if (accel.length() == 1) {
+ if (accelRef.length() == 1) {
#if defined(Q_OS_MACX)
- int qtKey = qtkeyForMacSymbol(accel[0]);
+ int qtKey = qtkeyForMacSymbol(accelRef.at(0));
if (qtKey != -1) {
ret |= qtKey;
} else
#endif
{
- ret |= accel[0].toUpper().unicode();
+ ret |= accelRef.at(0).toUpper().unicode();
}
- } else if (accel[0] == QLatin1Char('f') && (fnum = accel.mid(1).toInt()) && (fnum >= 1) && (fnum <= 35)) {
+ } else if (accelRef.at(0) == QLatin1Char('f') && (fnum = accelRef.mid(1).toInt()) >= 1 && fnum <= 35) {
ret |= Qt::Key_F1 + fnum - 1;
} else {
// For NativeText, check the traslation table first,
@@ -1182,7 +1183,7 @@ int QKeySequencePrivate::decodeString(const QString &str, QKeySequence::Sequence
QString keyName(tran == 0
? QCoreApplication::translate("QShortcut", keyname[i].name)
: QString::fromLatin1(keyname[i].name));
- if (accel == keyName.toLower()) {
+ if (accelRef == keyName.toLower()) {
ret |= keyname[i].key;
found = true;
break;
diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp
index 19464eeca3..7e5697e5d8 100644
--- a/src/gui/kernel/qopenglcontext.cpp
+++ b/src/gui/kernel/qopenglcontext.cpp
@@ -1418,7 +1418,7 @@ void QOpenGLContextGroupPrivate::removeContext(QOpenGLContext *ctx)
m_shares.removeOne(ctx);
if (ctx == m_context && !m_shares.isEmpty())
- m_context = m_shares.first();
+ m_context = m_shares.constFirst();
if (!m_refs.deref()) {
cleanup();
@@ -1582,7 +1582,7 @@ QOpenGLMultiGroupSharedResource::~QOpenGLMultiGroupSharedResource()
#endif
for (int i = 0; i < m_groups.size(); ++i) {
if (!m_groups.at(i)->shares().isEmpty()) {
- QOpenGLContext *context = m_groups.at(i)->shares().first();
+ QOpenGLContext *context = m_groups.at(i)->shares().constFirst();
QOpenGLSharedResource *resource = value(context);
if (resource)
resource->free();
diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp
index a0e65654a6..3490e786a8 100644
--- a/src/gui/kernel/qplatformintegration.cpp
+++ b/src/gui/kernel/qplatformintegration.cpp
@@ -474,11 +474,11 @@ void QPlatformIntegration::screenAdded(QPlatformScreen *ps, bool isPrimary)
void QPlatformIntegration::removeScreen(QScreen *screen)
{
- const bool wasPrimary = (!QGuiApplicationPrivate::screen_list.isEmpty() && QGuiApplicationPrivate::screen_list[0] == screen);
+ const bool wasPrimary = (!QGuiApplicationPrivate::screen_list.isEmpty() && QGuiApplicationPrivate::screen_list.at(0) == screen);
QGuiApplicationPrivate::screen_list.removeOne(screen);
if (wasPrimary && qGuiApp && !QGuiApplicationPrivate::screen_list.isEmpty())
- emit qGuiApp->primaryScreenChanged(QGuiApplicationPrivate::screen_list[0]);
+ emit qGuiApp->primaryScreenChanged(QGuiApplicationPrivate::screen_list.at(0));
}
/*!
diff --git a/src/gui/kernel/qplatformscreen.cpp b/src/gui/kernel/qplatformscreen.cpp
index 8450c6a083..3c1552c31e 100644
--- a/src/gui/kernel/qplatformscreen.cpp
+++ b/src/gui/kernel/qplatformscreen.cpp
@@ -93,7 +93,7 @@ QPixmap QPlatformScreen::grabWindow(WId window, int x, int y, int width, int hei
*/
QWindow *QPlatformScreen::topLevelAt(const QPoint & pos) const
{
- QWindowList list = QGuiApplication::topLevelWindows();
+ const QWindowList list = QGuiApplication::topLevelWindows();
for (int i = list.size()-1; i >= 0; --i) {
QWindow *w = list[i];
if (w->isVisible() && QHighDpi::toNativePixels(w->geometry(), w).contains(pos))
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index 81310ae2a2..fa26fd77a3 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -1688,11 +1688,9 @@ void QWindow::destroy()
if (QGuiApplicationPrivate::currentMousePressWindow == this)
QGuiApplicationPrivate::currentMousePressWindow = parent();
- for (int i = 0; i < QGuiApplicationPrivate::tabletDevicePoints.size(); ++i) {
- QGuiApplicationPrivate::TabletPointData &pointData = QGuiApplicationPrivate::tabletDevicePoints[i];
- if (pointData.target == this)
- pointData.target = parent();
- }
+ for (int i = 0; i < QGuiApplicationPrivate::tabletDevicePoints.size(); ++i)
+ if (QGuiApplicationPrivate::tabletDevicePoints.at(i).target == this)
+ QGuiApplicationPrivate::tabletDevicePoints[i].target = parent();
bool wasVisible = isVisible();
d->visibilityOnDestroy = wasVisible && d->platformWindow;
diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h
index cde70a1102..5e42f5ba90 100644
--- a/src/gui/kernel/qwindowsysteminterface.h
+++ b/src/gui/kernel/qwindowsysteminterface.h
@@ -117,7 +117,7 @@ public:
static void handleWheelEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, int d, Qt::Orientation o, Qt::KeyboardModifiers mods = Qt::NoModifier);
struct TouchPoint {
- TouchPoint() : id(0), uniqueId(-1), pressure(0), rotation(0), state(Qt::TouchPointStationary), flags(0) { }
+ TouchPoint() : id(0), uniqueId(-1), pressure(0), rotation(0), state(Qt::TouchPointStationary) { }
int id; // for application use
qint64 uniqueId; // for TUIO: object/token ID; otherwise empty
// TODO for TUIO 2.0: add registerPointerUniqueID(QPointerUniqueId)
@@ -142,7 +142,7 @@ public:
// rect is relative to parent
static void handleGeometryChange(QWindow *w, const QRect &newRect, const QRect &oldRect = QRect());
- static void handleCloseEvent(QWindow *w, bool *accepted = 0);
+ static void handleCloseEvent(QWindow *w, bool *accepted = Q_NULLPTR);
static void handleEnterEvent(QWindow *w, const QPointF &local = QPointF(), const QPointF& global = QPointF());
static void handleLeaveEvent(QWindow *w);
static void handleEnterLeaveEvent(QWindow *enter, QWindow *leave, const QPointF &local = QPointF(), const QPointF& global = QPointF());
diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp
index b932ee60c9..303d4d4eb1 100644
--- a/src/gui/opengl/qopenglframebufferobject.cpp
+++ b/src/gui/opengl/qopenglframebufferobject.cpp
@@ -1073,7 +1073,7 @@ bool QOpenGLFramebufferObject::bind()
if (d->format.samples() == 0) {
// Create new textures to replace the ones stolen via takeTexture().
for (int i = 0; i < d->colorAttachments.count(); ++i) {
- if (!d->colorAttachments[i].guard)
+ if (!d->colorAttachments.at(i).guard)
d->initTexture(i);
}
}
@@ -1206,10 +1206,11 @@ GLuint QOpenGLFramebufferObject::takeTexture(int colorAttachmentIndex)
QOpenGLContext *current = QOpenGLContext::currentContext();
if (current && current->shareGroup() == d->fbo_guard->group() && isBound())
release();
- id = d->colorAttachments[colorAttachmentIndex].guard ? d->colorAttachments[colorAttachmentIndex].guard->id() : 0;
+ auto &guard = d->colorAttachments[colorAttachmentIndex].guard;
+ id = guard ? guard->id() : 0;
// Do not call free() on texture_guard, just null it out.
// This way the texture will not be deleted when the guard is destroyed.
- d->colorAttachments[colorAttachmentIndex].guard = 0;
+ guard = 0;
}
return id;
}
diff --git a/src/gui/opengl/qopenglgradientcache.cpp b/src/gui/opengl/qopenglgradientcache.cpp
index c135489379..58dcbed50a 100644
--- a/src/gui/opengl/qopenglgradientcache.cpp
+++ b/src/gui/opengl/qopenglgradientcache.cpp
@@ -108,7 +108,7 @@ GLuint QOpenGL2GradientCache::getBuffer(const QGradient &gradient, qreal opacity
{
quint64 hash_val = 0;
- QGradientStops stops = gradient.stops();
+ const QGradientStops stops = gradient.stops();
for (int i = 0; i < stops.size() && i <= 2; i++)
hash_val += stops[i].second.rgba();
@@ -170,16 +170,12 @@ GLuint QOpenGL2GradientCache::addCacheElement(quint64 hash_val, const QGradient
void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient, QRgba64 *colorTable, int size, qreal opacity) const
{
int pos = 0;
- QGradientStops s = gradient.stops();
- QVector<QRgba64> colors(s.size());
-
- for (int i = 0; i < s.size(); ++i)
- colors[i] = s[i].second.rgba64();
+ const QGradientStops s = gradient.stops();
bool colorInterpolation = (gradient.interpolationMode() == QGradient::ColorInterpolation);
uint alpha = qRound(opacity * 256);
- QRgba64 current_color = combineAlpha256(colors[0], alpha);
+ QRgba64 current_color = combineAlpha256(s[0].second.rgba64(), alpha);
qreal incr = 1.0 / qreal(size);
qreal fpos = 1.5 * incr;
colorTable[pos++] = qPremultiply(current_color);
@@ -193,9 +189,10 @@ void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient
if (colorInterpolation)
current_color = qPremultiply(current_color);
- for (int i = 0; i < s.size() - 1; ++i) {
+ const int sLast = s.size() - 1;
+ for (int i = 0; i < sLast; ++i) {
qreal delta = 1/(s[i+1].first - s[i].first);
- QRgba64 next_color = combineAlpha256(colors[i+1], alpha);
+ QRgba64 next_color = combineAlpha256(s[i + 1].second.rgba64(), alpha);
if (colorInterpolation)
next_color = qPremultiply(next_color);
@@ -214,7 +211,7 @@ void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient
Q_ASSERT(s.size() > 0);
- QRgba64 last_color = qPremultiply(combineAlpha256(colors[s.size() - 1], alpha));
+ QRgba64 last_color = qPremultiply(combineAlpha256(s[sLast].second.rgba64(), alpha));
for (;pos < size; ++pos)
colorTable[pos] = last_color;
@@ -225,16 +222,13 @@ void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient
void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient, uint *colorTable, int size, qreal opacity) const
{
int pos = 0;
- QGradientStops s = gradient.stops();
- QVector<uint> colors(s.size());
-
- for (int i = 0; i < s.size(); ++i)
- colors[i] = s[i].second.rgba(); // Qt LIES! It returns ARGB (on little-endian AND on big-endian)
+ const QGradientStops s = gradient.stops();
bool colorInterpolation = (gradient.interpolationMode() == QGradient::ColorInterpolation);
uint alpha = qRound(opacity * 256);
- uint current_color = ARGB_COMBINE_ALPHA(colors[0], alpha);
+ // Qt LIES! It returns ARGB (on little-endian AND on big-endian)
+ uint current_color = ARGB_COMBINE_ALPHA(s[0].second.rgba(), alpha);
qreal incr = 1.0 / qreal(size);
qreal fpos = 1.5 * incr;
colorTable[pos++] = ARGB2RGBA(qPremultiply(current_color));
@@ -248,9 +242,10 @@ void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient
if (colorInterpolation)
current_color = qPremultiply(current_color);
- for (int i = 0; i < s.size() - 1; ++i) {
+ const int sLast = s.size() - 1;
+ for (int i = 0; i < sLast; ++i) {
qreal delta = 1/(s[i+1].first - s[i].first);
- uint next_color = ARGB_COMBINE_ALPHA(colors[i+1], alpha);
+ uint next_color = ARGB_COMBINE_ALPHA(s[i + 1].second.rgba(), alpha);
if (colorInterpolation)
next_color = qPremultiply(next_color);
@@ -269,7 +264,7 @@ void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient
Q_ASSERT(s.size() > 0);
- uint last_color = ARGB2RGBA(qPremultiply(ARGB_COMBINE_ALPHA(colors[s.size() - 1], alpha)));
+ uint last_color = ARGB2RGBA(qPremultiply(ARGB_COMBINE_ALPHA(s[sLast].second.rgba(), alpha)));
for (;pos < size; ++pos)
colorTable[pos] = last_color;
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index 8defcfb28d..6472481e7a 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -2186,11 +2186,10 @@ void QPainter::setBrushOrigin(const QPointF &p)
destination pixel in such a way that the alpha component of the
source defines the translucency of the pixel.
- When the paint device is a QImage, the image format must be set to
- \l {QImage::Format}{Format_ARGB32_Premultiplied} or
- \l {QImage::Format}{Format_ARGB32} for the composition modes to have
- any effect. For performance the premultiplied version is the preferred
- format.
+ Several composition modes require an alpha channel in the source or
+ target images to have an effect. For optimal performance the
+ image format \l {QImage::Format}{Format_ARGB32_Premultiplied} is
+ preferred.
When a composition mode is set it applies to all painting
operator, pens, brushes, gradients and pixmap/image drawing.
@@ -2469,7 +2468,7 @@ void QPainter::setClipping(bool enable)
// we can't enable clipping if we don't have a clip
if (enable
- && (d->state->clipInfo.isEmpty() || d->state->clipInfo.last().operation == Qt::NoClip))
+ && (d->state->clipInfo.isEmpty() || d->state->clipInfo.constLast().operation == Qt::NoClip))
return;
d->state->clipEnabled = enable;
diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp
index 7072a2d79c..7dbc83b338 100644
--- a/src/gui/painting/qpainterpath.cpp
+++ b/src/gui/painting/qpainterpath.cpp
@@ -690,7 +690,7 @@ void QPainterPath::moveTo(const QPointF &p)
d->require_moveTo = false;
- if (d->elements.last().type == MoveToElement) {
+ if (d->elements.constLast().type == MoveToElement) {
d->elements.last().x = p.x();
d->elements.last().y = p.y();
} else {
@@ -738,7 +738,7 @@ void QPainterPath::lineTo(const QPointF &p)
QPainterPathData *d = d_func();
Q_ASSERT(!d->elements.isEmpty());
d->maybeMoveTo();
- if (p == QPointF(d->elements.last()))
+ if (p == QPointF(d->elements.constLast()))
return;
Element elm = { p.x(), p.y(), LineToElement };
d->elements.append(elm);
@@ -801,7 +801,7 @@ void QPainterPath::cubicTo(const QPointF &c1, const QPointF &c2, const QPointF &
// Abort on empty curve as a stroker cannot handle this and the
// curve is irrelevant anyway.
- if (d->elements.last() == c1 && c1 == c2 && c2 == e)
+ if (d->elements.constLast() == c1 && c1 == c2 && c2 == e)
return;
d->maybeMoveTo();
@@ -984,7 +984,7 @@ QPointF QPainterPath::currentPosition() const
{
return !d_ptr || d_func()->elements.isEmpty()
? QPointF()
- : QPointF(d_func()->elements.last().x, d_func()->elements.last().y);
+ : QPointF(d_func()->elements.constLast().x, d_func()->elements.constLast().y);
}
@@ -1073,7 +1073,7 @@ void QPainterPath::addPolygon(const QPolygonF &polygon)
d_func()->elements.reserve(d_func()->elements.size() + polygon.size());
- moveTo(polygon.first());
+ moveTo(polygon.constFirst());
for (int i=1; i<polygon.size(); ++i) {
Element elm = { polygon.at(i).x(), polygon.at(i).y(), LineToElement };
d_func()->elements << elm;
@@ -1178,12 +1178,12 @@ void QPainterPath::addText(const QPointF &point, const QFont &f, const QString &
QVarLengthArray<int> visualOrder(nItems);
QVarLengthArray<uchar> levels(nItems);
for (int i = 0; i < nItems; ++i)
- levels[i] = eng->layoutData->items[i].analysis.bidiLevel;
+ levels[i] = eng->layoutData->items.at(i).analysis.bidiLevel;
QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data());
for (int i = 0; i < nItems; ++i) {
int item = visualOrder[i];
- QScriptItem &si = eng->layoutData->items[item];
+ const QScriptItem &si = eng->layoutData->items.at(item);
if (si.analysis.flags < QScriptAnalysis::TabOrObject) {
QGlyphLayout glyphs = eng->shapedGlyphs(&si);
@@ -1230,7 +1230,7 @@ void QPainterPath::addPath(const QPainterPath &other)
QPainterPathData *d = reinterpret_cast<QPainterPathData *>(d_func());
// Remove last moveto so we don't get multiple moveto's
- if (d->elements.last().type == MoveToElement)
+ if (d->elements.constLast().type == MoveToElement)
d->elements.remove(d->elements.size()-1);
// Locate where our own current subpath will start after the other path is added.
@@ -1261,7 +1261,7 @@ void QPainterPath::connectPath(const QPainterPath &other)
QPainterPathData *d = reinterpret_cast<QPainterPathData *>(d_func());
// Remove last moveto so we don't get multiple moveto's
- if (d->elements.last().type == MoveToElement)
+ if (d->elements.constLast().type == MoveToElement)
d->elements.remove(d->elements.size()-1);
// Locate where our own current subpath will start after the other path is added.
@@ -1273,7 +1273,7 @@ void QPainterPath::connectPath(const QPainterPath &other)
d->elements[first].type = LineToElement;
// avoid duplicate points
- if (first > 0 && QPointF(d->elements[first]) == QPointF(d->elements[first - 1])) {
+ if (first > 0 && QPointF(d->elements.at(first)) == QPointF(d->elements.at(first - 1))) {
d->elements.remove(first--);
--cStart;
}
@@ -1685,8 +1685,9 @@ QList<QPolygonF> QPainterPath::toFillPolygons(const QTransform &matrix) const
int isect_j = current_isects.at(j);
if (isect_j == i)
continue;
- for (int k=0; k<isects[isect_j].size(); ++k) {
- int isect_k = isects[isect_j][k];
+ const QVector<int> &isects_j = isects.at(isect_j);
+ for (int k = 0, size = isects_j.size(); k < size; ++k) {
+ int isect_k = isects_j.at(k);
if (isect_k != i && !isects.at(i).contains(isect_k)) {
isects[i] += isect_k;
}
@@ -1708,7 +1709,7 @@ QList<QPolygonF> QPainterPath::toFillPolygons(const QTransform &matrix) const
// Join the intersected subpaths as rewinded polygons
for (int i=0; i<count; ++i) {
- const QVector<int> &subpath_list = isects[i];
+ const QVector<int> &subpath_list = isects.at(i);
if (!subpath_list.isEmpty()) {
QPolygonF buildUp;
for (int j=0; j<subpath_list.size(); ++j) {
@@ -1717,7 +1718,7 @@ QList<QPolygonF> QPainterPath::toFillPolygons(const QTransform &matrix) const
if (!subpath.isClosed())
buildUp += subpath.first();
if (!buildUp.isClosed())
- buildUp += buildUp.first();
+ buildUp += buildUp.constFirst();
}
polys += buildUp;
}
@@ -2789,7 +2790,7 @@ void QPainterPathStroker::setDashOffset(qreal offset)
QPolygonF QPainterPath::toFillPolygon(const QTransform &matrix) const
{
- QList<QPolygonF> flats = toSubpathPolygons(matrix);
+ const QList<QPolygonF> flats = toSubpathPolygons(matrix);
QPolygonF polygon;
if (flats.isEmpty())
return polygon;
diff --git a/src/gui/painting/qpathclipper.cpp b/src/gui/painting/qpathclipper.cpp
index 48ae3cfc80..4f2b59c775 100644
--- a/src/gui/painting/qpathclipper.cpp
+++ b/src/gui/painting/qpathclipper.cpp
@@ -1648,7 +1648,7 @@ bool QPathClipper::doClip(QWingedEdge &list, ClipperMode mode)
#ifdef QDEBUG_CLIPPER
printf("sorted y coords:\n");
for (int i = 0; i < y_coords.size(); ++i) {
- printf("%.9f\n", y_coords[i]);
+ printf("%.9f\n", y_coords.at(i));
}
#endif
@@ -1686,23 +1686,23 @@ bool QPathClipper::doClip(QWingedEdge &list, ClipperMode mode)
QPathVertex *b = list.vertex(edge->second);
// FIXME: this can be optimized by using binary search
- const int first = qFuzzyFind(y_coords.begin(), y_coords.end(), qMin(a->y, b->y)) - y_coords.begin();
- const int last = qFuzzyFind(y_coords.begin() + first, y_coords.end(), qMax(a->y, b->y)) - y_coords.begin();
+ const int first = qFuzzyFind(y_coords.cbegin(), y_coords.cend(), qMin(a->y, b->y)) - y_coords.cbegin();
+ const int last = qFuzzyFind(y_coords.cbegin() + first, y_coords.cend(), qMax(a->y, b->y)) - y_coords.cbegin();
Q_ASSERT(first < y_coords.size() - 1);
Q_ASSERT(last < y_coords.size());
- qreal bestY = 0.5 * (y_coords[first] + y_coords[first+1]);
- qreal biggestGap = y_coords[first+1] - y_coords[first];
-
+ qreal biggestGap = y_coords.at(first + 1) - y_coords.at(first);
+ int bestIdx = first;
for (int i = first + 1; i < last; ++i) {
- qreal gap = y_coords[i+1] - y_coords[i];
+ qreal gap = y_coords.at(i + 1) - y_coords.at(i);
if (gap > biggestGap) {
- bestY = 0.5 * (y_coords[i] + y_coords[i+1]);
+ bestIdx = i;
biggestGap = gap;
}
}
+ const qreal bestY = 0.5 * (y_coords.at(bestIdx) + y_coords.at(bestIdx + 1));
#ifdef QDEBUG_CLIPPER
printf("y: %.9f, gap: %.9f\n", bestY, biggestGap);
diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp
index b014305796..34f1c51f6d 100644
--- a/src/gui/painting/qpdf.cpp
+++ b/src/gui/painting/qpdf.cpp
@@ -1674,7 +1674,7 @@ void QPdfEnginePrivate::writePage()
uint resources = requestObject();
uint annots = requestObject();
- addXrefEntry(pages.last());
+ addXrefEntry(pages.constLast());
xprintf("<<\n"
"/Type /Page\n"
"/Parent %d 0 R\n"
@@ -1767,7 +1767,7 @@ void QPdfEnginePrivate::writeTail()
">>\n"
"startxref\n%d\n"
"%%%%EOF\n",
- xrefPositions.size()-1, info, catalog, xrefPositions.last());
+ xrefPositions.size()-1, info, catalog, xrefPositions.constLast());
}
int QPdfEnginePrivate::addXrefEntry(int object, bool printostr)
diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp
index bb92e6bfba..940de87eee 100644
--- a/src/gui/text/qcssparser.cpp
+++ b/src/gui/text/qcssparser.cpp
@@ -1507,10 +1507,10 @@ QRect Declaration::rectValue() const
const QCss::Value &v = d->values.at(0);
if (v.type != Value::Function)
return QRect();
- QStringList func = v.variant.toStringList();
+ const QStringList func = v.variant.toStringList();
if (func.count() != 2 || func.at(0).compare(QLatin1String("rect")) != 0)
return QRect();
- QStringList args = func[1].split(QLatin1Char(' '), QString::SkipEmptyParts);
+ const auto args = func[1].splitRef(QLatin1Char(' '), QString::SkipEmptyParts);
if (args.count() != 4)
return QRect();
QRect rect(args[0].toInt(), args[1].toInt(), args[2].toInt(), args[3].toInt());
@@ -1653,6 +1653,7 @@ Qt::Alignment Declaration::alignmentValue() const
void Declaration::borderImageValue(QString *image, int *cuts,
TileMode *h, TileMode *v) const
{
+ const DeclarationData *d = this->d.data(); // make it const and shadow d
*image = uriValue();
for (int i = 0; i < 4; i++)
cuts[i] = -1;
@@ -1914,9 +1915,8 @@ bool StyleSelector::basicSelectorMatches(const BasicSelector &sel, NodePtr node)
return false;
if (a.valueMatchCriterium == QCss::AttributeSelector::MatchContains) {
-
- QStringList lst = attrValue.split(QLatin1Char(' '));
- if (!lst.contains(a.value))
+ const auto lst = attrValue.splitRef(QLatin1Char(' '));
+ if (!lst.contains(QStringRef(&a.value)))
return false;
} else if (
(a.valueMatchCriterium == QCss::AttributeSelector::MatchEqual
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index f92e4ab457..828dbc318c 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -2033,7 +2033,7 @@ uint qHash(const QFont &font, uint seed) Q_DECL_NOTHROW
*/
bool QFont::fromString(const QString &descrip)
{
- QStringList l(descrip.split(QLatin1Char(',')));
+ const auto l = descrip.splitRef(QLatin1Char(','));
int count = l.count();
if (!count || (count > 2 && count < 9) || count > 11) {
@@ -2042,7 +2042,7 @@ bool QFont::fromString(const QString &descrip)
return false;
}
- setFamily(l[0]);
+ setFamily(l[0].toString());
if (count > 1 && l[1].toDouble() > 0.0)
setPointSizeF(l[1].toDouble());
if (count == 9) {
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index e4c9b45dc2..cdfcdec80c 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -697,25 +697,20 @@ static QStringList familyList(const QFontDef &req)
if (req.family.isEmpty())
return family_list;
- QStringList list = req.family.split(QLatin1Char(','));
+ const auto list = req.family.splitRef(QLatin1Char(','));
const int numFamilies = list.size();
family_list.reserve(numFamilies);
for (int i = 0; i < numFamilies; ++i) {
- QString str = list.at(i).trimmed();
+ QStringRef str = list.at(i).trimmed();
if ((str.startsWith(QLatin1Char('"')) && str.endsWith(QLatin1Char('"')))
|| (str.startsWith(QLatin1Char('\'')) && str.endsWith(QLatin1Char('\''))))
str = str.mid(1, str.length() - 2);
- family_list << str;
+ family_list << str.toString();
}
// append the substitute list for each family in family_list
- QStringList subs_list;
- QStringList::ConstIterator it = family_list.constBegin(), end = family_list.constEnd();
- for (; it != end; ++it)
- subs_list += QFont::substitutes(*it);
-// qDebug() << "adding substs: " << subs_list;
-
- family_list += subs_list;
+ for (int i = 0, size = family_list.size(); i < size; ++i)
+ family_list += QFont::substitutes(family_list.at(i));
return family_list;
}
@@ -2737,8 +2732,6 @@ void QFontDatabase::load(const QFontPrivate *d, int script)
}
if (req.pointSize < 0)
req.pointSize = req.pixelSize*72.0/d->dpi;
- if (req.weight == 0)
- req.weight = QFont::Normal;
if (req.stretch == 0)
req.stretch = 100;
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index 16c654dcb7..adc8f634dc 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -1833,8 +1833,7 @@ QFontEngine *QFontEngineMulti::loadEngine(int at)
request.family = fallbackFamilyAt(at - 1);
if (QFontEngine *engine = QFontDatabase::findFont(request, m_script)) {
- if (request.weight > QFont::Normal)
- engine->fontDef.weight = request.weight;
+ engine->fontDef.weight = request.weight;
if (request.style > QFont::StyleNormal)
engine->fontDef.style = request.style;
return engine;
diff --git a/src/gui/text/qfragmentmap_p.h b/src/gui/text/qfragmentmap_p.h
index 4cf17aadc7..b54d7261d0 100644
--- a/src/gui/text/qfragmentmap_p.h
+++ b/src/gui/text/qfragmentmap_p.h
@@ -255,14 +255,11 @@ uint QFragmentMapData<Fragment>::createFragment()
uint freePos = head->freelist;
if (freePos == head->allocated) {
// need to create some free space
- if (freePos >= uint(MaxAllocSize) / fragmentSize)
- qBadAlloc();
- uint needed = qAllocMore((freePos+1)*fragmentSize, 0);
- Q_ASSERT(needed/fragmentSize > head->allocated);
- Fragment *newFragments = (Fragment *)realloc(fragments, needed);
+ auto blockInfo = qCalculateGrowingBlockSize(freePos + 1, fragmentSize);
+ Fragment *newFragments = (Fragment *)realloc(fragments, blockInfo.size);
Q_CHECK_PTR(newFragments);
fragments = newFragments;
- head->allocated = needed/fragmentSize;
+ head->allocated = quint32(blockInfo.elementCount);
F(freePos).right = 0;
}
diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp
index 8e4fa8a730..a3dbf455cf 100644
--- a/src/gui/text/qtextdocument.cpp
+++ b/src/gui/text/qtextdocument.cpp
@@ -2430,7 +2430,7 @@ bool QTextHtmlExporter::emitCharFormatStyle(const QTextCharFormat &format)
html += QLatin1Char(';');
attributesEmitted = true;
} else {
- html.chop(qstrlen(decorationTag.latin1()));
+ html.chop(decorationTag.size());
}
if (format.foreground() != defaultCharFormat.foreground()
@@ -2665,7 +2665,7 @@ void QTextHtmlExporter::emitFragment(const QTextFragment &fragment)
if (attributesEmitted)
html += QLatin1String("\">");
else
- html.chop(qstrlen(styleTag.latin1()));
+ html.chop(styleTag.size());
if (isObject) {
for (int i = 0; isImage && i < txt.length(); ++i) {
@@ -2700,13 +2700,8 @@ void QTextHtmlExporter::emitFragment(const QTextFragment &fragment)
// split for [\n{LineSeparator}]
QString forcedLineBreakRegExp = QString::fromLatin1("[\\na]");
forcedLineBreakRegExp[3] = QChar::LineSeparator;
-
- const QStringList lines = txt.split(QRegExp(forcedLineBreakRegExp));
- for (int i = 0; i < lines.count(); ++i) {
- if (i > 0)
- html += QLatin1String("<br />"); // space on purpose for compatibility with Netscape, Lynx & Co.
- html += lines.at(i);
- }
+ // space in BR on purpose for compatibility with old-fashioned browsers
+ html += txt.replace(QRegExp(forcedLineBreakRegExp), QLatin1String("<br />"));
}
if (attributesEmitted)
@@ -3227,7 +3222,7 @@ void QTextHtmlExporter::emitFrameStyle(const QTextFrameFormat &format, FrameType
QString::number(format.rightMargin()));
if (html.length() == originalHtmlLength) // nothing emitted?
- html.chop(qstrlen(styleAttribute.latin1()));
+ html.chop(styleAttribute.size());
else
html += QLatin1Char('\"');
}
diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp
index df0d52d8e9..3537adba9e 100644
--- a/src/gui/text/qtextdocument_p.cpp
+++ b/src/gui/text/qtextdocument_p.cpp
@@ -1006,9 +1006,9 @@ int QTextDocumentPrivate::undoRedo(bool undo)
bool inBlock = (
undoState > 0
&& undoState < undoStack.size()
- && undoStack[undoState].block_part
- && undoStack[undoState-1].block_part
- && !undoStack[undoState-1].block_end
+ && undoStack.at(undoState).block_part
+ && undoStack.at(undoState - 1).block_part
+ && !undoStack.at(undoState - 1).block_end
);
if (!inBlock)
break;
@@ -1074,13 +1074,14 @@ void QTextDocumentPrivate::appendUndoItem(const QTextUndoCommand &c)
if (!undoStack.isEmpty() && modified) {
- QTextUndoCommand &last = undoStack[undoState - 1];
+ const int lastIdx = undoState - 1;
+ const QTextUndoCommand &last = undoStack.at(lastIdx);
if ( (last.block_part && c.block_part && !last.block_end) // part of the same block => can merge
|| (!c.block_part && !last.block_part) // two single undo items => can merge
|| (c.command == QTextUndoCommand::Inserted && last.command == c.command && (last.block_part && !c.block_part))) {
// two sequential inserts that are not part of the same block => can merge
- if (last.tryMerge(c))
+ if (undoStack[lastIdx].tryMerge(c))
return;
}
}
@@ -1102,7 +1103,7 @@ void QTextDocumentPrivate::clearUndoRedoStacks(QTextDocument::Stacks stacksToCle
bool redoCommandsAvailable = undoState != undoStack.size();
if (stacksToClear == QTextDocument::UndoStack && undoCommandsAvailable) {
for (int i = 0; i < undoState; ++i) {
- QTextUndoCommand c = undoStack[undoState];
+ QTextUndoCommand c = undoStack.at(undoState);
if (c.command & QTextUndoCommand::Custom)
delete c.custom;
}
@@ -1114,7 +1115,7 @@ void QTextDocumentPrivate::clearUndoRedoStacks(QTextDocument::Stacks stacksToCle
} else if (stacksToClear == QTextDocument::RedoStack
&& redoCommandsAvailable) {
for (int i = undoState; i < undoStack.size(); ++i) {
- QTextUndoCommand c = undoStack[i];
+ QTextUndoCommand c = undoStack.at(i);
if (c.command & QTextUndoCommand::Custom)
delete c.custom;
}
@@ -1124,7 +1125,7 @@ void QTextDocumentPrivate::clearUndoRedoStacks(QTextDocument::Stacks stacksToCle
} else if (stacksToClear == QTextDocument::UndoAndRedoStacks
&& !undoStack.isEmpty()) {
for (int i = 0; i < undoStack.size(); ++i) {
- QTextUndoCommand c = undoStack[i];
+ QTextUndoCommand c = undoStack.at(i);
if (c.command & QTextUndoCommand::Custom)
delete c.custom;
}
@@ -1187,8 +1188,8 @@ void QTextDocumentPrivate::endEditBlock()
return;
if (undoEnabled && undoState > 0) {
- const bool wasBlocking = !undoStack[undoState - 1].block_end;
- if (undoStack[undoState - 1].block_part) {
+ const bool wasBlocking = !undoStack.at(undoState - 1).block_end;
+ if (undoStack.at(undoState - 1).block_part) {
undoStack[undoState - 1].block_end = true;
if (wasBlocking)
emit document()->undoCommandAdded();
diff --git a/src/gui/text/qtextdocumentfragment.cpp b/src/gui/text/qtextdocumentfragment.cpp
index f8f4e454e0..a1a562c839 100644
--- a/src/gui/text/qtextdocumentfragment.cpp
+++ b/src/gui/text/qtextdocumentfragment.cpp
@@ -882,7 +882,7 @@ QTextHtmlImporter::Table QTextHtmlImporter::scanTable(int tableNodeIdx)
if (at(cell).isTableCell()) {
// skip all columns with spans from previous rows
while (colsInRow < rowColSpanForColumn.size()) {
- const RowColSpanInfo &spanInfo = rowColSpanForColumn[colsInRow];
+ const RowColSpanInfo &spanInfo = rowColSpanForColumn.at(colsInRow);
if (spanInfo.row + spanInfo.rowSpan > effectiveRow) {
Q_ASSERT(spanInfo.col == colsInRow);
@@ -1081,8 +1081,8 @@ QTextHtmlImporter::ProcessNodeResult QTextHtmlImporter::processBlockNode()
&& indent != 0
&& (lists.isEmpty()
|| !hasBlock
- || !lists.last().list
- || lists.last().list->itemNumber(cursor.block()) == -1
+ || !lists.constLast().list
+ || lists.constLast().list->itemNumber(cursor.block()) == -1
)
) {
block.setIndent(indent);
diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp
index 1b2113d281..0c8904b4c5 100644
--- a/src/gui/text/qtextdocumentlayout.cpp
+++ b/src/gui/text/qtextdocumentlayout.cpp
@@ -265,7 +265,7 @@ void QTextTableData::updateTableSize()
const QFixed effectiveLeftMargin = this->leftMargin + border + padding;
const QFixed effectiveRightMargin = this->rightMargin + border + padding;
size.height = contentsHeight == -1
- ? rowPositions.last() + heights.last() + padding + border + cellSpacing + effectiveBottomMargin
+ ? rowPositions.constLast() + heights.constLast() + padding + border + cellSpacing + effectiveBottomMargin
: effectiveTopMargin + contentsHeight + effectiveBottomMargin;
size.width = effectiveLeftMargin + contentsWidth + effectiveRightMargin;
}
@@ -1238,7 +1238,7 @@ void QTextDocumentLayoutPrivate::drawFlow(const QPointF &offset, QPainter *paint
// if we're past what is already laid out then we're better off
// not trying to draw things that may not be positioned correctly yet
- if (currentPosInDoc >= checkPoints.last().positionInFrame)
+ if (currentPosInDoc >= checkPoints.constLast().positionInFrame)
break;
if (lastVisibleCheckPoint != checkPoints.end()
@@ -1798,7 +1798,7 @@ recalc_minmax_widths:
td->columnPositions[i] = td->columnPositions.at(i-1) + td->widths.at(i-1) + 2 * td->border + cellSpacing;
// - margin to compensate the + margin in columnPositions[0]
- const QFixed contentsWidth = td->columnPositions.last() + td->widths.last() + td->padding + td->border + cellSpacing - leftMargin;
+ const QFixed contentsWidth = td->columnPositions.constLast() + td->widths.constLast() + td->padding + td->border + cellSpacing - leftMargin;
// if the table is too big and causes an overflow re-do the layout with WrapAnywhere as wrap
// mode
@@ -1845,14 +1845,14 @@ recalc_minmax_widths:
td->calcRowPosition(r);
const int tableStartPage = (absoluteTableY / pageHeight).truncate();
- const int currentPage = ((td->rowPositions[r] + absoluteTableY) / pageHeight).truncate();
+ const int currentPage = ((td->rowPositions.at(r) + absoluteTableY) / pageHeight).truncate();
const QFixed pageBottom = (currentPage + 1) * pageHeight - td->effectiveBottomMargin - absoluteTableY - cellSpacing - td->border;
const QFixed pageTop = currentPage * pageHeight + td->effectiveTopMargin - absoluteTableY + cellSpacing + td->border;
const QFixed nextPageTop = pageTop + pageHeight;
- if (td->rowPositions[r] > pageBottom)
+ if (td->rowPositions.at(r) > pageBottom)
td->rowPositions[r] = nextPageTop;
- else if (td->rowPositions[r] < pageTop)
+ else if (td->rowPositions.at(r) < pageTop)
td->rowPositions[r] = pageTop;
bool dropRowToNextPage = true;
@@ -1863,7 +1863,7 @@ recalc_minmax_widths:
QFixed dropDistance = 0;
relayout:
- const int rowStartPage = ((td->rowPositions[r] + absoluteTableY) / pageHeight).truncate();
+ const int rowStartPage = ((td->rowPositions.at(r) + absoluteTableY) / pageHeight).truncate();
// if any of the header rows or the first non-header row start on the next page
// then the entire header should be dropped
if (r <= headerRowCount && rowStartPage > tableStartPage && !hasDroppedTable) {
@@ -1927,13 +1927,13 @@ relayout:
}
if (rowCellCount > 0 && dropRowToNextPage) {
- dropDistance = nextPageTop - td->rowPositions[r];
+ dropDistance = nextPageTop - td->rowPositions.at(r);
td->rowPositions[r] = nextPageTop;
td->heights[r] = 0;
dropRowToNextPage = false;
cellHeights.resize(cellCountBeforeRow);
if (r > headerRowCount)
- td->heights[r-1] = pageBottom - td->rowPositions[r-1];
+ td->heights[r - 1] = pageBottom - td->rowPositions.at(r - 1);
goto relayout;
}
@@ -1944,7 +1944,7 @@ relayout:
}
if (r == headerRowCount - 1) {
- td->headerHeight = td->rowPositions[r] + td->heights[r] - td->rowPositions[0] + td->cellSpacing + 2 * td->border;
+ td->headerHeight = td->rowPositions.at(r) + td->heights.at(r) - td->rowPositions.at(0) + td->cellSpacing + 2 * td->border;
td->headerHeight -= td->headerHeight * (td->headerHeight / pageHeight).truncate();
td->effectiveTopMargin += td->headerHeight;
}
@@ -2304,7 +2304,7 @@ void QTextDocumentLayoutPrivate::layoutFlow(QTextFrame::Iterator it, QTextLayout
docPos = it.currentBlock().position();
if (inRootFrame) {
- if (qAbs(layoutStruct->y - checkPoints.last().y) > 2000) {
+ if (qAbs(layoutStruct->y - checkPoints.constLast().y) > 2000) {
QFixed left, right;
floatMargins(layoutStruct->y, layoutStruct, &left, &right);
if (left == layoutStruct->x_left && right == layoutStruct->x_right) {
@@ -2554,7 +2554,7 @@ void QTextDocumentLayoutPrivate::layoutFlow(QTextFrame::Iterator it, QTextLayout
checkPoints.append(cp);
checkPoints.reserve(checkPoints.size());
} else {
- currentLazyLayoutPosition = checkPoints.last().positionInFrame;
+ currentLazyLayoutPosition = checkPoints.constLast().positionInFrame;
// #######
//checkPoints.last().positionInFrame = q->document()->docHandle()->length();
}
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 6be84c0186..d11f8c34b1 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -1643,8 +1643,14 @@ void QTextEngine::itemize() const
if (analysis->bidiLevel % 2)
--analysis->bidiLevel;
analysis->flags = QScriptAnalysis::LineOrParagraphSeparator;
- if (option.flags() & QTextOption::ShowLineAndParagraphSeparators)
+ if (option.flags() & QTextOption::ShowLineAndParagraphSeparators) {
+ const int offset = uc - string;
+ layoutData->string.detach();
+ string = reinterpret_cast<const ushort *>(layoutData->string.unicode());
+ uc = string + offset;
+ e = uc + length;
*const_cast<ushort*>(uc) = 0x21B5; // visual line separator
+ }
break;
case QChar::Tabulation:
analysis->flags = QScriptAnalysis::Tab;
@@ -3272,7 +3278,7 @@ int QTextEngine::endOfLine(int lineNum)
insertionPointsForLine(lineNum, insertionPoints);
if (insertionPoints.size() > 0)
- return insertionPoints.last();
+ return insertionPoints.constLast();
return 0;
}
@@ -3282,7 +3288,7 @@ int QTextEngine::beginningOfLine(int lineNum)
insertionPointsForLine(lineNum, insertionPoints);
if (insertionPoints.size() > 0)
- return insertionPoints.first();
+ return insertionPoints.constFirst();
return 0;
}
diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp
index 49ec9ca768..2109b15a85 100644
--- a/src/gui/text/qtextformat.cpp
+++ b/src/gui/text/qtextformat.cpp
@@ -364,9 +364,10 @@ void QTextFormatPrivate::recalcFont() const
f.setPixelSize(props.at(i).value.toInt());
break;
case QTextFormat::FontWeight: {
- int weight = props.at(i).value.toInt();
- if (weight == 0) weight = QFont::Normal;
- f.setWeight(weight);
+ const QVariant weightValue = props.at(i).value;
+ int weight = weightValue.toInt();
+ if (weight >= 0 && weightValue.isValid())
+ f.setWeight(weight);
break; }
case QTextFormat::FontItalic:
f.setItalic(props.at(i).value.toBool());
@@ -3462,7 +3463,7 @@ void QTextFormatCollection::setDefaultFont(const QFont &f)
{
defaultFnt = f;
for (int i = 0; i < formats.count(); ++i)
- if (formats[i].d)
+ if (formats.at(i).d)
formats[i].d->resolveFont(defaultFnt);
}
diff --git a/src/gui/text/qtextformat.h b/src/gui/text/qtextformat.h
index bc627521ff..805affd87c 100644
--- a/src/gui/text/qtextformat.h
+++ b/src/gui/text/qtextformat.h
@@ -431,9 +431,9 @@ public:
{ return doubleProperty(FontPointSize); }
inline void setFontWeight(int weight)
- { if (weight == QFont::Normal) weight = 0; setProperty(FontWeight, weight); }
+ { setProperty(FontWeight, weight); }
inline int fontWeight() const
- { int weight = intProperty(FontWeight); if (weight == 0) weight = QFont::Normal; return weight; }
+ { return hasProperty(FontWeight) ? intProperty(FontWeight) : QFont::Normal; }
inline void setFontItalic(bool italic)
{ setProperty(FontItalic, italic); }
inline bool fontItalic() const
diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp
index 576ff7d935..103a208c26 100644
--- a/src/gui/text/qtexthtmlparser.cpp
+++ b/src/gui/text/qtexthtmlparser.cpp
@@ -665,7 +665,7 @@ void QTextHtmlParser::parseTag()
if (hasPrefix(QLatin1Char('/'))) {
if (nodes.last().id == Html_style) {
#ifndef QT_NO_CSSPARSER
- QCss::Parser parser(nodes.last().text);
+ QCss::Parser parser(nodes.constLast().text);
QCss::StyleSheet sheet;
sheet.origin = QCss::StyleSheetOrigin_Author;
parser.parse(&sheet, Qt::CaseInsensitive);
diff --git a/src/gui/text/qtextodfwriter.cpp b/src/gui/text/qtextodfwriter.cpp
index f7741bad2c..73d2e545ba 100644
--- a/src/gui/text/qtextodfwriter.cpp
+++ b/src/gui/text/qtextodfwriter.cpp
@@ -812,10 +812,10 @@ bool QTextOdfWriter::writeAll()
}
// add objects for lists, frames and tables
- QVector<QTextFormat> allFormats = m_document->allFormats();
- QList<int> copy = formats.toList();
- for (QList<int>::Iterator iter = copy.begin(); iter != copy.end(); ++iter) {
- QTextObject *object = m_document->objectForFormat(allFormats[*iter]);
+ const QVector<QTextFormat> allFormats = m_document->allFormats();
+ const QList<int> copy = formats.toList();
+ for (auto index : copy) {
+ QTextObject *object = m_document->objectForFormat(allFormats[index]);
if (object)
formats << object->formatIndex();
}
diff --git a/src/gui/text/qtexttable.cpp b/src/gui/text/qtexttable.cpp
index 2d5636e1d9..e4a3c2b915 100644
--- a/src/gui/text/qtexttable.cpp
+++ b/src/gui/text/qtexttable.cpp
@@ -824,7 +824,7 @@ void QTextTable::insertColumns(int pos, int num)
QVector<QTextLength> columnWidths = tfmt.columnWidthConstraints();
if (! columnWidths.isEmpty()) {
for (int i = num; i > 0; --i)
- columnWidths.insert(pos, columnWidths[qMax(0, pos-1)]);
+ columnWidths.insert(pos, columnWidths.at(qMax(0, pos - 1)));
}
tfmt.setColumnWidthConstraints (columnWidths);
QTextObject::setFormat(tfmt);
@@ -1046,11 +1046,12 @@ void QTextTable::mergeCells(int row, int column, int numRows, int numCols)
// find the position at which to insert the contents of the merged cells
QFragmentFindHelper helper(origCellPosition, p->fragmentMap());
- const auto it = std::lower_bound(d->cells.begin(), d->cells.end(), helper);
+ const auto begin = d->cells.cbegin();
+ const auto it = std::lower_bound(begin, d->cells.cend(), helper);
Q_ASSERT(it != d->cells.end());
Q_ASSERT(!(helper < *it));
Q_ASSERT(*it == cellFragment);
- const int insertCellIndex = it - d->cells.begin();
+ const int insertCellIndex = it - begin;
int insertFragment = d->cells.value(insertCellIndex + 1, d->fragment_end);
uint insertPos = p->fragmentMap().position(insertFragment);
@@ -1079,11 +1080,12 @@ void QTextTable::mergeCells(int row, int column, int numRows, int numCols)
if (firstCellIndex == -1) {
QFragmentFindHelper helper(pos, p->fragmentMap());
- const auto it = std::lower_bound(d->cells.begin(), d->cells.end(), helper);
+ const auto begin = d->cells.cbegin();
+ const auto it = std::lower_bound(begin, d->cells.cend(), helper);
Q_ASSERT(it != d->cells.end());
Q_ASSERT(!(helper < *it));
Q_ASSERT(*it == fragment);
- firstCellIndex = cellIndex = it - d->cells.begin();
+ firstCellIndex = cellIndex = it - begin;
}
++cellIndex;
@@ -1136,7 +1138,7 @@ void QTextTable::mergeCells(int row, int column, int numRows, int numCols)
}
}
- d->fragment_start = d->cells.first();
+ d->fragment_start = d->cells.constFirst();
fmt.setTableCellRowSpan(numRows);
fmt.setTableCellColumnSpan(numCols);
@@ -1212,9 +1214,9 @@ void QTextTable::splitCell(int row, int column, int numRows, int numCols)
for (int r = row + 1; r < row + rowSpan; ++r) {
// find the cell before which to insert the new cell markers
int gridIndex = r * d->nCols + column;
- QVector<int>::iterator it = std::upper_bound(d->cellIndices.begin(), d->cellIndices.end(), gridIndex);
- int cellIndex = it - d->cellIndices.begin();
- int fragment = d->cells.value(cellIndex, d->fragment_end);
+ const auto begin = d->cellIndices.cbegin();
+ const auto it = std::upper_bound(begin, d->cellIndices.cend(), gridIndex);
+ int fragment = d->cells.value(it - begin, d->fragment_end);
rowPositions[r - row] = p->fragmentMap().position(fragment);
}
diff --git a/src/gui/util/qgridlayoutengine.cpp b/src/gui/util/qgridlayoutengine.cpp
index 20bc7166ab..8ff2a3eeec 100644
--- a/src/gui/util/qgridlayoutengine.cpp
+++ b/src/gui/util/qgridlayoutengine.cpp
@@ -218,8 +218,9 @@ void QGridLayoutRowData::calculateGeometries(int start, int end, qreal targetSiz
qreal sumAvailable;
for (int i = 0; i < n; ++i) {
- if (stretches[start + i] > 0)
- sumStretches += stretches[start + i];
+ const int stretch = stretches.at(start + i);
+ if (stretch > 0)
+ sumStretches += stretch;
}
if (targetSize < totalBox.q_preferredSize) {
@@ -1034,19 +1035,19 @@ void QGridLayoutEngine::setGeometries(const QRectF &contentsGeometry, const QAbs
for (int i = q_items.count() - 1; i >= 0; --i) {
QGridLayoutItem *item = q_items.at(i);
- qreal x = q_xx[item->firstColumn()];
- qreal y = q_yy[item->firstRow()];
- qreal width = q_widths[item->lastColumn()];
- qreal height = q_heights[item->lastRow()];
+ qreal x = q_xx.at(item->firstColumn());
+ qreal y = q_yy.at(item->firstRow());
+ qreal width = q_widths.at(item->lastColumn());
+ qreal height = q_heights.at(item->lastRow());
if (item->columnSpan() != 1)
- width += q_xx[item->lastColumn()] - x;
+ width += q_xx.at(item->lastColumn()) - x;
if (item->rowSpan() != 1)
- height += q_yy[item->lastRow()] - y;
+ height += q_yy.at(item->lastRow()) - y;
const Qt::Alignment align = effectiveAlignment(item);
QRectF geom = item->geometryWithin(contentsGeometry.x() + x, contentsGeometry.y() + y,
- width, height, q_descents[item->lastRow()], align, m_snapToPixelGrid);
+ width, height, q_descents.at(item->lastRow()), align, m_snapToPixelGrid);
if (m_snapToPixelGrid) {
// x and y should already be rounded, but the call to geometryWithin() above might
// result in a geom with x,y at half-pixels (due to centering within the cell)
diff --git a/src/network/access/access.pri b/src/network/access/access.pri
index 94f8b7cbc0..ba0e448010 100644
--- a/src/network/access/access.pri
+++ b/src/network/access/access.pri
@@ -74,14 +74,4 @@ SOURCES += \
mac: LIBS_PRIVATE += -framework Security
-uikit {
- HEADERS += \
- access/qnetworkreplynsurlconnectionimpl_p.h
-
- OBJECTIVE_SOURCES += \
- access/qnetworkreplynsurlconnectionimpl.mm
-
- LIBS_PRIVATE += -framework Foundation
-}
-
include($$PWD/../../3rdparty/zlib_dependency.pri)
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index 56716cbe01..2f7be01078 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -331,7 +331,7 @@ bool QHttpNetworkConnectionChannel::ensureConnection()
priv->phase = QAuthenticatorPrivate::Start;
QString connectHost = connection->d_func()->hostName;
- qint16 connectPort = connection->d_func()->port;
+ quint16 connectPort = connection->d_func()->port;
#ifndef QT_NO_NETWORKPROXY
// HTTPS always use transparent proxy.
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index 1aa2d71bc5..9fee172283 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -56,10 +56,6 @@
#include "qnetworkreplydataimpl_p.h"
#include "qnetworkreplyfileimpl_p.h"
-#if defined(QT_PLATFORM_UIKIT) && defined(QT_NO_SSL)
-#include "qnetworkreplynsurlconnectionimpl_p.h"
-#endif
-
#include "QtCore/qbuffer.h"
#include "QtCore/qurl.h"
#include "QtCore/qvector.h"
@@ -1207,12 +1203,6 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
}
}
-// Use NSURLConnection for https on iOS when OpenSSL is disabled.
-#if defined(QT_PLATFORM_UIKIT) && defined(QT_NO_SSL)
- if (scheme == QLatin1String("https"))
- return new QNetworkReplyNSURLConnectionImpl(this, request, op, outgoingData);
-#endif
-
#ifndef QT_NO_HTTP
// Since Qt 5 we use the new QNetworkReplyHttpImpl
if (scheme == QLatin1String("http") || scheme == QLatin1String("preconnect-http")
diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h
index 7e8c399047..6df0b63ba7 100644
--- a/src/network/access/qnetworkaccessmanager.h
+++ b/src/network/access/qnetworkaccessmanager.h
@@ -94,6 +94,7 @@ public:
NotAccessible = 0,
Accessible = 1
};
+ Q_ENUM(NetworkAccessibility)
#endif
explicit QNetworkAccessManager(QObject *parent = Q_NULLPTR);
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index e27391f760..30f4bb26ce 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -296,7 +296,7 @@ qint64 QNetworkReplyHttpImpl::bytesAvailable() const
// if we load from cache device
if (d->cacheLoadDevice) {
- return QNetworkReply::bytesAvailable() + d->cacheLoadDevice->bytesAvailable() + d->downloadMultiBuffer.byteAmount();
+ return QNetworkReply::bytesAvailable() + d->cacheLoadDevice->bytesAvailable();
}
// zerocopy buffer
@@ -305,7 +305,7 @@ qint64 QNetworkReplyHttpImpl::bytesAvailable() const
}
// normal buffer
- return QNetworkReply::bytesAvailable() + d->downloadMultiBuffer.byteAmount();
+ return QNetworkReply::bytesAvailable();
}
bool QNetworkReplyHttpImpl::isSequential () const
@@ -329,12 +329,6 @@ qint64 QNetworkReplyHttpImpl::readData(char* data, qint64 maxlen)
if (d->cacheLoadDevice) {
// FIXME bytesdownloaded, position etc?
- // There is something already in the buffer we buffered before because the user did not read()
- // anything, so we read there first:
- if (!d->downloadMultiBuffer.isEmpty()) {
- return d->downloadMultiBuffer.read(data, maxlen);
- }
-
qint64 ret = d->cacheLoadDevice->read(data, maxlen);
return ret;
}
@@ -351,25 +345,14 @@ qint64 QNetworkReplyHttpImpl::readData(char* data, qint64 maxlen)
}
// normal buffer
- if (d->downloadMultiBuffer.isEmpty()) {
- if (d->state == d->Finished || d->state == d->Aborted)
- return -1;
- return 0;
- }
+ if (d->state == d->Finished || d->state == d->Aborted)
+ return -1;
- if (maxlen == 1) {
- // optimization for getChar()
- *data = d->downloadMultiBuffer.getChar();
- if (readBufferSize())
- emit readBufferFreed(1);
- return 1;
- }
-
- maxlen = qMin<qint64>(maxlen, d->downloadMultiBuffer.byteAmount());
- qint64 bytesRead = d->downloadMultiBuffer.read(data, maxlen);
+ qint64 wasBuffered = d->bytesBuffered;
+ d->bytesBuffered = 0;
if (readBufferSize())
- emit readBufferFreed(bytesRead);
- return bytesRead;
+ emit readBufferFreed(wasBuffered);
+ return 0;
}
void QNetworkReplyHttpImpl::setReadBufferSize(qint64 size)
@@ -387,12 +370,12 @@ bool QNetworkReplyHttpImpl::canReadLine () const
return true;
if (d->cacheLoadDevice)
- return d->cacheLoadDevice->canReadLine() || d->downloadMultiBuffer.canReadLine();
+ return d->cacheLoadDevice->canReadLine();
if (d->downloadZerocopyBuffer)
return memchr(d->downloadZerocopyBuffer + d->downloadBufferReadPosition, '\n', d->downloadBufferCurrentSize - d->downloadBufferReadPosition);
- return d->downloadMultiBuffer.canReadLine();
+ return false;
}
#ifndef QT_NO_SSL
@@ -444,6 +427,7 @@ QNetworkReplyHttpImplPrivate::QNetworkReplyHttpImplPrivate()
, resumeOffset(0)
, preMigrationDownloaded(-1)
, bytesDownloaded(0)
+ , bytesBuffered(0)
, downloadBufferReadPosition(0)
, downloadBufferCurrentSize(0)
, downloadZerocopyBuffer(0)
@@ -1047,10 +1031,11 @@ void QNetworkReplyHttpImplPrivate::replyDownloadData(QByteArray d)
cacheSaveDevice->write(item.constData(), item.size());
if (!isHttpRedirectResponse())
- downloadMultiBuffer.append(item);
+ buffer.append(item);
bytesWritten += item.size();
}
+ bytesBuffered += bytesWritten;
pendingDownloadDataCopy.clear();
QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader);
@@ -1823,9 +1808,8 @@ void QNetworkReplyHttpImplPrivate::_q_cacheLoadReadyRead()
// If there are still bytes available in the cacheLoadDevice then the user did not read
// in response to the readyRead() signal. This means we have to load from the cacheLoadDevice
// and buffer that stuff. This is needed to be able to properly emit finished() later.
- while (cacheLoadDevice->bytesAvailable() && !isHttpRedirectResponse()) {
- downloadMultiBuffer.append(cacheLoadDevice->readAll());
- }
+ while (cacheLoadDevice->bytesAvailable() && !isHttpRedirectResponse())
+ buffer.append(cacheLoadDevice->readAll());
if (cacheLoadDevice->isSequential()) {
// check if end and we can read the EOF -1
diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h
index 669258f15b..4aba915c7d 100644
--- a/src/network/access/qnetworkreplyhttpimpl_p.h
+++ b/src/network/access/qnetworkreplyhttpimpl_p.h
@@ -240,12 +240,11 @@ public:
quint64 resumeOffset;
qint64 preMigrationDownloaded;
- // Used for normal downloading. For "zero copy" the downloadZerocopyBuffer is used
- QByteDataBuffer downloadMultiBuffer;
QByteDataBuffer pendingDownloadData; // For signal compression
qint64 bytesDownloaded;
+ qint64 bytesBuffered;
- // only used when the "zero copy" style is used. Else downloadMultiBuffer is used.
+ // Only used when the "zero copy" style is used.
// Please note that the whole "zero copy" download buffer API is private right now. Do not use it.
qint64 downloadBufferReadPosition;
qint64 downloadBufferCurrentSize;
diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp
index d69d5983cb..54930a351a 100644
--- a/src/network/access/qnetworkreplyimpl.cpp
+++ b/src/network/access/qnetworkreplyimpl.cpp
@@ -184,17 +184,13 @@ void QNetworkReplyImplPrivate::_q_copyReadyRead()
break;
bytesToRead = qBound<qint64>(1, bytesToRead, copyDevice->bytesAvailable());
- QByteArray byteData;
- byteData.resize(bytesToRead);
- qint64 bytesActuallyRead = copyDevice->read(byteData.data(), byteData.size());
+ qint64 bytesActuallyRead = copyDevice->read(buffer.reserve(bytesToRead), bytesToRead);
if (bytesActuallyRead == -1) {
- byteData.clear();
+ buffer.chop(bytesToRead);
backendNotify(NotifyCopyFinished);
break;
}
-
- byteData.resize(bytesActuallyRead);
- readBuffer.append(byteData);
+ buffer.chop(bytesToRead - bytesActuallyRead);
if (!copyDevice->isSequential() && copyDevice->atEnd()) {
backendNotify(NotifyCopyFinished);
@@ -582,7 +578,7 @@ qint64 QNetworkReplyImplPrivate::nextDownstreamBlockSize() const
if (readBufferMaxSize == 0)
return DesiredBufferSize;
- return qMax<qint64>(0, readBufferMaxSize - readBuffer.byteAmount());
+ return qMax<qint64>(0, readBufferMaxSize - buffer.size());
}
void QNetworkReplyImplPrivate::initCacheSaveDevice()
@@ -624,7 +620,7 @@ void QNetworkReplyImplPrivate::initCacheSaveDevice()
}
// we received downstream data and send this to the cache
-// and to our readBuffer (which in turn gets read by the user of QNetworkReply)
+// and to our buffer (which in turn gets read by the user of QNetworkReply)
void QNetworkReplyImplPrivate::appendDownstreamData(QByteDataBuffer &data)
{
Q_Q(QNetworkReplyImpl);
@@ -641,7 +637,7 @@ void QNetworkReplyImplPrivate::appendDownstreamData(QByteDataBuffer &data)
if (cacheSaveDevice)
cacheSaveDevice->write(item.constData(), item.size());
- readBuffer.append(item);
+ buffer.append(item);
bytesWritten += item.size();
}
@@ -975,13 +971,6 @@ void QNetworkReplyImpl::close()
d->finished();
}
-bool QNetworkReplyImpl::canReadLine () const
-{
- Q_D(const QNetworkReplyImpl);
- return QNetworkReply::canReadLine() || d->readBuffer.canReadLine();
-}
-
-
/*!
Returns the number of bytes available for reading with
QIODevice::read(). The number of bytes available may grow until
@@ -996,14 +985,14 @@ qint64 QNetworkReplyImpl::bytesAvailable() const
return QNetworkReply::bytesAvailable() + maxAvail;
}
- return QNetworkReply::bytesAvailable() + d_func()->readBuffer.byteAmount();
+ return QNetworkReply::bytesAvailable();
}
void QNetworkReplyImpl::setReadBufferSize(qint64 size)
{
Q_D(QNetworkReplyImpl);
if (size > d->readBufferMaxSize &&
- size > d->readBuffer.byteAmount())
+ size > d->buffer.size())
d->backendNotify(QNetworkReplyImplPrivate::NotifyDownstreamReadyWrite);
QNetworkReply::setReadBufferSize(size);
@@ -1061,19 +1050,12 @@ qint64 QNetworkReplyImpl::readData(char *data, qint64 maxlen)
}
- if (d->readBuffer.isEmpty())
- return d->state == QNetworkReplyPrivate::Finished ? -1 : 0;
// FIXME what about "Aborted" state?
+ if (d->state == QNetworkReplyPrivate::Finished)
+ return -1;
d->backendNotify(QNetworkReplyImplPrivate::NotifyDownstreamReadyWrite);
- if (maxlen == 1) {
- // optimization for getChar()
- *data = d->readBuffer.getChar();
- return 1;
- }
-
- maxlen = qMin<qint64>(maxlen, d->readBuffer.byteAmount());
- return d->readBuffer.read(data, maxlen);
+ return 0;
}
/*!
diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h
index 156cb411c7..054cbcc3a7 100644
--- a/src/network/access/qnetworkreplyimpl_p.h
+++ b/src/network/access/qnetworkreplyimpl_p.h
@@ -81,7 +81,6 @@ public:
virtual void close() Q_DECL_OVERRIDE;
virtual qint64 bytesAvailable() const Q_DECL_OVERRIDE;
virtual void setReadBufferSize(qint64 size) Q_DECL_OVERRIDE;
- virtual bool canReadLine () const Q_DECL_OVERRIDE;
virtual qint64 readData(char *data, qint64 maxlen) Q_DECL_OVERRIDE;
virtual bool event(QEvent *) Q_DECL_OVERRIDE;
@@ -187,8 +186,6 @@ public:
QList<QNetworkProxy> proxyList;
#endif
- // Used for normal downloading. For "zero copy" the downloadBuffer is used
- QByteDataBuffer readBuffer;
qint64 bytesDownloaded;
qint64 lastBytesDownloaded;
qint64 bytesUploaded;
@@ -199,7 +196,7 @@ public:
State state;
- // only used when the "zero copy" style is used. Else readBuffer is used.
+ // Only used when the "zero copy" style is used.
// Please note that the whole "zero copy" download buffer API is private right now. Do not use it.
qint64 downloadBufferReadPosition;
qint64 downloadBufferCurrentSize;
diff --git a/src/network/access/qnetworkreplynsurlconnectionimpl.mm b/src/network/access/qnetworkreplynsurlconnectionimpl.mm
deleted file mode 100644
index 25b79e3347..0000000000
--- a/src/network/access/qnetworkreplynsurlconnectionimpl.mm
+++ /dev/null
@@ -1,454 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtNetwork module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qnetworkreplynsurlconnectionimpl_p.h"
-
-#include "QtCore/qdatetime.h"
-#include <QtCore/qcoreapplication.h>
-#include <QtCore/qdebug.h>
-#include <Foundation/Foundation.h>
-
-QT_BEGIN_NAMESPACE
-
-// Network reply implementation using NSUrlConnection.
-//
-// Class/object structure:
-//
-// QNetworkReplyNSURLConnectionImpl
-// |- QNetworkReplyNSURLConnectionImplPrivate
-// |- (bytes read)
-// |- (QIODevice and CFStream for async POST data transfer)
-// |- NSURLConnection
-// |- QtNSURLConnectionDelegate <NSURLConnectionDataDelegate>
-// |- NSURLResponse/NSHTTPURLResponse
-// |- (response data)
-//
-// The main entry point is the QNetworkReplyNSURLConnectionImpl constructor, which
-// receives a network request from QNetworkAccessManager. The constructor
-// creates a NSURLRequest and initiates a NSURLConnection with a QtNSURLConnectionDelegate.
-// The delegate callbacks are then called asynchronously as the request completes.
-//
-
-@class QtNSURLConnectionDelegate;
-class QNetworkReplyNSURLConnectionImplPrivate: public QNetworkReplyPrivate
-{
-public:
- QNetworkReplyNSURLConnectionImplPrivate();
- virtual ~QNetworkReplyNSURLConnectionImplPrivate();
-
- Q_DECLARE_PUBLIC(QNetworkReplyNSURLConnectionImpl)
- NSURLConnection * urlConnection;
- QtNSURLConnectionDelegate *urlConnectionDelegate;
- qint64 bytesRead;
-
- // Sequental outgiong data streaming
- QIODevice *outgoingData;
- CFReadStreamRef readStream;
- CFWriteStreamRef writeStream;
- CFIndex transferBufferSize;
-
- // Forwarding functions to the public class.
- void setFinished();
- void setHeader(QNetworkRequest::KnownHeaders header, const QVariant &value);
- void setRawHeader(const QByteArray &headerName, const QByteArray &value);
- void setError(QNetworkReply::NetworkError errorCode, const QString &errorString);
- void setAttribute(QNetworkRequest::Attribute code, const QVariant &value);
-};
-
-@interface QtNSURLConnectionDelegate : NSObject
-{
- NSURLResponse *response;
- NSMutableData *responseData;
- QNetworkReplyNSURLConnectionImplPrivate * replyprivate;
-}
-
-- (id)initWithQNetworkReplyNSURLConnectionImplPrivate:(QNetworkReplyNSURLConnectionImplPrivate *)a_replyPrivate ;
-- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
-- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError*)error;
-- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse*)response;
-- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData*)data;
-- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten
- totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite;
-- (NSCachedURLResponse*)connection:(NSURLConnection*)connection willCacheResponse:(NSCachedURLResponse*)cachedResponse;
-- (NSURLRequest*)connection:(NSURLConnection*)connection willSendRequest:(NSURLRequest*)request redirectResponse:(NSURLResponse*)redirectResponse;
-- (void)connectionDidFinishLoading:(NSURLConnection*)connection;
-- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection*)connection;
-
-@end
-
-QNetworkReplyNSURLConnectionImplPrivate::QNetworkReplyNSURLConnectionImplPrivate()
- : QNetworkReplyPrivate()
- , urlConnection(0)
- , urlConnectionDelegate(0)
- , bytesRead(0)
- , readStream(0)
- , writeStream(0)
- , transferBufferSize(4096)
-{
-}
-
-QNetworkReplyNSURLConnectionImplPrivate::~QNetworkReplyNSURLConnectionImplPrivate()
-{
- [urlConnection cancel];
- [urlConnection release];
- [urlConnectionDelegate release];
- if (readStream)
- CFRelease(readStream);
- if (writeStream)
- CFRelease(writeStream);
-}
-
-void QNetworkReplyNSURLConnectionImplPrivate::setFinished()
-{
- q_func()->setFinished(true);
- QMetaObject::invokeMethod(q_func(), "finished", Qt::QueuedConnection);
-}
-
-void QNetworkReplyNSURLConnectionImplPrivate::setHeader(QNetworkRequest::KnownHeaders header, const QVariant &value)
-{
- q_func()->setHeader(header, value);
-}
-
-void QNetworkReplyNSURLConnectionImplPrivate::setRawHeader(const QByteArray &headerName, const QByteArray &value)
-{
- q_func()->setRawHeader(headerName, value);
-}
-
-void QNetworkReplyNSURLConnectionImplPrivate::setError(QNetworkReply::NetworkError errorCode, const QString &errorString)
-{
- q_func()->setError(errorCode, errorString);
-}
-
-void QNetworkReplyNSURLConnectionImplPrivate::setAttribute(QNetworkRequest::Attribute code, const QVariant &value)
-{
- q_func()->setAttribute(code, value);
-}
-
-void QNetworkReplyNSURLConnectionImpl::readyReadOutgoingData()
-{
- Q_D(QNetworkReplyNSURLConnectionImpl);
- int bytesRead = 0;
- do {
- char data[d->transferBufferSize];
- bytesRead = d->outgoingData->read(data, d->transferBufferSize);
- if (bytesRead <= 0)
- break;
- CFIndex bytesWritten = CFWriteStreamWrite(d->writeStream, reinterpret_cast<unsigned char *>(data), bytesRead);
- if (bytesWritten != bytesRead) {
- CFErrorRef err = CFWriteStreamCopyError(d->writeStream);
- qWarning() << "QNetworkReplyNSURLConnectionImpl: CFWriteStreamWrite error"
- << (err ? QString::number(CFErrorGetCode(err)) : QStringLiteral(""));
- }
- } while (bytesRead > 0);
-
- if (d->outgoingData->atEnd())
- CFWriteStreamClose(d->writeStream);
-}
-
-@interface QtNSURLConnectionDelegate ()
-
-@property (nonatomic, retain) NSURLResponse* response;
-@property (nonatomic, retain) NSMutableData* responseData;
-
-@end
-
-@implementation QtNSURLConnectionDelegate
-
-@synthesize response;
-@synthesize responseData;
-
-- (id)initWithQNetworkReplyNSURLConnectionImplPrivate:(QNetworkReplyNSURLConnectionImplPrivate *)a_replyPrivate
-{
- if (self = [super init])
- replyprivate = a_replyPrivate;
- return self;
-}
-
-- (void)dealloc
-{
- [response release];
- [responseData release];
- [super dealloc];
-}
-
-- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
-{
- Q_UNUSED(connection)
- Q_UNUSED(challenge)
-
- if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
- SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
- SecTrustResultType resultType;
- SecTrustEvaluate(serverTrust, &resultType);
- if (resultType == kSecTrustResultUnspecified) {
- // All good
- [challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge];
- } else if (resultType == kSecTrustResultRecoverableTrustFailure) {
- // Certificate verification error, ask user
- // ### TODO actually ask user
- // (test site: https://testssl-expire.disig.sk/index.en.html)
- qWarning() << "QNetworkReplyNSURLConnection: Certificate verification error handlig is"
- << "not implemented. Connection will time out.";
- } else {
- // other error, which the default handler will handle
- [challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge];
- }
- }
-
- [challenge.sender performDefaultHandlingForAuthenticationChallenge:challenge];
-}
-
-- (void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error
-{
- Q_UNUSED(connection)
-
- QNetworkReply::NetworkError qtError = QNetworkReply::UnknownNetworkError;
- if ([[error domain] isEqualToString:NSURLErrorDomain]) {
- switch ([error code]) {
- case NSURLErrorTimedOut: qtError = QNetworkReply::TimeoutError; break;
- case NSURLErrorUnsupportedURL: qtError = QNetworkReply::ProtocolUnknownError; break;
- case NSURLErrorCannotFindHost: qtError = QNetworkReply::HostNotFoundError; break;
- case NSURLErrorCannotConnectToHost: qtError = QNetworkReply::ConnectionRefusedError; break;
- case NSURLErrorNetworkConnectionLost: qtError = QNetworkReply::NetworkSessionFailedError; break;
- case NSURLErrorDNSLookupFailed: qtError = QNetworkReply::HostNotFoundError; break;
- case NSURLErrorNotConnectedToInternet: qtError = QNetworkReply::NetworkSessionFailedError; break;
- case NSURLErrorUserAuthenticationRequired: qtError = QNetworkReply::AuthenticationRequiredError; break;
- default: break;
- }
- }
-
- replyprivate->setError(qtError, QString::fromNSString([error localizedDescription]));
- replyprivate->setFinished();
-}
-
-- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)aResponse
-{
- Q_UNUSED(connection)
- self.response = aResponse;
- self.responseData = [NSMutableData data];
-
- // copy headers
- if ([aResponse isKindOfClass:[NSHTTPURLResponse class]]) {
- NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)aResponse;
- NSDictionary *headers = [httpResponse allHeaderFields];
- for (NSString *key in headers) {
- NSString *value = [headers objectForKey:key];
- replyprivate->setRawHeader(QString::fromNSString(key).toUtf8(), QString::fromNSString(value).toUtf8());
- }
-
- int code = [httpResponse statusCode];
- replyprivate->setAttribute(QNetworkRequest::HttpStatusCodeAttribute, code);
- } else {
- if ([aResponse expectedContentLength] != NSURLResponseUnknownLength)
- replyprivate->setHeader(QNetworkRequest::ContentLengthHeader, [aResponse expectedContentLength]);
- }
-
- QMetaObject::invokeMethod(replyprivate->q_func(), "metaDataChanged", Qt::QueuedConnection);
-}
-
-- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data
-{
- Q_UNUSED(connection)
- [responseData appendData:data];
-
- if ([response expectedContentLength] != NSURLResponseUnknownLength) {
- QMetaObject::invokeMethod(replyprivate->q_func(), "downloadProgress", Qt::QueuedConnection,
- Q_ARG(qint64, qint64([responseData length] + replyprivate->bytesRead)),
- Q_ARG(qint64, qint64([response expectedContentLength])));
- }
-
- QMetaObject::invokeMethod(replyprivate->q_func(), "readyRead", Qt::QueuedConnection);
-}
-
-- (void)connection:(NSURLConnection*)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten
- totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite
-{
- Q_UNUSED(connection)
- Q_UNUSED(bytesWritten)
- QMetaObject::invokeMethod(replyprivate->q_func(), "uploadProgress", Qt::QueuedConnection,
- Q_ARG(qint64, qint64(totalBytesWritten)),
- Q_ARG(qint64, qint64(totalBytesExpectedToWrite)));
-}
-
-- (NSCachedURLResponse*)connection:(NSURLConnection*)connection willCacheResponse:(NSCachedURLResponse*)cachedResponse
-{
- Q_UNUSED(connection)
- return cachedResponse;
-}
-
-- (NSURLRequest*)connection:(NSURLConnection*)connection willSendRequest:(NSURLRequest*)request redirectResponse:(NSURLResponse*)redirectResponse
-{
- Q_UNUSED(connection)
- Q_UNUSED(redirectResponse)
- return request;
-}
-
-- (void)connectionDidFinishLoading:(NSURLConnection*)connection
-{
- Q_UNUSED(connection)
- replyprivate->setFinished();
-}
-
-- (BOOL)connectionShouldUseCredentialStorage:(NSURLConnection*)connection
-{
- Q_UNUSED(connection)
- return YES;
-}
-
-@end
-
-QNetworkReplyNSURLConnectionImpl::~QNetworkReplyNSURLConnectionImpl()
-{
-}
-
-QNetworkReplyNSURLConnectionImpl::QNetworkReplyNSURLConnectionImpl(QObject *parent,
- const QNetworkRequest &request, const QNetworkAccessManager::Operation operation, QIODevice* outgoingData)
- : QNetworkReply(*new QNetworkReplyNSURLConnectionImplPrivate(), parent)
-{
- setRequest(request);
- setUrl(request.url());
- setOperation(operation);
- QNetworkReply::open(QIODevice::ReadOnly);
-
- QNetworkReplyNSURLConnectionImplPrivate *d = (QNetworkReplyNSURLConnectionImplPrivate*) d_func();
-
- QUrl url = request.url();
- if (url.host() == QLatin1String("localhost"))
- url.setHost(QString());
-
- if (url.path().isEmpty())
- url.setPath(QLatin1String("/"));
- setUrl(url);
-
- // Create a NSMutableURLRequest from QNetworkRequest
- NSMutableURLRequest *nsRequest = [NSMutableURLRequest requestWithURL:request.url().toNSURL()
- cachePolicy:NSURLRequestUseProtocolCachePolicy
- timeoutInterval:60.0];
- // copy headers
- const auto headers = request.rawHeaderList();
- for (const QByteArray &header : headers) {
- QByteArray headerValue = request.rawHeader(header);
- [nsRequest addValue:QString::fromUtf8(headerValue).toNSString()
- forHTTPHeaderField:QString::fromUtf8(header).toNSString()];
- }
-
- if (operation == QNetworkAccessManager::GetOperation)
- [nsRequest setHTTPMethod:@"GET"];
- else if (operation == QNetworkAccessManager::PostOperation)
- [nsRequest setHTTPMethod:@"POST"];
- else if (operation == QNetworkAccessManager::PutOperation)
- [nsRequest setHTTPMethod:@"PUT"];
- else if (operation == QNetworkAccessManager::DeleteOperation)
- [nsRequest setHTTPMethod:@"DELETE"];
- else
- qWarning() << "QNetworkReplyNSURLConnection: Unsupported netork operation" << operation;
-
- if (outgoingData) {
- d->outgoingData = outgoingData;
- if (outgoingData->isSequential()) {
- // set up streaming from outgoingData iodevice to request
- CFStreamCreateBoundPair(kCFAllocatorDefault, &d->readStream, &d->writeStream, d->transferBufferSize);
- CFWriteStreamOpen(d->writeStream);
- [nsRequest setHTTPBodyStream:reinterpret_cast<NSInputStream *>(d->readStream)];
- connect(outgoingData, SIGNAL(readyRead()), this, SLOT(readyReadOutgoingData()));
- readyReadOutgoingData();
- } else {
- // move all data at once
- QByteArray data = outgoingData->readAll();
- [nsRequest setHTTPBody:[NSData dataWithBytes:data.constData() length:data.length()]];
- }
- }
-
- // Create connection
- d->urlConnectionDelegate = [[QtNSURLConnectionDelegate alloc] initWithQNetworkReplyNSURLConnectionImplPrivate:d];
- d->urlConnection = [[NSURLConnection alloc] initWithRequest:nsRequest delegate:d->urlConnectionDelegate];
- if (!d->urlConnection) {
- // ### what type of error is an initWithRequest fail?
- setError(QNetworkReply::ProtocolUnknownError, QStringLiteral("QNetworkReplyNSURLConnection internal error"));
- }
-}
-
-void QNetworkReplyNSURLConnectionImpl::close()
-{
- // No-op? Network ops should continue (especially POSTs)
- QNetworkReply::close();
-}
-
-void QNetworkReplyNSURLConnectionImpl::abort()
-{
- Q_D(QNetworkReplyNSURLConnectionImpl);
- [d->urlConnection cancel];
- QNetworkReply::close();
-}
-
-qint64 QNetworkReplyNSURLConnectionImpl::bytesAvailable() const
-{
- Q_D(const QNetworkReplyNSURLConnectionImpl);
- qint64 available = QNetworkReply::bytesAvailable() +
- [[d->urlConnectionDelegate responseData] length];
- return available;
-}
-
-bool QNetworkReplyNSURLConnectionImpl::isSequential() const
-{
- return true;
-}
-
-qint64 QNetworkReplyNSURLConnectionImpl::size() const
-{
- Q_D(const QNetworkReplyNSURLConnectionImpl);
- return [[d->urlConnectionDelegate responseData] length] + d->bytesRead;
-}
-
-/*!
- \internal
-*/
-qint64 QNetworkReplyNSURLConnectionImpl::readData(char *data, qint64 maxlen)
-{
- Q_D(QNetworkReplyNSURLConnectionImpl);
- qint64 dataSize = [[d->urlConnectionDelegate responseData] length];
- qint64 canRead = qMin(maxlen, dataSize);
- const char *sourceBase = static_cast<const char *>([[d->urlConnectionDelegate responseData] bytes]);
- memcpy(data, sourceBase, canRead);
- [[d->urlConnectionDelegate responseData] replaceBytesInRange:NSMakeRange(0, canRead) withBytes:NULL length:0];
- d->bytesRead += canRead;
- return canRead;
-}
-
-QT_END_NAMESPACE
diff --git a/src/network/access/qnetworkreplynsurlconnectionimpl_p.h b/src/network/access/qnetworkreplynsurlconnectionimpl_p.h
deleted file mode 100644
index c948e66629..0000000000
--- a/src/network/access/qnetworkreplynsurlconnectionimpl_p.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtNetwork module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QNETWORKREPLYNSURLCONNECTIONIMPL_H
-#define QNETWORKREPLYNSURLCONNECTIONIMPL_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists for the convenience
-// of the Network Access API. This header file may change from
-// version to version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qnetworkreply.h"
-#include "qnetworkreply_p.h"
-#include "qnetworkaccessmanager.h"
-#include <QFile>
-#include <private/qabstractfileengine_p.h>
-
-QT_BEGIN_NAMESPACE
-
-
-class QNetworkReplyNSURLConnectionImplPrivate;
-class QNetworkReplyNSURLConnectionImpl: public QNetworkReply
-{
- Q_OBJECT
-public:
- QNetworkReplyNSURLConnectionImpl(QObject *parent, const QNetworkRequest &req, const QNetworkAccessManager::Operation op, QIODevice* outgoingData);
- virtual ~QNetworkReplyNSURLConnectionImpl();
- virtual void abort();
-
- // reimplemented from QNetworkReply
- virtual void close();
- virtual qint64 bytesAvailable() const;
- virtual bool isSequential () const;
- qint64 size() const;
-
- virtual qint64 readData(char *data, qint64 maxlen);
-public Q_SLOTS:
- void readyReadOutgoingData();
-
- Q_DECLARE_PRIVATE(QNetworkReplyNSURLConnectionImpl)
-};
-
-QT_END_NAMESPACE
-
-#endif // QNetworkReplyNSURLConnectionImpl_H
diff --git a/src/network/kernel/qdnslookup_unix.cpp b/src/network/kernel/qdnslookup_unix.cpp
index 35981a2f2c..41038dc8da 100644
--- a/src/network/kernel/qdnslookup_unix.cpp
+++ b/src/network/kernel/qdnslookup_unix.cpp
@@ -47,7 +47,9 @@
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
-#include <arpa/nameser_compat.h>
+#if !defined(Q_OS_OPENBSD)
+# include <arpa/nameser_compat.h>
+#endif
#include <resolv.h>
#if defined(__GNU_LIBRARY__) && !defined(__UCLIBC__)
@@ -58,6 +60,9 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_LIBRARY
+#if defined(Q_OS_OPENBSD)
+typedef struct __res_state* res_state;
+#endif
typedef int (*dn_expand_proto)(const unsigned char *, const unsigned char *, const unsigned char *, char *, int);
static dn_expand_proto local_dn_expand = 0;
typedef void (*res_nclose_proto)(res_state);
diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp
index 757a6ad0b0..681c81d6eb 100644
--- a/src/network/kernel/qhostaddress.cpp
+++ b/src/network/kernel/qhostaddress.cpp
@@ -115,14 +115,13 @@ public:
QString ipString;
QString scopeId;
- quint32 a; // IPv4 address
union {
Q_IPV6ADDR a6; // IPv6 address
struct { quint64 c[2]; } a6_64;
struct { quint32 c[4]; } a6_32;
};
- QAbstractSocket::NetworkLayerProtocol protocol;
-
+ quint32 a; // IPv4 address
+ qint8 protocol;
bool isParsed;
friend class QHostAddress;
@@ -735,7 +734,7 @@ quint32 QHostAddress::toIPv4Address(bool *ok) const
QAbstractSocket::NetworkLayerProtocol QHostAddress::protocol() const
{
QT_ENSURE_PARSED(this);
- return d->protocol;
+ return QAbstractSocket::NetworkLayerProtocol(d->protocol);
}
/*!
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp
index b3e456be69..7ef9d7f26b 100644
--- a/src/network/socket/qnativesocketengine_unix.cpp
+++ b/src/network/socket/qnativesocketengine_unix.cpp
@@ -560,7 +560,9 @@ int QNativeSocketEnginePrivate::nativeAccept()
setError(QAbstractSocket::SocketResourceError, NotSocketErrorString);
break;
case EPROTONOSUPPORT:
+#if !defined(Q_OS_OPENBSD)
case EPROTO:
+#endif
case EAFNOSUPPORT:
case EINVAL:
setError(QAbstractSocket::UnsupportedSocketOperationError, ProtocolUnsupportedErrorString);
@@ -900,7 +902,9 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxS
if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_RECVIF
&& cmsgptr->cmsg_len >= CMSG_LEN(sizeof(sockaddr_dl))) {
sockaddr_dl *sdl = reinterpret_cast<sockaddr_dl *>(CMSG_DATA(cmsgptr));
-
+# if defined(Q_OS_OPENBSD)
+# define LLINDEX(s) ((s)->sdl_index)
+# endif
header->ifindex = LLINDEX(sdl);
}
# endif
diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp
index 181c49f200..dd43615f98 100644
--- a/src/network/socket/qnativesocketengine_winrt.cpp
+++ b/src/network/socket/qnativesocketengine_winrt.cpp
@@ -337,7 +337,7 @@ bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port)
d->socketState = QAbstractSocket::ConnectingState;
hr = QEventDispatcherWinRT::runOnXamlThread([d]() {
return d->connectOp->put_Completed(Callback<IAsyncActionCompletedHandler>(
- d, &QNativeSocketEnginePrivate::handleConnectToHost).Get());
+ d, &QNativeSocketEnginePrivate::handleConnectOpFinished).Get());
});
Q_ASSERT_SUCCEEDED(hr);
@@ -477,7 +477,10 @@ void QNativeSocketEngine::close()
hr = socket3->CancelIOAsync(&action);
Q_ASSERT_SUCCEEDED(hr);
hr = QWinRTFunctions::await(action);
- Q_ASSERT_SUCCEEDED(hr);
+ // If there is no pending IO (no read established before) the function will fail with
+ // "function was called at an unexpected time" which is fine.
+ if (hr != E_ILLEGAL_METHOD_CALL)
+ Q_ASSERT_SUCCEEDED(hr);
return S_OK;
});
Q_ASSERT_SUCCEEDED(hr);
@@ -759,7 +762,7 @@ bool QNativeSocketEngine::waitForWrite(int msecs, bool *timedOut)
if (d->socketState == QAbstractSocket::ConnectingState) {
HRESULT hr = QWinRTFunctions::await(d->connectOp, QWinRTFunctions::ProcessMainThreadEvents);
if (SUCCEEDED(hr)) {
- d->handleConnectionEstablished(d->connectOp.Get());
+ d->handleConnectOpFinished(d->connectOp.Get(), Completed);
return true;
}
}
@@ -1214,38 +1217,32 @@ HRESULT QNativeSocketEnginePrivate::handleClientConnection(IStreamSocketListener
return S_OK;
}
-HRESULT QNativeSocketEnginePrivate::handleConnectToHost(IAsyncAction *action, AsyncStatus)
-{
- handleConnectionEstablished(action);
- return S_OK;
-}
-
-void QNativeSocketEnginePrivate::handleConnectionEstablished(IAsyncAction *action)
+HRESULT QNativeSocketEnginePrivate::handleConnectOpFinished(IAsyncAction *action, AsyncStatus)
{
Q_Q(QNativeSocketEngine);
if (wasDeleted || !connectOp) // Protect against a late callback
- return;
+ return S_OK;
HRESULT hr = action->GetResults();
switch (hr) {
case 0x8007274c: // A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString);
socketState = QAbstractSocket::UnconnectedState;
- break;
+ return S_OK;
case 0x80072751: // A socket operation was attempted to an unreachable host.
setError(QAbstractSocket::HostNotFoundError, HostUnreachableErrorString);
socketState = QAbstractSocket::UnconnectedState;
- break;
+ return S_OK;
case 0x8007274d: // No connection could be made because the target machine actively refused it.
setError(QAbstractSocket::ConnectionRefusedError, ConnectionRefusedErrorString);
socketState = QAbstractSocket::UnconnectedState;
- break;
+ return S_OK;
default:
if (FAILED(hr)) {
setError(QAbstractSocket::UnknownSocketError, UnknownSocketErrorString);
socketState = QAbstractSocket::UnconnectedState;
+ return S_OK;
}
- break;
}
// The callback might be triggered several times if we do not cancel/reset it here
@@ -1267,13 +1264,14 @@ void QNativeSocketEnginePrivate::handleConnectionEstablished(IAsyncAction *actio
emit q->connectionReady();
if (socketType != QAbstractSocket::TcpSocket)
- return;
+ return S_OK;
// Delay the reader so that the SSL socket can upgrade
if (sslSocket)
QObject::connect(qobject_cast<QSslSocket *>(sslSocket), &QSslSocket::encrypted, q, &QNativeSocketEngine::establishRead);
else
q->establishRead();
+ return S_OK;
}
HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *asyncInfo, AsyncStatus status)
diff --git a/src/network/socket/qnativesocketengine_winrt_p.h b/src/network/socket/qnativesocketengine_winrt_p.h
index 325e4965e6..5b76c2d223 100644
--- a/src/network/socket/qnativesocketengine_winrt_p.h
+++ b/src/network/socket/qnativesocketengine_winrt_p.h
@@ -220,8 +220,7 @@ private:
ABI::Windows::Networking::Sockets::IDatagramSocketMessageReceivedEventArgs *args);
HRESULT handleClientConnection(ABI::Windows::Networking::Sockets::IStreamSocketListener *tcpListener,
ABI::Windows::Networking::Sockets::IStreamSocketListenerConnectionReceivedEventArgs *args);
- HRESULT handleConnectToHost(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus);
- void handleConnectionEstablished(ABI::Windows::Foundation::IAsyncAction *action);
+ HRESULT handleConnectOpFinished(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus);
HRESULT handleReadyRead(ABI::Windows::Foundation::IAsyncOperationWithProgress<ABI::Windows::Storage::Streams::IBuffer *, UINT32> *asyncInfo, ABI::Windows::Foundation::AsyncStatus);
};
diff --git a/src/network/socket/qsocks5socketengine.cpp b/src/network/socket/qsocks5socketengine.cpp
index 1870091693..ee3e0d9f0e 100644
--- a/src/network/socket/qsocks5socketengine.cpp
+++ b/src/network/socket/qsocks5socketengine.cpp
@@ -1118,7 +1118,9 @@ bool QSocks5SocketEngine::connectInternal()
}
if (d->socketState != QAbstractSocket::ConnectingState) {
- if (d->socks5State == QSocks5SocketEnginePrivate::Uninitialized) {
+ if (d->socks5State == QSocks5SocketEnginePrivate::Uninitialized
+ // We may have new auth credentials since an earlier failure:
+ || d->socks5State == QSocks5SocketEnginePrivate::AuthenticatingError) {
setState(QAbstractSocket::ConnectingState);
//limit buffer in internal socket, data is buffered in the external socket under application control
d->data->controlSocket->setReadBufferSize(65536);
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index 75a38db5f9..580b0fbdde 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -2642,7 +2642,8 @@ QList<QByteArray> QSslSocketPrivate::unixRootCertDirectories()
<< "/var/ssl/certs/" // AIX
<< "/usr/local/ssl/certs/" // Solaris
<< "/etc/openssl/certs/" // BlackBerry
- << "/opt/openssl/certs/"; // HP-UX
+ << "/opt/openssl/certs/" // HP-UX
+ << "/etc/ssl/"; // OpenBSD
}
/*!
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
index c1ea10aefb..35d7654730 100644
--- a/src/network/ssl/qsslsocket_openssl.cpp
+++ b/src/network/ssl/qsslsocket_openssl.cpp
@@ -1344,8 +1344,12 @@ void QSslSocketBackendPrivate::_q_caRootLoaded(QSslCertificate cert, QSslCertifi
if (plainSocket)
plainSocket->resume();
paused = false;
- if (checkSslErrors() && ssl)
+ if (checkSslErrors() && ssl) {
+ bool willClose = (autoStartHandshake && pendingClose);
continueHandshake();
+ if (!willClose)
+ transmit();
+ }
}
class QWindowsCaRootFetcherThread : public QThread
diff --git a/src/platformheaders/doc/src/qtplatformheaders.qdoc b/src/platformheaders/doc/src/qtplatformheaders.qdoc
index 745edf7983..6eb7b27cce 100644
--- a/src/platformheaders/doc/src/qtplatformheaders.qdoc
+++ b/src/platformheaders/doc/src/qtplatformheaders.qdoc
@@ -80,6 +80,19 @@
\sa QXcbWindowFunctions QWindowsWindowFunctions
+ \section1 Getting Started
+
+ To include the definitions of the module's functions and classes, use the following directives:
+ \code
+ #include <QtPlatformHeaders/QWindowsWindowFunctions>
+ #include <QtPlatformHeaders/QXcbWindowFunctions>
+ \endcode
+
+ As the module is header-only, no further modifications to the .pro files are required to use it.
+
+ \note The module name (\c QtPlatformHeaders) must appear in the \c #include directive.
+ \note It is not necessary to enclose the code in \c #ifdef directives depending on platform.
+
\section1 API Reference
\list
\li \l{Qt Platform Headers C++ Classes}{C++ Classes}
diff --git a/src/platformsupport/devicediscovery/devicediscovery.pri b/src/platformsupport/devicediscovery/devicediscovery.pri
index 1ac25da901..9829ae88ba 100644
--- a/src/platformsupport/devicediscovery/devicediscovery.pri
+++ b/src/platformsupport/devicediscovery/devicediscovery.pri
@@ -1,18 +1,14 @@
HEADERS += $$PWD/qdevicediscovery_p.h
-linux {
- contains(QT_CONFIG, libudev) {
- SOURCES += $$PWD/qdevicediscovery_udev.cpp
- HEADERS += $$PWD/qdevicediscovery_udev_p.h
- INCLUDEPATH += $$QMAKE_INCDIR_LIBUDEV
- LIBS_PRIVATE += $$QMAKE_LIBS_LIBUDEV
- } else: contains(QT_CONFIG, evdev) {
- SOURCES += $$PWD/qdevicediscovery_static.cpp
- HEADERS += $$PWD/qdevicediscovery_static_p.h
- } else {
- SOURCES += $$PWD/qdevicediscovery_dummy.cpp
- HEADERS += $$PWD/qdevicediscovery_dummy_p.h
- }
+contains(QT_CONFIG, libudev) {
+ SOURCES += $$PWD/qdevicediscovery_udev.cpp
+ HEADERS += $$PWD/qdevicediscovery_udev_p.h
+ INCLUDEPATH += $$QMAKE_INCDIR_LIBUDEV
+ LIBS_PRIVATE += $$QMAKE_LIBS_LIBUDEV
+} else: contains(QT_CONFIG, evdev) {
+ SOURCES += $$PWD/qdevicediscovery_static.cpp
+ HEADERS += $$PWD/qdevicediscovery_static_p.h
} else {
SOURCES += $$PWD/qdevicediscovery_dummy.cpp
+ HEADERS += $$PWD/qdevicediscovery_dummy_p.h
}
diff --git a/src/platformsupport/eglconvenience/qeglconvenience.cpp b/src/platformsupport/eglconvenience/qeglconvenience.cpp
index f8efd105bc..da41cfeabf 100644
--- a/src/platformsupport/eglconvenience/qeglconvenience.cpp
+++ b/src/platformsupport/eglconvenience/qeglconvenience.cpp
@@ -587,6 +587,10 @@ int q_screenDepthFromFb(int framebufferDevice)
qreal q_refreshRateFromFb(int framebufferDevice)
{
+#ifndef Q_OS_LINUX
+ Q_UNUSED(framebufferDevice)
+#endif
+
static qreal rate = 0;
#ifdef Q_OS_LINUX
diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp
index 36de1e0c69..c7f6dd2740 100644
--- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp
+++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp
@@ -60,7 +60,7 @@ Q_LOGGING_CATEGORY(qLcEvdevKeyMap, "qt.qpa.input.keymap")
#include "qevdevkeyboard_defaultmap_p.h"
QEvdevKeyboardHandler::QEvdevKeyboardHandler(const QString &device, int fd, bool disableZap, bool enableCompose, const QString &keymapFile)
- : m_device(device), m_fd(fd),
+ : m_device(device), m_fd(fd), m_notify(Q_NULLPTR),
m_modifiers(0), m_composing(0), m_dead_unicode(0xffff),
m_no_zap(disableZap), m_do_compose(enableCompose),
m_keymap(0), m_keymap_size(0), m_keycompose(0), m_keycompose_size(0)
@@ -75,9 +75,8 @@ QEvdevKeyboardHandler::QEvdevKeyboardHandler(const QString &device, int fd, bool
unloadKeymap();
// socket notifier for events on the keyboard device
- QSocketNotifier *notifier;
- notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
- connect(notifier, SIGNAL(activated(int)), this, SLOT(readKeycode()));
+ m_notify = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
+ connect(m_notify, SIGNAL(activated(int)), this, SLOT(readKeycode()));
}
QEvdevKeyboardHandler::~QEvdevKeyboardHandler()
@@ -162,6 +161,14 @@ void QEvdevKeyboardHandler::readKeycode()
} else if (result < 0) {
if (errno != EINTR && errno != EAGAIN) {
qErrnoWarning(errno, "evdevkeyboard: Could not read from input device");
+ // If the device got disconnected, stop reading, otherwise we get flooded
+ // by the above error over and over again.
+ if (errno == ENODEV) {
+ delete m_notify;
+ m_notify = Q_NULLPTR;
+ qt_safe_close(m_fd);
+ m_fd = -1;
+ }
return;
}
} else {
diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h
index 89fa879115..b94323fcbb 100644
--- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h
+++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h
@@ -57,6 +57,8 @@
QT_BEGIN_NAMESPACE
+class QSocketNotifier;
+
namespace QEvdevKeyboardMap {
const quint32 FileMagic = 0x514d4150; // 'QMAP'
@@ -186,6 +188,7 @@ private:
QString m_device;
int m_fd;
+ QSocketNotifier *m_notify;
// keymap handling
quint8 m_modifiers;
diff --git a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp
index 382b9b1514..d5ea04bee8 100644
--- a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp
+++ b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp
@@ -111,9 +111,8 @@ QEvdevMouseHandler::QEvdevMouseHandler(const QString &device, int fd, bool abs,
m_abs = getHardwareMaximum();
// socket notifier for events on the mouse device
- QSocketNotifier *notifier;
- notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
- connect(notifier, SIGNAL(activated(int)), this, SLOT(readMouseData()));
+ m_notify = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
+ connect(m_notify, SIGNAL(activated(int)), this, SLOT(readMouseData()));
}
QEvdevMouseHandler::~QEvdevMouseHandler()
@@ -202,6 +201,14 @@ void QEvdevMouseHandler::readMouseData()
} else if (result < 0) {
if (errno != EINTR && errno != EAGAIN) {
qErrnoWarning(errno, "evdevmouse: Could not read from input device");
+ // If the device got disconnected, stop reading, otherwise we get flooded
+ // by the above error over and over again.
+ if (errno == ENODEV) {
+ delete m_notify;
+ m_notify = Q_NULLPTR;
+ qt_safe_close(m_fd);
+ m_fd = -1;
+ }
return;
}
} else {
diff --git a/src/platformsupport/platformsupport.pro b/src/platformsupport/platformsupport.pro
index 8fb05be3fa..9f6f3380e1 100644
--- a/src/platformsupport/platformsupport.pro
+++ b/src/platformsupport/platformsupport.pro
@@ -21,7 +21,11 @@ include(accessibility/accessibility.pri)
include(linuxaccessibility/linuxaccessibility.pri)
include(clipboard/clipboard.pri)
include(platformcompositor/platformcompositor.pri)
-contains(QT_CONFIG, dbus) {
+
+# dbus convenience, but not for darwin: the platform
+# plugins for these platforms do not use dbus and we
+# don't want to create a false dependency.
+!darwin: contains(QT_CONFIG, dbus) {
include(dbusmenu/dbusmenu.pri)
include(dbustray/dbustray.pri)
}
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 004ed04cab..c9c7ff6c2c 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -153,7 +153,7 @@ static bool isMouseEvent(NSEvent *ev)
if (NSMouseInRect(loc, windowFrame, NO) &&
!NSMouseInRect(loc, contentFrame, NO))
{
- QNSView *contentView = (QNSView *)pw->contentView();
+ QNSView *contentView = pw->m_qtView;
[contentView handleFrameStrutMouseEvent: theEvent];
}
}
@@ -1188,7 +1188,11 @@ NSView *QCocoaWindow::contentView() const
void QCocoaWindow::setContentView(NSView *contentView)
{
// Remove and release the previous content view
- [m_contentView removeFromSuperview];
+ if (m_nsWindow)
+ [m_nsWindow setContentView:nil];
+ else
+ [m_contentView removeFromSuperview];
+
[m_contentView release];
// Insert and retain the new content view
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index ffc3dec814..7834c2991d 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -632,7 +632,9 @@ static bool _q_dontOverrideCtrlLMB = false;
- (BOOL)becomeFirstResponder
{
- if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) )
+ if (!m_window || !m_platformWindow)
+ return NO;
+ if (m_window->flags() & Qt::WindowTransparentForInput)
return NO;
if (!m_platformWindow->windowIsPopupType() && !m_isMenuView)
QWindowSystemInterface::handleWindowActivated([self topLevelWindow]);
@@ -641,11 +643,13 @@ static bool _q_dontOverrideCtrlLMB = false;
- (BOOL)acceptsFirstResponder
{
+ if (!m_window || !m_platformWindow)
+ return NO;
if (m_isMenuView)
return NO;
if (m_platformWindow->shouldRefuseKeyWindowAndFirstResponder())
return NO;
- if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) )
+ if (m_window->flags() & Qt::WindowTransparentForInput)
return NO;
if ((m_window->flags() & Qt::ToolTip) == Qt::ToolTip)
return NO;
@@ -655,7 +659,9 @@ static bool _q_dontOverrideCtrlLMB = false;
- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
{
Q_UNUSED(theEvent)
- if (m_window && (m_window->flags() & Qt::WindowTransparentForInput) )
+ if (!m_window || !m_platformWindow)
+ return NO;
+ if (m_window->flags() & Qt::WindowTransparentForInput)
return NO;
return YES;
}
@@ -2162,7 +2168,11 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin
// keep our state, and QGuiApplication state (buttons member) in-sync,
// or future mouse events will be processed incorrectly
- m_buttons &= ~(m_sendUpAsRightButton ? Qt::RightButton : Qt::LeftButton);
+ NSUInteger pmb = [NSEvent pressedMouseButtons];
+ for (int buttonNumber = 0; buttonNumber < 32; buttonNumber++) { // see cocoaButton2QtButton() for the 32 value
+ if (!(pmb & (1 << buttonNumber)))
+ m_buttons &= ~cocoaButton2QtButton(buttonNumber);
+ }
NSPoint windowPoint = [self convertPoint: point fromView: nil];
QPoint qtWindowPoint(windowPoint.x, windowPoint.y);
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp
index abff88b4bd..5b779d6732 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp
@@ -132,7 +132,7 @@ void QEglFSKmsGbmCursor::updateMouseStatus()
m_state = visible ? CursorPendingVisible : CursorPendingHidden;
#ifndef QT_NO_CURSOR
- changeCursor(nullptr, m_screen->topLevelAt(pos()));
+ changeCursor(Q_NULLPTR, m_screen->topLevelAt(pos()));
#endif
}
diff --git a/src/plugins/platforms/ios/qiosinputcontext.h b/src/plugins/platforms/ios/qiosinputcontext.h
index 82bcf48855..2b0643f26e 100644
--- a/src/plugins/platforms/ios/qiosinputcontext.h
+++ b/src/plugins/platforms/ios/qiosinputcontext.h
@@ -42,6 +42,7 @@
#include <UIKit/UIKit.h>
+#include <QtCore/qlocale.h>
#include <QtGui/qevent.h>
#include <QtGui/qtransform.h>
#include <qpa/qplatforminputcontext.h>
@@ -52,6 +53,7 @@ const char kImePlatformDataReturnKeyType[] = "returnKeyType";
QT_BEGIN_NAMESPACE
+@class QIOSLocaleListener;
@class QIOSKeyboardListener;
@class QIOSTextInputResponder;
@protocol KeyboardState;
@@ -98,6 +100,8 @@ public:
void reset() Q_DECL_OVERRIDE;
void commit() Q_DECL_OVERRIDE;
+ QLocale locale() const Q_DECL_OVERRIDE;
+
void clearCurrentFocusObject();
void setFocusObject(QObject *object) Q_DECL_OVERRIDE;
@@ -118,6 +122,7 @@ public:
private:
UIView* scrollableRootView();
+ QIOSLocaleListener *m_localeListener;
QIOSKeyboardListener *m_keyboardHideGesture;
QIOSTextInputResponder *m_textResponder;
KeyboardState m_keyboardState;
diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm
index a1c51b6968..c6cbb9b101 100644
--- a/src/plugins/platforms/ios/qiosinputcontext.mm
+++ b/src/plugins/platforms/ios/qiosinputcontext.mm
@@ -62,6 +62,39 @@ static QUIView *focusView()
// -------------------------------------------------------------------------
+@interface QIOSLocaleListener : NSObject
+@end
+
+@implementation QIOSLocaleListener
+
+- (id)init
+{
+ if (self = [super init]) {
+ NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
+ [notificationCenter addObserver:self
+ selector:@selector(localeDidChange:)
+ name:NSCurrentLocaleDidChangeNotification object:nil];
+ }
+
+ return self;
+}
+
+- (void)dealloc
+{
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+ [super dealloc];
+}
+
+- (void)localeDidChange:(NSNotification *)notification
+{
+ Q_UNUSED(notification);
+ QIOSInputContext::instance()->emitLocaleChanged();
+}
+
+@end
+
+// -------------------------------------------------------------------------
+
@interface QIOSKeyboardListener : UIGestureRecognizer <UIGestureRecognizerDelegate> {
@private
QIOSInputContext *m_context;
@@ -293,6 +326,7 @@ QIOSInputContext *QIOSInputContext::instance()
QIOSInputContext::QIOSInputContext()
: QPlatformInputContext()
+ , m_localeListener([QIOSLocaleListener new])
, m_keyboardHideGesture([[QIOSKeyboardListener alloc] initWithQIOSInputContext:this])
, m_textResponder(0)
{
@@ -306,6 +340,7 @@ QIOSInputContext::QIOSInputContext()
QIOSInputContext::~QIOSInputContext()
{
+ [m_localeListener release];
[m_keyboardHideGesture.view removeGestureRecognizer:m_keyboardHideGesture];
[m_keyboardHideGesture release];
@@ -673,3 +708,8 @@ void QIOSInputContext::commit()
[m_textResponder unmarkText];
[m_textResponder notifyInputDelegate:Qt::ImSurroundingText];
}
+
+QLocale QIOSInputContext::locale() const
+{
+ return QLocale(QString::fromNSString([[NSLocale currentLocale] objectForKey:NSLocaleIdentifier]));
+}
diff --git a/src/plugins/platforms/ios/qiostextinputoverlay.mm b/src/plugins/platforms/ios/qiostextinputoverlay.mm
index 655e457664..94d82c3eb9 100644
--- a/src/plugins/platforms/ios/qiostextinputoverlay.mm
+++ b/src/plugins/platforms/ios/qiostextinputoverlay.mm
@@ -45,6 +45,7 @@
#include "qiostextinputoverlay.h"
typedef QPair<int, int> SelectionPair;
+typedef void (^Block)(void);
static const CGFloat kKnobWidth = 10;
@@ -68,7 +69,7 @@ static bool hasSelection()
return selection.first != selection.second;
}
-static void executeBlockWithoutAnimation(void (^block)(void))
+static void executeBlockWithoutAnimation(Block block)
{
[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
@@ -306,6 +307,7 @@ static void executeBlockWithoutAnimation(void (^block)(void))
@property (nonatomic, assign) CGRect cursorRectangle;
@property (nonatomic, assign) CGFloat handleScale;
@property (nonatomic, assign) BOOL visible;
+@property (nonatomic, copy) Block onAnimationDidStop;
@end
@implementation QIOSHandleLayer
@@ -359,7 +361,8 @@ static void executeBlockWithoutAnimation(void (^block)(void))
[NSNumber numberWithFloat:1], nil];
return animation;
} else {
- CABasicAnimation * animation = [CABasicAnimation animationWithKeyPath:key];
+ CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:key];
+ [animation setDelegate:self];
animation.fromValue = [self valueForKey:key];
[animation setDuration:0.2];
return animation;
@@ -368,6 +371,14 @@ static void executeBlockWithoutAnimation(void (^block)(void))
return [super actionForKey:key];
}
+- (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)flag
+{
+ Q_UNUSED(animation);
+ Q_UNUSED(flag);
+ if (self.onAnimationDidStop)
+ self.onAnimationDidStop();
+}
+
- (void)setVisible:(BOOL)visible
{
if (visible == _visible)
@@ -679,7 +690,7 @@ static void executeBlockWithoutAnimation(void (^block)(void))
if (enabled) {
// Create a layer that clips the handles inside the input field
- _clipRectLayer = [[CALayer new] autorelease];
+ _clipRectLayer = [CALayer new];
_clipRectLayer.masksToBounds = YES;
[self.focusView.layer addSublayer:_clipRectLayer];
@@ -705,7 +716,26 @@ static void executeBlockWithoutAnimation(void (^block)(void))
[self updateSelection];
} else {
- [_clipRectLayer removeFromSuperlayer];
+ // Fade out the handles by setting visible to NO, and wait for the animations
+ // to finish before removing the clip rect layer, including the handles.
+ // Create a local variable to hold the clipRectLayer while the animation is
+ // ongoing to ensure that any subsequent calls to setEnabled does not interfere.
+ // Also, declare it as __block to stop it from being automatically retained, which
+ // would cause a cyclic dependency between clipRectLayer and the block.
+ __block CALayer *clipRectLayer = _clipRectLayer;
+ __block int handleCount = 2;
+ Block block = ^{
+ if (--handleCount == 0) {
+ [clipRectLayer removeFromSuperlayer];
+ [clipRectLayer release];
+ }
+ };
+
+ _cursorLayer.onAnimationDidStop = block;
+ _anchorLayer.onAnimationDidStop = block;
+ _cursorLayer.visible = NO;
+ _anchorLayer.visible = NO;
+
_clipRectLayer = 0;
_cursorLayer = 0;
_anchorLayer = 0;
diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm
index 031cd90828..5ec05ec8ce 100644
--- a/src/plugins/platforms/ios/qiostextresponder.mm
+++ b/src/plugins/platforms/ios/qiostextresponder.mm
@@ -359,6 +359,7 @@
- (void)sendKeyPressRelease:(Qt::Key)key modifiers:(Qt::KeyboardModifiers)modifiers
{
+ QScopedValueRollback<BOOL> rollback(m_inSendEventToFocusObject, true);
QWindowSystemInterface::handleKeyEvent(qApp->focusWindow(), QEvent::KeyPress, key, modifiers);
QWindowSystemInterface::handleKeyEvent(qApp->focusWindow(), QEvent::KeyRelease, key, modifiers);
QWindowSystemInterface::flushWindowSystemEvents();
diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm
index 643192797a..c8c07bd298 100644
--- a/src/plugins/platforms/ios/qiosviewcontroller.mm
+++ b/src/plugins/platforms/ios/qiosviewcontroller.mm
@@ -310,17 +310,16 @@
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)orientation duration:(NSTimeInterval)duration
{
- Q_UNUSED(orientation);
- Q_UNUSED(duration);
-
self.changingOrientation = YES;
+
+ [super willRotateToInterfaceOrientation:orientation duration:duration];
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)orientation
{
- Q_UNUSED(orientation);
-
self.changingOrientation = NO;
+
+ [super didRotateFromInterfaceOrientation:orientation];
}
- (void)willChangeStatusBarFrame:(NSNotification*)notification
diff --git a/src/plugins/platforms/minimal/minimal.pro b/src/plugins/platforms/minimal/minimal.pro
index 0d31d6605b..bd6f2d8e6f 100644
--- a/src/plugins/platforms/minimal/minimal.pro
+++ b/src/plugins/platforms/minimal/minimal.pro
@@ -11,6 +11,7 @@ HEADERS = qminimalintegration.h \
OTHER_FILES += minimal.json
CONFIG += qpa/genericunixfontdatabase
+darwin: DEFINES += QT_NO_FONTCONFIG
PLUGIN_TYPE = platforms
PLUGIN_CLASS_NAME = QMinimalIntegrationPlugin
diff --git a/src/plugins/platforms/platforms.pro b/src/plugins/platforms/platforms.pro
index b447cf9b81..454d7f43bd 100644
--- a/src/plugins/platforms/platforms.pro
+++ b/src/plugins/platforms/platforms.pro
@@ -2,9 +2,9 @@ TEMPLATE = subdirs
android: SUBDIRS += android
-SUBDIRS += minimal
+!android: SUBDIRS += minimal
-!win32|contains(QT_CONFIG, freetype):SUBDIRS += offscreen
+!android:if(!win32|contains(QT_CONFIG, freetype)): SUBDIRS += offscreen
contains(QT_CONFIG, xcb) {
SUBDIRS += xcb
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp
index 23a6f35576..6124b004b6 100644
--- a/src/plugins/platforms/windows/qwindowseglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp
@@ -201,26 +201,9 @@ QWindowsEGLStaticContext::QWindowsEGLStaticContext(EGLDisplay display)
{
}
-QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester::Renderers preferredType)
+bool QWindowsEGLStaticContext::initializeAngle(QWindowsOpenGLTester::Renderers preferredType, HDC dc,
+ EGLDisplay *display, EGLint *major, EGLint *minor)
{
- const HDC dc = QWindowsContext::instance()->displayContext();
- if (!dc){
- qWarning("%s: No Display", __FUNCTION__);
- return 0;
- }
-
- if (!libEGL.init()) {
- qWarning("%s: Failed to load and resolve libEGL functions", __FUNCTION__);
- return 0;
- }
- if (!libGLESv2.init()) {
- qWarning("%s: Failed to load and resolve libGLESv2 functions", __FUNCTION__);
- return 0;
- }
-
- EGLDisplay display = EGL_NO_DISPLAY;
- EGLint major = 0;
- EGLint minor = 0;
#ifdef EGL_ANGLE_platform_angle
if (libEGL.eglGetPlatformDisplayEXT
&& (preferredType & QWindowsOpenGLTester::AngleBackendMask)) {
@@ -238,16 +221,52 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester:
else if (preferredType & QWindowsOpenGLTester::AngleRendererD3d11Warp)
attributes = anglePlatformAttributes[2];
if (attributes) {
- display = libEGL.eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, dc, attributes);
- if (!libEGL.eglInitialize(display, &major, &minor)) {
- display = EGL_NO_DISPLAY;
- major = minor = 0;
+ *display = libEGL.eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, dc, attributes);
+ if (!libEGL.eglInitialize(*display, major, minor)) {
+ libEGL.eglTerminate(*display);
+ *display = EGL_NO_DISPLAY;
+ *major = *minor = 0;
+ return false;
}
}
}
#else // EGL_ANGLE_platform_angle
- Q_UNUSED(preferredType)
+ Q_UNUSED(preferredType);
+ Q_UNUSED(dc);
+ Q_UNUSED(display);
+ Q_UNUSED(major);
+ Q_UNUSED(minor);
#endif
+ return true;
+}
+
+QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester::Renderers preferredType)
+{
+ const HDC dc = QWindowsContext::instance()->displayContext();
+ if (!dc){
+ qWarning("%s: No Display", __FUNCTION__);
+ return 0;
+ }
+
+ if (!libEGL.init()) {
+ qWarning("%s: Failed to load and resolve libEGL functions", __FUNCTION__);
+ return 0;
+ }
+ if (!libGLESv2.init()) {
+ qWarning("%s: Failed to load and resolve libGLESv2 functions", __FUNCTION__);
+ return 0;
+ }
+
+ EGLDisplay display = EGL_NO_DISPLAY;
+ EGLint major = 0;
+ EGLint minor = 0;
+
+ if (!initializeAngle(preferredType, dc, &display, &major, &minor)
+ && (preferredType & QWindowsOpenGLTester::AngleRendererD3d11)) {
+ preferredType &= ~QWindowsOpenGLTester::AngleRendererD3d11;
+ initializeAngle(preferredType, dc, &display, &major, &minor);
+ }
+
if (display == EGL_NO_DISPLAY)
display = libEGL.eglGetDisplay(dc);
if (!display) {
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.h b/src/plugins/platforms/windows/qwindowseglcontext.h
index c7f7cee3c2..48a19f81e5 100644
--- a/src/plugins/platforms/windows/qwindowseglcontext.h
+++ b/src/plugins/platforms/windows/qwindowseglcontext.h
@@ -131,6 +131,8 @@ public:
private:
explicit QWindowsEGLStaticContext(EGLDisplay display);
+ static bool initializeAngle(QWindowsOpenGLTester::Renderers preferredType, HDC dc,
+ EGLDisplay *display, EGLint *major, EGLint *minor);
const EGLDisplay m_display;
};
diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp
index 0f49c66462..744d882bb2 100644
--- a/src/plugins/platforms/windows/qwindowsfontengine.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp
@@ -1236,8 +1236,7 @@ QFontEngine *QWindowsMultiFontEngine::loadEngine(int at)
QWindowsFontEngineDirectWrite *fedw = new QWindowsFontEngineDirectWrite(directWriteFontFace,
fontEngine->fontDef.pixelSize,
data);
- if (fontEngine->fontDef.weight > QFont::Normal)
- fedw->fontDef.weight = fontEngine->fontDef.weight;
+ fedw->fontDef.weight = fontEngine->fontDef.weight;
if (fontEngine->fontDef.style > QFont::StyleNormal)
fedw->fontDef.style = fontEngine->fontDef.style;
fedw->fontDef.family = fam;
@@ -1254,8 +1253,7 @@ QFontEngine *QWindowsMultiFontEngine::loadEngine(int at)
// reason
QFontEngine *fe = new QWindowsFontEngine(fam, lf, data);
- if (fontEngine->fontDef.weight > QFont::Normal)
- fe->fontDef.weight = fontEngine->fontDef.weight;
+ fe->fontDef.weight = fontEngine->fontDef.weight;
if (fontEngine->fontDef.style > QFont::StyleNormal)
fe->fontDef.style = fontEngine->fontDef.style;
fe->fontDef.family = fam;
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index 6e324ce0ed..5b8cc7893a 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -322,7 +322,9 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons
if (customMarginsV.isValid())
requested.customMargins = qvariant_cast<QMargins>(customMarginsV);
- QWindowsWindowData obtained = QWindowsWindowData::create(window, requested, window->title());
+ QWindowsWindowData obtained =
+ QWindowsWindowData::create(window, requested,
+ QWindowsWindow::formatWindowTitle(window->title()));
qCDebug(lcQpaWindows).nospace()
<< __FUNCTION__ << ' ' << window
<< "\n Requested: " << requested.geometry << " frame incl.="
diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp
index a9307f79fb..6c6eb42d63 100644
--- a/src/plugins/platforms/windows/qwindowstheme.cpp
+++ b/src/plugins/platforms/windows/qwindowstheme.cpp
@@ -132,7 +132,16 @@ public:
explicit ShGetFileInfoFunction(const wchar_t *fn, DWORD a, SHFILEINFO *i, UINT f, bool *r) :
m_fileName(fn), m_attributes(a), m_flags(f), m_info(i), m_result(r) {}
- void operator()() const { *m_result = SHGetFileInfo(m_fileName, m_attributes, m_info, sizeof(SHFILEINFO), m_flags); }
+ void operator()() const
+ {
+#ifndef Q_OS_WINCE
+ const UINT oldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
+#endif
+ *m_result = SHGetFileInfo(m_fileName, m_attributes, m_info, sizeof(SHFILEINFO), m_flags);
+#ifndef Q_OS_WINCE
+ SetErrorMode(oldErrorMode);
+#endif
+ }
private:
const wchar_t *m_fileName;
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index f54c100f25..3a6e6840fd 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -1579,11 +1579,12 @@ bool QWindowsWindow::handleWmPaint(HWND hwnd, UINT message,
return false;
PAINTSTRUCT ps;
+ BeginPaint(hwnd, &ps);
+
// Observed painting problems with Aero style disabled (QTBUG-7865).
+ // 5.8: Consider making it dependent on !DwmIsCompositionEnabled().
if (testFlag(OpenGLSurface) && testFlag(OpenGLDoubleBuffered))
- InvalidateRect(hwnd, 0, false);
-
- BeginPaint(hwnd, &ps);
+ SelectClipRgn(ps.hdc, NULL);
// If the a window is obscured by another window (such as a child window)
// we still need to send isExposed=true, for compatibility.
@@ -1598,7 +1599,7 @@ bool QWindowsWindow::handleWmPaint(HWND hwnd, UINT message,
void QWindowsWindow::setWindowTitle(const QString &title)
{
- setWindowTitle_sys(QWindowsWindow::formatWindowTitle(title, QStringLiteral(" - ")));
+ setWindowTitle_sys(QWindowsWindow::formatWindowTitle(title));
}
void QWindowsWindow::setWindowFlags(Qt::WindowFlags flags)
@@ -2402,4 +2403,9 @@ void QWindowsWindow::setHasBorderInFullScreen(bool border)
clearFlag(HasBorderInFullScreen);
}
+QString QWindowsWindow::formatWindowTitle(const QString &title)
+{
+ return QPlatformWindow::formatWindowTitle(title, QStringLiteral(" - "));
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index 3736778095..924f242e6e 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -316,6 +316,8 @@ public:
void registerTouchWindow(QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes = QWindowsWindowFunctions::NormalTouch);
static void setHasBorderInFullScreenStatic(QWindow *window, bool border);
void setHasBorderInFullScreen(bool border);
+ static QString formatWindowTitle(const QString &title);
+
private:
inline void show_sys() const;
inline QWindowsWindowData setWindowFlags_sys(Qt::WindowFlags wt, unsigned flags = 0) const;
diff --git a/src/plugins/platforms/winrt/qwinrtdrag.cpp b/src/plugins/platforms/winrt/qwinrtdrag.cpp
new file mode 100644
index 0000000000..2ef50aa4e2
--- /dev/null
+++ b/src/plugins/platforms/winrt/qwinrtdrag.cpp
@@ -0,0 +1,893 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "qwinrtdrag.h"
+
+#include <QtCore/qglobal.h>
+#include <QtCore/QMimeData>
+#include <QtCore/QStringList>
+#include <QtGui/QGuiApplication>
+#include <qpa/qwindowsysteminterface.h>
+
+#include <qfunctions_winrt.h>
+#include <private/qeventdispatcher_winrt_p.h>
+
+#include <Windows.ApplicationModel.datatransfer.h>
+#include <windows.ui.xaml.h>
+#include <windows.foundation.collections.h>
+#include <windows.graphics.imaging.h>
+#include <windows.storage.streams.h>
+#include <functional>
+#include <robuffer.h>
+
+using namespace ABI::Windows::ApplicationModel::DataTransfer;
+using namespace ABI::Windows::ApplicationModel::DataTransfer::DragDrop;
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::Foundation::Collections;
+using namespace ABI::Windows::Graphics::Imaging;
+using namespace ABI::Windows::Storage;
+using namespace ABI::Windows::Storage::Streams;
+using namespace ABI::Windows::UI::Xaml;
+using namespace Microsoft::WRL;
+using namespace Microsoft::WRL::Wrappers;
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(lcQpaMime, "qt.qpa.mime")
+
+ComPtr<IBuffer> createIBufferFromData(const char *data, qint32 size)
+{
+ static ComPtr<IBufferFactory> bufferFactory;
+ HRESULT hr;
+ if (!bufferFactory) {
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(),
+ IID_PPV_ARGS(&bufferFactory));
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+
+ ComPtr<IBuffer> buffer;
+ const UINT32 length = size;
+ hr = bufferFactory->Create(length, &buffer);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = buffer->put_Length(length);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ ComPtr<Windows::Storage::Streams::IBufferByteAccess> byteArrayAccess;
+ hr = buffer.As(&byteArrayAccess);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ byte *bytes;
+ hr = byteArrayAccess->Buffer(&bytes);
+ Q_ASSERT_SUCCEEDED(hr);
+ memcpy(bytes, data, length);
+ return buffer;
+}
+
+class DragThreadTransferData : public QObject
+{
+ Q_OBJECT
+public slots:
+ void handleDrag();
+public:
+ explicit DragThreadTransferData(QObject *parent = Q_NULLPTR);
+ QWindow *window;
+ QWinRTInternalMimeData *mime;
+ QPoint point;
+ Qt::DropActions actions;
+ bool dropAction;
+ ComPtr<IDragEventArgs> nativeArgs;
+ ComPtr<IDragOperationDeferral> deferral;
+};
+
+inline QString hStringToQString(const HString &hString)
+{
+ quint32 l;
+ const wchar_t *raw = hString.GetRawBuffer(&l);
+ return (QString::fromWCharArray(raw, l));
+}
+
+inline HString qStringToHString(const QString &qString)
+{
+ HString h;
+ h.Set(reinterpret_cast<const wchar_t*>(qString.utf16()), qString.size());
+ return h;
+}
+
+namespace NativeFormatStrings {
+ static ComPtr<IStandardDataFormatsStatics> dataStatics;
+ static HSTRING text; // text/plain
+ static HSTRING html; // text/html
+ static HSTRING storage; // text/uri-list
+}
+
+static inline DataPackageOperation translateFromQDragDropActions(const Qt::DropAction action)
+{
+ switch (action) {
+ case Qt::CopyAction:
+ return DataPackageOperation_Copy;
+ case Qt::MoveAction:
+ return DataPackageOperation_Move;
+ case Qt::LinkAction:
+ return DataPackageOperation_Link;
+ case Qt::IgnoreAction:
+ default:
+ return DataPackageOperation_None;
+ }
+}
+
+static inline Qt::DropActions translateToQDragDropActions(const DataPackageOperation op)
+{
+ Qt::DropActions actions = Qt::IgnoreAction;
+ // None needs to be interpreted as the sender being able to handle
+ // anything and let the receiver decide
+ if (op == DataPackageOperation_None)
+ actions = Qt::LinkAction | Qt::CopyAction | Qt::MoveAction;
+ if (op & DataPackageOperation_Link)
+ actions |= Qt::LinkAction;
+ if (op & DataPackageOperation_Copy)
+ actions |= Qt::CopyAction;
+ if (op & DataPackageOperation_Move)
+ actions |= Qt::MoveAction;
+ return actions;
+}
+
+QWinRTInternalMimeData::QWinRTInternalMimeData()
+ : QInternalMimeData()
+{
+ qCDebug(lcQpaMime) << __FUNCTION__;
+ if (!NativeFormatStrings::dataStatics) {
+ HRESULT hr;
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_ApplicationModel_DataTransfer_StandardDataFormats).Get(),
+ IID_PPV_ARGS(&NativeFormatStrings::dataStatics));
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = NativeFormatStrings::dataStatics->get_Text(&NativeFormatStrings::text);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = NativeFormatStrings::dataStatics->get_Html(&NativeFormatStrings::html);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = NativeFormatStrings::dataStatics->get_StorageItems(&NativeFormatStrings::storage);
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+}
+
+QWinRTInternalMimeData::~QWinRTInternalMimeData()
+{
+}
+
+bool QWinRTInternalMimeData::hasFormat_sys(const QString &mimetype) const
+{
+ qCDebug(lcQpaMime) << __FUNCTION__ << mimetype;
+
+ if (!dataView)
+ return false;
+
+ return formats_sys().contains(mimetype);
+}
+
+QStringList QWinRTInternalMimeData::formats_sys() const
+{
+ qCDebug(lcQpaMime) << __FUNCTION__;
+
+ if (!dataView)
+ return QStringList();
+
+ if (!formats.isEmpty())
+ return formats;
+
+ HRESULT hr;
+ hr = QEventDispatcherWinRT::runOnXamlThread([this]() {
+ boolean contains;
+ HRESULT hr;
+ hr = dataView->Contains(NativeFormatStrings::text, &contains);
+ if (SUCCEEDED(hr) && contains)
+ formats.append(QLatin1String("text/plain"));
+
+ hr = dataView->Contains(NativeFormatStrings::html, &contains);
+ if (SUCCEEDED(hr) && contains)
+ formats.append(QLatin1String("text/html"));
+
+ hr = dataView->Contains(NativeFormatStrings::storage, &contains);
+ if (SUCCEEDED(hr) && contains)
+ formats.append(QLatin1String("text/uri-list"));
+
+ // We need to add any additional format as well, for legacy windows
+ // reasons, but also in case someone adds custom formats.
+ ComPtr<IVectorView<HSTRING>> availableFormats;
+ hr = dataView->get_AvailableFormats(&availableFormats);
+ RETURN_OK_IF_FAILED("Could not query available formats.");
+
+ quint32 size;
+ hr = availableFormats->get_Size(&size);
+ RETURN_OK_IF_FAILED("Could not query format vector size.");
+ for (quint32 i = 0; i < size; ++i) {
+ HString str;
+ hr = availableFormats->GetAt(i, str.GetAddressOf());
+ if (FAILED(hr))
+ continue;
+ formats.append(hStringToQString(str));
+ }
+ return S_OK;
+ });
+ Q_ASSERT_SUCCEEDED(hr);
+
+ return formats;
+}
+
+QVariant QWinRTInternalMimeData::retrieveData_sys(const QString &mimetype, QVariant::Type preferredType) const
+{
+ qCDebug(lcQpaMime) << __FUNCTION__ << mimetype << preferredType;
+
+ if (!dataView || !formats.contains(mimetype))
+ return QVariant();
+
+ QVariant result;
+ HRESULT hr;
+ if (mimetype == QLatin1String("text/plain")) {
+ hr = QEventDispatcherWinRT::runOnXamlThread([this, &result]() {
+ HRESULT hr;
+ ComPtr<IAsyncOperation<HSTRING>> op;
+ HString res;
+ hr = dataView->GetTextAsync(&op);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = QWinRTFunctions::await(op, res.GetAddressOf());
+ Q_ASSERT_SUCCEEDED(hr);
+ result.setValue(hStringToQString(res));
+ return S_OK;
+ });
+ } else if (mimetype == QLatin1String("text/uri-list")) {
+ hr = QEventDispatcherWinRT::runOnXamlThread([this, &result]() {
+ HRESULT hr;
+ ComPtr<IAsyncOperation<IVectorView<IStorageItem*>*>> op;
+ hr = dataView->GetStorageItemsAsync(&op);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<IVectorView<IStorageItem*>> nativeItems;
+ hr = QWinRTFunctions::await(op, nativeItems.GetAddressOf());
+ Q_ASSERT_SUCCEEDED(hr);
+ QList<QVariant> items;
+ quint32 count;
+ hr = nativeItems->get_Size(&count);
+ for (quint32 i = 0; i < count; ++i) {
+ ComPtr<IStorageItem> item;
+ hr = nativeItems->GetAt(i, &item);
+ Q_ASSERT_SUCCEEDED(hr);
+ HString path;
+ hr = item->get_Path(path.GetAddressOf());
+ Q_ASSERT_SUCCEEDED(hr);
+ items.append(QUrl::fromLocalFile(hStringToQString(path)));
+ }
+ result.setValue(items);
+ return S_OK;
+ });
+ } else if (mimetype == QLatin1String("text/html")) {
+ hr = QEventDispatcherWinRT::runOnXamlThread([this, &result]() {
+ HRESULT hr;
+ ComPtr<IAsyncOperation<HSTRING>> op;
+ HString res;
+ hr = dataView->GetHtmlFormatAsync(&op);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = QWinRTFunctions::await(op, res.GetAddressOf());
+ Q_ASSERT_SUCCEEDED(hr);
+ result.setValue(hStringToQString(res));
+ return S_OK;
+ });
+ } else {
+ // Asking for custom data
+ hr = QEventDispatcherWinRT::runOnXamlThread([this, &result, mimetype]() {
+ HRESULT hr;
+ ComPtr<IAsyncOperation<IInspectable*>> op;
+ ComPtr<IInspectable> res;
+ HString type;
+ type.Set(reinterpret_cast<const wchar_t*>(mimetype.utf16()), mimetype.size());
+ hr = dataView->GetDataAsync(type.Get(), &op);
+ RETURN_OK_IF_FAILED("Could not query custom drag data.");
+ hr = QWinRTFunctions::await(op, res.GetAddressOf());
+ if (FAILED(hr) || !res) {
+ qCDebug(lcQpaMime) << "Custom drop data operation returned no results or failed.";
+ return S_OK;
+ }
+
+ // Test for properties
+ ComPtr<IPropertyValue> propertyValue;
+ hr = res.As(&propertyValue);
+ if (SUCCEEDED(hr)) {
+ // We need to check which type of custom data we are receiving
+ PropertyType type;
+ propertyValue->get_Type(&type);
+ switch (type) {
+ case PropertyType_UInt8: {
+ quint8 v;
+ hr = propertyValue->GetUInt8(&v);
+ Q_ASSERT_SUCCEEDED(hr);
+ result.setValue(v);
+ return S_OK;
+ }
+ case PropertyType_Int16: {
+ qint16 v;
+ hr = propertyValue->GetInt16(&v);
+ Q_ASSERT_SUCCEEDED(hr);
+ result.setValue(v);
+ return S_OK;
+ }
+ case PropertyType_UInt16: {
+ quint16 v;
+ hr = propertyValue->GetUInt16(&v);
+ Q_ASSERT_SUCCEEDED(hr);
+ result.setValue(v);
+ return S_OK;
+ }
+ case PropertyType_Int32: {
+ qint32 v;
+ hr = propertyValue->GetInt32(&v);
+ Q_ASSERT_SUCCEEDED(hr);
+ result.setValue(v);
+ return S_OK;
+ }
+ case PropertyType_UInt32: {
+ quint32 v;
+ hr = propertyValue->GetUInt32(&v);
+ Q_ASSERT_SUCCEEDED(hr);
+ result.setValue(v);
+ return S_OK;
+ }
+ case PropertyType_Int64: {
+ qint64 v;
+ hr = propertyValue->GetInt64(&v);
+ Q_ASSERT_SUCCEEDED(hr);
+ result.setValue(v);
+ return S_OK;
+ }
+ case PropertyType_UInt64: {
+ quint64 v;
+ hr = propertyValue->GetUInt64(&v);
+ Q_ASSERT_SUCCEEDED(hr);
+ result.setValue(v);
+ return S_OK;
+ }
+ case PropertyType_Single: {
+ float v;
+ hr = propertyValue->GetSingle(&v);
+ Q_ASSERT_SUCCEEDED(hr);
+ result.setValue(v);
+ return S_OK;
+ }
+ case PropertyType_Double: {
+ double v;
+ hr = propertyValue->GetDouble(&v);
+ Q_ASSERT_SUCCEEDED(hr);
+ result.setValue(v);
+ return S_OK;
+ }
+ case PropertyType_Char16: {
+ wchar_t v;
+ hr = propertyValue->GetChar16(&v);
+ Q_ASSERT_SUCCEEDED(hr);
+ result.setValue(QString::fromWCharArray(&v, 1));
+ return S_OK;
+ }
+ case PropertyType_Boolean: {
+ boolean v;
+ hr = propertyValue->GetBoolean(&v);
+ Q_ASSERT_SUCCEEDED(hr);
+ result.setValue(v);
+ return S_OK;
+ }
+ case PropertyType_String: {
+ HString stringProperty;
+ hr = propertyValue->GetString(stringProperty.GetAddressOf());
+ Q_ASSERT_SUCCEEDED(hr);
+ result.setValue(hStringToQString(stringProperty));
+ return S_OK;
+ }
+ default:
+ qCDebug(lcQpaMime) << "Unknown property type dropped:" << type;
+ }
+ return S_OK;
+ }
+
+ // Custom data can be read via input streams
+ ComPtr<IRandomAccessStream> randomAccessStream;
+ hr = res.As(&randomAccessStream);
+ if (SUCCEEDED(hr)) {
+ UINT64 size;
+ hr = randomAccessStream->get_Size(&size);
+ Q_ASSERT_SUCCEEDED(hr);
+ ComPtr<IInputStream> stream;
+ hr = randomAccessStream.As(&stream);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ ComPtr<IBufferFactory> bufferFactory;
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(),
+ IID_PPV_ARGS(&bufferFactory));
+ Q_ASSERT_SUCCEEDED(hr);
+
+ UINT32 length = qBound(quint64(0), quint64(size), quint64(UINT_MAX));
+ ComPtr<IBuffer> buffer;
+ hr = bufferFactory->Create(length, &buffer);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ ComPtr<IAsyncOperationWithProgress<IBuffer *, UINT32>> readOp;
+ hr = stream->ReadAsync(buffer.Get(), length, InputStreamOptions_None, &readOp);
+
+ ComPtr<IBuffer> effectiveBuffer;
+ hr = QWinRTFunctions::await(readOp, effectiveBuffer.GetAddressOf());
+
+ hr = effectiveBuffer->get_Length(&length);
+
+ ComPtr<Windows::Storage::Streams::IBufferByteAccess> byteArrayAccess;
+ hr = effectiveBuffer.As(&byteArrayAccess);
+
+ byte *bytes;
+ hr = byteArrayAccess->Buffer(&bytes);
+ QByteArray array((char *)bytes, length);
+ result.setValue(array);
+ return S_OK;
+ }
+
+ HSTRING runtimeClass;
+ hr = res->GetRuntimeClassName(&runtimeClass);
+ Q_ASSERT_SUCCEEDED(hr);
+ HString converted;
+ converted.Set(runtimeClass);
+ qCDebug(lcQpaMime) << "Unknown drop data type received (" << hStringToQString(converted)
+ << "). Ignoring...";
+ return S_OK;
+ });
+ }
+ return result;
+}
+
+void QWinRTInternalMimeData::setDataView(const Microsoft::WRL::ComPtr<IDataPackageView> &d)
+{
+ dataView = d;
+ formats.clear();
+}
+
+static HRESULT qt_drag_enter(IInspectable *sender, ABI::Windows::UI::Xaml::IDragEventArgs *e)
+{
+ QWinRTDrag::instance()->handleNativeDragEvent(sender, e);
+ return S_OK;
+}
+
+static HRESULT qt_drag_over(IInspectable *sender, ABI::Windows::UI::Xaml::IDragEventArgs *e)
+{
+ QWinRTDrag::instance()->handleNativeDragEvent(sender, e);
+ return S_OK;
+}
+
+static HRESULT qt_drag_leave(IInspectable *sender, ABI::Windows::UI::Xaml::IDragEventArgs *e)
+{
+ // Qt internally checks for new drags and auto sends leave events
+ // Also there is no QPA function for handling leave
+ Q_UNUSED(sender);
+ Q_UNUSED(e);
+ return S_OK;
+}
+
+static HRESULT qt_drop(IInspectable *sender, ABI::Windows::UI::Xaml::IDragEventArgs *e)
+{
+ QWinRTDrag::instance()->handleNativeDragEvent(sender, e, true);
+ return S_OK;
+}
+
+#define Q_DECLARE_DRAGHANDLER(name,func) \
+class QtDragEventHandler##name : public IDragEventHandler \
+{ \
+public: \
+ virtual HRESULT STDMETHODCALLTYPE Invoke(IInspectable *sender, \
+ ABI::Windows::UI::Xaml::IDragEventArgs *e) \
+ { \
+ return qt_##func(sender, e);\
+ } \
+ \
+ STDMETHODIMP \
+ QueryInterface(REFIID riid, void FAR* FAR* ppvObj) \
+ { \
+ if (riid == IID_IUnknown || riid == IID_IDragEventHandler) { \
+ *ppvObj = this; \
+ AddRef(); \
+ return NOERROR; \
+ } \
+ *ppvObj = NULL; \
+ return ResultFromScode(E_NOINTERFACE); \
+ } \
+ \
+ STDMETHODIMP_(ULONG) \
+ AddRef(void) \
+ { \
+ return ++m_refs; \
+ } \
+ \
+ STDMETHODIMP_(ULONG) \
+ Release(void) \
+ { \
+ if (--m_refs == 0) { \
+ delete this; \
+ return 0; \
+ } \
+ return m_refs; \
+ } \
+private: \
+ULONG m_refs{0}; \
+};
+
+Q_DECLARE_DRAGHANDLER(Enter, drag_enter)
+Q_DECLARE_DRAGHANDLER(Over, drag_over)
+Q_DECLARE_DRAGHANDLER(Leave, drag_leave)
+Q_DECLARE_DRAGHANDLER(Drop, drop)
+
+#define Q_INST_DRAGHANDLER(name) QtDragEventHandler##name()
+
+Q_GLOBAL_STATIC(QWinRTDrag, gDrag);
+
+extern ComPtr<ABI::Windows::UI::Input::IPointerPoint> qt_winrt_lastPointerPoint; // qwinrtscreen.cpp
+
+QWinRTDrag::QWinRTDrag()
+ : QPlatformDrag()
+ , m_dragTarget(0)
+{
+ qCDebug(lcQpaMime) << __FUNCTION__;
+ m_enter = new Q_INST_DRAGHANDLER(Enter);
+ m_over = new Q_INST_DRAGHANDLER(Over);
+ m_leave = new Q_INST_DRAGHANDLER(Leave);
+ m_drop = new Q_INST_DRAGHANDLER(Drop);
+ m_mimeData = new QWinRTInternalMimeData;
+}
+
+QWinRTDrag::~QWinRTDrag()
+{
+ qCDebug(lcQpaMime) << __FUNCTION__;
+ delete m_enter;
+ delete m_over;
+ delete m_leave;
+ delete m_drop;
+ delete m_mimeData;
+}
+
+QWinRTDrag *QWinRTDrag::instance()
+{
+ return gDrag;
+}
+
+inline HRESULT resetUiElementDrag(ComPtr<IUIElement3> &elem3, EventRegistrationToken startingToken)
+{
+ return QEventDispatcherWinRT::runOnXamlThread([elem3, startingToken]() {
+ HRESULT hr;
+ hr = elem3->put_CanDrag(false);
+ Q_ASSERT_SUCCEEDED(hr);
+ hr = elem3->remove_DragStarting(startingToken);
+ Q_ASSERT_SUCCEEDED(hr);
+ return S_OK;
+ });
+}
+
+Qt::DropAction QWinRTDrag::drag(QDrag *drag)
+{
+ qCDebug(lcQpaMime) << __FUNCTION__ << drag;
+
+ if (!qt_winrt_lastPointerPoint) {
+ Q_ASSERT_X(qt_winrt_lastPointerPoint, Q_FUNC_INFO, "No pointerpoint known");
+ return Qt::IgnoreAction;
+ }
+
+ ComPtr<IUIElement3> elem3;
+ HRESULT hr = m_ui.As(&elem3);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ ComPtr<IAsyncOperation<ABI::Windows::ApplicationModel::DataTransfer::DataPackageOperation>> op;
+ EventRegistrationToken startingToken;
+
+ hr = QEventDispatcherWinRT::runOnXamlThread([drag, &op, &hr, elem3, &startingToken, this]() {
+
+ hr = elem3->put_CanDrag(true);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ auto startingCallback = Callback<ITypedEventHandler<UIElement*, DragStartingEventArgs*>> ([drag](IInspectable *, IDragStartingEventArgs *args) {
+ qCDebug(lcQpaMime) << "Drag starting" << args;
+
+ ComPtr<IDataPackage> dataPackage;
+ HRESULT hr;
+ hr = args->get_Data(dataPackage.GetAddressOf());
+ Q_ASSERT_SUCCEEDED(hr);
+ Qt::DropAction action = drag->defaultAction();
+ hr = dataPackage->put_RequestedOperation(translateFromQDragDropActions(action));
+ Q_ASSERT_SUCCEEDED(hr);
+
+#ifndef QT_WINRT_LIMITED_DRAGANDDROP
+ ComPtr<IDragStartingEventArgs2> args2;
+ hr = args->QueryInterface(IID_PPV_ARGS(&args2));
+ Q_ASSERT_SUCCEEDED(hr);
+
+ Qt::DropActions actions = drag->supportedActions();
+ DataPackageOperation allowedOperations = DataPackageOperation_None;
+ if (actions & Qt::CopyAction)
+ allowedOperations |= DataPackageOperation_Copy;
+ if (actions & Qt::MoveAction)
+ allowedOperations |= DataPackageOperation_Move;
+ if (actions & Qt::LinkAction)
+ allowedOperations |= DataPackageOperation_Link;
+ hr = args2->put_AllowedOperations(allowedOperations);
+ Q_ASSERT_SUCCEEDED(hr);
+#endif // QT_WINRT_LIMITED_DRAGANDDROP
+ QMimeData *mimeData = drag->mimeData();
+ if (mimeData->hasText()) {
+ hr = dataPackage->SetText(qStringToHString(mimeData->text()).Get());
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+ if (mimeData->hasHtml()) {
+ hr = dataPackage->SetHtmlFormat(qStringToHString(mimeData->html()).Get());
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+ // ### TODO: Missing: weblink, image
+
+ if (!drag->pixmap().isNull()) {
+ const QImage image2 = drag->pixmap().toImage();
+ const QImage image = image2.convertToFormat(QImage::Format_ARGB32);
+ if (!image.isNull()) {
+ // Create IBuffer containing image
+ ComPtr<IBuffer> imageBuffer = createIBufferFromData(reinterpret_cast<const char*>(image.bits()), image.byteCount());
+
+ ComPtr<ISoftwareBitmapFactory> bitmapFactory;
+ hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Graphics_Imaging_SoftwareBitmap).Get(),
+ IID_PPV_ARGS(&bitmapFactory));
+ Q_ASSERT_SUCCEEDED(hr);
+
+ ComPtr<ISoftwareBitmap> bitmap;
+ hr = bitmapFactory->Create(BitmapPixelFormat_Rgba8, image.width(), image.height(), &bitmap);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ hr = bitmap->CopyFromBuffer(imageBuffer.Get());
+ Q_ASSERT_SUCCEEDED(hr);
+
+ ComPtr<IDragUI> dragUi;
+ hr = args->get_DragUI(dragUi.GetAddressOf());
+ Q_ASSERT_SUCCEEDED(hr);
+
+ hr = dragUi->SetContentFromSoftwareBitmap(bitmap.Get());
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+ }
+
+ const QStringList formats = mimeData->formats();
+ for (auto item : formats) {
+ QByteArray data = mimeData->data(item);
+
+ ComPtr<IBuffer> buffer = createIBufferFromData(data.constData(), data.size());
+
+ // We cannot push the buffer to the data package as the result on
+ // recipient side is different from native events. It still sends a
+ // buffer, but that potentially cannot be parsed. Hence we need to create
+ // a IRandomAccessStream which gets forwarded as is to the drop side.
+ ComPtr<IRandomAccessStream> ras;
+ hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_InMemoryRandomAccessStream).Get(), &ras);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ hr = ras->put_Size(data.size());
+ ComPtr<IOutputStream> outputStream;
+ hr = ras->GetOutputStreamAt(0, &outputStream);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ ComPtr<IAsyncOperationWithProgress<UINT32,UINT32>> writeOp;
+ hr = outputStream->WriteAsync(buffer.Get(), &writeOp);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ UINT32 result;
+ hr = QWinRTFunctions::await(writeOp, &result);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ unsigned char flushResult;
+ ComPtr<IAsyncOperation<bool>> flushOp;
+ hr = outputStream->FlushAsync(&flushOp);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ hr = QWinRTFunctions::await(flushOp, &flushResult);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ hr = dataPackage->SetData(qStringToHString(item).Get(), ras.Get());
+ Q_ASSERT_SUCCEEDED(hr);
+ }
+ return S_OK;
+ });
+
+ hr = elem3->add_DragStarting(startingCallback.Get(), &startingToken);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ hr = elem3->StartDragAsync(qt_winrt_lastPointerPoint.Get(), &op);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ return hr;
+ });
+ if (!op || FAILED(hr)) {
+ qCDebug(lcQpaMime) << "Drag failed:" << hr;
+ hr = resetUiElementDrag(elem3, startingToken);
+ Q_ASSERT_SUCCEEDED(hr);
+ return Qt::IgnoreAction;
+ }
+
+ DataPackageOperation nativeOperationType;
+ // Do not yield, as that can cause deadlocks when dropping inside the same app
+ hr = QWinRTFunctions::await(op, &nativeOperationType, QWinRTFunctions::ProcessThreadEvents);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ hr = resetUiElementDrag(elem3, startingToken);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ Qt::DropAction resultAction;
+ switch (nativeOperationType) {
+ case DataPackageOperation_Link:
+ resultAction = Qt::LinkAction;
+ break;
+ case DataPackageOperation_Copy:
+ resultAction = Qt::CopyAction;
+ break;
+ case DataPackageOperation_Move:
+ resultAction = Qt::MoveAction;
+ break;
+ case DataPackageOperation_None:
+ default:
+ resultAction = Qt::IgnoreAction;
+ break;
+ }
+
+ return resultAction;
+}
+
+void QWinRTDrag::setDropTarget(QWindow *target)
+{
+ qCDebug(lcQpaMime) << __FUNCTION__ << target;
+ m_dragTarget = target;
+}
+
+QMimeData *QWinRTDrag::platformDropData()
+{
+ qCDebug(lcQpaMime) << __FUNCTION__;
+ return m_mimeData;
+}
+
+void QWinRTDrag::setUiElement(ComPtr<ABI::Windows::UI::Xaml::IUIElement> &element)
+{
+ qCDebug(lcQpaMime) << __FUNCTION__;
+ m_ui = element;
+ // We set the element to always accept drops and then evaluate during
+ // runtime
+ HRESULT hr = element->put_AllowDrop(TRUE);
+ EventRegistrationToken tok;
+ hr = element->add_DragEnter(m_enter, &tok);
+ RETURN_VOID_IF_FAILED("Failed to add DragEnter handler.");
+ hr = element->add_DragOver(m_over, &tok);
+ RETURN_VOID_IF_FAILED("Failed to add DragOver handler.");
+ hr = element->add_DragLeave(m_leave, &tok);
+ RETURN_VOID_IF_FAILED("Failed to add DragLeave handler.");
+ hr = element->add_Drop(m_drop, &tok);
+ RETURN_VOID_IF_FAILED("Failed to add Drop handler.");
+}
+
+void QWinRTDrag::handleNativeDragEvent(IInspectable *sender, ABI::Windows::UI::Xaml::IDragEventArgs *e, bool drop)
+{
+ Q_UNUSED(sender);
+
+ if (!m_dragTarget)
+ return;
+
+ HRESULT hr;
+ Point relativePoint;
+ hr = e->GetPosition(m_ui.Get(), &relativePoint);
+ RETURN_VOID_IF_FAILED("Could not query drag position.");
+ const QPoint p(relativePoint.X, relativePoint.Y);
+
+ ComPtr<IDragEventArgs2> e2;
+ hr = e->QueryInterface(IID_PPV_ARGS(&e2));
+ RETURN_VOID_IF_FAILED("Could not convert drag event args");
+
+ DragDropModifiers modifiers;
+ hr = e2->get_Modifiers(&modifiers);
+
+#ifndef QT_WINRT_LIMITED_DRAGANDDROP
+ ComPtr<IDragEventArgs3> e3;
+ hr = e->QueryInterface(IID_PPV_ARGS(&e3));
+ Q_ASSERT_SUCCEEDED(hr);
+
+ DataPackageOperation dataOp;
+ hr = e3->get_AllowedOperations(&dataOp);
+ if (FAILED(hr))
+ qCDebug(lcQpaMime) << __FUNCTION__ << "Could not query drag operations";
+
+ const Qt::DropActions actions = translateToQDragDropActions(dataOp);
+#else // !QT_WINRT_LIMITED_DRAGANDDROP
+ const Qt::DropActions actions = Qt::LinkAction | Qt::CopyAction | Qt::MoveAction;;
+#endif // !QT_WINRT_LIMITED_DRAGANDDROP
+
+ ComPtr<IDataPackageView> dataView;
+ hr = e2->get_DataView(&dataView);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ m_mimeData->setDataView(dataView);
+
+ // We use deferral as we need to jump to the Qt thread to handle
+ // the drag event
+ ComPtr<IDragOperationDeferral> deferral;
+ hr = e2->GetDeferral(&deferral);
+ Q_ASSERT_SUCCEEDED(hr);
+
+ DragThreadTransferData *transferData = new DragThreadTransferData;
+ transferData->moveToThread(qGuiApp->thread());
+ transferData->window = m_dragTarget;
+ transferData->point = p;
+ transferData->mime = m_mimeData;
+ transferData->actions = actions;
+ transferData->dropAction = drop;
+ transferData->nativeArgs = e;
+ transferData->deferral = deferral;
+ QMetaObject::invokeMethod(transferData, "handleDrag", Qt::QueuedConnection);
+}
+
+DragThreadTransferData::DragThreadTransferData(QObject *parent)
+ : QObject(parent)
+ , dropAction(false)
+{
+}
+
+void DragThreadTransferData::handleDrag()
+{
+ bool accepted = false;
+ Qt::DropAction acceptedAction;
+ if (dropAction) {
+ QPlatformDropQtResponse response = QWindowSystemInterface::handleDrop(window, mime, point, actions);
+ accepted = response.isAccepted();
+ acceptedAction = response.acceptedAction();
+ } else {
+ QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(window, mime, point, actions);
+ accepted = response.isAccepted();
+ acceptedAction = response.acceptedAction();
+ }
+
+ HRESULT hr;
+ hr = QEventDispatcherWinRT::runOnXamlThread([accepted, acceptedAction, this]() {
+ HRESULT hr;
+ hr = nativeArgs->put_Handled(accepted);
+ if (acceptedAction != Qt::IgnoreAction) {
+ ComPtr<IDragEventArgs2> e2;
+ hr = nativeArgs.As(&e2);
+ if (SUCCEEDED(hr))
+ hr = e2->put_AcceptedOperation(translateFromQDragDropActions(acceptedAction));
+ }
+ deferral->Complete();
+ return S_OK;
+ });
+ Q_ASSERT_SUCCEEDED(hr);
+ deleteLater();
+}
+
+QT_END_NAMESPACE
+
+#include "qwinrtdrag.moc"
diff --git a/src/plugins/platforms/winrt/qwinrtdrag.h b/src/plugins/platforms/winrt/qwinrtdrag.h
new file mode 100644
index 0000000000..97079d831b
--- /dev/null
+++ b/src/plugins/platforms/winrt/qwinrtdrag.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qpa/qplatformdrag.h>
+
+#include <QtCore/QLoggingCategory>
+#include <QtCore/QMimeData>
+#include <QtGui/private/qdnd_p.h> // QInternalMime
+
+#include <wrl.h>
+
+namespace ABI {
+ namespace Windows {
+ namespace ApplicationModel {
+ namespace DataTransfer {
+ struct IDataPackageView;
+ }
+ }
+ namespace UI {
+ namespace Xaml {
+ struct IUIElement;
+ struct IDragEventArgs;
+ struct IDragOperationDeferral;
+ //struct IDataPackageView;
+ }
+ }
+ }
+}
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(lcQpaMime)
+
+class QtDragEventHandlerEnter;
+class QtDragEventHandlerOver;
+class QtDragEventHandlerLeave;
+class QtDragEventHandlerDrop;
+class QWinRTInternalMimeData;
+
+class QWinRTInternalMimeData : public QInternalMimeData {
+public:
+ QWinRTInternalMimeData();
+ virtual ~QWinRTInternalMimeData();
+
+ bool hasFormat_sys(const QString &mimetype) const Q_DECL_OVERRIDE;
+ QStringList formats_sys() const Q_DECL_OVERRIDE;
+ QVariant retrieveData_sys(const QString &mimetype, QVariant::Type preferredType) const Q_DECL_OVERRIDE;
+
+ void setDataView(const Microsoft::WRL::ComPtr<ABI::Windows::ApplicationModel::DataTransfer::IDataPackageView> &d);
+private:
+ Microsoft::WRL::ComPtr<ABI::Windows::ApplicationModel::DataTransfer::IDataPackageView> dataView;
+ mutable QStringList formats;
+};
+
+class QWinRTDrag : public QPlatformDrag {
+public:
+ QWinRTDrag();
+ virtual ~QWinRTDrag();
+ static QWinRTDrag *instance();
+
+ QMimeData *platformDropData(void) Q_DECL_OVERRIDE;
+ Qt::DropAction drag(QDrag *) Q_DECL_OVERRIDE;
+
+ void setDropTarget(QWindow *target);
+
+ // Native integration and registration
+ void setUiElement(Microsoft::WRL::ComPtr<ABI::Windows::UI::Xaml::IUIElement> &element);
+
+ void handleNativeDragEvent(IInspectable *sender, ABI::Windows::UI::Xaml::IDragEventArgs *e, bool drop = false);
+private:
+ Microsoft::WRL::ComPtr<ABI::Windows::UI::Xaml::IUIElement> m_ui;
+ QWindow *m_dragTarget;
+ QtDragEventHandlerEnter *m_enter;
+ QtDragEventHandlerOver *m_over;
+ QtDragEventHandlerLeave *m_leave;
+ QtDragEventHandlerDrop *m_drop;
+ QWinRTInternalMimeData *m_mimeData;
+};
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp
index 8ef560ba20..42b7f7e909 100644
--- a/src/plugins/platforms/winrt/qwinrtintegration.cpp
+++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp
@@ -48,6 +48,9 @@
#include "qwinrtfontdatabase.h"
#include "qwinrttheme.h"
#include "qwinrtclipboard.h"
+#ifndef QT_NO_DRAGANDDROP
+#include "qwinrtdrag.h"
+#endif
#include <QtGui/QOffscreenSurface>
#include <QtGui/QOpenGLContext>
@@ -312,6 +315,17 @@ QPlatformClipboard *QWinRTIntegration::clipboard() const
return d->clipboard;
}
+#ifndef QT_NO_DRAGANDDROP
+QPlatformDrag *QWinRTIntegration::drag() const
+{
+#if _MSC_VER >= 1900
+ return QWinRTDrag::instance();
+#else
+ return QPlatformIntegration::drag();
+#endif
+}
+#endif // QT_NO_DRAGANDDROP
+
Qt::KeyboardModifiers QWinRTIntegration::queryKeyboardModifiers() const
{
Q_D(const QWinRTIntegration);
diff --git a/src/plugins/platforms/winrt/qwinrtintegration.h b/src/plugins/platforms/winrt/qwinrtintegration.h
index 9e28beb8fa..7b4d5531fc 100644
--- a/src/plugins/platforms/winrt/qwinrtintegration.h
+++ b/src/plugins/platforms/winrt/qwinrtintegration.h
@@ -97,6 +97,10 @@ public:
QPlatformInputContext *inputContext() const Q_DECL_OVERRIDE;
QPlatformServices *services() const Q_DECL_OVERRIDE;
QPlatformClipboard *clipboard() const Q_DECL_OVERRIDE;
+#ifndef QT_NO_DRAGANDDROP
+ QPlatformDrag *drag() const Q_DECL_OVERRIDE;
+#endif
+
Qt::KeyboardModifiers queryKeyboardModifiers() const Q_DECL_OVERRIDE;
QStringList themeNames() const Q_DECL_OVERRIDE;
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp
index aed33f6b48..ad32e63cad 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.cpp
+++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp
@@ -42,6 +42,9 @@
#include "qwinrtbackingstore.h"
#include "qwinrtinputcontext.h"
#include "qwinrtcursor.h"
+#ifndef QT_NO_DRAGANDDROP
+#include "qwinrtdrag.h"
+#endif
#include "qwinrtwindow.h"
#include <private/qeventdispatcher_winrt_p.h>
@@ -556,6 +559,9 @@ QWinRTScreen::QWinRTScreen()
ComPtr<Xaml::IUIElement> uiElement;
hr = canvas.As(&uiElement);
Q_ASSERT_SUCCEEDED(hr);
+#if _MSC_VER >= 1900 && !defined(QT_NO_DRAGANDDROP)
+ QWinRTDrag::instance()->setUiElement(uiElement);
+#endif
hr = window->put_Content(uiElement.Get());
Q_ASSERT_SUCCEEDED(hr);
hr = canvas.As(&d->canvas);
@@ -764,6 +770,10 @@ void QWinRTScreen::addWindow(QWindow *window)
QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason);
handleExpose();
QWindowSystemInterface::flushWindowSystemEvents();
+
+#if _MSC_VER >= 1900 && !defined(QT_NO_DRAGANDDROP)
+ QWinRTDrag::instance()->setDropTarget(window);
+#endif
}
void QWinRTScreen::removeWindow(QWindow *window)
@@ -778,6 +788,10 @@ void QWinRTScreen::removeWindow(QWindow *window)
QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason);
handleExpose();
QWindowSystemInterface::flushWindowSystemEvents();
+#if _MSC_VER >= 1900 && !defined(QT_NO_DRAGANDDROP)
+ if (wasTopWindow)
+ QWinRTDrag::instance()->setDropTarget(topWindow());
+#endif
}
void QWinRTScreen::raise(QWindow *window)
@@ -973,6 +987,9 @@ HRESULT QWinRTScreen::onPointerExited(ICoreWindow *, IPointerEventArgs *args)
return S_OK;
}
+// Required for qwinrtdrag.cpp
+ComPtr<IPointerPoint> qt_winrt_lastPointerPoint;
+
HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args)
{
Q_D(QWinRTScreen);
@@ -980,6 +997,7 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args)
if (FAILED(args->get_CurrentPoint(&pointerPoint)))
return E_INVALIDARG;
+ qt_winrt_lastPointerPoint = pointerPoint;
// Common traits - point, modifiers, properties
Point point;
pointerPoint->get_Position(&point);
diff --git a/src/plugins/platforms/winrt/winrt.pro b/src/plugins/platforms/winrt/winrt.pro
index 144c581015..28456f66ec 100644
--- a/src/plugins/platforms/winrt/winrt.pro
+++ b/src/plugins/platforms/winrt/winrt.pro
@@ -14,6 +14,7 @@ SOURCES = \
qwinrtbackingstore.cpp \
qwinrtclipboard.cpp \
qwinrtcursor.cpp \
+ qwinrtdrag.cpp \
qwinrteglcontext.cpp \
qwinrteventdispatcher.cpp \
qwinrtfiledialoghelper.cpp \
@@ -32,6 +33,7 @@ HEADERS = \
qwinrtbackingstore.h \
qwinrtclipboard.h \
qwinrtcursor.h \
+ qwinrtdrag.h \
qwinrteglcontext.h \
qwinrteventdispatcher.h \
qwinrtfiledialoghelper.h \
@@ -47,6 +49,15 @@ HEADERS = \
OTHER_FILES += winrt.json
+WINRT_SDK_VERSION_STRING = $$(UCRTVersion)
+WINRT_SDK_VERSION = $$member($$list($$split(WINRT_SDK_VERSION_STRING, .)), 2)
+lessThan(WINRT_SDK_VERSION, 14322): DEFINES += QT_WINRT_LIMITED_DRAGANDDROP
+
+*-msvc2013|contains(DEFINES, QT_NO_DRAGANDDROP) {
+ SOURCES -= qwinrtdrag.cpp
+ HEADERS -= qwinrtdrag.h
+}
+
PLUGIN_TYPE = platforms
PLUGIN_CLASS_NAME = QWinRTIntegrationPlugin
!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp
index d536121521..f97c01f390 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp
@@ -207,8 +207,10 @@ QPlatformOffscreenSurface *QXcbGlxIntegration::createPlatformOffscreenSurface(QO
display = static_cast<Display *>(m_connection->xlib_display());
#endif
const char *glxvendor = glXGetClientString(display, GLX_VENDOR);
- if (glxvendor && !strcmp(glxvendor, "ATI"))
- glxPbufferUsable = false;
+ if (glxvendor) {
+ if (!strcmp(glxvendor, "ATI") || !strcmp(glxvendor, "Chromium"))
+ glxPbufferUsable = false;
+ }
}
if (glxPbufferUsable)
return new QGLXPbuffer(surface);
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 377cb626ee..5d46c53b30 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/private/qhighdpiscaling_p.h>
#include <QtCore/QDebug>
#include "qxcbconnection.h"
@@ -264,6 +265,7 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
} else {
screen = createScreen(virtualDesktop, output, outputInfo.data());
qCDebug(lcQpaScreen) << "output" << screen->name() << "is connected and enabled";
+ QHighDpiScaling::updateHighDpiScaling();
}
}
} else if (screen) {
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 789229c0a7..063778a1de 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -797,9 +797,9 @@ void QXcbWindow::show()
propagateSizeHints();
// update WM_TRANSIENT_FOR
- const QWindow *tp = window()->transientParent();
- if (isTransient(window()) || tp != 0) {
- xcb_window_t transientXcbParent = 0;
+ xcb_window_t transientXcbParent = 0;
+ if (isTransient(window())) {
+ const QWindow *tp = window()->transientParent();
if (tp && tp->handle())
transientXcbParent = static_cast<const QXcbWindow *>(tp->handle())->winId();
// Default to client leader if there is no transient parent, else modal dialogs can
@@ -812,6 +812,8 @@ void QXcbWindow::show()
1, &transientXcbParent));
}
}
+ if (!transientXcbParent)
+ Q_XCB_CALL(xcb_delete_property(xcb_connection(), m_window, XCB_ATOM_WM_TRANSIENT_FOR));
// update _MOTIF_WM_HINTS
updateMotifWmHintsBeforeMap();
@@ -1173,9 +1175,11 @@ void QXcbWindow::setMotifWindowFlags(Qt::WindowFlags flags)
mwmhints.flags |= MWM_HINTS_DECORATIONS;
bool customize = flags & Qt::CustomizeWindowHint;
- if (type == Qt::Window && !customize)
- flags |= Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint;
-
+ if (type == Qt::Window && !customize) {
+ const Qt::WindowFlags defaultFlags = Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint;
+ if (!(flags & defaultFlags))
+ flags |= defaultFlags;
+ }
if (!(flags & Qt::FramelessWindowHint) && !(customize && !(flags & Qt::WindowTitleHint))) {
mwmhints.decorations |= MWM_DECOR_BORDER;
mwmhints.decorations |= MWM_DECOR_RESIZEH;
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index 55660ce31c..0f4207c636 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -6,7 +6,7 @@ qtHaveModule(network):!contains(QT_DISABLED_FEATURES, bearermanagement): SUBDIRS
qtHaveModule(gui) {
SUBDIRS *= platforms platforminputcontexts platformthemes
!contains(QT_DISABLED_FEATURES, imageformatplugin): SUBDIRS *= imageformats
- !contains(QT_DISABLED_FEATURES, library): SUBDIRS *= generic
+ !android:!contains(QT_DISABLED_FEATURES, library): SUBDIRS *= generic
}
!winrt:!wince*:qtHaveModule(widgets):!contains(QT_DISABLED_FEATURES, printer) {
diff --git a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp
index 6f5fb417c6..7e6eb7c559 100644
--- a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp
+++ b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2014 John Layt <jlayt@kde.org>
+** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@@ -80,6 +81,22 @@ static QPrint::InputSlot paperBinToInputSlot(int windowsId, const QString &name)
return slot;
}
+static LPDEVMODE getDevmode(HANDLE hPrinter, const QString &printerId)
+{
+ LPWSTR printerIdUtf16 = const_cast<LPWSTR>(reinterpret_cast<LPCWSTR>(printerId.utf16()));
+ // Allocate the required DEVMODE buffer
+ LONG dmSize = DocumentProperties(NULL, hPrinter, printerIdUtf16, NULL, NULL, 0);
+ if (dmSize < 0)
+ return Q_NULLPTR;
+ LPDEVMODE pDevMode = reinterpret_cast<LPDEVMODE>(malloc(dmSize));
+ // Get the default DevMode
+ LONG result = DocumentProperties(NULL, hPrinter, printerIdUtf16, pDevMode, NULL, DM_OUT_BUFFER);
+ if (result != IDOK) {
+ free(pDevMode);
+ pDevMode = Q_NULLPTR;
+ }
+ return pDevMode;
+}
QWindowsPrintDevice::QWindowsPrintDevice()
: QPlatformPrintDevice(),
@@ -197,26 +214,21 @@ QPageSize QWindowsPrintDevice::defaultPageSize() const
QPageSize pageSize;
- // Allocate the required DEVMODE buffer
- DWORD dmSize = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), NULL, NULL, 0);
- LPDEVMODE pDevMode = (LPDEVMODE)malloc(dmSize);
-
- // Get the default DevMode
- DWORD result = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), pDevMode, NULL, DM_OUT_BUFFER);
-
- // Get the default paper size
- if (result == IDOK && pDevMode->dmFields & DM_PAPERSIZE) {
- // Find the supported page size that matches, in theory default should be one of them
- foreach (const QPageSize &ps, m_pageSizes) {
- if (ps.windowsId() == pDevMode->dmPaperSize) {
- pageSize = ps;
- break;
+ if (LPDEVMODE pDevMode = getDevmode(m_hPrinter, m_id)) {
+ // Get the default paper size
+ if (pDevMode->dmFields & DM_PAPERSIZE) {
+ // Find the supported page size that matches, in theory default should be one of them
+ foreach (const QPageSize &ps, m_pageSizes) {
+ if (ps.windowsId() == pDevMode->dmPaperSize) {
+ pageSize = ps;
+ break;
+ }
}
}
+ // Clean-up
+ free(pDevMode);
}
- // Clean-up
- free(pDevMode);
return pageSize;
}
@@ -232,20 +244,14 @@ QMarginsF QWindowsPrintDevice::printableMargins(const QPageSize &pageSize,
QScopedArrayPointer<BYTE> buffer(new BYTE[needed]);
if (GetPrinter(m_hPrinter, 2, buffer.data(), needed, &needed)) {
PPRINTER_INFO_2 info = reinterpret_cast<PPRINTER_INFO_2>(buffer.data());
- DEVMODE *devMode = info->pDevMode;
+ LPDEVMODE devMode = info->pDevMode;
bool separateDevMode = false;
if (!devMode) {
// GetPrinter() didn't include the DEVMODE. Get it a different way.
- LONG result = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(),
- NULL, NULL, 0);
- devMode = (DEVMODE *)malloc(result);
- separateDevMode = true;
- result = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(),
- devMode, NULL, DM_OUT_BUFFER);
- if (result != IDOK) {
- free(devMode);
+ devMode = getDevmode(m_hPrinter, m_id);
+ if (!devMode)
return margins;
- }
+ separateDevMode = true;
}
HDC pDC = CreateDC(NULL, (LPWSTR)m_id.utf16(), NULL, devMode);
@@ -297,23 +303,17 @@ int QWindowsPrintDevice::defaultResolution() const
{
int resolution = 72; // TODO Set a sensible default?
- // Allocate the required DEVMODE buffer
- DWORD dmSize = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), NULL, NULL, 0);
- LPDEVMODE pDevMode = (LPDEVMODE)malloc(dmSize);
-
- // Get the default DevMode
- DWORD result = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), pDevMode, NULL, DM_OUT_BUFFER);
-
- // Get the default resolution
- if (result == IDOK && pDevMode->dmFields & DM_YRESOLUTION) {
- if (pDevMode->dmPrintQuality > 0)
- resolution = pDevMode->dmPrintQuality;
- else
- resolution = pDevMode->dmYResolution;
+ if (LPDEVMODE pDevMode = getDevmode(m_hPrinter, m_id)) {
+ // Get the default resolution
+ if (pDevMode->dmFields & DM_YRESOLUTION) {
+ if (pDevMode->dmPrintQuality > 0)
+ resolution = pDevMode->dmPrintQuality;
+ else
+ resolution = pDevMode->dmYResolution;
+ }
+ // Clean-up
+ free(pDevMode);
}
-
- // Clean-up
- free(pDevMode);
return resolution;
}
@@ -346,26 +346,20 @@ QPrint::InputSlot QWindowsPrintDevice::defaultInputSlot() const
{
QPrint::InputSlot inputSlot = QPlatformPrintDevice::defaultInputSlot();;
- // Allocate the required DEVMODE buffer
- DWORD dmSize = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), NULL, NULL, 0);
- LPDEVMODE pDevMode = (LPDEVMODE)malloc(dmSize);
-
- // Get the default DevMode
- DWORD result = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), pDevMode, NULL, DM_OUT_BUFFER);
-
- // Get the default input slot
- if (result == IDOK && pDevMode->dmFields & DM_DEFAULTSOURCE) {
- QPrint::InputSlot tempSlot = paperBinToInputSlot(pDevMode->dmDefaultSource, QString());
- foreach (const QPrint::InputSlot &slot, supportedInputSlots()) {
- if (slot.key == tempSlot.key) {
- inputSlot = slot;
- break;
+ if (LPDEVMODE pDevMode = getDevmode(m_hPrinter, m_id)) {
+ // Get the default input slot
+ if (pDevMode->dmFields & DM_DEFAULTSOURCE) {
+ QPrint::InputSlot tempSlot = paperBinToInputSlot(pDevMode->dmDefaultSource, QString());
+ foreach (const QPrint::InputSlot &slot, supportedInputSlots()) {
+ if (slot.key == tempSlot.key) {
+ inputSlot = slot;
+ break;
+ }
}
}
+ // Clean-up
+ free(pDevMode);
}
-
- // Clean-up
- free(pDevMode);
return inputSlot;
}
@@ -392,23 +386,17 @@ QPrint::DuplexMode QWindowsPrintDevice::defaultDuplexMode() const
{
QPrint::DuplexMode duplexMode = QPrint::DuplexNone;
- // Allocate the required DEVMODE buffer
- DWORD dmSize = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), NULL, NULL, 0);
- LPDEVMODE pDevMode = (LPDEVMODE)malloc(dmSize);
-
- // Get the default DevMode
- DWORD result = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), pDevMode, NULL, DM_OUT_BUFFER);
-
- // Get the default duplex mode
- if (result == IDOK && pDevMode->dmFields & DM_DUPLEX) {
- if (pDevMode->dmDuplex == DMDUP_VERTICAL)
- duplexMode = QPrint::DuplexLongSide;
- else if (pDevMode->dmDuplex == DMDUP_HORIZONTAL)
- duplexMode = QPrint::DuplexShortSide;
+ if (LPDEVMODE pDevMode = getDevmode(m_hPrinter, m_id)) {
+ // Get the default duplex mode
+ if (pDevMode->dmFields & DM_DUPLEX) {
+ if (pDevMode->dmDuplex == DMDUP_VERTICAL)
+ duplexMode = QPrint::DuplexLongSide;
+ else if (pDevMode->dmDuplex == DMDUP_HORIZONTAL)
+ duplexMode = QPrint::DuplexShortSide;
+ }
+ // Clean-up
+ free(pDevMode);
}
-
- // Clean-up
- free(pDevMode);
return duplexMode;
}
@@ -430,21 +418,13 @@ QPrint::ColorMode QWindowsPrintDevice::defaultColorMode() const
QPrint::ColorMode colorMode = QPrint::GrayScale;
- // Allocate the required DEVMODE buffer
- DWORD dmSize = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), NULL, NULL, 0);
- LPDEVMODE pDevMode = (LPDEVMODE)malloc(dmSize);
-
- // Get the default DevMode
- DWORD result = DocumentProperties(NULL, m_hPrinter, (LPWSTR)m_id.utf16(), pDevMode, NULL, DM_OUT_BUFFER);
-
- // Get the default color mode
- if (result == IDOK && pDevMode->dmFields & DM_COLOR) {
- if (pDevMode->dmColor == DMCOLOR_COLOR)
+ if (LPDEVMODE pDevMode = getDevmode(m_hPrinter, m_id)) {
+ // Get the default color mode
+ if (pDevMode->dmFields & DM_COLOR && pDevMode->dmColor == DMCOLOR_COLOR)
colorMode = QPrint::Color;
+ // Clean-up
+ free(pDevMode);
}
-
- // Clean-up
- free(pDevMode);
return colorMode;
}
diff --git a/src/src.pro b/src/src.pro
index fcececdeda..4ca1347f2b 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -88,6 +88,9 @@ src_3rdparty_harfbuzzng.subdir = $$PWD/3rdparty/harfbuzz-ng
src_3rdparty_harfbuzzng.target = sub-3rdparty-harfbuzzng
src_3rdparty_harfbuzzng.depends = src_corelib # for the Qt atomics
+src_3rdparty_libpng.subdir = $$PWD/3rdparty/libpng
+src_3rdparty_libpng.target = sub-3rdparty-libpng
+
src_3rdparty_freetype.subdir = $$PWD/3rdparty/freetype
src_3rdparty_freetype.target = sub-3rdparty-freetype
@@ -132,6 +135,7 @@ src_android.subdir = $$PWD/android
!contains(QT_CONFIG, system-zlib)|cross_compile {
SUBDIRS += src_qtzlib
!contains(QT_CONFIG, system-zlib) {
+ src_3rdparty_libpng.depends += src_corelib
src_3rdparty_freetype.depends += src_corelib
}
}
@@ -163,6 +167,11 @@ contains(QT_CONFIG, concurrent):SUBDIRS += src_concurrent
SUBDIRS += src_angle
src_gui.depends += src_angle
}
+ contains(QT_CONFIG, png) {
+ SUBDIRS += src_3rdparty_libpng
+ src_3rdparty_freetype.depends += src_3rdparty_libpng
+ src_plugins.depends += src_3rdparty_libpng
+ }
contains(QT_CONFIG, freetype):!contains(QT_CONFIG, system-freetype) {
SUBDIRS += src_3rdparty_freetype
src_platformsupport.depends += src_3rdparty_freetype
diff --git a/src/testlib/doc/qttestlib.qdocconf b/src/testlib/doc/qttestlib.qdocconf
index 0fafc733b1..899f94ec53 100644
--- a/src/testlib/doc/qttestlib.qdocconf
+++ b/src/testlib/doc/qttestlib.qdocconf
@@ -4,7 +4,7 @@ project = QtTestLib
description = Qt Test Reference Documentation
version = $QT_VERSION
-examplesinstallpath = testlib
+examplesinstallpath = qtestlib
qhp.projects = QtTestLib
diff --git a/src/testlib/doc/src/qttestlib-manual.qdoc b/src/testlib/doc/src/qttestlib-manual.qdoc
index 62cc6c9654..fc8f3b747e 100644
--- a/src/testlib/doc/src/qttestlib-manual.qdoc
+++ b/src/testlib/doc/src/qttestlib-manual.qdoc
@@ -487,6 +487,7 @@
\nextpage {Chapter 2: Data Driven Testing}{Chapter 2}
\title Chapter 1: Writing a Unit Test
+ \brief How to write a unit test.
In this first chapter we will see how to write a simple unit test
for a class, and how to execute it.
@@ -562,6 +563,7 @@
\nextpage {Chapter 3: Simulating Gui Events}{Chapter 3}
\title Chapter 2: Data Driven Testing
+ \brief How to create data driven tests.
In this chapter we will demonstrate how to execute a test
multiple times with different test data.
@@ -667,6 +669,7 @@
\nextpage {Chapter 4: Replaying GUI Events}{Chapter 4}
\title Chapter 3: Simulating GUI Events
+ \brief Howe to simulate GUI events.
Qt Test features some mechanisms to test graphical user
interfaces. Instead of simulating native window system events,
@@ -727,6 +730,7 @@
\nextpage {Chapter 5: Writing a Benchmark}{Chapter 5}
\title Chapter 4: Replaying GUI Events
+ \brief How to replay GUI events.
In this chapter, we will show how to simulate a GUI event,
and how to store a series of GUI events as well as replay them on
@@ -806,6 +810,7 @@
\contentspage {Qt Test Tutorial}{Contents}
\title Chapter 5: Writing a Benchmark
+ \brief How to write a benchmark.
In this final chapter we will demonstrate how to write benchmarks
using Qt Test.
diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h
index 261c769c15..49a0c2104b 100644
--- a/src/testlib/qtest.h
+++ b/src/testlib/qtest.h
@@ -160,7 +160,7 @@ template<> inline char *toString(const QVariant &v)
if (!v.isNull()) {
vstring.append(',');
if (v.canConvert(QVariant::String)) {
- vstring.append(qvariant_cast<QString>(v).toLocal8Bit());
+ vstring.append(v.toString().toLocal8Bit());
}
else {
vstring.append("<value not representable as string>");
diff --git a/src/testlib/qtestblacklist.cpp b/src/testlib/qtestblacklist.cpp
index 4435b509be..1fa76a692a 100644
--- a/src/testlib/qtestblacklist.cpp
+++ b/src/testlib/qtestblacklist.cpp
@@ -52,21 +52,38 @@
QT_BEGIN_NAMESPACE
/*
- The file format is simply a grouped listing of keywords
- Ungrouped entries at the beginning apply to the whole testcase
- Groups define testfunctions or specific test data to ignore.
- After the groups come a list of entries (one per line) that define
- for which platform/os combination to ignore the test result.
- All keys in a single line have to match to blacklist the test.
-
- mac
- [testFunction]
- linux
- windows 64bit
- [testfunction2:testData]
- msvc
-
- The known keys are listed below:
+ The BLACKLIST file format is a grouped listing of keywords.
+
+ Blank lines and lines starting with # are simply ignored. An initial #-line
+ referring to this documentation is kind to readers. Comments can also be used
+ to indicate the reasons for ignoring particular cases.
+
+ A key names a platform, O/S, distribution, tool-chain or architecture; a !
+ prefix reverses what it checks. A version, joined to a key (at present, only
+ for distributions and for msvc) with a hyphen, limits the key to the specific
+ version. A keyword line matches if every key on it applies to the present
+ run. Successive lines are alternate conditions for ignoring a test.
+
+ Ungrouped lines at the beginning of a file apply to the whole testcase.
+ A group starts with a [square-bracketed] identification of a test function,
+ optionally with (after a colon, the name of) a specific data set, to ignore.
+ Subsequent lines give conditions for ignoring this test.
+
+ # See qtbase/src/testlib/qtestblacklist.cpp for format
+ osx
+
+ # QTBUG-12345
+ [testFunction]
+ linux
+ windows 64bit
+
+ # Needs basic C++11 support
+ [testfunction2:testData]
+ msvc-2010
+
+ Keys are lower-case. Distribution name and version are supported if
+ QSysInfo's productType() and productVersion() return them.
+ The other known keys are listed below:
*/
static QSet<QByteArray> keywords()
@@ -148,19 +165,30 @@ static QSet<QByteArray> keywords()
return set;
}
-static bool checkCondition(const QByteArray &condition)
+static QSet<QByteArray> activeConditions()
{
- static QSet<QByteArray> matchedConditions = keywords();
- QList<QByteArray> conds = condition.split(' ');
+ QSet<QByteArray> result = keywords();
QByteArray distributionName = QSysInfo::productType().toLower().toUtf8();
QByteArray distributionRelease = QSysInfo::productVersion().toLower().toUtf8();
if (!distributionName.isEmpty()) {
- if (matchedConditions.find(distributionName) == matchedConditions.end())
- matchedConditions.insert(distributionName);
- matchedConditions.insert(distributionName + "-" + distributionRelease);
+ if (result.find(distributionName) == result.end())
+ result.insert(distributionName);
+ if (!distributionRelease.isEmpty()) {
+ QByteArray versioned = distributionName + "-" + distributionRelease;
+ if (result.find(versioned) == result.end())
+ result.insert(versioned);
+ }
}
+ return result;
+}
+
+static bool checkCondition(const QByteArray &condition)
+{
+ static const QSet<QByteArray> matchedConditions = activeConditions();
+ QList<QByteArray> conds = condition.split(' ');
+
for (int i = 0; i < conds.size(); ++i) {
QByteArray c = conds.at(i);
bool result = c.startsWith('!');
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index 73303ca28d..b6c70fdd86 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -116,7 +116,7 @@ static bool debuggerPresent()
if (fd == -1)
return false;
char buffer[2048];
- ssize_t size = read(fd, buffer, sizeof(buffer));
+ ssize_t size = read(fd, buffer, sizeof(buffer) - 1);
if (size == -1) {
close(fd);
return false;
diff --git a/src/widgets/dialogs/qdialog.cpp b/src/widgets/dialogs/qdialog.cpp
index 74d138442a..464a1e139e 100644
--- a/src/widgets/dialogs/qdialog.cpp
+++ b/src/widgets/dialogs/qdialog.cpp
@@ -846,6 +846,12 @@ void QDialog::adjustPosition(QWidget* w)
if (p.y() < desk.y())
p.setY(desk.y());
+ // QTBUG-52735: Manually set the correct target screen since scaling in a
+ // subsequent call to QWindow::resize() may otherwise use the wrong factor
+ // if the screen changed notification is still in an event queue.
+ if (QWindow *window = windowHandle())
+ window->setScreen(QGuiApplication::screens().at(scrn));
+
move(p);
}
diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp
index 0ab2e1860c..42e0cc7585 100644
--- a/src/widgets/itemviews/qabstractitemview.cpp
+++ b/src/widgets/itemviews/qabstractitemview.cpp
@@ -3671,6 +3671,9 @@ void QAbstractItemView::startDrag(Qt::DropActions supportedActions)
defaultDropAction = Qt::CopyAction;
if (drag->exec(supportedActions, defaultDropAction) == Qt::MoveAction)
d->clearOrRemove();
+ // Reset the drop indicator
+ d->dropIndicatorRect = QRect();
+ d->dropIndicatorPosition = OnItem;
}
}
#endif // QT_NO_DRAGANDDROP
diff --git a/src/widgets/kernel/qdesktopwidget.cpp b/src/widgets/kernel/qdesktopwidget.cpp
index fceb061867..ece673337a 100644
--- a/src/widgets/kernel/qdesktopwidget.cpp
+++ b/src/widgets/kernel/qdesktopwidget.cpp
@@ -46,6 +46,21 @@
QT_BEGIN_NAMESPACE
+QDesktopScreenWidget::QDesktopScreenWidget(QScreen *screen, const QRect &geometry)
+ : QWidget(Q_NULLPTR, Qt::Desktop), m_screen(screen)
+{
+ setVisible(false);
+ if (QWindow *winHandle = windowHandle())
+ winHandle->setScreen(screen);
+ setScreenGeometry(geometry);
+}
+
+void QDesktopScreenWidget::setScreenGeometry(const QRect &geometry)
+{
+ m_geometry = geometry;
+ setGeometry(geometry);
+}
+
int QDesktopScreenWidget::screenNumber() const
{
const QDesktopWidgetPrivate *desktopWidgetP
@@ -80,54 +95,76 @@ const QRect QDesktopWidget::availableGeometry(const QWidget *widget) const
return rect;
}
+QDesktopScreenWidget *QDesktopWidgetPrivate::widgetForScreen(QScreen *qScreen) const
+{
+ foreach (QDesktopScreenWidget *widget, screens) {
+ if (widget->screen() == qScreen)
+ return widget;
+ }
+ return Q_NULLPTR;
+}
+
void QDesktopWidgetPrivate::_q_updateScreens()
{
Q_Q(QDesktopWidget);
const QList<QScreen *> screenList = QGuiApplication::screens();
const int targetLength = screenList.length();
- const int oldLength = screens.length();
-
- // Add or remove screen widgets as necessary
- while (screens.size() > targetLength)
- delete screens.takeLast();
-
- for (int currentLength = screens.size(); currentLength < targetLength; ++currentLength) {
- QScreen *qScreen = screenList.at(currentLength);
- QDesktopScreenWidget *screenWidget = new QDesktopScreenWidget;
- screenWidget->setGeometry(qScreen->geometry());
- QObject::connect(qScreen, SIGNAL(geometryChanged(QRect)),
- q, SLOT(_q_updateScreens()), Qt::QueuedConnection);
- QObject::connect(qScreen, SIGNAL(availableGeometryChanged(QRect)),
- q, SLOT(_q_availableGeometryChanged()), Qt::QueuedConnection);
- QObject::connect(qScreen, SIGNAL(destroyed()),
- q, SLOT(_q_updateScreens()), Qt::QueuedConnection);
- screens.append(screenWidget);
- }
+ bool screenCountChanged = false;
+ // Re-build our screens list. This is the easiest way to later compute which signals to emit.
+ // Create new screen widgets as necessary. While iterating, keep the old list in place so
+ // that widgetForScreen works.
+ // Furthermore, we note which screens have changed, and compute the overall virtual geometry.
+ QList<QDesktopScreenWidget *> newScreens;
+ QList<int> changedScreens;
QRegion virtualGeometry;
- // update the geometry of each screen widget, determine virtual geometry,
- // set the new screen for window handle and emit change signals afterwards.
- QList<int> changedScreens;
- for (int i = 0; i < screens.length(); i++) {
- QDesktopScreenWidget *screenWidget = screens.at(i);
+ for (int i = 0; i < targetLength; ++i) {
QScreen *qScreen = screenList.at(i);
- QWindow *winHandle = screenWidget->windowHandle();
- if (winHandle && winHandle->screen() != qScreen)
- winHandle->setScreen(qScreen);
const QRect screenGeometry = qScreen->geometry();
- if (screenGeometry != screenWidget->geometry()) {
- screenWidget->setGeometry(screenGeometry);
- changedScreens.push_back(i);
+ QDesktopScreenWidget *screenWidget = widgetForScreen(qScreen);
+ if (screenWidget) {
+ // an old screen. update geometry and remember the index in the *new* list
+ if (screenGeometry != screenWidget->screenGeometry()) {
+ screenWidget->setScreenGeometry(screenGeometry);
+ changedScreens.push_back(i);
+ }
+ } else {
+ // a new screen, create a widget and connect the signals.
+ screenWidget = new QDesktopScreenWidget(qScreen, screenGeometry);
+ QObject::connect(qScreen, SIGNAL(geometryChanged(QRect)),
+ q, SLOT(_q_updateScreens()), Qt::QueuedConnection);
+ QObject::connect(qScreen, SIGNAL(availableGeometryChanged(QRect)),
+ q, SLOT(_q_availableGeometryChanged()), Qt::QueuedConnection);
+ QObject::connect(qScreen, SIGNAL(destroyed()),
+ q, SLOT(_q_updateScreens()), Qt::QueuedConnection);
+ screenCountChanged = true;
}
+ // record all the screens and the overall geometry.
+ newScreens.push_back(screenWidget);
virtualGeometry += screenGeometry;
}
+ // Now we apply the accumulated updates.
+ screens.swap(newScreens); // now [newScreens] is the old screen list
+ Q_ASSERT(screens.size() == targetLength);
q->setGeometry(virtualGeometry.boundingRect());
- if (oldLength != targetLength)
- emit q->screenCountChanged(targetLength);
+ // Delete the QDesktopScreenWidget that are not used any more.
+ foreach (QDesktopScreenWidget *screen, newScreens) {
+ if (!screens.contains(screen)) {
+ delete screen;
+ screenCountChanged = true;
+ }
+ }
+ // Finally, emit the signals.
+ if (screenCountChanged) {
+ // Notice that we trigger screenCountChanged even if a screen was removed and another one added,
+ // in which case the total number of screens did not change. This is the only way for applications
+ // to notice that a screen was swapped out against another one.
+ emit q->screenCountChanged(targetLength);
+ }
foreach (int changedScreen, changedScreens)
emit q->resized(changedScreen);
}
diff --git a/src/widgets/kernel/qdesktopwidget_p.h b/src/widgets/kernel/qdesktopwidget_p.h
index 7c68ad9b31..a590024b7c 100644
--- a/src/widgets/kernel/qdesktopwidget_p.h
+++ b/src/widgets/kernel/qdesktopwidget_p.h
@@ -61,12 +61,19 @@ QT_BEGIN_NAMESPACE
class QDesktopScreenWidget : public QWidget {
Q_OBJECT
public:
- QDesktopScreenWidget() : QWidget(Q_NULLPTR, Qt::Desktop)
- {
- setVisible(false);
- }
+ explicit QDesktopScreenWidget(QScreen *screen, const QRect &geometry);
int screenNumber() const;
+ void setScreenGeometry(const QRect &geometry);
+
+ QScreen *screen() const { return m_screen.data(); }
+ QRect screenGeometry() const { return m_geometry; }
+
+private:
+ // The widget updates its screen and geometry automatically. We need to save them separately
+ // to detect changes, and trigger the appropriate signals.
+ const QPointer<QScreen> m_screen;
+ QRect m_geometry;
};
class QDesktopWidgetPrivate : public QWidgetPrivate {
@@ -76,6 +83,7 @@ public:
~QDesktopWidgetPrivate() { qDeleteAll(screens); }
void _q_updateScreens();
void _q_availableGeometryChanged();
+ QDesktopScreenWidget *widgetForScreen(QScreen *qScreen) const;
QList<QDesktopScreenWidget *> screens;
};
diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp
index 5071c56763..124c8c000a 100644
--- a/src/widgets/kernel/qopenglwidget.cpp
+++ b/src/widgets/kernel/qopenglwidget.cpp
@@ -910,8 +910,10 @@ void QOpenGLWidgetPrivate::resizeViewportFramebuffer()
if (!initialized)
return;
- if (!fbo || q->size() * q->devicePixelRatioF() != fbo->size())
+ if (!fbo || q->size() * q->devicePixelRatioF() != fbo->size()) {
recreateFbo();
+ q->update();
+ }
}
/*!
diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp
index 7c9ac5571c..ecaba584f2 100644
--- a/src/widgets/kernel/qwidgetbackingstore.cpp
+++ b/src/widgets/kernel/qwidgetbackingstore.cpp
@@ -992,8 +992,18 @@ static QPlatformTextureList *widgetTexturesFor(QWidget *tlw, QWidget *widget)
static bool switchableWidgetComposition =
QGuiApplicationPrivate::instance()->platformIntegration()
->hasCapability(QPlatformIntegration::SwitchableWidgetComposition);
- if (!switchableWidgetComposition)
+ if (!switchableWidgetComposition
+// The Windows compositor handles fullscreen OpenGL window specially. Besides
+// having trouble with popups, it also has issues with flip-flopping between
+// OpenGL-based and normal flushing. Therefore, stick with GL for fullscreen
+// windows. (QTBUG-53515)
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) && !defined(Q_OS_WINCE)
+ || tlw->windowState().testFlag(Qt::WindowFullScreen)
+#endif
+ )
+ {
return qt_dummy_platformTextureList();
+ }
}
return 0;
@@ -1192,10 +1202,20 @@ void QWidgetBackingStore::doSync()
// We know for sure that the widget isn't overlapped if 'isMoved' is true.
if (!wd->isMoved)
wd->subtractOpaqueSiblings(wd->dirty, &hasDirtySiblingsAbove);
+
+ // Make a copy of the widget's dirty region, to restore it in case there is an opaque
+ // render-to-texture child that completely covers the widget, because otherwise the
+ // render-to-texture child won't be visible, due to its parent widget not being redrawn
+ // with a proper blending mask.
+ const QRegion dirtyBeforeSubtractedOpaqueChildren = wd->dirty;
+
// Scrolled and moved widgets must draw all children.
if (!wd->isScrolled && !wd->isMoved)
wd->subtractOpaqueChildren(wd->dirty, w->rect());
+ if (wd->dirty.isEmpty() && wd->textureChildSeen)
+ wd->dirty = dirtyBeforeSubtractedOpaqueChildren;
+
if (wd->dirty.isEmpty()) {
resetWidget(w);
continue;
diff --git a/src/widgets/kernel/qwidgetbackingstore_p.h b/src/widgets/kernel/qwidgetbackingstore_p.h
index a7dbfafc05..dc20446047 100644
--- a/src/widgets/kernel/qwidgetbackingstore_p.h
+++ b/src/widgets/kernel/qwidgetbackingstore_p.h
@@ -116,7 +116,7 @@ public:
inline bool isDirty() const
{
- return !(dirtyWidgets.isEmpty() && dirty.isEmpty());
+ return !(dirtyWidgets.isEmpty() && dirty.isEmpty() && dirtyRenderToTextureWidgets.isEmpty());
}
// ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore).
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index 675d54f6b4..2a4f31babf 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -883,14 +883,8 @@ void QWidgetWindow::handleExposeEvent(QExposeEvent *event)
{
if (isExposed()) {
m_widget->setAttribute(Qt::WA_Mapped);
- if (!event->region().isNull()) {
- // Exposed native widgets need to be marked dirty to get them repainted correctly.
- if (m_widget->internalWinId() && !m_widget->isWindow() && m_widget->isVisible() && m_widget->updatesEnabled()) {
- if (QWidgetBackingStore *bs = m_widget->d_func()->maybeBackingStore())
- bs->markDirty(event->region(), m_widget);
- }
+ if (!event->region().isNull())
m_widget->d_func()->syncBackingStore(event->region());
- }
} else {
m_widget->setAttribute(Qt::WA_Mapped, false);
}
diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp
index 1ac28f548b..06c3101643 100644
--- a/src/widgets/styles/qfusionstyle.cpp
+++ b/src/widgets/styles/qfusionstyle.cpp
@@ -2389,8 +2389,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
if (!titleBar->icon.isNull()) {
titleBar->icon.paint(painter, iconRect);
} else {
- QStyleOption tool(0);
- tool.palette = titleBar->palette;
+ QStyleOption tool = *titleBar;
QPixmap pm = proxy()->standardIcon(SP_TitleBarMenuButton, &tool, widget).pixmap(16, 16);
tool.rect = iconRect;
painter->save();
diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm
index deb2fb4da0..56531b10de 100644
--- a/src/widgets/styles/qmacstyle_mac.mm
+++ b/src/widgets/styles/qmacstyle_mac.mm
@@ -5951,12 +5951,10 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
#ifndef QT_NO_ACCESSIBILITY
if (QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ToolBar)) {
if (tb->subControls & SC_ToolButtonMenu) {
- QStyleOption arrowOpt(0);
+ QStyleOption arrowOpt = *tb;
arrowOpt.rect = proxy()->subControlRect(cc, tb, SC_ToolButtonMenu, widget);
arrowOpt.rect.setY(arrowOpt.rect.y() + arrowOpt.rect.height() / 2);
arrowOpt.rect.setHeight(arrowOpt.rect.height() / 2);
- arrowOpt.state = tb->state;
- arrowOpt.palette = tb->palette;
proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget);
} else if ((tb->features & QStyleOptionToolButton::HasMenu)
&& (tb->toolButtonStyle != Qt::ToolButtonTextOnly && !tb->icon.isNull())) {
diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp
index 7ce9bbc273..b41ad4249e 100644
--- a/src/widgets/styles/qwindowsstyle.cpp
+++ b/src/widgets/styles/qwindowsstyle.cpp
@@ -2131,9 +2131,8 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp
if (sunkenArrow)
flags |= State_Sunken;
- QStyleOption arrowOpt(0);
+ QStyleOption arrowOpt = *cmb;
arrowOpt.rect = ar.adjusted(1, 1, -1, -1);
- arrowOpt.palette = cmb->palette;
arrowOpt.state = flags;
proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget);
}
diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp
index 83820016aa..6009b5d1f8 100644
--- a/src/widgets/styles/qwindowsvistastyle.cpp
+++ b/src/widgets/styles/qwindowsvistastyle.cpp
@@ -1059,7 +1059,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
QPainter imagePainter(&image);
theme.painter = &imagePainter;
theme.partId = vertical ? PP_FILLVERT : PP_FILL;
- theme.rect = QRect(QPoint(0,0), theme.rect.size());
+ theme.rect = QRect(QPoint(0,0), animRect.size());
QLinearGradient alphaGradient(0, 0, vertical ? 0 : image.width(),
vertical ? image.height() : 0);
alphaGradient.setColorAt(0, QColor(0, 0, 0, 0));
diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp
index 916210ad09..2fbc40dc11 100644
--- a/src/widgets/styles/qwindowsxpstyle.cpp
+++ b/src/widgets/styles/qwindowsxpstyle.cpp
@@ -2866,8 +2866,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
}
}
- QStyleOption tool(0);
- tool.palette = toolbutton->palette;
+ QStyleOption tool = *toolbutton;
if (toolbutton->subControls & SC_ToolButton) {
if (flags & (State_Sunken | State_On | State_Raised) || !autoRaise) {
if (toolbutton->features & QStyleOptionToolButton::MenuButtonPopup && autoRaise) {
diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp
index c03c96333a..cb99b58d97 100644
--- a/src/widgets/widgets/qmenu.cpp
+++ b/src/widgets/widgets/qmenu.cpp
@@ -2744,10 +2744,15 @@ QMenu::event(QEvent *e)
return true;
}
} break;
- case QEvent::ContextMenu:
- if (d->delayState.timer.isActive()) {
- d->delayState.stop();
- internalDelayedPopup();
+ case QEvent::MouseButtonPress:
+ case QEvent::ContextMenu: {
+ bool canPopup = true;
+ if (e->type() == QEvent::MouseButtonPress)
+ canPopup = (static_cast<QMouseEvent*>(e)->button() == Qt::LeftButton);
+ if (canPopup && d->delayState.timer.isActive()) {
+ d->delayState.stop();
+ internalDelayedPopup();
+ }
}
break;
case QEvent::Resize: {
diff --git a/src/widgets/widgets/qwidgetlinecontrol.cpp b/src/widgets/widgets/qwidgetlinecontrol.cpp
index 23d52b278d..66f17dbe33 100644
--- a/src/widgets/widgets/qwidgetlinecontrol.cpp
+++ b/src/widgets/widgets/qwidgetlinecontrol.cpp
@@ -717,7 +717,7 @@ bool QWidgetLineControl::finishChange(int validateFromState, bool update, bool e
if (m_transactions.count())
return false;
internalUndo(validateFromState);
- m_history.resize(m_undoState);
+ m_history.erase(m_history.begin() + m_undoState, m_history.end());
if (m_modifiedState > m_undoState)
m_modifiedState = -1;
m_validInput = true;
@@ -796,14 +796,14 @@ void QWidgetLineControl::internalSetText(const QString &txt, int pos, bool edite
*/
void QWidgetLineControl::addCommand(const Command &cmd)
{
- if (m_separator && m_undoState && m_history[m_undoState - 1].type != Separator) {
- m_history.resize(m_undoState + 2);
- m_history[m_undoState++] = Command(Separator, m_cursor, 0, m_selstart, m_selend);
- } else {
- m_history.resize(m_undoState + 1);
- }
+ m_history.erase(m_history.begin() + m_undoState, m_history.end());
+
+ if (m_separator && m_undoState && m_history[m_undoState - 1].type != Separator)
+ m_history.push_back(Command(Separator, m_cursor, 0, m_selstart, m_selend));
+
m_separator = false;
- m_history[m_undoState++] = cmd;
+ m_history.push_back(cmd);
+ m_undoState = int(m_history.size());
}
/*!
@@ -1563,6 +1563,7 @@ void QWidgetLineControl::processShortcutOverrideEvent(QKeyEvent *ke)
if (ke == QKeySequence::Copy
|| ke == QKeySequence::MoveToNextWord
|| ke == QKeySequence::MoveToPreviousWord
+ || ke == QKeySequence::MoveToStartOfLine
|| ke == QKeySequence::MoveToEndOfLine
|| ke == QKeySequence::MoveToStartOfDocument
|| ke == QKeySequence::MoveToEndOfDocument
@@ -1957,7 +1958,7 @@ bool QWidgetLineControl::isRedoAvailable() const
// Same as with undo. Disabled for password modes.
return !m_readOnly
&& m_echoMode == QLineEdit::Normal
- && m_undoState < m_history.size();
+ && m_undoState < int(m_history.size());
}
QT_END_NAMESPACE
diff --git a/src/widgets/widgets/qwidgetlinecontrol_p.h b/src/widgets/widgets/qwidgetlinecontrol_p.h
index 34d19d1e77..5e52e29a51 100644
--- a/src/widgets/widgets/qwidgetlinecontrol_p.h
+++ b/src/widgets/widgets/qwidgetlinecontrol_p.h
@@ -67,6 +67,8 @@
#include "qplatformdefs.h"
+#include <vector>
+
#ifdef DrawText
# undef DrawText
#endif
@@ -469,7 +471,6 @@ private:
// undo/redo handling
enum CommandType { Separator, Insert, Remove, Delete, RemoveSelection, DeleteSelection, SetSelection };
struct Command {
- inline Command() {}
inline Command(CommandType t, int p, QChar c, int ss, int se) : type(t),uc(c),pos(p),selStart(ss),selEnd(se) {}
uint type : 4;
QChar uc;
@@ -477,7 +478,7 @@ private:
};
int m_modifiedState;
int m_undoState;
- QVector<Command> m_history;
+ std::vector<Command> m_history;
void addCommand(const Command& cmd);
inline void separate() { m_separator = true; }