c++ qtreewidget支持撤销恢复功能
时间: 2023-07-01 10:12:12 浏览: 135
QT树节点拖拽,支持两个QTreewidget相互拖拽
QTreeWidget本身并不直接支持撤销/恢复功能,但可以利用QUndoStack来实现。下面是一个简单的示例代码,用来演示如何实现QTreeWidget的撤销/恢复功能:
```cpp
#include <QtWidgets>
struct TreeOperation {
enum Type { Insert, Remove, Move, Update };
Type type;
QTreeWidgetItem *item;
QTreeWidgetItem *parent;
int index;
QVariantList data;
};
class TreeOperationCommand : public QUndoCommand {
public:
TreeOperationCommand(QTreeWidget *tree, const TreeOperation &op) :
QUndoCommand(),
m_tree(tree),
m_op(op)
{
setText(operationToString(m_op.type));
}
void undo() override
{
switch (m_op.type) {
case TreeOperation::Insert:
m_tree->blockSignals(true);
m_op.parent->removeChild(m_op.item);
m_tree->blockSignals(false);
break;
case TreeOperation::Remove:
m_tree->blockSignals(true);
m_op.parent->insertChild(m_op.index, m_op.item);
m_tree->blockSignals(false);
break;
case TreeOperation::Move:
m_tree->blockSignals(true);
m_op.parent->takeChild(m_op.index);
m_op.parent->insertChild(m_op.item);
m_tree->blockSignals(false);
break;
case TreeOperation::Update:
m_tree->blockSignals(true);
for (int i = 0; i < m_op.data.count(); i++) {
m_op.item->setData(i, Qt::EditRole, m_op.data[i]);
}
m_tree->blockSignals(false);
break;
}
}
void redo() override
{
switch (m_op.type) {
case TreeOperation::Insert:
m_tree->blockSignals(true);
m_op.parent->insertChild(m_op.index, m_op.item);
m_tree->blockSignals(false);
break;
case TreeOperation::Remove:
m_tree->blockSignals(true);
m_op.parent->removeChild(m_op.item);
m_tree->blockSignals(false);
break;
case TreeOperation::Move:
m_tree->blockSignals(true);
m_op.parent->takeChild(m_op.index);
m_op.parent->insertChild(m_op.item);
m_tree->blockSignals(false);
break;
case TreeOperation::Update:
m_tree->blockSignals(true);
for (int i = 0; i < m_op.data.count(); i++) {
m_op.item->setData(i, Qt::EditRole, m_op.data[i]);
}
m_tree->blockSignals(false);
break;
}
}
private:
QTreeWidget *m_tree;
TreeOperation m_op;
QString operationToString(TreeOperation::Type type) const
{
switch (type) {
case TreeOperation::Insert:
return "Insert";
case TreeOperation::Remove:
return "Remove";
case TreeOperation::Move:
return "Move";
case TreeOperation::Update:
return "Update";
}
return "";
}
};
class TreeWidget : public QTreeWidget {
public:
TreeWidget(QWidget *parent = nullptr) : QTreeWidget(parent)
{
m_undoStack = new QUndoStack(this);
connect(this, &QTreeWidget::itemChanged, this, &TreeWidget::onItemChanged);
}
void insertItem(QTreeWidgetItem *parent, int index, QTreeWidgetItem *item)
{
TreeOperation op;
op.type = TreeOperation::Insert;
op.item = item;
op.parent = parent;
op.index = index;
op.data = itemData(item);
m_undoStack->push(new TreeOperationCommand(this, op));
}
void removeItem(QTreeWidgetItem *parent, int index, QTreeWidgetItem *item)
{
TreeOperation op;
op.type = TreeOperation::Remove;
op.item = item;
op.parent = parent;
op.index = index;
op.data = itemData(item);
m_undoStack->push(new TreeOperationCommand(this, op));
}
void moveItem(QTreeWidgetItem *parent, int oldIndex, int newIndex, QTreeWidgetItem *item)
{
TreeOperation op;
op.type = TreeOperation::Move;
op.item = item;
op.parent = parent;
op.index = oldIndex;
op.data = itemData(item);
m_undoStack->push(new TreeOperationCommand(this, op));
}
void updateItem(QTreeWidgetItem *item)
{
TreeOperation op;
op.type = TreeOperation::Update;
op.item = item;
op.parent = item->parent();
op.index = indexOfTopLevelItem(item);
op.data = itemData(item);
m_undoStack->push(new TreeOperationCommand(this, op));
}
void undo()
{
m_undoStack->undo();
}
void redo()
{
m_undoStack->redo();
}
private:
QUndoStack *m_undoStack;
QVariantList itemData(QTreeWidgetItem *item) const
{
QVariantList data;
int count = item->columnCount();
for (int i = 0; i < count; i++) {
data.append(item->data(i, Qt::EditRole));
}
return data;
}
void onItemChanged(QTreeWidgetItem *item, int column)
{
updateItem(item);
}
};
```
在上面的示例代码中,我们定义了一个TreeOperation结构体,用来记录树形结构的操作,包括插入、删除、移动和更新等操作。然后,我们定义了一个TreeOperationCommand类,用来封装每个操作,并将其添加到QUndoStack中。在TreeWidget类中,我们重载了insertItem、removeItem、moveItem和updateItem方法,用来记录每个操作,并将其封装成TreeOperationCommand对象,并将其添加到QUndoStack中。最后,我们定义了undo和redo方法,用来执行撤销和恢复操作。
阅读全文