c++ - QSqlTableModel::setData() 对于 Qt::EditMode 也返回 false

标签 c++ qt sqlite qt5 qsqltablemodel

documentation QSqlTableModel::setData() 说:

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.

但即使角色是 Qt::EditRole,我仍然得到 false

我的模型:

#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;
    }
}

表定义:

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);
    }
}

但它返回false,当然数据库没有更新;

最佳答案

如果source code修改完毕,问题明白了:

bool QSqlTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    // ...

    if (!(flags(index) & Qt::ItemIsEditable))
        return false;
    // ...
}

可以看出,如果 QModelIndex 不可编辑,则 setData 将不执行任何操作并返回 false,如本例所示。

因此,解决方案是启用该版本,但我猜您不希望该列可编辑,因此我们将放置一个不允许编辑的委托(delegate),而不是使用该标志:

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);

关于c++ - QSqlTableModel::setData() 对于 Qt::EditMode 也返回 false,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54334601/

相关文章:

qt - 如何使用 Windows/MinGW 平台为带有 SQLCipher 扩展的 SQLite-DB 构建 Qt-SQL-driver-plugin 'QSQLCIPHER'?

C++ 在 Pimple 习语中的类之前或成员之前进行前向声明?

c++ - 我的树节点缺少链接

c++ - 使用 Linux 将 DVD 内容复制到硬盘的最快方法是什么?

c++ - 使用 unordered_sets 的 unordered_map

c++ - Qdialog执行的返回值

c++ - qt 5.7 + Xcode 8.1 + os x El Capitan - 无法解析 'macosx' 的 SDK 路径

php - 如何在 Ubuntu 13.10 上安装 PHP PECL 扩展 "SQLite"

c++ - 在 qt 中将 git hash 打印为编译时创建的宏

java - Ebean ORM在SQLite中自动创建表结构