1/* This file is part of the KDE project
2 Copyright (C) 2000 Werner Trobin <trobin@kde.org>
3 Copyright (C) 2000,2006 David Faure <faure@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library 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 GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21#ifndef kcommand_h
22#define kcommand_h
23
24#include <kde3support_export.h>
25
26#include <QtCore/QList>
27#include <QtCore/QString>
28#include <QtCore/QObject>
29
30class KAction;
31class KActionCollection;
32class QAction;
33
34/**
35 * The abstract base class for all Commands. Commands are used to
36 * store information needed for Undo/Redo functionality...
37 *
38 * Note: you might want to use the QUndo framework instead.
39 * It didn't exist when K3Command was written.
40 */
41class KDE3SUPPORT_EXPORT K3Command
42{
43protected:
44 /**
45 * Creates a command.
46 */
47 K3Command();
48
49public:
50 virtual ~K3Command();
51
52 /**
53 * The main method: executes this command.
54 * Implement here what this command is about, and remember to
55 * record any information that will be helpful for #unexecute.
56 */
57 virtual void execute() = 0;
58 /**
59 * Unexecutes (undo) this command.
60 * Implement here the steps to take for undoing the command.
61 * If your application uses actions for everything (it should),
62 * and if you implement unexecute correctly, the application is in the same
63 * state after unexecute as it was before execute. This means, the next
64 * call to execute will do the same thing as it did the first time.
65 */
66 virtual void unexecute() = 0;
67
68 /**
69 * @return the name of this command, translated, since it will appear
70 * in the menus.
71 */
72 virtual QString name() const = 0;
73protected:
74 virtual void virtual_hook( int id, void* data );
75private:
76 class Private;
77 Private* const d;
78 Q_DISABLE_COPY( K3Command )
79};
80
81/**
82 * A command which stores its name.
83 * It is more memory-efficient to use K3Command and to implement the name() method,
84 * but in some cases it's more simple or more flexible to store the name at creation time.
85 *
86 * Note: you might want to use the QUndo framework instead.
87 * It didn't exist when K3Command was written.
88 */
89class KDE3SUPPORT_EXPORT K3NamedCommand : public K3Command
90{
91protected:
92 /**
93 * Creates a command.
94 * @param name the name of this command, translated, since it will appear
95 * in the menus.
96 */
97 K3NamedCommand( const QString &name );
98
99public:
100 /**
101 * @return the name of this command
102 */
103 virtual QString name() const;
104 /**
105 * Updates the name of this command.
106 * Rarely necessary.
107 */
108 void setName( const QString &name );
109
110 virtual ~K3NamedCommand();
111
112protected:
113 virtual void virtual_hook( int id, void* data );
114
115private:
116 class Private;
117 Private* const d;
118 Q_DISABLE_COPY( K3NamedCommand )
119};
120
121/**
122 * A Macro Command is a command that holds several sub-commands.
123 * It will appear as one to the user and in the command history,
124 * but it can use the implementation of multiple commands internally.
125 */
126class KDE3SUPPORT_EXPORT K3MacroCommand : public K3NamedCommand
127{
128public:
129 /**
130 * Creates a macro command. You will then need to call addCommand
131 * for each subcommand to be added to this macro command.
132 * @param name the name of this command, translated, since it will appear
133 * in the menus.
134 */
135 K3MacroCommand( const QString & name );
136 virtual ~K3MacroCommand();
137
138 /**
139 * Appends a command to this macro command.
140 * The ownership is transferred to the macro command.
141 */
142 void addCommand(K3Command *command);
143
144 /**
145 * Executes this command, i.e. execute all the sub-commands
146 * in the order in which they were added.
147 */
148 virtual void execute();
149 /**
150 * Undoes the execution of this command, i.e. #unexecute all the sub-commands
151 * in the _reverse_ order to the one in which they were added.
152 */
153 virtual void unexecute();
154
155protected:
156 const QList<K3Command *> commands() const;
157
158 virtual void virtual_hook( int id, void* data );
159
160private:
161 class Private;
162 Private* const d;
163 Q_DISABLE_COPY( K3MacroCommand )
164};
165
166
167/**
168 * The command history stores a (user) configurable amount of
169 * Commands. It keeps track of its size and deletes commands
170 * if it gets too large. The user can set a maximum undo and
171 * a maximum redo limit (e.g. max. 50 undo / 30 redo commands).
172 * The K3CommandHistory keeps track of the "borders" and deletes
173 * commands, if appropriate. It also activates/deactivates the
174 * undo/redo actions in the menu and changes the text according
175 * to the name of the command.
176 *
177 * Note: you might want to use the QUndo framework instead.
178 * It didn't exist when K3Command was written.
179 */
180class KDE3SUPPORT_EXPORT K3CommandHistory : public QObject {
181 Q_OBJECT
182public:
183 /**
184 * Creates a command history, to store commands.
185 * This constructor doesn't create actions, so you need to call
186 * #undo and #redo yourself.
187 */
188 K3CommandHistory();
189
190 /**
191 * Creates a command history, to store commands.
192 * This also creates an undo and a redo action, in the @p actionCollection,
193 * using the standard names ("edit_undo" and "edit_redo").
194 * @param withMenus if true, the actions will display a menu when plugged
195 * into a toolbar.
196 * @param actionCollection the parent collection
197 */
198 K3CommandHistory(KActionCollection *actionCollection, bool withMenus = true);
199
200 /**
201 * Destructs the command history object.
202 */
203 virtual ~K3CommandHistory();
204
205 /**
206 * Erases all the undo/redo history.
207 * Use this when reloading the data, for instance, since this invalidates
208 * all the commands.
209 */
210 void clear();
211
212 /**
213 * Adds a command to the history. Call this for each @p command you create.
214 * Unless you set @p execute to false, this will also execute the command.
215 * This means, most of the application's code will look like
216 * MyCommand * cmd = new MyCommand( parameters );
217 * m_historyCommand.addCommand( cmd );
218 *
219 * Note that the command history takes ownership of the command, it will delete
220 * it when the undo limit is reached, or when deleting the command history itself.
221 */
222 void addCommand(K3Command *command, bool execute=true);
223
224 /**
225 * @return the maximum number of items in the undo history
226 */
227 int undoLimit() const;
228 /**
229 * Sets the maximum number of items in the undo history.
230 */
231 void setUndoLimit(int limit);
232 /**
233 * @return the maximum number of items in the redo history
234 */
235 int redoLimit() const;
236 /**
237 * Sets the maximum number of items in the redo history.
238 */
239 void setRedoLimit(int limit);
240
241 /**
242 * Enable or disable the undo and redo actions.
243 * This isn't usually necessary, but this method can be useful if
244 * you disable all actions (to go to a "readonly" state), and then
245 * want to come back to a readwrite mode.
246 */
247 void updateActions();
248
249 /**
250 * @return the present command, i.e. the one that undo() would unexecute.
251 * This can be used to e.g. show selection.
252 */
253 K3Command * presentCommand() const;
254
255 /**
256 * @return true if undo is available,
257 * i.e. there is at least one command that can be undone right now
258 */
259 bool isUndoAvailable() const;
260
261 /**
262 * @return true if redo is available
263 * i.e. there is at least one command that can be redone right now
264 */
265 bool isRedoAvailable() const;
266
267 /**
268 * @return the list of next @p maxCommands actions that will be undone by undo()
269 * The returned list is empty if !isUndoAvailable().
270 * Otherwise the list starts with the next command to undo,
271 * i.e. the order of the commands in the list is the reverse of the
272 * chronological order of the commands.
273 * @param maxCommands maximum number of commands requested. 0 means no maximum,
274 * all stored undo commands (within undoLimit()) are returned.
275 */
276 QList<K3Command *> undoCommands( int maxCommands = 0 ) const;
277
278 /**
279 * @return the list of next @p maxCommands actions that will be redone by redo()
280 * The returned list is empty if !isRedoAvailable().
281 * Otherwise the list starts with the next command to redo.
282 * @param maxCommands maximum number of commands requested. 0 means no maximum,
283 * all stored redo commands (within redoLimit()) are returned.
284 */
285 QList<K3Command *> redoCommands( int maxCommands = 0 ) const;
286
287public Q_SLOTS:
288 /**
289 * Undoes the last action.
290 * Call this if you don't use the builtin KActions.
291 */
292 virtual void undo();
293 /**
294 * Redoes the last undone action.
295 * Call this if you don't use the builtin KActions.
296 */
297 virtual void redo();
298 /**
299 * Remembers when you saved the document.
300 * Call this right after saving the document. As soon as
301 * the history reaches the current index again (via some
302 * undo/redo operations) it will emit documentRestored
303 * If you implemented undo/redo properly the document is
304 * the same you saved before.
305 */
306 virtual void documentSaved();
307
308Q_SIGNALS:
309 /**
310 * Emitted every time a command is executed
311 * (whether by addCommand, undo or redo).
312 * You can use this to update the GUI, for instance.
313 * @param command was executed
314 */
315 void commandExecuted(K3Command *command);
316
317 /**
318 * Emitted every time we reach the index where you
319 * saved the document for the last time. See documentSaved
320 */
321 void documentRestored();
322
323 /**
324 * Emitted whenever the command history has changed,
325 * i.e. after addCommand, undo or redo.
326 * This is used by the actions to update themselves.
327 */
328 void commandHistoryChanged();
329
330private:
331 void clipCommands(); // ensures that the limits are kept
332
333private:
334 class K3CommandHistoryPrivate;
335 K3CommandHistoryPrivate * const d;
336 Q_DISABLE_COPY( K3CommandHistory )
337};
338
339#include <ktoolbarpopupaction.h>
340
341/**
342 * This type of action is used to show undo or redo actions in the menu or in the
343 * toolbars.
344 * This action will keep itself up to date and change the text based on the undo
345 * history, plus it will disable itself when there is nothing to undo/redo.
346 * You will typically need two instances of this action per view (e.g. the mainwindow).
347 * @code
348 new KUndoRedoAction( KUndoRedoAction::Undo, view->actionCollection(), m_history );
349 new KUndoRedoAction( KUndoRedoAction::Redo, view->actionCollection(), m_history );
350 @endcode
351 * Note that there is no need to connect or even keep a reference to the object as
352 * all work is done automatically.
353 *
354 * Note: you might want to use the QUndo framework instead.
355 * It didn't exist when K3Command was written.
356 */
357class K3UndoRedoAction : public KToolBarPopupAction
358{
359 Q_OBJECT
360public:
361 enum Type { Undo, Redo };
362 K3UndoRedoAction( Type type, KActionCollection* actionCollection, K3CommandHistory* commandHistory );
363
364private Q_SLOTS:
365 void slotAboutToShow();
366 void slotActionTriggered( QAction *action );
367 void slotCommandHistoryChanged();
368
369private:
370 class Private;
371 Private* const d;
372 Q_DISABLE_COPY( K3UndoRedoAction )
373};
374
375#endif
376