1 /* 2 * LibrePCB - Professional EDA for everyone! 3 * Copyright (C) 2013 LibrePCB Developers, see AUTHORS.md for contributors. 4 * https://librepcb.org/ 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 /******************************************************************************* 21 * Includes 22 ******************************************************************************/ 23 #include "undocommandgroup.h" 24 25 #include "scopeguardlist.h" 26 27 #include <QtCore> 28 29 /******************************************************************************* 30 * Namespace 31 ******************************************************************************/ 32 namespace librepcb { 33 34 /******************************************************************************* 35 * Constructors / Destructor 36 ******************************************************************************/ 37 UndoCommandGroup(const QString & text)38UndoCommandGroup::UndoCommandGroup(const QString& text) noexcept 39 : UndoCommand(text) { 40 } 41 ~UndoCommandGroup()42UndoCommandGroup::~UndoCommandGroup() noexcept { 43 // delete childs in reverse order 44 while (mChilds.count() > 0) { 45 delete mChilds.takeLast(); 46 } 47 } 48 49 /******************************************************************************* 50 * General Methods 51 ******************************************************************************/ 52 appendChild(UndoCommand * cmd)53bool UndoCommandGroup::appendChild(UndoCommand* cmd) { 54 // make sure "cmd" is deleted when going out of scope (e.g. because of an 55 // exception) 56 QScopedPointer<UndoCommand> cmdScopeGuard(cmd); 57 58 if ((!cmd) || (mChilds.contains(cmd)) || (wasEverReverted())) { 59 throw LogicError(__FILE__, __LINE__); 60 } 61 62 if (wasEverExecuted()) { 63 if (cmdScopeGuard->execute()) { // can throw 64 mChilds.append(cmdScopeGuard.take()); 65 return true; 66 } else { 67 cmdScopeGuard 68 ->undo(); // just to be sure the command has executed nothing... 69 } 70 } else { 71 mChilds.append(cmdScopeGuard.take()); 72 } 73 return false; 74 } 75 76 /******************************************************************************* 77 * Inherited from UndoCommand 78 ******************************************************************************/ 79 performExecute()80bool UndoCommandGroup::performExecute() { 81 bool modified = false; 82 ScopeGuardList sgl(mChilds.count()); 83 for (int i = 0; i < mChilds.count(); ++i) { // from bottom to top 84 UndoCommand* cmd = mChilds.at(i); 85 if (cmd->execute()) { 86 modified = true; 87 } 88 sgl.add([cmd]() { cmd->undo(); }); 89 } 90 sgl.dismiss(); 91 return modified; 92 } 93 performUndo()94void UndoCommandGroup::performUndo() { 95 ScopeGuardList sgl(mChilds.count()); 96 for (int i = mChilds.count() - 1; i >= 0; --i) { // from top to bottom 97 UndoCommand* cmd = mChilds.at(i); 98 cmd->undo(); 99 sgl.add([cmd]() { cmd->redo(); }); 100 } 101 sgl.dismiss(); 102 } 103 performRedo()104void UndoCommandGroup::performRedo() { 105 ScopeGuardList sgl(mChilds.count()); 106 for (int i = 0; i < mChilds.count(); ++i) { // from bottom to top 107 UndoCommand* cmd = mChilds.at(i); 108 cmd->redo(); 109 sgl.add([cmd]() { cmd->undo(); }); 110 } 111 sgl.dismiss(); 112 } 113 114 /******************************************************************************* 115 * Protected Methods 116 ******************************************************************************/ 117 execNewChildCmd(UndoCommand * cmd)118void UndoCommandGroup::execNewChildCmd(UndoCommand* cmd) { 119 QScopedPointer<UndoCommand> cmdScopeGuard(cmd); 120 121 if ((!cmd) || (mChilds.contains(cmd)) || (wasEverExecuted())) { 122 throw LogicError(__FILE__, __LINE__); 123 } 124 125 if (cmdScopeGuard->execute()) { // can throw 126 mChilds.append(cmdScopeGuard.take()); 127 } else { 128 cmdScopeGuard 129 ->undo(); // just to be sure the command has executed nothing... 130 } 131 } 132 133 /******************************************************************************* 134 * End of File 135 ******************************************************************************/ 136 137 } // namespace librepcb 138