6#include <QtCore/qloggingcategory.h>
7#include <QtQml/qqmlinfo.h>
8#include <QtQml/qqmlengine.h>
166 if (rowsAsVariantList == mRows) {
171 if (!componentCompleted) {
173 mRows = rowsAsVariantList;
177 doSetRows(rowsAsVariantList);
180void QQmlTableModel::doSetRows(
const QVariantList &rowsAsVariantList)
186 qmlWarning(
this) <<
"No TableModelColumns were set; model will be empty";
190 const bool firstTimeValidRowsHaveBeenSet = mColumnMetadata.isEmpty();
191 if (!firstTimeValidRowsHaveBeenSet) {
193 for (
int rowIndex = 0; rowIndex < rowsAsVariantList.
size(); ++rowIndex) {
197 if (!validateNewRow(
"setRows()",
row, rowIndex, SetRowsOperation))
202 const int oldRowCount = mRowCount;
203 const int oldColumnCount = mColumnCount;
209 mRows = rowsAsVariantList;
210 mRowCount = mRows.
size();
213 if (firstTimeValidRowsHaveBeenSet && !mRows.
isEmpty())
214 fetchColumnMetadata();
220 if (mRowCount != oldRowCount)
222 if (mColumnCount != oldColumnCount)
226QQmlTableModel::ColumnRoleMetadata QQmlTableModel::fetchColumnRoleData(
const QString &roleNameKey,
240 if (firstRow.
userType() != QMetaType::QVariantMap) {
241 qmlWarning(
this).quote() <<
"expected row for role "
242 << roleNameKey <<
" of TableModelColumn at index "
243 << columnIndex <<
" to be a simple object, but it's "
244 << firstRow.
typeName() <<
" instead: " << firstRow;
249 const QVariant roleProperty = firstRowAsMap.
value(rolePropertyName);
258 const auto modelIndex =
index(0, columnIndex);
269 qmlWarning(
this) <<
"TableModelColumn role for column at index "
270 << columnIndex <<
" must be either a string or a function; actual type is: "
277void QQmlTableModel::fetchColumnMetadata()
279 qCDebug(lcTableModel) <<
"gathering metadata for" << mColumnCount <<
"columns from first row:";
286 for (
int columnIndex = 0; columnIndex < mColumns.
size(); ++columnIndex) {
288 qCDebug(lcTableModel).nospace() <<
"- column " << columnIndex <<
":";
290 ColumnMetadata metaData;
291 const auto builtInRoleKeys = supportedRoleNames.keys();
292 for (
const int builtInRoleKey : builtInRoleKeys) {
293 const QString builtInRoleName = supportedRoleNames.value(builtInRoleKey);
294 ColumnRoleMetadata
roleData = fetchColumnRoleData(builtInRoleName,
column, columnIndex);
300 qCDebug(lcTableModel).nospace() <<
" - added metadata for built-in role "
301 << builtInRoleName <<
" at column index " << columnIndex
306 metaData.roles.insert(builtInRoleName,
roleData);
308 mRoleNames[builtInRoleKey] = builtInRoleName.
toLatin1();
310 mColumnMetadata.insert(columnIndex, metaData);
334 if (!validateNewRow(
"appendRow()",
row, -1, AppendOperation))
337 doInsert(mRowCount,
row);
377 if (!validateRowIndex(
"getRow()",
"rowIndex", rowIndex))
380 return mRows.
at(rowIndex);
406 if (!validateNewRow(
"insertRow()",
row, rowIndex))
409 doInsert(rowIndex,
row);
412void QQmlTableModel::doInsert(
int rowIndex,
const QVariant &
row)
419 mRows.
insert(rowIndex, rowAsVariant);
422 qCDebug(lcTableModel).nospace() <<
"inserted the following row to the model at index "
423 << rowIndex <<
":\n" << rowAsVariant.
toMap();
426 if (mColumnMetadata.isEmpty())
427 fetchColumnMetadata();
439 componentCompleted =
true;
441 mColumnCount = mColumns.
size();
442 if (mColumnCount > 0)
465 if (fromRowIndex == toRowIndex) {
466 qmlWarning(
this) <<
"moveRow(): \"fromRowIndex\" cannot be equal to \"toRowIndex\"";
471 qmlWarning(
this) <<
"moveRow(): \"rows\" is less than or equal to 0";
475 if (!validateRowIndex(
"moveRow()",
"fromRowIndex", fromRowIndex))
478 if (!validateRowIndex(
"moveRow()",
"toRowIndex", toRowIndex))
481 if (fromRowIndex +
rows > mRowCount) {
482 qmlWarning(
this) <<
"moveRow(): \"fromRowIndex\" (" << fromRowIndex
483 <<
") + \"rows\" (" <<
rows <<
") = " << (fromRowIndex +
rows)
484 <<
", which is greater than rowCount() of " << mRowCount;
488 if (toRowIndex +
rows > mRowCount) {
489 qmlWarning(
this) <<
"moveRow(): \"toRowIndex\" (" << toRowIndex
490 <<
") + \"rows\" (" <<
rows <<
") = " << (toRowIndex +
rows)
491 <<
", which is greater than rowCount() of " << mRowCount;
495 qCDebug(lcTableModel).nospace() <<
"moving " <<
rows
496 <<
" row(s) from index " << fromRowIndex
497 <<
" to index " << toRowIndex;
501 toRowIndex > fromRowIndex ? toRowIndex +
rows : toRowIndex);
504 if (fromRowIndex > toRowIndex) {
506 const int from = fromRowIndex;
507 const int to = toRowIndex;
509 toRowIndex = to +
rows;
515 for (
int i = 0;
i < (toRowIndex - fromRowIndex); ++
i)
518 store.
append(mRows.
at(fromRowIndex +
i));
519 for (
int i = 0;
i < store.
size(); ++
i)
520 mRows[fromRowIndex +
i] = store[
i];
522 qCDebug(lcTableModel).nospace() <<
"after moving, rows are:\n" << mRows;
536 if (!validateRowIndex(
"removeRow()",
"rowIndex", rowIndex))
540 qmlWarning(
this) <<
"removeRow(): \"rows\" is less than or equal to zero";
544 if (rowIndex +
rows - 1 >= mRowCount) {
546 <<
" exceeds available rowCount() of " << mRowCount
547 <<
" when removing from \"rowIndex\" " << rowIndex;
553 auto firstIterator = mRows.
begin() + rowIndex;
555 auto lastIterator = firstIterator +
rows;
556 mRows.
erase(firstIterator, lastIterator);
562 qCDebug(lcTableModel).nospace() <<
"removed " <<
rows
563 <<
" items from the model, starting at index " << rowIndex;
590 if (!validateNewRow(
"setRow()",
row, rowIndex))
593 if (rowIndex != mRowCount) {
595 mRows[rowIndex] =
row;
603 doInsert(rowIndex,
row);
630 return model->mColumns.size();
655 model->mColumns.removeLast();
744 const int iRole = mRoleNames.
key(role.
toUtf8(), -1);
760 const ColumnMetadata columnMetadata = mColumnMetadata.at(
index.column());
762 if (!columnMetadata.roles.contains(roleName)) {
763 qmlWarning(
this) <<
"setData(): no role named " << roleName
764 <<
" at column index " <<
column <<
". The available roles for that column are: "
765 << columnMetadata.roles.keys();
769 const ColumnRoleMetadata
roleData = columnMetadata.roles.value(roleName);
773 const QString propertyName = columnMetadata.roles.value(roleName).name;
784 return getter.call(
args).toVariant();
797 const int intRole = mRoleNames.
key(role.
toUtf8(), -1);
815 qCDebug(lcTableModel).nospace() <<
"setData() called with index "
816 <<
index <<
", value " <<
value <<
" and role " << roleName;
819 const ColumnMetadata columnMetadata = mColumnMetadata.at(
index.column());
820 if (!columnMetadata.roles.contains(roleName)) {
821 qmlWarning(
this) <<
"setData(): no role named \"" << roleName
822 <<
"\" at column index " <<
column <<
". The available roles for that column are: "
823 << columnMetadata.roles.keys();
829 const ColumnRoleMetadata
roleData = columnMetadata.roles.value(roleName);
834 <<
" set at row " <<
row <<
" column " <<
column <<
" with role " << roleName
835 <<
" cannot be converted to " <<
roleData.typeName;
840 qmlWarning(
this).nospace() <<
"setData(): failed converting value " <<
value
841 <<
" set at row " <<
row <<
" column " <<
column <<
" with role " << roleName
852 mRows[
row] = modifiedRow;
901 rolesChanged.
append(role);
912QQmlTableModel::ColumnRoleMetadata::ColumnRoleMetadata()
916QQmlTableModel::ColumnRoleMetadata::ColumnRoleMetadata(
918 isStringRole(isStringRole),
925bool QQmlTableModel::ColumnRoleMetadata::isValid()
const
927 return !
name.isEmpty();
930bool QQmlTableModel::validateRowType(
const char *functionName,
const QVariant &
row)
const
933 qmlWarning(
this) << functionName <<
": expected \"row\" argument to be a QJSValue,"
934 <<
" but got " <<
row.typeName() <<
" instead:\n" <<
row;
940 qmlWarning(
this) << functionName <<
": expected \"row\" argument "
941 <<
"to be an object or array, but got:\n" << rowAsJSValue.
toString();
948bool QQmlTableModel::validateNewRow(
const char *functionName,
const QVariant &
row,
949 int rowIndex, NewRowOperationFlag operation)
const
951 if (mColumnMetadata.isEmpty()) {
960 if (operation != SetRowsOperation && !validateRowType(functionName,
row))
963 if (operation == OtherOperation) {
966 qmlWarning(
this) << functionName <<
": \"rowIndex\" cannot be negative";
970 if (rowIndex > mRowCount) {
971 qmlWarning(
this) << functionName <<
": \"rowIndex\" " << rowIndex
972 <<
" is greater than rowCount() of " << mRowCount;
977 const QVariant rowAsVariant = operation == SetRowsOperation
979 if (rowAsVariant.
userType() != QMetaType::QVariantMap) {
980 qmlWarning(
this) << functionName <<
": row manipulation functions "
981 <<
"do not support complex rows (row index: " << rowIndex <<
")";
988 qmlWarning(
this) << functionName <<
": expected " << mColumnCount
995 for (
int columnIndex = 0; columnIndex < mColumns.
size(); ++columnIndex) {
999 const ColumnMetadata columnMetadata = mColumnMetadata.at(columnIndex);
1001 const ColumnRoleMetadata
roleData = columnMetadata.roles.value(roleName);
1006 qmlWarning(
this).quote() << functionName <<
": expected a property named "
1007 <<
roleData.name <<
" in row at index " << rowIndex <<
", but couldn't find one";
1015 qmlWarning(
this).quote() << functionName <<
": expected the property named "
1022 QVariant effectiveValue = rolePropertyValue;
1024 qmlWarning(
this).nospace() << functionName <<
": failed converting value "
1025 << rolePropertyValue <<
" set at column " << columnIndex <<
" with role "
1037bool QQmlTableModel::validateRowIndex(
const char *functionName,
const char *argumentName,
int rowIndex)
const
1040 qmlWarning(
this) << functionName <<
": \"" << argumentName <<
"\" cannot be negative";
1044 if (rowIndex >= mRowCount) {
1045 qmlWarning(
this) << functionName <<
": \"" << argumentName
1046 <<
"\" " << rowIndex <<
" is greater than or equal to rowCount() of " << mRowCount;
1061#include "moc_qqmltablemodel_p.cpp"
void endResetModel()
Completes a model reset operation.
bool beginMoveRows(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destinationParent, int destinationRow)
void endRemoveRows()
Ends a row removal operation.
void endMoveRows()
Ends a row move operation.
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList< int > &roles=QList< int >())
This signal is emitted whenever the data in an existing item changes.
void endInsertRows()
Ends a row insertion operation.
void beginResetModel()
Begins a model reset operation.
QModelIndex createIndex(int row, int column, const void *data=nullptr) const
Creates a model index for the given row and column with the internal pointer ptr.
void beginRemoveRows(const QModelIndex &parent, int first, int last)
Begins a row removal operation.
void beginInsertRows(const QModelIndex &parent, int first, int last)
Begins a row insertion operation.
QObject * parent() const
Returns a pointer to the parent object.
QList< Key > keys() const
Returns a list containing all the keys in the hash, in an arbitrary order.
T value(const Key &key) const noexcept
Key key(const T &value) const noexcept
QJSValue newArray(uint length=0)
Creates a JavaScript object of class Array with the given length.
QJSValue toScriptValue(const T &value)
Creates a QJSValue with the given value.
The QJSValue class acts as a container for Qt/JavaScript data types.
bool isCallable() const
Returns true if this QJSValue is a function, otherwise returns false.
QJSValue call(const QJSValueList &args=QJSValueList()) const
Calls this QJSValue as a function, passing args as arguments to the function, and using the globalObj...
bool isObject() const
Returns true if this QJSValue is of the Object type; otherwise returns false.
bool isArray() const
Returns true if this QJSValue is an object of the Array class; otherwise returns false.
bool isUndefined() const
Returns true if this QJSValue is of the primitive type Undefined or if the managed value has been cle...
bool isString() const
Returns true if this QJSValue is of the primitive type String; otherwise returns false.
QString toString() const
Returns the string value of this QJSValue, as defined in \l{ECMA-262} section 9.8,...
QVariant toVariant() const
This is an overloaded member function, provided for convenience. It differs from the above function o...
qsizetype size() const noexcept
bool isEmpty() const noexcept
iterator erase(const_iterator begin, const_iterator end)
iterator insert(qsizetype i, parameter_type t)
const_reference at(qsizetype i) const noexcept
void reserve(qsizetype size)
void append(parameter_type t)
T value(const Key &key, const T &defaultValue=T()) const
bool contains(const Key &key) const
The QQmlEngine class provides an environment for instantiating QML components.
The QQmlListProperty class allows applications to expose list-like properties of QObject-derived clas...
QJSValue setterAtRole(const QString &roleName)
static const QHash< int, QString > supportedRoleNames()
QJSValue getterAtRole(const QString &roleName)
Q_INVOKABLE void moveRow(int fromRowIndex, int toRowIndex, int rows=1)
\qmlmethod TableModel::moveRow(int fromRowIndex, int toRowIndex, int rows)
static void columns_clear(QQmlListProperty< QQmlTableModelColumn > *property)
static void columns_append(QQmlListProperty< QQmlTableModelColumn > *property, QQmlTableModelColumn *value)
static qsizetype columns_count(QQmlListProperty< QQmlTableModelColumn > *property)
~QQmlTableModel() override
Q_INVOKABLE void appendRow(const QVariant &row)
\qmlmethod TableModel::appendRow(object row)
static void columns_replace(QQmlListProperty< QQmlTableModelColumn > *property, qsizetype index, QQmlTableModelColumn *value)
void columnCountChanged()
Q_INVOKABLE void clear()
\qmlmethod TableModel::clear()
Q_INVOKABLE QVariant getRow(int rowIndex)
\qmlmethod object TableModel::getRow(int rowIndex)
void setRows(const QVariant &rows)
Q_INVOKABLE void setRow(int rowIndex, const QVariant &row)
\qmlmethod TableModel::setRow(int rowIndex, object row)
Q_INVOKABLE QVariant data(const QModelIndex &index, const QString &role) const
\qmlmethod variant TableModel::data(QModelIndex index, string role)
Qt::ItemFlags flags(const QModelIndex &index) const override
\reimp
static void columns_removeLast(QQmlListProperty< QQmlTableModelColumn > *property)
Q_INVOKABLE bool setData(const QModelIndex &index, const QString &role, const QVariant &value)
\qmlmethod bool TableModel::setData(QModelIndex index, string role, variant value)
static QQmlTableModelColumn * columns_at(QQmlListProperty< QQmlTableModelColumn > *property, qsizetype index)
Q_INVOKABLE void removeRow(int rowIndex, int rows=1)
\qmlmethod TableModel::removeRow(int rowIndex, int rows = 1)
void componentComplete() override
Invoked after the root component that caused this instantiation has completed construction.
void classBegin() override
Invoked after class creation, but before any properties have been set.
Q_INVOKABLE void insertRow(int rowIndex, const QVariant &row)
\qmlmethod TableModel::insertRow(int rowIndex, object row)
QQmlListProperty< QQmlTableModelColumn > columns
QHash< int, QByteArray > roleNames() const override
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
\qmlmethod QModelIndex TableModel::index(int row, int column)
virtual void clear()
Clears the model and releases any acquired resource.
\macro QT_RESTRICTED_CAST_FROM_ASCII
QByteArray toLatin1() const &
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QByteArray toUtf8() const &
bool convert(QMetaType type)
Casts the variant to the requested type, targetType.
QList< QVariant > toList() const
Returns the variant as a QVariantList if the variant has userType() \l QMetaType::QVariantList.
QMap< QString, QVariant > toMap() const
Returns the variant as a QVariantMap if the variant has type() \l QMetaType::QVariantMap.
const char * typeName() const
Returns the name of the type stored in the variant.
bool canConvert(QMetaType targetType) const
static auto fromValue(T &&value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::conjunction_v< std::is_copy_constructible< T >, std::is_destructible< T > >, QVariant >
Combined button and popup list for selecting options.
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
QList< QJSValue > QJSValueList
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLenum GLsizei void GLsizei void * column
GLenum GLenum GLsizei void * row
QQmlEngine * qmlEngine(const QObject *obj)
Q_QML_EXPORT QQmlInfo qmlWarning(const QObject *me)
static QVariant toVariant(const QV4::Value &value, QMetaType typeHint, bool createJSValueForObjectsAndSymbols, V4ObjectSet *visitedObjects)
QSqlQueryModel * model
[16]
std::array< QModelRoleData, 3 > roleData
[13]
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent