处理QAbstractItemModel :: dataChanged()信号时如何获取旧值?

时间:2014-12-01 11:56:52

标签: c++ qt qabstractitemmodel

我有QTableView设置了QStandardItemModel。用户在视图中的某个索引中编辑数据,然后模型发出dataChanged()信号。在我处理SIGNAL的SLOT中,我有QModelIndex范围的用户更改,因此我可以获得用户输入的新值。我如何在那时获得旧值?

4 个答案:

答案 0 :(得分:2)

由于QStandardItemModel是一个简单的模型,因此它没有具有此功能的信号。如果您想要这样的功能,您可以继承QAbstractItemModel并拥有自己的自定义类并实现setData并发出包含旧值和新值的自定义信号。

作为一种解决方法,您可以将itemChanged的{​​{1}}信号连接到某个插槽:

QStandardItemModel

并将新值存储为模型中的connect(model,SIGNAL(itemChanged(QStandardItem*)),this, SLOT(onModelChanged(QStandardItem*))); ,以便在下次调用插槽时将其用作旧值:

Qt::UserRole

答案 1 :(得分:2)

经过一番研究后,我发现没有标准的方法来实现这种行为。要解决这个问题,我必须继承QStandardItemModel并重新实现setData(),如下所示:

class RecallModel : public QStandardItemModel
{
public:
    RecallModel (QObject * parent = 0) : QStandardItemModel(parent) {}

    // Reimplemented
    bool setData(const QModelIndex &index, const QVariant &value, int role= Qt::EditRole)
    {
        // backup the previous model data
        if (role == Qt::EditRole || role == Qt::DisplayRole)
            QStandardItemModel::setData(index, data(index), Qt::UserRole + 1);

        return QStandardItemModel::setData(index, value, role);
    }
};

之后,我可以访问处理dataChanged()信号的插槽中的旧数据:

void SomeObject::handleDataChange(const QModelIndex &topLeft, const QModelIndex &bottomRight)
{
    ...
    const QVariant &vOldData = index.data(Qt::UserRole + 1); // here is the old data
    const QVariant &vNewData = index.data(Qt::DisplayRole); // here is the new data
    ...
}

答案 2 :(得分:1)

用户可以使用委托更改数据,因此可能的解决方案是:

#ifndef ITEMDELEGATE_H
#define ITEMDELEGATE_H

#include <QItemDelegate>

class ItemDelegate : public QItemDelegate
{
    Q_OBJECT
public:
    explicit ItemDelegate(QObject *parent = 0);

protected:
    QWidget* createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
    void setEditorData(QWidget * editor, const QModelIndex & index) const;
    void setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const;
    void updateEditorGeometry(QWidget * editor, const QStyleOptionViewItem & option, const QModelIndex & index) const;

signals:
    void dataChanged(QString oldValue,QString newValue) const;

public slots:
private:
     mutable QString old;//we want change member data in const method

};

#endif // ITEMDELEGATE_H

正如您所看到的,默认情况下有很多方法const,所以我做了一些技巧(例如mutable)以避免出现问题。同样在我编辑的答案中,我没有将旧数据存储在UserRole+1中,所有这些都是使用旧mutable变量完成的。

CPP:

#include "itemdelegate.h"
#include <QLineEdit>
#include <QDebug>

ItemDelegate::ItemDelegate(QObject *parent) :
    QItemDelegate(parent)
{
}

QWidget *ItemDelegate::createEditor(QWidget *parent,
                                    const QStyleOptionViewItem &option,
                                    const QModelIndex &index) const
{
    QLineEdit *editor = new QLineEdit(parent);
    return editor;
}


void ItemDelegate::setEditorData(QWidget *editor,
                                 const QModelIndex &index) const
{
    old = index.model()->data(index, Qt::EditRole).toString();//store old data
    QLineEdit *line = qobject_cast<QLineEdit*>(editor);
    line->setText(old);
}


void ItemDelegate::setModelData(QWidget *editor,
                                QAbstractItemModel *model,
                                const QModelIndex &index)const
{
    QLineEdit *line = static_cast<QLineEdit*>(editor);
    QString data = line->text();

    emit dataChanged(old, line->text());
    model->setData(index, data);
}


void ItemDelegate::updateEditorGeometry(QWidget *editor,
                                        const QStyleOptionViewItem &option,
                                        const QModelIndex &index) const
{
    editor->setGeometry(option.rect);
}

用法:

  ItemDelegate * del = new ItemDelegate;
   connect(del,&ItemDelegate::dataChanged,[=](QString oldValue,QString newValue) {
        qDebug() << "old" << oldValue<< "new" <<newValue ;
   });
    ui->tableView->setItemDelegate(del);

我测试了它并且它有效。它适用于不同的型号。 QTableView默认使用lineEdit作为委托,因此用户不会在视图中看到任何更改。

我在这里使用C++11CONFIG += c++11.pro文件)和new syntax of signals and slots,但当然如果需要,您可以使用旧语法。

答案 3 :(得分:0)

此答案之前的所有解决方案都依赖于Qt特定的功能。但是你可以在Qt框架之外移动INSERT,UPDATE,DELETE(不是SQL,但是常见的)功能。查看工作单元设计模式,以及&#34;企业应用程序架构模式&#34; 中的相关域对象模式。

您可以修改此模式以保留旧值,并在setData()期间修改时获取它。