c++ qtableview支持撤销重做 代码
时间: 2023-10-21 19:14:57 浏览: 74
C++ 撤销重做功能
以下是一个简单的实现示例,其中数据模型继承自 QAbstractTableModel 类:
```
class MyTableModel : public QAbstractTableModel
{
public:
MyTableModel(QObject *parent = 0);
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
void undo();
void redo();
bool canUndo() const;
bool canRedo() const;
private:
QList<QList<QVariant>> m_data;
QUndoStack *m_undoStack;
};
MyTableModel::MyTableModel(QObject *parent)
: QAbstractTableModel(parent)
{
// 初始化数据
m_data = {
{1, "apple", 5},
{2, "banana", 3},
{3, "orange", 4},
};
// 创建QUndoStack对象
m_undoStack = new QUndoStack(this);
}
int MyTableModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return m_data.count();
}
int MyTableModel::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return 3;
}
QVariant MyTableModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if (role == Qt::DisplayRole || role == Qt::EditRole) {
int row = index.row();
int col = index.column();
return m_data.at(row).at(col);
}
return QVariant();
}
bool MyTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (!index.isValid() || role != Qt::EditRole)
return false;
int row = index.row();
int col = index.column();
QVariant oldValue = m_data.at(row).at(col);
if (oldValue != value) {
// 创建QUndoCommand对象,并将其放入QUndoStack中
EditCommand *command = new EditCommand(this, row, col, oldValue, value);
m_undoStack->push(command);
// 更新数据
m_data[row][col] = value;
// 发出数据变更信号
emit dataChanged(index, index, QVector<int>() << role);
return true;
}
return false;
}
Qt::ItemFlags MyTableModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return Qt::NoItemFlags;
return Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}
void MyTableModel::undo()
{
if (m_undoStack->canUndo())
m_undoStack->undo();
}
void MyTableModel::redo()
{
if (m_undoStack->canRedo())
m_undoStack->redo();
}
bool MyTableModel::canUndo() const
{
return m_undoStack->canUndo();
}
bool MyTableModel::canRedo() const
{
return m_undoStack->canRedo();
}
```
其中,EditCommand 是自定义的 QUndoCommand 子类,用于保存旧值和新值,并实现撤销和重做操作。以下是 EditCommand 类的实现:
```
class EditCommand : public QUndoCommand
{
public:
EditCommand(MyTableModel *model, int row, int col, QVariant oldValue, QVariant newValue);
void undo() override;
void redo() override;
private:
MyTableModel *m_model;
int m_row;
int m_col;
QVariant m_oldValue;
QVariant m_newValue;
};
EditCommand::EditCommand(MyTableModel *model, int row, int col, QVariant oldValue, QVariant newValue)
: QUndoCommand()
{
m_model = model;
m_row = row;
m_col = col;
m_oldValue = oldValue;
m_newValue = newValue;
}
void EditCommand::undo()
{
m_model->setData(m_model->index(m_row, m_col), m_oldValue, Qt::EditRole);
}
void EditCommand::redo()
{
m_model->setData(m_model->index(m_row, m_col), m_newValue, Qt::EditRole);
}
```
在 EditCommand 的构造函数中,保存了数据模型、行号、列号、旧值和新值,以便在撤销和重做时使用。
在 EditCommand 的 undo() 函数中,将数据模型的对应数据恢复为旧值;在 redo() 函数中,将数据模型的对应数据更新为新值。
阅读全文