下面是完整的代码示例,带有详细注释和重新命名区分model:
#include <QtWidgets>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
private slots:
void undoSlot();
void redoSlot();
void isDataChange();
private:
QTableView *m_tableView;
QList<QStandardItemModel *> m_undoStack; // 撤销栈
QList<QStandardItemModel *> m_redoStack; // 重做栈
};
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
// 创建表格视图
m_tableView = new QTableView(this);
setCentralWidget(m_tableView);
// 创建 Undo 和 Redo 工具栏按钮
QAction *undoAction = new QAction(QIcon(":/images/undo.png"), tr("&Undo"), this);
undoAction->setShortcut(tr("Ctrl+Z"));
undoAction->setEnabled(false);
connect(undoAction, &QAction::triggered, this, &MainWindow::undoSlot);
QAction *redoAction = new QAction(QIcon(":/images/redo.png"), tr("&Redo"), this);
redoAction->setShortcut(tr("Ctrl+Y"));
redoAction->setEnabled(false);
connect(redoAction, &QAction::triggered, this, &MainWindow::redoSlot);
QToolBar *editToolBar = addToolBar(tr("Edit"));
editToolBar->addAction(undoAction);
editToolBar->addAction(redoAction);
// 创建数据模型
QStandardItemModel *model = new QStandardItemModel(4, 2, this);
model->setData(model->index(0, 0), "Name");
model->setData(model->index(1, 0), "Address");
model->setData(model->index(2, 0), "Phone");
model->setData(model->index(3, 0), "Email");
m_tableView->setModel(model);
// 连接数据变化信号到槽函数
connect(model, &QStandardItemModel::dataChanged, this, &MainWindow::isDataChange);
}
void MainWindow::undoSlot()
{
if (m_undoStack.isEmpty()) {
return;
}
QStandardItemModel *model = m_undoStack.takeLast(); // 取出撤销栈的最后一个模型
m_redoStack.append(m_tableView->model()); // 将当前模型加入重做栈
m_tableView->setModel(model); // 设置表格视图的模型为取出的模型
}
void MainWindow::redoSlot()
{
if (m_redoStack.isEmpty()) {
return;
}
QStandardItemModel *model = m_redoStack.takeLast(); // 取出重做栈的最后一个模型
m_undoStack.append(m_tableView->model()); // 将当前模型加入撤销栈
m_tableView->setModel(model); // 设置表格视图的模型为取出的模型
}
void MainWindow::isDataChange()
{
QStandardItemModel *currentModel = static_cast<QStandardItemModel *>(m_tableView->model());
if (!m_undoStack.isEmpty() && m_undoStack.last() == currentModel) { // 如果当前模型已经存在于撤销栈中,则不需要再次加入
return;
}
m_undoStack.append(currentModel); // 将当前模型加入撤销栈
m_redoStack.clear(); // 清空重做栈
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}