Chris@376: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ Chris@376: Chris@376: /* Chris@376: Sonic Visualiser Chris@376: An audio file viewer and annotation editor. Chris@376: Centre for Digital Music, Queen Mary, University of London. Chris@376: Chris@376: This program is free software; you can redistribute it and/or Chris@376: modify it under the terms of the GNU General Public License as Chris@376: published by the Free Software Foundation; either version 2 of the Chris@376: License, or (at your option) any later version. See the file Chris@376: COPYING included with this distribution for more information. Chris@376: */ Chris@376: Chris@376: /* Chris@376: This is a modified version of a source file from the Rosegarden Chris@376: MIDI and audio sequencer and notation editor, copyright 2000-2006 Chris@376: Chris Cannam, distributed under the GNU General Public License. Chris@376: Chris@376: This file contains traces of the KCommandHistory class from the KDE Chris@376: project, copyright 2000 Werner Trobin and David Faure and Chris@376: distributed under the GNU Lesser General Public License. Chris@376: */ Chris@376: Chris@1407: #ifndef SV_MULTI_VIEW_COMMAND_HISTORY_H Chris@1407: #define SV_MULTI_VIEW_COMMAND_HISTORY_H Chris@376: Chris@376: #include Chris@376: #include Chris@376: Chris@376: #include Chris@376: #include Chris@376: #include Chris@376: Chris@376: class Command; Chris@376: class MacroCommand; Chris@376: class QAction; Chris@376: class QMenu; Chris@376: class QToolBar; Chris@376: class QTimer; Chris@376: Chris@376: /** Chris@376: * The CommandHistory class stores a list of executed commands and Chris@376: * maintains Undo and Redo actions synchronised with those commands. Chris@376: * Chris@376: * CommandHistory allows you to associate more than one Undo and Redo Chris@376: * menu or toolbar with the same command history, and it keeps them Chris@376: * all up-to-date at once. This makes it effective in systems where Chris@376: * multiple views may be editing the same data. Chris@376: */ Chris@376: Chris@376: class CommandHistory : public QObject Chris@376: { Chris@376: Q_OBJECT Chris@376: Chris@376: public: Chris@376: virtual ~CommandHistory(); Chris@376: Chris@376: static CommandHistory *getInstance(); Chris@376: Chris@376: void clear(); Chris@376: Chris@376: void registerMenu(QMenu *menu); Chris@376: void registerToolbar(QToolBar *toolbar); Chris@376: Chris@376: /** Chris@376: * Add a command to the command history. Chris@376: * Chris@376: * The command will normally be executed before being added; but Chris@376: * if a compound operation is in use (see startCompoundOperation Chris@376: * below), the execute status of the compound operation will Chris@376: * determine whether the command is executed or not. Chris@376: */ Chris@376: void addCommand(Command *command); Chris@376: Chris@376: /** Chris@376: * Add a command to the command history. Chris@376: * Chris@376: * If execute is true, the command will be executed before being Chris@376: * added. Otherwise it will be assumed to have been already Chris@376: * executed -- a command should not be added to the history unless Chris@376: * its work has actually been done somehow! Chris@376: * Chris@376: * If a compound operation is in use (see startCompoundOperation Chris@376: * below), the execute value passed to this method will override Chris@376: * the execute status of the compound operation. In this way it's Chris@376: * possible to have a compound operation mixing both to-execute Chris@376: * and pre-executed commands. Chris@376: * Chris@376: * If bundle is true, the command will be a candidate for bundling Chris@376: * with any adjacent bundleable commands that have the same name, Chris@376: * into a single compound command. This is useful for small Chris@376: * commands that may be executed repeatedly altering the same data Chris@376: * (e.g. type text, set a parameter) whose number and extent is Chris@376: * not known in advance. The bundle parameter will be ignored if Chris@376: * a compound operation is already in use. Chris@376: */ Chris@376: void addCommand(Command *command, bool execute, bool bundle = false); Chris@376: Chris@376: /// Return the maximum number of items in the undo history. Chris@376: int getUndoLimit() const { return m_undoLimit; } Chris@376: Chris@376: /// Set the maximum number of items in the undo history. Chris@376: void setUndoLimit(int limit); Chris@376: Chris@376: /// Return the maximum number of items in the redo history. Chris@376: int getRedoLimit() const { return m_redoLimit; } Chris@376: Chris@376: /// Set the maximum number of items in the redo history. Chris@376: void setRedoLimit(int limit); Chris@376: Chris@376: /// Return the maximum number of items visible in undo and redo menus. Chris@376: int getMenuLimit() const { return m_menuLimit; } Chris@376: Chris@376: /// Set the maximum number of items in the menus. Chris@376: void setMenuLimit(int limit); Chris@376: Chris@376: /// Return the time after which a bundle will be closed if nothing is added. Chris@376: int getBundleTimeout() const { return m_bundleTimeout; } Chris@376: Chris@376: /// Set the time after which a bundle will be closed if nothing is added. Chris@376: void setBundleTimeout(int msec); Chris@376: Chris@376: /// Start recording commands to batch up into a single compound command. Chris@376: void startCompoundOperation(QString name, bool execute); Chris@376: Chris@376: /// Finish recording commands and store the compound command. Chris@376: void endCompoundOperation(); Chris@376: Chris@376: public slots: Chris@376: /** Chris@376: * Checkpoint function that should be called when the document is Chris@376: * saved. If the undo/redo stack later returns to the point at Chris@376: * which the document was saved, the documentRestored signal will Chris@376: * be emitted. Chris@376: */ Chris@376: virtual void documentSaved(); Chris@376: Chris@376: /** Chris@376: * Add a command to the history that has already been executed, Chris@376: * without executing it again. Equivalent to addCommand(command, false). Chris@376: */ Chris@376: void addExecutedCommand(Command *); Chris@376: Chris@376: /** Chris@376: * Add a command to the history and also execute it. Equivalent Chris@376: * to addCommand(command, true). Chris@376: */ Chris@376: void addCommandAndExecute(Command *); Chris@376: Chris@376: void undo(); Chris@376: void redo(); Chris@376: Chris@376: protected slots: Chris@376: void undoActivated(QAction *); Chris@376: void redoActivated(QAction *); Chris@376: void bundleTimerTimeout(); Chris@376: Chris@376: signals: Chris@376: /** Chris@376: * Emitted whenever a command has just been executed or Chris@376: * unexecuted, whether by addCommand, undo, or redo. Chris@376: */ Chris@376: void commandExecuted(); Chris@376: Chris@376: /** Chris@376: * Emitted whenever a command has just been executed, whether by Chris@376: * addCommand or redo. Chris@376: */ Chris@376: void commandExecuted(Command *); Chris@376: Chris@376: /** Chris@376: * Emitted whenever a command has just been unexecuted, whether by Chris@376: * addCommand or undo. Chris@376: */ Chris@376: void commandUnexecuted(Command *); Chris@376: Chris@376: /** Chris@376: * Emitted when the undo/redo stack has reached the same state at Chris@376: * which the documentSaved slot was last called. Chris@376: */ Chris@376: void documentRestored(); Chris@376: Chris@502: /** Chris@502: * Emitted when some activity happened (for activity logging). Chris@502: */ Chris@502: void activity(QString); Chris@502: Chris@376: protected: Chris@376: CommandHistory(); Chris@376: static CommandHistory *m_instance; Chris@376: Chris@376: QAction *m_undoAction; Chris@376: QAction *m_redoAction; Chris@376: QAction *m_undoMenuAction; Chris@376: QAction *m_redoMenuAction; Chris@376: QMenu *m_undoMenu; Chris@376: QMenu *m_redoMenu; Chris@376: Chris@376: std::map m_actionCounts; Chris@376: Chris@376: typedef std::stack CommandStack; Chris@376: CommandStack m_undoStack; Chris@376: CommandStack m_redoStack; Chris@376: Chris@376: int m_undoLimit; Chris@376: int m_redoLimit; Chris@376: int m_menuLimit; Chris@376: int m_savedAt; Chris@376: Chris@376: MacroCommand *m_currentCompound; Chris@376: bool m_executeCompound; Chris@376: void addToCompound(Command *command, bool execute); Chris@376: Chris@376: MacroCommand *m_currentBundle; Chris@502: bool m_bundling; Chris@376: QString m_currentBundleName; Chris@376: QTimer *m_bundleTimer; Chris@376: int m_bundleTimeout; Chris@376: void addToBundle(Command *command, bool execute); Chris@376: void closeBundle(); Chris@376: Chris@376: void updateActions(); Chris@376: Chris@376: void clipCommands(); Chris@376: Chris@376: void clipStack(CommandStack &stack, int limit); Chris@376: void clearStack(CommandStack &stack); Chris@376: }; Chris@376: Chris@376: Chris@376: #endif