From 9e59174b49b8d4c6ebe0cab2b8df9e93f1090211 Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Sat, 20 Feb 2016 15:48:40 +0300 Subject: [PATCH 01/38] QPixmap: check data ptr in isQBitmap() Task-number: QTBUG-51271 Change-Id: I670e074ced1217d2614fa334eb365e40ef80b8b1 Reviewed-by: Edward Welbourne Reviewed-by: Marc Mutz --- src/gui/image/qpixmap.cpp | 2 +- tests/auto/gui/image/qpixmap/tst_qpixmap.cpp | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index fb62889e40..0c8ab527b2 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -481,7 +481,7 @@ QMatrix QPixmap::trueMatrix(const QMatrix &m, int w, int h) bool QPixmap::isQBitmap() const { - return data->type == QPlatformPixmap::BitmapType; + return data && data->type == QPlatformPixmap::BitmapType; } /*! diff --git a/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp b/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp index 67d7e57fd4..4ffe357d09 100644 --- a/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp +++ b/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp @@ -105,6 +105,7 @@ private slots: void drawBitmap(); void isNull(); void task_246446(); + void task_51271(); void convertFromImageNoDetach(); void convertFromImageDetach(); @@ -1441,6 +1442,14 @@ void tst_QPixmap::task_246446() QVERIFY(pm.mask().isNull()); } +void tst_QPixmap::task_51271() +{ + QPixmap pm; + QBitmap bm; + QVERIFY(!pm.isQBitmap()); // Should not crash ! + QVERIFY(bm.isQBitmap()); +} + void tst_QPixmap::preserveDepth() { QPixmap target(64, 64); From 479167cd4e7102b4cff654a13cc43298bbb638d0 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Wed, 24 Feb 2016 12:22:46 +0100 Subject: [PATCH 02/38] tst_QProcess: Transform loop into additional test rows Do not use a loop to execute similar but separate tests in tst_QProcess::softExitInSlots. Use separate test rows with distinguishable data tags instead. This way we can deduce from CI output which part of this test failed. Change-Id: Ic9bc996f2ced11b2bb1c33c1970e64937d860976 Reviewed-by: Friedemann Kleint --- .../auto/corelib/io/qprocess/tst_qprocess.cpp | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp index 712e3440d8..b7dd58870c 100644 --- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp +++ b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp @@ -1050,24 +1050,33 @@ private: void tst_QProcess::softExitInSlots_data() { QTest::addColumn("appName"); + QTest::addColumn("signalToConnect"); + QByteArray dataTagPrefix("gui app "); #ifndef QT_NO_WIDGETS - QTest::newRow("gui app") << "testGuiProcess/testGuiProcess"; + for (int i = 0; i < 5; ++i) { + QTest::newRow(dataTagPrefix + QByteArray::number(i)) + << "testGuiProcess/testGuiProcess" << i; + } #endif - QTest::newRow("console app") << "testProcessEcho2/testProcessEcho2"; + + dataTagPrefix = "console app "; + for (int i = 0; i < 5; ++i) { + QTest::newRow(dataTagPrefix + QByteArray::number(i)) + << "testProcessEcho2/testProcessEcho2" << i; + } } void tst_QProcess::softExitInSlots() { QFETCH(QString, appName); + QFETCH(int, signalToConnect); - for (int i = 0; i < 5; ++i) { - SoftExitProcess proc(i); - proc.writeAfterStart("OLEBOLE", 8); // include the \0 - proc.start(appName); - QTRY_VERIFY_WITH_TIMEOUT(proc.waitedForFinished, 10000); - QCOMPARE(proc.state(), QProcess::NotRunning); - } + SoftExitProcess proc(signalToConnect); + proc.writeAfterStart("OLEBOLE", 8); // include the \0 + proc.start(appName); + QTRY_VERIFY_WITH_TIMEOUT(proc.waitedForFinished, 10000); + QCOMPARE(proc.state(), QProcess::NotRunning); } #endif From 696a4bc2f96fb84c38ff40507608e834d2cd79c7 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Wed, 24 Feb 2016 14:12:44 +0100 Subject: [PATCH 03/38] Remove legacy from tst_qprocess.cpp The windows.h include is not needed, the enums are properly known to the metaobject system nowadays, and qprocess_p.h already has a QT_NO_PROCESS guard. Change-Id: I6bbdce19f097feb8260c51a29425279049aa0192 Reviewed-by: Friedemann Kleint --- tests/auto/corelib/io/qprocess/tst_qprocess.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp index b7dd58870c..8b311921e2 100644 --- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp +++ b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp @@ -45,15 +45,7 @@ #include #include -#ifndef QT_NO_PROCESS # include // only so we get QPROCESS_USE_SPAWN -# if defined(Q_OS_WIN) -# include -# endif - -Q_DECLARE_METATYPE(QProcess::ExitStatus); -Q_DECLARE_METATYPE(QProcess::ProcessState); -#endif typedef void (QProcess::*QProcessFinishedSignal1)(int); typedef void (QProcess::*QProcessFinishedSignal2)(int, QProcess::ExitStatus); From 1db9962cef140971d18110bb76486c40db373b8f Mon Sep 17 00:00:00 2001 From: Mark Brand Date: Thu, 18 Feb 2016 14:38:39 +0100 Subject: [PATCH 04/38] QSqlDriver::sqlStatement: documentation fix Change-Id: I12bd612c48020594b5377b04aeccc51f7c4be53d Reviewed-by: Andy Shaw Reviewed-by: Vyacheslav Grigoryev --- src/sql/kernel/qsqldriver.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/sql/kernel/qsqldriver.cpp b/src/sql/kernel/qsqldriver.cpp index 9ee8d67f56..adaeb8c846 100644 --- a/src/sql/kernel/qsqldriver.cpp +++ b/src/sql/kernel/qsqldriver.cpp @@ -457,6 +457,17 @@ QString QSqlDriver::stripDelimiters(const QString &identifier, IdentifierType ty This method can be used to manipulate tables without having to worry about database-dependent SQL dialects. For non-prepared statements, the values will be properly escaped. + + In the WHERE statement, each non-null field of \a rec specifies a + filter condition of equality to the field value, or if prepared, a + placeholder. However, prepared or not, a null field specifies the + condition IS NULL and never introduces a placeholder. The + application must not attempt to bind data for the null field during + execution. The field must be set to some non-null value if a + placeholder is desired. Furthermore, since non-null fields specify + equality conditions and SQL NULL is not equal to anything, even + itself, it is generally not useful to bind a null to a placeholder. + */ QString QSqlDriver::sqlStatement(StatementType type, const QString &tableName, const QSqlRecord &rec, bool preparedStatement) const From 28ee76fd0b9ce59291341c8a9937a6c98fcb926d Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 21 Dec 2015 15:06:40 +0100 Subject: [PATCH 05/38] QtPlatformHeaders/Windows: Add function to set window activation behavior. The Windows OS by default does not activate windows when the calling process is not active; only the taskbar entry is flashed as not to distract the user. Nevertheless, for some use cases, it is desirable to activate the window also in the inactive state. Introduce an enumeration specifying the behavior to QtPlatformHeaders and employ a workaround using the Win32 API AttachThreadInput() to attach to other processes while setting the foreground window to achieve the AlwaysActivateWindow behavior. Task-number: QTBUG-14062 Task-number: QTBUG-37435 Change-Id: I79cb6cd3fab29d55b5d3db7f9af01bbaa5096a37 Reviewed-by: Joerg Bornemann --- src/gui/doc/qtgui.qdocconf | 1 + src/gui/kernel/qwindow.cpp | 2 +- .../doc/qtplatformheaders.qdocconf | 1 + .../qwindowswindowfunctions.h | 15 ++++++ .../qwindowswindowfunctions.qdoc | 49 +++++++++++++++++++ .../windows/qwindowsnativeinterface.cpp | 5 ++ .../windows/qwindowsnativeinterface.h | 9 ++++ .../platforms/windows/qwindowswindow.cpp | 23 +++++++++ src/widgets/doc/qtwidgets.qdocconf | 2 +- src/widgets/kernel/qwidget.cpp | 2 +- 10 files changed, 106 insertions(+), 3 deletions(-) diff --git a/src/gui/doc/qtgui.qdocconf b/src/gui/doc/qtgui.qdocconf index e34347b801..027d2663de 100644 --- a/src/gui/doc/qtgui.qdocconf +++ b/src/gui/doc/qtgui.qdocconf @@ -33,6 +33,7 @@ depends += \ qtmultimedia \ qtnetwork \ qtopengl \ + qtplatformheaders \ qtsvg \ qtqml \ qtquick \ diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index 44fa88e7cf..c5c4f901e0 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -1002,7 +1002,7 @@ QRegion QWindow::mask() const /*! Requests the window to be activated, i.e. receive keyboard focus. - \sa isActive(), QGuiApplication::focusWindow() + \sa isActive(), QGuiApplication::focusWindow(), QWindowsWindowFunctions::setWindowActivationBehavior() */ void QWindow::requestActivate() { diff --git a/src/platformheaders/doc/qtplatformheaders.qdocconf b/src/platformheaders/doc/qtplatformheaders.qdocconf index fc8a9d8731..989df524e6 100644 --- a/src/platformheaders/doc/qtplatformheaders.qdocconf +++ b/src/platformheaders/doc/qtplatformheaders.qdocconf @@ -27,6 +27,7 @@ qhp.QtPlatformHeaders.subprojects.classes.sortPages = true depends += \ qtcore \ qtgui \ + qtwidgets \ qtdoc headerdirs += .. diff --git a/src/platformheaders/windowsfunctions/qwindowswindowfunctions.h b/src/platformheaders/windowsfunctions/qwindowswindowfunctions.h index 2b1efcdd6d..d0826bdb50 100644 --- a/src/platformheaders/windowsfunctions/qwindowswindowfunctions.h +++ b/src/platformheaders/windowsfunctions/qwindowswindowfunctions.h @@ -57,6 +57,11 @@ public: Q_DECLARE_FLAGS(TouchWindowTouchTypes, TouchWindowTouchType) + enum WindowActivationBehavior { + DefaultActivateWindow, + AlwaysActivateWindow + }; + typedef void (*SetTouchWindowTouchType)(QWindow *window, QWindowsWindowFunctions::TouchWindowTouchTypes touchType); static const QByteArray setTouchWindowTouchTypeIdentifier() { return QByteArrayLiteral("WindowsSetTouchWindowTouchType"); } @@ -75,6 +80,16 @@ public: if (func) func(window, border); } + + typedef void (*SetWindowActivationBehaviorType)(WindowActivationBehavior); + static const QByteArray setWindowActivationBehaviorIdentifier() { return QByteArrayLiteral("WindowsSetWindowActivationBehavior"); } + + static void setWindowActivationBehavior(WindowActivationBehavior behavior) + { + SetWindowActivationBehaviorType func = reinterpret_cast(QGuiApplication::platformFunction(setWindowActivationBehaviorIdentifier())); + if (func) + func(behavior); + } }; Q_DECLARE_OPERATORS_FOR_FLAGS(QWindowsWindowFunctions::TouchWindowTouchTypes) diff --git a/src/platformheaders/windowsfunctions/qwindowswindowfunctions.qdoc b/src/platformheaders/windowsfunctions/qwindowswindowfunctions.qdoc index d6b8764e7b..196f9f22ce 100644 --- a/src/platformheaders/windowsfunctions/qwindowswindowfunctions.qdoc +++ b/src/platformheaders/windowsfunctions/qwindowswindowfunctions.qdoc @@ -95,3 +95,52 @@ See also \l [QtDoc] {Fullscreen OpenGL Based Windows} */ + +/*! + \enum QWindowsWindowFunctions::WindowActivationBehavior + + This enum specifies the behavior of QWidget::activateWindow() and + QWindow::requestActivate(). + + \value DefaultActivateWindow The window is activated according to the default + behavior of the Windows operating system. This means the window will not + be activated in some circumstances (most notably when the calling process + is not the active process); only the taskbar entry will be flashed. + \value AlwaysActivateWindow The window is always activated, even when the + calling process is not the active process. + + \sa QWidget::activateWindow(), QWindow::requestActivate() + \since 5.7 +*/ + +/*! + \typedef QWindowsWindowFunctions::SetWindowActivationBehaviorType + + This is the typedef for the function returned by QGuiApplication::platformFunction() + when passed setWindowActivationBehaviorIdentifier(). + + \sa QWidget::activateWindow(), QWindow::requestActivate() + \since 5.7 +*/ + +/*! + \fn QByteArray setWindowActivationBehaviorIdentifier() + + This function returns a bytearray that can be used to query + QGuiApplication::platformFunction() to retrieve the SetWindowActivationBehaviorType + function. + + \sa QWidget::activateWindow(), QWindow::requestActivate() + \since 5.7 +*/ + +/*! + \fn void QWindowsWindowFunctions::setWindowActivationBehavior(WindowActivationBehavior behavior) + + This is a convenience function that can be used directly instead of resolving + the function pointer. \a behavior will be relayed to the function retrieved + by QGuiApplication. + + \sa QWidget::activateWindow(), QWindow::requestActivate() + \since 5.7 +*/ diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp index ac7c22fb7e..babca35149 100644 --- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp +++ b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp @@ -84,6 +84,9 @@ static int resourceType(const QByteArray &key) return int(result - names); } +QWindowsWindowFunctions::WindowActivationBehavior QWindowsNativeInterface::m_windowActivationBehavior = + QWindowsWindowFunctions::DefaultActivateWindow; + void *QWindowsNativeInterface::nativeResourceForWindow(const QByteArray &resource, QWindow *window) { if (!window || !window->handle()) { @@ -253,6 +256,8 @@ QFunctionPointer QWindowsNativeInterface::platformFunction(const QByteArray &fun return QFunctionPointer(QWindowsWindow::setTouchWindowTouchTypeStatic); else if (function == QWindowsWindowFunctions::setHasBorderInFullScreenIdentifier()) return QFunctionPointer(QWindowsWindow::setHasBorderInFullScreenStatic); + else if (function == QWindowsWindowFunctions::setWindowActivationBehaviorIdentifier()) + return QFunctionPointer(QWindowsNativeInterface::setWindowActivationBehavior); return Q_NULLPTR; } diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.h b/src/plugins/platforms/windows/qwindowsnativeinterface.h index 3a0d3398d9..9fc43ddcce 100644 --- a/src/plugins/platforms/windows/qwindowsnativeinterface.h +++ b/src/plugins/platforms/windows/qwindowsnativeinterface.h @@ -42,6 +42,7 @@ #include #include +#include QT_BEGIN_NAMESPACE @@ -96,7 +97,15 @@ public: QVariant windowProperty(QPlatformWindow *window, const QString &name, const QVariant &defaultValue) const Q_DECL_OVERRIDE; void setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value) Q_DECL_OVERRIDE; + static QWindowsWindowFunctions::WindowActivationBehavior windowActivationBehavior() + { return QWindowsNativeInterface::m_windowActivationBehavior; } + static void setWindowActivationBehavior(QWindowsWindowFunctions::WindowActivationBehavior b) + { QWindowsNativeInterface::m_windowActivationBehavior = b; } + QFunctionPointer platformFunction(const QByteArray &function) const Q_DECL_OVERRIDE; + +private: + static QWindowsWindowFunctions::WindowActivationBehavior m_windowActivationBehavior; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 4c503a2c48..c1a047e276 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -43,6 +43,7 @@ #include "qwindowsdrag.h" #include "qwindowsscreen.h" #include "qwindowsintegration.h" +#include "qwindowsnativeinterface.h" #include "qwindowsopenglcontext.h" #ifdef QT_NO_CURSOR # include "qwindowscursor.h" @@ -2083,8 +2084,30 @@ void QWindowsWindow::requestActivateWindow() // 'Active' state handling is based in focus since it needs to work for // child windows as well. if (m_data.hwnd) { +#ifndef Q_OS_WINCE + const DWORD currentThread = GetCurrentThreadId(); + bool attached = false; + DWORD foregroundThread = 0; + + // QTBUG-14062, QTBUG-37435: Windows normally only flashes the taskbar entry + // when activating windows of inactive applications. Attach to the input of the + // currently active window while setting the foreground window to always activate + // the window when desired. + if (QGuiApplication::applicationState() != Qt::ApplicationActive + && QWindowsNativeInterface::windowActivationBehavior() == QWindowsWindowFunctions::AlwaysActivateWindow) { + if (const HWND foregroundWindow = GetForegroundWindow()) { + foregroundThread = GetWindowThreadProcessId(foregroundWindow, NULL); + if (foregroundThread && foregroundThread != currentThread) + attached = AttachThreadInput(foregroundThread, currentThread, TRUE) == TRUE; + } + } +#endif // !Q_OS_WINCE SetForegroundWindow(m_data.hwnd); SetFocus(m_data.hwnd); +#ifndef Q_OS_WINCE + if (attached) + AttachThreadInput(foregroundThread, currentThread, FALSE); +#endif // !Q_OS_WINCE } } diff --git a/src/widgets/doc/qtwidgets.qdocconf b/src/widgets/doc/qtwidgets.qdocconf index 8160396ca2..75bbb99579 100644 --- a/src/widgets/doc/qtwidgets.qdocconf +++ b/src/widgets/doc/qtwidgets.qdocconf @@ -26,7 +26,7 @@ qhp.QtWidgets.subprojects.classes.sortPages = true tagfile = ../../../doc/qtwidgets/qtwidgets.tags -depends += qtcore qtgui qtdoc qtsql qtdesigner qtquick qmake qtsvg +depends += qtcore qtgui qtdoc qtsql qtdesigner qtquick qmake qtplatformheaders qtsvg headerdirs += .. diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 7e2e02b58e..de832d667d 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -12689,7 +12689,7 @@ QWidget *QWidget::keyboardGrabber() does not allow an application to interrupt what the user is currently doing in another application. - \sa isActiveWindow(), window(), show() + \sa isActiveWindow(), window(), show(), QWindowsWindowFunctions::setWindowActivationBehavior() */ void QWidget::activateWindow() { From de9de96d81cdbad4880cc06fcfbe928606c3143e Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Thu, 18 Feb 2016 15:28:14 +0100 Subject: [PATCH 06/38] Add QResource to the bootstrap library It's very useful for bootstrapped tools to be able to include resources. Those can now be accessed through the QResource API. Change-Id: Ie8247877a9a4a81cec006bab2b58331270487aef Reviewed-by: Oswald Buddenhagen Reviewed-by: Simon Hausmann --- src/corelib/io/qresource.cpp | 2 ++ src/corelib/io/qresource.h | 1 + src/tools/bootstrap/bootstrap.pro | 1 + 3 files changed, 4 insertions(+) diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp index 0303933de8..ad24b43568 100644 --- a/src/corelib/io/qresource.cpp +++ b/src/corelib/io/qresource.cpp @@ -1185,6 +1185,7 @@ QResource::unregisterResource(const uchar *rccData, const QString &resourceRoot) return false; } +#if !defined(QT_BOOTSTRAPPED) //resource engine class QResourceFileEnginePrivate : public QAbstractFileEnginePrivate { @@ -1490,5 +1491,6 @@ bool QResourceFileEnginePrivate::unmap(uchar *ptr) Q_UNUSED(ptr); return true; } +#endif // !defined(QT_BOOTSTRAPPED) QT_END_NAMESPACE diff --git a/src/corelib/io/qresource.h b/src/corelib/io/qresource.h index e84ad03353..a50bbbdaca 100644 --- a/src/corelib/io/qresource.h +++ b/src/corelib/io/qresource.h @@ -44,6 +44,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro index 4f2456cf79..522e13b17b 100644 --- a/src/tools/bootstrap/bootstrap.pro +++ b/src/tools/bootstrap/bootstrap.pro @@ -54,6 +54,7 @@ SOURCES += \ ../../corelib/io/qfsfileengine_iterator.cpp \ ../../corelib/io/qiodevice.cpp \ ../../corelib/io/qfiledevice.cpp \ + ../../corelib/io/qresource.cpp \ ../../corelib/io/qtemporaryfile.cpp \ ../../corelib/io/qtextstream.cpp \ ../../corelib/io/qstandardpaths.cpp \ From 3126fa227b96b5e59e9975a47d78cd6245365b07 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 23 Feb 2016 11:54:21 +0100 Subject: [PATCH 07/38] Improve QCOMPARE output of char comparisons Make actual and expected values of char tests more useful by using C syntax. This means we can actually read non-printable characters. Task-number: QTBUG-51294 Change-Id: I031e15916a2882c0499b6217ae1649d4eea09eb4 Reviewed-by: Friedemann Kleint --- src/testlib/qtestcase.cpp | 48 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index 7b567674e4..4720c0564e 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -2296,12 +2296,58 @@ TO_STRING_IMPL(qint64, %lld) TO_STRING_IMPL(quint64, %llu) #endif TO_STRING_IMPL(bool, %d) -TO_STRING_IMPL(char, %c) TO_STRING_IMPL(signed char, %hhd) TO_STRING_IMPL(unsigned char, %hhu) TO_STRING_IMPL(float, %g) TO_STRING_IMPL(double, %lg) +template <> Q_TESTLIB_EXPORT char *QTest::toString(const char &t) +{ + unsigned char c = static_cast(t); + char *msg = new char[16]; + switch (c) { + case 0x00: + qstrcpy(msg, "'\\0'"); + break; + case 0x07: + qstrcpy(msg, "'\\a'"); + break; + case 0x08: + qstrcpy(msg, "'\\b'"); + break; + case 0x09: + qstrcpy(msg, "'\\t'"); + break; + case 0x0a: + qstrcpy(msg, "'\\n'"); + break; + case 0x0b: + qstrcpy(msg, "'\\v'"); + break; + case 0x0c: + qstrcpy(msg, "'\\f'"); + break; + case 0x0d: + qstrcpy(msg, "'\\r'"); + break; + case 0x22: + qstrcpy(msg, "'\\\"'"); + break; + case 0x27: + qstrcpy(msg, "'\\\''"); + break; + case 0x5c: + qstrcpy(msg, "'\\\\'"); + break; + default: + if (c < 0x20 || c >= 0x7F) + qsnprintf(msg, 16, "'\\x%02x'", c); + else + qsnprintf(msg, 16, "'%c'" , c); + } + return msg; +} + /*! \internal */ char *QTest::toString(const char *str) From b690fe7cfa4f0586648922ce96b890aab978fe61 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 24 Feb 2016 13:43:36 +0100 Subject: [PATCH 08/38] Add We-mean-it comment to qnetworkdatagram_p.h. Fix warning: WARNING: qtbase/src/network/kernel/qnetworkdatagram_p.h does not have the "We mean it." warning Change-Id: I65fc2dc9129b194b08865e3486fae4d0cad3f3d3 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/network/kernel/qnetworkdatagram_p.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/network/kernel/qnetworkdatagram_p.h b/src/network/kernel/qnetworkdatagram_p.h index 55a0937ceb..4941d8c94b 100644 --- a/src/network/kernel/qnetworkdatagram_p.h +++ b/src/network/kernel/qnetworkdatagram_p.h @@ -34,6 +34,17 @@ #ifndef QNETWORKDATAGRAM_P_H #define QNETWORKDATAGRAM_P_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 QT_BEGIN_NAMESPACE From e695b92464f886bb9026bb20877f0ea3ea57d2c8 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 7 Jan 2016 12:18:26 +0100 Subject: [PATCH 09/38] QWindow: Use scaling when calling QPlatformWindow::mapTo/FromGlobal(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The platform window API uses native pixels. Task-number: QTBUG-50206 Change-Id: I1385d34bb0eacd61d77cad483e2a863d129ed129 Reviewed-by: Morten Johan Sørvig --- src/gui/kernel/qwindow.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index e0d991aaf8..68bcbdec71 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -2298,7 +2298,7 @@ QPoint QWindow::mapToGlobal(const QPoint &pos) const // QTBUG-43252, prefer platform implementation for foreign windows. if (d->platformWindow && (type() == Qt::ForeignWindow || d->platformWindow->isEmbedded())) { - return d->platformWindow->mapToGlobal(pos); + return QHighDpi::fromNativeLocalPosition(d->platformWindow->mapToGlobal(QHighDpi::toNativeLocalPosition(pos, this)), this); } return pos + d->globalPosition(); } @@ -2318,7 +2318,7 @@ QPoint QWindow::mapFromGlobal(const QPoint &pos) const // QTBUG-43252, prefer platform implementation for foreign windows. if (d->platformWindow && (type() == Qt::ForeignWindow || d->platformWindow->isEmbedded())) { - return d->platformWindow->mapFromGlobal(pos); + return QHighDpi::fromNativeLocalPosition(d->platformWindow->mapFromGlobal(QHighDpi::toNativeLocalPosition(pos, this)), this); } return pos - d->globalPosition(); } From 26961e32f34c06f083fe441c23be6874f03446a3 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Tue, 23 Feb 2016 14:46:33 +0100 Subject: [PATCH 10/38] QCocoaKeyMapper - correctly update key layouts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QCocoaKeyMapper has 2 bugs: - fails to update layouts even if input source changed - while looking for the possible keys it clears bits for neededMods thus making later shortcut match impossible Change-Id: Ie230b973acd5ca6f50b97ca4901ede61b581d273 Task-number: QTBUG-50865 Reviewed-by: Andy Shaw Reviewed-by: Morten Johan Sørvig Reviewed-by: Timur Pocheptsov --- src/plugins/platforms/cocoa/qcocoakeymapper.mm | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoakeymapper.mm b/src/plugins/platforms/cocoa/qcocoakeymapper.mm index 250f3f3bf7..ebe547f64b 100644 --- a/src/plugins/platforms/cocoa/qcocoakeymapper.mm +++ b/src/plugins/platforms/cocoa/qcocoakeymapper.mm @@ -390,6 +390,11 @@ bool QCocoaKeyMapper::updateKeyboard() keyboardInputLocale = QLocale::c(); keyboardInputDirection = Qt::LeftToRight; } + + const auto newMode = keyboard_mode; + deleteLayouts(); + keyboard_mode = newMode; + return true; } @@ -412,10 +417,8 @@ void QCocoaKeyMapper::clearMappings() void QCocoaKeyMapper::updateKeyMap(unsigned short macVirtualKey, QChar unicodeKey) { - if (updateKeyboard()) { - // ### Qt 4 did this: - // QKeyMapper::changeKeyboard(); - } + updateKeyboard(); + if (keyLayout[macVirtualKey]) return; @@ -471,9 +474,8 @@ QList QCocoaKeyMapper::possibleKeys(const QKeyEvent *event) const for (int i = 1; i < 8; ++i) { Qt::KeyboardModifiers neededMods = ModsTbl[i]; int key = kbItem->qtKey[i]; - if (key && key != baseKey && ((keyMods & neededMods) == neededMods)) { - ret << int(key + (keyMods & ~neededMods)); - } + if (key && key != baseKey && ((keyMods & neededMods) == neededMods)) + ret << int(key + neededMods); } return ret; } From 45feee5f93fad5396af2653ed904a535bc5b7938 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Thu, 25 Feb 2016 10:12:50 +0100 Subject: [PATCH 11/38] Fix QDBusPlatformMenu::menuItemAt() Other platform menu implementations check that the index is not out of bounds, so make QDBusPlatformMenu::menuItemAt() do the same. Change-Id: I1d2e42681f2dbfff8b80044141d620bddbc3b6aa Task-number: QTBUG-51372 Reviewed-by: Simon Hausmann Reviewed-by: Dmitry Shachnev --- src/platformsupport/dbusmenu/qdbusplatformmenu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platformsupport/dbusmenu/qdbusplatformmenu.cpp b/src/platformsupport/dbusmenu/qdbusplatformmenu.cpp index 9f99ef97e5..5c259d5b67 100644 --- a/src/platformsupport/dbusmenu/qdbusplatformmenu.cpp +++ b/src/platformsupport/dbusmenu/qdbusplatformmenu.cpp @@ -262,7 +262,7 @@ void QDBusPlatformMenu::setContainingMenuItem(QDBusPlatformMenuItem *item) QPlatformMenuItem *QDBusPlatformMenu::menuItemAt(int position) const { - return m_items.at(position); + return m_items.value(position); } QPlatformMenuItem *QDBusPlatformMenu::menuItemForTag(quintptr tag) const From debc44cf1106fb20065aab7848759eace3211c65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Arve=20S=C3=A6ther?= Date: Thu, 25 Feb 2016 15:54:40 +0100 Subject: [PATCH 12/38] Add missing initializations in QWheelEvent Change-Id: I77f014934b97aa6729d568996f0e6c03feb44588 Reviewed-by: Shawn Rutledge --- src/gui/kernel/qevent.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index b0f7adf43a..4f368e1db3 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -726,7 +726,8 @@ QHoverEvent::~QHoverEvent() QWheelEvent::QWheelEvent(const QPointF &pos, int delta, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::Orientation orient) - : QInputEvent(Wheel, modifiers), p(pos), qt4D(delta), qt4O(orient), mouseState(buttons) + : QInputEvent(Wheel, modifiers), p(pos), qt4D(delta), qt4O(orient), mouseState(buttons), + ph(Qt::ScrollUpdate), src(Qt::MouseEventNotSynthesized) { g = QCursor::pos(); if (orient == Qt::Vertical) @@ -760,7 +761,8 @@ QWheelEvent::~QWheelEvent() QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, int delta, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::Orientation orient) - : QInputEvent(Wheel, modifiers), p(pos), g(globalPos), qt4D(delta), qt4O(orient), mouseState(buttons) + : QInputEvent(Wheel, modifiers), p(pos), g(globalPos), qt4D(delta), qt4O(orient), mouseState(buttons), + ph(Qt::ScrollUpdate), src(Qt::MouseEventNotSynthesized) { if (orient == Qt::Vertical) angleD = QPoint(0, delta); @@ -796,7 +798,8 @@ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, QPoint pixelDelta, QPoint angleDelta, int qt4Delta, Qt::Orientation qt4Orientation, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers) : QInputEvent(Wheel, modifiers), p(pos), g(globalPos), pixelD(pixelDelta), - angleD(angleDelta), qt4D(qt4Delta), qt4O(qt4Orientation), mouseState(buttons), ph(Qt::ScrollUpdate) + angleD(angleDelta), qt4D(qt4Delta), qt4O(qt4Orientation), mouseState(buttons), ph(Qt::ScrollUpdate), + src(Qt::MouseEventNotSynthesized) {} /*! From 44357dbe423d430246504d977f4422ed0e2e7a5a Mon Sep 17 00:00:00 2001 From: Kai Pastor Date: Fri, 11 Sep 2015 01:22:14 +0200 Subject: [PATCH 13/38] QMacPrintEngine: Really set the printer resolution As already reported in 2009 (Qt 4.6) QPrinter never actually set the printer resolution. This change adds the necessary call to PMPrinterSetOutputResolution (available since OS X 10.5). [ChangeLog][QtPrintSupport][OS X] QMacPrintEngine now really sets the printer resolution. Task-number: QTBUG-7000 Change-Id: I3e851b62e1a7ed78564a8a6fd576b0a18d7eff63 Reviewed-by: Andy Shaw --- .../platforms/cocoa/qprintengine_mac.mm | 13 +++++++++++-- .../kernel/qprinter/tst_qprinter.cpp | 19 ++++++++++++++++++- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm index edd1d656f0..000a9c46c8 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm @@ -470,7 +470,6 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va d->embedFonts = value.toBool(); break; case PPK_Resolution: { - // TODO It appears the old code didn't actually set the resolution??? Can we delete all this??? int bestResolution = 0; int dpi = value.toInt(); int bestDistance = INT_MAX; @@ -486,7 +485,17 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va } } } - PMSessionValidatePageFormat(d->session(), d->format(), kPMDontWantBoolean); + PMResolution resolution; + resolution.hRes = resolution.vRes = bestResolution; + if (PMPrinterSetOutputResolution(d->m_printDevice->macPrinter(), d->settings(), &resolution) == noErr) { + // Setting the resolution succeeded. + // Now try to read the actual resolution selected by the OS. + if (PMPrinterGetOutputResolution(d->m_printDevice->macPrinter(), d->settings(), &d->resolution) != noErr) { + // Reading the resolution somehow failed; d->resolution is in undefined state. + // So use the value which was acceptable to PMPrinterSetOutputResolution. + d->resolution = resolution; + } + } break; } case PPK_CollateCopies: diff --git a/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp b/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp index aa72be3ea8..5e7a40d3b5 100644 --- a/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp +++ b/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp @@ -1628,7 +1628,24 @@ void tst_QPrinter::resolution() // Test set/get int expected = 333; #ifdef Q_OS_MAC - // Set resolution does nothing on OSX, see QTBUG-7000 + // QMacPrintEngine chooses the closest supported resolution. + const QList all_supported = native.supportedResolutions(); + foreach (int supported, all_supported) { + // Test setting a supported resolution + int requested = supported; + native.setResolution(requested); + QCOMPARE(native.resolution(), requested); + + // Test setting an unsupported resolution + do { + requested += 5; + } while (all_supported.contains(requested)); + native.setResolution(requested); + int result = native.resolution(); + QVERIFY(all_supported.contains(result)); + QVERIFY(qAbs(result - requested) <= qAbs(supported - requested)); + } + expected = native.resolution(); #endif // Q_OS_MAC native.setResolution(expected); From c0963486ce689e778d59dafd26d36d8ef9e3ee74 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 24 Feb 2016 13:13:36 +0100 Subject: [PATCH 14/38] QScreen::grabWindow(): Scale the coordinates. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The coordinates need to be scaled before calling QPlatformScreen::grabWindow() On return, set a devicePixelRatio on the pixmap. Adapt the QWidget test to scale the grabbed pixmaps. Fixes pixeltool displaying the wrong part of the screen when High DPI scaling is in effect. Task-number: QTBUG-46615 Change-Id: I12de7df0da669230cf0fae74f4a42d43f061d5ff Reviewed-by: Morten Johan Sørvig --- src/gui/kernel/qscreen.cpp | 15 ++++++++++++++- tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp | 6 ++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp index 52e7686439..e87f58d735 100644 --- a/src/gui/kernel/qscreen.cpp +++ b/src/gui/kernel/qscreen.cpp @@ -40,6 +40,7 @@ #include #include +#include "qhighdpiscaling_p.h" QT_BEGIN_NAMESPACE @@ -683,7 +684,19 @@ QPixmap QScreen::grabWindow(WId window, int x, int y, int width, int height) qWarning("invoked with handle==0"); return QPixmap(); } - return platformScreen->grabWindow(window, x, y, width, height); + const qreal factor = QHighDpiScaling::factor(this); + if (qFuzzyCompare(factor, 1)) + return platformScreen->grabWindow(window, x, y, width, height); + + const QPoint nativePos = QHighDpi::toNative(QPoint(x, y), factor); + QSize nativeSize(width, height); + if (nativeSize.isValid()) + nativeSize = QHighDpi::toNative(nativeSize, factor); + QPixmap result = + platformScreen->grabWindow(window, nativePos.x(), nativePos.y(), + nativeSize.width(), nativeSize.height()); + result.setDevicePixelRatio(factor); + return result; } #ifndef QT_NO_DEBUG_STREAM diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 8a5250aad4..293689bff3 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -4979,7 +4979,9 @@ static inline QByteArray msgRgbMismatch(unsigned actual, unsigned expected) static QPixmap grabWindow(QWindow *window, int x, int y, int width, int height) { QScreen *screen = window->screen(); - return screen ? screen->grabWindow(window->winId(), x, y, width, height) : QPixmap(); + Q_ASSERT(screen); + QPixmap result = screen->grabWindow(window->winId(), x, y, width, height); + return result.devicePixelRatio() > 1 ? result.scaled(width, height) : result; } #define VERIFY_COLOR(child, region, color) verifyColor(child, region, color, __LINE__) @@ -8505,7 +8507,7 @@ void tst_QWidget::translucentWidget() #ifdef Q_OS_WIN QWidget *desktopWidget = QApplication::desktop()->screen(0); if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA) - widgetSnapshot = qApp->primaryScreen()->grabWindow(desktopWidget->winId(), labelPos.x(), labelPos.y(), label.width(), label.height()); + widgetSnapshot = grabWindow(desktopWidget->windowHandle(), labelPos.x(), labelPos.y(), label.width(), label.height()); else #endif widgetSnapshot = label.grab(QRect(QPoint(0, 0), label.size())); From ea757da43697787cfcd1c01f11bd2b0288c679fe Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 22 Feb 2016 09:42:39 +0100 Subject: [PATCH 15/38] QWindowsTheme: Run SHGetFileInfo() in a thread. Windows 10: SHGetFileInfo() (as called by item views on file system models has been observed to trigger a WM_PAINT on the mainwindow for totally obscure reasons, causing a recursive repaint. Suppress this by running it via QThreadPool. Task-number: QTBUG-45298 Task-number: QTBUG-48823 Task-number: QTCREATORBUG-14888 Change-Id: I7479102b9b8fb0771681260298c3d735e66f220f Reviewed-by: Joerg Bornemann --- .../platforms/windows/qwindowstheme.cpp | 56 +++++++-- src/plugins/platforms/windows/qwindowstheme.h | 2 + .../windows/qwindowsthreadpoolrunner.h | 116 ++++++++++++++++++ src/plugins/platforms/windows/windows.pri | 3 +- 4 files changed, 165 insertions(+), 12 deletions(-) create mode 100644 src/plugins/platforms/windows/qwindowsthreadpoolrunner.h diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp index 887a217b06..ef652e6f98 100644 --- a/src/plugins/platforms/windows/qwindowstheme.cpp +++ b/src/plugins/platforms/windows/qwindowstheme.cpp @@ -122,6 +122,41 @@ static inline QColor getSysColor(int index) return COLORREFToQColor(GetSysColor(index)); } +#ifndef QT_NO_WINCE_SHELLSDK +// QTBUG-48823/Windows 10: SHGetFileInfo() (as called by item views on file system +// models has been observed to trigger a WM_PAINT on the mainwindow. Suppress the +// behavior by running it in a thread. +class ShGetFileInfoFunction +{ +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); } + +private: + const wchar_t *m_fileName; + const DWORD m_attributes; + const UINT m_flags; + SHFILEINFO *const m_info; + bool *m_result; +}; + +static bool shGetFileInfoBackground(QWindowsThreadPoolRunner &r, + const wchar_t *fileName, DWORD attributes, + SHFILEINFO *info, UINT flags, + unsigned long timeOutMSecs = 5000) +{ + bool result = false; + if (!r.run(ShGetFileInfoFunction(fileName, attributes, info, flags, &result), timeOutMSecs)) { + qWarning().noquote() << "ShGetFileInfoBackground() timed out for " + << QString::fromWCharArray(fileName); + return false; + } + return result; +} +#endif // !QT_NO_WINCE_SHELLSDK + // from QStyle::standardPalette static inline QPalette standardPalette() { @@ -690,23 +725,22 @@ QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &s } SHFILEINFO info; - unsigned int flags = + const unsigned int flags = #ifndef Q_OS_WINCE SHGFI_ICON|iconSize|SHGFI_SYSICONINDEX|SHGFI_ADDOVERLAYS|SHGFI_OVERLAYINDEX; #else iconSize|SHGFI_SYSICONINDEX; #endif // Q_OS_WINCE - unsigned long val = 0; + + #if !defined(QT_NO_WINCE_SHELLSDK) - if (cacheableDirIcon && useDefaultFolderIcon) { - flags |= SHGFI_USEFILEATTRIBUTES; - val = SHGetFileInfo(L"dummy", - FILE_ATTRIBUTE_DIRECTORY, - &info, sizeof(SHFILEINFO), flags); - } else { - val = SHGetFileInfo(reinterpret_cast(filePath.utf16()), 0, - &info, sizeof(SHFILEINFO), flags); - } + const bool val = cacheableDirIcon && useDefaultFolderIcon + ? shGetFileInfoBackground(m_threadPoolRunner, L"dummy", FILE_ATTRIBUTE_DIRECTORY, + &info, flags | SHGFI_USEFILEATTRIBUTES) + : shGetFileInfoBackground(m_threadPoolRunner, reinterpret_cast(filePath.utf16()), 0, + &info, flags); +#else + const bool val = false; #endif // !QT_NO_WINCE_SHELLSDK // Even if GetFileInfo returns a valid result, hIcon can be empty in some cases diff --git a/src/plugins/platforms/windows/qwindowstheme.h b/src/plugins/platforms/windows/qwindowstheme.h index fc004b68c8..cacde98601 100644 --- a/src/plugins/platforms/windows/qwindowstheme.h +++ b/src/plugins/platforms/windows/qwindowstheme.h @@ -34,6 +34,7 @@ #ifndef QWINDOWSTHEME_H #define QWINDOWSTHEME_H +#include "qwindowsthreadpoolrunner.h" #include QT_BEGIN_NAMESPACE @@ -74,6 +75,7 @@ private: static QWindowsTheme *m_instance; QPalette *m_palettes[NPalettes]; QFont *m_fonts[NFonts]; + mutable QWindowsThreadPoolRunner m_threadPoolRunner; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h b/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h new file mode 100644 index 0000000000..0361aa90f5 --- /dev/null +++ b/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** 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:LGPL21$ +** 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 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSTHREADPOOLRUNNER_H +#define QWINDOWSTHREADPOOLRUNNER_H + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QWindowsThreadPoolRunner + \brief Runs a task in the global instance of QThreadPool + + QThreadPool does not provide a method to wait on a single task, so this needs + to be done by using QWaitCondition/QMutex. + + \internal + \ingroup qt-lighthouse-win +*/ +class QWindowsThreadPoolRunner +{ + Q_DISABLE_COPY(QWindowsThreadPoolRunner) + +#ifndef QT_NO_THREAD + template // nested class implementing QRunnable to execute a function. + class Runnable : public QRunnable + { + public: + explicit Runnable(QMutex *m, QWaitCondition *c, RunnableFunction f) + : m_mutex(m), m_condition(c), m_function(f) {} + + void run() Q_DECL_OVERRIDE + { + m_function(); + m_mutex->lock(); + m_condition->wakeAll(); + m_mutex->unlock(); + } + + private: + QMutex *m_mutex; + QWaitCondition *m_condition; + RunnableFunction m_function; + }; // class Runnable + +public: + QWindowsThreadPoolRunner() {} + + template + bool run(Function f, unsigned long timeOutMSecs = 5000) + { + QThreadPool *pool = QThreadPool::globalInstance(); + Q_ASSERT(pool); + Runnable *runnable = new Runnable(&m_mutex, &m_condition, f); + m_mutex.lock(); + pool->start(runnable); + const bool ok = m_condition.wait(&m_mutex, timeOutMSecs); + m_mutex.unlock(); + if (!ok) + pool->cancel(runnable); + return ok; + } + +private: + QMutex m_mutex; + QWaitCondition m_condition; +#else // !QT_NO_THREAD +public: + QWindowsThreadPoolRunner() {} + + template + bool run(Function f, unsigned long /* timeOutMSecs */ = 5000) + { + f(); + return true; + } +#endif // QT_NO_THREAD +}; + +QT_END_NAMESPACE + +#endif // QWINDOWSTHREADPOOLRUNNER_H diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri index 67af5c03ef..eba0593d75 100644 --- a/src/plugins/platforms/windows/windows.pri +++ b/src/plugins/platforms/windows/windows.pri @@ -63,7 +63,8 @@ HEADERS += \ $$PWD/qplatformfunctions_wince.h \ $$PWD/qwindowsnativeimage.h \ $$PWD/qwindowsnativeinterface.h \ - $$PWD/qwindowsopengltester.h + $$PWD/qwindowsopengltester.h \ + $$PWD/qwindowsthreadpoolrunner.h INCLUDEPATH += $$PWD From 827420c4c6d015431fb5207855896d863624ea12 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 25 Feb 2016 12:32:26 +0100 Subject: [PATCH 16/38] Windows QPA: Fix scrolling down with mouse wheel. Use GET_WHEEL_DELTA_WPARAM() instead of HIWORD and casting. Fix breakage introduced by b20548f9999d8c111268f3f2287c0801c6c5cbb0 . Change-Id: I11bd97d73c12d72e824e3f769e9c402975f27d48 Reviewed-by: Joerg Bornemann --- src/plugins/platforms/windows/qwindowsmousehandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index 32f8285954..4ed708540c 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -422,7 +422,7 @@ bool QWindowsMouseHandler::translateMouseWheelEvent(QWindow *window, HWND, int delta; if (msg.message == WM_MOUSEWHEEL || msg.message == WM_MOUSEHWHEEL) - delta = HIWORD (msg.wParam); + delta = GET_WHEEL_DELTA_WPARAM(msg.wParam); else delta = int(msg.wParam); From cf846d6a8a0df0f0935f7f1306ab8439309cf6e5 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 25 Feb 2016 10:15:22 +0100 Subject: [PATCH 17/38] Fix QHighDpi::fromNative(QRect, QScreen *, QPoint). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Call fromNative() instead of toNative(). Task-number: QTBUG-46615 Change-Id: I1e648a2680126d1f560e71573f7346b053fe676b Reviewed-by: Morten Johan Sørvig --- src/gui/kernel/qhighdpiscaling_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/kernel/qhighdpiscaling_p.h b/src/gui/kernel/qhighdpiscaling_p.h index fac3ae420d..a7b80982af 100644 --- a/src/gui/kernel/qhighdpiscaling_p.h +++ b/src/gui/kernel/qhighdpiscaling_p.h @@ -162,7 +162,7 @@ inline QRect toNative(const QRect &rect, qreal scaleFactor, const QPoint &origin inline QRect fromNative(const QRect &rect, const QScreen *screen, const QPoint &screenOrigin) { - return toNative(rect, QHighDpiScaling::factor(screen), screenOrigin); + return fromNative(rect, QHighDpiScaling::factor(screen), screenOrigin); } inline QRect fromNativeScreenGeometry(const QRect &nativeScreenGeometry, const QScreen *screen) From d1dfcc776fd3bf738d0c6e7125f5bb2c9aecc57e Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 25 Feb 2016 10:01:21 +0100 Subject: [PATCH 18/38] Windows QPA: Apply scaling when fixing maximized/frameless geometry. Task-number: QTBUG-8361 Task-number: QTBUG-51327 Change-Id: I590702df8f6313701fe69d0873657c6af53fee16 Reviewed-by: Andy Shaw --- src/plugins/platforms/windows/qwindowswindow.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index e2f5885047..c0892feabe 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -2089,14 +2089,15 @@ void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const // Documentation of MINMAXINFO states that it will only work for the primary screen if (screen && screen == QGuiApplication::primaryScreen()) { - mmi->ptMaxSize.y = screen->availableGeometry().height(); + const QRect availableGeometry = QHighDpi::toNativePixels(screen->availableGeometry(), screen); + mmi->ptMaxSize.y = availableGeometry.height(); // Width, because you can have the taskbar on the sides too. - mmi->ptMaxSize.x = screen->availableGeometry().width(); + mmi->ptMaxSize.x = availableGeometry.width(); // If you have the taskbar on top, or on the left you don't want it at (0,0): - mmi->ptMaxPosition.x = screen->availableGeometry().x(); - mmi->ptMaxPosition.y = screen->availableGeometry().y(); + mmi->ptMaxPosition.x = availableGeometry.x(); + mmi->ptMaxPosition.y = availableGeometry.y(); } else if (!screen){ qWarning() << "window()->screen() returned a null screen"; } From 7984f24b1fcb9cc2785d4659d877ae2aaf377ac1 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 22 Feb 2016 16:46:21 +0100 Subject: [PATCH 19/38] Fix potential crash in QWindowsIA2Accessible::QueryInterface(). QWindowsIA2Accessible does not implement IAccessibleRelation (found when replacing the C-style casts by static_cast<>). Remove the corresponding branch. Task-number: QTBUG-50804 Change-Id: I80901634044f85e413666f34b91be2e6ad70da91 Reviewed-by: Joerg Bornemann --- src/plugins/platforms/windows/accessible/iaccessible2.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp index 9531272a07..e34c86158d 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp +++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp @@ -249,8 +249,6 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::QueryInterface(REFIID id, LPVOI //*iface = (IAccessibleHypertext*)this; } else if (id == IID_IAccessibleImage) { //*iface = (IAccessibleImage*)this; - } else if (id == IID_IAccessibleRelation) { - *iface = (IAccessibleRelation*)this; } else if (id == IID_IAccessibleTable) { //*iface = (IAccessibleTable*)this; // not supported } else if (id == IID_IAccessibleTable2) { From 403b7d4a21bba14bc059ad0c84a7614f221255e9 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 22 Feb 2016 16:56:07 +0100 Subject: [PATCH 20/38] Windows Accessibility: Refactor code creating COM arrays. Introduce a convenience function for allocating arrays and use algorithms. Task-number: QTBUG-50804 Change-Id: Iead75f8297923fd13efcfc7987f76262777d074b Reviewed-by: Joerg Bornemann --- .../windows/accessible/iaccessible2.cpp | 47 ++++++++++++------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp index e34c86158d..abca91a7db 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp +++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp @@ -41,8 +41,16 @@ #include #include +#include + QT_BEGIN_NAMESPACE +template +static inline T *coTaskMemAllocArray(int size) +{ + return static_cast(::CoTaskMemAlloc(sizeof(T) * size_t(size))); +} + /**************************************************************\ * AccessibleApplication * **************************************************************/ @@ -591,9 +599,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_keyBinding(long actionIndex numBindings = keyBindings.count(); if (numBindings > 0) { // The IDL documents that the client must free with CoTaskMemFree - arrayOfBindingsToReturn = (BSTR*)::CoTaskMemAlloc(sizeof(BSTR) * numBindings); - for (int i = 0; i < numBindings; ++i) - arrayOfBindingsToReturn[i] = QStringToBSTR(keyBindings.at(i)); + arrayOfBindingsToReturn = coTaskMemAllocArray(numBindings); + std::transform(keyBindings.constBegin(), keyBindings.constEnd(), + arrayOfBindingsToReturn, QStringToBSTR); } } *keyBindings = arrayOfBindingsToReturn; @@ -970,12 +978,13 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedColumns(long **sele if (QAccessibleTableInterface *tableIface = tableInterface()) { const QList selectedIndices = tableIface->selectedColumns(); - const int &count = selectedIndices.count(); - long *selected = (count ? (long*)::CoTaskMemAlloc(sizeof(long) * count) : (long*)0); - for (int i = 0; i < count; ++i) - selected[i] = selectedIndices.at(i); - *selectedColumns = selected; + const int count = selectedIndices.count(); *nColumns = count; + *selectedColumns = Q_NULLPTR; + if (count) { + *selectedColumns = coTaskMemAllocArray(count); + std::copy(selectedIndices.constBegin(), selectedIndices.constEnd(), *selectedColumns); + } return count ? S_OK : S_FALSE; } return E_FAIL; @@ -991,12 +1000,13 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedRows(long **selecte if (QAccessibleTableInterface *tableIface = tableInterface()) { const QList selectedIndices = tableIface->selectedRows(); - const int &count = selectedIndices.count(); - long *selected = (count ? (long*)::CoTaskMemAlloc(sizeof(long) * count) : (long*)0); - for (int i = 0; i < count; ++i) - selected[i] = selectedIndices.at(i); - *selectedRows = selected; + const int count = selectedIndices.count(); *nRows = count; + *selectedRows = Q_NULLPTR; + if (count) { + *selectedRows = coTaskMemAllocArray(count); + std::copy(selectedIndices.constBegin(), selectedIndices.constEnd(), *selectedRows); + } return count ? S_OK : S_FALSE; } return E_FAIL; @@ -1648,12 +1658,13 @@ HRESULT QWindowsIA2Accessible::wrapListOfCells(const QList(count); + std::transform(inputCells.constBegin(), inputCells.constEnd(), + *outputAccessibles, QWindowsAccessibility::wrap); + } return count > 0 ? S_OK : S_FALSE; } From 4905bf06549ce33250b13e837d192e92bffffcdb Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 22 Feb 2016 16:58:38 +0100 Subject: [PATCH 21/38] Windows Accessibility: Fix warnings as shown by Qt Creator's Clang based code model. Introduce C++ casts and add some conversions. Where possible, increase const-correctness. Remove trivial conversion function BSTRToQString(). Task-number: QTBUG-50804 Change-Id: I1820d4693db8bc0dfa6c4a5fecd768cf64a4405c Reviewed-by: Joerg Bornemann --- .../platforms/windows/accessible/comutils.cpp | 18 ++--- .../platforms/windows/accessible/comutils.h | 7 +- .../windows/accessible/iaccessible2.cpp | 71 +++++++++++-------- .../accessible/qwindowsaccessibility.cpp | 8 +-- .../accessible/qwindowsmsaaaccessible.cpp | 20 +++--- 5 files changed, 65 insertions(+), 59 deletions(-) diff --git a/src/plugins/platforms/windows/accessible/comutils.cpp b/src/plugins/platforms/windows/accessible/comutils.cpp index 94e56e8b73..acfab97899 100644 --- a/src/plugins/platforms/windows/accessible/comutils.cpp +++ b/src/plugins/platforms/windows/accessible/comutils.cpp @@ -58,15 +58,15 @@ static DATE QDateTimeToDATE(const QDateTime &dt) QDate date = dt.date(); QTime time = dt.time(); if (date.isValid() && !date.isNull()) { - stime.wDay = date.day(); - stime.wMonth = date.month(); - stime.wYear = date.year(); + stime.wDay = WORD(date.day()); + stime.wMonth = WORD(date.month()); + stime.wYear = WORD(date.year()); } if (time.isValid() && !time.isNull()) { - stime.wMilliseconds = time.msec(); - stime.wSecond = time.second(); - stime.wMinute = time.minute(); - stime.wHour = time.hour(); + stime.wMilliseconds = WORD(time.msec()); + stime.wSecond = WORD(time.second()); + stime.wMinute = WORD(time.minute()); + stime.wHour = WORD(time.hour()); } double vtime; @@ -92,8 +92,8 @@ bool QVariant2VARIANT(const QVariant &var, VARIANT &arg, const QByteArray &typeN proptype = QVariant::Double; } if (proptype != QVariant::Invalid && proptype != QVariant::UserType && proptype != qvar.type()) { - if (qvar.canConvert(proptype)) - qvar.convert(proptype); + if (qvar.canConvert(int(proptype))) + qvar.convert(int(proptype)); else qvar = QVariant(proptype); } diff --git a/src/plugins/platforms/windows/accessible/comutils.h b/src/plugins/platforms/windows/accessible/comutils.h index 113d79d473..d5476aa6e8 100644 --- a/src/plugins/platforms/windows/accessible/comutils.h +++ b/src/plugins/platforms/windows/accessible/comutils.h @@ -47,14 +47,9 @@ class QVariant; // Originally QVariantToVARIANT copied from ActiveQt - renamed to avoid conflicts in static builds. bool QVariant2VARIANT(const QVariant &var, VARIANT &arg, const QByteArray &typeName, bool out); -inline QString BSTRToQString(const BSTR &bstr) -{ - return QString((QChar*)bstr); -} - inline BSTR QStringToBSTR(const QString &str) { - return SysAllocStringLen((OLECHAR*)str.unicode(), str.length()); + return SysAllocStringLen(reinterpret_cast(str.unicode()), UINT(str.length())); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp index abca91a7db..7c0b0370b3 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp +++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp @@ -60,7 +60,7 @@ HRESULT STDMETHODCALLTYPE AccessibleApplication::QueryInterface(REFIID id, LPVOI *iface = 0; if (id == IID_IUnknown) { qCDebug(lcQpaAccessibility) << "AccessibleApplication::QI(): IID_IUnknown"; - *iface = (IUnknown*)this; + *iface = static_cast(this); } else if (id == IID_IAccessibleApplication) { qCDebug(lcQpaAccessibility) << "AccessibleApplication::QI(): IID_IAccessibleApplication"; *iface = static_cast(this); @@ -130,7 +130,7 @@ HRESULT STDMETHODCALLTYPE AccessibleRelation::QueryInterface(REFIID id, LPVOID * { *iface = 0; if (id == IID_IUnknown || id == IID_IAccessibleRelation) - *iface = (IUnknown*)this; + *iface = static_cast(this); if (*iface) { AddRef(); @@ -208,7 +208,7 @@ HRESULT STDMETHODCALLTYPE AccessibleRelation::get_targets( /* [retval][out] */ long *nTargets) { - const int numTargets = qMin((int)maxTargets, m_targets.count()); + const int numTargets = qMin(int(maxTargets), m_targets.count()); for (int i = 0; i < numTargets; ++i) { QAccessibleInterface *iface = m_targets.at(i); IAccessible *iacc = QWindowsAccessibility::wrap(iface); @@ -237,40 +237,40 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::QueryInterface(REFIID id, LPVOI HRESULT hr = QWindowsMsaaAccessible::QueryInterface(id, iface); if (!SUCCEEDED(hr)) { if (id == IID_IServiceProvider) { - *iface = (IServiceProvider*)this; + *iface = static_cast(this); } else if (id == IID_IAccessible2) { - *iface = (IAccessible2*)this; + *iface = static_cast(this); } else if (id == IID_IAccessibleAction) { if (accessible->actionInterface()) - *iface = (IAccessibleAction*)this; + *iface = static_cast(this); } else if (id == IID_IAccessibleComponent) { - *iface = (IAccessibleComponent*)this; + *iface = static_cast(this); } else if (id == IID_IAccessibleEditableText) { if (accessible->editableTextInterface() || accessible->role() == QAccessible::EditableText) { - *iface = (IAccessibleEditableText*)this; + *iface = static_cast(this); } } else if (id == IID_IAccessibleHyperlink) { - //*iface = (IAccessibleHyperlink*)this; + //*iface = static_cast(this); } else if (id == IID_IAccessibleHypertext) { - //*iface = (IAccessibleHypertext*)this; + //*iface = static_cast(this); } else if (id == IID_IAccessibleImage) { - //*iface = (IAccessibleImage*)this; + //*iface = static_cast(this); } else if (id == IID_IAccessibleTable) { - //*iface = (IAccessibleTable*)this; // not supported + //*iface = static_cast(this); // not supported } else if (id == IID_IAccessibleTable2) { if (accessible->tableInterface()) - *iface = (IAccessibleTable2*)this; + *iface = static_cast(this); } else if (id == IID_IAccessibleTableCell) { if (accessible->tableCellInterface()) - *iface = (IAccessibleTableCell*)this; + *iface = static_cast(this); } else if (id == IID_IAccessibleText) { if (accessible->textInterface()) - *iface = (IAccessibleText*)this; + *iface = static_cast(this); } else if (id == IID_IAccessibleValue) { if (accessible->valueInterface()) - *iface = (IAccessibleValue*)this; + *iface = static_cast(this); } if (*iface) { AddRef(); @@ -674,7 +674,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_foreground(IA2Color *foregr return E_FAIL; // IA2Color is a typedef for long - *foreground = (IA2Color)accessible->foregroundColor().rgb(); + *foreground = static_cast(accessible->foregroundColor().rgb()); return S_OK; } @@ -686,7 +686,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_background(IA2Color *backgr return E_FAIL; // IA2Color is a typedef for long - *background = (IA2Color)accessible->backgroundColor().rgb(); + *background = static_cast(accessible->backgroundColor().rgb()); return S_OK; } @@ -760,7 +760,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::insertText(long offset, BSTR *t { QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - const QString txt(BSTRToQString(*text)); + const QString txt = QString::fromWCharArray(*text); if (QAccessibleEditableTextInterface *editableTextIface = accessible->editableTextInterface()) editableTextIface->insertText(offset, txt); else @@ -805,7 +805,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::replaceText(long startOffset, l { QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - const QString txt(BSTRToQString(*text)); + const QString txt = QString::fromWCharArray(*text); if (QAccessibleEditableTextInterface *editableTextIface = accessible->editableTextInterface()) editableTextIface->replaceText(startOffset, endOffset, txt); else @@ -1206,10 +1206,10 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowColumnExtents(long *row, if (!accessible || !tableCellInterface()) return E_FAIL; - *row = (long)tableCellInterface()->rowIndex(); - *column = (long)tableCellInterface()->columnIndex(); - *rowExtents = (long)tableCellInterface()->rowExtent(); - *columnExtents = (long)tableCellInterface()->columnExtent(); + *row = tableCellInterface()->rowIndex(); + *column = tableCellInterface()->columnIndex(); + *rowExtents = tableCellInterface()->rowExtent(); + *columnExtents = tableCellInterface()->columnExtent(); *isSelected = tableCellInterface()->isSelected(); return S_OK; } @@ -1250,7 +1250,8 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_attributes(long offset, QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (QAccessibleTextInterface *text = textInterface()) { - const QString attrs = text->attributes(offset, (int*)startOffset, (int*)endOffset); + const QString attrs = text->attributes(offset, reinterpret_cast(startOffset), + reinterpret_cast(endOffset)); *textAttributes = QStringToBSTR(attrs); return S_OK; } @@ -1322,7 +1323,8 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selection(long selectionInd QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (QAccessibleTextInterface *text = textInterface()) { - text->selection(selectionIndex, (int*)startOffset, (int*)endOffset); + text->selection(selectionIndex, reinterpret_cast(startOffset), + reinterpret_cast(endOffset)); return S_OK; } return E_FAIL; @@ -1354,7 +1356,10 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textBeforeOffset(long offse QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (QAccessibleTextInterface *textIface = textInterface()) { - const QString txt = textIface->textBeforeOffset(offset, (QAccessible::TextBoundaryType)boundaryType, (int*)startOffset, (int*)endOffset); + const QString txt = + textIface->textBeforeOffset(offset, static_cast(boundaryType), + reinterpret_cast(startOffset), + reinterpret_cast(endOffset)); if (!txt.isEmpty()) { *text = QStringToBSTR(txt); return S_OK; @@ -1374,7 +1379,10 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textAfterOffset( QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (QAccessibleTextInterface *textIface = textInterface()) { - const QString txt = textIface->textAfterOffset(offset, (QAccessible::TextBoundaryType)boundaryType, (int*)startOffset, (int*)endOffset); + const QString txt = + textIface->textAfterOffset(offset, static_cast(boundaryType), + reinterpret_cast(startOffset), + reinterpret_cast(endOffset)); if (!txt.isEmpty()) { *text = QStringToBSTR(txt); return S_OK; @@ -1393,7 +1401,10 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textAtOffset(long offset, QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (QAccessibleTextInterface *textIface = textInterface()) { - const QString txt = textIface->textAtOffset(offset, (QAccessible::TextBoundaryType)boundaryType, (int*)startOffset, (int*)endOffset); + const QString txt = + textIface->textAtOffset(offset, static_cast(boundaryType), + reinterpret_cast(startOffset), + reinterpret_cast(endOffset)); if (!txt.isEmpty()) { *text = QStringToBSTR(txt); return S_OK; @@ -1632,7 +1643,7 @@ HRESULT QWindowsIA2Accessible::getRelationsHelper(IAccessibleRelation **relation QList keys = relationMap.keys(); const int numRelations = keys.count(); if (relations) { - for (int i = startIndex; i < qMin(startIndex + (int)maxRelations, numRelations); ++i) { + for (int i = startIndex; i < qMin(startIndex + int(maxRelations), numRelations); ++i) { QAccessible::Relation relation = keys.at(i); QList targets = relationMap.values(relation); AccessibleRelation *rel = new AccessibleRelation(targets, relation); diff --git a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp index cdadb070a5..3e96895bf9 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp +++ b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp @@ -167,7 +167,7 @@ void QWindowsAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event) QPlatformNativeInterface *platform = QGuiApplication::platformNativeInterface(); if (!window->handle()) // Called before show(), no native window yet. return; - HWND hWnd = (HWND)platform->nativeResourceForWindow("handle", window); + const HWND hWnd = reinterpret_cast(platform->nativeResourceForWindow("handle", window)); if (event->type() != QAccessible::MenuCommand && // MenuCommand is faked event->type() != QAccessible::ObjectDestroyed) { @@ -214,7 +214,7 @@ IAccessible *QWindowsAccessibility::wrap(QAccessibleInterface *acc) QWindowsIA2Accessible *wacc = new QWindowsIA2Accessible(acc); # endif IAccessible *iacc = 0; - wacc->QueryInterface(IID_IAccessible, (void**)&iacc); + wacc->QueryInterface(IID_IAccessible, reinterpret_cast(&iacc)); return iacc; #endif // defined(Q_OS_WINCE) } @@ -224,7 +224,7 @@ bool QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(HWND hwnd, W #if !defined(Q_OS_WINCE) if (static_cast(lParam) == static_cast(UiaRootObjectId)) { /* For UI Automation */ - } else if ((DWORD)lParam == DWORD(OBJID_CLIENT)) { + } else if (DWORD(lParam) == DWORD(OBJID_CLIENT)) { // Start handling accessibility internally QGuiApplicationPrivate::platformIntegration()->accessibility()->setActive(true); // Ignoring all requests while starting up @@ -238,7 +238,7 @@ bool QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(HWND hwnd, W if (!oleaccChecked) { oleaccChecked = true; - ptrLresultFromObject = (PtrLresultFromObject)QSystemLibrary::resolve(QLatin1String("oleacc"), "LresultFromObject"); + ptrLresultFromObject = reinterpret_cast(QSystemLibrary::resolve(QLatin1String("oleacc"), "LresultFromObject")); } if (ptrLresultFromObject) { diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp index 2189938248..4ecf78dbf6 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp +++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp @@ -94,9 +94,9 @@ HRESULT STDMETHODCALLTYPE QWindowsEnumerate::QueryInterface(REFIID id, LPVOID *i { *iface = 0; if (id == IID_IUnknown) - *iface = (IUnknown*)this; + *iface = static_cast(this); else if (id == IID_IEnumVARIANT) - *iface = (IEnumVARIANT*)this; + *iface = static_cast(this); if (*iface) { AddRef(); @@ -144,13 +144,13 @@ HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Next(unsigned long celt, VARIANT F ULONG l; for (l = 0; l < celt; l++) { VariantInit(&rgVar[l]); - if ((current+1) > (ULONG)array.size()) { + if (current + 1 > ULONG(array.size())) { *pCeltFetched = l; return S_FALSE; } rgVar[l].vt = VT_I4; - rgVar[l].lVal = array[(int)current]; + rgVar[l].lVal = array[int(current)]; ++current; } *pCeltFetched = l; @@ -166,8 +166,8 @@ HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Reset() HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Skip(unsigned long celt) { current += celt; - if (current > (ULONG)array.size()) { - current = array.size(); + if (current > ULONG(array.size())) { + current = ULONG(array.size()); return S_FALSE; } return S_OK; @@ -195,13 +195,13 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::QueryInterface(REFIID id, LPVO << strIID << ", iface:" << accessibleInterface(); } if (id == IID_IUnknown) { - *iface = (IUnknown*)(IDispatch*)this; + *iface = static_cast(static_cast(this)); } else if (id == IID_IDispatch) { - *iface = (IDispatch*)this; + *iface = static_cast(this); } else if (id == IID_IAccessible) { - *iface = (IAccessible*)this; + *iface = static_cast(this); } else if (id == IID_IOleWindow) { - *iface = (IOleWindow*)this; + *iface = static_cast(this); } if (*iface) { From c320d5221f166d3657771ae55585cba051f8caef Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 18 Feb 2016 13:20:24 +0100 Subject: [PATCH 22/38] Win: Prevent crash in qt_message_fatal() The source argument can be nullptr, e.g. if debug information has been stripped out. Task-number: QTBUG-51195 Change-Id: Ie229c82278c420200cad33c19e8c3f52ab7f12c3 Reviewed-by: Marc Mutz --- src/corelib/global/qlogging.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index 20c31f7ef8..e629e16e8d 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -250,10 +250,11 @@ static inline void convert_to_wchar_t_elided(wchar_t *d, size_t space, const cha if (len + 1 > space) { const size_t skip = len - space + 4; // 4 for "..." + '\0' s += skip; + len -= skip; for (int i = 0; i < 3; ++i) *d++ = L'.'; } - while (*s) + while (len--) *d++ = *s++; *d++ = 0; } From 0a8fd9c620adfc5dd38f41fcd14537296fde13b6 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 26 Feb 2016 01:25:29 +0100 Subject: [PATCH 23/38] tst_qguimetatype::flags(): port to QTypeInfoQuery QTypeInfoQuery was introduced for 5.6 to decouple isStatic and isRelocatable so old code continues to work. But since this test still uses !isStatic to mean trivially-relocatable, it will fail as soon as one of the checked types is marked as Q_RELOCATABLE_TYPE instead of Q_MOVABLE_TYPE. Incidentally, such a change is in the pipeline for Qt 5.7/5.8, so fix the test by porting to QTypeInfoQuery. Do this in 5.6, because that's when QTypeInfoQuery was introduced. Change-Id: I06f815f26ca9b430e124c4a2f8de2a729999762b Reviewed-by: Olivier Goffart (Woboq GmbH) --- tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp b/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp index d8709baa18..73a2f83bac 100644 --- a/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp +++ b/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp @@ -346,11 +346,11 @@ struct TypeAlignment void tst_QGuiMetaType::flags_data() { QTest::addColumn("type"); - QTest::addColumn("isMovable"); + QTest::addColumn("isRelocatable"); QTest::addColumn("isComplex"); #define ADD_METATYPE_TEST_ROW(MetaTypeName, MetaTypeId, RealType) \ - QTest::newRow(#RealType) << MetaTypeId << bool(!QTypeInfo::isStatic) << bool(QTypeInfo::isComplex); + QTest::newRow(#RealType) << MetaTypeId << bool(QTypeInfoQuery::isRelocatable) << bool(QTypeInfoQuery::isComplex); QT_FOR_EACH_STATIC_GUI_CLASS(ADD_METATYPE_TEST_ROW) #undef ADD_METATYPE_TEST_ROW } @@ -358,12 +358,12 @@ QT_FOR_EACH_STATIC_GUI_CLASS(ADD_METATYPE_TEST_ROW) void tst_QGuiMetaType::flags() { QFETCH(int, type); - QFETCH(bool, isMovable); + QFETCH(bool, isRelocatable); QFETCH(bool, isComplex); QCOMPARE(bool(QMetaType::typeFlags(type) & QMetaType::NeedsConstruction), isComplex); QCOMPARE(bool(QMetaType::typeFlags(type) & QMetaType::NeedsDestruction), isComplex); - QCOMPARE(bool(QMetaType::typeFlags(type) & QMetaType::MovableType), isMovable); + QCOMPARE(bool(QMetaType::typeFlags(type) & QMetaType::MovableType), isRelocatable); } From 45ae0cb780c1c11eddc3adb5d09c1d95b188b238 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 12 Jan 2016 15:43:22 +0100 Subject: [PATCH 24/38] Remove a mis-placed QSKIP(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It made us skip the rest of the test, not just the small set of sub-tests that were conditioned by the if () in whose else it sat. Change-Id: I5e914e0aeb9d5ba44b21966d071aaccbc590365d Reviewed-by: Jędrzej Nowacki --- tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp index f6f1c05814..35c278da0e 100644 --- a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp @@ -718,8 +718,6 @@ void tst_QDateTime::fromMSecsSinceEpoch() QCOMPARE(dtLocal.toLocalTime(), cet); QCOMPARE(dtUtc.toLocalTime(), cet); QCOMPARE(dtOffset.toLocalTime(), cet); - } else { - QSKIP("You must test using Central European (CET/CEST) time zone, e.g. TZ=Europe/Oslo"); } // LocalTime will overflow for max From 13bcdc0f50d04dc5b48ecd1a21da3fa754d10602 Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Fri, 26 Feb 2016 12:01:36 +0300 Subject: [PATCH 25/38] ItemModels: replace QLatin1String with QStringLiteral ... wherever it allocates memory. Since the string literal is used in more than one function, to avoid duplication of .rodata, wrap the QStringLiteral in an inline function. Change-Id: If4fca7443b3150b1c8360c850da32f5c567c1065 Reviewed-by: Marc Mutz --- src/corelib/itemmodels/qabstractitemmodel.cpp | 2 +- src/gui/itemmodels/qstandarditemmodel.cpp | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp index 7d80cb0e2b..02b1e1c306 100644 --- a/src/corelib/itemmodels/qabstractitemmodel.cpp +++ b/src/corelib/itemmodels/qabstractitemmodel.cpp @@ -1845,7 +1845,7 @@ bool QAbstractItemModel::setItemData(const QModelIndex &index, const QMaphasFormat(format)) return QAbstractItemModel::dropMimeData(data, action, row, column, parent); From 9f134750a1ab677cfba4f42fbf72208405e04b84 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 23 Feb 2016 15:26:49 +0100 Subject: [PATCH 26/38] QPlatformWindow::screenForGeometry(): Do not call mapToGlobal() on top level geometry. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use mapToGlobal() only for foreign windows passing relative coordinates. Amend change 9915630d0886434e8984904b1cadedc81dc78ca0. Task-number: QTBUG-50206 Task-number: QTBUG-51320 Change-Id: Idee60cc8ea8004c0355ce78a00f807798836b49c Reviewed-by: Morten Johan Sørvig --- src/gui/kernel/qplatformwindow.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp index 04532e82aa..9f2c6af51f 100644 --- a/src/gui/kernel/qplatformwindow.cpp +++ b/src/gui/kernel/qplatformwindow.cpp @@ -486,8 +486,9 @@ QPlatformScreen *QPlatformWindow::screenForGeometry(const QRect &newGeometry) co QPlatformScreen *fallback = currentScreen; // QRect::center can return a value outside the rectangle if it's empty. // Apply mapToGlobal() in case it is a foreign/embedded window. - const QPoint center = - mapToGlobal(newGeometry.isEmpty() ? newGeometry.topLeft() : newGeometry.center()); + QPoint center = newGeometry.isEmpty() ? newGeometry.topLeft() : newGeometry.center(); + if (window()->type() == Qt::ForeignWindow) + center = mapToGlobal(center - newGeometry.topLeft()); if (!parent() && currentScreen && !currentScreen->geometry().contains(center)) { Q_FOREACH (QPlatformScreen* screen, currentScreen->virtualSiblings()) { From 9c63ad562bf0a44807f41ce49e4fe1b5ff181a63 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 10 Feb 2016 15:43:15 +0100 Subject: [PATCH 27/38] qmake: restore nothrow move special members The user-defined copy assignment, copy constructor and dtor inhibit the move special member functions. Implement them manually. Change-Id: I0d38d7cf6c9611e13b5b081d734d01d6fe4d5276 Reviewed-by: Oswald Buddenhagen Reviewed-by: Marc Mutz --- qmake/library/proitems.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/qmake/library/proitems.h b/qmake/library/proitems.h index 858ed2e4ca..721abb90d0 100644 --- a/qmake/library/proitems.h +++ b/qmake/library/proitems.h @@ -364,6 +364,8 @@ class ProFunctionDef { public: ProFunctionDef(ProFile *pro, int offset) : m_pro(pro), m_offset(offset) { m_pro->ref(); } ProFunctionDef(const ProFunctionDef &o) : m_pro(o.m_pro), m_offset(o.m_offset) { m_pro->ref(); } + ProFunctionDef(ProFunctionDef &&other) Q_DECL_NOTHROW + : m_pro(other.m_pro), m_offset(other.m_offset) { other.m_pro = nullptr; } ~ProFunctionDef() { m_pro->deref(); } ProFunctionDef &operator=(const ProFunctionDef &o) { @@ -375,6 +377,18 @@ public: } return *this; } + ProFunctionDef &operator=(ProFunctionDef &&other) Q_DECL_NOTHROW + { + ProFunctionDef moved(std::move(other)); + swap(moved); + return *this; + } + void swap(ProFunctionDef &other) Q_DECL_NOTHROW + { + qSwap(m_pro, other.m_pro); + qSwap(m_offset, other.m_offset); + } + ProFile *pro() const { return m_pro; } const ushort *tokPtr() const { return m_pro->tokPtr() + m_offset; } private: From bc5917a10a16dd33b8c12c61db981f0328882049 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 26 Feb 2016 10:16:28 +0100 Subject: [PATCH 28/38] Fix warnings about constructor initialization order in tst_QObject. tst_qobject.cpp: In constructor 'DispatcherWatcher::DispatcherWatcher(QEventLoop&, int*, int*)': tst_qobject.cpp:5871:10: warning: 'DispatcherWatcher::m_statusAboutToBlock' will be initialized after [-Wreorder] tst_qobject.cpp:5870:10: warning: 'int* DispatcherWatcher::m_statusAwake' [-Wreorder] tst_qobject.cpp:5815:5: warning: when initialized here [-Wreorder] tst_qobject.cpp:5870:10: warning: 'DispatcherWatcher::m_statusAwake' will be initialized after [-Wreorder] tst_qobject.cpp:5869:17: warning: 'QEventLoop* DispatcherWatcher::m_eventLoop' [-Wreorder] Amends change c5d49725779292a04fed599eb7f508d334ffc5c3. Task-number: QTBUG-18434 Task-number: QTBUG-32859 Task-number: QTBUG-36434 Change-Id: I03a9c872469334741a26b4dc1783a36d48f1556f Reviewed-by: Paolo Angelelli Reviewed-by: Olivier Goffart (Woboq GmbH) --- tests/auto/corelib/kernel/qobject/tst_qobject.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index b1b94a3c5f..540cd66715 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -5813,9 +5813,9 @@ class DispatcherWatcher : public QObject Q_OBJECT public: DispatcherWatcher(QEventLoop &e, int *statusAwake, int *statusAboutToBlock) : - m_statusAboutToBlock(statusAboutToBlock), - m_statusAwake(statusAwake), m_eventLoop(&e), + m_statusAwake(statusAwake), + m_statusAboutToBlock(statusAboutToBlock), m_aboutToBlocks(0), m_awakes(0) { From 1d8030cc64df2cdfdc0faf3d06ea7d9ed0306948 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 30 Dec 2015 02:04:26 +0100 Subject: [PATCH 29/38] QtWidgets: prevent detach attempts from first()/etc. use [dialogs, kernel, util, widgets] The algorithm used was: - If possible, just declare the container const - Otherwise, for first()/last(), use constFirst()/constLast() and for front()/back(), to not destroy the use of the STL API subset, use qAsConst() Did some caching of function returns here and there, and converted one 0 to nullptr as a drive-by. Also saves almost 4KiB in text size on optimized GCC 4.9 Linux AMD64 builds. Change-Id: I04b7bfd68dc85c22de247cb65a310e1cbbca1e8c Reviewed-by: Thiago Macieira Reviewed-by: Lars Knoll Reviewed-by: Marc Mutz --- src/widgets/dialogs/qfiledialog.cpp | 8 +++---- src/widgets/dialogs/qfileinfogatherer.cpp | 4 ++-- src/widgets/dialogs/qfilesystemmodel.cpp | 2 +- src/widgets/dialogs/qsidebar.cpp | 4 ++-- src/widgets/dialogs/qwizard.cpp | 4 ++-- src/widgets/kernel/qapplication.cpp | 6 ++--- src/widgets/util/qcompleter.cpp | 4 ++-- src/widgets/util/qscroller.cpp | 27 ++++++++++++++-------- src/widgets/util/qundostack.cpp | 8 +++---- src/widgets/widgets/qdockarealayout.cpp | 6 ++--- src/widgets/widgets/qmainwindowlayout.cpp | 10 ++++---- src/widgets/widgets/qmenu.cpp | 2 +- src/widgets/widgets/qtabbar.cpp | 6 ++--- src/widgets/widgets/qtoolbararealayout.cpp | 2 +- 14 files changed, 51 insertions(+), 42 deletions(-) diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index 50667e2a91..c4ed72edc3 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -2689,7 +2689,7 @@ void QFileDialogPrivate::saveSettings() settings.beginGroup(QLatin1String("FileDialog")); if (usingWidgets()) { - settings.setValue(QLatin1String("sidebarWidth"), qFileDialogUi->splitter->sizes().first()); + settings.setValue(QLatin1String("sidebarWidth"), qFileDialogUi->splitter->sizes().constFirst()); settings.setValue(QLatin1String("shortcuts"), QUrl::toStringList(qFileDialogUi->sidebar->urls())); settings.setValue(QLatin1String("treeViewHeader"), qFileDialogUi->treeView->header()->saveState()); } @@ -3001,9 +3001,9 @@ void QFileDialogPrivate::createWidgets() q->selectNameFilter(options->initiallySelectedNameFilter()); q->setDefaultSuffix(options->defaultSuffix()); q->setHistory(options->history()); - if (options->initiallySelectedFiles().count() == 1) - q->selectFile(options->initiallySelectedFiles().first().fileName()); const auto initiallySelectedFiles = options->initiallySelectedFiles(); + if (initiallySelectedFiles.size() == 1) + q->selectFile(initiallySelectedFiles.first().fileName()); for (const QUrl &url : initiallySelectedFiles) q->selectUrl(url); lineEdit()->selectAll(); @@ -4095,7 +4095,7 @@ QStringList QFSCompleter::splitPath(const QString &path) const parts.removeFirst(); currentLocationList.removeLast(); } - if (!currentLocationList.isEmpty() && currentLocationList.last().isEmpty()) + if (!currentLocationList.isEmpty() && currentLocationList.constLast().isEmpty()) currentLocationList.removeLast(); return currentLocationList + parts; } diff --git a/src/widgets/dialogs/qfileinfogatherer.cpp b/src/widgets/dialogs/qfileinfogatherer.cpp index 48ae5f1fc4..b20db8fc7c 100644 --- a/src/widgets/dialogs/qfileinfogatherer.cpp +++ b/src/widgets/dialogs/qfileinfogatherer.cpp @@ -217,9 +217,9 @@ void QFileInfoGatherer::run() condition.wait(&mutex); if (abort.load()) return; - const QString thisPath = path.front(); + const QString thisPath = qAsConst(path).front(); path.pop_front(); - const QStringList thisList = files.front(); + const QStringList thisList = qAsConst(files).front(); files.pop_front(); locker.unlock(); diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp index bfa40317eb..c72761f2ae 100644 --- a/src/widgets/dialogs/qfilesystemmodel.cpp +++ b/src/widgets/dialogs/qfilesystemmodel.cpp @@ -374,7 +374,7 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS QModelIndex index = QModelIndex(); // start with "My Computer" #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) if (absolutePath.startsWith(QLatin1String("//"))) { // UNC path - QString host = QLatin1String("\\\\") + pathElements.first(); + QString host = QLatin1String("\\\\") + pathElements.constFirst(); if (absolutePath == QDir::fromNativeSeparators(host)) absolutePath.append(QLatin1Char('/')); if (longPath.endsWith(QLatin1Char('/')) && !absolutePath.endsWith(QLatin1Char('/'))) diff --git a/src/widgets/dialogs/qsidebar.cpp b/src/widgets/dialogs/qsidebar.cpp index 2e884e238d..1b1eb6472e 100644 --- a/src/widgets/dialogs/qsidebar.cpp +++ b/src/widgets/dialogs/qsidebar.cpp @@ -127,7 +127,7 @@ QMimeData *QUrlModel::mimeData(const QModelIndexList &indexes) const */ bool QUrlModel::canDrop(QDragEnterEvent *event) { - if (!event->mimeData()->formats().contains(mimeTypes().first())) + if (!event->mimeData()->formats().contains(mimeTypes().constFirst())) return false; const QList list = event->mimeData()->urls(); @@ -145,7 +145,7 @@ bool QUrlModel::canDrop(QDragEnterEvent *event) bool QUrlModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) { - if (!data->formats().contains(mimeTypes().first())) + if (!data->formats().contains(mimeTypes().constFirst())) return false; Q_UNUSED(action); Q_UNUSED(column); diff --git a/src/widgets/dialogs/qwizard.cpp b/src/widgets/dialogs/qwizard.cpp index aa10f65389..53f947354c 100644 --- a/src/widgets/dialogs/qwizard.cpp +++ b/src/widgets/dialogs/qwizard.cpp @@ -850,9 +850,9 @@ void QWizardPrivate::switchToPage(int newId, Direction direction) q->cleanupPage(oldId); initialized.remove(oldId); } - Q_ASSERT(history.last() == oldId); + Q_ASSERT(history.constLast() == oldId); history.removeLast(); - Q_ASSERT(history.last() == newId); + Q_ASSERT(history.constLast() == newId); } } diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index ebdbdbd3e6..eee91fea47 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -786,7 +786,7 @@ void QApplicationPrivate::initializeWidgetFontHash() QWidget *QApplication::activePopupWidget() { return QApplicationPrivate::popupWidgets && !QApplicationPrivate::popupWidgets->isEmpty() ? - QApplicationPrivate::popupWidgets->last() : 0; + QApplicationPrivate::popupWidgets->constLast() : nullptr; } @@ -2391,7 +2391,7 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, con const QPoint globalPos = qIsInf(globalPosF.x()) ? QPoint(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX) : globalPosF.toPoint(); - const QPoint windowPos = enterList.back()->window()->mapFromGlobal(globalPos); + const QPoint windowPos = qAsConst(enterList).back()->window()->mapFromGlobal(globalPos); for (auto it = enterList.crbegin(), end = enterList.crend(); it != end; ++it) { auto *w = *it; if (!QApplication::activeModalWidget() || QApplicationPrivate::tryModalHelper(w, 0)) { @@ -3795,7 +3795,7 @@ void QApplicationPrivate::closePopup(QWidget *popup) } else { // A popup was closed, so the previous popup gets the focus. - QWidget* aw = QApplicationPrivate::popupWidgets->last(); + QWidget* aw = QApplicationPrivate::popupWidgets->constLast(); if (QWidget *fw = aw->focusWidget()) fw->setFocus(Qt::PopupFocusReason); diff --git a/src/widgets/util/qcompleter.cpp b/src/widgets/util/qcompleter.cpp index 9c61a3a263..9f167f5924 100644 --- a/src/widgets/util/qcompleter.cpp +++ b/src/widgets/util/qcompleter.cpp @@ -755,9 +755,9 @@ void QUnsortedModelEngine::filterOnDemand(int n) const QAbstractItemModel *model = c->proxy->sourceModel(); int lastRow = model->rowCount(curParent) - 1; QIndexMapper im(curMatch.indices.last() + 1, lastRow); - int lastIndex = buildIndices(curParts.last(), curParent, n, im, &curMatch); + int lastIndex = buildIndices(curParts.constLast(), curParent, n, im, &curMatch); curMatch.partial = (lastRow != lastIndex); - saveInCache(curParts.last(), curParent, curMatch); + saveInCache(curParts.constLast(), curParent, curMatch); } QMatchData QUnsortedModelEngine::filter(const QString& part, const QModelIndex& parent, int n) diff --git a/src/widgets/util/qscroller.cpp b/src/widgets/util/qscroller.cpp index 2d6bcf72c6..02e3c2b82a 100644 --- a/src/widgets/util/qscroller.cpp +++ b/src/widgets/util/qscroller.cpp @@ -575,8 +575,11 @@ QPointF QScroller::pixelPerMeter() const if (QGraphicsObject *go = qobject_cast(d->target)) { QTransform viewtr; //TODO: the first view isn't really correct - maybe use an additional field in the prepare event? - if (go->scene() && !go->scene()->views().isEmpty()) - viewtr = go->scene()->views().first()->viewportTransform(); + if (const auto *scene = go->scene()) { + const auto views = scene->views(); + if (!views.isEmpty()) + viewtr = views.first()->viewportTransform(); + } QTransform tr = go->deviceTransform(viewtr); if (tr.isScaling()) { QPointF p0 = tr.map(QPointF(0, 0)); @@ -1121,12 +1124,15 @@ void QScrollerPrivate::pushSegment(ScrollType type, qreal deltaTime, qreal stopP return; ScrollSegment s; - if (orientation == Qt::Horizontal && !xSegments.isEmpty()) - s.startTime = xSegments.last().startTime + xSegments.last().deltaTime * xSegments.last().stopProgress; - else if (orientation == Qt::Vertical && !ySegments.isEmpty()) - s.startTime = ySegments.last().startTime + ySegments.last().deltaTime * ySegments.last().stopProgress; - else + if (orientation == Qt::Horizontal && !xSegments.isEmpty()) { + const auto &lastX = xSegments.constLast(); + s.startTime = lastX.startTime + lastX.deltaTime * lastX.stopProgress; + } else if (orientation == Qt::Vertical && !ySegments.isEmpty()) { + const auto &lastY = ySegments.constLast(); + s.startTime = lastY.startTime + lastY.deltaTime * lastY.stopProgress; + } else { s.startTime = monotonicTimer.elapsed(); + } s.startPos = startPos; s.deltaPos = deltaPos; @@ -1463,8 +1469,11 @@ bool QScrollerPrivate::prepareScrolling(const QPointF &position) #ifndef QT_NO_GRAPHICSVIEW if (QGraphicsObject *go = qobject_cast(target)) { //TODO: the first view isn't really correct - maybe use an additional field in the prepare event? - if (go->scene() && !go->scene()->views().isEmpty()) - setDpiFromWidget(go->scene()->views().first()); + if (const auto *scene = go->scene()) { + const auto views = scene->views(); + if (!views.isEmpty()) + setDpiFromWidget(views.first()); + } } #endif diff --git a/src/widgets/util/qundostack.cpp b/src/widgets/util/qundostack.cpp index 6643b4429c..6f733f99d5 100644 --- a/src/widgets/util/qundostack.cpp +++ b/src/widgets/util/qundostack.cpp @@ -588,9 +588,9 @@ void QUndoStack::push(QUndoCommand *cmd) QUndoCommand *cur = 0; if (macro) { - QUndoCommand *macro_cmd = d->macro_stack.last(); + QUndoCommand *macro_cmd = d->macro_stack.constLast(); if (!macro_cmd->d->child_list.isEmpty()) - cur = macro_cmd->d->child_list.last(); + cur = macro_cmd->d->child_list.constLast(); } else { if (d->index > 0) cur = d->command_list.at(d->index - 1); @@ -616,7 +616,7 @@ void QUndoStack::push(QUndoCommand *cmd) } } else { if (macro) { - d->macro_stack.last()->d->child_list.append(cmd); + d->macro_stack.constLast()->d->child_list.append(cmd); } else { d->command_list.append(cmd); d->checkUndoLimit(); @@ -963,7 +963,7 @@ void QUndoStack::beginMacro(const QString &text) d->clean_index = -1; // we've deleted the clean state d->command_list.append(cmd); } else { - d->macro_stack.last()->d->child_list.append(cmd); + d->macro_stack.constLast()->d->child_list.append(cmd); } d->macro_stack.append(cmd); diff --git a/src/widgets/widgets/qdockarealayout.cpp b/src/widgets/widgets/qdockarealayout.cpp index 29089311c6..c14fd5a942 100644 --- a/src/widgets/widgets/qdockarealayout.cpp +++ b/src/widgets/widgets/qdockarealayout.cpp @@ -3096,7 +3096,7 @@ void QDockAreaLayout::addDockWidget(QInternal::DockPosition pos, QDockWidget *do void QDockAreaLayout::tabifyDockWidget(QDockWidget *first, QDockWidget *second) { - QList path = indexOf(first); + const QList path = indexOf(first); if (path.isEmpty()) return; @@ -3133,7 +3133,7 @@ void QDockAreaLayout::resizeDocks(const QList &docks, while (path.size() > 1) { QDockAreaLayoutInfo *info = this->info(path); if (!info->tabbed && info->o == o) { - info->item_list[path.last()].size = size; + info->item_list[path.constLast()].size = size; int totalSize = 0; foreach (const QDockAreaLayoutItem &item, info->item_list) { if (!item.skip()) { @@ -3147,7 +3147,7 @@ void QDockAreaLayout::resizeDocks(const QList &docks, path.removeLast(); } - const int dockNum = path.first(); + const int dockNum = path.constFirst(); Q_ASSERT(dockNum < QInternal::DockCount); QRect &r = this->docks[dockNum].rect; QSize s = r.size(); diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp index ae87ea526d..e46063917d 100644 --- a/src/widgets/widgets/qmainwindowlayout.cpp +++ b/src/widgets/widgets/qmainwindowlayout.cpp @@ -1163,7 +1163,7 @@ void QMainWindowLayout::insertToolBar(QToolBar *before, QToolBar *toolbar) // copy the toolbar also in the saved state savedState.toolBarAreaLayout.insertItem(before, item); } - if (!currentGapPos.isEmpty() && currentGapPos.first() == 0) { + if (!currentGapPos.isEmpty() && currentGapPos.constFirst() == 0) { currentGapPos = layoutState.toolBarAreaLayout.currentGapIndex(); if (!currentGapPos.isEmpty()) { currentGapPos.prepend(0); @@ -1501,7 +1501,7 @@ void QMainWindowLayout::splitDockWidget(QDockWidget *after, Qt::DockWidgetArea QMainWindowLayout::dockWidgetArea(QWidget *widget) const { - QList pathToWidget = layoutState.dockAreaLayout.indexOf(widget); + const QList pathToWidget = layoutState.dockAreaLayout.indexOf(widget); if (pathToWidget.isEmpty()) return Qt::NoDockWidgetArea; return toDockWidgetArea(pathToWidget.first()); @@ -1783,7 +1783,7 @@ QLayoutItem *QMainWindowLayout::takeAt(int index) } #ifndef QT_NO_TOOLBAR - if (!currentGapPos.isEmpty() && currentGapPos.first() == 0) { + if (!currentGapPos.isEmpty() && currentGapPos.constFirst() == 0) { currentGapPos = layoutState.toolBarAreaLayout.currentGapIndex(); if (!currentGapPos.isEmpty()) { currentGapPos.prepend(0); @@ -2057,7 +2057,7 @@ void QMainWindowLayout::animationFinished(QWidget *widget) if (parentInfo->tabbed) { // merge the two tab widgets - int idx = path.last(); + int idx = path.constLast(); Q_ASSERT(parentInfo->item_list[idx].widgetItem->widget() == dwgw); delete parentInfo->item_list[idx].widgetItem; parentInfo->item_list.removeAt(idx); @@ -2283,7 +2283,7 @@ QLayoutItem *QMainWindowLayout::unplug(QWidget *widget, bool group) #ifndef QT_NO_DOCKWIDGET if (QDockWidget *dw = qobject_cast(widget)) { - Q_ASSERT(path.first() == 1); + Q_ASSERT(path.constFirst() == 1); bool actualGroup = false; #ifndef QT_NO_TABBAR if (group && (dockOptions & QMainWindow::GroupedDragging) && path.size() > 3) { diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index 514cb1a8c9..c07d48a513 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -117,7 +117,7 @@ public: { Q_D(QTornOffMenu); // make the torn-off menu a sibling of p (instead of a child) - QWidget *parentWidget = d->causedStack.isEmpty() ? p : d->causedStack.last(); + QWidget *parentWidget = d->causedStack.isEmpty() ? p : d->causedStack.constLast(); if (parentWidget->parentWidget()) parentWidget = parentWidget->parentWidget(); setParent(parentWidget, Qt::Window | Qt::Tool); diff --git a/src/widgets/widgets/qtabbar.cpp b/src/widgets/widgets/qtabbar.cpp index cf485974f6..ba3fc2fcd7 100644 --- a/src/widgets/widgets/qtabbar.cpp +++ b/src/widgets/widgets/qtabbar.cpp @@ -590,7 +590,7 @@ QRect QTabBarPrivate::normalizedScrollRect(int index) } bool tearTopVisible = index != 0 && topEdge != -scrollOffset; - bool tearBottomVisible = index != tabList.size() - 1 && bottomEdge != tabList.last().rect.bottom() + 1 - scrollOffset; + bool tearBottomVisible = index != tabList.size() - 1 && bottomEdge != tabList.constLast().rect.bottom() + 1 - scrollOffset; if (tearTopVisible && !tearLeftRect.isNull()) topEdge = tearLeftRect.bottom() + 1; if (tearBottomVisible && !tearRightRect.isNull()) @@ -621,7 +621,7 @@ QRect QTabBarPrivate::normalizedScrollRect(int index) } bool tearLeftVisible = index != 0 && leftEdge != -scrollOffset; - bool tearRightVisible = index != tabList.size() - 1 && rightEdge != tabList.last().rect.right() + 1 - scrollOffset; + bool tearRightVisible = index != tabList.size() - 1 && rightEdge != tabList.constLast().rect.right() + 1 - scrollOffset; if (tearLeftVisible && !tearLeftRect.isNull()) leftEdge = tearLeftRect.right() + 1; if (tearRightVisible && !tearRightRect.isNull()) @@ -642,7 +642,7 @@ void QTabBarPrivate::makeVisible(int index) const bool horiz = !verticalTabs(shape); const int tabStart = horiz ? tabRect.left() : tabRect.top(); const int tabEnd = horiz ? tabRect.right() : tabRect.bottom(); - const int lastTabEnd = horiz ? tabList.last().rect.right() : tabList.last().rect.bottom(); + const int lastTabEnd = horiz ? tabList.constLast().rect.right() : tabList.constLast().rect.bottom(); const QRect scrollRect = normalizedScrollRect(index); const int scrolledTabBarStart = qMax(1, scrollRect.left() + scrollOffset); const int scrolledTabBarEnd = qMin(lastTabEnd - 1, scrollRect.right() + scrollOffset); diff --git a/src/widgets/widgets/qtoolbararealayout.cpp b/src/widgets/widgets/qtoolbararealayout.cpp index 2e79b502ea..05564bb6b1 100644 --- a/src/widgets/widgets/qtoolbararealayout.cpp +++ b/src/widgets/widgets/qtoolbararealayout.cpp @@ -347,7 +347,7 @@ void QToolBarAreaLayoutInfo::removeToolBar(QToolBar *toolBar) void QToolBarAreaLayoutInfo::insertToolBarBreak(QToolBar *before) { if (before == 0) { - if (!lines.isEmpty() && lines.last().toolBarItems.isEmpty()) + if (!lines.isEmpty() && lines.constLast().toolBarItems.isEmpty()) return; lines.append(QToolBarAreaLayoutLine(o)); return; From c3761bf6a74a7ed0dee0e256794672fb73d3276d Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 26 Feb 2016 15:58:09 +0100 Subject: [PATCH 30/38] tst_QDialog::snapToDefaultButton(): Do not check on exact cursor position unless hint is set. Given the flakyness of cursor positioning, loosen the check to only verify that the cursor is outside the window. The hint is only active on Windows depending on a system setting. Task-number: QTBUG-51516 Change-Id: I474d251cc41e68f182baf8dba84eaf38d914d7ee Reviewed-by: Simon Hausmann --- .../widgets/dialogs/qdialog/tst_qdialog.cpp | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp index 37afa7f0a5..438884df33 100644 --- a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp +++ b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp @@ -560,6 +560,11 @@ void tst_QDialog::reject() QCOMPARE(dialog.called, 4); } +static QByteArray formatPoint(QPoint p) +{ + return QByteArray::number(p.x()) + ", " + QByteArray::number(p.y()); +} + void tst_QDialog::snapToDefaultButton() { #ifdef QT_NO_CURSOR @@ -568,9 +573,9 @@ void tst_QDialog::snapToDefaultButton() if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive)) QSKIP("Wayland: Wayland does not support setting the cursor position."); - QPoint topLeftPos = QApplication::desktop()->availableGeometry().topLeft(); - topLeftPos = QPoint(topLeftPos.x() + 100, topLeftPos.y() + 100); - QPoint startingPos(topLeftPos.x() + 250, topLeftPos.y() + 250); + const QRect dialogGeometry(QApplication::desktop()->availableGeometry().topLeft() + + QPoint(100, 100), QSize(200, 200)); + const QPoint startingPos = dialogGeometry.bottomRight() + QPoint(100, 100); QCursor::setPos(startingPos); #ifdef Q_OS_OSX // On OS X we use CGEventPost to move the cursor, it needs at least @@ -581,17 +586,14 @@ void tst_QDialog::snapToDefaultButton() QDialog dialog; QPushButton *button = new QPushButton(&dialog); button->setDefault(true); - dialog.setGeometry(QRect(topLeftPos, QSize(200, 200))); + dialog.setGeometry(dialogGeometry); dialog.show(); QVERIFY(QTest::qWaitForWindowExposed(&dialog)); - if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) { - if (theme->themeHint(QPlatformTheme::DialogSnapToDefaultButton).toBool()) { - QPoint localPos = button->mapFromGlobal(QCursor::pos()); - QVERIFY(button->rect().contains(localPos)); - } else { - QCOMPARE(startingPos, QCursor::pos()); - } - } + const QPoint localPos = button->mapFromGlobal(QCursor::pos()); + if (QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::DialogSnapToDefaultButton).toBool()) + QVERIFY2(button->rect().contains(localPos), formatPoint(localPos).constData()); + else + QVERIFY2(!button->rect().contains(localPos), formatPoint(localPos).constData()); #endif // !QT_NO_CURSOR } From a17a7d37c2d9a77446911a1836b9f511be7c9934 Mon Sep 17 00:00:00 2001 From: Boris Pek Date: Thu, 25 Feb 2016 01:01:37 +0300 Subject: [PATCH 31/38] Update QMAKE_LIB in win32-g++ mkspec `ar' tool from latest binutils shows warning: ar error: `u' modifier ignored since `D' is the default (see `U') Warning message includes word "error" so QtCreator processes it as error in UI. `ar' command-line option `u' might be dropped safely because it is unnecessary. Option `c' is added to suppress extra `ar' warnings. Other build systems are also affected. For example, automake: https://bugzilla.redhat.com/1155273 Change-Id: Ia378b720503d93b0c0c12ae7a5f38f4d7c32eee5 Reviewed-by: Oswald Buddenhagen --- mkspecs/win32-g++/qmake.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkspecs/win32-g++/qmake.conf b/mkspecs/win32-g++/qmake.conf index 2b9eab3e3d..f6828f68ea 100644 --- a/mkspecs/win32-g++/qmake.conf +++ b/mkspecs/win32-g++/qmake.conf @@ -105,7 +105,7 @@ QMAKE_LIBS_COMPAT = -ladvapi32 -lshell32 -lcomdlg32 -luser32 -lgdi32 -lws2 QMAKE_LIBS_QT_ENTRY = -lmingw32 -lqtmain QMAKE_IDL = midl -QMAKE_LIB = $${CROSS_COMPILE}ar -ru +QMAKE_LIB = $${CROSS_COMPILE}ar -rc QMAKE_RC = $${CROSS_COMPILE}windres QMAKE_STRIP = $${CROSS_COMPILE}strip From e1c2bfa53b7549a1283f5b52974ea90b6a2b4659 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sat, 27 Feb 2016 02:56:31 +0100 Subject: [PATCH 32/38] QtWidgets: eradicate Q_FOREACH loops [QVarLengthArray, std containers] Q_FOREACH over a QVarLengthArray or std containers is a particularly bad idea (because of the deep copy that Q_FOREACH then performs). Use C++11 range-for (without qAsConst(), because neither QVLA nor std containers are CoW). Saves 5.7KiB in text size on optimized GCC 5.3 Linux AMD64 builds. Change-Id: I4c1fb0b488bb08726912528b559840a45c1397df Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/widgets/widgets/qlineedit_p.cpp | 6 +++--- src/widgets/widgets/qmainwindowlayout.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/widgets/widgets/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp index 8410568cc1..b646e82209 100644 --- a/src/widgets/widgets/qlineedit_p.cpp +++ b/src/widgets/widgets/qlineedit_p.cpp @@ -427,7 +427,7 @@ QIcon QLineEditPrivate::clearButtonIcon() const void QLineEditPrivate::setClearButtonEnabled(bool enabled) { - foreach (const SideWidgetEntry &e, trailingSideWidgets) { + for (const SideWidgetEntry &e : trailingSideWidgets) { if (e.flags & SideWidgetClearButton) { e.action->setEnabled(enabled); break; @@ -443,13 +443,13 @@ void QLineEditPrivate::positionSideWidgets() const QSize iconSize = QLineEditPrivate::iconSize(); const int delta = QLineEditIconButton::IconMargin + iconSize.width(); QRect widgetGeometry(QPoint(QLineEditIconButton::IconMargin, (contentRect.height() - iconSize.height()) / 2), iconSize); - foreach (const SideWidgetEntry &e, leftSideWidgetList()) { + for (const SideWidgetEntry &e : leftSideWidgetList()) { e.widget->setGeometry(widgetGeometry); if (e.action->isVisible()) widgetGeometry.moveLeft(widgetGeometry.left() + delta); } widgetGeometry.moveLeft(contentRect.width() - iconSize.width() - QLineEditIconButton::IconMargin); - foreach (const SideWidgetEntry &e, rightSideWidgetList()) { + for (const SideWidgetEntry &e : rightSideWidgetList()) { e.widget->setGeometry(widgetGeometry); if (e.action->isVisible()) widgetGeometry.moveLeft(widgetGeometry.left() - delta); diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp index e46063917d..63a6c718bc 100644 --- a/src/widgets/widgets/qmainwindowlayout.cpp +++ b/src/widgets/widgets/qmainwindowlayout.cpp @@ -2386,7 +2386,7 @@ void QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos) } } } - foreach (QWidget *w, candidates) { + for (QWidget *w : candidates) { QWindow *handle1 = widget->windowHandle(); QWindow *handle2 = w->windowHandle(); if (handle1 && handle2 && handle1->screen() != handle2->screen()) From 85c2a128ef8d1b5fbddf551691bccc0770e558ba Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 26 Jan 2016 14:38:54 +0100 Subject: [PATCH 33/38] QtWidgets: eradicate Q_FOREACH loops [rvalues] ... by replacing them with C++11 range-for loops. This is the simplest of the patch series: Q_FOREACH took a copy, so we do, too. Except we don't, since we're just catching the return value that comes out of the function (RVO). We can't feed the rvalues into range-for, because they are non-const and would thus detach. Saves 2.2KiB in test size on optimized GCC 5.3 Linux AMD64 builds. Change-Id: I914aa20fe65577b2e32ea7ea89d51a8d003a57ba Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/widgets/itemviews/qtableview.cpp | 4 ++-- src/widgets/kernel/qapplication.cpp | 14 ++++++++++---- src/widgets/kernel/qgesturemanager.cpp | 9 ++++++--- src/widgets/kernel/qwhatsthis.cpp | 6 ++---- src/widgets/kernel/qwidget.cpp | 7 +++++-- src/widgets/styles/qwindowsxpstyle.cpp | 4 +++- src/widgets/util/qflickgesture.cpp | 9 ++++++--- src/widgets/widgets/qdialogbuttonbox.cpp | 3 ++- src/widgets/widgets/qmenu.cpp | 7 +++++-- 9 files changed, 41 insertions(+), 22 deletions(-) diff --git a/src/widgets/itemviews/qtableview.cpp b/src/widgets/itemviews/qtableview.cpp index 714f09e893..e045d60fc8 100644 --- a/src/widgets/itemviews/qtableview.cpp +++ b/src/widgets/itemviews/qtableview.cpp @@ -2016,8 +2016,8 @@ QRegion QTableView::visualRegionForSelection(const QItemSelection &selection) co if (viewportRect.intersects(rangeRect)) selectionRegion += rangeRect; if (d->hasSpans()) { - foreach (QSpanCollection::Span *s, - d->spans.spansInRect(range.left(), range.top(), range.width(), range.height())) { + const auto spansInRect = d->spans.spansInRect(range.left(), range.top(), range.width(), range.height()); + for (QSpanCollection::Span *s : spansInRect) { if (range.contains(s->top(), s->left(), range.parent())) { const QRect &visualSpanRect = d->visualSpanRect(*s); if (viewportRect.intersects(visualSpanRect)) diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index eee91fea47..a0a363ba2b 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -1718,9 +1718,11 @@ QString QApplicationPrivate::desktopStyleKey() // first valid one. if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) { const QStringList availableKeys = QStyleFactory::keys(); - foreach (const QString &style, theme->themeHint(QPlatformTheme::StyleNames).toStringList()) + const auto styles = theme->themeHint(QPlatformTheme::StyleNames).toStringList(); + for (const QString &style : styles) { if (availableKeys.contains(style, Qt::CaseInsensitive)) return style; + } } return QString(); } @@ -2225,10 +2227,13 @@ QWidget *qt_tlw_for_window(QWindow *wnd) else break; } - if (wnd) - foreach (QWidget *tlw, qApp->topLevelWidgets()) + if (wnd) { + const auto tlws = qApp->topLevelWidgets(); + for (QWidget *tlw : tlws) { if (tlw->windowHandle() == wnd) return tlw; + } + } return 0; } @@ -3942,7 +3947,8 @@ void QApplication::alert(QWidget *widget, int duration) if (QWindow *window= QApplicationPrivate::windowForWidget(widget)) window->alert(duration); } else { - foreach (QWidget *topLevel, topLevelWidgets()) + const auto topLevels = topLevelWidgets(); + for (QWidget *topLevel : topLevels) QApplication::alert(topLevel, duration); } } diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp index 4c85be33f5..9a3e9291bf 100644 --- a/src/widgets/kernel/qgesturemanager.cpp +++ b/src/widgets/kernel/qgesturemanager.cpp @@ -219,7 +219,8 @@ QGesture *QGestureManager::getState(QObject *object, QGestureRecognizer *recogni } // check if the QGesture for this recognizer has already been created - foreach (QGesture *state, m_objectGestures.value(QGestureManager::ObjectGesture(object, type))) { + const auto states = m_objectGestures.value(QGestureManager::ObjectGesture(object, type)); + for (QGesture *state : states) { if (m_gestureToRecognizer.value(state) == recognizer) return state; } @@ -684,7 +685,8 @@ void QGestureManager::deliverEvents(const QSet &gestures, QApplication::sendEvent(receiver, &event); bool eventAccepted = event.isAccepted(); - foreach(QGesture *gesture, event.gestures()) { + const auto eventGestures = event.gestures(); + for (QGesture *gesture : eventGestures) { if (eventAccepted || event.isAccepted(gesture)) { QWidget *w = event.m_targetWidgets.value(gesture->gestureType(), 0); Q_ASSERT(w); @@ -710,7 +712,8 @@ void QGestureManager::deliverEvents(const QSet &gestures, QGestureEvent event(it.value()); QApplication::sendEvent(it.key(), &event); bool eventAccepted = event.isAccepted(); - foreach (QGesture *gesture, event.gestures()) { + const auto eventGestures = event.gestures(); + for (QGesture *gesture : eventGestures) { if (gesture->state() == Qt::GestureStarted && (eventAccepted || event.isAccepted(gesture))) { QWidget *w = event.m_targetWidgets.value(gesture->gestureType(), 0); diff --git a/src/widgets/kernel/qwhatsthis.cpp b/src/widgets/kernel/qwhatsthis.cpp index b69ca54159..66b622911a 100644 --- a/src/widgets/kernel/qwhatsthis.cpp +++ b/src/widgets/kernel/qwhatsthis.cpp @@ -375,11 +375,9 @@ class QWhatsThisPrivate : public QObject void QWhatsThisPrivate::notifyToplevels(QEvent *e) { - QWidgetList toplevels = QApplication::topLevelWidgets(); - for (int i = 0; i < toplevels.count(); ++i) { - QWidget *w = toplevels.at(i); + const QWidgetList toplevels = QApplication::topLevelWidgets(); + for (auto *w : toplevels) QApplication::sendEvent(w, e); - } } QWhatsThisPrivate *QWhatsThisPrivate::instance = 0; diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index de832d667d..ec5a68eeef 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -1417,7 +1417,8 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO win = topData()->window; } - foreach (const QByteArray &propertyName, q->dynamicPropertyNames()) { + const auto dynamicPropertyNames = q->dynamicPropertyNames(); + for (const QByteArray &propertyName : dynamicPropertyNames) { if (!qstrncmp(propertyName, "_q_platform_", 12)) win->setProperty(propertyName, q->property(propertyName)); } @@ -11984,7 +11985,9 @@ QWidget *QWidgetPrivate::widgetInNavigationDirection(Direction direction) QWidget *targetWidget = 0; int shortestDistance = INT_MAX; - foreach(QWidget *targetCandidate, QApplication::allWidgets()) { + + const auto targetCandidates = QApplication::allWidgets(); + for (QWidget *targetCandidate : targetCandidates) { const QRect targetCandidateRect = targetCandidate->rect().translated(targetCandidate->mapToGlobal(QPoint())); diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp index cda7dff509..c33e4167c1 100644 --- a/src/widgets/styles/qwindowsxpstyle.cpp +++ b/src/widgets/styles/qwindowsxpstyle.cpp @@ -406,10 +406,12 @@ HWND QWindowsXPStylePrivate::winId(const QWidget *widget) return hwnd; // Find top level with native window (there might be dialogs that do not have one). - foreach (const QWidget *toplevel, QApplication::topLevelWidgets()) + const auto topLevels = QApplication::topLevelWidgets(); + for (const QWidget *toplevel : topLevels) { if (toplevel->windowHandle() && toplevel->windowHandle()->handle()) if (const HWND topLevelHwnd = QApplicationPrivate::getHWNDForWidget(toplevel)) return topLevelHwnd; + } if (QDesktopWidget *desktop = qApp->desktop()) if (const HWND desktopHwnd = QApplicationPrivate::getHWNDForWidget(desktop)) diff --git a/src/widgets/util/qflickgesture.cpp b/src/widgets/util/qflickgesture.cpp index 3d1971db8e..933db1711b 100644 --- a/src/widgets/util/qflickgesture.cpp +++ b/src/widgets/util/qflickgesture.cpp @@ -581,7 +581,8 @@ QGestureRecognizer::Result QFlickGestureRecognizer::recognize(QGesture *state, // Check for an active scroller at globalPos if (inputType == QScroller::InputPress) { - foreach (QScroller *as, QScroller::activeScrollers()) { + const auto activeScrollers = QScroller::activeScrollers(); + for (QScroller *as : activeScrollers) { if (as != scroller) { QRegion scrollerRegion; @@ -589,11 +590,13 @@ QGestureRecognizer::Result QFlickGestureRecognizer::recognize(QGesture *state, scrollerRegion = QRect(w->mapToGlobal(QPoint(0, 0)), w->size()); #ifndef QT_NO_GRAPHICSVIEW } else if (QGraphicsObject *go = qobject_cast(as->target())) { - if (go->scene()) { + if (const auto *scene = go->scene()) { const auto goBoundingRectMappedToScene = go->mapToScene(go->boundingRect()); - foreach (QGraphicsView *gv, go->scene()->views()) + const auto views = scene->views(); + for (QGraphicsView *gv : views) { scrollerRegion |= gv->mapFromScene(goBoundingRectMappedToScene) .translated(gv->mapToGlobal(QPoint(0, 0))); + } } #endif } diff --git a/src/widgets/widgets/qdialogbuttonbox.cpp b/src/widgets/widgets/qdialogbuttonbox.cpp index 6fc8cb5e26..2b68c308ec 100644 --- a/src/widgets/widgets/qdialogbuttonbox.cpp +++ b/src/widgets/widgets/qdialogbuttonbox.cpp @@ -964,7 +964,8 @@ bool QDialogButtonBox::event(QEvent *event) break; } - foreach (QPushButton *pb, (dialog ? dialog : this)->findChildren()) { + const auto pbs = (dialog ? dialog : this)->findChildren(); + for (QPushButton *pb : pbs) { if (pb->isDefault() && pb != firstAcceptButton) { hasDefault = true; break; diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index c07d48a513..1b9e31968a 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -1270,14 +1270,17 @@ void QMenuPrivate::_q_platformMenuAboutToShow() Q_Q(QMenu); #ifdef Q_OS_OSX - if (platformMenu) - Q_FOREACH (QAction *action, q->actions()) + if (platformMenu) { + const auto actions = q->actions(); + for (QAction *action : actions) { if (QWidget *widget = widgetItems.value(action)) if (widget->parent() == q) { QPlatformMenuItem *menuItem = platformMenu->menuItemForTag(reinterpret_cast(action)); moveWidgetToPlatformItem(widget, menuItem); platformMenu->syncMenuItem(menuItem); } + } + } #endif emit q->aboutToShow(); From a7885c9756d423042bd0670d82d78d8dffe9be54 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 16 Feb 2016 15:24:38 +0100 Subject: [PATCH 34/38] QVector: preserve capacity in clear() This is what std::vector implementations usually do, because it minimizes memory fragmentation and useless allocations since no user will call clear() unless she intends to append new data afterwards. Fix calls to resize(0) that show how existing code tried to work around the issue. Adjust test. Port from QVERIFY(==) to QCOMPARE as a drive-by. [ChangeLog][QtCore][QVector] clear() now preserves capacity. To shed capacity, call squeeze() or swap with a default-constructed QVector object, see the documentation for an example. Change-Id: I9cebe611a97e027a89e821e64408a4741b31f1f6 Reviewed-by: Lars Knoll --- src/corelib/kernel/qeventdispatcher_unix.cpp | 4 ++-- src/corelib/tools/qregexp.cpp | 2 +- src/corelib/tools/qvector.cpp | 15 +++++++++++++-- src/corelib/tools/qvector.h | 2 +- src/corelib/xml/qxmlstream_p.h | 6 ++---- src/gui/kernel/qshortcutmap.cpp | 4 ++-- src/gui/text/qcssparser.cpp | 2 +- src/gui/text/qtextdocument_p.cpp | 2 +- src/widgets/widgets/qmdiarea.cpp | 2 +- src/widgets/widgets/qmenubar.cpp | 2 +- src/widgets/widgets/qtextbrowser.cpp | 2 +- tests/auto/corelib/tools/qvector/tst_qvector.cpp | 9 +++++---- 12 files changed, 31 insertions(+), 21 deletions(-) diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp index 64b813bb13..9afbb84abf 100644 --- a/src/corelib/kernel/qeventdispatcher_unix.cpp +++ b/src/corelib/kernel/qeventdispatcher_unix.cpp @@ -286,7 +286,7 @@ void QEventDispatcherUNIXPrivate::markPendingSocketNotifiers() } } - pollfds.resize(0); + pollfds.clear(); } int QEventDispatcherUNIXPrivate::activateSocketNotifiers() @@ -480,8 +480,8 @@ bool QEventDispatcherUNIX::processEvents(QEventLoop::ProcessEventsFlags flags) if (!canWait || (include_timers && d->timerList.timerWait(wait_tm))) tm = &wait_tm; + d->pollfds.clear(); d->pollfds.reserve(1 + (include_notifiers ? d->socketNotifiers.size() : 0)); - d->pollfds.resize(0); if (include_notifiers) for (auto it = d->socketNotifiers.cbegin(); it != d->socketNotifiers.cend(); ++it) diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp index fd67193302..f8f3347786 100644 --- a/src/corelib/tools/qregexp.cpp +++ b/src/corelib/tools/qregexp.cpp @@ -2335,7 +2335,7 @@ QRegExpCharClass::QRegExpCharClass() void QRegExpCharClass::clear() { c = 0; - r.resize(0); + r.clear(); n = false; } diff --git a/src/corelib/tools/qvector.cpp b/src/corelib/tools/qvector.cpp index b3247b8af5..ef1c9c17b0 100644 --- a/src/corelib/tools/qvector.cpp +++ b/src/corelib/tools/qvector.cpp @@ -502,8 +502,19 @@ /*! \fn void QVector::clear() - Removes all the elements from the vector and releases the memory used by - the vector. + Removes all the elements from the vector. + + \note Until Qt 5.6, this also released the memory used by + the vector. From Qt 5.7, the capacity is preserved. To shed + all capacity, swap with a default-constructed vector: + \code + QVector v ...; + QVector().swap(v); + Q_ASSERT(v.capacity() == 0); + \endcode + or call squeeze(). + + \sa squeeze() */ /*! \fn const T &QVector::at(int i) const diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index d60be78ade..13ae121450 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -419,7 +419,7 @@ void QVector::resize(int asize) } template inline void QVector::clear() -{ *this = QVector(); } +{ resize(0); } template inline const T &QVector::at(int i) const { Q_ASSERT_X(i >= 0 && i < d->size, "QVector::at", "index out of range"); diff --git a/src/corelib/xml/qxmlstream_p.h b/src/corelib/xml/qxmlstream_p.h index 4c6c206bf3..ab0bbba413 100644 --- a/src/corelib/xml/qxmlstream_p.h +++ b/src/corelib/xml/qxmlstream_p.h @@ -1020,10 +1020,8 @@ bool QXmlStreamReaderPrivate::parse() prefix.clear(); qualifiedName.clear(); namespaceUri.clear(); - if (publicNamespaceDeclarations.size()) - publicNamespaceDeclarations.clear(); - if (attributes.size()) - attributes.resize(0); + publicNamespaceDeclarations.clear(); + attributes.clear(); if (isEmptyElement) { setType(QXmlStreamReader::EndElement); Tag &tag = tagStack_pop(); diff --git a/src/gui/kernel/qshortcutmap.cpp b/src/gui/kernel/qshortcutmap.cpp index 5eb216d58e..3b40aba49e 100644 --- a/src/gui/kernel/qshortcutmap.cpp +++ b/src/gui/kernel/qshortcutmap.cpp @@ -375,7 +375,7 @@ QKeySequence::SequenceMatch QShortcutMap::nextState(QKeyEvent *e) QKeySequence::SequenceMatch result = QKeySequence::NoMatch; // We start fresh each time.. - d->identicals.resize(0); + d->identicals.clear(); result = find(e); if (result == QKeySequence::NoMatch && (e->modifiers() & Qt::KeypadModifier)) { @@ -448,7 +448,7 @@ QKeySequence::SequenceMatch QShortcutMap::find(QKeyEvent *e, int ignoredModifier } // Looking for new identicals, scrap old - d->identicals.resize(0); + d->identicals.clear(); bool partialFound = false; bool identicalDisabledFound = false; diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp index fceb11959a..b9e05e726e 100644 --- a/src/gui/text/qcssparser.cpp +++ b/src/gui/text/qcssparser.cpp @@ -2166,7 +2166,7 @@ void Parser::init(const QString &css, bool isFile) } hasEscapeSequences = false; - symbols.resize(0); + symbols.clear(); symbols.reserve(8); Scanner::scan(Scanner::preprocess(styleSheet, &hasEscapeSequences), &symbols); index = 0; diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp index 348fa83756..93071aaf59 100644 --- a/src/gui/text/qtextdocument_p.cpp +++ b/src/gui/text/qtextdocument_p.cpp @@ -1128,7 +1128,7 @@ void QTextDocumentPrivate::clearUndoRedoStacks(QTextDocument::Stacks stacksToCle delete c.custom; } undoState = 0; - undoStack.resize(0); + undoStack.clear(); if (emitSignals && undoCommandsAvailable) emitUndoAvailable(false); if (emitSignals && redoCommandsAvailable) diff --git a/src/widgets/widgets/qmdiarea.cpp b/src/widgets/widgets/qmdiarea.cpp index 2b734b603f..b42ebe7e48 100644 --- a/src/widgets/widgets/qmdiarea.cpp +++ b/src/widgets/widgets/qmdiarea.cpp @@ -516,7 +516,7 @@ QVector MinOverlapPlacer::findMaxOverlappers(const QRect &domain, const Q if (overlap >= maxOverlap || maxOverlap == -1) { if (overlap > maxOverlap) { maxOverlap = overlap; - result.resize(0); + result.clear(); } result << srcRect; } diff --git a/src/widgets/widgets/qmenubar.cpp b/src/widgets/widgets/qmenubar.cpp index f15ce06e23..261ff0bca3 100644 --- a/src/widgets/widgets/qmenubar.cpp +++ b/src/widgets/widgets/qmenubar.cpp @@ -200,7 +200,7 @@ void QMenuBarPrivate::updateGeometries() if(itemsDirty) { for(int j = 0; j < shortcutIndexMap.size(); ++j) q->releaseShortcut(shortcutIndexMap.value(j)); - shortcutIndexMap.resize(0); // faster than clear + shortcutIndexMap.clear(); const int actionsCount = actions.count(); shortcutIndexMap.reserve(actionsCount); for (int i = 0; i < actionsCount; i++) diff --git a/src/widgets/widgets/qtextbrowser.cpp b/src/widgets/widgets/qtextbrowser.cpp index d8a7b27d60..db66d39089 100644 --- a/src/widgets/widgets/qtextbrowser.cpp +++ b/src/widgets/widgets/qtextbrowser.cpp @@ -1141,7 +1141,7 @@ void QTextBrowser::clearHistory() d->forwardStack.clear(); if (!d->stack.isEmpty()) { QTextBrowserPrivate::HistoryEntry historyEntry = d->stack.top(); - d->stack.resize(0); + d->stack.clear(); d->stack.push(historyEntry); d->home = historyEntry.url; } diff --git a/tests/auto/corelib/tools/qvector/tst_qvector.cpp b/tests/auto/corelib/tools/qvector/tst_qvector.cpp index 8fad672f42..eb37d6b8e6 100644 --- a/tests/auto/corelib/tools/qvector/tst_qvector.cpp +++ b/tests/auto/corelib/tools/qvector/tst_qvector.cpp @@ -734,10 +734,11 @@ void tst_QVector::clear() const QVector myvec; myvec << SimpleValue::at(0) << SimpleValue::at(1) << SimpleValue::at(2); - QVERIFY(myvec.size() == 3); + const auto oldCapacity = myvec.capacity(); + QCOMPARE(myvec.size(), 3); myvec.clear(); - QVERIFY(myvec.size() == 0); - QVERIFY(myvec.capacity() == 0); + QCOMPARE(myvec.size(), 0); + QCOMPARE(myvec.capacity(), oldCapacity); } void tst_QVector::clearInt() const @@ -1945,7 +1946,7 @@ void tst_QVector::resizePOD() const const int capacity = vector.capacity(); - vector.resize(0); + vector.clear(); QCOMPARE(vector.size(), 0); QVERIFY(vector.capacity() <= capacity); } From be84480785b9686dc09937fa33b685de7cc570f1 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 25 Jan 2016 12:23:56 +0100 Subject: [PATCH 35/38] QtTest: eradicate all Q_FOREACH loops ... by replacing them with C++11 ramge-for loops. In one case, I took the liberty to remove a useless if(isEmpty()) check around a for loop. Now that we don't use Q_FOREACH anymore, we don't incur the copy for empty containers anymore. Left the indention of the loop level to avoid code churn. Saves 1.8KiB in text size on optimized GCC 5.3 Linux AMD64 builds. Change-Id: I1b1fb34847f6a631f0d580fd5261c7f5fed8475c Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/testlib/qbenchmarkvalgrind.cpp | 8 ++++---- src/testlib/qtestaccessible.h | 4 ++-- src/testlib/qtestcase.cpp | 4 +--- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/testlib/qbenchmarkvalgrind.cpp b/src/testlib/qbenchmarkvalgrind.cpp index af500722c6..1de149258d 100644 --- a/src/testlib/qbenchmarkvalgrind.cpp +++ b/src/testlib/qbenchmarkvalgrind.cpp @@ -115,13 +115,13 @@ QString QBenchmarkValgrindUtils::getNewestFileName() Q_ASSERT(!base.isEmpty()); nameFilters << QString::fromLatin1("%1.*").arg(base); - QFileInfoList fiList = QDir().entryInfoList(nameFilters, QDir::Files | QDir::Readable); + const QFileInfoList fiList = QDir().entryInfoList(nameFilters, QDir::Files | QDir::Readable); Q_ASSERT(!fiList.empty()); int hiSuffix = -1; QFileInfo lastFileInfo; const QString pattern = QString::fromLatin1("%1.(\\d+)").arg(base); QRegExp rx(pattern); - foreach (const QFileInfo &fileInfo, fiList) { + for (const QFileInfo &fileInfo : fiList) { const int index = rx.indexIn(fileInfo.fileName()); Q_ASSERT(index == 0); Q_UNUSED(index); @@ -151,8 +151,8 @@ void QBenchmarkValgrindUtils::cleanup() nameFilters << base // overall summary << QString::fromLatin1("%1.*").arg(base); // individual dumps - QFileInfoList fiList = QDir().entryInfoList(nameFilters, QDir::Files | QDir::Readable); - foreach (const QFileInfo &fileInfo, fiList) { + const QFileInfoList fiList = QDir().entryInfoList(nameFilters, QDir::Files | QDir::Readable); + for (const QFileInfo &fileInfo : fiList) { const bool removeOk = QFile::remove(fileInfo.fileName()); Q_ASSERT(removeOk); Q_UNUSED(removeOk); diff --git a/src/testlib/qtestaccessible.h b/src/testlib/qtestaccessible.h index b6d8d6028c..c4c79b7deb 100644 --- a/src/testlib/qtestaccessible.h +++ b/src/testlib/qtestaccessible.h @@ -151,7 +151,7 @@ public: return res; } static bool containsEvent(QAccessibleEvent *event) { - Q_FOREACH (const QAccessibleEvent *ev, eventList()) { + for (const QAccessibleEvent *ev : qAsConst(eventList())) { if (*ev == *event) return true; } @@ -285,7 +285,7 @@ private: QDebug str = QDebug(&rc).nospace(); str << "Event " << *needle << " not found at head of event list of size " << haystack.size() << " :"; - Q_FOREACH (const QAccessibleEvent *e, haystack) + for (const QAccessibleEvent *e : haystack) str << ' ' << *e; return rc; } diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index 4720c0564e..d5b4ae218f 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -1694,8 +1694,7 @@ int QTest::qExec(QObject *testObject, int argc, char **argv) handler.reset(new FatalSignalHandler); #endif TestMethods::MetaMethods commandLineMethods; - if (!QTest::testFunctions.isEmpty()) { - foreach (const QString &tf, QTest::testFunctions) { + for (const QString &tf : qAsConst(QTest::testFunctions)) { const QByteArray tfB = tf.toLatin1(); const QByteArray signature = tfB + QByteArrayLiteral("()"); QMetaMethod m = TestMethods::findMethod(testObject, signature.constData()); @@ -1706,7 +1705,6 @@ int QTest::qExec(QObject *testObject, int argc, char **argv) exit(1); } commandLineMethods.push_back(m); - } } TestMethods test(testObject, commandLineMethods); test.invokeTests(testObject); From f253f4c3310655933266f62e90f46fd12b5c49e4 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Wed, 10 Feb 2016 11:30:33 -0800 Subject: [PATCH 36/38] Track target widget when wheel events are received This issue is reproducible on OS X when using a Magic Mouse or a combination of Magic Trackpad and regular mouse. In these cases it's possible to start a scrolling gesture on one widget and move the mouse cursor over another widget. Although we send the wheel event phase information, we never made any use of it. This means that a widget would start scrolling even though it never received a ScrollBegin event. In this patch, we make sure the scrolling cycle is respected and that once a widget starts scrolling, it'll be recieving all the wheel events until a ScrollEnd event reaches the application. For those input devices not supporting a proper phase cycle, we introduce a new (undocumented) phase value, NoScrollPhase. If the wheel event phase is NoScrollPhase, then we ignore the current scroll widget and proceed as usual. This value is the default for wheel events. It's up to the platform plugin to set the proper phase value according to the data received from the OS. Finally, we fix a few of QWheelEvent constructors to properly initialize the phase and source properties. Task-number: QTBUG-50199 Change-Id: I3773729a9c757e2d2fcc5100dcd79f0ed26cb808 Reviewed-by: Shawn Rutledge --- src/corelib/global/qnamespace.h | 3 +- src/corelib/global/qnamespace.qdoc | 2 + src/gui/kernel/qevent.cpp | 6 +- src/gui/kernel/qevent.h | 2 + src/gui/kernel/qwindowsysteminterface.h | 12 +++- src/gui/kernel/qwindowsysteminterface_p.h | 2 +- src/plugins/platforms/cocoa/qnsview.mm | 2 + src/widgets/kernel/qapplication.cpp | 68 +++++++++++++++++------ src/widgets/kernel/qapplication_p.h | 1 + 9 files changed, 74 insertions(+), 24 deletions(-) diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index c4f5415a01..4d0bd6903d 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -1626,7 +1626,8 @@ public: }; enum ScrollPhase { - ScrollBegin = 1, + NoScrollPhase = 0, // Make public in 5.7 or asap + ScrollBegin, ScrollUpdate, ScrollEnd }; diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index 7c5263ddbd..527bded3c2 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -3070,6 +3070,8 @@ This enum describes the phase of scrolling. + \omitvalue NoScrollPhase The input device doesn't support scroll phase. + \value ScrollBegin Scrolling is about to begin, but the scrolling distance did not yet change. diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 4f368e1db3..8abec2b05e 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -727,7 +727,7 @@ QWheelEvent::QWheelEvent(const QPointF &pos, int delta, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::Orientation orient) : QInputEvent(Wheel, modifiers), p(pos), qt4D(delta), qt4O(orient), mouseState(buttons), - ph(Qt::ScrollUpdate), src(Qt::MouseEventNotSynthesized) + ph(Qt::NoScrollPhase), src(Qt::MouseEventNotSynthesized) { g = QCursor::pos(); if (orient == Qt::Vertical) @@ -762,7 +762,7 @@ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, int delta Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::Orientation orient) : QInputEvent(Wheel, modifiers), p(pos), g(globalPos), qt4D(delta), qt4O(orient), mouseState(buttons), - ph(Qt::ScrollUpdate), src(Qt::MouseEventNotSynthesized) + ph(Qt::NoScrollPhase), src(Qt::MouseEventNotSynthesized) { if (orient == Qt::Vertical) angleD = QPoint(0, delta); @@ -798,7 +798,7 @@ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, QPoint pixelDelta, QPoint angleDelta, int qt4Delta, Qt::Orientation qt4Orientation, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers) : QInputEvent(Wheel, modifiers), p(pos), g(globalPos), pixelD(pixelDelta), - angleD(angleDelta), qt4D(qt4Delta), qt4O(qt4Orientation), mouseState(buttons), ph(Qt::ScrollUpdate), + angleD(angleDelta), qt4D(qt4Delta), qt4O(qt4Orientation), mouseState(buttons), ph(Qt::NoScrollPhase), src(Qt::MouseEventNotSynthesized) {} diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index ed2deda9a0..b407663338 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -219,6 +219,8 @@ protected: uint ph : 2; uint src: 2; int reserved : 28; + + friend class QApplication; }; #endif diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h index a27c68649e..20d560f82e 100644 --- a/src/gui/kernel/qwindowsysteminterface.h +++ b/src/gui/kernel/qwindowsysteminterface.h @@ -94,8 +94,16 @@ public: quint32 nativeModifiers, const QString& text = QString(), bool autorep = false, ushort count = 1, bool tryShortcutOverride = true); - static void handleWheelEvent(QWindow *w, const QPointF & local, const QPointF & global, QPoint pixelDelta, QPoint angleDelta, Qt::KeyboardModifiers mods = Qt::NoModifier, Qt::ScrollPhase phase = Qt::ScrollUpdate, Qt::MouseEventSource source = Qt::MouseEventNotSynthesized); - static void handleWheelEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, QPoint pixelDelta, QPoint angleDelta, Qt::KeyboardModifiers mods = Qt::NoModifier, Qt::ScrollPhase phase = Qt::ScrollUpdate, Qt::MouseEventSource source = Qt::MouseEventNotSynthesized); + static void handleWheelEvent(QWindow *w, const QPointF & local, const QPointF & global, + QPoint pixelDelta, QPoint angleDelta, + Qt::KeyboardModifiers mods = Qt::NoModifier, + Qt::ScrollPhase phase = Qt::NoScrollPhase, + Qt::MouseEventSource source = Qt::MouseEventNotSynthesized); + static void handleWheelEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, + QPoint pixelDelta, QPoint angleDelta, + Qt::KeyboardModifiers mods = Qt::NoModifier, + Qt::ScrollPhase phase = Qt::NoScrollPhase, + Qt::MouseEventSource source = Qt::MouseEventNotSynthesized); // Wheel event compatibility functions. Will be removed: do not use. static void handleWheelEvent(QWindow *w, const QPointF & local, const QPointF & global, int d, Qt::Orientation o, Qt::KeyboardModifiers mods = Qt::NoModifier); diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h index e48d1e965b..c2569f29cd 100644 --- a/src/gui/kernel/qwindowsysteminterface_p.h +++ b/src/gui/kernel/qwindowsysteminterface_p.h @@ -236,7 +236,7 @@ public: class WheelEvent : public InputEvent { public: WheelEvent(QWindow *w, ulong time, const QPointF & local, const QPointF & global, QPoint pixelD, QPoint angleD, int qt4D, Qt::Orientation qt4O, - Qt::KeyboardModifiers mods, Qt::ScrollPhase phase = Qt::ScrollUpdate, Qt::MouseEventSource src = Qt::MouseEventNotSynthesized) + Qt::KeyboardModifiers mods, Qt::ScrollPhase phase = Qt::NoScrollPhase, Qt::MouseEventSource src = Qt::MouseEventNotSynthesized) : InputEvent(w, time, Wheel, mods), pixelDelta(pixelD), angleDelta(angleD), qt4Delta(qt4D), qt4Orientation(qt4O), localPos(local), globalPos(global), phase(phase), source(src) { } QPoint pixelDelta; QPoint angleDelta; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 0d80333e65..05dcbd33ad 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -1405,6 +1405,8 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) momentumPhase == NSEventPhaseEnded || momentumPhase == NSEventPhaseCancelled) { ph = Qt::ScrollEnd; m_scrolling = false; + } else if (phase == NSEventPhaseNone && momentumPhase == NSEventPhaseNone) { + ph = Qt::NoScrollPhase; } QWindowSystemInterface::handleWheelEvent(m_window, qt_timestamp, qt_windowPoint, qt_screenPoint, pixelDelta, angleDelta, currentWheelModifiers, ph, source); diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 3ab477ccfb..7c5a0da0c1 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -417,6 +417,7 @@ QWidget *QApplicationPrivate::hidden_focus_widget = 0; // will get keyboard inpu QWidget *QApplicationPrivate::active_window = 0; // toplevel with keyboard focus #ifndef QT_NO_WHEELEVENT int QApplicationPrivate::wheel_scroll_lines; // number of lines to scroll +QWidget *QApplicationPrivate::wheel_widget = Q_NULLPTR; #endif bool qt_in_tab_key_event = false; int qt_antialiasing_threshold = -1; @@ -3309,7 +3310,6 @@ bool QApplication::notify(QObject *receiver, QEvent *e) case QEvent::Wheel: { QWidget* w = static_cast(receiver); - QWheelEvent* wheel = static_cast(e); // QTBUG-40656, QTBUG-42731: ignore wheel events when a popup (QComboBox) is open. if (const QWidget *popup = QApplication::activePopupWidget()) { @@ -3317,27 +3317,61 @@ bool QApplication::notify(QObject *receiver, QEvent *e) return true; } - QPoint relpos = wheel->pos(); - bool eventAccepted = wheel->isAccepted(); + QWheelEvent* wheel = static_cast(e); + const bool spontaneous = wheel->spontaneous(); + const Qt::ScrollPhase phase = wheel->phase(); - if (e->spontaneous() && wheel->phase() == Qt::ScrollUpdate) - QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, e, relpos); + if (phase == Qt::NoScrollPhase || phase == Qt::ScrollBegin + || (phase == Qt::ScrollUpdate && !QApplicationPrivate::wheel_widget)) { + + if (spontaneous && phase == Qt::ScrollBegin) + QApplicationPrivate::wheel_widget = Q_NULLPTR; + + const QPoint &relpos = wheel->pos(); + + if (spontaneous && (phase == Qt::NoScrollPhase || phase == Qt::ScrollUpdate)) + QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, e, relpos); - while (w) { QWheelEvent we(relpos, wheel->globalPos(), wheel->pixelDelta(), wheel->angleDelta(), wheel->delta(), wheel->orientation(), wheel->buttons(), - wheel->modifiers(), wheel->phase(), wheel->source()); - we.spont = wheel->spontaneous(); - res = d->notify_helper(w, w == receiver ? wheel : &we); - eventAccepted = ((w == receiver) ? wheel : &we)->isAccepted(); - e->spont = false; - if ((res && eventAccepted) - || w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation)) - break; + wheel->modifiers(), phase, wheel->source()); + bool eventAccepted; + while (w) { + we.spont = spontaneous && w == receiver; + we.ignore(); + res = d->notify_helper(w, &we); + eventAccepted = we.isAccepted(); + if (res && eventAccepted) { + if (spontaneous && phase != Qt::NoScrollPhase) + QApplicationPrivate::wheel_widget = w; + break; + } + if (w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation)) + break; - relpos += w->pos(); - w = w->parentWidget(); + we.p += w->pos(); + w = w->parentWidget(); + } + wheel->setAccepted(eventAccepted); + } else if (QApplicationPrivate::wheel_widget) { + if (!spontaneous) { + // wheel_widget may forward the wheel event to a delegate widget, + // either directly or indirectly (e.g. QAbstractScrollArea will + // forward to its QScrollBars through viewportEvent()). In that + // case, the event will not be spontaneous but synthesized, so + // we can send it straigth to the receiver. + d->notify_helper(w, wheel); + } else { + const QPoint &relpos = QApplicationPrivate::wheel_widget->mapFromGlobal(wheel->globalPos()); + QWheelEvent we(relpos, wheel->globalPos(), wheel->pixelDelta(), wheel->angleDelta(), wheel->delta(), wheel->orientation(), wheel->buttons(), + wheel->modifiers(), wheel->phase(), wheel->source()); + we.spont = true; + we.ignore(); + d->notify_helper(QApplicationPrivate::wheel_widget, &we); + wheel->setAccepted(we.isAccepted()); + if (phase == Qt::ScrollEnd) + QApplicationPrivate::wheel_widget = Q_NULLPTR; + } } - wheel->setAccepted(eventAccepted); } break; #endif diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h index 75d86a5eba..4cce2d84e8 100644 --- a/src/widgets/kernel/qapplication_p.h +++ b/src/widgets/kernel/qapplication_p.h @@ -202,6 +202,7 @@ public: static QWidget *active_window; #ifndef QT_NO_WHEELEVENT static int wheel_scroll_lines; + static QWidget *wheel_widget; #endif static int enabledAnimations; // Combination of QPlatformTheme::UiEffect From 31a880f1f37412abf930bb7427c8538e9d09e765 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 29 Feb 2016 12:13:01 +0100 Subject: [PATCH 37/38] Remove lib/fonts symlinking from configure The fonts directory is removed in 5.7. Avoid creating a broken symlink. Change-Id: I95d1970737f54810006c084436411fc95743f72d Reviewed-by: Simon Hausmann Reviewed-by: Oswald Buddenhagen --- configure | 8 -------- 1 file changed, 8 deletions(-) diff --git a/configure b/configure index 69d0a088ef..8b508ddf44 100755 --- a/configure +++ b/configure @@ -3372,14 +3372,6 @@ if [ "$OPT_SHADOW" = "yes" ]; then mkdir -p "$outpath/mkspecs" fi -# symlink fonts to be able to run application from build directory -if [ ! -d "${outpath}/lib/fonts" ]; then - if [ "$PLATFORM" = "$XPLATFORM" ]; then - mkdir -p "${outpath}/lib" - ln -s "${relpath}/lib/fonts" "${outpath}/lib/fonts" - fi -fi - # detect build style if [ "$CFG_DEBUG" = "auto" ]; then if [ "$XPLATFORM_MAC" = "yes" -o "$XPLATFORM_MINGW" = "yes" ]; then From 1dd0c4bf1af1c90fde1449a81d41acbc62cf1934 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Fri, 26 Feb 2016 16:53:24 +0100 Subject: [PATCH 38/38] SSSE3 optimized store of 24-bit formats Using shuffle and align storing our quint24 format can be done much faster. This in particular improves conversions to RGB888. Change-Id: I179748706a33a43fd6f60f5c40287317418c8867 Reviewed-by: Gunnar Sletta --- src/gui/painting/qdrawhelper.cpp | 4 +- src/gui/painting/qdrawhelper_p.h | 2 +- src/gui/painting/qdrawhelper_ssse3.cpp | 57 +++++++++++++++++++ .../qimageconversion/tst_qimageconversion.cpp | 44 ++++++++++---- 4 files changed, 93 insertions(+), 14 deletions(-) diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 1143123717..112dbd4738 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -961,7 +961,7 @@ const FetchPixelsFunc qFetchPixels[QPixelLayout::BPPCount] = { fetchPixels // BPP32 }; -const StorePixelsFunc qStorePixels[QPixelLayout::BPPCount] = { +StorePixelsFunc qStorePixels[QPixelLayout::BPPCount] = { 0, // BPPNone storePixels, // BPP1MSB storePixels, // BPP1LSB @@ -6375,10 +6375,12 @@ static void qInitDrawhelperFunctions() int w, int h, int const_alpha); + extern void QT_FASTCALL storePixelsBPP24_ssse3(uchar *dest, const uint *src, int index, int count); qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_ssse3; qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_ssse3; qBlendFunctions[QImage::Format_RGBX8888][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32_ssse3; qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32_ssse3; + qStorePixels[QPixelLayout::BPP24] = storePixelsBPP24_ssse3; } #endif // SSSE3 diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h index af52ed0b43..21af6039f8 100644 --- a/src/gui/painting/qdrawhelper_p.h +++ b/src/gui/painting/qdrawhelper_p.h @@ -1213,7 +1213,7 @@ typedef void (QT_FASTCALL *StorePixelsFunc)(uchar *dest, const uint *src, int in extern QPixelLayout qPixelLayouts[QImage::NImageFormats]; extern const FetchPixelsFunc qFetchPixels[QPixelLayout::BPPCount]; -extern const StorePixelsFunc qStorePixels[QPixelLayout::BPPCount]; +extern StorePixelsFunc qStorePixels[QPixelLayout::BPPCount]; diff --git a/src/gui/painting/qdrawhelper_ssse3.cpp b/src/gui/painting/qdrawhelper_ssse3.cpp index 09b25d30fd..e0d1bac6b1 100644 --- a/src/gui/painting/qdrawhelper_ssse3.cpp +++ b/src/gui/painting/qdrawhelper_ssse3.cpp @@ -176,6 +176,63 @@ void qt_blend_argb32_on_argb32_ssse3(uchar *destPixels, int dbpl, } } +static inline void store_uint24_ssse3(uchar *dst, const uint *src, int len) +{ + int i = 0; + + quint24 *dst24 = reinterpret_cast(dst); + // Align dst on 16 bytes + for (; i < len && (reinterpret_cast(dst24) & 0xf); ++i) + *dst24++ = quint24(*src++); + + // Shuffle masks for first and second half of every output, all outputs are aligned so the shuffled ends are not used. + const __m128i shuffleMask1 = _mm_setr_epi8(char(0x80), char(0x80), char(0x80), char(0x80), 2, 1, 0, 6, 5, 4, 10, 9, 8, 14, 13, 12); + const __m128i shuffleMask2 = _mm_setr_epi8(2, 1, 0, 6, 5, 4, 10, 9, 8, 14, 13, 12, char(0x80), char(0x80), char(0x80), char(0x80)); + + const __m128i *inVectorPtr = (const __m128i *)src; + __m128i *dstVectorPtr = (__m128i *)dst24; + + for (; i < (len - 15); i += 16) { + // Load four vectors, store three. + // Create each output vector by combining two shuffled input vectors. + __m128i srcVector1 = _mm_loadu_si128(inVectorPtr); + ++inVectorPtr; + __m128i srcVector2 = _mm_loadu_si128(inVectorPtr); + ++inVectorPtr; + __m128i outputVector1 = _mm_shuffle_epi8(srcVector1, shuffleMask1); + __m128i outputVector2 = _mm_shuffle_epi8(srcVector2, shuffleMask2); + __m128i outputVector = _mm_alignr_epi8(outputVector2, outputVector1, 4); + _mm_store_si128(dstVectorPtr, outputVector); + ++dstVectorPtr; + + srcVector1 = _mm_loadu_si128(inVectorPtr); + ++inVectorPtr; + outputVector1 = _mm_shuffle_epi8(srcVector2, shuffleMask1); + outputVector2 = _mm_shuffle_epi8(srcVector1, shuffleMask2); + outputVector = _mm_alignr_epi8(outputVector2, outputVector1, 8); + _mm_store_si128(dstVectorPtr, outputVector); + ++dstVectorPtr; + + srcVector2 = _mm_loadu_si128(inVectorPtr); + ++inVectorPtr; + outputVector1 = _mm_shuffle_epi8(srcVector1, shuffleMask1); + outputVector2 = _mm_shuffle_epi8(srcVector2, shuffleMask2); + outputVector = _mm_alignr_epi8(outputVector2, outputVector1, 12); + _mm_store_si128(dstVectorPtr, outputVector); + ++dstVectorPtr; + } + dst24 = reinterpret_cast(dstVectorPtr); + src = reinterpret_cast(inVectorPtr); + + for (; i < len; ++i) + *dst24++ = quint24(*src++); +} + +void QT_FASTCALL storePixelsBPP24_ssse3(uchar *dest, const uint *src, int index, int count) +{ + store_uint24_ssse3(dest + index * 3, src, count); +} + QT_END_NAMESPACE #endif // QT_COMPILER_SUPPORTS_SSSE3 diff --git a/tests/benchmarks/gui/image/qimageconversion/tst_qimageconversion.cpp b/tests/benchmarks/gui/image/qimageconversion/tst_qimageconversion.cpp index f631688870..31c5520b55 100644 --- a/tests/benchmarks/gui/image/qimageconversion/tst_qimageconversion.cpp +++ b/tests/benchmarks/gui/image/qimageconversion/tst_qimageconversion.cpp @@ -90,10 +90,8 @@ void tst_QImageConversion::convertRgb888ToRgb32() QFETCH(QImage, inputImage); QBENCHMARK { - volatile QImage output = inputImage.convertToFormat(QImage::Format_RGB32); - // we need the volatile and the following to make sure the compiler does not do - // anything stupid :) - (void)output; + QImage output = inputImage.convertToFormat(QImage::Format_RGB32); + output.constBits(); } } @@ -107,10 +105,8 @@ void tst_QImageConversion::convertRgb888ToRgbx8888() QFETCH(QImage, inputImage); QBENCHMARK { - volatile QImage output = inputImage.convertToFormat(QImage::Format_RGBX8888); - // we need the volatile and the following to make sure the compiler does not do - // anything stupid :) - (void)output; + QImage output = inputImage.convertToFormat(QImage::Format_RGBX8888); + output.constBits(); } } @@ -140,10 +136,8 @@ void tst_QImageConversion::convertRgb32ToRgb888() QFETCH(QImage, inputImage); QBENCHMARK { - volatile QImage output = inputImage.convertToFormat(QImage::Format_RGB888); - // we need the volatile and the following to make sure the compiler does not do - // anything stupid :) - (void)output; + QImage output = inputImage.convertToFormat(QImage::Format_RGB888); + output.constBits(); } } @@ -157,6 +151,8 @@ void tst_QImageConversion::convertRgb16_data() QTest::newRow("rgb888") << rgb16 << QImage::Format_RGB888; QTest::newRow("rgb666") << rgb16 << QImage::Format_RGB666; QTest::newRow("rgb555") << rgb16 << QImage::Format_RGB555; + QTest::newRow("argb8565") << rgb16 << QImage::Format_ARGB8565_Premultiplied; + QTest::newRow("argb8555") << rgb16 << QImage::Format_ARGB8555_Premultiplied; } void tst_QImageConversion::convertRgb16() @@ -189,6 +185,7 @@ void tst_QImageConversion::convertRgb32_data() QTest::newRow("rgb32 -> rgb888") << rgb32 << QImage::Format_RGB888; QTest::newRow("rgb32 -> rgb666") << rgb32 << QImage::Format_RGB666; QTest::newRow("rgb32 -> rgb555") << rgb32 << QImage::Format_RGB555; + QTest::newRow("rgb32 -> argb8565pm") << rgb32 << QImage::Format_ARGB8565_Premultiplied; QTest::newRow("argb32 -> rgb16") << argb32 << QImage::Format_RGB16; QTest::newRow("argb32 -> rgb32") << argb32 << QImage::Format_RGB32; @@ -237,12 +234,14 @@ void tst_QImageConversion::convertGeneric_data() QImage rgba32 = argb32.convertToFormat(QImage::Format_RGBA8888); QImage bgr30 = rgb32.convertToFormat(QImage::Format_BGR30); QImage a2rgb30 = argb32.convertToFormat(QImage::Format_A2RGB30_Premultiplied); + QImage rgb666 = rgb32.convertToFormat(QImage::Format_RGB666); QTest::newRow("rgba8888 -> rgb32") << rgba32 << QImage::Format_RGB32; QTest::newRow("rgba8888 -> argb32") << rgba32 << QImage::Format_ARGB32; QTest::newRow("rgba8888 -> argb32pm") << rgba32 << QImage::Format_ARGB32_Premultiplied; QTest::newRow("rgba8888 -> rgbx8888") << rgba32 << QImage::Format_RGBX8888; QTest::newRow("rgba8888 -> rgba8888pm") << rgba32 << QImage::Format_RGBA8888_Premultiplied; + QTest::newRow("rgba8888 -> rgb888") << rgba32 << QImage::Format_RGB888; QTest::newRow("rgba8888 -> rgb30") << rgba32 << QImage::Format_RGB30; QTest::newRow("rgba8888 -> a2bgr30") << rgba32 << QImage::Format_A2BGR30_Premultiplied; @@ -264,6 +263,14 @@ void tst_QImageConversion::convertGeneric_data() QTest::newRow("a2rgb30 -> rgb30") << a2rgb30 << QImage::Format_RGB30; QTest::newRow("a2rgb30 -> bgr30") << a2rgb30 << QImage::Format_BGR30; QTest::newRow("a2rgb30 -> a2bgr30") << a2rgb30 << QImage::Format_A2BGR30_Premultiplied; + + QTest::newRow("rgb666 -> rgb32") << rgb666 << QImage::Format_RGB32; + QTest::newRow("rgb666 -> argb32") << rgb666 << QImage::Format_ARGB32; + QTest::newRow("rgb666 -> argb32pm") << rgb666 << QImage::Format_ARGB32_Premultiplied; + QTest::newRow("rgb666 -> rgb888") << rgb666 << QImage::Format_RGB888; + QTest::newRow("rgb666 -> rgb16") << rgb666 << QImage::Format_RGB16; + QTest::newRow("rgb666 -> rgb555") << rgb666 << QImage::Format_RGB555; + QTest::newRow("rgb666 -> rgb30") << rgb666 << QImage::Format_RGB30; } void tst_QImageConversion::convertGeneric() @@ -285,6 +292,9 @@ void tst_QImageConversion::convertGenericInplace_data() QImage argb32 = generateImageArgb32(1000, 1000); QImage argb32pm = argb32.convertToFormat(QImage::Format_ARGB32_Premultiplied); QImage rgba8888 = argb32.convertToFormat(QImage::Format_RGBA8888); + QImage argb6666 = argb32.convertToFormat(QImage::Format_ARGB6666_Premultiplied); + QImage argb4444 = argb32.convertToFormat(QImage::Format_ARGB4444_Premultiplied); + QImage rgb16 = argb32.convertToFormat(QImage::Format_RGB16); QTest::newRow("argb32 -> argb32pm -> argb32") << argb32 << QImage::Format_ARGB32_Premultiplied; QTest::newRow("argb32 -> rgb32 -> argb32") << argb32 << QImage::Format_RGB32; @@ -301,6 +311,16 @@ void tst_QImageConversion::convertGenericInplace_data() QTest::newRow("rgba8888 -> rgb32 -> rgba8888") << rgba8888 << QImage::Format_RGB32; QTest::newRow("rgba8888 -> argb32pm -> rgba8888") << rgba8888 << QImage::Format_ARGB32_Premultiplied; QTest::newRow("rgba8888 -> rgba8888pm -> rgba8888") << rgba8888 << QImage::Format_RGBA8888_Premultiplied; + + QTest::newRow("argb6666pm -> argb8565pm -> argb6666pm") << argb6666 << QImage::Format_ARGB8565_Premultiplied; + QTest::newRow("argb6666pm -> rgb888 -> argb6666pm") << argb6666 << QImage::Format_RGB888; + + QTest::newRow("argb4444pm -> rgb16 -> argb4444pm") << argb4444 << QImage::Format_RGB16; + QTest::newRow("argb4444pm -> rgb444 -> argb4444pm") << argb4444 << QImage::Format_RGB444; + + QTest::newRow("rgb16 -> rgb555 -> rgb16") << rgb16 << QImage::Format_RGB555; + QTest::newRow("rgb16 -> rgb444 -> rgb16") << rgb16 << QImage::Format_RGB444; + QTest::newRow("rgb16 -> argb4444pm -> rgb16") << rgb16 << QImage::Format_ARGB4444_Premultiplied; } void tst_QImageConversion::convertGenericInplace()