对QTreeWidget中树节点的创建、删除和移动操作的撤销和恢复:
当每次操作成功之后保存当前操作的节点指针,父节点指针(为nullptr时默认认为父节点是QTreeWidget* )和当前操作节点在父节点的孩子节点中的位置
也可以使用Qt库中
- QtUndoCommand
- QtUndoStack - QtUndoCommand实现相关操作
//伪代码...
// .h:
enum E_StepType{ //步骤类型
ST_MoveUp=0X00,
ST_MoveDown=0X01,
ST_LevelUp=0X02,
ST_LevelDown=0X03,
ST_Create=0X04,
ST_Delete=0X05,
ST_Unknow=-1
};
struct StepInfo{ //步骤信息
E_StepType type=ST_Unknow;
QTreeWidgetItem* pParentItem=nullptr;
int itemIndex=-1;
QTreeWidgetItem* targetItem=nullptr;
};
QList<StepInfo> stepInfoList;
int steplistPos=0; //步骤位置
void undoTreeWidget(); // 撤销当前操作步骤并保存
void redoTreeWidget(); // 重做保存的撤销操作
void pushStepInfo(const StepInfo& stepInfo); // 保存操作项
// .cpp:
void undoTreeWidget(){ //撤销
auto bgn=this->stepInfoList.begin()+this->steplistPos;
if(bgn==this->stepInfoList.end()) //到栈底
return;
switch (E_StepType(bgn->type)) {
case ST_Create:
// *bgn得到项位置信息...
// takeTopLevelItem(int index)或pItemParent->takeChild(int index)
break;
case ST_MoveUp:
case ST_MoveDown:
case ST_LevelUp:
case ST_LevelDown:{
auto& startPos=*bgn;
++this->steplistPos;
++bgn;
auto& endPos=*bgn;
// 通过startPos和endPos得到前后位置信息
// QTreeWidget::takeTopLevelItem(int index)或QTreeWidgetItem::takeChild(int
// index)
}
break;
case ST_Delete:
// *bgn 得到项信息
// insertItem(int index, QTreeWidgetItem *item);
break;
default:
break;
}
++this->steplistPos;
}
void redoTreeWidget(){ //重做
auto bgn=this->stepInfoList.begin()+this->steplistPos;
if(bgn==this->stepInfoList.begin()) //到栈底
return;
--bgn;
--this->steplistPos;
switch (E_StepType(bgn->type)) {
case ST_Create:
// *bgn 得到项信息
// insertItem(int index, QTreeWidgetItem *item);
break;
case ST_MoveUp:
case ST_MoveDown:
case ST_LevelUp:
case ST_LevelDown:{
auto& startPos=*bgn;
--bgn;
--this->steplistPos;
auto& endPos=*bgn;
// 通过startPos和endPos得到前后位置信息
// takeTopLevelItem(int index)或pItemParent->takeChild(int index)
}
break;
case ST_Delete:
// *bgn得到项位置信息...
// takeTopLevelItem(int index)或pItemParent->takeChild(int index)
break;
default:
break;
}
}
//记录操作项信息:若移动、删除、创建成功保存记录,移动操作需要保存移动前后的位置信息
void pushStepInfo(const StepInfo& stepInfo){
this->stepInfoList.insert(this->steplistPos,stepInfo);
if(this->steplistPos!=0){ //移除重做项
for(int i=0;i<this->steplistPos;++i){
StepInfo& step= this->stepInfoList.front();
this->stepInfoList.pop_front();
if(step.type!=E_StepType::ST_Create)
continue;
if(step.targetItem->treeWidget()==nullptr)
delete step.targetItem;
}
this->steplistPos=0;
}