diff options
Diffstat (limited to 'src/corelib')
79 files changed, 3494 insertions, 1067 deletions
diff --git a/src/corelib/animation/qpropertyanimation.cpp b/src/corelib/animation/qpropertyanimation.cpp index 28c03553c5..271be248ec 100644 --- a/src/corelib/animation/qpropertyanimation.cpp +++ b/src/corelib/animation/qpropertyanimation.cpp @@ -303,6 +303,6 @@ void QPropertyAnimation::updateState(QAbstractAnimation::State newState, } } -#include "moc_qpropertyanimation.cpp" - QT_END_NAMESPACE + +#include "moc_qpropertyanimation.cpp" diff --git a/src/corelib/configure.json b/src/corelib/configure.json index 183eb3a13e..f18e79f1aa 100644 --- a/src/corelib/configure.json +++ b/src/corelib/configure.json @@ -793,6 +793,20 @@ "condition": "features.proxymodel", "output": [ "publicFeature", "feature" ] }, + "transposeproxymodel": { + "label": "QTransposeProxyModel", + "purpose": "Provides a proxy to swap rows and columns of a model.", + "section": "ItemViews", + "condition": "features.proxymodel", + "output": [ "publicFeature", "feature" ] + }, + "concatenatetablesproxymodel": { + "label": "QConcatenateTablesProxyModel", + "purpose": "Supports concatenating source models.", + "section": "ItemViews", + "condition": "features.proxymodel", + "output": [ "publicFeature", "feature" ] + }, "stringlistmodel": { "label": "QStringListModel", "purpose": "Provides a model that supplies strings to views.", diff --git a/src/corelib/doc/snippets/resource-system/mainwindow.cpp b/src/corelib/doc/snippets/resource-system/mainwindow.cpp index 6fcf52e588..0ab0034d5e 100644 --- a/src/corelib/doc/snippets/resource-system/mainwindow.cpp +++ b/src/corelib/doc/snippets/resource-system/mainwindow.cpp @@ -338,11 +338,11 @@ void MainWindow::loadFile(const QString &fileName) QTextStream in(&file); #ifndef QT_NO_CURSOR - QApplication::setOverrideCursor(Qt::WaitCursor); + QGuiApplication::setOverrideCursor(Qt::WaitCursor); #endif textEdit->setPlainText(in.readAll()); #ifndef QT_NO_CURSOR - QApplication::restoreOverrideCursor(); + QGuiApplication::restoreOverrideCursor(); #endif setCurrentFile(fileName); @@ -365,11 +365,11 @@ bool MainWindow::saveFile(const QString &fileName) QTextStream out(&file); #ifndef QT_NO_CURSOR - QApplication::setOverrideCursor(Qt::WaitCursor); + QGuiApplication::setOverrideCursor(Qt::WaitCursor); #endif out << textEdit->toPlainText(); #ifndef QT_NO_CURSOR - QApplication::restoreOverrideCursor(); + QGuiApplication::restoreOverrideCursor(); #endif setCurrentFile(fileName); diff --git a/src/corelib/global/qfloat16.h b/src/corelib/global/qfloat16.h index a8befd7adb..766ab319a4 100644 --- a/src/corelib/global/qfloat16.h +++ b/src/corelib/global/qfloat16.h @@ -67,11 +67,9 @@ QT_BEGIN_NAMESPACE class qfloat16 { public: -#ifndef Q_QDOC Q_DECL_CONSTEXPR inline qfloat16() Q_DECL_NOTHROW : b16(0) { } inline qfloat16(float f) Q_DECL_NOTHROW; inline operator float() const Q_DECL_NOTHROW; -#endif private: quint16 b16; diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 5c1665fa00..14fb4e77da 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -2142,11 +2142,20 @@ struct QUnixOSVersion static QString unquote(const char *begin, const char *end) { + // man os-release says: + // Variable assignment values must be enclosed in double + // or single quotes if they include spaces, semicolons or + // other special characters outside of A–Z, a–z, 0–9. Shell + // special characters ("$", quotes, backslash, backtick) + // must be escaped with backslashes, following shell style. + // All strings should be in UTF-8 format, and non-printable + // characters should not be used. It is not supported to + // concatenate multiple individually quoted strings. if (*begin == '"') { Q_ASSERT(end[-1] == '"'); - return QString::fromLatin1(begin + 1, end - begin - 2); + return QString::fromUtf8(begin + 1, end - begin - 2); } - return QString::fromLatin1(begin, end - begin); + return QString::fromUtf8(begin, end - begin); } static QByteArray getEtcFileContent(const char *filename) { @@ -3243,6 +3252,34 @@ void *qMemSet(void *dest, int c, size_t n) { return memset(dest, c, n); } // add thread-safety for the Qt wrappers. static QBasicMutex environmentMutex; +/* + Wraps tzset(), which accesses the environment, so should only be called while + we hold the lock on the environment mutex. +*/ +void qTzSet() +{ + QMutexLocker locker(&environmentMutex); +#if defined(Q_OS_WIN) + _tzset(); +#else + tzset(); +#endif // Q_OS_WIN +} + +/* + Wrap mktime(), which is specified to behave as if it called tzset(), hence + shares its implicit environment-dependence. +*/ +time_t qMkTime(struct tm *when) +{ + QMutexLocker locker(&environmentMutex); + return mktime(when); +} + +// Also specified to behave as if they call tzset(): +// localtime() -- but not localtime_r(), which we use when threaded +// strftime() -- not used (except in tests) + /*! \relates <QtGlobal> \threadsafe diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index b608489576..8680742c94 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -591,11 +591,11 @@ Q_DECL_CONSTEXPR inline qint64 qRound64(float d) { return d >= 0.0f ? qint64(d + 0.5f) : qint64(d - float(qint64(d-1)) + 0.5f) + qint64(d-1); } template <typename T> -Q_DECL_CONSTEXPR inline const T &qMin(const T &a, const T &b) { return (a < b) ? a : b; } +constexpr inline const T &qMin(const T &a, const T &b) { return (a < b) ? a : b; } template <typename T> -Q_DECL_CONSTEXPR inline const T &qMax(const T &a, const T &b) { return (a < b) ? b : a; } +constexpr inline const T &qMax(const T &a, const T &b) { return (a < b) ? b : a; } template <typename T> -Q_DECL_CONSTEXPR inline const T &qBound(const T &min, const T &val, const T &max) +constexpr inline const T &qBound(const T &min, const T &val, const T &max) { return qMax(min, qMin(max, val)); } #ifndef Q_FORWARD_DECLARE_OBJC_CLASS @@ -1005,6 +1005,15 @@ QForeachContainer<typename std::decay<T>::type> qMakeForeachContainer(T &&t) } } + +#if __cplusplus >= 201703L +// Use C++17 if statement with initializer. User's code ends up in a else so +// scoping of different ifs is not broken +#define Q_FOREACH(variable, container) \ +for (auto _container_ = QtPrivate::qMakeForeachContainer(container); \ + _container_.i != _container_.e; ++_container_.i) \ + if (variable = *_container_.i; false) {} else +#else // Explanation of the control word: // - it's initialized to 1 // - that means both the inner and outer loops start @@ -1019,7 +1028,7 @@ for (auto _container_ = QtPrivate::qMakeForeachContainer(container); \ _container_.control && _container_.i != _container_.e; \ ++_container_.i, _container_.control ^= 1) \ for (variable = *_container_.i; _container_.control; _container_.control = 0) - +#endif #endif // QT_NO_FOREACH #define Q_FOREVER for(;;) @@ -1186,9 +1195,6 @@ namespace QtPrivate { //like std::enable_if template <bool B, typename T = void> struct QEnableIf; template <typename T> struct QEnableIf<true, T> { typedef T Type; }; - -template <bool B, typename T, typename F> struct QConditional { typedef T Type; }; -template <typename T, typename F> struct QConditional<false, T, F> { typedef F Type; }; } QT_END_NAMESPACE diff --git a/src/corelib/global/qglobal_p.h b/src/corelib/global/qglobal_p.h index 0f092e9006..d52f6268e4 100644 --- a/src/corelib/global/qglobal_p.h +++ b/src/corelib/global/qglobal_p.h @@ -61,6 +61,16 @@ #endif #if defined(__cplusplus) +#include <time.h> + +QT_BEGIN_NAMESPACE + +// These behave as if they consult the environment, so need to share its locking: +Q_CORE_EXPORT void qTzSet(); +Q_CORE_EXPORT time_t qMkTime(struct tm *when); + +QT_END_NAMESPACE + #if !QT_HAS_BUILTIN(__builtin_available) #include <initializer_list> #include <QtCore/qoperatingsystemversion.h> diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index dec2c44637..41b94bf15a 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -516,7 +516,7 @@ public: AA_SetPalette = 19, AA_EnableHighDpiScaling = 20, AA_DisableHighDpiScaling = 21, - AA_UseStyleSheetPropagationInWidgetStyles = 22, // ### Qt 6: remove me + AA_UseStyleSheetPropagationInWidgetStyles = 22, AA_DontUseNativeDialogs = 23, AA_SynthesizeMouseForUnhandledTabletEvents = 24, AA_CompressHighFrequencyEvents = 25, @@ -1504,9 +1504,11 @@ public: // Metadata FontRole = 6, TextAlignmentRole = 7, +#if QT_DEPRECATED_SINCE(5, 13) BackgroundColorRole = 8, - BackgroundRole = 8, TextColorRole = 9, +#endif + BackgroundRole = 8, ForegroundRole = 9, CheckStateRole = 10, // Accessibility diff --git a/src/corelib/io/qbuffer.cpp b/src/corelib/io/qbuffer.cpp index e0b9c41323..7b3fa2ccad 100644 --- a/src/corelib/io/qbuffer.cpp +++ b/src/corelib/io/qbuffer.cpp @@ -60,8 +60,8 @@ public: QByteArray *buf; QByteArray defaultBuf; - virtual qint64 peek(char *data, qint64 maxSize) override; - virtual QByteArray peek(qint64 maxSize) override; + qint64 peek(char *data, qint64 maxSize) override; + QByteArray peek(qint64 maxSize) override; #ifndef QT_NO_QOBJECT // private slots diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index 75fd0f8e0a..0998d7ffd1 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -1040,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{QRegularExpression wildcard matching}.) + \c{*} and \c{?} wildcards. (See \l{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++ @@ -2120,7 +2120,7 @@ QString QDir::rootPath() patterns in the list of \a filters; otherwise returns \c false. The matching is case insensitive. - \sa {QRegularExpression Wildcard matching}, QRegularExpression::wildcardToRegularExpression(), + \sa {Wildcard matching}, QRegularExpression::wildcardToRegularExpression(), entryList(), entryInfoList() */ bool QDir::match(const QStringList &filters, const QString &fileName) @@ -2143,7 +2143,7 @@ bool QDir::match(const QStringList &filters, const QString &fileName) contain multiple patterns separated by spaces or semicolons. The matching is case insensitive. - \sa {QRegularExpression wildcard matching}, QRegularExpression::wildcardToRegularExpression, + \sa {Wildcard matching}, QRegularExpression::wildcardToRegularExpression, entryList(), entryInfoList() */ bool QDir::match(const QString &filter, const QString &fileName) diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index 3166fa1b83..d3f846bc1d 100644 --- a/src/corelib/io/qfile.cpp +++ b/src/corelib/io/qfile.cpp @@ -808,7 +808,7 @@ QFile::copy(const QString &newName) if (error) { out.close(); close(); - d->setError(QFile::CopyError, tr("Cannot open for output")); + d->setError(QFile::CopyError, tr("Cannot open for output: %1").arg(out.errorString())); } else { if (!d->engine()->cloneTo(out.d_func()->engine())) { char block[4096]; diff --git a/src/corelib/io/qfiledevice.h b/src/corelib/io/qfiledevice.h index af41bec2f6..2d524193c5 100644 --- a/src/corelib/io/qfiledevice.h +++ b/src/corelib/io/qfiledevice.h @@ -100,7 +100,7 @@ public: FileError error() const; void unsetError(); - virtual void close() override; + void close() override; bool isSequential() const override; diff --git a/src/corelib/io/qnoncontiguousbytedevice_p.h b/src/corelib/io/qnoncontiguousbytedevice_p.h index ebed1120db..bbc4ea5ae2 100644 --- a/src/corelib/io/qnoncontiguousbytedevice_p.h +++ b/src/corelib/io/qnoncontiguousbytedevice_p.h @@ -179,13 +179,13 @@ class QByteDeviceWrappingIoDevice : public QIODevice public: QByteDeviceWrappingIoDevice (QNonContiguousByteDevice *bd); ~QByteDeviceWrappingIoDevice (); - virtual bool isSequential () const override; - virtual bool atEnd () const override; - virtual bool reset () override; - virtual qint64 size () const override; + bool isSequential() const override; + bool atEnd() const override; + bool reset() override; + qint64 size() const override; protected: - virtual qint64 readData ( char * data, qint64 maxSize ) override; - virtual qint64 writeData ( const char * data, qint64 maxSize ) override; + qint64 readData(char *data, qint64 maxSize) override; + qint64 writeData(const char *data, qint64 maxSize) override; QNonContiguousByteDevice *byteDevice; }; diff --git a/src/corelib/io/qprocess.h b/src/corelib/io/qprocess.h index 474fc87de8..5e022e3a52 100644 --- a/src/corelib/io/qprocess.h +++ b/src/corelib/io/qprocess.h @@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE class QProcessPrivate; -#if !defined(Q_OS_WIN) || defined(Q_CLANG_QDOC) +#if !defined(Q_OS_WIN) typedef qint64 Q_PID; #else QT_END_NAMESPACE diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp index b85bca8590..8a0d2e0200 100644 --- a/src/corelib/io/qresource.cpp +++ b/src/corelib/io/qresource.cpp @@ -906,8 +906,8 @@ public: inline QDynamicBufferResourceRoot(const QString &_root) : root(_root), buffer(0) { } inline ~QDynamicBufferResourceRoot() { } inline const uchar *mappingBuffer() const { return buffer; } - virtual QString mappingRoot() const override { return root; } - virtual ResourceRootType type() const override { return Resource_Buffer; } + QString mappingRoot() const override { return root; } + ResourceRootType type() const override { return Resource_Buffer; } // size == -1 means "unknown" bool registerSelf(const uchar *b, int size) @@ -989,7 +989,7 @@ public: } } QString mappingFile() const { return fileName; } - virtual ResourceRootType type() const override { return Resource_File; } + ResourceRootType type() const override { return Resource_File; } bool registerSelf(const QString &f) { bool fromMM = false; diff --git a/src/corelib/io/qresource_p.h b/src/corelib/io/qresource_p.h index dcfe46704c..7451de8809 100644 --- a/src/corelib/io/qresource_p.h +++ b/src/corelib/io/qresource_p.h @@ -64,49 +64,49 @@ public: explicit QResourceFileEngine(const QString &path); ~QResourceFileEngine(); - virtual void setFileName(const QString &file) override; + void setFileName(const QString &file) override; - virtual bool open(QIODevice::OpenMode flags) override ; - virtual bool close() override; - virtual bool flush() override; - virtual qint64 size() const override; - virtual qint64 pos() const override; + bool open(QIODevice::OpenMode flags) override; + bool close() override; + bool flush() override; + qint64 size() const override; + qint64 pos() const override; virtual bool atEnd() const; - virtual bool seek(qint64) override; - virtual qint64 read(char *data, qint64 maxlen) override; - virtual qint64 write(const char *data, qint64 len) override; + bool seek(qint64) override; + qint64 read(char *data, qint64 maxlen) override; + qint64 write(const char *data, qint64 len) override; - virtual bool remove() override; - virtual bool copy(const QString &newName) override; - virtual bool rename(const QString &newName) override; - virtual bool link(const QString &newName) override; + bool remove() override; + bool copy(const QString &newName) override; + bool rename(const QString &newName) override; + bool link(const QString &newName) override; - virtual bool isSequential() const override; + bool isSequential() const override; - virtual bool isRelativePath() const override; + bool isRelativePath() const override; - virtual bool mkdir(const QString &dirName, bool createParentDirectories) const override; - virtual bool rmdir(const QString &dirName, bool recurseParentDirectories) const override; + bool mkdir(const QString &dirName, bool createParentDirectories) const override; + bool rmdir(const QString &dirName, bool recurseParentDirectories) const override; - virtual bool setSize(qint64 size) override; + bool setSize(qint64 size) override; - virtual QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const override; + QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const override; - virtual bool caseSensitive() const override; + bool caseSensitive() const override; - virtual FileFlags fileFlags(FileFlags type) const override; + FileFlags fileFlags(FileFlags type) const override; - virtual bool setPermissions(uint perms) override; + bool setPermissions(uint perms) override; - virtual QString fileName(QAbstractFileEngine::FileName file) const override; + QString fileName(QAbstractFileEngine::FileName file) const override; - virtual uint ownerId(FileOwner) const override; - virtual QString owner(FileOwner) const override; + uint ownerId(FileOwner) const override; + QString owner(FileOwner) const override; - virtual QDateTime fileTime(FileTime time) const override; + QDateTime fileTime(FileTime time) const override; - virtual Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames) override; - virtual Iterator *endEntryList() override; + Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames) override; + Iterator *endEntryList() override; bool extension(Extension extension, const ExtensionOption *option = 0, ExtensionReturn *output = 0) override; bool supportsExtension(Extension extension) const override; diff --git a/src/corelib/itemmodels/itemmodels.pri b/src/corelib/itemmodels/itemmodels.pri index 068a8c4b3a..ebeac6e211 100644 --- a/src/corelib/itemmodels/itemmodels.pri +++ b/src/corelib/itemmodels/itemmodels.pri @@ -20,6 +20,14 @@ qtConfig(proxymodel) { SOURCES += \ itemmodels/qabstractproxymodel.cpp + qtConfig(concatenatetablesproxymodel) { + HEADERS += \ + itemmodels/qconcatenatetablesproxymodel.h + + SOURCES += \ + itemmodels/qconcatenatetablesproxymodel.cpp + } + qtConfig(identityproxymodel) { HEADERS += \ itemmodels/qidentityproxymodel.h @@ -35,6 +43,15 @@ qtConfig(proxymodel) { SOURCES += \ itemmodels/qsortfilterproxymodel.cpp } + + qtConfig(transposeproxymodel) { + HEADERS += \ + itemmodels/qtransposeproxymodel.h \ + itemmodels/qtransposeproxymodel_p.h + + SOURCES += \ + itemmodels/qtransposeproxymodel.cpp + } } qtConfig(stringlistmodel) { diff --git a/src/corelib/itemmodels/qabstractitemmodel.h b/src/corelib/itemmodels/qabstractitemmodel.h index bec71b0606..c34876d1d6 100644 --- a/src/corelib/itemmodels/qabstractitemmodel.h +++ b/src/corelib/itemmodels/qabstractitemmodel.h @@ -163,6 +163,7 @@ typedef QList<QModelIndex> QModelIndexList; class QMimeData; class QAbstractItemModelPrivate; +class QTransposeProxyModelPrivate; template <class Key, class T> class QMap; @@ -173,6 +174,7 @@ class Q_CORE_EXPORT QAbstractItemModel : public QObject friend class QPersistentModelIndexData; friend class QAbstractItemViewPrivate; friend class QIdentityProxyModel; + friend class QTransposeProxyModelPrivate; public: explicit QAbstractItemModel(QObject *parent = nullptr); @@ -300,7 +302,9 @@ public Q_SLOTS: virtual void revert(); protected Q_SLOTS: - // Qt 6: Make virtual +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + virtual +#endif void resetInternalData(); protected: diff --git a/src/corelib/itemmodels/qabstractproxymodel.cpp b/src/corelib/itemmodels/qabstractproxymodel.cpp index b7c49a53e4..118e808a3c 100644 --- a/src/corelib/itemmodels/qabstractproxymodel.cpp +++ b/src/corelib/itemmodels/qabstractproxymodel.cpp @@ -313,6 +313,18 @@ bool QAbstractProxyModel::setHeaderData(int section, Qt::Orientation orientation return d->model->setHeaderData(sourceSection, orientation, value, role); } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +/*! + \reimp + \since 6.0 + */ +bool QAbstractProxyModel::clearItemData(const QModelIndex &index) +{ + Q_D(QAbstractProxyModel); + return d->model->clearItemData(mapToSource(index)); +} +#endif + /*! \reimp */ diff --git a/src/corelib/itemmodels/qabstractproxymodel.h b/src/corelib/itemmodels/qabstractproxymodel.h index c4e5d67908..6d9daee75a 100644 --- a/src/corelib/itemmodels/qabstractproxymodel.h +++ b/src/corelib/itemmodels/qabstractproxymodel.h @@ -78,6 +78,9 @@ public: bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; bool setItemData(const QModelIndex& index, const QMap<int, QVariant> &roles) override; bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole) override; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + bool clearItemData(const QModelIndex &index) override; +#endif QModelIndex buddy(const QModelIndex &index) const override; bool canFetchMore(const QModelIndex &parent) const override; diff --git a/src/corelib/itemmodels/qconcatenatetablesproxymodel.cpp b/src/corelib/itemmodels/qconcatenatetablesproxymodel.cpp new file mode 100644 index 0000000000..bbfe2dce16 --- /dev/null +++ b/src/corelib/itemmodels/qconcatenatetablesproxymodel.cpp @@ -0,0 +1,750 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com> +** 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$ +** +****************************************************************************/ + +#include "qconcatenatetablesproxymodel.h" +#include <private/qabstractitemmodel_p.h> +#include "qsize.h" +#include "qdebug.h" + +QT_BEGIN_NAMESPACE + +class QConcatenateTablesProxyModelPrivate : public QAbstractItemModelPrivate +{ + Q_DECLARE_PUBLIC(QConcatenateTablesProxyModel); + +public: + QConcatenateTablesProxyModelPrivate(); + + int computeRowsPrior(const QAbstractItemModel *sourceModel) const; + + struct SourceModelForRowResult + { + SourceModelForRowResult() : sourceModel(Q_NULLPTR), sourceRow(-1) {} + QAbstractItemModel *sourceModel; + int sourceRow; + }; + SourceModelForRowResult sourceModelForRow(int row) const; + + void _q_slotRowsAboutToBeInserted(const QModelIndex &, int start, int end); + void _q_slotRowsInserted(const QModelIndex &, int start, int end); + void _q_slotRowsAboutToBeRemoved(const QModelIndex &, int start, int end); + void _q_slotRowsRemoved(const QModelIndex &, int start, int end); + void _q_slotColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end); + void _q_slotColumnsInserted(const QModelIndex &parent, int, int); + void _q_slotColumnsAboutToBeRemoved(const QModelIndex &parent, int start, int end); + void _q_slotColumnsRemoved(const QModelIndex &parent, int, int); + void _q_slotDataChanged(const QModelIndex &from, const QModelIndex &to, const QVector<int> &roles); + void _q_slotSourceLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint); + void _q_slotSourceLayoutChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint); + void _q_slotModelAboutToBeReset(); + void _q_slotModelReset(); + int columnCountAfterChange(const QAbstractItemModel *model, int newCount) const; + int calculatedColumnCount() const; + void updateColumnCount(); + bool mapDropCoordinatesToSource(int row, int column, const QModelIndex &parent, + int *sourceRow, int *sourceColumn, QModelIndex *sourceParent, QAbstractItemModel **sourceModel) const; + + QVector<QAbstractItemModel *> m_models; + int m_rowCount; // have to maintain it here since we can't compute during model destruction + int m_columnCount; + + // for columns{AboutToBe,}{Inserted,Removed} + int m_newColumnCount; + + // for layoutAboutToBeChanged/layoutChanged + QVector<QPersistentModelIndex> layoutChangePersistentIndexes; + QVector<QModelIndex> layoutChangeProxyIndexes; +}; + +QConcatenateTablesProxyModelPrivate::QConcatenateTablesProxyModelPrivate() + : m_rowCount(0), + m_columnCount(0), + m_newColumnCount(0) +{ +} + +/*! + \since 5.13 + \class QConcatenateTablesProxyModel + \inmodule QtCore + \brief The QConcatenateTablesProxyModel class proxies multiple source models, concatenating their rows + + \ingroup model-view + + QConcatenateTablesProxyModel takes multiple source models and concatenates their rows. + + In other words, the proxy will have all rows of the first source model, + followed by all rows of the second source model, and so on. + + If the source models don't have the same number of columns, the proxy will only + have as many columns as the source model with the smallest number of columns. + Additional columns in other source models will simply be ignored. + + Source models can be added and removed at runtime, and the column count is adjusted accordingly. + + This proxy does not inherit from QAbstractProxyModel because it uses multiple source + models, rather than a single one. + + Only flat models (lists and tables) are supported, tree models are not. + + \sa QAbstractProxyModel, {Model/View Programming}, QIdentityProxyModel, QAbstractItemModel + */ + + +/*! + Constructs a concatenate-rows proxy model with the given \a parent. +*/ +QConcatenateTablesProxyModel::QConcatenateTablesProxyModel(QObject *parent) + : QAbstractItemModel(*new QConcatenateTablesProxyModelPrivate, parent) +{ +} + +/*! + Destroys this proxy model. +*/ +QConcatenateTablesProxyModel::~QConcatenateTablesProxyModel() +{ +} + +/*! + Returns the proxy index for a given \a sourceIndex, which can be from any of the source models. +*/ +QModelIndex QConcatenateTablesProxyModel::mapFromSource(const QModelIndex &sourceIndex) const +{ + Q_D(const QConcatenateTablesProxyModel); + if (!sourceIndex.isValid()) + return QModelIndex(); + const QAbstractItemModel *sourceModel = sourceIndex.model(); + if (!d->m_models.contains(const_cast<QAbstractItemModel *>(sourceModel))) { + qWarning("QConcatenateTablesProxyModel: index from wrong model passed to mapFromSource"); + Q_ASSERT(!"QConcatenateTablesProxyModel: index from wrong model passed to mapFromSource"); + return QModelIndex(); + } + if (sourceIndex.column() >= d->m_columnCount) + return QModelIndex(); + int rowsPrior = d_func()->computeRowsPrior(sourceModel); + return createIndex(rowsPrior + sourceIndex.row(), sourceIndex.column(), sourceIndex.internalPointer()); +} + +/*! + Returns the source index for a given proxy index. +*/ +QModelIndex QConcatenateTablesProxyModel::mapToSource(const QModelIndex &proxyIndex) const +{ + Q_D(const QConcatenateTablesProxyModel); + Q_ASSERT(checkIndex(proxyIndex)); + if (!proxyIndex.isValid()) + return QModelIndex(); + if (proxyIndex.model() != this) { + qWarning("QConcatenateTablesProxyModel: index from wrong model passed to mapToSource"); + Q_ASSERT(!"QConcatenateTablesProxyModel: index from wrong model passed to mapToSource"); + return QModelIndex(); + } + const int row = proxyIndex.row(); + const auto result = d->sourceModelForRow(row); + if (!result.sourceModel) + return QModelIndex(); + return result.sourceModel->index(result.sourceRow, proxyIndex.column()); +} + +/*! + \reimp +*/ +QVariant QConcatenateTablesProxyModel::data(const QModelIndex &index, int role) const +{ + const QModelIndex sourceIndex = mapToSource(index); + Q_ASSERT(checkIndex(index, CheckIndexOption::IndexIsValid)); + if (!sourceIndex.isValid()) + return QVariant(); + return sourceIndex.data(role); +} + +/*! + \reimp +*/ +bool QConcatenateTablesProxyModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + Q_ASSERT(checkIndex(index, CheckIndexOption::IndexIsValid)); + const QModelIndex sourceIndex = mapToSource(index); + Q_ASSERT(sourceIndex.isValid()); + const auto sourceModel = const_cast<QAbstractItemModel *>(sourceIndex.model()); + return sourceModel->setData(sourceIndex, value, role); +} + +/*! + \reimp +*/ +QMap<int, QVariant> QConcatenateTablesProxyModel::itemData(const QModelIndex &proxyIndex) const +{ + Q_ASSERT(checkIndex(proxyIndex)); + const QModelIndex sourceIndex = mapToSource(proxyIndex); + Q_ASSERT(sourceIndex.isValid()); + return sourceIndex.model()->itemData(sourceIndex); +} + +/*! + \reimp +*/ +bool QConcatenateTablesProxyModel::setItemData(const QModelIndex &proxyIndex, const QMap<int, QVariant> &roles) +{ + Q_ASSERT(checkIndex(proxyIndex)); + const QModelIndex sourceIndex = mapToSource(proxyIndex); + Q_ASSERT(sourceIndex.isValid()); + const auto sourceModel = const_cast<QAbstractItemModel *>(sourceIndex.model()); + return sourceModel->setItemData(sourceIndex, roles); +} + +/*! + Returns the flags for the given index. + If the index is valid, the flags come from the source model for this index. + If the index is invalid (as used to determine if dropping onto an empty area + in the view is allowed, for instance), the flags from the first model are returned. +*/ +Qt::ItemFlags QConcatenateTablesProxyModel::flags(const QModelIndex &index) const +{ + Q_D(const QConcatenateTablesProxyModel); + if (d->m_models.isEmpty()) + return Qt::NoItemFlags; + Q_ASSERT(checkIndex(index)); + if (!index.isValid()) + return d->m_models.at(0)->flags(index); + const QModelIndex sourceIndex = mapToSource(index); + Q_ASSERT(sourceIndex.isValid()); + return sourceIndex.model()->flags(sourceIndex); +} + +/*! + This method returns the horizontal header data for the first source model, + and the vertical header data for the source model corresponding to each row. + \reimp +*/ +QVariant QConcatenateTablesProxyModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + Q_D(const QConcatenateTablesProxyModel); + if (d->m_models.isEmpty()) + return QVariant(); + switch (orientation) { + case Qt::Horizontal: + return d->m_models.at(0)->headerData(section, orientation, role); + case Qt::Vertical: { + const auto result = d->sourceModelForRow(section); + Q_ASSERT(result.sourceModel); + return result.sourceModel->headerData(result.sourceRow, orientation, role); + } + } + return QVariant(); +} + +/*! + This method returns the column count of the source model with the smallest number of columns. + \reimp +*/ +int QConcatenateTablesProxyModel::columnCount(const QModelIndex &parent) const +{ + Q_D(const QConcatenateTablesProxyModel); + if (parent.isValid()) + return 0; // flat model + return d->m_columnCount; +} + +/*! + \reimp +*/ +QModelIndex QConcatenateTablesProxyModel::index(int row, int column, const QModelIndex &parent) const +{ + Q_D(const QConcatenateTablesProxyModel); + Q_ASSERT(hasIndex(row, column, parent)); + if (!hasIndex(row, column, parent)) + return QModelIndex(); + Q_ASSERT(checkIndex(parent, QAbstractItemModel::CheckIndexOption::ParentIsInvalid)); // flat model + const auto result = d->sourceModelForRow(row); + Q_ASSERT(result.sourceModel); + return mapFromSource(result.sourceModel->index(result.sourceRow, column)); +} + +/*! + \reimp +*/ +QModelIndex QConcatenateTablesProxyModel::parent(const QModelIndex &index) const +{ + Q_UNUSED(index); + return QModelIndex(); // flat model, no hierarchy +} + +/*! + \reimp +*/ +int QConcatenateTablesProxyModel::rowCount(const QModelIndex &parent) const +{ + Q_D(const QConcatenateTablesProxyModel); + Q_ASSERT(checkIndex(parent, QAbstractItemModel::CheckIndexOption::ParentIsInvalid)); // flat model + Q_UNUSED(parent); + return d->m_rowCount; +} + +/*! + This method returns the mime types for the first source model. + \reimp +*/ +QStringList QConcatenateTablesProxyModel::mimeTypes() const +{ + Q_D(const QConcatenateTablesProxyModel); + if (d->m_models.isEmpty()) + return QStringList(); + return d->m_models.at(0)->mimeTypes(); +} + +/*! + The call is forwarded to the source model of the first index in the list of \a indexes. + + Important: please note that this proxy only supports dragging a single row. + It will assert if called with indexes from multiple rows, because dragging rows that + might come from different source models cannot be implemented generically by this proxy model. + Each piece of data in the QMimeData needs to be merged, which is data-type-specific. + Reimplement this method in a subclass if you want to support dragging multiple rows. + + \reimp +*/ +QMimeData *QConcatenateTablesProxyModel::mimeData(const QModelIndexList &indexes) const +{ + Q_D(const QConcatenateTablesProxyModel); + if (indexes.isEmpty()) + return nullptr; + const QModelIndex firstIndex = indexes.first(); + Q_ASSERT(checkIndex(firstIndex, CheckIndexOption::IndexIsValid)); + const auto result = d->sourceModelForRow(firstIndex.row()); + QModelIndexList sourceIndexes; + sourceIndexes.reserve(indexes.count()); + for (const QModelIndex &index : indexes) { + const QModelIndex sourceIndex = mapToSource(index); + Q_ASSERT(sourceIndex.model() == result.sourceModel); // see documentation above + sourceIndexes.append(sourceIndex); + } + return result.sourceModel->mimeData(sourceIndexes); +} + + +bool QConcatenateTablesProxyModelPrivate::mapDropCoordinatesToSource(int row, int column, const QModelIndex &parent, + int *sourceRow, int *sourceColumn, QModelIndex *sourceParent, QAbstractItemModel **sourceModel) const +{ + Q_Q(const QConcatenateTablesProxyModel); + *sourceColumn = column; + if (!parent.isValid()) { + // Drop after the last item + if (row == -1 || row == m_rowCount) { + *sourceRow = -1; + *sourceModel = m_models.constLast(); + return true; + } + // Drop between toplevel items + const auto result = sourceModelForRow(row); + Q_ASSERT(result.sourceModel); + *sourceRow = result.sourceRow; + *sourceModel = result.sourceModel; + return true; + } else { + if (row > -1) + return false; // flat model, no dropping as new children of items + // Drop onto item + const int targetRow = parent.row(); + const auto result = sourceModelForRow(targetRow); + Q_ASSERT(result.sourceModel); + const QModelIndex sourceIndex = q->mapToSource(parent); + *sourceRow = -1; + *sourceParent = sourceIndex; + *sourceModel = result.sourceModel; + return true; + } +} + +/*! + \reimp +*/ +bool QConcatenateTablesProxyModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const +{ + Q_D(const QConcatenateTablesProxyModel); + if (d->m_models.isEmpty()) + return false; + + int sourceRow, sourceColumn; + QModelIndex sourceParent; + QAbstractItemModel *sourceModel; + if (!d->mapDropCoordinatesToSource(row, column, parent, &sourceRow, &sourceColumn, &sourceParent, &sourceModel)) + return false; + return sourceModel->canDropMimeData(data, action, sourceRow, sourceColumn, sourceParent); +} + +/*! + QConcatenateTablesProxyModel handles dropping onto an item, between items, and after the last item. + In all cases the call is forwarded to the underlying source model. + When dropping onto an item, the source model for this item is called. + When dropping between items, the source model immediately below the drop position is called. + When dropping after the last item, the last source model is called. + + \reimp +*/ +bool QConcatenateTablesProxyModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) +{ + Q_D(const QConcatenateTablesProxyModel); + if (d->m_models.isEmpty()) + return false; + int sourceRow, sourceColumn; + QModelIndex sourceParent; + QAbstractItemModel *sourceModel; + if (!d->mapDropCoordinatesToSource(row, column, parent, &sourceRow, &sourceColumn, &sourceParent, &sourceModel)) + return false; + + return sourceModel->dropMimeData(data, action, sourceRow, sourceColumn, sourceParent); +} + +/*! + \reimp +*/ +QSize QConcatenateTablesProxyModel::span(const QModelIndex &index) const +{ + Q_D(const QConcatenateTablesProxyModel); + Q_ASSERT(checkIndex(index)); + if (d->m_models.isEmpty() || !index.isValid()) + return QSize(); + const QModelIndex sourceIndex = mapToSource(index); + Q_ASSERT(sourceIndex.isValid()); + return sourceIndex.model()->span(sourceIndex); +} + +/*! + Adds a source model \a sourceModel, below all previously added source models. + + The ownership of \a sourceModel is not affected by this. + + The same source model cannot be added more than once. + */ +void QConcatenateTablesProxyModel::addSourceModel(QAbstractItemModel *sourceModel) +{ + Q_D(QConcatenateTablesProxyModel); + Q_ASSERT(sourceModel); + Q_ASSERT(!d->m_models.contains(sourceModel)); + connect(sourceModel, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)), this, SLOT(_q_slotDataChanged(QModelIndex,QModelIndex,QVector<int>))); + connect(sourceModel, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(_q_slotRowsInserted(QModelIndex,int,int))); + connect(sourceModel, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(_q_slotRowsRemoved(QModelIndex,int,int))); + connect(sourceModel, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), this, SLOT(_q_slotRowsAboutToBeInserted(QModelIndex,int,int))); + connect(sourceModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), this, SLOT(_q_slotRowsAboutToBeRemoved(QModelIndex,int,int))); + + connect(sourceModel, SIGNAL(columnsInserted(QModelIndex,int,int)), this, SLOT(_q_slotColumnsInserted(QModelIndex,int,int))); + connect(sourceModel, SIGNAL(columnsRemoved(QModelIndex,int,int)), this, SLOT(_q_slotColumnsRemoved(QModelIndex,int,int))); + connect(sourceModel, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), this, SLOT(_q_slotColumnsAboutToBeInserted(QModelIndex,int,int))); + connect(sourceModel, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), this, SLOT(_q_slotColumnsAboutToBeRemoved(QModelIndex,int,int))); + + connect(sourceModel, SIGNAL(layoutAboutToBeChanged(QList<QPersistentModelIndex>, QAbstractItemModel::LayoutChangeHint)), + this, SLOT(_q_slotSourceLayoutAboutToBeChanged(QList<QPersistentModelIndex>, QAbstractItemModel::LayoutChangeHint))); + connect(sourceModel, SIGNAL(layoutChanged(QList<QPersistentModelIndex>, QAbstractItemModel::LayoutChangeHint)), + this, SLOT(_q_slotSourceLayoutChanged(QList<QPersistentModelIndex>, QAbstractItemModel::LayoutChangeHint))); + connect(sourceModel, SIGNAL(modelAboutToBeReset()), this, SLOT(_q_slotModelAboutToBeReset())); + connect(sourceModel, SIGNAL(modelReset()), this, SLOT(_q_slotModelReset())); + + const int newRows = sourceModel->rowCount(); + if (newRows > 0) + beginInsertRows(QModelIndex(), d->m_rowCount, d->m_rowCount + newRows - 1); + d->m_rowCount += newRows; + d->m_models.append(sourceModel); + if (newRows > 0) + endInsertRows(); + + d->updateColumnCount(); +} + +/*! + Removes the source model \a sourceModel, which was previously added to this proxy. + + The ownership of \a sourceModel is not affected by this. +*/ +void QConcatenateTablesProxyModel::removeSourceModel(QAbstractItemModel *sourceModel) +{ + Q_D(QConcatenateTablesProxyModel); + Q_ASSERT(d->m_models.contains(sourceModel)); + disconnect(sourceModel, 0, this, 0); + + const int rowsRemoved = sourceModel->rowCount(); + const int rowsPrior = d->computeRowsPrior(sourceModel); // location of removed section + + if (rowsRemoved > 0) + beginRemoveRows(QModelIndex(), rowsPrior, rowsPrior + rowsRemoved - 1); + d->m_models.removeOne(sourceModel); + d->m_rowCount -= rowsRemoved; + if (rowsRemoved > 0) + endRemoveRows(); + + d->updateColumnCount(); +} + +void QConcatenateTablesProxyModelPrivate::_q_slotRowsAboutToBeInserted(const QModelIndex &parent, int start, int end) +{ + Q_Q(QConcatenateTablesProxyModel); + if (parent.isValid()) // not supported, the proxy is a flat model + return; + const QAbstractItemModel * const model = static_cast<QAbstractItemModel *>(q->sender()); + const int rowsPrior = computeRowsPrior(model); + q->beginInsertRows(QModelIndex(), rowsPrior + start, rowsPrior + end); +} + +void QConcatenateTablesProxyModelPrivate::_q_slotRowsInserted(const QModelIndex &parent, int start, int end) +{ + Q_Q(QConcatenateTablesProxyModel); + if (parent.isValid()) // flat model + return; + m_rowCount += end - start + 1; + q->endInsertRows(); +} + +void QConcatenateTablesProxyModelPrivate::_q_slotRowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) +{ + Q_Q(QConcatenateTablesProxyModel); + if (parent.isValid()) // flat model + return; + const QAbstractItemModel * const model = static_cast<QAbstractItemModel *>(q->sender()); + const int rowsPrior = computeRowsPrior(model); + q->beginRemoveRows(QModelIndex(), rowsPrior + start, rowsPrior + end); +} + +void QConcatenateTablesProxyModelPrivate::_q_slotRowsRemoved(const QModelIndex &parent, int start, int end) +{ + Q_Q(QConcatenateTablesProxyModel); + if (parent.isValid()) // flat model + return; + m_rowCount -= end - start + 1; + q->endRemoveRows(); +} + +void QConcatenateTablesProxyModelPrivate::_q_slotColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end) +{ + Q_Q(QConcatenateTablesProxyModel); + if (parent.isValid()) // flat model + return; + const QAbstractItemModel * const model = static_cast<QAbstractItemModel *>(q->sender()); + const int oldColCount = model->columnCount(); + const int newColCount = columnCountAfterChange(model, oldColCount + end - start + 1); + Q_ASSERT(newColCount >= oldColCount); + if (newColCount > oldColCount) + // If the underlying models have a different number of columns (example: 2 and 3), inserting 2 columns in + // the first model leads to inserting only one column in the proxy, since qMin(2+2,3) == 3. + q->beginInsertColumns(QModelIndex(), start, qMin(end, start + newColCount - oldColCount - 1)); + m_newColumnCount = newColCount; +} + +void QConcatenateTablesProxyModelPrivate::_q_slotColumnsInserted(const QModelIndex &parent, int start, int end) +{ + Q_UNUSED(start); + Q_UNUSED(end); + Q_Q(QConcatenateTablesProxyModel); + if (parent.isValid()) // flat model + return; + if (m_newColumnCount != m_columnCount) { + m_columnCount = m_newColumnCount; + q->endInsertColumns(); + } +} + +void QConcatenateTablesProxyModelPrivate::_q_slotColumnsAboutToBeRemoved(const QModelIndex &parent, int start, int end) +{ + Q_Q(QConcatenateTablesProxyModel); + if (parent.isValid()) // flat model + return; + const QAbstractItemModel * const model = static_cast<QAbstractItemModel *>(q->sender()); + const int oldColCount = model->columnCount(); + const int newColCount = columnCountAfterChange(model, oldColCount - (end - start + 1)); + Q_ASSERT(newColCount <= oldColCount); + if (newColCount < oldColCount) + q->beginRemoveColumns(QModelIndex(), start, qMax(end, start + oldColCount - newColCount - 1)); + m_newColumnCount = newColCount; +} + +void QConcatenateTablesProxyModelPrivate::_q_slotColumnsRemoved(const QModelIndex &parent, int start, int end) +{ + Q_Q(QConcatenateTablesProxyModel); + Q_UNUSED(start); + Q_UNUSED(end); + if (parent.isValid()) // flat model + return; + if (m_newColumnCount != m_columnCount) { + m_columnCount = m_newColumnCount; + q->endRemoveColumns(); + } +} + +void QConcatenateTablesProxyModelPrivate::_q_slotDataChanged(const QModelIndex &from, const QModelIndex &to, const QVector<int> &roles) +{ + Q_Q(QConcatenateTablesProxyModel); + Q_ASSERT(from.isValid()); + Q_ASSERT(to.isValid()); + const QModelIndex myFrom = q->mapFromSource(from); + Q_ASSERT(q->checkIndex(myFrom, QAbstractItemModel::CheckIndexOption::IndexIsValid)); + const QModelIndex myTo = q->mapFromSource(to); + Q_ASSERT(q->checkIndex(myTo, QAbstractItemModel::CheckIndexOption::IndexIsValid)); + emit q->dataChanged(myFrom, myTo, roles); +} + +void QConcatenateTablesProxyModelPrivate::_q_slotSourceLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint) +{ + Q_Q(QConcatenateTablesProxyModel); + + if (!sourceParents.isEmpty() && !sourceParents.contains(QModelIndex())) + return; + + emit q->layoutAboutToBeChanged({}, hint); + + const QModelIndexList persistentIndexList = q->persistentIndexList(); + layoutChangePersistentIndexes.reserve(persistentIndexList.size()); + layoutChangeProxyIndexes.reserve(persistentIndexList.size()); + + for (const QPersistentModelIndex &proxyPersistentIndex : persistentIndexList) { + layoutChangeProxyIndexes.append(proxyPersistentIndex); + Q_ASSERT(proxyPersistentIndex.isValid()); + const QPersistentModelIndex srcPersistentIndex = q->mapToSource(proxyPersistentIndex); + Q_ASSERT(srcPersistentIndex.isValid()); + layoutChangePersistentIndexes << srcPersistentIndex; + } +} + +void QConcatenateTablesProxyModelPrivate::_q_slotSourceLayoutChanged(const QList<QPersistentModelIndex> &sourceParents, QAbstractItemModel::LayoutChangeHint hint) +{ + Q_Q(QConcatenateTablesProxyModel); + if (!sourceParents.isEmpty() && !sourceParents.contains(QModelIndex())) + return; + for (int i = 0; i < layoutChangeProxyIndexes.size(); ++i) { + const QModelIndex proxyIdx = layoutChangeProxyIndexes.at(i); + const QModelIndex newProxyIdx = q->mapFromSource(layoutChangePersistentIndexes.at(i)); + q->changePersistentIndex(proxyIdx, newProxyIdx); + } + + layoutChangePersistentIndexes.clear(); + layoutChangeProxyIndexes.clear(); + + emit q->layoutChanged({}, hint); +} + +void QConcatenateTablesProxyModelPrivate::_q_slotModelAboutToBeReset() +{ + Q_Q(QConcatenateTablesProxyModel); + Q_ASSERT(m_models.contains(const_cast<QAbstractItemModel *>(static_cast<const QAbstractItemModel *>(q->sender())))); + q->beginResetModel(); + // A reset might reduce both rowCount and columnCount, and we can't notify of both at the same time, + // and notifying of one after the other leaves an intermediary invalid situation. + // So the only safe choice is to forward it as a full reset. +} + +void QConcatenateTablesProxyModelPrivate::_q_slotModelReset() +{ + Q_Q(QConcatenateTablesProxyModel); + Q_ASSERT(m_models.contains(const_cast<QAbstractItemModel *>(static_cast<const QAbstractItemModel *>(q->sender())))); + m_columnCount = calculatedColumnCount(); + m_rowCount = computeRowsPrior(nullptr); + q->endResetModel(); +} + +int QConcatenateTablesProxyModelPrivate::calculatedColumnCount() const +{ + if (m_models.isEmpty()) + return 0; + + const auto it = std::min_element(m_models.begin(), m_models.end(), [](const QAbstractItemModel* model1, const QAbstractItemModel* model2) { + return model1->columnCount() < model2->columnCount(); + }); + return (*it)->columnCount(); +} + +void QConcatenateTablesProxyModelPrivate::updateColumnCount() +{ + Q_Q(QConcatenateTablesProxyModel); + const int newColumnCount = calculatedColumnCount(); + const int columnDiff = newColumnCount - m_columnCount; + if (columnDiff > 0) { + q->beginInsertColumns(QModelIndex(), m_columnCount, m_columnCount + columnDiff - 1); + m_columnCount = newColumnCount; + q->endInsertColumns(); + } else if (columnDiff < 0) { + const int lastColumn = m_columnCount - 1; + q->beginRemoveColumns(QModelIndex(), lastColumn + columnDiff + 1, lastColumn); + m_columnCount = newColumnCount; + q->endRemoveColumns(); + } +} + +int QConcatenateTablesProxyModelPrivate::columnCountAfterChange(const QAbstractItemModel *model, int newCount) const +{ + int newColumnCount = 0; + for (int i = 0; i < m_models.count(); ++i) { + const QAbstractItemModel *mod = m_models.at(i); + const int colCount = mod == model ? newCount : mod->columnCount(); + if (i == 0) + newColumnCount = colCount; + else + newColumnCount = qMin(colCount, newColumnCount); + } + return newColumnCount; +} + +int QConcatenateTablesProxyModelPrivate::computeRowsPrior(const QAbstractItemModel *sourceModel) const +{ + int rowsPrior = 0; + for (const QAbstractItemModel *model : m_models) { + if (model == sourceModel) + break; + rowsPrior += model->rowCount(); + } + return rowsPrior; +} + +QConcatenateTablesProxyModelPrivate::SourceModelForRowResult QConcatenateTablesProxyModelPrivate::sourceModelForRow(int row) const +{ + QConcatenateTablesProxyModelPrivate::SourceModelForRowResult result; + int rowCount = 0; + for (QAbstractItemModel *model : m_models) { + const int subRowCount = model->rowCount(); + if (rowCount + subRowCount > row) { + result.sourceModel = model; + break; + } + rowCount += subRowCount; + } + result.sourceRow = row - rowCount; + return result; +} + +QT_END_NAMESPACE + +#include "moc_qconcatenatetablesproxymodel.cpp" diff --git a/src/corelib/itemmodels/qconcatenatetablesproxymodel.h b/src/corelib/itemmodels/qconcatenatetablesproxymodel.h new file mode 100644 index 0000000000..85fc6a9c72 --- /dev/null +++ b/src/corelib/itemmodels/qconcatenatetablesproxymodel.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author David Faure <david.faure@kdab.com> +** 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 QCONCATENATEROWSPROXYMODEL_H +#define QCONCATENATEROWSPROXYMODEL_H + +#include <QtCore/qabstractitemmodel.h> + +QT_BEGIN_NAMESPACE + +class QConcatenateTablesProxyModelPrivate; + +class Q_CORE_EXPORT QConcatenateTablesProxyModel : public QAbstractItemModel +{ + Q_OBJECT + +public: + explicit QConcatenateTablesProxyModel(QObject *parent = nullptr); + ~QConcatenateTablesProxyModel(); + + Q_SCRIPTABLE void addSourceModel(QAbstractItemModel *sourceModel); + Q_SCRIPTABLE void removeSourceModel(QAbstractItemModel *sourceModel); + + QModelIndex mapFromSource(const QModelIndex &sourceIndex) const; + QModelIndex mapToSource(const QModelIndex &proxyIndex) const; + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; + QMap<int, QVariant> itemData(const QModelIndex &proxyIndex) const override; + bool setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles) override; + Qt::ItemFlags flags(const QModelIndex &index) const override; + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; + QModelIndex parent(const QModelIndex &index) const override; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + QStringList mimeTypes() const override; + QMimeData *mimeData(const QModelIndexList &indexes) const override; + bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const override; + bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override; + QSize span(const QModelIndex &index) const override; + +private: + Q_DECLARE_PRIVATE(QConcatenateTablesProxyModel) + Q_DISABLE_COPY(QConcatenateTablesProxyModel) + + Q_PRIVATE_SLOT(d_func(), void _q_slotRowsAboutToBeInserted(const QModelIndex &, int start, int end)) + Q_PRIVATE_SLOT(d_func(), void _q_slotRowsInserted(const QModelIndex &, int start, int end)) + Q_PRIVATE_SLOT(d_func(), void _q_slotRowsAboutToBeRemoved(const QModelIndex &, int start, int end)) + Q_PRIVATE_SLOT(d_func(), void _q_slotRowsRemoved(const QModelIndex &, int start, int end)) + Q_PRIVATE_SLOT(d_func(), void _q_slotColumnsAboutToBeInserted(const QModelIndex &parent, int start, int end)) + Q_PRIVATE_SLOT(d_func(), void _q_slotColumnsInserted(const QModelIndex &parent, int, int)) + Q_PRIVATE_SLOT(d_func(), void _q_slotColumnsAboutToBeRemoved(const QModelIndex &parent, int start, int end)) + Q_PRIVATE_SLOT(d_func(), void _q_slotColumnsRemoved(const QModelIndex &parent, int, int)) + Q_PRIVATE_SLOT(d_func(), void _q_slotDataChanged(const QModelIndex &from, const QModelIndex &to, const QVector<int> &roles)) + Q_PRIVATE_SLOT(d_func(), void _q_slotSourceLayoutAboutToBeChanged(QList<QPersistentModelIndex>, QAbstractItemModel::LayoutChangeHint)) + Q_PRIVATE_SLOT(d_func(), void _q_slotSourceLayoutChanged(const QList<QPersistentModelIndex> &, QAbstractItemModel::LayoutChangeHint)) + Q_PRIVATE_SLOT(d_func(), void _q_slotModelAboutToBeReset()) + Q_PRIVATE_SLOT(d_func(), void _q_slotModelReset()) +}; + +QT_END_NAMESPACE + +#endif // QCONCATENATEROWSPROXYMODEL_H diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp index 21fbf83382..2ae4e4d5ee 100644 --- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp +++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp @@ -424,7 +424,7 @@ public: void updateChildrenMapping(const QModelIndex &source_parent, Mapping *parent_mapping, Qt::Orientation orient, int start, int end, int delta_item_count, bool remove); - virtual void _q_sourceModelDestroyed() override; + void _q_sourceModelDestroyed() override; bool needsReorder(const QVector<int> &source_rows, const QModelIndex &source_parent) const; diff --git a/src/corelib/itemmodels/qstringlistmodel.cpp b/src/corelib/itemmodels/qstringlistmodel.cpp index 567e6fa35e..cc7a885641 100644 --- a/src/corelib/itemmodels/qstringlistmodel.cpp +++ b/src/corelib/itemmodels/qstringlistmodel.cpp @@ -136,6 +136,42 @@ QModelIndex QStringListModel::sibling(int row, int column, const QModelIndex &id } /*! + \reimp + \since 5.13 +*/ +QMap<int, QVariant> QStringListModel::itemData(const QModelIndex &index) const +{ + if (!checkIndex(index, CheckIndexOption::IndexIsValid | CheckIndexOption::ParentIsInvalid)) + return QMap<int, QVariant>{}; + const QVariant displayData = lst.at(index.row()); + return QMap<int, QVariant>{{ + std::make_pair<int>(Qt::DisplayRole, displayData), + std::make_pair<int>(Qt::EditRole, displayData) + }}; +} + +/*! + \reimp + \since 5.13 + If \a roles contains both Qt::DisplayRole and Qt::EditRole, the latter will take precedence +*/ +bool QStringListModel::setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles) +{ + if (roles.isEmpty()) + return false; + if (std::any_of(roles.keyBegin(), roles.keyEnd(), [](int role) -> bool { + return role != Qt::DisplayRole && role != Qt::EditRole; + })) { + return false; + } + auto roleIter = roles.constFind(Qt::EditRole); + if (roleIter == roles.constEnd()) + roleIter = roles.constFind(Qt::DisplayRole); + Q_ASSERT(roleIter != roles.constEnd()); + return setData(index, roleIter.value(), roleIter.key()); +} + +/*! Returns data for the specified \a role, from the item with the given \a index. @@ -185,18 +221,23 @@ bool QStringListModel::setData(const QModelIndex &index, const QVariant &value, if (index.row() >= 0 && index.row() < lst.size() && (role == Qt::EditRole || role == Qt::DisplayRole)) { lst.replace(index.row(), value.toString()); - QVector<int> roles; - roles.reserve(2); - roles.append(Qt::DisplayRole); - roles.append(Qt::EditRole); - emit dataChanged(index, index, roles); - // once Q_COMPILER_UNIFORM_INIT can be used, change to: - // emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole}); + emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole}); return true; } return false; } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +/*! + \reimp + \since 6.0 + */ +bool QStringListModel::clearItemData(const QModelIndex &index) +{ + return setData(index, QVariant(), Qt::EditRole); +} +#endif + /*! Inserts \a count rows into the model, beginning at the given \a row. @@ -249,6 +290,38 @@ bool QStringListModel::removeRows(int row, int count, const QModelIndex &parent) return true; } +/*! + \since 5.13 + \reimp +*/ +bool QStringListModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) +{ + if (sourceRow < 0 + || sourceRow + count - 1 >= rowCount(sourceParent) + || destinationChild <= 0 + || destinationChild > rowCount(destinationParent) + || sourceRow == destinationChild - 1 + || count <= 0) { + return false; + } + if (!beginMoveRows(QModelIndex(), sourceRow, sourceRow + count - 1, QModelIndex(), destinationChild)) + return false; + /* + QList::move assumes that the second argument is the index where the item will end up to + i.e. the valid range for that argument is from 0 to QList::size()-1 + QAbstractItemModel::moveRows when source and destinations have the same parent assumes that + the item will end up being in the row BEFORE the one indicated by destinationChild + i.e. the valid range for that argument is from 1 to QList::size() + For this reason we remove 1 from destinationChild when using it inside QList + */ + destinationChild--; + const int fromRow = destinationChild < sourceRow ? (sourceRow + count - 1) : sourceRow; + while (count--) + lst.move(fromRow, destinationChild); + endMoveRows(); + return true; +} + static bool ascendingLessThan(const QPair<QString, int> &s1, const QPair<QString, int> &s2) { return s1.first < s2.first; diff --git a/src/corelib/itemmodels/qstringlistmodel.h b/src/corelib/itemmodels/qstringlistmodel.h index a40c13ae40..6c83917054 100644 --- a/src/corelib/itemmodels/qstringlistmodel.h +++ b/src/corelib/itemmodels/qstringlistmodel.h @@ -59,11 +59,18 @@ 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; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + bool clearItemData(const QModelIndex &index) override; +#endif Qt::ItemFlags flags(const QModelIndex &index) const override; bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; + bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) override; + + QMap<int, QVariant> itemData(const QModelIndex &index) const override; + bool setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles) override; void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override; diff --git a/src/corelib/itemmodels/qtransposeproxymodel.cpp b/src/corelib/itemmodels/qtransposeproxymodel.cpp new file mode 100644 index 0000000000..dd84b97118 --- /dev/null +++ b/src/corelib/itemmodels/qtransposeproxymodel.cpp @@ -0,0 +1,446 @@ +/**************************************************************************** +** +** Copyright (C) 2018 Luca Beldi <v.ronin@yahoo.it> +** 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$ +** +****************************************************************************/ + +#include "qtransposeproxymodel.h" +#include <private/qtransposeproxymodel_p.h> +#include <QtCore/qvector.h> +#include <QtCore/qmetaobject.h> +#include <QtCore/qsize.h> + +QT_BEGIN_NAMESPACE + +QModelIndex QTransposeProxyModelPrivate::uncheckedMapToSource(const QModelIndex &proxyIndex) const +{ + if (!model || !proxyIndex.isValid()) + return QModelIndex(); + if (proxyIndex.internalPointer()) + return model->createIndex(proxyIndex.column(), proxyIndex.row(), proxyIndex.internalPointer()); + return model->index(proxyIndex.column(), proxyIndex.row()); +} + +QModelIndex QTransposeProxyModelPrivate::uncheckedMapFromSource(const QModelIndex &sourceIndex) const +{ + if (!model || !sourceIndex.isValid()) + return QModelIndex(); + Q_Q(const QTransposeProxyModel); + return q->createIndex(sourceIndex.column(), sourceIndex.row(), sourceIndex.internalPointer()); +} + +void QTransposeProxyModelPrivate::onLayoutChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint) +{ + Q_Q(QTransposeProxyModel); + QModelIndexList toList; + toList.reserve(layoutChangePersistentIndexes.size()); + for (const QPersistentModelIndex &persistIdx : qAsConst(layoutChangePersistentIndexes)) + toList << q->mapFromSource(persistIdx); + q->changePersistentIndexList(layoutChangeProxyIndexes, toList); + layoutChangeProxyIndexes.clear(); + layoutChangePersistentIndexes.clear(); + QList<QPersistentModelIndex> proxyParents; + proxyParents.reserve(parents.size()); + for (const QPersistentModelIndex &srcParent : parents) + proxyParents << q->mapFromSource(srcParent); + QAbstractItemModel::LayoutChangeHint proxyHint = QAbstractItemModel::NoLayoutChangeHint; + if (hint == QAbstractItemModel::VerticalSortHint) + proxyHint = QAbstractItemModel::HorizontalSortHint; + else if (hint == QAbstractItemModel::HorizontalSortHint) + proxyHint = QAbstractItemModel::VerticalSortHint; + q->layoutChanged(proxyParents, proxyHint); +} + +void QTransposeProxyModelPrivate::onLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint) +{ + Q_Q(QTransposeProxyModel); + const QModelIndexList proxyPersistentIndexes = q->persistentIndexList(); + layoutChangeProxyIndexes.clear(); + layoutChangePersistentIndexes.clear(); + layoutChangeProxyIndexes.reserve(proxyPersistentIndexes.size()); + layoutChangePersistentIndexes.reserve(proxyPersistentIndexes.size()); + for (const QPersistentModelIndex &proxyPersistentIndex : proxyPersistentIndexes) { + layoutChangeProxyIndexes << proxyPersistentIndex; + Q_ASSERT(proxyPersistentIndex.isValid()); + const QPersistentModelIndex srcPersistentIndex = q->mapToSource(proxyPersistentIndex); + Q_ASSERT(srcPersistentIndex.isValid()); + layoutChangePersistentIndexes << srcPersistentIndex; + } + QList<QPersistentModelIndex> proxyParents; + proxyParents.reserve(parents.size()); + for (auto& srcParent : parents) + proxyParents << q->mapFromSource(srcParent); + QAbstractItemModel::LayoutChangeHint proxyHint = QAbstractItemModel::NoLayoutChangeHint; + if (hint == QAbstractItemModel::VerticalSortHint) + proxyHint = QAbstractItemModel::HorizontalSortHint; + else if (hint == QAbstractItemModel::HorizontalSortHint) + proxyHint = QAbstractItemModel::VerticalSortHint; + q->layoutAboutToBeChanged(proxyParents, proxyHint); +} + +void QTransposeProxyModelPrivate::onDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int>& roles) +{ + Q_Q(QTransposeProxyModel); + q->dataChanged(q->mapFromSource(topLeft), q->mapFromSource(bottomRight), roles); +} + +void QTransposeProxyModelPrivate::onHeaderDataChanged(Qt::Orientation orientation, int first, int last) +{ + Q_Q(QTransposeProxyModel); + q->headerDataChanged(orientation == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal, first, last); +} + +void QTransposeProxyModelPrivate::onColumnsAboutToBeInserted(const QModelIndex &parent, int first, int last) +{ + Q_Q(QTransposeProxyModel); + q->beginInsertRows(q->mapFromSource(parent), first, last); +} + +void QTransposeProxyModelPrivate::onColumnsAboutToBeRemoved(const QModelIndex &parent, int first, int last) +{ + Q_Q(QTransposeProxyModel); + q->beginRemoveRows(q->mapFromSource(parent), first, last); +} + +void QTransposeProxyModelPrivate::onColumnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn) +{ + Q_Q(QTransposeProxyModel); + q->beginMoveRows(q->mapFromSource(sourceParent), sourceStart, sourceEnd, q->mapFromSource(destinationParent), destinationColumn); +} + +void QTransposeProxyModelPrivate::onRowsAboutToBeInserted(const QModelIndex &parent, int first, int last) +{ + Q_Q(QTransposeProxyModel); + q->beginInsertColumns(q->mapFromSource(parent), first, last); +} + +void QTransposeProxyModelPrivate::onRowsAboutToBeRemoved(const QModelIndex &parent, int first, int last) +{ + Q_Q(QTransposeProxyModel); + q->beginRemoveColumns(q->mapFromSource(parent), first, last); +} + +void QTransposeProxyModelPrivate::onRowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow) +{ + Q_Q(QTransposeProxyModel); + q->beginMoveColumns(q->mapFromSource(sourceParent), sourceStart, sourceEnd, q->mapFromSource(destinationParent), destinationRow); +} + +/*! + \since 5.13 + \class QTransposeProxyModel + \brief This proxy transposes the source model + \details This model will make the rows of the source model become columns of the proxy model and vice-versa. + + If the model is a tree, the parents will be transposed as well. For example, if an index in the source model had parent `index(2,0)`, it will have parent `index(0,2)` in the proxy. +*/ + +/*! + Constructs a new proxy model with the given \a parent. +*/ +QTransposeProxyModel::QTransposeProxyModel(QObject* parent) + : QAbstractProxyModel(*new QTransposeProxyModelPrivate, parent) +{} + +/*! + Destructs the proxy model. +*/ +QTransposeProxyModel::~QTransposeProxyModel() = default; + +/*! + \internal +*/ +QTransposeProxyModel::QTransposeProxyModel(QTransposeProxyModelPrivate &dd, QObject *parent) + : QAbstractProxyModel(dd, parent) +{} + +/*! + \reimp +*/ +void QTransposeProxyModel::setSourceModel(QAbstractItemModel* newSourceModel) +{ + Q_D(QTransposeProxyModel); + if (newSourceModel == d->model) + return; + beginResetModel(); + if (d->model) { + for (const QMetaObject::Connection& discIter : qAsConst(d->sourceConnections)) + disconnect(discIter); + } + d->sourceConnections.clear(); + QAbstractProxyModel::setSourceModel(newSourceModel); + if (d->model) { + using namespace std::placeholders; + d->sourceConnections = QVector<QMetaObject::Connection>{ + connect(d->model, &QAbstractItemModel::modelAboutToBeReset, this, &QTransposeProxyModel::beginResetModel), + connect(d->model, &QAbstractItemModel::modelReset, this, &QTransposeProxyModel::endResetModel), + connect(d->model, &QAbstractItemModel::dataChanged, this, std::bind(&QTransposeProxyModelPrivate::onDataChanged, d, _1, _2, _3)), + connect(d->model, &QAbstractItemModel::headerDataChanged, this, std::bind(&QTransposeProxyModelPrivate::onHeaderDataChanged, d, _1, _2, _3)), + connect(d->model, &QAbstractItemModel::columnsAboutToBeInserted, this, std::bind(&QTransposeProxyModelPrivate::onColumnsAboutToBeInserted, d, _1, _2, _3)), + connect(d->model, &QAbstractItemModel::columnsAboutToBeMoved, this, std::bind(&QTransposeProxyModelPrivate::onColumnsAboutToBeMoved, d, _1, _2, _3, _4, _5)), + connect(d->model, &QAbstractItemModel::columnsAboutToBeRemoved, this, std::bind(&QTransposeProxyModelPrivate::onColumnsAboutToBeRemoved, d, _1, _2, _3)), + connect(d->model, &QAbstractItemModel::columnsInserted, this, &QTransposeProxyModel::endInsertRows), + connect(d->model, &QAbstractItemModel::columnsRemoved, this, &QTransposeProxyModel::endRemoveRows), + connect(d->model, &QAbstractItemModel::columnsMoved, this, &QTransposeProxyModel::endMoveRows), + connect(d->model, &QAbstractItemModel::rowsAboutToBeInserted, this, std::bind(&QTransposeProxyModelPrivate::onRowsAboutToBeInserted, d, _1, _2, _3)), + connect(d->model, &QAbstractItemModel::rowsAboutToBeMoved, this, std::bind(&QTransposeProxyModelPrivate::onRowsAboutToBeMoved, d, _1, _2, _3, _4, _5)), + connect(d->model, &QAbstractItemModel::rowsAboutToBeRemoved, this, std::bind(&QTransposeProxyModelPrivate::onRowsAboutToBeRemoved, d, _1, _2, _3)), + connect(d->model, &QAbstractItemModel::rowsInserted, this, &QTransposeProxyModel::endInsertColumns), + connect(d->model, &QAbstractItemModel::rowsRemoved, this, &QTransposeProxyModel::endRemoveColumns), + connect(d->model, &QAbstractItemModel::rowsMoved, this, &QTransposeProxyModel::endMoveColumns), + connect(d->model, &QAbstractItemModel::layoutAboutToBeChanged, this, std::bind(&QTransposeProxyModelPrivate::onLayoutAboutToBeChanged, d, _1, _2)), + connect(d->model, &QAbstractItemModel::layoutChanged, this, std::bind(&QTransposeProxyModelPrivate::onLayoutChanged, d, _1, _2)) + }; + } + endResetModel(); +} + +/*! + \reimp +*/ +int QTransposeProxyModel::rowCount(const QModelIndex &parent) const +{ + Q_D(const QTransposeProxyModel); + if (!d->model) + return 0; + Q_ASSERT(checkIndex(parent)); + return d->model->columnCount(mapToSource(parent)); +} + +/*! + \reimp +*/ +int QTransposeProxyModel::columnCount(const QModelIndex &parent) const +{ + Q_D(const QTransposeProxyModel); + if (!d->model) + return 0; + Q_ASSERT(checkIndex(parent)); + return d->model->rowCount(mapToSource(parent)); +} + +/*! + \reimp +*/ +QVariant QTransposeProxyModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + Q_D(const QTransposeProxyModel); + if (!d->model) + return QVariant(); + return d->model->headerData(section, orientation == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal, role); +} + +/*! + \reimp +*/ +bool QTransposeProxyModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role) +{ + Q_D(QTransposeProxyModel); + if (!d->model) + return false; + return d->model->setHeaderData(section, orientation == Qt::Horizontal ? Qt::Vertical : Qt::Horizontal, value, role); +} + +/*! + \reimp +*/ +bool QTransposeProxyModel::setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles) +{ + Q_D(QTransposeProxyModel); + Q_ASSERT(checkIndex(index)); + if (!d->model || !index.isValid()) + return false; + return d->model->setItemData(mapToSource(index), roles); +} + +/*! + \reimp +*/ +QSize QTransposeProxyModel::span(const QModelIndex &index) const +{ + Q_D(const QTransposeProxyModel); + Q_ASSERT(checkIndex(index)); + if (!d->model || !index.isValid()) + return QSize(); + return d->model->span(mapToSource(index)).transposed(); +} + +/*! + \reimp +*/ +QMap<int, QVariant> QTransposeProxyModel::itemData(const QModelIndex &index) const +{ + Q_D(const QTransposeProxyModel); + if (!d->model) + return QMap<int, QVariant>(); + Q_ASSERT(checkIndex(index)); + return d->model->itemData(mapToSource(index)); +} + +/*! + \reimp +*/ +QModelIndex QTransposeProxyModel::mapFromSource(const QModelIndex &sourceIndex) const +{ + Q_D(const QTransposeProxyModel); + if (!d->model || !sourceIndex.isValid()) + return QModelIndex(); + Q_ASSERT(d->model->checkIndex(sourceIndex)); + return d->uncheckedMapFromSource(sourceIndex); +} + +/*! + \reimp +*/ +QModelIndex QTransposeProxyModel::mapToSource(const QModelIndex &proxyIndex) const +{ + Q_D(const QTransposeProxyModel); + Q_ASSERT(checkIndex(proxyIndex)); + if (!d->model || !proxyIndex.isValid()) + return QModelIndex(); + return d->uncheckedMapToSource(proxyIndex); +} + +/*! + \reimp +*/ +QModelIndex QTransposeProxyModel::parent(const QModelIndex &index) const +{ + Q_D(const QTransposeProxyModel); + Q_ASSERT(checkIndex(index, CheckIndexOption::DoNotUseParent)); + if (!d->model || !index.isValid()) + return QModelIndex(); + return d->uncheckedMapFromSource(d->uncheckedMapToSource(index).parent()); +} + +/*! + \reimp +*/ +QModelIndex QTransposeProxyModel::index(int row, int column, const QModelIndex &parent) const +{ + Q_D(const QTransposeProxyModel); + Q_ASSERT(checkIndex(parent)); + if (!d->model) + return QModelIndex(); + return mapFromSource(d->model->index(column, row, mapToSource(parent))); +} + +/*! + \reimp +*/ +bool QTransposeProxyModel::insertRows(int row, int count, const QModelIndex &parent) +{ + Q_D(QTransposeProxyModel); + Q_ASSERT(checkIndex(parent)); + if (!d->model) + return false; + return d->model->insertColumns(row, count, mapToSource(parent)); +} + +/*! + \reimp +*/ +bool QTransposeProxyModel::removeRows(int row, int count, const QModelIndex &parent) +{ + Q_D(QTransposeProxyModel); + Q_ASSERT(checkIndex(parent)); + if (!d->model) + return false; + return d->model->removeColumns(row, count, mapToSource(parent)); +} + +/*! + \reimp +*/ +bool QTransposeProxyModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) +{ + Q_D(QTransposeProxyModel); + Q_ASSERT(checkIndex(sourceParent)); + Q_ASSERT(checkIndex(destinationParent)); + if (!d->model) + return false; + return d->model->moveColumns(mapToSource(sourceParent), sourceRow, count, mapToSource(destinationParent), destinationChild); +} + +/*! + \reimp +*/ +bool QTransposeProxyModel::insertColumns(int column, int count, const QModelIndex &parent) +{ + Q_D(QTransposeProxyModel); + Q_ASSERT(checkIndex(parent)); + if (!d->model) + return false; + return d->model->insertRows(column, count, mapToSource(parent)); +} + +/*! + \reimp +*/ +bool QTransposeProxyModel::removeColumns(int column, int count, const QModelIndex &parent) +{ + Q_D(QTransposeProxyModel); + Q_ASSERT(checkIndex(parent)); + if (!d->model) + return false; + return d->model->removeRows(column, count, mapToSource(parent)); +} + +/*! + \reimp +*/ +bool QTransposeProxyModel::moveColumns(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) +{ + Q_D(QTransposeProxyModel); + Q_ASSERT(checkIndex(sourceParent)); + Q_ASSERT(checkIndex(destinationParent)); + if (!d->model) + return false; + return d->model->moveRows(mapToSource(sourceParent), sourceRow, count, mapToSource(destinationParent), destinationChild); +} + +/*! + \reimp + This method will perform no action. Use a QSortFilterProxyModel on top of this one if you require sorting. +*/ +void QTransposeProxyModel::sort(int column, Qt::SortOrder order) +{ + Q_UNUSED(column) + Q_UNUSED(order) + return; +} + +QT_END_NAMESPACE diff --git a/src/corelib/itemmodels/qtransposeproxymodel.h b/src/corelib/itemmodels/qtransposeproxymodel.h new file mode 100644 index 0000000000..879266d931 --- /dev/null +++ b/src/corelib/itemmodels/qtransposeproxymodel.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2018 Luca Beldi <v.ronin@yahoo.it> +** 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 QTRANSPOSEPROXYMODEL_H +#define QTRANSPOSEPROXYMODEL_H + +#include <QtCore/qabstractproxymodel.h> +#include <QtCore/qscopedpointer.h> + +QT_BEGIN_NAMESPACE + +class QTransposeProxyModelPrivate; + +class Q_CORE_EXPORT QTransposeProxyModel : public QAbstractProxyModel +{ + Q_OBJECT + Q_DISABLE_COPY(QTransposeProxyModel) + Q_DECLARE_PRIVATE(QTransposeProxyModel) +public: + explicit QTransposeProxyModel(QObject* parent = nullptr); + ~QTransposeProxyModel(); + void setSourceModel(QAbstractItemModel* newSourceModel) override; + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole) override; + bool setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles) override; + QSize span(const QModelIndex &index) const override; + QMap<int, QVariant> itemData(const QModelIndex &index) const override; + QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override; + QModelIndex mapToSource(const QModelIndex &proxyIndex) const override; + QModelIndex parent(const QModelIndex &index) const override; + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; + bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; + bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override; + bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) override; + bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex()) override; + bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex()) override; + bool moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count, const QModelIndex &destinationParent, int destinationChild) override; + void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override; +protected: + QTransposeProxyModel(QTransposeProxyModelPrivate &, QObject *parent); +}; + +QT_END_NAMESPACE + +#endif // QTRANSPOSEPROXYMODEL_H diff --git a/src/corelib/itemmodels/qtransposeproxymodel_p.h b/src/corelib/itemmodels/qtransposeproxymodel_p.h new file mode 100644 index 0000000000..240fc4ccae --- /dev/null +++ b/src/corelib/itemmodels/qtransposeproxymodel_p.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2018 Luca Beldi <v.ronin@yahoo.it> +** 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 QTRANSPOSEPROXYMODEL_P_H +#define QTRANSPOSEPROXYMODEL_P_H + +#include "qtransposeproxymodel.h" +#include <private/qabstractproxymodel_p.h> + +QT_BEGIN_NAMESPACE + +class QTransposeProxyModelPrivate : public QAbstractProxyModelPrivate +{ + Q_DECLARE_PUBLIC(QTransposeProxyModel) + Q_DISABLE_COPY(QTransposeProxyModelPrivate) +private: + QTransposeProxyModelPrivate() = default; + QVector<QMetaObject::Connection> sourceConnections; + QVector<QPersistentModelIndex> layoutChangePersistentIndexes; + QModelIndexList layoutChangeProxyIndexes; + QModelIndex uncheckedMapToSource(const QModelIndex &proxyIndex) const; + QModelIndex uncheckedMapFromSource(const QModelIndex &sourceIndex) const; + void onLayoutChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint); + void onLayoutAboutToBeChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint); + void onDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int>& roles); + void onHeaderDataChanged(Qt::Orientation orientation, int first, int last); + void onColumnsAboutToBeInserted(const QModelIndex &parent, int first, int last); + void onColumnsAboutToBeRemoved(const QModelIndex &parent, int first, int last); + void onColumnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn); + void onRowsAboutToBeInserted(const QModelIndex &parent, int first, int last); + void onRowsAboutToBeRemoved(const QModelIndex &parent, int first, int last); + void onRowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow); +}; + +QT_END_NAMESPACE + +#endif //QTRANSPOSEPROXYMODEL_P_H diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 3c8b0f947c..e100ec8186 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -1265,7 +1265,11 @@ bool QCoreApplication::closingDown() \l{QCoreApplication::sendPostedEvents()}{sendPostedEvents()} from within that local loop. - Calling this function processes events only for the calling thread. + Calling this function processes events only for the calling thread, + and returns after all available events have been processed. Available + events are events queued before the function call. This means that + events that are posted while the function runs will be queued until + a later round of event processing. \threadsafe @@ -1282,7 +1286,7 @@ void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags) /*! \overload processEvents() - Processes pending events for the calling thread for \a maxtime + Processes pending events for the calling thread for \a ms milliseconds or until there are no more events to process, whichever is shorter. @@ -1291,11 +1295,14 @@ void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags) Calling this function processes events only for the calling thread. + \note Unlike the \l{QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags)}{processEvents()} + overload, this function also processes events that are posted while the function runs. + \threadsafe \sa exec(), QTimer, QEventLoop::processEvents() */ -void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int maxtime) +void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int ms) { // ### Qt 6: consider splitting this method into a public and a private // one, so that a user-invoked processEvents can be detected @@ -1306,7 +1313,7 @@ void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int m QElapsedTimer start; start.start(); while (data->eventDispatcher.load()->processEvents(flags & ~QEventLoop::WaitForMoreEvents)) { - if (start.elapsed() > maxtime) + if (start.elapsed() > ms) break; } } diff --git a/src/corelib/kernel/qeventdispatcher_glib.cpp b/src/corelib/kernel/qeventdispatcher_glib.cpp index 45c6e29e4b..34c2dde6a8 100644 --- a/src/corelib/kernel/qeventdispatcher_glib.cpp +++ b/src/corelib/kernel/qeventdispatcher_glib.cpp @@ -86,9 +86,10 @@ static gboolean socketNotifierSourceCheck(GSource *source) p->pollfd.fd, t[int(p->socketNotifier->type())]); // ### note, modifies src->pollfds! p->socketNotifier->setEnabled(false); + i--; + } else { + pending = pending || ((p->pollfd.revents & p->pollfd.events) != 0); } - - pending = ((p->pollfd.revents & p->pollfd.events) != 0); } return pending; diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index eb67544f21..1ba5f3979c 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -290,6 +290,10 @@ struct DefinedTypesFilter { \value QJsonObject QJsonObject \value QJsonArray QJsonArray \value QJsonDocument QJsonDocument + \value QCborValue QCborValue + \value QCborArray QCborArray + \value QCborMap QCborMap + \value QCborSimpleType QCborSimpleType \value QModelIndex QModelIndex \value QPersistentModelIndex QPersistentModelIndex (since 5.5) \value QUuid QUuid @@ -373,6 +377,13 @@ struct DefinedTypesFilter { */ /*! + \fn int QMetaType::id() const + \since 5.13 + + Returns id type hold by this QMetatype instance. +*/ + +/*! \fn bool QMetaType::sizeOf() const \since 5.0 @@ -1374,236 +1385,197 @@ int QMetaType::type(const QT_PREPEND_NAMESPACE(QByteArray) &typeName) } #ifndef QT_NO_DATASTREAM -/*! - Writes the object pointed to by \a data with the ID \a type to - the given \a stream. Returns \c true if the object is saved - successfully; otherwise returns \c false. - The type must have been registered with qRegisterMetaType() and - qRegisterMetaTypeStreamOperators() beforehand. +namespace +{ - Normally, you should not need to call this function directly. - Instead, use QVariant's \c operator<<(), which relies on save() - to stream custom types. +template<typename T> +class HasStreamOperator +{ + struct Yes { char unused[1]; }; + struct No { char unused[2]; }; + Q_STATIC_ASSERT(sizeof(Yes) != sizeof(No)); + + template<class C> static decltype(std::declval<QDataStream&>().operator>>(std::declval<C&>()), Yes()) load(int); + template<class C> static decltype(operator>>(std::declval<QDataStream&>(), std::declval<C&>()), Yes()) load(int); + template<class C> static No load(...); + template<class C> static decltype(operator<<(std::declval<QDataStream&>(), std::declval<const C&>()), Yes()) saveFunction(int); + template<class C> static decltype(std::declval<QDataStream&>().operator<<(std::declval<const C&>()), Yes()) saveMethod(int); + template<class C> static No saveMethod(...); + template<class C> static No saveFunction(...); + static constexpr bool LoadValue = QtMetaTypePrivate::TypeDefinition<T>::IsAvailable && (sizeof(load<T>(0)) == sizeof(Yes)); + static constexpr bool SaveValue = QtMetaTypePrivate::TypeDefinition<T>::IsAvailable && + ((sizeof(saveMethod<T>(0)) == sizeof(Yes)) || (sizeof(saveFunction<T>(0)) == sizeof(Yes))); +public: + static constexpr bool Value = LoadValue && SaveValue; +}; - \sa load(), qRegisterMetaTypeStreamOperators() -*/ -bool QMetaType::save(QDataStream &stream, int type, const void *data) +// Quick sanity checks +Q_STATIC_ASSERT(HasStreamOperator<NS(QJsonDocument)>::Value); +Q_STATIC_ASSERT(!HasStreamOperator<void*>::Value); +Q_STATIC_ASSERT(HasStreamOperator<qint8>::Value); + +template<typename T, bool IsAcceptedType = DefinedTypesFilter::Acceptor<T>::IsAccepted && HasStreamOperator<T>::Value> +struct FilteredOperatorSwitch +{ + static bool load(QDataStream &stream, T *data, int) + { + stream >> *data; + return true; + } + static bool save(QDataStream &stream, const T *data, int) + { + stream << *data; + return true; + } +}; +template<typename T> +struct FilteredOperatorSwitch<T, /* IsAcceptedType = */ false> { - if (!data || !isRegistered(type)) + static const QMetaTypeInterface* getMetaTypeInterface(int type) + { + if (QModulesPrivate::QTypeModuleInfo<T>::IsGui && qMetaTypeGuiHelper) + return &qMetaTypeGuiHelper[type - QMetaType::FirstGuiType]; + else if (QModulesPrivate::QTypeModuleInfo<T>::IsWidget && qMetaTypeWidgetsHelper) + return &qMetaTypeWidgetsHelper[type - QMetaType::FirstWidgetsType]; + return nullptr; + } + static bool save(QDataStream &stream, const T *data, int type) + { + if (auto interface = getMetaTypeInterface(type)) { + interface->saveOp(stream, data); + return true; + } return false; - - switch(type) { - case QMetaType::UnknownType: - case QMetaType::Void: - case QMetaType::VoidStar: - case QMetaType::QObjectStar: -#if QT_CONFIG(itemmodel) - case QMetaType::QModelIndex: - case QMetaType::QPersistentModelIndex: -#endif - case QMetaType::QJsonValue: - case QMetaType::QJsonObject: - case QMetaType::QJsonArray: - case QMetaType::QJsonDocument: - case QMetaType::QCborValue: - case QMetaType::QCborArray: - case QMetaType::QCborMap: + } + static bool load(QDataStream &stream, T *data, int type) + { + if (auto interface = getMetaTypeInterface(type)) { + interface->loadOp(stream, data); + return true; + } return false; - case QMetaType::Nullptr: - stream << *static_cast<const std::nullptr_t *>(data); - return true; - case QMetaType::Long: - stream << qlonglong(*static_cast<const long *>(data)); - break; - case QMetaType::Int: - stream << *static_cast<const int *>(data); - break; - case QMetaType::Short: - stream << *static_cast<const short *>(data); - break; - case QMetaType::Char: + } +}; + +class SaveOperatorSwitch +{ +public: + QDataStream &stream; + int m_type; + + template<typename T> + bool delegate(const T *data) + { + return FilteredOperatorSwitch<T>::save(stream, data, m_type); + } + bool delegate(const char *data) + { // force a char to be signed - stream << *static_cast<const signed char *>(data); - break; - case QMetaType::ULong: - stream << qulonglong(*static_cast<const ulong *>(data)); - break; - case QMetaType::UInt: - stream << *static_cast<const uint *>(data); - break; - case QMetaType::LongLong: - stream << *static_cast<const qlonglong *>(data); - break; - case QMetaType::ULongLong: - stream << *static_cast<const qulonglong *>(data); - break; - case QMetaType::UShort: - stream << *static_cast<const ushort *>(data); - break; - case QMetaType::SChar: - stream << *static_cast<const signed char *>(data); - break; - case QMetaType::UChar: - stream << *static_cast<const uchar *>(data); - break; - case QMetaType::Bool: - stream << qint8(*static_cast<const bool *>(data)); - break; - case QMetaType::Float: - stream << *static_cast<const float *>(data); - break; - case QMetaType::Double: - stream << *static_cast<const double *>(data); - break; - case QMetaType::QChar: - stream << *static_cast<const NS(QChar) *>(data); - break; -#ifndef QT_BOOTSTRAPPED - case QMetaType::QVariantMap: - stream << *static_cast<const NS(QVariantMap)*>(data); - break; - case QMetaType::QVariantHash: - stream << *static_cast<const NS(QVariantHash)*>(data); - break; - case QMetaType::QVariantList: - stream << *static_cast<const NS(QVariantList)*>(data); - break; - case QMetaType::QVariant: - stream << *static_cast<const NS(QVariant)*>(data); - break; - case QMetaType::QByteArrayList: - stream << *static_cast<const NS(QByteArrayList)*>(data); - break; -#endif - case QMetaType::QByteArray: - stream << *static_cast<const NS(QByteArray)*>(data); - break; - case QMetaType::QString: - stream << *static_cast<const NS(QString)*>(data); - break; - case QMetaType::QStringList: - stream << *static_cast<const NS(QStringList)*>(data); - break; -#ifndef QT_BOOTSTRAPPED - case QMetaType::QBitArray: - stream << *static_cast<const NS(QBitArray)*>(data); - break; -#endif - case QMetaType::QDate: - stream << *static_cast<const NS(QDate)*>(data); - break; - case QMetaType::QTime: - stream << *static_cast<const NS(QTime)*>(data); - break; - case QMetaType::QDateTime: - stream << *static_cast<const NS(QDateTime)*>(data); - break; -#ifndef QT_BOOTSTRAPPED - case QMetaType::QUrl: - stream << *static_cast<const NS(QUrl)*>(data); - break; -#endif - case QMetaType::QLocale: - stream << *static_cast<const NS(QLocale)*>(data); - break; -#ifndef QT_NO_GEOM_VARIANT - case QMetaType::QRect: - stream << *static_cast<const NS(QRect)*>(data); - break; - case QMetaType::QRectF: - stream << *static_cast<const NS(QRectF)*>(data); - break; - case QMetaType::QSize: - stream << *static_cast<const NS(QSize)*>(data); - break; - case QMetaType::QSizeF: - stream << *static_cast<const NS(QSizeF)*>(data); - break; - case QMetaType::QLine: - stream << *static_cast<const NS(QLine)*>(data); - break; - case QMetaType::QLineF: - stream << *static_cast<const NS(QLineF)*>(data); - break; - case QMetaType::QPoint: - stream << *static_cast<const NS(QPoint)*>(data); - break; - case QMetaType::QPointF: - stream << *static_cast<const NS(QPointF)*>(data); - break; -#endif -#ifndef QT_NO_REGEXP - case QMetaType::QRegExp: - stream << *static_cast<const NS(QRegExp)*>(data); - break; -#endif -#if QT_CONFIG(regularexpression) - case QMetaType::QRegularExpression: - stream << *static_cast<const NS(QRegularExpression)*>(data); - break; -#endif // QT_CONFIG(regularexpression) -#ifndef QT_BOOTSTRAPPED - case QMetaType::QEasingCurve: - stream << *static_cast<const NS(QEasingCurve)*>(data); - break; - case QMetaType::QCborSimpleType: - stream << *static_cast<const quint8 *>(data); - break; -#endif // QT_BOOTSTRAPPED - case QMetaType::QFont: - case QMetaType::QPixmap: - case QMetaType::QBrush: - case QMetaType::QColor: - case QMetaType::QPalette: - case QMetaType::QImage: - case QMetaType::QPolygon: - case QMetaType::QPolygonF: - case QMetaType::QRegion: - case QMetaType::QBitmap: - case QMetaType::QCursor: - case QMetaType::QKeySequence: - case QMetaType::QPen: - case QMetaType::QTextLength: - case QMetaType::QTextFormat: - case QMetaType::QMatrix: - case QMetaType::QTransform: - case QMetaType::QMatrix4x4: - case QMetaType::QVector2D: - case QMetaType::QVector3D: - case QMetaType::QVector4D: - case QMetaType::QQuaternion: - case QMetaType::QIcon: - if (!qMetaTypeGuiHelper) - return false; - qMetaTypeGuiHelper[type - FirstGuiType].saveOp(stream, data); - break; - case QMetaType::QSizePolicy: - if (!qMetaTypeWidgetsHelper) - return false; - qMetaTypeWidgetsHelper[type - FirstWidgetsType].saveOp(stream, data); - break; - case QMetaType::QUuid: - stream << *static_cast<const NS(QUuid)*>(data); - break; - default: { + stream << qint8(*data); + return true; + } + bool delegate(const long *data) + { + stream << qlonglong(*data); + return true; + } + bool delegate(const unsigned long *data) + { + stream << qulonglong(*data); + return true; + } + bool delegate(const QMetaTypeSwitcher::NotBuiltinType *data) + { const QVector<QCustomTypeInfo> * const ct = customTypes(); if (!ct) return false; - - SaveOperator saveOp = 0; + QMetaType::SaveOperator saveOp = nullptr; { QReadLocker locker(customTypesLock()); - saveOp = ct->at(type - User).saveOp; + saveOp = ct->at(m_type - QMetaType::User).saveOp; } - if (!saveOp) return false; saveOp(stream, data); - break; } + return true; } + bool delegate(const void*) { return false; } + bool delegate(const QMetaTypeSwitcher::UnknownType*) { return false; } +}; +class LoadOperatorSwitch +{ +public: + QDataStream &stream; + int m_type; - return true; + template<typename T> + bool delegate(const T *data) + { + return FilteredOperatorSwitch<T>::load(stream, const_cast<T*>(data), m_type); + } + bool delegate(const char *data) + { + // force a char to be signed + qint8 c; + stream >> c; + *const_cast<char*>(data) = c; + return true; + } + bool delegate(const long *data) + { + qlonglong l; + stream >> l; + *const_cast<long*>(data) = l; + return true; + } + bool delegate(const unsigned long *data) + { + qlonglong l; + stream >> l; + *const_cast<unsigned long*>(data) = l; + return true; + } + bool delegate(const QMetaTypeSwitcher::NotBuiltinType *data) + { + const QVector<QCustomTypeInfo> * const ct = customTypes(); + if (!ct) + return false; + QMetaType::LoadOperator loadOp = nullptr; + { + QReadLocker locker(customTypesLock()); + loadOp = ct->at(m_type - QMetaType::User).loadOp; + } + if (!loadOp) + return false; + loadOp(stream, const_cast<QMetaTypeSwitcher::NotBuiltinType*>(data)); + return true; + } + bool delegate(const void*) { return false; } + bool delegate(const QMetaTypeSwitcher::UnknownType*) { return false; } +}; +} // namespace + +/*! + Writes the object pointed to by \a data with the ID \a type to + the given \a stream. Returns \c true if the object is saved + successfully; otherwise returns \c false. + + The type must have been registered with qRegisterMetaType() and + qRegisterMetaTypeStreamOperators() beforehand. + + Normally, you should not need to call this function directly. + Instead, use QVariant's \c operator<<(), which relies on save() + to stream custom types. + + \sa load(), qRegisterMetaTypeStreamOperators() +*/ +bool QMetaType::save(QDataStream &stream, int type, const void *data) +{ + if (!data) + return false; + SaveOperatorSwitch saveOp{stream, type}; + return QMetaTypeSwitcher::switcher<bool>(saveOp, type, data); } /*! @@ -1622,225 +1594,10 @@ bool QMetaType::save(QDataStream &stream, int type, const void *data) */ bool QMetaType::load(QDataStream &stream, int type, void *data) { - if (!data || !isRegistered(type)) - return false; - - switch(type) { - case QMetaType::UnknownType: - case QMetaType::Void: - case QMetaType::VoidStar: - case QMetaType::QObjectStar: -#if QT_CONFIG(itemmodel) - case QMetaType::QModelIndex: - case QMetaType::QPersistentModelIndex: -#endif - case QMetaType::QJsonValue: - case QMetaType::QJsonObject: - case QMetaType::QJsonArray: - case QMetaType::QJsonDocument: - case QMetaType::QCborValue: - case QMetaType::QCborArray: - case QMetaType::QCborMap: + if (!data) return false; - case QMetaType::Nullptr: - stream >> *static_cast<std::nullptr_t *>(data); - return true; - case QMetaType::Long: { - qlonglong l; - stream >> l; - *static_cast<long *>(data) = long(l); - break; } - case QMetaType::Int: - stream >> *static_cast<int *>(data); - break; - case QMetaType::Short: - stream >> *static_cast<short *>(data); - break; - case QMetaType::Char: - // force a char to be signed - stream >> *static_cast<signed char *>(data); - break; - case QMetaType::ULong: { - qulonglong ul; - stream >> ul; - *static_cast<ulong *>(data) = ulong(ul); - break; } - case QMetaType::UInt: - stream >> *static_cast<uint *>(data); - break; - case QMetaType::LongLong: - stream >> *static_cast<qlonglong *>(data); - break; - case QMetaType::ULongLong: - stream >> *static_cast<qulonglong *>(data); - break; - case QMetaType::UShort: - stream >> *static_cast<ushort *>(data); - break; - case QMetaType::SChar: - stream >> *static_cast<signed char *>(data); - break; - case QMetaType::UChar: - stream >> *static_cast<uchar *>(data); - break; - case QMetaType::Bool: { - qint8 b; - stream >> b; - *static_cast<bool *>(data) = b; - break; } - case QMetaType::Float: - stream >> *static_cast<float *>(data); - break; - case QMetaType::Double: - stream >> *static_cast<double *>(data); - break; - case QMetaType::QChar: - stream >> *static_cast< NS(QChar)*>(data); - break; -#ifndef QT_BOOTSTRAPPED - case QMetaType::QVariantMap: - stream >> *static_cast< NS(QVariantMap)*>(data); - break; - case QMetaType::QVariantHash: - stream >> *static_cast< NS(QVariantHash)*>(data); - break; - case QMetaType::QVariantList: - stream >> *static_cast< NS(QVariantList)*>(data); - break; - case QMetaType::QVariant: - stream >> *static_cast< NS(QVariant)*>(data); - break; - case QMetaType::QByteArrayList: - stream >> *static_cast< NS(QByteArrayList)*>(data); - break; -#endif - case QMetaType::QByteArray: - stream >> *static_cast< NS(QByteArray)*>(data); - break; - case QMetaType::QString: - stream >> *static_cast< NS(QString)*>(data); - break; - case QMetaType::QStringList: - stream >> *static_cast< NS(QStringList)*>(data); - break; -#ifndef QT_BOOTSTRAPPED - case QMetaType::QBitArray: - stream >> *static_cast< NS(QBitArray)*>(data); - break; -#endif - case QMetaType::QDate: - stream >> *static_cast< NS(QDate)*>(data); - break; - case QMetaType::QTime: - stream >> *static_cast< NS(QTime)*>(data); - break; - case QMetaType::QDateTime: - stream >> *static_cast< NS(QDateTime)*>(data); - break; -#ifndef QT_BOOTSTRAPPED - case QMetaType::QUrl: - stream >> *static_cast< NS(QUrl)*>(data); - break; -#endif - case QMetaType::QLocale: - stream >> *static_cast< NS(QLocale)*>(data); - break; -#ifndef QT_NO_GEOM_VARIANT - case QMetaType::QRect: - stream >> *static_cast< NS(QRect)*>(data); - break; - case QMetaType::QRectF: - stream >> *static_cast< NS(QRectF)*>(data); - break; - case QMetaType::QSize: - stream >> *static_cast< NS(QSize)*>(data); - break; - case QMetaType::QSizeF: - stream >> *static_cast< NS(QSizeF)*>(data); - break; - case QMetaType::QLine: - stream >> *static_cast< NS(QLine)*>(data); - break; - case QMetaType::QLineF: - stream >> *static_cast< NS(QLineF)*>(data); - break; - case QMetaType::QPoint: - stream >> *static_cast< NS(QPoint)*>(data); - break; - case QMetaType::QPointF: - stream >> *static_cast< NS(QPointF)*>(data); - break; -#endif -#ifndef QT_NO_REGEXP - case QMetaType::QRegExp: - stream >> *static_cast< NS(QRegExp)*>(data); - break; -#endif -#if QT_CONFIG(regularexpression) - case QMetaType::QRegularExpression: - stream >> *static_cast< NS(QRegularExpression)*>(data); - break; -#endif // QT_CONFIG(regularexpression) -#ifndef QT_BOOTSTRAPPED - case QMetaType::QEasingCurve: - stream >> *static_cast< NS(QEasingCurve)*>(data); - break; - case QMetaType::QCborSimpleType: - stream >> *static_cast<quint8 *>(data); - break; -#endif // QT_BOOTSTRAPPED - case QMetaType::QFont: - case QMetaType::QPixmap: - case QMetaType::QBrush: - case QMetaType::QColor: - case QMetaType::QPalette: - case QMetaType::QImage: - case QMetaType::QPolygon: - case QMetaType::QPolygonF: - case QMetaType::QRegion: - case QMetaType::QBitmap: - case QMetaType::QCursor: - case QMetaType::QKeySequence: - case QMetaType::QPen: - case QMetaType::QTextLength: - case QMetaType::QTextFormat: - case QMetaType::QMatrix: - case QMetaType::QTransform: - case QMetaType::QMatrix4x4: - case QMetaType::QVector2D: - case QMetaType::QVector3D: - case QMetaType::QVector4D: - case QMetaType::QQuaternion: - case QMetaType::QIcon: - if (!qMetaTypeGuiHelper) - return false; - qMetaTypeGuiHelper[type - FirstGuiType].loadOp(stream, data); - break; - case QMetaType::QSizePolicy: - if (!qMetaTypeWidgetsHelper) - return false; - qMetaTypeWidgetsHelper[type - FirstWidgetsType].loadOp(stream, data); - break; - case QMetaType::QUuid: - stream >> *static_cast< NS(QUuid)*>(data); - break; - default: { - const QVector<QCustomTypeInfo> * const ct = customTypes(); - if (!ct) - return false; - - LoadOperator loadOp = 0; - { - QReadLocker locker(customTypesLock()); - loadOp = ct->at(type - User).loadOp; - } - - if (!loadOp) - return false; - loadOp(stream, data); - break; } - } - return true; + LoadOperatorSwitch loadOp{stream, type}; + return QMetaTypeSwitcher::switcher<bool>(loadOp, type, data); } #endif // QT_NO_DATASTREAM diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index ed7feee775..a47fbfe28d 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -570,6 +570,7 @@ public: inline bool isValid() const; inline bool isRegistered() const; + inline int id() const; inline int sizeOf() const; inline TypeFlags flags() const; inline const QMetaObject *metaObject() const; @@ -1976,7 +1977,9 @@ QT_FOR_EACH_STATIC_WIDGETS_CLASS(QT_FORWARD_DECLARE_STATIC_TYPES_ITER) typedef QList<QVariant> QVariantList; typedef QMap<QString, QVariant> QVariantMap; typedef QHash<QString, QVariant> QVariantHash; -#ifndef Q_CLANG_QDOC +#ifdef Q_CLANG_QDOC +class QByteArrayList; +#else typedef QList<QByteArray> QByteArrayList; #endif @@ -2221,6 +2224,11 @@ inline bool QMetaType::isRegistered() const return isValid(); } +inline int QMetaType::id() const +{ + return m_typeId; +} + inline void *QMetaType::create(const void *copy) const { // ### TODO Qt6 remove the extension diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 14af9ac8ef..d2a3d957e9 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -2144,7 +2144,8 @@ void QObject::removeEventFilter(QObject *obj) \fn void QObject::destroyed(QObject *obj) This signal is emitted immediately before the object \a obj is - destroyed, and can not be blocked. + destroyed, after any instances of QPointer have been notified, + and can not be blocked. All the objects's children are destroyed immediately after this signal is emitted. diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 6aea40cf4a..c4e1c69883 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -432,9 +432,9 @@ struct Q_CORE_EXPORT QAbstractDynamicMetaObject : public QDynamicMetaObjectData, { ~QAbstractDynamicMetaObject(); - virtual QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *) override { return this; } + QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *) override { return this; } virtual int createProperty(const char *, const char *) { return -1; } - virtual int metaCall(QObject *, QMetaObject::Call c, int _id, void **a) override + int metaCall(QObject *, QMetaObject::Call c, int _id, void **a) override { return metaCall(c, _id, a); } virtual int metaCall(QMetaObject::Call, int _id, void **) { return _id; } // Compat overload }; diff --git a/src/corelib/kernel/qsystemerror.cpp b/src/corelib/kernel/qsystemerror.cpp index 53c3136857..9d0394e4a5 100644 --- a/src/corelib/kernel/qsystemerror.cpp +++ b/src/corelib/kernel/qsystemerror.cpp @@ -152,10 +152,7 @@ QString QSystemError::string(ErrorScope errorScope, int errorCode) case NativeError: #if defined (Q_OS_WIN) return windowsErrorString(errorCode); -#else - //unix: fall through as native and standard library are the same - Q_FALLTHROUGH(); -#endif +#endif // else unix: native and standard library are the same case StandardLibraryError: return standardLibraryErrorString(errorCode); default: diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp index 90f29aa630..2059aae3eb 100644 --- a/src/corelib/kernel/qtimer.cpp +++ b/src/corelib/kernel/qtimer.cpp @@ -585,29 +585,16 @@ void QTimer::singleShot(int msec, Qt::TimerType timerType, const QObject *receiv */ /*! - \fn template<typename Functor> QMetaObject::Connection callOnTimeout(QObject *context, Functor functor, Qt::ConnectionType connectionType = Qt::AutoConnection) + \fn template<typename Functor> QMetaObject::Connection callOnTimeout(QObject *context, Functor function, Qt::ConnectionType connectionType = Qt::AutoConnection) \since 5.12 \overload callOnTimeout() - Creates a connection from the timeout() signal to \a functor to be placed in a specific - event loop of \a context, and returns a handle to the connection. + Creates a connection from the timeout() signal to \a function, which could be a pointer + to a member function of \a context, or it could be a functor to be placed in a specific + event loop of \a context. It returns a handle to the connection. This method is provided for convenience. It's equivalent to calling - \c {QObject::connect(timer, &QTimer::timeout, context, functor, connectionType)}. - - \sa QObject::connect(), timeout() -*/ - -/*! - \fn template<typename PointerToMemberFunction> QMetaObject::Connection callOnTimeout(QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType connectionType = Qt::AutoConnection) - \since 5.12 - \overload callOnTimeout() - - Creates a connection from the timeout() signal to the \a method in the \a receiver object. Returns - a handle to the connection. - - This method is provided for convenience. It's equivalent to calling - \c {QObject::connect(timer, &QTimer::timeout, receiver, method, connectionType)}. + \c {QObject::connect(timer, &QTimer::timeout, context, function, connectionType)}. \sa QObject::connect(), timeout() */ diff --git a/src/corelib/kernel/qtimer.h b/src/corelib/kernel/qtimer.h index 66f317c567..9ff340854f 100644 --- a/src/corelib/kernel/qtimer.h +++ b/src/corelib/kernel/qtimer.h @@ -100,8 +100,6 @@ public: QMetaObject::Connection callOnTimeout(Functor slot, Qt::ConnectionType connectionType = Qt::AutoConnection); template <typename Functor> QMetaObject::Connection callOnTimeout(const QObject *context, Functor slot, Qt::ConnectionType connectionType = Qt::AutoConnection); - template <typename PointerToMemberFunction> - QMetaObject::Connection callOnTimeout(const QObject *receiver, PointerToMemberFunction slot, Qt::ConnectionType connectionType = Qt::AutoConnection); #else // singleShot to a QObject slot template <typename Duration, typename Func1> diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index ff73c27b6e..f95502e75f 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -55,6 +55,8 @@ #if QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L #include <variant> +#elif defined(Q_CLANG_QDOC) +namespace std { template<typename...> struct variant; } #endif QT_BEGIN_NAMESPACE @@ -365,7 +367,7 @@ class Q_CORE_EXPORT QVariant static inline QVariant fromValue(const T &value) { return qVariantFromValue(value); } -#if defined(Q_CLANG_QDOC) || (QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L) +#if QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L template<typename... Types> static inline QVariant fromStdVariant(const std::variant<Types...> &value) { diff --git a/src/corelib/mimetypes/qmimedatabase.cpp b/src/corelib/mimetypes/qmimedatabase.cpp index bfe9be559a..50b30a1832 100644 --- a/src/corelib/mimetypes/qmimedatabase.cpp +++ b/src/corelib/mimetypes/qmimedatabase.cpp @@ -74,7 +74,6 @@ QMimeDatabasePrivate::QMimeDatabasePrivate() QMimeDatabasePrivate::~QMimeDatabasePrivate() { - qDeleteAll(m_providers); } #ifdef QT_BUILD_INTERNAL @@ -107,52 +106,52 @@ void QMimeDatabasePrivate::loadProviders() mimeDirs.prepend(QLatin1String(":/qt-project.org/qmime")); //qDebug() << "mime dirs:" << mimeDirs; - QVector<QMimeProviderBase *> currentProviders = m_providers; - m_providers.clear(); + Providers currentProviders; + std::swap(m_providers, currentProviders); m_providers.reserve(mimeDirs.size()); for (const QString &mimeDir : qAsConst(mimeDirs)) { const QString cacheFile = mimeDir + QStringLiteral("/mime.cache"); QFileInfo fileInfo(cacheFile); // Check if we already have a provider for this dir - const auto it = std::find_if(currentProviders.begin(), currentProviders.end(), [mimeDir](QMimeProviderBase *prov) { return prov->directory() == mimeDir; }); + const auto predicate = [mimeDir](const std::unique_ptr<QMimeProviderBase> &prov) + { + return prov && prov->directory() == mimeDir; + }; + const auto it = std::find_if(currentProviders.begin(), currentProviders.end(), predicate); if (it == currentProviders.end()) { - QMimeProviderBase *provider = nullptr; + std::unique_ptr<QMimeProviderBase> provider; #if defined(QT_USE_MMAP) if (qEnvironmentVariableIsEmpty("QT_NO_MIME_CACHE") && fileInfo.exists()) { - provider = new QMimeBinaryProvider(this, mimeDir); + provider.reset(new QMimeBinaryProvider(this, mimeDir)); //qDebug() << "Created binary provider for" << mimeDir; if (!provider->isValid()) { - delete provider; - provider = nullptr; + provider.reset(); } } #endif if (!provider) { - provider = new QMimeXMLProvider(this, mimeDir); + provider.reset(new QMimeXMLProvider(this, mimeDir)); //qDebug() << "Created XML provider for" << mimeDir; } - m_providers.append(provider); + m_providers.push_back(std::move(provider)); } else { - QMimeProviderBase *provider = *it; - currentProviders.erase(it); + auto provider = std::move(*it); // take provider out of the vector provider->ensureLoaded(); if (!provider->isValid()) { - delete provider; - provider = new QMimeXMLProvider(this, mimeDir); + provider.reset(new QMimeXMLProvider(this, mimeDir)); //qDebug() << "Created XML provider to replace binary provider for" << mimeDir; } - m_providers.append(provider); + m_providers.push_back(std::move(provider)); } } - qDeleteAll(currentProviders); } -QVector<QMimeProviderBase *> QMimeDatabasePrivate::providers() +const QMimeDatabasePrivate::Providers &QMimeDatabasePrivate::providers() { #ifndef Q_OS_WASM // stub implementation always returns true Q_ASSERT(!mutex.tryLock()); // caller should have locked mutex #endif - if (m_providers.isEmpty()) { + if (m_providers.empty()) { loadProviders(); m_lastCheck.start(); } else { @@ -164,8 +163,7 @@ QVector<QMimeProviderBase *> QMimeDatabasePrivate::providers() QString QMimeDatabasePrivate::resolveAlias(const QString &nameOrAlias) { - const auto allProviders = providers(); - for (QMimeProviderBase *provider : allProviders) { + for (const auto &provider : providers()) { const QString ret = provider->resolveAlias(nameOrAlias); if (!ret.isEmpty()) return ret; @@ -179,9 +177,8 @@ QString QMimeDatabasePrivate::resolveAlias(const QString &nameOrAlias) */ QMimeType QMimeDatabasePrivate::mimeTypeForName(const QString &nameOrAlias) { - const auto allProviders = providers(); const QString mimeName = resolveAlias(nameOrAlias); - for (QMimeProviderBase *provider : allProviders) { + for (const auto &provider : providers()) { const QMimeType mime = provider->mimeTypeForName(mimeName); if (mime.isValid()) return mime; @@ -205,8 +202,7 @@ QMimeGlobMatchResult QMimeDatabasePrivate::findByFileName(const QString &fileNam { QMimeGlobMatchResult result; // TODO this parses in the order (local, global). Check that it handles "NOGLOBS" correctly. - const auto allProviders = providers(); - for (QMimeProviderBase *provider : allProviders) + for (const auto &provider : providers()) provider->addFileNameMatches(fileName, result); return result; } @@ -227,8 +223,7 @@ void QMimeDatabasePrivate::loadGenericIcon(QMimeTypePrivate &mimePrivate) QMutexLocker locker(&mutex); if (mimePrivate.fromCache) { mimePrivate.genericIconName.clear(); - const auto allProviders = providers(); - for (QMimeProviderBase *provider : allProviders) { + for (const auto &provider : providers()) { provider->loadGenericIcon(mimePrivate); if (!mimePrivate.genericIconName.isEmpty()) break; @@ -241,8 +236,7 @@ void QMimeDatabasePrivate::loadIcon(QMimeTypePrivate &mimePrivate) QMutexLocker locker(&mutex); if (mimePrivate.fromCache) { mimePrivate.iconName.clear(); - const auto allProviders = providers(); - for (QMimeProviderBase *provider : allProviders) { + for (const auto &provider : providers()) { provider->loadIcon(mimePrivate); if (!mimePrivate.iconName.isEmpty()) break; @@ -276,8 +270,7 @@ QStringList QMimeDatabasePrivate::parents(const QString &mimeName) { Q_ASSERT(!mutex.tryLock()); QStringList result; - const auto allProviders = providers(); - for (QMimeProviderBase *provider : allProviders) + for (const auto &provider : providers()) provider->addParents(mimeName, result); if (result.isEmpty()) { const QString parent = fallbackParent(mimeName); @@ -291,8 +284,7 @@ QStringList QMimeDatabasePrivate::listAliases(const QString &mimeName) { QMutexLocker locker(&mutex); QStringList result; - const auto allProviders = providers(); - for (QMimeProviderBase *provider : allProviders) + for (const auto &provider : providers()) provider->addAliases(mimeName, result); return result; } @@ -331,8 +323,7 @@ QMimeType QMimeDatabasePrivate::findByData(const QByteArray &data, int *accuracy *accuracyPtr = 0; QMimeType candidate; - const auto allProviders = providers(); - for (QMimeProviderBase *provider : allProviders) + for (const auto &provider : providers()) provider->findByMagic(data, accuracyPtr, candidate); if (candidate.isValid()) @@ -414,8 +405,7 @@ QMimeType QMimeDatabasePrivate::mimeTypeForFileNameAndData(const QString &fileNa QList<QMimeType> QMimeDatabasePrivate::allMimeTypes() { QList<QMimeType> result; - const auto allProviders = providers(); - for (QMimeProviderBase *provider : allProviders) + for (const auto &provider : providers()) provider->addAllMimeTypes(result); return result; } diff --git a/src/corelib/mimetypes/qmimedatabase_p.h b/src/corelib/mimetypes/qmimedatabase_p.h index 1e605d9a24..7bc1d41c4d 100644 --- a/src/corelib/mimetypes/qmimedatabase_p.h +++ b/src/corelib/mimetypes/qmimedatabase_p.h @@ -63,6 +63,8 @@ QT_REQUIRE_CONFIG(mimetype); #include <QtCore/qmutex.h> #include <QtCore/qvector.h> +#include <memory> + QT_BEGIN_NAMESPACE class QIODevice; @@ -102,11 +104,12 @@ public: bool mimeInherits(const QString &mime, const QString &parent); private: - QVector<QMimeProviderBase *> providers(); + using Providers = std::vector<std::unique_ptr<QMimeProviderBase>>; + const Providers &providers(); bool shouldCheck(); void loadProviders(); - mutable QVector<QMimeProviderBase *> m_providers; + mutable Providers m_providers; QElapsedTimer m_lastCheck; public: diff --git a/src/corelib/mimetypes/qmimeprovider_p.h b/src/corelib/mimetypes/qmimeprovider_p.h index 875ff9e0eb..b6268210c0 100644 --- a/src/corelib/mimetypes/qmimeprovider_p.h +++ b/src/corelib/mimetypes/qmimeprovider_p.h @@ -97,17 +97,17 @@ public: QMimeBinaryProvider(QMimeDatabasePrivate *db, const QString &directory); virtual ~QMimeBinaryProvider(); - virtual bool isValid() override; - virtual QMimeType mimeTypeForName(const QString &name) override; + bool isValid() override; + QMimeType mimeTypeForName(const QString &name) override; void addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result) override; void addParents(const QString &mime, QStringList &result) override; - virtual QString resolveAlias(const QString &name) override; + QString resolveAlias(const QString &name) override; void addAliases(const QString &name, QStringList &result) override; void findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate) override; void addAllMimeTypes(QList<QMimeType> &result) override; static void loadMimeTypePrivate(QMimeTypePrivate &); - virtual void loadIcon(QMimeTypePrivate &) override; - virtual void loadGenericIcon(QMimeTypePrivate &) override; + void loadIcon(QMimeTypePrivate &) override; + void loadGenericIcon(QMimeTypePrivate &) override; void ensureLoaded() override; private: @@ -135,11 +135,11 @@ public: QMimeXMLProvider(QMimeDatabasePrivate *db, const QString &directory); ~QMimeXMLProvider(); - virtual bool isValid() override; - virtual QMimeType mimeTypeForName(const QString &name) override; + bool isValid() override; + QMimeType mimeTypeForName(const QString &name) override; void addFileNameMatches(const QString &fileName, QMimeGlobMatchResult &result) override; void addParents(const QString &mime, QStringList &result) override; - virtual QString resolveAlias(const QString &name) override; + QString resolveAlias(const QString &name) override; void addAliases(const QString &name, QStringList &result) override; void findByMagic(const QByteArray &data, int *accuracyPtr, QMimeType &candidate) override; void addAllMimeTypes(QList<QMimeType> &result) override; diff --git a/src/corelib/plugin/qfactoryinterface.h b/src/corelib/plugin/qfactoryinterface.h index f306460690..3aec4ddd55 100644 --- a/src/corelib/plugin/qfactoryinterface.h +++ b/src/corelib/plugin/qfactoryinterface.h @@ -52,8 +52,9 @@ struct Q_CORE_EXPORT QFactoryInterface virtual QStringList keys() const = 0; }; - +#ifndef Q_CLANG_QDOC Q_DECLARE_INTERFACE(QFactoryInterface, "org.qt-project.Qt.QFactoryInterface") +#endif QT_END_NAMESPACE diff --git a/src/corelib/plugin/qplugin.h b/src/corelib/plugin/qplugin.h index 5aca22497a..676b5047d6 100644 --- a/src/corelib/plugin/qplugin.h +++ b/src/corelib/plugin/qplugin.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2018 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -71,13 +72,27 @@ inline constexpr unsigned char qPluginArchRequirements() } typedef QObject *(*QtPluginInstanceFunction)(); +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) typedef const char *(*QtPluginMetaDataFunction)(); +#else +typedef QPair<const uchar *, size_t> (*QtPluginMetaDataFunction)(); +#endif + struct Q_CORE_EXPORT QStaticPlugin { +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +public: + constexpr QStaticPlugin(QtPluginInstanceFunction i, QtPluginMetaDataFunction m) + : instance(i), rawMetaData(m().first), rawMetaDataSize(m().second) + QtPluginInstanceFunction instance; +private: + // ### Qt 6: revise, as this is not standard-layout + const void *rawMetaData; + qsizetype rawMetaDataSize +#elif !defined(Q_QDOC) // Note: This struct is initialized using an initializer list. // As such, it cannot have any new constructors or variables. -#ifndef Q_QDOC QtPluginInstanceFunction instance; QtPluginMetaDataFunction rawMetaData; #else @@ -148,6 +163,15 @@ void Q_CORE_EXPORT qRegisterStaticPluginFunction(QStaticPlugin staticPlugin); return plugin; \ } +#elif QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + +# define QT_MOC_EXPORT_PLUGIN(PLUGINCLASS, PLUGINCLASSNAME) \ + Q_EXTERN_C Q_DECL_EXPORT \ + auto qt_plugin_query_metadata() \ + { return qMakePair<const void *, size_t>(qt_pluginMetaData, sizeof qt_pluginMetaData); } \ + Q_EXTERN_C Q_DECL_EXPORT QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance() \ + Q_PLUGIN_INSTANCE(PLUGINCLASS) + #else # define QT_MOC_EXPORT_PLUGIN(PLUGINCLASS, PLUGINCLASSNAME) \ diff --git a/src/corelib/serialization/qcborarray.cpp b/src/corelib/serialization/qcborarray.cpp index c56536cdb1..28ae40f3df 100644 --- a/src/corelib/serialization/qcborarray.cpp +++ b/src/corelib/serialization/qcborarray.cpp @@ -39,6 +39,7 @@ #include "qcborarray.h" #include "qcborvalue_p.h" +#include "qdatastream.h" QT_BEGIN_NAMESPACE @@ -1218,4 +1219,23 @@ QDebug operator<<(QDebug dbg, const QCborArray &a) } #endif +#ifndef QT_NO_DATASTREAM +QDataStream &operator<<(QDataStream &stream, const QCborArray &value) +{ + stream << value.toCborValue().toCbor(); + return stream; +} + +QDataStream &operator>>(QDataStream &stream, QCborArray &value) +{ + QByteArray buffer; + stream >> buffer; + QCborParserError parseError{}; + value = QCborValue::fromCbor(buffer, &parseError).toArray(); + if (parseError.error) + stream.setStatus(QDataStream::ReadCorruptData); + return stream; +} +#endif + QT_END_NAMESPACE diff --git a/src/corelib/serialization/qcborarray.h b/src/corelib/serialization/qcborarray.h index ed0f4912ba..e06544f245 100644 --- a/src/corelib/serialization/qcborarray.h +++ b/src/corelib/serialization/qcborarray.h @@ -47,6 +47,7 @@ QT_BEGIN_NAMESPACE class QJsonArray; +class QDataStream; class QCborContainerPrivate; class Q_CORE_EXPORT QCborArray @@ -271,6 +272,7 @@ private: void detach(qsizetype reserve = 0); friend QCborValue; + friend QCborValueRef; explicit QCborArray(QCborContainerPrivate &dd) noexcept; QExplicitlySharedDataPointer<QCborContainerPrivate> d; }; @@ -298,6 +300,11 @@ Q_CORE_EXPORT uint qHash(const QCborArray &array, uint seed = 0); Q_CORE_EXPORT QDebug operator<<(QDebug, const QCborArray &a); #endif +#ifndef QT_NO_DATASTREAM +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QCborArray &); +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QCborArray &); +#endif + QT_END_NAMESPACE #endif // QCBORARRAY_H diff --git a/src/corelib/serialization/qcborcommon.h b/src/corelib/serialization/qcborcommon.h index f8278f1649..3dfe50cd09 100644 --- a/src/corelib/serialization/qcborcommon.h +++ b/src/corelib/serialization/qcborcommon.h @@ -133,6 +133,11 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, QCborKnownTags tg); Q_CORE_EXPORT QDebug operator<<(QDebug, QCborTag tg); #endif +#if !defined(QT_NO_DEBUG_STREAM) +QDataStream &operator<<(QDataStream &ds, QCborSimpleType st); +QDataStream &operator>>(QDataStream &ds, QCborSimpleType &st); +#endif + inline uint qHash(QCborSimpleType tag, uint seed = 0) { return qHash(quint8(tag), seed); diff --git a/src/corelib/serialization/qcbormap.cpp b/src/corelib/serialization/qcbormap.cpp index 33f9249993..4b28ca4a2e 100644 --- a/src/corelib/serialization/qcbormap.cpp +++ b/src/corelib/serialization/qcbormap.cpp @@ -1763,4 +1763,23 @@ QDebug operator<<(QDebug dbg, const QCborMap &m) } #endif +#ifndef QT_NO_DATASTREAM +QDataStream &operator<<(QDataStream &stream, const QCborMap &value) +{ + stream << value.toCborValue().toCbor(); + return stream; +} + +QDataStream &operator>>(QDataStream &stream, QCborMap &value) +{ + QByteArray buffer; + stream >> buffer; + QCborParserError parseError{}; + value = QCborValue::fromCbor(buffer, &parseError).toMap(); + if (parseError.error) + stream.setStatus(QDataStream::ReadCorruptData); + return stream; +} +#endif + QT_END_NAMESPACE diff --git a/src/corelib/serialization/qcbormap.h b/src/corelib/serialization/qcbormap.h index 3eb2107691..15a3bcdcef 100644 --- a/src/corelib/serialization/qcbormap.h +++ b/src/corelib/serialization/qcbormap.h @@ -52,6 +52,7 @@ typedef QMap<QString, QVariant> QVariantMap; template <class Key, class T> class QHash; typedef QHash<QString, QVariant> QVariantHash; class QJsonObject; +class QDataStream; class QCborContainerPrivate; class Q_CORE_EXPORT QCborMap @@ -117,6 +118,8 @@ public: QCborValueRef item; // points to the value friend class Iterator; friend class QCborMap; + friend class QCborValue; + friend class QCborValueRef; ConstIterator(QCborContainerPrivate *dd, qsizetype ii) : item(dd, ii) {} public: typedef std::random_access_iterator_tag iterator_category; @@ -322,9 +325,10 @@ public: QJsonObject toJsonObject() const; private: + friend class QCborValue; + friend class QCborValueRef; void detach(qsizetype reserve = 0); - friend QCborValue; explicit QCborMap(QCborContainerPrivate &dd) noexcept; QExplicitlySharedDataPointer<QCborContainerPrivate> d; }; @@ -352,6 +356,12 @@ Q_CORE_EXPORT uint qHash(const QCborMap &map, uint seed = 0); Q_CORE_EXPORT QDebug operator<<(QDebug, const QCborMap &m); #endif +#ifndef QT_NO_DATASTREAM +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QCborMap &); +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QCborMap &); +#endif + + QT_END_NAMESPACE #endif // QCBORMAP_H diff --git a/src/corelib/serialization/qcborstream.cpp b/src/corelib/serialization/qcborstream.cpp index fc5610e341..39f9e2e70a 100644 --- a/src/corelib/serialization/qcborstream.cpp +++ b/src/corelib/serialization/qcborstream.cpp @@ -44,6 +44,7 @@ #include <qbuffer.h> #include <qdebug.h> #include <qstack.h> +#include <qdatastream.h> QT_BEGIN_NAMESPACE @@ -170,6 +171,21 @@ Q_CORE_EXPORT const char *qt_cbor_simpletype_id(QCborSimpleType st) return nullptr; } +#if !defined(QT_NO_DATASTREAM) +QDataStream &operator<<(QDataStream &ds, QCborSimpleType st) +{ + return ds << quint8(st); +} + +QDataStream &operator>>(QDataStream &ds, QCborSimpleType &st) +{ + quint8 v; + ds >> v; + st = QCborSimpleType(v); + return ds; +} +#endif + #if !defined(QT_NO_DEBUG_STREAM) QDebug operator<<(QDebug dbg, QCborSimpleType st) { diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp index 5d97a6a06a..2e2bac3f65 100644 --- a/src/corelib/serialization/qcborvalue.cpp +++ b/src/corelib/serialization/qcborvalue.cpp @@ -39,7 +39,7 @@ #include "qcborvalue.h" #include "qcborvalue_p.h" - +#include "qdatastream.h" #include "qcborarray.h" #include "qcbormap.h" #include "qcborstream.h" @@ -128,10 +128,11 @@ QT_BEGIN_NAMESPACE Such values are completely valid and may appear in CBOR streams, unlike JSON content and QJsonValue's undefined bit. But like QJsonValue's - Undefined, it is returned by QCborArray::value() when out of range or - QCborMap::operator[] when the key is not found in the container. It is not - possible to tell such a case apart from the value of Undefined, so if that - is required, check the QCborArray size and use the QCborMap iterator API. + Undefined, it is returned by a CBOR container's value() or read-only + operator[] for invalid look-ups (index out of range for QCborArray, or key + not found for QCborMap). It is not possible to tell such a case apart from + the value of Undefined, so if that is required, check the QCborArray size + and use the QCborMap iterator API. \section1 Simple types @@ -457,7 +458,7 @@ QT_BEGIN_NAMESPACE \fn QCborValue::QCborValue(QCborValue &&other) \overload - Moves the contents of the \a other CBorValue object into this one and frees + Moves the contents of the \a other QCborValue object into this one and frees the resources of this one. */ @@ -465,7 +466,7 @@ QT_BEGIN_NAMESPACE \fn QCborValue &&QCborValue::operator=(QCborValue &&other) \overload - Moves the contents of the \a other CBorValue object into this one and frees + Moves the contents of the \a other QCborValue object into this one and frees the resources of this one. Returns a reference to this object. */ @@ -1982,12 +1983,24 @@ QUuid QCborValue::toUuid(const QUuid &defaultValue) const return QUuid::fromRfc4122(byteData->asByteArrayView()); } -QCborArray QCborValue::toArray() const -{ - return toArray(QCborArray()); -} +/*! + \fn QCborArray QCborValue::toArray() const + \fn QCborArray QCborValue::toArray(const QCborArray &defaultValue) const + + Returns the array value stored in this QCborValue, if it is of the array + type. Otherwise, it returns \a defaultValue. + + Note that this function performs no conversion from other types to + QCborArray. + + \sa isArray(), isByteArray(), isMap(), isContainer(), toMap() + */ /*! + \fn QCborArray QCborValueRef::toArray() const + \fn QCborArray QCborValueRef::toArray(const QCborArray &defaultValue) const + \internal + Returns the array value stored in this QCborValue, if it is of the array type. Otherwise, it returns \a defaultValue. @@ -1996,6 +2009,11 @@ QCborArray QCborValue::toArray() const \sa isArray(), isByteArray(), isMap(), isContainer(), toMap() */ +QCborArray QCborValue::toArray() const +{ + return toArray(QCborArray()); +} + QCborArray QCborValue::toArray(const QCborArray &defaultValue) const { if (!isArray()) @@ -2007,12 +2025,24 @@ QCborArray QCborValue::toArray(const QCborArray &defaultValue) const return dd ? QCborArray(*dd) : defaultValue; } -QCborMap QCborValue::toMap() const -{ - return toMap(QCborMap()); -} +/*! + \fn QCborMap QCborValue::toMap() const + \fn QCborMap QCborValue::toMap(const QCborMap &defaultValue) const + + Returns the map value stored in this QCborValue, if it is of the map type. + Otherwise, it returns \a defaultValue. + + Note that this function performs no conversion from other types to + QCborMap. + + \sa isMap(), isArray(), isContainer(), toArray() + */ /*! + \fn QCborMap QCborValueRef::toMap() const + \fn QCborMap QCborValueRef::toMap(const QCborMap &defaultValue) const + \internal + Returns the map value stored in this QCborValue, if it is of the map type. Otherwise, it returns \a defaultValue. @@ -2021,6 +2051,11 @@ QCborMap QCborValue::toMap() const \sa isMap(), isArray(), isContainer(), toArray() */ +QCborMap QCborValue::toMap() const +{ + return toMap(QCborMap()); +} + QCborMap QCborValue::toMap(const QCborMap &defaultValue) const { if (!isMap()) @@ -2073,15 +2108,16 @@ const QCborValue QCborValue::operator[](QLatin1String key) const } /*! + \overload + If this QCborValue is a QCborMap, searches elements for the value whose key - matches \a key. If this is an array, returns the element whose index is \a - key. If there's no matching value in the array or map, or if this + matches \a key. If this is a QCborArray, returns the element whose index is + \a key. If there's no matching value in the array or map, or if this QCborValue object is not an array or map, returns the undefined value. \sa operator[], QCborMap::operator[], QCborMap::value(), QCborMap::find(), QCborArray::operator[], QCborArray::at() */ - const QCborValue QCborValue::operator[](qint64 key) const { if (isMap()) @@ -2092,6 +2128,191 @@ const QCborValue QCborValue::operator[](qint64 key) const } /*! + \internal + */ +static Q_DECL_COLD_FUNCTION QCborMap arrayAsMap(const QCborArray &array) +{ + if (array.size()) + qWarning("Using CBOR array as map forced conversion"); + QCborMap map; + for (qsizetype i = array.size(); i-- > 0; ) { + QCborValue entry = array.at(i); + // Ignore padding entries that may have been added to grow the array + // when inserting past its end: + if (!entry.isInvalid()) + map[i] = entry; + } + return map; +} + +/*! + \internal + */ +static QCborContainerPrivate *maybeDetach(QCborContainerPrivate *container, qsizetype size) +{ + auto replace = QCborContainerPrivate::detach(container, size); + Q_ASSERT(replace); + if (replace != container) { + if (container) + container->deref(); + replace->ref.ref(); + } + return replace; +} + +/*! + \internal + */ +static QCborContainerPrivate *maybeGrow(QCborContainerPrivate *container, qsizetype index) +{ + auto replace = QCborContainerPrivate::grow(container, index); + Q_ASSERT(replace); + if (replace != container) { + if (container) + container->deref(); + replace->ref.ref(); + } + if (replace->elements.size() == index) + replace->append(Undefined()); + else + Q_ASSERT(replace->elements.size() > index); + return replace; +} + +/*! + Returns a QCborValueRef that can be used to read or modify the entry in + this, as a map, with the given \a key. When this QCborValue is a QCborMap, + this function is equivalent to the matching operator[] on that map. + + Before returning the reference: if this QCborValue was an array, it is first + converted to a map (so that \c{map[i]} is \c{array[i]} for each index, \c i, + with valid \c{array[i]}); otherwise, if it was not a map it will be + over-written with an empty map. + + \sa operator[](qint64), QCborMap::operator[], QCborMap::value(), + QCborMap::find() + */ +QCborValueRef QCborValue::operator[](const QString &key) +{ + if (!isMap()) + *this = QCborValue(isArray() ? arrayAsMap(toArray()) : QCborMap()); + + const qsizetype size = container ? container->elements.size() : 0; + qsizetype index = size + 1; + bool found = false; + if (container) { + QCborMap proxy(*container); + auto it = proxy.constFind(key); + if (it < proxy.constEnd()) { + found = true; + index = it.item.i; + } + } + + container = maybeDetach(container, size + (found ? 0 : 2)); + Q_ASSERT(container); + if (!found) { + container->append(key); + container->append(QCborValue()); + } + Q_ASSERT(index & 1 && !(container->elements.size() & 1)); + Q_ASSERT(index < container->elements.size()); + return { container, index }; +} + +/*! + \overload + + Returns a QCborValueRef that can be used to read or modify the entry in + this, as a map, with the given \a key. When this QCborValue is a QCborMap, + this function is equivalent to the matching operator[] on that map. + + Before returning the reference: if this QCborValue was an array, it is first + converted to a map (so that \c{map[i]} is \c{array[i]} for each index, \c i, + with valid \c{array[i]}); otherwise, if it was not a map it will be + over-written with an empty map. + + \sa operator[](qint64), QCborMap::operator[], QCborMap::value(), + QCborMap::find() + */ +QCborValueRef QCborValue::operator[](QLatin1String key) +{ + if (!isMap()) + *this = QCborValue(isArray() ? arrayAsMap(toArray()) : QCborMap()); + + const qsizetype size = container ? container->elements.size() : 0; + qsizetype index = size + 1; + bool found = false; + if (container) { + QCborMap proxy(*container); + auto it = proxy.constFind(key); + if (it < proxy.constEnd()) { + found = true; + index = it.item.i; + } + } + + container = maybeDetach(container, size + (found ? 0 : 2)); + Q_ASSERT(container); + if (!found) { + container->append(key); + container->append(QCborValue()); + } + Q_ASSERT(index & 1 && !(container->elements.size() & 1)); + Q_ASSERT(index < container->elements.size()); + return { container, index }; +} + +/*! + \overload + + Returns a QCborValueRef that can be used to read or modify the entry in + this, as a map or array, with the given \a key. When this QCborValue is a + QCborMap or, for 0 <= key < 0x10000, a QCborArray, this function is + equivalent to the matching operator[] on that map or array. + + Before returning the reference: if this QCborValue was an array but the key + is out of range, the array is first converted to a map (so that \c{map[i]} + is \c{array[i]} for each index, \c i, with valid \c{array[i]}); otherwise, + if it was not a map it will be over-written with an empty map. + + \sa operator[], QCborMap::operator[], QCborMap::value(), + QCborMap::find(), QCborArray::operator[], QCborArray::at() + */ +QCborValueRef QCborValue::operator[](qint64 key) +{ + if (isArray() && key >= 0 && key < 0x10000) { + container = maybeGrow(container, key); + return { container, qsizetype(key) }; + } + if (!isMap()) + *this = QCborValue(isArray() ? arrayAsMap(toArray()) : QCborMap()); + + const qsizetype size = container ? container->elements.size() : 0; + Q_ASSERT(!(size & 1)); + qsizetype index = size + 1; + bool found = false; + if (container) { + QCborMap proxy(*container); + auto it = proxy.constFind(key); + if (it < proxy.constEnd()) { + found = true; + index = it.item.i; + } + } + + container = maybeDetach(container, size + (found ? 0 : 2)); + Q_ASSERT(container); + if (!found) { + container->append(key); + container->append(QCborValue()); + } + Q_ASSERT(index & 1 && !(container->elements.size() & 1)); + Q_ASSERT(index < container->elements.size()); + return { container, index }; +} + +/*! Decodes one item from the CBOR stream found in \a reader and returns the equivalent representation. This function is recursive: if the item is a map or array, it will decode all items found in that map or array, until the @@ -2355,6 +2576,255 @@ QCborValue::Type QCborValueRef::concreteType(QCborValueRef self) noexcept return self.d->elements.at(self.i).type; } +/*! + If this QCborValueRef refers to a QCborMap, searches elements for the value + whose key matches \a key. If there's no key matching \a key in the map or if + this QCborValueRef object is not a map, returns the undefined value. + + This function is equivalent to: + + \code + value.toMap().value(key); + \endcode + + \sa operator[](qint64), QCborMap::operator[], QCborMap::value(), + QCborMap::find() + */ +const QCborValue QCborValueRef::operator[](const QString &key) const +{ + const QCborValue item = d->valueAt(i); + return item[key]; +} + +/*! + \overload + + If this QCborValueRef refers to a QCborMap, searches elements for the value + whose key matches \a key. If there's no key matching \a key in the map or if + this QCborValueRef object is not a map, returns the undefined value. + + This function is equivalent to: + + \code + value.toMap().value(key); + \endcode + + \sa operator[](qint64), QCborMap::operator[], QCborMap::value(), + QCborMap::find() + */ +const QCborValue QCborValueRef::operator[](QLatin1String key) const +{ + const QCborValue item = d->valueAt(i); + return item[key]; +} + +/*! + \overload + + If this QCborValueRef refers to a QCborMap, searches elements for the value + whose key matches \a key. If this is a QCborArray, returns the element whose + index is \a key. If there's no matching value in the array or map, or if + this QCborValueRef object is not an array or map, returns the undefined + value. + + \sa operator[], QCborMap::operator[], QCborMap::value(), + QCborMap::find(), QCborArray::operator[], QCborArray::at() + */ +const QCborValue QCborValueRef::operator[](qint64 key) const +{ + const QCborValue item = d->valueAt(i); + return item[key]; +} + +/*! + Returns a QCborValueRef that can be used to read or modify the entry in + this, as a map, with the given \a key. When this QCborValueRef refers to a + QCborMap, this function is equivalent to the matching operator[] on that + map. + + Before returning the reference: if the QCborValue referenced was an array, + it is first converted to a map (so that \c{map[i]} is \c{array[i]} for each + index, \c i, with valid \c{array[i]}); otherwise, if it was not a map it + will be over-written with an empty map. + + \sa operator[](qint64), QCborMap::operator[], QCborMap::value(), + QCborMap::find() + */ +QCborValueRef QCborValueRef::operator[](const QString &key) +{ + auto &e = d->elements[i]; + qsizetype size = 0; + if (e.flags & QtCbor::Element::IsContainer) { + if (e.container) { + if (e.type == QCborValue::Array) { + QCborValue repack = QCborValue(arrayAsMap(QCborArray(*e.container))); + qSwap(e.container, repack.container); + } else if (e.type != QCborValue::Map) { + e.container->deref(); + e.container = nullptr; + } + } + e.type = QCborValue::Map; + if (e.container) + size = e.container->elements.size(); + } else { + // Stomp any prior e.value, replace with a map (that we'll grow) + e.container = nullptr; + e.type = QCborValue::Map; + e.flags = QtCbor::Element::IsContainer; + } + + qsizetype index = size + 1; + bool found = false; + if (e.container) { + QCborMap proxy(*e.container); + auto it = proxy.constFind(key); + if (it < proxy.constEnd()) { + found = true; + index = it.item.i; + } + } + + e.container = maybeDetach(e.container, size + (found ? 0 : 2)); + Q_ASSERT(e.container); + if (!found) { + e.container->append(key); + e.container->append(QCborValue()); + } + Q_ASSERT(index & 1 && !(e.container->elements.size() & 1)); + Q_ASSERT(index < e.container->elements.size()); + return { e.container, index }; +} + +/*! + \overload + + Returns a QCborValueRef that can be used to read or modify the entry in + this, as a map, with the given \a key. When this QCborValue is a QCborMap, + this function is equivalent to the matching operator[] on that map. + + Before returning the reference: if the QCborValue referenced was an array, + it is first converted to a map (so that \c{map[i]} is \c{array[i]} for each + index, \c i, with valid \c{array[i]}); otherwise, if it was not a map it + will be over-written with an empty map. + + \sa operator[](qint64), QCborMap::operator[], QCborMap::value(), + QCborMap::find() + */ +QCborValueRef QCborValueRef::operator[](QLatin1String key) +{ + auto &e = d->elements[i]; + qsizetype size = 0; + if (e.flags & QtCbor::Element::IsContainer) { + if (e.container) { + if (e.type == QCborValue::Array) { + QCborValue repack = QCborValue(arrayAsMap(QCborArray(*e.container))); + qSwap(e.container, repack.container); + } else if (e.type != QCborValue::Map) { + e.container->deref(); + e.container = nullptr; + } + } + e.type = QCborValue::Map; + if (e.container) + size = e.container->elements.size(); + } else { + // Stomp any prior e.value, replace with a map (that we'll grow) + e.container = nullptr; + e.type = QCborValue::Map; + e.flags = QtCbor::Element::IsContainer; + } + + qsizetype index = size + 1; + bool found = false; + if (e.container) { + QCborMap proxy(*e.container); + auto it = proxy.constFind(key); + if (it < proxy.constEnd()) { + found = true; + index = it.item.i; + } + } + + e.container = maybeDetach(e.container, size + (found ? 0 : 2)); + Q_ASSERT(e.container); + if (!found) { + e.container->append(key); + e.container->append(QCborValue()); + } + Q_ASSERT(index & 1 && !(e.container->elements.size() & 1)); + Q_ASSERT(index < e.container->elements.size()); + return { e.container, index }; +} + +/*! + \overload + + Returns a QCborValueRef that can be used to read or modify the entry in + this, as a map or array, with the given \a key. When this QCborValue is a + QCborMap or, for 0 <= key < 0x10000, a QCborArray, this function is + equivalent to the matching operator[] on that map or array. + + Before returning the reference: if the QCborValue referenced was an array + but the key is out of range, the array is first converted to a map (so that + \c{map[i]} is \c{array[i]} for each index, \c i, with valid \c{array[i]}); + otherwise, if it was not a map it will be over-written with an empty map. + + \sa operator[], QCborMap::operator[], QCborMap::value(), + QCborMap::find(), QCborArray::operator[], QCborArray::at() + */ +QCborValueRef QCborValueRef::operator[](qint64 key) +{ + auto &e = d->elements[i]; + if (e.type == QCborValue::Array && key >= 0 && key < 0x10000) { + e.container = maybeGrow(e.container, key); + return { e.container, qsizetype(key) }; + } + qsizetype size = 0; + if (e.flags & QtCbor::Element::IsContainer) { + if (e.container) { + if (e.type == QCborValue::Array) { + QCborValue repack = QCborValue(arrayAsMap(QCborArray(*e.container))); + qSwap(e.container, repack.container); + } else if (e.type != QCborValue::Map) { + e.container->deref(); + e.container = nullptr; + } + } + e.type = QCborValue::Map; + if (e.container) + size = e.container->elements.size(); + } else { + // Stomp any prior e.value, replace with a map (that we'll grow) + e.container = nullptr; + e.type = QCborValue::Map; + e.flags = QtCbor::Element::IsContainer; + } + Q_ASSERT(!(size & 1)); + + qsizetype index = size + 1; + bool found = false; + if (e.container) { + QCborMap proxy(*e.container); + auto it = proxy.constFind(key); + if (it < proxy.constEnd()) { + found = true; + index = it.item.i; + } + } + + e.container = maybeDetach(e.container, size + (found ? 0 : 2)); + Q_ASSERT(e.container); + if (!found) { + e.container->append(key); + e.container->append(QCborValue()); + } + Q_ASSERT(index & 1 && !(e.container->elements.size() & 1)); + Q_ASSERT(index < e.container->elements.size()); + return { e.container, index }; +} + + inline QCborArray::QCborArray(QCborContainerPrivate &dd) noexcept : d(&dd) { @@ -2469,6 +2939,26 @@ QDebug operator<<(QDebug dbg, const QCborValue &v) } #endif +#ifndef QT_NO_DATASTREAM +QDataStream &operator<<(QDataStream &stream, const QCborValue &value) +{ + stream << QCborValue(value).toCbor(); + return stream; +} + +QDataStream &operator>>(QDataStream &stream, QCborValue &value) +{ + QByteArray buffer; + stream >> buffer; + QCborParserError parseError{}; + value = QCborValue::fromCbor(buffer, &parseError); + if (parseError.error) + stream.setStatus(QDataStream::ReadCorruptData); + return stream; +} +#endif + + QT_END_NAMESPACE #include "qcborarray.cpp" diff --git a/src/corelib/serialization/qcborvalue.h b/src/corelib/serialization/qcborvalue.h index 105af1ba73..e6e73e1fb6 100644 --- a/src/corelib/serialization/qcborvalue.h +++ b/src/corelib/serialization/qcborvalue.h @@ -67,6 +67,7 @@ class QCborArray; class QCborMap; class QCborStreamReader; class QCborStreamWriter; +class QDataStream; struct QCborParserError { @@ -76,6 +77,7 @@ struct QCborParserError QString errorString() const { return error.toString(); } }; +class QCborValueRef; class QCborContainerPrivate; class Q_CORE_EXPORT QCborValue { @@ -236,20 +238,18 @@ public: QRegularExpression toRegularExpression(const QRegularExpression &defaultValue = {}) const; QUuid toUuid(const QUuid &defaultValue = {}) const; -#ifdef Q_QDOC - QCborArray toArray(const QCborArray &a = {}) const; - QCborMap toMap(const QCborMap &m = {}) const; -#else // only forward-declared, need split functions QCborArray toArray() const; QCborArray toArray(const QCborArray &defaultValue) const; QCborMap toMap() const; QCborMap toMap(const QCborMap &defaultValue) const; -#endif const QCborValue operator[](const QString &key) const; const QCborValue operator[](QLatin1String key) const; const QCborValue operator[](qint64 key) const; + QCborValueRef operator[](qint64 key); + QCborValueRef operator[](QLatin1String key); + QCborValueRef operator[](const QString & key); int compare(const QCborValue &other) const; #if 0 && QT_HAS_INCLUDE(<compare>) @@ -385,16 +385,18 @@ public: QUuid toUuid(const QUuid &defaultValue = {}) const { return concrete().toUuid(defaultValue); } -#ifdef Q_QDOC - QCborArray toArray(const QCborArray &a = {}) const; - QCborMap toMap(const QCborMap &m = {}) const; -#else // only forward-declared, need split functions. Implemented in qcbor{array,map}.h QCborArray toArray() const; QCborArray toArray(const QCborArray &a) const; QCborMap toMap() const; QCborMap toMap(const QCborMap &m) const; -#endif + + const QCborValue operator[](const QString &key) const; + const QCborValue operator[](QLatin1String key) const; + const QCborValue operator[](qint64 key) const; + QCborValueRef operator[](qint64 key); + QCborValueRef operator[](QLatin1String key); + QCborValueRef operator[](const QString & key); int compare(const QCborValue &other) const { return concrete().compare(other); } @@ -426,6 +428,7 @@ public: { return concrete().toDiagnosticNotation(opt); } private: + friend class QCborValue; friend class QCborArray; friend class QCborMap; friend class QCborContainerPrivate; @@ -457,6 +460,11 @@ Q_CORE_EXPORT uint qHash(const QCborValue &value, uint seed = 0); Q_CORE_EXPORT QDebug operator<<(QDebug, const QCborValue &v); #endif +#ifndef QT_NO_DATASTREAM +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QCborValue &); +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QCborValue &); +#endif + QT_END_NAMESPACE #if defined(QT_X11_DEFINES_FOUND) diff --git a/src/corelib/serialization/qdatastream.cpp b/src/corelib/serialization/qdatastream.cpp index 951f6c9736..01808ebce6 100644 --- a/src/corelib/serialization/qdatastream.cpp +++ b/src/corelib/serialization/qdatastream.cpp @@ -559,6 +559,7 @@ void QDataStream::setByteOrder(ByteOrder bo) \value Qt_5_10 Same as Qt_5_6 \value Qt_5_11 Same as Qt_5_6 \value Qt_5_12 Version 18 (Qt 5.12) + \value Qt_5_13 Version 19 (Qt 5.13) \omitvalue Qt_DefaultCompiledVersion \sa setVersion(), version() diff --git a/src/corelib/serialization/qdatastream.h b/src/corelib/serialization/qdatastream.h index eae0146553..2c874700e4 100644 --- a/src/corelib/serialization/qdatastream.h +++ b/src/corelib/serialization/qdatastream.h @@ -99,10 +99,11 @@ public: Qt_5_10 = Qt_5_9, Qt_5_11 = Qt_5_10, Qt_5_12 = 18, -#if QT_VERSION >= 0x050d00 + Qt_5_13 = 19, +#if QT_VERSION >= 0x050e00 #error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion #endif - Qt_DefaultCompiledVersion = Qt_5_12 + Qt_DefaultCompiledVersion = Qt_5_13 }; enum ByteOrder { diff --git a/src/corelib/serialization/qjsonarray.cpp b/src/corelib/serialization/qjsonarray.cpp index 1187bb03a3..5ba83c41b9 100644 --- a/src/corelib/serialization/qjsonarray.cpp +++ b/src/corelib/serialization/qjsonarray.cpp @@ -1259,5 +1259,22 @@ QDebug operator<<(QDebug dbg, const QJsonArray &a) } #endif +#ifndef QT_NO_DATASTREAM +QDataStream &operator<<(QDataStream &stream, const QJsonArray &array) +{ + QJsonDocument doc{array}; + stream << doc.toJson(QJsonDocument::Compact); + return stream; +} + +QDataStream &operator>>(QDataStream &stream, QJsonArray &array) +{ + QJsonDocument doc; + stream >> doc; + array = doc.array(); + return stream; +} +#endif + QT_END_NAMESPACE diff --git a/src/corelib/serialization/qjsonarray.h b/src/corelib/serialization/qjsonarray.h index 5dff4a0aa9..0a17951fb7 100644 --- a/src/corelib/serialization/qjsonarray.h +++ b/src/corelib/serialization/qjsonarray.h @@ -271,6 +271,11 @@ Q_CORE_EXPORT uint qHash(const QJsonArray &array, uint seed = 0); Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonArray &); #endif +#ifndef QT_NO_DATASTREAM +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QJsonArray &); +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QJsonArray &); +#endif + QT_END_NAMESPACE #endif // QJSONARRAY_H diff --git a/src/corelib/serialization/qjsondocument.cpp b/src/corelib/serialization/qjsondocument.cpp index 0cd86d3ded..179a87c699 100644 --- a/src/corelib/serialization/qjsondocument.cpp +++ b/src/corelib/serialization/qjsondocument.cpp @@ -47,6 +47,7 @@ #include "qjsonwriter_p.h" #include "qjsonparser_p.h" #include "qjson_p.h" +#include "qdatastream.h" QT_BEGIN_NAMESPACE @@ -657,4 +658,23 @@ QDebug operator<<(QDebug dbg, const QJsonDocument &o) } #endif +#ifndef QT_NO_DATASTREAM +QDataStream &operator<<(QDataStream &stream, const QJsonDocument &doc) +{ + stream << doc.toJson(QJsonDocument::Compact); + return stream; +} + +QDataStream &operator>>(QDataStream &stream, QJsonDocument &doc) +{ + QByteArray buffer; + stream >> buffer; + QJsonParseError parseError{}; + doc = QJsonDocument::fromJson(buffer, &parseError); + if (parseError.error && !buffer.isEmpty()) + stream.setStatus(QDataStream::ReadCorruptData); + return stream; +} +#endif + QT_END_NAMESPACE diff --git a/src/corelib/serialization/qjsondocument.h b/src/corelib/serialization/qjsondocument.h index b784890c54..a749439b7d 100644 --- a/src/corelib/serialization/qjsondocument.h +++ b/src/corelib/serialization/qjsondocument.h @@ -172,6 +172,11 @@ Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QJsonDocument) Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonDocument &); #endif +#ifndef QT_NO_DATASTREAM +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QJsonDocument &); +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QJsonDocument &); +#endif + QT_END_NAMESPACE #endif // QJSONDOCUMENT_H diff --git a/src/corelib/serialization/qjsonobject.cpp b/src/corelib/serialization/qjsonobject.cpp index 950bec535b..a9f25a119c 100644 --- a/src/corelib/serialization/qjsonobject.cpp +++ b/src/corelib/serialization/qjsonobject.cpp @@ -1320,4 +1320,21 @@ QDebug operator<<(QDebug dbg, const QJsonObject &o) } #endif +#ifndef QT_NO_DATASTREAM +QDataStream &operator<<(QDataStream &stream, const QJsonObject &object) +{ + QJsonDocument doc{object}; + stream << doc.toJson(QJsonDocument::Compact); + return stream; +} + +QDataStream &operator>>(QDataStream &stream, QJsonObject &object) +{ + QJsonDocument doc; + stream >> doc; + object = doc.object(); + return stream; +} +#endif + QT_END_NAMESPACE diff --git a/src/corelib/serialization/qjsonobject.h b/src/corelib/serialization/qjsonobject.h index be42d3747a..80fe6b2f3f 100644 --- a/src/corelib/serialization/qjsonobject.h +++ b/src/corelib/serialization/qjsonobject.h @@ -268,6 +268,11 @@ Q_CORE_EXPORT uint qHash(const QJsonObject &object, uint seed = 0); Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonObject &); #endif +#ifndef QT_NO_DATASTREAM +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QJsonObject &); +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QJsonObject &); +#endif + QT_END_NAMESPACE #endif // QJSONOBJECT_H diff --git a/src/corelib/serialization/qjsonvalue.cpp b/src/corelib/serialization/qjsonvalue.cpp index 2c04da4885..1fc610d7c7 100644 --- a/src/corelib/serialization/qjsonvalue.cpp +++ b/src/corelib/serialization/qjsonvalue.cpp @@ -45,6 +45,7 @@ #include <qvariant.h> #include <qstringlist.h> #include <qdebug.h> +#include "qdatastream.h" #ifndef QT_BOOTSTRAPPED # include <qcborarray.h> @@ -933,4 +934,78 @@ QDebug operator<<(QDebug dbg, const QJsonValue &o) } #endif +#ifndef QT_NO_DATASTREAM +QDataStream &operator<<(QDataStream &stream, const QJsonValue &v) +{ + quint8 type = v.t; + stream << type; + switch (type) { + case QJsonValue::Undefined: + case QJsonValue::Null: + break; + case QJsonValue::Bool: + stream << v.toBool(); + break; + case QJsonValue::Double: + stream << v.toDouble(); + break; + case QJsonValue::String: + stream << v.toString(); + break; + case QJsonValue::Array: + stream << v.toArray(); + break; + case QJsonValue::Object: + stream << v.toObject(); + break; + } + return stream; +} + +QDataStream &operator>>(QDataStream &stream, QJsonValue &v) +{ + quint8 type; + stream >> type; + switch (type) { + case QJsonValue::Undefined: + case QJsonValue::Null: + v = QJsonValue{QJsonValue::Type(type)}; + break; + case QJsonValue::Bool: { + bool b; + stream >> b; + v = QJsonValue(b); + break; + } case QJsonValue::Double: { + double d; + stream >> d; + v = QJsonValue{d}; + break; + } case QJsonValue::String: { + QString s; + stream >> s; + v = QJsonValue{s}; + break; + } + case QJsonValue::Array: { + QJsonArray a; + stream >> a; + v = QJsonValue{a}; + break; + } + case QJsonValue::Object: { + QJsonObject o; + stream >> o; + v = QJsonValue{o}; + break; + } + default: { + stream.setStatus(QDataStream::ReadCorruptData); + v = QJsonValue{QJsonValue::Undefined}; + } + } + return stream; +} +#endif + QT_END_NAMESPACE diff --git a/src/corelib/serialization/qjsonvalue.h b/src/corelib/serialization/qjsonvalue.h index d8e121524d..0339eb59f7 100644 --- a/src/corelib/serialization/qjsonvalue.h +++ b/src/corelib/serialization/qjsonvalue.h @@ -152,6 +152,7 @@ private: friend class QJsonObject; friend class QCborValue; friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonValue &); + friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QJsonValue &); QJsonValue(QJsonPrivate::Data *d, QJsonPrivate::Base *b, const QJsonPrivate::Value& v); void stringDataFromQStringHelper(const QString &string); @@ -218,7 +219,6 @@ private: uint index : 31; }; -#ifndef Q_QDOC // ### Qt 6: Get rid of these fake pointer classes class QJsonValuePtr { @@ -243,7 +243,6 @@ public: QJsonValueRef& operator*() { return valueRef; } QJsonValueRef* operator->() { return &valueRef; } }; -#endif Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QJsonValue) @@ -253,6 +252,11 @@ Q_CORE_EXPORT uint qHash(const QJsonValue &value, uint seed = 0); Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonValue &); #endif +#ifndef QT_NO_DATASTREAM +Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QJsonValue &); +Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QJsonValue &); +#endif + QT_END_NAMESPACE #endif // QJSONVALUE_H diff --git a/src/corelib/statemachine/qsignaltransition_p.h b/src/corelib/statemachine/qsignaltransition_p.h index 0666e600a4..b3de334677 100644 --- a/src/corelib/statemachine/qsignaltransition_p.h +++ b/src/corelib/statemachine/qsignaltransition_p.h @@ -70,7 +70,7 @@ public: void unregister(); void maybeRegister(); - virtual void callOnTransition(QEvent *e) override; + void callOnTransition(QEvent *e) override; const QObject *sender; QByteArray signal; diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 7388d496d9..ee3f7be279 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -1721,8 +1721,8 @@ QAbstractTransition *QStateMachinePrivate::createInitialTransition() const : QAbstractTransition() { setTargetStates(targets); } protected: - virtual bool eventTest(QEvent *) override { return true; } - virtual void onTransition(QEvent *) override {} + bool eventTest(QEvent *) override { return true; } + void onTransition(QEvent *) override {} }; QState *root = rootState(); diff --git a/src/corelib/thread/qresultstore.cpp b/src/corelib/thread/qresultstore.cpp index e0ce1b4b78..1b3bc20eca 100644 --- a/src/corelib/thread/qresultstore.cpp +++ b/src/corelib/thread/qresultstore.cpp @@ -43,6 +43,21 @@ QT_BEGIN_NAMESPACE namespace QtPrivate { +/*! + \class QtPrivate::ResultItem + \internal + */ + +/*! + \class QtPrivate::ResultIteratorBase + \internal + */ + +/*! + \class QtPrivate::ResultStoreBase + \internal + */ + ResultIteratorBase::ResultIteratorBase() : mapIterator(QMap<int, ResultItem>::const_iterator()), m_vectorIndex(0) { } ResultIteratorBase::ResultIteratorBase(QMap<int, ResultItem>::const_iterator _mapIterator, int _vectorIndex) diff --git a/src/corelib/thread/qresultstore.h b/src/corelib/thread/qresultstore.h index 39f0a6d1bb..1f29e8d187 100644 --- a/src/corelib/thread/qresultstore.h +++ b/src/corelib/thread/qresultstore.h @@ -56,7 +56,6 @@ QT_BEGIN_NAMESPACE either individually or in batches. */ -#ifndef Q_QDOC namespace QtPrivate { @@ -196,7 +195,6 @@ public: Q_DECLARE_TYPEINFO(QtPrivate::ResultItem, Q_PRIMITIVE_TYPE); -#endif //Q_QDOC QT_END_NAMESPACE diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index 8f2ad8c012..1d8621ad5a 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -3076,7 +3076,7 @@ bool QByteArray::endsWith(const char *str) const return qstrncmp(d->data() + d->size - len, str, len) == 0; } -/*! +/* Returns true if \a c is an uppercase Latin1 letter. \note The multiplication sign 0xD7 and the sz ligature 0xDF are not treated as uppercase Latin1. @@ -3112,7 +3112,7 @@ bool QByteArray::isUpper() const return true; } -/*! +/* Returns true if \a c is an lowercase Latin1 letter. \note The division sign 0xF7 is not treated as lowercase Latin1, but the small y dieresis 0xFF is. @@ -3882,9 +3882,7 @@ static qulonglong toIntegral_helper(const char *data, bool *ok, int base, qulong template <typename T> static inline T toIntegral_helper(const char *data, bool *ok, int base) { - // ### Qt6: use std::conditional<std::is_unsigned<T>::value, qulonglong, qlonglong>::type - const bool isUnsigned = T(0) < T(-1); - typedef typename QtPrivate::QConditional<isUnsigned, qulonglong, qlonglong>::Type Int64; + using Int64 = typename std::conditional<std::is_unsigned<T>::value, qulonglong, qlonglong>::type; #if defined(QT_CHECK_RANGE) if (base != 0 && (base < 2 || base > 36)) { diff --git a/src/corelib/tools/qbytearraylist.cpp b/src/corelib/tools/qbytearraylist.cpp index c815e766ab..d04555ed4d 100644 --- a/src/corelib/tools/qbytearraylist.cpp +++ b/src/corelib/tools/qbytearraylist.cpp @@ -150,4 +150,26 @@ QByteArray QtPrivate::QByteArrayList_join(const QByteArrayList *that, const char return res; } +/*! + \fn int QByteArrayList::indexOf(const char *needle, int from) const + + Returns the index position of the first occurrence of \a needle in + the list, searching forward from index position \a from. Returns + -1 if no item matched. + + \a needle must be NUL-terminated. + + This overload doesn't require creating a QByteArray, thus saving a + memory allocation and some CPU time. + + \since 5.13 + \overload +*/ + +int QtPrivate::QByteArrayList_indexOf(const QByteArrayList *that, const char *needle, int from) +{ + const auto it = std::find_if(that->begin() + from, that->end(), [needle](const QByteArray &item) { return item == needle; }); + return it == that->end() ? -1 : int(std::distance(that->begin(), it)); +} + QT_END_NAMESPACE diff --git a/src/corelib/tools/qbytearraylist.h b/src/corelib/tools/qbytearraylist.h index ed014dd157..d69e8bb54b 100644 --- a/src/corelib/tools/qbytearraylist.h +++ b/src/corelib/tools/qbytearraylist.h @@ -50,21 +50,22 @@ QT_BEGIN_NAMESPACE typedef QListIterator<QByteArray> QByteArrayListIterator; typedef QMutableListIterator<QByteArray> QMutableByteArrayListIterator; -#ifndef Q_QDOC +#ifndef Q_CLANG_QDOC typedef QList<QByteArray> QByteArrayList; namespace QtPrivate { QByteArray Q_CORE_EXPORT QByteArrayList_join(const QByteArrayList *that, const char *separator, int separatorLength); + int Q_CORE_EXPORT QByteArrayList_indexOf(const QByteArrayList *that, const char *needle, int from); } #endif -#ifdef Q_QDOC +#ifdef Q_CLANG_QDOC class QByteArrayList : public QList<QByteArray> #else template <> struct QListSpecialMethods<QByteArray> #endif { -#ifndef Q_QDOC +#ifndef Q_CLANG_QDOC protected: ~QListSpecialMethods() {} #endif @@ -76,6 +77,9 @@ public: inline QByteArray join(char sep) const { return QtPrivate::QByteArrayList_join(self(), &sep, 1); } + inline int indexOf(const char *needle, int from = 0) const + { return QtPrivate::QByteArrayList_indexOf(self(), needle, from); } + private: typedef QList<QByteArray> Self; Self *self() { return static_cast<Self *>(this); } diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index 816bd974eb..600bd1e0e5 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -2171,16 +2171,6 @@ int QTime::elapsed() const typedef QDateTimePrivate::QDateTimeShortData ShortData; typedef QDateTimePrivate::QDateTimeData QDateTimeData; -// Calls the platform variant of tzset -static void qt_tzset() -{ -#if defined(Q_OS_WIN) - _tzset(); -#else - tzset(); -#endif // Q_OS_WIN -} - // Returns the platform variant of timezone, i.e. the standard time offset // The timezone external variable is documented as always holding the // Standard Time offset as seconds west of Greenwich, i.e. UTC+01:00 is -3600 @@ -2278,7 +2268,7 @@ static qint64 qt_mktime(QDate *date, QTime *time, QDateTimePrivate::DaylightStat #if defined(Q_OS_WIN) int hh = local.tm_hour; #endif // Q_OS_WIN - time_t secsSinceEpoch = mktime(&local); + time_t secsSinceEpoch = qMkTime(&local); if (secsSinceEpoch != time_t(-1)) { *date = QDate(local.tm_year + 1900, local.tm_mon + 1, local.tm_mday); *time = QTime(local.tm_hour, local.tm_min, local.tm_sec, msec); @@ -2337,10 +2327,10 @@ static bool qt_localtime(qint64 msecsSinceEpoch, QDate *localDate, QTime *localT tm local; bool valid = false; - // localtime() is required to work as if tzset() was called before it. - // localtime_r() does not have this requirement, so make an explicit call. + // localtime() is specified to work as if it called tzset(). + // localtime_r() does not have this constraint, so make an explicit call. // The explicit call should also request the timezone info be re-parsed. - qt_tzset(); + qTzSet(); #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 @@ -2422,7 +2412,7 @@ static bool epochMSecsToLocalTime(qint64 msecs, QDate *localDate, QTime *localTi if (msecs < 0) { // Docs state any LocalTime before 1970-01-01 will *not* have any Daylight Time applied // Instead just use the standard offset from UTC to convert to UTC time - qt_tzset(); + qTzSet(); msecsToTime(msecs - qt_timezone() * 1000, localDate, localTime); if (daylightStatus) *daylightStatus = QDateTimePrivate::StandardTime; @@ -2485,7 +2475,7 @@ static qint64 localMSecsToEpochMSecs(qint64 localMsecs, } } else { // If we don't call mktime then need to call tzset to get offset - qt_tzset(); + qTzSet(); } // Time is clearly before 1970-01-01 so just use standard offset to convert qint64 utcMsecs = localMsecs + qt_timezone() * 1000; diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index ddc973cb37..4d5924a03e 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -620,13 +620,18 @@ static QLocalePrivate *c_private() */ /*! - Constructs a QSystemLocale object. The constructor will automatically - install this object as the system locale and remove any earlier installed - system locales. + Constructs a QSystemLocale object. + + The constructor will automatically install this object as the system locale, + if there's not one active. It also resets the flag that'll prompt + QLocale::system() to re-initialize its data, so that instantiating a + QSystemLocale transiently (doesn't install the transient as system locale if + there was one already and) triggers an update to the system locale's data. */ QSystemLocale::QSystemLocale() { - _systemLocale = this; + if (!_systemLocale) + _systemLocale = this; globalLocaleData.m_language_id = 0; } @@ -656,15 +661,17 @@ static const QSystemLocale *systemLocale() return QSystemLocale_globalSystemLocale(); } -void QLocalePrivate::updateSystemPrivate() +static void updateSystemPrivate() { - // this function is NOT thread-safe! + // This function is NOT thread-safe! + // It *should not* be called by anything but systemData() const QSystemLocale *sys_locale = systemLocale(); // tell the object that the system locale has changed. sys_locale->query(QSystemLocale::LocaleChanged, QVariant()); - globalLocaleData = *sys_locale->fallbackUiLocale().d->m_data; + // Populate global with fallback as basis: + globalLocaleData = *sys_locale->fallbackUiLocaleData(); QVariant res = sys_locale->query(QSystemLocale::LanguageId, QVariant()); if (!res.isNull()) { @@ -715,7 +722,7 @@ static const QLocaleData *systemData() static QBasicMutex systemDataMutex; systemDataMutex.lock(); if (globalLocaleData.m_language_id == 0) - QLocalePrivate::updateSystemPrivate(); + updateSystemPrivate(); systemDataMutex.unlock(); } @@ -1180,9 +1187,7 @@ static qulonglong toIntegral_helper(const QLocaleData *d, QStringView str, bool template <typename T> static inline T toIntegral_helper(const QLocalePrivate *d, QStringView str, bool *ok) { - // ### Qt6: use std::conditional<std::is_unsigned<T>::value, qulonglong, qlonglong>::type - const bool isUnsigned = T(0) < T(-1); - typedef typename QtPrivate::QConditional<isUnsigned, qulonglong, qlonglong>::Type Int64; + using Int64 = typename std::conditional<std::is_unsigned<T>::value, qulonglong, qlonglong>::type; // we select the right overload by the last, unused parameter Int64 val = toIntegral_helper(d->m_data, str, ok, d->m_numberOptions, Int64()); @@ -2353,7 +2358,6 @@ QString QLocale::toString(double i, char f, int prec) const QLocale QLocale::system() { - // this function is NOT thread-safe! QT_PREPEND_NAMESPACE(systemData)(); // trigger updating of the system data if necessary return QLocale(*systemLocalePrivate->data()); } @@ -3877,6 +3881,19 @@ QString QLocale::toCurrencyString(double value, const QString &symbol, int preci \sa formattedDataSize() */ +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +/*! + \obsolete + + Use the const version instead. +*/ +QString QLocale::formattedDataSize(qint64 bytes, int precision, DataSizeFormats format) +{ + const auto *that = this; + return that->formattedDataSize(bytes, precision, format); +} +#endif + /*! \since 5.10 @@ -3893,7 +3910,7 @@ QString QLocale::toCurrencyString(double value, const QString &symbol, int preci whereas \c DataSizeSIFormat uses the older SI quantifiers k, M, etc., and \c DataSizeTraditionalFormat abuses them. */ -QString QLocale::formattedDataSize(qint64 bytes, int precision, DataSizeFormats format) +QString QLocale::formattedDataSize(qint64 bytes, int precision, DataSizeFormats format) const { int power, base = 1000; if (!bytes) { diff --git a/src/corelib/tools/qlocale.h b/src/corelib/tools/qlocale.h index f3afb8c406..1fbd96c6d5 100644 --- a/src/corelib/tools/qlocale.h +++ b/src/corelib/tools/qlocale.h @@ -436,6 +436,11 @@ public: Cantonese = 357, Osage = 358, Tangut = 359, + Ido = 360, + Lojban = 361, + Sicilian = 362, + SouthernKurdish = 363, + WesternBalochi = 364, Afan = Oromo, Bhutani = Dzongkha, @@ -452,7 +457,7 @@ public: Twi = Akan, Uigur = Uighur, - LastLanguage = Tangut + LastLanguage = WesternBalochi }; enum Script { @@ -1061,7 +1066,10 @@ public: { return toCurrencyString(double(i), symbol, precision); } #endif +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) QString formattedDataSize(qint64 bytes, int precision = 2, DataSizeFormats format = DataSizeIecFormat); +#endif + QString formattedDataSize(qint64 bytes, int precision = 2, DataSizeFormats format = DataSizeIecFormat) const; QStringList uiLanguages() const; @@ -1091,6 +1099,7 @@ public: private: QLocale(QLocalePrivate &dd); friend class QLocalePrivate; + friend class QSystemLocale; friend Q_CORE_EXPORT uint qHash(const QLocale &key, uint seed) Q_DECL_NOTHROW; QSharedDataPointer<QLocalePrivate> d; diff --git a/src/corelib/tools/qlocale.qdoc b/src/corelib/tools/qlocale.qdoc index 76ca909d83..b852c10b8d 100644 --- a/src/corelib/tools/qlocale.qdoc +++ b/src/corelib/tools/qlocale.qdoc @@ -105,42 +105,80 @@ \value AnyLanguage \value C The "C" locale is identical in behavior to English/UnitedStates. + \value Abkhazian - \value Oromo \value Afan Obsolete, please use Oromo \value Afar \value Afrikaans + \value Aghem + \value Ahom Since Qt 5.7 + \value Akan + \value Akkadian Since Qt 5.1 \value Akoose Since Qt 5.3 \value Albanian + \value AmericanSignLanguage Since Qt 5.7 \value Amharic + \value AncientEgyptian Since Qt 5.1 + \value AncientGreek Since Qt 5.1 + \value AncientNorthArabian Since Qt 5.5 \value Arabic + \value Aragonese Since Qt 5.1 + \value Aramaic Since Qt 5.1 + \value ArdhamagadhiPrakrit Since Qt 5.7 \value Armenian \value Assamese + \value Asturian + \value Asu + \value Atsam \value Avaric + \value Avestan \value Aymara \value Azerbaijani + \value Bafia + \value Balinese Since Qt 5.1 + \value Bambara + \value Bamun Since Qt 5.1 + \value Basaa \value Bashkir \value Basque + \value Bassa Since Qt 5.5 + \value BatakToba Since Qt 5.1 + \value Belarusian + \value Bemba + \value Bena \value Bengali - \value Dzongkha + \value Bhojpuri Since Qt 5.7 \value Bhutani Obsolete, please use Dzongkha \value Bihari \value Bislama - \value Bosnian + \value Blin \value Bodo + \value Bosnian \value Breton + \value Buginese Since Qt 5.1 + \value Buhid Since Qt 5.1 \value Bulgarian \value Burmese - \value Belarusian \value Byelorussian Obsolete, please use Belarusian - \value Khmer \value Cambodian Obsolete, please use Khmer + \value Cantonese Since Qt 5.7 + \value Carian Since Qt 5.1 \value Catalan + \value CentralKurdish Since Qt 5.5 + \value CentralMoroccoTamazight + \value Chakma Since Qt 5.1 \value Chamorro \value Chechen + \value Cherokee + \value Chewa Obsolete, please use Nyanja + \value Chiga \value Chinese \value Church \value Chuvash + \value ClassicalMandaic Since Qt 5.1 + \value Colognian + \value CongoSwahili + \value Coptic Since Qt 5.1 \value Cornish \value Corsican \value Cree @@ -148,33 +186,58 @@ \value Czech \value Danish \value Divehi + \value Dogri Since Qt 5.1 + \value Duala \value Dutch + \value Dzongkha + \value EasternCham Since Qt 5.1 + \value EasternKayah Since Qt 5.1 + \value Embu \value English \value Esperanto \value Estonian + \value Etruscan Since Qt 5.1 + \value Ewe + \value Ewondo \value Faroese \value Fijian + \value Filipino \value Finnish \value French - \value WesternFrisian same as Frisian \value Frisian same as WesternFrisian + \value Friulian + \value Fulah + \value Ga \value Gaelic \value Galician + \value Ganda + \value Geez \value Georgian \value German + \value Gothic Since Qt 5.1 \value Greek \value Greenlandic \value Guarani \value Gujarati + \value Gusii \value Haitian + \value Hanunoo Since Qt 5.1 \value Hausa + \value Hawaiian \value Hebrew \value Herero + \value HieroglyphicLuwian Since Qt 5.7 \value Hindi \value HiriMotu + \value HmongNjua Since Qt 5.5 + \value Ho Since Qt 5.5 \value Hungarian \value Icelandic + \value Ido Since Qt 5.12 + \value Igbo + \value InariSami Since Qt 5.5 \value Indonesian + \value Ingush Since Qt 5.1 \value Interlingua \value Interlingue \value Inuktitut @@ -183,306 +246,244 @@ \value Italian \value Japanese \value Javanese + \value Jju + \value JolaFonyi + \value Kabuverdianu + \value Kabyle + \value Kako + \value Kalenjin + \value Kamba \value Kannada \value Kanuri \value Kashmiri \value Kazakh + \value Kenyang Since Qt 5.5 + \value Khmer + \value Kiche Since Qt 5.5 + \value Kikuyu \value Kinyarwanda \value Kirghiz \value Komi \value Kongo + \value Konkani \value Korean + \value Koro + \value KoyraboroSenni + \value KoyraChiini + \value Kpelle \value Kurdish - \value Rundi \value Kurundi Obsolete, please use Rundi \value Kwanyama + \value Kwasio \value Lakota Since Qt 5.3 + \value Langi \value Lao + \value LargeFloweryMiao Since Qt 5.1 \value Latin \value Latvian + \value Lepcha Since Qt 5.1 + \value Lezghian Since Qt 5.5 \value Limburgish + \value Limbu Since Qt 5.1 + \value LinearA Since Qt 5.5 \value Lingala + \value Lisu Since Qt 5.1 + \value LiteraryChinese Since Qt 5.7 \value Lithuanian + \value Lojban Since Qt 5.12 + \value LowerSorbian Since Qt 5.5 + \value LowGerman \value LubaKatanga + \value LuleSami Since Qt 5.5 + \value Luo + \value Lu Since Qt 5.1 \value Luxembourgish - \value Marshallese + \value Luyia + \value Lycian Since Qt 5.1 + \value Lydian Since Qt 5.1 \value Macedonian + \value Machame + \value Maithili Since Qt 5.5 + \value MakhuwaMeetto + \value Makonde \value Malagasy \value Malay \value Malayalam \value Maltese + \value Mandingo Since Qt 5.1 + \value ManichaeanMiddlePersian Since Qt 5.5 + \value Manipuri Since Qt 5.1 \value Manx \value Maori + \value Mapuche Since Qt 5.5 \value Marathi + \value Marshallese + \value Masai + \value Mazanderani Since Qt 5.7 + \value Mende Since Qt 5.5 + \value Meroitic Since Qt 5.1 + \value Meru + \value Meta + \value Mohawk Since Qt 5.5 \value Moldavian Obsolete, please use Romanian \value Mongolian + \value Mono Since Qt 5.5 + \value Morisyen + \value Mru Since Qt 5.7 + \value Mundang + \value Nama \value NauruLanguage \value Navaho \value Ndonga \value Nepali - \value Norwegian same as NorwegianBokmal + \value Newari Since Qt 5.7 + \value Ngiemboon + \value Ngomba + \value Nko Since Qt 5.5 + \value NorthernLuri Since Qt 5.7 + \value NorthernSami + \value NorthernSotho + \value NorthernThai Since Qt 5.1 + \value NorthNdebele \value NorwegianBokmal same as Norwegian \value NorwegianNynorsk + \value Norwegian same as NorwegianBokmal + \value Nuer + \value Nyanja + \value Nyankole \value Occitan \value Ojibwa + \value OldIrish Since Qt 5.1 + \value OldNorse Since Qt 5.1 + \value OldPersian Since Qt 5.1 + \value OldTurkish Since Qt 5.1 \value Oriya + \value Oromo + \value Osage Since Qt 5.7 \value Ossetic + \value Pahlavi Since Qt 5.1 + \value Palauan Since Qt 5.7 \value Pali + \value Papiamento Since Qt 5.7 + \value Parthian Since Qt 5.1 \value Pashto \value Persian + \value Phoenician Since Qt 5.1 \value Polish \value Portuguese + \value PrakritLanguage Since Qt 5.1 + \value Prussian Since Qt 5.5 \value Punjabi \value Quechua - \value Romansh + \value Rejang Since Qt 5.1 \value RhaetoRomance Obsolete, please use Romansh \value Romanian + \value Romansh + \value Rombo + \value Rundi \value Russian + \value Rwa + \value Sabaean Since Qt 5.1 + \value Saho + \value Sakha + \value Samaritan Since Qt 5.1 + \value Samburu \value Samoan \value Sango + \value Sangu \value Sanskrit + \value Santali Since Qt 5.1 + \value Saraiki Since Qt 5.7 \value Sardinian + \value Saurashtra Since Qt 5.1 + \value Sena \value Serbian \value SerboCroatian Obsolete, please use Serbian - \value SouthernSotho - \value Tswana + \value Shambala \value Shona + \value SichuanYi + \value Sicilian Since Qt 5.12 + \value Sidamo \value Sindhi \value Sinhala - \value Swati + \value SkoltSami Since Qt 5.5 \value Slovak \value Slovenian + \value Soga \value Somali + \value Sora Since Qt 5.1 + \value SouthernKurdish Since Qt 5.12 + \value SouthernSami Since Qt 5.5 + \value SouthernSotho + \value SouthNdebele \value Spanish \value StandardMoroccanTamazight Since Qt 5.3 \value Sundanese \value Swahili + \value Swati \value Swedish + \value SwissGerman + \value Sylheti Since Qt 5.1 + \value Syriac + \value Tachelhit \value Tagalog Obsolete, please use Filipino + \value Tagbanwa Since Qt 5.1 \value Tahitian + \value TaiDam Since Qt 5.1 + \value TaiNua Since Qt 5.1 + \value Taita \value Tajik \value Tamil + \value Tangut Since Qt 5.7 + \value Taroko + \value Tasawaq \value Tatar + \value TedimChin Since Qt 5.5 \value Telugu + \value Teso \value Thai \value Tibetan + \value Tigre \value Tigrinya + \value TokelauLanguage Since Qt 5.7 + \value TokPisin Since Qt 5.7 \value Tongan \value Tsonga + \value Tswana \value Turkish \value Turkmen + \value TuvaluLanguage Since Qt 5.7 \value Twi Obsolete, please use Akan + \value Tyap + \value Ugaritic Since Qt 5.1 \value Uighur \value Uigur Obsolete, please use Uighur \value Ukrainian + \value UncodedLanguages Since Qt 5.7 + \value UpperSorbian Since Qt 5.5 \value Urdu \value Uzbek + \value Vai + \value Venda \value Vietnamese \value Volapuk + \value Vunjo + \value Walamo \value Walloon + \value Walser + \value Warlpiri Since Qt 5.5 \value Welsh + \value WesternBalochi Since Qt 5.12 + \value WesternFrisian same as Frisian \value Wolof \value Xhosa + \value Yangben \value Yiddish \value Yoruba + \value Zarma \value Zhuang \value Zulu - \value Bosnian - \value Divehi - \value Manx - \value Cornish - \value Akan - \value Konkani - \value Ga - \value Igbo - \value Kamba - \value Syriac - \value Blin - \value Geez - \value Koro - \value Sidamo - \value Atsam - \value Tigre - \value Jju - \value Friulian - \value Venda - \value Ewe - \value Walamo - \value Hawaiian - \value Tyap - \value Nyanja - \value Chewa Obsolete, please use Nyanja - \value Filipino - \value SwissGerman - \value SichuanYi - \value Kpelle - \value LowGerman - \value SouthNdebele - \value NorthernSotho - \value NorthernSami - \value Taroko - \value Gusii - \value Taita - \value Fulah - \value Kikuyu - \value Samburu - \value Sena - \value NorthNdebele - \value Rombo - \value Tachelhit - \value Kabyle - \value Nyankole - \value Bena - \value Vunjo - \value Bambara - \value Embu - \value Cherokee - \value Morisyen - \value Makonde - \value Langi - \value Ganda - \value Bemba - \value Kabuverdianu - \value Meru - \value Kalenjin - \value Nama - \value Machame - \value Colognian - \value Masai - \value Soga - \value Luyia - \value Asu - \value Teso - \value Saho - \value KoyraChiini - \value Rwa - \value Luo - \value Chiga - \value CentralMoroccoTamazight - \value KoyraboroSenni - \value Shambala - \value Aghem - \value Basaa - \value Zarma - \value Duala - \value JolaFonyi - \value Ewondo - \value Bafia - \value MakhuwaMeetto - \value Mundang - \value Kwasio - \value Nuer - \value Sakha - \value Sangu - \value CongoSwahili - \value Tasawaq - \value Vai - \value Walser - \value Yangben - \value Avestan - \value Asturian - \value Ngomba - \value Kako - \value Meta - \value Ngiemboon - \value Aragonese - \value Akkadian - \value AncientEgyptian - \value AncientGreek - \value Aramaic - \value Balinese - \value Bamun - \value BatakToba - \value Buginese - \value Buhid - \value Carian - \value Chakma - \value ClassicalMandaic - \value Coptic - \value Dogri - \value EasternCham - \value EasternKayah - \value Etruscan - \value Gothic - \value Hanunoo - \value Ingush - \value LargeFloweryMiao - \value Lepcha - \value Limbu - \value Lisu - \value Lu - \value Lycian - \value Lydian - \value Mandingo - \value Manipuri - \value Meroitic - \value NorthernThai - \value OldIrish - \value OldNorse - \value OldPersian - \value OldTurkish - \value Pahlavi - \value Parthian - \value Phoenician - \value PrakritLanguage - \value Rejang - \value Sabaean - \value Samaritan - \value Santali - \value Saurashtra - \value Sora - \value Sylheti - \value Tagbanwa - \value TaiDam - \value TaiNua - \value Ugaritic - \value Mapuche Since Qt 5.5 - \value CentralKurdish Since Qt 5.5 - \value LowerSorbian Since Qt 5.5 - \value UpperSorbian Since Qt 5.5 - \value Kenyang Since Qt 5.5 - \value Mohawk Since Qt 5.5 - \value Nko Since Qt 5.5 - \value Prussian Since Qt 5.5 - \value Kiche Since Qt 5.5 - \value SouthernSami Since Qt 5.5 - \value LuleSami Since Qt 5.5 - \value InariSami Since Qt 5.5 - \value SkoltSami Since Qt 5.5 - \value Warlpiri Since Qt 5.5 - \value ManichaeanMiddlePersian Since Qt 5.5 - \value Mende Since Qt 5.5 - \value AncientNorthArabian Since Qt 5.5 - \value LinearA Since Qt 5.5 - \value HmongNjua Since Qt 5.5 - \value Ho Since Qt 5.5 - \value Lezghian Since Qt 5.5 - \value Bassa Since Qt 5.5 - \value Mono Since Qt 5.5 - \value TedimChin Since Qt 5.5 - \value Maithili Since Qt 5.5 - \value LowerSorbian Since Qt 5.5 - \value UpperSorbian Since Qt 5.5 - \value Ahom Since Qt 5.7 - \value AmericanSignLanguage Since Qt 5.7 - \value ArdhamagadhiPrakrit Since Qt 5.7 - \value Bhojpuri Since Qt 5.7 - \value Cantonese Since Qt 5.7 - \value HieroglyphicLuwian Since Qt 5.7 - \value LiteraryChinese Since Qt 5.7 - \value Mazanderani Since Qt 5.7 - \value Mru Since Qt 5.7 - \value Newari Since Qt 5.7 - \value NorthernLuri Since Qt 5.7 - \value Osage Since Qt 5.7 - \value Palauan Since Qt 5.7 - \value Papiamento Since Qt 5.7 - \value Saraiki Since Qt 5.7 - \value Tangut Since Qt 5.7 - \value TokelauLanguage Since Qt 5.7 - \value TokPisin Since Qt 5.7 - \value TuvaluLanguage Since Qt 5.7 - \value UncodedLanguages Since Qt 5.7 + \omitvalue LastLanguage \sa language(), languageToString() @@ -494,7 +495,9 @@ This enumerated type is used to specify a country. \value AnyCountry + \value Afghanistan + \value AlandIslands \value Albania \value Algeria \value AmericanSamoa @@ -506,6 +509,7 @@ \value Argentina \value Armenia \value Aruba + \value AscensionIsland \value Australia \value Austria \value Azerbaijan @@ -520,11 +524,13 @@ \value Bermuda \value Bhutan \value Bolivia + \value Bonaire \value BosniaAndHerzegowina \value Botswana \value BouvetIsland \value Brazil \value BritishIndianOceanTerritory + \value BritishVirginIslands \value Brunei \value Bulgaria \value BurkinaFaso @@ -536,6 +542,7 @@ \value CapeVerde \value CaymanIslands \value CentralAfricanRepublic + \value CeutaAndMelilla \value Chad \value Chile \value China @@ -544,18 +551,19 @@ \value CocosIslands \value Colombia \value Comoros - \value CongoKinshasa \value CongoBrazzaville - \value DemocraticRepublicOfCongo Obsolete, please use CongoKinshasa - \value PeoplesRepublicOfCongo Obsolete, please use CongoBrazzaville + \value CongoKinshasa \value CookIslands \value CostaRica - \value IvoryCoast \value Croatia \value Cuba + \value CuraSao \value Cyprus \value CzechRepublic + \value DemocraticRepublicOfCongo Obsolete, please use CongoKinshasa + \value DemocraticRepublicOfKorea Obsolete, please use NorthKorea \value Denmark + \value DiegoGarcia \value Djibouti \value Dominica \value DominicanRepublic @@ -604,19 +612,18 @@ \value Iran \value Iraq \value Ireland + \value IsleOfMan \value Israel \value Italy + \value IvoryCoast \value Jamaica \value Japan + \value Jersey \value Jordan \value Kazakhstan \value Kenya \value Kiribati - \value NorthKorea - \value SouthKorea - \value DemocraticRepublicOfKorea Obsolete, please use NorthKorea - \value RepublicOfKorea Obsolete, please use SouthKorea - \value Kosovo + \value Kosovo Since Qt 5.2 \value Kuwait \value Kyrgyzstan \value Laos @@ -648,6 +655,7 @@ \value Moldova \value Monaco \value Mongolia + \value Montenegro \value Montserrat \value Morocco \value Mozambique @@ -664,6 +672,7 @@ \value Niue \value NorfolkIsland \value NorthernMarianaIslands + \value NorthKorea \value Norway \value Oman \value OutlyingOceania Since Qt 5.7 @@ -673,6 +682,7 @@ \value Panama \value PapuaNewGuinea \value Paraguay + \value PeoplesRepublicOfCongo Obsolete, please use CongoBrazzaville \value Peru \value Philippines \value Pitcairn @@ -680,32 +690,39 @@ \value Portugal \value PuertoRico \value Qatar + \value RepublicOfKorea Obsolete, please use SouthKorea \value Reunion \value Romania - \value Russia same as RussianFederation \value RussianFederation same as Russia + \value Russia same as RussianFederation \value Rwanda + \value SaintBarthelemy + \value SaintHelena \value SaintKittsAndNevis \value SaintLucia + \value SaintMartin + \value SaintPierreAndMiquelon \value SaintVincentAndTheGrenadines \value Samoa \value SanMarino \value SaoTomeAndPrincipe \value SaudiArabia \value Senegal + \value Serbia \value Seychelles \value SierraLeone \value Singapore + \value SintMaarten \value Slovakia \value Slovenia \value SolomonIslands \value Somalia \value SouthAfrica \value SouthGeorgiaAndTheSouthSandwichIslands + \value SouthKorea + \value SouthSudan \value Spain \value SriLanka - \value SaintHelena - \value SaintPierreAndMiquelon \value Sudan \value Suriname \value SvalbardAndJanMayenIslands @@ -723,6 +740,7 @@ \value Tokelau Obsolete, please use TokelauCountry \value Tonga \value TrinidadAndTobago + \value TristanDaCunha \value Tunisia \value Turkey \value Turkmenistan @@ -735,35 +753,20 @@ \value UnitedKingdom \value UnitedStates \value UnitedStatesMinorOutlyingIslands + \value UnitedStatesVirginIslands \value Uruguay \value Uzbekistan \value Vanuatu \value VaticanCityState \value Venezuela \value Vietnam - \value BritishVirginIslands - \value UnitedStatesVirginIslands \value WallisAndFutunaIslands \value WesternSahara \value World Since Qt 5.12 \value Yemen \value Zambia \value Zimbabwe - \value Montenegro - \value Serbia - \value SaintBarthelemy - \value SaintMartin - \value AscensionIsland - \value AlandIslands - \value DiegoGarcia - \value CeutaAndMelilla - \value IsleOfMan - \value Jersey - \value TristanDaCunha - \value SouthSudan - \value CuraSao - \value Bonaire - \value SintMaarten + \omitvalue LastCountry \sa country(), countryToString() @@ -775,135 +778,136 @@ This enumerated type is used to specify a script. \value AnyScript + \value AdlamScript Since Qt 5.7 \value AhomScript Since Qt 5.7 \value AnatolianHieroglyphsScript Since Qt 5.7 \value ArabicScript \value ArmenianScript - \value AvestanScript - \value BalineseScript - \value BamumScript + \value AvestanScript Since Qt 5.1 + \value BalineseScript Since Qt 5.1 + \value BamumScript Since Qt 5.1 \value BassaVahScript Since Qt 5.5 - \value BatakScript + \value BatakScript Since Qt 5.1 \value BengaliScript \value BhaiksukiScript Since Qt 5.7 - \value BopomofoScript - \value BrahmiScript - \value BrailleScript - \value BugineseScript - \value BuhidScript - \value CanadianAboriginalScript - \value CarianScript + \value BopomofoScript Since Qt 5.1 + \value BrahmiScript Since Qt 5.1 + \value BrailleScript Since Qt 5.1 + \value BugineseScript Since Qt 5.1 + \value BuhidScript Since Qt 5.1 + \value CanadianAboriginalScript Since Qt 5.1 + \value CarianScript Since Qt 5.1 \value CaucasianAlbanianScript Since Qt 5.5 - \value ChakmaScript - \value ChamScript + \value ChakmaScript Since Qt 5.1 + \value ChamScript Since Qt 5.1 \value CherokeeScript - \value CopticScript - \value CypriotScript + \value CopticScript Since Qt 5.1 + \value CuneiformScript Since Qt 5.1 + \value CypriotScript Since Qt 5.1 \value CyrillicScript - \value DeseretScript + \value DeseretScript Since Qt 5.1 \value DevanagariScript \value DuployanScript Since Qt 5.5 - \value EgyptianHieroglyphsScript + \value EgyptianHieroglyphsScript Since Qt 5.1 \value ElbasanScript Since Qt 5.5 \value EthiopicScript - \value FraserScript + \value FraserScript Since Qt 5.1 \value GeorgianScript - \value GlagoliticScript - \value GothicScript + \value GlagoliticScript Since Qt 5.1 + \value GothicScript Since Qt 5.1 \value GranthaScript Since Qt 5.5 \value GreekScript \value GujaratiScript \value GurmukhiScript - \value HanScript - \value HangulScript - \value HanunooScript + \value HangulScript Since Qt 5.1 + \value HanScript Since Qt 5.1 + \value HanunooScript Since Qt 5.1 \value HanWithBopomofoScript Since Qt 5.7 \value HatranScript Since Qt 5.7 \value HebrewScript - \value HiraganaScript - \value ImperialAramaicScript - \value InscriptionalPahlaviScript - \value InscriptionalParthianScript + \value HiraganaScript Since Qt 5.1 + \value ImperialAramaicScript Since Qt 5.1 + \value InscriptionalPahlaviScript Since Qt 5.1 + \value InscriptionalParthianScript Since Qt 5.1 \value JamoScript Since Qt 5.7 \value JapaneseScript - \value JavaneseScript - \value KaithiScript + \value JavaneseScript Since Qt 5.1 + \value KaithiScript Since Qt 5.1 \value KannadaScript - \value KatakanaScript - \value KayahLiScript - \value KharoshthiScript - \value KhmerScript + \value KatakanaScript Since Qt 5.1 + \value KayahLiScript Since Qt 5.1 + \value KharoshthiScript Since Qt 5.1 + \value KhmerScript Since Qt 5.1 \value KhojkiScript Since Qt 5.5 \value KhudawadiScript Since Qt 5.5 \value KoreanScript - \value LannaScript + \value LannaScript Since Qt 5.1 \value LaoScript \value LatinScript - \value LepchaScript - \value LimbuScript + \value LepchaScript Since Qt 5.1 + \value LimbuScript Since Qt 5.1 \value LinearAScript Since Qt 5.5 - \value LinearBScript - \value LycianScript - \value LydianScript + \value LinearBScript Since Qt 5.1 + \value LycianScript Since Qt 5.1 + \value LydianScript Since Qt 5.1 \value MahajaniScript Since Qt 5.5 \value MalayalamScript - \value MandaeanScript + \value MandaeanScript Since Qt 5.1 \value ManichaeanScript Since Qt 5.5 \value MarchenScript Since Qt 5.7 - \value MeiteiMayekScript + \value MeiteiMayekScript Since Qt 5.1 \value MendeKikakuiScript Since Qt 5.5 - \value MeroiticScript - \value MeroiticCursiveScript + \value MeroiticCursiveScript Since Qt 5.1 + \value MeroiticScript Since Qt 5.1 \value ModiScript Since Qt 5.5 \value MongolianScript \value MroScript Since Qt 5.5 \value MultaniScript Since Qt 5.7 \value MyanmarScript \value NabataeanScript Since Qt 5.5 - \value NkoScript \value NewaScript Since Qt 5.7 - \value NewTaiLueScript - \value OghamScript - \value OlChikiScript - \value OldItalicScript + \value NewTaiLueScript Since Qt 5.1 + \value NkoScript Since Qt 5.1 + \value OghamScript Since Qt 5.1 + \value OlChikiScript Since Qt 5.1 \value OldHungarianScript Since Qt 5.7 + \value OldItalicScript Since Qt 5.1 \value OldNorthArabianScript Since Qt 5.5 \value OldPermicScript Since Qt 5.5 - \value OldPersianScript - \value OldSouthArabianScript + \value OldPersianScript Since Qt 5.1 + \value OldSouthArabianScript Since Qt 5.1 \value OriyaScript - \value OrkhonScript + \value OrkhonScript Since Qt 5.1 \value OsageScript Since Qt 5.7 - \value OsmanyaScript + \value OsmanyaScript Since Qt 5.1 \value PahawhHmongScript Since Qt 5.5 \value PalmyreneScript Since Qt 5.5 \value PauCinHauScript Since Qt 5.5 - \value PhagsPaScript - \value PhoenicianScript - \value PollardPhoneticScript + \value PhagsPaScript Since Qt 5.1 + \value PhoenicianScript Since Qt 5.1 + \value PollardPhoneticScript Since Qt 5.1 \value PsalterPahlaviScript Since Qt 5.5 - \value RejangScript - \value RunicScript - \value SamaritanScript - \value SaurashtraScript - \value SharadaScript - \value ShavianScript + \value RejangScript Since Qt 5.1 + \value RunicScript Since Qt 5.1 + \value SamaritanScript Since Qt 5.1 + \value SaurashtraScript Since Qt 5.1 + \value SharadaScript Since Qt 5.1 + \value ShavianScript Since Qt 5.1 \value SiddhamScript Since Qt 5.5 \value SignWritingScript Since Qt 5.7 - \value SimplifiedHanScript same as SimplifiedChineseScript \value SimplifiedChineseScript same as SimplifiedHanScript + \value SimplifiedHanScript same as SimplifiedChineseScript \value SinhalaScript - \value SoraSompengScript - \value CuneiformScript - \value SundaneseScript - \value SylotiNagriScript + \value SoraSompengScript Since Qt 5.1 + \value SundaneseScript Since Qt 5.1 + \value SylotiNagriScript Since Qt 5.1 \value SyriacScript - \value TagalogScript - \value TagbanwaScript - \value TaiLeScript - \value TaiVietScript - \value TakriScript + \value TagalogScript Since Qt 5.1 + \value TagbanwaScript Since Qt 5.1 + \value TaiLeScript Since Qt 5.1 + \value TaiVietScript Since Qt 5.1 + \value TakriScript Since Qt 5.1 \value TamilScript \value TangutScript Since Qt 5.7 \value TeluguScript @@ -912,12 +916,13 @@ \value TibetanScript \value TifinaghScript \value TirhutaScript Since Qt 5.5 - \value TraditionalHanScript same as TraditionalChineseScript \value TraditionalChineseScript same as TraditionalHanScript - \value UgariticScript + \value TraditionalHanScript same as TraditionalChineseScript + \value UgariticScript Since Qt 5.1 \value VaiScript \value VarangKshitiScript Since Qt 5.5 \value YiScript + \omitvalue LastScript \sa script(), scriptToString(), languageToString() diff --git a/src/corelib/tools/qlocale_data_p.h b/src/corelib/tools/qlocale_data_p.h index 507afdcecd..58e71e1dcc 100644 --- a/src/corelib/tools/qlocale_data_p.h +++ b/src/corelib/tools/qlocale_data_p.h @@ -77,7 +77,7 @@ static const int ImperialMeasurementSystemsCount = // GENERATED PART STARTS HERE /* - This part of the file was generated on 2018-10-19 from the + This part of the file was generated on 2018-11-08 from the Common Locale Data Repository v34 http://www.unicode.org/cldr/ @@ -122,6 +122,7 @@ static const QLocaleId likely_subtags[] = { { 195, 0, 0 }, { 195, 7, 239 }, // bem -> bem_Latn_ZM { 186, 0, 0 }, { 186, 7, 210 }, // bez -> bez_Latn_TZ { 20, 0, 0 }, { 20, 2, 33 }, // bg -> bg_Cyrl_BG + { 364, 0, 0 }, { 364, 1, 163 }, // bgn -> bgn_Arab_PK { 343, 0, 0 }, { 343, 13, 100 }, // bho -> bho_Deva_IN { 18, 0, 0 }, { 18, 7, 229 }, // bi -> bi_Latn_VU { 270, 0, 0 }, { 270, 7, 170 }, // bku -> bku_Latn_PH @@ -224,10 +225,12 @@ static const QLocaleId likely_subtags[] = { { 168, 0, 0 }, { 168, 34, 44 }, // ii -> ii_Yiii_CN { 56, 0, 0 }, { 56, 7, 225 }, // ik -> ik_Latn_US { 281, 0, 0 }, { 281, 2, 178 }, // inh -> inh_Cyrl_RU + { 360, 0, 0 }, { 360, 7, 260 }, // io -> io_Latn_001 { 51, 0, 0 }, { 51, 7, 99 }, // is -> is_Latn_IS { 58, 0, 0 }, { 58, 7, 106 }, // it -> it_Latn_IT { 55, 0, 0 }, { 55, 44, 38 }, // iu -> iu_Cans_CA { 59, 0, 0 }, { 59, 19, 108 }, // ja -> ja_Jpan_JP + { 361, 0, 0 }, { 361, 7, 260 }, // jbo -> jbo_Latn_001 { 257, 0, 0 }, { 257, 7, 37 }, // jgo -> jgo_Latn_CM { 200, 0, 0 }, { 200, 7, 210 }, // jmc -> jmc_Latn_TZ { 60, 0, 0 }, { 60, 7, 101 }, // jv -> jv_Latn_ID @@ -385,10 +388,12 @@ static const QLocaleId likely_subtags[] = { { 305, 0, 0 }, { 305, 90, 100 }, // saz -> saz_Saur_IN { 249, 0, 0 }, { 249, 7, 210 }, // sbp -> sbp_Latn_TZ { 115, 0, 0 }, { 115, 7, 106 }, // sc -> sc_Latn_IT + { 362, 0, 0 }, { 362, 7, 106 }, // scn -> scn_Latn_IT { 105, 0, 0 }, { 105, 1, 163 }, // sd -> sd_Arab_PK { 105, 13, 0 }, { 105, 13, 100 }, // sd_Deva -> sd_Deva_IN { 105, 111, 0 }, { 105, 111, 100 }, // sd_Khoj -> sd_Khoj_IN { 105, 125, 0 }, { 105, 125, 100 }, // sd_Sind -> sd_Sind_IN + { 363, 0, 0 }, { 363, 1, 102 }, // sdh -> sdh_Arab_IR { 173, 0, 0 }, { 173, 7, 161 }, // se -> se_Latn_NO { 180, 0, 0 }, { 180, 7, 146 }, // seh -> seh_Latn_MZ { 213, 0, 0 }, { 213, 7, 132 }, // ses -> ses_Latn_ML @@ -1252,6 +1257,11 @@ static const quint16 locale_index[] = { 574, // Cantonese 0, // Osage 0, // Tangut + 576, // Ido + 577, // Lojban + 578, // Sicilian + 579, // Southern Kurdish + 580, // Western Balochi 0 // trailing 0 }; @@ -1592,13 +1602,13 @@ static const QLocaleData locale_data[] = { { 98, 7, 41, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 415,8 , 97,16 , 37,5 , 8,10 , 16581,48 , 16629,91 , 16720,24 , 16581,48 , 16629,91 , 16720,24 , 8692,28 , 8720,66 , 8786,14 , 8692,28 , 8720,66 , 8786,14 , 226,2 , 216,2 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 11499,25 , 4,4 , 36,5 , 3506,5 , 3511,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}, 121,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 , 1067,7 , 1074,20 , 37,5 , 8,10 , 16744,48 , 16792,81 , 12698,24 , 16744,48 , 16792,81 , 12698,24 , 8800,28 , 8828,52 , 8880,14 , 8800,28 , 8828,52 , 8880,14 , 228,9 , 218,8 , 803,7 , 5,17 , 22,23 , {82,83,68}, 288,3 , 11524,58 , 13,5 , 4,0 , 3533,6 , 3539,6 , 0, 0, 1, 6, 7 }, // Serbian/Cyrillic/Serbia - { 100, 2, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 116,7 , 116,7 , 1067,7 , 1074,20 , 37,5 , 8,10 , 16873,50 , 16792,81 , 12698,24 , 16744,48 , 16792,81 , 12698,24 , 8894,26 , 8920,55 , 8880,14 , 8894,26 , 8920,55 , 8880,14 , 237,11 , 218,8 , 803,7 , 5,17 , 22,23 , {66,65,77}, 291,2 , 11582,174 , 13,5 , 4,0 , 3533,6 , 3545,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 , 1067,7 , 1074,20 , 37,5 , 8,10 , 16923,58 , 16792,81 , 12698,24 , 16923,58 , 16792,81 , 12698,24 , 8975,33 , 8920,55 , 8880,14 , 8975,33 , 8920,55 , 8880,14 , 237,11 , 218,8 , 803,7 , 5,17 , 22,23 , {69,85,82}, 14,1 , 11756,23 , 13,5 , 4,0 , 3533,6 , 3564,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 , 1067,7 , 1074,20 , 37,5 , 8,10 , 16923,58 , 16792,81 , 12698,24 , 16923,58 , 16792,81 , 12698,24 , 8975,33 , 8828,52 , 8880,14 , 8975,33 , 8828,52 , 8880,14 , 228,9 , 218,8 , 803,7 , 5,17 , 22,23 , {69,85,82}, 14,1 , 11756,23 , 13,5 , 4,0 , 3533,6 , 3573,6 , 2, 1, 1, 6, 7 }, // Serbian/Cyrillic/Kosovo - { 100, 7, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 163,7 , 163,7 , 1067,7 , 1074,20 , 37,5 , 8,10 , 16981,50 , 17031,81 , 9742,24 , 17112,48 , 17031,81 , 9742,24 , 9008,26 , 9034,57 , 2102,14 , 9008,26 , 9034,57 , 2102,14 , 248,11 , 226,8 , 296,7 , 5,17 , 22,23 , {66,65,77}, 144,2 , 11779,174 , 13,5 , 4,0 , 3579,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 , 1067,7 , 1074,20 , 37,5 , 8,10 , 17160,58 , 17031,81 , 9742,24 , 17160,58 , 17031,81 , 9742,24 , 9091,33 , 9034,57 , 2102,14 , 9091,33 , 9034,57 , 2102,14 , 248,11 , 226,8 , 296,7 , 5,17 , 22,23 , {69,85,82}, 14,1 , 11953,23 , 13,5 , 4,0 , 3579,6 , 3585,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 , 1067,7 , 1074,20 , 37,5 , 8,10 , 17112,48 , 17031,81 , 9742,24 , 17112,48 , 17031,81 , 9742,24 , 9124,28 , 9152,54 , 2102,14 , 9124,28 , 9152,54 , 2102,14 , 259,9 , 226,8 , 296,7 , 5,17 , 22,23 , {82,83,68}, 288,3 , 11976,58 , 13,5 , 4,0 , 3579,6 , 3594,6 , 0, 0, 1, 6, 7 }, // Serbian/Latin/Serbia - { 100, 7, 257, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 163,7 , 163,7 , 1067,7 , 1074,20 , 37,5 , 8,10 , 17160,58 , 17031,81 , 9742,24 , 17160,58 , 17031,81 , 9742,24 , 9091,33 , 9152,54 , 2102,14 , 9091,33 , 9152,54 , 2102,14 , 259,9 , 226,8 , 296,7 , 5,17 , 22,23 , {69,85,82}, 14,1 , 11953,23 , 13,5 , 4,0 , 3579,6 , 3600,6 , 2, 1, 1, 6, 7 }, // Serbian/Latin/Kosovo + { 100, 7, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 163,7 , 163,7 , 1067,7 , 1074,20 , 37,5 , 8,10 , 16873,50 , 16923,81 , 9742,24 , 17004,48 , 16923,81 , 9742,24 , 8894,26 , 8920,57 , 2102,14 , 8894,26 , 8920,57 , 2102,14 , 237,11 , 226,8 , 296,7 , 5,17 , 22,23 , {66,65,77}, 144,2 , 11582,174 , 13,5 , 4,0 , 3545,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 , 1067,7 , 1074,20 , 37,5 , 8,10 , 17052,58 , 16923,81 , 9742,24 , 17052,58 , 16923,81 , 9742,24 , 8977,33 , 8920,57 , 2102,14 , 8977,33 , 8920,57 , 2102,14 , 237,11 , 226,8 , 296,7 , 5,17 , 22,23 , {69,85,82}, 14,1 , 11756,23 , 13,5 , 4,0 , 3545,6 , 3551,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 , 1067,7 , 1074,20 , 37,5 , 8,10 , 17004,48 , 16923,81 , 9742,24 , 17004,48 , 16923,81 , 9742,24 , 9010,28 , 9038,54 , 2102,14 , 9010,28 , 9038,54 , 2102,14 , 248,9 , 226,8 , 296,7 , 5,17 , 22,23 , {82,83,68}, 288,3 , 11779,58 , 13,5 , 4,0 , 3545,6 , 3560,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 , 1067,7 , 1074,20 , 37,5 , 8,10 , 17110,50 , 16792,81 , 12698,24 , 16744,48 , 16792,81 , 12698,24 , 9092,26 , 9118,55 , 8880,14 , 9092,26 , 9118,55 , 8880,14 , 257,11 , 218,8 , 803,7 , 5,17 , 22,23 , {66,65,77}, 291,2 , 11837,174 , 13,5 , 4,0 , 3533,6 , 3566,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 , 1067,7 , 1074,20 , 37,5 , 8,10 , 17160,58 , 16792,81 , 12698,24 , 17160,58 , 16792,81 , 12698,24 , 9173,33 , 9118,55 , 8880,14 , 9173,33 , 9118,55 , 8880,14 , 257,11 , 218,8 , 803,7 , 5,17 , 22,23 , {69,85,82}, 14,1 , 12011,23 , 13,5 , 4,0 , 3533,6 , 3585,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 , 1067,7 , 1074,20 , 37,5 , 8,10 , 17160,58 , 16792,81 , 12698,24 , 17160,58 , 16792,81 , 12698,24 , 9173,33 , 8828,52 , 8880,14 , 9173,33 , 8828,52 , 8880,14 , 228,9 , 218,8 , 803,7 , 5,17 , 22,23 , {69,85,82}, 14,1 , 12011,23 , 13,5 , 4,0 , 3533,6 , 3594,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 , 1067,7 , 1074,20 , 37,5 , 8,10 , 17052,58 , 16923,81 , 9742,24 , 17052,58 , 16923,81 , 9742,24 , 8977,33 , 9038,54 , 2102,14 , 8977,33 , 9038,54 , 2102,14 , 248,9 , 226,8 , 296,7 , 5,17 , 22,23 , {69,85,82}, 14,1 , 11756,23 , 13,5 , 4,0 , 3545,6 , 3600,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 , 610,9 , 610,9 , 156,8 , 1094,23 , 37,5 , 8,10 , 17218,63 , 17281,82 , 11058,24 , 17363,60 , 17423,86 , 11058,24 , 9206,28 , 9234,61 , 9295,14 , 9309,28 , 9337,61 , 9295,14 , 268,15 , 234,15 , 45,4 , 5,17 , 22,23 , {71,69,76}, 228,1 , 12034,17 , 8,5 , 4,0 , 3606,4 , 3610,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 , 610,9 , 610,9 , 156,8 , 1094,23 , 37,5 , 8,10 , 17218,63 , 17281,82 , 11058,24 , 17363,60 , 17423,86 , 11058,24 , 9206,28 , 9234,61 , 9295,14 , 9309,28 , 9337,61 , 9295,14 , 268,15 , 234,15 , 45,4 , 5,17 , 22,23 , {82,85,66}, 123,1 , 12051,17 , 8,5 , 4,0 , 3606,4 , 3621,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/South Africa @@ -1684,7 +1694,7 @@ static const QLocaleData locale_data[] = { { 140, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 842,9 , 851,8 , 547,6 , 35,18 , 37,5 , 8,10 , 23839,48 , 23887,91 , 134,24 , 23839,48 , 23887,91 , 23978,24 , 12558,28 , 12586,74 , 12660,14 , 12558,28 , 12586,74 , 12660,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {90,65,82}, 5,1 , 14929,67 , 4,4 , 4,0 , 4446,7 , 4453,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 , 495,10 , 478,17 , 37,5 , 441,16 , 5656,48 , 14503,83 , 134,24 , 24002,59 , 14503,83 , 134,24 , 12674,28 , 12702,51 , 2293,14 , 12753,28 , 12702,51 , 2293,14 , 414,9 , 380,11 , 45,4 , 5,17 , 22,23 , {78,79,75}, 190,2 , 9840,44 , 13,5 , 4,0 , 4470,7 , 4477,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 , 1507,11 , 450,19 , 37,5 , 8,10 , 8336,48 , 24061,83 , 9742,24 , 8336,48 , 24061,83 , 9742,24 , 2016,28 , 2044,58 , 2102,14 , 2016,28 , 2044,58 , 2116,14 , 423,10 , 391,7 , 296,7 , 5,17 , 22,23 , {66,65,77}, 144,2 , 14996,170 , 13,5 , 4,0 , 4482,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 , 1067,7 , 1074,20 , 37,5 , 8,10 , 24144,48 , 24192,83 , 12698,24 , 24144,48 , 24192,83 , 12698,24 , 12781,28 , 12809,56 , 8880,14 , 12781,28 , 12809,56 , 8880,14 , 228,9 , 398,7 , 45,4 , 5,17 , 22,23 , {66,65,77}, 291,2 , 15166,151 , 13,5 , 4,0 , 4490,8 , 3545,19 , 2, 1, 1, 6, 7 }, // Bosnian/Cyrillic/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 , 1067,7 , 1074,20 , 37,5 , 8,10 , 24144,48 , 24192,83 , 12698,24 , 24144,48 , 24192,83 , 12698,24 , 12781,28 , 12809,56 , 8880,14 , 12781,28 , 12809,56 , 8880,14 , 228,9 , 398,7 , 45,4 , 5,17 , 22,23 , {66,65,77}, 291,2 , 15166,151 , 13,5 , 4,0 , 4490,8 , 3566,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 , 80,17 , 37,5 , 8,10 , 24275,102 , 24377,140 , 158,27 , 24275,102 , 24377,140 , 158,27 , 12865,30 , 12895,57 , 85,14 , 12865,30 , 12895,57 , 85,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {71,66,80}, 119,1 , 0,7 , 4,4 , 4,0 , 4498,5 , 4503,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 , 119,10 , 97,16 , 37,5 , 8,10 , 24517,46 , 24563,130 , 158,27 , 24517,46 , 24563,130 , 158,27 , 12952,28 , 12980,61 , 85,14 , 12952,28 , 12980,61 , 85,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {71,66,80}, 119,1 , 0,7 , 4,4 , 4,0 , 4515,8 , 4523,14 , 2, 1, 1, 6, 7 }, // Cornish/Latin/United Kingdom @@ -1833,6 +1843,11 @@ static const QLocaleData locale_data[] = { { 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 , 39219,77 , 39219,77 , 158,27 , 39219,77 , 39219,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 , 5865,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 , 1010,5 , 1010,5 , 394,8 , 423,14 , 198,6 , 215,13 , 4423,39 , 4423,39 , 158,27 , 4423,39 , 4423,39 , 158,27 , 1953,28 , 1953,28 , 1981,14 , 1953,28 , 1953,28 , 1981,14 , 58,2 , 55,2 , 45,4 , 5,17 , 22,23 , {72,75,68}, 134,3 , 17327,11 , 4,4 , 4,0 , 5876,2 , 5878,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 , 1010,5 , 1010,5 , 394,8 , 402,13 , 198,6 , 204,11 , 4423,39 , 4462,38 , 158,27 , 4423,39 , 4462,38 , 158,27 , 1932,21 , 1953,28 , 1981,14 , 1932,21 , 1953,28 , 1981,14 , 58,2 , 55,2 , 45,4 , 5,17 , 22,23 , {67,78,89}, 133,1 , 3122,13 , 4,4 , 4,0 , 5892,2 , 5894,7 , 2, 1, 7, 6, 7 }, // Cantonese/Simplified Han/China + { 360, 7, 260, 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 , {0,0,0}, 0,0 , 2586,0 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Ido/Latin/World + { 361, 7, 260, 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 , {0,0,0}, 0,0 , 2586,0 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Lojban/Latin/World + { 362, 7, 106, 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 }, // Sicilian/Latin/Italy + { 363, 1, 102, 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,82,82}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 6, 5, 5 }, // Southern Kurdish/Arabic/Iran + { 364, 1, 163, 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 , {80,75,82}, 176,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 0, 7, 6, 7 }, // Western Balochi/Arabic/Pakistan { 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 }; @@ -2860,24 +2875,24 @@ static const ushort months_data[] = { 0x435, 0x431, 0x440, 0x443, 0x430, 0x440, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x438, 0x43b, 0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x3b, 0x458, 0x443, 0x43b, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x43e, 0x43a, 0x442, 0x43e, 0x431, 0x430, 0x440, 0x3b, 0x43d, 0x43e, 0x432, 0x435, 0x43c, -0x431, 0x430, 0x440, 0x3b, 0x434, 0x435, 0x446, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x458, 0x430, 0x43d, 0x3b, 0x444, 0x435, 0x431, -0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x3b, 0x458, 0x443, -0x43b, 0x3b, 0x430, 0x432, 0x433, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x3b, 0x43e, 0x43a, 0x442, 0x3b, 0x43d, 0x43e, 0x432, 0x3b, 0x434, -0x435, 0x446, 0x3b, 0x458, 0x430, 0x43d, 0x2e, 0x3b, 0x444, 0x435, 0x431, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, -0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x3b, 0x458, 0x443, 0x43b, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, -0x441, 0x435, 0x43f, 0x442, 0x2e, 0x3b, 0x43e, 0x43a, 0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x432, 0x2e, 0x3b, 0x434, 0x435, 0x446, 0x2e, -0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, -0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x76, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x3b, 0x6f, -0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x63, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66, 0x65, -0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x6a, -0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x76, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, -0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, -0x61, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, -0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, -0x61, 0x76, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x63, 0x3b, -0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, -0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x76, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, -0x74, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x42f, 0x43d, +0x431, 0x430, 0x440, 0x3b, 0x434, 0x435, 0x446, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, +0x3b, 0x6d, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, +0x6c, 0x3b, 0x61, 0x76, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, +0x65, 0x63, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61, +0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, +0x3b, 0x61, 0x76, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x6f, 0x6b, +0x74, 0x6f, 0x62, 0x61, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, +0x62, 0x61, 0x72, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, +0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x76, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, +0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x63, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, +0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, +0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x76, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, +0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x458, 0x430, 0x43d, 0x3b, 0x444, 0x435, 0x431, 0x3b, 0x43c, 0x430, +0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x3b, 0x458, 0x443, 0x43b, 0x3b, 0x430, +0x432, 0x433, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x3b, 0x43e, 0x43a, 0x442, 0x3b, 0x43d, 0x43e, 0x432, 0x3b, 0x434, 0x435, 0x446, 0x3b, +0x458, 0x430, 0x43d, 0x2e, 0x3b, 0x444, 0x435, 0x431, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, +0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x3b, 0x458, 0x443, 0x43b, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441, 0x435, 0x43f, +0x442, 0x2e, 0x3b, 0x43e, 0x43a, 0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x432, 0x2e, 0x3b, 0x434, 0x435, 0x446, 0x2e, 0x3b, 0x42f, 0x43d, 0x432, 0x2e, 0x3b, 0x424, 0x435, 0x432, 0x440, 0x2e, 0x3b, 0x41c, 0x430, 0x440, 0x442, 0x2e, 0x3b, 0x410, 0x43f, 0x440, 0x2e, 0x3b, 0x41c, 0x430, 0x439, 0x3b, 0x418, 0x44e, 0x43d, 0x44c, 0x3b, 0x418, 0x44e, 0x43b, 0x44c, 0x3b, 0x410, 0x432, 0x433, 0x2e, 0x3b, 0x421, 0x435, 0x43d, 0x442, 0x2e, 0x3b, 0x41e, 0x43a, 0x442, 0x2e, 0x3b, 0x41d, 0x43e, 0x44f, 0x431, 0x2e, 0x3b, 0x414, 0x435, 0x43a, 0x2e, @@ -4429,23 +4444,23 @@ static const ushort days_data[] = { 0x43f, 0x435, 0x442, 0x3b, 0x441, 0x443, 0x431, 0x3b, 0x43d, 0x435, 0x434, 0x435, 0x459, 0x430, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x435, 0x459, 0x430, 0x43a, 0x3b, 0x443, 0x442, 0x43e, 0x440, 0x430, 0x43a, 0x3b, 0x441, 0x440, 0x435, 0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x440, 0x442, 0x430, 0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x430, 0x43a, 0x3b, 0x441, 0x443, 0x431, 0x43e, 0x442, 0x430, 0x3b, -0x43d, 0x3b, 0x43f, 0x3b, 0x443, 0x3b, 0x441, 0x3b, 0x447, 0x3b, 0x43f, 0x3b, 0x441, 0x3b, 0x43d, 0x435, 0x434, 0x3b, 0x43f, 0x43e, -0x43d, 0x3b, 0x443, 0x442, 0x3b, 0x441, 0x440, 0x3b, 0x447, 0x435, 0x442, 0x3b, 0x43f, 0x435, 0x442, 0x3b, 0x441, 0x443, 0x431, 0x3b, -0x43d, 0x435, 0x434, 0x458, 0x435, 0x459, 0x430, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x435, 0x459, 0x430, 0x43a, 0x3b, 0x443, 0x442, -0x43e, 0x440, 0x430, 0x43a, 0x3b, 0x441, 0x440, 0x438, 0x458, 0x435, 0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x440, 0x442, 0x430, -0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x430, 0x43a, 0x3b, 0x441, 0x443, 0x431, 0x43e, 0x442, 0x430, 0x3b, 0x43d, 0x435, 0x434, 0x2e, 0x3b, -0x43f, 0x43e, 0x43d, 0x2e, 0x3b, 0x443, 0x442, 0x2e, 0x3b, 0x441, 0x440, 0x2e, 0x3b, 0x447, 0x435, 0x442, 0x2e, 0x3b, 0x43f, 0x435, -0x442, 0x2e, 0x3b, 0x441, 0x443, 0x431, 0x2e, 0x3b, 0x6e, 0x65, 0x64, 0x3b, 0x70, 0x6f, 0x6e, 0x3b, 0x75, 0x74, 0x3b, 0x73, -0x72, 0x3b, 0x10d, 0x65, 0x74, 0x3b, 0x70, 0x65, 0x74, 0x3b, 0x73, 0x75, 0x62, 0x3b, 0x6e, 0x65, 0x64, 0x6a, 0x65, 0x6c, -0x6a, 0x61, 0x3b, 0x70, 0x6f, 0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a, 0x61, 0x6b, 0x3b, 0x75, 0x74, 0x6f, 0x72, 0x61, 0x6b, -0x3b, 0x73, 0x72, 0x69, 0x6a, 0x65, 0x64, 0x61, 0x3b, 0x10d, 0x65, 0x74, 0x76, 0x72, 0x74, 0x61, 0x6b, 0x3b, 0x70, 0x65, -0x74, 0x61, 0x6b, 0x3b, 0x73, 0x75, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x6e, 0x65, 0x64, 0x2e, 0x3b, 0x70, 0x6f, 0x6e, 0x2e, -0x3b, 0x75, 0x74, 0x2e, 0x3b, 0x73, 0x72, 0x2e, 0x3b, 0x10d, 0x65, 0x74, 0x2e, 0x3b, 0x70, 0x65, 0x74, 0x2e, 0x3b, 0x73, -0x75, 0x62, 0x2e, 0x3b, 0x6e, 0x65, 0x64, 0x3b, 0x70, 0x6f, 0x6e, 0x3b, 0x75, 0x74, 0x6f, 0x3b, 0x73, 0x72, 0x65, 0x3b, -0x10d, 0x65, 0x74, 0x3b, 0x70, 0x65, 0x74, 0x3b, 0x73, 0x75, 0x62, 0x3b, 0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a, 0x61, 0x3b, -0x70, 0x6f, 0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a, 0x61, 0x6b, 0x3b, 0x75, 0x74, 0x6f, 0x72, 0x61, 0x6b, 0x3b, 0x73, 0x72, -0x65, 0x64, 0x61, 0x3b, 0x10d, 0x65, 0x74, 0x76, 0x72, 0x74, 0x61, 0x6b, 0x3b, 0x70, 0x65, 0x74, 0x61, 0x6b, 0x3b, 0x73, -0x75, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x425, 0x446, 0x431, 0x3b, 0x41a, 0x440, 0x441, 0x3b, 0x414, 0x446, 0x433, 0x3b, 0x4d4, 0x440, +0x43d, 0x3b, 0x43f, 0x3b, 0x443, 0x3b, 0x441, 0x3b, 0x447, 0x3b, 0x43f, 0x3b, 0x441, 0x3b, 0x6e, 0x65, 0x64, 0x3b, 0x70, 0x6f, +0x6e, 0x3b, 0x75, 0x74, 0x3b, 0x73, 0x72, 0x3b, 0x10d, 0x65, 0x74, 0x3b, 0x70, 0x65, 0x74, 0x3b, 0x73, 0x75, 0x62, 0x3b, +0x6e, 0x65, 0x64, 0x6a, 0x65, 0x6c, 0x6a, 0x61, 0x3b, 0x70, 0x6f, 0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a, 0x61, 0x6b, 0x3b, +0x75, 0x74, 0x6f, 0x72, 0x61, 0x6b, 0x3b, 0x73, 0x72, 0x69, 0x6a, 0x65, 0x64, 0x61, 0x3b, 0x10d, 0x65, 0x74, 0x76, 0x72, +0x74, 0x61, 0x6b, 0x3b, 0x70, 0x65, 0x74, 0x61, 0x6b, 0x3b, 0x73, 0x75, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x6e, 0x65, 0x64, +0x2e, 0x3b, 0x70, 0x6f, 0x6e, 0x2e, 0x3b, 0x75, 0x74, 0x2e, 0x3b, 0x73, 0x72, 0x2e, 0x3b, 0x10d, 0x65, 0x74, 0x2e, 0x3b, +0x70, 0x65, 0x74, 0x2e, 0x3b, 0x73, 0x75, 0x62, 0x2e, 0x3b, 0x6e, 0x65, 0x64, 0x3b, 0x70, 0x6f, 0x6e, 0x3b, 0x75, 0x74, +0x6f, 0x3b, 0x73, 0x72, 0x65, 0x3b, 0x10d, 0x65, 0x74, 0x3b, 0x70, 0x65, 0x74, 0x3b, 0x73, 0x75, 0x62, 0x3b, 0x6e, 0x65, +0x64, 0x65, 0x6c, 0x6a, 0x61, 0x3b, 0x70, 0x6f, 0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a, 0x61, 0x6b, 0x3b, 0x75, 0x74, 0x6f, +0x72, 0x61, 0x6b, 0x3b, 0x73, 0x72, 0x65, 0x64, 0x61, 0x3b, 0x10d, 0x65, 0x74, 0x76, 0x72, 0x74, 0x61, 0x6b, 0x3b, 0x70, +0x65, 0x74, 0x61, 0x6b, 0x3b, 0x73, 0x75, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x43d, 0x435, 0x434, 0x3b, 0x43f, 0x43e, 0x43d, 0x3b, +0x443, 0x442, 0x3b, 0x441, 0x440, 0x3b, 0x447, 0x435, 0x442, 0x3b, 0x43f, 0x435, 0x442, 0x3b, 0x441, 0x443, 0x431, 0x3b, 0x43d, 0x435, +0x434, 0x458, 0x435, 0x459, 0x430, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x435, 0x459, 0x430, 0x43a, 0x3b, 0x443, 0x442, 0x43e, 0x440, +0x430, 0x43a, 0x3b, 0x441, 0x440, 0x438, 0x458, 0x435, 0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x440, 0x442, 0x430, 0x43a, 0x3b, +0x43f, 0x435, 0x442, 0x430, 0x43a, 0x3b, 0x441, 0x443, 0x431, 0x43e, 0x442, 0x430, 0x3b, 0x43d, 0x435, 0x434, 0x2e, 0x3b, 0x43f, 0x43e, +0x43d, 0x2e, 0x3b, 0x443, 0x442, 0x2e, 0x3b, 0x441, 0x440, 0x2e, 0x3b, 0x447, 0x435, 0x442, 0x2e, 0x3b, 0x43f, 0x435, 0x442, 0x2e, +0x3b, 0x441, 0x443, 0x431, 0x2e, 0x3b, 0x425, 0x446, 0x431, 0x3b, 0x41a, 0x440, 0x441, 0x3b, 0x414, 0x446, 0x433, 0x3b, 0x4d4, 0x440, 0x442, 0x3b, 0x426, 0x43f, 0x440, 0x3b, 0x41c, 0x440, 0x431, 0x3b, 0x421, 0x431, 0x442, 0x3b, 0x425, 0x443, 0x44b, 0x446, 0x430, 0x443, 0x431, 0x43e, 0x43d, 0x3b, 0x41a, 0x44a, 0x443, 0x44b, 0x440, 0x438, 0x441, 0x4d5, 0x440, 0x3b, 0x414, 0x44b, 0x446, 0x446, 0x4d5, 0x433, 0x3b, 0x4d4, 0x440, 0x442, 0x44b, 0x446, 0x446, 0x4d5, 0x433, 0x3b, 0x426, 0x44b, 0x43f, 0x43f, 0x4d5, 0x440, 0x4d5, 0x43c, 0x3b, 0x41c, @@ -5138,9 +5153,9 @@ static const ushort am_data[] = { 0x101, 0x6e, 0x74, 0x254, 0x301, 0x6e, 0x67, 0x254, 0x301, 0x70, 0x72, 0x69, 0x65, 0x161, 0x70, 0x69, 0x65, 0x74, 0x43f, 0x440, 0x435, 0x442, 0x43f, 0x43b, 0x430, 0x434, 0x43d, 0x435, 0x50, 0x47, 0x92e, 0x2e, 0x92a, 0x942, 0x2e, 0x4af, 0x2e, 0x4e9, 0x2e, 0x63a, 0x2e, 0x645, 0x2e, 0x642, 0x628, 0x644, 0x200c, 0x627, 0x632, 0x638, 0x647, 0x631, 0x64, 0x61, 0x20, 0x6d, 0x61, 0x6e, 0x68, 0xe3, -0xa2a, 0xa42, 0x2e, 0xa26, 0xa41, 0x2e, 0x4e, 0x44, 0x43f, 0x440, 0x435, 0x20, 0x43f, 0x43e, 0x434, 0x43d, 0x435, 0x43f, 0x440, 0x438, -0x458, 0x435, 0x20, 0x43f, 0x43e, 0x434, 0x43d, 0x435, 0x70, 0x72, 0x69, 0x6a, 0x65, 0x20, 0x70, 0x6f, 0x64, 0x6e, 0x65, 0x70, -0x72, 0x65, 0x20, 0x70, 0x6f, 0x64, 0x6e, 0x65, 0x4d5, 0x43c, 0x431, 0x438, 0x441, 0x431, 0x43e, 0x43d, 0x44b, 0x20, 0x440, 0x430, +0xa2a, 0xa42, 0x2e, 0xa26, 0xa41, 0x2e, 0x4e, 0x44, 0x43f, 0x440, 0x435, 0x20, 0x43f, 0x43e, 0x434, 0x43d, 0x435, 0x70, 0x72, 0x69, +0x6a, 0x65, 0x20, 0x70, 0x6f, 0x64, 0x6e, 0x65, 0x70, 0x72, 0x65, 0x20, 0x70, 0x6f, 0x64, 0x6e, 0x65, 0x43f, 0x440, 0x438, +0x458, 0x435, 0x20, 0x43f, 0x43e, 0x434, 0x43d, 0x435, 0x4d5, 0x43c, 0x431, 0x438, 0x441, 0x431, 0x43e, 0x43d, 0x44b, 0x20, 0x440, 0x430, 0x437, 0x43c, 0x4d5, 0x635, 0x628, 0x62d, 0x60c, 0x20, 0x645, 0x646, 0x62c, 0x647, 0x646, 0x62f, 0xdb4, 0xdd9, 0x2e, 0xdc0, 0x2e, 0x73, 0x6e, 0x2e, 0x66, 0x6d, 0x43f, 0x435, 0x2e, 0x20, 0x447, 0x43e, 0x2e, 0xbae, 0xbc1, 0xbb1, 0xbcd, 0xbaa, 0xb95, 0xbb2, 0xbcd, 0xe01, 0xe48, 0xe2d, 0xe19, 0xe40, 0xe17, 0xe35, 0xe48, 0xe22, 0xe07, 0xf66, 0xf94, 0xf0b, 0xf51, 0xfb2, 0xf7c, 0xf0b, 0x1295, 0x1309, 0x1206, 0x20, @@ -5814,29 +5829,29 @@ static const ushort currency_display_name_data[] = { 0x3b, 0x3b, 0x3b, 0x3b, 0x421, 0x440, 0x43f, 0x441, 0x43a, 0x438, 0x20, 0x434, 0x438, 0x43d, 0x430, 0x440, 0x3b, 0x3b, 0x441, 0x440, 0x43f, 0x441, 0x43a, 0x438, 0x20, 0x434, 0x438, 0x43d, 0x430, 0x440, 0x3b, 0x3b, 0x441, 0x440, 0x43f, 0x441, 0x43a, 0x430, 0x20, 0x434, 0x438, 0x43d, 0x430, 0x440, 0x430, 0x3b, 0x3b, 0x441, 0x440, 0x43f, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x434, 0x438, 0x43d, 0x430, 0x440, -0x430, 0x3b, 0x411, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, -0x447, 0x43a, 0x430, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x430, 0x20, 0x43c, 0x430, -0x440, 0x43a, 0x430, 0x3b, 0x3b, 0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, -0x43e, 0x432, 0x430, 0x447, 0x43a, 0x430, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x430, -0x20, 0x43c, 0x430, 0x440, 0x43a, 0x430, 0x3b, 0x3b, 0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, -0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a, 0x435, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, -0x43b, 0x43d, 0x435, 0x20, 0x43c, 0x430, 0x440, 0x43a, 0x65, 0x3b, 0x3b, 0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, -0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a, 0x438, 0x445, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, -0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x438, 0x445, 0x20, 0x43c, 0x430, 0x440, 0x430, 0x43a, 0x430, 0x3b, 0x415, 0x432, 0x440, 0x43e, -0x3b, 0x3b, 0x435, 0x432, 0x440, 0x43e, 0x3b, 0x3b, 0x435, 0x432, 0x440, 0x430, 0x3b, 0x3b, 0x435, 0x432, 0x440, 0x430, 0x3b, 0x42, -0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x2d, 0x68, 0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x61, -0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x61, -0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x2d, 0x68, 0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x61, +0x430, 0x3b, 0x42, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x2d, 0x68, 0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x61, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x2d, 0x68, 0x65, 0x72, 0x63, 0x65, 0x67, -0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x65, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x65, -0x20, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x2d, 0x68, 0x65, 0x72, -0x63, 0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x69, 0x68, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, -0x69, 0x6c, 0x6e, 0x69, 0x68, 0x20, 0x6d, 0x61, 0x72, 0x61, 0x6b, 0x61, 0x3b, 0x45, 0x76, 0x72, 0x6f, 0x3b, 0x3b, 0x65, -0x76, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x76, 0x72, 0x61, 0x3b, 0x3b, 0x65, 0x76, 0x72, 0x61, 0x3b, 0x53, 0x72, 0x70, 0x73, -0x6b, 0x69, 0x20, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x3b, 0x3b, 0x73, 0x72, 0x70, 0x73, 0x6b, 0x69, 0x20, 0x64, 0x69, 0x6e, -0x61, 0x72, 0x3b, 0x3b, 0x73, 0x72, 0x70, 0x73, 0x6b, 0x61, 0x20, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x61, 0x3b, 0x3b, 0x73, -0x72, 0x70, 0x73, 0x6b, 0x69, 0x68, 0x20, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x61, 0x3b, 0x41b, 0x430, 0x440, 0x3b, 0x3b, 0x43b, +0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x61, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x61, +0x20, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x2d, 0x68, 0x65, 0x72, +0x63, 0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x65, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, +0x6c, 0x6e, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x2d, +0x68, 0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x69, 0x68, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, +0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x69, 0x68, 0x20, 0x6d, 0x61, 0x72, 0x61, 0x6b, 0x61, 0x3b, 0x45, 0x76, 0x72, 0x6f, +0x3b, 0x3b, 0x65, 0x76, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x76, 0x72, 0x61, 0x3b, 0x3b, 0x65, 0x76, 0x72, 0x61, 0x3b, 0x53, +0x72, 0x70, 0x73, 0x6b, 0x69, 0x20, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x3b, 0x3b, 0x73, 0x72, 0x70, 0x73, 0x6b, 0x69, 0x20, +0x64, 0x69, 0x6e, 0x61, 0x72, 0x3b, 0x3b, 0x73, 0x72, 0x70, 0x73, 0x6b, 0x61, 0x20, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x61, +0x3b, 0x3b, 0x73, 0x72, 0x70, 0x73, 0x6b, 0x69, 0x68, 0x20, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x61, 0x3b, 0x411, 0x43e, 0x441, +0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a, 0x430, 0x20, 0x43a, +0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x430, 0x20, 0x43c, 0x430, 0x440, 0x43a, 0x430, 0x3b, 0x3b, +0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a, +0x430, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x430, 0x20, 0x43c, 0x430, 0x440, 0x43a, +0x430, 0x3b, 0x3b, 0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, +0x430, 0x447, 0x43a, 0x435, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x435, 0x20, 0x43c, +0x430, 0x440, 0x43a, 0x65, 0x3b, 0x3b, 0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, +0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a, 0x438, 0x445, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, +0x43d, 0x438, 0x445, 0x20, 0x43c, 0x430, 0x440, 0x430, 0x43a, 0x430, 0x3b, 0x415, 0x432, 0x440, 0x43e, 0x3b, 0x3b, 0x435, 0x432, 0x440, +0x43e, 0x3b, 0x3b, 0x435, 0x432, 0x440, 0x430, 0x3b, 0x3b, 0x435, 0x432, 0x440, 0x430, 0x3b, 0x41b, 0x430, 0x440, 0x3b, 0x3b, 0x43b, 0x430, 0x440, 0x3b, 0x3b, 0x3b, 0x3b, 0x43b, 0x430, 0x440, 0x44b, 0x3b, 0x421, 0x43e, 0x43c, 0x3b, 0x3b, 0x441, 0x43e, 0x43c, 0x3b, 0x3b, 0x3b, 0x3b, 0x441, 0x43e, 0x43c, 0x44b, 0x3b, 0x44, 0x6f, 0x72, 0x61, 0x20, 0x72, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x6b, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x67e, 0x627, 0x6aa, 0x633, 0x62a, 0x627, 0x646, 0x64a, 0x20, 0x631, @@ -6291,9 +6306,9 @@ static const ushort endonyms_data[] = { 0x441, 0x442, 0x430, 0x43d, 0x41a, 0x438, 0x440, 0x433, 0x438, 0x437, 0x438, 0x44f, 0x41c, 0x43e, 0x43b, 0x434, 0x43e, 0x432, 0x430, 0x423, 0x43a, 0x440, 0x430, 0x438, 0x43d, 0x430, 0x53, 0xe4, 0x6e, 0x67, 0xf6, 0x4b, 0xf6, 0x64, 0xf6, 0x72, 0xf6, 0x73, 0xea, 0x73, 0x65, 0x20, 0x74, 0xee, 0x20, 0x42, 0xea, 0x61, 0x66, 0x72, 0xee, 0x6b, 0x61, 0x441, 0x440, 0x43f, 0x441, 0x43a, 0x438, 0x421, -0x440, 0x431, 0x438, 0x458, 0x430, 0x411, 0x43e, 0x441, 0x43d, 0x430, 0x20, 0x438, 0x20, 0x425, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, -0x432, 0x438, 0x43d, 0x430, 0x426, 0x440, 0x43d, 0x430, 0x20, 0x413, 0x43e, 0x440, 0x430, 0x41a, 0x43e, 0x441, 0x43e, 0x432, 0x43e, 0x73, -0x72, 0x70, 0x73, 0x6b, 0x69, 0x43, 0x72, 0x6e, 0x61, 0x20, 0x47, 0x6f, 0x72, 0x61, 0x53, 0x72, 0x62, 0x69, 0x6a, 0x61, +0x440, 0x431, 0x438, 0x458, 0x430, 0x73, 0x72, 0x70, 0x73, 0x6b, 0x69, 0x43, 0x72, 0x6e, 0x61, 0x20, 0x47, 0x6f, 0x72, 0x61, +0x53, 0x72, 0x62, 0x69, 0x6a, 0x61, 0x411, 0x43e, 0x441, 0x43d, 0x430, 0x20, 0x438, 0x20, 0x425, 0x435, 0x440, 0x446, 0x435, 0x433, +0x43e, 0x432, 0x438, 0x43d, 0x430, 0x426, 0x440, 0x43d, 0x430, 0x20, 0x413, 0x43e, 0x440, 0x430, 0x41a, 0x43e, 0x441, 0x43e, 0x432, 0x43e, 0x4b, 0x6f, 0x73, 0x6f, 0x76, 0x6f, 0x438, 0x440, 0x43e, 0x43d, 0x413, 0x443, 0x44b, 0x440, 0x434, 0x437, 0x44b, 0x441, 0x442, 0x43e, 0x43d, 0x423, 0x4d5, 0x440, 0x4d5, 0x441, 0x435, 0x63, 0x68, 0x69, 0x53, 0x68, 0x6f, 0x6e, 0x61, 0x633, 0x646, 0x68c, 0x64a, 0x67e, 0x627, 0x6aa, 0x633, 0x62a, 0x627, 0x646, 0xdc3, 0xdd2, 0xd82, 0xdc4, 0xdbd, 0xdc1, 0xdca, 0x200d, 0xdbb, 0xdd3, 0x20, 0xdbd, 0xd82, 0xd9a, @@ -6773,6 +6788,11 @@ static const char language_name_list[] = "Cantonese\0" "Osage\0" "Tangut\0" +"Ido\0" +"Lojban\0" +"Sicilian\0" +"Southern Kurdish\0" +"Western Balochi\0" ; static const quint16 language_name_index[] = { @@ -7136,6 +7156,11 @@ static const quint16 language_name_index[] = { 3050, // Cantonese 3060, // Osage 3066, // Tangut + 3073, // Ido + 3077, // Lojban + 3084, // Sicilian + 3093, // Southern Kurdish + 3110, // Western Balochi }; static const char script_name_list[] = @@ -8319,6 +8344,11 @@ static const unsigned char language_code_list[] = "yue" // Cantonese "osa" // Osage "txg" // Tangut +"io\0" // Ido +"jbo" // Lojban +"scn" // Sicilian +"sdh" // Southern Kurdish +"bgn" // Western Balochi ; static const unsigned char script_code_list[] = diff --git a/src/corelib/tools/qlocale_p.h b/src/corelib/tools/qlocale_p.h index a9c23aed61..9f5811990b 100644 --- a/src/corelib/tools/qlocale_p.h +++ b/src/corelib/tools/qlocale_p.h @@ -66,6 +66,7 @@ QT_BEGIN_NAMESPACE #ifndef QT_NO_SYSTEMLOCALE +struct QLocaleData; class Q_CORE_EXPORT QSystemLocale { public: @@ -126,6 +127,7 @@ public: virtual QVariant query(QueryType type, QVariant in) const; virtual QLocale fallbackUiLocale() const; + inline const QLocaleData *fallbackUiLocaleData() const; private: QSystemLocale(bool); friend class QSystemLocaleSingleton; @@ -364,8 +366,6 @@ public: QLocale::MeasurementSystem measurementSystem() const; - static void updateSystemPrivate(); - QString dateTimeToString(QStringView format, const QDateTime &datetime, const QDate &dateOnly, const QTime &timeOnly, const QLocale *q) const; @@ -375,6 +375,10 @@ public: QLocale::NumberOptions m_numberOptions; }; +#ifndef QT_NO_SYSTEMLOCALE +const QLocaleData *QSystemLocale::fallbackUiLocaleData() const { return fallbackUiLocale().d->m_data; } +#endif + template <> inline QLocalePrivate *QSharedDataPointer<QLocalePrivate>::clone() { diff --git a/src/corelib/tools/qmakearray_p.h b/src/corelib/tools/qmakearray_p.h index ae4d7f07c6..71441c2c27 100644 --- a/src/corelib/tools/qmakearray_p.h +++ b/src/corelib/tools/qmakearray_p.h @@ -111,10 +111,10 @@ struct QuickSortFilter<Predicate, QuickSortData<Head, Tail...>> using TailFilteredData = typename QuickSortFilter< Predicate, QuickSortData<Tail...>>::Type; - using Type = typename QConditional< + using Type = typename std::conditional< Predicate<Head>::value, decltype(quickSortConcat(QuickSortData<Head> {}, TailFilteredData{})), - TailFilteredData>::Type; + TailFilteredData>::type; }; template <template <typename> class Predicate> diff --git a/src/corelib/tools/qoffsetstringarray_p.h b/src/corelib/tools/qoffsetstringarray_p.h new file mode 100644 index 0000000000..5ca2200091 --- /dev/null +++ b/src/corelib/tools/qoffsetstringarray_p.h @@ -0,0 +1,200 @@ +/**************************************************************************** +** +** 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 QOFFSETSTRINGARRAY_P_H +#define QOFFSETSTRINGARRAY_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 "private/qglobal_p.h" + +#include <tuple> +#include <array> + +QT_BEGIN_NAMESPACE + +namespace QtPrivate { +template<int N, int O, int I, int ... Idx> +struct OffsetSequenceHelper : OffsetSequenceHelper<N - 1, O + I, Idx..., O> { }; + +template<int Last, int I, int S, int ... Idx> +struct OffsetSequenceHelper<1, Last, I, S, Idx...> : IndexesList<Last + I, Idx..., Last> +{ + static const constexpr auto Length = Last + I; + using Type = typename std::conditional< + Last <= std::numeric_limits<quint8>::max(), + quint8, + typename std::conditional< + Last <= std::numeric_limits<quint16>::max(), + quint16, + int>::type + >::type; +}; + +template<int ... Idx> +struct OffsetSequence : OffsetSequenceHelper<sizeof ... (Idx), 0, Idx..., 0> { }; + +template<int N> +struct StaticString +{ + const char data[N]; + + constexpr StaticString(const StaticString<N> &other) noexcept = default; +}; + + +template<> +struct StaticString<0> +{ + static constexpr int size() noexcept + { + return 0; + } +}; + +template<typename, typename> +struct StaticStringBuilder; + +template<int ... I1, int ... I2> +struct StaticStringBuilder<IndexesList<I1...>, IndexesList<I2...>> +{ + +QT_WARNING_PUSH +QT_WARNING_DISABLE_MSVC(4100) // The formal parameter is not referenced in the body of the function. + // The unreferenced parameter is ignored. + // It happens when 'rs' is StaticString<0> + template<int N1, int N2> + static constexpr StaticString<N1 + N2> concatenate( + const char (&ls)[N1], const StaticString<N2> &rs) noexcept + { + return StaticString<N1 + N2>{{ls[I1]..., rs.data[I2]...}}; + } +QT_WARNING_POP +}; + +template<int Sum> +constexpr StaticString<0> staticString() noexcept +{ + return StaticString<0>{}; +} + +QT_WARNING_PUSH +QT_WARNING_DISABLE_MSVC(4503) +template<int Sum, int I, int ... Ix> +constexpr StaticString<Sum> staticString(const char (&s)[I], const char (&...sx)[Ix]) noexcept +{ + return StaticStringBuilder< + makeIndexSequence<I>, + makeIndexSequence<Sum - I>>::concatenate(s, staticString<Sum - I>(sx...)); +} +QT_WARNING_POP +} // namespace QtPrivate + +template<typename T, int SizeString, int SizeOffsets> +class QOffsetStringArray +{ +public: + using Type = T; + + template<int ... Ox> + constexpr QOffsetStringArray(const QtPrivate::StaticString<SizeString> &str, + QtPrivate::IndexesList<SizeString, Ox...>) noexcept + : m_string(str), + m_offsets{Ox...} + { } + + constexpr inline const char *operator[](const int index) const noexcept + { + return m_string.data + m_offsets[qBound(int(0), index, SizeOffsets - 1)]; + } + + constexpr inline const char *at(const int index) const noexcept + { + return m_string.data + m_offsets[index]; + } + + constexpr inline const char *str() const { return m_string.data; } + constexpr inline const T *offsets() const { return m_offsets; } + constexpr inline int count() const { return SizeOffsets; }; + + static constexpr const auto sizeString = SizeString; + static constexpr const auto sizeOffsets = SizeOffsets; + +private: + QtPrivate::StaticString<SizeString> m_string; + const T m_offsets[SizeOffsets]; +}; + +template<typename T, int N, int ... Ox> +constexpr QOffsetStringArray<T, N, sizeof ... (Ox)> qOffsetStringArray( + const QtPrivate::StaticString<N> &string, + QtPrivate::IndexesList<N, Ox...> offsets) noexcept +{ + return QOffsetStringArray<T, N, sizeof ... (Ox)>( + string, + offsets); +} + +template<int ... Nx> +struct QOffsetStringArrayRet +{ + using Offsets = QtPrivate::OffsetSequence<Nx...>; + using Type = QOffsetStringArray<typename Offsets::Type, Offsets::Length, sizeof ... (Nx)>; +}; + +template<int ... Nx> +constexpr auto qOffsetStringArray(const char (&...strings)[Nx]) noexcept -> typename QOffsetStringArrayRet<Nx...>::Type +{ + using Offsets = QtPrivate::OffsetSequence<Nx...>; + return qOffsetStringArray<typename Offsets::Type>( + QtPrivate::staticString<Offsets::Length>(strings...), Offsets{}); +} + +QT_END_NAMESPACE + +#endif // QOFFSETSTRINGARRAY_P_H diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index e52171fcec..560453de84 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -120,7 +120,7 @@ QT_BEGIN_NAMESPACE * Whenever multiple alternatives are equivalent or near so, we prefer the one * using instructions from SSE2, since SSE2 is guaranteed to be enabled for all * 64-bit builds and we enable it for 32-bit builds by default. Use of higher - * SSE versions should be done when there's a clear performance benefit and + * SSE versions should be done when there is a clear performance benefit and * requires fallback code to SSE2, if it exists. * * Performance measurement in the past shows that most strings are short in @@ -1505,7 +1505,7 @@ const QString::Null QString::null = { }; functions. The former searches forward starting from a given index position, the latter searches backward. Both return the index position of the character or substring if they find it; otherwise, - they return -1. For example, here's a typical loop that finds all + they return -1. For example, here is a typical loop that finds all occurrences of a particular substring: \snippet qstring/main.cpp 6 @@ -6620,7 +6620,7 @@ namespace QUnicodeTables { this function requires to be a valid, empty string) and \c{s} contains the only copy of the string, without reallocation (thus, \a it is still valid). - There's one pathological case left: when the in-place conversion needs to + There is one pathological case left: when the in-place conversion needs to reallocate memory to grow the buffer. In that case, we need to adjust the \a it pointer. */ @@ -6778,7 +6778,7 @@ QString &QString::sprintf(const char *cformat, ...) \warning We do not recommend using QString::asprintf() in new Qt code. Instead, consider using QTextStream or arg(), both of which support Unicode strings seamlessly and are type-safe. - Here's an example that uses QTextStream: + Here is an example that uses QTextStream: \snippet qstring/main.cpp 64 @@ -7743,7 +7743,7 @@ QStringList QString::split(const QString &sep, SplitBehavior behavior, Qt::CaseS the result. \note All references are valid as long this string is alive. Destroying this - string will cause all references be dangling pointers. + string will cause all references to be dangling pointers. \since 5.4 \sa QStringRef split() @@ -7777,7 +7777,7 @@ QVector<QStringRef> QString::splitRef(QChar sep, SplitBehavior behavior, Qt::Cas the result. \note All references are valid as long this string is alive. Destroying this - string will cause all references be dangling pointers. + string will cause all references to be dangling pointers. \since 5.4 */ @@ -7826,17 +7826,17 @@ static ResultList splitString(const QString &source, MidMethod mid, const QRegEx does not match anywhere in the string, split() returns a single-element list containing this string. - Here's an example where we extract the words in a sentence + Here is an example where we extract the words in a sentence using one or more whitespace characters as the separator: \snippet qstring/main.cpp 59 - Here's a similar example, but this time we use any sequence of + Here is a similar example, but this time we use any sequence of non-word characters as the separator: \snippet qstring/main.cpp 60 - Here's a third example where we use a zero-length assertion, + Here is a third example where we use a zero-length assertion, \b{\\b} (word boundary), to split the string into an alternating sequence of non-word and word tokens: @@ -7859,7 +7859,7 @@ QStringList QString::split(const QRegExp &rx, SplitBehavior behavior) const single-element vector containing this string reference. \note All references are valid as long this string is alive. Destroying this - string will cause all references be dangling pointers. + string will cause all references to be dangling pointers. \sa QStringRef split() */ @@ -7908,17 +7908,17 @@ static ResultList splitString(const QString &source, MidMethod mid, const QRegul does not match anywhere in the string, split() returns a single-element list containing this string. - Here's an example where we extract the words in a sentence + Here is an example where we extract the words in a sentence using one or more whitespace characters as the separator: \snippet qstring/main.cpp 90 - Here's a similar example, but this time we use any sequence of + Here is a similar example, but this time we use any sequence of non-word characters as the separator: \snippet qstring/main.cpp 91 - Here's a third example where we use a zero-length assertion, + Here is a third example where we use a zero-length assertion, \b{\\b} (word boundary), to split the string into an alternating sequence of non-word and word tokens: @@ -7941,7 +7941,7 @@ QStringList QString::split(const QRegularExpression &re, SplitBehavior behavior) single-element vector containing this string reference. \note All references are valid as long this string is alive. Destroying this - string will cause all references be dangling pointers. + string will cause all references to be dangling pointers. \sa split() QStringRef */ @@ -9078,7 +9078,7 @@ bool QString::isRightToLeft() const to create a deep copy of the data, ensuring that the raw data isn't modified. - Here's an example of how we can use a QRegularExpression on raw data in + Here is an example of how we can use a QRegularExpression on raw data in memory without requiring to copy the data into a QString: \snippet qstring/main.cpp 22 diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 6be3dcdbe1..da76601e88 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -899,10 +899,8 @@ private: template <typename T> static T toIntegral_helper(const QChar *data, int len, bool *ok, int base) { - // ### Qt6: use std::conditional<std::is_unsigned<T>::value, qulonglong, qlonglong>::type - const bool isUnsigned = T(0) < T(-1); - typedef typename QtPrivate::QConditional<isUnsigned, qulonglong, qlonglong>::Type Int64; - typedef typename QtPrivate::QConditional<isUnsigned, uint, int>::Type Int32; + using Int64 = typename std::conditional<std::is_unsigned<T>::value, qulonglong, qlonglong>::type; + using Int32 = typename std::conditional<std::is_unsigned<T>::value, uint, int>::type; // we select the right overload by casting size() to int or uint Int64 val = toIntegral_helper(data, Int32(len), ok, base); diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index dc28e0e0a2..995bab694e 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -39,6 +39,7 @@ HEADERS += \ tools/qmargins.h \ tools/qmessageauthenticationcode.h \ tools/qcontiguouscache.h \ + tools/qoffsetstringarray_p.h \ tools/qpair.h \ tools/qpoint.h \ tools/qqueue.h \ |