Undo actions.
-
Hi, i need to create the actions for the user, but i dont know how to do that.
I read the documentation, but i do not understand that.For example, i have one button, and when i press it, it's gonna increment the variable by one, if i understood good that documentation, i need to create something like commands or actions?
So one action increment the variable, and the other one decrement it, but how get the result, if i increment it 4 times, and decrement 2 times? I don't understand. -
Hi
It works with QUndoStack.
You push the commands to the stack when they are executed,
if you want to undo, you take them off the stack.
Each command will increase by one or if asked to undo , then decrease by one.
So each step of undo, goes back one step for the value. -
OK, but i need to create my own actions, because the program does custom stuff, so i need to do for example
void Undo_Something() { Variable_1-- Variable_2++ } void Redo_Something() { Variable_1++ Variable_2-- }
Or it's automatic?
I mean, i just need to call undo() and redo(), or i need to edit it? -
Ye, but as you can see, i am not so good with stuff like that, first time i need to do something like that. I just ask, because maybe he is "smart enough" to know it in some way.
But ok, i will try to do that.
So, i need to inherrit the class, implement undo() and redo(), and then create the actions?That "QUndoStack" class object need to be created too?
-
@Loc888
Hi
Yes you should have a QUndoStack variable too in the class.
Its not super complex if u take from the examples.
Here is how a "text"command is made. ( it can insert/remove some text in a document)class AppendText : public QUndoCommand { public: AppendText(QString *doc, const QString &text) : m_document(doc), m_text(text) { setText("append text"); } virtual void undo() { m_document->chop(m_text.length()); } virtual void redo() { m_document->append(m_text); } private: QString *m_document; QString m_text; };
-
Ok i have:
#ifndef COMMAND_ACTIONS_H #define COMMAND_ACTIONS_H #include <QUndoCommand> #include <QUndoStack> class Command_Actions : public QUndoCommand { public: Command_Actions(); virtual void redo(); virtual void undo(); }; #endif // COMMAND_ACTIONS_H
What should i put in undo() ? Because i want delete the last action, or i just do it in that QUndoStack ? I mean, delete the last action?
#include "Command_Actions.h" Command_Actions::Command_Actions() { } void Command_Actions::redo() { } void Command_Actions::undo() { }
-
I think i dont undersand it.
Maybe i explain it, so:
I create undo() and redo() as general actions, but then i wanna be able to do more stuff.
So it's gonna be:Action_Plus_5(); Action_Minus_5(); Action_Increment(); Action_Decrement();
And that's the problem, how i call them in undo() and redo??
I mean, how by undo() delete the last used action, so for example Action_Plus_5() ? -
@Loc888
Hi
Please look at this
http://doc.qt.io/qt-5/qtwidgets-tools-undoframework-example.html
you can see how it uses the undoStack and how to use the system. -
Ye, i see that... And i am lost.
I read that, and i dont know wher i must declare any functionality....When i use the Stack.push(Command), how i am gonna tell to the "Command" to do something??
It's a variable, so how can i declare to it any functionality?
Add or subtract something? -
Hi
You let the commands points to the data so u can change it from inside them.
From sampleclass MoveCommand : public QUndoCommand { public: enum { Id = 1234 }; MoveCommand(DiagramItem *diagramItem, const QPointF &oldPos, QUndoCommand *parent = 0); void undo() override; void redo() override; bool mergeWith(const QUndoCommand *command) override; int id() const override { return Id; } private: DiagramItem *myDiagramItem; // this would be your data. point to the variable QPointF myOldPos; // this would be old value }; and to restore you do void MoveCommand::undo() { myDiagramItem->setPos(myOldPos); // this would be to decrease or set old value back myDiagramItem->scene()->update(); setText(QObject::tr("Move %1") .arg(createCommandString(myDiagramItem, newPos))); }
-
Ther is no way to just undo a method or funtion? I have alot of this variables, so how many of those diagrams i am gonna create?
It's gonna mess up the code, at this point is a lot of stuff ther.Ps. It's not better, just to create one structure with all that data, and maybe then point to it?
-
Hi
how would u undo a method ?
Yes if u have a lots of single variables that need undo / redo then it will be many small classes.Since i dont know your use case or the code its hard to say if there would be easier way.
Do you need for each variable to be able to undo many levels or just last value ?
Also, you can make Commands class that can handle all, you just need to specify for what data member the undo applies when undoing etc.
But again, there are many ways to do this but it depends on the code u already have what will be easy.-Ps. It's not better, just tocreate one structure with all that data, and maybe then point to it?
Yes, using a struct would make is more easy to handle -
"Do you need for each variable to be able to undo many levels or just last value ?"
Ther almost everything must be able to undo, redo is not necessary. Needed 5 levels.
How to assign a structure member to that QUndoCommand object?
Ther is no way to point to the structure, because it's different type.
I dont find any method to set that equal. -
@Loc888
Hi
So each variable need to be able to undo many values back ?- How to assign a structure member to that QUndoCommand object?
You just do it. you can use any type u like.
class MoveCommand : public QUndoCommand { public: enum { Id = 1234 }; MoveCommand(DiagramItem *diagramItem, const QPointF &oldPos, QUndoCommand *parent = 0);
the DiagramItem and QPointF could be ANYTHIng you need
MoveCommand(DiagramItem *diagramItem, const QPointF &oldPos,
those are jsut what sample need, you can just use the types u need - How to assign a structure member to that QUndoCommand object?
-
@mrjj said in Undo actions.:
diagramItem
At this point, i am gonna create a structure, and create 10 objects, and then simply switch them, so:
Memory_001 = Memory_002
Memory_002 = Memory_003 // And progress.Is it a good idea? What about performance? (They are not so big, around 200 - 400 variables)
-
@Loc888
On a desktop class pc, it would be nothing for it.
But if u need multiple levels on undo such structure would not work.can you show some of the data u need multiple levels of undo for (real code) ?
are they int/floats, strings etc ?
Are they all of same type or very mixed? -
@mrjj Need at least5 of them, and max 10. Ther is rly no need to create more in this case.
I show you the template:
struct:Data
{int*
int*
int*long double*
long double*
long double*
long double*
long double*
long double*
long double*
long double*
long double*};
Stuff like that, i have around 4 - 6 of them, so it's like 30 objects * 10...
I think is much more then 300 variables, but not all must be able to undo,
cuz ther is a percentage calculator, so it's gonna re-calculate it again.
Ther are around +150 variables of "percent type", so they don't need to be stored, the function gonna recalculate them by current value of variables.So i am gonna create a structure with that six structures, and the total of variables gonna be maybe 800?? (Some long double) Gonna work?