{
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();
myDoc->NewCommand();
}
// starts a new operation
- myTransactions.push_back(0);
+ myTransactions.push_back(Transaction());
if (!myNestedNum.empty())
(*myNestedNum.rbegin())++;
myRedos.clear();
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();
}
}
// 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;
}
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
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())--;
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
{
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();
subDoc(*aSubIter)->redo();
}
+std::list<std::string> Model_Document::undoList() const
+{
+ std::list<std::string> aResult;
+ std::list<Transaction>::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<std::string> Model_Document::redoList() const
+{
+ std::list<std::string> aResult;
+ std::list<Transaction>::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)
{
//! 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<std::string> undoList() const;
+
+ //! Returns the list of Ids of the operations that can be redoed (called for the root document)
+ std::list<std::string> redoList() const;
+
friend class Model_Application;
friend class Model_Session;
friend class Model_Update;
/// the list is empty if not nested transaction is performed
std::list<int> 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<int> myTransactions;
- /// list of numbers of real document transactions undone (first is oldest undone)
- std::list<int> myRedos;
+ std::list<Transaction> myTransactions;
+ /// list of info about transactions undone (first is oldest undone)
+ std::list<Transaction> myRedos;
/// All features managed by this document (not only in history of OB)
/// For optimization mapped by labels
NCollection_DataMap<TDF_Label, FeaturePtr> myObjs;
void Model_Session::startOperation(const std::string& theId)
{
ROOT_DOC->startOperation();
+ ROOT_DOC->operationId(theId);
static std::shared_ptr<Events_Message> aStartedMsg
(new Events_Message(Events_Loop::eventByName("StartOperation")));
Events_Loop::loop()->send(aStartedMsg);
//! Returns stack of performed operations
std::list<std::string> Model_Session::undoList()
{
- std::list<std::string> 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<std::string> Model_Session::redoList()
{
- std::list<std::string> temp;
- return temp;
+ return ROOT_DOC->redoList();
}
FeaturePtr Model_Session::createFeature(string theFeatureID)