1 #ifndef CSM_WOLRD_COMMANDS_H
2 #define CSM_WOLRD_COMMANDS_H
3 
4 #include "record.hpp"
5 
6 #include <string>
7 #include <map>
8 #include <memory>
9 #include <vector>
10 
11 #include <QVariant>
12 #include <QUndoCommand>
13 #include <QModelIndex>
14 
15 #include "columnimp.hpp"
16 #include "universalid.hpp"
17 #include "nestedtablewrapper.hpp"
18 
19 class QModelIndex;
20 class QAbstractItemModel;
21 
22 namespace CSMWorld
23 {
24     class IdTable;
25     class IdTree;
26     struct RecordBase;
27     struct NestedTableWrapperBase;
28 
29     class TouchCommand : public QUndoCommand
30     {
31         public:
32 
33             TouchCommand(IdTable& model, const std::string& id, QUndoCommand* parent=nullptr);
34 
35             void redo() override;
36             void undo() override;
37 
38         private:
39 
40             IdTable& mTable;
41             std::string mId;
42             std::unique_ptr<RecordBase> mOld;
43 
44             bool mChanged;
45     };
46 
47     /// \brief Adds LandTexture records and modifies texture indices as needed.
48     ///
49     /// LandTexture records are different from other types of records, because
50     /// they only effect the current plugin. Thus, when modifying or copying
51     /// a Land record, all of the LandTexture records referenced need to be
52     /// added to the current plugin. Since these newly added LandTextures could
53     /// have indices that conflict with pre-existing LandTextures in the current
54     /// plugin, the indices might have to be changed, both for the newly added
55     /// LandRecord and within the Land record.
56     class ImportLandTexturesCommand : public QUndoCommand
57     {
58         public:
59 
60             ImportLandTexturesCommand(IdTable& landTable, IdTable& ltexTable,
61                 QUndoCommand* parent);
62 
63             void redo() override;
64             void undo() override;
65 
66         protected:
67 
68             using DataType = LandTexturesColumn::DataType;
69 
70             virtual const std::string& getOriginId() const = 0;
71             virtual const std::string& getDestinationId() const = 0;
72 
73             virtual void onRedo() = 0;
74             virtual void onUndo() = 0;
75 
76             IdTable& mLands;
77             IdTable& mLtexs;
78             DataType mOld;
79             int mOldState;
80             std::vector<std::string> mCreatedTextures;
81     };
82 
83     /// \brief This command is used to fix LandTexture records and texture
84     ///     indices after cloning a Land. See ImportLandTexturesCommand for
85     ///     details.
86     class CopyLandTexturesCommand : public ImportLandTexturesCommand
87     {
88         public:
89 
90             CopyLandTexturesCommand(IdTable& landTable, IdTable& ltexTable, const std::string& origin,
91                 const std::string& dest, QUndoCommand* parent = nullptr);
92 
93         private:
94 
95             const std::string& getOriginId() const override;
96             const std::string& getDestinationId() const override;
97 
onRedo()98             void onRedo() override {}
onUndo()99             void onUndo() override {}
100 
101             std::string mOriginId;
102             std::string mDestId;
103     };
104 
105     /// \brief This command brings a land record into the current plugin, adding
106     ///     LandTexture records and modifying texture indices as needed.
107     /// \note See ImportLandTextures for more details.
108     class TouchLandCommand : public ImportLandTexturesCommand
109     {
110         public:
111 
112             TouchLandCommand(IdTable& landTable, IdTable& ltexTable,
113                 const std::string& id, QUndoCommand* parent = nullptr);
114 
115         private:
116 
117             const std::string& getOriginId() const override;
118             const std::string& getDestinationId() const override;
119 
120             void onRedo() override;
121             void onUndo() override;
122 
123             std::string mId;
124             std::unique_ptr<RecordBase> mOld;
125 
126             bool mChanged;
127     };
128 
129     class ModifyCommand : public QUndoCommand
130     {
131             QAbstractItemModel *mModel;
132             QModelIndex mIndex;
133             QVariant mNew;
134             QVariant mOld;
135 
136             bool mHasRecordState;
137             QModelIndex mRecordStateIndex;
138             CSMWorld::RecordBase::State mOldRecordState;
139 
140         public:
141 
142             ModifyCommand (QAbstractItemModel& model, const QModelIndex& index, const QVariant& new_,
143                 QUndoCommand *parent = nullptr);
144 
145             void redo() override;
146 
147             void undo() override;
148     };
149 
150     class CreateCommand : public QUndoCommand
151     {
152             std::map<int, QVariant> mValues;
153             std::map<int, std::pair<int, QVariant> > mNestedValues;
154             ///< Parameter order: a parent column, a nested column, a data.
155             ///< A nested row has index of 0.
156 
157         protected:
158 
159             IdTable& mModel;
160             std::string mId;
161             UniversalId::Type mType;
162 
163         protected:
164 
165             /// Apply modifications set via addValue.
166             void applyModifications();
167 
168         public:
169 
170             CreateCommand (IdTable& model, const std::string& id, QUndoCommand *parent = nullptr);
171 
172             void setType (UniversalId::Type type);
173 
174             void addValue (int column, const QVariant& value);
175 
176             void addNestedValue(int parentColumn, int nestedColumn, const QVariant &value);
177 
178             void redo() override;
179 
180             void undo() override;
181     };
182 
183     class CloneCommand : public CreateCommand
184     {
185             std::string mIdOrigin;
186             std::vector<std::pair<int, QVariant>> mOverrideValues;
187 
188         public:
189 
190             CloneCommand (IdTable& model, const std::string& idOrigin,
191                           const std::string& IdDestination,
192                           const UniversalId::Type type,
193                           QUndoCommand* parent = nullptr);
194 
195             void redo() override;
196 
197             void undo() override;
198 
199             void setOverrideValue(int column, QVariant value);
200     };
201 
202     class RevertCommand : public QUndoCommand
203     {
204             IdTable& mModel;
205             std::string mId;
206             RecordBase *mOld;
207 
208             // not implemented
209             RevertCommand (const RevertCommand&);
210             RevertCommand& operator= (const RevertCommand&);
211 
212         public:
213 
214             RevertCommand (IdTable& model, const std::string& id, QUndoCommand *parent = nullptr);
215 
216             virtual ~RevertCommand();
217 
218             void redo() override;
219 
220             void undo() override;
221     };
222 
223     class DeleteCommand : public QUndoCommand
224     {
225             IdTable& mModel;
226             std::string mId;
227             RecordBase *mOld;
228             UniversalId::Type mType;
229 
230             // not implemented
231             DeleteCommand (const DeleteCommand&);
232             DeleteCommand& operator= (const DeleteCommand&);
233 
234         public:
235 
236             DeleteCommand (IdTable& model, const std::string& id,
237                     UniversalId::Type type = UniversalId::Type_None, QUndoCommand *parent = nullptr);
238 
239             virtual ~DeleteCommand();
240 
241             void redo() override;
242 
243             void undo() override;
244     };
245 
246     class ReorderRowsCommand : public QUndoCommand
247     {
248             IdTable& mModel;
249             int mBaseIndex;
250             std::vector<int> mNewOrder;
251 
252         public:
253 
254             ReorderRowsCommand (IdTable& model, int baseIndex, const std::vector<int>& newOrder);
255 
256             void redo() override;
257 
258             void undo() override;
259     };
260 
261     class CreatePathgridCommand : public CreateCommand
262     {
263         public:
264 
265             CreatePathgridCommand(IdTable& model, const std::string& id, QUndoCommand *parent = nullptr);
266 
267             void redo() override;
268     };
269 
270     /// \brief Update cell ID according to x/y-coordinates
271     ///
272     /// \note The new value will be calculated in the first call to redo instead of the
273     /// constructor to accommodate multiple coordinate-affecting commands being executed
274     /// in a macro.
275     class UpdateCellCommand : public QUndoCommand
276     {
277             IdTable& mModel;
278             int mRow;
279             QModelIndex mIndex;
280             QVariant mNew; // invalid, if new cell ID has not been calculated yet
281             QVariant mOld;
282 
283         public:
284 
285             UpdateCellCommand (IdTable& model, int row, QUndoCommand *parent = nullptr);
286 
287             void redo() override;
288 
289             void undo() override;
290     };
291 
292 
293     class NestedTableStoring
294     {
295         NestedTableWrapperBase* mOld;
296 
297     public:
298         NestedTableStoring(const IdTree& model, const std::string& id, int parentColumn);
299 
300         ~NestedTableStoring();
301 
302     protected:
303 
304         const NestedTableWrapperBase& getOld() const;
305     };
306 
307     class DeleteNestedCommand : public QUndoCommand, private NestedTableStoring
308     {
309             IdTree& mModel;
310 
311             std::string mId;
312 
313             int mParentColumn;
314 
315             int mNestedRow;
316 
317             // The command to redo/undo the Modified status of a record
318             ModifyCommand *mModifyParentCommand;
319 
320         public:
321 
322             DeleteNestedCommand (IdTree& model, const std::string& id, int nestedRow, int parentColumn, QUndoCommand* parent = nullptr);
323 
324             void redo() override;
325 
326             void undo() override;
327     };
328 
329     class AddNestedCommand : public QUndoCommand, private NestedTableStoring
330     {
331             IdTree& mModel;
332 
333             std::string mId;
334 
335             int mNewRow;
336 
337             int mParentColumn;
338 
339             // The command to redo/undo the Modified status of a record
340             ModifyCommand *mModifyParentCommand;
341 
342         public:
343 
344             AddNestedCommand(IdTree& model, const std::string& id, int nestedRow, int parentColumn, QUndoCommand* parent = nullptr);
345 
346             void redo() override;
347 
348             void undo() override;
349     };
350 }
351 
352 #endif
353