Unsolved QML, QSqlTableModel: not saving data
-
Hi, my data is being displayed by rolenames successfully but "setData" is not working. This function is receiving everything right from qml but the final call to
QSqlTableModel::setData
does not work, returns "false" & there are no errors.
QVariant ItemModel::data(const QModelIndex & index, int role) const { // qDebug() << role_names.value(role); // QString role_str = QString(roles.value(role)); qDebug() << index.row(); QModelIndex modelIndex = this->index(index.row(), role - Qt::UserRole - 1 ); return QSqlQueryModel::data(modelIndex, Qt::DisplayRole); } bool ItemModel::setData(const QModelIndex &index, const QVariant &value, int role) { qDebug() << role_names.value(role) << " " << value << " " << index.row() << " " << index.column() << " " << role - Qt::UserRole - 1; QModelIndex modelIndex = this->index(index.row(), role - Qt::UserRole - 1); // this->query().seek(index.row()); // qDebug() << this->query().record().value(1); qDebug() << QSqlTableModel::setData(modelIndex,value); qDebug() << lastError(); emit dataChanged(modelIndex,modelIndex); return true; } void ItemModel::generateRoleNames() { this->role_names.clear(); for (int i = 0; i < record().count(); ++i) { role_names[Qt::UserRole + i + 1] = record().fieldName(i).toUtf8(); } }
I have experience with abstract models but SQL models are giving me hardtime. I have no idea why it is not working. Any help will be much appreciated.
-
Hi,
@Bilal_Khan said in QML, QSqlTableModel: not saving data:
modelIndex
Are you sure this index is valid ?
-
This modelIndex is computed in both functions (data() & setData()) in the same way but it does not work while setting data. I have also tried this->index with different literal values but no success so far..
itemModel->setEditStrategy(QSqlTableModel::OnFieldChange);
-
Update (UBUNTU 20.04/ Qt-5.13 & 6.12/ SQLITE3 & PSQL):
- I no longer override setData and directly call the parent's implementation:
qDebug() << itemModel->setData(itemModel->index(0, 1), "NEW VALUE", Qt::EditRole); // false qDebug() << itemModel->lastError(); // QSqlError("", "", "")
but no vain.
-
Surprisingly, there are no errors on passing invalid index.
-
I confirm that setRecord is also not working (no errors)
ItemModel *itemModel = new ItemModel(nullptr,db); itemModel->setEditStrategy(QSqlTableModel::OnFieldChange); itemModel->setTable("items"); itemModel->generateRoleNames(); itemModel->select(); qDebug() << itemModel->rowCount(); // 2 itemModel->query().seek(0); QSqlRecord rec = itemModel->query().record(); rec.setValue(1, QString("SOMETHING")); qDebug() << itemModel->setRecord(0,rec); //true QModelIndex index = itemModel->index(0, 0); qDebug() << "Update" << itemModel->data(index, 258); // old value returned
-
It's just the problem with subclassing. setData does not work.
enum ItemRoles { CONTENTROLE = Qt::UserRole + 1, TYPEROLE = Qt::UserRole + 2, VIEWSROLE = Qt::UserRole + 3, WEIGHTROLE }; QHash<int, QByteArray> ItemModel::roleNames() const { QHash<int, QByteArray> roles; roles[CONTENTROLE] = "content"; roles[TYPEROLE] = "type"; roles[VIEWSROLE] = "views"; roles[WEIGHTROLE] = "weight"; return roles; } bool ItemModel::setData(const QModelIndex &index, const QVariant &value, int role) { QModelIndex modelIndex = this->index(index.row(), role - Qt::UserRole); qDebug() << QSqlTableModel::setData(modelIndex,value, Qt::EditRole); // true qDebug() << lastError(); emit dataChanged(modelIndex,modelIndex); return true; } // QModelIndex index = itemModel->index(0, 0); itemModel->setData(index, "VALUE", itemModel->CONTENTROLE); qDebug() << itemModel->data(index, itemModel->CONTENTROLE); // unchanged data
-
What if you call submit after setRecord ?
-
Yes, I did but does not work
-
Can you provide a minimal compilable example so that it's possible to reproduce your issue.
-
Hi,
Thank you @SGaist for your kind support ... so farAs you could see , I have made some changes. Now, after the update in setData, the data function returns qvariant(invalid).
Project Link:
Test Qt Project -
@SGaist , sorry to bother you again. Did you check it, what you have found?
-
This works correctly.
#ifndef ITEMMODEL_H #define ITEMMODEL_H #include <QSqlTableModel> class ItemModel : public QSqlTableModel { Q_OBJECT public: enum ItemRoles { IDROLE = Qt::UserRole + 1, CONTENTROLE = Qt::UserRole + 2, TYPEROLE = Qt::UserRole + 3, VIEWSROLE = Qt::UserRole + 4, WEIGHTROLE }; Q_ENUMS(ItemRoles) ItemModel(QObject *parent = nullptr, QSqlDatabase db = QSqlDatabase()); QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); QHash<int, QByteArray> roleNames() const; private: Q_DISABLE_COPY(ItemModel); QModelIndex indexForRole(const QModelIndex& index, int role) const; }; #endif // ITEMMODEL_H
#include "ItemModel.h" ItemModel::ItemModel(QObject *parent, QSqlDatabase db): QSqlTableModel(parent, db) { } QVariant ItemModel::data(const QModelIndex & index, int role) const { return QSqlTableModel::data(indexForRole(index, role), Qt::EditRole); } bool ItemModel::setData(const QModelIndex &index, const QVariant &value, int role) { return QSqlTableModel::setData(indexForRole(index, role), value, Qt::EditRole); } QHash<int, QByteArray> ItemModel::roleNames() const { QHash<int, QByteArray> roles; roles[IDROLE] = "id"; roles[CONTENTROLE] = "content"; roles[TYPEROLE] = "type"; roles[VIEWSROLE] = "views"; roles[WEIGHTROLE] = "weight"; return roles; } QModelIndex ItemModel::indexForRole(const QModelIndex& index, int role) const { int row = index.row(); int column = index.column(); if (role > Qt::UserRole) { column = role - Qt::UserRole - 1; } return this->index(row, column); }