aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmllist.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/qml/qqmllist.cpp')
-rw-r--r--src/qml/qml/qqmllist.cpp350
1 files changed, 275 insertions, 75 deletions
diff --git a/src/qml/qml/qqmllist.cpp b/src/qml/qml/qqmllist.cpp
index 5425bf498c..a166041070 100644
--- a/src/qml/qml/qqmllist.cpp
+++ b/src/qml/qml/qqmllist.cpp
@@ -1,68 +1,36 @@
-/****************************************************************************
-**
-** 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
#include "qqmllist.h"
#include "qqmllist_p.h"
-#include "qqmlengine_p.h"
-#include "qqmlproperty_p.h"
+#include <QtQml/private/qqmlproperty_p.h>
QT_BEGIN_NAMESPACE
+static bool isObjectCompatible(QObject *object, QQmlListReferencePrivate *d)
+{
+ if (object) {
+ const QQmlMetaObject elementType = d->elementType();
+ if (elementType.isNull() || !QQmlMetaObject::canConvert(object, elementType))
+ return false;
+ }
+ return true;
+}
+
QQmlListReferencePrivate::QQmlListReferencePrivate()
-: propertyType(-1), refCount(1)
+: refCount(1)
{
}
-QQmlListReference QQmlListReferencePrivate::init(const QQmlListProperty<QObject> &prop, int propType, QQmlEngine *engine)
+QQmlListReference QQmlListReferencePrivate::init(
+ const QQmlListProperty<QObject> &prop, QMetaType propType)
{
QQmlListReference rv;
if (!prop.object) return rv;
- QQmlEnginePrivate *p = engine?QQmlEnginePrivate::get(engine):nullptr;
-
- int listType = p?p->listType(propType):QQmlMetaType::listType(propType);
- if (listType == -1) return rv;
-
rv.d = new QQmlListReferencePrivate;
rv.d->object = prop.object;
- rv.d->elementType = QQmlPropertyPrivate::rawMetaObjectForType(p, listType);
rv.d->property = prop;
rv.d->propertyType = propType;
@@ -119,34 +87,83 @@ QQmlListReference::QQmlListReference()
{
}
+#if QT_DEPRECATED_SINCE(6, 4)
/*!
+\since 6.1
+\obsolete [6.4] Use the constructors without QQmlEngine argument instead.
+
+Constructs a QQmlListReference from a QVariant \a variant containing a QQmlListProperty. If
+\a variant does not contain a list property, an invalid QQmlListReference is created. If the object
+owning the list property is destroyed after the reference is constructed, it will automatically
+become invalid. That is, it is safe to hold QQmlListReference instances even after the object is
+deleted.
+
+The \a engine is unused.
+*/
+QQmlListReference::QQmlListReference(const QVariant &variant, [[maybe_unused]] QQmlEngine *engine)
+ : QQmlListReference(variant)
+{}
+
+/*!
+\obsolete [6.4] Use the constructors without QQmlEngine argument instead.
+
Constructs a QQmlListReference for \a object's \a property. If \a property is not a list
property, an invalid QQmlListReference is created. If \a object is destroyed after
the reference is constructed, it will automatically become invalid. That is, it is safe to hold
QQmlListReference instances even after \a object is deleted.
-Passing \a engine is required to access some QML created list properties. If in doubt, and an engine
-is available, pass it.
+The \a engine is unused.
*/
-QQmlListReference::QQmlListReference(QObject *object, const char *property, QQmlEngine *engine)
-: d(nullptr)
+QQmlListReference::QQmlListReference(QObject *object, const char *property,
+ [[maybe_unused]] QQmlEngine *engine)
+ : QQmlListReference(object, property)
+{}
+#endif
+
+/*!
+\since 6.1
+
+Constructs a QQmlListReference from a QVariant \a variant containing a QQmlListProperty. If
+\a variant does not contain a list property, an invalid QQmlListReference is created. If the object
+owning the list property is destroyed after the reference is constructed, it will automatically
+become invalid. That is, it is safe to hold QQmlListReference instances even after the object is
+deleted.
+*/
+QQmlListReference::QQmlListReference(const QVariant &variant)
+ : d(nullptr)
+{
+ const QMetaType t = variant.metaType();
+ if (!(t.flags() & QMetaType::IsQmlList))
+ return;
+
+ d = new QQmlListReferencePrivate;
+ d->propertyType = t;
+
+ d->property.~QQmlListProperty();
+ t.construct(&d->property, variant.constData());
+
+ d->object = d->property.object;
+}
+
+/*!
+Constructs a QQmlListReference for \a object's \a property. If \a property is not a list
+property, an invalid QQmlListReference is created. If \a object is destroyed after
+the reference is constructed, it will automatically become invalid. That is, it is safe to hold
+QQmlListReference instances even after \a object is deleted.
+*/
+QQmlListReference::QQmlListReference(QObject *object, const char *property)
+ : d(nullptr)
{
if (!object || !property) return;
QQmlPropertyData local;
- QQmlPropertyData *data =
- QQmlPropertyCache::property(engine, object, QLatin1String(property), nullptr, local);
+ const QQmlPropertyData *data =
+ QQmlPropertyCache::property(object, QLatin1String(property), nullptr, &local);
if (!data || !data->isQList()) return;
- QQmlEnginePrivate *p = engine?QQmlEnginePrivate::get(engine):nullptr;
-
- int listType = p?p->listType(data->propType()):QQmlMetaType::listType(data->propType());
- if (listType == -1) return;
-
d = new QQmlListReferencePrivate;
d->object = object;
- d->elementType = p ? p->rawMetaObjectForType(listType) : QQmlMetaType::qmlType(listType).baseMetaObject();
d->propertyType = data->propType();
void *args[] = { &d->property, nullptr };
@@ -197,12 +214,11 @@ Returns the QMetaObject for the elements stored in the list property,
or \nullptr if the reference is invalid.
The QMetaObject can be used ahead of time to determine whether a given instance can be added
-to a list.
+to a list. If you didn't pass an engine on construction this may return nullptr.
*/
const QMetaObject *QQmlListReference::listElementType() const
{
- if (isValid()) return d->elementType.metaObject();
- else return nullptr;
+ return isValid() ? d->elementType() : nullptr;
}
/*!
@@ -250,10 +266,37 @@ bool QQmlListReference::canCount() const
}
/*!
- Return true if at(), count(), append() and clear() are implemented, so you can manipulate
- the list.
+Returns true if items in the list property can be replaced, otherwise false.
+Returns false if the reference is invalid.
-\sa isReadable(), at(), count(), append(), clear()
+\sa replace()
+*/
+bool QQmlListReference::canReplace() const
+{
+ return (isValid() && d->property.replace);
+}
+
+/*!
+Returns true if the last item can be removed from the list property, otherwise false.
+Returns false if the reference is invalid.
+
+\sa removeLast()
+*/
+bool QQmlListReference::canRemoveLast() const
+{
+ return (isValid() && d->property.removeLast);
+}
+
+/*!
+ Return true if at(), count(), append(), and either clear() or removeLast()
+ are implemented, so you can manipulate the list.
+
+ Mind that replace() and removeLast() can be emulated by stashing all
+ items and rebuilding the list using clear() and append(). Therefore,
+ they are not required for the list to be manipulable. Furthermore,
+ clear() can be emulated using removeLast().
+
+\sa isReadable(), at(), count(), append(), clear(), replace(), removeLast()
*/
bool QQmlListReference::isManipulable() const
{
@@ -284,7 +327,7 @@ bool QQmlListReference::append(QObject *object) const
{
if (!canAppend()) return false;
- if (object && !QQmlMetaObject::canConvert(object, d->elementType))
+ if (!isObjectCompatible(object, d))
return false;
d->property.append(&d->property, object);
@@ -297,7 +340,7 @@ Returns the list element at \a index, or 0 if the operation failed.
\sa canAt()
*/
-QObject *QQmlListReference::at(int index) const
+QObject *QQmlListReference::at(qsizetype index) const
{
if (!canAt()) return nullptr;
@@ -321,7 +364,7 @@ bool QQmlListReference::clear() const
/*!
Returns the number of objects in the list, or 0 if the operation failed.
*/
-int QQmlListReference::count() const
+qsizetype QQmlListReference::count() const
{
if (!canCount()) return 0;
@@ -329,6 +372,45 @@ int QQmlListReference::count() const
}
/*!
+\fn qsizetype QQmlListReference::size() const
+\since 6.2
+Returns the number of objects in the list, or 0 if the operation failed.
+*/
+
+/*!
+Replaces the item at \a index in the list with \a object.
+Returns true if the operation succeeded, otherwise false.
+
+\sa canReplace()
+*/
+bool QQmlListReference::replace(qsizetype index, QObject *object) const
+{
+ if (!canReplace())
+ return false;
+
+ if (!isObjectCompatible(object, d))
+ return false;
+
+ d->property.replace(&d->property, index, object);
+ return true;
+}
+
+/*!
+Removes the last item in the list.
+Returns true if the operation succeeded, otherwise false.
+
+\sa canRemoveLast()
+*/
+bool QQmlListReference::removeLast() const
+{
+ if (!canRemoveLast())
+ return false;
+
+ d->property.removeLast(&d->property);
+ return true;
+}
+
+/*!
\class QQmlListProperty
\since 5.0
\inmodule QtQml
@@ -365,7 +447,54 @@ Q_PROPERTY(QQmlListProperty<Fruit> fruit READ fruit)
QML list properties are type-safe - in this case \c {Fruit} is a QObject type that
\c {Apple}, \c {Orange} and \c {Banana} all derive from.
-\sa {Extending QML - Object and List Property Types Example}
+\sa {Chapter 5: Using List Property Types}
+*/
+
+/*!
+ \macro QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_APPEND
+ \relates QQmlListProperty
+
+ This macro defines the behavior of the list properties of this class to Append.
+ When assigning the property in a derived type, the values are appended
+ to those of the base class. This is the default behavior.
+
+ \snippet code/src_qml_qqmllist.cpp 0
+
+ \sa QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_REPLACE_IF_NOT_DEFAULT
+ \sa QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_REPLACE
+ \sa {Defining Object Types through QML Documents}
+*/
+
+/*!
+ \macro QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_REPLACE_IF_NOT_DEFAULT
+ \relates QQmlListProperty
+
+ This macro defines the behavior of the list properties of this class to
+ ReplaceIfNotDefault.
+ When assigning the property in a derived type, the values replace those of
+ the base class unless it's the default property.
+ In the case of the default property, values are appended to those of the base class.
+
+ \snippet code/src_qml_qqmllist.cpp 1
+
+ \sa QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_APPEND
+ \sa QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_REPLACE
+ \sa {Defining Object Types through QML Documents}
+*/
+
+/*!
+ \macro QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_REPLACE
+ \relates QQmlListProperty
+
+ This macro defines the behavior of the list properties of this class to Replace.
+ When assigning the property in a derived type, the values replace those
+ of the base class.
+
+ \snippet code/src_qml_qqmllist.cpp 2
+
+ \sa QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_APPEND
+ \sa QML_LIST_PROPERTY_ASSIGN_BEHAVIOR_REPLACE_IF_NOT_DEFAULT
+ \sa {Defining Object Types through QML Documents}
*/
/*!
@@ -375,14 +504,25 @@ QML list properties are type-safe - in this case \c {Fruit} is a QObject type th
/*!
\fn template<typename T> QQmlListProperty<T>::QQmlListProperty(QObject *object, QList<T *> &list)
+\deprecated
Convenience constructor for making a QQmlListProperty value from an existing
QList \a list. The \a list reference must remain valid for as long as \a object
exists. \a object must be provided.
-Generally this constructor should not be used in production code, as a
-writable QList violates QML's memory management rules. However, this constructor
-can be very useful while prototyping.
+This constructor synthesizes the removeLast() and replace() methods
+introduced in Qt 5.15, using count(), at(), clear(), and append(). This is slow.
+If you intend to manipulate the list beyond clearing it, you should explicitly
+provide these methods.
+*/
+
+/*!
+\fn template<typename T> QQmlListProperty<T>::QQmlListProperty(QObject *object, QList<T *> *list)
+\since 5.15
+
+Convenience constructor for making a QQmlListProperty value from an existing
+QList \a list. The \a list reference must remain valid for as long as \a object
+exists. \a object must be provided.
*/
/*!
@@ -408,6 +548,39 @@ remains valid while \a object exists.
Null pointers can be passed for any function. If any null pointers are passed in, the list
will be neither designable nor alterable by the debugger. It is recommended to provide valid
pointers for all functions.
+
+\note The resulting QQmlListProperty will synthesize the removeLast() and
+replace() methods using \a count, \a at, \a clear, and \a append if all of those
+are given. This is slow. If you intend to manipulate the list beyond clearing it,
+you should explicitly provide these methods.
+*/
+
+/*!
+\fn template<typename T> QQmlListProperty<T>::QQmlListProperty(
+ QObject *object, void *data, AppendFunction append, CountFunction count,
+ AtFunction at, ClearFunction clear, ReplaceFunction replace,
+ RemoveLastFunction removeLast)
+
+Construct a QQmlListProperty from a set of operation functions \a append,
+\a count, \a at, \a clear, \a replace, and \removeLast. An opaque \a data handle
+may be passed which can be accessed from within the operation functions. The
+list property remains valid while \a object exists.
+
+Null pointers can be passed for any function, causing the respective function to
+be synthesized using the others, if possible. QQmlListProperty can synthesize
+\list
+ \li \a clear using \a count and \a removeLast
+ \li \a replace using \a count, \a at, \a clear, and \a append
+ \li \a replace using \a count, \a at, \a removeLast, and \a append
+ \li \a removeLast using \a count, \a at, \a clear, and \a append
+\endlist
+if those are given. This is slow, but if your list does not natively provide
+faster options for these primitives, you may want to use the synthesized ones.
+
+Furthermore, if either of \a count, \a at, \a append, and \a clear are neither
+given explicitly nor synthesized, the list will be neither designable nor
+alterable by the debugger. It is recommended to provide enough valid pointers
+to avoid this situation.
*/
/*!
@@ -421,7 +594,7 @@ Append the \a value to the list \a property.
/*!
\typedef QQmlListProperty::CountFunction
-Synonym for \c {int (*)(QQmlListProperty<T> *property)}.
+Synonym for \c {qsizetype (*)(QQmlListProperty<T> *property)}.
Return the number of elements in the list \a property.
*/
@@ -435,7 +608,7 @@ Returns true if this QQmlListProperty is equal to \a other, otherwise false.
/*!
\typedef QQmlListProperty::AtFunction
-Synonym for \c {T *(*)(QQmlListProperty<T> *property, int index)}.
+Synonym for \c {T *(*)(QQmlListProperty<T> *property, qsizetype index)}.
Return the element at position \a index in the list \a property.
*/
@@ -448,4 +621,31 @@ Synonym for \c {void (*)(QQmlListProperty<T> *property)}.
Clear the list \a property.
*/
+/*!
+\typedef QQmlListProperty::ReplaceFunction
+
+Synonym for \c {void (*)(QQmlListProperty<T> *property, qsizetype index, T *value)}.
+
+Replace the element at position \a index in the list \a property with \a value.
+*/
+
+/*!
+\typedef QQmlListProperty::RemoveLastFunction
+
+Synonym for \c {void (*)(QQmlListProperty<T> *property)}.
+
+Remove the last element from the list \a property.
+*/
+
+/*!
+\fn bool QQmlListReference::operator==(const QQmlListReference &other) const
+
+Compares this QQmlListReference to \a other, and returns \c true if they are
+equal. The two are only considered equal if one was created from the other
+via copy assignment or copy construction.
+
+\note Independently created references to the same object are not considered
+to be equal.
+*/
+
QT_END_NAMESPACE