Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmldmlistaccessordata_p.h
Go to the documentation of this file.
1// Copyright (C) 2023 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// Qt-Security score:significant
4
5#ifndef QQMLDMLISTACCESSORDATA_P_H
6#define QQMLDMLISTACCESSORDATA_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <private/qqmladaptormodelenginedata_p.h>
20#include <private/qqmldelegatemodel_p_p.h>
21#include <private/qobject_p.h>
22
23QT_BEGIN_NAMESPACE
24
25class VDMListDelegateDataType;
26
28{
29 Q_OBJECT
30 Q_PROPERTY(QVariant modelData READ modelData WRITE setModelData NOTIFY modelDataChanged)
32public:
36 const QVariant &value);
38
40 {
41 return cachedData;
42 }
43
44 void setModelData(const QVariant &data);
45
46 static QV4::ReturnedValue get_modelData(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
47 {
48 QV4::ExecutionEngine *v4 = b->engine();
49 const QQmlDelegateModelItemObject *o = thisObject->as<QQmlDelegateModelItemObject>();
50 if (!o)
51 return v4->throwTypeError(QStringLiteral("Not a valid DelegateModel object"));
52
53 return v4->fromVariant(static_cast<QQmlDMListAccessorData *>(o->d()->item())->cachedData);
54 }
55
56 static QV4::ReturnedValue set_modelData(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
57 {
58 QV4::ExecutionEngine *v4 = b->engine();
59 const QQmlDelegateModelItemObject *o = thisObject->as<QQmlDelegateModelItemObject>();
60 if (!o)
61 return v4->throwTypeError(QStringLiteral("Not a valid DelegateModel object"));
62 if (!argc)
63 return v4->throwTypeError();
64
65 static_cast<QQmlDMListAccessorData *>(o->d()->item())->setModelData(
66 QV4::ExecutionEngine::toVariant(argv[0], QMetaType {}));
67 return QV4::Encode::undefined();
68 }
69
70 QV4::ReturnedValue get() override
71 {
72 QV4::Scope scope(metaType()->v4Engine);
73 QQmlAdaptorModelEngineData *data = QQmlAdaptorModelEngineData::get(scope.engine);
74 QV4::ScopedObject o(
75 scope, scope.engine->memoryManager->allocate<QQmlDelegateModelItemObject>(this));
76 QV4::ScopedObject p(scope, data->listItemProto.value());
77 o->setPrototypeOf(p);
78 return o.asReturnedValue();
79 }
80
81 void setValue(const QString &role, const QVariant &value) override;
82 bool resolveIndex(const QQmlAdaptorModel &model, int idx) override;
83
86
87private:
89 QVariant cachedData;
90
91 // Gets cleaned when the metaobject has processed it.
92 bool cachedDataClean = false;
93};
94
95
100{
101public:
102 VDMListDelegateDataType(QQmlAdaptorModel *model)
103 : model(model)
104 {
105 QQmlAdaptorModelEngineData::setModelDataType<QQmlDMListAccessorData>(&builder, this);
106 metaObject.reset(builder.toMetaObject());
107 *static_cast<QMetaObject *>(this) = *metaObject.data();
108 }
109
110 void cleanup(QQmlAdaptorModel &) const override
111 {
112 release();
113 }
114
115 int rowCount(const QQmlAdaptorModel &model) const override
116 {
117 return model.list.count();
118 }
119
120 int columnCount(const QQmlAdaptorModel &model) const override
121 {
122 switch (model.list.type()) {
123 case QQmlListAccessor::Invalid:
124 return 0;
125 case QQmlListAccessor::StringList:
126 case QQmlListAccessor::UrlList:
127 case QQmlListAccessor::Integer:
128 return 1;
129 default:
130 break;
131 }
132
133 // If there are no properties, we can get modelData itself.
134 return std::max(1, propertyCount() - propertyOffset);
135 }
136
137 static const QMetaObject *metaObjectFromType(QMetaType type)
138 {
139 if (const QMetaObject *metaObject = type.metaObject())
140 return metaObject;
141
142 // NB: This acquires the lock on QQmlMetaTypeData. If we had a QQmlEngine here,
143 // we could use QQmlGadgetPtrWrapper::instance() to avoid this.
144 if (const QQmlValueType *valueType = QQmlMetaType::valueType(type))
145 return valueType->staticMetaObject();
146
147 return nullptr;
148 }
149
150 template<typename String>
151 static QString toQString(const String &string)
152 {
153 if constexpr (std::is_same_v<String, QString>)
154 return string;
155 else if constexpr (std::is_same_v<String, QByteArray>)
156 return QString::fromUtf8(string);
157 else if constexpr (std::is_same_v<String, const char *>)
158 return QString::fromUtf8(string);
159 else
160 static_assert(QtPrivate::type_dependent_false<String>::value, "unsupported string type");
161 }
162
163 template<typename String>
164 static QByteArray toUtf8(const String &string)
165 {
166 if constexpr (std::is_same_v<String, QString>)
167 return string.toUtf8();
168 else if constexpr (std::is_same_v<String, QByteArray>)
169 return string;
170 else if constexpr (std::is_same_v<String, const char *>)
171 return QByteArray::fromRawData(string, qstrlen(string));
172 else
173 static_assert(QtPrivate::type_dependent_false<String>::value, "unsupported string type");
174 }
175
176 template<typename String>
177 static QVariant value(const QVariant *row, const String &role)
178 {
179 const QMetaType type = row->metaType();
180 if (type == QMetaType::fromType<QVariantMap>())
181 return row->toMap().value(toQString(role));
182
183 if (type == QMetaType::fromType<QVariantHash>())
184 return row->toHash().value(toQString(role));
185
186 const QMetaType::TypeFlags typeFlags = type.flags();
187 if (typeFlags & QMetaType::PointerToQObject)
188 return row->value<QObject *>()->property(toUtf8(role));
189
190 if (const QMetaObject *metaObject = metaObjectFromType(type)) {
191 const int propertyIndex = metaObject->indexOfProperty(toUtf8(role));
192 if (propertyIndex >= 0)
193 return metaObject->property(propertyIndex).readOnGadget(row->constData());
194 }
195
196 return QVariant();
197 }
198
199 template<typename String>
200 void createPropertyIfMissing(const String &string)
201 {
202 for (int i = 0, end = propertyCount(); i < end; ++i) {
203 if (QAnyStringView(property(i).name()) == QAnyStringView(string))
204 return;
205 }
206
207 createProperty(toUtf8(string), nullptr);
208 }
209
210 void createMissingProperties(const QVariant *row)
211 {
212 const QMetaType type = row->metaType();
213 if (type == QMetaType::fromType<QVariantMap>()) {
214 const QVariantMap map = row->toMap();
215 for (auto it = map.keyBegin(), end = map.keyEnd(); it != end; ++it)
216 createPropertyIfMissing(*it);
217 } else if (type == QMetaType::fromType<QVariantHash>()) {
218 const QVariantHash map = row->toHash();
219 for (auto it = map.keyBegin(), end = map.keyEnd(); it != end; ++it)
220 createPropertyIfMissing(*it);
221 } else if (type.flags() & QMetaType::PointerToQObject) {
222 const QMetaObject *metaObject = row->value<QObject *>()->metaObject();
223 for (int i = 0, end = metaObject->propertyCount(); i < end; ++i)
224 createPropertyIfMissing(metaObject->property(i).name());
225 } else if (const QMetaObject *metaObject = metaObjectFromType(type)) {
226 for (int i = 0, end = metaObject->propertyCount(); i < end; ++i)
227 createPropertyIfMissing(metaObject->property(i).name());
228 }
229 }
230
231 template<typename String>
232 static void setValue(QVariant *row, const String &role, const QVariant &value)
233 {
234 const QMetaType type = row->metaType();
235 if (type == QMetaType::fromType<QVariantMap>()) {
236 static_cast<QVariantMap *>(row->data())->insert(toQString(role), value);
237 } else if (type == QMetaType::fromType<QVariantHash>()) {
238 static_cast<QVariantHash *>(row->data())->insert(toQString(role), value);
239 } else if (type.flags() & QMetaType::PointerToQObject) {
240 row->value<QObject *>()->setProperty(toUtf8(role), value);
241 } else if (const QMetaObject *metaObject = metaObjectFromType(type)) {
242 const int propertyIndex = metaObject->indexOfProperty(toUtf8(role));
243 if (propertyIndex >= 0)
244 metaObject->property(propertyIndex).writeOnGadget(row->data(), value);
245 }
246 }
247
248 QVariant value(const QQmlAdaptorModel &model, int index, const QString &role) const override
249 {
250 const QVariant entry = model.list.at(index);
251 if (role == QLatin1String("modelData") || role.isEmpty())
252 return entry;
253
254 return value(&entry, role);
255 }
256
258 QQmlAdaptorModel &model,
259 const QQmlRefPointer<QQmlDelegateModelItemMetaType> &metaType,
260 int index, int row, int column) override
261 {
262 const QVariant value = (index >= 0 && index < model.list.count())
263 ? model.list.at(index)
264 : QVariant();
265 return new QQmlDMListAccessorData(metaType, this, index, row, column, value);
266 }
267
268 bool notify(const QQmlAdaptorModel &model, const QList<QQmlDelegateModelItem *> &items, int index, int count, const QList<int> &) const override
269 {
270 for (auto modelItem : items) {
271 const int modelItemIndex = modelItem->modelIndex();
272 if (modelItemIndex < index || modelItemIndex >= index + count)
273 continue;
274
275 auto listModelItem = static_cast<QQmlDMListAccessorData *>(modelItem);
276 QVariant updatedModelData = model.list.at(listModelItem->modelIndex());
277 listModelItem->setModelData(updatedModelData);
278 }
279 return true;
280 }
281
282 void emitAllSignals(QQmlDMListAccessorData *accessor) const;
283
284 int metaCall(QObject *object, QMetaObject::Call call, int id, void **arguments) final;
285 int createProperty(const char *name, const char *) final;
286#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)
288#else
289 QMetaObject *toDynamicMetaObject(QObject *accessors) final;
290#endif
291
296};
297
298QT_END_NAMESPACE
299
300#endif // QQMLDMLISTACCESSORDATA_P_H
void setModelData(const QVariant &data)
bool resolveIndex(const QQmlAdaptorModel &model, int idx) override
void setValue(const QString &role, const QVariant &value) override
static QV4::ReturnedValue get_modelData(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
static QV4::ReturnedValue set_modelData(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
QV4::ReturnedValue get() override
void emitAllSignals(QQmlDMListAccessorData *accessor) const
bool notify(const QQmlAdaptorModel &model, const QList< QQmlDelegateModelItem * > &items, int index, int count, const QList< int > &) const override
void createMissingProperties(const QVariant *row)
int rowCount(const QQmlAdaptorModel &model) const override
const QMetaObject * toDynamicMetaObject(QObject *accessors) const final
VDMListDelegateDataType(QQmlAdaptorModel *model)
int createProperty(const char *name, const char *) final
static const QMetaObject * metaObjectFromType(QMetaType type)
static QString toQString(const String &string)
QQmlDelegateModelItem * createItem(QQmlAdaptorModel &model, const QQmlRefPointer< QQmlDelegateModelItemMetaType > &metaType, int index, int row, int column) override
int metaCall(QObject *object, QMetaObject::Call call, int id, void **arguments) final
static QVariant value(const QVariant *row, const String &role)
void createPropertyIfMissing(const String &string)
QVariant value(const QQmlAdaptorModel &model, int index, const QString &role) const override
static QByteArray toUtf8(const String &string)
int columnCount(const QQmlAdaptorModel &model) const override
static void setValue(QVariant *row, const String &role, const QVariant &value)
void cleanup(QQmlAdaptorModel &) const override