QSqlTableModel::setData() returns false 也与 Qt::EditMode
QSqlTableModel::setData() returns false also with Qt::EditMode
QSqlTableModel::setData()
的documentation说:
Returns false if the role is not Qt::EditRole. To set data for roles other than EditRole, either use a custom proxy model or subclass QSqlTableModel.
但我仍然得到 false
,即使角色是 Qt::EditRole
。
我的模型:
#ifndef MODELOPERATORS_H
#define MODELOPERATORS_H
#include <QSqlTableModel>
enum
{
MODEL_OPERATORS_COL_ID,
MODEL_OPERATORS_COL_NAME,
MODEL_OPERATORS_COL_SIGNATURE,
MODEL_OPERATORS_COL_COUNT
};
class ModelOperators : public QSqlTableModel
{
Q_OBJECT
public:
typedef struct
{
QString name;
QString signature;
} item_t;
ModelOperators(QObject *parent = nullptr, QSqlDatabase db = QSqlDatabase());
~ModelOperators();
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
};
#endif // MODELOPERATORS_H
#include "modeloperators.h"
ModelOperators::ModelOperators(QObject *parent, QSqlDatabase db) : QSqlTableModel(parent, db)
{
setTable("operators");
setEditStrategy(QSqlTableModel::OnFieldChange);
select();
}
ModelOperators::~ModelOperators() { }
QVariant ModelOperators::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal)
{
if (role == Qt::TextAlignmentRole) return Qt::AlignCenter;
if (role == Qt::DisplayRole)
{
switch(section)
{
case MODEL_OPERATORS_COL_NAME: return tr("Name");
case MODEL_OPERATORS_COL_SIGNATURE: return tr("Signature");
default: return "";
}
}
}
return QVariant();
}
Qt::ItemFlags ModelOperators::flags(const QModelIndex &index) const
{
switch (index.column())
{
case MODEL_OPERATORS_COL_NAME: return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
case MODEL_OPERATORS_COL_SIGNATURE: return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
default: return Qt::NoItemFlags;
}
}
Table定义:
bool DatabaseManager::appCreateTableOperators()
{
QSqlQuery query(QSqlDatabase::database("dbApp"));
query.prepare("CREATE TABLE operators ("
"id INTEGER PRIMARY KEY, "
"name TEXT, "
"signature TEXT)");
return query.exec();
}
用法:
DialogSettings::DialogSettings(QWidget *parent) : QDialog(parent), ui(new Ui::DialogSettings)
{
ui->setupUi(this);
_modelOperators = new ModelOperators(this, QSqlDatabase::database("dbApp"));
ui->tableOperators->setModel(_modelOperators);
ui->tableOperators->hideColumn(MODEL_OPERATORS_COL_ID);
ui->tableOperators->sortByColumn(MODEL_OPERATORS_COL_NAME);
ui->tableOperators->setItemDelegate(&_delegateOperators);
}
void DialogSettings::on_btnOperatorsBrowse_clicked()
{
if (ui->tableOperators->selectionModel()->hasSelection())
{
QString filename = QFileDialog::getOpenFileName(this, tr("Select signature image"), QDir::homePath(), tr("Portable Network Graphics (*.png)"));
if (filename.isEmpty()) return;
int row = ui->tableOperators->selectionModel()->currentIndex().row();
QModelIndex index = _modelOperators->index(row, MODEL_OPERATORS_COL_SIGNATURE);
qDebug() << _modelOperators->setData(index, filename, Qt::EditRole);
}
}
但是 returns false
当然数据库没有更新;
如果修改了source code,问题就明白了:
bool QSqlTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
// ...
if (!(flags(index) & Qt::ItemIsEditable))
return false;
// ...
}
可以看出,如果 QModelIndex 不可编辑,则 setData 将不执行任何操作,return false,如本例所示。
因此解决方案是启用版本,但我猜您不希望该列可编辑,因此我们将放置一个不允许编辑的委托,而不是使用标志:
Qt::ItemFlags ModelOperators::flags(const QModelIndex &index) const
{
switch (index.column())
{
case MODEL_OPERATORS_COL_NAME: return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
case MODEL_OPERATORS_COL_SIGNATURE: return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
default: return Qt::NoItemFlags;
}
}
class ReadOnlyDelegate: public QStyledItemDelegate
{
public:
using QStyledItemDelegate::QStyledItemDelegate;
QWidget *createEditor(QWidget */*parent*/, const QStyleOptionViewItem & /*option*/, const QModelIndex &/*index*/) const override
{
return nullptr;
}
};
_modelOperators = new ModelOperators(this, QSqlDatabase::database("dbApp"));
ui->tableOperators->setModel(_modelOperators);
ui->tableOperators->hideColumn(MODEL_OPERATORS_COL_ID);
ui->tableOperators->sortByColumn(MODEL_OPERATORS_COL_NAME);
ui->tableOperators->setItemDelegate(&_delegateOperators);
ReadOnlyDelegate *delegate = new ReadOnlyDelegate(ui->tableOperators);
ui->tableOperators->setItemDelegateForColumn(MODEL_OPERATORS_COL_SIGNATURE, delegate);
QSqlTableModel::setData()
的documentation说:
Returns false if the role is not Qt::EditRole. To set data for roles other than EditRole, either use a custom proxy model or subclass QSqlTableModel.
但我仍然得到 false
,即使角色是 Qt::EditRole
。
我的模型:
#ifndef MODELOPERATORS_H
#define MODELOPERATORS_H
#include <QSqlTableModel>
enum
{
MODEL_OPERATORS_COL_ID,
MODEL_OPERATORS_COL_NAME,
MODEL_OPERATORS_COL_SIGNATURE,
MODEL_OPERATORS_COL_COUNT
};
class ModelOperators : public QSqlTableModel
{
Q_OBJECT
public:
typedef struct
{
QString name;
QString signature;
} item_t;
ModelOperators(QObject *parent = nullptr, QSqlDatabase db = QSqlDatabase());
~ModelOperators();
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
};
#endif // MODELOPERATORS_H
#include "modeloperators.h"
ModelOperators::ModelOperators(QObject *parent, QSqlDatabase db) : QSqlTableModel(parent, db)
{
setTable("operators");
setEditStrategy(QSqlTableModel::OnFieldChange);
select();
}
ModelOperators::~ModelOperators() { }
QVariant ModelOperators::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal)
{
if (role == Qt::TextAlignmentRole) return Qt::AlignCenter;
if (role == Qt::DisplayRole)
{
switch(section)
{
case MODEL_OPERATORS_COL_NAME: return tr("Name");
case MODEL_OPERATORS_COL_SIGNATURE: return tr("Signature");
default: return "";
}
}
}
return QVariant();
}
Qt::ItemFlags ModelOperators::flags(const QModelIndex &index) const
{
switch (index.column())
{
case MODEL_OPERATORS_COL_NAME: return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
case MODEL_OPERATORS_COL_SIGNATURE: return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
default: return Qt::NoItemFlags;
}
}
Table定义:
bool DatabaseManager::appCreateTableOperators()
{
QSqlQuery query(QSqlDatabase::database("dbApp"));
query.prepare("CREATE TABLE operators ("
"id INTEGER PRIMARY KEY, "
"name TEXT, "
"signature TEXT)");
return query.exec();
}
用法:
DialogSettings::DialogSettings(QWidget *parent) : QDialog(parent), ui(new Ui::DialogSettings)
{
ui->setupUi(this);
_modelOperators = new ModelOperators(this, QSqlDatabase::database("dbApp"));
ui->tableOperators->setModel(_modelOperators);
ui->tableOperators->hideColumn(MODEL_OPERATORS_COL_ID);
ui->tableOperators->sortByColumn(MODEL_OPERATORS_COL_NAME);
ui->tableOperators->setItemDelegate(&_delegateOperators);
}
void DialogSettings::on_btnOperatorsBrowse_clicked()
{
if (ui->tableOperators->selectionModel()->hasSelection())
{
QString filename = QFileDialog::getOpenFileName(this, tr("Select signature image"), QDir::homePath(), tr("Portable Network Graphics (*.png)"));
if (filename.isEmpty()) return;
int row = ui->tableOperators->selectionModel()->currentIndex().row();
QModelIndex index = _modelOperators->index(row, MODEL_OPERATORS_COL_SIGNATURE);
qDebug() << _modelOperators->setData(index, filename, Qt::EditRole);
}
}
但是 returns false
当然数据库没有更新;
如果修改了source code,问题就明白了:
bool QSqlTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
// ...
if (!(flags(index) & Qt::ItemIsEditable))
return false;
// ...
}
可以看出,如果 QModelIndex 不可编辑,则 setData 将不执行任何操作,return false,如本例所示。
因此解决方案是启用版本,但我猜您不希望该列可编辑,因此我们将放置一个不允许编辑的委托,而不是使用标志:
Qt::ItemFlags ModelOperators::flags(const QModelIndex &index) const
{
switch (index.column())
{
case MODEL_OPERATORS_COL_NAME: return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
case MODEL_OPERATORS_COL_SIGNATURE: return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
default: return Qt::NoItemFlags;
}
}
class ReadOnlyDelegate: public QStyledItemDelegate
{
public:
using QStyledItemDelegate::QStyledItemDelegate;
QWidget *createEditor(QWidget */*parent*/, const QStyleOptionViewItem & /*option*/, const QModelIndex &/*index*/) const override
{
return nullptr;
}
};
_modelOperators = new ModelOperators(this, QSqlDatabase::database("dbApp"));
ui->tableOperators->setModel(_modelOperators);
ui->tableOperators->hideColumn(MODEL_OPERATORS_COL_ID);
ui->tableOperators->sortByColumn(MODEL_OPERATORS_COL_NAME);
ui->tableOperators->setItemDelegate(&_delegateOperators);
ReadOnlyDelegate *delegate = new ReadOnlyDelegate(ui->tableOperators);
ui->tableOperators->setItemDelegateForColumn(MODEL_OPERATORS_COL_SIGNATURE, delegate);