From 4b713fff3138a7cea908a85b58ed90cf99cfacd1 Mon Sep 17 00:00:00 2001 From: mpv Date: Mon, 9 Feb 2015 19:50:59 +0300 Subject: [PATCH] Make undo/redo lists stored/restored and managed correctly --- src/Model/Model_Document.cpp | 50 ++++++++++++++++++++++++++++-------- src/Model/Model_Document.h | 25 +++++++++++++++--- src/Model/Model_Session.cpp | 10 +++----- 3 files changed, 63 insertions(+), 22 deletions(-) diff --git a/src/Model/Model_Document.cpp b/src/Model/Model_Document.cpp index c923ee4ca..762dff5fa 100644 --- a/src/Model/Model_Document.cpp +++ b/src/Model/Model_Document.cpp @@ -291,7 +291,7 @@ void Model_Document::startOperation() { if (myDoc->HasOpenCommand()) { // start of nested command if (myDoc->CommitCommand()) { // commit the current: it will contain all nested after compactification - (*myTransactions.rbegin())++; // if has open command, the list is not empty + myTransactions.rbegin()->myOCAFNum++; // if has open command, the list is not empty } myNestedNum.push_back(0); // start of nested operation with zero transactions inside yet myDoc->OpenCommand(); @@ -299,7 +299,7 @@ void Model_Document::startOperation() myDoc->NewCommand(); } // starts a new operation - myTransactions.push_back(0); + myTransactions.push_back(Transaction()); if (!myNestedNum.empty()) (*myNestedNum.rbegin())++; myRedos.clear(); @@ -316,11 +316,11 @@ void Model_Document::compactNested() int aNumToCompact = *(myNestedNum.rbegin()); int aSumOfTransaction = 0; for(int a = 0; a < aNumToCompact; a++) { - aSumOfTransaction += *(myTransactions.rbegin()); + aSumOfTransaction += myTransactions.rbegin()->myOCAFNum; myTransactions.pop_back(); } // the latest transaction is the start of lower-level operation which startes the nested - *(myTransactions.rbegin()) += aSumOfTransaction; + myTransactions.rbegin()->myOCAFNum += aSumOfTransaction; myNestedNum.pop_back(); } } @@ -360,7 +360,7 @@ bool Model_Document::finishOperation() // transaction may be empty if this document was created during this transaction (create part) if (!myTransactions.empty() && myDoc->CommitCommand()) { // if commit is successfull, just increment counters - (*myTransactions.rbegin())++; + myTransactions.rbegin()->myOCAFNum++; aResult = true; } @@ -368,7 +368,7 @@ bool Model_Document::finishOperation() compactNested(); } if (!aResult && !myTransactions.empty() /* it can be for just created part document */) - aResult = *(myTransactions.rbegin()) != 0; + aResult = myTransactions.rbegin()->myOCAFNum != 0; if (!aResult && Model_Session::get()->moduleDocument().get() == this) { // nothing inside in all documents, so remove this transaction from the transactions list @@ -387,7 +387,7 @@ void Model_Document::abortOperation() myDoc->ClearRedos(); myRedos.clear(); } else { // abort the current - int aNumTransactions = *myTransactions.rbegin(); + int aNumTransactions = myTransactions.rbegin()->myOCAFNum; myTransactions.pop_back(); if (!myNestedNum.empty()) (*myNestedNum.rbegin())--; @@ -433,9 +433,9 @@ bool Model_Document::canUndo() void Model_Document::undoInternal(const bool theWithSubs, const bool theSynchronize) { - int aNumTransactions = *myTransactions.rbegin(); + int aNumTransactions = myTransactions.rbegin()->myOCAFNum; + myRedos.push_back(*myTransactions.rbegin()); myTransactions.pop_back(); - myRedos.push_back(aNumTransactions); if (!myNestedNum.empty()) (*myNestedNum.rbegin())--; // roll back the needed number of transactions @@ -475,9 +475,9 @@ void Model_Document::redo() { if (!myNestedNum.empty()) (*myNestedNum.rbegin())++; - int aNumRedos = *myRedos.rbegin(); + int aNumRedos = myRedos.rbegin()->myOCAFNum; + myTransactions.push_back(*myRedos.rbegin()); myRedos.pop_back(); - myTransactions.push_back(aNumRedos); for(int a = 0; a < aNumRedos; a++) myDoc->Redo(); @@ -489,6 +489,34 @@ void Model_Document::redo() subDoc(*aSubIter)->redo(); } +std::list Model_Document::undoList() const +{ + std::list aResult; + std::list::const_reverse_iterator aTrIter = myTransactions.crbegin(); + int aNumUndo = myTransactions.size(); + if (!myNestedNum.empty()) + aNumUndo = *myNestedNum.rbegin(); + for( ; aNumUndo > 0; aTrIter++, aNumUndo--) { + aResult.push_back(aTrIter->myId); + } + return aResult; +} + +std::list Model_Document::redoList() const +{ + std::list aResult; + std::list::const_reverse_iterator aTrIter = myRedos.crbegin(); + for( ; aTrIter != myRedos.crend(); aTrIter++) { + aResult.push_back(aTrIter->myId); + } + return aResult; +} + +void Model_Document::operationId(const std::string& theId) +{ + myTransactions.rbegin()->myId = theId; +} + /// Append to the array of references a new referenced label static void AddToRefArray(TDF_Label& theArrayLab, TDF_Label& theReferenced) { diff --git a/src/Model/Model_Document.h b/src/Model/Model_Document.h index cb99181f9..62bd3ad40 100644 --- a/src/Model/Model_Document.h +++ b/src/Model/Model_Document.h @@ -199,6 +199,15 @@ class Model_Document : public ModelAPI_Document //! The implementation of undo: with or without recoursive calls in the sub-documents void undoInternal(const bool theWithSubs, const bool theSynchronize); + //! Stores the Id of the current operation (normally is called for the root document) + void operationId(const std::string& theId); + + //! Returns the list of Ids of the operations that can be undoed (called for the root document) + std::list undoList() const; + + //! Returns the list of Ids of the operations that can be redoed (called for the root document) + std::list redoList() const; + friend class Model_Application; friend class Model_Session; friend class Model_Update; @@ -216,11 +225,19 @@ class Model_Document : public ModelAPI_Document /// the list is empty if not nested transaction is performed std::list myNestedNum; - /// transaction indexes (related to myTransactionsAfterSave) and number of real transactions + /// Information related to the every user-transaction + struct Transaction { + int myOCAFNum; ///< number of OCAF transactions related to each "this" transaction, may be 0 + std::string myId; ///< user-identifier string of transaction + /// default constructor with default Id + Transaction(): myOCAFNum(0), myId("") {} + }; + + /// transaction indexes (related to myTransactionsAfterSave) and info about the real transactions /// in myDocument connected to this operation (may be zero for empty transaction) - std::list myTransactions; - /// list of numbers of real document transactions undone (first is oldest undone) - std::list myRedos; + std::list myTransactions; + /// list of info about transactions undone (first is oldest undone) + std::list myRedos; /// All features managed by this document (not only in history of OB) /// For optimization mapped by labels NCollection_DataMap myObjs; diff --git a/src/Model/Model_Session.cpp b/src/Model/Model_Session.cpp index e9edb8856..8b81240a2 100644 --- a/src/Model/Model_Session.cpp +++ b/src/Model/Model_Session.cpp @@ -53,6 +53,7 @@ void Model_Session::closeAll() void Model_Session::startOperation(const std::string& theId) { ROOT_DOC->startOperation(); + ROOT_DOC->operationId(theId); static std::shared_ptr aStartedMsg (new Events_Message(Events_Loop::eventByName("StartOperation"))); Events_Loop::loop()->send(aStartedMsg); @@ -121,17 +122,12 @@ void Model_Session::redo() //! Returns stack of performed operations std::list Model_Session::undoList() { - std::list temp; - temp.push_front("Part"); - temp.push_front("Sketch"); - temp.push_front("Extrusion"); - return temp; + return ROOT_DOC->undoList(); } //! Returns stack of rolled back operations std::list Model_Session::redoList() { - std::list temp; - return temp; + return ROOT_DOC->redoList(); } FeaturePtr Model_Session::createFeature(string theFeatureID) -- 2.39.2