7#include <private/qjsvalue_p.h>
9#include <private/qqmlcustomparser_p.h>
10#include <private/qqmlengine_p.h>
11#include <private/qqmljsast_p.h>
12#include <private/qqmljsengine_p.h>
13#include <private/qqmllistwrapper_p.h>
14#include <private/qqmlnotifier_p.h>
15#include <private/qqmlopenmetaobject_p.h>
17#include <private/qv4alloca_p.h>
18#include <private/qv4dateobject_p.h>
19#include <private/qv4lookup_p.h>
20#include <private/qv4object_p.h>
21#include <private/qv4objectiterator_p.h>
22#include <private/qv4qmlcontext_p.h>
23#include <private/qv4sequenceobject_p.h>
24#include <private/qv4urlobject_p.h>
29#include <QtCore/qdebug.h>
30#include <QtCore/qstack.h>
31#include <QXmlStreamReader>
32#include <QtCore/qdatetime.h>
33#include <QScopedValueRollback>
47 for (
size_t i=0 ;
i <
sizeof(T) ; ++
i) {
57 static const QString roleTypeNames[] = {
64 return roleTypeNames[
t];
94 return createRole(qkey,
type);
99 const int dataSizes[] = {
110 const int dataAlignments[] = {
129 r->subLayout =
nullptr;
133 int dataAlignment = dataAlignments[
type];
135 int dataOffset = (currentBlockOffset + dataAlignment-1) & ~(dataAlignment-1);
137 r->blockIndex = ++currentBlock;
141 r->blockIndex = currentBlock;
142 r->blockOffset = dataOffset;
143 currentBlockOffset = dataOffset +
dataSize;
146 int roleIndex = roles.size();
147 r->index = roleIndex;
150 roleHash.insert(
key,
r);
157 const int otherRolesCount =
other->roles.size();
158 roles.reserve(otherRolesCount);
159 for (
int i=0 ;
i < otherRolesCount; ++
i) {
162 roleHash.insert(role->
name, role);
164 currentBlockOffset =
other->currentBlockOffset;
165 currentBlock =
other->currentBlock;
175 int roleOffset =
target->roles.size();
176 int newRoleCount =
src->roles.size() - roleOffset;
178 for (
int i=0 ;
i < newRoleCount ; ++
i) {
180 target->roles.append(role);
184 target->currentBlockOffset =
src->currentBlockOffset;
185 target->currentBlock =
src->currentBlock;
195 if (
other->subLayout)
210 switch (
data.userType()) {
219 if (
data.userType() == qMetaTypeId<QJSValue>() &&
223 }
else if (
data.userType() == qMetaTypeId<const QV4::CompiledData::Binding*>()
238 qmlWarning(
nullptr) <<
"Can't create role for unsupported data type";
275 arrayData = dataPointer->d_ptr();
277 stringSize = mutableString.size();
285 this->binding = binding;
308void StringOrTranslation::clear()
310 if (arrayData && !arrayData->deref())
321 if (e->m_objectCache ==
nullptr) {
333 return e->m_objectCache;
340 bool hasChanges =
false;
343 QHash<int, ElementSync> elementHash;
344 for (
int i = 0;
i <
target->elements.count(); ++
i) {
346 int uid = e->getUid();
349 sync.targetIndex =
i;
350 elementHash.insert(uid,
sync);
352 for (
int i = 0;
i <
src->elements.count(); ++
i) {
354 int uid = e->getUid();
357 if (
it == elementHash.
end()) {
361 elementHash.insert(uid,
sync);
363 ElementSync &
sync =
it.value();
373 for (
int i = 0 ;
i <
target->elements.count() ; ++
i) {
375 ElementSync &
s = elementHash.find(element->getUid()).value();
378 s.targetIndex -= rowsRemoved;
379 if (
s.src ==
nullptr) {
384 s.target->destroy(
target->m_layout);
385 target->elements.removeOne(
s.target);
388 targetModel->endRemoveRows();
400 for (
int i = 0;
i <
src->elements.count(); ++
i) {
402 ElementSync &
s = elementHash.find(srcElement->getUid()).value();
405 if (targetElement ==
nullptr) {
406 targetElement =
new ListElement(srcElement->getUid());
409 target->elements.append(targetElement);
412 target->updateCacheIndices();
415 for (
int i=0 ;
i <
target->elements.count() ; ++
i) {
426 int rowsInserted = 0;
427 const int targetElementCount =
target->elements.count();
428 for (
int i = 0 ;
i < targetElementCount ; ++
i) {
430 ElementSync &
s = elementHash.find(element->getUid()).value();
432 s.srcIndex += rowsInserted;
433 if (
s.srcIndex !=
s.targetIndex) {
435 if (
s.targetIndex == -1) {
437 targetModel->endInsertRows();
442 targetModel->endMoveRows();
444 for (
int j=
i+1;
j < targetElementCount; ++
j) {
446 ElementSync &sToFix = elementHash.find(eToFix->getUid()).value();
447 if (
i <
s.targetIndex) {
449 if (sToFix.targetIndex >
s.targetIndex || sToFix.targetIndex <
i)
452 sToFix.targetIndex += 1;
455 if (sToFix.targetIndex <
s.targetIndex || sToFix.targetIndex >
i)
458 sToFix.targetIndex -= 1;
465 if (
s.targetIndex != -1 && !
s.changedRoles.isEmpty()) {
468 targetModel->dataChanged(idx, idx,
s.changedRoles);
481 for (
const auto &destroyer :
remove(0, elements.
count()))
485 if (m_modelCache && m_modelCache->m_primary ==
false)
487 m_modelCache =
nullptr;
492 int elementIndex = elements.
count();
493 newElement(elementIndex);
500 updateCacheIndices(
index);
514 QPODVector<ListElement *, 4> store;
515 for (
int i=0 ;
i < (to-from) ; ++
i)
516 store.append(elements[from+
n+
i]);
517 for (
int i=0 ;
i <
n ; ++
i)
518 store.append(elements[from+
i]);
519 for (
int i=0 ;
i < store.count() ; ++
i)
520 elements[from+
i] = store[
i];
522 updateCacheIndices(from, to +
n);
525void ListModel::newElement(
int index)
531void ListModel::updateCacheIndices(
int start,
int end)
535 if (end < 0 || end >
count)
541 mo->m_elementIndex =
i;
551 return e->getProperty(
r, owner, eng);
557 return e->getListProperty(role);
566 cache->updateValues();
583 propertyName =
it.nextPropertyNameAsString(propertyValue);
593 roleIndex = e->setStringProperty(
r,
s->toQString());
594 }
else if (propertyValue->
isNumber()) {
596 roleIndex = e->setDoubleProperty(
r, propertyValue->
asDouble());
607 roleIndex = e->setListProperty(
r, subModel);
610 roleIndex = e->setBoolProperty(
r, propertyValue->
booleanValue());
614 roleIndex = e->setDateTimeProperty(
r, dt);
618 roleIndex = e->setUrlProperty(
r, qurl);
624 roleIndex = e->setFunctionProperty(
r, jsv);
629 roleIndex = e->setQObjectProperty(role,
wrapper);
631 o->asReturnedValue(), QMetaType::fromType<QUrl>(),
true);
632 maybeUrl.metaType() == QMetaType::fromType<QUrl>()) {
634 QUrl qurl = maybeUrl.toUrl();
635 roleIndex = e->setUrlProperty(
r, qurl);
640 roleIndex = e->setVariantMapProperty(role,
obj);
646 e->clearProperty(*
r);
650 roles->append(roleIndex);
654 mo->updateValues(*roles);
672 propertyName =
it.nextPropertyNameAsString(propertyValue);
680 e->setStringPropertyFast(
r,
s->toQString());
681 }
else if (propertyValue->
isNumber()) {
684 e->setDoublePropertyFast(
r, propertyValue->
asDouble());
687 setArrayLike(&
o, propertyName, e,
a);
689 setArrayLike(&
o, propertyName, e,
s);
691 setArrayLike(&
o, propertyName, e, l);
701 e->setDateTimePropertyFast(
r, dt);
707 e->setUrlPropertyFast(
r, qurl);
713 e->setQObjectPropertyFast(
r,
wrapper);
716 o->asReturnedValue(), QMetaType::fromType<QUrl>(),
true);
717 if (maybeUrl.metaType() == QMetaType::fromType<QUrl>()) {
718 const QUrl qurl = maybeUrl.toUrl();
721 e->setUrlPropertyFast(
r, qurl);
725 e->setVariantMapFast(role,
o);
731 auto memberName = propertyName->toString(v4)->toQString();
737 e->clearProperty(*
r);
748 auto element = elements[
index+
i];
755 updateCacheIndices(
index);
776 if (elementIndex >= 0 && elementIndex < elements.
count()) {
781 roleIndex = e->setVariantProperty(*
r,
data);
785 if (roleIndex != -1 &&
cache)
786 cache->updateValues(QVector<int>(1, roleIndex));
797 if (elementIndex >= 0 && elementIndex < elements.
count()) {
801 roleIndex = e->setJsProperty(*
r,
data, eng);
812 if (e->next ==
nullptr) {
833 char *mem = getPropertyMemory(role);
840 char *mem = getPropertyMemory(role);
849 char *mem = getPropertyMemory(role);
850 if (isMemoryUsed<QVariantMap>(mem))
860 char *mem = getPropertyMemory(role);
861 if (isMemoryUsed<QDateTime>(mem))
871 char *mem = getPropertyMemory(role);
872 if (isMemoryUsed<QUrl>(mem))
873 url =
reinterpret_cast<QUrl *
>(mem);
882 char *mem = getPropertyMemory(role);
883 if (isMemoryUsed<QJSValue>(mem))
892 char *mem = getPropertyMemory(role);
894 bool existingGuard =
false;
898 existingGuard =
true;
913 char *mem = getPropertyMemory(role);
920 char *mem = getPropertyMemory(role);
927 double *
value =
reinterpret_cast<double *
>(mem);
942 bool *
value =
reinterpret_cast<bool *
>(mem);
952 if (
model->m_modelCache ==
nullptr) {
970 if (isMemoryUsed<QVariantMap>(mem)) {
978 if (isMemoryUsed<QDateTime>(mem)) {
986 if (isMemoryUsed<QUrl>(mem)) {
994 if (isMemoryUsed<QJSValue>(mem)) {
1012 char *mem = getPropertyMemory(role);
1015 if (!
c->isSet() ||
c->isTranslation())
1021 roleIndex = role.
index;
1032 char *mem = getPropertyMemory(role);
1033 double *
value =
reinterpret_cast<double *
>(mem);
1034 bool changed = *
value !=
d;
1037 roleIndex = role.
index;
1048 char *mem = getPropertyMemory(role);
1049 bool *
value =
reinterpret_cast<bool *
>(mem);
1050 bool changed = *
value !=
b;
1053 roleIndex = role.
index;
1064 char *mem = getPropertyMemory(role);
1071 roleIndex = role.
index;
1082 char *mem = getPropertyMemory(role);
1083 if (isMemoryUsed<QVariantMap>(mem))
1087 roleIndex = role.
index;
1098 char *mem = getPropertyMemory(role);
1099 if (isMemoryUsed<QVariantMap>(mem)) {
1104 roleIndex = role.
index;
1115 char *mem = getPropertyMemory(role);
1116 if (isMemoryUsed<QVariantMap>(mem)) {
1128 roleIndex = role.
index;
1139 char *mem = getPropertyMemory(role);
1140 if (isMemoryUsed<QDateTime>(mem)) {
1145 roleIndex = role.
index;
1156 char *mem = getPropertyMemory(role);
1157 if (isMemoryUsed<QUrl>(mem)) {
1158 QUrl *qurl =
reinterpret_cast<QUrl *
>(mem);
1162 roleIndex = role.
index;
1173 char *mem = getPropertyMemory(role);
1174 if (isMemoryUsed<QJSValue>(mem)) {
1179 roleIndex = role.
index;
1190 char *mem = getPropertyMemory(role);
1193 roleIndex = role.
index;
1202 char *mem = getPropertyMemory(role);
1208 char *mem = getPropertyMemory(role);
1209 double *
value =
new (mem)
double;
1215 char *mem = getPropertyMemory(role);
1216 bool *
value =
new (mem)
bool;
1222 char *mem = getPropertyMemory(role);
1228 char *mem = getPropertyMemory(role);
1235 char *mem = getPropertyMemory(role);
1237 *
map =
o->engine()->variantMapFromJS(
o);
1242 char *mem = getPropertyMemory(role);
1248 char *mem = getPropertyMemory(role);
1254 char *mem = getPropertyMemory(role);
1260 switch (role.
type) {
1262 setStringProperty(role,
QString());
1265 setDoubleProperty(role, 0.0);
1268 setBoolProperty(role,
false);
1271 setListProperty(role,
nullptr);
1274 setQObjectProperty(role,
nullptr);
1280 setUrlProperty(role,
QUrl());
1283 setVariantMapProperty(role, (
QVariantMap *)
nullptr);
1286 setFunctionProperty(role,
QJSValue());
1295 m_objectCache =
nullptr;
1303 m_objectCache =
nullptr;
1316 QVector<int> changedRoles;
1322 switch (srcRole.type) {
1329 if (targetSubModel ==
nullptr) {
1330 targetSubModel =
new ListModel(targetRole.subLayout,
nullptr);
1331 target->setListPropertyFast(targetRole, targetSubModel);
1334 roleIndex = targetRole.index;
1341 roleIndex =
target->setQObjectProperty(targetRole,
object);
1350 QVariant v =
src->getProperty(srcRole,
nullptr,
nullptr);
1351 roleIndex =
target->setVariantProperty(targetRole,
v);
1357 roleIndex =
target->setVariantMapProperty(targetRole,
map);
1364 changedRoles << roleIndex;
1367 return changedRoles;
1373 for (
int i=0 ;
i <
layout->roleCount() ; ++
i) {
1381 string->~StringOrTranslation();
1396 guard->~PersistentValue();
1433 if (m_objectCache) {
1435 operator delete(m_objectCache);
1440 next->destroy(
nullptr);
1448 switch (role.
type) {
1450 roleIndex = setDoubleProperty(role,
d.toDouble());
1453 if (
d.userType() == qMetaTypeId<const QV4::CompiledData::Binding *>())
1456 roleIndex = setStringProperty(role,
d.toString());
1459 roleIndex = setBoolProperty(role,
d.toBool());
1462 roleIndex = setListProperty(role,
d.value<
ListModel *>());
1466 roleIndex = setVariantMapProperty(role, &
map);
1470 roleIndex = setDateTimeProperty(role,
d.toDateTime());
1473 roleIndex = setUrlProperty(role,
d.toUrl());
1476 roleIndex = setFunctionProperty(role,
d.value<
QJSValue>());
1495 roleIndex = setStringProperty(role, qstr);
1496 }
else if (
d.isNumber()) {
1497 roleIndex = setDoubleProperty(role,
d.asDouble());
1508 subModel->append(
o);
1510 roleIndex = setListProperty(role, subModel);
1514 }
else if (
d.isBoolean()) {
1515 roleIndex = setBoolProperty(role,
d.booleanValue());
1519 roleIndex = setDateTimeProperty(role, dt);
1523 roleIndex = setUrlProperty(role, qurl);
1528 roleIndex = setFunctionProperty(role, jsv);
1529 }
else if (
d.isObject()) {
1533 roleIndex = setQObjectProperty(role,
wrapper);
1535 roleIndex = setVariantMapProperty(role,
o);
1538 o.asReturnedValue(), QMetaType::fromType<QUrl>(),
true);
1539 if (maybeUrl.metaType() == QMetaType::fromType<QUrl>()) {
1540 roleIndex = setUrlProperty(role, maybeUrl.toUrl());
1543 }
else if (
d.isNullOrUndefined()) {
1544 clearProperty(role);
1554void ModelNodeMetaObject::initialize()
1559 for (
int i = 0 ;
i < roleCount ; ++
i) {
1575 if (!m_initialized) {
1576 m_initialized =
true;
1591 if (!m_initialized) {
1593 Q_ALLOCA_VAR(
int, changedRoles, roleCount *
sizeof(
int));
1594 for (
int i = 0;
i < roleCount; ++
i)
1595 changedRoles[
i] =
i;
1596 emitDirectNotifies(changedRoles, roleCount);
1600 for (
int i=0 ;
i < roleCount ; ++
i) {
1610 if (!m_initialized) {
1611 emitDirectNotifies(roles.constData(), roles.size());
1614 int roleCount = roles.size();
1615 for (
int i=0 ;
i < roleCount ; ++
i) {
1616 int roleIndex = roles.at(
i);
1636 if (roleIndex != -1)
1641void ModelNodeMetaObject::emitDirectNotifies(
const int *changedRoles,
int roleCount)
1650 for (
int i = 0;
i < roleCount; ++
i) {
1651 const int changedRole = changedRoles[
i];
1662 QString propName =
id.toQString();
1667 const int elementIndex = that->d()->elementIndex();
1668 int roleIndex = that->d()->m_model->m_listModel->setExistingProperty(elementIndex, propName,
value, eng);
1669 if (roleIndex != -1)
1670 that->d()->m_model->emitItemsChanged(elementIndex, 1, QVector<int>(1, roleIndex));
1673 if (
mo->initialized())
1674 mo->emitPropertyNotification(propName.
toUtf8());
1698 const int elementIndex = that->d()->elementIndex();
1700 return that->engine()->fromVariant(
value);
1722 if (roleNameIndex < that->listModel()->roleCount()) {
1723 Scope scope(that->engine());
1732 if (
auto recursiveListModel = qvariant_cast<QQmlListModel*>(
value)) {
1733 auto size = recursiveListModel->count();
1735 for (
auto i = 0;
i <
size;
i++) {
1737 v4, recursiveListModel->get(
i)));
1744 return roleName->toPropertyKey();
1772 object->updateValues(
obj, roles);
1778 QVector<int> changedRoles;
1779 for (
int i = 0;
i <
src->m_meta->count(); ++
i) {
1786 bool modelHasChanges =
false;
1788 if (targetModel ==
nullptr)
1789 targetModel = QQmlListModel::createWithOwner(
target->m_owner);
1793 QObject *targetModelObject = targetModel;
1795 }
else if (targetModel) {
1802 return changedRoles;
1807 for (
auto it =
object.cbegin(),
end =
object.cend();
it !=
end; ++
it) {
1810 int roleIndex = m_owner->m_roles.indexOf(
key);
1811 if (roleIndex == -1) {
1812 roleIndex = m_owner->m_roles.size();
1813 m_owner->m_roles.append(
key);
1820 if (
value.userType() == qMetaTypeId<QJSValue>())
1823 if (
value.userType() == QMetaType::QVariantList) {
1824 QQmlListModel *subModel = QQmlListModel::createWithOwner(m_owner);
1827 QVariantList::const_iterator subIt = subArray.
cbegin();
1828 QVariantList::const_iterator subEnd = subArray.cend();
1829 while (subIt != subEnd) {
1835 QObject *subModelObject = subModel;
1842 delete existingModel;
1856 for (
int i=0 ;
i <
count() ; ++
i) {
1883 if (
v.userType() == qMetaTypeId<QJSValue>())
1886 if (
v.userType() == QMetaType::QVariantList) {
1887 QQmlListModel *subModel = QQmlListModel::createWithOwner(parentModel);
1890 QVariantList::const_iterator subIt = subArray.
cbegin();
1891 QVariantList::const_iterator subEnd = subArray.cend();
1892 while (subIt != subEnd) {
1898 QObject *subModelObject = subModel;
1904 int elementIndex = parentModel->m_modelObjects.indexOf(m_owner);
1905 if (elementIndex != -1) {
1907 if (roleIndex != -1)
1908 parentModel->emitItemsChanged(elementIndex, 1, QVector<int>(1, roleIndex));
2014 m_mainThread =
true;
2017 m_dynamicRoles =
false;
2020 m_listModel =
new ListModel(m_layout,
this);
2028 m_mainThread = owner->m_mainThread;
2030 m_agent = owner->m_agent;
2032 Q_ASSERT(owner->m_dynamicRoles ==
false);
2033 m_dynamicRoles =
false;
2038 m_compilationUnit = owner->m_compilationUnit;
2044 m_mainThread =
false;
2047 m_dynamicRoles = orig->m_dynamicRoles;
2050 m_listModel =
new ListModel(m_layout,
this);
2058 m_compilationUnit = orig->m_compilationUnit;
2069 if (m_mainThread && m_agent) {
2075 m_listModel =
nullptr;
2085 model->m_mainThread = newOwner->m_mainThread;
2086 model->m_engine = newOwner->m_engine;
2087 model->m_agent = newOwner->m_agent;
2088 model->m_dynamicRoles = newOwner->m_dynamicRoles;
2091 model->m_agent->addref();
2100 if (m_engine ==
nullptr) {
2111 bool hasChanges =
false;
2116 QHash<int, ElementSync> elementHash;
2117 for (
int i = 0 ;
i <
target->m_modelObjects.size(); ++
i) {
2122 sync.targetIndex =
i;
2123 elementHash.insert(uid,
sync);
2125 for (
int i = 0 ;
i <
src->m_modelObjects.size(); ++
i) {
2130 if (
it == elementHash.
end()) {
2134 elementHash.insert(uid,
sync);
2136 ElementSync &
sync =
it.value();
2144 for (
int i = 0 ;
i <
target->m_modelObjects.size() ; ++
i) {
2146 ElementSync &
s = elementHash.find(element->
getUid()).value();
2150 if (
s.src ==
nullptr) {
2154 target->m_modelObjects.remove(
i, 1);
2164 target->m_modelObjects.clear();
2165 for (
int i = 0 ;
i <
src->m_modelObjects.size() ; ++
i) {
2167 ElementSync &
s = elementHash.find(element->
getUid()).value();
2170 if (targetElement ==
nullptr) {
2174 target->m_modelObjects.append(targetElement);
2183 for (
int i = 0 ;
i <
target->m_modelObjects.size() ; ++
i) {
2185 ElementSync &
s = elementHash.find(element->
getUid()).value();
2188 if (
s.srcIndex !=
s.targetIndex) {
2189 if (
s.targetIndex == -1) {
2199 if (
s.targetIndex != -1 && !
s.changedRoles.isEmpty()) {
2201 emit target->dataChanged(idx, idx,
s.changedRoles);
2208void QQmlListModel::emitItemsChanged(
int index,
int count,
const QVector<int> &roles)
2217void QQmlListModel::emitItemsAboutToBeInserted(
int index,
int count)
2224void QQmlListModel::emitItemsInserted()
2264 if (m_dynamicRoles) {
2265 const QByteArray property = m_roles.at(role).toUtf8();
2267 emitItemsChanged(
row, 1, QVector<int>(1, role));
2273 if (roleIndex != -1) {
2274 emitItemsChanged(
row, 1, QVector<int>(1, role));
2290 v = m_modelObjects[
index]->getValue(m_roles[role]);
2301 if (m_dynamicRoles) {
2302 for (
int i = 0 ;
i < m_roles.size() ; ++
i)
2342 if (m_mainThread && m_agent ==
nullptr) {
2343 if (enableDynamicRoles) {
2345 qmlWarning(
this) <<
tr(
"unable to enable dynamic roles as this model is not empty");
2347 m_dynamicRoles =
true;
2349 if (m_roles.size()) {
2350 qmlWarning(
this) <<
tr(
"unable to enable static roles as this model is not empty");
2352 m_dynamicRoles =
false;
2356 qmlWarning(
this) <<
tr(
"dynamic role setting must be made from the main thread, before any worker scripts are created");
2366 return m_dynamicRoles ? m_modelObjects.size() : m_listModel->
elementCount();
2378 removeElements(0,
count());
2392 if (argLength == 1 || argLength == 2) {
2397 if (index < 0 || index+removeCount >
count() || removeCount <= 0) {
2402 removeElements(
index, removeCount);
2404 qmlWarning(
this) <<
tr(
"remove: incorrect number of arguments");
2408void QQmlListModel::removeElements(
int index,
int removeCount)
2419 if (m_dynamicRoles) {
2420 for (
int i=0 ;
i < removeCount ; ++
i) {
2421 auto modelObject = m_modelObjects[
index+
i];
2422 toDestroy.append([modelObject](){
2426 m_modelObjects.remove(
index, removeCount);
2428 toDestroy = m_listModel->
remove(
index, removeCount);
2435 for (
const auto &destroyer : toDestroy)
2439void QQmlListModel::updateTranslations()
2454 if (!roles.isEmpty())
2481 int index = arg0->toInt32();
2483 if (index < 0 || index >
count()) {
2493 int objectArrayLength = objectArray->getLength();
2494 emitItemsAboutToBeInserted(
index, objectArrayLength);
2495 for (
int i=0 ;
i < objectArrayLength ; ++
i) {
2496 argObject = objectArray->get(
i);
2498 if (m_dynamicRoles) {
2504 emitItemsInserted();
2505 }
else if (argObject) {
2506 emitItemsAboutToBeInserted(
index, 1);
2508 if (m_dynamicRoles) {
2514 emitItemsInserted();
2516 qmlWarning(
this) <<
tr(
"insert: value is not an object");
2519 qmlWarning(
this) <<
tr(
"insert: value is not an object");
2539 if (
n == 0 || from == to)
2541 if (!canMove(from, to,
n)) {
2549 if (m_dynamicRoles) {
2551 int realFrom = from;
2564 QPODVector<DynamicRoleModelNode *, 4> store;
2565 for (
int i=0 ;
i < (realTo-realFrom) ; ++
i)
2566 store.append(m_modelObjects[realFrom+realN+
i]);
2567 for (
int i=0 ;
i < realN ; ++
i)
2568 store.append(m_modelObjects[realFrom+
i]);
2569 for (
int i=0 ;
i < store.count() ; ++
i)
2570 m_modelObjects[realFrom+
i] = store[
i];
2573 m_listModel->
move(from, to,
n);
2602 int objectArrayLength = objectArray->getLength();
2603 if (objectArrayLength > 0) {
2605 emitItemsAboutToBeInserted(
index, objectArrayLength);
2607 for (
int i=0 ;
i < objectArrayLength ; ++
i) {
2608 argObject = objectArray->get(
i);
2610 if (m_dynamicRoles) {
2613 m_listModel->
append(argObject);
2617 emitItemsInserted();
2619 }
else if (argObject) {
2622 if (m_dynamicRoles) {
2623 index = m_modelObjects.size();
2624 emitItemsAboutToBeInserted(
index, 1);
2628 emitItemsAboutToBeInserted(
index, 1);
2629 m_listModel->
append(argObject);
2632 emitItemsInserted();
2634 qmlWarning(
this) <<
tr(
"append: value is not an object");
2637 qmlWarning(
this) <<
tr(
"append: value is not an object");
2679 if (m_dynamicRoles) {
2685 if (ddata->jsWrapper.isNullOrUndefined()) {
2690 result = ddata->jsWrapper.value();
2730 emitItemsAboutToBeInserted(
index, 1);
2732 if (m_dynamicRoles) {
2738 emitItemsInserted();
2743 if (m_dynamicRoles) {
2746 m_listModel->
set(
index,
object, &roles);
2750 emitItemsChanged(
index, 1, roles);
2774 if (m_dynamicRoles) {
2775 int roleIndex = m_roles.indexOf(
property);
2776 if (roleIndex == -1) {
2777 roleIndex = m_roles.size();
2781 emitItemsChanged(
index, 1, QVector<int>(1, roleIndex));
2784 if (roleIndex != -1)
2785 emitItemsChanged(
index, 1, QVector<int>(1, roleIndex));
2800 qmlWarning(
this) <<
"List sync() can only be called from a WorkerScript";
2803bool QQmlListModelParser::verifyProperty(
const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
const QV4::CompiledData::Binding *binding)
2806 const quint32 targetObjectIndex = binding->
value.objectIndex;
2808 QString objName = compilationUnit->stringAt(
target->inheritedTypeNameIndex);
2809 if (objName != listElementTypeName) {
2811 if (
mo != &QQmlListElement::staticMetaObject) {
2812 error(
target, QQmlListModel::tr(
"ListElement: cannot contain nested elements"));
2815 listElementTypeName = objName;
2818 if (!compilationUnit->stringAt(
target->idNameIndex).isEmpty()) {
2819 error(
target->locationOfIdProperty, QQmlListModel::tr(
"ListElement: cannot use reserved \"id\" property"));
2827 error(binding, QQmlListModel::tr(
"ListElement: cannot contain nested elements"));
2830 if (!verifyProperty(compilationUnit, binding))
2834 QString scriptStr = compilationUnit->bindingValueAsScriptString(binding);
2839 error(binding, QQmlListModel::tr(
"ListElement: cannot use script for property value"));
2848bool QQmlListModelParser::applyProperty(
2849 const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit,
2854 bool roleSet =
false;
2857 const quint32 targetObjectIndex = binding->
value.objectIndex;
2861 if (outterElementIndex == -1) {
2866 subModel =
model->getListProperty(outterElementIndex, role);
2867 if (subModel ==
nullptr) {
2870 model->setOrCreateProperty(outterElementIndex, elementName, vModel);
2875 int elementIndex = subModel ? subModel->appendElement() : -1;
2879 roleSet |= applyProperty(compilationUnit, subBinding, subModel, elementIndex);
2886 if (isTranslationBinding) {
2887 value = QVariant::fromValue<const QV4::CompiledData::Binding*>(binding);
2889 value = compilationUnit->bindingValueAsString(binding);
2891 value = compilationUnit->bindingValueAsNumber(binding);
2897 QString scriptStr = compilationUnit->bindingValueAsScriptString(binding);
2898 if (definesEmptyList(scriptStr)) {
2906 auto v4 = compilationUnit->engine;
2914 if (v4->hasException)
2915 v4->catchException();
2929 model->setOrCreateProperty(outterElementIndex, elementName,
value);
2930 auto listModel =
model->m_modelCache;
2931 if (isTranslationBinding && listModel) {
2932 if (!listModel->translationChangeHandler) {
2934 model->m_modelCache->translationChangeHandler = std::make_unique<QPropertyNotifier>(
2935 ep->translationLanguage.addNotifier([listModel](){ listModel->updateTranslations(); }));
2945 listElementTypeName =
QString();
2950 error(binding, QQmlListModel::tr(
"ListModel: undefined property '%1'").
arg(propName));
2953 if (!verifyProperty(compilationUnit, binding))
2963 rv->m_compilationUnit = compilationUnit;
2965 bool setRoles =
false;
2970 setRoles |= applyProperty(compilationUnit, binding, rv->m_listModel, -1);
2973 if (setRoles ==
false)
2974 qmlWarning(
obj) <<
"All ListElement declarations are empty, no roles can be created unless dynamicRoles is set.";
2977bool QQmlListModelParser::definesEmptyList(
const QString &
s)
2980 for (
int i=1;
i<
s.size()-1;
i++) {
2981 if (!
s[
i].isSpace())
3038#include "moc_qqmllistmodel_p_p.cpp"
3040#include "moc_qqmllistmodel_p.cpp"
static QVector< int > sync(DynamicRoleModelNode *src, DynamicRoleModelNode *target)
static DynamicRoleModelNode * create(const QVariantMap &obj, QQmlListModel *owner)
DynamicRoleModelNode(QQmlListModel *owner, int uid)
void setNodeUpdatesEnabled(bool enable)
void updateValues(const QVariantMap &object, QVector< int > &roles)
static QVector< int > sync(ListElement *src, ListLayout *srcLayout, ListElement *target, ListLayout *targetLayout)
const Role * getRoleOrCreate(const QString &key, const QVariant &data)
static void sync(ListLayout *src, ListLayout *target)
const Role & getExistingRole(int index) const
Q_REQUIRED_RESULT QVector< std::function< void()> > remove(int index, int count)
static bool sync(ListModel *src, ListModel *target)
int append(QV4::Object *object)
QVariant getProperty(int elementIndex, int roleIndex, const QQmlListModel *owner, QV4::ExecutionEngine *eng)
void move(int from, int to, int n)
void insertElement(int index)
ListModel(ListLayout *layout, QQmlListModel *modelCache)
void insert(int elementIndex, QV4::Object *object)
int setExistingProperty(int uid, const QString &key, const QV4::Value &data, QV4::ExecutionEngine *eng)
void updateTranslations()
QObject * getOrCreateModelObject(QQmlListModel *model, int elementIndex)
void set(int elementIndex, QV4::Object *object, QVector< int > *roles)
ListModel * getListProperty(int elementIndex, const ListLayout::Role &role)
int setOrCreateProperty(int elementIndex, const QString &key, const QVariant &data)
const ListLayout::Role & getExistingRole(int index) const
bool beginMoveRows(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destinationParent, int destinationRow)
void endRemoveRows()
Ends a row removal operation.
void endMoveRows()
Ends a row move operation.
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList< int > &roles=QList< int >())
This signal is emitted whenever the data in an existing item changes.
void endInsertRows()
Ends a row insertion operation.
void rowsInserted(const QModelIndex &parent, int first, int last, QPrivateSignal)
This signal is emitted after rows have been inserted into the model.
QModelIndex createIndex(int row, int column, const void *data=nullptr) const
Creates a model index for the given row and column with the internal pointer ptr.
void beginRemoveRows(const QModelIndex &parent, int first, int last)
Begins a row removal operation.
void beginInsertRows(const QModelIndex &parent, int first, int last)
Begins a row insertion operation.
void rowsRemoved(const QModelIndex &parent, int first, int last, QPrivateSignal)
This signal is emitted after rows have been removed from the model.
QObject * parent() const
Returns a pointer to the parent object.
\inmodule QtCore\reentrant
~QDateTime()
Destroys the datetime.
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
QV4::ExecutionEngine * handle() const
static QJSValue fromReturnedValue(QV4::ReturnedValue d)
static QV4::ReturnedValue asReturnedValue(const QJSValue *jsval)
static QV4::ReturnedValue convertToReturnedValue(QV4::ExecutionEngine *e, const QJSValue &jsval)
static void setValue(QJSValue *jsval, const QV4::Value &v)
The QJSValue class acts as a container for Qt/JavaScript data types.
bool isCallable() const
Returns true if this QJSValue is a function, otherwise returns false.
~QJSValue()
Destroys this QJSValue.
QList< T > toList() const noexcept
qsizetype length() const noexcept
const_iterator cbegin() const noexcept
bool isSharedWith(const QMap< Key, T > &other) const noexcept
QDynamicMetaObjectData * metaObject
static QObjectPrivate * get(QObject *o)
virtual ~QObject()
Destroys the object, deleting all its child objects.
void remove(int idx, int count=1)
void insert(int idx, const T &v)
const T & at(int idx) const
static QQmlRefPointer< QQmlContextData > get(QQmlContext *context)
const QMetaObject * resolveType(const QString &) const
Resolves name to a type, or 0 if it is not a type.
int evaluateEnum(const QString &, bool *ok) const
If script is a simple enumeration expression (eg.
static QQmlData * get(QObjectPrivate *priv, bool create)
QQmlPropertyCapture * propertyCapture
static QQmlEnginePrivate * get(QQmlEngine *e)
The QQmlEngine class provides an environment for instantiating QML components.
static QQmlContext * contextForObject(const QObject *)
Returns the QQmlContext for the object, or nullptr if no context has been set.
static void setContextForObject(QObject *, QQmlContext *)
Sets the QQmlContext for the object to context.
QQmlEngine * qmlEngine(const QObject *object)
Returns the QQmlEngine associated with object, if any.
The QQmlError class encapsulates a QML error.
void setDescription(const QString &)
Sets the error description.
void verifyBindings(const QQmlRefPointer< QV4::ExecutableCompilationUnit > &compilationUnit, const QList< const QV4::CompiledData::Binding * > &bindings) override
void applyBindings(QObject *obj, const QQmlRefPointer< QV4::ExecutableCompilationUnit > &compilationUnit, const QList< const QV4::CompiledData::Binding * > &bindings) override
Q_INVOKABLE void release()
Q_INVOKABLE void sync()
\qmlmethod ListModel::sync()
Q_INVOKABLE void clear()
\qmlmethod ListModel::clear()
friend class QQmlListModelWorkerAgent
QVariant data(const QModelIndex &index, int role) const override
Returns the data stored under the given role for the item referred to by the index.
Q_INVOKABLE void insert(QQmlV4FunctionPtr args)
\qmlmethod ListModel::insert(int index, jsobject dict)
void setDynamicRoles(bool enableDynamicRoles)
\qmlproperty bool ListModel::dynamicRoles
QModelIndex index(int row, int column, const QModelIndex &parent) const override
Returns the index of the data in row and column with parent.
Q_INVOKABLE void setProperty(int index, const QString &property, const QVariant &value)
\qmlmethod ListModel::setProperty(int index, string property, variant value)
Q_INVOKABLE QJSValue get(int index) const
\qmlmethod object ListModel::get(int index)
Q_INVOKABLE void move(int from, int to, int count)
\qmlmethod ListModel::move(int from, int to, int n)
int rowCount(const QModelIndex &parent) const override
Returns the number of rows under the given parent.
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
Sets the role data for the item at index to value.
QHash< int, QByteArray > roleNames() const override
friend class DynamicRoleModelNode
QQmlListModel(QObject *parent=nullptr)
\qmltype ListModel \instantiates QQmlListModel \inherits AbstractListModel \inqmlmodule QtQml....
Q_INVOKABLE void append(QQmlV4FunctionPtr args)
\qmlmethod ListModel::append(jsobject dict)
Q_INVOKABLE void set(int index, const QJSValue &value)
\qmlmethod ListModel::set(int index, jsobject dict)
Q_INVOKABLE void remove(QQmlV4FunctionPtr args)
\qmlmethod ListModel::remove(int index, int count = 1)
void captureProperty(QQmlNotifier *)
iterator find(const T &value)
\macro QT_RESTRICTED_CAST_FROM_ASCII
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
int compare(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
QByteArray toUtf8() const &
~QUrl()
Destructor; called immediately before the object is deleted.
QString bindingValueAsString(const CompiledData::Binding *binding) const
ObjectType::Data * allocate(Args &&... args)
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 >
QMap< QString, QString > map
[6]
qDeleteAll(list.begin(), list.end())
QCache< int, Employee > cache
[0]
QSet< QString >::iterator it
Combined button and popup list for selecting options.
Scoped< FunctionObject > ScopedFunctionObject
Scoped< String > ScopedString
Scoped< ExecutionContext > ScopedContext
static int arrayLength(const QString &rawType)
QMap< QString, QVariant > QVariantMap
static const QCssKnownValue properties[NumProperties - 1]
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction function
DBusConnection const char DBusError * error
static struct AttrInfo attrs[]
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLsizei GLenum GLsizei GLsizei GLuint memory
GLenum GLenum GLsizei void GLsizei void * column
GLenum GLenum GLsizei void * row
QQmlEngine * qmlEngine(const QObject *obj)
QQmlContext * qmlContext(const QObject *obj)
Q_QML_EXPORT QQmlInfo qmlWarning(const QObject *me)
static QAtomicInt uidCounter(MIN_LISTMODEL_UID)
static bool isMemoryUsed(const char *mem)
static QString roleTypeName(ListLayout::Role::DataType t)
QLatin1StringView QLatin1String
#define QStringLiteral(str)
QArrayDataPointer< char16_t > QStringPrivate
static const QTextHtmlElement elements[Html_NumElements]
#define Q_ALLOCA_VAR(type, name, size)
static QVariant toVariant(const QV4::Value &value, QMetaType typeHint, JSToQVariantConversionBehavior conversionBehavior, V4ObjectSet *visitedObjects)
#define DEFINE_OBJECT_VTABLE(classname)
QSqlQueryModel * model
[16]
QFuture< QSet< QChar > > set
[10]
settings setValue("DataPump/bgcolor", color)
QUrl url("example.com")
[constructor-url-reference]
\inmodule QtCore \reentrant
static void deallocate(QArrayData *data) noexcept
quint32_le propertyNameIndex
bool isFunctionExpression() const
bool evaluatesToString() const
bool isTranslationBinding() const
bool valueAsBoolean() const
union QV4::CompiledData::Binding::@545 value
MemoryManager * memoryManager
QV4::ReturnedValue fromVariant(const QVariant &)
static QVariantMap variantMapFromJS(const QV4::Object *o)
Heap::String * newString(char16_t c)
static QVariant toVariant(const QV4::Value &value, QMetaType typeHint, bool createJSValueForObjectsAndSymbols=true)
Heap::ArrayObject * newArrayObject(int count=0)
static Heap::FunctionObject * createScriptFunction(ExecutionContext *scope, Function *function)
ReturnedValue(* getter)(Lookup *l, ExecutionEngine *engine, const Value &object)
static ReturnedValue getterFallback(Lookup *l, ExecutionEngine *engine, const Value &object)
ExecutionEngine * engine() const
PropertyKey next(const Object *o, Property *pd=nullptr, PropertyAttributes *attrs=nullptr) override
~ModelObjectOwnPropertyKeyIterator() override=default
PropertyKey next(const Object *o, Property *pd=nullptr, PropertyAttributes *attrs=nullptr) override
bool hasProperty(PropertyKey id) const
bool arrayPut(uint index, const Value &value)
static ReturnedValue wrap(ExecutionEngine *engine, QObject *object)
static Heap::QmlContext * create(QV4::ExecutionContext *parent, QQmlRefPointer< QQmlContextData > context, QObject *scopeObject)
bool isNullOrUndefined() const
bool booleanValue() const
static constexpr VTable::OwnPropertyKeys virtualOwnPropertyKeys
static constexpr VTable::Get virtualGet
static constexpr VTable::Put virtualPut
static constexpr VTable::ResolveLookupGetter virtualResolveLookupGetter
QML_NEARLY_ALWAYS_INLINE String * stringValue() const
static constexpr Value undefinedValue()
uchar data[MaxInternalSize]
void setString(const QString &s)
QString toString(const QQmlListModel *owner) const
void setTranslation(const QV4::CompiledData::Binding *binding)