Subversion Repositories Scribus

Rev

Rev 1247 | Rev 1252 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1111 tsoots 1
/***************************************************************************
2
 *   Copyright (C) 2005 by Riku Leino                                      *
3
 *   tsoots@gmail.com                                                      *
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 2 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, write to the                         *
17
 *   Free Software Foundation, Inc.,                                       *
18
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19
 ***************************************************************************/
20
 
21
#ifndef UNDOMANAGER_H
22
#define UNDOMANAGER_H
23
 
24
#include <vector>
25
#include <utility>
26
#include <qobject.h>
27
#include <qpixmap.h>
1190 tsoots 28
#include <qstring.h>
1111 tsoots 29
#include "undostate.h"
30
#include "undoobject.h"
31
 
1142 tsoots 32
class UndoGui;
1197 tsoots 33
class PrefsContext;
1142 tsoots 34
 
1111 tsoots 35
typedef std::pair<UndoObject*, UndoState*> ActionPair;
36
typedef std::vector<ActionPair> ActionList;
37
typedef std::pair<ActionList::iterator, ActionList> StackPair;
38
typedef QMap<QString, StackPair> StackMap;
39
 
40
/**
41
 * @brief UndoManager handles the undo stack.
42
 *
43
 * UndoManager is the engine of the undo/redo handling. When ever an undoable
44
 * action happens an UndoState object will be sent to the UndoManager which then
45
 * stores the state in the undo stack. When an undo is requested the state is
46
 * send back to it's creator which is then responsible for doing the actual undo or
47
 * redo.
48
 *
49
 * UndoManager also handles the UndoGuis by linking them together and reporting
50
 * all undo/redo actions to the guis for them to update the visual representation.
51
 * For this to work all UndoGuis need to be registered to the UndoManager with the
52
 * registerGui() method.
53
 *
54
 * @author Riku Leino tsoots@gmail.com
55
 * @date December 2004
56
 */
57
class UndoManager : public QObject
58
{
59
        Q_OBJECT
60
 
61
private:
1213 tsoots 62
 
63
/*** UndoManager::TransactionState ***************************************************/
64
 
65
        /**
66
         * @brief TransactionState provides a container where multiple actions can be stored
67
         * @brief as a single action which then appears in the attached <code>UndoGui</code>s.
68
         * @author Riku Leino tsoots@gmail.com
69
         * @date January 2005
70
         */
71
        class TransactionState : public UndoState
72
        {
73
        private:
74
                /** @brief Number of undo states stored in this transaction */
75
                uint _size;
76
                /** @brief vector to keep the states in */
77
                std::vector<ActionPair*> states;
78
        public:
79
                /** @brief Creates a new TransactionState instance */
80
                TransactionState();
81
                /** @brief Destroys the TransactionState instance */
82
                ~TransactionState();
83
                /**
84
                 * @brief Add a new <code>UndoState</code> object to the transaction.
85
                 * @param state state to be added to the transaction
86
                 */
87
                void pushBack(UndoObject *target, UndoState *state);
88
                /**
89
                 * @brief Returns the count of the <code>UndoState</code> objects in this transaction.
90
                 * @return count of the <code>UndoState</code> objects in this transaction
91
                 */
92
                uint sizet();
1226 tsoots 93
                /** @brief Use the name from last action added to this <code>TransactionState</code> */
94
                void useActionName();
1213 tsoots 95
                /**
96
                 * @brief Returns an <code>UndoState</code> object at <code>index</code>.
97
                 * @param index index from where an <code>UndoState</code> object is returned.
98
                 * If <code>index</code> is out of scope <code>NULL</code> will be rerturned.
99
                 * @return <code>UndoState</code> object from <code>index</code> or <code>NULL</code>
100
                 * if <code>index</code> is out of scope.
101
                 */
102
                ActionPair* at(int index);
1238 tsoots 103
                /**
104
                 * @brief Replace object with id uid with new UndoObject newUndoObject.
105
                 * @param uid id of the object that is wanted to be replaced
106
                 * @param newUndoObject object that is used for replacing
107
                 */
108
                void replace(ulong uid, UndoObject *newUndoObject);
1213 tsoots 109
        };
110
 
111
/*** UndoManager::TransactionObject ***************************************************/
112
 
113
        /**
114
         * @brief Dummy subclass of <code>UndoObject</code> which is used for holding the name
115
         * @brief for the transaction's target object(group) (f.e "Selection", "Group", "Script"...).
116
         * @author Riku Leino tsoots@gmail.com
117
         * @date January 2005
118
         */
119
        class TransactionObject : public UndoObject
120
        {
121
        public:
122
                TransactionObject() {};
1226 tsoots 123
                virtual ~TransactionObject() {};
1213 tsoots 124
                void restore(UndoState*, bool) {};
125
        };
126
 
127
/**************************************************************************************/
128
 
1111 tsoots 129
        /**
130
         * @brief The only instance of UndoManager available.
131
         *
132
         * UndoManager is singleton and the instance can be queried with the method
133
         * instance().
134
         */
135
        static UndoManager* _instance;
136
 
137
        /** @brief Should undo states be stored or ignored */
138
        static bool _undoEnabled;
139
 
1197 tsoots 140
        PrefsContext *prefs;
141
 
1111 tsoots 142
        /** @brief Doc to which the currently active stack belongs */
143
        QString currentDoc;
144
 
145
        /**
146
         * @brief Id number of the object for what the object specific undo is shown
147
         * @brief or -1 if global undo is used.
148
         */
149
        int currentUndoObjectId;
150
 
1213 tsoots 151
        /**
1238 tsoots 152
         * @brief Stores the transactions which are currently started but not
153
         * @brief canceled or commited.
154
         */
155
        std::vector<std::pair<TransactionObject*, TransactionState*> > transactions;
156
 
157
        /**
1213 tsoots 158
         * @brief If in transaction mode this is the container for incoming <code>UndoState</code>
159
         * @brief objects.
160
         *
161
         * It is also used to detect if we are in the transaction mode. When it is <code>NULL</code>
162
         * normal mode is on.
163
         */
164
        TransactionState *transaction;
165
 
166
        /** @brief Dummy object for storing transaction target's name */
167
        TransactionObject *transactionTarget;
168
 
1111 tsoots 169
        /**
170
         * @brief UndoGuis attached to this UndoManager
171
         * @sa UndoGui
172
         * @sa UndoWidget
173
         * @sa UndoPalette
174
         */
175
        std::vector<UndoGui*> undoGuis;
176
 
177
        /** @brief Undo stacks for all open documents */
178
        StackMap stacks;
179
 
180
        /** @brief Maximum length of the undo stack */
181
        int historyLength;
182
 
183
        /**
184
         * @brief Initializes the UndoGui.
185
         * @param gui UndoGui to be initialized
186
         * @param uid UndoObject's id if in object specific mode or -1 to tell
187
         * that global undo is used.
188
         */
189
        void setState(UndoGui* gui, int uid = -1);
190
 
191
        void connectGuis();
192
        void disconnectGuis();
1190 tsoots 193
        void initIcons();
1197 tsoots 194
        void checkStackLength();
1213 tsoots 195
        void doTransactionUndo(TransactionState *tstate);
196
        void doTransactionRedo(TransactionState *tstate);
1111 tsoots 197
 
198
public:
199
        /**
200
         * @brief Returns a pointer to the UndoManager instance
201
         * @return A pointer to the UndoManager instance
202
         */
203
        static UndoManager* instance();
204
 
205
        /**
206
         * @brief Deletes the UndoManager Instance
207
         *
208
         * Must be called when UndoManager is no more needed.
209
         */
210
        static void deleteInstance();
211
 
212
        /**
213
         * @brief Sets the undo action tracking enabled or disabled.
214
         * @param isEnabled If true undo stack is updated with the states sent
215
         * to the UndoManager else undo stack is not updated and attached UndoGuis
216
         * are not informed of the actions.
217
         */
218
        void setUndoEnabled(bool isEnabled);
219
 
220
        /**
221
         * @brief Returns true if undo actions are stored, if not will return false.
222
         * @return true if undo actions are stored, if not will return false
223
         */
224
        static bool undoEnabled();
225
 
226
        /**
1213 tsoots 227
         * @brief Start a transaction.
228
         *
229
         * After this method has been invoked <code>UndoManager</code> will switch to the
230
     * transaction (silent) mode where it does not report actions to the attached
231
         * <UndoGui> widgets but stores all incoming <code>UndoState</code> objects into
232
         * the transaction container which after call to the method commit() will be sent
233
         * to the guis as a single undo action. Transaction can be named when starting it or
234
         * naming can be done when commiting it.
235
         * @param targetName name for the target of this transaction (f.e. "Selection")
1250 tsoots 236
         * @param targetPixmap pixmap for the target on which this transaction works
1213 tsoots 237
         * @param name name for the transaction (f.e. "Move" would make with the above
238
         * "Move Selection")
239
         * @param description description for the transaction
1250 tsoots 240
         * @param actionPixmap icon for the action performed by the transaction
1213 tsoots 241
         * @sa commit()
242
         */
243
        void beginTransaction(const QString &targetName = "",
1250 tsoots 244
                          QPixmap *targetPixmap = 0,
245
                          const QString &actionName = "",
1213 tsoots 246
                          const QString &description = "",
1250 tsoots 247
                          QPixmap *actionPixmap = 0);
1213 tsoots 248
 
249
        /**
250
         * @brief Cancels the current transaction and deletes groupped <code>UndoState</code>s.
251
         * @brief Nothing from canceled transaction will be sent to the undo gui widgets.
252
         */
253
        void cancelTransaction();
254
 
255
        /**
256
         * @brief Commit the current transaction.
257
         *
258
         * Current transaction will be commited and <code>UndoManager</code> will be switched
259
         * to the normal mode. Commited transaction will be sent to the attached undo gui
260
         * widgets and it will show up there as a single undo action. Details used as a parameter
261
         * will be details shown in the gui widgets.
262
         * @param targetName name for the target of this transaction (f.e. "Selection")
1250 tsoots 263
         * @param targetPixmap pixmap for the target on which this transaction works
1213 tsoots 264
         * @param name name for the action
265
         * @param description description for the action
1250 tsoots 266
         * @param actionPixmap icon for the action performed by the transaction
1213 tsoots 267
         * @sa beginTransaction()
268
         */
269
        void commit(const QString &targetName = "",
1250 tsoots 270
                QPixmap *targetPixmap = 0,
1213 tsoots 271
                const QString &name = "",
272
                const QString &description = "",
1250 tsoots 273
                QPixmap *actionPixmap = 0);
1213 tsoots 274
 
275
        /**
276
         * @brief Returns true if in transaction mode if not will return false.
277
         * @return true if in transaction mode if not will return false
278
         */
279
        bool isTransactionMode();
280
 
281
        /**
1111 tsoots 282
         * @brief Register an UndoGui to the UndoManager.
283
         *
284
         * After registering a gui to the manager the gui will be updated with the
285
         * undo action information received by the UndoManager. Actions done with the
286
         * UndoGui to be registered are also handled after registering.
287
         * @param gui A pointer to the UndoGui that is wanted to be registered.
288
         */
289
        void registerGui(UndoGui* gui);
290
 
291
        /**
292
         * @brief Removes an UndoGui from UndoManager.
293
         * @param gui UndoGui to be removed from the UndoManager.
294
         */
295
        void removeGui(UndoGui* gui);
296
 
297
        /**
298
         * @brief Changes the active undo stack.
299
         *
300
         * Sets the stack connected to the name <code>stackName</code> active. Calling
301
         * this method will send clear() signal to the attached <code>UndoGui</code>s and
302
         * will update their undo stack representations.
303
         * @param stackName Name of the stack to be used
304
         */
305
        void switchStack(const QString& stackName);
306
 
307
        /**
308
         * @brief Rename the current stack
309
         * @param newName New name for the current stack.
310
         */
311
        void rename(const QString& newName);
312
 
313
        /**
314
         * @brief Remove the stack with the name <code>stackName</code>
315
         * @param stackName Name of the stack that is wanted to be removed
316
         */
317
        void remove(const QString& stackName);
318
 
319
        /**
320
         * @brief Returns true if there are actions that can be undone otherwise returns false.
321
         *
322
         * This is useful when undo/redo actions are handled with a gui that is not attached to
323
         * the UndoManager (f.e. menu items) and when those gui items are wanted to set enabled
324
         * or disabled depending on the status of the undo stack.
325
         * @return true if there are actions that can be undone otherwise returns false
326
         */
327
        bool hasUndoActions();
328
 
329
        /**
330
         * @brief Returns true if there are actions that can be redone otherwise returns false.
331
         * @return true if there are actions that can be redone otherwise returns false
332
         * @sa UndoManager::hasUndoActions()
333
         */
334
        bool hasRedoActions();
335
 
336
        /**
337
         * @brief Switches the state of UndoManager (global/object specific undo).
338
         *
339
         * If parameter uid is less than 0 global undo is used else the undo state
340
         * is object specific using the object whose uid is given as a parameter.
341
         * @param uid UndoObject's id for what the object specific undo is wanted or
342
         * -1 if global undo is wanted.
343
         */
344
        void showObject(int uid);
345
 
346
        /**
1238 tsoots 347
         * @brief Replace an UndoObject with the id uid with a new UndoObject new.
348
         * @param uid Id for the UndoObject that is wanted to be replaced.
349
         * @param newUndoObject UndoObject which will replace an old UndoObject in the stack.
350
         */
351
        void replace(ulong uid, UndoObject *newUndoObject);
352
 
353
        /**
1111 tsoots 354
         * @brief Returns the maximum length of the undostack.
355
         * @return the maximum length of the undostack
356
         */
357
        int getHistoryLength();
358
 
1199 tsoots 359
        /**
1190 tsoots 360
        * @name Action strings
361
        * Strings describing undo actions
362
        */
363
        /*@{*/
364
        static const QString AddVGuide;
365
        static const QString AddHGuide;
366
        static const QString DelVGuide;
367
        static const QString DelHGuide;
368
        static const QString MoveVGuide;
369
        static const QString MoveHGuide;
370
        static const QString LockGuides;
371
        static const QString UnlockGuides;
1204 tsoots 372
        static const QString Move;
1206 tsoots 373
        static const QString Resize;
1211 tsoots 374
        static const QString Rotate;
375
        static const QString MoveFromTo;
376
        static const QString ResizeFromTo;
377
        static const QString RotateFromTo;
1226 tsoots 378
        static const QString Selection;
379
        static const QString Group;
1238 tsoots 380
        static const QString Create;
381
        static const QString CreateTo;
1247 tsoots 382
        static const QString AlignDistribute;
383
        static const QString ItemsInvolved;
384
        static const QString Cancel;
1190 tsoots 385
        /*@}*/
1204 tsoots 386
 
1190 tsoots 387
        /**
388
         * @name Action icons
389
         * Icons for undo actions
390
         */
391
        /*@{*/
1250 tsoots 392
/*** Icons for UndoObjects *******************************************/
393
        static QPixmap *IImageFrame;
394
        static QPixmap *ITextFrame;
395
        static QPixmap *ILine;
396
        static QPixmap *IPolygon;
397
        static QPixmap *IPolyline;
398
        static QPixmap *IPathText;
399
/*** Icons for actions ***********************************************/
400
        static QPixmap *IMove;
401
        static QPixmap *IResize;
402
        static QPixmap *IRotate;
1190 tsoots 403
        static QPixmap *IGuides;
404
        static QPixmap *ILockGuides;
1247 tsoots 405
        static QPixmap *IAlignDistribute;
1190 tsoots 406
        /*@}*/
407
 
1111 tsoots 408
protected:
409
        /** @brief Creates a new UndoManager instance */
410
        UndoManager();
411
 
412
        /** @brief Destroys the UndoManager instance */
413
        ~UndoManager();
414
 
415
private slots:
416
        /**
417
         * @brief Take undo steps the given amount
418
         *
419
         * When an UndoGui is registered to the UndoManager gui's undo() signal
420
         * is connected to this slot. Emitting an undo() signal will make the
421
         * UndoManager perform undo actions the given number of steps.
422
         * @param steps Number of undo actions to make
423
         */
424
        void doUndo(int steps);
425
 
426
        /**
427
         * @brief Take redo steps the given amount
428
         * @param steps Number of redo actions to make
429
         * @sa UndoManager::doUndo(int steps)
430
         */
431
        void doRedo(int steps);
432
 
433
public slots:
434
        /**
435
         * @brief Adds a new action to the undo stack.
436
         *
437
         * If _unodEnabled is true the action will be stored otherwise it will
438
         * be just ignored. When a new action is added redo items from the stack
439
         * will be removed and the current action will be set to the one which was
440
         * added.
441
         * @param target Source of the action. When undoing/redoing this action
442
         * restore() method of this UndoObject will be called.
443
         * @param state UndoSate describing the state (action).
444
         */
445
        void action(UndoObject* target, UndoState* state);
446
 
447
        /**
448
         * @brief Informs UndoManager to perform undo
449
         *
450
         * If an undo is wanted and the caller is not registered UndoGui this method
451
         * can be used. Useful for example with the menu entry for undo.
452
         * @param steps Number of undo steps to take
453
         */
454
        void undo(int steps);
455
 
456
        /**
457
         * @brief Informs UndoManager to perform redo
458
         * @param steps Number of redo steps to take
459
         * @sa UndoManager::undo(int steps)
460
         */
461
        void redo(int steps);
462
 
1197 tsoots 463
        /**
464
         * @brief Sets the length of the undo stack.
465
         *
466
         * Tells how many UndoStates are stored.
467
         * @param steps number of UndoStates to store in the undo stack
468
         */
469
        void setHistoryLength(int steps);
470
 
1111 tsoots 471
signals:
472
        /**
473
         * @brief Emitted when a new undo action is stored to the undo stack.
474
         *
475
         * This signal is connected to the registered UndoGuis for them to update the
476
         * visual representation of the undo stack.
477
         * @param target Source of the action
478
         * @param state UndoState describing the action
479
         */
480
        void newAction(UndoObject* target, UndoState* state);
481
 
482
        /**
483
         * @brief Emitted when an undo action has been done.
484
         *
485
         * It is connected to attached guis to inform them to update the visual
1190 tsoots 486
         * representation of the undo stack. This signal will be also sent to the
487
         * <code>UndoGui</code> where it came from.
1111 tsoots 488
         * @param steps Number of steps to take
489
         */
490
        void undoSignal(int steps);
491
 
492
        /**
493
         * @brief Emitted when a redo action has been done.
494
         * @param steps Number of steps to take
495
         * @sa UndoManager::undoSignal(int steps)
496
         */
497
        void redoSignal(int steps);
498
 
499
        /**
500
         * @brief This signal is used to notify registered UndoGui instances that
501
         * @brief history limit is reached and the last item from the stack
502
         * @brief representation should be removed.
503
         */
504
        void popBack();
505
 
506
        /**
507
         * @brief This signal is emitted when all requested undo/redo actions have been done.
508
         *
509
         * It could be used in the application as a signal when the view can be rendered
510
         * again after undo/redo.
511
         */
512
        void undoRedoDone();
1190 tsoots 513
 
1111 tsoots 514
};
515
 
1190 tsoots 516
typedef UndoManager Um;
517
 
1111 tsoots 518
#endif