代码之家  ›  专栏  ›  技术社区  ›  Mark

QSqlTableModel::setData()也使用Qt::EditMode返回false

  •  1
  • Mark  · 技术社区  · 6 年前

    这个 documentation QSqlTableModel::setData() 说:

    如果角色不是Qt::EditRole,则返回false。要为EditRole以外的角色设置数据,请使用自定义代理模型或子类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;
        }
    }
    

    表定义:

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

    但它又回来了 错误的

    1 回复  |  直到 6 年前
        1
  •  2
  •   eyllanesc Yonghwan Shin    6 年前

    如果 source code 修改后,问题被理解为:

    bool QSqlTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
    {
        // ...
    
        if (!(flags(index) & Qt::ItemIsEditable))
            return false;
        // ...
    }
    

    可以看出,如果QModelIndex不可编辑,那么setData将不执行任何操作,并像本例中那样返回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);