Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qqmllistaccessor.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#include <private/qqmlmetatype_p.h>
7
8#include <QtCore/qdebug.h>
9#include <QtCore/qsequentialiterable.h>
10#include <QtCore/qstringlist.h>
11#include <QtCore/qurl.h>
12
14
19
23
25{
26 return d;
27}
28
30{
31 d = v;
32
33 // An incoming JS array as model is treated as a variant list, so we need to
34 // convert it first with toVariant().
35 QMetaType variantsType = d.metaType();
36 if (variantsType == QMetaType::fromType<QJSValue>()) {
37 d = d.value<QJSValue>().toVariant();
38 variantsType = d.metaType();
39 }
40
41 if (!d.isValid()) {
42 m_type = Invalid;
43 return;
44 }
45
46 if (variantsType == QMetaType::fromType<QStringList>()) {
47 m_type = StringList;
48 return;
49 }
50
51 if (variantsType == QMetaType::fromType<QList<QUrl>>()) {
52 m_type = UrlList;
53 return;
54 }
55
56 if (variantsType == QMetaType::fromType<QVariantList>()) {
57 m_type = VariantList;
58 return;
59 }
60
61 if (variantsType == QMetaType::fromType<QList<QObject *>>()) {
62 m_type = ObjectList;
63 return;
64 }
65
66 if (variantsType.flags() & QMetaType::IsQmlList) {
68 m_type = ListProperty;
69 return;
70 }
71
72 if (variantsType == QMetaType::fromType<QQmlListReference>()) {
73 m_type = ListProperty;
74 return;
75 }
76
77 if (variantsType.flags() & QMetaType::PointerToQObject) {
78 m_type = Instance;
79 return;
80 }
81
82 if (int i = 0; [&](){bool ok = false; i = v.toInt(&ok); return ok;}()) {
83 // Here we have to check for an upper limit, because down the line code might (well, will)
84 // allocate memory depending on the number of elements. The upper limit cannot be INT_MAX:
85 // QVector<QPointer<QQuickItem>> something;
86 // something.resize(count());
87 // (See e.g. QQuickRepeater::regenerate())
88 // This will allocate data along the lines of:
89 // sizeof(QPointer<QQuickItem>) * count() + QVector::headerSize
90 // So, doing an approximate round-down-to-nice-number, we get:
91 const int upperLimit = 100 * 1000 * 1000;
92
93 if (i < 0) {
94 qWarning("Model size of %d is less than 0", i);
95 m_type = Invalid;
96 return;
97 }
98
99 if (i > upperLimit) {
100 qWarning("Model size of %d is bigger than the upper limit %d", i, upperLimit);
101 m_type = Invalid;
102 return;
103 }
104
105 m_type = Integer;
106 d = i;
107 return;
108 }
109
110 const QQmlType type = QQmlMetaType::qmlListType(variantsType);
111 if (type.isSequentialContainer()) {
112 m_metaSequence = type.listMetaSequence();
113 m_type = Sequence;
114 return;
115 }
116
117 QSequentialIterable iterable;
119 variantsType, d.constData(),
120 QMetaType::fromType<QSequentialIterable>(), &iterable)) {
121 const QMetaSequence sequence = iterable.metaContainer();
122
123 if (sequence.hasSize() && sequence.canGetValueAtIndex()) {
124 // If the resulting iterable is useful for anything, use it.
125 m_metaSequence = sequence;
126 m_type = Sequence;
127 return;
128 }
129
130 if (sequence.hasConstIterator() && sequence.canGetValueAtConstIterator()) {
131 // As a last resort, try to read the contents of the container via an iterator
132 // and build a QVariantList from them.
133 QVariantList variantList;
134 for (auto it = iterable.constBegin(), end = iterable.constEnd(); it != end; ++it)
135 variantList.push_back(*it);
136 d = std::move(variantList);
137 m_type = VariantList;
138 return;
139 }
140 }
141
142 m_type = Instance;
143 return;
144}
145
147{
148 switch(m_type) {
149 case StringList:
150 Q_ASSERT(d.metaType() == QMetaType::fromType<QStringList>());
151 return reinterpret_cast<const QStringList *>(d.constData())->size();
152 case UrlList:
153 Q_ASSERT(d.metaType() == QMetaType::fromType<QList<QUrl>>());
154 return reinterpret_cast<const QList<QUrl> *>(d.constData())->size();
155 case VariantList:
156 Q_ASSERT(d.metaType() == QMetaType::fromType<QVariantList>());
157 return reinterpret_cast<const QVariantList *>(d.constData())->size();
158 case ObjectList:
159 Q_ASSERT(d.metaType() == QMetaType::fromType<QList<QObject *>>());
160 return reinterpret_cast<const QList<QObject *> *>(d.constData())->size();
161 case ListProperty:
162 Q_ASSERT(d.metaType() == QMetaType::fromType<QQmlListReference>());
163 return reinterpret_cast<const QQmlListReference *>(d.constData())->count();
164 case Sequence:
165 Q_ASSERT(m_metaSequence != QMetaSequence());
166 return m_metaSequence.size(d.constData());
167 case Instance:
168 return 1;
169 case Integer:
170 return *reinterpret_cast<const int *>(d.constData());
171 case Invalid:
172 return 0;
173 }
174 Q_UNREACHABLE_RETURN(0);
175}
176
178{
179 Q_ASSERT(idx >= 0 && idx < count());
180 switch(m_type) {
181 case StringList:
182 Q_ASSERT(d.metaType() == QMetaType::fromType<QStringList>());
183 return QVariant::fromValue(reinterpret_cast<const QStringList *>(d.constData())->at(idx));
184 case UrlList:
185 Q_ASSERT(d.metaType() == QMetaType::fromType<QList<QUrl>>());
186 return QVariant::fromValue(reinterpret_cast<const QList<QUrl> *>(d.constData())->at(idx));
187 case VariantList:
188 Q_ASSERT(d.metaType() == QMetaType::fromType<QVariantList>());
189 return reinterpret_cast<const QVariantList *>(d.constData())->at(idx);
190 case ObjectList:
191 Q_ASSERT(d.metaType() == QMetaType::fromType<QList<QObject *>>());
192 return QVariant::fromValue(reinterpret_cast<const QList<QObject *> *>(d.constData())->at(idx));
193 case ListProperty:
194 Q_ASSERT(d.metaType() == QMetaType::fromType<QQmlListReference>());
195 return QVariant::fromValue(reinterpret_cast<const QQmlListReference *>(d.constData())->at(idx));
196 case Sequence: {
197 Q_ASSERT(m_metaSequence != QMetaSequence());
199 const QMetaType valueMetaType = m_metaSequence.valueMetaType();
200 if (valueMetaType == QMetaType::fromType<QVariant>()) {
201 m_metaSequence.valueAtIndex(d.constData(), idx, &result);
202 } else {
203 result = QVariant(valueMetaType);
204 m_metaSequence.valueAtIndex(d.constData(), idx, result.data());
205 }
206 return result;
207 }
208 case Instance:
209 return d;
210 case Integer:
211 return QVariant(idx);
212 case Invalid:
213 return QVariant();
214 }
215 Q_UNREACHABLE_RETURN(QVariant());
216}
217
219{
220 Q_ASSERT(idx >= 0 && idx < count());
221 switch (m_type) {
222 case StringList:
223 Q_ASSERT(d.metaType() == QMetaType::fromType<QStringList>());
224 (*static_cast<QStringList *>(d.data()))[idx] = value.toString();
225 break;
226 case UrlList:
227 Q_ASSERT(d.metaType() == QMetaType::fromType<QList<QUrl>>());
228 (*static_cast<QList<QUrl> *>(d.data()))[idx] = value.value<QUrl>();
229 break;
230 case VariantList:
231 Q_ASSERT(d.metaType() == QMetaType::fromType<QVariantList>());
232 (*static_cast<QVariantList *>(d.data()))[idx] = value;
233 break;
234 case ObjectList:
235 Q_ASSERT(d.metaType() == QMetaType::fromType<QList<QObject *>>());
236 (*static_cast<QList<QObject *> *>(d.data()))[idx] = value.value<QObject *>();
237 break;
238 case ListProperty:
239 Q_ASSERT(d.metaType() == QMetaType::fromType<QQmlListReference>());
240 static_cast<QQmlListReference *>(d.data())->replace(idx, value.value<QObject *>());
241 break;
242 case Sequence: {
243 Q_ASSERT(m_metaSequence != QMetaSequence());
244 const QMetaType valueMetaType = m_metaSequence.valueMetaType();
245 if (valueMetaType == QMetaType::fromType<QVariant>()) {
246 m_metaSequence.setValueAtIndex(d.data(), idx, &value);
247 } else if (valueMetaType == value.metaType()) {
248 m_metaSequence.setValueAtIndex(d.data(), idx, value.constData());
249 } else {
250 QVariant converted = value;
251 converted.convert(valueMetaType);
252 m_metaSequence.setValueAtIndex(d.data(), idx, converted.constData());
253 }
254 break;
255 }
256 case Instance:
257 d = value;
258 break;
259 case Integer:
260 break;;
261 case Invalid:
262 break;
263 }
264}
265
267{
268 return m_type != Invalid;
269}
270
The QJSValue class acts as a container for Qt/JavaScript data types.
Definition qjsvalue.h:31
void push_back(parameter_type t)
Definition qlist.h:675
bool hasSize() const
Returns true if the container can be queried for its size, false otherwise.
qsizetype size(const void *container) const
Returns the number of values in the given container if it can be queried for its size.
bool hasConstIterator() const
Returns true if the underlying container offers a const iterator, false otherwise.
\inmodule QtCore
void setValueAtIndex(void *container, qsizetype index, const void *value) const
Overwrites the value at index in the container using the value passed as parameter if that is possibl...
bool canGetValueAtIndex() const
Returns true if values can be retrieved from the container by index, otherwise false.
bool canGetValueAtConstIterator() const
Returns true if the underlying container can retrieve the value pointed to by a const iterator,...
QMetaType valueMetaType() const
Returns the meta type for values stored in the container.
void valueAtIndex(const void *container, qsizetype index, void *result) const
Retrieves the value at index in the container and places it in the memory location pointed to by resu...
\inmodule QtCore
Definition qmetatype.h:341
static constexpr QMetaType fromType()
Definition qmetatype.h:2642
@ PointerToQObject
Definition qmetatype.h:406
static bool convert(QMetaType fromType, const void *from, QMetaType toType, void *to)
Converts the object at from from fromType to the preallocated space at to typed toType.
\inmodule QtCore
Definition qobject.h:103
QVariant at(qsizetype) const
qsizetype count() const
void set(qsizetype, const QVariant &)
void setList(const QVariant &)
QVariant list() const
The QQmlListReference class allows the manipulation of QQmlListProperty properties.
Definition qqmllist.h:183
QObject * at(qsizetype) const
Returns the list element at index, or 0 if the operation failed.
Definition qqmllist.cpp:343
static QQmlType qmlListType(QMetaType metaType)
The QSequentialIterable class is an iterable interface for a container in a QVariant.
const_iterator constBegin() const noexcept
Definition qset.h:139
\inmodule QtCore
\inmodule QtCore
Definition qurl.h:94
\inmodule QtCore
Definition qvariant.h:65
void * data()
Returns a pointer to the contained object as a generic void* that can be written to.
bool convert(QMetaType type)
Casts the variant to the requested type, targetType.
T value() const &
Definition qvariant.h:516
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
Definition qvariant.h:714
static auto fromValue(T &&value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::conjunction_v< std::is_copy_constructible< T >, std::is_destructible< T > >, QVariant >
Definition qvariant.h:536
QMetaType metaType() const
const void * constData() const
Definition qvariant.h:451
QSet< QString >::iterator it
Combined button and popup list for selecting options.
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qWarning
Definition qlogging.h:166
@ Invalid
GLsizei const GLfloat * v
[13]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint GLuint end
GLenum type
GLuint64EXT * result
[6]
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
ptrdiff_t qsizetype
Definition qtypes.h:165
static QVariant toVariant(const QV4::Value &value, QMetaType typeHint, JSToQVariantConversionBehavior conversionBehavior, V4ObjectSet *visitedObjects)
QAction * at