annotate widgets/CommandHistory.cpp @ 1363:bbeffb29bf09

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