diff options
Diffstat (limited to 'src/qmlmodels')
-rw-r--r-- | src/qmlmodels/CMakeLists.txt | 5 | ||||
-rw-r--r-- | src/qmlmodels/doc/src/qtqmlmodel.qdoc | 2 | ||||
-rw-r--r-- | src/qmlmodels/qqmlabstractdelegatecomponent.cpp | 2 | ||||
-rw-r--r-- | src/qmlmodels/qqmladaptormodel.cpp | 27 | ||||
-rw-r--r-- | src/qmlmodels/qqmladaptormodel_p.h | 8 | ||||
-rw-r--r-- | src/qmlmodels/qqmlchangeset.cpp | 10 | ||||
-rw-r--r-- | src/qmlmodels/qqmldelegatemodel.cpp | 52 | ||||
-rw-r--r-- | src/qmlmodels/qqmldelegatemodel_p.h | 3 | ||||
-rw-r--r-- | src/qmlmodels/qqmlinstantiator.cpp | 2 | ||||
-rw-r--r-- | src/qmlmodels/qqmllistaccessor.cpp | 4 | ||||
-rw-r--r-- | src/qmlmodels/qqmllistcompositor_p.h | 5 | ||||
-rw-r--r-- | src/qmlmodels/qqmllistmodel.cpp | 214 | ||||
-rw-r--r-- | src/qmlmodels/qqmllistmodel_p.h | 3 | ||||
-rw-r--r-- | src/qmlmodels/qqmllistmodel_p_p.h | 47 | ||||
-rw-r--r-- | src/qmlmodels/qqmlmodelindexvaluetype.cpp | 68 | ||||
-rw-r--r-- | src/qmlmodels/qqmlmodelindexvaluetype_p.h | 174 |
16 files changed, 457 insertions, 169 deletions
diff --git a/src/qmlmodels/CMakeLists.txt b/src/qmlmodels/CMakeLists.txt index 3166e5d90c..41a1475365 100644 --- a/src/qmlmodels/CMakeLists.txt +++ b/src/qmlmodels/CMakeLists.txt @@ -27,6 +27,11 @@ qt_internal_add_qml_module(QmlModels Qt::QmlPrivate ) +qt_internal_extend_target(QmlModels CONDITION QT_FEATURE_qml_itemmodel + SOURCES + qqmlmodelindexvaluetype.cpp qqmlmodelindexvaluetype_p.h +) + qt_internal_extend_target(QmlModels CONDITION QT_FEATURE_qml_object_model SOURCES qqmlinstantiator.cpp qqmlinstantiator_p.h diff --git a/src/qmlmodels/doc/src/qtqmlmodel.qdoc b/src/qmlmodels/doc/src/qtqmlmodel.qdoc index 33c648e87f..ea46bf7da9 100644 --- a/src/qmlmodels/doc/src/qtqmlmodel.qdoc +++ b/src/qmlmodels/doc/src/qtqmlmodel.qdoc @@ -26,7 +26,7 @@ ****************************************************************************/ /*! - \qmlmodule QtQml.Models 2.\QtMinorVersion + \qmlmodule QtQml.Models \title Qt QML Models QML Types \ingroup qmlmodules \brief Provides QML types for data models diff --git a/src/qmlmodels/qqmlabstractdelegatecomponent.cpp b/src/qmlmodels/qqmlabstractdelegatecomponent.cpp index 1058d87485..869c6a4fa9 100644 --- a/src/qmlmodels/qqmlabstractdelegatecomponent.cpp +++ b/src/qmlmodels/qqmlabstractdelegatecomponent.cpp @@ -59,3 +59,5 @@ QVariant QQmlAbstractDelegateComponent::value(QQmlAdaptorModel *adaptorModel, in } QT_END_NAMESPACE + +#include "moc_qqmlabstractdelegatecomponent_p.cpp" diff --git a/src/qmlmodels/qqmladaptormodel.cpp b/src/qmlmodels/qqmladaptormodel.cpp index dc3ea8019e..f283271018 100644 --- a/src/qmlmodels/qqmladaptormodel.cpp +++ b/src/qmlmodels/qqmladaptormodel.cpp @@ -549,7 +549,8 @@ public: metaObject.reset(builder.toMetaObject()); *static_cast<QMetaObject *>(this) = *metaObject; - propertyCache.adopt(new QQmlPropertyCache(metaObject.data(), model.modelItemRevision)); + propertyCache = QQmlPropertyCache::createStandalone( + metaObject.data(), model.modelItemRevision); } }; @@ -683,8 +684,8 @@ public: { VDMListDelegateDataType *dataType = const_cast<VDMListDelegateDataType *>(this); if (!propertyCache) { - dataType->propertyCache.adopt(new QQmlPropertyCache( - &QQmlDMListAccessorData::staticMetaObject, model.modelItemRevision)); + dataType->propertyCache = QQmlPropertyCache::createStandalone( + &QQmlDMListAccessorData::staticMetaObject, model.modelItemRevision); } return new QQmlDMListAccessorData( @@ -962,30 +963,38 @@ QQmlAdaptorModel::~QQmlAdaptorModel() accessors->cleanup(*this); } -void QQmlAdaptorModel::setModel(const QVariant &variant, QObject *parent) +void QQmlAdaptorModel::setModel(const QVariant &variant, QObject *) { accessors->cleanup(*this); + // Don't use variant anymore after this. list may transform it. list.setList(variant); + modelStrongReference.clear(); + if (QObject *object = qvariant_cast<QObject *>(list.list())) { - setObject(object, parent); + if (QQmlData *ddata = QQmlData::get(object)) + modelStrongReference = ddata->jsWrapper; + setObject(object); if (qobject_cast<QAbstractItemModel *>(object)) accessors = new VDMAbstractItemModelDataType(this); else accessors = new VDMObjectDelegateDataType; } else if (list.type() == QQmlListAccessor::ListProperty) { - setObject(static_cast<const QQmlListReference *>(variant.constData())->object(), parent); + auto object = static_cast<const QQmlListReference *>(list.list().constData())->object(); + if (QQmlData *ddata = QQmlData::get(object)) + modelStrongReference = ddata->jsWrapper; + setObject(object); accessors = new VDMObjectDelegateDataType; } else if (list.type() == QQmlListAccessor::ObjectList) { - setObject(nullptr, parent); + setObject(nullptr); accessors = new VDMObjectDelegateDataType; } else if (list.type() != QQmlListAccessor::Invalid && list.type() != QQmlListAccessor::Instance) { // Null QObject - setObject(nullptr, parent); + setObject(nullptr); accessors = new VDMListDelegateDataType; } else { - setObject(nullptr, parent); + setObject(nullptr); accessors = &qt_vdm_null_accessors; } } diff --git a/src/qmlmodels/qqmladaptormodel_p.h b/src/qmlmodels/qqmladaptormodel_p.h index 531e8d9105..8635762bc4 100644 --- a/src/qmlmodels/qqmladaptormodel_p.h +++ b/src/qmlmodels/qqmladaptormodel_p.h @@ -70,7 +70,7 @@ class QQmlDelegateModel; class QQmlDelegateModelItem; class QQmlDelegateModelItemMetaType; -class Q_QMLMODELS_PRIVATE_EXPORT QQmlAdaptorModel : public QQmlStrongJSQObjectReference<QObject> +class Q_QMLMODELS_PRIVATE_EXPORT QQmlAdaptorModel : public QQmlGuard<QObject> { public: class Accessors @@ -114,6 +114,10 @@ public: const Accessors *accessors; QPersistentModelIndex rootIndex; QQmlListAccessor list; + // we need to ensure that a JS created model does not get gced, but cannot + // arbitrarily set the parent (using QQmlStrongJSQObjectReference) of QObject based models, + // as that causes issues with singletons + QV4::PersistentValue modelStrongReference; QTypeRevision modelItemRevision = QTypeRevision::zero(); @@ -121,7 +125,7 @@ public: ~QQmlAdaptorModel(); inline QVariant model() const { return list.list(); } - void setModel(const QVariant &variant, QObject *parent); + void setModel(const QVariant &variant, QObject *parent = nullptr); void invalidateModel(); bool isValid() const; diff --git a/src/qmlmodels/qqmlchangeset.cpp b/src/qmlmodels/qqmlchangeset.cpp index ba876b42e2..99def9567c 100644 --- a/src/qmlmodels/qqmlchangeset.cpp +++ b/src/qmlmodels/qqmlchangeset.cpp @@ -557,16 +557,17 @@ void QQmlChangeSet::change(QVector<Change> *changes) QDebug operator <<(QDebug debug, const QQmlChangeSet &set) { + QDebugStateSaver stateSaver(debug); debug.nospace() << "QQmlChangeSet("; const QVector<QQmlChangeSet::Change> &removes = set.removes(); for (const QQmlChangeSet::Change &remove : removes) - debug << remove; + debug << remove << ' '; const QVector<QQmlChangeSet::Change> &inserts = set.inserts(); for (const QQmlChangeSet::Change &insert : inserts) - debug << insert; + debug << insert << ' '; const QVector<QQmlChangeSet::Change> &changes = set.changes(); for (const QQmlChangeSet::Change &change : changes) - debug << change; + debug << change << ' '; return debug.nospace() << ')'; } @@ -576,7 +577,8 @@ QDebug operator <<(QDebug debug, const QQmlChangeSet &set) QDebug operator <<(QDebug debug, const QQmlChangeSet::Change &change) { - return (debug.nospace() << "Change(" << change.index << ',' << change.count << ')').space(); + QDebugStateSaver stateSaver(debug); + return debug.nospace() << "Change(" << change.index << ',' << change.count << ')'; } QT_END_NAMESPACE diff --git a/src/qmlmodels/qqmldelegatemodel.cpp b/src/qmlmodels/qqmldelegatemodel.cpp index 5c5f464cd5..f127885e98 100644 --- a/src/qmlmodels/qqmldelegatemodel.cpp +++ b/src/qmlmodels/qqmldelegatemodel.cpp @@ -259,7 +259,7 @@ QQmlDelegateModel::~QQmlDelegateModel() { Q_D(QQmlDelegateModel); d->disconnectFromAbstractItemModel(); - d->m_adaptorModel.setObject(nullptr, this); + d->m_adaptorModel.setObject(nullptr); for (QQmlDelegateModelItem *cacheItem : qAsConst(d->m_cache)) { if (cacheItem->object) { @@ -389,6 +389,12 @@ void QQmlDelegateModelPrivate::connectToAbstractItemModel() q, QQmlDelegateModel, SLOT(_q_rowsRemoved(QModelIndex,int,int))); qmlobject_connect(aim, QAbstractItemModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), q, QQmlDelegateModel, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int))); + qmlobject_connect(aim, QAbstractItemModel, SIGNAL(columnsInserted(QModelIndex,int,int)), + q, QQmlDelegateModel, SLOT(_q_columnsInserted(QModelIndex,int,int))); + qmlobject_connect(aim, QAbstractItemModel, SIGNAL(columnsRemoved(QModelIndex,int,int)), + q, QQmlDelegateModel, SLOT(_q_columnsRemoved(QModelIndex,int,int))); + qmlobject_connect(aim, QAbstractItemModel, SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)), + q, QQmlDelegateModel, SLOT(_q_columnsMoved(QModelIndex,int,int,QModelIndex,int))); qmlobject_connect(aim, QAbstractItemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)), q, QQmlDelegateModel, SLOT(_q_dataChanged(QModelIndex,QModelIndex,QVector<int>))); qmlobject_connect(aim, QAbstractItemModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), @@ -413,6 +419,12 @@ void QQmlDelegateModelPrivate::disconnectFromAbstractItemModel() q, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int))); QObject::disconnect(aim, SIGNAL(rowsRemoved(QModelIndex,int,int)), q, SLOT(_q_rowsRemoved(QModelIndex,int,int))); + QObject::disconnect(aim, SIGNAL(columnsInserted(QModelIndex,int,int)), q, + SLOT(_q_columnsInserted(QModelIndex,int,int))); + QObject::disconnect(aim, SIGNAL(columnsRemoved(QModelIndex,int,int)), q, + SLOT(_q_columnsRemoved(QModelIndex,int,int))); + QObject::disconnect(aim, SIGNAL(columnsMoved(QModelIndex,int,int,QModelIndex,int)), q, + SLOT(_q_columnsMoved(QModelIndex,int,int,QModelIndex,int))); QObject::disconnect(aim, SIGNAL(dataChanged(QModelIndex,QModelIndex,QVector<int>)), q, SLOT(_q_dataChanged(QModelIndex,QModelIndex,QVector<int>))); QObject::disconnect(aim, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), @@ -431,7 +443,7 @@ void QQmlDelegateModel::setModel(const QVariant &model) _q_itemsRemoved(0, d->m_count); d->disconnectFromAbstractItemModel(); - d->m_adaptorModel.setModel(model, this); + d->m_adaptorModel.setModel(model); d->connectToAbstractItemModel(); d->m_adaptorModel.replaceWatchedRoles(QList<QByteArray>(), d->m_watchedRoles); @@ -1970,6 +1982,38 @@ void QQmlDelegateModel::_q_rowsMoved( } } +void QQmlDelegateModel::_q_columnsInserted(const QModelIndex &parent, int begin, int end) +{ + Q_D(QQmlDelegateModel); + Q_UNUSED(end); + if (parent == d->m_adaptorModel.rootIndex && begin == 0) { + // mark all items as changed + _q_itemsChanged(0, d->m_count, QVector<int>()); + } +} + +void QQmlDelegateModel::_q_columnsRemoved(const QModelIndex &parent, int begin, int end) +{ + Q_D(QQmlDelegateModel); + Q_UNUSED(end); + if (parent == d->m_adaptorModel.rootIndex && begin == 0) { + // mark all items as changed + _q_itemsChanged(0, d->m_count, QVector<int>()); + } +} + +void QQmlDelegateModel::_q_columnsMoved(const QModelIndex &parent, int start, int end, + const QModelIndex &destination, int column) +{ + Q_D(QQmlDelegateModel); + Q_UNUSED(end); + if ((parent == d->m_adaptorModel.rootIndex && start == 0) + || (destination == d->m_adaptorModel.rootIndex && column == 0)) { + // mark all items as changed + _q_itemsChanged(0, d->m_count, QVector<int>()); + } +} + void QQmlDelegateModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end, const QVector<int> &roles) { Q_D(QQmlDelegateModel); @@ -2054,8 +2098,8 @@ bool QQmlDelegateModelPrivate::insert(Compositor::insert_iterator &before, const // Must be before the new object is inserted into the cache or its indexes will be adjusted too. itemsInserted(QVector<Compositor::Insert>(1, Compositor::Insert(before, 1, cacheItem->groups & ~Compositor::CacheFlag))); - before = m_compositor.insert(before, nullptr, 0, 1, cacheItem->groups); m_cache.insert(before.cacheIndex, cacheItem); + m_compositor.insert(before, nullptr, 0, 1, cacheItem->groups); return true; } @@ -3922,4 +3966,6 @@ QV4::ReturnedValue QQmlDelegateModelEngineData::array(QV4::ExecutionEngine *v4, QT_END_NAMESPACE +#include "moc_qqmldelegatemodel_p_p.cpp" + #include "moc_qqmldelegatemodel_p.cpp" diff --git a/src/qmlmodels/qqmldelegatemodel_p.h b/src/qmlmodels/qqmldelegatemodel_p.h index f4578e130e..2ce02c4aa5 100644 --- a/src/qmlmodels/qqmldelegatemodel_p.h +++ b/src/qmlmodels/qqmldelegatemodel_p.h @@ -152,6 +152,9 @@ private Q_SLOTS: void _q_itemsMoved(int from, int to, int count); void _q_modelReset(); void _q_rowsInserted(const QModelIndex &,int,int); + void _q_columnsInserted(const QModelIndex &, int, int); + void _q_columnsRemoved(const QModelIndex &, int, int); + void _q_columnsMoved(const QModelIndex &, int, int, const QModelIndex &, int); void _q_rowsAboutToBeRemoved(const QModelIndex &parent, int begin, int end); void _q_rowsRemoved(const QModelIndex &,int,int); void _q_rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int); diff --git a/src/qmlmodels/qqmlinstantiator.cpp b/src/qmlmodels/qqmlinstantiator.cpp index 3b663badf5..cb7ca1126c 100644 --- a/src/qmlmodels/qqmlinstantiator.cpp +++ b/src/qmlmodels/qqmlinstantiator.cpp @@ -147,7 +147,7 @@ void QQmlInstantiatorPrivate::_q_modelUpdated(const QQmlChangeSet &changeSet, bo { Q_Q(QQmlInstantiator); - if (!componentComplete || effectiveReset) + if (!componentComplete || effectiveReset || !active) return; if (reset) { diff --git a/src/qmlmodels/qqmllistaccessor.cpp b/src/qmlmodels/qqmllistaccessor.cpp index 230f190834..381d5d34de 100644 --- a/src/qmlmodels/qqmllistaccessor.cpp +++ b/src/qmlmodels/qqmllistaccessor.cpp @@ -75,6 +75,7 @@ void QQmlListAccessor::setList(const QVariant &v) d = d.value<QJSValue>().toVariant(); variantsType = d.metaType(); } + if (!d.isValid()) { m_type = Invalid; } else if (variantsType == QMetaType::fromType<QStringList>()) { @@ -85,6 +86,9 @@ void QQmlListAccessor::setList(const QVariant &v) m_type = VariantList; } else if (variantsType == QMetaType::fromType<QList<QObject *>>()) { m_type = ObjectList; + } else if (variantsType.flags() & QMetaType::IsQmlList) { + d = QVariant::fromValue(QQmlListReference(d)); + m_type = ListProperty; } else if (variantsType == QMetaType::fromType<QQmlListReference>()) { m_type = ListProperty; } else if (variantsType.flags() & QMetaType::PointerToQObject) { diff --git a/src/qmlmodels/qqmllistcompositor_p.h b/src/qmlmodels/qqmllistcompositor_p.h index 7bf20397fd..797a457e8c 100644 --- a/src/qmlmodels/qqmllistcompositor_p.h +++ b/src/qmlmodels/qqmllistcompositor_p.h @@ -308,6 +308,10 @@ Q_DECLARE_TYPEINFO(QQmlListCompositor::Insert, Q_PRIMITIVE_TYPE); inline QQmlListCompositor::iterator::iterator() {} +QT_WARNING_PUSH +// GCC isn't wrong, as groupCount is public in iterator, but we tried Q_ASSUME(), +// right in front of the loops, and it didn't help, so we disable the warning: +QT_WARNING_DISABLE_GCC("-Warray-bounds") inline QQmlListCompositor::iterator::iterator( Range *range, int offset, Group group, int groupCount) : range(range) @@ -335,6 +339,7 @@ inline void QQmlListCompositor::iterator::decrementIndexes(int difference, uint index[i] -= difference; } } +QT_WARNING_POP // -Warray-bounds inline QQmlListCompositor::insert_iterator::insert_iterator( Range *range, int offset, Group group, int groupCount) diff --git a/src/qmlmodels/qqmllistmodel.cpp b/src/qmlmodels/qqmllistmodel.cpp index a9c58d59a5..c060aaec97 100644 --- a/src/qmlmodels/qqmllistmodel.cpp +++ b/src/qmlmodels/qqmllistmodel.cpp @@ -129,8 +129,28 @@ const ListLayout::Role &ListLayout::getRoleOrCreate(QV4::String *key, Role::Data const ListLayout::Role &ListLayout::createRole(const QString &key, ListLayout::Role::DataType type) { - const int dataSizes[] = { sizeof(StringOrTranslation), sizeof(double), sizeof(bool), sizeof(ListModel *), sizeof(ListElement::GuardedQObjectPointer), sizeof(QVariantMap), sizeof(QDateTime), sizeof(QUrl), sizeof(QJSValue) }; - const int dataAlignments[] = { alignof(StringOrTranslation), alignof(double), alignof(bool), alignof(ListModel *), alignof(QObject *), alignof(QVariantMap), alignof(QDateTime), alignof(QUrl), alignof(QJSValue) }; + const int dataSizes[] = { + sizeof(StringOrTranslation), + sizeof(double), + sizeof(bool), + sizeof(ListModel *), + sizeof(QV4::PersistentValue), + sizeof(QVariantMap), + sizeof(QDateTime), + sizeof(QUrl), + sizeof(QJSValue) + }; + const int dataAlignments[] = { + alignof(StringOrTranslation), + alignof(double), + alignof(bool), + alignof(ListModel *), + alignof(QV4::PersistentValue), + alignof(QVariantMap), + alignof(QDateTime), + alignof(QUrl), + alignof(QJSValue) + }; Role *r = new Role; r->name = key; @@ -567,6 +587,17 @@ ListModel *ListModel::getListProperty(int elementIndex, const ListLayout::Role & return e->getListProperty(role); } +void ListModel::updateTranslations() +{ + for (int index = 0; index != elements.count(); ++index) { + ListElement *e = elements[index]; + if (ModelNodeMetaObject *cache = e->objectCache()) { + // TODO: more fine grained tracking? + cache->updateValues(); + } + } +} + void ListModel::set(int elementIndex, QV4::Object *object, QVector<int> *roles) { ListElement *e = elements[elementIndex]; @@ -623,10 +654,9 @@ void ListModel::set(int elementIndex, QV4::Object *object, QVector<int> *roles) roleIndex = e->setFunctionProperty(r, jsv); } else if (QV4::Object *o = propertyValue->as<QV4::Object>()) { if (QV4::QObjectWrapper *wrapper = o->as<QV4::QObjectWrapper>()) { - QObject *o = wrapper->object(); const ListLayout::Role &role = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::QObject); if (role.type == ListLayout::Role::QObject) - roleIndex = e->setQObjectProperty(role, o); + roleIndex = e->setQObjectProperty(role, wrapper); } else if (QVariant maybeUrl = o->engine()->toVariant(o->asReturnedValue(), QMetaType::fromType<QUrl>(), true); maybeUrl.metaType() == QMetaType::fromType<QUrl>()) { const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Url); @@ -714,23 +744,21 @@ void ListModel::set(int elementIndex, QV4::Object *object, ListModel::SetElement } } else if (QV4::Object *o = propertyValue->as<QV4::Object>()) { if (QV4::QObjectWrapper *wrapper = o->as<QV4::QObjectWrapper>()) { - QObject *o = wrapper->object(); const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::QObject); if (r.type == ListLayout::Role::QObject) - e->setQObjectPropertyFast(r, o); + e->setQObjectPropertyFast(r, wrapper); } else { QVariant maybeUrl = o->engine()->toVariant(o->asReturnedValue(), QMetaType::fromType<QUrl>(), true); if (maybeUrl.metaType() == QMetaType::fromType<QUrl>()) { const QUrl qurl = maybeUrl.toUrl(); const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Url); - if (r.type == ListLayout::Role::Url) { + if (r.type == ListLayout::Role::Url) e->setUrlPropertyFast(r, qurl); - } - return; + } else { + const ListLayout::Role &role = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::VariantMap); + if (role.type == ListLayout::Role::VariantMap) + e->setVariantMapFast(role, o); } - const ListLayout::Role &role = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::VariantMap); - if (role.type == ListLayout::Role::VariantMap) - e->setVariantMapFast(role, o); } } else if (propertyValue->isNullOrUndefined()) { if (reason == SetElement::WasJustInserted) { @@ -842,12 +870,11 @@ StringOrTranslation *ListElement::getStringProperty(const ListLayout::Role &role return s; } -QObject *ListElement::getQObjectProperty(const ListLayout::Role &role) +QV4::QObjectWrapper *ListElement::getQObjectProperty(const ListLayout::Role &role) { char *mem = getPropertyMemory(role); - GuardedQObjectPointer *o - = reinterpret_cast<GuardedQObjectPointer *>(mem); - return o->data(); + QV4::PersistentValue *g = reinterpret_cast<QV4::PersistentValue *>(mem); + return g->as<QV4::QObjectWrapper>(); } QVariantMap *ListElement::getVariantMapProperty(const ListLayout::Role &role) @@ -894,13 +921,13 @@ QJSValue *ListElement::getFunctionProperty(const ListLayout::Role &role) return f; } -ListElement::GuardedQObjectPointer * +QV4::PersistentValue * ListElement::getGuardProperty(const ListLayout::Role &role) { char *mem = getPropertyMemory(role); bool existingGuard = false; - for (size_t i = 0; i < sizeof(GuardedQObjectPointer); + for (size_t i = 0; i < sizeof(QV4::PersistentValue); ++i) { if (mem[i] != 0) { existingGuard = true; @@ -908,12 +935,12 @@ ListElement::getGuardProperty(const ListLayout::Role &role) } } - GuardedQObjectPointer *o = nullptr; + QV4::PersistentValue *g = nullptr; if (existingGuard) - o = reinterpret_cast<GuardedQObjectPointer *>(mem); + g = reinterpret_cast<QV4::PersistentValue *>(mem); - return o; + return g; } ListModel *ListElement::getListProperty(const ListLayout::Role &role) @@ -969,12 +996,8 @@ QVariant ListElement::getProperty(const ListLayout::Role &role, const QQmlListMo break; case ListLayout::Role::QObject: { - GuardedQObjectPointer *guard = - reinterpret_cast<GuardedQObjectPointer *>( - mem); - QObject *object = guard->data(); - if (object) - data = QVariant::fromValue(object); + QV4::PersistentValue *guard = reinterpret_cast<QV4::PersistentValue *>(mem); + data = QVariant::fromValue(guard->as<QV4::QObjectWrapper>()->object()); } break; case ListLayout::Role::VariantMap: @@ -1086,69 +1109,17 @@ int ListElement::setListProperty(const ListLayout::Role &role, ListModel *m) return roleIndex; } -static void -restoreQObjectOwnership(ListElement::GuardedQObjectPointer *pointer) -{ - if (QObject *o = pointer->data()) { - QQmlData *data = QQmlData::get(o, 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) ListElement::GuardedQObjectPointer( - o, static_cast<ListElement::ObjectIndestructible>(ownership)); -} - -int ListElement::setQObjectProperty(const ListLayout::Role &role, QObject *o) +int ListElement::setQObjectProperty(const ListLayout::Role &role, QV4::QObjectWrapper *o) { int roleIndex = -1; if (role.type == ListLayout::Role::QObject) { char *mem = getPropertyMemory(role); - GuardedQObjectPointer *g = - reinterpret_cast<GuardedQObjectPointer *>(mem); - bool existingGuard = false; - for (size_t i = 0; i < sizeof(GuardedQObjectPointer); - ++i) { - if (mem[i] != 0) { - existingGuard = true; - break; - } - } - bool changed; - if (existingGuard) { - changed = g->data() != o; - if (changed) - restoreQObjectOwnership(g); - g->~GuardedQObjectPointer(); - } else { - changed = true; - } - - setQObjectOwnership(mem, o); - - if (changed) - roleIndex = role.index; + if (isMemoryUsed<QVariantMap>(mem)) + reinterpret_cast<QV4::PersistentValue *>(mem)->set(o->engine(), *o); + else + new (mem) QV4::PersistentValue(o->engine(), o); + roleIndex = role.index; } return roleIndex; @@ -1281,11 +1252,10 @@ void ListElement::setBoolPropertyFast(const ListLayout::Role &role, bool b) *value = b; } -void ListElement::setQObjectPropertyFast(const ListLayout::Role &role, QObject *o) +void ListElement::setQObjectPropertyFast(const ListLayout::Role &role, QV4::QObjectWrapper *o) { char *mem = getPropertyMemory(role); - - setQObjectOwnership(mem, o); + new (mem) QV4::PersistentValue(o->engine(), o); } void ListElement::setListPropertyFast(const ListLayout::Role &role, ListModel *m) @@ -1402,7 +1372,7 @@ QVector<int> ListElement::sync(ListElement *src, ListLayout *srcLayout, ListElem break; case ListLayout::Role::QObject: { - QObject *object = src->getQObjectProperty(srcRole); + QV4::QObjectWrapper *object = src->getQObjectProperty(srcRole); roleIndex = target->setQObjectProperty(targetRole, object); } break; @@ -1457,14 +1427,8 @@ void ListElement::destroy(ListLayout *layout) break; case ListLayout::Role::QObject: { - GuardedQObjectPointer *guard = - getGuardProperty(r); - - if (guard) { - restoreQObjectOwnership(guard); - - guard->~GuardedQObjectPointer(); - } + if (QV4::PersistentValue *guard = getGuardProperty(r)) + guard->~PersistentValue(); } break; case ListLayout::Role::VariantMap: @@ -1601,8 +1565,7 @@ int ListElement::setJsProperty(const ListLayout::Role &role, const QV4::Value &d QV4::ScopedObject o(scope, d); QV4::QObjectWrapper *wrapper = o->as<QV4::QObjectWrapper>(); if (role.type == ListLayout::Role::QObject && wrapper) { - QObject *o = wrapper->object(); - roleIndex = setQObjectProperty(role, o); + roleIndex = setQObjectProperty(role, wrapper); } else if (role.type == ListLayout::Role::VariantMap) { roleIndex = setVariantMapProperty(role, o); } else if (role.type == ListLayout::Role::Url) { @@ -2502,6 +2465,27 @@ void QQmlListModel::removeElements(int index, int removeCount) destroyer(); } +void QQmlListModel::updateTranslations() +{ + // assumption: it is impossible to have retranslatable strings in a + // dynamic list model, as they would already have "decayed" to strings + // when they were inserted + if (m_dynamicRoles) + return; + Q_ASSERT(m_listModel); + + QList<int> roles; + for (int i = 0, end = m_listModel->roleCount(); i != end; ++i) { + if (m_listModel->getExistingRole(i).type == ListLayout::Role::String) + roles.append(i); + } + + if (!roles.isEmpty()) + emitItemsChanged(0, rowCount(QModelIndex()), roles); + + m_listModel->updateTranslations(); +} + /*! \qmlmethod ListModel::insert(int index, jsobject dict) @@ -2847,7 +2831,7 @@ void QQmlListModel::sync() bool QQmlListModelParser::verifyProperty(const QQmlRefPointer<QV4::ExecutableCompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding) { - if (binding->type >= QV4::CompiledData::Binding::Type_Object) { + if (binding->type() >= QV4::CompiledData::Binding::Type_Object) { const quint32 targetObjectIndex = binding->value.objectIndex; const QV4::CompiledData::Object *target = compilationUnit->objectAt(targetObjectIndex); QString objName = compilationUnit->stringAt(target->inheritedTypeNameIndex); @@ -2875,7 +2859,7 @@ bool QQmlListModelParser::verifyProperty(const QQmlRefPointer<QV4::ExecutableCom if (!verifyProperty(compilationUnit, binding)) return false; } - } else if (binding->type == QV4::CompiledData::Binding::Type_Script) { + } else if (binding->type() == QV4::CompiledData::Binding::Type_Script) { QString scriptStr = compilationUnit->bindingValueAsScriptString(binding); if (!binding->isFunctionExpression() && !definesEmptyList(scriptStr)) { QByteArray script = scriptStr.toUtf8(); @@ -2898,7 +2882,8 @@ bool QQmlListModelParser::applyProperty( const QString elementName = compilationUnit->stringAt(binding->propertyNameIndex); bool roleSet = false; - if (binding->type >= QV4::CompiledData::Binding::Type_Object) { + const QV4::CompiledData::Binding::Type bindingType = binding->type(); + if (bindingType >= QV4::CompiledData::Binding::Type_Object) { const quint32 targetObjectIndex = binding->value.objectIndex; const QV4::CompiledData::Object *target = compilationUnit->objectAt(targetObjectIndex); @@ -2927,17 +2912,18 @@ bool QQmlListModelParser::applyProperty( } else { QVariant value; - if (binding->isTranslationBinding()) { + const bool isTranslationBinding = binding->isTranslationBinding(); + if (isTranslationBinding) { value = QVariant::fromValue<const QV4::CompiledData::Binding*>(binding); } else if (binding->evaluatesToString()) { value = compilationUnit->bindingValueAsString(binding); - } else if (binding->type == QV4::CompiledData::Binding::Type_Number) { + } else if (bindingType == QV4::CompiledData::Binding::Type_Number) { value = compilationUnit->bindingValueAsNumber(binding); - } else if (binding->type == QV4::CompiledData::Binding::Type_Boolean) { + } else if (bindingType == QV4::CompiledData::Binding::Type_Boolean) { value = binding->valueAsBoolean(); - } else if (binding->type == QV4::CompiledData::Binding::Type_Null) { + } else if (bindingType == QV4::CompiledData::Binding::Type_Null) { value = QVariant::fromValue(nullptr); - } else if (binding->type == QV4::CompiledData::Binding::Type_Script) { + } else if (bindingType == QV4::CompiledData::Binding::Type_Script) { QString scriptStr = compilationUnit->bindingValueAsScriptString(binding); if (definesEmptyList(scriptStr)) { const ListLayout::Role &role = model->getOrCreateListRole(elementName); @@ -2969,7 +2955,17 @@ bool QQmlListModelParser::applyProperty( Q_UNREACHABLE(); } + if (!model) + return roleSet; model->setOrCreateProperty(outterElementIndex, elementName, value); + auto listModel = model->m_modelCache; + if (isTranslationBinding && listModel) { + if (!listModel->translationChangeHandler) { + auto ep = QQmlEnginePrivate::get(compilationUnit->engine); + model->m_modelCache->translationChangeHandler = std::make_unique<QPropertyNotifier>( + ep->translationLanguage.addNotifier([listModel](){ listModel->updateTranslations(); })); + } + } roleSet = true; } return roleSet; @@ -3000,7 +2996,7 @@ void QQmlListModelParser::applyBindings(QObject *obj, const QQmlRefPointer<QV4:: bool setRoles = false; for (const QV4::CompiledData::Binding *binding : bindings) { - if (binding->type != QV4::CompiledData::Binding::Type_Object) + if (binding->type() != QV4::CompiledData::Binding::Type_Object) continue; setRoles |= applyProperty(compilationUnit, binding, rv->m_listModel, /*outter element index*/-1); } @@ -3070,4 +3066,6 @@ bool QQmlListModelParser::definesEmptyList(const QString &s) QT_END_NAMESPACE +#include "moc_qqmllistmodel_p_p.cpp" + #include "moc_qqmllistmodel_p.cpp" diff --git a/src/qmlmodels/qqmllistmodel_p.h b/src/qmlmodels/qqmllistmodel_p.h index 2e8181e10c..7cd2b4662b 100644 --- a/src/qmlmodels/qqmllistmodel_p.h +++ b/src/qmlmodels/qqmllistmodel_p.h @@ -148,6 +148,7 @@ private: ListLayout *m_layout; ListModel *m_listModel; + std::unique_ptr<QPropertyNotifier> translationChangeHandler; QVector<class DynamicRoleModelNode *> m_modelObjects; QVector<QString> m_roles; @@ -169,6 +170,8 @@ private: void emitItemsInserted(); void removeElements(int index, int removeCount); + + void updateTranslations(); }; // ### FIXME diff --git a/src/qmlmodels/qqmllistmodel_p_p.h b/src/qmlmodels/qqmllistmodel_p_p.h index 6c40934c04..19cba980f4 100644 --- a/src/qmlmodels/qqmllistmodel_p_p.h +++ b/src/qmlmodels/qqmllistmodel_p_p.h @@ -281,43 +281,6 @@ public: enum ObjectIndestructible { Indestructible = 1, ExplicitlySet = 2 }; enum { BLOCK_SIZE = 64 - sizeof(int) - sizeof(ListElement *) - sizeof(ModelNodeMetaObject *) }; - // This is a basic guarded QObject pointer, with tag. It cannot be copied or moved. - class GuardedQObjectPointer - { - Q_DISABLE_COPY_MOVE(GuardedQObjectPointer) - - using RefCountData = QtSharedPointer::ExternalRefCountData; - using Storage = QTaggedPointer<QObject, ObjectIndestructible>; - - public: - GuardedQObjectPointer(QObject *o, ObjectIndestructible ownership) - : storage(o, ownership) - , refCount(o ? RefCountData::getAndRef(o) : nullptr) - {} - - ~GuardedQObjectPointer() - { - if (refCount && !refCount->weakref.deref()) - delete refCount; - } - - QObject *data() const - { - return (refCount == nullptr || refCount->strongref.loadRelaxed() == 0) - ? nullptr - : storage.data(); - } - - ObjectIndestructible tag() const - { - return storage.tag(); - } - - private: - Storage storage; - RefCountData *refCount = nullptr; - }; - ListElement(); ListElement(int existingUid); ~ListElement(); @@ -336,7 +299,7 @@ private: int setDoubleProperty(const ListLayout::Role &role, double n); int setBoolProperty(const ListLayout::Role &role, bool b); int setListProperty(const ListLayout::Role &role, ListModel *m); - int setQObjectProperty(const ListLayout::Role &role, QObject *o); + int setQObjectProperty(const ListLayout::Role &role, QV4::QObjectWrapper *o); int setVariantMapProperty(const ListLayout::Role &role, QV4::Object *o); int setVariantMapProperty(const ListLayout::Role &role, QVariantMap *m); int setDateTimeProperty(const ListLayout::Role &role, const QDateTime &dt); @@ -347,7 +310,7 @@ private: void setStringPropertyFast(const ListLayout::Role &role, const QString &s); void setDoublePropertyFast(const ListLayout::Role &role, double n); void setBoolPropertyFast(const ListLayout::Role &role, bool b); - void setQObjectPropertyFast(const ListLayout::Role &role, QObject *o); + void setQObjectPropertyFast(const ListLayout::Role &role, QV4::QObjectWrapper *o); void setListPropertyFast(const ListLayout::Role &role, ListModel *m); void setVariantMapFast(const ListLayout::Role &role, QV4::Object *o); void setDateTimePropertyFast(const ListLayout::Role &role, const QDateTime &dt); @@ -359,8 +322,8 @@ private: QVariant getProperty(const ListLayout::Role &role, const QQmlListModel *owner, QV4::ExecutionEngine *eng); ListModel *getListProperty(const ListLayout::Role &role); StringOrTranslation *getStringProperty(const ListLayout::Role &role); - QObject *getQObjectProperty(const ListLayout::Role &role); - GuardedQObjectPointer *getGuardProperty(const ListLayout::Role &role); + QV4::QObjectWrapper *getQObjectProperty(const ListLayout::Role &role); + QV4::PersistentValue *getGuardProperty(const ListLayout::Role &role); QVariantMap *getVariantMapProperty(const ListLayout::Role &role); QDateTime *getDateTimeProperty(const ListLayout::Role &role); QUrl *getUrlProperty(const ListLayout::Role &role); @@ -399,6 +362,8 @@ public: QVariant getProperty(int elementIndex, int roleIndex, const QQmlListModel *owner, QV4::ExecutionEngine *eng); ListModel *getListProperty(int elementIndex, const ListLayout::Role &role); + void updateTranslations(); + int roleCount() const { return m_layout->roleCount(); diff --git a/src/qmlmodels/qqmlmodelindexvaluetype.cpp b/src/qmlmodels/qqmlmodelindexvaluetype.cpp new file mode 100644 index 0000000000..cbf2fef348 --- /dev/null +++ b/src/qmlmodels/qqmlmodelindexvaluetype.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qqmlmodelindexvaluetype_p.h" + +QT_BEGIN_NAMESPACE + +/*! + \internal +*/ +QString QQmlModelIndexValueType::propertiesString(const QModelIndex &idx) +{ + if (!idx.isValid()) + return QLatin1String("()"); + return QString(QLatin1String("(%1,%2,0x%3,%4(0x%5))")) + .arg(idx.row()).arg(idx.column()).arg(idx.internalId(), 0, 16) + .arg(QLatin1String(idx.model()->metaObject()->className())).arg(quintptr(idx.model()), 0, 16); +} + +/*! + \internal +*/ +QString QQmlItemSelectionRangeValueType::toString() const +{ + return QString(QLatin1String("QItemSelectionRange(%1,%2)")) + .arg(reinterpret_cast<const QQmlPersistentModelIndexValueType *>(&v.topLeft())->toString()) + .arg(reinterpret_cast<const QQmlPersistentModelIndexValueType *>(&v.bottomRight())->toString()); +} + +QT_END_NAMESPACE + +#include "moc_qqmlmodelindexvaluetype_p.cpp" diff --git a/src/qmlmodels/qqmlmodelindexvaluetype_p.h b/src/qmlmodels/qqmlmodelindexvaluetype_p.h new file mode 100644 index 0000000000..2c37d91c71 --- /dev/null +++ b/src/qmlmodels/qqmlmodelindexvaluetype_p.h @@ -0,0 +1,174 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QQMLMODELINDEXVALUETYPE_P_H +#define QQMLMODELINDEXVALUETYPE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qabstractitemmodel.h> +#include <QtCore/qitemselectionmodel.h> +#include <QtQml/qqml.h> + +QT_BEGIN_NAMESPACE + +struct QQmlModelIndexValueType +{ + QModelIndex v; + + Q_PROPERTY(int row READ row CONSTANT FINAL) + Q_PROPERTY(int column READ column CONSTANT FINAL) + Q_PROPERTY(QModelIndex parent READ parent FINAL) + Q_PROPERTY(bool valid READ isValid CONSTANT FINAL) + Q_PROPERTY(QAbstractItemModel *model READ model CONSTANT FINAL) + Q_PROPERTY(quint64 internalId READ internalId CONSTANT FINAL) + Q_GADGET + QML_ANONYMOUS + QML_EXTENDED(QQmlModelIndexValueType) + QML_FOREIGN(QModelIndex) + QML_ADDED_IN_VERSION(2, 0) + +public: + Q_INVOKABLE QString toString() const + { return QLatin1String("QModelIndex") + propertiesString(v); } + + inline int row() const noexcept { return v.row(); } + inline int column() const noexcept { return v.column(); } + inline QModelIndex parent() const { return v.parent(); } + inline bool isValid() const noexcept { return v.isValid(); } + inline QAbstractItemModel *model() const noexcept + { return const_cast<QAbstractItemModel *>(v.model()); } + quint64 internalId() const { return v.internalId(); } + + static QString propertiesString(const QModelIndex &idx); + + static QPersistentModelIndex toPersistentModelIndex(const QModelIndex &index) + { return QPersistentModelIndex(index); } +}; + +struct QQmlPersistentModelIndexValueType +{ + QPersistentModelIndex v; + + Q_PROPERTY(int row READ row FINAL) + Q_PROPERTY(int column READ column FINAL) + Q_PROPERTY(QModelIndex parent READ parent FINAL) + Q_PROPERTY(bool valid READ isValid FINAL) + Q_PROPERTY(QAbstractItemModel *model READ model FINAL) + Q_PROPERTY(quint64 internalId READ internalId FINAL) + Q_GADGET + QML_ANONYMOUS + QML_EXTENDED(QQmlPersistentModelIndexValueType) + QML_FOREIGN(QPersistentModelIndex) + QML_ADDED_IN_VERSION(2, 0) + +public: + Q_INVOKABLE QString toString() const + { return QLatin1String("QPersistentModelIndex") + QQmlModelIndexValueType::propertiesString(v); } + + inline int row() const { return v.row(); } + inline int column() const { return v.column(); } + inline QModelIndex parent() const { return v.parent(); } + inline bool isValid() const { return v.isValid(); } + inline QAbstractItemModel *model() const { return const_cast<QAbstractItemModel *>(v.model()); } + inline quint64 internalId() const { return v.internalId(); } +}; + +struct QQmlItemSelectionRangeValueType +{ + QItemSelectionRange v; + + Q_PROPERTY(int top READ top FINAL) + Q_PROPERTY(int left READ left FINAL) + Q_PROPERTY(int bottom READ bottom FINAL) + Q_PROPERTY(int right READ right FINAL) + Q_PROPERTY(int width READ width FINAL) + Q_PROPERTY(int height READ height FINAL) + Q_PROPERTY(QPersistentModelIndex topLeft READ topLeft FINAL) + Q_PROPERTY(QPersistentModelIndex bottomRight READ bottomRight FINAL) + Q_PROPERTY(QModelIndex parent READ parent FINAL) + Q_PROPERTY(bool valid READ isValid FINAL) + Q_PROPERTY(bool empty READ isEmpty FINAL) + Q_PROPERTY(QAbstractItemModel *model READ model FINAL) + Q_GADGET + QML_ANONYMOUS + QML_EXTENDED(QQmlItemSelectionRangeValueType) + QML_FOREIGN(QItemSelectionRange) + QML_ADDED_IN_VERSION(2, 0) + +public: + Q_INVOKABLE QString toString() const; + Q_INVOKABLE inline bool contains(const QModelIndex &index) const + { return v.contains(index); } + Q_INVOKABLE inline bool contains(int row, int column, const QModelIndex &parentIndex) const + { return v.contains(row, column, parentIndex); } + Q_INVOKABLE inline bool intersects(const QItemSelectionRange &other) const + { return v.intersects(other); } + Q_INVOKABLE QItemSelectionRange intersected(const QItemSelectionRange &other) const + { return v.intersected(other); } + + inline int top() const { return v.top(); } + inline int left() const { return v.left(); } + inline int bottom() const { return v.bottom(); } + inline int right() const { return v.right(); } + inline int width() const { return v.width(); } + inline int height() const { return v.height(); } + inline QPersistentModelIndex &topLeft() const { return const_cast<QPersistentModelIndex &>(v.topLeft()); } + inline QPersistentModelIndex &bottomRight() const { return const_cast<QPersistentModelIndex &>(v.bottomRight()); } + inline QModelIndex parent() const { return v.parent(); } + inline QAbstractItemModel *model() const { return const_cast<QAbstractItemModel *>(v.model()); } + inline bool isValid() const { return v.isValid(); } + inline bool isEmpty() const { return v.isEmpty(); } +}; + +#undef QLISTVALUETYPE_INVOKABLE_API + +QT_END_NAMESPACE + +#endif // QQMLMODELINDEXVALUETYPE_P_H + |