From 112c0632d944114ba2b4eb4875c4f65cd0c261eb Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Sun, 11 Jun 2017 00:51:20 +0200 Subject: [PATCH 1/9] tst_QLocale::formattedDataSize: add Russian The table and macros weren't extensible enough for non-Latin-based languages. Change-Id: I950f06de57aaf6bd0b24e0056e4acee2fb655f3d Reviewed-by: Edward Welbourne Reviewed-by: Thiago Macieira --- .../corelib/tools/qlocale/tst_qlocale.cpp | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp index 6132dabeea..2556c7e618 100644 --- a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp +++ b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp @@ -2742,6 +2742,37 @@ void tst_QLocale::formattedDataSize_data() #undef ROWQ #undef ROWB } + + // Languages which don't use a Latin alphabet + + const QLocale::DataSizeFormats iecFormat = QLocale::DataSizeIecFormat; + const QLocale::DataSizeFormats traditionalFormat = QLocale::DataSizeTraditionalFormat; + const QLocale::DataSizeFormats siFormat = QLocale::DataSizeSIFormat; + const QLocale::Language lang = QLocale::Russian; + + QTest::newRow("Russian-IEC-0") << lang << 2 << iecFormat << 0 << QString("0 \u0431\u0430\u0439\u0442\u044B"); + QTest::newRow("Russian-IEC-10") << lang << 2 << iecFormat << 10 << QString("10 \u0431\u0430\u0439\u0442\u044B"); + // CLDR doesn't provide IEC prefixes (yet?) so they aren't getting translated + QTest::newRow("Russian-IEC-12Ki") << lang << 2 << iecFormat << 12345 << QString("12,06 KiB"); + QTest::newRow("Russian-IEC-16Ki") << lang << 2 << iecFormat << 16384 << QString("16,00 KiB"); + QTest::newRow("Russian-IEC-1235k") << lang << 2 << iecFormat << 1234567 << QString("1,18 MiB"); + QTest::newRow("Russian-IEC-1374k") << lang << 2 << iecFormat << 1374744 << QString("1,31 MiB"); + QTest::newRow("Russian-IEC-1234M") << lang << 2 << iecFormat << 1234567890 << QString("1,15 GiB"); + + QTest::newRow("Russian-Trad-0") << lang << 2 << traditionalFormat << 0 << QString("0 \u0431\u0430\u0439\u0442\u044B"); + QTest::newRow("Russian-Trad-10") << lang << 2 << traditionalFormat << 10 << QString("10 \u0431\u0430\u0439\u0442\u044B"); + QTest::newRow("Russian-Trad-12Ki") << lang << 2 << traditionalFormat << 12345 << QString("12,06 \u043A\u0411"); + QTest::newRow("Russian-Trad-16Ki") << lang << 2 << traditionalFormat << 16384 << QString("16,00 \u043A\u0411"); + QTest::newRow("Russian-Trad-1235k") << lang << 2 << traditionalFormat << 1234567 << QString("1,18 \u041C\u0411"); + QTest::newRow("Russian-Trad-1374k") << lang << 2 << traditionalFormat << 1374744 << QString("1,31 \u041C\u0411"); + QTest::newRow("Russian-Trad-1234M") << lang << 2 << traditionalFormat << 1234567890 << QString("1,15 \u0413\u0411"); + + QTest::newRow("Russian-Decimal-0") << lang << 2 << siFormat << 0 << QString("0 \u0431\u0430\u0439\u0442\u044B"); + QTest::newRow("Russian-Decimal-10") << lang << 2 << siFormat << 10 << QString("10 \u0431\u0430\u0439\u0442\u044B"); + QTest::newRow("Russian-Decimal-16Ki") << lang << 2 << siFormat << 16384 << QString("16,38 \u043A\u0411"); + QTest::newRow("Russian-Decimal-1234k") << lang << 2 << siFormat << 1234567 << QString("1,23 \u041C\u0411"); + QTest::newRow("Russian-Decimal-1374k") << lang << 2 << siFormat << 1374744 << QString("1,37 \u041C\u0411"); + QTest::newRow("Russian-Decimal-1234M") << lang << 2 << siFormat << 1234567890 << QString("1,23 \u0413\u0411"); } void tst_QLocale::formattedDataSize() From 231273b130d4cc213158ce858262b7f1b7b6fcdd Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 28 Jun 2018 15:09:23 +0200 Subject: [PATCH 2/9] JSON: Add qHash functions for JSON and CBOR types This way we can easily use them as keys in QHash and QSet. Change-Id: Ie744c3b5ad1176ba2ab035c7e650af483757a0c9 Reviewed-by: Thiago Macieira --- src/corelib/serialization/qcborarray.cpp | 5 +++ src/corelib/serialization/qcborarray.h | 2 + src/corelib/serialization/qcbormap.cpp | 5 +++ src/corelib/serialization/qcbormap.h | 2 + src/corelib/serialization/qcborvalue.cpp | 47 +++++++++++++++++++++++ src/corelib/serialization/qcborvalue.h | 2 + src/corelib/serialization/qjsonarray.cpp | 4 ++ src/corelib/serialization/qjsonarray.h | 2 + src/corelib/serialization/qjsonobject.cpp | 11 ++++++ src/corelib/serialization/qjsonobject.h | 2 + src/corelib/serialization/qjsonvalue.cpp | 22 +++++++++++ src/corelib/serialization/qjsonvalue.h | 2 + src/corelib/tools/qhashfunctions.h | 5 +++ 13 files changed, 111 insertions(+) diff --git a/src/corelib/serialization/qcborarray.cpp b/src/corelib/serialization/qcborarray.cpp index 506fb052be..05403795b0 100644 --- a/src/corelib/serialization/qcborarray.cpp +++ b/src/corelib/serialization/qcborarray.cpp @@ -1181,6 +1181,11 @@ void QCborArray::detach(qsizetype reserved) Returns the offset of this iterator relative to \a other. */ +uint qHash(const QCborArray &array, uint seed) +{ + return qHashRange(array.begin(), array.end(), seed); +} + #if !defined(QT_NO_DEBUG_STREAM) QDebug operator<<(QDebug dbg, const QCborArray &a) { diff --git a/src/corelib/serialization/qcborarray.h b/src/corelib/serialization/qcborarray.h index 4e9f7cf9b5..6b07b52a02 100644 --- a/src/corelib/serialization/qcborarray.h +++ b/src/corelib/serialization/qcborarray.h @@ -286,6 +286,8 @@ inline QCborArray QCborValueRef::toArray(const QCborArray &a) const return concrete().toArray(a); } +Q_CORE_EXPORT uint qHash(const QCborArray &array, uint seed = 0); + #if !defined(QT_NO_DEBUG_STREAM) Q_CORE_EXPORT QDebug operator<<(QDebug, const QCborArray &a); #endif diff --git a/src/corelib/serialization/qcbormap.cpp b/src/corelib/serialization/qcbormap.cpp index f9b000393c..b18945ded1 100644 --- a/src/corelib/serialization/qcbormap.cpp +++ b/src/corelib/serialization/qcbormap.cpp @@ -1734,6 +1734,11 @@ void QCborMap::detach(qsizetype reserved) \sa operator+=(), operator-() */ +uint qHash(const QCborMap &map, uint seed) +{ + return qHashRange(map.begin(), map.end(), seed); +} + #if !defined(QT_NO_DEBUG_STREAM) QDebug operator<<(QDebug dbg, const QCborMap &m) { diff --git a/src/corelib/serialization/qcbormap.h b/src/corelib/serialization/qcbormap.h index 2e9422cf94..c895abfa59 100644 --- a/src/corelib/serialization/qcbormap.h +++ b/src/corelib/serialization/qcbormap.h @@ -337,6 +337,8 @@ inline QCborMap QCborValueRef::toMap(const QCborMap &m) const return concrete().toMap(m); } +Q_CORE_EXPORT uint qHash(const QCborMap &map, uint seed = 0); + #if !defined(QT_NO_DEBUG_STREAM) Q_CORE_EXPORT QDebug operator<<(QDebug, const QCborMap &m); #endif diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp index c1d78ef738..077a4754dc 100644 --- a/src/corelib/serialization/qcborvalue.cpp +++ b/src/corelib/serialization/qcborvalue.cpp @@ -2365,6 +2365,53 @@ inline QCborMap::QCborMap(QCborContainerPrivate &dd) noexcept { } +uint qHash(const QCborValue &value, uint seed) +{ + switch (value.type()) { + case QCborValue::Integer: + return qHash(value.toInteger(), seed); + case QCborValue::ByteArray: + return qHash(value.toByteArray(), seed); + case QCborValue::String: + return qHash(value.toString(), seed); + case QCborValue::Array: + return qHash(value.toArray(), seed); + case QCborValue::Map: + return qHash(value.toMap(), seed); + case QCborValue::Tag: { + QtPrivate::QHashCombine hash; + seed = hash(seed, value.tag()); + seed = hash(seed, value.taggedValue()); + return seed; + } + case QCborValue::SimpleType: + break; + case QCborValue::False: + return qHash(false, seed); + case QCborValue::True: + return qHash(true, seed); + case QCborValue::Null: + return qHash(nullptr, seed); + case QCborValue::Undefined: + return seed; + case QCborValue::Double: + return qHash(value.toDouble(), seed); + case QCborValue::DateTime: + return qHash(value.toDateTime(), seed); + case QCborValue::Url: + return qHash(value.toUrl(), seed); + case QCborValue::RegularExpression: + return qHash(value.toRegularExpression(), seed); + case QCborValue::Uuid: + return qHash(value.toUuid(), seed); + case QCborValue::Invalid: + return seed; + } + + Q_ASSERT(value.isSimpleType()); + return qHash(value.toSimpleType(), seed); +} + #if !defined(QT_NO_DEBUG_STREAM) static QDebug debugContents(QDebug &dbg, const QCborValue &v) { diff --git a/src/corelib/serialization/qcborvalue.h b/src/corelib/serialization/qcborvalue.h index f0bfa23392..6d9ed0810a 100644 --- a/src/corelib/serialization/qcborvalue.h +++ b/src/corelib/serialization/qcborvalue.h @@ -451,6 +451,8 @@ private: qsizetype i; }; +Q_CORE_EXPORT uint qHash(const QCborValue &value, uint seed = 0); + #if !defined(QT_NO_DEBUG_STREAM) Q_CORE_EXPORT QDebug operator<<(QDebug, const QCborValue &v); #endif diff --git a/src/corelib/serialization/qjsonarray.cpp b/src/corelib/serialization/qjsonarray.cpp index 8ee9ce0de7..1187bb03a3 100644 --- a/src/corelib/serialization/qjsonarray.cpp +++ b/src/corelib/serialization/qjsonarray.cpp @@ -1237,6 +1237,10 @@ void QJsonArray::compact() a = static_cast(d->header->root()); } +uint qHash(const QJsonArray &array, uint seed) +{ + return qHashRange(array.begin(), array.end(), seed); +} #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) QDebug operator<<(QDebug dbg, const QJsonArray &a) diff --git a/src/corelib/serialization/qjsonarray.h b/src/corelib/serialization/qjsonarray.h index 8d41138c97..5dff4a0aa9 100644 --- a/src/corelib/serialization/qjsonarray.h +++ b/src/corelib/serialization/qjsonarray.h @@ -265,6 +265,8 @@ private: Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QJsonArray) +Q_CORE_EXPORT uint qHash(const QJsonArray &array, uint seed = 0); + #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonArray &); #endif diff --git a/src/corelib/serialization/qjsonobject.cpp b/src/corelib/serialization/qjsonobject.cpp index 4a316c8a6f..950bec535b 100644 --- a/src/corelib/serialization/qjsonobject.cpp +++ b/src/corelib/serialization/qjsonobject.cpp @@ -1292,6 +1292,17 @@ void QJsonObject::setValueAt(int i, const QJsonValue &val) insert(e->key(), val); } +uint qHash(const QJsonObject &object, uint seed) +{ + QtPrivate::QHashCombine hash; + for (auto it = object.begin(), end = object.end(); it != end; ++it) { + const QString key = it.key(); + const QJsonValue value = it.value(); + seed = hash(seed, std::pair(key, value)); + } + return seed; +} + #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) QDebug operator<<(QDebug dbg, const QJsonObject &o) { diff --git a/src/corelib/serialization/qjsonobject.h b/src/corelib/serialization/qjsonobject.h index 610bce694c..be42d3747a 100644 --- a/src/corelib/serialization/qjsonobject.h +++ b/src/corelib/serialization/qjsonobject.h @@ -262,6 +262,8 @@ private: Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QJsonObject) +Q_CORE_EXPORT uint qHash(const QJsonObject &object, uint seed = 0); + #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonObject &); #endif diff --git a/src/corelib/serialization/qjsonvalue.cpp b/src/corelib/serialization/qjsonvalue.cpp index 4469302e31..2c04da4885 100644 --- a/src/corelib/serialization/qjsonvalue.cpp +++ b/src/corelib/serialization/qjsonvalue.cpp @@ -876,6 +876,28 @@ QJsonValue QJsonValueRef::toValue() const return o->valueAt(index); } +uint qHash(const QJsonValue &value, uint seed) +{ + switch (value.type()) { + case QJsonValue::Null: + return qHash(nullptr, seed); + case QJsonValue::Bool: + return qHash(value.toBool(), seed); + case QJsonValue::Double: + return qHash(value.toDouble(), seed); + case QJsonValue::String: + return qHash(value.toString(), seed); + case QJsonValue::Array: + return qHash(value.toArray(), seed); + case QJsonValue::Object: + return qHash(value.toObject(), seed); + case QJsonValue::Undefined: + return seed; + } + Q_UNREACHABLE(); + return 0; +} + #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) QDebug operator<<(QDebug dbg, const QJsonValue &o) { diff --git a/src/corelib/serialization/qjsonvalue.h b/src/corelib/serialization/qjsonvalue.h index 316d3fdf45..d8e121524d 100644 --- a/src/corelib/serialization/qjsonvalue.h +++ b/src/corelib/serialization/qjsonvalue.h @@ -247,6 +247,8 @@ public: Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QJsonValue) +Q_CORE_EXPORT uint qHash(const QJsonValue &value, uint seed = 0); + #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY) Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonValue &); #endif diff --git a/src/corelib/tools/qhashfunctions.h b/src/corelib/tools/qhashfunctions.h index e6ae7a0b85..d013c26d66 100644 --- a/src/corelib/tools/qhashfunctions.h +++ b/src/corelib/tools/qhashfunctions.h @@ -104,6 +104,11 @@ Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QBitArray &key, uint seed = Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(QLatin1String key, uint seed = 0) Q_DECL_NOTHROW; Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qt_hash(QStringView key, uint chained = 0) Q_DECL_NOTHROW; +Q_DECL_CONST_FUNCTION inline uint qHash(std::nullptr_t, uint seed = 0) Q_DECL_NOTHROW +{ + return qHash(reinterpret_cast(nullptr), seed); +} + template inline uint qHash(const T *key, uint seed = 0) Q_DECL_NOTHROW { return qHash(reinterpret_cast(key), seed); From 226d196ab0edb04e98c12d3f7ff091bc021425e3 Mon Sep 17 00:00:00 2001 From: Romain Pokrzywka Date: Wed, 22 Aug 2018 21:54:13 -0500 Subject: [PATCH 3/9] Windows QPA: Improve Pointer Pen events translation Compute QPointF hi-res screen coordinates based on the HIMETRIC values contained in the native message. This gives the same high-precision screen coordinates as what the old WinTab handler supported. Add the possibility to not synthesize mouse events if the platform plugin option DontPassOsMouseEventsSynthesizedFromTouch is set, just like we do for finger touches. This makes it possible to have clean Pen events without mouse duplicates for an application that handles both input types in parallel. Add raw event logging when the platform verbose level is >1. Change-Id: Ibf68b6275400388a76f8d5c573eed8f4b9bf4e9d Reviewed-by: Andre de la Rocha Reviewed-by: Friedemann Kleint --- .../platforms/windows/qwindowscontext.cpp | 4 ++- .../platforms/windows/qwindowscontext.h | 2 ++ .../windows/qwindowspointerhandler.cpp | 30 +++++++++++++++---- 3 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index e29e5b8187..0df6264bcb 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -197,6 +197,7 @@ void QWindowsUser32DLL::init() enableMouseInPointer = (EnableMouseInPointer)library.resolve("EnableMouseInPointer"); getPointerType = (GetPointerType)library.resolve("GetPointerType"); getPointerInfo = (GetPointerInfo)library.resolve("GetPointerInfo"); + getPointerDeviceRects = (GetPointerDeviceRects)library.resolve("GetPointerDeviceRects"); getPointerTouchInfo = (GetPointerTouchInfo)library.resolve("GetPointerTouchInfo"); getPointerFrameTouchInfo = (GetPointerFrameTouchInfo)library.resolve("GetPointerFrameTouchInfo"); getPointerPenInfo = (GetPointerPenInfo)library.resolve("GetPointerPenInfo"); @@ -212,7 +213,8 @@ void QWindowsUser32DLL::init() bool QWindowsUser32DLL::supportsPointerApi() { - return enableMouseInPointer && getPointerType && getPointerInfo && getPointerTouchInfo && getPointerFrameTouchInfo && getPointerPenInfo; + return enableMouseInPointer && getPointerType && getPointerInfo && getPointerDeviceRects + && getPointerTouchInfo && getPointerFrameTouchInfo && getPointerPenInfo; } void QWindowsShcoreDLL::init() diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h index 3709d9deee..33bd42a669 100644 --- a/src/plugins/platforms/windows/qwindowscontext.h +++ b/src/plugins/platforms/windows/qwindowscontext.h @@ -89,6 +89,7 @@ struct QWindowsUser32DLL typedef BOOL (WINAPI *EnableMouseInPointer)(BOOL); typedef BOOL (WINAPI *GetPointerType)(UINT32, PVOID); typedef BOOL (WINAPI *GetPointerInfo)(UINT32, PVOID); + typedef BOOL (WINAPI *GetPointerDeviceRects)(HANDLE, RECT *, RECT *); typedef BOOL (WINAPI *GetPointerTouchInfo)(UINT32, PVOID); typedef BOOL (WINAPI *GetPointerFrameTouchInfo)(UINT32, UINT32 *, PVOID); typedef BOOL (WINAPI *GetPointerPenInfo)(UINT32, PVOID); @@ -105,6 +106,7 @@ struct QWindowsUser32DLL EnableMouseInPointer enableMouseInPointer = nullptr; GetPointerType getPointerType = nullptr; GetPointerInfo getPointerInfo = nullptr; + GetPointerDeviceRects getPointerDeviceRects = nullptr; GetPointerTouchInfo getPointerTouchInfo = nullptr; GetPointerFrameTouchInfo getPointerFrameTouchInfo = nullptr; GetPointerPenInfo getPointerPenInfo = nullptr; diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp index c11be972b0..abd4d56da0 100644 --- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp +++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp @@ -428,9 +428,18 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin return false; // Let DefWindowProc() handle Non Client messages. POINTER_PEN_INFO *penInfo = static_cast(vPenInfo); + + RECT pRect, dRect; + if (!QWindowsContext::user32dll.getPointerDeviceRects(penInfo->pointerInfo.sourceDevice, &pRect, &dRect)) + return false; + const quint32 pointerId = penInfo->pointerInfo.pointerId; const QPoint globalPos = QPoint(penInfo->pointerInfo.ptPixelLocation.x, penInfo->pointerInfo.ptPixelLocation.y); const QPoint localPos = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPos); + const QPointF hiResGlobalPos = QPointF(dRect.left + qreal(penInfo->pointerInfo.ptHimetricLocation.x - pRect.left) + / (pRect.right - pRect.left) * (dRect.right - dRect.left), + dRect.top + qreal(penInfo->pointerInfo.ptHimetricLocation.y - pRect.top) + / (pRect.bottom - pRect.top) * (dRect.bottom - dRect.top)); const qreal pressure = (penInfo->penMask & PEN_MASK_PRESSURE) ? qreal(penInfo->pressure) / 1024.0 : 0.5; const qreal rotation = (penInfo->penMask & PEN_MASK_ROTATION) ? qreal(penInfo->rotation) : 0.0; const qreal tangentialPressure = 0.0; @@ -438,6 +447,13 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin const int yTilt = (penInfo->penMask & PEN_MASK_TILT_Y) ? penInfo->tiltY : 0; const int z = 0; + if (QWindowsContext::verbose > 1) + qCDebug(lcQpaEvents).noquote().nospace() << showbase + << __FUNCTION__ << " pointerId=" << pointerId + << " globalPos=" << globalPos << " localPos=" << localPos << " hiResGlobalPos=" << hiResGlobalPos + << " message=" << hex << msg.message + << " flags=" << hex << penInfo->pointerInfo.pointerFlags; + const QTabletEvent::TabletDevice device = QTabletEvent::Stylus; QTabletEvent::PointerType type; Qt::MouseButtons mouseButtons; @@ -491,16 +507,18 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin } const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers(); - QWindowSystemInterface::handleTabletEvent(target, localPos, globalPos, device, type, mouseButtons, + QWindowSystemInterface::handleTabletEvent(target, localPos, hiResGlobalPos, device, type, mouseButtons, pressure, xTilt, yTilt, tangentialPressure, rotation, z, pointerId, keyModifiers); - QEvent::Type eventType; - Qt::MouseButton button; - getMouseEventInfo(msg.message, penInfo->pointerInfo.ButtonChangeType, globalPos, &eventType, &button); + if (!(QWindowsIntegration::instance()->options() & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch)) { + QEvent::Type eventType; + Qt::MouseButton button; + getMouseEventInfo(msg.message, penInfo->pointerInfo.ButtonChangeType, globalPos, &eventType, &button); - QWindowSystemInterface::handleMouseEvent(target, localPos, globalPos, mouseButtons, button, eventType, - keyModifiers, Qt::MouseEventSynthesizedByQt); + QWindowSystemInterface::handleMouseEvent(target, localPos, globalPos, mouseButtons, button, eventType, + keyModifiers, Qt::MouseEventSynthesizedByQt); + } break; } } From 14bbb1857192f06274f595213dfde88423ffb0ae Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 28 Aug 2018 10:10:00 +0200 Subject: [PATCH 4/9] Windows Font databases: Rename struct FontNames to QFontNames Prefix by Q to unclutter the namespace in static builds. Amends 9204b8c31ea1b5f0c05870c5b5d74c33b1a4f622 Task-number: QTBUG-53458 Change-Id: I1448cd944b6a3262b9cfa9f5c3fbab17c1c5c71c Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../windows/qwindowsfontdatabase.cpp | 18 +++++++++--------- .../windows/qwindowsfontdatabase_ft.cpp | 2 +- .../windows/qwindowsfontdatabase_p.h | 5 +++-- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp index 953e2bf6be..890792fa2f 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp @@ -799,9 +799,9 @@ enum PlatformFieldValue { PlatformId_Microsoft = 3 }; -FontNames qt_getCanonicalFontNames(const uchar *table, quint32 bytes) +QFontNames qt_getCanonicalFontNames(const uchar *table, quint32 bytes) { - FontNames out; + QFontNames out; const int NameRecordSize = 12; const int MS_LangIdEnglish = 0x009; @@ -947,7 +947,7 @@ QString qt_getEnglishName(const QString &familyName, bool includeStyle) goto error; { - const FontNames names = qt_getCanonicalFontNames(table, bytes); + const QFontNames names = qt_getCanonicalFontNames(table, bytes); i18n_name = names.name; if (includeStyle) i18n_name += QLatin1Char(' ') + names.style; @@ -963,9 +963,9 @@ error: } // Note this duplicates parts of qt_getEnglishName, we should try to unify the two functions. -FontNames qt_getCanonicalFontNames(const LOGFONT &lf) +QFontNames qt_getCanonicalFontNames(const LOGFONT &lf) { - FontNames fontNames; + QFontNames fontNames; HDC hdc = GetDC(0); HFONT hfont = CreateFontIndirect(&lf); @@ -1054,7 +1054,7 @@ static bool addFontToDatabase(QString familyName, QString subFamilyStyle; if (ttf) { // Look-up names registered in the font - FontNames canonicalNames = qt_getCanonicalFontNames(logFont); + QFontNames canonicalNames = qt_getCanonicalFontNames(logFont); if (qt_localizedName(familyName) && !canonicalNames.name.isEmpty()) englishName = canonicalNames.name; if (!canonicalNames.preferredName.isEmpty()) { @@ -1488,7 +1488,7 @@ static void getFontTable(const uchar *fileBegin, const uchar *data, quint32 tag, } static void getFamiliesAndSignatures(const QByteArray &fontData, - QList *families, + QList *families, QVector *signatures) { const uchar *data = reinterpret_cast(fontData.constData()); @@ -1504,7 +1504,7 @@ static void getFamiliesAndSignatures(const QByteArray &fontData, getFontTable(data, font, MAKE_TAG('n', 'a', 'm', 'e'), &table, &length); if (!table) continue; - FontNames names = qt_getCanonicalFontNames(table, length); + QFontNames names = qt_getCanonicalFontNames(table, length); if (names.name.isEmpty()) continue; @@ -1535,7 +1535,7 @@ QStringList QWindowsFontDatabase::addApplicationFont(const QByteArray &fontData, WinApplicationFont font; font.fileName = fileName; QVector signatures; - QList families; + QList families; QStringList familyNames; if (!fontData.isEmpty()) { diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp index 299dfd40cd..f68ea54dcf 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp @@ -210,7 +210,7 @@ static bool addFontToDatabase(QString familyName, QString subFamilyStyle; if (ttf) { // Look-up names registered in the font - FontNames canonicalNames = qt_getCanonicalFontNames(logFont); + QFontNames canonicalNames = qt_getCanonicalFontNames(logFont); if (qt_localizedName(familyName) && !canonicalNames.name.isEmpty()) englishName = canonicalNames.name; if (!canonicalNames.preferredName.isEmpty()) { diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h index 30f5beefdf..9080d3ea9d 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h @@ -168,7 +168,8 @@ inline quint16 qt_getUShort(const unsigned char *p) return val; } -struct FontNames { +struct QFontNames +{ QString name; // e.g. "DejaVu Sans Condensed" QString style; // e.g. "Italic" QString preferredName; // e.g. "DejaVu Sans" @@ -177,7 +178,7 @@ struct FontNames { bool qt_localizedName(const QString &name); QString qt_getEnglishName(const QString &familyName, bool includeStyle = false); -FontNames qt_getCanonicalFontNames(const LOGFONT &lf); +QFontNames qt_getCanonicalFontNames(const LOGFONT &lf); QT_END_NAMESPACE From fbb4befa33196e04bc25e62bbf43f0d3a1d0846b Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 28 Aug 2018 09:29:00 +0200 Subject: [PATCH 5/9] Remove dead code in QWin32PrintEngine The functions checks for _glyphs.isEmpty() and returns in that case, so, there is no point in having another code branch for _glyphs.size() == 0 below. Unindent branch for _glyphs.size() > 0 and brush it up a bit to silence clang-tidy (warnings about using isEmpty(), nullptr). Change-Id: I78e86583bb30c7bea1357e7a45f61b07d5a4d139 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/printsupport/kernel/qprintengine_win.cpp | 43 +++++++------------- 1 file changed, 15 insertions(+), 28 deletions(-) diff --git a/src/printsupport/kernel/qprintengine_win.cpp b/src/printsupport/kernel/qprintengine_win.cpp index 6f263e5ea8..5ee93a46b3 100644 --- a/src/printsupport/kernel/qprintengine_win.cpp +++ b/src/printsupport/kernel/qprintengine_win.cpp @@ -1779,39 +1779,26 @@ static void draw_text_item_win(const QPointF &pos, const QTextItemInt &ti, HDC h QTransform matrix = QTransform::fromTranslate(baseline_pos.x(), baseline_pos.y()); ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, _glyphs, positions); - if (_glyphs.size() == 0) { + if (_glyphs.isEmpty()) { SelectObject(hdc, old_font); return; } - bool outputEntireItem = _glyphs.size() > 0; - - if (outputEntireItem) { - options |= ETO_PDY; - QVarLengthArray glyphDistances(_glyphs.size() * 2); - QVarLengthArray g(_glyphs.size()); - for (int i=0; i<_glyphs.size() - 1; ++i) { - glyphDistances[i * 2] = qRound(positions[i + 1].x) - qRound(positions[i].x); - glyphDistances[i * 2 + 1] = qRound(positions[i + 1].y) - qRound(positions[i].y); - g[i] = _glyphs[i]; - } - glyphDistances[(_glyphs.size() - 1) * 2] = 0; - glyphDistances[(_glyphs.size() - 1) * 2 + 1] = 0; - g[_glyphs.size() - 1] = _glyphs[_glyphs.size() - 1]; - ExtTextOut(hdc, qRound(positions[0].x), qRound(positions[0].y), options, 0, - g.constData(), _glyphs.size(), - glyphDistances.data()); - } else { - int i = 0; - while(i < _glyphs.size()) { - wchar_t g = _glyphs[i]; - - ExtTextOut(hdc, qRound(positions[i].x), - qRound(positions[i].y), options, 0, - &g, 1, 0); - ++i; - } + options |= ETO_PDY; + QVarLengthArray glyphDistances(_glyphs.size() * 2); + QVarLengthArray g(_glyphs.size()); + const int lastGlyph = _glyphs.size() - 1; + for (int i = 0; i < lastGlyph; ++i) { + glyphDistances[i * 2] = qRound(positions[i + 1].x) - qRound(positions[i].x); + glyphDistances[i * 2 + 1] = qRound(positions[i + 1].y) - qRound(positions[i].y); + g[i] = _glyphs[i]; } + glyphDistances[lastGlyph * 2] = 0; + glyphDistances[lastGlyph * 2 + 1] = 0; + g[lastGlyph] = _glyphs[lastGlyph]; + ExtTextOut(hdc, qRound(positions[0].x), qRound(positions[0].y), options, nullptr, + g.constData(), _glyphs.size(), + glyphDistances.data()); } win_xform.eM11 = win_xform.eM22 = 1.0; From 28702cb239b0dbc915ee3511768ff8e366e35e88 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Fri, 17 Aug 2018 12:58:01 +0200 Subject: [PATCH 6/9] Initialize the QSqlQuery to be invalid when creating a sql model When QSqlQueryModel or QSqlTableModel is created it will create a QSqlQuery which defaults to using the default QSqlDatabase connection. If this connection belongs to another thread then it will throw a warning as this is not safe to use. Since the QSqlQuery is always recreated when a query is set, the instance which is a member of the class can effectively be invalid until a new one is set. Task-number: QTBUG-69213 Change-Id: I68a5dd59fe62788f531d59a0680da11b118ee383 Reviewed-by: Christian Ehrlicher Reviewed-by: Edward Welbourne --- src/sql/models/qsqlquerymodel_p.h | 2 +- src/sql/models/qsqltablemodel_p.h | 2 +- .../qsqltablemodel/tst_qsqltablemodel.cpp | 47 +++++++++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/sql/models/qsqlquerymodel_p.h b/src/sql/models/qsqlquerymodel_p.h index 76aaf00c88..d5ca2f89cb 100644 --- a/src/sql/models/qsqlquerymodel_p.h +++ b/src/sql/models/qsqlquerymodel_p.h @@ -75,7 +75,7 @@ public: void initColOffsets(int size); int columnInQuery(int modelColumn) const; - mutable QSqlQuery query; + mutable QSqlQuery query = { QSqlQuery(0) }; mutable QSqlError error; QModelIndex bottom; QSqlRecord rec; diff --git a/src/sql/models/qsqltablemodel_p.h b/src/sql/models/qsqltablemodel_p.h index faa1b30803..bb568ab444 100644 --- a/src/sql/models/qsqltablemodel_p.h +++ b/src/sql/models/qsqltablemodel_p.h @@ -93,7 +93,7 @@ public: QSqlTableModel::EditStrategy strategy; bool busyInsertingRows; - QSqlQuery editQuery; + QSqlQuery editQuery = { QSqlQuery(0) }; QSqlIndex primaryIndex; QString tableName; QString filter; diff --git a/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp b/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp index 430fa981d5..da31f437d9 100644 --- a/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp +++ b/tests/auto/sql/models/qsqltablemodel/tst_qsqltablemodel.cpp @@ -31,11 +31,29 @@ #include "../../kernel/qsqldatabase/tst_databases.h" #include #include +#include const QString test(qTableName("test", __FILE__, QSqlDatabase())), test2(qTableName("test2", __FILE__, QSqlDatabase())), test3(qTableName("test3", __FILE__, QSqlDatabase())); +// In order to catch when the warning message occurs, indicating that the database belongs to another +// thread, we have to install our own message handler. To ensure that the test reporting still happens +// as before, we call the originating one. +// +// For now, this is only called inside the modelInAnotherThread() test +QtMessageHandler oldHandler = nullptr; + +void sqlTableModelMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) +{ + if (type == QtWarningMsg && + msg == "QSqlDatabasePrivate::database: requested database does not " + "belong to the calling thread.") { + QFAIL("Requested database does not belong to the calling thread."); + } + if (oldHandler) + oldHandler(type, context, msg); +} class tst_QSqlTableModel : public QObject { @@ -116,6 +134,7 @@ private slots: void sqlite_bigTable_data() { generic_data("QSQLITE"); } void sqlite_bigTable(); + void modelInAnotherThread(); // bug specific tests void insertRecordBeforeSelect_data() { generic_data(); } @@ -276,6 +295,10 @@ void tst_QSqlTableModel::init() void tst_QSqlTableModel::cleanup() { recreateTestTables(); + if (oldHandler) { + qInstallMessageHandler(oldHandler); + oldHandler = nullptr; + } } void tst_QSqlTableModel::select() @@ -2100,5 +2123,29 @@ void tst_QSqlTableModel::invalidFilterAndHeaderData() QVERIFY(!v.isValid()); } +class SqlThread : public QThread +{ +public: + SqlThread() : QThread() {} + void run() + { + QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "non-default-connection"); + QSqlTableModel stm(nullptr, db); + isDone = true; + } + bool isDone = false; +}; + +void tst_QSqlTableModel::modelInAnotherThread() +{ + oldHandler = qInstallMessageHandler(sqlTableModelMessageHandler); + QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); + CHECK_DATABASE(db); + SqlThread t; + t.start(); + QTRY_VERIFY(t.isDone); + QVERIFY(t.isFinished()); +} + QTEST_MAIN(tst_QSqlTableModel) #include "tst_qsqltablemodel.moc" From d18444fbfffbb01a9eb2d84454e55c231fe0a36f Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Mon, 27 Aug 2018 20:09:12 +0200 Subject: [PATCH 7/9] Handle device pixel ratio in QHeaderView::setupSectionIndicator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The device pixel ratio was not applied to the section indicator pixmap which made it look blurry on HighDPI screens. Task-number: QTBUG-70084 Change-Id: I8b07b2ffc51781c2d2d89484b8618173f0692fe4 Reviewed-by: Morten Johan Sørvig --- src/widgets/itemviews/qheaderview.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp index 70f8b28299..6857ccd8bb 100644 --- a/src/widgets/itemviews/qheaderview.cpp +++ b/src/widgets/itemviews/qheaderview.cpp @@ -3369,7 +3369,9 @@ void QHeaderViewPrivate::setupSectionIndicator(int section, int position) sectionIndicator->resize(w, h); #endif - QPixmap pm(w, h); + const qreal pixmapDevicePixelRatio = q->devicePixelRatioF(); + QPixmap pm(QSize(w, h) * pixmapDevicePixelRatio); + pm.setDevicePixelRatio(pixmapDevicePixelRatio); pm.fill(QColor(0, 0, 0, 45)); QRect rect(0, 0, w, h); From ee5573c6fb49d0b496b19d154e2e1c5154ed5a44 Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Thu, 23 Aug 2018 20:58:31 +0200 Subject: [PATCH 8/9] QSqlQuery: Specify documentation of named placeholders Named placeholders can only contain characters in the range of [a-zA-Z0-9_] but this was not documented anywhere. Task-number: QTBUG-69775 Change-Id: I5c4eff7674b1fc04cef60e7d7f44cd87414ffbe9 Reviewed-by: Paul Wicking Reviewed-by: Andy Shaw --- src/sql/kernel/qsqlquery.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sql/kernel/qsqlquery.cpp b/src/sql/kernel/qsqlquery.cpp index 628bfa1880..daadcb8a0e 100644 --- a/src/sql/kernel/qsqlquery.cpp +++ b/src/sql/kernel/qsqlquery.cpp @@ -942,10 +942,12 @@ void QSqlQuery::clear() query. See the \l{QSqlQuery examples}{Detailed Description} for examples. - Portability note: Some databases choose to delay preparing a query + Portability notes: Some databases choose to delay preparing a query until it is executed the first time. In this case, preparing a syntactically wrong query succeeds, but every consecutive exec() will fail. + When the database does not support named placeholders directly, + the placeholder can only contain characters in the range [a-zA-Z0-9_]. For SQLite, the query string can contain only one statement at a time. If more than one statement is given, the function returns \c false. From 546eb7b9473ee78a9ec4167a4f710eb7998f53eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joni=20J=C3=A4ntti?= Date: Tue, 28 Aug 2018 16:23:01 +0300 Subject: [PATCH 9/9] Blacklist tst_Gestures on Ubuntu 18.04 These autotests are not currently working with the Ubuntu 18.04 platform being introduced to the CI. Task-number: QTBUG-70227 Task-number: QTBUG-70226 Task-number: QTBUG-70224 Task-number: QTBUG-70223 Task-number: QTBUG-70209 Change-Id: Ibe7cafd37763d7d305d8c3d9ec17bc6339db744a Reviewed-by: Liang Qi --- tests/auto/other/gestures/BLACKLIST | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/auto/other/gestures/BLACKLIST b/tests/auto/other/gestures/BLACKLIST index 7f36054c6e..ff6d2fa48e 100644 --- a/tests/auto/other/gestures/BLACKLIST +++ b/tests/auto/other/gestures/BLACKLIST @@ -1,5 +1,6 @@ [] rhel-7.4 +ubuntu-18.04 [customGesture] # QTBUG-67254 ubuntu