Chris@49
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@16
|
2
|
Chris@16
|
3 /*
|
Chris@52
|
4 Sonic Visualiser
|
Chris@52
|
5 An audio file viewer and annotation editor.
|
Chris@52
|
6 Centre for Digital Music, Queen Mary, University of London.
|
Chris@16
|
7
|
Chris@52
|
8 This program is free software; you can redistribute it and/or
|
Chris@52
|
9 modify it under the terms of the GNU General Public License as
|
Chris@52
|
10 published by the Free Software Foundation; either version 2 of the
|
Chris@52
|
11 License, or (at your option) any later version. See the file
|
Chris@52
|
12 COPYING included with this distribution for more information.
|
Chris@16
|
13 */
|
Chris@16
|
14
|
Chris@16
|
15 /*
|
Chris@16
|
16 This is a modified version of a source file from the Rosegarden
|
Chris@16
|
17 MIDI and audio sequencer and notation editor, copyright 2000-2006
|
Chris@16
|
18 Chris Cannam, distributed under the GNU General Public License.
|
Chris@16
|
19
|
Chris@16
|
20 This file contains traces of the KCommandHistory class from the KDE
|
Chris@16
|
21 project, copyright 2000 Werner Trobin and David Faure and
|
Chris@16
|
22 distributed under the GNU Lesser General Public License.
|
Chris@16
|
23 */
|
Chris@16
|
24
|
Chris@17
|
25 #include "CommandHistory.h"
|
Chris@16
|
26
|
Chris@16
|
27 #include "Command.h"
|
Chris@16
|
28
|
Chris@16
|
29 #include <QRegExp>
|
Chris@16
|
30 #include <QMenu>
|
Chris@16
|
31 #include <QToolBar>
|
Chris@16
|
32 #include <QString>
|
Chris@47
|
33 #include <QTimer>
|
Chris@16
|
34
|
Chris@16
|
35 #include <iostream>
|
Chris@16
|
36
|
Chris@17
|
37 CommandHistory *CommandHistory::m_instance = 0;
|
Chris@17
|
38
|
Chris@17
|
39 CommandHistory::CommandHistory() :
|
Chris@16
|
40 m_undoLimit(50),
|
Chris@16
|
41 m_redoLimit(50),
|
Chris@46
|
42 m_menuLimit(15),
|
Chris@44
|
43 m_savedAt(0),
|
Chris@47
|
44 m_currentCompound(0),
|
Chris@47
|
45 m_executeCompound(false),
|
Chris@47
|
46 m_currentBundle(0),
|
Chris@47
|
47 m_bundleTimer(0),
|
Chris@47
|
48 m_bundleTimeout(5000)
|
Chris@16
|
49 {
|
Chris@16
|
50 m_undoAction = new QAction(QIcon(":/icons/undo.png"), tr("&Undo"), this);
|
Chris@16
|
51 m_undoAction->setShortcut(tr("Ctrl+Z"));
|
Chris@214
|
52 m_undoAction->setStatusTip(tr("Undo the last editing operation"));
|
Chris@16
|
53 connect(m_undoAction, SIGNAL(triggered()), this, SLOT(undo()));
|
Chris@16
|
54
|
Chris@17
|
55 m_undoMenuAction = new QAction(QIcon(":/icons/undo.png"), tr("&Undo"), this);
|
Chris@17
|
56 connect(m_undoMenuAction, SIGNAL(triggered()), this, SLOT(undo()));
|
Chris@17
|
57
|
Chris@16
|
58 m_undoMenu = new QMenu(tr("&Undo"));
|
Chris@17
|
59 m_undoMenuAction->setMenu(m_undoMenu);
|
Chris@16
|
60 connect(m_undoMenu, SIGNAL(triggered(QAction *)),
|
Chris@16
|
61 this, SLOT(undoActivated(QAction*)));
|
Chris@16
|
62
|
Chris@17
|
63 m_redoAction = new QAction(QIcon(":/icons/redo.png"), tr("Re&do"), this);
|
Chris@16
|
64 m_redoAction->setShortcut(tr("Ctrl+Shift+Z"));
|
Chris@214
|
65 m_redoAction->setStatusTip(tr("Redo the last operation that was undone"));
|
Chris@16
|
66 connect(m_redoAction, SIGNAL(triggered()), this, SLOT(redo()));
|
Chris@17
|
67
|
Chris@17
|
68 m_redoMenuAction = new QAction(QIcon(":/icons/redo.png"), tr("Re&do"), this);
|
Chris@17
|
69 connect(m_redoMenuAction, SIGNAL(triggered()), this, SLOT(redo()));
|
Chris@16
|
70
|
Chris@16
|
71 m_redoMenu = new QMenu(tr("Re&do"));
|
Chris@17
|
72 m_redoMenuAction->setMenu(m_redoMenu);
|
Chris@16
|
73 connect(m_redoMenu, SIGNAL(triggered(QAction *)),
|
Chris@16
|
74 this, SLOT(redoActivated(QAction*)));
|
Chris@16
|
75 }
|
Chris@16
|
76
|
Chris@17
|
77 CommandHistory::~CommandHistory()
|
Chris@16
|
78 {
|
Chris@16
|
79 m_savedAt = -1;
|
Chris@16
|
80 clearStack(m_undoStack);
|
Chris@16
|
81 clearStack(m_redoStack);
|
Chris@16
|
82
|
Chris@16
|
83 delete m_undoMenu;
|
Chris@16
|
84 delete m_redoMenu;
|
Chris@16
|
85 }
|
Chris@16
|
86
|
Chris@17
|
87 CommandHistory *
|
Chris@17
|
88 CommandHistory::getInstance()
|
Chris@17
|
89 {
|
Chris@17
|
90 if (!m_instance) m_instance = new CommandHistory();
|
Chris@17
|
91 return m_instance;
|
Chris@17
|
92 }
|
Chris@17
|
93
|
Chris@16
|
94 void
|
Chris@17
|
95 CommandHistory::clear()
|
Chris@16
|
96 {
|
Chris@78
|
97 // std::cerr << "CommandHistory::clear()" << std::endl;
|
Chris@47
|
98 closeBundle();
|
Chris@16
|
99 m_savedAt = -1;
|
Chris@16
|
100 clearStack(m_undoStack);
|
Chris@16
|
101 clearStack(m_redoStack);
|
Chris@16
|
102 updateActions();
|
Chris@16
|
103 }
|
Chris@16
|
104
|
Chris@16
|
105 void
|
Chris@17
|
106 CommandHistory::registerMenu(QMenu *menu)
|
Chris@16
|
107 {
|
Chris@16
|
108 menu->addAction(m_undoAction);
|
Chris@16
|
109 menu->addAction(m_redoAction);
|
Chris@16
|
110 }
|
Chris@16
|
111
|
Chris@16
|
112 void
|
Chris@17
|
113 CommandHistory::registerToolbar(QToolBar *toolbar)
|
Chris@16
|
114 {
|
Chris@17
|
115 toolbar->addAction(m_undoMenuAction);
|
Chris@17
|
116 toolbar->addAction(m_redoMenuAction);
|
Chris@16
|
117 }
|
Chris@16
|
118
|
Chris@16
|
119 void
|
Chris@115
|
120 CommandHistory::addCommand(Command *command)
|
Chris@115
|
121 {
|
Chris@115
|
122 if (!command) return;
|
Chris@115
|
123
|
Chris@115
|
124 if (m_currentCompound) {
|
Chris@115
|
125 addToCompound(command, m_executeCompound);
|
Chris@115
|
126 return;
|
Chris@115
|
127 }
|
Chris@115
|
128
|
Chris@115
|
129 addCommand(command, true);
|
Chris@115
|
130 }
|
Chris@115
|
131
|
Chris@115
|
132 void
|
Chris@47
|
133 CommandHistory::addCommand(Command *command, bool execute, bool bundle)
|
Chris@16
|
134 {
|
Chris@16
|
135 if (!command) return;
|
Chris@16
|
136
|
Chris@47
|
137 if (m_currentCompound) {
|
Chris@115
|
138 addToCompound(command, execute);
|
Chris@44
|
139 return;
|
Chris@44
|
140 }
|
Chris@44
|
141
|
Chris@47
|
142 if (bundle) {
|
Chris@47
|
143 addToBundle(command, execute);
|
Chris@47
|
144 return;
|
Chris@47
|
145 } else if (m_currentBundle) {
|
Chris@47
|
146 closeBundle();
|
Chris@47
|
147 }
|
Chris@47
|
148
|
Chris@78
|
149 // std::cerr << "CommandHistory::addCommand: " << command->getName().toLocal8Bit().data() << " at " << command << std::endl;
|
Chris@16
|
150
|
Chris@16
|
151 // We can't redo after adding a command
|
Chris@78
|
152 // std::cerr << "CommandHistory::clearing redo stack" << std::endl;
|
Chris@16
|
153 clearStack(m_redoStack);
|
Chris@16
|
154
|
Chris@16
|
155 // can we reach savedAt?
|
Chris@16
|
156 if ((int)m_undoStack.size() < m_savedAt) m_savedAt = -1; // nope
|
Chris@16
|
157
|
Chris@16
|
158 m_undoStack.push(command);
|
Chris@16
|
159 clipCommands();
|
Chris@16
|
160
|
Chris@16
|
161 if (execute) {
|
Chris@16
|
162 command->execute();
|
Chris@16
|
163 }
|
Chris@16
|
164
|
Chris@17
|
165 // Emit even if we aren't executing the command, because
|
Chris@17
|
166 // someone must have executed it for this to make any sense
|
Chris@17
|
167 emit commandExecuted();
|
Chris@17
|
168 emit commandExecuted(command);
|
Chris@17
|
169
|
Chris@16
|
170 updateActions();
|
Chris@16
|
171 }
|
Chris@16
|
172
|
Chris@16
|
173 void
|
Chris@47
|
174 CommandHistory::addToBundle(Command *command, bool execute)
|
Chris@44
|
175 {
|
Chris@47
|
176 if (m_currentBundle) {
|
Chris@47
|
177 if (!command || (command->getName() != m_currentBundleName)) {
|
Chris@47
|
178 closeBundle();
|
Chris@47
|
179 }
|
Chris@47
|
180 }
|
Chris@44
|
181
|
Chris@47
|
182 if (!command) return;
|
Chris@47
|
183
|
Chris@47
|
184 if (!m_currentBundle) {
|
Chris@47
|
185 // need to addCommand before setting m_currentBundle, as addCommand
|
Chris@47
|
186 // with bundle false will reset m_currentBundle to 0
|
Chris@47
|
187 MacroCommand *mc = new MacroCommand(command->getName());
|
Chris@47
|
188 addCommand(mc, false);
|
Chris@47
|
189 m_currentBundle = mc;
|
Chris@47
|
190 m_currentBundleName = command->getName();
|
Chris@47
|
191 }
|
Chris@47
|
192
|
Chris@47
|
193 if (execute) command->execute();
|
Chris@47
|
194 m_currentBundle->addCommand(command);
|
Chris@47
|
195
|
Chris@47
|
196 delete m_bundleTimer;
|
Chris@47
|
197 m_bundleTimer = new QTimer(this);
|
Chris@47
|
198 connect(m_bundleTimer, SIGNAL(timeout()), this, SLOT(bundleTimerTimeout()));
|
Chris@47
|
199 m_bundleTimer->start(m_bundleTimeout);
|
Chris@47
|
200 }
|
Chris@47
|
201
|
Chris@47
|
202 void
|
Chris@47
|
203 CommandHistory::closeBundle()
|
Chris@47
|
204 {
|
Chris@47
|
205 m_currentBundle = 0;
|
Chris@47
|
206 m_currentBundleName = "";
|
Chris@47
|
207 }
|
Chris@47
|
208
|
Chris@47
|
209 void
|
Chris@47
|
210 CommandHistory::bundleTimerTimeout()
|
Chris@47
|
211 {
|
Chris@47
|
212 closeBundle();
|
Chris@47
|
213 }
|
Chris@47
|
214
|
Chris@47
|
215 void
|
Chris@115
|
216 CommandHistory::addToCompound(Command *command, bool execute)
|
Chris@47
|
217 {
|
Chris@78
|
218 // std::cerr << "CommandHistory::addToCompound: " << command->getName().toLocal8Bit().data() << std::endl;
|
Chris@383
|
219 if (!m_currentCompound) {
|
Chris@383
|
220 std::cerr << "CommandHistory::addToCompound: ERROR: no compound operation in progress!" << std::endl;
|
Chris@383
|
221 return;
|
Chris@383
|
222 }
|
Chris@47
|
223
|
Chris@115
|
224 if (execute) command->execute();
|
Chris@47
|
225 m_currentCompound->addCommand(command);
|
Chris@44
|
226 }
|
Chris@44
|
227
|
Chris@44
|
228 void
|
Chris@44
|
229 CommandHistory::startCompoundOperation(QString name, bool execute)
|
Chris@44
|
230 {
|
Chris@47
|
231 if (m_currentCompound) {
|
Chris@47
|
232 std::cerr << "CommandHistory::startCompoundOperation: ERROR: compound operation already in progress!" << std::endl;
|
Chris@47
|
233 std::cerr << "(name is " << m_currentCompound->getName().toLocal8Bit().data() << ")" << std::endl;
|
Chris@383
|
234 return;
|
Chris@44
|
235 }
|
Chris@47
|
236
|
Chris@47
|
237 closeBundle();
|
Chris@47
|
238
|
Chris@47
|
239 m_currentCompound = new MacroCommand(name);
|
Chris@47
|
240 m_executeCompound = execute;
|
Chris@44
|
241 }
|
Chris@44
|
242
|
Chris@44
|
243 void
|
Chris@44
|
244 CommandHistory::endCompoundOperation()
|
Chris@44
|
245 {
|
Chris@47
|
246 if (!m_currentCompound) {
|
Chris@47
|
247 std::cerr << "CommandHistory::endCompoundOperation: ERROR: no compound operation in progress!" << std::endl;
|
Chris@383
|
248 return;
|
Chris@44
|
249 }
|
Chris@44
|
250
|
Chris@53
|
251 MacroCommand *toAdd = m_currentCompound;
|
Chris@47
|
252 m_currentCompound = 0;
|
Chris@44
|
253
|
Chris@53
|
254 if (toAdd->haveCommands()) {
|
Chris@53
|
255
|
Chris@53
|
256 // We don't execute the macro command here, because we have
|
Chris@53
|
257 // been executing the individual commands as we went along if
|
Chris@53
|
258 // m_executeCompound was true.
|
Chris@53
|
259 addCommand(toAdd, false);
|
Chris@53
|
260 }
|
Chris@44
|
261 }
|
Chris@44
|
262
|
Chris@44
|
263 void
|
Chris@17
|
264 CommandHistory::addExecutedCommand(Command *command)
|
Chris@17
|
265 {
|
Chris@17
|
266 addCommand(command, false);
|
Chris@17
|
267 }
|
Chris@17
|
268
|
Chris@17
|
269 void
|
Chris@17
|
270 CommandHistory::addCommandAndExecute(Command *command)
|
Chris@17
|
271 {
|
Chris@17
|
272 addCommand(command, true);
|
Chris@17
|
273 }
|
Chris@17
|
274
|
Chris@17
|
275 void
|
Chris@17
|
276 CommandHistory::undo()
|
Chris@16
|
277 {
|
Chris@16
|
278 if (m_undoStack.empty()) return;
|
Chris@16
|
279
|
Chris@47
|
280 closeBundle();
|
Chris@47
|
281
|
Chris@16
|
282 Command *command = m_undoStack.top();
|
Chris@16
|
283 command->unexecute();
|
Chris@16
|
284 emit commandExecuted();
|
Chris@17
|
285 emit commandUnexecuted(command);
|
Chris@16
|
286
|
Chris@16
|
287 m_redoStack.push(command);
|
Chris@16
|
288 m_undoStack.pop();
|
Chris@16
|
289
|
Chris@16
|
290 clipCommands();
|
Chris@16
|
291 updateActions();
|
Chris@16
|
292
|
Chris@16
|
293 if ((int)m_undoStack.size() == m_savedAt) emit documentRestored();
|
Chris@16
|
294 }
|
Chris@16
|
295
|
Chris@16
|
296 void
|
Chris@17
|
297 CommandHistory::redo()
|
Chris@16
|
298 {
|
Chris@16
|
299 if (m_redoStack.empty()) return;
|
Chris@16
|
300
|
Chris@47
|
301 closeBundle();
|
Chris@47
|
302
|
Chris@16
|
303 Command *command = m_redoStack.top();
|
Chris@16
|
304 command->execute();
|
Chris@16
|
305 emit commandExecuted();
|
Chris@16
|
306 emit commandExecuted(command);
|
Chris@16
|
307
|
Chris@16
|
308 m_undoStack.push(command);
|
Chris@16
|
309 m_redoStack.pop();
|
Chris@16
|
310 // no need to clip
|
Chris@16
|
311
|
Chris@16
|
312 updateActions();
|
Chris@41
|
313
|
Chris@41
|
314 if ((int)m_undoStack.size() == m_savedAt) emit documentRestored();
|
Chris@16
|
315 }
|
Chris@16
|
316
|
Chris@16
|
317 void
|
Chris@17
|
318 CommandHistory::setUndoLimit(int limit)
|
Chris@16
|
319 {
|
Chris@16
|
320 if (limit > 0 && limit != m_undoLimit) {
|
Chris@16
|
321 m_undoLimit = limit;
|
Chris@16
|
322 clipCommands();
|
Chris@16
|
323 }
|
Chris@16
|
324 }
|
Chris@16
|
325
|
Chris@16
|
326 void
|
Chris@17
|
327 CommandHistory::setRedoLimit(int limit)
|
Chris@16
|
328 {
|
Chris@16
|
329 if (limit > 0 && limit != m_redoLimit) {
|
Chris@16
|
330 m_redoLimit = limit;
|
Chris@16
|
331 clipCommands();
|
Chris@16
|
332 }
|
Chris@16
|
333 }
|
Chris@16
|
334
|
Chris@16
|
335 void
|
Chris@46
|
336 CommandHistory::setMenuLimit(int limit)
|
Chris@46
|
337 {
|
Chris@46
|
338 m_menuLimit = limit;
|
Chris@46
|
339 updateActions();
|
Chris@46
|
340 }
|
Chris@46
|
341
|
Chris@46
|
342 void
|
Chris@47
|
343 CommandHistory::setBundleTimeout(int ms)
|
Chris@47
|
344 {
|
Chris@47
|
345 m_bundleTimeout = ms;
|
Chris@47
|
346 }
|
Chris@47
|
347
|
Chris@47
|
348 void
|
Chris@17
|
349 CommandHistory::documentSaved()
|
Chris@16
|
350 {
|
Chris@47
|
351 closeBundle();
|
Chris@16
|
352 m_savedAt = m_undoStack.size();
|
Chris@16
|
353 }
|
Chris@16
|
354
|
Chris@16
|
355 void
|
Chris@17
|
356 CommandHistory::clipCommands()
|
Chris@16
|
357 {
|
Chris@16
|
358 if ((int)m_undoStack.size() > m_undoLimit) {
|
Chris@16
|
359 m_savedAt -= (m_undoStack.size() - m_undoLimit);
|
Chris@16
|
360 }
|
Chris@16
|
361
|
Chris@16
|
362 clipStack(m_undoStack, m_undoLimit);
|
Chris@16
|
363 clipStack(m_redoStack, m_redoLimit);
|
Chris@16
|
364 }
|
Chris@16
|
365
|
Chris@16
|
366 void
|
Chris@17
|
367 CommandHistory::clipStack(CommandStack &stack, int limit)
|
Chris@16
|
368 {
|
Chris@16
|
369 int i;
|
Chris@16
|
370
|
Chris@16
|
371 if ((int)stack.size() > limit) {
|
Chris@16
|
372
|
Chris@16
|
373 CommandStack tempStack;
|
Chris@16
|
374
|
Chris@16
|
375 for (i = 0; i < limit; ++i) {
|
Chris@259
|
376 // Command *command = stack.top();
|
Chris@78
|
377 // std::cerr << "CommandHistory::clipStack: Saving recent command: " << command->getName().toLocal8Bit().data() << " at " << command << std::endl;
|
Chris@16
|
378 tempStack.push(stack.top());
|
Chris@16
|
379 stack.pop();
|
Chris@16
|
380 }
|
Chris@16
|
381
|
Chris@16
|
382 clearStack(stack);
|
Chris@16
|
383
|
Chris@16
|
384 for (i = 0; i < m_undoLimit; ++i) {
|
Chris@16
|
385 stack.push(tempStack.top());
|
Chris@16
|
386 tempStack.pop();
|
Chris@16
|
387 }
|
Chris@16
|
388 }
|
Chris@16
|
389 }
|
Chris@16
|
390
|
Chris@16
|
391 void
|
Chris@17
|
392 CommandHistory::clearStack(CommandStack &stack)
|
Chris@16
|
393 {
|
Chris@16
|
394 while (!stack.empty()) {
|
Chris@16
|
395 Command *command = stack.top();
|
Chris@46
|
396 // Not safe to call getName() on a command about to be deleted
|
Chris@117
|
397 // std::cerr << "CommandHistory::clearStack: About to delete command " << command << std::endl;
|
Chris@16
|
398 delete command;
|
Chris@16
|
399 stack.pop();
|
Chris@16
|
400 }
|
Chris@16
|
401 }
|
Chris@16
|
402
|
Chris@16
|
403 void
|
Chris@17
|
404 CommandHistory::undoActivated(QAction *action)
|
Chris@16
|
405 {
|
Chris@16
|
406 int pos = m_actionCounts[action];
|
Chris@16
|
407 for (int i = 0; i <= pos; ++i) {
|
Chris@16
|
408 undo();
|
Chris@16
|
409 }
|
Chris@16
|
410 }
|
Chris@16
|
411
|
Chris@16
|
412 void
|
Chris@17
|
413 CommandHistory::redoActivated(QAction *action)
|
Chris@16
|
414 {
|
Chris@16
|
415 int pos = m_actionCounts[action];
|
Chris@16
|
416 for (int i = 0; i <= pos; ++i) {
|
Chris@16
|
417 redo();
|
Chris@16
|
418 }
|
Chris@16
|
419 }
|
Chris@16
|
420
|
Chris@16
|
421 void
|
Chris@17
|
422 CommandHistory::updateActions()
|
Chris@16
|
423 {
|
Chris@16
|
424 m_actionCounts.clear();
|
Chris@16
|
425
|
Chris@16
|
426 for (int undo = 0; undo <= 1; ++undo) {
|
Chris@16
|
427
|
Chris@17
|
428 QAction *action(undo ? m_undoAction : m_redoAction);
|
Chris@17
|
429 QAction *menuAction(undo ? m_undoMenuAction : m_redoMenuAction);
|
Chris@16
|
430 QMenu *menu(undo ? m_undoMenu : m_redoMenu);
|
Chris@16
|
431 CommandStack &stack(undo ? m_undoStack : m_redoStack);
|
Chris@16
|
432
|
Chris@17
|
433 if (stack.empty()) {
|
Chris@17
|
434
|
Chris@17
|
435 QString text(undo ? tr("Nothing to undo") : tr("Nothing to redo"));
|
Chris@17
|
436
|
Chris@17
|
437 action->setEnabled(false);
|
Chris@17
|
438 action->setText(text);
|
Chris@17
|
439
|
Chris@17
|
440 menuAction->setEnabled(false);
|
Chris@17
|
441 menuAction->setText(text);
|
Chris@17
|
442
|
Chris@17
|
443 } else {
|
Chris@17
|
444
|
Chris@17
|
445 action->setEnabled(true);
|
Chris@17
|
446 menuAction->setEnabled(true);
|
Chris@17
|
447
|
Chris@17
|
448 QString commandName = stack.top()->getName();
|
Chris@17
|
449 commandName.replace(QRegExp("&"), "");
|
Chris@17
|
450
|
Chris@17
|
451 QString text = (undo ? tr("&Undo %1") : tr("Re&do %1"))
|
Chris@17
|
452 .arg(commandName);
|
Chris@17
|
453
|
Chris@17
|
454 action->setText(text);
|
Chris@17
|
455 menuAction->setText(text);
|
Chris@17
|
456 }
|
Chris@17
|
457
|
Chris@16
|
458 menu->clear();
|
Chris@16
|
459
|
Chris@16
|
460 CommandStack tempStack;
|
Chris@16
|
461 int j = 0;
|
Chris@16
|
462
|
Chris@46
|
463 while (j < m_menuLimit && !stack.empty()) {
|
Chris@16
|
464
|
Chris@16
|
465 Command *command = stack.top();
|
Chris@16
|
466 tempStack.push(command);
|
Chris@16
|
467 stack.pop();
|
Chris@16
|
468
|
Chris@17
|
469 QString commandName = command->getName();
|
Chris@16
|
470 commandName.replace(QRegExp("&"), "");
|
Chris@16
|
471
|
Chris@16
|
472 QString text;
|
Chris@16
|
473 if (undo) text = tr("&Undo %1").arg(commandName);
|
Chris@16
|
474 else text = tr("Re&do %1").arg(commandName);
|
Chris@16
|
475
|
Chris@16
|
476 QAction *action = menu->addAction(text);
|
Chris@16
|
477 m_actionCounts[action] = j++;
|
Chris@16
|
478 }
|
Chris@16
|
479
|
Chris@16
|
480 while (!tempStack.empty()) {
|
Chris@16
|
481 stack.push(tempStack.top());
|
Chris@16
|
482 tempStack.pop();
|
Chris@16
|
483 }
|
Chris@16
|
484 }
|
Chris@16
|
485 }
|
Chris@16
|
486
|