diff options
Diffstat (limited to 'src/qmlmodels')
-rw-r--r-- | src/qmlmodels/qmlmodels.pro | 12 | ||||
-rw-r--r-- | src/qmlmodels/qqmlabstractdelegatecomponent.cpp | 61 | ||||
-rw-r--r-- | src/qmlmodels/qqmlabstractdelegatecomponent_p.h (renamed from src/qmlmodels/qqmldelegatecomponent_p.h) | 85 | ||||
-rw-r--r-- | src/qmlmodels/qqmladaptormodel.cpp | 7 | ||||
-rw-r--r-- | src/qmlmodels/qqmldelegatecomponent.cpp | 321 | ||||
-rw-r--r-- | src/qmlmodels/qqmldelegatemodel.cpp | 2 | ||||
-rw-r--r-- | src/qmlmodels/qqmlmodelsmodule.cpp | 21 | ||||
-rw-r--r-- | src/qmlmodels/qqmlobjectmodel.cpp | 7 | ||||
-rw-r--r-- | src/qmlmodels/qqmltableinstancemodel.cpp | 2 | ||||
-rw-r--r-- | src/qmlmodels/qqmltablemodel.cpp | 1059 | ||||
-rw-r--r-- | src/qmlmodels/qqmltablemodel_p.h | 173 | ||||
-rw-r--r-- | src/qmlmodels/qqmltablemodelcolumn.cpp | 200 | ||||
-rw-r--r-- | src/qmlmodels/qqmltablemodelcolumn_p.h | 227 |
13 files changed, 85 insertions, 2092 deletions
diff --git a/src/qmlmodels/qmlmodels.pro b/src/qmlmodels/qmlmodels.pro index 1d733f5bdb..78bf579903 100644 --- a/src/qmlmodels/qmlmodels.pro +++ b/src/qmlmodels/qmlmodels.pro @@ -28,14 +28,10 @@ qtConfig(qml-object-model) { qtConfig(qml-table-model) { SOURCES += \ - $$PWD/qqmltableinstancemodel.cpp \ - $$PWD/qqmltablemodel.cpp \ - $$PWD/qqmltablemodelcolumn.cpp + $$PWD/qqmltableinstancemodel.cpp HEADERS += \ - $$PWD/qqmltableinstancemodel_p.h \ - $$PWD/qqmltablemodel_p.h \ - $$PWD/qqmltablemodelcolumn_p.h + $$PWD/qqmltableinstancemodel_p.h } qtConfig(qml-list-model) { @@ -51,18 +47,18 @@ qtConfig(qml-list-model) { qtConfig(qml-delegate-model) { SOURCES += \ + $$PWD/qqmlabstractdelegatecomponent.cpp \ $$PWD/qqmladaptormodel.cpp \ $$PWD/qqmldelegatemodel.cpp \ - $$PWD/qqmldelegatecomponent.cpp \ $$PWD/qqmllistaccessor.cpp \ $$PWD/qqmllistcompositor.cpp \ $$PWD/qquickpackage.cpp HEADERS += \ + $$PWD/qqmlabstractdelegatecomponent_p.h \ $$PWD/qqmladaptormodel_p.h \ $$PWD/qqmldelegatemodel_p.h \ $$PWD/qqmldelegatemodel_p_p.h \ - $$PWD/qqmldelegatecomponent_p.h \ $$PWD/qqmllistaccessor_p.h \ $$PWD/qqmllistcompositor_p.h \ $$PWD/qquickpackage_p.h diff --git a/src/qmlmodels/qqmlabstractdelegatecomponent.cpp b/src/qmlmodels/qqmlabstractdelegatecomponent.cpp new file mode 100644 index 0000000000..1058d87485 --- /dev/null +++ b/src/qmlmodels/qqmlabstractdelegatecomponent.cpp @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** 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 <QtQmlModels/private/qqmlabstractdelegatecomponent_p.h> +#include <QtQmlModels/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); +} + +QT_END_NAMESPACE diff --git a/src/qmlmodels/qqmldelegatecomponent_p.h b/src/qmlmodels/qqmlabstractdelegatecomponent_p.h index 86ad04d2e3..07cae6b092 100644 --- a/src/qmlmodels/qqmldelegatecomponent_p.h +++ b/src/qmlmodels/qqmlabstractdelegatecomponent_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2018 The Qt Company Ltd. +** 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. @@ -37,8 +37,8 @@ ** ****************************************************************************/ -#ifndef QQMLDELEGATECOMPONENT_P_H -#define QQMLDELEGATECOMPONENT_P_H +#ifndef QQMLABSTRACTDELEGATECOMPONENT_P_H +#define QQMLABSTRACTDELEGATECOMPONENT_P_H // // W A R N I N G @@ -52,6 +52,7 @@ // #include <private/qtqmlmodelsglobal_p.h> +#include <private/qqmlcomponentattached_p.h> #include <qqmlcomponent.h> QT_REQUIRE_CONFIG(qml_delegate_model); @@ -59,7 +60,6 @@ QT_REQUIRE_CONFIG(qml_delegate_model); QT_BEGIN_NAMESPACE // TODO: consider making QQmlAbstractDelegateComponent public API -class QQmlAbstractDelegateComponentPrivate; class QQmlAdaptorModel; class Q_QMLMODELS_PRIVATE_EXPORT QQmlAbstractDelegateComponent : public QQmlComponent { @@ -78,83 +78,8 @@ signals: protected: QVariant value(QQmlAdaptorModel *adaptorModel,int row, int column, const QString &role) const; - -private: - Q_DECLARE_PRIVATE(QQmlAbstractDelegateComponent) - Q_DISABLE_COPY(QQmlAbstractDelegateComponent) -}; - -class Q_QMLMODELS_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") - QML_NAMED_ELEMENT(DelegateChoice) -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_QMLMODELS_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") - QML_NAMED_ELEMENT(DelegateChooser) - -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 +#endif // QQMLABSTRACTDELEGATECOMPONENT_P_H diff --git a/src/qmlmodels/qqmladaptormodel.cpp b/src/qmlmodels/qqmladaptormodel.cpp index 48ff4e7d5b..012540244f 100644 --- a/src/qmlmodels/qqmladaptormodel.cpp +++ b/src/qmlmodels/qqmladaptormodel.cpp @@ -459,6 +459,11 @@ public: QVariant value(const QQmlAdaptorModel &model, int index, const QString &role) const override { + if (!metaObject) { + VDMAbstractItemModelDataType *dataType = const_cast<VDMAbstractItemModelDataType *>(this); + dataType->initializeMetaType(model); + } + QHash<QByteArray, int>::const_iterator it = roleNames.find(role.toUtf8()); if (it != roleNames.end()) { return model.aim()->index(model.rowAt(index), model.columnAt(index), model.rootIndex).data(*it); @@ -505,7 +510,7 @@ public: return new QQmlDMAbstractItemModelData(metaType, dataType, index, row, column); } - void initializeMetaType(QQmlAdaptorModel &model) + void initializeMetaType(const QQmlAdaptorModel &model) { QMetaObjectBuilder builder; setModelDataType<QQmlDMAbstractItemModelData>(&builder, this); diff --git a/src/qmlmodels/qqmldelegatecomponent.cpp b/src/qmlmodels/qqmldelegatecomponent.cpp deleted file mode 100644 index cc3b38ec93..0000000000 --- a/src/qmlmodels/qqmldelegatecomponent.cpp +++ /dev/null @@ -1,321 +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 <QtQmlModels/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); -} - -/*! - \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 to 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. - - DelegateChooser is commonly used when a view needs to display a set of delegates that are significantly - different from each other. For example, a typical phone settings view might include toggle switches, - sliders, radio buttons, and other visualizations based on the type of each setting. In this case, DelegateChooser - could provide an easy way to associate a different type of delegate with each setting: - - \qml \QtMinorVersion - import QtQuick 2.\1 - import QtQuick.Controls 2.\1 - import Qt.labs.qmlmodels 1.0 - - ListView { - width: 200; height: 400 - - ListModel { - id: listModel - ListElement { type: "info"; ... } - ListElement { type: "switch"; ... } - ListElement { type: "swipe"; ... } - ListElement { type: "switch"; ... } - } - - DelegateChooser { - id: chooser - role: "type" - DelegateChoice { roleValue: "info"; ItemDelegate { ... } } - DelegateChoice { roleValue: "switch"; SwitchDelegate { ... } } - DelegateChoice { roleValue: "swipe"; SwipeDelegate { ... } } - } - - model: listModel - delegate: chooser - } - \endqml - - \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/qmlmodels/qqmldelegatemodel.cpp b/src/qmlmodels/qqmldelegatemodel.cpp index 2c3382c643..e3c01d040a 100644 --- a/src/qmlmodels/qqmldelegatemodel.cpp +++ b/src/qmlmodels/qqmldelegatemodel.cpp @@ -38,10 +38,10 @@ ****************************************************************************/ #include "qqmldelegatemodel_p_p.h" -#include "qqmldelegatecomponent_p.h" #include <QtQml/qqmlinfo.h> +#include <private/qqmlabstractdelegatecomponent_p.h> #include <private/qquickpackage_p.h> #include <private/qmetaobjectbuilder_p.h> #include <private/qqmladaptormodel_p.h> diff --git a/src/qmlmodels/qqmlmodelsmodule.cpp b/src/qmlmodels/qqmlmodelsmodule.cpp index 7ed8561558..8bd9b179b3 100644 --- a/src/qmlmodels/qqmlmodelsmodule.cpp +++ b/src/qmlmodels/qqmlmodelsmodule.cpp @@ -45,8 +45,8 @@ #include <private/qqmllistmodelworkeragent_p.h> #endif #if QT_CONFIG(qml_delegate_model) +#include <private/qqmlabstractdelegatecomponent_p.h> #include <private/qqmldelegatemodel_p.h> -#include <private/qqmldelegatecomponent_p.h> #include <private/qquickpackage_p.h> #include <private/qqmlcomponentattached_p.h> #endif @@ -54,10 +54,6 @@ #include <private/qqmlobjectmodel_p.h> #include <private/qqmlinstantiator_p.h> #endif -#if QT_CONFIG(qml_table_model) -#include <private/qqmltablemodel_p.h> -#include <private/qqmltablemodelcolumn_p.h> -#endif QT_BEGIN_NAMESPACE @@ -73,7 +69,7 @@ void QQmlModelsModule::defineModule() qmlRegisterType<QQmlDelegateModel>(uri, 2, 0, "VisualDataModel"); qmlRegisterType<QQmlDelegateModelGroup>(uri, 2, 0, "VisualDataGroup"); - qmlRegisterTypesAndRevisions<QQmlDelegateModel, QQmlDelegateModelGroup, QQuickPackage>(uri, 2); + qmlRegisterTypesAndRevisions<QQmlDelegateModel, QQmlDelegateModelGroup, QQuickPackage, QQmlAbstractDelegateComponent>(uri, 2); #endif #if QT_CONFIG(qml_object_model) qmlRegisterTypesAndRevisions<QQmlObjectModel, QQmlInstantiator, QQmlInstanceModel>(uri, 2); @@ -83,17 +79,4 @@ void QQmlModelsModule::defineModule() #endif } -void QQmlModelsModule::defineLabsModule() -{ - const char uri[] = "Qt.labs.qmlmodels"; - -#if QT_CONFIG(qml_delegate_model) - qmlRegisterTypesAndRevisions< - QQmlAbstractDelegateComponent, QQmlDelegateChooser, QQmlDelegateChoice>(uri, 1); -#endif -#if QT_CONFIG(qml_table_model) - qmlRegisterTypesAndRevisions<QQmlTableModel, QQmlTableModelColumn>(uri, 1); -#endif -} - QT_END_NAMESPACE diff --git a/src/qmlmodels/qqmlobjectmodel.cpp b/src/qmlmodels/qqmlobjectmodel.cpp index 7409178616..8e7b0a9b5f 100644 --- a/src/qmlmodels/qqmlobjectmodel.cpp +++ b/src/qmlmodels/qqmlobjectmodel.cpp @@ -154,7 +154,8 @@ public: void clear() { Q_Q(QQmlObjectModel); - for (const Item &child : qAsConst(children)) + const auto copy = children; + for (const Item &child : copy) emit q->destroyingItem(child.item); remove(0, children.count()); } @@ -170,6 +171,8 @@ public: QList<Item> children; }; +Q_DECLARE_TYPEINFO(QQmlObjectModelPrivate::Item, Q_PRIMITIVE_TYPE); + /*! \qmltype ObjectModel @@ -278,7 +281,7 @@ 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); + return d->children.at(index).item->property(role.toUtf8().constData()); } QQmlIncubator::Status QQmlObjectModel::incubationStatus(int) diff --git a/src/qmlmodels/qqmltableinstancemodel.cpp b/src/qmlmodels/qqmltableinstancemodel.cpp index 9b79df3441..a538ae4a1f 100644 --- a/src/qmlmodels/qqmltableinstancemodel.cpp +++ b/src/qmlmodels/qqmltableinstancemodel.cpp @@ -38,7 +38,7 @@ ****************************************************************************/ #include "qqmltableinstancemodel_p.h" -#include "qqmldelegatecomponent_p.h" +#include "qqmlabstractdelegatecomponent_p.h" #include <QtCore/QTimer> diff --git a/src/qmlmodels/qqmltablemodel.cpp b/src/qmlmodels/qqmltablemodel.cpp deleted file mode 100644 index f190ad86b1..0000000000 --- a/src/qmlmodels/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/qmlmodels/qqmltablemodel_p.h b/src/qmlmodels/qqmltablemodel_p.h deleted file mode 100644 index 4b667e1073..0000000000 --- a/src/qmlmodels/qqmltablemodel_p.h +++ /dev/null @@ -1,173 +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 <QtQmlModels/private/qtqmlmodelsglobal_p.h> -#include <QtQmlModels/private/qqmltablemodelcolumn_p.h> -#include <QtQml/QJSValue> -#include <QtQml/QQmlListProperty> - -QT_REQUIRE_CONFIG(qml_table_model); - -QT_BEGIN_NAMESPACE - -class Q_QMLMODELS_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") - QML_NAMED_ELEMENT(TableModel) - -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/qmlmodels/qqmltablemodelcolumn.cpp b/src/qmlmodels/qqmltablemodelcolumn.cpp deleted file mode 100644 index 93da0642de..0000000000 --- a/src/qmlmodels/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/qmlmodels/qqmltablemodelcolumn_p.h b/src/qmlmodels/qqmltablemodelcolumn_p.h deleted file mode 100644 index 33f32ccb68..0000000000 --- a/src/qmlmodels/qqmltablemodelcolumn_p.h +++ /dev/null @@ -1,227 +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 <QtQmlModels/private/qtqmlmodelsglobal_p.h> -#include <QtQml/qjsvalue.h> - -QT_REQUIRE_CONFIG(qml_table_model); - -QT_BEGIN_NAMESPACE - -class Q_QMLMODELS_PRIVATE_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) - QML_NAMED_ELEMENT(TableModelColumn) - -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 |