1 /* 2 # PostgreSQL Database Modeler (pgModeler) 3 # 4 # Copyright 2006-2020 - Raphael Araújo e Silva <raphael@pgmodeler.io> 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 version 3. 9 # 10 # This program is distributed in the hope that it will be useful, 11 # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 # GNU General Public License for more details. 14 # 15 # The complete text of GPLv3 is at LICENSE file on source code root directory. 16 # Also, you can get the complete GNU General Public License at <http://www.gnu.org/licenses/> 17 */ 18 19 /** 20 \ingroup libpgmodeler 21 \class OperationList 22 \brief Implements the operations to maintain a list of modifications made 23 by the user on database model objects. This class permits that user 24 undo / redo all the operations made. 25 \note <strong>Creation date:</strong> 17/07/2006 26 */ 27 28 #ifndef OPERATIONLIST_H 29 #define OPERATIONLIST_H 30 31 #include "databasemodel.h" 32 #include "pgmodelerns.h" 33 #include "operation.h" 34 35 class OperationList: public QObject { 36 private: 37 Q_OBJECT 38 39 //! \brief Inidcates that operation chaining is ignored temporarily 40 bool ignore_chain; 41 42 XmlParser *xmlparser; 43 44 //! \brief List of objects that were removed / modified on the model 45 vector<BaseObject *> object_pool; 46 47 /*! \brief List of objects that at the time of deletion from pool were still referenced 48 somehow on the model. The object is stored in this secondary list and 49 deleted when the whole list of operations is destroyed */ 50 vector<BaseObject *> not_removed_objs; 51 52 /*! \brief Stores the objects that were unallocated on the removeOperations() method. This maps 53 is used in order to avoid double delete on pointers. */ 54 map<BaseObject *, bool> unallocated_objs; 55 56 //! \brief Stores the operations executed by the user 57 vector<Operation *> operations; 58 59 //! \brief Database model that is linked with this operation list 60 DatabaseModel *model; 61 62 //! \brief Maximum number of stored operations (global) 63 static unsigned max_size; 64 65 /*! \brief Stores the type of chain to the next operation to be stored 66 in the list. This attribute is used in conjunction with the chaining 67 initialization / finalization methods. */ 68 unsigned next_op_chain; 69 70 //! \brief Current operation index 71 int current_index; 72 73 /*! \brief Validates operations by checking whether they have registered objects in the pool. 74 If found any operation whose object is not in the pool it will be removed 75 because an object outside the pool does not give a guarantee that is being 76 referenced in the model. */ 77 void validateOperations(); 78 79 //! \brief Checks whether the passed object is in the pool 80 bool isObjectOnPool(BaseObject *object); 81 82 //! \brief Adds the object on the pool according to the operation type passed 83 void addToPool(BaseObject *object, unsigned op_type); 84 85 /*! \brief Removes one object from the pool using its index and deallocating 86 it in case the object is not referenced on the model */ 87 void removeFromPool(unsigned obj_idx); 88 89 /*! \brief Executes the passed operation. The default behavior is the 'undo' if 90 the user passes the parameter 'redo=true' the method executes the 91 redo function */ 92 void executeOperation(Operation *operacao, bool redo); 93 94 //! \brief Returns the chain size from the current element 95 unsigned getChainSize(); 96 97 public: 98 OperationList(DatabaseModel *model); 99 virtual ~OperationList(); 100 101 /*! \brief Starts chaining operations. 102 This means that all operations added after calling this 103 method will be considered to be performed all at once 104 with a single call to the redoOperation / undoOperation methods */ 105 void startOperationChain(); 106 107 /*! \brief Finalizes the chaining marking the last operation on the list 108 as the end of operation chain */ 109 void finishOperationChain(); 110 111 /*! \brief Cancels the execution of operations in the form of chaining, 112 but if the list is open with chaining operations included will be chained too. 113 This method helps in situations where is necessary to remove operations or 114 execute them one by one but keeping the chaining created earlier. 115 116 Note: The user must cancel the annulment of chaining 117 to be able to finalize the operations chaining. If it does not 118 happens the operations will be created chained indefinitely */ 119 void ignoreOperationChain(bool value); 120 121 //! \brief Returns if the operation chaining where started 122 bool isOperationChainStarted(); 123 124 //! \brief Returns if an operation of the specified op_type is already registered for the object 125 bool isObjectRegistered(BaseObject *object, unsigned op_type); 126 127 //! \brief Undo the current operation on the list 128 void undoOperation(); 129 130 //! \brief Redo the current operation on the list 131 void redoOperation(); 132 133 //! \brief Removes all the operations from the list 134 void removeOperations(); 135 136 //! \brief Gets the data from the operation with specified index 137 void getOperationData(unsigned oper_idx, unsigned &oper_type, QString &obj_name, ObjectType &obj_type); 138 139 //! \brief Sets the maximum size for the list 140 static void setMaximumSize(unsigned max); 141 142 /*! \brief Registers in the list of operations that the passed object suffered some kind 143 of modification (modified, removed, inserted, moved) in addition the method stores 144 its original content. 145 This method should ALWAYS be called before the object in question 146 suffers any operation in the model. If this method is called after an operation on the 147 object the order of restoration / re-execution of operations can be broken and cause 148 segmentations fault. 149 150 In case of success this method returns an integer indicating the last registered operation ID */ 151 int registerObject(BaseObject *object, unsigned op_type, int object_idx=-1, BaseObject *parent_obj=nullptr); 152 153 //! \brief Gets the maximum size for the operation list 154 unsigned getMaximumSize(); 155 156 //! \brief Gets the current size for the operation list 157 unsigned getCurrentSize(); 158 159 //! \brief Gets the current operation index 160 int getCurrentIndex(); 161 162 //! \brief Returns if the list is prepared to execute redo operations 163 bool isRedoAvailable(); 164 165 //! \brief Returns if the list is prepared to execute undo operations 166 bool isUndoAvailable(); 167 168 /*! \brief Removes the last operation from the list. This method should be used with 169 care as it can break the chain of operations. It should be 170 used only when an exception is thrown after adding 171 some object on the list and if the user wants to discard this operation due 172 the thrown exception. If the last operation is part of a chain the entire chain 173 of operations is removed. 174 Warning: The execution of this method is different from the undo method because 175 the objects are removed pool but their states prior to adding it to the list are not 176 restored so this method can not be used deliberately. */ 177 void removeLastOperation(); 178 179 /*! \brief Updates the index of the object when it suffers a movement in the parente object. 180 Generally this method need not be called manually but in the case of table objects 181 (like columns, rules, constraints, indexes and triggers) which can be moved 182 (to have their position changed in the parent object). This method updates the index 183 of the object with the new value for the operations which refer the object is not 184 executed incorrectly using previous index */ 185 void updateObjectIndex(BaseObject *object, unsigned new_idx); 186 }; 187 188 #endif 189