我有一个基于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中。
现在,我想从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。
发布于 2020-10-26 01:30:24
我发现只有在调用submit时,数据才会保存到QSqlTableModel的数据库中。
所以我在addNewEntry of QuestionsProxyModel的末尾加上了
auto sqlModel = qobject_cast<QSqlTableModel*>(sourceModel());
if(sqlModel) {
sqlModel->submit();
}我觉得这个解决方案有点老生常谈。至少,如果底层模型不是QSqlTableModel,那么QuestionsProxyModel仍然可以正常工作。
https://stackoverflow.com/questions/64522739
复制相似问题