aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/types
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/types')
-rw-r--r--src/qml/types/qqmldelegatecomponent.cpp300
-rw-r--r--src/qml/types/qqmldelegatecomponent_p.h155
-rw-r--r--src/qml/types/qqmldelegatemodel.cpp3540
-rw-r--r--src/qml/types/qqmldelegatemodel_p.h248
-rw-r--r--src/qml/types/qqmldelegatemodel_p_p.h450
-rw-r--r--src/qml/types/qqmlinstantiator.cpp509
-rw-r--r--src/qml/types/qqmlinstantiator_p.h119
-rw-r--r--src/qml/types/qqmlinstantiator_p_p.h98
-rw-r--r--src/qml/types/qqmlitemmodels.qdoc110
-rw-r--r--src/qml/types/qqmlitemselectionmodel.qdoc239
-rw-r--r--src/qml/types/qqmllistmodel.cpp2900
-rw-r--r--src/qml/types/qqmllistmodel_p.h208
-rw-r--r--src/qml/types/qqmllistmodel_p_p.h428
-rw-r--r--src/qml/types/qqmllistmodelworkeragent.cpp177
-rw-r--r--src/qml/types/qqmllistmodelworkeragent_p.h140
-rw-r--r--src/qml/types/qqmlmodelsmodule.cpp123
-rw-r--r--src/qml/types/qqmlmodelsmodule_p.h72
-rw-r--r--src/qml/types/qqmlobjectmodel.cpp431
-rw-r--r--src/qml/types/qqmlobjectmodel_p.h194
-rw-r--r--src/qml/types/qqmltableinstancemodel.cpp547
-rw-r--r--src/qml/types/qqmltableinstancemodel_p.h162
-rw-r--r--src/qml/types/qqmltablemodel.cpp1059
-rw-r--r--src/qml/types/qqmltablemodel_p.h170
-rw-r--r--src/qml/types/qqmltablemodelcolumn.cpp200
-rw-r--r--src/qml/types/qqmltablemodelcolumn_p.h224
-rw-r--r--src/qml/types/qquickpackage.cpp198
-rw-r--r--src/qml/types/qquickpackage_p.h101
-rw-r--r--src/qml/types/types.pri41
28 files changed, 2 insertions, 13141 deletions
diff --git a/src/qml/types/qqmldelegatecomponent.cpp b/src/qml/types/qqmldelegatecomponent.cpp
deleted file mode 100644
index 470f6cab6a..0000000000
--- a/src/qml/types/qqmldelegatecomponent.cpp
+++ /dev/null
@@ -1,300 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 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 "qqmldelegatecomponent_p.h"
-#include <QtQml/private/qqmladaptormodel_p.h>
-
-QT_BEGIN_NAMESPACE
-
-QQmlAbstractDelegateComponent::QQmlAbstractDelegateComponent(QObject *parent)
- : QQmlComponent(parent)
-{
-}
-
-QQmlAbstractDelegateComponent::~QQmlAbstractDelegateComponent()
-{
-}
-
-QVariant QQmlAbstractDelegateComponent::value(QQmlAdaptorModel *adaptorModel, int row, int column, const QString &role) const
-{
- if (!adaptorModel)
- return QVariant();
- return adaptorModel->value(adaptorModel->indexAt(row, column), role);
-}
-
-/*!
- \qmlmodule Qt.labs.qmlmodels 1.0
- \title Qt Labs QML Models - QML Types
- \ingroup qmlmodules
- \brief The Qt Labs QML Models module provides various model-related types for use with views.
-
- To use this module, import the module with the following line:
-
- \qml
- import Qt.labs.qmlmodels 1.0
- \endqml
-*/
-
-/*!
- \qmltype DelegateChoice
- \instantiates QQmlDelegateChoice
- \inqmlmodule Qt.labs.qmlmodels
- \brief Encapsulates a delegate and when to use it.
-
- The DelegateChoice type wraps a delegate and defines the circumstances
- in which it should be chosen.
-
- DelegateChoices can be nested inside a DelegateChooser.
-
- \sa DelegateChooser
-*/
-
-/*!
- \qmlproperty string QtQml.Models::DelegateChoice::roleValue
- This property holds the value used to match the role data for the role provided by \l DelegateChooser::role.
-*/
-QVariant QQmlDelegateChoice::roleValue() const
-{
- return m_value;
-}
-
-void QQmlDelegateChoice::setRoleValue(const QVariant &value)
-{
- if (m_value == value)
- return;
- m_value = value;
- emit roleValueChanged();
- emit changed();
-}
-
-/*!
- \qmlproperty index QtQml.Models::DelegateChoice::row
- This property holds the value used to match the row value of model elements.
- With models that have only the index property (and thus only one column), this property
- should be intended as an index, and set to the desired index value.
-
- \note Setting both row and index has undefined behavior. The two are equivalent and only
- one should be used.
-
- \sa index
-*/
-
-/*!
- \qmlproperty index QtQml.Models::DelegateChoice::index
- This property holds the value used to match the index value of model elements.
- This is effectively an alias for \l row.
-
- \sa row
-*/
-int QQmlDelegateChoice::row() const
-{
- return m_row;
-}
-
-void QQmlDelegateChoice::setRow(int r)
-{
- if (m_row == r)
- return;
- m_row = r;
- emit rowChanged();
- emit indexChanged();
- emit changed();
-}
-
-/*!
- \qmlproperty index QtQml.Models::DelegateChoice::column
- This property holds the value used to match the column value of model elements.
-*/
-int QQmlDelegateChoice::column() const
-{
- return m_column;
-}
-
-void QQmlDelegateChoice::setColumn(int c)
-{
- if (m_column == c)
- return;
- m_column = c;
- emit columnChanged();
- emit changed();
-}
-
-QQmlComponent *QQmlDelegateChoice::delegate() const
-{
- return m_delegate;
-}
-
-/*!
- \qmlproperty Component QtQml.Models::DelegateChoice::delegate
- This property holds the delegate to use if this choice matches the model item.
-*/
-void QQmlDelegateChoice::setDelegate(QQmlComponent *delegate)
-{
- if (m_delegate == delegate)
- return;
- QQmlAbstractDelegateComponent *adc = static_cast<QQmlAbstractDelegateComponent *>(m_delegate);
- if (adc)
- disconnect(adc, &QQmlAbstractDelegateComponent::delegateChanged, this, &QQmlDelegateChoice::delegateChanged);
- m_delegate = delegate;
- adc = static_cast<QQmlAbstractDelegateComponent *>(delegate);
- if (adc)
- connect(adc, &QQmlAbstractDelegateComponent::delegateChanged, this, &QQmlDelegateChoice::delegateChanged);
- emit delegateChanged();
- emit changed();
-}
-
-bool QQmlDelegateChoice::match(int row, int column, const QVariant &value) const
-{
- if (!m_value.isValid() && m_row < 0 && m_column < 0)
- return true;
-
- const bool roleMatched = (m_value.isValid()) ? value == m_value : true;
- const bool rowMatched = (m_row < 0 ) ? true : m_row == row;
- const bool columnMatched = (m_column < 0 ) ? true : m_column == column;
- return roleMatched && rowMatched && columnMatched;
-}
-
-/*!
- \qmltype DelegateChooser
- \instantiates QQmlDelegateChooser
- \inqmlmodule Qt.labs.qmlmodels
- \brief Allows a view to use different delegates for different types of items in the model.
-
- The DelegateChooser is a special \l Component type intended for those scenarios where a Component is required
- by a view and used as a delegate.
- DelegateChooser encapsulates a set of \l {DelegateChoice}s.
- These choices are used determine the delegate that will be instantiated for each
- item in the model.
- The selection of the choice is performed based on the value that a model item has for \l role,
- and also based on index.
-
- \note This type is intended to transparently work only with TableView and any DelegateModel-based view.
- Views (including user-defined views) that aren't internally based on a DelegateModel need to explicitly support
- this type of component to make it function as described.
-
- \sa DelegateChoice
-*/
-
-/*!
- \qmlproperty string QtQml.Models::DelegateChooser::role
- This property holds the role used to determine the delegate for a given model item.
-
- \sa DelegateChoice
-*/
-void QQmlDelegateChooser::setRole(const QString &role)
-{
- if (m_role == role)
- return;
- m_role = role;
- emit roleChanged();
-}
-
-/*!
- \qmlproperty list<DelegateChoice> QtQml.Models::DelegateChooser::choices
- \default
-
- The list of DelegateChoices for the chooser.
-
- The list is treated as an ordered list, where the first DelegateChoice to match
- will be used be a view.
-
- It should not generally be necessary to refer to the \c choices property,
- as it is the default property for DelegateChooser and thus all child items are
- automatically assigned to this property.
-*/
-
-QQmlListProperty<QQmlDelegateChoice> QQmlDelegateChooser::choices()
-{
- return QQmlListProperty<QQmlDelegateChoice>(this, nullptr,
- QQmlDelegateChooser::choices_append,
- QQmlDelegateChooser::choices_count,
- QQmlDelegateChooser::choices_at,
- QQmlDelegateChooser::choices_clear);
-}
-
-void QQmlDelegateChooser::choices_append(QQmlListProperty<QQmlDelegateChoice> *prop, QQmlDelegateChoice *choice)
-{
- QQmlDelegateChooser *q = static_cast<QQmlDelegateChooser *>(prop->object);
- q->m_choices.append(choice);
- connect(choice, &QQmlDelegateChoice::changed, q, &QQmlAbstractDelegateComponent::delegateChanged);
- q->delegateChanged();
-}
-
-int QQmlDelegateChooser::choices_count(QQmlListProperty<QQmlDelegateChoice> *prop)
-{
- QQmlDelegateChooser *q = static_cast<QQmlDelegateChooser*>(prop->object);
- return q->m_choices.count();
-}
-
-QQmlDelegateChoice *QQmlDelegateChooser::choices_at(QQmlListProperty<QQmlDelegateChoice> *prop, int index)
-{
- QQmlDelegateChooser *q = static_cast<QQmlDelegateChooser*>(prop->object);
- return q->m_choices.at(index);
-}
-
-void QQmlDelegateChooser::choices_clear(QQmlListProperty<QQmlDelegateChoice> *prop)
-{
- QQmlDelegateChooser *q = static_cast<QQmlDelegateChooser *>(prop->object);
- for (QQmlDelegateChoice *choice : q->m_choices)
- disconnect(choice, &QQmlDelegateChoice::changed, q, &QQmlAbstractDelegateComponent::delegateChanged);
- q->m_choices.clear();
- q->delegateChanged();
-}
-
-QQmlComponent *QQmlDelegateChooser::delegate(QQmlAdaptorModel *adaptorModel, int row, int column) const
-{
- QVariant v;
- if (!m_role.isNull())
- v = value(adaptorModel, row, column, m_role);
- if (!v.isValid()) { // check if the row only has modelData, for example if the row is a QVariantMap
- v = value(adaptorModel, row, column, QStringLiteral("modelData"));
- if (v.isValid())
- v = v.toMap().value(m_role);
- }
- // loop through choices, finding first one that fits
- for (int i = 0; i < m_choices.count(); ++i) {
- const QQmlDelegateChoice *choice = m_choices.at(i);
- if (choice->match(row, column, v))
- return choice->delegate();
- }
-
- return nullptr;
-}
-
-QT_END_NAMESPACE
diff --git a/src/qml/types/qqmldelegatecomponent_p.h b/src/qml/types/qqmldelegatecomponent_p.h
deleted file mode 100644
index c925ed9a60..0000000000
--- a/src/qml/types/qqmldelegatecomponent_p.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 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 QQMLDELEGATECOMPONENT_P_H
-#define QQMLDELEGATECOMPONENT_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 <private/qtqmlglobal_p.h>
-#include <qqmlcomponent.h>
-
-QT_REQUIRE_CONFIG(qml_delegate_model);
-
-QT_BEGIN_NAMESPACE
-
-// TODO: consider making QQmlAbstractDelegateComponent public API
-class QQmlAbstractDelegateComponentPrivate;
-class QQmlAdaptorModel;
-class Q_QML_PRIVATE_EXPORT QQmlAbstractDelegateComponent : public QQmlComponent
-{
- Q_OBJECT
-public:
- QQmlAbstractDelegateComponent(QObject *parent = nullptr);
- ~QQmlAbstractDelegateComponent() override;
-
- virtual QQmlComponent *delegate(QQmlAdaptorModel *adaptorModel, int row, int column = 0) const = 0;
-
-signals:
- void delegateChanged();
-
-protected:
- QVariant value(QQmlAdaptorModel *adaptorModel,int row, int column, const QString &role) const;
-
-private:
- Q_DECLARE_PRIVATE(QQmlAbstractDelegateComponent)
- Q_DISABLE_COPY(QQmlAbstractDelegateComponent)
-};
-
-class Q_QML_PRIVATE_EXPORT QQmlDelegateChoice : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(QVariant roleValue READ roleValue WRITE setRoleValue NOTIFY roleValueChanged)
- Q_PROPERTY(int row READ row WRITE setRow NOTIFY rowChanged)
- Q_PROPERTY(int index READ row WRITE setRow NOTIFY indexChanged)
- Q_PROPERTY(int column READ column WRITE setColumn NOTIFY columnChanged)
- Q_PROPERTY(QQmlComponent* delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
- Q_CLASSINFO("DefaultProperty", "delegate")
-public:
- QVariant roleValue() const;
- void setRoleValue(const QVariant &roleValue);
-
- int row() const;
- void setRow(int r);
-
- int column() const;
- void setColumn(int c);
-
- QQmlComponent *delegate() const;
- void setDelegate(QQmlComponent *delegate);
-
- virtual bool match(int row, int column, const QVariant &value) const;
-
-signals:
- void roleValueChanged();
- void rowChanged();
- void indexChanged();
- void columnChanged();
- void delegateChanged();
- void changed();
-
-private:
- QVariant m_value;
- int m_row = -1;
- int m_column = -1;
- QQmlComponent *m_delegate = nullptr;
-};
-
-class Q_QML_PRIVATE_EXPORT QQmlDelegateChooser : public QQmlAbstractDelegateComponent
-{
- Q_OBJECT
- Q_PROPERTY(QString role READ role WRITE setRole NOTIFY roleChanged)
- Q_PROPERTY(QQmlListProperty<QQmlDelegateChoice> choices READ choices CONSTANT)
- Q_CLASSINFO("DefaultProperty", "choices")
-
-public:
- QString role() const { return m_role; }
- void setRole(const QString &role);
-
- virtual QQmlListProperty<QQmlDelegateChoice> choices();
- static void choices_append(QQmlListProperty<QQmlDelegateChoice> *, QQmlDelegateChoice *);
- static int choices_count(QQmlListProperty<QQmlDelegateChoice> *);
- static QQmlDelegateChoice *choices_at(QQmlListProperty<QQmlDelegateChoice> *, int);
- static void choices_clear(QQmlListProperty<QQmlDelegateChoice> *);
-
- QQmlComponent *delegate(QQmlAdaptorModel *adaptorModel, int row, int column = -1) const override;
-
-signals:
- void roleChanged();
-
-private:
- QString m_role;
- QList<QQmlDelegateChoice *> m_choices;
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQmlDelegateChoice)
-QML_DECLARE_TYPE(QQmlDelegateChooser)
-
-#endif // QQMLDELEGATECOMPONENT_P_H
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp
deleted file mode 100644
index 0e57119368..0000000000
--- a/src/qml/types/qqmldelegatemodel.cpp
+++ /dev/null
@@ -1,3540 +0,0 @@
-/****************************************************************************
-**
-** 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 "qqmldelegatemodel_p_p.h"
-#include "qqmldelegatecomponent_p.h"
-
-#include <QtQml/qqmlinfo.h>
-
-#include <private/qquickpackage_p.h>
-#include <private/qmetaobjectbuilder_p.h>
-#include <private/qqmladaptormodel_p.h>
-#include <private/qqmlchangeset_p.h>
-#include <private/qqmlengine_p.h>
-#include <private/qqmlcomponent_p.h>
-#include <private/qqmlincubator_p.h>
-
-#include <private/qv4value_p.h>
-#include <private/qv4functionobject_p.h>
-#include <qv4objectiterator_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QQmlDelegateModelItem;
-
-namespace QV4 {
-
-namespace Heap {
-
-struct DelegateModelGroupFunction : FunctionObject {
- void init(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::Value &arg));
-
- QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::Value &arg);
- uint flag;
-};
-
-struct QQmlDelegateModelGroupChange : Object {
- void init() { Object::init(); }
-
- QQmlChangeSet::ChangeData change;
-};
-
-struct QQmlDelegateModelGroupChangeArray : Object {
- void init(const QVector<QQmlChangeSet::Change> &changes);
- void destroy() {
- delete changes;
- Object::destroy();
- }
-
- QVector<QQmlChangeSet::Change> *changes;
-};
-
-
-}
-
-struct DelegateModelGroupFunction : QV4::FunctionObject
-{
- V4_OBJECT2(DelegateModelGroupFunction, FunctionObject)
-
- static Heap::DelegateModelGroupFunction *create(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::Value &arg))
- {
- return scope->engine()->memoryManager->allocate<DelegateModelGroupFunction>(scope, flag, code);
- }
-
- static ReturnedValue virtualCall(const QV4::FunctionObject *that, const Value *thisObject, const Value *argv, int argc)
- {
- QV4::Scope scope(that->engine());
- QV4::Scoped<DelegateModelGroupFunction> f(scope, static_cast<const DelegateModelGroupFunction *>(that));
- QV4::Scoped<QQmlDelegateModelItemObject> o(scope, thisObject);
- if (!o)
- return scope.engine->throwTypeError(QStringLiteral("Not a valid DelegateModel object"));
-
- QV4::ScopedValue v(scope, argc ? argv[0] : Value::undefinedValue());
- return f->d()->code(o->d()->item, f->d()->flag, v);
- }
-};
-
-void Heap::DelegateModelGroupFunction::init(QV4::ExecutionContext *scope, uint flag, QV4::ReturnedValue (*code)(QQmlDelegateModelItem *item, uint flag, const QV4::Value &arg))
-{
- QV4::Heap::FunctionObject::init(scope, QStringLiteral("DelegateModelGroupFunction"));
- this->flag = flag;
- this->code = code;
-}
-
-}
-
-DEFINE_OBJECT_VTABLE(QV4::DelegateModelGroupFunction);
-
-
-
-class QQmlDelegateModelEngineData : public QV8Engine::Deletable
-{
-public:
- QQmlDelegateModelEngineData(QV4::ExecutionEngine *v4);
- ~QQmlDelegateModelEngineData();
-
- QV4::ReturnedValue array(QV4::ExecutionEngine *engine,
- const QVector<QQmlChangeSet::Change> &changes);
-
- QV4::PersistentValue changeProto;
-};
-
-V4_DEFINE_EXTENSION(QQmlDelegateModelEngineData, engineData)
-
-
-void QQmlDelegateModelPartsMetaObject::propertyCreated(int, QMetaPropertyBuilder &prop)
-{
- prop.setWritable(false);
-}
-
-QVariant QQmlDelegateModelPartsMetaObject::initialValue(int id)
-{
- QQmlDelegateModelParts *parts = static_cast<QQmlDelegateModelParts *>(object());
- QQmlPartsModel *m = new QQmlPartsModel(
- parts->model, QString::fromUtf8(name(id)), parts);
- parts->models.append(m);
- return QVariant::fromValue(static_cast<QObject *>(m));
-}
-
-QQmlDelegateModelParts::QQmlDelegateModelParts(QQmlDelegateModel *parent)
-: QObject(parent), model(parent)
-{
- new QQmlDelegateModelPartsMetaObject(this);
-}
-
-//---------------------------------------------------------------------------
-
-/*!
- \qmltype DelegateModel
- \instantiates QQmlDelegateModel
- \inqmlmodule QtQml.Models
- \brief Encapsulates a model and delegate.
-
- The DelegateModel type encapsulates a model and the delegate that will
- be instantiated for items in the model.
-
- It is usually not necessary to create a DelegateModel.
- However, it can be useful for manipulating and accessing the \l modelIndex
- when a QAbstractItemModel subclass is used as the
- model. Also, DelegateModel is used together with \l Package to
- provide delegates to multiple views, and with DelegateModelGroup to sort and filter
- delegate items.
-
- The example below illustrates using a DelegateModel with a ListView.
-
- \snippet delegatemodel/delegatemodel.qml 0
-*/
-
-QQmlDelegateModelPrivate::QQmlDelegateModelPrivate(QQmlContext *ctxt)
- : m_delegateChooser(nullptr)
- , m_cacheMetaType(nullptr)
- , m_context(ctxt)
- , m_parts(nullptr)
- , m_filterGroup(QStringLiteral("items"))
- , m_count(0)
- , m_groupCount(Compositor::MinimumGroupCount)
- , m_compositorGroup(Compositor::Cache)
- , m_complete(false)
- , m_delegateValidated(false)
- , m_reset(false)
- , m_transaction(false)
- , m_incubatorCleanupScheduled(false)
- , m_waitingToFetchMore(false)
- , m_cacheItems(nullptr)
- , m_items(nullptr)
- , m_persistedItems(nullptr)
-{
-}
-
-QQmlDelegateModelPrivate::~QQmlDelegateModelPrivate()
-{
- qDeleteAll(m_finishedIncubating);
-
- if (m_cacheMetaType)
- m_cacheMetaType->release();
-}
-
-int QQmlDelegateModelPrivate::adaptorModelCount() const
-{
- // QQmlDelegateModel currently only support list models.
- // So even if a model is a table model, only the first
- // column will be used.
- return m_adaptorModel.rowCount();
-}
-
-void QQmlDelegateModelPrivate::requestMoreIfNecessary()
-{
- Q_Q(QQmlDelegateModel);
- if (!m_waitingToFetchMore && m_adaptorModel.canFetchMore()) {
- m_waitingToFetchMore = true;
- QCoreApplication::postEvent(q, new QEvent(QEvent::UpdateRequest));
- }
-}
-
-void QQmlDelegateModelPrivate::init()
-{
- Q_Q(QQmlDelegateModel);
- m_compositor.setRemoveGroups(Compositor::GroupMask & ~Compositor::PersistedFlag);
-
- m_items = new QQmlDelegateModelGroup(QStringLiteral("items"), q, Compositor::Default, q);
- m_items->setDefaultInclude(true);
- m_persistedItems = new QQmlDelegateModelGroup(QStringLiteral("persistedItems"), q, Compositor::Persisted, q);
- QQmlDelegateModelGroupPrivate::get(m_items)->emitters.insert(this);
-}
-
-QQmlDelegateModel::QQmlDelegateModel()
- : QQmlDelegateModel(nullptr, nullptr)
-{
-}
-
-QQmlDelegateModel::QQmlDelegateModel(QQmlContext *ctxt, QObject *parent)
-: QQmlInstanceModel(*(new QQmlDelegateModelPrivate(ctxt)), parent)
-{
- Q_D(QQmlDelegateModel);
- d->init();
-}
-
-QQmlDelegateModel::~QQmlDelegateModel()
-{
- Q_D(QQmlDelegateModel);
- d->disconnectFromAbstractItemModel();
- d->m_adaptorModel.setObject(nullptr, this);
-
- for (QQmlDelegateModelItem *cacheItem : qAsConst(d->m_cache)) {
- if (cacheItem->object) {
- delete cacheItem->object;
-
- cacheItem->object = nullptr;
- cacheItem->contextData->invalidate();
- Q_ASSERT(cacheItem->contextData->refCount == 1);
- cacheItem->contextData = nullptr;
- cacheItem->scriptRef -= 1;
- }
- cacheItem->groups &= ~Compositor::UnresolvedFlag;
- cacheItem->objectRef = 0;
- if (!cacheItem->isReferenced())
- delete cacheItem;
- else if (cacheItem->incubationTask)
- cacheItem->incubationTask->vdm = nullptr;
- }
-}
-
-
-void QQmlDelegateModel::classBegin()
-{
- Q_D(QQmlDelegateModel);
- if (!d->m_context)
- d->m_context = qmlContext(this);
-}
-
-void QQmlDelegateModel::componentComplete()
-{
- Q_D(QQmlDelegateModel);
- d->m_complete = true;
-
- int defaultGroups = 0;
- QStringList groupNames;
- groupNames.append(QStringLiteral("items"));
- groupNames.append(QStringLiteral("persistedItems"));
- if (QQmlDelegateModelGroupPrivate::get(d->m_items)->defaultInclude)
- defaultGroups |= Compositor::DefaultFlag;
- if (QQmlDelegateModelGroupPrivate::get(d->m_persistedItems)->defaultInclude)
- defaultGroups |= Compositor::PersistedFlag;
- for (int i = Compositor::MinimumGroupCount; i < d->m_groupCount; ++i) {
- QString name = d->m_groups[i]->name();
- if (name.isEmpty()) {
- d->m_groups[i] = d->m_groups[d->m_groupCount - 1];
- --d->m_groupCount;
- --i;
- } else if (name.at(0).isUpper()) {
- qmlWarning(d->m_groups[i]) << QQmlDelegateModelGroup::tr("Group names must start with a lower case letter");
- d->m_groups[i] = d->m_groups[d->m_groupCount - 1];
- --d->m_groupCount;
- --i;
- } else {
- groupNames.append(name);
-
- QQmlDelegateModelGroupPrivate *group = QQmlDelegateModelGroupPrivate::get(d->m_groups[i]);
- group->setModel(this, Compositor::Group(i));
- if (group->defaultInclude)
- defaultGroups |= (1 << i);
- }
- }
-
- d->m_cacheMetaType = new QQmlDelegateModelItemMetaType(
- d->m_context->engine()->handle(), this, groupNames);
-
- d->m_compositor.setGroupCount(d->m_groupCount);
- d->m_compositor.setDefaultGroups(defaultGroups);
- d->updateFilterGroup();
-
- while (!d->m_pendingParts.isEmpty())
- static_cast<QQmlPartsModel *>(d->m_pendingParts.first())->updateFilterGroup();
-
- QVector<Compositor::Insert> inserts;
- d->m_count = d->adaptorModelCount();
- d->m_compositor.append(
- &d->m_adaptorModel,
- 0,
- d->m_count,
- defaultGroups | Compositor::AppendFlag | Compositor::PrependFlag,
- &inserts);
- d->itemsInserted(inserts);
- d->emitChanges();
- d->requestMoreIfNecessary();
-}
-
-/*!
- \qmlproperty model QtQml.Models::DelegateModel::model
- This property holds the model providing data for the DelegateModel.
-
- The model provides a set of data that is used to create the items
- for a view. For large or dynamic datasets the model is usually
- provided by a C++ model object. The C++ model object must be a \l
- {QAbstractItemModel} subclass or a simple list.
-
- Models can also be created directly in QML, using a \l{ListModel} or
- \l{QtQuick.XmlListModel::XmlListModel}{XmlListModel}.
-
- \sa {qml-data-models}{Data Models}
- \keyword dm-model-property
-*/
-QVariant QQmlDelegateModel::model() const
-{
- Q_D(const QQmlDelegateModel);
- return d->m_adaptorModel.model();
-}
-
-void QQmlDelegateModelPrivate::connectToAbstractItemModel()
-{
- Q_Q(QQmlDelegateModel);
- if (!m_adaptorModel.adaptsAim())
- return;
-
- auto aim = m_adaptorModel.aim();
-
- qmlobject_connect(aim, QAbstractItemModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
- q, QQmlDelegateModel, SLOT(_q_rowsInserted(QModelIndex,int,int)));
- qmlobject_connect(aim, QAbstractItemModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
- 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(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)),
- q, QQmlDelegateModel, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
- qmlobject_connect(aim, QAbstractItemModel, SIGNAL(modelReset()),
- q, QQmlDelegateModel, SLOT(_q_modelReset()));
- qmlobject_connect(aim, QAbstractItemModel, SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
- q, QQmlDelegateModel, SLOT(_q_layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
-}
-
-void QQmlDelegateModelPrivate::disconnectFromAbstractItemModel()
-{
- Q_Q(QQmlDelegateModel);
- if (!m_adaptorModel.adaptsAim())
- return;
-
- auto aim = m_adaptorModel.aim();
-
- QObject::disconnect(aim, SIGNAL(rowsInserted(QModelIndex,int,int)),
- q, SLOT(_q_rowsInserted(QModelIndex,int,int)));
- QObject::disconnect(aim, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
- 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(dataChanged(QModelIndex,QModelIndex,QVector<int>)),
- q, SLOT(_q_dataChanged(QModelIndex,QModelIndex,QVector<int>)));
- QObject::disconnect(aim, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
- q, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
- QObject::disconnect(aim, SIGNAL(modelReset()),
- q, SLOT(_q_modelReset()));
- QObject::disconnect(aim, SIGNAL(layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)),
- q, SLOT(_q_layoutChanged(QList<QPersistentModelIndex>,QAbstractItemModel::LayoutChangeHint)));
-}
-
-void QQmlDelegateModel::setModel(const QVariant &model)
-{
- Q_D(QQmlDelegateModel);
-
- if (d->m_complete)
- _q_itemsRemoved(0, d->m_count);
-
- d->disconnectFromAbstractItemModel();
- d->m_adaptorModel.setModel(model, this, d->m_context->engine());
- d->connectToAbstractItemModel();
-
- d->m_adaptorModel.replaceWatchedRoles(QList<QByteArray>(), d->m_watchedRoles);
- for (int i = 0; d->m_parts && i < d->m_parts->models.count(); ++i) {
- d->m_adaptorModel.replaceWatchedRoles(
- QList<QByteArray>(), d->m_parts->models.at(i)->watchedRoles());
- }
-
- if (d->m_complete) {
- _q_itemsInserted(0, d->adaptorModelCount());
- d->requestMoreIfNecessary();
- }
-}
-
-/*!
- \qmlproperty Component QtQml.Models::DelegateModel::delegate
-
- The delegate provides a template defining each item instantiated by a view.
- The index is exposed as an accessible \c index property. Properties of the
- model are also available depending upon the type of \l {qml-data-models}{Data Model}.
-*/
-QQmlComponent *QQmlDelegateModel::delegate() const
-{
- Q_D(const QQmlDelegateModel);
- return d->m_delegate;
-}
-
-void QQmlDelegateModel::setDelegate(QQmlComponent *delegate)
-{
- Q_D(QQmlDelegateModel);
- if (d->m_transaction) {
- qmlWarning(this) << tr("The delegate of a DelegateModel cannot be changed within onUpdated.");
- return;
- }
- if (d->m_delegate == delegate)
- return;
- bool wasValid = d->m_delegate != nullptr;
- d->m_delegate.setObject(delegate, this);
- d->m_delegateValidated = false;
- if (d->m_delegateChooser)
- QObject::disconnect(d->m_delegateChooserChanged);
-
- d->m_delegateChooser = nullptr;
- if (delegate) {
- QQmlAbstractDelegateComponent *adc =
- qobject_cast<QQmlAbstractDelegateComponent *>(delegate);
- if (adc) {
- d->m_delegateChooser = adc;
- d->m_delegateChooserChanged = connect(adc, &QQmlAbstractDelegateComponent::delegateChanged,
- [d](){ d->delegateChanged(); });
- }
- }
- d->delegateChanged(d->m_delegate, wasValid);
-}
-
-/*!
- \qmlproperty QModelIndex QtQml.Models::DelegateModel::rootIndex
-
- QAbstractItemModel provides a hierarchical tree of data, whereas
- QML only operates on list data. \c rootIndex allows the children of
- any node in a QAbstractItemModel to be provided by this model.
-
- This property only affects models of type QAbstractItemModel that
- are hierarchical (e.g, a tree model).
-
- For example, here is a simple interactive file system browser.
- When a directory name is clicked, the view's \c rootIndex is set to the
- QModelIndex node of the clicked directory, thus updating the view to show
- the new directory's contents.
-
- \c main.cpp:
- \snippet delegatemodel/delegatemodel_rootindex/main.cpp 0
-
- \c view.qml:
- \snippet delegatemodel/delegatemodel_rootindex/view.qml 0
-
- If the \l {dm-model-property}{model} is a QAbstractItemModel subclass,
- the delegate can also reference a \c hasModelChildren property (optionally
- qualified by a \e model. prefix) that indicates whether the delegate's
- model item has any child nodes.
-
- \sa modelIndex(), parentModelIndex()
-*/
-QVariant QQmlDelegateModel::rootIndex() const
-{
- Q_D(const QQmlDelegateModel);
- return QVariant::fromValue(QModelIndex(d->m_adaptorModel.rootIndex));
-}
-
-void QQmlDelegateModel::setRootIndex(const QVariant &root)
-{
- Q_D(QQmlDelegateModel);
-
- QModelIndex modelIndex = qvariant_cast<QModelIndex>(root);
- const bool changed = d->m_adaptorModel.rootIndex != modelIndex;
- if (changed || !d->m_adaptorModel.isValid()) {
- const int oldCount = d->m_count;
- d->m_adaptorModel.rootIndex = modelIndex;
- if (!d->m_adaptorModel.isValid() && d->m_adaptorModel.aim()) {
- // The previous root index was invalidated, so we need to reconnect the model.
- d->disconnectFromAbstractItemModel();
- d->m_adaptorModel.setModel(d->m_adaptorModel.list.list(), this, d->m_context->engine());
- d->connectToAbstractItemModel();
- }
- if (d->m_adaptorModel.canFetchMore())
- d->m_adaptorModel.fetchMore();
- if (d->m_complete) {
- const int newCount = d->adaptorModelCount();
- if (oldCount)
- _q_itemsRemoved(0, oldCount);
- if (newCount)
- _q_itemsInserted(0, newCount);
- }
- if (changed)
- emit rootIndexChanged();
- }
-}
-
-/*!
- \qmlmethod QModelIndex QtQml.Models::DelegateModel::modelIndex(int index)
-
- QAbstractItemModel provides a hierarchical tree of data, whereas
- QML only operates on list data. This function assists in using
- tree models in QML.
-
- Returns a QModelIndex for the specified index.
- This value can be assigned to rootIndex.
-
- \sa rootIndex
-*/
-QVariant QQmlDelegateModel::modelIndex(int idx) const
-{
- Q_D(const QQmlDelegateModel);
- return d->m_adaptorModel.modelIndex(idx);
-}
-
-/*!
- \qmlmethod QModelIndex QtQml.Models::DelegateModel::parentModelIndex()
-
- QAbstractItemModel provides a hierarchical tree of data, whereas
- QML only operates on list data. This function assists in using
- tree models in QML.
-
- Returns a QModelIndex for the parent of the current rootIndex.
- This value can be assigned to rootIndex.
-
- \sa rootIndex
-*/
-QVariant QQmlDelegateModel::parentModelIndex() const
-{
- Q_D(const QQmlDelegateModel);
- return d->m_adaptorModel.parentModelIndex();
-}
-
-/*!
- \qmlproperty int QtQml.Models::DelegateModel::count
-*/
-
-int QQmlDelegateModel::count() const
-{
- Q_D(const QQmlDelegateModel);
- if (!d->m_delegate)
- return 0;
- return d->m_compositor.count(d->m_compositorGroup);
-}
-
-QQmlDelegateModel::ReleaseFlags QQmlDelegateModelPrivate::release(QObject *object)
-{
- if (!object)
- return QQmlDelegateModel::ReleaseFlags(0);
-
- QQmlDelegateModelItem *cacheItem = QQmlDelegateModelItem::dataForObject(object);
- if (!cacheItem)
- return QQmlDelegateModel::ReleaseFlags(0);
-
- if (!cacheItem->releaseObject())
- return QQmlDelegateModel::Referenced;
-
- cacheItem->destroyObject();
- emitDestroyingItem(object);
- if (cacheItem->incubationTask) {
- releaseIncubator(cacheItem->incubationTask);
- cacheItem->incubationTask = nullptr;
- }
- cacheItem->Dispose();
- return QQmlInstanceModel::Destroyed;
-}
-
-/*
- Returns ReleaseStatus flags.
-*/
-
-QQmlDelegateModel::ReleaseFlags QQmlDelegateModel::release(QObject *item)
-{
- Q_D(QQmlDelegateModel);
- QQmlInstanceModel::ReleaseFlags stat = d->release(item);
- return stat;
-}
-
-// Cancel a requested async item
-void QQmlDelegateModel::cancel(int index)
-{
- Q_D(QQmlDelegateModel);
- if (!d->m_delegate || index < 0 || index >= d->m_compositor.count(d->m_compositorGroup)) {
- qWarning() << "DelegateModel::cancel: index out range" << index << d->m_compositor.count(d->m_compositorGroup);
- return;
- }
-
- Compositor::iterator it = d->m_compositor.find(d->m_compositorGroup, index);
- QQmlDelegateModelItem *cacheItem = it->inCache() ? d->m_cache.at(it.cacheIndex) : 0;
- if (cacheItem) {
- if (cacheItem->incubationTask && !cacheItem->isObjectReferenced()) {
- d->releaseIncubator(cacheItem->incubationTask);
- cacheItem->incubationTask = nullptr;
-
- if (cacheItem->object) {
- QObject *object = cacheItem->object;
- cacheItem->destroyObject();
- if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object))
- d->emitDestroyingPackage(package);
- else
- d->emitDestroyingItem(object);
- }
-
- cacheItem->scriptRef -= 1;
- }
- if (!cacheItem->isReferenced()) {
- d->m_compositor.clearFlags(Compositor::Cache, it.cacheIndex, 1, Compositor::CacheFlag);
- d->m_cache.removeAt(it.cacheIndex);
- delete cacheItem;
- Q_ASSERT(d->m_cache.count() == d->m_compositor.count(Compositor::Cache));
- }
- }
-}
-
-void QQmlDelegateModelPrivate::group_append(
- QQmlListProperty<QQmlDelegateModelGroup> *property, QQmlDelegateModelGroup *group)
-{
- QQmlDelegateModelPrivate *d = static_cast<QQmlDelegateModelPrivate *>(property->data);
- if (d->m_complete)
- return;
- if (d->m_groupCount == Compositor::MaximumGroupCount) {
- qmlWarning(d->q_func()) << QQmlDelegateModel::tr("The maximum number of supported DelegateModelGroups is 8");
- return;
- }
- d->m_groups[d->m_groupCount] = group;
- d->m_groupCount += 1;
-}
-
-int QQmlDelegateModelPrivate::group_count(
- QQmlListProperty<QQmlDelegateModelGroup> *property)
-{
- QQmlDelegateModelPrivate *d = static_cast<QQmlDelegateModelPrivate *>(property->data);
- return d->m_groupCount - 1;
-}
-
-QQmlDelegateModelGroup *QQmlDelegateModelPrivate::group_at(
- QQmlListProperty<QQmlDelegateModelGroup> *property, int index)
-{
- QQmlDelegateModelPrivate *d = static_cast<QQmlDelegateModelPrivate *>(property->data);
- return index >= 0 && index < d->m_groupCount - 1
- ? d->m_groups[index + 1]
- : nullptr;
-}
-
-/*!
- \qmlproperty list<DelegateModelGroup> QtQml.Models::DelegateModel::groups
-
- This property holds a delegate model's group definitions.
-
- Groups define a sub-set of the items in a delegate model and can be used to filter
- a model.
-
- For every group defined in a DelegateModel two attached properties are added to each
- delegate item. The first of the form DelegateModel.in\e{GroupName} holds whether the
- item belongs to the group and the second DelegateModel.\e{groupName}Index holds the
- index of the item in that group.
-
- The following example illustrates using groups to select items in a model.
-
- \snippet delegatemodel/delegatemodelgroup.qml 0
- \keyword dm-groups-property
-*/
-
-QQmlListProperty<QQmlDelegateModelGroup> QQmlDelegateModel::groups()
-{
- Q_D(QQmlDelegateModel);
- return QQmlListProperty<QQmlDelegateModelGroup>(
- this,
- d,
- QQmlDelegateModelPrivate::group_append,
- QQmlDelegateModelPrivate::group_count,
- QQmlDelegateModelPrivate::group_at,
- nullptr);
-}
-
-/*!
- \qmlproperty DelegateModelGroup QtQml.Models::DelegateModel::items
-
- This property holds default group to which all new items are added.
-*/
-
-QQmlDelegateModelGroup *QQmlDelegateModel::items()
-{
- Q_D(QQmlDelegateModel);
- return d->m_items;
-}
-
-/*!
- \qmlproperty DelegateModelGroup QtQml.Models::DelegateModel::persistedItems
-
- This property holds delegate model's persisted items group.
-
- Items in this group are not destroyed when released by a view, instead they are persisted
- until removed from the group.
-
- An item can be removed from the persistedItems group by setting the
- DelegateModel.inPersistedItems property to false. If the item is not referenced by a view
- at that time it will be destroyed. Adding an item to this group will not create a new
- instance.
-
- Items returned by the \l QtQml.Models::DelegateModelGroup::create() function are automatically added
- to this group.
-*/
-
-QQmlDelegateModelGroup *QQmlDelegateModel::persistedItems()
-{
- Q_D(QQmlDelegateModel);
- return d->m_persistedItems;
-}
-
-/*!
- \qmlproperty string QtQml.Models::DelegateModel::filterOnGroup
-
- This property holds name of the group that is used to filter the delegate model.
-
- Only items that belong to this group are visible to a view.
-
- By default this is the \l items group.
-*/
-
-QString QQmlDelegateModel::filterGroup() const
-{
- Q_D(const QQmlDelegateModel);
- return d->m_filterGroup;
-}
-
-void QQmlDelegateModel::setFilterGroup(const QString &group)
-{
- Q_D(QQmlDelegateModel);
-
- if (d->m_transaction) {
- qmlWarning(this) << tr("The group of a DelegateModel cannot be changed within onChanged");
- return;
- }
-
- if (d->m_filterGroup != group) {
- d->m_filterGroup = group;
- d->updateFilterGroup();
- emit filterGroupChanged();
- }
-}
-
-void QQmlDelegateModel::resetFilterGroup()
-{
- setFilterGroup(QStringLiteral("items"));
-}
-
-void QQmlDelegateModelPrivate::updateFilterGroup()
-{
- Q_Q(QQmlDelegateModel);
- if (!m_cacheMetaType)
- return;
-
- QQmlListCompositor::Group previousGroup = m_compositorGroup;
- m_compositorGroup = Compositor::Default;
- for (int i = 1; i < m_groupCount; ++i) {
- if (m_filterGroup == m_cacheMetaType->groupNames.at(i - 1)) {
- m_compositorGroup = Compositor::Group(i);
- break;
- }
- }
-
- QQmlDelegateModelGroupPrivate::get(m_groups[m_compositorGroup])->emitters.insert(this);
- if (m_compositorGroup != previousGroup) {
- QVector<QQmlChangeSet::Change> removes;
- QVector<QQmlChangeSet::Change> inserts;
- m_compositor.transition(previousGroup, m_compositorGroup, &removes, &inserts);
-
- QQmlChangeSet changeSet;
- changeSet.move(removes, inserts);
- emit q->modelUpdated(changeSet, false);
-
- if (changeSet.difference() != 0)
- emit q->countChanged();
-
- if (m_parts) {
- auto partsCopy = m_parts->models; // deliberate; this may alter m_parts
- for (QQmlPartsModel *model : qAsConst(partsCopy))
- model->updateFilterGroup(m_compositorGroup, changeSet);
- }
- }
-}
-
-/*!
- \qmlproperty object QtQml.Models::DelegateModel::parts
-
- The \a parts property selects a DelegateModel which creates
- delegates from the part named. This is used in conjunction with
- the \l Package type.
-
- For example, the code below selects a model which creates
- delegates named \e list from a \l Package:
-
- \code
- DelegateModel {
- id: visualModel
- delegate: Package {
- Item { Package.name: "list" }
- }
- model: myModel
- }
-
- ListView {
- width: 200; height:200
- model: visualModel.parts.list
- }
- \endcode
-
- \sa Package
-*/
-
-QObject *QQmlDelegateModel::parts()
-{
- Q_D(QQmlDelegateModel);
- if (!d->m_parts)
- d->m_parts = new QQmlDelegateModelParts(this);
- return d->m_parts;
-}
-
-const QAbstractItemModel *QQmlDelegateModel::abstractItemModel() const
-{
- Q_D(const QQmlDelegateModel);
- return d->m_adaptorModel.adaptsAim() ? d->m_adaptorModel.aim() : nullptr;
-}
-
-void QQmlDelegateModelPrivate::emitCreatedPackage(QQDMIncubationTask *incubationTask, QQuickPackage *package)
-{
- for (int i = 1; i < m_groupCount; ++i)
- QQmlDelegateModelGroupPrivate::get(m_groups[i])->createdPackage(incubationTask->index[i], package);
-}
-
-void QQmlDelegateModelPrivate::emitInitPackage(QQDMIncubationTask *incubationTask, QQuickPackage *package)
-{
- for (int i = 1; i < m_groupCount; ++i)
- QQmlDelegateModelGroupPrivate::get(m_groups[i])->initPackage(incubationTask->index[i], package);
-}
-
-void QQmlDelegateModelPrivate::emitDestroyingPackage(QQuickPackage *package)
-{
- for (int i = 1; i < m_groupCount; ++i)
- QQmlDelegateModelGroupPrivate::get(m_groups[i])->destroyingPackage(package);
-}
-
-static bool isDoneIncubating(QQmlIncubator::Status status)
-{
- return status == QQmlIncubator::Ready || status == QQmlIncubator::Error;
-}
-
-void QQDMIncubationTask::statusChanged(Status status)
-{
- if (vdm) {
- vdm->incubatorStatusChanged(this, status);
- } else if (isDoneIncubating(status)) {
- Q_ASSERT(incubating);
- // The model was deleted from under our feet, cleanup ourselves
- delete incubating->object;
- incubating->object = nullptr;
- if (incubating->contextData) {
- incubating->contextData->invalidate();
- Q_ASSERT(incubating->contextData->refCount == 1);
- incubating->contextData = nullptr;
- }
- incubating->scriptRef = 0;
- incubating->deleteLater();
- }
-}
-
-void QQmlDelegateModelPrivate::releaseIncubator(QQDMIncubationTask *incubationTask)
-{
- Q_Q(QQmlDelegateModel);
- if (!incubationTask->isError())
- incubationTask->clear();
- m_finishedIncubating.append(incubationTask);
- if (!m_incubatorCleanupScheduled) {
- m_incubatorCleanupScheduled = true;
- QCoreApplication::postEvent(q, new QEvent(QEvent::User));
- }
-}
-
-void QQmlDelegateModelPrivate::addCacheItem(QQmlDelegateModelItem *item, Compositor::iterator it)
-{
- m_cache.insert(it.cacheIndex, item);
- m_compositor.setFlags(it, 1, Compositor::CacheFlag);
- Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache));
-}
-
-void QQmlDelegateModelPrivate::removeCacheItem(QQmlDelegateModelItem *cacheItem)
-{
- int cidx = m_cache.lastIndexOf(cacheItem);
- if (cidx >= 0) {
- m_compositor.clearFlags(Compositor::Cache, cidx, 1, Compositor::CacheFlag);
- m_cache.removeAt(cidx);
- }
- Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache));
-}
-
-void QQmlDelegateModelPrivate::incubatorStatusChanged(QQDMIncubationTask *incubationTask, QQmlIncubator::Status status)
-{
- if (!isDoneIncubating(status))
- return;
-
- const QList<QQmlError> incubationTaskErrors = incubationTask->errors();
-
- QQmlDelegateModelItem *cacheItem = incubationTask->incubating;
- cacheItem->incubationTask = nullptr;
- incubationTask->incubating = nullptr;
- releaseIncubator(incubationTask);
-
- if (status == QQmlIncubator::Ready) {
- cacheItem->referenceObject();
- if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(cacheItem->object))
- emitCreatedPackage(incubationTask, package);
- else
- emitCreatedItem(incubationTask, cacheItem->object);
- cacheItem->releaseObject();
- } else if (status == QQmlIncubator::Error) {
- qmlInfo(m_delegate, incubationTaskErrors + m_delegate->errors()) << "Cannot create delegate";
- }
-
- if (!cacheItem->isObjectReferenced()) {
- if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(cacheItem->object))
- emitDestroyingPackage(package);
- else
- emitDestroyingItem(cacheItem->object);
- delete cacheItem->object;
- cacheItem->object = nullptr;
- cacheItem->scriptRef -= 1;
- if (cacheItem->contextData) {
- cacheItem->contextData->invalidate();
- Q_ASSERT(cacheItem->contextData->refCount == 1);
- }
- cacheItem->contextData = nullptr;
-
- if (!cacheItem->isReferenced()) {
- removeCacheItem(cacheItem);
- delete cacheItem;
- }
- }
-}
-
-void QQDMIncubationTask::setInitialState(QObject *o)
-{
- vdm->setInitialState(this, o);
-}
-
-void QQmlDelegateModelPrivate::setInitialState(QQDMIncubationTask *incubationTask, QObject *o)
-{
- QQmlDelegateModelItem *cacheItem = incubationTask->incubating;
- cacheItem->object = o;
-
- if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(cacheItem->object))
- emitInitPackage(incubationTask, package);
- else
- emitInitItem(incubationTask, cacheItem->object);
-}
-
-QObject *QQmlDelegateModelPrivate::object(Compositor::Group group, int index, QQmlIncubator::IncubationMode incubationMode)
-{
- if (!m_delegate || index < 0 || index >= m_compositor.count(group)) {
- qWarning() << "DelegateModel::item: index out range" << index << m_compositor.count(group);
- return nullptr;
- } else if (!m_context || !m_context->isValid()) {
- return nullptr;
- }
-
- Compositor::iterator it = m_compositor.find(group, index);
-
- QQmlDelegateModelItem *cacheItem = it->inCache() ? m_cache.at(it.cacheIndex) : 0;
-
- if (!cacheItem) {
- cacheItem = m_adaptorModel.createItem(m_cacheMetaType, it.modelIndex());
- if (!cacheItem)
- return nullptr;
-
- cacheItem->groups = it->flags;
- addCacheItem(cacheItem, it);
- }
-
- // Bump the reference counts temporarily so neither the content data or the delegate object
- // are deleted if incubatorStatusChanged() is called synchronously.
- cacheItem->scriptRef += 1;
- cacheItem->referenceObject();
-
- if (cacheItem->incubationTask) {
- bool sync = (incubationMode == QQmlIncubator::Synchronous || incubationMode == QQmlIncubator::AsynchronousIfNested);
- if (sync && cacheItem->incubationTask->incubationMode() == QQmlIncubator::Asynchronous) {
- // previously requested async - now needed immediately
- cacheItem->incubationTask->forceCompletion();
- }
- } else if (!cacheItem->object) {
- QQmlComponent *delegate = m_delegate;
- if (m_delegateChooser) {
- QQmlAbstractDelegateComponent *chooser = m_delegateChooser;
- do {
- delegate = chooser->delegate(&m_adaptorModel, index);
- chooser = qobject_cast<QQmlAbstractDelegateComponent *>(delegate);
- } while (chooser);
- if (!delegate)
- return nullptr;
- }
-
- QQmlContext *creationContext = delegate->creationContext();
-
- cacheItem->scriptRef += 1;
-
- cacheItem->incubationTask = new QQDMIncubationTask(this, incubationMode);
- cacheItem->incubationTask->incubating = cacheItem;
- cacheItem->incubationTask->clear();
-
- for (int i = 1; i < m_groupCount; ++i)
- cacheItem->incubationTask->index[i] = it.index[i];
-
- QQmlContextData *ctxt = new QQmlContextData;
- ctxt->setParent(QQmlContextData::get(creationContext ? creationContext : m_context.data()));
- ctxt->contextObject = cacheItem;
- cacheItem->contextData = ctxt;
-
- if (m_adaptorModel.hasProxyObject()) {
- if (QQmlAdaptorModelProxyInterface *proxy
- = qobject_cast<QQmlAdaptorModelProxyInterface *>(cacheItem)) {
- ctxt = new QQmlContextData;
- ctxt->setParent(cacheItem->contextData, /*stronglyReferencedByParent*/true);
- QObject *proxied = proxy->proxiedObject();
- ctxt->contextObject = proxied;
- // We don't own the proxied object. We need to clear it if it goes away.
- QObject::connect(proxied, &QObject::destroyed,
- cacheItem, &QQmlDelegateModelItem::childContextObjectDestroyed);
- }
- }
-
- QQmlComponentPrivate *cp = QQmlComponentPrivate::get(delegate);
- cp->incubateObject(
- cacheItem->incubationTask,
- delegate,
- m_context->engine(),
- ctxt,
- QQmlContextData::get(m_context));
- }
-
- if (index == m_compositor.count(group) - 1)
- requestMoreIfNecessary();
-
- // Remove the temporary reference count.
- cacheItem->scriptRef -= 1;
- if (cacheItem->object && (!cacheItem->incubationTask || isDoneIncubating(cacheItem->incubationTask->status())))
- return cacheItem->object;
-
- cacheItem->releaseObject();
- if (!cacheItem->isReferenced()) {
- removeCacheItem(cacheItem);
- delete cacheItem;
- }
-
- return nullptr;
-}
-
-/*
- If asynchronous is true or the component is being loaded asynchronously due
- to an ancestor being loaded asynchronously, object() may return 0. In this
- case createdItem() will be emitted when the object is available. The object
- at this stage does not have any references, so object() must be called again
- to ensure a reference is held. Any call to object() which returns a valid object
- must be matched by a call to release() in order to destroy the object.
-*/
-QObject *QQmlDelegateModel::object(int index, QQmlIncubator::IncubationMode incubationMode)
-{
- Q_D(QQmlDelegateModel);
- if (!d->m_delegate || index < 0 || index >= d->m_compositor.count(d->m_compositorGroup)) {
- qWarning() << "DelegateModel::item: index out range" << index << d->m_compositor.count(d->m_compositorGroup);
- return nullptr;
- }
-
- return d->object(d->m_compositorGroup, index, incubationMode);
-}
-
-QQmlIncubator::Status QQmlDelegateModel::incubationStatus(int index)
-{
- Q_D(QQmlDelegateModel);
- Compositor::iterator it = d->m_compositor.find(d->m_compositorGroup, index);
- if (!it->inCache())
- return QQmlIncubator::Null;
-
- if (auto incubationTask = d->m_cache.at(it.cacheIndex)->incubationTask)
- return incubationTask->status();
-
- return QQmlIncubator::Ready;
-}
-
-QVariant QQmlDelegateModelPrivate::variantValue(QQmlListCompositor::Group group, int index, const QString &name)
-{
- Compositor::iterator it = m_compositor.find(group, index);
- if (QQmlAdaptorModel *model = it.list<QQmlAdaptorModel>()) {
- QString role = name;
- int dot = name.indexOf(QLatin1Char('.'));
- if (dot > 0)
- role = name.left(dot);
- QVariant value = model->value(it.modelIndex(), role);
- while (dot > 0) {
- QObject *obj = qvariant_cast<QObject*>(value);
- if (!obj)
- return QVariant();
- const int from = dot + 1;
- dot = name.indexOf(QLatin1Char('.'), from);
- value = obj->property(name.midRef(from, dot - from).toUtf8());
- }
- return value;
- }
- return QVariant();
-}
-
-QVariant QQmlDelegateModel::variantValue(int index, const QString &role)
-{
- Q_D(QQmlDelegateModel);
- return d->variantValue(d->m_compositorGroup, index, role);
-}
-
-int QQmlDelegateModel::indexOf(QObject *item, QObject *) const
-{
- Q_D(const QQmlDelegateModel);
- if (QQmlDelegateModelItem *cacheItem = QQmlDelegateModelItem::dataForObject(item))
- return cacheItem->groupIndex(d->m_compositorGroup);
- return -1;
-}
-
-void QQmlDelegateModel::setWatchedRoles(const QList<QByteArray> &roles)
-{
- Q_D(QQmlDelegateModel);
- d->m_adaptorModel.replaceWatchedRoles(d->m_watchedRoles, roles);
- d->m_watchedRoles = roles;
-}
-
-void QQmlDelegateModelPrivate::addGroups(
- Compositor::iterator from, int count, Compositor::Group group, int groupFlags)
-{
- QVector<Compositor::Insert> inserts;
- m_compositor.setFlags(from, count, group, groupFlags, &inserts);
- itemsInserted(inserts);
- emitChanges();
-}
-
-void QQmlDelegateModelPrivate::removeGroups(
- Compositor::iterator from, int count, Compositor::Group group, int groupFlags)
-{
- QVector<Compositor::Remove> removes;
- m_compositor.clearFlags(from, count, group, groupFlags, &removes);
- itemsRemoved(removes);
- emitChanges();
-}
-
-void QQmlDelegateModelPrivate::setGroups(
- Compositor::iterator from, int count, Compositor::Group group, int groupFlags)
-{
- QVector<Compositor::Remove> removes;
- QVector<Compositor::Insert> inserts;
-
- m_compositor.setFlags(from, count, group, groupFlags, &inserts);
- itemsInserted(inserts);
- const int removeFlags = ~groupFlags & Compositor::GroupMask;
-
- from = m_compositor.find(from.group, from.index[from.group]);
- m_compositor.clearFlags(from, count, group, removeFlags, &removes);
- itemsRemoved(removes);
- emitChanges();
-}
-
-bool QQmlDelegateModel::event(QEvent *e)
-{
- Q_D(QQmlDelegateModel);
- if (e->type() == QEvent::UpdateRequest) {
- d->m_waitingToFetchMore = false;
- d->m_adaptorModel.fetchMore();
- } else if (e->type() == QEvent::User) {
- d->m_incubatorCleanupScheduled = false;
- qDeleteAll(d->m_finishedIncubating);
- d->m_finishedIncubating.clear();
- }
- return QQmlInstanceModel::event(e);
-}
-
-void QQmlDelegateModelPrivate::itemsChanged(const QVector<Compositor::Change> &changes)
-{
- if (!m_delegate)
- return;
-
- QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> translatedChanges(m_groupCount);
-
- for (const Compositor::Change &change : changes) {
- for (int i = 1; i < m_groupCount; ++i) {
- if (change.inGroup(i)) {
- translatedChanges[i].append(QQmlChangeSet::Change(change.index[i], change.count));
- }
- }
- }
-
- for (int i = 1; i < m_groupCount; ++i)
- QQmlDelegateModelGroupPrivate::get(m_groups[i])->changeSet.change(translatedChanges.at(i));
-}
-
-void QQmlDelegateModel::_q_itemsChanged(int index, int count, const QVector<int> &roles)
-{
- Q_D(QQmlDelegateModel);
- if (count <= 0 || !d->m_complete)
- return;
-
- if (d->m_adaptorModel.notify(d->m_cache, index, count, roles)) {
- QVector<Compositor::Change> changes;
- d->m_compositor.listItemsChanged(&d->m_adaptorModel, index, count, &changes);
- d->itemsChanged(changes);
- d->emitChanges();
- }
-}
-
-static void incrementIndexes(QQmlDelegateModelItem *cacheItem, int count, const int *deltas)
-{
- if (QQDMIncubationTask *incubationTask = cacheItem->incubationTask) {
- for (int i = 1; i < count; ++i)
- incubationTask->index[i] += deltas[i];
- }
- if (QQmlDelegateModelAttached *attached = cacheItem->attached) {
- for (int i = 1; i < qMin<int>(count, Compositor::MaximumGroupCount); ++i)
- attached->m_currentIndex[i] += deltas[i];
- }
-}
-
-void QQmlDelegateModelPrivate::itemsInserted(
- const QVector<Compositor::Insert> &inserts,
- QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> *translatedInserts,
- QHash<int, QList<QQmlDelegateModelItem *> > *movedItems)
-{
- int cacheIndex = 0;
-
- int inserted[Compositor::MaximumGroupCount];
- for (int i = 1; i < m_groupCount; ++i)
- inserted[i] = 0;
-
- for (const Compositor::Insert &insert : inserts) {
- for (; cacheIndex < insert.cacheIndex; ++cacheIndex)
- incrementIndexes(m_cache.at(cacheIndex), m_groupCount, inserted);
-
- for (int i = 1; i < m_groupCount; ++i) {
- if (insert.inGroup(i)) {
- (*translatedInserts)[i].append(
- QQmlChangeSet::Change(insert.index[i], insert.count, insert.moveId));
- inserted[i] += insert.count;
- }
- }
-
- if (!insert.inCache())
- continue;
-
- if (movedItems && insert.isMove()) {
- QList<QQmlDelegateModelItem *> items = movedItems->take(insert.moveId);
- Q_ASSERT(items.count() == insert.count);
- m_cache = m_cache.mid(0, insert.cacheIndex) + items + m_cache.mid(insert.cacheIndex);
- }
- if (insert.inGroup()) {
- for (int offset = 0; cacheIndex < insert.cacheIndex + insert.count; ++cacheIndex, ++offset) {
- QQmlDelegateModelItem *cacheItem = m_cache.at(cacheIndex);
- cacheItem->groups |= insert.flags & Compositor::GroupMask;
-
- if (QQDMIncubationTask *incubationTask = cacheItem->incubationTask) {
- for (int i = 1; i < m_groupCount; ++i)
- incubationTask->index[i] = cacheItem->groups & (1 << i)
- ? insert.index[i] + offset
- : insert.index[i];
- }
- if (QQmlDelegateModelAttached *attached = cacheItem->attached) {
- for (int i = 1; i < m_groupCount; ++i)
- attached->m_currentIndex[i] = cacheItem->groups & (1 << i)
- ? insert.index[i] + offset
- : insert.index[i];
- }
- }
- } else {
- cacheIndex = insert.cacheIndex + insert.count;
- }
- }
- for (const QList<QQmlDelegateModelItem *> cache = m_cache; cacheIndex < cache.count(); ++cacheIndex)
- incrementIndexes(cache.at(cacheIndex), m_groupCount, inserted);
-}
-
-void QQmlDelegateModelPrivate::itemsInserted(const QVector<Compositor::Insert> &inserts)
-{
- QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> translatedInserts(m_groupCount);
- itemsInserted(inserts, &translatedInserts);
- Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache));
- if (!m_delegate)
- return;
-
- for (int i = 1; i < m_groupCount; ++i)
- QQmlDelegateModelGroupPrivate::get(m_groups[i])->changeSet.insert(translatedInserts.at(i));
-}
-
-void QQmlDelegateModel::_q_itemsInserted(int index, int count)
-{
-
- Q_D(QQmlDelegateModel);
- if (count <= 0 || !d->m_complete)
- return;
-
- d->m_count += count;
-
- const QList<QQmlDelegateModelItem *> cache = d->m_cache;
- for (int i = 0, c = cache.count(); i < c; ++i) {
- QQmlDelegateModelItem *item = cache.at(i);
- if (item->modelIndex() >= index) {
- const int newIndex = item->modelIndex() + count;
- const int row = newIndex;
- const int column = 0;
- item->setModelIndex(newIndex, row, column);
- }
- }
-
- QVector<Compositor::Insert> inserts;
- d->m_compositor.listItemsInserted(&d->m_adaptorModel, index, count, &inserts);
- d->itemsInserted(inserts);
- d->emitChanges();
-}
-
-//### This method should be split in two. It will remove delegates, and it will re-render the list.
-// When e.g. QQmlListModel::remove is called, the removal of the delegates should be done on
-// QAbstractItemModel::rowsAboutToBeRemoved, and the re-rendering on
-// QAbstractItemModel::rowsRemoved. Currently both are done on the latter signal. The problem is
-// that the destruction of an item will emit a changed signal that ends up at the delegate, which
-// in turn will try to load the data from the model (which should have already freed it), resulting
-// in a use-after-free. See QTBUG-59256.
-void QQmlDelegateModelPrivate::itemsRemoved(
- const QVector<Compositor::Remove> &removes,
- QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> *translatedRemoves,
- QHash<int, QList<QQmlDelegateModelItem *> > *movedItems)
-{
- int cacheIndex = 0;
- int removedCache = 0;
-
- int removed[Compositor::MaximumGroupCount];
- for (int i = 1; i < m_groupCount; ++i)
- removed[i] = 0;
-
- for (const Compositor::Remove &remove : removes) {
- for (; cacheIndex < remove.cacheIndex; ++cacheIndex)
- incrementIndexes(m_cache.at(cacheIndex), m_groupCount, removed);
-
- for (int i = 1; i < m_groupCount; ++i) {
- if (remove.inGroup(i)) {
- (*translatedRemoves)[i].append(
- QQmlChangeSet::Change(remove.index[i], remove.count, remove.moveId));
- removed[i] -= remove.count;
- }
- }
-
- if (!remove.inCache())
- continue;
-
- if (movedItems && remove.isMove()) {
- movedItems->insert(remove.moveId, m_cache.mid(remove.cacheIndex, remove.count));
- QList<QQmlDelegateModelItem *>::iterator begin = m_cache.begin() + remove.cacheIndex;
- QList<QQmlDelegateModelItem *>::iterator end = begin + remove.count;
- m_cache.erase(begin, end);
- } else {
- for (; cacheIndex < remove.cacheIndex + remove.count - removedCache; ++cacheIndex) {
- QQmlDelegateModelItem *cacheItem = m_cache.at(cacheIndex);
- if (remove.inGroup(Compositor::Persisted) && cacheItem->objectRef == 0 && cacheItem->object) {
- QObject *object = cacheItem->object;
- cacheItem->destroyObject();
- if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object))
- emitDestroyingPackage(package);
- else
- emitDestroyingItem(object);
- cacheItem->scriptRef -= 1;
- }
- if (!cacheItem->isReferenced()) {
- m_compositor.clearFlags(Compositor::Cache, cacheIndex, 1, Compositor::CacheFlag);
- m_cache.removeAt(cacheIndex);
- delete cacheItem;
- --cacheIndex;
- ++removedCache;
- Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache));
- } else if (remove.groups() == cacheItem->groups) {
- cacheItem->groups = 0;
- if (QQDMIncubationTask *incubationTask = cacheItem->incubationTask) {
- for (int i = 1; i < m_groupCount; ++i)
- incubationTask->index[i] = -1;
- }
- if (QQmlDelegateModelAttached *attached = cacheItem->attached) {
- for (int i = 1; i < m_groupCount; ++i)
- attached->m_currentIndex[i] = -1;
- }
- } else {
- if (QQDMIncubationTask *incubationTask = cacheItem->incubationTask) {
- if (!cacheItem->isObjectReferenced()) {
- releaseIncubator(cacheItem->incubationTask);
- cacheItem->incubationTask = nullptr;
- if (cacheItem->object) {
- QObject *object = cacheItem->object;
- cacheItem->destroyObject();
- if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object))
- emitDestroyingPackage(package);
- else
- emitDestroyingItem(object);
- }
- cacheItem->scriptRef -= 1;
- } else {
- for (int i = 1; i < m_groupCount; ++i) {
- if (remove.inGroup(i))
- incubationTask->index[i] = remove.index[i];
- }
- }
- }
- if (QQmlDelegateModelAttached *attached = cacheItem->attached) {
- for (int i = 1; i < m_groupCount; ++i) {
- if (remove.inGroup(i))
- attached->m_currentIndex[i] = remove.index[i];
- }
- }
- cacheItem->groups &= ~remove.flags;
- }
- }
- }
- }
-
- for (const QList<QQmlDelegateModelItem *> cache = m_cache; cacheIndex < cache.count(); ++cacheIndex)
- incrementIndexes(cache.at(cacheIndex), m_groupCount, removed);
-}
-
-void QQmlDelegateModelPrivate::itemsRemoved(const QVector<Compositor::Remove> &removes)
-{
- QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> translatedRemoves(m_groupCount);
- itemsRemoved(removes, &translatedRemoves);
- Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache));
- if (!m_delegate)
- return;
-
- for (int i = 1; i < m_groupCount; ++i)
- QQmlDelegateModelGroupPrivate::get(m_groups[i])->changeSet.remove(translatedRemoves.at(i));
-}
-
-void QQmlDelegateModel::_q_itemsRemoved(int index, int count)
-{
- Q_D(QQmlDelegateModel);
- if (count <= 0|| !d->m_complete)
- return;
-
- d->m_count -= count;
- const QList<QQmlDelegateModelItem *> cache = d->m_cache;
- for (int i = 0, c = cache.count(); i < c; ++i) {
- QQmlDelegateModelItem *item = cache.at(i);
- // layout change triggered by removal of a previous item might have
- // already invalidated this item in d->m_cache and deleted it
- if (!d->m_cache.contains(item))
- continue;
-
- if (item->modelIndex() >= index + count) {
- const int newIndex = item->modelIndex() - count;
- const int row = newIndex;
- const int column = 0;
- item->setModelIndex(newIndex, row, column);
- } else if (item->modelIndex() >= index) {
- item->setModelIndex(-1, -1, -1);
- }
- }
-
- QVector<Compositor::Remove> removes;
- d->m_compositor.listItemsRemoved(&d->m_adaptorModel, index, count, &removes);
- d->itemsRemoved(removes);
-
- d->emitChanges();
-}
-
-void QQmlDelegateModelPrivate::itemsMoved(
- const QVector<Compositor::Remove> &removes, const QVector<Compositor::Insert> &inserts)
-{
- QHash<int, QList<QQmlDelegateModelItem *> > movedItems;
-
- QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> translatedRemoves(m_groupCount);
- itemsRemoved(removes, &translatedRemoves, &movedItems);
-
- QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> translatedInserts(m_groupCount);
- itemsInserted(inserts, &translatedInserts, &movedItems);
- Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache));
- Q_ASSERT(movedItems.isEmpty());
- if (!m_delegate)
- return;
-
- for (int i = 1; i < m_groupCount; ++i) {
- QQmlDelegateModelGroupPrivate::get(m_groups[i])->changeSet.move(
- translatedRemoves.at(i),
- translatedInserts.at(i));
- }
-}
-
-void QQmlDelegateModel::_q_itemsMoved(int from, int to, int count)
-{
- Q_D(QQmlDelegateModel);
- if (count <= 0 || !d->m_complete)
- return;
-
- const int minimum = qMin(from, to);
- const int maximum = qMax(from, to) + count;
- const int difference = from > to ? count : -count;
-
- const QList<QQmlDelegateModelItem *> cache = d->m_cache;
- for (int i = 0, c = cache.count(); i < c; ++i) {
- QQmlDelegateModelItem *item = cache.at(i);
- if (item->modelIndex() >= from && item->modelIndex() < from + count) {
- const int newIndex = item->modelIndex() - from + to;
- const int row = newIndex;
- const int column = 0;
- item->setModelIndex(newIndex, row, column);
- } else if (item->modelIndex() >= minimum && item->modelIndex() < maximum) {
- const int newIndex = item->modelIndex() + difference;
- const int row = newIndex;
- const int column = 0;
- item->setModelIndex(newIndex, row, column);
- }
- }
-
- QVector<Compositor::Remove> removes;
- QVector<Compositor::Insert> inserts;
- d->m_compositor.listItemsMoved(&d->m_adaptorModel, from, to, count, &removes, &inserts);
- d->itemsMoved(removes, inserts);
- d->emitChanges();
-}
-
-void QQmlDelegateModelPrivate::emitModelUpdated(const QQmlChangeSet &changeSet, bool reset)
-{
- Q_Q(QQmlDelegateModel);
- emit q->modelUpdated(changeSet, reset);
- if (changeSet.difference() != 0)
- emit q->countChanged();
-}
-
-void QQmlDelegateModelPrivate::delegateChanged(bool add, bool remove)
-{
- Q_Q(QQmlDelegateModel);
- if (!m_complete)
- return;
-
- if (m_transaction) {
- qmlWarning(q) << QQmlDelegateModel::tr("The delegates of a DelegateModel cannot be changed within onUpdated.");
- return;
- }
-
- if (remove) {
- for (int i = 1; i < m_groupCount; ++i) {
- QQmlDelegateModelGroupPrivate::get(m_groups[i])->changeSet.remove(
- 0, m_compositor.count(Compositor::Group(i)));
- }
- }
- if (add) {
- for (int i = 1; i < m_groupCount; ++i) {
- QQmlDelegateModelGroupPrivate::get(m_groups[i])->changeSet.insert(
- 0, m_compositor.count(Compositor::Group(i)));
- }
- }
- emitChanges();
-}
-
-void QQmlDelegateModelPrivate::emitChanges()
-{
- if (m_transaction || !m_complete || !m_context || !m_context->isValid())
- return;
-
- m_transaction = true;
- QV4::ExecutionEngine *engine = m_context->engine()->handle();
- for (int i = 1; i < m_groupCount; ++i)
- QQmlDelegateModelGroupPrivate::get(m_groups[i])->emitChanges(engine);
- m_transaction = false;
-
- const bool reset = m_reset;
- m_reset = false;
- for (int i = 1; i < m_groupCount; ++i)
- QQmlDelegateModelGroupPrivate::get(m_groups[i])->emitModelUpdated(reset);
-
- auto cacheCopy = m_cache; // deliberate; emitChanges may alter m_cache
- for (QQmlDelegateModelItem *cacheItem : qAsConst(cacheCopy)) {
- if (cacheItem->attached)
- cacheItem->attached->emitChanges();
- }
-}
-
-void QQmlDelegateModel::_q_modelReset()
-{
- Q_D(QQmlDelegateModel);
- if (!d->m_delegate)
- return;
-
- int oldCount = d->m_count;
- d->m_adaptorModel.rootIndex = QModelIndex();
-
- if (d->m_complete) {
- d->m_count = d->adaptorModelCount();
-
- const QList<QQmlDelegateModelItem *> cache = d->m_cache;
- for (int i = 0, c = cache.count(); i < c; ++i) {
- QQmlDelegateModelItem *item = cache.at(i);
- if (item->modelIndex() != -1)
- item->setModelIndex(-1, -1, -1);
- }
-
- QVector<Compositor::Remove> removes;
- QVector<Compositor::Insert> inserts;
- if (oldCount)
- d->m_compositor.listItemsRemoved(&d->m_adaptorModel, 0, oldCount, &removes);
- if (d->m_count)
- d->m_compositor.listItemsInserted(&d->m_adaptorModel, 0, d->m_count, &inserts);
- d->itemsMoved(removes, inserts);
- d->m_reset = true;
-
- if (d->m_adaptorModel.canFetchMore())
- d->m_adaptorModel.fetchMore();
-
- d->emitChanges();
- }
- emit rootIndexChanged();
-}
-
-void QQmlDelegateModel::_q_rowsInserted(const QModelIndex &parent, int begin, int end)
-{
- Q_D(QQmlDelegateModel);
- if (parent == d->m_adaptorModel.rootIndex)
- _q_itemsInserted(begin, end - begin + 1);
-}
-
-void QQmlDelegateModel::_q_rowsAboutToBeRemoved(const QModelIndex &parent, int begin, int end)
-{
- Q_D(QQmlDelegateModel);
- if (!d->m_adaptorModel.rootIndex.isValid())
- return;
- const QModelIndex index = d->m_adaptorModel.rootIndex;
- if (index.parent() == parent && index.row() >= begin && index.row() <= end) {
- const int oldCount = d->m_count;
- d->m_count = 0;
- d->disconnectFromAbstractItemModel();
- d->m_adaptorModel.invalidateModel();
-
- if (d->m_complete && oldCount > 0) {
- QVector<Compositor::Remove> removes;
- d->m_compositor.listItemsRemoved(&d->m_adaptorModel, 0, oldCount, &removes);
- d->itemsRemoved(removes);
- d->emitChanges();
- }
- }
-}
-
-void QQmlDelegateModel::_q_rowsRemoved(const QModelIndex &parent, int begin, int end)
-{
- Q_D(QQmlDelegateModel);
- if (parent == d->m_adaptorModel.rootIndex)
- _q_itemsRemoved(begin, end - begin + 1);
-}
-
-void QQmlDelegateModel::_q_rowsMoved(
- const QModelIndex &sourceParent, int sourceStart, int sourceEnd,
- const QModelIndex &destinationParent, int destinationRow)
-{
- Q_D(QQmlDelegateModel);
- const int count = sourceEnd - sourceStart + 1;
- if (destinationParent == d->m_adaptorModel.rootIndex && sourceParent == d->m_adaptorModel.rootIndex) {
- _q_itemsMoved(sourceStart, sourceStart > destinationRow ? destinationRow : destinationRow - count, count);
- } else if (sourceParent == d->m_adaptorModel.rootIndex) {
- _q_itemsRemoved(sourceStart, count);
- } else if (destinationParent == d->m_adaptorModel.rootIndex) {
- _q_itemsInserted(destinationRow, count);
- }
-}
-
-void QQmlDelegateModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end, const QVector<int> &roles)
-{
- Q_D(QQmlDelegateModel);
- if (begin.parent() == d->m_adaptorModel.rootIndex)
- _q_itemsChanged(begin.row(), end.row() - begin.row() + 1, roles);
-}
-
-bool QQmlDelegateModel::isDescendantOf(const QPersistentModelIndex& desc, const QList< QPersistentModelIndex >& parents) const
-{
- for (int i = 0, c = parents.count(); i < c; ++i) {
- for (QPersistentModelIndex parent = desc; parent.isValid(); parent = parent.parent()) {
- if (parent == parents[i])
- return true;
- }
- }
-
- return false;
-}
-
-void QQmlDelegateModel::_q_layoutChanged(const QList<QPersistentModelIndex> &parents, QAbstractItemModel::LayoutChangeHint hint)
-{
- Q_D(QQmlDelegateModel);
- if (!d->m_complete)
- return;
-
- if (hint == QAbstractItemModel::VerticalSortHint) {
- if (!parents.isEmpty() && d->m_adaptorModel.rootIndex.isValid() && !isDescendantOf(d->m_adaptorModel.rootIndex, parents)) {
- return;
- }
-
- // mark all items as changed
- _q_itemsChanged(0, d->m_count, QVector<int>());
-
- } else if (hint == QAbstractItemModel::HorizontalSortHint) {
- // Ignored
- } else {
- // We don't know what's going on, so reset the model
- _q_modelReset();
- }
-}
-
-QQmlDelegateModelAttached *QQmlDelegateModel::qmlAttachedProperties(QObject *obj)
-{
- if (QQmlDelegateModelItem *cacheItem = QQmlDelegateModelItem::dataForObject(obj)) {
- if (cacheItem->object == obj) { // Don't create attached item for child objects.
- cacheItem->attached = new QQmlDelegateModelAttached(cacheItem, obj);
- return cacheItem->attached;
- }
- }
- return new QQmlDelegateModelAttached(obj);
-}
-
-bool QQmlDelegateModelPrivate::insert(Compositor::insert_iterator &before, const QV4::Value &object, int groups)
-{
- if (!m_context || !m_context->isValid())
- return false;
-
- QQmlDelegateModelItem *cacheItem = m_adaptorModel.createItem(m_cacheMetaType, -1);
- if (!cacheItem)
- return false;
- if (!object.isObject())
- return false;
-
- QV4::ExecutionEngine *v4 = object.as<QV4::Object>()->engine();
- QV4::Scope scope(v4);
- QV4::ScopedObject o(scope, object);
- if (!o)
- return false;
-
- QV4::ObjectIterator it(scope, o, QV4::ObjectIterator::EnumerableOnly);
- QV4::ScopedValue propertyName(scope);
- QV4::ScopedValue v(scope);
- while (1) {
- propertyName = it.nextPropertyNameAsString(v);
- if (propertyName->isNull())
- break;
- cacheItem->setValue(propertyName->toQStringNoThrow(), scope.engine->toVariant(v, QVariant::Invalid));
- }
-
- cacheItem->groups = groups | Compositor::UnresolvedFlag | Compositor::CacheFlag;
-
- // 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);
-
- return true;
-}
-
-//============================================================================
-
-QQmlDelegateModelItemMetaType::QQmlDelegateModelItemMetaType(
- QV4::ExecutionEngine *engine, QQmlDelegateModel *model, const QStringList &groupNames)
- : model(model)
- , groupCount(groupNames.count() + 1)
- , v4Engine(engine)
- , metaObject(nullptr)
- , groupNames(groupNames)
-{
-}
-
-QQmlDelegateModelItemMetaType::~QQmlDelegateModelItemMetaType()
-{
- if (metaObject)
- metaObject->release();
-}
-
-void QQmlDelegateModelItemMetaType::initializeMetaObject()
-{
- QMetaObjectBuilder builder;
- builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
- builder.setClassName(QQmlDelegateModelAttached::staticMetaObject.className());
- builder.setSuperClass(&QQmlDelegateModelAttached::staticMetaObject);
-
- int notifierId = 0;
- for (int i = 0; i < groupNames.count(); ++i, ++notifierId) {
- QString propertyName = QLatin1String("in") + groupNames.at(i);
- propertyName.replace(2, 1, propertyName.at(2).toUpper());
- builder.addSignal("__" + propertyName.toUtf8() + "Changed()");
- QMetaPropertyBuilder propertyBuilder = builder.addProperty(
- propertyName.toUtf8(), "bool", notifierId);
- propertyBuilder.setWritable(true);
- }
- for (int i = 0; i < groupNames.count(); ++i, ++notifierId) {
- const QString propertyName = groupNames.at(i) + QLatin1String("Index");
- builder.addSignal("__" + propertyName.toUtf8() + "Changed()");
- QMetaPropertyBuilder propertyBuilder = builder.addProperty(
- propertyName.toUtf8(), "int", notifierId);
- propertyBuilder.setWritable(true);
- }
-
- metaObject = new QQmlDelegateModelAttachedMetaObject(this, builder.toMetaObject());
-}
-
-void QQmlDelegateModelItemMetaType::initializePrototype()
-{
- QV4::Scope scope(v4Engine);
-
- QV4::ScopedObject proto(scope, v4Engine->newObject());
- proto->defineAccessorProperty(QStringLiteral("model"), QQmlDelegateModelItem::get_model, nullptr);
- proto->defineAccessorProperty(QStringLiteral("groups"), QQmlDelegateModelItem::get_groups, QQmlDelegateModelItem::set_groups);
- QV4::ScopedString s(scope);
- QV4::ScopedProperty p(scope);
-
- s = v4Engine->newString(QStringLiteral("isUnresolved"));
- QV4::ScopedFunctionObject f(scope);
- QV4::ExecutionContext *global = scope.engine->rootContext();
- p->setGetter((f = QV4::DelegateModelGroupFunction::create(global, 30, QQmlDelegateModelItem::get_member)));
- p->setSetter(nullptr);
- proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
-
- s = v4Engine->newString(QStringLiteral("inItems"));
- p->setGetter((f = QV4::DelegateModelGroupFunction::create(global, QQmlListCompositor::Default, QQmlDelegateModelItem::get_member)));
- p->setSetter((f = QV4::DelegateModelGroupFunction::create(global, QQmlListCompositor::Default, QQmlDelegateModelItem::set_member)));
- proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
-
- s = v4Engine->newString(QStringLiteral("inPersistedItems"));
- p->setGetter((f = QV4::DelegateModelGroupFunction::create(global, QQmlListCompositor::Persisted, QQmlDelegateModelItem::get_member)));
- p->setSetter((f = QV4::DelegateModelGroupFunction::create(global, QQmlListCompositor::Persisted, QQmlDelegateModelItem::set_member)));
- proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
-
- s = v4Engine->newString(QStringLiteral("itemsIndex"));
- p->setGetter((f = QV4::DelegateModelGroupFunction::create(global, QQmlListCompositor::Default, QQmlDelegateModelItem::get_index)));
- proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
-
- s = v4Engine->newString(QStringLiteral("persistedItemsIndex"));
- p->setGetter((f = QV4::DelegateModelGroupFunction::create(global, QQmlListCompositor::Persisted, QQmlDelegateModelItem::get_index)));
- p->setSetter(nullptr);
- proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
-
- for (int i = 2; i < groupNames.count(); ++i) {
- QString propertyName = QLatin1String("in") + groupNames.at(i);
- propertyName.replace(2, 1, propertyName.at(2).toUpper());
- s = v4Engine->newString(propertyName);
- p->setGetter((f = QV4::DelegateModelGroupFunction::create(global, i + 1, QQmlDelegateModelItem::get_member)));
- p->setSetter((f = QV4::DelegateModelGroupFunction::create(global, i + 1, QQmlDelegateModelItem::set_member)));
- proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
- }
- for (int i = 2; i < groupNames.count(); ++i) {
- const QString propertyName = groupNames.at(i) + QLatin1String("Index");
- s = v4Engine->newString(propertyName);
- p->setGetter((f = QV4::DelegateModelGroupFunction::create(global, i + 1, QQmlDelegateModelItem::get_index)));
- p->setSetter(nullptr);
- proto->insertMember(s, p, QV4::Attr_Accessor|QV4::Attr_NotConfigurable|QV4::Attr_NotEnumerable);
- }
- modelItemProto.set(v4Engine, proto);
-}
-
-int QQmlDelegateModelItemMetaType::parseGroups(const QStringList &groups) const
-{
- int groupFlags = 0;
- for (const QString &groupName : groups) {
- int index = groupNames.indexOf(groupName);
- if (index != -1)
- groupFlags |= 2 << index;
- }
- return groupFlags;
-}
-
-int QQmlDelegateModelItemMetaType::parseGroups(const QV4::Value &groups) const
-{
- int groupFlags = 0;
- QV4::Scope scope(v4Engine);
-
- QV4::ScopedString s(scope, groups);
- if (s) {
- const QString groupName = s->toQString();
- int index = groupNames.indexOf(groupName);
- if (index != -1)
- groupFlags |= 2 << index;
- return groupFlags;
- }
-
- QV4::ScopedArrayObject array(scope, groups);
- if (array) {
- QV4::ScopedValue v(scope);
- uint arrayLength = array->getLength();
- for (uint i = 0; i < arrayLength; ++i) {
- v = array->get(i);
- const QString groupName = v->toQString();
- int index = groupNames.indexOf(groupName);
- if (index != -1)
- groupFlags |= 2 << index;
- }
- }
- return groupFlags;
-}
-
-QV4::ReturnedValue QQmlDelegateModelItem::get_model(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
-{
- QV4::Scope scope(b);
- QV4::Scoped<QQmlDelegateModelItemObject> o(scope, thisObject->as<QQmlDelegateModelItemObject>());
- if (!o)
- return b->engine()->throwTypeError(QStringLiteral("Not a valid DelegateModel object"));
- if (!o->d()->item->metaType->model)
- RETURN_UNDEFINED();
-
- return o->d()->item->get();
-}
-
-QV4::ReturnedValue QQmlDelegateModelItem::get_groups(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
-{
- QV4::Scope scope(b);
- QV4::Scoped<QQmlDelegateModelItemObject> o(scope, thisObject->as<QQmlDelegateModelItemObject>());
- if (!o)
- return scope.engine->throwTypeError(QStringLiteral("Not a valid DelegateModel object"));
-
- QStringList groups;
- for (int i = 1; i < o->d()->item->metaType->groupCount; ++i) {
- if (o->d()->item->groups & (1 << i))
- groups.append(o->d()->item->metaType->groupNames.at(i - 1));
- }
-
- return scope.engine->fromVariant(groups);
-}
-
-QV4::ReturnedValue QQmlDelegateModelItem::set_groups(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
-{
- QV4::Scope scope(b);
- QV4::Scoped<QQmlDelegateModelItemObject> o(scope, thisObject->as<QQmlDelegateModelItemObject>());
- if (!o)
- return scope.engine->throwTypeError(QStringLiteral("Not a valid DelegateModel object"));
-
- if (!argc)
- THROW_TYPE_ERROR();
-
- if (!o->d()->item->metaType->model)
- RETURN_UNDEFINED();
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(o->d()->item->metaType->model);
-
- const int groupFlags = model->m_cacheMetaType->parseGroups(argv[0]);
- const int cacheIndex = model->m_cache.indexOf(o->d()->item);
- Compositor::iterator it = model->m_compositor.find(Compositor::Cache, cacheIndex);
- model->setGroups(it, 1, Compositor::Cache, groupFlags);
- return QV4::Encode::undefined();
-}
-
-QV4::ReturnedValue QQmlDelegateModelItem::get_member(QQmlDelegateModelItem *thisItem, uint flag, const QV4::Value &)
-{
- return QV4::Encode(bool(thisItem->groups & (1 << flag)));
-}
-
-QV4::ReturnedValue QQmlDelegateModelItem::set_member(QQmlDelegateModelItem *cacheItem, uint flag, const QV4::Value &arg)
-{
- if (!cacheItem->metaType->model)
- return QV4::Encode::undefined();
-
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(cacheItem->metaType->model);
-
- bool member = arg.toBoolean();
- uint groupFlag = (1 << flag);
- if (member == ((cacheItem->groups & groupFlag) != 0))
- return QV4::Encode::undefined();
-
- const int cacheIndex = model->m_cache.indexOf(cacheItem);
- Compositor::iterator it = model->m_compositor.find(Compositor::Cache, cacheIndex);
- if (member)
- model->addGroups(it, 1, Compositor::Cache, groupFlag);
- else
- model->removeGroups(it, 1, Compositor::Cache, groupFlag);
- return QV4::Encode::undefined();
-}
-
-QV4::ReturnedValue QQmlDelegateModelItem::get_index(QQmlDelegateModelItem *thisItem, uint flag, const QV4::Value &)
-{
- return QV4::Encode((int)thisItem->groupIndex(Compositor::Group(flag)));
-}
-
-void QQmlDelegateModelItem::childContextObjectDestroyed(QObject *childContextObject)
-{
- if (!contextData)
- return;
-
- for (QQmlContextData *ctxt = contextData->childContexts; ctxt; ctxt = ctxt->nextChild) {
- if (ctxt->contextObject == childContextObject)
- ctxt->contextObject = nullptr;
- }
-}
-
-
-//---------------------------------------------------------------------------
-
-DEFINE_OBJECT_VTABLE(QQmlDelegateModelItemObject);
-
-void QV4::Heap::QQmlDelegateModelItemObject::destroy()
-{
- item->Dispose();
- Object::destroy();
-}
-
-
-QQmlDelegateModelItem::QQmlDelegateModelItem(QQmlDelegateModelItemMetaType *metaType,
- QQmlAdaptorModel::Accessors *accessor,
- int modelIndex, int row, int column)
- : v4(metaType->v4Engine)
- , metaType(metaType)
- , contextData(nullptr)
- , object(nullptr)
- , attached(nullptr)
- , incubationTask(nullptr)
- , delegate(nullptr)
- , poolTime(0)
- , objectRef(0)
- , scriptRef(0)
- , groups(0)
- , index(modelIndex)
- , row(row)
- , column(column)
-{
- metaType->addref();
-
- if (accessor->propertyCache) {
- // The property cache in the accessor is common for all the model
- // items in the model it wraps. It describes available model roles,
- // together with revisioned properties like row, column and index, all
- // which should be available in the delegate. We assign this cache to the
- // model item so that the QML engine can use the revision information
- // when resolving the properties (rather than falling back to just
- // inspecting the QObject in the model item directly).
- QQmlData *qmldata = QQmlData::get(this, true);
- if (qmldata->propertyCache)
- qmldata->propertyCache->release();
- qmldata->propertyCache = accessor->propertyCache.data();
- qmldata->propertyCache->addref();
- }
-}
-
-QQmlDelegateModelItem::~QQmlDelegateModelItem()
-{
- Q_ASSERT(scriptRef == 0);
- Q_ASSERT(objectRef == 0);
- Q_ASSERT(!object);
-
- if (incubationTask) {
- if (metaType->model)
- QQmlDelegateModelPrivate::get(metaType->model)->releaseIncubator(incubationTask);
- else
- delete incubationTask;
- }
-
- metaType->release();
-
-}
-
-void QQmlDelegateModelItem::Dispose()
-{
- --scriptRef;
- if (isReferenced())
- return;
-
- if (metaType->model) {
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(metaType->model);
- model->removeCacheItem(this);
- }
- delete this;
-}
-
-void QQmlDelegateModelItem::setModelIndex(int idx, int newRow, int newColumn)
-{
- const int prevIndex = index;
- const int prevRow = row;
- const int prevColumn = column;
-
- index = idx;
- row = newRow;
- column = newColumn;
-
- if (idx != prevIndex)
- emit modelIndexChanged();
- if (row != prevRow)
- emit rowChanged();
- if (column != prevColumn)
- emit columnChanged();
-}
-
-void QQmlDelegateModelItem::destroyObject()
-{
- Q_ASSERT(object);
- Q_ASSERT(contextData);
-
- QQmlData *data = QQmlData::get(object);
- Q_ASSERT(data);
- if (data->ownContext) {
- data->ownContext->clearContext();
- if (data->ownContext->contextObject == object)
- data->ownContext->contextObject = nullptr;
- data->ownContext = nullptr;
- data->context = nullptr;
- }
- object->deleteLater();
-
- if (attached) {
- attached->m_cacheItem = nullptr;
- attached = nullptr;
- }
-
- contextData->invalidate();
- contextData = nullptr;
- object = nullptr;
-}
-
-QQmlDelegateModelItem *QQmlDelegateModelItem::dataForObject(QObject *object)
-{
- QQmlData *d = QQmlData::get(object);
- QQmlContextData *context = d ? d->context : nullptr;
- for (context = context ? context->parent : nullptr; context; context = context->parent) {
- if (QQmlDelegateModelItem *cacheItem = qobject_cast<QQmlDelegateModelItem *>(
- context->contextObject)) {
- return cacheItem;
- }
- }
- return nullptr;
-}
-
-int QQmlDelegateModelItem::groupIndex(Compositor::Group group)
-{
- if (QQmlDelegateModelPrivate * const model = metaType->model
- ? QQmlDelegateModelPrivate::get(metaType->model)
- : nullptr) {
- return model->m_compositor.find(Compositor::Cache, model->m_cache.indexOf(this)).index[group];
- }
- return -1;
-}
-
-//---------------------------------------------------------------------------
-
-QQmlDelegateModelAttachedMetaObject::QQmlDelegateModelAttachedMetaObject(
- QQmlDelegateModelItemMetaType *metaType, QMetaObject *metaObject)
- : metaType(metaType)
- , metaObject(metaObject)
- , memberPropertyOffset(QQmlDelegateModelAttached::staticMetaObject.propertyCount())
- , indexPropertyOffset(QQmlDelegateModelAttached::staticMetaObject.propertyCount() + metaType->groupNames.count())
-{
- // Don't reference count the meta-type here as that would create a circular reference.
- // Instead we rely the fact that the meta-type's reference count can't reach 0 without first
- // destroying all delegates with attached objects.
- *static_cast<QMetaObject *>(this) = *metaObject;
-}
-
-QQmlDelegateModelAttachedMetaObject::~QQmlDelegateModelAttachedMetaObject()
-{
- ::free(metaObject);
-}
-
-void QQmlDelegateModelAttachedMetaObject::objectDestroyed(QObject *)
-{
- release();
-}
-
-int QQmlDelegateModelAttachedMetaObject::metaCall(QObject *object, QMetaObject::Call call, int _id, void **arguments)
-{
- QQmlDelegateModelAttached *attached = static_cast<QQmlDelegateModelAttached *>(object);
- if (call == QMetaObject::ReadProperty) {
- if (_id >= indexPropertyOffset) {
- Compositor::Group group = Compositor::Group(_id - indexPropertyOffset + 1);
- *static_cast<int *>(arguments[0]) = attached->m_currentIndex[group];
- return -1;
- } else if (_id >= memberPropertyOffset) {
- Compositor::Group group = Compositor::Group(_id - memberPropertyOffset + 1);
- *static_cast<bool *>(arguments[0]) = attached->m_cacheItem->groups & (1 << group);
- return -1;
- }
- } else if (call == QMetaObject::WriteProperty) {
- if (_id >= memberPropertyOffset) {
- if (!metaType->model)
- return -1;
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(metaType->model);
- Compositor::Group group = Compositor::Group(_id - memberPropertyOffset + 1);
- const int groupFlag = 1 << group;
- const bool member = attached->m_cacheItem->groups & groupFlag;
- if (member && !*static_cast<bool *>(arguments[0])) {
- Compositor::iterator it = model->m_compositor.find(
- group, attached->m_currentIndex[group]);
- model->removeGroups(it, 1, group, groupFlag);
- } else if (!member && *static_cast<bool *>(arguments[0])) {
- for (int i = 1; i < metaType->groupCount; ++i) {
- if (attached->m_cacheItem->groups & (1 << i)) {
- Compositor::iterator it = model->m_compositor.find(
- Compositor::Group(i), attached->m_currentIndex[i]);
- model->addGroups(it, 1, Compositor::Group(i), groupFlag);
- break;
- }
- }
- }
- return -1;
- }
- }
- return attached->qt_metacall(call, _id, arguments);
-}
-
-QQmlDelegateModelAttached::QQmlDelegateModelAttached(QObject *parent)
- : m_cacheItem(nullptr)
- , m_previousGroups(0)
-{
- QQml_setParent_noEvent(this, parent);
-}
-
-QQmlDelegateModelAttached::QQmlDelegateModelAttached(
- QQmlDelegateModelItem *cacheItem, QObject *parent)
- : m_cacheItem(cacheItem)
- , m_previousGroups(cacheItem->groups)
-{
- QQml_setParent_noEvent(this, parent);
- resetCurrentIndex();
- // Let m_previousIndex be equal to m_currentIndex
- std::copy(std::begin(m_currentIndex), std::end(m_currentIndex), std::begin(m_previousIndex));
-
- if (!cacheItem->metaType->metaObject)
- cacheItem->metaType->initializeMetaObject();
-
- QObjectPrivate::get(this)->metaObject = cacheItem->metaType->metaObject;
- cacheItem->metaType->metaObject->addref();
-}
-
-void QQmlDelegateModelAttached::resetCurrentIndex()
-{
- if (QQDMIncubationTask *incubationTask = m_cacheItem->incubationTask) {
- for (int i = 1; i < qMin<int>(m_cacheItem->metaType->groupCount, Compositor::MaximumGroupCount); ++i)
- m_currentIndex[i] = incubationTask->index[i];
- } else {
- QQmlDelegateModelPrivate * const model = QQmlDelegateModelPrivate::get(m_cacheItem->metaType->model);
- Compositor::iterator it = model->m_compositor.find(
- Compositor::Cache, model->m_cache.indexOf(m_cacheItem));
- for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i)
- m_currentIndex[i] = it.index[i];
- }
-}
-
-/*!
- \qmlattachedproperty model QtQml.Models::DelegateModel::model
-
- This attached property holds the data model this delegate instance belongs to.
-
- It is attached to each instance of the delegate.
-*/
-
-QQmlDelegateModel *QQmlDelegateModelAttached::model() const
-{
- return m_cacheItem ? m_cacheItem->metaType->model : nullptr;
-}
-
-/*!
- \qmlattachedproperty stringlist QtQml.Models::DelegateModel::groups
-
- This attached property holds the name of DelegateModelGroups the item belongs to.
-
- It is attached to each instance of the delegate.
-*/
-
-QStringList QQmlDelegateModelAttached::groups() const
-{
- QStringList groups;
-
- if (!m_cacheItem)
- return groups;
- for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i) {
- if (m_cacheItem->groups & (1 << i))
- groups.append(m_cacheItem->metaType->groupNames.at(i - 1));
- }
- return groups;
-}
-
-void QQmlDelegateModelAttached::setGroups(const QStringList &groups)
-{
- if (!m_cacheItem)
- return;
-
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(m_cacheItem->metaType->model);
-
- const int groupFlags = model->m_cacheMetaType->parseGroups(groups);
- const int cacheIndex = model->m_cache.indexOf(m_cacheItem);
- Compositor::iterator it = model->m_compositor.find(Compositor::Cache, cacheIndex);
- model->setGroups(it, 1, Compositor::Cache, groupFlags);
-}
-
-/*!
- \qmlattachedproperty bool QtQml.Models::DelegateModel::isUnresolved
-
- This attached property indicates whether the visual item is bound to a data model index.
- Returns true if the item is not bound to the model, and false if it is.
-
- An unresolved item can be bound to the data model using the DelegateModelGroup::resolve()
- function.
-
- It is attached to each instance of the delegate.
-*/
-
-bool QQmlDelegateModelAttached::isUnresolved() const
-{
- if (!m_cacheItem)
- return false;
-
- return m_cacheItem->groups & Compositor::UnresolvedFlag;
-}
-
-/*!
- \qmlattachedproperty int QtQml.Models::DelegateModel::inItems
-
- This attached property holds whether the item belongs to the default \l items DelegateModelGroup.
-
- Changing this property will add or remove the item from the items group.
-
- It is attached to each instance of the delegate.
-*/
-
-/*!
- \qmlattachedproperty int QtQml.Models::DelegateModel::itemsIndex
-
- This attached property holds the index of the item in the default \l items DelegateModelGroup.
-
- It is attached to each instance of the delegate.
-*/
-
-/*!
- \qmlattachedproperty int QtQml.Models::DelegateModel::inPersistedItems
-
- This attached property holds whether the item belongs to the \l persistedItems DelegateModelGroup.
-
- Changing this property will add or remove the item from the items group. Change with caution
- as removing an item from the persistedItems group will destroy the current instance if it is
- not referenced by a model.
-
- It is attached to each instance of the delegate.
-*/
-
-/*!
- \qmlattachedproperty int QtQml.Models::DelegateModel::persistedItemsIndex
-
- This attached property holds the index of the item in the \l persistedItems DelegateModelGroup.
-
- It is attached to each instance of the delegate.
-*/
-
-void QQmlDelegateModelAttached::emitChanges()
-{
- const int groupChanges = m_previousGroups ^ m_cacheItem->groups;
- m_previousGroups = m_cacheItem->groups;
-
- int indexChanges = 0;
- for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i) {
- if (m_previousIndex[i] != m_currentIndex[i]) {
- m_previousIndex[i] = m_currentIndex[i];
- indexChanges |= (1 << i);
- }
- }
-
- int notifierId = 0;
- const QMetaObject *meta = metaObject();
- for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i, ++notifierId) {
- if (groupChanges & (1 << i))
- QMetaObject::activate(this, meta, notifierId, nullptr);
- }
- for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i, ++notifierId) {
- if (indexChanges & (1 << i))
- QMetaObject::activate(this, meta, notifierId, nullptr);
- }
-
- if (groupChanges)
- emit groupsChanged();
-}
-
-//============================================================================
-
-void QQmlDelegateModelGroupPrivate::setModel(QQmlDelegateModel *m, Compositor::Group g)
-{
- Q_ASSERT(!model);
- model = m;
- group = g;
-}
-
-bool QQmlDelegateModelGroupPrivate::isChangedConnected()
-{
- Q_Q(QQmlDelegateModelGroup);
- IS_SIGNAL_CONNECTED(q, QQmlDelegateModelGroup, changed, (const QJSValue &,const QJSValue &));
-}
-
-void QQmlDelegateModelGroupPrivate::emitChanges(QV4::ExecutionEngine *v4)
-{
- Q_Q(QQmlDelegateModelGroup);
- if (isChangedConnected() && !changeSet.isEmpty()) {
- emit q->changed(QJSValue(v4, engineData(v4)->array(v4, changeSet.removes())),
- QJSValue(v4, engineData(v4)->array(v4, changeSet.inserts())));
- }
- if (changeSet.difference() != 0)
- emit q->countChanged();
-}
-
-void QQmlDelegateModelGroupPrivate::emitModelUpdated(bool reset)
-{
- for (QQmlDelegateModelGroupEmitterList::iterator it = emitters.begin(); it != emitters.end(); ++it)
- it->emitModelUpdated(changeSet, reset);
- changeSet.clear();
-}
-
-typedef QQmlDelegateModelGroupEmitterList::iterator GroupEmitterListIt;
-
-void QQmlDelegateModelGroupPrivate::createdPackage(int index, QQuickPackage *package)
-{
- for (GroupEmitterListIt it = emitters.begin(), end = emitters.end(); it != end; ++it)
- it->createdPackage(index, package);
-}
-
-void QQmlDelegateModelGroupPrivate::initPackage(int index, QQuickPackage *package)
-{
- for (GroupEmitterListIt it = emitters.begin(), end = emitters.end(); it != end; ++it)
- it->initPackage(index, package);
-}
-
-void QQmlDelegateModelGroupPrivate::destroyingPackage(QQuickPackage *package)
-{
- for (GroupEmitterListIt it = emitters.begin(), end = emitters.end(); it != end; ++it)
- it->destroyingPackage(package);
-}
-
-/*!
- \qmltype DelegateModelGroup
- \instantiates QQmlDelegateModelGroup
- \inqmlmodule QtQml.Models
- \ingroup qtquick-models
- \brief Encapsulates a filtered set of visual data items.
-
- The DelegateModelGroup type provides a means to address the model data of a
- DelegateModel's delegate items, as well as sort and filter these delegate
- items.
-
- The initial set of instantiable delegate items in a DelegateModel is represented
- by its \l {QtQml.Models::DelegateModel::items}{items} group, which normally directly reflects
- the contents of the model assigned to DelegateModel::model. This set can be changed to
- the contents of any other member of DelegateModel::groups by assigning the \l name of that
- DelegateModelGroup to the DelegateModel::filterOnGroup property.
-
- The data of an item in a DelegateModelGroup can be accessed using the get() function, which returns
- information about group membership and indexes as well as model data. In combination
- with the move() function this can be used to implement view sorting, with remove() to filter
- items out of a view, or with setGroups() and \l Package delegates to categorize items into
- different views. Different groups can only be sorted independently if they are disjunct. Moving
- an item in one group will also move it in all other groups it is a part of.
-
- Data from models can be supplemented by inserting data directly into a DelegateModelGroup
- with the insert() function. This can be used to introduce mock items into a view, or
- placeholder items that are later \l {resolve()}{resolved} to real model data when it becomes
- available.
-
- Delegate items can also be instantiated directly from a DelegateModelGroup using the
- create() function, making it possible to use DelegateModel without an accompanying view
- type or to cherry-pick specific items that should be instantiated irregardless of whether
- they're currently within a view's visible area.
-
- \sa {QML Dynamic View Ordering Tutorial}
-*/
-QQmlDelegateModelGroup::QQmlDelegateModelGroup(QObject *parent)
- : QObject(*new QQmlDelegateModelGroupPrivate, parent)
-{
-}
-
-QQmlDelegateModelGroup::QQmlDelegateModelGroup(
- const QString &name, QQmlDelegateModel *model, int index, QObject *parent)
- : QQmlDelegateModelGroup(parent)
-{
- Q_D(QQmlDelegateModelGroup);
- d->name = name;
- d->setModel(model, Compositor::Group(index));
-}
-
-QQmlDelegateModelGroup::~QQmlDelegateModelGroup()
-{
-}
-
-/*!
- \qmlproperty string QtQml.Models::DelegateModelGroup::name
-
- This property holds the name of the group.
-
- Each group in a model must have a unique name starting with a lower case letter.
-*/
-
-QString QQmlDelegateModelGroup::name() const
-{
- Q_D(const QQmlDelegateModelGroup);
- return d->name;
-}
-
-void QQmlDelegateModelGroup::setName(const QString &name)
-{
- Q_D(QQmlDelegateModelGroup);
- if (d->model)
- return;
- if (d->name != name) {
- d->name = name;
- emit nameChanged();
- }
-}
-
-/*!
- \qmlproperty int QtQml.Models::DelegateModelGroup::count
-
- This property holds the number of items in the group.
-*/
-
-int QQmlDelegateModelGroup::count() const
-{
- Q_D(const QQmlDelegateModelGroup);
- if (!d->model)
- return 0;
- return QQmlDelegateModelPrivate::get(d->model)->m_compositor.count(d->group);
-}
-
-/*!
- \qmlproperty bool QtQml.Models::DelegateModelGroup::includeByDefault
-
- This property holds whether new items are assigned to this group by default.
-*/
-
-bool QQmlDelegateModelGroup::defaultInclude() const
-{
- Q_D(const QQmlDelegateModelGroup);
- return d->defaultInclude;
-}
-
-void QQmlDelegateModelGroup::setDefaultInclude(bool include)
-{
- Q_D(QQmlDelegateModelGroup);
- if (d->defaultInclude != include) {
- d->defaultInclude = include;
-
- if (d->model) {
- if (include)
- QQmlDelegateModelPrivate::get(d->model)->m_compositor.setDefaultGroup(d->group);
- else
- QQmlDelegateModelPrivate::get(d->model)->m_compositor.clearDefaultGroup(d->group);
- }
- emit defaultIncludeChanged();
- }
-}
-
-/*!
- \qmlmethod object QtQml.Models::DelegateModelGroup::get(int index)
-
- Returns a javascript object describing the item at \a index in the group.
-
- The returned object contains the same information that is available to a delegate from the
- DelegateModel attached as well as the model for that item. It has the properties:
-
- \list
- \li \b model The model data of the item. This is the same as the model context property in
- a delegate
- \li \b groups A list the of names of groups the item is a member of. This property can be
- written to change the item's membership.
- \li \b inItems Whether the item belongs to the \l {QtQml.Models::DelegateModel::items}{items} group.
- Writing to this property will add or remove the item from the group.
- \li \b itemsIndex The index of the item within the \l {QtQml.Models::DelegateModel::items}{items} group.
- \li \b {in<GroupName>} Whether the item belongs to the dynamic group \e groupName. Writing to
- this property will add or remove the item from the group.
- \li \b {<groupName>Index} The index of the item within the dynamic group \e groupName.
- \li \b isUnresolved Whether the item is bound to an index in the model assigned to
- DelegateModel::model. Returns true if the item is not bound to the model, and false if it is.
- \endlist
-*/
-
-QJSValue QQmlDelegateModelGroup::get(int index)
-{
- Q_D(QQmlDelegateModelGroup);
- if (!d->model)
- return QJSValue();
-
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
- if (!model->m_context || !model->m_context->isValid()) {
- return QJSValue();
- } else if (index < 0 || index >= model->m_compositor.count(d->group)) {
- qmlWarning(this) << tr("get: index out of range");
- return QJSValue();
- }
-
- Compositor::iterator it = model->m_compositor.find(d->group, index);
- QQmlDelegateModelItem *cacheItem = it->inCache()
- ? model->m_cache.at(it.cacheIndex)
- : 0;
-
- if (!cacheItem) {
- cacheItem = model->m_adaptorModel.createItem(
- model->m_cacheMetaType, it.modelIndex());
- if (!cacheItem)
- return QJSValue();
- cacheItem->groups = it->flags;
-
- model->m_cache.insert(it.cacheIndex, cacheItem);
- model->m_compositor.setFlags(it, 1, Compositor::CacheFlag);
- }
-
- if (model->m_cacheMetaType->modelItemProto.isUndefined())
- model->m_cacheMetaType->initializePrototype();
- QV4::ExecutionEngine *v4 = model->m_cacheMetaType->v4Engine;
- QV4::Scope scope(v4);
- QV4::ScopedObject o(scope, v4->memoryManager->allocate<QQmlDelegateModelItemObject>(cacheItem));
- QV4::ScopedObject p(scope, model->m_cacheMetaType->modelItemProto.value());
- o->setPrototypeOf(p);
- ++cacheItem->scriptRef;
-
- return QJSValue(v4, o->asReturnedValue());
-}
-
-bool QQmlDelegateModelGroupPrivate::parseIndex(const QV4::Value &value, int *index, Compositor::Group *group) const
-{
- if (value.isNumber()) {
- *index = value.toInt32();
- return true;
- }
-
- if (!value.isObject())
- return false;
-
- QV4::ExecutionEngine *v4 = value.as<QV4::Object>()->engine();
- QV4::Scope scope(v4);
- QV4::Scoped<QQmlDelegateModelItemObject> object(scope, value);
-
- if (object) {
- QQmlDelegateModelItem * const cacheItem = object->d()->item;
- if (QQmlDelegateModelPrivate *model = cacheItem->metaType->model
- ? QQmlDelegateModelPrivate::get(cacheItem->metaType->model)
- : nullptr) {
- *index = model->m_cache.indexOf(cacheItem);
- *group = Compositor::Cache;
- return true;
- }
- }
- return false;
-}
-
-/*!
- \qmlmethod QtQml.Models::DelegateModelGroup::insert(int index, jsdict data, array groups = undefined)
- \qmlmethod QtQml.Models::DelegateModelGroup::insert(jsdict data, var groups = undefined)
-
- Creates a new entry at \a index in a DelegateModel with the values from \a data that
- correspond to roles in the model assigned to DelegateModel::model.
-
- If no index is supplied the data is appended to the model.
-
- The optional \a groups parameter identifies the groups the new entry should belong to,
- if unspecified this is equal to the group insert was called on.
-
- Data inserted into a DelegateModel can later be merged with an existing entry in
- DelegateModel::model using the \l resolve() function. This can be used to create placeholder
- items that are later replaced by actual data.
-*/
-
-void QQmlDelegateModelGroup::insert(QQmlV4Function *args)
-{
- Q_D(QQmlDelegateModelGroup);
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
-
- int index = model->m_compositor.count(d->group);
- Compositor::Group group = d->group;
-
- if (args->length() == 0)
- return;
-
- int i = 0;
- QV4::Scope scope(args->v4engine());
- QV4::ScopedValue v(scope, (*args)[i]);
- if (d->parseIndex(v, &index, &group)) {
- if (index < 0 || index > model->m_compositor.count(group)) {
- qmlWarning(this) << tr("insert: index out of range");
- return;
- }
- if (++i == args->length())
- return;
- v = (*args)[i];
- }
-
- Compositor::insert_iterator before = index < model->m_compositor.count(group)
- ? model->m_compositor.findInsertPosition(group, index)
- : model->m_compositor.end();
-
- int groups = 1 << d->group;
- if (++i < args->length()) {
- QV4::ScopedValue val(scope, (*args)[i]);
- groups |= model->m_cacheMetaType->parseGroups(val);
- }
-
- if (v->as<QV4::ArrayObject>()) {
- return;
- } else if (v->as<QV4::Object>()) {
- model->insert(before, v, groups);
- model->emitChanges();
- }
-}
-
-/*!
- \qmlmethod QtQml.Models::DelegateModelGroup::create(int index)
- \qmlmethod QtQml.Models::DelegateModelGroup::create(int index, jsdict data, array groups = undefined)
- \qmlmethod QtQml.Models::DelegateModelGroup::create(jsdict data, array groups = undefined)
-
- Returns a reference to the instantiated item at \a index in the group.
-
- If a \a data object is provided it will be \l {insert}{inserted} at \a index and an item
- referencing this new entry will be returned. The optional \a groups parameter identifies
- the groups the new entry should belong to, if unspecified this is equal to the group create()
- was called on.
-
- All items returned by create are added to the
- \l {QtQml.Models::DelegateModel::persistedItems}{persistedItems} group. Items in this
- group remain instantiated when not referenced by any view.
-*/
-
-void QQmlDelegateModelGroup::create(QQmlV4Function *args)
-{
- Q_D(QQmlDelegateModelGroup);
- if (!d->model)
- return;
-
- if (args->length() == 0)
- return;
-
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
-
- int index = model->m_compositor.count(d->group);
- Compositor::Group group = d->group;
-
- int i = 0;
- QV4::Scope scope(args->v4engine());
- QV4::ScopedValue v(scope, (*args)[i]);
- if (d->parseIndex(v, &index, &group))
- ++i;
-
- if (i < args->length() && index >= 0 && index <= model->m_compositor.count(group)) {
- v = (*args)[i];
- if (v->as<QV4::Object>()) {
- int groups = 1 << d->group;
- if (++i < args->length()) {
- QV4::ScopedValue val(scope, (*args)[i]);
- groups |= model->m_cacheMetaType->parseGroups(val);
- }
-
- Compositor::insert_iterator before = index < model->m_compositor.count(group)
- ? model->m_compositor.findInsertPosition(group, index)
- : model->m_compositor.end();
-
- index = before.index[d->group];
- group = d->group;
-
- if (!model->insert(before, v, groups)) {
- return;
- }
- }
- }
- if (index < 0 || index >= model->m_compositor.count(group)) {
- qmlWarning(this) << tr("create: index out of range");
- return;
- }
-
- QObject *object = model->object(group, index, QQmlIncubator::AsynchronousIfNested);
- if (object) {
- QVector<Compositor::Insert> inserts;
- Compositor::iterator it = model->m_compositor.find(group, index);
- model->m_compositor.setFlags(it, 1, d->group, Compositor::PersistedFlag, &inserts);
- model->itemsInserted(inserts);
- model->m_cache.at(it.cacheIndex)->releaseObject();
- }
-
- args->setReturnValue(QV4::QObjectWrapper::wrap(args->v4engine(), object));
- model->emitChanges();
-}
-
-/*!
- \qmlmethod QtQml.Models::DelegateModelGroup::resolve(int from, int to)
-
- Binds an unresolved item at \a from to an item in DelegateModel::model at index \a to.
-
- Unresolved items are entries whose data has been \l {insert()}{inserted} into a DelegateModelGroup
- instead of being derived from a DelegateModel::model index. Resolving an item will replace
- the item at the target index with the unresolved item. A resolved an item will reflect the data
- of the source model at its bound index and will move when that index moves like any other item.
-
- If a new item is replaced in the DelegateModelGroup onChanged() handler its insertion and
- replacement will be communicated to views as an atomic operation, creating the appearance
- that the model contents have not changed, or if the unresolved and model item are not adjacent
- that the previously unresolved item has simply moved.
-
-*/
-void QQmlDelegateModelGroup::resolve(QQmlV4Function *args)
-{
- Q_D(QQmlDelegateModelGroup);
- if (!d->model)
- return;
-
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
-
- if (args->length() < 2)
- return;
-
- int from = -1;
- int to = -1;
- Compositor::Group fromGroup = d->group;
- Compositor::Group toGroup = d->group;
-
- QV4::Scope scope(args->v4engine());
- QV4::ScopedValue v(scope, (*args)[0]);
- if (d->parseIndex(v, &from, &fromGroup)) {
- if (from < 0 || from >= model->m_compositor.count(fromGroup)) {
- qmlWarning(this) << tr("resolve: from index out of range");
- return;
- }
- } else {
- qmlWarning(this) << tr("resolve: from index invalid");
- return;
- }
-
- v = (*args)[1];
- if (d->parseIndex(v, &to, &toGroup)) {
- if (to < 0 || to >= model->m_compositor.count(toGroup)) {
- qmlWarning(this) << tr("resolve: to index out of range");
- return;
- }
- } else {
- qmlWarning(this) << tr("resolve: to index invalid");
- return;
- }
-
- Compositor::iterator fromIt = model->m_compositor.find(fromGroup, from);
- Compositor::iterator toIt = model->m_compositor.find(toGroup, to);
-
- if (!fromIt->isUnresolved()) {
- qmlWarning(this) << tr("resolve: from is not an unresolved item");
- return;
- }
- if (!toIt->list) {
- qmlWarning(this) << tr("resolve: to is not a model item");
- return;
- }
-
- const int unresolvedFlags = fromIt->flags;
- const int resolvedFlags = toIt->flags;
- const int resolvedIndex = toIt.modelIndex();
- void * const resolvedList = toIt->list;
-
- QQmlDelegateModelItem *cacheItem = model->m_cache.at(fromIt.cacheIndex);
- cacheItem->groups &= ~Compositor::UnresolvedFlag;
-
- if (toIt.cacheIndex > fromIt.cacheIndex)
- toIt.decrementIndexes(1, unresolvedFlags);
- if (!toIt->inGroup(fromGroup) || toIt.index[fromGroup] > from)
- from += 1;
-
- model->itemsMoved(
- QVector<Compositor::Remove>(1, Compositor::Remove(fromIt, 1, unresolvedFlags, 0)),
- QVector<Compositor::Insert>(1, Compositor::Insert(toIt, 1, unresolvedFlags, 0)));
- model->itemsInserted(
- QVector<Compositor::Insert>(1, Compositor::Insert(toIt, 1, (resolvedFlags & ~unresolvedFlags) | Compositor::CacheFlag)));
- toIt.incrementIndexes(1, resolvedFlags | unresolvedFlags);
- model->itemsRemoved(QVector<Compositor::Remove>(1, Compositor::Remove(toIt, 1, resolvedFlags)));
-
- model->m_compositor.setFlags(toGroup, to, 1, unresolvedFlags & ~Compositor::UnresolvedFlag);
- model->m_compositor.clearFlags(fromGroup, from, 1, unresolvedFlags);
-
- if (resolvedFlags & Compositor::CacheFlag)
- model->m_compositor.insert(Compositor::Cache, toIt.cacheIndex, resolvedList, resolvedIndex, 1, Compositor::CacheFlag);
-
- Q_ASSERT(model->m_cache.count() == model->m_compositor.count(Compositor::Cache));
-
- if (!cacheItem->isReferenced()) {
- Q_ASSERT(toIt.cacheIndex == model->m_cache.indexOf(cacheItem));
- model->m_cache.removeAt(toIt.cacheIndex);
- model->m_compositor.clearFlags(Compositor::Cache, toIt.cacheIndex, 1, Compositor::CacheFlag);
- delete cacheItem;
- Q_ASSERT(model->m_cache.count() == model->m_compositor.count(Compositor::Cache));
- } else {
- cacheItem->resolveIndex(model->m_adaptorModel, resolvedIndex);
- if (cacheItem->attached)
- cacheItem->attached->emitUnresolvedChanged();
- }
-
- model->emitChanges();
-}
-
-/*!
- \qmlmethod QtQml.Models::DelegateModelGroup::remove(int index, int count)
-
- Removes \a count items starting at \a index from the group.
-*/
-
-void QQmlDelegateModelGroup::remove(QQmlV4Function *args)
-{
- Q_D(QQmlDelegateModelGroup);
- if (!d->model)
- return;
- Compositor::Group group = d->group;
- int index = -1;
- int count = 1;
-
- if (args->length() == 0)
- return;
-
- int i = 0;
- QV4::Scope scope(args->v4engine());
- QV4::ScopedValue v(scope, (*args)[0]);
- if (!d->parseIndex(v, &index, &group)) {
- qmlWarning(this) << tr("remove: invalid index");
- return;
- }
-
- if (++i < args->length()) {
- v = (*args)[i];
- if (v->isNumber())
- count = v->toInt32();
- }
-
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
- if (index < 0 || index >= model->m_compositor.count(group)) {
- qmlWarning(this) << tr("remove: index out of range");
- } else if (count != 0) {
- Compositor::iterator it = model->m_compositor.find(group, index);
- if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) {
- qmlWarning(this) << tr("remove: invalid count");
- } else {
- model->removeGroups(it, count, d->group, 1 << d->group);
- }
- }
-}
-
-bool QQmlDelegateModelGroupPrivate::parseGroupArgs(
- QQmlV4Function *args, Compositor::Group *group, int *index, int *count, int *groups) const
-{
- if (!model || !QQmlDelegateModelPrivate::get(model)->m_cacheMetaType)
- return false;
-
- if (args->length() < 2)
- return false;
-
- int i = 0;
- QV4::Scope scope(args->v4engine());
- QV4::ScopedValue v(scope, (*args)[i]);
- if (!parseIndex(v, index, group))
- return false;
-
- v = (*args)[++i];
- if (v->isNumber()) {
- *count = v->toInt32();
-
- if (++i == args->length())
- return false;
- v = (*args)[i];
- }
-
- *groups = QQmlDelegateModelPrivate::get(model)->m_cacheMetaType->parseGroups(v);
-
- return true;
-}
-
-/*!
- \qmlmethod QtQml.Models::DelegateModelGroup::addGroups(int index, int count, stringlist groups)
-
- Adds \a count items starting at \a index to \a groups.
-*/
-
-void QQmlDelegateModelGroup::addGroups(QQmlV4Function *args)
-{
- Q_D(QQmlDelegateModelGroup);
- Compositor::Group group = d->group;
- int index = -1;
- int count = 1;
- int groups = 0;
-
- if (!d->parseGroupArgs(args, &group, &index, &count, &groups))
- return;
-
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
- if (index < 0 || index >= model->m_compositor.count(group)) {
- qmlWarning(this) << tr("addGroups: index out of range");
- } else if (count != 0) {
- Compositor::iterator it = model->m_compositor.find(group, index);
- if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) {
- qmlWarning(this) << tr("addGroups: invalid count");
- } else {
- model->addGroups(it, count, d->group, groups);
- }
- }
-}
-
-/*!
- \qmlmethod QtQml.Models::DelegateModelGroup::removeGroups(int index, int count, stringlist groups)
-
- Removes \a count items starting at \a index from \a groups.
-*/
-
-void QQmlDelegateModelGroup::removeGroups(QQmlV4Function *args)
-{
- Q_D(QQmlDelegateModelGroup);
- Compositor::Group group = d->group;
- int index = -1;
- int count = 1;
- int groups = 0;
-
- if (!d->parseGroupArgs(args, &group, &index, &count, &groups))
- return;
-
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
- if (index < 0 || index >= model->m_compositor.count(group)) {
- qmlWarning(this) << tr("removeGroups: index out of range");
- } else if (count != 0) {
- Compositor::iterator it = model->m_compositor.find(group, index);
- if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) {
- qmlWarning(this) << tr("removeGroups: invalid count");
- } else {
- model->removeGroups(it, count, d->group, groups);
- }
- }
-}
-
-/*!
- \qmlmethod QtQml.Models::DelegateModelGroup::setGroups(int index, int count, stringlist groups)
-
- Sets the \a groups \a count items starting at \a index belong to.
-*/
-
-void QQmlDelegateModelGroup::setGroups(QQmlV4Function *args)
-{
- Q_D(QQmlDelegateModelGroup);
- Compositor::Group group = d->group;
- int index = -1;
- int count = 1;
- int groups = 0;
-
- if (!d->parseGroupArgs(args, &group, &index, &count, &groups))
- return;
-
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
- if (index < 0 || index >= model->m_compositor.count(group)) {
- qmlWarning(this) << tr("setGroups: index out of range");
- } else if (count != 0) {
- Compositor::iterator it = model->m_compositor.find(group, index);
- if (count < 0 || count > model->m_compositor.count(d->group) - it.index[d->group]) {
- qmlWarning(this) << tr("setGroups: invalid count");
- } else {
- model->setGroups(it, count, d->group, groups);
- }
- }
-}
-
-/*!
- \qmlmethod QtQml.Models::DelegateModelGroup::setGroups(int index, int count, stringlist groups)
-
- Sets the \a groups \a count items starting at \a index belong to.
-*/
-
-/*!
- \qmlmethod QtQml.Models::DelegateModelGroup::move(var from, var to, int count)
-
- Moves \a count at \a from in a group \a to a new position.
-
- \note The DelegateModel acts as a proxy model: it holds the delegates in a
- different order than the \l{dm-model-property}{underlying model} has them.
- Any subsequent changes to the underlying model will not undo whatever
- reordering you have done via this function.
-*/
-
-void QQmlDelegateModelGroup::move(QQmlV4Function *args)
-{
- Q_D(QQmlDelegateModelGroup);
-
- if (args->length() < 2)
- return;
-
- Compositor::Group fromGroup = d->group;
- Compositor::Group toGroup = d->group;
- int from = -1;
- int to = -1;
- int count = 1;
-
- QV4::Scope scope(args->v4engine());
- QV4::ScopedValue v(scope, (*args)[0]);
- if (!d->parseIndex(v, &from, &fromGroup)) {
- qmlWarning(this) << tr("move: invalid from index");
- return;
- }
-
- v = (*args)[1];
- if (!d->parseIndex(v, &to, &toGroup)) {
- qmlWarning(this) << tr("move: invalid to index");
- return;
- }
-
- if (args->length() > 2) {
- v = (*args)[2];
- if (v->isNumber())
- count = v->toInt32();
- }
-
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(d->model);
-
- if (count < 0) {
- qmlWarning(this) << tr("move: invalid count");
- } else if (from < 0 || from + count > model->m_compositor.count(fromGroup)) {
- qmlWarning(this) << tr("move: from index out of range");
- } else if (!model->m_compositor.verifyMoveTo(fromGroup, from, toGroup, to, count, d->group)) {
- qmlWarning(this) << tr("move: to index out of range");
- } else if (count > 0) {
- QVector<Compositor::Remove> removes;
- QVector<Compositor::Insert> inserts;
-
- model->m_compositor.move(fromGroup, from, toGroup, to, count, d->group, &removes, &inserts);
- model->itemsMoved(removes, inserts);
- model->emitChanges();
- }
-
-}
-
-/*!
- \qmlsignal QtQml.Models::DelegateModelGroup::changed(array removed, array inserted)
-
- This signal is emitted when items have been removed from or inserted into the group.
-
- Each object in the \a removed and \a inserted arrays has two values; the \e index of the first
- item inserted or removed and a \e count of the number of consecutive items inserted or removed.
-
- Each index is adjusted for previous changes with all removed items preceding any inserted
- items.
-
- The corresponding handler is \c onChanged.
-*/
-
-//============================================================================
-
-QQmlPartsModel::QQmlPartsModel(QQmlDelegateModel *model, const QString &part, QObject *parent)
- : QQmlInstanceModel(*new QObjectPrivate, parent)
- , m_model(model)
- , m_part(part)
- , m_compositorGroup(Compositor::Cache)
- , m_inheritGroup(true)
-{
- QQmlDelegateModelPrivate *d = QQmlDelegateModelPrivate::get(m_model);
- if (d->m_cacheMetaType) {
- QQmlDelegateModelGroupPrivate::get(d->m_groups[1])->emitters.insert(this);
- m_compositorGroup = Compositor::Default;
- } else {
- d->m_pendingParts.insert(this);
- }
-}
-
-QQmlPartsModel::~QQmlPartsModel()
-{
-}
-
-QString QQmlPartsModel::filterGroup() const
-{
- if (m_inheritGroup)
- return m_model->filterGroup();
- return m_filterGroup;
-}
-
-void QQmlPartsModel::setFilterGroup(const QString &group)
-{
- if (QQmlDelegateModelPrivate::get(m_model)->m_transaction) {
- qmlWarning(this) << tr("The group of a DelegateModel cannot be changed within onChanged");
- return;
- }
-
- if (m_filterGroup != group || m_inheritGroup) {
- m_filterGroup = group;
- m_inheritGroup = false;
- updateFilterGroup();
-
- emit filterGroupChanged();
- }
-}
-
-void QQmlPartsModel::resetFilterGroup()
-{
- if (!m_inheritGroup) {
- m_inheritGroup = true;
- updateFilterGroup();
- emit filterGroupChanged();
- }
-}
-
-void QQmlPartsModel::updateFilterGroup()
-{
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(m_model);
- if (!model->m_cacheMetaType)
- return;
-
- if (m_inheritGroup) {
- if (m_filterGroup == model->m_filterGroup)
- return;
- m_filterGroup = model->m_filterGroup;
- }
-
- QQmlListCompositor::Group previousGroup = m_compositorGroup;
- m_compositorGroup = Compositor::Default;
- QQmlDelegateModelGroupPrivate::get(model->m_groups[Compositor::Default])->emitters.insert(this);
- for (int i = 1; i < model->m_groupCount; ++i) {
- if (m_filterGroup == model->m_cacheMetaType->groupNames.at(i - 1)) {
- m_compositorGroup = Compositor::Group(i);
- break;
- }
- }
-
- QQmlDelegateModelGroupPrivate::get(model->m_groups[m_compositorGroup])->emitters.insert(this);
- if (m_compositorGroup != previousGroup) {
- QVector<QQmlChangeSet::Change> removes;
- QVector<QQmlChangeSet::Change> inserts;
- model->m_compositor.transition(previousGroup, m_compositorGroup, &removes, &inserts);
-
- QQmlChangeSet changeSet;
- changeSet.move(removes, inserts);
- if (!changeSet.isEmpty())
- emit modelUpdated(changeSet, false);
-
- if (changeSet.difference() != 0)
- emit countChanged();
- }
-}
-
-void QQmlPartsModel::updateFilterGroup(
- Compositor::Group group, const QQmlChangeSet &changeSet)
-{
- if (!m_inheritGroup)
- return;
-
- m_compositorGroup = group;
- QQmlDelegateModelGroupPrivate::get(QQmlDelegateModelPrivate::get(m_model)->m_groups[m_compositorGroup])->emitters.insert(this);
-
- if (!changeSet.isEmpty())
- emit modelUpdated(changeSet, false);
-
- if (changeSet.difference() != 0)
- emit countChanged();
-
- emit filterGroupChanged();
-}
-
-int QQmlPartsModel::count() const
-{
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(m_model);
- return model->m_delegate
- ? model->m_compositor.count(m_compositorGroup)
- : 0;
-}
-
-bool QQmlPartsModel::isValid() const
-{
- return m_model->isValid();
-}
-
-QObject *QQmlPartsModel::object(int index, QQmlIncubator::IncubationMode incubationMode)
-{
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(m_model);
-
- if (!model->m_delegate || index < 0 || index >= model->m_compositor.count(m_compositorGroup)) {
- qWarning() << "DelegateModel::item: index out range" << index << model->m_compositor.count(m_compositorGroup);
- return nullptr;
- }
-
- QObject *object = model->object(m_compositorGroup, index, incubationMode);
-
- if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object)) {
- QObject *part = package->part(m_part);
- if (!part)
- return nullptr;
- m_packaged.insertMulti(part, package);
- return part;
- }
-
- model->release(object);
- if (!model->m_delegateValidated) {
- if (object)
- qmlWarning(model->m_delegate) << tr("Delegate component must be Package type.");
- model->m_delegateValidated = true;
- }
-
- return nullptr;
-}
-
-QQmlInstanceModel::ReleaseFlags QQmlPartsModel::release(QObject *item)
-{
- QQmlInstanceModel::ReleaseFlags flags = nullptr;
-
- QHash<QObject *, QQuickPackage *>::iterator it = m_packaged.find(item);
- if (it != m_packaged.end()) {
- QQuickPackage *package = *it;
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(m_model);
- flags = model->release(package);
- m_packaged.erase(it);
- if (!m_packaged.contains(item))
- flags &= ~Referenced;
- if (flags & Destroyed)
- QQmlDelegateModelPrivate::get(m_model)->emitDestroyingPackage(package);
- }
- return flags;
-}
-
-QVariant QQmlPartsModel::variantValue(int index, const QString &role)
-{
- return QQmlDelegateModelPrivate::get(m_model)->variantValue(m_compositorGroup, index, role);
-}
-
-void QQmlPartsModel::setWatchedRoles(const QList<QByteArray> &roles)
-{
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(m_model);
- model->m_adaptorModel.replaceWatchedRoles(m_watchedRoles, roles);
- m_watchedRoles = roles;
-}
-
-QQmlIncubator::Status QQmlPartsModel::incubationStatus(int index)
-{
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(m_model);
- Compositor::iterator it = model->m_compositor.find(model->m_compositorGroup, index);
- if (!it->inCache())
- return QQmlIncubator::Null;
-
- if (auto incubationTask = model->m_cache.at(it.cacheIndex)->incubationTask)
- return incubationTask->status();
-
- return QQmlIncubator::Ready;
-}
-
-int QQmlPartsModel::indexOf(QObject *item, QObject *) const
-{
- QHash<QObject *, QQuickPackage *>::const_iterator it = m_packaged.find(item);
- if (it != m_packaged.end()) {
- if (QQmlDelegateModelItem *cacheItem = QQmlDelegateModelItem::dataForObject(*it))
- return cacheItem->groupIndex(m_compositorGroup);
- }
- return -1;
-}
-
-void QQmlPartsModel::createdPackage(int index, QQuickPackage *package)
-{
- emit createdItem(index, package->part(m_part));
-}
-
-void QQmlPartsModel::initPackage(int index, QQuickPackage *package)
-{
- if (m_modelUpdatePending)
- m_pendingPackageInitializations << index;
- else
- emit initItem(index, package->part(m_part));
-}
-
-void QQmlPartsModel::destroyingPackage(QQuickPackage *package)
-{
- QObject *item = package->part(m_part);
- Q_ASSERT(!m_packaged.contains(item));
- emit destroyingItem(item);
-}
-
-void QQmlPartsModel::emitModelUpdated(const QQmlChangeSet &changeSet, bool reset)
-{
- m_modelUpdatePending = false;
- emit modelUpdated(changeSet, reset);
- if (changeSet.difference() != 0)
- emit countChanged();
-
- QQmlDelegateModelPrivate *model = QQmlDelegateModelPrivate::get(m_model);
- QVector<int> pendingPackageInitializations;
- qSwap(pendingPackageInitializations, m_pendingPackageInitializations);
- for (int index : pendingPackageInitializations) {
- if (!model->m_delegate || index < 0 || index >= model->m_compositor.count(m_compositorGroup))
- continue;
- QObject *object = model->object(m_compositorGroup, index, QQmlIncubator::Asynchronous);
- if (QQuickPackage *package = qmlobject_cast<QQuickPackage *>(object))
- emit initItem(index, package->part(m_part));
- model->release(object);
- }
-}
-
-//============================================================================
-
-struct QQmlDelegateModelGroupChange : QV4::Object
-{
- V4_OBJECT2(QQmlDelegateModelGroupChange, QV4::Object)
-
- static QV4::Heap::QQmlDelegateModelGroupChange *create(QV4::ExecutionEngine *e) {
- return e->memoryManager->allocate<QQmlDelegateModelGroupChange>();
- }
-
- static QV4::ReturnedValue method_get_index(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int) {
- QV4::Scope scope(b);
- QV4::Scoped<QQmlDelegateModelGroupChange> that(scope, thisObject->as<QQmlDelegateModelGroupChange>());
- if (!that)
- THROW_TYPE_ERROR();
- return QV4::Encode(that->d()->change.index);
- }
- static QV4::ReturnedValue method_get_count(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int) {
- QV4::Scope scope(b);
- QV4::Scoped<QQmlDelegateModelGroupChange> that(scope, thisObject->as<QQmlDelegateModelGroupChange>());
- if (!that)
- THROW_TYPE_ERROR();
- return QV4::Encode(that->d()->change.count);
- }
- static QV4::ReturnedValue method_get_moveId(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int) {
- QV4::Scope scope(b);
- QV4::Scoped<QQmlDelegateModelGroupChange> that(scope, thisObject->as<QQmlDelegateModelGroupChange>());
- if (!that)
- THROW_TYPE_ERROR();
- if (that->d()->change.moveId < 0)
- RETURN_UNDEFINED();
- return QV4::Encode(that->d()->change.moveId);
- }
-};
-
-DEFINE_OBJECT_VTABLE(QQmlDelegateModelGroupChange);
-
-struct QQmlDelegateModelGroupChangeArray : public QV4::Object
-{
- V4_OBJECT2(QQmlDelegateModelGroupChangeArray, QV4::Object)
- V4_NEEDS_DESTROY
-public:
- static QV4::Heap::QQmlDelegateModelGroupChangeArray *create(QV4::ExecutionEngine *engine, const QVector<QQmlChangeSet::Change> &changes)
- {
- return engine->memoryManager->allocate<QQmlDelegateModelGroupChangeArray>(changes);
- }
-
- quint32 count() const { return d()->changes->count(); }
- const QQmlChangeSet::Change &at(int index) const { return d()->changes->at(index); }
-
- static QV4::ReturnedValue virtualGet(const QV4::Managed *m, QV4::PropertyKey id, const QV4::Value *receiver, bool *hasProperty)
- {
- if (id.isArrayIndex()) {
- uint index = id.asArrayIndex();
- Q_ASSERT(m->as<QQmlDelegateModelGroupChangeArray>());
- QV4::ExecutionEngine *v4 = static_cast<const QQmlDelegateModelGroupChangeArray *>(m)->engine();
- QV4::Scope scope(v4);
- QV4::Scoped<QQmlDelegateModelGroupChangeArray> array(scope, static_cast<const QQmlDelegateModelGroupChangeArray *>(m));
-
- if (index >= array->count()) {
- if (hasProperty)
- *hasProperty = false;
- return QV4::Value::undefinedValue().asReturnedValue();
- }
-
- const QQmlChangeSet::Change &change = array->at(index);
-
- QV4::ScopedObject changeProto(scope, engineData(v4)->changeProto.value());
- QV4::Scoped<QQmlDelegateModelGroupChange> object(scope, QQmlDelegateModelGroupChange::create(v4));
- object->setPrototypeOf(changeProto);
- object->d()->change = change;
-
- if (hasProperty)
- *hasProperty = true;
- return object.asReturnedValue();
- }
-
- Q_ASSERT(m->as<QQmlDelegateModelGroupChangeArray>());
- const QQmlDelegateModelGroupChangeArray *array = static_cast<const QQmlDelegateModelGroupChangeArray *>(m);
-
- if (id == array->engine()->id_length()->propertyKey()) {
- if (hasProperty)
- *hasProperty = true;
- return QV4::Encode(array->count());
- }
-
- return Object::virtualGet(m, id, receiver, hasProperty);
- }
-};
-
-void QV4::Heap::QQmlDelegateModelGroupChangeArray::init(const QVector<QQmlChangeSet::Change> &changes)
-{
- Object::init();
- this->changes = new QVector<QQmlChangeSet::Change>(changes);
- QV4::Scope scope(internalClass->engine);
- QV4::ScopedObject o(scope, this);
- o->setArrayType(QV4::Heap::ArrayData::Custom);
-}
-
-DEFINE_OBJECT_VTABLE(QQmlDelegateModelGroupChangeArray);
-
-QQmlDelegateModelEngineData::QQmlDelegateModelEngineData(QV4::ExecutionEngine *v4)
-{
- QV4::Scope scope(v4);
-
- QV4::ScopedObject proto(scope, v4->newObject());
- proto->defineAccessorProperty(QStringLiteral("index"), QQmlDelegateModelGroupChange::method_get_index, nullptr);
- proto->defineAccessorProperty(QStringLiteral("count"), QQmlDelegateModelGroupChange::method_get_count, nullptr);
- proto->defineAccessorProperty(QStringLiteral("moveId"), QQmlDelegateModelGroupChange::method_get_moveId, nullptr);
- changeProto.set(v4, proto);
-}
-
-QQmlDelegateModelEngineData::~QQmlDelegateModelEngineData()
-{
-}
-
-QV4::ReturnedValue QQmlDelegateModelEngineData::array(QV4::ExecutionEngine *v4,
- const QVector<QQmlChangeSet::Change> &changes)
-{
- QV4::Scope scope(v4);
- QV4::ScopedObject o(scope, QQmlDelegateModelGroupChangeArray::create(v4, changes));
- return o.asReturnedValue();
-}
-
-QT_END_NAMESPACE
-
-#include "moc_qqmldelegatemodel_p.cpp"
diff --git a/src/qml/types/qqmldelegatemodel_p.h b/src/qml/types/qqmldelegatemodel_p.h
deleted file mode 100644
index 2684162514..0000000000
--- a/src/qml/types/qqmldelegatemodel_p.h
+++ /dev/null
@@ -1,248 +0,0 @@
-/****************************************************************************
-**
-** 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 QQMLDATAMODEL_P_H
-#define QQMLDATAMODEL_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 <private/qtqmlglobal_p.h>
-#include <private/qqmllistcompositor_p.h>
-#include <private/qqmlobjectmodel_p.h>
-#include <private/qqmlincubator_p.h>
-
-#include <QtCore/qabstractitemmodel.h>
-#include <QtCore/qstringlist.h>
-
-#include <private/qqmlglobal_p.h>
-
-QT_REQUIRE_CONFIG(qml_delegate_model);
-
-QT_BEGIN_NAMESPACE
-
-class QQmlChangeSet;
-class QQuickPackage;
-class QQmlV4Function;
-class QQmlDelegateModelGroup;
-class QQmlDelegateModelAttached;
-class QQmlDelegateModelPrivate;
-
-
-class Q_QML_PRIVATE_EXPORT QQmlDelegateModel : public QQmlInstanceModel, public QQmlParserStatus
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QQmlDelegateModel)
-
- Q_PROPERTY(QVariant model READ model WRITE setModel)
- Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate)
- Q_PROPERTY(QString filterOnGroup READ filterGroup WRITE setFilterGroup NOTIFY filterGroupChanged RESET resetFilterGroup)
- Q_PROPERTY(QQmlDelegateModelGroup *items READ items CONSTANT) //TODO : worth renaming?
- Q_PROPERTY(QQmlDelegateModelGroup *persistedItems READ persistedItems CONSTANT)
- Q_PROPERTY(QQmlListProperty<QQmlDelegateModelGroup> groups READ groups CONSTANT)
- Q_PROPERTY(QObject *parts READ parts CONSTANT)
- Q_PROPERTY(QVariant rootIndex READ rootIndex WRITE setRootIndex NOTIFY rootIndexChanged)
- Q_CLASSINFO("DefaultProperty", "delegate")
- Q_INTERFACES(QQmlParserStatus)
-public:
- QQmlDelegateModel();
- QQmlDelegateModel(QQmlContext *, QObject *parent=nullptr);
- ~QQmlDelegateModel();
-
- void classBegin() override;
- void componentComplete() override;
-
- QVariant model() const;
- void setModel(const QVariant &);
-
- QQmlComponent *delegate() const;
- void setDelegate(QQmlComponent *);
-
- QVariant rootIndex() const;
- void setRootIndex(const QVariant &root);
-
- Q_INVOKABLE QVariant modelIndex(int idx) const;
- Q_INVOKABLE QVariant parentModelIndex() const;
-
- int count() const override;
- bool isValid() const override { return delegate() != nullptr; }
- QObject *object(int index, QQmlIncubator::IncubationMode incubationMode = QQmlIncubator::AsynchronousIfNested) override;
- ReleaseFlags release(QObject *object) override;
- void cancel(int index) override;
- QVariant variantValue(int index, const QString &role) override;
- void setWatchedRoles(const QList<QByteArray> &roles) override;
- QQmlIncubator::Status incubationStatus(int index) override;
-
- int indexOf(QObject *object, QObject *objectContext) const override;
-
- QString filterGroup() const;
- void setFilterGroup(const QString &group);
- void resetFilterGroup();
-
- QQmlDelegateModelGroup *items();
- QQmlDelegateModelGroup *persistedItems();
- QQmlListProperty<QQmlDelegateModelGroup> groups();
- QObject *parts();
-
- const QAbstractItemModel *abstractItemModel() const override;
-
- bool event(QEvent *) override;
-
- static QQmlDelegateModelAttached *qmlAttachedProperties(QObject *obj);
-
-Q_SIGNALS:
- void filterGroupChanged();
- void defaultGroupsChanged();
- void rootIndexChanged();
-
-private Q_SLOTS:
- void _q_itemsChanged(int index, int count, const QVector<int> &roles);
- void _q_itemsInserted(int index, int count);
- void _q_itemsRemoved(int index, int count);
- void _q_itemsMoved(int from, int to, int count);
- void _q_modelReset();
- void _q_rowsInserted(const QModelIndex &,int,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);
- void _q_dataChanged(const QModelIndex&,const QModelIndex&,const QVector<int> &);
- void _q_layoutChanged(const QList<QPersistentModelIndex>&, QAbstractItemModel::LayoutChangeHint);
-
-private:
- bool isDescendantOf(const QPersistentModelIndex &desc, const QList<QPersistentModelIndex> &parents) const;
-
- Q_DISABLE_COPY(QQmlDelegateModel)
-};
-
-class QQmlDelegateModelGroupPrivate;
-class Q_QML_PRIVATE_EXPORT QQmlDelegateModelGroup : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(int count READ count NOTIFY countChanged)
- Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
- Q_PROPERTY(bool includeByDefault READ defaultInclude WRITE setDefaultInclude NOTIFY defaultIncludeChanged)
-public:
- QQmlDelegateModelGroup(QObject *parent = nullptr);
- QQmlDelegateModelGroup(const QString &name, QQmlDelegateModel *model, int compositorType, QObject *parent = nullptr);
- ~QQmlDelegateModelGroup();
-
- QString name() const;
- void setName(const QString &name);
-
- int count() const;
-
- bool defaultInclude() const;
- void setDefaultInclude(bool include);
-
- Q_INVOKABLE QJSValue get(int index);
-
-public Q_SLOTS:
- void insert(QQmlV4Function *);
- void create(QQmlV4Function *);
- void resolve(QQmlV4Function *);
- void remove(QQmlV4Function *);
- void addGroups(QQmlV4Function *);
- void removeGroups(QQmlV4Function *);
- void setGroups(QQmlV4Function *);
- void move(QQmlV4Function *);
-
-Q_SIGNALS:
- void countChanged();
- void nameChanged();
- void defaultIncludeChanged();
- void changed(const QJSValue &removed, const QJSValue &inserted);
-private:
- Q_DECLARE_PRIVATE(QQmlDelegateModelGroup)
-};
-
-class QQmlDelegateModelItem;
-class QQmlDelegateModelAttachedMetaObject;
-class QQmlDelegateModelAttached : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(QQmlDelegateModel *model READ model CONSTANT)
- Q_PROPERTY(QStringList groups READ groups WRITE setGroups NOTIFY groupsChanged)
- Q_PROPERTY(bool isUnresolved READ isUnresolved NOTIFY unresolvedChanged)
-public:
- QQmlDelegateModelAttached(QObject *parent);
- QQmlDelegateModelAttached(QQmlDelegateModelItem *cacheItem, QObject *parent);
- ~QQmlDelegateModelAttached() {}
-
- void resetCurrentIndex();
- void setCacheItem(QQmlDelegateModelItem *item);
-
- QQmlDelegateModel *model() const;
-
- QStringList groups() const;
- void setGroups(const QStringList &groups);
-
- bool isUnresolved() const;
-
- void emitChanges();
-
- void emitUnresolvedChanged() { Q_EMIT unresolvedChanged(); }
-
-Q_SIGNALS:
- void groupsChanged();
- void unresolvedChanged();
-
-public:
- QQmlDelegateModelItem *m_cacheItem;
- int m_previousGroups;
- int m_currentIndex[QQmlListCompositor::MaximumGroupCount];
- int m_previousIndex[QQmlListCompositor::MaximumGroupCount];
-
- friend class QQmlDelegateModelAttachedMetaObject;
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQmlDelegateModel)
-QML_DECLARE_TYPEINFO(QQmlDelegateModel, QML_HAS_ATTACHED_PROPERTIES)
-QML_DECLARE_TYPE(QQmlDelegateModelGroup)
-
-#endif // QQMLDATAMODEL_P_H
diff --git a/src/qml/types/qqmldelegatemodel_p_p.h b/src/qml/types/qqmldelegatemodel_p_p.h
deleted file mode 100644
index 7f10bbf370..0000000000
--- a/src/qml/types/qqmldelegatemodel_p_p.h
+++ /dev/null
@@ -1,450 +0,0 @@
-/****************************************************************************
-**
-** 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 QQMLDATAMODEL_P_P_H
-#define QQMLDATAMODEL_P_P_H
-
-#include "qqmldelegatemodel_p.h"
-#include <private/qv4qobjectwrapper_p.h>
-
-#include <QtQml/qqmlcontext.h>
-#include <QtQml/qqmlincubator.h>
-
-#include <private/qqmladaptormodel_p.h>
-#include <private/qqmlopenmetaobject_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.
-//
-
-QT_REQUIRE_CONFIG(qml_delegate_model);
-
-QT_BEGIN_NAMESPACE
-
-typedef QQmlListCompositor Compositor;
-
-class QQmlDelegateModelAttachedMetaObject;
-class QQmlAbstractDelegateComponent;
-
-class Q_QML_PRIVATE_EXPORT QQmlDelegateModelItemMetaType : public QQmlRefCount
-{
-public:
- QQmlDelegateModelItemMetaType(QV4::ExecutionEngine *engine, QQmlDelegateModel *model, const QStringList &groupNames);
- ~QQmlDelegateModelItemMetaType();
-
- void initializeMetaObject();
- void initializePrototype();
-
- int parseGroups(const QStringList &groupNames) const;
- int parseGroups(const QV4::Value &groupNames) const;
-
- QPointer<QQmlDelegateModel> model;
- const int groupCount;
- QV4::ExecutionEngine * const v4Engine;
- QQmlDelegateModelAttachedMetaObject *metaObject;
- const QStringList groupNames;
- QV4::PersistentValue modelItemProto;
-};
-
-class QQmlAdaptorModel;
-class QQDMIncubationTask;
-
-class QQmlDelegateModelItem : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(int index READ modelIndex NOTIFY modelIndexChanged)
- Q_PROPERTY(int row READ modelRow NOTIFY rowChanged REVISION 12)
- Q_PROPERTY(int column READ modelColumn NOTIFY columnChanged REVISION 12)
- Q_PROPERTY(QObject *model READ modelObject CONSTANT)
-public:
- QQmlDelegateModelItem(QQmlDelegateModelItemMetaType *metaType,
- QQmlAdaptorModel::Accessors *accessor, int modelIndex,
- int row, int column);
- ~QQmlDelegateModelItem();
-
- void referenceObject() { ++objectRef; }
- bool releaseObject() { return --objectRef == 0 && !(groups & Compositor::PersistedFlag); }
- bool isObjectReferenced() const { return objectRef != 0 || (groups & Compositor::PersistedFlag); }
- void childContextObjectDestroyed(QObject *childContextObject);
-
- bool isReferenced() const {
- return scriptRef
- || incubationTask
- || ((groups & Compositor::UnresolvedFlag) && (groups & Compositor::GroupMask));
- }
-
- void Dispose();
-
- QObject *modelObject() { return this; }
-
- void destroyObject();
-
- static QQmlDelegateModelItem *dataForObject(QObject *object);
-
- int groupIndex(Compositor::Group group);
-
- int modelRow() const { return row; }
- int modelColumn() const { return column; }
- int modelIndex() const { return index; }
- virtual void setModelIndex(int idx, int newRow, int newColumn);
-
- virtual QV4::ReturnedValue get() { return QV4::QObjectWrapper::wrap(v4, this); }
-
- virtual void setValue(const QString &role, const QVariant &value) { Q_UNUSED(role); Q_UNUSED(value); }
- virtual bool resolveIndex(const QQmlAdaptorModel &, int) { return false; }
-
- static QV4::ReturnedValue get_model(const QV4::FunctionObject *, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
- static QV4::ReturnedValue get_groups(const QV4::FunctionObject *, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
- static QV4::ReturnedValue set_groups(const QV4::FunctionObject *, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
- static QV4::ReturnedValue get_member(QQmlDelegateModelItem *thisItem, uint flag, const QV4::Value &);
- static QV4::ReturnedValue set_member(QQmlDelegateModelItem *thisItem, uint flag, const QV4::Value &arg);
- static QV4::ReturnedValue get_index(QQmlDelegateModelItem *thisItem, uint flag, const QV4::Value &arg);
-
- QV4::ExecutionEngine *v4;
- QQmlDelegateModelItemMetaType * const metaType;
- QQmlContextDataRef contextData;
- QPointer<QObject> object;
- QPointer<QQmlDelegateModelAttached> attached;
- QQDMIncubationTask *incubationTask;
- QQmlComponent *delegate;
- int poolTime;
- int objectRef;
- int scriptRef;
- int groups;
- int index;
-
-Q_SIGNALS:
- void modelIndexChanged();
- Q_REVISION(12) void rowChanged();
- Q_REVISION(12) void columnChanged();
-
-protected:
- void objectDestroyed(QObject *);
- int row;
- int column;
-};
-
-namespace QV4 {
-namespace Heap {
-struct QQmlDelegateModelItemObject : Object {
- inline void init(QQmlDelegateModelItem *item);
- void destroy();
- QQmlDelegateModelItem *item;
-};
-
-}
-}
-
-struct QQmlDelegateModelItemObject : QV4::Object
-{
- V4_OBJECT2(QQmlDelegateModelItemObject, QV4::Object)
- V4_NEEDS_DESTROY
-};
-
-void QV4::Heap::QQmlDelegateModelItemObject::init(QQmlDelegateModelItem *item)
-{
- Object::init();
- this->item = item;
-}
-
-
-
-class QQmlDelegateModelPrivate;
-class QQDMIncubationTask : public QQmlIncubator
-{
-public:
- QQDMIncubationTask(QQmlDelegateModelPrivate *l, IncubationMode mode)
- : QQmlIncubator(mode)
- , incubating(nullptr)
- , vdm(l) {}
-
- void statusChanged(Status) override;
- void setInitialState(QObject *) override;
-
- QQmlDelegateModelItem *incubating = nullptr;
- QQmlDelegateModelPrivate *vdm = nullptr;
- int index[QQmlListCompositor::MaximumGroupCount];
-};
-
-
-class QQmlDelegateModelGroupEmitter
-{
-public:
- virtual ~QQmlDelegateModelGroupEmitter() {}
- virtual void emitModelUpdated(const QQmlChangeSet &changeSet, bool reset) = 0;
- virtual void createdPackage(int, QQuickPackage *) {}
- virtual void initPackage(int, QQuickPackage *) {}
- virtual void destroyingPackage(QQuickPackage *) {}
-
- QIntrusiveListNode emitterNode;
-};
-
-typedef QIntrusiveList<QQmlDelegateModelGroupEmitter, &QQmlDelegateModelGroupEmitter::emitterNode> QQmlDelegateModelGroupEmitterList;
-
-class QQmlDelegateModelGroupPrivate : public QObjectPrivate
-{
-public:
- Q_DECLARE_PUBLIC(QQmlDelegateModelGroup)
-
- QQmlDelegateModelGroupPrivate() : group(Compositor::Cache), defaultInclude(false) {}
-
- static QQmlDelegateModelGroupPrivate *get(QQmlDelegateModelGroup *group) {
- return static_cast<QQmlDelegateModelGroupPrivate *>(QObjectPrivate::get(group)); }
-
- void setModel(QQmlDelegateModel *model, Compositor::Group group);
- bool isChangedConnected();
- void emitChanges(QV4::ExecutionEngine *engine);
- void emitModelUpdated(bool reset);
-
- void createdPackage(int index, QQuickPackage *package);
- void initPackage(int index, QQuickPackage *package);
- void destroyingPackage(QQuickPackage *package);
-
- bool parseIndex(const QV4::Value &value, int *index, Compositor::Group *group) const;
- bool parseGroupArgs(
- QQmlV4Function *args, Compositor::Group *group, int *index, int *count, int *groups) const;
-
- Compositor::Group group;
- QPointer<QQmlDelegateModel> model;
- QQmlDelegateModelGroupEmitterList emitters;
- QQmlChangeSet changeSet;
- QString name;
- bool defaultInclude;
-};
-
-class QQmlDelegateModelParts;
-
-class QQmlDelegateModelPrivate : public QObjectPrivate, public QQmlDelegateModelGroupEmitter
-{
- Q_DECLARE_PUBLIC(QQmlDelegateModel)
-public:
- QQmlDelegateModelPrivate(QQmlContext *);
- ~QQmlDelegateModelPrivate();
-
- static QQmlDelegateModelPrivate *get(QQmlDelegateModel *m) {
- return static_cast<QQmlDelegateModelPrivate *>(QObjectPrivate::get(m));
- }
-
- void init();
- void connectModel(QQmlAdaptorModel *model);
- void connectToAbstractItemModel();
- void disconnectFromAbstractItemModel();
-
- void requestMoreIfNecessary();
- QObject *object(Compositor::Group group, int index, QQmlIncubator::IncubationMode incubationMode);
- QQmlDelegateModel::ReleaseFlags release(QObject *object);
- QVariant variantValue(Compositor::Group group, int index, const QString &name);
- void emitCreatedPackage(QQDMIncubationTask *incubationTask, QQuickPackage *package);
- void emitInitPackage(QQDMIncubationTask *incubationTask, QQuickPackage *package);
- void emitCreatedItem(QQDMIncubationTask *incubationTask, QObject *item) {
- Q_EMIT q_func()->createdItem(incubationTask->index[m_compositorGroup], item); }
- void emitInitItem(QQDMIncubationTask *incubationTask, QObject *item) {
- Q_EMIT q_func()->initItem(incubationTask->index[m_compositorGroup], item); }
- void emitDestroyingPackage(QQuickPackage *package);
- void emitDestroyingItem(QObject *item) { Q_EMIT q_func()->destroyingItem(item); }
- void addCacheItem(QQmlDelegateModelItem *item, Compositor::iterator it);
- void removeCacheItem(QQmlDelegateModelItem *cacheItem);
-
- void updateFilterGroup();
-
- void addGroups(Compositor::iterator from, int count, Compositor::Group group, int groupFlags);
- void removeGroups(Compositor::iterator from, int count, Compositor::Group group, int groupFlags);
- void setGroups(Compositor::iterator from, int count, Compositor::Group group, int groupFlags);
-
- void itemsInserted(
- const QVector<Compositor::Insert> &inserts,
- QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> *translatedInserts,
- QHash<int, QList<QQmlDelegateModelItem *> > *movedItems = nullptr);
- void itemsInserted(const QVector<Compositor::Insert> &inserts);
- void itemsRemoved(
- const QVector<Compositor::Remove> &removes,
- QVarLengthArray<QVector<QQmlChangeSet::Change>, Compositor::MaximumGroupCount> *translatedRemoves,
- QHash<int, QList<QQmlDelegateModelItem *> > *movedItems = nullptr);
- void itemsRemoved(const QVector<Compositor::Remove> &removes);
- void itemsMoved(
- const QVector<Compositor::Remove> &removes, const QVector<Compositor::Insert> &inserts);
- void itemsChanged(const QVector<Compositor::Change> &changes);
- void emitChanges();
- void emitModelUpdated(const QQmlChangeSet &changeSet, bool reset) override;
- void delegateChanged(bool add = true, bool remove = true);
-
- bool insert(Compositor::insert_iterator &before, const QV4::Value &object, int groups);
-
- int adaptorModelCount() const;
-
- static void group_append(QQmlListProperty<QQmlDelegateModelGroup> *property, QQmlDelegateModelGroup *group);
- static int group_count(QQmlListProperty<QQmlDelegateModelGroup> *property);
- static QQmlDelegateModelGroup *group_at(QQmlListProperty<QQmlDelegateModelGroup> *property, int index);
-
- void releaseIncubator(QQDMIncubationTask *incubationTask);
- void incubatorStatusChanged(QQDMIncubationTask *incubationTask, QQmlIncubator::Status status);
- void setInitialState(QQDMIncubationTask *incubationTask, QObject *o);
-
- QQmlAdaptorModel m_adaptorModel;
- QQmlListCompositor m_compositor;
- QQmlStrongJSQObjectReference<QQmlComponent> m_delegate;
- QQmlAbstractDelegateComponent *m_delegateChooser;
- QMetaObject::Connection m_delegateChooserChanged;
- QQmlDelegateModelItemMetaType *m_cacheMetaType;
- QPointer<QQmlContext> m_context;
- QQmlDelegateModelParts *m_parts;
- QQmlDelegateModelGroupEmitterList m_pendingParts;
-
- QList<QQmlDelegateModelItem *> m_cache;
- QList<QQDMIncubationTask *> m_finishedIncubating;
- QList<QByteArray> m_watchedRoles;
-
- QString m_filterGroup;
-
- int m_count;
- int m_groupCount;
-
- QQmlListCompositor::Group m_compositorGroup;
- bool m_complete : 1;
- bool m_delegateValidated : 1;
- bool m_reset : 1;
- bool m_transaction : 1;
- bool m_incubatorCleanupScheduled : 1;
- bool m_waitingToFetchMore : 1;
-
- union {
- struct {
- QQmlDelegateModelGroup *m_cacheItems;
- QQmlDelegateModelGroup *m_items;
- QQmlDelegateModelGroup *m_persistedItems;
- };
- QQmlDelegateModelGroup *m_groups[Compositor::MaximumGroupCount];
- };
-};
-
-class QQmlPartsModel : public QQmlInstanceModel, public QQmlDelegateModelGroupEmitter
-{
- Q_OBJECT
- Q_PROPERTY(QString filterOnGroup READ filterGroup WRITE setFilterGroup NOTIFY filterGroupChanged RESET resetFilterGroup)
-public:
- QQmlPartsModel(QQmlDelegateModel *model, const QString &part, QObject *parent = nullptr);
- ~QQmlPartsModel();
-
- QString filterGroup() const;
- void setFilterGroup(const QString &group);
- void resetFilterGroup();
- void updateFilterGroup();
- void updateFilterGroup(Compositor::Group group, const QQmlChangeSet &changeSet);
-
- int count() const override;
- bool isValid() const override;
- QObject *object(int index, QQmlIncubator::IncubationMode incubationMode = QQmlIncubator::AsynchronousIfNested) override;
- ReleaseFlags release(QObject *item) override;
- QVariant variantValue(int index, const QString &role) override;
- QList<QByteArray> watchedRoles() const { return m_watchedRoles; }
- void setWatchedRoles(const QList<QByteArray> &roles) override;
- QQmlIncubator::Status incubationStatus(int index) override;
-
- int indexOf(QObject *item, QObject *objectContext) const override;
-
- void emitModelUpdated(const QQmlChangeSet &changeSet, bool reset) override;
-
- void createdPackage(int index, QQuickPackage *package) override;
- void initPackage(int index, QQuickPackage *package) override;
- void destroyingPackage(QQuickPackage *package) override;
-
-Q_SIGNALS:
- void filterGroupChanged();
-
-private:
- QQmlDelegateModel *m_model;
- QHash<QObject *, QQuickPackage *> m_packaged;
- QString m_part;
- QString m_filterGroup;
- QList<QByteArray> m_watchedRoles;
- QVector<int> m_pendingPackageInitializations; // vector holds model indices
- Compositor::Group m_compositorGroup;
- bool m_inheritGroup;
- bool m_modelUpdatePending = true;
-};
-
-class QMetaPropertyBuilder;
-
-class QQmlDelegateModelPartsMetaObject : public QQmlOpenMetaObject
-{
-public:
- QQmlDelegateModelPartsMetaObject(QObject *parent)
- : QQmlOpenMetaObject(parent) {}
-
- void propertyCreated(int, QMetaPropertyBuilder &) override;
- QVariant initialValue(int) override;
-};
-
-class QQmlDelegateModelParts : public QObject
-{
-Q_OBJECT
-public:
- QQmlDelegateModelParts(QQmlDelegateModel *parent);
-
- QQmlDelegateModel *model;
- QList<QQmlPartsModel *> models;
-};
-
-class QQmlDelegateModelAttachedMetaObject : public QAbstractDynamicMetaObject, public QQmlRefCount
-{
-public:
- QQmlDelegateModelAttachedMetaObject(
- QQmlDelegateModelItemMetaType *metaType, QMetaObject *metaObject);
- ~QQmlDelegateModelAttachedMetaObject();
-
- void objectDestroyed(QObject *) override;
- int metaCall(QObject *, QMetaObject::Call, int _id, void **) override;
-
-private:
- QQmlDelegateModelItemMetaType * const metaType;
- QMetaObject * const metaObject;
- const int memberPropertyOffset;
- const int indexPropertyOffset;
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/qml/types/qqmlinstantiator.cpp b/src/qml/types/qqmlinstantiator.cpp
deleted file mode 100644
index a23ec0f2b4..0000000000
--- a/src/qml/types/qqmlinstantiator.cpp
+++ /dev/null
@@ -1,509 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Research In Motion.
-** 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 "qqmlinstantiator_p.h"
-#include "qqmlinstantiator_p_p.h"
-#include <QtQml/QQmlContext>
-#include <QtQml/QQmlComponent>
-#include <QtQml/QQmlInfo>
-#include <QtQml/QQmlError>
-#include <QtQml/private/qqmlobjectmodel_p.h>
-#if QT_CONFIG(qml_delegate_model)
-#include <QtQml/private/qqmldelegatemodel_p.h>
-#endif
-
-QT_BEGIN_NAMESPACE
-
-QQmlInstantiatorPrivate::QQmlInstantiatorPrivate()
- : componentComplete(true)
- , effectiveReset(false)
- , active(true)
- , async(false)
-#if QT_CONFIG(qml_delegate_model)
- , ownModel(false)
-#endif
- , requestedIndex(-1)
- , model(QVariant(1))
- , instanceModel(nullptr)
- , delegate(nullptr)
-{
-}
-
-QQmlInstantiatorPrivate::~QQmlInstantiatorPrivate()
-{
- qDeleteAll(objects);
-}
-
-void QQmlInstantiatorPrivate::clear()
-{
- Q_Q(QQmlInstantiator);
- if (!instanceModel)
- return;
- if (!objects.count())
- return;
-
- for (int i=0; i < objects.count(); i++) {
- q->objectRemoved(i, objects[i]);
- instanceModel->release(objects[i]);
- }
- objects.clear();
- q->objectChanged();
-}
-
-QObject *QQmlInstantiatorPrivate::modelObject(int index, bool async)
-{
- requestedIndex = index;
- QObject *o = instanceModel->object(index, async ? QQmlIncubator::Asynchronous : QQmlIncubator::AsynchronousIfNested);
- requestedIndex = -1;
- return o;
-}
-
-
-void QQmlInstantiatorPrivate::regenerate()
-{
- Q_Q(QQmlInstantiator);
- if (!componentComplete)
- return;
-
- int prevCount = q->count();
-
- clear();
-
- if (!active || !instanceModel || !instanceModel->count() || !instanceModel->isValid()) {
- if (prevCount)
- q->countChanged();
- return;
- }
-
- for (int i = 0; i < instanceModel->count(); i++) {
- QObject *object = modelObject(i, async);
- // If the item was already created we won't get a createdItem
- if (object)
- _q_createdItem(i, object);
- }
- if (q->count() != prevCount)
- q->countChanged();
-}
-
-void QQmlInstantiatorPrivate::_q_createdItem(int idx, QObject* item)
-{
- Q_Q(QQmlInstantiator);
- if (objects.contains(item)) //Case when it was created synchronously in regenerate
- return;
- if (requestedIndex != idx) // Asynchronous creation, reference the object
- (void)instanceModel->object(idx);
- item->setParent(q);
- if (objects.size() < idx + 1) {
- int modelCount = instanceModel->count();
- if (objects.capacity() < modelCount)
- objects.reserve(modelCount);
- objects.resize(idx + 1);
- }
- if (QObject *o = objects.at(idx))
- instanceModel->release(o);
- objects.replace(idx, item);
- if (objects.count() == 1)
- q->objectChanged();
- q->objectAdded(idx, item);
-}
-
-void QQmlInstantiatorPrivate::_q_modelUpdated(const QQmlChangeSet &changeSet, bool reset)
-{
- Q_Q(QQmlInstantiator);
-
- if (!componentComplete || effectiveReset)
- return;
-
- if (reset) {
- regenerate();
- if (changeSet.difference() != 0)
- q->countChanged();
- return;
- }
-
- int difference = 0;
- QHash<int, QVector<QPointer<QObject> > > moved;
- const QVector<QQmlChangeSet::Change> &removes = changeSet.removes();
- for (const QQmlChangeSet::Change &remove : removes) {
- int index = qMin(remove.index, objects.count());
- int count = qMin(remove.index + remove.count, objects.count()) - index;
- if (remove.isMove()) {
- moved.insert(remove.moveId, objects.mid(index, count));
- objects.erase(
- objects.begin() + index,
- objects.begin() + index + count);
- } else while (count--) {
- QObject *obj = objects.at(index);
- objects.remove(index);
- q->objectRemoved(index, obj);
- if (obj)
- instanceModel->release(obj);
- }
-
- difference -= remove.count;
- }
-
- const QVector<QQmlChangeSet::Change> &inserts = changeSet.inserts();
- for (const QQmlChangeSet::Change &insert : inserts) {
- int index = qMin(insert.index, objects.count());
- if (insert.isMove()) {
- QVector<QPointer<QObject> > movedObjects = moved.value(insert.moveId);
- objects = objects.mid(0, index) + movedObjects + objects.mid(index);
- } else {
- if (insert.index <= objects.size())
- objects.insert(insert.index, insert.count, nullptr);
- for (int i = 0; i < insert.count; ++i) {
- int modelIndex = index + i;
- QObject* obj = modelObject(modelIndex, async);
- if (obj)
- _q_createdItem(modelIndex, obj);
- }
- }
- difference += insert.count;
- }
-
- if (difference != 0)
- q->countChanged();
-}
-
-#if QT_CONFIG(qml_delegate_model)
-void QQmlInstantiatorPrivate::makeModel()
-{
- Q_Q(QQmlInstantiator);
- QQmlDelegateModel* delegateModel = new QQmlDelegateModel(qmlContext(q), q);
- instanceModel = delegateModel;
- ownModel = true;
- delegateModel->setDelegate(delegate);
- delegateModel->classBegin(); //Pretend it was made in QML
- if (componentComplete)
- delegateModel->componentComplete();
-}
-#endif
-
-
-/*!
- \qmltype Instantiator
- \instantiates QQmlInstantiator
- \inqmlmodule QtQml
- \brief Dynamically creates objects.
-
- A Instantiator can be used to control the dynamic creation of objects, or to dynamically
- create multiple objects from a template.
-
- The Instantiator element will manage the objects it creates. Those objects are parented to the
- Instantiator and can also be deleted by the Instantiator if the Instantiator's properties change. Objects
- can also be destroyed dynamically through other means, and the Instantiator will not recreate
- them unless the properties of the Instantiator change.
-
-*/
-QQmlInstantiator::QQmlInstantiator(QObject *parent)
- : QObject(*(new QQmlInstantiatorPrivate), parent)
-{
-}
-
-QQmlInstantiator::~QQmlInstantiator()
-{
-}
-
-/*!
- \qmlsignal QtQml::Instantiator::objectAdded(int index, QtObject object)
-
- This signal is emitted when an object is added to the Instantiator. The \a index
- parameter holds the index which the object has been given, and the \a object
- parameter holds the \l QtObject that has been added.
-
- The corresponding handler is \c onObjectAdded.
-*/
-
-/*!
- \qmlsignal QtQml::Instantiator::objectRemoved(int index, QtObject object)
-
- This signal is emitted when an object is removed from the Instantiator. The \a index
- parameter holds the index which the object had been given, and the \a object
- parameter holds the \l QtObject that has been removed.
-
- Do not keep a reference to \a object if it was created by this Instantiator, as
- in these cases it will be deleted shortly after the signal is handled.
-
- The corresponding handler is \c onObjectRemoved.
-*/
-/*!
- \qmlproperty bool QtQml::Instantiator::active
-
- When active is true, and the delegate component is ready, the Instantiator will
- create objects according to the model. When active is false, no objects
- will be created and any previously created objects will be destroyed.
-
- Default is true.
-*/
-bool QQmlInstantiator::isActive() const
-{
- Q_D(const QQmlInstantiator);
- return d->active;
-}
-
-void QQmlInstantiator::setActive(bool newVal)
-{
- Q_D(QQmlInstantiator);
- if (newVal == d->active)
- return;
- d->active = newVal;
- emit activeChanged();
- d->regenerate();
-}
-
-/*!
- \qmlproperty bool QtQml::Instantiator::asynchronous
-
- When asynchronous is true the Instantiator will attempt to create objects
- asynchronously. This means that objects may not be available immediately,
- even if active is set to true.
-
- You can use the objectAdded signal to respond to items being created.
-
- Default is false.
-*/
-bool QQmlInstantiator::isAsync() const
-{
- Q_D(const QQmlInstantiator);
- return d->async;
-}
-
-void QQmlInstantiator::setAsync(bool newVal)
-{
- Q_D(QQmlInstantiator);
- if (newVal == d->async)
- return;
- d->async = newVal;
- emit asynchronousChanged();
-}
-
-
-/*!
- \qmlproperty int QtQml::Instantiator::count
-
- The number of objects the Instantiator is currently managing.
-*/
-
-int QQmlInstantiator::count() const
-{
- Q_D(const QQmlInstantiator);
- return d->objects.count();
-}
-
-/*!
- \qmlproperty QtQml::Component QtQml::Instantiator::delegate
- \default
-
- The component used to create all objects.
-
- Note that an extra variable, index, will be available inside instances of the
- delegate. This variable refers to the index of the instance inside the Instantiator,
- and can be used to obtain the object through the objectAt method of the Instantiator.
-
- If this property is changed, all instances using the old delegate will be destroyed
- and new instances will be created using the new delegate.
-*/
-QQmlComponent* QQmlInstantiator::delegate()
-{
- Q_D(QQmlInstantiator);
- return d->delegate;
-}
-
-void QQmlInstantiator::setDelegate(QQmlComponent* c)
-{
- Q_D(QQmlInstantiator);
- if (c == d->delegate)
- return;
-
- d->delegate = c;
- emit delegateChanged();
-
-#if QT_CONFIG(qml_delegate_model)
- if (!d->ownModel)
- return;
-
- if (QQmlDelegateModel *dModel = qobject_cast<QQmlDelegateModel*>(d->instanceModel))
- dModel->setDelegate(c);
- if (d->componentComplete)
- d->regenerate();
-#endif
-}
-
-/*!
- \qmlproperty variant QtQml::Instantiator::model
-
- This property can be set to any of the supported \l {qml-data-models}{data models}:
-
- \list
- \li A number that indicates the number of delegates to be created by the repeater
- \li A model (e.g. a ListModel item, or a QAbstractItemModel subclass)
- \li A string list
- \li An object list
- \endlist
-
- The type of model affects the properties that are exposed to the \l delegate.
-
- Default value is 1, which creates a single delegate instance.
-
- \sa {qml-data-models}{Data Models}
-*/
-
-QVariant QQmlInstantiator::model() const
-{
- Q_D(const QQmlInstantiator);
- return d->model;
-}
-
-void QQmlInstantiator::setModel(const QVariant &v)
-{
- Q_D(QQmlInstantiator);
- if (d->model == v)
- return;
-
- d->model = v;
- //Don't actually set model until componentComplete in case it wants to create its delegates immediately
- if (!d->componentComplete)
- return;
-
- QQmlInstanceModel *prevModel = d->instanceModel;
- QObject *object = qvariant_cast<QObject*>(v);
- QQmlInstanceModel *vim = nullptr;
- if (object && (vim = qobject_cast<QQmlInstanceModel *>(object))) {
-#if QT_CONFIG(qml_delegate_model)
- if (d->ownModel) {
- delete d->instanceModel;
- prevModel = nullptr;
- d->ownModel = false;
- }
-#endif
- d->instanceModel = vim;
-#if QT_CONFIG(qml_delegate_model)
- } else if (v != QVariant(0)){
- if (!d->ownModel)
- d->makeModel();
-
- if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel *>(d->instanceModel)) {
- d->effectiveReset = true;
- dataModel->setModel(v);
- d->effectiveReset = false;
- }
-#endif
- }
-
- if (d->instanceModel != prevModel) {
- if (prevModel) {
- disconnect(prevModel, SIGNAL(modelUpdated(QQmlChangeSet,bool)),
- this, SLOT(_q_modelUpdated(QQmlChangeSet,bool)));
- disconnect(prevModel, SIGNAL(createdItem(int,QObject*)), this, SLOT(_q_createdItem(int,QObject*)));
- //disconnect(prevModel, SIGNAL(initItem(int,QObject*)), this, SLOT(initItem(int,QObject*)));
- }
-
- if (d->instanceModel) {
- connect(d->instanceModel, SIGNAL(modelUpdated(QQmlChangeSet,bool)),
- this, SLOT(_q_modelUpdated(QQmlChangeSet,bool)));
- connect(d->instanceModel, SIGNAL(createdItem(int,QObject*)), this, SLOT(_q_createdItem(int,QObject*)));
- //connect(d->instanceModel, SIGNAL(initItem(int,QObject*)), this, SLOT(initItem(int,QObject*)));
- }
- }
-
- d->regenerate();
- emit modelChanged();
-}
-
-/*!
- \qmlproperty QtObject QtQml::Instantiator::object
-
- This is a reference to the first created object, intended as a convenience
- for the case where only one object has been created.
-*/
-QObject *QQmlInstantiator::object() const
-{
- Q_D(const QQmlInstantiator);
- if (d->objects.count())
- return d->objects[0];
- return nullptr;
-}
-
-/*!
- \qmlmethod QtObject QtQml::Instantiator::objectAt(int index)
-
- Returns a reference to the object with the given \a index.
-*/
-QObject *QQmlInstantiator::objectAt(int index) const
-{
- Q_D(const QQmlInstantiator);
- if (index >= 0 && index < d->objects.count())
- return d->objects[index];
- return nullptr;
-}
-
-/*!
- \internal
-*/
-void QQmlInstantiator::classBegin()
-{
- Q_D(QQmlInstantiator);
- d->componentComplete = false;
-}
-
-/*!
- \internal
-*/
-void QQmlInstantiator::componentComplete()
-{
- Q_D(QQmlInstantiator);
- d->componentComplete = true;
-#if QT_CONFIG(qml_delegate_model)
- if (d->ownModel) {
- static_cast<QQmlDelegateModel*>(d->instanceModel)->componentComplete();
- d->regenerate();
- } else
-#endif
- {
- QVariant realModel = d->model;
- d->model = QVariant(0);
- setModel(realModel); //If realModel == d->model this won't do anything, but that's fine since the model's 0
- //setModel calls regenerate
- }
-}
-
-QT_END_NAMESPACE
-
-#include "moc_qqmlinstantiator_p.cpp"
diff --git a/src/qml/types/qqmlinstantiator_p.h b/src/qml/types/qqmlinstantiator_p.h
deleted file mode 100644
index ca371adc23..0000000000
--- a/src/qml/types/qqmlinstantiator_p.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Research In Motion.
-** 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 QQMLINSTANTIATOR_P_H
-#define QQMLINSTANTIATOR_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 <QtQml/qqmlcomponent.h>
-#include <QtQml/qqmlparserstatus.h>
-#include <QtQml/private/qtqmlglobal_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QQmlInstantiatorPrivate;
-class Q_QML_PRIVATE_EXPORT QQmlInstantiator : public QObject, public QQmlParserStatus
-{
- Q_OBJECT
- Q_INTERFACES(QQmlParserStatus)
-
- Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged)
- Q_PROPERTY(bool asynchronous READ isAsync WRITE setAsync NOTIFY asynchronousChanged)
- Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged)
- Q_PROPERTY(int count READ count NOTIFY countChanged)
- Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
- Q_PROPERTY(QObject *object READ object NOTIFY objectChanged)
- Q_CLASSINFO("DefaultProperty", "delegate")
-
-public:
- QQmlInstantiator(QObject *parent = nullptr);
- ~QQmlInstantiator();
-
- bool isActive() const;
- void setActive(bool newVal);
-
- bool isAsync() const;
- void setAsync(bool newVal);
-
- int count() const;
-
- QQmlComponent* delegate();
- void setDelegate(QQmlComponent* c);
-
- QVariant model() const;
- void setModel(const QVariant &v);
-
- QObject *object() const;
-
- Q_INVOKABLE QObject *objectAt(int index) const;
-
- void classBegin() override;
- void componentComplete() override;
-
-Q_SIGNALS:
- void modelChanged();
- void delegateChanged();
- void countChanged();
- void objectChanged();
- void activeChanged();
- void asynchronousChanged();
-
- void objectAdded(int index, QObject* object);
- void objectRemoved(int index, QObject* object);
-
-private:
- Q_DISABLE_COPY(QQmlInstantiator)
- Q_DECLARE_PRIVATE(QQmlInstantiator)
- Q_PRIVATE_SLOT(d_func(), void _q_createdItem(int, QObject *))
- Q_PRIVATE_SLOT(d_func(), void _q_modelUpdated(const QQmlChangeSet &, bool))
-};
-
-QT_END_NAMESPACE
-
-#endif // QQMLCREATOR_P_H
diff --git a/src/qml/types/qqmlinstantiator_p_p.h b/src/qml/types/qqmlinstantiator_p_p.h
deleted file mode 100644
index 4c76d5c689..0000000000
--- a/src/qml/types/qqmlinstantiator_p_p.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Research In Motion.
-** 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 QQMLINSTANTIATOR_P_P_H
-#define QQMLINSTANTIATOR_P_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 "qqmlinstantiator_p.h"
-#include <QObject>
-#include <private/qobject_p.h>
-#include <private/qqmlchangeset_p.h>
-#include <private/qqmlobjectmodel_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class Q_QML_PRIVATE_EXPORT QQmlInstantiatorPrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QQmlInstantiator)
-
-public:
- QQmlInstantiatorPrivate();
- ~QQmlInstantiatorPrivate();
-
- void clear();
- void regenerate();
-#if QT_CONFIG(qml_delegate_model)
- void makeModel();
-#endif
- void _q_createdItem(int, QObject *);
- void _q_modelUpdated(const QQmlChangeSet &, bool);
- QObject *modelObject(int index, bool async);
-
- static QQmlInstantiatorPrivate *get(QQmlInstantiator *instantiator) { return instantiator->d_func(); }
- static const QQmlInstantiatorPrivate *get(const QQmlInstantiator *instantiator) { return instantiator->d_func(); }
-
- bool componentComplete:1;
- bool effectiveReset:1;
- bool active:1;
- bool async:1;
-#if QT_CONFIG(qml_delegate_model)
- bool ownModel:1;
-#endif
- int requestedIndex;
- QVariant model;
- QQmlInstanceModel *instanceModel;
- QQmlComponent *delegate;
- QVector<QPointer<QObject> > objects;
-};
-
-QT_END_NAMESPACE
-
-#endif // QQMLCREATOR_P_P_H
diff --git a/src/qml/types/qqmlitemmodels.qdoc b/src/qml/types/qqmlitemmodels.qdoc
deleted file mode 100644
index f6e1b0b1b9..0000000000
--- a/src/qml/types/qqmlitemmodels.qdoc
+++ /dev/null
@@ -1,110 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** 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 Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/*!
- \page qmodelindex-and-related-classes-in-qml.html
- \title QModelIndex and related Classes in QML
-
- Since Qt 5.5, QModelIndex and QPersistentModelIndex are exposed in QML as
- value-based types. Also exposed in a similar fashion are QModelIndexList,
- QItemSelectionRange and QItemSelection. All objects from these types can
- be passed back and forth between QML and C++ as \c var properties or plain
- JavaScript variables.
-
- Below you will find an overview of the API exposed to QML for these classes.
- For more information, refer to their C++ documentation.
-
- \note Since all these types are exposed as \l{Q_GADGET}{gadgets}, there are no property
- change notification signals emitted. Therefore binding to their properties
- may not give the expected results. This is especially true for QPersistentModelIndex.
-
- \section1 QModelIndex and QPersistentModelIndex Types
-
- \list
- \li \b row : int
- \li \b column : int
- \li \b parent : QModelIndex
- \li \b valid : bool
- \li \b model : QAbstractItemModel
- \li \b internalId : quint64
- \endlist
-
- All these properties are read-only, as are their C++ counterparts.
-
- \note The usual caveats apply to QModelIndex in QML. If the underlying model changes
- or gets deleted, it may become dangerous to access its properties. Therefore, you
- should not store any QModelIndex objects. You can, however, store QPersistentModelIndexe
- objects in a safe way.
-
- \section1 QModelIndexList Type
-
- \l QModelIndexList is exposed in QML as a JavaScript array. Conversions are
- automatically made from and to C++. In fact, any JavaScript array can be
- converted back to QModelIndexList, with non-QModelIndex objects replaced by
- invalid \l{QModelIndex}es.
-
- \note QModelIndex to QPersistentModelIndex conversion happens when accessing
- the array elements because any QModelIndexList property retains reference
- semantics when exposed this way.
-
- \section1 \l QItemSelectionRange Type
-
- \list
- \li \b top : int
- \li \b left : int
- \li \b bottom : int
- \li \b right : int
- \li \b width : int
- \li \b height : int
- \li \b topLeft : QPersistentModelIndex
- \li \b bottomRight : QPersistentModelIndex
- \li \b parent : QModelIndex
- \li \b valid : bool
- \li \b empty : bool
- \li \b model : QAbstractItemModel
- \endlist
-
- All these properties are read-only, as are their C++ counterparts. In addition,
- we also expose the following functions:
-
- \list
- \li bool \b{contains}(QModelIndex \e index)
- \li bool \b{contains}(int \e row, int \e column, QModelIndex \e parentIndex)
- \li bool \b{intersects}(QItemSelectionRange \e other)
- \li QItemSelectionRange \b{intersected}(QItemSelectionRange \e other)
- \endlist
-
- \section1 QItemSelection Type
-
- Similarly to QModelIndexList, \l QItemSelection is exposed in QML as a JavaScript
- array of QItemSelectionRange objects. Conversions are automatically made from and to C++.
- In fact, any JavaScript array can be converted back to QItemSelection, with
- non-QItemSelectionRange objects replaced by empty \l {QItemSelectionRange}s.
-
-
- \sa ItemSelectionModel
-*/
diff --git a/src/qml/types/qqmlitemselectionmodel.qdoc b/src/qml/types/qqmlitemselectionmodel.qdoc
deleted file mode 100644
index 43da4f7a55..0000000000
--- a/src/qml/types/qqmlitemselectionmodel.qdoc
+++ /dev/null
@@ -1,239 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:FDL$
-** 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 Free Documentation License Usage
-** Alternatively, this file may be used under the terms of the GNU Free
-** Documentation License version 1.3 as published by the Free Software
-** Foundation and appearing in the file included in the packaging of
-** this file. Please review the following information to ensure
-** the GNU Free Documentation License version 1.3 requirements
-** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-/*!
- \qmltype ItemSelectionModel
- \instantiates QItemSelectionModel
- \inqmlmodule QtQml.Models
- \since 5.5
- \ingroup qtquick-models
-
- \brief Instantiates a QItemSelectionModel to be used in conjunction
- with a QAbstractItemModel and any view supporting it.
-
- \sa QItemSelectionModel, {Models and Views in Qt Quick}
-*/
-
-
-/*!
- \qmlproperty QAbstractItemModel ItemSelectionModel::model
-
- This property's value must match the view's model.
-*/
-
-/*!
- \qmlproperty bool ItemSelectionModel::hasSelection
- \readonly
-
- It will trigger property binding updates every time \l selectionChanged()
- is emitted, even though its value hasn't changed.
-
- \sa selection, selectedIndexes, select(), selectionChanged()
-*/
-
-/*!
- \qmlproperty QModelIndex ItemSelectionModel::currentIndex
- \readonly
-
- Use \l setCurrentIndex() to set its value.
-
- \sa setCurrentIndex(), currentChanged()
-*/
-
-/*!
- \qmlproperty QModelIndexList ItemSelectionModel::selectedIndexes
- \readonly
-
- Contains the list of all the indexes in the selection model.
-*/
-
-/*!
- \qmlmethod bool ItemSelectionModel::isSelected(QModelIndex index)
-
- Returns \c true if the given model item \a index is selected.
-*/
-
-/*!
- \qmlmethod bool ItemSelectionModel::isRowSelected(int row, QModelIndex parent)
-
- Returns \c true if all items are selected in the \a row with the given
- \a parent.
-
- Note that this function is usually faster than calling isSelected()
- on all items in the same row, and that unselectable items are ignored.
-*/
-
-/*!
- \qmlmethod bool ItemSelectionModel::isColumnSelected(int column, QModelIndex parent)
-
- Returns \c true if all items are selected in the \a column with the given
- \a parent.
-
- Note that this function is usually faster than calling isSelected()
- on all items in the same column, and that unselectable items are ignored.
-*/
-
-/*!
- \qmlmethod bool ItemSelectionModel::rowIntersectsSelection(int row, QModelIndex parent)
-
- Returns \c true if there are any items selected in the \a row with the
- given \a parent.
-*/
-
-/*!
- \qmlmethod bool ItemSelectionModel::columnIntersectsSelection(int column, QModelIndex parent)
-
- Returns \c true if there are any items selected in the \a column with the
- given \a parent.
-*/
-
-/*!
- \qmlmethod QModelIndexList ItemSelectionModel::selectedRows(int column)
-
- Returns the indexes in the given \a column for the rows where all columns
- are selected.
-
- \sa selectedColumns()
-*/
-
-/*!
- \qmlmethod QModelIndexList ItemSelectionModel::selectedColumns(int row)
-
- Returns the indexes in the given \a row for columns where all rows are
- selected.
-
- \sa selectedRows()
-*/
-
-/*!
- \qmlproperty object ItemSelectionModel::selection
- \readonly
-
- Holds the selection ranges stored in the selection model.
-*/
-
-/*!
- \qmlmethod void ItemSelectionModel::setCurrentIndex(QModelIndex index, SelectionFlags command)
-
- Sets the model item \a index to be the current item, and emits
- currentChanged(). The current item is used for keyboard navigation and
- focus indication; it is independent of any selected items, although a
- selected item can also be the current item.
-
- Depending on the specified \a command, the \a index can also become part
- of the current selection.
-
- Valid \a command values are described in \l {itemselectionmodelselectindex}
- {select(\e index, \e command)}.
-
- \sa select()
-*/
-
-/*!
- \qmlmethod void ItemSelectionModel::select(QModelIndex index, SelectionFlags command)
- \keyword itemselectionmodelselectindex
-
- Selects the model item \a index using the specified \a command, and emits
- selectionChanged().
-
- Valid values for the \a command parameter, are:
-
- \value NoUpdate No selection will be made.
- \value Clear The complete selection will be cleared.
- \value Select All specified indexes will be selected.
- \value Deselect All specified indexes will be deselected.
- \value Toggle All specified indexes will be selected or
- deselected depending on their current state.
- \value Current The current selection will be updated.
- \value Rows All indexes will be expanded to span rows.
- \value Columns All indexes will be expanded to span columns.
- \value SelectCurrent A combination of Select and Current, provided for
- convenience.
- \value ToggleCurrent A combination of Toggle and Current, provided for
- convenience.
- \value ClearAndSelect A combination of Clear and Select, provided for
- convenience.
-*/
-
-/*!
- \qmlmethod void ItemSelectionModel::select(QItemSelection selection, SelectionFlags command)
-
- Selects the item \a selection using the specified \a command, and emits
- selectionChanged().
-
- Valid \a command values are described in \l {itemselectionmodelselectindex}
- {select(\e index, \e command)}.
-*/
-
-/*!
- \qmlmethod void ItemSelectionModel::clear()
-
- Clears the selection model. Emits selectionChanged() and currentChanged().
-*/
-
-/*!
- \qmlmethod void ItemSelectionModel::reset()
-
- Clears the selection model. Does not emit any signals.
-*/
-
-/*!
- \qmlmethod void ItemSelectionModel::clearSelection()
-
- Clears the selection in the selection model. Emits selectionChanged().
-*/
-
-/*!
- \qmlmethod void ItemSelectionModel::clearCurrentIndex()
-
- Clears the current index. Emits currentChanged().
-*/
-
-/*!
- \qmlsignal ItemSelectionModel::selectionChanged(QItemSelection selected, QItemSelection deselected)
-
- This signal is emitted whenever the selection changes. The change in the
- selection is represented as an item selection of \a deselected items and
- an item selection of \a selected items.
-
- Note the that the current index changes independently from the selection.
- Also note that this signal will not be emitted when the item model is reset.
-
- \sa select(), currentChanged()
-*/
-
-/*!
- \qmlsignal ItemSelectionModel::currentChanged(QModelIndex current, QModelIndex previous)
-
- This signal is emitted whenever the current item changes. The \a previous
- model item index is replaced by the \a current index as the selection's
- current item.
-
- Note that this signal will not be emitted when the item model is reset.
-
- \sa currentIndex, setCurrentIndex(), selectionChanged()
-*/
diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp
deleted file mode 100644
index 5b5bcd8464..0000000000
--- a/src/qml/types/qqmllistmodel.cpp
+++ /dev/null
@@ -1,2900 +0,0 @@
-/****************************************************************************
-**
-** 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 "qqmllistmodel_p_p.h"
-#include "qqmllistmodelworkeragent_p.h"
-#include <private/qqmlopenmetaobject_p.h>
-#include <private/qqmljsast_p.h>
-#include <private/qqmljsengine_p.h>
-#include <private/qjsvalue_p.h>
-
-#include <private/qqmlcustomparser_p.h>
-#include <private/qqmlengine_p.h>
-#include <private/qqmlnotifier_p.h>
-
-#include <private/qv4object_p.h>
-#include <private/qv4dateobject_p.h>
-#include <private/qv4objectiterator_p.h>
-#include <private/qv4alloca_p.h>
-#include <private/qv4lookup_p.h>
-
-#include <qqmlcontext.h>
-#include <qqmlinfo.h>
-
-#include <QtCore/qdebug.h>
-#include <QtCore/qstack.h>
-#include <QXmlStreamReader>
-#include <QtCore/qdatetime.h>
-#include <QScopedValueRollback>
-
-Q_DECLARE_METATYPE(const QV4::CompiledData::Binding*);
-
-QT_BEGIN_NAMESPACE
-
-// Set to 1024 as a debugging aid - easier to distinguish uids from indices of elements/models.
-enum { MIN_LISTMODEL_UID = 1024 };
-
-static QAtomicInt uidCounter(MIN_LISTMODEL_UID);
-
-template <typename T>
-static bool isMemoryUsed(const char *mem)
-{
- for (size_t i=0 ; i < sizeof(T) ; ++i) {
- if (mem[i] != 0)
- return true;
- }
-
- return false;
-}
-
-static QString roleTypeName(ListLayout::Role::DataType t)
-{
- static const QString roleTypeNames[] = {
- QStringLiteral("String"), QStringLiteral("Number"), QStringLiteral("Bool"),
- QStringLiteral("List"), QStringLiteral("QObject"), QStringLiteral("VariantMap"),
- QStringLiteral("DateTime"), QStringLiteral("Function")
- };
-
- if (t > ListLayout::Role::Invalid && t < ListLayout::Role::MaxDataType)
- return roleTypeNames[t];
-
- return QString();
-}
-
-const ListLayout::Role &ListLayout::getRoleOrCreate(const QString &key, Role::DataType type)
-{
- QStringHash<Role *>::Node *node = roleHash.findNode(key);
- if (node) {
- const Role &r = *node->value;
- if (type != r.type)
- qmlWarning(nullptr) << QStringLiteral("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(r.name).arg(roleTypeName(type)).arg(roleTypeName(r.type));
- return r;
- }
-
- return createRole(key, type);
-}
-
-const ListLayout::Role &ListLayout::getRoleOrCreate(QV4::String *key, Role::DataType type)
-{
- QStringHash<Role *>::Node *node = roleHash.findNode(key);
- if (node) {
- const Role &r = *node->value;
- if (type != r.type)
- qmlWarning(nullptr) << QStringLiteral("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(r.name).arg(roleTypeName(type)).arg(roleTypeName(r.type));
- return r;
- }
-
- QString qkey = key->toQString();
-
- return createRole(qkey, type);
-}
-
-const ListLayout::Role &ListLayout::createRole(const QString &key, ListLayout::Role::DataType type)
-{
- const int dataSizes[] = { sizeof(StringOrTranslation), sizeof(double), sizeof(bool), sizeof(ListModel *), sizeof(QPointer<QObject>), sizeof(QVariantMap), sizeof(QDateTime), sizeof(QJSValue) };
- const int dataAlignments[] = { sizeof(StringOrTranslation), sizeof(double), sizeof(bool), sizeof(ListModel *), sizeof(QObject *), sizeof(QVariantMap), sizeof(QDateTime), sizeof(QJSValue) };
-
- Role *r = new Role;
- r->name = key;
- r->type = type;
-
- if (type == Role::List) {
- r->subLayout = new ListLayout;
- } else {
- r->subLayout = nullptr;
- }
-
- int dataSize = dataSizes[type];
- int dataAlignment = dataAlignments[type];
-
- int dataOffset = (currentBlockOffset + dataAlignment-1) & ~(dataAlignment-1);
- if (dataOffset + dataSize > ListElement::BLOCK_SIZE) {
- r->blockIndex = ++currentBlock;
- r->blockOffset = 0;
- currentBlockOffset = dataSize;
- } else {
- r->blockIndex = currentBlock;
- r->blockOffset = dataOffset;
- currentBlockOffset = dataOffset + dataSize;
- }
-
- int roleIndex = roles.count();
- r->index = roleIndex;
-
- roles.append(r);
- roleHash.insert(key, r);
-
- return *r;
-}
-
-ListLayout::ListLayout(const ListLayout *other) : currentBlock(0), currentBlockOffset(0)
-{
- const int otherRolesCount = other->roles.count();
- roles.reserve(otherRolesCount);
- for (int i=0 ; i < otherRolesCount; ++i) {
- Role *role = new Role(other->roles[i]);
- roles.append(role);
- roleHash.insert(role->name, role);
- }
- currentBlockOffset = other->currentBlockOffset;
- currentBlock = other->currentBlock;
-}
-
-ListLayout::~ListLayout()
-{
- qDeleteAll(roles);
-}
-
-void ListLayout::sync(ListLayout *src, ListLayout *target)
-{
- int roleOffset = target->roles.count();
- int newRoleCount = src->roles.count() - roleOffset;
-
- for (int i=0 ; i < newRoleCount ; ++i) {
- Role *role = new Role(src->roles[roleOffset + i]);
- target->roles.append(role);
- target->roleHash.insert(role->name, role);
- }
-
- target->currentBlockOffset = src->currentBlockOffset;
- target->currentBlock = src->currentBlock;
-}
-
-ListLayout::Role::Role(const Role *other)
-{
- name = other->name;
- type = other->type;
- blockIndex = other->blockIndex;
- blockOffset = other->blockOffset;
- index = other->index;
- if (other->subLayout)
- subLayout = new ListLayout(other->subLayout);
- else
- subLayout = nullptr;
-}
-
-ListLayout::Role::~Role()
-{
- delete subLayout;
-}
-
-const ListLayout::Role *ListLayout::getRoleOrCreate(const QString &key, const QVariant &data)
-{
- Role::DataType type;
-
- switch (data.type()) {
- case QVariant::Double: type = Role::Number; break;
- case QVariant::Int: type = Role::Number; break;
- case QVariant::Bool: type = Role::Bool; break;
- case QVariant::String: type = Role::String; break;
- case QVariant::Map: type = Role::VariantMap; break;
- case QVariant::DateTime: type = Role::DateTime; break;
- case QVariant::UserType: {
- if (data.userType() == qMetaTypeId<QJSValue>() &&
- data.value<QJSValue>().isCallable()) {
- type = Role::Function;
- break;
- } else if (data.userType() == qMetaTypeId<const QV4::CompiledData::Binding*>()
- && data.value<const QV4::CompiledData::Binding*>()->isTranslationBinding()) {
- type = Role::String;
- break;
- } else {
- type = Role::List;
- break;
- }
- }
- default: type = Role::Invalid; break;
- }
-
- if (type == Role::Invalid) {
- qmlWarning(nullptr) << "Can't create role for unsupported data type";
- return nullptr;
- }
-
- return &getRoleOrCreate(key, type);
-}
-
-const ListLayout::Role *ListLayout::getExistingRole(const QString &key) const
-{
- Role *r = nullptr;
- QStringHash<Role *>::Node *node = roleHash.findNode(key);
- if (node)
- r = node->value;
- return r;
-}
-
-const ListLayout::Role *ListLayout::getExistingRole(QV4::String *key) const
-{
- Role *r = nullptr;
- QStringHash<Role *>::Node *node = roleHash.findNode(key);
- if (node)
- r = node->value;
- return r;
-}
-
-StringOrTranslation::StringOrTranslation(const QString &s)
-{
- d.setFlag();
- setString(s);
-}
-
-StringOrTranslation::StringOrTranslation(const QV4::CompiledData::Binding *binding)
-{
- d.setFlag();
- clear();
- d = binding;
-}
-
-StringOrTranslation::~StringOrTranslation()
-{
- clear();
-}
-
-void StringOrTranslation::setString(const QString &s)
-{
- d.setFlag();
- clear();
- QStringData *stringData = const_cast<QString &>(s).data_ptr();
- d = stringData;
- if (stringData)
- stringData->ref.ref();
-}
-
-void StringOrTranslation::setTranslation(const QV4::CompiledData::Binding *binding)
-{
- d.setFlag();
- clear();
- d = binding;
-}
-
-QString StringOrTranslation::toString(const QQmlListModel *owner) const
-{
- if (d.isNull())
- return QString();
- if (d.isT1()) {
- QStringDataPtr holder = { d.asT1() };
- holder.ptr->ref.ref();
- return QString(holder);
- }
- if (!owner)
- return QString();
- return d.asT2()->valueAsString(owner->m_compilationUnit.data());
-}
-
-QString StringOrTranslation::asString() const
-{
- if (d.isNull())
- return QString();
- if (!d.isT1())
- return QString();
- QStringDataPtr holder = { d.asT1() };
- holder.ptr->ref.ref();
- return QString(holder);
-}
-
-void StringOrTranslation::clear()
-{
- if (QStringData *strData = d.isT1() ? d.asT1() : nullptr) {
- if (!strData->ref.deref())
- QStringData::deallocate(strData);
- }
- d = static_cast<QStringData *>(nullptr);
-}
-
-QObject *ListModel::getOrCreateModelObject(QQmlListModel *model, int elementIndex)
-{
- ListElement *e = elements[elementIndex];
- if (e->m_objectCache == nullptr) {
- void *memory = operator new(sizeof(QObject) + sizeof(QQmlData));
- void *ddataMemory = ((char *)memory) + sizeof(QObject);
- e->m_objectCache = new (memory) QObject;
- QQmlData *ddata = new (ddataMemory) QQmlData;
- ddata->ownMemory = false;
- QObjectPrivate::get(e->m_objectCache)->declarativeData = ddata;
- (void)new ModelNodeMetaObject(e->m_objectCache, model, elementIndex);
- }
- return e->m_objectCache;
-}
-
-bool ListModel::sync(ListModel *src, ListModel *target)
-{
- // Sanity check
-
- bool hasChanges = false;
-
- // Build hash of elements <-> uid for each of the lists
- QHash<int, ElementSync> elementHash;
- for (int i = 0; i < target->elements.count(); ++i) {
- ListElement *e = target->elements.at(i);
- int uid = e->getUid();
- ElementSync sync;
- sync.target = e;
- sync.targetIndex = i;
- elementHash.insert(uid, sync);
- }
- for (int i = 0; i < src->elements.count(); ++i) {
- ListElement *e = src->elements.at(i);
- int uid = e->getUid();
-
- QHash<int, ElementSync>::iterator it = elementHash.find(uid);
- if (it == elementHash.end()) {
- ElementSync sync;
- sync.src = e;
- sync.srcIndex = i;
- elementHash.insert(uid, sync);
- } else {
- ElementSync &sync = it.value();
- sync.src = e;
- sync.srcIndex = i;
- }
- }
-
- QQmlListModel *targetModel = target->m_modelCache;
-
- // Get list of elements that are in the target but no longer in the source. These get deleted first.
- int rowsRemoved = 0;
- for (int i = 0 ; i < target->elements.count() ; ++i) {
- ListElement *element = target->elements.at(i);
- ElementSync &s = elementHash.find(element->getUid()).value();
- Q_ASSERT(s.targetIndex >= 0);
- // need to update the targetIndex, to keep it correct after removals
- s.targetIndex -= rowsRemoved;
- if (s.src == nullptr) {
- Q_ASSERT(s.targetIndex == i);
- hasChanges = true;
- if (targetModel)
- targetModel->beginRemoveRows(QModelIndex(), i, i);
- s.target->destroy(target->m_layout);
- target->elements.removeOne(s.target);
- delete s.target;
- if (targetModel)
- targetModel->endRemoveRows();
- ++rowsRemoved;
- --i;
- continue;
- }
- }
-
- // Sync the layouts
- ListLayout::sync(src->m_layout, target->m_layout);
-
- // Clear the target list, and append in correct order from the source
- target->elements.clear();
- for (int i = 0; i < src->elements.count(); ++i) {
- ListElement *srcElement = src->elements.at(i);
- ElementSync &s = elementHash.find(srcElement->getUid()).value();
- Q_ASSERT(s.srcIndex >= 0);
- ListElement *targetElement = s.target;
- if (targetElement == nullptr) {
- targetElement = new ListElement(srcElement->getUid());
- }
- s.changedRoles = ListElement::sync(srcElement, src->m_layout, targetElement, target->m_layout);
- target->elements.append(targetElement);
- }
-
- target->updateCacheIndices();
-
- // Update values stored in target meta objects
- for (int i=0 ; i < target->elements.count() ; ++i) {
- ListElement *e = target->elements[i];
- if (ModelNodeMetaObject *mo = e->objectCache())
- mo->updateValues();
- }
-
- // now emit the change notifications required. This can be safely done, as we're only emitting changes, moves and inserts,
- // so the model indices can't be out of bounds
- //
- // to ensure things are kept in the correct order, emit inserts and moves first. This shouls ensure all persistent
- // model indices are updated correctly
- int rowsInserted = 0;
- for (int i = 0 ; i < target->elements.count() ; ++i) {
- ListElement *element = target->elements.at(i);
- ElementSync &s = elementHash.find(element->getUid()).value();
- Q_ASSERT(s.srcIndex >= 0);
- s.srcIndex += rowsInserted;
- if (s.srcIndex != s.targetIndex) {
- if (targetModel) {
- if (s.targetIndex == -1) {
- targetModel->beginInsertRows(QModelIndex(), i, i);
- targetModel->endInsertRows();
- } else {
- targetModel->beginMoveRows(QModelIndex(), i, i, QModelIndex(), s.srcIndex);
- targetModel->endMoveRows();
- }
- }
- hasChanges = true;
- ++rowsInserted;
- }
- if (s.targetIndex != -1 && !s.changedRoles.isEmpty()) {
- QModelIndex idx = targetModel->createIndex(i, 0);
- if (targetModel)
- targetModel->dataChanged(idx, idx, s.changedRoles);
- hasChanges = true;
- }
- }
- return hasChanges;
-}
-
-ListModel::ListModel(ListLayout *layout, QQmlListModel *modelCache) : m_layout(layout), m_modelCache(modelCache)
-{
-}
-
-void ListModel::destroy()
-{
- for (const auto &destroyer : remove(0, elements.count()))
- destroyer();
-
- m_layout = nullptr;
- if (m_modelCache && m_modelCache->m_primary == false)
- delete m_modelCache;
- m_modelCache = nullptr;
-}
-
-int ListModel::appendElement()
-{
- int elementIndex = elements.count();
- newElement(elementIndex);
- return elementIndex;
-}
-
-void ListModel::insertElement(int index)
-{
- newElement(index);
- updateCacheIndices(index);
-}
-
-void ListModel::move(int from, int to, int n)
-{
- if (from > to) {
- // Only move forwards - flip if backwards moving
- int tfrom = from;
- int tto = to;
- from = tto;
- to = tto+n;
- n = tfrom-tto;
- }
-
- QPODVector<ListElement *, 4> store;
- for (int i=0 ; i < (to-from) ; ++i)
- store.append(elements[from+n+i]);
- for (int i=0 ; i < n ; ++i)
- store.append(elements[from+i]);
- for (int i=0 ; i < store.count() ; ++i)
- elements[from+i] = store[i];
-
- updateCacheIndices(from, to + n);
-}
-
-void ListModel::newElement(int index)
-{
- ListElement *e = new ListElement;
- elements.insert(index, e);
-}
-
-void ListModel::updateCacheIndices(int start, int end)
-{
- int count = elements.count();
-
- if (end < 0 || end > count)
- end = count;
-
- for (int i = start; i < end; ++i) {
- ListElement *e = elements.at(i);
- if (ModelNodeMetaObject *mo = e->objectCache())
- mo->m_elementIndex = i;
- }
-}
-
-QVariant ListModel::getProperty(int elementIndex, int roleIndex, const QQmlListModel *owner, QV4::ExecutionEngine *eng)
-{
- if (roleIndex >= m_layout->roleCount())
- return QVariant();
- ListElement *e = elements[elementIndex];
- const ListLayout::Role &r = m_layout->getExistingRole(roleIndex);
- return e->getProperty(r, owner, eng);
-}
-
-ListModel *ListModel::getListProperty(int elementIndex, const ListLayout::Role &role)
-{
- ListElement *e = elements[elementIndex];
- return e->getListProperty(role);
-}
-
-void ListModel::set(int elementIndex, QV4::Object *object, QVector<int> *roles)
-{
- ListElement *e = elements[elementIndex];
-
- QV4::ExecutionEngine *v4 = object->engine();
- QV4::Scope scope(v4);
- QV4::ScopedObject o(scope);
-
- QV4::ObjectIterator it(scope, object, QV4::ObjectIterator::EnumerableOnly);
- QV4::ScopedString propertyName(scope);
- QV4::ScopedValue propertyValue(scope);
- while (1) {
- propertyName = it.nextPropertyNameAsString(propertyValue);
- if (!propertyName)
- break;
-
- // Check if this key exists yet
- int roleIndex = -1;
-
- // Add the value now
- if (const QV4::String *s = propertyValue->as<QV4::String>()) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::String);
- roleIndex = e->setStringProperty(r, s->toQString());
- } else if (propertyValue->isNumber()) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Number);
- roleIndex = e->setDoubleProperty(r, propertyValue->asDouble());
- } else if (QV4::ArrayObject *a = propertyValue->as<QV4::ArrayObject>()) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::List);
- ListModel *subModel = new ListModel(r.subLayout, nullptr);
-
- int arrayLength = a->getLength();
- for (int j=0 ; j < arrayLength ; ++j) {
- o = a->get(j);
- subModel->append(o);
- }
-
- roleIndex = e->setListProperty(r, subModel);
- } else if (propertyValue->isBoolean()) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Bool);
- roleIndex = e->setBoolProperty(r, propertyValue->booleanValue());
- } else if (QV4::DateObject *dd = propertyValue->as<QV4::DateObject>()) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::DateTime);
- QDateTime dt = dd->toQDateTime();
- roleIndex = e->setDateTimeProperty(r, dt);
- } else if (QV4::FunctionObject *f = propertyValue->as<QV4::FunctionObject>()) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Function);
- QV4::ScopedFunctionObject func(scope, f);
- QJSValue jsv;
- QJSValuePrivate::setValue(&jsv, v4, func);
- 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);
- } else {
- const ListLayout::Role &role = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::VariantMap);
- if (role.type == ListLayout::Role::VariantMap) {
- QV4::ScopedObject obj(scope, o);
- roleIndex = e->setVariantMapProperty(role, obj);
- }
- }
- } else if (propertyValue->isNullOrUndefined()) {
- const ListLayout::Role *r = m_layout->getExistingRole(propertyName);
- if (r)
- e->clearProperty(*r);
- }
-
- if (roleIndex != -1)
- roles->append(roleIndex);
- }
-
- if (ModelNodeMetaObject *mo = e->objectCache())
- mo->updateValues(*roles);
-}
-
-void ListModel::set(int elementIndex, QV4::Object *object)
-{
- if (!object)
- return;
-
- ListElement *e = elements[elementIndex];
-
- QV4::ExecutionEngine *v4 = object->engine();
- QV4::Scope scope(v4);
-
- QV4::ObjectIterator it(scope, object, QV4::ObjectIterator::EnumerableOnly);
- QV4::ScopedString propertyName(scope);
- QV4::ScopedValue propertyValue(scope);
- QV4::ScopedObject o(scope);
- while (1) {
- propertyName = it.nextPropertyNameAsString(propertyValue);
- if (!propertyName)
- break;
-
- // Add the value now
- if (QV4::String *s = propertyValue->stringValue()) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::String);
- if (r.type == ListLayout::Role::String)
- e->setStringPropertyFast(r, s->toQString());
- } else if (propertyValue->isNumber()) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Number);
- if (r.type == ListLayout::Role::Number) {
- e->setDoublePropertyFast(r, propertyValue->asDouble());
- }
- } else if (QV4::ArrayObject *a = propertyValue->as<QV4::ArrayObject>()) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::List);
- if (r.type == ListLayout::Role::List) {
- ListModel *subModel = new ListModel(r.subLayout, nullptr);
-
- int arrayLength = a->getLength();
- for (int j=0 ; j < arrayLength ; ++j) {
- o = a->get(j);
- subModel->append(o);
- }
-
- e->setListPropertyFast(r, subModel);
- }
- } else if (propertyValue->isBoolean()) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::Bool);
- if (r.type == ListLayout::Role::Bool) {
- e->setBoolPropertyFast(r, propertyValue->booleanValue());
- }
- } else if (QV4::DateObject *date = propertyValue->as<QV4::DateObject>()) {
- const ListLayout::Role &r = m_layout->getRoleOrCreate(propertyName, ListLayout::Role::DateTime);
- if (r.type == ListLayout::Role::DateTime) {
- QDateTime dt = date->toQDateTime();;
- e->setDateTimePropertyFast(r, dt);
- }
- } 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);
- } else {
- 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()) {
- const ListLayout::Role *r = m_layout->getExistingRole(propertyName);
- if (r)
- e->clearProperty(*r);
- }
- }
-}
-
-QVector<std::function<void()>> ListModel::remove(int index, int count)
-{
- QVector<std::function<void()>> toDestroy;
- auto layout = m_layout;
- for (int i=0 ; i < count ; ++i) {
- auto element = elements[index+i];
- toDestroy.append([element, layout](){
- element->destroy(layout);
- delete element;
- });
- }
- elements.remove(index, count);
- updateCacheIndices(index);
- return toDestroy;
-}
-
-void ListModel::insert(int elementIndex, QV4::Object *object)
-{
- insertElement(elementIndex);
- set(elementIndex, object);
-}
-
-int ListModel::append(QV4::Object *object)
-{
- int elementIndex = appendElement();
- set(elementIndex, object);
- return elementIndex;
-}
-
-int ListModel::setOrCreateProperty(int elementIndex, const QString &key, const QVariant &data)
-{
- int roleIndex = -1;
-
- if (elementIndex >= 0 && elementIndex < elements.count()) {
- ListElement *e = elements[elementIndex];
-
- const ListLayout::Role *r = m_layout->getRoleOrCreate(key, data);
- if (r) {
- roleIndex = e->setVariantProperty(*r, data);
-
- ModelNodeMetaObject *cache = e->objectCache();
-
- if (roleIndex != -1 && cache)
- cache->updateValues(QVector<int>(1, roleIndex));
- }
- }
-
- return roleIndex;
-}
-
-int ListModel::setExistingProperty(int elementIndex, const QString &key, const QV4::Value &data, QV4::ExecutionEngine *eng)
-{
- int roleIndex = -1;
-
- if (elementIndex >= 0 && elementIndex < elements.count()) {
- ListElement *e = elements[elementIndex];
- const ListLayout::Role *r = m_layout->getExistingRole(key);
- if (r)
- roleIndex = e->setJsProperty(*r, data, eng);
- }
-
- return roleIndex;
-}
-
-inline char *ListElement::getPropertyMemory(const ListLayout::Role &role)
-{
- ListElement *e = this;
- int blockIndex = 0;
- while (blockIndex < role.blockIndex) {
- if (e->next == nullptr) {
- e->next = new ListElement;
- e->next->uid = uid;
- }
- e = e->next;
- ++blockIndex;
- }
-
- char *mem = &e->data[role.blockOffset];
- return mem;
-}
-
-ModelNodeMetaObject *ListElement::objectCache()
-{
- if (!m_objectCache)
- return nullptr;
- return ModelNodeMetaObject::get(m_objectCache);
-}
-
-StringOrTranslation *ListElement::getStringProperty(const ListLayout::Role &role)
-{
- char *mem = getPropertyMemory(role);
- StringOrTranslation *s = reinterpret_cast<StringOrTranslation *>(mem);
- return s;
-}
-
-QObject *ListElement::getQObjectProperty(const ListLayout::Role &role)
-{
- char *mem = getPropertyMemory(role);
- QPointer<QObject> *o = reinterpret_cast<QPointer<QObject> *>(mem);
- return o->data();
-}
-
-QVariantMap *ListElement::getVariantMapProperty(const ListLayout::Role &role)
-{
- QVariantMap *map = nullptr;
-
- char *mem = getPropertyMemory(role);
- if (isMemoryUsed<QVariantMap>(mem))
- map = reinterpret_cast<QVariantMap *>(mem);
-
- return map;
-}
-
-QDateTime *ListElement::getDateTimeProperty(const ListLayout::Role &role)
-{
- QDateTime *dt = nullptr;
-
- char *mem = getPropertyMemory(role);
- if (isMemoryUsed<QDateTime>(mem))
- dt = reinterpret_cast<QDateTime *>(mem);
-
- return dt;
-}
-
-QJSValue *ListElement::getFunctionProperty(const ListLayout::Role &role)
-{
- QJSValue *f = nullptr;
-
- char *mem = getPropertyMemory(role);
- if (isMemoryUsed<QJSValue>(mem))
- f = reinterpret_cast<QJSValue *>(mem);
-
- return f;
-}
-
-QPointer<QObject> *ListElement::getGuardProperty(const ListLayout::Role &role)
-{
- char *mem = getPropertyMemory(role);
-
- bool existingGuard = false;
- for (size_t i=0 ; i < sizeof(QPointer<QObject>) ; ++i) {
- if (mem[i] != 0) {
- existingGuard = true;
- break;
- }
- }
-
- QPointer<QObject> *o = nullptr;
-
- if (existingGuard)
- o = reinterpret_cast<QPointer<QObject> *>(mem);
-
- return o;
-}
-
-ListModel *ListElement::getListProperty(const ListLayout::Role &role)
-{
- char *mem = getPropertyMemory(role);
- ListModel **value = reinterpret_cast<ListModel **>(mem);
- return *value;
-}
-
-QVariant ListElement::getProperty(const ListLayout::Role &role, const QQmlListModel *owner, QV4::ExecutionEngine *eng)
-{
- char *mem = getPropertyMemory(role);
-
- QVariant data;
-
- switch (role.type) {
- case ListLayout::Role::Number:
- {
- double *value = reinterpret_cast<double *>(mem);
- data = *value;
- }
- break;
- case ListLayout::Role::String:
- {
- StringOrTranslation *value = reinterpret_cast<StringOrTranslation *>(mem);
- if (value->isSet())
- data = value->toString(owner);
- }
- break;
- case ListLayout::Role::Bool:
- {
- bool *value = reinterpret_cast<bool *>(mem);
- data = *value;
- }
- break;
- case ListLayout::Role::List:
- {
- ListModel **value = reinterpret_cast<ListModel **>(mem);
- ListModel *model = *value;
-
- if (model) {
- if (model->m_modelCache == nullptr) {
- model->m_modelCache = new QQmlListModel(owner, model, eng);
- QQmlEngine::setContextForObject(model->m_modelCache, QQmlEngine::contextForObject(owner));
- }
-
- QObject *object = model->m_modelCache;
- data = QVariant::fromValue(object);
- }
- }
- break;
- case ListLayout::Role::QObject:
- {
- QPointer<QObject> *guard = reinterpret_cast<QPointer<QObject> *>(mem);
- QObject *object = guard->data();
- if (object)
- data = QVariant::fromValue(object);
- }
- break;
- case ListLayout::Role::VariantMap:
- {
- if (isMemoryUsed<QVariantMap>(mem)) {
- QVariantMap *map = reinterpret_cast<QVariantMap *>(mem);
- data = *map;
- }
- }
- break;
- case ListLayout::Role::DateTime:
- {
- if (isMemoryUsed<QDateTime>(mem)) {
- QDateTime *dt = reinterpret_cast<QDateTime *>(mem);
- data = *dt;
- }
- }
- break;
- case ListLayout::Role::Function:
- {
- if (isMemoryUsed<QJSValue>(mem)) {
- QJSValue *func = reinterpret_cast<QJSValue *>(mem);
- data = QVariant::fromValue(*func);
- }
- }
- break;
- default:
- break;
- }
-
- return data;
-}
-
-int ListElement::setStringProperty(const ListLayout::Role &role, const QString &s)
-{
- int roleIndex = -1;
-
- if (role.type == ListLayout::Role::String) {
- char *mem = getPropertyMemory(role);
- StringOrTranslation *c = reinterpret_cast<StringOrTranslation *>(mem);
- bool changed;
- if (!c->isSet() || c->isTranslation())
- changed = true;
- else
- changed = c->asString().compare(s) != 0;
- c->setString(s);
- if (changed)
- roleIndex = role.index;
- }
-
- return roleIndex;
-}
-
-int ListElement::setDoubleProperty(const ListLayout::Role &role, double d)
-{
- int roleIndex = -1;
-
- if (role.type == ListLayout::Role::Number) {
- char *mem = getPropertyMemory(role);
- double *value = reinterpret_cast<double *>(mem);
- bool changed = *value != d;
- *value = d;
- if (changed)
- roleIndex = role.index;
- }
-
- return roleIndex;
-}
-
-int ListElement::setBoolProperty(const ListLayout::Role &role, bool b)
-{
- int roleIndex = -1;
-
- if (role.type == ListLayout::Role::Bool) {
- char *mem = getPropertyMemory(role);
- bool *value = reinterpret_cast<bool *>(mem);
- bool changed = *value != b;
- *value = b;
- if (changed)
- roleIndex = role.index;
- }
-
- return roleIndex;
-}
-
-int ListElement::setListProperty(const ListLayout::Role &role, ListModel *m)
-{
- int roleIndex = -1;
-
- if (role.type == ListLayout::Role::List) {
- char *mem = getPropertyMemory(role);
- ListModel **value = reinterpret_cast<ListModel **>(mem);
- if (*value && *value != m) {
- (*value)->destroy();
- delete *value;
- }
- *value = m;
- roleIndex = role.index;
- }
-
- return roleIndex;
-}
-
-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);
- bool existingGuard = false;
- for (size_t i=0 ; i < sizeof(QPointer<QObject>) ; ++i) {
- if (mem[i] != 0) {
- existingGuard = true;
- break;
- }
- }
- bool changed;
- if (existingGuard) {
- changed = g->data() != o;
- g->~QPointer();
- } else {
- changed = true;
- }
- new (mem) QPointer<QObject>(o);
- if (changed)
- roleIndex = role.index;
- }
-
- return roleIndex;
-}
-
-int ListElement::setVariantMapProperty(const ListLayout::Role &role, QV4::Object *o)
-{
- int roleIndex = -1;
-
- if (role.type == ListLayout::Role::VariantMap) {
- char *mem = getPropertyMemory(role);
- if (isMemoryUsed<QVariantMap>(mem)) {
- QVariantMap *map = reinterpret_cast<QVariantMap *>(mem);
- map->~QMap();
- }
- new (mem) QVariantMap(o->engine()->variantMapFromJS(o));
- roleIndex = role.index;
- }
-
- return roleIndex;
-}
-
-int ListElement::setVariantMapProperty(const ListLayout::Role &role, QVariantMap *m)
-{
- int roleIndex = -1;
-
- if (role.type == ListLayout::Role::VariantMap) {
- char *mem = getPropertyMemory(role);
- if (isMemoryUsed<QVariantMap>(mem)) {
- QVariantMap *map = reinterpret_cast<QVariantMap *>(mem);
- if (m && map->isSharedWith(*m))
- return roleIndex;
- map->~QMap();
- } else if (!m) {
- return roleIndex;
- }
- if (m)
- new (mem) QVariantMap(*m);
- else
- new (mem) QVariantMap;
- roleIndex = role.index;
- }
-
- return roleIndex;
-}
-
-int ListElement::setDateTimeProperty(const ListLayout::Role &role, const QDateTime &dt)
-{
- int roleIndex = -1;
-
- if (role.type == ListLayout::Role::DateTime) {
- char *mem = getPropertyMemory(role);
- if (isMemoryUsed<QDateTime>(mem)) {
- QDateTime *dt = reinterpret_cast<QDateTime *>(mem);
- dt->~QDateTime();
- }
- new (mem) QDateTime(dt);
- roleIndex = role.index;
- }
-
- return roleIndex;
-}
-
-int ListElement::setFunctionProperty(const ListLayout::Role &role, const QJSValue &f)
-{
- int roleIndex = -1;
-
- if (role.type == ListLayout::Role::Function) {
- char *mem = getPropertyMemory(role);
- if (isMemoryUsed<QJSValue>(mem)) {
- QJSValue *f = reinterpret_cast<QJSValue *>(mem);
- f->~QJSValue();
- }
- new (mem) QJSValue(f);
- roleIndex = role.index;
- }
-
- return roleIndex;
-}
-
-int ListElement::setTranslationProperty(const ListLayout::Role &role, const QV4::CompiledData::Binding *b)
-{
- int roleIndex = -1;
-
- if (role.type == ListLayout::Role::String) {
- char *mem = getPropertyMemory(role);
- StringOrTranslation *s = reinterpret_cast<StringOrTranslation *>(mem);
- s->setTranslation(b);
- roleIndex = role.index;
- }
-
- return roleIndex;
-}
-
-
-void ListElement::setStringPropertyFast(const ListLayout::Role &role, const QString &s)
-{
- char *mem = getPropertyMemory(role);
- new (mem) StringOrTranslation(s);
-}
-
-void ListElement::setDoublePropertyFast(const ListLayout::Role &role, double d)
-{
- char *mem = getPropertyMemory(role);
- double *value = new (mem) double;
- *value = d;
-}
-
-void ListElement::setBoolPropertyFast(const ListLayout::Role &role, bool b)
-{
- char *mem = getPropertyMemory(role);
- bool *value = new (mem) bool;
- *value = b;
-}
-
-void ListElement::setQObjectPropertyFast(const ListLayout::Role &role, QObject *o)
-{
- char *mem = getPropertyMemory(role);
- new (mem) QPointer<QObject>(o);
-}
-
-void ListElement::setListPropertyFast(const ListLayout::Role &role, ListModel *m)
-{
- char *mem = getPropertyMemory(role);
- ListModel **value = new (mem) ListModel *;
- *value = m;
-}
-
-void ListElement::setVariantMapFast(const ListLayout::Role &role, QV4::Object *o)
-{
- char *mem = getPropertyMemory(role);
- QVariantMap *map = new (mem) QVariantMap;
- *map = o->engine()->variantMapFromJS(o);
-}
-
-void ListElement::setDateTimePropertyFast(const ListLayout::Role &role, const QDateTime &dt)
-{
- char *mem = getPropertyMemory(role);
- new (mem) QDateTime(dt);
-}
-
-void ListElement::setFunctionPropertyFast(const ListLayout::Role &role, const QJSValue &f)
-{
- char *mem = getPropertyMemory(role);
- new (mem) QJSValue(f);
-}
-
-void ListElement::clearProperty(const ListLayout::Role &role)
-{
- switch (role.type) {
- case ListLayout::Role::String:
- setStringProperty(role, QString());
- break;
- case ListLayout::Role::Number:
- setDoubleProperty(role, 0.0);
- break;
- case ListLayout::Role::Bool:
- setBoolProperty(role, false);
- break;
- case ListLayout::Role::List:
- setListProperty(role, nullptr);
- break;
- case ListLayout::Role::QObject:
- setQObjectProperty(role, nullptr);
- break;
- case ListLayout::Role::DateTime:
- setDateTimeProperty(role, QDateTime());
- break;
- case ListLayout::Role::VariantMap:
- setVariantMapProperty(role, (QVariantMap *)nullptr);
- break;
- case ListLayout::Role::Function:
- setFunctionProperty(role, QJSValue());
- break;
- default:
- break;
- }
-}
-
-ListElement::ListElement()
-{
- m_objectCache = nullptr;
- uid = uidCounter.fetchAndAddOrdered(1);
- next = nullptr;
- memset(data, 0, sizeof(data));
-}
-
-ListElement::ListElement(int existingUid)
-{
- m_objectCache = nullptr;
- uid = existingUid;
- next = nullptr;
- memset(data, 0, sizeof(data));
-}
-
-ListElement::~ListElement()
-{
- delete next;
-}
-
-QVector<int> ListElement::sync(ListElement *src, ListLayout *srcLayout, ListElement *target, ListLayout *targetLayout)
-{
- QVector<int> changedRoles;
- for (int i=0 ; i < srcLayout->roleCount() ; ++i) {
- const ListLayout::Role &srcRole = srcLayout->getExistingRole(i);
- const ListLayout::Role &targetRole = targetLayout->getExistingRole(i);
-
- int roleIndex = -1;
- switch (srcRole.type) {
- case ListLayout::Role::List:
- {
- ListModel *srcSubModel = src->getListProperty(srcRole);
- ListModel *targetSubModel = target->getListProperty(targetRole);
-
- if (srcSubModel) {
- if (targetSubModel == nullptr) {
- targetSubModel = new ListModel(targetRole.subLayout, nullptr);
- target->setListPropertyFast(targetRole, targetSubModel);
- }
- if (ListModel::sync(srcSubModel, targetSubModel))
- roleIndex = targetRole.index;
- }
- }
- break;
- case ListLayout::Role::QObject:
- {
- QObject *object = src->getQObjectProperty(srcRole);
- roleIndex = target->setQObjectProperty(targetRole, object);
- }
- break;
- case ListLayout::Role::String:
- case ListLayout::Role::Number:
- case ListLayout::Role::Bool:
- case ListLayout::Role::DateTime:
- case ListLayout::Role::Function:
- {
- QVariant v = src->getProperty(srcRole, nullptr, nullptr);
- roleIndex = target->setVariantProperty(targetRole, v);
- }
- break;
- case ListLayout::Role::VariantMap:
- {
- QVariantMap *map = src->getVariantMapProperty(srcRole);
- roleIndex = target->setVariantMapProperty(targetRole, map);
- }
- break;
- default:
- break;
- }
- if (roleIndex >= 0)
- changedRoles << roleIndex;
- }
-
- return changedRoles;
-}
-
-void ListElement::destroy(ListLayout *layout)
-{
- if (layout) {
- for (int i=0 ; i < layout->roleCount() ; ++i) {
- const ListLayout::Role &r = layout->getExistingRole(i);
-
- switch (r.type) {
- case ListLayout::Role::String:
- {
- StringOrTranslation *string = getStringProperty(r);
- if (string)
- string->~StringOrTranslation();
- }
- break;
- case ListLayout::Role::List:
- {
- ListModel *model = getListProperty(r);
- if (model) {
- model->destroy();
- delete model;
- }
- }
- break;
- case ListLayout::Role::QObject:
- {
- QPointer<QObject> *guard = getGuardProperty(r);
- if (guard)
- guard->~QPointer();
- }
- break;
- case ListLayout::Role::VariantMap:
- {
- QVariantMap *map = getVariantMapProperty(r);
- if (map)
- map->~QMap();
- }
- break;
- case ListLayout::Role::DateTime:
- {
- QDateTime *dt = getDateTimeProperty(r);
- if (dt)
- dt->~QDateTime();
- }
- break;
- case ListLayout::Role::Function:
- {
- QJSValue *f = getFunctionProperty(r);
- if (f)
- f->~QJSValue();
- }
- break;
- default:
- // other types don't need explicit cleanup.
- break;
- }
- }
-
- if (m_objectCache) {
- m_objectCache->~QObject();
- operator delete(m_objectCache);
- }
- }
-
- if (next)
- next->destroy(nullptr);
- uid = -1;
-}
-
-int ListElement::setVariantProperty(const ListLayout::Role &role, const QVariant &d)
-{
- int roleIndex = -1;
-
- switch (role.type) {
- case ListLayout::Role::Number:
- roleIndex = setDoubleProperty(role, d.toDouble());
- break;
- case ListLayout::Role::String:
- if (d.userType() == qMetaTypeId<const QV4::CompiledData::Binding *>())
- roleIndex = setTranslationProperty(role, d.value<const QV4::CompiledData::Binding*>());
- else
- roleIndex = setStringProperty(role, d.toString());
- break;
- case ListLayout::Role::Bool:
- roleIndex = setBoolProperty(role, d.toBool());
- break;
- case ListLayout::Role::List:
- roleIndex = setListProperty(role, d.value<ListModel *>());
- break;
- case ListLayout::Role::VariantMap: {
- QVariantMap map = d.toMap();
- roleIndex = setVariantMapProperty(role, &map);
- }
- break;
- case ListLayout::Role::DateTime:
- roleIndex = setDateTimeProperty(role, d.toDateTime());
- break;
- case ListLayout::Role::Function:
- roleIndex = setFunctionProperty(role, d.value<QJSValue>());
- break;
- default:
- break;
- }
-
- return roleIndex;
-}
-
-int ListElement::setJsProperty(const ListLayout::Role &role, const QV4::Value &d, QV4::ExecutionEngine *eng)
-{
- // Check if this key exists yet
- int roleIndex = -1;
-
- QV4::Scope scope(eng);
-
- // Add the value now
- if (d.isString()) {
- QString qstr = d.toQString();
- roleIndex = setStringProperty(role, qstr);
- } else if (d.isNumber()) {
- roleIndex = setDoubleProperty(role, d.asDouble());
- } else if (d.as<QV4::ArrayObject>()) {
- QV4::ScopedArrayObject a(scope, d);
- if (role.type == ListLayout::Role::List) {
- QV4::Scope scope(a->engine());
- QV4::ScopedObject o(scope);
-
- ListModel *subModel = new ListModel(role.subLayout, nullptr);
- int arrayLength = a->getLength();
- for (int j=0 ; j < arrayLength ; ++j) {
- o = a->get(j);
- subModel->append(o);
- }
- roleIndex = setListProperty(role, subModel);
- } else {
- qmlWarning(nullptr) << QStringLiteral("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(role.name).arg(roleTypeName(role.type)).arg(roleTypeName(ListLayout::Role::List));
- }
- } else if (d.isBoolean()) {
- roleIndex = setBoolProperty(role, d.booleanValue());
- } else if (d.as<QV4::DateObject>()) {
- QV4::Scoped<QV4::DateObject> dd(scope, d);
- QDateTime dt = dd->toQDateTime();
- roleIndex = setDateTimeProperty(role, dt);
- } else if (d.as<QV4::FunctionObject>()) {
- QV4::ScopedFunctionObject f(scope, d);
- QJSValue jsv;
- QJSValuePrivate::setValue(&jsv, eng, f);
- roleIndex = setFunctionProperty(role, jsv);
- } else if (d.isObject()) {
- 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);
- } else if (role.type == ListLayout::Role::VariantMap) {
- roleIndex = setVariantMapProperty(role, o);
- }
- } else if (d.isNullOrUndefined()) {
- clearProperty(role);
- }
-
- return roleIndex;
-}
-
-ModelNodeMetaObject::ModelNodeMetaObject(QObject *object, QQmlListModel *model, int elementIndex)
-: QQmlOpenMetaObject(object), m_enabled(false), m_model(model), m_elementIndex(elementIndex), m_initialized(false)
-{}
-
-void ModelNodeMetaObject::initialize()
-{
- const int roleCount = m_model->m_listModel->roleCount();
- QVector<QByteArray> properties;
- properties.reserve(roleCount);
- for (int i = 0 ; i < roleCount ; ++i) {
- const ListLayout::Role &role = m_model->m_listModel->getExistingRole(i);
- QByteArray name = role.name.toUtf8();
- properties << name;
- }
- type()->createProperties(properties);
- updateValues();
- m_enabled = true;
-}
-
-ModelNodeMetaObject::~ModelNodeMetaObject()
-{
-}
-
-QAbstractDynamicMetaObject *ModelNodeMetaObject::toDynamicMetaObject(QObject *object)
-{
- if (!m_initialized) {
- m_initialized = true;
- initialize();
- }
- return QQmlOpenMetaObject::toDynamicMetaObject(object);
-}
-
-ModelNodeMetaObject *ModelNodeMetaObject::get(QObject *obj)
-{
- QObjectPrivate *op = QObjectPrivate::get(obj);
- return static_cast<ModelNodeMetaObject*>(op->metaObject);
-}
-
-void ModelNodeMetaObject::updateValues()
-{
- const int roleCount = m_model->m_listModel->roleCount();
- if (!m_initialized) {
- if (roleCount) {
- Q_ALLOCA_VAR(int, changedRoles, roleCount * sizeof(int));
- for (int i = 0; i < roleCount; ++i)
- changedRoles[i] = i;
- emitDirectNotifies(changedRoles, roleCount);
- }
- return;
- }
- for (int i=0 ; i < roleCount ; ++i) {
- const ListLayout::Role &role = m_model->m_listModel->getExistingRole(i);
- QByteArray name = role.name.toUtf8();
- const QVariant &data = m_model->data(m_elementIndex, i);
- setValue(name, data, role.type == ListLayout::Role::List);
- }
-}
-
-void ModelNodeMetaObject::updateValues(const QVector<int> &roles)
-{
- if (!m_initialized) {
- emitDirectNotifies(roles.constData(), roles.count());
- return;
- }
- int roleCount = roles.count();
- for (int i=0 ; i < roleCount ; ++i) {
- int roleIndex = roles.at(i);
- const ListLayout::Role &role = m_model->m_listModel->getExistingRole(roleIndex);
- QByteArray name = role.name.toUtf8();
- const QVariant &data = m_model->data(m_elementIndex, roleIndex);
- setValue(name, data, role.type == ListLayout::Role::List);
- }
-}
-
-void ModelNodeMetaObject::propertyWritten(int index)
-{
- if (!m_enabled)
- return;
-
- QString propName = QString::fromUtf8(name(index));
- const QVariant value = this->value(index);
-
- QV4::Scope scope(m_model->engine());
- QV4::ScopedValue v(scope, scope.engine->fromVariant(value));
-
- int roleIndex = m_model->m_listModel->setExistingProperty(m_elementIndex, propName, v, scope.engine);
- if (roleIndex != -1)
- m_model->emitItemsChanged(m_elementIndex, 1, QVector<int>(1, roleIndex));
-}
-
-// Does the emission of the notifiers when we haven't created the meta-object yet
-void ModelNodeMetaObject::emitDirectNotifies(const int *changedRoles, int roleCount)
-{
- Q_ASSERT(!m_initialized);
- QQmlData *ddata = QQmlData::get(object(), /*create*/false);
- if (!ddata)
- return;
- // There's nothing to emit if we're a list model in a worker thread.
- if (!qmlEngine(m_model))
- return;
- for (int i = 0; i < roleCount; ++i) {
- const int changedRole = changedRoles[i];
- QQmlNotifier::notify(ddata, changedRole);
- }
-}
-
-namespace QV4 {
-
-bool ModelObject::virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver)
-{
- if (!id.isString())
- return Object::virtualPut(m, id, value, receiver);
- QString propName = id.toQString();
-
- ModelObject *that = static_cast<ModelObject*>(m);
-
- ExecutionEngine *eng = that->engine();
- const int elementIndex = that->d()->elementIndex();
- int roleIndex = that->d()->m_model->m_listModel->setExistingProperty(elementIndex, propName, value, eng);
- if (roleIndex != -1)
- that->d()->m_model->emitItemsChanged(elementIndex, 1, QVector<int>(1, roleIndex));
-
- ModelNodeMetaObject *mo = ModelNodeMetaObject::get(that->object());
- if (mo->initialized())
- mo->emitPropertyNotification(propName.toUtf8());
- return true;
-}
-
-ReturnedValue ModelObject::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
-{
- if (!id.isString())
- return QObjectWrapper::virtualGet(m, id, receiver, hasProperty);
-
- const ModelObject *that = static_cast<const ModelObject*>(m);
- Scope scope(that);
- ScopedString name(scope, id.asStringOrSymbol());
- const ListLayout::Role *role = that->d()->m_model->m_listModel->getExistingRole(name);
- if (!role)
- return QObjectWrapper::virtualGet(m, id, receiver, hasProperty);
- if (hasProperty)
- *hasProperty = true;
-
- if (QQmlEngine *qmlEngine = that->engine()->qmlEngine()) {
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(qmlEngine);
- if (ep && ep->propertyCapture)
- ep->propertyCapture->captureProperty(that->object(), -1, role->index, /*doNotify=*/ false);
- }
-
- const int elementIndex = that->d()->elementIndex();
- QVariant value = that->d()->m_model->data(elementIndex, role->index);
- return that->engine()->fromVariant(value);
-}
-
-ReturnedValue ModelObject::virtualResolveLookupGetter(const Object *object, ExecutionEngine *engine, Lookup *lookup)
-{
- lookup->getter = Lookup::getterFallback;
- return lookup->getter(lookup, engine, *object);
-}
-
-struct ModelObjectOwnPropertyKeyIterator : ObjectOwnPropertyKeyIterator
-{
- int roleNameIndex = 0;
- ~ModelObjectOwnPropertyKeyIterator() override = default;
- PropertyKey next(const Object *o, Property *pd = nullptr, PropertyAttributes *attrs = nullptr) override;
-
-};
-
-PropertyKey ModelObjectOwnPropertyKeyIterator::next(const Object *o, Property *pd, PropertyAttributes *attrs)
-{
- const ModelObject *that = static_cast<const ModelObject *>(o);
-
- ExecutionEngine *v4 = that->engine();
- if (roleNameIndex < that->listModel()->roleCount()) {
- Scope scope(that->engine());
- const ListLayout::Role &role = that->listModel()->getExistingRole(roleNameIndex);
- ++roleNameIndex;
- ScopedString roleName(scope, v4->newString(role.name));
- if (attrs)
- *attrs = QV4::Attr_Data;
- if (pd) {
- QVariant value = that->d()->m_model->data(that->d()->elementIndex(), role.index);
- pd->value = v4->fromVariant(value);
- }
- return roleName->toPropertyKey();
- }
-
- // Fall back to QV4::Object as opposed to QV4::QObjectWrapper otherwise it will add
- // unnecessary entries that relate to the roles used. These just create extra work
- // later on as they will just be ignored.
- return ObjectOwnPropertyKeyIterator::next(o, pd, attrs);
-}
-
-OwnPropertyKeyIterator *ModelObject::virtualOwnPropertyKeys(const Object *m, Value *target)
-{
- *target = *m;
- return new ModelObjectOwnPropertyKeyIterator;
-}
-
-DEFINE_OBJECT_VTABLE(ModelObject);
-
-} // namespace QV4
-
-DynamicRoleModelNode::DynamicRoleModelNode(QQmlListModel *owner, int uid) : m_owner(owner), m_uid(uid), m_meta(new DynamicRoleModelNodeMetaObject(this))
-{
- setNodeUpdatesEnabled(true);
-}
-
-DynamicRoleModelNode *DynamicRoleModelNode::create(const QVariantMap &obj, QQmlListModel *owner)
-{
- DynamicRoleModelNode *object = new DynamicRoleModelNode(owner, uidCounter.fetchAndAddOrdered(1));
- QVector<int> roles;
- object->updateValues(obj, roles);
- return object;
-}
-
-QVector<int> DynamicRoleModelNode::sync(DynamicRoleModelNode *src, DynamicRoleModelNode *target)
-{
- QVector<int> changedRoles;
- for (int i = 0; i < src->m_meta->count(); ++i) {
- const QByteArray &name = src->m_meta->name(i);
- QVariant value = src->m_meta->value(i);
-
- QQmlListModel *srcModel = qobject_cast<QQmlListModel *>(value.value<QObject *>());
- QQmlListModel *targetModel = qobject_cast<QQmlListModel *>(target->m_meta->value(i).value<QObject *>());
-
- bool modelHasChanges = false;
- if (srcModel) {
- if (targetModel == nullptr)
- targetModel = QQmlListModel::createWithOwner(target->m_owner);
-
- modelHasChanges = QQmlListModel::sync(srcModel, targetModel);
-
- QObject *targetModelObject = targetModel;
- value = QVariant::fromValue(targetModelObject);
- } else if (targetModel) {
- delete targetModel;
- }
-
- if (target->setValue(name, value) || modelHasChanges)
- changedRoles << target->m_owner->m_roles.indexOf(QString::fromUtf8(name));
- }
- return changedRoles;
-}
-
-void DynamicRoleModelNode::updateValues(const QVariantMap &object, QVector<int> &roles)
-{
- for (auto it = object.cbegin(), end = object.cend(); it != end; ++it) {
- const QString &key = it.key();
-
- int roleIndex = m_owner->m_roles.indexOf(key);
- if (roleIndex == -1) {
- roleIndex = m_owner->m_roles.count();
- m_owner->m_roles.append(key);
- }
-
- QVariant value = it.value();
-
- // A JS array/object is translated into a (hierarchical) QQmlListModel,
- // so translate to a variant map/list first with toVariant().
- if (value.userType() == qMetaTypeId<QJSValue>())
- value = value.value<QJSValue>().toVariant();
-
- if (value.type() == QVariant::List) {
- QQmlListModel *subModel = QQmlListModel::createWithOwner(m_owner);
-
- QVariantList subArray = value.toList();
- QVariantList::const_iterator subIt = subArray.cbegin();
- QVariantList::const_iterator subEnd = subArray.cend();
- while (subIt != subEnd) {
- const QVariantMap &subObject = subIt->toMap();
- subModel->m_modelObjects.append(DynamicRoleModelNode::create(subObject, subModel));
- ++subIt;
- }
-
- QObject *subModelObject = subModel;
- value = QVariant::fromValue(subModelObject);
- }
-
- const QByteArray &keyUtf8 = key.toUtf8();
-
- QQmlListModel *existingModel = qobject_cast<QQmlListModel *>(m_meta->value(keyUtf8).value<QObject *>());
- delete existingModel;
-
- if (m_meta->setValue(keyUtf8, value))
- roles << roleIndex;
- }
-}
-
-DynamicRoleModelNodeMetaObject::DynamicRoleModelNodeMetaObject(DynamicRoleModelNode *object)
- : QQmlOpenMetaObject(object), m_enabled(false), m_owner(object)
-{
-}
-
-DynamicRoleModelNodeMetaObject::~DynamicRoleModelNodeMetaObject()
-{
- for (int i=0 ; i < count() ; ++i) {
- QQmlListModel *subModel = qobject_cast<QQmlListModel *>(value(i).value<QObject *>());
- delete subModel;
- }
-}
-
-void DynamicRoleModelNodeMetaObject::propertyWrite(int index)
-{
- if (!m_enabled)
- return;
-
- QVariant v = value(index);
- QQmlListModel *model = qobject_cast<QQmlListModel *>(v.value<QObject *>());
- delete model;
-}
-
-void DynamicRoleModelNodeMetaObject::propertyWritten(int index)
-{
- if (!m_enabled)
- return;
-
- QQmlListModel *parentModel = m_owner->m_owner;
-
- QVariant v = value(index);
-
- // A JS array/object is translated into a (hierarchical) QQmlListModel,
- // so translate to a variant map/list first with toVariant().
- if (v.userType() == qMetaTypeId<QJSValue>())
- v= v.value<QJSValue>().toVariant();
-
- if (v.type() == QVariant::List) {
- QQmlListModel *subModel = QQmlListModel::createWithOwner(parentModel);
-
- QVariantList subArray = v.toList();
- QVariantList::const_iterator subIt = subArray.cbegin();
- QVariantList::const_iterator subEnd = subArray.cend();
- while (subIt != subEnd) {
- const QVariantMap &subObject = subIt->toMap();
- subModel->m_modelObjects.append(DynamicRoleModelNode::create(subObject, subModel));
- ++subIt;
- }
-
- QObject *subModelObject = subModel;
- v = QVariant::fromValue(subModelObject);
-
- setValue(index, v);
- }
-
- int elementIndex = parentModel->m_modelObjects.indexOf(m_owner);
- if (elementIndex != -1) {
- int roleIndex = parentModel->m_roles.indexOf(QString::fromLatin1(name(index).constData()));
- if (roleIndex != -1)
- parentModel->emitItemsChanged(elementIndex, 1, QVector<int>(1, roleIndex));
- }
-}
-
-/*!
- \qmltype ListModel
- \instantiates QQmlListModel
- \inqmlmodule QtQml.Models
- \ingroup qtquick-models
- \brief Defines a free-form list data source.
-
- The ListModel is a simple container of ListElement definitions, each
- containing data roles. The contents can be defined dynamically, or
- explicitly in QML.
-
- The number of elements in the model can be obtained from its \l count property.
- A number of familiar methods are also provided to manipulate the contents of the
- model, including append(), insert(), move(), remove() and set(). These methods
- accept dictionaries as their arguments; these are translated to ListElement objects
- by the model.
-
- Elements can be manipulated via the model using the setProperty() method, which
- allows the roles of the specified element to be set and changed.
-
- \section1 Example Usage
-
- The following example shows a ListModel containing three elements, with the roles
- "name" and "cost".
-
- \div {class="float-right"}
- \inlineimage listmodel.png
- \enddiv
-
- \snippet qml/listmodel/listmodel.qml 0
-
- Roles (properties) in each element must begin with a lower-case letter and
- should be common to all elements in a model. The ListElement documentation
- provides more guidelines for how elements should be defined.
-
- Since the example model contains an \c id property, it can be referenced
- by views, such as the ListView in this example:
-
- \snippet qml/listmodel/listmodel-simple.qml 0
- \dots 8
- \snippet qml/listmodel/listmodel-simple.qml 1
-
- It is possible for roles to contain list data. In the following example we
- create a list of fruit attributes:
-
- \snippet qml/listmodel/listmodel-nested.qml model
-
- The delegate displays all the fruit attributes:
-
- \div {class="float-right"}
- \inlineimage listmodel-nested.png
- \enddiv
-
- \snippet qml/listmodel/listmodel-nested.qml delegate
-
- \section1 Modifying List Models
-
- The content of a ListModel may be created and modified using the clear(),
- append(), set(), insert() and setProperty() methods. For example:
-
- \snippet qml/listmodel/listmodel-modify.qml delegate
-
- Note that when creating content dynamically the set of available properties
- cannot be changed once set. Whatever properties are first added to the model
- are the only permitted properties in the model.
-
- \section1 Using Threaded List Models with WorkerScript
-
- ListModel can be used together with WorkerScript access a list model
- from multiple threads. This is useful if list modifications are
- synchronous and take some time: the list operations can be moved to a
- different thread to avoid blocking of the main GUI thread.
-
- Here is an example that uses WorkerScript to periodically append the
- current time to a list model:
-
- \snippet ../quick/threading/threadedlistmodel/timedisplay.qml 0
-
- The included file, \tt dataloader.mjs, looks like this:
-
- \snippet ../quick/threading/threadedlistmodel/dataloader.mjs 0
-
- The timer in the main example sends messages to the worker script by calling
- \l WorkerScript::sendMessage(). When this message is received,
- \c WorkerScript.onMessage() is invoked in \c dataloader.mjs,
- which appends the current time to the list model.
-
- Note the call to sync() from the external thread.
- You must call sync() or else the changes made to the list from that
- thread will not be reflected in the list model in the main thread.
-
- \sa {qml-data-models}{Data Models}, {Qt Quick Examples - Threading}, {Qt QML}
-*/
-
-QQmlListModel::QQmlListModel(QObject *parent)
-: QAbstractListModel(parent)
-{
- m_mainThread = true;
- m_primary = true;
- m_agent = nullptr;
- m_dynamicRoles = false;
-
- m_layout = new ListLayout;
- m_listModel = new ListModel(m_layout, this);
-
- m_engine = nullptr;
-}
-
-QQmlListModel::QQmlListModel(const QQmlListModel *owner, ListModel *data, QV4::ExecutionEngine *engine, QObject *parent)
-: QAbstractListModel(parent)
-{
- m_mainThread = owner->m_mainThread;
- m_primary = false;
- m_agent = owner->m_agent;
-
- Q_ASSERT(owner->m_dynamicRoles == false);
- m_dynamicRoles = false;
- m_layout = nullptr;
- m_listModel = data;
-
- m_engine = engine;
- m_compilationUnit = owner->m_compilationUnit;
-}
-
-QQmlListModel::QQmlListModel(QQmlListModel *orig, QQmlListModelWorkerAgent *agent)
-: QAbstractListModel(agent)
-{
- m_mainThread = false;
- m_primary = true;
- m_agent = agent;
- m_dynamicRoles = orig->m_dynamicRoles;
-
- m_layout = new ListLayout(orig->m_layout);
- m_listModel = new ListModel(m_layout, this);
-
- if (m_dynamicRoles)
- sync(orig, this);
- else
- ListModel::sync(orig->m_listModel, m_listModel);
-
- m_engine = nullptr;
- m_compilationUnit = orig->m_compilationUnit;
-}
-
-QQmlListModel::~QQmlListModel()
-{
- qDeleteAll(m_modelObjects);
-
- if (m_primary) {
- m_listModel->destroy();
- delete m_listModel;
-
- if (m_mainThread && m_agent) {
- m_agent->modelDestroyed();
- m_agent->release();
- }
- }
-
- m_listModel = nullptr;
-
- delete m_layout;
- m_layout = nullptr;
-}
-
-QQmlListModel *QQmlListModel::createWithOwner(QQmlListModel *newOwner)
-{
- QQmlListModel *model = new QQmlListModel;
-
- model->m_mainThread = newOwner->m_mainThread;
- model->m_engine = newOwner->m_engine;
- model->m_agent = newOwner->m_agent;
- model->m_dynamicRoles = newOwner->m_dynamicRoles;
-
- if (model->m_mainThread && model->m_agent)
- model->m_agent->addref();
-
- QQmlEngine::setContextForObject(model, QQmlEngine::contextForObject(newOwner));
-
- return model;
-}
-
-QV4::ExecutionEngine *QQmlListModel::engine() const
-{
- if (m_engine == nullptr) {
- m_engine = qmlEngine(this)->handle();
- }
-
- return m_engine;
-}
-
-bool QQmlListModel::sync(QQmlListModel *src, QQmlListModel *target)
-{
- Q_ASSERT(src->m_dynamicRoles && target->m_dynamicRoles);
-
- bool hasChanges = false;
-
- target->m_roles = src->m_roles;
-
- // Build hash of elements <-> uid for each of the lists
- QHash<int, ElementSync> elementHash;
- for (int i = 0 ; i < target->m_modelObjects.count(); ++i) {
- DynamicRoleModelNode *e = target->m_modelObjects.at(i);
- int uid = e->getUid();
- ElementSync sync;
- sync.target = e;
- sync.targetIndex = i;
- elementHash.insert(uid, sync);
- }
- for (int i = 0 ; i < src->m_modelObjects.count(); ++i) {
- DynamicRoleModelNode *e = src->m_modelObjects.at(i);
- int uid = e->getUid();
-
- QHash<int, ElementSync>::iterator it = elementHash.find(uid);
- if (it == elementHash.end()) {
- ElementSync sync;
- sync.src = e;
- sync.srcIndex = i;
- elementHash.insert(uid, sync);
- } else {
- ElementSync &sync = it.value();
- sync.src = e;
- sync.srcIndex = i;
- }
- }
-
- // Get list of elements that are in the target but no longer in the source. These get deleted first.
- int rowsRemoved = 0;
- for (int i = 0 ; i < target->m_modelObjects.count() ; ++i) {
- DynamicRoleModelNode *element = target->m_modelObjects.at(i);
- ElementSync &s = elementHash.find(element->getUid()).value();
- Q_ASSERT(s.targetIndex >= 0);
- // need to update the targetIndex, to keep it correct after removals
- s.targetIndex -= rowsRemoved;
- if (s.src == nullptr) {
- Q_ASSERT(s.targetIndex == i);
- hasChanges = true;
- target->beginRemoveRows(QModelIndex(), i, i);
- target->m_modelObjects.remove(i, 1);
- target->endRemoveRows();
- delete s.target;
- ++rowsRemoved;
- --i;
- continue;
- }
- }
-
- // Clear the target list, and append in correct order from the source
- target->m_modelObjects.clear();
- for (int i = 0 ; i < src->m_modelObjects.count() ; ++i) {
- DynamicRoleModelNode *element = src->m_modelObjects.at(i);
- ElementSync &s = elementHash.find(element->getUid()).value();
- Q_ASSERT(s.srcIndex >= 0);
- DynamicRoleModelNode *targetElement = s.target;
- if (targetElement == nullptr) {
- targetElement = new DynamicRoleModelNode(target, element->getUid());
- }
- s.changedRoles = DynamicRoleModelNode::sync(element, targetElement);
- target->m_modelObjects.append(targetElement);
- }
-
- // now emit the change notifications required. This can be safely done, as we're only emitting changes, moves and inserts,
- // so the model indices can't be out of bounds
- //
- // to ensure things are kept in the correct order, emit inserts and moves first. This shouls ensure all persistent
- // model indices are updated correctly
- int rowsInserted = 0;
- for (int i = 0 ; i < target->m_modelObjects.count() ; ++i) {
- DynamicRoleModelNode *element = target->m_modelObjects.at(i);
- ElementSync &s = elementHash.find(element->getUid()).value();
- Q_ASSERT(s.srcIndex >= 0);
- s.srcIndex += rowsInserted;
- if (s.srcIndex != s.targetIndex) {
- if (s.targetIndex == -1) {
- target->beginInsertRows(QModelIndex(), i, i);
- target->endInsertRows();
- } else {
- target->beginMoveRows(QModelIndex(), i, i, QModelIndex(), s.srcIndex);
- target->endMoveRows();
- }
- hasChanges = true;
- ++rowsInserted;
- }
- if (s.targetIndex != -1 && !s.changedRoles.isEmpty()) {
- QModelIndex idx = target->createIndex(i, 0);
- emit target->dataChanged(idx, idx, s.changedRoles);
- hasChanges = true;
- }
- }
- return hasChanges;
-}
-
-void QQmlListModel::emitItemsChanged(int index, int count, const QVector<int> &roles)
-{
- if (count <= 0)
- return;
-
- if (m_mainThread)
- emit dataChanged(createIndex(index, 0), createIndex(index + count - 1, 0), roles);;
-}
-
-void QQmlListModel::emitItemsAboutToBeInserted(int index, int count)
-{
- Q_ASSERT(index >= 0 && count >= 0);
- if (m_mainThread)
- beginInsertRows(QModelIndex(), index, index + count - 1);
-}
-
-void QQmlListModel::emitItemsInserted()
-{
- if (m_mainThread) {
- endInsertRows();
- emit countChanged();
- }
-}
-
-QQmlListModelWorkerAgent *QQmlListModel::agent()
-{
- if (m_agent)
- return m_agent;
-
- m_agent = new QQmlListModelWorkerAgent(this);
- return m_agent;
-}
-
-QModelIndex QQmlListModel::index(int row, int column, const QModelIndex &parent) const
-{
- return row >= 0 && row < count() && column == 0 && !parent.isValid()
- ? createIndex(row, column)
- : QModelIndex();
-}
-
-int QQmlListModel::rowCount(const QModelIndex &parent) const
-{
- return !parent.isValid() ? count() : 0;
-}
-
-QVariant QQmlListModel::data(const QModelIndex &index, int role) const
-{
- return data(index.row(), role);
-}
-
-bool QQmlListModel::setData(const QModelIndex &index, const QVariant &value, int role)
-{
- const int row = index.row();
- if (row >= count() || row < 0)
- return false;
-
- if (m_dynamicRoles) {
- const QByteArray property = m_roles.at(role).toUtf8();
- if (m_modelObjects[row]->setValue(property, value)) {
- emitItemsChanged(row, 1, QVector<int>(1, role));
- return true;
- }
- } else {
- const ListLayout::Role &r = m_listModel->getExistingRole(role);
- const int roleIndex = m_listModel->setOrCreateProperty(row, r.name, value);
- if (roleIndex != -1) {
- emitItemsChanged(row, 1, QVector<int>(1, role));
- return true;
- }
- }
-
- return false;
-}
-
-QVariant QQmlListModel::data(int index, int role) const
-{
- QVariant v;
-
- if (index >= count() || index < 0)
- return v;
-
- if (m_dynamicRoles)
- v = m_modelObjects[index]->getValue(m_roles[role]);
- else
- v = m_listModel->getProperty(index, role, this, engine());
-
- return v;
-}
-
-QHash<int, QByteArray> QQmlListModel::roleNames() const
-{
- QHash<int, QByteArray> roleNames;
-
- if (m_dynamicRoles) {
- for (int i = 0 ; i < m_roles.count() ; ++i)
- roleNames.insert(i, m_roles.at(i).toUtf8());
- } else {
- for (int i = 0 ; i < m_listModel->roleCount() ; ++i) {
- const ListLayout::Role &r = m_listModel->getExistingRole(i);
- roleNames.insert(i, r.name.toUtf8());
- }
- }
-
- return roleNames;
-}
-
-/*!
- \qmlproperty bool ListModel::dynamicRoles
-
- By default, the type of a role is fixed the first time
- the role is used. For example, if you create a role called
- "data" and assign a number to it, you can no longer assign
- a string to the "data" role. However, when the dynamicRoles
- property is enabled, the type of a given role is not fixed
- and can be different between elements.
-
- The dynamicRoles property must be set before any data is
- added to the ListModel, and must be set from the main
- thread.
-
- A ListModel that has data statically defined (via the
- ListElement QML syntax) cannot have the dynamicRoles
- property enabled.
-
- There is a significant performance cost to using a
- ListModel with dynamic roles enabled. The cost varies
- from platform to platform but is typically somewhere
- between 4-6x slower than using static role types.
-
- Due to the performance cost of using dynamic roles,
- they are disabled by default.
-*/
-void QQmlListModel::setDynamicRoles(bool enableDynamicRoles)
-{
- if (m_mainThread && m_agent == nullptr) {
- if (enableDynamicRoles) {
- if (m_layout->roleCount())
- qmlWarning(this) << tr("unable to enable dynamic roles as this model is not empty");
- else
- m_dynamicRoles = true;
- } else {
- if (m_roles.count()) {
- qmlWarning(this) << tr("unable to enable static roles as this model is not empty");
- } else {
- m_dynamicRoles = false;
- }
- }
- } else {
- qmlWarning(this) << tr("dynamic role setting must be made from the main thread, before any worker scripts are created");
- }
-}
-
-/*!
- \qmlproperty int ListModel::count
- The number of data entries in the model.
-*/
-int QQmlListModel::count() const
-{
- return m_dynamicRoles ? m_modelObjects.count() : m_listModel->elementCount();
-}
-
-/*!
- \qmlmethod ListModel::clear()
-
- Deletes all content from the model.
-
- \sa append(), remove()
-*/
-void QQmlListModel::clear()
-{
- removeElements(0, count());
-}
-
-/*!
- \qmlmethod ListModel::remove(int index, int count = 1)
-
- Deletes the content at \a index from the model.
-
- \sa clear()
-*/
-void QQmlListModel::remove(QQmlV4Function *args)
-{
- int argLength = args->length();
-
- if (argLength == 1 || argLength == 2) {
- QV4::Scope scope(args->v4engine());
- int index = QV4::ScopedValue(scope, (*args)[0])->toInt32();
- int removeCount = (argLength == 2 ? QV4::ScopedValue(scope, (*args)[1])->toInt32() : 1);
-
- if (index < 0 || index+removeCount > count() || removeCount <= 0) {
- qmlWarning(this) << tr("remove: indices [%1 - %2] out of range [0 - %3]").arg(index).arg(index+removeCount).arg(count());
- return;
- }
-
- removeElements(index, removeCount);
- } else {
- qmlWarning(this) << tr("remove: incorrect number of arguments");
- }
-}
-
-void QQmlListModel::removeElements(int index, int removeCount)
-{
- Q_ASSERT(index >= 0 && removeCount >= 0);
-
- if (!removeCount)
- return;
-
- if (m_mainThread)
- beginRemoveRows(QModelIndex(), index, index + removeCount - 1);
-
- QVector<std::function<void()>> toDestroy;
- if (m_dynamicRoles) {
- for (int i=0 ; i < removeCount ; ++i) {
- auto modelObject = m_modelObjects[index+i];
- toDestroy.append([modelObject](){
- delete modelObject;
- });
- }
- m_modelObjects.remove(index, removeCount);
- } else {
- toDestroy = m_listModel->remove(index, removeCount);
- }
-
- if (m_mainThread) {
- endRemoveRows();
- emit countChanged();
- }
- for (const auto &destroyer : toDestroy)
- destroyer();
-}
-
-/*!
- \qmlmethod ListModel::insert(int index, jsobject dict)
-
- Adds a new item to the list model at position \a index, with the
- values in \a dict.
-
- \code
- fruitModel.insert(2, {"cost": 5.95, "name":"Pizza"})
- \endcode
-
- The \a index must be to an existing item in the list, or one past
- the end of the list (equivalent to append).
-
- \sa set(), append()
-*/
-
-void QQmlListModel::insert(QQmlV4Function *args)
-{
- if (args->length() == 2) {
- QV4::Scope scope(args->v4engine());
- QV4::ScopedValue arg0(scope, (*args)[0]);
- int index = arg0->toInt32();
-
- if (index < 0 || index > count()) {
- qmlWarning(this) << tr("insert: index %1 out of range").arg(index);
- return;
- }
-
- QV4::ScopedObject argObject(scope, (*args)[1]);
- QV4::ScopedArrayObject objectArray(scope, (*args)[1]);
- if (objectArray) {
- QV4::ScopedObject argObject(scope);
-
- int objectArrayLength = objectArray->getLength();
- emitItemsAboutToBeInserted(index, objectArrayLength);
- for (int i=0 ; i < objectArrayLength ; ++i) {
- argObject = objectArray->get(i);
-
- if (m_dynamicRoles) {
- m_modelObjects.insert(index+i, DynamicRoleModelNode::create(scope.engine->variantMapFromJS(argObject), this));
- } else {
- m_listModel->insert(index+i, argObject);
- }
- }
- emitItemsInserted();
- } else if (argObject) {
- emitItemsAboutToBeInserted(index, 1);
-
- if (m_dynamicRoles) {
- m_modelObjects.insert(index, DynamicRoleModelNode::create(scope.engine->variantMapFromJS(argObject), this));
- } else {
- m_listModel->insert(index, argObject);
- }
-
- emitItemsInserted();
- } else {
- qmlWarning(this) << tr("insert: value is not an object");
- }
- } else {
- qmlWarning(this) << tr("insert: value is not an object");
- }
-}
-
-/*!
- \qmlmethod ListModel::move(int from, int to, int n)
-
- Moves \a n items \a from one position \a to another.
-
- The from and to ranges must exist; for example, to move the first 3 items
- to the end of the list:
-
- \code
- fruitModel.move(0, fruitModel.count - 3, 3)
- \endcode
-
- \sa append()
-*/
-void QQmlListModel::move(int from, int to, int n)
-{
- if (n == 0 || from == to)
- return;
- if (!canMove(from, to, n)) {
- qmlWarning(this) << tr("move: out of range");
- return;
- }
-
- if (m_mainThread)
- beginMoveRows(QModelIndex(), from, from + n - 1, QModelIndex(), to > from ? to + n : to);
-
- if (m_dynamicRoles) {
-
- int realFrom = from;
- int realTo = to;
- int realN = n;
-
- if (from > to) {
- // Only move forwards - flip if backwards moving
- int tfrom = from;
- int tto = to;
- realFrom = tto;
- realTo = tto+n;
- realN = tfrom-tto;
- }
-
- QPODVector<DynamicRoleModelNode *, 4> store;
- for (int i=0 ; i < (realTo-realFrom) ; ++i)
- store.append(m_modelObjects[realFrom+realN+i]);
- for (int i=0 ; i < realN ; ++i)
- store.append(m_modelObjects[realFrom+i]);
- for (int i=0 ; i < store.count() ; ++i)
- m_modelObjects[realFrom+i] = store[i];
-
- } else {
- m_listModel->move(from, to, n);
- }
-
- if (m_mainThread)
- endMoveRows();
-}
-
-/*!
- \qmlmethod ListModel::append(jsobject dict)
-
- Adds a new item to the end of the list model, with the
- values in \a dict.
-
- \code
- fruitModel.append({"cost": 5.95, "name":"Pizza"})
- \endcode
-
- \sa set(), remove()
-*/
-void QQmlListModel::append(QQmlV4Function *args)
-{
- if (args->length() == 1) {
- QV4::Scope scope(args->v4engine());
- QV4::ScopedObject argObject(scope, (*args)[0]);
- QV4::ScopedArrayObject objectArray(scope, (*args)[0]);
-
- if (objectArray) {
- QV4::ScopedObject argObject(scope);
-
- int objectArrayLength = objectArray->getLength();
- if (objectArrayLength > 0) {
- int index = count();
- emitItemsAboutToBeInserted(index, objectArrayLength);
-
- for (int i=0 ; i < objectArrayLength ; ++i) {
- argObject = objectArray->get(i);
-
- if (m_dynamicRoles) {
- m_modelObjects.append(DynamicRoleModelNode::create(scope.engine->variantMapFromJS(argObject), this));
- } else {
- m_listModel->append(argObject);
- }
- }
-
- emitItemsInserted();
- }
- } else if (argObject) {
- int index;
-
- if (m_dynamicRoles) {
- index = m_modelObjects.count();
- emitItemsAboutToBeInserted(index, 1);
- m_modelObjects.append(DynamicRoleModelNode::create(scope.engine->variantMapFromJS(argObject), this));
- } else {
- index = m_listModel->elementCount();
- emitItemsAboutToBeInserted(index, 1);
- m_listModel->append(argObject);
- }
-
- emitItemsInserted();
- } else {
- qmlWarning(this) << tr("append: value is not an object");
- }
- } else {
- qmlWarning(this) << tr("append: value is not an object");
- }
-}
-
-/*!
- \qmlmethod object ListModel::get(int index)
-
- Returns the item at \a index in the list model. This allows the item
- data to be accessed or modified from JavaScript:
-
- \code
- Component.onCompleted: {
- fruitModel.append({"cost": 5.95, "name":"Jackfruit"});
- console.log(fruitModel.get(0).cost);
- fruitModel.get(0).cost = 10.95;
- }
- \endcode
-
- The \a index must be an element in the list.
-
- Note that properties of the returned object that are themselves objects
- will also be models, and this get() method is used to access elements:
-
- \code
- fruitModel.append(..., "attributes":
- [{"name":"spikes","value":"7mm"},
- {"name":"color","value":"green"}]);
- fruitModel.get(0).attributes.get(1).value; // == "green"
- \endcode
-
- \warning The returned object is not guaranteed to remain valid. It
- should not be used in \l{Property Binding}{property bindings}.
-
- \sa append()
-*/
-QJSValue QQmlListModel::get(int index) const
-{
- QV4::Scope scope(engine());
- QV4::ScopedValue result(scope, QV4::Value::undefinedValue());
-
- if (index >= 0 && index < count()) {
-
- if (m_dynamicRoles) {
- DynamicRoleModelNode *object = m_modelObjects[index];
- result = QV4::QObjectWrapper::wrap(scope.engine, object);
- } else {
- QObject *object = m_listModel->getOrCreateModelObject(const_cast<QQmlListModel *>(this), index);
- QQmlData *ddata = QQmlData::get(object);
- if (ddata->jsWrapper.isNullOrUndefined()) {
- result = scope.engine->memoryManager->allocate<QV4::ModelObject>(object, const_cast<QQmlListModel *>(this));
- // Keep track of the QObjectWrapper in persistent value storage
- ddata->jsWrapper.set(scope.engine, result);
- } else {
- result = ddata->jsWrapper.value();
- }
- }
- }
-
- return QJSValue(engine(), result->asReturnedValue());
-}
-
-/*!
- \qmlmethod ListModel::set(int index, jsobject dict)
-
- Changes the item at \a index in the list model with the
- values in \a dict. Properties not appearing in \a dict
- are left unchanged.
-
- \code
- fruitModel.set(3, {"cost": 5.95, "name":"Pizza"})
- \endcode
-
- If \a index is equal to count() then a new item is appended to the
- list. Otherwise, \a index must be an element in the list.
-
- \sa append()
-*/
-void QQmlListModel::set(int index, const QJSValue &value)
-{
- QV4::Scope scope(engine());
- QV4::ScopedObject object(scope, QJSValuePrivate::getValue(&value));
-
- if (!object) {
- qmlWarning(this) << tr("set: value is not an object");
- return;
- }
- if (index > count() || index < 0) {
- qmlWarning(this) << tr("set: index %1 out of range").arg(index);
- return;
- }
-
-
- if (index == count()) {
- emitItemsAboutToBeInserted(index, 1);
-
- if (m_dynamicRoles) {
- m_modelObjects.append(DynamicRoleModelNode::create(scope.engine->variantMapFromJS(object), this));
- } else {
- m_listModel->insert(index, object);
- }
-
- emitItemsInserted();
- } else {
-
- QVector<int> roles;
-
- if (m_dynamicRoles) {
- m_modelObjects[index]->updateValues(scope.engine->variantMapFromJS(object), roles);
- } else {
- m_listModel->set(index, object, &roles);
- }
-
- if (roles.count())
- emitItemsChanged(index, 1, roles);
- }
-}
-
-/*!
- \qmlmethod ListModel::setProperty(int index, string property, variant value)
-
- Changes the \a property of the item at \a index in the list model to \a value.
-
- \code
- fruitModel.setProperty(3, "cost", 5.95)
- \endcode
-
- The \a index must be an element in the list.
-
- \sa append()
-*/
-void QQmlListModel::setProperty(int index, const QString& property, const QVariant& value)
-{
- if (count() == 0 || index >= count() || index < 0) {
- qmlWarning(this) << tr("set: index %1 out of range").arg(index);
- return;
- }
-
- if (m_dynamicRoles) {
- int roleIndex = m_roles.indexOf(property);
- if (roleIndex == -1) {
- roleIndex = m_roles.count();
- m_roles.append(property);
- }
- if (m_modelObjects[index]->setValue(property.toUtf8(), value))
- emitItemsChanged(index, 1, QVector<int>(1, roleIndex));
- } else {
- int roleIndex = m_listModel->setOrCreateProperty(index, property, value);
- if (roleIndex != -1)
- emitItemsChanged(index, 1, QVector<int>(1, roleIndex));
- }
-}
-
-/*!
- \qmlmethod ListModel::sync()
-
- Writes any unsaved changes to the list model after it has been modified
- from a worker script.
-*/
-void QQmlListModel::sync()
-{
- // This is just a dummy method to make it look like sync() exists in
- // ListModel (and not just QQmlListModelWorkerAgent) and to let
- // us document sync().
- qmlWarning(this) << "List sync() can only be called from a WorkerScript";
-}
-
-bool QQmlListModelParser::verifyProperty(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding)
-{
- 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);
- if (objName != listElementTypeName) {
- const QMetaObject *mo = resolveType(objName);
- if (mo != &QQmlListElement::staticMetaObject) {
- error(target, QQmlListModel::tr("ListElement: cannot contain nested elements"));
- return false;
- }
- listElementTypeName = objName; // cache right name for next time
- }
-
- if (!compilationUnit->stringAt(target->idNameIndex).isEmpty()) {
- error(target->locationOfIdProperty, QQmlListModel::tr("ListElement: cannot use reserved \"id\" property"));
- return false;
- }
-
- const QV4::CompiledData::Binding *binding = target->bindingTable();
- for (quint32 i = 0; i < target->nBindings; ++i, ++binding) {
- QString propName = compilationUnit->stringAt(binding->propertyNameIndex);
- if (propName.isEmpty()) {
- error(binding, QQmlListModel::tr("ListElement: cannot contain nested elements"));
- return false;
- }
- if (!verifyProperty(compilationUnit, binding))
- return false;
- }
- } else if (binding->type == QV4::CompiledData::Binding::Type_Script) {
- QString scriptStr = binding->valueAsScriptString(compilationUnit.data());
- if (!binding->isFunctionExpression() && !definesEmptyList(scriptStr)) {
- QByteArray script = scriptStr.toUtf8();
- bool ok;
- evaluateEnum(script, &ok);
- if (!ok) {
- error(binding, QQmlListModel::tr("ListElement: cannot use script for property value"));
- return false;
- }
- }
- }
-
- return true;
-}
-
-bool QQmlListModelParser::applyProperty(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding, ListModel *model, int outterElementIndex)
-{
- const QString elementName = compilationUnit->stringAt(binding->propertyNameIndex);
-
- bool roleSet = false;
- if (binding->type >= QV4::CompiledData::Binding::Type_Object) {
- const quint32 targetObjectIndex = binding->value.objectIndex;
- const QV4::CompiledData::Object *target = compilationUnit->objectAt(targetObjectIndex);
-
- ListModel *subModel = nullptr;
- if (outterElementIndex == -1) {
- subModel = model;
- } else {
- const ListLayout::Role &role = model->getOrCreateListRole(elementName);
- if (role.type == ListLayout::Role::List) {
- subModel = model->getListProperty(outterElementIndex, role);
- if (subModel == nullptr) {
- subModel = new ListModel(role.subLayout, nullptr);
- QVariant vModel = QVariant::fromValue(subModel);
- model->setOrCreateProperty(outterElementIndex, elementName, vModel);
- }
- }
- }
-
- int elementIndex = subModel ? subModel->appendElement() : -1;
-
- const QV4::CompiledData::Binding *subBinding = target->bindingTable();
- for (quint32 i = 0; i < target->nBindings; ++i, ++subBinding) {
- roleSet |= applyProperty(compilationUnit, subBinding, subModel, elementIndex);
- }
-
- } else {
- QVariant value;
-
- if (binding->isTranslationBinding()) {
- value = QVariant::fromValue<const QV4::CompiledData::Binding*>(binding);
- } else if (binding->evaluatesToString()) {
- value = binding->valueAsString(compilationUnit.data());
- } else if (binding->type == QV4::CompiledData::Binding::Type_Number) {
- value = binding->valueAsNumber(compilationUnit->constants);
- } else if (binding->type == QV4::CompiledData::Binding::Type_Boolean) {
- value = binding->valueAsBoolean();
- } else if (binding->type == QV4::CompiledData::Binding::Type_Null) {
- value = QVariant::fromValue(nullptr);
- } else if (binding->type == QV4::CompiledData::Binding::Type_Script) {
- QString scriptStr = binding->valueAsScriptString(compilationUnit.data());
- if (definesEmptyList(scriptStr)) {
- const ListLayout::Role &role = model->getOrCreateListRole(elementName);
- ListModel *emptyModel = new ListModel(role.subLayout, nullptr);
- value = QVariant::fromValue(emptyModel);
- } else if (binding->isFunctionExpression()) {
- QQmlBinding::Identifier id = binding->value.compiledScriptIndex;
- Q_ASSERT(id != QQmlBinding::Invalid);
-
- auto v4 = compilationUnit->engine;
- QV4::Scope scope(v4);
- // for now we do not provide a context object; data from the ListElement must be passed to the function
- QV4::ScopedContext context(scope, QV4::QmlContext::create(v4->rootContext(), QQmlContextData::get(qmlContext(model->m_modelCache)), nullptr));
- QV4::ScopedFunctionObject function(scope, QV4::FunctionObject::createScriptFunction(context, compilationUnit->runtimeFunctions[id]));
-
- QV4::ReturnedValue result = function->call(v4->globalObject, nullptr, 0);
-
- QJSValue v;
- QJSValuePrivate::setValue(&v, v4, result);
- value.setValue<QJSValue>(v);
- } else {
- QByteArray script = scriptStr.toUtf8();
- bool ok;
- value = evaluateEnum(script, &ok);
- }
- } else {
- Q_UNREACHABLE();
- }
-
- model->setOrCreateProperty(outterElementIndex, elementName, value);
- roleSet = true;
- }
- return roleSet;
-}
-
-void QQmlListModelParser::verifyBindings(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
-{
- listElementTypeName = QString(); // unknown
-
- for (const QV4::CompiledData::Binding *binding : bindings) {
- QString propName = compilationUnit->stringAt(binding->propertyNameIndex);
- if (!propName.isEmpty()) { // isn't default property
- error(binding, QQmlListModel::tr("ListModel: undefined property '%1'").arg(propName));
- return;
- }
- if (!verifyProperty(compilationUnit, binding))
- return;
- }
-}
-
-void QQmlListModelParser::applyBindings(QObject *obj, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
-{
- QQmlListModel *rv = static_cast<QQmlListModel *>(obj);
-
- rv->m_engine = qmlEngine(rv)->handle();
- rv->m_compilationUnit = compilationUnit;
-
- bool setRoles = false;
-
- for (const QV4::CompiledData::Binding *binding : bindings) {
- if (binding->type != QV4::CompiledData::Binding::Type_Object)
- continue;
- setRoles |= applyProperty(compilationUnit, binding, rv->m_listModel, /*outter element index*/-1);
- }
-
- if (setRoles == false)
- qmlWarning(obj) << "All ListElement declarations are empty, no roles can be created unless dynamicRoles is set.";
-}
-
-bool QQmlListModelParser::definesEmptyList(const QString &s)
-{
- if (s.startsWith(QLatin1Char('[')) && s.endsWith(QLatin1Char(']'))) {
- for (int i=1; i<s.length()-1; i++) {
- if (!s[i].isSpace())
- return false;
- }
- return true;
- }
- return false;
-}
-
-
-/*!
- \qmltype ListElement
- \instantiates QQmlListElement
- \inqmlmodule QtQml.Models
- \brief Defines a data item in a ListModel.
- \ingroup qtquick-models
-
- List elements are defined inside ListModel definitions, and represent items in a
- list that will be displayed using ListView or \l Repeater items.
-
- List elements are defined like other QML elements except that they contain
- a collection of \e role definitions instead of properties. Using the same
- syntax as property definitions, roles both define how the data is accessed
- and include the data itself.
-
- The names used for roles must begin with a lower-case letter and should be
- common to all elements in a given model. Values must be simple constants; either
- strings (quoted and optionally within a call to QT_TR_NOOP), boolean values
- (true, false), numbers, or enumeration values (such as AlignText.AlignHCenter).
-
- Beginning with Qt 5.11 ListElement also allows assigning a function declaration to
- a role. This allows the definition of ListElements with callable actions.
-
- \section1 Referencing Roles
-
- The role names are used by delegates to obtain data from list elements.
- Each role name is accessible in the delegate's scope, and refers to the
- corresponding role in the current element. Where a role name would be
- ambiguous to use, it can be accessed via the \l{ListView::}{model}
- property (e.g., \c{model.cost} instead of \c{cost}).
-
- \section1 Example Usage
-
- The following model defines a series of list elements, each of which
- contain "name" and "cost" roles and their associated values.
-
- \snippet qml/listmodel/listelements.qml model
-
- The delegate obtains the name and cost for each element by simply referring
- to \c name and \c cost:
-
- \snippet qml/listmodel/listelements.qml view
-
- \sa ListModel
-*/
-
-QT_END_NAMESPACE
-
-#include "moc_qqmllistmodel_p.cpp"
diff --git a/src/qml/types/qqmllistmodel_p.h b/src/qml/types/qqmllistmodel_p.h
deleted file mode 100644
index 471e33aa5a..0000000000
--- a/src/qml/types/qqmllistmodel_p.h
+++ /dev/null
@@ -1,208 +0,0 @@
-/****************************************************************************
-**
-** 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 QQMLLISTMODEL_H
-#define QQMLLISTMODEL_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 <qqml.h>
-#include <private/qqmlcustomparser_p.h>
-
-#include <QtCore/QObject>
-#include <QtCore/QStringList>
-#include <QtCore/QHash>
-#include <QtCore/QList>
-#include <QtCore/QVariant>
-#include <QtCore/qabstractitemmodel.h>
-
-#include <private/qv4engine_p.h>
-#include <private/qpodvector_p.h>
-
-QT_REQUIRE_CONFIG(qml_list_model);
-
-QT_BEGIN_NAMESPACE
-
-
-class QQmlListModelWorkerAgent;
-class ListModel;
-class ListLayout;
-
-namespace QV4 {
-struct ModelObject;
-}
-
-class Q_QML_PRIVATE_EXPORT QQmlListModel : public QAbstractListModel
-{
- Q_OBJECT
- Q_PROPERTY(int count READ count NOTIFY countChanged)
- Q_PROPERTY(bool dynamicRoles READ dynamicRoles WRITE setDynamicRoles)
-
-public:
- QQmlListModel(QObject *parent=nullptr);
- ~QQmlListModel();
-
- QModelIndex index(int row, int column, const QModelIndex &parent) const override;
- int rowCount(const QModelIndex &parent) const override;
- QVariant data(const QModelIndex &index, int role) const override;
- bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
- QHash<int,QByteArray> roleNames() const override;
-
- QVariant data(int index, int role) const;
- int count() const;
-
- Q_INVOKABLE void clear();
- Q_INVOKABLE void remove(QQmlV4Function *args);
- Q_INVOKABLE void append(QQmlV4Function *args);
- Q_INVOKABLE void insert(QQmlV4Function *args);
- Q_INVOKABLE QJSValue get(int index) const;
- Q_INVOKABLE void set(int index, const QJSValue &value);
- Q_INVOKABLE void setProperty(int index, const QString& property, const QVariant& value);
- Q_INVOKABLE void move(int from, int to, int count);
- Q_INVOKABLE void sync();
-
- QQmlListModelWorkerAgent *agent();
-
- bool dynamicRoles() const { return m_dynamicRoles; }
- void setDynamicRoles(bool enableDynamicRoles);
-
-Q_SIGNALS:
- void countChanged();
-
-private:
- friend class QQmlListModelParser;
- friend class QQmlListModelWorkerAgent;
- friend class ModelObject;
- friend struct QV4::ModelObject;
- friend class ModelNodeMetaObject;
- friend class ListModel;
- friend class ListElement;
- friend class DynamicRoleModelNode;
- friend class DynamicRoleModelNodeMetaObject;
- friend struct StringOrTranslation;
-
- // Constructs a flat list model for a worker agent
- QQmlListModel(QQmlListModel *orig, QQmlListModelWorkerAgent *agent);
- QQmlListModel(const QQmlListModel *owner, ListModel *data, QV4::ExecutionEngine *engine, QObject *parent=nullptr);
-
- QV4::ExecutionEngine *engine() const;
-
- inline bool canMove(int from, int to, int n) const { return !(from+n > count() || to+n > count() || from < 0 || to < 0 || n < 0); }
-
- QQmlListModelWorkerAgent *m_agent;
- mutable QV4::ExecutionEngine *m_engine;
- QQmlRefPointer<QV4::CompiledData::CompilationUnit> m_compilationUnit;
- bool m_mainThread;
- bool m_primary;
-
- bool m_dynamicRoles;
-
- ListLayout *m_layout;
- ListModel *m_listModel;
-
- QVector<class DynamicRoleModelNode *> m_modelObjects;
- QVector<QString> m_roles;
-
- struct ElementSync
- {
- DynamicRoleModelNode *src = nullptr;
- DynamicRoleModelNode *target = nullptr;
- int srcIndex = -1;
- int targetIndex = -1;
- QVector<int> changedRoles;
- };
-
- static bool sync(QQmlListModel *src, QQmlListModel *target);
- static QQmlListModel *createWithOwner(QQmlListModel *newOwner);
-
- void emitItemsChanged(int index, int count, const QVector<int> &roles);
- void emitItemsAboutToBeInserted(int index, int count);
- void emitItemsInserted();
-
- void removeElements(int index, int removeCount);
-};
-
-// ### FIXME
-class QQmlListElement : public QObject
-{
-Q_OBJECT
-};
-
-class QQmlListModelParser : public QQmlCustomParser
-{
-public:
- enum PropertyType {
- Invalid,
- Boolean,
- Number,
- String,
- Script
- };
-
-
- QQmlListModelParser() : QQmlCustomParser(QQmlCustomParser::AcceptsSignalHandlers) {}
-
- void verifyBindings(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings) override;
- void applyBindings(QObject *obj, const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings) override;
-
-private:
- bool verifyProperty(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding);
- // returns true if a role was set
- bool applyProperty(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &compilationUnit, const QV4::CompiledData::Binding *binding, ListModel *model, int outterElementIndex);
-
- static bool definesEmptyList(const QString &);
-
- QString listElementTypeName;
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQmlListModel)
-QML_DECLARE_TYPE(QQmlListElement)
-
-#endif // QQMLLISTMODEL_H
diff --git a/src/qml/types/qqmllistmodel_p_p.h b/src/qml/types/qqmllistmodel_p_p.h
deleted file mode 100644
index 2876c71de6..0000000000
--- a/src/qml/types/qqmllistmodel_p_p.h
+++ /dev/null
@@ -1,428 +0,0 @@
-/****************************************************************************
-**
-** 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 QQMLLISTMODEL_P_P_H
-#define QQMLLISTMODEL_P_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 "qqmllistmodel_p.h"
-#include <private/qqmlengine_p.h>
-#include <private/qqmlopenmetaobject_p.h>
-#include <private/qv4qobjectwrapper_p.h>
-#include <qqml.h>
-
-QT_REQUIRE_CONFIG(qml_list_model);
-
-QT_BEGIN_NAMESPACE
-
-
-class DynamicRoleModelNode;
-
-class DynamicRoleModelNodeMetaObject : public QQmlOpenMetaObject
-{
-public:
- DynamicRoleModelNodeMetaObject(DynamicRoleModelNode *object);
- ~DynamicRoleModelNodeMetaObject();
-
- bool m_enabled;
-
-protected:
- void propertyWrite(int index) override;
- void propertyWritten(int index) override;
-
-private:
- DynamicRoleModelNode *m_owner;
-};
-
-class DynamicRoleModelNode : public QObject
-{
- Q_OBJECT
-public:
- DynamicRoleModelNode(QQmlListModel *owner, int uid);
-
- static DynamicRoleModelNode *create(const QVariantMap &obj, QQmlListModel *owner);
-
- void updateValues(const QVariantMap &object, QVector<int> &roles);
-
- QVariant getValue(const QString &name) const
- {
- return m_meta->value(name.toUtf8());
- }
-
- bool setValue(const QByteArray &name, const QVariant &val)
- {
- return m_meta->setValue(name, val);
- }
-
- void setNodeUpdatesEnabled(bool enable)
- {
- m_meta->m_enabled = enable;
- }
-
- int getUid() const
- {
- return m_uid;
- }
-
- static QVector<int> sync(DynamicRoleModelNode *src, DynamicRoleModelNode *target);
-
-private:
- QQmlListModel *m_owner;
- int m_uid;
- DynamicRoleModelNodeMetaObject *m_meta;
-
- friend class DynamicRoleModelNodeMetaObject;
-};
-
-class ModelNodeMetaObject : public QQmlOpenMetaObject
-{
-public:
- ModelNodeMetaObject(QObject *object, QQmlListModel *model, int elementIndex);
- ~ModelNodeMetaObject();
-
- QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *object) override;
-
- static ModelNodeMetaObject *get(QObject *obj);
-
- bool m_enabled;
- QQmlListModel *m_model;
- int m_elementIndex;
-
- void updateValues();
- void updateValues(const QVector<int> &roles);
-
- bool initialized() const { return m_initialized; }
-
-protected:
- void propertyWritten(int index) override;
-
-private:
- using QQmlOpenMetaObject::setValue;
-
- void emitDirectNotifies(const int *changedRoles, int roleCount);
-
- void initialize();
- bool m_initialized;
-};
-
-namespace QV4 {
-
-namespace Heap {
-
-struct ModelObject : public QObjectWrapper {
- void init(QObject *object, QQmlListModel *model)
- {
- QObjectWrapper::init(object);
- m_model = model;
- QObjectPrivate *op = QObjectPrivate::get(object);
- m_nodeModelMetaObject = static_cast<ModelNodeMetaObject *>(op->metaObject);
- }
- void destroy() { QObjectWrapper::destroy(); }
- int elementIndex() const { return m_nodeModelMetaObject->m_elementIndex; }
- QQmlListModel *m_model;
- ModelNodeMetaObject *m_nodeModelMetaObject;
-};
-
-}
-
-struct ModelObject : public QObjectWrapper
-{
- V4_OBJECT2(ModelObject, QObjectWrapper)
- V4_NEEDS_DESTROY
-
- ListModel *listModel() const { return d()->m_model->m_listModel; }
-
-protected:
- static bool virtualPut(Managed *m, PropertyKey id, const Value& value, Value *receiver);
- static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
- static ReturnedValue virtualResolveLookupGetter(const Object *object, ExecutionEngine *engine, Lookup *lookup);
- static ReturnedValue lookupGetter(Lookup *l, ExecutionEngine *engine, const Value &object);
- static OwnPropertyKeyIterator *virtualOwnPropertyKeys(const Object *m, Value *target);
-};
-
-} // namespace QV4
-
-class ListLayout
-{
-public:
- ListLayout() : currentBlock(0), currentBlockOffset(0) {}
- ListLayout(const ListLayout *other);
- ~ListLayout();
-
- class Role
- {
- public:
-
- Role() : type(Invalid), blockIndex(-1), blockOffset(-1), index(-1), subLayout(0) {}
- explicit Role(const Role *other);
- ~Role();
-
- // This enum must be kept in sync with the roleTypeNames variable in qqmllistmodel.cpp
- enum DataType
- {
- Invalid = -1,
-
- String,
- Number,
- Bool,
- List,
- QObject,
- VariantMap,
- DateTime,
- Function,
-
- MaxDataType
- };
-
- QString name;
- DataType type;
- int blockIndex;
- int blockOffset;
- int index;
- ListLayout *subLayout;
- };
-
- const Role *getRoleOrCreate(const QString &key, const QVariant &data);
- const Role &getRoleOrCreate(QV4::String *key, Role::DataType type);
- const Role &getRoleOrCreate(const QString &key, Role::DataType type);
-
- const Role &getExistingRole(int index) const { return *roles.at(index); }
- const Role *getExistingRole(const QString &key) const;
- const Role *getExistingRole(QV4::String *key) const;
-
- int roleCount() const { return roles.count(); }
-
- static void sync(ListLayout *src, ListLayout *target);
-
-private:
- const Role &createRole(const QString &key, Role::DataType type);
-
- int currentBlock;
- int currentBlockOffset;
- QVector<Role *> roles;
- QStringHash<Role *> roleHash;
-};
-
-struct StringOrTranslation
-{
- explicit StringOrTranslation(const QString &s);
- explicit StringOrTranslation(const QV4::CompiledData::Binding *binding);
- ~StringOrTranslation();
- bool isSet() const { return d.flag(); }
- bool isTranslation() const { return d.isT2(); }
- void setString(const QString &s);
- void setTranslation(const QV4::CompiledData::Binding *binding);
- QString toString(const QQmlListModel *owner) const;
- QString asString() const;
-private:
- void clear();
- QBiPointer<QStringData, const QV4::CompiledData::Binding> d;
-};
-
-/*!
-\internal
-*/
-class ListElement
-{
-public:
-
- ListElement();
- ListElement(int existingUid);
- ~ListElement();
-
- static QVector<int> sync(ListElement *src, ListLayout *srcLayout, ListElement *target, ListLayout *targetLayout);
-
- enum
- {
- BLOCK_SIZE = 64 - sizeof(int) - sizeof(ListElement *) - sizeof(ModelNodeMetaObject *)
- };
-
-private:
-
- void destroy(ListLayout *layout);
-
- int setVariantProperty(const ListLayout::Role &role, const QVariant &d);
-
- int setJsProperty(const ListLayout::Role &role, const QV4::Value &d, QV4::ExecutionEngine *eng);
-
- int setStringProperty(const ListLayout::Role &role, const QString &s);
- 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 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);
- int setFunctionProperty(const ListLayout::Role &role, const QJSValue &f);
- int setTranslationProperty(const ListLayout::Role &role, const QV4::CompiledData::Binding *b);
-
- 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 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);
- void setFunctionPropertyFast(const ListLayout::Role &role, const QJSValue &f);
-
- void clearProperty(const ListLayout::Role &role);
-
- 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);
- QPointer<QObject> *getGuardProperty(const ListLayout::Role &role);
- QVariantMap *getVariantMapProperty(const ListLayout::Role &role);
- QDateTime *getDateTimeProperty(const ListLayout::Role &role);
- QJSValue *getFunctionProperty(const ListLayout::Role &role);
-
- inline char *getPropertyMemory(const ListLayout::Role &role);
-
- int getUid() const { return uid; }
-
- ModelNodeMetaObject *objectCache();
-
- char data[BLOCK_SIZE];
- ListElement *next;
-
- int uid;
- QObject *m_objectCache;
-
- friend class ListModel;
-};
-
-/*!
-\internal
-*/
-class ListModel
-{
-public:
-
- ListModel(ListLayout *layout, QQmlListModel *modelCache);
- ~ListModel() {}
-
- void destroy();
-
- int setOrCreateProperty(int elementIndex, const QString &key, const QVariant &data);
- int setExistingProperty(int uid, const QString &key, const QV4::Value &data, QV4::ExecutionEngine *eng);
-
- QVariant getProperty(int elementIndex, int roleIndex, const QQmlListModel *owner, QV4::ExecutionEngine *eng);
- ListModel *getListProperty(int elementIndex, const ListLayout::Role &role);
-
- int roleCount() const
- {
- return m_layout->roleCount();
- }
-
- const ListLayout::Role &getExistingRole(int index) const
- {
- return m_layout->getExistingRole(index);
- }
-
- const ListLayout::Role *getExistingRole(QV4::String *key) const
- {
- return m_layout->getExistingRole(key);
- }
-
- const ListLayout::Role &getOrCreateListRole(const QString &name)
- {
- return m_layout->getRoleOrCreate(name, ListLayout::Role::List);
- }
-
- int elementCount() const
- {
- return elements.count();
- }
-
- void set(int elementIndex, QV4::Object *object, QVector<int> *roles);
- void set(int elementIndex, QV4::Object *object);
-
- int append(QV4::Object *object);
- void insert(int elementIndex, QV4::Object *object);
-
- Q_REQUIRED_RESULT QVector<std::function<void()>> remove(int index, int count);
-
- int appendElement();
- void insertElement(int index);
-
- void move(int from, int to, int n);
-
- static bool sync(ListModel *src, ListModel *target);
-
- QObject *getOrCreateModelObject(QQmlListModel *model, int elementIndex);
-
-private:
- QPODVector<ListElement *, 4> elements;
- ListLayout *m_layout;
-
- QQmlListModel *m_modelCache;
-
- struct ElementSync
- {
- ListElement *src = nullptr;
- ListElement *target = nullptr;
- int srcIndex = -1;
- int targetIndex = -1;
- QVector<int> changedRoles;
- };
-
- void newElement(int index);
-
- void updateCacheIndices(int start = 0, int end = -1);
-
- friend class ListElement;
- friend class QQmlListModelWorkerAgent;
- friend class QQmlListModelParser;
-};
-
-QT_END_NAMESPACE
-
-Q_DECLARE_METATYPE(ListModel *);
-
-#endif // QQUICKLISTMODEL_P_P_H
diff --git a/src/qml/types/qqmllistmodelworkeragent.cpp b/src/qml/types/qqmllistmodelworkeragent.cpp
deleted file mode 100644
index f7cb08dcf4..0000000000
--- a/src/qml/types/qqmllistmodelworkeragent.cpp
+++ /dev/null
@@ -1,177 +0,0 @@
-/****************************************************************************
-**
-** 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 "qqmllistmodelworkeragent_p.h"
-#include "qqmllistmodel_p_p.h"
-#include <private/qqmldata_p.h>
-#include <private/qqmlengine_p.h>
-#include <qqmlinfo.h>
-
-#include <QtCore/qcoreevent.h>
-#include <QtCore/qcoreapplication.h>
-#include <QtCore/qdebug.h>
-
-
-QT_BEGIN_NAMESPACE
-
-QQmlListModelWorkerAgent::Sync::~Sync()
-{
-}
-
-QQmlListModelWorkerAgent::QQmlListModelWorkerAgent(QQmlListModel *model)
-: m_ref(1), m_orig(model), m_copy(new QQmlListModel(model, this))
-{
-}
-
-QQmlListModelWorkerAgent::~QQmlListModelWorkerAgent()
-{
- mutex.lock();
- syncDone.wakeAll();
- mutex.unlock();
-}
-
-void QQmlListModelWorkerAgent::setEngine(QV4::ExecutionEngine *eng)
-{
- m_copy->m_engine = eng;
-}
-
-void QQmlListModelWorkerAgent::addref()
-{
- m_ref.ref();
-}
-
-void QQmlListModelWorkerAgent::release()
-{
- bool del = !m_ref.deref();
-
- if (del)
- deleteLater();
-}
-
-void QQmlListModelWorkerAgent::modelDestroyed()
-{
- m_orig = nullptr;
-}
-
-int QQmlListModelWorkerAgent::count() const
-{
- return m_copy->count();
-}
-
-void QQmlListModelWorkerAgent::clear()
-{
- m_copy->clear();
-}
-
-void QQmlListModelWorkerAgent::remove(QQmlV4Function *args)
-{
- m_copy->remove(args);
-}
-
-void QQmlListModelWorkerAgent::append(QQmlV4Function *args)
-{
- m_copy->append(args);
-}
-
-void QQmlListModelWorkerAgent::insert(QQmlV4Function *args)
-{
- m_copy->insert(args);
-}
-
-QJSValue QQmlListModelWorkerAgent::get(int index) const
-{
- return m_copy->get(index);
-}
-
-void QQmlListModelWorkerAgent::set(int index, const QJSValue &value)
-{
- m_copy->set(index, value);
-}
-
-void QQmlListModelWorkerAgent::setProperty(int index, const QString& property, const QVariant& value)
-{
- m_copy->setProperty(index, property, value);
-}
-
-void QQmlListModelWorkerAgent::move(int from, int to, int count)
-{
- m_copy->move(from, to, count);
-}
-
-void QQmlListModelWorkerAgent::sync()
-{
- Sync *s = new Sync(m_copy);
-
- mutex.lock();
- QCoreApplication::postEvent(this, s);
- syncDone.wait(&mutex);
- mutex.unlock();
-}
-
-bool QQmlListModelWorkerAgent::event(QEvent *e)
-{
- if (e->type() == QEvent::User) {
- bool cc = false;
- QMutexLocker locker(&mutex);
- if (m_orig) {
- Sync *s = static_cast<Sync *>(e);
-
- cc = (m_orig->count() != s->list->count());
-
- Q_ASSERT(m_orig->m_dynamicRoles == s->list->m_dynamicRoles);
- if (m_orig->m_dynamicRoles)
- QQmlListModel::sync(s->list, m_orig);
- else
- ListModel::sync(s->list->m_listModel, m_orig->m_listModel);
- }
-
- syncDone.wakeAll();
- locker.unlock();
-
- if (cc)
- emit m_orig->countChanged();
- return true;
- }
-
- return QObject::event(e);
-}
-
-QT_END_NAMESPACE
-
-#include "moc_qqmllistmodelworkeragent_p.cpp"
diff --git a/src/qml/types/qqmllistmodelworkeragent_p.h b/src/qml/types/qqmllistmodelworkeragent_p.h
deleted file mode 100644
index 69d1785618..0000000000
--- a/src/qml/types/qqmllistmodelworkeragent_p.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/****************************************************************************
-**
-** 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 QQUICKLISTMODELWORKERAGENT_P_H
-#define QQUICKLISTMODELWORKERAGENT_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 <qqml.h>
-
-#include <QEvent>
-#include <QMutex>
-#include <QWaitCondition>
-
-#include <private/qv8engine_p.h>
-
-QT_REQUIRE_CONFIG(qml_list_model);
-
-QT_BEGIN_NAMESPACE
-
-
-class QQmlListModel;
-
-class QQmlListModelWorkerAgent : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(int count READ count)
-
-public:
- QQmlListModelWorkerAgent(QQmlListModel *);
- ~QQmlListModelWorkerAgent();
- void setEngine(QV4::ExecutionEngine *eng);
-
- void addref();
- void release();
-
- int count() const;
-
- Q_INVOKABLE void clear();
- Q_INVOKABLE void remove(QQmlV4Function *args);
- Q_INVOKABLE void append(QQmlV4Function *args);
- Q_INVOKABLE void insert(QQmlV4Function *args);
- Q_INVOKABLE QJSValue get(int index) const;
- Q_INVOKABLE void set(int index, const QJSValue &value);
- Q_INVOKABLE void setProperty(int index, const QString& property, const QVariant& value);
- Q_INVOKABLE void move(int from, int to, int count);
- Q_INVOKABLE void sync();
-
- struct VariantRef
- {
- VariantRef() : a(nullptr) {}
- VariantRef(const VariantRef &r) : a(r.a) { if (a) a->addref(); }
- VariantRef(QQmlListModelWorkerAgent *_a) : a(_a) { if (a) a->addref(); }
- ~VariantRef() { if (a) a->release(); }
-
- VariantRef &operator=(const VariantRef &o) {
- if (o.a) o.a->addref();
- if (a) a->release();
- a = o.a;
- return *this;
- }
-
- QQmlListModelWorkerAgent *a;
- };
-
- void modelDestroyed();
-protected:
- bool event(QEvent *) override;
-
-private:
- friend class QQuickWorkerScriptEnginePrivate;
- friend class QQmlListModel;
-
- struct Sync : public QEvent {
- Sync(QQmlListModel *l)
- : QEvent(QEvent::User)
- , list(l)
- {}
- ~Sync();
- QQmlListModel *list;
- };
-
- QAtomicInt m_ref;
- QQmlListModel *m_orig;
- QQmlListModel *m_copy;
- QMutex mutex;
- QWaitCondition syncDone;
-};
-
-QT_END_NAMESPACE
-
-Q_DECLARE_METATYPE(QQmlListModelWorkerAgent::VariantRef)
-
-#endif // QQUICKLISTMODELWORKERAGENT_P_H
-
diff --git a/src/qml/types/qqmlmodelsmodule.cpp b/src/qml/types/qqmlmodelsmodule.cpp
deleted file mode 100644
index 840b435d18..0000000000
--- a/src/qml/types/qqmlmodelsmodule.cpp
+++ /dev/null
@@ -1,123 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Research In Motion.
-** 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 "qqmlmodelsmodule_p.h"
-#include <QtCore/qitemselectionmodel.h>
-#if QT_CONFIG(qml_list_model)
-#include <private/qqmllistmodel_p.h>
-#endif
-#if QT_CONFIG(qml_delegate_model)
-#include <private/qqmldelegatemodel_p.h>
-#include <private/qqmldelegatecomponent_p.h>
-#endif
-#include <private/qqmlobjectmodel_p.h>
-#include <private/qqmltablemodel_p.h>
-#include <private/qqmltablemodelcolumn_p.h>
-#include <private/qqmlinstantiator_p.h>
-#include <private/qquickpackage_p.h>
-
-QT_BEGIN_NAMESPACE
-
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-
-void QQmlModelsModule::registerQmlTypes()
-{
- // Don't add anything here. These are only for backwards compatibility.
- qmlRegisterType<QQmlInstantiator>("QtQml", 2, 1, "Instantiator"); // Only available in >= 2.1
- qmlRegisterType<QQmlInstanceModel>();
-}
-
-void QQmlModelsModule::registerQuickTypes()
-{
- // Don't add anything here. These are only for backwards compatibility.
-
- const char uri[] = "QtQuick";
-
- qmlRegisterType<QQmlInstantiator>(uri, 2, 1, "Instantiator");
- qmlRegisterType<QQmlInstanceModel>();
-#if QT_CONFIG(qml_list_model)
- qmlRegisterType<QQmlListElement>(uri, 2, 0, "ListElement");
- qmlRegisterCustomType<QQmlListModel>(uri, 2, 0, "ListModel", new QQmlListModelParser);
-#endif
- qmlRegisterType<QQuickPackage>(uri, 2, 0, "Package");
-#if QT_CONFIG(qml_delegate_model)
- qmlRegisterType<QQmlDelegateModel>(uri, 2, 0, "VisualDataModel");
- qmlRegisterType<QQmlDelegateModelGroup>(uri, 2, 0, "VisualDataGroup");
-#endif
- qmlRegisterType<QQmlObjectModel>(uri, 2, 0, "VisualItemModel");
-}
-
-#endif // QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-
-void QQmlModelsModule::defineModule()
-{
- const char uri[] = "QtQml.Models";
-
-#if QT_CONFIG(qml_list_model)
- qmlRegisterType<QQmlListElement>(uri, 2, 1, "ListElement");
- qmlRegisterCustomType<QQmlListModel>(uri, 2, 1, "ListModel", new QQmlListModelParser);
-#endif
-#if QT_CONFIG(qml_delegate_model)
- qmlRegisterType<QQmlDelegateModel>(uri, 2, 1, "DelegateModel");
- qmlRegisterType<QQmlDelegateModelGroup>(uri, 2, 1, "DelegateModelGroup");
-#endif
- qmlRegisterType<QQmlObjectModel>(uri, 2, 1, "ObjectModel");
- qmlRegisterType<QQmlObjectModel,3>(uri, 2, 3, "ObjectModel");
-
- qmlRegisterType<QItemSelectionModel>(uri, 2, 2, "ItemSelectionModel");
-
- qmlRegisterType<QQuickPackage>(uri, 2, 14, "Package");
- qmlRegisterType<QQmlInstantiator>(uri, 2, 14, "Instantiator");
- qmlRegisterType<QQmlInstanceModel>();
-}
-
-void QQmlModelsModule::defineLabsModule()
-{
- const char uri[] = "Qt.labs.qmlmodels";
-
-#if QT_CONFIG(qml_delegate_model)
- qmlRegisterUncreatableType<QQmlAbstractDelegateComponent>(uri, 1, 0, "AbstractDelegateComponent", QQmlAbstractDelegateComponent::tr("Cannot create instance of abstract class AbstractDelegateComponent."));
- qmlRegisterType<QQmlDelegateChooser>(uri, 1, 0, "DelegateChooser");
- qmlRegisterType<QQmlDelegateChoice>(uri, 1, 0, "DelegateChoice");
-#endif
- qmlRegisterType<QQmlTableModel>(uri, 1, 0, "TableModel");
- qmlRegisterType<QQmlTableModelColumn>(uri, 1, 0, "TableModelColumn");
-}
-
-QT_END_NAMESPACE
diff --git a/src/qml/types/qqmlmodelsmodule_p.h b/src/qml/types/qqmlmodelsmodule_p.h
deleted file mode 100644
index 2bb04f1e11..0000000000
--- a/src/qml/types/qqmlmodelsmodule_p.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 Research In Motion.
-** 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 QQMLMODELSMODULE_H
-#define QQMLMODELSMODULE_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 <private/qtqmlglobal_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class Q_QML_PRIVATE_EXPORT QQmlModelsModule
-{
-public:
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
- static void registerQmlTypes();
- static void registerQuickTypes();
-#endif
-
- static void defineModule();
- static void defineLabsModule();
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/qml/types/qqmlobjectmodel.cpp b/src/qml/types/qqmlobjectmodel.cpp
deleted file mode 100644
index b6330b4295..0000000000
--- a/src/qml/types/qqmlobjectmodel.cpp
+++ /dev/null
@@ -1,431 +0,0 @@
-/****************************************************************************
-**
-** 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 "qqmlobjectmodel_p.h"
-
-#include <QtCore/qcoreapplication.h>
-#include <QtQml/qqmlcontext.h>
-#include <QtQml/qqmlengine.h>
-#include <QtQml/qqmlinfo.h>
-
-#include <private/qqmlchangeset_p.h>
-#include <private/qqmlglobal_p.h>
-#include <private/qobject_p.h>
-#include <private/qpodvector_p.h>
-
-#include <QtCore/qhash.h>
-#include <QtCore/qlist.h>
-
-QT_BEGIN_NAMESPACE
-
-QHash<QObject*, QQmlObjectModelAttached*> QQmlObjectModelAttached::attachedProperties;
-
-
-class QQmlObjectModelPrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QQmlObjectModel)
-public:
- class Item {
- public:
- Item(QObject *i) : item(i), ref(0) {}
-
- void addRef() { ++ref; }
- bool deref() { return --ref == 0; }
-
- QObject *item;
- int ref;
- };
-
- QQmlObjectModelPrivate() : QObjectPrivate(), moveId(0) {}
-
- static void children_append(QQmlListProperty<QObject> *prop, QObject *item) {
- int index = static_cast<QQmlObjectModelPrivate *>(prop->data)->children.count();
- static_cast<QQmlObjectModelPrivate *>(prop->data)->insert(index, item);
- }
-
- static int children_count(QQmlListProperty<QObject> *prop) {
- return static_cast<QQmlObjectModelPrivate *>(prop->data)->children.count();
- }
-
- static QObject *children_at(QQmlListProperty<QObject> *prop, int index) {
- return static_cast<QQmlObjectModelPrivate *>(prop->data)->children.at(index).item;
- }
-
- static void children_clear(QQmlListProperty<QObject> *prop) {
- static_cast<QQmlObjectModelPrivate *>(prop->data)->clear();
- }
-
- void insert(int index, QObject *item) {
- Q_Q(QQmlObjectModel);
- children.insert(index, Item(item));
- for (int i = index; i < children.count(); ++i) {
- QQmlObjectModelAttached *attached = QQmlObjectModelAttached::properties(children.at(i).item);
- attached->setIndex(i);
- }
- QQmlChangeSet changeSet;
- changeSet.insert(index, 1);
- emit q->modelUpdated(changeSet, false);
- emit q->countChanged();
- emit q->childrenChanged();
- }
-
- void move(int from, int to, int n) {
- Q_Q(QQmlObjectModel);
- if (from > to) {
- // Only move forwards - flip if backwards moving
- int tfrom = from;
- int tto = to;
- from = tto;
- to = tto+n;
- n = tfrom-tto;
- }
-
- QPODVector<QQmlObjectModelPrivate::Item, 4> store;
- for (int i = 0; i < to - from; ++i)
- store.append(children[from + n + i]);
- for (int i = 0; i < n; ++i)
- store.append(children[from + i]);
-
- for (int i = 0; i < store.count(); ++i) {
- children[from + i] = store[i];
- QQmlObjectModelAttached *attached = QQmlObjectModelAttached::properties(children.at(from + i).item);
- attached->setIndex(from + i);
- }
-
- QQmlChangeSet changeSet;
- changeSet.move(from, to, n, ++moveId);
- emit q->modelUpdated(changeSet, false);
- emit q->childrenChanged();
- }
-
- void remove(int index, int n) {
- Q_Q(QQmlObjectModel);
- for (int i = index; i < index + n; ++i) {
- QQmlObjectModelAttached *attached = QQmlObjectModelAttached::properties(children.at(i).item);
- attached->setIndex(-1);
- }
- children.erase(children.begin() + index, children.begin() + index + n);
- for (int i = index; i < children.count(); ++i) {
- QQmlObjectModelAttached *attached = QQmlObjectModelAttached::properties(children.at(i).item);
- attached->setIndex(i);
- }
- QQmlChangeSet changeSet;
- changeSet.remove(index, n);
- emit q->modelUpdated(changeSet, false);
- emit q->countChanged();
- emit q->childrenChanged();
- }
-
- void clear() {
- Q_Q(QQmlObjectModel);
- for (const Item &child : qAsConst(children))
- emit q->destroyingItem(child.item);
- remove(0, children.count());
- }
-
- int indexOf(QObject *item) const {
- for (int i = 0; i < children.count(); ++i)
- if (children.at(i).item == item)
- return i;
- return -1;
- }
-
- uint moveId;
- QList<Item> children;
-};
-
-
-/*!
- \qmltype ObjectModel
- \instantiates QQmlObjectModel
- \inqmlmodule QtQml.Models
- \ingroup qtquick-models
- \brief Defines a set of items to be used as a model.
-
- An ObjectModel contains the visual items to be used in a view.
- When an ObjectModel is used in a view, the view does not require
- a delegate since the ObjectModel already contains the visual
- delegate (items).
-
- An item can determine its index within the
- model via the \l{ObjectModel::index}{index} attached property.
-
- The example below places three colored rectangles in a ListView.
- \code
- import QtQuick 2.0
- import QtQml.Models 2.1
-
- Rectangle {
- ObjectModel {
- id: itemModel
- Rectangle { height: 30; width: 80; color: "red" }
- Rectangle { height: 30; width: 80; color: "green" }
- Rectangle { height: 30; width: 80; color: "blue" }
- }
-
- ListView {
- anchors.fill: parent
- model: itemModel
- }
- }
- \endcode
-
- \image objectmodel.png
-
- \sa {Qt Quick Examples - Views}
-*/
-
-QQmlObjectModel::QQmlObjectModel(QObject *parent)
- : QQmlInstanceModel(*(new QQmlObjectModelPrivate), parent)
-{
-}
-
-/*!
- \qmlattachedproperty int QtQml.Models::ObjectModel::index
- This attached property holds the index of this delegate's item within the model.
-
- It is attached to each instance of the delegate.
-*/
-
-QQmlListProperty<QObject> QQmlObjectModel::children()
-{
- Q_D(QQmlObjectModel);
- return QQmlListProperty<QObject>(this,
- d,
- d->children_append,
- d->children_count,
- d->children_at,
- d->children_clear);
-}
-
-/*!
- \qmlproperty int QtQml.Models::ObjectModel::count
-
- The number of items in the model. This property is readonly.
-*/
-int QQmlObjectModel::count() const
-{
- Q_D(const QQmlObjectModel);
- return d->children.count();
-}
-
-bool QQmlObjectModel::isValid() const
-{
- return true;
-}
-
-QObject *QQmlObjectModel::object(int index, QQmlIncubator::IncubationMode)
-{
- Q_D(QQmlObjectModel);
- QQmlObjectModelPrivate::Item &item = d->children[index];
- item.addRef();
- if (item.ref == 1) {
- emit initItem(index, item.item);
- emit createdItem(index, item.item);
- }
- return item.item;
-}
-
-QQmlInstanceModel::ReleaseFlags QQmlObjectModel::release(QObject *item)
-{
- Q_D(QQmlObjectModel);
- int idx = d->indexOf(item);
- if (idx >= 0) {
- if (!d->children[idx].deref())
- return QQmlInstanceModel::Referenced;
- }
- return nullptr;
-}
-
-QVariant QQmlObjectModel::variantValue(int index, const QString &role)
-{
- Q_D(QQmlObjectModel);
- if (index < 0 || index >= d->children.count())
- return QString();
- return QQmlEngine::contextForObject(d->children.at(index).item)->contextProperty(role);
-}
-
-QQmlIncubator::Status QQmlObjectModel::incubationStatus(int)
-{
- return QQmlIncubator::Ready;
-}
-
-int QQmlObjectModel::indexOf(QObject *item, QObject *) const
-{
- Q_D(const QQmlObjectModel);
- return d->indexOf(item);
-}
-
-QQmlObjectModelAttached *QQmlObjectModel::qmlAttachedProperties(QObject *obj)
-{
- return QQmlObjectModelAttached::properties(obj);
-}
-
-/*!
- \qmlmethod object QtQml.Models::ObjectModel::get(int index)
- \since 5.6
-
- Returns the item at \a index in the model. This allows the item
- to be accessed or modified from JavaScript:
-
- \code
- Component.onCompleted: {
- objectModel.append(objectComponent.createObject())
- console.log(objectModel.get(0).objectName);
- objectModel.get(0).objectName = "first";
- }
- \endcode
-
- The \a index must be an element in the list.
-
- \sa append()
-*/
-QObject *QQmlObjectModel::get(int index) const
-{
- Q_D(const QQmlObjectModel);
- if (index < 0 || index >= d->children.count())
- return nullptr;
- return d->children.at(index).item;
-}
-
-/*!
- \qmlmethod QtQml.Models::ObjectModel::append(object item)
- \since 5.6
-
- Appends a new item to the end of the model.
-
- \code
- objectModel.append(objectComponent.createObject())
- \endcode
-
- \sa insert(), remove()
-*/
-void QQmlObjectModel::append(QObject *object)
-{
- Q_D(QQmlObjectModel);
- d->insert(count(), object);
-}
-
-/*!
- \qmlmethod QtQml.Models::ObjectModel::insert(int index, object item)
- \since 5.6
-
- Inserts a new item to the model at position \a index.
-
- \code
- objectModel.insert(2, objectComponent.createObject())
- \endcode
-
- The \a index must be to an existing item in the list, or one past
- the end of the list (equivalent to append).
-
- \sa append(), remove()
-*/
-void QQmlObjectModel::insert(int index, QObject *object)
-{
- Q_D(QQmlObjectModel);
- if (index < 0 || index > count()) {
- qmlWarning(this) << tr("insert: index %1 out of range").arg(index);
- return;
- }
- d->insert(index, object);
-}
-
-/*!
- \qmlmethod QtQml.Models::ObjectModel::move(int from, int to, int n = 1)
- \since 5.6
-
- Moves \a n items \a from one position \a to another.
-
- The from and to ranges must exist; for example, to move the first 3 items
- to the end of the model:
-
- \code
- objectModel.move(0, objectModel.count - 3, 3)
- \endcode
-
- \sa append()
-*/
-void QQmlObjectModel::move(int from, int to, int n)
-{
- Q_D(QQmlObjectModel);
- if (n <= 0 || from == to)
- return;
- if (from < 0 || to < 0 || from + n > count() || to + n > count()) {
- qmlWarning(this) << tr("move: out of range");
- return;
- }
- d->move(from, to, n);
-}
-
-/*!
- \qmlmethod QtQml.Models::ObjectModel::remove(int index, int n = 1)
- \since 5.6
-
- Removes the items at \a index from the model.
-
- \sa clear()
-*/
-void QQmlObjectModel::remove(int index, int n)
-{
- Q_D(QQmlObjectModel);
- if (index < 0 || n <= 0 || index + n > count()) {
- qmlWarning(this) << tr("remove: indices [%1 - %2] out of range [0 - %3]").arg(index).arg(index+n).arg(count());
- return;
- }
- d->remove(index, n);
-}
-
-/*!
- \qmlmethod QtQml.Models::ObjectModel::clear()
- \since 5.6
-
- Clears all items from the model.
-
- \sa append(), remove()
-*/
-void QQmlObjectModel::clear()
-{
- Q_D(QQmlObjectModel);
- d->clear();
-}
-
-QT_END_NAMESPACE
-
-#include "moc_qqmlobjectmodel_p.cpp"
diff --git a/src/qml/types/qqmlobjectmodel_p.h b/src/qml/types/qqmlobjectmodel_p.h
deleted file mode 100644
index 1284ba1780..0000000000
--- a/src/qml/types/qqmlobjectmodel_p.h
+++ /dev/null
@@ -1,194 +0,0 @@
-/****************************************************************************
-**
-** 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 QQMLINSTANCEMODEL_P_H
-#define QQMLINSTANCEMODEL_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 <private/qtqmlglobal_p.h>
-#include <private/qqmlincubator_p.h>
-#include <QtQml/qqml.h>
-#include <QtCore/qobject.h>
-
-QT_BEGIN_NAMESPACE
-
-class QObject;
-class QQmlChangeSet;
-class QAbstractItemModel;
-
-class Q_QML_PRIVATE_EXPORT QQmlInstanceModel : public QObject
-{
- Q_OBJECT
-
- Q_PROPERTY(int count READ count NOTIFY countChanged)
-
-public:
- virtual ~QQmlInstanceModel() {}
-
- enum ReleaseFlag { Referenced = 0x01, Destroyed = 0x02 };
- Q_DECLARE_FLAGS(ReleaseFlags, ReleaseFlag)
-
- virtual int count() const = 0;
- virtual bool isValid() const = 0;
- virtual QObject *object(int index, QQmlIncubator::IncubationMode incubationMode = QQmlIncubator::AsynchronousIfNested) = 0;
- virtual ReleaseFlags release(QObject *object) = 0;
- virtual void cancel(int) {}
- QString stringValue(int index, const QString &role) { return variantValue(index, role).toString(); }
- virtual QVariant variantValue(int, const QString &) = 0;
- virtual void setWatchedRoles(const QList<QByteArray> &roles) = 0;
- virtual QQmlIncubator::Status incubationStatus(int index) = 0;
-
- virtual int indexOf(QObject *object, QObject *objectContext) const = 0;
- virtual const QAbstractItemModel *abstractItemModel() const { return nullptr; }
-
-Q_SIGNALS:
- void countChanged();
- void modelUpdated(const QQmlChangeSet &changeSet, bool reset);
- void createdItem(int index, QObject *object);
- void initItem(int index, QObject *object);
- void destroyingItem(QObject *object);
-
-protected:
- QQmlInstanceModel(QObjectPrivate &dd, QObject *parent = nullptr)
- : QObject(dd, parent) {}
-
-private:
- Q_DISABLE_COPY(QQmlInstanceModel)
-};
-
-class QQmlObjectModelAttached;
-class QQmlObjectModelPrivate;
-class Q_QML_PRIVATE_EXPORT QQmlObjectModel : public QQmlInstanceModel
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QQmlObjectModel)
-
- Q_PROPERTY(QQmlListProperty<QObject> children READ children NOTIFY childrenChanged DESIGNABLE false)
- Q_CLASSINFO("DefaultProperty", "children")
-
-public:
- QQmlObjectModel(QObject *parent=nullptr);
- ~QQmlObjectModel() {}
-
- int count() const override;
- bool isValid() const override;
- QObject *object(int index, QQmlIncubator::IncubationMode incubationMode = QQmlIncubator::AsynchronousIfNested) override;
- ReleaseFlags release(QObject *object) override;
- QVariant variantValue(int index, const QString &role) override;
- void setWatchedRoles(const QList<QByteArray> &) override {}
- QQmlIncubator::Status incubationStatus(int index) override;
-
- int indexOf(QObject *object, QObject *objectContext) const override;
-
- QQmlListProperty<QObject> children();
-
- static QQmlObjectModelAttached *qmlAttachedProperties(QObject *obj);
-
- Q_REVISION(3) Q_INVOKABLE QObject *get(int index) const;
- Q_REVISION(3) Q_INVOKABLE void append(QObject *object);
- Q_REVISION(3) Q_INVOKABLE void insert(int index, QObject *object);
- Q_REVISION(3) Q_INVOKABLE void move(int from, int to, int n = 1);
- Q_REVISION(3) Q_INVOKABLE void remove(int index, int n = 1);
-
-public Q_SLOTS:
- Q_REVISION(3) void clear();
-
-Q_SIGNALS:
- void childrenChanged();
-
-private:
- Q_DISABLE_COPY(QQmlObjectModel)
-};
-
-class QQmlObjectModelAttached : public QObject
-{
- Q_OBJECT
-
-public:
- QQmlObjectModelAttached(QObject *parent)
- : QObject(parent), m_index(-1) {}
- ~QQmlObjectModelAttached() {
- attachedProperties.remove(parent());
- }
-
- Q_PROPERTY(int index READ index NOTIFY indexChanged)
- int index() const { return m_index; }
- void setIndex(int idx) {
- if (m_index != idx) {
- m_index = idx;
- Q_EMIT indexChanged();
- }
- }
-
- static QQmlObjectModelAttached *properties(QObject *obj) {
- QQmlObjectModelAttached *rv = attachedProperties.value(obj);
- if (!rv) {
- rv = new QQmlObjectModelAttached(obj);
- attachedProperties.insert(obj, rv);
- }
- return rv;
- }
-
-Q_SIGNALS:
- void indexChanged();
-
-public:
- int m_index;
-
- static QHash<QObject*, QQmlObjectModelAttached*> attachedProperties;
-};
-
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQmlInstanceModel)
-QML_DECLARE_TYPE(QQmlObjectModel)
-QML_DECLARE_TYPEINFO(QQmlObjectModel, QML_HAS_ATTACHED_PROPERTIES)
-
-#endif // QQMLINSTANCEMODEL_P_H
diff --git a/src/qml/types/qqmltableinstancemodel.cpp b/src/qml/types/qqmltableinstancemodel.cpp
deleted file mode 100644
index 2170e2daec..0000000000
--- a/src/qml/types/qqmltableinstancemodel.cpp
+++ /dev/null
@@ -1,547 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 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 "qqmltableinstancemodel_p.h"
-#include "qqmldelegatecomponent_p.h"
-
-#include <QtCore/QTimer>
-
-#include <QtQml/private/qqmlincubator_p.h>
-#include <QtQml/private/qqmlchangeset_p.h>
-#include <QtQml/private/qqmlcomponent_p.h>
-
-QT_BEGIN_NAMESPACE
-
-const char* kModelItemTag = "_tableinstancemodel_modelItem";
-
-bool QQmlTableInstanceModel::isDoneIncubating(QQmlDelegateModelItem *modelItem)
-{
- if (!modelItem->incubationTask)
- return true;
-
- const auto status = modelItem->incubationTask->status();
- return (status == QQmlIncubator::Ready) || (status == QQmlIncubator::Error);
-}
-
-void QQmlTableInstanceModel::deleteModelItemLater(QQmlDelegateModelItem *modelItem)
-{
- Q_ASSERT(modelItem);
-
- delete modelItem->object;
- modelItem->object = nullptr;
-
- if (modelItem->contextData) {
- modelItem->contextData->invalidate();
- Q_ASSERT(modelItem->contextData->refCount == 1);
- modelItem->contextData = nullptr;
- }
-
- modelItem->deleteLater();
-}
-
-QQmlTableInstanceModel::QQmlTableInstanceModel(QQmlContext *qmlContext, QObject *parent)
- : QQmlInstanceModel(*(new QObjectPrivate()), parent)
- , m_qmlContext(qmlContext)
- , m_metaType(new QQmlDelegateModelItemMetaType(m_qmlContext->engine()->handle(), nullptr, QStringList()))
-{
-}
-
-void QQmlTableInstanceModel::useImportVersion(int minorVersion)
-{
- m_adaptorModel.useImportVersion(minorVersion);
-}
-
-QQmlTableInstanceModel::~QQmlTableInstanceModel()
-{
- for (const auto modelItem : m_modelItems) {
- // No item in m_modelItems should be referenced at this point. The view
- // should release all its items before it deletes this model. Only model items
- // that are still being incubated should be left for us to delete.
- Q_ASSERT(modelItem->objectRef == 0);
- Q_ASSERT(modelItem->incubationTask);
- // Check that we are not being deleted while we're
- // in the process of e.g emitting a created signal.
- Q_ASSERT(modelItem->scriptRef == 0);
-
- if (modelItem->object) {
- delete modelItem->object;
- modelItem->object = nullptr;
- modelItem->contextData->invalidate();
- modelItem->contextData = nullptr;
- }
- }
-
- deleteAllFinishedIncubationTasks();
- qDeleteAll(m_modelItems);
- drainReusableItemsPool(0);
-}
-
-QQmlComponent *QQmlTableInstanceModel::resolveDelegate(int index)
-{
- if (m_delegateChooser) {
- const int row = m_adaptorModel.rowAt(index);
- const int column = m_adaptorModel.columnAt(index);
- QQmlComponent *delegate = nullptr;
- QQmlAbstractDelegateComponent *chooser = m_delegateChooser;
- do {
- delegate = chooser->delegate(&m_adaptorModel, row, column);
- chooser = qobject_cast<QQmlAbstractDelegateComponent *>(delegate);
- } while (chooser);
- return delegate;
- }
-
- return m_delegate;
-}
-
-QQmlDelegateModelItem *QQmlTableInstanceModel::resolveModelItem(int index)
-{
- // Check if an item for the given index is already loaded and ready
- QQmlDelegateModelItem *modelItem = m_modelItems.value(index, nullptr);
- if (modelItem)
- return modelItem;
-
- QQmlComponent *delegate = resolveDelegate(index);
- if (!delegate)
- return nullptr;
-
- // Check if the pool contains an item that can be reused
- modelItem = takeFromReusableItemsPool(delegate);
- if (modelItem) {
- reuseItem(modelItem, index);
- m_modelItems.insert(index, modelItem);
- return modelItem;
- }
-
- // Create a new item from scratch
- modelItem = m_adaptorModel.createItem(m_metaType, index);
- if (modelItem) {
- modelItem->delegate = delegate;
- m_modelItems.insert(index, modelItem);
- return modelItem;
- }
-
- qWarning() << Q_FUNC_INFO << "failed creating a model item for index: " << index;
- return nullptr;
-}
-
-QObject *QQmlTableInstanceModel::object(int index, QQmlIncubator::IncubationMode incubationMode)
-{
- Q_ASSERT(m_delegate);
- Q_ASSERT(index >= 0 && index < m_adaptorModel.count());
- Q_ASSERT(m_qmlContext && m_qmlContext->isValid());
-
- QQmlDelegateModelItem *modelItem = resolveModelItem(index);
- if (!modelItem)
- return nullptr;
-
- if (modelItem->object) {
- // The model item has already been incubated. So
- // just bump the ref-count and return it.
- modelItem->referenceObject();
- return modelItem->object;
- }
-
- // The object is not ready, and needs to be incubated
- incubateModelItem(modelItem, incubationMode);
- if (!isDoneIncubating(modelItem))
- return nullptr;
-
- // Incubation is done, so the task should be removed
- Q_ASSERT(!modelItem->incubationTask);
-
- if (!modelItem->object) {
- // The object was incubated synchronously (otherwise we would return above). But since
- // we have no object, the incubation must have failed. And when we have no object, there
- // should be no object references either. And there should also not be any internal script
- // refs at this point. So we delete the model item.
- Q_ASSERT(!modelItem->isObjectReferenced());
- Q_ASSERT(!modelItem->isReferenced());
- m_modelItems.remove(modelItem->index);
- delete modelItem;
- return nullptr;
- }
-
- // Incubation was completed sync and successful
- modelItem->referenceObject();
- return modelItem->object;
-}
-
-QQmlInstanceModel::ReleaseFlags QQmlTableInstanceModel::release(QObject *object, ReusableFlag reusable)
-{
- Q_ASSERT(object);
- auto modelItem = qvariant_cast<QQmlDelegateModelItem *>(object->property(kModelItemTag));
- Q_ASSERT(modelItem);
-
- if (!modelItem->releaseObject())
- return QQmlDelegateModel::Referenced;
-
- if (modelItem->isReferenced()) {
- // We still have an internal reference to this object, which means that we are told to release an
- // object while the createdItem signal for it is still on the stack. This can happen when objects
- // are e.g delivered async, and the user flicks back and forth quicker than the loading can catch
- // up with. The view might then find that the object is no longer visible and should be released.
- // We detect this case in incubatorStatusChanged(), and delete it there instead. But from the callers
- // point of view, it should consider it destroyed.
- return QQmlDelegateModel::Destroyed;
- }
-
- // The item is not referenced by anyone
- m_modelItems.remove(modelItem->index);
-
- if (reusable == Reusable) {
- insertIntoReusableItemsPool(modelItem);
- return QQmlInstanceModel::Referenced;
- }
-
- // The item is not reused or referenced by anyone, so just delete it
- modelItem->destroyObject();
- emit destroyingItem(object);
-
- delete modelItem;
- return QQmlInstanceModel::Destroyed;
-}
-
-void QQmlTableInstanceModel::cancel(int index)
-{
- auto modelItem = m_modelItems.value(index);
- Q_ASSERT(modelItem);
-
- // Since the view expects the item to be incubating, there should be
- // an incubation task. And since the incubation is not done, no-one
- // should yet have received, and therfore hold a reference to, the object.
- Q_ASSERT(modelItem->incubationTask);
- Q_ASSERT(!modelItem->isObjectReferenced());
-
- m_modelItems.remove(index);
-
- if (modelItem->object)
- delete modelItem->object;
-
- // modelItem->incubationTask will be deleted from the modelItems destructor
- delete modelItem;
-}
-
-void QQmlTableInstanceModel::insertIntoReusableItemsPool(QQmlDelegateModelItem *modelItem)
-{
- // Currently, the only way for a view to reuse items is to call QQmlTableInstanceModel::release()
- // with the second argument explicitly set to QQmlTableInstanceModel::Reusable. If the released
- // item is no longer referenced, it will be added to the pool. Reusing of items can be specified
- // per item, in case certain items cannot be recycled.
- // A QQmlDelegateModelItem knows which delegate its object was created from. So when we are
- // about to create a new item, we first check if the pool contains an item based on the same
- // delegate from before. If so, we take it out of the pool (instead of creating a new item), and
- // update all its context-, and attached properties.
- // When a view is recycling items, it should call QQmlTableInstanceModel::drainReusableItemsPool()
- // regularly. As there is currently no logic to 'hibernate' items in the pool, they are only
- // meant to rest there for a short while, ideally only from the time e.g a row is unloaded
- // on one side of the view, and until a new row is loaded on the opposite side. In-between
- // this time, the application will see the item as fully functional and 'alive' (just not
- // visible on screen). Since this time is supposed to be short, we don't take any action to
- // notify the application about it, since we don't want to trigger any bindings that can
- // disturb performance.
- // A recommended time for calling drainReusableItemsPool() is each time a view has finished
- // loading e.g a new row or column. If there are more items in the pool after that, it means
- // that the view most likely doesn't need them anytime soon. Those items should be destroyed to
- // not consume resources.
- // Depending on if a view is a list or a table, it can sometimes be performant to keep
- // items in the pool for a bit longer than one "row out/row in" cycle. E.g for a table, if the
- // number of visible rows in a view is much larger than the number of visible columns.
- // In that case, if you flick out a row, and then flick in a column, you would throw away a lot
- // of items in the pool if completely draining it. The reason is that unloading a row places more
- // items in the pool than what ends up being recycled when loading a new column. And then, when you
- // next flick in a new row, you would need to load all those drained items again from scratch. For
- // that reason, you can specify a maxPoolTime to the drainReusableItemsPool() that allows you to keep
- // items in the pool for a bit longer, effectively keeping more items in circulation.
- // A recommended maxPoolTime would be equal to the number of dimenstions in the view, which
- // means 1 for a list view and 2 for a table view. If you specify 0, all items will be drained.
- Q_ASSERT(!modelItem->incubationTask);
- Q_ASSERT(!modelItem->isObjectReferenced());
- Q_ASSERT(!modelItem->isReferenced());
- Q_ASSERT(modelItem->object);
-
- modelItem->poolTime = 0;
- m_reusableItemsPool.append(modelItem);
- emit itemPooled(modelItem->index, modelItem->object);
-}
-
-QQmlDelegateModelItem *QQmlTableInstanceModel::takeFromReusableItemsPool(const QQmlComponent *delegate)
-{
- // Find the oldest item in the pool that was made from the same delegate as
- // the given argument, remove it from the pool, and return it.
- if (m_reusableItemsPool.isEmpty())
- return nullptr;
-
- for (auto it = m_reusableItemsPool.begin(); it != m_reusableItemsPool.end(); ++it) {
- if ((*it)->delegate != delegate)
- continue;
- auto modelItem = *it;
- m_reusableItemsPool.erase(it);
- return modelItem;
- }
-
- return nullptr;
-}
-
-void QQmlTableInstanceModel::drainReusableItemsPool(int maxPoolTime)
-{
- // Rather than releasing all pooled items upon a call to this function, each
- // item has a poolTime. The poolTime specifies for how many loading cycles an item
- // has been resting in the pool. And for each invocation of this function, poolTime
- // will increase. If poolTime is equal to, or exceeds, maxPoolTime, it will be removed
- // from the pool and released. This way, the view can tweak a bit for how long
- // items should stay in "circulation", even if they are not recycled right away.
- for (auto it = m_reusableItemsPool.begin(); it != m_reusableItemsPool.end();) {
- auto modelItem = *it;
- modelItem->poolTime++;
- if (modelItem->poolTime <= maxPoolTime) {
- ++it;
- } else {
- it = m_reusableItemsPool.erase(it);
- release(modelItem->object, NotReusable);
- }
- }
-}
-
-void QQmlTableInstanceModel::reuseItem(QQmlDelegateModelItem *item, int newModelIndex)
-{
- // Update the context properties index, row and column on
- // the delegate item, and inform the application about it.
- const int newRow = m_adaptorModel.rowAt(newModelIndex);
- const int newColumn = m_adaptorModel.columnAt(newModelIndex);
- item->setModelIndex(newModelIndex, newRow, newColumn);
-
- // Notify the application that all 'dynamic'/role-based context data has
- // changed as well (their getter function will use the updated index).
- auto const itemAsList = QList<QQmlDelegateModelItem *>() << item;
- auto const updateAllRoles = QVector<int>();
- m_adaptorModel.notify(itemAsList, newModelIndex, 1, updateAllRoles);
-
- // Inform the view that the item is recycled. This will typically result
- // in the view updating its own attached delegate item properties.
- emit itemReused(newModelIndex, item->object);
-}
-
-void QQmlTableInstanceModel::incubateModelItem(QQmlDelegateModelItem *modelItem, QQmlIncubator::IncubationMode incubationMode)
-{
- // Guard the model item temporarily so that it's not deleted from
- // incubatorStatusChanged(), in case the incubation is done synchronously.
- modelItem->scriptRef++;
-
- if (modelItem->incubationTask) {
- // We're already incubating the model item from a previous request. If the previous call requested
- // the item async, but the current request needs it sync, we need to force-complete the incubation.
- const bool sync = (incubationMode == QQmlIncubator::Synchronous || incubationMode == QQmlIncubator::AsynchronousIfNested);
- if (sync && modelItem->incubationTask->incubationMode() == QQmlIncubator::Asynchronous)
- modelItem->incubationTask->forceCompletion();
- } else {
- modelItem->incubationTask = new QQmlTableInstanceModelIncubationTask(this, modelItem, incubationMode);
-
- QQmlContextData *ctxt = new QQmlContextData;
- QQmlContext *creationContext = modelItem->delegate->creationContext();
- ctxt->setParent(QQmlContextData::get(creationContext ? creationContext : m_qmlContext.data()));
- ctxt->contextObject = modelItem;
- modelItem->contextData = ctxt;
-
- QQmlComponentPrivate::get(modelItem->delegate)->incubateObject(
- modelItem->incubationTask,
- modelItem->delegate,
- m_qmlContext->engine(),
- ctxt,
- QQmlContextData::get(m_qmlContext));
- }
-
- // Remove the temporary guard
- modelItem->scriptRef--;
-}
-
-void QQmlTableInstanceModel::incubatorStatusChanged(QQmlTableInstanceModelIncubationTask *incubationTask, QQmlIncubator::Status status)
-{
- QQmlDelegateModelItem *modelItem = incubationTask->modelItemToIncubate;
- Q_ASSERT(modelItem->incubationTask);
-
- modelItem->incubationTask = nullptr;
- incubationTask->modelItemToIncubate = nullptr;
-
- if (status == QQmlIncubator::Ready) {
- // Tag the incubated object with the model item for easy retrieval upon release etc.
- modelItem->object->setProperty(kModelItemTag, QVariant::fromValue(modelItem));
-
- // Emit that the item has been created. What normally happens next is that the view
- // upon receiving the signal asks for the model item once more. And since the item is
- // now in the map, it will be returned directly.
- Q_ASSERT(modelItem->object);
- modelItem->scriptRef++;
- emit createdItem(modelItem->index, modelItem->object);
- modelItem->scriptRef--;
- } else if (status == QQmlIncubator::Error) {
- qWarning() << "Error incubating delegate:" << incubationTask->errors();
- }
-
- if (!modelItem->isReferenced() && !modelItem->isObjectReferenced()) {
- // We have no internal reference to the model item, and the view has no
- // reference to the incubated object. So just delete the model item.
- // Note that being here means that the object was incubated _async_
- // (otherwise modelItem->isReferenced() would be true).
- m_modelItems.remove(modelItem->index);
-
- if (modelItem->object) {
- modelItem->scriptRef++;
- emit destroyingItem(modelItem->object);
- modelItem->scriptRef--;
- Q_ASSERT(!modelItem->isReferenced());
- }
-
- deleteModelItemLater(modelItem);
- }
-
- deleteIncubationTaskLater(incubationTask);
-}
-
-QQmlIncubator::Status QQmlTableInstanceModel::incubationStatus(int index) {
- const auto modelItem = m_modelItems.value(index, nullptr);
- if (!modelItem)
- return QQmlIncubator::Null;
-
- if (modelItem->incubationTask)
- return modelItem->incubationTask->status();
-
- // Since we clear the incubation task when we're done
- // incubating, it means that the status is Ready.
- return QQmlIncubator::Ready;
-}
-
-void QQmlTableInstanceModel::deleteIncubationTaskLater(QQmlIncubator *incubationTask)
-{
- // We often need to post-delete incubation tasks, since we cannot
- // delete them while we're in the middle of an incubation change callback.
- Q_ASSERT(!m_finishedIncubationTasks.contains(incubationTask));
- m_finishedIncubationTasks.append(incubationTask);
- if (m_finishedIncubationTasks.count() == 1)
- QTimer::singleShot(1, this, &QQmlTableInstanceModel::deleteAllFinishedIncubationTasks);
-}
-
-void QQmlTableInstanceModel::deleteAllFinishedIncubationTasks()
-{
- qDeleteAll(m_finishedIncubationTasks);
- m_finishedIncubationTasks.clear();
-}
-
-QVariant QQmlTableInstanceModel::model() const
-{
- return m_adaptorModel.model();
-}
-
-void QQmlTableInstanceModel::setModel(const QVariant &model)
-{
- // Pooled items are still accessible/alive for the application, and
- // needs to stay in sync with the model. So we need to drain the pool
- // completely when the model changes.
- drainReusableItemsPool(0);
- if (auto const aim = abstractItemModel())
- disconnect(aim, &QAbstractItemModel::dataChanged, this, &QQmlTableInstanceModel::dataChangedCallback);
- m_adaptorModel.setModel(model, this, m_qmlContext->engine());
- if (auto const aim = abstractItemModel())
- connect(aim, &QAbstractItemModel::dataChanged, this, &QQmlTableInstanceModel::dataChangedCallback);
-}
-
-void QQmlTableInstanceModel::dataChangedCallback(const QModelIndex &begin, const QModelIndex &end, const QVector<int> &roles)
-{
- // This function is called when model data has changed. In that case, we tell the adaptor model
- // to go through all the items we have created, find the ones that are affected, and notify that
- // their model data has changed. This will in turn update QML bindings inside the delegate items.
- int numberOfRowsChanged = end.row() - begin.row() + 1;
- int numberOfColumnsChanged = end.column() - begin.column() + 1;
-
- for (int column = 0; column < numberOfColumnsChanged; ++column) {
- const int columnIndex = begin.column() + column;
- const int rowIndex = begin.row() + (columnIndex * rows());
- m_adaptorModel.notify(m_modelItems.values(), rowIndex, numberOfRowsChanged, roles);
- }
-}
-
-QQmlComponent *QQmlTableInstanceModel::delegate() const
-{
- return m_delegate;
-}
-
-void QQmlTableInstanceModel::setDelegate(QQmlComponent *delegate)
-{
- if (m_delegate == delegate)
- return;
-
- m_delegateChooser = nullptr;
- if (delegate) {
- QQmlAbstractDelegateComponent *adc =
- qobject_cast<QQmlAbstractDelegateComponent *>(delegate);
- if (adc)
- m_delegateChooser = adc;
- }
-
- m_delegate = delegate;
-}
-
-const QAbstractItemModel *QQmlTableInstanceModel::abstractItemModel() const
-{
- return m_adaptorModel.adaptsAim() ? m_adaptorModel.aim() : nullptr;
-}
-
-// --------------------------------------------------------
-
-void QQmlTableInstanceModelIncubationTask::setInitialState(QObject *object)
-{
- modelItemToIncubate->object = object;
- emit tableInstanceModel->initItem(modelItemToIncubate->index, object);
-}
-
-void QQmlTableInstanceModelIncubationTask::statusChanged(QQmlIncubator::Status status)
-{
- if (!QQmlTableInstanceModel::isDoneIncubating(modelItemToIncubate))
- return;
-
- // We require the view to cancel any ongoing load
- // requests before the tableInstanceModel is destructed.
- Q_ASSERT(tableInstanceModel);
-
- tableInstanceModel->incubatorStatusChanged(this, status);
-}
-
-#include "moc_qqmltableinstancemodel_p.cpp"
-
-QT_END_NAMESPACE
-
diff --git a/src/qml/types/qqmltableinstancemodel_p.h b/src/qml/types/qqmltableinstancemodel_p.h
deleted file mode 100644
index 39ec66d136..0000000000
--- a/src/qml/types/qqmltableinstancemodel_p.h
+++ /dev/null
@@ -1,162 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 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 QQMLTABLEINSTANCEMODEL_P_H
-#define QQMLTABLEINSTANCEMODEL_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 <QtQml/private/qqmldelegatemodel_p.h>
-#include <QtQml/private/qqmldelegatemodel_p_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QQmlTableInstanceModel;
-class QQmlAbstractDelegateComponent;
-
-class QQmlTableInstanceModelIncubationTask : public QQDMIncubationTask
-{
-public:
- QQmlTableInstanceModelIncubationTask(
- QQmlTableInstanceModel *tableInstanceModel
- , QQmlDelegateModelItem* modelItemToIncubate
- , IncubationMode mode)
- : QQDMIncubationTask(nullptr, mode)
- , modelItemToIncubate(modelItemToIncubate)
- , tableInstanceModel(tableInstanceModel) {
- clear();
- }
-
- void statusChanged(Status status) override;
- void setInitialState(QObject *object) override;
-
- QQmlDelegateModelItem *modelItemToIncubate = nullptr;
- QQmlTableInstanceModel *tableInstanceModel = nullptr;
-};
-
-class Q_QML_PRIVATE_EXPORT QQmlTableInstanceModel : public QQmlInstanceModel
-{
- Q_OBJECT
-
-public:
-
- enum ReusableFlag {
- NotReusable,
- Reusable
- };
-
- QQmlTableInstanceModel(QQmlContext *qmlContext, QObject *parent = nullptr);
- ~QQmlTableInstanceModel() override;
-
- void useImportVersion(int minorVersion);
-
- int count() const override { return m_adaptorModel.count(); }
- int rows() const { return m_adaptorModel.rowCount(); }
- int columns() const { return m_adaptorModel.columnCount(); }
-
- bool isValid() const override { return true; }
-
- QVariant model() const;
- void setModel(const QVariant &model);
-
- QQmlComponent *delegate() const;
- void setDelegate(QQmlComponent *);
-
- const QAbstractItemModel *abstractItemModel() const override;
-
- QObject *object(int index, QQmlIncubator::IncubationMode incubationMode = QQmlIncubator::AsynchronousIfNested) override;
- ReleaseFlags release(QObject *object) override { return release(object, NotReusable); }
- ReleaseFlags release(QObject *object, ReusableFlag reusable);
- void cancel(int) override;
-
- void insertIntoReusableItemsPool(QQmlDelegateModelItem *modelItem);
- QQmlDelegateModelItem *takeFromReusableItemsPool(const QQmlComponent *delegate);
- void drainReusableItemsPool(int maxPoolTime);
- int poolSize() { return m_reusableItemsPool.size(); }
- void reuseItem(QQmlDelegateModelItem *item, int newModelIndex);
-
- QQmlIncubator::Status incubationStatus(int index) override;
-
- QVariant variantValue(int, const QString &) override { Q_UNREACHABLE(); return QVariant(); }
- void setWatchedRoles(const QList<QByteArray> &) override { Q_UNREACHABLE(); }
- int indexOf(QObject *, QObject *) const override { Q_UNREACHABLE(); return 0; }
-
-Q_SIGNALS:
- void itemPooled(int index, QObject *object);
- void itemReused(int index, QObject *object);
-
-private:
- QQmlComponent *resolveDelegate(int index);
-
- QQmlAdaptorModel m_adaptorModel;
- QQmlAbstractDelegateComponent *m_delegateChooser = nullptr;
- QQmlComponent *m_delegate = nullptr;
- QPointer<QQmlContext> m_qmlContext;
- QQmlDelegateModelItemMetaType *m_metaType;
-
- QHash<int, QQmlDelegateModelItem *> m_modelItems;
- QList<QQmlDelegateModelItem *> m_reusableItemsPool;
- QList<QQmlIncubator *> m_finishedIncubationTasks;
-
- void incubateModelItem(QQmlDelegateModelItem *modelItem, QQmlIncubator::IncubationMode incubationMode);
- void incubatorStatusChanged(QQmlTableInstanceModelIncubationTask *dmIncubationTask, QQmlIncubator::Status status);
- void deleteIncubationTaskLater(QQmlIncubator *incubationTask);
- void deleteAllFinishedIncubationTasks();
- QQmlDelegateModelItem *resolveModelItem(int index);
-
- void dataChangedCallback(const QModelIndex &begin, const QModelIndex &end, const QVector<int> &roles);
-
- static bool isDoneIncubating(QQmlDelegateModelItem *modelItem);
- static void deleteModelItemLater(QQmlDelegateModelItem *modelItem);
-
- friend class QQmlTableInstanceModelIncubationTask;
-};
-
-QT_END_NAMESPACE
-
-#endif // QQMLTABLEINSTANCEMODEL_P_H
diff --git a/src/qml/types/qqmltablemodel.cpp b/src/qml/types/qqmltablemodel.cpp
deleted file mode 100644
index 4a96e7a46b..0000000000
--- a/src/qml/types/qqmltablemodel.cpp
+++ /dev/null
@@ -1,1059 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 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 "qqmltablemodel_p.h"
-
-#include <QtCore/qloggingcategory.h>
-#include <QtQml/qqmlinfo.h>
-#include <QtQml/qqmlengine.h>
-
-QT_BEGIN_NAMESPACE
-
-Q_LOGGING_CATEGORY(lcTableModel, "qt.qml.tablemodel")
-
-/*!
- \qmltype TableModel
- \instantiates QQmlTableModel
- \inqmlmodule Qt.labs.qmlmodels
- \brief Encapsulates a simple table model.
- \since 5.14
-
- The TableModel type stores JavaScript/JSON objects as data for a table
- model that can be used with \l TableView. It is intended to support
- very simple models without requiring the creation of a custom
- QAbstractTableModel subclass in C++.
-
- \snippet qml/tablemodel/fruit-example-simpledelegate.qml file
-
- The model's initial row data is set with either the \l rows property or by
- calling \l appendRow(). Each column in the model is specified by declaring
- a \l TableModelColumn instance, where the order of each instance determines
- its column index. Once the model's \l Component.completed() signal has been
- emitted, the columns and roles will have been established and are then
- fixed for the lifetime of the model.
-
- To access a specific row, the \l getRow() function can be used.
- It's also possible to access the model's JavaScript data
- directly via the \l rows property, but it is not possible to
- modify the model data this way.
-
- To add new rows, use \l appendRow() and \l insertRow(). To modify
- existing rows, use \l setRow(), \l moveRow(), \l removeRow(), and
- \l clear().
-
- It is also possible to modify the model's data via the delegate,
- as shown in the example above:
-
- \snippet qml/tablemodel/fruit-example-simpledelegate.qml delegate
-
- If the type of the data at the modified role does not match the type of the
- data that is set, it will be automatically converted via
- \l {QVariant::canConvert()}{QVariant}.
-
- \section1 Supported Row Data Structures
-
- TableModel is designed to work with JavaScript/JSON data, where each row
- is a simple key-pair object:
-
- \code
- {
- // Each property is one cell/column.
- checked: false,
- amount: 1,
- fruitType: "Apple",
- fruitName: "Granny Smith",
- fruitPrice: 1.50
- },
- // ...
- \endcode
-
- As model manipulation in Qt is done via row and column indices,
- and because object keys are unordered, each column must be specified via
- TableModelColumn. This allows mapping Qt's built-in roles to any property
- in each row object.
-
- Complex row structures are supported, but with limited functionality.
- As TableModel has no way of knowing how each row is structured,
- it cannot manipulate it. As a consequence of this, the copy of the
- model data that TableModel has stored in \l rows is not kept in sync
- with the source data that was set in QML. For these reasons, TableModel
- relies on the user to handle simple data manipulation.
-
- For example, suppose you wanted to have several roles per column. One way
- of doing this is to use a data source where each row is an array and each
- cell is an object. To use this data source with TableModel, define a
- getter and setter:
-
- \code
- TableModel {
- TableModelColumn {
- display: function(modelIndex) { return rows[modelIndex.row][0].checked }
- setDisplay: function(modelIndex, cellData) { rows[modelIndex.row][0].checked = cellData }
- }
- // ...
-
- rows: [
- [
- { checked: false, checkable: true },
- { amount: 1 },
- { fruitType: "Apple" },
- { fruitName: "Granny Smith" },
- { fruitPrice: 1.50 }
- ]
- // ...
- ]
- }
- \endcode
-
- The row above is one example of a complex row.
-
- \note Row manipulation functions such as \l appendRow(), \l removeRow(),
- etc. are not supported when using complex rows.
-
- \section1 Using DelegateChooser with TableModel
-
- For most real world use cases, it is recommended to use DelegateChooser
- as the delegate of a TableView that uses TableModel. This allows you to
- use specific roles in the relevant delegates. For example, the snippet
- above can be rewritten to use DelegateChooser like so:
-
- \snippet qml/tablemodel/fruit-example-delegatechooser.qml file
-
- The most specific delegates are declared first: the columns at index \c 0
- and \c 1 have \c bool and \c integer data types, so they use a
- \l [QtQuickControls2]{CheckBox} and \l [QtQuickControls2]{SpinBox},
- respectively. The remaining columns can simply use a
- \l [QtQuickControls2]{TextField}, and so that delegate is declared
- last as a fallback.
-
- \sa TableModelColumn, TableView, QAbstractTableModel
-*/
-
-QQmlTableModel::QQmlTableModel(QObject *parent)
- : QAbstractTableModel(parent)
-{
-}
-
-QQmlTableModel::~QQmlTableModel()
-{
-}
-
-/*!
- \qmlproperty object TableModel::rows
-
- This property holds the model data in the form of an array of rows:
-
- \snippet qml/tablemodel/fruit-example-simpledelegate.qml rows
-
- \sa getRow(), setRow(), moveRow(), appendRow(), insertRow(), clear(), rowCount, columnCount
-*/
-QVariant QQmlTableModel::rows() const
-{
- return mRows;
-}
-
-void QQmlTableModel::setRows(const QVariant &rows)
-{
- if (rows.userType() != qMetaTypeId<QJSValue>()) {
- qmlWarning(this) << "setRows(): \"rows\" must be an array; actual type is " << rows.typeName();
- return;
- }
-
- const QJSValue rowsAsJSValue = rows.value<QJSValue>();
- const QVariantList rowsAsVariantList = rowsAsJSValue.toVariant().toList();
- if (rowsAsVariantList == mRows) {
- // No change.
- return;
- }
-
- if (!componentCompleted) {
- // Store the rows until we can call doSetRows() after component completion.
- mRows = rowsAsVariantList;
- return;
- }
-
- doSetRows(rowsAsVariantList);
-}
-
-void QQmlTableModel::doSetRows(const QVariantList &rowsAsVariantList)
-{
- Q_ASSERT(componentCompleted);
-
- // By now, all TableModelColumns should have been set.
- if (mColumns.isEmpty()) {
- qmlWarning(this) << "No TableModelColumns were set; model will be empty";
- return;
- }
-
- const bool firstTimeValidRowsHaveBeenSet = mColumnMetadata.isEmpty();
- if (!firstTimeValidRowsHaveBeenSet) {
- // This is not the first time rows have been set; validate each one.
- for (int rowIndex = 0; rowIndex < rowsAsVariantList.size(); ++rowIndex) {
- // validateNewRow() expects a QVariant wrapping a QJSValue, so to
- // simplify the code, just create one here.
- const QVariant row = QVariant::fromValue(rowsAsVariantList.at(rowIndex));
- if (!validateNewRow("setRows()", row, rowIndex, SetRowsOperation))
- return;
- }
- }
-
- const int oldRowCount = mRowCount;
- const int oldColumnCount = mColumnCount;
-
- beginResetModel();
-
- // We don't clear the column or role data, because a TableModel should not be reused in that way.
- // Once it has valid data, its columns and roles are fixed.
- mRows = rowsAsVariantList;
- mRowCount = mRows.size();
-
- // Gather metadata the first time rows is set.
- if (firstTimeValidRowsHaveBeenSet && !mRows.isEmpty())
- fetchColumnMetadata();
-
- endResetModel();
-
- emit rowsChanged();
-
- if (mRowCount != oldRowCount)
- emit rowCountChanged();
- if (mColumnCount != oldColumnCount)
- emit columnCountChanged();
-}
-
-QQmlTableModel::ColumnRoleMetadata QQmlTableModel::fetchColumnRoleData(const QString &roleNameKey,
- QQmlTableModelColumn *tableModelColumn, int columnIndex) const
-{
- const QVariant firstRow = mRows.first();
- ColumnRoleMetadata roleData;
-
- QJSValue columnRoleGetter = tableModelColumn->getterAtRole(roleNameKey);
- if (columnRoleGetter.isUndefined()) {
- // This role is not defined, which is fine; just skip it.
- return roleData;
- }
-
- if (columnRoleGetter.isString()) {
- // The role is set as a string, so we assume the row is a simple object.
- if (firstRow.type() != QVariant::Map) {
- qmlWarning(this).quote() << "expected row for role "
- << roleNameKey << " of TableModelColumn at index "
- << columnIndex << " to be a simple object, but it's "
- << firstRow.typeName() << " instead: " << firstRow;
- return roleData;
- }
- const QVariantMap firstRowAsMap = firstRow.toMap();
- const QString rolePropertyName = columnRoleGetter.toString();
- const QVariant roleProperty = firstRowAsMap.value(rolePropertyName);
-
- roleData.isStringRole = true;
- roleData.name = rolePropertyName;
- roleData.type = roleProperty.type();
- roleData.typeName = QString::fromLatin1(roleProperty.typeName());
- } else if (columnRoleGetter.isCallable()) {
- // The role is provided via a function, which means the row is complex and
- // the user needs to provide the data for it.
- const auto modelIndex = index(0, columnIndex);
- const auto args = QJSValueList() << qmlEngine(this)->toScriptValue(modelIndex);
- const QVariant cellData = columnRoleGetter.call(args).toVariant();
-
- // We don't know the property name since it's provided through the function.
- // roleData.name = ???
- roleData.isStringRole = false;
- roleData.type = cellData.type();
- roleData.typeName = QString::fromLatin1(cellData.typeName());
- } else {
- // Invalid role.
- qmlWarning(this) << "TableModelColumn role for column at index "
- << columnIndex << " must be either a string or a function; actual type is: "
- << columnRoleGetter.toString();
- }
-
- return roleData;
-}
-
-void QQmlTableModel::fetchColumnMetadata()
-{
- qCDebug(lcTableModel) << "gathering metadata for" << mColumnCount << "columns from first row:";
-
- static const auto supportedRoleNames = QQmlTableModelColumn::supportedRoleNames();
-
- // Since we support different data structures at the row level, we require that there
- // is a TableModelColumn for each column.
- // Collect and cache metadata for each column. This makes data lookup faster.
- for (int columnIndex = 0; columnIndex < mColumns.size(); ++columnIndex) {
- QQmlTableModelColumn *column = mColumns.at(columnIndex);
- qCDebug(lcTableModel).nospace() << "- column " << columnIndex << ":";
-
- ColumnMetadata metaData;
- const auto builtInRoleKeys = supportedRoleNames.keys();
- for (const int builtInRoleKey : builtInRoleKeys) {
- const QString builtInRoleName = supportedRoleNames.value(builtInRoleKey);
- ColumnRoleMetadata roleData = fetchColumnRoleData(builtInRoleName, column, columnIndex);
- if (roleData.type == QVariant::Invalid) {
- // This built-in role was not specified in this column.
- continue;
- }
-
- qCDebug(lcTableModel).nospace() << " - added metadata for built-in role "
- << builtInRoleName << " at column index " << columnIndex
- << ": name=" << roleData.name << " typeName=" << roleData.typeName
- << " type=" << roleData.type;
-
- // This column now supports this specific built-in role.
- metaData.roles.insert(builtInRoleName, roleData);
- // Add it if it doesn't already exist.
- mRoleNames[builtInRoleKey] = builtInRoleName.toLatin1();
- }
- mColumnMetadata.insert(columnIndex, metaData);
- }
-}
-
-/*!
- \qmlmethod TableModel::appendRow(object row)
-
- Adds a new row to the end of the model, with the
- values (cells) in \a row.
-
- \code
- model.appendRow({
- checkable: true,
- amount: 1,
- fruitType: "Pear",
- fruitName: "Williams",
- fruitPrice: 1.50,
- })
- \endcode
-
- \sa insertRow(), setRow(), removeRow()
-*/
-void QQmlTableModel::appendRow(const QVariant &row)
-{
- if (!validateNewRow("appendRow()", row, -1, AppendOperation))
- return;
-
- doInsert(mRowCount, row);
-}
-
-/*!
- \qmlmethod TableModel::clear()
-
- Removes all rows from the model.
-
- \sa removeRow()
-*/
-void QQmlTableModel::clear()
-{
- QQmlEngine *engine = qmlEngine(this);
- Q_ASSERT(engine);
- setRows(QVariant::fromValue(engine->newArray()));
-}
-
-/*!
- \qmlmethod object TableModel::getRow(int rowIndex)
-
- Returns the row at \a rowIndex in the model.
-
- Note that this equivalent to accessing the row directly
- through the \l rows property:
-
- \code
- Component.onCompleted: {
- // These two lines are equivalent.
- console.log(model.getRow(0).display);
- console.log(model.rows[0].fruitName);
- }
- \endcode
-
- \note the returned object cannot be used to modify the contents of the
- model; use setRow() instead.
-
- \sa setRow(), appendRow(), insertRow(), removeRow(), moveRow()
-*/
-QVariant QQmlTableModel::getRow(int rowIndex)
-{
- if (!validateRowIndex("getRow()", "rowIndex", rowIndex))
- return QVariant();
-
- return mRows.at(rowIndex);
-}
-
-/*!
- \qmlmethod TableModel::insertRow(int rowIndex, object row)
-
- Adds a new row to the list model at position \a rowIndex, with the
- values (cells) in \a row.
-
- \code
- model.insertRow(2, {
- checkable: true, checked: false,
- amount: 1,
- fruitType: "Pear",
- fruitName: "Williams",
- fruitPrice: 1.50,
- })
- \endcode
-
- The \a rowIndex must be to an existing item in the list, or one past
- the end of the list (equivalent to \l appendRow()).
-
- \sa appendRow(), setRow(), removeRow(), rowCount
-*/
-void QQmlTableModel::insertRow(int rowIndex, const QVariant &row)
-{
- if (!validateNewRow("insertRow()", row, rowIndex))
- return;
-
- doInsert(rowIndex, row);
-}
-
-void QQmlTableModel::doInsert(int rowIndex, const QVariant &row)
-{
- beginInsertRows(QModelIndex(), rowIndex, rowIndex);
-
- // Adding rowAsVariant.toList() will add each invidual variant in the list,
- // which is definitely not what we want.
- const QVariant rowAsVariant = row.value<QJSValue>().toVariant();
- mRows.insert(rowIndex, rowAsVariant);
- ++mRowCount;
-
- qCDebug(lcTableModel).nospace() << "inserted the following row to the model at index "
- << rowIndex << ":\n" << rowAsVariant.toMap();
-
- // Gather metadata the first time a row is added.
- if (mColumnMetadata.isEmpty())
- fetchColumnMetadata();
-
- endInsertRows();
- emit rowCountChanged();
-}
-
-void QQmlTableModel::classBegin()
-{
-}
-
-void QQmlTableModel::componentComplete()
-{
- componentCompleted = true;
-
- mColumnCount = mColumns.size();
- if (mColumnCount > 0)
- emit columnCountChanged();
-
- doSetRows(mRows);
-}
-
-/*!
- \qmlmethod TableModel::moveRow(int fromRowIndex, int toRowIndex, int rows)
-
- Moves \a rows from the index at \a fromRowIndex to the index at
- \a toRowIndex.
-
- The from and to ranges must exist; for example, to move the first 3 items
- to the end of the list:
-
- \code
- model.moveRow(0, model.rowCount - 3, 3)
- \endcode
-
- \sa appendRow(), insertRow(), removeRow(), rowCount
-*/
-void QQmlTableModel::moveRow(int fromRowIndex, int toRowIndex, int rows)
-{
- if (fromRowIndex == toRowIndex) {
- qmlWarning(this) << "moveRow(): \"fromRowIndex\" cannot be equal to \"toRowIndex\"";
- return;
- }
-
- if (rows <= 0) {
- qmlWarning(this) << "moveRow(): \"rows\" is less than or equal to 0";
- return;
- }
-
- if (!validateRowIndex("moveRow()", "fromRowIndex", fromRowIndex))
- return;
-
- if (!validateRowIndex("moveRow()", "toRowIndex", toRowIndex))
- return;
-
- if (fromRowIndex + rows > mRowCount) {
- qmlWarning(this) << "moveRow(): \"fromRowIndex\" (" << fromRowIndex
- << ") + \"rows\" (" << rows << ") = " << (fromRowIndex + rows)
- << ", which is greater than rowCount() of " << mRowCount;
- return;
- }
-
- if (toRowIndex + rows > mRowCount) {
- qmlWarning(this) << "moveRow(): \"toRowIndex\" (" << toRowIndex
- << ") + \"rows\" (" << rows << ") = " << (toRowIndex + rows)
- << ", which is greater than rowCount() of " << mRowCount;
- return;
- }
-
- qCDebug(lcTableModel).nospace() << "moving " << rows
- << " row(s) from index " << fromRowIndex
- << " to index " << toRowIndex;
-
- // Based on the same call in QQmlListModel::moveRow().
- beginMoveRows(QModelIndex(), fromRowIndex, fromRowIndex + rows - 1, QModelIndex(),
- toRowIndex > fromRowIndex ? toRowIndex + rows : toRowIndex);
-
- // Based on ListModel::moveRow().
- if (fromRowIndex > toRowIndex) {
- // Only move forwards - flip if moving backwards.
- const int from = fromRowIndex;
- const int to = toRowIndex;
- fromRowIndex = to;
- toRowIndex = to + rows;
- rows = from - to;
- }
-
- QVector<QVariant> store;
- store.reserve(rows);
- for (int i = 0; i < (toRowIndex - fromRowIndex); ++i)
- store.append(mRows.at(fromRowIndex + rows + i));
- for (int i = 0; i < rows; ++i)
- store.append(mRows.at(fromRowIndex + i));
- for (int i = 0; i < store.size(); ++i)
- mRows[fromRowIndex + i] = store[i];
-
- qCDebug(lcTableModel).nospace() << "after moving, rows are:\n" << mRows;
-
- endMoveRows();
-}
-
-/*!
- \qmlmethod TableModel::removeRow(int rowIndex, int rows = 1)
-
- Removes the row at \a rowIndex from the model.
-
- \sa clear(), rowCount
-*/
-void QQmlTableModel::removeRow(int rowIndex, int rows)
-{
- if (!validateRowIndex("removeRow()", "rowIndex", rowIndex))
- return;
-
- if (rows <= 0) {
- qmlWarning(this) << "removeRow(): \"rows\" is less than or equal to zero";
- return;
- }
-
- if (rowIndex + rows - 1 >= mRowCount) {
- qmlWarning(this) << "removeRow(): \"rows\" " << rows
- << " exceeds available rowCount() of " << mRowCount
- << " when removing from \"rowIndex\" " << rowIndex;
- return;
- }
-
- beginRemoveRows(QModelIndex(), rowIndex, rowIndex + rows - 1);
-
- auto firstIterator = mRows.begin() + rowIndex;
- // The "last" argument to erase() is exclusive, so we go one past the last item.
- auto lastIterator = firstIterator + rows;
- mRows.erase(firstIterator, lastIterator);
- mRowCount -= rows;
-
- endRemoveRows();
- emit rowCountChanged();
-
- qCDebug(lcTableModel).nospace() << "removed " << rows
- << " items from the model, starting at index " << rowIndex;
-}
-
-/*!
- \qmlmethod TableModel::setRow(int rowIndex, object row)
-
- Changes the row at \a rowIndex in the model with \a row.
-
- All columns/cells must be present in \c row, and in the correct order.
-
- \code
- model.setRow(0, {
- checkable: true,
- amount: 1,
- fruitType: "Pear",
- fruitName: "Williams",
- fruitPrice: 1.50,
- })
- \endcode
-
- If \a rowIndex is equal to \c rowCount(), then a new row is appended to the
- model. Otherwise, \a rowIndex must point to an existing row in the model.
-
- \sa appendRow(), insertRow(), rowCount
-*/
-void QQmlTableModel::setRow(int rowIndex, const QVariant &row)
-{
- if (!validateNewRow("setRow()", row, rowIndex))
- return;
-
- if (rowIndex != mRowCount) {
- // Setting an existing row.
- mRows[rowIndex] = row;
-
- // For now we just assume the whole row changed, as it's simpler.
- const QModelIndex topLeftModelIndex(createIndex(rowIndex, 0));
- const QModelIndex bottomRightModelIndex(createIndex(rowIndex, mColumnCount - 1));
- emit dataChanged(topLeftModelIndex, bottomRightModelIndex);
- } else {
- // Appending a row.
- doInsert(rowIndex, row);
- }
-}
-
-QQmlListProperty<QQmlTableModelColumn> QQmlTableModel::columns()
-{
- return QQmlListProperty<QQmlTableModelColumn>(this, nullptr,
- &QQmlTableModel::columns_append,
- &QQmlTableModel::columns_count,
- &QQmlTableModel::columns_at,
- &QQmlTableModel::columns_clear);
-}
-
-void QQmlTableModel::columns_append(QQmlListProperty<QQmlTableModelColumn> *property,
- QQmlTableModelColumn *value)
-{
- QQmlTableModel *model = static_cast<QQmlTableModel*>(property->object);
- QQmlTableModelColumn *column = qobject_cast<QQmlTableModelColumn*>(value);
- if (column)
- model->mColumns.append(column);
-}
-
-int QQmlTableModel::columns_count(QQmlListProperty<QQmlTableModelColumn> *property)
-{
- const QQmlTableModel *model = static_cast<QQmlTableModel*>(property->object);
- return model->mColumns.count();
-}
-
-QQmlTableModelColumn *QQmlTableModel::columns_at(QQmlListProperty<QQmlTableModelColumn> *property, int index)
-{
- const QQmlTableModel *model = static_cast<QQmlTableModel*>(property->object);
- return model->mColumns.at(index);
-}
-
-void QQmlTableModel::columns_clear(QQmlListProperty<QQmlTableModelColumn> *property)
-{
- QQmlTableModel *model = static_cast<QQmlTableModel*>(property->object);
- return model->mColumns.clear();
-}
-
-/*!
- \qmlmethod QModelIndex TableModel::index(int row, int column)
-
- Returns a \l QModelIndex object referencing the given \a row and \a column,
- which can be passed to the data() function to get the data from that cell,
- or to setData() to edit the contents of that cell.
-
- \code
- import QtQml 2.14
- import Qt.labs.qmlmodels 1.0
-
- TableModel {
- id: model
-
- TableModelColumn { display: "fruitType" }
- TableModelColumn { display: "fruitPrice" }
-
- rows: [
- { fruitType: "Apple", fruitPrice: 1.50 },
- { fruitType: "Orange", fruitPrice: 2.50 }
- ]
-
- Component.onCompleted: {
- for (var r = 0; r < model.rowCount; ++r) {
- console.log("An " + model.data(model.index(r, 0)).display +
- " costs " + model.data(model.index(r, 1)).display.toFixed(2))
- }
- }
- }
- \endcode
-
- \sa {QModelIndex and related Classes in QML}, data()
-*/
-// Note: we don't document the parent argument, because you never need it, because
-// cells in a TableModel don't have parents. But it is there because this function is an override.
-QModelIndex QQmlTableModel::index(int row, int column, const QModelIndex &parent) const
-{
- return row >= 0 && row < rowCount() && column >= 0 && column < columnCount() && !parent.isValid()
- ? createIndex(row, column)
- : QModelIndex();
-}
-
-/*!
- \qmlproperty int TableModel::rowCount
- \readonly
-
- This read-only property holds the number of rows in the model.
-
- This value changes whenever rows are added or removed from the model.
-*/
-int QQmlTableModel::rowCount(const QModelIndex &parent) const
-{
- if (parent.isValid())
- return 0;
-
- return mRowCount;
-}
-
-/*!
- \qmlproperty int TableModel::columnCount
- \readonly
-
- This read-only property holds the number of columns in the model.
-
- The number of columns is fixed for the lifetime of the model
- after the \l rows property is set or \l appendRow() is called for the first
- time.
-*/
-int QQmlTableModel::columnCount(const QModelIndex &parent) const
-{
- if (parent.isValid())
- return 0;
-
- return mColumnCount;
-}
-
-/*!
- \qmlmethod variant TableModel::data(QModelIndex index, string role)
-
- Returns the data from the table cell at the given \a index belonging to the
- given \a role.
-
- \sa index()
-*/
-QVariant QQmlTableModel::data(const QModelIndex &index, const QString &role) const
-{
- const int iRole = mRoleNames.key(role.toUtf8(), -1);
- if (iRole >= 0)
- return data(index, iRole);
- return QVariant();
-}
-
-QVariant QQmlTableModel::data(const QModelIndex &index, int role) const
-{
- const int row = index.row();
- if (row < 0 || row >= rowCount())
- return QVariant();
-
- const int column = index.column();
- if (column < 0 || column >= columnCount())
- return QVariant();
-
- const ColumnMetadata columnMetadata = mColumnMetadata.at(index.column());
- const QString roleName = QString::fromUtf8(mRoleNames.value(role));
- if (!columnMetadata.roles.contains(roleName)) {
- qmlWarning(this) << "setData(): no role named " << roleName
- << " at column index " << column << ". The available roles for that column are: "
- << columnMetadata.roles.keys();
- return QVariant();
- }
-
- const ColumnRoleMetadata roleData = columnMetadata.roles.value(roleName);
- if (roleData.isStringRole) {
- // We know the data structure, so we can get the data for the user.
- const QVariantMap rowData = mRows.at(row).toMap();
- const QString propertyName = columnMetadata.roles.value(roleName).name;
- const QVariant value = rowData.value(propertyName);
- return value;
- }
-
- // We don't know the data structure, so the user has to modify their data themselves.
- // First, find the getter for this column and role.
- QJSValue getter = mColumns.at(column)->getterAtRole(roleName);
-
- // Then, call it and return what it returned.
- const auto args = QJSValueList() << qmlEngine(this)->toScriptValue(index);
- return getter.call(args).toVariant();
-}
-
-/*!
- \qmlmethod bool TableModel::setData(QModelIndex index, string role, variant value)
-
- Inserts or updates the data field named by \a role in the table cell at the
- given \a index with \a value. Returns true if sucessful, false if not.
-
- \sa index()
-*/
-bool QQmlTableModel::setData(const QModelIndex &index, const QString &role, const QVariant &value)
-{
- const int intRole = mRoleNames.key(role.toUtf8(), -1);
- if (intRole >= 0)
- return setData(index, value, intRole);
- return false;
-}
-
-bool QQmlTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
-{
- const int row = index.row();
- if (row < 0 || row >= rowCount())
- return false;
-
- const int column = index.column();
- if (column < 0 || column >= columnCount())
- return false;
-
- const QString roleName = QString::fromUtf8(mRoleNames.value(role));
-
- qCDebug(lcTableModel).nospace() << "setData() called with index "
- << index << ", value " << value << " and role " << roleName;
-
- // Verify that the role exists for this column.
- const ColumnMetadata columnMetadata = mColumnMetadata.at(index.column());
- if (!columnMetadata.roles.contains(roleName)) {
- qmlWarning(this) << "setData(): no role named \"" << roleName
- << "\" at column index " << column << ". The available roles for that column are: "
- << columnMetadata.roles.keys();
- return false;
- }
-
- // Verify that the type of the value is what we expect.
- // If the value set is not of the expected type, we can try to convert it automatically.
- const ColumnRoleMetadata roleData = columnMetadata.roles.value(roleName);
- QVariant effectiveValue = value;
- if (value.type() != roleData.type) {
- if (!value.canConvert(int(roleData.type))) {
- qmlWarning(this).nospace() << "setData(): the value " << value
- << " set at row " << row << " column " << column << " with role " << roleName
- << " cannot be converted to " << roleData.typeName;
- return false;
- }
-
- if (!effectiveValue.convert(int(roleData.type))) {
- qmlWarning(this).nospace() << "setData(): failed converting value " << value
- << " set at row " << row << " column " << column << " with role " << roleName
- << " to " << roleData.typeName;
- return false;
- }
- }
-
- if (roleData.isStringRole) {
- // We know the data structure, so we can set it for the user.
- QVariantMap modifiedRow = mRows.at(row).toMap();
- modifiedRow[roleData.name] = value;
-
- mRows[row] = modifiedRow;
- } else {
- // We don't know the data structure, so the user has to modify their data themselves.
- auto engine = qmlEngine(this);
- auto args = QJSValueList()
- // arg 0: modelIndex.
- << engine->toScriptValue(index)
- // arg 1: cellData.
- << engine->toScriptValue(value);
- // Do the actual setting.
- QJSValue setter = mColumns.at(column)->setterAtRole(roleName);
- setter.call(args);
-
- /*
- The chain of events so far:
-
- - User did e.g.: model.edit = textInput.text
- - setData() is called
- - setData() calls the setter
- (remember that we need to emit the dataChanged() signal,
- which is why the user can't just set the data directly in the delegate)
-
- Now the user's setter function has modified *their* copy of the
- data, but *our* copy of the data is old. Imagine the getters and setters looked like this:
-
- display: function(modelIndex) { return rows[modelIndex.row][1].amount }
- setDisplay: function(modelIndex, cellData) { rows[modelIndex.row][1].amount = cellData }
-
- We don't know the structure of the user's data, so we can't just do
- what we do above for the isStringRole case:
-
- modifiedRow[column][roleName] = value
-
- This means that, besides getting the implicit row count when rows is initially set,
- our copy of the data is unused when it comes to complex columns.
-
- Another point to note is that we can't pass rowData in to the getter as a convenience,
- because we would be passing in *our* copy of the row, which is not up-to-date.
- Since the user already has access to the data, it's not a big deal for them to do:
-
- display: function(modelIndex) { return rows[modelIndex.row][1].amount }
-
- instead of:
-
- display: function(modelIndex, rowData) { return rowData[1].amount }
- */
- }
-
- QVector<int> rolesChanged;
- rolesChanged.append(role);
- emit dataChanged(index, index, rolesChanged);
-
- return true;
-}
-
-QHash<int, QByteArray> QQmlTableModel::roleNames() const
-{
- return mRoleNames;
-}
-
-QQmlTableModel::ColumnRoleMetadata::ColumnRoleMetadata()
-{
-}
-
-QQmlTableModel::ColumnRoleMetadata::ColumnRoleMetadata(
- bool isStringRole, const QString &name, QVariant::Type type, const QString &typeName) :
- isStringRole(isStringRole),
- name(name),
- type(type),
- typeName(typeName)
-{
-}
-
-bool QQmlTableModel::ColumnRoleMetadata::isValid() const
-{
- return !name.isEmpty();
-}
-
-bool QQmlTableModel::validateRowType(const char *functionName, const QVariant &row) const
-{
- if (!row.canConvert<QJSValue>()) {
- qmlWarning(this) << functionName << ": expected \"row\" argument to be a QJSValue,"
- << " but got " << row.typeName() << " instead:\n" << row;
- return false;
- }
-
- const QJSValue rowAsJSValue = row.value<QJSValue>();
- if (!rowAsJSValue.isObject() && !rowAsJSValue.isArray()) {
- qmlWarning(this) << functionName << ": expected \"row\" argument "
- << "to be an object or array, but got:\n" << rowAsJSValue.toString();
- return false;
- }
-
- return true;
-}
-
-bool QQmlTableModel::validateNewRow(const char *functionName, const QVariant &row,
- int rowIndex, NewRowOperationFlag operation) const
-{
- if (mColumnMetadata.isEmpty()) {
- // There is no column metadata, so we have nothing to validate the row against.
- // Rows have to be added before we can gather metadata from them, so just this
- // once we'll return true to allow the rows to be added.
- return true;
- }
-
- // Don't require each row to be a QJSValue when setting all rows,
- // as they won't be; they'll be QVariantMap.
- if (operation != SetRowsOperation && !validateRowType(functionName, row))
- return false;
-
- if (operation == OtherOperation) {
- // Inserting/setting.
- if (rowIndex < 0) {
- qmlWarning(this) << functionName << ": \"rowIndex\" cannot be negative";
- return false;
- }
-
- if (rowIndex > mRowCount) {
- qmlWarning(this) << functionName << ": \"rowIndex\" " << rowIndex
- << " is greater than rowCount() of " << mRowCount;
- return false;
- }
- }
-
- const QVariant rowAsVariant = operation == SetRowsOperation
- ? row : row.value<QJSValue>().toVariant();
- if (rowAsVariant.type() != QVariant::Map) {
- qmlWarning(this) << functionName << ": row manipulation functions "
- << "do not support complex rows (row index: " << rowIndex << ")";
- return false;
- }
-
- const QVariantMap rowAsMap = rowAsVariant.toMap();
- const int columnCount = rowAsMap.size();
- if (columnCount < mColumnCount) {
- qmlWarning(this) << functionName << ": expected " << mColumnCount
- << " columns, but only got " << columnCount;
- return false;
- }
-
- // We can't validate complex structures, but we can make sure that
- // each simple string-based role in each column is correct.
- for (int columnIndex = 0; columnIndex < mColumns.size(); ++columnIndex) {
- QQmlTableModelColumn *column = mColumns.at(columnIndex);
- const QHash<QString, QJSValue> getters = column->getters();
- const auto roleNames = getters.keys();
- const ColumnMetadata columnMetadata = mColumnMetadata.at(columnIndex);
- for (const QString &roleName : roleNames) {
- const ColumnRoleMetadata roleData = columnMetadata.roles.value(roleName);
- if (!roleData.isStringRole)
- continue;
-
- if (!rowAsMap.contains(roleData.name)) {
- qmlWarning(this).quote() << functionName << ": expected a property named "
- << roleData.name << " in row at index " << rowIndex << ", but couldn't find one";
- return false;
- }
-
- const QVariant rolePropertyValue = rowAsMap.value(roleData.name);
- if (rolePropertyValue.type() != roleData.type) {
- qmlWarning(this).quote() << functionName << ": expected the property named "
- << roleData.name << " to be of type " << roleData.typeName
- << ", but got " << QString::fromLatin1(rolePropertyValue.typeName()) << " instead";
- return false;
- }
- }
- }
-
- return true;
-}
-
-bool QQmlTableModel::validateRowIndex(const char *functionName, const char *argumentName, int rowIndex) const
-{
- if (rowIndex < 0) {
- qmlWarning(this) << functionName << ": \"" << argumentName << "\" cannot be negative";
- return false;
- }
-
- if (rowIndex >= mRowCount) {
- qmlWarning(this) << functionName << ": \"" << argumentName
- << "\" " << rowIndex << " is greater than or equal to rowCount() of " << mRowCount;
- return false;
- }
-
- return true;
-}
-
-QT_END_NAMESPACE
diff --git a/src/qml/types/qqmltablemodel_p.h b/src/qml/types/qqmltablemodel_p.h
deleted file mode 100644
index a1bb97e7d4..0000000000
--- a/src/qml/types/qqmltablemodel_p.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 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 QQMLTABLEMODEL_P_H
-#define QQMLTABLEMODEL_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/QObject>
-#include <QtCore/QAbstractTableModel>
-#include <QtQml/qqml.h>
-#include <QtQml/private/qtqmlglobal_p.h>
-#include <QtQml/private/qqmltablemodelcolumn_p.h>
-#include <QtQml/QJSValue>
-#include <QtQml/QQmlListProperty>
-
-QT_BEGIN_NAMESPACE
-
-class Q_QML_PRIVATE_EXPORT QQmlTableModel : public QAbstractTableModel, public QQmlParserStatus
-{
- Q_OBJECT
- Q_PROPERTY(int columnCount READ columnCount NOTIFY columnCountChanged FINAL)
- Q_PROPERTY(int rowCount READ rowCount NOTIFY rowCountChanged FINAL)
- Q_PROPERTY(QVariant rows READ rows WRITE setRows NOTIFY rowsChanged FINAL)
- Q_PROPERTY(QQmlListProperty<QQmlTableModelColumn> columns READ columns CONSTANT FINAL)
- Q_INTERFACES(QQmlParserStatus)
- Q_CLASSINFO("DefaultProperty", "columns")
-
-public:
- QQmlTableModel(QObject *parent = nullptr);
- ~QQmlTableModel() override;
-
- QVariant rows() const;
- void setRows(const QVariant &rows);
-
- Q_INVOKABLE void appendRow(const QVariant &row);
- Q_INVOKABLE void clear();
- Q_INVOKABLE QVariant getRow(int rowIndex);
- Q_INVOKABLE void insertRow(int rowIndex, const QVariant &row);
- Q_INVOKABLE void moveRow(int fromRowIndex, int toRowIndex, int rows = 1);
- Q_INVOKABLE void removeRow(int rowIndex, int rows = 1);
- Q_INVOKABLE void setRow(int rowIndex, const QVariant &row);
-
- QQmlListProperty<QQmlTableModelColumn> columns();
-
- static void columns_append(QQmlListProperty<QQmlTableModelColumn> *property, QQmlTableModelColumn *value);
- static int columns_count(QQmlListProperty<QQmlTableModelColumn> *property);
- static QQmlTableModelColumn *columns_at(QQmlListProperty<QQmlTableModelColumn> *property, int index);
- static void columns_clear(QQmlListProperty<QQmlTableModelColumn> *property);
-
- QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
- int rowCount(const QModelIndex &parent = QModelIndex()) const override;
- int columnCount(const QModelIndex &parent = QModelIndex()) const override;
- Q_INVOKABLE QVariant data(const QModelIndex &index, const QString &role) const;
- QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
- Q_INVOKABLE bool setData(const QModelIndex &index, const QString &role, const QVariant &value);
- bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::DisplayRole) override;
- QHash<int, QByteArray> roleNames() const override;
-
-Q_SIGNALS:
- void columnCountChanged();
- void rowCountChanged();
- void rowsChanged();
-
-private:
- class ColumnRoleMetadata
- {
- public:
- ColumnRoleMetadata();
- ColumnRoleMetadata(bool isStringRole, const QString &name, QVariant::Type type, const QString &typeName);
-
- bool isValid() const;
-
- // If this is false, it's a function role.
- bool isStringRole = false;
- QString name;
- QVariant::Type type = QVariant::Invalid;
- QString typeName;
- };
-
- struct ColumnMetadata
- {
- // Key = role name that will be made visible to the delegate
- // Value = metadata about that role, including actual name in the model data, type, etc.
- QHash<QString, ColumnRoleMetadata> roles;
- };
-
- enum NewRowOperationFlag {
- OtherOperation, // insert(), set(), etc.
- SetRowsOperation,
- AppendOperation
- };
-
- void doSetRows(const QVariantList &rowsAsVariantList);
- ColumnRoleMetadata fetchColumnRoleData(const QString &roleNameKey,
- QQmlTableModelColumn *tableModelColumn, int columnIndex) const;
- void fetchColumnMetadata();
-
- bool validateRowType(const char *functionName, const QVariant &row) const;
- bool validateNewRow(const char *functionName, const QVariant &row,
- int rowIndex, NewRowOperationFlag operation = OtherOperation) const;
- bool validateRowIndex(const char *functionName, const char *argumentName, int rowIndex) const;
-
- void doInsert(int rowIndex, const QVariant &row);
-
- void classBegin() override;
- void componentComplete() override;
-
- bool componentCompleted = false;
- QVariantList mRows;
- QList<QQmlTableModelColumn *> mColumns;
- int mRowCount = 0;
- int mColumnCount = 0;
- // Each entry contains information about the properties of the column at that index.
- QVector<ColumnMetadata> mColumnMetadata;
- // key = property index (0 to number of properties across all columns)
- // value = role name
- QHash<int, QByteArray> mRoleNames;
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQmlTableModel)
-
-#endif // QQMLTABLEMODEL_P_H
diff --git a/src/qml/types/qqmltablemodelcolumn.cpp b/src/qml/types/qqmltablemodelcolumn.cpp
deleted file mode 100644
index 93da0642de..0000000000
--- a/src/qml/types/qqmltablemodelcolumn.cpp
+++ /dev/null
@@ -1,200 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 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 "qqmltablemodelcolumn_p.h"
-
-#include <QtQml/qqmlinfo.h>
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \qmltype TableModelColumn
- \instantiates QQmlTableModelColumn
- \inqmlmodule Qt.labs.qmlmodels
- \brief Represents a column in a model.
- \since 5.14
-
- \section1 Supported Roles
-
- TableModelColumn supports all of \l {Qt::ItemDataRole}{Qt's roles},
- with the exception of \c Qt::InitialSortOrderRole.
-
- \sa TableModel, TableView
-*/
-
-static const QString displayRoleName = QStringLiteral("display");
-static const QString decorationRoleName = QStringLiteral("decoration");
-static const QString editRoleName = QStringLiteral("edit");
-static const QString toolTipRoleName = QStringLiteral("toolTip");
-static const QString statusTipRoleName = QStringLiteral("statusTip");
-static const QString whatsThisRoleName = QStringLiteral("whatsThis");
-
-static const QString fontRoleName = QStringLiteral("font");
-static const QString textAlignmentRoleName = QStringLiteral("textAlignment");
-static const QString backgroundRoleName = QStringLiteral("background");
-static const QString foregroundRoleName = QStringLiteral("foreground");
-static const QString checkStateRoleName = QStringLiteral("checkState");
-
-static const QString accessibleTextRoleName = QStringLiteral("accessibleText");
-static const QString accessibleDescriptionRoleName = QStringLiteral("accessibleDescription");
-
-static const QString sizeHintRoleName = QStringLiteral("sizeHint");
-
-
-QQmlTableModelColumn::QQmlTableModelColumn(QObject *parent)
- : QObject(parent)
-{
-}
-
-QQmlTableModelColumn::~QQmlTableModelColumn()
-{
-}
-
-#define DEFINE_ROLE_PROPERTIES(getterGetterName, getterSetterName, getterSignal, setterGetterName, setterSetterName, setterSignal, roleName) \
-QJSValue QQmlTableModelColumn::getterGetterName() const \
-{ \
- return mGetters.value(roleName); \
-} \
-\
-void QQmlTableModelColumn::getterSetterName(const QJSValue &stringOrFunction) \
-{ \
- if (!stringOrFunction.isString() && !stringOrFunction.isCallable()) { \
- qmlWarning(this).quote() << "getter for " << roleName << " must be a function"; \
- return; \
- } \
- if (stringOrFunction.strictlyEquals(decoration())) \
- return; \
-\
- mGetters[roleName] = stringOrFunction; \
- emit decorationChanged(); \
-} \
-\
-QJSValue QQmlTableModelColumn::setterGetterName() const \
-{ \
- return mSetters.value(roleName); \
-} \
-\
-void QQmlTableModelColumn::setterSetterName(const QJSValue &function) \
-{ \
- if (!function.isCallable()) { \
- qmlWarning(this).quote() << "setter for " << roleName << " must be a function"; \
- return; \
- } \
-\
- if (function.strictlyEquals(getSetDisplay())) \
- return; \
-\
- mSetters[roleName] = function; \
- emit setDisplayChanged(); \
-}
-
-DEFINE_ROLE_PROPERTIES(display, setDisplay, displayChanged,
- getSetDisplay, setSetDisplay, setDisplayChanged, displayRoleName)
-DEFINE_ROLE_PROPERTIES(decoration, setDecoration, decorationChanged,
- getSetDecoration, setSetDecoration, setDecorationChanged, decorationRoleName)
-DEFINE_ROLE_PROPERTIES(edit, setEdit, editChanged,
- getSetEdit, setSetEdit, setEditChanged, editRoleName)
-DEFINE_ROLE_PROPERTIES(toolTip, setToolTip, toolTipChanged,
- getSetToolTip, setSetToolTip, setToolTipChanged, toolTipRoleName)
-DEFINE_ROLE_PROPERTIES(statusTip, setStatusTip, statusTipChanged,
- getSetStatusTip, setSetStatusTip, setStatusTipChanged, statusTipRoleName)
-DEFINE_ROLE_PROPERTIES(whatsThis, setWhatsThis, whatsThisChanged,
- getSetWhatsThis, setSetWhatsThis, setWhatsThisChanged, whatsThisRoleName)
-
-DEFINE_ROLE_PROPERTIES(font, setFont, fontChanged,
- getSetFont, setSetFont, setFontChanged, fontRoleName)
-DEFINE_ROLE_PROPERTIES(textAlignment, setTextAlignment, textAlignmentChanged,
- getSetTextAlignment, setSetTextAlignment, setTextAlignmentChanged, textAlignmentRoleName)
-DEFINE_ROLE_PROPERTIES(background, setBackground, backgroundChanged,
- getSetBackground, setSetBackground, setBackgroundChanged, backgroundRoleName)
-DEFINE_ROLE_PROPERTIES(foreground, setForeground, foregroundChanged,
- getSetForeground, setSetForeground, setForegroundChanged, foregroundRoleName)
-DEFINE_ROLE_PROPERTIES(checkState, setCheckState, checkStateChanged,
- getSetCheckState, setSetCheckState, setCheckStateChanged, checkStateRoleName)
-
-DEFINE_ROLE_PROPERTIES(accessibleText, setAccessibleText, accessibleTextChanged,
- getSetAccessibleText, setSetAccessibleText, setAccessibleTextChanged, accessibleTextRoleName)
-DEFINE_ROLE_PROPERTIES(accessibleDescription, setAccessibleDescription, accessibleDescriptionChanged,
- getSetAccessibleDescription, setSetAccessibleDescription, setAccessibleDescriptionChanged, accessibleDescriptionRoleName)
-
-DEFINE_ROLE_PROPERTIES(sizeHint, setSizeHint, sizeHintChanged,
- getSetSizeHint, setSetSizeHint, setSizeHintChanged, sizeHintRoleName)
-
-QJSValue QQmlTableModelColumn::getterAtRole(const QString &roleName)
-{
- auto it = mGetters.find(roleName);
- if (it == mGetters.end())
- return QJSValue();
- return *it;
-}
-
-QJSValue QQmlTableModelColumn::setterAtRole(const QString &roleName)
-{
- auto it = mSetters.find(roleName);
- if (it == mSetters.end())
- return QJSValue();
- return *it;
-}
-
-const QHash<QString, QJSValue> QQmlTableModelColumn::getters() const
-{
- return mGetters;
-}
-
-const QHash<int, QString> QQmlTableModelColumn::supportedRoleNames()
-{
- QHash<int, QString> names;
- names[Qt::DisplayRole] = QLatin1String("display");
- names[Qt::DecorationRole] = QLatin1String("decoration");
- names[Qt::EditRole] = QLatin1String("edit");
- names[Qt::ToolTipRole] = QLatin1String("toolTip");
- names[Qt::StatusTipRole] = QLatin1String("statusTip");
- names[Qt::WhatsThisRole] = QLatin1String("whatsThis");
- names[Qt::FontRole] = QLatin1String("font");
- names[Qt::TextAlignmentRole] = QLatin1String("textAlignment");
- names[Qt::BackgroundRole] = QLatin1String("background");
- names[Qt::ForegroundRole] = QLatin1String("foreground");
- names[Qt::CheckStateRole] = QLatin1String("checkState");
- names[Qt::AccessibleTextRole] = QLatin1String("accessibleText");
- names[Qt::AccessibleDescriptionRole] = QLatin1String("accessibleDescription");
- names[Qt::SizeHintRole] = QLatin1String("sizeHint");
- return names;
-}
-
-QT_END_NAMESPACE
diff --git a/src/qml/types/qqmltablemodelcolumn_p.h b/src/qml/types/qqmltablemodelcolumn_p.h
deleted file mode 100644
index 41c02482c0..0000000000
--- a/src/qml/types/qqmltablemodelcolumn_p.h
+++ /dev/null
@@ -1,224 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2019 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 QQMLTABLEMODELCOLUMN_P_H
-#define QQMLTABLEMODELCOLUMN_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/QObject>
-#include <QtQml/qqml.h>
-#include <QtQml/private/qtqmlglobal_p.h>
-#include <QtQml/qjsvalue.h>
-
-QT_BEGIN_NAMESPACE
-
-class Q_QML_AUTOTEST_EXPORT QQmlTableModelColumn : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(QJSValue display READ display WRITE setDisplay NOTIFY displayChanged FINAL)
- Q_PROPERTY(QJSValue setDisplay READ getSetDisplay WRITE setSetDisplay NOTIFY setDisplayChanged)
- Q_PROPERTY(QJSValue decoration READ decoration WRITE setDecoration NOTIFY decorationChanged FINAL)
- Q_PROPERTY(QJSValue setDecoration READ getSetDecoration WRITE setSetDecoration NOTIFY setDecorationChanged FINAL)
- Q_PROPERTY(QJSValue edit READ edit WRITE setEdit NOTIFY editChanged FINAL)
- Q_PROPERTY(QJSValue setEdit READ getSetEdit WRITE setSetEdit NOTIFY setEditChanged FINAL)
- Q_PROPERTY(QJSValue toolTip READ toolTip WRITE setToolTip NOTIFY toolTipChanged FINAL)
- Q_PROPERTY(QJSValue setToolTip READ getSetToolTip WRITE setSetToolTip NOTIFY setToolTipChanged FINAL)
- Q_PROPERTY(QJSValue statusTip READ statusTip WRITE setStatusTip NOTIFY statusTipChanged FINAL)
- Q_PROPERTY(QJSValue setStatusTip READ getSetStatusTip WRITE setSetStatusTip NOTIFY setStatusTipChanged FINAL)
- Q_PROPERTY(QJSValue whatsThis READ whatsThis WRITE setWhatsThis NOTIFY whatsThisChanged FINAL)
- Q_PROPERTY(QJSValue setWhatsThis READ getSetWhatsThis WRITE setSetWhatsThis NOTIFY setWhatsThisChanged FINAL)
-
- Q_PROPERTY(QJSValue font READ font WRITE setFont NOTIFY fontChanged FINAL)
- Q_PROPERTY(QJSValue setFont READ getSetFont WRITE setSetFont NOTIFY setFontChanged FINAL)
- Q_PROPERTY(QJSValue textAlignment READ textAlignment WRITE setTextAlignment NOTIFY textAlignmentChanged FINAL)
- Q_PROPERTY(QJSValue setTextAlignment READ getSetTextAlignment WRITE setSetTextAlignment NOTIFY setTextAlignmentChanged FINAL)
- Q_PROPERTY(QJSValue background READ background WRITE setBackground NOTIFY backgroundChanged FINAL)
- Q_PROPERTY(QJSValue setBackground READ getSetBackground WRITE setSetBackground NOTIFY setBackgroundChanged FINAL)
- Q_PROPERTY(QJSValue foreground READ foreground WRITE setForeground NOTIFY foregroundChanged FINAL)
- Q_PROPERTY(QJSValue setForeground READ getSetForeground WRITE setSetForeground NOTIFY setForegroundChanged FINAL)
- Q_PROPERTY(QJSValue checkState READ checkState WRITE setCheckState NOTIFY checkStateChanged FINAL)
- Q_PROPERTY(QJSValue setCheckState READ getSetCheckState WRITE setSetCheckState NOTIFY setCheckStateChanged FINAL)
-
- Q_PROPERTY(QJSValue accessibleText READ accessibleText WRITE setAccessibleText NOTIFY accessibleTextChanged FINAL)
- Q_PROPERTY(QJSValue setAccessibleText READ getSetAccessibleText WRITE setSetAccessibleText NOTIFY setAccessibleTextChanged FINAL)
- Q_PROPERTY(QJSValue accessibleDescription READ accessibleDescription
- WRITE setAccessibleDescription NOTIFY accessibleDescriptionChanged FINAL)
- Q_PROPERTY(QJSValue setAccessibleDescription READ getSetAccessibleDescription
- WRITE setSetAccessibleDescription NOTIFY setAccessibleDescriptionChanged FINAL)
-
- Q_PROPERTY(QJSValue sizeHint READ sizeHint WRITE setSizeHint NOTIFY sizeHintChanged FINAL)
- Q_PROPERTY(QJSValue setSizeHint READ getSetSizeHint WRITE setSetSizeHint NOTIFY setSizeHintChanged FINAL)
-
-public:
- QQmlTableModelColumn(QObject *parent = nullptr);
- ~QQmlTableModelColumn() override;
-
- QJSValue display() const;
- void setDisplay(const QJSValue &stringOrFunction);
- QJSValue getSetDisplay() const;
- void setSetDisplay(const QJSValue &function);
-
- QJSValue decoration() const;
- void setDecoration(const QJSValue &stringOrFunction);
- QJSValue getSetDecoration() const;
- void setSetDecoration(const QJSValue &function);
-
- QJSValue edit() const;
- void setEdit(const QJSValue &stringOrFunction);
- QJSValue getSetEdit() const;
- void setSetEdit(const QJSValue &function);
-
- QJSValue toolTip() const;
- void setToolTip(const QJSValue &stringOrFunction);
- QJSValue getSetToolTip() const;
- void setSetToolTip(const QJSValue &function);
-
- QJSValue statusTip() const;
- void setStatusTip(const QJSValue &stringOrFunction);
- QJSValue getSetStatusTip() const;
- void setSetStatusTip(const QJSValue &function);
-
- QJSValue whatsThis() const;
- void setWhatsThis(const QJSValue &stringOrFunction);
- QJSValue getSetWhatsThis() const;
- void setSetWhatsThis(const QJSValue &function);
-
- QJSValue font() const;
- void setFont(const QJSValue &stringOrFunction);
- QJSValue getSetFont() const;
- void setSetFont(const QJSValue &function);
-
- QJSValue textAlignment() const;
- void setTextAlignment(const QJSValue &stringOrFunction);
- QJSValue getSetTextAlignment() const;
- void setSetTextAlignment(const QJSValue &function);
-
- QJSValue background() const;
- void setBackground(const QJSValue &stringOrFunction);
- QJSValue getSetBackground() const;
- void setSetBackground(const QJSValue &function);
-
- QJSValue foreground() const;
- void setForeground(const QJSValue &stringOrFunction);
- QJSValue getSetForeground() const;
- void setSetForeground(const QJSValue &function);
-
- QJSValue checkState() const;
- void setCheckState(const QJSValue &stringOrFunction);
- QJSValue getSetCheckState() const;
- void setSetCheckState(const QJSValue &function);
-
- QJSValue accessibleText() const;
- void setAccessibleText(const QJSValue &stringOrFunction);
- QJSValue getSetAccessibleText() const;
- void setSetAccessibleText(const QJSValue &function);
-
- QJSValue accessibleDescription() const;
- void setAccessibleDescription(const QJSValue &stringOrFunction);
- QJSValue getSetAccessibleDescription() const;
- void setSetAccessibleDescription(const QJSValue &function);
-
- QJSValue sizeHint() const;
- void setSizeHint(const QJSValue &stringOrFunction);
- QJSValue getSetSizeHint() const;
- void setSetSizeHint(const QJSValue &function);
-
- QJSValue getterAtRole(const QString &roleName);
- QJSValue setterAtRole(const QString &roleName);
-
- const QHash<QString, QJSValue> getters() const;
-
- static const QHash<int, QString> supportedRoleNames();
-
-Q_SIGNALS:
- void indexChanged();
- void displayChanged();
- void setDisplayChanged();
- void decorationChanged();
- void setDecorationChanged();
- void editChanged();
- void setEditChanged();
- void toolTipChanged();
- void setToolTipChanged();
- void statusTipChanged();
- void setStatusTipChanged();
- void whatsThisChanged();
- void setWhatsThisChanged();
-
- void fontChanged();
- void setFontChanged();
- void textAlignmentChanged();
- void setTextAlignmentChanged();
- void backgroundChanged();
- void setBackgroundChanged();
- void foregroundChanged();
- void setForegroundChanged();
- void checkStateChanged();
- void setCheckStateChanged();
-
- void accessibleTextChanged();
- void setAccessibleTextChanged();
- void accessibleDescriptionChanged();
- void setAccessibleDescriptionChanged();
- void sizeHintChanged();
- void setSizeHintChanged();
-
-private:
- int mIndex = -1;
-
- // We store these in hashes because QQuickTableModel needs string-based lookup in certain situations.
- QHash<QString, QJSValue> mGetters;
- QHash<QString, QJSValue> mSetters;
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQmlTableModelColumn)
-
-#endif // QQMLTABLEMODELCOLUMN_P_H
diff --git a/src/qml/types/qquickpackage.cpp b/src/qml/types/qquickpackage.cpp
deleted file mode 100644
index 03539d8737..0000000000
--- a/src/qml/types/qquickpackage.cpp
+++ /dev/null
@@ -1,198 +0,0 @@
-/****************************************************************************
-**
-** 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 "qquickpackage_p.h"
-
-#include <private/qobject_p.h>
-#include <private/qqmlguard_p.h>
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \qmltype Package
- \instantiates QQuickPackage
- \inqmlmodule QtQuick
- \ingroup qtquick-views
- \brief Specifies a collection of named items.
-
- The Package type is used in conjunction with
- DelegateModel to enable delegates with a shared context
- to be provided to multiple views.
-
- Any item within a Package may be assigned a name via the
- \l{Package::name}{Package.name} attached property.
-
- The example below creates a Package containing two named items;
- \e list and \e grid. The third item in the package (the \l Rectangle) is parented to whichever
- delegate it should appear in. This allows an item to move
- between views.
-
- \snippet package/Delegate.qml 0
-
- These named items are used as the delegates by the two views who
- reference the special \l{DelegateModel::parts} property to select
- a model which provides the chosen delegate.
-
- \snippet package/view.qml 0
-
- \sa {Qt Quick Examples - Views}, {Qt Quick Demo - Photo Viewer}, {Qt QML}
-*/
-
-/*!
- \qmlattachedproperty string QtQuick::Package::name
- This attached property holds the name of an item within a Package.
-*/
-
-
-class QQuickPackagePrivate : public QObjectPrivate
-{
-public:
- QQuickPackagePrivate() {}
-
- struct DataGuard : public QQmlGuard<QObject>
- {
- DataGuard(QObject *obj, QList<DataGuard> *l) : list(l) { (QQmlGuard<QObject>&)*this = obj; }
- QList<DataGuard> *list;
- void objectDestroyed(QObject *) override {
- // we assume priv will always be destroyed after objectDestroyed calls
- list->removeOne(*this);
- }
- };
-
- QList<DataGuard> dataList;
- static void data_append(QQmlListProperty<QObject> *prop, QObject *o) {
- QList<DataGuard> *list = static_cast<QList<DataGuard> *>(prop->data);
- list->append(DataGuard(o, list));
- }
- static void data_clear(QQmlListProperty<QObject> *prop) {
- QList<DataGuard> *list = static_cast<QList<DataGuard> *>(prop->data);
- list->clear();
- }
- static QObject *data_at(QQmlListProperty<QObject> *prop, int index) {
- QList<DataGuard> *list = static_cast<QList<DataGuard> *>(prop->data);
- return list->at(index);
- }
- static int data_count(QQmlListProperty<QObject> *prop) {
- QList<DataGuard> *list = static_cast<QList<DataGuard> *>(prop->data);
- return list->count();
- }
-};
-
-QHash<QObject *, QQuickPackageAttached *> QQuickPackageAttached::attached;
-
-QQuickPackageAttached::QQuickPackageAttached(QObject *parent)
-: QObject(parent)
-{
- attached.insert(parent, this);
-}
-
-QQuickPackageAttached::~QQuickPackageAttached()
-{
- attached.remove(parent());
-}
-
-QString QQuickPackageAttached::name() const
-{
- return _name;
-}
-
-void QQuickPackageAttached::setName(const QString &n)
-{
- _name = n;
-}
-
-QQuickPackage::QQuickPackage(QObject *parent)
- : QObject(*(new QQuickPackagePrivate), parent)
-{
-}
-
-QQuickPackage::~QQuickPackage()
-{
-}
-
-QQmlListProperty<QObject> QQuickPackage::data()
-{
- Q_D(QQuickPackage);
- return QQmlListProperty<QObject>(this, &d->dataList, QQuickPackagePrivate::data_append,
- QQuickPackagePrivate::data_count,
- QQuickPackagePrivate::data_at,
- QQuickPackagePrivate::data_clear);
-}
-
-bool QQuickPackage::hasPart(const QString &name)
-{
- Q_D(QQuickPackage);
- for (int ii = 0; ii < d->dataList.count(); ++ii) {
- QObject *obj = d->dataList.at(ii);
- QQuickPackageAttached *a = QQuickPackageAttached::attached.value(obj);
- if (a && a->name() == name)
- return true;
- }
- return false;
-}
-
-QObject *QQuickPackage::part(const QString &name)
-{
- Q_D(QQuickPackage);
- if (name.isEmpty() && !d->dataList.isEmpty())
- return d->dataList.at(0);
-
- for (int ii = 0; ii < d->dataList.count(); ++ii) {
- QObject *obj = d->dataList.at(ii);
- QQuickPackageAttached *a = QQuickPackageAttached::attached.value(obj);
- if (a && a->name() == name)
- return obj;
- }
-
- if (name == QLatin1String("default") && !d->dataList.isEmpty())
- return d->dataList.at(0);
-
- return nullptr;
-}
-
-QQuickPackageAttached *QQuickPackage::qmlAttachedProperties(QObject *o)
-{
- return new QQuickPackageAttached(o);
-}
-
-
-
-QT_END_NAMESPACE
-
-#include "moc_qquickpackage_p.cpp"
diff --git a/src/qml/types/qquickpackage_p.h b/src/qml/types/qquickpackage_p.h
deleted file mode 100644
index 122c7fcb30..0000000000
--- a/src/qml/types/qquickpackage_p.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/****************************************************************************
-**
-** 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 QQUICKPACKAGE_H
-#define QQUICKPACKAGE_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 <qqml.h>
-
-QT_BEGIN_NAMESPACE
-
-class QQuickPackagePrivate;
-class QQuickPackageAttached;
-class Q_AUTOTEST_EXPORT QQuickPackage : public QObject
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QQuickPackage)
-
- Q_CLASSINFO("DefaultProperty", "data")
- Q_PROPERTY(QQmlListProperty<QObject> data READ data)
-
-public:
- QQuickPackage(QObject *parent=nullptr);
- virtual ~QQuickPackage();
-
- QQmlListProperty<QObject> data();
-
- QObject *part(const QString & = QString());
- bool hasPart(const QString &);
-
- static QQuickPackageAttached *qmlAttachedProperties(QObject *);
-};
-
-class QQuickPackageAttached : public QObject
-{
-Q_OBJECT
-Q_PROPERTY(QString name READ name WRITE setName)
-public:
- QQuickPackageAttached(QObject *parent);
- virtual ~QQuickPackageAttached();
-
- QString name() const;
- void setName(const QString &n);
-
- static QHash<QObject *, QQuickPackageAttached *> attached;
-private:
- QString _name;
-};
-
-QT_END_NAMESPACE
-
-QML_DECLARE_TYPE(QQuickPackage)
-QML_DECLARE_TYPEINFO(QQuickPackage, QML_HAS_ATTACHED_PROPERTIES)
-
-#endif // QQUICKPACKAGE_H
diff --git a/src/qml/types/types.pri b/src/qml/types/types.pri
index 5a56208dc4..ba11271d66 100644
--- a/src/qml/types/types.pri
+++ b/src/qml/types/types.pri
@@ -1,27 +1,12 @@
SOURCES += \
$$PWD/qqmlbind.cpp \
$$PWD/qqmlconnections.cpp \
- $$PWD/qqmlmodelsmodule.cpp \
- $$PWD/qqmlmodelindexvaluetype.cpp \
- $$PWD/qqmlobjectmodel.cpp \
- $$PWD/qquickpackage.cpp \
- $$PWD/qqmlinstantiator.cpp \
- $$PWD/qqmltableinstancemodel.cpp \
- $$PWD/qqmltablemodel.cpp \
- $$PWD/qqmltablemodelcolumn.cpp
+ $$PWD/qqmlmodelindexvaluetype.cpp
HEADERS += \
$$PWD/qqmlbind_p.h \
$$PWD/qqmlconnections_p.h \
- $$PWD/qqmlmodelsmodule_p.h \
- $$PWD/qqmlmodelindexvaluetype_p.h \
- $$PWD/qqmlobjectmodel_p.h \
- $$PWD/qquickpackage_p.h \
- $$PWD/qqmlinstantiator_p.h \
- $$PWD/qqmlinstantiator_p_p.h \
- $$PWD/qqmltableinstancemodel_p.h \
- $$PWD/qqmltablemodel_p.h \
- $$PWD/qqmltablemodelcolumn_p.h
+ $$PWD/qqmlmodelindexvaluetype_p.h
qtConfig(qml-worker-script) {
SOURCES += \
@@ -30,28 +15,6 @@ qtConfig(qml-worker-script) {
$$PWD/qquickworkerscript_p.h
}
-qtConfig(qml-list-model) {
- SOURCES += \
- $$PWD/qqmllistmodel.cpp \
- $$PWD/qqmllistmodelworkeragent.cpp
-
- HEADERS += \
- $$PWD/qqmllistmodel_p.h \
- $$PWD/qqmllistmodel_p_p.h \
- $$PWD/qqmllistmodelworkeragent_p.h
-}
-
-qtConfig(qml-delegate-model) {
- SOURCES += \
- $$PWD/qqmldelegatemodel.cpp \
- $$PWD/qqmldelegatecomponent.cpp
-
- HEADERS += \
- $$PWD/qqmldelegatemodel_p.h \
- $$PWD/qqmldelegatemodel_p_p.h \
- $$PWD/qqmldelegatecomponent_p.h
-}
-
qtConfig(qml-animation) {
SOURCES += \
$$PWD/qqmltimer.cpp