Is there a default undo operation?
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Be nice to others! Respect the FreeCAD code of conduct!
-
- Posts: 216
- Joined: Tue Oct 02, 2012 7:29 am
Is there a default undo operation?
I tried to implement the undo function for my project, I tried to use 'Ctrl+Z', which is in line with the user habits.
But when I create objects and press 'Ctrl+Z'(I code nothing for the 'Ctrl+Z'), some objects hided.
So, is there a default undo operation? How to work with it, or could I just close it?
But when I create objects and press 'Ctrl+Z'(I code nothing for the 'Ctrl+Z'), some objects hided.
So, is there a default undo operation? How to work with it, or could I just close it?
Re: Is there a default undo operation?
The Gui objects (ViewProvider) are not included in the Undo (transaction) mechanisms .
The Transaction system has a interface in the Document python class, you don't need to intercept the key strokes...
The Transaction system has a interface in the Document python class, you don't need to intercept the key strokes...
Stop whining - start coding!
-
- Posts: 216
- Joined: Tue Oct 02, 2012 7:29 am
Re: Is there a default undo operation?
Currently, I am planning to use the follow code to implement the undo function:
Then I could use
I used Document python class, and the App part of my objects do nothing for most of my shapes .
To be honest I just design a lightweight architecture, which only applies to DDA and may not be consistent with FreeCAD in architecture. In the architecture, there is a database in the background to store all DDA data, data is stored by category. And all shapes of one kind are display with only one document object. The objects are kept in my workbench once created until the workbench done. Once data in database changed, corresponding ViewProvider(by category) is trigger to update graph.
So the key of undo process in my project is the changes of database.
(The design of my architecture of my project is in iteration, it 6th version now. Because I didn't read FreeCAD code in-depth, this is the best architecure I could designed currently. I will try to improve my architecture)
I don't want to intercept the key strokes as well, but I have to do my custom undo process.
Currently, if I press 'Ctrl+Z', some objects disappeared in my surprise, which is out of my plan.
So could I close the default Undo mechanisms, or how could I implement my undo process under the default Undo mechanisms(just the start to put my undo code is ok)?
Code: Select all
from pivy import coin
class OperationObverser:
'''
observe the operation, catch keyboard event to supply redo/undo application
'''
def __init__(self):
self.call = None
self.on = False
def Activated(self, name="None"):
self.on = True
self.view = FreeCADGui.ActiveDocument.ActiveView
self.call = self.view.addEventCallback("SoEvent", self.action)
def IsActive(self):
return self.on
def action(self, arg):
"scene event handler"
if arg["Type"] == "SoKeyboardEvent":
# FreeCAD.Console.PrintMessage('keyboardEvent\n')
if arg["CtrlDown"] and arg["Key"] == 'z':
print 'ctrl z'
# do the undo process
def Deactivated(self):
if self.call:
self.view.removeEventCallback("SoEvent", self.call)
self.call=None
self.on = False
self.view = None
import FreeCADGui
FreeCADGui.DDAOperationObverser = OperationObverser()
Code: Select all
FreeCADGui.DDAOperationObverser.Activated() # start my undo observation
FreeCADGui.DDAOperationObverser.Deactivated() # stop my undo observation
To be honest I just design a lightweight architecture, which only applies to DDA and may not be consistent with FreeCAD in architecture. In the architecture, there is a database in the background to store all DDA data, data is stored by category. And all shapes of one kind are display with only one document object. The objects are kept in my workbench once created until the workbench done. Once data in database changed, corresponding ViewProvider(by category) is trigger to update graph.
So the key of undo process in my project is the changes of database.
(The design of my architecture of my project is in iteration, it 6th version now. Because I didn't read FreeCAD code in-depth, this is the best architecure I could designed currently. I will try to improve my architecture)
I don't want to intercept the key strokes as well, but I have to do my custom undo process.
Currently, if I press 'Ctrl+Z', some objects disappeared in my surprise, which is out of my plan.
So could I close the default Undo mechanisms, or how could I implement my undo process under the default Undo mechanisms(just the start to put my undo code is ok)?
Re: Is there a default undo operation?
Ok, I see...
If you want to use the undo/redo system you have to give the document informations about you modeling steps. So if you ,for exampel, create a object, open a new transaction:
App.AcctiveDocument.openTransaction("name of the transaction").
if you change the object open a new transaction.
now when the user do Undo, the transactions get rolled back one after another. If its role back the first transaction the object gets removed (not deleted cause of a possible redo). If you have only one transaction running from the start, a Undo will undo all from the start.....
Most of the FreeCAD commands open a transaction, so you can look into that code....
If you want to use the undo/redo system you have to give the document informations about you modeling steps. So if you ,for exampel, create a object, open a new transaction:
App.AcctiveDocument.openTransaction("name of the transaction").
if you change the object open a new transaction.
now when the user do Undo, the transactions get rolled back one after another. If its role back the first transaction the object gets removed (not deleted cause of a possible redo). If you have only one transaction running from the start, a Undo will undo all from the start.....
Most of the FreeCAD commands open a transaction, so you can look into that code....
Stop whining - start coding!
-
- Posts: 216
- Joined: Tue Oct 02, 2012 7:29 am
Re: Is there a default undo operation?
Ahh, thank you, jriegel.
I read the 'todo' of 'Draft' workbench again, I understand the todo.commitList now. I will try to use it.
And it is incredible that FreeCAD could do Undo steps like this. It is called much simpler than my undo process.
But could you explain a bit for me. I want to understand the mechanism to code better.
Let's look at the simplest step of Draft, like adding a line.
If I created 3 lines with the class 'Line', the code above were used for 3 times. So there are 3 transactions, we named them A B and C . If I press 'Ctrl+Z', how did FreeCAD do?
Does FreeCAD do transaction A and B again, and don't do transaction C?
If not , how does FreeCAD roll back?
I read the 'todo' of 'Draft' workbench again, I understand the todo.commitList now. I will try to use it.
And it is incredible that FreeCAD could do Undo steps like this. It is called much simpler than my undo process.
But could you explain a bit for me. I want to understand the mechanism to code better.
Let's look at the simplest step of Draft, like adding a line.
Code: Select all
# the following code comes from Line.finish() of 'DraftTools.py'
self.commit(translate("draft","Create DWire"),
['import Draft',
'points='+pts,
'Draft.makeWire(points,closed='+str(closed)+',face='+fil+',support='+sup+')'])
Does FreeCAD do transaction A and B again, and don't do transaction C?
If not , how does FreeCAD roll back?
Re: Is there a default undo operation?
Its much simpler, you don't need to bother with what you do. After start a transaction the document records all changes to the objects in the document. Also creation and deletion of objects. The size of transactions is on you. Normaly one user command or the result of a dialog. When undoing a transaction or do a roll-back in a transaction, the document just simply undo all changes to the document and you have the state before start of a transaction.
If the document is in transaction mode, there is allways one transaction open. A new transaction end the last one. If you close a transaction a automatic one will be opened if you change the document . So the only thing you have to do is give the document the points in time where to start a new transaction, and of course name, which see the user in the undo box.
Yorik put in Draft ontop of this mechanism a additional logic, to make it easier to use in Draft. Thats all. If you want to keep it simple, just use App.ActiveDocument.openTransaction(name)......
If the document is in transaction mode, there is allways one transaction open. A new transaction end the last one. If you close a transaction a automatic one will be opened if you change the document . So the only thing you have to do is give the document the points in time where to start a new transaction, and of course name, which see the user in the undo box.
Yorik put in Draft ontop of this mechanism a additional logic, to make it easier to use in Draft. Thats all. If you want to keep it simple, just use App.ActiveDocument.openTransaction(name)......
Stop whining - start coding!
-
- Posts: 216
- Joined: Tue Oct 02, 2012 7:29 am
Re: Is there a default undo operation?
Thank you, jriegel.
I will try.
I will try.
-
- Posts: 216
- Joined: Tue Oct 02, 2012 7:29 am
Re: Is there a default undo operation?
The transaction attracts me a lot, and I tried to use it today.
I write a simple example, but it doesn't work.
After the script, I press 'Ctrl+Z', nothing happened.
Do I use it in a wrong way?
There are something confusing me at the same time:
1. Does a transaction starts with 'FreeCAD.ActiveDocument.openTransaction([name])' and ends with FreeCAD.ActiveDocument.commitTransaction() ?
2. Will commands between 2 transactions be recorded?
3.Do commands in a transaction must have run before store in a transaction?
3. What kinds of command could be recorded?
I write a simple example, but it doesn't work.
Code: Select all
import FreeCAD , FreeCADGui , Part
from FreeCAD import Vector
obj = FreeCAD.ActiveDocument.addObject("Part::Feature", 'ABC')
v1 = Vector(1,1,0)
v2 = Vector(1,0,0)
v3 = Vector(0,0,0)
v4 = Vector(0,1,0)
l1 = Part.makeLine(v1,v2)
l2 = Part.makeLine(v1,v3)
l3 = Part.makeLine(v1,v4)
def saveTransaction(commands):
assert isinstance(commands , list)
FreeCAD.ActiveDocument.openTransaction('abc')
for command in commands:
FreeCADGui.doCommand(command)
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.getObject('ABC').Shape = l1
saveTransaction(['''FreeCAD.ActiveDocument.getObject('ABC').ViewObject.LineColor = (1.0,0.0,0.0)'''])
FreeCAD.ActiveDocument.getObject('ABC').Shape = l2
saveTransaction(['''FreeCAD.ActiveDocument.getObject('ABC').ViewObject.LineColor = (0.0,1.0,0.0)'''])
FreeCAD.ActiveDocument.getObject('ABC').Shape = l3
saveTransaction(['''FreeCAD.ActiveDocument.getObject('ABC').ViewObject.LineColor = (0.0,0.0,1.0)'''])
Do I use it in a wrong way?
There are something confusing me at the same time:
1. Does a transaction starts with 'FreeCAD.ActiveDocument.openTransaction([name])' and ends with FreeCAD.ActiveDocument.commitTransaction() ?
2. Will commands between 2 transactions be recorded?
3.Do commands in a transaction must have run before store in a transaction?
3. What kinds of command could be recorded?
Re: Is there a default undo operation?
You are mixing up two concepts: the transaction framework and macro recording
The second call of openTransaction automatically closes the first transaction.
And again for the transaction framework it's currently impossible to store changes on the GUI side. So, that's why your script doesn't do for CTRL+Z. Here is a modified one:
Yes. And for convenience you can also do:1. Does a transaction starts with 'FreeCAD.ActiveDocument.openTransaction([name])' and ends with FreeCAD.ActiveDocument.commitTransaction() ?
Code: Select all
FreeCAD.ActiveDocument.openTransaction("Command 1")
... # change some properties
FreeCAD.ActiveDocument.openTransaction("Command 2")
...
The recording of a command has nothing to do with the transaction framework. Since (funnily) for Python it's impossible to record the code (because we need to save a string) Yorik wrote the saveTransaction() function where he can pass a string to the interpreter and thus make it possible to record the command.2. Will commands between 2 transactions be recorded?
If macro recording is activated and the command comes through the doCommand() function it gets recorded.3. What kinds of command could be recorded?
And again for the transaction framework it's currently impossible to store changes on the GUI side. So, that's why your script doesn't do for CTRL+Z. Here is a modified one:
Code: Select all
import FreeCAD , FreeCADGui , Part
from FreeCAD import Vector
obj = FreeCAD.ActiveDocument.addObject("Part::Feature", 'ABC')
v1 = Vector(1,1,0)
v2 = Vector(1,0,0)
v3 = Vector(0,0,0)
v4 = Vector(0,1,0)
l1 = Part.makeLine(v1,v2)
l2 = Part.makeLine(v1,v3)
l3 = Part.makeLine(v1,v4)
def saveTransaction(commands):
assert isinstance(commands , list)
FreeCAD.ActiveDocument.openTransaction('abc')
for command in commands:
FreeCADGui.doCommand(command)
FreeCAD.ActiveDocument.commitTransaction()
saveTransaction(['''FreeCAD.ActiveDocument.getObject('ABC').Shape = l1'''])
saveTransaction(['''FreeCAD.ActiveDocument.getObject('ABC').Shape = l2'''])
saveTransaction(['''FreeCAD.ActiveDocument.getObject('ABC').Shape = l3'''])
-
- Posts: 216
- Joined: Tue Oct 02, 2012 7:29 am
Re: Is there a default undo operation?
To speed up my program, as I said above, I code the gui class and app class for my objects in my project. The app class I wrote does nothing, and gui class read data from database in background to draw shapes.And again for the transaction framework it's currently impossible to store changes on the GUI side. So, that's why your script doesn't do for CTRL+Z. Here is a modified one:
Does this mean that I could not use transaction to implement undo process?