diff options
Diffstat (limited to 'src/qml/qml/qqmllist.h')
-rw-r--r-- | src/qml/qml/qqmllist.h | 228 |
1 files changed, 150 insertions, 78 deletions
diff --git a/src/qml/qml/qqmllist.h b/src/qml/qml/qqmllist.h index 90ec57c911..6f2c077764 100644 --- a/src/qml/qml/qqmllist.h +++ b/src/qml/qml/qqmllist.h @@ -1,76 +1,44 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtQml 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QQMLLIST_H #define QQMLLIST_H #include <QtQml/qtqmlglobal.h> + +#include <QtCore/qcontainerinfo.h> #include <QtCore/qlist.h> +#include <QtCore/qmetatype.h> #include <QtCore/qvariant.h> QT_BEGIN_NAMESPACE - class QObject; struct QMetaObject; -#ifndef QQMLLISTPROPERTY -#define QQMLLISTPROPERTY +#define QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_APPEND Q_CLASSINFO("QML.ListPropertyAssignBehavior", "Append") +#define QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_REPLACE_IF_NOT_DEFAULT Q_CLASSINFO("QML.ListPropertyAssignBehavior", "ReplaceIfNotDefault") +#define QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_REPLACE Q_CLASSINFO("QML.ListPropertyAssignBehavior", "Replace") + template<typename T> class QQmlListProperty { public: - typedef void (*AppendFunction)(QQmlListProperty<T> *, T*); - typedef int (*CountFunction)(QQmlListProperty<T> *); - typedef T *(*AtFunction)(QQmlListProperty<T> *, int); - typedef void (*ClearFunction)(QQmlListProperty<T> *); - - QQmlListProperty() - : append(nullptr), - count(nullptr), - at(nullptr), - clear(nullptr) - {} - QQmlListProperty(QObject *o, QList<T *> &list) - : object(o), data(&list), append(qlist_append), count(qlist_count), at(qlist_at), - clear(qlist_clear) + using value_type = T*; + + using AppendFunction = void (*)(QQmlListProperty<T> *, T *); + using CountFunction = qsizetype (*)(QQmlListProperty<T> *); + using AtFunction = T *(*)(QQmlListProperty<T> *, qsizetype); + using ClearFunction = void (*)(QQmlListProperty<T> *); + using ReplaceFunction = void (*)(QQmlListProperty<T> *, qsizetype, T *); + using RemoveLastFunction = void (*)(QQmlListProperty<T> *); + QQmlListProperty() = default; + + QQmlListProperty(QObject *o, QList<T *> *list) + : object(o), data(list), append(qlist_append), count(qlist_count), at(qlist_at), + clear(qlist_clear), replace(qlist_replace), removeLast(qlist_removeLast) {} + QQmlListProperty(QObject *o, void *d, AppendFunction a, CountFunction c, AtFunction t, ClearFunction r ) : object(o), @@ -78,53 +46,136 @@ public: append(a), count(c), at(t), - clear(r) - + clear(r), + replace((a && c && t && r) ? qslow_replace : nullptr), + removeLast((a && c && t && r) ? qslow_removeLast : nullptr) {} - QQmlListProperty(QObject *o, void *d, CountFunction c, AtFunction t) + + QQmlListProperty(QObject *o, void *d, AppendFunction a, CountFunction c, AtFunction t, + ClearFunction r, ReplaceFunction s, RemoveLastFunction p) : object(o), data(d), - append(nullptr), - count(c), at(t), - clear(nullptr) + append(a), + count(c), + at(t), + clear((!r && p && c) ? qslow_clear : r), + replace((!s && a && c && t && (r || p)) ? qslow_replace : s), + removeLast((!p && a && c && t && r) ? qslow_removeLast : p) {} + + QQmlListProperty(QObject *o, void *d, CountFunction c, AtFunction a) + : object(o), data(d), count(c), at(a) + {} + bool operator==(const QQmlListProperty &o) const { return object == o.object && data == o.data && append == o.append && count == o.count && at == o.at && - clear == o.clear; + clear == o.clear && + replace == o.replace && + removeLast == o.removeLast; } QObject *object = nullptr; void *data = nullptr; - AppendFunction append; + AppendFunction append = nullptr; + CountFunction count = nullptr; + AtFunction at = nullptr; + ClearFunction clear = nullptr; + ReplaceFunction replace = nullptr; + RemoveLastFunction removeLast = nullptr; + + template<typename List> + List toList() + { + if constexpr (std::is_same_v<List, QList<T *>>) { + if (append == qlist_append) + return *static_cast<QList<T *> *>(data); + } - CountFunction count; - AtFunction at; + const qsizetype size = count(this); - ClearFunction clear; + List result; + if constexpr (QContainerInfo::has_reserve_v<List>) + result.reserve(size); - void *dummy1 = nullptr; - void *dummy2 = nullptr; + static_assert(QContainerInfo::has_push_back_v<List>); + for (qsizetype i = 0; i < size; ++i) + result.push_back(at(this, i)); + + return result; + } private: static void qlist_append(QQmlListProperty *p, T *v) { - reinterpret_cast<QList<T *> *>(p->data)->append(v); + static_cast<QList<T *> *>(p->data)->append(v); } - static int qlist_count(QQmlListProperty *p) { - return reinterpret_cast<QList<T *> *>(p->data)->count(); + static qsizetype qlist_count(QQmlListProperty *p) { + return static_cast<QList<T *> *>(p->data)->size(); } - static T *qlist_at(QQmlListProperty *p, int idx) { - return reinterpret_cast<QList<T *> *>(p->data)->at(idx); + static T *qlist_at(QQmlListProperty *p, qsizetype idx) { + return static_cast<QList<T *> *>(p->data)->at(idx); } static void qlist_clear(QQmlListProperty *p) { - return reinterpret_cast<QList<T *> *>(p->data)->clear(); + return static_cast<QList<T *> *>(p->data)->clear(); + } + static void qlist_replace(QQmlListProperty *p, qsizetype idx, T *v) { + return static_cast<QList<T *> *>(p->data)->replace(idx, v); + } + static void qlist_removeLast(QQmlListProperty *p) { + return static_cast<QList<T *> *>(p->data)->removeLast(); + } + + static void qslow_replace(QQmlListProperty<T> *list, qsizetype idx, T *v) + { + const qsizetype length = list->count(list); + if (idx < 0 || idx >= length) + return; + + QVector<T *> stash; + if (list->clear != qslow_clear) { + stash.reserve(length); + for (qsizetype i = 0; i < length; ++i) + stash.append(i == idx ? v : list->at(list, i)); + list->clear(list); + for (T *item : std::as_const(stash)) + list->append(list, item); + } else { + stash.reserve(length - idx - 1); + for (qsizetype i = length - 1; i > idx; --i) { + stash.append(list->at(list, i)); + list->removeLast(list); + } + list->removeLast(list); + list->append(list, v); + while (!stash.isEmpty()) + list->append(list, stash.takeLast()); + } + } + + static void qslow_clear(QQmlListProperty<T> *list) + { + for (qsizetype i = 0, end = list->count(list); i < end; ++i) + list->removeLast(list); + } + + static void qslow_removeLast(QQmlListProperty<T> *list) + { + const qsizetype length = list->count(list) - 1; + if (length < 0) + return; + QVector<T *> stash; + stash.reserve(length); + for (qsizetype i = 0; i < length; ++i) + stash.append(list->at(list, i)); + list->clear(list); + for (T *item : std::as_const(stash)) + list->append(list, item); } }; -#endif class QQmlEngine; class QQmlListReferencePrivate; @@ -132,7 +183,17 @@ class Q_QML_EXPORT QQmlListReference { public: QQmlListReference(); - QQmlListReference(QObject *, const char *property, QQmlEngine * = nullptr); + +#if QT_DEPRECATED_SINCE(6, 4) + QT_DEPRECATED_X("Drop the QQmlEngine* argument") + QQmlListReference(const QVariant &variant, [[maybe_unused]] QQmlEngine *engine); + + QT_DEPRECATED_X("Drop the QQmlEngine* argument") + QQmlListReference(QObject *o, const char *property, [[maybe_unused]] QQmlEngine *engine); +#endif + + explicit QQmlListReference(const QVariant &variant); + QQmlListReference(QObject *o, const char *property); QQmlListReference(const QQmlListReference &); QQmlListReference &operator=(const QQmlListReference &); ~QQmlListReference(); @@ -146,20 +207,31 @@ public: bool canAt() const; bool canClear() const; bool canCount() const; + bool canReplace() const; + bool canRemoveLast() const; bool isManipulable() const; bool isReadable() const; bool append(QObject *) const; - QObject *at(int) const; + QObject *at(qsizetype) const; bool clear() const; - int count() const; + qsizetype count() const; + qsizetype size() const { return count(); } + bool replace(qsizetype, QObject *) const; + bool removeLast() const; + bool operator==(const QQmlListReference &other) const {return d == other.d;} private: friend class QQmlListReferencePrivate; QQmlListReferencePrivate* d; }; +namespace QtPrivate { +template<typename T> +inline constexpr bool IsQmlListType<QQmlListProperty<T>> = true; +} + QT_END_NAMESPACE Q_DECLARE_METATYPE(QQmlListReference) |