Custom Undo/Redo develop

Operating system: window 11
Slicer version: slicer 5.2.1

Q1. After searching various materials, it was said that the undo/redo function for all nodes drawn in the scene is difficult to implement. Is this true?

Q2. If so, I want to create a redo and undo function for a specific node (markupFiducial, Closedcurved).

# Enable undo for the scene

slicer.mrmlScene.SetUndoOn()

# Enable undo for markups fiducial nodes

defaultMarkupsNode = slicer.mrmlScene.GetDefaultNodeByClass("vtkMRMLMarkupsFiducialNode")
if not defaultMarkupsNode:
    defaultMarkupsNode = slicer.vtkMRMLMarkupsFiducialNode()
    slicer.mrmlScene.AddDefaultNode(defaultMarkupsNode)

defaultMarkupsNode.UndoEnabledOn()

# Add standard keyboard shortcuts for scene undo/redo

redoKeyBindings = qt.QKeySequence.keyBindings(qt.QKeySequence.Redo)
for redoBinding in redoKeyBindings:
    redoShortcut = qt.QShortcut(slicer.util.mainWindow())
    redoShortcut.setKey(redoBinding)
    redoShortcut.connect("activated()", slicer.mrmlScene.Redo)

undoKeyBindings = qt.QKeySequence.keyBindings(qt.QKeySequence.Undo)
for undoBinding in undoKeyBindings:
    undoShortcut = qt.QShortcut(slicer.util.mainWindow())
    undoShortcut.setKey(undoBinding)
    undoShortcut.connect("activated()", slicer.mrmlScene.Undo)

This @lassoan 's code not working in python interactor

After posting this question, I’ll add more detailed questions as I continue to investigate.

What I want to know is how to implement redo/undo for a specific node.

After copy-pasting the code snippet in the Python console, undo/redo works well for markup point lists. Please describe what you did, what you expected to happen, and what happened instead.

step1) copy-pasting your full-code in python console

step2) check one markup points

step3) Press ‘Ctrl+z’ or ‘Alt + Backspace’

result ) The markup point does not disappear and is maintained.

# set undo flag on 
slicer.mrmlScene.SetUndoOn()

# set node types what you want to undo
m_node = slicer.mrmlScene.GetDefaultNodeByClass("vtkMRMLMarkupsFiducialNode")

# save current state
slicer.mrmlScene.SaveStateForUndo()


'making.. markups...'

'oh my mistakes ! let's undo '

# exe undo fucntions ! 
slicer.mrmlScene.Undo


# render preview view 
"um.. i don't know built-in functions"

I think the undo process for vtkMRMLMarkupsFiducialNode is the same as above. Is that correct?
@lassoan

The code snippets changes the default markup point list node so that by default all new nodes of this class are created with undo enabled. If you already have a node then call UndoEnabledOn() method on that existing node.