annotate widgets/CommandHistory.cpp @ 1613:fe9a643b83bf

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