From 7dc930d40037c99d87b09de09a882d5f86f157d5 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Mon, 6 Aug 2018 13:47:18 +0200 Subject: qmake vcxproj generator: Fix compilation of generated C++ sources Generated C++ source files with extensions other than .cpp would not get compiled, because the code ignored all other C++ source extensions like .cc and .cxx. Fix this by respecting the value of QMAKE_EXT_CPP and QMAKE_EXT_C. Task-number: QTBUG-69770 Change-Id: I097dfef6920e353a351c97891cdbfdc9a859815f Reviewed-by: Oliver Wolff Reviewed-by: Oswald Buddenhagen --- qmake/generators/win32/msbuild_objectmodel.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/qmake/generators/win32/msbuild_objectmodel.cpp b/qmake/generators/win32/msbuild_objectmodel.cpp index 9f82ce4f8e..e58999bb97 100644 --- a/qmake/generators/win32/msbuild_objectmodel.cpp +++ b/qmake/generators/win32/msbuild_objectmodel.cpp @@ -1977,6 +1977,15 @@ bool VCXProjectWriter::outputFileConfig(OutputFilterData *d, XmlOutput &xml, Xml return fileAdded; } +static bool isFileClCompatible(const QString &filePath) +{ + auto filePathEndsWith = [&filePath] (const QString &ext) { + return filePath.endsWith(ext, Qt::CaseInsensitive); + }; + return std::any_of(Option::cpp_ext.cbegin(), Option::cpp_ext.cend(), filePathEndsWith) + || std::any_of(Option::c_ext.cbegin(), Option::c_ext.cend(), filePathEndsWith); +} + void VCXProjectWriter::outputFileConfig(XmlOutput &xml, XmlOutput &xmlFilter, const QString &filePath, const QString &filterName) { @@ -2000,7 +2009,7 @@ void VCXProjectWriter::outputFileConfig(XmlOutput &xml, XmlOutput &xmlFilter, << attrTagS("Filter", filterName); xml << tag("ClInclude") << attrTag("Include", nativeFilePath); - } else if (filePath.endsWith(".cpp")) { + } else if (isFileClCompatible(filePath)) { xmlFilter << tag("ClCompile") << attrTag("Include", nativeFilePath) << attrTagS("Filter", filterName); -- cgit v1.2.3 From 2adc06f9406ec2f8c02d1619c73f384eb2947498 Mon Sep 17 00:00:00 2001 From: Robin Lee Date: Wed, 27 Jun 2018 11:54:20 +0800 Subject: IBus: Support the portal, needed for Flatpak environment Following commit 35ce6247 in IBus, IBus input plugin now connects to session bus and use IBus portal to create input context when running in Flatpak environment or IBUS_USE_PORTAL is set. [ChangeLog][plugins][ibus] Support IBus portal. Qt programs in Flatpak environment can now trigger IBus input method. Change-Id: I561f5f873d709b8abeae554d804daa058f9f6e16 Reviewed-by: Lars Knoll Reviewed-by: Takao Fujiwara --- src/plugins/platforminputcontexts/ibus/ibus.pro | 2 + .../interfaces/org.freedesktop.IBus.Portal.xml | 10 ++++ .../ibus/qibusplatforminputcontext.cpp | 64 ++++++++++++++++++---- .../ibus/qibusproxyportal.cpp | 26 +++++++++ .../platforminputcontexts/ibus/qibusproxyportal.h | 49 +++++++++++++++++ 5 files changed, 140 insertions(+), 11 deletions(-) create mode 100644 src/plugins/platforminputcontexts/ibus/interfaces/org.freedesktop.IBus.Portal.xml create mode 100644 src/plugins/platforminputcontexts/ibus/qibusproxyportal.cpp create mode 100644 src/plugins/platforminputcontexts/ibus/qibusproxyportal.h diff --git a/src/plugins/platforminputcontexts/ibus/ibus.pro b/src/plugins/platforminputcontexts/ibus/ibus.pro index 9f6c848e6a..52836bb8b6 100644 --- a/src/plugins/platforminputcontexts/ibus/ibus.pro +++ b/src/plugins/platforminputcontexts/ibus/ibus.pro @@ -3,12 +3,14 @@ TARGET = ibusplatforminputcontextplugin QT += dbus gui-private SOURCES += $$PWD/qibusplatforminputcontext.cpp \ $$PWD/qibusproxy.cpp \ + $$PWD/qibusproxyportal.cpp \ $$PWD/qibusinputcontextproxy.cpp \ $$PWD/qibustypes.cpp \ $$PWD/main.cpp HEADERS += $$PWD/qibusplatforminputcontext.h \ $$PWD/qibusproxy.h \ + $$PWD/qibusproxyportal.h \ $$PWD/qibusinputcontextproxy.h \ $$PWD/qibustypes.h diff --git a/src/plugins/platforminputcontexts/ibus/interfaces/org.freedesktop.IBus.Portal.xml b/src/plugins/platforminputcontexts/ibus/interfaces/org.freedesktop.IBus.Portal.xml new file mode 100644 index 0000000000..1a5414d0ae --- /dev/null +++ b/src/plugins/platforminputcontexts/ibus/interfaces/org.freedesktop.IBus.Portal.xml @@ -0,0 +1,10 @@ + + + + + + + + + diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp index f339938f86..19f0afbf50 100644 --- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp +++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp @@ -50,6 +50,7 @@ #include #include "qibusproxy.h" +#include "qibusproxyportal.h" #include "qibusinputcontextproxy.h" #include "qibustypes.h" @@ -78,19 +79,22 @@ public: { delete context; delete bus; + delete portalBus; delete connection; } static QString getSocketPath(); - static QDBusConnection *createConnection(); + QDBusConnection *createConnection(); void initBus(); void createBusProxy(); QDBusConnection *connection; QIBusProxy *bus; + QIBusProxyPortal *portalBus; // bus and portalBus are alternative. QIBusInputContextProxy *context; + bool usePortal; // return value of shouldConnectIbusPortal bool valid; bool busConnected; QString predit; @@ -507,6 +511,9 @@ void QIBusPlatformInputContext::filterEventFinished(QDBusPendingCallWatcher *cal QLocale QIBusPlatformInputContext::locale() const { + // d->locale is not updated when IBus portal is used + if (d->usePortal) + return QPlatformInputContext::locale(); return d->locale; } @@ -572,15 +579,34 @@ void QIBusPlatformInputContext::connectToContextSignals() } } +static inline bool checkRunningUnderFlatpak() +{ + return !QStandardPaths::locate(QStandardPaths::RuntimeLocation, QLatin1String("flatpak-info")).isEmpty(); +} + +static bool shouldConnectIbusPortal() +{ + // honor the same env as ibus-gtk + return (checkRunningUnderFlatpak() || !qgetenv("IBUS_USE_PORTAL").isNull()); +} + QIBusPlatformInputContextPrivate::QIBusPlatformInputContextPrivate() : connection(0), bus(0), + portalBus(0), context(0), + usePortal(shouldConnectIbusPortal()), valid(false), busConnected(false), needsSurroundingText(false) { - valid = !QStandardPaths::findExecutable(QString::fromLocal8Bit("ibus-daemon"), QStringList()).isEmpty(); + if (usePortal) { + valid = true; + if (debug) + qDebug() << "use IBus portal"; + } else { + valid = !QStandardPaths::findExecutable(QString::fromLocal8Bit("ibus-daemon"), QStringList()).isEmpty(); + } if (!valid) return; initBus(); @@ -603,21 +629,35 @@ void QIBusPlatformInputContextPrivate::createBusProxy() if (!connection || !connection->isConnected()) return; - bus = new QIBusProxy(QLatin1String("org.freedesktop.IBus"), - QLatin1String("/org/freedesktop/IBus"), - *connection); - if (!bus->isValid()) { - qWarning("QIBusPlatformInputContext: invalid bus."); - return; - } + const char* ibusService = usePortal ? "org.freedesktop.portal.IBus" : "org.freedesktop.IBus"; + QDBusReply ic; + if (usePortal) { + portalBus = new QIBusProxyPortal(QLatin1String(ibusService), + QLatin1String("/org/freedesktop/IBus"), + *connection); + if (!portalBus->isValid()) { + qWarning("QIBusPlatformInputContext: invalid portal bus."); + return; + } - QDBusReply ic = bus->CreateInputContext(QLatin1String("QIBusInputContext")); + ic = portalBus->CreateInputContext(QLatin1String("QIBusInputContext")); + } else { + bus = new QIBusProxy(QLatin1String(ibusService), + QLatin1String("/org/freedesktop/IBus"), + *connection); + if (!bus->isValid()) { + qWarning("QIBusPlatformInputContext: invalid bus."); + return; + } + + ic = bus->CreateInputContext(QLatin1String("QIBusInputContext")); + } if (!ic.isValid()) { qWarning("QIBusPlatformInputContext: CreateInputContext failed."); return; } - context = new QIBusInputContextProxy(QLatin1String("org.freedesktop.IBus"), ic.value().path(), *connection); + context = new QIBusInputContextProxy(QLatin1String(ibusService), ic.value().path(), *connection); if (!context->isValid()) { qWarning("QIBusPlatformInputContext: invalid input context."); @@ -665,6 +705,8 @@ QString QIBusPlatformInputContextPrivate::getSocketPath() QDBusConnection *QIBusPlatformInputContextPrivate::createConnection() { + if (usePortal) + return new QDBusConnection(QDBusConnection::connectToBus(QDBusConnection::SessionBus, QLatin1String("QIBusProxy"))); QFile file(getSocketPath()); if (!file.open(QFile::ReadOnly)) diff --git a/src/plugins/platforminputcontexts/ibus/qibusproxyportal.cpp b/src/plugins/platforminputcontexts/ibus/qibusproxyportal.cpp new file mode 100644 index 0000000000..50482e2d9a --- /dev/null +++ b/src/plugins/platforminputcontexts/ibus/qibusproxyportal.cpp @@ -0,0 +1,26 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -N -p qibusproxyportal -c QIBusProxyPortal interfaces/org.freedesktop.IBus.Portal.xml + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "qibusproxyportal.h" + +/* + * Implementation of interface class QIBusProxyPortal + */ + +QIBusProxyPortal::QIBusProxyPortal(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +QIBusProxyPortal::~QIBusProxyPortal() +{ +} + diff --git a/src/plugins/platforminputcontexts/ibus/qibusproxyportal.h b/src/plugins/platforminputcontexts/ibus/qibusproxyportal.h new file mode 100644 index 0000000000..bdd1d9c395 --- /dev/null +++ b/src/plugins/platforminputcontexts/ibus/qibusproxyportal.h @@ -0,0 +1,49 @@ +/* + * This file was generated by qdbusxml2cpp version 0.8 + * Command line was: qdbusxml2cpp -N -p qibusproxyportal -c QIBusProxyPortal interfaces/org.freedesktop.IBus.Portal.xml + * + * qdbusxml2cpp is Copyright (C) 2017 The Qt Company Ltd. + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#ifndef QIBUSPROXYPORTAL_H +#define QIBUSPROXYPORTAL_H + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Proxy class for interface org.freedesktop.IBus.Portal + */ +class QIBusProxyPortal: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "org.freedesktop.IBus.Portal"; } + +public: + QIBusProxyPortal(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = nullptr); + + ~QIBusProxyPortal(); + +public Q_SLOTS: // METHODS + inline QDBusPendingReply CreateInputContext(const QString &name) + { + QList argumentList; + argumentList << QVariant::fromValue(name); + return asyncCallWithArgumentList(QStringLiteral("CreateInputContext"), argumentList); + } + +Q_SIGNALS: // SIGNALS +}; + +#endif -- cgit v1.2.3 From 25feee4e061b99edab79503d81f5bd045c6c8e3d Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 7 Aug 2018 09:38:42 -0700 Subject: Fix qmake build with glibc 2.28 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We haven't yet run the configure checks to see if statx and renameat2 are present in glibc, so this fails when we redefine the structures and functions. linux/stat.h:56:8: error: redefinition of 'struct statx_timestamp' bits/statx.h:25:8: note: previous definition of 'struct statx_timestamp' qfilesystemengine_unix.cpp:110:12: error: 'int renameat2(int, const char*, int, const char*, unsigned int)' was declared 'extern' and later 'static' [-fpermissive] Change-Id: Ia741b559c24d46c78fb2fffd1548a792d22e3368 Reviewed-by: Oswald Buddenhagen Reviewed-by: Jüri Valdmann --- src/corelib/global/qconfig-bootstrapped.h | 12 ++++++++++-- src/corelib/io/qfilesystemengine_unix.cpp | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/corelib/global/qconfig-bootstrapped.h b/src/corelib/global/qconfig-bootstrapped.h index 3469ebe5e6..c5585ea32a 100644 --- a/src/corelib/global/qconfig-bootstrapped.h +++ b/src/corelib/global/qconfig-bootstrapped.h @@ -98,10 +98,18 @@ #define QT_NO_QOBJECT #define QT_FEATURE_process -1 #define QT_FEATURE_regularexpression -1 -#define QT_FEATURE_renameat2 -1 +#ifdef __GLIBC_PREREQ +# define QT_FEATURE_renameat2 (__GLIBC_PREREQ(2, 28) ? 1 : -1) +#else +# define QT_FEATURE_renameat2 -1 +#endif #define QT_FEATURE_sharedmemory -1 #define QT_FEATURE_slog2 -1 -#define QT_FEATURE_statx -1 +#ifdef __GLIBC_PREREQ +# define QT_FEATURE_statx (__GLIBC_PREREQ(2, 28) ? 1 : -1) +#else +# define QT_FEATURE_statx -1 +#endif #define QT_FEATURE_syslog -1 #define QT_NO_SYSTEMLOCALE #define QT_FEATURE_systemsemaphore -1 diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index 0c9cdb8667..deb4a9f220 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -91,7 +91,6 @@ extern "C" NSString *NSTemporaryDirectory(); # include # include # include -# include // in case linux/fs.h is too old and doesn't define it: #ifndef FICLONE @@ -112,6 +111,7 @@ static int renameat2(int oldfd, const char *oldpath, int newfd, const char *newp # endif # if !QT_CONFIG(statx) && defined(SYS_statx) +# include static int statx(int dirfd, const char *pathname, int flag, unsigned mask, struct statx *statxbuf) { return syscall(SYS_statx, dirfd, pathname, flag, mask, statxbuf); } # elif !QT_CONFIG(statx) && !defined(SYS_statx) -- cgit v1.2.3 From 58b6b723defd8006c08624d690e32d53db91cc89 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 7 Aug 2018 20:22:27 -0700 Subject: QSysInfo: fall back to /usr/lib/os-release if the /etc one is missing Turns out that there are two files and while a lot of distros symlink one to the other, some distros lack the one in /etc. [ChangeLog][QtCore][QSysInfo] Fixed QSysInfo::productType() to properly detect some Linux distributions that ship with a minimal /etc. Change-Id: Ia741b559c24d46c78fb2fffd1548cab414037220 Reviewed-by: Oswald Buddenhagen Reviewed-by: Simon Hausmann --- src/corelib/global/qglobal.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index a6990b88f4..b30d690025 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -2211,10 +2211,19 @@ static bool readEtcFile(QUnixOSVersion &v, const char *filename, return true; } -static bool readEtcOsRelease(QUnixOSVersion &v) +static bool readOsRelease(QUnixOSVersion &v) { - return readEtcFile(v, "/etc/os-release", QByteArrayLiteral("ID="), - QByteArrayLiteral("VERSION_ID="), QByteArrayLiteral("PRETTY_NAME=")); + QByteArray id = QByteArrayLiteral("ID="); + QByteArray versionId = QByteArrayLiteral("VERSION_ID="); + QByteArray prettyName = QByteArrayLiteral("PRETTY_NAME="); + + // man os-release(5) says: + // The file /etc/os-release takes precedence over /usr/lib/os-release. + // Applications should check for the former, and exclusively use its data + // if it exists, and only fall back to /usr/lib/os-release if it is + // missing. + return readEtcFile(v, "/etc/os-release", id, versionId, prettyName) || + readEtcFile(v, "/usr/lib/os-release", id, versionId, prettyName); } static bool readEtcLsbRelease(QUnixOSVersion &v) @@ -2296,7 +2305,7 @@ static bool readEtcDebianVersion(QUnixOSVersion &v) static bool findUnixOsVersion(QUnixOSVersion &v) { - if (readEtcOsRelease(v)) + if (readOsRelease(v)) return true; if (readEtcLsbRelease(v)) return true; -- cgit v1.2.3 From f2668c6b43a80a83ebdd46407a01af8a0dc6285f Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Tue, 7 Aug 2018 08:30:07 +0200 Subject: qmake vcxproj generator: Fix extra compilers for single configs For single config mode (no debug_and_release) extra compilers wouldn't get added to the vcxproj file. Single config mode creates a temporary project, and that was incomplete. Multi config mode, on the other hand, directly operates on the "real data" and wasn't affected by this problem. Task-number: QTBUG-69769 Change-Id: I9cd942e43d80adbeac9a3c8fbe1a5766bc9645a0 Reviewed-by: Oswald Buddenhagen Reviewed-by: Joerg Bornemann --- qmake/generators/win32/msbuild_objectmodel.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/qmake/generators/win32/msbuild_objectmodel.cpp b/qmake/generators/win32/msbuild_objectmodel.cpp index e58999bb97..082f357d32 100644 --- a/qmake/generators/win32/msbuild_objectmodel.cpp +++ b/qmake/generators/win32/msbuild_objectmodel.cpp @@ -557,6 +557,12 @@ void VCXProjectWriter::write(XmlOutput &xml, VCProjectSingleConfig &tool) addFilters(tempProj, xmlFilter, "Deployment Files"); addFilters(tempProj, xmlFilter, "Distribution Files"); + tempProj.ExtraCompilers.reserve(tool.ExtraCompilersFiles.size()); + std::transform(tool.ExtraCompilersFiles.cbegin(), tool.ExtraCompilersFiles.cend(), + std::back_inserter(tempProj.ExtraCompilers), + [] (const VCFilter &filter) { return filter.Name; }); + tempProj.ExtraCompilers.removeDuplicates(); + for (int x = 0; x < tempProj.ExtraCompilers.count(); ++x) addFilters(tempProj, xmlFilter, tempProj.ExtraCompilers.at(x)); -- cgit v1.2.3 From 490d461ab080777d6418dce97db632dc2270d218 Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Thu, 15 Mar 2018 09:08:30 +0200 Subject: Fix apkPath for gradle 4.0+ This change keeps the compatibility with old gradle. It is needed for projects that must use the old gradle version. src/tools/androiddeployqt/main.cpp was moved from qttools into qtbase in 5.11. So re-apply c03f5673 in qttools here. Task-number: QTBUG-69755 Change-Id: I2399d445f8208766e4185d717bb51f1317fdcc00 Reviewed-by: Volker Krause (cherry picked from commit e2f41931129d77dd9e92c812d965d7252673661a) Reviewed-by: Vikas Pachdha Reviewed-by: Liang Qi --- src/tools/androiddeployqt/main.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/tools/androiddeployqt/main.cpp b/src/tools/androiddeployqt/main.cpp index f00188396d..57714fc687 100644 --- a/src/tools/androiddeployqt/main.cpp +++ b/src/tools/androiddeployqt/main.cpp @@ -2328,10 +2328,15 @@ enum PackageType { QString apkPath(const Options &options, PackageType pt) { QString path(options.outputDirectory); - if (options.gradle) - path += QLatin1String("/build/outputs/apk/") + QDir(options.outputDirectory).dirName() + QLatin1Char('-'); - else + if (options.gradle) { + path += QLatin1String("/build/outputs/apk/"); + QString buildType(options.releasePackage ? QLatin1String("release/") : QLatin1String("debug/")); + if (QDir(path + buildType).exists()) + path += buildType; + path += QDir(options.outputDirectory).dirName() + QLatin1Char('-'); + } else { path += QLatin1String("/bin/QtApp-"); + } if (options.releasePackage) { path += QLatin1String("release-"); if (pt == UnsignedAPK) -- cgit v1.2.3 From 04671a80db32bd7fce470c50934cf60f2e8ffa70 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Fri, 15 Jun 2018 23:15:10 +0200 Subject: macOS: Force light theme on macOS 10.14+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Until we can properly fix QPalette and QMacStyle, we should disable dark appearance in Qt applications. Disable by setting NSApp.appearance to Aqua, unless dark mode support has been requested via Info.plist or environment variable. Read the NSRequiresAquaSystemAppearance Info.plist key, don’t set NSApp.appearance if its value is false. Also check the QT_MAC_REQUIRES_AQUA_SYSTEM_APPEARANCE environment variable and apply similar logic. You then enable dark mode support by setting: QT_MAC_REQUIRES_AQUA_SYSTEM_APPEARANCE=0 which is slightly awkward, but matches Info.plist behavior. Task-number: QTBUG-68891 Change-Id: I86dc6cf3dee951d46c953396c57d2c31f2e4afcc Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoaintegration.mm | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 55b3805df3..79f7ebda54 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -70,6 +70,12 @@ #include +#if !QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14) +@interface NSApplication (MojaveForwardDeclarations) +@property (strong) NSAppearance *appearance NS_AVAILABLE_MAC(10_14); +@end +#endif + static void initResources() { Q_INIT_RESOURCE(qcocoaresources); @@ -131,6 +137,21 @@ QCocoaIntegration::QCocoaIntegration(const QStringList ¶mList) NSApplication *cocoaApplication = [QNSApplication sharedApplication]; qt_redirectNSApplicationSendEvent(); + if (__builtin_available(macOS 10.14, *)) { + // Disable dark appearance, unless the Info.plist or environment requests that it should be enabled + bool plistEnablesDarkAppearance = [[[NSBundle mainBundle] objectForInfoDictionaryKey: + @"NSRequiresAquaSystemAppearance"] boolValue]; + + bool hasEnvironmentRequiresAquaAppearance; + int environmentRequiresAquaAppearance = qEnvironmentVariableIntValue( + "QT_MAC_REQUIRES_AQUA_SYSTEM_APPEARANCE", &hasEnvironmentRequiresAquaAppearance); + bool environmentEnablesDarkAppearance = hasEnvironmentRequiresAquaAppearance + && environmentRequiresAquaAppearance == 0; + + if (!(plistEnablesDarkAppearance || environmentEnablesDarkAppearance)) + NSApp.appearance = [NSAppearance appearanceNamed:NSAppearanceNameAqua]; + } + if (qEnvironmentVariableIsEmpty("QT_MAC_DISABLE_FOREGROUND_APPLICATION_TRANSFORM")) { // Applications launched from plain executables (without an app // bundle) are "background" applications that does not take keybaord -- cgit v1.2.3 From 65a1d41a092e78f7ab142c4c62689e1ca40ba10c Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 7 Aug 2018 08:43:09 +0200 Subject: Fix potential crash when showing line/paragraph separators When showing line and paragraph separators at an offset from the start of the string, the end of string pointer would be incorrectly set, and we would read past the end of the string. If any part of this memory happened to match the line or paragraph separator, then we would overwrite it and have a crash. I couldn't find any reliable way to test this, since the crash depends on the contents of the memory after the string allocated by the algorithm. But with an overflow of 100 000 characters, I found that it crashed every time I ran the test. [ChangeLog][QtGui][Text] Fixed potential crash when using QTextOption::ShowLineAndParagraphSeparators. Task-number: QTBUG-69661 Change-Id: I17d1996b883560bacdc7ce114c8aeb2b0108faea Reviewed-by: JiDe Zhang Reviewed-by: Michal Lazo Reviewed-by: Konstantin Ritt --- src/gui/text/qtextengine.cpp | 2 +- tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 5e38311fa1..6751c077ac 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -2053,7 +2053,7 @@ void QTextEngine::itemize() const layoutData->string.detach(); string = reinterpret_cast(layoutData->string.unicode()); uc = string + offset; - e = uc + length; + e = string + length; *const_cast(uc) = 0x21B5; // visual line separator } break; diff --git a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp index 4e3d1da8fe..9c477589f9 100644 --- a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp +++ b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp @@ -137,6 +137,7 @@ private slots: void nbspWithFormat(); void noModificationOfInputString(); void superscriptCrash_qtbug53911(); + void showLineAndParagraphSeparatorsCrash(); private: QFont testFont; @@ -2199,6 +2200,23 @@ void tst_QTextLayout::noModificationOfInputString() } } +void tst_QTextLayout::showLineAndParagraphSeparatorsCrash() +{ + QString s = QString(100000, QChar('a')) + QChar(QChar::LineSeparator); + { + QTextLayout layout; + layout.setText(s); + + QTextOption option; + option.setFlags(QTextOption::ShowLineAndParagraphSeparators); + layout.setTextOption(option); + + layout.beginLayout(); + layout.createLine(); + layout.endLayout(); + } +} + void tst_QTextLayout::superscriptCrash_qtbug53911() { static int fontSizes = 64; -- cgit v1.2.3 From 9742ee681b6c877f518013a3af1ce1aa0a328d2c Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 26 Apr 2018 18:56:00 +0200 Subject: configure: fix passing of -L and -F to configure tests the global flags are deprecated in favor of per-library paths, but they obviously should still work. but apparently no-one cares, because there isn't even a bug report about it ... amends 90eee08b3. Change-Id: I85aee41ca11de1715d1c750ae8e663093e012fb7 Reviewed-by: Joerg Bornemann --- mkspecs/features/qt_configure.prf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mkspecs/features/qt_configure.prf b/mkspecs/features/qt_configure.prf index 58888856da..4039bba431 100644 --- a/mkspecs/features/qt_configure.prf +++ b/mkspecs/features/qt_configure.prf @@ -960,9 +960,9 @@ defineTest(qtConfTest_compile) { # add compiler flags, these are set for the target and should not be applied to host tests !isEmpty(EXTRA_DEFINES): \ qmake_args += $$system_quote(DEFINES += $$val_escape(EXTRA_DEFINES)) - !isEmpty(EXTRA_LIBDIR) \ + !isEmpty(EXTRA_LIBDIR): \ qmake_args += $$system_quote(QMAKE_LIBDIR += $$val_escape(EXTRA_LIBDIR)) - !isEmpty(EXTRA_FRAMEWORKPATH) \ + !isEmpty(EXTRA_FRAMEWORKPATH): \ qmake_args += $$system_quote(QMAKE_FRAMEWORKPATH += $$val_escape(EXTRA_FRAMEWORKPATH)) !isEmpty(EXTRA_INCLUDEPATH): \ qmake_args += $$system_quote(INCLUDEPATH += $$val_escape(EXTRA_INCLUDEPATH)) -- cgit v1.2.3 From e9a8facc96ce6d3b8df4832032ca4df9fac6e9d7 Mon Sep 17 00:00:00 2001 From: Takao Fujiwara Date: Thu, 9 Aug 2018 16:37:21 +0900 Subject: IBus: connect to ibus-daemon when it restarts in Flatpak IBus clients cannot access the IBus socket path in Flatpak and need to watch the D-Bus disconnection. Change-Id: Ida1a5ce4fe112c1c4f8855ec886e74f2cbdcc8a0 Reviewed-by: Lars Knoll --- .../ibus/qibusplatforminputcontext.cpp | 49 +++++++++++++++++----- .../ibus/qibusplatforminputcontext.h | 2 + 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp index 19f0afbf50..0e587965ca 100644 --- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp +++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp @@ -93,6 +93,7 @@ public: QIBusProxy *bus; QIBusProxyPortal *portalBus; // bus and portalBus are alternative. QIBusInputContextProxy *context; + QDBusServiceWatcher serviceWatcher; bool usePortal; // return value of shouldConnectIbusPortal bool valid; @@ -107,20 +108,25 @@ public: QIBusPlatformInputContext::QIBusPlatformInputContext () : d(new QIBusPlatformInputContextPrivate()) { - QString socketPath = QIBusPlatformInputContextPrivate::getSocketPath(); - QFile file(socketPath); - if (file.open(QFile::ReadOnly)) { + if (!d->usePortal) { + QString socketPath = QIBusPlatformInputContextPrivate::getSocketPath(); + QFile file(socketPath); + if (file.open(QFile::ReadOnly)) { #ifndef QT_NO_FILESYSTEMWATCHER - // If KDE session save is used or restart ibus-daemon, - // the applications could run before ibus-daemon runs. - // We watch the getSocketPath() to get the launching ibus-daemon. - m_socketWatcher.addPath(socketPath); - connect(&m_socketWatcher, SIGNAL(fileChanged(QString)), this, SLOT(socketChanged(QString))); + qCDebug(qtQpaInputMethods) << "socketWatcher.addPath" << socketPath; + // If KDE session save is used or restart ibus-daemon, + // the applications could run before ibus-daemon runs. + // We watch the getSocketPath() to get the launching ibus-daemon. + m_socketWatcher.addPath(socketPath); + connect(&m_socketWatcher, SIGNAL(fileChanged(QString)), this, SLOT(socketChanged(QString))); #endif + } + m_timer.setSingleShot(true); + connect(&m_timer, SIGNAL(timeout()), this, SLOT(connectToBus())); } - m_timer.setSingleShot(true); - connect(&m_timer, SIGNAL(timeout()), this, SLOT(connectToBus())); + QObject::connect(&d->serviceWatcher, SIGNAL(serviceRegistered(QString)), this, SLOT(busRegistered(QString))); + QObject::connect(&d->serviceWatcher, SIGNAL(serviceUnregistered(QString)), this, SLOT(busUnregistered(QString))); connectToContextSignals(); @@ -534,6 +540,22 @@ void QIBusPlatformInputContext::socketChanged(const QString &str) m_timer.start(100); } +void QIBusPlatformInputContext::busRegistered(const QString &str) +{ + qCDebug(qtQpaInputMethods) << "busRegistered"; + Q_UNUSED (str); + if (d->usePortal) { + connectToBus(); + } +} + +void QIBusPlatformInputContext::busUnregistered(const QString &str) +{ + qCDebug(qtQpaInputMethods) << "busUnregistered"; + Q_UNUSED (str); + d->busConnected = false; +} + // When getSocketPath() is modified, the bus is not established yet // so use m_timer. void QIBusPlatformInputContext::connectToBus() @@ -543,7 +565,7 @@ void QIBusPlatformInputContext::connectToBus() connectToContextSignals(); #ifndef QT_NO_FILESYSTEMWATCHER - if (m_socketWatcher.files().size() == 0) + if (!d->usePortal && m_socketWatcher.files().size() == 0) m_socketWatcher.addPath(QIBusPlatformInputContextPrivate::getSocketPath()); #endif } @@ -652,6 +674,11 @@ void QIBusPlatformInputContextPrivate::createBusProxy() ic = bus->CreateInputContext(QLatin1String("QIBusInputContext")); } + + serviceWatcher.removeWatchedService(ibusService); + serviceWatcher.setConnection(*connection); + serviceWatcher.addWatchedService(ibusService); + if (!ic.isValid()) { qWarning("QIBusPlatformInputContext: CreateInputContext failed."); return; diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h index 9b92b2e1f9..f37552b937 100644 --- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h +++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h @@ -108,6 +108,8 @@ public Q_SLOTS: void showPreeditText(); void filterEventFinished(QDBusPendingCallWatcher *call); void socketChanged(const QString &str); + void busRegistered(const QString &str); + void busUnregistered(const QString &str); void connectToBus(); void globalEngineChanged(const QString &engine_name); -- cgit v1.2.3 From 6854fa75f78ec202f1e5dce5bd8adec31d1dbc7e Mon Sep 17 00:00:00 2001 From: Sune Vuorela Date: Fri, 3 Aug 2018 19:01:44 +0200 Subject: Glib dispatcher: use default priority for timers For some reason, the GLib event dispatcher was lowering the priority for timers compared to other events like for example socket events. the IDLE priority is for "Do this later when you are not busy", and that is wrong for generic timer events. See also https://bugs.kde.org/show_bug.cgi?id=230184 Task-number: QTBUG-48344 Change-Id: Id337a8f0c7fad3ebd5e5fa49d7831a0001ea9010 Reviewed-by: Thiago Macieira Reviewed-by: David Faure Reviewed-by: Allan Sandfeld Jensen --- src/corelib/kernel/qeventdispatcher_glib.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/corelib/kernel/qeventdispatcher_glib.cpp b/src/corelib/kernel/qeventdispatcher_glib.cpp index 8cefa7a118..4c780a9294 100644 --- a/src/corelib/kernel/qeventdispatcher_glib.cpp +++ b/src/corelib/kernel/qeventdispatcher_glib.cpp @@ -345,7 +345,6 @@ QEventDispatcherGlibPrivate::QEventDispatcherGlibPrivate(GMainContext *context) sizeof(GIdleTimerSource))); idleTimerSource->timerSource = timerSource; g_source_set_can_recurse(&idleTimerSource->source, true); - g_source_set_priority(&idleTimerSource->source, G_PRIORITY_DEFAULT_IDLE); g_source_attach(&idleTimerSource->source, mainContext); } -- cgit v1.2.3 From 6256729a6da532079505edfe4c56a6ef29cd8ab8 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 13 Aug 2018 15:29:16 +0200 Subject: Fix possible heap corruption in QXmlStream The value of 'tos' at the check might already be on the last element, so triggering stack expansion on the second last element is too late. Change-Id: Ib3ab2662d4d27a71effe9e988b9e172923af2908 Reviewed-by: Richard J. Moore Reviewed-by: Thiago Macieira --- src/corelib/serialization/qxmlstream_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/serialization/qxmlstream_p.h b/src/corelib/serialization/qxmlstream_p.h index 4157fbbd0e..f8b1ede943 100644 --- a/src/corelib/serialization/qxmlstream_p.h +++ b/src/corelib/serialization/qxmlstream_p.h @@ -1250,7 +1250,7 @@ bool QXmlStreamReaderPrivate::parse() state_stack[tos] = 0; return true; } else if (act > 0) { - if (++tos == stack_size-1) + if (++tos >= stack_size-1) reallocateStack(); Value &val = sym_stack[tos]; -- cgit v1.2.3 From 833b9997fd8c93132186d6538770f0c415f73d53 Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Fri, 27 Jul 2018 12:25:12 +0200 Subject: xcb: make sure we have a valid m_qimage in backing store MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch amends a62f1d03560937a306c7586669a46cd9575e9464. If the initial backing store resize request is called with QSize(0, 0), we end up with QXcbBackingStoreImage holding a default contructed QImage / m_qimage. This happens because of the logic in QXcbBackingStoreImage::create(), where if we detect that the requested segmentSize == 0, we do not allocate any memory, and thus don't create a valid image in m_qimage. On subsequent call to QXcbBackingStore::resize() we would only check if QXcbBackingStoreImage object has been created, but not if it is in a valid state. This obviously would cause problems. This patch re-factors the logic to handle better resize to QSize(0, 0). And make the code cleaner by: - merging ::create and ::resize as semantically it is always resize(). - dropping unnecessary argument passing. Task-number: QTBUG-69581 Change-Id: Ied337beb449dea8259fcf6b7d29f0a5bd553019d Reviewed-by: Błażej Szczygieł Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbbackingstore.cpp | 111 ++++++++++++++----------- 1 file changed, 61 insertions(+), 50 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index b81cb8efa1..8ae9d9899e 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -100,9 +100,7 @@ public: private: void createShmSegment(size_t segmentSize); - void destroyShmSegment(size_t segmentSize); - - void create(const QSize &size, const xcb_format_t *fmt, QImage::Format format); + void destroyShmSegment(); void destroy(bool destroyShm); void ensureGC(xcb_drawable_t dst); @@ -142,6 +140,9 @@ private: bool m_hasAlpha = false; bool m_clientSideScroll = false; + + const xcb_format_t *m_xcb_format = nullptr; + QImage::Format m_qimage_format = QImage::Format_Invalid; }; class QXcbGraphicsBuffer : public QPlatformGraphicsBuffer @@ -183,58 +184,66 @@ QXcbBackingStoreImage::QXcbBackingStoreImage(QXcbBackingStore *backingStore, con : QXcbObject(backingStore->connection()) , m_backingStore(backingStore) { - QXcbWindow *window = static_cast(backingStore->window()->handle()); - const xcb_format_t *fmt = connection()->formatForDepth(window->depth()); - Q_ASSERT(fmt); + auto window = static_cast(m_backingStore->window()->handle()); + m_xcb_format = connection()->formatForDepth(window->depth()); + Q_ASSERT(m_xcb_format); + + m_qimage_format = window->imageFormat(); + m_hasAlpha = QImage::toPixelFormat(m_qimage_format).alphaUsage() == QPixelFormat::UsesAlpha; + if (!m_hasAlpha) + m_qimage_format = qt_maybeAlphaVersionWithSameDepth(m_qimage_format); memset(&m_shm_info, 0, sizeof m_shm_info); - QImage::Format format = window->imageFormat(); - m_hasAlpha = QImage::toPixelFormat(format).alphaUsage() == QPixelFormat::UsesAlpha; - if (!m_hasAlpha) - create(size, fmt, qt_maybeAlphaVersionWithSameDepth(format)); - else - create(size, fmt, format); + resize(size); } void QXcbBackingStoreImage::resize(const QSize &size) { - xcb_format_t fmt; - fmt.depth = m_xcb_image->depth; - fmt.bits_per_pixel = m_xcb_image->bpp; - fmt.scanline_pad = m_xcb_image->scanline_pad; - memset(fmt.pad0, 0, sizeof(fmt.pad0)); destroy(false); - create(size, &fmt, m_qimage.format()); -} -void QXcbBackingStoreImage::create(const QSize &size, const xcb_format_t *fmt, QImage::Format format) -{ + auto byteOrder = QSysInfo::ByteOrder == QSysInfo::BigEndian ? XCB_IMAGE_ORDER_MSB_FIRST + : XCB_IMAGE_ORDER_LSB_FIRST; m_xcb_image = xcb_image_create(size.width(), size.height(), XCB_IMAGE_FORMAT_Z_PIXMAP, - fmt->scanline_pad, - fmt->depth, fmt->bits_per_pixel, 0, - QSysInfo::ByteOrder == QSysInfo::BigEndian ? XCB_IMAGE_ORDER_MSB_FIRST : XCB_IMAGE_ORDER_LSB_FIRST, + m_xcb_format->scanline_pad, + m_xcb_format->depth, + m_xcb_format->bits_per_pixel, + 0, byteOrder, XCB_IMAGE_ORDER_MSB_FIRST, 0, ~0, 0); const size_t segmentSize = imageDataSize(m_xcb_image); - if (!segmentSize) - return; if (connection()->hasShm()) { - if (m_shm_info.shmaddr && (m_segmentSize < segmentSize || m_segmentSize / 2 >= segmentSize)) - destroyShmSegment(m_segmentSize); - if (!m_shm_info.shmaddr) { - qCDebug(lcQpaXcb) << "creating shared memory" << segmentSize << "for" - << size << "depth" << fmt->depth << "bits" << fmt->bits_per_pixel; - createShmSegment(segmentSize); + if (segmentSize == 0) { + if (m_segmentSize > 0) { + destroyShmSegment(); + qCDebug(lcQpaXcb) << "[" << m_backingStore->window() + << "] destroyed SHM segment due to resize to" << size; + } + } else { + // Destroy shared memory segment if it is double (or more) of what we actually + // need with new window size. Or if the new size is bigger than what we currently + // have allocated. + if (m_shm_info.shmaddr && (m_segmentSize < segmentSize || m_segmentSize / 2 >= segmentSize)) + destroyShmSegment(); + if (!m_shm_info.shmaddr) { + qCDebug(lcQpaXcb) << "[" << m_backingStore->window() + << "] creating shared memory" << segmentSize << "bytes for" + << size << "depth" << m_xcb_format->depth << "bits" + << m_xcb_format->bits_per_pixel; + createShmSegment(segmentSize); + } } } - m_xcb_image->data = m_shm_info.shmaddr ? m_shm_info.shmaddr : (uint8_t *)malloc(segmentSize); + if (segmentSize == 0) + return; - m_qimage = QImage( (uchar*) m_xcb_image->data, m_xcb_image->width, m_xcb_image->height, m_xcb_image->stride, format); + m_xcb_image->data = m_shm_info.shmaddr ? m_shm_info.shmaddr : (uint8_t *)malloc(segmentSize); + m_qimage = QImage(static_cast(m_xcb_image->data), m_xcb_image->width, + m_xcb_image->height, m_xcb_image->stride, m_qimage_format); m_graphics_buffer = new QXcbGraphicsBuffer(&m_qimage); m_xcb_pixmap = xcb_generate_id(xcb_connection()); @@ -248,17 +257,18 @@ void QXcbBackingStoreImage::create(const QSize &size, const xcb_format_t *fmt, Q void QXcbBackingStoreImage::destroy(bool destroyShm) { - if (m_xcb_image->data) { - if (m_shm_info.shmaddr) { - if (destroyShm) - destroyShmSegment(m_segmentSize); - } else { - free(m_xcb_image->data); + if (m_xcb_image) { + if (m_xcb_image->data) { + if (m_shm_info.shmaddr) { + if (destroyShm) + destroyShmSegment(); + } else { + free(m_xcb_image->data); + } } + xcb_image_destroy(m_xcb_image); } - xcb_image_destroy(m_xcb_image); - if (m_gc) { xcb_free_gc(xcb_connection(), m_gc); m_gc = 0; @@ -268,8 +278,12 @@ void QXcbBackingStoreImage::destroy(bool destroyShm) delete m_graphics_buffer; m_graphics_buffer = nullptr; - xcb_free_pixmap(xcb_connection(), m_xcb_pixmap); - m_xcb_pixmap = 0; + if (m_xcb_pixmap) { + xcb_free_pixmap(xcb_connection(), m_xcb_pixmap); + m_xcb_pixmap = 0; + } + + m_qimage = QImage(); } void QXcbBackingStoreImage::flushScrolledRegion(bool clientSideScroll) @@ -412,11 +426,8 @@ bool QXcbBackingStoreImage::createSystemVShmSegment(QXcbConnection *c, size_t se return true; } -void QXcbBackingStoreImage::destroyShmSegment(size_t segmentSize) +void QXcbBackingStoreImage::destroyShmSegment() { -#ifndef XCB_USE_SHM_FD - Q_UNUSED(segmentSize) -#endif auto cookie = xcb_shm_detach_checked(xcb_connection(), m_shm_info.shmseg); xcb_generic_error_t *error = xcb_request_check(xcb_connection(), cookie); if (error) @@ -425,9 +436,9 @@ void QXcbBackingStoreImage::destroyShmSegment(size_t segmentSize) #ifdef XCB_USE_SHM_FD if (connection()->hasShmFd()) { - if (munmap(m_shm_info.shmaddr, segmentSize) == -1) { + if (munmap(m_shm_info.shmaddr, m_segmentSize) == -1) { qCWarning(lcQpaXcb, "munmap() failed (%d: %s) for %p with size %zu", - errno, strerror(errno), m_shm_info.shmaddr, segmentSize); + errno, strerror(errno), m_shm_info.shmaddr, m_segmentSize); } } else #endif -- cgit v1.2.3 From edbac716911e49a6b0f81b328e65756f95cb1f0a Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Fri, 9 Mar 2018 12:48:16 +0100 Subject: Skip all qfocusevent test on platforms that don't support window activation Task-number: QTBUG-66846 Change-Id: Ia8b69ede9154822f78ca28e0a2470b8bfb2abef0 Reviewed-by: Shawn Rutledge --- tests/auto/other/qfocusevent/qfocusevent.pro | 2 +- tests/auto/other/qfocusevent/tst_qfocusevent.cpp | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/auto/other/qfocusevent/qfocusevent.pro b/tests/auto/other/qfocusevent/qfocusevent.pro index 5f799291c6..95445f30fa 100644 --- a/tests/auto/other/qfocusevent/qfocusevent.pro +++ b/tests/auto/other/qfocusevent/qfocusevent.pro @@ -1,4 +1,4 @@ CONFIG += testcase TARGET = tst_qfocusevent -QT += widgets testlib +QT += widgets testlib gui-private SOURCES += tst_qfocusevent.cpp diff --git a/tests/auto/other/qfocusevent/tst_qfocusevent.cpp b/tests/auto/other/qfocusevent/tst_qfocusevent.cpp index e82327bbb1..ceac02279e 100644 --- a/tests/auto/other/qfocusevent/tst_qfocusevent.cpp +++ b/tests/auto/other/qfocusevent/tst_qfocusevent.cpp @@ -38,6 +38,9 @@ #include #include +#include +#include + QT_FORWARD_DECLARE_CLASS(QWidget) class FocusLineEdit : public QLineEdit @@ -92,13 +95,16 @@ private slots: void checkReason_ActiveWindow(); private: - QWidget* testFocusWidget; + QWidget* testFocusWidget = nullptr; FocusLineEdit* childFocusWidgetOne; FocusLineEdit* childFocusWidgetTwo; }; void tst_QFocusEvent::initTestCase() { + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported on this platform."); + testFocusWidget = new QWidget( 0 ); childFocusWidgetOne = new FocusLineEdit( testFocusWidget ); childFocusWidgetOne->setGeometry( 10, 10, 180, 20 ); -- cgit v1.2.3 From 43f5377fad3f462a033d836fd71a6eb356462c11 Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Wed, 18 Jul 2018 17:51:11 +0300 Subject: Make QMessageBox window with the detailed text closable QMessageBox window ignores QCloseEvent if it was created with Ok button and the detailed text was set. But it can be closed if it contains only one button. Make it closable if there are two buttons and one of them is the "Show Details..." button. [ChangeLog][QtWidgets][QMessageBox] A message box with two buttons, one of which is the "Show Details..." button, can be closed by clicking the X button on the window's title bar. Task-number: QTBUG-69526 Change-Id: Iba09e38561eb3898dc2aecfd38d8519d512a71c1 Reviewed-by: Richard Moe Gustavsen --- src/widgets/dialogs/qmessagebox.cpp | 10 ++++++++++ tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/src/widgets/dialogs/qmessagebox.cpp b/src/widgets/dialogs/qmessagebox.cpp index 52ca88891e..6de952a1d3 100644 --- a/src/widgets/dialogs/qmessagebox.cpp +++ b/src/widgets/dialogs/qmessagebox.cpp @@ -1022,6 +1022,16 @@ void QMessageBoxPrivate::detectEscapeButton() return; } + // If there are two buttons and one of them is the "Show Details..." + // button, then make the other one the escape button + if (buttons.count() == 2 && detailsButton) { + auto idx = buttons.indexOf(detailsButton); + if (idx != -1) { + detectedEscapeButton = buttons.at(1 - idx); + return; + } + } + // if the message box has one RejectRole button, make it the escape button for (auto *button : buttons) { if (buttonBox->buttonRole(button) == QDialogButtonBox::RejectRole) { diff --git a/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp b/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp index a5058f4b6c..70f5c40bcc 100644 --- a/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp +++ b/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp @@ -329,6 +329,12 @@ void tst_QMessageBox::escapeButton() closeHelper.start(ExecCloseHelper::CloseWindow, &msgBox2); msgBox2.exec(); QVERIFY(msgBox2.clickedButton() == msgBox2.button(QMessageBox::No)); // auto detected (one No button only) + + QMessageBox msgBox3; + msgBox3.setDetailedText("Details"); + closeHelper.start(ExecCloseHelper::CloseWindow, &msgBox3); + msgBox3.exec(); + QVERIFY(msgBox3.clickedButton() == msgBox3.button(QMessageBox::Ok)); // auto detected } void tst_QMessageBox::statics() -- cgit v1.2.3 From 30e26d258bc69018b7dd6517d816cf36d5606bd3 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Thu, 9 Aug 2018 13:14:37 +0200 Subject: macOS: Handle missing key in QKeySequencePrivate::decodeString() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On macOS we pull out all the modifiers up front, which in the case of incomplete key sequences such as "Meta+Shift+" will result in an empty string as a result. The cross-platform code does not handle that case, so we need to exit early. This fixes an assert in tst_QKeySequence::parseString(). An assert has been added to QKeySequencePrivate::decodeString() to make the assumption about the 'accel' argument explicit. Change-Id: I135e62f9051a8b899202e5fb224b5d3c77bf2062 Reviewed-by: Tor Arne Vestbø --- src/gui/kernel/qkeysequence.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp index 9a9677b476..a428da8ca4 100644 --- a/src/gui/kernel/qkeysequence.cpp +++ b/src/gui/kernel/qkeysequence.cpp @@ -1062,6 +1062,8 @@ int QKeySequence::decodeString(const QString &str) int QKeySequencePrivate::decodeString(QString accel, QKeySequence::SequenceFormat format) { + Q_ASSERT(!accel.isEmpty()); + int ret = 0; accel = std::move(accel).toLower(); bool nativeText = (format == QKeySequence::NativeText); @@ -1121,7 +1123,10 @@ int QKeySequencePrivate::decodeString(QString accel, QKeySequence::SequenceForma sl = accel; } } + if (accel.isEmpty()) // Incomplete, like for "Meta+Shift+" + return Qt::Key_unknown; #endif + int i = 0; int lastI = 0; while ((i = sl.indexOf(QLatin1Char('+'), i + 1)) != -1) { -- cgit v1.2.3 From f2862b4d5def2c07b8b018532ab74a12b129db2c Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 22 May 2018 13:00:38 +0200 Subject: VNC plugin: explicitly cast int to uint16_t before calling htons Otherwise there is a -Werror=narrowing error on big-endian architectures (where htons does nothing). Task-number: QTBUG-68390 Change-Id: Idb204a81aaedb9f4fde1d5fae406da36c7a1953e Reviewed-by: Thiago Macieira (cherry-picked from b206d1c8082a9e01ad3755d311a4cf683ec35161) --- src/plugins/platforms/vnc/qvnc.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/vnc/qvnc.cpp b/src/plugins/platforms/vnc/qvnc.cpp index 44fc1c6101..ffe00de2b1 100644 --- a/src/plugins/platforms/vnc/qvnc.cpp +++ b/src/plugins/platforms/vnc/qvnc.cpp @@ -552,9 +552,9 @@ void QVncClientCursor::write(QVncClient *client) const { const quint16 tmp[6] = { htons(0), htons(1), - htons(hotspot.x()), htons(hotspot.y()), - htons(cursor.width()), - htons(cursor.height()) }; + htons(uint16_t(hotspot.x())), htons(uint16_t(hotspot.y())), + htons(uint16_t(cursor.width())), + htons(uint16_t(cursor.height())) }; socket->write((char*)tmp, sizeof(tmp)); const qint32 encoding = qToBigEndian(-239); -- cgit v1.2.3 From 8dd40e9b0931d2698ff2ee3a655aab8b4947dae8 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Thu, 9 Aug 2018 11:34:27 +0200 Subject: [macOS] Fix lower bound when searching for previous transitions The lower bound shouldn't be the smallest (positive) value representable by a double, but the *lowest* (finite) value. Task-number: QTBUG-69862 Change-Id: Ia66610e3c0f8d9643c329714607f5af573206fd8 Reviewed-by: Edward Welbourne --- src/corelib/tools/qtimezoneprivate_mac.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/tools/qtimezoneprivate_mac.mm b/src/corelib/tools/qtimezoneprivate_mac.mm index fa0dd87cfc..d3c4fbe5da 100644 --- a/src/corelib/tools/qtimezoneprivate_mac.mm +++ b/src/corelib/tools/qtimezoneprivate_mac.mm @@ -227,7 +227,7 @@ QTimeZonePrivate::Data QMacTimeZonePrivate::nextTransition(qint64 afterMSecsSinc QTimeZonePrivate::Data QMacTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const { // The native API only lets us search forward, so we need to find an early-enough start: - const NSTimeInterval lowerBound = std::numeric_limits::min(); + const NSTimeInterval lowerBound = std::numeric_limits::lowest(); const qint64 endSecs = beforeMSecsSinceEpoch / 1000; const int year = 366 * 24 * 3600; // a (long) year, in seconds NSTimeInterval prevSecs = endSecs; // sentinel for later check -- cgit v1.2.3 From 8f1851013363ae22d311881abcb1186949068270 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 14 Aug 2018 07:19:02 +0200 Subject: Silence warning about comparing signed and unsigned qxcbimage.cpp:72:26: error: comparison between signed and unsigned integer expressions [-Werror=sign-compare] Task-number: QTBUG-69923 Change-Id: Icdb4ce8cb7ce5b48d7ee3839166eb1c7c9520c78 Reviewed-by: Thiago Macieira --- src/plugins/platforms/xcb/qxcbimage.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbimage.cpp b/src/plugins/platforms/xcb/qxcbimage.cpp index e18a08755b..44c7d22344 100644 --- a/src/plugins/platforms/xcb/qxcbimage.cpp +++ b/src/plugins/platforms/xcb/qxcbimage.cpp @@ -69,7 +69,7 @@ QImage::Format imageFormatForMasks(int depth, int bits_per_pixel, int red_mask, if (red_mask == 0xff && blue_mask == 0xff0000) return QImage::Format_RGBA8888_Premultiplied; #else - if (red_mask == 0xff000000 && blue_mask == 0xff00) + if (unsigned(red_mask) == unsigned(0xff000000) && blue_mask == 0xff00) return QImage::Format_RGBA8888_Premultiplied; #endif if (red_mask == 0x3ff && blue_mask == 0x3ff00000) @@ -90,7 +90,7 @@ QImage::Format imageFormatForMasks(int depth, int bits_per_pixel, int red_mask, if (red_mask == 0xff && blue_mask == 0xff0000) return QImage::Format_RGBX8888; #else - if (red_mask == 0xff000000 && blue_mask == 0xff00) + if (unsigned(red_mask) == unsigned(0xff000000) && blue_mask == 0xff00) return QImage::Format_RGBX8888; #endif break; -- cgit v1.2.3 From 109af99261f3a3fd05954ba0f6e01b83c19dcf81 Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Fri, 10 Aug 2018 12:14:05 +0200 Subject: qdoc: Fix several minor errors to reduce qdoc warnings This update corrects several minor documentation errors that cause qdoc warnings. These include incorrect or missing \fn commands, incorrect uses of \e and \a commands together, incorrect spellings, etc. Change-Id: Ib26edef541fa3440025490bcf79cc101623e7f7b Reviewed-by: Martin Smith --- .../doc/src/objectmodel/signalsandslots.qdoc | 4 +-- src/corelib/global/qglobal.cpp | 4 +-- src/gui/kernel/qplatformgraphicsbufferhelper.cpp | 41 +++++++++++++--------- src/network/ssl/qssl.h | 2 +- src/widgets/dialogs/qcolordialog.cpp | 2 +- src/widgets/dialogs/qinputdialog.cpp | 6 ++-- src/widgets/itemviews/qtreewidget.cpp | 1 + src/widgets/widgets/qabstractspinbox.cpp | 7 ++++ src/widgets/widgets/qmenu.h | 8 ++--- src/widgets/widgets/qmenu_mac.mm | 3 ++ src/widgets/widgets/qmenubar.h | 6 ++-- src/widgets/widgets/qspinbox.cpp | 24 +++++++++---- src/xml/doc/src/xml-processing.qdoc | 4 +-- 13 files changed, 71 insertions(+), 41 deletions(-) diff --git a/src/corelib/doc/src/objectmodel/signalsandslots.qdoc b/src/corelib/doc/src/objectmodel/signalsandslots.qdoc index 213caa6c59..fcf091458a 100644 --- a/src/corelib/doc/src/objectmodel/signalsandslots.qdoc +++ b/src/corelib/doc/src/objectmodel/signalsandslots.qdoc @@ -321,8 +321,8 @@ callbacks, you'd have to find five different names and keep track of the types yourself. - \sa QLCDNumber, QObject::connect(), {Digital Clock Example}, and - {Tetrix Example}. + \sa QLCDNumber, QObject::connect(), {Digital Clock Example}, + {Tetrix Example} \section1 Signals And Slots With Default Arguments diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 9cbfda3c2c..d197688316 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -3814,14 +3814,14 @@ bool qunsetenv(const char *varName) Marks the UTF-8 encoded string literal \a sourceText for numerator dependent delayed translation in the given \a context with the given - \a disambiguation. + \a comment. The \a context is typically a class and also needs to be specified as a string literal. The string literal \a disambiguation should be a short semantic tag to tell apart otherwise identical strings. The macro tells lupdate to collect the string, and expands to an anonymous struct of the two string literals passed as \a sourceText - and \a disambiguation. + and \a comment. Example: diff --git a/src/gui/kernel/qplatformgraphicsbufferhelper.cpp b/src/gui/kernel/qplatformgraphicsbufferhelper.cpp index 2afb5e6ba5..924266997d 100644 --- a/src/gui/kernel/qplatformgraphicsbufferhelper.cpp +++ b/src/gui/kernel/qplatformgraphicsbufferhelper.cpp @@ -57,24 +57,28 @@ QT_BEGIN_NAMESPACE /*! - Convenience function to both lock and bind the buffer to a texture. This - function will first try and lock with texture read and texture write + Convenience function to both lock and bind the \a graphicsBuffer to a texture. + This function will first try to lock with texture read and texture write access. If this succeeds it will use the bindToTexture function to bind the - content to the currently bound texture. If this fail it will try and lock - with SWReadAccess and then use the bindSWToTexture convenience function. + content to the currently bound texture, and if \a premultiplied is provided, + it is set to false. - \a swizzle is suppose to be used by the caller to figure out if the Red and + If it fails, it will try to lock with SWReadAccess and then use the + bindSWToTexture convenience function. If \a premultiplied is provided, it is + passed to the bindSWToTexture() function. + + \a swizzle is meant to be used by the caller to figure out if the Red and Blue color channels need to be swizzled when rendering. \a rect is the subrect which is desired to be bounded to the texture. This - argument has a no less than semantic, meaning more (if not all) of the buffer + argument has a not less than semantic, meaning more (if not all) of the buffer can be bounded to the texture. An empty QRect is interpreted as entire buffer should be bound. The user should use the AccessTypes returned by isLocked to figure out what lock has been obtained. - returns true if the buffer has successfully been bound to the currently + Returns true if the buffer has successfully been bound to the currently bound texture, otherwise returns false. */ bool QPlatformGraphicsBufferHelper::lockAndBindToTexture(QPlatformGraphicsBuffer *graphicsBuffer, @@ -103,26 +107,29 @@ bool QPlatformGraphicsBufferHelper::lockAndBindToTexture(QPlatformGraphicsBuffer } /*! - Convenience function that uploads the current raster content to the currently bound texture. + Convenience function that uploads the current raster content to the currently + bound texture. - \a swizzleRandB is suppose to be used by the caller to figure out if the Red and + \a swizzleRandB is meant to be used by the caller to decide if the Red and Blue color channels need to be swizzled when rendering. This is an optimization. Qt often renders to software buffers interpreting pixels as unsigned ints. When these buffers are uploaded to textures and each color channel per pixel is interpreted as a byte (read sequentially), then the - Red and Blue channels are swapped. Conveniently the Alpha buffer will be - correct since Qt historically has had the alpha channel as the first + Red and Blue channels are swapped. Conveniently, the Alpha buffer will be + correct, since Qt historically has had the alpha channel as the first channel, while OpenGL typically expects the alpha channel to be the last channel. - \a subRect is the subrect which is desired to be bounded to the texture. This - argument has a no less than semantic, meaning more (if not all) of the buffer - can be bounded to the texture. An empty QRect is interpreted as entire buffer - should be bound. + \a subRect is the region to be bound to the texture. This argument has a + not less than semantic, meaning more (if not all) of the buffer can be + bound to the texture. An empty QRect is interpreted as meaning the entire + buffer should be bound. - This function fails for buffers not capable of locking to SWAccess. + This function fails if the \a graphicsBuffer is not locked to SWAccess. - Returns true on success, otherwise false. + Returns true on success, otherwise false. If \a premultipliedB is + provided, it is set according to what happens, if the function returns + true. */ bool QPlatformGraphicsBufferHelper::bindSWToTexture(const QPlatformGraphicsBuffer *graphicsBuffer, bool *swizzleRandB, bool *premultipliedB, diff --git a/src/network/ssl/qssl.h b/src/network/ssl/qssl.h index 8ab24d89e1..dd268cd86d 100644 --- a/src/network/ssl/qssl.h +++ b/src/network/ssl/qssl.h @@ -91,7 +91,7 @@ namespace QSsl { TlsV1_1OrLater, TlsV1_2OrLater, -#if QT_CONFIG(dtls) +#if QT_CONFIG(dtls) || defined(Q_CLANG_QDOC) DtlsV1_0, DtlsV1_0OrLater, DtlsV1_2, diff --git a/src/widgets/dialogs/qcolordialog.cpp b/src/widgets/dialogs/qcolordialog.cpp index e6a8ec47a4..434cedfdb9 100644 --- a/src/widgets/dialogs/qcolordialog.cpp +++ b/src/widgets/dialogs/qcolordialog.cpp @@ -2170,7 +2170,7 @@ QColor QColorDialog::getColor(const QColor &initial, QWidget *parent, const QStr and an alpha channel (transparency) value. The color+alpha is initially set to \a initial. The dialog is a child of \a parent. - If \a ok is non-null, \e *\a ok is set to true if the user clicked + If \a ok is non-null, \e {*ok} is set to true if the user clicked \uicontrol{OK}, and to false if the user clicked Cancel. If the user clicks Cancel, the \a initial value is returned. diff --git a/src/widgets/dialogs/qinputdialog.cpp b/src/widgets/dialogs/qinputdialog.cpp index 5c6e0f45a5..9a9bd173bd 100644 --- a/src/widgets/dialogs/qinputdialog.cpp +++ b/src/widgets/dialogs/qinputdialog.cpp @@ -1180,7 +1180,7 @@ void QInputDialog::done(int result) \a inputMethodHints is the input method hints that will be used in the edit widget if an input method is active. - If \a ok is nonnull \e *\a ok will be set to true if the user pressed + If \a ok is nonnull \e {*ok} will be set to true if the user pressed \uicontrol OK and to false if the user pressed \uicontrol Cancel. The dialog's parent is \a parent. The dialog will be modal and uses the specified widget \a flags. @@ -1228,7 +1228,7 @@ QString QInputDialog::getText(QWidget *parent, const QString &title, const QStri \a inputMethodHints is the input method hints that will be used in the edit widget if an input method is active. - If \a ok is nonnull \e *\a ok will be set to true if the user pressed + If \a ok is nonnull \e {*ok} will be set to true if the user pressed \uicontrol OK and to false if the user pressed \uicontrol Cancel. The dialog's parent is \a parent. The dialog will be modal and uses the specified widget \a flags. @@ -1436,7 +1436,7 @@ double QInputDialog::getDouble(QWidget *parent, const QString &title, const QStr If \a editable is true the user can enter their own text; otherwise, the user may only select one of the existing items. - If \a ok is nonnull \e *\a ok will be set to true if the user pressed + If \a ok is nonnull \e {*ok} will be set to true if the user pressed \uicontrol OK and to false if the user pressed \uicontrol Cancel. The dialog's parent is \a parent. The dialog will be modal and uses the widget \a flags. diff --git a/src/widgets/itemviews/qtreewidget.cpp b/src/widgets/itemviews/qtreewidget.cpp index d0728b1af2..a0af27115d 100644 --- a/src/widgets/itemviews/qtreewidget.cpp +++ b/src/widgets/itemviews/qtreewidget.cpp @@ -1001,6 +1001,7 @@ void QTreeModel::timerEvent(QTimerEvent *ev) */ /*! + \fn void QTreeWidgetItem::setHidden(bool hide) \since 4.2 Hides the item if \a hide is true, otherwise shows the item. diff --git a/src/widgets/widgets/qabstractspinbox.cpp b/src/widgets/widgets/qabstractspinbox.cpp index 822d896ee6..1eafb73ba8 100644 --- a/src/widgets/widgets/qabstractspinbox.cpp +++ b/src/widgets/widgets/qabstractspinbox.cpp @@ -126,6 +126,13 @@ QT_BEGIN_NAMESPACE \value StepDownEnabled */ +/*! + \enum QAbstractSpinBox::StepType + + \value DefaultStepType + \value AdaptiveDecimalStepType +*/ + /*! \fn void QAbstractSpinBox::editingFinished() diff --git a/src/widgets/widgets/qmenu.h b/src/widgets/widgets/qmenu.h index 86d927e919..628f818b5e 100644 --- a/src/widgets/widgets/qmenu.h +++ b/src/widgets/widgets/qmenu.h @@ -46,7 +46,7 @@ #include #include -#ifdef Q_OS_OSX +#if defined(Q_OS_MACOS) || defined(Q_CLANG_QDOC) Q_FORWARD_DECLARE_OBJC_CLASS(NSMenu); #endif @@ -81,7 +81,7 @@ public: QAction *addAction(const QString &text, const QObject *receiver, const char* member, const QKeySequence &shortcut = 0); QAction *addAction(const QIcon &icon, const QString &text, const QObject *receiver, const char* member, const QKeySequence &shortcut = 0); -#ifdef Q_QDOC +#ifdef Q_CLANG_QDOC template QAction *addAction(const QString &text, const QObject *receiver, PointerToMemberFunction method, const QKeySequence &shortcut = 0); template @@ -151,7 +151,7 @@ public: connect(result, &QAction::triggered, std::move(slot)); return result; } -#endif // !Q_QDOC +#endif // !Q_CLANG_QDOC QAction *addMenu(QMenu *menu); QMenu *addMenu(const QString &title); @@ -211,7 +211,7 @@ public: QPlatformMenu *platformMenu(); void setPlatformMenu(QPlatformMenu *platformMenu); -#ifdef Q_OS_OSX +#if defined(Q_OS_MACOS) || defined(Q_CLANG_QDOC) NSMenu* toNSMenu(); void setAsDockMenu(); #endif diff --git a/src/widgets/widgets/qmenu_mac.mm b/src/widgets/widgets/qmenu_mac.mm index 0d680fb4dc..0872da803d 100644 --- a/src/widgets/widgets/qmenu_mac.mm +++ b/src/widgets/widgets/qmenu_mac.mm @@ -73,6 +73,7 @@ inline QPlatformNativeInterface::NativeResourceForIntegrationFunction resolvePla /*! + \fn NSMenu *QMenu::toNSMenu() \since 5.2 Returns the native NSMenu for this menu. Available on \macos only. @@ -94,6 +95,7 @@ NSMenu *QMenu::toNSMenu() /*! + \fn void QMenu::setAsDockMenu() \since 5.2 Set this menu to be the dock menu available by option-clicking @@ -149,6 +151,7 @@ void QMenuPrivate::moveWidgetToPlatformItem(QWidget *widget, QPlatformMenuItem* #if QT_CONFIG(menubar) /*! + \fn NSMenu *QMenuBar::toNSMenu() \since 5.2 Returns the native NSMenu for this menu bar. Available on \macos only. diff --git a/src/widgets/widgets/qmenubar.h b/src/widgets/widgets/qmenubar.h index 2f071e7e3b..cf6663f94a 100644 --- a/src/widgets/widgets/qmenubar.h +++ b/src/widgets/widgets/qmenubar.h @@ -67,7 +67,7 @@ public: QAction *addAction(const QString &text); QAction *addAction(const QString &text, const QObject *receiver, const char* member); -#ifdef Q_QDOC +#ifdef Q_CLANG_QDOC template QAction *addAction(const QString &text, const Obj *receiver, PointerToMemberFunctionOrFunctor method); template @@ -91,7 +91,7 @@ public: connect(result, &QAction::triggered, std::move(slot)); return result; } -#endif // !Q_QDOC +#endif // !Q_CLANG_QDOC QAction *addMenu(QMenu *menu); QMenu *addMenu(const QString &title); @@ -121,7 +121,7 @@ public: void setCornerWidget(QWidget *w, Qt::Corner corner = Qt::TopRightCorner); QWidget *cornerWidget(Qt::Corner corner = Qt::TopRightCorner) const; -#ifdef Q_OS_OSX +#if defined(Q_OS_MACOS) || defined(Q_CLANG_QDOC) NSMenu* toNSMenu(); #endif diff --git a/src/widgets/widgets/qspinbox.cpp b/src/widgets/widgets/qspinbox.cpp index 7f29c0c52c..dcf3906dd7 100644 --- a/src/widgets/widgets/qspinbox.cpp +++ b/src/widgets/widgets/qspinbox.cpp @@ -421,8 +421,8 @@ void QSpinBox::setRange(int minimum, int maximum) } /*! - Sets the step type for the spin box: single step or adaptive - decimal step. + Sets the step type for the spin box to \a stepType, which is single + step or adaptive decimal step. Adaptive decimal step means that the step size will continuously be adjusted to one power of ten below the current \l value. So when @@ -439,7 +439,6 @@ void QSpinBox::setRange(int minimum, int maximum) \l singleStep, although it is preserved so that \l singleStep comes into effect if adaptive decimal step is later turned off. - \sa QAbstractSpinBox::groupSeparator() \since 5.12 */ @@ -449,6 +448,13 @@ void QSpinBox::setStepType(QAbstractSpinBox::StepType stepType) d->stepType = stepType; } +/*! + \property QSpinBox::stepType + \brief The step type. + + The step type can be single step or adaptive decimal step. +*/ + QAbstractSpinBox::StepType QSpinBox::stepType() const { Q_D(const QSpinBox); @@ -888,8 +894,8 @@ void QDoubleSpinBox::setRange(double minimum, double maximum) } /*! - Sets the step type for the spin box: single step or adaptive - decimal step. + Sets the step type for the spin box to \a stepType, which is single + step or adaptive decimal step. Adaptive decimal step means that the step size will continuously be adjusted to one power of ten below the current \l value. So when @@ -909,7 +915,6 @@ void QDoubleSpinBox::setRange(double minimum, double maximum) \l singleStep, although it is preserved so that \l singleStep comes into effect if adaptive decimal step is later turned off. - \sa QAbstractSpinBox::groupSeparator() \since 5.12 */ @@ -919,6 +924,13 @@ void QDoubleSpinBox::setStepType(StepType stepType) d->stepType = stepType; } +/*! + \property QDoubleSpinBox::stepType + \brief The step type. + + The step type can be single step or adaptive decimal step. +*/ + QAbstractSpinBox::StepType QDoubleSpinBox::stepType() const { Q_D(const QDoubleSpinBox); diff --git a/src/xml/doc/src/xml-processing.qdoc b/src/xml/doc/src/xml-processing.qdoc index 00c73b4465..4dfcbf4722 100644 --- a/src/xml/doc/src/xml-processing.qdoc +++ b/src/xml/doc/src/xml-processing.qdoc @@ -376,7 +376,7 @@ reported through the handler. \endtable - The \l{SAX Bookmarks example} illustrates how to subclass + The \l{SAX Bookmarks Example} illustrates how to subclass QXmlDefaultHandler to read an XML bookmark file (XBEL) and how to generate XML by hand. @@ -606,7 +606,7 @@ DOM implementation. To get started please refer to the \l QDomDocument documentation. - You might also want to take a look at the \l{DOM Bookmarks example}, + You might also want to take a look at the \l{DOM Bookmarks Example}, which illustrates how to read and write an XML bookmark file (XBEL) using DOM. */ -- cgit v1.2.3 From 1ae3db46e8e98b6c3ce07a5b35330bc75dd86bfc Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Tue, 14 Aug 2018 11:29:31 +0200 Subject: drop usages of Q_COMPILER_CLASS_ENUM It is not relevant anymore. C++11 is a hard requirement for a while already. Change-Id: Idb8fbdcd13398cc85fba583f40c2b5c4dc7c4943 Reviewed-by: Thiago Macieira --- src/corelib/io/qurl.cpp | 11 ++--------- src/plugins/platforms/windows/qwindowsmousehandler.cpp | 5 ----- src/plugins/platforms/windows/qwindowsscreen.cpp | 5 +---- src/plugins/platforms/xcb/qxcbwindow.cpp | 4 ---- 4 files changed, 3 insertions(+), 22 deletions(-) diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index f200419fcd..e531505877 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -472,16 +472,10 @@ static inline QString webDavSslTag() return QStringLiteral("@SSL"); } -#ifdef Q_COMPILER_CLASS_ENUM -# define colon_uchar : uchar -#else -# define colon_uchar -#endif - class QUrlPrivate { public: - enum Section colon_uchar { + enum Section : uchar { Scheme = 0x01, UserName = 0x02, Password = 0x04, @@ -496,7 +490,7 @@ public: FullUrl = 0xff }; - enum Flags colon_uchar { + enum Flags : uchar { IsLocalFile = 0x01 }; @@ -616,7 +610,6 @@ public: // 32-bit: 2 bytes tail padding available // 64-bit: 6 bytes tail padding available }; -#undef colon_uchar inline QUrlPrivate::QUrlPrivate() : ref(1), port(-1), diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index 87f48e0c84..c1c275144f 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -257,12 +257,7 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result) { -#ifdef Q_COMPILER_CLASS_ENUM enum : quint64 { signatureMask = 0xffffff00, miWpSignature = 0xff515700 }; -#else - static const quint64 signatureMask = 0xffffff00; - static const quint64 miWpSignature = 0xff515700; -#endif // !Q_COMPILER_CLASS_ENUM if (et == QtWindows::MouseWheelEvent) return translateMouseWheelEvent(window, hwnd, msg, result); diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp index 29165ef72c..2eaf386d42 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.cpp +++ b/src/plugins/platforms/windows/qwindowsscreen.cpp @@ -330,10 +330,7 @@ QRect QWindowsScreen::virtualGeometry(const QPlatformScreen *screen) // cf QScre return result; } -enum OrientationPreference // matching Win32 API ORIENTATION_PREFERENCE -#if defined(Q_COMPILER_CLASS_ENUM) || defined(Q_CC_MSVC) - : DWORD -#endif +enum OrientationPreference : DWORD // matching Win32 API ORIENTATION_PREFERENCE { orientationPreferenceNone = 0, orientationPreferenceLandscape = 0x1, diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index d42d95f890..e313e2f648 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -275,11 +275,7 @@ QXcbWindow::QXcbWindow(QWindow *window) setConnection(xcbScreen()->connection()); } -#ifdef Q_COMPILER_CLASS_ENUM enum : quint32 { -#else -enum { -#endif baseEventMask = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_FOCUS_CHANGE, -- cgit v1.2.3 From 4fdda5a584f7ecf68a0a9ac4006c2abd730b918c Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Thu, 2 Aug 2018 07:41:03 +0200 Subject: Fix delta in QWheelEvent passed to QQuickItem While the property is deprecated, we should still set it, even in the legacy free constructor. The window system never sends x and y changes at the same time, so either coordinate will be null, therefor add them. This should restore the old behavior. Task-number: QTBUG-69089 Change-Id: Ie329cb4196f53c70b25934cbbac5e2e48c65d2b3 Reviewed-by: Mitch Curtis --- src/gui/kernel/qevent.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 2362b93bf0..2a81cdf385 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -995,10 +995,12 @@ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, QWheelEvent::QWheelEvent(QPointF pos, QPointF globalPos, QPoint pixelDelta, QPoint angleDelta, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::ScrollPhase phase, bool inverted, Qt::MouseEventSource source) - : QInputEvent(Wheel, modifiers), p(pos), g(globalPos), pixelD(pixelDelta), - angleD(angleDelta), mouseState(buttons), ph(phase), src(source), - invertedScrolling(inverted) -{} + : QInputEvent(Wheel, modifiers), p(pos), g(globalPos), pixelD(pixelDelta), angleD(angleDelta), + qt4O(qAbs(angleDelta.x()) > qAbs(angleDelta.y()) ? Qt::Horizontal : Qt::Vertical), + mouseState(buttons), ph(phase), src(source), invertedScrolling(inverted) +{ + qt4D = (qt4O == Qt::Horizontal ? angleDelta.x() : angleDelta.y()); +} #endif // QT_CONFIG(wheelevent) -- cgit v1.2.3 From 540525bceb23d63198f89a0987c4a6042b323ce0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Arve=20S=C3=A6ther?= Date: Tue, 31 Jul 2018 13:49:58 +0200 Subject: Windows QPA: Do not double delete the QTouchDevice This caused a crash on destruction because as soon as you construct a QTouchDevice it will register itself to a list of devices. On application exit the function cleanupDevicesList() in qtouchdevice.cpp would go through all registered QTouchDevices and destroy them. Therefore, there is no need to delete the QTouchDevice from QWindowsPointerHandler. This was a regression that was caused by 20d6dac63c25d227ed5315801e3e853ee78ec248 Change-Id: I58fb50016c047c3843a3f9677f2c2ef824223d43 Reviewed-by: Friedemann Kleint Reviewed-by: Andre de la Rocha --- src/plugins/platforms/windows/qwindowspointerhandler.cpp | 6 +++--- src/plugins/platforms/windows/qwindowspointerhandler.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp index f25e6d13d8..c11be972b0 100644 --- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp +++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp @@ -239,8 +239,8 @@ static QTouchDevice *createTouchDevice() QTouchDevice *QWindowsPointerHandler::ensureTouchDevice() { if (!m_touchDevice) - m_touchDevice.reset(createTouchDevice()); - return m_touchDevice.data(); + m_touchDevice = createTouchDevice(); + return m_touchDevice; } Qt::MouseButtons QWindowsPointerHandler::queryMouseButtons() @@ -400,7 +400,7 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd, touchPoints.append(touchPoint); } - QWindowSystemInterface::handleTouchEvent(window, m_touchDevice.data(), touchPoints, + QWindowSystemInterface::handleTouchEvent(window, m_touchDevice, touchPoints, QWindowsKeyMapper::queryKeyboardModifiers()); if (!(QWindowsIntegration::instance()->options() & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch)) { diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.h b/src/plugins/platforms/windows/qwindowspointerhandler.h index 11bc9419d7..c4d0e0ce4a 100644 --- a/src/plugins/platforms/windows/qwindowspointerhandler.h +++ b/src/plugins/platforms/windows/qwindowspointerhandler.h @@ -59,7 +59,7 @@ public: QWindowsPointerHandler() = default; bool translatePointerEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result); bool translateMouseEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result); - QTouchDevice *touchDevice() const { return m_touchDevice.data(); } + QTouchDevice *touchDevice() const { return m_touchDevice; } QTouchDevice *ensureTouchDevice(); Qt::MouseButtons queryMouseButtons(); QWindow *windowUnderMouse() const { return m_windowUnderPointer.data(); } @@ -70,7 +70,7 @@ private: bool translateTouchEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vTouchInfo, unsigned int count); bool translatePenEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vPenInfo); - QScopedPointer m_touchDevice; + QTouchDevice *m_touchDevice = nullptr; QHash m_lastTouchPositions; QPointer m_windowUnderPointer; QPointer m_currentWindow; -- cgit v1.2.3 From 1a350077ff6aae315b87f220276f3fba8038d93d Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Tue, 14 Aug 2018 09:03:57 +0200 Subject: Revert "macOS: Don't call [NSOpenGLContext update] for every frame" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 823acb069d92b68b36f1b2bb59575bb0595275b4. It caused some test failures in qtdeclarative and etc. Task-number: QTBUG-69891 Change-Id: I2e4038a46de254834e6389c63f6dad0c2e523b8e Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/qcocoaglcontext.h | 9 +- src/plugins/platforms/cocoa/qcocoaglcontext.mm | 132 ++++++--------------- .../platforms/cocoa/qcocoanativeinterface.mm | 4 + src/plugins/platforms/cocoa/qcocoawindow.h | 8 ++ src/plugins/platforms/cocoa/qcocoawindow.mm | 22 ++++ 5 files changed, 76 insertions(+), 99 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.h b/src/plugins/platforms/cocoa/qcocoaglcontext.h index 3f7966b247..0e5934bc23 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.h +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.h @@ -41,9 +41,6 @@ #define QCOCOAGLCONTEXT_H #include -#include -#include - #include #include #include @@ -68,6 +65,8 @@ public: bool isSharing() const override; bool isValid() const override; + void windowWasHidden(); + NSOpenGLContext *nativeContext() const; QFunctionPointer getProcAddress(const char *procName) override; @@ -75,14 +74,14 @@ public: private: static NSOpenGLPixelFormat *pixelFormatForSurfaceFormat(const QSurfaceFormat &format); - bool setDrawable(QPlatformSurface *surface); + bool setActiveWindow(QWindow *window); void updateSurfaceFormat(); NSOpenGLContext *m_context = nil; NSOpenGLContext *m_shareContext = nil; QSurfaceFormat m_format; + QPointer m_currentWindow; bool m_didCheckForSoftwareContext = false; - QVarLengthArray m_observers; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm index cba9e90a78..4d0fa2e28e 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm @@ -41,8 +41,6 @@ #include "qcocoawindow.h" #include "qcocoahelpers.h" #include -#include -#include #include #include #include @@ -322,6 +320,9 @@ void QCocoaGLContext::updateSurfaceFormat() QCocoaGLContext::~QCocoaGLContext() { + if (m_currentWindow && m_currentWindow.data()->handle()) + static_cast(m_currentWindow.data()->handle())->setCurrentContext(0); + [m_context release]; } @@ -330,14 +331,6 @@ bool QCocoaGLContext::makeCurrent(QPlatformSurface *surface) qCDebug(lcQpaOpenGLContext) << "Making" << m_context << "current" << "in" << QThread::currentThread() << "for" << surface; - // No need to make context current if it already is. This also ensures - // that we only lock the context once, meaning we don't need to keep - // track of how many times we've locked it to undo it in doneCurrent(). - // Note that we're not using QOpenGLContext::currentContext() here, as - // that has already been updated to match context() before this call. - if ([NSOpenGLContext currentContext] == m_context) - return true; - Q_ASSERT(surface->surface()->supportsOpenGL()); if (surface->surface()->surfaceClass() == QSurface::Offscreen) { @@ -345,14 +338,11 @@ bool QCocoaGLContext::makeCurrent(QPlatformSurface *surface) return true; } - if (!setDrawable(surface)) + QWindow *window = static_cast(surface)->window(); + if (!setActiveWindow(window)) { + qCDebug(lcQpaOpenGLContext) << "Failed to activate window, skipping makeCurrent"; return false; - - // The context may be owned and used by a dedicated render thread, but - // we will get notifications that trigger update() on the main thread, - // so we need to guard against concurrent uses of the context. We hold - // this lock until swapBuffer() or doneCurrent() gets called. - CGLLockContext(m_context.CGLContextObj); + } [m_context makeCurrentContext]; @@ -373,74 +363,43 @@ bool QCocoaGLContext::makeCurrent(QPlatformSurface *surface) } } + update(); return true; } -/*! - Sets the drawable object of the NSOpenGLContext, which is the - frame buffer that is the target of OpenGL drawing operations. -*/ -bool QCocoaGLContext::setDrawable(QPlatformSurface *surface) +bool QCocoaGLContext::setActiveWindow(QWindow *window) { - Q_ASSERT(surface->surface()->surfaceClass() == QSurface::Window); - NSView *view = static_cast(surface)->view(); - - if (view == m_context.view) + if (window == m_currentWindow.data()) return true; - m_observers.clear(); + Q_ASSERT(window->handle()); + QCocoaWindow *cocoaWindow = static_cast(window->handle()); + NSView *view = cocoaWindow->view(); if ((m_context.view = view) != view) { - qCInfo(lcQpaOpenGLContext) << "Failed to set" << view << "as drawable for" << m_context; + qCDebug(lcQpaOpenGLContext) << "Associating" << view << "with" << m_context << "failed"; return false; } - qCInfo(lcQpaOpenGLContext) << "Set drawable for" << m_context << "to" << m_context.view; - - auto updateCallback = [&]() { update(); }; + qCDebug(lcQpaOpenGLContext) << m_context << "now associated with" << m_context.view; - if (view.layer) { - m_observers.append(QMacScopedObserver(view, NSViewFrameDidChangeNotification, updateCallback)); - m_observers.append(QMacScopedObserver(view.window, NSWindowDidChangeScreenNotification, updateCallback)); - } else { - m_observers.append(QMacScopedObserver(view, NSViewGlobalFrameDidChangeNotification, updateCallback)); - } + if (m_currentWindow && m_currentWindow.data()->handle()) + static_cast(m_currentWindow.data()->handle())->setCurrentContext(0); - m_observers.append(QMacScopedObserver([NSApplication sharedApplication], - NSApplicationDidChangeScreenParametersNotification, updateCallback)); + m_currentWindow = window; + cocoaWindow->setCurrentContext(this); return true; } -// NSOpenGLContext is not re-entrant, which means that even when using separate -// contexts per thread, per view, and window, calls into the API will still deadlock. -// Note that this is different from the use of CGLLockContext and CGLUnlockContext -// to prevent concurrent access to the _same_ context from two different threads. -// The latter is expected due to NSOpenGLContext not being thread-safe, while the -// former is working around bugs in NSOpenGLContext that make it not re-entrant. -// For more information see https://openradar.appspot.com/37064579 +// NSOpenGLContext is not re-entrant (https://openradar.appspot.com/37064579) static QMutex s_contextMutex; void QCocoaGLContext::update() { - // Updating the context may result in a call to [NSSurface setFrame:], which - // will recurse back here through NSViewGlobalFrameDidChangeNotification. We - // could use a recursive mutex to prevent a deadlock, but since they are slower - // we opt for a manual recursion check. - static QAtomicPointer updatingThread = nullptr; - if (updatingThread == QThread::currentThreadId()) - return; - - // Guard against concurrent access to the context in the case where there - // is a dedicated render thread operating on the context. See makeCurrent(). - CGLLockContext(m_context.CGLContextObj); - QMutexLocker locker(&s_contextMutex); - QScopedValueRollback> rollback(updatingThread, QThread::currentThreadId()); qCInfo(lcQpaOpenGLContext) << "Updating" << m_context << "for" << m_context.view; [m_context update]; - - CGLUnlockContext(m_context.CGLContextObj); } void QCocoaGLContext::swapBuffers(QPlatformSurface *surface) @@ -451,52 +410,37 @@ void QCocoaGLContext::swapBuffers(QPlatformSurface *surface) if (surface->surface()->surfaceClass() == QSurface::Offscreen) return; // Nothing to do - if (!setDrawable(surface)) { - qCWarning(lcQpaOpenGLContext) << "Can't flush" << m_context - << "without" << surface << "as drawable"; + QWindow *window = static_cast(surface)->window(); + if (!setActiveWindow(window)) { + qCWarning(lcQpaOpenGLContext) << "Failed to activate window, skipping swapBuffers"; return; } QMutexLocker locker(&s_contextMutex); [m_context flushBuffer]; - - // We're done flushing, and should release the lock we have on the - // context. To ensure that we're not leaving the context current - // without a lock held on it, we need to couple this with actually - // clearing the context. This should not be a performance hit for the - // case where the same context is made current and then cleared, and - // QOpenGLContext::swapBuffers is documented as requiring makeCurrent - // again before beginning a new frame, so the user can't expect the - // context to be current after a call to swapBuffers(). We explicitly - // go via QOpenGLContext for this, instead of calling our platform - // method directly, as that will ensure QOpenGLContext records the - // fact that there is no longer a current context. We then end up - // in QCocoaGLContext::doneCurrent, where we clear the lock. - context()->doneCurrent(); } void QCocoaGLContext::doneCurrent() { - auto currentContext = QOpenGLContext::currentContext(); - if (!currentContext) - return; - - // QOpenGLContext::doneCurrent() clears the current context, but can - // be called on any context, not necessarily the current one. Since - // we rely on unlocking the context lock we must propagate the call - // to the right context. - if (context() != currentContext) { - currentContext->doneCurrent(); - return; - } - - Q_ASSERT([NSOpenGLContext currentContext] == m_context); - qCDebug(lcQpaOpenGLContext) << "Clearing current context" << [NSOpenGLContext currentContext] << "in" << QThread::currentThread(); + if (m_currentWindow && m_currentWindow.data()->handle()) + static_cast(m_currentWindow.data()->handle())->setCurrentContext(nullptr); + + m_currentWindow.clear(); + [NSOpenGLContext clearCurrentContext]; - CGLUnlockContext(m_context.CGLContextObj); +} + +void QCocoaGLContext::windowWasHidden() +{ + // If the window is hidden, we need to unset the m_currentWindow + // variable so that succeeding makeCurrent's will not abort prematurely + // because of the optimization in setActiveWindow. + // Doing a full doneCurrent here is not preferable, because the GL context + // might be rendering in a different thread at this time. + m_currentWindow.clear(); } QSurfaceFormat QCocoaGLContext::format() const diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm index 7979e430ac..228df50d86 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm @@ -102,6 +102,10 @@ void *QCocoaNativeInterface::nativeResourceForWindow(const QByteArray &resourceS if (resourceString == "nsview") { return static_cast(window->handle())->m_view; +#ifndef QT_NO_OPENGL + } else if (resourceString == "nsopenglcontext") { + return static_cast(window->handle())->currentContext()->nativeContext(); +#endif } else if (resourceString == "nswindow") { return static_cast(window->handle())->nativeWindow(); #if QT_CONFIG(vulkan) diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index 8f1bdb8af0..225c7eda84 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -169,6 +169,11 @@ public: NSUInteger windowStyleMask(Qt::WindowFlags flags); void setWindowZoomButton(Qt::WindowFlags flags); +#ifndef QT_NO_OPENGL + void setCurrentContext(QCocoaGLContext *context); + QCocoaGLContext *currentContext() const; +#endif + bool setWindowModified(bool modified) override; void setFrameStrutEventsEnabled(bool enabled) override; @@ -248,6 +253,9 @@ public: // for QNSView bool m_inSetVisible; bool m_inSetGeometry; bool m_inSetStyleMask; +#ifndef QT_NO_OPENGL + QCocoaGLContext *m_glContext; +#endif QCocoaMenuBar *m_menubar; bool m_needsInvalidateShadow; diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index b79804fd0b..3148501006 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -41,6 +41,9 @@ #include "qcocoascreen.h" #include "qnswindowdelegate.h" #include "qcocoaeventdispatcher.h" +#ifndef QT_NO_OPENGL +#include "qcocoaglcontext.h" +#endif #include "qcocoahelpers.h" #include "qcocoanativeinterface.h" #include "qnsview.h" @@ -148,6 +151,9 @@ QCocoaWindow::QCocoaWindow(QWindow *win, WId nativeHandle) , m_inSetVisible(false) , m_inSetGeometry(false) , m_inSetStyleMask(false) +#ifndef QT_NO_OPENGL + , m_glContext(nullptr) +#endif , m_menubar(nullptr) , m_needsInvalidateShadow(false) , m_hasModalSession(false) @@ -397,6 +403,10 @@ void QCocoaWindow::setVisible(bool visible) [m_view setHidden:NO]; } else { // qDebug() << "close" << this; +#ifndef QT_NO_OPENGL + if (m_glContext) + m_glContext->windowWasHidden(); +#endif QCocoaEventDispatcher *cocoaEventDispatcher = qobject_cast(QGuiApplication::instance()->eventDispatcher()); QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = nullptr; if (cocoaEventDispatcher) @@ -1324,6 +1334,18 @@ bool QCocoaWindow::windowIsPopupType(Qt::WindowType type) const return ((type & Qt::Popup) == Qt::Popup); } +#ifndef QT_NO_OPENGL +void QCocoaWindow::setCurrentContext(QCocoaGLContext *context) +{ + m_glContext = context; +} + +QCocoaGLContext *QCocoaWindow::currentContext() const +{ + return m_glContext; +} +#endif + /*! Checks if the window is the content view of its immediate NSWindow. -- cgit v1.2.3 From 23d7d5627391be1ad5a13ec6f6ec3fc8db2b1c93 Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Tue, 14 Aug 2018 12:27:41 +0200 Subject: qdoc: Fix qdoc warnings from changes to QDtls This update corrects several minor documentation errors that were introduced by a recent change to QDtls. Change-Id: I6ee6b0bf74c82dca86ba8d5f39acbd642829ec44 Reviewed-by: Timur Pocheptsov --- src/network/ssl/qdtls.cpp | 56 ++++++++++++++++++++++------------- src/network/ssl/qsslconfiguration.cpp | 2 +- src/network/ssl/qsslconfiguration.h | 2 +- 3 files changed, 37 insertions(+), 23 deletions(-) diff --git a/src/network/ssl/qdtls.cpp b/src/network/ssl/qdtls.cpp index e27bca51b9..7fc3a486a0 100644 --- a/src/network/ssl/qdtls.cpp +++ b/src/network/ssl/qdtls.cpp @@ -276,6 +276,12 @@ \sa QUdpSocket, QDtlsClientVerifier, HandshakeState, QDtlsError, QSslConfiguration */ +/*! + \typedef QDtls::GeneratorParameters + + This is a synonym for QDtlsClientVerifier::GeneratorParameters. +*/ + /*! \fn void QDtls::handshakeTimeout() @@ -447,9 +453,10 @@ QDtlsClientVerifier::QDtlsClientVerifier(QObject *parent) } /*! - Sets the secret and cryptographic hash algorithm that this QDtlsClientVerifier - will use to generate cookies. If the new secret has size zero, this function - returns \c false and does not change the previous generator parameters. + Sets the secret and the cryptographic hash algorithm from \a params. This + QDtlsClientVerifier will use these to generate cookies. If the new secret + has size zero, this function returns \c false and does not change the + cookie generator parameters. \note The secret is supposed to be a cryptographically secure sequence of bytes. @@ -481,11 +488,12 @@ QDtlsClientVerifier::GeneratorParameters QDtlsClientVerifier::cookieGeneratorPar } /*! - \a socket must be a valid pointer, \a dgram must be a non-empty datagram, - \a address cannot be null, broadcast, or multicast. This function returns - \c true if \a dgram contains a ClientHello message with a valid cookie. - If no matching cookie is found, verifyClient() will send a HelloVerifyRequest - message using \a socket and will return \c false. + \a socket must be a valid pointer, \a dgram must be a non-empty + datagram, \a address cannot be null, broadcast, or multicast. + \a port is the remote peer's port. This function returns \c true + if \a dgram contains a ClientHello message with a valid cookie. + If no matching cookie is found, verifyClient() will send a + HelloVerifyRequest message using \a socket and return \c false. The following snippet shows how a server application may check for errors: @@ -556,7 +564,7 @@ QString QDtlsClientVerifier::dtlsErrorString() const \a mode is QSslSocket::SslServerMode for a server-side DTLS connection or QSslSocket::SslClientMode for a client. - \sa sslMode(), QSslSocket::SslSocket + \sa sslMode(), QSslSocket::SslMode */ QDtls::QDtls(QSslSocket::SslMode mode, QObject *parent) : QObject(*new QDtlsPrivateOpenSSL, parent) @@ -568,9 +576,9 @@ QDtls::QDtls(QSslSocket::SslMode mode, QObject *parent) } /*! - Sets the peer's address, \a port, and host name. \a address must not be - null, multicast, or broadcast. \a verificationName is the host name used - for the certificate validation. + Sets the peer's address, \a port, and host name and returns \c true + if successful. \a address must not be null, multicast, or broadcast. + \a verificationName is the host name used for the certificate validation. \sa peerAddress(), peerPort(), peerVerificationName() */ @@ -607,7 +615,9 @@ bool QDtls::setPeer(const QHostAddress &address, quint16 port, } /*! - Sets the host name that will be used for the certificate validation. + Sets the host \a name that will be used for the certificate validation + and returns \c true if successful. + \note This function must be called before the handshake starts. \sa peerVerificationName(), setPeer() @@ -704,8 +714,9 @@ quint16 QDtls::mtuHint() const } /*! - Sets the cryptographic hash algorithm and the secret. This function is only - needed for a server-side QDtls connection. + Sets the cryptographic hash algorithm and the secret from \a params. + This function is only needed for a server-side QDtls connection. + Returns \c true if successful. \note This function must be called before the handshake starts. @@ -738,7 +749,8 @@ QDtls::GeneratorParameters QDtls::cookieGeneratorParameters() const } /*! - Sets the connection's TLS configuration from \a configuration. + Sets the connection's TLS configuration from \a configuration + and returns \c true if successful. \note This function must be called before the handshake starts. @@ -892,8 +904,10 @@ bool QDtls::continueHandshake(QUdpSocket *socket, const QByteArray &datagram) } /*! - If peer verification errors were ignored during the handshake, resumeHandshake() - resumes and completes the handshake. \a socket must be a valid pointer. + If peer verification errors were ignored during the handshake, + resumeHandshake() resumes and completes the handshake and returns + \c true. \a socket must be a valid pointer. Returns \c false if + the handshake could not be resumed. \sa doHandshake(), abortHandshake() peerVerificationErrors(), ignoreVerificationErrors() */ @@ -919,7 +933,7 @@ bool QDtls::resumeHandshake(QUdpSocket *socket) Aborts the handshake in case peer verification errors could not be ignored. \a socket must be a valid pointer. - \sa doHandshake(), resumeHandshakeAfterError() + \sa doHandshake(), resumeHandshake() */ bool QDtls::abortHandshake(QUdpSocket *socket) { @@ -1021,7 +1035,7 @@ QSsl::SslProtocol QDtls::sessionProtocol() const before writing encrypted data. \a socket must be a valid pointer. - \sa doHandshake(), handshakeState(), connectionEncrypted(), dtlsError() + \sa doHandshake(), handshakeState(), isConnectionEncrypted(), dtlsError() */ qint64 QDtls::writeDatagramEncrypted(QUdpSocket *socket, const QByteArray &dgram) { @@ -1107,7 +1121,7 @@ QVector QDtls::peerVerificationErrors() const } /*! - This method tells QDtls to ignore only the errors given in \a errors. + This method tells QDtls to ignore only the errors given in \a errorsToIgnore. If, for instance, you want to connect to a server that uses a self-signed certificate, consider the following snippet: diff --git a/src/network/ssl/qsslconfiguration.cpp b/src/network/ssl/qsslconfiguration.cpp index 12fbb9a8e4..df5660d4c3 100644 --- a/src/network/ssl/qsslconfiguration.cpp +++ b/src/network/ssl/qsslconfiguration.cpp @@ -1031,7 +1031,7 @@ void QSslConfiguration::setDefaultConfiguration(const QSslConfiguration &configu QSslConfigurationPrivate::setDefaultConfiguration(configuration); } -#if QT_CONFIG(dtls) +#if QT_CONFIG(dtls) || defined(Q_CLANG_QDOC) /*! This function returns true if DTLS cookie verification was enabled on a diff --git a/src/network/ssl/qsslconfiguration.h b/src/network/ssl/qsslconfiguration.h index 7f6028db27..454ac0cee3 100644 --- a/src/network/ssl/qsslconfiguration.h +++ b/src/network/ssl/qsslconfiguration.h @@ -162,7 +162,7 @@ public: static QSslConfiguration defaultConfiguration(); static void setDefaultConfiguration(const QSslConfiguration &configuration); -#if QT_CONFIG(dtls) +#if QT_CONFIG(dtls) || defined(Q_CLANG_QDOC) bool dtlsCookieVerificationEnabled() const; void setDtlsCookieVerificationEnabled(bool enable); -- cgit v1.2.3 From 48eb08d2555992964fd3dda8a29f9e8c8feb80eb Mon Sep 17 00:00:00 2001 From: Kevin Funk Date: Mon, 9 Jul 2018 23:40:15 +0200 Subject: tests: Fix top-level CMakeLists.txt Problem: CMake Error in CMakeLists.txt: A logical block opening on the line .../qtbase/tests/auto/cmake/CMakeLists.txt:149 (if) is not closed. Broken by change 02ed1b36daebed5f3997bb676cf5e818c0db9d3c Change-Id: I6c04721edbccaa9fcdb53af92d33dfa87eeaebb8 Reviewed-by: Rolf Eike Beer Reviewed-by: Simon Hausmann Reviewed-by: Kai Koehne --- tests/auto/cmake/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/auto/cmake/CMakeLists.txt b/tests/auto/cmake/CMakeLists.txt index ec75ec7caf..7f685b0338 100644 --- a/tests/auto/cmake/CMakeLists.txt +++ b/tests/auto/cmake/CMakeLists.txt @@ -153,3 +153,4 @@ if (NOT CMAKE_VERSION VERSION_LESS 3.8) # /usr/bin/ld: CMakeFiles/mywidget.dir/moc_mywidget.cpp.o: previous definition here # Reason: SKIP_* properties were added in CMake 3.8 only expect_pass(test_QTBUG-63422) +endif() -- cgit v1.2.3 From 0160b5a6cb25e40a61f6ab2059250a9e93ada592 Mon Sep 17 00:00:00 2001 From: Ryan Chu Date: Wed, 15 Aug 2018 07:55:46 +0000 Subject: Revert "Disable Docker-based test servers on QEMU devices temporarily" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 0eb1574b28ced49cc0134c557a1744d4af0f84e6. Required toolchain update was integrated as: 23560769c1293f7cd7754ed916db2eea42efbd32 Change-Id: I5015a780e31dce5475c8485940ca9de62230e550 Reviewed-by: Jędrzej Nowacki --- tests/auto/testserver.pri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/testserver.pri b/tests/auto/testserver.pri index 125d7f0bc6..2adf85a044 100644 --- a/tests/auto/testserver.pri +++ b/tests/auto/testserver.pri @@ -55,7 +55,7 @@ TESTSERVER_COMPOSE_FILE = $$dirname(_QMAKE_CONF_)/tests/testserver/docker-compos TESTSERVER_VERSION = $$system(docker-compose --version) TESTSERVER_IMAGES = $$system(docker images -aq "qt-test-server-*") -equals(QMAKE_HOST.os, Windows)|isEmpty(TESTSERVER_VERSION)|!linux-g++ { +equals(QMAKE_HOST.os, Windows)|isEmpty(TESTSERVER_VERSION) { # Make check with server "qt-test-server.qt-test-net" as a fallback message("testserver: qt-test-server.qt-test-net") } else { -- cgit v1.2.3 From 65491150b2077f11a101f3864d724f1a5857b2e7 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 13 Aug 2018 12:39:25 +0200 Subject: Add direct conversions between RGB30<->RGBA8888 Expands the existing conversions for ARGB32<->RGB30 to also handle RGBA8888 to avoid any performance regression of the 16bpc conversion path. Change-Id: I34e519a04276b0e7ff00c6125ba06c889045d2ac Reviewed-by: Eirik Aavitsland --- src/gui/image/qimage_conversions.cpp | 92 ++++++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 30 deletions(-) diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp index dd21ade2fd..e1f66dceee 100644 --- a/src/gui/image/qimage_conversions.cpp +++ b/src/gui/image/qimage_conversions.cpp @@ -540,11 +540,12 @@ static bool convert_RGBA_to_ARGB_inplace(QImageData *data, Qt::ImageConversionFl return true; } -template +template static void convert_RGB_to_RGB30(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) { - Q_ASSERT(src->format == QImage::Format_RGB32 || src->format == QImage::Format_ARGB32); + Q_ASSERT(RGBA || src->format == QImage::Format_RGB32 || src->format == QImage::Format_ARGB32); + Q_ASSERT(!RGBA || src->format == QImage::Format_RGBX8888 || src->format == QImage::Format_RGBA8888); Q_ASSERT(dest->format == QImage::Format_BGR30 || dest->format == QImage::Format_RGB30); Q_ASSERT(src->width == dest->width); Q_ASSERT(src->height == dest->height); @@ -557,7 +558,10 @@ static void convert_RGB_to_RGB30(QImageData *dest, const QImageData *src, Qt::Im for (int i = 0; i < src->height; ++i) { const quint32 *end = src_data + src->width; while (src_data < end) { - *dest_data = qConvertRgb32ToRgb30(*src_data); + QRgb c = *src_data; + if (RGBA) + c = RGBA2ARGB(c); + *dest_data = qConvertRgb32ToRgb30(c); ++src_data; ++dest_data; } @@ -566,10 +570,11 @@ static void convert_RGB_to_RGB30(QImageData *dest, const QImageData *src, Qt::Im } } -template +template static bool convert_RGB_to_RGB30_inplace(QImageData *data, Qt::ImageConversionFlags) { - Q_ASSERT(data->format == QImage::Format_RGB32 || data->format == QImage::Format_ARGB32); + Q_ASSERT(RGBA || (data->format == QImage::Format_RGB32 || data->format == QImage::Format_ARGB32)); + Q_ASSERT(!RGBA || (data->format == QImage::Format_RGBX8888 || data->format == QImage::Format_RGBA8888)); const int pad = (data->bytes_per_line >> 2) - data->width; QRgb *rgb_data = (QRgb *) data->data; @@ -577,7 +582,10 @@ static bool convert_RGB_to_RGB30_inplace(QImageData *data, Qt::ImageConversionFl for (int i = 0; i < data->height; ++i) { const QRgb *end = rgb_data + data->width; while (rgb_data < end) { - *rgb_data = qConvertRgb32ToRgb30(*rgb_data); + QRgb c = *rgb_data; + if (RGBA) + c = RGBA2ARGB(c); + *rgb_data = qConvertRgb32ToRgb30(c); ++rgb_data; } rgb_data += pad; @@ -738,11 +746,11 @@ static bool convert_BGR30_to_A2RGB30_inplace(QImageData *data, Qt::ImageConversi return true; } -template +template static void convert_A2RGB30_PM_to_ARGB(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) { Q_ASSERT(src->format == QImage::Format_A2RGB30_Premultiplied || src->format == QImage::Format_A2BGR30_Premultiplied); - Q_ASSERT(dest->format == QImage::Format_ARGB32); + Q_ASSERT(RGBA ? dest->format == QImage::Format_RGBA8888 : dest->format == QImage::Format_ARGB32); Q_ASSERT(src->width == dest->width); Q_ASSERT(src->height == dest->height); @@ -755,6 +763,8 @@ static void convert_A2RGB30_PM_to_ARGB(QImageData *dest, const QImageData *src, const quint32 *end = src_data + src->width; while (src_data < end) { *dest_data = qConvertA2rgb30ToArgb32(qUnpremultiplyRgb30(*src_data)); + if (RGBA) + *dest_data = ARGB2RGBA(*dest_data); ++src_data; ++dest_data; } @@ -763,7 +773,7 @@ static void convert_A2RGB30_PM_to_ARGB(QImageData *dest, const QImageData *src, } } -template +template static bool convert_A2RGB30_PM_to_ARGB_inplace(QImageData *data, Qt::ImageConversionFlags) { Q_ASSERT(data->format == QImage::Format_A2RGB30_Premultiplied || data->format == QImage::Format_A2BGR30_Premultiplied); @@ -775,11 +785,16 @@ static bool convert_A2RGB30_PM_to_ARGB_inplace(QImageData *data, Qt::ImageConver const uint *end = rgb_data + data->width; while (rgb_data < end) { *rgb_data = qConvertA2rgb30ToArgb32(qUnpremultiplyRgb30(*rgb_data)); + if (RGBA) + *rgb_data = ARGB2RGBA(*rgb_data); ++rgb_data; } rgb_data += pad; } - data->format = QImage::Format_ARGB32; + if (RGBA) + data->format = QImage::Format_RGBA8888; + else + data->format = QImage::Format_ARGB32; return true; } @@ -2354,9 +2369,9 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - convert_RGB_to_RGB30, + convert_RGB_to_RGB30, 0, - convert_RGB_to_RGB30, + convert_RGB_to_RGB30, 0, 0, 0, 0, 0, 0 @@ -2382,9 +2397,9 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat convert_ARGB_to_RGBx, convert_ARGB_to_RGBA, 0, - convert_RGB_to_RGB30, + convert_RGB_to_RGB30, 0, - convert_RGB_to_RGB30, + convert_RGB_to_RGB30, 0, 0, 0, 0, @@ -2634,7 +2649,10 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, convert_passthrough, convert_passthrough, - 0, 0, 0, 0, + convert_RGB_to_RGB30, + 0, + convert_RGB_to_RGB30, + 0, 0, 0, 0, 0, 0 }, // Format_RGBX8888 @@ -2658,7 +2676,11 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat mask_alpha_converter_RGBx, 0, 0, - 0, 0, 0, 0, 0, 0, + convert_RGB_to_RGB30, + 0, + convert_RGB_to_RGB30, + 0, + 0, 0, 0, convert_ARGB32_to_RGBA64, 0 @@ -2719,8 +2741,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - convert_A2RGB30_PM_to_ARGB, - 0, + convert_A2RGB30_PM_to_ARGB, 0, 0, 0, @@ -2732,6 +2753,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, + convert_A2RGB30_PM_to_ARGB, 0, convert_A2RGB30_PM_to_RGB30, 0, @@ -2772,8 +2794,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, - convert_A2RGB30_PM_to_ARGB, - 0, + convert_A2RGB30_PM_to_ARGB, 0, 0, 0, @@ -2785,6 +2806,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat 0, 0, 0, + convert_A2RGB30_PM_to_ARGB, 0, convert_A2RGB30_PM_to_RGB30, convert_BGR30_to_RGB30, @@ -2951,9 +2973,9 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, 0, 0, - convert_RGB_to_RGB30_inplace, + convert_RGB_to_RGB30_inplace, 0, - convert_RGB_to_RGB30_inplace, + convert_RGB_to_RGB30_inplace, 0, 0, 0, 0, 0, 0 @@ -2978,9 +3000,9 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma convert_ARGB_to_RGBA_inplace, convert_ARGB_to_RGBA_inplace, 0, - convert_RGB_to_RGB30_inplace, + convert_RGB_to_RGB30_inplace, 0, - convert_RGB_to_RGB30_inplace, + convert_RGB_to_RGB30_inplace, 0, 0, 0, 0, 0, 0 @@ -3056,7 +3078,12 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, convert_passthrough_inplace, convert_passthrough_inplace, - 0, 0, 0, 0, 0, 0, 0, 0, 0 + convert_RGB_to_RGB30_inplace, + 0, + convert_RGB_to_RGB30_inplace, + 0, + 0, 0, + 0, 0, 0 }, // Format_RGBX8888 { 0, @@ -3078,7 +3105,12 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma mask_alpha_converter_rgbx_inplace, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0 + convert_RGB_to_RGB30_inplace, + 0, + convert_RGB_to_RGB30_inplace, + 0, + 0, 0, + 0, 0, 0 }, // Format_RGBA8888 { 0, @@ -3135,8 +3167,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, 0, 0, - convert_A2RGB30_PM_to_ARGB_inplace, - 0, + convert_A2RGB30_PM_to_ARGB_inplace, 0, 0, 0, @@ -3148,6 +3179,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, 0, 0, + convert_A2RGB30_PM_to_ARGB_inplace, 0, convert_A2RGB30_PM_to_RGB30_inplace, 0, // self @@ -3187,8 +3219,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, 0, 0, - convert_A2RGB30_PM_to_ARGB_inplace, - 0, + convert_A2RGB30_PM_to_ARGB_inplace, 0, 0, 0, @@ -3200,6 +3231,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, 0, 0, + convert_A2RGB30_PM_to_ARGB_inplace, 0, convert_A2RGB30_PM_to_RGB30_inplace, convert_BGR30_to_RGB30_inplace, -- cgit v1.2.3 From 5c07efffac604ffb7c7c819b2285e0f09de5f27d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 14 Aug 2018 14:43:48 +0200 Subject: Improve QWheelEvent debug output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We now include the phase, which is helpful, and we distinguish between modern wheel events with a pixel and/or angle delta, and compatibility events sent from QWindowSystemInterface::handleWheelEvent with the old Qt 4 single value delta and orientation. Change-Id: I2efe9fe7a55c43240ec94bfa70cafaac6d52603c Reviewed-by: Shawn Rutledge Reviewed-by: Tor Arne Vestbø --- src/gui/kernel/qevent.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 2a81cdf385..49f1ba3048 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -4070,7 +4070,12 @@ QDebug operator<<(QDebug dbg, const QEvent *e) # if QT_CONFIG(wheelevent) case QEvent::Wheel: { const QWheelEvent *we = static_cast(e); - dbg << "QWheelEvent(" << "pixelDelta=" << we->pixelDelta() << ", angleDelta=" << we->angleDelta() << ')'; + dbg << "QWheelEvent(" << we->phase(); + if (!we->pixelDelta().isNull() || !we->angleDelta().isNull()) + dbg << ", pixelDelta=" << we->pixelDelta() << ", angleDelta=" << we->angleDelta(); + else if (int qt4Delta = we->delta()) + dbg << ", delta=" << qt4Delta << ", orientation=" << we->orientation(); + dbg << ')'; } break; # endif // QT_CONFIG(wheelevent) -- cgit v1.2.3 From e86b1d44247f87e38f73f0ecc3bdd1607c03cc6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 15 Aug 2018 14:49:41 +0200 Subject: Fix documentation issue for QOpenGLContext::makeCurrent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Id0118e44e1ed44fecdd803dbc57ca0588a1afec0 Reviewed-by: Leena Miettinen Reviewed-by: Martin Smith Reviewed-by: Tor Arne Vestbø --- src/gui/kernel/qopenglcontext.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp index a49599b4d1..7bf941b9a1 100644 --- a/src/gui/kernel/qopenglcontext.cpp +++ b/src/gui/kernel/qopenglcontext.cpp @@ -945,7 +945,7 @@ GLuint QOpenGLContext::defaultFramebufferObject() const Avoid calling this function from a different thread than the one the QOpenGLContext instance lives in. If you wish to use QOpenGLContext from a - different thread you should first call make sure it's not current in the + different thread you should first make sure it's not current in the current thread, by calling doneCurrent() if necessary. Then call moveToThread(otherThread) before using it in the other thread. -- cgit v1.2.3 From d47c287d70fa7ef5a04c61b1518c988de939f07f Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Wed, 15 Aug 2018 15:27:26 +0200 Subject: Document xkbcommon version Task-number: QTBUG-69276 Change-Id: I0023ce210205def958b9e18f3d3c3a63576fc871 Reviewed-by: Gatis Paeglis --- src/3rdparty/xkbcommon/qt_attribution.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/3rdparty/xkbcommon/qt_attribution.json b/src/3rdparty/xkbcommon/qt_attribution.json index 8ee0df1b22..4be9b42917 100644 --- a/src/3rdparty/xkbcommon/qt_attribution.json +++ b/src/3rdparty/xkbcommon/qt_attribution.json @@ -6,6 +6,7 @@ "Description": "xkbcommon is a keymap compiler and support library which processes a reduced subset of keymaps as defined by the XKB specification.", "Homepage": "http://xkbcommon.org/", + "Version": "0.4.1", "License": "MIT Licenses (with no-advertisement clause)", "LicenseId": "MIT", "LicenseFile": "COPYING", -- cgit v1.2.3 From b58da27aef4868ebadc14bab714675e72e82ee2a Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Mon, 13 Aug 2018 12:15:46 +0200 Subject: QDtsl::abortHandshake() - generalize the notion of 'abort' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, the function had a different name that made its purpose clear - "abort after peer verification error was encoutered". Since now it's just 'abort handshake', it also should abort an ongoing handshake, even if no peer verification error found so that we now have an API that can reset a QDtls object to its initial 'nothing done yet' state. Change-Id: Idadfec6f82d65c8f07d1c2afa4467c921c7e85c4 Reviewed-by: Mårten Nordheim Reviewed-by: Edward Welbourne Reviewed-by: Timur Pocheptsov --- src/network/ssl/qdtls.cpp | 8 ++++---- src/network/ssl/qdtls_openssl.cpp | 13 +++++++++---- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/network/ssl/qdtls.cpp b/src/network/ssl/qdtls.cpp index 7fc3a486a0..e9c462cd80 100644 --- a/src/network/ssl/qdtls.cpp +++ b/src/network/ssl/qdtls.cpp @@ -930,8 +930,8 @@ bool QDtls::resumeHandshake(QUdpSocket *socket) } /*! - Aborts the handshake in case peer verification errors could not be ignored. - \a socket must be a valid pointer. + Aborts the ongoing handshake. Returns true if one was on-going on \a socket; + otherwise, sets a suitable error and returns false. \sa doHandshake(), resumeHandshake() */ @@ -944,9 +944,9 @@ bool QDtls::abortHandshake(QUdpSocket *socket) return false; } - if (d->handshakeState != PeerVerificationFailed) { + if (d->handshakeState != PeerVerificationFailed && d->handshakeState != HandshakeInProgress) { d->setDtlsError(QDtlsError::InvalidOperation, - tr("Not in VerificationError state, nothing to abort")); + tr("No handshake in progress, nothing to abort")); return false; } diff --git a/src/network/ssl/qdtls_openssl.cpp b/src/network/ssl/qdtls_openssl.cpp index 9b11f58f2f..1f4b5a0419 100644 --- a/src/network/ssl/qdtls_openssl.cpp +++ b/src/network/ssl/qdtls_openssl.cpp @@ -1115,13 +1115,18 @@ bool QDtlsPrivateOpenSSL::resumeHandshake(QUdpSocket *socket) void QDtlsPrivateOpenSSL::abortHandshake(QUdpSocket *socket) { Q_ASSERT(socket); - Q_ASSERT(handshakeState == QDtls::PeerVerificationFailed); + Q_ASSERT(handshakeState == QDtls::PeerVerificationFailed + || handshakeState == QDtls::HandshakeInProgress); clearDtlsError(); - // Yes, while peer verification failed, we were actually encrypted. - // Let's play it nice - inform our peer about connection shut down. - sendShutdownAlert(socket); + if (handshakeState == QDtls::PeerVerificationFailed) { + // Yes, while peer verification failed, we were actually encrypted. + // Let's play it nice - inform our peer about connection shut down. + sendShutdownAlert(socket); + } else { + resetDtls(); + } } void QDtlsPrivateOpenSSL::sendShutdownAlert(QUdpSocket *socket) -- cgit v1.2.3 From c5bde010eabb79b10cea630d366d94ff5981fa57 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Wed, 15 Aug 2018 09:38:58 +0200 Subject: DTLS: load roots from system stores only if allowed Respect allowRootCertOnDemandLoading, as it's done in QSslSocket (well, almost as in QSslSocket). Change-Id: Ic6cbb24a91e92cdb20f5f749553f15a62aae8b02 Reviewed-by: Edward Welbourne --- src/network/ssl/qdtls.cpp | 1 + src/network/ssl/qdtls_openssl.cpp | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/network/ssl/qdtls.cpp b/src/network/ssl/qdtls.cpp index e9c462cd80..da37951de2 100644 --- a/src/network/ssl/qdtls.cpp +++ b/src/network/ssl/qdtls.cpp @@ -369,6 +369,7 @@ void QDtlsBasePrivate::setConfiguration(const QSslConfiguration &configuration) dtlsConfiguration.nextNegotiatedProtocol = configuration.nextNegotiatedProtocol(); dtlsConfiguration.nextProtocolNegotiationStatus = configuration.nextProtocolNegotiationStatus(); dtlsConfiguration.dtlsCookieEnabled = configuration.dtlsCookieVerificationEnabled(); + dtlsConfiguration.allowRootCertOnDemandLoading = configuration.d->allowRootCertOnDemandLoading; clearDtlsError(); } diff --git a/src/network/ssl/qdtls_openssl.cpp b/src/network/ssl/qdtls_openssl.cpp index 1f4b5a0419..8be53df24f 100644 --- a/src/network/ssl/qdtls_openssl.cpp +++ b/src/network/ssl/qdtls_openssl.cpp @@ -732,11 +732,9 @@ bool DtlsState::initCtxAndConnection(QDtlsBasePrivate *dtlsBase) configurationCopy->ref.store(0); // the QSslConfiguration constructor refs up // DTLSTODO: check we do not set something DTLS-incompatible there ... - // 'true' - means load root certs on-demand loading - double check how this - // expected to be done (QSslSocket). TlsContext newContext(QSslContext::sharedFromConfiguration(dtlsBase->mode, configurationCopy, - true)); + dtlsBase->dtlsConfiguration.allowRootCertOnDemandLoading)); if (newContext->error() != QSslError::NoError) { dtlsBase->setDtlsError(QDtlsError::TlsInitializationError, newContext->errorString()); -- cgit v1.2.3 From b7dcc3455f1270cef3b21699e909ef502374db97 Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Sat, 28 Jul 2018 14:40:12 +0200 Subject: xcb: Use functors in QXcbConnection::checkEvent() ... to check for buffered events. This makes the code less verbose and easier to read. Changed the filter signature to pass an event type in addition to the actual event, for the convenience of API user. And do not pass worthless nullptr-s to the filter. The only reason why KeyChecker from qxcbkeyboard.cpp was not converted to lambda expression is that the code looks suspicious - KeyChecker::m_release default value is 'true' and I don't see where it would ever be assigned 'false' (ref. QTBUG-69679) and the code is known to be buggy (ref. QTBUG-57335). Those issues are out-of-scope for this patch. Change-Id: If2fdd60fbb93eb983f3c9ad616aaf04834fede9f Reviewed-by: Shawn Rutledge Reviewed-by: Mikhail Svetkin --- src/plugins/platforms/xcb/qxcbclipboard.cpp | 79 +++++++--------------- src/plugins/platforms/xcb/qxcbclipboard.h | 2 +- src/plugins/platforms/xcb/qxcbconnection.cpp | 43 ++++-------- src/plugins/platforms/xcb/qxcbconnection.h | 14 ++-- src/plugins/platforms/xcb/qxcbdrag.cpp | 14 ++-- src/plugins/platforms/xcb/qxcbkeyboard.cpp | 6 +- src/plugins/platforms/xcb/qxcbwindow.cpp | 98 ++++++++-------------------- src/plugins/platforms/xcb/qxcbwindow.h | 2 - 8 files changed, 80 insertions(+), 178 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp index 24eb13326c..7b1cca4070 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.cpp +++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp @@ -807,73 +807,44 @@ bool QXcbClipboard::clipboardReadProperty(xcb_window_t win, xcb_atom_t property, return ok; } - -namespace +xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t window, int type, int timeout, bool checkManager) { - class Notify { - public: - Notify(xcb_window_t win, int t) - : window(win), type(t) {} - xcb_window_t window; - int type; - bool checkEvent(xcb_generic_event_t *event) const { - if (!event) - return false; - int t = event->response_type & 0x7f; - if (t != type) + QElapsedTimer timer; + timer.start(); + do { + auto e = connection()->checkEvent([window, type](xcb_generic_event_t *event, int eventType) { + if (eventType != type) return false; - if (t == XCB_PROPERTY_NOTIFY) { - xcb_property_notify_event_t *pn = (xcb_property_notify_event_t *)event; - if (pn->window == window) + if (eventType == XCB_PROPERTY_NOTIFY) { + auto propertyNotify = reinterpret_cast(event); + if (propertyNotify->window == window) return true; - } else if (t == XCB_SELECTION_NOTIFY) { - xcb_selection_notify_event_t *sn = (xcb_selection_notify_event_t *)event; - if (sn->requestor == window) + } else if (eventType == XCB_SELECTION_NOTIFY) { + auto selectionNotify = reinterpret_cast(event); + if (selectionNotify->requestor == window) return true; } return false; - } - }; - class ClipboardEvent { - public: - ClipboardEvent(QXcbConnection *c) - { clipboard = c->internAtom("CLIPBOARD"); } - xcb_atom_t clipboard; - bool checkEvent(xcb_generic_event_t *e) const { - if (!e) - return false; - int type = e->response_type & 0x7f; - if (type == XCB_SELECTION_REQUEST) { - xcb_selection_request_event_t *sr = (xcb_selection_request_event_t *)e; - return sr->selection == XCB_ATOM_PRIMARY || sr->selection == clipboard; - } else if (type == XCB_SELECTION_CLEAR) { - xcb_selection_clear_event_t *sc = (xcb_selection_clear_event_t *)e; - return sc->selection == XCB_ATOM_PRIMARY || sc->selection == clipboard; - } - return false; - } - }; -} - -xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t win, int type, int timeout, bool checkManager) -{ - QElapsedTimer timer; - timer.start(); - do { - Notify notify(win, type); - xcb_generic_event_t *e = connection()->checkEvent(notify); - if (e) + }); + if (e) // found the waited for event return e; if (checkManager) { auto reply = Q_XCB_REPLY(xcb_get_selection_owner, xcb_connection(), atom(QXcbAtom::CLIPBOARD_MANAGER)); if (!reply || reply->owner == XCB_NONE) - return 0; + return nullptr; } // process other clipboard events, since someone is probably requesting data from us - ClipboardEvent clipboard(connection()); - e = connection()->checkEvent(clipboard); + auto clipboardAtom = connection()->internAtom("CLIPBOARD"); + e = connection()->checkEvent([clipboardAtom](xcb_generic_event_t *event, int type) { + xcb_atom_t selection = XCB_ATOM_NONE; + if (type == XCB_SELECTION_REQUEST) + selection = reinterpret_cast(event)->selection; + else if (type == XCB_SELECTION_CLEAR) + selection = reinterpret_cast(event)->selection; + return selection == XCB_ATOM_PRIMARY || selection == clipboardAtom; + }); if (e) { connection()->handleXcbEvent(e); free(e); @@ -885,7 +856,7 @@ xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t win, int QThread::msleep(50); } while (timer.elapsed() < timeout); - return 0; + return nullptr; } QByteArray QXcbClipboard::clipboardReadIncrementalProperty(xcb_window_t win, xcb_atom_t property, int nbytes, bool nullterm) diff --git a/src/plugins/platforms/xcb/qxcbclipboard.h b/src/plugins/platforms/xcb/qxcbclipboard.h index bfeae13e10..8d0df39ac8 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.h +++ b/src/plugins/platforms/xcb/qxcbclipboard.h @@ -89,7 +89,7 @@ public: QByteArray getSelection(xcb_atom_t selection, xcb_atom_t target, xcb_atom_t property, xcb_timestamp_t t = 0); private: - xcb_generic_event_t *waitForClipboardEvent(xcb_window_t win, int type, int timeout, bool checkManager = false); + xcb_generic_event_t *waitForClipboardEvent(xcb_window_t window, int type, int timeout, bool checkManager = false); xcb_atom_t sendTargetsSelection(QMimeData *d, xcb_window_t window, xcb_atom_t property); xcb_atom_t sendSelection(QMimeData *d, xcb_atom_t target, xcb_window_t window, xcb_atom_t property); diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index c14f3f3703..1a5d9d1667 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -1484,54 +1484,35 @@ void QXcbConnection::sendConnectionEvent(QXcbAtom::Atom a, uint id) xcb_flush(xcb_connection()); } -namespace -{ - class PropertyNotifyEvent { - public: - PropertyNotifyEvent(xcb_window_t win, xcb_atom_t property) - : window(win), type(XCB_PROPERTY_NOTIFY), atom(property) {} - xcb_window_t window; - int type; - xcb_atom_t atom; - bool checkEvent(xcb_generic_event_t *event) const { - if (!event) - return false; - if ((event->response_type & ~0x80) != type) { - return false; - } else { - xcb_property_notify_event_t *pn = reinterpret_cast(event); - if ((pn->window == window) && (pn->atom == atom)) - return true; - } - return false; - } - }; -} - xcb_timestamp_t QXcbConnection::getTimestamp() { // send a dummy event to myself to get the timestamp from X server. - xcb_window_t root_win = rootWindow(); - xcb_change_property(xcb_connection(), XCB_PROP_MODE_APPEND, root_win, atom(QXcbAtom::CLIP_TEMPORARY), - XCB_ATOM_INTEGER, 32, 0, NULL); + xcb_window_t window = rootWindow(); + xcb_atom_t dummyAtom = atom(QXcbAtom::CLIP_TEMPORARY); + xcb_change_property(xcb_connection(), XCB_PROP_MODE_APPEND, window, dummyAtom, + XCB_ATOM_INTEGER, 32, 0, nullptr); connection()->flush(); - PropertyNotifyEvent checker(root_win, atom(QXcbAtom::CLIP_TEMPORARY)); - xcb_generic_event_t *event = 0; + xcb_generic_event_t *event = nullptr; // lets keep this inside a loop to avoid a possible race condition, where // reader thread has not yet had the time to acquire the mutex in order // to add the new set of events to its event queue while (!event) { connection()->sync(); - event = checkEvent(checker); + event = checkEvent([window, dummyAtom](xcb_generic_event_t *event, int type) { + if (type != XCB_PROPERTY_NOTIFY) + return false; + auto propertyNotify = reinterpret_cast(event); + return propertyNotify->window == window && propertyNotify->atom == dummyAtom; + }); } xcb_property_notify_event_t *pn = reinterpret_cast(event); xcb_timestamp_t timestamp = pn->time; free(event); - xcb_delete_property(xcb_connection(), root_win, atom(QXcbAtom::CLIP_TEMPORARY)); + xcb_delete_property(xcb_connection(), window, dummyAtom); return timestamp; } diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 0b31e9c3e7..24719a6c31 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -440,8 +440,8 @@ public: QXcbWindowEventListener *windowEventListenerFromId(xcb_window_t id); QXcbWindow *platformWindowFromId(xcb_window_t id); - template - inline xcb_generic_event_t *checkEvent(T &checker); + template + inline xcb_generic_event_t *checkEvent(Functor &&filter); typedef bool (*PeekFunc)(QXcbConnection *, xcb_generic_event_t *); void addPeekFunc(PeekFunc f); @@ -734,21 +734,21 @@ Q_DECLARE_TYPEINFO(QXcbConnection::TabletData, Q_MOVABLE_TYPE); #endif #endif -template -xcb_generic_event_t *QXcbConnection::checkEvent(T &checker) +template +xcb_generic_event_t *QXcbConnection::checkEvent(Functor &&filter) { QXcbEventArray *eventqueue = m_reader->lock(); for (int i = 0; i < eventqueue->size(); ++i) { xcb_generic_event_t *event = eventqueue->at(i); - if (checker.checkEvent(event)) { - (*eventqueue)[i] = 0; + if (event && filter(event, event->response_type & ~0x80)) { + (*eventqueue)[i] = nullptr; m_reader->unlock(); return event; } } m_reader->unlock(); - return 0; + return nullptr; } class QXcbConnectionGrabber diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index 0d72da0701..2b8e507f30 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -781,12 +781,11 @@ namespace public: ClientMessageScanner(xcb_atom_t a) : atom(a) {} xcb_atom_t atom; - bool checkEvent(xcb_generic_event_t *event) const { - if (!event) + bool operator() (xcb_generic_event_t *event, int type) const { + if (type != XCB_CLIENT_MESSAGE) return false; - if ((event->response_type & 0x7f) != XCB_CLIENT_MESSAGE) - return false; - return ((xcb_client_message_event_t *)event)->type == atom; + auto clientMessage = reinterpret_cast(event); + return clientMessage->type == atom; } }; } @@ -794,12 +793,11 @@ namespace void QXcbDrag::handlePosition(QPlatformWindow * w, const xcb_client_message_event_t *event) { xcb_client_message_event_t *lastEvent = const_cast(event); - xcb_generic_event_t *nextEvent; ClientMessageScanner scanner(atom(QXcbAtom::XdndPosition)); - while ((nextEvent = connection()->checkEvent(scanner))) { + while (auto nextEvent = connection()->checkEvent(scanner)) { if (lastEvent != event) free(lastEvent); - lastEvent = (xcb_client_message_event_t *)nextEvent; + lastEvent = reinterpret_cast(nextEvent); } handle_xdnd_position(w, lastEvent); diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index 5a2dac4a5a..37c8def6cc 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -1485,12 +1485,11 @@ public: { } - bool checkEvent(xcb_generic_event_t *ev) + bool operator() (xcb_generic_event_t *ev, int type) { if (m_error || !ev) return false; - int type = ev->response_type & ~0x80; if (type != XCB_KEY_PRESS && type != XCB_KEY_RELEASE) return false; @@ -1517,9 +1516,6 @@ public: return false; } - bool release() const { return m_release; } - xcb_timestamp_t time() const { return m_time; } - private: xcb_window_t m_window; xcb_keycode_t m_code; diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index e313e2f648..9c589771d0 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -1809,53 +1809,6 @@ bool QXcbWindow::requestSystemTrayWindowDock() return true; } -class ExposeCompressor -{ -public: - ExposeCompressor(xcb_window_t window, QRegion *region) - : m_window(window) - , m_region(region) - , m_pending(true) - { - } - - bool checkEvent(xcb_generic_event_t *event) - { - if (!event) - return false; - if ((event->response_type & ~0x80) != XCB_EXPOSE) - return false; - xcb_expose_event_t *expose = (xcb_expose_event_t *)event; - if (expose->window != m_window) - return false; - if (expose->count == 0) - m_pending = false; - *m_region |= QRect(expose->x, expose->y, expose->width, expose->height); - return true; - } - - bool pending() const - { - return m_pending; - } - -private: - xcb_window_t m_window; - QRegion *m_region; - bool m_pending; -}; - -bool QXcbWindow::compressExposeEvent(QRegion &exposeRegion) -{ - ExposeCompressor compressor(m_window, &exposeRegion); - xcb_generic_event_t *filter = 0; - do { - filter = connection()->checkEvent(compressor); - free(filter); - } while (filter); - return compressor.pending(); -} - bool QXcbWindow::handleGenericEvent(xcb_generic_event_t *event, long *result) { return QWindowSystemInterface::handleNativeEvent(window(), @@ -1867,9 +1820,24 @@ bool QXcbWindow::handleGenericEvent(xcb_generic_event_t *event, long *result) void QXcbWindow::handleExposeEvent(const xcb_expose_event_t *event) { QRect rect(event->x, event->y, event->width, event->height); - m_exposeRegion |= rect; - bool pending = compressExposeEvent(m_exposeRegion); + + bool pending = true; + xcb_generic_event_t *e = nullptr; + do { // compress expose events + e = connection()->checkEvent([this, &pending](xcb_generic_event_t *event, int type) { + if (type != XCB_EXPOSE) + return false; + auto expose = reinterpret_cast(event); + if (expose->window != m_window) + return false; + if (expose->count == 0) + pending = false; + m_exposeRegion |= QRect(expose->x, expose->y, expose->width, expose->height); + return true; + }); + free(e); + } while (e); // if count is non-zero there are more expose events pending if (event->count == 0 || !pending) { @@ -2162,24 +2130,6 @@ static bool ignoreEnterEvent(quint8 mode, quint8 detail, QXcbConnection *conn = || detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL); } -class EnterEventChecker -{ -public: - bool checkEvent(xcb_generic_event_t *event) - { - if (!event) - return false; - if ((event->response_type & ~0x80) != XCB_ENTER_NOTIFY) - return false; - - xcb_enter_notify_event_t *enter = (xcb_enter_notify_event_t *)event; - if (ignoreEnterEvent(enter->mode, enter->detail)) - return false; - - return true; - } -}; - void QXcbWindow::handleEnterNotifyEvent(int event_x, int event_y, int root_x, int root_y, quint8 mode, quint8 detail, xcb_timestamp_t timestamp) { @@ -2206,9 +2156,17 @@ void QXcbWindow::handleLeaveNotifyEvent(int root_x, int root_y, if (ignoreLeaveEvent(mode, detail, connection()) || connection()->mousePressWindow()) return; - EnterEventChecker checker; - xcb_enter_notify_event_t *enter = (xcb_enter_notify_event_t *)connection()->checkEvent(checker); - QXcbWindow *enterWindow = enter ? connection()->platformWindowFromId(enter->event) : 0; + // check if enter event is buffered + auto event = connection()->checkEvent([](xcb_generic_event_t *event, int type) { + if (type != XCB_ENTER_NOTIFY) + return false; + auto enter = reinterpret_cast(event); + if (ignoreEnterEvent(enter->mode, enter->detail)) + return false; + return true; + }); + auto enter = reinterpret_cast(event); + QXcbWindow *enterWindow = enter ? connection()->platformWindowFromId(enter->event) : nullptr; if (enterWindow) { QPoint local(enter->event_x, enter->event_y); diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 047ee2eae9..128c6e126d 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -217,8 +217,6 @@ protected: void doFocusIn(); void doFocusOut(); - bool compressExposeEvent(QRegion &exposeRegion); - void handleButtonPressEvent(int event_x, int event_y, int root_x, int root_y, int detail, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp, QEvent::Type type, Qt::MouseEventSource source = Qt::MouseEventNotSynthesized); -- cgit v1.2.3 From f79cb977e672949a2b42206c407a9f9ba7d8d544 Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Sat, 28 Jul 2018 21:47:28 +0200 Subject: xcb: remove redudant timeout arg from QXcbClipboard::waitForClipboardEvent ... clipboard_timeout is QXcbClipboard class member, accessible directly from QXcbClipboard::waitForClipboardEvent(). Change-Id: Ibc241d1da4baedc0eaf84063251a1359b1cf4162 Reviewed-by: Laszlo Agocs --- src/plugins/platforms/xcb/qxcbclipboard.cpp | 10 +++++----- src/plugins/platforms/xcb/qxcbclipboard.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp index 7b1cca4070..4be0f31b4d 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.cpp +++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp @@ -305,7 +305,7 @@ QXcbClipboard::~QXcbClipboard() connection()->sync(); // waiting until the clipboard manager fetches the content. - if (!waitForClipboardEvent(m_owner, XCB_SELECTION_NOTIFY, clipboard_timeout, true)) { + if (!waitForClipboardEvent(m_owner, XCB_SELECTION_NOTIFY, true)) { qWarning("QXcbClipboard: Unable to receive an event from the " "clipboard manager in a reasonable time"); } @@ -807,7 +807,7 @@ bool QXcbClipboard::clipboardReadProperty(xcb_window_t win, xcb_atom_t property, return ok; } -xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t window, int type, int timeout, bool checkManager) +xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t window, int type, bool checkManager) { QElapsedTimer timer; timer.start(); @@ -854,7 +854,7 @@ xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t window, i // sleep 50 ms, so we don't use up CPU cycles all the time. QThread::msleep(50); - } while (timer.elapsed() < timeout); + } while (timer.elapsed() < clipboard_timeout); return nullptr; } @@ -878,7 +878,7 @@ QByteArray QXcbClipboard::clipboardReadIncrementalProperty(xcb_window_t win, xcb for (;;) { connection()->flush(); - xcb_generic_event_t *ge = waitForClipboardEvent(win, XCB_PROPERTY_NOTIFY, clipboard_timeout); + xcb_generic_event_t *ge = waitForClipboardEvent(win, XCB_PROPERTY_NOTIFY); if (!ge) break; xcb_property_notify_event_t *event = (xcb_property_notify_event_t *)ge; @@ -941,7 +941,7 @@ QByteArray QXcbClipboard::getSelection(xcb_atom_t selection, xcb_atom_t target, connection()->sync(); - xcb_generic_event_t *ge = waitForClipboardEvent(win, XCB_SELECTION_NOTIFY, clipboard_timeout); + xcb_generic_event_t *ge = waitForClipboardEvent(win, XCB_SELECTION_NOTIFY); bool no_selection = !ge || ((xcb_selection_notify_event_t *)ge)->property == XCB_NONE; free(ge); diff --git a/src/plugins/platforms/xcb/qxcbclipboard.h b/src/plugins/platforms/xcb/qxcbclipboard.h index 8d0df39ac8..abab42a613 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.h +++ b/src/plugins/platforms/xcb/qxcbclipboard.h @@ -89,7 +89,7 @@ public: QByteArray getSelection(xcb_atom_t selection, xcb_atom_t target, xcb_atom_t property, xcb_timestamp_t t = 0); private: - xcb_generic_event_t *waitForClipboardEvent(xcb_window_t window, int type, int timeout, bool checkManager = false); + xcb_generic_event_t *waitForClipboardEvent(xcb_window_t window, int type, bool checkManager = false); xcb_atom_t sendTargetsSelection(QMimeData *d, xcb_window_t window, xcb_atom_t property); xcb_atom_t sendSelection(QMimeData *d, xcb_atom_t target, xcb_window_t window, xcb_atom_t property); -- cgit v1.2.3 From 279edd52548b2b3d0fb0566157de148d1d0ddbaf Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Sat, 11 Aug 2018 16:55:47 +0200 Subject: xcb: remove a redundant call to xcb_change_window_attributes() Few lines above we use the same attributes to create the window. If attributes don't change, there is not need to call xcb_change_window_attributes() Change-Id: I1335b8be866bdd9911d7911c87f09091bf77e955 Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbwindow.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 9c589771d0..fd0d2f9f07 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -437,8 +437,6 @@ void QXcbWindow::create() connection()->addWindowEventListener(m_window, this); - xcb_change_window_attributes(xcb_connection(), m_window, mask, values); - propagateSizeHints(); xcb_atom_t properties[5]; -- cgit v1.2.3 From 32e21762fa58be2459c43fe17ec87bd302d04d59 Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Wed, 8 Aug 2018 11:58:19 +0200 Subject: xcb: remove unused xcb_icccm.h include from qxcbclipboard.cpp Change-Id: I7afe3bece5f143f6040cf1009d6345c1fe430367 Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbclipboard.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp index 4be0f31b4d..ca2eff170d 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.cpp +++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp @@ -49,10 +49,6 @@ #include -#define class class_name // Workaround XCB-ICCCM 3.8 breakage -#include -#undef class - QT_BEGIN_NAMESPACE #ifndef QT_NO_CLIPBOARD -- cgit v1.2.3 From 21f976f4f0f79b1c4c77a402ebed88d8afb3d9e1 Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Sat, 4 Aug 2018 00:47:14 +0200 Subject: xcb: rewrite auto-repeat key detection logic It's unclear what the original code was doing. It relied on 'm_release' which could never be 'false' (ref. QTBUG-69679). It was subtracting event times and comparing with arbitrary '10'. On X11 auto-repeat keys can be detected by checking time and keycode of the current release event and the next event in the queue. If an event is an auto-repeat, then next event in the queue will be a key press with matching time and keycode. Verified that auto-repeat was unreliable in Qt 4 as well. With this patch auto-repeat works as expected. Added support for Xlib's XPeekEvent in our XCB implementation QXcbConnection::checkEvent(): "The XPeekEvent() function returns the first event from the event queue, but it does not remove the event from the queue." Sneaking in one variable renaming: "string" -> "text", to match the QKeyEvent::text(). Task-number: QTBUG-57335 Task-number: QTBUG-69679 Change-Id: I0a23f138287f57eaaecf1a009bd939e7e0e23269 Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbconnection.h | 7 +- src/plugins/platforms/xcb/qxcbkeyboard.cpp | 108 ++++++----------------------- src/plugins/platforms/xcb/qxcbkeyboard.h | 3 +- 3 files changed, 26 insertions(+), 92 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 24719a6c31..697b509bf0 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -441,7 +441,7 @@ public: QXcbWindow *platformWindowFromId(xcb_window_t id); template - inline xcb_generic_event_t *checkEvent(Functor &&filter); + inline xcb_generic_event_t *checkEvent(Functor &&filter, bool removeFromQueue = true); typedef bool (*PeekFunc)(QXcbConnection *, xcb_generic_event_t *); void addPeekFunc(PeekFunc f); @@ -735,14 +735,15 @@ Q_DECLARE_TYPEINFO(QXcbConnection::TabletData, Q_MOVABLE_TYPE); #endif template -xcb_generic_event_t *QXcbConnection::checkEvent(Functor &&filter) +xcb_generic_event_t *QXcbConnection::checkEvent(Functor &&filter, bool removeFromQueue) { QXcbEventArray *eventqueue = m_reader->lock(); for (int i = 0; i < eventqueue->size(); ++i) { xcb_generic_event_t *event = eventqueue->at(i); if (event && filter(event, event->response_type & ~0x80)) { - (*eventqueue)[i] = nullptr; + if (removeFromQueue) + (*eventqueue)[i] = nullptr; m_reader->unlock(); return event; } diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index 37c8def6cc..40100c3a62 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -1472,60 +1472,6 @@ void QXcbKeyboard::resolveMaskConflicts() } } -class KeyChecker -{ -public: - KeyChecker(xcb_window_t window, xcb_keycode_t code, xcb_timestamp_t time, quint16 state) - : m_window(window) - , m_code(code) - , m_time(time) - , m_state(state) - , m_error(false) - , m_release(true) - { - } - - bool operator() (xcb_generic_event_t *ev, int type) - { - if (m_error || !ev) - return false; - - if (type != XCB_KEY_PRESS && type != XCB_KEY_RELEASE) - return false; - - xcb_key_press_event_t *event = (xcb_key_press_event_t *)ev; - - if (event->event != m_window || event->detail != m_code || event->state != m_state) { - m_error = true; - return false; - } - - if (type == XCB_KEY_PRESS) { - m_error = !m_release || event->time - m_time > 10; - return !m_error; - } - - if (m_release) { - m_error = true; - return false; - } - - m_release = true; - m_time = event->time; - - return false; - } - -private: - xcb_window_t m_window; - xcb_keycode_t m_code; - xcb_timestamp_t m_time; - quint16 m_state; - - bool m_error; - bool m_release; -}; - void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type, xcb_keycode_t code, quint16 state, xcb_timestamp_t time, bool fromSendEvent) { @@ -1539,7 +1485,6 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type, if (type == QEvent::KeyPress) targetWindow->updateNetWmUserTime(time); - ScopedXKBState sendEventState; if (fromSendEvent) { // Have a temporary keyboard state filled in from state @@ -1557,7 +1502,7 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type, struct xkb_state *xkbState = fromSendEvent ? sendEventState.get() : m_xkbState.get(); xcb_keysym_t sym = xkb_state_key_get_one_sym(xkbState, code); - QString string = lookupString(xkbState, code); + QString text = lookupString(xkbState, code); Qt::KeyboardModifiers modifiers = translateModifiers(state); if (sym >= XKB_KEY_KP_Space && sym <= XKB_KEY_KP_9) @@ -1582,55 +1527,42 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type, int qtcode = keysymToQtKey(latinKeysym != XKB_KEY_NoSymbol ? latinKeysym : sym, modifiers, xkbState, code); - bool isAutoRepeat = false; if (type == QEvent::KeyPress) { - if (m_autorepeat_code == code) { - isAutoRepeat = true; - m_autorepeat_code = 0; - } + if (m_isAutoRepeat && m_autoRepeatCode != code) + // Some other key was pressed while we are auto-repeating on a different key. + m_isAutoRepeat = false; } else { - // look ahead for auto-repeat - KeyChecker checker(source->xcb_window(), code, time, state); - xcb_generic_event_t *event = connection()->checkEvent(checker); - if (event) { - isAutoRepeat = true; - free(event); - } - m_autorepeat_code = isAutoRepeat ? code : 0; + m_isAutoRepeat = false; + // Look at the next event in the queue to see if we are auto-repeating. + connection()->checkEvent([this, time, code](xcb_generic_event_t *event, int type) { + if (type == XCB_KEY_PRESS) { + auto keyPress = reinterpret_cast(event); + m_isAutoRepeat = keyPress->time == time && keyPress->detail == code; + if (m_isAutoRepeat) + m_autoRepeatCode = code; + } + return true; + }, false /* removeFromQueue */); } bool filtered = false; - QPlatformInputContext *inputContext = QGuiApplicationPrivate::platformIntegration()->inputContext(); - if (inputContext) { - QKeyEvent event(type, qtcode, modifiers, code, sym, state, string, isAutoRepeat, string.length()); + if (auto inputContext = QGuiApplicationPrivate::platformIntegration()->inputContext()) { + QKeyEvent event(type, qtcode, modifiers, code, sym, state, text, m_isAutoRepeat, text.size()); event.setTimestamp(time); filtered = inputContext->filterEvent(&event); } - QWindow *window = targetWindow->window(); if (!filtered) { + QWindow *window = targetWindow->window(); #ifndef QT_NO_CONTEXTMENU if (type == QEvent::KeyPress && qtcode == Qt::Key_Menu) { const QPoint globalPos = window->screen()->handle()->cursor()->pos(); const QPoint pos = window->mapFromGlobal(globalPos); QWindowSystemInterface::handleContextMenuEvent(window, false, pos, globalPos, modifiers); } -#endif // QT_NO_CONTEXTMENU +#endif QWindowSystemInterface::handleExtendedKeyEvent(window, time, type, qtcode, modifiers, - code, sym, state, string, isAutoRepeat); - } - - if (isAutoRepeat && type == QEvent::KeyRelease) { - // since we removed it from the event queue using checkEvent we need to send the key press here - filtered = false; - if (inputContext) { - QKeyEvent event(QEvent::KeyPress, qtcode, modifiers, code, sym, state, string, isAutoRepeat, string.length()); - event.setTimestamp(time); - filtered = inputContext->filterEvent(&event); - } - if (!filtered) - QWindowSystemInterface::handleExtendedKeyEvent(window, time, QEvent::KeyPress, qtcode, modifiers, - code, sym, state, string, isAutoRepeat); + code, sym, state, text, m_isAutoRepeat); } } diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h index ab926eab84..95915fb2e6 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.h +++ b/src/plugins/platforms/xcb/qxcbkeyboard.h @@ -109,7 +109,8 @@ protected: private: bool m_config = false; - xcb_keycode_t m_autorepeat_code = 0; + bool m_isAutoRepeat = false; + xcb_keycode_t m_autoRepeatCode = 0; struct _mod_masks { uint alt; -- cgit v1.2.3 From a0ebd98f58b2d92c34fafbc620f024caa36bf0ad Mon Sep 17 00:00:00 2001 From: Paolo Angelelli Date: Fri, 10 Aug 2018 14:40:10 +0200 Subject: Normalize path segments in QHttpNetworkRequest::uri MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-69659 Change-Id: I184cc460d2e3736d042893a38aa1c11b7d443f88 Reviewed-by: Jesus Fernandez Reviewed-by: Timur Pocheptsov Reviewed-by: Mårten Nordheim Reviewed-by: Thiago Macieira --- src/network/access/qhttpnetworkrequest.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/network/access/qhttpnetworkrequest.cpp b/src/network/access/qhttpnetworkrequest.cpp index cf4be3df95..8de9760710 100644 --- a/src/network/access/qhttpnetworkrequest.cpp +++ b/src/network/access/qhttpnetworkrequest.cpp @@ -133,6 +133,8 @@ QByteArray QHttpNetworkRequest::uri(bool throughProxy) const QUrl copy = d->url; if (copy.path().isEmpty()) copy.setPath(QStringLiteral("/")); + else + format |= QUrl::NormalizePathSegments; QByteArray uri = copy.toEncoded(format); return uri; } -- cgit v1.2.3 From f1a6b97fe2d3eda9455b13bb79828f250d46b92e Mon Sep 17 00:00:00 2001 From: Mikhail Svetkin Date: Sun, 29 Jul 2018 11:55:01 +0200 Subject: xcb: Add missing X11/XCB keysyms Undo, Redo, Find, Cancel It was added 558dd7f58735716d7d1f61fb5323d807b178f0c7 It was missed after 128a6eec065dfe683e6d776183d63908ca02e8fb Change-Id: I99f5c42ea45227bef08092e22d656e2d7d3cf60f Reviewed-by: Gatis Paeglis --- src/plugins/platforms/xcb/qxcbkeyboard.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index 40100c3a62..20c169fc53 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -161,6 +161,13 @@ static constexpr const auto KeyTbl = qMakeArray( Xkb2Qt, Xkb2Qt, + // special non-XF86 function keys + + Xkb2Qt, + Xkb2Qt, + Xkb2Qt, + Xkb2Qt, + // International input method support keys // International & multi-key character composition -- cgit v1.2.3 From 30c973c93c182d53ba502cb30af7fb57bb222b0a Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Thu, 9 Aug 2018 15:12:28 +0200 Subject: Rework tst_QLocale::emptyCtor() as a data-driven test That way, we'll get told all the cases that fail, rather than only the first. Provoked by investigation of failures that turned out to be caused by QTBUG-69875. Change-Id: I8fa2902cbbcb307cbe1fdec2e7d8d6b0c3eb998a Reviewed-by: Erik Verbruggen --- tests/auto/corelib/tools/qlocale/tst_qlocale.cpp | 146 ++++++++++++++--------- 1 file changed, 88 insertions(+), 58 deletions(-) diff --git a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp index 7efcd14d33..2f533b4914 100644 --- a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp +++ b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp @@ -78,6 +78,7 @@ private slots: #endif void ctor(); + void emptyCtor_data(); void emptyCtor(); void consistentC(); void matchingLocales(); @@ -157,6 +158,7 @@ private slots: private: QString m_decimal, m_thousand, m_sdate, m_ldate, m_time; QString m_sysapp; + QStringList cleanEnv; bool europeanTimeZone; }; @@ -189,6 +191,14 @@ void tst_QLocale::initTestCase() QVERIFY2(fi.exists() && fi.isExecutable(), qPrintable(QDir::toNativeSeparators(m_sysapp) + QStringLiteral(" does not exist or is not executable."))); + + // Get an environment free of any locale-related variables + cleanEnv.clear(); + foreach (QString const& entry, QProcess::systemEnvironment()) { + if (entry.startsWith("LANG=") || entry.startsWith("LC_") || entry.startsWith("LANGUAGE=")) + continue; + cleanEnv << entry; + } #endif // QT_CONFIG(process) } @@ -528,81 +538,101 @@ static inline bool runSysAppTest(const QString &binary, } #endif -void tst_QLocale::emptyCtor() +void tst_QLocale::emptyCtor_data() { #if !QT_CONFIG(process) QSKIP("No qprocess support", SkipAll); -#else +#endif #ifdef Q_OS_ANDROID QSKIP("This test crashes on Android"); #endif -#define TEST_CTOR(req_lc, exp_str) \ - { \ - /* Test constructor without arguments. Needs separate process */ \ - /* because of caching of the system locale. */ \ - QString errorMessage; \ - QVERIFY2(runSysAppTest(m_sysapp, env, QLatin1String(req_lc), QLatin1String(exp_str), &errorMessage), \ - qPrintable(errorMessage)); \ - } - - // Get an environment free of any locale-related variables - QStringList env; - foreach (QString const& entry, QProcess::systemEnvironment()) { - if (entry.startsWith("LANG=") || entry.startsWith("LC_") || entry.startsWith("LANGUAGE=")) - continue; - env << entry; - } + QTest::addColumn("expected"); + +#define ADD_CTOR_TEST(give, expect) QTest::newRow(give) << QStringLiteral(expect); + + // For format and meaning, see: + // http://pubs.opengroup.org/onlinepubs/7908799/xbd/envvar.html + // Note that the accepted values for fields are implementation-dependent; + // the template is language[_territory][.codeset][@modifier] + + // Vanilla: + ADD_CTOR_TEST("C", "C"); + + // Standard forms: + ADD_CTOR_TEST("en", "en_US"); + ADD_CTOR_TEST("en_GB", "en_GB"); + ADD_CTOR_TEST("de", "de_DE"); + // Norsk has some quirks: + ADD_CTOR_TEST("no", "nb_NO"); + ADD_CTOR_TEST("nb", "nb_NO"); + ADD_CTOR_TEST("nn", "nn_NO"); + ADD_CTOR_TEST("no_NO", "nb_NO"); + ADD_CTOR_TEST("nb_NO", "nb_NO"); + ADD_CTOR_TEST("nn_NO", "nn_NO"); + + // Not too fussy about case: + ADD_CTOR_TEST("DE", "de_DE"); + ADD_CTOR_TEST("EN", "en_US"); + + // Invalid fields + ADD_CTOR_TEST("bla", "C"); + ADD_CTOR_TEST("zz", "C"); + ADD_CTOR_TEST("zz_zz", "C"); + ADD_CTOR_TEST("zz...", "C"); + ADD_CTOR_TEST("en.bla", "en_US"); + ADD_CTOR_TEST("en@bla", "en_US"); + ADD_CTOR_TEST("en_blaaa", "en_US"); + ADD_CTOR_TEST("en_zz", "en_US"); + ADD_CTOR_TEST("en_GB.bla", "en_GB"); + ADD_CTOR_TEST("en_GB@.bla", "en_GB"); + ADD_CTOR_TEST("en_GB@bla", "en_GB"); + + // Empty optional fields, but with punctuators supplied + ADD_CTOR_TEST("en.", "en_US"); + ADD_CTOR_TEST("en@", "en_US"); + ADD_CTOR_TEST("en.@", "en_US"); + ADD_CTOR_TEST("en_", "en_US"); + ADD_CTOR_TEST("en_.", "en_US"); + ADD_CTOR_TEST("en_.@", "en_US"); +#undef ADD_CTOR_TEST + +#if QT_CONFIG(process) // for runSysApp // Get default locale. QString defaultLoc; QString errorMessage; - QVERIFY2(runSysApp(m_sysapp, env, &defaultLoc, &errorMessage), - qPrintable(errorMessage)); - - TEST_CTOR("C", "C") - TEST_CTOR("bla", "C") - TEST_CTOR("zz", "C") - TEST_CTOR("zz_zz", "C") - TEST_CTOR("zz...", "C") - TEST_CTOR("en", "en_US") - TEST_CTOR("en", "en_US") - TEST_CTOR("en.", "en_US") - TEST_CTOR("en@", "en_US") - TEST_CTOR("en.@", "en_US") - TEST_CTOR("en_", "en_US") - TEST_CTOR("en_.", "en_US") - TEST_CTOR("en_.@", "en_US") - TEST_CTOR("en.bla", "en_US") - TEST_CTOR("en@bla", "en_US") - TEST_CTOR("en_blaaa", "en_US") - TEST_CTOR("en_zz", "en_US") - TEST_CTOR("en_GB", "en_GB") - TEST_CTOR("en_GB.bla", "en_GB") - TEST_CTOR("en_GB@.bla", "en_GB") - TEST_CTOR("en_GB@bla", "en_GB") - TEST_CTOR("de", "de_DE") - - QVERIFY(QLocale::Norwegian == QLocale::NorwegianBokmal); - TEST_CTOR("no", "nb_NO") - TEST_CTOR("nb", "nb_NO") - TEST_CTOR("nn", "nn_NO") - TEST_CTOR("no_NO", "nb_NO") - TEST_CTOR("nb_NO", "nb_NO") - TEST_CTOR("nn_NO", "nn_NO") + if (runSysApp(m_sysapp, cleanEnv, &defaultLoc, &errorMessage)) { +#define ADD_CTOR_TEST(give) QTest::newRow(give) << defaultLoc; + ADD_CTOR_TEST("en/"); + ADD_CTOR_TEST("asdfghj"); + ADD_CTOR_TEST("123456"); +#undef ADD_CTOR_TEST + } else { + qDebug() << "Skipping tests based on default locale" << qPrintable(errorMessage); + } +#endif // process +} - TEST_CTOR("DE", "de_DE"); - TEST_CTOR("EN", "en_US"); +void tst_QLocale::emptyCtor() +{ +#if QT_CONFIG(process) // for runSysAppTest + QLatin1String request(QTest::currentDataTag()); + QFETCH(QString, expected); - TEST_CTOR("en/", defaultLoc.toLatin1()) - TEST_CTOR("asdfghj", defaultLoc.toLatin1()); - TEST_CTOR("123456", defaultLoc.toLatin1()); + // Test constructor without arguments (see syslocaleapp/syslocaleapp.cpp) + // Needs separate process because of caching of the system locale. + QString errorMessage; + QVERIFY2(runSysAppTest(m_sysapp, cleanEnv, request, expected, &errorMessage), + qPrintable(errorMessage)); -#undef TEST_CTOR -#endif +#else + // This won't be called, as _data() skipped out early. +#endif // process } void tst_QLocale::legacyNames() { + QVERIFY(QLocale::Norwegian == QLocale::NorwegianBokmal); QLocale::setDefault(QLocale(QLocale::C)); #define TEST_CTOR(req_lang, req_country, exp_lang, exp_country) \ -- cgit v1.2.3 From d363113745edab3a52da009837f0f940409234aa Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Mon, 13 Aug 2018 14:08:11 +0200 Subject: Normalise spacing in Language, Country and Script names The scripts that generate the C++ enum names clean out spaces, so there's no need for enumdata.py to use the squished names; instead, include spaces where they belong and use them in the relevant names where they show up. Change-Id: I7261c87d69e654bc2e89f44d7ebbc06bfb403c58 Reviewed-by: Thiago Macieira --- src/corelib/tools/qlocale_data_p.h | 1942 ++++++++++++++++++------------------ util/local_database/enumdata.py | 1528 ++++++++++++++-------------- 2 files changed, 1735 insertions(+), 1735 deletions(-) diff --git a/src/corelib/tools/qlocale_data_p.h b/src/corelib/tools/qlocale_data_p.h index 723b40beda..aeeec2b085 100644 --- a/src/corelib/tools/qlocale_data_p.h +++ b/src/corelib/tools/qlocale_data_p.h @@ -977,7 +977,7 @@ static const quint16 locale_index[] = { 294, // Mongolian 0, // Nauru 296, // Nepali - 298, // NorwegianBokmal + 298, // Norwegian Bokmal 300, // Occitan 301, // Oriya 302, // Pashto @@ -1033,7 +1033,7 @@ static const quint16 locale_index[] = { 421, // Yoruba 0, // Zhuang 423, // Zulu - 424, // NorwegianNynorsk + 424, // Norwegian Nynorsk 425, // Bosnian 427, // Divehi 428, // Manx @@ -1122,7 +1122,7 @@ static const quint16 locale_index[] = { 0, // Kongo 0, // Kwanyama 0, // Limburgish - 515, // LubaKatanga + 515, // Luba Katanga 516, // Luxembourgish 0, // Navaho 0, // Ndonga @@ -1133,10 +1133,10 @@ static const quint16 locale_index[] = { 519, // Basaa 520, // Zarma 521, // Duala - 522, // JolaFonyi + 522, // Jola Fonyi 523, // Ewondo 524, // Bafia - 525, // MakhuwaMeetto + 525, // Makhuwa Meetto 526, // Mundang 527, // Kwasio 528, // Nuer @@ -1155,26 +1155,26 @@ static const quint16 locale_index[] = { 540, // Ngiemboon 0, // Aragonese 0, // Akkadian - 0, // AncientEgyptian - 0, // AncientGreek + 0, // Ancient Egyptian + 0, // Ancient Greek 0, // Aramaic 0, // Balinese 0, // Bamun - 0, // BatakToba + 0, // Batak Toba 0, // Buginese 0, // Buhid 0, // Carian 0, // Chakma - 0, // ClassicalMandaic + 0, // Classical Mandaic 0, // Coptic 0, // Dogri - 0, // EasternCham - 0, // EasternKayah + 0, // Eastern Cham + 0, // Eastern Kayah 0, // Etruscan 0, // Gothic 0, // Hanunoo 0, // Ingush - 0, // LargeFloweryMiao + 0, // Large Flowery Miao 0, // Lepcha 0, // Limbu 0, // Lisu @@ -1184,15 +1184,15 @@ static const quint16 locale_index[] = { 0, // Mandingo 541, // Manipuri 0, // Meroitic - 0, // NorthernThai - 0, // OldIrish - 0, // OldNorse - 0, // OldPersian - 0, // OldTurkish + 0, // Northern Thai + 0, // Old Irish + 0, // Old Norse + 0, // Old Persian + 0, // Old Turkish 0, // Pahlavi 0, // Parthian 0, // Phoenician - 0, // PrakritLanguage + 0, // Prakrit Language 0, // Rejang 0, // Sabaean 0, // Samaritan @@ -1201,16 +1201,16 @@ static const quint16 locale_index[] = { 0, // Sora 0, // Sylheti 0, // Tagbanwa - 542, // TaiDam - 0, // TaiNua + 542, // Tai Dam + 0, // Tai Nua 0, // Ugaritic 543, // Akoose 544, // Lakota 545, // Standard Moroccan Tamazight 546, // Mapuche 547, // Central Kurdish - 549, // LowerSorbian - 550, // UpperSorbian + 549, // Lower Sorbian + 550, // Upper Sorbian 551, // Kenyang 552, // Mohawk 553, // Nko @@ -1248,7 +1248,7 @@ static const quint16 locale_index[] = { 0, // Tokelau 0, // Tok Pisin 0, // Tuvalu - 0, // UncodedLanguages + 0, // Uncoded Languages 564, // Cantonese 0, // Osage 0, // Tangut @@ -1261,7 +1261,7 @@ static const QLocaleData locale_data[] = { { 3, 7, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 35,18 , 18,7 , 25,12 , 185,48 , 233,111 , 134,24 , 185,48 , 233,111 , 134,24 , 113,28 , 141,55 , 85,14 , 113,28 , 141,55 , 85,14 , 2,2 , 2,2 , 45,4 , 5,17 , 22,23 , {69,84,66}, 0,2 , 7,24 , 4,4 , 4,0 , 0,6 , 6,10 , 2, 1, 7, 6, 7 }, // Oromo/Latin/Ethiopia { 3, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 35,18 , 37,5 , 8,10 , 185,48 , 233,111 , 344,24 , 185,48 , 233,111 , 134,24 , 113,28 , 141,55 , 196,14 , 113,28 , 141,55 , 196,14 , 2,2 , 2,2 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 0,7 , 4,4 , 4,0 , 0,6 , 16,8 , 2, 1, 7, 6, 7 }, // Oromo/Latin/Kenya { 4, 7, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,84,66}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Afar/Latin/Ethiopia - { 5, 7, 195, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 6,8 , 6,8 , 53,10 , 80,18 , 37,5 , 8,10 , 416,59 , 475,92 , 134,24 , 416,59 , 475,92 , 134,24 , 210,28 , 238,58 , 296,14 , 210,28 , 238,58 , 296,14 , 4,3 , 4,3 , 49,5 , 5,17 , 22,23 , {90,65,82}, 5,1 , 31,67 , 4,4 , 4,0 , 24,9 , 33,11 , 2, 1, 7, 6, 7 }, // Afrikaans/Latin/SouthAfrica + { 5, 7, 195, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 6,8 , 6,8 , 53,10 , 80,18 , 37,5 , 8,10 , 416,59 , 475,92 , 134,24 , 416,59 , 475,92 , 134,24 , 210,28 , 238,58 , 296,14 , 210,28 , 238,58 , 296,14 , 4,3 , 4,3 , 49,5 , 5,17 , 22,23 , {90,65,82}, 5,1 , 31,67 , 4,4 , 4,0 , 24,9 , 33,11 , 2, 1, 7, 6, 7 }, // Afrikaans/Latin/South Africa { 5, 7, 148, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 6,8 , 6,8 , 53,10 , 98,16 , 37,5 , 8,10 , 416,59 , 475,92 , 134,24 , 416,59 , 475,92 , 134,24 , 210,28 , 238,58 , 296,14 , 210,28 , 238,58 , 296,14 , 4,3 , 4,3 , 49,5 , 5,17 , 22,23 , {78,65,68}, 6,1 , 98,55 , 4,4 , 4,0 , 24,9 , 44,7 , 2, 1, 1, 6, 7 }, // Afrikaans/Latin/Namibia { 6, 7, 2, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 14,9 , 14,9 , 114,6 , 10,17 , 18,7 , 42,13 , 567,50 , 617,78 , 695,27 , 722,50 , 772,78 , 850,27 , 310,28 , 338,58 , 396,15 , 310,28 , 411,58 , 396,15 , 7,11 , 7,10 , 54,4 , 5,17 , 22,23 , {65,76,76}, 7,4 , 153,45 , 13,5 , 4,0 , 51,5 , 56,8 , 0, 0, 1, 6, 7 }, // Albanian/Latin/Albania { 6, 7, 127, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 14,9 , 14,9 , 114,6 , 10,17 , 37,5 , 8,10 , 567,50 , 617,78 , 695,27 , 722,50 , 772,78 , 850,27 , 310,28 , 338,58 , 396,15 , 310,28 , 411,58 , 396,15 , 7,11 , 7,10 , 54,4 , 5,17 , 22,23 , {77,75,68}, 11,3 , 198,54 , 13,5 , 4,0 , 51,5 , 64,8 , 2, 1, 1, 6, 7 }, // Albanian/Latin/Macedonia @@ -1283,17 +1283,17 @@ static const QLocaleData locale_data[] = { { 8, 1, 136, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,17 , 18,7 , 25,12 , 1410,72 , 1410,72 , 1482,24 , 1410,72 , 1410,72 , 1482,24 , 538,52 , 538,52 , 590,14 , 538,52 , 538,52 , 590,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {77,82,85}, 0,0 , 1530,112 , 13,5 , 4,0 , 87,7 , 172,9 , 2, 1, 1, 6, 7 }, // Arabic/Arabic/Mauritania { 8, 1, 145, 44, 46, 59, 37, 48, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,17 , 37,5 , 8,10 , 1506,70 , 1506,70 , 1576,24 , 1506,70 , 1506,70 , 1576,24 , 538,52 , 538,52 , 590,14 , 538,52 , 538,52 , 590,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {77,65,68}, 70,5 , 1642,87 , 13,5 , 4,0 , 87,7 , 181,6 , 2, 1, 6, 5, 6 }, // Arabic/Arabic/Morocco { 8, 1, 162, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,17 , 18,7 , 25,12 , 1008,75 , 1008,75 , 1083,24 , 1008,75 , 1008,75 , 1083,24 , 538,52 , 538,52 , 590,14 , 538,52 , 538,52 , 590,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {79,77,82}, 75,5 , 1729,77 , 13,5 , 4,0 , 87,7 , 187,5 , 3, 0, 6, 5, 6 }, // Arabic/Arabic/Oman - { 8, 1, 165, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,17 , 18,7 , 25,12 , 1202,92 , 1202,92 , 1294,24 , 1202,92 , 1202,92 , 1294,24 , 538,52 , 538,52 , 590,14 , 538,52 , 538,52 , 590,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {73,76,83}, 49,1 , 1057,133 , 13,5 , 4,0 , 87,7 , 192,18 , 2, 1, 1, 6, 7 }, // Arabic/Arabic/PalestinianTerritories + { 8, 1, 165, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,17 , 18,7 , 25,12 , 1202,92 , 1202,92 , 1294,24 , 1202,92 , 1202,92 , 1294,24 , 538,52 , 538,52 , 590,14 , 538,52 , 538,52 , 590,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {73,76,83}, 49,1 , 1057,133 , 13,5 , 4,0 , 87,7 , 192,18 , 2, 1, 1, 6, 7 }, // Arabic/Arabic/Palestinian Territories { 8, 1, 175, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,17 , 18,7 , 25,12 , 1008,75 , 1008,75 , 1083,24 , 1008,75 , 1008,75 , 1083,24 , 538,52 , 538,52 , 590,14 , 538,52 , 538,52 , 590,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {81,65,82}, 80,5 , 1806,70 , 13,5 , 4,0 , 87,7 , 210,3 , 2, 1, 6, 5, 6 }, // Arabic/Arabic/Qatar - { 8, 1, 186, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,17 , 18,7 , 25,12 , 1008,75 , 1008,75 , 1083,24 , 1008,75 , 1008,75 , 1083,24 , 538,52 , 538,52 , 590,14 , 538,52 , 538,52 , 590,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {83,65,82}, 85,5 , 1876,77 , 13,5 , 4,0 , 87,7 , 213,24 , 2, 1, 7, 5, 6 }, // Arabic/Arabic/SaudiArabia + { 8, 1, 186, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,17 , 18,7 , 25,12 , 1008,75 , 1008,75 , 1083,24 , 1008,75 , 1008,75 , 1083,24 , 538,52 , 538,52 , 590,14 , 538,52 , 538,52 , 590,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {83,65,82}, 85,5 , 1876,77 , 13,5 , 4,0 , 87,7 , 213,24 , 2, 1, 7, 5, 6 }, // Arabic/Arabic/Saudi Arabia { 8, 1, 194, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,17 , 18,7 , 25,12 , 1008,75 , 1008,75 , 1083,24 , 1008,75 , 1008,75 , 1083,24 , 538,52 , 538,52 , 590,14 , 538,52 , 538,52 , 590,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {83,79,83}, 90,1 , 1953,77 , 13,5 , 4,0 , 87,7 , 237,7 , 0, 0, 1, 6, 7 }, // Arabic/Arabic/Somalia { 8, 1, 201, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,17 , 18,7 , 25,12 , 1008,75 , 1008,75 , 1083,24 , 1008,75 , 1008,75 , 1083,24 , 538,52 , 538,52 , 590,14 , 538,52 , 538,52 , 590,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {83,68,71}, 91,4 , 2030,91 , 13,5 , 4,0 , 87,7 , 244,7 , 2, 1, 6, 5, 6 }, // Arabic/Arabic/Sudan { 8, 1, 207, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,17 , 18,7 , 25,12 , 1202,92 , 1202,92 , 1294,24 , 1202,92 , 1202,92 , 1294,24 , 538,52 , 538,52 , 590,14 , 538,52 , 538,52 , 590,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {83,89,80}, 95,5 , 2121,77 , 13,5 , 4,0 , 87,7 , 251,5 , 0, 0, 6, 5, 6 }, // Arabic/Arabic/Syria { 8, 1, 216, 44, 46, 59, 37, 48, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,17 , 18,7 , 25,12 , 1107,71 , 1107,71 , 1178,24 , 1107,71 , 1107,71 , 1178,24 , 538,52 , 538,52 , 590,14 , 538,52 , 538,52 , 590,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {84,78,68}, 100,5 , 2198,95 , 13,5 , 4,0 , 87,7 , 256,4 , 3, 0, 7, 5, 6 }, // Arabic/Arabic/Tunisia - { 8, 1, 223, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,17 , 18,7 , 25,12 , 1008,75 , 1008,75 , 1083,24 , 1008,75 , 1008,75 , 1083,24 , 538,52 , 538,52 , 590,14 , 538,52 , 538,52 , 590,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {65,69,68}, 105,5 , 2293,91 , 13,5 , 4,0 , 87,7 , 260,24 , 2, 1, 6, 5, 6 }, // Arabic/Arabic/UnitedArabEmirates - { 8, 1, 236, 46, 44, 59, 37, 48, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,17 , 18,7 , 25,12 , 1008,75 , 1008,75 , 1083,24 , 1008,75 , 1008,75 , 1083,24 , 538,52 , 538,52 , 590,14 , 538,52 , 538,52 , 590,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {77,65,68}, 70,5 , 1642,87 , 13,5 , 4,0 , 87,7 , 284,15 , 2, 1, 1, 6, 7 }, // Arabic/Arabic/WesternSahara + { 8, 1, 223, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,17 , 18,7 , 25,12 , 1008,75 , 1008,75 , 1083,24 , 1008,75 , 1008,75 , 1083,24 , 538,52 , 538,52 , 590,14 , 538,52 , 538,52 , 590,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {65,69,68}, 105,5 , 2293,91 , 13,5 , 4,0 , 87,7 , 260,24 , 2, 1, 6, 5, 6 }, // Arabic/Arabic/United Arab Emirates + { 8, 1, 236, 46, 44, 59, 37, 48, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,17 , 18,7 , 25,12 , 1008,75 , 1008,75 , 1083,24 , 1008,75 , 1008,75 , 1083,24 , 538,52 , 538,52 , 590,14 , 538,52 , 538,52 , 590,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {77,65,68}, 70,5 , 1642,87 , 13,5 , 4,0 , 87,7 , 284,15 , 2, 1, 1, 6, 7 }, // Arabic/Arabic/Western Sahara { 8, 1, 237, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,17 , 18,7 , 25,12 , 1008,75 , 1008,75 , 1083,24 , 1008,75 , 1008,75 , 1083,24 , 538,52 , 538,52 , 590,14 , 538,52 , 538,52 , 590,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {89,69,82}, 110,5 , 2384,70 , 13,5 , 4,0 , 87,7 , 299,5 , 0, 0, 7, 5, 6 }, // Arabic/Arabic/Yemen - { 8, 1, 254, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,17 , 18,7 , 25,12 , 1008,75 , 1008,75 , 1083,24 , 1008,75 , 1008,75 , 1083,24 , 538,52 , 538,52 , 590,14 , 538,52 , 538,52 , 590,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {83,83,80}, 115,1 , 2454,132 , 13,5 , 4,0 , 87,7 , 304,12 , 2, 1, 1, 6, 7 }, // Arabic/Arabic/SouthSudan + { 8, 1, 254, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,17 , 18,7 , 25,12 , 1008,75 , 1008,75 , 1083,24 , 1008,75 , 1008,75 , 1083,24 , 538,52 , 538,52 , 590,14 , 538,52 , 538,52 , 590,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {83,83,80}, 115,1 , 2454,132 , 13,5 , 4,0 , 87,7 , 304,12 , 2, 1, 1, 6, 7 }, // Arabic/Arabic/South Sudan { 8, 1, 260, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,17 , 18,7 , 25,12 , 1008,75 , 1008,75 , 1083,24 , 1008,75 , 1008,75 , 1083,24 , 538,52 , 538,52 , 590,14 , 538,52 , 538,52 , 590,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {0,0,0}, 0,0 , 2586,0 , 13,5 , 4,0 , 316,23 , 339,6 , 2, 1, 1, 6, 7 }, // Arabic/Arabic/World { 9, 10, 11, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 65,7 , 65,7 , 174,8 , 182,20 , 37,5 , 8,10 , 1600,48 , 1648,94 , 1742,24 , 1600,48 , 1766,106 , 1742,24 , 604,28 , 632,62 , 694,14 , 604,28 , 632,62 , 694,14 , 22,2 , 22,2 , 129,6 , 135,17 , 22,23 , {65,77,68}, 116,1 , 2586,46 , 13,5 , 4,0 , 345,7 , 352,8 , 0, 0, 1, 6, 7 }, // Armenian/Armenian/Armenia { 10, 11, 100, 46, 44, 59, 37, 2534, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 72,9 , 72,9 , 202,8 , 210,18 , 68,7 , 75,12 , 1872,64 , 1936,89 , 2025,24 , 1872,64 , 1936,89 , 2025,24 , 708,32 , 740,58 , 798,14 , 708,32 , 740,58 , 798,14 , 24,9 , 24,7 , 152,4 , 156,37 , 22,23 , {73,78,82}, 117,1 , 2632,43 , 8,5 , 4,0 , 360,7 , 367,4 , 2, 1, 7, 7, 7 }, // Assamese/Bengali/India @@ -1315,30 +1315,30 @@ static const QLocaleData locale_data[] = { { 24, 7, 74, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 163,7 , 163,7 , 287,6 , 390,22 , 55,4 , 59,9 , 4285,60 , 4345,82 , 4427,36 , 4463,93 , 4556,115 , 4427,36 , 1893,28 , 1921,60 , 1981,21 , 1893,28 , 1921,60 , 1981,21 , 55,5 , 52,5 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 521,6 , 541,6 , 2, 1, 1, 6, 7 }, // Catalan/Latin/France { 24, 7, 106, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 163,7 , 163,7 , 287,6 , 390,22 , 55,4 , 59,9 , 4285,60 , 4345,82 , 4427,36 , 4463,93 , 4556,115 , 4427,36 , 1893,28 , 1921,60 , 1981,21 , 1893,28 , 1921,60 , 1981,21 , 55,5 , 52,5 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 521,6 , 547,6 , 2, 1, 1, 6, 7 }, // Catalan/Latin/Italy { 25, 5, 44, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 170,5 , 170,5 , 175,5 , 175,5 , 412,8 , 420,13 , 198,6 , 204,11 , 4671,39 , 4710,38 , 158,27 , 4671,39 , 4710,38 , 158,27 , 2002,21 , 2023,28 , 2051,14 , 2002,21 , 2023,28 , 2051,14 , 60,2 , 57,2 , 287,2 , 289,21 , 22,23 , {67,78,89}, 129,1 , 3122,13 , 4,4 , 4,0 , 553,4 , 557,2 , 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/China - { 25, 5, 97, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 170,5 , 170,5 , 175,5 , 175,5 , 287,6 , 420,13 , 198,6 , 204,11 , 4671,39 , 4710,38 , 158,27 , 4671,39 , 4710,38 , 158,27 , 2002,21 , 2023,28 , 2051,14 , 2002,21 , 2023,28 , 2051,14 , 60,2 , 57,2 , 287,2 , 289,21 , 22,23 , {72,75,68}, 130,3 , 3135,11 , 4,4 , 4,0 , 553,4 , 559,9 , 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/HongKong + { 25, 5, 97, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 170,5 , 170,5 , 175,5 , 175,5 , 287,6 , 420,13 , 198,6 , 204,11 , 4671,39 , 4710,38 , 158,27 , 4671,39 , 4710,38 , 158,27 , 2002,21 , 2023,28 , 2051,14 , 2002,21 , 2023,28 , 2051,14 , 60,2 , 57,2 , 287,2 , 289,21 , 22,23 , {72,75,68}, 130,3 , 3135,11 , 4,4 , 4,0 , 553,4 , 559,9 , 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/Hong Kong { 25, 5, 126, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 170,5 , 170,5 , 175,5 , 175,5 , 287,6 , 420,13 , 198,6 , 204,11 , 4671,39 , 4710,38 , 158,27 , 4671,39 , 4710,38 , 158,27 , 2002,21 , 2023,28 , 2051,14 , 2002,21 , 2023,28 , 2051,14 , 60,2 , 57,2 , 287,2 , 289,21 , 22,23 , {77,79,80}, 133,4 , 3146,13 , 4,4 , 4,0 , 553,4 , 568,9 , 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/Macau { 25, 5, 190, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 170,5 , 170,5 , 175,5 , 175,5 , 27,8 , 420,13 , 198,6 , 204,11 , 4671,39 , 4710,38 , 158,27 , 4671,39 , 4710,38 , 158,27 , 2002,21 , 2023,28 , 2051,14 , 2002,21 , 2023,28 , 2051,14 , 60,2 , 57,2 , 287,2 , 289,21 , 22,23 , {83,71,68}, 6,1 , 3159,15 , 4,4 , 4,0 , 553,4 , 577,3 , 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/Singapore - { 25, 6, 97, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 170,5 , 170,5 , 180,5 , 180,5 , 433,8 , 420,13 , 198,6 , 215,13 , 4671,39 , 4671,39 , 158,27 , 4671,39 , 4671,39 , 158,27 , 2065,21 , 2023,28 , 2051,14 , 2065,21 , 2023,28 , 2051,14 , 60,2 , 57,2 , 310,3 , 5,17 , 22,23 , {72,75,68}, 130,3 , 3135,11 , 18,5 , 4,0 , 580,4 , 584,9 , 2, 1, 7, 6, 7 }, // Chinese/Traditional Han/HongKong + { 25, 6, 97, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 170,5 , 170,5 , 180,5 , 180,5 , 433,8 , 420,13 , 198,6 , 215,13 , 4671,39 , 4671,39 , 158,27 , 4671,39 , 4671,39 , 158,27 , 2065,21 , 2023,28 , 2051,14 , 2065,21 , 2023,28 , 2051,14 , 60,2 , 57,2 , 310,3 , 5,17 , 22,23 , {72,75,68}, 130,3 , 3135,11 , 18,5 , 4,0 , 580,4 , 584,9 , 2, 1, 7, 6, 7 }, // Chinese/Traditional Han/Hong Kong { 25, 6, 126, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 170,5 , 170,5 , 180,5 , 180,5 , 433,8 , 420,13 , 198,6 , 215,13 , 4671,39 , 4671,39 , 158,27 , 4671,39 , 4671,39 , 158,27 , 2065,21 , 2023,28 , 2051,14 , 2065,21 , 2023,28 , 2051,14 , 60,2 , 57,2 , 310,3 , 5,17 , 22,23 , {77,79,80}, 133,4 , 3174,13 , 18,5 , 4,0 , 580,4 , 593,9 , 2, 1, 7, 6, 7 }, // Chinese/Traditional Han/Macau { 25, 6, 208, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 170,5 , 170,5 , 175,5 , 175,5 , 412,8 , 441,14 , 198,6 , 215,13 , 4671,39 , 4671,39 , 158,27 , 4671,39 , 4671,39 , 158,27 , 2065,21 , 2023,28 , 2051,14 , 2065,21 , 2023,28 , 2051,14 , 60,2 , 57,2 , 45,4 , 5,17 , 22,23 , {84,87,68}, 6,1 , 3187,13 , 4,4 , 4,0 , 580,4 , 602,2 , 2, 0, 7, 6, 7 }, // Chinese/Traditional Han/Taiwan { 26, 7, 74, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Corsican/Latin/France { 27, 7, 54, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 163,7 , 163,7 , 455,13 , 468,19 , 37,5 , 87,12 , 4748,49 , 4797,94 , 4891,39 , 4748,49 , 4930,98 , 4891,39 , 2086,28 , 2114,58 , 2172,14 , 2086,28 , 2114,58 , 2186,14 , 0,2 , 0,2 , 313,7 , 5,17 , 22,23 , {72,82,75}, 137,3 , 3200,60 , 13,5 , 4,0 , 604,8 , 612,8 , 2, 1, 1, 6, 7 }, // Croatian/Latin/Croatia - { 27, 7, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 163,7 , 163,7 , 487,9 , 468,19 , 37,5 , 87,12 , 4748,49 , 4797,94 , 4891,39 , 4748,49 , 4930,98 , 4891,39 , 2086,28 , 2114,58 , 2186,14 , 2086,28 , 2114,58 , 2186,14 , 0,2 , 0,2 , 313,7 , 5,17 , 22,23 , {66,65,77}, 140,2 , 3260,85 , 13,5 , 4,0 , 604,8 , 620,19 , 2, 1, 1, 6, 7 }, // Croatian/Latin/BosniaAndHerzegowina - { 28, 7, 57, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 185,7 , 185,7 , 174,8 , 496,17 , 55,4 , 59,9 , 5028,48 , 5076,82 , 158,27 , 5028,48 , 5158,84 , 158,27 , 2200,21 , 2221,49 , 2270,14 , 2200,21 , 2221,49 , 2270,14 , 62,4 , 59,4 , 320,5 , 5,17 , 22,23 , {67,90,75}, 142,2 , 3345,68 , 13,5 , 4,0 , 639,7 , 646,5 , 2, 0, 1, 6, 7 }, // Czech/Latin/CzechRepublic + { 27, 7, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 163,7 , 163,7 , 487,9 , 468,19 , 37,5 , 87,12 , 4748,49 , 4797,94 , 4891,39 , 4748,49 , 4930,98 , 4891,39 , 2086,28 , 2114,58 , 2186,14 , 2086,28 , 2114,58 , 2186,14 , 0,2 , 0,2 , 313,7 , 5,17 , 22,23 , {66,65,77}, 140,2 , 3260,85 , 13,5 , 4,0 , 604,8 , 620,19 , 2, 1, 1, 6, 7 }, // Croatian/Latin/Bosnia And Herzegowina + { 28, 7, 57, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 185,7 , 185,7 , 174,8 , 496,17 , 55,4 , 59,9 , 5028,48 , 5076,82 , 158,27 , 5028,48 , 5158,84 , 158,27 , 2200,21 , 2221,49 , 2270,14 , 2200,21 , 2221,49 , 2270,14 , 62,4 , 59,4 , 320,5 , 5,17 , 22,23 , {67,90,75}, 142,2 , 3345,68 , 13,5 , 4,0 , 639,7 , 646,5 , 2, 0, 1, 6, 7 }, // Czech/Latin/Czech Republic { 29, 7, 58, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 192,8 , 192,8 , 120,10 , 513,23 , 228,5 , 233,10 , 5242,59 , 5301,84 , 134,24 , 5242,59 , 5301,84 , 134,24 , 2284,28 , 2312,51 , 2363,14 , 2377,35 , 2312,51 , 2363,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {68,75,75}, 144,3 , 3413,42 , 13,5 , 4,0 , 651,5 , 656,7 , 2, 0, 1, 6, 7 }, // Danish/Latin/Denmark { 29, 7, 86, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 192,8 , 192,8 , 120,10 , 513,23 , 228,5 , 233,10 , 5242,59 , 5301,84 , 134,24 , 5242,59 , 5301,84 , 134,24 , 2284,28 , 2312,51 , 2363,14 , 2377,35 , 2312,51 , 2363,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {68,75,75}, 144,3 , 3413,42 , 13,5 , 4,0 , 651,5 , 663,8 , 2, 0, 1, 6, 7 }, // Danish/Latin/Greenland { 30, 7, 151, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 357,8 , 98,16 , 37,5 , 8,10 , 5385,59 , 5444,88 , 134,24 , 5385,59 , 5444,88 , 134,24 , 2412,21 , 2433,59 , 2492,14 , 2412,21 , 2433,59 , 2492,14 , 66,4 , 63,4 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3455,19 , 13,5 , 4,0 , 671,10 , 681,9 , 2, 1, 1, 6, 7 }, // Dutch/Latin/Netherlands { 30, 7, 12, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 357,8 , 98,16 , 37,5 , 8,10 , 5385,59 , 5444,88 , 134,24 , 5385,59 , 5444,88 , 134,24 , 2412,21 , 2433,59 , 2492,14 , 2412,21 , 2433,59 , 2492,14 , 66,4 , 63,4 , 45,4 , 5,17 , 22,23 , {65,87,71}, 147,4 , 3474,55 , 13,5 , 4,0 , 671,10 , 690,5 , 2, 1, 1, 6, 7 }, // Dutch/Latin/Aruba { 30, 7, 21, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 536,7 , 98,16 , 37,5 , 8,10 , 5385,59 , 5444,88 , 134,24 , 5385,59 , 5444,88 , 134,24 , 2412,21 , 2433,59 , 2492,14 , 2412,21 , 2433,59 , 2492,14 , 66,4 , 63,4 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3455,19 , 13,5 , 4,0 , 671,10 , 695,6 , 2, 1, 1, 6, 7 }, // Dutch/Latin/Belgium - { 30, 7, 152, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 357,8 , 98,16 , 37,5 , 8,10 , 5385,59 , 5444,88 , 134,24 , 5385,59 , 5444,88 , 134,24 , 2412,21 , 2433,59 , 2492,14 , 2412,21 , 2433,59 , 2492,14 , 66,4 , 63,4 , 45,4 , 5,17 , 22,23 , {65,78,71}, 151,4 , 3529,97 , 13,5 , 4,0 , 671,10 , 701,7 , 2, 1, 1, 6, 7 }, // Dutch/Latin/CuraSao + { 30, 7, 152, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 357,8 , 98,16 , 37,5 , 8,10 , 5385,59 , 5444,88 , 134,24 , 5385,59 , 5444,88 , 134,24 , 2412,21 , 2433,59 , 2492,14 , 2412,21 , 2433,59 , 2492,14 , 66,4 , 63,4 , 45,4 , 5,17 , 22,23 , {65,78,71}, 151,4 , 3529,97 , 13,5 , 4,0 , 671,10 , 701,7 , 2, 1, 1, 6, 7 }, // Dutch/Latin/Cura Sao { 30, 7, 202, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 357,8 , 98,16 , 37,5 , 8,10 , 5385,59 , 5444,88 , 134,24 , 5385,59 , 5444,88 , 134,24 , 2412,21 , 2433,59 , 2492,14 , 2412,21 , 2433,59 , 2492,14 , 66,4 , 63,4 , 45,4 , 5,17 , 22,23 , {83,82,68}, 6,1 , 3626,58 , 13,5 , 4,0 , 671,10 , 708,8 , 2, 1, 1, 6, 7 }, // Dutch/Latin/Suriname { 30, 7, 255, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 357,8 , 98,16 , 37,5 , 8,10 , 5385,59 , 5444,88 , 134,24 , 5385,59 , 5444,88 , 134,24 , 2412,21 , 2433,59 , 2492,14 , 2412,21 , 2433,59 , 2492,14 , 66,4 , 63,4 , 45,4 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3684,61 , 13,5 , 4,0 , 671,10 , 716,19 , 2, 1, 1, 6, 7 }, // Dutch/Latin/Bonaire - { 30, 7, 256, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 357,8 , 98,16 , 37,5 , 8,10 , 5385,59 , 5444,88 , 134,24 , 5385,59 , 5444,88 , 134,24 , 2412,21 , 2433,59 , 2492,14 , 2412,21 , 2433,59 , 2492,14 , 66,4 , 63,4 , 45,4 , 5,17 , 22,23 , {65,78,71}, 151,4 , 3529,97 , 13,5 , 4,0 , 671,10 , 735,12 , 2, 1, 1, 6, 7 }, // Dutch/Latin/SintMaarten - { 31, 7, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 543,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3745,35 , 4,4 , 4,0 , 747,16 , 763,13 , 2, 1, 7, 6, 7 }, // English/Latin/UnitedStates - { 31, 3, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,83,68}, 155,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // English/Deseret/UnitedStates - { 31, 7, 4, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 543,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3745,35 , 4,4 , 4,0 , 776,7 , 783,14 , 2, 1, 7, 6, 7 }, // English/Latin/AmericanSamoa + { 30, 7, 256, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 357,8 , 98,16 , 37,5 , 8,10 , 5385,59 , 5444,88 , 134,24 , 5385,59 , 5444,88 , 134,24 , 2412,21 , 2433,59 , 2492,14 , 2412,21 , 2433,59 , 2492,14 , 66,4 , 63,4 , 45,4 , 5,17 , 22,23 , {65,78,71}, 151,4 , 3529,97 , 13,5 , 4,0 , 671,10 , 735,12 , 2, 1, 1, 6, 7 }, // Dutch/Latin/Sint Maarten + { 31, 7, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 543,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3745,35 , 4,4 , 4,0 , 747,16 , 763,13 , 2, 1, 7, 6, 7 }, // English/Latin/United States + { 31, 3, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,83,68}, 155,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // English/Deseret/United States + { 31, 7, 4, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 543,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3745,35 , 4,4 , 4,0 , 776,7 , 783,14 , 2, 1, 7, 6, 7 }, // English/Latin/American Samoa { 31, 7, 7, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3780,71 , 4,4 , 4,0 , 776,7 , 797,8 , 2, 1, 1, 6, 7 }, // English/Latin/Anguilla - { 31, 7, 9, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3780,71 , 4,4 , 4,0 , 776,7 , 805,17 , 2, 1, 7, 6, 7 }, // English/Latin/AntiguaAndBarbuda + { 31, 7, 9, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3780,71 , 4,4 , 4,0 , 776,7 , 805,17 , 2, 1, 7, 6, 7 }, // English/Latin/Antigua And Barbuda { 31, 7, 13, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 210,9 , 210,9 , 287,6 , 10,17 , 18,7 , 25,12 , 5532,59 , 48,86 , 134,24 , 5532,59 , 48,86 , 134,24 , 2506,35 , 28,57 , 2541,25 , 2506,35 , 28,57 , 2541,25 , 70,2 , 67,2 , 0,5 , 5,17 , 22,23 , {65,85,68}, 6,1 , 3851,59 , 4,4 , 4,0 , 822,18 , 840,9 , 2, 1, 7, 6, 7 }, // English/Latin/Australia { 31, 7, 14, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3910,20 , 8,5 , 4,0 , 776,7 , 849,7 , 2, 1, 1, 6, 7 }, // English/Latin/Austria { 31, 7, 16, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {66,83,68}, 6,1 , 3930,53 , 4,4 , 4,0 , 776,7 , 856,7 , 2, 1, 7, 6, 7 }, // English/Latin/Bahamas @@ -1347,19 +1347,19 @@ static const QLocaleData locale_data[] = { { 31, 7, 22, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 27,8 , 80,18 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {66,90,68}, 6,1 , 4039,47 , 4,4 , 4,0 , 776,7 , 878,6 , 2, 1, 7, 6, 7 }, // English/Latin/Belize { 31, 7, 24, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {66,77,68}, 6,1 , 4086,53 , 4,4 , 4,0 , 776,7 , 884,7 , 2, 1, 1, 6, 7 }, // English/Latin/Bermuda { 31, 7, 28, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 27,8 , 80,18 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {66,87,80}, 158,1 , 4139,50 , 4,4 , 4,0 , 776,7 , 891,8 , 2, 1, 7, 6, 7 }, // English/Latin/Botswana - { 31, 7, 31, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 155,3 , 3745,35 , 4,4 , 4,0 , 776,7 , 899,30 , 2, 1, 1, 6, 7 }, // English/Latin/BritishIndianOceanTerritory + { 31, 7, 31, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 155,3 , 3745,35 , 4,4 , 4,0 , 776,7 , 899,30 , 2, 1, 1, 6, 7 }, // English/Latin/British Indian Ocean Territory { 31, 7, 35, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 543,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {66,73,70}, 159,3 , 4189,53 , 4,4 , 4,0 , 776,7 , 929,7 , 0, 0, 1, 6, 7 }, // English/Latin/Burundi { 31, 7, 37, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,65,70}, 32,4 , 4242,83 , 4,4 , 4,0 , 776,7 , 936,8 , 0, 0, 1, 6, 7 }, // English/Latin/Cameroon { 31, 7, 38, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 53,10 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 5532,59 , 48,86 , 134,24 , 2506,35 , 28,57 , 85,14 , 2506,35 , 28,57 , 85,14 , 66,4 , 63,4 , 0,5 , 5,17 , 22,23 , {67,65,68}, 6,1 , 4325,53 , 4,4 , 4,0 , 944,16 , 960,6 , 2, 0, 7, 6, 7 }, // English/Latin/Canada - { 31, 7, 40, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {75,89,68}, 6,1 , 4378,71 , 4,4 , 4,0 , 776,7 , 966,14 , 2, 1, 1, 6, 7 }, // English/Latin/CaymanIslands - { 31, 7, 45, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {65,85,68}, 6,1 , 3851,59 , 4,4 , 4,0 , 776,7 , 980,16 , 2, 1, 1, 6, 7 }, // English/Latin/ChristmasIsland - { 31, 7, 46, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {65,85,68}, 6,1 , 3851,59 , 4,4 , 4,0 , 776,7 , 996,23 , 2, 1, 1, 6, 7 }, // English/Latin/CocosIslands - { 31, 7, 51, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {78,90,68}, 6,1 , 4449,62 , 4,4 , 4,0 , 776,7 , 1019,12 , 2, 1, 1, 6, 7 }, // English/Latin/CookIslands + { 31, 7, 40, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {75,89,68}, 6,1 , 4378,71 , 4,4 , 4,0 , 776,7 , 966,14 , 2, 1, 1, 6, 7 }, // English/Latin/Cayman Islands + { 31, 7, 45, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {65,85,68}, 6,1 , 3851,59 , 4,4 , 4,0 , 776,7 , 980,16 , 2, 1, 1, 6, 7 }, // English/Latin/Christmas Island + { 31, 7, 46, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {65,85,68}, 6,1 , 3851,59 , 4,4 , 4,0 , 776,7 , 996,23 , 2, 1, 1, 6, 7 }, // English/Latin/Cocos Islands + { 31, 7, 51, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {78,90,68}, 6,1 , 4449,62 , 4,4 , 4,0 , 776,7 , 1019,12 , 2, 1, 1, 6, 7 }, // English/Latin/Cook Islands { 31, 7, 56, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3910,20 , 4,4 , 4,0 , 776,7 , 1031,6 , 2, 1, 1, 6, 7 }, // English/Latin/Cyprus { 31, 7, 58, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 228,5 , 233,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {68,75,75}, 144,3 , 4511,44 , 13,5 , 4,0 , 776,7 , 1037,7 , 2, 0, 1, 6, 7 }, // English/Latin/Denmark { 31, 7, 60, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3780,71 , 4,4 , 4,0 , 776,7 , 1044,8 , 2, 1, 7, 6, 7 }, // English/Latin/Dominica { 31, 7, 67, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {69,82,78}, 41,3 , 4555,50 , 4,4 , 4,0 , 776,7 , 1052,7 , 2, 1, 1, 6, 7 }, // English/Latin/Eritrea - { 31, 7, 70, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {70,75,80}, 115,1 , 4605,74 , 4,4 , 4,0 , 776,7 , 1059,16 , 2, 1, 1, 6, 7 }, // English/Latin/FalklandIslands + { 31, 7, 70, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {70,75,80}, 115,1 , 4605,74 , 4,4 , 4,0 , 776,7 , 1059,16 , 2, 1, 1, 6, 7 }, // English/Latin/Falkland Islands { 31, 7, 72, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {70,74,68}, 6,1 , 4679,47 , 4,4 , 4,0 , 776,7 , 1075,4 , 2, 1, 1, 6, 7 }, // English/Latin/Fiji { 31, 7, 73, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 243,4 , 247,9 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3910,20 , 13,5 , 4,0 , 776,7 , 1079,7 , 2, 1, 1, 6, 7 }, // English/Latin/Finland { 31, 7, 75, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {71,66,80}, 115,1 , 4726,32 , 4,4 , 4,0 , 776,7 , 1086,8 , 2, 1, 1, 6, 7 }, // English/Latin/Guernsey @@ -1370,7 +1370,7 @@ static const QLocaleData locale_data[] = { { 31, 7, 87, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3780,71 , 4,4 , 4,0 , 776,7 , 1121,7 , 2, 1, 1, 6, 7 }, // English/Latin/Grenada { 31, 7, 89, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 543,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3745,35 , 4,4 , 4,0 , 776,7 , 1128,4 , 2, 1, 7, 6, 7 }, // English/Latin/Guam { 31, 7, 93, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {71,89,68}, 6,1 , 4908,56 , 4,4 , 4,0 , 776,7 , 1132,6 , 0, 0, 1, 6, 7 }, // English/Latin/Guyana - { 31, 7, 97, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 433,8 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {72,75,68}, 130,3 , 4964,56 , 4,4 , 4,0 , 776,7 , 1138,19 , 2, 1, 7, 6, 7 }, // English/Latin/HongKong + { 31, 7, 97, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 433,8 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {72,75,68}, 130,3 , 4964,56 , 4,4 , 4,0 , 776,7 , 1138,19 , 2, 1, 7, 6, 7 }, // English/Latin/Hong Kong { 31, 7, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 27,8 , 210,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {73,78,82}, 117,1 , 5020,44 , 8,5 , 4,0 , 776,7 , 1157,5 , 2, 1, 7, 7, 7 }, // English/Latin/India { 31, 7, 104, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 98,16 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 66,4 , 63,4 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3910,20 , 4,4 , 4,0 , 776,7 , 1162,7 , 2, 1, 7, 6, 7 }, // English/Latin/Ireland { 31, 7, 105, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 55,4 , 59,9 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {73,76,83}, 49,1 , 5064,62 , 4,4 , 4,0 , 776,7 , 1169,6 , 2, 1, 7, 5, 6 }, // English/Latin/Israel @@ -1384,36 +1384,36 @@ static const QLocaleData locale_data[] = { { 31, 7, 129, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {77,87,75}, 168,2 , 5453,53 , 4,4 , 4,0 , 776,7 , 1234,6 , 2, 1, 1, 6, 7 }, // English/Latin/Malawi { 31, 7, 130, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {77,89,82}, 170,2 , 5506,59 , 4,4 , 4,0 , 776,7 , 1240,8 , 2, 1, 1, 6, 7 }, // English/Latin/Malaysia { 31, 7, 133, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3910,20 , 4,4 , 4,0 , 776,7 , 1248,5 , 2, 1, 7, 6, 7 }, // English/Latin/Malta - { 31, 7, 134, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 543,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3745,35 , 4,4 , 4,0 , 776,7 , 1253,16 , 2, 1, 7, 6, 7 }, // English/Latin/MarshallIslands + { 31, 7, 134, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 543,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3745,35 , 4,4 , 4,0 , 776,7 , 1253,16 , 2, 1, 7, 6, 7 }, // English/Latin/Marshall Islands { 31, 7, 137, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {77,85,82}, 172,2 , 5565,53 , 4,4 , 4,0 , 776,7 , 1269,9 , 0, 0, 1, 6, 7 }, // English/Latin/Mauritius { 31, 7, 140, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 155,3 , 3745,35 , 4,4 , 4,0 , 776,7 , 1278,10 , 2, 1, 1, 6, 7 }, // English/Latin/Micronesia { 31, 7, 144, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3780,71 , 4,4 , 4,0 , 776,7 , 1288,10 , 2, 1, 1, 6, 7 }, // English/Latin/Montserrat { 31, 7, 148, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {78,65,68}, 6,1 , 5618,53 , 4,4 , 4,0 , 776,7 , 1298,7 , 2, 1, 1, 6, 7 }, // English/Latin/Namibia { 31, 7, 149, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {65,85,68}, 6,1 , 3851,59 , 4,4 , 4,0 , 776,7 , 1305,5 , 2, 1, 1, 6, 7 }, // English/Latin/Nauru { 31, 7, 151, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3910,20 , 8,5 , 23,6 , 776,7 , 1310,11 , 2, 1, 1, 6, 7 }, // English/Latin/Netherlands - { 31, 7, 154, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 536,7 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {78,90,68}, 6,1 , 4449,62 , 4,4 , 4,0 , 776,7 , 1321,11 , 2, 1, 1, 6, 7 }, // English/Latin/NewZealand + { 31, 7, 154, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 536,7 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {78,90,68}, 6,1 , 4449,62 , 4,4 , 4,0 , 776,7 , 1321,11 , 2, 1, 1, 6, 7 }, // English/Latin/New Zealand { 31, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {78,71,78}, 174,1 , 5671,50 , 4,4 , 4,0 , 776,7 , 1332,7 , 2, 1, 1, 6, 7 }, // English/Latin/Nigeria { 31, 7, 158, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {78,90,68}, 6,1 , 4449,62 , 4,4 , 4,0 , 776,7 , 1339,4 , 2, 1, 1, 6, 7 }, // English/Latin/Niue - { 31, 7, 159, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {65,85,68}, 6,1 , 3851,59 , 4,4 , 4,0 , 776,7 , 1343,14 , 2, 1, 1, 6, 7 }, // English/Latin/NorfolkIsland - { 31, 7, 160, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 543,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3745,35 , 4,4 , 4,0 , 776,7 , 1357,24 , 2, 1, 1, 6, 7 }, // English/Latin/NorthernMarianaIslands + { 31, 7, 159, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {65,85,68}, 6,1 , 3851,59 , 4,4 , 4,0 , 776,7 , 1343,14 , 2, 1, 1, 6, 7 }, // English/Latin/Norfolk Island + { 31, 7, 160, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 543,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3745,35 , 4,4 , 4,0 , 776,7 , 1357,24 , 2, 1, 1, 6, 7 }, // English/Latin/Northern Mariana Islands { 31, 7, 163, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {80,75,82}, 172,2 , 5721,53 , 4,4 , 4,0 , 776,7 , 1381,8 , 0, 0, 7, 6, 7 }, // English/Latin/Pakistan { 31, 7, 164, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 155,3 , 3745,35 , 4,4 , 4,0 , 776,7 , 1389,5 , 2, 1, 1, 6, 7 }, // English/Latin/Palau - { 31, 7, 167, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {80,71,75}, 127,1 , 5774,73 , 4,4 , 4,0 , 776,7 , 1394,16 , 2, 1, 1, 6, 7 }, // English/Latin/PapuaNewGuinea + { 31, 7, 167, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {80,71,75}, 127,1 , 5774,73 , 4,4 , 4,0 , 776,7 , 1394,16 , 2, 1, 1, 6, 7 }, // English/Latin/Papua New Guinea { 31, 7, 170, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {80,72,80}, 175,1 , 5847,53 , 4,4 , 4,0 , 776,7 , 1410,11 , 2, 1, 7, 6, 7 }, // English/Latin/Philippines { 31, 7, 171, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {78,90,68}, 6,1 , 4449,62 , 4,4 , 4,0 , 776,7 , 1421,16 , 2, 1, 1, 6, 7 }, // English/Latin/Pitcairn - { 31, 7, 174, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 543,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3745,35 , 4,4 , 4,0 , 776,7 , 1437,11 , 2, 1, 7, 6, 7 }, // English/Latin/PuertoRico + { 31, 7, 174, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 543,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3745,35 , 4,4 , 4,0 , 776,7 , 1437,11 , 2, 1, 7, 6, 7 }, // English/Latin/Puerto Rico { 31, 7, 179, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {82,87,70}, 176,2 , 5900,47 , 4,4 , 4,0 , 776,7 , 1448,6 , 0, 0, 1, 6, 7 }, // English/Latin/Rwanda - { 31, 7, 180, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3780,71 , 4,4 , 4,0 , 776,7 , 1454,17 , 2, 1, 1, 6, 7 }, // English/Latin/SaintKittsAndNevis - { 31, 7, 181, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3780,71 , 4,4 , 4,0 , 776,7 , 1471,9 , 2, 1, 1, 6, 7 }, // English/Latin/SaintLucia - { 31, 7, 182, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3780,71 , 4,4 , 4,0 , 776,7 , 1480,24 , 2, 1, 1, 6, 7 }, // English/Latin/SaintVincentAndTheGrenadines + { 31, 7, 180, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3780,71 , 4,4 , 4,0 , 776,7 , 1454,17 , 2, 1, 1, 6, 7 }, // English/Latin/Saint Kitts And Nevis + { 31, 7, 181, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3780,71 , 4,4 , 4,0 , 776,7 , 1471,9 , 2, 1, 1, 6, 7 }, // English/Latin/Saint Lucia + { 31, 7, 182, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3780,71 , 4,4 , 4,0 , 776,7 , 1480,24 , 2, 1, 1, 6, 7 }, // English/Latin/Saint Vincent And The Grenadines { 31, 7, 183, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {87,83,84}, 178,3 , 5947,40 , 4,4 , 4,0 , 776,7 , 1504,5 , 2, 1, 7, 6, 7 }, // English/Latin/Samoa { 31, 7, 188, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,67,82}, 181,2 , 5987,59 , 4,4 , 4,0 , 776,7 , 1509,10 , 2, 1, 1, 6, 7 }, // English/Latin/Seychelles - { 31, 7, 189, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,76,76}, 183,2 , 6046,68 , 4,4 , 4,0 , 776,7 , 1519,12 , 0, 0, 1, 6, 7 }, // English/Latin/SierraLeone + { 31, 7, 189, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,76,76}, 183,2 , 6046,68 , 4,4 , 4,0 , 776,7 , 1519,12 , 0, 0, 1, 6, 7 }, // English/Latin/Sierra Leone { 31, 7, 190, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 287,6 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,71,68}, 6,1 , 6114,56 , 4,4 , 4,0 , 776,7 , 1531,9 , 2, 1, 7, 6, 7 }, // English/Latin/Singapore { 31, 7, 192, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3910,20 , 13,5 , 29,7 , 776,7 , 1540,8 , 2, 1, 1, 6, 7 }, // English/Latin/Slovenia - { 31, 7, 193, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,66,68}, 6,1 , 6170,74 , 4,4 , 4,0 , 776,7 , 1548,15 , 2, 1, 1, 6, 7 }, // English/Latin/SolomonIslands - { 31, 7, 195, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 549,10 , 80,18 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {90,65,82}, 5,1 , 5232,61 , 4,4 , 4,0 , 776,7 , 1563,12 , 2, 1, 7, 6, 7 }, // English/Latin/SouthAfrica - { 31, 7, 199, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,72,80}, 115,1 , 6244,56 , 4,4 , 4,0 , 776,7 , 1575,10 , 2, 1, 1, 6, 7 }, // English/Latin/SaintHelena + { 31, 7, 193, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,66,68}, 6,1 , 6170,74 , 4,4 , 4,0 , 776,7 , 1548,15 , 2, 1, 1, 6, 7 }, // English/Latin/Solomon Islands + { 31, 7, 195, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 549,10 , 80,18 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {90,65,82}, 5,1 , 5232,61 , 4,4 , 4,0 , 776,7 , 1563,12 , 2, 1, 7, 6, 7 }, // English/Latin/South Africa + { 31, 7, 199, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,72,80}, 115,1 , 6244,56 , 4,4 , 4,0 , 776,7 , 1575,10 , 2, 1, 1, 6, 7 }, // English/Latin/Saint Helena { 31, 7, 201, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,68,71}, 0,0 , 6300,50 , 4,4 , 4,0 , 776,7 , 1585,5 , 2, 1, 6, 5, 6 }, // English/Latin/Sudan { 31, 7, 204, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,90,76}, 185,1 , 6350,53 , 4,4 , 4,0 , 776,7 , 1590,9 , 2, 1, 1, 6, 7 }, // English/Latin/Swaziland { 31, 7, 205, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 53,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,69,75}, 186,2 , 6403,47 , 13,5 , 4,0 , 776,7 , 1599,6 , 2, 0, 1, 6, 7 }, // English/Latin/Sweden @@ -1421,47 +1421,47 @@ static const QLocaleData locale_data[] = { { 31, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {84,90,83}, 188,3 , 6491,62 , 4,4 , 4,0 , 776,7 , 1616,8 , 0, 0, 1, 6, 7 }, // English/Latin/Tanzania { 31, 7, 213, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {78,90,68}, 6,1 , 4449,62 , 4,4 , 4,0 , 776,7 , 1624,7 , 2, 1, 1, 6, 7 }, // English/Latin/Tokelau { 31, 7, 214, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {84,79,80}, 191,2 , 6553,49 , 4,4 , 4,0 , 776,7 , 1631,5 , 2, 1, 1, 6, 7 }, // English/Latin/Tonga - { 31, 7, 215, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {84,84,68}, 6,1 , 6602,80 , 4,4 , 4,0 , 776,7 , 1636,17 , 2, 1, 7, 6, 7 }, // English/Latin/TrinidadAndTobago - { 31, 7, 219, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 155,3 , 3745,35 , 4,4 , 4,0 , 776,7 , 1653,22 , 2, 1, 1, 6, 7 }, // English/Latin/TurksAndCaicosIslands + { 31, 7, 215, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {84,84,68}, 6,1 , 6602,80 , 4,4 , 4,0 , 776,7 , 1636,17 , 2, 1, 7, 6, 7 }, // English/Latin/Trinidad And Tobago + { 31, 7, 219, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 155,3 , 3745,35 , 4,4 , 4,0 , 776,7 , 1653,22 , 2, 1, 1, 6, 7 }, // English/Latin/Turks And Caicos Islands { 31, 7, 220, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {65,85,68}, 6,1 , 3851,59 , 4,4 , 4,0 , 776,7 , 1675,6 , 2, 1, 1, 6, 7 }, // English/Latin/Tuvalu { 31, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,71,88}, 193,3 , 6682,56 , 4,4 , 4,0 , 776,7 , 1681,6 , 0, 0, 1, 6, 7 }, // English/Latin/Uganda - { 31, 7, 224, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 210,9 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 70,2 , 67,2 , 0,5 , 5,17 , 22,23 , {71,66,80}, 115,1 , 6738,47 , 4,4 , 4,0 , 1687,15 , 1702,14 , 2, 1, 1, 6, 7 }, // English/Latin/UnitedKingdom - { 31, 7, 226, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 543,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3745,35 , 4,4 , 4,0 , 776,7 , 1716,21 , 2, 1, 7, 6, 7 }, // English/Latin/UnitedStatesMinorOutlyingIslands + { 31, 7, 224, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 210,9 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 70,2 , 67,2 , 0,5 , 5,17 , 22,23 , {71,66,80}, 115,1 , 6738,47 , 4,4 , 4,0 , 1687,15 , 1702,14 , 2, 1, 1, 6, 7 }, // English/Latin/United Kingdom + { 31, 7, 226, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 543,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3745,35 , 4,4 , 4,0 , 776,7 , 1716,21 , 2, 1, 7, 6, 7 }, // English/Latin/United States Minor Outlying Islands { 31, 7, 229, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {86,85,86}, 196,2 , 6785,44 , 4,4 , 4,0 , 776,7 , 1737,7 , 0, 0, 1, 6, 7 }, // English/Latin/Vanuatu - { 31, 7, 233, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 155,3 , 3745,35 , 4,4 , 4,0 , 776,7 , 1744,22 , 2, 1, 1, 6, 7 }, // English/Latin/BritishVirginIslands - { 31, 7, 234, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 543,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3745,35 , 4,4 , 4,0 , 776,7 , 1766,19 , 2, 1, 7, 6, 7 }, // English/Latin/UnitedStatesVirginIslands + { 31, 7, 233, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 155,3 , 3745,35 , 4,4 , 4,0 , 776,7 , 1744,22 , 2, 1, 1, 6, 7 }, // English/Latin/British Virgin Islands + { 31, 7, 234, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 543,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3745,35 , 4,4 , 4,0 , 776,7 , 1766,19 , 2, 1, 7, 6, 7 }, // English/Latin/United States Virgin Islands { 31, 7, 239, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {90,77,87}, 127,1 , 6829,50 , 4,4 , 4,0 , 776,7 , 1785,6 , 2, 1, 1, 6, 7 }, // English/Latin/Zambia { 31, 7, 240, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 433,8 , 80,18 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 155,3 , 3745,35 , 4,4 , 4,0 , 776,7 , 1791,8 , 2, 1, 7, 6, 7 }, // English/Latin/Zimbabwe - { 31, 7, 249, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 155,3 , 3745,35 , 4,4 , 4,0 , 776,7 , 1799,12 , 2, 1, 1, 6, 7 }, // English/Latin/DiegoGarcia - { 31, 7, 251, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {71,66,80}, 115,1 , 4726,32 , 4,4 , 4,0 , 776,7 , 1811,11 , 2, 1, 1, 6, 7 }, // English/Latin/IsleOfMan + { 31, 7, 249, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 155,3 , 3745,35 , 4,4 , 4,0 , 776,7 , 1799,12 , 2, 1, 1, 6, 7 }, // English/Latin/Diego Garcia + { 31, 7, 251, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {71,66,80}, 115,1 , 4726,32 , 4,4 , 4,0 , 776,7 , 1811,11 , 2, 1, 1, 6, 7 }, // English/Latin/Isle Of Man { 31, 7, 252, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {71,66,80}, 115,1 , 4726,32 , 4,4 , 4,0 , 776,7 , 1822,6 , 2, 1, 1, 6, 7 }, // English/Latin/Jersey - { 31, 7, 254, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,83,80}, 115,1 , 6879,68 , 4,4 , 4,0 , 776,7 , 1828,11 , 2, 1, 1, 6, 7 }, // English/Latin/SouthSudan - { 31, 7, 256, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {65,78,71}, 151,4 , 6947,95 , 4,4 , 4,0 , 776,7 , 1839,12 , 2, 1, 1, 6, 7 }, // English/Latin/SintMaarten + { 31, 7, 254, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,83,80}, 115,1 , 6879,68 , 4,4 , 4,0 , 776,7 , 1828,11 , 2, 1, 1, 6, 7 }, // English/Latin/South Sudan + { 31, 7, 256, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {65,78,71}, 151,4 , 6947,95 , 4,4 , 4,0 , 776,7 , 1839,12 , 2, 1, 1, 6, 7 }, // English/Latin/Sint Maarten { 31, 7, 260, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {0,0,0}, 0,0 , 2586,0 , 4,4 , 4,0 , 776,7 , 1851,5 , 2, 1, 1, 6, 7 }, // English/Latin/World { 31, 7, 261, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 200,10 , 210,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {0,0,0}, 0,0 , 2586,0 , 13,5 , 4,0 , 776,7 , 1856,6 , 2, 1, 1, 6, 7 }, // English/Latin/Europe { 32, 7, 260, 44, 160, 59, 37, 48, 8722, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 219,9 , 219,9 , 559,8 , 567,26 , 37,5 , 256,25 , 5591,48 , 5639,91 , 134,24 , 5591,48 , 5639,91 , 134,24 , 2566,21 , 2587,51 , 2638,14 , 2566,21 , 2587,51 , 2638,14 , 72,3 , 69,3 , 325,6 , 5,17 , 22,23 , {0,0,0}, 0,0 , 2586,0 , 41,6 , 4,0 , 1862,9 , 0,0 , 2, 1, 1, 6, 7 }, // Esperanto/Latin/World { 33, 7, 68, 44, 160, 59, 37, 48, 8722, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 228,8 , 228,8 , 174,8 , 593,18 , 37,5 , 8,10 , 5730,59 , 5789,91 , 5880,24 , 5730,59 , 5789,91 , 5880,24 , 2652,14 , 2666,63 , 2652,14 , 2652,14 , 2666,63 , 2652,14 , 0,2 , 0,2 , 331,6 , 5,17 , 22,23 , {69,85,82}, 14,1 , 7042,20 , 13,5 , 4,0 , 1871,5 , 1876,5 , 2, 1, 1, 6, 7 }, // Estonian/Latin/Estonia - { 34, 7, 71, 44, 46, 59, 37, 48, 8722, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 192,8 , 192,8 , 174,8 , 593,18 , 37,5 , 8,10 , 5904,48 , 5952,83 , 134,24 , 6035,59 , 5952,83 , 134,24 , 2729,28 , 2757,74 , 2831,14 , 2845,35 , 2757,74 , 2831,14 , 0,2 , 0,2 , 337,3 , 340,17 , 22,23 , {68,75,75}, 186,2 , 7062,43 , 13,5 , 4,0 , 1881,8 , 1889,7 , 2, 0, 1, 6, 7 }, // Faroese/Latin/FaroeIslands + { 34, 7, 71, 44, 46, 59, 37, 48, 8722, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 192,8 , 192,8 , 174,8 , 593,18 , 37,5 , 8,10 , 5904,48 , 5952,83 , 134,24 , 6035,59 , 5952,83 , 134,24 , 2729,28 , 2757,74 , 2831,14 , 2845,35 , 2757,74 , 2831,14 , 0,2 , 0,2 , 337,3 , 340,17 , 22,23 , {68,75,75}, 186,2 , 7062,43 , 13,5 , 4,0 , 1881,8 , 1889,7 , 2, 0, 1, 6, 7 }, // Faroese/Latin/Faroe Islands { 34, 7, 58, 44, 46, 59, 37, 48, 8722, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 192,8 , 192,8 , 174,8 , 593,18 , 37,5 , 8,10 , 5904,48 , 5952,83 , 134,24 , 6035,59 , 5952,83 , 134,24 , 2729,28 , 2757,74 , 2831,14 , 2845,35 , 2757,74 , 2831,14 , 0,2 , 0,2 , 337,3 , 340,17 , 22,23 , {68,75,75}, 144,3 , 7062,43 , 13,5 , 4,0 , 1881,8 , 656,7 , 2, 0, 1, 6, 7 }, // Faroese/Latin/Denmark { 36, 7, 73, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 228,8 , 228,8 , 611,8 , 496,17 , 243,4 , 247,9 , 6094,69 , 6163,105 , 6268,24 , 6292,93 , 6385,129 , 6268,24 , 2880,21 , 2901,67 , 2968,14 , 2880,21 , 2982,81 , 2968,14 , 75,3 , 72,3 , 357,5 , 362,17 , 379,23 , {69,85,82}, 14,1 , 7105,20 , 13,5 , 4,0 , 1896,5 , 1901,5 , 2, 1, 1, 6, 7 }, // Finnish/Latin/Finland { 37, 7, 74, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 1906,8 , 1914,6 , 2, 1, 1, 6, 7 }, // French/Latin/France { 37, 7, 3, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 18,7 , 25,12 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {68,90,68}, 198,2 , 7125,51 , 13,5 , 4,0 , 1906,8 , 1920,7 , 2, 1, 6, 5, 6 }, // French/Latin/Algeria { 37, 7, 21, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 536,7 , 98,16 , 37,5 , 281,23 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 1906,8 , 1927,8 , 2, 1, 1, 6, 7 }, // French/Latin/Belgium { 37, 7, 23, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {88,79,70}, 200,3 , 7176,59 , 13,5 , 4,0 , 1906,8 , 1935,5 , 0, 0, 1, 6, 7 }, // French/Latin/Benin - { 37, 7, 34, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {88,79,70}, 200,3 , 7176,59 , 13,5 , 4,0 , 1906,8 , 1940,12 , 0, 0, 1, 6, 7 }, // French/Latin/BurkinaFaso + { 37, 7, 34, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {88,79,70}, 200,3 , 7176,59 , 13,5 , 4,0 , 1906,8 , 1940,12 , 0, 0, 1, 6, 7 }, // French/Latin/Burkina Faso { 37, 7, 35, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {66,73,70}, 159,3 , 7235,53 , 13,5 , 4,0 , 1906,8 , 929,7 , 0, 0, 1, 6, 7 }, // French/Latin/Burundi { 37, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 78,5 , 75,4 , 402,6 , 211,17 , 228,23 , {88,65,70}, 32,4 , 7288,56 , 13,5 , 4,0 , 1906,8 , 1952,8 , 0, 0, 1, 6, 7 }, // French/Latin/Cameroon { 37, 7, 38, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8221, 8220, 0,6 , 0,6 , 236,8 , 236,8 , 559,8 , 98,16 , 304,9 , 313,24 , 6662,64 , 6577,85 , 134,24 , 6662,64 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 66,4 , 63,4 , 402,6 , 211,17 , 228,23 , {67,65,68}, 6,1 , 7344,54 , 47,6 , 4,0 , 1960,17 , 960,6 , 2, 0, 7, 6, 7 }, // French/Latin/Canada - { 37, 7, 41, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {88,65,70}, 32,4 , 7288,56 , 13,5 , 4,0 , 1906,8 , 1977,25 , 0, 0, 1, 6, 7 }, // French/Latin/CentralAfricanRepublic + { 37, 7, 41, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {88,65,70}, 32,4 , 7288,56 , 13,5 , 4,0 , 1906,8 , 1977,25 , 0, 0, 1, 6, 7 }, // French/Latin/Central African Republic { 37, 7, 42, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 18,7 , 25,12 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {88,65,70}, 32,4 , 7288,56 , 13,5 , 4,0 , 1906,8 , 2002,5 , 0, 0, 1, 6, 7 }, // French/Latin/Chad { 37, 7, 48, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {75,77,70}, 36,2 , 7398,51 , 13,5 , 4,0 , 1906,8 , 2007,7 , 0, 0, 1, 6, 7 }, // French/Latin/Comoros - { 37, 7, 49, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {67,68,70}, 203,2 , 7449,53 , 13,5 , 4,0 , 1906,8 , 2014,14 , 2, 1, 1, 6, 7 }, // French/Latin/CongoKinshasa - { 37, 7, 50, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {88,65,70}, 32,4 , 7288,56 , 13,5 , 4,0 , 1906,8 , 2028,17 , 0, 0, 1, 6, 7 }, // French/Latin/CongoBrazzaville - { 37, 7, 53, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {88,79,70}, 200,3 , 7176,59 , 13,5 , 4,0 , 1906,8 , 2045,13 , 0, 0, 1, 6, 7 }, // French/Latin/IvoryCoast + { 37, 7, 49, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {67,68,70}, 203,2 , 7449,53 , 13,5 , 4,0 , 1906,8 , 2014,14 , 2, 1, 1, 6, 7 }, // French/Latin/Congo Kinshasa + { 37, 7, 50, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {88,65,70}, 32,4 , 7288,56 , 13,5 , 4,0 , 1906,8 , 2028,17 , 0, 0, 1, 6, 7 }, // French/Latin/Congo Brazzaville + { 37, 7, 53, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {88,79,70}, 200,3 , 7176,59 , 13,5 , 4,0 , 1906,8 , 2045,13 , 0, 0, 1, 6, 7 }, // French/Latin/Ivory Coast { 37, 7, 59, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 18,7 , 25,12 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {68,74,70}, 38,3 , 7502,57 , 13,5 , 4,0 , 1906,8 , 2058,8 , 0, 0, 6, 6, 7 }, // French/Latin/Djibouti - { 37, 7, 66, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {88,65,70}, 32,4 , 7288,56 , 13,5 , 4,0 , 1906,8 , 2066,18 , 0, 0, 1, 6, 7 }, // French/Latin/EquatorialGuinea - { 37, 7, 76, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 1906,8 , 2084,16 , 2, 1, 1, 6, 7 }, // French/Latin/FrenchGuiana - { 37, 7, 77, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {88,80,70}, 205,4 , 7559,35 , 13,5 , 4,0 , 1906,8 , 2100,19 , 0, 0, 1, 6, 7 }, // French/Latin/FrenchPolynesia + { 37, 7, 66, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {88,65,70}, 32,4 , 7288,56 , 13,5 , 4,0 , 1906,8 , 2066,18 , 0, 0, 1, 6, 7 }, // French/Latin/Equatorial Guinea + { 37, 7, 76, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 1906,8 , 2084,16 , 2, 1, 1, 6, 7 }, // French/Latin/French Guiana + { 37, 7, 77, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {88,80,70}, 205,4 , 7559,35 , 13,5 , 4,0 , 1906,8 , 2100,19 , 0, 0, 1, 6, 7 }, // French/Latin/French Polynesia { 37, 7, 79, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {88,65,70}, 32,4 , 7288,56 , 13,5 , 4,0 , 1906,8 , 2119,5 , 0, 0, 1, 6, 7 }, // French/Latin/Gabon { 37, 7, 88, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 1906,8 , 2124,10 , 2, 1, 1, 6, 7 }, // French/Latin/Guadeloupe { 37, 7, 91, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {71,78,70}, 209,2 , 7594,48 , 13,5 , 4,0 , 1906,8 , 2134,6 , 0, 0, 1, 6, 7 }, // French/Latin/Guinea @@ -1475,23 +1475,23 @@ static const QLocaleData locale_data[] = { { 37, 7, 138, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 1906,8 , 2186,7 , 2, 1, 1, 6, 7 }, // French/Latin/Mayotte { 37, 7, 142, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 1906,8 , 2193,6 , 2, 1, 1, 6, 7 }, // French/Latin/Monaco { 37, 7, 145, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6726,61 , 6577,85 , 134,24 , 6726,61 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 66,4 , 63,4 , 402,6 , 211,17 , 228,23 , {77,65,68}, 214,3 , 7882,54 , 13,5 , 4,0 , 1906,8 , 2199,5 , 2, 1, 6, 5, 6 }, // French/Latin/Morocco - { 37, 7, 153, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {88,80,70}, 205,4 , 7559,35 , 13,5 , 4,0 , 1906,8 , 2204,18 , 0, 0, 1, 6, 7 }, // French/Latin/NewCaledonia + { 37, 7, 153, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {88,80,70}, 205,4 , 7559,35 , 13,5 , 4,0 , 1906,8 , 2204,18 , 0, 0, 1, 6, 7 }, // French/Latin/New Caledonia { 37, 7, 156, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {88,79,70}, 200,3 , 7176,59 , 13,5 , 4,0 , 1906,8 , 2222,5 , 0, 0, 1, 6, 7 }, // French/Latin/Niger { 37, 7, 176, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 1906,8 , 2227,10 , 2, 1, 1, 6, 7 }, // French/Latin/Reunion { 37, 7, 179, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {82,87,70}, 176,2 , 7936,50 , 13,5 , 4,0 , 1906,8 , 1448,6 , 0, 0, 1, 6, 7 }, // French/Latin/Rwanda { 37, 7, 187, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {88,79,70}, 200,3 , 7176,59 , 13,5 , 4,0 , 1906,8 , 2237,7 , 0, 0, 1, 6, 7 }, // French/Latin/Senegal { 37, 7, 188, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {83,67,82}, 181,2 , 7986,71 , 13,5 , 4,0 , 1906,8 , 1509,10 , 2, 1, 1, 6, 7 }, // French/Latin/Seychelles - { 37, 7, 200, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 1906,8 , 2244,24 , 2, 1, 1, 6, 7 }, // French/Latin/SaintPierreAndMiquelon + { 37, 7, 200, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 1906,8 , 2244,24 , 2, 1, 1, 6, 7 }, // French/Latin/Saint Pierre And Miquelon { 37, 7, 206, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 236,8 , 236,8 , 174,8 , 10,17 , 37,5 , 337,14 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {67,72,70}, 217,3 , 8057,45 , 13,5 , 53,6 , 2268,15 , 2283,6 , 2, 0, 1, 6, 7 }, // French/Latin/Switzerland { 37, 7, 207, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 18,7 , 25,12 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {83,89,80}, 220,2 , 8102,51 , 13,5 , 4,0 , 1906,8 , 2289,5 , 0, 0, 6, 5, 6 }, // French/Latin/Syria { 37, 7, 212, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {88,79,70}, 200,3 , 7176,59 , 13,5 , 4,0 , 1906,8 , 2294,4 , 0, 0, 1, 6, 7 }, // French/Latin/Togo { 37, 7, 216, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 18,7 , 25,12 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {84,78,68}, 222,2 , 8153,51 , 13,5 , 4,0 , 1906,8 , 2298,7 , 3, 0, 7, 5, 6 }, // French/Latin/Tunisia { 37, 7, 229, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 18,7 , 25,12 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {86,85,86}, 196,2 , 8204,51 , 13,5 , 4,0 , 1906,8 , 1737,7 , 0, 0, 1, 6, 7 }, // French/Latin/Vanuatu - { 37, 7, 235, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {88,80,70}, 205,4 , 7559,35 , 13,5 , 4,0 , 1906,8 , 2305,16 , 0, 0, 1, 6, 7 }, // French/Latin/WallisAndFutunaIslands + { 37, 7, 235, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {88,80,70}, 205,4 , 7559,35 , 13,5 , 4,0 , 1906,8 , 2305,16 , 0, 0, 1, 6, 7 }, // French/Latin/Wallis And Futuna Islands { 37, 7, 244, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 1906,8 , 2321,16 , 2, 1, 1, 6, 7 }, // French/Latin/Saint Barthelemy { 37, 7, 245, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 236,8 , 236,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6514,63 , 6577,85 , 134,24 , 6514,63 , 6577,85 , 134,24 , 3063,35 , 3098,52 , 3150,14 , 3063,35 , 3098,52 , 3150,14 , 0,2 , 0,2 , 402,6 , 211,17 , 228,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 1906,8 , 2337,12 , 2, 1, 1, 6, 7 }, // French/Latin/Saint Martin { 38, 7, 151, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 6,8 , 6,8 , 357,8 , 98,16 , 37,5 , 8,10 , 6787,48 , 6835,95 , 134,24 , 6787,48 , 6835,95 , 134,24 , 3164,21 , 3185,54 , 85,14 , 3164,21 , 3185,54 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3455,19 , 8,5 , 59,6 , 2349,5 , 2354,8 , 2, 1, 1, 6, 7 }, // Western Frisian/Latin/Netherlands - { 39, 7, 224, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 244,10 , 244,10 , 120,10 , 619,21 , 37,5 , 8,10 , 6930,61 , 6991,142 , 7133,24 , 6930,61 , 7157,167 , 7133,24 , 3239,28 , 3267,69 , 3336,14 , 3239,28 , 3267,69 , 3336,14 , 83,1 , 79,1 , 408,6 , 5,17 , 22,23 , {71,66,80}, 115,1 , 8255,86 , 4,4 , 4,0 , 2362,8 , 2370,22 , 2, 1, 1, 6, 7 }, // Gaelic/Latin/UnitedKingdom + { 39, 7, 224, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 244,10 , 244,10 , 120,10 , 619,21 , 37,5 , 8,10 , 6930,61 , 6991,142 , 7133,24 , 6930,61 , 7157,167 , 7133,24 , 3239,28 , 3267,69 , 3336,14 , 3239,28 , 3267,69 , 3336,14 , 83,1 , 79,1 , 408,6 , 5,17 , 22,23 , {71,66,80}, 115,1 , 8255,86 , 4,4 , 4,0 , 2362,8 , 2370,22 , 2, 1, 1, 6, 7 }, // Gaelic/Latin/United Kingdom { 40, 7, 197, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 640,27 , 37,5 , 8,10 , 7324,60 , 7384,87 , 7471,24 , 7495,60 , 7555,87 , 7642,36 , 3350,35 , 3385,49 , 3434,14 , 3448,35 , 3483,49 , 3532,21 , 66,4 , 63,4 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3910,20 , 13,5 , 4,0 , 2392,6 , 2398,6 , 2, 1, 1, 6, 7 }, // Galician/Latin/Spain { 41, 15, 81, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8220, 171, 187, 0,6 , 0,6 , 261,8 , 261,8 , 174,8 , 667,19 , 37,5 , 8,10 , 7678,48 , 7726,99 , 7825,24 , 7678,48 , 7726,99 , 7825,24 , 3553,28 , 3581,62 , 3643,14 , 3553,28 , 3581,62 , 3643,14 , 0,2 , 0,2 , 414,5 , 419,33 , 22,23 , {71,69,76}, 224,1 , 8341,43 , 13,5 , 4,0 , 2404,7 , 2411,10 , 2, 1, 1, 6, 7 }, // Georgian/Georgian/Georgia { 42, 7, 82, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 269,9 , 269,9 , 174,8 , 593,18 , 37,5 , 8,10 , 7849,48 , 7897,83 , 134,24 , 7980,59 , 7897,83 , 134,24 , 3657,21 , 3678,60 , 3738,14 , 3752,28 , 3678,60 , 3738,14 , 0,2 , 0,2 , 452,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8384,19 , 13,5 , 4,0 , 2421,7 , 2428,11 , 2, 1, 1, 6, 7 }, // German/Latin/Germany @@ -1516,13 +1516,13 @@ static const QLocaleData locale_data[] = { { 51, 7, 99, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 192,8 , 192,8 , 611,8 , 593,18 , 37,5 , 8,10 , 9548,59 , 9607,82 , 9689,24 , 9548,59 , 9607,82 , 9689,24 , 4539,35 , 4574,81 , 4655,14 , 4539,35 , 4574,81 , 4655,14 , 106,4 , 99,4 , 473,4 , 5,17 , 22,23 , {73,83,75}, 228,3 , 8778,49 , 13,5 , 4,0 , 2655,8 , 2663,6 , 0, 0, 1, 6, 7 }, // Icelandic/Latin/Iceland { 52, 7, 101, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 338,10 , 348,9 , 27,8 , 80,18 , 228,5 , 233,10 , 9713,48 , 9761,87 , 134,24 , 9713,48 , 9761,87 , 134,24 , 4669,28 , 4697,43 , 4740,14 , 4669,28 , 4697,43 , 4740,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,68,82}, 231,2 , 8827,39 , 4,4 , 4,0 , 2669,9 , 2669,9 , 0, 0, 7, 6, 7 }, // Indonesian/Latin/Indonesia { 53, 7, 74, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Interlingua/Latin/France - { 55, 44, 38, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {67,65,68}, 233,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 0, 7, 6, 7 }, // Inuktitut/CanadianAboriginal/Canada + { 55, 44, 38, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {67,65,68}, 233,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 0, 7, 6, 7 }, // Inuktitut/Canadian Aboriginal/Canada { 55, 7, 38, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {67,65,68}, 233,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 0, 7, 6, 7 }, // Inuktitut/Latin/Canada { 57, 7, 104, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 357,11 , 244,10 , 120,10 , 98,16 , 37,5 , 8,10 , 9848,62 , 9910,107 , 10017,24 , 9848,62 , 9910,107 , 10017,24 , 4754,37 , 4791,75 , 4866,14 , 4754,37 , 4791,75 , 4866,14 , 110,4 , 103,4 , 477,6 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8866,31 , 4,4 , 4,0 , 2678,7 , 2685,4 , 2, 1, 7, 6, 7 }, // Irish/Latin/Ireland { 58, 7, 106, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 98,16 , 37,5 , 8,10 , 10041,48 , 10089,94 , 10183,24 , 10041,48 , 10089,94 , 10183,24 , 4880,28 , 4908,57 , 4965,14 , 4880,28 , 4908,57 , 4965,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8897,19 , 13,5 , 4,0 , 2689,8 , 2697,6 , 2, 1, 1, 6, 7 }, // Italian/Latin/Italy - { 58, 7, 184, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 98,16 , 37,5 , 8,10 , 10041,48 , 10089,94 , 10183,24 , 10041,48 , 10089,94 , 10183,24 , 4880,28 , 4908,57 , 4965,14 , 4880,28 , 4908,57 , 4965,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8897,19 , 13,5 , 4,0 , 2689,8 , 2703,10 , 2, 1, 1, 6, 7 }, // Italian/Latin/SanMarino + { 58, 7, 184, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 98,16 , 37,5 , 8,10 , 10041,48 , 10089,94 , 10183,24 , 10041,48 , 10089,94 , 10183,24 , 4880,28 , 4908,57 , 4965,14 , 4880,28 , 4908,57 , 4965,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8897,19 , 13,5 , 4,0 , 2689,8 , 2703,10 , 2, 1, 1, 6, 7 }, // Italian/Latin/San Marino { 58, 7, 206, 46, 8217, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 254,7 , 254,7 , 174,8 , 10,17 , 37,5 , 8,10 , 10041,48 , 10089,94 , 10183,24 , 10041,48 , 10089,94 , 10183,24 , 4880,28 , 4908,57 , 4965,14 , 4880,28 , 4908,57 , 4965,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {67,72,70}, 217,3 , 8916,53 , 8,5 , 36,5 , 2689,8 , 2713,8 , 2, 0, 1, 6, 7 }, // Italian/Latin/Switzerland - { 58, 7, 230, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 98,16 , 37,5 , 8,10 , 10041,48 , 10089,94 , 10183,24 , 10041,48 , 10089,94 , 10183,24 , 4880,28 , 4908,57 , 4965,14 , 4880,28 , 4908,57 , 4965,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8897,19 , 13,5 , 4,0 , 2689,8 , 2721,18 , 2, 1, 1, 6, 7 }, // Italian/Latin/VaticanCityState + { 58, 7, 230, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 98,16 , 37,5 , 8,10 , 10041,48 , 10089,94 , 10183,24 , 10041,48 , 10089,94 , 10183,24 , 4880,28 , 4908,57 , 4965,14 , 4880,28 , 4908,57 , 4965,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8897,19 , 13,5 , 4,0 , 2689,8 , 2721,18 , 2, 1, 1, 6, 7 }, // Italian/Latin/Vatican City State { 59, 19, 108, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 170,5 , 170,5 , 170,5 , 170,5 , 549,10 , 420,13 , 55,4 , 372,10 , 4671,39 , 4671,39 , 158,27 , 4671,39 , 4671,39 , 158,27 , 4979,14 , 4993,28 , 4979,14 , 4979,14 , 4993,28 , 4979,14 , 114,2 , 107,2 , 483,3 , 340,17 , 22,23 , {74,80,89}, 129,1 , 8969,11 , 4,4 , 4,0 , 2739,3 , 2742,2 , 0, 0, 7, 6, 7 }, // Japanese/Japanese/Japan { 60, 7, 101, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,68,82}, 231,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 7, 6, 7 }, // Javanese/Latin/Indonesia { 61, 21, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 368,12 , 380,11 , 287,6 , 35,18 , 351,8 , 359,13 , 10207,63 , 10270,87 , 10357,31 , 10388,69 , 10270,87 , 10357,31 , 5021,33 , 5054,54 , 5108,20 , 5021,33 , 5054,54 , 5108,20 , 116,9 , 109,7 , 486,8 , 494,33 , 22,23 , {73,78,82}, 117,1 , 8980,49 , 4,4 , 4,0 , 2744,5 , 2749,4 , 2, 1, 7, 7, 7 }, // Kannada/Kannada/India @@ -1530,16 +1530,16 @@ static const QLocaleData locale_data[] = { { 63, 2, 110, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 391,10 , 174,8 , 753,22 , 37,5 , 8,10 , 10553,60 , 10613,83 , 10696,24 , 10720,60 , 10780,83 , 10696,24 , 5252,21 , 5273,56 , 5329,14 , 5252,21 , 5343,56 , 5329,14 , 0,2 , 0,2 , 527,4 , 531,17 , 548,23 , {75,90,84}, 236,1 , 9052,58 , 13,5 , 4,0 , 2768,10 , 2778,9 , 2, 1, 1, 6, 7 }, // Kazakh/Cyrillic/Kazakhstan { 64, 7, 179, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 10863,60 , 10923,101 , 158,27 , 10863,60 , 10923,101 , 158,27 , 5399,35 , 5434,84 , 85,14 , 5399,35 , 5434,84 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {82,87,70}, 176,2 , 0,7 , 8,5 , 4,0 , 2787,11 , 2798,8 , 0, 0, 1, 6, 7 }, // Kinyarwanda/Latin/Rwanda { 65, 2, 116, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 401,10 , 401,10 , 287,6 , 775,23 , 37,5 , 8,10 , 11024,48 , 11072,80 , 11152,24 , 11176,59 , 11235,80 , 11152,24 , 5518,38 , 5556,57 , 5613,14 , 5518,38 , 5556,57 , 5613,14 , 125,5 , 116,14 , 527,4 , 571,17 , 22,23 , {75,71,83}, 237,3 , 9110,52 , 13,5 , 4,0 , 2806,8 , 2814,10 , 2, 1, 1, 6, 7 }, // Kirghiz/Cyrillic/Kyrgyzstan - { 66, 22, 114, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 411,7 , 411,7 , 798,9 , 807,16 , 382,7 , 389,13 , 11315,39 , 11315,39 , 11315,39 , 11315,39 , 11315,39 , 11315,39 , 5627,14 , 5641,28 , 5627,14 , 5627,14 , 5641,28 , 5627,14 , 130,2 , 130,2 , 588,3 , 5,17 , 22,23 , {75,82,87}, 240,1 , 9162,19 , 4,4 , 4,0 , 2824,3 , 2827,4 , 0, 0, 7, 6, 7 }, // Korean/Korean/SouthKorea - { 66, 22, 113, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 411,7 , 411,7 , 798,9 , 807,16 , 382,7 , 389,13 , 11315,39 , 11315,39 , 11315,39 , 11315,39 , 11315,39 , 11315,39 , 5627,14 , 5641,28 , 5627,14 , 5627,14 , 5641,28 , 5627,14 , 130,2 , 130,2 , 588,3 , 5,17 , 22,23 , {75,80,87}, 241,3 , 9181,39 , 4,4 , 4,0 , 2824,3 , 2831,11 , 0, 0, 1, 6, 7 }, // Korean/Korean/NorthKorea + { 66, 22, 114, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 411,7 , 411,7 , 798,9 , 807,16 , 382,7 , 389,13 , 11315,39 , 11315,39 , 11315,39 , 11315,39 , 11315,39 , 11315,39 , 5627,14 , 5641,28 , 5627,14 , 5627,14 , 5641,28 , 5627,14 , 130,2 , 130,2 , 588,3 , 5,17 , 22,23 , {75,82,87}, 240,1 , 9162,19 , 4,4 , 4,0 , 2824,3 , 2827,4 , 0, 0, 7, 6, 7 }, // Korean/Korean/South Korea + { 66, 22, 113, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 411,7 , 411,7 , 798,9 , 807,16 , 382,7 , 389,13 , 11315,39 , 11315,39 , 11315,39 , 11315,39 , 11315,39 , 11315,39 , 5627,14 , 5641,28 , 5627,14 , 5627,14 , 5641,28 , 5627,14 , 130,2 , 130,2 , 588,3 , 5,17 , 22,23 , {75,80,87}, 241,3 , 9181,39 , 4,4 , 4,0 , 2824,3 , 2831,11 , 0, 0, 1, 6, 7 }, // Korean/Korean/North Korea { 67, 7, 217, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {84,82,89}, 244,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Kurdish/Latin/Turkey { 68, 7, 35, 44, 46, 59, 37, 48, 45, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 433,8 , 98,16 , 37,5 , 8,10 , 11354,60 , 11414,106 , 158,27 , 11354,60 , 11414,106 , 158,27 , 5669,34 , 5703,89 , 85,14 , 5669,34 , 5703,89 , 85,14 , 132,5 , 132,5 , 45,4 , 5,17 , 22,23 , {66,73,70}, 159,3 , 9220,27 , 0,4 , 4,0 , 2842,8 , 2850,8 , 0, 0, 1, 6, 7 }, // Rundi/Latin/Burundi { 69, 23, 117, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 418,9 , 433,8 , 823,19 , 55,4 , 402,24 , 11520,61 , 11581,75 , 158,27 , 11520,61 , 11581,75 , 158,27 , 5792,36 , 5828,57 , 5885,17 , 5792,36 , 5828,57 , 5885,17 , 137,8 , 137,8 , 45,4 , 5,17 , 22,23 , {76,65,75}, 245,1 , 9247,21 , 4,4 , 36,5 , 2858,3 , 2858,3 , 0, 0, 7, 6, 7 }, // Lao/Lao/Laos { 71, 7, 118, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 427,8 , 427,8 , 174,8 , 842,26 , 37,5 , 8,10 , 11656,65 , 11721,101 , 134,24 , 11656,65 , 11721,101 , 134,24 , 5902,51 , 5953,72 , 6025,14 , 6039,51 , 6090,72 , 6025,14 , 145,14 , 145,11 , 591,5 , 340,17 , 22,23 , {69,85,82}, 14,1 , 9268,23 , 13,5 , 4,0 , 2861,8 , 2869,7 , 2, 1, 1, 6, 7 }, // Latvian/Latin/Latvia - { 72, 7, 49, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 435,9 , 435,9 , 433,8 , 98,16 , 37,5 , 8,10 , 11822,48 , 11870,203 , 12073,24 , 11822,48 , 11870,203 , 12073,24 , 6162,28 , 6190,100 , 6290,14 , 6162,28 , 6190,100 , 6290,14 , 159,8 , 156,6 , 45,4 , 5,17 , 22,23 , {67,68,70}, 203,2 , 9291,23 , 13,5 , 4,0 , 2876,7 , 2883,30 , 2, 1, 1, 6, 7 }, // Lingala/Latin/CongoKinshasa + { 72, 7, 49, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 435,9 , 435,9 , 433,8 , 98,16 , 37,5 , 8,10 , 11822,48 , 11870,203 , 12073,24 , 11822,48 , 11870,203 , 12073,24 , 6162,28 , 6190,100 , 6290,14 , 6162,28 , 6190,100 , 6290,14 , 159,8 , 156,6 , 45,4 , 5,17 , 22,23 , {67,68,70}, 203,2 , 9291,23 , 13,5 , 4,0 , 2876,7 , 2883,30 , 2, 1, 1, 6, 7 }, // Lingala/Latin/Congo Kinshasa { 72, 7, 6, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 435,9 , 435,9 , 433,8 , 98,16 , 37,5 , 8,10 , 11822,48 , 11870,203 , 12073,24 , 11822,48 , 11870,203 , 12073,24 , 6162,28 , 6190,100 , 6290,14 , 6162,28 , 6190,100 , 6290,14 , 159,8 , 156,6 , 45,4 , 5,17 , 22,23 , {65,79,65}, 246,2 , 9314,23 , 13,5 , 4,0 , 2876,7 , 2913,6 , 2, 1, 1, 6, 7 }, // Lingala/Latin/Angola - { 72, 7, 41, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 435,9 , 435,9 , 433,8 , 98,16 , 37,5 , 8,10 , 11822,48 , 11870,203 , 12073,24 , 11822,48 , 11870,203 , 12073,24 , 6162,28 , 6190,100 , 6290,14 , 6162,28 , 6190,100 , 6290,14 , 159,8 , 156,6 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 9337,23 , 13,5 , 4,0 , 2876,7 , 2919,26 , 0, 0, 1, 6, 7 }, // Lingala/Latin/CentralAfricanRepublic - { 72, 7, 50, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 435,9 , 435,9 , 433,8 , 98,16 , 37,5 , 8,10 , 11822,48 , 11870,203 , 12073,24 , 11822,48 , 11870,203 , 12073,24 , 6162,28 , 6190,100 , 6290,14 , 6162,28 , 6190,100 , 6290,14 , 159,8 , 156,6 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 9337,23 , 13,5 , 4,0 , 2876,7 , 2945,5 , 0, 0, 1, 6, 7 }, // Lingala/Latin/CongoBrazzaville + { 72, 7, 41, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 435,9 , 435,9 , 433,8 , 98,16 , 37,5 , 8,10 , 11822,48 , 11870,203 , 12073,24 , 11822,48 , 11870,203 , 12073,24 , 6162,28 , 6190,100 , 6290,14 , 6162,28 , 6190,100 , 6290,14 , 159,8 , 156,6 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 9337,23 , 13,5 , 4,0 , 2876,7 , 2919,26 , 0, 0, 1, 6, 7 }, // Lingala/Latin/Central African Republic + { 72, 7, 50, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 435,9 , 435,9 , 433,8 , 98,16 , 37,5 , 8,10 , 11822,48 , 11870,203 , 12073,24 , 11822,48 , 11870,203 , 12073,24 , 6162,28 , 6190,100 , 6290,14 , 6162,28 , 6190,100 , 6290,14 , 159,8 , 156,6 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 9337,23 , 13,5 , 4,0 , 2876,7 , 2945,5 , 0, 0, 1, 6, 7 }, // Lingala/Latin/Congo Brazzaville { 73, 7, 124, 44, 160, 59, 37, 48, 8722, 43, 101, 8222, 8220, 8222, 8220, 0,6 , 0,6 , 444,8 , 444,8 , 53,10 , 868,27 , 37,5 , 8,10 , 12097,70 , 12167,96 , 12263,24 , 12097,70 , 12287,98 , 12263,24 , 6304,21 , 6325,89 , 6414,14 , 6304,21 , 6325,89 , 6414,14 , 167,9 , 162,6 , 596,6 , 5,17 , 22,23 , {69,85,82}, 14,1 , 9360,30 , 13,5 , 4,0 , 2950,8 , 2958,7 , 2, 1, 1, 6, 7 }, // Lithuanian/Latin/Lithuania { 74, 2, 127, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 116,7 , 116,7 , 895,7 , 80,18 , 37,5 , 8,10 , 12385,61 , 12446,85 , 12531,24 , 12385,61 , 12446,85 , 12531,24 , 6428,35 , 6463,54 , 1659,14 , 6517,34 , 6463,54 , 1659,14 , 176,10 , 168,8 , 602,5 , 5,17 , 22,23 , {77,75,68}, 248,3 , 9390,56 , 13,5 , 4,0 , 2965,10 , 2975,10 , 2, 1, 1, 6, 7 }, // Macedonian/Cyrillic/Macedonia { 75, 7, 128, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 98,16 , 37,5 , 8,10 , 12555,48 , 12603,92 , 134,24 , 12555,48 , 12603,92 , 134,24 , 6551,34 , 6585,60 , 6645,14 , 6551,34 , 6585,60 , 6645,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {77,71,65}, 166,2 , 9446,13 , 8,5 , 4,0 , 2985,8 , 2993,12 , 0, 0, 1, 6, 7 }, // Malagasy/Latin/Madagascar @@ -1549,14 +1549,14 @@ static const QLocaleData locale_data[] = { { 76, 7, 190, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 348,9 , 348,9 , 536,7 , 10,17 , 18,7 , 25,12 , 12695,48 , 12743,82 , 12825,24 , 12695,48 , 12743,82 , 12825,24 , 6659,28 , 6687,43 , 6730,14 , 6659,28 , 6687,43 , 6730,14 , 186,2 , 176,3 , 607,4 , 5,17 , 22,23 , {83,71,68}, 6,1 , 9529,37 , 4,4 , 4,0 , 3005,6 , 3017,9 , 2, 1, 7, 6, 7 }, // Malay/Latin/Singapore { 77, 24, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 452,13 , 465,12 , 287,6 , 914,18 , 18,7 , 25,12 , 12849,62 , 12911,88 , 12999,32 , 12849,62 , 12911,88 , 12999,32 , 6744,41 , 6785,77 , 6862,22 , 6744,41 , 6884,76 , 6960,21 , 0,2 , 0,2 , 611,6 , 617,31 , 22,23 , {73,78,82}, 117,1 , 9566,40 , 4,4 , 4,0 , 3026,6 , 3032,6 , 2, 1, 7, 7, 7 }, // Malayalam/Malayalam/India { 78, 7, 133, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 477,8 , 485,7 , 120,10 , 932,23 , 37,5 , 8,10 , 13031,48 , 13079,86 , 13165,36 , 13031,48 , 13079,86 , 13201,24 , 6981,28 , 7009,63 , 7072,21 , 6981,28 , 7009,63 , 7093,20 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 9606,27 , 4,4 , 4,0 , 3038,5 , 1248,5 , 2, 1, 7, 6, 7 }, // Maltese/Latin/Malta - { 79, 7, 154, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {78,90,68}, 251,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Maori/Latin/NewZealand + { 79, 7, 154, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {78,90,68}, 251,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Maori/Latin/New Zealand { 80, 13, 100, 46, 44, 59, 37, 2406, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 492,9 , 492,9 , 287,6 , 210,18 , 18,7 , 25,12 , 13225,66 , 13291,86 , 13377,32 , 13225,66 , 13291,86 , 13377,32 , 7113,32 , 7145,53 , 4432,19 , 7113,32 , 7145,53 , 4432,19 , 188,5 , 179,4 , 465,4 , 5,17 , 22,23 , {73,78,82}, 117,1 , 9633,43 , 4,4 , 4,0 , 3043,5 , 2633,4 , 2, 1, 7, 7, 7 }, // Marathi/Devanagari/India { 82, 2, 143, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 955,10 , 965,16 , 37,5 , 87,12 , 13409,99 , 13508,190 , 13698,38 , 13409,99 , 13508,190 , 13698,38 , 7198,21 , 7219,43 , 7198,21 , 7198,21 , 7219,43 , 7198,21 , 193,3 , 183,3 , 527,4 , 571,17 , 22,23 , {77,78,84}, 254,1 , 9676,25 , 8,5 , 4,0 , 3048,6 , 3054,6 , 0, 0, 1, 6, 7 }, // Mongolian/Cyrillic/Mongolia { 82, 8, 44, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {67,78,89}, 255,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Mongolian/Mongolian/China { 84, 13, 150, 46, 44, 59, 37, 2406, 45, 43, 101, 8220, 8221, 8216, 8217, 501,5 , 0,6 , 506,7 , 506,7 , 245,6 , 63,17 , 37,5 , 8,10 , 13736,85 , 13736,85 , 13821,53 , 13736,85 , 13736,85 , 13874,52 , 7262,33 , 7295,54 , 7349,18 , 7262,33 , 7295,54 , 7349,18 , 94,9 , 89,7 , 465,4 , 5,17 , 22,23 , {78,80,82}, 258,4 , 9701,49 , 8,5 , 4,0 , 3060,6 , 3066,5 , 2, 1, 7, 6, 7 }, // Nepali/Devanagari/Nepal { 84, 13, 100, 46, 44, 59, 37, 2406, 45, 43, 101, 8220, 8221, 8216, 8217, 501,5 , 0,6 , 506,7 , 506,7 , 245,6 , 63,17 , 18,7 , 25,12 , 13736,85 , 13736,85 , 13821,53 , 13736,85 , 13736,85 , 13874,52 , 7262,33 , 7295,54 , 7349,18 , 7262,33 , 7295,54 , 7349,18 , 94,9 , 89,7 , 465,4 , 5,17 , 22,23 , {73,78,82}, 117,1 , 9750,49 , 8,5 , 4,0 , 3060,6 , 2633,4 , 2, 1, 7, 7, 7 }, // Nepali/Devanagari/India - { 85, 7, 161, 44, 160, 59, 37, 48, 8722, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 192,8 , 192,8 , 981,10 , 496,17 , 37,5 , 8,10 , 5904,48 , 13926,83 , 134,24 , 6035,59 , 13926,83 , 134,24 , 2377,35 , 2312,51 , 2363,14 , 2377,35 , 2312,51 , 2363,14 , 66,4 , 63,4 , 45,4 , 5,17 , 22,23 , {78,79,75}, 186,2 , 9799,44 , 8,5 , 4,0 , 3071,12 , 3083,5 , 2, 0, 1, 6, 7 }, // NorwegianBokmal/Latin/Norway - { 85, 7, 203, 44, 160, 59, 37, 48, 8722, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 192,8 , 192,8 , 981,10 , 496,17 , 37,5 , 8,10 , 5904,48 , 13926,83 , 134,24 , 6035,59 , 13926,83 , 134,24 , 2377,35 , 2312,51 , 2363,14 , 2377,35 , 2312,51 , 2363,14 , 66,4 , 63,4 , 45,4 , 5,17 , 22,23 , {78,79,75}, 186,2 , 9799,44 , 8,5 , 4,0 , 3071,12 , 3088,21 , 2, 0, 1, 6, 7 }, // NorwegianBokmal/Latin/SvalbardAndJanMayenIslands + { 85, 7, 161, 44, 160, 59, 37, 48, 8722, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 192,8 , 192,8 , 981,10 , 496,17 , 37,5 , 8,10 , 5904,48 , 13926,83 , 134,24 , 6035,59 , 13926,83 , 134,24 , 2377,35 , 2312,51 , 2363,14 , 2377,35 , 2312,51 , 2363,14 , 66,4 , 63,4 , 45,4 , 5,17 , 22,23 , {78,79,75}, 186,2 , 9799,44 , 8,5 , 4,0 , 3071,12 , 3083,5 , 2, 0, 1, 6, 7 }, // Norwegian Bokmal/Latin/Norway + { 85, 7, 203, 44, 160, 59, 37, 48, 8722, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 192,8 , 192,8 , 981,10 , 496,17 , 37,5 , 8,10 , 5904,48 , 13926,83 , 134,24 , 6035,59 , 13926,83 , 134,24 , 2377,35 , 2312,51 , 2363,14 , 2377,35 , 2312,51 , 2363,14 , 66,4 , 63,4 , 45,4 , 5,17 , 22,23 , {78,79,75}, 186,2 , 9799,44 , 8,5 , 4,0 , 3071,12 , 3088,21 , 2, 0, 1, 6, 7 }, // Norwegian Bokmal/Latin/Svalbard And Jan Mayen Islands { 86, 7, 74, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Occitan/Latin/France { 87, 26, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 513,8 , 521,7 , 543,6 , 35,18 , 18,7 , 25,12 , 14009,86 , 14009,86 , 14095,32 , 14009,86 , 14009,86 , 14095,32 , 7367,33 , 7400,54 , 7454,18 , 7367,33 , 7400,54 , 7454,18 , 0,2 , 0,2 , 648,5 , 5,17 , 22,23 , {73,78,82}, 117,1 , 9843,43 , 8,5 , 4,0 , 3109,5 , 3114,4 , 2, 1, 7, 7, 7 }, // Oriya/Oriya/India { 88, 1, 1, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 8220, 8221, 8216, 8217, 46,6 , 46,6 , 528,9 , 537,8 , 412,8 , 991,20 , 55,4 , 426,11 , 14127,68 , 14195,69 , 158,27 , 14264,69 , 14264,69 , 14333,24 , 7472,39 , 7472,39 , 85,14 , 7472,39 , 7472,39 , 85,14 , 196,4 , 186,4 , 0,5 , 5,17 , 22,23 , {65,70,78}, 262,1 , 9886,25 , 13,5 , 4,0 , 3118,4 , 3122,9 , 0, 0, 6, 4, 5 }, // Pashto/Arabic/Afghanistan @@ -1565,15 +1565,15 @@ static const QLocaleData locale_data[] = { { 90, 7, 172, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 171, 187, 0,6 , 0,6 , 163,7 , 163,7 , 981,10 , 10,17 , 37,5 , 8,10 , 14655,48 , 14703,97 , 14800,24 , 14655,48 , 14824,99 , 14923,24 , 7574,34 , 7608,59 , 7667,14 , 7574,34 , 7608,59 , 7681,14 , 0,2 , 0,2 , 320,5 , 5,17 , 22,23 , {80,76,78}, 267,2 , 10003,77 , 13,5 , 4,0 , 3144,6 , 3150,6 , 2, 1, 1, 6, 7 }, // Polish/Latin/Poland { 91, 7, 30, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 254,7 , 254,7 , 120,10 , 640,27 , 37,5 , 8,10 , 14947,48 , 14995,89 , 134,24 , 14947,48 , 14995,89 , 134,24 , 7695,28 , 7723,79 , 7802,14 , 7695,28 , 7723,79 , 7802,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {66,82,76}, 269,2 , 10080,54 , 8,5 , 4,0 , 3156,9 , 3165,6 , 2, 1, 7, 6, 7 }, // Portuguese/Latin/Brazil { 91, 7, 6, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 640,27 , 37,5 , 8,10 , 14947,48 , 14995,89 , 134,24 , 14947,48 , 14995,89 , 134,24 , 7816,49 , 7723,79 , 7802,14 , 7816,49 , 7723,79 , 7802,14 , 209,8 , 198,8 , 0,5 , 5,17 , 22,23 , {65,79,65}, 246,2 , 10134,54 , 13,5 , 4,0 , 3156,9 , 3171,6 , 2, 1, 1, 6, 7 }, // Portuguese/Latin/Angola - { 91, 7, 39, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 640,27 , 37,5 , 8,10 , 14947,48 , 14995,89 , 134,24 , 14947,48 , 14995,89 , 134,24 , 7816,49 , 7723,79 , 7802,14 , 7816,49 , 7723,79 , 7802,14 , 209,8 , 198,8 , 0,5 , 5,17 , 22,23 , {67,86,69}, 271,1 , 10188,69 , 13,5 , 4,0 , 3156,9 , 3177,10 , 2, 1, 1, 6, 7 }, // Portuguese/Latin/CapeVerde - { 91, 7, 62, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 640,27 , 37,5 , 8,10 , 14947,48 , 14995,89 , 134,24 , 14947,48 , 14995,89 , 134,24 , 7816,49 , 7723,79 , 7802,14 , 7816,49 , 7723,79 , 7802,14 , 209,8 , 198,8 , 0,5 , 5,17 , 22,23 , {85,83,68}, 155,3 , 10257,81 , 13,5 , 4,0 , 3156,9 , 3187,11 , 2, 1, 1, 6, 7 }, // Portuguese/Latin/EastTimor - { 91, 7, 66, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 640,27 , 37,5 , 8,10 , 14947,48 , 14995,89 , 134,24 , 14947,48 , 14995,89 , 134,24 , 7816,49 , 7723,79 , 7802,14 , 7816,49 , 7723,79 , 7802,14 , 209,8 , 198,8 , 0,5 , 5,17 , 22,23 , {88,65,70}, 32,4 , 10338,59 , 13,5 , 4,0 , 3156,9 , 3198,16 , 0, 0, 1, 6, 7 }, // Portuguese/Latin/EquatorialGuinea - { 91, 7, 92, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 640,27 , 37,5 , 8,10 , 14947,48 , 14995,89 , 134,24 , 14947,48 , 14995,89 , 134,24 , 7816,49 , 7723,79 , 7802,14 , 7816,49 , 7723,79 , 7802,14 , 209,8 , 198,8 , 0,5 , 5,17 , 22,23 , {88,79,70}, 200,3 , 10397,62 , 13,5 , 4,0 , 3156,9 , 3214,12 , 0, 0, 1, 6, 7 }, // Portuguese/Latin/GuineaBissau + { 91, 7, 39, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 640,27 , 37,5 , 8,10 , 14947,48 , 14995,89 , 134,24 , 14947,48 , 14995,89 , 134,24 , 7816,49 , 7723,79 , 7802,14 , 7816,49 , 7723,79 , 7802,14 , 209,8 , 198,8 , 0,5 , 5,17 , 22,23 , {67,86,69}, 271,1 , 10188,69 , 13,5 , 4,0 , 3156,9 , 3177,10 , 2, 1, 1, 6, 7 }, // Portuguese/Latin/Cape Verde + { 91, 7, 62, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 640,27 , 37,5 , 8,10 , 14947,48 , 14995,89 , 134,24 , 14947,48 , 14995,89 , 134,24 , 7816,49 , 7723,79 , 7802,14 , 7816,49 , 7723,79 , 7802,14 , 209,8 , 198,8 , 0,5 , 5,17 , 22,23 , {85,83,68}, 155,3 , 10257,81 , 13,5 , 4,0 , 3156,9 , 3187,11 , 2, 1, 1, 6, 7 }, // Portuguese/Latin/East Timor + { 91, 7, 66, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 640,27 , 37,5 , 8,10 , 14947,48 , 14995,89 , 134,24 , 14947,48 , 14995,89 , 134,24 , 7816,49 , 7723,79 , 7802,14 , 7816,49 , 7723,79 , 7802,14 , 209,8 , 198,8 , 0,5 , 5,17 , 22,23 , {88,65,70}, 32,4 , 10338,59 , 13,5 , 4,0 , 3156,9 , 3198,16 , 0, 0, 1, 6, 7 }, // Portuguese/Latin/Equatorial Guinea + { 91, 7, 92, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 640,27 , 37,5 , 8,10 , 14947,48 , 14995,89 , 134,24 , 14947,48 , 14995,89 , 134,24 , 7816,49 , 7723,79 , 7802,14 , 7816,49 , 7723,79 , 7802,14 , 209,8 , 198,8 , 0,5 , 5,17 , 22,23 , {88,79,70}, 200,3 , 10397,62 , 13,5 , 4,0 , 3156,9 , 3214,12 , 0, 0, 1, 6, 7 }, // Portuguese/Latin/Guinea Bissau { 91, 7, 125, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 640,27 , 37,5 , 8,10 , 14947,48 , 14995,89 , 134,24 , 14947,48 , 14995,89 , 134,24 , 7816,49 , 7723,79 , 7802,14 , 7816,49 , 7723,79 , 7802,14 , 209,8 , 198,8 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 3156,9 , 3226,10 , 2, 1, 1, 6, 7 }, // Portuguese/Latin/Luxembourg { 91, 7, 126, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 640,27 , 18,7 , 25,12 , 14947,48 , 14995,89 , 134,24 , 14947,48 , 14995,89 , 134,24 , 7816,49 , 7723,79 , 7802,14 , 7816,49 , 7723,79 , 7802,14 , 209,8 , 198,8 , 0,5 , 5,17 , 22,23 , {77,79,80}, 133,4 , 10459,53 , 13,5 , 4,0 , 3156,9 , 3236,19 , 2, 1, 7, 6, 7 }, // Portuguese/Latin/Macau { 91, 7, 146, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 640,27 , 37,5 , 8,10 , 14947,48 , 14995,89 , 134,24 , 14947,48 , 14995,89 , 134,24 , 7816,49 , 7723,79 , 7802,14 , 7816,49 , 7723,79 , 7802,14 , 209,8 , 198,8 , 0,5 , 5,17 , 22,23 , {77,90,78}, 272,3 , 10512,72 , 13,5 , 4,0 , 3156,9 , 3255,10 , 2, 1, 7, 6, 7 }, // Portuguese/Latin/Mozambique { 91, 7, 173, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 640,27 , 37,5 , 8,10 , 14947,48 , 14995,89 , 134,24 , 14947,48 , 14995,89 , 134,24 , 7816,49 , 7723,79 , 7802,14 , 7816,49 , 7723,79 , 7802,14 , 209,8 , 198,8 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 3265,17 , 3282,8 , 2, 1, 1, 6, 7 }, // Portuguese/Latin/Portugal - { 91, 7, 185, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 640,27 , 37,5 , 8,10 , 14947,48 , 14995,89 , 134,24 , 14947,48 , 14995,89 , 134,24 , 7816,49 , 7723,79 , 7802,14 , 7816,49 , 7723,79 , 7802,14 , 209,8 , 198,8 , 0,5 , 5,17 , 22,23 , {83,84,78}, 275,2 , 10584,104 , 13,5 , 4,0 , 3156,9 , 3290,19 , 2, 1, 1, 6, 7 }, // Portuguese/Latin/SaoTomeAndPrincipe + { 91, 7, 185, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 640,27 , 37,5 , 8,10 , 14947,48 , 14995,89 , 134,24 , 14947,48 , 14995,89 , 134,24 , 7816,49 , 7723,79 , 7802,14 , 7816,49 , 7723,79 , 7802,14 , 209,8 , 198,8 , 0,5 , 5,17 , 22,23 , {83,84,78}, 275,2 , 10584,104 , 13,5 , 4,0 , 3156,9 , 3290,19 , 2, 1, 1, 6, 7 }, // Portuguese/Latin/Sao Tome And Principe { 91, 7, 206, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 640,27 , 37,5 , 8,10 , 14947,48 , 14995,89 , 134,24 , 14947,48 , 14995,89 , 134,24 , 7816,49 , 7723,79 , 7802,14 , 7816,49 , 7723,79 , 7802,14 , 209,8 , 198,8 , 0,5 , 5,17 , 22,23 , {67,72,70}, 217,3 , 10688,45 , 13,5 , 4,0 , 3156,9 , 3309,5 , 2, 0, 1, 6, 7 }, // Portuguese/Latin/Switzerland { 92, 4, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 567,9 , 567,9 , 287,6 , 10,17 , 18,7 , 25,12 , 15084,50 , 15134,68 , 15202,28 , 15084,50 , 15134,68 , 15202,28 , 7865,36 , 7901,57 , 7958,23 , 7865,36 , 7901,57 , 7958,23 , 217,6 , 206,6 , 696,4 , 5,17 , 22,23 , {73,78,82}, 117,1 , 10733,39 , 4,4 , 4,0 , 3314,6 , 3320,4 , 2, 1, 7, 7, 7 }, // Punjabi/Gurmukhi/India { 92, 1, 163, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 80,18 , 18,7 , 25,12 , 15230,67 , 15230,67 , 158,27 , 15230,67 , 15230,67 , 158,27 , 7981,37 , 7981,37 , 85,14 , 7981,37 , 7981,37 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {80,75,82}, 277,1 , 10772,13 , 41,6 , 4,0 , 3324,6 , 3330,7 , 0, 0, 7, 6, 7 }, // Punjabi/Arabic/Pakistan @@ -1589,24 +1589,24 @@ static const QLocaleData locale_data[] = { { 96, 2, 116, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 116,7 , 116,7 , 981,10 , 335,22 , 55,4 , 59,9 , 15798,62 , 11235,80 , 11152,24 , 15860,62 , 15922,82 , 11152,24 , 8332,21 , 8353,62 , 8415,14 , 8332,21 , 8353,62 , 8332,21 , 0,2 , 0,2 , 263,5 , 571,17 , 22,23 , {75,71,83}, 237,3 , 11223,82 , 13,5 , 4,0 , 3408,7 , 3430,8 , 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Kyrgyzstan { 96, 2, 141, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 116,7 , 116,7 , 981,10 , 335,22 , 55,4 , 59,9 , 15798,62 , 11235,80 , 11152,24 , 15860,62 , 15922,82 , 11152,24 , 8332,21 , 8353,62 , 8415,14 , 8332,21 , 8353,62 , 8332,21 , 0,2 , 0,2 , 263,5 , 571,17 , 22,23 , {77,68,76}, 285,1 , 11305,79 , 13,5 , 4,0 , 3408,7 , 3438,7 , 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Moldova { 96, 2, 222, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 116,7 , 116,7 , 981,10 , 335,22 , 37,5 , 8,10 , 15798,62 , 11235,80 , 11152,24 , 15860,62 , 15922,82 , 11152,24 , 8332,21 , 8353,62 , 8415,14 , 8332,21 , 8353,62 , 8332,21 , 0,2 , 0,2 , 263,5 , 571,17 , 22,23 , {85,65,72}, 286,1 , 11384,92 , 13,5 , 4,0 , 3408,7 , 3445,7 , 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Ukraine - { 98, 7, 41, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 433,8 , 98,16 , 37,5 , 8,10 , 16004,48 , 16052,91 , 16143,24 , 16004,48 , 16052,91 , 16143,24 , 8429,28 , 8457,66 , 8523,14 , 8429,28 , 8457,66 , 8523,14 , 223,2 , 212,2 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 11476,25 , 4,4 , 36,5 , 3452,5 , 3457,22 , 0, 0, 1, 6, 7 }, // Sango/Latin/CentralAfricanRepublic + { 98, 7, 41, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 433,8 , 98,16 , 37,5 , 8,10 , 16004,48 , 16052,91 , 16143,24 , 16004,48 , 16052,91 , 16143,24 , 8429,28 , 8457,66 , 8523,14 , 8429,28 , 8457,66 , 8523,14 , 223,2 , 212,2 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 11476,25 , 4,4 , 36,5 , 3452,5 , 3457,22 , 0, 0, 1, 6, 7 }, // Sango/Latin/Central African Republic { 99, 13, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,78,82}, 117,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 7, 7 }, // Sanskrit/Devanagari/India { 100, 2, 243, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 116,7 , 116,7 , 1039,7 , 1046,20 , 37,5 , 8,10 , 16167,48 , 16215,81 , 12531,24 , 16167,48 , 16215,81 , 12531,24 , 8537,28 , 8565,52 , 8617,14 , 8537,28 , 8565,52 , 8617,14 , 225,9 , 214,8 , 704,7 , 5,17 , 22,23 , {82,83,68}, 287,3 , 11501,58 , 13,5 , 4,0 , 3479,6 , 3485,6 , 0, 0, 1, 6, 7 }, // Serbian/Cyrillic/Serbia - { 100, 7, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 163,7 , 163,7 , 1039,7 , 1046,20 , 37,5 , 8,10 , 16296,58 , 16354,81 , 16435,24 , 16296,58 , 16354,81 , 16435,24 , 8631,33 , 8664,57 , 2172,14 , 8631,33 , 8664,57 , 2172,14 , 234,11 , 222,8 , 313,7 , 5,17 , 22,23 , {66,65,77}, 140,2 , 11559,174 , 13,5 , 4,0 , 3491,6 , 620,19 , 2, 1, 1, 6, 7 }, // Serbian/Latin/BosniaAndHerzegowina + { 100, 7, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 163,7 , 163,7 , 1039,7 , 1046,20 , 37,5 , 8,10 , 16296,58 , 16354,81 , 16435,24 , 16296,58 , 16354,81 , 16435,24 , 8631,33 , 8664,57 , 2172,14 , 8631,33 , 8664,57 , 2172,14 , 234,11 , 222,8 , 313,7 , 5,17 , 22,23 , {66,65,77}, 140,2 , 11559,174 , 13,5 , 4,0 , 3491,6 , 620,19 , 2, 1, 1, 6, 7 }, // Serbian/Latin/Bosnia And Herzegowina { 100, 7, 242, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 163,7 , 163,7 , 1039,7 , 1046,20 , 37,5 , 8,10 , 16296,58 , 16354,81 , 16435,24 , 16296,58 , 16354,81 , 16435,24 , 8631,33 , 8664,57 , 2172,14 , 8631,33 , 8664,57 , 2172,14 , 234,11 , 222,8 , 313,7 , 5,17 , 22,23 , {69,85,82}, 14,1 , 11733,23 , 13,5 , 4,0 , 3491,6 , 3497,9 , 2, 1, 1, 6, 7 }, // Serbian/Latin/Montenegro { 100, 7, 243, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 163,7 , 163,7 , 1039,7 , 1046,20 , 37,5 , 8,10 , 16459,48 , 16354,81 , 16435,24 , 16459,48 , 16354,81 , 16435,24 , 8721,28 , 8749,54 , 2172,14 , 8721,28 , 8749,54 , 2172,14 , 245,9 , 222,8 , 313,7 , 5,17 , 22,23 , {82,83,68}, 287,3 , 11756,58 , 13,5 , 4,0 , 3491,6 , 3506,6 , 0, 0, 1, 6, 7 }, // Serbian/Latin/Serbia - { 100, 2, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 116,7 , 116,7 , 1039,7 , 1046,20 , 37,5 , 8,10 , 16507,58 , 16215,81 , 12531,24 , 16507,58 , 16215,81 , 12531,24 , 8803,33 , 8836,55 , 8617,14 , 8803,33 , 8836,55 , 8617,14 , 254,11 , 214,8 , 704,7 , 5,17 , 22,23 , {66,65,77}, 290,2 , 11814,174 , 13,5 , 4,0 , 3479,6 , 3512,19 , 2, 1, 1, 6, 7 }, // Serbian/Cyrillic/BosniaAndHerzegowina + { 100, 2, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 116,7 , 116,7 , 1039,7 , 1046,20 , 37,5 , 8,10 , 16507,58 , 16215,81 , 12531,24 , 16507,58 , 16215,81 , 12531,24 , 8803,33 , 8836,55 , 8617,14 , 8803,33 , 8836,55 , 8617,14 , 254,11 , 214,8 , 704,7 , 5,17 , 22,23 , {66,65,77}, 290,2 , 11814,174 , 13,5 , 4,0 , 3479,6 , 3512,19 , 2, 1, 1, 6, 7 }, // Serbian/Cyrillic/Bosnia And Herzegowina { 100, 2, 242, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 116,7 , 116,7 , 1039,7 , 1046,20 , 37,5 , 8,10 , 16507,58 , 16215,81 , 12531,24 , 16507,58 , 16215,81 , 12531,24 , 8803,33 , 8836,55 , 8617,14 , 8803,33 , 8836,55 , 8617,14 , 254,11 , 214,8 , 704,7 , 5,17 , 22,23 , {69,85,82}, 14,1 , 11988,23 , 13,5 , 4,0 , 3479,6 , 3531,9 , 2, 1, 1, 6, 7 }, // Serbian/Cyrillic/Montenegro { 100, 2, 257, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 116,7 , 116,7 , 1039,7 , 1046,20 , 37,5 , 8,10 , 16507,58 , 16215,81 , 12531,24 , 16507,58 , 16215,81 , 12531,24 , 8803,33 , 8565,52 , 8617,14 , 8803,33 , 8565,52 , 8617,14 , 225,9 , 214,8 , 704,7 , 5,17 , 22,23 , {69,85,82}, 14,1 , 11988,23 , 13,5 , 4,0 , 3479,6 , 3540,6 , 2, 1, 1, 6, 7 }, // Serbian/Cyrillic/Kosovo { 100, 7, 257, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 163,7 , 163,7 , 1039,7 , 1046,20 , 37,5 , 8,10 , 16296,58 , 16354,81 , 16435,24 , 16296,58 , 16354,81 , 16435,24 , 8631,33 , 8749,54 , 2172,14 , 8631,33 , 8749,54 , 2172,14 , 245,9 , 222,8 , 313,7 , 5,17 , 22,23 , {69,85,82}, 14,1 , 11733,23 , 13,5 , 4,0 , 3491,6 , 3546,6 , 2, 1, 1, 6, 7 }, // Serbian/Latin/Kosovo { 101, 2, 81, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 584,9 , 584,9 , 174,8 , 1066,23 , 37,5 , 8,10 , 16565,63 , 16628,82 , 11152,24 , 16710,60 , 16770,86 , 11152,24 , 8891,28 , 8919,61 , 8980,14 , 8994,28 , 9022,61 , 8980,14 , 265,15 , 230,15 , 45,4 , 5,17 , 22,23 , {71,69,76}, 224,1 , 12011,17 , 8,5 , 4,0 , 3552,4 , 3556,11 , 2, 1, 1, 6, 7 }, // Ossetic/Cyrillic/Georgia { 101, 2, 178, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 584,9 , 584,9 , 174,8 , 1066,23 , 37,5 , 8,10 , 16565,63 , 16628,82 , 11152,24 , 16710,60 , 16770,86 , 11152,24 , 8891,28 , 8919,61 , 8980,14 , 8994,28 , 9022,61 , 8980,14 , 265,15 , 230,15 , 45,4 , 5,17 , 22,23 , {82,85,66}, 119,1 , 12028,17 , 8,5 , 4,0 , 3552,4 , 3567,6 , 2, 1, 1, 6, 7 }, // Ossetic/Cyrillic/Russia - { 102, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Southern Sotho/Latin/SouthAfrica - { 103, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Tswana/Latin/SouthAfrica + { 102, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Southern Sotho/Latin/South Africa + { 103, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Tswana/Latin/South Africa { 104, 7, 240, 46, 44, 59, 37, 48, 45, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 16856,48 , 16904,100 , 17004,24 , 16856,48 , 16904,100 , 17004,24 , 9083,28 , 9111,55 , 9166,14 , 9083,28 , 9111,55 , 9166,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,83,68}, 155,3 , 12045,22 , 4,4 , 4,0 , 3573,8 , 1791,8 , 2, 1, 7, 6, 7 }, // Shona/Latin/Zimbabwe { 105, 1, 163, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 18,7 , 25,12 , 17028,72 , 17028,72 , 158,27 , 17028,72 , 17028,72 , 158,27 , 9180,35 , 9180,35 , 9215,21 , 9180,35 , 9180,35 , 9236,31 , 280,11 , 245,11 , 711,6 , 717,52 , 22,23 , {80,75,82}, 172,2 , 12067,43 , 8,5 , 4,0 , 3581,4 , 3585,7 , 0, 0, 7, 6, 7 }, // Sindhi/Arabic/Pakistan - { 106, 32, 198, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 593,9 , 602,8 , 53,10 , 63,17 , 228,5 , 233,10 , 17100,59 , 17159,96 , 17255,32 , 17287,61 , 17159,96 , 17255,32 , 9267,39 , 9306,62 , 9368,19 , 9267,39 , 9306,62 , 9368,19 , 291,5 , 256,4 , 769,5 , 774,37 , 22,23 , {76,75,82}, 292,3 , 12110,58 , 4,4 , 4,0 , 3592,5 , 3597,11 , 2, 1, 1, 6, 7 }, // Sinhala/Sinhala/SriLanka - { 107, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Swati/Latin/SouthAfrica + { 106, 32, 198, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 593,9 , 602,8 , 53,10 , 63,17 , 228,5 , 233,10 , 17100,59 , 17159,96 , 17255,32 , 17287,61 , 17159,96 , 17255,32 , 9267,39 , 9306,62 , 9368,19 , 9267,39 , 9306,62 , 9368,19 , 291,5 , 256,4 , 769,5 , 774,37 , 22,23 , {76,75,82}, 292,3 , 12110,58 , 4,4 , 4,0 , 3592,5 , 3597,11 , 2, 1, 1, 6, 7 }, // Sinhala/Sinhala/Sri Lanka + { 107, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Swati/Latin/South Africa { 108, 7, 191, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 185,7 , 610,7 , 1089,10 , 496,17 , 55,4 , 59,9 , 17348,48 , 17396,82 , 16435,24 , 17348,48 , 17478,89 , 16435,24 , 9387,21 , 9408,52 , 9460,14 , 9387,21 , 9408,52 , 9460,14 , 0,2 , 0,2 , 320,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 12168,26 , 13,5 , 4,0 , 3608,10 , 3618,9 , 2, 1, 1, 6, 7 }, // Slovak/Latin/Slovakia { 109, 7, 192, 44, 46, 59, 37, 48, 8722, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 617,8 , 617,8 , 1099,9 , 1108,19 , 37,5 , 8,10 , 17567,59 , 17626,86 , 16435,24 , 17567,59 , 17626,86 , 16435,24 , 9474,35 , 9509,52 , 9561,14 , 9474,35 , 9509,52 , 9561,14 , 62,4 , 260,4 , 54,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 12194,28 , 13,5 , 4,0 , 3627,11 , 3638,9 , 2, 1, 1, 6, 7 }, // Slovenian/Latin/Slovenia { 110, 7, 194, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1127,19 , 18,7 , 25,12 , 17712,48 , 17760,189 , 17949,24 , 17712,48 , 17760,189 , 17949,24 , 9575,28 , 9603,47 , 9650,15 , 9575,28 , 9603,47 , 9650,15 , 296,3 , 264,3 , 45,4 , 5,17 , 22,23 , {83,79,83}, 90,1 , 12222,22 , 4,4 , 4,0 , 3647,8 , 3655,10 , 0, 0, 1, 6, 7 }, // Somali/Latin/Somalia @@ -1620,12 +1620,12 @@ static const QLocaleData locale_data[] = { { 111, 7, 30, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 625,7 , 625,7 , 287,6 , 640,27 , 37,5 , 8,10 , 18147,60 , 18034,89 , 18123,24 , 18147,60 , 18034,89 , 18123,24 , 9665,35 , 9700,53 , 3150,14 , 9665,35 , 9700,53 , 9753,14 , 66,4 , 63,4 , 0,5 , 5,17 , 22,23 , {66,82,76}, 269,2 , 12425,52 , 4,4 , 4,0 , 3704,7 , 3165,6 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Brazil { 111, 7, 43, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 625,7 , 625,7 , 357,8 , 640,27 , 37,5 , 8,10 , 17973,61 , 18034,89 , 18123,24 , 18147,60 , 18034,89 , 18123,24 , 9665,35 , 9700,53 , 3150,14 , 9665,35 , 9700,53 , 9753,14 , 55,5 , 52,5 , 0,5 , 5,17 , 22,23 , {67,76,80}, 6,1 , 12477,45 , 4,4 , 36,5 , 3704,7 , 3726,5 , 0, 0, 1, 6, 7 }, // Spanish/Latin/Chile { 111, 7, 47, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 625,7 , 625,7 , 536,7 , 640,27 , 18,7 , 25,12 , 17973,61 , 18034,89 , 18123,24 , 18147,60 , 18034,89 , 18123,24 , 9665,35 , 9700,53 , 9753,14 , 9665,35 , 9700,53 , 3150,14 , 55,5 , 52,5 , 0,5 , 5,17 , 22,23 , {67,79,80}, 6,1 , 12522,54 , 8,5 , 4,0 , 3704,7 , 3731,8 , 0, 0, 7, 6, 7 }, // Spanish/Latin/Colombia - { 111, 7, 52, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 625,7 , 625,7 , 287,6 , 640,27 , 37,5 , 8,10 , 18147,60 , 18034,89 , 18123,24 , 18147,60 , 18034,89 , 18123,24 , 9665,35 , 9700,53 , 3150,14 , 9665,35 , 9700,53 , 9753,14 , 55,5 , 52,5 , 0,5 , 5,17 , 22,23 , {67,82,67}, 295,1 , 12576,67 , 4,4 , 4,0 , 3704,7 , 3739,10 , 2, 0, 1, 6, 7 }, // Spanish/Latin/CostaRica + { 111, 7, 52, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 625,7 , 625,7 , 287,6 , 640,27 , 37,5 , 8,10 , 18147,60 , 18034,89 , 18123,24 , 18147,60 , 18034,89 , 18123,24 , 9665,35 , 9700,53 , 3150,14 , 9665,35 , 9700,53 , 9753,14 , 55,5 , 52,5 , 0,5 , 5,17 , 22,23 , {67,82,67}, 295,1 , 12576,67 , 4,4 , 4,0 , 3704,7 , 3739,10 , 2, 0, 1, 6, 7 }, // Spanish/Latin/Costa Rica { 111, 7, 55, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 625,7 , 625,7 , 287,6 , 640,27 , 37,5 , 8,10 , 18147,60 , 18034,89 , 18123,24 , 18147,60 , 18034,89 , 18123,24 , 9665,35 , 9700,53 , 3150,14 , 9665,35 , 9700,53 , 9753,14 , 66,4 , 63,4 , 0,5 , 5,17 , 22,23 , {67,85,80}, 6,1 , 12643,42 , 4,4 , 4,0 , 3704,7 , 3749,4 , 2, 1, 1, 6, 7 }, // Spanish/Latin/Cuba - { 111, 7, 61, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 625,7 , 625,7 , 287,6 , 640,27 , 18,7 , 25,12 , 18147,60 , 18034,89 , 18123,24 , 18147,60 , 18034,89 , 18123,24 , 9665,35 , 9700,53 , 3150,14 , 9665,35 , 9700,53 , 3150,14 , 55,5 , 52,5 , 0,5 , 5,17 , 22,23 , {68,79,80}, 296,3 , 12685,54 , 4,4 , 89,6 , 3704,7 , 3753,20 , 2, 1, 7, 6, 7 }, // Spanish/Latin/DominicanRepublic + { 111, 7, 61, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 625,7 , 625,7 , 287,6 , 640,27 , 18,7 , 25,12 , 18147,60 , 18034,89 , 18123,24 , 18147,60 , 18034,89 , 18123,24 , 9665,35 , 9700,53 , 3150,14 , 9665,35 , 9700,53 , 3150,14 , 55,5 , 52,5 , 0,5 , 5,17 , 22,23 , {68,79,80}, 296,3 , 12685,54 , 4,4 , 89,6 , 3704,7 , 3753,20 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Dominican Republic { 111, 7, 63, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 625,7 , 625,7 , 287,6 , 640,27 , 37,5 , 8,10 , 18147,60 , 18034,89 , 18123,24 , 18147,60 , 18034,89 , 18123,24 , 9665,35 , 9700,53 , 3150,14 , 9665,35 , 9700,53 , 9753,14 , 55,5 , 52,5 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 12739,70 , 4,4 , 36,5 , 3704,7 , 3356,7 , 2, 1, 1, 6, 7 }, // Spanish/Latin/Ecuador - { 111, 7, 65, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 625,7 , 625,7 , 287,6 , 640,27 , 37,5 , 8,10 , 18147,60 , 18034,89 , 18123,24 , 18147,60 , 18034,89 , 18123,24 , 9665,35 , 9700,53 , 3150,14 , 9665,35 , 9700,53 , 9753,14 , 55,5 , 52,5 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 12739,70 , 4,4 , 4,0 , 3704,7 , 3773,11 , 2, 1, 7, 6, 7 }, // Spanish/Latin/ElSalvador - { 111, 7, 66, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 625,7 , 625,7 , 287,6 , 640,27 , 55,4 , 426,11 , 17973,61 , 18034,89 , 18123,24 , 17973,61 , 18034,89 , 18123,24 , 9665,35 , 9700,53 , 8099,14 , 9665,35 , 9700,53 , 8099,14 , 55,5 , 52,5 , 0,5 , 5,17 , 22,23 , {88,65,70}, 32,4 , 12809,92 , 4,4 , 4,0 , 3704,7 , 3784,17 , 0, 0, 1, 6, 7 }, // Spanish/Latin/EquatorialGuinea + { 111, 7, 65, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 625,7 , 625,7 , 287,6 , 640,27 , 37,5 , 8,10 , 18147,60 , 18034,89 , 18123,24 , 18147,60 , 18034,89 , 18123,24 , 9665,35 , 9700,53 , 3150,14 , 9665,35 , 9700,53 , 9753,14 , 55,5 , 52,5 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 12739,70 , 4,4 , 4,0 , 3704,7 , 3773,11 , 2, 1, 7, 6, 7 }, // Spanish/Latin/El Salvador + { 111, 7, 66, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 625,7 , 625,7 , 287,6 , 640,27 , 55,4 , 426,11 , 17973,61 , 18034,89 , 18123,24 , 17973,61 , 18034,89 , 18123,24 , 9665,35 , 9700,53 , 8099,14 , 9665,35 , 9700,53 , 8099,14 , 55,5 , 52,5 , 0,5 , 5,17 , 22,23 , {88,65,70}, 32,4 , 12809,92 , 4,4 , 4,0 , 3704,7 , 3784,17 , 0, 0, 1, 6, 7 }, // Spanish/Latin/Equatorial Guinea { 111, 7, 90, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 625,7 , 625,7 , 536,7 , 640,27 , 37,5 , 8,10 , 18147,60 , 18034,89 , 18123,24 , 18147,60 , 18034,89 , 18123,24 , 9665,35 , 9700,53 , 3150,14 , 9665,35 , 9700,53 , 9753,14 , 55,5 , 52,5 , 0,5 , 5,17 , 22,23 , {71,84,81}, 299,1 , 12901,30 , 18,5 , 4,0 , 3704,7 , 3801,9 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Guatemala { 111, 7, 96, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 625,7 , 625,7 , 287,6 , 1146,27 , 37,5 , 8,10 , 18147,60 , 18034,89 , 18123,24 , 18147,60 , 18034,89 , 18123,24 , 9665,35 , 9700,53 , 3150,14 , 9665,35 , 9700,53 , 9753,14 , 55,5 , 52,5 , 0,5 , 5,17 , 22,23 , {72,78,76}, 285,1 , 12931,60 , 4,4 , 4,0 , 3704,7 , 3810,8 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Honduras { 111, 7, 139, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 625,7 , 625,7 , 27,8 , 640,27 , 55,4 , 59,9 , 18147,60 , 18034,89 , 18123,24 , 18207,48 , 18034,89 , 18123,24 , 9665,35 , 9700,53 , 3150,14 , 9665,35 , 9700,53 , 3150,14 , 55,5 , 52,5 , 0,5 , 5,17 , 22,23 , {77,88,78}, 6,1 , 12991,48 , 47,6 , 4,0 , 3818,17 , 3835,6 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Mexico @@ -1634,25 +1634,25 @@ static const QLocaleData locale_data[] = { { 111, 7, 168, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 625,7 , 625,7 , 287,6 , 640,27 , 37,5 , 8,10 , 17973,61 , 18034,89 , 18123,24 , 17973,61 , 18034,89 , 18123,24 , 9665,35 , 9700,53 , 3150,14 , 9665,35 , 9700,53 , 9753,14 , 55,5 , 52,5 , 0,5 , 5,17 , 22,23 , {80,89,71}, 305,3 , 13162,61 , 8,5 , 23,6 , 3704,7 , 3856,8 , 0, 0, 7, 6, 7 }, // Spanish/Latin/Paraguay { 111, 7, 169, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 625,7 , 625,7 , 536,7 , 640,27 , 37,5 , 8,10 , 18255,60 , 15345,88 , 18123,24 , 18315,60 , 18375,88 , 18123,24 , 9665,35 , 9700,53 , 3150,14 , 9665,35 , 9700,53 , 9753,14 , 55,5 , 52,5 , 0,5 , 5,17 , 22,23 , {80,69,78}, 278,2 , 13223,43 , 4,4 , 4,0 , 3704,7 , 3345,4 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Peru { 111, 7, 170, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 625,7 , 625,7 , 287,6 , 640,27 , 18,7 , 25,12 , 17973,61 , 18034,89 , 18123,24 , 17973,61 , 18034,89 , 18123,24 , 9665,35 , 9700,53 , 8099,14 , 9665,35 , 9700,53 , 8099,14 , 55,5 , 52,5 , 0,5 , 5,17 , 22,23 , {80,72,80}, 175,1 , 13266,48 , 13,5 , 4,0 , 3704,7 , 3864,9 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Philippines - { 111, 7, 174, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 625,7 , 625,7 , 1173,8 , 640,27 , 18,7 , 25,12 , 18147,60 , 18034,89 , 18123,24 , 18147,60 , 18034,89 , 18123,24 , 9665,35 , 9700,53 , 3150,14 , 9665,35 , 9700,53 , 9753,14 , 55,5 , 52,5 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 12739,70 , 4,4 , 4,0 , 3704,7 , 1437,11 , 2, 1, 7, 6, 7 }, // Spanish/Latin/PuertoRico - { 111, 7, 225, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 625,7 , 625,7 , 433,8 , 640,27 , 18,7 , 25,12 , 18147,60 , 18034,89 , 18123,24 , 18147,60 , 18034,89 , 18123,24 , 9665,35 , 9700,53 , 3150,14 , 9665,35 , 9700,53 , 3150,14 , 55,5 , 52,5 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 12739,70 , 95,7 , 4,0 , 3704,7 , 3873,14 , 2, 1, 7, 6, 7 }, // Spanish/Latin/UnitedStates + { 111, 7, 174, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 625,7 , 625,7 , 1173,8 , 640,27 , 18,7 , 25,12 , 18147,60 , 18034,89 , 18123,24 , 18147,60 , 18034,89 , 18123,24 , 9665,35 , 9700,53 , 3150,14 , 9665,35 , 9700,53 , 9753,14 , 55,5 , 52,5 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 12739,70 , 4,4 , 4,0 , 3704,7 , 1437,11 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Puerto Rico + { 111, 7, 225, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 625,7 , 625,7 , 433,8 , 640,27 , 18,7 , 25,12 , 18147,60 , 18034,89 , 18123,24 , 18147,60 , 18034,89 , 18123,24 , 9665,35 , 9700,53 , 3150,14 , 9665,35 , 9700,53 , 3150,14 , 55,5 , 52,5 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 12739,70 , 95,7 , 4,0 , 3704,7 , 3873,14 , 2, 1, 7, 6, 7 }, // Spanish/Latin/United States { 111, 7, 227, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 625,7 , 625,7 , 287,6 , 640,27 , 37,5 , 8,10 , 18255,60 , 15345,88 , 18123,24 , 18315,60 , 18375,88 , 18123,24 , 9665,35 , 9700,53 , 3150,14 , 9665,35 , 9700,53 , 9753,14 , 55,5 , 52,5 , 0,5 , 5,17 , 22,23 , {85,89,85}, 6,1 , 13314,48 , 8,5 , 4,0 , 3704,7 , 3887,7 , 2, 1, 1, 6, 7 }, // Spanish/Latin/Uruguay { 111, 7, 231, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 625,7 , 625,7 , 287,6 , 640,27 , 18,7 , 25,12 , 17973,61 , 18034,89 , 18123,24 , 17973,61 , 18034,89 , 18123,24 , 9665,35 , 9700,53 , 3150,14 , 9665,35 , 9700,53 , 9753,14 , 55,5 , 52,5 , 0,5 , 5,17 , 22,23 , {86,69,70}, 308,3 , 13362,64 , 4,4 , 36,5 , 3704,7 , 3894,9 , 2, 0, 7, 6, 7 }, // Spanish/Latin/Venezuela - { 111, 7, 238, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 625,7 , 625,7 , 287,6 , 640,27 , 55,4 , 426,11 , 17973,61 , 18034,89 , 18123,24 , 17973,61 , 18034,89 , 18123,24 , 9665,35 , 9700,53 , 8099,14 , 9665,35 , 9700,53 , 8099,14 , 55,5 , 52,5 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 3704,7 , 3903,8 , 2, 1, 1, 6, 7 }, // Spanish/Latin/CanaryIslands + { 111, 7, 238, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 625,7 , 625,7 , 287,6 , 640,27 , 55,4 , 426,11 , 17973,61 , 18034,89 , 18123,24 , 17973,61 , 18034,89 , 18123,24 , 9665,35 , 9700,53 , 8099,14 , 9665,35 , 9700,53 , 8099,14 , 55,5 , 52,5 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 3704,7 , 3903,8 , 2, 1, 1, 6, 7 }, // Spanish/Latin/Canary Islands { 111, 7, 246, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 625,7 , 625,7 , 287,6 , 640,27 , 37,5 , 8,10 , 18147,60 , 18034,89 , 18123,24 , 18147,60 , 18034,89 , 18123,24 , 9665,35 , 9700,53 , 3150,14 , 9665,35 , 9700,53 , 9753,14 , 66,4 , 63,4 , 0,5 , 5,17 , 22,23 , {0,0,0}, 0,0 , 2586,0 , 4,4 , 4,0 , 3911,23 , 3934,13 , 2, 1, 1, 6, 7 }, // Spanish/Latin/Latin America - { 111, 7, 250, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 625,7 , 625,7 , 287,6 , 640,27 , 55,4 , 426,11 , 17973,61 , 18034,89 , 18123,24 , 17973,61 , 18034,89 , 18123,24 , 9665,35 , 9700,53 , 8099,14 , 9665,35 , 9700,53 , 8099,14 , 55,5 , 52,5 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 3704,7 , 3947,15 , 2, 1, 1, 6, 7 }, // Spanish/Latin/CeutaAndMelilla + { 111, 7, 250, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 625,7 , 625,7 , 287,6 , 640,27 , 55,4 , 426,11 , 17973,61 , 18034,89 , 18123,24 , 17973,61 , 18034,89 , 18123,24 , 9665,35 , 9700,53 , 8099,14 , 9665,35 , 9700,53 , 8099,14 , 55,5 , 52,5 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3102,20 , 13,5 , 4,0 , 3704,7 , 3947,15 , 2, 1, 1, 6, 7 }, // Spanish/Latin/Ceuta And Melilla { 113, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 632,8 , 632,8 , 120,10 , 10,17 , 37,5 , 8,10 , 18463,48 , 18511,84 , 134,24 , 18463,48 , 18511,84 , 134,24 , 9767,60 , 9767,60 , 85,14 , 9767,60 , 9767,60 , 85,14 , 0,2 , 0,2 , 591,5 , 811,47 , 22,23 , {84,90,83}, 188,3 , 13426,67 , 4,4 , 4,0 , 3962,9 , 1616,8 , 0, 0, 1, 6, 7 }, // Swahili/Latin/Tanzania - { 113, 7, 49, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 632,8 , 632,8 , 120,10 , 10,17 , 37,5 , 8,10 , 18463,48 , 18511,84 , 134,24 , 18463,48 , 18511,84 , 134,24 , 9767,60 , 9767,60 , 85,14 , 9767,60 , 9767,60 , 85,14 , 0,2 , 0,2 , 591,5 , 811,47 , 22,23 , {67,68,70}, 203,2 , 13493,55 , 4,4 , 4,0 , 3971,8 , 3979,32 , 2, 1, 1, 6, 7 }, // Swahili/Latin/CongoKinshasa + { 113, 7, 49, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 632,8 , 632,8 , 120,10 , 10,17 , 37,5 , 8,10 , 18463,48 , 18511,84 , 134,24 , 18463,48 , 18511,84 , 134,24 , 9767,60 , 9767,60 , 85,14 , 9767,60 , 9767,60 , 85,14 , 0,2 , 0,2 , 591,5 , 811,47 , 22,23 , {67,68,70}, 203,2 , 13493,55 , 4,4 , 4,0 , 3971,8 , 3979,32 , 2, 1, 1, 6, 7 }, // Swahili/Latin/Congo Kinshasa { 113, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 632,8 , 632,8 , 120,10 , 10,17 , 37,5 , 8,10 , 18463,48 , 18511,84 , 134,24 , 18463,48 , 18511,84 , 134,24 , 9767,60 , 9767,60 , 85,14 , 9767,60 , 9767,60 , 85,14 , 0,2 , 0,2 , 591,5 , 811,47 , 22,23 , {75,69,83}, 2,3 , 13548,58 , 4,4 , 4,0 , 3962,9 , 1182,5 , 2, 1, 7, 6, 7 }, // Swahili/Latin/Kenya { 113, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 632,8 , 632,8 , 120,10 , 10,17 , 37,5 , 8,10 , 18463,48 , 18511,84 , 134,24 , 18463,48 , 18511,84 , 134,24 , 9767,60 , 9767,60 , 85,14 , 9767,60 , 9767,60 , 85,14 , 0,2 , 0,2 , 591,5 , 811,47 , 22,23 , {85,71,88}, 193,3 , 13606,61 , 4,4 , 4,0 , 3962,9 , 1681,6 , 0, 0, 1, 6, 7 }, // Swahili/Latin/Uganda { 114, 7, 205, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 640,9 , 640,9 , 53,10 , 98,16 , 37,5 , 437,16 , 18595,59 , 18654,86 , 134,24 , 18595,59 , 18654,86 , 134,24 , 9827,29 , 9856,50 , 2363,14 , 9827,29 , 9856,50 , 2363,14 , 299,2 , 267,2 , 45,4 , 5,17 , 22,23 , {83,69,75}, 186,2 , 13667,45 , 13,5 , 4,0 , 4011,7 , 4018,7 , 2, 0, 1, 6, 7 }, // Swedish/Latin/Sweden { 114, 7, 73, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 640,9 , 640,9 , 1181,10 , 98,16 , 37,5 , 437,16 , 18595,59 , 18654,86 , 134,24 , 18595,59 , 18654,86 , 134,24 , 9827,29 , 9856,50 , 2363,14 , 9827,29 , 9856,50 , 2363,14 , 299,2 , 267,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8897,19 , 13,5 , 4,0 , 4011,7 , 1079,7 , 2, 1, 1, 6, 7 }, // Swedish/Latin/Finland - { 114, 7, 248, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 640,9 , 640,9 , 53,10 , 98,16 , 37,5 , 437,16 , 18595,59 , 18654,86 , 134,24 , 18595,59 , 18654,86 , 134,24 , 9827,29 , 9856,50 , 2363,14 , 9827,29 , 9856,50 , 2363,14 , 299,2 , 267,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8897,19 , 13,5 , 4,0 , 4011,7 , 4025,5 , 2, 1, 1, 6, 7 }, // Swedish/Latin/AlandIslands + { 114, 7, 248, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 640,9 , 640,9 , 53,10 , 98,16 , 37,5 , 437,16 , 18595,59 , 18654,86 , 134,24 , 18595,59 , 18654,86 , 134,24 , 9827,29 , 9856,50 , 2363,14 , 9827,29 , 9856,50 , 2363,14 , 299,2 , 267,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8897,19 , 13,5 , 4,0 , 4011,7 , 4025,5 , 2, 1, 1, 6, 7 }, // Swedish/Latin/Aland Islands { 116, 2, 209, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 80,18 , 37,5 , 8,10 , 11024,48 , 18740,71 , 11152,24 , 11024,48 , 18740,71 , 11152,24 , 9906,28 , 9934,55 , 9989,14 , 9906,28 , 9934,55 , 9989,14 , 301,7 , 269,7 , 45,4 , 5,17 , 22,23 , {84,74,83}, 311,4 , 13712,19 , 13,5 , 4,0 , 4030,6 , 4036,10 , 2, 1, 1, 6, 7 }, // Tajik/Cyrillic/Tajikistan { 117, 27, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 649,13 , 649,13 , 287,6 , 210,18 , 382,7 , 453,12 , 18811,58 , 18869,86 , 18955,31 , 18811,58 , 18869,86 , 18955,31 , 10003,39 , 10042,49 , 10091,20 , 10003,39 , 10042,49 , 10091,20 , 308,8 , 276,8 , 858,7 , 5,17 , 22,23 , {73,78,82}, 117,1 , 13731,49 , 8,5 , 4,0 , 4046,5 , 4051,7 , 2, 1, 7, 7, 7 }, // Tamil/Tamil/India { 117, 27, 130, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 649,13 , 649,13 , 287,6 , 210,18 , 382,7 , 453,12 , 18811,58 , 18869,86 , 18955,31 , 18811,58 , 18869,86 , 18955,31 , 10003,39 , 10042,49 , 10091,20 , 10003,39 , 10042,49 , 10091,20 , 308,8 , 276,8 , 858,7 , 5,17 , 22,23 , {77,89,82}, 170,2 , 13780,61 , 8,5 , 4,0 , 4046,5 , 4058,7 , 2, 1, 1, 6, 7 }, // Tamil/Tamil/Malaysia { 117, 27, 190, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 649,13 , 649,13 , 287,6 , 210,18 , 382,7 , 453,12 , 18811,58 , 18869,86 , 18955,31 , 18811,58 , 18869,86 , 18955,31 , 10003,39 , 10042,49 , 10091,20 , 10003,39 , 10042,49 , 10091,20 , 308,8 , 276,8 , 858,7 , 5,17 , 22,23 , {83,71,68}, 6,1 , 13841,61 , 8,5 , 4,0 , 4046,5 , 4065,11 , 2, 1, 7, 6, 7 }, // Tamil/Tamil/Singapore - { 117, 27, 198, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 649,13 , 649,13 , 287,6 , 210,18 , 37,5 , 8,10 , 18811,58 , 18869,86 , 18955,31 , 18811,58 , 18869,86 , 18955,31 , 10003,39 , 10042,49 , 10091,20 , 10003,39 , 10042,49 , 10091,20 , 308,8 , 276,8 , 858,7 , 5,17 , 22,23 , {76,75,82}, 315,3 , 13902,49 , 8,5 , 4,0 , 4046,5 , 4076,6 , 2, 1, 1, 6, 7 }, // Tamil/Tamil/SriLanka + { 117, 27, 198, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 649,13 , 649,13 , 287,6 , 210,18 , 37,5 , 8,10 , 18811,58 , 18869,86 , 18955,31 , 18811,58 , 18869,86 , 18955,31 , 10003,39 , 10042,49 , 10091,20 , 10003,39 , 10042,49 , 10091,20 , 308,8 , 276,8 , 858,7 , 5,17 , 22,23 , {76,75,82}, 315,3 , 13902,49 , 8,5 , 4,0 , 4046,5 , 4076,6 , 2, 1, 1, 6, 7 }, // Tamil/Tamil/Sri Lanka { 118, 2, 178, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 662,9 , 662,9 , 981,10 , 1191,23 , 55,4 , 59,9 , 18986,62 , 19048,81 , 158,27 , 18986,62 , 19048,81 , 158,27 , 10111,36 , 10147,56 , 10203,14 , 10111,36 , 10147,56 , 10203,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {82,85,66}, 119,1 , 13951,21 , 0,4 , 4,0 , 4082,5 , 3415,6 , 2, 1, 1, 6, 7 }, // Tatar/Cyrillic/Russia { 119, 28, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 671,11 , 671,11 , 357,8 , 1214,18 , 18,7 , 25,12 , 19129,62 , 19191,86 , 19277,31 , 19129,62 , 19191,86 , 19277,31 , 10217,32 , 10249,60 , 10309,18 , 10217,32 , 10249,60 , 10309,18 , 0,2 , 0,2 , 865,7 , 872,27 , 22,23 , {73,78,82}, 117,1 , 13972,26 , 4,4 , 4,0 , 4087,6 , 4093,8 , 2, 1, 7, 7, 7 }, // Telugu/Telugu/India { 120, 30, 211, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 123,5 , 123,5 , 682,8 , 690,7 , 287,6 , 1232,19 , 37,5 , 465,28 , 19308,63 , 19371,98 , 19308,63 , 19308,63 , 19371,98 , 19308,63 , 10327,23 , 10350,68 , 10418,16 , 10327,23 , 10350,68 , 10418,16 , 316,10 , 284,10 , 899,4 , 5,17 , 22,23 , {84,72,66}, 318,3 , 13998,16 , 4,4 , 4,0 , 4101,3 , 4101,3 , 2, 1, 7, 6, 7 }, // Thai/Thai/Thailand @@ -1661,7 +1661,7 @@ static const QLocaleData locale_data[] = { { 122, 14, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1274,23 , 18,7 , 25,12 , 19775,36 , 19811,54 , 19865,24 , 19775,36 , 19811,54 , 19865,24 , 10591,21 , 10612,29 , 10641,14 , 10591,21 , 10655,29 , 10684,14 , 333,7 , 302,7 , 45,4 , 5,17 , 22,23 , {69,84,66}, 0,2 , 14046,16 , 4,4 , 4,0 , 4125,4 , 82,5 , 2, 1, 7, 6, 7 }, // Tigrinya/Ethiopic/Ethiopia { 122, 14, 67, 46, 44, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1274,23 , 18,7 , 25,12 , 19775,36 , 19811,54 , 19865,24 , 19775,36 , 19811,54 , 19865,24 , 10591,21 , 10612,29 , 10684,14 , 10591,21 , 10655,29 , 10684,14 , 333,7 , 302,7 , 45,4 , 5,17 , 22,23 , {69,82,78}, 41,3 , 0,7 , 4,4 , 4,0 , 4125,4 , 4129,4 , 2, 1, 1, 6, 7 }, // Tigrinya/Ethiopic/Eritrea { 123, 7, 214, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 697,8 , 697,8 , 697,8 , 697,8 , 287,6 , 98,16 , 18,7 , 25,12 , 19889,51 , 19940,87 , 20027,24 , 19889,51 , 19940,87 , 20027,24 , 10698,29 , 10727,60 , 10787,14 , 10698,29 , 10727,60 , 10787,14 , 340,10 , 309,6 , 903,5 , 908,59 , 967,65 , {84,79,80}, 191,2 , 14062,41 , 13,5 , 4,0 , 4133,13 , 1631,5 , 2, 1, 1, 6, 7 }, // Tongan/Latin/Tonga - { 124, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Tsonga/Latin/SouthAfrica + { 124, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Tsonga/Latin/South Africa { 125, 7, 217, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 705,8 , 705,8 , 1297,9 , 1306,16 , 37,5 , 8,10 , 20051,48 , 20099,75 , 20174,24 , 20051,48 , 20099,75 , 20174,24 , 10801,28 , 10829,54 , 10883,14 , 10801,28 , 10829,54 , 10883,14 , 350,2 , 315,2 , 193,4 , 5,17 , 22,23 , {84,82,89}, 244,1 , 14103,40 , 4,4 , 4,0 , 4146,6 , 4152,7 , 2, 1, 1, 6, 7 }, // Turkish/Latin/Turkey { 125, 7, 56, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 705,8 , 705,8 , 1297,9 , 1306,16 , 18,7 , 25,12 , 20051,48 , 20099,75 , 20174,24 , 20051,48 , 20099,75 , 20174,24 , 10801,28 , 10829,54 , 10883,14 , 10801,28 , 10829,54 , 10883,14 , 350,2 , 315,2 , 193,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8384,19 , 4,4 , 4,0 , 4146,6 , 4159,6 , 2, 1, 1, 6, 7 }, // Turkish/Latin/Cyprus { 126, 7, 218, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8220, 8221, 0,6 , 0,6 , 713,8 , 713,8 , 981,10 , 1306,16 , 37,5 , 8,10 , 20198,51 , 20249,77 , 20326,24 , 20350,51 , 20401,77 , 20326,24 , 10897,28 , 10925,54 , 10979,14 , 10993,28 , 11021,54 , 10979,14 , 352,13 , 317,14 , 1032,4 , 5,17 , 22,23 , {84,77,84}, 322,3 , 14143,49 , 13,5 , 4,0 , 4165,12 , 4177,12 , 2, 1, 1, 6, 7 }, // Turkmen/Latin/Turkmenistan @@ -1674,19 +1674,19 @@ static const QLocaleData locale_data[] = { { 131, 2, 228, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 667,19 , 37,5 , 87,12 , 11024,48 , 18740,71 , 11152,24 , 21292,48 , 21340,71 , 11152,24 , 11399,28 , 11427,53 , 11480,14 , 11494,28 , 11522,53 , 11480,14 , 381,2 , 347,2 , 45,4 , 5,17 , 22,23 , {85,90,83}, 329,3 , 14443,49 , 13,5 , 4,0 , 4251,7 , 4258,10 , 0, 0, 1, 6, 7 }, // Uzbek/Cyrillic/Uzbekistan { 132, 7, 232, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 754,8 , 754,8 , 120,10 , 210,18 , 37,5 , 8,10 , 21411,75 , 21486,99 , 158,27 , 21585,75 , 21660,99 , 158,27 , 11575,33 , 11608,55 , 11663,21 , 11575,33 , 11608,55 , 11663,21 , 383,2 , 349,2 , 45,4 , 5,17 , 22,23 , {86,78,68}, 332,1 , 14492,33 , 13,5 , 4,0 , 4268,10 , 4278,8 , 0, 0, 1, 6, 7 }, // Vietnamese/Latin/Vietnam { 133, 7, 260, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 1430,23 , 37,5 , 8,10 , 21759,48 , 21807,74 , 21881,24 , 21905,48 , 21807,74 , 21881,24 , 11684,21 , 11705,43 , 11748,14 , 11762,28 , 11705,43 , 11748,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {0,0,0}, 0,0 , 2586,0 , 8,5 , 4,0 , 4286,7 , 0,0 , 2, 1, 1, 6, 7 }, // Volapuk/Latin/World - { 134, 7, 224, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 762,11 , 773,10 , 27,8 , 10,17 , 37,5 , 8,10 , 21953,52 , 22005,87 , 22092,26 , 22118,59 , 22005,87 , 22092,26 , 11790,29 , 11819,77 , 11896,15 , 11911,30 , 11819,77 , 11896,15 , 385,2 , 351,2 , 1045,7 , 5,17 , 22,23 , {71,66,80}, 115,1 , 14525,92 , 4,4 , 4,0 , 4293,7 , 4300,16 , 2, 1, 1, 6, 7 }, // Welsh/Latin/UnitedKingdom + { 134, 7, 224, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 762,11 , 773,10 , 27,8 , 10,17 , 37,5 , 8,10 , 21953,52 , 22005,87 , 22092,26 , 22118,59 , 22005,87 , 22092,26 , 11790,29 , 11819,77 , 11896,15 , 11911,30 , 11819,77 , 11896,15 , 385,2 , 351,2 , 1045,7 , 5,17 , 22,23 , {71,66,80}, 115,1 , 14525,92 , 4,4 , 4,0 , 4293,7 , 4300,16 , 2, 1, 1, 6, 7 }, // Welsh/Latin/United Kingdom { 135, 7, 187, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 1181,10 , 1453,17 , 37,5 , 8,10 , 22177,47 , 22224,84 , 158,27 , 22177,47 , 22224,84 , 158,27 , 11941,28 , 11969,50 , 11941,28 , 11941,28 , 11969,50 , 11941,28 , 387,3 , 353,3 , 45,4 , 5,17 , 22,23 , {88,79,70}, 200,3 , 14617,65 , 8,5 , 4,0 , 4316,5 , 4321,8 , 0, 0, 1, 6, 7 }, // Wolof/Latin/Senegal - { 136, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Xhosa/Latin/SouthAfrica + { 136, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Xhosa/Latin/South Africa { 137, 18, 260, 46, 44, 59, 37, 48, 45, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 783,9 , 783,9 , 27,8 , 1470,19 , 37,5 , 8,10 , 22308,58 , 22366,92 , 158,27 , 22366,92 , 22366,92 , 158,27 , 12019,54 , 12019,54 , 85,14 , 12019,54 , 12019,54 , 85,14 , 390,11 , 356,10 , 45,4 , 5,17 , 22,23 , {0,0,0}, 0,0 , 2586,0 , 41,6 , 4,0 , 4329,6 , 4335,5 , 2, 1, 1, 6, 7 }, // Yiddish/Hebrew/World { 138, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 22458,73 , 22531,121 , 158,27 , 22458,73 , 22531,121 , 158,27 , 12073,44 , 12117,69 , 85,14 , 12073,44 , 12117,69 , 85,14 , 401,5 , 366,5 , 45,4 , 5,17 , 22,23 , {78,71,78}, 174,1 , 14682,34 , 4,4 , 4,0 , 4340,10 , 4350,18 , 2, 1, 1, 6, 7 }, // Yoruba/Latin/Nigeria { 138, 7, 23, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 22652,74 , 22726,134 , 158,27 , 22652,74 , 22726,134 , 158,27 , 12186,44 , 12230,69 , 85,14 , 12186,44 , 12230,69 , 85,14 , 406,5 , 371,5 , 45,4 , 5,17 , 22,23 , {88,79,70}, 200,3 , 14716,34 , 4,4 , 4,0 , 4340,10 , 4368,16 , 0, 0, 1, 6, 7 }, // Yoruba/Latin/Benin - { 140, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 792,9 , 801,8 , 543,6 , 35,18 , 37,5 , 8,10 , 22860,48 , 22908,91 , 134,24 , 22860,48 , 22908,91 , 22999,24 , 12299,28 , 12327,74 , 12401,14 , 12299,28 , 12327,74 , 12401,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {90,65,82}, 5,1 , 14750,67 , 4,4 , 4,0 , 4384,7 , 4391,17 , 2, 1, 7, 6, 7 }, // Zulu/Latin/SouthAfrica - { 141, 7, 161, 44, 160, 59, 37, 48, 8722, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 192,8 , 192,8 , 981,10 , 496,17 , 37,5 , 437,16 , 5904,48 , 13926,83 , 134,24 , 23023,59 , 13926,83 , 134,24 , 12415,28 , 12443,51 , 2363,14 , 12494,28 , 12443,51 , 2363,14 , 411,9 , 376,11 , 45,4 , 5,17 , 22,23 , {78,79,75}, 186,2 , 9799,44 , 13,5 , 4,0 , 4408,7 , 4415,5 , 2, 0, 1, 6, 7 }, // NorwegianNynorsk/Latin/Norway - { 142, 7, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8221, 8216, 8217, 0,6 , 0,6 , 163,7 , 163,7 , 1039,7 , 468,19 , 37,5 , 8,10 , 16459,48 , 23082,83 , 16435,24 , 16459,48 , 23082,83 , 16435,24 , 2086,28 , 2114,58 , 2172,14 , 2086,28 , 2114,58 , 2186,14 , 420,10 , 387,7 , 313,7 , 5,17 , 22,23 , {66,65,77}, 140,2 , 14817,170 , 13,5 , 4,0 , 4420,8 , 620,19 , 2, 1, 1, 6, 7 }, // Bosnian/Latin/BosniaAndHerzegowina - { 142, 2, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 116,7 , 116,7 , 1039,7 , 1046,20 , 37,5 , 8,10 , 23165,48 , 23213,83 , 12531,24 , 23165,48 , 23213,83 , 12531,24 , 12522,28 , 12550,56 , 8617,14 , 12522,28 , 12550,56 , 8617,14 , 225,9 , 394,7 , 45,4 , 5,17 , 22,23 , {66,65,77}, 290,2 , 14987,151 , 13,5 , 4,0 , 4428,8 , 3512,19 , 2, 1, 1, 6, 7 }, // Bosnian/Cyrillic/BosniaAndHerzegowina + { 140, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 792,9 , 801,8 , 543,6 , 35,18 , 37,5 , 8,10 , 22860,48 , 22908,91 , 134,24 , 22860,48 , 22908,91 , 22999,24 , 12299,28 , 12327,74 , 12401,14 , 12299,28 , 12327,74 , 12401,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {90,65,82}, 5,1 , 14750,67 , 4,4 , 4,0 , 4384,7 , 4391,17 , 2, 1, 7, 6, 7 }, // Zulu/Latin/South Africa + { 141, 7, 161, 44, 160, 59, 37, 48, 8722, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 192,8 , 192,8 , 981,10 , 496,17 , 37,5 , 437,16 , 5904,48 , 13926,83 , 134,24 , 23023,59 , 13926,83 , 134,24 , 12415,28 , 12443,51 , 2363,14 , 12494,28 , 12443,51 , 2363,14 , 411,9 , 376,11 , 45,4 , 5,17 , 22,23 , {78,79,75}, 186,2 , 9799,44 , 13,5 , 4,0 , 4408,7 , 4415,5 , 2, 0, 1, 6, 7 }, // Norwegian Nynorsk/Latin/Norway + { 142, 7, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8221, 8216, 8217, 0,6 , 0,6 , 163,7 , 163,7 , 1039,7 , 468,19 , 37,5 , 8,10 , 16459,48 , 23082,83 , 16435,24 , 16459,48 , 23082,83 , 16435,24 , 2086,28 , 2114,58 , 2172,14 , 2086,28 , 2114,58 , 2186,14 , 420,10 , 387,7 , 313,7 , 5,17 , 22,23 , {66,65,77}, 140,2 , 14817,170 , 13,5 , 4,0 , 4420,8 , 620,19 , 2, 1, 1, 6, 7 }, // Bosnian/Latin/Bosnia And Herzegowina + { 142, 2, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 116,7 , 116,7 , 1039,7 , 1046,20 , 37,5 , 8,10 , 23165,48 , 23213,83 , 12531,24 , 23165,48 , 23213,83 , 12531,24 , 12522,28 , 12550,56 , 8617,14 , 12522,28 , 12550,56 , 8617,14 , 225,9 , 394,7 , 45,4 , 5,17 , 22,23 , {66,65,77}, 290,2 , 14987,151 , 13,5 , 4,0 , 4428,8 , 3512,19 , 2, 1, 1, 6, 7 }, // Bosnian/Cyrillic/Bosnia And Herzegowina { 143, 29, 131, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {77,86,82}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 5, 6, 7 }, // Divehi/Thaana/Maldives - { 144, 7, 251, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 686,17 , 37,5 , 8,10 , 23296,102 , 23398,140 , 158,27 , 23296,102 , 23398,140 , 158,27 , 12606,30 , 12636,57 , 85,14 , 12606,30 , 12636,57 , 85,14 , 66,4 , 63,4 , 45,4 , 5,17 , 22,23 , {71,66,80}, 115,1 , 0,7 , 4,4 , 4,0 , 4436,5 , 4441,12 , 2, 1, 1, 6, 7 }, // Manx/Latin/IsleOfMan - { 145, 7, 224, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 98,16 , 37,5 , 8,10 , 23538,46 , 23584,130 , 158,27 , 23538,46 , 23584,130 , 158,27 , 12693,28 , 12721,61 , 85,14 , 12693,28 , 12721,61 , 85,14 , 66,4 , 63,4 , 45,4 , 5,17 , 22,23 , {71,66,80}, 115,1 , 0,7 , 4,4 , 4,0 , 4453,8 , 4461,14 , 2, 1, 1, 6, 7 }, // Cornish/Latin/UnitedKingdom + { 144, 7, 251, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 686,17 , 37,5 , 8,10 , 23296,102 , 23398,140 , 158,27 , 23296,102 , 23398,140 , 158,27 , 12606,30 , 12636,57 , 85,14 , 12606,30 , 12636,57 , 85,14 , 66,4 , 63,4 , 45,4 , 5,17 , 22,23 , {71,66,80}, 115,1 , 0,7 , 4,4 , 4,0 , 4436,5 , 4441,12 , 2, 1, 1, 6, 7 }, // Manx/Latin/Isle Of Man + { 145, 7, 224, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 98,16 , 37,5 , 8,10 , 23538,46 , 23584,130 , 158,27 , 23538,46 , 23584,130 , 158,27 , 12693,28 , 12721,61 , 85,14 , 12693,28 , 12721,61 , 85,14 , 66,4 , 63,4 , 45,4 , 5,17 , 22,23 , {71,66,80}, 115,1 , 0,7 , 4,4 , 4,0 , 4453,8 , 4461,14 , 2, 1, 1, 6, 7 }, // Cornish/Latin/United Kingdom { 146, 7, 83, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 1489,8 , 1497,18 , 18,7 , 25,12 , 23714,48 , 23762,192 , 158,27 , 23714,48 , 23762,192 , 158,27 , 12782,28 , 12810,49 , 12859,14 , 12782,28 , 12810,49 , 12859,14 , 430,2 , 401,2 , 45,4 , 5,17 , 22,23 , {71,72,83}, 163,3 , 15138,17 , 4,4 , 4,0 , 4475,4 , 4479,5 , 2, 1, 1, 6, 7 }, // Akan/Latin/Ghana { 147, 13, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 1515,6 , 98,16 , 18,7 , 25,12 , 23954,88 , 23954,88 , 158,27 , 23954,88 , 23954,88 , 158,27 , 12873,49 , 12873,49 , 12922,20 , 12873,49 , 12873,49 , 12922,20 , 188,5 , 403,5 , 45,4 , 5,17 , 22,23 , {73,78,82}, 117,1 , 15155,13 , 8,5 , 4,0 , 4484,6 , 2633,4 , 2, 1, 7, 7, 7 }, // Konkani/Devanagari/India { 148, 7, 83, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {71,72,83}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Ga/Latin/Ghana @@ -1700,11 +1700,11 @@ static const QLocaleData locale_data[] = { { 157, 14, 67, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,82,78}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Tigre/Ethiopic/Eritrea { 158, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {78,71,78}, 174,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Jju/Latin/Nigeria { 159, 7, 106, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 254,7 , 254,7 , 27,8 , 1521,27 , 37,5 , 8,10 , 24437,48 , 24485,77 , 24562,24 , 24437,48 , 24485,77 , 24562,24 , 13144,28 , 13172,50 , 3150,14 , 13144,28 , 13172,50 , 3150,14 , 441,2 , 419,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3102,20 , 8,5 , 4,0 , 4509,6 , 4515,6 , 2, 1, 1, 6, 7 }, // Friulian/Latin/Italy - { 160, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Venda/Latin/SouthAfrica + { 160, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Venda/Latin/South Africa { 161, 7, 83, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 809,11 , 820,10 , 543,6 , 1548,23 , 493,12 , 505,17 , 24586,48 , 24634,87 , 24721,24 , 24586,48 , 24634,87 , 24721,24 , 13222,28 , 13250,44 , 13294,14 , 13222,28 , 13250,44 , 13294,14 , 443,3 , 421,5 , 45,4 , 5,17 , 22,23 , {71,72,83}, 163,3 , 15203,37 , 4,4 , 4,0 , 4521,6 , 4527,12 , 2, 1, 1, 6, 7 }, // Ewe/Latin/Ghana { 161, 7, 212, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 809,11 , 820,10 , 543,6 , 1548,23 , 37,5 , 8,10 , 24586,48 , 24634,87 , 24721,24 , 24586,48 , 24634,87 , 24721,24 , 13222,28 , 13250,44 , 13294,14 , 13222,28 , 13250,44 , 13294,14 , 443,3 , 421,5 , 45,4 , 5,17 , 22,23 , {88,79,70}, 200,3 , 15240,106 , 4,4 , 4,0 , 4521,6 , 4539,11 , 0, 0, 1, 6, 7 }, // Ewe/Latin/Togo { 162, 14, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,84,66}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Walamo/Ethiopic/Ethiopia - { 163, 7, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 287,6 , 10,17 , 18,7 , 25,12 , 24745,59 , 24804,95 , 158,27 , 24745,59 , 24804,95 , 158,27 , 13308,21 , 13329,57 , 85,14 , 13308,21 , 13329,57 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,83,68}, 6,1 , 0,7 , 4,4 , 4,0 , 4550,14 , 4564,19 , 2, 1, 7, 6, 7 }, // Hawaiian/Latin/UnitedStates + { 163, 7, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 287,6 , 10,17 , 18,7 , 25,12 , 24745,59 , 24804,95 , 158,27 , 24745,59 , 24804,95 , 158,27 , 13308,21 , 13329,57 , 85,14 , 13308,21 , 13329,57 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,83,68}, 6,1 , 0,7 , 4,4 , 4,0 , 4550,14 , 4564,19 , 2, 1, 7, 6, 7 }, // Hawaiian/Latin/United States { 164, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {78,71,78}, 174,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Tyap/Latin/Nigeria { 165, 7, 129, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {77,87,75}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Nyanja/Latin/Malawi { 166, 7, 170, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 830,9 , 839,8 , 543,6 , 35,18 , 18,7 , 25,12 , 24899,48 , 24947,88 , 25035,38 , 24899,48 , 24947,88 , 24899,48 , 13386,28 , 13414,55 , 13386,28 , 13386,28 , 13414,55 , 13386,28 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {80,72,80}, 175,1 , 15346,58 , 4,4 , 4,0 , 4583,8 , 4591,9 , 2, 1, 7, 6, 7 }, // Filipino/Latin/Philippines @@ -1715,8 +1715,8 @@ static const QLocaleData locale_data[] = { { 169, 7, 121, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {76,82,68}, 6,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Kpelle/Latin/Liberia { 170, 7, 82, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 427,8 , 427,8 , 383,7 , 1571,23 , 522,10 , 532,19 , 7980,59 , 25197,85 , 134,24 , 7980,59 , 25197,85 , 134,24 , 13623,28 , 13651,65 , 3738,14 , 13623,28 , 13651,65 , 3738,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 15459,15 , 13,5 , 4,0 , 4651,14 , 4665,11 , 2, 1, 1, 6, 7 }, // Low German/Latin/Germany { 170, 7, 151, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 427,8 , 427,8 , 383,7 , 1571,23 , 522,10 , 532,19 , 7980,59 , 25197,85 , 134,24 , 7980,59 , 25197,85 , 134,24 , 13623,28 , 13651,65 , 3738,14 , 13623,28 , 13651,65 , 3738,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 15459,15 , 13,5 , 4,0 , 4651,14 , 4676,12 , 2, 1, 1, 6, 7 }, // Low German/Latin/Netherlands - { 171, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // South Ndebele/Latin/SouthAfrica - { 172, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Northern Sotho/Latin/SouthAfrica + { 171, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // South Ndebele/Latin/South Africa + { 172, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Northern Sotho/Latin/South Africa { 173, 7, 161, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 228,8 , 228,8 , 53,10 , 63,17 , 37,5 , 8,10 , 25282,59 , 25341,145 , 25486,24 , 25282,59 , 25341,145 , 25486,24 , 13716,33 , 13749,75 , 13824,14 , 13716,33 , 13749,75 , 13824,14 , 460,11 , 439,13 , 45,4 , 5,17 , 22,23 , {78,79,75}, 186,2 , 15474,63 , 13,5 , 4,0 , 4688,15 , 4703,5 , 2, 0, 1, 6, 7 }, // Northern Sami/Latin/Norway { 173, 7, 73, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 228,8 , 228,8 , 981,10 , 98,16 , 37,5 , 8,10 , 25510,60 , 25341,145 , 25486,24 , 25510,60 , 25341,145 , 25486,24 , 13838,21 , 13859,70 , 13929,14 , 13838,21 , 13859,70 , 13929,14 , 471,2 , 452,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 15537,23 , 13,5 , 4,0 , 4688,15 , 4708,6 , 2, 1, 1, 6, 7 }, // Northern Sami/Latin/Finland { 173, 7, 205, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 228,8 , 228,8 , 53,10 , 63,17 , 37,5 , 8,10 , 25282,59 , 25341,145 , 25486,24 , 25282,59 , 25341,145 , 25486,24 , 13716,33 , 13749,75 , 13824,14 , 13716,33 , 13749,75 , 13824,14 , 460,11 , 439,13 , 45,4 , 5,17 , 22,23 , {83,69,75}, 186,2 , 15560,63 , 13,5 , 4,0 , 4688,15 , 4714,6 , 2, 0, 1, 6, 7 }, // Northern Sami/Latin/Sweden @@ -1741,13 +1741,13 @@ static const QLocaleData locale_data[] = { { 188, 7, 132, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 433,8 , 98,16 , 37,5 , 8,10 , 28484,47 , 28531,92 , 28623,24 , 28484,47 , 28531,92 , 28623,24 , 15514,28 , 15542,44 , 15586,14 , 15514,28 , 15542,44 , 15586,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,79,70}, 200,3 , 16022,24 , 4,4 , 4,0 , 4878,9 , 2155,4 , 0, 0, 1, 6, 7 }, // Bambara/Latin/Mali { 188, 75, 132, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,79,70}, 200,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Bambara/Nko/Mali { 189, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 28647,48 , 28695,207 , 28902,24 , 28647,48 , 28695,207 , 28902,24 , 15600,28 , 15628,64 , 15692,14 , 15600,28 , 15628,64 , 15692,14 , 547,2 , 535,2 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 15623,24 , 4,4 , 4,0 , 4887,6 , 1182,5 , 2, 1, 7, 6, 7 }, // Embu/Latin/Kenya - { 190, 12, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 870,8 , 870,8 , 543,6 , 35,18 , 18,7 , 25,12 , 28926,36 , 28962,58 , 29020,24 , 28926,36 , 28962,58 , 29020,24 , 15706,28 , 15734,49 , 15783,14 , 15706,28 , 15734,49 , 15783,14 , 549,3 , 537,6 , 1111,6 , 5,17 , 22,23 , {85,83,68}, 6,1 , 16046,25 , 4,4 , 4,0 , 4893,3 , 4896,15 , 2, 1, 7, 6, 7 }, // Cherokee/Cherokee/UnitedStates + { 190, 12, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 870,8 , 870,8 , 543,6 , 35,18 , 18,7 , 25,12 , 28926,36 , 28962,58 , 29020,24 , 28926,36 , 28962,58 , 29020,24 , 15706,28 , 15734,49 , 15783,14 , 15706,28 , 15734,49 , 15783,14 , 549,3 , 537,6 , 1111,6 , 5,17 , 22,23 , {85,83,68}, 6,1 , 16046,25 , 4,4 , 4,0 , 4893,3 , 4896,15 , 2, 1, 7, 6, 7 }, // Cherokee/Cherokee/United States { 191, 7, 137, 46, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 433,8 , 98,16 , 37,5 , 8,10 , 29044,47 , 29091,68 , 29159,24 , 29044,47 , 29091,68 , 29159,24 , 15797,27 , 15824,48 , 15872,14 , 15797,27 , 15824,48 , 15872,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {77,85,82}, 172,2 , 16071,21 , 41,6 , 4,0 , 4911,14 , 4925,5 , 0, 0, 1, 6, 7 }, // Morisyen/Latin/Mauritius { 192, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 18463,48 , 29183,264 , 134,24 , 18463,48 , 29183,264 , 134,24 , 15886,28 , 15914,133 , 14830,14 , 15886,28 , 15914,133 , 14830,14 , 552,4 , 543,5 , 45,4 , 5,17 , 22,23 , {84,90,83}, 188,3 , 15995,27 , 4,4 , 4,0 , 4930,10 , 1616,8 , 0, 0, 1, 6, 7 }, // Makonde/Latin/Tanzania { 193, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 29447,83 , 29530,111 , 29641,24 , 29447,83 , 29530,111 , 29641,24 , 16047,36 , 16083,63 , 16146,14 , 16047,36 , 16083,63 , 16146,14 , 556,3 , 548,3 , 45,4 , 5,17 , 22,23 , {84,90,83}, 188,3 , 16092,29 , 41,6 , 4,0 , 4940,8 , 4948,9 , 0, 0, 1, 6, 7 }, // Langi/Latin/Tanzania { 194, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 29665,48 , 29713,97 , 134,24 , 29665,48 , 29713,97 , 134,24 , 16160,28 , 16188,66 , 16254,14 , 16160,28 , 16188,66 , 16254,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,71,88}, 193,3 , 16121,26 , 0,4 , 4,0 , 4957,7 , 4964,7 , 0, 0, 1, 6, 7 }, // Ganda/Latin/Uganda { 195, 7, 239, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 18,7 , 25,12 , 29810,48 , 29858,83 , 29941,24 , 29810,48 , 29858,83 , 29941,24 , 16268,80 , 16268,80 , 85,14 , 16268,80 , 16268,80 , 85,14 , 559,8 , 551,7 , 45,4 , 5,17 , 22,23 , {90,77,87}, 127,1 , 0,7 , 4,4 , 4,0 , 4971,9 , 1785,6 , 2, 1, 1, 6, 7 }, // Bemba/Latin/Zambia - { 196, 7, 39, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 163,7 , 163,7 , 433,8 , 1594,27 , 37,5 , 8,10 , 29965,48 , 30013,85 , 134,24 , 29965,48 , 30013,85 , 134,24 , 16348,28 , 16376,73 , 16449,14 , 16348,28 , 16463,73 , 16449,14 , 70,2 , 67,2 , 45,4 , 340,17 , 22,23 , {67,86,69}, 271,1 , 16147,43 , 13,5 , 4,0 , 4980,12 , 4992,10 , 2, 1, 1, 6, 7 }, // Kabuverdianu/Latin/CapeVerde + { 196, 7, 39, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 163,7 , 163,7 , 433,8 , 1594,27 , 37,5 , 8,10 , 29965,48 , 30013,85 , 134,24 , 29965,48 , 30013,85 , 134,24 , 16348,28 , 16376,73 , 16449,14 , 16348,28 , 16463,73 , 16449,14 , 70,2 , 67,2 , 45,4 , 340,17 , 22,23 , {67,86,69}, 271,1 , 16147,43 , 13,5 , 4,0 , 4980,12 , 4992,10 , 2, 1, 1, 6, 7 }, // Kabuverdianu/Latin/Cape Verde { 197, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 30098,48 , 30146,86 , 30232,24 , 30098,48 , 30146,86 , 30232,24 , 16536,28 , 16564,51 , 16615,14 , 16536,28 , 16564,51 , 16615,14 , 567,2 , 558,2 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 15623,24 , 4,4 , 4,0 , 5002,6 , 1182,5 , 2, 1, 7, 6, 7 }, // Meru/Latin/Kenya { 198, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 30256,49 , 30305,121 , 30426,24 , 30256,49 , 30305,121 , 30426,24 , 16629,28 , 16657,53 , 16710,14 , 16629,28 , 16657,53 , 16710,14 , 569,6 , 560,10 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 16190,26 , 4,4 , 4,0 , 5008,8 , 5016,12 , 2, 1, 7, 6, 7 }, // Kalenjin/Latin/Kenya { 199, 7, 148, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 30450,136 , 134,24 , 0,48 , 30450,136 , 134,24 , 16724,23 , 16747,92 , 16839,14 , 16724,23 , 16747,92 , 16839,14 , 575,7 , 570,5 , 45,4 , 5,17 , 22,23 , {78,65,68}, 6,1 , 16216,22 , 4,4 , 4,0 , 5028,13 , 5041,8 , 2, 1, 1, 6, 7 }, // Nama/Latin/Namibia @@ -1772,20 +1772,20 @@ static const QLocaleData locale_data[] = { { 218, 2, 178, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 21292,48 , 11235,80 , 11152,24 , 21292,48 , 11235,80 , 11152,24 , 17949,25 , 17974,45 , 18019,17 , 17949,25 , 17974,45 , 17949,25 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {82,85,66}, 119,1 , 16513,43 , 13,5 , 4,0 , 5210,7 , 5217,5 , 2, 1, 1, 6, 7 }, // Chechen/Cyrillic/Russia { 219, 2, 178, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 878,8 , 878,8 , 955,10 , 1644,23 , 37,5 , 8,10 , 32002,65 , 32067,117 , 32184,30 , 32002,65 , 32214,117 , 32184,30 , 18036,37 , 18073,68 , 11221,14 , 18036,37 , 18073,68 , 11221,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {82,85,66}, 119,1 , 16556,44 , 13,5 , 4,0 , 5222,19 , 5241,7 , 2, 1, 1, 6, 7 }, // Church/Cyrillic/Russia { 220, 2, 178, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {82,85,66}, 119,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Chuvash/Cyrillic/Russia - { 230, 7, 49, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 433,8 , 98,16 , 37,5 , 8,10 , 32331,49 , 32380,99 , 32479,24 , 32331,49 , 32380,99 , 32479,24 , 18141,28 , 18169,50 , 18219,14 , 18141,28 , 18169,50 , 18219,14 , 656,5 , 649,6 , 45,4 , 5,17 , 22,23 , {67,68,70}, 203,2 , 16600,24 , 0,4 , 4,0 , 5248,8 , 5256,16 , 2, 1, 1, 6, 7 }, // LubaKatanga/Latin/CongoKinshasa + { 230, 7, 49, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 433,8 , 98,16 , 37,5 , 8,10 , 32331,49 , 32380,99 , 32479,24 , 32331,49 , 32380,99 , 32479,24 , 18141,28 , 18169,50 , 18219,14 , 18141,28 , 18169,50 , 18219,14 , 656,5 , 649,6 , 45,4 , 5,17 , 22,23 , {67,68,70}, 203,2 , 16600,24 , 0,4 , 4,0 , 5248,8 , 5256,16 , 2, 1, 1, 6, 7 }, // Luba Katanga/Latin/Congo Kinshasa { 231, 7, 125, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 886,10 , 886,10 , 174,8 , 593,18 , 37,5 , 8,10 , 32503,48 , 32551,85 , 134,24 , 32636,59 , 32551,85 , 134,24 , 18233,28 , 18261,65 , 3738,14 , 18326,35 , 18261,65 , 3738,14 , 661,5 , 655,8 , 452,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8384,19 , 13,5 , 4,0 , 5272,14 , 5286,10 , 2, 1, 1, 6, 7 }, // Luxembourgish/Latin/Luxembourg { 236, 7, 21, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Walloon/Latin/Belgium { 237, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 8218, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 433,8 , 98,16 , 37,5 , 8,10 , 32695,48 , 32743,195 , 32938,24 , 32695,48 , 32743,195 , 32938,24 , 18361,28 , 18389,72 , 18461,14 , 18361,28 , 18389,72 , 18461,14 , 666,3 , 663,3 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16624,21 , 0,4 , 4,0 , 5296,5 , 5301,7 , 0, 0, 1, 6, 7 }, // Aghem/Latin/Cameroon { 238, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 0,6 , 0,6 , 433,8 , 98,16 , 37,5 , 8,10 , 32962,48 , 33010,90 , 33100,24 , 32962,48 , 33010,90 , 33100,24 , 18475,28 , 18503,70 , 18573,14 , 18475,28 , 18503,70 , 18573,14 , 669,10 , 666,9 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16645,22 , 13,5 , 4,0 , 5308,5 , 5313,8 , 0, 0, 1, 6, 7 }, // Basaa/Latin/Cameroon { 239, 7, 156, 46, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 433,8 , 98,16 , 37,5 , 8,10 , 31225,46 , 31271,88 , 31359,24 , 31225,46 , 31271,88 , 31359,24 , 17656,28 , 18587,53 , 18640,14 , 17656,28 , 18587,53 , 18640,14 , 679,8 , 675,10 , 45,4 , 5,17 , 22,23 , {88,79,70}, 200,3 , 16408,23 , 0,4 , 4,0 , 5321,10 , 5331,5 , 0, 0, 1, 6, 7 }, // Zarma/Latin/Niger { 240, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 433,8 , 98,16 , 37,5 , 8,10 , 33124,49 , 33173,99 , 33272,24 , 33124,49 , 33173,99 , 33272,24 , 18654,28 , 18682,45 , 18727,14 , 18654,28 , 18682,45 , 18727,14 , 687,5 , 685,6 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 0,7 , 13,5 , 4,0 , 5336,5 , 1952,8 , 0, 0, 1, 6, 7 }, // Duala/Latin/Cameroon - { 241, 7, 187, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 433,8 , 98,16 , 37,5 , 8,10 , 33296,36 , 33332,82 , 33414,24 , 33296,36 , 33332,82 , 33414,24 , 18741,28 , 18769,50 , 18819,14 , 18741,28 , 18769,50 , 18819,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,79,70}, 200,3 , 16667,23 , 13,5 , 4,0 , 5341,5 , 5346,7 , 0, 0, 1, 6, 7 }, // JolaFonyi/Latin/Senegal + { 241, 7, 187, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 433,8 , 98,16 , 37,5 , 8,10 , 33296,36 , 33332,82 , 33414,24 , 33296,36 , 33332,82 , 33414,24 , 18741,28 , 18769,50 , 18819,14 , 18741,28 , 18769,50 , 18819,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,79,70}, 200,3 , 16667,23 , 13,5 , 4,0 , 5341,5 , 5346,7 , 0, 0, 1, 6, 7 }, // Jola Fonyi/Latin/Senegal { 242, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 433,8 , 98,16 , 37,5 , 8,10 , 33438,50 , 33488,141 , 33629,24 , 33438,50 , 33488,141 , 33629,24 , 18833,30 , 18863,85 , 18948,14 , 18833,30 , 18863,85 , 18948,14 , 692,7 , 691,9 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16690,23 , 13,5 , 4,0 , 5353,6 , 5359,7 , 0, 0, 1, 6, 7 }, // Ewondo/Latin/Cameroon { 243, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 433,8 , 98,16 , 37,5 , 8,10 , 33653,39 , 33692,191 , 158,27 , 33653,39 , 33692,191 , 158,27 , 18962,29 , 18991,45 , 19036,14 , 18962,29 , 18991,45 , 19036,14 , 699,6 , 700,7 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16713,11 , 13,5 , 4,0 , 5366,5 , 5371,7 , 0, 0, 1, 6, 7 }, // Bafia/Latin/Cameroon - { 244, 7, 146, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 33883,48 , 33931,213 , 34144,24 , 33883,48 , 33931,213 , 34144,24 , 19050,28 , 19078,59 , 19137,14 , 19050,28 , 19078,59 , 19137,14 , 705,8 , 707,10 , 45,4 , 5,17 , 22,23 , {77,90,78}, 272,3 , 0,7 , 41,6 , 4,0 , 5378,5 , 5383,10 , 2, 1, 7, 6, 7 }, // MakhuwaMeetto/Latin/Mozambique + { 244, 7, 146, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 33883,48 , 33931,213 , 34144,24 , 33883,48 , 33931,213 , 34144,24 , 19050,28 , 19078,59 , 19137,14 , 19050,28 , 19078,59 , 19137,14 , 705,8 , 707,10 , 45,4 , 5,17 , 22,23 , {77,90,78}, 272,3 , 0,7 , 41,6 , 4,0 , 5378,5 , 5383,10 , 2, 1, 7, 6, 7 }, // Makhuwa Meetto/Latin/Mozambique { 245, 7, 37, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 433,8 , 98,16 , 37,5 , 8,10 , 34168,48 , 34216,139 , 34355,24 , 34168,48 , 34216,139 , 34355,24 , 19151,28 , 19179,74 , 19253,14 , 19151,28 , 19179,74 , 19253,14 , 713,5 , 717,5 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16724,17 , 4,4 , 4,0 , 5393,6 , 5399,7 , 0, 0, 1, 6, 7 }, // Mundang/Latin/Cameroon { 246, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 171, 187, 0,6 , 0,6 , 0,6 , 0,6 , 433,8 , 98,16 , 37,5 , 8,10 , 34379,51 , 34430,143 , 158,27 , 34379,51 , 34430,143 , 158,27 , 19267,30 , 19297,89 , 19386,14 , 19267,30 , 19297,89 , 19386,14 , 718,4 , 722,4 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16741,20 , 13,5 , 4,0 , 5406,6 , 5412,7 , 0, 0, 1, 6, 7 }, // Kwasio/Latin/Cameroon - { 247, 7, 254, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 1667,9 , 98,16 , 18,7 , 551,12 , 34573,54 , 34627,96 , 34723,24 , 34573,54 , 34627,96 , 34723,24 , 19400,38 , 19438,79 , 19517,14 , 19400,38 , 19438,79 , 19517,14 , 722,2 , 726,2 , 45,4 , 5,17 , 22,23 , {83,83,80}, 115,1 , 0,7 , 4,4 , 4,0 , 5419,9 , 0,0 , 2, 1, 1, 6, 7 }, // Nuer/Latin/SouthSudan + { 247, 7, 254, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 1667,9 , 98,16 , 18,7 , 551,12 , 34573,54 , 34627,96 , 34723,24 , 34573,54 , 34627,96 , 34723,24 , 19400,38 , 19438,79 , 19517,14 , 19400,38 , 19438,79 , 19517,14 , 722,2 , 726,2 , 45,4 , 5,17 , 22,23 , {83,83,80}, 115,1 , 0,7 , 4,4 , 4,0 , 5419,9 , 0,0 , 2, 1, 1, 6, 7 }, // Nuer/Latin/South Sudan { 248, 2, 178, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 896,11 , 896,11 , 245,6 , 1676,30 , 37,5 , 8,10 , 34747,50 , 34797,116 , 34913,24 , 34747,50 , 34937,121 , 34913,24 , 19531,21 , 19552,71 , 19623,14 , 19531,21 , 19552,71 , 19623,14 , 724,2 , 728,2 , 1117,5 , 1122,17 , 22,23 , {82,85,66}, 119,1 , 16761,47 , 13,5 , 4,0 , 5428,9 , 5437,9 , 2, 1, 1, 6, 7 }, // Sakha/Cyrillic/Russia { 249, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 35058,48 , 35106,117 , 158,27 , 35058,48 , 35106,117 , 158,27 , 19637,28 , 19665,60 , 19725,14 , 19637,28 , 19665,60 , 19725,14 , 726,9 , 730,9 , 45,4 , 5,17 , 22,23 , {84,90,83}, 188,3 , 16808,25 , 0,4 , 4,0 , 5446,9 , 5455,9 , 0, 0, 1, 6, 7 }, // Sangu/Latin/Tanzania { 251, 7, 156, 46, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 433,8 , 98,16 , 37,5 , 8,10 , 31225,46 , 31271,88 , 31359,24 , 31225,46 , 31271,88 , 31359,24 , 17656,28 , 17684,54 , 17441,14 , 17656,28 , 17684,54 , 17441,14 , 679,8 , 675,10 , 45,4 , 5,17 , 22,23 , {88,79,70}, 200,3 , 16408,23 , 0,4 , 4,0 , 5464,13 , 5331,5 , 0, 0, 1, 6, 7 }, // Tasawaq/Latin/Niger @@ -1799,15 +1799,15 @@ static const QLocaleData locale_data[] = { { 259, 7, 37, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 1497,18 , 37,5 , 8,10 , 36414,137 , 36551,142 , 36693,36 , 36414,137 , 36551,142 , 36693,36 , 20260,49 , 20260,49 , 20309,21 , 20260,49 , 20260,49 , 20309,21 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16896,12 , 8,5 , 4,0 , 5551,5 , 5556,7 , 0, 0, 1, 6, 7 }, // Meta/Latin/Cameroon { 260, 7, 37, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1716,32 , 37,5 , 8,10 , 36729,165 , 36729,165 , 158,27 , 36729,165 , 36729,165 , 158,27 , 20330,111 , 20330,111 , 85,14 , 20330,111 , 20330,111 , 85,14 , 763,9 , 771,8 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16908,16 , 8,5 , 4,0 , 5563,16 , 5579,7 , 0, 0, 1, 6, 7 }, // Ngiemboon/Latin/Cameroon { 290, 11, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,78,82}, 117,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 7, 7 }, // Manipuri/Bengali/India - { 309, 100, 232, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {86,78,68}, 332,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // TaiDam/Tai Viet/Vietnam + { 309, 100, 232, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {86,78,68}, 332,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Tai Dam/Tai Viet/Vietnam { 312, 7, 37, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Akoose/Latin/Cameroon - { 313, 7, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 543,6 , 35,18 , 18,7 , 25,12 , 36894,180 , 36894,180 , 158,27 , 36894,180 , 36894,180 , 158,27 , 20441,87 , 20441,87 , 85,14 , 20441,87 , 20441,87 , 20528,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,83,68}, 6,1 , 0,7 , 41,6 , 4,0 , 5586,12 , 5598,22 , 2, 1, 7, 6, 7 }, // Lakota/Latin/UnitedStates + { 313, 7, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 543,6 , 35,18 , 18,7 , 25,12 , 36894,180 , 36894,180 , 158,27 , 36894,180 , 36894,180 , 158,27 , 20441,87 , 20441,87 , 85,14 , 20441,87 , 20441,87 , 20528,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,83,68}, 6,1 , 0,7 , 41,6 , 4,0 , 5586,12 , 5598,22 , 2, 1, 7, 6, 7 }, // Lakota/Latin/United States { 314, 9, 145, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 433,8 , 98,16 , 37,5 , 8,10 , 27255,48 , 27303,81 , 27384,24 , 27255,48 , 27303,81 , 27384,24 , 14844,30 , 20542,48 , 85,14 , 14844,30 , 20542,48 , 85,14 , 516,6 , 494,8 , 45,4 , 5,17 , 22,23 , {77,65,68}, 0,0 , 15845,21 , 0,4 , 4,0 , 5620,8 , 4805,6 , 2, 1, 6, 5, 6 }, // Standard Moroccan Tamazight/Tifinagh/Morocco { 315, 7, 43, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {67,76,80}, 6,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Mapuche/Latin/Chile { 316, 1, 103, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 18,7 , 25,12 , 37074,105 , 37074,105 , 37179,24 , 37074,105 , 37074,105 , 37179,24 , 20590,58 , 20590,58 , 20648,14 , 20590,58 , 20590,58 , 20648,14 , 772,3 , 779,3 , 45,4 , 5,17 , 22,23 , {73,81,68}, 44,5 , 16924,20 , 13,5 , 4,0 , 5628,14 , 5642,5 , 0, 0, 6, 5, 6 }, // Central Kurdish/Arabic/Iraq { 316, 1, 102, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 37074,105 , 37074,105 , 37179,24 , 37074,105 , 37074,105 , 37179,24 , 20590,58 , 20590,58 , 20648,14 , 20590,58 , 20590,58 , 20648,14 , 772,3 , 779,3 , 45,4 , 5,17 , 22,23 , {73,82,82}, 0,0 , 16944,19 , 13,5 , 4,0 , 5628,14 , 5647,5 , 0, 0, 6, 5, 5 }, // Central Kurdish/Arabic/Iran - { 317, 7, 82, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 185,7 , 185,7 , 114,6 , 593,18 , 55,4 , 59,9 , 37203,48 , 37251,85 , 16435,24 , 37336,60 , 37396,93 , 16435,24 , 20662,28 , 20690,53 , 20743,14 , 20662,28 , 20690,53 , 20743,14 , 775,9 , 782,10 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 16963,27 , 13,5 , 4,0 , 5652,14 , 5666,6 , 2, 1, 1, 6, 7 }, // LowerSorbian/Latin/Germany - { 318, 7, 82, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 185,7 , 185,7 , 114,6 , 593,18 , 563,12 , 59,9 , 37489,48 , 37537,86 , 16435,24 , 37623,60 , 37683,93 , 16435,24 , 20757,28 , 20785,53 , 20838,14 , 20757,28 , 20785,53 , 20838,14 , 775,9 , 792,9 , 1139,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 16990,29 , 13,5 , 4,0 , 5672,15 , 5687,6 , 2, 1, 1, 6, 7 }, // UpperSorbian/Latin/Germany + { 317, 7, 82, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 185,7 , 185,7 , 114,6 , 593,18 , 55,4 , 59,9 , 37203,48 , 37251,85 , 16435,24 , 37336,60 , 37396,93 , 16435,24 , 20662,28 , 20690,53 , 20743,14 , 20662,28 , 20690,53 , 20743,14 , 775,9 , 782,10 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 16963,27 , 13,5 , 4,0 , 5652,14 , 5666,6 , 2, 1, 1, 6, 7 }, // Lower Sorbian/Latin/Germany + { 318, 7, 82, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 185,7 , 185,7 , 114,6 , 593,18 , 563,12 , 59,9 , 37489,48 , 37537,86 , 16435,24 , 37623,60 , 37683,93 , 16435,24 , 20757,28 , 20785,53 , 20838,14 , 20757,28 , 20785,53 , 20838,14 , 775,9 , 792,9 , 1139,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 16990,29 , 13,5 , 4,0 , 5672,15 , 5687,6 , 2, 1, 1, 6, 7 }, // Upper Sorbian/Latin/Germany { 319, 7, 37, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Kenyang/Latin/Cameroon { 320, 7, 38, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {67,65,68}, 233,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 0, 7, 6, 7 }, // Mohawk/Latin/Canada { 321, 75, 91, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {71,78,70}, 209,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Nko/Nko/Guinea @@ -1821,7 +1821,7 @@ static const QLocaleData locale_data[] = { { 346, 1, 102, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 14357,70 , 14357,70 , 158,27 , 14357,70 , 14357,70 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 653,4 , 657,39 , 22,23 , {73,82,82}, 338,3 , 17030,27 , 8,5 , 4,0 , 5724,7 , 3136,5 , 0, 0, 6, 5, 5 }, // Mazanderani/Arabic/Iran { 349, 1, 102, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 38181,77 , 38181,77 , 158,27 , 38181,77 , 38181,77 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,82,82}, 0,0 , 0,7 , 8,5 , 4,0 , 5731,11 , 0,0 , 0, 0, 6, 5, 5 }, // Northern Luri/Arabic/Iran { 349, 1, 103, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 18,7 , 25,12 , 38181,77 , 38181,77 , 158,27 , 38181,77 , 38181,77 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,81,68}, 44,5 , 0,7 , 8,5 , 4,0 , 5731,11 , 0,0 , 0, 0, 6, 5, 6 }, // Northern Luri/Arabic/Iraq - { 357, 6, 97, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 170,5 , 170,5 , 951,5 , 951,5 , 412,8 , 441,14 , 198,6 , 215,13 , 4671,39 , 4671,39 , 158,27 , 4671,39 , 4671,39 , 158,27 , 2023,28 , 2023,28 , 2051,14 , 2023,28 , 2023,28 , 2051,14 , 60,2 , 57,2 , 45,4 , 5,17 , 22,23 , {72,75,68}, 130,3 , 17057,11 , 4,4 , 4,0 , 5742,2 , 5744,14 , 2, 1, 7, 6, 7 }, // Cantonese/Traditional Han/HongKong + { 357, 6, 97, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 170,5 , 170,5 , 951,5 , 951,5 , 412,8 , 441,14 , 198,6 , 215,13 , 4671,39 , 4671,39 , 158,27 , 4671,39 , 4671,39 , 158,27 , 2023,28 , 2023,28 , 2051,14 , 2023,28 , 2023,28 , 2051,14 , 60,2 , 57,2 , 45,4 , 5,17 , 22,23 , {72,75,68}, 130,3 , 17057,11 , 4,4 , 4,0 , 5742,2 , 5744,14 , 2, 1, 7, 6, 7 }, // Cantonese/Traditional Han/Hong Kong { 357, 5, 44, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 170,5 , 170,5 , 951,5 , 951,5 , 412,8 , 420,13 , 198,6 , 204,11 , 4671,39 , 4710,38 , 158,27 , 4671,39 , 4710,38 , 158,27 , 2002,21 , 2023,28 , 2051,14 , 2002,21 , 2023,28 , 2051,14 , 60,2 , 57,2 , 45,4 , 5,17 , 22,23 , {67,78,89}, 129,1 , 3122,13 , 4,4 , 4,0 , 5758,2 , 5760,7 , 2, 1, 7, 6, 7 }, // Cantonese/Simplified Han/China { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, {0,0,0}, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, 0, 0, 0, 0, 0 } // trailing 0s }; @@ -6392,7 +6392,7 @@ static const char language_name_list[] = "Mongolian\0" "Nauru\0" "Nepali\0" -"NorwegianBokmal\0" +"Norwegian Bokmal\0" "Occitan\0" "Oriya\0" "Pashto\0" @@ -6448,7 +6448,7 @@ static const char language_name_list[] = "Yoruba\0" "Zhuang\0" "Zulu\0" -"NorwegianNynorsk\0" +"Norwegian Nynorsk\0" "Bosnian\0" "Divehi\0" "Manx\0" @@ -6537,7 +6537,7 @@ static const char language_name_list[] = "Kongo\0" "Kwanyama\0" "Limburgish\0" -"LubaKatanga\0" +"Luba Katanga\0" "Luxembourgish\0" "Navaho\0" "Ndonga\0" @@ -6548,10 +6548,10 @@ static const char language_name_list[] = "Basaa\0" "Zarma\0" "Duala\0" -"JolaFonyi\0" +"Jola Fonyi\0" "Ewondo\0" "Bafia\0" -"MakhuwaMeetto\0" +"Makhuwa Meetto\0" "Mundang\0" "Kwasio\0" "Nuer\0" @@ -6570,26 +6570,26 @@ static const char language_name_list[] = "Ngiemboon\0" "Aragonese\0" "Akkadian\0" -"AncientEgyptian\0" -"AncientGreek\0" +"Ancient Egyptian\0" +"Ancient Greek\0" "Aramaic\0" "Balinese\0" "Bamun\0" -"BatakToba\0" +"Batak Toba\0" "Buginese\0" "Buhid\0" "Carian\0" "Chakma\0" -"ClassicalMandaic\0" +"Classical Mandaic\0" "Coptic\0" "Dogri\0" -"EasternCham\0" -"EasternKayah\0" +"Eastern Cham\0" +"Eastern Kayah\0" "Etruscan\0" "Gothic\0" "Hanunoo\0" "Ingush\0" -"LargeFloweryMiao\0" +"Large Flowery Miao\0" "Lepcha\0" "Limbu\0" "Lisu\0" @@ -6599,15 +6599,15 @@ static const char language_name_list[] = "Mandingo\0" "Manipuri\0" "Meroitic\0" -"NorthernThai\0" -"OldIrish\0" -"OldNorse\0" -"OldPersian\0" -"OldTurkish\0" +"Northern Thai\0" +"Old Irish\0" +"Old Norse\0" +"Old Persian\0" +"Old Turkish\0" "Pahlavi\0" "Parthian\0" "Phoenician\0" -"PrakritLanguage\0" +"Prakrit Language\0" "Rejang\0" "Sabaean\0" "Samaritan\0" @@ -6616,16 +6616,16 @@ static const char language_name_list[] = "Sora\0" "Sylheti\0" "Tagbanwa\0" -"TaiDam\0" -"TaiNua\0" +"Tai Dam\0" +"Tai Nua\0" "Ugaritic\0" "Akoose\0" "Lakota\0" "Standard Moroccan Tamazight\0" "Mapuche\0" "Central Kurdish\0" -"LowerSorbian\0" -"UpperSorbian\0" +"Lower Sorbian\0" +"Upper Sorbian\0" "Kenyang\0" "Mohawk\0" "Nko\0" @@ -6663,7 +6663,7 @@ static const char language_name_list[] = "Tokelau\0" "Tok Pisin\0" "Tuvalu\0" -"UncodedLanguages\0" +"Uncoded Languages\0" "Cantonese\0" "Osage\0" "Tangut\0" @@ -6755,281 +6755,281 @@ static const quint16 language_name_index[] = { 680, // Mongolian 690, // Nauru 696, // Nepali - 703, // NorwegianBokmal - 719, // Occitan - 727, // Oriya - 733, // Pashto - 740, // Persian - 748, // Polish - 755, // Portuguese - 766, // Punjabi - 774, // Quechua - 782, // Romansh - 790, // Romanian - 799, // Russian - 807, // Samoan - 814, // Sango - 820, // Sanskrit - 829, // Serbian - 837, // Ossetic - 845, // Southern Sotho - 860, // Tswana - 867, // Shona - 873, // Sindhi - 880, // Sinhala - 888, // Swati - 894, // Slovak - 901, // Slovenian - 911, // Somali - 918, // Spanish - 926, // Sundanese - 936, // Swahili - 944, // Swedish - 952, // Sardinian - 962, // Tajik - 968, // Tamil - 974, // Tatar - 980, // Telugu - 987, // Thai - 992, // Tibetan - 1000, // Tigrinya - 1009, // Tongan - 1016, // Tsonga - 1023, // Turkish - 1031, // Turkmen - 1039, // Tahitian - 1048, // Uighur - 1055, // Ukrainian - 1065, // Urdu - 1070, // Uzbek - 1076, // Vietnamese - 1087, // Volapuk - 1095, // Welsh - 1101, // Wolof - 1107, // Xhosa - 1113, // Yiddish - 1121, // Yoruba - 1128, // Zhuang - 1135, // Zulu - 1140, // NorwegianNynorsk - 1157, // Bosnian - 1165, // Divehi - 1172, // Manx - 1177, // Cornish - 1185, // Akan - 1190, // Konkani - 1198, // Ga - 1201, // Igbo - 1206, // Kamba - 1212, // Syriac - 1219, // Blin - 1224, // Geez - 1229, // Koro - 1234, // Sidamo - 1241, // Atsam - 1247, // Tigre - 1253, // Jju - 1257, // Friulian - 1266, // Venda - 1272, // Ewe - 1276, // Walamo - 1283, // Hawaiian - 1292, // Tyap - 1297, // Nyanja - 1304, // Filipino - 1313, // Swiss German - 1326, // Sichuan Yi - 1337, // Kpelle - 1344, // Low German - 1355, // South Ndebele - 1369, // Northern Sotho - 1384, // Northern Sami - 1398, // Taroko - 1405, // Gusii - 1411, // Taita - 1417, // Fulah - 1423, // Kikuyu - 1430, // Samburu - 1438, // Sena - 1443, // North Ndebele - 1457, // Rombo - 1463, // Tachelhit - 1473, // Kabyle - 1480, // Nyankole - 1489, // Bena - 1494, // Vunjo - 1500, // Bambara - 1508, // Embu - 1513, // Cherokee - 1522, // Morisyen - 1531, // Makonde - 1539, // Langi - 1545, // Ganda - 1551, // Bemba - 1557, // Kabuverdianu - 1570, // Meru - 1575, // Kalenjin - 1584, // Nama - 1589, // Machame - 1597, // Colognian - 1607, // Masai - 1613, // Soga - 1618, // Luyia - 1624, // Asu - 1628, // Teso - 1633, // Saho - 1638, // Koyra Chiini - 1651, // Rwa - 1655, // Luo - 1659, // Chiga - 1665, // Central Morocco Tamazight - 1691, // Koyraboro Senni - 1707, // Shambala - 1716, // Bodo - 1721, // Avaric - 1728, // Chamorro - 1737, // Chechen - 1745, // Church - 1752, // Chuvash - 1760, // Cree - 1765, // Haitian - 1773, // Herero - 1780, // Hiri Motu - 1790, // Kanuri - 1797, // Komi - 1802, // Kongo - 1808, // Kwanyama - 1817, // Limburgish - 1828, // LubaKatanga - 1840, // Luxembourgish - 1854, // Navaho - 1861, // Ndonga - 1868, // Ojibwa - 1875, // Pali - 1880, // Walloon - 1888, // Aghem - 1894, // Basaa - 1900, // Zarma - 1906, // Duala - 1912, // JolaFonyi - 1922, // Ewondo - 1929, // Bafia - 1935, // MakhuwaMeetto - 1949, // Mundang - 1957, // Kwasio - 1964, // Nuer - 1969, // Sakha - 1975, // Sangu - 1981, // Congo Swahili - 1995, // Tasawaq - 2003, // Vai - 2007, // Walser - 2014, // Yangben - 2022, // Avestan - 2030, // Asturian - 2039, // Ngomba - 2046, // Kako - 2051, // Meta - 2056, // Ngiemboon - 2066, // Aragonese - 2076, // Akkadian - 2085, // AncientEgyptian - 2101, // AncientGreek - 2114, // Aramaic - 2122, // Balinese - 2131, // Bamun - 2137, // BatakToba - 2147, // Buginese - 2156, // Buhid - 2162, // Carian - 2169, // Chakma - 2176, // ClassicalMandaic - 2193, // Coptic - 2200, // Dogri - 2206, // EasternCham - 2218, // EasternKayah - 2231, // Etruscan - 2240, // Gothic - 2247, // Hanunoo - 2255, // Ingush - 2262, // LargeFloweryMiao - 2279, // Lepcha - 2286, // Limbu - 2292, // Lisu - 2297, // Lu - 2300, // Lycian - 2307, // Lydian - 2314, // Mandingo - 2323, // Manipuri - 2332, // Meroitic - 2341, // NorthernThai - 2354, // OldIrish - 2363, // OldNorse - 2372, // OldPersian - 2383, // OldTurkish - 2394, // Pahlavi - 2402, // Parthian - 2411, // Phoenician - 2422, // PrakritLanguage - 2438, // Rejang - 2445, // Sabaean - 2453, // Samaritan - 2463, // Santali - 2471, // Saurashtra - 2482, // Sora - 2487, // Sylheti - 2495, // Tagbanwa - 2504, // TaiDam - 2511, // TaiNua - 2518, // Ugaritic - 2527, // Akoose - 2534, // Lakota - 2541, // Standard Moroccan Tamazight - 2569, // Mapuche - 2577, // Central Kurdish - 2593, // LowerSorbian - 2606, // UpperSorbian - 2619, // Kenyang - 2627, // Mohawk - 2634, // Nko - 2638, // Prussian - 2647, // Kiche - 2653, // Southern Sami - 2667, // Lule Sami - 2677, // Inari Sami - 2688, // Skolt Sami - 2699, // Warlpiri - 2708, // Manichaean Middle Persian - 2734, // Mende - 2740, // Ancient North Arabian - 2762, // Linear A - 2771, // Hmong Njua - 2782, // Ho - 2785, // Lezghian - 2794, // Bassa - 2800, // Mono - 2805, // Tedim Chin - 2816, // Maithili - 2825, // Ahom - 2830, // American Sign Language - 2853, // Ardhamagadhi Prakrit - 2874, // Bhojpuri - 2883, // Hieroglyphic Luwian - 2903, // Literary Chinese - 2920, // Mazanderani - 2932, // Mru - 2936, // Newari - 2943, // Northern Luri - 2957, // Palauan - 2965, // Papiamento - 2976, // Saraiki - 2984, // Tokelau - 2992, // Tok Pisin - 3002, // Tuvalu - 3009, // UncodedLanguages - 3026, // Cantonese - 3036, // Osage - 3042, // Tangut + 703, // Norwegian Bokmal + 720, // Occitan + 728, // Oriya + 734, // Pashto + 741, // Persian + 749, // Polish + 756, // Portuguese + 767, // Punjabi + 775, // Quechua + 783, // Romansh + 791, // Romanian + 800, // Russian + 808, // Samoan + 815, // Sango + 821, // Sanskrit + 830, // Serbian + 838, // Ossetic + 846, // Southern Sotho + 861, // Tswana + 868, // Shona + 874, // Sindhi + 881, // Sinhala + 889, // Swati + 895, // Slovak + 902, // Slovenian + 912, // Somali + 919, // Spanish + 927, // Sundanese + 937, // Swahili + 945, // Swedish + 953, // Sardinian + 963, // Tajik + 969, // Tamil + 975, // Tatar + 981, // Telugu + 988, // Thai + 993, // Tibetan + 1001, // Tigrinya + 1010, // Tongan + 1017, // Tsonga + 1024, // Turkish + 1032, // Turkmen + 1040, // Tahitian + 1049, // Uighur + 1056, // Ukrainian + 1066, // Urdu + 1071, // Uzbek + 1077, // Vietnamese + 1088, // Volapuk + 1096, // Welsh + 1102, // Wolof + 1108, // Xhosa + 1114, // Yiddish + 1122, // Yoruba + 1129, // Zhuang + 1136, // Zulu + 1141, // Norwegian Nynorsk + 1159, // Bosnian + 1167, // Divehi + 1174, // Manx + 1179, // Cornish + 1187, // Akan + 1192, // Konkani + 1200, // Ga + 1203, // Igbo + 1208, // Kamba + 1214, // Syriac + 1221, // Blin + 1226, // Geez + 1231, // Koro + 1236, // Sidamo + 1243, // Atsam + 1249, // Tigre + 1255, // Jju + 1259, // Friulian + 1268, // Venda + 1274, // Ewe + 1278, // Walamo + 1285, // Hawaiian + 1294, // Tyap + 1299, // Nyanja + 1306, // Filipino + 1315, // Swiss German + 1328, // Sichuan Yi + 1339, // Kpelle + 1346, // Low German + 1357, // South Ndebele + 1371, // Northern Sotho + 1386, // Northern Sami + 1400, // Taroko + 1407, // Gusii + 1413, // Taita + 1419, // Fulah + 1425, // Kikuyu + 1432, // Samburu + 1440, // Sena + 1445, // North Ndebele + 1459, // Rombo + 1465, // Tachelhit + 1475, // Kabyle + 1482, // Nyankole + 1491, // Bena + 1496, // Vunjo + 1502, // Bambara + 1510, // Embu + 1515, // Cherokee + 1524, // Morisyen + 1533, // Makonde + 1541, // Langi + 1547, // Ganda + 1553, // Bemba + 1559, // Kabuverdianu + 1572, // Meru + 1577, // Kalenjin + 1586, // Nama + 1591, // Machame + 1599, // Colognian + 1609, // Masai + 1615, // Soga + 1620, // Luyia + 1626, // Asu + 1630, // Teso + 1635, // Saho + 1640, // Koyra Chiini + 1653, // Rwa + 1657, // Luo + 1661, // Chiga + 1667, // Central Morocco Tamazight + 1693, // Koyraboro Senni + 1709, // Shambala + 1718, // Bodo + 1723, // Avaric + 1730, // Chamorro + 1739, // Chechen + 1747, // Church + 1754, // Chuvash + 1762, // Cree + 1767, // Haitian + 1775, // Herero + 1782, // Hiri Motu + 1792, // Kanuri + 1799, // Komi + 1804, // Kongo + 1810, // Kwanyama + 1819, // Limburgish + 1830, // Luba Katanga + 1843, // Luxembourgish + 1857, // Navaho + 1864, // Ndonga + 1871, // Ojibwa + 1878, // Pali + 1883, // Walloon + 1891, // Aghem + 1897, // Basaa + 1903, // Zarma + 1909, // Duala + 1915, // Jola Fonyi + 1926, // Ewondo + 1933, // Bafia + 1939, // Makhuwa Meetto + 1954, // Mundang + 1962, // Kwasio + 1969, // Nuer + 1974, // Sakha + 1980, // Sangu + 1986, // Congo Swahili + 2000, // Tasawaq + 2008, // Vai + 2012, // Walser + 2019, // Yangben + 2027, // Avestan + 2035, // Asturian + 2044, // Ngomba + 2051, // Kako + 2056, // Meta + 2061, // Ngiemboon + 2071, // Aragonese + 2081, // Akkadian + 2090, // Ancient Egyptian + 2107, // Ancient Greek + 2121, // Aramaic + 2129, // Balinese + 2138, // Bamun + 2144, // Batak Toba + 2155, // Buginese + 2164, // Buhid + 2170, // Carian + 2177, // Chakma + 2184, // Classical Mandaic + 2202, // Coptic + 2209, // Dogri + 2215, // Eastern Cham + 2228, // Eastern Kayah + 2242, // Etruscan + 2251, // Gothic + 2258, // Hanunoo + 2266, // Ingush + 2273, // Large Flowery Miao + 2292, // Lepcha + 2299, // Limbu + 2305, // Lisu + 2310, // Lu + 2313, // Lycian + 2320, // Lydian + 2327, // Mandingo + 2336, // Manipuri + 2345, // Meroitic + 2354, // Northern Thai + 2368, // Old Irish + 2378, // Old Norse + 2388, // Old Persian + 2400, // Old Turkish + 2412, // Pahlavi + 2420, // Parthian + 2429, // Phoenician + 2440, // Prakrit Language + 2457, // Rejang + 2464, // Sabaean + 2472, // Samaritan + 2482, // Santali + 2490, // Saurashtra + 2501, // Sora + 2506, // Sylheti + 2514, // Tagbanwa + 2523, // Tai Dam + 2531, // Tai Nua + 2539, // Ugaritic + 2548, // Akoose + 2555, // Lakota + 2562, // Standard Moroccan Tamazight + 2590, // Mapuche + 2598, // Central Kurdish + 2614, // Lower Sorbian + 2628, // Upper Sorbian + 2642, // Kenyang + 2650, // Mohawk + 2657, // Nko + 2661, // Prussian + 2670, // Kiche + 2676, // Southern Sami + 2690, // Lule Sami + 2700, // Inari Sami + 2711, // Skolt Sami + 2722, // Warlpiri + 2731, // Manichaean Middle Persian + 2757, // Mende + 2763, // Ancient North Arabian + 2785, // Linear A + 2794, // Hmong Njua + 2805, // Ho + 2808, // Lezghian + 2817, // Bassa + 2823, // Mono + 2828, // Tedim Chin + 2839, // Maithili + 2848, // Ahom + 2853, // American Sign Language + 2876, // Ardhamagadhi Prakrit + 2897, // Bhojpuri + 2906, // Hieroglyphic Luwian + 2926, // Literary Chinese + 2943, // Mazanderani + 2955, // Mru + 2959, // Newari + 2966, // Northern Luri + 2980, // Palauan + 2988, // Papiamento + 2999, // Saraiki + 3007, // Tokelau + 3015, // Tok Pisin + 3025, // Tuvalu + 3032, // Uncoded Languages + 3050, // Cantonese + 3060, // Osage + 3066, // Tangut }; static const char script_name_list[] = @@ -7077,7 +7077,7 @@ static const char script_name_list[] = "Brahmi\0" "Buginese\0" "Buhid\0" -"CanadianAboriginal\0" +"Canadian Aboriginal\0" "Carian\0" "Chakma\0" "Cham\0" @@ -7166,7 +7166,7 @@ static const char script_name_list[] = "Hatran\0" "Multani\0" "Old Hungarian\0" -"SignWriting\0" +"Sign Writing\0" "Adlam\0" "Bhaiksuki\0" "Marchen\0" @@ -7222,104 +7222,104 @@ static const quint16 script_name_index[] = { 325, // Brahmi 332, // Buginese 341, // Buhid - 347, // CanadianAboriginal - 366, // Carian - 373, // Chakma - 380, // Cham - 385, // Coptic - 392, // Cypriot - 400, // Egyptian Hieroglyphs - 421, // Fraser - 428, // Glagolitic - 439, // Gothic - 446, // Han - 450, // Hangul - 457, // Hanunoo - 465, // Imperial Aramaic - 482, // Inscriptional Pahlavi - 504, // Inscriptional Parthian - 527, // Javanese - 536, // Kaithi - 543, // Katakana - 552, // Kayah Li - 561, // Kharoshthi - 572, // Lanna - 578, // Lepcha - 585, // Limbu - 591, // Linear B - 600, // Lycian - 607, // Lydian - 614, // Mandaean - 623, // Meitei Mayek - 636, // Meroitic - 645, // Meroitic Cursive - 662, // Nko - 666, // New Tai Lue - 678, // Ogham - 684, // Ol Chiki - 693, // Old Italic - 704, // Old Persian - 716, // Old South Arabian - 734, // Orkhon - 741, // Osmanya - 749, // Phags Pa - 758, // Phoenician - 769, // Pollard Phonetic - 786, // Rejang - 793, // Runic - 799, // Samaritan - 809, // Saurashtra - 820, // Sharada - 828, // Shavian - 836, // Sora Sompeng - 849, // Cuneiform - 859, // Sundanese - 869, // Syloti Nagri - 882, // Tagalog - 890, // Tagbanwa - 899, // Tai Le - 906, // Tai Viet - 915, // Takri - 921, // Ugaritic - 930, // Braille - 938, // Hiragana - 947, // Caucasian Albanian - 966, // Bassa Vah - 976, // Duployan - 985, // Elbasan - 993, // Grantha - 1001, // Pahawh Hmong - 1014, // Khojki - 1021, // Linear A - 1030, // Mahajani - 1039, // Manichaean - 1050, // Mende Kikakui - 1064, // Modi - 1069, // Mro - 1073, // Old North Arabian - 1091, // Nabataean - 1101, // Palmyrene - 1111, // Pau Cin Hau - 1123, // Old Permic - 1134, // Psalter Pahlavi - 1150, // Siddham - 1158, // Khudawadi - 1168, // Tirhuta - 1176, // Varang Kshiti - 1190, // Ahom - 1195, // Anatolian Hieroglyphs - 1217, // Hatran - 1224, // Multani - 1232, // Old Hungarian - 1246, // SignWriting - 1258, // Adlam - 1264, // Bhaiksuki - 1274, // Marchen - 1282, // Newa - 1287, // Osage - 1293, // Tangut - 1300, // Han with Bopomofo - 1318, // Jamo + 347, // Canadian Aboriginal + 367, // Carian + 374, // Chakma + 381, // Cham + 386, // Coptic + 393, // Cypriot + 401, // Egyptian Hieroglyphs + 422, // Fraser + 429, // Glagolitic + 440, // Gothic + 447, // Han + 451, // Hangul + 458, // Hanunoo + 466, // Imperial Aramaic + 483, // Inscriptional Pahlavi + 505, // Inscriptional Parthian + 528, // Javanese + 537, // Kaithi + 544, // Katakana + 553, // Kayah Li + 562, // Kharoshthi + 573, // Lanna + 579, // Lepcha + 586, // Limbu + 592, // Linear B + 601, // Lycian + 608, // Lydian + 615, // Mandaean + 624, // Meitei Mayek + 637, // Meroitic + 646, // Meroitic Cursive + 663, // Nko + 667, // New Tai Lue + 679, // Ogham + 685, // Ol Chiki + 694, // Old Italic + 705, // Old Persian + 717, // Old South Arabian + 735, // Orkhon + 742, // Osmanya + 750, // Phags Pa + 759, // Phoenician + 770, // Pollard Phonetic + 787, // Rejang + 794, // Runic + 800, // Samaritan + 810, // Saurashtra + 821, // Sharada + 829, // Shavian + 837, // Sora Sompeng + 850, // Cuneiform + 860, // Sundanese + 870, // Syloti Nagri + 883, // Tagalog + 891, // Tagbanwa + 900, // Tai Le + 907, // Tai Viet + 916, // Takri + 922, // Ugaritic + 931, // Braille + 939, // Hiragana + 948, // Caucasian Albanian + 967, // Bassa Vah + 977, // Duployan + 986, // Elbasan + 994, // Grantha + 1002, // Pahawh Hmong + 1015, // Khojki + 1022, // Linear A + 1031, // Mahajani + 1040, // Manichaean + 1051, // Mende Kikakui + 1065, // Modi + 1070, // Mro + 1074, // Old North Arabian + 1092, // Nabataean + 1102, // Palmyrene + 1112, // Pau Cin Hau + 1124, // Old Permic + 1135, // Psalter Pahlavi + 1151, // Siddham + 1159, // Khudawadi + 1169, // Tirhuta + 1177, // Varang Kshiti + 1191, // Ahom + 1196, // Anatolian Hieroglyphs + 1218, // Hatran + 1225, // Multani + 1233, // Old Hungarian + 1247, // Sign Writing + 1260, // Adlam + 1266, // Bhaiksuki + 1276, // Marchen + 1284, // Newa + 1289, // Osage + 1295, // Tangut + 1302, // Han with Bopomofo + 1320, // Jamo }; static const char country_name_list[] = @@ -7327,12 +7327,12 @@ static const char country_name_list[] = "Afghanistan\0" "Albania\0" "Algeria\0" -"AmericanSamoa\0" +"American Samoa\0" "Andorra\0" "Angola\0" "Anguilla\0" "Antarctica\0" -"AntiguaAndBarbuda\0" +"Antigua And Barbuda\0" "Argentina\0" "Armenia\0" "Aruba\0" @@ -7350,58 +7350,58 @@ static const char country_name_list[] = "Bermuda\0" "Bhutan\0" "Bolivia\0" -"BosniaAndHerzegowina\0" +"Bosnia And Herzegowina\0" "Botswana\0" -"BouvetIsland\0" +"Bouvet Island\0" "Brazil\0" -"BritishIndianOceanTerritory\0" +"British Indian Ocean Territory\0" "Brunei\0" "Bulgaria\0" -"BurkinaFaso\0" +"Burkina Faso\0" "Burundi\0" "Cambodia\0" "Cameroon\0" "Canada\0" -"CapeVerde\0" -"CaymanIslands\0" -"CentralAfricanRepublic\0" +"Cape Verde\0" +"Cayman Islands\0" +"Central African Republic\0" "Chad\0" "Chile\0" "China\0" -"ChristmasIsland\0" -"CocosIslands\0" +"Christmas Island\0" +"Cocos Islands\0" "Colombia\0" "Comoros\0" -"CongoKinshasa\0" -"CongoBrazzaville\0" -"CookIslands\0" -"CostaRica\0" -"IvoryCoast\0" +"Congo Kinshasa\0" +"Congo Brazzaville\0" +"Cook Islands\0" +"Costa Rica\0" +"Ivory Coast\0" "Croatia\0" "Cuba\0" "Cyprus\0" -"CzechRepublic\0" +"Czech Republic\0" "Denmark\0" "Djibouti\0" "Dominica\0" -"DominicanRepublic\0" -"EastTimor\0" +"Dominican Republic\0" +"East Timor\0" "Ecuador\0" "Egypt\0" -"ElSalvador\0" -"EquatorialGuinea\0" +"El Salvador\0" +"Equatorial Guinea\0" "Eritrea\0" "Estonia\0" "Ethiopia\0" -"FalklandIslands\0" -"FaroeIslands\0" +"Falkland Islands\0" +"Faroe Islands\0" "Fiji\0" "Finland\0" "France\0" "Guernsey\0" -"FrenchGuiana\0" -"FrenchPolynesia\0" -"FrenchSouthernTerritories\0" +"French Guiana\0" +"French Polynesia\0" +"French Southern Territories\0" "Gabon\0" "Gambia\0" "Georgia\0" @@ -7415,12 +7415,12 @@ static const char country_name_list[] = "Guam\0" "Guatemala\0" "Guinea\0" -"GuineaBissau\0" +"Guinea Bissau\0" "Guyana\0" "Haiti\0" -"HeardAndMcDonaldIslands\0" +"Heard And McDonald Islands\0" "Honduras\0" -"HongKong\0" +"Hong Kong\0" "Hungary\0" "Iceland\0" "India\0" @@ -7436,8 +7436,8 @@ static const char country_name_list[] = "Kazakhstan\0" "Kenya\0" "Kiribati\0" -"NorthKorea\0" -"SouthKorea\0" +"North Korea\0" +"South Korea\0" "Kuwait\0" "Kyrgyzstan\0" "Laos\0" @@ -7457,7 +7457,7 @@ static const char country_name_list[] = "Maldives\0" "Mali\0" "Malta\0" -"MarshallIslands\0" +"Marshall Islands\0" "Martinique\0" "Mauritania\0" "Mauritius\0" @@ -7475,58 +7475,58 @@ static const char country_name_list[] = "Nauru\0" "Nepal\0" "Netherlands\0" -"CuraSao\0" -"NewCaledonia\0" -"NewZealand\0" +"Cura Sao\0" +"New Caledonia\0" +"New Zealand\0" "Nicaragua\0" "Niger\0" "Nigeria\0" "Niue\0" -"NorfolkIsland\0" -"NorthernMarianaIslands\0" +"Norfolk Island\0" +"Northern Mariana Islands\0" "Norway\0" "Oman\0" "Pakistan\0" "Palau\0" -"PalestinianTerritories\0" +"Palestinian Territories\0" "Panama\0" -"PapuaNewGuinea\0" +"Papua New Guinea\0" "Paraguay\0" "Peru\0" "Philippines\0" "Pitcairn\0" "Poland\0" "Portugal\0" -"PuertoRico\0" +"Puerto Rico\0" "Qatar\0" "Reunion\0" "Romania\0" "Russia\0" "Rwanda\0" -"SaintKittsAndNevis\0" -"SaintLucia\0" -"SaintVincentAndTheGrenadines\0" +"Saint Kitts And Nevis\0" +"Saint Lucia\0" +"Saint Vincent And The Grenadines\0" "Samoa\0" -"SanMarino\0" -"SaoTomeAndPrincipe\0" -"SaudiArabia\0" +"San Marino\0" +"Sao Tome And Principe\0" +"Saudi Arabia\0" "Senegal\0" "Seychelles\0" -"SierraLeone\0" +"Sierra Leone\0" "Singapore\0" "Slovakia\0" "Slovenia\0" -"SolomonIslands\0" +"Solomon Islands\0" "Somalia\0" -"SouthAfrica\0" -"SouthGeorgiaAndTheSouthSandwichIslands\0" +"South Africa\0" +"South Georgia And The South Sandwich Islands\0" "Spain\0" -"SriLanka\0" -"SaintHelena\0" -"SaintPierreAndMiquelon\0" +"Sri Lanka\0" +"Saint Helena\0" +"Saint Pierre And Miquelon\0" "Sudan\0" "Suriname\0" -"SvalbardAndJanMayenIslands\0" +"Svalbard And Jan Mayen Islands\0" "Swaziland\0" "Sweden\0" "Switzerland\0" @@ -7538,48 +7538,48 @@ static const char country_name_list[] = "Togo\0" "Tokelau\0" "Tonga\0" -"TrinidadAndTobago\0" +"Trinidad And Tobago\0" "Tunisia\0" "Turkey\0" "Turkmenistan\0" -"TurksAndCaicosIslands\0" +"Turks And Caicos Islands\0" "Tuvalu\0" "Uganda\0" "Ukraine\0" -"UnitedArabEmirates\0" -"UnitedKingdom\0" -"UnitedStates\0" -"UnitedStatesMinorOutlyingIslands\0" +"United Arab Emirates\0" +"United Kingdom\0" +"United States\0" +"United States Minor Outlying Islands\0" "Uruguay\0" "Uzbekistan\0" "Vanuatu\0" -"VaticanCityState\0" +"Vatican City State\0" "Venezuela\0" "Vietnam\0" -"BritishVirginIslands\0" -"UnitedStatesVirginIslands\0" -"WallisAndFutunaIslands\0" -"WesternSahara\0" +"British Virgin Islands\0" +"United States Virgin Islands\0" +"Wallis And Futuna Islands\0" +"Western Sahara\0" "Yemen\0" -"CanaryIslands\0" +"Canary Islands\0" "Zambia\0" "Zimbabwe\0" -"ClippertonIsland\0" +"Clipperton Island\0" "Montenegro\0" "Serbia\0" "Saint Barthelemy\0" "Saint Martin\0" "Latin America\0" -"AscensionIsland\0" -"AlandIslands\0" -"DiegoGarcia\0" -"CeutaAndMelilla\0" -"IsleOfMan\0" +"Ascension Island\0" +"Aland Islands\0" +"Diego Garcia\0" +"Ceuta And Melilla\0" +"Isle Of Man\0" "Jersey\0" -"TristanDaCunha\0" -"SouthSudan\0" +"Tristan Da Cunha\0" +"South Sudan\0" "Bonaire\0" -"SintMaarten\0" +"Sint Maarten\0" "Kosovo\0" "European Union\0" "Outlying Oceania\0" @@ -7592,264 +7592,264 @@ static const quint16 country_name_index[] = { 8, // Afghanistan 20, // Albania 28, // Algeria - 36, // AmericanSamoa - 50, // Andorra - 58, // Angola - 65, // Anguilla - 74, // Antarctica - 85, // AntiguaAndBarbuda - 103, // Argentina - 113, // Armenia - 121, // Aruba - 127, // Australia - 137, // Austria - 145, // Azerbaijan - 156, // Bahamas - 164, // Bahrain - 172, // Bangladesh - 183, // Barbados - 192, // Belarus - 200, // Belgium - 208, // Belize - 215, // Benin - 221, // Bermuda - 229, // Bhutan - 236, // Bolivia - 244, // BosniaAndHerzegowina - 265, // Botswana - 274, // BouvetIsland - 287, // Brazil - 294, // BritishIndianOceanTerritory - 322, // Brunei - 329, // Bulgaria - 338, // BurkinaFaso - 350, // Burundi - 358, // Cambodia - 367, // Cameroon - 376, // Canada - 383, // CapeVerde - 393, // CaymanIslands - 407, // CentralAfricanRepublic - 430, // Chad - 435, // Chile - 441, // China - 447, // ChristmasIsland - 463, // CocosIslands - 476, // Colombia - 485, // Comoros - 493, // CongoKinshasa - 507, // CongoBrazzaville - 524, // CookIslands - 536, // CostaRica - 546, // IvoryCoast - 557, // Croatia - 565, // Cuba - 570, // Cyprus - 577, // CzechRepublic - 591, // Denmark - 599, // Djibouti - 608, // Dominica - 617, // DominicanRepublic - 635, // EastTimor - 645, // Ecuador - 653, // Egypt - 659, // ElSalvador - 670, // EquatorialGuinea - 687, // Eritrea - 695, // Estonia - 703, // Ethiopia - 712, // FalklandIslands - 728, // FaroeIslands - 741, // Fiji - 746, // Finland - 754, // France - 761, // Guernsey - 770, // FrenchGuiana - 783, // FrenchPolynesia - 799, // FrenchSouthernTerritories - 825, // Gabon - 831, // Gambia - 838, // Georgia - 846, // Germany - 854, // Ghana - 860, // Gibraltar - 870, // Greece - 877, // Greenland - 887, // Grenada - 895, // Guadeloupe - 906, // Guam - 911, // Guatemala - 921, // Guinea - 928, // GuineaBissau - 941, // Guyana - 948, // Haiti - 954, // HeardAndMcDonaldIslands - 978, // Honduras - 987, // HongKong - 996, // Hungary - 1004, // Iceland - 1012, // India - 1018, // Indonesia - 1028, // Iran - 1033, // Iraq - 1038, // Ireland - 1046, // Israel - 1053, // Italy - 1059, // Jamaica - 1067, // Japan - 1073, // Jordan - 1080, // Kazakhstan - 1091, // Kenya - 1097, // Kiribati - 1106, // NorthKorea - 1117, // SouthKorea - 1128, // Kuwait - 1135, // Kyrgyzstan - 1146, // Laos - 1151, // Latvia - 1158, // Lebanon - 1166, // Lesotho - 1174, // Liberia - 1182, // Libya - 1188, // Liechtenstein - 1202, // Lithuania - 1212, // Luxembourg - 1223, // Macau - 1229, // Macedonia - 1239, // Madagascar - 1250, // Malawi - 1257, // Malaysia - 1266, // Maldives - 1275, // Mali - 1280, // Malta - 1286, // MarshallIslands - 1302, // Martinique - 1313, // Mauritania - 1324, // Mauritius - 1334, // Mayotte - 1342, // Mexico - 1349, // Micronesia - 1360, // Moldova - 1368, // Monaco - 1375, // Mongolia - 1384, // Montserrat - 1395, // Morocco - 1403, // Mozambique - 1414, // Myanmar - 1422, // Namibia - 1430, // Nauru - 1436, // Nepal - 1442, // Netherlands - 1454, // CuraSao - 1462, // NewCaledonia - 1475, // NewZealand - 1486, // Nicaragua - 1496, // Niger - 1502, // Nigeria - 1510, // Niue - 1515, // NorfolkIsland - 1529, // NorthernMarianaIslands - 1552, // Norway - 1559, // Oman - 1564, // Pakistan - 1573, // Palau - 1579, // PalestinianTerritories - 1602, // Panama - 1609, // PapuaNewGuinea - 1624, // Paraguay - 1633, // Peru - 1638, // Philippines - 1650, // Pitcairn - 1659, // Poland - 1666, // Portugal - 1675, // PuertoRico - 1686, // Qatar - 1692, // Reunion - 1700, // Romania - 1708, // Russia - 1715, // Rwanda - 1722, // SaintKittsAndNevis - 1741, // SaintLucia - 1752, // SaintVincentAndTheGrenadines - 1781, // Samoa - 1787, // SanMarino - 1797, // SaoTomeAndPrincipe - 1816, // SaudiArabia - 1828, // Senegal - 1836, // Seychelles - 1847, // SierraLeone - 1859, // Singapore - 1869, // Slovakia - 1878, // Slovenia - 1887, // SolomonIslands - 1902, // Somalia - 1910, // SouthAfrica - 1922, // SouthGeorgiaAndTheSouthSandwichIslands - 1961, // Spain - 1967, // SriLanka - 1976, // SaintHelena - 1988, // SaintPierreAndMiquelon - 2011, // Sudan - 2017, // Suriname - 2026, // SvalbardAndJanMayenIslands - 2053, // Swaziland - 2063, // Sweden - 2070, // Switzerland - 2082, // Syria - 2088, // Taiwan - 2095, // Tajikistan - 2106, // Tanzania - 2115, // Thailand - 2124, // Togo - 2129, // Tokelau - 2137, // Tonga - 2143, // TrinidadAndTobago - 2161, // Tunisia - 2169, // Turkey - 2176, // Turkmenistan - 2189, // TurksAndCaicosIslands - 2211, // Tuvalu - 2218, // Uganda - 2225, // Ukraine - 2233, // UnitedArabEmirates - 2252, // UnitedKingdom - 2266, // UnitedStates - 2279, // UnitedStatesMinorOutlyingIslands - 2312, // Uruguay - 2320, // Uzbekistan - 2331, // Vanuatu - 2339, // VaticanCityState - 2356, // Venezuela - 2366, // Vietnam - 2374, // BritishVirginIslands - 2395, // UnitedStatesVirginIslands - 2421, // WallisAndFutunaIslands - 2444, // WesternSahara - 2458, // Yemen - 2464, // CanaryIslands - 2478, // Zambia - 2485, // Zimbabwe - 2494, // ClippertonIsland - 2511, // Montenegro - 2522, // Serbia - 2529, // Saint Barthelemy - 2546, // Saint Martin - 2559, // Latin America - 2573, // AscensionIsland - 2589, // AlandIslands - 2602, // DiegoGarcia - 2614, // CeutaAndMelilla - 2630, // IsleOfMan - 2640, // Jersey - 2647, // TristanDaCunha - 2662, // SouthSudan - 2673, // Bonaire - 2681, // SintMaarten - 2693, // Kosovo - 2700, // European Union - 2715, // Outlying Oceania - 2732, // World - 2738, // Europe + 36, // American Samoa + 51, // Andorra + 59, // Angola + 66, // Anguilla + 75, // Antarctica + 86, // Antigua And Barbuda + 106, // Argentina + 116, // Armenia + 124, // Aruba + 130, // Australia + 140, // Austria + 148, // Azerbaijan + 159, // Bahamas + 167, // Bahrain + 175, // Bangladesh + 186, // Barbados + 195, // Belarus + 203, // Belgium + 211, // Belize + 218, // Benin + 224, // Bermuda + 232, // Bhutan + 239, // Bolivia + 247, // Bosnia And Herzegowina + 270, // Botswana + 279, // Bouvet Island + 293, // Brazil + 300, // British Indian Ocean Territory + 331, // Brunei + 338, // Bulgaria + 347, // Burkina Faso + 360, // Burundi + 368, // Cambodia + 377, // Cameroon + 386, // Canada + 393, // Cape Verde + 404, // Cayman Islands + 419, // Central African Republic + 444, // Chad + 449, // Chile + 455, // China + 461, // Christmas Island + 478, // Cocos Islands + 492, // Colombia + 501, // Comoros + 509, // Congo Kinshasa + 524, // Congo Brazzaville + 542, // Cook Islands + 555, // Costa Rica + 566, // Ivory Coast + 578, // Croatia + 586, // Cuba + 591, // Cyprus + 598, // Czech Republic + 613, // Denmark + 621, // Djibouti + 630, // Dominica + 639, // Dominican Republic + 658, // East Timor + 669, // Ecuador + 677, // Egypt + 683, // El Salvador + 695, // Equatorial Guinea + 713, // Eritrea + 721, // Estonia + 729, // Ethiopia + 738, // Falkland Islands + 755, // Faroe Islands + 769, // Fiji + 774, // Finland + 782, // France + 789, // Guernsey + 798, // French Guiana + 812, // French Polynesia + 829, // French Southern Territories + 857, // Gabon + 863, // Gambia + 870, // Georgia + 878, // Germany + 886, // Ghana + 892, // Gibraltar + 902, // Greece + 909, // Greenland + 919, // Grenada + 927, // Guadeloupe + 938, // Guam + 943, // Guatemala + 953, // Guinea + 960, // Guinea Bissau + 974, // Guyana + 981, // Haiti + 987, // Heard And McDonald Islands + 1014, // Honduras + 1023, // Hong Kong + 1033, // Hungary + 1041, // Iceland + 1049, // India + 1055, // Indonesia + 1065, // Iran + 1070, // Iraq + 1075, // Ireland + 1083, // Israel + 1090, // Italy + 1096, // Jamaica + 1104, // Japan + 1110, // Jordan + 1117, // Kazakhstan + 1128, // Kenya + 1134, // Kiribati + 1143, // North Korea + 1155, // South Korea + 1167, // Kuwait + 1174, // Kyrgyzstan + 1185, // Laos + 1190, // Latvia + 1197, // Lebanon + 1205, // Lesotho + 1213, // Liberia + 1221, // Libya + 1227, // Liechtenstein + 1241, // Lithuania + 1251, // Luxembourg + 1262, // Macau + 1268, // Macedonia + 1278, // Madagascar + 1289, // Malawi + 1296, // Malaysia + 1305, // Maldives + 1314, // Mali + 1319, // Malta + 1325, // Marshall Islands + 1342, // Martinique + 1353, // Mauritania + 1364, // Mauritius + 1374, // Mayotte + 1382, // Mexico + 1389, // Micronesia + 1400, // Moldova + 1408, // Monaco + 1415, // Mongolia + 1424, // Montserrat + 1435, // Morocco + 1443, // Mozambique + 1454, // Myanmar + 1462, // Namibia + 1470, // Nauru + 1476, // Nepal + 1482, // Netherlands + 1494, // Cura Sao + 1503, // New Caledonia + 1517, // New Zealand + 1529, // Nicaragua + 1539, // Niger + 1545, // Nigeria + 1553, // Niue + 1558, // Norfolk Island + 1573, // Northern Mariana Islands + 1598, // Norway + 1605, // Oman + 1610, // Pakistan + 1619, // Palau + 1625, // Palestinian Territories + 1649, // Panama + 1656, // Papua New Guinea + 1673, // Paraguay + 1682, // Peru + 1687, // Philippines + 1699, // Pitcairn + 1708, // Poland + 1715, // Portugal + 1724, // Puerto Rico + 1736, // Qatar + 1742, // Reunion + 1750, // Romania + 1758, // Russia + 1765, // Rwanda + 1772, // Saint Kitts And Nevis + 1794, // Saint Lucia + 1806, // Saint Vincent And The Grenadines + 1839, // Samoa + 1845, // San Marino + 1856, // Sao Tome And Principe + 1878, // Saudi Arabia + 1891, // Senegal + 1899, // Seychelles + 1910, // Sierra Leone + 1923, // Singapore + 1933, // Slovakia + 1942, // Slovenia + 1951, // Solomon Islands + 1967, // Somalia + 1975, // South Africa + 1988, // South Georgia And The South Sandwich Islands + 2033, // Spain + 2039, // Sri Lanka + 2049, // Saint Helena + 2062, // Saint Pierre And Miquelon + 2088, // Sudan + 2094, // Suriname + 2103, // Svalbard And Jan Mayen Islands + 2134, // Swaziland + 2144, // Sweden + 2151, // Switzerland + 2163, // Syria + 2169, // Taiwan + 2176, // Tajikistan + 2187, // Tanzania + 2196, // Thailand + 2205, // Togo + 2210, // Tokelau + 2218, // Tonga + 2224, // Trinidad And Tobago + 2244, // Tunisia + 2252, // Turkey + 2259, // Turkmenistan + 2272, // Turks And Caicos Islands + 2297, // Tuvalu + 2304, // Uganda + 2311, // Ukraine + 2319, // United Arab Emirates + 2340, // United Kingdom + 2355, // United States + 2369, // United States Minor Outlying Islands + 2406, // Uruguay + 2414, // Uzbekistan + 2425, // Vanuatu + 2433, // Vatican City State + 2452, // Venezuela + 2462, // Vietnam + 2470, // British Virgin Islands + 2493, // United States Virgin Islands + 2522, // Wallis And Futuna Islands + 2548, // Western Sahara + 2563, // Yemen + 2569, // Canary Islands + 2584, // Zambia + 2591, // Zimbabwe + 2600, // Clipperton Island + 2618, // Montenegro + 2629, // Serbia + 2636, // Saint Barthelemy + 2653, // Saint Martin + 2666, // Latin America + 2680, // Ascension Island + 2697, // Aland Islands + 2711, // Diego Garcia + 2724, // Ceuta And Melilla + 2742, // Isle Of Man + 2754, // Jersey + 2761, // Tristan Da Cunha + 2778, // South Sudan + 2790, // Bonaire + 2798, // Sint Maarten + 2811, // Kosovo + 2818, // European Union + 2833, // Outlying Oceania + 2850, // World + 2856, // Europe }; static const unsigned char language_code_list[] = @@ -7938,7 +7938,7 @@ static const unsigned char language_code_list[] = "mn\0" // Mongolian "na\0" // Nauru "ne\0" // Nepali -"nb\0" // NorwegianBokmal +"nb\0" // Norwegian Bokmal "oc\0" // Occitan "or\0" // Oriya "ps\0" // Pashto @@ -7994,7 +7994,7 @@ static const unsigned char language_code_list[] = "yo\0" // Yoruba "za\0" // Zhuang "zu\0" // Zulu -"nn\0" // NorwegianNynorsk +"nn\0" // Norwegian Nynorsk "bs\0" // Bosnian "dv\0" // Divehi "gv\0" // Manx @@ -8083,7 +8083,7 @@ static const unsigned char language_code_list[] = "kg\0" // Kongo "kj\0" // Kwanyama "li\0" // Limburgish -"lu\0" // LubaKatanga +"lu\0" // Luba Katanga "lb\0" // Luxembourgish "nv\0" // Navaho "ng\0" // Ndonga @@ -8094,10 +8094,10 @@ static const unsigned char language_code_list[] = "bas" // Basaa "dje" // Zarma "dua" // Duala -"dyo" // JolaFonyi +"dyo" // Jola Fonyi "ewo" // Ewondo "ksf" // Bafia -"mgh" // MakhuwaMeetto +"mgh" // Makhuwa Meetto "mua" // Mundang "nmg" // Kwasio "nus" // Nuer @@ -8116,26 +8116,26 @@ static const unsigned char language_code_list[] = "nnh" // Ngiemboon "an\0" // Aragonese "akk" // Akkadian -"egy" // AncientEgyptian -"grc" // AncientGreek +"egy" // Ancient Egyptian +"grc" // Ancient Greek "arc" // Aramaic "ban" // Balinese "bax" // Bamun -"bbc" // BatakToba +"bbc" // Batak Toba "bug" // Buginese "bku" // Buhid "xcr" // Carian "ccp" // Chakma -"myz" // ClassicalMandaic +"myz" // Classical Mandaic "cop" // Coptic "doi" // Dogri -"cjm" // EasternCham -"eky" // EasternKayah +"cjm" // Eastern Cham +"eky" // Eastern Kayah "ett" // Etruscan "got" // Gothic "hnn" // Hanunoo "inh" // Ingush -"hmd" // LargeFloweryMiao +"hmd" // Large Flowery Miao "lep" // Lepcha "lif" // Limbu "lis" // Lisu @@ -8145,15 +8145,15 @@ static const unsigned char language_code_list[] = "man" // Mandingo "mni" // Manipuri "xmr" // Meroitic -"nod" // NorthernThai -"sga" // OldIrish -"non" // OldNorse -"peo" // OldPersian -"otk" // OldTurkish +"nod" // Northern Thai +"sga" // Old Irish +"non" // Old Norse +"peo" // Old Persian +"otk" // Old Turkish "pal" // Pahlavi "xpr" // Parthian "phn" // Phoenician -"pra" // PrakritLanguage +"pra" // Prakrit Language "rej" // Rejang "xsa" // Sabaean "smp" // Samaritan @@ -8162,16 +8162,16 @@ static const unsigned char language_code_list[] = "srb" // Sora "syl" // Sylheti "tbw" // Tagbanwa -"blt" // TaiDam -"tdd" // TaiNua +"blt" // Tai Dam +"tdd" // Tai Nua "uga" // Ugaritic "bss" // Akoose "lkt" // Lakota "zgh" // Standard Moroccan Tamazight "arn" // Mapuche "ckb" // Central Kurdish -"dsb" // LowerSorbian -"hsb" // UpperSorbian +"dsb" // Lower Sorbian +"hsb" // Upper Sorbian "ken" // Kenyang "moh" // Mohawk "nqo" // Nko @@ -8209,7 +8209,7 @@ static const unsigned char language_code_list[] = "tkl" // Tokelau "tpi" // Tok Pisin "tvl" // Tuvalu -"mis" // UncodedLanguages +"mis" // Uncoded Languages "yue" // Cantonese "osa" // Osage "txg" // Tangut @@ -8260,7 +8260,7 @@ static const unsigned char script_code_list[] = "Brah" // Brahmi "Bugi" // Buginese "Buhd" // Buhid -"Cans" // CanadianAboriginal +"Cans" // Canadian Aboriginal "Cari" // Carian "Cakm" // Chakma "Cham" // Cham @@ -8349,7 +8349,7 @@ static const unsigned char script_code_list[] = "Hatr" // Hatran "Mult" // Multani "Hung" // Old Hungarian -"Sgnw" // SignWriting +"Sgnw" // Sign Writing "Adlm" // Adlam "Bhks" // Bhaiksuki "Marc" // Marchen @@ -8364,12 +8364,12 @@ static const unsigned char country_code_list[] = "AF\0" // Afghanistan "AL\0" // Albania "DZ\0" // Algeria -"AS\0" // AmericanSamoa +"AS\0" // American Samoa "AD\0" // Andorra "AO\0" // Angola "AI\0" // Anguilla "AQ\0" // Antarctica -"AG\0" // AntiguaAndBarbuda +"AG\0" // Antigua And Barbuda "AR\0" // Argentina "AM\0" // Armenia "AW\0" // Aruba @@ -8387,58 +8387,58 @@ static const unsigned char country_code_list[] = "BM\0" // Bermuda "BT\0" // Bhutan "BO\0" // Bolivia -"BA\0" // BosniaAndHerzegowina +"BA\0" // Bosnia And Herzegowina "BW\0" // Botswana -"BV\0" // BouvetIsland +"BV\0" // Bouvet Island "BR\0" // Brazil -"IO\0" // BritishIndianOceanTerritory +"IO\0" // British Indian Ocean Territory "BN\0" // Brunei "BG\0" // Bulgaria -"BF\0" // BurkinaFaso +"BF\0" // Burkina Faso "BI\0" // Burundi "KH\0" // Cambodia "CM\0" // Cameroon "CA\0" // Canada -"CV\0" // CapeVerde -"KY\0" // CaymanIslands -"CF\0" // CentralAfricanRepublic +"CV\0" // Cape Verde +"KY\0" // Cayman Islands +"CF\0" // Central African Republic "TD\0" // Chad "CL\0" // Chile "CN\0" // China -"CX\0" // ChristmasIsland -"CC\0" // CocosIslands +"CX\0" // Christmas Island +"CC\0" // Cocos Islands "CO\0" // Colombia "KM\0" // Comoros -"CD\0" // CongoKinshasa -"CG\0" // CongoBrazzaville -"CK\0" // CookIslands -"CR\0" // CostaRica -"CI\0" // IvoryCoast +"CD\0" // Congo Kinshasa +"CG\0" // Congo Brazzaville +"CK\0" // Cook Islands +"CR\0" // Costa Rica +"CI\0" // Ivory Coast "HR\0" // Croatia "CU\0" // Cuba "CY\0" // Cyprus -"CZ\0" // CzechRepublic +"CZ\0" // Czech Republic "DK\0" // Denmark "DJ\0" // Djibouti "DM\0" // Dominica -"DO\0" // DominicanRepublic -"TL\0" // EastTimor +"DO\0" // Dominican Republic +"TL\0" // East Timor "EC\0" // Ecuador "EG\0" // Egypt -"SV\0" // ElSalvador -"GQ\0" // EquatorialGuinea +"SV\0" // El Salvador +"GQ\0" // Equatorial Guinea "ER\0" // Eritrea "EE\0" // Estonia "ET\0" // Ethiopia -"FK\0" // FalklandIslands -"FO\0" // FaroeIslands +"FK\0" // Falkland Islands +"FO\0" // Faroe Islands "FJ\0" // Fiji "FI\0" // Finland "FR\0" // France "GG\0" // Guernsey -"GF\0" // FrenchGuiana -"PF\0" // FrenchPolynesia -"TF\0" // FrenchSouthernTerritories +"GF\0" // French Guiana +"PF\0" // French Polynesia +"TF\0" // French Southern Territories "GA\0" // Gabon "GM\0" // Gambia "GE\0" // Georgia @@ -8452,12 +8452,12 @@ static const unsigned char country_code_list[] = "GU\0" // Guam "GT\0" // Guatemala "GN\0" // Guinea -"GW\0" // GuineaBissau +"GW\0" // Guinea Bissau "GY\0" // Guyana "HT\0" // Haiti -"HM\0" // HeardAndMcDonaldIslands +"HM\0" // Heard And McDonald Islands "HN\0" // Honduras -"HK\0" // HongKong +"HK\0" // Hong Kong "HU\0" // Hungary "IS\0" // Iceland "IN\0" // India @@ -8473,8 +8473,8 @@ static const unsigned char country_code_list[] = "KZ\0" // Kazakhstan "KE\0" // Kenya "KI\0" // Kiribati -"KP\0" // NorthKorea -"KR\0" // SouthKorea +"KP\0" // North Korea +"KR\0" // South Korea "KW\0" // Kuwait "KG\0" // Kyrgyzstan "LA\0" // Laos @@ -8494,7 +8494,7 @@ static const unsigned char country_code_list[] = "MV\0" // Maldives "ML\0" // Mali "MT\0" // Malta -"MH\0" // MarshallIslands +"MH\0" // Marshall Islands "MQ\0" // Martinique "MR\0" // Mauritania "MU\0" // Mauritius @@ -8512,58 +8512,58 @@ static const unsigned char country_code_list[] = "NR\0" // Nauru "NP\0" // Nepal "NL\0" // Netherlands -"CW\0" // CuraSao -"NC\0" // NewCaledonia -"NZ\0" // NewZealand +"CW\0" // Cura Sao +"NC\0" // New Caledonia +"NZ\0" // New Zealand "NI\0" // Nicaragua "NE\0" // Niger "NG\0" // Nigeria "NU\0" // Niue -"NF\0" // NorfolkIsland -"MP\0" // NorthernMarianaIslands +"NF\0" // Norfolk Island +"MP\0" // Northern Mariana Islands "NO\0" // Norway "OM\0" // Oman "PK\0" // Pakistan "PW\0" // Palau -"PS\0" // PalestinianTerritories +"PS\0" // Palestinian Territories "PA\0" // Panama -"PG\0" // PapuaNewGuinea +"PG\0" // Papua New Guinea "PY\0" // Paraguay "PE\0" // Peru "PH\0" // Philippines "PN\0" // Pitcairn "PL\0" // Poland "PT\0" // Portugal -"PR\0" // PuertoRico +"PR\0" // Puerto Rico "QA\0" // Qatar "RE\0" // Reunion "RO\0" // Romania "RU\0" // Russia "RW\0" // Rwanda -"KN\0" // SaintKittsAndNevis -"LC\0" // SaintLucia -"VC\0" // SaintVincentAndTheGrenadines +"KN\0" // Saint Kitts And Nevis +"LC\0" // Saint Lucia +"VC\0" // Saint Vincent And The Grenadines "WS\0" // Samoa -"SM\0" // SanMarino -"ST\0" // SaoTomeAndPrincipe -"SA\0" // SaudiArabia +"SM\0" // San Marino +"ST\0" // Sao Tome And Principe +"SA\0" // Saudi Arabia "SN\0" // Senegal "SC\0" // Seychelles -"SL\0" // SierraLeone +"SL\0" // Sierra Leone "SG\0" // Singapore "SK\0" // Slovakia "SI\0" // Slovenia -"SB\0" // SolomonIslands +"SB\0" // Solomon Islands "SO\0" // Somalia -"ZA\0" // SouthAfrica -"GS\0" // SouthGeorgiaAndTheSouthSandwichIslands +"ZA\0" // South Africa +"GS\0" // South Georgia And The South Sandwich Islands "ES\0" // Spain -"LK\0" // SriLanka -"SH\0" // SaintHelena -"PM\0" // SaintPierreAndMiquelon +"LK\0" // Sri Lanka +"SH\0" // Saint Helena +"PM\0" // Saint Pierre And Miquelon "SD\0" // Sudan "SR\0" // Suriname -"SJ\0" // SvalbardAndJanMayenIslands +"SJ\0" // Svalbard And Jan Mayen Islands "SZ\0" // Swaziland "SE\0" // Sweden "CH\0" // Switzerland @@ -8575,48 +8575,48 @@ static const unsigned char country_code_list[] = "TG\0" // Togo "TK\0" // Tokelau "TO\0" // Tonga -"TT\0" // TrinidadAndTobago +"TT\0" // Trinidad And Tobago "TN\0" // Tunisia "TR\0" // Turkey "TM\0" // Turkmenistan -"TC\0" // TurksAndCaicosIslands +"TC\0" // Turks And Caicos Islands "TV\0" // Tuvalu "UG\0" // Uganda "UA\0" // Ukraine -"AE\0" // UnitedArabEmirates -"GB\0" // UnitedKingdom -"US\0" // UnitedStates -"UM\0" // UnitedStatesMinorOutlyingIslands +"AE\0" // United Arab Emirates +"GB\0" // United Kingdom +"US\0" // United States +"UM\0" // United States Minor Outlying Islands "UY\0" // Uruguay "UZ\0" // Uzbekistan "VU\0" // Vanuatu -"VA\0" // VaticanCityState +"VA\0" // Vatican City State "VE\0" // Venezuela "VN\0" // Vietnam -"VG\0" // BritishVirginIslands -"VI\0" // UnitedStatesVirginIslands -"WF\0" // WallisAndFutunaIslands -"EH\0" // WesternSahara +"VG\0" // British Virgin Islands +"VI\0" // United States Virgin Islands +"WF\0" // Wallis And Futuna Islands +"EH\0" // Western Sahara "YE\0" // Yemen -"IC\0" // CanaryIslands +"IC\0" // Canary Islands "ZM\0" // Zambia "ZW\0" // Zimbabwe -"CP\0" // ClippertonIsland +"CP\0" // Clipperton Island "ME\0" // Montenegro "RS\0" // Serbia "BL\0" // Saint Barthelemy "MF\0" // Saint Martin "419" // Latin America -"AC\0" // AscensionIsland -"AX\0" // AlandIslands -"DG\0" // DiegoGarcia -"EA\0" // CeutaAndMelilla -"IM\0" // IsleOfMan +"AC\0" // Ascension Island +"AX\0" // Aland Islands +"DG\0" // Diego Garcia +"EA\0" // Ceuta And Melilla +"IM\0" // Isle Of Man "JE\0" // Jersey -"TA\0" // TristanDaCunha -"SS\0" // SouthSudan +"TA\0" // Tristan Da Cunha +"SS\0" // South Sudan "BQ\0" // Bonaire -"SX\0" // SintMaarten +"SX\0" // Sint Maarten "XK\0" // Kosovo "EU\0" // European Union "QO\0" // Outlying Oceania diff --git a/util/local_database/enumdata.py b/util/local_database/enumdata.py index d8f6453d31..5505b68575 100644 --- a/util/local_database/enumdata.py +++ b/util/local_database/enumdata.py @@ -33,776 +33,776 @@ ### Qt 6: restore alphabetic order in each list. language_list = { - 0 : [ "AnyLanguage", " " ], - 1 : [ "C", " " ], - 2 : [ "Abkhazian", "ab" ], - 3 : [ "Oromo", "om" ], # macrolanguage - 4 : [ "Afar", "aa" ], - 5 : [ "Afrikaans", "af" ], - 6 : [ "Albanian", "sq" ], # macrolanguage - 7 : [ "Amharic", "am" ], - 8 : [ "Arabic", "ar" ], # macrolanguage - 9 : [ "Armenian", "hy" ], - 10 : [ "Assamese", "as" ], - 11 : [ "Aymara", "ay" ], # macrolanguage - 12 : [ "Azerbaijani", "az" ], # macrolanguage - 13 : [ "Bashkir", "ba" ], - 14 : [ "Basque", "eu" ], - 15 : [ "Bengali", "bn" ], - 16 : [ "Dzongkha", "dz" ], - 17 : [ "Bihari", "bh" ], - 18 : [ "Bislama", "bi" ], - 19 : [ "Breton", "br" ], - 20 : [ "Bulgarian", "bg" ], - 21 : [ "Burmese", "my" ], - 22 : [ "Belarusian", "be" ], - 23 : [ "Khmer", "km" ], - 24 : [ "Catalan", "ca" ], - 25 : [ "Chinese", "zh" ], # macrolanguage - 26 : [ "Corsican", "co" ], - 27 : [ "Croatian", "hr" ], - 28 : [ "Czech", "cs" ], - 29 : [ "Danish", "da" ], - 30 : [ "Dutch", "nl" ], - 31 : [ "English", "en" ], - 32 : [ "Esperanto", "eo" ], - 33 : [ "Estonian", "et" ], # macrolanguage - 34 : [ "Faroese", "fo" ], - 35 : [ "Fijian", "fj" ], - 36 : [ "Finnish", "fi" ], - 37 : [ "French", "fr" ], - 38 : [ "Western Frisian", "fy" ], - 39 : [ "Gaelic", "gd" ], - 40 : [ "Galician", "gl" ], - 41 : [ "Georgian", "ka" ], - 42 : [ "German", "de" ], - 43 : [ "Greek", "el" ], - 44 : [ "Greenlandic", "kl" ], - 45 : [ "Guarani", "gn" ], # macrolanguage - 46 : [ "Gujarati", "gu" ], - 47 : [ "Hausa", "ha" ], - 48 : [ "Hebrew", "he" ], - 49 : [ "Hindi", "hi" ], - 50 : [ "Hungarian", "hu" ], - 51 : [ "Icelandic", "is" ], - 52 : [ "Indonesian", "id" ], - 53 : [ "Interlingua", "ia" ], - 54 : [ "Interlingue", "ie" ], - 55 : [ "Inuktitut", "iu" ], # macrolanguage - 56 : [ "Inupiak", "ik" ], # macrolanguage - 57 : [ "Irish", "ga" ], - 58 : [ "Italian", "it" ], - 59 : [ "Japanese", "ja" ], - 60 : [ "Javanese", "jv" ], - 61 : [ "Kannada", "kn" ], - 62 : [ "Kashmiri", "ks" ], - 63 : [ "Kazakh", "kk" ], - 64 : [ "Kinyarwanda", "rw" ], - 65 : [ "Kirghiz", "ky" ], - 66 : [ "Korean", "ko" ], - 67 : [ "Kurdish", "ku" ], # macrolanguage - 68 : [ "Rundi", "rn" ], - 69 : [ "Lao", "lo" ], - 70 : [ "Latin", "la" ], - 71 : [ "Latvian", "lv" ], # macrolanguage - 72 : [ "Lingala", "ln" ], - 73 : [ "Lithuanian", "lt" ], - 74 : [ "Macedonian", "mk" ], - 75 : [ "Malagasy", "mg" ], # macrolanguage - 76 : [ "Malay", "ms" ], # macrolanguage - 77 : [ "Malayalam", "ml" ], - 78 : [ "Maltese", "mt" ], - 79 : [ "Maori", "mi" ], - 80 : [ "Marathi", "mr" ], - 81 : [ "Marshallese", "mh" ], - 82 : [ "Mongolian", "mn" ], # macrolanguage - 83 : [ "Nauru", "na" ], - 84 : [ "Nepali", "ne" ], # macrolanguage - 85 : [ "NorwegianBokmal", "nb" ], - 86 : [ "Occitan", "oc" ], - 87 : [ "Oriya", "or" ], # macrolanguage - 88 : [ "Pashto", "ps" ], # macrolanguage - 89 : [ "Persian", "fa" ], # macrolanguage - 90 : [ "Polish", "pl" ], - 91 : [ "Portuguese", "pt" ], - 92 : [ "Punjabi", "pa" ], - 93 : [ "Quechua", "qu" ], # macrolanguage - 94 : [ "Romansh", "rm" ], - 95 : [ "Romanian", "ro" ], - 96 : [ "Russian", "ru" ], - 97 : [ "Samoan", "sm" ], - 98 : [ "Sango", "sg" ], - 99 : [ "Sanskrit", "sa" ], - 100 : [ "Serbian", "sr" ], - 101 : [ "Ossetic", "os" ], - 102 : [ "Southern Sotho", "st" ], - 103 : [ "Tswana", "tn" ], - 104 : [ "Shona", "sn" ], - 105 : [ "Sindhi", "sd" ], - 106 : [ "Sinhala", "si" ], - 107 : [ "Swati", "ss" ], - 108 : [ "Slovak", "sk" ], - 109 : [ "Slovenian", "sl" ], - 110 : [ "Somali", "so" ], - 111 : [ "Spanish", "es" ], - 112 : [ "Sundanese", "su" ], - 113 : [ "Swahili", "sw" ], # macrolanguage - 114 : [ "Swedish", "sv" ], - 115 : [ "Sardinian", "sc" ], # macrolanguage - 116 : [ "Tajik", "tg" ], - 117 : [ "Tamil", "ta" ], - 118 : [ "Tatar", "tt" ], - 119 : [ "Telugu", "te" ], - 120 : [ "Thai", "th" ], - 121 : [ "Tibetan", "bo" ], - 122 : [ "Tigrinya", "ti" ], - 123 : [ "Tongan", "to" ], - 124 : [ "Tsonga", "ts" ], - 125 : [ "Turkish", "tr" ], - 126 : [ "Turkmen", "tk" ], - 127 : [ "Tahitian", "ty" ], - 128 : [ "Uighur", "ug" ], - 129 : [ "Ukrainian", "uk" ], - 130 : [ "Urdu", "ur" ], - 131 : [ "Uzbek", "uz" ], # macrolanguage - 132 : [ "Vietnamese", "vi" ], - 133 : [ "Volapuk", "vo" ], - 134 : [ "Welsh", "cy" ], - 135 : [ "Wolof", "wo" ], - 136 : [ "Xhosa", "xh" ], - 137 : [ "Yiddish", "yi" ], # macrolanguage - 138 : [ "Yoruba", "yo" ], - 139 : [ "Zhuang", "za" ], # macrolanguage - 140 : [ "Zulu", "zu" ], - 141 : [ "NorwegianNynorsk", "nn" ], - 142 : [ "Bosnian", "bs" ], - 143 : [ "Divehi", "dv" ], - 144 : [ "Manx", "gv" ], - 145 : [ "Cornish", "kw" ], - 146 : [ "Akan", "ak" ], # macrolanguage - 147 : [ "Konkani", "kok" ], - 148 : [ "Ga", "gaa" ], - 149 : [ "Igbo", "ig" ], - 150 : [ "Kamba", "kam" ], - 151 : [ "Syriac", "syr" ], - 152 : [ "Blin", "byn" ], - 153 : [ "Geez", "gez" ], - 154 : [ "Koro", "kfo" ], - 155 : [ "Sidamo", "sid" ], - 156 : [ "Atsam", "cch" ], - 157 : [ "Tigre", "tig" ], - 158 : [ "Jju", "kaj" ], - 159 : [ "Friulian", "fur" ], - 160 : [ "Venda", "ve" ], - 161 : [ "Ewe", "ee" ], - 162 : [ "Walamo", "wal" ], - 163 : [ "Hawaiian", "haw" ], - 164 : [ "Tyap", "kcg" ], - 165 : [ "Nyanja", "ny" ], - 166 : [ "Filipino", "fil" ], - 167 : [ "Swiss German", "gsw" ], - 168 : [ "Sichuan Yi", "ii" ], - 169 : [ "Kpelle", "kpe" ], - 170 : [ "Low German", "nds" ], - 171 : [ "South Ndebele", "nr" ], - 172 : [ "Northern Sotho", "nso" ], - 173 : [ "Northern Sami", "se" ], - 174 : [ "Taroko", "trv" ], - 175 : [ "Gusii", "guz" ], - 176 : [ "Taita", "dav" ], - 177 : [ "Fulah", "ff" ], # macrolanguage - 178 : [ "Kikuyu", "ki" ], - 179 : [ "Samburu", "saq" ], - 180 : [ "Sena", "seh" ], - 181 : [ "North Ndebele", "nd" ], - 182 : [ "Rombo", "rof" ], - 183 : [ "Tachelhit", "shi" ], - 184 : [ "Kabyle", "kab" ], - 185 : [ "Nyankole", "nyn" ], - 186 : [ "Bena", "bez" ], - 187 : [ "Vunjo", "vun" ], - 188 : [ "Bambara", "bm" ], - 189 : [ "Embu", "ebu" ], - 190 : [ "Cherokee", "chr" ], - 191 : [ "Morisyen", "mfe" ], - 192 : [ "Makonde", "kde" ], - 193 : [ "Langi", "lag" ], - 194 : [ "Ganda", "lg" ], - 195 : [ "Bemba", "bem" ], - 196 : [ "Kabuverdianu", "kea" ], - 197 : [ "Meru", "mer" ], - 198 : [ "Kalenjin", "kln" ], - 199 : [ "Nama", "naq" ], - 200 : [ "Machame", "jmc" ], - 201 : [ "Colognian", "ksh" ], - 202 : [ "Masai", "mas" ], - 203 : [ "Soga", "xog" ], - 204 : [ "Luyia", "luy" ], - 205 : [ "Asu", "asa" ], - 206 : [ "Teso", "teo" ], - 207 : [ "Saho", "ssy" ], - 208 : [ "Koyra Chiini", "khq" ], - 209 : [ "Rwa", "rwk" ], - 210 : [ "Luo", "luo" ], - 211 : [ "Chiga", "cgg" ], - 212 : [ "Central Morocco Tamazight", "tzm" ], - 213 : [ "Koyraboro Senni", "ses" ], - 214 : [ "Shambala", "ksb" ], - 215 : [ "Bodo", "brx" ], - 216 : [ "Avaric", "av" ], - 217 : [ "Chamorro", "ch" ], - 218 : [ "Chechen", "ce" ], - 219 : [ "Church", "cu" ], # macrolanguage - 220 : [ "Chuvash", "cv" ], - 221 : [ "Cree", "cr" ], # macrolanguage - 222 : [ "Haitian", "ht" ], - 223 : [ "Herero", "hz" ], - 224 : [ "Hiri Motu", "ho" ], - 225 : [ "Kanuri", "kr" ], # macrolanguage - 226 : [ "Komi", "kv" ], # macrolanguage - 227 : [ "Kongo", "kg" ], # macrolanguage - 228 : [ "Kwanyama", "kj" ], - 229 : [ "Limburgish", "li" ], - 230 : [ "LubaKatanga", "lu" ], - 231 : [ "Luxembourgish", "lb" ], - 232 : [ "Navaho", "nv" ], - 233 : [ "Ndonga", "ng" ], - 234 : [ "Ojibwa", "oj" ], # macrolanguage - 235 : [ "Pali", "pi" ], # macrolanguage - 236 : [ "Walloon", "wa" ], - 237 : [ "Aghem", "agq" ], - 238 : [ "Basaa", "bas" ], - 239 : [ "Zarma", "dje" ], - 240 : [ "Duala", "dua" ], - 241 : [ "JolaFonyi", "dyo" ], - 242 : [ "Ewondo", "ewo" ], - 243 : [ "Bafia", "ksf" ], - 244 : [ "MakhuwaMeetto", "mgh" ], - 245 : [ "Mundang", "mua" ], - 246 : [ "Kwasio", "nmg" ], - 247 : [ "Nuer", "nus" ], - 248 : [ "Sakha", "sah" ], - 249 : [ "Sangu", "sbp" ], - 250 : [ "Congo Swahili", "swc" ], - 251 : [ "Tasawaq", "twq" ], - 252 : [ "Vai", "vai" ], - 253 : [ "Walser", "wae" ], - 254 : [ "Yangben", "yav" ], - 255 : [ "Avestan", "ae" ], - 256 : [ "Asturian", "ast" ], - 257 : [ "Ngomba", "jgo" ], - 258 : [ "Kako", "kkj" ], - 259 : [ "Meta", "mgo" ], - 260 : [ "Ngiemboon", "nnh" ], - 261 : [ "Aragonese", "an" ], - 262 : [ "Akkadian", "akk" ], - 263 : [ "AncientEgyptian", "egy" ], - 264 : [ "AncientGreek", "grc" ], - 265 : [ "Aramaic", "arc" ], - 266 : [ "Balinese", "ban" ], - 267 : [ "Bamun", "bax" ], - 268 : [ "BatakToba", "bbc" ], - 269 : [ "Buginese", "bug" ], - 270 : [ "Buhid", "bku" ], - 271 : [ "Carian", "xcr" ], - 272 : [ "Chakma", "ccp" ], - 273 : [ "ClassicalMandaic", "myz" ], - 274 : [ "Coptic", "cop" ], - 275 : [ "Dogri", "doi" ], # macrolanguage - 276 : [ "EasternCham", "cjm" ], - 277 : [ "EasternKayah", "eky" ], - 278 : [ "Etruscan", "ett" ], - 279 : [ "Gothic", "got" ], - 280 : [ "Hanunoo", "hnn" ], - 281 : [ "Ingush", "inh" ], - 282 : [ "LargeFloweryMiao", "hmd" ], - 283 : [ "Lepcha", "lep" ], - 284 : [ "Limbu", "lif" ], - 285 : [ "Lisu", "lis" ], - 286 : [ "Lu", "khb" ], - 287 : [ "Lycian", "xlc" ], - 288 : [ "Lydian", "xld" ], - 289 : [ "Mandingo", "man" ], # macrolanguage - 290 : [ "Manipuri", "mni" ], - 291 : [ "Meroitic", "xmr" ], - 292 : [ "NorthernThai", "nod" ], - 293 : [ "OldIrish", "sga" ], - 294 : [ "OldNorse", "non" ], - 295 : [ "OldPersian", "peo" ], - 296 : [ "OldTurkish", "otk" ], - 297 : [ "Pahlavi", "pal" ], - 298 : [ "Parthian", "xpr" ], - 299 : [ "Phoenician", "phn" ], - 300 : [ "PrakritLanguage", "pra" ], - 301 : [ "Rejang", "rej" ], - 302 : [ "Sabaean", "xsa" ], - 303 : [ "Samaritan", "smp" ], - 304 : [ "Santali", "sat" ], - 305 : [ "Saurashtra", "saz" ], - 306 : [ "Sora", "srb" ], - 307 : [ "Sylheti", "syl" ], - 308 : [ "Tagbanwa", "tbw" ], - 309 : [ "TaiDam", "blt" ], - 310 : [ "TaiNua", "tdd" ], - 311 : [ "Ugaritic", "uga" ], - 312 : [ "Akoose", "bss" ], - 313 : [ "Lakota", "lkt" ], - 314 : [ "Standard Moroccan Tamazight", "zgh" ], - 315 : [ "Mapuche", "arn" ], - 316 : [ "Central Kurdish", "ckb" ], - 317 : [ "LowerSorbian", "dsb" ], - 318 : [ "UpperSorbian", "hsb" ], - 319 : [ "Kenyang", "ken" ], - 320 : [ "Mohawk", "moh" ], - 321 : [ "Nko", "nqo" ], - 322 : [ "Prussian", "prg" ], - 323 : [ "Kiche", "quc" ], - 324 : [ "Southern Sami", "sma" ], - 325 : [ "Lule Sami", "smj" ], - 326 : [ "Inari Sami", "smn" ], - 327 : [ "Skolt Sami", "sms" ], - 328 : [ "Warlpiri", "wbp" ], - 329 : [ "Manichaean Middle Persian", "xmn" ], - 330 : [ "Mende", "men" ], - 331 : [ "Ancient North Arabian", "xna" ], - 332 : [ "Linear A", "lab" ], - 333 : [ "Hmong Njua", "hnj" ], - 334 : [ "Ho", "hoc" ], - 335 : [ "Lezghian", "lez" ], - 336 : [ "Bassa", "bsq" ], - 337 : [ "Mono", "mru" ], - 338 : [ "Tedim Chin", "ctd" ], - 339 : [ "Maithili", "mai" ], - 340 : [ "Ahom", "aho" ], - 341 : [ "American Sign Language", "ase" ], - 342 : [ "Ardhamagadhi Prakrit", "pka" ], - 343 : [ "Bhojpuri", "bho" ], - 344 : [ "Hieroglyphic Luwian", "hlu" ], - 345 : [ "Literary Chinese", "lzh" ], - 346 : [ "Mazanderani", "mzn" ], - 347 : [ "Mru", "mro" ], - 348 : [ "Newari", "new" ], - 349 : [ "Northern Luri", "lrc" ], - 350 : [ "Palauan", "pau" ], - 351 : [ "Papiamento", "pap" ], - 352 : [ "Saraiki", "skr" ], - 353 : [ "Tokelau", "tkl" ], - 354 : [ "Tok Pisin", "tpi" ], - 355 : [ "Tuvalu", "tvl" ], - 356 : [ "UncodedLanguages", "mis" ], - 357 : [ "Cantonese", "yue" ], - 358 : [ "Osage", "osa" ], - 359 : [ "Tangut", "txg" ] + 0 : ["AnyLanguage", " "], + 1 : ["C", " "], + 2 : ["Abkhazian", "ab"], + 3 : ["Oromo", "om"], # macrolanguage + 4 : ["Afar", "aa"], + 5 : ["Afrikaans", "af"], + 6 : ["Albanian", "sq"], # macrolanguage + 7 : ["Amharic", "am"], + 8 : ["Arabic", "ar"], # macrolanguage + 9 : ["Armenian", "hy"], + 10 : ["Assamese", "as"], + 11 : ["Aymara", "ay"], # macrolanguage + 12 : ["Azerbaijani", "az"], # macrolanguage + 13 : ["Bashkir", "ba"], + 14 : ["Basque", "eu"], + 15 : ["Bengali", "bn"], + 16 : ["Dzongkha", "dz"], + 17 : ["Bihari", "bh"], + 18 : ["Bislama", "bi"], + 19 : ["Breton", "br"], + 20 : ["Bulgarian", "bg"], + 21 : ["Burmese", "my"], + 22 : ["Belarusian", "be"], + 23 : ["Khmer", "km"], + 24 : ["Catalan", "ca"], + 25 : ["Chinese", "zh"], # macrolanguage + 26 : ["Corsican", "co"], + 27 : ["Croatian", "hr"], + 28 : ["Czech", "cs"], + 29 : ["Danish", "da"], + 30 : ["Dutch", "nl"], + 31 : ["English", "en"], + 32 : ["Esperanto", "eo"], + 33 : ["Estonian", "et"], # macrolanguage + 34 : ["Faroese", "fo"], + 35 : ["Fijian", "fj"], + 36 : ["Finnish", "fi"], + 37 : ["French", "fr"], + 38 : ["Western Frisian", "fy"], + 39 : ["Gaelic", "gd"], + 40 : ["Galician", "gl"], + 41 : ["Georgian", "ka"], + 42 : ["German", "de"], + 43 : ["Greek", "el"], + 44 : ["Greenlandic", "kl"], + 45 : ["Guarani", "gn"], # macrolanguage + 46 : ["Gujarati", "gu"], + 47 : ["Hausa", "ha"], + 48 : ["Hebrew", "he"], + 49 : ["Hindi", "hi"], + 50 : ["Hungarian", "hu"], + 51 : ["Icelandic", "is"], + 52 : ["Indonesian", "id"], + 53 : ["Interlingua", "ia"], + 54 : ["Interlingue", "ie"], + 55 : ["Inuktitut", "iu"], # macrolanguage + 56 : ["Inupiak", "ik"], # macrolanguage + 57 : ["Irish", "ga"], + 58 : ["Italian", "it"], + 59 : ["Japanese", "ja"], + 60 : ["Javanese", "jv"], + 61 : ["Kannada", "kn"], + 62 : ["Kashmiri", "ks"], + 63 : ["Kazakh", "kk"], + 64 : ["Kinyarwanda", "rw"], + 65 : ["Kirghiz", "ky"], + 66 : ["Korean", "ko"], + 67 : ["Kurdish", "ku"], # macrolanguage + 68 : ["Rundi", "rn"], + 69 : ["Lao", "lo"], + 70 : ["Latin", "la"], + 71 : ["Latvian", "lv"], # macrolanguage + 72 : ["Lingala", "ln"], + 73 : ["Lithuanian", "lt"], + 74 : ["Macedonian", "mk"], + 75 : ["Malagasy", "mg"], # macrolanguage + 76 : ["Malay", "ms"], # macrolanguage + 77 : ["Malayalam", "ml"], + 78 : ["Maltese", "mt"], + 79 : ["Maori", "mi"], + 80 : ["Marathi", "mr"], + 81 : ["Marshallese", "mh"], + 82 : ["Mongolian", "mn"], # macrolanguage + 83 : ["Nauru", "na"], + 84 : ["Nepali", "ne"], # macrolanguage + 85 : ["Norwegian Bokmal", "nb"], + 86 : ["Occitan", "oc"], + 87 : ["Oriya", "or"], # macrolanguage + 88 : ["Pashto", "ps"], # macrolanguage + 89 : ["Persian", "fa"], # macrolanguage + 90 : ["Polish", "pl"], + 91 : ["Portuguese", "pt"], + 92 : ["Punjabi", "pa"], + 93 : ["Quechua", "qu"], # macrolanguage + 94 : ["Romansh", "rm"], + 95 : ["Romanian", "ro"], + 96 : ["Russian", "ru"], + 97 : ["Samoan", "sm"], + 98 : ["Sango", "sg"], + 99 : ["Sanskrit", "sa"], + 100 : ["Serbian", "sr"], + 101 : ["Ossetic", "os"], + 102 : ["Southern Sotho", "st"], + 103 : ["Tswana", "tn"], + 104 : ["Shona", "sn"], + 105 : ["Sindhi", "sd"], + 106 : ["Sinhala", "si"], + 107 : ["Swati", "ss"], + 108 : ["Slovak", "sk"], + 109 : ["Slovenian", "sl"], + 110 : ["Somali", "so"], + 111 : ["Spanish", "es"], + 112 : ["Sundanese", "su"], + 113 : ["Swahili", "sw"], # macrolanguage + 114 : ["Swedish", "sv"], + 115 : ["Sardinian", "sc"], # macrolanguage + 116 : ["Tajik", "tg"], + 117 : ["Tamil", "ta"], + 118 : ["Tatar", "tt"], + 119 : ["Telugu", "te"], + 120 : ["Thai", "th"], + 121 : ["Tibetan", "bo"], + 122 : ["Tigrinya", "ti"], + 123 : ["Tongan", "to"], + 124 : ["Tsonga", "ts"], + 125 : ["Turkish", "tr"], + 126 : ["Turkmen", "tk"], + 127 : ["Tahitian", "ty"], + 128 : ["Uighur", "ug"], + 129 : ["Ukrainian", "uk"], + 130 : ["Urdu", "ur"], + 131 : ["Uzbek", "uz"], # macrolanguage + 132 : ["Vietnamese", "vi"], + 133 : ["Volapuk", "vo"], + 134 : ["Welsh", "cy"], + 135 : ["Wolof", "wo"], + 136 : ["Xhosa", "xh"], + 137 : ["Yiddish", "yi"], # macrolanguage + 138 : ["Yoruba", "yo"], + 139 : ["Zhuang", "za"], # macrolanguage + 140 : ["Zulu", "zu"], + 141 : ["Norwegian Nynorsk", "nn"], + 142 : ["Bosnian", "bs"], + 143 : ["Divehi", "dv"], + 144 : ["Manx", "gv"], + 145 : ["Cornish", "kw"], + 146 : ["Akan", "ak"], # macrolanguage + 147 : ["Konkani", "kok"], + 148 : ["Ga", "gaa"], + 149 : ["Igbo", "ig" ], + 150 : ["Kamba", "kam"], + 151 : ["Syriac", "syr"], + 152 : ["Blin", "byn"], + 153 : ["Geez", "gez"], + 154 : ["Koro", "kfo"], + 155 : ["Sidamo", "sid"], + 156 : ["Atsam", "cch"], + 157 : ["Tigre", "tig"], + 158 : ["Jju", "kaj"], + 159 : ["Friulian", "fur"], + 160 : ["Venda", "ve" ], + 161 : ["Ewe", "ee" ], + 162 : ["Walamo", "wal"], + 163 : ["Hawaiian", "haw"], + 164 : ["Tyap", "kcg"], + 165 : ["Nyanja", "ny" ], + 166 : ["Filipino", "fil"], + 167 : ["Swiss German", "gsw"], + 168 : ["Sichuan Yi", "ii" ], + 169 : ["Kpelle", "kpe"], + 170 : ["Low German", "nds"], + 171 : ["South Ndebele", "nr" ], + 172 : ["Northern Sotho", "nso"], + 173 : ["Northern Sami", "se" ], + 174 : ["Taroko", "trv"], + 175 : ["Gusii", "guz"], + 176 : ["Taita", "dav"], + 177 : ["Fulah", "ff"], # macrolanguage + 178 : ["Kikuyu", "ki"], + 179 : ["Samburu", "saq"], + 180 : ["Sena", "seh"], + 181 : ["North Ndebele", "nd"], + 182 : ["Rombo", "rof"], + 183 : ["Tachelhit", "shi"], + 184 : ["Kabyle", "kab"], + 185 : ["Nyankole", "nyn"], + 186 : ["Bena", "bez"], + 187 : ["Vunjo", "vun"], + 188 : ["Bambara", "bm"], + 189 : ["Embu", "ebu"], + 190 : ["Cherokee", "chr"], + 191 : ["Morisyen", "mfe"], + 192 : ["Makonde", "kde"], + 193 : ["Langi", "lag"], + 194 : ["Ganda", "lg"], + 195 : ["Bemba", "bem"], + 196 : ["Kabuverdianu", "kea"], + 197 : ["Meru", "mer"], + 198 : ["Kalenjin", "kln"], + 199 : ["Nama", "naq"], + 200 : ["Machame", "jmc"], + 201 : ["Colognian", "ksh"], + 202 : ["Masai", "mas"], + 203 : ["Soga", "xog"], + 204 : ["Luyia", "luy"], + 205 : ["Asu", "asa"], + 206 : ["Teso", "teo"], + 207 : ["Saho", "ssy"], + 208 : ["Koyra Chiini", "khq"], + 209 : ["Rwa", "rwk"], + 210 : ["Luo", "luo"], + 211 : ["Chiga", "cgg"], + 212 : ["Central Morocco Tamazight", "tzm"], + 213 : ["Koyraboro Senni", "ses"], + 214 : ["Shambala", "ksb"], + 215 : ["Bodo", "brx"], + 216 : ["Avaric", "av"], + 217 : ["Chamorro", "ch"], + 218 : ["Chechen", "ce"], + 219 : ["Church", "cu"], # macrolanguage + 220 : ["Chuvash", "cv"], + 221 : ["Cree", "cr"], # macrolanguage + 222 : ["Haitian", "ht"], + 223 : ["Herero", "hz"], + 224 : ["Hiri Motu", "ho"], + 225 : ["Kanuri", "kr"], # macrolanguage + 226 : ["Komi", "kv"], # macrolanguage + 227 : ["Kongo", "kg"], # macrolanguage + 228 : ["Kwanyama", "kj"], + 229 : ["Limburgish", "li"], + 230 : ["Luba Katanga", "lu"], + 231 : ["Luxembourgish", "lb"], + 232 : ["Navaho", "nv"], + 233 : ["Ndonga", "ng"], + 234 : ["Ojibwa", "oj"], # macrolanguage + 235 : ["Pali", "pi"], # macrolanguage + 236 : ["Walloon", "wa"], + 237 : ["Aghem", "agq"], + 238 : ["Basaa", "bas"], + 239 : ["Zarma", "dje"], + 240 : ["Duala", "dua"], + 241 : ["Jola Fonyi", "dyo"], + 242 : ["Ewondo", "ewo"], + 243 : ["Bafia", "ksf"], + 244 : ["Makhuwa Meetto", "mgh"], + 245 : ["Mundang", "mua"], + 246 : ["Kwasio", "nmg"], + 247 : ["Nuer", "nus"], + 248 : ["Sakha", "sah"], + 249 : ["Sangu", "sbp"], + 250 : ["Congo Swahili", "swc"], + 251 : ["Tasawaq", "twq"], + 252 : ["Vai", "vai"], + 253 : ["Walser", "wae"], + 254 : ["Yangben", "yav"], + 255 : ["Avestan", "ae"], + 256 : ["Asturian", "ast"], + 257 : ["Ngomba", "jgo"], + 258 : ["Kako", "kkj"], + 259 : ["Meta", "mgo"], + 260 : ["Ngiemboon", "nnh"], + 261 : ["Aragonese", "an"], + 262 : ["Akkadian", "akk"], + 263 : ["Ancient Egyptian", "egy"], + 264 : ["Ancient Greek", "grc"], + 265 : ["Aramaic", "arc"], + 266 : ["Balinese", "ban"], + 267 : ["Bamun", "bax"], + 268 : ["Batak Toba", "bbc"], + 269 : ["Buginese", "bug"], + 270 : ["Buhid", "bku"], + 271 : ["Carian", "xcr"], + 272 : ["Chakma", "ccp"], + 273 : ["Classical Mandaic", "myz"], + 274 : ["Coptic", "cop"], + 275 : ["Dogri", "doi"], # macrolanguage + 276 : ["Eastern Cham", "cjm"], + 277 : ["Eastern Kayah", "eky"], + 278 : ["Etruscan", "ett"], + 279 : ["Gothic", "got"], + 280 : ["Hanunoo", "hnn"], + 281 : ["Ingush", "inh"], + 282 : ["Large Flowery Miao", "hmd"], + 283 : ["Lepcha", "lep"], + 284 : ["Limbu", "lif"], + 285 : ["Lisu", "lis"], + 286 : ["Lu", "khb"], + 287 : ["Lycian", "xlc"], + 288 : ["Lydian", "xld"], + 289 : ["Mandingo", "man"], # macrolanguage + 290 : ["Manipuri", "mni"], + 291 : ["Meroitic", "xmr"], + 292 : ["Northern Thai", "nod"], + 293 : ["Old Irish", "sga"], + 294 : ["Old Norse", "non"], + 295 : ["Old Persian", "peo"], + 296 : ["Old Turkish", "otk"], + 297 : ["Pahlavi", "pal"], + 298 : ["Parthian", "xpr"], + 299 : ["Phoenician", "phn"], + 300 : ["Prakrit Language", "pra"], + 301 : ["Rejang", "rej"], + 302 : ["Sabaean", "xsa"], + 303 : ["Samaritan", "smp"], + 304 : ["Santali", "sat"], + 305 : ["Saurashtra", "saz"], + 306 : ["Sora", "srb"], + 307 : ["Sylheti", "syl"], + 308 : ["Tagbanwa", "tbw"], + 309 : ["Tai Dam", "blt"], + 310 : ["Tai Nua", "tdd"], + 311 : ["Ugaritic", "uga"], + 312 : ["Akoose", "bss"], + 313 : ["Lakota", "lkt"], + 314 : ["Standard Moroccan Tamazight", "zgh"], + 315 : ["Mapuche", "arn"], + 316 : ["Central Kurdish", "ckb"], + 317 : ["Lower Sorbian", "dsb"], + 318 : ["Upper Sorbian", "hsb"], + 319 : ["Kenyang", "ken"], + 320 : ["Mohawk", "moh"], + 321 : ["Nko", "nqo"], + 322 : ["Prussian", "prg"], + 323 : ["Kiche", "quc"], + 324 : ["Southern Sami", "sma"], + 325 : ["Lule Sami", "smj"], + 326 : ["Inari Sami", "smn"], + 327 : ["Skolt Sami", "sms"], + 328 : ["Warlpiri", "wbp"], + 329 : ["Manichaean Middle Persian", "xmn"], + 330 : ["Mende", "men"], + 331 : ["Ancient North Arabian", "xna"], + 332 : ["Linear A", "lab"], + 333 : ["Hmong Njua", "hnj"], + 334 : ["Ho", "hoc"], + 335 : ["Lezghian", "lez"], + 336 : ["Bassa", "bsq"], + 337 : ["Mono", "mru"], + 338 : ["Tedim Chin", "ctd"], + 339 : ["Maithili", "mai"], + 340 : ["Ahom", "aho"], + 341 : ["American Sign Language", "ase"], + 342 : ["Ardhamagadhi Prakrit", "pka"], + 343 : ["Bhojpuri", "bho"], + 344 : ["Hieroglyphic Luwian", "hlu"], + 345 : ["Literary Chinese", "lzh"], + 346 : ["Mazanderani", "mzn"], + 347 : ["Mru", "mro"], + 348 : ["Newari", "new"], + 349 : ["Northern Luri", "lrc"], + 350 : ["Palauan", "pau"], + 351 : ["Papiamento", "pap"], + 352 : ["Saraiki", "skr"], + 353 : ["Tokelau", "tkl"], + 354 : ["Tok Pisin", "tpi"], + 355 : ["Tuvalu", "tvl"], + 356 : ["Uncoded Languages", "mis"], + 357 : ["Cantonese", "yue"], + 358 : ["Osage", "osa"], + 359 : ["Tangut", "txg"] } country_list = { - 0 : [ "AnyCountry", "ZZ" ], - 1 : [ "Afghanistan", "AF" ], - 2 : [ "Albania", "AL" ], - 3 : [ "Algeria", "DZ" ], - 4 : [ "AmericanSamoa", "AS" ], - 5 : [ "Andorra", "AD" ], - 6 : [ "Angola", "AO" ], - 7 : [ "Anguilla", "AI" ], - 8 : [ "Antarctica", "AQ" ], - 9 : [ "AntiguaAndBarbuda", "AG" ], - 10 : [ "Argentina", "AR" ], - 11 : [ "Armenia", "AM" ], - 12 : [ "Aruba", "AW" ], - 13 : [ "Australia", "AU" ], - 14 : [ "Austria", "AT" ], - 15 : [ "Azerbaijan", "AZ" ], - 16 : [ "Bahamas", "BS" ], - 17 : [ "Bahrain", "BH" ], - 18 : [ "Bangladesh", "BD" ], - 19 : [ "Barbados", "BB" ], - 20 : [ "Belarus", "BY" ], - 21 : [ "Belgium", "BE" ], - 22 : [ "Belize", "BZ" ], - 23 : [ "Benin", "BJ" ], - 24 : [ "Bermuda", "BM" ], - 25 : [ "Bhutan", "BT" ], - 26 : [ "Bolivia", "BO" ], - 27 : [ "BosniaAndHerzegowina", "BA" ], - 28 : [ "Botswana", "BW" ], - 29 : [ "BouvetIsland", "BV" ], - 30 : [ "Brazil", "BR" ], - 31 : [ "BritishIndianOceanTerritory", "IO" ], - 32 : [ "Brunei", "BN" ], - 33 : [ "Bulgaria", "BG" ], - 34 : [ "BurkinaFaso", "BF" ], - 35 : [ "Burundi", "BI" ], - 36 : [ "Cambodia", "KH" ], - 37 : [ "Cameroon", "CM" ], - 38 : [ "Canada", "CA" ], - 39 : [ "CapeVerde", "CV" ], - 40 : [ "CaymanIslands", "KY" ], - 41 : [ "CentralAfricanRepublic", "CF" ], - 42 : [ "Chad", "TD" ], - 43 : [ "Chile", "CL" ], - 44 : [ "China", "CN" ], - 45 : [ "ChristmasIsland", "CX" ], - 46 : [ "CocosIslands", "CC" ], - 47 : [ "Colombia", "CO" ], - 48 : [ "Comoros", "KM" ], - 49 : [ "CongoKinshasa", "CD" ], - 50 : [ "CongoBrazzaville", "CG" ], - 51 : [ "CookIslands", "CK" ], - 52 : [ "CostaRica", "CR" ], - 53 : [ "IvoryCoast", "CI" ], - 54 : [ "Croatia", "HR" ], - 55 : [ "Cuba", "CU" ], - 56 : [ "Cyprus", "CY" ], - 57 : [ "CzechRepublic", "CZ" ], - 58 : [ "Denmark", "DK" ], - 59 : [ "Djibouti", "DJ" ], - 60 : [ "Dominica", "DM" ], - 61 : [ "DominicanRepublic", "DO" ], - 62 : [ "EastTimor", "TL" ], - 63 : [ "Ecuador", "EC" ], - 64 : [ "Egypt", "EG" ], - 65 : [ "ElSalvador", "SV" ], - 66 : [ "EquatorialGuinea", "GQ" ], - 67 : [ "Eritrea", "ER" ], - 68 : [ "Estonia", "EE" ], - 69 : [ "Ethiopia", "ET" ], - 70 : [ "FalklandIslands", "FK" ], - 71 : [ "FaroeIslands", "FO" ], - 72 : [ "Fiji", "FJ" ], - 73 : [ "Finland", "FI" ], - 74 : [ "France", "FR" ], - 75 : [ "Guernsey", "GG" ], - 76 : [ "FrenchGuiana", "GF" ], - 77 : [ "FrenchPolynesia", "PF" ], - 78 : [ "FrenchSouthernTerritories", "TF" ], - 79 : [ "Gabon", "GA" ], - 80 : [ "Gambia", "GM" ], - 81 : [ "Georgia", "GE" ], - 82 : [ "Germany", "DE" ], - 83 : [ "Ghana", "GH" ], - 84 : [ "Gibraltar", "GI" ], - 85 : [ "Greece", "GR" ], - 86 : [ "Greenland", "GL" ], - 87 : [ "Grenada", "GD" ], - 88 : [ "Guadeloupe", "GP" ], - 89 : [ "Guam", "GU" ], - 90 : [ "Guatemala", "GT" ], - 91 : [ "Guinea", "GN" ], - 92 : [ "GuineaBissau", "GW" ], - 93 : [ "Guyana", "GY" ], - 94 : [ "Haiti", "HT" ], - 95 : [ "HeardAndMcDonaldIslands", "HM" ], - 96 : [ "Honduras", "HN" ], - 97 : [ "HongKong", "HK" ], - 98 : [ "Hungary", "HU" ], - 99 : [ "Iceland", "IS" ], - 100 : [ "India", "IN" ], - 101 : [ "Indonesia", "ID" ], - 102 : [ "Iran", "IR" ], - 103 : [ "Iraq", "IQ" ], - 104 : [ "Ireland", "IE" ], - 105 : [ "Israel", "IL" ], - 106 : [ "Italy", "IT" ], - 107 : [ "Jamaica", "JM" ], - 108 : [ "Japan", "JP" ], - 109 : [ "Jordan", "JO" ], - 110 : [ "Kazakhstan", "KZ" ], - 111 : [ "Kenya", "KE" ], - 112 : [ "Kiribati", "KI" ], - 113 : [ "NorthKorea", "KP" ], - 114 : [ "SouthKorea", "KR" ], - 115 : [ "Kuwait", "KW" ], - 116 : [ "Kyrgyzstan", "KG" ], - 117 : [ "Laos", "LA" ], - 118 : [ "Latvia", "LV" ], - 119 : [ "Lebanon", "LB" ], - 120 : [ "Lesotho", "LS" ], - 121 : [ "Liberia", "LR" ], - 122 : [ "Libya", "LY" ], - 123 : [ "Liechtenstein", "LI" ], - 124 : [ "Lithuania", "LT" ], - 125 : [ "Luxembourg", "LU" ], - 126 : [ "Macau", "MO" ], - 127 : [ "Macedonia", "MK" ], - 128 : [ "Madagascar", "MG" ], - 129 : [ "Malawi", "MW" ], - 130 : [ "Malaysia", "MY" ], - 131 : [ "Maldives", "MV" ], - 132 : [ "Mali", "ML" ], - 133 : [ "Malta", "MT" ], - 134 : [ "MarshallIslands", "MH" ], - 135 : [ "Martinique", "MQ" ], - 136 : [ "Mauritania", "MR" ], - 137 : [ "Mauritius", "MU" ], - 138 : [ "Mayotte", "YT" ], - 139 : [ "Mexico", "MX" ], - 140 : [ "Micronesia", "FM" ], - 141 : [ "Moldova", "MD" ], - 142 : [ "Monaco", "MC" ], - 143 : [ "Mongolia", "MN" ], - 144 : [ "Montserrat", "MS" ], - 145 : [ "Morocco", "MA" ], - 146 : [ "Mozambique", "MZ" ], - 147 : [ "Myanmar", "MM" ], - 148 : [ "Namibia", "NA" ], - 149 : [ "Nauru", "NR" ], - 150 : [ "Nepal", "NP" ], - 151 : [ "Netherlands", "NL" ], - 152 : [ "CuraSao", "CW" ], - 153 : [ "NewCaledonia", "NC" ], - 154 : [ "NewZealand", "NZ" ], - 155 : [ "Nicaragua", "NI" ], - 156 : [ "Niger", "NE" ], - 157 : [ "Nigeria", "NG" ], - 158 : [ "Niue", "NU" ], - 159 : [ "NorfolkIsland", "NF" ], - 160 : [ "NorthernMarianaIslands", "MP" ], - 161 : [ "Norway", "NO" ], - 162 : [ "Oman", "OM" ], - 163 : [ "Pakistan", "PK" ], - 164 : [ "Palau", "PW" ], - 165 : [ "PalestinianTerritories", "PS" ], - 166 : [ "Panama", "PA" ], - 167 : [ "PapuaNewGuinea", "PG" ], - 168 : [ "Paraguay", "PY" ], - 169 : [ "Peru", "PE" ], - 170 : [ "Philippines", "PH" ], - 171 : [ "Pitcairn", "PN" ], - 172 : [ "Poland", "PL" ], - 173 : [ "Portugal", "PT" ], - 174 : [ "PuertoRico", "PR" ], - 175 : [ "Qatar", "QA" ], - 176 : [ "Reunion", "RE" ], - 177 : [ "Romania", "RO" ], - 178 : [ "Russia", "RU" ], - 179 : [ "Rwanda", "RW" ], - 180 : [ "SaintKittsAndNevis", "KN" ], - 181 : [ "SaintLucia", "LC" ], - 182 : [ "SaintVincentAndTheGrenadines", "VC" ], - 183 : [ "Samoa", "WS" ], - 184 : [ "SanMarino", "SM" ], - 185 : [ "SaoTomeAndPrincipe", "ST" ], - 186 : [ "SaudiArabia", "SA" ], - 187 : [ "Senegal", "SN" ], - 188 : [ "Seychelles", "SC" ], - 189 : [ "SierraLeone", "SL" ], - 190 : [ "Singapore", "SG" ], - 191 : [ "Slovakia", "SK" ], - 192 : [ "Slovenia", "SI" ], - 193 : [ "SolomonIslands", "SB" ], - 194 : [ "Somalia", "SO" ], - 195 : [ "SouthAfrica", "ZA" ], - 196 : [ "SouthGeorgiaAndTheSouthSandwichIslands", "GS" ], - 197 : [ "Spain", "ES" ], - 198 : [ "SriLanka", "LK" ], - 199 : [ "SaintHelena", "SH" ], - 200 : [ "SaintPierreAndMiquelon", "PM" ], - 201 : [ "Sudan", "SD" ], - 202 : [ "Suriname", "SR" ], - 203 : [ "SvalbardAndJanMayenIslands", "SJ" ], - 204 : [ "Swaziland", "SZ" ], - 205 : [ "Sweden", "SE" ], - 206 : [ "Switzerland", "CH" ], - 207 : [ "Syria", "SY" ], - 208 : [ "Taiwan", "TW" ], - 209 : [ "Tajikistan", "TJ" ], - 210 : [ "Tanzania", "TZ" ], - 211 : [ "Thailand", "TH" ], - 212 : [ "Togo", "TG" ], - 213 : [ "Tokelau", "TK" ], - 214 : [ "Tonga", "TO" ], - 215 : [ "TrinidadAndTobago", "TT" ], - 216 : [ "Tunisia", "TN" ], - 217 : [ "Turkey", "TR" ], - 218 : [ "Turkmenistan", "TM" ], - 219 : [ "TurksAndCaicosIslands", "TC" ], - 220 : [ "Tuvalu", "TV" ], - 221 : [ "Uganda", "UG" ], - 222 : [ "Ukraine", "UA" ], - 223 : [ "UnitedArabEmirates", "AE" ], - 224 : [ "UnitedKingdom", "GB" ], - 225 : [ "UnitedStates", "US" ], - 226 : [ "UnitedStatesMinorOutlyingIslands", "UM" ], - 227 : [ "Uruguay", "UY" ], - 228 : [ "Uzbekistan", "UZ" ], - 229 : [ "Vanuatu", "VU" ], - 230 : [ "VaticanCityState", "VA" ], - 231 : [ "Venezuela", "VE" ], - 232 : [ "Vietnam", "VN" ], - 233 : [ "BritishVirginIslands", "VG" ], - 234 : [ "UnitedStatesVirginIslands", "VI" ], - 235 : [ "WallisAndFutunaIslands", "WF" ], - 236 : [ "WesternSahara", "EH" ], - 237 : [ "Yemen", "YE" ], - 238 : [ "CanaryIslands", "IC" ], - 239 : [ "Zambia", "ZM" ], - 240 : [ "Zimbabwe", "ZW" ], - 241 : [ "ClippertonIsland", "CP" ], - 242 : [ "Montenegro", "ME" ], - 243 : [ "Serbia", "RS" ], - 244 : [ "Saint Barthelemy", "BL" ], - 245 : [ "Saint Martin", "MF" ], - 246 : [ "Latin America", "419" ], - 247 : [ "AscensionIsland", "AC" ], - 248 : [ "AlandIslands", "AX" ], - 249 : [ "DiegoGarcia", "DG" ], - 250 : [ "CeutaAndMelilla", "EA" ], - 251 : [ "IsleOfMan", "IM" ], - 252 : [ "Jersey", "JE" ], - 253 : [ "TristanDaCunha", "TA" ], - 254 : [ "SouthSudan", "SS" ], - 255 : [ "Bonaire", "BQ" ], - 256 : [ "SintMaarten", "SX" ], - 257 : [ "Kosovo", "XK" ], - 258 : [ "European Union", "EU" ], - 259 : [ "Outlying Oceania", "QO" ], - 260 : [ "World", "001" ], - 261 : [ "Europe", "150" ] + 0 : ["AnyCountry", "ZZ"], + 1 : ["Afghanistan", "AF"], + 2 : ["Albania", "AL"], + 3 : ["Algeria", "DZ"], + 4 : ["American Samoa", "AS"], + 5 : ["Andorra", "AD"], + 6 : ["Angola", "AO"], + 7 : ["Anguilla", "AI"], + 8 : ["Antarctica", "AQ"], + 9 : ["Antigua And Barbuda", "AG"], + 10 : ["Argentina", "AR"], + 11 : ["Armenia", "AM"], + 12 : ["Aruba", "AW"], + 13 : ["Australia", "AU"], + 14 : ["Austria", "AT"], + 15 : ["Azerbaijan", "AZ"], + 16 : ["Bahamas", "BS"], + 17 : ["Bahrain", "BH"], + 18 : ["Bangladesh", "BD"], + 19 : ["Barbados", "BB"], + 20 : ["Belarus", "BY"], + 21 : ["Belgium", "BE"], + 22 : ["Belize", "BZ"], + 23 : ["Benin", "BJ"], + 24 : ["Bermuda", "BM"], + 25 : ["Bhutan", "BT"], + 26 : ["Bolivia", "BO"], + 27 : ["Bosnia And Herzegowina", "BA"], + 28 : ["Botswana", "BW"], + 29 : ["Bouvet Island", "BV"], + 30 : ["Brazil", "BR"], + 31 : ["British Indian Ocean Territory", "IO"], + 32 : ["Brunei", "BN"], + 33 : ["Bulgaria", "BG"], + 34 : ["Burkina Faso", "BF"], + 35 : ["Burundi", "BI"], + 36 : ["Cambodia", "KH"], + 37 : ["Cameroon", "CM"], + 38 : ["Canada", "CA"], + 39 : ["Cape Verde", "CV"], + 40 : ["Cayman Islands", "KY"], + 41 : ["Central African Republic", "CF"], + 42 : ["Chad", "TD"], + 43 : ["Chile", "CL"], + 44 : ["China", "CN"], + 45 : ["Christmas Island", "CX"], + 46 : ["Cocos Islands", "CC"], + 47 : ["Colombia", "CO"], + 48 : ["Comoros", "KM"], + 49 : ["Congo Kinshasa", "CD"], + 50 : ["Congo Brazzaville", "CG"], + 51 : ["Cook Islands", "CK"], + 52 : ["Costa Rica", "CR"], + 53 : ["Ivory Coast", "CI"], + 54 : ["Croatia", "HR"], + 55 : ["Cuba", "CU"], + 56 : ["Cyprus", "CY"], + 57 : ["Czech Republic", "CZ"], + 58 : ["Denmark", "DK"], + 59 : ["Djibouti", "DJ"], + 60 : ["Dominica", "DM"], + 61 : ["Dominican Republic", "DO"], + 62 : ["East Timor", "TL"], + 63 : ["Ecuador", "EC"], + 64 : ["Egypt", "EG"], + 65 : ["El Salvador", "SV"], + 66 : ["Equatorial Guinea", "GQ"], + 67 : ["Eritrea", "ER"], + 68 : ["Estonia", "EE"], + 69 : ["Ethiopia", "ET"], + 70 : ["Falkland Islands", "FK"], + 71 : ["Faroe Islands", "FO"], + 72 : ["Fiji", "FJ"], + 73 : ["Finland", "FI"], + 74 : ["France", "FR"], + 75 : ["Guernsey", "GG"], + 76 : ["French Guiana", "GF"], + 77 : ["French Polynesia", "PF"], + 78 : ["French Southern Territories", "TF"], + 79 : ["Gabon", "GA"], + 80 : ["Gambia", "GM"], + 81 : ["Georgia", "GE"], + 82 : ["Germany", "DE"], + 83 : ["Ghana", "GH"], + 84 : ["Gibraltar", "GI"], + 85 : ["Greece", "GR"], + 86 : ["Greenland", "GL"], + 87 : ["Grenada", "GD"], + 88 : ["Guadeloupe", "GP"], + 89 : ["Guam", "GU"], + 90 : ["Guatemala", "GT"], + 91 : ["Guinea", "GN"], + 92 : ["Guinea Bissau", "GW"], + 93 : ["Guyana", "GY"], + 94 : ["Haiti", "HT"], + 95 : ["Heard And McDonald Islands", "HM"], + 96 : ["Honduras", "HN"], + 97 : ["Hong Kong", "HK"], + 98 : ["Hungary", "HU"], + 99 : ["Iceland", "IS"], + 100 : ["India", "IN"], + 101 : ["Indonesia", "ID"], + 102 : ["Iran", "IR"], + 103 : ["Iraq", "IQ"], + 104 : ["Ireland", "IE"], + 105 : ["Israel", "IL"], + 106 : ["Italy", "IT"], + 107 : ["Jamaica", "JM"], + 108 : ["Japan", "JP"], + 109 : ["Jordan", "JO"], + 110 : ["Kazakhstan", "KZ"], + 111 : ["Kenya", "KE"], + 112 : ["Kiribati", "KI"], + 113 : ["North Korea", "KP"], + 114 : ["South Korea", "KR"], + 115 : ["Kuwait", "KW"], + 116 : ["Kyrgyzstan", "KG"], + 117 : ["Laos", "LA"], + 118 : ["Latvia", "LV"], + 119 : ["Lebanon", "LB"], + 120 : ["Lesotho", "LS"], + 121 : ["Liberia", "LR"], + 122 : ["Libya", "LY"], + 123 : ["Liechtenstein", "LI"], + 124 : ["Lithuania", "LT"], + 125 : ["Luxembourg", "LU"], + 126 : ["Macau", "MO"], + 127 : ["Macedonia", "MK"], + 128 : ["Madagascar", "MG"], + 129 : ["Malawi", "MW"], + 130 : ["Malaysia", "MY"], + 131 : ["Maldives", "MV"], + 132 : ["Mali", "ML"], + 133 : ["Malta", "MT"], + 134 : ["Marshall Islands", "MH"], + 135 : ["Martinique", "MQ"], + 136 : ["Mauritania", "MR"], + 137 : ["Mauritius", "MU"], + 138 : ["Mayotte", "YT"], + 139 : ["Mexico", "MX"], + 140 : ["Micronesia", "FM"], + 141 : ["Moldova", "MD"], + 142 : ["Monaco", "MC"], + 143 : ["Mongolia", "MN"], + 144 : ["Montserrat", "MS"], + 145 : ["Morocco", "MA"], + 146 : ["Mozambique", "MZ"], + 147 : ["Myanmar", "MM"], + 148 : ["Namibia", "NA"], + 149 : ["Nauru", "NR"], + 150 : ["Nepal", "NP"], + 151 : ["Netherlands", "NL"], + 152 : ["Cura Sao", "CW"], + 153 : ["New Caledonia", "NC"], + 154 : ["New Zealand", "NZ"], + 155 : ["Nicaragua", "NI"], + 156 : ["Niger", "NE"], + 157 : ["Nigeria", "NG"], + 158 : ["Niue", "NU"], + 159 : ["Norfolk Island", "NF"], + 160 : ["Northern Mariana Islands", "MP"], + 161 : ["Norway", "NO"], + 162 : ["Oman", "OM"], + 163 : ["Pakistan", "PK"], + 164 : ["Palau", "PW"], + 165 : ["Palestinian Territories", "PS"], + 166 : ["Panama", "PA"], + 167 : ["Papua New Guinea", "PG"], + 168 : ["Paraguay", "PY"], + 169 : ["Peru", "PE"], + 170 : ["Philippines", "PH"], + 171 : ["Pitcairn", "PN"], + 172 : ["Poland", "PL"], + 173 : ["Portugal", "PT"], + 174 : ["Puerto Rico", "PR"], + 175 : ["Qatar", "QA"], + 176 : ["Reunion", "RE"], + 177 : ["Romania", "RO"], + 178 : ["Russia", "RU"], + 179 : ["Rwanda", "RW"], + 180 : ["Saint Kitts And Nevis", "KN"], + 181 : ["Saint Lucia", "LC"], + 182 : ["Saint Vincent And The Grenadines", "VC"], + 183 : ["Samoa", "WS"], + 184 : ["San Marino", "SM"], + 185 : ["Sao Tome And Principe", "ST"], + 186 : ["Saudi Arabia", "SA"], + 187 : ["Senegal", "SN"], + 188 : ["Seychelles", "SC"], + 189 : ["Sierra Leone", "SL"], + 190 : ["Singapore", "SG"], + 191 : ["Slovakia", "SK"], + 192 : ["Slovenia", "SI"], + 193 : ["Solomon Islands", "SB"], + 194 : ["Somalia", "SO"], + 195 : ["South Africa", "ZA"], + 196 : ["South Georgia And The South Sandwich Islands", "GS"], + 197 : ["Spain", "ES"], + 198 : ["Sri Lanka", "LK"], + 199 : ["Saint Helena", "SH"], + 200 : ["Saint Pierre And Miquelon", "PM"], + 201 : ["Sudan", "SD"], + 202 : ["Suriname", "SR"], + 203 : ["Svalbard And Jan Mayen Islands", "SJ"], + 204 : ["Swaziland", "SZ"], + 205 : ["Sweden", "SE"], + 206 : ["Switzerland", "CH"], + 207 : ["Syria", "SY"], + 208 : ["Taiwan", "TW"], + 209 : ["Tajikistan", "TJ"], + 210 : ["Tanzania", "TZ"], + 211 : ["Thailand", "TH"], + 212 : ["Togo", "TG"], + 213 : ["Tokelau", "TK"], + 214 : ["Tonga", "TO"], + 215 : ["Trinidad And Tobago", "TT"], + 216 : ["Tunisia", "TN"], + 217 : ["Turkey", "TR"], + 218 : ["Turkmenistan", "TM"], + 219 : ["Turks And Caicos Islands", "TC"], + 220 : ["Tuvalu", "TV"], + 221 : ["Uganda", "UG"], + 222 : ["Ukraine", "UA"], + 223 : ["United Arab Emirates", "AE"], + 224 : ["United Kingdom", "GB"], + 225 : ["United States", "US"], + 226 : ["United States Minor Outlying Islands", "UM"], + 227 : ["Uruguay", "UY"], + 228 : ["Uzbekistan", "UZ"], + 229 : ["Vanuatu", "VU"], + 230 : ["Vatican City State", "VA"], + 231 : ["Venezuela", "VE"], + 232 : ["Vietnam", "VN"], + 233 : ["British Virgin Islands", "VG"], + 234 : ["United States Virgin Islands", "VI"], + 235 : ["Wallis And Futuna Islands", "WF"], + 236 : ["Western Sahara", "EH"], + 237 : ["Yemen", "YE"], + 238 : ["Canary Islands", "IC"], + 239 : ["Zambia", "ZM"], + 240 : ["Zimbabwe", "ZW"], + 241 : ["Clipperton Island", "CP"], + 242 : ["Montenegro", "ME"], + 243 : ["Serbia", "RS"], + 244 : ["Saint Barthelemy", "BL"], + 245 : ["Saint Martin", "MF"], + 246 : ["Latin America", "419"], + 247 : ["Ascension Island", "AC"], + 248 : ["Aland Islands", "AX"], + 249 : ["Diego Garcia", "DG"], + 250 : ["Ceuta And Melilla", "EA"], + 251 : ["Isle Of Man", "IM"], + 252 : ["Jersey", "JE"], + 253 : ["Tristan Da Cunha", "TA"], + 254 : ["South Sudan", "SS"], + 255 : ["Bonaire", "BQ"], + 256 : ["Sint Maarten", "SX"], + 257 : ["Kosovo", "XK"], + 258 : ["European Union", "EU"], + 259 : ["Outlying Oceania", "QO"], + 260 : ["World", "001"], + 261 : ["Europe", "150"] } script_list = { - 0 : [ "AnyScript", "Zzzz" ], - 1 : [ "Arabic", "Arab" ], - 2 : [ "Cyrillic", "Cyrl" ], - 3 : [ "Deseret", "Dsrt" ], - 4 : [ "Gurmukhi", "Guru" ], - 5 : [ "Simplified Han", "Hans" ], - 6 : [ "Traditional Han", "Hant" ], - 7 : [ "Latin", "Latn" ], - 8 : [ "Mongolian", "Mong" ], - 9 : [ "Tifinagh", "Tfng" ], - 10 : [ "Armenian", "Armn" ], - 11 : [ "Bengali", "Beng" ], - 12 : [ "Cherokee", "Cher" ], - 13 : [ "Devanagari", "Deva" ], - 14 : [ "Ethiopic", "Ethi" ], - 15 : [ "Georgian", "Geor" ], - 16 : [ "Greek", "Grek" ], - 17 : [ "Gujarati", "Gujr" ], - 18 : [ "Hebrew", "Hebr" ], - 19 : [ "Japanese", "Jpan" ], - 20 : [ "Khmer", "Khmr" ], - 21 : [ "Kannada", "Knda" ], - 22 : [ "Korean", "Kore" ], - 23 : [ "Lao", "Laoo" ], - 24 : [ "Malayalam", "Mlym" ], - 25 : [ "Myanmar", "Mymr" ], - 26 : [ "Oriya", "Orya" ], - 27 : [ "Tamil", "Taml" ], - 28 : [ "Telugu", "Telu" ], - 29 : [ "Thaana", "Thaa" ], - 30 : [ "Thai", "Thai" ], - 31 : [ "Tibetan", "Tibt" ], - 32 : [ "Sinhala", "Sinh" ], - 33 : [ "Syriac", "Syrc" ], - 34 : [ "Yi", "Yiii" ], - 35 : [ "Vai", "Vaii" ], - 36 : [ "Avestan", "Avst" ], - 37 : [ "Balinese", "Bali" ], - 38 : [ "Bamum", "Bamu" ], - 39 : [ "Batak", "Batk" ], - 40 : [ "Bopomofo", "Bopo" ], - 41 : [ "Brahmi", "Brah" ], - 42 : [ "Buginese", "Bugi" ], - 43 : [ "Buhid", "Buhd" ], - 44 : [ "CanadianAboriginal", "Cans" ], - 45 : [ "Carian", "Cari" ], - 46 : [ "Chakma", "Cakm" ], - 47 : [ "Cham", "Cham" ], - 48 : [ "Coptic", "Copt" ], - 49 : [ "Cypriot", "Cprt" ], - 50 : [ "Egyptian Hieroglyphs", "Egyp" ], - 51 : [ "Fraser", "Lisu" ], - 52 : [ "Glagolitic", "Glag" ], - 53 : [ "Gothic", "Goth" ], - 54 : [ "Han", "Hani" ], - 55 : [ "Hangul", "Hang" ], - 56 : [ "Hanunoo", "Hano" ], - 57 : [ "Imperial Aramaic", "Armi" ], - 58 : [ "Inscriptional Pahlavi", "Phli" ], - 59 : [ "Inscriptional Parthian", "Prti" ], - 60 : [ "Javanese", "Java" ], - 61 : [ "Kaithi", "Kthi" ], - 62 : [ "Katakana", "Kana" ], - 63 : [ "Kayah Li", "Kali" ], - 64 : [ "Kharoshthi", "Khar" ], - 65 : [ "Lanna", "Lana" ], - 66 : [ "Lepcha", "Lepc" ], - 67 : [ "Limbu", "Limb" ], - 68 : [ "Linear B", "Linb" ], - 69 : [ "Lycian", "Lyci" ], - 70 : [ "Lydian", "Lydi" ], - 71 : [ "Mandaean", "Mand" ], - 72 : [ "Meitei Mayek", "Mtei" ], - 73 : [ "Meroitic", "Mero" ], - 74 : [ "Meroitic Cursive", "Merc" ], - 75 : [ "Nko", "Nkoo" ], - 76 : [ "New Tai Lue", "Talu" ], - 77 : [ "Ogham", "Ogam" ], - 78 : [ "Ol Chiki", "Olck" ], - 79 : [ "Old Italic", "Ital" ], - 80 : [ "Old Persian", "Xpeo" ], - 81 : [ "Old South Arabian", "Sarb" ], - 82 : [ "Orkhon", "Orkh" ], - 83 : [ "Osmanya", "Osma" ], - 84 : [ "Phags Pa", "Phag" ], - 85 : [ "Phoenician", "Phnx" ], - 86 : [ "Pollard Phonetic", "Plrd" ], - 87 : [ "Rejang", "Rjng" ], - 88 : [ "Runic", "Runr" ], - 89 : [ "Samaritan", "Samr" ], - 90 : [ "Saurashtra", "Saur" ], - 91 : [ "Sharada", "Shrd" ], - 92 : [ "Shavian", "Shaw" ], - 93 : [ "Sora Sompeng", "Sora" ], - 94 : [ "Cuneiform", "Xsux" ], - 95 : [ "Sundanese", "Sund" ], - 96 : [ "Syloti Nagri", "Sylo" ], - 97 : [ "Tagalog", "Tglg" ], - 98 : [ "Tagbanwa", "Tagb" ], - 99 : [ "Tai Le", "Tale" ], - 100 : [ "Tai Viet", "Tavt" ], - 101 : [ "Takri", "Takr" ], - 102 : [ "Ugaritic", "Ugar" ], - 103 : [ "Braille", "Brai" ], - 104 : [ "Hiragana", "Hira" ], - 105 : [ "Caucasian Albanian", "Aghb" ], - 106 : [ "Bassa Vah", "Bass" ], - 107 : [ "Duployan", "Dupl" ], - 108 : [ "Elbasan", "Elba" ], - 109 : [ "Grantha", "Gran" ], - 110 : [ "Pahawh Hmong", "Hmng" ], - 111 : [ "Khojki", "Khoj" ], - 112 : [ "Linear A", "Lina" ], - 113 : [ "Mahajani", "Mahj" ], - 114 : [ "Manichaean", "Mani" ], - 115 : [ "Mende Kikakui", "Mend" ], - 116 : [ "Modi", "Modi" ], - 117 : [ "Mro", "Mroo" ], - 118 : [ "Old North Arabian", "Narb" ], - 119 : [ "Nabataean", "Nbat" ], - 120 : [ "Palmyrene", "Palm" ], - 121 : [ "Pau Cin Hau", "Pauc" ], - 122 : [ "Old Permic", "Perm" ], - 123 : [ "Psalter Pahlavi", "Phlp" ], - 124 : [ "Siddham", "Sidd" ], - 125 : [ "Khudawadi", "Sind" ], - 126 : [ "Tirhuta", "Tirh" ], - 127 : [ "Varang Kshiti", "Wara" ], - 128 : [ "Ahom", "Ahom" ], - 129 : [ "Anatolian Hieroglyphs", "Hluw" ], - 130 : [ "Hatran", "Hatr" ], - 131 : [ "Multani", "Mult" ], - 132 : [ "Old Hungarian", "Hung" ], - 133 : [ "SignWriting", "Sgnw" ], - 134 : [ "Adlam", "Adlm" ], - 135 : [ "Bhaiksuki", "Bhks" ], - 136 : [ "Marchen", "Marc" ], - 137 : [ "Newa", "Newa" ], - 138 : [ "Osage", "Osge" ], - 139 : [ "Tangut", "Tang" ], - 140 : [ "Han with Bopomofo", "Hanb" ], - 141 : [ "Jamo", "Jamo" ] + 0 : ["AnyScript", "Zzzz"], + 1 : ["Arabic", "Arab"], + 2 : ["Cyrillic", "Cyrl"], + 3 : ["Deseret", "Dsrt"], + 4 : ["Gurmukhi", "Guru"], + 5 : ["Simplified Han", "Hans"], + 6 : ["Traditional Han", "Hant"], + 7 : ["Latin", "Latn"], + 8 : ["Mongolian", "Mong"], + 9 : ["Tifinagh", "Tfng"], + 10 : ["Armenian", "Armn"], + 11 : ["Bengali", "Beng"], + 12 : ["Cherokee", "Cher"], + 13 : ["Devanagari", "Deva"], + 14 : ["Ethiopic", "Ethi"], + 15 : ["Georgian", "Geor"], + 16 : ["Greek", "Grek"], + 17 : ["Gujarati", "Gujr"], + 18 : ["Hebrew", "Hebr"], + 19 : ["Japanese", "Jpan"], + 20 : ["Khmer", "Khmr"], + 21 : ["Kannada", "Knda"], + 22 : ["Korean", "Kore"], + 23 : ["Lao", "Laoo"], + 24 : ["Malayalam", "Mlym"], + 25 : ["Myanmar", "Mymr"], + 26 : ["Oriya", "Orya"], + 27 : ["Tamil", "Taml"], + 28 : ["Telugu", "Telu"], + 29 : ["Thaana", "Thaa"], + 30 : ["Thai", "Thai"], + 31 : ["Tibetan", "Tibt"], + 32 : ["Sinhala", "Sinh"], + 33 : ["Syriac", "Syrc"], + 34 : ["Yi", "Yiii"], + 35 : ["Vai", "Vaii"], + 36 : ["Avestan", "Avst"], + 37 : ["Balinese", "Bali"], + 38 : ["Bamum", "Bamu"], + 39 : ["Batak", "Batk"], + 40 : ["Bopomofo", "Bopo"], + 41 : ["Brahmi", "Brah"], + 42 : ["Buginese", "Bugi"], + 43 : ["Buhid", "Buhd"], + 44 : ["Canadian Aboriginal", "Cans"], + 45 : ["Carian", "Cari"], + 46 : ["Chakma", "Cakm"], + 47 : ["Cham", "Cham"], + 48 : ["Coptic", "Copt"], + 49 : ["Cypriot", "Cprt"], + 50 : ["Egyptian Hieroglyphs", "Egyp"], + 51 : ["Fraser", "Lisu"], + 52 : ["Glagolitic", "Glag"], + 53 : ["Gothic", "Goth"], + 54 : ["Han", "Hani"], + 55 : ["Hangul", "Hang"], + 56 : ["Hanunoo", "Hano"], + 57 : ["Imperial Aramaic", "Armi"], + 58 : ["Inscriptional Pahlavi", "Phli"], + 59 : ["Inscriptional Parthian", "Prti"], + 60 : ["Javanese", "Java"], + 61 : ["Kaithi", "Kthi"], + 62 : ["Katakana", "Kana"], + 63 : ["Kayah Li", "Kali"], + 64 : ["Kharoshthi", "Khar"], + 65 : ["Lanna", "Lana"], + 66 : ["Lepcha", "Lepc"], + 67 : ["Limbu", "Limb"], + 68 : ["Linear B", "Linb"], + 69 : ["Lycian", "Lyci"], + 70 : ["Lydian", "Lydi"], + 71 : ["Mandaean", "Mand"], + 72 : ["Meitei Mayek", "Mtei"], + 73 : ["Meroitic", "Mero"], + 74 : ["Meroitic Cursive", "Merc"], + 75 : ["Nko", "Nkoo"], + 76 : ["New Tai Lue", "Talu"], + 77 : ["Ogham", "Ogam"], + 78 : ["Ol Chiki", "Olck"], + 79 : ["Old Italic", "Ital"], + 80 : ["Old Persian", "Xpeo"], + 81 : ["Old South Arabian", "Sarb"], + 82 : ["Orkhon", "Orkh"], + 83 : ["Osmanya", "Osma"], + 84 : ["Phags Pa", "Phag"], + 85 : ["Phoenician", "Phnx"], + 86 : ["Pollard Phonetic", "Plrd"], + 87 : ["Rejang", "Rjng"], + 88 : ["Runic", "Runr"], + 89 : ["Samaritan", "Samr"], + 90 : ["Saurashtra", "Saur"], + 91 : ["Sharada", "Shrd"], + 92 : ["Shavian", "Shaw"], + 93 : ["Sora Sompeng", "Sora"], + 94 : ["Cuneiform", "Xsux"], + 95 : ["Sundanese", "Sund"], + 96 : ["Syloti Nagri", "Sylo"], + 97 : ["Tagalog", "Tglg"], + 98 : ["Tagbanwa", "Tagb"], + 99 : ["Tai Le", "Tale"], + 100 : ["Tai Viet", "Tavt"], + 101 : ["Takri", "Takr"], + 102 : ["Ugaritic", "Ugar"], + 103 : ["Braille", "Brai"], + 104 : ["Hiragana", "Hira"], + 105 : ["Caucasian Albanian", "Aghb"], + 106 : ["Bassa Vah", "Bass"], + 107 : ["Duployan", "Dupl"], + 108 : ["Elbasan", "Elba"], + 109 : ["Grantha", "Gran"], + 110 : ["Pahawh Hmong", "Hmng"], + 111 : ["Khojki", "Khoj"], + 112 : ["Linear A", "Lina"], + 113 : ["Mahajani", "Mahj"], + 114 : ["Manichaean", "Mani"], + 115 : ["Mende Kikakui", "Mend"], + 116 : ["Modi", "Modi"], + 117 : ["Mro", "Mroo"], + 118 : ["Old North Arabian", "Narb"], + 119 : ["Nabataean", "Nbat"], + 120 : ["Palmyrene", "Palm"], + 121 : ["Pau Cin Hau", "Pauc"], + 122 : ["Old Permic", "Perm"], + 123 : ["Psalter Pahlavi", "Phlp"], + 124 : ["Siddham", "Sidd"], + 125 : ["Khudawadi", "Sind"], + 126 : ["Tirhuta", "Tirh"], + 127 : ["Varang Kshiti", "Wara"], + 128 : ["Ahom", "Ahom"], + 129 : ["Anatolian Hieroglyphs", "Hluw"], + 130 : ["Hatran", "Hatr"], + 131 : ["Multani", "Mult"], + 132 : ["Old Hungarian", "Hung"], + 133 : ["Sign Writing", "Sgnw"], + 134 : ["Adlam", "Adlm"], + 135 : ["Bhaiksuki", "Bhks"], + 136 : ["Marchen", "Marc"], + 137 : ["Newa", "Newa"], + 138 : ["Osage", "Osge"], + 139 : ["Tangut", "Tang"], + 140 : ["Han with Bopomofo", "Hanb"], + 141 : ["Jamo", "Jamo"] } def countryCodeToId(code): -- cgit v1.2.3 From cd0a76a1503668155f67d7243e6e9aa8c4d77377 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Mon, 13 Aug 2018 14:32:18 +0200 Subject: Tidy up generation of aliases in locale-related enums Replace lines of formatted output with dictionaries from which that output can be generated efficiently (in sorted order). Tidy up the python code, in the process. Change-Id: Ifb74eb69342646c5dbabc3247b3a8ddef602e934 Reviewed-by: Thiago Macieira --- src/corelib/tools/qlocale.h | 24 ++++++------- util/local_database/enumdata.py | 49 +++++++++++++++++++++++-- util/local_database/qlocalexml2cpp.py | 67 +++++++++++++---------------------- 3 files changed, 82 insertions(+), 58 deletions(-) diff --git a/src/corelib/tools/qlocale.h b/src/corelib/tools/qlocale.h index e3d6c84c50..8e6c5c503b 100644 --- a/src/corelib/tools/qlocale.h +++ b/src/corelib/tools/qlocale.h @@ -437,19 +437,19 @@ public: Osage = 358, Tangut = 359, - Norwegian = NorwegianBokmal, - Moldavian = Romanian, - SerboCroatian = Serbian, - Tagalog = Filipino, - Twi = Akan, Afan = Oromo, - Byelorussian = Belarusian, Bhutani = Dzongkha, + Byelorussian = Belarusian, Cambodian = Khmer, - Kurundi = Rundi, - RhaetoRomance = Romansh, Chewa = Nyanja, Frisian = WesternFrisian, + Kurundi = Rundi, + Moldavian = Romanian, + Norwegian = NorwegianBokmal, + RhaetoRomance = Romansh, + SerboCroatian = Serbian, + Tagalog = Filipino, + Twi = Akan, Uigur = Uighur, LastLanguage = Tangut @@ -868,15 +868,15 @@ public: World = 260, Europe = 261, - Tokelau = TokelauCountry, - Tuvalu = TuvaluCountry, DemocraticRepublicOfCongo = CongoKinshasa, - PeoplesRepublicOfCongo = CongoBrazzaville, DemocraticRepublicOfKorea = NorthKorea, + LatinAmericaAndTheCaribbean = LatinAmerica, + PeoplesRepublicOfCongo = CongoBrazzaville, RepublicOfKorea = SouthKorea, RussianFederation = Russia, SyrianArabRepublic = Syria, - LatinAmericaAndTheCaribbean = LatinAmerica, + Tokelau = TokelauCountry, + Tuvalu = TuvaluCountry, LastCountry = Europe }; diff --git a/util/local_database/enumdata.py b/util/local_database/enumdata.py index 5505b68575..e24ac02b07 100644 --- a/util/local_database/enumdata.py +++ b/util/local_database/enumdata.py @@ -27,9 +27,13 @@ ## ############################################################################# -# language_list and country_list reflect the current values of enums in qlocale.h -# If new xml language files are available in CLDR, these languages and countries -# need to be *appended* to this list (for compatibility between versions). +# Each *_list reflects the current values of its enums in qlocale.h; +# if new xml language files are available in CLDR, these languages and +# countries need to be *appended* to this list (for compatibility +# between versions). Include any spaces present in names (scripts +# shall squish them out for the enum entries) in *_list, but use the +# squished forms of names in the *_aliases mappings. + ### Qt 6: restore alphabetic order in each list. language_list = { @@ -395,6 +399,25 @@ language_list = { 359 : ["Tangut", "txg"] } +language_aliases = { + # Legacy - should disappear at some point: + 'Norwegian': 'NorwegianBokmal', + 'Moldavian': 'Romanian', + 'SerboCroatian': 'Serbian', + 'Tagalog': 'Filipino', + 'Twi': 'Akan', + # Renamings: + 'Afan': 'Oromo', + 'Byelorussian': 'Belarusian', + 'Bhutani': 'Dzongkha', + 'Cambodian': 'Khmer', + 'Kurundi': 'Rundi', + 'RhaetoRomance': 'Romansh', + 'Chewa': 'Nyanja', + 'Frisian': 'WesternFrisian', + 'Uigur': 'Uighur', +} + country_list = { 0 : ["AnyCountry", "ZZ"], 1 : ["Afghanistan", "AF"], @@ -660,6 +683,20 @@ country_list = { 261 : ["Europe", "150"] } +country_aliases = { + # Deprecated: + 'Tokelau': 'TokelauCountry', + 'Tuvalu': 'TuvaluCountry', + # Renamings: + 'DemocraticRepublicOfCongo': 'CongoKinshasa', + 'PeoplesRepublicOfCongo': 'CongoBrazzaville', + 'DemocraticRepublicOfKorea': 'NorthKorea', + 'RepublicOfKorea': 'SouthKorea', + 'RussianFederation': 'Russia', + 'SyrianArabRepublic': 'Syria', + 'LatinAmericaAndTheCaribbean': 'LatinAmerica', +} + script_list = { 0 : ["AnyScript", "Zzzz"], 1 : ["Arabic", "Arab"], @@ -805,6 +842,12 @@ script_list = { 141 : ["Jamo", "Jamo"] } +script_aliases = { + # Renamings: + 'SimplifiedChineseScript': 'SimplifiedHanScript', + 'TraditionalChineseScript': 'TraditionalHanScript', +} + def countryCodeToId(code): if not code: return 0 diff --git a/util/local_database/qlocalexml2cpp.py b/util/local_database/qlocalexml2cpp.py index b1dfddea23..fb5ae5ba54 100755 --- a/util/local_database/qlocalexml2cpp.py +++ b/util/local_database/qlocalexml2cpp.py @@ -38,6 +38,7 @@ import sys import tempfile import datetime import xml.dom.minidom +from enumdata import language_aliases, country_aliases, script_aliases from localexml import Locale @@ -751,27 +752,15 @@ def main(): # Language enum qlocaleh_temp_file.write(" enum Language {\n") - language = "" - for key in language_map.keys(): - language = fixedLanguageName(language_map[key][0], dupes) + language = None + for key, value in language_map.items(): + language = fixedLanguageName(value[0], dupes) qlocaleh_temp_file.write(" " + language + " = " + str(key) + ",\n") - # legacy. should disappear at some point - qlocaleh_temp_file.write("\n") - qlocaleh_temp_file.write(" Norwegian = NorwegianBokmal,\n") - qlocaleh_temp_file.write(" Moldavian = Romanian,\n") - qlocaleh_temp_file.write(" SerboCroatian = Serbian,\n") - qlocaleh_temp_file.write(" Tagalog = Filipino,\n") - qlocaleh_temp_file.write(" Twi = Akan,\n") - # renamings - qlocaleh_temp_file.write(" Afan = Oromo,\n") - qlocaleh_temp_file.write(" Byelorussian = Belarusian,\n") - qlocaleh_temp_file.write(" Bhutani = Dzongkha,\n") - qlocaleh_temp_file.write(" Cambodian = Khmer,\n") - qlocaleh_temp_file.write(" Kurundi = Rundi,\n") - qlocaleh_temp_file.write(" RhaetoRomance = Romansh,\n") - qlocaleh_temp_file.write(" Chewa = Nyanja,\n") - qlocaleh_temp_file.write(" Frisian = WesternFrisian,\n") - qlocaleh_temp_file.write(" Uigur = Uighur,\n") + + qlocaleh_temp_file.write("\n " + + ",\n ".join('%s = %s' % pair + for pair in sorted(language_aliases.items())) + + ",\n") qlocaleh_temp_file.write("\n") qlocaleh_temp_file.write(" LastLanguage = " + language + "\n") qlocaleh_temp_file.write(" };\n") @@ -780,36 +769,28 @@ def main(): # Script enum qlocaleh_temp_file.write(" enum Script {\n") - script = "" - for key in script_map.keys(): - script = fixedScriptName(script_map[key][0], dupes) + script = None + for key, value in script_map.items(): + script = fixedScriptName(value[0], dupes) qlocaleh_temp_file.write(" " + script + " = " + str(key) + ",\n") - # renamings - qlocaleh_temp_file.write("\n") - qlocaleh_temp_file.write(" SimplifiedChineseScript = SimplifiedHanScript,\n") - qlocaleh_temp_file.write(" TraditionalChineseScript = TraditionalHanScript,\n") + qlocaleh_temp_file.write("\n " + + ",\n ".join('%s = %s' % pair + for pair in sorted(script_aliases.items())) + + ",\n") qlocaleh_temp_file.write("\n") qlocaleh_temp_file.write(" LastScript = " + script + "\n") qlocaleh_temp_file.write(" };\n") # Country enum qlocaleh_temp_file.write(" enum Country {\n") - country = "" - for key in country_map.keys(): - country = fixedCountryName(country_map[key][0], dupes) + country = None + for key, value in country_map.items(): + country = fixedCountryName(value[0], dupes) qlocaleh_temp_file.write(" " + country + " = " + str(key) + ",\n") - # deprecated - qlocaleh_temp_file.write("\n") - qlocaleh_temp_file.write(" Tokelau = TokelauCountry,\n") - qlocaleh_temp_file.write(" Tuvalu = TuvaluCountry,\n") - # renamings - qlocaleh_temp_file.write(" DemocraticRepublicOfCongo = CongoKinshasa,\n") - qlocaleh_temp_file.write(" PeoplesRepublicOfCongo = CongoBrazzaville,\n") - qlocaleh_temp_file.write(" DemocraticRepublicOfKorea = NorthKorea,\n") - qlocaleh_temp_file.write(" RepublicOfKorea = SouthKorea,\n") - qlocaleh_temp_file.write(" RussianFederation = Russia,\n") - qlocaleh_temp_file.write(" SyrianArabRepublic = Syria,\n") - qlocaleh_temp_file.write(" LatinAmericaAndTheCaribbean = LatinAmerica,\n") + qlocaleh_temp_file.write("\n " + + ",\n ".join('%s = %s' % pair + for pair in sorted(country_aliases.items())) + + ",\n") qlocaleh_temp_file.write("\n") qlocaleh_temp_file.write(" LastCountry = " + country + "\n") qlocaleh_temp_file.write(" };\n") @@ -836,7 +817,7 @@ def main(): qlocaleqdoc_temp_file = os.fdopen(qlocaleqdoc_temp_file, "w") qlocaleqdoc_file = open(qtsrcdir + "/src/corelib/tools/qlocale.qdoc", "r") s = qlocaleqdoc_file.readline() - DOCSTRING=" QLocale's data is based on Common Locale Data Repository " + DOCSTRING = " QLocale's data is based on Common Locale Data Repository " while s: if DOCSTRING in s: qlocaleqdoc_temp_file.write(DOCSTRING + "v" + cldr_version + ".\n") -- cgit v1.2.3 From bcf0be9b8ffa4739c2be26c53210b2fe3c3f1fe0 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 15 Aug 2018 10:32:25 +0200 Subject: Avoid signed/unsigned warning in template tst_QtEndian's transformRegion_template() was getting a signed/unsigned comparison warning when T was unsigned in a QCOMPARE(T-value, 0); so use T(0) instead. Change-Id: I78cb2ab96f79393def65ed2c020aa3039017ab92 Reviewed-by: Thiago Macieira --- tests/auto/corelib/global/qtendian/tst_qtendian.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/corelib/global/qtendian/tst_qtendian.cpp b/tests/auto/corelib/global/qtendian/tst_qtendian.cpp index 89c93bf245..7043969c2f 100644 --- a/tests/auto/corelib/global/qtendian/tst_qtendian.cpp +++ b/tests/auto/corelib/global/qtendian/tst_qtendian.cpp @@ -134,7 +134,7 @@ void transformRegion_template(T (*transformOne)(T), void (*transformRegion)(cons auto checkBounds = [&](int from) { for ( ; from < Size; ++from) - QCOMPARE(dest[from], 0); + QCOMPARE(dest[from], T(0)); }; transformRegion(source, 1, dest); -- cgit v1.2.3 From 32f1bf0cac28806ae79a7467ed9dd5f16f6debde Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 15 Aug 2018 14:09:38 +0200 Subject: Update QLocale::Country doc for new territories Neglected in 44b6757fe50b6bf581864d3da519a3ff60818fa8 Noted the need for this in a relevant script's instructions. Change-Id: If69666f1799acebd434034c80b91056cb8777488 Reviewed-by: Konstantin Ritt Reviewed-by: Thiago Macieira --- src/corelib/tools/qlocale.qdoc | 5 ++++- util/local_database/cldr2qlocalexml.py | 7 ++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/corelib/tools/qlocale.qdoc b/src/corelib/tools/qlocale.qdoc index bbb13bd165..5c0a9b63e5 100644 --- a/src/corelib/tools/qlocale.qdoc +++ b/src/corelib/tools/qlocale.qdoc @@ -568,6 +568,7 @@ \value Estonia \value Ethiopia \value EuropeanUnion Since Qt 5.7 + \value Europe Since Qt 5.12 \value FalklandIslands \value FaroeIslands \value Fiji @@ -619,6 +620,8 @@ \value Kuwait \value Kyrgyzstan \value Laos + \value LatinAmerica + \value LatinAmericaAndTheCaribbean Obsolete, please use LatinAmerica \value Latvia \value Lebanon \value Lesotho @@ -742,6 +745,7 @@ \value UnitedStatesVirginIslands \value WallisAndFutunaIslands \value WesternSahara + \value World Since Qt 5.12 \value Yemen \value Zambia \value Zimbabwe @@ -749,7 +753,6 @@ \value Serbia \value SaintBarthelemy \value SaintMartin - \value LatinAmericaAndTheCaribbean \value AscensionIsland \value AlandIslands \value DiegoGarcia diff --git a/util/local_database/cldr2qlocalexml.py b/util/local_database/cldr2qlocalexml.py index c8605dcc94..ce45f631a6 100755 --- a/util/local_database/cldr2qlocalexml.py +++ b/util/local_database/cldr2qlocalexml.py @@ -38,7 +38,12 @@ command-line argument. Save its standard output (but not error) to a file for later processing by ``./qlocalexml2cpp.py`` When you update the CLDR data, be sure to also update -src/corelib/tools/qt_attribution.json's entry for unicode-cldr. +src/corelib/tools/qt_attribution.json's entry for unicode-cldr. Check +this script's output for unknown language, country or script messages; +if any can be resolved, use their entry in common/main/en.xml to +append new entries to enumdata.py's lists and update documentation in +src/corelib/tools/qlocale.qdoc, adding the new entries in alphabetic +order. .. _CLDR: ftp://unicode.org/Public/cldr/ """ -- cgit v1.2.3 From 9b59a2ef973a067fb0c4a43396d1aca329b24f9c Mon Sep 17 00:00:00 2001 From: Paul Wicking Date: Fri, 3 Aug 2018 14:51:37 +0200 Subject: Doc: Update out-of-date screenshots in example docs Task-number: QTBUG-63248 Change-Id: I4cd47977ae020b43ca92b1781ac8b038e6ef851c Reviewed-by: Martin Smith --- doc/src/images/standarddialogs-example.png | Bin 18852 -> 25619 bytes .../widgets/doc/images/basiclayouts-example.png | Bin 28771 -> 20791 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/src/images/standarddialogs-example.png b/doc/src/images/standarddialogs-example.png index b6b8a076db..f584ebb27d 100644 Binary files a/doc/src/images/standarddialogs-example.png and b/doc/src/images/standarddialogs-example.png differ diff --git a/examples/widgets/doc/images/basiclayouts-example.png b/examples/widgets/doc/images/basiclayouts-example.png index 4a1c45dd80..d19afdb069 100644 Binary files a/examples/widgets/doc/images/basiclayouts-example.png and b/examples/widgets/doc/images/basiclayouts-example.png differ -- cgit v1.2.3 From 37bb907a921edab7e2ac675f82d93cc08e96fc01 Mon Sep 17 00:00:00 2001 From: Mitch Curtis Date: Tue, 7 Aug 2018 11:06:35 +0200 Subject: Add debugging output to help diagnose cause of tst_qspinbox failure I've tried to reproduce the failures in the CI a couple of times now, but it keeps passing. Let's leave some debug output in the test so that if/when it does fail, we might know a bit more about why it does so. Task-number: QTBUG-69492 Change-Id: I5b39ac692e9026ce4b25cd13d342b11e061b777b Reviewed-by: Edward Welbourne Reviewed-by: Nathan Collins Reviewed-by: Oliver Wolff --- tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp b/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp index 5a51bab51f..37bb28dec9 100644 --- a/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp +++ b/tests/auto/widgets/widgets/qspinbox/tst_qspinbox.cpp @@ -1775,6 +1775,10 @@ void tst_QSpinBox::stepModifierPressAndHold() spin.setStyle(stepModifierStyle.data()); QSignalSpy spy(&spin, QOverload::of(&SpinBox::valueChanged)); + // TODO: remove debug output when QTBUG-69492 is fixed + connect(&spin, QOverload::of(&SpinBox::valueChanged), [=]() { + qDebug() << QTime::currentTime() << "valueChanged emitted"; + }); spin.show(); QVERIFY(QTest::qWaitForWindowActive(&spin)); @@ -1785,6 +1789,9 @@ void tst_QSpinBox::stepModifierPressAndHold() const QRect buttonRect = spin.style()->subControlRect( QStyle::CC_SpinBox, &spinBoxStyleOption, subControl, &spin); + // TODO: remove debug output when QTBUG-69492 is fixed + qDebug() << "QGuiApplication::focusWindow():" << QGuiApplication::focusWindow(); + qDebug() << "QGuiApplication::topLevelWindows():" << QGuiApplication::topLevelWindows(); QTest::mousePress(&spin, Qt::LeftButton, modifiers, buttonRect.center()); QTRY_VERIFY2(spy.length() >= 3, qPrintable(QString::fromLatin1( "Expected valueChanged() to be emitted 3 or more times, but it was only emitted %1 times").arg(spy.length()))); -- cgit v1.2.3 From 0f6b941ca54f9714627b8d5a94be163dc02126c1 Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Mon, 30 Jul 2018 18:31:50 +0200 Subject: xcb: cleanup QXcbConnection::handleXcbEvent() - the usage of 'handled' variable was a mess. - remove "generic" from API names. The naming was probably influenced too much from underlying C API (xcb_generic_event_t): - handleGenericEvent() -> handleNativeEvent() to be consistent with QWindow::nativeEvent(). - dropped unnecessary 'long *result' from signature. It is useful only on MS Windows. - genericEventFilterType() -> nativeEventType(), it *is* an event type, not a filter type. - XCB_CLIENT_MESSAGE was not passed to QWindow::nativeEvent(), which is done via HANDLE_PLATFORM_WINDOW_EVENT. - minor: added some 'auto's where it makes sense and improved some variable names. Change-Id: Id1c9896054e2dbd9a79bacd88394149c8cf2cdea Reviewed-by: Shawn Rutledge --- .../gl_integrations/xcb_glx/qxcbglxintegration.cpp | 4 +- src/plugins/platforms/xcb/qxcbconnection.cpp | 367 ++++++++++----------- src/plugins/platforms/xcb/qxcbconnection.h | 3 +- src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 3 +- src/plugins/platforms/xcb/qxcbnativeinterface.cpp | 3 +- src/plugins/platforms/xcb/qxcbnativeinterface.h | 4 +- src/plugins/platforms/xcb/qxcbwindow.cpp | 9 +- src/plugins/platforms/xcb/qxcbwindow.h | 2 +- 8 files changed, 189 insertions(+), 206 deletions(-) diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp index a7641baea1..b751aaf8a3 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp @@ -163,9 +163,9 @@ bool QXcbGlxIntegration::handleXcbEvent(xcb_generic_event_t *event, uint respons // Unlock the display before calling the native event filter XUnlockDisplay(xdisplay); locked = false; - QByteArray genericEventFilterType = m_connection->nativeInterface()->genericEventFilterType(); + auto eventType = m_connection->nativeInterface()->nativeEventType(); long result = 0; - handled = dispatcher->filterNativeEvent(genericEventFilterType, &ev, &result); + handled = dispatcher->filterNativeEvent(eventType, &ev, &result); } #endif } diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 1a5d9d1667..75275f6fd2 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -733,22 +733,22 @@ QXcbWindow *QXcbConnection::platformWindowFromId(xcb_window_t id) #define HANDLE_PLATFORM_WINDOW_EVENT(event_t, windowMember, handler) \ { \ - event_t *e = reinterpret_cast(event); \ + auto e = reinterpret_cast(event); \ if (QXcbWindowEventListener *eventListener = windowEventListenerFromId(e->windowMember)) { \ - handled = eventListener->handleGenericEvent(event, &result); \ - if (!handled) \ - eventListener->handler(e); \ + if (eventListener->handleNativeEvent(event)) \ + return; \ + eventListener->handler(e); \ } \ } \ break; #define HANDLE_KEYBOARD_EVENT(event_t, handler) \ { \ - event_t *e = reinterpret_cast(event); \ + auto e = reinterpret_cast(event); \ if (QXcbWindowEventListener *eventListener = windowEventListenerFromId(e->event)) { \ - handled = eventListener->handleGenericEvent(event, &result); \ - if (!handled) \ - m_keyboard->handler(e); \ + if (eventListener->handleNativeEvent(event)) \ + return; \ + m_keyboard->handler(e); \ } \ } \ break; @@ -974,7 +974,7 @@ void QXcbConnection::handleXcbError(xcb_generic_error_t *error) { long result = 0; QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance(); - if (dispatcher && dispatcher->filterNativeEvent(m_nativeInterface->genericEventFilterType(), error, &result)) + if (dispatcher && dispatcher->filterNativeEvent(m_nativeInterface->nativeEventType(), error, &result)) return; printXcbError("QXcbConnection: XCB error", error); @@ -1066,197 +1066,206 @@ namespace { void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) { - long result = 0; + if (Q_UNLIKELY(lcQpaEvents().isDebugEnabled())) + printXcbEvent(lcQpaEvents(), "Event", event); + + long result = 0; // Used only by MS Windows QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance(); - bool handled = dispatcher && dispatcher->filterNativeEvent(m_nativeInterface->genericEventFilterType(), event, &result); + bool handledByNativeEventFilter = dispatcher && dispatcher->filterNativeEvent( + m_nativeInterface->nativeEventType(), event, &result); + if (handledByNativeEventFilter) + return; uint response_type = event->response_type & ~0x80; - if (!handled) { - switch (response_type) { - case XCB_EXPOSE: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_expose_event_t, window, handleExposeEvent); - - case XCB_BUTTON_PRESS: { - xcb_button_press_event_t *ev = (xcb_button_press_event_t *)event; - m_keyboard->updateXKBStateFromCore(ev->state); - // the event explicitly contains the state of the three first buttons, - // the rest we need to manage ourselves - m_buttonState = (m_buttonState & ~0x7) | translateMouseButtons(ev->state); - setButtonState(translateMouseButton(ev->detail), true); - if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) - qCDebug(lcQpaXInputEvents, "legacy mouse press, button %d state %X", ev->detail, static_cast(m_buttonState)); - HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_press_event_t, event, handleButtonPressEvent); - } - case XCB_BUTTON_RELEASE: { - xcb_button_release_event_t *ev = (xcb_button_release_event_t *)event; - m_keyboard->updateXKBStateFromCore(ev->state); - m_buttonState = (m_buttonState & ~0x7) | translateMouseButtons(ev->state); - setButtonState(translateMouseButton(ev->detail), false); - if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) - qCDebug(lcQpaXInputEvents, "legacy mouse release, button %d state %X", ev->detail, static_cast(m_buttonState)); - HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_release_event_t, event, handleButtonReleaseEvent); - } - case XCB_MOTION_NOTIFY: { - xcb_motion_notify_event_t *ev = (xcb_motion_notify_event_t *)event; - m_keyboard->updateXKBStateFromCore(ev->state); - m_buttonState = (m_buttonState & ~0x7) | translateMouseButtons(ev->state); - if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) - qCDebug(lcQpaXInputEvents, "legacy mouse move %d,%d button %d state %X", ev->event_x, ev->event_y, - ev->detail, static_cast(m_buttonState)); - HANDLE_PLATFORM_WINDOW_EVENT(xcb_motion_notify_event_t, event, handleMotionNotifyEvent); - } - - case XCB_CONFIGURE_NOTIFY: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_configure_notify_event_t, event, handleConfigureNotifyEvent); - case XCB_MAP_NOTIFY: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_map_notify_event_t, event, handleMapNotifyEvent); - case XCB_UNMAP_NOTIFY: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_unmap_notify_event_t, event, handleUnmapNotifyEvent); - case XCB_DESTROY_NOTIFY: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_destroy_notify_event_t, event, handleDestroyNotifyEvent); - case XCB_CLIENT_MESSAGE: - handleClientMessageEvent((xcb_client_message_event_t *)event); - break; - case XCB_ENTER_NOTIFY: -#if QT_CONFIG(xcb_xinput) - if (hasXInput2() && !xi2MouseEventsDisabled()) - break; + bool handled = true; + switch (response_type) { + case XCB_EXPOSE: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_expose_event_t, window, handleExposeEvent); + case XCB_BUTTON_PRESS: { + auto ev = reinterpret_cast(event); + m_keyboard->updateXKBStateFromCore(ev->state); + // the event explicitly contains the state of the three first buttons, + // the rest we need to manage ourselves + m_buttonState = (m_buttonState & ~0x7) | translateMouseButtons(ev->state); + setButtonState(translateMouseButton(ev->detail), true); + if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) + qCDebug(lcQpaXInputEvents, "legacy mouse press, button %d state %X", + ev->detail, static_cast(m_buttonState)); + HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_press_event_t, event, handleButtonPressEvent); + } + case XCB_BUTTON_RELEASE: { + auto ev = reinterpret_cast(event); + m_keyboard->updateXKBStateFromCore(ev->state); + m_buttonState = (m_buttonState & ~0x7) | translateMouseButtons(ev->state); + setButtonState(translateMouseButton(ev->detail), false); + if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) + qCDebug(lcQpaXInputEvents, "legacy mouse release, button %d state %X", + ev->detail, static_cast(m_buttonState)); + HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_release_event_t, event, handleButtonReleaseEvent); + } + case XCB_MOTION_NOTIFY: { + auto ev = reinterpret_cast(event); + m_keyboard->updateXKBStateFromCore(ev->state); + m_buttonState = (m_buttonState & ~0x7) | translateMouseButtons(ev->state); + if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) + qCDebug(lcQpaXInputEvents, "legacy mouse move %d,%d button %d state %X", + ev->event_x, ev->event_y, ev->detail, static_cast(m_buttonState)); + HANDLE_PLATFORM_WINDOW_EVENT(xcb_motion_notify_event_t, event, handleMotionNotifyEvent); + } + case XCB_CONFIGURE_NOTIFY: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_configure_notify_event_t, event, handleConfigureNotifyEvent); + case XCB_MAP_NOTIFY: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_map_notify_event_t, event, handleMapNotifyEvent); + case XCB_UNMAP_NOTIFY: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_unmap_notify_event_t, event, handleUnmapNotifyEvent); + case XCB_DESTROY_NOTIFY: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_destroy_notify_event_t, event, handleDestroyNotifyEvent); + case XCB_CLIENT_MESSAGE: { + auto clientMessage = reinterpret_cast(event); + if (clientMessage->format != 32) + return; +#if QT_CONFIG(draganddrop) + if (clientMessage->type == atom(QXcbAtom::XdndStatus)) + drag()->handleStatus(clientMessage); + else if (clientMessage->type == atom(QXcbAtom::XdndFinished)) + drag()->handleFinished(clientMessage); #endif - HANDLE_PLATFORM_WINDOW_EVENT(xcb_enter_notify_event_t, event, handleEnterNotifyEvent); - case XCB_LEAVE_NOTIFY: + if (m_systemTrayTracker && clientMessage->type == atom(QXcbAtom::MANAGER)) + m_systemTrayTracker->notifyManagerClientMessageEvent(clientMessage); + HANDLE_PLATFORM_WINDOW_EVENT(xcb_client_message_event_t, window, handleClientMessageEvent); + } + case XCB_ENTER_NOTIFY: #if QT_CONFIG(xcb_xinput) - if (hasXInput2() && !xi2MouseEventsDisabled()) - break; + if (hasXInput2() && !xi2MouseEventsDisabled()) + break; #endif - m_keyboard->updateXKBStateFromCore(((xcb_leave_notify_event_t *)event)->state); - HANDLE_PLATFORM_WINDOW_EVENT(xcb_leave_notify_event_t, event, handleLeaveNotifyEvent); - case XCB_FOCUS_IN: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_in_event_t, event, handleFocusInEvent); - case XCB_FOCUS_OUT: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_out_event_t, event, handleFocusOutEvent); - case XCB_KEY_PRESS: - { - xcb_key_press_event_t *kp = (xcb_key_press_event_t *)event; - m_keyboard->updateXKBStateFromCore(kp->state); - setTime(kp->time); - HANDLE_KEYBOARD_EVENT(xcb_key_press_event_t, handleKeyPressEvent); - } - case XCB_KEY_RELEASE: - m_keyboard->updateXKBStateFromCore(((xcb_key_release_event_t *)event)->state); - HANDLE_KEYBOARD_EVENT(xcb_key_release_event_t, handleKeyReleaseEvent); - case XCB_MAPPING_NOTIFY: - m_keyboard->updateKeymap(reinterpret_cast(event)); + HANDLE_PLATFORM_WINDOW_EVENT(xcb_enter_notify_event_t, event, handleEnterNotifyEvent); + case XCB_LEAVE_NOTIFY: +#if QT_CONFIG(xcb_xinput) + if (hasXInput2() && !xi2MouseEventsDisabled()) break; - case XCB_SELECTION_REQUEST: - { +#endif + m_keyboard->updateXKBStateFromCore(reinterpret_cast(event)->state); + HANDLE_PLATFORM_WINDOW_EVENT(xcb_leave_notify_event_t, event, handleLeaveNotifyEvent); + case XCB_FOCUS_IN: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_in_event_t, event, handleFocusInEvent); + case XCB_FOCUS_OUT: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_out_event_t, event, handleFocusOutEvent); + case XCB_KEY_PRESS: + { + auto keyPress = reinterpret_cast(event); + m_keyboard->updateXKBStateFromCore(keyPress->state); + setTime(keyPress->time); + HANDLE_KEYBOARD_EVENT(xcb_key_press_event_t, handleKeyPressEvent); + } + case XCB_KEY_RELEASE: + m_keyboard->updateXKBStateFromCore(reinterpret_cast(event)->state); + HANDLE_KEYBOARD_EVENT(xcb_key_release_event_t, handleKeyReleaseEvent); + case XCB_MAPPING_NOTIFY: + m_keyboard->updateKeymap(reinterpret_cast(event)); + break; + case XCB_SELECTION_REQUEST: + { #if QT_CONFIG(draganddrop) || QT_CONFIG(clipboard) - xcb_selection_request_event_t *sr = reinterpret_cast(event); + auto selectionRequest = reinterpret_cast(event); #endif #if QT_CONFIG(draganddrop) - if (sr->selection == atom(QXcbAtom::XdndSelection)) - m_drag->handleSelectionRequest(sr); - else + if (selectionRequest->selection == atom(QXcbAtom::XdndSelection)) + m_drag->handleSelectionRequest(selectionRequest); + else #endif - { + { #ifndef QT_NO_CLIPBOARD - m_clipboard->handleSelectionRequest(sr); + m_clipboard->handleSelectionRequest(selectionRequest); #endif - } - break; } - case XCB_SELECTION_CLEAR: - setTime((reinterpret_cast(event))->time); + break; + } + case XCB_SELECTION_CLEAR: + setTime((reinterpret_cast(event))->time); #ifndef QT_NO_CLIPBOARD - m_clipboard->handleSelectionClearRequest(reinterpret_cast(event)); + m_clipboard->handleSelectionClearRequest(reinterpret_cast(event)); #endif - handled = true; - break; - case XCB_SELECTION_NOTIFY: - setTime((reinterpret_cast(event))->time); - handled = false; - break; - case XCB_PROPERTY_NOTIFY: - { - xcb_property_notify_event_t *pn = reinterpret_cast(event); - if (pn->atom == atom(QXcbAtom::_NET_WORKAREA)) { - QXcbVirtualDesktop *virtualDesktop = virtualDesktopForRootWindow(pn->window); - if (virtualDesktop) - virtualDesktop->updateWorkArea(); - } else { - HANDLE_PLATFORM_WINDOW_EVENT(xcb_property_notify_event_t, window, handlePropertyNotifyEvent); - } - break; + break; + case XCB_SELECTION_NOTIFY: + setTime((reinterpret_cast(event))->time); + break; + case XCB_PROPERTY_NOTIFY: + { + auto propertyNotify = reinterpret_cast(event); + if (propertyNotify->atom == atom(QXcbAtom::_NET_WORKAREA)) { + QXcbVirtualDesktop *virtualDesktop = virtualDesktopForRootWindow(propertyNotify->window); + if (virtualDesktop) + virtualDesktop->updateWorkArea(); + } else { + HANDLE_PLATFORM_WINDOW_EVENT(xcb_property_notify_event_t, window, handlePropertyNotifyEvent); } + break; + } #if QT_CONFIG(xcb_xinput) - case XCB_GE_GENERIC: - // Here the windowEventListener is invoked from xi2HandleEvent() - if (hasXInput2() && isXIEvent(event, m_xiOpCode)) - xi2HandleEvent(reinterpret_cast(event)); - break; + case XCB_GE_GENERIC: + // Here the windowEventListener is invoked from xi2HandleEvent() + if (hasXInput2() && isXIEvent(event, m_xiOpCode)) + xi2HandleEvent(reinterpret_cast(event)); + break; #endif - default: - handled = false; - break; - } + default: + handled = false; // event type not recognized + break; } - if (!handled) { - if (has_xfixes && response_type == xfixes_first_event + XCB_XFIXES_SELECTION_NOTIFY) { - xcb_xfixes_selection_notify_event_t *notify_event = reinterpret_cast(event); - setTime(notify_event->timestamp); + if (handled) + return; + + handled = true; + if (has_xfixes && response_type == xfixes_first_event + XCB_XFIXES_SELECTION_NOTIFY) { + auto notify_event = reinterpret_cast(event); + setTime(notify_event->timestamp); #ifndef QT_NO_CLIPBOARD - m_clipboard->handleXFixesSelectionRequest(notify_event); + m_clipboard->handleXFixesSelectionRequest(notify_event); #endif - for (QXcbVirtualDesktop *virtualDesktop : qAsConst(m_virtualDesktops)) - virtualDesktop->handleXFixesSelectionNotify(notify_event); - - handled = true; - } else if (has_randr_extension && response_type == xrandr_first_event + XCB_RANDR_NOTIFY) { - updateScreens(reinterpret_cast(event)); - handled = true; - } else if (has_randr_extension && response_type == xrandr_first_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY) { - xcb_randr_screen_change_notify_event_t *change_event = reinterpret_cast(event); - if (auto *virtualDesktop = virtualDesktopForRootWindow(change_event->root)) - virtualDesktop->handleScreenChange(change_event); - - handled = true; + for (QXcbVirtualDesktop *virtualDesktop : qAsConst(m_virtualDesktops)) + virtualDesktop->handleXFixesSelectionNotify(notify_event); + } else if (has_randr_extension && response_type == xrandr_first_event + XCB_RANDR_NOTIFY) { + updateScreens(reinterpret_cast(event)); + } else if (has_randr_extension && response_type == xrandr_first_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY) { + auto change_event = reinterpret_cast(event); + if (auto virtualDesktop = virtualDesktopForRootWindow(change_event->root)) + virtualDesktop->handleScreenChange(change_event); #if QT_CONFIG(xkb) - } else if (response_type == xkb_first_event) { // https://bugs.freedesktop.org/show_bug.cgi?id=51295 - _xkb_event *xkb_event = reinterpret_cast<_xkb_event *>(event); - if (xkb_event->any.deviceID == m_keyboard->coreDeviceId()) { - switch (xkb_event->any.xkbType) { - // XkbNewKkdNotify and XkbMapNotify together capture all sorts of keymap - // updates (e.g. xmodmap, xkbcomp, setxkbmap), with minimal redundent recompilations. - case XCB_XKB_STATE_NOTIFY: - m_keyboard->updateXKBState(&xkb_event->state_notify); - handled = true; - break; - case XCB_XKB_MAP_NOTIFY: + } else if (response_type == xkb_first_event) { // https://bugs.freedesktop.org/show_bug.cgi?id=51295 + auto xkb_event = reinterpret_cast<_xkb_event *>(event); + if (xkb_event->any.deviceID == m_keyboard->coreDeviceId()) { + switch (xkb_event->any.xkbType) { + // XkbNewKkdNotify and XkbMapNotify together capture all sorts of keymap + // updates (e.g. xmodmap, xkbcomp, setxkbmap), with minimal redundent recompilations. + case XCB_XKB_STATE_NOTIFY: + m_keyboard->updateXKBState(&xkb_event->state_notify); + break; + case XCB_XKB_MAP_NOTIFY: + m_keyboard->updateKeymap(); + break; + case XCB_XKB_NEW_KEYBOARD_NOTIFY: { + xcb_xkb_new_keyboard_notify_event_t *ev = &xkb_event->new_keyboard_notify; + if (ev->changed & XCB_XKB_NKN_DETAIL_KEYCODES) m_keyboard->updateKeymap(); - handled = true; - break; - case XCB_XKB_NEW_KEYBOARD_NOTIFY: { - xcb_xkb_new_keyboard_notify_event_t *ev = &xkb_event->new_keyboard_notify; - if (ev->changed & XCB_XKB_NKN_DETAIL_KEYCODES) - m_keyboard->updateKeymap(); - break; - } - default: - break; + break; } + default: + break; } -#endif } +#endif + } else { + handled = false; // event type still not recognized } - if (!handled && m_glIntegration) - handled = m_glIntegration->handleXcbEvent(event, response_type); + if (handled) + return; -#if 0 - if (Q_UNLIKELY(lcQpaEvents().isDebugEnabled())) - printXcbEvent(lcQpaEvents(), handled ? "Handled" : "Unhandled", event); -#endif + if (m_glIntegration) + m_glIntegration->handleXcbEvent(event, response_type); } void QXcbConnection::addPeekFunc(PeekFunc f) @@ -1761,28 +1770,6 @@ void QXcbConnection::processXcbEvents() xcb_flush(xcb_connection()); } -void QXcbConnection::handleClientMessageEvent(const xcb_client_message_event_t *event) -{ - if (event->format != 32) - return; - -#if QT_CONFIG(draganddrop) - if (event->type == atom(QXcbAtom::XdndStatus)) { - drag()->handleStatus(event); - } else if (event->type == atom(QXcbAtom::XdndFinished)) { - drag()->handleFinished(event); - } -#endif - if (m_systemTrayTracker && event->type == atom(QXcbAtom::MANAGER)) - m_systemTrayTracker->notifyManagerClientMessageEvent(event); - - QXcbWindow *window = platformWindowFromId(event->window); - if (!window) - return; - - window->handleClientMessageEvent(event); -} - static const char * xcb_atomnames = { // window-manager <-> client protocols "WM_PROTOCOLS\0" diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 697b509bf0..342efca55e 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -335,7 +335,7 @@ class QXcbWindowEventListener { public: virtual ~QXcbWindowEventListener() {} - virtual bool handleGenericEvent(xcb_generic_event_t *, long *) { return false; } + virtual bool handleNativeEvent(xcb_generic_event_t *) { return false; } virtual void handleExposeEvent(const xcb_expose_event_t *) {} virtual void handleClientMessageEvent(const xcb_client_message_event_t *) {} @@ -553,7 +553,6 @@ private: void initializeXShape(); void initializeXKB(); void initializeXSync(); - void handleClientMessageEvent(const xcb_client_message_event_t *event); QXcbScreen* findScreenForCrtc(xcb_window_t rootWindow, xcb_randr_crtc_t crtc) const; QXcbScreen* findScreenForOutput(xcb_window_t rootWindow, xcb_randr_output_t output) const; QXcbVirtualDesktop* virtualDesktopForRootWindow(xcb_window_t rootWindow) const; diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index a327d8dea7..a3befc7384 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -581,8 +581,7 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event) } if (eventListener) { - long result = 0; - if (eventListener->handleGenericEvent(reinterpret_cast(event), &result)) + if (eventListener->handleNativeEvent(reinterpret_cast(event))) return; } diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp index 26b9fcc15a..3d2197796f 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp @@ -92,8 +92,7 @@ static int resourceType(const QByteArray &key) return int(result - names); } -QXcbNativeInterface::QXcbNativeInterface() : - m_genericEventFilterType(QByteArrayLiteral("xcb_generic_event_t")) +QXcbNativeInterface::QXcbNativeInterface() { } diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.h b/src/plugins/platforms/xcb/qxcbnativeinterface.h index 5ec3827afd..d1f2747bea 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.h +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.h @@ -98,7 +98,7 @@ public: QFunctionPointer platformFunction(const QByteArray &function) const override; - inline const QByteArray &genericEventFilterType() const { return m_genericEventFilterType; } + inline const QByteArray &nativeEventType() const { return m_nativeEventType; } void *displayForWindow(QWindow *window); void *connectionForWindow(QWindow *window); @@ -131,7 +131,7 @@ signals: void systemTrayWindowChanged(QScreen *screen); private: - const QByteArray m_genericEventFilterType; + const QByteArray m_nativeEventType = QByteArrayLiteral("xcb_generic_event_t"); xcb_atom_t m_sysTraySelectionAtom = XCB_ATOM_NONE; diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index fd0d2f9f07..2c333cb22b 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -1807,12 +1807,11 @@ bool QXcbWindow::requestSystemTrayWindowDock() return true; } -bool QXcbWindow::handleGenericEvent(xcb_generic_event_t *event, long *result) +bool QXcbWindow::handleNativeEvent(xcb_generic_event_t *event) { - return QWindowSystemInterface::handleNativeEvent(window(), - connection()->nativeInterface()->genericEventFilterType(), - event, - result); + auto eventType = connection()->nativeInterface()->nativeEventType(); + long result = 0; // Used only by MS Windows + return QWindowSystemInterface::handleNativeEvent(window(), eventType, event, &result); } void QXcbWindow::handleExposeEvent(const xcb_expose_event_t *event) diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 128c6e126d..99e8e40725 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -121,7 +121,7 @@ public: QImage::Format imageFormat() const { return m_imageFormat; } bool imageNeedsRgbSwap() const { return m_imageRgbSwap; } - bool handleGenericEvent(xcb_generic_event_t *event, long *result) override; + bool handleNativeEvent(xcb_generic_event_t *event) override; void handleExposeEvent(const xcb_expose_event_t *event) override; void handleClientMessageEvent(const xcb_client_message_event_t *event) override; -- cgit v1.2.3 From 242ea38375534f529f155efa46593e2a42577455 Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Thu, 8 Dec 2016 00:23:14 +0300 Subject: doc: Add missing override and remove redundant virtual for snippets Change-Id: I2395fd01b93c4ea364225e0cf1a5f59908b691d0 Reviewed-by: Martin Smith --- .../code/src_corelib_concurrent_qthreadpool.cpp | 2 +- .../code/src_corelib_io_qabstractfileengine.cpp | 8 +++---- .../doc/snippets/code/src_corelib_io_qprocess.cpp | 2 +- .../code/src_corelib_kernel_qabstractitemmodel.cpp | 2 +- .../snippets/code/src_corelib_kernel_qobject.cpp | 8 +++---- .../code/src_corelib_thread_qexception.cpp | 4 ++-- .../code/src_gui_itemviews_qidentityproxymodel.cpp | 2 +- .../doc/snippets/eventfilters/filterobject.h | 2 +- src/corelib/doc/snippets/events/events.cpp | 4 ++-- src/corelib/doc/snippets/settings/settings.cpp | 2 +- .../doc/snippets/statemachine/eventtest.cpp | 4 ++-- src/corelib/doc/snippets/statemachine/main4.cpp | 4 ++-- src/gui/doc/snippets/draganddrop/dragwidget.h | 8 +++---- src/gui/doc/snippets/dragging/mainwindow.h | 2 +- src/gui/doc/snippets/dropevents/window.h | 4 ++-- src/gui/doc/snippets/droprectangle/window.h | 4 ++-- src/gui/doc/snippets/matrix/matrix.cpp | 6 ++--- src/gui/doc/snippets/plaintextlayout/window.h | 2 +- src/gui/doc/snippets/qfileopenevent/main.cpp | 2 +- src/gui/doc/snippets/separations/finalwidget.h | 4 ++-- .../doc/snippets/textdocument-imagedrop/textedit.h | 4 ++-- src/gui/doc/snippets/transform/main.cpp | 6 ++--- src/opengl/doc/snippets/code/src_opengl_qgl.cpp | 6 ++--- src/sql/doc/snippets/sqldatabase/sqldatabase.cpp | 26 +++++++++++----------- .../code/doc_gui_widgets_qopenglwidget.cpp | 10 ++++----- src/widgets/doc/snippets/code/doc_src_layout.cpp | 14 ++++++------ .../code/src_gui_graphicsview_qgraphicsitem.cpp | 8 +++---- .../doc/snippets/code/src_gui_qproxystyle.cpp | 4 ++-- .../doc/snippets/code/src_gui_util_qundostack.cpp | 4 ++-- src/widgets/doc/snippets/customstyle/customstyle.h | 2 +- .../doc/snippets/graphicssceneadditemsnippet.cpp | 2 +- src/widgets/doc/snippets/myscrollarea.cpp | 4 ++-- src/widgets/doc/snippets/qlistview-dnd/model.h | 12 +++++----- src/widgets/doc/snippets/qstyleoption/main.cpp | 4 ++-- src/widgets/doc/snippets/qstyleplugin/main.cpp | 2 +- src/widgets/doc/snippets/splitterhandle/splitter.h | 4 ++-- src/widgets/doc/snippets/styles/styles.cpp | 2 +- 37 files changed, 95 insertions(+), 95 deletions(-) diff --git a/src/corelib/doc/snippets/code/src_corelib_concurrent_qthreadpool.cpp b/src/corelib/doc/snippets/code/src_corelib_concurrent_qthreadpool.cpp index ba31972aa1..8490942048 100644 --- a/src/corelib/doc/snippets/code/src_corelib_concurrent_qthreadpool.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_concurrent_qthreadpool.cpp @@ -51,7 +51,7 @@ //! [0] class HelloWorldTask : public QRunnable { - void run() + void run() override { qDebug() << "Hello world from thread" << QThread::currentThread(); } diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qabstractfileengine.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qabstractfileengine.cpp index 055812ea60..ae2f305313 100644 --- a/src/corelib/doc/snippets/code/src_corelib_io_qabstractfileengine.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_io_qabstractfileengine.cpp @@ -52,7 +52,7 @@ class ZipEngineHandler : public QAbstractFileEngineHandler { public: - QAbstractFileEngine *create(const QString &fileName) const; + QAbstractFileEngine *create(const QString &fileName) const override; }; QAbstractFileEngine *ZipEngineHandler::create(const QString &fileName) const @@ -105,12 +105,12 @@ public: entries << "entry1" << "entry2" << "entry3"; } - bool hasNext() const + bool hasNext() const override { return index < entries.size() - 1; } - QString next() + QString next() override { if (!hasNext()) return QString(); @@ -118,7 +118,7 @@ public: return currentFilePath(); } - QString currentFileName() + QString currentFileName() override { return entries.at(index); } diff --git a/src/corelib/doc/snippets/code/src_corelib_io_qprocess.cpp b/src/corelib/doc/snippets/code/src_corelib_io_qprocess.cpp index 2e94666970..8a2825cd10 100644 --- a/src/corelib/doc/snippets/code/src_corelib_io_qprocess.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_io_qprocess.cpp @@ -94,7 +94,7 @@ class SandboxProcess : public QProcess { ... protected: - void setupChildProcess(); + void setupChildProcess() override; ... }; diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp index 3379d0bc1a..2e055ec439 100644 --- a/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp @@ -120,7 +120,7 @@ public: ... - QVariant data(const QModelIndex &index, int role) + QVariant data(const QModelIndex &index, int role) override { if (role != Qt::BackgroundRole) return QSortFilterProxyModel::data(index, role); diff --git a/src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp b/src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp index c12ed147db..6451f46b36 100644 --- a/src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_kernel_qobject.cpp @@ -101,7 +101,7 @@ public: MainWindow(); protected: - bool eventFilter(QObject *obj, QEvent *ev); + bool eventFilter(QObject *obj, QEvent *ev) override; private: QTextEdit *textEdit; @@ -147,7 +147,7 @@ public: MyObject(QObject *parent = 0); protected: - void timerEvent(QTimerEvent *event); + void timerEvent(QTimerEvent *event) override; }; MyObject::MyObject(QObject *parent) @@ -215,7 +215,7 @@ class KeyPressEater : public QObject ... protected: - bool eventFilter(QObject *obj, QEvent *event); + bool eventFilter(QObject *obj, QEvent *event) override; }; bool KeyPressEater::eventFilter(QObject *obj, QEvent *event) @@ -508,7 +508,7 @@ public: MyClass(QWidget *parent = 0); ~MyClass(); - bool event(QEvent* ev) + bool event(QEvent* ev) override { if (ev->type() == QEvent::PolishRequest) { // overwrite handling of PolishRequest if any diff --git a/src/corelib/doc/snippets/code/src_corelib_thread_qexception.cpp b/src/corelib/doc/snippets/code/src_corelib_thread_qexception.cpp index eaf3a156cf..723c1630f6 100644 --- a/src/corelib/doc/snippets/code/src_corelib_thread_qexception.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_thread_qexception.cpp @@ -53,8 +53,8 @@ class MyException : public QException { public: - void raise() const { throw *this; } - MyException *clone() const { return new MyException(*this); } + void raise() const override { throw *this; } + MyException *clone() const override { return new MyException(*this); } }; //! [0] diff --git a/src/corelib/doc/snippets/code/src_gui_itemviews_qidentityproxymodel.cpp b/src/corelib/doc/snippets/code/src_gui_itemviews_qidentityproxymodel.cpp index 65ee9260b2..d89e28836f 100644 --- a/src/corelib/doc/snippets/code/src_gui_itemviews_qidentityproxymodel.cpp +++ b/src/corelib/doc/snippets/code/src_gui_itemviews_qidentityproxymodel.cpp @@ -58,7 +58,7 @@ class DateFormatProxyModel : public QIdentityProxyModel m_formatString = formatString; } - QVariant data(const QModelIndex &index, int role) const + QVariant data(const QModelIndex &index, int role) const override { if (role != Qt::DisplayRole) return QIdentityProxyModel::data(index, role); diff --git a/src/corelib/doc/snippets/eventfilters/filterobject.h b/src/corelib/doc/snippets/eventfilters/filterobject.h index 08b7c67192..354aa4ff5c 100644 --- a/src/corelib/doc/snippets/eventfilters/filterobject.h +++ b/src/corelib/doc/snippets/eventfilters/filterobject.h @@ -59,7 +59,7 @@ class FilterObject : public QObject public: FilterObject(QObject *parent = 0); - bool eventFilter(QObject *object, QEvent *event); + bool eventFilter(QObject *object, QEvent *event) override; void setFilteredObject(QObject *object); private: diff --git a/src/corelib/doc/snippets/events/events.cpp b/src/corelib/doc/snippets/events/events.cpp index 9606b0c2ee..969b0047f0 100644 --- a/src/corelib/doc/snippets/events/events.cpp +++ b/src/corelib/doc/snippets/events/events.cpp @@ -54,7 +54,7 @@ class MyCheckBox : public QCheckBox { public: - void mousePressEvent(QMouseEvent *event); + void mousePressEvent(QMouseEvent *event) override; }; //! [0] @@ -72,7 +72,7 @@ void MyCheckBox::mousePressEvent(QMouseEvent *event) class MyWidget : public QWidget { public: - bool event(QEvent *event); + bool event(QEvent *event) override; }; static const int MyCustomEventType = 1099; diff --git a/src/corelib/doc/snippets/settings/settings.cpp b/src/corelib/doc/snippets/settings/settings.cpp index 28b72acd6a..49312b9cfc 100644 --- a/src/corelib/doc/snippets/settings/settings.cpp +++ b/src/corelib/doc/snippets/settings/settings.cpp @@ -143,7 +143,7 @@ public: void readSettings(); protected: - void closeEvent(QCloseEvent *event); + void closeEvent(QCloseEvent *event) override; }; //! [16] diff --git a/src/corelib/doc/snippets/statemachine/eventtest.cpp b/src/corelib/doc/snippets/statemachine/eventtest.cpp index cecf26f2e7..d7d4ce0d21 100644 --- a/src/corelib/doc/snippets/statemachine/eventtest.cpp +++ b/src/corelib/doc/snippets/statemachine/eventtest.cpp @@ -58,7 +58,7 @@ public: protected: //![0] - bool eventTest(QEvent *event) + bool eventTest(QEvent *event) override { if (event->type() == QEvent::Wrapped) { QEvent *wrappedEvent = static_cast(event)->event(); @@ -71,7 +71,7 @@ protected: } //![0] - void onTransition(QEvent *event) + void onTransition(QEvent *event) override { } diff --git a/src/corelib/doc/snippets/statemachine/main4.cpp b/src/corelib/doc/snippets/statemachine/main4.cpp index 5786fa3c17..e21656b91c 100644 --- a/src/corelib/doc/snippets/statemachine/main4.cpp +++ b/src/corelib/doc/snippets/statemachine/main4.cpp @@ -72,7 +72,7 @@ public: : m_value(value) {} protected: - virtual bool eventTest(QEvent *e) + bool eventTest(QEvent *e) override { if (e->type() != QEvent::Type(QEvent::User+1)) // StringEvent return false; @@ -80,7 +80,7 @@ protected: return (m_value == se->value); } - virtual void onTransition(QEvent *) {} + void onTransition(QEvent *) override {} private: QString m_value; diff --git a/src/gui/doc/snippets/draganddrop/dragwidget.h b/src/gui/doc/snippets/draganddrop/dragwidget.h index 424c0b334b..709f9338bf 100644 --- a/src/gui/doc/snippets/draganddrop/dragwidget.h +++ b/src/gui/doc/snippets/draganddrop/dragwidget.h @@ -74,10 +74,10 @@ signals: void mimeTypes(const QStringList &types); protected: - void dragEnterEvent(QDragEnterEvent *event); - void dropEvent(QDropEvent *event); - void mouseMoveEvent(QMouseEvent *event); - void mousePressEvent(QMouseEvent *event); + void dragEnterEvent(QDragEnterEvent *event) override; + void dropEvent(QDropEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; + void mousePressEvent(QMouseEvent *event) override; private: QByteArray data; diff --git a/src/gui/doc/snippets/dragging/mainwindow.h b/src/gui/doc/snippets/dragging/mainwindow.h index 5e796d530f..8a8e43b223 100644 --- a/src/gui/doc/snippets/dragging/mainwindow.h +++ b/src/gui/doc/snippets/dragging/mainwindow.h @@ -68,7 +68,7 @@ public: MainWindow(QWidget *parent = 0); protected: - void mousePressEvent(QMouseEvent *event); + void mousePressEvent(QMouseEvent *event) override; private: QLabel *iconLabel; diff --git a/src/gui/doc/snippets/dropevents/window.h b/src/gui/doc/snippets/dropevents/window.h index 17c323b952..6ac35181ed 100644 --- a/src/gui/doc/snippets/dropevents/window.h +++ b/src/gui/doc/snippets/dropevents/window.h @@ -67,8 +67,8 @@ public: Window(QWidget *parent = 0); protected: - void dragEnterEvent(QDragEnterEvent *event); - void dropEvent(QDropEvent *event); + void dragEnterEvent(QDragEnterEvent *event) override; + void dropEvent(QDropEvent *event) override; private: QComboBox *mimeTypeCombo; diff --git a/src/gui/doc/snippets/droprectangle/window.h b/src/gui/doc/snippets/droprectangle/window.h index 683e5cb813..5a9ef75d3b 100644 --- a/src/gui/doc/snippets/droprectangle/window.h +++ b/src/gui/doc/snippets/droprectangle/window.h @@ -67,8 +67,8 @@ public: Window(QWidget *parent = 0); protected: - void dragMoveEvent(QDragMoveEvent *event); - void dropEvent(QDropEvent *event); + void dragMoveEvent(QDragMoveEvent *event) override; + void dropEvent(QDropEvent *event) override; private: QComboBox *mimeTypeCombo; diff --git a/src/gui/doc/snippets/matrix/matrix.cpp b/src/gui/doc/snippets/matrix/matrix.cpp index ec9e130a29..115dc3d508 100644 --- a/src/gui/doc/snippets/matrix/matrix.cpp +++ b/src/gui/doc/snippets/matrix/matrix.cpp @@ -53,7 +53,7 @@ class SimpleTransformation : public QWidget { - void paintEvent(QPaintEvent *); + void paintEvent(QPaintEvent *) override; }; //! [0] @@ -73,7 +73,7 @@ void SimpleTransformation::paintEvent(QPaintEvent *) class CombinedTransformation : public QWidget { - void paintEvent(QPaintEvent *); + void paintEvent(QPaintEvent *) override; }; //! [1] @@ -97,7 +97,7 @@ void CombinedTransformation::paintEvent(QPaintEvent *) class BasicOperations : public QWidget { - void paintEvent(QPaintEvent *); + void paintEvent(QPaintEvent *) override; }; //! [2] diff --git a/src/gui/doc/snippets/plaintextlayout/window.h b/src/gui/doc/snippets/plaintextlayout/window.h index 0068a37482..8552ecd4ba 100644 --- a/src/gui/doc/snippets/plaintextlayout/window.h +++ b/src/gui/doc/snippets/plaintextlayout/window.h @@ -61,7 +61,7 @@ public: Window(QWidget *parent = 0); protected: - void paintEvent(QPaintEvent *event); + void paintEvent(QPaintEvent *event) override; private: QFont font; diff --git a/src/gui/doc/snippets/qfileopenevent/main.cpp b/src/gui/doc/snippets/qfileopenevent/main.cpp index 3e707f2ddf..f18e763bbc 100644 --- a/src/gui/doc/snippets/qfileopenevent/main.cpp +++ b/src/gui/doc/snippets/qfileopenevent/main.cpp @@ -61,7 +61,7 @@ public: { } - bool event(QEvent *event) + bool event(QEvent *event) override { if (event->type() == QEvent::FileOpen) { QFileOpenEvent *openEvent = static_cast(event); diff --git a/src/gui/doc/snippets/separations/finalwidget.h b/src/gui/doc/snippets/separations/finalwidget.h index 0301f68fe9..886a5dfaf3 100644 --- a/src/gui/doc/snippets/separations/finalwidget.h +++ b/src/gui/doc/snippets/separations/finalwidget.h @@ -71,8 +71,8 @@ public: const QPixmap *pixmap() const; protected: - void mouseMoveEvent(QMouseEvent *event); - void mousePressEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event) override; + void mousePressEvent(QMouseEvent *event) override; private: void createImage(); diff --git a/src/gui/doc/snippets/textdocument-imagedrop/textedit.h b/src/gui/doc/snippets/textdocument-imagedrop/textedit.h index 9f73bceeaf..3f570884ba 100644 --- a/src/gui/doc/snippets/textdocument-imagedrop/textedit.h +++ b/src/gui/doc/snippets/textdocument-imagedrop/textedit.h @@ -59,8 +59,8 @@ class TextEdit : public QTextEdit public: TextEdit(QWidget *parent=0); - bool canInsertFromMimeData( const QMimeData *source ) const; - void insertFromMimeData( const QMimeData *source ); + bool canInsertFromMimeData( const QMimeData *source ) const override; + void insertFromMimeData( const QMimeData *source ) override; }; #endif diff --git a/src/gui/doc/snippets/transform/main.cpp b/src/gui/doc/snippets/transform/main.cpp index e096eee7fc..e30a3b63bf 100644 --- a/src/gui/doc/snippets/transform/main.cpp +++ b/src/gui/doc/snippets/transform/main.cpp @@ -53,7 +53,7 @@ class SimpleTransformation : public QWidget { - void paintEvent(QPaintEvent *); + void paintEvent(QPaintEvent *) override; }; //! [0] @@ -73,7 +73,7 @@ void SimpleTransformation::paintEvent(QPaintEvent *) class CombinedTransformation : public QWidget { - void paintEvent(QPaintEvent *); + void paintEvent(QPaintEvent *) override; }; //! [1] @@ -97,7 +97,7 @@ void CombinedTransformation::paintEvent(QPaintEvent *) class BasicOperations : public QWidget { - void paintEvent(QPaintEvent *); + void paintEvent(QPaintEvent *) override; }; //! [2] diff --git a/src/opengl/doc/snippets/code/src_opengl_qgl.cpp b/src/opengl/doc/snippets/code/src_opengl_qgl.cpp index 839d941a1c..a73ee2cdc5 100644 --- a/src/opengl/doc/snippets/code/src_opengl_qgl.cpp +++ b/src/opengl/doc/snippets/code/src_opengl_qgl.cpp @@ -146,7 +146,7 @@ public: protected: - void initializeGL() + void initializeGL() override { // Set up the rendering context, define display lists etc.: ... @@ -155,7 +155,7 @@ protected: ... } - void resizeGL(int w, int h) + void resizeGL(int w, int h) override { // setup viewport, projection etc.: glViewport(0, 0, (GLint)w, (GLint)h); @@ -164,7 +164,7 @@ protected: ... } - void paintGL() + void paintGL() override { // draw the scene: ... diff --git a/src/sql/doc/snippets/sqldatabase/sqldatabase.cpp b/src/sql/doc/snippets/sqldatabase/sqldatabase.cpp index d0f9a367c5..a27feb1505 100644 --- a/src/sql/doc/snippets/sqldatabase/sqldatabase.cpp +++ b/src/sql/doc/snippets/sqldatabase/sqldatabase.cpp @@ -273,7 +273,7 @@ void QSqlQueryModel_snippets() class MyModel : public QSqlQueryModel { public: - QVariant data(const QModelIndex &item, int role) const; + QVariant data(const QModelIndex &item, int role) const override; int m_specialColumnNo; }; @@ -526,15 +526,15 @@ public: ~XyzResult() {} protected: - QVariant data(int /* index */) { return QVariant(); } - bool isNull(int /* index */) { return false; } - bool reset(const QString & /* query */) { return false; } - bool fetch(int /* index */) { return false; } - bool fetchFirst() { return false; } - bool fetchLast() { return false; } - int size() { return 0; } - int numRowsAffected() { return 0; } - QSqlRecord record() const { return QSqlRecord(); } + QVariant data(int /* index */) override { return QVariant(); } + bool isNull(int /* index */) override { return false; } + bool reset(const QString & /* query */) override { return false; } + bool fetch(int /* index */) override { return false; } + bool fetchFirst() override { return false; } + bool fetchLast() override { return false; } + int size() override { return 0; } + int numRowsAffected() override { return 0; } + QSqlRecord record() const override { return QSqlRecord(); } }; //! [47] @@ -545,13 +545,13 @@ public: XyzDriver() {} ~XyzDriver() {} - bool hasFeature(DriverFeature /* feature */) const { return false; } + bool hasFeature(DriverFeature /* feature */) const override { return false; } bool open(const QString & /* db */, const QString & /* user */, const QString & /* password */, const QString & /* host */, - int /* port */, const QString & /* options */) + int /* port */, const QString & /* options */) override { return false; } void close() {} - QSqlResult *createResult() const { return new XyzResult(this); } + QSqlResult *createResult() const override { return new XyzResult(this); } }; //! [48] diff --git a/src/widgets/doc/snippets/code/doc_gui_widgets_qopenglwidget.cpp b/src/widgets/doc/snippets/code/doc_gui_widgets_qopenglwidget.cpp index 4a3816ae72..633a413b4f 100644 --- a/src/widgets/doc/snippets/code/doc_gui_widgets_qopenglwidget.cpp +++ b/src/widgets/doc/snippets/code/doc_gui_widgets_qopenglwidget.cpp @@ -55,7 +55,7 @@ public: MyGLWidget(QWidget *parent) : QOpenGLWidget(parent) { } protected: - void initializeGL() + void initializeGL() override { // Set up the rendering context, load shaders and other resources, etc.: QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions(); @@ -63,7 +63,7 @@ protected: ... } - void resizeGL(int w, int h) + void resizeGL(int w, int h) override { // Update projection matrix and other size related settings: m_projection.setToIdentity(); @@ -71,7 +71,7 @@ protected: ... } - void paintGL() + void paintGL() override { // Draw the scene: QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions(); @@ -86,7 +86,7 @@ protected: class MyGLWidget : public QOpenGLWidget, protected QOpenGLFunctions { ... - void initializeGL() + void initializeGL() override { initializeOpenGLFunctions(); glClearColor(...); @@ -108,7 +108,7 @@ widget->setFormat(format); // must be called before the widget or its parent win //! [3] ... - void paintGL() + void paintGL() override { QOpenGLFunctions_3_2_Core *f = QOpenGLContext::currentContext()->versionFunctions(); ... diff --git a/src/widgets/doc/snippets/code/doc_src_layout.cpp b/src/widgets/doc/snippets/code/doc_src_layout.cpp index 42f5611bde..5e9a740244 100644 --- a/src/widgets/doc/snippets/code/doc_src_layout.cpp +++ b/src/widgets/doc/snippets/code/doc_src_layout.cpp @@ -63,13 +63,13 @@ public: CardLayout(int dist): QLayout(dist) {} ~CardLayout(); - void addItem(QLayoutItem *item); - QSize sizeHint() const; - QSize minimumSize() const; - int count() const; - QLayoutItem *itemAt(int) const; - QLayoutItem *takeAt(int); - void setGeometry(const QRect &rect); + void addItem(QLayoutItem *item) override; + QSize sizeHint() const override; + QSize minimumSize() const override; + int count() const override; + QLayoutItem *itemAt(int) const override; + QLayoutItem *takeAt(int) override; + void setGeometry(const QRect &rect) override; private: QList list; diff --git a/src/widgets/doc/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp b/src/widgets/doc/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp index 7511c83b3c..8d8c63db9e 100644 --- a/src/widgets/doc/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp +++ b/src/widgets/doc/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp @@ -52,7 +52,7 @@ class SimpleItem : public QGraphicsItem { public: - QRectF boundingRect() const + QRectF boundingRect() const override { qreal penWidth = 1; return QRectF(-10 - penWidth / 2, -10 - penWidth / 2, @@ -60,7 +60,7 @@ public: } void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, - QWidget *widget) + QWidget *widget) override { painter->drawRoundedRect(-10, -10, 20, 20, 5, 5); } @@ -74,7 +74,7 @@ class CustomItem : public QGraphicsItem public: enum { Type = UserType + 1 }; - int type() const + int type() const override { // Enable the use of qgraphicsitem_cast with this item. return Type; @@ -260,7 +260,7 @@ class QGraphicsPathItem : public QAbstractGraphicsShapeItem { public: enum { Type = 2 }; - int type() const { return Type; } + int type() const override { return Type; } ... }; //! [18] diff --git a/src/widgets/doc/snippets/code/src_gui_qproxystyle.cpp b/src/widgets/doc/snippets/code/src_gui_qproxystyle.cpp index 33d5fab321..3169d1c193 100644 --- a/src/widgets/doc/snippets/code/src_gui_qproxystyle.cpp +++ b/src/widgets/doc/snippets/code/src_gui_qproxystyle.cpp @@ -54,7 +54,7 @@ class MyProxyStyle : public QProxyStyle public: int styleHint(StyleHint hint, const QStyleOption *option = 0, - const QWidget *widget = 0, QStyleHintReturn *returnData = 0) const + const QWidget *widget = 0, QStyleHintReturn *returnData = 0) const override { if (hint == QStyle::SH_UnderlineShortcut) return 1; @@ -73,7 +73,7 @@ class MyProxyStyle : public QProxyStyle { public: int styleHint(StyleHint hint, const QStyleOption *option = 0, - const QWidget *widget = 0, QStyleHintReturn *returnData = 0) const + const QWidget *widget = 0, QStyleHintReturn *returnData = 0) const override { if (hint == QStyle::SH_UnderlineShortcut) return 0; diff --git a/src/widgets/doc/snippets/code/src_gui_util_qundostack.cpp b/src/widgets/doc/snippets/code/src_gui_util_qundostack.cpp index e191c74287..8f59fe9cb3 100644 --- a/src/widgets/doc/snippets/code/src_gui_util_qundostack.cpp +++ b/src/widgets/doc/snippets/code/src_gui_util_qundostack.cpp @@ -54,9 +54,9 @@ class AppendText : public QUndoCommand public: AppendText(QString *doc, const QString &text) : m_document(doc), m_text(text) { setText("append text"); } - virtual void undo() + void undo() override { m_document->chop(m_text.length()); } - virtual void redo() + void redo() override { m_document->append(m_text); } private: QString *m_document; diff --git a/src/widgets/doc/snippets/customstyle/customstyle.h b/src/widgets/doc/snippets/customstyle/customstyle.h index addb1dfb6e..be9edf0bf4 100644 --- a/src/widgets/doc/snippets/customstyle/customstyle.h +++ b/src/widgets/doc/snippets/customstyle/customstyle.h @@ -63,7 +63,7 @@ public: ~CustomStyle() {} void drawPrimitive(PrimitiveElement element, const QStyleOption *option, - QPainter *painter, const QWidget *widget) const; + QPainter *painter, const QWidget *widget) const override; }; //! [0] diff --git a/src/widgets/doc/snippets/graphicssceneadditemsnippet.cpp b/src/widgets/doc/snippets/graphicssceneadditemsnippet.cpp index b3ace9ce46..96e6bd650c 100644 --- a/src/widgets/doc/snippets/graphicssceneadditemsnippet.cpp +++ b/src/widgets/doc/snippets/graphicssceneadditemsnippet.cpp @@ -58,7 +58,7 @@ public: void drawItems(QPainter *painter, int numItems, QGraphicsItem *items[], const QStyleOptionGraphicsItem options[], - QWidget *widget = 0); + QWidget *widget = 0) override; }; //! [0] diff --git a/src/widgets/doc/snippets/myscrollarea.cpp b/src/widgets/doc/snippets/myscrollarea.cpp index 477b041fe1..dbf8da1603 100644 --- a/src/widgets/doc/snippets/myscrollarea.cpp +++ b/src/widgets/doc/snippets/myscrollarea.cpp @@ -57,8 +57,8 @@ public: void setWidget(QWidget *w); protected: - void scrollContentsBy(int dx, int dy); - void resizeEvent(QResizeEvent *event); + void scrollContentsBy(int dx, int dy) override; + void resizeEvent(QResizeEvent *event) override; private: void updateWidgetPosition(); diff --git a/src/widgets/doc/snippets/qlistview-dnd/model.h b/src/widgets/doc/snippets/qlistview-dnd/model.h index 7635d2f21a..3d418dca14 100644 --- a/src/widgets/doc/snippets/qlistview-dnd/model.h +++ b/src/widgets/doc/snippets/qlistview-dnd/model.h @@ -61,15 +61,15 @@ class DragDropListModel : public QStringListModel public: DragDropListModel(const QStringList &strings, QObject *parent = 0); - Qt::ItemFlags flags(const QModelIndex &index) const; + Qt::ItemFlags flags(const QModelIndex &index) const override; bool canDropMimeData(const QMimeData *data, Qt::DropAction action, - int row, int column, const QModelIndex &parent); + int row, int column, const QModelIndex &parent) override; bool dropMimeData(const QMimeData *data, Qt::DropAction action, - int row, int column, const QModelIndex &parent); - QMimeData *mimeData(const QModelIndexList &indexes) const; - QStringList mimeTypes() const; - Qt::DropActions supportedDropActions() const; + int row, int column, const QModelIndex &parent) override; + QMimeData *mimeData(const QModelIndexList &indexes) const override; + QStringList mimeTypes() const override; + Qt::DropActions supportedDropActions() const override; }; #endif diff --git a/src/widgets/doc/snippets/qstyleoption/main.cpp b/src/widgets/doc/snippets/qstyleoption/main.cpp index 659a5f945b..529f88f1d9 100644 --- a/src/widgets/doc/snippets/qstyleoption/main.cpp +++ b/src/widgets/doc/snippets/qstyleoption/main.cpp @@ -56,7 +56,7 @@ class MyPushButton : public QPushButton public: MyPushButton(QWidget *parent = 0); - void paintEvent(QPaintEvent *); + void paintEvent(QPaintEvent *) override; }; MyPushButton::MyPushButton(QWidget *parent) @@ -87,7 +87,7 @@ class MyStyle : public QStyle public: void drawPrimitive(PrimitiveElement element, const QStyleOption *option, - QPainter *painter, const QWidget *widget); + QPainter *painter, const QWidget *widget) override; }; //! [4] diff --git a/src/widgets/doc/snippets/qstyleplugin/main.cpp b/src/widgets/doc/snippets/qstyleplugin/main.cpp index 2cc7040e93..1c61581572 100644 --- a/src/widgets/doc/snippets/qstyleplugin/main.cpp +++ b/src/widgets/doc/snippets/qstyleplugin/main.cpp @@ -59,7 +59,7 @@ class MyStylePlugin : public QStylePlugin public: MyStylePlugin(QObject *parent = 0); - QStyle *create(const QString &key); + QStyle *create(const QString &key) override; }; //! [0] diff --git a/src/widgets/doc/snippets/splitterhandle/splitter.h b/src/widgets/doc/snippets/splitterhandle/splitter.h index 49ef20a620..8df7bc14a2 100644 --- a/src/widgets/doc/snippets/splitterhandle/splitter.h +++ b/src/widgets/doc/snippets/splitterhandle/splitter.h @@ -64,7 +64,7 @@ public: Splitter(Qt::Orientation orientation, QWidget *parent = 0); protected: - QSplitterHandle *createHandle(); + QSplitterHandle *createHandle() override; }; //! [0] @@ -74,7 +74,7 @@ public: SplitterHandle(Qt::Orientation orientation, QSplitter *parent); protected: - void paintEvent(QPaintEvent *event); + void paintEvent(QPaintEvent *event) override; private: QLinearGradient gradient; diff --git a/src/widgets/doc/snippets/styles/styles.cpp b/src/widgets/doc/snippets/styles/styles.cpp index 116c807f39..77fde0693d 100644 --- a/src/widgets/doc/snippets/styles/styles.cpp +++ b/src/widgets/doc/snippets/styles/styles.cpp @@ -55,7 +55,7 @@ class MyWidget : public QWidget { protected: - void paintEvent(QPaintEvent *event); + void paintEvent(QPaintEvent *event) override; void paintEvent2(QPaintEvent *event); }; -- cgit v1.2.3 From 30b0701c9b50ec718ec858d7777a01c66e333a9c Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Wed, 1 Aug 2018 00:07:11 +0200 Subject: Refactor wildcard support in QRegularExpression The API originally proposed was flawed in the sense that the setter function would use a modified version of the parameter given which would have make it a black box for the user. This patch fixes that by removing that setter and providing a static method that will return the pattern suitably modified to be used by QRegularExpression the same way the escape method does. [ChangeLog][Core][QRegularExpression] Implemented support for wildcard patterns through a static method. Change-Id: I0054bcaffd7525dac569f54fa81f73b7e4544b2e Reviewed-by: Thiago Macieira --- .../code/src_corelib_tools_qregularexpression.cpp | 7 + src/corelib/tools/qregularexpression.cpp | 238 ++++++++++----------- src/corelib/tools/qregularexpression.h | 2 +- src/corelib/tools/qregularexpression_p.h | 70 ------ src/corelib/tools/tools.pri | 3 +- .../qregularexpression/tst_qregularexpression.cpp | 14 +- 6 files changed, 133 insertions(+), 201 deletions(-) delete mode 100644 src/corelib/tools/qregularexpression_p.h diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qregularexpression.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qregularexpression.cpp index 5f0a175374..28c66628b7 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qregularexpression.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qregularexpression.cpp @@ -350,4 +350,11 @@ while (i.hasNext()) { //! [30] } +{ +//! [31] +QString wildcard = QRegularExpression::wildcardToRegularExpression("*.jpeg"); +// wilcard == ".*\.jpeg" +//! [31] +} + } diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp index af2e46dd00..17caaabc97 100644 --- a/src/corelib/tools/qregularexpression.cpp +++ b/src/corelib/tools/qregularexpression.cpp @@ -516,10 +516,10 @@ QT_BEGIN_NAMESPACE \section2 Wildcard matching - There is no equivalent of wildcard matching in QRegularExpression. - Nevertheless, rewriting a regular expression in wildcard syntax to a - Perl-compatible regular expression is a very easy task, given the fact - that wildcard syntax supported by QRegExp is very simple. + There is no direct way to do wildcard matching in QRegularExpression. + However, the wildcardToRegularExpression method is provided to translate + glob patterns into a Perl-compatible regular expression that can be used + for that purpose. \section2 Other pattern syntaxes @@ -784,82 +784,6 @@ QT_BEGIN_NAMESPACE Qt 5.4. */ -namespace QtPrivate { -/*! - internal -*/ -QString wildcardToRegularExpression(const QString &wildcardString) -{ - const int wclen = wildcardString.length(); - QString rx; - int i = 0; - bool hasNegativeBracket = false; - const QChar *wc = wildcardString.unicode(); - - while (i < wclen) { - const QChar c = wc[i++]; - switch (c.unicode()) { - case '*': - rx += QLatin1String(".*"); - break; - case '?': - rx += QLatin1Char('.'); - break; - case '$': - case '(': - case ')': - case '+': - case '.': - case '^': - case '{': - case '|': - case '}': - rx += QLatin1Char('\\'); - rx += c; - break; - case '[': - // Support for the [!abc] or [!a-c] syntax - // Implements a negative look-behind for one char. - if (wc[i] == QLatin1Char(']')) { - rx += c; - rx += wc[i++]; - } else if (wc[i] == QLatin1Char('!')) { - rx += QLatin1String(".(?<"); - rx += wc[i++]; - rx += c; - hasNegativeBracket = true; - } else { - rx += c; - } - - if (i < wclen) { - if (rx[i] == QLatin1Char(']')) - rx += wc[i++]; - while (i < wclen && wc[i] != QLatin1Char(']')) { - if (wc[i] == QLatin1Char('\\')) - rx += QLatin1Char('\\'); - rx += wc[i++]; - } - } - break; - case ']': - rx += c; - // Closes the negative look-behind expression. - if (hasNegativeBracket) { - rx += QLatin1Char(')'); - hasNegativeBracket = false; - } - break; - default: - rx += c; - break; - } - } - - return rx; -} -} - /*! \internal */ @@ -1582,47 +1506,6 @@ void QRegularExpression::setPattern(const QString &pattern) d->pattern = pattern; } -/*! - \since 5.12 - - Sets the pattern string of the regular expression to \a wildcard pattern. - The pattern options are left unchanged. - - \warning Unlike QRegExp, this implementation follows closely the definition - of wildcard for glob patterns: - \table - \row \li \b{c} - \li Any character represents itself apart from those mentioned - below. Thus \b{c} matches the character \e c. - \row \li \b{?} - \li Matches any single character. It is the same as - \b{.} in full regexps. - \row \li \b{*} - \li Matches zero or more of any characters. It is the - same as \b{.*} in full regexps. - \row \li \b{[abc]} - \li Matches one character given in the bracket. - \row \li \b{[a-c]} - \li Matches one character from the range given in the bracket. - \row \li \b{[!abc]} - \li Matches one character that is not given in the bracket. - \row \li \b{[!a-c]} - \li matches one character that is not from the range given in the - bracket. - \endtable - - \note This function generates a regular expression that will act following - the wildcard pattern given. However the content of the regular expression - will not be the same as the one set. - - \sa pattern(), setPattern() -*/ -void QRegularExpression::setWildcardPattern(const QString &pattern) -{ - setPattern(QtPrivate::wildcardToRegularExpression(pattern)); -} - - /*! Returns the pattern options for the regular expression. @@ -1987,6 +1870,119 @@ QString QRegularExpression::escape(const QString &str) return result; } +/*! + \since 5.12 + + Returns a regular expression representation of the given glob \a pattern. + + \snippet code/src_corelib_tools_qregularexpression.cpp 31 + + \warning Unlike QRegExp, this implementation follows closely the definition + of wildcard for glob patterns: + \table + \row \li \b{c} + \li Any character represents itself apart from those mentioned + below. Thus \b{c} matches the character \e c. + \row \li \b{?} + \li Matches any single character. It is the same as + \b{.} in full regexps. + \row \li \b{*} + \li Matches zero or more of any characters. It is the + same as \b{.*} in full regexps. + \row \li \b{[abc]} + \li Matches one character given in the bracket. + \row \li \b{[a-c]} + \li Matches one character from the range given in the bracket. + \row \li \b{[!abc]} + \li Matches one character that is not given in the bracket. It is the + same as \b{[^abc]} in full regexp. + \row \li \b{[!a-c]} + \li Matches one character that is not from the range given in the + bracket. It is the same as \b{[^a-c]} in full regexp. + \endtable + + \note The backslash (\\) character is \e not an escape char in this context. + In order to match one of the special characters, place it in square brackets + (for example, "[?]"). + + More information about the implementation can be found in: + \list + \li \l {https://en.wikipedia.org/wiki/Glob_(programming)} {The Wikipedia Glob article} + \li \c man 7 glob + \endlist + + \sa escape() +*/ +QString QRegularExpression::wildcardToRegularExpression(const QString &pattern) +{ + const int wclen = pattern.length(); + QString rx; + int i = 0; + bool hasNegativeBracket = false; + const QChar *wc = pattern.unicode(); + + while (i < wclen) { + const QChar c = wc[i++]; + switch (c.unicode()) { + case '*': + rx += QLatin1String(".*"); + break; + case '?': + rx += QLatin1Char('.'); + break; + case '$': + case '(': + case ')': + case '+': + case '.': + case '^': + case '{': + case '|': + case '}': + rx += QLatin1Char('\\'); + rx += c; + break; + case '[': + // Support for the [!abc] or [!a-c] syntax + // Implements a negative look-behind for one char. + if (i < wclen) { + if (wc[i] == QLatin1Char(']')) { + rx += c; + rx += wc[i++]; + } else if (wc[i] == QLatin1Char('!')) { + rx += QLatin1String(".(?<"); + rx += wc[i++]; + rx += c; + hasNegativeBracket = true; + } else { + rx += c; + } + while (i < wclen && wc[i] != QLatin1Char(']')) { + if (wc[i] == QLatin1Char('\\')) + rx += QLatin1Char('\\'); + rx += wc[i++]; + } + } else { + rx += c; + } + break; + case ']': + rx += c; + // Closes the negative look-behind expression. + if (hasNegativeBracket) { + rx += QLatin1Char(')'); + hasNegativeBracket = false; + } + break; + default: + rx += c; + break; + } + } + + return rx; +} + /*! \since 5.1 diff --git a/src/corelib/tools/qregularexpression.h b/src/corelib/tools/qregularexpression.h index d0f90b90b3..388aa7a8ca 100644 --- a/src/corelib/tools/qregularexpression.h +++ b/src/corelib/tools/qregularexpression.h @@ -96,7 +96,6 @@ public: QString pattern() const; void setPattern(const QString &pattern); - void setWildcardPattern(const QString &pattern); bool isValid() const; int patternErrorOffset() const; @@ -142,6 +141,7 @@ public: void optimize() const; static QString escape(const QString &str); + static QString wildcardToRegularExpression(const QString &str); bool operator==(const QRegularExpression &re) const; inline bool operator!=(const QRegularExpression &re) const { return !operator==(re); } diff --git a/src/corelib/tools/qregularexpression_p.h b/src/corelib/tools/qregularexpression_p.h deleted file mode 100644 index f5455de853..0000000000 --- a/src/corelib/tools/qregularexpression_p.h +++ /dev/null @@ -1,70 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2018 Samuel Gaist -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QREGULAREXPRESSION_P_H -#define QREGULAREXPRESSION_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - -#include -#include - -QT_REQUIRE_CONFIG(regularexpression); - -QT_BEGIN_NAMESPACE - -namespace QtPrivate { -QString wildcardToRegularExpression(const QString &expression); -} - -QT_END_NAMESPACE - -#endif diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index 7a74dfda3e..9ec6ea4894 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -183,8 +183,7 @@ qtConfig(regularexpression) { QMAKE_USE_PRIVATE += pcre2 HEADERS += \ - tools/qregularexpression.h \ - tools/qregularexpression_p.h + tools/qregularexpression.h SOURCES += tools/qregularexpression.cpp } diff --git a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp index 5130b7cfcd..987ca519ee 100644 --- a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp +++ b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp @@ -2171,6 +2171,10 @@ void tst_QRegularExpression::wildcard_data() addRow(".???l", "test.html", 4); addRow("?", "test.html", 0); addRow("?m", "test.html", 6); + addRow("[*]", "test.html", -1); + addRow("[?]","test.html", -1); + addRow("[[]","test.h[ml", 6); + addRow("[]]","test.h]ml", 6); addRow(".h[a-z]ml", "test.html", 4); addRow(".h[A-Z]ml", "test.html", -1); addRow(".h[A-Z]ml", "test.hTml", 4); @@ -2191,9 +2195,7 @@ void tst_QRegularExpression::wildcard() QFETCH(QString, string); QFETCH(int, foundIndex); - QRegularExpression re; - re.setWildcardPattern(pattern); - + QRegularExpression re(QRegularExpression::wildcardToRegularExpression(pattern)); QRegularExpressionMatch match = re.match(string); QCOMPARE(match.capturedStart(), foundIndex); @@ -2217,11 +2219,9 @@ void tst_QRegularExpression::testInvalidWildcard_data() void tst_QRegularExpression::testInvalidWildcard() { QFETCH(QString, pattern); - - QRegularExpression re; - re.setWildcardPattern(pattern); - QFETCH(bool, isValid); + + QRegularExpression re(QRegularExpression::wildcardToRegularExpression(pattern)); QCOMPARE(re.isValid(), isValid); } -- cgit v1.2.3 From 04bbf534f98387073ce327eac2718e0170f8d8c0 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 15 Aug 2018 13:43:18 -0700 Subject: MSVC: add support for 64-bit POPCNT on 32-bit machines It's just adding the count of each half. Change-Id: I9868946ceaf74002bde1fffd154b29908319007f Reviewed-by: Samuel Gaist Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/tools/qalgorithms.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/corelib/tools/qalgorithms.h b/src/corelib/tools/qalgorithms.h index b658d8afcf..0146e22fa3 100644 --- a/src/corelib/tools/qalgorithms.h +++ b/src/corelib/tools/qalgorithms.h @@ -651,6 +651,7 @@ Q_ALWAYS_INLINE uint qt_builtin_clzs(quint16 v) Q_DECL_NOTHROW // So it's an acceptable compromise. #if defined(__AVX__) || defined(__SSE4_2__) || defined(__POPCNT__) #define QALGORITHMS_USE_BUILTIN_POPCOUNT +#define QALGORITHMS_USE_BUILTIN_POPCOUNTLL Q_ALWAYS_INLINE uint qt_builtin_popcount(quint32 v) Q_DECL_NOTHROW { return __popcnt(v); @@ -663,13 +664,15 @@ Q_ALWAYS_INLINE uint qt_builtin_popcount(quint16 v) Q_DECL_NOTHROW { return __popcnt16(v); } -#if Q_PROCESSOR_WORDSIZE == 8 -#define QALGORITHMS_USE_BUILTIN_POPCOUNTLL Q_ALWAYS_INLINE uint qt_builtin_popcountll(quint64 v) Q_DECL_NOTHROW { +#if Q_PROCESSOR_WORDSIZE == 8 return __popcnt64(v); -} +#else + return __popcnt(quint32(v)) + __popcnt(quint32(v >> 32)); #endif // MSVC 64bit +} + #endif // __AVX__ || __SSE4_2__ || __POPCNT__ #endif // MSVC -- cgit v1.2.3 From d9d35b9fb6eef13b69d54c876a3b6f1c1b629704 Mon Sep 17 00:00:00 2001 From: Mikhail Svetkin Date: Thu, 26 Jul 2018 10:42:03 +0200 Subject: Optimize implementation of Indexes generator ... which is Qt's version of std::make_index_sequence / C++14. The current Indexes generator is recursing O(N) times which is reaching recursion limits level for long IndexesList. This implementation has only O(log N) recursion. Change-Id: I423ef05152d77b18f1f5a64c49b273f49aa958bb Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Thiago Macieira --- src/corelib/kernel/qobjectdefs_impl.h | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/src/corelib/kernel/qobjectdefs_impl.h b/src/corelib/kernel/qobjectdefs_impl.h index a6ad00ea22..8afff1fb98 100644 --- a/src/corelib/kernel/qobjectdefs_impl.h +++ b/src/corelib/kernel/qobjectdefs_impl.h @@ -112,13 +112,31 @@ namespace QtPrivate { The Functor struct is the helper to call a functor of N argument. its call function is the same as the FunctionPointer::call function. */ - template struct IndexesList {}; - template struct IndexesAppend; - template struct IndexesAppend, Right> - { typedef IndexesList Value; }; - template struct Indexes - { typedef typename IndexesAppend::Value, N - 1>::Value Value; }; - template <> struct Indexes<0> { typedef IndexesList<> Value; }; + template using InvokeGenSeq = typename T::Type; + + template struct IndexesList { using Type = IndexesList; }; + + template struct ConcatSeqImpl; + + template + struct ConcatSeqImpl, IndexesList> + : IndexesList{}; + + template + using ConcatSeq = InvokeGenSeq>; + + template struct GenSeq; + template using makeIndexSequence = InvokeGenSeq>; + + template + struct GenSeq : ConcatSeq, makeIndexSequence>{}; + + template<> struct GenSeq<0> : IndexesList<>{}; + template<> struct GenSeq<1> : IndexesList<0>{}; + + template + struct Indexes { using Value = makeIndexSequence; }; + template struct FunctionPointer { enum {ArgumentCount = -1, IsPointerToMemberFunction = false}; }; template struct FunctorCall; -- cgit v1.2.3 From b0479aab297f041aa9842c3e1996d62c16d7dbcf Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sat, 28 Jul 2018 19:50:27 -0700 Subject: QUrl: Make sure we do reject URLs for which IDNA nameprep failed qt_nameprep() already reset the string to its original length to indicate failure, but we didn't handle that in qt_ACE_do(). So make it have a return value whcih makes it easier to handle that case and do handle it. [ChangeLog][QtCore][QUrl] Fixed a bug that caused URLs whose hostnames contained unassigned or prohibited Unicode codepoints to report isValid() = true, despite clearing the hostname. Change-Id: I41e7b3bced5944239f41fffd1545b7274c4b419d Reviewed-by: David Faure --- src/corelib/io/qurl_p.h | 2 +- src/corelib/io/qurlidna.cpp | 17 +++++++++++------ tests/auto/corelib/io/qurl/tst_qurl.cpp | 19 ++++++++++++++++++- 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/corelib/io/qurl_p.h b/src/corelib/io/qurl_p.h index cb88cac35e..1b9237e58a 100644 --- a/src/corelib/io/qurl_p.h +++ b/src/corelib/io/qurl_p.h @@ -65,7 +65,7 @@ extern Q_AUTOTEST_EXPORT int qt_urlRecode(QString &appendTo, const QChar *begin, enum AceLeadingDot { AllowLeadingDot, ForbidLeadingDot }; enum AceOperation { ToAceOnly, NormalizeAce }; extern QString qt_ACE_do(const QString &domain, AceOperation op, AceLeadingDot dot); -extern Q_AUTOTEST_EXPORT void qt_nameprep(QString *source, int from); +extern Q_AUTOTEST_EXPORT bool qt_nameprep(QString *source, int from); extern Q_AUTOTEST_EXPORT bool qt_check_std3rules(const QChar *uc, int len); extern Q_AUTOTEST_EXPORT void qt_punycodeEncoder(const QChar *s, int ucLength, QString *output); extern Q_AUTOTEST_EXPORT QString qt_punycodeDecoder(const QString &pc); diff --git a/src/corelib/io/qurlidna.cpp b/src/corelib/io/qurlidna.cpp index 2f8bd91f6e..2305e66407 100644 --- a/src/corelib/io/qurlidna.cpp +++ b/src/corelib/io/qurlidna.cpp @@ -2021,7 +2021,7 @@ static bool isBidirectionalL(uint uc) return false; } -Q_AUTOTEST_EXPORT void qt_nameprep(QString *source, int from) +Q_AUTOTEST_EXPORT bool qt_nameprep(QString *source, int from) { QChar *src = source->data(); // causes a detach, so we're sure the only one using it QChar *out = src + from; @@ -2036,7 +2036,7 @@ Q_AUTOTEST_EXPORT void qt_nameprep(QString *source, int from) } } if (out == e) - return; // everything was mapped easily (lowercased, actually) + return true; // everything was mapped easily (lowercased, actually) int firstNonAscii = out - src; // Characters unassigned in Unicode 3.2 are not allowed in "stored string" scheme @@ -2059,7 +2059,7 @@ Q_AUTOTEST_EXPORT void qt_nameprep(QString *source, int from) QChar::UnicodeVersion version = QChar::unicodeVersion(uc); if (version == QChar::Unicode_Unassigned || version > QChar::Unicode_3_2) { source->resize(from); // not allowed, clear the label - return; + return false; } } if (!isMappedToNothing(uc)) { @@ -2086,7 +2086,7 @@ Q_AUTOTEST_EXPORT void qt_nameprep(QString *source, int from) // Strip prohibited output if (containsProhibitedOuptut(source, firstNonAscii)) { source->resize(from); - return; + return false; } // Check for valid bidirectional characters @@ -2110,9 +2110,13 @@ Q_AUTOTEST_EXPORT void qt_nameprep(QString *source, int from) } if (containsRandALCat) { if (containsLCat || (!isBidirectionalRorAL(src[from].unicode()) - || !isBidirectionalRorAL(e[-1].unicode()))) + || !isBidirectionalRorAL(e[-1].unicode()))) { source->resize(from); // not allowed, clear the label + return false; + } } + + return true; } static const QChar *qt_find_nonstd3(const QChar *uc, int len, Qt::CaseSensitivity cs) @@ -2553,7 +2557,8 @@ QString qt_ACE_do(const QString &domain, AceOperation op, AceLeadingDot dot) } else { // Punycode encoding and decoding cannot be done in-place // That means we need one or two temporaries - qt_nameprep(&result, prevLen); + if (!qt_nameprep(&result, prevLen)) + return QString(); // failed labelLength = result.length() - prevLen; int toReserve = labelLength + 4 + 6; // "xn--" plus some extra bytes aceForm.resize(0); diff --git a/tests/auto/corelib/io/qurl/tst_qurl.cpp b/tests/auto/corelib/io/qurl/tst_qurl.cpp index 20282068cb..09aefcee91 100644 --- a/tests/auto/corelib/io/qurl/tst_qurl.cpp +++ b/tests/auto/corelib/io/qurl/tst_qurl.cpp @@ -2047,6 +2047,21 @@ void tst_QUrl::isValid() qPrintable(url.errorString())); } + { + QUrl url = QUrl::fromEncoded("foo://%f0%9f%93%99.example.la/g"); + QVERIFY(!url.isValid()); + QVERIFY(url.toString().isEmpty()); + QCOMPARE(url.path(), QString("/g")); + url.setHost("%f0%9f%93%99.example.la/"); + QVERIFY(!url.isValid()); + QVERIFY(url.toString().isEmpty()); + url.setHost("\xf0\x9f\x93\x99.example.la/"); + QVERIFY(!url.isValid()); + QVERIFY(url.toString().isEmpty()); + QVERIFY2(url.errorString().contains("Invalid hostname"), + qPrintable(url.errorString())); + } + { QUrl url("http://example.com"); QVERIFY(url.isValid()); @@ -2778,7 +2793,9 @@ void tst_QUrl::hosts() { QFETCH(QString, url); - QTEST(QUrl(url).host(), "host"); + QUrl u(url); + QTEST(u.host(), "host"); + QVERIFY(u.isEmpty() || u.isValid()); } void tst_QUrl::hostFlags_data() -- cgit v1.2.3 From 29778037f8a7b2c86bc4044409b37d5a51a15432 Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Thu, 5 Apr 2018 12:54:01 +0100 Subject: Don't block on lost context When glGetError returns GL_CONTEXT_LOST, on XCB + Nvidia at least, the error does not get cleared until the next successful glGetGraphicsResetStatus. We can't handle this properly until the start of the next frame where we will hopefully have a valid context, but in the meantime we should avoid locking up completely. Change-Id: Id438d44d83b926e1f3e4281ca3704231bf1a23cf Reviewed-by: Allan Sandfeld Jensen --- src/gui/opengl/qopenglframebufferobject.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp index 91c25184b6..83bc568ba7 100644 --- a/src/gui/opengl/qopenglframebufferobject.cpp +++ b/src/gui/opengl/qopenglframebufferobject.cpp @@ -55,12 +55,16 @@ QT_BEGIN_NAMESPACE #ifndef QT_NO_DEBUG #define QT_RESET_GLERROR() \ { \ - while (QOpenGLContext::currentContext()->functions()->glGetError() != GL_NO_ERROR) {} \ + while (true) {\ + GLenum error = QOpenGLContext::currentContext()->functions()->glGetError(); \ + if (error == GL_NO_ERROR || error == GL_CONTEXT_LOST) \ + break; \ + } \ } #define QT_CHECK_GLERROR() \ { \ GLenum err = QOpenGLContext::currentContext()->functions()->glGetError(); \ - if (err != GL_NO_ERROR) { \ + if (err != GL_NO_ERROR && err != GL_CONTEXT_LOST) { \ qDebug("[%s line %d] OpenGL Error: %d", \ __FILE__, __LINE__, (int)err); \ } \ @@ -126,6 +130,10 @@ QT_BEGIN_NAMESPACE #define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 #endif +#ifndef GL_CONTEXT_LOST +#define GL_CONTEXT_LOST 0x0507 +#endif + /*! \class QOpenGLFramebufferObjectFormat @@ -1303,8 +1311,11 @@ static QImage qt_gl_read_framebuffer(const QSize &size, GLenum internal_format, { QOpenGLContext *ctx = QOpenGLContext::currentContext(); QOpenGLFunctions *funcs = ctx->functions(); - while (funcs->glGetError()); - + while (true) { + GLenum error = funcs->glGetError(); + if (error == GL_NO_ERROR || error == GL_CONTEXT_LOST) + break; + } switch (internal_format) { case GL_RGB: case GL_RGB8: -- cgit v1.2.3 From 07f6eff58d5ffd8d148cd848141be1ba11c6c5da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Fri, 1 Jun 2018 10:33:08 +0200 Subject: Correctly initialize adopted threads in stub implementation Set data->threadId, which makes the thread detection used by Qt::AutoConnection work: it will now actually select Qt::DirectConnection. Change-Id: I9369e47eb7ed3ec88dba25f2d41e92139958bcd7 Reviewed-by: Lorn Potter --- src/corelib/thread/qthread.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index 472c6f6795..f784bf5cb6 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -778,7 +778,9 @@ QThreadData *QThreadData::current(bool createIfNecessary) if (!data && createIfNecessary) { data = new QThreadData; data->thread = new QAdoptedThread(data); + data->threadId.store(Qt::HANDLE(data->thread)); data->deref(); + data->isAdopted = true; if (!QCoreApplicationPrivate::theMainThread) QCoreApplicationPrivate::theMainThread = data->thread.load(); } -- cgit v1.2.3 From 815153d4a453855bb528f0fa9cb7e5a77d589a11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Thu, 31 May 2018 10:36:11 +0200 Subject: Add QThreadStorage stub implementation Add implementation for the no-thread configuration: Assume access will only happen from one thread and use a QScopedPointer to hold the data. Unlike the real implementation this version will delete the stored data on destruction, as opposed to on QApplication destruction. Change-Id: I9d8e89e7da18f967f463e2db7b50549c962acc84 Reviewed-by: Lorn Potter --- src/corelib/thread/qthreadstorage.h | 75 +++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/src/corelib/thread/qthreadstorage.h b/src/corelib/thread/qthreadstorage.h index fed41a0760..9a91883de8 100644 --- a/src/corelib/thread/qthreadstorage.h +++ b/src/corelib/thread/qthreadstorage.h @@ -152,6 +152,81 @@ public: QT_END_NAMESPACE +#else // !QT_NO_THREAD + +#include + +#include + +template +inline bool qThreadStorage_hasLocalData(const QScopedPointer &data) +{ + return !!data; +} + +template +inline bool qThreadStorage_hasLocalData(const QScopedPointer &data) +{ + return !!data ? *data != nullptr : false; +} + +template +inline void qThreadStorage_deleteLocalData(T *t) +{ + delete t; +} + +template +inline void qThreadStorage_deleteLocalData(T **t) +{ + delete *t; + delete t; +} + +template +class QThreadStorage +{ +private: + struct ScopedPointerThreadStorageDeleter + { + static inline void cleanup(T *t) + { + if (t == nullptr) + return; + qThreadStorage_deleteLocalData(t); + } + }; + QScopedPointer data; + +public: + QThreadStorage() = default; + ~QThreadStorage() = default; + QThreadStorage(const QThreadStorage &rhs) = delete; + QThreadStorage &operator=(const QThreadStorage &rhs) = delete; + + inline bool hasLocalData() const + { + return qThreadStorage_hasLocalData(data); + } + + inline T& localData() + { + if (!data) + data.reset(new T()); + return *data; + } + + inline T localData() const + { + return !!data ? *data : T(); + } + + inline void setLocalData(T t) + { + data.reset(new T(t)); + } +}; + #endif // QT_NO_THREAD #endif // QTHREADSTORAGE_H -- cgit v1.2.3 From 0a06e1baf9e6da5308582b9dc928f4d9fea508d0 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 29 Dec 2016 17:11:24 +0100 Subject: Modernize the "thread" feature Add it to configure.json and replace all occurrences of QT_NO_THREAD with QT_CONFIG(thread). Add conditions for other features that depend on thread support. Remove conditions where we can use the QMutex and QThreadStorage stubs. Change-Id: I284e5d794fda9a4c6f4a1ab29e55aa686272a0eb Reviewed-by: Eskil Abrahamsen Blomfeldt --- configure.json | 10 ++ src/corelib/animation/qabstractanimation.cpp | 12 +-- src/corelib/global/qconfig-bootstrapped.h | 2 +- src/corelib/global/qglobal.cpp | 4 - src/corelib/global/qglobalstatic.h | 2 +- src/corelib/global/qglobalstatic.qdoc | 2 +- src/corelib/global/qrandom.cpp | 2 +- src/corelib/io/qfilesystemengine_unix.cpp | 8 +- src/corelib/io/qfsfileengine_win.cpp | 1 - src/corelib/io/qprocess_unix.cpp | 1 - src/corelib/kernel/qcore_mac.cpp | 1 + src/corelib/kernel/qcoreapplication.cpp | 20 +--- src/corelib/kernel/qmetaobject.cpp | 12 ++- src/corelib/kernel/qobject.cpp | 6 +- src/corelib/kernel/qsystemerror.cpp | 4 +- src/corelib/thread/qmutex.cpp | 4 - src/corelib/thread/qmutex.h | 6 +- src/corelib/thread/qmutex_linux.cpp | 5 - src/corelib/thread/qmutex_mac.cpp | 5 - src/corelib/thread/qmutex_unix.cpp | 4 - src/corelib/thread/qmutexpool.cpp | 4 - src/corelib/thread/qmutexpool_p.h | 4 +- src/corelib/thread/qreadwritelock.cpp | 3 - src/corelib/thread/qreadwritelock.h | 6 +- src/corelib/thread/qreadwritelock_p.h | 4 +- src/corelib/thread/qsemaphore.cpp | 4 - src/corelib/thread/qsemaphore.h | 7 +- src/corelib/thread/qthread.cpp | 16 +-- src/corelib/thread/qthread.h | 6 +- src/corelib/thread/qthread_p.h | 10 +- src/corelib/thread/qthread_unix.cpp | 12 +-- src/corelib/thread/qthread_win.cpp | 12 +-- src/corelib/thread/qthreadpool.cpp | 4 - src/corelib/thread/qthreadpool.h | 4 +- src/corelib/thread/qthreadpool_p.h | 3 +- src/corelib/thread/qthreadstorage.cpp | 3 - src/corelib/thread/qthreadstorage.h | 6 +- src/corelib/thread/qwaitcondition.h | 5 +- src/corelib/thread/qwaitcondition_unix.cpp | 4 - src/corelib/thread/qwaitcondition_win.cpp | 3 - src/corelib/thread/thread.pri | 110 +++++++++++---------- src/corelib/tools/qdatetime.cpp | 2 +- src/dbus/qdbus_symbols.cpp | 2 - src/gui/configure.json | 6 +- src/gui/text/qfont.cpp | 13 --- src/network/configure.json | 3 +- src/network/ssl/qsslsocket_openssl_symbols.cpp | 2 - .../eventdispatchers/qunixeventdispatcher.cpp | 5 - .../fontdatabases/freetype/qfontengine_ft.cpp | 9 -- .../fontdatabases/windows/qwindowsfontdatabase.cpp | 12 --- .../platforms/windows/qwindowsthreadpoolrunner.h | 6 +- src/plugins/sqldrivers/mysql/qsql_mysql.cpp | 4 +- src/printsupport/dialogs/qprintpreviewdialog.cpp | 5 +- src/testlib/qtestcase.cpp | 18 +++- src/widgets/configure.json | 2 +- src/widgets/kernel/qwidget.cpp | 2 +- src/widgets/util/qcompleter.cpp | 1 + .../qcoreapplication/tst_qcoreapplication.cpp | 4 +- .../kernel/qcoreapplication/tst_qcoreapplication.h | 2 +- .../corelib/thread/qthreadonce/qthreadonce.cpp | 3 - .../auto/corelib/thread/qthreadonce/qthreadonce.h | 4 - tests/auto/corelib/thread/thread.pro | 39 ++++---- 62 files changed, 203 insertions(+), 282 deletions(-) diff --git a/configure.json b/configure.json index ae5f71291c..16a2af5bab 100644 --- a/configure.json +++ b/configure.json @@ -1106,10 +1106,17 @@ "condition": "libs.zlib", "output": [ "privateFeature" ] }, + "thread": { + "label": "Thread support", + "purpose": "Provides QThread and related classes.", + "section": "Kernel", + "output": [ "publicFeature" ] + }, "future": { "label": "QFuture", "purpose": "Provides QFuture and related classes.", "section": "Kernel", + "condition": "features.thread", "output": [ "publicFeature" ] }, "concurrent": { @@ -1122,6 +1129,7 @@ "dbus": { "label": "Qt D-Bus", "autoDetect": "!config.uikit && !config.android && !config.winrt", + "condition": "features.thread", "output": [ "privateFeature", "feature" ] }, "dbus-linked": { @@ -1153,10 +1161,12 @@ }, "network": { "label": "Qt Network", + "condition": "features.thread", "output": [ "privateFeature" ] }, "sql": { "label": "Qt Sql", + "condition": "features.thread", "output": [ "privateFeature" ] }, "testlib": { diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp index b3db200ed1..48983def79 100644 --- a/src/corelib/animation/qabstractanimation.cpp +++ b/src/corelib/animation/qabstractanimation.cpp @@ -215,9 +215,7 @@ typedef QList::ConstIterator AnimationListConstIt; QUnifiedTimer drives animations indirectly, via QAbstractAnimationTimer. */ -#ifndef QT_NO_THREAD Q_GLOBAL_STATIC(QThreadStorage, unifiedTimer) -#endif QUnifiedTimer::QUnifiedTimer() : QObject(), defaultDriver(this), lastTick(0), timingInterval(DEFAULT_TIMER_INTERVAL), @@ -234,18 +232,12 @@ QUnifiedTimer::QUnifiedTimer() : QUnifiedTimer *QUnifiedTimer::instance(bool create) { QUnifiedTimer *inst; -#ifndef QT_NO_THREAD if (create && !unifiedTimer()->hasLocalData()) { inst = new QUnifiedTimer; unifiedTimer()->setLocalData(inst); } else { inst = unifiedTimer() ? unifiedTimer()->localData() : 0; } -#else - Q_UNUSED(create); - static QUnifiedTimer unifiedTimer; - inst = &unifiedTimer; -#endif return inst; } @@ -554,7 +546,7 @@ bool QUnifiedTimer::canUninstallAnimationDriver(QAnimationDriver *d) return d == driver && driver != &defaultDriver; } -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) Q_GLOBAL_STATIC(QThreadStorage, animationTimer) #endif @@ -569,7 +561,7 @@ QAnimationTimer::QAnimationTimer() : QAnimationTimer *QAnimationTimer::instance(bool create) { QAnimationTimer *inst; -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) if (create && !animationTimer()->hasLocalData()) { inst = new QAnimationTimer; animationTimer()->setLocalData(inst); diff --git a/src/corelib/global/qconfig-bootstrapped.h b/src/corelib/global/qconfig-bootstrapped.h index b8b064d43b..a8dbb3edcd 100644 --- a/src/corelib/global/qconfig-bootstrapped.h +++ b/src/corelib/global/qconfig-bootstrapped.h @@ -115,7 +115,7 @@ #define QT_NO_SYSTEMLOCALE #define QT_FEATURE_systemsemaphore -1 #define QT_FEATURE_temporaryfile 1 -#define QT_NO_THREAD +#define QT_FEATURE_thread -1 #define QT_FEATURE_timezone -1 #define QT_FEATURE_topleveldomain -1 #define QT_NO_TRANSLATION diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 37cc40f577..a369bbe490 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -53,10 +53,6 @@ #include -#ifndef QT_NO_QOBJECT -#include -#endif - #include #include #include diff --git a/src/corelib/global/qglobalstatic.h b/src/corelib/global/qglobalstatic.h index 7a6dea9b92..555bdf04c1 100644 --- a/src/corelib/global/qglobalstatic.h +++ b/src/corelib/global/qglobalstatic.h @@ -55,7 +55,7 @@ enum GuardValues { }; } -#if defined(QT_NO_THREAD) || defined(Q_COMPILER_THREADSAFE_STATICS) +#if !QT_CONFIG(thread) || defined(Q_COMPILER_THREADSAFE_STATICS) // some compilers support thread-safe statics // The IA-64 C++ ABI requires this, so we know that all GCC versions since 3.4 // support it. C++11 also requires this behavior. diff --git a/src/corelib/global/qglobalstatic.qdoc b/src/corelib/global/qglobalstatic.qdoc index 303709bb1d..dbea04ecab 100644 --- a/src/corelib/global/qglobalstatic.qdoc +++ b/src/corelib/global/qglobalstatic.qdoc @@ -264,7 +264,7 @@ [stmt.decl], but as of the time of this writing, only compilers based on the IA-64 C++ ABI implemented it properly. The implementation requiring thread-safe initialization is also used on the Qt bootstrapped tools, which - define QT_NO_THREAD. + disable the "thread" feature. The implementation requiring thread-safe initialization from the compiler is the simplest: it creates the \a Type object as a function-local static diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp index 66deac2a29..a7d4aa303a 100644 --- a/src/corelib/global/qrandom.cpp +++ b/src/corelib/global/qrandom.cpp @@ -1298,7 +1298,7 @@ struct QRandEngine }; } -#if defined(QT_NO_THREAD) || defined(Q_OS_WIN) +#if defined(Q_OS_WIN) // On Windows srand() and rand() already use Thread-Local-Storage // to store the seed between calls static inline QRandEngine *randTLS() diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index d0cd5449f0..835e6a6a44 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -853,7 +853,7 @@ QByteArray QFileSystemEngine::id(int id) //static QString QFileSystemEngine::resolveUserName(uint userId) { -#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) +#if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) int size_max = sysconf(_SC_GETPW_R_SIZE_MAX); if (size_max == -1) size_max = 1024; @@ -862,7 +862,7 @@ QString QFileSystemEngine::resolveUserName(uint userId) #if !defined(Q_OS_INTEGRITY) struct passwd *pw = 0; -#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_VXWORKS) +#if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_VXWORKS) struct passwd entry; getpwuid_r(userId, &entry, buf.data(), buf.size(), &pw); #else @@ -877,7 +877,7 @@ QString QFileSystemEngine::resolveUserName(uint userId) //static QString QFileSystemEngine::resolveGroupName(uint groupId) { -#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) +#if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) int size_max = sysconf(_SC_GETPW_R_SIZE_MAX); if (size_max == -1) size_max = 1024; @@ -886,7 +886,7 @@ QString QFileSystemEngine::resolveGroupName(uint groupId) #if !defined(Q_OS_INTEGRITY) struct group *gr = 0; -#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_VXWORKS) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID) && (__ANDROID_API__ >= 24)) +#if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_VXWORKS) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID) && (__ANDROID_API__ >= 24)) size_max = sysconf(_SC_GETGR_R_SIZE_MAX); if (size_max == -1) size_max = 1024; diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index 93cfd93d7e..9d3bfbba31 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -45,7 +45,6 @@ #include "qfile.h" #include "qdir.h" -#include "private/qmutexpool_p.h" #include "qvarlengtharray.h" #include "qdatetime.h" #include "qt_windows.h" diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index 713af9bd40..7a2daa2a57 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -101,7 +101,6 @@ QT_END_NAMESPACE #include #include #include -#include #include #include #include diff --git a/src/corelib/kernel/qcore_mac.cpp b/src/corelib/kernel/qcore_mac.cpp index b5df0db232..58380001a4 100644 --- a/src/corelib/kernel/qcore_mac.cpp +++ b/src/corelib/kernel/qcore_mac.cpp @@ -42,6 +42,7 @@ #include "qhash.h" #include "qpair.h" +#include "qmutex.h" #include "qvarlengtharray.h" QT_BEGIN_NAMESPACE diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index aea8fe6658..04da52a960 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -58,9 +58,11 @@ #include #ifndef QT_NO_QOBJECT #include -#include #include #include +#if QT_CONFIG(thread) +#include +#endif #endif #include #include @@ -268,9 +270,7 @@ typedef QList QStartUpFuncList; Q_GLOBAL_STATIC(QStartUpFuncList, preRList) typedef QList QVFuncList; Q_GLOBAL_STATIC(QVFuncList, postRList) -#ifndef QT_NO_QOBJECT static QBasicMutex globalRoutinesMutex; -#endif /*! \internal @@ -289,9 +289,7 @@ void qAddPreRoutine(QtStartUpFunction p) // Due to C++11 parallel dynamic initialization, this can be called // from multiple threads. -#ifndef QT_NO_THREAD QMutexLocker locker(&globalRoutinesMutex); -#endif list->prepend(p); // in case QCoreApplication is re-created, see qt_call_pre_routines } @@ -300,9 +298,7 @@ void qAddPostRoutine(QtCleanUpFunction p) QVFuncList *list = postRList(); if (!list) return; -#ifndef QT_NO_THREAD QMutexLocker locker(&globalRoutinesMutex); -#endif list->prepend(p); } @@ -311,9 +307,7 @@ void qRemovePostRoutine(QtCleanUpFunction p) QVFuncList *list = postRList(); if (!list) return; -#ifndef QT_NO_THREAD QMutexLocker locker(&globalRoutinesMutex); -#endif list->removeAll(p); } @@ -324,9 +318,7 @@ static void qt_call_pre_routines() QVFuncList list; { -#ifndef QT_NO_THREAD QMutexLocker locker(&globalRoutinesMutex); -#endif // Unlike qt_call_post_routines, we don't empty the list, because // Q_COREAPP_STARTUP_FUNCTION is a macro, so the user expects // the function to be executed every time QCoreApplication is created. @@ -345,9 +337,7 @@ void Q_CORE_EXPORT qt_call_post_routines() QVFuncList list; { // extract the current list and make the stored list empty -#ifndef QT_NO_THREAD QMutexLocker locker(&globalRoutinesMutex); -#endif qSwap(*postRList, list); } @@ -513,7 +503,7 @@ QCoreApplicationPrivate::~QCoreApplicationPrivate() void QCoreApplicationPrivate::cleanupThreadData() { if (threadData && !threadData_clean) { -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) void *data = &threadData->tls; QThreadStorageData::finish((void **)data); #endif @@ -888,7 +878,7 @@ QCoreApplication::~QCoreApplication() QCoreApplicationPrivate::is_app_running = false; #endif -#if !defined(QT_NO_THREAD) +#if QT_CONFIG(thread) // Synchronize and stop the global thread pool threads. QThreadPool *globalThreadPool = 0; QT_TRY { diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 65d0bd2351..6c17535f07 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -50,7 +50,9 @@ #include #include #include +#if QT_CONFIG(thread) #include +#endif #include "private/qobject_p.h" #include "private/qmetaobject_p.h" @@ -1540,14 +1542,14 @@ bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase * QCoreApplication::postEvent(object, new QMetaCallEvent(slot, 0, -1, 1, types, args)); } else if (type == Qt::BlockingQueuedConnection) { -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) if (currentThread == objectThread) qWarning("QMetaObject::invokeMethod: Dead lock detected"); QSemaphore semaphore; QCoreApplication::postEvent(object, new QMetaCallEvent(slot, 0, -1, 0, 0, argv, &semaphore)); semaphore.acquire(); -#endif // QT_NO_THREAD +#endif // QT_CONFIG(thread) } else { qWarning("QMetaObject::invokeMethod: Unknown connection type"); return false; @@ -2272,7 +2274,7 @@ bool QMetaMethod::invoke(QObject *object, : Qt::QueuedConnection; } -#ifdef QT_NO_THREAD +#if !QT_CONFIG(thread) if (connectionType == Qt::BlockingQueuedConnection) { connectionType = Qt::DirectConnection; } @@ -2348,7 +2350,7 @@ bool QMetaMethod::invoke(QObject *object, QCoreApplication::postEvent(object, new QMetaCallEvent(idx_offset, idx_relative, callFunction, 0, -1, nargs, types, args)); } else { // blocking queued connection -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) if (currentThread == objectThread) { qWarning("QMetaMethod::invoke: Dead lock detected in " "BlockingQueuedConnection: Receiver is %s(%p)", @@ -2359,7 +2361,7 @@ bool QMetaMethod::invoke(QObject *object, QCoreApplication::postEvent(object, new QMetaCallEvent(idx_offset, idx_relative, callFunction, 0, -1, 0, 0, param, &semaphore)); semaphore.acquire(); -#endif // QT_NO_THREAD +#endif // QT_CONFIG(thread) } return true; } diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 698ac256ff..6254330d25 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -59,7 +59,9 @@ #include #include #include +#if QT_CONFIG(thread) #include +#endif #include #include @@ -488,7 +490,7 @@ QMetaCallEvent::~QMetaCallEvent() free(types_); free(args_); } -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) if (semaphore_) semaphore_->release(); #endif @@ -3727,7 +3729,7 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i || (c->connectionType == Qt::QueuedConnection)) { queued_activate(sender, signal_index, c, argv ? argv : empty_argv, locker); continue; -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) } else if (c->connectionType == Qt::BlockingQueuedConnection) { if (receiverInSameThread) { qWarning("Qt: Dead lock detected while activating a BlockingQueuedConnection: " diff --git a/src/corelib/kernel/qsystemerror.cpp b/src/corelib/kernel/qsystemerror.cpp index fc825257ec..53c3136857 100644 --- a/src/corelib/kernel/qsystemerror.cpp +++ b/src/corelib/kernel/qsystemerror.cpp @@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE -#if !defined(Q_OS_WIN) && !defined(QT_NO_THREAD) && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX) && \ +#if !defined(Q_OS_WIN) && QT_CONFIG(thread) && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX) && \ defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L namespace { // There are two incompatible versions of strerror_r: @@ -130,7 +130,7 @@ static QString standardLibraryErrorString(int errorCode) s = QT_TRANSLATE_NOOP("QIODevice", "No space left on device"); break; default: { - #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX) + #if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX) QByteArray buf(1024, Qt::Uninitialized); ret = fromstrerror_helper(strerror_r(errorCode, buf.data(), buf.size()), buf); #else diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp index 63fb6f3efb..3881ac017e 100644 --- a/src/corelib/thread/qmutex.cpp +++ b/src/corelib/thread/qmutex.cpp @@ -42,8 +42,6 @@ #include "qplatformdefs.h" #include "qmutex.h" #include - -#ifndef QT_NO_THREAD #include "qatomic.h" #include "qelapsedtimer.h" #include "qthread.h" @@ -739,5 +737,3 @@ QT_END_NAMESPACE #else # include "qmutex_unix.cpp" #endif - -#endif // QT_NO_THREAD diff --git a/src/corelib/thread/qmutex.h b/src/corelib/thread/qmutex.h index 7cda53db5f..837355a602 100644 --- a/src/corelib/thread/qmutex.h +++ b/src/corelib/thread/qmutex.h @@ -54,7 +54,7 @@ class tst_QMutex; QT_BEGIN_NAMESPACE -#if !defined(QT_NO_THREAD) || defined(Q_CLANG_QDOC) +#if QT_CONFIG(thread) || defined(Q_CLANG_QDOC) #ifdef Q_OS_LINUX # define QT_MUTEX_LOCK_NOEXCEPT Q_DECL_NOTHROW @@ -250,7 +250,7 @@ private: quintptr val; }; -#else // QT_NO_THREAD && !Q_CLANG_QDOC +#else // !QT_CONFIG(thread) && !Q_CLANG_QDOC class Q_CORE_EXPORT QMutex { @@ -301,7 +301,7 @@ private: typedef QMutex QBasicMutex; -#endif // QT_NO_THREAD && !Q_CLANG_QDOC +#endif // !QT_CONFIG(thread) && !Q_CLANG_QDOC QT_END_NAMESPACE diff --git a/src/corelib/thread/qmutex_linux.cpp b/src/corelib/thread/qmutex_linux.cpp index d3d97ea108..507e72cb76 100644 --- a/src/corelib/thread/qmutex_linux.cpp +++ b/src/corelib/thread/qmutex_linux.cpp @@ -40,8 +40,6 @@ #include "qplatformdefs.h" #include "qmutex.h" - -#ifndef QT_NO_THREAD #include "qatomic.h" #include "qmutex_p.h" #include "qfutex_p.h" @@ -54,7 +52,6 @@ # define FUTEX_PRIVATE_FLAG 0 #endif - QT_BEGIN_NAMESPACE using namespace QtFutex; @@ -183,5 +180,3 @@ void QBasicMutex::unlockInternal() Q_DECL_NOTHROW } QT_END_NAMESPACE - -#endif // QT_NO_THREAD diff --git a/src/corelib/thread/qmutex_mac.cpp b/src/corelib/thread/qmutex_mac.cpp index 67498611c9..9a8d9bc750 100644 --- a/src/corelib/thread/qmutex_mac.cpp +++ b/src/corelib/thread/qmutex_mac.cpp @@ -39,9 +39,6 @@ #include "qplatformdefs.h" #include "qmutex.h" - -#if !defined(QT_NO_THREAD) - #include "qmutex_p.h" #include @@ -89,5 +86,3 @@ void QMutexPrivate::wakeUp() Q_DECL_NOTHROW QT_END_NAMESPACE - -#endif //QT_NO_THREAD diff --git a/src/corelib/thread/qmutex_unix.cpp b/src/corelib/thread/qmutex_unix.cpp index 91f02ba3ec..3ee24a292c 100644 --- a/src/corelib/thread/qmutex_unix.cpp +++ b/src/corelib/thread/qmutex_unix.cpp @@ -42,8 +42,6 @@ #include "qmutex.h" #include "qstring.h" #include "qelapsedtimer.h" - -#ifndef QT_NO_THREAD #include "qatomic.h" #include "qmutex_p.h" #include @@ -159,5 +157,3 @@ void QMutexPrivate::wakeUp() Q_DECL_NOTHROW #endif QT_END_NAMESPACE - -#endif // QT_NO_THREAD diff --git a/src/corelib/thread/qmutexpool.cpp b/src/corelib/thread/qmutexpool.cpp index 90b6989467..3f9e8da942 100644 --- a/src/corelib/thread/qmutexpool.cpp +++ b/src/corelib/thread/qmutexpool.cpp @@ -40,8 +40,6 @@ #include "qatomic.h" #include "qmutexpool_p.h" -#ifndef QT_NO_THREAD - QT_BEGIN_NAMESPACE Q_GLOBAL_STATIC_WITH_ARGS(QMutexPool, globalMutexPool, (QMutex::Recursive)) @@ -148,5 +146,3 @@ QMutex *QMutexPool::globalInstanceGet(const void *address) } QT_END_NAMESPACE - -#endif // QT_NO_THREAD diff --git a/src/corelib/thread/qmutexpool_p.h b/src/corelib/thread/qmutexpool_p.h index 58d853b0e3..89d006ac29 100644 --- a/src/corelib/thread/qmutexpool_p.h +++ b/src/corelib/thread/qmutexpool_p.h @@ -56,7 +56,7 @@ #include "QtCore/qmutex.h" #include "QtCore/qvarlengtharray.h" -#ifndef QT_NO_THREAD +QT_REQUIRE_CONFIG(thread); QT_BEGIN_NAMESPACE @@ -85,6 +85,4 @@ private: QT_END_NAMESPACE -#endif // QT_NO_THREAD - #endif // QMUTEXPOOL_P_H diff --git a/src/corelib/thread/qreadwritelock.cpp b/src/corelib/thread/qreadwritelock.cpp index 42befc4b80..21835ff592 100644 --- a/src/corelib/thread/qreadwritelock.cpp +++ b/src/corelib/thread/qreadwritelock.cpp @@ -42,7 +42,6 @@ #include "qplatformdefs.h" #include "qreadwritelock.h" -#ifndef QT_NO_THREAD #include "qmutex.h" #include "qthread.h" #include "qwaitcondition.h" @@ -781,5 +780,3 @@ void QReadWriteLockPrivate::release() */ QT_END_NAMESPACE - -#endif // QT_NO_THREAD diff --git a/src/corelib/thread/qreadwritelock.h b/src/corelib/thread/qreadwritelock.h index ecdb98f2f5..65fa76fd6d 100644 --- a/src/corelib/thread/qreadwritelock.h +++ b/src/corelib/thread/qreadwritelock.h @@ -45,7 +45,7 @@ QT_BEGIN_NAMESPACE -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) class QReadWriteLockPrivate; @@ -174,7 +174,7 @@ inline QWriteLocker::QWriteLocker(QReadWriteLock *areadWriteLock) #pragma warning( pop ) #endif -#else // QT_NO_THREAD +#else // QT_CONFIG(thread) class Q_CORE_EXPORT QReadWriteLock { @@ -225,7 +225,7 @@ private: Q_DISABLE_COPY(QWriteLocker) }; -#endif // QT_NO_THREAD +#endif // QT_CONFIG(thread) QT_END_NAMESPACE diff --git a/src/corelib/thread/qreadwritelock_p.h b/src/corelib/thread/qreadwritelock_p.h index a01d010043..31da2401c0 100644 --- a/src/corelib/thread/qreadwritelock_p.h +++ b/src/corelib/thread/qreadwritelock_p.h @@ -56,7 +56,7 @@ #include #include -#ifndef QT_NO_THREAD +QT_REQUIRE_CONFIG(thread); QT_BEGIN_NAMESPACE @@ -99,6 +99,4 @@ public: QT_END_NAMESPACE -#endif // QT_NO_THREAD - #endif // QREADWRITELOCK_P_H diff --git a/src/corelib/thread/qsemaphore.cpp b/src/corelib/thread/qsemaphore.cpp index 82d439a728..bb578ff617 100644 --- a/src/corelib/thread/qsemaphore.cpp +++ b/src/corelib/thread/qsemaphore.cpp @@ -39,8 +39,6 @@ ****************************************************************************/ #include "qsemaphore.h" - -#ifndef QT_NO_THREAD #include "qmutex.h" #include "qfutex_p.h" #include "qwaitcondition.h" @@ -646,5 +644,3 @@ bool QSemaphore::tryAcquire(int n, int timeout) QT_END_NAMESPACE - -#endif // QT_NO_THREAD diff --git a/src/corelib/thread/qsemaphore.h b/src/corelib/thread/qsemaphore.h index 2639085e99..b830ff1bfd 100644 --- a/src/corelib/thread/qsemaphore.h +++ b/src/corelib/thread/qsemaphore.h @@ -42,10 +42,9 @@ #include -QT_BEGIN_NAMESPACE - +QT_REQUIRE_CONFIG(thread); -#ifndef QT_NO_THREAD +QT_BEGIN_NAMESPACE class QSemaphorePrivate; @@ -113,8 +112,6 @@ private: int m_n; }; -#endif // QT_NO_THREAD - QT_END_NAMESPACE #endif // QSEMAPHORE_H diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index f784bf5cb6..a4101764bc 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -103,7 +103,7 @@ QThreadData::~QThreadData() void QThreadData::ref() { -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) (void) _ref.ref(); Q_ASSERT(_ref.load() != 0); #endif @@ -111,7 +111,7 @@ void QThreadData::ref() void QThreadData::deref() { -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) if (!_ref.deref()) delete this; #endif @@ -134,7 +134,7 @@ QAdoptedThread::QAdoptedThread(QThreadData *data) { // thread should be running and not finished for the lifetime // of the application (even if QCoreApplication goes away) -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) d_func()->running = true; d_func()->finished = false; init(); @@ -148,7 +148,7 @@ QAdoptedThread::~QAdoptedThread() // fprintf(stderr, "~QAdoptedThread = %p\n", this); } -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) void QAdoptedThread::run() { // this function should never be called @@ -756,7 +756,7 @@ int QThread::loopLevel() const return d->data->eventLoops.size(); } -#else // QT_NO_THREAD +#else // QT_CONFIG(thread) QThread::QThread(QObject *parent) : QObject(*(new QThreadPrivate), parent) @@ -813,7 +813,7 @@ QThreadPrivate::~QThreadPrivate() delete data; } -#endif // QT_NO_THREAD +#endif // QT_CONFIG(thread) /*! \since 5.0 @@ -850,7 +850,7 @@ void QThread::setEventDispatcher(QAbstractEventDispatcher *eventDispatcher) } } -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) /*! \reimp @@ -1015,7 +1015,7 @@ QDaemonThread::~QDaemonThread() { } -#endif // QT_NO_THREAD +#endif // QT_CONFIG(thread) QT_END_NAMESPACE diff --git a/src/corelib/thread/qthread.h b/src/corelib/thread/qthread.h index 83c3329cc0..d0ffd9f909 100644 --- a/src/corelib/thread/qthread.h +++ b/src/corelib/thread/qthread.h @@ -66,7 +66,7 @@ class QThreadData; class QThreadPrivate; class QAbstractEventDispatcher; -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) class Q_CORE_EXPORT QThread : public QObject { Q_OBJECT @@ -239,7 +239,7 @@ QThread *QThread::create(Function &&f) #endif // QT_CONFIG(cxx11_future) -#else // QT_NO_THREAD +#else // QT_CONFIG(thread) class Q_CORE_EXPORT QThread : public QObject { @@ -267,7 +267,7 @@ private: Q_DECLARE_PRIVATE(QThread) }; -#endif // QT_NO_THREAD +#endif // QT_CONFIG(thread) QT_END_NAMESPACE diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h index 93f245ff6e..22a0669032 100644 --- a/src/corelib/thread/qthread_p.h +++ b/src/corelib/thread/qthread_p.h @@ -57,7 +57,9 @@ #include "QtCore/qthread.h" #include "QtCore/qmutex.h" #include "QtCore/qstack.h" +#if QT_CONFIG(thread) #include "QtCore/qwaitcondition.h" +#endif #include "QtCore/qmap.h" #include "QtCore/qcoreapplication.h" #include "private/qobject_p.h" @@ -141,7 +143,7 @@ private: using QVector::insert; }; -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) class Q_CORE_EXPORT QDaemonThread : public QThread { @@ -210,7 +212,7 @@ public: } }; -#else // QT_NO_THREAD +#else // QT_CONFIG(thread) class QThreadPrivate : public QObjectPrivate { @@ -231,7 +233,7 @@ public: Q_DECLARE_PUBLIC(QThread) }; -#endif // QT_NO_THREAD +#endif // QT_CONFIG(thread) class QThreadData { @@ -327,7 +329,7 @@ public: void init(); private: -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) void run() override; #endif }; diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index 0b3c7ddf10..329caa02ba 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -103,7 +103,7 @@ QT_BEGIN_NAMESPACE -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) Q_STATIC_ASSERT(sizeof(pthread_t) <= sizeof(Qt::HANDLE)); @@ -270,7 +270,7 @@ extern "C" { typedef void*(*QtThreadCallback)(void*); } -#endif // QT_NO_THREAD +#endif // QT_CONFIG(thread) QAbstractEventDispatcher *QThreadPrivate::createEventDispatcher(QThreadData *data) { @@ -295,7 +295,7 @@ QAbstractEventDispatcher *QThreadPrivate::createEventDispatcher(QThreadData *dat #endif } -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) #if (defined(Q_OS_LINUX) || defined(Q_OS_MAC) || defined(Q_OS_QNX)) static void setCurrentThreadName(const char *name) @@ -513,7 +513,7 @@ void QThread::yieldCurrentThread() sched_yield(); } -#endif // QT_NO_THREAD +#endif // QT_CONFIG(thread) static timespec makeTimespec(time_t secs, long nsecs) { @@ -538,7 +538,7 @@ void QThread::usleep(unsigned long usecs) qt_nanosleep(makeTimespec(usecs / 1000 / 1000, usecs % (1000*1000) * 1000)); } -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) #ifdef QT_HAS_THREAD_PRIORITY_SCHEDULING #if defined(Q_OS_QNX) @@ -839,7 +839,7 @@ void QThreadPrivate::setPriority(QThread::Priority threadPriority) #endif } -#endif // QT_NO_THREAD +#endif // QT_CONFIG(thread) QT_END_NAMESPACE diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp index 83bcb7d751..57ae671897 100644 --- a/src/corelib/thread/qthread_win.cpp +++ b/src/corelib/thread/qthread_win.cpp @@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) #ifdef Q_OS_WINRT inline DWORD qWinRTTlsAlloc() { @@ -330,7 +330,7 @@ void qt_set_thread_name(HANDLE threadId, LPCSTR threadName) ** QThreadPrivate *************************************************************************/ -#endif // QT_NO_THREAD +#endif // QT_CONFIG(thread) QAbstractEventDispatcher *QThreadPrivate::createEventDispatcher(QThreadData *data) { @@ -342,7 +342,7 @@ QAbstractEventDispatcher *QThreadPrivate::createEventDispatcher(QThreadData *dat #endif } -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(void *arg) Q_DECL_NOEXCEPT { @@ -444,7 +444,7 @@ void QThread::yieldCurrentThread() #endif } -#endif // QT_NO_THREAD +#endif // QT_CONFIG(thread) void QThread::sleep(unsigned long secs) { @@ -461,7 +461,7 @@ void QThread::usleep(unsigned long usecs) ::Sleep((usecs / 1000) + 1); } -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) void QThread::start(Priority priority) { @@ -699,6 +699,6 @@ void QThreadPrivate::setPriority(QThread::Priority threadPriority) } } -#endif // QT_NO_THREAD +#endif // QT_CONFIG(thread) QT_END_NAMESPACE diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp index 157cbeaf4d..ea2c611082 100644 --- a/src/corelib/thread/qthreadpool.cpp +++ b/src/corelib/thread/qthreadpool.cpp @@ -43,8 +43,6 @@ #include -#ifndef QT_NO_THREAD - QT_BEGIN_NAMESPACE Q_GLOBAL_STATIC(QThreadPool, theInstance) @@ -730,5 +728,3 @@ void QThreadPool::cancel(QRunnable *runnable) QT_END_NAMESPACE #include "moc_qthreadpool.cpp" - -#endif diff --git a/src/corelib/thread/qthreadpool.h b/src/corelib/thread/qthreadpool.h index 606e192768..cd27b7c08a 100644 --- a/src/corelib/thread/qthreadpool.h +++ b/src/corelib/thread/qthreadpool.h @@ -45,7 +45,7 @@ #include #include -#ifndef QT_NO_THREAD +QT_REQUIRE_CONFIG(thread); QT_BEGIN_NAMESPACE @@ -97,6 +97,4 @@ public: QT_END_NAMESPACE -#endif // QT_NO_THREAD - #endif diff --git a/src/corelib/thread/qthreadpool_p.h b/src/corelib/thread/qthreadpool_p.h index d03ba9d77f..0e6a00d243 100644 --- a/src/corelib/thread/qthreadpool_p.h +++ b/src/corelib/thread/qthreadpool_p.h @@ -59,7 +59,7 @@ #include "QtCore/qqueue.h" #include "private/qobject_p.h" -#ifndef QT_NO_THREAD +QT_REQUIRE_CONFIG(thread); QT_BEGIN_NAMESPACE @@ -184,5 +184,4 @@ public: QT_END_NAMESPACE -#endif // QT_NO_THREAD #endif diff --git a/src/corelib/thread/qthreadstorage.cpp b/src/corelib/thread/qthreadstorage.cpp index c0b523a431..8b82118a5c 100644 --- a/src/corelib/thread/qthreadstorage.cpp +++ b/src/corelib/thread/qthreadstorage.cpp @@ -39,7 +39,6 @@ #include "qthreadstorage.h" -#ifndef QT_NO_THREAD #include "qthread.h" #include "qthread_p.h" #include "qmutex.h" @@ -323,6 +322,4 @@ void QThreadStorageData::finish(void **p) \sa localData(), hasLocalData() */ -#endif // QT_NO_THREAD - QT_END_NAMESPACE diff --git a/src/corelib/thread/qthreadstorage.h b/src/corelib/thread/qthreadstorage.h index 9a91883de8..d556e33c57 100644 --- a/src/corelib/thread/qthreadstorage.h +++ b/src/corelib/thread/qthreadstorage.h @@ -42,7 +42,7 @@ #include -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) QT_BEGIN_NAMESPACE @@ -152,7 +152,7 @@ public: QT_END_NAMESPACE -#else // !QT_NO_THREAD +#else // !QT_CONFIG(thread) #include @@ -227,6 +227,6 @@ public: } }; -#endif // QT_NO_THREAD +#endif // QT_CONFIG(thread) #endif // QTHREADSTORAGE_H diff --git a/src/corelib/thread/qwaitcondition.h b/src/corelib/thread/qwaitcondition.h index e42efbdfca..11520e4cfe 100644 --- a/src/corelib/thread/qwaitcondition.h +++ b/src/corelib/thread/qwaitcondition.h @@ -46,8 +46,7 @@ QT_BEGIN_NAMESPACE - -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) class QDeadlineTimer; class QWaitConditionPrivate; @@ -98,7 +97,7 @@ public: void wakeAll() {} }; -#endif // QT_NO_THREAD +#endif // QT_CONFIG(thread) QT_END_NAMESPACE diff --git a/src/corelib/thread/qwaitcondition_unix.cpp b/src/corelib/thread/qwaitcondition_unix.cpp index 9706be1504..c93328b4bc 100644 --- a/src/corelib/thread/qwaitcondition_unix.cpp +++ b/src/corelib/thread/qwaitcondition_unix.cpp @@ -56,8 +56,6 @@ #include #include -#ifndef QT_NO_THREAD - QT_BEGIN_NAMESPACE #ifdef Q_OS_ANDROID @@ -264,5 +262,3 @@ bool QWaitCondition::wait(QReadWriteLock *readWriteLock, QDeadlineTimer deadline } QT_END_NAMESPACE - -#endif // QT_NO_THREAD diff --git a/src/corelib/thread/qwaitcondition_win.cpp b/src/corelib/thread/qwaitcondition_win.cpp index 61e4c2bcb1..534456a935 100644 --- a/src/corelib/thread/qwaitcondition_win.cpp +++ b/src/corelib/thread/qwaitcondition_win.cpp @@ -45,8 +45,6 @@ #include "qlist.h" #include "qalgorithms.h" -#ifndef QT_NO_THREAD - #define Q_MUTEX_T void* #include #include @@ -247,4 +245,3 @@ void QWaitCondition::wakeAll() } QT_END_NAMESPACE -#endif // QT_NO_THREAD diff --git a/src/corelib/thread/thread.pri b/src/corelib/thread/thread.pri index dae72564b4..22f0de0523 100644 --- a/src/corelib/thread/thread.pri +++ b/src/corelib/thread/thread.pri @@ -1,38 +1,66 @@ # Qt core thread module -# public headers -HEADERS += thread/qmutex.h \ - thread/qrunnable.h \ - thread/qreadwritelock.h \ - thread/qsemaphore.h \ - thread/qthread.h \ - thread/qthreadpool.h \ - thread/qthreadstorage.h \ - thread/qwaitcondition.h \ - thread/qatomic.h \ - thread/qatomic_bootstrap.h \ - thread/qatomic_cxx11.h \ - thread/qbasicatomic.h \ - thread/qgenericatomic.h +HEADERS += \ + thread/qmutex.h \ + thread/qreadwritelock.h \ + thread/qrunnable.h \ + thread/qthread.h \ + thread/qthreadstorage.h \ + thread/qwaitcondition.h -# private headers -HEADERS += thread/qmutex_p.h \ - thread/qmutexpool_p.h \ - thread/qfutex_p.h \ - thread/qorderedmutexlocker_p.h \ - thread/qreadwritelock_p.h \ - thread/qthread_p.h \ - thread/qthreadpool_p.h +SOURCES += \ + thread/qrunnable.cpp \ + thread/qthread.cpp -SOURCES += thread/qatomic.cpp \ - thread/qmutex.cpp \ - thread/qreadwritelock.cpp \ - thread/qrunnable.cpp \ - thread/qmutexpool.cpp \ - thread/qsemaphore.cpp \ - thread/qthread.cpp \ - thread/qthreadpool.cpp \ - thread/qthreadstorage.cpp +win32 { + HEADERS += thread/qatomic_msvc.h + + SOURCES += thread/qthread_win.cpp +} else { + SOURCES += thread/qthread_unix.cpp +} + +qtConfig(thread) { + HEADERS += \ + thread/qatomic.h \ + thread/qatomic_bootstrap.h \ + thread/qatomic_cxx11.h \ + thread/qbasicatomic.h \ + thread/qfutex_p.h \ + thread/qgenericatomic.h \ + thread/qmutexpool_p.h \ + thread/qmutex_p.h \ + thread/qorderedmutexlocker_p.h \ + thread/qreadwritelock_p.h \ + thread/qsemaphore.h \ + thread/qthreadpool.h \ + thread/qthreadpool_p.h \ + thread/qthread_p.h + + SOURCES += \ + thread/qatomic.cpp \ + thread/qmutex.cpp \ + thread/qmutexpool.cpp \ + thread/qreadwritelock.cpp \ + thread/qsemaphore.cpp \ + thread/qthreadpool.cpp \ + thread/qthreadstorage.cpp + + win32 { + SOURCES += \ + thread/qmutex_win.cpp \ + thread/qwaitcondition_win.cpp + } else { + darwin { + SOURCES += thread/qmutex_mac.cpp + } else: linux { + SOURCES += thread/qmutex_linux.cpp + } else { + SOURCES += thread/qmutex_unix.cpp + } + SOURCES += thread/qwaitcondition_unix.cpp + } +} qtConfig(future) { HEADERS += \ @@ -52,24 +80,4 @@ qtConfig(future) { thread/qresultstore.cpp } -win32 { - HEADERS += thread/qatomic_msvc.h - - SOURCES += \ - thread/qmutex_win.cpp \ - thread/qthread_win.cpp \ - thread/qwaitcondition_win.cpp -} else { - darwin { - SOURCES += thread/qmutex_mac.cpp - } else: linux { - SOURCES += thread/qmutex_linux.cpp - } else { - SOURCES += thread/qmutex_unix.cpp - } - SOURCES += \ - thread/qthread_unix.cpp \ - thread/qwaitcondition_unix.cpp -} - qtConfig(std-atomic64): QMAKE_USE += libatomic diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index 288c7963d9..58755c94bb 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -2339,7 +2339,7 @@ static bool qt_localtime(qint64 msecsSinceEpoch, QDate *localDate, QTime *localT // localtime_r() does not have this requirement, so make an explicit call. // The explicit call should also request the timezone info be re-parsed. qt_tzset(); -#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) +#if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) // Use the reentrant version of localtime() where available // as is thread-safe and doesn't use a shared static data area tm *res = 0; diff --git a/src/dbus/qdbus_symbols.cpp b/src/dbus/qdbus_symbols.cpp index 5e06c337f2..f22696639d 100644 --- a/src/dbus/qdbus_symbols.cpp +++ b/src/dbus/qdbus_symbols.cpp @@ -79,10 +79,8 @@ bool qdbus_loadLibDBus() #endif static bool triedToLoadLibrary = false; -#ifndef QT_NO_THREAD static QBasicMutex mutex; QMutexLocker locker(&mutex); -#endif QLibrary *&lib = qdbus_libdbus; if (triedToLoadLibrary) diff --git a/src/gui/configure.json b/src/gui/configure.json index 506caf6794..8e6569c069 100644 --- a/src/gui/configure.json +++ b/src/gui/configure.json @@ -979,7 +979,7 @@ }, "evdev": { "label": "evdev", - "condition": "tests.evdev", + "condition": "features.thread && tests.evdev", "output": [ "privateFeature" ] }, "freetype": { @@ -1170,7 +1170,7 @@ }, "egl_x11": { "label": "EGL on X11", - "condition": "features.egl && tests.egl-x11", + "condition": "features.thread && features.egl && tests.egl-x11", "output": [ "privateFeature" ] }, "eglfs": { @@ -1300,7 +1300,7 @@ "section": "Platform plugins", "autoDetect": "!config.darwin", "enable": "input.xcb == 'system' || input.xcb == 'qt' || input.xcb == 'yes'", - "condition": "libs.xcb", + "condition": "features.thread && libs.xcb", "output": [ "privateFeature" ] }, "system-xcb": { diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index f7462b65c8..580a09427c 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -2703,18 +2703,6 @@ static const int slow_timeout = 300000; // 5m const uint QFontCache::min_cost = 4*1024; // 4mb -#ifdef QT_NO_THREAD -Q_GLOBAL_STATIC(QFontCache, theFontCache) - -QFontCache *QFontCache::instance() -{ - return theFontCache(); -} - -void QFontCache::cleanup() -{ -} -#else Q_GLOBAL_STATIC(QThreadStorage, theFontCache) QFontCache *QFontCache::instance() @@ -2736,7 +2724,6 @@ void QFontCache::cleanup() if (cache && cache->hasLocalData()) cache->setLocalData(0); } -#endif // QT_NO_THREAD QBasicAtomicInt font_cache_id = Q_BASIC_ATOMIC_INITIALIZER(1); diff --git a/src/network/configure.json b/src/network/configure.json index 0215ad73c5..32fcfb499f 100644 --- a/src/network/configure.json +++ b/src/network/configure.json @@ -263,6 +263,7 @@ "label": "HTTP", "purpose": "Provides support for the Hypertext Transfer Protocol in QNetworkAccessManager.", "section": "Networking", + "condition": "features.thread", "output": [ "publicFeature", "feature" ] }, "udpsocket": { @@ -301,7 +302,7 @@ "label": "Bearer management", "purpose": "Provides bearer management for the network stack.", "section": "Networking", - "condition": "features.library && features.networkinterface && features.properties", + "condition": "features.thread && features.library && features.networkinterface && features.properties", "output": [ "publicFeature", "feature" ] }, "localserver": { diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp index 8812912c18..63cb276d54 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols.cpp +++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp @@ -903,12 +903,10 @@ bool q_resolveOpenSslSymbols() { static bool symbolsResolved = false; static bool triedToResolveSymbols = false; -#ifndef QT_NO_THREAD #if QT_CONFIG(opensslv11) QMutexLocker locker(QMutexPool::globalInstanceGet((void *)&q_OPENSSL_init_ssl)); #else QMutexLocker locker(QMutexPool::globalInstanceGet((void *)&q_SSL_library_init)); -#endif #endif if (symbolsResolved) return true; diff --git a/src/platformsupport/eventdispatchers/qunixeventdispatcher.cpp b/src/platformsupport/eventdispatchers/qunixeventdispatcher.cpp index 7438ab65c1..44258538ec 100644 --- a/src/platformsupport/eventdispatchers/qunixeventdispatcher.cpp +++ b/src/platformsupport/eventdispatchers/qunixeventdispatcher.cpp @@ -43,14 +43,9 @@ #include "private/qguiapplication_p.h" #include -#include -#include -#include #include -#include - QT_BEGIN_NAMESPACE QT_USE_NAMESPACE diff --git a/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp index dabe2bc09e..7b4f6aa107 100644 --- a/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp +++ b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp @@ -139,14 +139,6 @@ QtFreetypeData::~QtFreetypeData() library = 0; } -#ifdef QT_NO_THREAD -Q_GLOBAL_STATIC(QtFreetypeData, theFreetypeData) - -QtFreetypeData *qt_getFreetypeData() -{ - return theFreetypeData(); -} -#else Q_GLOBAL_STATIC(QThreadStorage, theFreetypeData) QtFreetypeData *qt_getFreetypeData() @@ -169,7 +161,6 @@ QtFreetypeData *qt_getFreetypeData() } return freetypeData; } -#endif FT_Library qt_getFreetype() { diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp index 8df8da1a38..953e2bf6be 100644 --- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp +++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp @@ -1231,7 +1231,6 @@ void QWindowsFontDatabase::populateFontDatabase() typedef QSharedPointer QWindowsFontEngineDataPtr; -#ifndef QT_NO_THREAD typedef QThreadStorage FontEngineThreadLocalData; Q_GLOBAL_STATIC(FontEngineThreadLocalData, fontEngineThreadLocalData) @@ -1243,17 +1242,6 @@ QSharedPointer sharedFontData() data->setLocalData(QSharedPointer::create()); return data->localData(); } -#else // !QT_NO_THREAD -Q_GLOBAL_STATIC(QWindowsFontEngineDataPtr, fontEngineData) - -QWindowsFontEngineDataPtr sharedFontData() -{ - QWindowsFontEngineDataPtr *data = fontEngineData(); - if (data->isNull()) - *data = QWindowsFontEngineDataPtr::create(); - return *data; -} -#endif // QT_NO_THREAD QWindowsFontDatabase::QWindowsFontDatabase() { diff --git a/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h b/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h index 99705927af..731e4b5432 100644 --- a/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h +++ b/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h @@ -61,7 +61,7 @@ class QWindowsThreadPoolRunner { Q_DISABLE_COPY(QWindowsThreadPoolRunner) -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) template // nested class implementing QRunnable to execute a function. class Runnable : public QRunnable { @@ -104,7 +104,7 @@ public: private: QMutex m_mutex; QWaitCondition m_condition; -#else // !QT_NO_THREAD +#else // QT_CONFIG(thread) public: QWindowsThreadPoolRunner() {} @@ -114,7 +114,7 @@ public: f(); return true; } -#endif // QT_NO_THREAD +#endif // QT_CONFIG(thread) }; QT_END_NAMESPACE diff --git a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp index a1636302b7..e2455f87fb 100644 --- a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp +++ b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp @@ -1454,7 +1454,7 @@ bool QMYSQLDriver::open(const QString& db, d->preparedQuerysEnabled = false; #endif -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) mysql_thread_init(); #endif @@ -1468,7 +1468,7 @@ void QMYSQLDriver::close() { Q_D(QMYSQLDriver); if (isOpen()) { -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) mysql_thread_end(); #endif mysql_close(d->mysql); diff --git a/src/printsupport/dialogs/qprintpreviewdialog.cpp b/src/printsupport/dialogs/qprintpreviewdialog.cpp index a4f721fbc8..418bc47a59 100644 --- a/src/printsupport/dialogs/qprintpreviewdialog.cpp +++ b/src/printsupport/dialogs/qprintpreviewdialog.cpp @@ -573,8 +573,11 @@ void QPrintPreviewDialogPrivate::_q_print() if (printer->outputFormat() != QPrinter::NativeFormat) { QString title = QCoreApplication::translate("QPrintPreviewDialog", "Export to PDF"); QString suffix = QLatin1String(".pdf"); - QString fileName = QFileDialog::getSaveFileName(q, title, printer->outputFileName(), + QString fileName; +#if QT_CONFIG(filedialog) + fileName = QFileDialog::getSaveFileName(q, title, printer->outputFileName(), QLatin1Char('*') + suffix); +#endif if (!fileName.isEmpty()) { if (QFileInfo(fileName).suffix().isEmpty()) fileName.append(suffix); diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index d9fbfcffa8..32facaf12b 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -346,7 +346,9 @@ namespace QTest static int keyDelay = -1; static int mouseDelay = -1; static int eventDelay = -1; +#if QT_CONFIG(thread) static int timeout = -1; +#endif static bool noCrashHandler = false; /*! \internal @@ -397,7 +399,7 @@ int Q_TESTLIB_EXPORT defaultKeyDelay() } return keyDelay; } - +#if QT_CONFIG(thread) static int defaultTimeout() { if (timeout == -1) { @@ -409,6 +411,7 @@ static int defaultTimeout() } return timeout; } +#endif Q_TESTLIB_EXPORT bool printAvailableFunctions = false; Q_TESTLIB_EXPORT QStringList testFunctions; @@ -975,6 +978,8 @@ void TestMethods::invokeTestOnData(int index) const } } +#if QT_CONFIG(thread) + class WatchDog : public QThread { public: @@ -1026,6 +1031,17 @@ private: QWaitCondition waitCondition; }; +#else // !QT_CONFIG(thread) + +class WatchDog : public QObject +{ +public: + void beginTest() {}; + void testFinished() {}; +}; + +#endif + /*! \internal diff --git a/src/widgets/configure.json b/src/widgets/configure.json index b3a5227d26..0015c9160a 100644 --- a/src/widgets/configure.json +++ b/src/widgets/configure.json @@ -81,7 +81,7 @@ "label": "QFileSystemModel", "purpose": "Provides a data model for the local filesystem.", "section": "File I/O", - "condition": "features.itemmodel", + "condition": "features.itemmodel && features.thread", "output": [ "publicFeature", "feature" ] }, "itemviews": { diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 0a4efc980c..23d8d32b0d 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -1138,7 +1138,7 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f) q->data = &data; -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) if (!parent) { Q_ASSERT_X(q->thread() == qApp->thread(), "QWidget", "Widgets must be created in the GUI thread."); diff --git a/src/widgets/util/qcompleter.cpp b/src/widgets/util/qcompleter.cpp index 96dde64ccc..c50d0dc9e0 100644 --- a/src/widgets/util/qcompleter.cpp +++ b/src/widgets/util/qcompleter.cpp @@ -144,6 +144,7 @@ #include "qcompleter_p.h" #include "QtWidgets/qscrollbar.h" +#include "QtCore/qdir.h" #include "QtCore/qstringlistmodel.h" #if QT_CONFIG(dirmodel) #include "QtWidgets/qdirmodel.h" diff --git a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp index 5e9dbdd226..a53501b9dd 100644 --- a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp +++ b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp @@ -415,7 +415,7 @@ void tst_QCoreApplication::removePostedEvents() expected.clear(); } -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) class DeliverInDefinedOrderThread : public QThread { Q_OBJECT @@ -532,7 +532,7 @@ void tst_QCoreApplication::deliverInDefinedOrder() QObject::connect(&obj, SIGNAL(done()), &app, SLOT(quit())); app.exec(); } -#endif // QT_NO_QTHREAD +#endif // QT_CONFIG(thread) void tst_QCoreApplication::applicationPid() { diff --git a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.h b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.h index b6c20a915f..105cca5174 100644 --- a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.h +++ b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.h @@ -43,7 +43,7 @@ private slots: void argc(); void postEvent(); void removePostedEvents(); -#ifndef QT_NO_THREAD +#if QT_CONFIG(thread) void deliverInDefinedOrder(); #endif void applicationPid(); diff --git a/tests/auto/corelib/thread/qthreadonce/qthreadonce.cpp b/tests/auto/corelib/thread/qthreadonce/qthreadonce.cpp index 9179750218..d27884197a 100644 --- a/tests/auto/corelib/thread/qthreadonce/qthreadonce.cpp +++ b/tests/auto/corelib/thread/qthreadonce/qthreadonce.cpp @@ -30,7 +30,6 @@ #include "qplatformdefs.h" #include "qthreadonce.h" -#ifndef QT_NO_THREAD #include "qmutex.h" Q_GLOBAL_STATIC_WITH_ARGS(QMutex, onceInitializationMutex, (QMutex::Recursive)) @@ -104,5 +103,3 @@ void QOnceControl::done() { extra &= ~MustRunCode; } - -#endif // QT_NO_THREAD diff --git a/tests/auto/corelib/thread/qthreadonce/qthreadonce.h b/tests/auto/corelib/thread/qthreadonce/qthreadonce.h index 71e830ca16..e5918b8fa5 100644 --- a/tests/auto/corelib/thread/qthreadonce/qthreadonce.h +++ b/tests/auto/corelib/thread/qthreadonce/qthreadonce.h @@ -34,8 +34,6 @@ #include -#ifndef QT_NO_THREAD - class QOnceControl { public: @@ -91,6 +89,4 @@ public: inline operator T*() { return value(); } }; -#endif // QT_NO_THREAD - #endif diff --git a/tests/auto/corelib/thread/thread.pro b/tests/auto/corelib/thread/thread.pro index d3c669859b..dc60e5a7f5 100644 --- a/tests/auto/corelib/thread/thread.pro +++ b/tests/auto/corelib/thread/thread.pro @@ -1,22 +1,25 @@ TEMPLATE=subdirs -SUBDIRS=\ - qatomicint \ - qatomicinteger \ - qatomicpointer \ - qresultstore \ - qfuture \ - qfuturesynchronizer \ - qmutex \ - qmutexlocker \ - qreadlocker \ - qreadwritelock \ - qsemaphore \ - qthread \ - qthreadonce \ - qthreadpool \ - qthreadstorage \ - qwaitcondition \ - qwritelocker + +qtHaveFeature(thread) { + SUBDIRS=\ + qatomicint \ + qatomicinteger \ + qatomicpointer \ + qresultstore \ + qfuture \ + qfuturesynchronizer \ + qmutex \ + qmutexlocker \ + qreadlocker \ + qreadwritelock \ + qsemaphore \ + qthread \ + qthreadonce \ + qthreadpool \ + qthreadstorage \ + qwaitcondition \ + qwritelocker +} qtHaveModule(concurrent) { SUBDIRS += \ -- cgit v1.2.3 From 67352c92761fcb2e2c6a98b24e1bf5f33805cb3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Mon, 2 Jul 2018 22:24:35 +0200 Subject: Merge QThread class definitions We can reuse the main QThread definition for the no-thread configuration and avoid having to keep them in sync. Add stub definitions for member functions where needed. Change-Id: I128db11684a6040d09c4a4ce114f1399cba523f8 Reviewed-by: Lorn Potter --- src/corelib/thread/qthread.cpp | 69 ++++++++++++++++++++++++++++++++++++++++++ src/corelib/thread/qthread.h | 31 ------------------- src/corelib/thread/qthread_p.h | 1 + 3 files changed, 70 insertions(+), 31 deletions(-) diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index a4101764bc..5df0508829 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -765,11 +765,80 @@ QThread::QThread(QObject *parent) d->data->thread = this; } +QThread::~QThread() +{ + +} + +void QThread::run() +{ + +} + +int QThread::exec() +{ + return 0; +} + +void QThread::start(Priority priority) +{ + Q_D(QThread); + Q_UNUSED(priority); + d->running = true; +} + +void QThread::terminate() +{ + +} + +void QThread::quit() +{ + +} + +bool QThread::wait(unsigned long time) +{ + Q_UNUSED(time); + return false; +} + +bool QThread::event(QEvent* event) +{ + return QObject::event(event); +} + +Qt::HANDLE QThread::currentThreadId() Q_DECL_NOTHROW +{ + return Qt::HANDLE(currentThread()); +} + QThread *QThread::currentThread() { return QThreadData::current()->thread; } +int QThread::idealThreadCount() Q_DECL_NOTHROW +{ + return 1; +} + +void QThread::yieldCurrentThread() +{ + +} + +bool QThread::isFinished() const +{ + return false; +} + +bool QThread::isRunning() const +{ + Q_D(const QThread); + return d->running; +} + // No threads: so we can just use static variables static QThreadData *data = 0; diff --git a/src/corelib/thread/qthread.h b/src/corelib/thread/qthread.h index d0ffd9f909..b6c5bf47d0 100644 --- a/src/corelib/thread/qthread.h +++ b/src/corelib/thread/qthread.h @@ -66,7 +66,6 @@ class QThreadData; class QThreadPrivate; class QAbstractEventDispatcher; -#if QT_CONFIG(thread) class Q_CORE_EXPORT QThread : public QObject { Q_OBJECT @@ -239,36 +238,6 @@ QThread *QThread::create(Function &&f) #endif // QT_CONFIG(cxx11_future) -#else // QT_CONFIG(thread) - -class Q_CORE_EXPORT QThread : public QObject -{ -public: - static Qt::HANDLE currentThreadId() { return Qt::HANDLE(currentThread()); } - static QThread* currentThread(); - - static void sleep(unsigned long); - static void msleep(unsigned long); - static void usleep(unsigned long); - - QAbstractEventDispatcher *eventDispatcher() const; - void setEventDispatcher(QAbstractEventDispatcher *eventDispatcher); - -protected: - QThread(QThreadPrivate &dd, QObject *parent = nullptr); - -private: - explicit QThread(QObject *parent = nullptr); - static QThread *instance; - - friend class QCoreApplication; - friend class QThreadData; - friend class QAdoptedThread; - Q_DECLARE_PRIVATE(QThread) -}; - -#endif // QT_CONFIG(thread) - QT_END_NAMESPACE #endif // QTHREAD_H diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h index 22a0669032..64e3f33191 100644 --- a/src/corelib/thread/qthread_p.h +++ b/src/corelib/thread/qthread_p.h @@ -222,6 +222,7 @@ public: mutable QMutex mutex; QThreadData *data; + bool running = false; static void setCurrentThread(QThread*) {} static QThread *threadForId(int) { return QThread::currentThread(); } -- cgit v1.2.3 From d0069ff8c91e0027a0a1f3ef7767dbb13e0eacc4 Mon Sep 17 00:00:00 2001 From: Luca Beldi Date: Wed, 1 Aug 2018 16:43:31 +0100 Subject: Add a method to clear the data to QStandardItemModel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After the behavior of setItemData has been changed following QTBUG-45114, QStandardItemModel was lacking an interface to clear all the data from a single index. Task-number: QTBUG-69616 Change-Id: Ide0b5bb6358439fc42c474df8b044fbace6def8d Reviewed-by: André Hartmann Reviewed-by: David Faure --- src/corelib/itemmodels/qabstractitemmodel.cpp | 17 ++++++++++++ src/corelib/itemmodels/qabstractitemmodel.h | 3 ++ src/gui/itemmodels/qstandarditemmodel.cpp | 32 ++++++++++++++++++++++ src/gui/itemmodels/qstandarditemmodel.h | 3 ++ .../itemmodels/qstandarditem/tst_qstandarditem.cpp | 12 ++++++++ .../qstandarditemmodel/tst_qstandarditemmodel.cpp | 22 +++++++++++++++ 6 files changed, 89 insertions(+) diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp index 3a6f67521f..e816add91d 100644 --- a/src/corelib/itemmodels/qabstractitemmodel.cpp +++ b/src/corelib/itemmodels/qabstractitemmodel.cpp @@ -1866,6 +1866,23 @@ bool QAbstractItemModel::setData(const QModelIndex &index, const QVariant &value return false; } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +/*! + \since 6.0 + Removes the data stored in all the roles for the given \a index. + Returns \c{true} if successful; otherwise returns \c{false}. + The dataChanged() signal should be emitted if the data was successfully + removed. + The base class implementation returns \c{false} + \sa data(), itemData(), setData(), setItemData() +*/ +bool QAbstractItemModel::clearItemData(const QModelIndex &index) +{ + Q_UNUSED(index); + return false; +} +#endif + /*! \fn QVariant QAbstractItemModel::data(const QModelIndex &index, int role) const = 0 diff --git a/src/corelib/itemmodels/qabstractitemmodel.h b/src/corelib/itemmodels/qabstractitemmodel.h index 21171124f9..bec71b0606 100644 --- a/src/corelib/itemmodels/qabstractitemmodel.h +++ b/src/corelib/itemmodels/qabstractitemmodel.h @@ -198,6 +198,9 @@ public: virtual QMap itemData(const QModelIndex &index) const; virtual bool setItemData(const QModelIndex &index, const QMap &roles); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + virtual bool clearItemData(const QModelIndex &index); +#endif virtual QStringList mimeTypes() const; virtual QMimeData *mimeData(const QModelIndexList &indexes) const; diff --git a/src/gui/itemmodels/qstandarditemmodel.cpp b/src/gui/itemmodels/qstandarditemmodel.cpp index 235bc5bd7d..a771bffa2f 100644 --- a/src/gui/itemmodels/qstandarditemmodel.cpp +++ b/src/gui/itemmodels/qstandarditemmodel.cpp @@ -930,6 +930,21 @@ void QStandardItem::setData(const QVariant &value, int role) d->model->d_func()->itemChanged(this, roles); } +/*! + \since 5.12 + Removes all the data from all roles previously set. + \sa data(), setData() +*/ +void QStandardItem::clearData() +{ + Q_D(QStandardItem); + if (d->values.isEmpty()) + return; + d->values.clear(); + if (d->model) + d->model->d_func()->itemChanged(this, QVector{}); +} + /*! Returns the item's data for the given \a role, or an invalid QVariant if there is no data for the role. @@ -2990,6 +3005,23 @@ bool QStandardItemModel::setData(const QModelIndex &index, const QVariant &value return true; } +/*! + \since 5.12 + Removes the data stored in all the roles for the given \a index. + \sa setData(), data() +*/ +bool QStandardItemModel::clearItemData(const QModelIndex &index) +{ + if (!checkIndex(index, CheckIndexOption::IndexIsValid)) + return false; + Q_D(QStandardItemModel); + QStandardItem *item = d->itemFromIndex(index); + if (!item) + return false; + item->clearData(); + return true; +} + /*! \reimp */ diff --git a/src/gui/itemmodels/qstandarditemmodel.h b/src/gui/itemmodels/qstandarditemmodel.h index 827179b31d..a9ee25da75 100644 --- a/src/gui/itemmodels/qstandarditemmodel.h +++ b/src/gui/itemmodels/qstandarditemmodel.h @@ -69,6 +69,7 @@ public: virtual QVariant data(int role = Qt::UserRole + 1) const; virtual void setData(const QVariant &value, int role = Qt::UserRole + 1); + void clearData(); inline QString text() const { return qvariant_cast(data(Qt::DisplayRole)); @@ -343,6 +344,8 @@ public: QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; + // Qt 6: add override keyword + bool clearItemData(const QModelIndex &index); QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; diff --git a/tests/auto/gui/itemmodels/qstandarditem/tst_qstandarditem.cpp b/tests/auto/gui/itemmodels/qstandarditem/tst_qstandarditem.cpp index a45539a041..d19aa9b54f 100644 --- a/tests/auto/gui/itemmodels/qstandarditem/tst_qstandarditem.cpp +++ b/tests/auto/gui/itemmodels/qstandarditem/tst_qstandarditem.cpp @@ -69,8 +69,20 @@ private slots: void sortChildren(); void subclassing(); void lessThan(); + void clearData(); }; +void tst_QStandardItem::clearData() +{ + QStandardItem item; + item.setData(QStringLiteral("Test"), Qt::EditRole); + item.setData(5, Qt::UserRole); + item.clearData(); + QCOMPARE(item.data(Qt::EditRole), QVariant()); + QCOMPARE(item.data(Qt::UserRole), QVariant()); + QCOMPARE(item.data(Qt::DisplayRole), QVariant()); +} + void tst_QStandardItem::ctor() { QStandardItem item; diff --git a/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp b/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp index 9399ebce34..f6ed3e142d 100644 --- a/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp +++ b/tests/auto/gui/itemmodels/qstandarditemmodel/tst_qstandarditemmodel.cpp @@ -98,6 +98,7 @@ private slots: void checkChildren(); void data(); void clear(); + void clearItemData(); void sort_data(); void sort(); void sortRole_data(); @@ -752,6 +753,27 @@ void tst_QStandardItemModel::data() } +void tst_QStandardItemModel::clearItemData() +{ + currentRoles.clear(); + QVERIFY(!m_model->clearItemData(QModelIndex())); + QCOMPARE(currentRoles, {}); + const QModelIndex idx = m_model->index(0, 0); + const QMap oldData = m_model->itemData(idx); + m_model->setData(idx, QLatin1String("initialitem"), Qt::DisplayRole); + m_model->setData(idx, QLatin1String("tooltip"), Qt::ToolTipRole); + m_model->setData(idx, 5, Qt::UserRole); + currentRoles.clear(); + QVERIFY(m_model->clearItemData(idx)); + QCOMPARE(idx.data(Qt::UserRole), QVariant()); + QCOMPARE(idx.data(Qt::ToolTipRole), QVariant()); + QCOMPARE(idx.data(Qt::DisplayRole), QVariant()); + QCOMPARE(idx.data(Qt::EditRole), QVariant()); + QCOMPARE(currentRoles, {}); + m_model->setItemData(idx, oldData); + currentRoles.clear(); +} + void tst_QStandardItemModel::clear() { QStandardItemModel model; -- cgit v1.2.3 From b9a0276a79856ff4eb329b8c79925bfc41925c1c Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Wed, 8 Aug 2018 11:53:50 +0200 Subject: qdoc: Fix remaining qdoc warnings for QCborxxx classes Several \fn commands are added for functions and operators that were not documented. A few qdoc warnings remain in qcborstream.cpp, but these are because an enum class was used, and qdoc doesn't yet handle those correctly all the time. Change-Id: I02a740c595e36c1b383af242c2a6419d1f37b135 Reviewed-by: Thiago Macieira --- src/corelib/serialization/qcborarray.cpp | 9 ++- src/corelib/serialization/qcbordiagnostic.cpp | 2 +- src/corelib/serialization/qcbormap.cpp | 100 ++++++++++++++++++++++++++ src/corelib/serialization/qcborstream.cpp | 4 +- src/corelib/serialization/qcborvalue.cpp | 12 +++- 5 files changed, 121 insertions(+), 6 deletions(-) diff --git a/src/corelib/serialization/qcborarray.cpp b/src/corelib/serialization/qcborarray.cpp index 28ee941a15..506fb052be 100644 --- a/src/corelib/serialization/qcborarray.cpp +++ b/src/corelib/serialization/qcborarray.cpp @@ -327,8 +327,8 @@ void QCborArray::insert(qsizetype i, QCborValue &&value) } /*! - \fn QCborValue QCborArray::extract(iterator it) - \fn QCborValue QCborArray::extract(const_iterator it) + \fn QCborValue QCborArray::extract(Iterator it) + \fn QCborValue QCborArray::extract(ConstIterator it) Extracts a value from the array at the position indicated by iterator \a it and returns the value so extracted. @@ -1048,6 +1048,7 @@ void QCborArray::detach(qsizetype reserved) */ /*! + \fn bool QCborArray::ConstIterator::operator==(const Iterator &other) const \fn bool QCborArray::ConstIterator::operator==(const ConstIterator &other) const Returns \c true if \a other points to the same entry in the array as this @@ -1067,6 +1068,7 @@ void QCborArray::detach(qsizetype reserved) */ /*! + \fn bool QCborArray::ConstIterator::operator<(const Iterator &other) const \fn bool QCborArray::ConstIterator::operator<(const ConstIterator &other) const Returns \c true if the entry in the array pointed to by this iterator @@ -1074,6 +1076,7 @@ void QCborArray::detach(qsizetype reserved) */ /*! + \fn bool QCborArray::ConstIterator::operator<=(const Iterator &other) const \fn bool QCborArray::ConstIterator::operator<=(const ConstIterator &other) const Returns \c true if the entry in the array pointed to by this iterator @@ -1082,6 +1085,7 @@ void QCborArray::detach(qsizetype reserved) */ /*! + \fn bool QCborArray::ConstIterator::operator>(const Iterator &other) const \fn bool QCborArray::ConstIterator::operator>(const ConstIterator &other) const Returns \c true if the entry in the array pointed to by this iterator @@ -1089,6 +1093,7 @@ void QCborArray::detach(qsizetype reserved) */ /*! + \fn bool QCborArray::ConstIterator::operator>=(const Iterator &other) const \fn bool QCborArray::ConstIterator::operator>=(const ConstIterator &other) const Returns \c true if the entry in the array pointed to by this iterator diff --git a/src/corelib/serialization/qcbordiagnostic.cpp b/src/corelib/serialization/qcbordiagnostic.cpp index 78f99927c8..75feaded17 100644 --- a/src/corelib/serialization/qcbordiagnostic.cpp +++ b/src/corelib/serialization/qcbordiagnostic.cpp @@ -337,7 +337,7 @@ void DiagnosticNotation::appendValue(const QCborValue &v) high-fidelity notation of a stream, without transformation, see the \c cbordump example. - \sa toCbor(), toJsonDocument(), QJsonDocument::toJson() + \sa toCbor(), QJsonDocument::toJson() */ QString QCborValue::toDiagnosticNotation(DiagnosticNotationOptions opts) const { diff --git a/src/corelib/serialization/qcbormap.cpp b/src/corelib/serialization/qcbormap.cpp index b7067f4afd..f9b000393c 100644 --- a/src/corelib/serialization/qcbormap.cpp +++ b/src/corelib/serialization/qcbormap.cpp @@ -804,6 +804,9 @@ QCborValueRef QCborMap::operator[](const QCborValue &key) } /*! + \fn QCborMap::iterator QCborMap::find(qint64 key) + \fn QCborMap::const_iterator QCborMap::find(qint64 key) const + Returns a map iterator to the key-value pair whose key is \a key, if the map contains such a pair. If it doesn't, this function returns end(). @@ -828,6 +831,8 @@ QCborMap::iterator QCborMap::find(qint64 key) } /*! + \fn QCborMap::iterator QCborMap::find(QLatin1String key) + \fn QCborMap::const_iterator QCborMap::find(QLatin1String key) const \overload Returns a map iterator to the key-value pair whose key is \a key, if the @@ -852,6 +857,8 @@ QCborMap::iterator QCborMap::find(QLatin1String key) } /*! + \fn QCborMap::iterator QCborMap::find(const QString & key) + \fn QCborMap::const_iterator QCborMap::find(const QString & key) const \overload Returns a map iterator to the key-value pair whose key is \a key, if the @@ -876,6 +883,8 @@ QCborMap::iterator QCborMap::find(const QString & key) } /*! + \fn QCborMap::iterator QCborMap::find(const QCborValue &key) + \fn QCborMap::const_iterator QCborMap::find(const QCborValue &key) const \overload Returns a map iterator to the key-value pair whose key is \a key, if the @@ -1100,6 +1109,9 @@ QCborMap::iterator QCborMap::erase(QCborMap::iterator it) } /*! + \fn QCborValue QCborMap::extract(iterator it) + \fn QCborValue QCborMap::extract(const_iterator it) + Extracts a value from the map at the position indicated by iterator \a it and returns the value so extracted. @@ -1359,6 +1371,40 @@ void QCborMap::detach(qsizetype reserved) \sa operator==() */ +/*! + \fn bool QCborMap::Iterator::operator<(const Iterator& other) const + \fn bool QCborMap::Iterator::operator<(const ConstIterator& other) const + + Returns \c true if the entry in the map pointed to by this iterator + occurs before the entry pointed to by the \a other iterator. +*/ + +/*! + \fn bool QCborMap::Iterator::operator<=(const Iterator& other) const + \fn bool QCborMap::Iterator::operator<=(const ConstIterator& other) const + + Returns \c true if the entry in the map pointed to by this iterator + occurs before or is the same entry as is pointed to by the \a other + iterator. +*/ + +/*! + \fn bool QCborMap::Iterator::operator>(const Iterator& other) const + \fn bool QCborMap::Iterator::operator>(const ConstIterator& other) const + + Returns \c true if the entry in the map pointed to by this iterator + occurs after the entry pointed to by the \a other iterator. + */ + +/*! + \fn bool QCborMap::Iterator::operator>=(const Iterator& other) const + \fn bool QCborMap::Iterator::operator>=(const ConstIterator& other) const + + Returns \c true if the entry in the map pointed to by this iterator + occurs after or is the same entry as is pointed to by the \a other + iterator. +*/ + /*! \fn QCborMap::Iterator &QCborMap::Iterator::operator++() @@ -1415,6 +1461,16 @@ void QCborMap::detach(qsizetype reserved) \sa operator+() */ +/*! + \fn qsizetype QCborMap::Iterator::operator-(QCborMap::Iterator j) const + + Returns the position of the item at iterator \a j relative to the item + at this iterator. If the item at \a j is forward of this time, the returned + value is negative. + + \sa operator+() +*/ + /*! \fn QCborMap::Iterator &QCborMap::Iterator::operator+=(qsizetype j) @@ -1560,6 +1616,40 @@ void QCborMap::detach(qsizetype reserved) \sa operator==() */ +/*! + \fn bool QCborMap::ConstIterator::operator<(const Iterator &other) const + \fn bool QCborMap::ConstIterator::operator<(const ConstIterator &other) const + + Returns \c true if the entry in the map pointed to by this iterator + occurs before the entry pointed to by the \a other iterator. +*/ + +/*! + \fn bool QCborMap::ConstIterator::operator<=(const Iterator &other) const + \fn bool QCborMap::ConstIterator::operator<=(const ConstIterator &other) const + + Returns \c true if the entry in the map pointed to by this iterator + occurs before or is the same entry as is pointed to by the \a other + iterator. +*/ + +/*! + \fn bool QCborMap::ConstIterator::operator>(const Iterator &other) const + \fn bool QCborMap::ConstIterator::operator>(const ConstIterator &other) const + + Returns \c true if the entry in the map pointed to by this iterator + occurs after the entry pointed to by the \a other iterator. +*/ + +/*! + \fn bool QCborMap::ConstIterator::operator>=(const Iterator &other) const + \fn bool QCborMap::ConstIterator::operator>=(const ConstIterator &other) const + + Returns \c true if the entry in the map pointed to by this iterator + occurs after or is the same entry as is pointed to by the \a other + iterator. +*/ + /*! \fn QCborMap::ConstIterator &QCborMap::ConstIterator::operator++() @@ -1616,6 +1706,16 @@ void QCborMap::detach(qsizetype reserved) \sa operator+() */ +/*! + \fn qsizetype QCborMap::ConstIterator::operator-(QCborMap::ConstIterator j) const + + Returns the position of the item at iterator \a j relative to the item + at this iterator. If the item at \a j is forward of this time, the returned + value is negative. + + \sa operator+() +*/ + /*! \fn QCborMap::ConstIterator &QCborMap::ConstIterator::operator+=(qsizetype j) diff --git a/src/corelib/serialization/qcborstream.cpp b/src/corelib/serialization/qcborstream.cpp index ce1b981f8f..aed286a11f 100644 --- a/src/corelib/serialization/qcborstream.cpp +++ b/src/corelib/serialization/qcborstream.cpp @@ -1044,7 +1044,7 @@ void QCborStreamWriter::append(QCborSimpleType st) Appends the floating point number \a f to the stream, creating a CBOR 16-bit Half-Precision Floating Point value. The following code can be used to convert - a C++ \tt float to \l qfloat16 if there's no loss of precision and append it, or + a C++ \tt float to \c qfloat16 if there's no loss of precision and append it, or instead append the \tt float. \code @@ -1144,7 +1144,7 @@ void QCborStreamWriter::append(double d) QCborStreamReader::readByteArray() nor QCborValue support reading CBOR streams with byte arrays larger than 2 GB. - \sa append(QByteArray), appendTextString(), + \sa append(), appendTextString(), QCborStreamReader::isByteArray(), QCborStreamReader::readByteArray() */ void QCborStreamWriter::appendByteString(const char *data, qsizetype len) diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp index 4108418550..c1d78ef738 100644 --- a/src/corelib/serialization/qcborvalue.cpp +++ b/src/corelib/serialization/qcborvalue.cpp @@ -2196,6 +2196,16 @@ QCborValue QCborValue::fromCbor(const QByteArray &ba, QCborParserError *error) return result; } +/*! + \fn QCborValue QCborValue::fromCbor(const char *data, qsizetype len, QCborParserError *error) + \fn QCborValue QCborValue::fromCbor(const quint8 *data, qsizetype len, QCborParserError *error) + \overload + + Converts \a len bytes of \a data to a QByteArray and then calls the + overload of this function that accepts a QByteArray, also passing \a error, + if provided. +*/ + /*! Encodes this QCborValue object to its CBOR representation, using the options specified in \a opt, and return the byte array containing that @@ -2213,7 +2223,7 @@ QCborValue QCborValue::fromCbor(const QByteArray &ba, QCborParserError *error) infinities and NaN values. Similarly, if \l{EncodingOption}{UseFloat16} is specified, this function - will try to use half-precision (\l qfloat16) floating point if the + will try to use half-precision (\c qfloat16) floating point if the conversion to that results in no loss of precision. This is always true for infinities and NaN. -- cgit v1.2.3 From 0e63111416e3407c4fa3eac33ae69028216cf1b7 Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Fri, 3 Aug 2018 15:00:39 +0200 Subject: xcb: avoid unnecessary InternAtom requests QXcbConnection::internAtom() creates the atom if it does not exist. The lifetime of an atom is not tied to the interning client. Atoms remain defined until server reset (lost connection, restart). So create the atom once via QXcbConnection::initializeAllAtoms(), and later fetch the atom value from local array, instead of repeating InternAtom requests. Change-Id: I3cae21895febad6e5daf8c32e72612202baaad64 Reviewed-by: Gatis Paeglis --- src/plugins/platforms/xcb/qxcbclipboard.cpp | 2 +- src/plugins/platforms/xcb/qxcbconnection.cpp | 4 ++++ src/plugins/platforms/xcb/qxcbconnection.h | 6 ++++++ src/plugins/platforms/xcb/qxcbnativeinterface.cpp | 2 +- src/plugins/platforms/xcb/qxcbscreen.cpp | 16 ++++++---------- 5 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp index ca2eff170d..84831cdbe5 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.cpp +++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp @@ -832,7 +832,7 @@ xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t window, i } // process other clipboard events, since someone is probably requesting data from us - auto clipboardAtom = connection()->internAtom("CLIPBOARD"); + auto clipboardAtom = atom(QXcbAtom::CLIPBOARD); e = connection()->checkEvent([clipboardAtom](xcb_generic_event_t *event, int type) { xcb_atom_t selection = XCB_ATOM_NONE; if (type == XCB_SELECTION_REQUEST) diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 75275f6fd2..84551fd74b 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -1964,6 +1964,10 @@ static const char * xcb_atomnames = { "_COMPIZ_DECOR_DELETE_PIXMAP\0" "_COMPIZ_TOOLKIT_ACTION\0" "_GTK_LOAD_ICONTHEMES\0" + "AT_SPI_BUS\0" + "EDID\0" + "EDID_DATA\0" + "XFree86_DDC_EDID1_RAWDATA\0" // \0\0 terminates loop. }; diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 342efca55e..596174d234 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -295,6 +295,12 @@ namespace QXcbAtom { _COMPIZ_TOOLKIT_ACTION, _GTK_LOAD_ICONTHEMES, + AT_SPI_BUS, + + EDID, + EDID_DATA, + XFree86_DDC_EDID1_RAWDATA, + NAtoms }; } diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp index 3d2197796f..98bedea48a 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp @@ -408,7 +408,7 @@ void *QXcbNativeInterface::atspiBus() QXcbIntegration *integration = static_cast(QGuiApplicationPrivate::platformIntegration()); QXcbConnection *defaultConnection = integration->defaultConnection(); if (defaultConnection) { - xcb_atom_t atspiBusAtom = defaultConnection->internAtom("AT_SPI_BUS"); + auto atspiBusAtom = defaultConnection->atom(QXcbAtom::AT_SPI_BUS); auto reply = Q_XCB_REPLY(xcb_get_property, defaultConnection->xcb_connection(), false, defaultConnection->rootWindow(), atspiBusAtom, XCB_ATOM_STRING, 0, 128); diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index b398768bbc..8c0ce8dd7e 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -906,16 +906,12 @@ QByteArray QXcbScreen::getEdid() const return result; // Try a bunch of atoms - xcb_atom_t atom = connection()->internAtom("EDID"); - result = getOutputProperty(atom); - if (result.isEmpty()) { - atom = connection()->internAtom("EDID_DATA"); - result = getOutputProperty(atom); - } - if (result.isEmpty()) { - atom = connection()->internAtom("XFree86_DDC_EDID1_RAWDATA"); - result = getOutputProperty(atom); - } + result = getOutputProperty(atom(QXcbAtom::EDID)); + if (result.isEmpty()) + result = getOutputProperty(atom(QXcbAtom::EDID_DATA)); + if (result.isEmpty()) + result = getOutputProperty(atom(QXcbAtom::XFree86_DDC_EDID1_RAWDATA)); + return result; } -- cgit v1.2.3 From 52d4a2976fd7edaf68d697bb1f5cb379cb1739cc Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Mon, 13 Aug 2018 15:38:30 +0200 Subject: xcb: replace tiny helper function with an inline code Having these 2 lines in a function does not add much value and requires scrolling that could be avoided. Change-Id: Ife814be6478521cd64b0048d1b6ee447afea55de Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbwindow.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 2c333cb22b..52c87ee8a4 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -732,13 +732,6 @@ void QXcbWindow::setVisible(bool visible) hide(); } -static inline bool testShowWithoutActivating(const QWindow *window) -{ - // QWidget-attribute Qt::WA_ShowWithoutActivating. - const QVariant showWithoutActivating = window->property("_q_showWithoutActivating"); - return showWithoutActivating.isValid() && showWithoutActivating.toBool(); -} - void QXcbWindow::show() { if (window()->isTopLevel()) { @@ -786,7 +779,9 @@ void QXcbWindow::show() updateNetWmStateBeforeMap(); } - if (testShowWithoutActivating(window())) + // QWidget-attribute Qt::WA_ShowWithoutActivating. + const auto showWithoutActivating = window()->property("_q_showWithoutActivating"); + if (showWithoutActivating.isValid() && showWithoutActivating.toBool()) updateNetWmUserTime(0); else if (connection()->time() != XCB_TIME_CURRENT_TIME) updateNetWmUserTime(connection()->time()); -- cgit v1.2.3 From 23d73ae46d0bf7cbd75f8ce0e1b75814f8665cb9 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 13 Jul 2018 17:57:18 +0200 Subject: Eliminate QLocale's system_data in favor of globalLocaleData This is simpler than initializing a pointer to its address and accessing it via that pointer; it saves the initialization and a few checks that it's happened. Change-Id: I3d82ee1cb02981654ec769632d3a055e11737113 Reviewed-by: Thiago Macieira --- src/corelib/tools/qlocale.cpp | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index 24fd597e52..b285e58779 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -83,7 +83,6 @@ public: }; Q_GLOBAL_STATIC(QSystemLocaleSingleton, QSystemLocale_globalSystemLocale) -static QLocaleData *system_data = 0; static QLocaleData globalLocaleData; #endif @@ -629,8 +628,7 @@ QSystemLocale::QSystemLocale() { _systemLocale = this; - if (system_data) - system_data->m_language_id = 0; + globalLocaleData.m_language_id = 0; } /*! @@ -647,8 +645,7 @@ QSystemLocale::~QSystemLocale() if (_systemLocale == this) { _systemLocale = 0; - if (system_data) - system_data->m_language_id = 0; + globalLocaleData.m_language_id = 0; } } @@ -663,47 +660,45 @@ void QLocalePrivate::updateSystemPrivate() { // this function is NOT thread-safe! const QSystemLocale *sys_locale = systemLocale(); - if (!system_data) - system_data = &globalLocaleData; // tell the object that the system locale has changed. sys_locale->query(QSystemLocale::LocaleChanged, QVariant()); - *system_data = *sys_locale->fallbackUiLocale().d->m_data; + globalLocaleData = *sys_locale->fallbackUiLocale().d->m_data; QVariant res = sys_locale->query(QSystemLocale::LanguageId, QVariant()); if (!res.isNull()) { - system_data->m_language_id = res.toInt(); - system_data->m_script_id = QLocale::AnyScript; // default for compatibility + globalLocaleData.m_language_id = res.toInt(); + globalLocaleData.m_script_id = QLocale::AnyScript; // default for compatibility } res = sys_locale->query(QSystemLocale::CountryId, QVariant()); if (!res.isNull()) { - system_data->m_country_id = res.toInt(); - system_data->m_script_id = QLocale::AnyScript; // default for compatibility + globalLocaleData.m_country_id = res.toInt(); + globalLocaleData.m_script_id = QLocale::AnyScript; // default for compatibility } res = sys_locale->query(QSystemLocale::ScriptId, QVariant()); if (!res.isNull()) - system_data->m_script_id = res.toInt(); + globalLocaleData.m_script_id = res.toInt(); res = sys_locale->query(QSystemLocale::DecimalPoint, QVariant()); if (!res.isNull()) - system_data->m_decimal = res.toString().at(0).unicode(); + globalLocaleData.m_decimal = res.toString().at(0).unicode(); res = sys_locale->query(QSystemLocale::GroupSeparator, QVariant()); if (!res.isNull()) - system_data->m_group = res.toString().at(0).unicode(); + globalLocaleData.m_group = res.toString().at(0).unicode(); res = sys_locale->query(QSystemLocale::ZeroDigit, QVariant()); if (!res.isNull()) - system_data->m_zero = res.toString().at(0).unicode(); + globalLocaleData.m_zero = res.toString().at(0).unicode(); res = sys_locale->query(QSystemLocale::NegativeSign, QVariant()); if (!res.isNull()) - system_data->m_minus = res.toString().at(0).unicode(); + globalLocaleData.m_minus = res.toString().at(0).unicode(); res = sys_locale->query(QSystemLocale::PositiveSign, QVariant()); if (!res.isNull()) - system_data->m_plus = res.toString().at(0).unicode(); + globalLocaleData.m_plus = res.toString().at(0).unicode(); } #endif // !QT_NO_SYSTEMLOCALE @@ -719,12 +714,12 @@ static const QLocaleData *systemData() { static QBasicMutex systemDataMutex; systemDataMutex.lock(); - if (!system_data || system_data->m_language_id == 0) + if (globalLocaleData.m_language_id == 0) QLocalePrivate::updateSystemPrivate(); systemDataMutex.unlock(); } - return system_data; + return &globalLocaleData; #else return locale_data; #endif -- cgit v1.2.3 From d7fbc9ea883313ad19ff12318e8efb5deab6d439 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 10 Jul 2018 14:10:26 +0200 Subject: Add displayName getters to QSslCertificate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Provides two convenient getter for a display name of the subject and issuer. This simplifies cases where you just want a simple string describing either of the two. Change-Id: Ia5d0e058f14dae067b13ac7360e7fec4edd9ec53 Reviewed-by: Mårten Nordheim Reviewed-by: Timur Pocheptsov --- src/network/ssl/qsslcertificate.cpp | 54 +++++++++++++++++++++++++++++++++++-- src/network/ssl/qsslcertificate.h | 3 +++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp index 6cb07c46e1..31ff296480 100644 --- a/src/network/ssl/qsslcertificate.cpp +++ b/src/network/ssl/qsslcertificate.cpp @@ -691,6 +691,56 @@ QByteArray QSslCertificatePrivate::subjectInfoToString(QSslCertificate::SubjectI return str; } +/*! + \since 5.12 + + Returns a name that describes the issuer. It returns the QSslCertificate::CommonName + if available, otherwise falls back to the first QSslCertificate::Organization or the + first QSslCertificate::OrganizationalUnitName. + + \sa issuerInfo() +*/ +QString QSslCertificate::issuerDisplayName() const +{ + QStringList names; + names = issuerInfo(QSslCertificate::CommonName); + if (!names.isEmpty()) + return names.first(); + names = issuerInfo(QSslCertificate::Organization); + if (!names.isEmpty()) + return names.first(); + names = issuerInfo(QSslCertificate::OrganizationalUnitName); + if (!names.isEmpty()) + return names.first(); + + return QString(); +} + +/*! + \since 5.12 + + Returns a name that describes the subject. It returns the QSslCertificate::CommonName + if available, otherwise falls back to the first QSslCertificate::Organization or the + first QSslCertificate::OrganizationalUnitName. + + \sa subjectInfo() +*/ +QString QSslCertificate::subjectDisplayName() const +{ + QStringList names; + names = subjectInfo(QSslCertificate::CommonName); + if (!names.isEmpty()) + return names.first(); + names = subjectInfo(QSslCertificate::Organization); + if (!names.isEmpty()) + return names.first(); + names = subjectInfo(QSslCertificate::OrganizationalUnitName); + if (!names.isEmpty()) + return names.first(); + + return QString(); +} + /*! \fn uint qHash(const QSslCertificate &key, uint seed) @@ -708,8 +758,8 @@ QDebug operator<<(QDebug debug, const QSslCertificate &certificate) << certificate.version() << ", " << certificate.serialNumber() << ", " << certificate.digest().toBase64() - << ", " << certificate.issuerInfo(QSslCertificate::Organization) - << ", " << certificate.subjectInfo(QSslCertificate::Organization) + << ", " << certificate.issuerDisplayName() + << ", " << certificate.subjectDisplayName() << ", " << certificate.subjectAlternativeNames() #ifndef QT_NO_DATESTRING << ", " << certificate.effectiveDate() diff --git a/src/network/ssl/qsslcertificate.h b/src/network/ssl/qsslcertificate.h index 553fb8884d..266fcdacb4 100644 --- a/src/network/ssl/qsslcertificate.h +++ b/src/network/ssl/qsslcertificate.h @@ -120,6 +120,9 @@ public: QStringList issuerInfo(const QByteArray &attribute) const; QStringList subjectInfo(SubjectInfo info) const; QStringList subjectInfo(const QByteArray &attribute) const; + QString issuerDisplayName() const; + QString subjectDisplayName() const; + QList subjectInfoAttributes() const; QList issuerInfoAttributes() const; #if QT_DEPRECATED_SINCE(5,0) -- cgit v1.2.3 From d26289ffb43a5fcf34e855db1dfbf42aa03c4f5a Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Tue, 7 Aug 2018 12:29:21 +0200 Subject: Add ++/--/min/max to QSpecialInteger Add both prefix and postfix versions of the increment/decrement operators, and a static constexpr min/max which returns the minimum/maximumm values that can be stored in the QSpecialInteger. These latter functions are useful to define constants, e.g.: typedef quint8_be IPv4_TTL; static constexpr TTL_TO_DROP = IPv4_TTL::min(); Change-Id: I825a279feb68b93572765a9fdb5aa7b06d1be35b Reviewed-by: Thiago Macieira --- src/corelib/global/qendian.cpp | 80 ++++++++++++++++++++++++++++++++++++++++++ src/corelib/global/qendian.h | 40 +++++++++++++++++++++ 2 files changed, 120 insertions(+) diff --git a/src/corelib/global/qendian.cpp b/src/corelib/global/qendian.cpp index 5bc5507dd5..7fd6e13d3b 100644 --- a/src/corelib/global/qendian.cpp +++ b/src/corelib/global/qendian.cpp @@ -432,6 +432,46 @@ QT_BEGIN_NAMESPACE this object. */ +/*! + \fn template QLEInteger &QLEInteger::operator++() + + Performs a prefix ++ (increment) on this QLEInteger and returns a reference to + this object. +*/ + +/*! + \fn template QLEInteger QLEInteger::operator++(int) + + Performs a postfix ++ (increment) on this QLEInteger and returns a reference to + this object. +*/ + +/*! + \fn template QLEInteger &QLEInteger::operator--() + + Performs a prefix -- (decrement) on this QLEInteger and returns a reference to + this object. +*/ + +/*! + \fn template QLEInteger QLEInteger::operator--(int) + + Performs a postfix -- (decrement) on this QLEInteger and returns a reference to + this object. +*/ + +/*! + \fn template QLEInteger QLEInteger::max() + + Returns the maximum (finite) value representable by the numeric type T. +*/ + +/*! + \fn template QLEInteger QLEInteger::min() + + Returns the minimum (finite) value representable by the numeric type T. +*/ + /*! \class QBEInteger \inmodule QtCore @@ -551,6 +591,46 @@ QT_BEGIN_NAMESPACE this object. */ +/*! + \fn template QBEInteger &QBEInteger::operator++() + + Performs a prefix ++ (increment) on this QBEInteger and returns a reference to + this object. +*/ + +/*! + \fn template QBEInteger QBEInteger::operator++(int) + + Performs a postfix ++ (increment) on this QBEInteger and returns a reference to + this object. +*/ + +/*! + \fn template QBEInteger &QBEInteger::operator--() + + Performs a prefix -- (decrement) on this QBEInteger and returns a reference to + this object. +*/ + +/*! + \fn template QBEInteger QBEInteger::operator--(int) + + Performs a postfix -- (decrement) on this QBEInteger and returns a reference to + this object. +*/ + +/*! + \fn template QBEInteger QBEInteger::max() + + Returns the maximum (finite) value representable by the numeric type T. +*/ + +/*! + \fn template QBEInteger QBEInteger::min() + + Returns the minimum (finite) value representable by the numeric type T. +*/ + /*! \typedef quint16_le \relates diff --git a/src/corelib/global/qendian.h b/src/corelib/global/qendian.h index 135bc4460b..1cc8a823d9 100644 --- a/src/corelib/global/qendian.h +++ b/src/corelib/global/qendian.h @@ -47,6 +47,11 @@ #include #include +#ifdef min // MSVC +#undef min +#undef max +#endif + QT_BEGIN_NAMESPACE /* @@ -279,6 +284,27 @@ public: { return (*this = S::fromSpecial(val) & i); } QSpecialInteger &operator ^=(T i) { return (*this = S::fromSpecial(val) ^ i); } + QSpecialInteger &operator ++() + { return (*this = S::fromSpecial(val) + 1); } + QSpecialInteger &operator --() + { return (*this = S::fromSpecial(val) - 1); } + QSpecialInteger operator ++(int) + { + QSpecialInteger pre = *this; + *this += 1; + return pre; + } + QSpecialInteger operator --(int) + { + QSpecialInteger pre = *this; + *this -= 1; + return pre; + } + + static constexpr QSpecialInteger max() + { return QSpecialInteger(std::numeric_limits::max()); } + static constexpr QSpecialInteger min() + { return QSpecialInteger(std::numeric_limits::min()); } }; template @@ -316,6 +342,13 @@ public: QLEInteger &operator |=(T i); QLEInteger &operator &=(T i); QLEInteger &operator ^=(T i); + QLEInteger &operator ++(); + QLEInteger &operator --(); + QLEInteger &operator ++(int); + QLEInteger &operator --(int); + + static constexpr QLEInteger max(); + static constexpr QLEInteger min(); }; template @@ -336,6 +369,13 @@ public: QBEInteger &operator |=(T i); QBEInteger &operator &=(T i); QBEInteger &operator ^=(T i); + QBEInteger &operator ++(); + QBEInteger &operator --(); + QBEInteger &operator ++(int); + QBEInteger &operator --(int); + + static constexpr QBEInteger max(); + static constexpr QBEInteger min(); }; #else -- cgit v1.2.3 From df91fd119828b75cb5c411e3e8b9e9af64c864e1 Mon Sep 17 00:00:00 2001 From: Andre de la Rocha Date: Thu, 16 Aug 2018 16:45:26 +0200 Subject: WinRT QPA: Fix mapping of static text accessibility role QAccessible::StaticText should be mapped to AutomationControlType_Text instead of AutomationControlType_Edit. Change-Id: If8c840f0dea553c1a750225586778a7d24cf424a Reviewed-by: Oliver Wolff --- src/plugins/platforms/winrt/uiautomation/qwinrtuiautils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/winrt/uiautomation/qwinrtuiautils.cpp b/src/plugins/platforms/winrt/uiautomation/qwinrtuiautils.cpp index 98483216c0..16197c99b9 100644 --- a/src/plugins/platforms/winrt/uiautomation/qwinrtuiautils.cpp +++ b/src/plugins/platforms/winrt/uiautomation/qwinrtuiautils.cpp @@ -126,7 +126,7 @@ AutomationControlType roleToControlType(QAccessible::Role role) {QAccessible::PropertyPage, AutomationControlType::AutomationControlType_Custom}, {QAccessible::Indicator, AutomationControlType::AutomationControlType_Custom}, {QAccessible::Graphic, AutomationControlType::AutomationControlType_Image}, - {QAccessible::StaticText, AutomationControlType::AutomationControlType_Edit}, + {QAccessible::StaticText, AutomationControlType::AutomationControlType_Text}, {QAccessible::EditableText, AutomationControlType::AutomationControlType_Edit}, {QAccessible::Button, AutomationControlType::AutomationControlType_Button}, {QAccessible::CheckBox, AutomationControlType::AutomationControlType_CheckBox}, -- cgit v1.2.3 From a4a730f4cbe63ef14edce6be0dfb50a34eb08255 Mon Sep 17 00:00:00 2001 From: Ales Erjavec Date: Wed, 18 Apr 2018 13:05:25 +0200 Subject: QComboBox: Start blockMouseReleaseTimer after showPopup call The layout/size hinting done in showPopup should not count towards the mouse release blocking timeout as it might take more then the double click interval itself, causing the popup to hide immediately on button release. Task-number: QTBUG-67583 Change-Id: I37ac77ac331a4f865a9242581232b85606f883c5 Reviewed-by: Richard Moe Gustavsen --- src/widgets/widgets/qcombobox.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index 04a44e1f37..e20a0892b4 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -3160,7 +3160,6 @@ void QComboBoxPrivate::showPopupFromMouseEvent(QMouseEvent *e) #endif // We've restricted the next couple of lines, because by not calling // viewContainer(), we avoid creating the QComboBoxPrivateContainer. - viewContainer()->blockMouseReleaseTimer.start(QApplication::doubleClickInterval()); viewContainer()->initialClickPosition = q->mapToGlobal(e->pos()); #ifdef QT_KEYPAD_NAVIGATION } @@ -3169,8 +3168,10 @@ void QComboBoxPrivate::showPopupFromMouseEvent(QMouseEvent *e) // The code below ensures that regular mousepress and pick item still works // If it was not called the viewContainer would ignore event since it didn't have // a mousePressEvent first. - if (viewContainer()) + if (viewContainer()) { + viewContainer()->blockMouseReleaseTimer.start(QApplication::doubleClickInterval()); viewContainer()->maybeIgnoreMouseButtonRelease = false; + } } else { #ifdef QT_KEYPAD_NAVIGATION if (QApplication::keypadNavigationEnabled() && sc == QStyle::SC_ComboBoxEditField && lineEdit) { -- cgit v1.2.3 From e09f5b17865a09dac41d0f30ef2ea238f38873eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 17 Aug 2018 13:30:38 +0200 Subject: macOS: Teach QWheelEvent to handle a new ScrollMomentum phase We detect if there's an upcoming momentum phase using the same trick used by e.g. Mozilla in their event handling: https://tinyurl.com/yd8lcs4l, and as recommended by an Apple engineer: https://tinyurl.com/y8yytlgv The event is not guaranteed to be in the queue, but in practice it seems to be. If this assumption fails we can add a wait timeout to the event search instead of using [NSDate distantPast] as a timeout (which only looks at queued events). When the momentum phase is detected, QWheelEvent::phase will have the new ScrollMomentum value, and the phase transitions will be ScrollBegin -> ScrollUpdate -> ScrollMomentum -> ScrollEnd. We no longer send ScrollEnd to signify that the user's fingers have been lifted off the trackpad; rather, the first event with ScrollMomentum phase means that the fingers have been lifted and macOS is now sending simulated-momentum events. This means ScrollEnd is a reliable indicator that the entire scroll gesture (both the user interaction and the momentum) has ended. If the ScrollMomentum phase is skipped, it means the user's fingers came to rest before being lifted, so there is no momentum. In that case the transitions will be ScrollBegin -> ScrollUpdate -> ScrollEnd. Task-number: QTBUG-63026 Task-number: QTBUG-65160 Change-Id: I80191a472f6fa892387004c199166a6350124274 Reviewed-by: Shawn Rutledge --- src/corelib/global/qnamespace.h | 3 +- src/gui/kernel/qevent.cpp | 10 ++--- src/gui/kernel/qevent.h | 5 ++- src/plugins/platforms/cocoa/qnsview_mouse.mm | 64 ++++++++++++++++++---------- 4 files changed, 51 insertions(+), 31 deletions(-) diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index 288c966eec..dec2c44637 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -1704,7 +1704,8 @@ public: NoScrollPhase = 0, ScrollBegin, ScrollUpdate, - ScrollEnd + ScrollEnd, + ScrollMomentum }; enum MouseEventSource { diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 49f1ba3048..f5527354a2 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -783,7 +783,7 @@ QWheelEvent::QWheelEvent(const QPointF &pos, int delta, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::Orientation orient) : QInputEvent(Wheel, modifiers), p(pos), qt4D(delta), qt4O(orient), mouseState(buttons), - ph(Qt::NoScrollPhase), src(Qt::MouseEventNotSynthesized), invertedScrolling(false) + src(Qt::MouseEventNotSynthesized), invertedScrolling(false), ph(Qt::NoScrollPhase) { g = QCursor::pos(); if (orient == Qt::Vertical) @@ -818,7 +818,7 @@ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, int delta Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::Orientation orient) : QInputEvent(Wheel, modifiers), p(pos), g(globalPos), qt4D(delta), qt4O(orient), mouseState(buttons), - ph(Qt::NoScrollPhase), src(Qt::MouseEventNotSynthesized), invertedScrolling(false) + src(Qt::MouseEventNotSynthesized), invertedScrolling(false), ph(Qt::NoScrollPhase) { if (orient == Qt::Vertical) angleD = QPoint(0, delta); @@ -959,8 +959,8 @@ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, QPoint pixelDelta, QPoint angleDelta, int qt4Delta, Qt::Orientation qt4Orientation, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::ScrollPhase phase, Qt::MouseEventSource source, bool inverted) : QInputEvent(Wheel, modifiers), p(pos), g(globalPos), pixelD(pixelDelta), - angleD(angleDelta), qt4D(qt4Delta), qt4O(qt4Orientation), mouseState(buttons), ph(phase), src(source), - invertedScrolling(inverted) + angleD(angleDelta), qt4D(qt4Delta), qt4O(qt4Orientation), mouseState(buttons), src(source), + invertedScrolling(inverted), ph(phase) {} /*! @@ -997,7 +997,7 @@ QWheelEvent::QWheelEvent(QPointF pos, QPointF globalPos, QPoint pixelDelta, QPoi bool inverted, Qt::MouseEventSource source) : QInputEvent(Wheel, modifiers), p(pos), g(globalPos), pixelD(pixelDelta), angleD(angleDelta), qt4O(qAbs(angleDelta.x()) > qAbs(angleDelta.y()) ? Qt::Horizontal : Qt::Vertical), - mouseState(buttons), ph(phase), src(source), invertedScrolling(inverted) + mouseState(buttons), src(source), invertedScrolling(inverted), ph(phase) { qt4D = (qt4O == Qt::Horizontal ? angleDelta.x() : angleDelta.y()); } diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index 8d2f225809..2b1c6a6e31 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -232,10 +232,11 @@ protected: int qt4D = 0; Qt::Orientation qt4O = Qt::Vertical; Qt::MouseButtons mouseState; - uint ph : 2; + uint _unused_ : 2; // Kept for binary compatibility uint src: 2; bool invertedScrolling : 1; - int reserved : 27; + uint ph : 3; + int reserved : 24; friend class QApplication; }; diff --git a/src/plugins/platforms/cocoa/qnsview_mouse.mm b/src/plugins/platforms/cocoa/qnsview_mouse.mm index 1de256825a..65bc9f837d 100644 --- a/src/plugins/platforms/cocoa/qnsview_mouse.mm +++ b/src/plugins/platforms/cocoa/qnsview_mouse.mm @@ -566,6 +566,42 @@ NSTimeInterval timestamp = [theEvent timestamp]; ulong qt_timestamp = timestamp * 1000; + Qt::ScrollPhase phase = Qt::NoScrollPhase; + if (theEvent.phase == NSEventPhaseMayBegin || theEvent.phase == NSEventPhaseBegan) { + // MayBegin is likely to happen. We treat it the same as an actual begin, + // and follow it with an update when the actual begin is delivered. + phase = m_scrolling ? Qt::ScrollUpdate : Qt::ScrollBegin; + m_scrolling = true; + } else if (theEvent.phase == NSEventPhaseStationary || theEvent.phase == NSEventPhaseChanged) { + phase = Qt::ScrollUpdate; + } else if (theEvent.phase == NSEventPhaseEnded) { + // A scroll event phase may be followed by a momentum phase after the user releases + // the finger, and in that case we don't want to send a Qt::ScrollEnd until after + // the momentum phase has ended. Unfortunately there isn't any guaranteed way of + // knowing whether or not a NSEventPhaseEnded will be followed by a momentum phase. + // The best we can do is to look at the event queue and hope that the system has + // had time to emit a momentum phase event. + if ([NSApp nextEventMatchingMask:NSScrollWheelMask untilDate:[NSDate distantPast] + inMode:@"QtMomementumEventSearchMode" dequeue:NO].momentumPhase == NSEventPhaseBegan) { + Q_ASSERT(pixelDelta.isNull() && angleDelta.isNull()); + return; // Ignore this event, as it has a delta of 0,0 + } + phase = Qt::ScrollEnd; + m_scrolling = false; + } else if (theEvent.momentumPhase == NSEventPhaseBegan) { + Q_ASSERT(!pixelDelta.isNull() && !angleDelta.isNull()); + phase = Qt::ScrollUpdate; // Send as update, it has a delta + } else if (theEvent.momentumPhase == NSEventPhaseChanged) { + phase = Qt::ScrollMomentum; + } else if (theEvent.phase == NSEventPhaseCancelled + || theEvent.momentumPhase == NSEventPhaseEnded + || theEvent.momentumPhase == NSEventPhaseCancelled) { + phase = Qt::ScrollEnd; + m_scrolling = false; + } else { + Q_ASSERT(theEvent.momentumPhase != NSEventPhaseStationary); + } + // Prevent keyboard modifier state from changing during scroll event streams. // A two-finger trackpad flick generates a stream of scroll events. We want // the keyboard modifier state to be the state at the beginning of the @@ -573,34 +609,16 @@ // mid-stream. One example of this happening would be when pressing cmd // after scrolling in Qt Creator: not taking the phase into account causes // the end of the event stream to be interpreted as font size changes. - NSEventPhase momentumPhase = [theEvent momentumPhase]; - if (momentumPhase == NSEventPhaseNone) + if (theEvent.momentumPhase == NSEventPhaseNone) m_currentWheelModifiers = [QNSView convertKeyModifiers:[theEvent modifierFlags]]; - NSEventPhase phase = [theEvent phase]; - Qt::ScrollPhase ph = Qt::ScrollUpdate; - - // MayBegin is likely to happen. We treat it the same as an actual begin. - if (phase == NSEventPhaseMayBegin) { - m_scrolling = true; - ph = Qt::ScrollBegin; - } else if (phase == NSEventPhaseBegan) { - // If MayBegin did not happen, Began is the actual beginning. - if (!m_scrolling) - ph = Qt::ScrollBegin; - m_scrolling = true; - } else if (phase == NSEventPhaseEnded || phase == NSEventPhaseCancelled || - momentumPhase == NSEventPhaseEnded || momentumPhase == NSEventPhaseCancelled) { - ph = Qt::ScrollEnd; - m_scrolling = false; - } else if (phase == NSEventPhaseNone && momentumPhase == NSEventPhaseNone) { - ph = Qt::NoScrollPhase; - } // "isInverted": natural OS X scrolling, inverted from the Qt/other platform/Jens perspective. bool isInverted = [theEvent isDirectionInvertedFromDevice]; - qCDebug(lcQpaMouse) << "scroll wheel @ window pos" << qt_windowPoint << "delta px" << pixelDelta << "angle" << angleDelta << "phase" << ph << (isInverted ? "inverted" : ""); - QWindowSystemInterface::handleWheelEvent(m_platformWindow->window(), qt_timestamp, qt_windowPoint, qt_screenPoint, pixelDelta, angleDelta, m_currentWheelModifiers, ph, source, isInverted); + qCDebug(lcQpaMouse) << "scroll wheel @ window pos" << qt_windowPoint << "delta px" << pixelDelta + << "angle" << angleDelta << "phase" << phase << (isInverted ? "inverted" : ""); + QWindowSystemInterface::handleWheelEvent(m_platformWindow->window(), qt_timestamp, qt_windowPoint, + qt_screenPoint, pixelDelta, angleDelta, m_currentWheelModifiers, phase, source, isInverted); } #endif // QT_CONFIG(wheelevent) -- cgit v1.2.3 From ba9585bd02ba975013d73a75fa2382ffa708c990 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Fri, 10 Aug 2018 10:54:20 +0200 Subject: [macOS] Skip test that triggers a buffer overflow in CoreFoundation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deep down in CoreFoundation, ICU is used, and this test triggers a heap-buffer-overflow with AddressSanitizer. Disable this test for macOS until Apple fixes it. Task-number: QTBUG-69875 Change-Id: I43e4a69708be8cde3bde87c57db21f5b717f96b8 Reviewed-by: Tor Arne Vestbø Reviewed-by: Edward Welbourne --- tests/auto/corelib/tools/qlocale/tst_qlocale.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp index 2f533b4914..9e9ba03a60 100644 --- a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp +++ b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp @@ -581,7 +581,10 @@ void tst_QLocale::emptyCtor_data() ADD_CTOR_TEST("zz_zz", "C"); ADD_CTOR_TEST("zz...", "C"); ADD_CTOR_TEST("en.bla", "en_US"); +#if !(defined(Q_OS_DARWIN) && QT_HAS_FEATURE(address_sanitizer)) + // See QTBUG-69875 ADD_CTOR_TEST("en@bla", "en_US"); +#endif ADD_CTOR_TEST("en_blaaa", "en_US"); ADD_CTOR_TEST("en_zz", "en_US"); ADD_CTOR_TEST("en_GB.bla", "en_GB"); @@ -590,7 +593,10 @@ void tst_QLocale::emptyCtor_data() // Empty optional fields, but with punctuators supplied ADD_CTOR_TEST("en.", "en_US"); +#if !(defined(Q_OS_DARWIN) && QT_HAS_FEATURE(address_sanitizer)) + // See QTBUG-69875 ADD_CTOR_TEST("en@", "en_US"); +#endif ADD_CTOR_TEST("en.@", "en_US"); ADD_CTOR_TEST("en_", "en_US"); ADD_CTOR_TEST("en_.", "en_US"); -- cgit v1.2.3 From 7a649d259638dad45aba81d4b72e9358d0b1fa28 Mon Sep 17 00:00:00 2001 From: Jesus Fernandez Date: Fri, 17 Aug 2018 13:54:45 +0200 Subject: Fix -Winconsistent-missing-destructor-override Change-Id: I7a33d6b0cf0bd775567235e0efc858796d8ad852 Reviewed-by: David Faure --- src/widgets/util/qcompleter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/util/qcompleter.h b/src/widgets/util/qcompleter.h index fd1191d123..5620b55589 100644 --- a/src/widgets/util/qcompleter.h +++ b/src/widgets/util/qcompleter.h @@ -87,7 +87,7 @@ public: #if QT_CONFIG(stringlistmodel) QCompleter(const QStringList& completions, QObject *parent = nullptr); #endif - ~QCompleter(); + ~QCompleter() override; void setWidget(QWidget *widget); QWidget *widget() const; -- cgit v1.2.3 From 32b4cb1b5438f0cc5bb7141ea8fa31da8c1ca8a6 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 9 Aug 2018 16:34:07 +0200 Subject: qmake: remove pointless input redirections from compiler calls Change-Id: I1b5d2b33ec62d24f1d6a9bd155bf3f28ab8bbf4e Reviewed-by: Joerg Bornemann --- mkspecs/features/toolchain.prf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mkspecs/features/toolchain.prf b/mkspecs/features/toolchain.prf index fdf3d1cdd3..cdeb86daa3 100644 --- a/mkspecs/features/toolchain.prf +++ b/mkspecs/features/toolchain.prf @@ -168,14 +168,14 @@ isEmpty($${target_prefix}.INCDIRS) { # defineReplace(qtVariablesFromMSVC) { - ret = $$system("$$1 -nologo -E $$2 $$system_quote($$PWD/data/macros.cpp) NUL", lines, ec) + ret = $$system("$$1 -nologo -E $$2 $$system_quote($$PWD/data/macros.cpp) 2>NUL", lines, ec) !equals(ec, 0): qtCompilerErrror($$1, $$ret) return($$ret) } defineReplace(qtVariablesFromGCC) { ret = $$system("$$1 -E $$system_quote($$PWD/data/macros.cpp) \ - <$$QMAKE_SYSTEM_NULL_DEVICE 2>$$QMAKE_SYSTEM_NULL_DEVICE", lines, ec) + 2>$$QMAKE_SYSTEM_NULL_DEVICE", lines, ec) !equals(ec, 0): qtCompilerErrror($$1, $$ret) return($$ret) } -- cgit v1.2.3 From 89f2a731cf85ff06c5295148b523ec83194068f7 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 9 Aug 2018 16:05:51 +0200 Subject: qmake: add default path and version detection for ghs toolchain Change-Id: Ic35f3e25078909e212864218835663989f647aae Reviewed-by: Joerg Bornemann Reviewed-by: Nikola Velinov Reviewed-by: Oswald Buddenhagen --- configure.pri | 6 ++++++ mkspecs/features/data/macros.cpp | 3 +++ mkspecs/features/toolchain.prf | 29 +++++++++++++++++++++++++++-- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/configure.pri b/configure.pri index 41c3f13ea1..03eacd3c07 100644 --- a/configure.pri +++ b/configure.pri @@ -1144,6 +1144,12 @@ defineReplace(qtConfOutputPostProcess_publicPro) { "QT_ICC_MINOR_VERSION = $$format_number($$replace(QMAKE_ICC_VER, "(..)(..)", "\\2"))" \ "QT_ICC_PATCH_VERSION = $$QMAKE_ICC_UPDATE_VER" } + !isEmpty(QMAKE_GHS_VERSION) { + output += \ + "QT_GHS_MAJOR_VERSION = $$replace(QMAKE_GHS_VERSION, "(.*)(.)(.)", "\\1")" \ + "QT_GHS_MINOR_VERSION = $$replace(QMAKE_GHS_VERSION, "(.*)(.)(.)", "\\2")" \ + "QT_GHS_PATCH_VERSION = $$replace(QMAKE_GHS_VERSION, "(.*)(.)(.)", "\\3")" + } output += "QT_EDITION = $$config.input.qt_edition" !contains(config.input.qt_edition, "(OpenSource|Preview)") { diff --git a/mkspecs/features/data/macros.cpp b/mkspecs/features/data/macros.cpp index 9dcb8f0914..7a06fad1a6 100644 --- a/mkspecs/features/data/macros.cpp +++ b/mkspecs/features/data/macros.cpp @@ -27,3 +27,6 @@ QMAKE_GCC_MAJOR_VERSION = __GNUC__ QMAKE_GCC_MINOR_VERSION = __GNUC_MINOR__ QMAKE_GCC_PATCH_VERSION = __GNUC_PATCHLEVEL__ #endif +#ifdef __ghs__ +QMAKE_GHS_VERSION = __GHS_VERSION_NUMBER +#endif diff --git a/mkspecs/features/toolchain.prf b/mkspecs/features/toolchain.prf index cdeb86daa3..bce3ef3954 100644 --- a/mkspecs/features/toolchain.prf +++ b/mkspecs/features/toolchain.prf @@ -142,6 +142,29 @@ isEmpty($${target_prefix}.INCDIRS) { !integrity: \ error("failed to parse default search paths from compiler output") QMAKE_DEFAULT_LIBDIRS = $$unique(QMAKE_DEFAULT_LIBDIRS) + } else: ghs { + cmd = $$QMAKE_CXX $$QMAKE_CXXFLAGS -$${LITERAL_HASH} -o /tmp/fake_output /tmp/fake_input.cpp + output = $$system("$$cmd", blob, ec) + !equals(ec, 0): qtCompilerErrror($$QMAKE_CXX, $$output) + output ~= s/\\\\\\n {8}//g + output = $$split(output, $$escape_expand(\\n)) + for (line, output) { + contains(line, "^[^ ]+/ecom[^ ]+ .* /tmp/fake_input\\.cpp") { + for (parameter, $$list($$line)) { + contains(parameter, "^(-I|--include_no_mmd=|--sys_include=).*") { + parameter ~= s/^(-I|--include_no_mmd=|--sys_include=)// + QMAKE_DEFAULT_INCDIRS += $$clean_path($$parameter) + } + } + } else: contains(line, "^[^ ]+/elxr .*") { + for (parameter, $$list($$line)) { + contains(parameter, "^-L.*") { + parameter ~= s/^-L// + QMAKE_DEFAULT_LIBDIRS += $$clean_path($$parameter) + } + } + } + } } else: msvc { # This doesn't differentiate between host and target, # but neither do the compilers. @@ -199,11 +222,11 @@ isEmpty($${target_prefix}.COMPILER_MACROS) { } else { vars = $$qtVariablesFromMSVC($$QMAKE_CXX) } - } else: gcc { + } else: gcc|ghs { vars = $$qtVariablesFromGCC($$QMAKE_CXX) } for (v, vars) { - contains(v, $${LITERAL_HASH}.*)|contains(v, " *"): next() + !contains(v, "[A-Z_]+ = .*"): next() # Set both for the outer scope ... eval($$v) v ~= s/ .*// @@ -245,6 +268,8 @@ QMAKE_COMPILER_DEFINES += __cplusplus=$$QT_COMPILER_STDCXX __GNUC__=$$QMAKE_GCC_MAJOR_VERSION \ __GNUC_MINOR__=$$QMAKE_GCC_MINOR_VERSION \ __GNUC_PATCHLEVEL__=$$QMAKE_GCC_PATCH_VERSION +!isEmpty(QMAKE_GHS_VERSION): \ + QMAKE_COMPILER_DEFINES += __ghs__ __GHS_VERSION_NUMBER=$$QMAKE_GHS_VERSION QMAKE_CFLAGS += $$QMAKE_CFLAGS_MSVC_COMPAT QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_MSVC_COMPAT -- cgit v1.2.3 From 6b65be5554de382a3d0186f54e5d28cdfc0bb6fa Mon Sep 17 00:00:00 2001 From: Jesus Fernandez Date: Fri, 3 Aug 2018 15:23:32 +0200 Subject: Improve Q_ASSERT readability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I231ecafe1eb48d74f787083e86a85536a90ed69b Reviewed-by: Mårten Nordheim Reviewed-by: Timur Pocheptsov Reviewed-by: Edward Welbourne --- src/gui/text/qtextengine.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 5d582551a7..6826f62b61 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -597,7 +597,13 @@ struct QBidiAlgorithm { } else if (current == QChar::DirBN) { current = last; } else { - Q_ASSERT(current != QChar::DirLRE && current != QChar::DirRLE && current != QChar::DirLRO && current != QChar::DirRLO && current != QChar::DirPDF); // there shouldn't be any explicit embedding marks here + // there shouldn't be any explicit embedding marks here + Q_ASSERT(current != QChar::DirLRE); + Q_ASSERT(current != QChar::DirRLE); + Q_ASSERT(current != QChar::DirLRO); + Q_ASSERT(current != QChar::DirRLO); + Q_ASSERT(current != QChar::DirPDF); + last = current; } -- cgit v1.2.3 From cfcfc96d8f918e16b35e30cead4a4bc370bb690b Mon Sep 17 00:00:00 2001 From: Jesus Fernandez Date: Fri, 17 Aug 2018 14:32:35 +0200 Subject: Use nullptr instead of 0 Change-Id: I8d18dfbc3451fd8748127415fcb1da54b0870b9a Reviewed-by: David Faure --- src/widgets/util/qcompleter.cpp | 43 +++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/src/widgets/util/qcompleter.cpp b/src/widgets/util/qcompleter.cpp index c50d0dc9e0..df280119cb 100644 --- a/src/widgets/util/qcompleter.cpp +++ b/src/widgets/util/qcompleter.cpp @@ -182,10 +182,10 @@ int QCompletionModel::columnCount(const QModelIndex &) const void QCompletionModel::setSourceModel(QAbstractItemModel *source) { - bool hadModel = (sourceModel() != 0); + bool hadModel = (sourceModel() != nullptr); if (hadModel) - QObject::disconnect(sourceModel(), 0, this, 0); + QObject::disconnect(sourceModel(), nullptr, this, nullptr); QAbstractProxyModel::setSourceModel(source); @@ -402,7 +402,7 @@ QVariant QCompletionModel::data(const QModelIndex& index, int role) const void QCompletionModel::modelDestroyed() { - QAbstractProxyModel::setSourceModel(0); // switch to static empty model + QAbstractProxyModel::setSourceModel(nullptr); // switch to static empty model invalidate(); } @@ -471,13 +471,13 @@ QMatchData QCompletionEngine::filterHistory() return QMatchData(); #if QT_CONFIG(dirmodel) - const bool isDirModel = (qobject_cast(source) != 0); + const bool isDirModel = (qobject_cast(source) != nullptr); #else const bool isDirModel = false; #endif Q_UNUSED(isDirModel) #if QT_CONFIG(filesystemmodel) - const bool isFsModel = (qobject_cast(source) != 0); + const bool isFsModel = (qobject_cast(source) != nullptr); #else const bool isFsModel = false; #endif @@ -828,9 +828,18 @@ QMatchData QUnsortedModelEngine::filter(const QString& part, const QModelIndex& /////////////////////////////////////////////////////////////////////////////// QCompleterPrivate::QCompleterPrivate() -: widget(0), proxy(0), popup(0), filterMode(Qt::MatchStartsWith), cs(Qt::CaseSensitive), - role(Qt::EditRole), column(0), maxVisibleItems(7), sorting(QCompleter::UnsortedModel), - wrap(true), eatFocusOut(true), hiddenBecauseNoMatch(false) + : widget(nullptr), + proxy(nullptr), + popup(nullptr), + filterMode(Qt::MatchStartsWith), + cs(Qt::CaseSensitive), + role(Qt::EditRole), + column(0), + maxVisibleItems(7), + sorting(QCompleter::UnsortedModel), + wrap(true), + eatFocusOut(true), + hiddenBecauseNoMatch(false) { } @@ -1146,7 +1155,7 @@ void QCompleter::setCompletionMode(QCompleter::CompletionMode mode) d->widget->removeEventFilter(this); if (d->popup) { d->popup->deleteLater(); - d->popup = 0; + d->popup = nullptr; } } else { if (d->widget) @@ -1222,8 +1231,8 @@ void QCompleter::setPopup(QAbstractItemView *popup) Q_D(QCompleter); Q_ASSERT(popup != 0); if (d->popup) { - QObject::disconnect(d->popup->selectionModel(), 0, this, 0); - QObject::disconnect(d->popup, 0, this, 0); + QObject::disconnect(d->popup->selectionModel(), nullptr, this, nullptr); + QObject::disconnect(d->popup, nullptr, this, nullptr); } if (d->popup != popup) delete d->popup; @@ -1234,7 +1243,7 @@ void QCompleter::setPopup(QAbstractItemView *popup) Qt::FocusPolicy origPolicy = Qt::NoFocus; if (d->widget) origPolicy = d->widget->focusPolicy(); - popup->setParent(0, Qt::Popup); + popup->setParent(nullptr, Qt::Popup); popup->setFocusPolicy(Qt::NoFocus); if (d->widget) d->widget->setFocusPolicy(origPolicy); @@ -1488,7 +1497,7 @@ void QCompleter::complete(const QRect& rect) return; } - Q_ASSERT(d->widget != 0); + Q_ASSERT(d->widget); if ((d->mode == QCompleter::PopupCompletion && !idx.isValid()) || (d->mode == QCompleter::UnfilteredPopupCompletion && d->proxy->rowCount() == 0)) { if (d->popup) @@ -1798,10 +1807,10 @@ QString QCompleter::pathFromIndex(const QModelIndex& index) const bool isDirModel = false; bool isFsModel = false; #if QT_CONFIG(dirmodel) - isDirModel = qobject_cast(d->proxy->sourceModel()) != 0; + isDirModel = qobject_cast(d->proxy->sourceModel()) != nullptr; #endif #if QT_CONFIG(filesystemmodel) - isFsModel = qobject_cast(d->proxy->sourceModel()) != 0; + isFsModel = qobject_cast(d->proxy->sourceModel()) != nullptr; #endif if (!isDirModel && !isFsModel) return sourceModel->data(index, d->role).toString(); @@ -1848,13 +1857,13 @@ QStringList QCompleter::splitPath(const QString& path) const bool isFsModel = false; #if QT_CONFIG(dirmodel) Q_D(const QCompleter); - isDirModel = qobject_cast(d->proxy->sourceModel()) != 0; + isDirModel = qobject_cast(d->proxy->sourceModel()) != nullptr; #endif #if QT_CONFIG(filesystemmodel) #if !QT_CONFIG(dirmodel) Q_D(const QCompleter); #endif - isFsModel = qobject_cast(d->proxy->sourceModel()) != 0; + isFsModel = qobject_cast(d->proxy->sourceModel()) != nullptr; #endif if ((!isDirModel && !isFsModel) || path.isEmpty()) -- cgit v1.2.3 From 3746eb8412ea42d7e3c519926460482530782a75 Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Wed, 1 Aug 2018 00:28:26 +0200 Subject: QRegularExpression: refactor wildcard translation This patch refactors the wildcardToRegularExpression method to generate a simpler regular expression. It also fixes some shortcomings of the previous implementation. Tests have been updated to ensure all cases are properly supported. Change-Id: I454e3fe8fe0bb663b2f319d6fa2fa8aec626c50d Reviewed-by: Shawn Rutledge --- src/corelib/tools/qregularexpression.cpp | 59 +++++++++++++--------- .../qregularexpression/tst_qregularexpression.cpp | 19 +++++++ 2 files changed, 54 insertions(+), 24 deletions(-) diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp index 17caaabc97..1bd06a73cd 100644 --- a/src/corelib/tools/qregularexpression.cpp +++ b/src/corelib/tools/qregularexpression.cpp @@ -1874,6 +1874,9 @@ QString QRegularExpression::escape(const QString &str) \since 5.12 Returns a regular expression representation of the given glob \a pattern. + The transformation is targeting file path globbing, which means in particular + that path separators receive special treatment. This implies that it is not + just a basic translation from "*" to ".*". \snippet code/src_corelib_tools_qregularexpression.cpp 31 @@ -1917,19 +1920,35 @@ QString QRegularExpression::wildcardToRegularExpression(const QString &pattern) { const int wclen = pattern.length(); QString rx; + rx.reserve(wclen + wclen / 16); int i = 0; - bool hasNegativeBracket = false; const QChar *wc = pattern.unicode(); +#ifdef Q_OS_WIN + const QLatin1Char nativePathSeparator('\\'); + const QLatin1String starEscape("[^/\\\\]*"); + const QLatin1String questionMarkEscape("[^/\\\\]"); +#else + const QLatin1Char nativePathSeparator('/'); + const QLatin1String starEscape("[^/]*"); + const QLatin1String questionMarkEscape("[^/]"); +#endif + while (i < wclen) { const QChar c = wc[i++]; switch (c.unicode()) { case '*': - rx += QLatin1String(".*"); + rx += starEscape; break; case '?': - rx += QLatin1Char('.'); + rx += questionMarkEscape; + break; + case '\\': +#ifdef Q_OS_WIN + case '/': + rx += QLatin1String("[/\\\\]"); break; +#endif case '$': case '(': case ')': @@ -1943,35 +1962,27 @@ QString QRegularExpression::wildcardToRegularExpression(const QString &pattern) rx += c; break; case '[': + rx += c; // Support for the [!abc] or [!a-c] syntax - // Implements a negative look-behind for one char. if (i < wclen) { - if (wc[i] == QLatin1Char(']')) { - rx += c; - rx += wc[i++]; - } else if (wc[i] == QLatin1Char('!')) { - rx += QLatin1String(".(?<"); - rx += wc[i++]; - rx += c; - hasNegativeBracket = true; - } else { - rx += c; + if (wc[i] == QLatin1Char('!')) { + rx += QLatin1Char('^'); + ++i; } + + if (i < wclen && wc[i] == QLatin1Char(']')) + rx += wc[i++]; + while (i < wclen && wc[i] != QLatin1Char(']')) { + // The '/' appearing in a character class invalidates the + // regular expression parsing. It also concerns '\\' on + // Windows OS types. + if (wc[i] == QLatin1Char('/') || wc[i] == nativePathSeparator) + return rx; if (wc[i] == QLatin1Char('\\')) rx += QLatin1Char('\\'); rx += wc[i++]; } - } else { - rx += c; - } - break; - case ']': - rx += c; - // Closes the negative look-behind expression. - if (hasNegativeBracket) { - rx += QLatin1Char(')'); - hasNegativeBracket = false; } break; default: diff --git a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp index 987ca519ee..f520e9742a 100644 --- a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp +++ b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp @@ -2173,6 +2173,7 @@ void tst_QRegularExpression::wildcard_data() addRow("?m", "test.html", 6); addRow("[*]", "test.html", -1); addRow("[?]","test.html", -1); + addRow("[?]","test.h?ml", 6); addRow("[[]","test.h[ml", 6); addRow("[]]","test.h]ml", 6); addRow(".h[a-z]ml", "test.html", 4); @@ -2187,6 +2188,24 @@ void tst_QRegularExpression::wildcard_data() addRow(".h[][!]", "test.h]ml", 4); addRow(".h[][!]", "test.h[ml", 4); addRow(".h[][!]", "test.h!ml", 4); + + addRow("foo/*/bar", "Qt/foo/baz/bar", 3); + addRow("foo/(*)/bar", "Qt/foo/baz/bar", -1); + addRow("foo/(*)/bar", "Qt/foo/(baz)/bar", 3); + addRow("foo/?/bar", "Qt/foo/Q/bar", 3); + addRow("foo/?/bar", "Qt/foo/Qt/bar", -1); + addRow("foo/(?)/bar", "Qt/foo/Q/bar", -1); + addRow("foo/(?)/bar", "Qt/foo/(Q)/bar", 3); + +#ifdef Q_OS_WIN + addRow("foo\\*\\bar", "Qt\\foo\\baz\\bar", 3); + addRow("foo\\(*)\\bar", "Qt\\foo\\baz\\bar", -1); + addRow("foo\\(*)\\bar", "Qt\\foo\\(baz)\\bar", 3); + addRow("foo\\?\\bar", "Qt\\foo\\Q\\bar", 3); + addRow("foo\\?\\bar", "Qt\\foo\\Qt\\bar", -1); + addRow("foo\\(?)\\bar", "Qt\\foo\\Q\\bar", -1); + addRow("foo\\(?)\\bar", "Qt\\foo\\(Q)\\bar", 3); +#endif } void tst_QRegularExpression::wildcard() -- cgit v1.2.3 From a2c85bffbeaa027e98fb6c23b2d7919adc8d28b7 Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Thu, 19 Jul 2018 00:21:49 +0200 Subject: Migrate QDir to use QRegularExpression The match method still uses QRegExp. This patch updates the code to use QRegularExpression and translates the wildcard patterns to a suitable form for QRegularExpression. [ChangeLog][Core][QDir] QDir now uses QRegularExpression internally for wildcard matching. Note that QRegularExpression might not give the exact same result as QRegExp as its implementation follows strictly the glob patterns definition for wildcard expressions. Nevertheless, the tests for QDir return the same results as before. Change-Id: I095959443ac7362f7534e35454eff038061fca82 Reviewed-by: Ulf Hermann --- src/corelib/io/qdir.cpp | 24 ++++++++++++++++-------- src/corelib/io/qdir.h | 2 +- tests/auto/corelib/io/qdir/tst_qdir.cpp | 1 - 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index 7c0a48f8f2..85ea2cb139 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -48,7 +48,9 @@ #include "qdiriterator.h" #include "qdatetime.h" #include "qstring.h" -#include "qregexp.h" +#if QT_CONFIG(regularexpression) +# include +#endif #include "qvector.h" #include "qvarlengtharray.h" #include "qfilesystementry_p.h" @@ -1038,7 +1040,7 @@ QStringList QDir::nameFilters() const list of filters specified by \a nameFilters. Each name filter is a wildcard (globbing) filter that understands - \c{*} and \c{?} wildcards. (See \l{QRegExp wildcard matching}.) + \c{*} and \c{?} wildcards. (See \l{QRegularExpression wildcard matching}.) For example, the following code sets three name filters on a QDir to ensure that only files with extensions typically used for C++ @@ -2110,7 +2112,7 @@ QString QDir::rootPath() return QFileSystemEngine::rootPath(); } -#ifndef QT_NO_REGEXP +#if QT_CONFIG(regularexpression) /*! \overload @@ -2118,13 +2120,18 @@ QString QDir::rootPath() patterns in the list of \a filters; otherwise returns \c false. The matching is case insensitive. - \sa {QRegExp wildcard matching}, QRegExp::exactMatch(), entryList(), entryInfoList() + \sa {QRegularExpression Wildcard matching}, QRegularExpression::wildcardToRegularExpression(), + entryList(), entryInfoList() */ bool QDir::match(const QStringList &filters, const QString &fileName) { for (QStringList::ConstIterator sit = filters.constBegin(); sit != filters.constEnd(); ++sit) { - QRegExp rx(*sit, Qt::CaseInsensitive, QRegExp::Wildcard); - if (rx.exactMatch(fileName)) + QString wildcard = QRegularExpression::wildcardToRegularExpression(*sit); + // Insensitive exact match + // (see Notes for QRegExp Users in QRegularExpression's documentation) + QRegularExpression rx(QLatin1String("\\A(?:") + wildcard + QLatin1String(")\\z"), + QRegularExpression::CaseInsensitiveOption); + if (rx.match(fileName).hasMatch()) return true; } return false; @@ -2136,13 +2143,14 @@ bool QDir::match(const QStringList &filters, const QString &fileName) contain multiple patterns separated by spaces or semicolons. The matching is case insensitive. - \sa {QRegExp wildcard matching}, QRegExp::exactMatch(), entryList(), entryInfoList() + \sa {QRegularExpression wildcard matching}, QRegularExpression::wildcardToRegularExpression, + entryList(), entryInfoList() */ bool QDir::match(const QString &filter, const QString &fileName) { return match(nameFiltersFromString(filter), fileName); } -#endif // QT_NO_REGEXP +#endif // QT_CONFIG(regularexpression) /*! \internal diff --git a/src/corelib/io/qdir.h b/src/corelib/io/qdir.h index 950a26f327..45c59d9e1d 100644 --- a/src/corelib/io/qdir.h +++ b/src/corelib/io/qdir.h @@ -206,7 +206,7 @@ public: static inline QDir temp() { return QDir(tempPath()); } static QString tempPath(); -#ifndef QT_NO_REGEXP +#if QT_CONFIG(regularexpression) static bool match(const QStringList &filters, const QString &fileName); static bool match(const QString &filter, const QString &fileName); #endif diff --git a/tests/auto/corelib/io/qdir/tst_qdir.cpp b/tests/auto/corelib/io/qdir/tst_qdir.cpp index afa15fe895..30f0e447ad 100644 --- a/tests/auto/corelib/io/qdir/tst_qdir.cpp +++ b/tests/auto/corelib/io/qdir/tst_qdir.cpp @@ -33,7 +33,6 @@ #include #include #include -#include #include #if defined(Q_OS_WIN) -- cgit v1.2.3 From 5dd9616f6d4f4b010958dc4869881f597f3d4d0c Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Thu, 19 Jul 2018 00:22:15 +0200 Subject: Replace QRegExp by QRegularExpression in QFileSystemModel [ChangeLog][Widgets][Dialogs] QFileSystemModel now uses QRegularExpression internally for wildcard matching. Note that QRegularExpression might not give the exact same result as QRegExp as its implementation follows strictly the glob patterns definition for wildcard expressions. Change-Id: I6ca893833ff7b5b7f678221bb9bc623fd17c1cfa Reviewed-by: Edward Welbourne --- src/widgets/dialogs/qfilesystemmodel.cpp | 37 +++++++++++++++++--------------- src/widgets/dialogs/qfilesystemmodel_p.h | 4 ++-- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp index 33b8b51216..b67335822b 100644 --- a/src/widgets/dialogs/qfilesystemmodel.cpp +++ b/src/widgets/dialogs/qfilesystemmodel.cpp @@ -48,6 +48,9 @@ #endif #include #include +#if QT_CONFIG(regularexpression) +# include +#endif #include @@ -1580,7 +1583,7 @@ bool QFileSystemModel::nameFilterDisables() const void QFileSystemModel::setNameFilters(const QStringList &filters) { // Prep the regexp's ahead of time -#ifndef QT_NO_REGEXP +#if QT_CONFIG(regularexpression) Q_D(QFileSystemModel); if (!d->bypassFilters.isEmpty()) { @@ -1601,11 +1604,7 @@ void QFileSystemModel::setNameFilters(const QStringList &filters) } } - d->nameFilters.clear(); - const Qt::CaseSensitivity caseSensitive = - (filter() & QDir::CaseSensitive) ? Qt::CaseSensitive : Qt::CaseInsensitive; - for (const auto &filter : filters) - d->nameFilters << QRegExp(filter, caseSensitive, QRegExp::Wildcard); + d->nameFilters = filters; d->forceSort = true; d->delayedSort(); #endif @@ -1616,16 +1615,12 @@ void QFileSystemModel::setNameFilters(const QStringList &filters) */ QStringList QFileSystemModel::nameFilters() const { +#if QT_CONFIG(regularexpression) Q_D(const QFileSystemModel); - QStringList filters; -#ifndef QT_NO_REGEXP - const int numNameFilters = d->nameFilters.size(); - filters.reserve(numNameFilters); - for (int i = 0; i < numNameFilters; ++i) { - filters << d->nameFilters.at(i).pattern(); - } + return d->nameFilters; +#else + return QStringList(); #endif - return filters; } /*! @@ -2026,15 +2021,23 @@ bool QFileSystemModelPrivate::filtersAcceptsNode(const QFileSystemNode *node) co */ bool QFileSystemModelPrivate::passNameFilters(const QFileSystemNode *node) const { -#ifndef QT_NO_REGEXP +#if QT_CONFIG(regularexpression) if (nameFilters.isEmpty()) return true; // Check the name regularexpression filters if (!(node->isDir() && (filters & QDir::AllDirs))) { + const QRegularExpression::PatternOptions options = + (filters & QDir::CaseSensitive) ? QRegularExpression::NoPatternOption + : QRegularExpression::CaseInsensitiveOption; + for (const auto &nameFilter : nameFilters) { - QRegExp copy = nameFilter; - if (copy.exactMatch(node->fileName)) + const QString wildcard = QLatin1String("\\A(?:") + + QRegularExpression::wildcardToRegularExpression(nameFilter) + + QLatin1String(")\\z"); + QRegularExpression rx(wildcard, options); + QRegularExpressionMatch match = rx.match(node->fileName); + if (match.hasMatch()) return true; } return false; diff --git a/src/widgets/dialogs/qfilesystemmodel_p.h b/src/widgets/dialogs/qfilesystemmodel_p.h index 1e72bb69a8..9c432e1ae6 100644 --- a/src/widgets/dialogs/qfilesystemmodel_p.h +++ b/src/widgets/dialogs/qfilesystemmodel_p.h @@ -315,8 +315,8 @@ public: //It enable a sort which is not recursive, it means //we sort only what we see. bool disableRecursiveSort; -#ifndef QT_NO_REGEXP - QList nameFilters; +#if QT_CONFIG(regularexpression) + QStringList nameFilters; #endif QHash resolvedSymLinks; -- cgit v1.2.3 From 6228c0528ca5cea2f8c309c4f64e38eb729b04da Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 31 Jul 2018 12:39:13 -0700 Subject: QGraphicsAnchorLayout: move some private classes to a namespace with Q MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoids polluting the global namespace Change-Id: Ie01831ddac5446fdbdeefffd15468b5ca22d5e7b Reviewed-by: André Hartmann Reviewed-by: Edward Welbourne Reviewed-by: David Faure --- src/widgets/graphicsview/qgraphicsanchorlayout.h | 1 - src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp | 4 ++-- src/widgets/graphicsview/qgraphicsanchorlayout_p.h | 7 +++++++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/widgets/graphicsview/qgraphicsanchorlayout.h b/src/widgets/graphicsview/qgraphicsanchorlayout.h index e392be1568..9bea43dd8e 100644 --- a/src/widgets/graphicsview/qgraphicsanchorlayout.h +++ b/src/widgets/graphicsview/qgraphicsanchorlayout.h @@ -70,7 +70,6 @@ private: Q_DECLARE_PRIVATE(QGraphicsAnchor) friend class QGraphicsAnchorLayoutPrivate; - friend struct AnchorData; }; class Q_WIDGETS_EXPORT QGraphicsAnchorLayout : public QGraphicsLayout diff --git a/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp b/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp index 86c1fa243c..008560d856 100644 --- a/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp +++ b/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp @@ -167,7 +167,7 @@ AnchorData::~AnchorData() if (graphicsAnchor) { // Remove reference to ourself to avoid double removal in // QGraphicsAnchorPrivate dtor. - graphicsAnchor->d_func()->data = 0; + QGraphicsAnchorPrivate::get(graphicsAnchor)->data = nullptr; delete graphicsAnchor; } @@ -215,7 +215,7 @@ void AnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo) } else { // It is a user-created anchor, fetch size information from the associated QGraphicsAnchor Q_ASSERT(graphicsAnchor); - QGraphicsAnchorPrivate *anchorPrivate = graphicsAnchor->d_func(); + QGraphicsAnchorPrivate *anchorPrivate = QGraphicsAnchorPrivate::get(graphicsAnchor); // Policy, min and max sizes are straightforward policy = anchorPrivate->sizePolicy; diff --git a/src/widgets/graphicsview/qgraphicsanchorlayout_p.h b/src/widgets/graphicsview/qgraphicsanchorlayout_p.h index 6b2408b2eb..699ca32bfe 100644 --- a/src/widgets/graphicsview/qgraphicsanchorlayout_p.h +++ b/src/widgets/graphicsview/qgraphicsanchorlayout_p.h @@ -73,6 +73,7 @@ QT_BEGIN_NAMESPACE respectively. */ +namespace QtGraphicsAnchorLayout { /*! \internal @@ -326,6 +327,9 @@ public: QSet positives; QSet negatives; }; +} // namespace QtGraphicsAnchorLayout +using namespace QtGraphicsAnchorLayout; + Q_DECLARE_TYPEINFO(GraphPath, Q_MOVABLE_TYPE); class QGraphicsAnchorLayoutPrivate; @@ -346,6 +350,9 @@ public: void setSizePolicy(QSizePolicy::Policy policy); + static QGraphicsAnchorPrivate *get(QGraphicsAnchor *q) + { return q->d_func(); } + QGraphicsAnchorLayoutPrivate *layoutPrivate; AnchorData *data; -- cgit v1.2.3 From bcd80eebf983a2b547662d7e0d67bc8624d1130f Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Wed, 25 Jul 2018 09:23:28 +0200 Subject: Implement exact match expression builder for QRegularExpression QRegularExpression doesn't offer a direct equivalent of QRegExp's exact match. There are several places in the Qt sources that use this feature. This patch implements a small helper function that builds the expression as recommended in the documentation and updates the related code. [ChangeLog][Core][Tools] QRegularExpression now provides anchoredPattern() which is a helper function to build regular expressions used for exact matching. Change-Id: Idbbf142c4c5cb9b62abf8229f4ce85fd4409e5d0 Reviewed-by: Oswald Buddenhagen Reviewed-by: Thiago Macieira --- src/corelib/io/qdir.cpp | 2 +- src/corelib/tools/qregularexpression.cpp | 16 ++++++++++++++++ src/corelib/tools/qregularexpression.h | 6 ++++++ src/corelib/tools/qstringlist.cpp | 4 ++-- src/gui/util/qvalidator.cpp | 2 +- src/widgets/dialogs/qfilesystemmodel.cpp | 6 ++---- 6 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index 85ea2cb139..39422c3401 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -2129,7 +2129,7 @@ bool QDir::match(const QStringList &filters, const QString &fileName) QString wildcard = QRegularExpression::wildcardToRegularExpression(*sit); // Insensitive exact match // (see Notes for QRegExp Users in QRegularExpression's documentation) - QRegularExpression rx(QLatin1String("\\A(?:") + wildcard + QLatin1String(")\\z"), + QRegularExpression rx(QRegularExpression::anchoredPattern(wildcard), QRegularExpression::CaseInsensitiveOption); if (rx.match(fileName).hasMatch()) return true; diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp index 1bd06a73cd..6f0e572f41 100644 --- a/src/corelib/tools/qregularexpression.cpp +++ b/src/corelib/tools/qregularexpression.cpp @@ -483,6 +483,11 @@ QT_BEGIN_NAMESPACE Note the usage of the non-capturing group in order to preserve the meaning of the branch operator inside the pattern. + The QRegularExpression::anchoredPattern() helper method does exactly that for + you. + + \sa anchoredPattern + \section3 Porting from QRegExp's Partial Matching When using QRegExp::exactMatch(), if an exact match was not found, one @@ -1994,6 +1999,17 @@ QString QRegularExpression::wildcardToRegularExpression(const QString &pattern) return rx; } +/*! + \fn QRegularExpression::anchoredPattern(const QString &expression) + + \since 5.12 + + Returns the expression wrapped between the \c{\A} and \c{\z} anchors to be + used for exact matching. + + \sa {Porting from QRegExp's Exact Matching} +*/ + /*! \since 5.1 diff --git a/src/corelib/tools/qregularexpression.h b/src/corelib/tools/qregularexpression.h index 388aa7a8ca..f9e7029550 100644 --- a/src/corelib/tools/qregularexpression.h +++ b/src/corelib/tools/qregularexpression.h @@ -142,6 +142,12 @@ public: static QString escape(const QString &str); static QString wildcardToRegularExpression(const QString &str); + static inline QString anchoredPattern(const QString &expression) + { + return QLatin1String("\\A(?:") + + expression + + QLatin1String(")\\z"); + } bool operator==(const QRegularExpression &re) const; inline bool operator!=(const QRegularExpression &re) const { return !operator==(re); } diff --git a/src/corelib/tools/qstringlist.cpp b/src/corelib/tools/qstringlist.cpp index e9b7397a74..712ba74716 100644 --- a/src/corelib/tools/qstringlist.cpp +++ b/src/corelib/tools/qstringlist.cpp @@ -692,7 +692,7 @@ int QtPrivate::QStringList_indexOf(const QStringList *that, const QRegularExpres if (from < 0) from = qMax(from + that->size(), 0); - QString exactPattern = QLatin1String("\\A(?:") + re.pattern() + QLatin1String(")\\z"); + QString exactPattern = QRegularExpression::anchoredPattern(re.pattern()); QRegularExpression exactRe(exactPattern, re.patternOptions()); for (int i = from; i < that->size(); ++i) { @@ -722,7 +722,7 @@ int QtPrivate::QStringList_lastIndexOf(const QStringList *that, const QRegularEx else if (from >= that->size()) from = that->size() - 1; - QString exactPattern = QLatin1String("\\A(?:") + re.pattern() + QLatin1String(")\\z"); + QString exactPattern = QRegularExpression::anchoredPattern(re.pattern()); QRegularExpression exactRe(exactPattern, re.patternOptions()); for (int i = from; i >= 0; --i) { diff --git a/src/gui/util/qvalidator.cpp b/src/gui/util/qvalidator.cpp index ae4f56a12e..2237b016e9 100644 --- a/src/gui/util/qvalidator.cpp +++ b/src/gui/util/qvalidator.cpp @@ -1079,7 +1079,7 @@ void QRegularExpressionValidatorPrivate::setRegularExpression(const QRegularExpr if (origRe != re) { usedRe = origRe = re; // copies also the pattern options - usedRe.setPattern(QLatin1String("\\A(?:") + re.pattern() + QLatin1String(")\\z")); + usedRe.setPattern(QRegularExpression::anchoredPattern(re.pattern())); emit q->regularExpressionChanged(re); emit q->changed(); } diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp index b67335822b..e4edd2f6ef 100644 --- a/src/widgets/dialogs/qfilesystemmodel.cpp +++ b/src/widgets/dialogs/qfilesystemmodel.cpp @@ -2032,10 +2032,8 @@ bool QFileSystemModelPrivate::passNameFilters(const QFileSystemNode *node) const : QRegularExpression::CaseInsensitiveOption; for (const auto &nameFilter : nameFilters) { - const QString wildcard = QLatin1String("\\A(?:") - + QRegularExpression::wildcardToRegularExpression(nameFilter) - + QLatin1String(")\\z"); - QRegularExpression rx(wildcard, options); + const QString wildcard = QRegularExpression::wildcardToRegularExpression(nameFilter); + QRegularExpression rx(QRegularExpression::anchoredPattern(wildcard), options); QRegularExpressionMatch match = rx.match(node->fileName); if (match.hasMatch()) return true; -- cgit v1.2.3 From 346c15102b14c58b8aaeed2c1586cd3100200e28 Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Tue, 31 Jul 2018 16:58:21 +0200 Subject: Add support for QRegularExpression to QSortFilterProxyModel This patch implements the support for QRegularExpression in QSortFilterProxyModel. [ChangeLog][QtCore][QSFPM] QSortFilterProxyModel now supports QRegularExpression. Task-number: QTBUG-46810 Change-Id: If932d55f98f9b8bcf3a72c03ffd51da52cb50ad1 Reviewed-by: Christian Ehrlicher Reviewed-by: Luca Beldi Reviewed-by: David Faure --- src/corelib/itemmodels/qsortfilterproxymodel.cpp | 234 +- src/corelib/itemmodels/qsortfilterproxymodel.h | 10 + tests/auto/corelib/itemmodels/itemmodels.pro | 3 +- .../itemmodels/qsortfilterproxymodel/.gitignore | 1 - .../qsortfilterproxymodel.pro | 9 - .../tst_qsortfilterproxymodel.cpp | 4750 -------------------- .../tst_qsortfilterproxymodel.cpp | 4665 +++++++++++++++++++ .../tst_qsortfilterproxymodel.h | 183 + .../qsortfilterproxymodel_regexp/.gitignore | 1 + .../qsortfilterproxymodel_regexp.pro | 16 + .../tst_qsortfilterproxymodel_regexp.cpp | 59 + .../.gitignore | 1 + .../qsortfilterproxymodel_regularexpression.pro | 16 + ...tst_qsortfilterproxymodel_regularexpression.cpp | 59 + 14 files changed, 5227 insertions(+), 4780 deletions(-) delete mode 100644 tests/auto/corelib/itemmodels/qsortfilterproxymodel/.gitignore delete mode 100644 tests/auto/corelib/itemmodels/qsortfilterproxymodel/qsortfilterproxymodel.pro delete mode 100644 tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp create mode 100644 tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp create mode 100644 tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.h create mode 100644 tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/.gitignore create mode 100644 tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/qsortfilterproxymodel_regexp.pro create mode 100644 tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/tst_qsortfilterproxymodel_regexp.cpp create mode 100644 tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/.gitignore create mode 100644 tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/qsortfilterproxymodel_regularexpression.pro create mode 100644 tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/tst_qsortfilterproxymodel_regularexpression.cpp diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp index 8312318e4c..d8b4c8cc97 100644 --- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp +++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -146,6 +147,133 @@ private: int end; }; +class RegularExpressionData { + +private: + enum class ExpressionType { + RegExp, +#if QT_CONFIG(regularexpression) + RegularExpression +#endif + }; + +public: + RegularExpressionData() : + m_type(ExpressionType::RegExp) + {} + +#if QT_CONFIG(regularexpression) + QRegularExpression regularExpression() const + { + if (m_type == ExpressionType::RegularExpression) + return m_regularExpression; + return QRegularExpression(); + } + + void setRegularExpression(const QRegularExpression &rx) + { + m_type = ExpressionType::RegularExpression; + m_regularExpression = rx; + m_regExp = QRegExp(); + } +#endif + + QRegExp regExp() const + { + if (m_type == ExpressionType::RegExp) + return m_regExp; + return QRegExp(); + } + + void setRegExp(const QRegExp &rx) + { + m_type = ExpressionType::RegExp; + m_regExp = rx; +#if QT_CONFIG(regularexpression) + m_regularExpression = QRegularExpression(); +#endif + + } + + bool isEmpty() const + { + bool result = true; + switch (m_type) { + case ExpressionType::RegExp: + result = m_regExp.isEmpty(); + break; +#if QT_CONFIG(regularexpression) + case ExpressionType::RegularExpression: + result = m_regularExpression.pattern().isEmpty(); + break; +#endif + } + return result; + } + + Qt::CaseSensitivity caseSensitivity() const + { + Qt::CaseSensitivity sensitivity = Qt::CaseInsensitive; + switch (m_type) { + case ExpressionType::RegExp: + sensitivity = m_regExp.caseSensitivity(); + break; +#if QT_CONFIG(regularexpression) + case ExpressionType::RegularExpression: + { + QRegularExpression::PatternOptions options = m_regularExpression.patternOptions(); + if (!(options & QRegularExpression::CaseInsensitiveOption)) + sensitivity = Qt::CaseSensitive; + } + break; +#endif + } + return sensitivity; + } + + void setCaseSensitivity(Qt::CaseSensitivity cs) + { + switch (m_type) { + case ExpressionType::RegExp: + m_regExp.setCaseSensitivity(cs); + break; +#if QT_CONFIG(regularexpression) + case ExpressionType::RegularExpression: + { + QRegularExpression::PatternOptions options = m_regularExpression.patternOptions(); + options.setFlag(QRegularExpression::CaseInsensitiveOption, cs == Qt::CaseSensitive); + m_regularExpression.setPatternOptions(options); + } + break; +#endif + } + } + + bool hasMatch(const QString &str) const + { + bool result = false; + switch (m_type) { + case ExpressionType::RegExp: + result = str.contains(m_regExp); + break; +#if QT_CONFIG(regularexpression) + case ExpressionType::RegularExpression: + result = str.contains(m_regularExpression); + break; +#endif + } + return result; + } + +private: + ExpressionType m_type; + QRegExp m_regExp; +#if QT_CONFIG(regularexpression) + QRegularExpression m_regularExpression; +#endif +}; + + class QSortFilterProxyModelPrivate : public QAbstractProxyModelPrivate { Q_DECLARE_PUBLIC(QSortFilterProxyModel) @@ -171,7 +299,7 @@ public: int filter_column; int filter_role; - QRegExp filter_regexp; + RegularExpressionData filter_data; QModelIndex last_top_source; bool filter_recursive; @@ -1109,7 +1237,7 @@ void QSortFilterProxyModelPrivate::update_persistent_indexes( */ void QSortFilterProxyModelPrivate::filter_about_to_be_changed(const QModelIndex &source_parent) { - if (!filter_regexp.pattern().isEmpty() && + if (!filter_data.isEmpty() && source_index_mapping.constFind(source_parent) == source_index_mapping.constEnd()) create_mapping(source_parent); } @@ -1786,9 +1914,9 @@ void QSortFilterProxyModelPrivate::_q_sourceColumnsMoved( If a parent item doesn't match the filter, none of its children will be shown. - A common use case is to let the user specify the filter regexp, wildcard - pattern, or fixed string in a QLineEdit and to connect the - \l{QLineEdit::textChanged()}{textChanged()} signal to setFilterRegExp(), + A common use case is to let the user specify the filter regular expression, + wildcard pattern, or fixed string in a QLineEdit and to connect the + \l{QLineEdit::textChanged()}{textChanged()} signal to setFilterRegularExpression(), setFilterWildcard(), or setFilterFixedString() to reapply the filter. Custom filtering behavior can be achieved by reimplementing the @@ -1825,6 +1953,21 @@ void QSortFilterProxyModelPrivate::_q_sourceColumnsMoved( \note Some general guidelines for subclassing models are available in the \l{Model Subclassing Reference}. + \note With Qt 5, regular expression support has been improved through the + QRegularExpression class. QSortFilterProxyModel dating back prior to that + class creation, it originally supported only QRegExp. Since Qt 5.12, + QRegularExpression APIs have been added. Therefore, QRegExp APIs should be + considered deprecated and the QRegularExpression version should be used in + place. + + \warning Don't mix calls to the getters and setters of different regexp types + as this will lead to unexpected results. For maximum compatibility, the original + implementation has been kept. Therefore, if, for example, a call to + setFilterRegularExpression is made followed by another one to + setFilterFixedString, the first call will setup a QRegularExpression object + to use as filter while the second will setup a QRegExp in FixedString mode. + However, this is an implementation detail that might change in the future. + \sa QAbstractProxyModel, QAbstractItemModel, {Model/View Programming}, {Basic Sort/Filter Model Example}, {Custom Sort/Filter Model Example}, QIdentityProxyModel */ @@ -2437,16 +2580,46 @@ Qt::SortOrder QSortFilterProxyModel::sortOrder() const QRegExp QSortFilterProxyModel::filterRegExp() const { Q_D(const QSortFilterProxyModel); - return d->filter_regexp; + return d->filter_data.regExp(); } void QSortFilterProxyModel::setFilterRegExp(const QRegExp ®Exp) { Q_D(QSortFilterProxyModel); d->filter_about_to_be_changed(); - d->filter_regexp = regExp; + d->filter_data.setRegExp(regExp); + d->filter_changed(); +} + +#if QT_CONFIG(regularexpression) +/*! + \since 5.12 + \property QSortFilterProxyModel::filterRegularExpression + \brief the QRegularExpression used to filter the contents of the source model + + Setting this property overwrites the current + \l{QSortFilterProxyModel::filterCaseSensitivity}{filterCaseSensitivity}. + By default, the QRegularExpression is an empty string matching all contents. + + If no QRegularExpression or an empty string is set, everything in the source + model will be accepted. + + \sa filterCaseSensitivity, setFilterWildcard(), setFilterFixedString() +*/ +QRegularExpression QSortFilterProxyModel::filterRegularExpression() const +{ + Q_D(const QSortFilterProxyModel); + return d->filter_data.regularExpression(); +} + +void QSortFilterProxyModel::setFilterRegularExpression(const QRegularExpression ®ularExpression) +{ + Q_D(QSortFilterProxyModel); + d->filter_about_to_be_changed(); + d->filter_data.setRegularExpression(regularExpression); d->filter_changed(); } +#endif /*! \property QSortFilterProxyModel::filterKeyColumn @@ -2483,16 +2656,16 @@ void QSortFilterProxyModel::setFilterKeyColumn(int column) Qt::CaseSensitivity QSortFilterProxyModel::filterCaseSensitivity() const { Q_D(const QSortFilterProxyModel); - return d->filter_regexp.caseSensitivity(); + return d->filter_data.caseSensitivity(); } void QSortFilterProxyModel::setFilterCaseSensitivity(Qt::CaseSensitivity cs) { Q_D(QSortFilterProxyModel); - if (cs == d->filter_regexp.caseSensitivity()) + if (cs == d->filter_data.caseSensitivity()) return; d->filter_about_to_be_changed(); - d->filter_regexp.setCaseSensitivity(cs); + d->filter_data.setCaseSensitivity(cs); d->filter_changed(); } @@ -2558,11 +2731,33 @@ void QSortFilterProxyModel::setFilterRegExp(const QString &pattern) { Q_D(QSortFilterProxyModel); d->filter_about_to_be_changed(); - d->filter_regexp.setPatternSyntax(QRegExp::RegExp); - d->filter_regexp.setPattern(pattern); + QRegExp rx(pattern); + d->filter_data.setRegExp(rx); d->filter_changed(); } +#if QT_CONFIG(regularexpression) +/*! + \since 5.12 + + Sets the regular expression used to filter the contents + of the source model to \a pattern. + + This method should be preferred for new code as it will use + QRegularExpression internally. + + \sa setFilterCaseSensitivity(), setFilterWildcard(), setFilterFixedString(), filterRegularExpression() +*/ +void QSortFilterProxyModel::setFilterRegularExpression(const QString &pattern) +{ + Q_D(QSortFilterProxyModel); + d->filter_about_to_be_changed(); + QRegularExpression rx(pattern); + d->filter_data.setRegularExpression(rx); + d->filter_changed(); +} +#endif + /*! Sets the wildcard expression used to filter the contents of the source model to the given \a pattern. @@ -2573,8 +2768,8 @@ void QSortFilterProxyModel::setFilterWildcard(const QString &pattern) { Q_D(QSortFilterProxyModel); d->filter_about_to_be_changed(); - d->filter_regexp.setPatternSyntax(QRegExp::Wildcard); - d->filter_regexp.setPattern(pattern); + QRegExp rx(pattern, d->filter_data.caseSensitivity(), QRegExp::Wildcard); + d->filter_data.setRegExp(rx); d->filter_changed(); } @@ -2588,8 +2783,8 @@ void QSortFilterProxyModel::setFilterFixedString(const QString &pattern) { Q_D(QSortFilterProxyModel); d->filter_about_to_be_changed(); - d->filter_regexp.setPatternSyntax(QRegExp::FixedString); - d->filter_regexp.setPattern(pattern); + QRegExp rx(pattern, d->filter_data.caseSensitivity(), QRegExp::FixedString); + d->filter_data.setRegExp(rx); d->filter_changed(); } @@ -2814,14 +3009,15 @@ bool QSortFilterProxyModel::lessThan(const QModelIndex &source_left, const QMode bool QSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { Q_D(const QSortFilterProxyModel); - if (d->filter_regexp.isEmpty()) + + if (d->filter_data.isEmpty()) return true; if (d->filter_column == -1) { int column_count = d->model->columnCount(source_parent); for (int column = 0; column < column_count; ++column) { QModelIndex source_index = d->model->index(source_row, column, source_parent); QString key = d->model->data(source_index, d->filter_role).toString(); - if (key.contains(d->filter_regexp)) + if (d->filter_data.hasMatch(key)) return true; } return false; @@ -2830,7 +3026,7 @@ bool QSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex & if (!source_index.isValid()) // the column may not exist return true; QString key = d->model->data(source_index, d->filter_role).toString(); - return key.contains(d->filter_regexp); + return d->filter_data.hasMatch(key); } /*! diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.h b/src/corelib/itemmodels/qsortfilterproxymodel.h index 907ceb8e6d..0b7c69f37d 100644 --- a/src/corelib/itemmodels/qsortfilterproxymodel.h +++ b/src/corelib/itemmodels/qsortfilterproxymodel.h @@ -42,6 +42,7 @@ #include #include +#include QT_REQUIRE_CONFIG(sortfilterproxymodel); @@ -59,6 +60,9 @@ class Q_CORE_EXPORT QSortFilterProxyModel : public QAbstractProxyModel Q_OBJECT Q_PROPERTY(QRegExp filterRegExp READ filterRegExp WRITE setFilterRegExp) +#if QT_CONFIG(regularexpression) + Q_PROPERTY(QRegularExpression filterRegularExpression READ filterRegularExpression WRITE setFilterRegularExpression) +#endif Q_PROPERTY(int filterKeyColumn READ filterKeyColumn WRITE setFilterKeyColumn) Q_PROPERTY(bool dynamicSortFilter READ dynamicSortFilter WRITE setDynamicSortFilter) Q_PROPERTY(Qt::CaseSensitivity filterCaseSensitivity READ filterCaseSensitivity WRITE setFilterCaseSensitivity) @@ -83,6 +87,9 @@ public: QRegExp filterRegExp() const; void setFilterRegExp(const QRegExp ®Exp); + QRegularExpression filterRegularExpression() const; + void setFilterRegularExpression(const QRegularExpression ®ularExpression); + int filterKeyColumn() const; void setFilterKeyColumn(int column); @@ -112,6 +119,9 @@ public: public Q_SLOTS: void setFilterRegExp(const QString &pattern); +#if QT_CONFIG(regularexpression) + void setFilterRegularExpression(const QString &pattern); +#endif void setFilterWildcard(const QString &pattern); void setFilterFixedString(const QString &pattern); #if QT_DEPRECATED_SINCE(5, 11) diff --git a/tests/auto/corelib/itemmodels/itemmodels.pro b/tests/auto/corelib/itemmodels/itemmodels.pro index a09f03a7b4..bcb6e604f8 100644 --- a/tests/auto/corelib/itemmodels/itemmodels.pro +++ b/tests/auto/corelib/itemmodels/itemmodels.pro @@ -11,7 +11,8 @@ qtHaveModule(gui): SUBDIRS += \ qtHaveModule(widgets) { SUBDIRS += \ - qsortfilterproxymodel + qsortfilterproxymodel_regexp \ + qsortfilterproxymodel_regularexpression qtHaveModule(sql): SUBDIRS += \ qitemmodel diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/.gitignore b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/.gitignore deleted file mode 100644 index d3672fe4ae..0000000000 --- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_qsortfilterproxymodel diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/qsortfilterproxymodel.pro b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/qsortfilterproxymodel.pro deleted file mode 100644 index dfa8b9fa1b..0000000000 --- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/qsortfilterproxymodel.pro +++ /dev/null @@ -1,9 +0,0 @@ -CONFIG += testcase -TARGET = tst_qsortfilterproxymodel - -QT += widgets testlib -mtdir = ../../../other/qabstractitemmodelutils - -INCLUDEPATH += $$PWD/$${mtdir} -SOURCES += tst_qsortfilterproxymodel.cpp $${mtdir}/dynamictreemodel.cpp -HEADERS += $${mtdir}/dynamictreemodel.h diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp deleted file mode 100644 index b3431bcc7a..0000000000 --- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp +++ /dev/null @@ -1,4750 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include "dynamictreemodel.h" - -#include -#include -#include -#include - -#include - -typedef QList IntList; -typedef QPair IntPair; -typedef QList IntPairList; - -Q_DECLARE_METATYPE(QList) - -class tst_QSortFilterProxyModel : public QObject -{ - Q_OBJECT -public: - tst_QSortFilterProxyModel(); - -public slots: - void initTestCase(); - void cleanupTestCase(); - void cleanup(); - -private slots: - void getSetCheck(); - void sort_data(); - void sort(); - void sortHierarchy_data(); - void sortHierarchy(); - - void insertRows_data(); - void insertRows(); - void prependRow(); - void removeRows_data(); - void removeRows(); - void removeColumns_data(); - void removeColumns(); - void insertAfterSelect(); - void removeAfterSelect(); - void filter_data(); - void filter(); - void filterHierarchy_data(); - void filterHierarchy(); - void filterColumns_data(); - void filterColumns(); - - void filterTable(); - void filterCurrent(); - void filter_qtbug30662(); - - void changeSourceLayout(); - void changeSourceLayoutFilteredOut(); - void removeSourceRows_data(); - void removeSourceRows(); - void insertSourceRows_data(); - void insertSourceRows(); - void changeFilter_data(); - void changeFilter(); - void changeSourceData_data(); - void changeSourceData(); - void changeSourceDataKeepsStableSorting_qtbug1548(); - void changeSourceDataForwardsRoles_qtbug35440(); - void resortingDoesNotBreakTreeModels(); - void dynamicFilterWithoutSort(); - void sortFilterRole(); - void selectionFilteredOut(); - void match_data(); - void match(); - void insertIntoChildrenlessItem(); - void invalidateMappedChildren(); - void insertRowIntoFilteredParent(); - void filterOutParentAndFilterInChild(); - - void sourceInsertRows(); - void sourceModelDeletion(); - - void sortColumnTracking1(); - void sortColumnTracking2(); - - void sortStable(); - - void hiddenColumns(); - void insertRowsSort(); - void staticSorting(); - void dynamicSorting(); - void fetchMore(); - void hiddenChildren(); - void mapFromToSource(); - void removeRowsRecursive(); - void doubleProxySelectionSetSourceModel(); - void appearsAndSort(); - void unnecessaryDynamicSorting(); - void unnecessaryMapCreation(); - void resetInvalidate_data(); - void resetInvalidate(); - - void testMultipleProxiesWithSelection(); - void mapSelectionFromSource(); - void testResetInternalData(); - void filteredColumns(); - void headerDataChanged(); - - void testParentLayoutChanged(); - void moveSourceRows(); - - void hierarchyFilterInvalidation(); - void simpleFilterInvalidation(); - - void chainedProxyModelRoleNames(); - - void noMapAfterSourceDelete(); - void forwardDropApi(); - void canDropMimeData(); - void filterHint(); - - void sourceLayoutChangeLeavesValidPersistentIndexes(); - void rowMoveLeavesValidPersistentIndexes(); - - void emitLayoutChangedOnlyIfSortingChanged_data(); - void emitLayoutChangedOnlyIfSortingChanged(); - - void checkSetNewModel(); - - void removeIntervals_data(); - void removeIntervals(); - -protected: - void buildHierarchy(const QStringList &data, QAbstractItemModel *model); - void checkHierarchy(const QStringList &data, const QAbstractItemModel *model); - -private: - QStandardItemModel *m_model; - QSortFilterProxyModel *m_proxy; -}; - -Q_DECLARE_METATYPE(QAbstractItemModel::LayoutChangeHint) - -// Testing get/set functions -void tst_QSortFilterProxyModel::getSetCheck() -{ - QSortFilterProxyModel obj1; - QCOMPARE(obj1.sourceModel(), (QAbstractItemModel *)0); - // int QSortFilterProxyModel::filterKeyColumn() - // void QSortFilterProxyModel::setFilterKeyColumn(int) - obj1.setFilterKeyColumn(0); - QCOMPARE(0, obj1.filterKeyColumn()); - obj1.setFilterKeyColumn(INT_MIN); - QCOMPARE(INT_MIN, obj1.filterKeyColumn()); - obj1.setFilterKeyColumn(INT_MAX); - QCOMPARE(INT_MAX, obj1.filterKeyColumn()); -} - -tst_QSortFilterProxyModel::tst_QSortFilterProxyModel() - : m_model(0), m_proxy(0) -{ - qRegisterMetaType(); -} - -void tst_QSortFilterProxyModel::initTestCase() -{ - qRegisterMetaType >(); - m_model = new QStandardItemModel(0, 1); - m_proxy = new QSortFilterProxyModel(); - m_proxy->setSourceModel(m_model); -} - -void tst_QSortFilterProxyModel::cleanupTestCase() -{ - delete m_proxy; - delete m_model; -} - -void tst_QSortFilterProxyModel::cleanup() -{ - m_proxy->setFilterRegExp(QRegExp()); - m_proxy->sort(-1, Qt::AscendingOrder); - m_model->clear(); - m_model->insertColumns(0, 1); -} - -/* - tests -*/ - -void tst_QSortFilterProxyModel::sort_data() -{ - QTest::addColumn("sortOrder"); - QTest::addColumn("sortCaseSensitivity"); - QTest::addColumn("initial"); - QTest::addColumn("expected"); - - QTest::newRow("flat descending") << static_cast(Qt::DescendingOrder) - << int(Qt::CaseSensitive) - << (QStringList() - << "delta" - << "yankee" - << "bravo" - << "lima" - << "charlie" - << "juliet" - << "tango" - << "hotel" - << "uniform" - << "alpha" - << "echo" - << "golf" - << "quebec" - << "foxtrot" - << "india" - << "romeo" - << "november" - << "oskar" - << "zulu" - << "kilo" - << "whiskey" - << "mike" - << "papa" - << "sierra" - << "xray" - << "viktor") - << (QStringList() - << "zulu" - << "yankee" - << "xray" - << "whiskey" - << "viktor" - << "uniform" - << "tango" - << "sierra" - << "romeo" - << "quebec" - << "papa" - << "oskar" - << "november" - << "mike" - << "lima" - << "kilo" - << "juliet" - << "india" - << "hotel" - << "golf" - << "foxtrot" - << "echo" - << "delta" - << "charlie" - << "bravo" - << "alpha"); - QTest::newRow("flat ascending") << static_cast(Qt::AscendingOrder) - << int(Qt::CaseSensitive) - << (QStringList() - << "delta" - << "yankee" - << "bravo" - << "lima" - << "charlie" - << "juliet" - << "tango" - << "hotel" - << "uniform" - << "alpha" - << "echo" - << "golf" - << "quebec" - << "foxtrot" - << "india" - << "romeo" - << "november" - << "oskar" - << "zulu" - << "kilo" - << "whiskey" - << "mike" - << "papa" - << "sierra" - << "xray" - << "viktor") - << (QStringList() - << "alpha" - << "bravo" - << "charlie" - << "delta" - << "echo" - << "foxtrot" - << "golf" - << "hotel" - << "india" - << "juliet" - << "kilo" - << "lima" - << "mike" - << "november" - << "oskar" - << "papa" - << "quebec" - << "romeo" - << "sierra" - << "tango" - << "uniform" - << "viktor" - << "whiskey" - << "xray" - << "yankee" - << "zulu"); - QTest::newRow("case insensitive") << static_cast(Qt::AscendingOrder) - << int(Qt::CaseInsensitive) - << (QStringList() - << "alpha" << "BETA" << "Gamma" << "delta") - << (QStringList() - << "alpha" << "BETA" << "delta" << "Gamma"); - QTest::newRow("case sensitive") << static_cast(Qt::AscendingOrder) - << int(Qt::CaseSensitive) - << (QStringList() - << "alpha" << "BETA" << "Gamma" << "delta") - << (QStringList() - << "BETA" << "Gamma" << "alpha" << "delta"); - - QStringList list; - for (int i = 10000; i < 20000; ++i) - list.append(QStringLiteral("Number: ") + QString::number(i)); - QTest::newRow("large set ascending") << static_cast(Qt::AscendingOrder) << int(Qt::CaseSensitive) << list << list; -} - -void tst_QSortFilterProxyModel::sort() -{ - QFETCH(int, sortOrder); - QFETCH(int, sortCaseSensitivity); - QFETCH(QStringList, initial); - QFETCH(QStringList, expected); - - // prepare model - QStandardItem *root = m_model->invisibleRootItem (); - QList items; - for (int i = 0; i < initial.count(); ++i) { - items.append(new QStandardItem(initial.at(i))); - } - root->insertRows(0, items); - QCOMPARE(m_model->rowCount(QModelIndex()), initial.count()); - QCOMPARE(m_model->columnCount(QModelIndex()), 1); - - // make sure the proxy is unsorted - QCOMPARE(m_proxy->columnCount(QModelIndex()), 1); - QCOMPARE(m_proxy->rowCount(QModelIndex()), initial.count()); - for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) { - QModelIndex index = m_proxy->index(row, 0, QModelIndex()); - QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), initial.at(row)); - } - - // sort - m_proxy->sort(0, static_cast(sortOrder)); - m_proxy->setSortCaseSensitivity(static_cast(sortCaseSensitivity)); - - // make sure the model is unchanged - for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) { - QModelIndex index = m_model->index(row, 0, QModelIndex()); - QCOMPARE(m_model->data(index, Qt::DisplayRole).toString(), initial.at(row)); - } - // make sure the proxy is sorted - for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) { - QModelIndex index = m_proxy->index(row, 0, QModelIndex()); - QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), expected.at(row)); - } - - // restore the unsorted order - m_proxy->sort(-1); - - // make sure the proxy is unsorted again - for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) { - QModelIndex index = m_proxy->index(row, 0, QModelIndex()); - QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), initial.at(row)); - } -} - -void tst_QSortFilterProxyModel::sortHierarchy_data() -{ - QTest::addColumn("sortOrder"); - QTest::addColumn("initial"); - QTest::addColumn("expected"); - - QTest::newRow("flat ascending") - << static_cast(Qt::AscendingOrder) - << (QStringList() - << "c" << "f" << "d" << "e" << "a" << "b") - << (QStringList() - << "a" << "b" << "c" << "d" << "e" << "f"); - - QTest::newRow("simple hierarchy") - << static_cast(Qt::AscendingOrder) - << (QStringList() << "a" << "<" << "b" << "<" << "c" << ">" << ">") - << (QStringList() << "a" << "<" << "b" << "<" << "c" << ">" << ">"); - - QTest::newRow("hierarchical ascending") - << static_cast(Qt::AscendingOrder) - << (QStringList() - << "c" - << "<" - << "h" - << "<" - << "2" - << "0" - << "1" - << ">" - << "g" - << "i" - << ">" - << "b" - << "<" - << "l" - << "k" - << "<" - << "8" - << "7" - << "9" - << ">" - << "m" - << ">" - << "a" - << "<" - << "z" - << "y" - << "x" - << ">") - << (QStringList() - << "a" - << "<" - << "x" - << "y" - << "z" - << ">" - << "b" - << "<" - << "k" - << "<" - << "7" - << "8" - << "9" - << ">" - << "l" - << "m" - << ">" - << "c" - << "<" - << "g" - << "h" - << "<" - << "0" - << "1" - << "2" - << ">" - << "i" - << ">"); -} - -void tst_QSortFilterProxyModel::sortHierarchy() -{ - QFETCH(int, sortOrder); - QFETCH(QStringList, initial); - QFETCH(QStringList, expected); - - buildHierarchy(initial, m_model); - checkHierarchy(initial, m_model); - checkHierarchy(initial, m_proxy); - m_proxy->sort(0, static_cast(sortOrder)); - checkHierarchy(initial, m_model); - checkHierarchy(expected, m_proxy); -} - -void tst_QSortFilterProxyModel::insertRows_data() -{ - QTest::addColumn("initial"); - QTest::addColumn("expected"); - QTest::addColumn("insert"); - QTest::addColumn("position"); - - QTest::newRow("insert one row in the middle") - << (QStringList() - << "One" - << "Two" - << "Four" - << "Five") - << (QStringList() - << "One" - << "Two" - << "Three" - << "Four" - << "Five") - << (QStringList() - << "Three") - << 2; - - QTest::newRow("insert one row in the beginning") - << (QStringList() - << "Two" - << "Three" - << "Four" - << "Five") - << (QStringList() - << "One" - << "Two" - << "Three" - << "Four" - << "Five") - << (QStringList() - << "One") - << 0; - - QTest::newRow("insert one row in the end") - << (QStringList() - << "One" - << "Two" - << "Three" - << "Four") - << (QStringList() - << "One" - << "Two" - << "Three" - << "Four" - << "Five") - << (QStringList() - <<"Five") - << 4; -} - -void tst_QSortFilterProxyModel::insertRows() -{ - QFETCH(QStringList, initial); - QFETCH(QStringList, expected); - QFETCH(QStringList, insert); - QFETCH(int, position); - // prepare model - m_model->insertRows(0, initial.count(), QModelIndex()); - //m_model->insertColumns(0, 1, QModelIndex()); - QCOMPARE(m_model->columnCount(QModelIndex()), 1); - QCOMPARE(m_model->rowCount(QModelIndex()), initial.count()); - for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) { - QModelIndex index = m_model->index(row, 0, QModelIndex()); - m_model->setData(index, initial.at(row), Qt::DisplayRole); - } - // make sure the model correct before insert - for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) { - QModelIndex index = m_model->index(row, 0, QModelIndex()); - QCOMPARE(m_model->data(index, Qt::DisplayRole).toString(), initial.at(row)); - } - // make sure the proxy is correct before insert - for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) { - QModelIndex index = m_proxy->index(row, 0, QModelIndex()); - QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), initial.at(row)); - } - - // insert the row - m_proxy->insertRows(position, insert.count(), QModelIndex()); - QCOMPARE(m_model->rowCount(QModelIndex()), expected.count()); - QCOMPARE(m_proxy->rowCount(QModelIndex()), expected.count()); - - // set the data for the inserted row - for (int i = 0; i < insert.count(); ++i) { - QModelIndex index = m_proxy->index(position + i, 0, QModelIndex()); - m_proxy->setData(index, insert.at(i), Qt::DisplayRole); - } - - // make sure the model correct after insert - for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) { - QModelIndex index = m_model->index(row, 0, QModelIndex()); - QCOMPARE(m_model->data(index, Qt::DisplayRole).toString(), expected.at(row)); - } - - // make sure the proxy is correct after insert - for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) { - QModelIndex index = m_proxy->index(row, 0, QModelIndex()); - QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), expected.at(row)); - } -} - -void tst_QSortFilterProxyModel::prependRow() -{ - //this tests that data is correctly handled by the sort filter when prepending a row - QStandardItemModel model; - QSortFilterProxyModel proxy; - proxy.setSourceModel(&model); - - QStandardItem item("root"); - model.appendRow(&item); - - QStandardItem sub("sub"); - item.appendRow(&sub); - - sub.appendRow(new QStandardItem("test1")); - sub.appendRow(new QStandardItem("test2")); - - QStandardItem sub2("sub2"); - sub2.appendRow(new QStandardItem("sub3")); - item.insertRow(0, &sub2); - - QModelIndex index_sub2 = proxy.mapFromSource(model.indexFromItem(&sub2)); - - QCOMPARE(sub2.rowCount(), proxy.rowCount(index_sub2)); - QCOMPARE(proxy.rowCount(QModelIndex()), 1); //only the "root" item is there -} - -void tst_QSortFilterProxyModel::removeRows_data() -{ - QTest::addColumn("initial"); - QTest::addColumn("sortOrder"); - QTest::addColumn("filter"); - QTest::addColumn("position"); - QTest::addColumn("count"); - QTest::addColumn("success"); - QTest::addColumn("expectedProxy"); - QTest::addColumn("expectedSource"); - - QTest::newRow("remove one row in the middle [no sorting/filter]") - << (QStringList() - << "One" - << "Two" - << "Three" - << "Four" - << "Five") - << -1 // no sorting - << QString() // no filter - << 2 // position - << 1 // count - << true // success - << (QStringList() // expectedProxy - << "One" - << "Two" - << "Four" - << "Five") - << (QStringList() // expectedSource - << "One" - << "Two" - << "Four" - << "Five"); - - QTest::newRow("remove one row in the beginning [no sorting/filter]") - << (QStringList() - << "One" - << "Two" - << "Three" - << "Four" - << "Five") - << -1 // no sorting - << QString() // no filter - << 0 // position - << 1 // count - << true // success - << (QStringList() // expectedProxy - << "Two" - << "Three" - << "Four" - << "Five") - << (QStringList() // expectedSource - << "Two" - << "Three" - << "Four" - << "Five"); - - QTest::newRow("remove one row in the end [no sorting/filter]") - << (QStringList() - << "One" - << "Two" - << "Three" - << "Four" - << "Five") - << -1 // no sorting - << QString() // no filter - << 4 // position - << 1 // count - << true // success - << (QStringList() // expectedProxy - << "One" - << "Two" - << "Three" - << "Four") - << (QStringList() // expectedSource - << "One" - << "Two" - << "Three" - << "Four"); - - QTest::newRow("remove all [no sorting/filter]") - << (QStringList() - << "One" - << "Two" - << "Three" - << "Four" - << "Five") - << -1 // no sorting - << QString() // no filter - << 0 // position - << 5 // count - << true // success - << QStringList() // expectedProxy - << QStringList(); // expectedSource - - QTest::newRow("remove one row past the end [no sorting/filter]") - << (QStringList() - << "One" - << "Two" - << "Three" - << "Four" - << "Five") - << -1 // no sorting - << QString() // no filter - << 5 // position - << 1 // count - << false // success - << (QStringList() // expectedProxy - << "One" - << "Two" - << "Three" - << "Four" - << "Five") - << (QStringList() // expectedSource - << "One" - << "Two" - << "Three" - << "Four" - << "Five"); - - QTest::newRow("remove row -1 [no sorting/filter]") - << (QStringList() - << "One" - << "Two" - << "Three" - << "Four" - << "Five") - << -1 // no sorting - << QString() // no filter - << -1 // position - << 1 // count - << false // success - << (QStringList() // expectedProxy - << "One" - << "Two" - << "Three" - << "Four" - << "Five") - << (QStringList() // expectedSource - << "One" - << "Two" - << "Three" - << "Four" - << "Five"); - - QTest::newRow("remove three rows in the middle [no sorting/filter]") - << (QStringList() - << "One" - << "Two" - << "Three" - << "Four" - << "Five") - << -1 // no sorting - << QString() // no filter - << 1 // position - << 3 // count - << true // success - << (QStringList() // expectedProxy - << "One" - << "Five") - << (QStringList() // expectedSource - << "One" - << "Five"); - - QTest::newRow("remove one row in the middle [ascending sorting, no filter]") - << (QStringList() - << "1" - << "5" - << "2" - << "4" - << "3") - << static_cast(Qt::AscendingOrder) - << QString() // no filter - << 2 // position - << 1 // count - << true // success - << (QStringList() // expectedProxy - << "1" - << "2" - << "4" - << "5") - << (QStringList() // expectedSource - << "1" - << "5" - << "2" - << "4"); - - QTest::newRow("remove two rows in the middle [ascending sorting, no filter]") - << (QStringList() - << "1" - << "5" - << "2" - << "4" - << "3") - << static_cast(Qt::AscendingOrder) - << QString() // no filter - << 2 // position - << 2 // count - << true // success - << (QStringList() // expectedProxy - << "1" - << "2" - << "5") - << (QStringList() // expectedSource - << "1" - << "5" - << "2"); - - QTest::newRow("remove two rows in the middle [descending sorting, no filter]") - << (QStringList() - << "1" - << "5" - << "2" - << "4" - << "3") - << static_cast(Qt::DescendingOrder) - << QString() // no filter - << 2 // position - << 2 // count - << true // success - << (QStringList() // expectedProxy - << "5" - << "4" - << "1") - << (QStringList() // expectedSource - << "1" - << "5" - << "4"); - - QTest::newRow("remove one row in the middle [no sorting, filter=5|2|3]") - << (QStringList() - << "1" - << "5" - << "2" - << "4" - << "3") - << -1 // no sorting - << QString("5|2|3") - << 1 // position - << 1 // count - << true // success - << (QStringList() // expectedProxy - << "5" - << "3") - << (QStringList() // expectedSource - << "1" - << "5" - << "4" - << "3"); - - QTest::newRow("remove all [ascending sorting, no filter]") - << (QStringList() - << "1" - << "5" - << "2" - << "4" - << "3") - << static_cast(Qt::AscendingOrder) - << QString() // no filter - << 0 // position - << 5 // count - << true // success - << QStringList() // expectedProxy - << QStringList(); // expectedSource -} - -void tst_QSortFilterProxyModel::removeRows() -{ - QFETCH(QStringList, initial); - QFETCH(int, sortOrder); - QFETCH(QString, filter); - QFETCH(int, position); - QFETCH(int, count); - QFETCH(bool, success); - QFETCH(QStringList, expectedProxy); - QFETCH(QStringList, expectedSource); - - QStandardItemModel model; - QSortFilterProxyModel proxy; - proxy.setSourceModel(&model); - - // prepare model - foreach (QString s, initial) - model.appendRow(new QStandardItem(s)); - - if (sortOrder != -1) - proxy.sort(0, static_cast(sortOrder)); - if (!filter.isEmpty()) - proxy.setFilterRegExp(QRegExp(filter)); - - // remove the rows - QCOMPARE(proxy.removeRows(position, count, QModelIndex()), success); - QCOMPARE(model.rowCount(QModelIndex()), expectedSource.count()); - QCOMPARE(proxy.rowCount(QModelIndex()), expectedProxy.count()); - - // make sure the model is correct after remove - for (int row = 0; row < model.rowCount(QModelIndex()); ++row) - QCOMPARE(model.item(row)->text(), expectedSource.at(row)); - - // make sure the proxy is correct after remove - for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) { - QModelIndex index = proxy.index(row, 0, QModelIndex()); - QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expectedProxy.at(row)); - } -} - -class MyFilteredColumnProxyModel : public QSortFilterProxyModel -{ - Q_OBJECT -public: - MyFilteredColumnProxyModel(QObject *parent = 0) - : QSortFilterProxyModel(parent) { } -protected: - bool filterAcceptsColumn(int sourceColumn, const QModelIndex &) const - { - QString key = sourceModel()->headerData(sourceColumn, Qt::Horizontal).toString(); - return key.contains(filterRegExp()); - } -}; - -void tst_QSortFilterProxyModel::removeColumns_data() -{ - QTest::addColumn("initial"); - QTest::addColumn("filter"); - QTest::addColumn("position"); - QTest::addColumn("count"); - QTest::addColumn("success"); - QTest::addColumn("expectedProxy"); - QTest::addColumn("expectedSource"); - - QTest::newRow("remove one column in the middle [no filter]") - << (QStringList() - << "1" - << "2" - << "3" - << "4" - << "5") - << QString() // no filter - << 2 // position - << 1 // count - << true // success - << (QStringList() // expectedProxy - << "1" - << "2" - << "4" - << "5") - << (QStringList() // expectedSource - << "1" - << "2" - << "4" - << "5"); - - QTest::newRow("remove one column in the end [no filter]") - << (QStringList() - << "1" - << "2" - << "3" - << "4" - << "5") - << QString() // no filter - << 4 // position - << 1 // count - << true // success - << (QStringList() // expectedProxy - << "1" - << "2" - << "3" - << "4") - << (QStringList() // expectedSource - << "1" - << "2" - << "3" - << "4"); - - QTest::newRow("remove one column past the end [no filter]") - << (QStringList() - << "1" - << "2" - << "3" - << "4" - << "5") - << QString() // no filter - << 5 // position - << 1 // count - << false // success - << (QStringList() // expectedProxy - << "1" - << "2" - << "3" - << "4" - << "5") - << (QStringList() // expectedSource - << "1" - << "2" - << "3" - << "4" - << "5"); - - QTest::newRow("remove column -1 [no filter]") - << (QStringList() - << "1" - << "2" - << "3" - << "4" - << "5") - << QString() // no filter - << -1 // position - << 1 // count - << false // success - << (QStringList() // expectedProxy - << "1" - << "2" - << "3" - << "4" - << "5") - << (QStringList() // expectedSource - << "1" - << "2" - << "3" - << "4" - << "5"); - - QTest::newRow("remove all columns [no filter]") - << (QStringList() - << "1" - << "2" - << "3" - << "4" - << "5") - << QString() // no filter - << 0 // position - << 5 // count - << true // success - << QStringList() // expectedProxy - << QStringList(); // expectedSource - - QTest::newRow("remove one column in the middle [filter=1|3|5]") - << (QStringList() - << "1" - << "2" - << "3" - << "4" - << "5") - << QString("1|3|5") - << 1 // position - << 1 // count - << true // success - << (QStringList() // expectedProxy - << "1" - << "5") - << (QStringList() // expectedSource - << "1" - << "2" - << "4" - << "5"); - - QTest::newRow("remove one column in the end [filter=1|3|5]") - << (QStringList() - << "1" - << "2" - << "3" - << "4" - << "5") - << QString("1|3|5") - << 2 // position - << 1 // count - << true // success - << (QStringList() // expectedProxy - << "1" - << "3") - << (QStringList() // expectedSource - << "1" - << "2" - << "3" - << "4"); - - QTest::newRow("remove one column past the end [filter=1|3|5]") - << (QStringList() - << "1" - << "2" - << "3" - << "4" - << "5") - << QString("1|3|5") - << 3 // position - << 1 // count - << false // success - << (QStringList() // expectedProxy - << "1" - << "3" - << "5") - << (QStringList() // expectedSource - << "1" - << "2" - << "3" - << "4" - << "5"); - - QTest::newRow("remove all columns [filter=1|3|5]") - << (QStringList() - << "1" - << "2" - << "3" - << "4" - << "5") - << QString("1|3|5") - << 0 // position - << 3 // count - << true // success - << QStringList() // expectedProxy - << (QStringList() // expectedSource - << "2" - << "4"); -} - -void tst_QSortFilterProxyModel::removeColumns() -{ - QFETCH(QStringList, initial); - QFETCH(QString, filter); - QFETCH(int, position); - QFETCH(int, count); - QFETCH(bool, success); - QFETCH(QStringList, expectedProxy); - QFETCH(QStringList, expectedSource); - - QStandardItemModel model; - MyFilteredColumnProxyModel proxy; - proxy.setSourceModel(&model); - if (!filter.isEmpty()) - proxy.setFilterRegExp(QRegExp(filter)); - - // prepare model - model.setHorizontalHeaderLabels(initial); - - // remove the columns - QCOMPARE(proxy.removeColumns(position, count, QModelIndex()), success); - QCOMPARE(model.columnCount(QModelIndex()), expectedSource.count()); - QCOMPARE(proxy.columnCount(QModelIndex()), expectedProxy.count()); - - // make sure the model is correct after remove - for (int col = 0; col < model.columnCount(QModelIndex()); ++col) - QCOMPARE(model.horizontalHeaderItem(col)->text(), expectedSource.at(col)); - - // make sure the proxy is correct after remove - for (int col = 0; col < proxy.columnCount(QModelIndex()); ++col) { - QCOMPARE(proxy.headerData(col, Qt::Horizontal, Qt::DisplayRole).toString(), - expectedProxy.at(col)); - } -} - -void tst_QSortFilterProxyModel::filterColumns_data() -{ - QTest::addColumn("pattern"); - QTest::addColumn("initial"); - QTest::addColumn("data"); - - QTest::newRow("all") << "a" - << (QStringList() - << "delta" - << "yankee" - << "bravo" - << "lima") - << true; - - QTest::newRow("some") << "lie" - << (QStringList() - << "charlie" - << "juliet" - << "tango" - << "hotel") - << true; - - QTest::newRow("nothing") << "zoo" - << (QStringList() - << "foxtrot" - << "uniform" - << "alpha" - << "golf") - << false; -} - -void tst_QSortFilterProxyModel::filterColumns() -{ - QFETCH(QString, pattern); - QFETCH(QStringList, initial); - QFETCH(bool, data); - // prepare model - m_model->setColumnCount(initial.count()); - m_model->setRowCount(1); - QCOMPARE(m_model->columnCount(QModelIndex()), initial.count()); - QCOMPARE(m_model->rowCount(QModelIndex()), 1); - // set data - QCOMPARE(m_model->rowCount(QModelIndex()), 1); - for (int col = 0; col < m_model->columnCount(QModelIndex()); ++col) { - QModelIndex index = m_model->index(0, col, QModelIndex()); - m_model->setData(index, initial.at(col), Qt::DisplayRole); - } - m_proxy->setFilterRegExp(pattern); - m_proxy->setFilterKeyColumn(-1); - // make sure the model is unchanged - for (int col = 0; col < m_model->columnCount(QModelIndex()); ++col) { - QModelIndex index = m_model->index(0, col, QModelIndex()); - QCOMPARE(m_model->data(index, Qt::DisplayRole).toString(), initial.at(col)); - } - // make sure the proxy is filtered - QModelIndex index = m_proxy->index(0, 0, QModelIndex()); - QCOMPARE(index.isValid(), data); -} - -void tst_QSortFilterProxyModel::filter_data() -{ - QTest::addColumn("pattern"); - QTest::addColumn("initial"); - QTest::addColumn("expected"); - - QTest::newRow("flat") << "e" - << (QStringList() - << "delta" - << "yankee" - << "bravo" - << "lima" - << "charlie" - << "juliet" - << "tango" - << "hotel" - << "uniform" - << "alpha" - << "echo" - << "golf" - << "quebec" - << "foxtrot" - << "india" - << "romeo" - << "november" - << "oskar" - << "zulu" - << "kilo" - << "whiskey" - << "mike" - << "papa" - << "sierra" - << "xray" - << "viktor") - << (QStringList() - << "delta" - << "yankee" - << "charlie" - << "juliet" - << "hotel" - << "echo" - << "quebec" - << "romeo" - << "november" - << "whiskey" - << "mike" - << "sierra"); -} - -void tst_QSortFilterProxyModel::filter() -{ - QFETCH(QString, pattern); - QFETCH(QStringList, initial); - QFETCH(QStringList, expected); - // prepare model - QVERIFY(m_model->insertRows(0, initial.count(), QModelIndex())); - QCOMPARE(m_model->rowCount(QModelIndex()), initial.count()); - // set data - QCOMPARE(m_model->columnCount(QModelIndex()), 1); - for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) { - QModelIndex index = m_model->index(row, 0, QModelIndex()); - m_model->setData(index, initial.at(row), Qt::DisplayRole); - } - m_proxy->setFilterRegExp(pattern); - // make sure the proxy is unfiltered - QCOMPARE(m_proxy->columnCount(QModelIndex()), 1); - QCOMPARE(m_proxy->rowCount(QModelIndex()), expected.count()); - // make sure the model is unchanged - for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) { - QModelIndex index = m_model->index(row, 0, QModelIndex()); - QCOMPARE(m_model->data(index, Qt::DisplayRole).toString(), initial.at(row)); - } - // make sure the proxy is filtered - for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) { - QModelIndex index = m_proxy->index(row, 0, QModelIndex()); - QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), expected.at(row)); - } -} - -void tst_QSortFilterProxyModel::filterHierarchy_data() -{ - QTest::addColumn("pattern"); - QTest::addColumn("initial"); - QTest::addColumn("expected"); - - QTest::newRow("flat") << ".*oo" - << (QStringList() - << "foo" << "boo" << "baz" << "moo" << "laa" << "haa") - << (QStringList() - << "foo" << "boo" << "moo"); - - QTest::newRow("simple hierarchy") << "b.*z" - << (QStringList() << "baz" << "<" << "boz" << "<" << "moo" << ">" << ">") - << (QStringList() << "baz" << "<" << "boz" << ">"); -} - -void tst_QSortFilterProxyModel::filterHierarchy() -{ - QFETCH(QString, pattern); - QFETCH(QStringList, initial); - QFETCH(QStringList, expected); - buildHierarchy(initial, m_model); - m_proxy->setFilterRegExp(pattern); - checkHierarchy(initial, m_model); - checkHierarchy(expected, m_proxy); -} - -void tst_QSortFilterProxyModel::buildHierarchy(const QStringList &l, QAbstractItemModel *m) -{ - int ind = 0; - int row = 0; - QStack row_stack; - QModelIndex parent; - QStack parent_stack; - for (int i = 0; i < l.count(); ++i) { - QString token = l.at(i); - if (token == QLatin1String("<")) { // start table - ++ind; - parent_stack.push(parent); - row_stack.push(row); - parent = m->index(row - 1, 0, parent); - row = 0; - QVERIFY(m->insertColumns(0, 1, parent)); // add column - } else if (token == QLatin1String(">")) { // end table - --ind; - parent = parent_stack.pop(); - row = row_stack.pop(); - } else { // append row - QVERIFY(m->insertRows(row, 1, parent)); - QModelIndex index = m->index(row, 0, parent); - QVERIFY(index.isValid()); - m->setData(index, token, Qt::DisplayRole); - ++row; - } - } -} - -void tst_QSortFilterProxyModel::checkHierarchy(const QStringList &l, const QAbstractItemModel *m) -{ - int row = 0; - int indent = 0; - QStack row_stack; - QModelIndex parent; - QStack parent_stack; - for (int i = 0; i < l.count(); ++i) { - QString token = l.at(i); - if (token == QLatin1String("<")) { // start table - ++indent; - parent_stack.push(parent); - row_stack.push(row); - parent = m->index(row - 1, 0, parent); - QVERIFY(parent.isValid()); - row = 0; - } else if (token == QLatin1String(">")) { // end table - --indent; - parent = parent_stack.pop(); - row = row_stack.pop(); - } else { // compare row - QModelIndex index = m->index(row, 0, parent); - QVERIFY(index.isValid()); - QString str = m->data(index, Qt::DisplayRole).toString(); - QCOMPARE(str, token); - ++row; - } - } -} - -class TestModel: public QAbstractTableModel -{ -public: - int rowCount(const QModelIndex &) const { return 10000; } - int columnCount(const QModelIndex &) const { return 1; } - QVariant data(const QModelIndex &index, int role) const - { - if (role != Qt::DisplayRole) - return QVariant(); - return QString::number(index.row()); - } -}; - -void tst_QSortFilterProxyModel::filterTable() -{ - TestModel model; - QSortFilterProxyModel filter; - filter.setSourceModel(&model); - filter.setFilterRegExp("9"); - - for (int i = 0; i < filter.rowCount(); ++i) - QVERIFY(filter.data(filter.index(i, 0)).toString().contains(QLatin1Char('9'))); -} - -void tst_QSortFilterProxyModel::insertAfterSelect() -{ - QStandardItemModel model(10, 2); - for (int i = 0; i<10;i++) - model.setData(model.index(i, 0), QVariant(i)); - QSortFilterProxyModel filter; - filter.setSourceModel(&model); - QTreeView view; - view.setModel(&filter); - view.show(); - QModelIndex firstIndex = filter.mapFromSource(model.index(0, 0, QModelIndex())); - QCOMPARE(firstIndex.model(), (const QAbstractItemModel *)view.model()); - QVERIFY(firstIndex.isValid()); - int itemOffset = view.visualRect(firstIndex).width() / 2; - QPoint p(itemOffset, 1); - QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, p); - QVERIFY(view.selectionModel()->selectedIndexes().size() > 0); - model.insertRows(5, 1, QModelIndex()); - QVERIFY(view.selectionModel()->selectedIndexes().size() > 0); // Should still have a selection -} - -void tst_QSortFilterProxyModel::removeAfterSelect() -{ - QStandardItemModel model(10, 2); - for (int i = 0; i<10;i++) - model.setData(model.index(i, 0), QVariant(i)); - QSortFilterProxyModel filter; - filter.setSourceModel(&model); - QTreeView view; - view.setModel(&filter); - view.show(); - QModelIndex firstIndex = filter.mapFromSource(model.index(0, 0, QModelIndex())); - QCOMPARE(firstIndex.model(), (const QAbstractItemModel *)view.model()); - QVERIFY(firstIndex.isValid()); - int itemOffset = view.visualRect(firstIndex).width() / 2; - QPoint p(itemOffset, 1); - QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, p); - QVERIFY(view.selectionModel()->selectedIndexes().size() > 0); - model.removeRows(5, 1, QModelIndex()); - QVERIFY(view.selectionModel()->selectedIndexes().size() > 0); // Should still have a selection -} - -void tst_QSortFilterProxyModel::filterCurrent() -{ - QStandardItemModel model(2, 1); - model.setData(model.index(0, 0), QString("AAA")); - model.setData(model.index(1, 0), QString("BBB")); - QSortFilterProxyModel proxy; - proxy.setSourceModel(&model); - QTreeView view; - - view.show(); - view.setModel(&proxy); - QSignalSpy spy(view.selectionModel(), &QItemSelectionModel::currentChanged); - QVERIFY(spy.isValid()); - - view.setCurrentIndex(proxy.index(0, 0)); - QCOMPARE(spy.count(), 1); - proxy.setFilterRegExp(QRegExp("^B")); - QCOMPARE(spy.count(), 2); -} - -void tst_QSortFilterProxyModel::filter_qtbug30662() -{ - QStringListModel model; - QSortFilterProxyModel proxy; - proxy.setSourceModel(&model); - - // make sure the filter does not match any entry - proxy.setFilterRegExp(QRegExp("[0-9]+")); - - QStringList slSource; - slSource << "z" << "x" << "a" << "b"; - - proxy.setDynamicSortFilter(true); - proxy.sort(0); - model.setStringList(slSource); - - // without fix for QTBUG-30662 this will make all entries visible - but unsorted - proxy.setFilterRegExp(QRegExp("[a-z]+")); - - QStringList slResult; - for (int i = 0; i < proxy.rowCount(); ++i) - slResult.append(proxy.index(i, 0).data().toString()); - - slSource.sort(); - QCOMPARE(slResult, slSource); -} - -void tst_QSortFilterProxyModel::changeSourceLayout() -{ - QStandardItemModel model(2, 1); - model.setData(model.index(0, 0), QString("b")); - model.setData(model.index(1, 0), QString("a")); - QSortFilterProxyModel proxy; - proxy.setSourceModel(&model); - - QList persistentSourceIndexes; - QList persistentProxyIndexes; - for (int row = 0; row < model.rowCount(); ++row) { - persistentSourceIndexes.append(model.index(row, 0)); - persistentProxyIndexes.append(proxy.index(row, 0)); - } - - // change layout of source model - model.sort(0, Qt::AscendingOrder); - - for (int row = 0; row < model.rowCount(); ++row) { - QCOMPARE(persistentProxyIndexes.at(row).row(), - persistentSourceIndexes.at(row).row()); - } -} - -void tst_QSortFilterProxyModel::changeSourceLayoutFilteredOut() -{ - QStandardItemModel model(2, 1); - model.setData(model.index(0, 0), QString("b")); - model.setData(model.index(1, 0), QString("a")); - QSortFilterProxyModel proxy; - proxy.setSourceModel(&model); - - int beforeSortFilter = proxy.rowCount(); - - QSignalSpy removeSpy(&proxy, &QSortFilterProxyModel::rowsRemoved); - // Filter everything out - proxy.setFilterRegExp(QRegExp("c")); - QCOMPARE(removeSpy.count(), 1); - QCOMPARE(0, proxy.rowCount()); - - // change layout of source model - model.sort(0, Qt::AscendingOrder); - - QSignalSpy insertSpy(&proxy, &QSortFilterProxyModel::rowsInserted); - // Remove filter; we expect an insert - proxy.setFilterRegExp(QRegExp("")); - QCOMPARE(insertSpy.count(), 1); - QCOMPARE(beforeSortFilter, proxy.rowCount()); -} - -void tst_QSortFilterProxyModel::removeSourceRows_data() -{ - QTest::addColumn("sourceItems"); - QTest::addColumn("start"); - QTest::addColumn("count"); - QTest::addColumn("sortOrder"); - QTest::addColumn("expectedRemovedProxyIntervals"); - QTest::addColumn("expectedProxyItems"); - - QTest::newRow("remove one, no sorting") - << (QStringList() << "a" << "b") // sourceItems - << 0 // start - << 1 // count - << -1 // sortOrder (no sorting) - << (IntPairList() << IntPair(0, 0)) // expectedRemovedIntervals - << (QStringList() << "b") // expectedProxyItems - ; - QTest::newRow("remove one, ascending sort (same order)") - << (QStringList() << "a" << "b") // sourceItems - << 0 // start - << 1 // count - << static_cast(Qt::AscendingOrder) // sortOrder - << (IntPairList() << IntPair(0, 0)) // expectedRemovedIntervals - << (QStringList() << "b") // expectedProxyItems - ; - QTest::newRow("remove one, ascending sort (reverse order)") - << (QStringList() << "b" << "a") // sourceItems - << 0 // start - << 1 // count - << static_cast(Qt::AscendingOrder) // sortOrder - << (IntPairList() << IntPair(1, 1)) // expectedRemovedIntervals - << (QStringList() << "a") // expectedProxyItems - ; - QTest::newRow("remove two, multiple proxy intervals") - << (QStringList() << "c" << "d" << "a" << "b") // sourceItems - << 1 // start - << 2 // count - << static_cast(Qt::AscendingOrder) // sortOrder - << (IntPairList() << IntPair(3, 3) << IntPair(0, 0)) // expectedRemovedIntervals - << (QStringList() << "b" << "c") // expectedProxyItems - ; - QTest::newRow("remove three, multiple proxy intervals") - << (QStringList() << "b" << "d" << "f" << "a" << "c" << "e") // sourceItems - << 3 // start - << 3 // count - << static_cast(Qt::AscendingOrder) // sortOrder - << (IntPairList() << IntPair(4, 4) << IntPair(2, 2) << IntPair(0, 0)) // expectedRemovedIntervals - << (QStringList() << "b" << "d" << "f") // expectedProxyItems - ; - QTest::newRow("remove all, single proxy intervals") - << (QStringList() << "a" << "b" << "c" << "d" << "e" << "f") // sourceItems - << 0 // start - << 6 // count - << static_cast(Qt::DescendingOrder) // sortOrder - << (IntPairList() << IntPair(0, 5)) // expectedRemovedIntervals - << QStringList() // expectedProxyItems - ; -} - -// Check that correct proxy model rows are removed when rows are removed -// from the source model -void tst_QSortFilterProxyModel::removeSourceRows() -{ - QFETCH(QStringList, sourceItems); - QFETCH(int, start); - QFETCH(int, count); - QFETCH(int, sortOrder); - QFETCH(IntPairList, expectedRemovedProxyIntervals); - QFETCH(QStringList, expectedProxyItems); - - QStandardItemModel model; - QSortFilterProxyModel proxy; - - proxy.setSourceModel(&model); - model.insertColumns(0, 1); - model.insertRows(0, sourceItems.count()); - - for (int i = 0; i < sourceItems.count(); ++i) { - QModelIndex sindex = model.index(i, 0, QModelIndex()); - model.setData(sindex, sourceItems.at(i), Qt::DisplayRole); - QModelIndex pindex = proxy.index(i, 0, QModelIndex()); - QCOMPARE(proxy.data(pindex, Qt::DisplayRole), model.data(sindex, Qt::DisplayRole)); - } - - if (sortOrder != -1) - proxy.sort(0, static_cast(sortOrder)); - (void)proxy.rowCount(QModelIndex()); // force mapping - - QSignalSpy removeSpy(&proxy, &QSortFilterProxyModel::rowsRemoved); - QSignalSpy insertSpy(&proxy, &QSortFilterProxyModel::rowsInserted); - QSignalSpy aboutToRemoveSpy(&proxy, &QSortFilterProxyModel::rowsAboutToBeRemoved); - QSignalSpy aboutToInsertSpy(&proxy, &QSortFilterProxyModel::rowsAboutToBeInserted); - - QVERIFY(removeSpy.isValid()); - QVERIFY(insertSpy.isValid()); - QVERIFY(aboutToRemoveSpy.isValid()); - QVERIFY(aboutToInsertSpy.isValid()); - - model.removeRows(start, count, QModelIndex()); - - QCOMPARE(aboutToRemoveSpy.count(), expectedRemovedProxyIntervals.count()); - for (int i = 0; i < aboutToRemoveSpy.count(); ++i) { - QList args = aboutToRemoveSpy.at(i); - QCOMPARE(args.at(1).type(), QVariant::Int); - QCOMPARE(args.at(2).type(), QVariant::Int); - QCOMPARE(args.at(1).toInt(), expectedRemovedProxyIntervals.at(i).first); - QCOMPARE(args.at(2).toInt(), expectedRemovedProxyIntervals.at(i).second); - } - QCOMPARE(removeSpy.count(), expectedRemovedProxyIntervals.count()); - for (int i = 0; i < removeSpy.count(); ++i) { - QList args = removeSpy.at(i); - QCOMPARE(args.at(1).type(), QVariant::Int); - QCOMPARE(args.at(2).type(), QVariant::Int); - QCOMPARE(args.at(1).toInt(), expectedRemovedProxyIntervals.at(i).first); - QCOMPARE(args.at(2).toInt(), expectedRemovedProxyIntervals.at(i).second); - } - - QCOMPARE(insertSpy.count(), 0); - QCOMPARE(aboutToInsertSpy.count(), 0); - - QCOMPARE(proxy.rowCount(QModelIndex()), expectedProxyItems.count()); - for (int i = 0; i < expectedProxyItems.count(); ++i) { - QModelIndex pindex = proxy.index(i, 0, QModelIndex()); - QCOMPARE(proxy.data(pindex, Qt::DisplayRole).toString(), expectedProxyItems.at(i)); - } -} - -void tst_QSortFilterProxyModel::insertSourceRows_data() -{ - QTest::addColumn("sourceItems"); - QTest::addColumn("start"); - QTest::addColumn("newItems"); - QTest::addColumn("sortOrder"); - QTest::addColumn("proxyItems"); - - QTest::newRow("insert (1)") - << (QStringList() << "c" << "b") // sourceItems - << 1 // start - << (QStringList() << "a") // newItems - << static_cast(Qt::AscendingOrder) // sortOrder - << (QStringList() << "a" << "b" << "c") // proxyItems - ; - - QTest::newRow("insert (2)") - << (QStringList() << "d" << "b" << "c") // sourceItems - << 3 // start - << (QStringList() << "a") // newItems - << static_cast(Qt::DescendingOrder) // sortOrder - << (QStringList() << "d" << "c" << "b" << "a") // proxyItems - ; -} - -// Check that rows are inserted at correct position in proxy model when -// rows are inserted into the source model -void tst_QSortFilterProxyModel::insertSourceRows() -{ - QFETCH(QStringList, sourceItems); - QFETCH(int, start); - QFETCH(QStringList, newItems); - QFETCH(int, sortOrder); - QFETCH(QStringList, proxyItems); - - QStandardItemModel model; - QSortFilterProxyModel proxy; - proxy.setDynamicSortFilter(true); - - proxy.setSourceModel(&model); - model.insertColumns(0, 1); - model.insertRows(0, sourceItems.count()); - - for (int i = 0; i < sourceItems.count(); ++i) { - QModelIndex index = model.index(i, 0, QModelIndex()); - model.setData(index, sourceItems.at(i), Qt::DisplayRole); - } - - proxy.sort(0, static_cast(sortOrder)); - (void)proxy.rowCount(QModelIndex()); // force mapping - - model.insertRows(start, newItems.size(), QModelIndex()); - - QCOMPARE(proxy.rowCount(QModelIndex()), proxyItems.count()); - for (int i = 0; i < newItems.count(); ++i) { - QModelIndex index = model.index(start + i, 0, QModelIndex()); - model.setData(index, newItems.at(i), Qt::DisplayRole); - } - - for (int i = 0; i < proxyItems.count(); ++i) { - QModelIndex index = proxy.index(i, 0, QModelIndex()); - QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), proxyItems.at(i)); - } -} - -void tst_QSortFilterProxyModel::changeFilter_data() -{ - QTest::addColumn("sourceItems"); - QTest::addColumn("sortOrder"); - QTest::addColumn("initialFilter"); - QTest::addColumn("initialRemoveIntervals"); - QTest::addColumn("initialProxyItems"); - QTest::addColumn("finalFilter"); - QTest::addColumn("finalRemoveIntervals"); - QTest::addColumn("insertIntervals"); - QTest::addColumn("finalProxyItems"); - - QTest::newRow("filter (1)") - << (QStringList() << "a" << "b" << "c" << "d" << "e" << "f") // sourceItems - << static_cast(Qt::AscendingOrder) // sortOrder - << "a|b|c" // initialFilter - << (IntPairList() << IntPair(3, 5)) // initialRemoveIntervals - << (QStringList() << "a" << "b" << "c") // initialProxyItems - << "b|d|f" // finalFilter - << (IntPairList() << IntPair(2, 2) << IntPair(0, 0)) // finalRemoveIntervals - << (IntPairList() << IntPair(1, 2)) // insertIntervals - << (QStringList() << "b" << "d" << "f") // finalProxyItems - ; - - QTest::newRow("filter (2)") - << (QStringList() << "a" << "b" << "c" << "d" << "e" << "f") // sourceItems - << static_cast(Qt::AscendingOrder) // sortOrder - << "a|c|e" // initialFilter - << (IntPairList() << IntPair(5, 5) << IntPair(3, 3) << IntPair(1, 1)) // initialRemoveIntervals - << (QStringList() << "a" << "c" << "e") // initialProxyItems - << "" // finalFilter - << IntPairList() // finalRemoveIntervals - << (IntPairList() << IntPair(3, 3) << IntPair(2, 2) << IntPair(1, 1)) // insertIntervals - << (QStringList() << "a" << "b" << "c" << "d" << "e" << "f") // finalProxyItems - ; - - QTest::newRow("filter (3)") - << (QStringList() << "a" << "b" << "c") // sourceItems - << static_cast(Qt::AscendingOrder) // sortOrder - << "a" // initialFilter - << (IntPairList() << IntPair(1, 2)) // initialRemoveIntervals - << (QStringList() << "a") // initialProxyItems - << "a" // finalFilter - << IntPairList() // finalRemoveIntervals - << IntPairList() // insertIntervals - << (QStringList() << "a") // finalProxyItems - ; -} - -// Check that rows are added/removed when filter changes -void tst_QSortFilterProxyModel::changeFilter() -{ - QFETCH(QStringList, sourceItems); - QFETCH(int, sortOrder); - QFETCH(QString, initialFilter); - QFETCH(IntPairList, initialRemoveIntervals); - QFETCH(QStringList, initialProxyItems); - QFETCH(QString, finalFilter); - QFETCH(IntPairList, finalRemoveIntervals); - QFETCH(IntPairList, insertIntervals); - QFETCH(QStringList, finalProxyItems); - - QStandardItemModel model; - QSortFilterProxyModel proxy; - - proxy.setSourceModel(&model); - model.insertColumns(0, 1); - model.insertRows(0, sourceItems.count()); - - for (int i = 0; i < sourceItems.count(); ++i) { - QModelIndex index = model.index(i, 0, QModelIndex()); - model.setData(index, sourceItems.at(i), Qt::DisplayRole); - } - - proxy.sort(0, static_cast(sortOrder)); - (void)proxy.rowCount(QModelIndex()); // force mapping - - QSignalSpy initialRemoveSpy(&proxy, &QSortFilterProxyModel::rowsRemoved); - QSignalSpy initialInsertSpy(&proxy, &QSortFilterProxyModel::rowsInserted); - - QVERIFY(initialRemoveSpy.isValid()); - QVERIFY(initialInsertSpy.isValid()); - - proxy.setFilterRegExp(initialFilter); - - QCOMPARE(initialRemoveSpy.count(), initialRemoveIntervals.count()); - QCOMPARE(initialInsertSpy.count(), 0); - for (int i = 0; i < initialRemoveSpy.count(); ++i) { - QList args = initialRemoveSpy.at(i); - QCOMPARE(args.at(1).type(), QVariant::Int); - QCOMPARE(args.at(2).type(), QVariant::Int); - QCOMPARE(args.at(1).toInt(), initialRemoveIntervals.at(i).first); - QCOMPARE(args.at(2).toInt(), initialRemoveIntervals.at(i).second); - } - - QCOMPARE(proxy.rowCount(QModelIndex()), initialProxyItems.count()); - for (int i = 0; i < initialProxyItems.count(); ++i) { - QModelIndex index = proxy.index(i, 0, QModelIndex()); - QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), initialProxyItems.at(i)); - } - - QSignalSpy finalRemoveSpy(&proxy, &QSortFilterProxyModel::rowsRemoved); - QSignalSpy finalInsertSpy(&proxy, &QSortFilterProxyModel::rowsInserted); - - QVERIFY(finalRemoveSpy.isValid()); - QVERIFY(finalInsertSpy.isValid()); - - proxy.setFilterRegExp(finalFilter); - - QCOMPARE(finalRemoveSpy.count(), finalRemoveIntervals.count()); - for (int i = 0; i < finalRemoveSpy.count(); ++i) { - QList args = finalRemoveSpy.at(i); - QCOMPARE(args.at(1).type(), QVariant::Int); - QCOMPARE(args.at(2).type(), QVariant::Int); - QCOMPARE(args.at(1).toInt(), finalRemoveIntervals.at(i).first); - QCOMPARE(args.at(2).toInt(), finalRemoveIntervals.at(i).second); - } - - QCOMPARE(finalInsertSpy.count(), insertIntervals.count()); - for (int i = 0; i < finalInsertSpy.count(); ++i) { - QList args = finalInsertSpy.at(i); - QCOMPARE(args.at(1).type(), QVariant::Int); - QCOMPARE(args.at(2).type(), QVariant::Int); - QCOMPARE(args.at(1).toInt(), insertIntervals.at(i).first); - QCOMPARE(args.at(2).toInt(), insertIntervals.at(i).second); - } - - QCOMPARE(proxy.rowCount(QModelIndex()), finalProxyItems.count()); - for (int i = 0; i < finalProxyItems.count(); ++i) { - QModelIndex index = proxy.index(i, 0, QModelIndex()); - QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), finalProxyItems.at(i)); - } -} - -void tst_QSortFilterProxyModel::changeSourceData_data() -{ - QTest::addColumn("sourceItems"); - QTest::addColumn("sortOrder"); - QTest::addColumn("filter"); - QTest::addColumn("expectedInitialProxyItems"); - QTest::addColumn("dynamic"); - QTest::addColumn("row"); - QTest::addColumn("newValue"); - QTest::addColumn("removeIntervals"); - QTest::addColumn("insertIntervals"); - QTest::addColumn("expectedDataChangedRow"); // -1 if no dataChanged signal expected - QTest::addColumn("expectedLayoutChanged"); - QTest::addColumn("proxyItems"); - - QTest::newRow("move_to_end_ascending") - << (QStringList() << "c" << "b" << "a") // sourceItems - << static_cast(Qt::AscendingOrder) // sortOrder - << "" // filter - << (QStringList() << "a" << "b" << "c") // expectedInitialProxyItems - << true // dynamic - << 2 // row - << "z" // newValue - << IntPairList() // removeIntervals - << IntPairList() // insertIntervals - << 2 // dataChanged(row 2) is emitted, see comment "Make sure we also emit dataChanged for the rows" in the source code (unclear why, though) - << true // layoutChanged - << (QStringList() << "b" << "c" << "z") // proxyItems - ; - - QTest::newRow("move_to_end_descending") - << (QStringList() << "b" << "c" << "z") // sourceItems - << static_cast(Qt::DescendingOrder) // sortOrder - << "" // filter - << (QStringList() << "z" << "c" << "b") // expectedInitialProxyItems - << true // dynamic - << 1 // row - << "a" // newValue - << IntPairList() // removeIntervals - << IntPairList() // insertIntervals - << 2 // dataChanged(row 2) is emitted, see comment "Make sure we also emit dataChanged for the rows" in the source code (unclear why, though) - << true // layoutChanged - << (QStringList() << "z" << "b" << "a") // proxyItems - ; - - QTest::newRow("no_op_change") - << (QStringList() << "a" << "b") // sourceItems - << static_cast(Qt::DescendingOrder) // sortOrder - << "" // filter - << (QStringList() << "b" << "a") // expectedInitialProxyItems - << true // dynamic - << 0 // row - << "a" // newValue - << IntPairList() // removeIntervals - << IntPairList() // insertIntervals - << -1 // no dataChanged signal - << false // layoutChanged - << (QStringList() << "b" << "a") // proxyItems - ; - - QTest::newRow("no_effect_on_filtering") - << (QStringList() << "a" << "b") // sourceItems - << static_cast(Qt::AscendingOrder) // sortOrder - << "" // filter - << (QStringList() << "a" << "b") // expectedInitialProxyItems - << true // dynamic - << 1 // row - << "z" // newValue - << IntPairList() // removeIntervals - << IntPairList() // insertIntervals - << 1 // expectedDataChangedRow - << false // layoutChanged - << (QStringList() << "a" << "z") // proxyItems - ; - - QTest::newRow("filtered_out_value_stays_out") - << (QStringList() << "a" << "b" << "c" << "d") // sourceItems - << static_cast(Qt::AscendingOrder) // sortOrder - << "a|c" // filter - << (QStringList() << "a" << "c") // expectedInitialProxyItems - << true // dynamic - << 1 // row - << "x" // newValue - << IntPairList() // removeIntervals - << IntPairList() // insertIntervals - << -1 // no dataChanged signal - << false // layoutChanged - << (QStringList() << "a" << "c") // proxyItems - ; - - QTest::newRow("filtered_out_now_matches") - << (QStringList() << "a" << "b" << "c" << "d") // sourceItems - << static_cast(Qt::AscendingOrder) // sortOrder - << "a|c|x" // filter - << (QStringList() << "a" << "c") // expectedInitialProxyItems - << true // dynamic - << 1 // row - << "x" // newValue - << IntPairList() // removeIntervals - << (IntPairList() << IntPair(2, 2)) // insertIntervals - << -1 // no dataChanged signal - << false // layoutChanged - << (QStringList() << "a" << "c" << "x") // proxyItems - ; - - QTest::newRow("value_is_now_filtered_out") - << (QStringList() << "a" << "b" << "c" << "d") // sourceItems - << static_cast(Qt::AscendingOrder) // sortOrder - << "a|c" // filter - << (QStringList() << "a" << "c") // expectedInitialProxyItems - << true // dynamic - << 2 // row - << "x" // newValue - << (IntPairList() << IntPair(1, 1)) // removeIntervals - << IntPairList() // insertIntervals - << -1 // no dataChanged signal - << false // layoutChanged - << (QStringList() << "a") // proxyItems - ; - - QTest::newRow("non_dynamic_filter_does_not_update_sort") - << (QStringList() << "c" << "b" << "a") // sourceItems - << static_cast(Qt::AscendingOrder) // sortOrder - << "" // filter - << (QStringList() << "a" << "b" << "c") // expectedInitialProxyItems - << false // dynamic - << 2 // row - << "x" // newValue - << IntPairList() // removeIntervals - << IntPairList() // insertIntervals - << 0 // expectedDataChangedRow - << false // layoutChanged - << (QStringList() << "x" << "b" << "c") // proxyItems - ; -} - -void tst_QSortFilterProxyModel::changeSourceData() -{ - QFETCH(QStringList, sourceItems); - QFETCH(int, sortOrder); - QFETCH(QString, filter); - QFETCH(QStringList, expectedInitialProxyItems); - QFETCH(bool, dynamic); - QFETCH(int, row); - QFETCH(QString, newValue); - QFETCH(IntPairList, removeIntervals); - QFETCH(IntPairList, insertIntervals); - QFETCH(int, expectedDataChangedRow); - QFETCH(bool, expectedLayoutChanged); - QFETCH(QStringList, proxyItems); - - QStandardItemModel model; - QSortFilterProxyModel proxy; - - proxy.setDynamicSortFilter(dynamic); - proxy.setSourceModel(&model); - model.insertColumns(0, 1); - model.insertRows(0, sourceItems.count()); - - for (int i = 0; i < sourceItems.count(); ++i) { - QModelIndex index = model.index(i, 0, QModelIndex()); - model.setData(index, sourceItems.at(i), Qt::DisplayRole); - } - - proxy.sort(0, static_cast(sortOrder)); - (void)proxy.rowCount(QModelIndex()); // force mapping - - proxy.setFilterRegExp(filter); - - QCOMPARE(proxy.rowCount(), expectedInitialProxyItems.count()); - for (int i = 0; i < expectedInitialProxyItems.count(); ++i) { - const QModelIndex index = proxy.index(i, 0, QModelIndex()); - QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expectedInitialProxyItems.at(i)); - } - - QSignalSpy removeSpy(&proxy, &QSortFilterProxyModel::rowsRemoved); - QSignalSpy insertSpy(&proxy, &QSortFilterProxyModel::rowsInserted); - QSignalSpy dataChangedSpy(&proxy, &QSortFilterProxyModel::dataChanged); - QSignalSpy layoutChangedSpy(&proxy, &QSortFilterProxyModel::layoutChanged); - - QVERIFY(removeSpy.isValid()); - QVERIFY(insertSpy.isValid()); - QVERIFY(dataChangedSpy.isValid()); - QVERIFY(layoutChangedSpy.isValid()); - - { - QModelIndex index = model.index(row, 0, QModelIndex()); - model.setData(index, newValue, Qt::DisplayRole); - } - - QCOMPARE(removeSpy.count(), removeIntervals.count()); - for (int i = 0; i < removeSpy.count(); ++i) { - QList args = removeSpy.at(i); - QCOMPARE(args.at(1).type(), QVariant::Int); - QCOMPARE(args.at(2).type(), QVariant::Int); - QCOMPARE(args.at(1).toInt(), removeIntervals.at(i).first); - QCOMPARE(args.at(2).toInt(), removeIntervals.at(i).second); - } - - QCOMPARE(insertSpy.count(), insertIntervals.count()); - for (int i = 0; i < insertSpy.count(); ++i) { - QList args = insertSpy.at(i); - QCOMPARE(args.at(1).type(), QVariant::Int); - QCOMPARE(args.at(2).type(), QVariant::Int); - QCOMPARE(args.at(1).toInt(), insertIntervals.at(i).first); - QCOMPARE(args.at(2).toInt(), insertIntervals.at(i).second); - } - - QCOMPARE(proxy.rowCount(QModelIndex()), proxyItems.count()); - for (int i = 0; i < proxyItems.count(); ++i) { - QModelIndex index = proxy.index(i, 0, QModelIndex()); - QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), proxyItems.at(i)); - } - - if (expectedDataChangedRow == -1) { - QCOMPARE(dataChangedSpy.count(), 0); - } else { - QCOMPARE(dataChangedSpy.count(), 1); - const QModelIndex idx = dataChangedSpy.at(0).at(0).value(); - QCOMPARE(idx.row(), expectedDataChangedRow); - QCOMPARE(idx.column(), 0); - } - - QCOMPARE(layoutChangedSpy.count(), expectedLayoutChanged ? 1 : 0); -} - -// Checks that the model is a table, and that each and every row is like this: -// i-th row: ( rows.at(i), i ) -static void checkSortedTableModel(const QAbstractItemModel *model, const QStringList &rows) -{ - QCOMPARE(model->rowCount(), rows.length()); - QCOMPARE(model->columnCount(), 2); - - for (int row = 0; row < model->rowCount(); ++row) { - const QString column0 = model->index(row, 0).data().toString(); - const int column1 = model->index(row, 1).data().toString().toInt(); - - QCOMPARE(column0, rows.at(row)); - QCOMPARE(column1, row); - } -} - -void tst_QSortFilterProxyModel::changeSourceDataKeepsStableSorting_qtbug1548() -{ - // Check that emitting dataChanged from the source model - // for a change of a role which is not the sorting role - // doesn't alter the sorting. In this case, we sort on the DisplayRole, - // and play with other roles. - - static const QStringList rows - = QStringList() << "a" << "b" << "b" << "b" << "c" << "c" << "x"; - - // Build a table of pairs (string, #row) in each row - QStandardItemModel model(0, 2); - - for (int rowNumber = 0; rowNumber < rows.length(); ++rowNumber) { - QStandardItem *column0 = new QStandardItem(rows.at(rowNumber)); - column0->setCheckable(true); - column0->setCheckState(Qt::Unchecked); - - QStandardItem *column1 = new QStandardItem(QString::number(rowNumber)); - - const QList row - = QList() << column0 << column1; - - model.appendRow(row); - } - - checkSortedTableModel(&model, rows); - - // Build the proxy model - QSortFilterProxyModel proxy; - proxy.setSourceModel(&model); - proxy.setDynamicSortFilter(true); - proxy.sort(0); - - // The proxy is now sorted by the first column, check that the sorting - // * is correct (the input is already sorted, so it must not have changed) - // * was stable (by looking at the second column) - checkSortedTableModel(&model, rows); - - // Change the check status of an item. That must not break the stable sorting - // changes the middle "b" - model.item(2)->setCheckState(Qt::Checked); - checkSortedTableModel(&model, rows); - - // changes the starting "a" - model.item(0)->setCheckState(Qt::Checked); - checkSortedTableModel(&model, rows); - - // change the background color of the first "c" - model.item(4)->setBackground(Qt::red); - checkSortedTableModel(&model, rows); - - // change the background color of the second "c" - model.item(5)->setBackground(Qt::red); - checkSortedTableModel(&model, rows); -} - -void tst_QSortFilterProxyModel::changeSourceDataForwardsRoles_qtbug35440() -{ - QStringList strings; - for (int i = 0; i < 100; ++i) - strings << QString::number(i); - - QStringListModel model(strings); - - QSortFilterProxyModel proxy; - proxy.setSourceModel(&model); - proxy.sort(0, Qt::AscendingOrder); - - QSignalSpy spy(&proxy, &QAbstractItemModel::dataChanged); - QVERIFY(spy.isValid()); - QCOMPARE(spy.length(), 0); - - QModelIndex index; - - // QStringListModel doesn't distinguish between edit and display roles, - // so changing one always changes the other, too. - QVector expectedChangedRoles; - expectedChangedRoles.append(Qt::DisplayRole); - expectedChangedRoles.append(Qt::EditRole); - - index = model.index(0, 0); - QVERIFY(index.isValid()); - model.setData(index, QStringLiteral("teststring"), Qt::DisplayRole); - QCOMPARE(spy.length(), 1); - QCOMPARE(spy.at(0).at(2).value >(), expectedChangedRoles); - - index = model.index(1, 0); - QVERIFY(index.isValid()); - model.setData(index, QStringLiteral("teststring2"), Qt::EditRole); - QCOMPARE(spy.length(), 2); - QCOMPARE(spy.at(1).at(2).value >(), expectedChangedRoles); -} - -void tst_QSortFilterProxyModel::sortFilterRole() -{ - QStandardItemModel model; - QSortFilterProxyModel proxy; - proxy.setSourceModel(&model); - model.insertColumns(0, 1); - - QList > sourceItems; - sourceItems = QList >() - << QPair("b", 3) - << QPair("c", 2) - << QPair("a", 1); - - QList orderedItems; - orderedItems = QList() - << 2 << 1; - - model.insertRows(0, sourceItems.count()); - for (int i = 0; i < sourceItems.count(); ++i) { - QModelIndex index = model.index(i, 0, QModelIndex()); - model.setData(index, sourceItems.at(i).first, Qt::DisplayRole); - model.setData(index, sourceItems.at(i).second, Qt::UserRole); - } - - proxy.setFilterRegExp("2"); - QCOMPARE(proxy.rowCount(), 0); // Qt::DisplayRole is default role - - proxy.setFilterRole(Qt::UserRole); - QCOMPARE(proxy.rowCount(), 1); - - proxy.setFilterRole(Qt::DisplayRole); - QCOMPARE(proxy.rowCount(), 0); - - proxy.setFilterRegExp("1|2|3"); - QCOMPARE(proxy.rowCount(), 0); - - proxy.setFilterRole(Qt::UserRole); - QCOMPARE(proxy.rowCount(), 3); - - proxy.sort(0, Qt::AscendingOrder); - QCOMPARE(proxy.rowCount(), 3); - - proxy.setSortRole(Qt::UserRole); - proxy.setFilterRole(Qt::DisplayRole); - proxy.setFilterRegExp("a|c"); - QCOMPARE(proxy.rowCount(), orderedItems.count()); - for (int i = 0; i < proxy.rowCount(); ++i) { - QModelIndex index = proxy.index(i, 0, QModelIndex()); - QCOMPARE(proxy.data(index, Qt::DisplayRole), sourceItems.at(orderedItems.at(i)).first); - } -} - -void tst_QSortFilterProxyModel::selectionFilteredOut() -{ - QStandardItemModel model(2, 1); - model.setData(model.index(0, 0), QString("AAA")); - model.setData(model.index(1, 0), QString("BBB")); - QSortFilterProxyModel proxy; - proxy.setSourceModel(&model); - QTreeView view; - - view.show(); - view.setModel(&proxy); - QSignalSpy spy(view.selectionModel(), &QItemSelectionModel::currentChanged); - QVERIFY(spy.isValid()); - - view.setCurrentIndex(proxy.index(0, 0)); - QCOMPARE(spy.count(), 1); - proxy.setFilterRegExp(QRegExp("^B")); - QCOMPARE(spy.count(), 2); -} - -void tst_QSortFilterProxyModel::match_data() -{ - QTest::addColumn("sourceItems"); - QTest::addColumn("sortOrder"); - QTest::addColumn("filter"); - QTest::addColumn("proxyStartRow"); - QTest::addColumn("what"); - QTest::addColumn("matchFlags"); - QTest::addColumn("expectedProxyItems"); - QTest::newRow("1") - << (QStringList() << "a") // sourceItems - << static_cast(Qt::AscendingOrder) // sortOrder - << "" // filter - << 0 // proxyStartRow - << "a" // what - << static_cast(Qt::MatchExactly) // matchFlags - << (IntList() << 0); // expectedProxyItems - QTest::newRow("2") - << (QStringList() << "a" << "b") // sourceItems - << static_cast(Qt::AscendingOrder) // sortOrder - << "" // filter - << 0 // proxyStartRow - << "b" // what - << static_cast(Qt::MatchExactly) // matchFlags - << (IntList() << 1); // expectedProxyItems - QTest::newRow("3") - << (QStringList() << "a" << "b") // sourceItems - << static_cast(Qt::DescendingOrder) // sortOrder - << "" // filter - << 0 // proxyStartRow - << "a" // what - << static_cast(Qt::MatchExactly) // matchFlags - << (IntList() << 1); // expectedProxyItems - QTest::newRow("4") - << (QStringList() << "b" << "d" << "a" << "c") // sourceItems - << static_cast(Qt::AscendingOrder) // sortOrder - << "" // filter - << 1 // proxyStartRow - << "a" // what - << static_cast(Qt::MatchExactly) // matchFlags - << IntList(); // expectedProxyItems - QTest::newRow("5") - << (QStringList() << "b" << "d" << "a" << "c") // sourceItems - << static_cast(Qt::AscendingOrder) // sortOrder - << "a|b" // filter - << 0 // proxyStartRow - << "c" // what - << static_cast(Qt::MatchExactly) // matchFlags - << IntList(); // expectedProxyItems - QTest::newRow("6") - << (QStringList() << "b" << "d" << "a" << "c") // sourceItems - << static_cast(Qt::DescendingOrder) // sortOrder - << "a|b" // filter - << 0 // proxyStartRow - << "b" // what - << static_cast(Qt::MatchExactly) // matchFlags - << (IntList() << 0); // expectedProxyItems -} - -void tst_QSortFilterProxyModel::match() -{ - QFETCH(QStringList, sourceItems); - QFETCH(int, sortOrder); - QFETCH(QString, filter); - QFETCH(int, proxyStartRow); - QFETCH(QString, what); - QFETCH(int, matchFlags); - QFETCH(IntList, expectedProxyItems); - - QStandardItemModel model; - QSortFilterProxyModel proxy; - - proxy.setSourceModel(&model); - model.insertColumns(0, 1); - model.insertRows(0, sourceItems.count()); - - for (int i = 0; i < sourceItems.count(); ++i) { - QModelIndex index = model.index(i, 0, QModelIndex()); - model.setData(index, sourceItems.at(i), Qt::DisplayRole); - } - - proxy.sort(0, static_cast(sortOrder)); - proxy.setFilterRegExp(filter); - - QModelIndex startIndex = proxy.index(proxyStartRow, 0); - QModelIndexList indexes = proxy.match(startIndex, Qt::DisplayRole, what, - expectedProxyItems.count(), - Qt::MatchFlags(matchFlags)); - QCOMPARE(indexes.count(), expectedProxyItems.count()); - for (int i = 0; i < indexes.count(); ++i) - QCOMPARE(indexes.at(i).row(), expectedProxyItems.at(i)); -} - -void tst_QSortFilterProxyModel::insertIntoChildrenlessItem() -{ - QStandardItemModel model; - QStandardItem *itemA = new QStandardItem("a"); - model.appendRow(itemA); - QStandardItem *itemB = new QStandardItem("b"); - model.appendRow(itemB); - QStandardItem *itemC = new QStandardItem("c"); - model.appendRow(itemC); - - QSortFilterProxyModel proxy; - proxy.setSourceModel(&model); - - QSignalSpy colsInsertedSpy(&proxy, &QSortFilterProxyModel::columnsInserted); - QSignalSpy rowsInsertedSpy(&proxy, &QSortFilterProxyModel::rowsInserted); - - QVERIFY(colsInsertedSpy.isValid()); - QVERIFY(rowsInsertedSpy.isValid()); - - (void)proxy.rowCount(QModelIndex()); // force mapping of "a", "b", "c" - QCOMPARE(colsInsertedSpy.count(), 0); - QCOMPARE(rowsInsertedSpy.count(), 0); - - // now add a child to itemB ==> should get insert notification from the proxy - itemB->appendRow(new QStandardItem("a.0")); - QCOMPARE(colsInsertedSpy.count(), 1); - QCOMPARE(rowsInsertedSpy.count(), 1); - - QVariantList args = colsInsertedSpy.takeFirst(); - QCOMPARE(qvariant_cast(args.at(0)), proxy.mapFromSource(itemB->index())); - QCOMPARE(qvariant_cast(args.at(1)), 0); - QCOMPARE(qvariant_cast(args.at(2)), 0); - - args = rowsInsertedSpy.takeFirst(); - QCOMPARE(qvariant_cast(args.at(0)), proxy.mapFromSource(itemB->index())); - QCOMPARE(qvariant_cast(args.at(1)), 0); - QCOMPARE(qvariant_cast(args.at(2)), 0); -} - -void tst_QSortFilterProxyModel::invalidateMappedChildren() -{ - QStandardItemModel model; - - QSortFilterProxyModel proxy; - proxy.setSourceModel(&model); - - QStandardItem *itemA = new QStandardItem("a"); - model.appendRow(itemA); - QStandardItem *itemB = new QStandardItem("b"); - itemA->appendRow(itemB); - - QStandardItem *itemC = new QStandardItem("c"); - itemB->appendRow(itemC); - itemC->appendRow(new QStandardItem("d")); - - // force mappings - (void)proxy.hasChildren(QModelIndex()); - (void)proxy.hasChildren(proxy.mapFromSource(itemA->index())); - (void)proxy.hasChildren(proxy.mapFromSource(itemB->index())); - (void)proxy.hasChildren(proxy.mapFromSource(itemC->index())); - - itemB->removeRow(0); // should invalidate mapping of itemC - itemC = new QStandardItem("c"); - itemA->appendRow(itemC); - itemC->appendRow(new QStandardItem("d")); - - itemA->removeRow(1); // should invalidate mapping of itemC - itemC = new QStandardItem("c"); - itemB->appendRow(itemC); - itemC->appendRow(new QStandardItem("d")); - - QCOMPARE(proxy.rowCount(proxy.mapFromSource(itemA->index())), 1); - QCOMPARE(proxy.rowCount(proxy.mapFromSource(itemB->index())), 1); - QCOMPARE(proxy.rowCount(proxy.mapFromSource(itemC->index())), 1); -} - -class EvenOddFilterModel : public QSortFilterProxyModel -{ -public: - virtual bool filterAcceptsRow(int srcRow, const QModelIndex& srcParent) const - { - if (srcParent.isValid()) - return (srcParent.row() % 2) ^ !(srcRow % 2); - return (srcRow % 2); - } -}; - -void tst_QSortFilterProxyModel::insertRowIntoFilteredParent() -{ - QStandardItemModel model; - EvenOddFilterModel proxy; - proxy.setSourceModel(&model); - - QSignalSpy spy(&proxy, &EvenOddFilterModel::rowsInserted); - QVERIFY(spy.isValid()); - - QStandardItem *itemA = new QStandardItem(); - model.appendRow(itemA); // A will be filtered - QStandardItem *itemB = new QStandardItem(); - itemA->appendRow(itemB); - - QCOMPARE(spy.count(), 0); - - itemA->removeRow(0); - - QCOMPARE(spy.count(), 0); -} - -void tst_QSortFilterProxyModel::filterOutParentAndFilterInChild() -{ - QStandardItemModel model; - QSortFilterProxyModel proxy; - proxy.setSourceModel(&model); - - proxy.setFilterRegExp("A|B"); - QStandardItem *itemA = new QStandardItem("A"); - model.appendRow(itemA); // not filtered - QStandardItem *itemB = new QStandardItem("B"); - itemA->appendRow(itemB); // not filtered - QStandardItem *itemC = new QStandardItem("C"); - itemA->appendRow(itemC); // filtered - - QSignalSpy removedSpy(&proxy, &QSortFilterProxyModel::rowsRemoved); - QSignalSpy insertedSpy(&proxy, &QSortFilterProxyModel::rowsInserted); - - QVERIFY(removedSpy.isValid()); - QVERIFY(insertedSpy.isValid()); - - proxy.setFilterRegExp("C"); // A and B will be filtered out, C filtered in - - // we should now have been notified that the subtree represented by itemA has been removed - QCOMPARE(removedSpy.count(), 1); - // we should NOT get any inserts; itemC should be filtered because its parent (itemA) is - QCOMPARE(insertedSpy.count(), 0); -} - -void tst_QSortFilterProxyModel::sourceInsertRows() -{ - QStandardItemModel model; - QSortFilterProxyModel proxyModel; - proxyModel.setSourceModel(&model); - - model.insertColumns(0, 1, QModelIndex()); - model.insertRows(0, 2, QModelIndex()); - - { - QModelIndex parent = model.index(0, 0, QModelIndex()); - model.insertColumns(0, 1, parent); - model.insertRows(0, 1, parent); - } - - { - QModelIndex parent = model.index(1, 0, QModelIndex()); - model.insertColumns(0, 1, parent); - model.insertRows(0, 1, parent); - } - - model.insertRows(0, 1, QModelIndex()); - model.insertRows(0, 1, QModelIndex()); - - QVERIFY(true); // if you got here without asserting, it's all good -} - -void tst_QSortFilterProxyModel::sourceModelDeletion() -{ - QSortFilterProxyModel proxyModel; - { - QStandardItemModel model; - proxyModel.setSourceModel(&model); - QCOMPARE(proxyModel.sourceModel(), static_cast(&model)); - } - QCOMPARE(proxyModel.sourceModel(), static_cast(0)); -} - -void tst_QSortFilterProxyModel::sortColumnTracking1() -{ - QStandardItemModel model; - QSortFilterProxyModel proxyModel; - proxyModel.setSourceModel(&model); - - model.insertColumns(0, 10); - model.insertRows(0, 10); - - proxyModel.sort(1); - QCOMPARE(proxyModel.sortColumn(), 1); - - model.insertColumn(8); - QCOMPARE(proxyModel.sortColumn(), 1); - - model.removeColumn(8); - QCOMPARE(proxyModel.sortColumn(), 1); - - model.insertColumn(2); - QCOMPARE(proxyModel.sortColumn(), 1); - - model.removeColumn(2); - QCOMPARE(proxyModel.sortColumn(), 1); - - model.insertColumn(1); - QCOMPARE(proxyModel.sortColumn(), 2); - - model.removeColumn(1); - QCOMPARE(proxyModel.sortColumn(), 1); - - model.removeColumn(1); - QCOMPARE(proxyModel.sortColumn(), -1); -} - -void tst_QSortFilterProxyModel::sortColumnTracking2() -{ - QStandardItemModel model; - QSortFilterProxyModel proxyModel; - proxyModel.setDynamicSortFilter(true); - proxyModel.setSourceModel(&model); - - proxyModel.sort(0); - QCOMPARE(proxyModel.sortColumn(), 0); - - QList items; // Stable sorting: Items with invalid data should move to the end - items << new QStandardItem << new QStandardItem("foo") << new QStandardItem("bar") - << new QStandardItem("some") << new QStandardItem("others") << new QStandardItem("item") - << new QStandardItem("aa") << new QStandardItem("zz") << new QStandardItem; - - model.insertColumn(0,items); - QCOMPARE(proxyModel.sortColumn(), 0); - QCOMPARE(proxyModel.data(proxyModel.index(0,0)).toString(),QString::fromLatin1("aa")); - const int zzIndex = items.count() - 3; // 2 invalid at end. - QCOMPARE(proxyModel.data(proxyModel.index(zzIndex,0)).toString(),QString::fromLatin1("zz")); -} - -void tst_QSortFilterProxyModel::sortStable() -{ - QStandardItemModel* model = new QStandardItemModel(5, 2); - for (int r = 0; r < 5; r++) { - const QString prefix = QLatin1String("Row:") + QString::number(r) + QLatin1String(", Column:"); - for (int c = 0; c < 2; c++) { - QStandardItem* item = new QStandardItem(prefix + QString::number(c)); - for (int i = 0; i < 3; i++) { - QStandardItem* child = new QStandardItem(QLatin1String("Item ") + QString::number(i)); - item->appendRow( child ); - } - model->setItem(r, c, item); - } - } - model->setHorizontalHeaderItem( 0, new QStandardItem( "Name" )); - model->setHorizontalHeaderItem( 1, new QStandardItem( "Value" )); - - QSortFilterProxyModel *filterModel = new QSortFilterProxyModel(model); - filterModel->setSourceModel(model); - - QTreeView *view = new QTreeView; - view->setModel(filterModel); - QModelIndex firstRoot = filterModel->index(0,0); - view->expand(firstRoot); - view->setSortingEnabled(true); - - view->model()->sort(1, Qt::DescendingOrder); - QVariant lastItemData =filterModel->index(2,0, firstRoot).data(); - view->model()->sort(1, Qt::DescendingOrder); - QCOMPARE(lastItemData, filterModel->index(2,0, firstRoot).data()); -} - -void tst_QSortFilterProxyModel::hiddenColumns() -{ - class MyStandardItemModel : public QStandardItemModel - { - public: - MyStandardItemModel() : QStandardItemModel(0,5) {} - void reset() - { beginResetModel(); endResetModel(); } - friend class tst_QSortFilterProxyModel; - } model; - QSortFilterProxyModel proxy; - proxy.setSourceModel(&model); - - QTableView view; - view.setModel(&proxy); - - view.hideColumn(0); - - QVERIFY(view.isColumnHidden(0)); - model.blockSignals(true); - model.setRowCount(1); - model.blockSignals(false); - model.reset(); - - // In the initial bug report that spawned this test, this would be false - // because resetting model would also reset the hidden columns. - QVERIFY(view.isColumnHidden(0)); -} - -void tst_QSortFilterProxyModel::insertRowsSort() -{ - QStandardItemModel model(2,2); - QSortFilterProxyModel proxyModel; - proxyModel.setSourceModel(&model); - - proxyModel.sort(0); - QCOMPARE(proxyModel.sortColumn(), 0); - - model.insertColumns(0, 3, model.index(0,0)); - QCOMPARE(proxyModel.sortColumn(), 0); - - model.removeColumns(0, 3, model.index(0,0)); - QCOMPARE(proxyModel.sortColumn(), 0); -} - -void tst_QSortFilterProxyModel::staticSorting() -{ - QStandardItemModel model(0, 1); - QSortFilterProxyModel proxy; - proxy.setSourceModel(&model); - proxy.setDynamicSortFilter(false); - QStringList initial = QString("bateau avion dragon hirondelle flamme camion elephant").split(QLatin1Char(' ')); - - // prepare model - QStandardItem *root = model.invisibleRootItem (); - QList items; - for (int i = 0; i < initial.count(); ++i) { - items.append(new QStandardItem(initial.at(i))); - } - root->insertRows(0, items); - QCOMPARE(model.rowCount(QModelIndex()), initial.count()); - QCOMPARE(model.columnCount(QModelIndex()), 1); - - // make sure the proxy is unsorted - QCOMPARE(proxy.columnCount(QModelIndex()), 1); - QCOMPARE(proxy.rowCount(QModelIndex()), initial.count()); - for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) { - QModelIndex index = proxy.index(row, 0, QModelIndex()); - QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), initial.at(row)); - } - - // sort - proxy.sort(0); - - QStringList expected = initial; - expected.sort(); - // make sure the proxy is sorted - for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) { - QModelIndex index = proxy.index(row, 0, QModelIndex()); - QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expected.at(row)); - } - - //update one item. - items.first()->setData("girafe", Qt::DisplayRole); - - // make sure the proxy is updated but not sorted - expected.replaceInStrings("bateau", "girafe"); - for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) { - QModelIndex index = proxy.index(row, 0, QModelIndex()); - QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expected.at(row)); - } - - // sort again - proxy.sort(0); - expected.sort(); - - // make sure the proxy is sorted - for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) { - QModelIndex index = proxy.index(row, 0, QModelIndex()); - QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expected.at(row)); - } -} - -void tst_QSortFilterProxyModel::dynamicSorting() -{ - QStringListModel model1; - const QStringList initial = QString("bateau avion dragon hirondelle flamme camion elephant").split(QLatin1Char(' ')); - model1.setStringList(initial); - QSortFilterProxyModel proxy1; - proxy1.setDynamicSortFilter(false); - proxy1.sort(0); - proxy1.setSourceModel(&model1); - - QCOMPARE(proxy1.columnCount(QModelIndex()), 1); - //the model should not be sorted because sorting has not been set to dynamic yet. - QCOMPARE(proxy1.rowCount(QModelIndex()), initial.count()); - for (int row = 0; row < proxy1.rowCount(QModelIndex()); ++row) { - QModelIndex index = proxy1.index(row, 0, QModelIndex()); - QCOMPARE(proxy1.data(index, Qt::DisplayRole).toString(), initial.at(row)); - } - - proxy1.setDynamicSortFilter(true); - - //now the model should be sorted. - QStringList expected = initial; - expected.sort(); - for (int row = 0; row < proxy1.rowCount(QModelIndex()); ++row) { - QModelIndex index = proxy1.index(row, 0, QModelIndex()); - QCOMPARE(proxy1.data(index, Qt::DisplayRole).toString(), expected.at(row)); - } - - QStringList initial2 = initial; - initial2.replaceInStrings("bateau", "girafe"); - model1.setStringList(initial2); //this will cause a reset - - QStringList expected2 = initial2; - expected2.sort(); - - //now the model should still be sorted. - for (int row = 0; row < proxy1.rowCount(QModelIndex()); ++row) { - QModelIndex index = proxy1.index(row, 0, QModelIndex()); - QCOMPARE(proxy1.data(index, Qt::DisplayRole).toString(), expected2.at(row)); - } - - QStringListModel model2(initial); - proxy1.setSourceModel(&model2); - - //the model should again be sorted - for (int row = 0; row < proxy1.rowCount(QModelIndex()); ++row) { - QModelIndex index = proxy1.index(row, 0, QModelIndex()); - QCOMPARE(proxy1.data(index, Qt::DisplayRole).toString(), expected.at(row)); - } - - //set up the sorting before seting the model up - QSortFilterProxyModel proxy2; - proxy2.sort(0); - proxy2.setSourceModel(&model2); - for (int row = 0; row < proxy2.rowCount(QModelIndex()); ++row) { - QModelIndex index = proxy2.index(row, 0, QModelIndex()); - QCOMPARE(proxy2.data(index, Qt::DisplayRole).toString(), expected.at(row)); - } -} - -class QtTestModel: public QAbstractItemModel -{ -public: - QtTestModel(int _rows, int _cols, QObject *parent = 0) - : QAbstractItemModel(parent) - , rows(_rows) - , cols(_cols) - , wrongIndex(false) - { - } - - bool canFetchMore(const QModelIndex &idx) const - { - return !fetched.contains(idx); - } - - void fetchMore(const QModelIndex &idx) - { - if (fetched.contains(idx)) - return; - beginInsertRows(idx, 0, rows-1); - fetched.insert(idx); - endInsertRows(); - } - - bool hasChildren(const QModelIndex & = QModelIndex()) const - { - return true; - } - - int rowCount(const QModelIndex& parent = QModelIndex()) const - { - return fetched.contains(parent) ? rows : 0; - } - - int columnCount(const QModelIndex& parent = QModelIndex()) const - { - Q_UNUSED(parent); - return cols; - } - - QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const - { - if (row < 0 || column < 0 || column >= cols || row >= rows) { - return QModelIndex(); - } - QModelIndex i = createIndex(row, column, int(parent.internalId() + 1)); - parentHash[i] = parent; - return i; - } - - QModelIndex parent(const QModelIndex &index) const - { - if (!parentHash.contains(index)) - return QModelIndex(); - return parentHash[index]; - } - - QVariant data(const QModelIndex &idx, int role) const - { - if (!idx.isValid()) - return QVariant(); - - if (role == Qt::DisplayRole) { - if (idx.row() < 0 || idx.column() < 0 || idx.column() >= cols || idx.row() >= rows) { - wrongIndex = true; - qWarning("Invalid modelIndex [%d,%d,%p]", idx.row(), idx.column(), - idx.internalPointer()); - } - return QLatin1Char('[') + QString::number(idx.row()) + QLatin1Char(',') - + QString::number(idx.column()) + QLatin1Char(']'); - } - return QVariant(); - } - - QSet fetched; - int rows, cols; - mutable bool wrongIndex; - mutable QMap parentHash; -}; - -void tst_QSortFilterProxyModel::fetchMore() -{ - QtTestModel model(10,10); - QSortFilterProxyModel proxy; - proxy.setSourceModel(&model); - QVERIFY(proxy.canFetchMore(QModelIndex())); - QVERIFY(proxy.hasChildren()); - while (proxy.canFetchMore(QModelIndex())) - proxy.fetchMore(QModelIndex()); - QCOMPARE(proxy.rowCount(), 10); - QCOMPARE(proxy.columnCount(), 10); - - QModelIndex idx = proxy.index(1,1); - QVERIFY(idx.isValid()); - QVERIFY(proxy.canFetchMore(idx)); - QVERIFY(proxy.hasChildren(idx)); - while (proxy.canFetchMore(idx)) - proxy.fetchMore(idx); - QCOMPARE(proxy.rowCount(idx), 10); - QCOMPARE(proxy.columnCount(idx), 10); -} - -void tst_QSortFilterProxyModel::hiddenChildren() -{ - QStandardItemModel model; - QSortFilterProxyModel proxy; - proxy.setSourceModel(&model); - proxy.setDynamicSortFilter(true); - - QStandardItem *itemA = new QStandardItem("A VISIBLE"); - model.appendRow(itemA); - QStandardItem *itemB = new QStandardItem("B VISIBLE"); - itemA->appendRow(itemB); - QStandardItem *itemC = new QStandardItem("C"); - itemA->appendRow(itemC); - proxy.setFilterRegExp("VISIBLE"); - - QCOMPARE(proxy.rowCount(QModelIndex()) , 1); - QPersistentModelIndex indexA = proxy.index(0,0); - QCOMPARE(proxy.data(indexA).toString(), QString::fromLatin1("A VISIBLE")); - - QCOMPARE(proxy.rowCount(indexA) , 1); - QPersistentModelIndex indexB = proxy.index(0, 0, indexA); - QCOMPARE(proxy.data(indexB).toString(), QString::fromLatin1("B VISIBLE")); - - itemA->setText("A"); - QCOMPARE(proxy.rowCount(QModelIndex()), 0); - QVERIFY(!indexA.isValid()); - QVERIFY(!indexB.isValid()); - - itemB->setText("B"); - itemA->setText("A VISIBLE"); - itemC->setText("C VISIBLE"); - - QCOMPARE(proxy.rowCount(QModelIndex()), 1); - indexA = proxy.index(0,0); - QCOMPARE(proxy.data(indexA).toString(), QString::fromLatin1("A VISIBLE")); - - QCOMPARE(proxy.rowCount(indexA) , 1); - QModelIndex indexC = proxy.index(0, 0, indexA); - QCOMPARE(proxy.data(indexC).toString(), QString::fromLatin1("C VISIBLE")); - - proxy.setFilterRegExp("C"); - QCOMPARE(proxy.rowCount(QModelIndex()), 0); - itemC->setText("invisible"); - itemA->setText("AC"); - - QCOMPARE(proxy.rowCount(QModelIndex()), 1); - indexA = proxy.index(0,0); - QCOMPARE(proxy.data(indexA).toString(), QString::fromLatin1("AC")); - QCOMPARE(proxy.rowCount(indexA) , 0); -} - -void tst_QSortFilterProxyModel::mapFromToSource() -{ - QtTestModel source(10,10); - source.fetchMore(QModelIndex()); - QSortFilterProxyModel proxy; - proxy.setSourceModel(&source); - QCOMPARE(proxy.mapFromSource(source.index(5, 4)), proxy.index(5, 4)); - QCOMPARE(proxy.mapToSource(proxy.index(3, 2)), source.index(3, 2)); - QCOMPARE(proxy.mapFromSource(QModelIndex()), QModelIndex()); - QCOMPARE(proxy.mapToSource(QModelIndex()), QModelIndex()); - -#ifdef QT_NO_DEBUG //if Qt is compiled in debug mode, this will assert - QTest::ignoreMessage(QtWarningMsg, "QSortFilterProxyModel: index from wrong model passed to mapToSource"); - QCOMPARE(proxy.mapToSource(source.index(2, 3)), QModelIndex()); - QTest::ignoreMessage(QtWarningMsg, "QSortFilterProxyModel: index from wrong model passed to mapFromSource"); - QCOMPARE(proxy.mapFromSource(proxy.index(6, 2)), QModelIndex()); -#endif -} - -static QStandardItem *addEntry(QStandardItem* pParent, const QString &description) -{ - QStandardItem* pItem = new QStandardItem(description); - pParent->appendRow(pItem); - return pItem; -} - -void tst_QSortFilterProxyModel::removeRowsRecursive() -{ - QStandardItemModel pModel; - QStandardItem *pItem1 = new QStandardItem("root"); - pModel.appendRow(pItem1); - QList items; - - QStandardItem *pItem11 = addEntry(pItem1,"Sub-heading"); - items << pItem11; - QStandardItem *pItem111 = addEntry(pItem11,"A"); - items << pItem111; - items << addEntry(pItem111,"A1"); - items << addEntry(pItem111,"A2"); - QStandardItem *pItem112 = addEntry(pItem11,"B"); - items << pItem112; - items << addEntry(pItem112,"B1"); - items << addEntry(pItem112,"B2"); - QStandardItem *pItem1123 = addEntry(pItem112,"B3"); - items << pItem1123; - items << addEntry(pItem1123,"B3-"); - - QSortFilterProxyModel proxy; - proxy.setSourceModel(&pModel); - - QList sourceIndexes; - QList proxyIndexes; - foreach (QStandardItem *item, items) { - QModelIndex idx = item->index(); - sourceIndexes << idx; - proxyIndexes << proxy.mapFromSource(idx); - } - - foreach (const QPersistentModelIndex &pidx, sourceIndexes) - QVERIFY(pidx.isValid()); - foreach (const QPersistentModelIndex &pidx, proxyIndexes) - QVERIFY(pidx.isValid()); - - QList itemRow = pItem1->takeRow(0); - - QCOMPARE(itemRow.count(), 1); - QCOMPARE(itemRow.first(), pItem11); - - foreach (const QPersistentModelIndex &pidx, sourceIndexes) - QVERIFY(!pidx.isValid()); - foreach (const QPersistentModelIndex &pidx, proxyIndexes) - QVERIFY(!pidx.isValid()); - - delete pItem11; -} - -void tst_QSortFilterProxyModel::doubleProxySelectionSetSourceModel() -{ - QStandardItemModel *model1 = new QStandardItemModel; - QStandardItem *parentItem = model1->invisibleRootItem(); - for (int i = 0; i < 4; ++i) { - QStandardItem *item = new QStandardItem(QLatin1String("model1 item ") + QString::number(i)); - parentItem->appendRow(item); - parentItem = item; - } - - QStandardItemModel *model2 = new QStandardItemModel; - QStandardItem *parentItem2 = model2->invisibleRootItem(); - for (int i = 0; i < 4; ++i) { - QStandardItem *item = new QStandardItem(QLatin1String("model2 item ") + QString::number(i)); - parentItem2->appendRow(item); - parentItem2 = item; - } - - QSortFilterProxyModel *toggleProxy = new QSortFilterProxyModel; - toggleProxy->setSourceModel(model1); - - QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel; - proxyModel->setSourceModel(toggleProxy); - - QModelIndex mi = proxyModel->index(0, 0, proxyModel->index(0, 0, proxyModel->index(0, 0))); - QItemSelectionModel ism(proxyModel); - ism.select(mi, QItemSelectionModel::Select); - QModelIndexList mil = ism.selectedIndexes(); - QCOMPARE(mil.count(), 1); - QCOMPARE(mil.first(), mi); - - toggleProxy->setSourceModel(model2); - // No crash, it's good news! - QVERIFY(ism.selection().isEmpty()); -} - -void tst_QSortFilterProxyModel::appearsAndSort() -{ - class PModel : public QSortFilterProxyModel - { - public: - PModel() : mVisible(false) {}; - protected: - bool filterAcceptsRow(int, const QModelIndex &) const - { - return mVisible; - } - - public: - void updateXX() - { - mVisible = true; - invalidate(); - } - private: - bool mVisible; - } proxyModel; - - QStringListModel sourceModel; - QStringList list; - list << "b" << "a" << "c"; - sourceModel.setStringList(list); - - proxyModel.setSourceModel(&sourceModel); - proxyModel.setDynamicSortFilter(true); - proxyModel.sort(0, Qt::AscendingOrder); - - QApplication::processEvents(); - QCOMPARE(sourceModel.rowCount(), 3); - QCOMPARE(proxyModel.rowCount(), 0); //all rows are hidden at first; - - QSignalSpy spyAbout1(&proxyModel, &PModel::layoutAboutToBeChanged); - QSignalSpy spyChanged1(&proxyModel, &PModel::layoutChanged); - - QVERIFY(spyAbout1.isValid()); - QVERIFY(spyChanged1.isValid()); - - //introducing secondProxyModel to test the layoutChange when many items appears at once - QSortFilterProxyModel secondProxyModel; - secondProxyModel.setSourceModel(&proxyModel); - secondProxyModel.setDynamicSortFilter(true); - secondProxyModel.sort(0, Qt::DescendingOrder); - QCOMPARE(secondProxyModel.rowCount(), 0); //all rows are hidden at first; - QSignalSpy spyAbout2(&secondProxyModel, &QSortFilterProxyModel::layoutAboutToBeChanged); - QSignalSpy spyChanged2(&secondProxyModel, &QSortFilterProxyModel::layoutChanged); - - QVERIFY(spyAbout2.isValid()); - QVERIFY(spyChanged2.isValid()); - - proxyModel.updateXX(); - QApplication::processEvents(); - //now rows should be visible, and sorted - QCOMPARE(proxyModel.rowCount(), 3); - QCOMPARE(proxyModel.data(proxyModel.index(0,0), Qt::DisplayRole).toString(), QString::fromLatin1("a")); - QCOMPARE(proxyModel.data(proxyModel.index(1,0), Qt::DisplayRole).toString(), QString::fromLatin1("b")); - QCOMPARE(proxyModel.data(proxyModel.index(2,0), Qt::DisplayRole).toString(), QString::fromLatin1("c")); - - //now rows should be visible, and sorted - QCOMPARE(secondProxyModel.rowCount(), 3); - QCOMPARE(secondProxyModel.data(secondProxyModel.index(0,0), Qt::DisplayRole).toString(), QString::fromLatin1("c")); - QCOMPARE(secondProxyModel.data(secondProxyModel.index(1,0), Qt::DisplayRole).toString(), QString::fromLatin1("b")); - QCOMPARE(secondProxyModel.data(secondProxyModel.index(2,0), Qt::DisplayRole).toString(), QString::fromLatin1("a")); - - QCOMPARE(spyAbout1.count(), 1); - QCOMPARE(spyChanged1.count(), 1); - QCOMPARE(spyAbout2.count(), 1); - QCOMPARE(spyChanged2.count(), 1); -} - -void tst_QSortFilterProxyModel::unnecessaryDynamicSorting() -{ - QStringListModel model; - const QStringList initial = QString("bravo charlie delta echo").split(QLatin1Char(' ')); - model.setStringList(initial); - QSortFilterProxyModel proxy; - proxy.setDynamicSortFilter(false); - proxy.setSourceModel(&model); - proxy.sort(Qt::AscendingOrder); - - //append two rows - int maxrows = proxy.rowCount(QModelIndex()); - model.insertRows(maxrows, 2); - model.setData(model.index(maxrows, 0), QString("alpha")); - model.setData(model.index(maxrows + 1, 0), QString("fondue")); - - //append new items to the initial string list and compare with model - QStringList expected = initial; - expected << QString("alpha") << QString("fondue"); - - //if bug 7716 is present, new rows were prepended, when they should have been appended - for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) { - QModelIndex index = proxy.index(row, 0, QModelIndex()); - QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expected.at(row)); - } -} - -class SelectionProxyModel : QAbstractProxyModel -{ - Q_OBJECT -public: - SelectionProxyModel() - : QAbstractProxyModel(), selectionModel(0) - { - } - - QModelIndex mapFromSource(QModelIndex const&) const - { return QModelIndex(); } - - QModelIndex mapToSource(QModelIndex const&) const - { return QModelIndex(); } - - QModelIndex index(int, int, const QModelIndex&) const - { return QModelIndex(); } - - QModelIndex parent(const QModelIndex&) const - { return QModelIndex(); } - - int rowCount(const QModelIndex&) const - { return 0; } - - int columnCount(const QModelIndex&) const - { return 0; } - - void setSourceModel( QAbstractItemModel *sourceModel ) - { - beginResetModel(); - disconnect( sourceModel, SIGNAL(modelAboutToBeReset()), this, SLOT(sourceModelAboutToBeReset()) ); - QAbstractProxyModel::setSourceModel( sourceModel ); - connect( sourceModel, SIGNAL(modelAboutToBeReset()), this, SLOT(sourceModelAboutToBeReset()) ); - endResetModel(); - } - - void setSelectionModel( QItemSelectionModel *_selectionModel ) - { - selectionModel = _selectionModel; - } - -private slots: - void sourceModelAboutToBeReset() - { - QVERIFY( selectionModel->selectedIndexes().size() == 1 ); - beginResetModel(); - } - - void sourceModelReset() - { - endResetModel(); - } - -private: - QItemSelectionModel *selectionModel; -}; - -void tst_QSortFilterProxyModel::testMultipleProxiesWithSelection() -{ - QStringListModel model; - const QStringList initial = QString("bravo charlie delta echo").split(QLatin1Char(' ')); - model.setStringList(initial); - - QSortFilterProxyModel proxy; - proxy.setSourceModel( &model ); - - SelectionProxyModel proxy1; - QSortFilterProxyModel proxy2; - - // Note that the order here matters. The order of the sourceAboutToBeReset - // exposes the bug in QSortFilterProxyModel. - proxy2.setSourceModel( &proxy ); - proxy1.setSourceModel( &proxy ); - - QItemSelectionModel selectionModel(&proxy2); - proxy1.setSelectionModel( &selectionModel ); - - selectionModel.select( proxy2.index( 0, 0 ), QItemSelectionModel::Select ); - - // trick the proxy into emitting begin/end reset signals. - proxy.setSourceModel(0); -} - -static bool isValid(const QItemSelection &selection) -{ - foreach (const QItemSelectionRange &range, selection) - if (!range.isValid()) - return false; - return true; -} - -void tst_QSortFilterProxyModel::mapSelectionFromSource() -{ - QStringListModel model; - const QStringList initial = QString("bravo charlie delta echo").split(QLatin1Char(' ')); - model.setStringList(initial); - - QSortFilterProxyModel proxy; - proxy.setDynamicSortFilter(true); - proxy.setFilterRegExp("d.*"); - proxy.setSourceModel(&model); - - // Only "delta" remains. - QCOMPARE(proxy.rowCount(), 1); - - QItemSelection selection; - QModelIndex charlie = model.index(1, 0); - selection.append(QItemSelectionRange(charlie, charlie)); - QModelIndex delta = model.index(2, 0); - selection.append(QItemSelectionRange(delta, delta)); - QModelIndex echo = model.index(3, 0); - selection.append(QItemSelectionRange(echo, echo)); - - QVERIFY(isValid(selection)); - - QItemSelection proxiedSelection = proxy.mapSelectionFromSource(selection); - - // Only "delta" is in the mapped result. - QCOMPARE(proxiedSelection.size(), 1); - QVERIFY(isValid(proxiedSelection)); -} - -class Model10287 : public QStandardItemModel -{ - Q_OBJECT - -public: - Model10287(QObject *parent = 0) - : QStandardItemModel(0, 1, parent) - { - parentItem = new QStandardItem("parent"); - parentItem->setData(false, Qt::UserRole); - appendRow(parentItem); - - childItem = new QStandardItem("child"); - childItem->setData(true, Qt::UserRole); - parentItem->appendRow(childItem); - - childItem2 = new QStandardItem("child2"); - childItem2->setData(true, Qt::UserRole); - parentItem->appendRow(childItem2); - } - - void removeChild() - { - childItem2->setData(false, Qt::UserRole); - parentItem->removeRow(0); - } - -private: - QStandardItem *parentItem, *childItem, *childItem2; -}; - -class Proxy10287 : public QSortFilterProxyModel -{ - Q_OBJECT - -public: - Proxy10287(QAbstractItemModel *model, QObject *parent = 0) - : QSortFilterProxyModel(parent) - { - setSourceModel(model); - setDynamicSortFilter(true); - } - -protected: - virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const - { - // Filter based on UserRole in model - QModelIndex i = sourceModel()->index(source_row, 0, source_parent); - return i.data(Qt::UserRole).toBool(); - } -}; - -void tst_QSortFilterProxyModel::unnecessaryMapCreation() -{ - Model10287 m; - Proxy10287 p(&m); - m.removeChild(); - // No assert failure, it passes. -} - -class FilteredColumnProxyModel : public QSortFilterProxyModel -{ - Q_OBJECT -public: - FilteredColumnProxyModel(QObject *parent = 0) - : QSortFilterProxyModel(parent) - { - } - -protected: - bool filterAcceptsColumn(int column, const QModelIndex & /* source_parent */) const - { - return column % 2 != 0; - } -}; - -void tst_QSortFilterProxyModel::filteredColumns() -{ - DynamicTreeModel *model = new DynamicTreeModel(this); - - FilteredColumnProxyModel *proxy = new FilteredColumnProxyModel(this); - proxy->setSourceModel(model); - - new QAbstractItemModelTester(proxy, this); - - ModelInsertCommand *insertCommand = new ModelInsertCommand(model, this); - insertCommand->setNumCols(2); - insertCommand->setStartRow(0); - insertCommand->setEndRow(0); - // Parent is QModelIndex() - insertCommand->doCommand(); -} - -class ChangableHeaderData : public QStringListModel -{ - Q_OBJECT -public: - explicit ChangableHeaderData(QObject *parent = 0) - : QStringListModel(parent) - { - - } - - void emitHeaderDataChanged() - { - headerDataChanged(Qt::Vertical, 0, rowCount() - 1); - } -}; - - -void tst_QSortFilterProxyModel::headerDataChanged() -{ - ChangableHeaderData *model = new ChangableHeaderData(this); - - QStringList numbers; - for (int i = 0; i < 10; ++i) - numbers.append(QString::number(i)); - model->setStringList(numbers); - - QSortFilterProxyModel *proxy = new QSortFilterProxyModel(this); - proxy->setSourceModel(model); - - new QAbstractItemModelTester(proxy, this); - - model->emitHeaderDataChanged(); -} - -void tst_QSortFilterProxyModel::resetInvalidate_data() -{ - QTest::addColumn("test"); - QTest::addColumn("works"); - - QTest::newRow("nothing") << 0 << false; - QTest::newRow("reset") << 1 << true; - QTest::newRow("invalidate") << 2 << true; - QTest::newRow("invalidate_filter") << 3 << true; -} - -void tst_QSortFilterProxyModel::resetInvalidate() -{ - QFETCH(int, test); - QFETCH(bool, works); - - struct Proxy : QSortFilterProxyModel { - QString pattern; - virtual bool filterAcceptsRow(int source_row, const QModelIndex&) const - { - return sourceModel()->data(sourceModel()->index(source_row, 0)).toString().contains(pattern); - } - void notifyChange(int test) - { - switch (test) { - case 0: break; - case 1: - beginResetModel(); - endResetModel(); - break; - case 2: invalidate(); break; - case 3: invalidateFilter(); break; - } - } - }; - - QStringListModel sourceModel(QStringList() << "Poisson" << "Vache" << "Brebis" - << "Elephant" << "Cochon" << "Serpent" - << "Mouton" << "Ecureuil" << "Mouche"); - Proxy proxy; - proxy.pattern = QString::fromLatin1("n"); - proxy.setSourceModel(&sourceModel); - - QCOMPARE(proxy.rowCount(), 5); - for (int i = 0; i < proxy.rowCount(); i++) { - QVERIFY(proxy.data(proxy.index(i,0)).toString().contains('n')); - } - - proxy.pattern = QString::fromLatin1("o"); - proxy.notifyChange(test); - - QCOMPARE(proxy.rowCount(), works ? 4 : 5); - bool ok = true; - for (int i = 0; i < proxy.rowCount(); i++) { - if (!proxy.data(proxy.index(i,0)).toString().contains('o')) - ok = false; - } - QCOMPARE(ok, works); -} - -/** - * A proxy which changes the background color for items ending in 'y' or 'r' - */ -class CustomDataProxy : public QSortFilterProxyModel -{ - Q_OBJECT - -public: - CustomDataProxy(QObject *parent = 0) - : QSortFilterProxyModel(parent) - { - setDynamicSortFilter(true); - } - - void setSourceModel(QAbstractItemModel *sourceModel) - { - // It would be possible to use only the modelReset signal of the source model to clear - // the data in *this, however, this requires that the slot is connected - // before QSortFilterProxyModel::setSourceModel is called, and even then depends - // on the order of invocation of slots being the same as the order of connection. - // ie, not reliable. -// connect(sourceModel, SIGNAL(modelReset()), SLOT(resetInternalData())); - QSortFilterProxyModel::setSourceModel(sourceModel); - // Making the connect after the setSourceModel call clears the data too late. -// connect(sourceModel, SIGNAL(modelReset()), SLOT(resetInternalData())); - - // This could be done in data(), but the point is to need to cache something in the proxy - // which needs to be cleared on reset. - for (int i = 0; i < sourceModel->rowCount(); ++i) - { - if (sourceModel->index(i, 0).data().toString().endsWith(QLatin1Char('y'))) - { - m_backgroundColours.insert(i, Qt::blue); - } else if (sourceModel->index(i, 0).data().toString().endsWith(QLatin1Char('r'))) - { - m_backgroundColours.insert(i, Qt::red); - } - } - } - - QVariant data(const QModelIndex &index, int role) const - { - if (role != Qt::BackgroundRole) - return QSortFilterProxyModel::data(index, role); - return m_backgroundColours.value(index.row()); - } - -private slots: - void resetInternalData() - { - m_backgroundColours.clear(); - } - -private: - QHash m_backgroundColours; -}; - -class ModelObserver : public QObject -{ - Q_OBJECT -public: - ModelObserver(QAbstractItemModel *model, QObject *parent = 0) - : QObject(parent), m_model(model) - { - connect(m_model, SIGNAL(modelAboutToBeReset()), SLOT(modelAboutToBeReset())); - connect(m_model, SIGNAL(modelReset()), SLOT(modelReset())); - } - -public slots: - void modelAboutToBeReset() - { - int reds = 0, blues = 0; - for (int i = 0; i < m_model->rowCount(); ++i) - { - QColor color = m_model->index(i, 0).data(Qt::BackgroundRole).value(); - if (color == Qt::blue) - ++blues; - if (color == Qt::red) - ++reds; - } - QCOMPARE(blues, 11); - QCOMPARE(reds, 4); - } - - void modelReset() - { - int reds = 0, blues = 0; - for (int i = 0; i < m_model->rowCount(); ++i) - { - QColor color = m_model->index(i, 0).data(Qt::BackgroundRole).value(); - if (color == Qt::blue) - ++blues; - if (color == Qt::red) - ++reds; - } - QCOMPARE(reds, 0); - QCOMPARE(blues, 0); - } - -private: - QAbstractItemModel * const m_model; - -}; - -void tst_QSortFilterProxyModel::testResetInternalData() -{ - - QStringListModel model(QStringList() << "Monday" - << "Tuesday" - << "Wednesday" - << "Thursday" - << "Friday" - << "January" - << "February" - << "March" - << "April" - << "May" - << "Saturday" - << "June" - << "Sunday" - << "July" - << "August" - << "September" - << "October" - << "November" - << "December"); - - CustomDataProxy proxy; - proxy.setSourceModel(&model); - - ModelObserver observer(&proxy); - - // Cause the source model to reset. - model.setStringList(QStringList() << "Spam" << "Eggs"); - -} - -void tst_QSortFilterProxyModel::testParentLayoutChanged() -{ - QStandardItemModel model; - QStandardItem *parentItem = model.invisibleRootItem(); - for (int i = 0; i < 4; ++i) { - { - QStandardItem *item = new QStandardItem(QLatin1String("item ") + QString::number(i)); - parentItem->appendRow(item); - } - { - QStandardItem *item = new QStandardItem(QLatin1String("item 1") + QString::number(i)); - parentItem->appendRow(item); - parentItem = item; - } - } - // item 0 - // item 10 - // - item 1 - // - item 11 - // - item 2 - // - item 12 - // ... - - QSortFilterProxyModel proxy; - proxy.sort(0, Qt::AscendingOrder); - proxy.setDynamicSortFilter(true); - - proxy.setSourceModel(&model); - proxy.setObjectName("proxy"); - - // When Proxy1 emits layoutChanged(QList) this - // one will too, with mapped indexes. - QSortFilterProxyModel proxy2; - proxy2.sort(0, Qt::AscendingOrder); - proxy2.setDynamicSortFilter(true); - - proxy2.setSourceModel(&proxy); - proxy2.setObjectName("proxy2"); - - QSignalSpy dataChangedSpy(&model, &QSortFilterProxyModel::dataChanged); - - QVERIFY(dataChangedSpy.isValid()); - - // Verify that the no-arg signal is still emitted. - QSignalSpy layoutAboutToBeChangedSpy(&proxy, &QSortFilterProxyModel::layoutAboutToBeChanged); - QSignalSpy layoutChangedSpy(&proxy, &QSortFilterProxyModel::layoutChanged); - - QVERIFY(layoutAboutToBeChangedSpy.isValid()); - QVERIFY(layoutChangedSpy.isValid()); - - QSignalSpy parentsAboutToBeChangedSpy(&proxy, &QSortFilterProxyModel::layoutAboutToBeChanged); - QSignalSpy parentsChangedSpy(&proxy, &QSortFilterProxyModel::layoutChanged); - - QVERIFY(parentsAboutToBeChangedSpy.isValid()); - QVERIFY(parentsChangedSpy.isValid()); - - QSignalSpy proxy2ParentsAboutToBeChangedSpy(&proxy2, &QSortFilterProxyModel::layoutAboutToBeChanged); - QSignalSpy proxy2ParentsChangedSpy(&proxy2, &QSortFilterProxyModel::layoutChanged); - - QVERIFY(proxy2ParentsAboutToBeChangedSpy.isValid()); - QVERIFY(proxy2ParentsChangedSpy.isValid()); - - QStandardItem *item = model.invisibleRootItem()->child(1)->child(1); - QCOMPARE(item->text(), QStringLiteral("item 11")); - - // Ensure mapped: - proxy.mapFromSource(model.indexFromItem(item)); - - item->setText("Changed"); - - QCOMPARE(dataChangedSpy.size(), 1); - QCOMPARE(layoutAboutToBeChangedSpy.size(), 1); - QCOMPARE(layoutChangedSpy.size(), 1); - QCOMPARE(parentsAboutToBeChangedSpy.size(), 1); - QCOMPARE(parentsChangedSpy.size(), 1); - QCOMPARE(proxy2ParentsAboutToBeChangedSpy.size(), 1); - QCOMPARE(proxy2ParentsChangedSpy.size(), 1); - - QVariantList beforeSignal = parentsAboutToBeChangedSpy.first(); - QVariantList afterSignal = parentsChangedSpy.first(); - - QCOMPARE(beforeSignal.size(), 2); - QCOMPARE(afterSignal.size(), 2); - - QList beforeParents = beforeSignal.first().value >(); - QList afterParents = afterSignal.first().value >(); - - QCOMPARE(beforeParents.size(), 1); - QCOMPARE(afterParents.size(), 1); - - QVERIFY(beforeParents.first().isValid()); - QVERIFY(beforeParents.first() == afterParents.first()); - - QVERIFY(beforeParents.first() == proxy.mapFromSource(model.indexFromItem(model.invisibleRootItem()->child(1)))); - - QList proxy2BeforeList = proxy2ParentsAboutToBeChangedSpy.first().first().value >(); - QList proxy2AfterList = proxy2ParentsChangedSpy.first().first().value >(); - - QCOMPARE(proxy2BeforeList.size(), beforeParents.size()); - QCOMPARE(proxy2AfterList.size(), afterParents.size()); - foreach (const QPersistentModelIndex &idx, proxy2BeforeList) - QVERIFY(beforeParents.contains(proxy2.mapToSource(idx))); - foreach (const QPersistentModelIndex &idx, proxy2AfterList) - QVERIFY(afterParents.contains(proxy2.mapToSource(idx))); -} - -class SignalArgumentChecker : public QObject -{ - Q_OBJECT -public: - SignalArgumentChecker(QAbstractItemModel *model, QAbstractProxyModel *proxy, QObject *parent = 0) - : QObject(parent), m_proxy(proxy) - { - connect(model, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), SLOT(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int))); - connect(model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), SLOT(rowsMoved(QModelIndex,int,int,QModelIndex,int))); - connect(proxy, SIGNAL(layoutAboutToBeChanged(QList)), SLOT(layoutAboutToBeChanged(QList))); - connect(proxy, SIGNAL(layoutChanged(QList)), SLOT(layoutChanged(QList))); - } - -private slots: - void rowsAboutToBeMoved(const QModelIndex &source, int, int, const QModelIndex &destination, int) - { - m_p1PersistentBefore = source; - m_p2PersistentBefore = destination; - m_p2FirstProxyChild = m_proxy->index(0, 0, m_proxy->mapFromSource(destination)); - } - - void rowsMoved(const QModelIndex &source, int, int, const QModelIndex &destination, int) - { - m_p1PersistentAfter = source; - m_p2PersistentAfter = destination; - } - - void layoutAboutToBeChanged(const QList &parents) - { - QVERIFY(m_p1PersistentBefore.isValid()); - QVERIFY(m_p2PersistentBefore.isValid()); - QCOMPARE(parents.size(), 2); - QVERIFY(parents.first() != parents.at(1)); - QVERIFY(parents.contains(m_proxy->mapFromSource(m_p1PersistentBefore))); - QVERIFY(parents.contains(m_proxy->mapFromSource(m_p2PersistentBefore))); - } - - void layoutChanged(const QList &parents) - { - QVERIFY(m_p1PersistentAfter.isValid()); - QVERIFY(m_p2PersistentAfter.isValid()); - QCOMPARE(parents.size(), 2); - QVERIFY(parents.first() != parents.at(1)); - QVERIFY(parents.contains(m_proxy->mapFromSource(m_p1PersistentAfter))); - QVERIFY(parents.contains(m_proxy->mapFromSource(m_p2PersistentAfter))); - - // In the source model, the rows were moved to row 1 in the parent. - // m_p2FirstProxyChild was created with row 0 in the proxy. - // The moved rows in the proxy do not appear at row 1 because of sorting. - // Sorting causes them to appear at row 0 instead, pushing what used to - // be row 0 in the proxy down by two rows. - QCOMPARE(m_p2FirstProxyChild.row(), 2); - } - -private: - QAbstractProxyModel *m_proxy; - QPersistentModelIndex m_p1PersistentBefore; - QPersistentModelIndex m_p2PersistentBefore; - QPersistentModelIndex m_p1PersistentAfter; - QPersistentModelIndex m_p2PersistentAfter; - - QPersistentModelIndex m_p2FirstProxyChild; -}; - -void tst_QSortFilterProxyModel::moveSourceRows() -{ - DynamicTreeModel model; - - { - ModelInsertCommand insertCommand(&model); - insertCommand.setStartRow(0); - insertCommand.setEndRow(9); - insertCommand.doCommand(); - } - { - ModelInsertCommand insertCommand(&model); - insertCommand.setAncestorRowNumbers(QList() << 2); - insertCommand.setStartRow(0); - insertCommand.setEndRow(9); - insertCommand.doCommand(); - } - { - ModelInsertCommand insertCommand(&model); - insertCommand.setAncestorRowNumbers(QList() << 5); - insertCommand.setStartRow(0); - insertCommand.setEndRow(9); - insertCommand.doCommand(); - } - - QSortFilterProxyModel proxy; - proxy.setDynamicSortFilter(true); - proxy.sort(0, Qt::AscendingOrder); - - // We need to check the arguments at emission time - SignalArgumentChecker checker(&model, &proxy); - - proxy.setSourceModel(&model); - - QSortFilterProxyModel filterProxy; - filterProxy.setDynamicSortFilter(true); - filterProxy.sort(0, Qt::AscendingOrder); - filterProxy.setSourceModel(&proxy); - filterProxy.setFilterRegExp("6"); // One of the parents - - QSortFilterProxyModel filterBothProxy; - filterBothProxy.setDynamicSortFilter(true); - filterBothProxy.sort(0, Qt::AscendingOrder); - filterBothProxy.setSourceModel(&proxy); - filterBothProxy.setFilterRegExp("5"); // The parents are 6 and 3. This filters both out. - - QSignalSpy modelBeforeSpy(&model, &DynamicTreeModel::rowsAboutToBeMoved); - QSignalSpy modelAfterSpy(&model, &DynamicTreeModel::rowsMoved); - QSignalSpy proxyBeforeMoveSpy(m_proxy, &QSortFilterProxyModel::rowsAboutToBeMoved); - QSignalSpy proxyAfterMoveSpy(m_proxy, &QSortFilterProxyModel::rowsMoved); - QSignalSpy proxyBeforeParentLayoutSpy(&proxy, &QSortFilterProxyModel::layoutAboutToBeChanged); - QSignalSpy proxyAfterParentLayoutSpy(&proxy, &QSortFilterProxyModel::layoutChanged); - QSignalSpy filterBeforeParentLayoutSpy(&filterProxy, &QSortFilterProxyModel::layoutAboutToBeChanged); - QSignalSpy filterAfterParentLayoutSpy(&filterProxy, &QSortFilterProxyModel::layoutChanged); - QSignalSpy filterBothBeforeParentLayoutSpy(&filterBothProxy, &QSortFilterProxyModel::layoutAboutToBeChanged); - QSignalSpy filterBothAfterParentLayoutSpy(&filterBothProxy, &QSortFilterProxyModel::layoutChanged); - - QVERIFY(modelBeforeSpy.isValid()); - QVERIFY(modelAfterSpy.isValid()); - QVERIFY(proxyBeforeMoveSpy.isValid()); - QVERIFY(proxyAfterMoveSpy.isValid()); - QVERIFY(proxyBeforeParentLayoutSpy.isValid()); - QVERIFY(proxyAfterParentLayoutSpy.isValid()); - QVERIFY(filterBeforeParentLayoutSpy.isValid()); - QVERIFY(filterAfterParentLayoutSpy.isValid()); - QVERIFY(filterBothBeforeParentLayoutSpy.isValid()); - QVERIFY(filterBothAfterParentLayoutSpy.isValid()); - - { - ModelMoveCommand moveCommand(&model, 0); - moveCommand.setAncestorRowNumbers(QList() << 2); - moveCommand.setDestAncestors(QList() << 5); - moveCommand.setStartRow(3); - moveCommand.setEndRow(4); - moveCommand.setDestRow(1); - moveCommand.doCommand(); - } - - // Proxy notifies layout change - QCOMPARE(modelBeforeSpy.size(), 1); - QCOMPARE(proxyBeforeParentLayoutSpy.size(), 1); - QCOMPARE(modelAfterSpy.size(), 1); - QCOMPARE(proxyAfterParentLayoutSpy.size(), 1); - - // But it doesn't notify a move. - QCOMPARE(proxyBeforeMoveSpy.size(), 0); - QCOMPARE(proxyAfterMoveSpy.size(), 0); - - QCOMPARE(filterBeforeParentLayoutSpy.size(), 1); - QCOMPARE(filterAfterParentLayoutSpy.size(), 1); - - QList filterBeforeParents = filterBeforeParentLayoutSpy.first().first().value >(); - QList filterAfterParents = filterAfterParentLayoutSpy.first().first().value >(); - - QCOMPARE(filterBeforeParents.size(), 1); - QCOMPARE(filterAfterParents.size(), 1); - - QCOMPARE( - filterBeforeParentLayoutSpy.first().at(1).value(), - QAbstractItemModel::NoLayoutChangeHint); - QCOMPARE(filterAfterParentLayoutSpy.first().at(1).value(), - QAbstractItemModel::NoLayoutChangeHint); - - QCOMPARE(filterBothBeforeParentLayoutSpy.size(), 0); - QCOMPARE(filterBothAfterParentLayoutSpy.size(), 0); -} - -class FilterProxy : public QSortFilterProxyModel -{ - Q_OBJECT -public: - FilterProxy(QObject *parent = 0) - : QSortFilterProxyModel(parent), - mode(false) - { - - } - -public slots: - void setMode(bool on) - { - mode = on; - invalidateFilter(); - } - -protected: - virtual bool filterAcceptsRow ( int source_row, const QModelIndex & source_parent ) const - { - if (mode) { - if (!source_parent.isValid()) { - return true; - } else { - return (source_row % 2) != 0; - } - } else { - if (!source_parent.isValid()) { - return source_row >= 2 && source_row < 10; - } else { - return true; - } - } - } - -private: - bool mode; -}; - -void tst_QSortFilterProxyModel::hierarchyFilterInvalidation() -{ - QStandardItemModel model; - for (int i = 0; i < 10; ++i) { - const QString rowText = QLatin1String("Row ") + QString::number(i); - QStandardItem *child = new QStandardItem(rowText); - for (int j = 0; j < 1; ++j) { - child->appendRow(new QStandardItem(rowText + QLatin1Char('/') + QString::number(j))); - } - model.appendRow(child); - } - - FilterProxy proxy; - proxy.setSourceModel(&model); - - QTreeView view; - view.setModel(&proxy); - - view.setCurrentIndex(proxy.index(2, 0).child(0, 0)); - - view.show(); - QVERIFY(QTest::qWaitForWindowExposed(&view)); - - proxy.setMode(true); -} - -class FilterProxy2 : public QSortFilterProxyModel -{ - Q_OBJECT -public: - FilterProxy2(QObject *parent = 0) - : QSortFilterProxyModel(parent), - mode(false) - { - - } - -public slots: - void setMode(bool on) - { - mode = on; - invalidateFilter(); - } - -protected: - virtual bool filterAcceptsRow ( int source_row, const QModelIndex & source_parent ) const - { - if (source_parent.isValid()) { - return true; - } else { - if (0 == source_row) { - return true; - } else { - return !mode; - } - } - } - -private: - bool mode; -}; - -void tst_QSortFilterProxyModel::simpleFilterInvalidation() -{ - QStandardItemModel model; - for (int i = 0; i < 2; ++i) { - QStandardItem *child = new QStandardItem(QLatin1String("Row ") + QString::number(i)); - child->appendRow(new QStandardItem("child")); - model.appendRow(child); - } - - FilterProxy2 proxy; - proxy.setSourceModel(&model); - - QTreeView view; - view.setModel(&proxy); - - view.show(); - QVERIFY(QTest::qWaitForWindowExposed(&view)); - - proxy.setMode(true); - model.insertRow(0, new QStandardItem("extra")); -} - -class CustomRoleNameModel : public QAbstractListModel -{ - Q_OBJECT -public: - CustomRoleNameModel(QObject *parent = 0) : QAbstractListModel(parent) {} - - QVariant data(const QModelIndex &index, int role) const - { - Q_UNUSED(index); - Q_UNUSED(role); - return QVariant(); - } - - int rowCount(const QModelIndex &parent = QModelIndex()) const - { - Q_UNUSED(parent); - return 0; - } - - QHash roleNames() const - { - QHash rn = QAbstractListModel::roleNames(); - rn[Qt::UserRole + 1] = "custom"; - return rn; - } -}; - -void tst_QSortFilterProxyModel::chainedProxyModelRoleNames() -{ - QSortFilterProxyModel proxy1; - QSortFilterProxyModel proxy2; - CustomRoleNameModel customModel; - - proxy2.setSourceModel(&proxy1); - - // changing the sourceModel of proxy1 must also update roleNames of proxy2 - proxy1.setSourceModel(&customModel); - QVERIFY(proxy2.roleNames().value(Qt::UserRole + 1) == "custom"); -} - -// A source model with ABABAB rows, where only A rows accept drops. -// It will then be sorted by a QSFPM. -class DropOnOddRows : public QAbstractListModel -{ - Q_OBJECT -public: - DropOnOddRows(QObject *parent = 0) : QAbstractListModel(parent) {} - - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override - { - if (role == Qt::DisplayRole) - return (index.row() % 2 == 0) ? "A" : "B"; - return QVariant(); - } - - int rowCount(const QModelIndex &parent = QModelIndex()) const override - { - Q_UNUSED(parent); - return 10; - } - - bool canDropMimeData(const QMimeData *, Qt::DropAction, - int row, int column, const QModelIndex &parent) const override - { - Q_UNUSED(row); - Q_UNUSED(column); - return parent.row() % 2 == 0; - } -}; - -class SourceAssertion : public QSortFilterProxyModel -{ - Q_OBJECT -public: - explicit SourceAssertion(QObject *parent = 0) - : QSortFilterProxyModel(parent) - { - - } - - QModelIndex mapToSource(const QModelIndex &proxyIndex) const override - { - Q_ASSERT(sourceModel()); - return QSortFilterProxyModel::mapToSource(proxyIndex); - } -}; - -void tst_QSortFilterProxyModel::noMapAfterSourceDelete() -{ - SourceAssertion proxy; - QStringListModel *model = new QStringListModel(QStringList() << "Foo" << "Bar"); - - proxy.setSourceModel(model); - - // Create mappings - QPersistentModelIndex persistent = proxy.index(0, 0); - - QVERIFY(persistent.isValid()); - - delete model; - - QVERIFY(!persistent.isValid()); -} - -// QTBUG-39549, test whether canDropMimeData(), dropMimeData() are proxied as well -// by invoking them on a QSortFilterProxyModel proxying a QStandardItemModel that allows drops -// on row #1, filtering for that row. -class DropTestModel : public QStandardItemModel { -public: - explicit DropTestModel(QObject *parent = 0) : QStandardItemModel(0, 1, parent) - { - appendRow(new QStandardItem(QStringLiteral("Row0"))); - appendRow(new QStandardItem(QStringLiteral("Row1"))); - } - - bool canDropMimeData(const QMimeData *, Qt::DropAction, - int row, int /* column */, const QModelIndex & /* parent */) const override - { return row == 1; } - - bool dropMimeData(const QMimeData *, Qt::DropAction, - int row, int /* column */, const QModelIndex & /* parent */) override - { return row == 1; } -}; - -void tst_QSortFilterProxyModel::forwardDropApi() -{ - QSortFilterProxyModel model; - model.setSourceModel(new DropTestModel(&model)); - model.setFilterFixedString(QStringLiteral("Row1")); - QCOMPARE(model.rowCount(), 1); - QVERIFY(model.canDropMimeData(0, Qt::CopyAction, 0, 0, QModelIndex())); - QVERIFY(model.dropMimeData(0, Qt::CopyAction, 0, 0, QModelIndex())); -} - -static QString rowTexts(QAbstractItemModel *model) { - QString str; - for (int row = 0 ; row < model->rowCount(); ++row) - str += model->index(row, 0).data().toString(); - return str; -} - -void tst_QSortFilterProxyModel::canDropMimeData() -{ - // Given a source model which only supports dropping on even rows - DropOnOddRows sourceModel; - QCOMPARE(rowTexts(&sourceModel), QString("ABABABABAB")); - - // and a proxy model that sorts the rows - QSortFilterProxyModel proxy; - proxy.setSourceModel(&sourceModel); - proxy.sort(0, Qt::AscendingOrder); - QCOMPARE(rowTexts(&proxy), QString("AAAAABBBBB")); - - // the proxy should correctly map canDropMimeData to the source model, - // i.e. accept drops on the first 5 rows and refuse drops on the next 5. - for (int row = 0; row < proxy.rowCount(); ++row) - QCOMPARE(proxy.canDropMimeData(0, Qt::CopyAction, -1, -1, proxy.index(row, 0)), row < 5); -} - -void tst_QSortFilterProxyModel::resortingDoesNotBreakTreeModels() -{ - QStandardItemModel *treeModel = new QStandardItemModel(this); - QStandardItem *e1 = new QStandardItem("Loading..."); - e1->appendRow(new QStandardItem("entry10")); - treeModel->appendRow(e1); - QStandardItem *e0 = new QStandardItem("Loading..."); - e0->appendRow(new QStandardItem("entry00")); - e0->appendRow(new QStandardItem("entry01")); - treeModel->appendRow(e0); - - QSortFilterProxyModel proxy; - proxy.setDynamicSortFilter(true); - proxy.sort(0); - proxy.setSourceModel(treeModel); - - QAbstractItemModelTester modelTester(&proxy); - - QCOMPARE(proxy.rowCount(), 2); - e1->setText("entry1"); - e0->setText("entry0"); - - QModelIndex pi0 = proxy.index(0, 0); - QCOMPARE(pi0.data().toString(), QString("entry0")); - QCOMPARE(proxy.rowCount(pi0), 2); - - QModelIndex pi01 = proxy.index(1, 0, pi0); - QCOMPARE(pi01.data().toString(), QString("entry01")); - - QModelIndex pi1 = proxy.index(1, 0); - QCOMPARE(pi1.data().toString(), QString("entry1")); - QCOMPARE(proxy.rowCount(pi1), 1); -} - -void tst_QSortFilterProxyModel::filterHint() -{ - // test that a filtering model does not emit layoutChanged with a hint - QStringListModel model(QStringList() << "one" - << "two" - << "three" - << "four" - << "five" - << "six"); - QSortFilterProxyModel proxy1; - proxy1.setSourceModel(&model); - proxy1.setSortRole(Qt::DisplayRole); - proxy1.setDynamicSortFilter(true); - proxy1.sort(0); - - QSortFilterProxyModel proxy2; - proxy2.setSourceModel(&proxy1); - proxy2.setFilterRole(Qt::DisplayRole); - proxy2.setFilterRegExp("^[^ ]*$"); - proxy2.setDynamicSortFilter(true); - - QSignalSpy proxy1BeforeSpy(&proxy1, &QSortFilterProxyModel::layoutAboutToBeChanged); - QSignalSpy proxy1AfterSpy(&proxy1, &QSortFilterProxyModel::layoutChanged); - QSignalSpy proxy2BeforeSpy(&proxy2, &QSortFilterProxyModel::layoutAboutToBeChanged); - QSignalSpy proxy2AfterSpy(&proxy2, &QSortFilterProxyModel::layoutChanged); - - model.setData(model.index(2), QStringLiteral("modified three"), Qt::DisplayRole); - - // The first proxy was re-sorted as one item as changed. - QCOMPARE(proxy1BeforeSpy.size(), 1); - QCOMPARE(proxy1BeforeSpy.first().at(1).value(), - QAbstractItemModel::VerticalSortHint); - QCOMPARE(proxy1AfterSpy.size(), 1); - QCOMPARE(proxy1AfterSpy.first().at(1).value(), - QAbstractItemModel::VerticalSortHint); - - // But the second proxy must not have the VerticalSortHint since an item was filtered - QCOMPARE(proxy2BeforeSpy.size(), 1); - QCOMPARE(proxy2BeforeSpy.first().at(1).value(), - QAbstractItemModel::NoLayoutChangeHint); - QCOMPARE(proxy2AfterSpy.size(), 1); - QCOMPARE(proxy2AfterSpy.first().at(1).value(), - QAbstractItemModel::NoLayoutChangeHint); -} - -/** - - Creates a model where each item has one child, to a set depth, - and the last item has no children. For a model created with - setDepth(4): - - - 1 - - - 2 - - - - 3 - - - - - 4 -*/ -class StepTreeModel : public QAbstractItemModel -{ - Q_OBJECT -public: - StepTreeModel(QObject * parent = 0) - : QAbstractItemModel(parent), m_depth(0) {} - - int columnCount(const QModelIndex& = QModelIndex()) const override { return 1; } - - int rowCount(const QModelIndex& parent = QModelIndex()) const override - { - quintptr parentId = (parent.isValid()) ? parent.internalId() : 0; - return (parentId < m_depth) ? 1 : 0; - } - - QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override - { - if (role != Qt::DisplayRole) - return QVariant(); - - return QString::number(index.internalId()); - } - - QModelIndex index(int, int, const QModelIndex& parent = QModelIndex()) const override - { - // QTBUG-44962: Would we always expect the parent to belong to the model - qDebug() << parent.model() << this; - Q_ASSERT(!parent.isValid() || parent.model() == this); - - quintptr parentId = (parent.isValid()) ? parent.internalId() : 0; - if (parentId >= m_depth) - return QModelIndex(); - - return createIndex(0, 0, parentId + 1); - } - - QModelIndex parent(const QModelIndex& index) const override - { - if (index.internalId() == 0) - return QModelIndex(); - - return createIndex(0, 0, index.internalId() - 1); - } - - void setDepth(quintptr depth) - { - int parentIdWithLayoutChange = (m_depth < depth) ? m_depth : depth; - - QList parentsOfLayoutChange; - parentsOfLayoutChange.push_back(createIndex(0, 0, parentIdWithLayoutChange)); - - layoutAboutToBeChanged(parentsOfLayoutChange); - - auto existing = persistentIndexList(); - - QList updated; - - for (auto idx : existing) { - if (indexDepth(idx) <= depth) - updated.push_back(idx); - else - updated.push_back({}); - } - - m_depth = depth; - - changePersistentIndexList(existing, updated); - - layoutChanged(parentsOfLayoutChange); - } - -private: - static quintptr indexDepth(QModelIndex const& index) - { - return (index.isValid()) ? 1 + indexDepth(index.parent()) : 0; - } - -private: - quintptr m_depth; -}; - -void tst_QSortFilterProxyModel::sourceLayoutChangeLeavesValidPersistentIndexes() -{ - StepTreeModel model; - Q_SET_OBJECT_NAME(model); - model.setDepth(4); - - QSortFilterProxyModel proxy1; - proxy1.setSourceModel(&model); - Q_SET_OBJECT_NAME(proxy1); - - proxy1.setFilterRegExp("1|2"); - - // The current state of things: - // model proxy - // - 1 - 1 - // - - 2 - - 2 - // - - - 3 - // - - - - 4 - - // The setDepth call below removes '4' with a layoutChanged call. - // Because the proxy filters that out anyway, the proxy doesn't need - // to emit any signals or update persistent indexes. - - QPersistentModelIndex persistentIndex = proxy1.index(0, 0, proxy1.index(0, 0)); - - model.setDepth(3); - - // Calling parent() causes the internalPointer to be used. - // Before fixing QTBUG-47711, that could be a dangling pointer. - // The use of qDebug here makes sufficient use of the heap to - // cause corruption at runtime with normal use on linux (before - // the fix). valgrind confirms the fix. - qDebug() << persistentIndex.parent(); - QVERIFY(persistentIndex.parent().isValid()); -} - -void tst_QSortFilterProxyModel::rowMoveLeavesValidPersistentIndexes() -{ - DynamicTreeModel model; - Q_SET_OBJECT_NAME(model); - - QList ancestors; - for (auto i = 0; i < 5; ++i) - { - Q_UNUSED(i); - ModelInsertCommand insertCommand(&model); - insertCommand.setAncestorRowNumbers(ancestors); - insertCommand.setStartRow(0); - insertCommand.setEndRow(0); - insertCommand.doCommand(); - ancestors.push_back(0); - } - - QSortFilterProxyModel proxy1; - proxy1.setSourceModel(&model); - Q_SET_OBJECT_NAME(proxy1); - - proxy1.setFilterRegExp("1|2"); - - auto item5 = model.match(model.index(0, 0), Qt::DisplayRole, "5", 1, Qt::MatchRecursive).first(); - auto item3 = model.match(model.index(0, 0), Qt::DisplayRole, "3", 1, Qt::MatchRecursive).first(); - - Q_ASSERT(item5.isValid()); - Q_ASSERT(item3.isValid()); - - QPersistentModelIndex persistentIndex = proxy1.match(proxy1.index(0, 0), Qt::DisplayRole, "2", 1, Qt::MatchRecursive).first(); - - ModelMoveCommand moveCommand(&model, 0); - moveCommand.setAncestorRowNumbers(QList{0, 0, 0, 0}); - moveCommand.setStartRow(0); - moveCommand.setEndRow(0); - moveCommand.setDestRow(0); - moveCommand.setDestAncestors(QList{0, 0, 0}); - moveCommand.doCommand(); - - // Calling parent() causes the internalPointer to be used. - // Before fixing QTBUG-47711 (moveRows case), that could be - // a dangling pointer. - QVERIFY(persistentIndex.parent().isValid()); -} - -void tst_QSortFilterProxyModel::emitLayoutChangedOnlyIfSortingChanged_data() -{ - QTest::addColumn("changedRow"); - QTest::addColumn("changedRole"); - QTest::addColumn("newData"); - QTest::addColumn("expectedSourceRowTexts"); - QTest::addColumn("expectedProxyRowTexts"); - QTest::addColumn("expectedLayoutChanged"); - - // Starting point: - // a source model with 8,7,6,5,4,3,2,1 - // a proxy model keeping only even rows and sorting them, therefore showing 2,4,6,8 - - // When setData changes ordering, layoutChanged should be emitted - QTest::newRow("ordering_change") << 0 << Qt::DisplayRole << "0" << "07654321" << "0246" << 1; - - // When setData on visible row doesn't change ordering, layoutChanged should not be emitted - QTest::newRow("no_ordering_change") << 6 << Qt::DisplayRole << "0" << "87654301" << "0468" << 0; - - // When setData happens on a filtered out row, layoutChanged should not be emitted - QTest::newRow("filtered_out") << 1 << Qt::DisplayRole << "9" << "89654321" << "2468" << 0; - - // When setData makes a row visible, layoutChanged should not be emitted (rowsInserted is emitted instead) - QTest::newRow("make_row_visible") << 7 << Qt::DisplayRole << "0" << "87654320" << "02468" << 0; - - // When setData makes a row hidden, layoutChanged should not be emitted (rowsRemoved is emitted instead) - QTest::newRow("make_row_hidden") << 4 << Qt::DisplayRole << "1" << "87651321" << "268" << 0; - - // When setData happens on an unrelated role, layoutChanged should not be emitted - QTest::newRow("unrelated_role") << 0 << Qt::DecorationRole << "" << "87654321" << "2468" << 0; - - // When many changes happen together... and trigger removal, insertion, and layoutChanged - QTest::newRow("many_changes") << -1 << Qt::DisplayRole << "3,4,2,5,6,0,7,9" << "34256079" << "0246" << 1; - - // When many changes happen together... and trigger removal, insertion, but no change in ordering of visible rows => no layoutChanged - QTest::newRow("many_changes_no_layoutChanged") << -1 << Qt::DisplayRole << "7,5,4,3,2,1,0,8" << "75432108" << "0248" << 0; -} - -// Custom version of QStringListModel which supports emitting dataChanged for many rows at once -class CustomStringListModel : public QAbstractListModel -{ -public: - bool setData(const QModelIndex &index, const QVariant &value, int role) override - { - if (index.row() >= 0 && index.row() < lst.size() - && (role == Qt::EditRole || role == Qt::DisplayRole)) { - lst.replace(index.row(), value.toString()); - emit dataChanged(index, index, { Qt::DisplayRole, Qt::EditRole }); - return true; - } - return false; - } - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override - { - if (role == Qt::DisplayRole || role == Qt::EditRole) - return lst.at(index.row()); - return QVariant(); - } - int rowCount(const QModelIndex & = QModelIndex()) const override { return lst.count(); } - - void replaceData(const QStringList &newData) - { - lst = newData; - emit dataChanged(index(0, 0), index(rowCount() - 1, 0), { Qt::DisplayRole, Qt::EditRole }); - } - - void emitDecorationChangedSignal() - { - const QModelIndex idx = index(0, 0); - emit dataChanged(idx, idx, { Qt::DecorationRole }); - } - -private: - QStringList lst; -}; - -void tst_QSortFilterProxyModel::emitLayoutChangedOnlyIfSortingChanged() -{ - QFETCH(int, changedRow); - QFETCH(QString, newData); - QFETCH(Qt::ItemDataRole, changedRole); - QFETCH(QString, expectedSourceRowTexts); - QFETCH(QString, expectedProxyRowTexts); - QFETCH(int, expectedLayoutChanged); - - CustomStringListModel model; - QStringList strings; - for (auto i = 8; i >= 1; --i) - strings.append(QString::number(i)); - model.replaceData(strings); - QCOMPARE(rowTexts(&model), QStringLiteral("87654321")); - - class FilterEvenRowsProxyModel : public QSortFilterProxyModel - { - public: - bool filterAcceptsRow(int srcRow, const QModelIndex& srcParent) const override - { - return sourceModel()->index(srcRow, 0, srcParent).data().toInt() % 2 == 0; - } - }; - - FilterEvenRowsProxyModel proxy; - proxy.sort(0); - proxy.setSourceModel(&model); - QCOMPARE(rowTexts(&proxy), QStringLiteral("2468")); - - QSignalSpy modelDataChangedSpy(&model, &QAbstractItemModel::dataChanged); - QSignalSpy proxyLayoutChangedSpy(&proxy, &QAbstractItemModel::layoutChanged); - - if (changedRole == Qt::DecorationRole) - model.emitDecorationChangedSignal(); - else if (changedRow == -1) - model.replaceData(newData.split(QLatin1Char(','))); - else - model.setData(model.index(changedRow, 0), newData, changedRole); - - QCOMPARE(rowTexts(&model), expectedSourceRowTexts); - QCOMPARE(rowTexts(&proxy), expectedProxyRowTexts); - QCOMPARE(modelDataChangedSpy.size(), 1); - QCOMPARE(proxyLayoutChangedSpy.size(), expectedLayoutChanged); -} - -void tst_QSortFilterProxyModel::removeIntervals_data() -{ - QTest::addColumn("sourceItems"); - QTest::addColumn("sortOrder"); - QTest::addColumn("filter"); - QTest::addColumn("replacementSourceItems"); - QTest::addColumn("expectedRemovedProxyIntervals"); - QTest::addColumn("expectedProxyItems"); - - QTest::newRow("filter all, sort ascending") - << (QStringList() << "a" - << "b" - << "c") // sourceItems - << static_cast(Qt::AscendingOrder) // sortOrder - << "[^x]" // filter - << (QStringList() << "x" - << "x" - << "x") // replacementSourceItems - << (IntPairList() << IntPair(0, 2)) // expectedRemovedIntervals - << QStringList() // expectedProxyItems - ; - - QTest::newRow("filter all, sort descending") - << (QStringList() << "a" - << "b" - << "c") // sourceItems - << static_cast(Qt::DescendingOrder) // sortOrder - << "[^x]" // filter - << (QStringList() << "x" - << "x" - << "x") // replacementSourceItems - << (IntPairList() << IntPair(0, 2)) // expectedRemovedIntervals - << QStringList() // expectedProxyItems - ; - - QTest::newRow("filter first and last, sort ascending") - << (QStringList() << "a" - << "b" - << "c") // sourceItems - << static_cast(Qt::AscendingOrder) // sortOrder - << "[^x]" // filter - << (QStringList() << "x" - << "b" - << "x") // replacementSourceItems - << (IntPairList() << IntPair(2, 2) << IntPair(0, 0)) // expectedRemovedIntervals - << (QStringList() << "b") // expectedProxyItems - ; - - QTest::newRow("filter first and last, sort descending") - << (QStringList() << "a" - << "b" - << "c") // sourceItems - << static_cast(Qt::DescendingOrder) // sortOrder - << "[^x]" // filter - << (QStringList() << "x" - << "b" - << "x") // replacementSourceItems - << (IntPairList() << IntPair(2, 2) << IntPair(0, 0)) // expectedRemovedIntervals - << (QStringList() << "b") // expectedProxyItems - ; -} - -void tst_QSortFilterProxyModel::removeIntervals() -{ - QFETCH(QStringList, sourceItems); - QFETCH(int, sortOrder); - QFETCH(QString, filter); - QFETCH(QStringList, replacementSourceItems); - QFETCH(IntPairList, expectedRemovedProxyIntervals); - QFETCH(QStringList, expectedProxyItems); - - CustomStringListModel model; - QSortFilterProxyModel proxy; - - model.replaceData(sourceItems); - proxy.setSourceModel(&model); - - for (int i = 0; i < sourceItems.count(); ++i) { - QModelIndex sindex = model.index(i, 0, QModelIndex()); - QModelIndex pindex = proxy.index(i, 0, QModelIndex()); - QCOMPARE(proxy.data(pindex, Qt::DisplayRole), model.data(sindex, Qt::DisplayRole)); - } - - proxy.setDynamicSortFilter(true); - - if (sortOrder != -1) - proxy.sort(0, static_cast(sortOrder)); - if (!filter.isEmpty()) - proxy.setFilterRegExp(QRegExp(filter)); - - (void)proxy.rowCount(QModelIndex()); // force mapping - - QSignalSpy removeSpy(&proxy, &QSortFilterProxyModel::rowsRemoved); - QSignalSpy insertSpy(&proxy, &QSortFilterProxyModel::rowsInserted); - QSignalSpy aboutToRemoveSpy(&proxy, &QSortFilterProxyModel::rowsAboutToBeRemoved); - QSignalSpy aboutToInsertSpy(&proxy, &QSortFilterProxyModel::rowsAboutToBeInserted); - - QVERIFY(removeSpy.isValid()); - QVERIFY(insertSpy.isValid()); - QVERIFY(aboutToRemoveSpy.isValid()); - QVERIFY(aboutToInsertSpy.isValid()); - - model.replaceData(replacementSourceItems); - - QCOMPARE(aboutToRemoveSpy.count(), expectedRemovedProxyIntervals.count()); - for (int i = 0; i < aboutToRemoveSpy.count(); ++i) { - QList args = aboutToRemoveSpy.at(i); - QCOMPARE(args.at(1).type(), QVariant::Int); - QCOMPARE(args.at(2).type(), QVariant::Int); - QCOMPARE(args.at(1).toInt(), expectedRemovedProxyIntervals.at(i).first); - QCOMPARE(args.at(2).toInt(), expectedRemovedProxyIntervals.at(i).second); - } - QCOMPARE(removeSpy.count(), expectedRemovedProxyIntervals.count()); - for (int i = 0; i < removeSpy.count(); ++i) { - QList args = removeSpy.at(i); - QCOMPARE(args.at(1).type(), QVariant::Int); - QCOMPARE(args.at(2).type(), QVariant::Int); - QCOMPARE(args.at(1).toInt(), expectedRemovedProxyIntervals.at(i).first); - QCOMPARE(args.at(2).toInt(), expectedRemovedProxyIntervals.at(i).second); - } - - QCOMPARE(insertSpy.count(), 0); - QCOMPARE(aboutToInsertSpy.count(), 0); - - QCOMPARE(proxy.rowCount(QModelIndex()), expectedProxyItems.count()); - for (int i = 0; i < expectedProxyItems.count(); ++i) { - QModelIndex pindex = proxy.index(i, 0, QModelIndex()); - QCOMPARE(proxy.data(pindex, Qt::DisplayRole).toString(), expectedProxyItems.at(i)); - } -} - -void tst_QSortFilterProxyModel::dynamicFilterWithoutSort() -{ - QStringListModel model; - const QStringList initial = QString("bravo charlie delta echo").split(QLatin1Char(' ')); - model.setStringList(initial); - QSortFilterProxyModel proxy; - proxy.setDynamicSortFilter(true); - proxy.setSourceModel(&model); - - QSignalSpy layoutChangeSpy(&proxy, &QAbstractItemModel::layoutChanged); - QSignalSpy resetSpy(&proxy, &QAbstractItemModel::modelReset); - - QVERIFY(layoutChangeSpy.isValid()); - QVERIFY(resetSpy.isValid()); - - model.setStringList(QStringList() << "Monday" << "Tuesday" << "Wednesday" << "Thursday" << "Friday"); - - QVERIFY(layoutChangeSpy.isEmpty()); - - QCOMPARE(model.stringList(), QStringList() << "Monday" << "Tuesday" << "Wednesday" << "Thursday" << "Friday"); - - QCOMPARE(resetSpy.count(), 1); -} - -void tst_QSortFilterProxyModel::checkSetNewModel() -{ - QTreeView tv; - StepTreeModel model1; - model1.setDepth(4); - - QSortFilterProxyModel proxy; - proxy.setSourceModel(&model1); - tv.setModel(&proxy); - tv.show(); - QVERIFY(QTest::qWaitForWindowExposed(&tv)); - tv.expandAll(); - { - StepTreeModel model2; - model2.setDepth(4); - proxy.setSourceModel(&model2); - tv.expandAll(); - proxy.setSourceModel(&model1); - tv.expandAll(); - // the destruction of model2 here caused a proxy model reset due to - // missing disconnect in setSourceModel() - } - // handle repaint events, will assert when qsortfilterproxymodel is in wrong state - QCoreApplication::processEvents(); -} - -QTEST_MAIN(tst_QSortFilterProxyModel) -#include "tst_qsortfilterproxymodel.moc" diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp new file mode 100644 index 0000000000..94c3fa6e46 --- /dev/null +++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.cpp @@ -0,0 +1,4665 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "tst_qsortfilterproxymodel.h" +#include "dynamictreemodel.h" + +#include +#include +#include +#include + +#include + +// Testing get/set functions +void tst_QSortFilterProxyModel::getSetCheck() +{ + QSortFilterProxyModel obj1; + QCOMPARE(obj1.sourceModel(), (QAbstractItemModel *)0); + // int QSortFilterProxyModel::filterKeyColumn() + // void QSortFilterProxyModel::setFilterKeyColumn(int) + obj1.setFilterKeyColumn(0); + QCOMPARE(0, obj1.filterKeyColumn()); + obj1.setFilterKeyColumn(INT_MIN); + QCOMPARE(INT_MIN, obj1.filterKeyColumn()); + obj1.setFilterKeyColumn(INT_MAX); + QCOMPARE(INT_MAX, obj1.filterKeyColumn()); +} + +tst_QSortFilterProxyModel::tst_QSortFilterProxyModel() + : m_model(0), m_proxy(0) +{ + qRegisterMetaType(); +} + +void tst_QSortFilterProxyModel::initTestCase() +{ + qRegisterMetaType >(); + m_model = new QStandardItemModel(0, 1); + m_proxy = new QSortFilterProxyModel(); + m_proxy->setSourceModel(m_model); +} + +void tst_QSortFilterProxyModel::cleanupTestCase() +{ + delete m_proxy; + delete m_model; +} + +void tst_QSortFilterProxyModel::cleanup() +{ + switch (m_filterType) { + case FilterType::RegExp: + m_proxy->setFilterRegExp(QRegExp()); + break; + case FilterType::RegularExpression: + m_proxy->setFilterRegularExpression(QRegularExpression()); + break; + } + + m_proxy->sort(-1, Qt::AscendingOrder); + m_model->clear(); + m_model->insertColumns(0, 1); +} + +/* + tests +*/ + +void tst_QSortFilterProxyModel::sort_data() +{ + QTest::addColumn("sortOrder"); + QTest::addColumn("sortCaseSensitivity"); + QTest::addColumn("initial"); + QTest::addColumn("expected"); + + QTest::newRow("flat descending") << static_cast(Qt::DescendingOrder) + << int(Qt::CaseSensitive) + << (QStringList() + << "delta" + << "yankee" + << "bravo" + << "lima" + << "charlie" + << "juliet" + << "tango" + << "hotel" + << "uniform" + << "alpha" + << "echo" + << "golf" + << "quebec" + << "foxtrot" + << "india" + << "romeo" + << "november" + << "oskar" + << "zulu" + << "kilo" + << "whiskey" + << "mike" + << "papa" + << "sierra" + << "xray" + << "viktor") + << (QStringList() + << "zulu" + << "yankee" + << "xray" + << "whiskey" + << "viktor" + << "uniform" + << "tango" + << "sierra" + << "romeo" + << "quebec" + << "papa" + << "oskar" + << "november" + << "mike" + << "lima" + << "kilo" + << "juliet" + << "india" + << "hotel" + << "golf" + << "foxtrot" + << "echo" + << "delta" + << "charlie" + << "bravo" + << "alpha"); + QTest::newRow("flat ascending") << static_cast(Qt::AscendingOrder) + << int(Qt::CaseSensitive) + << (QStringList() + << "delta" + << "yankee" + << "bravo" + << "lima" + << "charlie" + << "juliet" + << "tango" + << "hotel" + << "uniform" + << "alpha" + << "echo" + << "golf" + << "quebec" + << "foxtrot" + << "india" + << "romeo" + << "november" + << "oskar" + << "zulu" + << "kilo" + << "whiskey" + << "mike" + << "papa" + << "sierra" + << "xray" + << "viktor") + << (QStringList() + << "alpha" + << "bravo" + << "charlie" + << "delta" + << "echo" + << "foxtrot" + << "golf" + << "hotel" + << "india" + << "juliet" + << "kilo" + << "lima" + << "mike" + << "november" + << "oskar" + << "papa" + << "quebec" + << "romeo" + << "sierra" + << "tango" + << "uniform" + << "viktor" + << "whiskey" + << "xray" + << "yankee" + << "zulu"); + QTest::newRow("case insensitive") << static_cast(Qt::AscendingOrder) + << int(Qt::CaseInsensitive) + << (QStringList() + << "alpha" << "BETA" << "Gamma" << "delta") + << (QStringList() + << "alpha" << "BETA" << "delta" << "Gamma"); + QTest::newRow("case sensitive") << static_cast(Qt::AscendingOrder) + << int(Qt::CaseSensitive) + << (QStringList() + << "alpha" << "BETA" << "Gamma" << "delta") + << (QStringList() + << "BETA" << "Gamma" << "alpha" << "delta"); + + QStringList list; + for (int i = 10000; i < 20000; ++i) + list.append(QStringLiteral("Number: ") + QString::number(i)); + QTest::newRow("large set ascending") << static_cast(Qt::AscendingOrder) << int(Qt::CaseSensitive) << list << list; +} + +void tst_QSortFilterProxyModel::sort() +{ + QFETCH(int, sortOrder); + QFETCH(int, sortCaseSensitivity); + QFETCH(QStringList, initial); + QFETCH(QStringList, expected); + + // prepare model + QStandardItem *root = m_model->invisibleRootItem (); + QList items; + for (int i = 0; i < initial.count(); ++i) { + items.append(new QStandardItem(initial.at(i))); + } + root->insertRows(0, items); + QCOMPARE(m_model->rowCount(QModelIndex()), initial.count()); + QCOMPARE(m_model->columnCount(QModelIndex()), 1); + + // make sure the proxy is unsorted + QCOMPARE(m_proxy->columnCount(QModelIndex()), 1); + QCOMPARE(m_proxy->rowCount(QModelIndex()), initial.count()); + for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) { + QModelIndex index = m_proxy->index(row, 0, QModelIndex()); + QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), initial.at(row)); + } + + // sort + m_proxy->sort(0, static_cast(sortOrder)); + m_proxy->setSortCaseSensitivity(static_cast(sortCaseSensitivity)); + + // make sure the model is unchanged + for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) { + QModelIndex index = m_model->index(row, 0, QModelIndex()); + QCOMPARE(m_model->data(index, Qt::DisplayRole).toString(), initial.at(row)); + } + // make sure the proxy is sorted + for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) { + QModelIndex index = m_proxy->index(row, 0, QModelIndex()); + QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), expected.at(row)); + } + + // restore the unsorted order + m_proxy->sort(-1); + + // make sure the proxy is unsorted again + for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) { + QModelIndex index = m_proxy->index(row, 0, QModelIndex()); + QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), initial.at(row)); + } +} + +void tst_QSortFilterProxyModel::sortHierarchy_data() +{ + QTest::addColumn("sortOrder"); + QTest::addColumn("initial"); + QTest::addColumn("expected"); + + QTest::newRow("flat ascending") + << static_cast(Qt::AscendingOrder) + << (QStringList() + << "c" << "f" << "d" << "e" << "a" << "b") + << (QStringList() + << "a" << "b" << "c" << "d" << "e" << "f"); + + QTest::newRow("simple hierarchy") + << static_cast(Qt::AscendingOrder) + << (QStringList() << "a" << "<" << "b" << "<" << "c" << ">" << ">") + << (QStringList() << "a" << "<" << "b" << "<" << "c" << ">" << ">"); + + QTest::newRow("hierarchical ascending") + << static_cast(Qt::AscendingOrder) + << (QStringList() + << "c" + << "<" + << "h" + << "<" + << "2" + << "0" + << "1" + << ">" + << "g" + << "i" + << ">" + << "b" + << "<" + << "l" + << "k" + << "<" + << "8" + << "7" + << "9" + << ">" + << "m" + << ">" + << "a" + << "<" + << "z" + << "y" + << "x" + << ">") + << (QStringList() + << "a" + << "<" + << "x" + << "y" + << "z" + << ">" + << "b" + << "<" + << "k" + << "<" + << "7" + << "8" + << "9" + << ">" + << "l" + << "m" + << ">" + << "c" + << "<" + << "g" + << "h" + << "<" + << "0" + << "1" + << "2" + << ">" + << "i" + << ">"); +} + +void tst_QSortFilterProxyModel::sortHierarchy() +{ + QFETCH(int, sortOrder); + QFETCH(QStringList, initial); + QFETCH(QStringList, expected); + + buildHierarchy(initial, m_model); + checkHierarchy(initial, m_model); + checkHierarchy(initial, m_proxy); + m_proxy->sort(0, static_cast(sortOrder)); + checkHierarchy(initial, m_model); + checkHierarchy(expected, m_proxy); +} + +void tst_QSortFilterProxyModel::insertRows_data() +{ + QTest::addColumn("initial"); + QTest::addColumn("expected"); + QTest::addColumn("insert"); + QTest::addColumn("position"); + + QTest::newRow("insert one row in the middle") + << (QStringList() + << "One" + << "Two" + << "Four" + << "Five") + << (QStringList() + << "One" + << "Two" + << "Three" + << "Four" + << "Five") + << (QStringList() + << "Three") + << 2; + + QTest::newRow("insert one row in the beginning") + << (QStringList() + << "Two" + << "Three" + << "Four" + << "Five") + << (QStringList() + << "One" + << "Two" + << "Three" + << "Four" + << "Five") + << (QStringList() + << "One") + << 0; + + QTest::newRow("insert one row in the end") + << (QStringList() + << "One" + << "Two" + << "Three" + << "Four") + << (QStringList() + << "One" + << "Two" + << "Three" + << "Four" + << "Five") + << (QStringList() + <<"Five") + << 4; +} + +void tst_QSortFilterProxyModel::insertRows() +{ + QFETCH(QStringList, initial); + QFETCH(QStringList, expected); + QFETCH(QStringList, insert); + QFETCH(int, position); + // prepare model + m_model->insertRows(0, initial.count(), QModelIndex()); + //m_model->insertColumns(0, 1, QModelIndex()); + QCOMPARE(m_model->columnCount(QModelIndex()), 1); + QCOMPARE(m_model->rowCount(QModelIndex()), initial.count()); + for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) { + QModelIndex index = m_model->index(row, 0, QModelIndex()); + m_model->setData(index, initial.at(row), Qt::DisplayRole); + } + // make sure the model correct before insert + for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) { + QModelIndex index = m_model->index(row, 0, QModelIndex()); + QCOMPARE(m_model->data(index, Qt::DisplayRole).toString(), initial.at(row)); + } + // make sure the proxy is correct before insert + for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) { + QModelIndex index = m_proxy->index(row, 0, QModelIndex()); + QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), initial.at(row)); + } + + // insert the row + m_proxy->insertRows(position, insert.count(), QModelIndex()); + QCOMPARE(m_model->rowCount(QModelIndex()), expected.count()); + QCOMPARE(m_proxy->rowCount(QModelIndex()), expected.count()); + + // set the data for the inserted row + for (int i = 0; i < insert.count(); ++i) { + QModelIndex index = m_proxy->index(position + i, 0, QModelIndex()); + m_proxy->setData(index, insert.at(i), Qt::DisplayRole); + } + + // make sure the model correct after insert + for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) { + QModelIndex index = m_model->index(row, 0, QModelIndex()); + QCOMPARE(m_model->data(index, Qt::DisplayRole).toString(), expected.at(row)); + } + + // make sure the proxy is correct after insert + for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) { + QModelIndex index = m_proxy->index(row, 0, QModelIndex()); + QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), expected.at(row)); + } +} + +void tst_QSortFilterProxyModel::prependRow() +{ + //this tests that data is correctly handled by the sort filter when prepending a row + QStandardItemModel model; + QSortFilterProxyModel proxy; + proxy.setSourceModel(&model); + + QStandardItem item("root"); + model.appendRow(&item); + + QStandardItem sub("sub"); + item.appendRow(&sub); + + sub.appendRow(new QStandardItem("test1")); + sub.appendRow(new QStandardItem("test2")); + + QStandardItem sub2("sub2"); + sub2.appendRow(new QStandardItem("sub3")); + item.insertRow(0, &sub2); + + QModelIndex index_sub2 = proxy.mapFromSource(model.indexFromItem(&sub2)); + + QCOMPARE(sub2.rowCount(), proxy.rowCount(index_sub2)); + QCOMPARE(proxy.rowCount(QModelIndex()), 1); //only the "root" item is there +} + +void tst_QSortFilterProxyModel::removeRows_data() +{ + QTest::addColumn("initial"); + QTest::addColumn("sortOrder"); + QTest::addColumn("filter"); + QTest::addColumn("position"); + QTest::addColumn("count"); + QTest::addColumn("success"); + QTest::addColumn("expectedProxy"); + QTest::addColumn("expectedSource"); + + QTest::newRow("remove one row in the middle [no sorting/filter]") + << (QStringList() + << "One" + << "Two" + << "Three" + << "Four" + << "Five") + << -1 // no sorting + << QString() // no filter + << 2 // position + << 1 // count + << true // success + << (QStringList() // expectedProxy + << "One" + << "Two" + << "Four" + << "Five") + << (QStringList() // expectedSource + << "One" + << "Two" + << "Four" + << "Five"); + + QTest::newRow("remove one row in the beginning [no sorting/filter]") + << (QStringList() + << "One" + << "Two" + << "Three" + << "Four" + << "Five") + << -1 // no sorting + << QString() // no filter + << 0 // position + << 1 // count + << true // success + << (QStringList() // expectedProxy + << "Two" + << "Three" + << "Four" + << "Five") + << (QStringList() // expectedSource + << "Two" + << "Three" + << "Four" + << "Five"); + + QTest::newRow("remove one row in the end [no sorting/filter]") + << (QStringList() + << "One" + << "Two" + << "Three" + << "Four" + << "Five") + << -1 // no sorting + << QString() // no filter + << 4 // position + << 1 // count + << true // success + << (QStringList() // expectedProxy + << "One" + << "Two" + << "Three" + << "Four") + << (QStringList() // expectedSource + << "One" + << "Two" + << "Three" + << "Four"); + + QTest::newRow("remove all [no sorting/filter]") + << (QStringList() + << "One" + << "Two" + << "Three" + << "Four" + << "Five") + << -1 // no sorting + << QString() // no filter + << 0 // position + << 5 // count + << true // success + << QStringList() // expectedProxy + << QStringList(); // expectedSource + + QTest::newRow("remove one row past the end [no sorting/filter]") + << (QStringList() + << "One" + << "Two" + << "Three" + << "Four" + << "Five") + << -1 // no sorting + << QString() // no filter + << 5 // position + << 1 // count + << false // success + << (QStringList() // expectedProxy + << "One" + << "Two" + << "Three" + << "Four" + << "Five") + << (QStringList() // expectedSource + << "One" + << "Two" + << "Three" + << "Four" + << "Five"); + + QTest::newRow("remove row -1 [no sorting/filter]") + << (QStringList() + << "One" + << "Two" + << "Three" + << "Four" + << "Five") + << -1 // no sorting + << QString() // no filter + << -1 // position + << 1 // count + << false // success + << (QStringList() // expectedProxy + << "One" + << "Two" + << "Three" + << "Four" + << "Five") + << (QStringList() // expectedSource + << "One" + << "Two" + << "Three" + << "Four" + << "Five"); + + QTest::newRow("remove three rows in the middle [no sorting/filter]") + << (QStringList() + << "One" + << "Two" + << "Three" + << "Four" + << "Five") + << -1 // no sorting + << QString() // no filter + << 1 // position + << 3 // count + << true // success + << (QStringList() // expectedProxy + << "One" + << "Five") + << (QStringList() // expectedSource + << "One" + << "Five"); + + QTest::newRow("remove one row in the middle [ascending sorting, no filter]") + << (QStringList() + << "1" + << "5" + << "2" + << "4" + << "3") + << static_cast(Qt::AscendingOrder) + << QString() // no filter + << 2 // position + << 1 // count + << true // success + << (QStringList() // expectedProxy + << "1" + << "2" + << "4" + << "5") + << (QStringList() // expectedSource + << "1" + << "5" + << "2" + << "4"); + + QTest::newRow("remove two rows in the middle [ascending sorting, no filter]") + << (QStringList() + << "1" + << "5" + << "2" + << "4" + << "3") + << static_cast(Qt::AscendingOrder) + << QString() // no filter + << 2 // position + << 2 // count + << true // success + << (QStringList() // expectedProxy + << "1" + << "2" + << "5") + << (QStringList() // expectedSource + << "1" + << "5" + << "2"); + + QTest::newRow("remove two rows in the middle [descending sorting, no filter]") + << (QStringList() + << "1" + << "5" + << "2" + << "4" + << "3") + << static_cast(Qt::DescendingOrder) + << QString() // no filter + << 2 // position + << 2 // count + << true // success + << (QStringList() // expectedProxy + << "5" + << "4" + << "1") + << (QStringList() // expectedSource + << "1" + << "5" + << "4"); + + QTest::newRow("remove one row in the middle [no sorting, filter=5|2|3]") + << (QStringList() + << "1" + << "5" + << "2" + << "4" + << "3") + << -1 // no sorting + << QString("5|2|3") + << 1 // position + << 1 // count + << true // success + << (QStringList() // expectedProxy + << "5" + << "3") + << (QStringList() // expectedSource + << "1" + << "5" + << "4" + << "3"); + + QTest::newRow("remove all [ascending sorting, no filter]") + << (QStringList() + << "1" + << "5" + << "2" + << "4" + << "3") + << static_cast(Qt::AscendingOrder) + << QString() // no filter + << 0 // position + << 5 // count + << true // success + << QStringList() // expectedProxy + << QStringList(); // expectedSource +} + +void tst_QSortFilterProxyModel::removeRows() +{ + QFETCH(QStringList, initial); + QFETCH(int, sortOrder); + QFETCH(QString, filter); + QFETCH(int, position); + QFETCH(int, count); + QFETCH(bool, success); + QFETCH(QStringList, expectedProxy); + QFETCH(QStringList, expectedSource); + + QStandardItemModel model; + QSortFilterProxyModel proxy; + proxy.setSourceModel(&model); + + // prepare model + foreach (QString s, initial) + model.appendRow(new QStandardItem(s)); + + if (sortOrder != -1) + proxy.sort(0, static_cast(sortOrder)); + + if (!filter.isEmpty()) + setupFilter(&proxy, filter); + + // remove the rows + QCOMPARE(proxy.removeRows(position, count, QModelIndex()), success); + QCOMPARE(model.rowCount(QModelIndex()), expectedSource.count()); + QCOMPARE(proxy.rowCount(QModelIndex()), expectedProxy.count()); + + // make sure the model is correct after remove + for (int row = 0; row < model.rowCount(QModelIndex()); ++row) + QCOMPARE(model.item(row)->text(), expectedSource.at(row)); + + // make sure the proxy is correct after remove + for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) { + QModelIndex index = proxy.index(row, 0, QModelIndex()); + QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expectedProxy.at(row)); + } +} + +class MyFilteredColumnProxyModel : public QSortFilterProxyModel +{ + Q_OBJECT +public: + MyFilteredColumnProxyModel(FilterType filterType, QObject *parent = 0) : + QSortFilterProxyModel(parent), + m_filterType(filterType) + { } + +protected: + bool filterAcceptsColumn(int sourceColumn, const QModelIndex &) const + { + QString key = sourceModel()->headerData(sourceColumn, Qt::Horizontal).toString(); + bool result = false; + switch (m_filterType) { + case FilterType::RegExp: + result = key.contains(filterRegExp()); + break; + case FilterType::RegularExpression: + result = key.contains(filterRegularExpression()); + break; + } + return result; + } + +private: + FilterType m_filterType; +}; + +void tst_QSortFilterProxyModel::removeColumns_data() +{ + QTest::addColumn("initial"); + QTest::addColumn("filter"); + QTest::addColumn("position"); + QTest::addColumn("count"); + QTest::addColumn("success"); + QTest::addColumn("expectedProxy"); + QTest::addColumn("expectedSource"); + + QTest::newRow("remove one column in the middle [no filter]") + << (QStringList() + << "1" + << "2" + << "3" + << "4" + << "5") + << QString() // no filter + << 2 // position + << 1 // count + << true // success + << (QStringList() // expectedProxy + << "1" + << "2" + << "4" + << "5") + << (QStringList() // expectedSource + << "1" + << "2" + << "4" + << "5"); + + QTest::newRow("remove one column in the end [no filter]") + << (QStringList() + << "1" + << "2" + << "3" + << "4" + << "5") + << QString() // no filter + << 4 // position + << 1 // count + << true // success + << (QStringList() // expectedProxy + << "1" + << "2" + << "3" + << "4") + << (QStringList() // expectedSource + << "1" + << "2" + << "3" + << "4"); + + QTest::newRow("remove one column past the end [no filter]") + << (QStringList() + << "1" + << "2" + << "3" + << "4" + << "5") + << QString() // no filter + << 5 // position + << 1 // count + << false // success + << (QStringList() // expectedProxy + << "1" + << "2" + << "3" + << "4" + << "5") + << (QStringList() // expectedSource + << "1" + << "2" + << "3" + << "4" + << "5"); + + QTest::newRow("remove column -1 [no filter]") + << (QStringList() + << "1" + << "2" + << "3" + << "4" + << "5") + << QString() // no filter + << -1 // position + << 1 // count + << false // success + << (QStringList() // expectedProxy + << "1" + << "2" + << "3" + << "4" + << "5") + << (QStringList() // expectedSource + << "1" + << "2" + << "3" + << "4" + << "5"); + + QTest::newRow("remove all columns [no filter]") + << (QStringList() + << "1" + << "2" + << "3" + << "4" + << "5") + << QString() // no filter + << 0 // position + << 5 // count + << true // success + << QStringList() // expectedProxy + << QStringList(); // expectedSource + + QTest::newRow("remove one column in the middle [filter=1|3|5]") + << (QStringList() + << "1" + << "2" + << "3" + << "4" + << "5") + << QString("1|3|5") + << 1 // position + << 1 // count + << true // success + << (QStringList() // expectedProxy + << "1" + << "5") + << (QStringList() // expectedSource + << "1" + << "2" + << "4" + << "5"); + + QTest::newRow("remove one column in the end [filter=1|3|5]") + << (QStringList() + << "1" + << "2" + << "3" + << "4" + << "5") + << QString("1|3|5") + << 2 // position + << 1 // count + << true // success + << (QStringList() // expectedProxy + << "1" + << "3") + << (QStringList() // expectedSource + << "1" + << "2" + << "3" + << "4"); + + QTest::newRow("remove one column past the end [filter=1|3|5]") + << (QStringList() + << "1" + << "2" + << "3" + << "4" + << "5") + << QString("1|3|5") + << 3 // position + << 1 // count + << false // success + << (QStringList() // expectedProxy + << "1" + << "3" + << "5") + << (QStringList() // expectedSource + << "1" + << "2" + << "3" + << "4" + << "5"); + + QTest::newRow("remove all columns [filter=1|3|5]") + << (QStringList() + << "1" + << "2" + << "3" + << "4" + << "5") + << QString("1|3|5") + << 0 // position + << 3 // count + << true // success + << QStringList() // expectedProxy + << (QStringList() // expectedSource + << "2" + << "4"); +} + +void tst_QSortFilterProxyModel::removeColumns() +{ + QFETCH(QStringList, initial); + QFETCH(QString, filter); + QFETCH(int, position); + QFETCH(int, count); + QFETCH(bool, success); + QFETCH(QStringList, expectedProxy); + QFETCH(QStringList, expectedSource); + + QStandardItemModel model; + MyFilteredColumnProxyModel proxy(m_filterType); + proxy.setSourceModel(&model); + if (!filter.isEmpty()) + setupFilter(&proxy, filter); + + // prepare model + model.setHorizontalHeaderLabels(initial); + + // remove the columns + QCOMPARE(proxy.removeColumns(position, count, QModelIndex()), success); + QCOMPARE(model.columnCount(QModelIndex()), expectedSource.count()); + QCOMPARE(proxy.columnCount(QModelIndex()), expectedProxy.count()); + + // make sure the model is correct after remove + for (int col = 0; col < model.columnCount(QModelIndex()); ++col) + QCOMPARE(model.horizontalHeaderItem(col)->text(), expectedSource.at(col)); + + // make sure the proxy is correct after remove + for (int col = 0; col < proxy.columnCount(QModelIndex()); ++col) { + QCOMPARE(proxy.headerData(col, Qt::Horizontal, Qt::DisplayRole).toString(), + expectedProxy.at(col)); + } +} + +void tst_QSortFilterProxyModel::filterColumns_data() +{ + QTest::addColumn("pattern"); + QTest::addColumn("initial"); + QTest::addColumn("data"); + + QTest::newRow("all") << "a" + << (QStringList() + << "delta" + << "yankee" + << "bravo" + << "lima") + << true; + + QTest::newRow("some") << "lie" + << (QStringList() + << "charlie" + << "juliet" + << "tango" + << "hotel") + << true; + + QTest::newRow("nothing") << "zoo" + << (QStringList() + << "foxtrot" + << "uniform" + << "alpha" + << "golf") + << false; +} + +void tst_QSortFilterProxyModel::filterColumns() +{ + QFETCH(QString, pattern); + QFETCH(QStringList, initial); + QFETCH(bool, data); + // prepare model + m_model->setColumnCount(initial.count()); + m_model->setRowCount(1); + QCOMPARE(m_model->columnCount(QModelIndex()), initial.count()); + QCOMPARE(m_model->rowCount(QModelIndex()), 1); + // set data + QCOMPARE(m_model->rowCount(QModelIndex()), 1); + for (int col = 0; col < m_model->columnCount(QModelIndex()); ++col) { + QModelIndex index = m_model->index(0, col, QModelIndex()); + m_model->setData(index, initial.at(col), Qt::DisplayRole); + } + setupFilter(m_proxy, pattern); + + m_proxy->setFilterKeyColumn(-1); + // make sure the model is unchanged + for (int col = 0; col < m_model->columnCount(QModelIndex()); ++col) { + QModelIndex index = m_model->index(0, col, QModelIndex()); + QCOMPARE(m_model->data(index, Qt::DisplayRole).toString(), initial.at(col)); + } + // make sure the proxy is filtered + QModelIndex index = m_proxy->index(0, 0, QModelIndex()); + QCOMPARE(index.isValid(), data); +} + +void tst_QSortFilterProxyModel::filter_data() +{ + QTest::addColumn("pattern"); + QTest::addColumn("initial"); + QTest::addColumn("expected"); + + QTest::newRow("flat") << "e" + << (QStringList() + << "delta" + << "yankee" + << "bravo" + << "lima" + << "charlie" + << "juliet" + << "tango" + << "hotel" + << "uniform" + << "alpha" + << "echo" + << "golf" + << "quebec" + << "foxtrot" + << "india" + << "romeo" + << "november" + << "oskar" + << "zulu" + << "kilo" + << "whiskey" + << "mike" + << "papa" + << "sierra" + << "xray" + << "viktor") + << (QStringList() + << "delta" + << "yankee" + << "charlie" + << "juliet" + << "hotel" + << "echo" + << "quebec" + << "romeo" + << "november" + << "whiskey" + << "mike" + << "sierra"); +} + +void tst_QSortFilterProxyModel::filter() +{ + QFETCH(QString, pattern); + QFETCH(QStringList, initial); + QFETCH(QStringList, expected); + + // prepare model + QVERIFY(m_model->insertRows(0, initial.count(), QModelIndex())); + QCOMPARE(m_model->rowCount(QModelIndex()), initial.count()); + // set data + QCOMPARE(m_model->columnCount(QModelIndex()), 1); + for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) { + QModelIndex index = m_model->index(row, 0, QModelIndex()); + m_model->setData(index, initial.at(row), Qt::DisplayRole); + } + setupFilter(m_proxy, pattern); + // make sure the proxy is unfiltered + QCOMPARE(m_proxy->columnCount(QModelIndex()), 1); + QCOMPARE(m_proxy->rowCount(QModelIndex()), expected.count()); + // make sure the model is unchanged + for (int row = 0; row < m_model->rowCount(QModelIndex()); ++row) { + QModelIndex index = m_model->index(row, 0, QModelIndex()); + QCOMPARE(m_model->data(index, Qt::DisplayRole).toString(), initial.at(row)); + } + // make sure the proxy is filtered + for (int row = 0; row < m_proxy->rowCount(QModelIndex()); ++row) { + QModelIndex index = m_proxy->index(row, 0, QModelIndex()); + QCOMPARE(m_proxy->data(index, Qt::DisplayRole).toString(), expected.at(row)); + } +} + +void tst_QSortFilterProxyModel::filterHierarchy_data() +{ + QTest::addColumn("pattern"); + QTest::addColumn("initial"); + QTest::addColumn("expected"); + + QTest::newRow("flat") << ".*oo" + << (QStringList() + << "foo" << "boo" << "baz" << "moo" << "laa" << "haa") + << (QStringList() + << "foo" << "boo" << "moo"); + + QTest::newRow("simple hierarchy") << "b.*z" + << (QStringList() << "baz" << "<" << "boz" << "<" << "moo" << ">" << ">") + << (QStringList() << "baz" << "<" << "boz" << ">"); +} + +void tst_QSortFilterProxyModel::filterHierarchy() +{ + QFETCH(QString, pattern); + QFETCH(QStringList, initial); + QFETCH(QStringList, expected); + buildHierarchy(initial, m_model); + setupFilter(m_proxy, pattern); + checkHierarchy(initial, m_model); + checkHierarchy(expected, m_proxy); +} + +void tst_QSortFilterProxyModel::buildHierarchy(const QStringList &l, QAbstractItemModel *m) +{ + int ind = 0; + int row = 0; + QStack row_stack; + QModelIndex parent; + QStack parent_stack; + for (int i = 0; i < l.count(); ++i) { + QString token = l.at(i); + if (token == QLatin1String("<")) { // start table + ++ind; + parent_stack.push(parent); + row_stack.push(row); + parent = m->index(row - 1, 0, parent); + row = 0; + QVERIFY(m->insertColumns(0, 1, parent)); // add column + } else if (token == QLatin1String(">")) { // end table + --ind; + parent = parent_stack.pop(); + row = row_stack.pop(); + } else { // append row + QVERIFY(m->insertRows(row, 1, parent)); + QModelIndex index = m->index(row, 0, parent); + QVERIFY(index.isValid()); + m->setData(index, token, Qt::DisplayRole); + ++row; + } + } +} + +void tst_QSortFilterProxyModel::checkHierarchy(const QStringList &l, const QAbstractItemModel *m) +{ + int row = 0; + int indent = 0; + QStack row_stack; + QModelIndex parent; + QStack parent_stack; + for (int i = 0; i < l.count(); ++i) { + QString token = l.at(i); + if (token == QLatin1String("<")) { // start table + ++indent; + parent_stack.push(parent); + row_stack.push(row); + parent = m->index(row - 1, 0, parent); + QVERIFY(parent.isValid()); + row = 0; + } else if (token == QLatin1String(">")) { // end table + --indent; + parent = parent_stack.pop(); + row = row_stack.pop(); + } else { // compare row + QModelIndex index = m->index(row, 0, parent); + QVERIFY(index.isValid()); + QString str = m->data(index, Qt::DisplayRole).toString(); + QCOMPARE(str, token); + ++row; + } + } +} + +void tst_QSortFilterProxyModel::setupFilter(QSortFilterProxyModel *model, const QString& pattern) +{ + switch (m_filterType) { + case FilterType::RegExp: + model->setFilterRegExp(pattern); + break; + case FilterType::RegularExpression: + model->setFilterRegularExpression(pattern); + break; + } +} + +class TestModel: public QAbstractTableModel +{ +public: + int rowCount(const QModelIndex &) const { return 10000; } + int columnCount(const QModelIndex &) const { return 1; } + QVariant data(const QModelIndex &index, int role) const + { + if (role != Qt::DisplayRole) + return QVariant(); + return QString::number(index.row()); + } +}; + +void tst_QSortFilterProxyModel::filterTable() +{ + TestModel model; + QSortFilterProxyModel filter; + filter.setSourceModel(&model); + setupFilter(&filter, QLatin1String("9")); + + for (int i = 0; i < filter.rowCount(); ++i) + QVERIFY(filter.data(filter.index(i, 0)).toString().contains(QLatin1Char('9'))); +} + +void tst_QSortFilterProxyModel::insertAfterSelect() +{ + QStandardItemModel model(10, 2); + for (int i = 0; i<10;i++) + model.setData(model.index(i, 0), QVariant(i)); + QSortFilterProxyModel filter; + filter.setSourceModel(&model); + QTreeView view; + view.setModel(&filter); + view.show(); + QModelIndex firstIndex = filter.mapFromSource(model.index(0, 0, QModelIndex())); + QCOMPARE(firstIndex.model(), (const QAbstractItemModel *)view.model()); + QVERIFY(firstIndex.isValid()); + int itemOffset = view.visualRect(firstIndex).width() / 2; + QPoint p(itemOffset, 1); + QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, p); + QVERIFY(view.selectionModel()->selectedIndexes().size() > 0); + model.insertRows(5, 1, QModelIndex()); + QVERIFY(view.selectionModel()->selectedIndexes().size() > 0); // Should still have a selection +} + +void tst_QSortFilterProxyModel::removeAfterSelect() +{ + QStandardItemModel model(10, 2); + for (int i = 0; i<10;i++) + model.setData(model.index(i, 0), QVariant(i)); + QSortFilterProxyModel filter; + filter.setSourceModel(&model); + QTreeView view; + view.setModel(&filter); + view.show(); + QModelIndex firstIndex = filter.mapFromSource(model.index(0, 0, QModelIndex())); + QCOMPARE(firstIndex.model(), (const QAbstractItemModel *)view.model()); + QVERIFY(firstIndex.isValid()); + int itemOffset = view.visualRect(firstIndex).width() / 2; + QPoint p(itemOffset, 1); + QTest::mouseClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, p); + QVERIFY(view.selectionModel()->selectedIndexes().size() > 0); + model.removeRows(5, 1, QModelIndex()); + QVERIFY(view.selectionModel()->selectedIndexes().size() > 0); // Should still have a selection +} + +void tst_QSortFilterProxyModel::filterCurrent() +{ + QStandardItemModel model(2, 1); + model.setData(model.index(0, 0), QString("AAA")); + model.setData(model.index(1, 0), QString("BBB")); + QSortFilterProxyModel proxy; + proxy.setSourceModel(&model); + QTreeView view; + + view.show(); + view.setModel(&proxy); + QSignalSpy spy(view.selectionModel(), &QItemSelectionModel::currentChanged); + QVERIFY(spy.isValid()); + + view.setCurrentIndex(proxy.index(0, 0)); + QCOMPARE(spy.count(), 1); + setupFilter(&proxy, QLatin1String("^B")); + QCOMPARE(spy.count(), 2); +} + +void tst_QSortFilterProxyModel::filter_qtbug30662() +{ + QStringListModel model; + QSortFilterProxyModel proxy; + proxy.setSourceModel(&model); + + // make sure the filter does not match any entry + setupFilter(&proxy, QLatin1String("[0-9]+")); + + QStringList slSource; + slSource << "z" << "x" << "a" << "b"; + + proxy.setDynamicSortFilter(true); + proxy.sort(0); + model.setStringList(slSource); + + // without fix for QTBUG-30662 this will make all entries visible - but unsorted + setupFilter(&proxy, QLatin1String("[a-z]+")); + + QStringList slResult; + for (int i = 0; i < proxy.rowCount(); ++i) + slResult.append(proxy.index(i, 0).data().toString()); + + slSource.sort(); + QCOMPARE(slResult, slSource); +} + +void tst_QSortFilterProxyModel::changeSourceLayout() +{ + QStandardItemModel model(2, 1); + model.setData(model.index(0, 0), QString("b")); + model.setData(model.index(1, 0), QString("a")); + QSortFilterProxyModel proxy; + proxy.setSourceModel(&model); + + QList persistentSourceIndexes; + QList persistentProxyIndexes; + for (int row = 0; row < model.rowCount(); ++row) { + persistentSourceIndexes.append(model.index(row, 0)); + persistentProxyIndexes.append(proxy.index(row, 0)); + } + + // change layout of source model + model.sort(0, Qt::AscendingOrder); + + for (int row = 0; row < model.rowCount(); ++row) { + QCOMPARE(persistentProxyIndexes.at(row).row(), + persistentSourceIndexes.at(row).row()); + } +} + +void tst_QSortFilterProxyModel::changeSourceLayoutFilteredOut() +{ + QStandardItemModel model(2, 1); + model.setData(model.index(0, 0), QString("b")); + model.setData(model.index(1, 0), QString("a")); + QSortFilterProxyModel proxy; + proxy.setSourceModel(&model); + + int beforeSortFilter = proxy.rowCount(); + + QSignalSpy removeSpy(&proxy, &QSortFilterProxyModel::rowsRemoved); + // Filter everything out + setupFilter(&proxy, QLatin1String("c")); + + QCOMPARE(removeSpy.count(), 1); + QCOMPARE(0, proxy.rowCount()); + + // change layout of source model + model.sort(0, Qt::AscendingOrder); + + QSignalSpy insertSpy(&proxy, &QSortFilterProxyModel::rowsInserted); + // Remove filter; we expect an insert + setupFilter(&proxy, ""); + + QCOMPARE(insertSpy.count(), 1); + QCOMPARE(beforeSortFilter, proxy.rowCount()); +} + +void tst_QSortFilterProxyModel::removeSourceRows_data() +{ + QTest::addColumn("sourceItems"); + QTest::addColumn("start"); + QTest::addColumn("count"); + QTest::addColumn("sortOrder"); + QTest::addColumn("expectedRemovedProxyIntervals"); + QTest::addColumn("expectedProxyItems"); + + QTest::newRow("remove one, no sorting") + << (QStringList() << "a" << "b") // sourceItems + << 0 // start + << 1 // count + << -1 // sortOrder (no sorting) + << (IntPairList() << IntPair(0, 0)) // expectedRemovedIntervals + << (QStringList() << "b") // expectedProxyItems + ; + QTest::newRow("remove one, ascending sort (same order)") + << (QStringList() << "a" << "b") // sourceItems + << 0 // start + << 1 // count + << static_cast(Qt::AscendingOrder) // sortOrder + << (IntPairList() << IntPair(0, 0)) // expectedRemovedIntervals + << (QStringList() << "b") // expectedProxyItems + ; + QTest::newRow("remove one, ascending sort (reverse order)") + << (QStringList() << "b" << "a") // sourceItems + << 0 // start + << 1 // count + << static_cast(Qt::AscendingOrder) // sortOrder + << (IntPairList() << IntPair(1, 1)) // expectedRemovedIntervals + << (QStringList() << "a") // expectedProxyItems + ; + QTest::newRow("remove two, multiple proxy intervals") + << (QStringList() << "c" << "d" << "a" << "b") // sourceItems + << 1 // start + << 2 // count + << static_cast(Qt::AscendingOrder) // sortOrder + << (IntPairList() << IntPair(3, 3) << IntPair(0, 0)) // expectedRemovedIntervals + << (QStringList() << "b" << "c") // expectedProxyItems + ; + QTest::newRow("remove three, multiple proxy intervals") + << (QStringList() << "b" << "d" << "f" << "a" << "c" << "e") // sourceItems + << 3 // start + << 3 // count + << static_cast(Qt::AscendingOrder) // sortOrder + << (IntPairList() << IntPair(4, 4) << IntPair(2, 2) << IntPair(0, 0)) // expectedRemovedIntervals + << (QStringList() << "b" << "d" << "f") // expectedProxyItems + ; + QTest::newRow("remove all, single proxy intervals") + << (QStringList() << "a" << "b" << "c" << "d" << "e" << "f") // sourceItems + << 0 // start + << 6 // count + << static_cast(Qt::DescendingOrder) // sortOrder + << (IntPairList() << IntPair(0, 5)) // expectedRemovedIntervals + << QStringList() // expectedProxyItems + ; +} + +// Check that correct proxy model rows are removed when rows are removed +// from the source model +void tst_QSortFilterProxyModel::removeSourceRows() +{ + QFETCH(QStringList, sourceItems); + QFETCH(int, start); + QFETCH(int, count); + QFETCH(int, sortOrder); + QFETCH(IntPairList, expectedRemovedProxyIntervals); + QFETCH(QStringList, expectedProxyItems); + + QStandardItemModel model; + QSortFilterProxyModel proxy; + + proxy.setSourceModel(&model); + model.insertColumns(0, 1); + model.insertRows(0, sourceItems.count()); + + for (int i = 0; i < sourceItems.count(); ++i) { + QModelIndex sindex = model.index(i, 0, QModelIndex()); + model.setData(sindex, sourceItems.at(i), Qt::DisplayRole); + QModelIndex pindex = proxy.index(i, 0, QModelIndex()); + QCOMPARE(proxy.data(pindex, Qt::DisplayRole), model.data(sindex, Qt::DisplayRole)); + } + + if (sortOrder != -1) + proxy.sort(0, static_cast(sortOrder)); + (void)proxy.rowCount(QModelIndex()); // force mapping + + QSignalSpy removeSpy(&proxy, &QSortFilterProxyModel::rowsRemoved); + QSignalSpy insertSpy(&proxy, &QSortFilterProxyModel::rowsInserted); + QSignalSpy aboutToRemoveSpy(&proxy, &QSortFilterProxyModel::rowsAboutToBeRemoved); + QSignalSpy aboutToInsertSpy(&proxy, &QSortFilterProxyModel::rowsAboutToBeInserted); + + QVERIFY(removeSpy.isValid()); + QVERIFY(insertSpy.isValid()); + QVERIFY(aboutToRemoveSpy.isValid()); + QVERIFY(aboutToInsertSpy.isValid()); + + model.removeRows(start, count, QModelIndex()); + + QCOMPARE(aboutToRemoveSpy.count(), expectedRemovedProxyIntervals.count()); + for (int i = 0; i < aboutToRemoveSpy.count(); ++i) { + QList args = aboutToRemoveSpy.at(i); + QCOMPARE(args.at(1).type(), QVariant::Int); + QCOMPARE(args.at(2).type(), QVariant::Int); + QCOMPARE(args.at(1).toInt(), expectedRemovedProxyIntervals.at(i).first); + QCOMPARE(args.at(2).toInt(), expectedRemovedProxyIntervals.at(i).second); + } + QCOMPARE(removeSpy.count(), expectedRemovedProxyIntervals.count()); + for (int i = 0; i < removeSpy.count(); ++i) { + QList args = removeSpy.at(i); + QCOMPARE(args.at(1).type(), QVariant::Int); + QCOMPARE(args.at(2).type(), QVariant::Int); + QCOMPARE(args.at(1).toInt(), expectedRemovedProxyIntervals.at(i).first); + QCOMPARE(args.at(2).toInt(), expectedRemovedProxyIntervals.at(i).second); + } + + QCOMPARE(insertSpy.count(), 0); + QCOMPARE(aboutToInsertSpy.count(), 0); + + QCOMPARE(proxy.rowCount(QModelIndex()), expectedProxyItems.count()); + for (int i = 0; i < expectedProxyItems.count(); ++i) { + QModelIndex pindex = proxy.index(i, 0, QModelIndex()); + QCOMPARE(proxy.data(pindex, Qt::DisplayRole).toString(), expectedProxyItems.at(i)); + } +} + +void tst_QSortFilterProxyModel::insertSourceRows_data() +{ + QTest::addColumn("sourceItems"); + QTest::addColumn("start"); + QTest::addColumn("newItems"); + QTest::addColumn("sortOrder"); + QTest::addColumn("proxyItems"); + + QTest::newRow("insert (1)") + << (QStringList() << "c" << "b") // sourceItems + << 1 // start + << (QStringList() << "a") // newItems + << static_cast(Qt::AscendingOrder) // sortOrder + << (QStringList() << "a" << "b" << "c") // proxyItems + ; + + QTest::newRow("insert (2)") + << (QStringList() << "d" << "b" << "c") // sourceItems + << 3 // start + << (QStringList() << "a") // newItems + << static_cast(Qt::DescendingOrder) // sortOrder + << (QStringList() << "d" << "c" << "b" << "a") // proxyItems + ; +} + +// Check that rows are inserted at correct position in proxy model when +// rows are inserted into the source model +void tst_QSortFilterProxyModel::insertSourceRows() +{ + QFETCH(QStringList, sourceItems); + QFETCH(int, start); + QFETCH(QStringList, newItems); + QFETCH(int, sortOrder); + QFETCH(QStringList, proxyItems); + + QStandardItemModel model; + QSortFilterProxyModel proxy; + proxy.setDynamicSortFilter(true); + + proxy.setSourceModel(&model); + model.insertColumns(0, 1); + model.insertRows(0, sourceItems.count()); + + for (int i = 0; i < sourceItems.count(); ++i) { + QModelIndex index = model.index(i, 0, QModelIndex()); + model.setData(index, sourceItems.at(i), Qt::DisplayRole); + } + + proxy.sort(0, static_cast(sortOrder)); + (void)proxy.rowCount(QModelIndex()); // force mapping + + model.insertRows(start, newItems.size(), QModelIndex()); + + QCOMPARE(proxy.rowCount(QModelIndex()), proxyItems.count()); + for (int i = 0; i < newItems.count(); ++i) { + QModelIndex index = model.index(start + i, 0, QModelIndex()); + model.setData(index, newItems.at(i), Qt::DisplayRole); + } + + for (int i = 0; i < proxyItems.count(); ++i) { + QModelIndex index = proxy.index(i, 0, QModelIndex()); + QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), proxyItems.at(i)); + } +} + +void tst_QSortFilterProxyModel::changeFilter_data() +{ + QTest::addColumn("sourceItems"); + QTest::addColumn("sortOrder"); + QTest::addColumn("initialFilter"); + QTest::addColumn("initialRemoveIntervals"); + QTest::addColumn("initialProxyItems"); + QTest::addColumn("finalFilter"); + QTest::addColumn("finalRemoveIntervals"); + QTest::addColumn("insertIntervals"); + QTest::addColumn("finalProxyItems"); + + QTest::newRow("filter (1)") + << (QStringList() << "a" << "b" << "c" << "d" << "e" << "f") // sourceItems + << static_cast(Qt::AscendingOrder) // sortOrder + << "a|b|c" // initialFilter + << (IntPairList() << IntPair(3, 5)) // initialRemoveIntervals + << (QStringList() << "a" << "b" << "c") // initialProxyItems + << "b|d|f" // finalFilter + << (IntPairList() << IntPair(2, 2) << IntPair(0, 0)) // finalRemoveIntervals + << (IntPairList() << IntPair(1, 2)) // insertIntervals + << (QStringList() << "b" << "d" << "f") // finalProxyItems + ; + + QTest::newRow("filter (2)") + << (QStringList() << "a" << "b" << "c" << "d" << "e" << "f") // sourceItems + << static_cast(Qt::AscendingOrder) // sortOrder + << "a|c|e" // initialFilter + << (IntPairList() << IntPair(5, 5) << IntPair(3, 3) << IntPair(1, 1)) // initialRemoveIntervals + << (QStringList() << "a" << "c" << "e") // initialProxyItems + << "" // finalFilter + << IntPairList() // finalRemoveIntervals + << (IntPairList() << IntPair(3, 3) << IntPair(2, 2) << IntPair(1, 1)) // insertIntervals + << (QStringList() << "a" << "b" << "c" << "d" << "e" << "f") // finalProxyItems + ; + + QTest::newRow("filter (3)") + << (QStringList() << "a" << "b" << "c") // sourceItems + << static_cast(Qt::AscendingOrder) // sortOrder + << "a" // initialFilter + << (IntPairList() << IntPair(1, 2)) // initialRemoveIntervals + << (QStringList() << "a") // initialProxyItems + << "a" // finalFilter + << IntPairList() // finalRemoveIntervals + << IntPairList() // insertIntervals + << (QStringList() << "a") // finalProxyItems + ; +} + +// Check that rows are added/removed when filter changes +void tst_QSortFilterProxyModel::changeFilter() +{ + QFETCH(QStringList, sourceItems); + QFETCH(int, sortOrder); + QFETCH(QString, initialFilter); + QFETCH(IntPairList, initialRemoveIntervals); + QFETCH(QStringList, initialProxyItems); + QFETCH(QString, finalFilter); + QFETCH(IntPairList, finalRemoveIntervals); + QFETCH(IntPairList, insertIntervals); + QFETCH(QStringList, finalProxyItems); + + QStandardItemModel model; + QSortFilterProxyModel proxy; + + proxy.setSourceModel(&model); + model.insertColumns(0, 1); + model.insertRows(0, sourceItems.count()); + + for (int i = 0; i < sourceItems.count(); ++i) { + QModelIndex index = model.index(i, 0, QModelIndex()); + model.setData(index, sourceItems.at(i), Qt::DisplayRole); + } + + proxy.sort(0, static_cast(sortOrder)); + (void)proxy.rowCount(QModelIndex()); // force mapping + + QSignalSpy initialRemoveSpy(&proxy, &QSortFilterProxyModel::rowsRemoved); + QSignalSpy initialInsertSpy(&proxy, &QSortFilterProxyModel::rowsInserted); + + QVERIFY(initialRemoveSpy.isValid()); + QVERIFY(initialInsertSpy.isValid()); + + setupFilter(&proxy, initialFilter); + + QCOMPARE(initialRemoveSpy.count(), initialRemoveIntervals.count()); + QCOMPARE(initialInsertSpy.count(), 0); + for (int i = 0; i < initialRemoveSpy.count(); ++i) { + QList args = initialRemoveSpy.at(i); + QCOMPARE(args.at(1).type(), QVariant::Int); + QCOMPARE(args.at(2).type(), QVariant::Int); + QCOMPARE(args.at(1).toInt(), initialRemoveIntervals.at(i).first); + QCOMPARE(args.at(2).toInt(), initialRemoveIntervals.at(i).second); + } + + QCOMPARE(proxy.rowCount(QModelIndex()), initialProxyItems.count()); + for (int i = 0; i < initialProxyItems.count(); ++i) { + QModelIndex index = proxy.index(i, 0, QModelIndex()); + QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), initialProxyItems.at(i)); + } + + QSignalSpy finalRemoveSpy(&proxy, &QSortFilterProxyModel::rowsRemoved); + QSignalSpy finalInsertSpy(&proxy, &QSortFilterProxyModel::rowsInserted); + + QVERIFY(finalRemoveSpy.isValid()); + QVERIFY(finalInsertSpy.isValid()); + + setupFilter(&proxy, finalFilter); + + QCOMPARE(finalRemoveSpy.count(), finalRemoveIntervals.count()); + for (int i = 0; i < finalRemoveSpy.count(); ++i) { + QList args = finalRemoveSpy.at(i); + QCOMPARE(args.at(1).type(), QVariant::Int); + QCOMPARE(args.at(2).type(), QVariant::Int); + QCOMPARE(args.at(1).toInt(), finalRemoveIntervals.at(i).first); + QCOMPARE(args.at(2).toInt(), finalRemoveIntervals.at(i).second); + } + + QCOMPARE(finalInsertSpy.count(), insertIntervals.count()); + for (int i = 0; i < finalInsertSpy.count(); ++i) { + QList args = finalInsertSpy.at(i); + QCOMPARE(args.at(1).type(), QVariant::Int); + QCOMPARE(args.at(2).type(), QVariant::Int); + QCOMPARE(args.at(1).toInt(), insertIntervals.at(i).first); + QCOMPARE(args.at(2).toInt(), insertIntervals.at(i).second); + } + + QCOMPARE(proxy.rowCount(QModelIndex()), finalProxyItems.count()); + for (int i = 0; i < finalProxyItems.count(); ++i) { + QModelIndex index = proxy.index(i, 0, QModelIndex()); + QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), finalProxyItems.at(i)); + } +} + +void tst_QSortFilterProxyModel::changeSourceData_data() +{ + QTest::addColumn("sourceItems"); + QTest::addColumn("sortOrder"); + QTest::addColumn("filter"); + QTest::addColumn("expectedInitialProxyItems"); + QTest::addColumn("dynamic"); + QTest::addColumn("row"); + QTest::addColumn("newValue"); + QTest::addColumn("removeIntervals"); + QTest::addColumn("insertIntervals"); + QTest::addColumn("expectedDataChangedRow"); // -1 if no dataChanged signal expected + QTest::addColumn("expectedLayoutChanged"); + QTest::addColumn("proxyItems"); + + QTest::newRow("move_to_end_ascending") + << (QStringList() << "c" << "b" << "a") // sourceItems + << static_cast(Qt::AscendingOrder) // sortOrder + << "" // filter + << (QStringList() << "a" << "b" << "c") // expectedInitialProxyItems + << true // dynamic + << 2 // row + << "z" // newValue + << IntPairList() // removeIntervals + << IntPairList() // insertIntervals + << 2 // dataChanged(row 2) is emitted, see comment "Make sure we also emit dataChanged for the rows" in the source code (unclear why, though) + << true // layoutChanged + << (QStringList() << "b" << "c" << "z") // proxyItems + ; + + QTest::newRow("move_to_end_descending") + << (QStringList() << "b" << "c" << "z") // sourceItems + << static_cast(Qt::DescendingOrder) // sortOrder + << "" // filter + << (QStringList() << "z" << "c" << "b") // expectedInitialProxyItems + << true // dynamic + << 1 // row + << "a" // newValue + << IntPairList() // removeIntervals + << IntPairList() // insertIntervals + << 2 // dataChanged(row 2) is emitted, see comment "Make sure we also emit dataChanged for the rows" in the source code (unclear why, though) + << true // layoutChanged + << (QStringList() << "z" << "b" << "a") // proxyItems + ; + + QTest::newRow("no_op_change") + << (QStringList() << "a" << "b") // sourceItems + << static_cast(Qt::DescendingOrder) // sortOrder + << "" // filter + << (QStringList() << "b" << "a") // expectedInitialProxyItems + << true // dynamic + << 0 // row + << "a" // newValue + << IntPairList() // removeIntervals + << IntPairList() // insertIntervals + << -1 // no dataChanged signal + << false // layoutChanged + << (QStringList() << "b" << "a") // proxyItems + ; + + QTest::newRow("no_effect_on_filtering") + << (QStringList() << "a" << "b") // sourceItems + << static_cast(Qt::AscendingOrder) // sortOrder + << "" // filter + << (QStringList() << "a" << "b") // expectedInitialProxyItems + << true // dynamic + << 1 // row + << "z" // newValue + << IntPairList() // removeIntervals + << IntPairList() // insertIntervals + << 1 // expectedDataChangedRow + << false // layoutChanged + << (QStringList() << "a" << "z") // proxyItems + ; + + QTest::newRow("filtered_out_value_stays_out") + << (QStringList() << "a" << "b" << "c" << "d") // sourceItems + << static_cast(Qt::AscendingOrder) // sortOrder + << "a|c" // filter + << (QStringList() << "a" << "c") // expectedInitialProxyItems + << true // dynamic + << 1 // row + << "x" // newValue + << IntPairList() // removeIntervals + << IntPairList() // insertIntervals + << -1 // no dataChanged signal + << false // layoutChanged + << (QStringList() << "a" << "c") // proxyItems + ; + + QTest::newRow("filtered_out_now_matches") + << (QStringList() << "a" << "b" << "c" << "d") // sourceItems + << static_cast(Qt::AscendingOrder) // sortOrder + << "a|c|x" // filter + << (QStringList() << "a" << "c") // expectedInitialProxyItems + << true // dynamic + << 1 // row + << "x" // newValue + << IntPairList() // removeIntervals + << (IntPairList() << IntPair(2, 2)) // insertIntervals + << -1 // no dataChanged signal + << false // layoutChanged + << (QStringList() << "a" << "c" << "x") // proxyItems + ; + + QTest::newRow("value_is_now_filtered_out") + << (QStringList() << "a" << "b" << "c" << "d") // sourceItems + << static_cast(Qt::AscendingOrder) // sortOrder + << "a|c" // filter + << (QStringList() << "a" << "c") // expectedInitialProxyItems + << true // dynamic + << 2 // row + << "x" // newValue + << (IntPairList() << IntPair(1, 1)) // removeIntervals + << IntPairList() // insertIntervals + << -1 // no dataChanged signal + << false // layoutChanged + << (QStringList() << "a") // proxyItems + ; + + QTest::newRow("non_dynamic_filter_does_not_update_sort") + << (QStringList() << "c" << "b" << "a") // sourceItems + << static_cast(Qt::AscendingOrder) // sortOrder + << "" // filter + << (QStringList() << "a" << "b" << "c") // expectedInitialProxyItems + << false // dynamic + << 2 // row + << "x" // newValue + << IntPairList() // removeIntervals + << IntPairList() // insertIntervals + << 0 // expectedDataChangedRow + << false // layoutChanged + << (QStringList() << "x" << "b" << "c") // proxyItems + ; +} + +void tst_QSortFilterProxyModel::changeSourceData() +{ + QFETCH(QStringList, sourceItems); + QFETCH(int, sortOrder); + QFETCH(QString, filter); + QFETCH(QStringList, expectedInitialProxyItems); + QFETCH(bool, dynamic); + QFETCH(int, row); + QFETCH(QString, newValue); + QFETCH(IntPairList, removeIntervals); + QFETCH(IntPairList, insertIntervals); + QFETCH(int, expectedDataChangedRow); + QFETCH(bool, expectedLayoutChanged); + QFETCH(QStringList, proxyItems); + + QStandardItemModel model; + QSortFilterProxyModel proxy; + + proxy.setDynamicSortFilter(dynamic); + proxy.setSourceModel(&model); + model.insertColumns(0, 1); + model.insertRows(0, sourceItems.count()); + + for (int i = 0; i < sourceItems.count(); ++i) { + QModelIndex index = model.index(i, 0, QModelIndex()); + model.setData(index, sourceItems.at(i), Qt::DisplayRole); + } + + proxy.sort(0, static_cast(sortOrder)); + (void)proxy.rowCount(QModelIndex()); // force mapping + + setupFilter(&proxy, filter); + + QCOMPARE(proxy.rowCount(), expectedInitialProxyItems.count()); + for (int i = 0; i < expectedInitialProxyItems.count(); ++i) { + const QModelIndex index = proxy.index(i, 0, QModelIndex()); + QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expectedInitialProxyItems.at(i)); + } + + QSignalSpy removeSpy(&proxy, &QSortFilterProxyModel::rowsRemoved); + QSignalSpy insertSpy(&proxy, &QSortFilterProxyModel::rowsInserted); + QSignalSpy dataChangedSpy(&proxy, &QSortFilterProxyModel::dataChanged); + QSignalSpy layoutChangedSpy(&proxy, &QSortFilterProxyModel::layoutChanged); + + QVERIFY(removeSpy.isValid()); + QVERIFY(insertSpy.isValid()); + QVERIFY(dataChangedSpy.isValid()); + QVERIFY(layoutChangedSpy.isValid()); + + { + QModelIndex index = model.index(row, 0, QModelIndex()); + model.setData(index, newValue, Qt::DisplayRole); + } + + QCOMPARE(removeSpy.count(), removeIntervals.count()); + for (int i = 0; i < removeSpy.count(); ++i) { + QList args = removeSpy.at(i); + QCOMPARE(args.at(1).type(), QVariant::Int); + QCOMPARE(args.at(2).type(), QVariant::Int); + QCOMPARE(args.at(1).toInt(), removeIntervals.at(i).first); + QCOMPARE(args.at(2).toInt(), removeIntervals.at(i).second); + } + + QCOMPARE(insertSpy.count(), insertIntervals.count()); + for (int i = 0; i < insertSpy.count(); ++i) { + QList args = insertSpy.at(i); + QCOMPARE(args.at(1).type(), QVariant::Int); + QCOMPARE(args.at(2).type(), QVariant::Int); + QCOMPARE(args.at(1).toInt(), insertIntervals.at(i).first); + QCOMPARE(args.at(2).toInt(), insertIntervals.at(i).second); + } + + QCOMPARE(proxy.rowCount(QModelIndex()), proxyItems.count()); + for (int i = 0; i < proxyItems.count(); ++i) { + QModelIndex index = proxy.index(i, 0, QModelIndex()); + QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), proxyItems.at(i)); + } + + if (expectedDataChangedRow == -1) { + QCOMPARE(dataChangedSpy.count(), 0); + } else { + QCOMPARE(dataChangedSpy.count(), 1); + const QModelIndex idx = dataChangedSpy.at(0).at(0).value(); + QCOMPARE(idx.row(), expectedDataChangedRow); + QCOMPARE(idx.column(), 0); + } + + QCOMPARE(layoutChangedSpy.count(), expectedLayoutChanged ? 1 : 0); +} + +// Checks that the model is a table, and that each and every row is like this: +// i-th row: ( rows.at(i), i ) +static void checkSortedTableModel(const QAbstractItemModel *model, const QStringList &rows) +{ + QCOMPARE(model->rowCount(), rows.length()); + QCOMPARE(model->columnCount(), 2); + + for (int row = 0; row < model->rowCount(); ++row) { + const QString column0 = model->index(row, 0).data().toString(); + const int column1 = model->index(row, 1).data().toString().toInt(); + + QCOMPARE(column0, rows.at(row)); + QCOMPARE(column1, row); + } +} + +void tst_QSortFilterProxyModel::changeSourceDataKeepsStableSorting_qtbug1548() +{ + // Check that emitting dataChanged from the source model + // for a change of a role which is not the sorting role + // doesn't alter the sorting. In this case, we sort on the DisplayRole, + // and play with other roles. + + static const QStringList rows + = QStringList() << "a" << "b" << "b" << "b" << "c" << "c" << "x"; + + // Build a table of pairs (string, #row) in each row + QStandardItemModel model(0, 2); + + for (int rowNumber = 0; rowNumber < rows.length(); ++rowNumber) { + QStandardItem *column0 = new QStandardItem(rows.at(rowNumber)); + column0->setCheckable(true); + column0->setCheckState(Qt::Unchecked); + + QStandardItem *column1 = new QStandardItem(QString::number(rowNumber)); + + const QList row + = QList() << column0 << column1; + + model.appendRow(row); + } + + checkSortedTableModel(&model, rows); + + // Build the proxy model + QSortFilterProxyModel proxy; + proxy.setSourceModel(&model); + proxy.setDynamicSortFilter(true); + proxy.sort(0); + + // The proxy is now sorted by the first column, check that the sorting + // * is correct (the input is already sorted, so it must not have changed) + // * was stable (by looking at the second column) + checkSortedTableModel(&model, rows); + + // Change the check status of an item. That must not break the stable sorting + // changes the middle "b" + model.item(2)->setCheckState(Qt::Checked); + checkSortedTableModel(&model, rows); + + // changes the starting "a" + model.item(0)->setCheckState(Qt::Checked); + checkSortedTableModel(&model, rows); + + // change the background color of the first "c" + model.item(4)->setBackground(Qt::red); + checkSortedTableModel(&model, rows); + + // change the background color of the second "c" + model.item(5)->setBackground(Qt::red); + checkSortedTableModel(&model, rows); +} + +void tst_QSortFilterProxyModel::changeSourceDataForwardsRoles_qtbug35440() +{ + QStringList strings; + for (int i = 0; i < 100; ++i) + strings << QString::number(i); + + QStringListModel model(strings); + + QSortFilterProxyModel proxy; + proxy.setSourceModel(&model); + proxy.sort(0, Qt::AscendingOrder); + + QSignalSpy spy(&proxy, &QAbstractItemModel::dataChanged); + QVERIFY(spy.isValid()); + QCOMPARE(spy.length(), 0); + + QModelIndex index; + + // QStringListModel doesn't distinguish between edit and display roles, + // so changing one always changes the other, too. + QVector expectedChangedRoles; + expectedChangedRoles.append(Qt::DisplayRole); + expectedChangedRoles.append(Qt::EditRole); + + index = model.index(0, 0); + QVERIFY(index.isValid()); + model.setData(index, QStringLiteral("teststring"), Qt::DisplayRole); + QCOMPARE(spy.length(), 1); + QCOMPARE(spy.at(0).at(2).value >(), expectedChangedRoles); + + index = model.index(1, 0); + QVERIFY(index.isValid()); + model.setData(index, QStringLiteral("teststring2"), Qt::EditRole); + QCOMPARE(spy.length(), 2); + QCOMPARE(spy.at(1).at(2).value >(), expectedChangedRoles); +} + +void tst_QSortFilterProxyModel::sortFilterRole() +{ + QStandardItemModel model; + QSortFilterProxyModel proxy; + proxy.setSourceModel(&model); + model.insertColumns(0, 1); + + QList > sourceItems; + sourceItems = QList >() + << QPair("b", 3) + << QPair("c", 2) + << QPair("a", 1); + + QList orderedItems; + orderedItems = QList() + << 2 << 1; + + model.insertRows(0, sourceItems.count()); + for (int i = 0; i < sourceItems.count(); ++i) { + QModelIndex index = model.index(i, 0, QModelIndex()); + model.setData(index, sourceItems.at(i).first, Qt::DisplayRole); + model.setData(index, sourceItems.at(i).second, Qt::UserRole); + } + + setupFilter(&proxy, QLatin1String("2")); + + QCOMPARE(proxy.rowCount(), 0); // Qt::DisplayRole is default role + + proxy.setFilterRole(Qt::UserRole); + QCOMPARE(proxy.rowCount(), 1); + + proxy.setFilterRole(Qt::DisplayRole); + QCOMPARE(proxy.rowCount(), 0); + + setupFilter(&proxy, QLatin1String("1|2|3")); + + QCOMPARE(proxy.rowCount(), 0); + + proxy.setFilterRole(Qt::UserRole); + QCOMPARE(proxy.rowCount(), 3); + + proxy.sort(0, Qt::AscendingOrder); + QCOMPARE(proxy.rowCount(), 3); + + proxy.setSortRole(Qt::UserRole); + proxy.setFilterRole(Qt::DisplayRole); + setupFilter(&proxy, QLatin1String("a|c")); + + QCOMPARE(proxy.rowCount(), orderedItems.count()); + for (int i = 0; i < proxy.rowCount(); ++i) { + QModelIndex index = proxy.index(i, 0, QModelIndex()); + QCOMPARE(proxy.data(index, Qt::DisplayRole), sourceItems.at(orderedItems.at(i)).first); + } +} + +void tst_QSortFilterProxyModel::selectionFilteredOut() +{ + QStandardItemModel model(2, 1); + model.setData(model.index(0, 0), QString("AAA")); + model.setData(model.index(1, 0), QString("BBB")); + QSortFilterProxyModel proxy; + proxy.setSourceModel(&model); + QTreeView view; + + view.show(); + view.setModel(&proxy); + QSignalSpy spy(view.selectionModel(), &QItemSelectionModel::currentChanged); + QVERIFY(spy.isValid()); + + view.setCurrentIndex(proxy.index(0, 0)); + QCOMPARE(spy.count(), 1); + + setupFilter(&proxy, QLatin1String("^B")); + QCOMPARE(spy.count(), 2); +} + +void tst_QSortFilterProxyModel::match_data() +{ + QTest::addColumn("sourceItems"); + QTest::addColumn("sortOrder"); + QTest::addColumn("filter"); + QTest::addColumn("proxyStartRow"); + QTest::addColumn("what"); + QTest::addColumn("matchFlags"); + QTest::addColumn("expectedProxyItems"); + QTest::newRow("1") + << (QStringList() << "a") // sourceItems + << static_cast(Qt::AscendingOrder) // sortOrder + << "" // filter + << 0 // proxyStartRow + << "a" // what + << static_cast(Qt::MatchExactly) // matchFlags + << (IntList() << 0); // expectedProxyItems + QTest::newRow("2") + << (QStringList() << "a" << "b") // sourceItems + << static_cast(Qt::AscendingOrder) // sortOrder + << "" // filter + << 0 // proxyStartRow + << "b" // what + << static_cast(Qt::MatchExactly) // matchFlags + << (IntList() << 1); // expectedProxyItems + QTest::newRow("3") + << (QStringList() << "a" << "b") // sourceItems + << static_cast(Qt::DescendingOrder) // sortOrder + << "" // filter + << 0 // proxyStartRow + << "a" // what + << static_cast(Qt::MatchExactly) // matchFlags + << (IntList() << 1); // expectedProxyItems + QTest::newRow("4") + << (QStringList() << "b" << "d" << "a" << "c") // sourceItems + << static_cast(Qt::AscendingOrder) // sortOrder + << "" // filter + << 1 // proxyStartRow + << "a" // what + << static_cast(Qt::MatchExactly) // matchFlags + << IntList(); // expectedProxyItems + QTest::newRow("5") + << (QStringList() << "b" << "d" << "a" << "c") // sourceItems + << static_cast(Qt::AscendingOrder) // sortOrder + << "a|b" // filter + << 0 // proxyStartRow + << "c" // what + << static_cast(Qt::MatchExactly) // matchFlags + << IntList(); // expectedProxyItems + QTest::newRow("6") + << (QStringList() << "b" << "d" << "a" << "c") // sourceItems + << static_cast(Qt::DescendingOrder) // sortOrder + << "a|b" // filter + << 0 // proxyStartRow + << "b" // what + << static_cast(Qt::MatchExactly) // matchFlags + << (IntList() << 0); // expectedProxyItems +} + +void tst_QSortFilterProxyModel::match() +{ + QFETCH(QStringList, sourceItems); + QFETCH(int, sortOrder); + QFETCH(QString, filter); + QFETCH(int, proxyStartRow); + QFETCH(QString, what); + QFETCH(int, matchFlags); + QFETCH(IntList, expectedProxyItems); + + QStandardItemModel model; + QSortFilterProxyModel proxy; + + proxy.setSourceModel(&model); + model.insertColumns(0, 1); + model.insertRows(0, sourceItems.count()); + + for (int i = 0; i < sourceItems.count(); ++i) { + QModelIndex index = model.index(i, 0, QModelIndex()); + model.setData(index, sourceItems.at(i), Qt::DisplayRole); + } + + proxy.sort(0, static_cast(sortOrder)); + setupFilter(&proxy, filter); + + QModelIndex startIndex = proxy.index(proxyStartRow, 0); + QModelIndexList indexes = proxy.match(startIndex, Qt::DisplayRole, what, + expectedProxyItems.count(), + Qt::MatchFlags(matchFlags)); + QCOMPARE(indexes.count(), expectedProxyItems.count()); + for (int i = 0; i < indexes.count(); ++i) + QCOMPARE(indexes.at(i).row(), expectedProxyItems.at(i)); +} + +void tst_QSortFilterProxyModel::insertIntoChildrenlessItem() +{ + QStandardItemModel model; + QStandardItem *itemA = new QStandardItem("a"); + model.appendRow(itemA); + QStandardItem *itemB = new QStandardItem("b"); + model.appendRow(itemB); + QStandardItem *itemC = new QStandardItem("c"); + model.appendRow(itemC); + + QSortFilterProxyModel proxy; + proxy.setSourceModel(&model); + + QSignalSpy colsInsertedSpy(&proxy, &QSortFilterProxyModel::columnsInserted); + QSignalSpy rowsInsertedSpy(&proxy, &QSortFilterProxyModel::rowsInserted); + + QVERIFY(colsInsertedSpy.isValid()); + QVERIFY(rowsInsertedSpy.isValid()); + + (void)proxy.rowCount(QModelIndex()); // force mapping of "a", "b", "c" + QCOMPARE(colsInsertedSpy.count(), 0); + QCOMPARE(rowsInsertedSpy.count(), 0); + + // now add a child to itemB ==> should get insert notification from the proxy + itemB->appendRow(new QStandardItem("a.0")); + QCOMPARE(colsInsertedSpy.count(), 1); + QCOMPARE(rowsInsertedSpy.count(), 1); + + QVariantList args = colsInsertedSpy.takeFirst(); + QCOMPARE(qvariant_cast(args.at(0)), proxy.mapFromSource(itemB->index())); + QCOMPARE(qvariant_cast(args.at(1)), 0); + QCOMPARE(qvariant_cast(args.at(2)), 0); + + args = rowsInsertedSpy.takeFirst(); + QCOMPARE(qvariant_cast(args.at(0)), proxy.mapFromSource(itemB->index())); + QCOMPARE(qvariant_cast(args.at(1)), 0); + QCOMPARE(qvariant_cast(args.at(2)), 0); +} + +void tst_QSortFilterProxyModel::invalidateMappedChildren() +{ + QStandardItemModel model; + + QSortFilterProxyModel proxy; + proxy.setSourceModel(&model); + + QStandardItem *itemA = new QStandardItem("a"); + model.appendRow(itemA); + QStandardItem *itemB = new QStandardItem("b"); + itemA->appendRow(itemB); + + QStandardItem *itemC = new QStandardItem("c"); + itemB->appendRow(itemC); + itemC->appendRow(new QStandardItem("d")); + + // force mappings + (void)proxy.hasChildren(QModelIndex()); + (void)proxy.hasChildren(proxy.mapFromSource(itemA->index())); + (void)proxy.hasChildren(proxy.mapFromSource(itemB->index())); + (void)proxy.hasChildren(proxy.mapFromSource(itemC->index())); + + itemB->removeRow(0); // should invalidate mapping of itemC + itemC = new QStandardItem("c"); + itemA->appendRow(itemC); + itemC->appendRow(new QStandardItem("d")); + + itemA->removeRow(1); // should invalidate mapping of itemC + itemC = new QStandardItem("c"); + itemB->appendRow(itemC); + itemC->appendRow(new QStandardItem("d")); + + QCOMPARE(proxy.rowCount(proxy.mapFromSource(itemA->index())), 1); + QCOMPARE(proxy.rowCount(proxy.mapFromSource(itemB->index())), 1); + QCOMPARE(proxy.rowCount(proxy.mapFromSource(itemC->index())), 1); +} + +class EvenOddFilterModel : public QSortFilterProxyModel +{ +public: + virtual bool filterAcceptsRow(int srcRow, const QModelIndex& srcParent) const + { + if (srcParent.isValid()) + return (srcParent.row() % 2) ^ !(srcRow % 2); + return (srcRow % 2); + } +}; + +void tst_QSortFilterProxyModel::insertRowIntoFilteredParent() +{ + QStandardItemModel model; + EvenOddFilterModel proxy; + proxy.setSourceModel(&model); + + QSignalSpy spy(&proxy, &EvenOddFilterModel::rowsInserted); + QVERIFY(spy.isValid()); + + QStandardItem *itemA = new QStandardItem(); + model.appendRow(itemA); // A will be filtered + QStandardItem *itemB = new QStandardItem(); + itemA->appendRow(itemB); + + QCOMPARE(spy.count(), 0); + + itemA->removeRow(0); + + QCOMPARE(spy.count(), 0); +} + +void tst_QSortFilterProxyModel::filterOutParentAndFilterInChild() +{ + QStandardItemModel model; + QSortFilterProxyModel proxy; + proxy.setSourceModel(&model); + + setupFilter(&proxy, QLatin1String("A|B")); + + QStandardItem *itemA = new QStandardItem("A"); + model.appendRow(itemA); // not filtered + QStandardItem *itemB = new QStandardItem("B"); + itemA->appendRow(itemB); // not filtered + QStandardItem *itemC = new QStandardItem("C"); + itemA->appendRow(itemC); // filtered + + QSignalSpy removedSpy(&proxy, &QSortFilterProxyModel::rowsRemoved); + QSignalSpy insertedSpy(&proxy, &QSortFilterProxyModel::rowsInserted); + + QVERIFY(removedSpy.isValid()); + QVERIFY(insertedSpy.isValid()); + + setupFilter(&proxy, QLatin1String("C")); // A and B will be filtered out, C filtered in + + // we should now have been notified that the subtree represented by itemA has been removed + QCOMPARE(removedSpy.count(), 1); + // we should NOT get any inserts; itemC should be filtered because its parent (itemA) is + QCOMPARE(insertedSpy.count(), 0); +} + +void tst_QSortFilterProxyModel::sourceInsertRows() +{ + QStandardItemModel model; + QSortFilterProxyModel proxyModel; + proxyModel.setSourceModel(&model); + + model.insertColumns(0, 1, QModelIndex()); + model.insertRows(0, 2, QModelIndex()); + + { + QModelIndex parent = model.index(0, 0, QModelIndex()); + model.insertColumns(0, 1, parent); + model.insertRows(0, 1, parent); + } + + { + QModelIndex parent = model.index(1, 0, QModelIndex()); + model.insertColumns(0, 1, parent); + model.insertRows(0, 1, parent); + } + + model.insertRows(0, 1, QModelIndex()); + model.insertRows(0, 1, QModelIndex()); + + QVERIFY(true); // if you got here without asserting, it's all good +} + +void tst_QSortFilterProxyModel::sourceModelDeletion() +{ + QSortFilterProxyModel proxyModel; + { + QStandardItemModel model; + proxyModel.setSourceModel(&model); + QCOMPARE(proxyModel.sourceModel(), static_cast(&model)); + } + QCOMPARE(proxyModel.sourceModel(), static_cast(0)); +} + +void tst_QSortFilterProxyModel::sortColumnTracking1() +{ + QStandardItemModel model; + QSortFilterProxyModel proxyModel; + proxyModel.setSourceModel(&model); + + model.insertColumns(0, 10); + model.insertRows(0, 10); + + proxyModel.sort(1); + QCOMPARE(proxyModel.sortColumn(), 1); + + model.insertColumn(8); + QCOMPARE(proxyModel.sortColumn(), 1); + + model.removeColumn(8); + QCOMPARE(proxyModel.sortColumn(), 1); + + model.insertColumn(2); + QCOMPARE(proxyModel.sortColumn(), 1); + + model.removeColumn(2); + QCOMPARE(proxyModel.sortColumn(), 1); + + model.insertColumn(1); + QCOMPARE(proxyModel.sortColumn(), 2); + + model.removeColumn(1); + QCOMPARE(proxyModel.sortColumn(), 1); + + model.removeColumn(1); + QCOMPARE(proxyModel.sortColumn(), -1); +} + +void tst_QSortFilterProxyModel::sortColumnTracking2() +{ + QStandardItemModel model; + QSortFilterProxyModel proxyModel; + proxyModel.setDynamicSortFilter(true); + proxyModel.setSourceModel(&model); + + proxyModel.sort(0); + QCOMPARE(proxyModel.sortColumn(), 0); + + QList items; // Stable sorting: Items with invalid data should move to the end + items << new QStandardItem << new QStandardItem("foo") << new QStandardItem("bar") + << new QStandardItem("some") << new QStandardItem("others") << new QStandardItem("item") + << new QStandardItem("aa") << new QStandardItem("zz") << new QStandardItem; + + model.insertColumn(0,items); + QCOMPARE(proxyModel.sortColumn(), 0); + QCOMPARE(proxyModel.data(proxyModel.index(0,0)).toString(),QString::fromLatin1("aa")); + const int zzIndex = items.count() - 3; // 2 invalid at end. + QCOMPARE(proxyModel.data(proxyModel.index(zzIndex,0)).toString(),QString::fromLatin1("zz")); +} + +void tst_QSortFilterProxyModel::sortStable() +{ + QStandardItemModel* model = new QStandardItemModel(5, 2); + for (int r = 0; r < 5; r++) { + const QString prefix = QLatin1String("Row:") + QString::number(r) + QLatin1String(", Column:"); + for (int c = 0; c < 2; c++) { + QStandardItem* item = new QStandardItem(prefix + QString::number(c)); + for (int i = 0; i < 3; i++) { + QStandardItem* child = new QStandardItem(QLatin1String("Item ") + QString::number(i)); + item->appendRow( child ); + } + model->setItem(r, c, item); + } + } + model->setHorizontalHeaderItem( 0, new QStandardItem( "Name" )); + model->setHorizontalHeaderItem( 1, new QStandardItem( "Value" )); + + QSortFilterProxyModel *filterModel = new QSortFilterProxyModel(model); + filterModel->setSourceModel(model); + + QTreeView *view = new QTreeView; + view->setModel(filterModel); + QModelIndex firstRoot = filterModel->index(0,0); + view->expand(firstRoot); + view->setSortingEnabled(true); + + view->model()->sort(1, Qt::DescendingOrder); + QVariant lastItemData =filterModel->index(2,0, firstRoot).data(); + view->model()->sort(1, Qt::DescendingOrder); + QCOMPARE(lastItemData, filterModel->index(2,0, firstRoot).data()); +} + +void tst_QSortFilterProxyModel::hiddenColumns() +{ + class MyStandardItemModel : public QStandardItemModel + { + public: + MyStandardItemModel() : QStandardItemModel(0,5) {} + void reset() + { beginResetModel(); endResetModel(); } + friend class tst_QSortFilterProxyModel; + } model; + QSortFilterProxyModel proxy; + proxy.setSourceModel(&model); + + QTableView view; + view.setModel(&proxy); + + view.hideColumn(0); + + QVERIFY(view.isColumnHidden(0)); + model.blockSignals(true); + model.setRowCount(1); + model.blockSignals(false); + model.reset(); + + // In the initial bug report that spawned this test, this would be false + // because resetting model would also reset the hidden columns. + QVERIFY(view.isColumnHidden(0)); +} + +void tst_QSortFilterProxyModel::insertRowsSort() +{ + QStandardItemModel model(2,2); + QSortFilterProxyModel proxyModel; + proxyModel.setSourceModel(&model); + + proxyModel.sort(0); + QCOMPARE(proxyModel.sortColumn(), 0); + + model.insertColumns(0, 3, model.index(0,0)); + QCOMPARE(proxyModel.sortColumn(), 0); + + model.removeColumns(0, 3, model.index(0,0)); + QCOMPARE(proxyModel.sortColumn(), 0); +} + +void tst_QSortFilterProxyModel::staticSorting() +{ + QStandardItemModel model(0, 1); + QSortFilterProxyModel proxy; + proxy.setSourceModel(&model); + proxy.setDynamicSortFilter(false); + QStringList initial = QString("bateau avion dragon hirondelle flamme camion elephant").split(QLatin1Char(' ')); + + // prepare model + QStandardItem *root = model.invisibleRootItem (); + QList items; + for (int i = 0; i < initial.count(); ++i) { + items.append(new QStandardItem(initial.at(i))); + } + root->insertRows(0, items); + QCOMPARE(model.rowCount(QModelIndex()), initial.count()); + QCOMPARE(model.columnCount(QModelIndex()), 1); + + // make sure the proxy is unsorted + QCOMPARE(proxy.columnCount(QModelIndex()), 1); + QCOMPARE(proxy.rowCount(QModelIndex()), initial.count()); + for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) { + QModelIndex index = proxy.index(row, 0, QModelIndex()); + QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), initial.at(row)); + } + + // sort + proxy.sort(0); + + QStringList expected = initial; + expected.sort(); + // make sure the proxy is sorted + for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) { + QModelIndex index = proxy.index(row, 0, QModelIndex()); + QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expected.at(row)); + } + + //update one item. + items.first()->setData("girafe", Qt::DisplayRole); + + // make sure the proxy is updated but not sorted + expected.replaceInStrings("bateau", "girafe"); + for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) { + QModelIndex index = proxy.index(row, 0, QModelIndex()); + QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expected.at(row)); + } + + // sort again + proxy.sort(0); + expected.sort(); + + // make sure the proxy is sorted + for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) { + QModelIndex index = proxy.index(row, 0, QModelIndex()); + QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expected.at(row)); + } +} + +void tst_QSortFilterProxyModel::dynamicSorting() +{ + QStringListModel model1; + const QStringList initial = QString("bateau avion dragon hirondelle flamme camion elephant").split(QLatin1Char(' ')); + model1.setStringList(initial); + QSortFilterProxyModel proxy1; + proxy1.setDynamicSortFilter(false); + proxy1.sort(0); + proxy1.setSourceModel(&model1); + + QCOMPARE(proxy1.columnCount(QModelIndex()), 1); + //the model should not be sorted because sorting has not been set to dynamic yet. + QCOMPARE(proxy1.rowCount(QModelIndex()), initial.count()); + for (int row = 0; row < proxy1.rowCount(QModelIndex()); ++row) { + QModelIndex index = proxy1.index(row, 0, QModelIndex()); + QCOMPARE(proxy1.data(index, Qt::DisplayRole).toString(), initial.at(row)); + } + + proxy1.setDynamicSortFilter(true); + + //now the model should be sorted. + QStringList expected = initial; + expected.sort(); + for (int row = 0; row < proxy1.rowCount(QModelIndex()); ++row) { + QModelIndex index = proxy1.index(row, 0, QModelIndex()); + QCOMPARE(proxy1.data(index, Qt::DisplayRole).toString(), expected.at(row)); + } + + QStringList initial2 = initial; + initial2.replaceInStrings("bateau", "girafe"); + model1.setStringList(initial2); //this will cause a reset + + QStringList expected2 = initial2; + expected2.sort(); + + //now the model should still be sorted. + for (int row = 0; row < proxy1.rowCount(QModelIndex()); ++row) { + QModelIndex index = proxy1.index(row, 0, QModelIndex()); + QCOMPARE(proxy1.data(index, Qt::DisplayRole).toString(), expected2.at(row)); + } + + QStringListModel model2(initial); + proxy1.setSourceModel(&model2); + + //the model should again be sorted + for (int row = 0; row < proxy1.rowCount(QModelIndex()); ++row) { + QModelIndex index = proxy1.index(row, 0, QModelIndex()); + QCOMPARE(proxy1.data(index, Qt::DisplayRole).toString(), expected.at(row)); + } + + //set up the sorting before seting the model up + QSortFilterProxyModel proxy2; + proxy2.sort(0); + proxy2.setSourceModel(&model2); + for (int row = 0; row < proxy2.rowCount(QModelIndex()); ++row) { + QModelIndex index = proxy2.index(row, 0, QModelIndex()); + QCOMPARE(proxy2.data(index, Qt::DisplayRole).toString(), expected.at(row)); + } +} + +class QtTestModel: public QAbstractItemModel +{ +public: + QtTestModel(int _rows, int _cols, QObject *parent = 0) + : QAbstractItemModel(parent) + , rows(_rows) + , cols(_cols) + , wrongIndex(false) + { + } + + bool canFetchMore(const QModelIndex &idx) const + { + return !fetched.contains(idx); + } + + void fetchMore(const QModelIndex &idx) + { + if (fetched.contains(idx)) + return; + beginInsertRows(idx, 0, rows-1); + fetched.insert(idx); + endInsertRows(); + } + + bool hasChildren(const QModelIndex & = QModelIndex()) const + { + return true; + } + + int rowCount(const QModelIndex& parent = QModelIndex()) const + { + return fetched.contains(parent) ? rows : 0; + } + + int columnCount(const QModelIndex& parent = QModelIndex()) const + { + Q_UNUSED(parent); + return cols; + } + + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const + { + if (row < 0 || column < 0 || column >= cols || row >= rows) { + return QModelIndex(); + } + QModelIndex i = createIndex(row, column, int(parent.internalId() + 1)); + parentHash[i] = parent; + return i; + } + + QModelIndex parent(const QModelIndex &index) const + { + if (!parentHash.contains(index)) + return QModelIndex(); + return parentHash[index]; + } + + QVariant data(const QModelIndex &idx, int role) const + { + if (!idx.isValid()) + return QVariant(); + + if (role == Qt::DisplayRole) { + if (idx.row() < 0 || idx.column() < 0 || idx.column() >= cols || idx.row() >= rows) { + wrongIndex = true; + qWarning("Invalid modelIndex [%d,%d,%p]", idx.row(), idx.column(), + idx.internalPointer()); + } + return QLatin1Char('[') + QString::number(idx.row()) + QLatin1Char(',') + + QString::number(idx.column()) + QLatin1Char(']'); + } + return QVariant(); + } + + QSet fetched; + int rows, cols; + mutable bool wrongIndex; + mutable QMap parentHash; +}; + +void tst_QSortFilterProxyModel::fetchMore() +{ + QtTestModel model(10,10); + QSortFilterProxyModel proxy; + proxy.setSourceModel(&model); + QVERIFY(proxy.canFetchMore(QModelIndex())); + QVERIFY(proxy.hasChildren()); + while (proxy.canFetchMore(QModelIndex())) + proxy.fetchMore(QModelIndex()); + QCOMPARE(proxy.rowCount(), 10); + QCOMPARE(proxy.columnCount(), 10); + + QModelIndex idx = proxy.index(1,1); + QVERIFY(idx.isValid()); + QVERIFY(proxy.canFetchMore(idx)); + QVERIFY(proxy.hasChildren(idx)); + while (proxy.canFetchMore(idx)) + proxy.fetchMore(idx); + QCOMPARE(proxy.rowCount(idx), 10); + QCOMPARE(proxy.columnCount(idx), 10); +} + +void tst_QSortFilterProxyModel::hiddenChildren() +{ + QStandardItemModel model; + QSortFilterProxyModel proxy; + proxy.setSourceModel(&model); + proxy.setDynamicSortFilter(true); + + QStandardItem *itemA = new QStandardItem("A VISIBLE"); + model.appendRow(itemA); + QStandardItem *itemB = new QStandardItem("B VISIBLE"); + itemA->appendRow(itemB); + QStandardItem *itemC = new QStandardItem("C"); + itemA->appendRow(itemC); + setupFilter(&proxy, QLatin1String("VISIBLE")); + + QCOMPARE(proxy.rowCount(QModelIndex()) , 1); + QPersistentModelIndex indexA = proxy.index(0,0); + QCOMPARE(proxy.data(indexA).toString(), QString::fromLatin1("A VISIBLE")); + + QCOMPARE(proxy.rowCount(indexA) , 1); + QPersistentModelIndex indexB = proxy.index(0, 0, indexA); + QCOMPARE(proxy.data(indexB).toString(), QString::fromLatin1("B VISIBLE")); + + itemA->setText("A"); + QCOMPARE(proxy.rowCount(QModelIndex()), 0); + QVERIFY(!indexA.isValid()); + QVERIFY(!indexB.isValid()); + + itemB->setText("B"); + itemA->setText("A VISIBLE"); + itemC->setText("C VISIBLE"); + + QCOMPARE(proxy.rowCount(QModelIndex()), 1); + indexA = proxy.index(0,0); + QCOMPARE(proxy.data(indexA).toString(), QString::fromLatin1("A VISIBLE")); + + QCOMPARE(proxy.rowCount(indexA) , 1); + QModelIndex indexC = proxy.index(0, 0, indexA); + QCOMPARE(proxy.data(indexC).toString(), QString::fromLatin1("C VISIBLE")); + + setupFilter(&proxy, QLatin1String("C")); + + QCOMPARE(proxy.rowCount(QModelIndex()), 0); + itemC->setText("invisible"); + itemA->setText("AC"); + + QCOMPARE(proxy.rowCount(QModelIndex()), 1); + indexA = proxy.index(0,0); + QCOMPARE(proxy.data(indexA).toString(), QString::fromLatin1("AC")); + QCOMPARE(proxy.rowCount(indexA) , 0); +} + +void tst_QSortFilterProxyModel::mapFromToSource() +{ + QtTestModel source(10,10); + source.fetchMore(QModelIndex()); + QSortFilterProxyModel proxy; + proxy.setSourceModel(&source); + QCOMPARE(proxy.mapFromSource(source.index(5, 4)), proxy.index(5, 4)); + QCOMPARE(proxy.mapToSource(proxy.index(3, 2)), source.index(3, 2)); + QCOMPARE(proxy.mapFromSource(QModelIndex()), QModelIndex()); + QCOMPARE(proxy.mapToSource(QModelIndex()), QModelIndex()); + +#ifdef QT_NO_DEBUG //if Qt is compiled in debug mode, this will assert + QTest::ignoreMessage(QtWarningMsg, "QSortFilterProxyModel: index from wrong model passed to mapToSource"); + QCOMPARE(proxy.mapToSource(source.index(2, 3)), QModelIndex()); + QTest::ignoreMessage(QtWarningMsg, "QSortFilterProxyModel: index from wrong model passed to mapFromSource"); + QCOMPARE(proxy.mapFromSource(proxy.index(6, 2)), QModelIndex()); +#endif +} + +static QStandardItem *addEntry(QStandardItem* pParent, const QString &description) +{ + QStandardItem* pItem = new QStandardItem(description); + pParent->appendRow(pItem); + return pItem; +} + +void tst_QSortFilterProxyModel::removeRowsRecursive() +{ + QStandardItemModel pModel; + QStandardItem *pItem1 = new QStandardItem("root"); + pModel.appendRow(pItem1); + QList items; + + QStandardItem *pItem11 = addEntry(pItem1,"Sub-heading"); + items << pItem11; + QStandardItem *pItem111 = addEntry(pItem11,"A"); + items << pItem111; + items << addEntry(pItem111,"A1"); + items << addEntry(pItem111,"A2"); + QStandardItem *pItem112 = addEntry(pItem11,"B"); + items << pItem112; + items << addEntry(pItem112,"B1"); + items << addEntry(pItem112,"B2"); + QStandardItem *pItem1123 = addEntry(pItem112,"B3"); + items << pItem1123; + items << addEntry(pItem1123,"B3-"); + + QSortFilterProxyModel proxy; + proxy.setSourceModel(&pModel); + + QList sourceIndexes; + QList proxyIndexes; + foreach (QStandardItem *item, items) { + QModelIndex idx = item->index(); + sourceIndexes << idx; + proxyIndexes << proxy.mapFromSource(idx); + } + + foreach (const QPersistentModelIndex &pidx, sourceIndexes) + QVERIFY(pidx.isValid()); + foreach (const QPersistentModelIndex &pidx, proxyIndexes) + QVERIFY(pidx.isValid()); + + QList itemRow = pItem1->takeRow(0); + + QCOMPARE(itemRow.count(), 1); + QCOMPARE(itemRow.first(), pItem11); + + foreach (const QPersistentModelIndex &pidx, sourceIndexes) + QVERIFY(!pidx.isValid()); + foreach (const QPersistentModelIndex &pidx, proxyIndexes) + QVERIFY(!pidx.isValid()); + + delete pItem11; +} + +void tst_QSortFilterProxyModel::doubleProxySelectionSetSourceModel() +{ + QStandardItemModel *model1 = new QStandardItemModel; + QStandardItem *parentItem = model1->invisibleRootItem(); + for (int i = 0; i < 4; ++i) { + QStandardItem *item = new QStandardItem(QLatin1String("model1 item ") + QString::number(i)); + parentItem->appendRow(item); + parentItem = item; + } + + QStandardItemModel *model2 = new QStandardItemModel; + QStandardItem *parentItem2 = model2->invisibleRootItem(); + for (int i = 0; i < 4; ++i) { + QStandardItem *item = new QStandardItem(QLatin1String("model2 item ") + QString::number(i)); + parentItem2->appendRow(item); + parentItem2 = item; + } + + QSortFilterProxyModel *toggleProxy = new QSortFilterProxyModel; + toggleProxy->setSourceModel(model1); + + QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel; + proxyModel->setSourceModel(toggleProxy); + + QModelIndex mi = proxyModel->index(0, 0, proxyModel->index(0, 0, proxyModel->index(0, 0))); + QItemSelectionModel ism(proxyModel); + ism.select(mi, QItemSelectionModel::Select); + QModelIndexList mil = ism.selectedIndexes(); + QCOMPARE(mil.count(), 1); + QCOMPARE(mil.first(), mi); + + toggleProxy->setSourceModel(model2); + // No crash, it's good news! + QVERIFY(ism.selection().isEmpty()); +} + +void tst_QSortFilterProxyModel::appearsAndSort() +{ + class PModel : public QSortFilterProxyModel + { + public: + PModel() : mVisible(false) {}; + protected: + bool filterAcceptsRow(int, const QModelIndex &) const + { + return mVisible; + } + + public: + void updateXX() + { + mVisible = true; + invalidate(); + } + private: + bool mVisible; + } proxyModel; + + QStringListModel sourceModel; + QStringList list; + list << "b" << "a" << "c"; + sourceModel.setStringList(list); + + proxyModel.setSourceModel(&sourceModel); + proxyModel.setDynamicSortFilter(true); + proxyModel.sort(0, Qt::AscendingOrder); + + QApplication::processEvents(); + QCOMPARE(sourceModel.rowCount(), 3); + QCOMPARE(proxyModel.rowCount(), 0); //all rows are hidden at first; + + QSignalSpy spyAbout1(&proxyModel, &PModel::layoutAboutToBeChanged); + QSignalSpy spyChanged1(&proxyModel, &PModel::layoutChanged); + + QVERIFY(spyAbout1.isValid()); + QVERIFY(spyChanged1.isValid()); + + //introducing secondProxyModel to test the layoutChange when many items appears at once + QSortFilterProxyModel secondProxyModel; + secondProxyModel.setSourceModel(&proxyModel); + secondProxyModel.setDynamicSortFilter(true); + secondProxyModel.sort(0, Qt::DescendingOrder); + QCOMPARE(secondProxyModel.rowCount(), 0); //all rows are hidden at first; + QSignalSpy spyAbout2(&secondProxyModel, &QSortFilterProxyModel::layoutAboutToBeChanged); + QSignalSpy spyChanged2(&secondProxyModel, &QSortFilterProxyModel::layoutChanged); + + QVERIFY(spyAbout2.isValid()); + QVERIFY(spyChanged2.isValid()); + + proxyModel.updateXX(); + QApplication::processEvents(); + //now rows should be visible, and sorted + QCOMPARE(proxyModel.rowCount(), 3); + QCOMPARE(proxyModel.data(proxyModel.index(0,0), Qt::DisplayRole).toString(), QString::fromLatin1("a")); + QCOMPARE(proxyModel.data(proxyModel.index(1,0), Qt::DisplayRole).toString(), QString::fromLatin1("b")); + QCOMPARE(proxyModel.data(proxyModel.index(2,0), Qt::DisplayRole).toString(), QString::fromLatin1("c")); + + //now rows should be visible, and sorted + QCOMPARE(secondProxyModel.rowCount(), 3); + QCOMPARE(secondProxyModel.data(secondProxyModel.index(0,0), Qt::DisplayRole).toString(), QString::fromLatin1("c")); + QCOMPARE(secondProxyModel.data(secondProxyModel.index(1,0), Qt::DisplayRole).toString(), QString::fromLatin1("b")); + QCOMPARE(secondProxyModel.data(secondProxyModel.index(2,0), Qt::DisplayRole).toString(), QString::fromLatin1("a")); + + QCOMPARE(spyAbout1.count(), 1); + QCOMPARE(spyChanged1.count(), 1); + QCOMPARE(spyAbout2.count(), 1); + QCOMPARE(spyChanged2.count(), 1); +} + +void tst_QSortFilterProxyModel::unnecessaryDynamicSorting() +{ + QStringListModel model; + const QStringList initial = QString("bravo charlie delta echo").split(QLatin1Char(' ')); + model.setStringList(initial); + QSortFilterProxyModel proxy; + proxy.setDynamicSortFilter(false); + proxy.setSourceModel(&model); + proxy.sort(Qt::AscendingOrder); + + //append two rows + int maxrows = proxy.rowCount(QModelIndex()); + model.insertRows(maxrows, 2); + model.setData(model.index(maxrows, 0), QString("alpha")); + model.setData(model.index(maxrows + 1, 0), QString("fondue")); + + //append new items to the initial string list and compare with model + QStringList expected = initial; + expected << QString("alpha") << QString("fondue"); + + //if bug 7716 is present, new rows were prepended, when they should have been appended + for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) { + QModelIndex index = proxy.index(row, 0, QModelIndex()); + QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expected.at(row)); + } +} + +class SelectionProxyModel : QAbstractProxyModel +{ + Q_OBJECT +public: + SelectionProxyModel() + : QAbstractProxyModel(), selectionModel(0) + { + } + + QModelIndex mapFromSource(QModelIndex const&) const + { return QModelIndex(); } + + QModelIndex mapToSource(QModelIndex const&) const + { return QModelIndex(); } + + QModelIndex index(int, int, const QModelIndex&) const + { return QModelIndex(); } + + QModelIndex parent(const QModelIndex&) const + { return QModelIndex(); } + + int rowCount(const QModelIndex&) const + { return 0; } + + int columnCount(const QModelIndex&) const + { return 0; } + + void setSourceModel( QAbstractItemModel *sourceModel ) + { + beginResetModel(); + disconnect( sourceModel, SIGNAL(modelAboutToBeReset()), this, SLOT(sourceModelAboutToBeReset()) ); + QAbstractProxyModel::setSourceModel( sourceModel ); + connect( sourceModel, SIGNAL(modelAboutToBeReset()), this, SLOT(sourceModelAboutToBeReset()) ); + endResetModel(); + } + + void setSelectionModel( QItemSelectionModel *_selectionModel ) + { + selectionModel = _selectionModel; + } + +private slots: + void sourceModelAboutToBeReset() + { + QVERIFY( selectionModel->selectedIndexes().size() == 1 ); + beginResetModel(); + } + + void sourceModelReset() + { + endResetModel(); + } + +private: + QItemSelectionModel *selectionModel; +}; + +void tst_QSortFilterProxyModel::testMultipleProxiesWithSelection() +{ + QStringListModel model; + const QStringList initial = QString("bravo charlie delta echo").split(QLatin1Char(' ')); + model.setStringList(initial); + + QSortFilterProxyModel proxy; + proxy.setSourceModel( &model ); + + SelectionProxyModel proxy1; + QSortFilterProxyModel proxy2; + + // Note that the order here matters. The order of the sourceAboutToBeReset + // exposes the bug in QSortFilterProxyModel. + proxy2.setSourceModel( &proxy ); + proxy1.setSourceModel( &proxy ); + + QItemSelectionModel selectionModel(&proxy2); + proxy1.setSelectionModel( &selectionModel ); + + selectionModel.select( proxy2.index( 0, 0 ), QItemSelectionModel::Select ); + + // trick the proxy into emitting begin/end reset signals. + proxy.setSourceModel(0); +} + +static bool isValid(const QItemSelection &selection) +{ + foreach (const QItemSelectionRange &range, selection) + if (!range.isValid()) + return false; + return true; +} + +void tst_QSortFilterProxyModel::mapSelectionFromSource() +{ + QStringListModel model; + const QStringList initial = QString("bravo charlie delta echo").split(QLatin1Char(' ')); + model.setStringList(initial); + + QSortFilterProxyModel proxy; + proxy.setDynamicSortFilter(true); + setupFilter(&proxy, QLatin1String("d.*")); + + proxy.setSourceModel(&model); + + // Only "delta" remains. + QCOMPARE(proxy.rowCount(), 1); + + QItemSelection selection; + QModelIndex charlie = model.index(1, 0); + selection.append(QItemSelectionRange(charlie, charlie)); + QModelIndex delta = model.index(2, 0); + selection.append(QItemSelectionRange(delta, delta)); + QModelIndex echo = model.index(3, 0); + selection.append(QItemSelectionRange(echo, echo)); + + QVERIFY(isValid(selection)); + + QItemSelection proxiedSelection = proxy.mapSelectionFromSource(selection); + + // Only "delta" is in the mapped result. + QCOMPARE(proxiedSelection.size(), 1); + QVERIFY(isValid(proxiedSelection)); +} + +class Model10287 : public QStandardItemModel +{ + Q_OBJECT + +public: + Model10287(QObject *parent = 0) + : QStandardItemModel(0, 1, parent) + { + parentItem = new QStandardItem("parent"); + parentItem->setData(false, Qt::UserRole); + appendRow(parentItem); + + childItem = new QStandardItem("child"); + childItem->setData(true, Qt::UserRole); + parentItem->appendRow(childItem); + + childItem2 = new QStandardItem("child2"); + childItem2->setData(true, Qt::UserRole); + parentItem->appendRow(childItem2); + } + + void removeChild() + { + childItem2->setData(false, Qt::UserRole); + parentItem->removeRow(0); + } + +private: + QStandardItem *parentItem, *childItem, *childItem2; +}; + +class Proxy10287 : public QSortFilterProxyModel +{ + Q_OBJECT + +public: + Proxy10287(QAbstractItemModel *model, QObject *parent = 0) + : QSortFilterProxyModel(parent) + { + setSourceModel(model); + setDynamicSortFilter(true); + } + +protected: + virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const + { + // Filter based on UserRole in model + QModelIndex i = sourceModel()->index(source_row, 0, source_parent); + return i.data(Qt::UserRole).toBool(); + } +}; + +void tst_QSortFilterProxyModel::unnecessaryMapCreation() +{ + Model10287 m; + Proxy10287 p(&m); + m.removeChild(); + // No assert failure, it passes. +} + +class FilteredColumnProxyModel : public QSortFilterProxyModel +{ + Q_OBJECT +public: + FilteredColumnProxyModel(QObject *parent = 0) + : QSortFilterProxyModel(parent) + { + } + +protected: + bool filterAcceptsColumn(int column, const QModelIndex & /* source_parent */) const + { + return column % 2 != 0; + } +}; + +void tst_QSortFilterProxyModel::filteredColumns() +{ + DynamicTreeModel *model = new DynamicTreeModel(this); + + FilteredColumnProxyModel *proxy = new FilteredColumnProxyModel(this); + proxy->setSourceModel(model); + + new QAbstractItemModelTester(proxy, this); + + ModelInsertCommand *insertCommand = new ModelInsertCommand(model, this); + insertCommand->setNumCols(2); + insertCommand->setStartRow(0); + insertCommand->setEndRow(0); + // Parent is QModelIndex() + insertCommand->doCommand(); +} + +class ChangableHeaderData : public QStringListModel +{ + Q_OBJECT +public: + explicit ChangableHeaderData(QObject *parent = 0) + : QStringListModel(parent) + { + + } + + void emitHeaderDataChanged() + { + headerDataChanged(Qt::Vertical, 0, rowCount() - 1); + } +}; + + +void tst_QSortFilterProxyModel::headerDataChanged() +{ + ChangableHeaderData *model = new ChangableHeaderData(this); + + QStringList numbers; + for (int i = 0; i < 10; ++i) + numbers.append(QString::number(i)); + model->setStringList(numbers); + + QSortFilterProxyModel *proxy = new QSortFilterProxyModel(this); + proxy->setSourceModel(model); + + new QAbstractItemModelTester(proxy, this); + + model->emitHeaderDataChanged(); +} + +void tst_QSortFilterProxyModel::resetInvalidate_data() +{ + QTest::addColumn("test"); + QTest::addColumn("works"); + + QTest::newRow("nothing") << 0 << false; + QTest::newRow("reset") << 1 << true; + QTest::newRow("invalidate") << 2 << true; + QTest::newRow("invalidate_filter") << 3 << true; +} + +void tst_QSortFilterProxyModel::resetInvalidate() +{ + QFETCH(int, test); + QFETCH(bool, works); + + struct Proxy : QSortFilterProxyModel { + QString pattern; + virtual bool filterAcceptsRow(int source_row, const QModelIndex&) const + { + return sourceModel()->data(sourceModel()->index(source_row, 0)).toString().contains(pattern); + } + void notifyChange(int test) + { + switch (test) { + case 0: break; + case 1: + beginResetModel(); + endResetModel(); + break; + case 2: invalidate(); break; + case 3: invalidateFilter(); break; + } + } + }; + + QStringListModel sourceModel(QStringList() << "Poisson" << "Vache" << "Brebis" + << "Elephant" << "Cochon" << "Serpent" + << "Mouton" << "Ecureuil" << "Mouche"); + Proxy proxy; + proxy.pattern = QString::fromLatin1("n"); + proxy.setSourceModel(&sourceModel); + + QCOMPARE(proxy.rowCount(), 5); + for (int i = 0; i < proxy.rowCount(); i++) { + QVERIFY(proxy.data(proxy.index(i,0)).toString().contains('n')); + } + + proxy.pattern = QString::fromLatin1("o"); + proxy.notifyChange(test); + + QCOMPARE(proxy.rowCount(), works ? 4 : 5); + bool ok = true; + for (int i = 0; i < proxy.rowCount(); i++) { + if (!proxy.data(proxy.index(i,0)).toString().contains('o')) + ok = false; + } + QCOMPARE(ok, works); +} + +/** + * A proxy which changes the background color for items ending in 'y' or 'r' + */ +class CustomDataProxy : public QSortFilterProxyModel +{ + Q_OBJECT + +public: + CustomDataProxy(QObject *parent = 0) + : QSortFilterProxyModel(parent) + { + setDynamicSortFilter(true); + } + + void setSourceModel(QAbstractItemModel *sourceModel) + { + // It would be possible to use only the modelReset signal of the source model to clear + // the data in *this, however, this requires that the slot is connected + // before QSortFilterProxyModel::setSourceModel is called, and even then depends + // on the order of invocation of slots being the same as the order of connection. + // ie, not reliable. +// connect(sourceModel, SIGNAL(modelReset()), SLOT(resetInternalData())); + QSortFilterProxyModel::setSourceModel(sourceModel); + // Making the connect after the setSourceModel call clears the data too late. +// connect(sourceModel, SIGNAL(modelReset()), SLOT(resetInternalData())); + + // This could be done in data(), but the point is to need to cache something in the proxy + // which needs to be cleared on reset. + for (int i = 0; i < sourceModel->rowCount(); ++i) + { + if (sourceModel->index(i, 0).data().toString().endsWith(QLatin1Char('y'))) + { + m_backgroundColours.insert(i, Qt::blue); + } else if (sourceModel->index(i, 0).data().toString().endsWith(QLatin1Char('r'))) + { + m_backgroundColours.insert(i, Qt::red); + } + } + } + + QVariant data(const QModelIndex &index, int role) const + { + if (role != Qt::BackgroundRole) + return QSortFilterProxyModel::data(index, role); + return m_backgroundColours.value(index.row()); + } + +private slots: + void resetInternalData() + { + m_backgroundColours.clear(); + } + +private: + QHash m_backgroundColours; +}; + +class ModelObserver : public QObject +{ + Q_OBJECT +public: + ModelObserver(QAbstractItemModel *model, QObject *parent = 0) + : QObject(parent), m_model(model) + { + connect(m_model, SIGNAL(modelAboutToBeReset()), SLOT(modelAboutToBeReset())); + connect(m_model, SIGNAL(modelReset()), SLOT(modelReset())); + } + +public slots: + void modelAboutToBeReset() + { + int reds = 0, blues = 0; + for (int i = 0; i < m_model->rowCount(); ++i) + { + QColor color = m_model->index(i, 0).data(Qt::BackgroundRole).value(); + if (color == Qt::blue) + ++blues; + if (color == Qt::red) + ++reds; + } + QCOMPARE(blues, 11); + QCOMPARE(reds, 4); + } + + void modelReset() + { + int reds = 0, blues = 0; + for (int i = 0; i < m_model->rowCount(); ++i) + { + QColor color = m_model->index(i, 0).data(Qt::BackgroundRole).value(); + if (color == Qt::blue) + ++blues; + if (color == Qt::red) + ++reds; + } + QCOMPARE(reds, 0); + QCOMPARE(blues, 0); + } + +private: + QAbstractItemModel * const m_model; + +}; + +void tst_QSortFilterProxyModel::testResetInternalData() +{ + + QStringListModel model(QStringList() << "Monday" + << "Tuesday" + << "Wednesday" + << "Thursday" + << "Friday" + << "January" + << "February" + << "March" + << "April" + << "May" + << "Saturday" + << "June" + << "Sunday" + << "July" + << "August" + << "September" + << "October" + << "November" + << "December"); + + CustomDataProxy proxy; + proxy.setSourceModel(&model); + + ModelObserver observer(&proxy); + + // Cause the source model to reset. + model.setStringList(QStringList() << "Spam" << "Eggs"); + +} + +void tst_QSortFilterProxyModel::testParentLayoutChanged() +{ + QStandardItemModel model; + QStandardItem *parentItem = model.invisibleRootItem(); + for (int i = 0; i < 4; ++i) { + { + QStandardItem *item = new QStandardItem(QLatin1String("item ") + QString::number(i)); + parentItem->appendRow(item); + } + { + QStandardItem *item = new QStandardItem(QLatin1String("item 1") + QString::number(i)); + parentItem->appendRow(item); + parentItem = item; + } + } + // item 0 + // item 10 + // - item 1 + // - item 11 + // - item 2 + // - item 12 + // ... + + QSortFilterProxyModel proxy; + proxy.sort(0, Qt::AscendingOrder); + proxy.setDynamicSortFilter(true); + + proxy.setSourceModel(&model); + proxy.setObjectName("proxy"); + + // When Proxy1 emits layoutChanged(QList) this + // one will too, with mapped indexes. + QSortFilterProxyModel proxy2; + proxy2.sort(0, Qt::AscendingOrder); + proxy2.setDynamicSortFilter(true); + + proxy2.setSourceModel(&proxy); + proxy2.setObjectName("proxy2"); + + QSignalSpy dataChangedSpy(&model, &QSortFilterProxyModel::dataChanged); + + QVERIFY(dataChangedSpy.isValid()); + + // Verify that the no-arg signal is still emitted. + QSignalSpy layoutAboutToBeChangedSpy(&proxy, &QSortFilterProxyModel::layoutAboutToBeChanged); + QSignalSpy layoutChangedSpy(&proxy, &QSortFilterProxyModel::layoutChanged); + + QVERIFY(layoutAboutToBeChangedSpy.isValid()); + QVERIFY(layoutChangedSpy.isValid()); + + QSignalSpy parentsAboutToBeChangedSpy(&proxy, &QSortFilterProxyModel::layoutAboutToBeChanged); + QSignalSpy parentsChangedSpy(&proxy, &QSortFilterProxyModel::layoutChanged); + + QVERIFY(parentsAboutToBeChangedSpy.isValid()); + QVERIFY(parentsChangedSpy.isValid()); + + QSignalSpy proxy2ParentsAboutToBeChangedSpy(&proxy2, &QSortFilterProxyModel::layoutAboutToBeChanged); + QSignalSpy proxy2ParentsChangedSpy(&proxy2, &QSortFilterProxyModel::layoutChanged); + + QVERIFY(proxy2ParentsAboutToBeChangedSpy.isValid()); + QVERIFY(proxy2ParentsChangedSpy.isValid()); + + QStandardItem *item = model.invisibleRootItem()->child(1)->child(1); + QCOMPARE(item->text(), QStringLiteral("item 11")); + + // Ensure mapped: + proxy.mapFromSource(model.indexFromItem(item)); + + item->setText("Changed"); + + QCOMPARE(dataChangedSpy.size(), 1); + QCOMPARE(layoutAboutToBeChangedSpy.size(), 1); + QCOMPARE(layoutChangedSpy.size(), 1); + QCOMPARE(parentsAboutToBeChangedSpy.size(), 1); + QCOMPARE(parentsChangedSpy.size(), 1); + QCOMPARE(proxy2ParentsAboutToBeChangedSpy.size(), 1); + QCOMPARE(proxy2ParentsChangedSpy.size(), 1); + + QVariantList beforeSignal = parentsAboutToBeChangedSpy.first(); + QVariantList afterSignal = parentsChangedSpy.first(); + + QCOMPARE(beforeSignal.size(), 2); + QCOMPARE(afterSignal.size(), 2); + + QList beforeParents = beforeSignal.first().value >(); + QList afterParents = afterSignal.first().value >(); + + QCOMPARE(beforeParents.size(), 1); + QCOMPARE(afterParents.size(), 1); + + QVERIFY(beforeParents.first().isValid()); + QVERIFY(beforeParents.first() == afterParents.first()); + + QVERIFY(beforeParents.first() == proxy.mapFromSource(model.indexFromItem(model.invisibleRootItem()->child(1)))); + + QList proxy2BeforeList = proxy2ParentsAboutToBeChangedSpy.first().first().value >(); + QList proxy2AfterList = proxy2ParentsChangedSpy.first().first().value >(); + + QCOMPARE(proxy2BeforeList.size(), beforeParents.size()); + QCOMPARE(proxy2AfterList.size(), afterParents.size()); + foreach (const QPersistentModelIndex &idx, proxy2BeforeList) + QVERIFY(beforeParents.contains(proxy2.mapToSource(idx))); + foreach (const QPersistentModelIndex &idx, proxy2AfterList) + QVERIFY(afterParents.contains(proxy2.mapToSource(idx))); +} + +class SignalArgumentChecker : public QObject +{ + Q_OBJECT +public: + SignalArgumentChecker(QAbstractItemModel *model, QAbstractProxyModel *proxy, QObject *parent = 0) + : QObject(parent), m_proxy(proxy) + { + connect(model, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), SLOT(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int))); + connect(model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), SLOT(rowsMoved(QModelIndex,int,int,QModelIndex,int))); + connect(proxy, SIGNAL(layoutAboutToBeChanged(QList)), SLOT(layoutAboutToBeChanged(QList))); + connect(proxy, SIGNAL(layoutChanged(QList)), SLOT(layoutChanged(QList))); + } + +private slots: + void rowsAboutToBeMoved(const QModelIndex &source, int, int, const QModelIndex &destination, int) + { + m_p1PersistentBefore = source; + m_p2PersistentBefore = destination; + m_p2FirstProxyChild = m_proxy->index(0, 0, m_proxy->mapFromSource(destination)); + } + + void rowsMoved(const QModelIndex &source, int, int, const QModelIndex &destination, int) + { + m_p1PersistentAfter = source; + m_p2PersistentAfter = destination; + } + + void layoutAboutToBeChanged(const QList &parents) + { + QVERIFY(m_p1PersistentBefore.isValid()); + QVERIFY(m_p2PersistentBefore.isValid()); + QCOMPARE(parents.size(), 2); + QVERIFY(parents.first() != parents.at(1)); + QVERIFY(parents.contains(m_proxy->mapFromSource(m_p1PersistentBefore))); + QVERIFY(parents.contains(m_proxy->mapFromSource(m_p2PersistentBefore))); + } + + void layoutChanged(const QList &parents) + { + QVERIFY(m_p1PersistentAfter.isValid()); + QVERIFY(m_p2PersistentAfter.isValid()); + QCOMPARE(parents.size(), 2); + QVERIFY(parents.first() != parents.at(1)); + QVERIFY(parents.contains(m_proxy->mapFromSource(m_p1PersistentAfter))); + QVERIFY(parents.contains(m_proxy->mapFromSource(m_p2PersistentAfter))); + + // In the source model, the rows were moved to row 1 in the parent. + // m_p2FirstProxyChild was created with row 0 in the proxy. + // The moved rows in the proxy do not appear at row 1 because of sorting. + // Sorting causes them to appear at row 0 instead, pushing what used to + // be row 0 in the proxy down by two rows. + QCOMPARE(m_p2FirstProxyChild.row(), 2); + } + +private: + QAbstractProxyModel *m_proxy; + QPersistentModelIndex m_p1PersistentBefore; + QPersistentModelIndex m_p2PersistentBefore; + QPersistentModelIndex m_p1PersistentAfter; + QPersistentModelIndex m_p2PersistentAfter; + + QPersistentModelIndex m_p2FirstProxyChild; +}; + +void tst_QSortFilterProxyModel::moveSourceRows() +{ + DynamicTreeModel model; + + { + ModelInsertCommand insertCommand(&model); + insertCommand.setStartRow(0); + insertCommand.setEndRow(9); + insertCommand.doCommand(); + } + { + ModelInsertCommand insertCommand(&model); + insertCommand.setAncestorRowNumbers(QList() << 2); + insertCommand.setStartRow(0); + insertCommand.setEndRow(9); + insertCommand.doCommand(); + } + { + ModelInsertCommand insertCommand(&model); + insertCommand.setAncestorRowNumbers(QList() << 5); + insertCommand.setStartRow(0); + insertCommand.setEndRow(9); + insertCommand.doCommand(); + } + + QSortFilterProxyModel proxy; + proxy.setDynamicSortFilter(true); + proxy.sort(0, Qt::AscendingOrder); + + // We need to check the arguments at emission time + SignalArgumentChecker checker(&model, &proxy); + + proxy.setSourceModel(&model); + + QSortFilterProxyModel filterProxy; + filterProxy.setDynamicSortFilter(true); + filterProxy.sort(0, Qt::AscendingOrder); + filterProxy.setSourceModel(&proxy); + setupFilter(&filterProxy, QLatin1String("6")); // One of the parents + + QSortFilterProxyModel filterBothProxy; + filterBothProxy.setDynamicSortFilter(true); + filterBothProxy.sort(0, Qt::AscendingOrder); + filterBothProxy.setSourceModel(&proxy); + setupFilter(&filterBothProxy, QLatin1String("5")); // The parents are 6 and 3. This filters both out. + + QSignalSpy modelBeforeSpy(&model, &DynamicTreeModel::rowsAboutToBeMoved); + QSignalSpy modelAfterSpy(&model, &DynamicTreeModel::rowsMoved); + QSignalSpy proxyBeforeMoveSpy(m_proxy, &QSortFilterProxyModel::rowsAboutToBeMoved); + QSignalSpy proxyAfterMoveSpy(m_proxy, &QSortFilterProxyModel::rowsMoved); + QSignalSpy proxyBeforeParentLayoutSpy(&proxy, &QSortFilterProxyModel::layoutAboutToBeChanged); + QSignalSpy proxyAfterParentLayoutSpy(&proxy, &QSortFilterProxyModel::layoutChanged); + QSignalSpy filterBeforeParentLayoutSpy(&filterProxy, &QSortFilterProxyModel::layoutAboutToBeChanged); + QSignalSpy filterAfterParentLayoutSpy(&filterProxy, &QSortFilterProxyModel::layoutChanged); + QSignalSpy filterBothBeforeParentLayoutSpy(&filterBothProxy, &QSortFilterProxyModel::layoutAboutToBeChanged); + QSignalSpy filterBothAfterParentLayoutSpy(&filterBothProxy, &QSortFilterProxyModel::layoutChanged); + + QVERIFY(modelBeforeSpy.isValid()); + QVERIFY(modelAfterSpy.isValid()); + QVERIFY(proxyBeforeMoveSpy.isValid()); + QVERIFY(proxyAfterMoveSpy.isValid()); + QVERIFY(proxyBeforeParentLayoutSpy.isValid()); + QVERIFY(proxyAfterParentLayoutSpy.isValid()); + QVERIFY(filterBeforeParentLayoutSpy.isValid()); + QVERIFY(filterAfterParentLayoutSpy.isValid()); + QVERIFY(filterBothBeforeParentLayoutSpy.isValid()); + QVERIFY(filterBothAfterParentLayoutSpy.isValid()); + + { + ModelMoveCommand moveCommand(&model, 0); + moveCommand.setAncestorRowNumbers(QList() << 2); + moveCommand.setDestAncestors(QList() << 5); + moveCommand.setStartRow(3); + moveCommand.setEndRow(4); + moveCommand.setDestRow(1); + moveCommand.doCommand(); + } + + // Proxy notifies layout change + QCOMPARE(modelBeforeSpy.size(), 1); + QCOMPARE(proxyBeforeParentLayoutSpy.size(), 1); + QCOMPARE(modelAfterSpy.size(), 1); + QCOMPARE(proxyAfterParentLayoutSpy.size(), 1); + + // But it doesn't notify a move. + QCOMPARE(proxyBeforeMoveSpy.size(), 0); + QCOMPARE(proxyAfterMoveSpy.size(), 0); + + QCOMPARE(filterBeforeParentLayoutSpy.size(), 1); + QCOMPARE(filterAfterParentLayoutSpy.size(), 1); + + QList filterBeforeParents = filterBeforeParentLayoutSpy.first().first().value >(); + QList filterAfterParents = filterAfterParentLayoutSpy.first().first().value >(); + + QCOMPARE(filterBeforeParents.size(), 1); + QCOMPARE(filterAfterParents.size(), 1); + + QCOMPARE( + filterBeforeParentLayoutSpy.first().at(1).value(), + QAbstractItemModel::NoLayoutChangeHint); + QCOMPARE(filterAfterParentLayoutSpy.first().at(1).value(), + QAbstractItemModel::NoLayoutChangeHint); + + QCOMPARE(filterBothBeforeParentLayoutSpy.size(), 0); + QCOMPARE(filterBothAfterParentLayoutSpy.size(), 0); +} + +class FilterProxy : public QSortFilterProxyModel +{ + Q_OBJECT +public: + FilterProxy(QObject *parent = 0) + : QSortFilterProxyModel(parent), + mode(false) + { + + } + +public slots: + void setMode(bool on) + { + mode = on; + invalidateFilter(); + } + +protected: + virtual bool filterAcceptsRow ( int source_row, const QModelIndex & source_parent ) const + { + if (mode) { + if (!source_parent.isValid()) { + return true; + } else { + return (source_row % 2) != 0; + } + } else { + if (!source_parent.isValid()) { + return source_row >= 2 && source_row < 10; + } else { + return true; + } + } + } + +private: + bool mode; +}; + +void tst_QSortFilterProxyModel::hierarchyFilterInvalidation() +{ + QStandardItemModel model; + for (int i = 0; i < 10; ++i) { + const QString rowText = QLatin1String("Row ") + QString::number(i); + QStandardItem *child = new QStandardItem(rowText); + for (int j = 0; j < 1; ++j) { + child->appendRow(new QStandardItem(rowText + QLatin1Char('/') + QString::number(j))); + } + model.appendRow(child); + } + + FilterProxy proxy; + proxy.setSourceModel(&model); + + QTreeView view; + view.setModel(&proxy); + + view.setCurrentIndex(proxy.index(2, 0).child(0, 0)); + + view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + + proxy.setMode(true); +} + +class FilterProxy2 : public QSortFilterProxyModel +{ + Q_OBJECT +public: + FilterProxy2(QObject *parent = 0) + : QSortFilterProxyModel(parent), + mode(false) + { + + } + +public slots: + void setMode(bool on) + { + mode = on; + invalidateFilter(); + } + +protected: + virtual bool filterAcceptsRow ( int source_row, const QModelIndex & source_parent ) const + { + if (source_parent.isValid()) { + return true; + } else { + if (0 == source_row) { + return true; + } else { + return !mode; + } + } + } + +private: + bool mode; +}; + +void tst_QSortFilterProxyModel::simpleFilterInvalidation() +{ + QStandardItemModel model; + for (int i = 0; i < 2; ++i) { + QStandardItem *child = new QStandardItem(QLatin1String("Row ") + QString::number(i)); + child->appendRow(new QStandardItem("child")); + model.appendRow(child); + } + + FilterProxy2 proxy; + proxy.setSourceModel(&model); + + QTreeView view; + view.setModel(&proxy); + + view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + + proxy.setMode(true); + model.insertRow(0, new QStandardItem("extra")); +} + +class CustomRoleNameModel : public QAbstractListModel +{ + Q_OBJECT +public: + CustomRoleNameModel(QObject *parent = 0) : QAbstractListModel(parent) {} + + QVariant data(const QModelIndex &index, int role) const + { + Q_UNUSED(index); + Q_UNUSED(role); + return QVariant(); + } + + int rowCount(const QModelIndex &parent = QModelIndex()) const + { + Q_UNUSED(parent); + return 0; + } + + QHash roleNames() const + { + QHash rn = QAbstractListModel::roleNames(); + rn[Qt::UserRole + 1] = "custom"; + return rn; + } +}; + +void tst_QSortFilterProxyModel::chainedProxyModelRoleNames() +{ + QSortFilterProxyModel proxy1; + QSortFilterProxyModel proxy2; + CustomRoleNameModel customModel; + + proxy2.setSourceModel(&proxy1); + + // changing the sourceModel of proxy1 must also update roleNames of proxy2 + proxy1.setSourceModel(&customModel); + QVERIFY(proxy2.roleNames().value(Qt::UserRole + 1) == "custom"); +} + +// A source model with ABABAB rows, where only A rows accept drops. +// It will then be sorted by a QSFPM. +class DropOnOddRows : public QAbstractListModel +{ + Q_OBJECT +public: + DropOnOddRows(QObject *parent = 0) : QAbstractListModel(parent) {} + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override + { + if (role == Qt::DisplayRole) + return (index.row() % 2 == 0) ? "A" : "B"; + return QVariant(); + } + + int rowCount(const QModelIndex &parent = QModelIndex()) const override + { + Q_UNUSED(parent); + return 10; + } + + bool canDropMimeData(const QMimeData *, Qt::DropAction, + int row, int column, const QModelIndex &parent) const override + { + Q_UNUSED(row); + Q_UNUSED(column); + return parent.row() % 2 == 0; + } +}; + +class SourceAssertion : public QSortFilterProxyModel +{ + Q_OBJECT +public: + explicit SourceAssertion(QObject *parent = 0) + : QSortFilterProxyModel(parent) + { + + } + + QModelIndex mapToSource(const QModelIndex &proxyIndex) const override + { + Q_ASSERT(sourceModel()); + return QSortFilterProxyModel::mapToSource(proxyIndex); + } +}; + +void tst_QSortFilterProxyModel::noMapAfterSourceDelete() +{ + SourceAssertion proxy; + QStringListModel *model = new QStringListModel(QStringList() << "Foo" << "Bar"); + + proxy.setSourceModel(model); + + // Create mappings + QPersistentModelIndex persistent = proxy.index(0, 0); + + QVERIFY(persistent.isValid()); + + delete model; + + QVERIFY(!persistent.isValid()); +} + +// QTBUG-39549, test whether canDropMimeData(), dropMimeData() are proxied as well +// by invoking them on a QSortFilterProxyModel proxying a QStandardItemModel that allows drops +// on row #1, filtering for that row. +class DropTestModel : public QStandardItemModel { +public: + explicit DropTestModel(QObject *parent = 0) : QStandardItemModel(0, 1, parent) + { + appendRow(new QStandardItem(QStringLiteral("Row0"))); + appendRow(new QStandardItem(QStringLiteral("Row1"))); + } + + bool canDropMimeData(const QMimeData *, Qt::DropAction, + int row, int /* column */, const QModelIndex & /* parent */) const override + { return row == 1; } + + bool dropMimeData(const QMimeData *, Qt::DropAction, + int row, int /* column */, const QModelIndex & /* parent */) override + { return row == 1; } +}; + +void tst_QSortFilterProxyModel::forwardDropApi() +{ + QSortFilterProxyModel model; + model.setSourceModel(new DropTestModel(&model)); + model.setFilterFixedString(QStringLiteral("Row1")); + QCOMPARE(model.rowCount(), 1); + QVERIFY(model.canDropMimeData(0, Qt::CopyAction, 0, 0, QModelIndex())); + QVERIFY(model.dropMimeData(0, Qt::CopyAction, 0, 0, QModelIndex())); +} + +static QString rowTexts(QAbstractItemModel *model) { + QString str; + for (int row = 0 ; row < model->rowCount(); ++row) + str += model->index(row, 0).data().toString(); + return str; +} + +void tst_QSortFilterProxyModel::canDropMimeData() +{ + // Given a source model which only supports dropping on even rows + DropOnOddRows sourceModel; + QCOMPARE(rowTexts(&sourceModel), QString("ABABABABAB")); + + // and a proxy model that sorts the rows + QSortFilterProxyModel proxy; + proxy.setSourceModel(&sourceModel); + proxy.sort(0, Qt::AscendingOrder); + QCOMPARE(rowTexts(&proxy), QString("AAAAABBBBB")); + + // the proxy should correctly map canDropMimeData to the source model, + // i.e. accept drops on the first 5 rows and refuse drops on the next 5. + for (int row = 0; row < proxy.rowCount(); ++row) + QCOMPARE(proxy.canDropMimeData(0, Qt::CopyAction, -1, -1, proxy.index(row, 0)), row < 5); +} + +void tst_QSortFilterProxyModel::resortingDoesNotBreakTreeModels() +{ + QStandardItemModel *treeModel = new QStandardItemModel(this); + QStandardItem *e1 = new QStandardItem("Loading..."); + e1->appendRow(new QStandardItem("entry10")); + treeModel->appendRow(e1); + QStandardItem *e0 = new QStandardItem("Loading..."); + e0->appendRow(new QStandardItem("entry00")); + e0->appendRow(new QStandardItem("entry01")); + treeModel->appendRow(e0); + + QSortFilterProxyModel proxy; + proxy.setDynamicSortFilter(true); + proxy.sort(0); + proxy.setSourceModel(treeModel); + + QAbstractItemModelTester modelTester(&proxy); + + QCOMPARE(proxy.rowCount(), 2); + e1->setText("entry1"); + e0->setText("entry0"); + + QModelIndex pi0 = proxy.index(0, 0); + QCOMPARE(pi0.data().toString(), QString("entry0")); + QCOMPARE(proxy.rowCount(pi0), 2); + + QModelIndex pi01 = proxy.index(1, 0, pi0); + QCOMPARE(pi01.data().toString(), QString("entry01")); + + QModelIndex pi1 = proxy.index(1, 0); + QCOMPARE(pi1.data().toString(), QString("entry1")); + QCOMPARE(proxy.rowCount(pi1), 1); +} + +void tst_QSortFilterProxyModel::filterHint() +{ + // test that a filtering model does not emit layoutChanged with a hint + QStringListModel model(QStringList() << "one" + << "two" + << "three" + << "four" + << "five" + << "six"); + QSortFilterProxyModel proxy1; + proxy1.setSourceModel(&model); + proxy1.setSortRole(Qt::DisplayRole); + proxy1.setDynamicSortFilter(true); + proxy1.sort(0); + + QSortFilterProxyModel proxy2; + proxy2.setSourceModel(&proxy1); + proxy2.setFilterRole(Qt::DisplayRole); + setupFilter(&proxy2, QLatin1String("^[^ ]*$")); + proxy2.setDynamicSortFilter(true); + + QSignalSpy proxy1BeforeSpy(&proxy1, &QSortFilterProxyModel::layoutAboutToBeChanged); + QSignalSpy proxy1AfterSpy(&proxy1, &QSortFilterProxyModel::layoutChanged); + QSignalSpy proxy2BeforeSpy(&proxy2, &QSortFilterProxyModel::layoutAboutToBeChanged); + QSignalSpy proxy2AfterSpy(&proxy2, &QSortFilterProxyModel::layoutChanged); + + model.setData(model.index(2), QStringLiteral("modified three"), Qt::DisplayRole); + + // The first proxy was re-sorted as one item as changed. + QCOMPARE(proxy1BeforeSpy.size(), 1); + QCOMPARE(proxy1BeforeSpy.first().at(1).value(), + QAbstractItemModel::VerticalSortHint); + QCOMPARE(proxy1AfterSpy.size(), 1); + QCOMPARE(proxy1AfterSpy.first().at(1).value(), + QAbstractItemModel::VerticalSortHint); + + // But the second proxy must not have the VerticalSortHint since an item was filtered + QCOMPARE(proxy2BeforeSpy.size(), 1); + QCOMPARE(proxy2BeforeSpy.first().at(1).value(), + QAbstractItemModel::NoLayoutChangeHint); + QCOMPARE(proxy2AfterSpy.size(), 1); + QCOMPARE(proxy2AfterSpy.first().at(1).value(), + QAbstractItemModel::NoLayoutChangeHint); +} + +/** + + Creates a model where each item has one child, to a set depth, + and the last item has no children. For a model created with + setDepth(4): + + - 1 + - - 2 + - - - 3 + - - - - 4 +*/ +class StepTreeModel : public QAbstractItemModel +{ + Q_OBJECT +public: + StepTreeModel(QObject * parent = 0) + : QAbstractItemModel(parent), m_depth(0) {} + + int columnCount(const QModelIndex& = QModelIndex()) const override { return 1; } + + int rowCount(const QModelIndex& parent = QModelIndex()) const override + { + quintptr parentId = (parent.isValid()) ? parent.internalId() : 0; + return (parentId < m_depth) ? 1 : 0; + } + + QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const override + { + if (role != Qt::DisplayRole) + return QVariant(); + + return QString::number(index.internalId()); + } + + QModelIndex index(int, int, const QModelIndex& parent = QModelIndex()) const override + { + // QTBUG-44962: Would we always expect the parent to belong to the model + qDebug() << parent.model() << this; + Q_ASSERT(!parent.isValid() || parent.model() == this); + + quintptr parentId = (parent.isValid()) ? parent.internalId() : 0; + if (parentId >= m_depth) + return QModelIndex(); + + return createIndex(0, 0, parentId + 1); + } + + QModelIndex parent(const QModelIndex& index) const override + { + if (index.internalId() == 0) + return QModelIndex(); + + return createIndex(0, 0, index.internalId() - 1); + } + + void setDepth(quintptr depth) + { + int parentIdWithLayoutChange = (m_depth < depth) ? m_depth : depth; + + QList parentsOfLayoutChange; + parentsOfLayoutChange.push_back(createIndex(0, 0, parentIdWithLayoutChange)); + + layoutAboutToBeChanged(parentsOfLayoutChange); + + auto existing = persistentIndexList(); + + QList updated; + + for (auto idx : existing) { + if (indexDepth(idx) <= depth) + updated.push_back(idx); + else + updated.push_back({}); + } + + m_depth = depth; + + changePersistentIndexList(existing, updated); + + layoutChanged(parentsOfLayoutChange); + } + +private: + static quintptr indexDepth(QModelIndex const& index) + { + return (index.isValid()) ? 1 + indexDepth(index.parent()) : 0; + } + +private: + quintptr m_depth; +}; + +void tst_QSortFilterProxyModel::sourceLayoutChangeLeavesValidPersistentIndexes() +{ + StepTreeModel model; + Q_SET_OBJECT_NAME(model); + model.setDepth(4); + + QSortFilterProxyModel proxy1; + proxy1.setSourceModel(&model); + Q_SET_OBJECT_NAME(proxy1); + setupFilter(&proxy1, QLatin1String("1|2")); + + // The current state of things: + // model proxy + // - 1 - 1 + // - - 2 - - 2 + // - - - 3 + // - - - - 4 + + // The setDepth call below removes '4' with a layoutChanged call. + // Because the proxy filters that out anyway, the proxy doesn't need + // to emit any signals or update persistent indexes. + + QPersistentModelIndex persistentIndex = proxy1.index(0, 0, proxy1.index(0, 0)); + + model.setDepth(3); + + // Calling parent() causes the internalPointer to be used. + // Before fixing QTBUG-47711, that could be a dangling pointer. + // The use of qDebug here makes sufficient use of the heap to + // cause corruption at runtime with normal use on linux (before + // the fix). valgrind confirms the fix. + qDebug() << persistentIndex.parent(); + QVERIFY(persistentIndex.parent().isValid()); +} + +void tst_QSortFilterProxyModel::rowMoveLeavesValidPersistentIndexes() +{ + DynamicTreeModel model; + Q_SET_OBJECT_NAME(model); + + QList ancestors; + for (auto i = 0; i < 5; ++i) + { + Q_UNUSED(i); + ModelInsertCommand insertCommand(&model); + insertCommand.setAncestorRowNumbers(ancestors); + insertCommand.setStartRow(0); + insertCommand.setEndRow(0); + insertCommand.doCommand(); + ancestors.push_back(0); + } + + QSortFilterProxyModel proxy1; + proxy1.setSourceModel(&model); + Q_SET_OBJECT_NAME(proxy1); + + setupFilter(&proxy1, QLatin1String("1|2")); + + auto item5 = model.match(model.index(0, 0), Qt::DisplayRole, "5", 1, Qt::MatchRecursive).first(); + auto item3 = model.match(model.index(0, 0), Qt::DisplayRole, "3", 1, Qt::MatchRecursive).first(); + + Q_ASSERT(item5.isValid()); + Q_ASSERT(item3.isValid()); + + QPersistentModelIndex persistentIndex = proxy1.match(proxy1.index(0, 0), Qt::DisplayRole, "2", 1, Qt::MatchRecursive).first(); + + ModelMoveCommand moveCommand(&model, 0); + moveCommand.setAncestorRowNumbers(QList{0, 0, 0, 0}); + moveCommand.setStartRow(0); + moveCommand.setEndRow(0); + moveCommand.setDestRow(0); + moveCommand.setDestAncestors(QList{0, 0, 0}); + moveCommand.doCommand(); + + // Calling parent() causes the internalPointer to be used. + // Before fixing QTBUG-47711 (moveRows case), that could be + // a dangling pointer. + QVERIFY(persistentIndex.parent().isValid()); +} + +void tst_QSortFilterProxyModel::emitLayoutChangedOnlyIfSortingChanged_data() +{ + QTest::addColumn("changedRow"); + QTest::addColumn("changedRole"); + QTest::addColumn("newData"); + QTest::addColumn("expectedSourceRowTexts"); + QTest::addColumn("expectedProxyRowTexts"); + QTest::addColumn("expectedLayoutChanged"); + + // Starting point: + // a source model with 8,7,6,5,4,3,2,1 + // a proxy model keeping only even rows and sorting them, therefore showing 2,4,6,8 + + // When setData changes ordering, layoutChanged should be emitted + QTest::newRow("ordering_change") << 0 << Qt::DisplayRole << "0" << "07654321" << "0246" << 1; + + // When setData on visible row doesn't change ordering, layoutChanged should not be emitted + QTest::newRow("no_ordering_change") << 6 << Qt::DisplayRole << "0" << "87654301" << "0468" << 0; + + // When setData happens on a filtered out row, layoutChanged should not be emitted + QTest::newRow("filtered_out") << 1 << Qt::DisplayRole << "9" << "89654321" << "2468" << 0; + + // When setData makes a row visible, layoutChanged should not be emitted (rowsInserted is emitted instead) + QTest::newRow("make_row_visible") << 7 << Qt::DisplayRole << "0" << "87654320" << "02468" << 0; + + // When setData makes a row hidden, layoutChanged should not be emitted (rowsRemoved is emitted instead) + QTest::newRow("make_row_hidden") << 4 << Qt::DisplayRole << "1" << "87651321" << "268" << 0; + + // When setData happens on an unrelated role, layoutChanged should not be emitted + QTest::newRow("unrelated_role") << 0 << Qt::DecorationRole << "" << "87654321" << "2468" << 0; + + // When many changes happen together... and trigger removal, insertion, and layoutChanged + QTest::newRow("many_changes") << -1 << Qt::DisplayRole << "3,4,2,5,6,0,7,9" << "34256079" << "0246" << 1; + + // When many changes happen together... and trigger removal, insertion, but no change in ordering of visible rows => no layoutChanged + QTest::newRow("many_changes_no_layoutChanged") << -1 << Qt::DisplayRole << "7,5,4,3,2,1,0,8" << "75432108" << "0248" << 0; +} + +// Custom version of QStringListModel which supports emitting dataChanged for many rows at once +class CustomStringListModel : public QAbstractListModel +{ +public: + bool setData(const QModelIndex &index, const QVariant &value, int role) override + { + if (index.row() >= 0 && index.row() < lst.size() + && (role == Qt::EditRole || role == Qt::DisplayRole)) { + lst.replace(index.row(), value.toString()); + emit dataChanged(index, index, { Qt::DisplayRole, Qt::EditRole }); + return true; + } + return false; + } + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override + { + if (role == Qt::DisplayRole || role == Qt::EditRole) + return lst.at(index.row()); + return QVariant(); + } + int rowCount(const QModelIndex & = QModelIndex()) const override { return lst.count(); } + + void replaceData(const QStringList &newData) + { + lst = newData; + emit dataChanged(index(0, 0), index(rowCount() - 1, 0), { Qt::DisplayRole, Qt::EditRole }); + } + + void emitDecorationChangedSignal() + { + const QModelIndex idx = index(0, 0); + emit dataChanged(idx, idx, { Qt::DecorationRole }); + } + +private: + QStringList lst; +}; + +void tst_QSortFilterProxyModel::emitLayoutChangedOnlyIfSortingChanged() +{ + QFETCH(int, changedRow); + QFETCH(QString, newData); + QFETCH(Qt::ItemDataRole, changedRole); + QFETCH(QString, expectedSourceRowTexts); + QFETCH(QString, expectedProxyRowTexts); + QFETCH(int, expectedLayoutChanged); + + CustomStringListModel model; + QStringList strings; + for (auto i = 8; i >= 1; --i) + strings.append(QString::number(i)); + model.replaceData(strings); + QCOMPARE(rowTexts(&model), QStringLiteral("87654321")); + + class FilterEvenRowsProxyModel : public QSortFilterProxyModel + { + public: + bool filterAcceptsRow(int srcRow, const QModelIndex& srcParent) const override + { + return sourceModel()->index(srcRow, 0, srcParent).data().toInt() % 2 == 0; + } + }; + + FilterEvenRowsProxyModel proxy; + proxy.sort(0); + proxy.setSourceModel(&model); + QCOMPARE(rowTexts(&proxy), QStringLiteral("2468")); + + QSignalSpy modelDataChangedSpy(&model, &QAbstractItemModel::dataChanged); + QSignalSpy proxyLayoutChangedSpy(&proxy, &QAbstractItemModel::layoutChanged); + + if (changedRole == Qt::DecorationRole) + model.emitDecorationChangedSignal(); + else if (changedRow == -1) + model.replaceData(newData.split(QLatin1Char(','))); + else + model.setData(model.index(changedRow, 0), newData, changedRole); + + QCOMPARE(rowTexts(&model), expectedSourceRowTexts); + QCOMPARE(rowTexts(&proxy), expectedProxyRowTexts); + QCOMPARE(modelDataChangedSpy.size(), 1); + QCOMPARE(proxyLayoutChangedSpy.size(), expectedLayoutChanged); +} + +void tst_QSortFilterProxyModel::removeIntervals_data() +{ + QTest::addColumn("sourceItems"); + QTest::addColumn("sortOrder"); + QTest::addColumn("filter"); + QTest::addColumn("replacementSourceItems"); + QTest::addColumn("expectedRemovedProxyIntervals"); + QTest::addColumn("expectedProxyItems"); + + QTest::newRow("filter all, sort ascending") + << (QStringList() << "a" + << "b" + << "c") // sourceItems + << static_cast(Qt::AscendingOrder) // sortOrder + << "[^x]" // filter + << (QStringList() << "x" + << "x" + << "x") // replacementSourceItems + << (IntPairList() << IntPair(0, 2)) // expectedRemovedIntervals + << QStringList() // expectedProxyItems + ; + + QTest::newRow("filter all, sort descending") + << (QStringList() << "a" + << "b" + << "c") // sourceItems + << static_cast(Qt::DescendingOrder) // sortOrder + << "[^x]" // filter + << (QStringList() << "x" + << "x" + << "x") // replacementSourceItems + << (IntPairList() << IntPair(0, 2)) // expectedRemovedIntervals + << QStringList() // expectedProxyItems + ; + + QTest::newRow("filter first and last, sort ascending") + << (QStringList() << "a" + << "b" + << "c") // sourceItems + << static_cast(Qt::AscendingOrder) // sortOrder + << "[^x]" // filter + << (QStringList() << "x" + << "b" + << "x") // replacementSourceItems + << (IntPairList() << IntPair(2, 2) << IntPair(0, 0)) // expectedRemovedIntervals + << (QStringList() << "b") // expectedProxyItems + ; + + QTest::newRow("filter first and last, sort descending") + << (QStringList() << "a" + << "b" + << "c") // sourceItems + << static_cast(Qt::DescendingOrder) // sortOrder + << "[^x]" // filter + << (QStringList() << "x" + << "b" + << "x") // replacementSourceItems + << (IntPairList() << IntPair(2, 2) << IntPair(0, 0)) // expectedRemovedIntervals + << (QStringList() << "b") // expectedProxyItems + ; +} + +void tst_QSortFilterProxyModel::removeIntervals() +{ + QFETCH(QStringList, sourceItems); + QFETCH(int, sortOrder); + QFETCH(QString, filter); + QFETCH(QStringList, replacementSourceItems); + QFETCH(IntPairList, expectedRemovedProxyIntervals); + QFETCH(QStringList, expectedProxyItems); + + CustomStringListModel model; + QSortFilterProxyModel proxy; + + model.replaceData(sourceItems); + proxy.setSourceModel(&model); + + for (int i = 0; i < sourceItems.count(); ++i) { + QModelIndex sindex = model.index(i, 0, QModelIndex()); + QModelIndex pindex = proxy.index(i, 0, QModelIndex()); + QCOMPARE(proxy.data(pindex, Qt::DisplayRole), model.data(sindex, Qt::DisplayRole)); + } + + proxy.setDynamicSortFilter(true); + + if (sortOrder != -1) + proxy.sort(0, static_cast(sortOrder)); + if (!filter.isEmpty()) + setupFilter(&proxy, filter); + + (void)proxy.rowCount(QModelIndex()); // force mapping + + QSignalSpy removeSpy(&proxy, &QSortFilterProxyModel::rowsRemoved); + QSignalSpy insertSpy(&proxy, &QSortFilterProxyModel::rowsInserted); + QSignalSpy aboutToRemoveSpy(&proxy, &QSortFilterProxyModel::rowsAboutToBeRemoved); + QSignalSpy aboutToInsertSpy(&proxy, &QSortFilterProxyModel::rowsAboutToBeInserted); + + QVERIFY(removeSpy.isValid()); + QVERIFY(insertSpy.isValid()); + QVERIFY(aboutToRemoveSpy.isValid()); + QVERIFY(aboutToInsertSpy.isValid()); + + model.replaceData(replacementSourceItems); + + QCOMPARE(aboutToRemoveSpy.count(), expectedRemovedProxyIntervals.count()); + for (int i = 0; i < aboutToRemoveSpy.count(); ++i) { + QList args = aboutToRemoveSpy.at(i); + QCOMPARE(args.at(1).type(), QVariant::Int); + QCOMPARE(args.at(2).type(), QVariant::Int); + QCOMPARE(args.at(1).toInt(), expectedRemovedProxyIntervals.at(i).first); + QCOMPARE(args.at(2).toInt(), expectedRemovedProxyIntervals.at(i).second); + } + QCOMPARE(removeSpy.count(), expectedRemovedProxyIntervals.count()); + for (int i = 0; i < removeSpy.count(); ++i) { + QList args = removeSpy.at(i); + QCOMPARE(args.at(1).type(), QVariant::Int); + QCOMPARE(args.at(2).type(), QVariant::Int); + QCOMPARE(args.at(1).toInt(), expectedRemovedProxyIntervals.at(i).first); + QCOMPARE(args.at(2).toInt(), expectedRemovedProxyIntervals.at(i).second); + } + + QCOMPARE(insertSpy.count(), 0); + QCOMPARE(aboutToInsertSpy.count(), 0); + + QCOMPARE(proxy.rowCount(QModelIndex()), expectedProxyItems.count()); + for (int i = 0; i < expectedProxyItems.count(); ++i) { + QModelIndex pindex = proxy.index(i, 0, QModelIndex()); + QCOMPARE(proxy.data(pindex, Qt::DisplayRole).toString(), expectedProxyItems.at(i)); + } +} + +void tst_QSortFilterProxyModel::dynamicFilterWithoutSort() +{ + QStringListModel model; + const QStringList initial = QString("bravo charlie delta echo").split(QLatin1Char(' ')); + model.setStringList(initial); + QSortFilterProxyModel proxy; + proxy.setDynamicSortFilter(true); + proxy.setSourceModel(&model); + + QSignalSpy layoutChangeSpy(&proxy, &QAbstractItemModel::layoutChanged); + QSignalSpy resetSpy(&proxy, &QAbstractItemModel::modelReset); + + QVERIFY(layoutChangeSpy.isValid()); + QVERIFY(resetSpy.isValid()); + + model.setStringList(QStringList() << "Monday" << "Tuesday" << "Wednesday" << "Thursday" << "Friday"); + + QVERIFY(layoutChangeSpy.isEmpty()); + + QCOMPARE(model.stringList(), QStringList() << "Monday" << "Tuesday" << "Wednesday" << "Thursday" << "Friday"); + + QCOMPARE(resetSpy.count(), 1); +} + +void tst_QSortFilterProxyModel::checkSetNewModel() +{ + QTreeView tv; + StepTreeModel model1; + model1.setDepth(4); + + QSortFilterProxyModel proxy; + proxy.setSourceModel(&model1); + tv.setModel(&proxy); + tv.show(); + QVERIFY(QTest::qWaitForWindowExposed(&tv)); + tv.expandAll(); + { + StepTreeModel model2; + model2.setDepth(4); + proxy.setSourceModel(&model2); + tv.expandAll(); + proxy.setSourceModel(&model1); + tv.expandAll(); + // the destruction of model2 here caused a proxy model reset due to + // missing disconnect in setSourceModel() + } + // handle repaint events, will assert when qsortfilterproxymodel is in wrong state + QCoreApplication::processEvents(); +} + +#include "tst_qsortfilterproxymodel.moc" diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.h b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.h new file mode 100644 index 0000000000..92f0b35065 --- /dev/null +++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_common/tst_qsortfilterproxymodel.h @@ -0,0 +1,183 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TST_QSORTFILTERPROXYMODEL_H +#define TST_QSORTFILTERPROXYMODEL_H + +#include +#include "dynamictreemodel.h" + +#include +#include +#include +#include + +#include + +typedef QList IntList; +typedef QPair IntPair; +typedef QList IntPairList; + +enum class FilterType { + RegExp, + RegularExpression +}; + +Q_DECLARE_METATYPE(QList) + +class tst_QSortFilterProxyModel : public QObject +{ + Q_OBJECT + +public: + tst_QSortFilterProxyModel(); + +public slots: + void initTestCase(); + void cleanupTestCase(); + void cleanup(); + +private slots: + void getSetCheck(); + void sort_data(); + void sort(); + void sortHierarchy_data(); + void sortHierarchy(); + + void insertRows_data(); + void insertRows(); + void prependRow(); + void removeRows_data(); + void removeRows(); + void removeColumns_data(); + void removeColumns(); + void insertAfterSelect(); + void removeAfterSelect(); + void filter_data(); + void filter(); + void filterHierarchy_data(); + void filterHierarchy(); + void filterColumns_data(); + void filterColumns(); + + void filterTable(); + void filterCurrent(); + void filter_qtbug30662(); + + void changeSourceLayout(); + void changeSourceLayoutFilteredOut(); + void removeSourceRows_data(); + void removeSourceRows(); + void insertSourceRows_data(); + void insertSourceRows(); + void changeFilter_data(); + void changeFilter(); + void changeSourceData_data(); + void changeSourceData(); + void changeSourceDataKeepsStableSorting_qtbug1548(); + void changeSourceDataForwardsRoles_qtbug35440(); + void resortingDoesNotBreakTreeModels(); + void dynamicFilterWithoutSort(); + void sortFilterRole(); + void selectionFilteredOut(); + void match_data(); + void match(); + void insertIntoChildrenlessItem(); + void invalidateMappedChildren(); + void insertRowIntoFilteredParent(); + void filterOutParentAndFilterInChild(); + + void sourceInsertRows(); + void sourceModelDeletion(); + + void sortColumnTracking1(); + void sortColumnTracking2(); + + void sortStable(); + + void hiddenColumns(); + void insertRowsSort(); + void staticSorting(); + void dynamicSorting(); + void fetchMore(); + void hiddenChildren(); + void mapFromToSource(); + void removeRowsRecursive(); + void doubleProxySelectionSetSourceModel(); + void appearsAndSort(); + void unnecessaryDynamicSorting(); + void unnecessaryMapCreation(); + void resetInvalidate_data(); + void resetInvalidate(); + + void testMultipleProxiesWithSelection(); + void mapSelectionFromSource(); + void testResetInternalData(); + void filteredColumns(); + void headerDataChanged(); + + void testParentLayoutChanged(); + void moveSourceRows(); + + void hierarchyFilterInvalidation(); + void simpleFilterInvalidation(); + + void chainedProxyModelRoleNames(); + + void noMapAfterSourceDelete(); + void forwardDropApi(); + void canDropMimeData(); + void filterHint(); + + void sourceLayoutChangeLeavesValidPersistentIndexes(); + void rowMoveLeavesValidPersistentIndexes(); + + void emitLayoutChangedOnlyIfSortingChanged_data(); + void emitLayoutChangedOnlyIfSortingChanged(); + + void checkSetNewModel(); + + void removeIntervals_data(); + void removeIntervals(); + +protected: + void buildHierarchy(const QStringList &data, QAbstractItemModel *model); + void checkHierarchy(const QStringList &data, const QAbstractItemModel *model); + void setupFilter(QSortFilterProxyModel *model, const QString& pattern); + +protected: + FilterType m_filterType; + +private: + QStandardItemModel *m_model; + QSortFilterProxyModel *m_proxy; +}; + +Q_DECLARE_METATYPE(QAbstractItemModel::LayoutChangeHint) + +#endif // TST_QSORTFILTERPROXYMODEL_H diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/.gitignore b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/.gitignore new file mode 100644 index 0000000000..4fdaebc09d --- /dev/null +++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/.gitignore @@ -0,0 +1 @@ +tst_qsortfilterproxymodel_regexp diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/qsortfilterproxymodel_regexp.pro b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/qsortfilterproxymodel_regexp.pro new file mode 100644 index 0000000000..7c510930f4 --- /dev/null +++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/qsortfilterproxymodel_regexp.pro @@ -0,0 +1,16 @@ +CONFIG += testcase +TARGET = tst_qsortfilterproxymodel_regexp + +QT += widgets testlib +mtdir = ../../../other/qabstractitemmodelutils +qsfpmdir = ../qsortfilterproxymodel_common + +INCLUDEPATH += $$PWD/$${mtdir} $$PWD/$${qsfpmdir} +SOURCES += \ + tst_qsortfilterproxymodel_regexp.cpp \ + $${qsfpmdir}/tst_qsortfilterproxymodel.cpp \ + $${mtdir}/dynamictreemodel.cpp + +HEADERS += \ + $${qsfpmdir}/tst_qsortfilterproxymodel.h \ + $${mtdir}/dynamictreemodel.h diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/tst_qsortfilterproxymodel_regexp.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/tst_qsortfilterproxymodel_regexp.cpp new file mode 100644 index 0000000000..e83738661e --- /dev/null +++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regexp/tst_qsortfilterproxymodel_regexp.cpp @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "tst_qsortfilterproxymodel.h" + +class tst_QSortFilterProxyModelRegExp : public tst_QSortFilterProxyModel +{ + Q_OBJECT +public: + tst_QSortFilterProxyModelRegExp(); +private slots: + void tst_invalid(); +}; + +tst_QSortFilterProxyModelRegExp::tst_QSortFilterProxyModelRegExp() : + tst_QSortFilterProxyModel() +{ + m_filterType = FilterType::RegExp; +} + +void tst_QSortFilterProxyModelRegExp::tst_invalid() +{ + const QLatin1String pattern("test"); + QSortFilterProxyModel model; + model.setFilterRegExp(pattern); + QCOMPARE(model.filterRegExp(), QRegExp(pattern)); + model.setFilterRegularExpression(pattern); + QCOMPARE(model.filterRegExp(), QRegExp()); +} + +QTEST_MAIN(tst_QSortFilterProxyModelRegExp) +#include "tst_qsortfilterproxymodel_regexp.moc" diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/.gitignore b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/.gitignore new file mode 100644 index 0000000000..286771e250 --- /dev/null +++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/.gitignore @@ -0,0 +1 @@ +tst_qsortfilterproxymodel_regularexpression diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/qsortfilterproxymodel_regularexpression.pro b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/qsortfilterproxymodel_regularexpression.pro new file mode 100644 index 0000000000..e993d07126 --- /dev/null +++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/qsortfilterproxymodel_regularexpression.pro @@ -0,0 +1,16 @@ +CONFIG += testcase +TARGET = tst_qsortfilterproxymodel_regularexpression + +QT += widgets testlib +mtdir = ../../../other/qabstractitemmodelutils +qsfpmdir = ../qsortfilterproxymodel_common + +INCLUDEPATH += $$PWD/$${mtdir} $${qsfpmdir} +SOURCES += \ + tst_qsortfilterproxymodel_regularexpression.cpp \ + $${qsfpmdir}/tst_qsortfilterproxymodel.cpp \ + $${mtdir}/dynamictreemodel.cpp + +HEADERS += \ + $${qsfpmdir}/tst_qsortfilterproxymodel.h \ + $${mtdir}/dynamictreemodel.h diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/tst_qsortfilterproxymodel_regularexpression.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/tst_qsortfilterproxymodel_regularexpression.cpp new file mode 100644 index 0000000000..821e199bcb --- /dev/null +++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_regularexpression/tst_qsortfilterproxymodel_regularexpression.cpp @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "tst_qsortfilterproxymodel.h" + +class tst_QSortFilterProxyModelRegularExpression : public tst_QSortFilterProxyModel +{ + Q_OBJECT +public: + tst_QSortFilterProxyModelRegularExpression(); +private slots: + void tst_invalid(); +}; + +tst_QSortFilterProxyModelRegularExpression::tst_QSortFilterProxyModelRegularExpression() : + tst_QSortFilterProxyModel() +{ + m_filterType = FilterType::RegularExpression; +} + +void tst_QSortFilterProxyModelRegularExpression::tst_invalid() +{ + const QLatin1String pattern("test"); + QSortFilterProxyModel model; + model.setFilterRegularExpression(pattern); + QCOMPARE(model.filterRegularExpression(), QRegularExpression(pattern)); + model.setFilterRegExp(pattern); + QCOMPARE(model.filterRegularExpression(), QRegularExpression()); +} + +QTEST_MAIN(tst_QSortFilterProxyModelRegularExpression) +#include "tst_qsortfilterproxymodel_regularexpression.moc" -- cgit v1.2.3 From fe9a37ac4865f397533f36d1216dce6ebbacc80b Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 17 Aug 2018 11:19:32 +0200 Subject: QTimeZonePrivate::dataForLocalTime(): cope with negative DST offsets The tz database's latest update now records the cases where summer time is deemed standard and winter-time is deemed DST. (This doesn't change what the offsets are, just how they're described.) The resulting negative DST offsets mess up the algorithm for converting local time to UTC, causing tst_QTimeZone::transitionEachZone() to fail for Europe/Dublin in the hour before its transition; so refine the algorithm to cope with the new case. Task-number: QTBUG-69980 Change-Id: I24003872fffb03b2903161859158d0ce998b3073 Reviewed-by: Thiago Macieira --- src/corelib/tools/qtimezoneprivate.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/corelib/tools/qtimezoneprivate.cpp b/src/corelib/tools/qtimezoneprivate.cpp index 2b6c2ea6a5..44ecf9a6c9 100644 --- a/src/corelib/tools/qtimezoneprivate.cpp +++ b/src/corelib/tools/qtimezoneprivate.cpp @@ -357,10 +357,10 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs, /* So now tran is definitely before and nextTran is either after or only - slightly before. The one with the larger offset is in DST; the other in - standard time. Our hint tells us which of those to use (defaulting to - standard if no hint): try it first; if that fails, try the other; if both - fail life's tricky. + slightly before. One is standard time; we interpret the other as DST + (although the transition might in fact by a change in standard offset). Our + hint tells us which of those to use (defaulting to standard if no hint): try + it first; if that fails, try the other; if both fail, life's tricky. */ Q_ASSERT(forLocalMSecs < 0 || forLocalMSecs - tran.offsetFromUtc * 1000 > tran.atMSecsSinceEpoch); @@ -369,7 +369,9 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs, nextTran.atMSecsSinceEpoch = forLocalMSecs - nextTran.offsetFromUtc * 1000; tran.atMSecsSinceEpoch = forLocalMSecs - tran.offsetFromUtc * 1000; - const bool nextIsDst = tran.offsetFromUtc < nextTran.offsetFromUtc; + // If both or neither have zero DST, treat the one with lower offset as standard: + const bool nextIsDst = !nextTran.daylightTimeOffset == !tran.daylightTimeOffset + ? tran.offsetFromUtc < nextTran.offsetFromUtc : nextTran.daylightTimeOffset; // If that agrees with hint > 0, our first guess is to use nextTran; else tran. const bool nextFirst = nextIsDst == (hint > 0) && nextStart != invalidMSecs(); for (int i = 0; i < 2; i++) { -- cgit v1.2.3 From 67984b265a359a217c833938475a51c010057344 Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Sat, 18 Aug 2018 13:08:50 +0200 Subject: QMimeDatabase: Fix MIME detection issues with magics in MIME hierarchies Assume two MIME types A and B are registered, both with the same glob pattern, A being parent of B, A with some magic rule, and B with another magic rule. Given a file that matches the glob pattern and the magic rule of A, the resulting MIME type depended on the order of registration of A and B, because it would just check if some glob matching MIME type was also a subclass of the magic matching MIME type. The patch prefers the the MIME type that matches by magic if that matches by glob pattern as well (i.e. A in our example). The "recommended checking order" of the spec does handle that case. Task-number: QTBUG-44846 Change-Id: I2af43f6199faf9a42cd9c35d3a045441afbd6217 Reviewed-by: Eike Ziller Reviewed-by: David Faure --- src/corelib/mimetypes/qmimedatabase.cpp | 7 +++++-- .../mimetypes/qmimedatabase/magic-and-hierarchy.foo | 3 +++ .../mimetypes/qmimedatabase/magic-and-hierarchy.xml | 21 +++++++++++++++++++++ .../qmimedatabase/magic-and-hierarchy2.foo | 3 +++ .../corelib/mimetypes/qmimedatabase/testdata.qrc | 3 +++ .../mimetypes/qmimedatabase/tst_qmimedatabase.cpp | 7 +++++++ 6 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy.foo create mode 100644 tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy.xml create mode 100644 tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy2.foo diff --git a/src/corelib/mimetypes/qmimedatabase.cpp b/src/corelib/mimetypes/qmimedatabase.cpp index 68e3c8f10d..a58698af53 100644 --- a/src/corelib/mimetypes/qmimedatabase.cpp +++ b/src/corelib/mimetypes/qmimedatabase.cpp @@ -382,9 +382,12 @@ QMimeType QMimeDatabasePrivate::mimeTypeForFileNameAndData(const QString &fileNa // Disambiguate conflicting extensions (if magic matching found something) if (candidateByData.isValid() && magicAccuracy > 0) { - // "for glob_match in glob_matches:" - // "if glob_match is subclass or equal to sniffed_type, use glob_match" const QString sniffedMime = candidateByData.name(); + // If the sniffedMime matches a glob match, use it + if (candidatesByName.m_matchingMimeTypes.contains(sniffedMime)) { + *accuracyPtr = 100; + return candidateByData; + } for (const QString &m : qAsConst(candidatesByName.m_matchingMimeTypes)) { if (inherits(m, sniffedMime)) { // We have magic + pattern pointing to this, so it's a pretty good match diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy.foo b/tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy.foo new file mode 100644 index 0000000000..ed5e761417 --- /dev/null +++ b/tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy.foo @@ -0,0 +1,3 @@ + + + diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy.xml b/tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy.xml new file mode 100644 index 0000000000..27b5bd7e1f --- /dev/null +++ b/tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy2.foo b/tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy2.foo new file mode 100644 index 0000000000..fd90ed04b3 --- /dev/null +++ b/tests/auto/corelib/mimetypes/qmimedatabase/magic-and-hierarchy2.foo @@ -0,0 +1,3 @@ + + + diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/testdata.qrc b/tests/auto/corelib/mimetypes/qmimedatabase/testdata.qrc index 29666627a1..1002d0195d 100644 --- a/tests/auto/corelib/mimetypes/qmimedatabase/testdata.qrc +++ b/tests/auto/corelib/mimetypes/qmimedatabase/testdata.qrc @@ -7,5 +7,8 @@ invalid-magic1.xml invalid-magic2.xml invalid-magic3.xml + magic-and-hierarchy.xml + magic-and-hierarchy.foo + magic-and-hierarchy2.foo diff --git a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp index 3144c3071c..597d51e7e0 100644 --- a/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp +++ b/tests/auto/corelib/mimetypes/qmimedatabase/tst_qmimedatabase.cpp @@ -52,6 +52,7 @@ static const char *const additionalMimeFiles[] = { "invalid-magic1.xml", "invalid-magic2.xml", "invalid-magic3.xml", + "magic-and-hierarchy.xml", 0 }; @@ -985,6 +986,12 @@ void tst_QMimeDatabase::installNewGlobalMimeType() qDebug() << objcsrc.globPatterns(); } + const QString fooTestFile = QLatin1String(RESOURCE_PREFIX "magic-and-hierarchy.foo"); + QCOMPARE(db.mimeTypeForFile(fooTestFile).name(), QString::fromLatin1("application/foo")); + + const QString fooTestFile2 = QLatin1String(RESOURCE_PREFIX "magic-and-hierarchy2.foo"); + QCOMPARE(db.mimeTypeForFile(fooTestFile2).name(), QString::fromLatin1("application/vnd.qnx.bar-descriptor")); + // Now test removing the mimetype definitions again for (int i = 0; i < m_additionalMimeFileNames.size(); ++i) QFile::remove(destDir + m_additionalMimeFileNames.at(i)); -- cgit v1.2.3 From e4cee4bd572a95eff8d908fb0a1b8cd810f0934e Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 17 Aug 2018 13:07:14 +0200 Subject: Add some local const variables to save some repeated computation QTimeZonePrivate::dataForLocalTime() makes repeated use of the times sixteen hours before and after the target local time, so compute those up front once instead of each time they're needed, giving them expressive names and making code terser. Change-Id: I4b682cc6de2adb98c3ee5489eec4b63ac1090961 Reviewed-by: Thiago Macieira --- src/corelib/tools/qtimezoneprivate.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/corelib/tools/qtimezoneprivate.cpp b/src/corelib/tools/qtimezoneprivate.cpp index 44ecf9a6c9..de571d8d23 100644 --- a/src/corelib/tools/qtimezoneprivate.cpp +++ b/src/corelib/tools/qtimezoneprivate.cpp @@ -260,6 +260,8 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs, const qint64 sixteenHoursInMSecs(16 * 3600 * 1000); Q_STATIC_ASSERT(-sixteenHoursInMSecs / 1000 < QTimeZone::MinUtcOffsetSecs && sixteenHoursInMSecs / 1000 > QTimeZone::MaxUtcOffsetSecs); + const qint64 recent = forLocalMSecs - sixteenHoursInMSecs; + const qint64 imminent = forLocalMSecs + sixteenHoursInMSecs; /* Offsets are Local - UTC, positive to the east of Greenwich, negative to the west; DST offset always exceeds standard offset, when DST applies. @@ -327,7 +329,7 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs, // Get a transition definitely before the local MSecs; usually all we need. // Only around the transition times might we need another. - Data tran = previousTransition(forLocalMSecs - sixteenHoursInMSecs); + Data tran = previousTransition(recent); Q_ASSERT(forLocalMSecs < 0 || // Pre-epoch TZ info may be unavailable forLocalMSecs - tran.offsetFromUtc * 1000 >= tran.atMSecsSinceEpoch); Data nextTran = nextTransition(tran.atMSecsSinceEpoch); @@ -343,8 +345,7 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs, && forLocalMSecs > nextTran.atMSecsSinceEpoch + nextTran.offsetFromUtc * 1000) { Data newTran = nextTransition(nextTran.atMSecsSinceEpoch); if (newTran.atMSecsSinceEpoch == invalidMSecs() - || newTran.atMSecsSinceEpoch + newTran.offsetFromUtc * 1000 - > forLocalMSecs + sixteenHoursInMSecs) { + || newTran.atMSecsSinceEpoch + newTran.offsetFromUtc * 1000 > imminent) { // Definitely not a relevant tansition: too far in the future. break; } @@ -417,8 +418,8 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs, /* Bracket and refine to discover offset. */ qint64 utcEpochMSecs; - int early = offsetFromUtc(forLocalMSecs - sixteenHoursInMSecs); - int late = offsetFromUtc(forLocalMSecs + sixteenHoursInMSecs); + int early = offsetFromUtc(recent); + int late = offsetFromUtc(imminent); if (Q_LIKELY(early == late)) { // > 99% of the time utcEpochMSecs = forLocalMSecs - early * 1000; } else { @@ -439,9 +440,7 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs, utcEpochMSecs = forStd; } else { // Invalid forLocalMSecs: in spring-forward gap. - const int dstStep = daylightTimeOffset(early < late ? - forLocalMSecs + sixteenHoursInMSecs : - forLocalMSecs - sixteenHoursInMSecs); + const int dstStep = daylightTimeOffset(early < late ? imminent : recent); Q_ASSERT(dstStep); // There can't be a transition without it ! utcEpochMSecs = (hint > 0) ? forStd - dstStep : forDst + dstStep; } -- cgit v1.2.3 From 98b030fc952b55b743b699e4b1e185422c0a800d Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 17 Aug 2018 13:10:02 +0200 Subject: Scale a correction by a factor of a thousand that it was missing The difference between two transitions' offsets is measured in seconds, but we add it to a time in milliseconds; so it needs to be scaled to fit. Fortunately rarely enough applied that it hadn't caused any reported problems. Change-Id: I11f9f9e46d43d748220e072ad7504d4c8c5bf192 Reviewed-by: Thiago Macieira --- src/corelib/tools/qtimezoneprivate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/tools/qtimezoneprivate.cpp b/src/corelib/tools/qtimezoneprivate.cpp index de571d8d23..8bf7336a42 100644 --- a/src/corelib/tools/qtimezoneprivate.cpp +++ b/src/corelib/tools/qtimezoneprivate.cpp @@ -402,7 +402,7 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs, 0 < tran.atMSecsSinceEpoch - nextTran.atMSecsSinceEpoch = (nextTran.offsetFromUtc - tran.offsetFromUtc) * 1000 */ - int dstStep = nextTran.offsetFromUtc - tran.offsetFromUtc; + int dstStep = (nextTran.offsetFromUtc - tran.offsetFromUtc) * 1000; Q_ASSERT(dstStep > 0); // How else could we get here ? if (nextFirst) { // hint thought we needed nextTran, so use tran tran.atMSecsSinceEpoch -= dstStep; -- cgit v1.2.3 From 1acafb12070ce4ae70a8030f00cc65d1c157350a Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 17 Aug 2018 14:49:10 +0200 Subject: Use std::partition_point for faster searches among transitions QTzTimeZonePrivate's methods were iterating transitions from first to last, or last to first, to find where .atMSecsSinceEpoch crossed some threshold; but the transitions are sorted in order of increasing .atMSecsSinceEpoch, so binary chop would be more efficient than such linear searches. So use std::partition_point() instead. Change-Id: I65c43cb20fca6685a22ea52a4ca2f1089c128ebf Reviewed-by: Thiago Macieira --- src/corelib/tools/qtimezoneprivate_tz.cpp | 111 +++++++++++++++--------------- 1 file changed, 55 insertions(+), 56 deletions(-) diff --git a/src/corelib/tools/qtimezoneprivate_tz.cpp b/src/corelib/tools/qtimezoneprivate_tz.cpp index 6a27aad9e5..bed62a02bd 100644 --- a/src/corelib/tools/qtimezoneprivate_tz.cpp +++ b/src/corelib/tools/qtimezoneprivate_tz.cpp @@ -878,14 +878,17 @@ QString QTzTimeZonePrivate::displayName(QTimeZone::TimeType timeType, } // Otherwise is strange sequence, so work backwards through trans looking for first match, if any - for (int i = m_tranTimes.size() - 1; i >= 0; --i) { - if (m_tranTimes.at(i).atMSecsSinceEpoch <= currentMSecs) { - tran = dataForTzTransition(m_tranTimes.at(i)); - if ((timeType == QTimeZone::DaylightTime && tran.daylightTimeOffset != 0) - || (timeType == QTimeZone::StandardTime && tran.daylightTimeOffset == 0)) { - return tran.abbreviation; - } - } + auto it = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(), + [currentMSecs](const QTzTransitionTime &at) { + return at.atMSecsSinceEpoch <= currentMSecs; + }); + + while (it != m_tranTimes.cbegin()) { + --it; + tran = dataForTzTransition(*it); + int offset = tran.daylightTimeOffset; + if ((timeType == QTimeZone::DaylightTime) != (offset == 0)) + return tran.abbreviation; } // Otherwise if no match use current data @@ -900,7 +903,7 @@ QString QTzTimeZonePrivate::abbreviation(qint64 atMSecsSinceEpoch) const int QTzTimeZonePrivate::offsetFromUtc(qint64 atMSecsSinceEpoch) const { const QTimeZonePrivate::Data tran = data(atMSecsSinceEpoch); - return tran.standardTimeOffset + tran.daylightTimeOffset; + return tran.offsetFromUtc; // == tran.standardTimeOffset + tran.daylightTimeOffset } int QTzTimeZonePrivate::standardTimeOffset(qint64 atMSecsSinceEpoch) const @@ -942,40 +945,38 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::dataForTzTransition(QTzTransitionTime QTimeZonePrivate::Data QTzTimeZonePrivate::data(qint64 forMSecsSinceEpoch) const { + // If we have no rules (so probably an invalid tz), return invalid data: + if (!m_tranTimes.size()) + return invalidData(); + // If the required time is after the last transition and we have a POSIX rule then use it - if (m_tranTimes.size() > 0 && m_tranTimes.last().atMSecsSinceEpoch < forMSecsSinceEpoch + if (m_tranTimes.last().atMSecsSinceEpoch < forMSecsSinceEpoch && !m_posixRule.isEmpty() && forMSecsSinceEpoch >= 0) { const int year = QDateTime::fromMSecsSinceEpoch(forMSecsSinceEpoch, Qt::UTC).date().year(); QVector posixTrans = calculatePosixTransitions(m_posixRule, year - 1, year + 1, m_tranTimes.last().atMSecsSinceEpoch); - for (int i = posixTrans.size() - 1; i >= 0; --i) { - if (posixTrans.at(i).atMSecsSinceEpoch <= forMSecsSinceEpoch) { - QTimeZonePrivate::Data data = posixTrans.at(i); - data.atMSecsSinceEpoch = forMSecsSinceEpoch; - return data; - } - } - } - - // Otherwise if we can find a valid tran then use its rule - for (int i = m_tranTimes.size() - 1; i >= 0; --i) { - if (m_tranTimes.at(i).atMSecsSinceEpoch <= forMSecsSinceEpoch) { - Data data = dataForTzTransition(m_tranTimes.at(i)); + auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(), + [forMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) { + return at.atMSecsSinceEpoch <= forMSecsSinceEpoch; + }); + if (it > posixTrans.cbegin()) { + QTimeZonePrivate::Data data = *--it; data.atMSecsSinceEpoch = forMSecsSinceEpoch; return data; } } - // Otherwise use the earliest transition we have - if (m_tranTimes.size() > 0) { - Data data = dataForTzTransition(m_tranTimes.at(0)); - data.atMSecsSinceEpoch = forMSecsSinceEpoch; - return data; - } - - // Otherwise we have no rules, so probably an invalid tz, so return invalid data - return invalidData(); + // Otherwise, if we can find a valid tran, then use its rule: + auto last = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(), + [forMSecsSinceEpoch] (const QTzTransitionTime &at) { + return at.atMSecsSinceEpoch <= forMSecsSinceEpoch; + }); + if (last > m_tranTimes.cbegin()) + --last; + Data data = dataForTzTransition(*last); + data.atMSecsSinceEpoch = forMSecsSinceEpoch; + return data; } bool QTzTimeZonePrivate::hasTransitions() const @@ -992,21 +993,20 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::nextTransition(qint64 afterMSecsSince QVector posixTrans = calculatePosixTransitions(m_posixRule, year - 1, year + 1, m_tranTimes.last().atMSecsSinceEpoch); - for (int i = 0; i < posixTrans.size(); ++i) { - if (posixTrans.at(i).atMSecsSinceEpoch > afterMSecsSinceEpoch) - return posixTrans.at(i); - } - } + auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(), + [afterMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) { + return at.atMSecsSinceEpoch <= afterMSecsSinceEpoch; + }); - // Otherwise if we can find a valid tran then use its rule - for (int i = 0; i < m_tranTimes.size(); ++i) { - if (m_tranTimes.at(i).atMSecsSinceEpoch > afterMSecsSinceEpoch) { - return dataForTzTransition(m_tranTimes.at(i)); - } + return it == posixTrans.cend() ? invalidData() : *it; } - // Otherwise we have no rule, or there is no next transition, so return invalid data - return invalidData(); + // Otherwise, if we can find a valid tran, use its rule: + auto last = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(), + [afterMSecsSinceEpoch] (const QTzTransitionTime &at) { + return at.atMSecsSinceEpoch <= afterMSecsSinceEpoch; + }); + return last != m_tranTimes.cend() ? dataForTzTransition(*last) : invalidData(); } QTimeZonePrivate::Data QTzTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const @@ -1018,21 +1018,20 @@ QTimeZonePrivate::Data QTzTimeZonePrivate::previousTransition(qint64 beforeMSecs QVector posixTrans = calculatePosixTransitions(m_posixRule, year - 1, year + 1, m_tranTimes.last().atMSecsSinceEpoch); - for (int i = posixTrans.size() - 1; i >= 0; --i) { - if (posixTrans.at(i).atMSecsSinceEpoch < beforeMSecsSinceEpoch) - return posixTrans.at(i); - } + auto it = std::partition_point(posixTrans.cbegin(), posixTrans.cend(), + [beforeMSecsSinceEpoch] (const QTimeZonePrivate::Data &at) { + return at.atMSecsSinceEpoch < beforeMSecsSinceEpoch; + }); + Q_ASSERT(it > posixTrans.cbegin()); + return *--it; } // Otherwise if we can find a valid tran then use its rule - for (int i = m_tranTimes.size() - 1; i >= 0; --i) { - if (m_tranTimes.at(i).atMSecsSinceEpoch < beforeMSecsSinceEpoch) { - return dataForTzTransition(m_tranTimes.at(i)); - } - } - - // Otherwise we have no rule, so return invalid data - return invalidData(); + auto last = std::partition_point(m_tranTimes.cbegin(), m_tranTimes.cend(), + [beforeMSecsSinceEpoch] (const QTzTransitionTime &at) { + return at.atMSecsSinceEpoch < beforeMSecsSinceEpoch; + }); + return last > m_tranTimes.cbegin() ? dataForTzTransition(*--last) : invalidData(); } // TODO Could cache the value and monitor the required files for any changes -- cgit v1.2.3 From b9923b30f082e5f3ccfd4b0f10c4386727b8a53f Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Wed, 6 Jun 2018 17:16:30 +0200 Subject: tst_QWidget: Explain why some tests fail on Wayland Task-number: QTBUG-66849 Change-Id: Ie6295bd402f6bc960c16f1e4b3b5a786017453e1 Reviewed-by: Richard Moe Gustavsen --- tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index e30429b7e7..ae50b32164 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -2321,6 +2321,12 @@ void tst_QWidget::resizeEvent() void tst_QWidget::showMinimized() { + if (m_platform == QStringLiteral("wayland")) { + QSKIP("Wayland: Neither xdg_shell, wl_shell or ivi_application support " + "letting a client know whether it's minimized. So on these shells " + "Qt Wayland will always report that it's unmimized."); + } + QWidget plain; plain.move(100, 100); plain.resize(200, 200); @@ -9165,7 +9171,7 @@ void tst_QWidget::syntheticEnterLeave() void tst_QWidget::taskQTBUG_4055_sendSyntheticEnterLeave() { if (m_platform == QStringLiteral("wayland")) - QSKIP("Wayland: This fails. Figure out why."); + QSKIP("Wayland: Clients can't set cursor position on wayland."); class SELParent : public QWidget { public: -- cgit v1.2.3 From 6553921dd537e416da2f4d1441ab6d63059cda60 Mon Sep 17 00:00:00 2001 From: Rolf Eike Beer Date: Wed, 18 Jul 2018 11:07:52 +0200 Subject: QWindowsStyle: respect rectangle when drawing PE_IndicatorViewItemCheck The hardcoded value is based on the values set in qcommonstyle.cpp, but in case this is changed using a proxy style the actual values are not respected. They would even be wrong if nothing is changed but QStyleHelper::dpiScaled(13.) does not return 13. Change-Id: Ib451d07800b3b4e8cafd1f4fef84cd9bf02f9bba Reviewed-by: Andre de la Rocha Reviewed-by: Friedemann Kleint --- src/widgets/styles/qwindowsstyle.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp index 4b9d0b5adc..d4ccd0931e 100644 --- a/src/widgets/styles/qwindowsstyle.cpp +++ b/src/widgets/styles/qwindowsstyle.cpp @@ -840,7 +840,7 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, : opt->palette.text().color()); if (opt->state & State_NoChange) p->setBrush(opt->palette.brush(QPalette::Button)); - p->drawRect(opt->rect.x() + 1, opt->rect.y() + 1, 11, 11); + p->drawRect(opt->rect.x() + 1, opt->rect.y() + 1, opt->rect.width() - 2, opt->rect.height() - 2); } #endif // QT_CONFIG(itemviews) if (!(opt->state & State_Off)) { -- cgit v1.2.3