From e9190eda1a2b16bd6aa07cce4e00f302eeb3562e Mon Sep 17 00:00:00 2001 From: Paul Wicking Date: Mon, 9 Sep 2019 10:43:27 +0200 Subject: [PATCH 01/22] Doc: Remove broken example snippet from Q_ENUMS The code snippet is used by both Q_ENUMS and Q_ENUM. Therefore, remove the example snippet from Q_ENUMS documentation, as it is obsolete. Also, move recommendation to use Q_ENUM in new code to the very top of Q_ENUMS' documentation. Fixes: QTBUG-63203 Change-Id: I12a9f45e0b3bd75dfe98e1ecbc45e299a688b80c Reviewed-by: Giuseppe D'Angelo --- src/corelib/kernel/qobject.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 1f5b61c978..598ce75bd4 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -4291,22 +4291,18 @@ QDebug operator<<(QDebug dbg, const QObject *o) \relates QObject \obsolete + In new code, you should prefer the use of the Q_ENUM() macro, which makes the + type available also to the meta type system. + For instance, QMetaEnum::fromType() will not work with types declared with Q_ENUMS(). + This macro registers one or several enum types to the meta-object system. - For example: - - \snippet code/src_corelib_kernel_qobject.cpp 38 - If you want to register an enum that is declared in another class, the enum must be fully qualified with the name of the class defining it. In addition, the class \e defining the enum has to inherit QObject as well as declare the enum using Q_ENUMS(). - In new code, you should prefer the use of the Q_ENUM() macro, which makes the - type available also to the meta type system. - For instance, QMetaEnum::fromType() will not work with types declared with Q_ENUMS(). - \sa {Qt's Property System} */ From 51f1428d3cd782c22226b0ee4bd7145a45762d86 Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Thu, 19 Sep 2019 11:56:24 +0200 Subject: [PATCH 02/22] qmake: Replace WinRT with UWP in the qmake Manual Remove info about Windows Phone, which is no longer supported. Task-number: QTBUG-61884 Change-Id: Ic330f0f19a4e7314dd175f6c492fa25133185517 Reviewed-by: Oliver Wolff --- qmake/doc/src/qmake-manual.qdoc | 51 ++++++++++++++------------------- 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc index b178084690..5e54278dd1 100644 --- a/qmake/doc/src/qmake-manual.qdoc +++ b/qmake/doc/src/qmake-manual.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2017 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the documentation of the Qt Toolkit. @@ -2891,8 +2891,8 @@ On desktop Windows, the default value is the value of the environment variable \c{WindowsSDKVersion}. - On WinRT, the default value is the value of the environment variable - \c{UCRTVERSION}. + On Universal Windows Platform (UWP), the default value is the value of the + environment variable \c{UCRTVERSION}. \target WINDOWS_TARGET_PLATFORM_MIN_VERSION \section1 WINDOWS_TARGET_PLATFORM_MIN_VERSION @@ -2905,8 +2905,8 @@ \target WINRT_MANIFEST \section1 WINRT_MANIFEST - Specifies parameters to be passed to the application manifest on \l{Qt for WinRT}{Windows - Runtime}. The allowed values are: + Specifies parameters to be passed to the application manifest on + \l{Qt for UWP}{UWP}. The allowed values are: \table \header @@ -2941,7 +2941,6 @@ \row \li foreground \li Tile foreground (text) color. Defaults to \c{light}. - This option is only available for Windows Store apps on Windows 8 and Windows RT. \row \li iconic_tile_icon \li Image file for the \c{iconic} tile template icon. Default provided by @@ -2956,16 +2955,16 @@ manifest's UUID, or generates a new UUID if none is present. \row \li logo_30x30 - \li Logo image file of size 30x30 pixels. This is not supported on Windows Phone. + \li Logo image file of size 30x30 pixels. \row \li logo_41x41 - \li Logo image file of size 41x41 pixels. This is only supported on Windows Phone. + \li Logo image file of size 41x41 pixels. This parameter is obsolete. \row \li logo_70x70 - \li Logo image file of size 70x70 pixels. This is not supported on Windows Phone. + \li Logo image file of size 70x70 pixels. \row \li logo_71x71 - \li Logo image file of size 71x71 pixels. This is only supported on Windows Phone. + \li Logo image file of size 71x71 pixels. This parameter is obsolete. \row \li logo_150x150 \li Logo image file of size 150x150 pixels. This is supported on all Windows @@ -2980,31 +2979,27 @@ Store App platforms. \row \li logo_620x300 - \li Splash screen image file of size 620x300 pixels. This is not supported on - Windows Phone. + \li Splash screen image file of size 620x300 pixels. \row \li logo_480x800 - \li Splash screen image file of size 480x800 pixels. This is only supported on - Windows Phone. + \li Splash screen image file of size 480x800 pixels. + This parameter is obsolete. \row \li logo_large \li Large logo image file. This has to be 150x150 pixels. Supported on all Windows Store App platforms. Default provided by the mkspec. \row \li logo_medium - \li Medium logo image file. For Windows Phone the image must have a pixel size - of 71x71, for other Windows Store App platforms 70x70. Default provided by - the mkspec. + \li Medium logo image file. The image must have a pixel size of 70x70. + Default provided by the mkspec. \row \li logo_small - \li Small logo image file. For Windows Phone the image must have a pixel size - of 44x44, for other Windows Store App platforms 30x30. Default provided by - the mkspec. + \li Small logo image file. The image must have a pixel size of 30x30. + Default provided by the mkspec. \row \li logo_splash - \li Splash screen image file. For Windows Phone the image must have a pixel size - of 480x800, for other Windows Store App platforms 620x300. Default provided - by the mkspec. + \li Splash screen image file. The image must have a pixel size of + 620x300. Default provided by the mkspec. \row \li logo_store \li Logo image file for Windows Store. Default provided by the mkspec. @@ -3017,10 +3012,12 @@ \li The name of the package as displayed to the user. Defaults to TARGET. \row \li phone_product_id - \li The GUID of the product. Defaults to the value of WINRT_MANIFEST.identity. (Windows Phone only) + \li The GUID of the product. + This parameter is obsolete. \row \li phone_publisher_id - \li The GUID of the publisher. Defaults to an invalid GUID. (Windows Phone only) + \li The GUID of the publisher. + This parameter is obsolete. \row \li publisher \li Display name of the publisher. Defaults to \c{Default publisher display name}. @@ -3071,10 +3068,6 @@ WINRT_MANIFEST.CONFIG += verbatim \endcode - \note The required image sizes of \e logo_small, \e logo_medium, and \e logo_large - depend on the target platform. The general descriptions are overwritten if a - description that specifies the size is provided. - \target YACCSOURCES \section1 YACCSOURCES From b8a911fbebfcd297ce08b91fbe85bb1624d257d9 Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Wed, 11 Sep 2019 11:46:47 +0200 Subject: [PATCH 03/22] QPainter: Avoid leaking memory on unbalanced save/restore If a QPainter ended without all saved states having been restored, the state stack would leak memory. Fixes: QTBUG-77843 Change-Id: I760904d6391de24a4867be54fa1bebf76be14ba7 Reviewed-by: Allan Sandfeld Jensen --- src/gui/painting/qpainter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 95e6bda78b..f9e9563f10 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -1710,8 +1710,8 @@ void QPainter::restore() static inline void qt_cleanup_painter_state(QPainterPrivate *d) { + qDeleteAll(d->states); d->states.clear(); - delete d->state; d->state = 0; d->engine = 0; d->device = 0; From 9b6179cf957c32e0c02547d510dfee2088f02340 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Thu, 5 Sep 2019 12:52:43 +0200 Subject: [PATCH 04/22] Ensure all children of a widget get updated when a stylesheet changes Before, only the direct children would get an update when the stylesheet changed, any children below that would be unchanged. Fixes: QTBUG-77006 Change-Id: Id668eaae74a8289d78d66644f077e6a3302960cd Reviewed-by: Frederik Gladhorn --- src/widgets/styles/qstylesheetstyle.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp index 85b65f39b1..98a9f74f5b 100644 --- a/src/widgets/styles/qstylesheetstyle.cpp +++ b/src/widgets/styles/qstylesheetstyle.cpp @@ -2735,6 +2735,11 @@ static void updateObjects(const QList& objects) if (auto widget = qobject_cast(const_cast(object))) { widget->style()->polish(widget); QApplication::sendEvent(widget, &event); + QList children; + children.reserve(widget->children().size() + 1); + for (auto child: qAsConst(widget->children())) + children.append(child); + updateObjects(children); } } } From ac5e198db4eea4670a5a4a22fb44eb8a6acc4c47 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Sat, 21 Sep 2019 02:02:58 +0200 Subject: [PATCH 05/22] Add SQLite specific documentation when specifying a database name Fixes: QTBUG-67847 Change-Id: I3c640233526260b596e8224dc48f713a3f0cff56 Reviewed-by: Paul Wicking --- src/sql/kernel/qsqldatabase.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/sql/kernel/qsqldatabase.cpp b/src/sql/kernel/qsqldatabase.cpp index d63a9e59a8..f61c72285a 100644 --- a/src/sql/kernel/qsqldatabase.cpp +++ b/src/sql/kernel/qsqldatabase.cpp @@ -881,6 +881,14 @@ bool QSqlDatabase::rollback() connection name must be passed to addDatabase() at connection object create time. + For the QSQLITE driver, if the database name specified does not + exist, then it will create the file for you unless the + QSQLITE_OPEN_READONLY option is set. + + Additionally, \a name can be set to \c ":memory:" which will + create a temporary database which is only available for the + lifetime of the application. + For the QOCI (Oracle) driver, the database name is the TNS Service Name. From ec0e9f29dfd0b45edf5fd33e8ccf763e604612d7 Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Tue, 17 Sep 2019 09:54:28 +0300 Subject: [PATCH 06/22] Android: Fix loading of plugins In 5bb178c479a247720fbc3fbb7f06a32b725193ac, the Android platform plugin was moved from platforms/android to platforms/. The unforeseen consequence of this was that the plugin loader for plugins/platforms would now find it, whereas before it would be ignored. It would therefore be detected as the appropriate plugin, but since it was intended to be loaded as a static plugin, loading it dynamically would fail. Instead of fixing the static plugin loading, we remove this hack. Fixes: QTBUG-78440 Change-Id: Idcb6c075fdebaf67644f32a59d7aaf0d1c0bbe20 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/corelib/kernel/qcoreapplication.cpp | 24 ++++--- src/corelib/plugin/qfactoryloader.cpp | 12 +++- src/corelib/plugin/qlibrary_unix.cpp | 8 +++ src/corelib/plugin/qpluginloader.cpp | 10 +++ src/plugins/platforms/android/android.pro | 8 +-- .../platforms/android/androidjnimain.cpp | 2 - src/plugins/platforms/android/main.cpp | 63 +++++++++++++++++++ 7 files changed, 109 insertions(+), 18 deletions(-) create mode 100644 src/plugins/platforms/android/main.cpp diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index c537e8f51b..e25049f821 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -2708,18 +2708,22 @@ QStringList QCoreApplication::libraryPathsLocked() QStringList *app_libpaths = new QStringList; coreappdata()->app_libpaths.reset(app_libpaths); - QString libPathEnv = qEnvironmentVariable("QT_PLUGIN_PATH"); - if (!libPathEnv.isEmpty()) { - QStringList paths = libPathEnv.split(QDir::listSeparator(), QString::SkipEmptyParts); - for (QStringList::const_iterator it = paths.constBegin(); it != paths.constEnd(); ++it) { - QString canonicalPath = QDir(*it).canonicalPath(); - if (!canonicalPath.isEmpty() - && !app_libpaths->contains(canonicalPath)) { - app_libpaths->append(canonicalPath); + auto setPathsFromEnv = [&](QString libPathEnv) { + if (!libPathEnv.isEmpty()) { + QStringList paths = libPathEnv.split(QDir::listSeparator(), QString::SkipEmptyParts); + for (QStringList::const_iterator it = paths.constBegin(); it != paths.constEnd(); ++it) { + QString canonicalPath = QDir(*it).canonicalPath(); + if (!canonicalPath.isEmpty() + && !app_libpaths->contains(canonicalPath)) { + app_libpaths->append(canonicalPath); + } } } - } - + }; + setPathsFromEnv(qEnvironmentVariable("QT_PLUGIN_PATH")); +#ifdef Q_OS_ANDROID + setPathsFromEnv(qEnvironmentVariable("QT_BUNDLED_LIBS_PATH")); +#endif #ifdef Q_OS_DARWIN // Check the main bundle's PlugIns directory as this is a standard location for Apple OSes. // Note that the QLibraryInfo::PluginsPath below will coincidentally be the same as this value diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp index 6737aeccd2..79315ae50f 100644 --- a/src/corelib/plugin/qfactoryloader.cpp +++ b/src/corelib/plugin/qfactoryloader.cpp @@ -193,7 +193,11 @@ void QFactoryLoader::update() continue; d->loadedPaths << pluginDir; +#ifdef Q_OS_ANDROID + QString path = pluginDir; +#else QString path = pluginDir + d->suffix; +#endif if (qt_debug_component()) qDebug() << "QFactoryLoader::QFactoryLoader() checking directory path" << path << "..."; @@ -202,8 +206,10 @@ void QFactoryLoader::update() continue; QStringList plugins = QDir(path).entryList( -#ifdef Q_OS_WIN +#if defined(Q_OS_WIN) QStringList(QStringLiteral("*.dll")), +#elif defined(Q_OS_ANDROID) + QStringList(QLatin1String("plugins_%1_*.so").arg(d->suffix)), #endif QDir::Files); QLibraryPrivate *library = 0; @@ -339,6 +345,10 @@ QFactoryLoader::QFactoryLoader(const char *iid, #if QT_CONFIG(library) d->cs = cs; d->suffix = suffix; +# ifdef Q_OS_ANDROID + if (!d->suffix.isEmpty() && d->suffix.at(0) == QLatin1Char('/')) + d->suffix.remove(0, 1); +# endif QMutexLocker locker(qt_factoryloader_mutex()); update(); diff --git a/src/corelib/plugin/qlibrary_unix.cpp b/src/corelib/plugin/qlibrary_unix.cpp index 44d5513163..f0de1010d7 100644 --- a/src/corelib/plugin/qlibrary_unix.cpp +++ b/src/corelib/plugin/qlibrary_unix.cpp @@ -236,6 +236,14 @@ bool QLibraryPrivate::load_sys() auto attemptFromBundle = attempt; pHnd = dlopen(QFile::encodeName(attemptFromBundle.replace(QLatin1Char('/'), QLatin1Char('_'))), dlFlags); } + if (pHnd) { + using JniOnLoadPtr = jint (*)(JavaVM *vm, void *reserved); + JniOnLoadPtr jniOnLoad = reinterpret_cast(dlsym(pHnd, "JNI_OnLoad")); + if (jniOnLoad && jniOnLoad(QtAndroidPrivate::javaVM(), nullptr) == JNI_ERR) { + dlclose(pHnd); + pHnd = nullptr; + } + } #endif if (!pHnd && fileName.startsWith(QLatin1Char('/')) && QFile::exists(attempt)) { diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp index 4e0c3a511b..cadff4f32b 100644 --- a/src/corelib/plugin/qpluginloader.cpp +++ b/src/corelib/plugin/qpluginloader.cpp @@ -311,6 +311,16 @@ static QString locatePlugin(const QString& fileName) for (const QString &path : qAsConst(paths)) { for (const QString &prefix : qAsConst(prefixes)) { for (const QString &suffix : qAsConst(suffixes)) { +#ifdef Q_OS_ANDROID + { + QString pluginPath = basePath + prefix + baseName + suffix; + const QString fn = path + QLatin1String("/lib") + pluginPath.replace(QLatin1Char('/'), QLatin1Char('_')); + if (debug) + qDebug() << "Trying..." << fn; + if (QFileInfo(fn).isFile()) + return fn; + } +#endif const QString fn = path + QLatin1Char('/') + basePath + prefix + baseName + suffix; if (debug) qDebug() << "Trying..." << fn; diff --git a/src/plugins/platforms/android/android.pro b/src/plugins/platforms/android/android.pro index 346df84038..730247cd7f 100644 --- a/src/plugins/platforms/android/android.pro +++ b/src/plugins/platforms/android/android.pro @@ -1,9 +1,5 @@ TARGET = qtforandroid -# STATICPLUGIN needed because there's a Q_IMPORT_PLUGIN in androidjnimain.cpp -# Yes, the plugin imports itself statically -DEFINES += QT_STATICPLUGIN - LIBS += -ljnigraphics -landroid QT += \ @@ -19,7 +15,8 @@ INCLUDEPATH += \ $$PWD \ $$QT_SOURCE_TREE/src/3rdparty/android -SOURCES += $$PWD/androidplatformplugin.cpp \ +SOURCES += $$PWD/main.cpp \ + $$PWD/androidplatformplugin.cpp \ $$PWD/androidcontentfileengine.cpp \ $$PWD/androiddeadlockprotector.cpp \ $$PWD/androidjnimain.cpp \ @@ -92,4 +89,5 @@ qtConfig(vulkan) { } PLUGIN_TYPE = platforms +PLUGIN_CLASS_NAME = QAndroidIntegrationPlugin load(qt_plugin) diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index 915f7f0f5b..27eb337aaa 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -68,8 +68,6 @@ #include -Q_IMPORT_PLUGIN(QAndroidPlatformIntegrationPlugin) - QT_BEGIN_NAMESPACE static JavaVM *m_javaVM = nullptr; diff --git a/src/plugins/platforms/android/main.cpp b/src/plugins/platforms/android/main.cpp new file mode 100644 index 0000000000..c304fc8d69 --- /dev/null +++ b/src/plugins/platforms/android/main.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2019 BogDan Vatra +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include +#include "qandroidplatformintegration.h" + +QT_BEGIN_NAMESPACE + +class QAndroidIntegrationPlugin : public QPlatformIntegrationPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "android.json") + +public: + QPlatformIntegration *create(const QString& system, const QStringList& paramList) override; +}; + +QPlatformIntegration *QAndroidIntegrationPlugin::create(const QString& system, const QStringList& paramList) +{ + if (!system.compare(QLatin1String("android"), Qt::CaseInsensitive)) + return new QAndroidPlatformIntegration(paramList); + + return nullptr; +} + +QT_END_NAMESPACE From bc35941dbbf6cbd09805a2217ecb062c565855ad Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 20 Sep 2019 13:13:17 +0200 Subject: [PATCH 07/22] Add QQuickMultiPointTouchArea as a friend of QTouchEvent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QQuickMultiPointTouchArea needs to understand whether a stationary touchpoint has relevant property changes, to decide whether to emit its updated() signal. Amends 217dd1b3b03cd40b4bb926631464c684f7f84a69 Task-number: QTBUG-77142 Change-Id: I85e031820bef9d687369b7d67a57c67fe2875b4b Reviewed-by: Tor Arne Vestbø --- src/gui/kernel/qevent.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index bf00d4a9a3..dc33a83ac0 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -960,6 +960,7 @@ public: friend class QApplication; friend class QApplicationPrivate; friend class QQuickPointerTouchEvent; + friend class QQuickMultiPointTouchArea; }; #if QT_DEPRECATED_SINCE(5, 0) From d0d18b06458edd3b6b0712ea71c787404bbaa7e1 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 4 Dec 2018 15:05:04 +0100 Subject: [PATCH 08/22] Handle transparent pen color in fast text path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Switches the text blending to be SourceOver as that is much more common than Source, and means we can now handle semi-transparent text colors there. Task-number: QTBUG-72165 Change-Id: I7b3aedb22412e6fb6f60197596b37f26c6008784 Reviewed-by: Tor Arne Vestbø --- src/gui/painting/qdrawhelper.cpp | 195 ++++++++++++----------- src/gui/painting/qdrawhelper_p.h | 2 + src/gui/painting/qpaintengine_raster.cpp | 4 +- src/gui/painting/qrgba64_p.h | 2 + 4 files changed, 105 insertions(+), 98 deletions(-) diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index edb363ac69..3d06a27d8e 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -5658,44 +5658,60 @@ static inline void alphamapblend_argb32(quint32 *dst, int coverage, QRgba64 srcL { if (coverage == 0) { // nothing - } else if (coverage == 255) { - *dst = src; - } else if (!colorProfile) { - *dst = INTERPOLATE_PIXEL_255(src, coverage, *dst, 255 - coverage); + } else if (coverage == 255 || !colorProfile) { + blend_pixel(*dst, src, coverage); + } else if (*dst < 0xff000000) { + // Give up and do a naive gray alphablend. Needed to deal with ARGB32 and invalid ARGB32_premultiplied, see QTBUG-60571 + blend_pixel(*dst, src, coverage); + } else if (src >= 0xff000000) { + grayBlendPixel(dst, coverage, srcLinear, colorProfile); } else { - if (*dst >= 0xff000000) { - grayBlendPixel(dst, coverage, srcLinear, colorProfile); - } else { - // Give up and do a naive gray alphablend. Needed to deal with ARGB32 and invalid ARGB32_premultiplied, see QTBUG-60571 - *dst = INTERPOLATE_PIXEL_255(src, coverage, *dst, 255 - coverage); - } + // First do naive blend with text-color + QRgb s = *dst; + blend_pixel(s, src); + // Then gamma-corrected blend with glyph shape + grayBlendPixel(dst, coverage, colorProfile->toLinear64(s), colorProfile); } } #if QT_CONFIG(raster_64bit) + +static inline void grayBlendPixel(QRgba64 &dst, int coverage, QRgba64 srcLinear, const QColorTrcLut *colorProfile) +{ + // Do a gammacorrected gray alphablend... + QRgba64 dstColor = dst; + if (colorProfile) { + if (dstColor.isOpaque()) + dstColor = colorProfile->toLinear(dstColor); + else if (!dstColor.isTransparent()) + dstColor = colorProfile->toLinear(dstColor.unpremultiplied()).premultiplied(); + } + + blend_pixel(dstColor, srcLinear, coverage); + + if (colorProfile) { + if (dstColor.isOpaque()) + dstColor = colorProfile->fromLinear(dstColor); + else if (!dstColor.isTransparent()) + dstColor = colorProfile->fromLinear(dstColor.unpremultiplied()).premultiplied(); + } + dst = dstColor; +} + static inline void alphamapblend_generic(int coverage, QRgba64 *dest, int x, const QRgba64 &srcLinear, const QRgba64 &src, const QColorTrcLut *colorProfile) { if (coverage == 0) { // nothing } else if (coverage == 255) { - dest[x] = src; + blend_pixel(dest[x], src); + } else if (src.isOpaque()) { + grayBlendPixel(dest[x], coverage, srcLinear, colorProfile); } else { - QRgba64 dstColor = dest[x]; - if (colorProfile) { - if (dstColor.isOpaque()) - dstColor = colorProfile->toLinear(dstColor); - else if (!dstColor.isTransparent()) - dstColor = colorProfile->toLinear(dstColor.unpremultiplied()).premultiplied(); - } - - dstColor = interpolate255(srcLinear, coverage, dstColor, 255 - coverage); - if (colorProfile) { - if (dstColor.isOpaque()) - dstColor = colorProfile->fromLinear(dstColor); - else if (!dstColor.isTransparent()) - dstColor = colorProfile->fromLinear(dstColor.unpremultiplied()).premultiplied(); - } - dest[x] = dstColor; + // First do naive blend with text-color + QRgba64 s = dest[x]; + blend_pixel(s, src); + // Then gamma-corrected blend with glyph shape + grayBlendPixel(dest[x], coverage, colorProfile->toLinear(s), colorProfile); } } @@ -5714,12 +5730,8 @@ static void qt_alphamapblit_generic(QRasterBuffer *rasterBuffer, colorProfile = QGuiApplicationPrivate::instance()->colorProfileForA8Text(); QRgba64 srcColor = color; - if (colorProfile) { - if (color.isOpaque()) - srcColor = colorProfile->toLinear(srcColor); - else - srcColor = colorProfile->toLinear(srcColor.unpremultiplied()).premultiplied(); - } + if (colorProfile && color.isOpaque()) + srcColor = colorProfile->toLinear(srcColor); alignas(8) QRgba64 buffer[BufferSize]; const DestFetchProc64 destFetch64 = destFetchProc64[rasterBuffer->format]; @@ -5792,12 +5804,8 @@ static void qt_alphamapblit_generic(QRasterBuffer *rasterBuffer, colorProfile = QGuiApplicationPrivate::instance()->colorProfileForA8Text(); QRgba64 srcColor = color; - if (colorProfile) { - if (color.isOpaque()) - srcColor = colorProfile->toLinear(srcColor); - else - srcColor = colorProfile->toLinear(srcColor.unpremultiplied()).premultiplied(); - } + if (colorProfile && color.isOpaque()) + srcColor = colorProfile->toLinear(srcColor); quint32 buffer[BufferSize]; const DestFetchProc destFetch = destFetchProc[rasterBuffer->format]; @@ -5872,7 +5880,7 @@ void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer, int mapWidth, int mapHeight, int mapStride, const QClipData *clip, bool useGammaCorrection) { - if (useGammaCorrection) { + if (useGammaCorrection || !color.isOpaque()) { qt_alphamapblit_generic(rasterBuffer, x, y, color, map, mapWidth, mapHeight, mapStride, clip, useGammaCorrection); return; } @@ -5931,12 +5939,8 @@ static void qt_alphamapblit_argb32(QRasterBuffer *rasterBuffer, colorProfile = QGuiApplicationPrivate::instance()->colorProfileForA8Text(); QRgba64 srcColor = color; - if (colorProfile) { - if (color.isOpaque()) - srcColor = colorProfile->toLinear(srcColor); - else - srcColor = colorProfile->toLinear(srcColor.unpremultiplied()).premultiplied(); - } + if (colorProfile && color.isOpaque()) + srcColor = colorProfile->toLinear(srcColor); if (!clip) { quint32 *dest = reinterpret_cast(rasterBuffer->scanLine(y)) + x; @@ -6031,48 +6035,59 @@ static inline QRgb rgbBlend(QRgb d, QRgb s, uint rgbAlpha) #endif } +static inline void alphargbblend_argb32(quint32 *dst, uint coverage, const QRgba64 &srcLinear, quint32 src, const QColorTrcLut *colorProfile) +{ + if (coverage == 0xff000000) { + // nothing + } else if (coverage == 0xffffffff && qAlpha(src) == 255) { + blend_pixel(*dst, src); + } else if (!colorProfile) { + *dst = rgbBlend(*dst, src, coverage); + } else if (*dst < 0xff000000) { + // Give up and do a naive gray alphablend. Needed to deal with ARGB32 and invalid ARGB32_premultiplied, see QTBUG-60571 + blend_pixel(*dst, src, qRgbAvg(coverage)); + } else if (srcLinear.isOpaque()) { + rgbBlendPixel(dst, coverage, srcLinear, colorProfile); + } else { + // First do naive blend with text-color + QRgb s = *dst; + blend_pixel(s, src); + // Then gamma-corrected blend with glyph shape + rgbBlendPixel(dst, coverage, colorProfile->toLinear64(s), colorProfile); + } +} + #if QT_CONFIG(raster_64bit) +static inline void rgbBlendPixel(QRgba64 &dst, int coverage, QRgba64 slinear, const QColorTrcLut *colorProfile) +{ + // Do a gammacorrected RGB alphablend... + const QRgba64 dlinear = colorProfile ? colorProfile->toLinear64(dst) : dst; + + QRgba64 blend = rgbBlend(dlinear, slinear, coverage); + + dst = colorProfile ? colorProfile->fromLinear(blend) : blend; +} + static inline void alphargbblend_generic(uint coverage, QRgba64 *dest, int x, const QRgba64 &srcLinear, const QRgba64 &src, const QColorTrcLut *colorProfile) { if (coverage == 0xff000000) { // nothing } else if (coverage == 0xffffffff) { - dest[x] = src; + blend_pixel(dest[x], src); + } else if (!dest[x].isOpaque()) { + // Do a gray alphablend. + alphamapblend_generic(qRgbAvg(coverage), dest, x, srcLinear, src, colorProfile); + } else if (src.isOpaque()) { + rgbBlendPixel(dest[x], coverage, srcLinear, colorProfile); } else { - QRgba64 dstColor = dest[x]; - if (dstColor.isOpaque()) { - if (colorProfile) - dstColor = colorProfile->toLinear(dstColor); - dstColor = rgbBlend(dstColor, srcLinear, coverage); - if (colorProfile) - dstColor = colorProfile->fromLinear(dstColor); - dest[x] = dstColor; - } else { - // Do a gray alphablend. - alphamapblend_generic(qRgbAvg(coverage), dest, x, srcLinear, src, colorProfile); - } - } -} -#endif - -static inline void alphargbblend_argb32(quint32 *dst, uint coverage, const QRgba64 &srcLinear, quint32 src, const QColorTrcLut *colorProfile) -{ - if (coverage == 0xff000000) { - // nothing - } else if (coverage == 0xffffffff) { - *dst = src; - } else if (*dst < 0xff000000) { - // Give up and do a naive gray alphablend. Needed to deal with ARGB32 and invalid ARGB32_premultiplied, see QTBUG-60571 - const int a = qRgbAvg(coverage); - *dst = INTERPOLATE_PIXEL_255(src, a, *dst, 255 - a); - } else if (!colorProfile) { - *dst = rgbBlend(*dst, src, coverage); - } else { - rgbBlendPixel(dst, coverage, srcLinear, colorProfile); + // First do naive blend with text-color + QRgba64 s = dest[x]; + blend_pixel(s, src); + // Then gamma-corrected blend with glyph shape + rgbBlendPixel(dest[x], coverage, colorProfile->toLinear(s), colorProfile); } } -#if QT_CONFIG(raster_64bit) static void qt_alphargbblit_generic(QRasterBuffer *rasterBuffer, int x, int y, const QRgba64 &color, const uint *src, int mapWidth, int mapHeight, int srcStride, @@ -6087,12 +6102,8 @@ static void qt_alphargbblit_generic(QRasterBuffer *rasterBuffer, colorProfile = QGuiApplicationPrivate::instance()->colorProfileForA32Text(); QRgba64 srcColor = color; - if (colorProfile) { - if (color.isOpaque()) - srcColor = colorProfile->toLinear(srcColor); - else - srcColor = colorProfile->toLinear(srcColor.unpremultiplied()).premultiplied(); - } + if (colorProfile && color.isOpaque()) + srcColor = colorProfile->toLinear(srcColor); alignas(8) QRgba64 buffer[BufferSize]; const DestFetchProc64 destFetch64 = destFetchProc64[rasterBuffer->format]; @@ -6164,12 +6175,8 @@ static void qt_alphargbblit_generic(QRasterBuffer *rasterBuffer, colorProfile = QGuiApplicationPrivate::instance()->colorProfileForA32Text(); QRgba64 srcColor = color; - if (colorProfile) { - if (color.isOpaque()) - srcColor = colorProfile->toLinear(srcColor); - else - srcColor = colorProfile->toLinear(srcColor.unpremultiplied()).premultiplied(); - } + if (colorProfile && color.isOpaque()) + srcColor = colorProfile->toLinear(srcColor); quint32 buffer[BufferSize]; const DestFetchProc destFetch = destFetchProc[rasterBuffer->format]; @@ -6242,12 +6249,8 @@ static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer, colorProfile = QGuiApplicationPrivate::instance()->colorProfileForA32Text(); QRgba64 srcColor = color; - if (colorProfile) { - if (color.isOpaque()) - srcColor = colorProfile->toLinear(srcColor); - else - srcColor = colorProfile->toLinear(srcColor.unpremultiplied()).premultiplied(); - } + if (colorProfile && color.isOpaque()) + srcColor = colorProfile->toLinear(srcColor); if (!clip) { quint32 *dst = reinterpret_cast(rasterBuffer->scanLine(y)) + x; diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h index 9c5d525722..dd42b96d79 100644 --- a/src/gui/painting/qdrawhelper_p.h +++ b/src/gui/painting/qdrawhelper_p.h @@ -671,6 +671,8 @@ static Q_ALWAYS_INLINE void blend_pixel(quint32 &dst, const quint32 src) static Q_ALWAYS_INLINE void blend_pixel(quint32 &dst, const quint32 src, const int const_alpha) { + if (const_alpha == 255) + return blend_pixel(dst, src); if (src != 0) { const quint32 s = BYTE_MUL(src, const_alpha); dst = s + BYTE_MUL(dst, qAlpha(~s)); diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 9894da8fe1..447ecb358a 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -842,8 +842,8 @@ void QRasterPaintEngine::updateRasterState() const QPainter::CompositionMode mode = s->composition_mode; s->flags.fast_text = (s->penData.type == QSpanData::Solid) && s->intOpacity == 256 - && (mode == QPainter::CompositionMode_Source - || (mode == QPainter::CompositionMode_SourceOver + && (mode == QPainter::CompositionMode_SourceOver + || (mode == QPainter::CompositionMode_Source && s->penData.solidColor.isOpaque())); } diff --git a/src/gui/painting/qrgba64_p.h b/src/gui/painting/qrgba64_p.h index ca879de27c..d145dbfbea 100644 --- a/src/gui/painting/qrgba64_p.h +++ b/src/gui/painting/qrgba64_p.h @@ -284,6 +284,8 @@ static Q_ALWAYS_INLINE void blend_pixel(QRgba64 &dst, QRgba64 src) static Q_ALWAYS_INLINE void blend_pixel(QRgba64 &dst, QRgba64 src, const int const_alpha) { + if (const_alpha == 255) + return blend_pixel(dst, src); if (!src.isTransparent()) { src = multiplyAlpha255(src, const_alpha); dst = src + multiplyAlpha65535(dst, 65535 - src.alpha()); From 60e20abf19f58c34cb3a878636d955993b81cf2e Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 17 Sep 2019 12:31:50 +0200 Subject: [PATCH 09/22] Add a RPi4 device spec [ChangeLog][Platform Specific Changes][Linux] Added a device spec for Raspberry Pi 4 (32-bit, V3D) Change-Id: Idea889842a89dcc74705f1bb9559953dadc07251 Reviewed-by: Eirik Aavitsland Reviewed-by: Andy Nichols --- .../devices/linux-rasp-pi4-v3d-g++/qmake.conf | 40 +++++++++++++++++++ .../linux-rasp-pi4-v3d-g++/qplatformdefs.h | 40 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 mkspecs/devices/linux-rasp-pi4-v3d-g++/qmake.conf create mode 100644 mkspecs/devices/linux-rasp-pi4-v3d-g++/qplatformdefs.h diff --git a/mkspecs/devices/linux-rasp-pi4-v3d-g++/qmake.conf b/mkspecs/devices/linux-rasp-pi4-v3d-g++/qmake.conf new file mode 100644 index 0000000000..69b0c761a8 --- /dev/null +++ b/mkspecs/devices/linux-rasp-pi4-v3d-g++/qmake.conf @@ -0,0 +1,40 @@ +# qmake configuration for the Raspberry Pi 4 (32-bit) using the Mesa V3D +# graphics stack. (not the Broadcom stack) +# +# This supports accelerated OpenGL both for X11 and DRM/KMS. Perhaps +# Wayland too. +# +# Tested with a sysroot created from Raspbian Buster and a gcc 7.4 +# toolchain from Linaro. +# +# Example configure command line, assuming installation to +# /usr/local/qt5pi on device and ~/rpi/qt5 on the host: +# +# ./configure -release -opengl es2 -device linux-rasp-pi4-v3d-g++ -device-option CROSS_COMPILE=~/rpi/gcc-linaro-7.4.1-2019.02-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf- \ +# -sysroot ~/rpi/sysroot -opensource -confirm-license -make libs -prefix /usr/local/qt5pi -extprefix ~/rpi/qt5 -v +# +# Check the configure output carefully. EGLFS, EGLFS GBM, and EGL on X11 +# should all be 'yes'. Otherwise something is wrong. +# +# If getting linker errors like "undefined reference to `_dl_stack_flags'" check the +# symlinks in the sysroot, they were probably not adjusted +# correctly. F.ex. sysroot/usr/lib/arm-linux-gnueabihf/libpthread.so must point to +# sysroot/lib/arm-linux-gnueabihf/libpthread.so.0. If it is a broken link instead, bad +# things will happen. + +include(../common/linux_device_pre.conf) + +QMAKE_LIBS_EGL += -lEGL +QMAKE_LIBS_OPENGL_ES2 += -lGLESv2 -lEGL + +QMAKE_CFLAGS = -march=armv8-a -mtune=cortex-a72 -mfpu=crypto-neon-fp-armv8 +QMAKE_CXXFLAGS = $$QMAKE_CFLAGS + +DISTRO_OPTS += hard-float +DISTRO_OPTS += deb-multi-arch + +EGLFS_DEVICE_INTEGRATION = eglfs_kms + +include(../common/linux_arm_device_post.conf) + +load(qt_config) diff --git a/mkspecs/devices/linux-rasp-pi4-v3d-g++/qplatformdefs.h b/mkspecs/devices/linux-rasp-pi4-v3d-g++/qplatformdefs.h new file mode 100644 index 0000000000..4435fb2557 --- /dev/null +++ b/mkspecs/devices/linux-rasp-pi4-v3d-g++/qplatformdefs.h @@ -0,0 +1,40 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the qmake spec of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "../../linux-g++/qplatformdefs.h" From 963941faae561aeadd3b3e97726d1b57e8bccf90 Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Sun, 8 Sep 2019 20:06:46 +0200 Subject: [PATCH 10/22] tst_QListView: cleanup Cleanup QListView autotest: - use range-based for loops - use nullptr - use member initialization - use new signal/slot syntax - use static invocations - use override - replaced QCoreApplication::processEvents with QTRY_VERIFY/QTRY_COMPARE Change-Id: I38de7fb105cd70259e60e6b05de82944bee53a54 Reviewed-by: Friedemann Kleint --- .../itemviews/qlistview/tst_qlistview.cpp | 782 ++++++++---------- 1 file changed, 326 insertions(+), 456 deletions(-) diff --git a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp index 3a60b3b7c6..e02986b712 100644 --- a/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp +++ b/tests/auto/widgets/itemviews/qlistview/tst_qlistview.cpp @@ -27,32 +27,27 @@ ****************************************************************************/ -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include using namespace QTestPrivate; #if defined(Q_OS_WIN) # include -# include +# include +# include +# include #include #endif // Q_OS_WIN @@ -67,6 +62,7 @@ static inline HWND getHWNDForWidget(const QWidget *widget) Q_DECLARE_METATYPE(QAbstractItemView::ScrollMode) Q_DECLARE_METATYPE(QMargins) Q_DECLARE_METATYPE(QSize) +using IntList = QVector; static QStringList generateList(const QString &prefix, int size) { @@ -77,6 +73,26 @@ static QStringList generateList(const QString &prefix, int size) return result; } +class PublicListView : public QListView +{ +public: + using QListView::QListView; + using QListView::contentsSize; + using QListView::moveCursor; + using QListView::selectedIndexes; + using QListView::setPositionForIndex; + using QListView::setSelection; + using QListView::setViewportMargins; + using QListView::startDrag; + using QListView::viewOptions; + QRegion getVisualRegionForSelection() const + { + return QListView::visualRegionForSelection(selectionModel()->selection()); + } + + friend class tst_QListView; +}; + class tst_QListView : public QObject { Q_OBJECT @@ -160,57 +176,57 @@ void tst_QListView::getSetCheck() QListView obj1; // Movement QListView::movement() // void QListView::setMovement(Movement) - obj1.setMovement(QListView::Movement(QListView::Static)); - QCOMPARE(QListView::Movement(QListView::Static), obj1.movement()); - obj1.setMovement(QListView::Movement(QListView::Free)); - QCOMPARE(QListView::Movement(QListView::Free), obj1.movement()); - obj1.setMovement(QListView::Movement(QListView::Snap)); - QCOMPARE(QListView::Movement(QListView::Snap), obj1.movement()); + obj1.setMovement(QListView::Static); + QCOMPARE(QListView::Static, obj1.movement()); + obj1.setMovement(QListView::Free); + QCOMPARE(QListView::Free, obj1.movement()); + obj1.setMovement(QListView::Snap); + QCOMPARE(QListView::Snap, obj1.movement()); // Flow QListView::flow() // void QListView::setFlow(Flow) - obj1.setFlow(QListView::Flow(QListView::LeftToRight)); - QCOMPARE(QListView::Flow(QListView::LeftToRight), obj1.flow()); - obj1.setFlow(QListView::Flow(QListView::TopToBottom)); - QCOMPARE(QListView::Flow(QListView::TopToBottom), obj1.flow()); + obj1.setFlow(QListView::LeftToRight); + QCOMPARE(QListView::LeftToRight, obj1.flow()); + obj1.setFlow(QListView::TopToBottom); + QCOMPARE(QListView::TopToBottom, obj1.flow()); // ResizeMode QListView::resizeMode() // void QListView::setResizeMode(ResizeMode) - obj1.setResizeMode(QListView::ResizeMode(QListView::Fixed)); - QCOMPARE(QListView::ResizeMode(QListView::Fixed), obj1.resizeMode()); - obj1.setResizeMode(QListView::ResizeMode(QListView::Adjust)); - QCOMPARE(QListView::ResizeMode(QListView::Adjust), obj1.resizeMode()); + obj1.setResizeMode(QListView::Fixed); + QCOMPARE(QListView::Fixed, obj1.resizeMode()); + obj1.setResizeMode(QListView::Adjust); + QCOMPARE(QListView::Adjust, obj1.resizeMode()); // LayoutMode QListView::layoutMode() // void QListView::setLayoutMode(LayoutMode) - obj1.setLayoutMode(QListView::LayoutMode(QListView::SinglePass)); - QCOMPARE(QListView::LayoutMode(QListView::SinglePass), obj1.layoutMode()); - obj1.setLayoutMode(QListView::LayoutMode(QListView::Batched)); - QCOMPARE(QListView::LayoutMode(QListView::Batched), obj1.layoutMode()); + obj1.setLayoutMode(QListView::SinglePass); + QCOMPARE(QListView::SinglePass, obj1.layoutMode()); + obj1.setLayoutMode(QListView::Batched); + QCOMPARE(QListView::Batched, obj1.layoutMode()); // int QListView::spacing() // void QListView::setSpacing(int) obj1.setSpacing(0); QCOMPARE(0, obj1.spacing()); - obj1.setSpacing(INT_MIN); - QCOMPARE(INT_MIN, obj1.spacing()); - obj1.setSpacing(INT_MAX); - QCOMPARE(INT_MAX, obj1.spacing()); + obj1.setSpacing(std::numeric_limits::min()); + QCOMPARE(std::numeric_limits::min(), obj1.spacing()); + obj1.setSpacing(std::numeric_limits::max()); + QCOMPARE(std::numeric_limits::max(), obj1.spacing()); // ViewMode QListView::viewMode() // void QListView::setViewMode(ViewMode) - obj1.setViewMode(QListView::ViewMode(QListView::ListMode)); - QCOMPARE(QListView::ViewMode(QListView::ListMode), obj1.viewMode()); - obj1.setViewMode(QListView::ViewMode(QListView::IconMode)); - QCOMPARE(QListView::ViewMode(QListView::IconMode), obj1.viewMode()); + obj1.setViewMode(QListView::ListMode); + QCOMPARE(QListView::ListMode, obj1.viewMode()); + obj1.setViewMode(QListView::IconMode); + QCOMPARE(QListView::IconMode, obj1.viewMode()); // int QListView::modelColumn() // void QListView::setModelColumn(int) obj1.setModelColumn(0); QCOMPARE(0, obj1.modelColumn()); - obj1.setModelColumn(INT_MIN); + obj1.setModelColumn(std::numeric_limits::min()); QCOMPARE(0, obj1.modelColumn()); // Less than 0 => 0 - obj1.setModelColumn(INT_MAX); + obj1.setModelColumn(std::numeric_limits::max()); QCOMPARE(0, obj1.modelColumn()); // No model => 0 // bool QListView::uniformItemSizes() @@ -234,23 +250,21 @@ void tst_QListView::getSetCheck() class QtTestModel: public QAbstractListModel { + Q_OBJECT public: - QtTestModel(QObject *parent = 0): QAbstractListModel(parent), - colCount(0), rCount(0), wrongIndex(false) {} - int rowCount(const QModelIndex&) const { return rCount; } - int columnCount(const QModelIndex&) const { return colCount; } - bool isEditable(const QModelIndex &) const { return true; } + QtTestModel(int rc, int cc, QObject *parent = nullptr) + : QAbstractListModel(parent), rCount(rc), cCount(cc) {} + int rowCount(const QModelIndex &) const override { return rCount; } + int columnCount(const QModelIndex &) const override { return cCount; } - QVariant data(const QModelIndex &idx, int role) const + QVariant data(const QModelIndex &idx, int role) const override { - - if (!m_icon.isNull() && role == Qt::DecorationRole) { + if (!m_icon.isNull() && role == Qt::DecorationRole) return m_icon; - } if (role != Qt::DisplayRole) return QVariant(); - if (idx.row() < 0 || idx.column() < 0 || idx.column() >= colCount + if (idx.row() < 0 || idx.column() < 0 || idx.column() >= cCount || idx.row() >= rCount) { wrongIndex = true; qWarning("got invalid modelIndex %d/%d", idx.row(), idx.column()); @@ -277,13 +291,14 @@ public: m_icon = icon; } - int colCount, rCount; QIcon m_icon; - mutable bool wrongIndex; + int rCount, cCount; + mutable bool wrongIndex = false; }; class ScrollPerItemListView : public QListView { + Q_OBJECT public: explicit ScrollPerItemListView(QWidget *parent = nullptr) : QListView(parent) @@ -301,12 +316,12 @@ void tst_QListView::cleanup() void tst_QListView::noDelegate() { - QtTestModel model(0); - model.rCount = model.colCount = 10; + QtTestModel model(10, 10); QListView view; view.setModel(&model); - view.setItemDelegate(0); + view.setItemDelegate(nullptr); view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); } void tst_QListView::noModel() @@ -314,11 +329,13 @@ void tst_QListView::noModel() QListView view; view.show(); view.setRowHidden(0, true); + // no model -> not able to hide a row + QVERIFY(!view.isRowHidden(0)); } void tst_QListView::emptyModel() { - QtTestModel model(0); + QtTestModel model(0, 0); QListView view; view.setModel(&model); view.show(); @@ -327,9 +344,7 @@ void tst_QListView::emptyModel() void tst_QListView::removeRows() { - QtTestModel model(0); - model.rCount = model.colCount = 10; - + QtTestModel model(10, 10); QListView view; view.setModel(&model); view.show(); @@ -358,8 +373,7 @@ void tst_QListView::cursorMove() QModelIndex index = model.index(i, j); model.setData(index, QLatin1Char('[') + QString::number(i) + postfix); view.setCurrentIndex(index); - QApplication::processEvents(); - QCOMPARE(view.currentIndex(), index); + QTRY_COMPARE(view.currentIndex(), index); } } @@ -375,11 +389,12 @@ void tst_QListView::cursorMove() view.doItemsLayout(); topLevel.show(); - QVector keymoves; - keymoves << Qt::Key_Up << Qt::Key_Up << Qt::Key_Right << Qt::Key_Right << Qt::Key_Up - << Qt::Key_Left << Qt::Key_Left << Qt::Key_Up << Qt::Key_Down << Qt::Key_Up - << Qt::Key_Up << Qt::Key_Up << Qt::Key_Up << Qt::Key_Up << Qt::Key_Up - << Qt::Key_Left << Qt::Key_Left << Qt::Key_Up << Qt::Key_Down; + static const Qt::Key keymoves[] { + Qt::Key_Up, Qt::Key_Up, Qt::Key_Right, Qt::Key_Right, Qt::Key_Up, + Qt::Key_Left, Qt::Key_Left, Qt::Key_Up, Qt::Key_Down, Qt::Key_Up, + Qt::Key_Up, Qt::Key_Up, Qt::Key_Up, Qt::Key_Up, Qt::Key_Up, + Qt::Key_Left, Qt::Key_Left, Qt::Key_Up, Qt::Key_Down + }; int lastRow = rows / displayColumns - 1; int lastColumn = displayColumns - 1; @@ -387,9 +402,8 @@ void tst_QListView::cursorMove() int displayRow = lastRow; int displayColumn = lastColumn - (rows % displayColumns); - QApplication::instance()->processEvents(); - for (int i = 0; i < keymoves.size(); ++i) { - Qt::Key key = keymoves.at(i); + QCoreApplication::processEvents(); + for (Qt::Key key : keymoves) { QTest::keyClick(&view, key); switch (key) { case Qt::Key_Up: @@ -422,7 +436,7 @@ void tst_QListView::cursorMove() QVERIFY(false); } - QApplication::instance()->processEvents(); + QCoreApplication::processEvents(); int row = displayRow * displayColumns + displayColumn; int column = columns - 1; @@ -435,9 +449,7 @@ void tst_QListView::cursorMove() void tst_QListView::hideRows() { - QtTestModel model(0); - model.rCount = model.colCount = 10; - + QtTestModel model(10, 10); QListView view; view.setModel(&model); view.show(); @@ -471,9 +483,9 @@ void tst_QListView::hideRows() view.setRowHidden(0, false); QVERIFY(!view.isRowHidden(0)); - QStandardItemModel sim(0); + QStandardItemModel sim; QStandardItem *root = new QStandardItem("Root row"); - for (int i=0;i<5;i++) + for (int i = 0;i < 5; i++) root->appendRow(new QStandardItem(QLatin1String("Row ") + QString::number(i))); sim.appendRow(root); view.setModel(&sim); @@ -488,15 +500,13 @@ void tst_QListView::hideRows() void tst_QListView::moveCursor() { - QtTestModel model(0); - model.rCount = model.colCount = 10; - + QtTestModel model(10, 10); QListView view; view.setModel(&model); QTest::keyClick(&view, Qt::Key_Down); - view.setModel(0); + view.setModel(nullptr); view.setModel(&model); view.setRowHidden(0, true); @@ -504,32 +514,14 @@ void tst_QListView::moveCursor() QCOMPARE(view.selectionModel()->currentIndex(), model.index(1, 0)); } -class QMoveCursorListView : public QListView -{ -public: - QMoveCursorListView() : QListView() {} - - // enum CursorAction and moveCursor() are protected in QListView. - enum CursorAction { MoveUp, MoveDown, MoveLeft, MoveRight, - MoveHome, MoveEnd, MovePageUp, MovePageDown, - MoveNext, MovePrevious }; - - QModelIndex doMoveCursor(QMoveCursorListView::CursorAction action, Qt::KeyboardModifiers modifiers) - { - return QListView::moveCursor((QListView::CursorAction)action, modifiers); - } -}; - void tst_QListView::moveCursor2() { - QtTestModel model(0); - model.colCount = 1; - model.rCount = 100; + QtTestModel model(100, 1); QPixmap pm(32, 32); pm.fill(Qt::green); model.setDataIcon(QIcon(pm)); - QMoveCursorListView vu; + PublicListView vu; vu.setModel(&model); vu.setIconSize(QSize(36,48)); vu.setGridSize(QSize(34,56)); @@ -545,10 +537,10 @@ void tst_QListView::moveCursor2() vu.selectionModel()->setCurrentIndex(model.index(0,0), QItemSelectionModel::SelectCurrent); QCoreApplication::processEvents(); - QModelIndex idx = vu.doMoveCursor(QMoveCursorListView::MoveHome, Qt::NoModifier); - QCOMPARE(idx, model.index(0,0)); - idx = vu.doMoveCursor(QMoveCursorListView::MoveDown, Qt::NoModifier); - QCOMPARE(idx, model.index(8,0)); + QModelIndex idx = vu.moveCursor(PublicListView::MoveHome, Qt::NoModifier); + QCOMPARE(idx, model.index(0, 0)); + idx = vu.moveCursor(PublicListView::MoveDown, Qt::NoModifier); + QCOMPARE(idx, model.index(8, 0)); } void tst_QListView::moveCursor3() @@ -582,11 +574,12 @@ void tst_QListView::moveCursor3() class QListViewShowEventListener : public QListView { + Q_OBJECT public: - QListViewShowEventListener() : QListView() { m_shown = false;} - - virtual void showEvent(QShowEvent * /*e*/) + using QListView::QListView; + void showEvent(QShowEvent *e) override { + QListView::showEvent(e); int columnwidth = sizeHintForColumn(0); QSize sz = sizeHintForIndex(model()->index(0,0)); @@ -596,16 +589,13 @@ public: } QModelIndex m_index; - bool m_shown; + bool m_shown = false; }; void tst_QListView::indexAt() { - QtTestModel model(0); - model.rCount = 2; - model.colCount = 1; - + QtTestModel model(2, 1); QListView view; view.setModel(&model); view.setViewMode(QListView::ListMode); @@ -637,7 +627,7 @@ void tst_QListView::indexAt() model.rCount = 30; QListViewShowEventListener view2; // Set the height to a small enough value so that it wraps to a new section. - view2.resize(300,100); + view2.resize(300, 100); view2.setModel(&model); view2.setFlow(QListView::TopToBottom); view2.setViewMode(QListView::ListMode); @@ -653,15 +643,11 @@ void tst_QListView::indexAt() void tst_QListView::clicked() { - QtTestModel model; - model.rCount = 10; - model.colCount = 2; - + QtTestModel model(10, 2); QListView view; view.setModel(&model); - view.show(); - QApplication::processEvents(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); QModelIndex firstIndex = model.index(0, 0, QModelIndex()); QVERIFY(firstIndex.isValid()); @@ -673,7 +659,7 @@ void tst_QListView::clicked() QModelIndex index = view.indexAt(p); if (!index.isValid()) continue; - QSignalSpy spy(&view, SIGNAL(clicked(QModelIndex))); + QSignalSpy spy(&view, &QListView::clicked); QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, p); QCOMPARE(spy.count(), 1); } @@ -681,10 +667,7 @@ void tst_QListView::clicked() void tst_QListView::singleSelectionRemoveRow() { - QStringList items; - items << "item1" << "item2" << "item3" << "item4"; - QStringListModel model(items); - + QStringListModel model({"item1", "item2", "item3", "item4"}); QListView view; view.setModel(&model); view.show(); @@ -764,7 +747,7 @@ void tst_QListView::modelColumn() // Out of bound cases should not modify the modelColumn view.setModelColumn(-1); QCOMPARE(view.modelColumn(), 2); - view.setModelColumn(INT_MAX); + view.setModelColumn(std::numeric_limits::max()); QCOMPARE(view.modelColumn(), 2); @@ -788,15 +771,12 @@ void tst_QListView::modelColumn() void tst_QListView::hideFirstRow() { - QStringList items; - for (int i=0; i <100; ++i) - items << "item"; - QStringListModel model(items); + QStringListModel model(generateList(QLatin1String("item"), 100)); QListView view; view.setModel(&model); view.setUniformItemSizes(true); - view.setRowHidden(0,true); + view.setRowHidden(0, true); view.show(); QVERIFY(QTest::qWaitForWindowExposed(&view)); } @@ -828,7 +808,7 @@ void tst_QListView::batchedMode() view.setViewMode(QListView::ListMode); view.setLayoutMode(QListView::Batched); view.setBatchSize(2); - view.resize(200,400); + view.resize(200, 400); view.show(); QVERIFY(QTest::qWaitForWindowExposed(&view)); @@ -849,21 +829,18 @@ void tst_QListView::setCurrentIndex() ScrollPerItemListView view; view.setModel(&model); - view.resize(220,182); view.show(); for (int pass = 0; pass < 2; ++pass) { view.setFlow(pass == 0 ? QListView::TopToBottom : QListView::LeftToRight); QScrollBar *sb = pass == 0 ? view.verticalScrollBar() : view.horizontalScrollBar(); - QList gridsizes; - gridsizes << QSize() << QSize(200,38); - for (int ig = 0; ig < gridsizes.count(); ++ig) { - if (pass == 1 && !gridsizes.at(ig).isValid()) // the width of an item varies, so it might jump two times + for (const QSize &gridSize : {QSize(), QSize(200, 38)}) { + if (pass == 1 && !gridSize.isValid()) // the width of an item varies, so it might jump two times continue; - view.setGridSize(gridsizes.at(ig)); + view.setGridSize(gridSize); - qApp->processEvents(); + QCoreApplication::processEvents(); int offset = sb->value(); // first "scroll" down, verify that we scroll one step at a time @@ -897,44 +874,21 @@ void tst_QListView::setCurrentIndex() } } -class PublicListView : public QListView -{ - public: - PublicListView(QWidget *parent = 0) : QListView(parent) - { - - } - void setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags flags) { - QListView::setSelection(rect, flags); - } - QSize contentsSize() const { return QListView::contentsSize(); } - - void setPositionForIndex(const QPoint &pos, const QModelIndex &index) { - QListView::setPositionForIndex(pos, index); - } - - QStyleOptionViewItem viewOptions() const { - return QListView::viewOptions(); - } -}; - -class TestDelegate : public QItemDelegate +class TestDelegate : public QStyledItemDelegate { public: - explicit TestDelegate(QObject *parent, const QSize &sizeHint = QSize(50,50)) - : QItemDelegate(parent), m_sizeHint(sizeHint) {} - QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const { return m_sizeHint; } + explicit TestDelegate(QObject *parent, const QSize &sizeHint = QSize(50, 50)) + : QStyledItemDelegate(parent), m_sizeHint(sizeHint) {} + QSize sizeHint(const QStyleOptionViewItem &, const QModelIndex &) const override { return m_sizeHint; } const QSize m_sizeHint; }; -typedef QList IntList; - void tst_QListView::selection_data() { QTest::addColumn("itemCount"); - QTest::addColumn("viewMode"); - QTest::addColumn("flow"); + QTest::addColumn("viewMode"); + QTest::addColumn("flow"); QTest::addColumn("wrapping"); QTest::addColumn("spacing"); QTest::addColumn("gridSize"); @@ -944,8 +898,8 @@ void tst_QListView::selection_data() QTest::newRow("select all") << 4 // itemCount - << int(QListView::ListMode) - << int(QListView::TopToBottom) + << QListView::ListMode + << QListView::TopToBottom << false // wrapping << 0 // spacing << QSize() // gridSize @@ -955,8 +909,8 @@ void tst_QListView::selection_data() QTest::newRow("select below, (on viewport)") << 4 // itemCount - << int(QListView::ListMode) - << int(QListView::TopToBottom) + << QListView::ListMode + << QListView::TopToBottom << false // wrapping << 0 // spacing << QSize() // gridSize @@ -966,8 +920,8 @@ void tst_QListView::selection_data() QTest::newRow("select below 2, (on viewport)") << 4 // itemCount - << int(QListView::ListMode) - << int(QListView::TopToBottom) + << QListView::ListMode + << QListView::TopToBottom << true // wrapping << 0 // spacing << QSize() // gridSize @@ -977,8 +931,8 @@ void tst_QListView::selection_data() QTest::newRow("select to the right, (on viewport)") << 40 // itemCount - << int(QListView::ListMode) - << int(QListView::TopToBottom) + << QListView::ListMode + << QListView::TopToBottom << true // wrapping << 0 // spacing << QSize() // gridSize @@ -988,8 +942,8 @@ void tst_QListView::selection_data() QTest::newRow("select to the right 2, (on viewport)") << 40 // itemCount - << int(QListView::ListMode) - << int(QListView::TopToBottom) + << QListView::ListMode + << QListView::TopToBottom << true // wrapping << 0 // spacing << QSize() // gridSize @@ -999,8 +953,8 @@ void tst_QListView::selection_data() QTest::newRow("select inside contents, (on viewport)") << 35 // itemCount - << int(QListView::ListMode) - << int(QListView::TopToBottom) + << QListView::ListMode + << QListView::TopToBottom << true // wrapping << 0 // spacing << QSize() // gridSize @@ -1010,8 +964,8 @@ void tst_QListView::selection_data() QTest::newRow("select a tall rect in LeftToRight flow, wrap items") << 70 // itemCount - << int(QListView::ListMode) - << int(QListView::LeftToRight) + << QListView::ListMode + << QListView::LeftToRight << true // wrapping << 0 // spacing << QSize() // gridSize @@ -1024,8 +978,8 @@ void tst_QListView::selection_data() QTest::newRow("select a wide rect in LeftToRight, wrap items") << 70 // itemCount - << int(QListView::ListMode) - << int(QListView::LeftToRight) + << QListView::ListMode + << QListView::LeftToRight << true // wrapping << 0 // spacing << QSize() // gridSize @@ -1036,8 +990,8 @@ void tst_QListView::selection_data() QTest::newRow("select a wide negative rect in LeftToRight flow, wrap items") << 70 // itemCount - << int(QListView::ListMode) - << int(QListView::LeftToRight) + << QListView::ListMode + << QListView::LeftToRight << true // wrapping << 0 // spacing << QSize() // gridSize @@ -1048,8 +1002,8 @@ void tst_QListView::selection_data() QTest::newRow("select a tall rect in TopToBottom flow, wrap items") << 70 // itemCount - << int(QListView::ListMode) - << int(QListView::TopToBottom) + << QListView::ListMode + << QListView::TopToBottom << true // wrapping << 0 // spacing << QSize() // gridSize @@ -1062,8 +1016,8 @@ void tst_QListView::selection_data() QTest::newRow("select a tall negative rect in TopToBottom flow, wrap items") << 70 // itemCount - << int(QListView::ListMode) - << int(QListView::TopToBottom) + << QListView::ListMode + << QListView::TopToBottom << true // wrapping << 0 // spacing << QSize() // gridSize @@ -1076,8 +1030,8 @@ void tst_QListView::selection_data() QTest::newRow("select a wide rect in TopToBottom, wrap items") << 70 // itemCount - << int(QListView::ListMode) - << int(QListView::TopToBottom) + << QListView::ListMode + << QListView::TopToBottom << true // wrapping << 0 // spacing << QSize() // gridSize @@ -1099,8 +1053,8 @@ void tst_QListView::selection_data() void tst_QListView::selection() { QFETCH(int, itemCount); - QFETCH(int, viewMode); - QFETCH(int, flow); + QFETCH(QListView::ViewMode, viewMode); + QFETCH(QListView::Flow, flow); QFETCH(bool, wrapping); QFETCH(int, spacing); QFETCH(QSize, gridSize); @@ -1110,9 +1064,7 @@ void tst_QListView::selection() QWidget topLevel; PublicListView v(&topLevel); - QtTestModel model; - model.colCount = 1; - model.rCount = itemCount; + QtTestModel model(itemCount, 1); // avoid scrollbar size mismatches among different styles v.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); @@ -1120,16 +1072,15 @@ void tst_QListView::selection() v.setItemDelegate(new TestDelegate(&v)); v.setModel(&model); - v.setViewMode(QListView::ViewMode(viewMode)); - v.setFlow(QListView::Flow(flow)); + v.setViewMode(viewMode); + v.setFlow(flow); v.setWrapping(wrapping); v.setResizeMode(QListView::Adjust); v.setSpacing(spacing); if (gridSize.isValid()) v.setGridSize(gridSize); - for (int j = 0; j < hiddenRows.count(); ++j) { + for (int j = 0; j < hiddenRows.count(); ++j) v.setRowHidden(hiddenRows.at(j), true); - } v.resize(525,525); @@ -1141,9 +1092,8 @@ void tst_QListView::selection() QModelIndexList selected = v.selectionModel()->selectedIndexes(); QCOMPARE(selected.count(), expectedItems.count()); - for (int i = 0; i < selected.count(); ++i) { + for (int i = 0; i < selected.count(); ++i) QVERIFY(expectedItems.contains(selected.at(i).row())); - } } void tst_QListView::scrollTo() @@ -1232,7 +1182,7 @@ void tst_QListView::scrollTo() QCOMPARE(lv.visualRect(index).x(), 0); lv.setWrapping(false); - qApp->processEvents(); //let the layout happen + QCoreApplication::processEvents(); //let the layout happen //Let's try with scrolling per pixel lv.setHorizontalScrollMode( QListView::ScrollPerPixel); @@ -1262,11 +1212,7 @@ void tst_QListView::scrollBarRanges() QWidget topLevel; ScrollPerItemListView lv(&topLevel); QStringListModel model(&lv); - QStringList list; - for (int i = 0; i < rowCount; ++i) - list << QLatin1String("Item ") + QString::number(i); - - model.setStringList(list); + model.setStringList(generateList(QLatin1String("Item "), rowCount)); lv.setModel(&model); lv.resize(250, 130); @@ -1275,10 +1221,9 @@ void tst_QListView::scrollBarRanges() for (int h = 30; h <= 210; ++h) { lv.resize(250, h); - QApplication::processEvents(); // wait for the layout to be done int visibleRowCount = lv.viewport()->size().height() / rowHeight; int invisibleRowCount = rowCount - visibleRowCount; - QCOMPARE(lv.verticalScrollBar()->maximum(), invisibleRowCount); + QTRY_COMPARE(lv.verticalScrollBar()->maximum(), invisibleRowCount); } } @@ -1289,7 +1234,7 @@ void tst_QListView::scrollBarAsNeeded_data() QTest::addColumn("verticalScrollMode"); QTest::addColumn("viewportMargins"); QTest::addColumn("delegateSize"); - QTest::addColumn("flow"); + QTest::addColumn("flow"); QTest::addColumn("horizontalScrollBarVisible"); QTest::addColumn("verticalScrollBarVisible"); @@ -1298,7 +1243,7 @@ void tst_QListView::scrollBarAsNeeded_data() << 0 << QListView::ScrollPerItem << QMargins() << QSize() - << int(QListView::TopToBottom) + << QListView::TopToBottom << false << false; @@ -1307,7 +1252,7 @@ void tst_QListView::scrollBarAsNeeded_data() << 1 << QListView::ScrollPerItem << QMargins() << QSize() - << int(QListView::TopToBottom) + << QListView::TopToBottom << false << false; @@ -1316,7 +1261,7 @@ void tst_QListView::scrollBarAsNeeded_data() << 20 << QListView::ScrollPerItem << QMargins() << QSize() - << int(QListView::TopToBottom) + << QListView::TopToBottom << false << true; @@ -1325,7 +1270,7 @@ void tst_QListView::scrollBarAsNeeded_data() << 4 << QListView::ScrollPerPixel << QMargins() << QSize(40, 40) - << int(QListView::TopToBottom) + << QListView::TopToBottom << false << false; @@ -1335,7 +1280,7 @@ void tst_QListView::scrollBarAsNeeded_data() << 4 << QListView::ScrollPerPixel << QMargins(0, 50, 0, 50) << QSize(40, 40) - << int(QListView::TopToBottom) + << QListView::TopToBottom << false << true; @@ -1345,7 +1290,7 @@ void tst_QListView::scrollBarAsNeeded_data() << 4 << QListView::ScrollPerPixel << QMargins(50, 0, 50, 0) << QSize(120, 40) - << int(QListView::TopToBottom) + << QListView::TopToBottom << true << false; @@ -1354,7 +1299,7 @@ void tst_QListView::scrollBarAsNeeded_data() << 0 << QListView::ScrollPerItem << QMargins() << QSize() - << int(QListView::LeftToRight) + << QListView::LeftToRight << false << false; @@ -1363,7 +1308,7 @@ void tst_QListView::scrollBarAsNeeded_data() << 1 << QListView::ScrollPerItem << QMargins() << QSize() - << int(QListView::LeftToRight) + << QListView::LeftToRight << false << false; @@ -1372,45 +1317,36 @@ void tst_QListView::scrollBarAsNeeded_data() << 20 << QListView::ScrollPerItem << QMargins() << QSize() - << int(QListView::LeftToRight) + << QListView::LeftToRight << true << false; } -class ScrollBarTestListView : public QListView -{ - public: - explicit ScrollBarTestListView(QWidget *p) : QListView(p) {} - - using QAbstractScrollArea::setViewportMargins; -}; - void tst_QListView::scrollBarAsNeeded() { - QFETCH(QSize, size); QFETCH(int, itemCount); QFETCH(QAbstractItemView::ScrollMode, verticalScrollMode); QFETCH(QMargins, viewportMargins); QFETCH(QSize, delegateSize); - QFETCH(int, flow); + QFETCH(QListView::Flow, flow); QFETCH(bool, horizontalScrollBarVisible); QFETCH(bool, verticalScrollBarVisible); - const int rowCounts[3] = {0, 1, 20}; + constexpr int rowCounts[3] = {0, 1, 20}; QWidget topLevel; topLevel.setWindowTitle(QLatin1String(QTest::currentTestFunction()) + QStringLiteral("::") + QLatin1String(QTest::currentDataTag())); - ScrollBarTestListView lv(&topLevel); + PublicListView lv(&topLevel); lv.setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); lv.setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); lv.setVerticalScrollMode(verticalScrollMode); lv.setViewportMargins(viewportMargins); - lv.setFlow((QListView::Flow)flow); + lv.setFlow(flow); if (!delegateSize.isEmpty()) lv.setItemDelegate(new TestDelegate(&lv, delegateSize)); @@ -1420,13 +1356,8 @@ void tst_QListView::scrollBarAsNeeded() topLevel.show(); QVERIFY(QTest::qWaitForWindowActive(&topLevel)); - for (uint r = 0; r < sizeof(rowCounts)/sizeof(int); ++r) { - QStringList list; - for (int i = 0; i < rowCounts[r]; ++i) - list << QLatin1String("Item ") + QString::number(i); - - model.setStringList(list); - + for (uint r = 0; r < sizeof(rowCounts) / sizeof(int); ++r) { + model.setStringList(generateList(QLatin1String("Item "), rowCounts[r])); model.setStringList(generateList(QLatin1String("Item "), itemCount)); QTRY_COMPARE(lv.horizontalScrollBar()->isVisible(), horizontalScrollBarVisible); @@ -1483,7 +1414,6 @@ void tst_QListView::wordWrap() lv.setWordWrap(true); lv.setFixedSize(400, 150); lv.showNormal(); - QApplication::processEvents(); QTRY_COMPARE(lv.horizontalScrollBar()->isVisible(), false); #ifdef Q_OS_WINRT @@ -1509,7 +1439,8 @@ public: listView->setModel(model); timer = new QTimer(this); - connect(timer, SIGNAL(timeout()), this, SLOT(buttonClicked())); + connect(timer, &QTimer::timeout, + this, &SetCurrentIndexAfterAppendRowCrashDialog::buttonClicked); timer->start(1000); } @@ -1519,7 +1450,7 @@ protected: QDialog::showEvent(event); DWORD lParam = 0xFFFFFFFC/*OBJID_CLIENT*/; DWORD wParam = 0; - if (const HWND hwnd =getHWNDForWidget(this)) + if (const HWND hwnd = getHWNDForWidget(this)) SendMessage(hwnd, WM_GETOBJECT, wParam, lParam); } @@ -1581,12 +1512,11 @@ void tst_QListView::task228566_infiniteRelayout() QListView view; QStringList list; - for (int i = 0; i < 10; ++i) { + for (int i = 0; i < 10; ++i) list << "small"; - } - list << "BIGBIGBIGBIGBIGBIGBIGBIGBIGBIGBIGBIG"; - list << "BIGBIGBIGBIGBIGBIGBIGBIGBIGBIGBIGBIG"; + list << "BIGBIGBIGBIGBIGBIGBIGBIGBIGBIGBIGBIG" + << "BIGBIGBIGBIGBIGBIGBIGBIGBIGBIGBIGBIG"; QStringListModel model(list); view.setModel(&model); @@ -1600,7 +1530,7 @@ void tst_QListView::task228566_infiniteRelayout() QVERIFY(QTest::qWaitForWindowActive(&view)); QTest::qWait(100); //make sure the layout is done once - QSignalSpy spy(view.horizontalScrollBar(), SIGNAL(rangeChanged(int,int))); + QSignalSpy spy(view.horizontalScrollBar(), &QScrollBar::rangeChanged); //the layout should already have been done //so there should be no change made to the scrollbar @@ -1611,7 +1541,7 @@ void tst_QListView::task248430_crashWith0SizedItem() { QListView view; view.setViewMode(QListView::IconMode); - QStringListModel model(QStringList() << QLatin1String("item1") << QString()); + QStringListModel model({QLatin1String("item1"), QString()}); view.setModel(&model); view.show(); QVERIFY(QTest::qWaitForWindowExposed(&view)); @@ -1630,11 +1560,10 @@ void tst_QListView::task250446_scrollChanged() QVERIFY(QTest::qWaitForWindowExposed(&view)); const int scrollValue = view.verticalScrollBar()->maximum(); view.verticalScrollBar()->setValue(scrollValue); - QCOMPARE(view.verticalScrollBar()->value(), scrollValue); - QCOMPARE(view.currentIndex(), index); + QTRY_COMPARE(view.verticalScrollBar()->value(), scrollValue); + QTRY_COMPARE(view.currentIndex(), index); view.showMinimized(); - QTest::qWait(50); QTRY_COMPARE(view.verticalScrollBar()->value(), scrollValue); QTRY_COMPARE(view.currentIndex(), index); @@ -1646,18 +1575,12 @@ void tst_QListView::task250446_scrollChanged() void tst_QListView::task196118_visualRegionForSelection() { - class MyListView : public QListView - { - public: - QRegion getVisualRegionForSelection() const - { return QListView::visualRegionForSelection( selectionModel()->selection()); } - } view; - + PublicListView view; QStandardItemModel model; QStandardItem top1("top1"); QStandardItem sub1("sub1"); - top1.appendRow(QList() << &sub1); - model.appendColumn(QList() << &top1); + top1.appendRow(&sub1); + model.appendColumn({&top1}); view.setModel(&model); view.setRootIndex(top1.index()); @@ -1670,16 +1593,9 @@ void tst_QListView::task196118_visualRegionForSelection() void tst_QListView::task254449_draggingItemToNegativeCoordinates() { //we'll check that the items are painted correctly - class MyListView : public QListView - { - public: - void setPositionForIndex(const QPoint &position, const QModelIndex &index) - { QListView::setPositionForIndex(position, index); } - - } list; - - QStandardItemModel model(1,1); - QModelIndex index = model.index(0,0); + PublicListView list; + QStandardItemModel model(1, 1); + QModelIndex index = model.index(0, 0); model.setData(index, QLatin1String("foo")); list.setModel(&model); list.setViewMode(QListView::IconMode); @@ -1691,27 +1607,23 @@ void tst_QListView::task254449_draggingItemToNegativeCoordinates() class MyItemDelegate : public QStyledItemDelegate { public: - MyItemDelegate() : numPaints(0) { } - void paint(QPainter *painter, - const QStyleOptionViewItem &option, const QModelIndex &index) const + using QStyledItemDelegate::QStyledItemDelegate; + void paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index) const override { numPaints++; QStyledItemDelegate::paint(painter, option, index); } - mutable int numPaints; + mutable int numPaints = 0; } delegate; - delegate.numPaints = 0; list.setItemDelegate(&delegate); - QApplication::processEvents(); QTRY_VERIFY(delegate.numPaints > 0); //makes sure the layout is done - const QPoint topLeft(-6, 0); - list.setPositionForIndex(topLeft, index); - //we'll make sure the item is repainted delegate.numPaints = 0; - QApplication::processEvents(); + const QPoint topLeft(-6, 0); + list.setPositionForIndex(topLeft, index); QTRY_COMPARE(delegate.numPaints, 1); QCOMPARE(list.visualRect(index).topLeft(), topLeft); } @@ -1719,14 +1631,13 @@ void tst_QListView::task254449_draggingItemToNegativeCoordinates() void tst_QListView::keyboardSearch() { - QStringList items; - items << "AB" << "AC" << "BA" << "BB" << "BD" << "KAFEINE" << "KONQUEROR" << "KOPETE" << "KOOKA" << "OKULAR"; - QStringListModel model(items); + QStringListModel model({"AB", "AC", "BA", "BB", "BD", "KAFEINE", + "KONQUEROR", "KOPETE", "KOOKA", "OKULAR"}); QListView view; view.setModel(&model); view.show(); - qApp->setActiveWindow(&view); + QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); QTest::keyClick(&view, Qt::Key_K); @@ -1744,9 +1655,7 @@ void tst_QListView::shiftSelectionWithNonUniformItemSizes() // This checks that no items are selected unexpectedly by Shift-Arrow // when items with non-uniform sizes are laid out in a grid { // First test: QListView::LeftToRight flow - QStringList items; - items << "Long\nText" << "Text" << "Text" << "Text"; - QStringListModel model(items); + QStringListModel model({"Long\nText", "Text", "Text","Text"}); QListView view; view.setFixedSize(250, 250); @@ -1773,9 +1682,7 @@ void tst_QListView::shiftSelectionWithNonUniformItemSizes() QVERIFY(!selected.contains(model.index(0, 0))); } { // Second test: QListView::TopToBottom flow - QStringList items; - items << "ab" << "a" << "a" << "a"; - QStringListModel model(items); + QStringListModel model({"ab", "a", "a", "a"}); QListView view; view.setFixedSize(250, 250); @@ -1836,7 +1743,7 @@ void tst_QListView::shiftSelectionWithItemAlignment() QModelIndex index1 = view.model()->index(items.size() / 4, 0); QPoint p = view.visualRect(index1).center(); QVERIFY(view.viewport()->rect().contains(p)); - QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p); + QTest::mouseClick(view.viewport(), Qt::LeftButton, {}, p); QCOMPARE(view.currentIndex(), index1); QCOMPARE(view.selectionModel()->selectedIndexes().size(), 1); @@ -1850,9 +1757,7 @@ void tst_QListView::shiftSelectionWithItemAlignment() void tst_QListView::clickOnViewportClearsSelection() { - QStringList items; - items << "Text1"; - QStringListModel model(items); + QStringListModel model({"Text1"}); QListView view; view.setModel(&model); view.setSelectionMode(QListView::ExtendedSelection); @@ -1865,12 +1770,12 @@ void tst_QListView::clickOnViewportClearsSelection() //we try to click outside of the index const QPoint point = view.visualRect(index).bottomRight() + QPoint(10,10); - QTest::mousePress(view.viewport(), Qt::LeftButton, 0, point); + QTest::mousePress(view.viewport(), Qt::LeftButton, {}, point); //at this point, the selection shouldn't have changed QCOMPARE(view.selectionModel()->selectedIndexes().count(), 1); QVERIFY(view.selectionModel()->isSelected(index)); - QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, point); + QTest::mouseRelease(view.viewport(), Qt::LeftButton, {}, point); //now the selection should be cleared QVERIFY(!view.selectionModel()->hasSelection()); } @@ -1879,9 +1784,9 @@ void tst_QListView::task262152_setModelColumnNavigate() { QListView view; QStandardItemModel model(3,2); - model.setItem(0,1,new QStandardItem("[0,1]")); - model.setItem(1,1,new QStandardItem("[1,1]")); - model.setItem(2,1,new QStandardItem("[2,1]")); + model.setItem(0, 1, new QStandardItem("[0,1]")); + model.setItem(1, 1, new QStandardItem("[1,1]")); + model.setItem(2, 1, new QStandardItem("[2,1]")); view.setModel(&model); view.setModelColumn(1); @@ -1889,7 +1794,7 @@ void tst_QListView::task262152_setModelColumnNavigate() view.show(); QApplication::setActiveWindow(&view); QVERIFY(QTest::qWaitForWindowActive(&view)); - QCOMPARE(static_cast(&view), QApplication::activeWindow()); + QCOMPARE(&view, QApplication::activeWindow()); QTest::keyClick(&view, Qt::Key_Down); QTRY_COMPARE(view.currentIndex(), model.index(1,1)); QTest::keyClick(&view, Qt::Key_Down); @@ -1898,32 +1803,28 @@ void tst_QListView::task262152_setModelColumnNavigate() void tst_QListView::taskQTBUG_2233_scrollHiddenItems_data() { - QTest::addColumn("flow"); + QTest::addColumn("flow"); - QTest::newRow("TopToBottom") << static_cast(QListView::TopToBottom); - QTest::newRow("LeftToRight") << static_cast(QListView::LeftToRight); + QTest::newRow("TopToBottom") << QListView::TopToBottom; + QTest::newRow("LeftToRight") << QListView::LeftToRight; } void tst_QListView::taskQTBUG_2233_scrollHiddenItems() { - QFETCH(int, flow); + QFETCH(QListView::Flow, flow); const int rowCount = 200; QWidget topLevel; setFrameless(&topLevel); ScrollPerItemListView view(&topLevel); QStringListModel model(&view); - QStringList list; - for (int i = 0; i < rowCount; ++i) - list << QString::number(i); - - model.setStringList(list); + model.setStringList(generateList(QString(), rowCount)); view.setModel(&model); view.setUniformItemSizes(true); view.setViewMode(QListView::ListMode); for (int i = 0; i < rowCount / 2; ++i) view.setRowHidden(2 * i, true); - view.setFlow(static_cast(flow)); + view.setFlow(flow); view.resize(130, 130); for (int i = 0; i < 10; ++i) { @@ -1944,10 +1845,9 @@ void tst_QListView::taskQTBUG_2233_scrollHiddenItems() int nbVisibleItem = rowCount / 2 - bar->maximum(); bar->setValue(bar->maximum()); - for (int i = rowCount; i > rowCount / 2; i--) { + for (int i = rowCount; i > rowCount / 2; i--) view.setRowHidden(i, true); - } - QTRY_COMPARE(bar->maximum(), rowCount/4 - nbVisibleItem); + QTRY_COMPARE(bar->maximum(), rowCount / 4 - nbVisibleItem); QCOMPARE(bar->value(), bar->maximum()); } @@ -1956,9 +1856,8 @@ void tst_QListView::taskQTBUG_633_changeModelData() QListView view; view.setFlow(QListView::LeftToRight); QStandardItemModel model(5,1); - for (int i = 0; i < model.rowCount(); ++i) { - model.setData( model.index(i, 0), QString::number(i)); - } + for (int i = 0; i < model.rowCount(); ++i) + model.setData(model.index(i, 0), QString::number(i)); view.setModel(&model); view.show(); @@ -1975,7 +1874,7 @@ void tst_QListView::taskQTBUG_633_changeModelData() void tst_QListView::taskQTBUG_435_deselectOnViewportClick() { QListView view; - QStringListModel model( QStringList() << "1" << "2" << "3" << "4"); + QStringListModel model({"1", "2", "3", "4"}); view.setModel(&model); view.setSelectionMode(QAbstractItemView::ExtendedSelection); view.selectAll(); @@ -1985,21 +1884,21 @@ void tst_QListView::taskQTBUG_435_deselectOnViewportClick() const QRect itemRect = view.visualRect(model.index(model.rowCount() - 1)); QPoint p = view.visualRect(model.index(model.rowCount() - 1)).center() + QPoint(0, itemRect.height()); //first the left button - QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, p); + QTest::mouseClick(view.viewport(), Qt::LeftButton, {}, p); QVERIFY(!view.selectionModel()->hasSelection()); view.selectAll(); QCOMPARE(view.selectionModel()->selectedIndexes().count(), model.rowCount()); //and now the right button - QTest::mouseClick(view.viewport(), Qt::RightButton, 0, p); + QTest::mouseClick(view.viewport(), Qt::RightButton, {}, p); QVERIFY(!view.selectionModel()->hasSelection()); } void tst_QListView::taskQTBUG_2678_spacingAndWrappedText() { static const QString lorem("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."); - QStringListModel model(QStringList() << lorem << lorem << "foo" << lorem << "bar" << lorem << lorem); + QStringListModel model({lorem, lorem, "foo", lorem, "bar", lorem, lorem}); QListView w; w.setModel(&model); w.setViewMode(QListView::ListMode); @@ -2012,14 +1911,11 @@ void tst_QListView::taskQTBUG_2678_spacingAndWrappedText() void tst_QListView::taskQTBUG_5877_skippingItemInPageDownUp() { - QList currentItemIndexes; - QtTestModel model(0); - model.colCount = 1; - model.rCount = 100; + QtTestModel model(100, 1); - currentItemIndexes << 0 << 6 << 16 << 25 << 34 << 42 << 57 << 68 << 77 - << 83 << 91 << 94; - QMoveCursorListView vu; + static const int currentItemIndexes[] = + {0, 6, 16, 25, 34, 42, 57, 68, 77, 83, 91, 94}; + PublicListView vu; vu.setModel(&model); vu.show(); @@ -2029,43 +1925,34 @@ void tst_QListView::taskQTBUG_5877_skippingItemInPageDownUp() int visibleRowCount = vu.viewport()->height() / itemHeight; int scrolledRowCount = visibleRowCount - 1; - for (int i = 0; i < currentItemIndexes.size(); ++i) { - vu.selectionModel()->setCurrentIndex(model.index(currentItemIndexes[i], 0), + for (int currentItemIndex : currentItemIndexes) { + vu.selectionModel()->setCurrentIndex(model.index(currentItemIndex, 0), QItemSelectionModel::SelectCurrent); - QModelIndex idx = vu.doMoveCursor(QMoveCursorListView::MovePageDown, Qt::NoModifier); - int newCurrent = qMin(currentItemIndexes[i] + scrolledRowCount, 99); + QModelIndex idx = vu.moveCursor(PublicListView::MovePageDown, Qt::NoModifier); + int newCurrent = qMin(currentItemIndex + scrolledRowCount, 99); QCOMPARE(idx, model.index(newCurrent, 0)); - idx = vu.doMoveCursor(QMoveCursorListView::MovePageUp, Qt::NoModifier); - newCurrent = qMax(currentItemIndexes[i] - scrolledRowCount, 0); + idx = vu.moveCursor(PublicListView::MovePageUp, Qt::NoModifier); + newCurrent = qMax(currentItemIndex - scrolledRowCount, 0); QCOMPARE(idx, model.index(newCurrent, 0)); } } -class ListView_9455 : public QListView -{ -public: - QSize contentsSize() const - { - return QListView::contentsSize(); - } -}; - void tst_QListView::taskQTBUG_9455_wrongScrollbarRanges() { QStringListModel model(generateList("item ", 8)); - ListView_9455 w; + PublicListView w; setFrameless(&w); w.setModel(&model); w.setViewMode(QListView::IconMode); w.resize(116, 132); w.setMovement(QListView::Static); - const int spacing = 200; - w.setSpacing(spacing); + w.setSpacing(200); w.showNormal(); QVERIFY(QTest::qWaitForWindowExposed(&w)); - QCOMPARE(w.verticalScrollBar()->maximum(), w.contentsSize().height() - w.viewport()->geometry().height()); + QCOMPARE(w.verticalScrollBar()->maximum(), + w.contentsSize().height() - w.viewport()->geometry().height()); } void tst_QListView::styleOptionViewItem() @@ -2073,7 +1960,8 @@ void tst_QListView::styleOptionViewItem() class MyDelegate : public QStyledItemDelegate { public: - void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const + void paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index) const override { QStyleOptionViewItem opt(option); initStyleOption(&opt, index); @@ -2089,12 +1977,14 @@ void tst_QListView::styleOptionViewItem() view.setModel(&model); MyDelegate delegate; view.setItemDelegate(&delegate); - model.appendRow(QList() - << new QStandardItem("Beginning") << new QStandardItem("Middle") << new QStandardItem("Middle") << new QStandardItem("End") ); + model.appendRow({new QStandardItem("Beginning"), + new QStandardItem("Middle"), + new QStandardItem("Middle"), + new QStandardItem("End")}); // Run test view.showMaximized(); - QApplication::processEvents(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); } void tst_QListView::taskQTBUG_12308_artihmeticException() @@ -2103,8 +1993,8 @@ void tst_QListView::taskQTBUG_12308_artihmeticException() lw.setLayoutMode(QListView::Batched); lw.setViewMode(QListView::IconMode); for (int i = 0; i < lw.batchSize() + 1; i++) { - QListWidgetItem *item = new QListWidgetItem(); - item->setText(QString("Item %L1").arg(i)); + QListWidgetItem *item = new QListWidgetItem( + QLatin1String("Item ") + QString::number(i)); lw.addItem(item); item->setHidden(true); } @@ -2117,10 +2007,9 @@ class Delegate12308 : public QStyledItemDelegate { Q_OBJECT public: - Delegate12308(QObject *parent = 0) : QStyledItemDelegate(parent) - { } - - void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const + using QStyledItemDelegate::QStyledItemDelegate; + void paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index) const override { QVERIFY(option.rect.topLeft() != QPoint(-1, -1)); QStyledItemDelegate::paint(painter, option, index); @@ -2135,8 +2024,8 @@ void tst_QListView::taskQTBUG_12308_wrongFlowLayout() lw.setViewMode(QListView::IconMode); lw.setItemDelegate(&delegate); for (int i = 0; i < lw.batchSize() + 1; i++) { - QListWidgetItem *item = new QListWidgetItem(); - item->setText(QString("Item %L1").arg(i)); + QListWidgetItem *item = new QListWidgetItem( + QLatin1String("Item ") + QString::number(i)); lw.addItem(item); if (!item->text().contains(QLatin1Char('1'))) item->setHidden(true); @@ -2147,27 +2036,24 @@ void tst_QListView::taskQTBUG_12308_wrongFlowLayout() void tst_QListView::taskQTBUG_21115_scrollToAndHiddenItems_data() { - QTest::addColumn("flow"); - QTest::newRow("flow TopToBottom") << static_cast(QListView::TopToBottom); - QTest::newRow("flow LeftToRight") << static_cast(QListView::LeftToRight); + QTest::addColumn("flow"); + QTest::newRow("flow TopToBottom") << QListView::TopToBottom; + QTest::newRow("flow LeftToRight") << QListView::LeftToRight; } void tst_QListView::taskQTBUG_21115_scrollToAndHiddenItems() { - QFETCH(int, flow); + QFETCH(QListView::Flow, flow); #ifdef Q_OS_WINRT QSKIP("Fails on WinRT - QTBUG-68297"); #endif ScrollPerItemListView lv; lv.setUniformItemSizes(true); - lv.setFlow(static_cast(flow)); + lv.setFlow(flow); QStringListModel model; - QStringList list; - for (int i = 0; i < 30; i++) - list << QString::number(i); - model.setStringList(list); + model.setStringList(generateList(QString(), 30)); lv.setModel(&model); lv.showNormal(); QVERIFY(QTest::qWaitForWindowExposed(&lv)); @@ -2179,8 +2065,7 @@ void tst_QListView::taskQTBUG_21115_scrollToAndHiddenItems() QModelIndex index = model.index(2, 0); lv.setCurrentIndex(index); lv.scrollTo(index, QAbstractItemView::PositionAtTop); - QApplication::processEvents(); - QCOMPARE(lv.visualRect(index), firstItemRect); + QTRY_COMPARE(lv.visualRect(index), firstItemRect); // Hide some rows and scroll to selection for (int i = 0; i < 5; i++) { @@ -2189,8 +2074,7 @@ void tst_QListView::taskQTBUG_21115_scrollToAndHiddenItems() lv.setRowHidden(i, true); } lv.scrollTo(index, QAbstractItemView::PositionAtTop); - QApplication::processEvents(); - QCOMPARE(lv.visualRect(index), firstItemRect); + QTRY_COMPARE(lv.visualRect(index), firstItemRect); } void tst_QListView::draggablePaintPairs_data() @@ -2208,10 +2092,7 @@ void tst_QListView::draggablePaintPairs() QListView view; QStringListModel model; - QStringList list; - for (int i = 0; i < 30; i++) - list << QString::number(i); - model.setStringList(list); + model.setStringList(generateList(QString(), 30)); view.setModel(&model); view.show(); @@ -2220,12 +2101,11 @@ void tst_QListView::draggablePaintPairs() QModelIndex expectedIndex = model.index(row, 0); QListViewPrivate *privateClass = static_cast(QListViewPrivate::get(&view)); QRect rect; - QModelIndexList indexList; - indexList << expectedIndex; + const QModelIndexList indexList{ expectedIndex }; view.scrollTo(expectedIndex); - QItemViewPaintPairs pairs = privateClass->draggablePaintPairs(indexList, &rect); + const QItemViewPaintPairs pairs = privateClass->draggablePaintPairs(indexList, &rect); QCOMPARE(indexList.size(), pairs.size()); - foreach (const QItemViewPaintPair &pair, pairs) { + for (const QItemViewPaintPair &pair : pairs) { QCOMPARE(rect, pair.rect); QCOMPARE(expectedIndex, pair.index); } @@ -2233,29 +2113,26 @@ void tst_QListView::draggablePaintPairs() void tst_QListView::taskQTBUG_21804_hiddenItemsAndScrollingWithKeys_data() { - QTest::addColumn("flow"); + QTest::addColumn("flow"); QTest::addColumn("spacing"); - QTest::newRow("flow TopToBottom no spacing") << static_cast(QListView::TopToBottom) << 0; - QTest::newRow("flow TopToBottom with spacing") << static_cast(QListView::TopToBottom) << 5; - QTest::newRow("flow LeftToRight no spacing") << static_cast(QListView::LeftToRight) << 0; - QTest::newRow("flow LeftToRight with spacing") << static_cast(QListView::LeftToRight) << 5; + QTest::newRow("flow TopToBottom no spacing") << QListView::TopToBottom << 0; + QTest::newRow("flow TopToBottom with spacing") << QListView::TopToBottom << 5; + QTest::newRow("flow LeftToRight no spacing") << QListView::LeftToRight << 0; + QTest::newRow("flow LeftToRight with spacing") << QListView::LeftToRight << 5; } void tst_QListView::taskQTBUG_21804_hiddenItemsAndScrollingWithKeys() { - QFETCH(int, flow); + QFETCH(QListView::Flow, flow); QFETCH(int, spacing); // create some items to show QStringListModel model; - QStringList list; - for (int i = 0; i < 60; i++) - list << QString::number(i); - model.setStringList(list); + model.setStringList(generateList(QString(), 60)); // create listview ScrollPerItemListView lv; - lv.setFlow(static_cast(flow)); + lv.setFlow(flow); lv.setSpacing(spacing); lv.setModel(&model); lv.show(); @@ -2266,7 +2143,7 @@ void tst_QListView::taskQTBUG_21804_hiddenItemsAndScrollingWithKeys() lv.setRowHidden(i, true); // scroll forward and check that selected item is visible always - int visibleItemCount = model.rowCount()/2; + int visibleItemCount = model.rowCount() / 2; for (int i = 0; i < visibleItemCount; i++) { if (flow == QListView::TopToBottom) QTest::keyClick(&lv, Qt::Key_Down); @@ -2285,7 +2162,7 @@ void tst_QListView::taskQTBUG_21804_hiddenItemsAndScrollingWithKeys() } // scroll forward only half way - for (int i = 0; i < visibleItemCount/2; i++) { + for (int i = 0; i < visibleItemCount / 2; i++) { if (flow == QListView::TopToBottom) QTest::keyClick(&lv, Qt::Key_Down); else @@ -2294,7 +2171,7 @@ void tst_QListView::taskQTBUG_21804_hiddenItemsAndScrollingWithKeys() } // scroll backward again - for (int i = 0; i < visibleItemCount/2; i++) { + for (int i = 0; i < visibleItemCount / 2; i++) { if (flow == QListView::TopToBottom) QTest::keyClick(&lv, Qt::Key_Up); else @@ -2305,29 +2182,26 @@ void tst_QListView::taskQTBUG_21804_hiddenItemsAndScrollingWithKeys() void tst_QListView::spacing_data() { - QTest::addColumn("flow"); + QTest::addColumn("flow"); QTest::addColumn("spacing"); - QTest::newRow("flow=TopToBottom spacing=0") << static_cast(QListView::TopToBottom) << 0; - QTest::newRow("flow=TopToBottom spacing=10") << static_cast(QListView::TopToBottom) << 10; - QTest::newRow("flow=LeftToRight spacing=0") << static_cast(QListView::LeftToRight) << 0; - QTest::newRow("flow=LeftToRight spacing=10") << static_cast(QListView::LeftToRight) << 10; + QTest::newRow("flow=TopToBottom spacing=0") << QListView::TopToBottom << 0; + QTest::newRow("flow=TopToBottom spacing=10") << QListView::TopToBottom << 10; + QTest::newRow("flow=LeftToRight spacing=0") << QListView::LeftToRight << 0; + QTest::newRow("flow=LeftToRight spacing=10") << QListView::LeftToRight << 10; } void tst_QListView::spacing() { - QFETCH(int, flow); + QFETCH(QListView::Flow, flow); QFETCH(int, spacing); // create some items to show QStringListModel model; - QStringList list; - for (int i = 0; i < 60; i++) - list << QString::number(i); - model.setStringList(list); + model.setStringList(generateList(QString(), 60)); // create listview ScrollPerItemListView lv; - lv.setFlow(static_cast(flow)); + lv.setFlow(flow); lv.setModel(&model); lv.setSpacing(spacing); lv.show(); @@ -2352,10 +2226,7 @@ void tst_QListView::testScrollToWithHidden() QListView lv; QStringListModel model; - QStringList list; - for (int i = 0; i < 30; i++) - list << QString::number(i); - model.setStringList(list); + model.setStringList(generateList(QString(), 30)); lv.setModel(&model); lv.setRowHidden(1, true); @@ -2394,11 +2265,12 @@ class TempStyleSetter { public: TempStyleSetter() - : m_oldStyle(qApp->style()) + : m_oldStyle(QApplication::style()) { - m_oldStyle->setParent(0); + m_oldStyle->setParent(nullptr); QListView tempView; - if (QApplication::style()->styleHint(QStyle::SH_ScrollBar_Transient, 0, tempView.horizontalScrollBar())) + if (QApplication::style()->styleHint(QStyle::SH_ScrollBar_Transient, + nullptr, tempView.horizontalScrollBar())) QApplication::setStyle(QStyleFactory::create("Fusion")); } @@ -2407,17 +2279,21 @@ public: QApplication::setStyle(m_oldStyle); } private: - QStyle* m_oldStyle; + QStyle *m_oldStyle; }; void tst_QListView::taskQTBUG_39902_mutualScrollBars_data() { QTest::addColumn("horizontalScrollMode"); QTest::addColumn("verticalScrollMode"); - QTest::newRow("per item / per item") << QAbstractItemView::ScrollPerItem << QAbstractItemView::ScrollPerItem; - QTest::newRow("per pixel / per item") << QAbstractItemView::ScrollPerPixel << QAbstractItemView::ScrollPerItem; - QTest::newRow("per item / per pixel") << QAbstractItemView::ScrollPerItem << QAbstractItemView::ScrollPerPixel; - QTest::newRow("per pixel / per pixel") << QAbstractItemView::ScrollPerPixel << QAbstractItemView::ScrollPerPixel; + QTest::newRow("per item / per item") << QAbstractItemView::ScrollPerItem + << QAbstractItemView::ScrollPerItem; + QTest::newRow("per pixel / per item") << QAbstractItemView::ScrollPerPixel + << QAbstractItemView::ScrollPerItem; + QTest::newRow("per item / per pixel") << QAbstractItemView::ScrollPerItem + << QAbstractItemView::ScrollPerPixel; + QTest::newRow("per pixel / per pixel") << QAbstractItemView::ScrollPerPixel + << QAbstractItemView::ScrollPerPixel; } void tst_QListView::taskQTBUG_39902_mutualScrollBars() @@ -2447,50 +2323,60 @@ void tst_QListView::taskQTBUG_39902_mutualScrollBars() model.setRowCount(2); for (int i = 0; i < model.rowCount(); ++i) model.setData(model.index(i, 0), itemSize, Qt::SizeHintRole); - view->resize(itemSize.width() + view->frameWidth() * 2, model.rowCount() * itemSize.height() + view->frameWidth() * 2); + view->resize(itemSize.width() + view->frameWidth() * 2, + model.rowCount() * itemSize.height() + view->frameWidth() * 2); // this will end up in a stack overflow, if QTBUG-39902 is not fixed QTest::qWait(100); // these tests do not apply with transient scroll bars enabled - QVERIFY (!view->style()->styleHint(QStyle::SH_ScrollBar_Transient, 0, view->horizontalScrollBar())); + QVERIFY (!view->style()->styleHint(QStyle::SH_ScrollBar_Transient, + nullptr, view->horizontalScrollBar())); // make it double as large, no scroll bars should be visible - view->resize((itemSize.width() + view->frameWidth() * 2) * 2, (model.rowCount() * itemSize.height() + view->frameWidth() * 2) * 2); + view->resize((itemSize.width() + view->frameWidth() * 2) * 2, + (model.rowCount() * itemSize.height() + view->frameWidth() * 2) * 2); QTRY_VERIFY(!view->horizontalScrollBar()->isVisible()); QTRY_VERIFY(!view->verticalScrollBar()->isVisible()); // make it half the size, both scroll bars should be visible - view->resize((itemSize.width() + view->frameWidth() * 2) / 2, (model.rowCount() * itemSize.height() + view->frameWidth() * 2) / 2); + view->resize((itemSize.width() + view->frameWidth() * 2) / 2, + (model.rowCount() * itemSize.height() + view->frameWidth() * 2) / 2); QTRY_VERIFY(view->horizontalScrollBar()->isVisible()); QTRY_VERIFY(view->verticalScrollBar()->isVisible()); // make it double as large, no scroll bars should be visible - view->resize((itemSize.width() + view->frameWidth() * 2) * 2, (model.rowCount() * itemSize.height() + view->frameWidth() * 2) * 2); + view->resize((itemSize.width() + view->frameWidth() * 2) * 2, + (model.rowCount() * itemSize.height() + view->frameWidth() * 2) * 2); QTRY_VERIFY(!view->horizontalScrollBar()->isVisible()); QTRY_VERIFY(!view->verticalScrollBar()->isVisible()); // now, coming from the double size, resize it to the exactly matching size, still no scroll bars should be visible again - view->resize(itemSize.width() + view->frameWidth() * 2, model.rowCount() * itemSize.height() + view->frameWidth() * 2); + view->resize(itemSize.width() + view->frameWidth() * 2, + model.rowCount() * itemSize.height() + view->frameWidth() * 2); QTRY_VERIFY(!view->horizontalScrollBar()->isVisible()); QTRY_VERIFY(!view->verticalScrollBar()->isVisible()); // now remove just one single pixel in height -> both scroll bars will show up since they depend on each other - view->resize(itemSize.width() + view->frameWidth() * 2, model.rowCount() * itemSize.height() + view->frameWidth() * 2 - 1); + view->resize(itemSize.width() + view->frameWidth() * 2, + model.rowCount() * itemSize.height() + view->frameWidth() * 2 - 1); QTRY_VERIFY(view->horizontalScrollBar()->isVisible()); QTRY_VERIFY(view->verticalScrollBar()->isVisible()); // now remove just one single pixel in width -> both scroll bars will show up since they depend on each other - view->resize(itemSize.width() + view->frameWidth() * 2 - 1, model.rowCount() * itemSize.height() + view->frameWidth() * 2); + view->resize(itemSize.width() + view->frameWidth() * 2 - 1, + model.rowCount() * itemSize.height() + view->frameWidth() * 2); QTRY_VERIFY(view->horizontalScrollBar()->isVisible()); QTRY_VERIFY(view->verticalScrollBar()->isVisible()); // finally, coming from a size being to small, resize back to the exactly matching size -> both scroll bars should disappear again - view->resize(itemSize.width() + view->frameWidth() * 2, model.rowCount() * itemSize.height() + view->frameWidth() * 2); + view->resize(itemSize.width() + view->frameWidth() * 2, + model.rowCount() * itemSize.height() + view->frameWidth() * 2); QTRY_VERIFY(!view->horizontalScrollBar()->isVisible()); QTRY_VERIFY(!view->verticalScrollBar()->isVisible()); // now remove just one single pixel in height -> both scroll bars will show up since they depend on each other - view->resize(itemSize.width() + view->frameWidth() * 2, model.rowCount() * itemSize.height() + view->frameWidth() * 2 - 1); + view->resize(itemSize.width() + view->frameWidth() * 2, + model.rowCount() * itemSize.height() + view->frameWidth() * 2 - 1); QTRY_VERIFY(view->horizontalScrollBar()->isVisible()); QTRY_VERIFY(view->verticalScrollBar()->isVisible()); } @@ -2503,12 +2389,8 @@ void tst_QListView::horizontalScrollingByVerticalWheelEvents() lv.setItemDelegate(new TestDelegate(&lv, QSize(100, 100))); - QtTestModel model; - model.colCount = 1; - model.rCount = 100; - + QtTestModel model(100, 1); lv.setModel(&model); - lv.resize(300, 300); lv.show(); QVERIFY(QTest::qWaitForWindowExposed(&lv)); @@ -2534,7 +2416,7 @@ void tst_QListView::horizontalScrollingByVerticalWheelEvents() // scroll bar is not visible but vertical scrolling is possible lv.setWrapping(false); lv.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - QApplication::processEvents(); + QCoreApplication::processEvents(); int vValue = lv.verticalScrollBar()->value(); QApplication::sendEvent(lv.viewport(), &wheelDownEvent); @@ -2584,16 +2466,9 @@ void tst_QListView::taskQTBUG_7232_AllowUserToControlSingleStep() void tst_QListView::taskQTBUG_51086_skippingIndexesInSelectedIndexes() { - // simple way to get access to selectedIndexes() - class QListViewWithPublicSelectedIndexes : public QListView - { - public: - using QListView::selectedIndexes; - }; - QStandardItemModel data(10, 1); QItemSelectionModel selections(&data); - QListViewWithPublicSelectedIndexes list; + PublicListView list; list.setModel(&data); list.setSelectionModel(&selections); @@ -2640,7 +2515,7 @@ void tst_QListView::itemAlignment() QVERIFY(w.visualRect(item1->index()).width() == w.visualRect(item2->index()).width()); w.setItemAlignment(Qt::AlignLeft); - QApplication::processEvents(); + QCoreApplication::processEvents(); QVERIFY(w.visualRect(item1->index()).width() < w.visualRect(item2->index()).width()); } @@ -2653,11 +2528,6 @@ void tst_QListView::internalDragDropMove() // on an internal move, the item was deleted which should not happen // see QTBUG-67440 - class QListViewWithPublicStartDrag : public QListView - { - public: - using QListView::startDrag; - }; QStandardItemModel data(0, 1); QPixmap pixmap(32, 32); @@ -2666,7 +2536,7 @@ void tst_QListView::internalDragDropMove() data.appendRow(new QStandardItem(QIcon(pixmap), QString::number(i))); } QItemSelectionModel selections(&data); - QListViewWithPublicStartDrag list; + PublicListView list; list.setWindowTitle(QTest::currentTestFunction()); list.setViewMode(QListView::IconMode); list.setDefaultDropAction(Qt::MoveAction); @@ -2682,9 +2552,9 @@ void tst_QListView::internalDragDropMove() QTimer::singleShot(0, [&list]() { const QPoint pos = list.rect().center(); - QMouseEvent mouseMove(QEvent::MouseMove, pos, list.mapToGlobal(pos), Qt::NoButton, 0, 0); + QMouseEvent mouseMove(QEvent::MouseMove, pos, list.mapToGlobal(pos), Qt::NoButton, {}, {}); QApplication::sendEvent(&list, &mouseMove); - QMouseEvent mouseRelease(QEvent::MouseButtonRelease, pos, list.mapToGlobal(pos), Qt::LeftButton, 0, 0); + QMouseEvent mouseRelease(QEvent::MouseButtonRelease, pos, list.mapToGlobal(pos), Qt::LeftButton, {}, {}); QApplication::sendEvent(&list, &mouseRelease); }); const int expectedCount = data.rowCount(); From 895a786827a0056398c07e3b668f35bd5952849e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Wed, 18 Sep 2019 10:46:58 +0200 Subject: [PATCH 11/22] Fix crash when using signaldumper and sender is deleted Testlib's signaldumper functionality would crash inside testlib as it dereferenced the sender after it was deleted. Change-Id: I6013b75b0a121e2768429d8a3cf0339a940314f2 Reviewed-by: Lars Knoll --- src/corelib/kernel/qobject.cpp | 7 ++++--- .../testlib/selftests/expected_signaldumper.lightxml | 9 ++++++++- .../auto/testlib/selftests/expected_signaldumper.tap | 12 +++++++----- .../testlib/selftests/expected_signaldumper.teamcity | 3 +++ .../auto/testlib/selftests/expected_signaldumper.txt | 6 ++++-- .../auto/testlib/selftests/expected_signaldumper.xml | 9 ++++++++- .../testlib/selftests/expected_signaldumper.xunitxml | 10 +++++++--- .../selftests/signaldumper/tst_signaldumper.cpp | 11 +++++++++++ 8 files changed, 52 insertions(+), 15 deletions(-) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 0b396343af..cf107498dd 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -3908,11 +3908,12 @@ void doActivate(QObject *sender, int signal_index, void **argv) if (connections->currentConnectionId.loadRelaxed() == 0) senderDeleted = true; } - if (!senderDeleted) + if (!senderDeleted) { sp->connections.loadRelaxed()->cleanOrphanedConnections(sender); - if (callbacks_enabled && signal_spy_set->signal_end_callback != nullptr) - signal_spy_set->signal_end_callback(sender, signal_index); + if (callbacks_enabled && signal_spy_set->signal_end_callback != nullptr) + signal_spy_set->signal_end_callback(sender, signal_index); + } } /*! diff --git a/tests/auto/testlib/selftests/expected_signaldumper.lightxml b/tests/auto/testlib/selftests/expected_signaldumper.lightxml index f68834e1a2..443f649bb6 100644 --- a/tests/auto/testlib/selftests/expected_signaldumper.lightxml +++ b/tests/auto/testlib/selftests/expected_signaldumper.lightxml @@ -568,11 +568,18 @@ + + + + + + + - + diff --git a/tests/auto/testlib/selftests/expected_signaldumper.tap b/tests/auto/testlib/selftests/expected_signaldumper.tap index 04d7d94745..e2d664f4f1 100644 --- a/tests/auto/testlib/selftests/expected_signaldumper.tap +++ b/tests/auto/testlib/selftests/expected_signaldumper.tap @@ -143,9 +143,11 @@ ok 18 - slotEmittingSignalOldSyntax(queued) # Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant()) # Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant()) ok 19 - variousTypes() -ok 20 - cleanupTestCase() -# Signal: QThread(_POINTER_) finished () -1..20 -# tests 20 -# pass 20 +# Signal: SignalSlotClass(_POINTER_) signalWithoutParameters () +ok 20 - deletingSender() +ok 21 - cleanupTestCase() +# Signal: QThread(_POINTER_) finished () +1..21 +# tests 21 +# pass 21 # fail 0 diff --git a/tests/auto/testlib/selftests/expected_signaldumper.teamcity b/tests/auto/testlib/selftests/expected_signaldumper.teamcity index 3b8cf8c54f..0fc568e086 100644 --- a/tests/auto/testlib/selftests/expected_signaldumper.teamcity +++ b/tests/auto/testlib/selftests/expected_signaldumper.teamcity @@ -56,6 +56,9 @@ ##teamcity[testStarted name='variousTypes()' flowId='tst_Signaldumper'] ##teamcity[testStdOut name='variousTypes()' out='INFO: Signal: SignalSlotClass(_POINTER_) qStringSignal (QString(Test string))|nINFO: Signal: SignalSlotClass(_POINTER_) qStringRefSignal ((QString&)@_POINTER_)|nINFO: Signal: SignalSlotClass(_POINTER_) qStringConstRefSignal (QString(Test string))|nINFO: Signal: SignalSlotClass(_POINTER_) qByteArraySignal (QByteArray(Test bytearray))|nINFO: Signal: SignalSlotClass(_POINTER_) qListSignal (QList())|nINFO: Signal: SignalSlotClass(_POINTER_) qVectorSignal (QVector())|nINFO: Signal: SignalSlotClass(_POINTER_) qVectorRefSignal ((QVector&)@_POINTER_)|nINFO: Signal: SignalSlotClass(_POINTER_) qVectorConstRefSignal (QVector())|nINFO: Signal: SignalSlotClass(_POINTER_) qVectorConstPointerSignal ((const QVector*)_POINTER_)|nINFO: Signal: SignalSlotClass(_POINTER_) qVectorPointerConstSignal ()|nINFO: Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant())|nINFO: Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant())' flowId='tst_Signaldumper'] ##teamcity[testFinished name='variousTypes()' flowId='tst_Signaldumper'] +##teamcity[testStarted name='deletingSender()' flowId='tst_Signaldumper'] +##teamcity[testStdOut name='deletingSender()' out='INFO: Signal: SignalSlotClass(_POINTER_) signalWithoutParameters ()' flowId='tst_Signaldumper'] +##teamcity[testFinished name='deletingSender()' flowId='tst_Signaldumper'] ##teamcity[testStarted name='cleanupTestCase()' flowId='tst_Signaldumper'] ##teamcity[testFinished name='cleanupTestCase()' flowId='tst_Signaldumper'] ##teamcity[testSuiteFinished name='tst_Signaldumper' flowId='tst_Signaldumper'] diff --git a/tests/auto/testlib/selftests/expected_signaldumper.txt b/tests/auto/testlib/selftests/expected_signaldumper.txt index f89c31afe5..0ee8cd38a2 100644 --- a/tests/auto/testlib/selftests/expected_signaldumper.txt +++ b/tests/auto/testlib/selftests/expected_signaldumper.txt @@ -143,7 +143,9 @@ INFO : tst_Signaldumper::variousTypes() Signal: SignalSlotClass(_POINTER_) qVe INFO : tst_Signaldumper::variousTypes() Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant()) INFO : tst_Signaldumper::variousTypes() Signal: SignalSlotClass(_POINTER_) qVariantSignal (QVariant()) PASS : tst_Signaldumper::variousTypes() +INFO : tst_Signaldumper::deletingSender() Signal: SignalSlotClass(_POINTER_) signalWithoutParameters () +PASS : tst_Signaldumper::deletingSender() PASS : tst_Signaldumper::cleanupTestCase() -INFO : tst_Signaldumper::UnknownTestFunc() Signal: QThread(_POINTER_) finished () -Totals: 20 passed, 0 failed, 0 skipped, 0 blacklisted, 0ms +INFO : tst_Signaldumper::UnknownTestFunc() Signal: QThread(_POINTER_) finished () +Totals: 21 passed, 0 failed, 0 skipped, 0 blacklisted, 0ms ********* Finished testing of tst_Signaldumper ********* diff --git a/tests/auto/testlib/selftests/expected_signaldumper.xml b/tests/auto/testlib/selftests/expected_signaldumper.xml index 82959c62df..f11a0c3ce6 100644 --- a/tests/auto/testlib/selftests/expected_signaldumper.xml +++ b/tests/auto/testlib/selftests/expected_signaldumper.xml @@ -570,12 +570,19 @@ + + + + + + + - + diff --git a/tests/auto/testlib/selftests/expected_signaldumper.xunitxml b/tests/auto/testlib/selftests/expected_signaldumper.xunitxml index 930dc97262..cbf7075ba1 100644 --- a/tests/auto/testlib/selftests/expected_signaldumper.xunitxml +++ b/tests/auto/testlib/selftests/expected_signaldumper.xunitxml @@ -1,5 +1,5 @@ - + @@ -151,8 +151,11 @@ + + + - + @@ -279,6 +282,7 @@ - + + diff --git a/tests/auto/testlib/selftests/signaldumper/tst_signaldumper.cpp b/tests/auto/testlib/selftests/signaldumper/tst_signaldumper.cpp index f6cd0d510e..08592e222d 100644 --- a/tests/auto/testlib/selftests/signaldumper/tst_signaldumper.cpp +++ b/tests/auto/testlib/selftests/signaldumper/tst_signaldumper.cpp @@ -56,6 +56,8 @@ private slots: void slotEmittingSignalOldSyntax(); void variousTypes(); + + void deletingSender(); }; void tst_Signaldumper::addConnectionTypeData() @@ -413,5 +415,14 @@ void tst_Signaldumper::variousTypes() emit signalSlotOwner.qVariantSignal(variant); } +void tst_Signaldumper::deletingSender() +{ + SignalSlotClass *signalSlotOwner = new SignalSlotClass(); + connect(signalSlotOwner, &SignalSlotClass::signalWithoutParameters, [signalSlotOwner]() { + delete signalSlotOwner; + }); + emit signalSlotOwner->signalWithoutParameters(); +} + QTEST_MAIN(tst_Signaldumper) #include "tst_signaldumper.moc" From 6db83e2584a30b1339adba18279fbfd527a10ce7 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 23 Sep 2019 10:33:20 +0200 Subject: [PATCH 12/22] Fix crash with gamma-corrected text blending disabled Change-Id: I7e3ca78278bf8bf2dda44711eb57d64aa6f455ce Reviewed-by: Eirik Aavitsland --- src/gui/painting/qdrawhelper.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 3d06a27d8e..e5f752b94e 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -5670,7 +5670,8 @@ static inline void alphamapblend_argb32(quint32 *dst, int coverage, QRgba64 srcL QRgb s = *dst; blend_pixel(s, src); // Then gamma-corrected blend with glyph shape - grayBlendPixel(dst, coverage, colorProfile->toLinear64(s), colorProfile); + QRgba64 s64 = colorProfile ? colorProfile->toLinear64(s) : QRgba64::fromArgb32(s); + grayBlendPixel(dst, coverage, s64, colorProfile); } } @@ -5711,7 +5712,9 @@ static inline void alphamapblend_generic(int coverage, QRgba64 *dest, int x, con QRgba64 s = dest[x]; blend_pixel(s, src); // Then gamma-corrected blend with glyph shape - grayBlendPixel(dest[x], coverage, colorProfile->toLinear(s), colorProfile); + if (colorProfile) + s = colorProfile->toLinear(s); + grayBlendPixel(dest[x], coverage, s, colorProfile); } } @@ -6053,7 +6056,8 @@ static inline void alphargbblend_argb32(quint32 *dst, uint coverage, const QRgba QRgb s = *dst; blend_pixel(s, src); // Then gamma-corrected blend with glyph shape - rgbBlendPixel(dst, coverage, colorProfile->toLinear64(s), colorProfile); + QRgba64 s64 = colorProfile ? colorProfile->toLinear64(s) : QRgba64::fromArgb32(s); + rgbBlendPixel(dst, coverage, s64, colorProfile); } } @@ -6084,7 +6088,9 @@ static inline void alphargbblend_generic(uint coverage, QRgba64 *dest, int x, co QRgba64 s = dest[x]; blend_pixel(s, src); // Then gamma-corrected blend with glyph shape - rgbBlendPixel(dest[x], coverage, colorProfile->toLinear(s), colorProfile); + if (colorProfile) + s = colorProfile->toLinear(s); + rgbBlendPixel(dest[x], coverage, s, colorProfile); } } From 04dcc902eb64d94653a12005f3aedf32be1011c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 19 Sep 2019 18:09:52 +0200 Subject: [PATCH 13/22] macOS: Handle backing property changes in a single place Change-Id: I70d57632a1756f74249f64d4d4c405cb3120a179 Reviewed-by: Timur Pocheptsov --- src/plugins/platforms/cocoa/qcocoawindow.h | 1 - src/plugins/platforms/cocoa/qcocoawindow.mm | 11 ---------- .../platforms/cocoa/qnsview_drawing.mm | 20 +++++++++++-------- 3 files changed, 12 insertions(+), 20 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index c6ce6e6819..fef72bc496 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -161,7 +161,6 @@ public: Q_NOTIFICATION_HANDLER(NSWindowDidOrderOffScreenNotification) void windowDidOrderOffScreen(); Q_NOTIFICATION_HANDLER(NSWindowDidChangeOcclusionStateNotification) void windowDidChangeOcclusionState(); Q_NOTIFICATION_HANDLER(NSWindowDidChangeScreenNotification) void windowDidChangeScreen(); - Q_NOTIFICATION_HANDLER(NSWindowDidChangeBackingPropertiesNotification) void windowDidChangeBackingProperties(); Q_NOTIFICATION_HANDLER(NSWindowWillCloseNotification) void windowWillClose(); bool windowShouldClose(); diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index db4bc12210..35b7162346 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -1262,17 +1262,6 @@ void QCocoaWindow::windowDidChangeScreen() currentScreen->requestUpdate(); } } -/* - The window's backing scale factor or color space has changed. -*/ -void QCocoaWindow::windowDidChangeBackingProperties() -{ - // Ideally we would plumb this thought QPA in a way that lets clients - // invalidate their own caches, and recreate QBackingStore. For now we - // trigger an expose, and let QCocoaBackingStore deal with its own - // buffer invalidation. - [m_view setNeedsDisplay:YES]; -} void QCocoaWindow::windowWillClose() { diff --git a/src/plugins/platforms/cocoa/qnsview_drawing.mm b/src/plugins/platforms/cocoa/qnsview_drawing.mm index d2e6f848a0..de93e03685 100644 --- a/src/plugins/platforms/cocoa/qnsview_drawing.mm +++ b/src/plugins/platforms/cocoa/qnsview_drawing.mm @@ -211,17 +211,21 @@ - (void)viewDidChangeBackingProperties { - CALayer *layer = self.layer; - if (!layer) - return; + qCDebug(lcQpaDrawing) << "Backing properties changed for" << self; - layer.contentsScale = self.window.backingScaleFactor; + if (CALayer *layer = self.layer) { + layer.contentsScale = self.window.backingScaleFactor; - // Metal layers must be manually updated on e.g. screen change - if ([layer isKindOfClass:CAMetalLayer.class]) { - [self updateMetalLayerDrawableSize:static_cast(layer)]; - [self setNeedsDisplay:YES]; + // Metal layers must be manually updated on e.g. screen change + if ([layer isKindOfClass:CAMetalLayer.class]) + [self updateMetalLayerDrawableSize:static_cast(layer)]; } + + // Ideally we would plumb this situation through QPA in a way that lets + // clients invalidate their own caches, recreate QBackingStore, etc. + // For now we trigger an expose, and let QCocoaBackingStore deal with + // buffer invalidation internally. + [self setNeedsDisplay:YES]; } @end From 0642ca3528b1020acf1deadf8bf6d374c0db05f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 19 Sep 2019 18:15:18 +0200 Subject: [PATCH 14/22] macOS: Don't update Metal layer's drawableSize automatically MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Like our other rendering code paths, the Metal path should allow the user to resize their surface when they see fit. This is the case today with e.g QBackingStore::resize() and QOpenGLPaintDevice::setSize(). [ChangeLog][macOS] The drawableSize of Metal layers is no longer updated automatically on window resize or screen change. Update the size manually in response to resizeEvent(), or at the start of each frame, as needed. Change-Id: I9ed6d4326d0e0a3f4e3c63984d3b193e8bb77cae Reviewed-by: Morten Johan Sørvig --- .../platforms/cocoa/qnsview_drawing.mm | 23 ++----------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/src/plugins/platforms/cocoa/qnsview_drawing.mm b/src/plugins/platforms/cocoa/qnsview_drawing.mm index de93e03685..e72142466b 100644 --- a/src/plugins/platforms/cocoa/qnsview_drawing.mm +++ b/src/plugins/platforms/cocoa/qnsview_drawing.mm @@ -173,20 +173,6 @@ } #endif -- (void)updateMetalLayerDrawableSize:(CAMetalLayer *)layer -{ - CGSize drawableSize = layer.bounds.size; - drawableSize.width *= layer.contentsScale; - drawableSize.height *= layer.contentsScale; - layer.drawableSize = drawableSize; -} - -- (void)layoutSublayersOfLayer:(CALayer *)layer -{ - if ([layer isKindOfClass:CAMetalLayer.class]) - [self updateMetalLayerDrawableSize:static_cast(layer)]; -} - - (void)displayLayer:(CALayer *)layer { if (!NSThread.isMainThread) { @@ -213,13 +199,8 @@ { qCDebug(lcQpaDrawing) << "Backing properties changed for" << self; - if (CALayer *layer = self.layer) { - layer.contentsScale = self.window.backingScaleFactor; - - // Metal layers must be manually updated on e.g. screen change - if ([layer isKindOfClass:CAMetalLayer.class]) - [self updateMetalLayerDrawableSize:static_cast(layer)]; - } + if (self.layer) + self.layer.contentsScale = self.window.backingScaleFactor; // Ideally we would plumb this situation through QPA in a way that lets // clients invalidate their own caches, recreate QBackingStore, etc. From 2dfeea921b8ac9fef92db8fab7b518f3f5994512 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Mon, 23 Sep 2019 13:48:30 +0200 Subject: [PATCH 15/22] Avoid unused parameter 'grab' warnings Android (5220042 based on r346389c) clang version 8.0.7: src/plugins/platforms/android/qandroidplatformwindow.h:68:35: error: unused parameter 'grab' [-Werror,-Wunused-parameter] bool setMouseGrabEnabled(bool grab) override { return false; } ^ src/plugins/platforms/android/qandroidplatformwindow.h:69:38: error: unused parameter 'grab' [-Werror,-Wunused-parameter] bool setKeyboardGrabEnabled(bool grab) override { return false; } ^ Change-Id: I4d8a18d5e3bfbc13c05b47f0cdfe10370673e359 Reviewed-by: Ville Voutilainen --- src/plugins/platforms/android/qandroidplatformwindow.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/android/qandroidplatformwindow.h b/src/plugins/platforms/android/qandroidplatformwindow.h index 5edd274759..d8eb6b7b7f 100644 --- a/src/plugins/platforms/android/qandroidplatformwindow.h +++ b/src/plugins/platforms/android/qandroidplatformwindow.h @@ -65,8 +65,8 @@ public: void setParent(const QPlatformWindow *window) override; WId winId() const override { return m_windowId; } - bool setMouseGrabEnabled(bool grab) override { return false; } - bool setKeyboardGrabEnabled(bool grab) override { return false; } + bool setMouseGrabEnabled(bool grab) override { Q_UNUSED(grab); return false; } + bool setKeyboardGrabEnabled(bool grab) override { Q_UNUSED(grab); return false; } QAndroidPlatformScreen *platformScreen() const; From 35aec918c15d50893dd4e403e400f37e6a2d7c6f Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 18 Sep 2019 11:32:50 +0200 Subject: [PATCH 16/22] Rearrange tst_QNumeric's tests for infinity and (quiet) NaN Separate quiet NaN from infinity and expand the nan-with-payload test to a general test that bits outside the exponent don't break qIsNan(). Generally test more thoroughly and systematically. Tests for signalling NaN shall follow. Change-Id: Ib35dabacc8ebcc9a0761df38f6f419f0398d0e20 Reviewed-by: Erik Verbruggen --- .../corelib/global/qnumeric/tst_qnumeric.cpp | 118 +++++++++++++----- 1 file changed, 88 insertions(+), 30 deletions(-) diff --git a/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp b/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp index 0a84b1fdd8..5697d21547 100644 --- a/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp +++ b/tests/auto/corelib/global/qnumeric/tst_qnumeric.cpp @@ -42,7 +42,11 @@ class tst_QNumeric: public QObject private slots: void fuzzyCompare_data(); void fuzzyCompare(); - void qNanInf(); + void rawNaN_data(); + void rawNaN(); + void generalNaN_data(); + void generalNaN(); + void infinity(); void classifyfp(); void floatDistance_data(); void floatDistance(); @@ -53,6 +57,8 @@ private slots: void mulOverflow_data(); void mulOverflow(); void signedOverflow(); +private: + void checkNaN(double nan); }; void tst_QNumeric::fuzzyCompare_data() @@ -92,44 +98,89 @@ void tst_QNumeric::fuzzyCompare() # pragma GCC optimize "no-fast-math" #endif -void tst_QNumeric::qNanInf() +void tst_QNumeric::checkNaN(double nan) { -#if defined __FAST_MATH__ && (__GNUC__ * 100 + __GNUC_MINOR__ < 404) - QSKIP("Non-conformant fast math mode is enabled, cannot run test"); -#endif - double nan = qQNaN(); +#define CHECKNAN(value) \ + do { \ + const double v = (value); \ + QCOMPARE(qFpClassify(v), FP_NAN); \ + QVERIFY(qIsNaN(v)); \ + QVERIFY(!qIsFinite(v)); \ + QVERIFY(!qIsInf(v)); \ + } while (0) + QVERIFY(!(0 > nan)); QVERIFY(!(0 < nan)); QVERIFY(!(0 == nan)); QVERIFY(!(nan == nan)); - QVERIFY(qIsNaN(nan)); - QVERIFY(qIsNaN(nan + 1)); - QVERIFY(qIsNaN(-nan)); - QVERIFY(qIsNaN(1.0 / nan)); - QVERIFY(qIsNaN(0.0 / nan)); - QVERIFY(qIsNaN(0.0 * nan)); - QCOMPARE(nan, nan); - QCOMPARE(nan, -nan); - Q_STATIC_ASSERT(sizeof(double) == 8); -#ifdef Q_LITTLE_ENDIAN - const uchar bytes[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f }; -#else - const uchar bytes[] = { 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }; -#endif - memcpy(&nan, bytes, 8); - QVERIFY(!qIsFinite(nan)); - QVERIFY(!qIsInf(nan)); - QVERIFY(qIsNaN(nan)); - QVERIFY(qIsNaN(-nan)); - QVERIFY(!(nan == nan)); - QVERIFY(qIsNaN(0.0 * nan)); - QCOMPARE(qFpClassify(nan), FP_NAN); + CHECKNAN(nan); + CHECKNAN(nan + 1); + CHECKNAN(nan - 1); + CHECKNAN(-nan); + CHECKNAN(nan * 2.0); + CHECKNAN(nan / 2.0); + CHECKNAN(1.0 / nan); + CHECKNAN(0.0 / nan); + CHECKNAN(0.0 * nan); + + // When any NaN is expected, any NaN will do: QCOMPARE(nan, nan); QCOMPARE(nan, -nan); QCOMPARE(nan, qQNaN()); +#undef CHECKNAN +} - double inf = qInf(); +void tst_QNumeric::rawNaN_data() +{ +#if defined __FAST_MATH__ && (__GNUC__ * 100 + __GNUC_MINOR__ < 404) + QSKIP("Non-conformant fast math mode is enabled, cannot run test"); +#endif + QTest::addColumn("nan"); + + QTest::newRow("quiet") << qQNaN(); +} + +void tst_QNumeric::rawNaN() +{ + QFETCH(double, nan); + checkNaN(nan); +} + +void tst_QNumeric::generalNaN_data() +{ + QTest::addColumn("most"); + QTest::addColumn("next"); + QTest::addColumn("least"); + // Every value with every bit of the exponent set is a NaN. + // Sign and mantissa can be anything without interfering with that. + // The 0x7f bits of most and the 0xf0 bits of next are the exponent. + + QTest::newRow("lowload") << 0x7f << 0xf0 << 1; + QTest::newRow("sign-lowload") << 0xff << 0xf0 << 1; + QTest::newRow("highload") << 0x7f << 0xf1 << 0; + QTest::newRow("sign-highload") << 0xff << 0xf1 << 0; +} + +void tst_QNumeric::generalNaN() +{ + QFETCH(int, most); + QFETCH(int, next); + QFETCH(int, least); + double nan; + Q_STATIC_ASSERT(sizeof(double) == 8); +#ifdef Q_LITTLE_ENDIAN + const uchar bytes[] = { uchar(least), 0, 0, 0, 0, 0, uchar(next), uchar(most) }; +#else + const uchar bytes[] = { uchar(most), uchar(next), 0, 0, 0, 0, 0, uchar(least) }; +#endif + memcpy(&nan, bytes, 8); + checkNaN(nan); +} + +void tst_QNumeric::infinity() +{ + const double inf = qInf(); QVERIFY(inf > 0); QVERIFY(-inf < 0); QVERIFY(qIsInf(inf)); @@ -138,16 +189,23 @@ void tst_QNumeric::qNanInf() QVERIFY(qIsInf(-inf)); QVERIFY(qIsInf(inf + 1)); QVERIFY(qIsInf(inf - 1)); + QVERIFY(qIsInf(-inf - 1)); + QVERIFY(qIsInf(-inf + 1)); QVERIFY(qIsInf(inf * 2.0)); + QVERIFY(qIsInf(-inf * 2.0)); QVERIFY(qIsInf(inf / 2.0)); + QVERIFY(qIsInf(-inf / 2.0)); QVERIFY(qFuzzyCompare(1.0 / inf, 0.0)); QCOMPARE(1.0 / inf, 0.0); + QVERIFY(qFuzzyCompare(1.0 / -inf, 0.0)); + QCOMPARE(1.0 / -inf, 0.0); QVERIFY(qIsNaN(0.0 * inf)); + QVERIFY(qIsNaN(0.0 * -inf)); } void tst_QNumeric::classifyfp() { - QCOMPARE(qFpClassify(qQNaN()), FP_NAN); + // NaNs already handled, see checkNaN()'s callers. QCOMPARE(qFpClassify(qInf()), FP_INFINITE); QCOMPARE(qFpClassify(-qInf()), FP_INFINITE); From b8d8e0dfbbf721604eaa340b3bc47e5a574228fb Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 20 Sep 2019 15:58:02 +0200 Subject: [PATCH 17/22] Follow platform plugin change wrt layer size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Have to set the drawableSize ourselves. This is not yet fully correct in the sense that does not ensure what the platform plugin patch tries to enable, namely atomic frames when it comes to the drawable size. Going to fix that up in separate patches, maybe it will need some QRhi API changes as well so won't mix that in here. Change-Id: I47a3816930bc6a87a2c96d4a6c4c85b2577147dc Reviewed-by: Tor Arne Vestbø --- src/gui/rhi/qrhimetal.mm | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm index 0b1ab72c2c..bfd6944cdb 100644 --- a/src/gui/rhi/qrhimetal.mm +++ b/src/gui/rhi/qrhimetal.mm @@ -3524,7 +3524,10 @@ QSize QMetalSwapChain::surfacePixelSize() if (v) { CAMetalLayer *layer = (CAMetalLayer *) [v layer]; if (layer) { - CGSize size = [layer drawableSize]; + CGSize size = layer.bounds.size; + size.width *= layer.contentsScale; + size.height *= layer.contentsScale; + layer.drawableSize = size; return QSize(int(size.width), int(size.height)); } } From 22742c5f21ba5d9396c08d40c2f4471ae3382387 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Thu, 19 Sep 2019 13:51:27 +0200 Subject: [PATCH 18/22] Include missing shbang line in executable shell script Change-Id: I802665c89fcac9e07e745cf6dce1a04404ae764d Reviewed-by: Laszlo Agocs --- tests/manual/rhi/shadowmap/buildshaders.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/manual/rhi/shadowmap/buildshaders.sh b/tests/manual/rhi/shadowmap/buildshaders.sh index c4d17841e6..8991bb074a 100755 --- a/tests/manual/rhi/shadowmap/buildshaders.sh +++ b/tests/manual/rhi/shadowmap/buildshaders.sh @@ -1,3 +1,4 @@ +#!/bin/sh qsb --glsl "120,300 es" --hlsl 50 --msl 12 shadowmap.vert -o shadowmap.vert.qsb qsb --glsl "120,300 es" --hlsl 50 --msl 12 shadowmap.frag -o shadowmap.frag.qsb qsb --glsl "120,300 es" --hlsl 50 --msl 12 main.vert -o main.vert.qsb From da46ea92e537501c932343f65e11032a2f5984f3 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 11 Sep 2019 09:40:17 +0200 Subject: [PATCH 19/22] doc: add a note to QFileSystemWatcher about files saved by re-creation Fixes: QTBUG-46483 Fixes: QTBUG-53607 Change-Id: I434f177b35689d55aa1deea360bf7e6ae009ad68 Reviewed-by: Venugopal Shivashankar --- src/corelib/io/qfilesystemwatcher.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp index a4705136a2..54460aff77 100644 --- a/src/corelib/io/qfilesystemwatcher.cpp +++ b/src/corelib/io/qfilesystemwatcher.cpp @@ -451,6 +451,12 @@ QStringList QFileSystemWatcher::removePaths(const QStringList &paths) This signal is emitted when the file at the specified \a path is modified, renamed or removed from disk. + \note As a safety measure, many applications save an open file by + writing a new file and then deleting the old one. In your slot + function, you can check \c watcher.files().contains(path). + If it returns \c false, check whether the file still exists + and then call \c addPath() to continue watching it. + \sa directoryChanged() */ From 1d1ed017119df2cd28a9e21aee0a8cece5282250 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 20 Sep 2019 14:28:49 +0200 Subject: [PATCH 20/22] Xcode: Ensure there's always a CFBundle[Short]Version[String] set Leaving it empty resulted in errors from Xcode when compiling the app. Task-number: QTBUG-25309 Task-number: QTBUG-74872 Change-Id: I61b0f47d754c5f5b181a6f918283d990458cc78d Reviewed-by: Joerg Bornemann --- mkspecs/features/mac/default_post.prf | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/mkspecs/features/mac/default_post.prf b/mkspecs/features/mac/default_post.prf index 26bd3e2e98..993f4d56a9 100644 --- a/mkspecs/features/mac/default_post.prf +++ b/mkspecs/features/mac/default_post.prf @@ -97,21 +97,22 @@ macx-xcode { qmake_pkginfo_typeinfo.value = "????" QMAKE_MAC_XCODE_SETTINGS += qmake_pkginfo_typeinfo - !isEmpty(VERSION) { - l = $$split(VERSION, '.') 0 0 # make sure there are at least three - VER_MAJ = $$member(l, 0, 0) - VER_MIN = $$member(l, 1, 1) - VER_PAT = $$member(l, 2, 2) - unset(l) + bundle_version = $$VERSION + isEmpty(bundle_version): bundle_version = 1.0.0 - qmake_full_version.name = QMAKE_FULL_VERSION - qmake_full_version.value = $${VER_MAJ}.$${VER_MIN}.$${VER_PAT} - QMAKE_MAC_XCODE_SETTINGS += qmake_full_version + l = $$split(bundle_version, '.') 0 0 # make sure there are at least three + VER_MAJ = $$member(l, 0, 0) + VER_MIN = $$member(l, 1, 1) + VER_PAT = $$member(l, 2, 2) + unset(l) - qmake_short_version.name = QMAKE_SHORT_VERSION - qmake_short_version.value = $${VER_MAJ}.$${VER_MIN} - QMAKE_MAC_XCODE_SETTINGS += qmake_short_version - } + qmake_full_version.name = QMAKE_FULL_VERSION + qmake_full_version.value = $${VER_MAJ}.$${VER_MIN}.$${VER_PAT} + QMAKE_MAC_XCODE_SETTINGS += qmake_full_version + + qmake_short_version.name = QMAKE_SHORT_VERSION + qmake_short_version.value = $${VER_MAJ}.$${VER_MIN} + QMAKE_MAC_XCODE_SETTINGS += qmake_short_version !isEmpty(QMAKE_XCODE_DEBUG_INFORMATION_FORMAT) { debug_information_format.name = DEBUG_INFORMATION_FORMAT From 70c053ee684448984b1f762abd3b40884cece2fa Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Fri, 20 Sep 2019 22:27:44 +0200 Subject: [PATCH 21/22] QAbstractSpinBox css: properly honor spincontrol-disable-on-bounds The css style 'spincontrol-disable-on-bounds' was not properly honored within QAbstractSpinBox::initStyleOption() because the affected widget was not passed to QStyle::styleHint(). Therefore QStyleSheetStyle did not find the correct render rule. Fix it by passing 'this' as third argument to QStyle::styleHint(). Fixes: QTBUG-18008 Change-Id: Iabcebf0b83143f45309b4e7066bccb8d20bd0419 Reviewed-by: Eirik Aavitsland --- src/widgets/widgets/qabstractspinbox.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/widgets/qabstractspinbox.cpp b/src/widgets/widgets/qabstractspinbox.cpp index d49d9dbd66..fc19e0793e 100644 --- a/src/widgets/widgets/qabstractspinbox.cpp +++ b/src/widgets/widgets/qabstractspinbox.cpp @@ -1726,7 +1726,7 @@ void QAbstractSpinBox::initStyleOption(QStyleOptionSpinBox *option) const option->activeSubControls = d->hoverControl; } - option->stepEnabled = style()->styleHint(QStyle::SH_SpinControls_DisableOnBounds) + option->stepEnabled = style()->styleHint(QStyle::SH_SpinControls_DisableOnBounds, nullptr, this) ? stepEnabled() : (QAbstractSpinBox::StepDownEnabled|QAbstractSpinBox::StepUpEnabled); From 0c15cf66a4224714b57085c2f2a84455f242d0d6 Mon Sep 17 00:00:00 2001 From: Christian Ehrlicher Date: Sun, 8 Sep 2019 20:04:02 +0200 Subject: [PATCH 22/22] tst_QListWidget: cleanup Cleanup QTreeWidget autotest: - use range-based for loops - use nullptr - use member initialization - use new signal/slot syntax - use static invocations - use override Change-Id: Ied5c0b12c0d3338469e50f3b30892557c9b4479d Reviewed-by: Edward Welbourne --- .../itemviews/qlistwidget/tst_qlistwidget.cpp | 444 ++++++++---------- 1 file changed, 204 insertions(+), 240 deletions(-) diff --git a/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp b/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp index fe2ede4183..befb45e683 100644 --- a/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp +++ b/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp @@ -26,22 +26,23 @@ ** ****************************************************************************/ - -#include -#include -#include -#include +#include +#include +#include +#include #include - -#include +#include +#include #include +using IntList = QVector; + class tst_QListWidget : public QObject { Q_OBJECT public: - tst_QListWidget(); + tst_QListWidget() = default; enum ModelChanged { RowsAboutToBeInserted, @@ -144,13 +145,18 @@ protected slots: void columnsRemoved(const QModelIndex &parent, int first, int last) { modelChanged(ColumnsRemoved, parent, first, last); } - void modelChanged(ModelChanged change, const QModelIndex &parent, int first, int last); + void modelChanged(ModelChanged change, const QModelIndex &parent, int first, int last) + { + rcParent[change] = parent; + rcFirst[change] = first; + rcLast[change] = last; + } private: - QListWidget *testWidget; - QVector rcParent; - QVector rcFirst; - QVector rcLast; + QListWidget *testWidget = nullptr; + QVector rcParent{8}; + QVector rcFirst = QVector(8, 0); + QVector rcLast = QVector(8, 0); void populate(); void checkDefaultValues(); @@ -168,7 +174,7 @@ void tst_QListWidget::moveRowsInvalid_data() const auto createWidget = []() -> QListWidget* { QListWidget* result = new QListWidget; - result->addItems(QStringList{"A", "B", "C", "D", "E", "F"}); + result->addItems({"A", "B", "C", "D", "E", "F"}); return result; }; @@ -259,35 +265,32 @@ void tst_QListWidget::moveRows() } -typedef QList IntList; - -tst_QListWidget::tst_QListWidget(): testWidget(0), rcParent(8), rcFirst(8,0), rcLast(8,0) -{ -} - void tst_QListWidget::initTestCase() { qRegisterMetaType("QListWidgetItem*"); - testWidget = new QListWidget(); + qRegisterMetaType>("QList"); + qRegisterMetaType("QAbstractItemModel::LayoutChangeHint"); + + testWidget = new QListWidget; testWidget->show(); - connect(testWidget->model(), SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(rowsAboutToBeInserted(QModelIndex,int,int))); - connect(testWidget->model(), SIGNAL(rowsInserted(QModelIndex,int,int)), - this, SLOT(rowsInserted(QModelIndex,int,int))); - connect(testWidget->model(), SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int))); - connect(testWidget->model(), SIGNAL(rowsRemoved(QModelIndex,int,int)), - this, SLOT(rowsRemoved(QModelIndex,int,int))); + connect(testWidget->model(), &QAbstractItemModel::rowsAboutToBeInserted, + this, &tst_QListWidget::rowsAboutToBeInserted); + connect(testWidget->model(), &QAbstractItemModel::rowsInserted, + this, &tst_QListWidget::rowsInserted); + connect(testWidget->model(), &QAbstractItemModel::rowsAboutToBeRemoved, + this, &tst_QListWidget::rowsAboutToBeRemoved); + connect(testWidget->model(), &QAbstractItemModel::rowsRemoved, + this, &tst_QListWidget::rowsRemoved); - connect(testWidget->model(), SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(columnsAboutToBeInserted(QModelIndex,int,int))); - connect(testWidget->model(), SIGNAL(columnsInserted(QModelIndex,int,int)), - this, SLOT(columnsInserted(QModelIndex,int,int))); - connect(testWidget->model(), SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(columnsAboutToBeRemoved(QModelIndex,int,int))); - connect(testWidget->model(), SIGNAL(columnsRemoved(QModelIndex,int,int)), - this, SLOT(columnsRemoved(QModelIndex,int,int))); + connect(testWidget->model(), &QAbstractItemModel::columnsAboutToBeInserted, + this, &tst_QListWidget::columnsAboutToBeInserted); + connect(testWidget->model(), &QAbstractItemModel::columnsInserted, + this, &tst_QListWidget::columnsInserted); + connect(testWidget->model(), &QAbstractItemModel::columnsAboutToBeRemoved, + this, &tst_QListWidget::columnsAboutToBeRemoved); + connect(testWidget->model(), &QAbstractItemModel::columnsRemoved, + this, &tst_QListWidget::columnsRemoved); checkDefaultValues(); } @@ -300,7 +303,7 @@ void tst_QListWidget::cleanupTestCase() void tst_QListWidget::init() { testWidget->clear(); - QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); + QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); } void tst_QListWidget::checkDefaultValues() @@ -317,7 +320,7 @@ void tst_QListWidget::populate() addItems(); setItemHidden(); - testWidget->setCurrentIndex(testWidget->model()->index(0,0)); + testWidget->setCurrentIndex(testWidget->model()->index(0, 0)); // setCurrentItem(); // setCurrentRow(); @@ -329,7 +332,7 @@ void tst_QListWidget::addItem() const QString label = QString::number(count); testWidget->addItem(label); QCOMPARE(testWidget->count(), ++count); - QCOMPARE(testWidget->item(testWidget->count()-1)->text(), label); + QCOMPARE(testWidget->item(testWidget->count() - 1)->text(), label); } void tst_QListWidget::addItem2() @@ -337,7 +340,7 @@ void tst_QListWidget::addItem2() int count = testWidget->count(); // Boundary Checking - testWidget->addItem(0); + testWidget->addItem(nullptr); QCOMPARE(testWidget->count(), count); QListWidgetItem *item = new QListWidgetItem(QString::number(count)); @@ -356,12 +359,11 @@ void tst_QListWidget::addItems() testWidget->addItems(QStringList()); QCOMPARE(testWidget->count(), count); - QStringList stringList; QString label = QString::number(count); - stringList << QString::number(testWidget->count() + 1) - << QString::number(testWidget->count() + 2) - << QString::number(testWidget->count() + 3) - << label; + const QStringList stringList{QString::number(testWidget->count() + 1), + QString::number(testWidget->count() + 2), + QString::number(testWidget->count() + 3), + label}; testWidget->addItems(stringList); QCOMPARE(testWidget->count(), count + stringList.count()); QCOMPARE(testWidget->item(testWidget->count()-1)->text(), label); @@ -371,7 +373,7 @@ void tst_QListWidget::addItems() void tst_QListWidget::openPersistentEditor() { // Boundary checking - testWidget->openPersistentEditor(0); + testWidget->openPersistentEditor(nullptr); QListWidgetItem *item = new QListWidgetItem(QString::number(testWidget->count())); testWidget->openPersistentEditor(item); @@ -385,7 +387,7 @@ void tst_QListWidget::closePersistentEditor() { // Boundary checking int childCount = testWidget->viewport()->children().count(); - testWidget->closePersistentEditor(0); + testWidget->closePersistentEditor(nullptr); QListWidgetItem *item = new QListWidgetItem(QString::number(testWidget->count())); testWidget->closePersistentEditor(item); QCOMPARE(childCount, testWidget->viewport()->children().count()); @@ -397,7 +399,7 @@ void tst_QListWidget::closePersistentEditor() // actual test childCount = testWidget->viewport()->children().count(); testWidget->closePersistentEditor(item); - QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); + QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete); QCOMPARE(testWidget->viewport()->children().count(), childCount - 1); } @@ -412,40 +414,33 @@ QT_WARNING_DISABLE_DEPRECATED QT_WARNING_POP #endif - int totalHidden = 0; - for (int i = 0; i < testWidget->model()->rowCount(); ++i) - if (testWidget->item(i)->isHidden()) - totalHidden++; - + auto countHidden = [](QListWidget *testWidget) + { + int totalHidden = 0; + for (int i = 0; i < testWidget->model()->rowCount(); ++i) { + if (testWidget->item(i)->isHidden()) + totalHidden++; + } + return totalHidden; + }; + const int totalHidden = countHidden(testWidget); QListWidgetItem *item = new QListWidgetItem(QString::number(testWidget->count())); testWidget->addItem(item); // Check that nothing else changed - int newTotal = 0; - for (int i = 0; i < testWidget->model()->rowCount(); ++i) - if (testWidget->item(i)->isHidden()) - newTotal++; - QCOMPARE(newTotal, totalHidden); + QCOMPARE(countHidden(testWidget), totalHidden); item->setHidden(true); QCOMPARE(item->isHidden(), true); // Check that nothing else changed - newTotal = 0; - for (int i = 0; i < testWidget->model()->rowCount(); ++i) - if (testWidget->item(i)->isHidden()) - newTotal++; - QCOMPARE(newTotal, totalHidden + 1); + QCOMPARE(countHidden(testWidget), totalHidden + 1); item->setHidden(false); QCOMPARE(item->isHidden(), false); // Check that nothing else changed - newTotal = 0; - for (int i = 0; i < testWidget->model()->rowCount(); ++i) - if (testWidget->item(i)->isHidden()) - newTotal++; - QCOMPARE(newTotal, totalHidden); + QCOMPARE(countHidden(testWidget), totalHidden); item->setHidden(true); } @@ -466,11 +461,11 @@ void tst_QListWidget::setCurrentItem() testWidget->addItem(QString::number(i)); // Boundary checking - testWidget->setCurrentItem((QListWidgetItem *)0); - QCOMPARE((QListWidgetItem *)0, testWidget->currentItem()); + testWidget->setCurrentItem(nullptr); + QVERIFY(!testWidget->currentItem()); QListWidgetItem item; testWidget->setCurrentItem(&item); - QCOMPARE((QListWidgetItem *)0, testWidget->currentItem()); + QVERIFY(!testWidget->currentItem()); // Make sure that currentItem changes to what is passed into setCurrentItem for (int i = 0; i < testWidget->count(); ++i) { @@ -555,7 +550,7 @@ void tst_QListWidget::editItem_data() void tst_QListWidget::editItem() { // Boundary checking - testWidget->editItem(0); + testWidget->editItem(nullptr); QListWidgetItem *item = new QListWidgetItem(QString::number(testWidget->count())); testWidget->editItem(item); @@ -593,8 +588,8 @@ void tst_QListWidget::findItems() populate(); - for (int i=0; i < testWidget->count(); ++i) - QCOMPARE(testWidget->findItems( (testWidget->item(i)->text()), Qt::MatchExactly).count(), 1); + for (int i = 0; i < testWidget->count(); ++i) + QCOMPARE(testWidget->findItems(testWidget->item(i)->text(), Qt::MatchExactly).count(), 1); } @@ -605,8 +600,7 @@ void tst_QListWidget::insertItem_data() QTest::addColumn("itemLabel"); QTest::addColumn("expectedIndex"); - QStringList initialItems; - initialItems << "foo" << "bar"; + const QStringList initialItems{"foo", "bar"}; QTest::newRow("Insert less then 0") << initialItems << -1 << "inserted" << 0; QTest::newRow("Insert at 0") << initialItems << 0 << "inserted" << 0; @@ -669,7 +663,7 @@ void tst_QListWidget::insertItems() if (insertType == 3) { QStringList strings; - for (int i=0; iinsertItems(0, strings); } else { @@ -685,7 +679,7 @@ void tst_QListWidget::insertItems() testWidget->insertItem(r, QString::number(r)); } else if (insertType == 3) { QStringList strings; - for (int i=0; iinsertItems(0, strings); break; @@ -702,7 +696,7 @@ void tst_QListWidget::insertItems() QCOMPARE(testWidget->item(r)->text(), QString::number(r)); // make sure all items have view set correctly - for (int i=0; icount(); ++i) + for (int i = 0; i < testWidget->count(); ++i) QCOMPARE(testWidget->item(i)->listWidget(), testWidget); QCOMPARE(itemChangedSpy.count(), 0); @@ -845,19 +839,19 @@ void tst_QListWidget::selectedItems_data() void tst_QListWidget::selectedItems() { QFETCH(int, itemCount); - QFETCH(IntList, hiddenRows); - QFETCH(IntList, selectedRows); - QFETCH(IntList, expectedRows); + QFETCH(const IntList, hiddenRows); + QFETCH(const IntList, selectedRows); + QFETCH(const IntList, expectedRows); QCOMPARE(testWidget->count(), 0); //insert items - for (int i=0; isetSelectionMode(QListWidget::SingleSelection); - for (int i=0; iitem(i); item->setSelected(true); QVERIFY(item->isSelected()); @@ -871,20 +865,20 @@ void tst_QListWidget::selectedItems() //verify items are inserted QCOMPARE(testWidget->count(), itemCount); // hide items - foreach (int row, hiddenRows) + for (int row : hiddenRows) testWidget->item(row)->setHidden(true); // select items - foreach (int row, selectedRows) + for (int row : selectedRows) testWidget->item(row)->setSelected(true); // check that the correct number of items and the expected items are there QList selectedItems = testWidget->selectedItems(); QCOMPARE(selectedItems.count(), expectedRows.count()); - foreach (int row, expectedRows) + for (int row : expectedRows) QVERIFY(selectedItems.contains(testWidget->item(row))); //check that isSelected agrees with selectedItems - for (int i=0; iitem(i); if (item->isSelected()) QVERIFY(selectedItems.contains(item)); @@ -927,8 +921,6 @@ void tst_QListWidget::removeItems() QCOMPARE(testWidget->item(r)->text(), QString::number(r)); else QCOMPARE(testWidget->item(r)->text(), QString::number(r + removeRows)); - - } void tst_QListWidget::moveItemsPriv_data() @@ -967,8 +959,8 @@ void tst_QListWidget::moveItemsPriv() QListModel *model = qobject_cast(testWidget->model()); QVERIFY(model); - QSignalSpy beginMoveSpy(model, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int))); - QSignalSpy movedSpy(model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int))); + QSignalSpy beginMoveSpy(model, &QAbstractItemModel::rowsAboutToBeMoved); + QSignalSpy movedSpy(model, &QAbstractItemModel::rowsMoved); model->move(srcRow, dstRow); if (shouldHaveSignaled) { @@ -1034,31 +1026,31 @@ void tst_QListWidget::itemStreaming() void tst_QListWidget::sortItems_data() { - QTest::addColumn("order"); + QTest::addColumn("order"); QTest::addColumn("initialList"); QTest::addColumn("expectedList"); QTest::addColumn("expectedRows"); QTest::newRow("ascending strings") - << static_cast(Qt::AscendingOrder) + << Qt::AscendingOrder << (QVariantList() << QString("c") << QString("d") << QString("a") << QString("b")) << (QVariantList() << QString("a") << QString("b") << QString("c") << QString("d")) << (IntList() << 2 << 3 << 0 << 1); QTest::newRow("descending strings") - << static_cast(Qt::DescendingOrder) + << Qt::DescendingOrder << (QVariantList() << QString("c") << QString("d") << QString("a") << QString("b")) << (QVariantList() << QString("d") << QString("c") << QString("b") << QString("a")) << (IntList() << 1 << 0 << 3 << 2); QTest::newRow("ascending numbers") - << static_cast(Qt::AscendingOrder) + << Qt::AscendingOrder << (QVariantList() << 1 << 11 << 2 << 22) << (QVariantList() << 1 << 2 << 11 << 22) << (IntList() << 0 << 2 << 1 << 3); QTest::newRow("descending numbers") - << static_cast(Qt::DescendingOrder) + << Qt::DescendingOrder << (QVariantList() << 1 << 11 << 2 << 22) << (QVariantList() << 22 << 11 << 2 << 1) << (IntList() << 3 << 1 << 2 << 0); @@ -1066,22 +1058,22 @@ void tst_QListWidget::sortItems_data() void tst_QListWidget::sortItems() { - QFETCH(int, order); - QFETCH(QVariantList, initialList); - QFETCH(QVariantList, expectedList); - QFETCH(IntList, expectedRows); + QFETCH(Qt::SortOrder, order); + QFETCH(const QVariantList, initialList); + QFETCH(const QVariantList, expectedList); + QFETCH(const IntList, expectedRows); - foreach (const QVariant &data, initialList) { + for (const QVariant &data : initialList) { QListWidgetItem *item = new QListWidgetItem(testWidget); item->setData(Qt::DisplayRole, data); } QAbstractItemModel *model = testWidget->model(); - QList persistent; + QVector persistent; for (int j = 0; j < model->rowCount(QModelIndex()); ++j) persistent << model->index(j, 0, QModelIndex()); - testWidget->sortItems(static_cast(order)); + testWidget->sortItems(order); QCOMPARE(testWidget->count(), expectedList.count()); for (int i = 0; i < testWidget->count(); ++i) @@ -1093,7 +1085,7 @@ void tst_QListWidget::sortItems() void tst_QListWidget::sortHiddenItems_data() { - QTest::addColumn("order"); + QTest::addColumn("order"); QTest::addColumn("initialList"); QTest::addColumn("expectedList"); QTest::addColumn("expectedRows"); @@ -1110,21 +1102,21 @@ void tst_QListWidget::sortHiddenItems_data() } QTest::newRow("descending order, 20 items") - << static_cast(Qt::DescendingOrder) + << Qt::DescendingOrder << initial << expected << rowOrder << visible; QTest::newRow("ascending order") - << static_cast(Qt::AscendingOrder) + << Qt::AscendingOrder << (QStringList() << "c" << "d" << "a" << "b") << (QStringList() << "a" << "b" << "c" << "d") << (IntList() << 2 << 3 << 0 << 1) << (IntList() << 1 << 0 << 1 << 0); QTest::newRow("descending order") - << static_cast(Qt::DescendingOrder) + << Qt::DescendingOrder << (QStringList() << "c" << "d" << "a" << "b") << (QStringList() << "d" << "c" << "b" << "a") << (IntList() << 1 << 0 << 3 << 2) @@ -1133,7 +1125,7 @@ void tst_QListWidget::sortHiddenItems_data() void tst_QListWidget::sortHiddenItems() { - QFETCH(int, order); + QFETCH(Qt::SortOrder, order); QFETCH(QStringList, initialList); QFETCH(QStringList, expectedList); QFETCH(IntList, expectedRows); @@ -1144,14 +1136,14 @@ void tst_QListWidget::sortHiddenItems() tw->addItems(initialList); QAbstractItemModel *model = tw->model(); - QList persistent; + QVector persistent; for (int j = 0; j < model->rowCount(QModelIndex()); ++j) { persistent << model->index(j, 0, QModelIndex()); tw->setRowHidden(j, j & 1); // every odd is hidden } tw->setSortingEnabled(true); - tw->sortItems(static_cast(order)); + tw->sortItems(order); QCOMPARE(tw->count(), expectedList.count()); for (int i = 0; i < tw->count(); ++i) { @@ -1165,50 +1157,35 @@ void tst_QListWidget::sortHiddenItems() delete tw; } -void tst_QListWidget::modelChanged(ModelChanged change, const QModelIndex &parent, - int first, int last) +class TestListWidget : public QListWidget { - rcParent[change] = parent; - rcFirst[change] = first; - rcLast[change] = last; -} - -class TestListWidget : public QListWidget { + Q_OBJECT public: - TestListWidget() : QListWidget() - { - - } - State getState() {return QListWidget::state();} - - void closeEditor(QWidget *w, QAbstractItemDelegate::EndEditHint hint) { - QListWidget::closeEditor(w, hint); - } - - bool isEditingState(QListWidgetItem *item) { - Q_UNUSED(item); - return QListWidget::state() == QListWidget::EditingState; - } - + using QListWidget::QListWidget; + using QListWidget::state; + using QListWidget::closeEditor; using QListWidget::mimeData; using QListWidget::indexFromItem; + + bool isEditingState() const { + return QListWidget::state() == QListWidget::EditingState; + } }; void tst_QListWidget::closeEditor() { TestListWidget w; - QStringList labels = (QStringList() << "a" << "b" << "c" << "d"); - w.addItems(labels); + w.addItems({"a", "b", "c", "d"}); QListWidgetItem *item = w.item(0); item->setFlags(item->flags() | Qt::ItemIsEditable); QVERIFY(item); w.editItem(item); - QVERIFY(w.isEditingState(item)); + QVERIFY(w.isEditingState()); w.reset(); - QVERIFY(!w.isEditingState(item)); + QVERIFY(!w.isEditingState()); } void tst_QListWidget::setData_data() @@ -1267,15 +1244,15 @@ void tst_QListWidget::setData() QCOMPARE(roles.count(), values.count()); - for (int manipulateModel=0; manipulateModel<2; ++manipulateModel) { + for (int manipulateModel = 0; manipulateModel < 2; ++manipulateModel) { testWidget->clear(); testWidget->insertItems(0, initialItems); QCOMPARE(testWidget->count(), initialItems.count()); - QSignalSpy itemChanged(testWidget, SIGNAL(itemChanged(QListWidgetItem*))); - QSignalSpy dataChanged(testWidget->model(), SIGNAL(dataChanged(QModelIndex,QModelIndex))); + QSignalSpy itemChanged(testWidget, &QListWidget::itemChanged); + QSignalSpy dataChanged(testWidget->model(), &QAbstractItemModel::dataChanged); - for (int i=0; i < roles.count(); ++i) { + for (int i = 0; i < roles.count(); ++i) { if (manipulateModel) testWidget->model()->setData( testWidget->model()->index(itemIndex, 0, testWidget->rootIndex()), @@ -1286,7 +1263,7 @@ void tst_QListWidget::setData() } // make sure the data is actually set - for (int i=0; i < roles.count(); ++i) + for (int i = 0; i < roles.count(); ++i) QCOMPARE(testWidget->item(itemIndex)->data(roles.at(i)), values.at(i)); // make sure we get the right number of emits @@ -1297,50 +1274,50 @@ void tst_QListWidget::setData() void tst_QListWidget::insertItemsWithSorting_data() { - QTest::addColumn("sortOrder"); + QTest::addColumn("sortOrder"); QTest::addColumn("initialItems"); QTest::addColumn("insertItems"); QTest::addColumn("expectedItems"); QTest::addColumn("expectedRows"); QTest::newRow("() + (a) = (a)") - << static_cast(Qt::AscendingOrder) + << Qt::AscendingOrder << QStringList() << (QStringList() << "a") << (QStringList() << "a") << IntList(); QTest::newRow("() + (c, b, a) = (a, b, c)") - << static_cast(Qt::AscendingOrder) + << Qt::AscendingOrder << QStringList() << (QStringList() << "c" << "b" << "a") << (QStringList() << "a" << "b" << "c") << IntList(); QTest::newRow("() + (a, b, c) = (c, b, a)") - << static_cast(Qt::DescendingOrder) + << Qt::DescendingOrder << QStringList() << (QStringList() << "a" << "b" << "c") << (QStringList() << "c" << "b" << "a") << IntList(); QTest::newRow("(a) + (b) = (a, b)") - << static_cast(Qt::AscendingOrder) + << Qt::AscendingOrder << QStringList("a") << (QStringList() << "b") << (QStringList() << "a" << "b") << (IntList() << 0); QTest::newRow("(a) + (b) = (b, a)") - << static_cast(Qt::DescendingOrder) + << Qt::DescendingOrder << QStringList("a") << (QStringList() << "b") << (QStringList() << "b" << "a") << (IntList() << 1); QTest::newRow("(a, c, b) + (d) = (a, b, c, d)") - << static_cast(Qt::AscendingOrder) + << Qt::AscendingOrder << (QStringList() << "a" << "c" << "b") << (QStringList() << "d") << (QStringList() << "a" << "b" << "c" << "d") << (IntList() << 0 << 1 << 2); QTest::newRow("(b, c, a) + (d) = (d, c, b, a)") - << static_cast(Qt::DescendingOrder) + << Qt::DescendingOrder << (QStringList() << "b" << "c" << "a") << (QStringList() << "d") << (QStringList() << "d" << "c" << "b" << "a") @@ -1350,38 +1327,38 @@ void tst_QListWidget::insertItemsWithSorting_data() IntList reverseRows; QStringList ascendingItems; QStringList reverseItems; - for (int i = 'a'; i <= 'z'; ++i) { + for (char i = 'a'; i <= 'z'; ++i) { ascendingItems << QString(1, QLatin1Char(i)); reverseItems << QString(1, QLatin1Char('z' - i + 'a')); ascendingRows << i - 'a'; reverseRows << 'z' - i + 'a'; } QTest::newRow("() + (sorted items) = (sorted items)") - << static_cast(Qt::AscendingOrder) + << Qt::AscendingOrder << QStringList() << ascendingItems << ascendingItems << IntList(); QTest::newRow("(sorted items) + () = (sorted items)") - << static_cast(Qt::AscendingOrder) + << Qt::AscendingOrder << ascendingItems << QStringList() << ascendingItems << ascendingRows; QTest::newRow("() + (ascending items) = (reverse items)") - << static_cast(Qt::DescendingOrder) + << Qt::DescendingOrder << QStringList() << ascendingItems << reverseItems << IntList(); QTest::newRow("(reverse items) + () = (ascending items)") - << static_cast(Qt::AscendingOrder) + << Qt::AscendingOrder << reverseItems << QStringList() << ascendingItems << ascendingRows; QTest::newRow("(reverse items) + () = (reverse items)") - << static_cast(Qt::DescendingOrder) + << Qt::DescendingOrder << reverseItems << QStringList() << reverseItems @@ -1391,16 +1368,16 @@ void tst_QListWidget::insertItemsWithSorting_data() void tst_QListWidget::insertItemsWithSorting() { - QFETCH(int, sortOrder); - QFETCH(QStringList, initialItems); - QFETCH(QStringList, insertItems); - QFETCH(QStringList, expectedItems); - QFETCH(IntList, expectedRows); + QFETCH(Qt::SortOrder, sortOrder); + QFETCH(const QStringList, initialItems); + QFETCH(const QStringList, insertItems); + QFETCH(const QStringList, expectedItems); + QFETCH(const IntList, expectedRows); for (int method = 0; method < 5; ++method) { QListWidget w; w.setSortingEnabled(true); - w.sortItems(static_cast(sortOrder)); + w.sortItems(sortOrder); w.addItems(initialItems); QAbstractItemModel *model = w.model(); @@ -1411,8 +1388,8 @@ void tst_QListWidget::insertItemsWithSorting() switch (method) { case 0: // insert using item constructor - for (int i = 0; i < insertItems.size(); ++i) - new QListWidgetItem(insertItems.at(i), &w); + for (const QString &str : insertItems) + new QListWidgetItem(str, &w); break; case 1: // insert using insertItems() @@ -1420,8 +1397,8 @@ void tst_QListWidget::insertItemsWithSorting() break; case 2: // insert using insertItem() - for (int i = 0; i < insertItems.size(); ++i) - w.insertItem(0, insertItems.at(i)); + for (const QString &str : insertItems) + w.insertItem(0, str); break; case 3: // insert using addItems() @@ -1429,8 +1406,8 @@ void tst_QListWidget::insertItemsWithSorting() break; case 4: // insert using addItem() - for (int i = 0; i < insertItems.size(); ++i) - w.addItem(insertItems.at(i)); + for (const QString &str : insertItems) + w.addItem(str); break; } QCOMPARE(w.count(), expectedItems.count()); @@ -1444,7 +1421,7 @@ void tst_QListWidget::insertItemsWithSorting() void tst_QListWidget::changeDataWithSorting_data() { - QTest::addColumn("sortOrder"); + QTest::addColumn("sortOrder"); QTest::addColumn("initialItems"); QTest::addColumn("itemIndex"); QTest::addColumn("newValue"); @@ -1453,49 +1430,49 @@ void tst_QListWidget::changeDataWithSorting_data() QTest::addColumn("reorderingExpected"); QTest::newRow("change a to b in (a)") - << static_cast(Qt::AscendingOrder) + << Qt::AscendingOrder << (QStringList() << "a") << 0 << "b" << (QStringList() << "b") << (IntList() << 0) << false; QTest::newRow("change a to b in (a, c)") - << static_cast(Qt::AscendingOrder) + << Qt::AscendingOrder << (QStringList() << "a" << "c") << 0 << "b" << (QStringList() << "b" << "c") << (IntList() << 0 << 1) << false; QTest::newRow("change a to c in (a, b)") - << static_cast(Qt::AscendingOrder) + << Qt::AscendingOrder << (QStringList() << "a" << "b") << 0 << "c" << (QStringList() << "b" << "c") << (IntList() << 1 << 0) << true; QTest::newRow("change c to a in (c, b)") - << static_cast(Qt::DescendingOrder) + << Qt::DescendingOrder << (QStringList() << "c" << "b") << 0 << "a" << (QStringList() << "b" << "a") << (IntList() << 1 << 0) << true; QTest::newRow("change e to i in (a, c, e, g)") - << static_cast(Qt::AscendingOrder) + << Qt::AscendingOrder << (QStringList() << "a" << "c" << "e" << "g") << 2 << "i" << (QStringList() << "a" << "c" << "g" << "i") << (IntList() << 0 << 1 << 3 << 2) << true; QTest::newRow("change e to a in (c, e, g, i)") - << static_cast(Qt::AscendingOrder) + << Qt::AscendingOrder << (QStringList() << "c" << "e" << "g" << "i") << 1 << "a" << (QStringList() << "a" << "c" << "g" << "i") << (IntList() << 1 << 0 << 2 << 3) << true; QTest::newRow("change e to f in (c, e, g, i)") - << static_cast(Qt::AscendingOrder) + << Qt::AscendingOrder << (QStringList() << "c" << "e" << "g" << "i") << 1 << "f" << (QStringList() << "c" << "f" << "g" << "i") @@ -1539,7 +1516,7 @@ void tst_QListWidget::itemData() void tst_QListWidget::changeDataWithSorting() { - QFETCH(int, sortOrder); + QFETCH(Qt::SortOrder, sortOrder); QFETCH(QStringList, initialItems); QFETCH(int, itemIndex); QFETCH(QString, newValue); @@ -1549,16 +1526,16 @@ void tst_QListWidget::changeDataWithSorting() QListWidget w; w.setSortingEnabled(true); - w.sortItems(static_cast(sortOrder)); + w.sortItems(sortOrder); w.addItems(initialItems); QAbstractItemModel *model = w.model(); - QList persistent; + QVector persistent; for (int j = 0; j < model->rowCount(QModelIndex()); ++j) persistent << model->index(j, 0, QModelIndex()); - QSignalSpy dataChangedSpy(model, SIGNAL(dataChanged(QModelIndex,QModelIndex))); - QSignalSpy layoutChangedSpy(model, SIGNAL(layoutChanged())); + QSignalSpy dataChangedSpy(model, &QAbstractItemModel::dataChanged); + QSignalSpy layoutChangedSpy(model, &QAbstractItemModel::layoutChanged); QListWidgetItem *item = w.item(itemIndex); item->setText(newValue); @@ -1566,7 +1543,7 @@ void tst_QListWidget::changeDataWithSorting() QCOMPARE(w.item(i)->text(), expectedItems.at(i)); for (int j = 0; j < persistent.count(); ++j) { if (persistent.at(j).row() == i) // the same toplevel row - QCOMPARE(persistent.at(j).internalPointer(), (void *)w.item(i)); + QCOMPARE(persistent.at(j).internalPointer(), static_cast(w.item(i))); } } @@ -1595,13 +1572,12 @@ void tst_QListWidget::itemWidget() #ifndef Q_OS_MAC class MyListWidget : public QListWidget { + Q_OBJECT public: - MyListWidget(QWidget *parent=0) - : QListWidget(parent) - { - } + using QListWidget::QListWidget; - void paintEvent(QPaintEvent *e) { + void paintEvent(QPaintEvent *e) override + { painted += e->region(); QListWidget::paintEvent(e); } @@ -1649,7 +1625,7 @@ void tst_QListWidget::fastScroll() void tst_QListWidget::insertUnchanged() { QListWidget w; - QSignalSpy itemChangedSpy(&w, SIGNAL(itemChanged(QListWidgetItem*))); + QSignalSpy itemChangedSpy(&w, &QListWidget::itemChanged); QListWidgetItem item("foo", &w); QCOMPARE(itemChangedSpy.count(), 0); } @@ -1670,9 +1646,9 @@ void tst_QListWidget::task199503_crashWhenCleared() { //we test here for a crash that would occur if you clear the items in the currentItemChanged signal QListWidget w; - w.addItems( QStringList() << "item1" << "item2" << "item3"); + w.addItems({"item1", "item2", "item3"}); w.setCurrentRow(0); - w.connect(&w, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)), SLOT(clear())); + w.connect(&w, &QListWidget::currentItemChanged, &w, &QListWidget::clear); w.setCurrentRow(1); } @@ -1680,21 +1656,22 @@ void tst_QListWidget::task217070_scrollbarsAdjusted() { //This task was mailing for style using SH_ScrollView_FrameOnlyAroundContents such as QMotifStyle QListWidget v; - for (int i = 0; i<200;i++) + for (int i = 0; i < 200;i++) v.addItem(QString::number(i)); v.show(); v.setViewMode(QListView::IconMode); v.setResizeMode(QListView::Adjust); v.setUniformItemSizes(true); - v.resize(160,100); + v.resize(160, 100); QVERIFY(QTest::qWaitForWindowActive(&v)); QScrollBar *hbar = v.horizontalScrollBar(); QScrollBar *vbar = v.verticalScrollBar(); QVERIFY(hbar && vbar); - for(int f=150; f>90 ; f--) { - v.resize(f,100); - QTest::qWait(30); - QVERIFY(vbar->style()->styleHint(QStyle::SH_ScrollBar_Transient, 0, vbar) || vbar->isVisible()); + const auto style = vbar->style(); + for (int f = 150; f > 90 ; f--) { + v.resize(f, 100); + QTRY_VERIFY(style->styleHint(QStyle::SH_ScrollBar_Transient, nullptr, vbar) || + vbar->isVisible()); //the horizontal scrollbar must not be visible. QVERIFY(!hbar->isVisible()); } @@ -1711,12 +1688,11 @@ void tst_QListWidget::task258949_keypressHangup() } lw.show(); - lw.setCurrentIndex(lw.model()->index(0,0)); - QCOMPARE(lw.currentIndex(), lw.model()->index(0,0)); + lw.setCurrentIndex(lw.model()->index(0, 0)); + QCOMPARE(lw.currentIndex(), lw.model()->index(0, 0)); QTest::qWait(30); QTest::keyPress(&lw, '1'); //this used to freeze - QTest::qWait(30); - QCOMPARE(lw.currentIndex(), lw.model()->index(0,0)); + QTRY_COMPARE(lw.currentIndex(), lw.model()->index(0, 0)); } void tst_QListWidget::QTBUG8086_currentItemChangedOnClick() @@ -1735,25 +1711,26 @@ void tst_QListWidget::QTBUG8086_currentItemChangedOnClick() edit.setFocus(); win.show(); - QSignalSpy spy(&list, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*))); + QSignalSpy spy(&list, &QListWidget::currentItemChanged); QVERIFY(QTest::qWaitForWindowExposed(&win)); QCOMPARE(spy.count(), 0); - QTest::mouseClick(list.viewport(), Qt::LeftButton, 0, list.visualItemRect(list.item(2)).center()); + QTest::mouseClick(list.viewport(), Qt::LeftButton, {}, + list.visualItemRect(list.item(2)).center()); QCOMPARE(spy.count(), 1); - } -class ItemDelegate : public QItemDelegate +class ItemDelegate : public QStyledItemDelegate { + Q_OBJECT public: - ItemDelegate(QObject *parent = 0) : QItemDelegate(parent) - {} - virtual QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const + using QStyledItemDelegate::QStyledItemDelegate; + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &, + const QModelIndex &) const override { QLineEdit *lineEdit = new QLineEdit(parent); lineEdit->setFrame(false); @@ -1775,10 +1752,10 @@ void tst_QListWidget::QTBUG14363_completerWithAnyKeyPressedEditTriggers() new QListWidgetItem(QLatin1String("completer"), &listWidget); listWidget.show(); listWidget.setCurrentItem(item); - qApp->setActiveWindow(&listWidget); + QApplication::setActiveWindow(&listWidget); QVERIFY(QTest::qWaitForWindowActive(&listWidget)); listWidget.setFocus(); - QCOMPARE(qApp->focusWidget(), &listWidget); + QCOMPARE(QApplication::focusWidget(), &listWidget); QTest::keyClick(listWidget.viewport(), Qt::Key_C); @@ -1792,41 +1769,27 @@ void tst_QListWidget::mimeData() { TestListWidget list; - for (int x = 0; x < 10; ++x) { - QListWidgetItem *item = new QListWidgetItem(QStringLiteral("123")); - list.addItem(item); - } + for (int x = 0; x < 10; ++x) + list.addItem(new QListWidgetItem(QStringLiteral("123"))); - QList tableWidgetItemList; - QModelIndexList modelIndexList; + const QList tableWidgetItemList{list.item(1)}; + const QModelIndexList modelIndexList{list.indexFromItem(list.item(1))}; // do these checks more than once to ensure that the "cached indexes" work as expected - QVERIFY(!list.mimeData(tableWidgetItemList)); - QVERIFY(!list.model()->mimeData(modelIndexList)); - QVERIFY(!list.model()->mimeData(modelIndexList)); - QVERIFY(!list.mimeData(tableWidgetItemList)); - - tableWidgetItemList << list.item(1); - modelIndexList << list.indexFromItem(list.item(1)); - QMimeData *data; + for (int i = 0; i < 2; ++i) { + QVERIFY(!list.mimeData({})); + QVERIFY(!list.model()->mimeData({})); - QVERIFY((data = list.mimeData(tableWidgetItemList))); - delete data; + QVERIFY((data = list.mimeData(tableWidgetItemList))); + delete data; - QVERIFY((data = list.model()->mimeData(modelIndexList))); - delete data; - - QVERIFY((data = list.model()->mimeData(modelIndexList))); - delete data; - - QVERIFY((data = list.mimeData(tableWidgetItemList))); - delete data; + QVERIFY((data = list.model()->mimeData(modelIndexList))); + delete data; + } // check the saved data is actually the same - QMimeData *data2; - data = list.mimeData(tableWidgetItemList); data2 = list.model()->mimeData(modelIndexList); @@ -1850,13 +1813,14 @@ void tst_QListWidget::QTBUG50891_ensureSelectionModelSignalConnectionsAreSet() list.show(); QVERIFY(QTest::qWaitForWindowExposed(&list)); - QSignalSpy currentItemChangedSpy(&list, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*))); - QSignalSpy itemSelectionChangedSpy(&list, SIGNAL(itemSelectionChanged())); + QSignalSpy currentItemChangedSpy(&list, &QListWidget::currentItemChanged); + QSignalSpy itemSelectionChangedSpy(&list, &QListWidget::itemSelectionChanged); QCOMPARE(currentItemChangedSpy.count(), 0); QCOMPARE(itemSelectionChangedSpy.count(), 0); - QTest::mouseClick(list.viewport(), Qt::LeftButton, 0, list.visualItemRect(list.item(2)).center()); + QTest::mouseClick(list.viewport(), Qt::LeftButton, {}, + list.visualItemRect(list.item(2)).center()); QCOMPARE(currentItemChangedSpy.count(), 1); QCOMPARE(itemSelectionChangedSpy.count(), 1);