1 | // Copyright (C) 2019 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #ifndef QQMLTABLEMODEL_P_H |
5 | #define QQMLTABLEMODEL_P_H |
6 | |
7 | // |
8 | // W A R N I N G |
9 | // ------------- |
10 | // |
11 | // This file is not part of the Qt API. It exists purely as an |
12 | // implementation detail. This header file may change from version to |
13 | // version without notice, or even be removed. |
14 | // |
15 | // We mean it. |
16 | // |
17 | |
18 | #include "qqmlmodelsglobal_p.h" |
19 | #include "qqmltablemodelcolumn_p.h" |
20 | |
21 | #include <QtCore/QObject> |
22 | #include <QtCore/QHash> |
23 | #include <QtCore/QAbstractTableModel> |
24 | #include <QtQml/qqml.h> |
25 | #include <QtQmlModels/private/qtqmlmodelsglobal_p.h> |
26 | #include <QtQml/QJSValue> |
27 | #include <QtQml/QQmlListProperty> |
28 | |
29 | QT_REQUIRE_CONFIG(qml_table_model); |
30 | |
31 | QT_BEGIN_NAMESPACE |
32 | |
33 | class Q_LABSQMLMODELS_PRIVATE_EXPORT QQmlTableModel : public QAbstractTableModel, public QQmlParserStatus |
34 | { |
35 | Q_OBJECT |
36 | Q_PROPERTY(int columnCount READ columnCount NOTIFY columnCountChanged FINAL) |
37 | Q_PROPERTY(int rowCount READ rowCount NOTIFY rowCountChanged FINAL) |
38 | Q_PROPERTY(QVariant rows READ rows WRITE setRows NOTIFY rowsChanged FINAL) |
39 | Q_PROPERTY(QQmlListProperty<QQmlTableModelColumn> columns READ columns CONSTANT FINAL) |
40 | Q_INTERFACES(QQmlParserStatus) |
41 | Q_CLASSINFO("DefaultProperty" , "columns" ) |
42 | QML_NAMED_ELEMENT(TableModel) |
43 | QML_ADDED_IN_VERSION(1, 0) |
44 | |
45 | public: |
46 | QQmlTableModel(QObject *parent = nullptr); |
47 | ~QQmlTableModel() override; |
48 | |
49 | QVariant rows() const; |
50 | void setRows(const QVariant &rows); |
51 | |
52 | Q_INVOKABLE void appendRow(const QVariant &row); |
53 | Q_INVOKABLE void clear(); |
54 | Q_INVOKABLE QVariant getRow(int rowIndex); |
55 | Q_INVOKABLE void insertRow(int rowIndex, const QVariant &row); |
56 | Q_INVOKABLE void moveRow(int fromRowIndex, int toRowIndex, int rows = 1); |
57 | Q_INVOKABLE void removeRow(int rowIndex, int rows = 1); |
58 | Q_INVOKABLE void setRow(int rowIndex, const QVariant &row); |
59 | |
60 | QQmlListProperty<QQmlTableModelColumn> columns(); |
61 | |
62 | static void columns_append(QQmlListProperty<QQmlTableModelColumn> *property, QQmlTableModelColumn *value); |
63 | static qsizetype columns_count(QQmlListProperty<QQmlTableModelColumn> *property); |
64 | static QQmlTableModelColumn *columns_at(QQmlListProperty<QQmlTableModelColumn> *property, qsizetype index); |
65 | static void columns_clear(QQmlListProperty<QQmlTableModelColumn> *property); |
66 | static void columns_replace(QQmlListProperty<QQmlTableModelColumn> *property, qsizetype index, QQmlTableModelColumn *value); |
67 | static void columns_removeLast(QQmlListProperty<QQmlTableModelColumn> *property); |
68 | |
69 | QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; |
70 | int rowCount(const QModelIndex &parent = QModelIndex()) const override; |
71 | int columnCount(const QModelIndex &parent = QModelIndex()) const override; |
72 | Q_INVOKABLE QVariant data(const QModelIndex &index, const QString &role) const; |
73 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; |
74 | Q_INVOKABLE bool setData(const QModelIndex &index, const QString &role, const QVariant &value); |
75 | bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::DisplayRole) override; |
76 | QHash<int, QByteArray> roleNames() const override; |
77 | Qt::ItemFlags flags(const QModelIndex &index) const override; |
78 | |
79 | Q_SIGNALS: |
80 | void columnCountChanged(); |
81 | void rowCountChanged(); |
82 | void rowsChanged(); |
83 | |
84 | private: |
85 | class ColumnRoleMetadata |
86 | { |
87 | public: |
88 | ColumnRoleMetadata(); |
89 | ColumnRoleMetadata(bool isStringRole, const QString &name, int type, const QString &typeName); |
90 | |
91 | bool isValid() const; |
92 | |
93 | // If this is false, it's a function role. |
94 | bool isStringRole = false; |
95 | QString name; |
96 | int type = QMetaType::UnknownType; |
97 | QString typeName; |
98 | }; |
99 | |
100 | struct ColumnMetadata |
101 | { |
102 | // Key = role name that will be made visible to the delegate |
103 | // Value = metadata about that role, including actual name in the model data, type, etc. |
104 | QHash<QString, ColumnRoleMetadata> roles; |
105 | }; |
106 | |
107 | enum NewRowOperationFlag { |
108 | OtherOperation, // insert(), set(), etc. |
109 | SetRowsOperation, |
110 | AppendOperation |
111 | }; |
112 | |
113 | void doSetRows(const QVariantList &rowsAsVariantList); |
114 | ColumnRoleMetadata fetchColumnRoleData(const QString &roleNameKey, |
115 | QQmlTableModelColumn *tableModelColumn, int columnIndex) const; |
116 | void fetchColumnMetadata(); |
117 | |
118 | bool validateRowType(const char *functionName, const QVariant &row) const; |
119 | bool validateNewRow(const char *functionName, const QVariant &row, |
120 | int rowIndex, NewRowOperationFlag operation = OtherOperation) const; |
121 | bool validateRowIndex(const char *functionName, const char *argumentName, int rowIndex) const; |
122 | |
123 | void doInsert(int rowIndex, const QVariant &row); |
124 | |
125 | void classBegin() override; |
126 | void componentComplete() override; |
127 | |
128 | bool componentCompleted = false; |
129 | QVariantList mRows; |
130 | QList<QQmlTableModelColumn *> mColumns; |
131 | int mRowCount = 0; |
132 | int mColumnCount = 0; |
133 | // Each entry contains information about the properties of the column at that index. |
134 | QVector<ColumnMetadata> mColumnMetadata; |
135 | // key = property index (0 to number of properties across all columns) |
136 | // value = role name |
137 | QHash<int, QByteArray> mRoleNames; |
138 | }; |
139 | |
140 | QT_END_NAMESPACE |
141 | |
142 | QML_DECLARE_TYPE(QQmlTableModel) |
143 | |
144 | #endif // QQMLTABLEMODEL_P_H |
145 | |