c++ - 通过 QIdentityProxyModel 向 QSqlTableModel 添加数据失败
问题描述
我有一个基于QSqlTableModel
:
class QuestionSqlTableModel : public QSqlTableModel
{
Q_OBJECT
public:
explicit QuestionSqlTableModel(QObject *parent = nullptr,
const QSqlDatabase &db = QSqlDatabase());
};
QuestionSqlTableModel::QuestionSqlTableModel(
QObject *parent, const QSqlDatabase &db)
: QSqlTableModel{parent, db}
{
setEditStrategy(EditStrategy::OnFieldChange);
}
现在要将列映射到要在 qml 中使用的角色,我将此模型安装到派生自QIdentityProxyModel
.
一切似乎都很好。我可以从现有数据库中读取数据并通过QIdentityProxyModel
.
现在从 QML 我想添加一个新的数据行。为此,我在QIdentityProxyModel
.
该模型的完整代码:
#include <QObject>
#include <QIdentityProxyModel>
class QuestionsProxyModel : public QIdentityProxyModel
{
Q_OBJECT
enum questionRoles {
idRole = Qt::UserRole + 1,
askedQuestionRole,
answer1Role,
answer2Role,
answer3Role,
answer4Role,
correctAnswerRole,
pictureRole
};
public:
QuestionsProxyModel(QObject* parent = nullptr);
QHash<int, QByteArray> roleNames() const override;
Q_INVOKABLE QVariant data(const QModelIndex &index, int role) const override;
Q_INVOKABLE bool addNewEntry(const QString& askedQuestion,
const QString& answer1,
const QString& answer2,
const QString& answer3,
const QString& answer4,
int correctAnswer,
const QString& picturePath);
private:
QModelIndex mapIndex(const QModelIndex &index, int role) const;
};
#include <QDebug>
#include <QPixmap>
#include <QBuffer>
#include <QByteArray>
namespace QuestionColumn
{
static constexpr auto id = 0;
static constexpr auto askedQuestion = 1;
static constexpr auto answer1 = 2;
static constexpr auto answer2 = 3;
static constexpr auto answer3 = 4;
static constexpr auto answer4 = 5;
static constexpr auto correct_answer = 6;
static constexpr auto picture = 7;
}
QuestionsProxyModel::QuestionsProxyModel(QObject* parent)
:QIdentityProxyModel(parent)
{
}
QHash<int, QByteArray> QuestionsProxyModel::roleNames() const
{
QHash <int,QByteArray> roles;
roles[idRole] = "id";
roles[askedQuestionRole] = "askedQuestion";
roles[answer1Role] = "answer1";
roles[answer2Role] = "answer2";
roles[answer3Role] = "answer3";
roles[answer4Role] = "answer4";
roles[correctAnswerRole] = "correctAnswer";
roles[pictureRole] = "picture";
return roles;
}
QVariant QuestionsProxyModel::data(const QModelIndex &index, int role) const
{
QModelIndex newIndex = mapIndex(index, role);
if (role == idRole
|| role == askedQuestionRole
|| role == answer1Role
|| role == answer2Role
|| role == answer3Role
|| role == answer4Role
|| role == correctAnswerRole
|| role == pictureRole) {
return QIdentityProxyModel::data(newIndex, Qt::DisplayRole);
}
return QIdentityProxyModel::data(newIndex, role);
}
bool QuestionsProxyModel::addNewEntry(const QString &askedQuestion,
const QString &answer1,
const QString &answer2,
const QString &answer3,
const QString &answer4,
int correctAnswer,
const QString &picturePath)
{
Q_ASSERT(!askedQuestion.isEmpty());
Q_ASSERT(!answer1.isEmpty());
Q_ASSERT(!answer2.isEmpty());
Q_ASSERT(!answer3.isEmpty());
Q_ASSERT(!answer4.isEmpty());
Q_ASSERT(correctAnswer >= 1 && correctAnswer <= 4);
auto newRow = rowCount();
if(!insertRow(newRow, QModelIndex{})) {
return false;
}
if(!setData(index(newRow, QuestionColumn::id), newRow + 1)) {
removeRow(newRow);
return false;
}
if(!setData(index(newRow, QuestionColumn::askedQuestion),
askedQuestion)) {
removeRow(newRow);
return false;
}
if(!setData(index(newRow, QuestionColumn::answer1), answer1)) {
removeRow(newRow);
return false;
}
if(!setData(index(newRow, QuestionColumn::answer2), answer2)) {
removeRow(newRow);
return false;
}
if(!setData(index(newRow, QuestionColumn::answer3), answer3)) {
removeRow(newRow);
return false;
}
if(!setData(index(newRow, QuestionColumn::answer4), answer4)) {
removeRow(newRow);
return false;
}
if(!setData(index(newRow, QuestionColumn::correct_answer), correctAnswer)) {
removeRow(newRow);
return false;
}
if(!setData(index(newRow, QuestionColumn::picture), picturePath)) {
removeRow(newRow);
return false;
}
return true;
}
QModelIndex QuestionsProxyModel::mapIndex(const QModelIndex &source, int role) const
{
switch(role) {
case idRole:
return createIndex(source.row(), QuestionColumn::id);
case askedQuestionRole:
return createIndex(source.row(), QuestionColumn::askedQuestion);
case answer1Role:
return createIndex(source.row(), QuestionColumn::answer1);
case answer2Role:
return createIndex(source.row(), QuestionColumn::answer2);
case answer3Role:
return createIndex(source.row(), QuestionColumn::answer3);
case answer4Role:
return createIndex(source.row(), QuestionColumn::answer4);
case correctAnswerRole:
return createIndex(source.row(), QuestionColumn::correct_answer);
case pictureRole:
return createIndex(source.row(), QuestionColumn::picture);
}
return source;
}
现在,如果我使用该方法QuestionsProxyModel::addNewEntry
,我希望所有这些数据都会添加到 SQL 数据库中,但事实并非如此。
奇怪的是在 QML 的视图中我可以看到添加的数据,但是在关闭应用程序时它没有存储在数据库中。insertRow
除了使用和setData
保存到数据库之外,我还需要做些什么吗?
也addNewEntry
只适用于第一次。第二次insertRow
简单地返回 false。
解决方案
我发现数据只保存到调用QSqlTableModel
时的数据库中submit
。
所以我在末尾添加addNewEntry
了 QuestionsProxyModel
:
auto sqlModel = qobject_cast<QSqlTableModel*>(sourceModel());
if(sqlModel) {
sqlModel->submit();
}
我觉得这个解决方案有点 hacky。至少如果基础模型不是 a仍然可以正常工作QSqlTableModel
。QuestionsProxyModel
推荐阅读
- autocomplete - 如何使用 Antd Autocomplete 更改显示建议的数量?
- kotlin - Google Calendar API v3 未保存活动地点和与会者
- java - 无法在华为设备上多次播放音乐文件
- javascript - JavaScript 解析 (JSON)
- javascript - 从 XRegExp 获取匹配
- python - 如果知道中心点,如何计算网格的角点
- python - 根据 2 个数据框(日期时间)获取前后天数
- objective-c - 如何仅更改 UIDatePicker 中所选日期的文本颜色
- c# - 我可以通过访问我在 WinForm App 中为图片框设置的位图图像来使用 C# 录制视频吗?
- android - 线程管理互斥与同步