From 4c0e27ae6f56cc43b871d7659b77747d9ba969bc Mon Sep 17 00:00:00 2001 From: Kai Pastor Date: Sun, 24 Apr 2016 17:37:29 +0200 Subject: [PATCH 01/51] Add Qt::SvgMiterJoin option to pathstroke example Qt::SvgMiterJoin is more important than the name suggests: It is used not only by SVG but also by PDF. It differs from Qt::MiterJoin in the miter limit behavior. Task-number: QTBUG-52640 Change-Id: I8ad04b1231958628caab18a233d54d42ea6449e7 Reviewed-by: Sze Howe Koh --- examples/widgets/painting/pathstroke/pathstroke.cpp | 4 ++++ examples/widgets/painting/pathstroke/pathstroke.h | 1 + 2 files changed, 5 insertions(+) diff --git a/examples/widgets/painting/pathstroke/pathstroke.cpp b/examples/widgets/painting/pathstroke/pathstroke.cpp index 1e2f75b2a5..5a7b8fd9fe 100644 --- a/examples/widgets/painting/pathstroke/pathstroke.cpp +++ b/examples/widgets/painting/pathstroke/pathstroke.cpp @@ -87,10 +87,12 @@ void PathStrokeControls::createCommonControls(QWidget* parent) m_joinGroup->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); QRadioButton *bevelJoin = new QRadioButton(m_joinGroup); QRadioButton *miterJoin = new QRadioButton(m_joinGroup); + QRadioButton *svgMiterJoin = new QRadioButton(m_joinGroup); QRadioButton *roundJoin = new QRadioButton(m_joinGroup); m_joinGroup->setTitle(tr("Join Style")); bevelJoin->setText(tr("Bevel")); miterJoin->setText(tr("Miter")); + svgMiterJoin->setText(tr("SvgMiter")); roundJoin->setText(tr("Round")); m_styleGroup = new QGroupBox(parent); @@ -145,6 +147,7 @@ void PathStrokeControls::createCommonControls(QWidget* parent) QVBoxLayout *joinGroupLayout = new QVBoxLayout(m_joinGroup); joinGroupLayout->addWidget(bevelJoin); joinGroupLayout->addWidget(miterJoin); + joinGroupLayout->addWidget(svgMiterJoin); joinGroupLayout->addWidget(roundJoin); QVBoxLayout *styleGroupLayout = new QVBoxLayout(m_styleGroup); @@ -167,6 +170,7 @@ void PathStrokeControls::createCommonControls(QWidget* parent) connect(bevelJoin, SIGNAL(clicked()), m_renderer, SLOT(setBevelJoin())); connect(miterJoin, SIGNAL(clicked()), m_renderer, SLOT(setMiterJoin())); + connect(svgMiterJoin, SIGNAL(clicked()), m_renderer, SLOT(setSvgMiterJoin())); connect(roundJoin, SIGNAL(clicked()), m_renderer, SLOT(setRoundJoin())); connect(curveMode, SIGNAL(clicked()), m_renderer, SLOT(setCurveMode())); diff --git a/examples/widgets/painting/pathstroke/pathstroke.h b/examples/widgets/painting/pathstroke/pathstroke.h index 71352c8cc2..7bc7e09003 100644 --- a/examples/widgets/painting/pathstroke/pathstroke.h +++ b/examples/widgets/painting/pathstroke/pathstroke.h @@ -92,6 +92,7 @@ public slots: void setBevelJoin() { m_joinStyle = Qt::BevelJoin; update(); } void setMiterJoin() { m_joinStyle = Qt::MiterJoin; update(); } + void setSvgMiterJoin() { m_joinStyle = Qt::SvgMiterJoin; update(); } void setRoundJoin() { m_joinStyle = Qt::RoundJoin; update(); } void setCurveMode() { m_pathMode = CurveMode; update(); } From f1bf7eb34a72cc5c58b3ee4e4ebf384e2539c202 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 21 Mar 2018 10:16:59 +0100 Subject: [PATCH 02/51] qtestlib/Unix: Output function time and total time in case of a crash This helps to distinguish timeouts from real crashes in COIN. This is already done for Windows. Change-Id: I4daeafa36f50482d20cea4bd1106647081ff7abe Reviewed-by: Mitch Curtis --- src/testlib/qtestcase.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index d53530dadd..d03eb4c2c0 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -208,8 +208,13 @@ static void stackTrace() if (debuggerPresent()) return; +#if defined(Q_OS_LINUX) || defined(Q_OS_MACOS) + const int msecsFunctionTime = qRound(QTestLog::msecsFunctionTime()); + const int msecsTotalTime = qRound(QTestLog::msecsTotalTime()); + fprintf(stderr, "\n=== Received signal at function time: %dms, total time: %dms, dumping stack ===\n", + msecsFunctionTime, msecsTotalTime); +#endif #ifdef Q_OS_LINUX - fprintf(stderr, "\n========= Received signal, dumping stack ==============\n"); char cmd[512]; qsnprintf(cmd, 512, "gdb --pid %d 2>/dev/null </dev/null < Date: Mon, 26 Feb 2018 16:03:16 +0100 Subject: [PATCH 03/51] Cocoa: Restore resizable window mask setting to 5.9 behavior MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This should be tied to the CustomizeWindowHint flag: if that flag is set we start out without NSResizableWindowMask and possibly add it later on if WindowMaximizeButtonHint is set. Change-Id: I7e826d4bd357a8a17c60cfef948af25d61b66ebf Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/qcocoawindow.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index f9c676a5b0..54254455e4 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -503,7 +503,7 @@ NSUInteger QCocoaWindow::windowStyleMask(Qt::WindowFlags flags) { const Qt::WindowType type = static_cast(int(flags & Qt::WindowType_Mask)); const bool frameless = (flags & Qt::FramelessWindowHint) || windowIsPopupType(type); - const bool resizeable = type != Qt::Dialog; // Dialogs: remove zoom button by disabling resize + const bool resizeable = !(flags & Qt::CustomizeWindowHint); // Remove zoom button by disabling resize // Select base window type. Note that the value of NSBorderlessWindowMask is 0. NSUInteger styleMask = (frameless || !resizeable) ? NSBorderlessWindowMask : NSResizableWindowMask; From 4a56d86ee43bd6be23f70ef2d29ba4b4ebb17029 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Tue, 20 Mar 2018 10:00:06 +0100 Subject: [PATCH 04/51] Make QSsl::SecureProtocols also enable use of TLS1.{1,2} Previously it was only enabling use of TLS1.0, unlike our openssl backend, which understandably caused some confusion among some of our users. Seeing as this is also the default value in QSslConfiguration it is nice to have it negotatiate more secure ciphers. Task-number: QTBUG-67112 Change-Id: Ie216703da1ec4e6b973a881040e14816ad4c0a32 Reviewed-by: Oliver Wolff --- src/network/ssl/qsslsocket_winrt.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/network/ssl/qsslsocket_winrt.cpp b/src/network/ssl/qsslsocket_winrt.cpp index f64ae2e020..ff9dccc734 100644 --- a/src/network/ssl/qsslsocket_winrt.cpp +++ b/src/network/ssl/qsslsocket_winrt.cpp @@ -238,7 +238,6 @@ void QSslSocketBackendPrivate::startClientEncryption() case QSsl::SslV3: protectionLevel = SocketProtectionLevel_Ssl; // Only use this value if weak cipher support is required break; - case QSsl::SecureProtocols: case QSsl::TlsV1SslV3: case QSsl::TlsV1_0: protectionLevel = SocketProtectionLevel_Tls10; @@ -257,6 +256,11 @@ void QSslSocketBackendPrivate::startClientEncryption() setErrorAndEmit(QAbstractSocket::SslInvalidUserDataError, QStringLiteral("unsupported protocol")); return; + case QSsl::SecureProtocols: + // SocketProtectionLevel_Tls12 actually means "use TLS1.0, 1.1 or 1.2" + // https://docs.microsoft.com/en-us/uwp/api/windows.networking.sockets.socketprotectionlevel + protectionLevel = SocketProtectionLevel_Tls12; + break; default: protectionLevel = SocketProtectionLevel_Tls12; // default to highest protocol = QSsl::TlsV1_2; From 4db38197c2bac8bcee9d08a0e20ed2c8d127b8f2 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 13 Feb 2018 12:25:10 +0100 Subject: [PATCH 05/51] Testlib: Rename qtest_global.h to qttestglobal.h This follows the naming convention for global headers and causes qttestglobal.h to be added to the top of the generated QtTest header. It is necessary to have it there when other headers depend on features defined in configure.json. [ChangeLog][QtTest] The qtest_global.h header is now deprecated. Include qttestglobal.h instead. Change-Id: Iaed639d4e13dd99cee6387fce9d15d6e55b0b1e8 Reviewed-by: Oswald Buddenhagen --- src/testlib/qabstractitemmodeltester.h | 2 +- src/testlib/qbenchmark.h | 2 +- src/testlib/qbenchmark_p.h | 2 +- src/testlib/qbenchmarkmetric.h | 2 +- src/testlib/qbenchmarkmetric_p.h | 2 +- src/testlib/qtest.h | 2 +- src/testlib/qtestaccessible.h | 2 +- src/testlib/qtestblacklist_p.h | 2 +- src/testlib/qtestcase.h | 2 +- src/testlib/qtestdata.h | 2 +- src/testlib/qtestevent.h | 2 +- src/testlib/qtesteventloop.h | 2 +- src/testlib/qtestkeyboard.h | 2 +- src/testlib/qtestlog_p.h | 2 +- src/testlib/qtestmouse.cpp | 2 +- src/testlib/qtestmouse.h | 2 +- src/testlib/qtestresult_p.h | 2 +- src/testlib/qtesttable_p.h | 2 +- src/testlib/qtesttouch.h | 2 +- src/testlib/{qtest_global.h => qttestglobal.h} | 5 ++--- src/testlib/testlib.pro | 4 ++-- sync.profile | 3 +++ 22 files changed, 26 insertions(+), 24 deletions(-) rename src/testlib/{qtest_global.h => qttestglobal.h} (98%) diff --git a/src/testlib/qabstractitemmodeltester.h b/src/testlib/qabstractitemmodeltester.h index 617e189817..e85d7522f7 100644 --- a/src/testlib/qabstractitemmodeltester.h +++ b/src/testlib/qabstractitemmodeltester.h @@ -30,7 +30,7 @@ #define QABSTRACTITEMMODELTESTER_H #include -#include +#include #ifdef QT_GUI_LIB #include diff --git a/src/testlib/qbenchmark.h b/src/testlib/qbenchmark.h index 1340fd7715..4a55fcc23e 100644 --- a/src/testlib/qbenchmark.h +++ b/src/testlib/qbenchmark.h @@ -40,7 +40,7 @@ #ifndef QBENCHMARK_H #define QBENCHMARK_H -#include +#include #include QT_BEGIN_NAMESPACE diff --git a/src/testlib/qbenchmark_p.h b/src/testlib/qbenchmark_p.h index dbfa0127b6..3fa9c5f534 100644 --- a/src/testlib/qbenchmark_p.h +++ b/src/testlib/qbenchmark_p.h @@ -69,7 +69,7 @@ #include #include -#include +#include #ifdef QTESTLIB_USE_VALGRIND #include #endif diff --git a/src/testlib/qbenchmarkmetric.h b/src/testlib/qbenchmarkmetric.h index 6e423473b1..6605606402 100644 --- a/src/testlib/qbenchmarkmetric.h +++ b/src/testlib/qbenchmarkmetric.h @@ -41,7 +41,7 @@ #ifndef QBENCHMARKMETRIC_H #define QBENCHMARKMETRIC_H -#include +#include QT_BEGIN_NAMESPACE diff --git a/src/testlib/qbenchmarkmetric_p.h b/src/testlib/qbenchmarkmetric_p.h index a036c645bf..049b9711e2 100644 --- a/src/testlib/qbenchmarkmetric_p.h +++ b/src/testlib/qbenchmarkmetric_p.h @@ -51,7 +51,7 @@ // We mean it. // -#include +#include #include QT_BEGIN_NAMESPACE diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h index a5df27e3b9..1cb6a91d33 100644 --- a/src/testlib/qtest.h +++ b/src/testlib/qtest.h @@ -41,7 +41,7 @@ #ifndef QTEST_H #define QTEST_H -#include +#include #include #include #include diff --git a/src/testlib/qtestaccessible.h b/src/testlib/qtestaccessible.h index 0470d15ed7..d14dcec031 100644 --- a/src/testlib/qtestaccessible.h +++ b/src/testlib/qtestaccessible.h @@ -54,7 +54,7 @@ #include #include #include -#include +#include #include #if QT_CONFIG(accessibility) diff --git a/src/testlib/qtestblacklist_p.h b/src/testlib/qtestblacklist_p.h index df205fc77b..08ce052231 100644 --- a/src/testlib/qtestblacklist_p.h +++ b/src/testlib/qtestblacklist_p.h @@ -51,7 +51,7 @@ // We mean it. // -#include +#include QT_BEGIN_NAMESPACE diff --git a/src/testlib/qtestcase.h b/src/testlib/qtestcase.h index cc666c365a..54669c11de 100644 --- a/src/testlib/qtestcase.h +++ b/src/testlib/qtestcase.h @@ -40,7 +40,7 @@ #ifndef QTESTCASE_H #define QTESTCASE_H -#include +#include #include #include diff --git a/src/testlib/qtestdata.h b/src/testlib/qtestdata.h index c87236fcfc..cf10fed8f3 100644 --- a/src/testlib/qtestdata.h +++ b/src/testlib/qtestdata.h @@ -40,7 +40,7 @@ #ifndef QTESTDATA_H #define QTESTDATA_H -#include +#include #include #include diff --git a/src/testlib/qtestevent.h b/src/testlib/qtestevent.h index 159e3e01ff..3f6bd20bd8 100644 --- a/src/testlib/qtestevent.h +++ b/src/testlib/qtestevent.h @@ -45,7 +45,7 @@ #pragma qt_no_master_include #endif -#include +#include #ifdef QT_GUI_LIB #include #include diff --git a/src/testlib/qtesteventloop.h b/src/testlib/qtesteventloop.h index 81c0b9126c..19ad22565e 100644 --- a/src/testlib/qtesteventloop.h +++ b/src/testlib/qtesteventloop.h @@ -40,7 +40,7 @@ #ifndef QTESTEVENTLOOP_H #define QTESTEVENTLOOP_H -#include +#include #include #include diff --git a/src/testlib/qtestkeyboard.h b/src/testlib/qtestkeyboard.h index a7cf78f25a..63501ffb1e 100644 --- a/src/testlib/qtestkeyboard.h +++ b/src/testlib/qtestkeyboard.h @@ -46,7 +46,7 @@ #endif #include -#include +#include #include #include diff --git a/src/testlib/qtestlog_p.h b/src/testlib/qtestlog_p.h index f72c047c35..3d28795188 100644 --- a/src/testlib/qtestlog_p.h +++ b/src/testlib/qtestlog_p.h @@ -51,7 +51,7 @@ // We mean it. // -#include +#include QT_BEGIN_NAMESPACE diff --git a/src/testlib/qtestmouse.cpp b/src/testlib/qtestmouse.cpp index eda7edbd89..76369e0490 100644 --- a/src/testlib/qtestmouse.cpp +++ b/src/testlib/qtestmouse.cpp @@ -39,7 +39,7 @@ #include #include -#include +#include QT_BEGIN_NAMESPACE diff --git a/src/testlib/qtestmouse.h b/src/testlib/qtestmouse.h index e2835828a1..e3e446577d 100644 --- a/src/testlib/qtestmouse.h +++ b/src/testlib/qtestmouse.h @@ -45,7 +45,7 @@ #pragma qt_no_master_include #endif -#include +#include #include #include #include diff --git a/src/testlib/qtestresult_p.h b/src/testlib/qtestresult_p.h index 061ca5f311..4df75b2805 100644 --- a/src/testlib/qtestresult_p.h +++ b/src/testlib/qtestresult_p.h @@ -51,7 +51,7 @@ // We mean it. // -#include +#include QT_BEGIN_NAMESPACE diff --git a/src/testlib/qtesttable_p.h b/src/testlib/qtesttable_p.h index 53de9a2f43..d2f389a134 100644 --- a/src/testlib/qtesttable_p.h +++ b/src/testlib/qtesttable_p.h @@ -51,7 +51,7 @@ // We mean it. // -#include +#include QT_BEGIN_NAMESPACE diff --git a/src/testlib/qtesttouch.h b/src/testlib/qtesttouch.h index 83ca83602e..20a9476ee7 100644 --- a/src/testlib/qtesttouch.h +++ b/src/testlib/qtesttouch.h @@ -45,7 +45,7 @@ #pragma qt_no_master_include #endif -#include +#include #include #include #include diff --git a/src/testlib/qtest_global.h b/src/testlib/qttestglobal.h similarity index 98% rename from src/testlib/qtest_global.h rename to src/testlib/qttestglobal.h index 3fbb1d428c..d07464345d 100644 --- a/src/testlib/qtest_global.h +++ b/src/testlib/qttestglobal.h @@ -37,14 +37,13 @@ ** ****************************************************************************/ -#ifndef QTEST_GLOBAL_H -#define QTEST_GLOBAL_H +#ifndef QTTESTGLOBAL_H +#define QTTESTGLOBAL_H #include QT_BEGIN_NAMESPACE - #if defined(QT_STATIC) # define Q_TESTLIB_EXPORT #else diff --git a/src/testlib/testlib.pro b/src/testlib/testlib.pro index 109feee630..1e1f21e740 100644 --- a/src/testlib/testlib.pro +++ b/src/testlib/testlib.pro @@ -29,7 +29,6 @@ HEADERS = \ qtestdata.h \ qtestevent.h \ qtesteventloop.h \ - qtest_global.h \ qtest_gui.h \ qtest_network.h \ qtest_widgets.h \ @@ -40,7 +39,8 @@ HEADERS = \ qtestsystem.h \ qtesttouch.h \ qtestblacklist_p.h \ - qtesthelpers_p.h + qtesthelpers_p.h \ + qttestglobal.h SOURCES = \ qabstractitemmodeltester.cpp \ diff --git a/sync.profile b/sync.profile index 6a50e31102..c674aab2f3 100644 --- a/sync.profile +++ b/sync.profile @@ -73,6 +73,9 @@ }, "QtDBus" => { "qdbusmacros.h" => "QtDbus/qtdbusglobal.h" + }, + "QtTest" => { + "qtest_global.h" => "QtTest/qttestglobal.h" } ); From 955cf40b18ba37c46d692206c5fc39e93bfda01c Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 9 Feb 2018 15:38:27 +0100 Subject: [PATCH 06/51] Testlib: Add a feature for the item model tester It depends on QAbstractItemModel, so we need to switch it off if itemmodel is unavailable. Change-Id: I97246767a5e387b7a2cee90c34125a8411ef1c4e Reviewed-by: Oswald Buddenhagen --- configure.json | 3 ++- src/testlib/configure.json | 22 ++++++++++++++++++++++ src/testlib/qabstractitemmodeltester.h | 2 ++ src/testlib/qttestglobal.h | 1 + src/testlib/testlib.pro | 10 ++++++++-- 5 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 src/testlib/configure.json diff --git a/configure.json b/configure.json index 003c6c5b90..ae2aa22070 100644 --- a/configure.json +++ b/configure.json @@ -14,7 +14,8 @@ "src/xml", "src/widgets", "src/printsupport", - "src/plugins/sqldrivers" + "src/plugins/sqldrivers", + "src/testlib" ], "commandline": { diff --git a/src/testlib/configure.json b/src/testlib/configure.json new file mode 100644 index 0000000000..c464037205 --- /dev/null +++ b/src/testlib/configure.json @@ -0,0 +1,22 @@ +{ + "module": "testlib", + "depends": [ + "core" + ], + + "features": { + "itemmodeltester": { + "label": "Tester for item models", + "purpose": "Provides a utility to test item models.", + "condition": "features.itemmodel", + "output": [ "publicFeature" ] + } + }, + + "summary": [ + { + "section": "Qt Testlib", + "entries": [ "itemmodeltester" ] + } + ] +} diff --git a/src/testlib/qabstractitemmodeltester.h b/src/testlib/qabstractitemmodeltester.h index e85d7522f7..706c0ac16f 100644 --- a/src/testlib/qabstractitemmodeltester.h +++ b/src/testlib/qabstractitemmodeltester.h @@ -41,6 +41,8 @@ #include #endif +QT_REQUIRE_CONFIG(itemmodeltester); + QT_BEGIN_NAMESPACE class QAbstractItemModel; diff --git a/src/testlib/qttestglobal.h b/src/testlib/qttestglobal.h index d07464345d..9561e56ba3 100644 --- a/src/testlib/qttestglobal.h +++ b/src/testlib/qttestglobal.h @@ -41,6 +41,7 @@ #define QTTESTGLOBAL_H #include +#include QT_BEGIN_NAMESPACE diff --git a/src/testlib/testlib.pro b/src/testlib/testlib.pro index 1e1f21e740..06a6f8b8e5 100644 --- a/src/testlib/testlib.pro +++ b/src/testlib/testlib.pro @@ -12,7 +12,6 @@ unix:!embedded:QMAKE_PKGCONFIG_DESCRIPTION = Qt \ QMAKE_DOCS = $$PWD/doc/qttestlib.qdocconf HEADERS = \ - qabstractitemmodeltester.h \ qbenchmark.h \ qbenchmark_p.h \ qbenchmarkmeasurement_p.h \ @@ -43,7 +42,6 @@ HEADERS = \ qttestglobal.h SOURCES = \ - qabstractitemmodeltester.cpp \ qtestcase.cpp \ qtestlog.cpp \ qtesttable.cpp \ @@ -69,6 +67,14 @@ SOURCES = \ qxunittestlogger.cpp \ qtestblacklist.cpp +qtConfig(itemmodeltester) { + HEADERS += \ + qabstractitemmodeltester.h + + SOURCES += \ + qabstractitemmodeltester.cpp +} + DEFINES *= QT_NO_CAST_TO_ASCII \ QT_NO_CAST_FROM_ASCII \ QT_NO_FOREACH \ From 90ec3aba06d9832b802df3e5eb77221b2bb31bdb Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 9 Jan 2017 11:39:46 +0100 Subject: [PATCH 07/51] Clean up the moc "no-keywords" test We can use the QT_LIB_FOO #defines instead of our own WITH_FOO ones to determine if a library is available. Also, it doesn't currently make sense to refer to libraries which are not part of qtbase here. We might add that in the future, but QtScript (being deprecated) is probably not the first one we should add. Change-Id: I7f2397ca5499ba6003088478161182e960e815fb Reviewed-by: Oswald Buddenhagen --- tests/auto/tools/moc/moc.pro | 10 +++++----- tests/auto/tools/moc/no-keywords.h | 19 +++++++++++-------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/tests/auto/tools/moc/moc.pro b/tests/auto/tools/moc/moc.pro index d2b13f9c4e..3cbc9ebb5e 100644 --- a/tests/auto/tools/moc/moc.pro +++ b/tests/auto/tools/moc/moc.pro @@ -36,11 +36,11 @@ if(*-g++*|*-icc*|*-clang*|*-llvm):!win32-*: HEADERS += os9-newlines.h win-newlin if(*-g++*|*-clang*): HEADERS += dollars.h SOURCES += tst_moc.cpp -QT = core sql network testlib -qtHaveModule(dbus) { - DEFINES += WITH_DBUS - QT += dbus -} +QT = core testlib +qtHaveModule(dbus): QT += dbus +qtHaveModule(concurrent): QT += concurrent +qtHaveModule(network): QT += network +qtHaveModule(sql): QT += sql # tst_Moc::specifyMetaTagsFromCmdline() # Ensure that plugin_metadata.h are moc-ed with some extra -M arguments: diff --git a/tests/auto/tools/moc/no-keywords.h b/tests/auto/tools/moc/no-keywords.h index d31063665b..ca77056503 100644 --- a/tests/auto/tools/moc/no-keywords.h +++ b/tests/auto/tools/moc/no-keywords.h @@ -37,16 +37,19 @@ #define slots Baz #define emit Yoyodyne +#include + +#ifdef QT_CONCURRENT_LIB #include -#include -#include -#include -//#include -#if defined(WITH_DBUS) -#include #endif -#ifdef QT_SCRIPT_LIB -#include +#ifdef QT_NETWORK_LIB +#include +#endif +#ifdef QT_SQL_LIB +#include +#endif +#ifdef QT_DBUS_LIB +#include #endif #undef signals From 992f673782ac7b8edea0dc7b4498eb7f970b4ba8 Mon Sep 17 00:00:00 2001 From: Nathan Collins Date: Wed, 21 Mar 2018 10:14:09 +0000 Subject: [PATCH 08/51] macOS: Handle NaN mouse event positions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When performing gestures such as Exposé or Mission Control with the mouse button down, the position of the mouse release event is returned with NaN values. This causes QGuiApplicationPrivate::processMouseEvent to be called recursively and ultimately crash. Task-number: QTBUG-67194 Change-Id: If1536bc4dc2075c498cdd6c5afe57c86bdaac13b Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/qnsview.mm | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 7b7b3f53d5..a88cd5feda 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -487,8 +487,12 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") NSPoint screenPoint; if (theEvent) { NSPoint windowPoint = [theEvent locationInWindow]; - NSRect screenRect = [[theEvent window] convertRectToScreen:NSMakeRect(windowPoint.x, windowPoint.y, 1, 1)]; - screenPoint = screenRect.origin; + if (qIsNaN(windowPoint.x) || qIsNaN(windowPoint.y)) { + screenPoint = [NSEvent mouseLocation]; + } else { + NSRect screenRect = [[theEvent window] convertRectToScreen:NSMakeRect(windowPoint.x, windowPoint.y, 1, 1)]; + screenPoint = screenRect.origin; + } } else { screenPoint = [NSEvent mouseLocation]; } From 5f66486cc254e1483f776d3058f96db493fd26e5 Mon Sep 17 00:00:00 2001 From: Marcel Krems Date: Wed, 21 Feb 2018 19:19:36 +0100 Subject: [PATCH 09/51] Fix crash when deleting a QSqlQueryModel after closing the database Task-number: QTBUG-66553 Change-Id: Ib5c04ebe5ac2b7581613e0044804072eb0980b2e Reviewed-by: Andy Shaw --- src/plugins/sqldrivers/psql/qsql_psql.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/plugins/sqldrivers/psql/qsql_psql.cpp b/src/plugins/sqldrivers/psql/qsql_psql.cpp index b4eb69e6cf..5e0f7626b4 100644 --- a/src/plugins/sqldrivers/psql/qsql_psql.cpp +++ b/src/plugins/sqldrivers/psql/qsql_psql.cpp @@ -462,8 +462,10 @@ void QPSQLResult::cleanup() d->result = nullptr; while (!d->nextResultSets.isEmpty()) PQclear(d->nextResultSets.takeFirst()); - if (d->stmtId != InvalidStatementId) - d->drv_d_func()->finishQuery(d->stmtId); + if (d->stmtId != InvalidStatementId) { + if (d->drv_d_func()) + d->drv_d_func()->finishQuery(d->stmtId); + } d->stmtId = InvalidStatementId; setAt(QSql::BeforeFirstRow); d->currentSize = -1; From a47cb146809e32f43449dcfe9932833c2f0ab987 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Wed, 14 Feb 2018 13:40:57 +0100 Subject: [PATCH 10/51] Detect C standard and try using the most recent Fixes the default C version used with gcc < 5 Change-Id: I948dece961caed8e6b181e1c6e6b9dc43c46583f Reviewed-by: Oswald Buddenhagen --- configure.json | 48 +++++++++++++++++++++++++ mkspecs/common/android-base-tail.conf | 2 ++ mkspecs/common/clang.conf | 2 ++ mkspecs/common/g++-base.conf | 2 ++ mkspecs/common/gcc-base.conf | 3 ++ mkspecs/features/default_post.prf | 15 ++++++++ mkspecs/features/qt_common.prf | 2 ++ mkspecs/features/qt_configure.prf | 13 +++++-- src/3rdparty/xkbcommon.pri | 1 - src/corelib/global/qcompilerdetection.h | 2 +- 10 files changed, 86 insertions(+), 4 deletions(-) diff --git a/configure.json b/configure.json index ae2aa22070..b4d763116c 100644 --- a/configure.json +++ b/configure.json @@ -259,6 +259,36 @@ "type": "compile", "test": "stl" }, + "c99": { + "label": "C99 support", + "type": "compile", + "test": { + "head": [ + "#if __STDC_VERSION__ >= 199901L", + "// Compiler claims to support C99, trust it", + "#else", + "# error __STDC_VERSION__ must be >= 199901L", + "#endif" + ], + "lang": "c", + "qmake": "CONFIG += c99" + } + }, + "c11": { + "label": "C11 support", + "type": "compile", + "test": { + "head": [ + "#if __STDC_VERSION__ >= 201112L", + "// Compiler claims to support C11, trust it", + "#else", + "# error __STDC_VERSION__ must be >= 201112L", + "#endif" + ], + "lang": "c", + "qmake": "CONFIG += c11" + } + }, "c++14": { "label": "C++14 support", "type": "compile", @@ -786,6 +816,19 @@ "condition": "features.c++14 && tests.c++1z", "output": [ "publicFeature", "publicQtConfig" ] }, + "c89": { + "label": "C89" + }, + "c99": { + "label": "C99", + "condition": "tests.c99", + "output": [ "publicFeature" ] + }, + "c11": { + "label": "C11", + "condition": "features.c99 && tests.c11", + "output": [ "publicFeature" ] + }, "precompile_header": { "label": "Using precompiled headers", "condition": "config.msvc || tests.precompile_header", @@ -1246,6 +1289,11 @@ Configure with '-qreal float' to create a build that is binary-compatible with 5 "condition": "!features.debug || features.debug_and_release" }, "shared", + { + "message": "Using C standard", + "type": "firstAvailableFeature", + "args": "c11 c99 c89" + }, { "message": "Using C++ standard", "type": "firstAvailableFeature", diff --git a/mkspecs/common/android-base-tail.conf b/mkspecs/common/android-base-tail.conf index 160caf011f..464b60b1c4 100644 --- a/mkspecs/common/android-base-tail.conf +++ b/mkspecs/common/android-base-tail.conf @@ -38,6 +38,8 @@ QMAKE_CFLAGS_THREAD = -D_REENTRANT QMAKE_CFLAGS_HIDESYMS = -fvisibility=hidden QMAKE_CFLAGS_NEON = -mfpu=neon +QMAKE_CFLAGS_GNUC99 = -std=gnu99 +QMAKE_CFLAGS_GNUC11 = -std=gnu11 QMAKE_CXXFLAGS_CXX11 = -std=c++11 QMAKE_CXXFLAGS_CXX14 = -std=c++14 QMAKE_CXXFLAGS_CXX1Z = -std=c++1z diff --git a/mkspecs/common/clang.conf b/mkspecs/common/clang.conf index e003b947aa..6122a37213 100644 --- a/mkspecs/common/clang.conf +++ b/mkspecs/common/clang.conf @@ -21,6 +21,8 @@ QMAKE_CFLAGS_PRECOMPILE = -x c-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_ QMAKE_CFLAGS_USE_PRECOMPILE = -Xclang -include-pch -Xclang ${QMAKE_PCH_OUTPUT} QMAKE_CFLAGS_LTCG = -flto QMAKE_CFLAGS_DISABLE_LTCG = -fno-lto +QMAKE_CFLAGS_GNUC99 = -std=gnu99 +QMAKE_CFLAGS_GNUC11 = -std=gnu11 QMAKE_CXXFLAGS_PRECOMPILE = -x c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} QMAKE_CXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE diff --git a/mkspecs/common/g++-base.conf b/mkspecs/common/g++-base.conf index c42c46b0ec..fa0f0c391d 100644 --- a/mkspecs/common/g++-base.conf +++ b/mkspecs/common/g++-base.conf @@ -27,6 +27,8 @@ QMAKE_CFLAGS_USE_PRECOMPILE = -include ${QMAKE_PCH_OUTPUT_BASE} QMAKE_CXXFLAGS_PRECOMPILE = -x c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} QMAKE_CXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE +QMAKE_CFLAGS_GNUC99 = -std=gnu99 +QMAKE_CFLAGS_GNUC11 = -std=gnu11 QMAKE_CXXFLAGS_CXX11 = -std=c++11 QMAKE_CXXFLAGS_CXX14 = -std=c++1y QMAKE_CXXFLAGS_CXX1Z = -std=c++1z diff --git a/mkspecs/common/gcc-base.conf b/mkspecs/common/gcc-base.conf index 234f71d495..0407ba9724 100644 --- a/mkspecs/common/gcc-base.conf +++ b/mkspecs/common/gcc-base.conf @@ -81,6 +81,9 @@ QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO += QMAKE_LFLAGS_EXCEPTIONS_OFF += QMAKE_LFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG -fuse-linker-plugin +QMAKE_CFLAGS_C99 = -std=c99 +QMAKE_CFLAGS_C11 = -std=c11 + QMAKE_CFLAGS_SSE2 += -msse2 QMAKE_CFLAGS_SSE3 += -msse3 QMAKE_CFLAGS_SSSE3 += -mssse3 diff --git a/mkspecs/features/default_post.prf b/mkspecs/features/default_post.prf index 9eba5bcf00..bf5acdefc4 100644 --- a/mkspecs/features/default_post.prf +++ b/mkspecs/features/default_post.prf @@ -143,6 +143,21 @@ c++11|c++14|c++1z { unset(cxxstd) } +c99|c11 { + c11: cstd = C11 + else: cstd = C99 + + # Check if we should disable compiler extensions or not + !isEmpty(QMAKE_CFLAGS_GNU$$cstd) { + # Let strict C++ imply strict C + !strict_c++: cstd = GNU$$cstd + } + + QMAKE_CFLAGS += $$eval(QMAKE_CFLAGS_$$cstd) + + unset(cstd) +} + utf8_source { QMAKE_CFLAGS += $$QMAKE_CFLAGS_UTF8_SOURCE QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_UTF8_SOURCE diff --git a/mkspecs/features/qt_common.prf b/mkspecs/features/qt_common.prf index f4ae5bde80..40f03d2186 100644 --- a/mkspecs/features/qt_common.prf +++ b/mkspecs/features/qt_common.prf @@ -17,6 +17,8 @@ DEFINES *= QT_NO_NARROWING_CONVERSIONS_IN_CONNECT qtConfig(c++11): CONFIG += c++11 strict_c++ qtConfig(c++14): CONFIG += c++14 qtConfig(c++1z): CONFIG += c++1z +qtConfig(c99): CONFIG += c99 +qtConfig(c11): CONFIG += c11 qtConfig(stack-protector-strong): CONFIG += stack_protector_strong contains(TEMPLATE, .*lib) { # module and plugins diff --git a/mkspecs/features/qt_configure.prf b/mkspecs/features/qt_configure.prf index 98fff59ea1..a7da26c745 100644 --- a/mkspecs/features/qt_configure.prf +++ b/mkspecs/features/qt_configure.prf @@ -866,6 +866,15 @@ defineTest(qtConfTestPrepare_compile) { defineTest(qtConfPrepareCompileTestSource) { test_dir = $$2 + test_lang = $$eval($${1}.lang) + isEmpty(test_lang): test_lang = "c++" + + equals(test_lang, "c++"): suffix = "cpp" + else: equals(test_lang, "c"): suffix = "c" + else: equals(test_lang, "objc"): suffix = "m" + else: equals(test_lang, "objc++"): suffix = "mm" + else: error("Unknown language '$$test_lang' in compile test $$1") + # Create source code contents = "/* Generated by configure */" # Custom code before includes @@ -889,10 +898,10 @@ defineTest(qtConfPrepareCompileTestSource) { " /* END TEST */" \ " return 0;" \ "}" - write_file($$test_dir/main.cpp, contents)|error() + write_file($$test_dir/main.$$suffix, contents)|error() # Create stub .pro file - contents = "SOURCES = main.cpp" + contents = "SOURCES = main.$$suffix" # Custom project code for (ent, $$qtConfScalarOrList($${1}.qmake)): \ contents += $$ent diff --git a/src/3rdparty/xkbcommon.pri b/src/3rdparty/xkbcommon.pri index 1d953d8372..1050e54f3a 100644 --- a/src/3rdparty/xkbcommon.pri +++ b/src/3rdparty/xkbcommon.pri @@ -1,4 +1,3 @@ -QMAKE_CFLAGS += -std=gnu99 -w INCLUDEPATH += $$PWD/xkbcommon \ $$PWD/xkbcommon/xkbcommon \ $$PWD/xkbcommon/src \ diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index f3f3139d1a..e5e47082d8 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -898,7 +898,7 @@ /* C11 features supported in GCC 4.7: */ # define Q_COMPILER_STATIC_ASSERT # endif -# if Q_CC_GNU >= 409 +# if Q_CC_GNU >= 409 && defined(__has_include) /* C11 features supported in GCC 4.9: */ # if __has_include() # define Q_COMPILER_THREAD_LOCAL From 6e8e9979d0786d7d730528c2888e0e1af4fb96ca Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Fri, 9 Feb 2018 15:22:03 +0100 Subject: [PATCH 11/51] Make sure we can build with -no-feature-itemmodel Various pieces of code have to be disabled in this case. Change-Id: I83b133f17e9f024016a79c9103293627185449d2 Reviewed-by: Oswald Buddenhagen --- src/corelib/global/qconfig-bootstrapped.h | 1 + src/corelib/itemmodels/itemmodels.pri | 48 ++++++++++++---- src/corelib/itemmodels/qabstractitemmodel.h | 2 + src/corelib/itemmodels/qabstractitemmodel_p.h | 2 + .../itemmodels/qabstractproxymodel.cpp | 5 -- src/corelib/itemmodels/qabstractproxymodel.h | 7 +-- .../itemmodels/qabstractproxymodel_p.h | 4 +- .../itemmodels/qidentityproxymodel.cpp | 5 -- src/corelib/itemmodels/qidentityproxymodel.h | 4 +- src/corelib/itemmodels/qitemselectionmodel.h | 2 + .../itemmodels/qitemselectionmodel_p.h | 2 + .../itemmodels/qsortfilterproxymodel.cpp | 5 -- .../itemmodels/qsortfilterproxymodel.h | 7 +-- src/corelib/itemmodels/qstringlistmodel.cpp | 4 -- src/corelib/itemmodels/qstringlistmodel.h | 7 +-- src/corelib/kernel/qmetatype.cpp | 9 ++- src/corelib/kernel/qmetatype.h | 11 +++- src/corelib/kernel/qmetatype_p.h | 2 - src/corelib/kernel/qvariant.cpp | 56 +++++++++++-------- src/corelib/kernel/qvariant.h | 14 +++-- 20 files changed, 114 insertions(+), 83 deletions(-) diff --git a/src/corelib/global/qconfig-bootstrapped.h b/src/corelib/global/qconfig-bootstrapped.h index 86ef1a2613..3469ebe5e6 100644 --- a/src/corelib/global/qconfig-bootstrapped.h +++ b/src/corelib/global/qconfig-bootstrapped.h @@ -87,6 +87,7 @@ #define QT_FEATURE_journald -1 #define QT_FEATURE_futimens -1 #define QT_FEATURE_futimes -1 +#define QT_FEATURE_itemmodel -1 #define QT_FEATURE_library -1 #ifdef __linux__ # define QT_FEATURE_linkat 1 diff --git a/src/corelib/itemmodels/itemmodels.pri b/src/corelib/itemmodels/itemmodels.pri index 83ec4c5dbf..068a8c4b3a 100644 --- a/src/corelib/itemmodels/itemmodels.pri +++ b/src/corelib/itemmodels/itemmodels.pri @@ -1,20 +1,46 @@ # Qt itemmodels core module +!qtConfig(itemmodel): return() + HEADERS += \ itemmodels/qabstractitemmodel.h \ itemmodels/qabstractitemmodel_p.h \ - itemmodels/qabstractproxymodel.h \ - itemmodels/qabstractproxymodel_p.h \ itemmodels/qitemselectionmodel.h \ - itemmodels/qitemselectionmodel_p.h \ - itemmodels/qidentityproxymodel.h \ - itemmodels/qsortfilterproxymodel.h \ - itemmodels/qstringlistmodel.h + itemmodels/qitemselectionmodel_p.h SOURCES += \ itemmodels/qabstractitemmodel.cpp \ - itemmodels/qabstractproxymodel.cpp \ - itemmodels/qitemselectionmodel.cpp \ - itemmodels/qidentityproxymodel.cpp \ - itemmodels/qsortfilterproxymodel.cpp \ - itemmodels/qstringlistmodel.cpp + itemmodels/qitemselectionmodel.cpp + +qtConfig(proxymodel) { + HEADERS += \ + itemmodels/qabstractproxymodel.h \ + itemmodels/qabstractproxymodel_p.h + + SOURCES += \ + itemmodels/qabstractproxymodel.cpp + + qtConfig(identityproxymodel) { + HEADERS += \ + itemmodels/qidentityproxymodel.h + + SOURCES += \ + itemmodels/qidentityproxymodel.cpp + } + + qtConfig(sortfilterproxymodel) { + HEADERS += \ + itemmodels/qsortfilterproxymodel.h + + SOURCES += \ + itemmodels/qsortfilterproxymodel.cpp + } +} + +qtConfig(stringlistmodel) { + HEADERS += \ + itemmodels/qstringlistmodel.h + + SOURCES += \ + itemmodels/qstringlistmodel.cpp +} diff --git a/src/corelib/itemmodels/qabstractitemmodel.h b/src/corelib/itemmodels/qabstractitemmodel.h index fca21b9bbc..21171124f9 100644 --- a/src/corelib/itemmodels/qabstractitemmodel.h +++ b/src/corelib/itemmodels/qabstractitemmodel.h @@ -45,6 +45,8 @@ #include #include +QT_REQUIRE_CONFIG(itemmodel); + QT_BEGIN_NAMESPACE diff --git a/src/corelib/itemmodels/qabstractitemmodel_p.h b/src/corelib/itemmodels/qabstractitemmodel_p.h index 7086ae730a..12fd93d217 100644 --- a/src/corelib/itemmodels/qabstractitemmodel_p.h +++ b/src/corelib/itemmodels/qabstractitemmodel_p.h @@ -60,6 +60,8 @@ QT_BEGIN_NAMESPACE +QT_REQUIRE_CONFIG(itemmodel); + class QPersistentModelIndexData { public: diff --git a/src/corelib/itemmodels/qabstractproxymodel.cpp b/src/corelib/itemmodels/qabstractproxymodel.cpp index 39bfdd7782..b7c49a53e4 100644 --- a/src/corelib/itemmodels/qabstractproxymodel.cpp +++ b/src/corelib/itemmodels/qabstractproxymodel.cpp @@ -38,9 +38,6 @@ ****************************************************************************/ #include "qabstractproxymodel.h" - -#ifndef QT_NO_PROXYMODEL - #include "qitemselectionmodel.h" #include #include @@ -471,5 +468,3 @@ Qt::DropActions QAbstractProxyModel::supportedDropActions() const QT_END_NAMESPACE #include "moc_qabstractproxymodel.cpp" - -#endif // QT_NO_PROXYMODEL diff --git a/src/corelib/itemmodels/qabstractproxymodel.h b/src/corelib/itemmodels/qabstractproxymodel.h index 6aa82b21ee..c4e5d67908 100644 --- a/src/corelib/itemmodels/qabstractproxymodel.h +++ b/src/corelib/itemmodels/qabstractproxymodel.h @@ -42,11 +42,10 @@ #include +QT_REQUIRE_CONFIG(proxymodel); + QT_BEGIN_NAMESPACE - -#ifndef QT_NO_PROXYMODEL - class QAbstractProxyModelPrivate; class QItemSelection; @@ -112,8 +111,6 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_sourceModelDestroyed()) }; -#endif // QT_NO_PROXYMODEL - QT_END_NAMESPACE #endif // QABSTRACTPROXYMODEL_H diff --git a/src/corelib/itemmodels/qabstractproxymodel_p.h b/src/corelib/itemmodels/qabstractproxymodel_p.h index 929bf1eb75..3a9f33baba 100644 --- a/src/corelib/itemmodels/qabstractproxymodel_p.h +++ b/src/corelib/itemmodels/qabstractproxymodel_p.h @@ -54,7 +54,7 @@ #include "private/qabstractitemmodel_p.h" -#ifndef QT_NO_PROXYMODEL +QT_REQUIRE_CONFIG(proxymodel); QT_BEGIN_NAMESPACE @@ -71,6 +71,4 @@ public: QT_END_NAMESPACE -#endif // QT_NO_PROXYMODEL - #endif // QABSTRACTPROXYMODEL_P_H diff --git a/src/corelib/itemmodels/qidentityproxymodel.cpp b/src/corelib/itemmodels/qidentityproxymodel.cpp index 7c306799d0..e984ec194e 100644 --- a/src/corelib/itemmodels/qidentityproxymodel.cpp +++ b/src/corelib/itemmodels/qidentityproxymodel.cpp @@ -38,9 +38,6 @@ ****************************************************************************/ #include "qidentityproxymodel.h" - -#ifndef QT_NO_IDENTITYPROXYMODEL - #include "qitemselectionmodel.h" #include @@ -616,5 +613,3 @@ void QIdentityProxyModelPrivate::_q_sourceRowsRemoved(const QModelIndex &parent, QT_END_NAMESPACE #include "moc_qidentityproxymodel.cpp" - -#endif // QT_NO_IDENTITYPROXYMODEL diff --git a/src/corelib/itemmodels/qidentityproxymodel.h b/src/corelib/itemmodels/qidentityproxymodel.h index d2b1ed9498..3e6f5e4c48 100644 --- a/src/corelib/itemmodels/qidentityproxymodel.h +++ b/src/corelib/itemmodels/qidentityproxymodel.h @@ -43,7 +43,7 @@ #include -#ifndef QT_NO_IDENTITYPROXYMODEL +QT_REQUIRE_CONFIG(identityproxymodel); QT_BEGIN_NAMESPACE @@ -110,7 +110,5 @@ private: QT_END_NAMESPACE -#endif // QT_NO_IDENTITYPROXYMODEL - #endif // QIDENTITYPROXYMODEL_H diff --git a/src/corelib/itemmodels/qitemselectionmodel.h b/src/corelib/itemmodels/qitemselectionmodel.h index 091c5a21a5..63e5f0ca9c 100644 --- a/src/corelib/itemmodels/qitemselectionmodel.h +++ b/src/corelib/itemmodels/qitemselectionmodel.h @@ -47,6 +47,8 @@ #include #include +QT_REQUIRE_CONFIG(itemmodel); + QT_BEGIN_NAMESPACE class Q_CORE_EXPORT QItemSelectionRange diff --git a/src/corelib/itemmodels/qitemselectionmodel_p.h b/src/corelib/itemmodels/qitemselectionmodel_p.h index dfc0387563..187d4a2c1d 100644 --- a/src/corelib/itemmodels/qitemselectionmodel_p.h +++ b/src/corelib/itemmodels/qitemselectionmodel_p.h @@ -53,6 +53,8 @@ #include "private/qobject_p.h" +QT_REQUIRE_CONFIG(itemmodel); + QT_BEGIN_NAMESPACE class QItemSelectionModelPrivate: public QObjectPrivate diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp index 220c6be79e..78093727b8 100644 --- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp +++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp @@ -38,9 +38,6 @@ ****************************************************************************/ #include "qsortfilterproxymodel.h" - -#ifndef QT_NO_SORTFILTERPROXYMODEL - #include "qitemselectionmodel.h" #include #include @@ -2883,5 +2880,3 @@ QItemSelection QSortFilterProxyModel::mapSelectionFromSource(const QItemSelectio QT_END_NAMESPACE #include "moc_qsortfilterproxymodel.cpp" - -#endif // QT_NO_SORTFILTERPROXYMODEL diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.h b/src/corelib/itemmodels/qsortfilterproxymodel.h index 196dab2770..907ceb8e6d 100644 --- a/src/corelib/itemmodels/qsortfilterproxymodel.h +++ b/src/corelib/itemmodels/qsortfilterproxymodel.h @@ -41,11 +41,10 @@ #define QSORTFILTERPROXYMODEL_H #include - -#ifndef QT_NO_SORTFILTERPROXYMODEL - #include +QT_REQUIRE_CONFIG(sortfilterproxymodel); + QT_BEGIN_NAMESPACE @@ -198,6 +197,4 @@ private: QT_END_NAMESPACE -#endif // QT_NO_SORTFILTERPROXYMODEL - #endif // QSORTFILTERPROXYMODEL_H diff --git a/src/corelib/itemmodels/qstringlistmodel.cpp b/src/corelib/itemmodels/qstringlistmodel.cpp index bcfd88fb19..567e6fa35e 100644 --- a/src/corelib/itemmodels/qstringlistmodel.cpp +++ b/src/corelib/itemmodels/qstringlistmodel.cpp @@ -47,8 +47,6 @@ #include -#ifndef QT_NO_STRINGLISTMODEL - QT_BEGIN_NAMESPACE /*! @@ -329,5 +327,3 @@ Qt::DropActions QStringListModel::supportedDropActions() const QT_END_NAMESPACE #include "moc_qstringlistmodel.cpp" - -#endif // QT_NO_STRINGLISTMODEL diff --git a/src/corelib/itemmodels/qstringlistmodel.h b/src/corelib/itemmodels/qstringlistmodel.h index 38da1022ea..a40c13ae40 100644 --- a/src/corelib/itemmodels/qstringlistmodel.h +++ b/src/corelib/itemmodels/qstringlistmodel.h @@ -43,11 +43,10 @@ #include #include +QT_REQUIRE_CONFIG(stringlistmodel); + QT_BEGIN_NAMESPACE - -#ifndef QT_NO_STRINGLISTMODEL - class Q_CORE_EXPORT QStringListModel : public QAbstractListModel { Q_OBJECT @@ -78,8 +77,6 @@ private: QStringList lst; }; -#endif // QT_NO_STRINGLISTMODEL - QT_END_NAMESPACE #endif // QSTRINGLISTMODEL_H diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index 518381712a..fc40668c9a 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -61,7 +61,6 @@ # include "qbitarray.h" # include "qurl.h" # include "qvariant.h" -# include "qabstractitemmodel.h" # include "qjsonvalue.h" # include "qjsonobject.h" # include "qjsonarray.h" @@ -69,6 +68,10 @@ # include "qbytearraylist.h" #endif +#if QT_CONFIG(itemmodel) +# include "qabstractitemmodel.h" +#endif + #ifndef QT_NO_GEOM_VARIANT # include "qsize.h" # include "qpoint.h" @@ -1349,8 +1352,10 @@ bool QMetaType::save(QDataStream &stream, int type, const void *data) case QMetaType::Void: case QMetaType::VoidStar: case QMetaType::QObjectStar: +#if QT_CONFIG(itemmodel) case QMetaType::QModelIndex: case QMetaType::QPersistentModelIndex: +#endif case QMetaType::QJsonValue: case QMetaType::QJsonObject: case QMetaType::QJsonArray: @@ -1573,8 +1578,10 @@ bool QMetaType::load(QDataStream &stream, int type, void *data) case QMetaType::Void: case QMetaType::VoidStar: case QMetaType::QObjectStar: +#if QT_CONFIG(itemmodel) case QMetaType::QModelIndex: case QMetaType::QPersistentModelIndex: +#endif case QMetaType::QJsonValue: case QMetaType::QJsonObject: case QMetaType::QJsonArray: diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 4674efe568..a0969ee908 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -89,6 +89,14 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId(); #define QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(F)\ F(VoidStar, 31, void*) \ +#if QT_CONFIG(itemmodel) +#define QT_FOR_EACH_STATIC_ITEMMODEL_CLASS(F)\ + F(QModelIndex, 42, QModelIndex) \ + F(QPersistentModelIndex, 50, QPersistentModelIndex) +#else +#define QT_FOR_EACH_STATIC_ITEMMODEL_CLASS(F) +#endif + #define QT_FOR_EACH_STATIC_CORE_CLASS(F)\ F(QChar, 7, QChar) \ F(QString, 10, QString) \ @@ -112,13 +120,12 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId(); F(QEasingCurve, 29, QEasingCurve) \ F(QUuid, 30, QUuid) \ F(QVariant, 41, QVariant) \ - F(QModelIndex, 42, QModelIndex) \ F(QRegularExpression, 44, QRegularExpression) \ F(QJsonValue, 45, QJsonValue) \ F(QJsonObject, 46, QJsonObject) \ F(QJsonArray, 47, QJsonArray) \ F(QJsonDocument, 48, QJsonDocument) \ - F(QPersistentModelIndex, 50, QPersistentModelIndex) \ + QT_FOR_EACH_STATIC_ITEMMODEL_CLASS(F) #define QT_FOR_EACH_STATIC_CORE_POINTER(F)\ F(QObjectStar, 39, QObject*) diff --git a/src/corelib/kernel/qmetatype_p.h b/src/corelib/kernel/qmetatype_p.h index 0bf6bcb922..cef20a5d12 100644 --- a/src/corelib/kernel/qmetatype_p.h +++ b/src/corelib/kernel/qmetatype_p.h @@ -201,8 +201,6 @@ template<> struct TypeDefinition { static const bool IsAvailable = f template<> struct TypeDefinition { static const bool IsAvailable = false; }; template<> struct TypeDefinition { static const bool IsAvailable = false; }; template<> struct TypeDefinition { static const bool IsAvailable = false; }; -template<> struct TypeDefinition { static const bool IsAvailable = false; }; -template<> struct TypeDefinition { static const bool IsAvailable = false; }; template<> struct TypeDefinition { static const bool IsAvailable = false; }; template<> struct TypeDefinition { static const bool IsAvailable = false; }; #endif diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index c3c36e05d7..b3a86576af 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -56,8 +56,10 @@ #include "qurl.h" #include "qlocale.h" #include "quuid.h" -#ifndef QT_BOOTSTRAPPED +#if QT_CONFIG(itemmodel) #include "qabstractitemmodel.h" +#endif +#ifndef QT_BOOTSTRAPPED #include "qjsonvalue.h" #include "qjsonobject.h" #include "qjsonarray.h" @@ -393,6 +395,8 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) return false; } break; +#endif // QT_BOOTSTRAPPED +#if QT_CONFIG(itemmodel) case QVariant::ModelIndex: switch (d->type) { case QVariant::PersistentModelIndex: @@ -411,7 +415,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) return false; } break; -#endif // QT_BOOTSTRAPPED +#endif // QT_CONFIG(itemmodel) case QVariant::String: { QString *str = static_cast(result); switch (d->type) { @@ -1952,12 +1956,6 @@ QVariant::QVariant(const QRegularExpression &re) QVariant::QVariant(const QUuid &uuid) : d(Uuid) { v_construct(&d, uuid); } -QVariant::QVariant(const QModelIndex &modelIndex) - : d(ModelIndex) -{ v_construct(&d, modelIndex); } -QVariant::QVariant(const QPersistentModelIndex &modelIndex) - : d(PersistentModelIndex) -{ v_construct(&d, modelIndex); } QVariant::QVariant(const QJsonValue &jsonValue) : d(QMetaType::QJsonValue) { v_construct(&d, jsonValue); } @@ -1971,6 +1969,14 @@ QVariant::QVariant(const QJsonDocument &jsonDocument) : d(QMetaType::QJsonDocument) { v_construct(&d, jsonDocument); } #endif // QT_BOOTSTRAPPED +#if QT_CONFIG(itemmodel) +QVariant::QVariant(const QModelIndex &modelIndex) + : d(ModelIndex) +{ v_construct(&d, modelIndex); } +QVariant::QVariant(const QPersistentModelIndex &modelIndex) + : d(PersistentModelIndex) +{ v_construct(&d, modelIndex); } +#endif /*! Returns the storage type of the value stored in the variant. @@ -2668,21 +2674,7 @@ QRegularExpression QVariant::toRegularExpression() const } #endif // QT_CONFIG(regularexpression) -#ifndef QT_BOOTSTRAPPED -/*! - \since 5.0 - - Returns the variant as a QUuid if the variant has type() - \l QMetaType::QUuid, \l QMetaType::QByteArray or \l QMetaType::QString; - otherwise returns a default-constructed QUuid. - - \sa canConvert(), convert() -*/ -QUuid QVariant::toUuid() const -{ - return qVariantToHelper(d, handlerManager); -} - +#if QT_CONFIG(itemmodel) /*! \since 5.0 @@ -2708,6 +2700,22 @@ QPersistentModelIndex QVariant::toPersistentModelIndex() const { return qVariantToHelper(d, handlerManager); } +#endif // QT_CONFIG(itemmodel) + +#ifndef QT_BOOTSTRAPPED +/*! + \since 5.0 + + Returns the variant as a QUuid if the variant has type() + \l QMetaType::QUuid, \l QMetaType::QByteArray or \l QMetaType::QString; + otherwise returns a default-constructed QUuid. + + \sa canConvert(), convert() +*/ +QUuid QVariant::toUuid() const +{ + return qVariantToHelper(d, handlerManager); +} /*! \since 5.0 @@ -3182,9 +3190,11 @@ bool QVariant::canConvert(int targetTypeId) const if (d.type == targetTypeId) return true; +#if QT_CONFIG(itemmodel) if ((targetTypeId == QMetaType::QModelIndex && d.type == QMetaType::QPersistentModelIndex) || (targetTypeId == QMetaType::QPersistentModelIndex && d.type == QMetaType::QModelIndex)) return true; +#endif if (targetTypeId == QMetaType::QVariantList && (d.type == QMetaType::QVariantList diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index 361768ef00..9a5fc63d03 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -165,8 +165,10 @@ class Q_CORE_EXPORT QVariant Hash = QMetaType::QVariantHash, EasingCurve = QMetaType::QEasingCurve, Uuid = QMetaType::QUuid, +#if QT_CONFIG(itemmodel) ModelIndex = QMetaType::QModelIndex, PersistentModelIndex = QMetaType::QPersistentModelIndex, +#endif LastCoreType = QMetaType::LastCoreType, Font = QMetaType::QFont, @@ -255,13 +257,15 @@ class Q_CORE_EXPORT QVariant QVariant(const QUrl &url); QVariant(const QEasingCurve &easing); QVariant(const QUuid &uuid); - QVariant(const QModelIndex &modelIndex); - QVariant(const QPersistentModelIndex &modelIndex); QVariant(const QJsonValue &jsonValue); QVariant(const QJsonObject &jsonObject); QVariant(const QJsonArray &jsonArray); QVariant(const QJsonDocument &jsonDocument); #endif // QT_BOOTSTRAPPED +#if QT_CONFIG(itemmodel) + QVariant(const QModelIndex &modelIndex); + QVariant(const QPersistentModelIndex &modelIndex); +#endif QVariant& operator=(const QVariant &other); #ifdef Q_COMPILER_RVALUE_REFS @@ -329,13 +333,15 @@ class Q_CORE_EXPORT QVariant QUrl toUrl() const; QEasingCurve toEasingCurve() const; QUuid toUuid() const; - QModelIndex toModelIndex() const; - QPersistentModelIndex toPersistentModelIndex() const; QJsonValue toJsonValue() const; QJsonObject toJsonObject() const; QJsonArray toJsonArray() const; QJsonDocument toJsonDocument() const; #endif // QT_BOOTSTRAPPED +#if QT_CONFIG(itemmodel) + QModelIndex toModelIndex() const; + QPersistentModelIndex toPersistentModelIndex() const; +#endif #ifndef QT_NO_DATASTREAM void load(QDataStream &ds); From 79493a3ee129c014298c6ef694415b8f0fffd74b Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 9 Jan 2018 18:21:45 -0800 Subject: [PATCH 12/51] Make QCOMPARE(-inf, -inf) and QCOMPARE(NaN, NaN) succeed This will make two floating points containing NaN compare as equal, instead of the regular nan != nan IEEE behavior (which isn't very useful in a unit-test framework). Note that this does not apply to indirect comparisons, for example via QVariant. Change-Id: I39332e0a867442d58082fffd150851acfdd18c23 Reviewed-by: Lars Knoll --- src/testlib/qtestcase.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index d03eb4c2c0..adf4b9e1ef 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -75,6 +75,7 @@ #include #endif +#include #include #include @@ -2443,7 +2444,16 @@ bool QTest::qCompare(float const &t1, float const &t2, const char *actual, const bool QTest::qCompare(double const &t1, double const &t2, const char *actual, const char *expected, const char *file, int line) { - return compare_helper(qFuzzyCompare(t1, t2), "Compared doubles are not the same (fuzzy compare)", + bool equal = false; + int cl1 = std::fpclassify(t1); + int cl2 = std::fpclassify(t2); + if (cl1 == FP_INFINITE) + equal = ((t1 < 0) == (t2 < 0)) && cl2 == FP_INFINITE; + else if (cl1 == FP_NAN) + equal = (cl2 == FP_NAN); + else + equal = qFuzzyCompare(t1, t2); + return compare_helper(equal, "Compared doubles are not the same (fuzzy compare)", toString(t1), toString(t2), actual, expected, file, line); } From d3b6ef6ccfa93a93d7a80d71bc2779f4ca7600f6 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sat, 17 Feb 2018 10:06:42 -0800 Subject: [PATCH 13/51] QFile::rename: fix the error message if renaming a file by copy fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The QFile out variable cannot be open because if out.open() succeeded, we could never reach this line. Instead, we want to capture *why* either the source or the destination failed to open. Task-number: QTBUG-66445 Change-Id: I940917d6763842499b18fffd15142f231bf34a47 Reviewed-by: Jędrzej Nowacki --- src/corelib/io/qfile.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index 33b0b2eb66..3166fa1b83 100644 --- a/src/corelib/io/qfile.cpp +++ b/src/corelib/io/qfile.cpp @@ -676,8 +676,11 @@ QFile::rename(const QString &newName) return !error; } close(); + d->setError(QFile::RenameError, + tr("Cannot open destination file: %1").arg(out.errorString())); + } else { + d->setError(QFile::RenameError, errorString()); } - d->setError(QFile::RenameError, out.isOpen() ? errorString() : out.errorString()); } return false; } From f4435d2d5cddc763ac9fb3d0b1b97e551ea463e1 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Tue, 20 Mar 2018 23:27:36 +0100 Subject: [PATCH 14/51] offscreen: Check that native interface is valid before using it If the offscreen platform plugin is used on Windows then it can end up crashing since there is no native interface. This prevents a crash from occurring when these functions are called. Change-Id: I526fc0703771fa5f85b26d182ad3b15ef1a3ada5 Reviewed-by: Friedemann Kleint --- src/plugins/styles/windowsvista/qwindowsxpstyle.cpp | 3 ++- src/widgets/kernel/qapplication_p.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp index ff27cab98a..733b3a9e9c 100644 --- a/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp +++ b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp @@ -122,7 +122,8 @@ static inline HDC hdcForWidgetBackingStore(const QWidget *widget) { if (QBackingStore *backingStore = backingStoreForWidget(widget)) { QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); - return static_cast(nativeInterface->nativeResourceForBackingStore(QByteArrayLiteral("getDC"), backingStore)); + if (nativeInterface) + return static_cast(nativeInterface->nativeResourceForBackingStore(QByteArrayLiteral("getDC"), backingStore)); } return 0; } diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h index 9983cc7d9e..019fad3fc3 100644 --- a/src/widgets/kernel/qapplication_p.h +++ b/src/widgets/kernel/qapplication_p.h @@ -242,7 +242,7 @@ public: static HWND getHWNDForWidget(const QWidget *widget) { if (QWindow *window = windowForWidget(widget)) - if (window->handle()) + if (window->handle() && QGuiApplication::platformNativeInterface()) return static_cast (QGuiApplication::platformNativeInterface()-> nativeResourceForWindow(QByteArrayLiteral("handle"), window)); return 0; From ee54df0311516b07d04ada71c6c5e81827cb0b38 Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Thu, 15 Feb 2018 02:01:39 +0000 Subject: [PATCH 15/51] Support GLX_NV_robustness_video_memory_purge in XCB-GLX Nvidia doesn't handle suspend very well in Linux and textures get corrupted. To handle this Nvidia has a bespoke extension to query when this has happened. This patch checks if graphics have been reset and invalidates the surface. Task-number: QTBUG-56610 Change-Id: I0b97d539ce6cc2b9cfe41c71bf6efd4f68496cd6 Reviewed-by: Laszlo Agocs --- .../xcb_glx/qglxintegration.cpp | 64 ++++++++++++++++--- .../gl_integrations/xcb_glx/qglxintegration.h | 2 + 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp index 21024385b0..86ca7afa12 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp @@ -86,6 +86,22 @@ typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXC #define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002 #endif +#ifndef GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB +#define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004 +#endif + +#ifndef GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB +#define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256 +#endif + +#ifndef GLX_LOSE_CONTEXT_ON_RESET_ARB +#define GLX_LOSE_CONTEXT_ON_RESET_ARB 0x8252 +#endif + +#ifndef GLX_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV +#define GLX_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV 0x20F7 +#endif + static Window createDummyWindow(Display *dpy, XVisualInfo *visualInfo, int screenNumber, Window rootWin) { Colormap cmap = XCreateColormap(dpy, rootWin, visualInfo->visual, AllocNone); @@ -179,6 +195,8 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat , m_isPBufferCurrent(false) , m_swapInterval(-1) , m_ownsContext(nativeHandle.isNull()) + , m_getGraphicsResetStatus(0) + , m_lost(false) { if (nativeHandle.isNull()) init(screen, share); @@ -214,6 +232,8 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share) glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB"); const bool supportsProfiles = glxExt.contains("GLX_ARB_create_context_profile"); + const bool supportsRobustness = glxExt.contains("GLX_ARB_create_context_robustness"); + const bool supportsVideoMemoryPurge = glxExt.contains("GLX_NV_robustness_video_memory_purge"); // Use glXCreateContextAttribsARB if available // Also, GL ES context creation requires GLX_EXT_create_context_es2_profile @@ -266,6 +286,9 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share) int flags = 0; + if (supportsRobustness) + flags |= GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB; + if (m_format.testOption(QSurfaceFormat::DebugContext)) flags |= GLX_CONTEXT_DEBUG_BIT_ARB; @@ -279,14 +302,33 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share) contextAttributes << GLX_CONTEXT_PROFILE_MASK_ARB << GLX_CONTEXT_ES2_PROFILE_BIT_EXT; } - contextAttributes << None; + if (supportsRobustness && supportsVideoMemoryPurge) { + QVector contextAttributesWithNvidiaReset = contextAttributes; - m_context = glXCreateContextAttribsARB(m_display, config, m_shareContext, true, contextAttributes.data()); - if (!m_context && m_shareContext) { - // re-try without a shared glx context - m_context = glXCreateContextAttribsARB(m_display, config, 0, true, contextAttributes.data()); - if (m_context) - m_shareContext = 0; + contextAttributesWithNvidiaReset << GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB << GLX_LOSE_CONTEXT_ON_RESET_ARB; + contextAttributesWithNvidiaReset << GLX_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV << GL_TRUE; + + contextAttributesWithNvidiaReset << None; + m_context = glXCreateContextAttribsARB(m_display, config, m_shareContext, true, contextAttributesWithNvidiaReset.data()); + if (!m_context && m_shareContext) { + // re-try without a shared glx context + m_context = glXCreateContextAttribsARB(m_display, config, 0, true, contextAttributesWithNvidiaReset.data()); + if (m_context) + m_shareContext = 0; + } + } + + if (m_context) { + m_getGraphicsResetStatus = reinterpret_cast(getProcAddress("glGetGraphicsResetStatusARB")); + } else { + contextAttributes << None; + m_context = glXCreateContextAttribsARB(m_display, config, m_shareContext, true, contextAttributes.data()); + if (!m_context && m_shareContext) { + // re-try without a shared glx context + m_context = glXCreateContextAttribsARB(m_display, config, 0, true, contextAttributes.data()); + if (m_context) + m_shareContext = 0; + } } } } @@ -494,6 +536,12 @@ bool QGLXContext::makeCurrent(QPlatformSurface *surface) QXcbWindow *window = static_cast(surface); glxDrawable = window->xcb_window(); success = glXMakeCurrent(m_display, glxDrawable, m_context); + m_lost = false; + if (m_getGraphicsResetStatus && m_getGraphicsResetStatus() != GL_NO_ERROR) { + m_lost = true; + // Drop the surface. Will recreate on the next makeCurrent. + window->invalidateSurface(); + } } else if (surfaceClass == QSurface::Offscreen) { m_isPBufferCurrent = true; QGLXPbuffer *pbuffer = static_cast(surface); @@ -609,7 +657,7 @@ bool QGLXContext::isSharing() const bool QGLXContext::isValid() const { - return m_context != 0; + return m_context != 0 && !m_lost; } bool QGLXContext::m_queriedDummyContext = false; diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h index f6372582db..be9d3f5dcb 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h @@ -89,6 +89,8 @@ private: bool m_isPBufferCurrent; int m_swapInterval; bool m_ownsContext; + GLenum (APIENTRY * m_getGraphicsResetStatus)(); + bool m_lost; static bool m_queriedDummyContext; static bool m_supportsThreading; }; From 58b373c9e3c0a7307e3fbafeb5ad710088b8e685 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 2 Mar 2018 12:30:44 +0100 Subject: [PATCH 16/51] Make sure $$relative_path() uses an absolute path as its first arg Thanks to QTBUG-61373, this qmake function was called with /usr/local/5.10.1 as baseDir, which isn't absolute, leading to an assertion failure. We could raise the error within qmake but it proved easier to simply resolve any non-absolute baseDir using PWD, before trying to use it as an absolute path. Did the same for $$absolute_path(). Documented both. Adjusted the assert that caught this to report any non-absolute path that upsets it. Added simple tests, fixed an existing test. Task-number: QTBUG-66156 Change-Id: Icfef2e2f5b236e071177c9beffa38d71bf404292 Reviewed-by: Oswald Buddenhagen --- qmake/doc/src/qmake-manual.qdoc | 15 +++++++++++---- qmake/library/ioutils.cpp | 2 +- qmake/library/qmakebuiltins.cpp | 8 ++++++-- tests/auto/tools/qmakelib/evaltest.cpp | 16 ++++++++++++++-- 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc index cc3b73418b..35f24e1793 100644 --- a/qmake/doc/src/qmake-manual.qdoc +++ b/qmake/doc/src/qmake-manual.qdoc @@ -2913,7 +2913,8 @@ Returns the absolute path of \c path. If \c base is not specified, uses the current directory as the base - directory. + directory. If it is a relative path, it is resolved relative to the current + directory before use. For example, the following call returns the string \c {"/home/johndoe/myproject/readme.txt"}: @@ -3152,9 +3153,15 @@ \section2 relative_path(filePath[, base]) - Returns the path to \c filePath relative to \c base. If \c base is not - specified, it is the current project directory. This function is a wrapper - around QDir::relativeFilePath. + Returns the path to \c filePath relative to \c base. + + If \c base is not specified, it is the current project + directory. If it is relative, it is resolved relative to the + current project directory before use. + + If \c filePath is relative, it is first resolved against the base + directory; in that case, this function effectively acts as + $$clean_path(). See also \l{absolute_path(path[, base])}{absolute_path()}, \l{clean_path(path)}{clean_path()}. diff --git a/qmake/library/ioutils.cpp b/qmake/library/ioutils.cpp index afd41912fe..cb4aa5e74d 100644 --- a/qmake/library/ioutils.cpp +++ b/qmake/library/ioutils.cpp @@ -103,7 +103,7 @@ QString IoUtils::resolvePath(const QString &baseDir, const QString &fileName) return QDir::cleanPath(fileName); #ifdef Q_OS_WIN // Add drive to otherwise-absolute path: if (fileName.at(0).unicode() == '/' || fileName.at(0).unicode() == '\\') { - Q_ASSERT(isAbsolutePath(baseDir)); + Q_ASSERT_X(isAbsolutePath(baseDir), "IoUtils::resolvePath", qUtf8Printable(baseDir)); return QDir::cleanPath(baseDir.left(2) + fileName); } #endif // Q_OS_WIN diff --git a/qmake/library/qmakebuiltins.cpp b/qmake/library/qmakebuiltins.cpp index 83c3d1d643..0a83b9b930 100644 --- a/qmake/library/qmakebuiltins.cpp +++ b/qmake/library/qmakebuiltins.cpp @@ -1178,7 +1178,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand( evalError(fL1S("absolute_path(path[, base]) requires one or two arguments.")); } else { QString arg = args.at(0).toQString(m_tmp1); - QString baseDir = args.count() > 1 ? args.at(1).toQString(m_tmp2) : currentDirectory(); + QString baseDir = args.count() > 1 + ? IoUtils::resolvePath(currentDirectory(), args.at(1).toQString(m_tmp2)) + : currentDirectory(); QString rstr = arg.isEmpty() ? baseDir : IoUtils::resolvePath(baseDir, arg); ret << (rstr.isSharedWith(m_tmp1) ? args.at(0) @@ -1192,7 +1194,9 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand( evalError(fL1S("relative_path(path[, base]) requires one or two arguments.")); } else { QString arg = args.at(0).toQString(m_tmp1); - QString baseDir = args.count() > 1 ? args.at(1).toQString(m_tmp2) : currentDirectory(); + QString baseDir = args.count() > 1 + ? IoUtils::resolvePath(currentDirectory(), args.at(1).toQString(m_tmp2)) + : currentDirectory(); QString absArg = arg.isEmpty() ? baseDir : IoUtils::resolvePath(baseDir, arg); QString rstr = QDir(baseDir).relativeFilePath(absArg); ret << (rstr.isSharedWith(m_tmp1) ? args.at(0) : ProString(rstr).setSource(args.at(0))); diff --git a/tests/auto/tools/qmakelib/evaltest.cpp b/tests/auto/tools/qmakelib/evaltest.cpp index 786b9e72f1..abb7a1a964 100644 --- a/tests/auto/tools/qmakelib/evaltest.cpp +++ b/tests/auto/tools/qmakelib/evaltest.cpp @@ -1604,6 +1604,12 @@ void tst_qmakelib::addReplaceFunctions(const QString &qindir) << "" << true; + QTest::newRow("$$absolute_path(): relative file & relative path") + << "VAR = $$absolute_path(dir/file.ext, some/where)" + << "VAR = " + qindir + "/some/where/dir/file.ext" + << "" + << true; + QTest::newRow("$$absolute_path(): file & path") << "VAR = $$absolute_path(dir/file.ext, " EVAL_DRIVE "/root/sub)" << "VAR = " EVAL_DRIVE "/root/sub/dir/file.ext" @@ -1642,6 +1648,12 @@ void tst_qmakelib::addReplaceFunctions(const QString &qindir) << "" << true; + QTest::newRow("$$relative_path(): relative file & relative path") + << "VAR = $$relative_path(dir/file.ext, some/where)" + << "VAR = dir/file.ext" + << "" + << true; + QTest::newRow("$$relative_path(): relative file to empty") << "VAR = $$relative_path(dir/..)" << "VAR = ." @@ -2752,9 +2764,9 @@ void tst_qmakelib::proEval_data() // Raw data leak with empty file name. Verify with Valgrind or asan. QTest::newRow("QTBUG-54550") - << "FULL = /there/is\n" + << "FULL = " EVAL_DRIVE "/there/is\n" "VAR = $$absolute_path(, $$FULL/nothing/here/really)" - << "VAR = /there/is/nothing/here/really" + << "VAR = " EVAL_DRIVE "/there/is/nothing/here/really" << "" << true; } From 141582505f0132a1acb9f60de24b3d35552d8e5c Mon Sep 17 00:00:00 2001 From: Kari Oikarinen Date: Wed, 21 Mar 2018 12:08:33 +0200 Subject: [PATCH 17/51] Stabilize tst_QGraphicsView::acceptMouseDoubleClickEvent This test has been flaky on openSUSE in CI. The problem was that the window is sometimes resized or removed while processing events after adding the rectangle item to the QGraphicsScene. When the same mouse event is reused again, it uses wrong screen coordinates. QGraphicsScene handling of mouse events then looks for items under cursor at the wrong coordinates, does not find any items and thus doesn't accept the mouse event. Fix by using QTest API for simulating mouse events. Also wait for changed signal rather than blindly running one iteration of event loop. Task-number: QTBUG-67212 Task-number: QTBUG-66216 Change-Id: I968f9470c6f8803d01cebeda6f12ad76b4fd5293 Reviewed-by: Gatis Paeglis --- .../qgraphicsview/tst_qgraphicsview.cpp | 26 ++++++------------- 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp index 3d5df7506d..10129eb10c 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp @@ -2986,19 +2986,14 @@ void tst_QGraphicsView::acceptMousePressEvent() view.show(); QVERIFY(QTest::qWaitForWindowExposed(&view)); - QMouseEvent event(QEvent::MouseButtonPress, - view.viewport()->rect().center(), - view.viewport()->mapToGlobal(view.viewport()->rect().center()), - Qt::LeftButton, 0, 0); - event.setAccepted(false); - QApplication::sendEvent(view.viewport(), &event); + QTest::mouseClick(view.viewport(), Qt::LeftButton); QVERIFY(!view.pressAccepted); + QSignalSpy spy(&scene, &QGraphicsScene::changed); scene.addRect(0, 0, 2000, 2000)->setFlag(QGraphicsItem::ItemIsMovable); + QVERIFY(spy.wait()); - qApp->processEvents(); // ensure scene rect is updated - - QApplication::sendEvent(view.viewport(), &event); + QTest::mouseClick(view.viewport(), Qt::LeftButton); QVERIFY(view.pressAccepted); } @@ -3010,19 +3005,14 @@ void tst_QGraphicsView::acceptMouseDoubleClickEvent() view.show(); QVERIFY(QTest::qWaitForWindowExposed(&view)); - QMouseEvent event(QEvent::MouseButtonDblClick, - view.viewport()->rect().center(), - view.viewport()->mapToGlobal(view.viewport()->rect().center()), - Qt::LeftButton, 0, 0); - event.setAccepted(false); - QApplication::sendEvent(view.viewport(), &event); + QTest::mouseDClick(view.viewport(), Qt::LeftButton); QVERIFY(!view.doubleClickAccepted); + QSignalSpy spy(&scene, &QGraphicsScene::changed); scene.addRect(0, 0, 2000, 2000)->setFlag(QGraphicsItem::ItemIsMovable); + QVERIFY(spy.wait()); - qApp->processEvents(); // ensure scene rect is updated - - QApplication::sendEvent(view.viewport(), &event); + QTest::mouseDClick(view.viewport(), Qt::LeftButton); QVERIFY(view.doubleClickAccepted); } From 14157a1a3e1d934e4892f469abc4e2cdf4e65f52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pasi=20Pet=C3=A4j=C3=A4j=C3=A4rvi?= Date: Mon, 19 Feb 2018 11:32:23 +0200 Subject: [PATCH 18/51] Add env variable to set QNX screen debugging information Enables different QNX Screen graphics system information as overlay. Following are valid options for the env variable: * fps, posts, blits, updates, cpu_time, gpu_time, statistics More info: http://www.qnx.com/developers/docs/7.0.0/index.html#com.qnx.doc.screen/topic/group__screen__debugging_1Screen_Debug_Graph_Types.html Change-Id: I8cbee44de31bb2aaf3892a063769f4740027242b Reviewed-by: Adam Treat Reviewed-by: James McDonnell --- src/plugins/platforms/qnx/qqnxwindow.cpp | 41 ++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp index 38b61fd782..4a547aa158 100644 --- a/src/plugins/platforms/qnx/qqnxwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxwindow.cpp @@ -63,6 +63,18 @@ QT_BEGIN_NAMESPACE +#define DECLARE_DEBUG_VAR(variable) \ + static bool debug_ ## variable() \ + { static bool value = qgetenv("QNX_SCREEN_DEBUG").contains(QT_STRINGIFY(variable)); return value; } +DECLARE_DEBUG_VAR(fps) +DECLARE_DEBUG_VAR(posts) +DECLARE_DEBUG_VAR(blits) +DECLARE_DEBUG_VAR(updates) +DECLARE_DEBUG_VAR(cpu_time) +DECLARE_DEBUG_VAR(gpu_time) +DECLARE_DEBUG_VAR(statistics) +#undef DECLARE_DEBUG_VAR + /*! \class QQnxWindow \brief The QQnxWindow is the base class of the various classes used as instances of @@ -211,6 +223,35 @@ QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context, bool needRootW // it'll cause us not to join a group (the app will presumably join at some future time). if (windowGroup.isValid() && windowGroup.canConvert()) joinWindowGroup(windowGroup.toByteArray()); + + int debug = 0; + if (Q_UNLIKELY(debug_fps())) { + debug |= SCREEN_DEBUG_GRAPH_FPS; + } + if (Q_UNLIKELY(debug_posts())) { + debug |= SCREEN_DEBUG_GRAPH_POSTS; + } + if (Q_UNLIKELY(debug_blits())) { + debug |= SCREEN_DEBUG_GRAPH_BLITS; + } + if (Q_UNLIKELY(debug_updates())) { + debug |= SCREEN_DEBUG_GRAPH_UPDATES; + } + if (Q_UNLIKELY(debug_cpu_time())) { + debug |= SCREEN_DEBUG_GRAPH_CPU_TIME; + } + if (Q_UNLIKELY(debug_gpu_time())) { + debug |= SCREEN_DEBUG_GRAPH_GPU_TIME; + } + if (Q_UNLIKELY(debug_statistics())) { + debug = SCREEN_DEBUG_STATISTICS; + } + + if (debug > 0) { + Q_SCREEN_CHECKERROR(screen_set_window_property_iv(nativeHandle(), SCREEN_PROPERTY_DEBUG, &debug), + "Could not set SCREEN_PROPERTY_DEBUG"); + qWindowDebug() << "window SCREEN_PROPERTY_DEBUG= " << debug; + } } QQnxWindow::~QQnxWindow() From 3691c411159ff4d7cf7601dbb87dbf43cc8d46d4 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 13 Mar 2018 18:04:30 -0700 Subject: [PATCH 19/51] QMacStyle: Make CocoaControl a full type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit And one small code clean-up. Change-Id: I57c71ce2e18c95529ee45ba4fdfc68e21209e384 Reviewed-by: Morten Johan Sørvig --- src/plugins/styles/mac/qmacstyle_mac.mm | 118 ++++++++++++--------- src/plugins/styles/mac/qmacstyle_mac_p_p.h | 12 ++- 2 files changed, 80 insertions(+), 50 deletions(-) diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index 9e8af78a8e..79109dbbfe 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -1210,13 +1210,13 @@ void QMacStylePrivate::drawFocusRing(QPainter *p, const QRect &targetRect, int h QPainterPath focusRingPath; qreal hOffset = 0.0; qreal vOffset = 0.0; - switch (cw.first) { + switch (cw.type) { case Button_CheckBox: { - const auto cbInnerRadius = (cw.second == QStyleHelper::SizeMini ? 2.0 : 3.0); - const auto cbSize = cw.second == QStyleHelper::SizeLarge ? 13 : - cw.second == QStyleHelper::SizeSmall ? 11 : 9; // As measured - hOffset = hMargin + (cw.second == QStyleHelper::SizeLarge ? 2.5 : - cw.second == QStyleHelper::SizeSmall ? 2.0 : 1.0); // As measured + const auto cbInnerRadius = (cw.size == QStyleHelper::SizeMini ? 2.0 : 3.0); + const auto cbSize = cw.size == QStyleHelper::SizeLarge ? 13 : + cw.size == QStyleHelper::SizeSmall ? 11 : 9; // As measured + hOffset = hMargin + (cw.size == QStyleHelper::SizeLarge ? 2.5 : + cw.size == QStyleHelper::SizeSmall ? 2.0 : 1.0); // As measured vOffset = 0.5 * qreal(targetRect.height() - cbSize); const auto cbInnerRect = QRectF(0, 0, cbSize, cbSize); const auto cbOutterRadius = cbInnerRadius + focusRingWidth; @@ -1227,10 +1227,10 @@ void QMacStylePrivate::drawFocusRing(QPainter *p, const QRect &targetRect, int h break; } case Button_RadioButton: { - const auto rbSize = cw.second == QStyleHelper::SizeLarge ? 15 : - cw.second == QStyleHelper::SizeSmall ? 13 : 9; // As measured - hOffset = hMargin + (cw.second == QStyleHelper::SizeLarge ? 1.5 : - cw.second == QStyleHelper::SizeSmall ? 1.0 : 1.0); // As measured + const auto rbSize = cw.size == QStyleHelper::SizeLarge ? 15 : + cw.size == QStyleHelper::SizeSmall ? 13 : 9; // As measured + hOffset = hMargin + (cw.size == QStyleHelper::SizeLarge ? 1.5 : + cw.size == QStyleHelper::SizeSmall ? 1.0 : 1.0); // As measured vOffset = 0.5 * qreal(targetRect.height() - rbSize); const auto rbInnerRect = QRectF(0, 0, rbSize, rbSize); const auto rbOutterRect = rbInnerRect.adjusted(-focusRingWidth, -focusRingWidth, focusRingWidth, focusRingWidth); @@ -1501,6 +1501,26 @@ QSize QMacStylePrivate::pushButtonSizeFromContents(const QStyleOptionButton *btn return csz; } +uint qHash(const QMacStylePrivate::CocoaControl &cw, uint seed = 0) +{ + return ((cw.type << 2) | cw.size) ^ seed; +} + +QMacStylePrivate::CocoaControl::CocoaControl() + : type(NoControl), size(QStyleHelper::SizeDefault) +{ +} + +QMacStylePrivate::CocoaControl::CocoaControl(CocoaControlType t, QStyleHelper::WidgetSizePolicy s) + : type(t), size(s) +{ +} + +bool QMacStylePrivate::CocoaControl::operator==(const CocoaControl &other) const +{ + return other.type == type && other.size == size; +} + /** Checks if the actual contents of btn fits inside the free content bounds of 'buttonKindToCheck'. Meant as a helper function for 'initHIThemePushButton' @@ -1605,8 +1625,8 @@ void QMacStylePrivate::initComboboxBdi(const QStyleOptionComboBox *combo, HIThem bdi->state = tds; QStyleHelper::WidgetSizePolicy aSize = aquaSizeConstrain(combo, widget); - cw->first = combo->editable ? ComboBox : Button_PopupButton; - cw->second = aSize; + cw->type = combo->editable ? ComboBox : Button_PopupButton; + cw->size = aSize; switch (aSize) { case QStyleHelper::SizeMini: bdi->kind = combo->editable ? ThemeButtonKind(kThemeComboBoxMini) @@ -1638,26 +1658,26 @@ void QMacStylePrivate::initComboboxBdi(const QStyleOptionComboBox *combo, HIThem // or return any subcontrol size of the poor thing. if (h < 9) { bdi->kind = kThemeComboBoxMini; - cw->second = QStyleHelper::SizeMini; + cw->size = QStyleHelper::SizeMini; } else if (h < 22) { bdi->kind = kThemeComboBoxSmall; - cw->second = QStyleHelper::SizeSmall; + cw->size = QStyleHelper::SizeSmall; } else { bdi->kind = kThemeComboBox; - cw->second = QStyleHelper::SizeLarge; + cw->size = QStyleHelper::SizeLarge; } } else #endif { if (h < 21) { bdi->kind = kThemeComboBoxMini; - cw->second = QStyleHelper::SizeMini; + cw->size = QStyleHelper::SizeMini; } else if (h < 26) { bdi->kind = kThemeComboBoxSmall; - cw->second = QStyleHelper::SizeSmall; + cw->size = QStyleHelper::SizeSmall; } else { bdi->kind = kThemeComboBox; - cw->second = QStyleHelper::SizeLarge; + cw->size = QStyleHelper::SizeLarge; } } } else { @@ -1668,13 +1688,13 @@ void QMacStylePrivate::initComboboxBdi(const QStyleOptionComboBox *combo, HIThem // the use of LargeButtons explicit. if (h < 21) { bdi->kind = kThemePopupButtonMini; - cw->second = QStyleHelper::SizeMini; + cw->size = QStyleHelper::SizeMini; } else if (h < 26) { bdi->kind = kThemePopupButtonSmall; - cw->second = QStyleHelper::SizeSmall; + cw->size = QStyleHelper::SizeSmall; } else { bdi->kind = kThemePopupButton; - cw->second = QStyleHelper::SizeLarge; + cw->size = QStyleHelper::SizeLarge; } } break; @@ -1691,8 +1711,8 @@ CGRect QMacStylePrivate::comboboxInnerBounds(const CGRect &outerBounds, const Co // Carbon draw parts of the view outside the rect. // So make the rect a bit smaller to compensate // (I wish HIThemeGetButtonBackgroundBounds worked) - if (cocoaWidget.first == Button_PopupButton) { - switch (cocoaWidget.second) { + if (cocoaWidget.type == Button_PopupButton) { + switch (cocoaWidget.size) { case QStyleHelper::SizeSmall: innerBounds.origin.x += 3; innerBounds.origin.y += 3; @@ -1712,8 +1732,8 @@ CGRect QMacStylePrivate::comboboxInnerBounds(const CGRect &outerBounds, const Co innerBounds.size.width -= 5; innerBounds.size.height -= 6; } - } else if (cocoaWidget.first == ComboBox) { - switch (cocoaWidget.second) { + } else if (cocoaWidget.type == ComboBox) { + switch (cocoaWidget.size) { case QStyleHelper::SizeSmall: innerBounds.origin.x += 3; innerBounds.origin.y += 3; @@ -1866,28 +1886,28 @@ ThemeDrawState QMacStylePrivate::getDrawState(QStyle::State flags) case kThemePopupButton: case kThemePopupButtonSmall: case kThemePopupButtonMini: - w.first = Button_PopupButton; + w.type = Button_PopupButton; break; case kThemeComboBox: - w.first = ComboBox; + w.type = ComboBox; break; case kThemeArrowButton: - w.first = Button_Disclosure; + w.type = Button_Disclosure; break; case kThemeCheckBox: case kThemeCheckBoxSmall: case kThemeCheckBoxMini: - w.first = Button_CheckBox; + w.type = Button_CheckBox; break; case kThemeRadioButton: case kThemeRadioButtonSmall: case kThemeRadioButtonMini: - w.first = Button_RadioButton; + w.type = Button_RadioButton; break; case kThemePushButton: case kThemePushButtonSmall: case kThemePushButtonMini: - w.first = Button_PushButton; + w.type = Button_PushButton; break; default: break; @@ -1898,16 +1918,16 @@ ThemeDrawState QMacStylePrivate::getDrawState(QStyle::State flags) case kThemePopupButtonSmall: case kThemeCheckBoxSmall: case kThemeRadioButtonSmall: - w.second = QStyleHelper::SizeSmall; + w.size = QStyleHelper::SizeSmall; break; case kThemePushButtonMini: case kThemePopupButtonMini: case kThemeCheckBoxMini: case kThemeRadioButtonMini: - w.second = QStyleHelper::SizeMini; + w.size = QStyleHelper::SizeMini; break; default: - w.second = QStyleHelper::SizeLarge; + w.size = QStyleHelper::SizeLarge; break; } @@ -1928,7 +1948,7 @@ NSView *QMacStylePrivate::cocoaControl(CocoaControl widget) const NSView *bv = cocoaControls.value(widget, nil); if (!bv) { - switch (widget.first) { + switch (widget.type) { case Box: { NSBox *bc = [[NSBox alloc] init]; bc.title = @""; @@ -1948,7 +1968,7 @@ NSView *QMacStylePrivate::cocoaControl(CocoaControl widget) const case Button_PullDown: { NSPopUpButton *bc = [[NSPopUpButton alloc] init]; bc.title = @""; - if (widget.first == Button_PullDown) + if (widget.type == Button_PullDown) bc.pullsDown = YES; bv = bc; break; @@ -1963,7 +1983,7 @@ NSView *QMacStylePrivate::cocoaControl(CocoaControl widget) const case Button_WindowMiniaturize: case Button_WindowZoom: { const NSWindowButton button = [=] { - switch (widget.first) { + switch (widget.type) { case Button_WindowClose: return NSWindowCloseButton; case Button_WindowMiniaturize: @@ -2030,7 +2050,7 @@ NSView *QMacStylePrivate::cocoaControl(CocoaControl widget) const if ([bv isKindOfClass:[NSControl class]]) { auto *ctrl = static_cast(bv); - switch (widget.second) { + switch (widget.size) { case QStyleHelper::SizeSmall: ctrl.controlSize = NSSmallControlSize; break; @@ -2040,11 +2060,11 @@ NSView *QMacStylePrivate::cocoaControl(CocoaControl widget) const default: break; } - } else if (widget.first == ProgressIndicator_Determinate || - widget.first == ProgressIndicator_Indeterminate) { + } else if (widget.type == ProgressIndicator_Determinate || + widget.type == ProgressIndicator_Indeterminate) { auto *pi = static_cast(bv); - pi.indeterminate = (widget.first == ProgressIndicator_Indeterminate); - switch (widget.second) { + pi.indeterminate = (widget.type == ProgressIndicator_Indeterminate); + switch (widget.size) { case QStyleHelper::SizeSmall: pi.controlSize = NSSmallControlSize; break; @@ -2066,7 +2086,7 @@ NSCell *QMacStylePrivate::cocoaCell(CocoaControl widget) const { NSCell *cell = cocoaCells[widget]; if (!cell) { - switch (widget.first) { + switch (widget.type) { case Stepper: cell = [[NSStepperCell alloc] init]; break; @@ -2081,7 +2101,7 @@ NSCell *QMacStylePrivate::cocoaCell(CocoaControl widget) const break; } - switch (widget.second) { + switch (widget.size) { case QStyleHelper::SizeSmall: cell.controlSize = NSSmallControlSize; break; @@ -3839,13 +3859,13 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter QMacStylePrivate::CocoaControl cw = QMacStylePrivate::cocoaControlFromHIThemeButtonKind(bdi.kind); if (hasMenu) - cw.first = QMacStylePrivate::Button_PullDown; + cw.type = QMacStylePrivate::Button_PullDown; if (hasMenu && bdi.kind != kThemeBevelButton) { NSPopUpButton *pdb = (NSPopUpButton *)d->cocoaControl(cw); [pdb highlight:(bdi.state == kThemeStatePressed)]; pdb.enabled = bdi.state != kThemeStateUnavailable && bdi.state != kThemeStateUnavailableInactive; QRect rect = opt->rect; - rect.adjust(0, 0, cw.second == QStyleHelper::SizeSmall ? -4 : cw.second == QStyleHelper::SizeMini ? -9 : -6, 0); + rect.adjust(0, 0, cw.size == QStyleHelper::SizeSmall ? -4 : cw.size == QStyleHelper::SizeMini ? -9 : -6, 0); d->drawNSViewInRect(cw, pdb, rect, p, w != 0); } else if (hasMenu && bdi.state == kThemeStatePressed) d->drawColorlessButton(newRect, &bdi, cw, p, opt); @@ -4513,7 +4533,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter const auto cw = QMacStylePrivate::CocoaControl(ct, QStyleHelper::SizeLarge); auto *sv = static_cast(d->cocoaControl(cw)); sv.frame = opt->rect.toCGRect(); - d->drawNSViewInRect(cw, sv, opt->rect, p, w != nullptr, ^(CGContextRef ctx, const CGRect &rect) { + d->drawNSViewInRect(cw, sv, opt->rect, p, w != nullptr, ^(CGContextRef __unused ctx, const CGRect &rect) { [sv drawDividerInRect:rect]; }); } else { @@ -6467,8 +6487,8 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, if (const QStyleOptionComboBox *combo = qstyleoption_cast(opt)){ const auto widgetSize = d->aquaSizeConstrain(opt, widget); QMacStylePrivate::CocoaControl cw; - cw.first = combo->editable ? QMacStylePrivate::ComboBox : QMacStylePrivate::Button_PopupButton; - cw.second = widgetSize; + cw.type = combo->editable ? QMacStylePrivate::ComboBox : QMacStylePrivate::Button_PopupButton; + cw.size = widgetSize; const CGRect diffRect = QMacStylePrivate::comboboxInnerBounds(CGRectZero, cw); sz.rwidth() -= qRound(diffRect.size.width); sz.rheight() -= qRound(diffRect.size.height); diff --git a/src/plugins/styles/mac/qmacstyle_mac_p_p.h b/src/plugins/styles/mac/qmacstyle_mac_p_p.h index 00dc8a9b53..1c4986dd06 100644 --- a/src/plugins/styles/mac/qmacstyle_mac_p_p.h +++ b/src/plugins/styles/mac/qmacstyle_mac_p_p.h @@ -206,7 +206,17 @@ public: TextField }; - typedef QPair CocoaControl; + + struct CocoaControl { + CocoaControl(); + CocoaControl(CocoaControlType t, QStyleHelper::WidgetSizePolicy s); + + CocoaControlType type; + QStyleHelper::WidgetSizePolicy size; + + bool operator==(const CocoaControl &other) const; + }; + typedef void (^DrawRectBlock)(CGContextRef, const CGRect &); From e3561dbda0be663ea8d1e810d47afc80d171f43e Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 13 Mar 2018 18:09:27 -0700 Subject: [PATCH 20/51] QMacStyle: No more HITheme for CE_PushButtonBevel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For rendering only. Sizing is still pending and, consequently, square buttons since these depend on the button's intrinsic size. Change-Id: Iacadc02a1a75970b221543b32ca724c92e118ce1 Reviewed-by: Morten Johan Sørvig --- src/plugins/styles/mac/qmacstyle_mac.mm | 260 ++++++++++++--------- src/plugins/styles/mac/qmacstyle_mac_p_p.h | 6 +- 2 files changed, 155 insertions(+), 111 deletions(-) diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index 79109dbbfe..dd2e28264f 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -331,6 +331,22 @@ static const qreal closeButtonCornerRadius = 2.0; static const int headerSectionArrowHeight = 6; static const int headerSectionSeparatorInset = 2; +// One for each of QStyleHelper::WidgetSizePolicy +static const QMarginsF pullDownButtonShadowMargins[3] = { + { 0.5, -1, 0.5, 2 }, + { 0.5, -1.5, 0.5, 2.5 }, + { 0.5, 0, 0.5, 1 } +}; + +static const QMarginsF pushButtonShadowMargins[3] = { + { 1.5, -1.5, 1.5, 4.5 }, + { 1.5, -1, 1.5, 4 }, + { 1.5, 0.5, 1.5, 2.5 } +}; + +static const int toolButtonArrowSize = 7; +static const int toolButtonArrowMargin = 2; + #if QT_CONFIG(tabbar) static bool isVerticalTabs(const QTabBar::Shape shape) { return (shape == QTabBar::RoundedEast @@ -1203,7 +1219,7 @@ void QMacStylePrivate::drawFocusRing(QPainter *p, const QRect &targetRect, int h QRect(focusRingPixmap.width() - shCornerSize, svCornerSize, shCornerSize, focusRingPixmap.width() - 2 * svCornerSize)); } -void QMacStylePrivate::drawFocusRing(QPainter *p, const QRect &targetRect, int hMargin, int vMargin, const CocoaControl &cw) const +void QMacStylePrivate::drawFocusRing(QPainter *p, const QRectF &targetRect, int hMargin, int vMargin, const CocoaControl &cw) const { static const auto focusRingWidth = 3.5; @@ -1239,8 +1255,21 @@ void QMacStylePrivate::drawFocusRing(QPainter *p, const QRect &targetRect, int h focusRingPath.addEllipse(rbOutterRect); break; } + case Button_PopupButton: + case Button_PullDown: + case Button_PushButton: { + const qreal innerRadius = cw.type == Button_PullDown ? 4 : 3; + const qreal outterRadius = innerRadius + focusRingWidth; + hOffset = targetRect.left(); + vOffset = targetRect.top(); + const auto innerRect = targetRect.translated(-targetRect.topLeft()); + const auto outterRect = innerRect.adjusted(-hMargin, -vMargin, hMargin, vMargin); + focusRingPath.setFillRule(Qt::OddEvenFill); + focusRingPath.addRoundedRect(innerRect, innerRadius, innerRadius); + focusRingPath.addRoundedRect(outterRect, outterRadius, outterRadius); + break; + } default: - Q_UNUSED(vMargin); Q_UNREACHABLE(); } @@ -1521,6 +1550,35 @@ bool QMacStylePrivate::CocoaControl::operator==(const CocoaControl &other) const return other.type == type && other.size == size; } +QSizeF QMacStylePrivate::CocoaControl::defaultFrameSize() const +{ + // We need this because things like NSView.alignmentRectInsets + // or -[NSCell titleRectForBounds:] won't work unless the control + // has a reasonable frame set. IOW, it's a chicken and egg problem. + // These values are as observed in Xcode 9's Interface Builder. + + if (type == Button_PushButton) { + if (size == QStyleHelper::SizeLarge) + return QSizeF(-1, 32); + if (size == QStyleHelper::SizeSmall) + return QSizeF(-1, 28); + if (size == QStyleHelper::SizeMini) + return QSizeF(-1, 16); + } + + if (type == Button_PopupButton + || type == Button_PullDown) { + if (size == QStyleHelper::SizeLarge) + return QSizeF(-1, 26); + if (size == QStyleHelper::SizeSmall) + return QSizeF(-1, 22); + if (size == QStyleHelper::SizeMini) + return QSizeF(-1, 15); + } + + return QSizeF(); +} + /** Checks if the actual contents of btn fits inside the free content bounds of 'buttonKindToCheck'. Meant as a helper function for 'initHIThemePushButton' @@ -2118,19 +2176,14 @@ NSCell *QMacStylePrivate::cocoaCell(CocoaControl widget) const return cell; } -void QMacStylePrivate::drawNSViewInRect(CocoaControl widget, NSView *view, const QRect &qtRect, QPainter *p, bool isQWidget, __attribute__((noescape)) DrawRectBlock drawRectBlock) const +void QMacStylePrivate::drawNSViewInRect(CocoaControl widget, NSView *view, const QRectF &qtRect, QPainter *p, bool isQWidget, __attribute__((noescape)) DrawRectBlock drawRectBlock) const { + Q_UNUSED(isQWidget); QPoint offset; if (widget == CocoaControl(Button_PopupButton, QStyleHelper::SizeSmall)) offset.setY(1); else if (widget == CocoaControl(Button_PopupButton, QStyleHelper::SizeMini)) offset = QPoint(2, -1); - else if (widget == CocoaControl(Button_PullDown, QStyleHelper::SizeLarge)) - offset = isQWidget ? QPoint(3, -1) : QPoint(-1, -3); - else if (widget == CocoaControl(Button_PullDown, QStyleHelper::SizeSmall)) - offset = QPoint(2, 1); - else if (widget == CocoaControl(Button_PullDown, QStyleHelper::SizeMini)) - offset = QPoint(5, 0); else if (widget == CocoaControl(ComboBox, QStyleHelper::SizeLarge)) offset = QPoint(3, 0); @@ -2478,6 +2531,10 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW ret = 0; break; + case PM_MenuButtonIndicator: + ret = toolButtonArrowSize; + break; + case QStyle::PM_MenuDesktopFrameWidth: ret = 5; break; @@ -3643,7 +3700,6 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter const QWidget *w) const { Q_D(const QMacStyle); - ThemeDrawState tds = d->getDrawState(opt->state); QMacCGContext cg(p); QWindow *window = w && w->window() ? w->window()->windowHandle() : QStyleHelper::styleObjectWindow(opt->styleObject); @@ -3815,120 +3871,104 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter break; } + const bool hasFocus = btn->state & State_HasFocus; + const bool isActive = btn->state & State_Active; + // a focused auto-default button within an active window // takes precedence over a normal default button if ((btn->features & QStyleOptionButton::AutoDefaultButton) - && (opt->state & State_Active) - && (opt->state & State_HasFocus)) + && isActive && hasFocus) d->autoDefaultButton = opt->styleObject; else if (d->autoDefaultButton == opt->styleObject) d->autoDefaultButton = nullptr; - bool hasMenu = btn->features & QStyleOptionButton::HasMenu; - HIThemeButtonDrawInfo bdi; - d->initHIThemePushButton(btn, w, tds, &bdi); - - if (!hasMenu) { - // HITheme is not drawing a nice focus frame around buttons. - // We'll do it ourselves further down. - bdi.adornment &= ~kThemeAdornmentFocus; - - // We can't rely on an animation existing to test for the default look. That means a bit - // more logic (notice that the logic is slightly different for the bevel and the label). - if (tds == kThemeStateActive - && (btn->features & QStyleOptionButton::DefaultButton - || (btn->features & QStyleOptionButton::AutoDefaultButton - && d->autoDefaultButton == btn->styleObject))) - bdi.adornment |= kThemeAdornmentDefault; - } - - // Unlike Carbon, we want the button to always be drawn inside its bounds. - // Therefore, make the button a bit smaller, so that even if it got focus, - // the focus 'shadow' will be inside. - CGRect newRect = btn->rect.toCGRect(); - if (bdi.kind == kThemePushButton || bdi.kind == kThemePushButtonSmall) { - newRect.origin.x += QMacStylePrivate::PushButtonLeftOffset; - newRect.origin.y += QMacStylePrivate::PushButtonTopOffset; - newRect.size.width -= QMacStylePrivate::PushButtonRightOffset; - newRect.size.height -= QMacStylePrivate::PushButtonBottomOffset; - } else if (bdi.kind == kThemePushButtonMini) { - newRect.origin.x += QMacStylePrivate::PushButtonLeftOffset - 2; - newRect.origin.y += QMacStylePrivate::PushButtonTopOffset; - newRect.size.width -= QMacStylePrivate::PushButtonRightOffset - 4; - } - - QMacStylePrivate::CocoaControl cw = QMacStylePrivate::cocoaControlFromHIThemeButtonKind(bdi.kind); - if (hasMenu) - cw.type = QMacStylePrivate::Button_PullDown; - if (hasMenu && bdi.kind != kThemeBevelButton) { - NSPopUpButton *pdb = (NSPopUpButton *)d->cocoaControl(cw); - [pdb highlight:(bdi.state == kThemeStatePressed)]; - pdb.enabled = bdi.state != kThemeStateUnavailable && bdi.state != kThemeStateUnavailableInactive; - QRect rect = opt->rect; - rect.adjust(0, 0, cw.size == QStyleHelper::SizeSmall ? -4 : cw.size == QStyleHelper::SizeMini ? -9 : -6, 0); - d->drawNSViewInRect(cw, pdb, rect, p, w != 0); - } else if (hasMenu && bdi.state == kThemeStatePressed) - d->drawColorlessButton(newRect, &bdi, cw, p, opt); - else - HIThemeDrawButton(&newRect, &bdi, cg, kHIThemeOrientationNormal, 0); - - if (btn->state & State_HasFocus) { - CGRect focusRect = newRect; - if (bdi.kind == kThemePushButton) - focusRect.size.height += 1; // Another thing HITheme and Cocoa seem to disagree about. - else if (bdi.kind == kThemePushButtonMini) - focusRect.size.height = 15; // Our QPushButton sizes are really weird - - if (bdi.adornment & kThemeAdornmentDefault || bdi.state == kThemeStatePressed) { - if (bdi.kind == kThemePushButtonSmall) { - focusRect = CGRectInset(focusRect, -1, 0); - } else if (bdi.kind == kThemePushButtonMini) { - focusRect = CGRectInset(focusRect, 1, 0); - } + const bool isEnabled = btn->state & State_Enabled; + const bool isPressed = btn->state & State_Sunken; + const bool isHighlighted = isActive && + ((btn->state & State_On) + || (btn->features & QStyleOptionButton::DefaultButton) + || (btn->features & QStyleOptionButton::AutoDefaultButton + && d->autoDefaultButton == btn->styleObject)); + const bool hasMenu = btn->features & QStyleOptionButton::HasMenu; + // TODO When the contents won't fit in a large sized button, + // and WA_MacNormalSize is not set, make the button square. + const bool isSquare = btn->features & QStyleOptionButton::Flat; + const auto ct = hasMenu ? QMacStylePrivate::Button_PullDown : QMacStylePrivate::Button_PushButton; + const auto cs = d->effectiveAquaSizeConstrain(opt, w); + const auto cw = QMacStylePrivate::CocoaControl(ct, cs); + auto *pb = static_cast(d->cocoaControl(cw)); + // Ensure same size and location as we used to have with HITheme. + // This is more convoluted than we initialy thought. See for example + // differences between plain and menu button frames. + QRectF frameRect; + if (isSquare) { + frameRect = btn->rect; + } else { + const auto frameSize = cw.defaultFrameSize(); + if (hasMenu) { + // Center in the style option's rect. + frameRect = QRectF(QPointF(0, (btn->rect.height() - frameSize.height()) / 2.0), + QSizeF(btn->rect.width(), frameSize.height())); + if (cw.size == QStyleHelper::SizeLarge) + frameRect = frameRect.adjusted(0, 0, -6, 0).translated(3, -1); + else if (cw.size == QStyleHelper::SizeSmall) + frameRect = frameRect.adjusted(0, 0, -4, 0).translated(2, 1); + else if (cw.size == QStyleHelper::SizeMini) + frameRect = frameRect.adjusted(0, 0, -9, 0).translated(5, 0); } else { - if (bdi.kind == kThemePushButton) { - focusRect = CGRectInset(focusRect, 1, 1); - } else if (bdi.kind == kThemePushButtonSmall) { - focusRect = CGRectInset(focusRect, 0, 2); - } else if (bdi.kind == kThemePushButtonMini) { - focusRect = CGRectInset(focusRect, 2, 1); - } + // Start from the style option's top-left corner. + frameRect = QRectF(btn->rect.topLeft(), + QSizeF(btn->rect.width(), frameSize.height())); + if (cw.size == QStyleHelper::SizeSmall) + frameRect = frameRect.translated(0, 1.5); + else if (cw.size == QStyleHelper::SizeMini) + frameRect = frameRect.adjusted(0, 0, -8, 0).translated(4, 4); } - - const qreal radius = bdi.kind == kThemeBevelButton ? 0 : 3; - const int hMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, btn, w); - const int vMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, btn, w); - const QRect focusTargetRect(focusRect.origin.x, focusRect.origin.y, focusRect.size.width, focusRect.size.height); - d->drawFocusRing(p, focusTargetRect.adjusted(-hMargin, -vMargin, hMargin, vMargin), hMargin, vMargin, radius); } + pb.frame = frameRect.toCGRect(); - if (hasMenu && bdi.kind == kThemeBevelButton) { - int mbi = proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, w); - QRect ir = btn->rect; - int arrowXOffset = bdi.kind == kThemePushButton ? 6 : - bdi.kind == kThemePushButtonSmall ? 7 : 8; - int arrowYOffset = bdi.kind == kThemePushButton ? 3 : - bdi.kind == kThemePushButtonSmall ? 1 : 2; + pb.bezelStyle = isSquare ? NSBezelStyleShadowlessSquare : NSBezelStyleRounded; + pb.buttonType = NSPushOnPushOffButton; + pb.enabled = isEnabled; + [pb highlight:isPressed]; + pb.state = isHighlighted && !isPressed ? NSOnState : NSOffState; + d->drawNSViewInRect(cw, pb, frameRect, p, true, ^(CGContextRef __unused ctx, const CGRect &r) { + [pb.cell drawBezelWithFrame:r inView:pb.superview]; + }); + + if (hasMenu && isSquare) { + // Using -[NSPopuButtonCell drawWithFrame:inView:] above won't do + // it right because we don't set the text in the native button. + const int mbi = proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, w); + const auto ir = frameRect.toRect(); + int arrowYOffset = 0; +#if 0 + // FIXME What's this for again? if (!w) { // adjustment for Qt Quick Controls arrowYOffset -= ir.top(); - if (bdi.kind == kThemePushButtonSmall) + if (cw.second == QStyleHelper::SizeSmall) arrowYOffset += 1; } - QRect ar = QRect(ir.right() - mbi - QMacStylePrivate::PushButtonRightOffset, - ir.height() / 2 - arrowYOffset, mbi, ir.height() / 2); - ar = visualRect(btn->direction, ir, ar); - CGRect arrowRect = CGRectMake(ar.x() + arrowXOffset, ar.y(), ar.width(), ar.height()); +#endif + const auto ar = visualRect(btn->direction, ir, QRect(ir.right() - mbi - 6, ir.height() / 2 - arrowYOffset, mbi, mbi)); - HIThemePopupArrowDrawInfo pdi; - pdi.version = qt_mac_hitheme_version; - pdi.state = tds == kThemeStateInactive ? kThemeStateActive : tds; - pdi.orientation = kThemeArrowDown; - if (bdi.kind == kThemePushButtonMini) - pdi.size = kThemeArrow5pt; - else if (bdi.kind == kThemePushButton || bdi.kind == kThemePushButtonSmall) - pdi.size = kThemeArrow7pt; - HIThemeDrawPopupArrow(&arrowRect, &pdi, cg, kHIThemeOrientationNormal); + QStyleOption arrowOpt = *opt; + arrowOpt.rect = ar; + proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, w); + } + + + if (btn->state & State_HasFocus) { + // TODO Remove and use QFocusFrame instead. + const int hMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, btn, w); + const int vMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, btn, w); + auto focusRect = QRectF::fromCGRect([pb alignmentRectForFrame:pb.frame]); + if (cw.type == QMacStylePrivate::Button_PushButton) + focusRect -= pushButtonShadowMargins[cw.size]; + else if (cw.type == QMacStylePrivate::Button_PullDown) + focusRect -= pullDownButtonShadowMargins[cw.size]; + d->drawFocusRing(p, focusRect, hMargin, vMargin, cw); } } break; @@ -3942,10 +3982,12 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter const bool hasMenu = btn.features & QStyleOptionButton::HasMenu; const bool hasIcon = !btn.icon.isNull(); const bool hasText = !btn.text.isEmpty(); + const bool isActive = btn.state & State_Active; + const bool isPressed = btn.state & State_Sunken; if (!hasMenu) { - if (tds == kThemeStatePressed - || (tds == kThemeStateActive + if (isPressed + || (isActive && ((btn.features & QStyleOptionButton::DefaultButton && !d->autoDefaultButton) || d->autoDefaultButton == btn.styleObject))) btn.palette.setColor(QPalette::ButtonText, Qt::white); diff --git a/src/plugins/styles/mac/qmacstyle_mac_p_p.h b/src/plugins/styles/mac/qmacstyle_mac_p_p.h index 1c4986dd06..c279162d1e 100644 --- a/src/plugins/styles/mac/qmacstyle_mac_p_p.h +++ b/src/plugins/styles/mac/qmacstyle_mac_p_p.h @@ -215,6 +215,8 @@ public: QStyleHelper::WidgetSizePolicy size; bool operator==(const CocoaControl &other) const; + + QSizeF defaultFrameSize() const; }; @@ -283,11 +285,11 @@ public: void setupVerticalInvertedXform(CGContextRef cg, bool reverse, bool vertical, const CGRect &rect) const; - void drawNSViewInRect(CocoaControl widget, NSView *view, const QRect &rect, QPainter *p, bool isQWidget = true, __attribute__((noescape)) DrawRectBlock drawRectBlock = nil) const; + void drawNSViewInRect(CocoaControl widget, NSView *view, const QRectF &rect, QPainter *p, bool isQWidget = true, __attribute__((noescape)) DrawRectBlock drawRectBlock = nil) const; void resolveCurrentNSView(QWindow *window) const; void drawFocusRing(QPainter *p, const QRect &targetRect, int hMargin, int vMargin, qreal radius = 0) const; - void drawFocusRing(QPainter *p, const QRect &targetRect, int hMargin, int vMargin, const CocoaControl &cw) const; + void drawFocusRing(QPainter *p, const QRectF &targetRect, int hMargin, int vMargin, const CocoaControl &cw) const; QPainterPath windowPanelPath(const QRectF &r) const; From bec1e609ec69c54dcac85ab49003dfe73f8c3af5 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 13 Mar 2018 19:07:58 -0700 Subject: [PATCH 21/51] QMacStyle: No more HITheme for CC_ToolButton MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As for CE_PushButtonBevel, sizing is still pending. These two seem to go together anyway. Change-Id: I631c3f32ba201b16adbfa264a2920bfb636fb86f Reviewed-by: Morten Johan Sørvig --- src/plugins/styles/mac/qmacstyle_mac.mm | 109 +++++++-------------- src/plugins/styles/mac/qmacstyle_mac_p_p.h | 2 + 2 files changed, 38 insertions(+), 73 deletions(-) diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index dd2e28264f..442ecae6e8 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -5183,16 +5183,15 @@ QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt, return rect; } -static inline void drawToolbarButtonArrow(const QRect &toolButtonRect, ThemeDrawState tds, CGContextRef cg) +void QMacStylePrivate::drawToolbarButtonArrow(const QStyleOption *opt, QPainter *p) const { - QRect arrowRect = QRect(toolButtonRect.right() - 9, toolButtonRect.bottom() - 9, 7, 5); - HIThemePopupArrowDrawInfo padi; - padi.version = qt_mac_hitheme_version; - padi.state = tds; - padi.orientation = kThemeArrowDown; - padi.size = kThemeArrow7pt; - CGRect cgRect = arrowRect.toCGRect(); - HIThemeDrawPopupArrow(&cgRect, &padi, cg, kHIThemeOrientationNormal); + Q_Q(const QMacStyle); + QStyleOption arrowOpt = *opt; + arrowOpt.rect = QRect(opt->rect.right() - (toolButtonArrowSize + toolButtonArrowMargin), + opt->rect.bottom() - (toolButtonArrowSize + toolButtonArrowMargin), + toolButtonArrowSize, + toolButtonArrowSize); + q->proxy()->drawPrimitive(QStyle::PE_IndicatorArrowDown, &arrowOpt, p); } void QMacStylePrivate::setupNSGraphicsContext(CGContextRef cg, bool flipped) const @@ -5701,7 +5700,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget); } else if ((tb->features & QStyleOptionToolButton::HasMenu) && (tb->toolButtonStyle != Qt::ToolButtonTextOnly && !tb->icon.isNull())) { - drawToolbarButtonArrow(tb->rect, tds, cg); + d->drawToolbarButtonArrow(tb, p); } if (tb->state & State_On) { QWindow *window = 0; @@ -5726,81 +5725,45 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex } else #endif // QT_NO_ACCESSIBILITY { - ThemeButtonKind bkind = kThemeBevelButton; - switch (d->aquaSizeConstrain(opt, widget)) { - case QStyleHelper::SizeDefault: - case QStyleHelper::SizeLarge: - bkind = kThemeBevelButton; - break; - case QStyleHelper::SizeMini: - case QStyleHelper::SizeSmall: - bkind = kThemeSmallBevelButton; - break; - } - - QRect button, menuarea; - button = proxy()->subControlRect(cc, tb, SC_ToolButton, widget); - menuarea = proxy()->subControlRect(cc, tb, SC_ToolButtonMenu, widget); - State bflags = tb->state, - mflags = tb->state; + auto bflags = tb->state; if (tb->subControls & SC_ToolButton) bflags |= State_Sunken; + auto mflags = tb->state; if (tb->subControls & SC_ToolButtonMenu) mflags |= State_Sunken; if (tb->subControls & SC_ToolButton) { if (bflags & (State_Sunken | State_On | State_Raised)) { - HIThemeButtonDrawInfo bdi; - bdi.version = qt_mac_hitheme_version; - bdi.state = tds; - bdi.adornment = kThemeAdornmentNone; - bdi.kind = bkind; - bdi.value = kThemeButtonOff; - if (tb->state & State_HasFocus) - bdi.adornment = kThemeAdornmentFocus; - if (tb->state & State_Sunken) - bdi.state = kThemeStatePressed; - if (tb->state & State_On) - bdi.value = kThemeButtonOn; - - CGRect myRect, macRect; - myRect = CGRectMake(tb->rect.x(), tb->rect.y(), - tb->rect.width(), tb->rect.height()); - HIThemeGetButtonBackgroundBounds(&myRect, &bdi, &macRect); - - const auto offMargins = QMargins(int(myRect.origin.x - macRect.origin.x), - int(myRect.origin.y - macRect.origin.y), - int(macRect.size.width - myRect.size.width), - int(macRect.size.height - myRect.size.height)); - myRect = button.marginsRemoved(offMargins).toCGRect(); - HIThemeDrawButton(&myRect, &bdi, cg, kHIThemeOrientationNormal, 0); + const bool isEnabled = tb->state & State_Enabled; + const bool isPressed = tb->state & State_Sunken; + const bool isHighlighted = (tb->state & State_Active) && (tb->state & State_On); + const auto ct = QMacStylePrivate::Button_PushButton; + const auto cs = d->effectiveAquaSizeConstrain(opt, widget); + const auto cw = QMacStylePrivate::CocoaControl(ct, cs); + auto *pb = static_cast(d->cocoaControl(cw)); + pb.bezelStyle = NSShadowlessSquareBezelStyle; // TODO Use NSTexturedRoundedBezelStyle in the future. + pb.frame = opt->rect.toCGRect(); + pb.buttonType = NSPushOnPushOffButton; + pb.enabled = isEnabled; + [pb highlight:isPressed]; + pb.state = isHighlighted && !isPressed ? NSOnState : NSOffState; + const auto buttonRect = proxy()->subControlRect(cc, tb, SC_ToolButton, widget); + d->drawNSViewInRect(cw, pb, buttonRect, p, ^(CGContextRef __unused ctx, const CGRect &rect) { + [pb.cell drawBezelWithFrame:rect inView:pb]; + }); } } if (tb->subControls & SC_ToolButtonMenu) { - HIThemeButtonDrawInfo bdi; - bdi.version = qt_mac_hitheme_version; - bdi.state = tds; - bdi.value = kThemeButtonOff; - bdi.adornment = kThemeAdornmentNone; - bdi.kind = bkind; - if (tb->state & State_HasFocus) - bdi.adornment = kThemeAdornmentFocus; - if (tb->state & (State_On | State_Sunken) - || (tb->activeSubControls & SC_ToolButtonMenu)) - bdi.state = kThemeStatePressed; - CGRect cgRect = menuarea.toCGRect(); - HIThemeDrawButton(&cgRect, &bdi, cg, kHIThemeOrientationNormal, 0); - QRect r(menuarea.x() + ((menuarea.width() / 2) - 3), menuarea.height() - 8, 8, 8); - HIThemePopupArrowDrawInfo padi; - padi.version = qt_mac_hitheme_version; - padi.state = tds; - padi.orientation = kThemeArrowDown; - padi.size = kThemeArrow7pt; - cgRect = r.toCGRect(); - HIThemeDrawPopupArrow(&cgRect, &padi, cg, kHIThemeOrientationNormal); + const auto menuRect = proxy()->subControlRect(cc, tb, SC_ToolButtonMenu, widget); + QStyleOption arrowOpt = *tb; + arrowOpt.rect = QRect(menuRect.x() + ((menuRect.width() - toolButtonArrowSize) / 2), + menuRect.height() - (toolButtonArrowSize + toolButtonArrowMargin), + toolButtonArrowSize, + toolButtonArrowSize); + proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget); } else if (tb->features & QStyleOptionToolButton::HasMenu) { - drawToolbarButtonArrow(tb->rect, tds, cg); + d->drawToolbarButtonArrow(tb, p); } QRect buttonRect = proxy()->subControlRect(CC_ToolButton, tb, SC_ToolButton, widget); int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget); diff --git a/src/plugins/styles/mac/qmacstyle_mac_p_p.h b/src/plugins/styles/mac/qmacstyle_mac_p_p.h index c279162d1e..af34f8f1e4 100644 --- a/src/plugins/styles/mac/qmacstyle_mac_p_p.h +++ b/src/plugins/styles/mac/qmacstyle_mac_p_p.h @@ -291,6 +291,8 @@ public: void drawFocusRing(QPainter *p, const QRect &targetRect, int hMargin, int vMargin, qreal radius = 0) const; void drawFocusRing(QPainter *p, const QRectF &targetRect, int hMargin, int vMargin, const CocoaControl &cw) const; + void drawToolbarButtonArrow(const QStyleOption *opt, QPainter *p) const; + QPainterPath windowPanelPath(const QRectF &r) const; CocoaControlType windowButtonCocoaControl(QStyle::SubControl sc) const; From 3e665c8df8d0f5e3bb6e4bdda957fbd77f8a76ba Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Thu, 15 Mar 2018 18:44:44 -0700 Subject: [PATCH 22/51] QMacStyle: Make CE_PushButtonBevel square if large enough MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Meaning, if larger than the size of a regular NSButton. No intermediate size square buttons anymore. We'll try to get the closest one later, once the sizing problem is solved. We also refactor the button creation code a bit. Change-Id: I965520469546aea596cd1abec2309b40d70399ce Reviewed-by: Morten Johan Sørvig --- src/plugins/styles/mac/qmacstyle_mac.mm | 128 +++++++++++++++------ src/plugins/styles/mac/qmacstyle_mac_p_p.h | 3 + 2 files changed, 94 insertions(+), 37 deletions(-) diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index 442ecae6e8..f44747c295 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -344,9 +344,15 @@ static const QMarginsF pushButtonShadowMargins[3] = { { 1.5, 0.5, 1.5, 2.5 } }; +static const qreal pushButtonDefaultHeight[3] = { + 32, 28, 24 +}; + static const int toolButtonArrowSize = 7; static const int toolButtonArrowMargin = 2; +static const qreal focusRingWidth = 3.5; + #if QT_CONFIG(tabbar) static bool isVerticalTabs(const QTabBar::Shape shape) { return (shape == QTabBar::RoundedEast @@ -1221,8 +1227,6 @@ void QMacStylePrivate::drawFocusRing(QPainter *p, const QRect &targetRect, int h void QMacStylePrivate::drawFocusRing(QPainter *p, const QRectF &targetRect, int hMargin, int vMargin, const CocoaControl &cw) const { - static const auto focusRingWidth = 3.5; - QPainterPath focusRingPath; qreal hOffset = 0.0; qreal vOffset = 0.0; @@ -1579,6 +1583,55 @@ QSizeF QMacStylePrivate::CocoaControl::defaultFrameSize() const return QSizeF(); } +bool QMacStylePrivate::CocoaControl::getCocoaButtonTypeAndBezelStyle(NSButtonType *buttonType, NSBezelStyle *bezelStyle) const +{ + switch (type) { + case Button_CheckBox: + *buttonType = NSSwitchButton; + *bezelStyle = NSRegularSquareBezelStyle; + break; + case Button_Disclosure: + *buttonType = NSOnOffButton; + *bezelStyle = NSDisclosureBezelStyle; + break; + case Button_RadioButton: + *buttonType = NSRadioButton; + *bezelStyle = NSRegularSquareBezelStyle; + break; + case Button_SquareButton: + *buttonType = NSPushOnPushOffButton; + *bezelStyle = NSShadowlessSquareBezelStyle; + break; + case Button_PushButton: + *buttonType = NSPushOnPushOffButton; + *bezelStyle = NSRoundedBezelStyle; + break; + default: + return false; + } + + return true; +} + +QMacStylePrivate::CocoaControlType cocoaControlType(const QStyleOption *opt, const QWidget *w) +{ + if (const auto *btn = qstyleoption_cast(opt)) { + const bool hasMenu = btn->features & QStyleOptionButton::HasMenu; + // When the contents won't fit in a large sized button, + // and WA_MacNormalSize is not set, make the button square. + // Threshold used to be at 34, not 32. + const auto maxNonSquareHeight = pushButtonDefaultHeight[QStyleHelper::SizeLarge]; + const bool isSquare = (btn->features & QStyleOptionButton::Flat) + || (btn->rect.height() > maxNonSquareHeight + && !(w && w->testAttribute(Qt::WA_MacNormalSize))); + return (isSquare? QMacStylePrivate::Button_SquareButton : + hasMenu ? QMacStylePrivate::Button_PullDown : + QMacStylePrivate::Button_PushButton); + } + + return QMacStylePrivate::NoControl; +} + /** Checks if the actual contents of btn fits inside the free content bounds of 'buttonKindToCheck'. Meant as a helper function for 'initHIThemePushButton' @@ -1992,19 +2045,9 @@ ThemeDrawState QMacStylePrivate::getDrawState(QStyle::State flags) return w; } -static NSButton *makeButton(NSButtonType type, NSBezelStyle style) -{ - NSButton *b = [[NSButton alloc] init]; - b.title = @""; - b.buttonType = type; - b.bezelStyle = style; - return b; -} - NSView *QMacStylePrivate::cocoaControl(CocoaControl widget) const { NSView *bv = cocoaControls.value(widget, nil); - if (!bv) { switch (widget.type) { case Box: { @@ -2017,11 +2060,16 @@ NSView *QMacStylePrivate::cocoaControl(CocoaControl widget) const break; } case Button_CheckBox: - bv = makeButton(NSSwitchButton, NSRegularSquareBezelStyle); - break; case Button_Disclosure: - bv = makeButton(NSOnOffButton, NSDisclosureBezelStyle); + case Button_PushButton: + case Button_RadioButton: + case Button_SquareButton: { + NSButton *bc = [[NSButton alloc] init]; + bc.title = @""; + // See below for style and bezel setting. + bv = bc; break; + } case Button_PopupButton: case Button_PullDown: { NSPopUpButton *bc = [[NSPopUpButton alloc] init]; @@ -2031,12 +2079,6 @@ NSView *QMacStylePrivate::cocoaControl(CocoaControl widget) const bv = bc; break; } - case Button_PushButton: - bv = makeButton(NSMomentaryLightButton, NSRoundedBezelStyle); - break; - case Button_RadioButton: - bv = makeButton(NSRadioButton, NSRegularSquareBezelStyle); - break; case Button_WindowClose: case Button_WindowMiniaturize: case Button_WindowZoom: { @@ -2137,6 +2179,16 @@ NSView *QMacStylePrivate::cocoaControl(CocoaControl widget) const cocoaControls.insert(widget, bv); } + NSButtonType buttonType; + NSBezelStyle bezelStyle; + if (widget.getCocoaButtonTypeAndBezelStyle(&buttonType, &bezelStyle)) { + // FIXME We need to reset the button's type and + // bezel style properties, even when cached. + auto *button = static_cast(bv); + button.buttonType = buttonType; + button.bezelStyle = bezelStyle; + } + return bv; } @@ -3890,10 +3942,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter || (btn->features & QStyleOptionButton::AutoDefaultButton && d->autoDefaultButton == btn->styleObject)); const bool hasMenu = btn->features & QStyleOptionButton::HasMenu; - // TODO When the contents won't fit in a large sized button, - // and WA_MacNormalSize is not set, make the button square. - const bool isSquare = btn->features & QStyleOptionButton::Flat; - const auto ct = hasMenu ? QMacStylePrivate::Button_PullDown : QMacStylePrivate::Button_PushButton; + const auto ct = cocoaControlType(btn, w); const auto cs = d->effectiveAquaSizeConstrain(opt, w); const auto cw = QMacStylePrivate::CocoaControl(ct, cs); auto *pb = static_cast(d->cocoaControl(cw)); @@ -3901,8 +3950,10 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter // This is more convoluted than we initialy thought. See for example // differences between plain and menu button frames. QRectF frameRect; - if (isSquare) { - frameRect = btn->rect; + if (cw.type == QMacStylePrivate::Button_SquareButton) { + frameRect = btn->rect + .adjusted(3, 1, -3, -5) + .adjusted(focusRingWidth, focusRingWidth, -focusRingWidth, -focusRingWidth); } else { const auto frameSize = cw.defaultFrameSize(); if (hasMenu) { @@ -3915,7 +3966,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter frameRect = frameRect.adjusted(0, 0, -4, 0).translated(2, 1); else if (cw.size == QStyleHelper::SizeMini) frameRect = frameRect.adjusted(0, 0, -9, 0).translated(5, 0); - } else { + } else if (cw.type == QMacStylePrivate::Button_PushButton) { // Start from the style option's top-left corner. frameRect = QRectF(btn->rect.topLeft(), QSizeF(btn->rect.width(), frameSize.height())); @@ -3927,8 +3978,6 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter } pb.frame = frameRect.toCGRect(); - pb.bezelStyle = isSquare ? NSBezelStyleShadowlessSquare : NSBezelStyleRounded; - pb.buttonType = NSPushOnPushOffButton; pb.enabled = isEnabled; [pb highlight:isPressed]; pb.state = isHighlighted && !isPressed ? NSOnState : NSOffState; @@ -3936,7 +3985,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter [pb.cell drawBezelWithFrame:r inView:pb.superview]; }); - if (hasMenu && isSquare) { + if (hasMenu && cw.type == QMacStylePrivate::Button_SquareButton) { // Using -[NSPopuButtonCell drawWithFrame:inView:] above won't do // it right because we don't set the text in the native button. const int mbi = proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, w); @@ -3963,12 +4012,17 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter // TODO Remove and use QFocusFrame instead. const int hMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, btn, w); const int vMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, btn, w); - auto focusRect = QRectF::fromCGRect([pb alignmentRectForFrame:pb.frame]); - if (cw.type == QMacStylePrivate::Button_PushButton) - focusRect -= pushButtonShadowMargins[cw.size]; - else if (cw.type == QMacStylePrivate::Button_PullDown) - focusRect -= pullDownButtonShadowMargins[cw.size]; - d->drawFocusRing(p, focusRect, hMargin, vMargin, cw); + if (cw.type == QMacStylePrivate::Button_SquareButton) { + const auto focusRect = frameRect.adjusted(-focusRingWidth, -focusRingWidth, focusRingWidth, focusRingWidth); + d->drawFocusRing(p, focusRect.toAlignedRect(), hMargin, vMargin, 0); + } else { + auto focusRect = QRectF::fromCGRect([pb alignmentRectForFrame:pb.frame]); + if (cw.type == QMacStylePrivate::Button_PushButton) + focusRect -= pushButtonShadowMargins[cw.size]; + else if (cw.type == QMacStylePrivate::Button_PullDown) + focusRect -= pullDownButtonShadowMargins[cw.size]; + d->drawFocusRing(p, focusRect, hMargin, vMargin, cw); + } } } break; diff --git a/src/plugins/styles/mac/qmacstyle_mac_p_p.h b/src/plugins/styles/mac/qmacstyle_mac_p_p.h index af34f8f1e4..d740277e8f 100644 --- a/src/plugins/styles/mac/qmacstyle_mac_p_p.h +++ b/src/plugins/styles/mac/qmacstyle_mac_p_p.h @@ -190,6 +190,7 @@ public: Button_PullDown, // QPushButton with menu Button_PushButton, Button_RadioButton, + Button_SquareButton, // Oversized QPushButton Button_WindowClose, Button_WindowMiniaturize, Button_WindowZoom, @@ -217,6 +218,8 @@ public: bool operator==(const CocoaControl &other) const; QSizeF defaultFrameSize() const; + + bool getCocoaButtonTypeAndBezelStyle(NSButtonType *buttonType, NSBezelStyle *bezelStyle) const; }; From b8dc00ea4bf50fef22eaca163b78ae408530ae55 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Fri, 16 Mar 2018 14:28:11 -0700 Subject: [PATCH 23/51] QMacStyle: Refactor button sizing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We prepare for a better world without HITheme. Sadly, we can't guarantee Cocoa will be good enough as a replacement. So, expect more hardcoded values and margins. Change-Id: I915906b5dbfbfbfc8c7f5c3224fc0ed98562bb9f Reviewed-by: Morten Johan Sørvig --- src/plugins/styles/mac/qmacstyle_mac.mm | 90 +++++++++++----------- src/plugins/styles/mac/qmacstyle_mac_p_p.h | 1 + 2 files changed, 47 insertions(+), 44 deletions(-) diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index f44747c295..15ffd4853a 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -344,8 +344,16 @@ static const QMarginsF pushButtonShadowMargins[3] = { { 1.5, 0.5, 1.5, 2.5 } }; +// These are frame heights as reported by Xcode 9's Interface Builder. +// Alignemnet rectangle's heights match for push and popup buttons +// with respective values 21, 18 and 15. + static const qreal pushButtonDefaultHeight[3] = { - 32, 28, 24 + 32, 28, 16 +}; + +static const qreal popupButtonDefaultHeight[3] = { + 26, 22, 15 }; static const int toolButtonArrowSize = 7; @@ -1561,28 +1569,48 @@ QSizeF QMacStylePrivate::CocoaControl::defaultFrameSize() const // has a reasonable frame set. IOW, it's a chicken and egg problem. // These values are as observed in Xcode 9's Interface Builder. - if (type == Button_PushButton) { - if (size == QStyleHelper::SizeLarge) - return QSizeF(-1, 32); - if (size == QStyleHelper::SizeSmall) - return QSizeF(-1, 28); - if (size == QStyleHelper::SizeMini) - return QSizeF(-1, 16); - } + if (type == Button_PushButton) + return QSizeF(-1, pushButtonDefaultHeight[size]); if (type == Button_PopupButton - || type == Button_PullDown) { - if (size == QStyleHelper::SizeLarge) - return QSizeF(-1, 26); - if (size == QStyleHelper::SizeSmall) - return QSizeF(-1, 22); - if (size == QStyleHelper::SizeMini) - return QSizeF(-1, 15); - } + || type == Button_PullDown) + return QSizeF(-1, popupButtonDefaultHeight[size]); return QSizeF(); } +QRectF QMacStylePrivate::CocoaControl::adjustedControlFrame(const QRectF &rect) const +{ + QRectF frameRect; + if (type == QMacStylePrivate::Button_SquareButton) { + frameRect = rect.adjusted(3, 1, -3, -5) + .adjusted(focusRingWidth, focusRingWidth, -focusRingWidth, -focusRingWidth); + } else { + const auto frameSize = defaultFrameSize(); + if (type == QMacStylePrivate::Button_PullDown) { + // Center in the style option's rect. + frameRect = QRectF(QPointF(0, (rect.height() - frameSize.height()) / 2.0), + QSizeF(rect.width(), frameSize.height())); + if (size == QStyleHelper::SizeLarge) + frameRect = frameRect.adjusted(0, 0, -6, 0).translated(3, -1); + else if (size == QStyleHelper::SizeSmall) + frameRect = frameRect.adjusted(0, 0, -4, 0).translated(2, 1); + else if (size == QStyleHelper::SizeMini) + frameRect = frameRect.adjusted(0, 0, -9, 0).translated(5, 0); + } else if (type == QMacStylePrivate::Button_PushButton) { + // Start from the style option's top-left corner. + frameRect = QRectF(rect.topLeft(), + QSizeF(rect.width(), frameSize.height())); + if (size == QStyleHelper::SizeSmall) + frameRect = frameRect.translated(0, 1.5); + else if (size == QStyleHelper::SizeMini) + frameRect = frameRect.adjusted(0, 0, -8, 0).translated(4, 4); + } + } + + return frameRect; +} + bool QMacStylePrivate::CocoaControl::getCocoaButtonTypeAndBezelStyle(NSButtonType *buttonType, NSBezelStyle *bezelStyle) const { switch (type) { @@ -3949,33 +3977,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter // Ensure same size and location as we used to have with HITheme. // This is more convoluted than we initialy thought. See for example // differences between plain and menu button frames. - QRectF frameRect; - if (cw.type == QMacStylePrivate::Button_SquareButton) { - frameRect = btn->rect - .adjusted(3, 1, -3, -5) - .adjusted(focusRingWidth, focusRingWidth, -focusRingWidth, -focusRingWidth); - } else { - const auto frameSize = cw.defaultFrameSize(); - if (hasMenu) { - // Center in the style option's rect. - frameRect = QRectF(QPointF(0, (btn->rect.height() - frameSize.height()) / 2.0), - QSizeF(btn->rect.width(), frameSize.height())); - if (cw.size == QStyleHelper::SizeLarge) - frameRect = frameRect.adjusted(0, 0, -6, 0).translated(3, -1); - else if (cw.size == QStyleHelper::SizeSmall) - frameRect = frameRect.adjusted(0, 0, -4, 0).translated(2, 1); - else if (cw.size == QStyleHelper::SizeMini) - frameRect = frameRect.adjusted(0, 0, -9, 0).translated(5, 0); - } else if (cw.type == QMacStylePrivate::Button_PushButton) { - // Start from the style option's top-left corner. - frameRect = QRectF(btn->rect.topLeft(), - QSizeF(btn->rect.width(), frameSize.height())); - if (cw.size == QStyleHelper::SizeSmall) - frameRect = frameRect.translated(0, 1.5); - else if (cw.size == QStyleHelper::SizeMini) - frameRect = frameRect.adjusted(0, 0, -8, 0).translated(4, 4); - } - } + const QRectF frameRect = cw.adjustedControlFrame(btn->rect); pb.frame = frameRect.toCGRect(); pb.enabled = isEnabled; diff --git a/src/plugins/styles/mac/qmacstyle_mac_p_p.h b/src/plugins/styles/mac/qmacstyle_mac_p_p.h index d740277e8f..cef9da041f 100644 --- a/src/plugins/styles/mac/qmacstyle_mac_p_p.h +++ b/src/plugins/styles/mac/qmacstyle_mac_p_p.h @@ -218,6 +218,7 @@ public: bool operator==(const CocoaControl &other) const; QSizeF defaultFrameSize() const; + QRectF adjustedControlFrame(const QRectF &rect) const; bool getCocoaButtonTypeAndBezelStyle(NSButtonType *buttonType, NSBezelStyle *bezelStyle) const; }; From fae42e1e73edd2aa18ec257933d856a1d88337a7 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Mon, 19 Mar 2018 13:15:00 -0700 Subject: [PATCH 24/51] QMacStyle: Don't highlight square buttons text when pressed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Native square buttons keep their text black when pressed or on. Plus using the QStyleOptionButton variable over the QStyleOption one where appropriate. Change-Id: Idba8197e64d408e8a0987f1ef9243fde08e3e839 Reviewed-by: Morten Johan Sørvig --- src/plugins/styles/mac/qmacstyle_mac.mm | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index 15ffd4853a..043a910a7c 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -3958,8 +3958,8 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter // takes precedence over a normal default button if ((btn->features & QStyleOptionButton::AutoDefaultButton) && isActive && hasFocus) - d->autoDefaultButton = opt->styleObject; - else if (d->autoDefaultButton == opt->styleObject) + d->autoDefaultButton = btn->styleObject; + else if (d->autoDefaultButton == btn->styleObject) d->autoDefaultButton = nullptr; const bool isEnabled = btn->state & State_Enabled; @@ -3971,7 +3971,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter && d->autoDefaultButton == btn->styleObject)); const bool hasMenu = btn->features & QStyleOptionButton::HasMenu; const auto ct = cocoaControlType(btn, w); - const auto cs = d->effectiveAquaSizeConstrain(opt, w); + const auto cs = d->effectiveAquaSizeConstrain(btn, w); const auto cw = QMacStylePrivate::CocoaControl(ct, cs); auto *pb = static_cast(d->cocoaControl(cw)); // Ensure same size and location as we used to have with HITheme. @@ -4041,7 +4041,9 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter const bool isActive = btn.state & State_Active; const bool isPressed = btn.state & State_Sunken; - if (!hasMenu) { + const auto ct = cocoaControlType(&btn, w); + + if (!hasMenu && ct != QMacStylePrivate::Button_SquareButton) { if (isPressed || (isActive && ((btn.features & QStyleOptionButton::DefaultButton && !d->autoDefaultButton) From 1d616e764d33da1d3435ae8ee366f6ea8af71787 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Thu, 22 Mar 2018 15:35:34 +0100 Subject: [PATCH 25/51] Avoid of bounds memory reads when scaling and mirroring images The bounds check we had wasn't complete for mirroring cases. Task-number: QTBUG-65387 Change-Id: I5333912621c1223f83b4f1b95f2b16d12b520bd2 Reviewed-by: Lars Knoll Reviewed-by: Eirik Aavitsland --- src/gui/painting/qblendfunctions_p.h | 20 ++++++++++++++++++++ src/gui/painting/qdrawhelper_sse2.cpp | 10 ++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/gui/painting/qblendfunctions_p.h b/src/gui/painting/qblendfunctions_p.h index 167f725143..dc7a4dfe8c 100644 --- a/src/gui/painting/qblendfunctions_p.h +++ b/src/gui/painting/qblendfunctions_p.h @@ -137,6 +137,16 @@ void qt_scale_image_16bit(uchar *destPixels, int dbpl, // this bounds check here is required as floating point rounding above might in some cases lead to // w/h values that are one pixel too large, falling outside of the valid image area. + const int ystart = srcy >> 16; + if (ystart >= srch && iy < 0) { + srcy += iy; + --h; + } + const int xstart = basex >> 16; + if (xstart >= (int)(sbpl/sizeof(SRC)) && ix < 0) { + basex += ix; + --w; + } int yend = (srcy + iy * (h - 1)) >> 16; if (yend < 0 || yend >= srch) --h; @@ -248,6 +258,16 @@ template void qt_scale_image_32bit(uchar *destPixels, int dbpl, // this bounds check here is required as floating point rounding above might in some cases lead to // w/h values that are one pixel too large, falling outside of the valid image area. + const int ystart = srcy >> 16; + if (ystart >= srch && iy < 0) { + srcy += iy; + --h; + } + const int xstart = basex >> 16; + if (xstart >= (int)(sbpl/sizeof(quint32)) && ix < 0) { + basex += ix; + --w; + } int yend = (srcy + iy * (h - 1)) >> 16; if (yend < 0 || yend >= srch) --h; diff --git a/src/gui/painting/qdrawhelper_sse2.cpp b/src/gui/painting/qdrawhelper_sse2.cpp index bfe2080298..3212ffdd2d 100644 --- a/src/gui/painting/qdrawhelper_sse2.cpp +++ b/src/gui/painting/qdrawhelper_sse2.cpp @@ -558,6 +558,16 @@ void qt_scale_image_argb32_on_argb32_sse2(uchar *destPixels, int dbpl, // this bounds check here is required as floating point rounding above might in some cases lead to // w/h values that are one pixel too large, falling outside of the valid image area. + const int ystart = srcy >> 16; + if (ystart >= srch && iy < 0) { + srcy += iy; + --h; + } + const int xstart = basex >> 16; + if (xstart >= (int)(sbpl/sizeof(quint32)) && ix < 0) { + basex += ix; + --w; + } int yend = (srcy + iy * (h - 1)) >> 16; if (yend < 0 || yend >= srch) --h; From 8e93988cce4af9f1dab452152a0995f400f2d7d9 Mon Sep 17 00:00:00 2001 From: Kari Oikarinen Date: Tue, 6 Mar 2018 15:04:37 +0200 Subject: [PATCH 26/51] Blacklist tst_QProcess::softExitInSlots on Windows Task-number: QTBUG-66903 Task-number: QTBUG-66216 Change-Id: I4a36d6f4b980f016e11fd7a8840dbc60a2964e83 Reviewed-by: Sami Nurmenniemi Reviewed-by: Ville Voutilainen --- tests/auto/corelib/io/qprocess/BLACKLIST | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/auto/corelib/io/qprocess/BLACKLIST b/tests/auto/corelib/io/qprocess/BLACKLIST index a278af12d3..b355bb0f75 100644 --- a/tests/auto/corelib/io/qprocess/BLACKLIST +++ b/tests/auto/corelib/io/qprocess/BLACKLIST @@ -4,3 +4,6 @@ redhatenterpriselinuxworkstation-6.6 [fileWriterProcess] msvc-2015 ci msvc-2017 ci +[softExitInSlots] +# QTBUG-66903 +windows From f3db6971eec4854abd15cc8fe3375e8beb774e8a Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Mon, 5 Mar 2018 12:08:20 +0100 Subject: [PATCH 27/51] winrt: Rework socket handling Buffer handling is now completely moved to the worker. Instead of moving data around all the time, the worker is responsible for buffer handling. When reads happen, the data that is read is used directly from the worker and its buffer is updated. With the previous approach it was possible, that transfers never completed. It was possible, that new data was read between calls of bytesAvailable and read and the availability of that data was never communicated to the user. If a read that does not read all the data happens, we signal, that there is still data available, so that the user is notified about that fact. At the same time we avoid unnecessary readyRead calls by blocking them until a read happens. To make future debugging sessions easier, categorized logging (including verbose) was added to the socket engine. Task-number: QTBUG-65556 Change-Id: I12020ffcccf8eb3efec9c36dc5b0e6c0ebef7eb5 Reviewed-by: Andre de la Rocha Reviewed-by: Maurice Kalinowski --- .../socket/qnativesocketengine_winrt.cpp | 194 ++++++++++-------- .../socket/qnativesocketengine_winrt_p.h | 23 +-- 2 files changed, 119 insertions(+), 98 deletions(-) diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index 9df5f0c500..cd2873fb59 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -87,6 +87,9 @@ typedef IAsyncOperationWithProgress IAsyncBufferOperation; QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcNetworkSocket, "qt.network.socket"); +Q_LOGGING_CATEGORY(lcNetworkSocketVerbose, "qt.network.socket.verbose"); + #if _MSC_VER >= 1900 static HRESULT qt_winrt_try_create_thread_network_context(QString host, ComPtr &context) { @@ -167,11 +170,14 @@ public: SocketEngineWorker(QNativeSocketEnginePrivate *engine) : enginePrivate(engine) { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << engine; } ~SocketEngineWorker() { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO; if (Q_UNLIKELY(initialReadOp)) { + qCDebug(lcNetworkSocket) << Q_FUNC_INFO << "Closing initial read operation"; ComPtr info; HRESULT hr = initialReadOp.As(&info); Q_ASSERT_SUCCEEDED(hr); @@ -184,6 +190,7 @@ public: } if (readOp) { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << "Closing read operation"; ComPtr info; HRESULT hr = readOp.As(&info); Q_ASSERT_SUCCEEDED(hr); @@ -196,6 +203,7 @@ public: } if (connectOp) { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << "Closing connect operation"; ComPtr info; HRESULT hr = connectOp.As(&info); Q_ASSERT_SUCCEEDED(hr); @@ -210,30 +218,13 @@ public: signals: void connectOpFinished(bool success, QAbstractSocket::SocketError error, WinRTSocketEngine::ErrorString errorString); - void newDatagramsReceived(const QList &datagram); - void newDataReceived(const QVector &data); + void newDataReceived(); void socketErrorOccured(QAbstractSocket::SocketError error); -public slots: - Q_INVOKABLE void notifyAboutNewDatagrams() - { - QMutexLocker locker(&mutex); - QList datagrams = pendingDatagrams; - pendingDatagrams.clear(); - emit newDatagramsReceived(datagrams); - } - - Q_INVOKABLE void notifyAboutNewData() - { - QMutexLocker locker(&mutex); - const QVector newData = std::move(pendingData); - pendingData.clear(); - emit newDataReceived(newData); - } - public: void startReading() { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO; ComPtr buffer; HRESULT hr = g->bufferFactory->Create(READ_BUFFER_SIZE, &buffer); Q_ASSERT_SUCCEEDED(hr); @@ -249,6 +240,7 @@ public: HRESULT onConnectOpFinished(IAsyncAction *action, AsyncStatus) { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO; HRESULT hr = action->GetResults(); if (FAILED(hr)) { if (hr == HRESULT_FROM_WIN32(WSAETIMEDOUT)) { @@ -287,6 +279,7 @@ public: HRESULT OnNewDatagramReceived(IDatagramSocket *, IDatagramSocketMessageReceivedEventArgs *args) { + qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO; WinRtDatagram datagram; QHostAddress returnAddress; ComPtr remoteHost; @@ -311,10 +304,11 @@ public: datagram.data.resize(length); hr = reader->ReadBytes(length, reinterpret_cast(datagram.data.data())); RETURN_OK_IF_FAILED("Could not read datagram"); + QMutexLocker locker(&mutex); // Notify the engine about new datagrams being present at the next event loop iteration - if (pendingDatagrams.isEmpty()) - QMetaObject::invokeMethod(this, "notifyAboutNewDatagrams", Qt::QueuedConnection); + if (emitDataReceived) + emit newDataReceived(); pendingDatagrams << datagram; return S_OK; @@ -322,6 +316,7 @@ public: HRESULT onReadyRead(IAsyncBufferOperation *asyncInfo, AsyncStatus status) { + qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO; if (asyncInfo == initialReadOp.Get()) { initialReadOp.Reset(); } else if (asyncInfo == readOp.Get()) { @@ -334,6 +329,7 @@ public: // that the connection was closed. The socket cannot be closed here, as the subsequent read // might fail then. if (status == Error || status == Canceled) { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << "Remote host closed"; emit socketErrorOccured(QAbstractSocket::RemoteHostClosedError); return S_OK; } @@ -358,6 +354,7 @@ public: // the closing of the socket won't be communicated to the caller. So only the error is set. The // actual socket close happens inside of read. if (!bufferLength) { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << "Remote host closed"; emit socketErrorOccured(QAbstractSocket::RemoteHostClosedError); return S_OK; } @@ -378,10 +375,10 @@ public: } QByteArray newData(reinterpret_cast(data), qint64(bufferLength)); + QMutexLocker readLocker(&mutex); - if (pendingData.isEmpty()) - QMetaObject::invokeMethod(this, "notifyAboutNewData", Qt::QueuedConnection); - pendingData << newData; + emit newDataReceived(); + pendingData.append(newData); readLocker.unlock(); hr = QEventDispatcherWinRT::runOnXamlThread([buffer, this]() { @@ -433,7 +430,8 @@ private: ComPtr tcpSocket; QList pendingDatagrams; - QVector pendingData; + bool emitDataReceived = true; + QByteArray pendingData; // Protects pendingData/pendingDatagrams which are accessed from native callbacks QMutex mutex; @@ -509,6 +507,7 @@ static AsyncStatus opStatus(const ComPtr &op) static qint64 writeIOStream(ComPtr stream, const char *data, qint64 len) { + qCDebug(lcNetworkSocket) << Q_FUNC_INFO << data << len; ComPtr buffer; HRESULT hr = g->bufferFactory->Create(len, &buffer); Q_ASSERT_SUCCEEDED(hr); @@ -533,6 +532,7 @@ static qint64 writeIOStream(ComPtr stream, const char *data, qint QNativeSocketEngine::QNativeSocketEngine(QObject *parent) : QAbstractSocketEngine(*new QNativeSocketEnginePrivate(), parent) { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << parent; qRegisterMetaType(); qRegisterMetaType(); Q_D(QNativeSocketEngine); @@ -546,20 +546,20 @@ QNativeSocketEngine::QNativeSocketEngine(QObject *parent) connect(this, SIGNAL(writeReady()), SLOT(writeNotification()), Qt::QueuedConnection); connect(d->worker, &SocketEngineWorker::connectOpFinished, this, &QNativeSocketEngine::handleConnectOpFinished, Qt::QueuedConnection); - connect(d->worker, &SocketEngineWorker::newDatagramsReceived, this, &QNativeSocketEngine::handleNewDatagrams, Qt::QueuedConnection); - connect(d->worker, &SocketEngineWorker::newDataReceived, - this, &QNativeSocketEngine::handleNewData, Qt::QueuedConnection); + connect(d->worker, &SocketEngineWorker::newDataReceived, this, &QNativeSocketEngine::handleNewData, Qt::QueuedConnection); connect(d->worker, &SocketEngineWorker::socketErrorOccured, this, &QNativeSocketEngine::handleTcpError, Qt::QueuedConnection); } QNativeSocketEngine::~QNativeSocketEngine() { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO; close(); } bool QNativeSocketEngine::initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol) { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << type << protocol; Q_D(QNativeSocketEngine); if (isValid()) close(); @@ -575,6 +575,7 @@ bool QNativeSocketEngine::initialize(QAbstractSocket::SocketType type, QAbstract bool QNativeSocketEngine::initialize(qintptr socketDescriptor, QAbstractSocket::SocketState socketState) { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << socketDescriptor << socketState; Q_D(QNativeSocketEngine); if (isValid()) @@ -622,18 +623,21 @@ bool QNativeSocketEngine::isValid() const bool QNativeSocketEngine::connectToHost(const QHostAddress &address, quint16 port) { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << address << port; const QString addressString = address.toString(); return connectToHostByName(addressString, port); } bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port) { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << name << port; Q_D(QNativeSocketEngine); HRESULT hr; #if _MSC_VER >= 1900 ComPtr networkContext; if (!qEnvironmentVariableIsEmpty("QT_WINRT_USE_THREAD_NETWORK_CONTEXT")) { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << "Creating network context"; hr = qt_winrt_try_create_thread_network_context(name, networkContext); if (FAILED(hr)) { setError(QAbstractSocket::ConnectionRefusedError, QLatin1String("Could not create thread network context.")); @@ -668,6 +672,7 @@ bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port) #if _MSC_VER >= 1900 if (networkContext != nullptr) { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << "Closing network context"; ComPtr networkContextCloser; hr = networkContext.As(&networkContextCloser); Q_ASSERT_SUCCEEDED(hr); @@ -691,6 +696,7 @@ bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port) bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port) { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << address << port; Q_D(QNativeSocketEngine); HRESULT hr; // runOnXamlThread may only return S_OK (will assert otherwise) so no need to check its result. @@ -773,6 +779,7 @@ bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port) bool QNativeSocketEngine::listen() { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO; Q_D(QNativeSocketEngine); Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::listen(), false); Q_CHECK_STATE(QNativeSocketEngine::listen(), QAbstractSocket::BoundState, false); @@ -787,6 +794,7 @@ bool QNativeSocketEngine::listen() int QNativeSocketEngine::accept() { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO; Q_D(QNativeSocketEngine); Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::accept(), -1); Q_CHECK_STATE(QNativeSocketEngine::accept(), QAbstractSocket::ListeningState, -1); @@ -810,6 +818,7 @@ int QNativeSocketEngine::accept() void QNativeSocketEngine::close() { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO; Q_D(QNativeSocketEngine); if (d->closingDown) @@ -878,16 +887,14 @@ void QNativeSocketEngine::close() bool QNativeSocketEngine::joinMulticastGroup(const QHostAddress &groupAddress, const QNetworkInterface &iface) { - Q_UNUSED(groupAddress); - Q_UNUSED(iface); + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << groupAddress << iface; Q_UNIMPLEMENTED(); return false; } bool QNativeSocketEngine::leaveMulticastGroup(const QHostAddress &groupAddress, const QNetworkInterface &iface) { - Q_UNUSED(groupAddress); - Q_UNUSED(iface); + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << groupAddress << iface; Q_UNIMPLEMENTED(); return false; } @@ -900,7 +907,7 @@ QNetworkInterface QNativeSocketEngine::multicastInterface() const bool QNativeSocketEngine::setMulticastInterface(const QNetworkInterface &iface) { - Q_UNUSED(iface); + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << iface; Q_UNIMPLEMENTED(); return false; } @@ -911,11 +918,16 @@ qint64 QNativeSocketEngine::bytesAvailable() const if (d->socketType != QAbstractSocket::TcpSocket) return -1; - return d->bytesAvailable; + QMutexLocker locker(&d->worker->mutex); + const qint64 bytesAvailable = d->worker->pendingData.length(); + + qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << bytesAvailable; + return bytesAvailable; } qint64 QNativeSocketEngine::read(char *data, qint64 maxlen) { + qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << maxlen; Q_D(QNativeSocketEngine); if (d->socketType != QAbstractSocket::TcpSocket) return -1; @@ -923,37 +935,37 @@ qint64 QNativeSocketEngine::read(char *data, qint64 maxlen) // There will be a read notification when the socket was closed by the remote host. If that // happens and there isn't anything left in the buffer, we have to return -1 in order to signal // the closing of the socket. - QMutexLocker mutexLocker(&d->readMutex); - if (d->pendingData.isEmpty() && d->socketState != QAbstractSocket::ConnectedState) { + QMutexLocker mutexLocker(&d->worker->mutex); + if (d->worker->pendingData.isEmpty() && d->socketState != QAbstractSocket::ConnectedState) { close(); return -1; } QByteArray readData; - qint64 leftToMaxLen = maxlen; - while (leftToMaxLen > 0 && !d->pendingData.isEmpty()) { - QByteArray pendingData = d->pendingData.takeFirst(); - // Do not read the whole data. Put the rest of it back into the "queue" - if (leftToMaxLen < pendingData.length()) { - readData += pendingData.left(leftToMaxLen); - pendingData = pendingData.remove(0, maxlen); - d->pendingData.prepend(pendingData); - break; - } else { - readData += pendingData; - leftToMaxLen -= pendingData.length(); - } + const int copyLength = qMin(maxlen, qint64(d->worker->pendingData.length())); + if (maxlen >= d->worker->pendingData.length()) { + qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << "Reading full buffer"; + readData = d->worker->pendingData; + d->worker->pendingData.clear(); + d->emitReadReady = true; + } else { + qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << "Reading part of the buffer (" + << copyLength << "of" << d->worker->pendingData.length() << "bytes"; + readData = d->worker->pendingData.left(maxlen); + d->worker->pendingData.remove(0, maxlen); + if (d->notifyOnRead) + emit readReady(); } - const int copyLength = qMin(maxlen, qint64(readData.length())); - d->bytesAvailable -= copyLength; mutexLocker.unlock(); memcpy(data, readData, copyLength); + qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << "Read" << copyLength << "bytes"; return copyLength; } qint64 QNativeSocketEngine::write(const char *data, qint64 len) { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << data << len; Q_D(QNativeSocketEngine); if (!isValid()) return -1; @@ -978,16 +990,17 @@ qint64 QNativeSocketEngine::write(const char *data, qint64 len) qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QIpPacketHeader *header, PacketHeaderOptions) { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << maxlen; #ifndef QT_NO_UDPSOCKET Q_D(QNativeSocketEngine); - QMutexLocker locker(&d->readMutex); - if (d->socketType != QAbstractSocket::UdpSocket || d->pendingDatagrams.isEmpty()) { + QMutexLocker locker(&d->worker->mutex); + if (d->socketType != QAbstractSocket::UdpSocket || d->worker->pendingDatagrams.isEmpty()) { if (header) header->clear(); return -1; } - WinRtDatagram datagram = d->pendingDatagrams.takeFirst(); + WinRtDatagram datagram = d->worker->pendingDatagrams.takeFirst(); if (header) *header = datagram.header; @@ -996,10 +1009,16 @@ qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QIpPacketHea if (maxlen < datagram.data.length()) { readOrigin = datagram.data.left(maxlen); datagram.data = datagram.data.remove(0, maxlen); - d->pendingDatagrams.prepend(datagram); + d->worker->pendingDatagrams.prepend(datagram); } else { readOrigin = datagram.data; } + if (d->worker->pendingDatagrams.isEmpty()) { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << "That's all folks"; + d->worker->emitDataReceived = true; + d->emitReadReady = true; + } + locker.unlock(); memcpy(data, readOrigin, qMin(maxlen, qint64(datagram.data.length()))); return readOrigin.length(); @@ -1013,6 +1032,7 @@ qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QIpPacketHea qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 len, const QIpPacketHeader &header) { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << data << len; #ifndef QT_NO_UDPSOCKET Q_D(QNativeSocketEngine); if (d->socketType != QAbstractSocket::UdpSocket) @@ -1051,18 +1071,18 @@ qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 len, const QI bool QNativeSocketEngine::hasPendingDatagrams() const { Q_D(const QNativeSocketEngine); - QMutexLocker locker(&d->readMutex); - return d->pendingDatagrams.length() > 0; + QMutexLocker locker(&d->worker->mutex); + return d->worker->pendingDatagrams.length() > 0; } qint64 QNativeSocketEngine::pendingDatagramSize() const { Q_D(const QNativeSocketEngine); - QMutexLocker locker(&d->readMutex); - if (d->pendingDatagrams.isEmpty()) + QMutexLocker locker(&d->worker->mutex); + if (d->worker->pendingDatagrams.isEmpty()) return -1; - return d->pendingDatagrams.at(0).data.length(); + return d->worker->pendingDatagrams.at(0).data.length(); } qint64 QNativeSocketEngine::bytesToWrite() const @@ -1078,6 +1098,7 @@ qint64 QNativeSocketEngine::receiveBufferSize() const void QNativeSocketEngine::setReceiveBufferSize(qint64 bufferSize) { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << bufferSize; Q_D(QNativeSocketEngine); d->setOption(QAbstractSocketEngine::ReceiveBufferSocketOption, bufferSize); } @@ -1090,6 +1111,7 @@ qint64 QNativeSocketEngine::sendBufferSize() const void QNativeSocketEngine::setSendBufferSize(qint64 bufferSize) { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << bufferSize; Q_D(QNativeSocketEngine); d->setOption(QAbstractSocketEngine::SendBufferSocketOption, bufferSize); } @@ -1102,12 +1124,14 @@ int QNativeSocketEngine::option(QAbstractSocketEngine::SocketOption option) cons bool QNativeSocketEngine::setOption(QAbstractSocketEngine::SocketOption option, int value) { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << option << value; Q_D(QNativeSocketEngine); return d->setOption(option, value); } bool QNativeSocketEngine::waitForRead(int msecs, bool *timedOut) { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << msecs; Q_D(QNativeSocketEngine); Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::waitForRead(), false); Q_CHECK_NOT_STATE(QNativeSocketEngine::waitForRead(), @@ -1124,8 +1148,8 @@ bool QNativeSocketEngine::waitForRead(int msecs, bool *timedOut) return true; // If we are a client, we are ready to read if our buffer has data - QMutexLocker locker(&d->readMutex); - if (!d->pendingData.isEmpty()) + QMutexLocker locker(&d->worker->mutex); + if (!d->worker->pendingData.isEmpty()) return true; // Nothing to do, wait for more events @@ -1142,7 +1166,7 @@ bool QNativeSocketEngine::waitForRead(int msecs, bool *timedOut) bool QNativeSocketEngine::waitForWrite(int msecs, bool *timedOut) { - Q_UNUSED(msecs); + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << msecs; Q_UNUSED(timedOut); Q_D(QNativeSocketEngine); if (d->socketState == QAbstractSocket::ConnectingState) { @@ -1157,11 +1181,9 @@ bool QNativeSocketEngine::waitForWrite(int msecs, bool *timedOut) bool QNativeSocketEngine::waitForReadOrWrite(bool *readyToRead, bool *readyToWrite, bool checkRead, bool checkWrite, int msecs, bool *timedOut) { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << checkRead << checkWrite << msecs; Q_UNUSED(readyToRead); Q_UNUSED(readyToWrite); - Q_UNUSED(checkRead); - Q_UNUSED(checkWrite); - Q_UNUSED(msecs); Q_UNUSED(timedOut); return false; } @@ -1174,6 +1196,7 @@ bool QNativeSocketEngine::isReadNotificationEnabled() const void QNativeSocketEngine::setReadNotificationEnabled(bool enable) { + qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << enable; Q_D(QNativeSocketEngine); d->notifyOnRead = enable; } @@ -1186,6 +1209,7 @@ bool QNativeSocketEngine::isWriteNotificationEnabled() const void QNativeSocketEngine::setWriteNotificationEnabled(bool enable) { + qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << enable; Q_D(QNativeSocketEngine); d->notifyOnWrite = enable; if (enable && d->socketState == QAbstractSocket::ConnectedState) { @@ -1203,12 +1227,14 @@ bool QNativeSocketEngine::isExceptionNotificationEnabled() const void QNativeSocketEngine::setExceptionNotificationEnabled(bool enable) { + qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << enable; Q_D(QNativeSocketEngine); d->notifyOnException = enable; } void QNativeSocketEngine::establishRead() { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO; Q_D(QNativeSocketEngine); HRESULT hr; @@ -1222,6 +1248,7 @@ void QNativeSocketEngine::establishRead() void QNativeSocketEngine::handleConnectOpFinished(bool success, QAbstractSocket::SocketError error, WinRTSocketEngine::ErrorString errorString) { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << success << error << errorString; Q_D(QNativeSocketEngine); disconnect(d->worker, &SocketEngineWorker::connectOpFinished, this, &QNativeSocketEngine::handleConnectOpFinished); @@ -1246,29 +1273,24 @@ void QNativeSocketEngine::handleConnectOpFinished(bool success, QAbstractSocket: establishRead(); } -void QNativeSocketEngine::handleNewDatagrams(const QList &datagrams) +void QNativeSocketEngine::handleNewData() { + qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO; Q_D(QNativeSocketEngine); - QMutexLocker locker(&d->readMutex); - d->pendingDatagrams.append(datagrams); - if (d->notifyOnRead) - emit readReady(); -} -void QNativeSocketEngine::handleNewData(const QVector &data) -{ - Q_D(QNativeSocketEngine); - QMutexLocker locker(&d->readMutex); - d->pendingData.append(data); - for (const QByteArray &newData : data) - d->bytesAvailable += newData.length(); - locker.unlock(); - if (d->notifyOnRead) - readNotification(); + if (d->notifyOnRead && d->emitReadReady) { + if (d->socketType == QAbstractSocket::UdpSocket && !d->worker->emitDataReceived) + return; + qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << "Emitting readReady"; + emit readReady(); + d->worker->emitDataReceived = false; + d->emitReadReady = false; + } } void QNativeSocketEngine::handleTcpError(QAbstractSocket::SocketError error) { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << error; Q_D(QNativeSocketEngine); WinRTSocketEngine::ErrorString errorString; switch (error) { @@ -1287,6 +1309,7 @@ void QNativeSocketEngine::handleTcpError(QAbstractSocket::SocketError error) bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType, QAbstractSocket::NetworkLayerProtocol &socketProtocol) { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << socketType << socketProtocol; Q_UNUSED(socketProtocol); HRESULT hr; @@ -1343,10 +1366,12 @@ QNativeSocketEnginePrivate::QNativeSocketEnginePrivate() , sslSocket(nullptr) , connectionToken( { -1 } ) { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO; } QNativeSocketEnginePrivate::~QNativeSocketEnginePrivate() { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO; if (socketDescriptor == -1 || connectionToken.value == -1) return; @@ -1362,6 +1387,7 @@ QNativeSocketEnginePrivate::~QNativeSocketEnginePrivate() void QNativeSocketEnginePrivate::setError(QAbstractSocket::SocketError error, WinRTSocketEngine::ErrorString errorString) const { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << error << errorString; if (hasSetSocketError) { // Only set socket errors once for one engine; expect the // socket to recreate its engine after an error. Note: There's @@ -1523,6 +1549,7 @@ int QNativeSocketEnginePrivate::option(QAbstractSocketEngine::SocketOption opt) bool QNativeSocketEnginePrivate::setOption(QAbstractSocketEngine::SocketOption opt, int v) { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << opt << v; ComPtr control; if (socketType == QAbstractSocket::TcpSocket) { if (FAILED(tcpSocket()->get_Control(&control))) { @@ -1583,6 +1610,7 @@ bool QNativeSocketEnginePrivate::setOption(QAbstractSocketEngine::SocketOption o bool QNativeSocketEnginePrivate::fetchConnectionParameters() { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO; localPort = 0; localAddress.clear(); peerPort = 0; @@ -1659,6 +1687,7 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters() HRESULT QNativeSocketEnginePrivate::handleClientConnection(IStreamSocketListener *listener, IStreamSocketListenerConnectionReceivedEventArgs *args) { + qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO; Q_Q(QNativeSocketEngine); Q_UNUSED(listener) IStreamSocket *socket; @@ -1672,6 +1701,7 @@ HRESULT QNativeSocketEnginePrivate::handleClientConnection(IStreamSocketListener HRESULT QNativeSocketEnginePrivate::handleNewDatagram(IDatagramSocket *socket, IDatagramSocketMessageReceivedEventArgs *args) { + qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO; Q_Q(QNativeSocketEngine); Q_UNUSED(socket); diff --git a/src/network/socket/qnativesocketengine_winrt_p.h b/src/network/socket/qnativesocketengine_winrt_p.h index 13922cb397..d7b44174b0 100644 --- a/src/network/socket/qnativesocketengine_winrt_p.h +++ b/src/network/socket/qnativesocketengine_winrt_p.h @@ -54,6 +54,7 @@ #include #include #include +#include #include #include #include "QtNetwork/qhostaddress.h" @@ -63,6 +64,9 @@ QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(lcNetworkSocket) +Q_DECLARE_LOGGING_CATEGORY(lcNetworkSocketVerbose) + namespace WinRTSocketEngine { enum ErrorString { NonBlockingInitFailedErrorString, @@ -178,8 +182,7 @@ private slots: void establishRead(); void handleConnectOpFinished(bool success, QAbstractSocket::SocketError error, WinRTSocketEngine::ErrorString errorString); - void handleNewDatagrams(const QList &datagram); - void handleNewData(const QVector &data); + void handleNewData(); void handleTcpError(QAbstractSocket::SocketError error); private: @@ -218,26 +221,14 @@ private: { return reinterpret_cast(socketDescriptor); } Microsoft::WRL::ComPtr tcpListener; - // In case of TCP readMutex protects readBytes and bytesAvailable. In case of UDP it is - // pendingDatagrams. They are written inside native callbacks (handleReadyRead and - // handleNewDatagrams/putIntoPendingDatagramsList) - mutable QMutex readMutex; - - // Protected by readMutex. Written in handleReadyRead (native callback) - QAtomicInteger bytesAvailable; - - // Protected by readMutex. Written in handleNewData/putIntoPendingData (native callback) - QVector pendingData; - - // Protected by readMutex. Written in handleNewDatagrams/putIntoPendingDatagramsList - QList pendingDatagrams; - QList pendingConnections; QList currentConnections; QEventLoop eventLoop; QAbstractSocket *sslSocket; EventRegistrationToken connectionToken; + bool emitReadReady = true; + HRESULT handleNewDatagram(ABI::Windows::Networking::Sockets::IDatagramSocket *socket, ABI::Windows::Networking::Sockets::IDatagramSocketMessageReceivedEventArgs *args); HRESULT handleClientConnection(ABI::Windows::Networking::Sockets::IStreamSocketListener *tcpListener, From e72b583bc2a3381fe6394eb56ff0db11a337031e Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Wed, 7 Mar 2018 09:46:23 +0100 Subject: [PATCH 28/51] winrt: Remove unneeded function Change-Id: I62f3abcabf1a0e5f909c603cbdcf407e36bd0402 Reviewed-by: Maurice Kalinowski Reviewed-by: Andre de la Rocha --- .../socket/qnativesocketengine_winrt.cpp | 35 ------------------- .../socket/qnativesocketengine_winrt_p.h | 2 -- 2 files changed, 37 deletions(-) diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index cd2873fb59..09ca8169af 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -1699,41 +1699,6 @@ HRESULT QNativeSocketEnginePrivate::handleClientConnection(IStreamSocketListener return S_OK; } -HRESULT QNativeSocketEnginePrivate::handleNewDatagram(IDatagramSocket *socket, IDatagramSocketMessageReceivedEventArgs *args) -{ - qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO; - Q_Q(QNativeSocketEngine); - Q_UNUSED(socket); - - WinRtDatagram datagram; - QHostAddress returnAddress; - ComPtr remoteHost; - HRESULT hr = args->get_RemoteAddress(&remoteHost); - RETURN_OK_IF_FAILED("Could not obtain remote host"); - HString remoteHostString; - remoteHost->get_CanonicalName(remoteHostString.GetAddressOf()); - RETURN_OK_IF_FAILED("Could not obtain remote host's canonical name"); - returnAddress.setAddress(qt_QStringFromHString(remoteHostString)); - datagram.header.senderAddress = returnAddress; - HString remotePort; - hr = args->get_RemotePort(remotePort.GetAddressOf()); - RETURN_OK_IF_FAILED("Could not obtain remote port"); - datagram.header.senderPort = qt_QStringFromHString(remotePort).toInt(); - - ComPtr reader; - hr = args->GetDataReader(&reader); - RETURN_OK_IF_FAILED("Could not obtain data reader"); - quint32 length; - hr = reader->get_UnconsumedBufferLength(&length); - RETURN_OK_IF_FAILED("Could not obtain unconsumed buffer length"); - datagram.data.resize(length); - hr = reader->ReadBytes(length, reinterpret_cast(datagram.data.data())); - RETURN_OK_IF_FAILED("Could not read datagram"); - emit q->newDatagramReceived(datagram); - - return S_OK; -} - QT_END_NAMESPACE #include "qnativesocketengine_winrt.moc" diff --git a/src/network/socket/qnativesocketengine_winrt_p.h b/src/network/socket/qnativesocketengine_winrt_p.h index d7b44174b0..f47e2a7dd7 100644 --- a/src/network/socket/qnativesocketengine_winrt_p.h +++ b/src/network/socket/qnativesocketengine_winrt_p.h @@ -229,8 +229,6 @@ private: bool emitReadReady = true; - HRESULT handleNewDatagram(ABI::Windows::Networking::Sockets::IDatagramSocket *socket, - ABI::Windows::Networking::Sockets::IDatagramSocketMessageReceivedEventArgs *args); HRESULT handleClientConnection(ABI::Windows::Networking::Sockets::IStreamSocketListener *tcpListener, ABI::Windows::Networking::Sockets::IStreamSocketListenerConnectionReceivedEventArgs *args); }; From 6696c37e0027108f7d425b2e8c76992e7d2d8a76 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Wed, 7 Mar 2018 09:44:39 +0100 Subject: [PATCH 29/51] winrt: Add initial setting of options and additional state checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The initial settings are done for other socket engines too. The state checks return a message when they fail. Socket engine auto tests rely on these messages to be shown. Change-Id: If7734b453a24ecee4c3a028395ecdbb12859c871 Reviewed-by: Mårten Nordheim Reviewed-by: Maurice Kalinowski Reviewed-by: Andre de la Rocha --- .../socket/qnativesocketengine_winrt.cpp | 94 ++++++++++++++++++- 1 file changed, 92 insertions(+), 2 deletions(-) diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index 09ca8169af..474dbdd13c 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -485,6 +485,12 @@ static QByteArray socketDescription(const QAbstractSocketEngine *s) " not in "#state1" or "#state2); \ return (returnValue); \ } } while (0) +#define Q_CHECK_STATES3(function, state1, state2, state3, returnValue) do { \ + if (d->socketState != (state1) && d->socketState != (state2) && d->socketState != (state3)) { \ + qWarning(""#function" was called" \ + " not in "#state1", "#state2" or "#state3); \ + return (returnValue); \ + } } while (0) #define Q_CHECK_TYPE(function, type, returnValue) do { \ if (d->socketType != (type)) { \ qWarning(#function" was called by a" \ @@ -568,6 +574,28 @@ bool QNativeSocketEngine::initialize(QAbstractSocket::SocketType type, QAbstract if (!d->createNewSocket(type, protocol)) return false; + if (type == QAbstractSocket::UdpSocket) { + // Set the broadcasting flag if it's a UDP socket. + if (!setOption(BroadcastSocketOption, 1)) { + d->setError(QAbstractSocket::UnsupportedSocketOperationError, + WinRTSocketEngine::BroadcastingInitFailedErrorString); + close(); + return false; + } + + // Set some extra flags that are interesting to us, but accept failure + setOption(ReceivePacketInformation, 1); + setOption(ReceiveHopLimit, 1); + } + + + // Make sure we receive out-of-band data + if (type == QAbstractSocket::TcpSocket + && !setOption(ReceiveOutOfBandData, 1)) { + qWarning("QNativeSocketEngine::initialize unable to inline out-of-band data"); + } + + d->socketType = type; d->socketProtocol = protocol; return true; @@ -624,6 +652,10 @@ bool QNativeSocketEngine::isValid() const bool QNativeSocketEngine::connectToHost(const QHostAddress &address, quint16 port) { qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << address << port; + Q_D(QNativeSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::connectToHost(), false); + Q_CHECK_STATES3(QNativeSocketEngine::connectToHost(), QAbstractSocket::BoundState, + QAbstractSocket::UnconnectedState, QAbstractSocket::ConnectingState, false); const QString addressString = address.toString(); return connectToHostByName(addressString, port); } @@ -632,6 +664,9 @@ bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port) { qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << name << port; Q_D(QNativeSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::connectToHostByName(), false); + Q_CHECK_STATES3(QNativeSocketEngine::connectToHostByName(), QAbstractSocket::BoundState, + QAbstractSocket::UnconnectedState, QAbstractSocket::ConnectingState, false); HRESULT hr; #if _MSC_VER >= 1900 @@ -698,6 +733,9 @@ bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port) { qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << address << port; Q_D(QNativeSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::bind(), false); + Q_CHECK_STATE(QNativeSocketEngine::bind(), QAbstractSocket::UnconnectedState, false); + HRESULT hr; // runOnXamlThread may only return S_OK (will assert otherwise) so no need to check its result. // hr is set inside the lambda though. If an error occurred hr will point that out. @@ -783,7 +821,12 @@ bool QNativeSocketEngine::listen() Q_D(QNativeSocketEngine); Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::listen(), false); Q_CHECK_STATE(QNativeSocketEngine::listen(), QAbstractSocket::BoundState, false); +#if QT_CONFIG(sctp) + Q_CHECK_TYPES(QNativeSocketEngine::listen(), QAbstractSocket::TcpSocket, + QAbstractSocket::SctpSocket, false); +#else Q_CHECK_TYPE(QNativeSocketEngine::listen(), QAbstractSocket::TcpSocket, false); +#endif if (d->tcpListener && d->socketDescriptor != -1) { d->socketState = QAbstractSocket::ListeningState; @@ -798,7 +841,12 @@ int QNativeSocketEngine::accept() Q_D(QNativeSocketEngine); Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::accept(), -1); Q_CHECK_STATE(QNativeSocketEngine::accept(), QAbstractSocket::ListeningState, -1); +#if QT_CONFIG(sctp) + Q_CHECK_TYPES(QNativeSocketEngine::accept(), QAbstractSocket::TcpSocket, + QAbstractSocket::SctpSocket, -1); +#else Q_CHECK_TYPE(QNativeSocketEngine::accept(), QAbstractSocket::TcpSocket, -1); +#endif if (d->socketDescriptor == -1 || d->pendingConnections.isEmpty()) { d->setError(QAbstractSocket::TemporaryError, WinRTSocketEngine::TemporaryErrorString); @@ -887,6 +935,10 @@ void QNativeSocketEngine::close() bool QNativeSocketEngine::joinMulticastGroup(const QHostAddress &groupAddress, const QNetworkInterface &iface) { + Q_D(QNativeSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::joinMulticastGroup(), false); + Q_CHECK_STATE(QNativeSocketEngine::joinMulticastGroup(), QAbstractSocket::BoundState, false); + Q_CHECK_TYPE(QNativeSocketEngine::joinMulticastGroup(), QAbstractSocket::UdpSocket, false); qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << groupAddress << iface; Q_UNIMPLEMENTED(); return false; @@ -894,6 +946,10 @@ bool QNativeSocketEngine::joinMulticastGroup(const QHostAddress &groupAddress, c bool QNativeSocketEngine::leaveMulticastGroup(const QHostAddress &groupAddress, const QNetworkInterface &iface) { + Q_D(QNativeSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::leaveMulticastGroup(), false); + Q_CHECK_STATE(QNativeSocketEngine::leaveMulticastGroup(), QAbstractSocket::BoundState, false); + Q_CHECK_TYPE(QNativeSocketEngine::leaveMulticastGroup(), QAbstractSocket::UdpSocket, false); qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << groupAddress << iface; Q_UNIMPLEMENTED(); return false; @@ -901,12 +957,18 @@ bool QNativeSocketEngine::leaveMulticastGroup(const QHostAddress &groupAddress, QNetworkInterface QNativeSocketEngine::multicastInterface() const { + Q_D(const QNativeSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::multicastInterface(), QNetworkInterface()); + Q_CHECK_TYPE(QNativeSocketEngine::multicastInterface(), QAbstractSocket::UdpSocket, QNetworkInterface()); Q_UNIMPLEMENTED(); return QNetworkInterface(); } bool QNativeSocketEngine::setMulticastInterface(const QNetworkInterface &iface) { + Q_D(QNativeSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::setMulticastInterface(), false); + Q_CHECK_TYPE(QNativeSocketEngine::setMulticastInterface(), QAbstractSocket::UdpSocket, false); qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << iface; Q_UNIMPLEMENTED(); return false; @@ -915,6 +977,8 @@ bool QNativeSocketEngine::setMulticastInterface(const QNetworkInterface &iface) qint64 QNativeSocketEngine::bytesAvailable() const { Q_D(const QNativeSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::bytesAvailable(), -1); + Q_CHECK_NOT_STATE(QNativeSocketEngine::bytesAvailable(), QAbstractSocket::UnconnectedState, -1); if (d->socketType != QAbstractSocket::TcpSocket) return -1; @@ -929,6 +993,8 @@ qint64 QNativeSocketEngine::read(char *data, qint64 maxlen) { qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << maxlen; Q_D(QNativeSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::read(), -1); + Q_CHECK_STATES(QNativeSocketEngine::read(), QAbstractSocket::ConnectedState, QAbstractSocket::BoundState, -1); if (d->socketType != QAbstractSocket::TcpSocket) return -1; @@ -967,8 +1033,8 @@ qint64 QNativeSocketEngine::write(const char *data, qint64 len) { qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << data << len; Q_D(QNativeSocketEngine); - if (!isValid()) - return -1; + Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::write(), -1); + Q_CHECK_STATE(QNativeSocketEngine::write(), QAbstractSocket::ConnectedState, -1); HRESULT hr = E_FAIL; ComPtr stream; @@ -993,6 +1059,10 @@ qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QIpPacketHea qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << maxlen; #ifndef QT_NO_UDPSOCKET Q_D(QNativeSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::readDatagram(), -1); + Q_CHECK_STATES(QNativeSocketEngine::readDatagram(), QAbstractSocket::BoundState, + QAbstractSocket::ConnectedState, -1); + QMutexLocker locker(&d->worker->mutex); if (d->socketType != QAbstractSocket::UdpSocket || d->worker->pendingDatagrams.isEmpty()) { if (header) @@ -1035,6 +1105,10 @@ qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 len, const QI qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << data << len; #ifndef QT_NO_UDPSOCKET Q_D(QNativeSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::writeDatagram(), -1); + Q_CHECK_STATES(QNativeSocketEngine::writeDatagram(), QAbstractSocket::BoundState, + QAbstractSocket::ConnectedState, -1); + if (d->socketType != QAbstractSocket::UdpSocket) return -1; @@ -1071,6 +1145,10 @@ qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 len, const QI bool QNativeSocketEngine::hasPendingDatagrams() const { Q_D(const QNativeSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::hasPendingDatagrams(), false); + Q_CHECK_NOT_STATE(QNativeSocketEngine::hasPendingDatagrams(), QAbstractSocket::UnconnectedState, false); + Q_CHECK_TYPE(QNativeSocketEngine::hasPendingDatagrams(), QAbstractSocket::UdpSocket, false); + QMutexLocker locker(&d->worker->mutex); return d->worker->pendingDatagrams.length() > 0; } @@ -1078,6 +1156,9 @@ bool QNativeSocketEngine::hasPendingDatagrams() const qint64 QNativeSocketEngine::pendingDatagramSize() const { Q_D(const QNativeSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::pendingDatagramSize(), -1); + Q_CHECK_TYPE(QNativeSocketEngine::pendingDatagramSize(), QAbstractSocket::UdpSocket, -1); + QMutexLocker locker(&d->worker->mutex); if (d->worker->pendingDatagrams.isEmpty()) return -1; @@ -1169,6 +1250,10 @@ bool QNativeSocketEngine::waitForWrite(int msecs, bool *timedOut) qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << msecs; Q_UNUSED(timedOut); Q_D(QNativeSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::waitForWrite(), false); + Q_CHECK_NOT_STATE(QNativeSocketEngine::waitForWrite(), + QAbstractSocket::UnconnectedState, false); + if (d->socketState == QAbstractSocket::ConnectingState) { HRESULT hr = QWinRTFunctions::await(d->worker->connectOp, QWinRTFunctions::ProcessMainThreadEvents); if (SUCCEEDED(hr)) { @@ -1182,6 +1267,11 @@ bool QNativeSocketEngine::waitForWrite(int msecs, bool *timedOut) bool QNativeSocketEngine::waitForReadOrWrite(bool *readyToRead, bool *readyToWrite, bool checkRead, bool checkWrite, int msecs, bool *timedOut) { qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << checkRead << checkWrite << msecs; + Q_D(QNativeSocketEngine); + Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::waitForReadOrWrite(), false); + Q_CHECK_NOT_STATE(QNativeSocketEngine::waitForReadOrWrite(), + QAbstractSocket::UnconnectedState, false); + Q_UNUSED(readyToRead); Q_UNUSED(readyToWrite); Q_UNUSED(timedOut); From 1f77332db07d6a82ac9a8114f3bffa9373df2cea Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Tue, 13 Mar 2018 12:15:02 +0100 Subject: [PATCH 30/51] winrt: Remove partially read datagrams from queue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to the documentation, datagrams that were not completely read are discarded. Change-Id: Id3a038d8aeeba05e8c8f92b70877f5f5297b89ca Reviewed-by: Mårten Nordheim Reviewed-by: Maurice Kalinowski Reviewed-by: Andre de la Rocha --- src/network/socket/qnativesocketengine_winrt.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index 474dbdd13c..3ca84ad55a 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -1075,14 +1075,10 @@ qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QIpPacketHea *header = datagram.header; QByteArray readOrigin; - // Do not read the whole datagram. Put the rest of it back into the "queue" - if (maxlen < datagram.data.length()) { + if (maxlen < datagram.data.length()) readOrigin = datagram.data.left(maxlen); - datagram.data = datagram.data.remove(0, maxlen); - d->worker->pendingDatagrams.prepend(datagram); - } else { + else readOrigin = datagram.data; - } if (d->worker->pendingDatagrams.isEmpty()) { qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << "That's all folks"; d->worker->emitDataReceived = true; From f6ec2ea8a13c2b2bb3726a370fb2a4e3382ac103 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Tue, 13 Mar 2018 12:16:36 +0100 Subject: [PATCH 31/51] winrt: Fetch connection parameters when connection is successful Change-Id: Iaf5f5d93cd07429626d5c500ac04e67daada8e6e Reviewed-by: Andre de la Rocha Reviewed-by: Maurice Kalinowski --- src/network/socket/qnativesocketengine_winrt.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index 3ca84ad55a..4470d19d8c 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -1345,6 +1345,7 @@ void QNativeSocketEngine::handleConnectOpFinished(bool success, QAbstractSocket: } d->socketState = QAbstractSocket::ConnectedState; + d->fetchConnectionParameters(); emit connectionReady(); if (d->socketType != QAbstractSocket::TcpSocket) From 443a98e881ed6b6a4dfdd2bb0f68214aa62b392e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Tue, 20 Mar 2018 13:53:17 +0100 Subject: [PATCH 32/51] Document an odditity in WinRTs SSL backend Internally we use "Tls11" and "Tls12" from Microsoft's API for TlsV1_1 and TlsV1_2 respectively. However, in their documentation these values are defined to also include the lower TLS versions when you use them. We should document this. For "SslV3" TLS V1.0 support will also be enabled. https://docs.microsoft.com/en-us/uwp/api/windows.networking.sockets.socketprotectionlevel Change-Id: I0b20fb745eba40afc37e8430008872fc8174a72d Reviewed-by: Timur Pocheptsov Reviewed-by: Oliver Wolff --- src/network/ssl/qssl.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/network/ssl/qssl.cpp b/src/network/ssl/qssl.cpp index 8a5540e8bd..85d1a99c45 100644 --- a/src/network/ssl/qssl.cpp +++ b/src/network/ssl/qssl.cpp @@ -116,14 +116,14 @@ Q_LOGGING_CATEGORY(lcSsl, "qt.network.ssl"); Describes the protocol of the cipher. - \value SslV3 SSLv3 + \value SslV3 SSLv3. When using the WinRT backend this option will also enable TLSv1.0 \value SslV2 SSLv2 \value TlsV1_0 TLSv1.0 \value TlsV1_0OrLater TLSv1.0 and later versions. This option is not available when using the WinRT backend due to platform limitations. \value TlsV1 Obsolete, means the same as TlsV1_0 - \value TlsV1_1 TLSv1.1 + \value TlsV1_1 TLSv1.1. When using the WinRT backend this option will also enable TLSv1.0. \value TlsV1_1OrLater TLSv1.1 and later versions. This option is not available when using the WinRT backend due to platform limitations. - \value TlsV1_2 TLSv1.2 + \value TlsV1_2 TLSv1.2. When using the WinRT backend this option will also enable TLSv1.0 and TLSv1.1. \value TlsV1_2OrLater TLSv1.2 and later versions. This option is not available when using the WinRT backend due to platform limitations. \value UnknownProtocol The cipher's protocol cannot be determined. \value AnyProtocol The socket understands SSLv2, SSLv3, and TLSv1.0. This From 915fa58060bbccebc993a1edfbba1d2618117750 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Mon, 19 Feb 2018 12:55:54 +0100 Subject: [PATCH 33/51] QTableWidget: fix spelling error Change-Id: Ifd6f116a214d13328ccf0d070ef4517a3b53bf25 Reviewed-by: Nico Vertriest --- src/widgets/itemviews/qtablewidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/itemviews/qtablewidget.cpp b/src/widgets/itemviews/qtablewidget.cpp index 1cb88cbeeb..301d5dbe4d 100644 --- a/src/widgets/itemviews/qtablewidget.cpp +++ b/src/widgets/itemviews/qtablewidget.cpp @@ -1525,7 +1525,7 @@ QTableWidgetItem &QTableWidgetItem::operator=(const QTableWidgetItem &other) \snippet qtablewidget-resizing/mainwindow.cpp 0 \snippet qtablewidget-resizing/mainwindow.cpp 1 - Items are created ouside the table (with no parent widget) and inserted + Items are created outside the table (with no parent widget) and inserted into the table with setItem(): \snippet qtablewidget-resizing/mainwindow.cpp 2 From d5b9a4ebc425b4ba2b4daaba410dd352f06f849a Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Tue, 20 Mar 2018 14:24:10 +0100 Subject: [PATCH 34/51] Fix: avoid realloc when adding primitives to painterpath Calling reserve() for every primitive added would defeat QVector's over-allocation strategy to avoid reallocs. Task-number: QTBUG-66677 Change-Id: I7bdafdfa4d3ef60b00752c11e1b803abba773658 Reviewed-by: Christian Ehrlicher Reviewed-by: Allan Sandfeld Jensen --- src/gui/painting/qpainterpath.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index 27bd2e59e6..2574a00838 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -1033,7 +1033,6 @@ void QPainterPath::addRect(const QRectF &r) bool first = d_func()->elements.size() < 2; - d_func()->elements.reserve(d_func()->elements.size() + 5); moveTo(r.x(), r.y()); Element l1 = { r.x() + r.width(), r.y(), LineToElement }; @@ -1071,8 +1070,6 @@ void QPainterPath::addPolygon(const QPolygonF &polygon) ensureData(); detach(); - d_func()->elements.reserve(d_func()->elements.size() + polygon.size()); - moveTo(polygon.constFirst()); for (int i=1; ielements.size() < 2; - d->elements.reserve(d->elements.size() + 13); QPointF pts[12]; int point_count; @@ -1294,7 +1289,6 @@ void QPainterPath::addRegion(const QRegion ®ion) ensureData(); detach(); - d_func()->elements.reserve(region.rectCount() * 5); for (const QRect &rect : region) addRect(rect); } @@ -2463,7 +2457,6 @@ QDataStream &operator>>(QDataStream &s, QPainterPath &p) Q_ASSERT(p.d_func()->elements.at(0).type == QPainterPath::MoveToElement); p.d_func()->elements.clear(); } - p.d_func()->elements.reserve(p.d_func()->elements.size() + size); for (int i=0; i Date: Thu, 22 Mar 2018 11:09:40 +0000 Subject: [PATCH 35/51] Fix win32-clang-msvc build due to -Werror,-Wunused-private-field Task-number: QTBUG-63512 Change-Id: Ie1507faffc11be09d9ce5e95c3b537dd65bb6978 Reviewed-by: Friedemann Kleint --- src/testlib/qtestevent.h | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/testlib/qtestevent.h b/src/testlib/qtestevent.h index 3f6bd20bd8..faad914a47 100644 --- a/src/testlib/qtestevent.h +++ b/src/testlib/qtestevent.h @@ -103,7 +103,10 @@ class QTestKeyClicksEvent: public QTestEvent { public: inline QTestKeyClicksEvent(const QString &keys, Qt::KeyboardModifiers modifiers, int delay) - : _keys(keys), _modifiers(modifiers), _delay(delay) {} + : _keys(keys), _modifiers(modifiers), _delay(delay) + { + Q_UNUSED(_delay) // Silence -Werror,-Wunused-private-field + } inline QTestEvent *clone() const override { return new QTestKeyClicksEvent(*this); } #ifdef QT_WIDGETS_LIB @@ -124,7 +127,12 @@ class QTestMouseEvent: public QTestEvent public: inline QTestMouseEvent(QTest::MouseAction action, Qt::MouseButton button, Qt::KeyboardModifiers modifiers, QPoint position, int delay) - : _action(action), _button(button), _modifiers(modifiers), _pos(position), _delay(delay) {} + : _action(action), _button(button), _modifiers(modifiers), _pos(position), _delay(delay) + { + Q_UNUSED(_action) + Q_UNUSED(_button) + Q_UNUSED(_delay) + } inline QTestEvent *clone() const override { return new QTestMouseEvent(*this); } #ifdef QT_WIDGETS_LIB @@ -147,7 +155,10 @@ private: class QTestDelayEvent: public QTestEvent { public: - inline QTestDelayEvent(int msecs): _delay(msecs) {} + inline QTestDelayEvent(int msecs): _delay(msecs) + { + Q_UNUSED(_delay) + } inline QTestEvent *clone() const override { return new QTestDelayEvent(*this); } #ifdef QT_WIDGETS_LIB From 25956a1e7cef0fef39c94638b44c07457b452d00 Mon Sep 17 00:00:00 2001 From: Rolf Eike Beer Date: Thu, 22 Mar 2018 09:07:17 +0100 Subject: [PATCH 36/51] DBus: merge calls to set_source_files_properties() in CMake functions This can handle multiple files at once just fine. Change-Id: I9dcf7b0c72df432f02200ac7f3967f36a408f306 Reviewed-by: David Faure --- src/dbus/Qt5DBusMacros.cmake | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/dbus/Qt5DBusMacros.cmake b/src/dbus/Qt5DBusMacros.cmake index 0bd7364637..b381ab0934 100644 --- a/src/dbus/Qt5DBusMacros.cmake +++ b/src/dbus/Qt5DBusMacros.cmake @@ -61,8 +61,7 @@ function(QT5_ADD_DBUS_INTERFACE _sources _interface _basename) COMMAND ${Qt5DBus_QDBUSXML2CPP_EXECUTABLE} ${_params} -p ${_basename} ${_infile} DEPENDS ${_infile} VERBATIM) - set_source_files_properties("${_impl}" PROPERTIES SKIP_AUTOMOC TRUE) - set_source_files_properties("${_header}" PROPERTIES SKIP_AUTOMOC TRUE) + set_source_files_properties("${_impl}" "${_header}" PROPERTIES SKIP_AUTOMOC TRUE) qt5_generate_moc("${_header}" "${_moc}") @@ -147,8 +146,7 @@ function(QT5_ADD_DBUS_ADAPTOR _sources _xml_file _include _parentClass) # _optio endif() qt5_generate_moc("${_header}" "${_moc}") - set_source_files_properties("${_impl}" PROPERTIES SKIP_AUTOMOC TRUE) - set_source_files_properties("${_header}" PROPERTIES SKIP_AUTOMOC TRUE) + set_source_files_properties("${_impl}" "${_header}" PROPERTIES SKIP_AUTOMOC TRUE) macro_add_file_dependencies("${_impl}" "${_moc}") list(APPEND ${_sources} "${_impl}" "${_header}" "${_moc}") From 69948f48997e2995cf212d878839acb4e7c396c3 Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Sun, 4 Mar 2018 20:29:21 +0100 Subject: [PATCH 37/51] QSqlResult: use QVector instead QList for indexes value Minor tweak: QList is taking 64bit per entry, QVector only 32bit - this should reduce memory usage a little bit. Change-Id: I3e17269feb4840343f5cecfc71f8fccd70edc80f Reviewed-by: Andy Shaw --- src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp | 9 +++++---- src/sql/kernel/qsqlresult.cpp | 6 +++--- src/sql/kernel/qsqlresult_p.h | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp b/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp index cb3d905f46..91d2e9b205 100644 --- a/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp +++ b/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp @@ -471,7 +471,7 @@ bool QSQLiteResult::exec() // can end up in a case where for virtual tables it returns 0 even though it // has parameters if (paramCount > 1 && paramCount < values.count()) { - const auto countIndexes = [](int counter, const QList& indexList) { + const auto countIndexes = [](int counter, const QVector &indexList) { return counter + indexList.length(); }; @@ -485,13 +485,14 @@ bool QSQLiteResult::exec() // placeholders. So we need to ensure the QVector has only one instance of // each value as SQLite will do the rest for us. QVector prunedValues; - QList handledIndexes; + QVector handledIndexes; for (int i = 0, currentIndex = 0; i < values.size(); ++i) { if (handledIndexes.contains(i)) continue; const auto placeHolder = QString::fromUtf8(sqlite3_bind_parameter_name(d->stmt, currentIndex + 1)); - handledIndexes << d->indexes[placeHolder]; - prunedValues << values.at(d->indexes[placeHolder].first()); + const auto &indexes = d->indexes.value(placeHolder); + handledIndexes << indexes; + prunedValues << values.at(indexes.first()); ++currentIndex; } values = prunedValues; diff --git a/src/sql/kernel/qsqlresult.cpp b/src/sql/kernel/qsqlresult.cpp index cdb1379502..915a980bf0 100644 --- a/src/sql/kernel/qsqlresult.cpp +++ b/src/sql/kernel/qsqlresult.cpp @@ -690,7 +690,7 @@ void QSqlResult::bindValue(int index, const QVariant& val, QSql::ParamType param { Q_D(QSqlResult); d->binds = PositionalBinding; - QList& indexes = d->indexes[d->fieldSerial(index)]; + QVector &indexes = d->indexes[d->fieldSerial(index)]; if (!indexes.contains(index)) indexes.append(index); if (d->values.count() <= index) @@ -717,7 +717,7 @@ void QSqlResult::bindValue(const QString& placeholder, const QVariant& val, d->binds = NamedBinding; // if the index has already been set when doing emulated named // bindings - don't reset it - const QList indexes = d->indexes.value(placeholder); + const QVector indexes = d->indexes.value(placeholder); for (int idx : indexes) { if (d->values.count() <= idx) d->values.resize(idx + 1); @@ -764,7 +764,7 @@ QVariant QSqlResult::boundValue(int index) const QVariant QSqlResult::boundValue(const QString& placeholder) const { Q_D(const QSqlResult); - QList indexes = d->indexes.value(placeholder); + const QVector indexes = d->indexes.value(placeholder); return d->values.value(indexes.value(0,-1)); } diff --git a/src/sql/kernel/qsqlresult_p.h b/src/sql/kernel/qsqlresult_p.h index 7b312800c1..f0816a7fb5 100644 --- a/src/sql/kernel/qsqlresult_p.h +++ b/src/sql/kernel/qsqlresult_p.h @@ -135,7 +135,7 @@ public: QString executedQuery; QHash types; QVector values; - typedef QHash > IndexMap; + typedef QHash > IndexMap; IndexMap indexes; typedef QVector QHolderVector; From 927db42882569a23a004722598ff02f57391c361 Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Wed, 21 Mar 2018 19:29:39 +0200 Subject: [PATCH 38/51] tst_QWinEventNotifier: fix flakiness disableNotifiersInActivatedSlot(disable_signaled2) fails, if a signaled state of the event #2 is detected prior to the event #1. In this case, we get a timeout on waiting for event #1 which was disabled by the first notification. So, accept a disabled state of the notifier in condition for successful exit from the loop. Change-Id: I8a2fe76f8ec9362556d1ca1fe0be39a93ed58977 Reviewed-by: Joerg Bornemann --- .../kernel/qwineventnotifier/tst_qwineventnotifier.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp b/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp index 76efa008f7..e2a0c2dad3 100644 --- a/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp +++ b/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp @@ -125,6 +125,7 @@ public: HANDLE eventHandle() const { return notifier.handle(); } int numberOfTimesActivated() const { return activatedCount; } void setEnabled(bool b) { notifier.setEnabled(b); } + bool isEnabled() const { return notifier.isEnabled(); } signals: void activated(); @@ -218,8 +219,9 @@ void tst_QWinEventNotifier::disableNotifiersInActivatedSlot() for (int i = 0; i < count; ++i) events[i].reset(new EventWithNotifier); - auto isActivatedOrNull = [&events](int i) { - return !events.at(i) || events.at(i)->numberOfTimesActivated() > 0; + auto isActivatedOrDisabled = [&events](int i) { + return !events.at(i) || !events.at(i)->isEnabled() + || events.at(i)->numberOfTimesActivated() > 0; }; for (auto &e : events) { @@ -230,8 +232,10 @@ void tst_QWinEventNotifier::disableNotifiersInActivatedSlot() else events.at(i)->setEnabled(false); } - if (std::all_of(notifiersToSignal.begin(), notifiersToSignal.end(), isActivatedOrNull)) + if (std::all_of(notifiersToSignal.begin(), notifiersToSignal.end(), + isActivatedOrDisabled)) { QTimer::singleShot(0, &QTestEventLoop::instance(), SLOT(exitLoop())); + } }); } for (int i : notifiersToSignal) From 02ed1b36daebed5f3997bb676cf5e818c0db9d3c Mon Sep 17 00:00:00 2001 From: Kevin Funk Date: Fri, 29 Sep 2017 21:45:37 +0200 Subject: [PATCH 39/51] Remove CMake code for CMake < 3.1 This removes the following functions from Qt5CoreMacros: - qt5_use_modules(...) Task-number: QTBUG-63519 Change-Id: I59769060a3a93686bf319b558c0ede55755fdb70 Reviewed-by: David Faure --- mkspecs/features/ctest_testcase_common.prf | 2 +- .../data/cmake/Qt5BasicConfig.cmake.in | 21 ++----- src/corelib/Qt5Config.cmake.in | 4 +- src/corelib/Qt5CoreConfigExtras.cmake.in | 23 +------- src/corelib/Qt5CoreMacros.cmake | 57 ------------------- tests/auto/cmake/CMakeLists.txt | 23 ++------ .../test_use_modules_function/CMakeLists.txt | 18 ------ .../cmake/test_use_modules_function/three.cpp | 45 --------------- .../cmake/test_use_modules_function/two.cpp | 43 -------------- 9 files changed, 15 insertions(+), 221 deletions(-) delete mode 100644 tests/auto/cmake/test_use_modules_function/CMakeLists.txt delete mode 100644 tests/auto/cmake/test_use_modules_function/three.cpp delete mode 100644 tests/auto/cmake/test_use_modules_function/two.cpp diff --git a/mkspecs/features/ctest_testcase_common.prf b/mkspecs/features/ctest_testcase_common.prf index 1e3f9d2c1c..0d5ff5f89c 100644 --- a/mkspecs/features/ctest_testcase_common.prf +++ b/mkspecs/features/ctest_testcase_common.prf @@ -20,7 +20,7 @@ isEmpty(CTEST_VERSION) { return() } -!versionAtLeast(CMAKE_VERSION, 2.8.3) { +!versionAtLeast(CMAKE_VERSION, 3.1.0) { message("cmake $$CMAKE_VERSION is too old for this test.") return() } diff --git a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in index 55c74aad66..27f4c277d6 100644 --- a/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in +++ b/mkspecs/features/data/cmake/Qt5BasicConfig.cmake.in @@ -1,13 +1,7 @@ -!!IF !equals(TEMPLATE, aux) -if (CMAKE_VERSION VERSION_LESS 2.8.3) - message(FATAL_ERROR \"Qt 5 requires at least CMake version 2.8.3\") +if (CMAKE_VERSION VERSION_LESS 3.1.0) + message(FATAL_ERROR \"Qt 5 $${CMAKE_MODULE_NAME} module requires at least CMake version 3.1.0\") endif() -!!ELSE -if (CMAKE_VERSION VERSION_LESS 3.0.0) - message(FATAL_ERROR \"Qt 5 $${CMAKE_MODULE_NAME} module requires at least CMake version 3.0.0\") -endif() -!!ENDIF !!IF !isEmpty(CMAKE_USR_MOVE_WORKAROUND) !!IF !isEmpty(CMAKE_LIB_DIR_IS_ABSOLUTE) @@ -161,9 +155,7 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME}) set(_Qt5$${CMAKE_MODULE_NAME}_MODULE_DEPENDENCIES \"$${CMAKE_MODULE_DEPS}\") !!IF !isEmpty(CMAKE_INTERFACE_MODULE_DEPS) - if (NOT CMAKE_VERSION VERSION_LESS 3.0.0) - list(APPEND _Qt5$${CMAKE_MODULE_NAME}_MODULE_DEPENDENCIES \"$${CMAKE_INTERFACE_MODULE_DEPS}\") - endif() + list(APPEND _Qt5$${CMAKE_MODULE_NAME}_MODULE_DEPENDENCIES \"$${CMAKE_INTERFACE_MODULE_DEPS}\") !!ENDIF set(Qt5$${CMAKE_MODULE_NAME}_OWN_PRIVATE_INCLUDE_DIRS ${Qt5$${CMAKE_MODULE_NAME}_PRIVATE_INCLUDE_DIRS}) @@ -219,9 +211,7 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME}) set(_Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES \"$${CMAKE_QT5_MODULE_DEPS}\") !!IF !isEmpty(CMAKE_INTERFACE_QT5_MODULE_DEPS) - if (NOT CMAKE_VERSION VERSION_LESS 3.0.0) - list(APPEND _Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES \"$${CMAKE_INTERFACE_QT5_MODULE_DEPS}\") - endif() + list(APPEND _Qt5$${CMAKE_MODULE_NAME}_LIB_DEPENDENCIES \"$${CMAKE_INTERFACE_QT5_MODULE_DEPS}\") !!ENDIF !!IF !isEmpty(CMAKE_STATIC_TYPE) @@ -252,8 +242,7 @@ if (NOT TARGET Qt5::$${CMAKE_MODULE_NAME}) endif() endforeach() - if (_Qt5$${CMAKE_MODULE_NAME}_PRIVATE_DIRS_EXIST - AND NOT CMAKE_VERSION VERSION_LESS 3.0.0 ) + if (_Qt5$${CMAKE_MODULE_NAME}_PRIVATE_DIRS_EXIST) add_library(Qt5::$${CMAKE_MODULE_NAME}Private INTERFACE IMPORTED) set_property(TARGET Qt5::$${CMAKE_MODULE_NAME}Private PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${Qt5$${CMAKE_MODULE_NAME}_OWN_PRIVATE_INCLUDE_DIRS} diff --git a/src/corelib/Qt5Config.cmake.in b/src/corelib/Qt5Config.cmake.in index 75b53485b7..6b6544f932 100644 --- a/src/corelib/Qt5Config.cmake.in +++ b/src/corelib/Qt5Config.cmake.in @@ -1,6 +1,6 @@ -if (CMAKE_VERSION VERSION_LESS 2.8.9) - message(FATAL_ERROR \"Qt5 requires at least CMake version 2.8.9\") +if (CMAKE_VERSION VERSION_LESS 3.1.0) + message(FATAL_ERROR \"Qt5 requires at least CMake version 3.1.0\") endif() if (NOT Qt5_FIND_COMPONENTS) diff --git a/src/corelib/Qt5CoreConfigExtras.cmake.in b/src/corelib/Qt5CoreConfigExtras.cmake.in index 545b9a3d1e..e0652fdcf9 100644 --- a/src/corelib/Qt5CoreConfigExtras.cmake.in +++ b/src/corelib/Qt5CoreConfigExtras.cmake.in @@ -78,27 +78,10 @@ set(Qt5_POSITION_INDEPENDENT_CODE True) # Applications now need to be compiled with the -fPIC option if the Qt option # \"reduce relocations\" is active. For backward compatibility only, Qt accepts # the use of -fPIE for GCC 4.x versions. -if (CMAKE_VERSION VERSION_LESS 2.8.12 - AND (NOT CMAKE_CXX_COMPILER_ID STREQUAL \"GNU\" - OR CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0)) - set_property(TARGET Qt5::Core APPEND PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE \"ON\") -else() - set_property(TARGET Qt5::Core APPEND PROPERTY INTERFACE_COMPILE_OPTIONS $$QMAKE_CXXFLAGS_APP) -endif() +set_property(TARGET Qt5::Core APPEND PROPERTY INTERFACE_COMPILE_OPTIONS $$QMAKE_CXXFLAGS_APP) -# Applications using qmake or cmake >= 2.8.12 as their build system will -# adapt automatically. Applications using an older release of cmake in -# combination with GCC 5.x need to change their CMakeLists.txt to add -# Qt5Core_EXECUTABLE_COMPILE_FLAGS to CMAKE_CXX_FLAGS. In particular, -# applications using cmake >= 2.8.9 and < 2.8.11 will continue to build -# with the -fPIE option and invoke the special compatibility mode if using -# GCC 4.x. +# TODO Qt6: Remove set(Qt5Core_EXECUTABLE_COMPILE_FLAGS \"\") -if (CMAKE_VERSION VERSION_LESS 2.8.12 - AND (CMAKE_CXX_COMPILER_ID STREQUAL \"GNU\" - AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0)) - set(Qt5Core_EXECUTABLE_COMPILE_FLAGS \"-fPIC\") -endif() !!IF !isEmpty(QT_NAMESPACE) list(APPEND Qt5Core_DEFINITIONS -DQT_NAMESPACE=$$QT_NAMESPACE) @@ -157,7 +140,7 @@ if (NOT TARGET Qt5::WinMain) ) !!ENDIF - if (NOT CMAKE_VERSION VERSION_LESS 2.8.11 AND NOT Qt5_NO_LINK_QTMAIN) + if (NOT Qt5_NO_LINK_QTMAIN) set(_isExe $,EXECUTABLE>) set(_isWin32 $>) set(_isNotExcluded $>>) diff --git a/src/corelib/Qt5CoreMacros.cmake b/src/corelib/Qt5CoreMacros.cmake index 8d3dbe3ecf..1627de4002 100644 --- a/src/corelib/Qt5CoreMacros.cmake +++ b/src/corelib/Qt5CoreMacros.cmake @@ -152,9 +152,6 @@ function(QT5_GENERATE_MOC infile outfile ) set(_outfile "${CMAKE_CURRENT_BINARY_DIR}/${outfile}") endif() if ("x${ARGV2}" STREQUAL "xTARGET") - if (CMAKE_VERSION VERSION_LESS 2.8.12) - message(FATAL_ERROR "The TARGET parameter to qt5_generate_moc is only available when using CMake 2.8.12 or later.") - endif() set(moc_target ${ARGV3}) endif() qt5_create_moc_command(${abs_infile} ${_outfile} "${moc_flags}" "" "${moc_target}" "") @@ -178,9 +175,6 @@ function(QT5_WRAP_CPP outfiles ) set(moc_target ${_WRAP_CPP_TARGET}) set(moc_depends ${_WRAP_CPP_DEPENDS}) - if (moc_target AND CMAKE_VERSION VERSION_LESS 2.8.12) - message(FATAL_ERROR "The TARGET parameter to qt5_wrap_cpp is only available when using CMake 2.8.12 or later.") - endif() foreach(it ${moc_files}) get_filename_component(it ${it} ABSOLUTE) qt5_make_output_file(${it} moc_ cpp outfile) @@ -300,54 +294,3 @@ function(QT5_ADD_RESOURCES outfiles ) endfunction() set(_Qt5_COMPONENT_PATH "${CMAKE_CURRENT_LIST_DIR}/..") - -if (NOT CMAKE_VERSION VERSION_LESS 2.8.9) - macro(qt5_use_modules _target _link_type) - if(NOT CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.11) - if(CMAKE_WARN_DEPRECATED) - set(messageType WARNING) - endif() - if(CMAKE_ERROR_DEPRECATED) - set(messageType FATAL_ERROR) - endif() - if(messageType) - message(${messageType} "The qt5_use_modules macro is obsolete. Use target_link_libraries with IMPORTED targets instead.") - endif() - endif() - - if (NOT TARGET ${_target}) - message(FATAL_ERROR "The first argument to qt5_use_modules must be an existing target.") - endif() - if ("${_link_type}" STREQUAL "LINK_PUBLIC" OR "${_link_type}" STREQUAL "LINK_PRIVATE" ) - set(_qt5_modules ${ARGN}) - set(_qt5_link_type ${_link_type}) - else() - set(_qt5_modules ${_link_type} ${ARGN}) - endif() - - if ("${_qt5_modules}" STREQUAL "") - message(FATAL_ERROR "qt5_use_modules requires at least one Qt module to use.") - endif() - - foreach(_module ${_qt5_modules}) - if (NOT Qt5${_module}_FOUND) - find_package(Qt5${_module} PATHS "${_Qt5_COMPONENT_PATH}" NO_DEFAULT_PATH) - if (NOT Qt5${_module}_FOUND) - message(FATAL_ERROR "Can not use \"${_module}\" module which has not yet been found.") - endif() - endif() - target_link_libraries(${_target} ${_qt5_link_type} ${Qt5${_module}_LIBRARIES}) - set_property(TARGET ${_target} APPEND PROPERTY INCLUDE_DIRECTORIES ${Qt5${_module}_INCLUDE_DIRS}) - set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS ${Qt5${_module}_COMPILE_DEFINITIONS}) - set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_RELEASE QT_NO_DEBUG) - set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_RELWITHDEBINFO QT_NO_DEBUG) - set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_MINSIZEREL QT_NO_DEBUG) - if (Qt5_POSITION_INDEPENDENT_CODE - AND (CMAKE_VERSION VERSION_LESS 2.8.12 - AND (NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU" - OR CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0))) - set_property(TARGET ${_target} PROPERTY POSITION_INDEPENDENT_CODE ${Qt5_POSITION_INDEPENDENT_CODE}) - endif() - endforeach() - endmacro() -endif() diff --git a/tests/auto/cmake/CMakeLists.txt b/tests/auto/cmake/CMakeLists.txt index 40c86132e9..f1d8657091 100644 --- a/tests/auto/cmake/CMakeLists.txt +++ b/tests/auto/cmake/CMakeLists.txt @@ -47,17 +47,7 @@ find_package(Qt5Core REQUIRED) include("${_Qt5CTestMacros}") -if(NOT ${CMAKE_VERSION} VERSION_LESS 2.8.9) - # Requires INCLUDE_DIRECTORIES target property in CMake 2.8.8 - # and POSITION_INDEPENDENT_CODE target property in 2.8.9 - if (NOT NO_GUI) - expect_pass(test_use_modules_function) - endif() - expect_pass(test_umbrella_config) -else() - message("CMake version older than 2.8.9 (Found ${CMAKE_VERSION}). Not running test \"test_use_modules_function\" or \"test_umbrella_config\"") -endif() - +expect_pass(test_umbrella_config) expect_pass(test_wrap_cpp_and_resources) if (NOT NO_WIDGETS) expect_pass(test_dependent_modules) @@ -90,12 +80,8 @@ if (NOT NO_DBUS) expect_pass(test_dbus_module) endif() expect_pass(test_multiple_find_package) -if (NOT WIN32 OR (WIN32 AND NOT CMAKE_VERSION VERSION_LESS 2.8.11)) - # Broken on windows on earlier CMake versions. - # http://public.kitware.com/Bug/view.php?id=13392 - expect_pass(test_add_resources_delayed_file) - expect_pass(test_add_binary_resources_delayed_file BINARY test_add_binary_resources_delayed_file) -endif() +expect_pass(test_add_resources_delayed_file) +expect_pass(test_add_binary_resources_delayed_file BINARY test_add_binary_resources_delayed_file) expect_pass(test_private_includes) expect_pass(test_private_targets) expect_pass(test_testlib_definitions) @@ -153,7 +139,7 @@ if (QT_WITH_ANGLE OR (NOT WIN32 AND NOT APPLE AND NOT NO_EGL)) endif() expect_pass(test_opengl_lib) -if (NOT CMAKE_VERSION VERSION_LESS 2.8.11 AND NOT NO_WIDGETS) +if (NOT NO_WIDGETS) expect_pass(test_interface) endif() @@ -166,4 +152,3 @@ if (NOT CMAKE_VERSION VERSION_LESS 3.8) # /usr/bin/ld: CMakeFiles/mywidget.dir/moc_mywidget.cpp.o: previous definition here # Reason: SKIP_* properties were added in CMake 3.8 only expect_pass(test_QTBUG-63422) -endif() diff --git a/tests/auto/cmake/test_use_modules_function/CMakeLists.txt b/tests/auto/cmake/test_use_modules_function/CMakeLists.txt deleted file mode 100644 index be05c75054..0000000000 --- a/tests/auto/cmake/test_use_modules_function/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ - -cmake_minimum_required(VERSION 2.8) - -project(test_use_modules_function) - -set(CMAKE_AUTOMOC ON) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -add_executable(two two.cpp) -add_executable(three three.cpp) - -find_package(Qt5Core) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Core_EXECUTABLE_COMPILE_FLAGS}") - -qt5_use_modules(two Test) -qt5_use_modules(three Gui Test) diff --git a/tests/auto/cmake/test_use_modules_function/three.cpp b/tests/auto/cmake/test_use_modules_function/three.cpp deleted file mode 100644 index 507cc8479d..0000000000 --- a/tests/auto/cmake/test_use_modules_function/three.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include - -class Three : public QObject -{ - Q_OBJECT -public: - Three(QObject *parent = 0) - { - QWindow *w = new QWindow; - w->show(); - } -}; - -QTEST_MAIN(Three) - -#include "three.moc" diff --git a/tests/auto/cmake/test_use_modules_function/two.cpp b/tests/auto/cmake/test_use_modules_function/two.cpp deleted file mode 100644 index 44eb7fe96e..0000000000 --- a/tests/auto/cmake/test_use_modules_function/two.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include - -class Two : public QObject -{ - Q_OBJECT -public: - Two(QObject *parent = 0) - { - - } -}; - -QTEST_MAIN(Two) - -#include "two.moc" From edf96b984d406cb7c00eb83f1b7e8588ac663c1f Mon Sep 17 00:00:00 2001 From: Eric Lemanissier Date: Fri, 9 Mar 2018 10:18:02 +0100 Subject: [PATCH 40/51] fixup oversight in rvalue overloads of operator+=() and operator<<() ammends 4dee5446bee9c7417bf6f5dc44294a0b7238a9ba Change-Id: Ia0ca27644eb71815a93d6e76681b8a9e61a4e7ab Reviewed-by: Allan Sandfeld Jensen --- src/corelib/tools/qvarlengtharray.h | 4 +- src/corelib/tools/qvector.h | 4 +- .../qvarlengtharray/tst_qvarlengtharray.cpp | 59 ++++++++++++++++--- .../corelib/tools/qvector/tst_qvector.cpp | 23 +++++++- 4 files changed, 77 insertions(+), 13 deletions(-) diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h index bc22ea26f6..a6bd7847a5 100644 --- a/src/corelib/tools/qvarlengtharray.h +++ b/src/corelib/tools/qvarlengtharray.h @@ -176,11 +176,11 @@ public: inline QVarLengthArray &operator<<(const T &t) { append(t); return *this; } inline QVarLengthArray &operator<<(T &&t) - { append(t); return *this; } + { append(std::move(t)); return *this; } inline QVarLengthArray &operator+=(const T &t) { append(t); return *this; } inline QVarLengthArray &operator+=(T &&t) - { append(t); return *this; } + { append(std::move(t)); return *this; } void prepend(T &&t); void prepend(const T &t); diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index e4c7fd06d8..345ba4b097 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -284,9 +284,9 @@ public: inline QVector &operator<<(const QVector &l) { *this += l; return *this; } inline QVector &operator+=(T &&t) - { append(t); return *this; } + { append(std::move(t)); return *this; } inline QVector &operator<<(T &&t) - { append(t); return *this; } + { append(std::move(t)); return *this; } QList toList() const; diff --git a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp index ac4c8c8d4e..5737db760c 100644 --- a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp +++ b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp @@ -957,19 +957,21 @@ void tst_QVarLengthArray::insertMove() QCOMPARE(MyBase::copyCount, 0); { - QVarLengthArray vec; + QVarLengthArray vec; MyMovable m1; MyMovable m2; MyMovable m3; MyMovable m4; + MyMovable m5; + MyMovable m6; QCOMPARE(MyBase::copyCount, 0); - QCOMPARE(MyBase::liveCount, 4); + QCOMPARE(MyBase::liveCount, 6); vec.append(std::move(m3)); QVERIFY(m3.wasConstructedAt(nullptr)); QVERIFY(vec.at(0).wasConstructedAt(&m3)); QCOMPARE(MyBase::errorCount, 0); - QCOMPARE(MyBase::liveCount, 4); + QCOMPARE(MyBase::liveCount, 6); QCOMPARE(MyBase::movedCount, 1); vec.push_back(std::move(m4)); @@ -977,7 +979,7 @@ void tst_QVarLengthArray::insertMove() QVERIFY(vec.at(0).wasConstructedAt(&m3)); QVERIFY(vec.at(1).wasConstructedAt(&m4)); QCOMPARE(MyBase::errorCount, 0); - QCOMPARE(MyBase::liveCount, 4); + QCOMPARE(MyBase::liveCount, 6); QCOMPARE(MyBase::movedCount, 2); vec.prepend(std::move(m1)); @@ -986,7 +988,7 @@ void tst_QVarLengthArray::insertMove() QVERIFY(vec.at(1).wasConstructedAt(&m3)); QVERIFY(vec.at(2).wasConstructedAt(&m4)); QCOMPARE(MyBase::errorCount, 0); - QCOMPARE(MyBase::liveCount, 4); + QCOMPARE(MyBase::liveCount, 6); QCOMPARE(MyBase::movedCount, 3); vec.insert(1, std::move(m2)); @@ -995,11 +997,34 @@ void tst_QVarLengthArray::insertMove() QVERIFY(vec.at(1).wasConstructedAt(&m2)); QVERIFY(vec.at(2).wasConstructedAt(&m3)); QVERIFY(vec.at(3).wasConstructedAt(&m4)); + QCOMPARE(MyBase::errorCount, 0); + QCOMPARE(MyBase::liveCount, 6); + QCOMPARE(MyBase::movedCount, 4); + + vec += std::move(m5); + QVERIFY(m5.wasConstructedAt(nullptr)); + QVERIFY(vec.at(0).wasConstructedAt(&m1)); + QVERIFY(vec.at(1).wasConstructedAt(&m2)); + QVERIFY(vec.at(2).wasConstructedAt(&m3)); + QVERIFY(vec.at(3).wasConstructedAt(&m4)); + QVERIFY(vec.at(4).wasConstructedAt(&m5)); + QCOMPARE(MyBase::errorCount, 0); + QCOMPARE(MyBase::liveCount, 6); + QCOMPARE(MyBase::movedCount, 5); + + vec << std::move(m6); + QVERIFY(m6.wasConstructedAt(nullptr)); + QVERIFY(vec.at(0).wasConstructedAt(&m1)); + QVERIFY(vec.at(1).wasConstructedAt(&m2)); + QVERIFY(vec.at(2).wasConstructedAt(&m3)); + QVERIFY(vec.at(3).wasConstructedAt(&m4)); + QVERIFY(vec.at(4).wasConstructedAt(&m5)); + QVERIFY(vec.at(5).wasConstructedAt(&m6)); QCOMPARE(MyBase::copyCount, 0); - QCOMPARE(MyBase::liveCount, 4); + QCOMPARE(MyBase::liveCount, 6); QCOMPARE(MyBase::errorCount, 0); - QCOMPARE(MyBase::movedCount, 4); + QCOMPARE(MyBase::movedCount, 6); } QCOMPARE(MyBase::liveCount, 0); QCOMPARE(MyBase::errorCount, 0); @@ -1013,10 +1038,14 @@ void tst_QVarLengthArray::nonCopyable() std::unique_ptr val2(new int(2)); std::unique_ptr val3(new int(3)); std::unique_ptr val4(new int(4)); + std::unique_ptr val5(new int(5)); + std::unique_ptr val6(new int(6)); int *const ptr1 = val1.get(); int *const ptr2 = val2.get(); int *const ptr3 = val3.get(); int *const ptr4 = val4.get(); + int *const ptr5 = val5.get(); + int *const ptr6 = val6.get(); vec.append(std::move(val3)); QVERIFY(!val3); @@ -1035,6 +1064,22 @@ void tst_QVarLengthArray::nonCopyable() QVERIFY(ptr1 == vec.at(0).get()); QVERIFY(ptr2 == vec.at(1).get()); QVERIFY(ptr3 == vec.at(2).get()); + QVERIFY(ptr4 == vec.at(3).get()); + vec += std::move(val5); + QVERIFY(!val5); + QVERIFY(ptr1 == vec.at(0).get()); + QVERIFY(ptr2 == vec.at(1).get()); + QVERIFY(ptr3 == vec.at(2).get()); + QVERIFY(ptr4 == vec.at(3).get()); + QVERIFY(ptr5 == vec.at(4).get()); + vec << std::move(val6); + QVERIFY(!val6); + QVERIFY(ptr1 == vec.at(0).get()); + QVERIFY(ptr2 == vec.at(1).get()); + QVERIFY(ptr3 == vec.at(2).get()); + QVERIFY(ptr4 == vec.at(3).get()); + QVERIFY(ptr5 == vec.at(4).get()); + QVERIFY(ptr6 == vec.at(5).get()); } QTEST_APPLESS_MAIN(tst_QVarLengthArray) diff --git a/tests/auto/corelib/tools/qvector/tst_qvector.cpp b/tests/auto/corelib/tools/qvector/tst_qvector.cpp index 600291715a..a7faeb5ca5 100644 --- a/tests/auto/corelib/tools/qvector/tst_qvector.cpp +++ b/tests/auto/corelib/tools/qvector/tst_qvector.cpp @@ -2895,12 +2895,14 @@ void tst_QVector::insertMove() const const int instancesCount = Movable::counter.loadAcquire(); { QVector vec; - vec.reserve(5); + vec.reserve(7); Movable m0; Movable m1; Movable m2; Movable m3; Movable m4; + Movable m5; + Movable m6; vec.append(std::move(m3)); QVERIFY(m3.wasConstructedAt(nullptr)); @@ -2920,6 +2922,21 @@ void tst_QVector::insertMove() const QVERIFY(vec.at(1).wasConstructedAt(&m2)); QVERIFY(vec.at(2).wasConstructedAt(&m3)); QVERIFY(vec.at(3).wasConstructedAt(&m4)); + vec += std::move(m5); + QVERIFY(m5.wasConstructedAt(nullptr)); + QVERIFY(vec.at(0).wasConstructedAt(&m1)); + QVERIFY(vec.at(1).wasConstructedAt(&m2)); + QVERIFY(vec.at(2).wasConstructedAt(&m3)); + QVERIFY(vec.at(3).wasConstructedAt(&m4)); + QVERIFY(vec.at(4).wasConstructedAt(&m5)); + vec << std::move(m6); + QVERIFY(m6.wasConstructedAt(nullptr)); + QVERIFY(vec.at(0).wasConstructedAt(&m1)); + QVERIFY(vec.at(1).wasConstructedAt(&m2)); + QVERIFY(vec.at(2).wasConstructedAt(&m3)); + QVERIFY(vec.at(3).wasConstructedAt(&m4)); + QVERIFY(vec.at(4).wasConstructedAt(&m5)); + QVERIFY(vec.at(5).wasConstructedAt(&m6)); vec.push_front(std::move(m0)); QVERIFY(m0.wasConstructedAt(nullptr)); QVERIFY(vec.at(0).wasConstructedAt(&m0)); @@ -2927,8 +2944,10 @@ void tst_QVector::insertMove() const QVERIFY(vec.at(2).wasConstructedAt(&m2)); QVERIFY(vec.at(3).wasConstructedAt(&m3)); QVERIFY(vec.at(4).wasConstructedAt(&m4)); + QVERIFY(vec.at(5).wasConstructedAt(&m5)); + QVERIFY(vec.at(6).wasConstructedAt(&m6)); - QCOMPARE(Movable::counter.loadAcquire(), instancesCount + 10); + QCOMPARE(Movable::counter.loadAcquire(), instancesCount + 14); } QCOMPARE(Movable::counter.loadAcquire(), instancesCount); } From dbc983a513a6dff9973490d013b144812ec707aa Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 26 Mar 2018 12:58:23 +0200 Subject: [PATCH 41/51] Revert "Detect C standard and try using the most recent" The change causes a crash when compiling the xkbcommon 3rdparty library and compile failures (qtimageformats on Android). This reverts commit a47cb146809e32f43449dcfe9932833c2f0ab987. Task-number: QTBUG-67326 Task-number: QTBUG-67327 Change-Id: I5ddc4eccad699e3eaec535fd6a63d11b0026b42e Reviewed-by: Sami Nurmenniemi Reviewed-by: Liang Qi Reviewed-by: Gatis Paeglis --- configure.json | 48 ------------------------- mkspecs/common/android-base-tail.conf | 2 -- mkspecs/common/clang.conf | 2 -- mkspecs/common/g++-base.conf | 2 -- mkspecs/common/gcc-base.conf | 3 -- mkspecs/features/default_post.prf | 15 -------- mkspecs/features/qt_common.prf | 2 -- mkspecs/features/qt_configure.prf | 13 ++----- src/3rdparty/xkbcommon.pri | 1 + src/corelib/global/qcompilerdetection.h | 2 +- 10 files changed, 4 insertions(+), 86 deletions(-) diff --git a/configure.json b/configure.json index b4d763116c..ae2aa22070 100644 --- a/configure.json +++ b/configure.json @@ -259,36 +259,6 @@ "type": "compile", "test": "stl" }, - "c99": { - "label": "C99 support", - "type": "compile", - "test": { - "head": [ - "#if __STDC_VERSION__ >= 199901L", - "// Compiler claims to support C99, trust it", - "#else", - "# error __STDC_VERSION__ must be >= 199901L", - "#endif" - ], - "lang": "c", - "qmake": "CONFIG += c99" - } - }, - "c11": { - "label": "C11 support", - "type": "compile", - "test": { - "head": [ - "#if __STDC_VERSION__ >= 201112L", - "// Compiler claims to support C11, trust it", - "#else", - "# error __STDC_VERSION__ must be >= 201112L", - "#endif" - ], - "lang": "c", - "qmake": "CONFIG += c11" - } - }, "c++14": { "label": "C++14 support", "type": "compile", @@ -816,19 +786,6 @@ "condition": "features.c++14 && tests.c++1z", "output": [ "publicFeature", "publicQtConfig" ] }, - "c89": { - "label": "C89" - }, - "c99": { - "label": "C99", - "condition": "tests.c99", - "output": [ "publicFeature" ] - }, - "c11": { - "label": "C11", - "condition": "features.c99 && tests.c11", - "output": [ "publicFeature" ] - }, "precompile_header": { "label": "Using precompiled headers", "condition": "config.msvc || tests.precompile_header", @@ -1289,11 +1246,6 @@ Configure with '-qreal float' to create a build that is binary-compatible with 5 "condition": "!features.debug || features.debug_and_release" }, "shared", - { - "message": "Using C standard", - "type": "firstAvailableFeature", - "args": "c11 c99 c89" - }, { "message": "Using C++ standard", "type": "firstAvailableFeature", diff --git a/mkspecs/common/android-base-tail.conf b/mkspecs/common/android-base-tail.conf index 464b60b1c4..160caf011f 100644 --- a/mkspecs/common/android-base-tail.conf +++ b/mkspecs/common/android-base-tail.conf @@ -38,8 +38,6 @@ QMAKE_CFLAGS_THREAD = -D_REENTRANT QMAKE_CFLAGS_HIDESYMS = -fvisibility=hidden QMAKE_CFLAGS_NEON = -mfpu=neon -QMAKE_CFLAGS_GNUC99 = -std=gnu99 -QMAKE_CFLAGS_GNUC11 = -std=gnu11 QMAKE_CXXFLAGS_CXX11 = -std=c++11 QMAKE_CXXFLAGS_CXX14 = -std=c++14 QMAKE_CXXFLAGS_CXX1Z = -std=c++1z diff --git a/mkspecs/common/clang.conf b/mkspecs/common/clang.conf index 6122a37213..e003b947aa 100644 --- a/mkspecs/common/clang.conf +++ b/mkspecs/common/clang.conf @@ -21,8 +21,6 @@ QMAKE_CFLAGS_PRECOMPILE = -x c-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_ QMAKE_CFLAGS_USE_PRECOMPILE = -Xclang -include-pch -Xclang ${QMAKE_PCH_OUTPUT} QMAKE_CFLAGS_LTCG = -flto QMAKE_CFLAGS_DISABLE_LTCG = -fno-lto -QMAKE_CFLAGS_GNUC99 = -std=gnu99 -QMAKE_CFLAGS_GNUC11 = -std=gnu11 QMAKE_CXXFLAGS_PRECOMPILE = -x c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} QMAKE_CXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE diff --git a/mkspecs/common/g++-base.conf b/mkspecs/common/g++-base.conf index fa0f0c391d..c42c46b0ec 100644 --- a/mkspecs/common/g++-base.conf +++ b/mkspecs/common/g++-base.conf @@ -27,8 +27,6 @@ QMAKE_CFLAGS_USE_PRECOMPILE = -include ${QMAKE_PCH_OUTPUT_BASE} QMAKE_CXXFLAGS_PRECOMPILE = -x c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} QMAKE_CXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE -QMAKE_CFLAGS_GNUC99 = -std=gnu99 -QMAKE_CFLAGS_GNUC11 = -std=gnu11 QMAKE_CXXFLAGS_CXX11 = -std=c++11 QMAKE_CXXFLAGS_CXX14 = -std=c++1y QMAKE_CXXFLAGS_CXX1Z = -std=c++1z diff --git a/mkspecs/common/gcc-base.conf b/mkspecs/common/gcc-base.conf index 0407ba9724..234f71d495 100644 --- a/mkspecs/common/gcc-base.conf +++ b/mkspecs/common/gcc-base.conf @@ -81,9 +81,6 @@ QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO += QMAKE_LFLAGS_EXCEPTIONS_OFF += QMAKE_LFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG -fuse-linker-plugin -QMAKE_CFLAGS_C99 = -std=c99 -QMAKE_CFLAGS_C11 = -std=c11 - QMAKE_CFLAGS_SSE2 += -msse2 QMAKE_CFLAGS_SSE3 += -msse3 QMAKE_CFLAGS_SSSE3 += -mssse3 diff --git a/mkspecs/features/default_post.prf b/mkspecs/features/default_post.prf index bf5acdefc4..9eba5bcf00 100644 --- a/mkspecs/features/default_post.prf +++ b/mkspecs/features/default_post.prf @@ -143,21 +143,6 @@ c++11|c++14|c++1z { unset(cxxstd) } -c99|c11 { - c11: cstd = C11 - else: cstd = C99 - - # Check if we should disable compiler extensions or not - !isEmpty(QMAKE_CFLAGS_GNU$$cstd) { - # Let strict C++ imply strict C - !strict_c++: cstd = GNU$$cstd - } - - QMAKE_CFLAGS += $$eval(QMAKE_CFLAGS_$$cstd) - - unset(cstd) -} - utf8_source { QMAKE_CFLAGS += $$QMAKE_CFLAGS_UTF8_SOURCE QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_UTF8_SOURCE diff --git a/mkspecs/features/qt_common.prf b/mkspecs/features/qt_common.prf index 40f03d2186..f4ae5bde80 100644 --- a/mkspecs/features/qt_common.prf +++ b/mkspecs/features/qt_common.prf @@ -17,8 +17,6 @@ DEFINES *= QT_NO_NARROWING_CONVERSIONS_IN_CONNECT qtConfig(c++11): CONFIG += c++11 strict_c++ qtConfig(c++14): CONFIG += c++14 qtConfig(c++1z): CONFIG += c++1z -qtConfig(c99): CONFIG += c99 -qtConfig(c11): CONFIG += c11 qtConfig(stack-protector-strong): CONFIG += stack_protector_strong contains(TEMPLATE, .*lib) { # module and plugins diff --git a/mkspecs/features/qt_configure.prf b/mkspecs/features/qt_configure.prf index a7da26c745..98fff59ea1 100644 --- a/mkspecs/features/qt_configure.prf +++ b/mkspecs/features/qt_configure.prf @@ -866,15 +866,6 @@ defineTest(qtConfTestPrepare_compile) { defineTest(qtConfPrepareCompileTestSource) { test_dir = $$2 - test_lang = $$eval($${1}.lang) - isEmpty(test_lang): test_lang = "c++" - - equals(test_lang, "c++"): suffix = "cpp" - else: equals(test_lang, "c"): suffix = "c" - else: equals(test_lang, "objc"): suffix = "m" - else: equals(test_lang, "objc++"): suffix = "mm" - else: error("Unknown language '$$test_lang' in compile test $$1") - # Create source code contents = "/* Generated by configure */" # Custom code before includes @@ -898,10 +889,10 @@ defineTest(qtConfPrepareCompileTestSource) { " /* END TEST */" \ " return 0;" \ "}" - write_file($$test_dir/main.$$suffix, contents)|error() + write_file($$test_dir/main.cpp, contents)|error() # Create stub .pro file - contents = "SOURCES = main.$$suffix" + contents = "SOURCES = main.cpp" # Custom project code for (ent, $$qtConfScalarOrList($${1}.qmake)): \ contents += $$ent diff --git a/src/3rdparty/xkbcommon.pri b/src/3rdparty/xkbcommon.pri index 1050e54f3a..1d953d8372 100644 --- a/src/3rdparty/xkbcommon.pri +++ b/src/3rdparty/xkbcommon.pri @@ -1,3 +1,4 @@ +QMAKE_CFLAGS += -std=gnu99 -w INCLUDEPATH += $$PWD/xkbcommon \ $$PWD/xkbcommon/xkbcommon \ $$PWD/xkbcommon/src \ diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index e5e47082d8..f3f3139d1a 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -898,7 +898,7 @@ /* C11 features supported in GCC 4.7: */ # define Q_COMPILER_STATIC_ASSERT # endif -# if Q_CC_GNU >= 409 && defined(__has_include) +# if Q_CC_GNU >= 409 /* C11 features supported in GCC 4.9: */ # if __has_include() # define Q_COMPILER_THREAD_LOCAL From 411a4cb67cd3d976ddbd94b37a0ce936bfb223e5 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sat, 24 Mar 2018 08:26:11 +0800 Subject: [PATCH 42/51] QNetworkInterface/Linux: fix support for P-t-P tunnels The kernel stores the local address in IFA_LOCAL and the peer's address in IFA_ADDRESS. My testing with loopback, Ethernet, WiFi, OpenVPN TAP and TUN and Openconnect shows IFA_LOCAL is always passed and always correct, so we could have used just that, but let's leave the use of IFA_ADDRESS because that's also what all libcs' getifaddrs() do. [ChangeLog][QtNetwork][QNetworkInterface] Fixed a regression in reporting the local address of a point-to-point tunnel network interface. Task-number: QTBUG-67226 Change-Id: I04a43ee94975482f9e32fffd151eb393d1775580 Reviewed-by: Edward Welbourne --- src/network/kernel/qnetworkinterface_linux.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/network/kernel/qnetworkinterface_linux.cpp b/src/network/kernel/qnetworkinterface_linux.cpp index 01b2811070..5dc62bf7bb 100644 --- a/src/network/kernel/qnetworkinterface_linux.cpp +++ b/src/network/kernel/qnetworkinterface_linux.cpp @@ -382,7 +382,14 @@ static void getAddresses(int sock, char *buf, QList auto payloadPtr = reinterpret_cast(RTA_DATA(rta)); switch (rta->rta_type) { - case IFA_ADDRESS: // address + case IFA_ADDRESS: + // Local address (all interfaces except for point-to-point) + if (entry.ip().isNull()) + entry.setIp(makeAddress(payloadPtr, payloadLen)); + break; + + case IFA_LOCAL: + // Override the local address (point-to-point interfaces) entry.setIp(makeAddress(payloadPtr, payloadLen)); break; From 50cfbd6112a2682228cdf34cd72b5abae967cdb2 Mon Sep 17 00:00:00 2001 From: Svenn-Arne Dragly Date: Wed, 14 Mar 2018 16:36:09 +0100 Subject: [PATCH 43/51] Animation: Fix case where QEasingCurve::valueForProgress returns nan Previously, we would divide by zero in BezierEase::findTForX if factorT3 was zero when solving the cubic equation. This change fixes the problem by adding solutions for the special cases where the cubic equation can be reduced to a quadratic or linear equation. This change also adds tests that cover cases where the equation becomes quadratic, linear or invalid. Task-number: QTBUG-67061 Change-Id: I2b59f7e0392eb807663c3c8927509fd8b226ebc7 Reviewed-by: Christian Stromme --- src/corelib/tools/qeasingcurve.cpp | 67 +++++++++++++----- .../tools/qeasingcurve/tst_qeasingcurve.cpp | 70 +++++++++++++++++++ 2 files changed, 120 insertions(+), 17 deletions(-) diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp index 0b8fa4ca74..e66db58ed7 100644 --- a/src/corelib/tools/qeasingcurve.cpp +++ b/src/corelib/tools/qeasingcurve.cpp @@ -797,27 +797,60 @@ struct BezierEase : public QEasingCurveFunction return t3; } - qreal static inline findTForX(const SingleCubicBezier &singleCubicBezier, qreal x) - { - const qreal p0 = singleCubicBezier.p0x; - const qreal p1 = singleCubicBezier.p1x; - const qreal p2 = singleCubicBezier.p2x; - const qreal p3 = singleCubicBezier.p3x; + bool static inline almostZero(qreal value) + { + // 1e-3 might seem excessively fuzzy, but any smaller value will make the + // factors a, b, and c large enough to knock out the cubic solver. + return value > -1e-3 && value < 1e-3; + } - const qreal factorT3 = p3 - p0 + 3 * p1 - 3 * p2; - const qreal factorT2 = 3 * p0 - 6 * p1 + 3 * p2; - const qreal factorT1 = -3 * p0 + 3 * p1; - const qreal factorT0 = p0 - x; + qreal static inline findTForX(const SingleCubicBezier &singleCubicBezier, qreal x) + { + const qreal p0 = singleCubicBezier.p0x; + const qreal p1 = singleCubicBezier.p1x; + const qreal p2 = singleCubicBezier.p2x; + const qreal p3 = singleCubicBezier.p3x; - const qreal a = factorT2 / factorT3; - const qreal b = factorT1 / factorT3; - const qreal c = factorT0 / factorT3; + const qreal factorT3 = p3 - p0 + 3 * p1 - 3 * p2; + const qreal factorT2 = 3 * p0 - 6 * p1 + 3 * p2; + const qreal factorT1 = -3 * p0 + 3 * p1; + const qreal factorT0 = p0 - x; - return singleRealSolutionForCubic(a, b, c); + // Cases for quadratic, linear and invalid equations + if (almostZero(factorT3)) { + if (almostZero(factorT2)) { + if (almostZero(factorT1)) + return 0.0; - //one new iteration to increase numeric stability - //return newtonIteration(singleCubicBezier, t, x); - } + return -factorT0 / factorT1; + } + const qreal discriminant = factorT1 * factorT1 - 4.0 * factorT2 * factorT0; + if (discriminant < 0.0) + return 0.0; + + if (discriminant == 0.0) + return -factorT1 / (2.0 * factorT2); + + const qreal solution1 = (-factorT1 + std::sqrt(discriminant)) / (2.0 * factorT2); + if (solution1 >= 0.0 && solution1 <= 1.0) + return solution1; + + const qreal solution2 = (-factorT1 - std::sqrt(discriminant)) / (2.0 * factorT2); + if (solution2 >= 0.0 && solution2 <= 1.0) + return solution2; + + return 0.0; + } + + const qreal a = factorT2 / factorT3; + const qreal b = factorT1 / factorT3; + const qreal c = factorT0 / factorT3; + + return singleRealSolutionForCubic(a, b, c); + + //one new iteration to increase numeric stability + //return newtonIteration(singleCubicBezier, t, x); + } }; struct TCBEase : public BezierEase diff --git a/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp b/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp index 0714883855..79309f960d 100644 --- a/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp +++ b/tests/auto/corelib/tools/qeasingcurve/tst_qeasingcurve.cpp @@ -54,6 +54,7 @@ private slots: void testCbrtDouble(); void testCbrtFloat(); void cpp11(); + void quadraticEquation(); }; void tst_QEasingCurve::type() @@ -804,5 +805,74 @@ void tst_QEasingCurve::cpp11() #endif } +void tst_QEasingCurve::quadraticEquation() { + // We find the value for a given time by solving a cubic equation. + // ax^3 + bx^2 + cx + d = 0 + // However, the solver also needs to take care of cases where a = 0, + // b = 0 or c = 0, and the equation becomes quadratic, linear or invalid. + // A naive cubic solver might divide by zero and return nan, even + // when the solution is a real number. + // This test should triggers those cases. + + { + // If the control points are spaced 1/3 apart of the distance of the + // start- and endpoint, the equation becomes linear. + QEasingCurve test(QEasingCurve::BezierSpline); + const qreal p1 = 1.0 / 3.0; + const qreal p2 = 1.0 - 1.0 / 3.0; + const qreal p3 = 1.0; + + test.addCubicBezierSegment(QPointF(p1, 0.0), QPointF(p2, 1.0), QPointF(p3, 1.0)); + QVERIFY(qAbs(test.valueForProgress(0.25) - 0.15625) < 1e-6); + QVERIFY(qAbs(test.valueForProgress(0.5) - 0.5) < 1e-6); + QVERIFY(qAbs(test.valueForProgress(0.75) - 0.84375) < 1e-6); + } + + { + // If both the start point and the first control point + // are placed a 0.0, and the second control point is + // placed at 1/3, we get a case where a = 0 and b != 0 + // i.e. a quadratic equation. + QEasingCurve test(QEasingCurve::BezierSpline); + const qreal p1 = 0.0; + const qreal p2 = 1.0 / 3.0; + const qreal p3 = 1.0; + test.addCubicBezierSegment(QPointF(p1, 0.0), QPointF(p2, 1.0), QPointF(p3, 1.0)); + QVERIFY(qAbs(test.valueForProgress(0.25) - 0.5) < 1e-6); + QVERIFY(qAbs(test.valueForProgress(0.5) - 0.792893) < 1e-6); + QVERIFY(qAbs(test.valueForProgress(0.75) - 0.950962) < 1e-6); + } + + { + // If both the start point and the first control point + // are placed a 0.0, and the second control point is + // placed close to 1/3, we get a case where a = ~0 and b != 0. + // It's not truly a quadratic equation, but should be treated + // as one, because it causes some cubic solvers to fail. + QEasingCurve test(QEasingCurve::BezierSpline); + const qreal p1 = 0.0; + const qreal p2 = 1.0 / 3.0 + 1e-6; + const qreal p3 = 1.0; + test.addCubicBezierSegment(QPointF(p1, 0.0), QPointF(p2, 1.0), QPointF(p3, 1.0)); + QVERIFY(qAbs(test.valueForProgress(0.25) - 0.499999) < 1e-6); + QVERIFY(qAbs(test.valueForProgress(0.5) - 0.792892) < 1e-6); + QVERIFY(qAbs(test.valueForProgress(0.75) - 0.950961) < 1e-6); + } + + { + // A bad case, where the segment is of zero length. + // However, it might still happen in user code, + // and we should return a sensible answer. + QEasingCurve test(QEasingCurve::BezierSpline); + const qreal p0 = 0.0; + const qreal p1 = p0; + const qreal p2 = p0; + const qreal p3 = p0; + test.addCubicBezierSegment(QPointF(p1, 0.0), QPointF(p2, 1.0), QPointF(p3, 1.0)); + test.addCubicBezierSegment(QPointF(p3, 1.0), QPointF(1.0, 1.0), QPointF(1.0, 1.0)); + QCOMPARE(test.valueForProgress(0.0), 0.0); + } +} + QTEST_MAIN(tst_QEasingCurve) #include "tst_qeasingcurve.moc" From c7c41fa1c6bced218e9a44859feb593624340228 Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Thu, 22 Mar 2018 16:45:01 +0100 Subject: [PATCH 44/51] Fix QPainter save/restore of clipping enabled state Clipping enabled state would not always be correctly restored for the raster engine (other engines work fine). The raster engine's QClipData object is sometimes shared between painter state objects on the save/restore stack. QClipData has its own enabled flag, and this could then come out of sync. Fix by making sure we sync the enabled state on restore. Task-number: QTBUG-58789 Change-Id: I81e6254ebb93df6e153bbef58e32a885273e3224 Reviewed-by: Allan Sandfeld Jensen --- src/gui/painting/qpaintengine_raster.cpp | 5 ++++ .../gui/painting/qpainter/tst_qpainter.cpp | 30 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 33fde8c61a..6336b2943e 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -698,6 +698,11 @@ void QRasterPaintEngine::setState(QPainterState *s) { Q_D(QRasterPaintEngine); QPaintEngineEx::setState(s); + QRasterPaintEngineState *t = state(); + if (t->clip && t->clip->enabled != t->clipEnabled) { + // Since we do not "detach" clipdata when changing only enabled state, we need to resync state here + t->clip->enabled = t->clipEnabled; + } d->rasterBuffer->compositionMode = s->composition_mode; } diff --git a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp index 8dfaa6f5cd..ba405e2860 100644 --- a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp +++ b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp @@ -153,6 +153,7 @@ private slots: void setEqualClipRegionAndPath(); void clipRectSaveRestore(); + void clipStateSaveRestore(); void clippedFillPath_data(); void clippedFillPath(); @@ -3425,6 +3426,35 @@ void tst_QPainter::clipRectSaveRestore() QCOMPARE(img.pixel(0, 0), QColor(Qt::black).rgba()); } +void tst_QPainter::clipStateSaveRestore() +{ + QImage img(16, 16, QImage::Format_RGB32); + img.fill(Qt::blue); + { + QPainter p(&img); + p.setClipRect(QRect(5, 5, 10, 10)); + p.save(); + p.setClipping(false); + p.restore(); + p.fillRect(0, 0, 16, 16, Qt::red); + p.end(); + QCOMPARE(img.pixel(0, 0), QColor(Qt::blue).rgb()); + } + + img.fill(Qt::blue); + { + QPainter p(&img); + p.setClipRect(QRect(5, 5, 10, 10)); + p.setClipping(false); + p.save(); + p.setClipping(true); + p.restore(); + p.fillRect(0, 0, 16, 16, Qt::red); + p.end(); + QCOMPARE(img.pixel(0, 0), QColor(Qt::red).rgb()); + } +} + void tst_QPainter::clippedImage() { QImage img(16, 16, QImage::Format_ARGB32_Premultiplied); From c2373fce3c112a0e497ab1de5dfe670ad8aa59c5 Mon Sep 17 00:00:00 2001 From: Pablo Marcos Oltra Date: Thu, 8 Mar 2018 09:34:25 +0100 Subject: [PATCH 45/51] macOS: Fix memory leak in systemCaCertificates We were releasing only the memory of latest iteration since cfCerts was being rewritten in every iteration, invalidating the RAII. Hence, we need to define the variable within the loop to ensure the object is released for every iteration. Task-number: QTBUG-66937 Change-Id: Iaa9365168728337c6cdaac4aef686652903cf5a9 Reviewed-by: Timur Pocheptsov --- src/network/ssl/qsslsocket_mac_shared.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/ssl/qsslsocket_mac_shared.cpp b/src/network/ssl/qsslsocket_mac_shared.cpp index d239fe23dd..4f0adf16f9 100644 --- a/src/network/ssl/qsslsocket_mac_shared.cpp +++ b/src/network/ssl/qsslsocket_mac_shared.cpp @@ -128,10 +128,10 @@ QList QSslSocketPrivate::systemCaCertificates() QList systemCerts; // SecTrustSettingsCopyCertificates is not defined on iOS. #ifdef Q_OS_OSX - QCFType cfCerts; // iterate through all enum members, order: // kSecTrustSettingsDomainUser, kSecTrustSettingsDomainAdmin, kSecTrustSettingsDomainSystem for (int dom = kSecTrustSettingsDomainUser; dom <= int(kSecTrustSettingsDomainSystem); dom++) { + QCFType cfCerts; OSStatus status = SecTrustSettingsCopyCertificates(SecTrustSettingsDomain(dom), &cfCerts); if (status == noErr) { const CFIndex size = CFArrayGetCount(cfCerts); From 7775eb248ac9cab0ea1e882889f00bec0efb178f Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Thu, 1 Mar 2018 06:45:45 +0100 Subject: [PATCH 46/51] sqlite: Support using execBatch() with duplicated named placeholders Also expands the tst_qsqlquery::batchExec() test to account for this case and generally test the functionality. In addition it is made to be more robust to avoid any discrepencies with the testing data. The test in general is also cleaned up to enable more of it being tested with the different database drivers where possible. An expected fail is added for MySQL due to the fact that it has a bug where null timestamp entries are being converted to the current datetime when adding it as a bind value. Change-Id: I0061bd1c69ae35b4858afc49420f13ce59cf48ae Reviewed-by: Edward Welbourne --- src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp | 25 ++++ .../sql/kernel/qsqlquery/tst_qsqlquery.cpp | 138 +++++++++++------- 2 files changed, 107 insertions(+), 56 deletions(-) diff --git a/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp b/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp index 91d2e9b205..6375825720 100644 --- a/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp +++ b/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp @@ -56,6 +56,7 @@ #include #endif #include +#include #if defined Q_OS_WIN # include @@ -129,6 +130,7 @@ protected: bool gotoNext(QSqlCachedResult::ValueCache& row, int idx) override; bool reset(const QString &query) override; bool prepare(const QString &query) override; + bool execBatch(bool arrayBind) override; bool exec() override; int size() override; int numRowsAffected() override; @@ -443,6 +445,29 @@ static QString timespecToString(const QDateTime &dateTime) } } +bool QSQLiteResult::execBatch(bool arrayBind) +{ + Q_UNUSED(arrayBind); + Q_D(QSqlResult); + QScopedValueRollback> valuesScope(d->values); + QVector values = d->values; + if (values.count() == 0) + return false; + + for (int i = 0; i < values.at(0).toList().count(); ++i) { + d->values.clear(); + QScopedValueRollback>> indexesScope(d->indexes); + QHash>::const_iterator it = d->indexes.constBegin(); + while (it != d->indexes.constEnd()) { + bindValue(it.key(), values.at(it.value().first()).toList().at(i), QSql::In); + ++it; + } + if (!exec()) + return false; + } + return true; +} + bool QSQLiteResult::exec() { Q_D(QSQLiteResult); diff --git a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp index 6843ff7d4a..9093485c40 100644 --- a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp +++ b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp @@ -359,7 +359,6 @@ void tst_QSqlQuery::dropTestTables( QSqlDatabase db ) << qTableName("more_results", __FILE__, db) << qTableName("blobstest", __FILE__, db) << qTableName("oraRowId", __FILE__, db) - << qTableName("qtest_batch", __FILE__, db) << qTableName("bug43874", __FILE__, db) << qTableName("bug6421", __FILE__, db).toUpper() << qTableName("bug5765", __FILE__, db) @@ -2439,76 +2438,103 @@ void tst_QSqlQuery::batchExec() QSqlDatabase db = QSqlDatabase::database( dbName ); CHECK_DATABASE( db ); - if ( !db.driver()->hasFeature( QSqlDriver::BatchOperations ) ) - QSKIP( "Database can't do BatchOperations"); - QSqlQuery q( db ); const QString tableName = qTableName("qtest_batch", __FILE__, db); + tst_Databases::safeDropTable(db, tableName); + QVERIFY_SQL(q, exec(QStringLiteral("create table ") + tableName + + QStringLiteral(" (id int, name varchar(20), dt date, num numeric(8, 4), " + "dtstamp TIMESTAMP(3), extraId int, extraName varchar(20))"))); - QVERIFY_SQL(q, exec("create table " + tableName + " (id int, name varchar(20), dt date, num numeric(8, 4), dtstamp TIMESTAMP(3))")); - QVERIFY_SQL(q, prepare("insert into " + tableName + " (id, name, dt, num, dtstamp) values (?, ?, ?, ?, ?)")); - - QVariantList intCol; - intCol << 1 << 2 << QVariant( QVariant::Int ); - - QVariantList charCol; - charCol << QLatin1String( "harald" ) << QLatin1String( "boris" ) << QVariant( QVariant::String ); - - QVariantList dateCol; - QDateTime dt = QDateTime( QDate::currentDate(), QTime( 1, 2, 3 ) ); - dateCol << dt << dt.addDays( -1 ) << QVariant( QVariant::DateTime ); - - QVariantList numCol; - numCol << 2.3 << 3.4 << QVariant( QVariant::Double ); - - QVariantList timeStampCol; - const QDateTime dtStamp = QDateTime(QDate::currentDate(), QTime(1, 2, 3, 4)); - timeStampCol << dtStamp << dtStamp.addDays(-1) << QVariant(QVariant::DateTime); + const QVariantList intCol = { 1, 2, QVariant(QVariant::Int) }; + const QVariantList charCol = { QStringLiteral("harald"), QStringLiteral("boris"), + QVariant(QVariant::String) }; + const QDateTime currentDateTime = QDateTime(QDateTime::currentDateTime()); + const QVariantList dateCol = { currentDateTime.date(), currentDateTime.date().addDays(-1), + QVariant(QVariant::Date) }; + const QVariantList numCol = { 2.3, 3.4, QVariant(QVariant::Double) }; + const QVariantList timeStampCol = { currentDateTime, currentDateTime.addDays(-1), + QVariant(QVariant::DateTime) }; + // Test with positional placeholders + QVERIFY_SQL(q, prepare(QStringLiteral("insert into ") + tableName + + QStringLiteral(" (id, name, dt, num, dtstamp, extraId, extraName) values " + "(?, ?, ?, ?, ?, ?, ?)"))); q.addBindValue(intCol); q.addBindValue( charCol ); q.addBindValue( dateCol ); q.addBindValue( numCol ); q.addBindValue(timeStampCol); + q.addBindValue(intCol); + q.addBindValue(charCol); QVERIFY_SQL( q, execBatch() ); - QVERIFY_SQL(q, exec("select id, name, dt, num, dtstamp from " + tableName + " order by id")); + QVERIFY_SQL(q, exec(QStringLiteral("select id, name, dt, num, dtstamp, " + "extraId, extraName from ") + tableName)); - QVERIFY( q.next() ); - QCOMPARE( q.value( 0 ).toInt(), 1 ); - QCOMPARE( q.value( 1 ).toString(), QString( "harald" ) ); - QCOMPARE( q.value( 2 ).toDateTime(), dt ); - QCOMPARE( q.value( 3 ).toDouble(), 2.3 ); - QCOMPARE(q.value(4).toDateTime(), dtStamp); + for (int i = 0; i < intCol.size(); ++i) { + QVERIFY(q.next()); + QCOMPARE(q.value(0).toInt(), intCol.at(i)); + QCOMPARE(q.value(1).toString(), charCol.at(i)); + QCOMPARE(q.value(2).toDate(), dateCol.at(i)); + QCOMPARE(q.value(3).toDouble(), numCol.at(i)); + if (tst_Databases::getDatabaseType(db) == QSqlDriver::MySqlServer && timeStampCol.at(i).isNull()) { + QEXPECT_FAIL("", "This appears to be a bug in MySQL as it converts null datetimes to the " + "current datetime for a timestamp field", Continue); + } + QCOMPARE(q.value(4).toDateTime(), timeStampCol.at(i)); + QCOMPARE(q.value(5).toInt(), intCol.at(i)); + QCOMPARE(q.value(6).toString(), charCol.at(i)); + } - QVERIFY( q.next() ); - QCOMPARE( q.value( 0 ).toInt(), 2 ); - QCOMPARE( q.value( 1 ).toString(), QString( "boris" ) ); - QCOMPARE( q.value( 2 ).toDateTime(), dt.addDays( -1 ) ); - QCOMPARE( q.value( 3 ).toDouble(), 3.4 ); - QCOMPARE(q.value(4).toDateTime(), dtStamp.addDays(-1)); + // Empty table ready for retesting with duplicated named placeholders + QVERIFY_SQL(q, exec(QStringLiteral("delete from ") + tableName)); + QVERIFY_SQL(q, prepare(QStringLiteral("insert into ") + tableName + + QStringLiteral(" (id, name, dt, num, dtstamp, extraId, extraName) " + "values (:id, :name, :dt, :num, :dtstamp, :id, :name)"))); + q.bindValue(":id", intCol); + q.bindValue(":name", charCol); + q.bindValue(":dt", dateCol); + q.bindValue(":num", numCol); + q.bindValue(":dtstamp", timeStampCol); - QVERIFY( q.next() ); - QVERIFY( q.value( 0 ).isNull() ); - QVERIFY( q.value( 1 ).isNull() ); - QVERIFY( q.value( 2 ).isNull() ); - QVERIFY( q.value( 3 ).isNull() ); - QVERIFY(q.value(4).isNull()); - - const QString procName = qTableName("qtest_batch_proc", __FILE__, db); - QVERIFY_SQL(q, exec("create or replace procedure " + procName + " (x in timestamp, y out timestamp) is\n" - "begin\n" - " y := x;\n" - "end;\n")); - QVERIFY(q.prepare("call " + procName + "(?, ?)")); - q.addBindValue(timeStampCol, QSql::In); - QVariantList emptyDateTimes; - emptyDateTimes.reserve(timeStampCol.size()); - for (int i = 0; i < timeStampCol.size(); i++) - emptyDateTimes << QVariant(QDateTime()); - q.addBindValue(emptyDateTimes, QSql::Out); QVERIFY_SQL(q, execBatch()); - QCOMPARE(q.boundValue(1).toList(), timeStampCol); + QVERIFY_SQL(q, exec(QStringLiteral("select id, name, dt, num, dtstamp, extraId, extraName from ") + + tableName)); + + for (int i = 0; i < intCol.size(); ++i) { + QVERIFY(q.next()); + QCOMPARE(q.value(0).toInt(), intCol.at(i)); + QCOMPARE(q.value(1).toString(), charCol.at(i)); + QCOMPARE(q.value(2).toDate(), dateCol.at(i)); + QCOMPARE(q.value(3).toDouble(), numCol.at(i)); + if (tst_Databases::getDatabaseType(db) == QSqlDriver::MySqlServer && timeStampCol.at(i).isNull()) { + QEXPECT_FAIL("", "This appears to be a bug in MySQL as it converts null datetimes to the " + "current datetime for a timestamp field", Continue); + } + QCOMPARE(q.value(4).toDateTime(), timeStampCol.at(i)); + QCOMPARE(q.value(5).toInt(), intCol.at(i)); + QCOMPARE(q.value(6).toString(), charCol.at(i)); + } + + // Only test the prepared stored procedure approach where the driver has support + // for batch operations as this will not work without it + if (db.driver()->hasFeature(QSqlDriver::BatchOperations)) { + const QString procName = qTableName("qtest_batch_proc", __FILE__, db); + QVERIFY_SQL(q, exec("create or replace procedure " + procName + + " (x in timestamp, y out timestamp) is\n" + "begin\n" + " y := x;\n" + "end;\n")); + QVERIFY(q.prepare("call " + procName + "(?, ?)")); + q.addBindValue(timeStampCol, QSql::In); + QVariantList emptyDateTimes; + emptyDateTimes.reserve(timeStampCol.size()); + for (int i = 0; i < timeStampCol.size(); i++) + emptyDateTimes << QVariant(QDateTime()); + q.addBindValue(emptyDateTimes, QSql::Out); + QVERIFY_SQL(q, execBatch()); + QCOMPARE(q.boundValue(1).toList(), timeStampCol); + } } void tst_QSqlQuery::QTBUG_43874() From 2562fe35cfd43c539a2a815752c5b9bf23529214 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Fri, 16 Mar 2018 18:06:37 -0700 Subject: [PATCH 47/51] QMacStyle: Do manual button sizing for CT_PushButton MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We guarantee the same sizes as previously with HITheme for most common cases. Exotic cases may break and will be fixed along the way. Change-Id: I3e3e6ea702c7489c1cbaa821a30916f63c440c1f Reviewed-by: Morten Johan Sørvig --- src/plugins/styles/mac/qmacstyle_mac.mm | 77 ++++++++++++------------- 1 file changed, 37 insertions(+), 40 deletions(-) diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index 043a910a7c..14c4dd34d3 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -888,7 +888,11 @@ static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QWidget *widg // However, this doesn't work for German, therefore only do it for English, // I suppose it would be better to do some sort of lookups for languages // that like to have really long words. - ret.setWidth(77 - 8); + // FIXME This is not exactly true. Out of context, OK buttons have their + // implicit size calculated the same way as any other button. Inside a + // QDialogButtonBox, their size should be calculated such that the action + // or accept button (i.e., rightmost) and cancel button have the same width. + ret.setWidth(69); } } else { // The only sensible thing to do is to return whatever the style suggests... @@ -6419,16 +6423,33 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, } break; #endif - case QStyle::CT_PushButton: + case QStyle::CT_PushButton: { + if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) + if (btn->features & QStyleOptionButton::CommandLinkButton) + return QCommonStyle::sizeFromContents(ct, opt, sz, widget); + // By default, we fit the contents inside a normal rounded push button. // Do this by add enough space around the contents so that rounded // borders (including highlighting when active) will show. - sz.rwidth() += QMacStylePrivate::PushButtonLeftOffset + QMacStylePrivate::PushButtonRightOffset + 12; - if (opt->state & QStyle::State_Small) - sz.rheight() += 14; + // TODO Use QFocusFrame and get rid of these horrors. + QSize macsz; + const auto controlSize = d->effectiveAquaSizeConstrain(opt, widget, CT_PushButton, sz, &macsz); + // FIXME See comment in CT_PushButton case in qt_aqua_get_known_size(). + if (macsz.width() != -1) + sz.setWidth(macsz.width()); else - sz.rheight() += 4; + sz.rwidth() += QMacStylePrivate::PushButtonLeftOffset + QMacStylePrivate::PushButtonRightOffset + 12; + // All values as measured from HIThemeGetButtonBackgroundBounds() + if (controlSize != QStyleHelper::SizeMini) + sz.rwidth() += 12; // We like 12 over here. + if (controlSize == QStyleHelper::SizeLarge && sz.height() > 16) + sz.rheight() += pushButtonDefaultHeight[QStyleHelper::SizeLarge] - 16; + else if (controlSize == QStyleHelper::SizeMini) + sz.setHeight(24); // FIXME Our previous HITheme-based logic returned this. + else + sz.setHeight(pushButtonDefaultHeight[controlSize]); break; + } case QStyle::CT_MenuItem: if (const QStyleOptionMenuItem *mi = qstyleoption_cast(opt)) { int maxpmw = mi->maxIconWidth; @@ -6535,7 +6556,8 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget); } - if (useAquaGuideline){ + if (useAquaGuideline && ct != CT_PushButton) { + // TODO Probably going away at some point QSize macsz; if (d->aquaSizeConstrain(opt, widget, ct, sz, &macsz) != QStyleHelper::SizeDefault) { if (macsz.width() != -1) @@ -6555,42 +6577,17 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, const CGRect diffRect = QMacStylePrivate::comboboxInnerBounds(CGRectZero, cw); sz.rwidth() -= qRound(diffRect.size.width); sz.rheight() -= qRound(diffRect.size.height); - } else if (ct == CT_PushButton || ct == CT_ToolButton){ + } else if (ct == CT_ToolButton){ ThemeButtonKind bkind; QStyleHelper::WidgetSizePolicy widgetSize = d->aquaSizeConstrain(opt, widget); - switch (ct) { - default: - case CT_PushButton: - if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { - if (btn->features & QStyleOptionButton::CommandLinkButton) { - return QCommonStyle::sizeFromContents(ct, opt, sz, widget); - } - } - - switch (widgetSize) { - case QStyleHelper::SizeDefault: - case QStyleHelper::SizeLarge: - bkind = kThemePushButton; - break; - case QStyleHelper::SizeSmall: - bkind = kThemePushButtonSmall; - break; - case QStyleHelper::SizeMini: - bkind = kThemePushButtonMini; - break; - } - break; - case CT_ToolButton: - switch (widgetSize) { - case QStyleHelper::SizeDefault: - case QStyleHelper::SizeLarge: - bkind = kThemeLargeBevelButton; - break; - case QStyleHelper::SizeMini: - case QStyleHelper::SizeSmall: - bkind = kThemeSmallBevelButton; - } + switch (widgetSize) { + case QStyleHelper::SizeDefault: + case QStyleHelper::SizeLarge: + bkind = kThemeLargeBevelButton; break; + case QStyleHelper::SizeMini: + case QStyleHelper::SizeSmall: + bkind = kThemeSmallBevelButton; } HIThemeButtonDrawInfo bdi; From 50428e97270ad7c87439af599dce33b697c8cc44 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Mon, 19 Mar 2018 18:32:56 -0700 Subject: [PATCH 48/51] QMacStyle: SE_PushButtonContents is HITheme-free MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This also removes a few HITheme-related functions that are no longer needed. Change-Id: I356938d1e99f5fed106c945a94050fa35db58716 Reviewed-by: Morten Johan Sørvig --- src/plugins/styles/mac/qmacstyle_mac.mm | 172 +++++---------------- src/plugins/styles/mac/qmacstyle_mac_p_p.h | 1 + 2 files changed, 42 insertions(+), 131 deletions(-) diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index 14c4dd34d3..f945555326 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -1505,47 +1505,6 @@ QStyleHelper::WidgetSizePolicy QMacStylePrivate::aquaSizeConstrain(const QStyleO #endif } -/** - Returns the free space awailable for contents inside the - button (and not the size of the contents itself) -*/ -CGRect QMacStylePrivate::pushButtonContentBounds(const QStyleOptionButton *btn, - const HIThemeButtonDrawInfo *bdi) const -{ - CGRect outerBounds = btn->rect.toCGRect(); - // Adjust the bounds to correct for - // carbon not calculating the content bounds fully correct - if (bdi->kind == kThemePushButton || bdi->kind == kThemePushButtonSmall){ - outerBounds.origin.y += QMacStylePrivate::PushButtonTopOffset; - outerBounds.size.height -= QMacStylePrivate::PushButtonBottomOffset; - } else if (bdi->kind == kThemePushButtonMini) { - outerBounds.origin.y += QMacStylePrivate::PushButtonTopOffset; - } - - CGRect contentBounds; - HIThemeGetButtonContentBounds(&outerBounds, bdi, &contentBounds); - return contentBounds; -} - -/** - Calculates the size of the button contents. - This includes both the text and the icon. -*/ -QSize QMacStylePrivate::pushButtonSizeFromContents(const QStyleOptionButton *btn) const -{ - Q_Q(const QMacStyle); - QSize csz(0, 0); - QSize iconSize = btn->icon.isNull() ? QSize(0, 0) - : (btn->iconSize + QSize(QMacStylePrivate::PushButtonContentPadding, 0)); - QRect textRect = btn->text.isEmpty() ? QRect(0, 0, 1, 1) - : btn->fontMetrics.boundingRect(QRect(), Qt::AlignCenter, btn->text); - csz.setWidth(iconSize.width() + textRect.width() - + ((btn->features & QStyleOptionButton::HasMenu) - ? q->proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, 0) : 0)); - csz.setHeight(qMax(iconSize.height(), textRect.height())); - return csz; -} - uint qHash(const QMacStylePrivate::CocoaControl &cw, uint seed = 0) { return ((cw.type << 2) | cw.size) ^ seed; @@ -1615,6 +1574,33 @@ QRectF QMacStylePrivate::CocoaControl::adjustedControlFrame(const QRectF &rect) return frameRect; } +QMarginsF QMacStylePrivate::CocoaControl::titleMargins() const +{ + if (type == QMacStylePrivate::Button_PushButton) { + if (size == QStyleHelper::SizeLarge) + return QMarginsF(12, 5, 12, 9); + if (size == QStyleHelper::SizeSmall) + return QMarginsF(12, 4, 12, 9); + if (size == QStyleHelper::SizeMini) + return QMarginsF(10, 1, 10, 2); + } + + if (type == QMacStylePrivate::Button_PullDown) { + if (size == QStyleHelper::SizeLarge) + return QMarginsF(7.5, 2.5, 22.5, 5.5); + if (size == QStyleHelper::SizeSmall) + return QMarginsF(7.5, 2, 20.5, 4); + if (size == QStyleHelper::SizeMini) + return QMarginsF(4.5, 1, 16.5, 2); + } + + if (type == QMacStylePrivate::Button_SquareButton) + return QMarginsF(6, 1, 6, 2); + + return QMarginsF(); +} + + bool QMacStylePrivate::CocoaControl::getCocoaButtonTypeAndBezelStyle(NSButtonType *buttonType, NSBezelStyle *bezelStyle) const { switch (type) { @@ -1664,89 +1650,6 @@ QMacStylePrivate::CocoaControlType cocoaControlType(const QStyleOption *opt, con return QMacStylePrivate::NoControl; } -/** - Checks if the actual contents of btn fits inside the free content bounds of - 'buttonKindToCheck'. Meant as a helper function for 'initHIThemePushButton' - for determining which button kind to use for drawing. -*/ -bool QMacStylePrivate::contentFitsInPushButton(const QStyleOptionButton *btn, - HIThemeButtonDrawInfo *bdi, - ThemeButtonKind buttonKindToCheck) const -{ - ThemeButtonKind tmp = bdi->kind; - bdi->kind = buttonKindToCheck; - QSize contentSize = pushButtonSizeFromContents(btn); - QRect freeContentRect = QRectF::fromCGRect(pushButtonContentBounds(btn, bdi)).toRect(); - bdi->kind = tmp; - return freeContentRect.contains(QRect(freeContentRect.x(), freeContentRect.y(), - contentSize.width(), contentSize.height())); -} - -/** - Creates a HIThemeButtonDrawInfo structure that specifies the correct button - kind and other details to use for drawing the given push button. Which - button kind depends on the size of the button, the size of the contents, - explicit user style settings, etc. -*/ -void QMacStylePrivate::initHIThemePushButton(const QStyleOptionButton *btn, - const QWidget *widget, - const ThemeDrawState tds, - HIThemeButtonDrawInfo *bdi) const -{ - ThemeDrawState tdsModified = tds; - if (btn->state & QStyle::State_On) - tdsModified = kThemeStatePressed; - bdi->version = qt_mac_hitheme_version; - bdi->state = tdsModified; - bdi->value = kThemeButtonOff; - - if (tds == kThemeStateInactive) - bdi->state = kThemeStateActive; - if (btn->state & QStyle::State_HasFocus) - bdi->adornment = kThemeAdornmentFocus; - else - bdi->adornment = kThemeAdornmentNone; - - - if (btn->features & (QStyleOptionButton::Flat)) { - bdi->kind = kThemeBevelButton; - } else { - switch (aquaSizeConstrain(btn, widget)) { - case QStyleHelper::SizeSmall: - bdi->kind = kThemePushButtonSmall; - break; - case QStyleHelper::SizeMini: - bdi->kind = kThemePushButtonMini; - break; - case QStyleHelper::SizeLarge: - // ... We should honor if the user is explicit about using the - // large button. But right now Qt will specify the large button - // as default rather than QStyleHelper::SizeDefault. - // So we treat it like QStyleHelper::SizeDefault - // to get the dynamic choosing of button kind. - case QStyleHelper::SizeDefault: - // Choose the button kind that closest match the button rect, but at the - // same time displays the button contents without clipping. - bdi->kind = kThemeBevelButton; - if (btn->rect.width() >= QMacStylePrivate::BevelButtonW && btn->rect.height() >= QMacStylePrivate::BevelButtonH){ - if (widget && widget->testAttribute(Qt::WA_MacVariableSize)) { - if (btn->rect.height() <= QMacStylePrivate::MiniButtonH){ - if (contentFitsInPushButton(btn, bdi, kThemePushButtonMini)) - bdi->kind = kThemePushButtonMini; - } else if (btn->rect.height() <= QMacStylePrivate::SmallButtonH){ - if (contentFitsInPushButton(btn, bdi, kThemePushButtonSmall)) - bdi->kind = kThemePushButtonSmall; - } else if (contentFitsInPushButton(btn, bdi, kThemePushButton)) { - bdi->kind = kThemePushButton; - } - } else { - bdi->kind = kThemePushButton; - } - } - } - } -} - /** Creates a HIThemeButtonDrawInfo structure that specifies the correct button kind and other details to use for drawing the given combobox. Which button @@ -4778,13 +4681,20 @@ QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt, break; case SE_PushButtonContents: if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { - // Unlike Carbon, we want the button to always be drawn inside its bounds. - // Therefore, the button is a bit smaller, so that even if it got focus, - // the focus 'shadow' will be inside. Adjust the content rect likewise. - HIThemeButtonDrawInfo bdi; - d->initHIThemePushButton(btn, widget, d->getDrawState(opt->state), &bdi); - CGRect contentRect = d->pushButtonContentBounds(btn, &bdi); - rect = QRectF::fromCGRect(contentRect).toRect(); + // Comment from the old HITheme days: + // "Unlike Carbon, we want the button to always be drawn inside its bounds. + // Therefore, the button is a bit smaller, so that even if it got focus, + // the focus 'shadow' will be inside. Adjust the content rect likewise." + // In the future, we should consider using -[NSCell titleRectForBounds:]. + // Since it requires configuring the NSButton fully, i.e. frame, image, + // title and font, we keep things more manual until we are more familiar + // with side effects when changing NSButton state. + const auto ct = cocoaControlType(btn, widget); + const auto cs = d->effectiveAquaSizeConstrain(btn, widget); + const auto cw = QMacStylePrivate::CocoaControl(ct, cs); + const auto frameRect = cw.adjustedControlFrame(btn->rect); + const auto titleMargins = cw.titleMargins(); + rect = (frameRect - titleMargins).toRect(); } break; case SE_HeaderLabel: { diff --git a/src/plugins/styles/mac/qmacstyle_mac_p_p.h b/src/plugins/styles/mac/qmacstyle_mac_p_p.h index cef9da041f..e43b16d0f1 100644 --- a/src/plugins/styles/mac/qmacstyle_mac_p_p.h +++ b/src/plugins/styles/mac/qmacstyle_mac_p_p.h @@ -219,6 +219,7 @@ public: QSizeF defaultFrameSize() const; QRectF adjustedControlFrame(const QRectF &rect) const; + QMarginsF titleMargins() const; bool getCocoaButtonTypeAndBezelStyle(NSButtonType *buttonType, NSBezelStyle *bezelStyle) const; }; From 76bec0c49af3504afbb37a1ce805cfcc1d751373 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 20 Mar 2018 11:00:38 -0700 Subject: [PATCH 49/51] QMacStyle: Remove CT_ToolButton related dead code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sizeFromContents() just adds 10 points to the tool button size and returns. Therefore, the HITheme code that used to be shared with CT_PushButton becomes effectively dead. Change-Id: Ib0519b0037ec3097a00e2c14067d851040853499 Reviewed-by: Morten Johan Sørvig --- src/plugins/styles/mac/qmacstyle_mac.mm | 29 ------------------------- 1 file changed, 29 deletions(-) diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index f945555326..67d800df3f 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -6487,35 +6487,6 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, const CGRect diffRect = QMacStylePrivate::comboboxInnerBounds(CGRectZero, cw); sz.rwidth() -= qRound(diffRect.size.width); sz.rheight() -= qRound(diffRect.size.height); - } else if (ct == CT_ToolButton){ - ThemeButtonKind bkind; - QStyleHelper::WidgetSizePolicy widgetSize = d->aquaSizeConstrain(opt, widget); - switch (widgetSize) { - case QStyleHelper::SizeDefault: - case QStyleHelper::SizeLarge: - bkind = kThemeLargeBevelButton; - break; - case QStyleHelper::SizeMini: - case QStyleHelper::SizeSmall: - bkind = kThemeSmallBevelButton; - } - - HIThemeButtonDrawInfo bdi; - bdi.version = qt_mac_hitheme_version; - bdi.state = kThemeStateActive; - bdi.kind = bkind; - bdi.value = kThemeButtonOff; - bdi.adornment = kThemeAdornmentNone; - CGRect macRect, myRect; - myRect = CGRectMake(0, 0, sz.width(), sz.height()); - HIThemeGetButtonBackgroundBounds(&myRect, &bdi, &macRect); - // Mini buttons only return their actual size in HIThemeGetButtonBackgroundBounds, so help them out a bit (guess), - if (bkind == kThemePushButtonMini) - macRect.size.height += 8.; - else if (bkind == kThemePushButtonSmall) - macRect.size.height -= 10; - sz.setWidth(sz.width() + int(macRect.size.width - myRect.size.width)); - sz.setHeight(sz.height() + int(macRect.size.height - myRect.size.height)); } return sz; } From 857e73e042ec4178a2e8c4f1b4f8979aa73e0dbe Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Thu, 22 Mar 2018 18:01:30 -0700 Subject: [PATCH 50/51] QMacStyle: Fix text color for disabled default buttons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I7c6ba0c3818a3e269e0350153cbde355bafd249a Reviewed-by: Morten Johan Sørvig --- src/plugins/styles/mac/qmacstyle_mac.mm | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index 67d800df3f..7134d904fc 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -3942,6 +3942,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter // windows style if it has an icon and text, then it should be more like a // tab. So, cheat a little here. However, if it *is* only an icon // the windows style works great, so just use that implementation. + const bool isEnabled = btn.state & State_Enabled; const bool hasMenu = btn.features & QStyleOptionButton::HasMenu; const bool hasIcon = !btn.icon.isNull(); const bool hasText = !btn.text.isEmpty(); @@ -3952,7 +3953,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter if (!hasMenu && ct != QMacStylePrivate::Button_SquareButton) { if (isPressed - || (isActive + || (isActive && isEnabled && ((btn.features & QStyleOptionButton::DefaultButton && !d->autoDefaultButton) || d->autoDefaultButton == btn.styleObject))) btn.palette.setColor(QPalette::ButtonText, Qt::white); @@ -3963,7 +3964,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter } else { QRect freeContentRect = btn.rect; QRect textRect = itemTextRect( - btn.fontMetrics, freeContentRect, Qt::AlignCenter, btn.state & State_Enabled, btn.text); + btn.fontMetrics, freeContentRect, Qt::AlignCenter, isEnabled, btn.text); if (hasMenu) { textRect.moveTo(w ? 15 : 11, textRect.top()); // Supports Qt Quick Controls } @@ -3972,7 +3973,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter int contentW = textRect.width(); if (hasMenu) contentW += proxy()->pixelMetric(PM_MenuButtonIndicator) + 4; - QIcon::Mode mode = btn.state & State_Enabled ? QIcon::Normal : QIcon::Disabled; + QIcon::Mode mode = isEnabled ? QIcon::Normal : QIcon::Disabled; if (mode == QIcon::Normal && btn.state & State_HasFocus) mode = QIcon::Active; // Decide if the icon is should be on or off: @@ -3996,7 +3997,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter if (hasText) { textRect = visualRect(btn.direction, freeContentRect, textRect); proxy()->drawItemText(p, textRect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, btn.palette, - (btn.state & State_Enabled), btn.text, QPalette::ButtonText); + isEnabled, btn.text, QPalette::ButtonText); } } } From e83f1900f657a41036bd16e917527fcb7a52fd2b Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Thu, 22 Mar 2018 18:02:09 -0700 Subject: [PATCH 51/51] QMacStyle: Fix spinbox implicit height MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't need to accommodate for the fake frame anymore. Change-Id: I2d84441d4239e1ff68f640dffda1a0d1a97fa2b3 Reviewed-by: Morten Johan Sørvig --- src/plugins/styles/mac/qmacstyle_mac.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index 7134d904fc..10649e6115 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -6209,7 +6209,7 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, case CT_SpinBox: if (const QStyleOptionSpinBox *vopt = qstyleoption_cast(opt)) { const int buttonWidth = 20; // FIXME Use subControlRect() - sz += QSize(buttonWidth, -3); + sz += QSize(buttonWidth, 0); } break; #endif