实现这个功能需要使用QAbstractItemModel类中的数据修改信号和undo/redo框架。下面是一个简单的示例代码:
首先,创建一个自定义的模型MyModel,继承自QAbstractItemModel,实现必要的接口函数:
class MyModel : public QAbstractItemModel
{
Q_OBJECT
public:
explicit MyModel(QObject *parent = nullptr);
QModelIndex index(int row, int column, const QModelIndex &parent) const override;
QModelIndex parent(const QModelIndex &child) const override;
int rowCount(const QModelIndex &parent) const override;
int columnCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
signals:
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int>());
private:
QMap<QModelIndex, QVariant> m_dataMap;
};
在setData函数中捕获数据修改信号,并将原数据保存到undo栈中:
bool MyModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (role == Qt::EditRole) {
// save original data for undo
QVariant originalData = data(index, role);
QUndoCommand *undoCommand = new DataChangeUndoCommand(this, index, originalData);
QUndoStack *undoStack = MainWindow::getInstance()->getUndoStack();
undoStack->push(undoCommand);
m_dataMap[index] = value;
emit dataChanged(index, index);
return true;
}
return false;
}
然后,创建一个自定义的undo命令DataChangeUndoCommand,继承自QUndoCommand,用于保存数据修改的原始状态和新状态:
class DataChangeUndoCommand : public QUndoCommand
{
public:
DataChangeUndoCommand(MyModel *model, const QModelIndex &index, const QVariant &originalData)
: m_model(model), m_index(index), m_originalData(originalData)
{
setText(tr("Data Change"));
}
void undo() override
{
m_model->setData(m_index, m_originalData, Qt::EditRole);
}
void redo() override
{
QVariant newData = m_model->data(m_index, Qt::EditRole);
m_model->setData(m_index, newData, Qt::EditRole);
}
private:
MyModel *m_model;
QModelIndex m_index;
QVariant m_originalData;
};
最后,在窗口中双击QTreeView中的一个项时,获取到该项的数据并保存到变量中:
void MainWindow::on_treeView_doubleClicked(const QModelIndex &index)
{
QVariant data = ui->treeView->model()->data(index);
// save data to variable for later use
}
当需要回到原始状态时,通过调用undo栈的undo函数即可:
MainWindow::getInstance()->getUndoStack()->undo();