Answer the question
In order to leave comments, you need to log in
What is the most simple and correct way to organize behavior similar to a “transaction” (or ctrl-z) for class properties?
Good afternoon!
There is a certain class, with Q_PROPERTY(....)
From UI values are set to it.
After installation, I call the transaction confirmation method.
When setting values, it is possible that you need to undo all changes made and return to the previous values of all properties (at the moment when the previous transaction was confirmed).
So far, when I confirm the transaction, I enter the values of all properties into the array,
when canceled, I restore accordingly from there.
What does not suit you is that you need to manually register each property for each class in which such behavior is needed, which is somewhat tiring, and has already encountered a copy-paste error a couple of times.
Ideally, the solution to the problem would be to inherit from some class, where the functions of confirming and canceling the transaction would be implemented, so that all properties would be remembered or restored.
Tell me, please, where to dig and how to implement?
Answer the question
In order to leave comments, you need to log in
As far as I understand you are using Qt. In this case, do not cycle doc.qt.io/qt-5/qtwidgets-tools-undoframework-examp...
Put in the array not all the members of the object, but the object itself. And here an array is not needed, a stack is ideal here.
Here I gave you an example https://ideone.com/tOXA0S
#include <iostream>
#include <stack>
#include <memory>
template<typename T>
class Undo : public T {
private:
std::shared_ptr<std::stack<Undo>> history_ptr = std::make_shared<std::stack<Undo>>();
public:
template <typename... Args>
explicit Undo(const Args&... args): T(args ...) {}
void save() {
history_ptr->push(*this);
}
void undo() {
if (!history_ptr->empty()) {
*this = history_ptr->top();
history_ptr->pop();
}
}
};
class Foo {
public:
int a = 0;
std::string s;
Foo(const int _a, std::string _s): a(_a), s(std::move(_s)) {}
};
std::ostream &operator<<(std::ostream &out, const Foo &foo) {
out << "Foo(" << foo.a << ", \"" << foo.s << "\")";
return out;
}
int main() {
Undo<Foo> foo(1, "Hello World!");
foo.save();
std::cout << "Save\t" << foo << std::endl;
foo.a = 6661313;
foo.save();
std::cout << "Save\t" << foo << std::endl;
foo.s = "Lakad Matataaag!";
foo.save();
std::cout << "Save\t" << foo << std::endl;
foo.a = 9000;
foo.s = "Normalin, Normalin!";
foo.save();
std::cout << "Save\t" << foo << std::endl;
foo.a = 12345678;
foo.s = "Da next lebel play!";
std::cout << "Current\t" << foo << std::endl;
foo.undo();
std::cout << "Undo\t" << foo << std::endl;
foo.undo();
std::cout << "Undo\t" << foo << std::endl;
foo.undo();
std::cout << "Undo\t" << foo << std::endl;
foo.undo();
std::cout << "Undo\t" << foo << std::endl;
return 0;
}
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question