Tue, 28 Sep 2021 23:07:23 +0300
Use QSaveFile to save the file more safely
136 | 1 | /* |
2 | * LDForge: LDraw parts authoring CAD | |
3 | * Copyright (C) 2013 - 2020 Teemu Piippo | |
4 | * | |
5 | * This program is free software: you can redistribute it and/or modify | |
6 | * it under the terms of the GNU General Public License as published by | |
7 | * the Free Software Foundation, either version 3 of the License, or | |
8 | * (at your option) any later version. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License | |
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
17 | */ | |
18 | ||
133 | 19 | #pragma once |
20 | #include "main.h" | |
21 | #include "model.h" | |
22 | ||
23 | class AbstractHistoryEntry | |
24 | { | |
25 | public: | |
26 | virtual void undo(Model::EditContext& editContext) = 0; | |
27 | virtual void redo(Model::EditContext& editContext) = 0; | |
28 | }; | |
29 | ||
30 | class InsertHistoryEntry : public AbstractHistoryEntry | |
31 | { | |
32 | public: | |
136 | 33 | InsertHistoryEntry(int position, const QByteArray& state) : |
133 | 34 | position{position}, |
136 | 35 | state{state} {} |
133 | 36 | void undo(Model::EditContext& editContext) override; |
37 | void redo(Model::EditContext& editContext) override; | |
38 | protected: | |
39 | int position; | |
136 | 40 | QByteArray state; |
133 | 41 | }; |
42 | ||
43 | class DeleteHistoryEntry : public InsertHistoryEntry | |
44 | { | |
45 | public: | |
46 | void undo(Model::EditContext& editContext) override; | |
47 | void redo(Model::EditContext& editContext) override; | |
48 | }; | |
49 | ||
50 | class EditHistoryEntry : public AbstractHistoryEntry | |
51 | { | |
52 | public: | |
136 | 53 | EditHistoryEntry(int position, const QByteArray& stateBefore, const QByteArray& stateAfter) : |
133 | 54 | position{position}, |
136 | 55 | stateBefore{stateBefore}, |
56 | stateAfter{stateAfter} {} | |
133 | 57 | void undo(Model::EditContext& editContext) override; |
58 | void redo(Model::EditContext& editContext) override; | |
59 | private: | |
60 | int position; | |
136 | 61 | QByteArray stateBefore; |
62 | QByteArray stateAfter; | |
133 | 63 | }; |
64 | ||
65 | class EditHistory | |
66 | { | |
67 | public: | |
136 | 68 | using Changeset = std::vector<std::unique_ptr<AbstractHistoryEntry>>; |
133 | 69 | EditHistory(); |
136 | 70 | /** |
71 | * @brief Adds a new entry into the edit history. Creates a new changeset if there is not one already open. | |
72 | * If behind in history, deletes all history entries in front. | |
73 | */ | |
74 | template<typename T, typename... Rs> | |
75 | void add(Rs&&... args) | |
76 | { | |
77 | if (not this->changesetOpen) | |
78 | { | |
79 | while (this->position < this->changesets.size()) | |
80 | { | |
81 | this->changesets.erase(this->changesets.end() - 1); | |
82 | } | |
83 | if (this->changesets.empty()) | |
84 | { | |
85 | this->changesets.emplace_back(); | |
86 | } | |
87 | this->changesetOpen = true; | |
88 | } | |
89 | this->changesets.back().emplace_back(args...); | |
90 | } | |
91 | void commit() | |
92 | { | |
93 | this->changesetOpen = false; | |
94 | this->position += 1; | |
95 | } | |
96 | private: | |
97 | std::vector<Changeset> changesets; | |
98 | std::size_t position = 0; | |
99 | bool changesetOpen = false; | |
133 | 100 | }; |