• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdelibs API Reference
  • KDE Home
  • Contact Us
 

KDE3Support

  • sources
  • kde-4.14
  • kdelibs
  • kde3support
  • kdeui
k3command.cpp
Go to the documentation of this file.
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 #include "k3command.h"
22 #include <kaction.h>
23 #include <kactioncollection.h>
24 #include <kstandardshortcut.h>
25 #include <kstandardaction.h>
26 #include <kdebug.h>
27 #include <kicon.h>
28 #include <klocale.h>
29 #include <kmenu.h>
30 
31 #include "ktoolbarpopupaction.h"
32 
33 K3Command::K3Command()
34  : d( 0 )
35 {
36 }
37 
38 K3Command::~K3Command()
39 {
40 }
41 
42 class K3NamedCommand::Private
43 {
44  public:
45  QString name;
46 };
47 
48 K3NamedCommand::K3NamedCommand( const QString &name )
49  : K3Command(),
50  d( new Private )
51 {
52  d->name = name;
53 }
54 
55 K3NamedCommand::~K3NamedCommand()
56 {
57  delete d;
58 }
59 
60 QString K3NamedCommand::name() const
61 {
62  return d->name;
63 }
64 
65 void K3NamedCommand::setName( const QString &name )
66 {
67  d->name = name;
68 }
69 
70 class K3MacroCommand::Private
71 {
72  public:
73  QList<K3Command *> commands;
74 };
75 
76 K3MacroCommand::K3MacroCommand( const QString & name )
77  : K3NamedCommand(name),
78  d( new Private )
79 {
80 }
81 
82 K3MacroCommand::~K3MacroCommand()
83 {
84  qDeleteAll( d->commands );
85  delete d;
86 }
87 
88 void K3MacroCommand::addCommand( K3Command *command )
89 {
90  d->commands.append(command);
91 }
92 
93 void K3MacroCommand::execute()
94 {
95  QListIterator<K3Command *> it( d->commands );
96  while ( it.hasNext() ) {
97  it.next()->execute();
98  }
99 }
100 
101 void K3MacroCommand::unexecute()
102 {
103  QListIterator<K3Command *> it( d->commands );
104  it.toBack();
105  while ( it.hasPrevious() ) {
106  it.previous()->unexecute();
107  }
108 }
109 
110 const QList<K3Command *> K3MacroCommand::commands() const
111 {
112  return d->commands;
113 }
114 
115 
116 class K3CommandHistory::K3CommandHistoryPrivate {
117 public:
118  K3CommandHistoryPrivate()
119  : m_undoLimit(50), m_redoLimit(30),
120  m_savedAt(-1), m_current(-1) {
121  }
122  ~K3CommandHistoryPrivate() {
123  qDeleteAll( m_commands );
124  }
125 
126  QList<K3Command *> m_commands;
127  int m_undoLimit, m_redoLimit;
128 
129  int m_savedAt;
130  int m_current;
131  /*
132  If m_commands contains: <c0> <c1> <c2> <c3>
133 
134  m_current = 1 means we are between <c1> and <c2>, i.e. undo would unexecute c1.
135  So m_current is the index of the current undo command, m_current+1 the current redo command if any.
136 
137  Adding a command at this point would delete <c2> and <c3>.
138  m_current compared to the commands: -1 <c0> 0 <c1> 1 <c2> 2.
139 
140  m_savedAt = 1 means that we where at m_current == 1 when the document was saved.
141  m_savedAt = -1 means that the document was saved with an empty history (initial state, too).
142  m_savedAt = -2 means that the document wasn't saved in the current visible history
143  (this happens when the undo history got truncated)
144  */
145 };
146 
148 
149 K3CommandHistory::K3CommandHistory() :
150  d( new K3CommandHistoryPrivate )
151 {
152  clear();
153 }
154 
155 K3CommandHistory::K3CommandHistory(KActionCollection * actionCollection, bool withMenus) :
156  d( new K3CommandHistoryPrivate )
157 {
158  if (withMenus)
159  {
160  // TODO instead of a menu this should show a listbox like koffice's KoCommandHistory does,
161  // so that it's clearer that N actions will be undone together, not just action number N.
162 
163  // TODO also move this out of K3CommandHistory, to make it core-only.
164 
165  new K3UndoRedoAction( K3UndoRedoAction::Undo, actionCollection, this );
166  new K3UndoRedoAction( K3UndoRedoAction::Redo, actionCollection, this );
167  }
168  else
169  {
170  actionCollection->addAction(KStandardAction::Undo, this, SLOT(undo()));
171  actionCollection->addAction(KStandardAction::Redo, this, SLOT(redo()));
172  }
173  clear();
174 }
175 
176 K3CommandHistory::~K3CommandHistory() {
177  delete d;
178 }
179 
180 void K3CommandHistory::clear() {
181  qDeleteAll( d->m_commands );
182  d->m_commands.clear();
183  d->m_current = -1;
184  d->m_savedAt = -1;
185  emit commandHistoryChanged();
186 }
187 
188 void K3CommandHistory::addCommand(K3Command *command, bool execute) {
189  if ( !command )
190  return;
191 
192  ++d->m_current;
193  d->m_commands.insert( d->m_current, command );
194  // Truncate history
195  int count = d->m_commands.count();
196  for ( int i = d->m_current + 1; i < count; ++i )
197  delete d->m_commands.takeLast();
198 
199  // Check whether we still can reach savedAt
200  if ( d->m_current < d->m_savedAt )
201  d->m_savedAt = -2;
202 
203  clipCommands();
204 
205  if ( execute )
206  {
207  command->execute();
208  emit commandExecuted(command);
209  }
210 }
211 
212 K3Command * K3CommandHistory::presentCommand() const
213 {
214  if ( d->m_current >= 0 )
215  return d->m_commands[ d->m_current ];
216  return 0;
217 }
218 
219 void K3CommandHistory::undo() {
220  Q_ASSERT( d->m_current >= 0 );
221 
222  K3Command* command = d->m_commands[ d->m_current ];
223 
224  command->unexecute();
225  emit commandExecuted( command );
226 
227  --d->m_current;
228 
229  if ( d->m_current == d->m_savedAt )
230  emit documentRestored();
231 
232  clipCommands(); // only needed here and in addCommand, NOT in redo
233 }
234 
235 void K3CommandHistory::redo() {
236  K3Command* command = d->m_commands[ d->m_current + 1 ];
237  command->execute();
238  emit commandExecuted( command );
239 
240  ++d->m_current;
241 
242  if ( d->m_current == d->m_savedAt )
243  emit documentRestored();
244 
245  emit commandHistoryChanged();
246 }
247 
248 void K3CommandHistory::documentSaved() {
249  d->m_savedAt = d->m_current;
250 }
251 
252 void K3CommandHistory::setUndoLimit(int limit) {
253  if ( limit>0 && limit != d->m_undoLimit ) {
254  d->m_undoLimit = limit;
255  clipCommands();
256  }
257 }
258 
259 void K3CommandHistory::setRedoLimit(int limit) {
260  if ( limit>0 && limit != d->m_redoLimit ) {
261  d->m_redoLimit = limit;
262  clipCommands();
263  }
264 }
265 
266 void K3CommandHistory::clipCommands() {
267  int count = d->m_commands.count();
268  if ( count <= d->m_undoLimit && count <= d->m_redoLimit ) {
269  emit commandHistoryChanged();
270  return;
271  }
272 
273  if ( d->m_current >= d->m_undoLimit ) {
274  const int toRemove = (d->m_current - d->m_undoLimit) + 1;
275  for ( int i = 0; i < toRemove; ++i ) {
276  delete d->m_commands.takeFirst();
277  --d->m_savedAt;
278  --d->m_current;
279  }
280  Q_ASSERT( d->m_current >= -1 );
281  count = d->m_commands.count(); // update count for the redo branch below
282  if ( d->m_savedAt < 0 )
283  d->m_savedAt = -1; // savedAt went out of the history
284  }
285 
286  if ( d->m_current + d->m_redoLimit + 1 < count ) {
287  if ( d->m_savedAt > (d->m_current + d->m_redoLimit) )
288  d->m_savedAt = -1;
289  const int toRemove = count - (d->m_current + d->m_redoLimit + 1);
290  for ( int i = 0; i< toRemove; ++i )
291  delete d->m_commands.takeLast();
292  }
293  emit commandHistoryChanged();
294 }
295 
296 void K3CommandHistory::updateActions()
297 {
298  // it hasn't changed, but this updates all actions connected to this command history.
299  emit commandHistoryChanged();
300 }
301 
302 bool K3CommandHistory::isUndoAvailable() const
303 {
304  return d->m_current >= 0;
305 }
306 
307 bool K3CommandHistory::isRedoAvailable() const
308 {
309  return d->m_current < d->m_commands.count() - 1;
310 }
311 
312 QList<K3Command *> K3CommandHistory::undoCommands( int maxCommands ) const
313 {
314  QList<K3Command *> lst;
315  for ( int i = d->m_current; i >= 0; --i ) {
316  lst.append( d->m_commands[i] );
317  if ( maxCommands > 0 && lst.count() == maxCommands )
318  break;
319  }
320  return lst;
321 }
322 
323 QList<K3Command *> K3CommandHistory::redoCommands( int maxCommands ) const
324 {
325  QList<K3Command *> lst;
326  for ( int i = d->m_current + 1; i < d->m_commands.count(); ++i )
327  {
328  lst.append( d->m_commands[i] );
329  if ( maxCommands > 0 && lst.count() == maxCommands )
330  break;
331  }
332  return lst;
333 }
334 
335 int K3CommandHistory::undoLimit() const
336 {
337  return d->m_undoLimit;
338 }
339 
340 int K3CommandHistory::redoLimit() const
341 {
342  return d->m_redoLimit;
343 }
344 
345 class K3UndoRedoAction::Private
346 {
347  public:
348  Private( K3UndoRedoAction::Type type, K3CommandHistory* commandHistory)
349  : type( type ),
350  commandHistory( commandHistory )
351  {
352  }
353 
354  Type type;
355  K3CommandHistory* commandHistory;
356 };
357 
358 
359 
360 K3UndoRedoAction::K3UndoRedoAction( Type type, KActionCollection* actionCollection, K3CommandHistory* commandHistory )
361  : KToolBarPopupAction( KIcon( type == Undo ? "edit-undo" : "edit-redo" ),
362  QString(), // text is set in clear() on start
363  actionCollection),
364  d( new Private( type, commandHistory ) )
365 {
366  setShortcut( KStandardShortcut::shortcut( type == Undo ? KStandardShortcut::Undo : KStandardShortcut::Redo ) );
367  if ( d->type == Undo ) {
368  connect( this, SIGNAL(triggered(bool)), d->commandHistory, SLOT(undo()) );
369  } else {
370  connect( this, SIGNAL(triggered(bool)), d->commandHistory, SLOT(redo()) );
371  }
372  connect( this->menu(), SIGNAL(aboutToShow()), this, SLOT(slotAboutToShow()) );
373  connect( this->menu(), SIGNAL(triggered(QAction*)), this, SLOT(slotActionTriggered(QAction*)) );
374 
375  connect( d->commandHistory, SIGNAL(commandHistoryChanged()), this, SLOT(slotCommandHistoryChanged()) );
376  slotCommandHistoryChanged();
377  actionCollection->addAction(KStandardAction::name(type == Undo ? KStandardAction::Undo : KStandardAction::Redo),
378  this);
379 }
380 
381 void K3UndoRedoAction::slotAboutToShow()
382 {
383  menu()->clear();
384  // TODO make number of items configurable ?
385  const int maxCommands = 9;
386  if ( d->type == Undo ) {
387  const QList<K3Command *> commands = d->commandHistory->undoCommands( maxCommands );
388  for (int i = 0; i < commands.count(); ++i) {
389  QAction *action = menu()->addAction( i18n("Undo: %1", commands[i]->name()) );
390  action->setData( i );
391  }
392  } else {
393  const QList<K3Command *> commands = d->commandHistory->redoCommands( maxCommands );
394  for (int i = 0; i < commands.count(); ++i) {
395  QAction *action = menu()->addAction( i18n("Redo: %1", commands[i]->name()) );
396  action->setData( i );
397  }
398  }
399 }
400 
401 void K3UndoRedoAction::slotActionTriggered( QAction *action )
402 {
403  const int pos = action->data().toInt();
404  //kDebug(230) << pos;
405  if ( d->type == Undo ) {
406  for ( int i = 0 ; i < pos+1; ++i ) {
407  d->commandHistory->undo();
408  }
409  } else {
410  for ( int i = 0 ; i < pos+1; ++i ) {
411  d->commandHistory->redo();
412  }
413  }
414 }
415 
416 void K3UndoRedoAction::slotCommandHistoryChanged()
417 {
418  const bool isUndo = d->type == Undo;
419  const bool enabled = isUndo ? d->commandHistory->isUndoAvailable() : d->commandHistory->isRedoAvailable();
420  setEnabled(enabled);
421  if (!enabled) {
422  setText(isUndo ? i18n("&Undo") : i18n("&Redo"));
423  } else {
424  if (isUndo) {
425  K3Command* presentCommand = d->commandHistory->presentCommand();
426  Q_ASSERT(presentCommand);
427  setText(i18n("&Undo: %1", presentCommand->name()));
428  } else {
429  K3Command* redoCommand = d->commandHistory->redoCommands(1).first();
430  setText(i18n("&Redo: %1", redoCommand->name()));
431  }
432  }
433 }
434 
435 
436 void K3Command::virtual_hook( int, void* )
437 { /*BASE::virtual_hook( id, data );*/ }
438 
439 void K3NamedCommand::virtual_hook( int id, void* data )
440 { K3Command::virtual_hook( id, data ); }
441 
442 void K3MacroCommand::virtual_hook( int id, void* data )
443 { K3NamedCommand::virtual_hook( id, data ); }
444 
445 #include "k3command.moc"
QAction::setText
void setText(const QString &text)
i18n
QString i18n(const char *text)
KActionCollection
K3CommandHistory::K3CommandHistory
K3CommandHistory()
Creates a command history, to store commands.
Definition: k3command.cpp:149
K3NamedCommand::virtual_hook
virtual void virtual_hook(int id, void *data)
Definition: k3command.cpp:439
K3Command::virtual_hook
virtual void virtual_hook(int id, void *data)
Definition: k3command.cpp:436
K3UndoRedoAction
This type of action is used to show undo or redo actions in the menu or in the toolbars.
Definition: k3command.h:357
K3CommandHistory::undoCommands
QList< K3Command * > undoCommands(int maxCommands=0) const
Definition: k3command.cpp:312
Type
Type
kdebug.h
KStandardAction::Redo
undo
KAction * undo(const QObject *recvr, const char *slot, QObject *parent)
QListIterator::next
const T & next()
QListIterator::previous
const T & previous()
K3MacroCommand::addCommand
void addCommand(K3Command *command)
Appends a command to this macro command.
Definition: k3command.cpp:88
K3Command
The abstract base class for all Commands.
Definition: k3command.h:41
K3UndoRedoAction::K3UndoRedoAction
K3UndoRedoAction(Type type, KActionCollection *actionCollection, K3CommandHistory *commandHistory)
Definition: k3command.cpp:360
QAction::data
QVariant data() const
kactioncollection.h
KStandardShortcut::shortcut
const KShortcut & shortcut(StandardShortcut id)
K3NamedCommand::setName
void setName(const QString &name)
Updates the name of this command.
Definition: k3command.cpp:65
K3CommandHistory::~K3CommandHistory
virtual ~K3CommandHistory()
Destructs the command history object.
Definition: k3command.cpp:176
QMenu::addAction
void addAction(QAction *action)
K3MacroCommand::commands
const QList< K3Command * > commands() const
Definition: k3command.cpp:110
KStandardAction::name
const char * name(StandardAction id)
KActionCollection::addAction
QAction * addAction(const QString &name, QAction *action)
K3CommandHistory::addCommand
void addCommand(K3Command *command, bool execute=true)
Adds a command to the history.
Definition: k3command.cpp:188
K3CommandHistory::redoCommands
QList< K3Command * > redoCommands(int maxCommands=0) const
Definition: k3command.cpp:323
KStandardAction::Undo
K3Command::K3Command
K3Command()
Creates a command.
Definition: k3command.cpp:33
K3CommandHistory::presentCommand
K3Command * presentCommand() const
Definition: k3command.cpp:212
klocale.h
K3NamedCommand::K3NamedCommand
K3NamedCommand(const QString &name)
Creates a command.
Definition: k3command.cpp:48
K3MacroCommand::K3MacroCommand
K3MacroCommand(const QString &name)
Creates a macro command.
Definition: k3command.cpp:76
QMenu::clear
void clear()
QObject::name
const char * name() const
K3MacroCommand::~K3MacroCommand
virtual ~K3MacroCommand()
Definition: k3command.cpp:82
K3CommandHistory::commandExecuted
void commandExecuted(K3Command *command)
Emitted every time a command is executed (whether by addCommand, undo or redo).
QList::count
int count(const T &value) const
QList::append
void append(const T &value)
QVariant::toInt
int toInt(bool *ok) const
kmenu.h
K3CommandHistory::setUndoLimit
void setUndoLimit(int limit)
Sets the maximum number of items in the undo history.
Definition: k3command.cpp:252
K3Command::name
virtual QString name() const =0
KIcon
K3Command::unexecute
virtual void unexecute()=0
Unexecutes (undo) this command.
QListIterator::toBack
void toBack()
redo
KAction * redo(const QObject *recvr, const char *slot, QObject *parent)
QString
kstandardaction.h
QList< K3Command * >
KStandardShortcut::Redo
K3CommandHistory::redo
virtual void redo()
Redoes the last undone action.
Definition: k3command.cpp:235
K3CommandHistory::undo
virtual void undo()
Undoes the last action.
Definition: k3command.cpp:219
QAction::setData
void setData(const QVariant &userData)
KAction::setShortcut
void setShortcut(const KShortcut &shortcut, ShortcutTypes type=ShortcutTypes(ActiveShortcut|DefaultShortcut))
kaction.h
kstandardshortcut.h
K3NamedCommand
A command which stores its name.
Definition: k3command.h:89
K3CommandHistory::redoLimit
int redoLimit() const
Definition: k3command.cpp:340
K3CommandHistory::documentSaved
virtual void documentSaved()
Remembers when you saved the document.
Definition: k3command.cpp:248
K3MacroCommand::execute
virtual void execute()
Executes this command, i.e.
Definition: k3command.cpp:93
K3CommandHistory::updateActions
void updateActions()
Enable or disable the undo and redo actions.
Definition: k3command.cpp:296
KAction::triggered
void triggered(Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
K3NamedCommand::~K3NamedCommand
virtual ~K3NamedCommand()
Definition: k3command.cpp:55
QListIterator::hasPrevious
bool hasPrevious() const
K3CommandHistory::setRedoLimit
void setRedoLimit(int limit)
Sets the maximum number of items in the redo history.
Definition: k3command.cpp:259
K3Command::execute
virtual void execute()=0
The main method: executes this command.
K3MacroCommand::virtual_hook
virtual void virtual_hook(int id, void *data)
Definition: k3command.cpp:442
K3NamedCommand::name
virtual QString name() const
Definition: k3command.cpp:60
QAction
K3CommandHistory::isUndoAvailable
bool isUndoAvailable() const
Definition: k3command.cpp:302
K3UndoRedoAction::Redo
Definition: k3command.h:361
K3UndoRedoAction::Type
Type
Definition: k3command.h:361
QListIterator
KToolBarPopupAction
K3CommandHistory::documentRestored
void documentRestored()
Emitted every time we reach the index where you saved the document for the last time.
ktoolbarpopupaction.h
K3CommandHistory::undoLimit
int undoLimit() const
Definition: k3command.cpp:335
kicon.h
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QAction::menu
QMenu * menu() const
K3CommandHistory::clear
void clear()
Erases all the undo/redo history.
Definition: k3command.cpp:180
K3CommandHistory::commandHistoryChanged
void commandHistoryChanged()
Emitted whenever the command history has changed, i.e.
QAction::enabled
enabled
K3MacroCommand::unexecute
virtual void unexecute()
Undoes the execution of this command, i.e.
Definition: k3command.cpp:101
K3UndoRedoAction::Undo
Definition: k3command.h:361
KStandardShortcut::Undo
K3CommandHistory
The command history stores a (user) configurable amount of Commands.
Definition: k3command.h:180
k3command.h
K3CommandHistory::isRedoAvailable
bool isRedoAvailable() const
Definition: k3command.cpp:307
K3Command::~K3Command
virtual ~K3Command()
Definition: k3command.cpp:38
QListIterator::hasNext
bool hasNext() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:26:47 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDE3Support

Skip menu "KDE3Support"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal