annotate widgets/CommandHistory.cpp @ 1615:911330a28a7c

Where the "below" view represents only a subset of the "above" view, cut off the feature mappings at the outer edges of the "below" view - don't map everything outside this (it would all just map onto the same single points at beginning and end, which is excessive, confusing and not useful)
author Chris Cannam
date Thu, 02 Jul 2020 15:37:43 +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