aboutsummaryrefslogtreecommitdiffstats
path: root/src/qmlmodels/qqmllistmodel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qmlmodels/qqmllistmodel.cpp')
-rw-r--r--src/qmlmodels/qqmllistmodel.cpp79
1 files changed, 63 insertions, 16 deletions
diff --git a/src/qmlmodels/qqmllistmodel.cpp b/src/qmlmodels/qqmllistmodel.cpp
index 583f12164a..833f102e79 100644
--- a/src/qmlmodels/qqmllistmodel.cpp
+++ b/src/qmlmodels/qqmllistmodel.cpp
@@ -893,22 +893,24 @@ QJSValue *ListElement::getFunctionProperty(const ListLayout::Role &role)
return f;
}
-QPointer<QObject> *ListElement::getGuardProperty(const ListLayout::Role &role)
+QTaggedPointer<QObject, ListElement::ObjectIndestructible> *
+ListElement::getGuardProperty(const ListLayout::Role &role)
{
char *mem = getPropertyMemory(role);
bool existingGuard = false;
- for (size_t i=0 ; i < sizeof(QPointer<QObject>) ; ++i) {
+ for (size_t i = 0; i < sizeof(QTaggedPointer<QObject, ListElement::ObjectIndestructible>);
+ ++i) {
if (mem[i] != 0) {
existingGuard = true;
break;
}
}
- QPointer<QObject> *o = nullptr;
+ QTaggedPointer<QObject, ListElement::ObjectIndestructible> *o = nullptr;
if (existingGuard)
- o = reinterpret_cast<QPointer<QObject> *>(mem);
+ o = reinterpret_cast<QTaggedPointer<QObject, ListElement::ObjectIndestructible> *>(mem);
return o;
}
@@ -964,10 +966,12 @@ QVariant ListElement::getProperty(const ListLayout::Role &role, const QQmlListMo
break;
case ListLayout::Role::QObject:
{
- QPointer<QObject> *guard = reinterpret_cast<QPointer<QObject> *>(mem);
- QObject *object = guard->data();
- if (object)
- data = QVariant::fromValue(object);
+ QTaggedPointer<QObject, ListElement::ObjectIndestructible> *guard =
+ reinterpret_cast<QTaggedPointer<QObject, ListElement::ObjectIndestructible> *>(
+ mem);
+ QObject *object = guard->data();
+ if (object)
+ data = QVariant::fromValue(object);
}
break;
case ListLayout::Role::VariantMap:
@@ -1079,15 +1083,48 @@ int ListElement::setListProperty(const ListLayout::Role &role, ListModel *m)
return roleIndex;
}
+static void
+restoreQObjectOwnership(QTaggedPointer<QObject, ListElement::ObjectIndestructible> *pointer)
+{
+ QQmlData *data = QQmlData::get(pointer->data(), false);
+ Q_ASSERT(data);
+
+ // Only restore the previous state if the object hasn't become explicitly
+ // owned
+ if (!data->explicitIndestructibleSet) {
+ data->indestructible = (pointer->tag() & ListElement::Indestructible);
+ data->explicitIndestructibleSet = (pointer->tag() & ListElement::ExplicitlySet);
+ }
+}
+
+static void setQObjectOwnership(char *mem, QObject *o)
+{
+ QQmlData *ddata = QQmlData::get(o, false);
+ const int ownership = (!ddata || ddata->indestructible ? ListElement::Indestructible : 0)
+ | (ddata && ddata->explicitIndestructibleSet ? ListElement::ExplicitlySet : 0);
+
+ // If ddata didn't exist above, force its creation now
+ if (!ddata)
+ ddata = QQmlData::get(o, true);
+
+ ddata->indestructible = true;
+ ddata->explicitIndestructibleSet = false;
+
+ new (mem) QTaggedPointer<QObject, ListElement::ObjectIndestructible>(
+ o, static_cast<ListElement::ObjectIndestructible>(ownership));
+}
+
int ListElement::setQObjectProperty(const ListLayout::Role &role, QObject *o)
{
int roleIndex = -1;
if (role.type == ListLayout::Role::QObject) {
char *mem = getPropertyMemory(role);
- QPointer<QObject> *g = reinterpret_cast<QPointer<QObject> *>(mem);
+ QTaggedPointer<QObject, ListElement::ObjectIndestructible> *g =
+ reinterpret_cast<QTaggedPointer<QObject, ListElement::ObjectIndestructible> *>(mem);
bool existingGuard = false;
- for (size_t i=0 ; i < sizeof(QPointer<QObject>) ; ++i) {
+ for (size_t i = 0; i < sizeof(QTaggedPointer<QObject, ListElement::ObjectIndestructible>);
+ ++i) {
if (mem[i] != 0) {
existingGuard = true;
break;
@@ -1096,11 +1133,15 @@ int ListElement::setQObjectProperty(const ListLayout::Role &role, QObject *o)
bool changed;
if (existingGuard) {
changed = g->data() != o;
- g->~QPointer();
+ if (changed)
+ restoreQObjectOwnership(g);
+ g->~QTaggedPointer();
} else {
changed = true;
}
- new (mem) QPointer<QObject>(o);
+
+ setQObjectOwnership(mem, o);
+
if (changed)
roleIndex = role.index;
}
@@ -1238,7 +1279,8 @@ void ListElement::setBoolPropertyFast(const ListLayout::Role &role, bool b)
void ListElement::setQObjectPropertyFast(const ListLayout::Role &role, QObject *o)
{
char *mem = getPropertyMemory(role);
- new (mem) QPointer<QObject>(o);
+
+ setQObjectOwnership(mem, o);
}
void ListElement::setListPropertyFast(const ListLayout::Role &role, ListModel *m)
@@ -1410,9 +1452,14 @@ void ListElement::destroy(ListLayout *layout)
break;
case ListLayout::Role::QObject:
{
- QPointer<QObject> *guard = getGuardProperty(r);
- if (guard)
- guard->~QPointer();
+ QTaggedPointer<QObject, ListElement::ObjectIndestructible> *guard =
+ getGuardProperty(r);
+
+ if (guard) {
+ restoreQObjectOwnership(guard);
+
+ guard->~QTaggedPointer();
+ }
}
break;
case ListLayout::Role::VariantMap: