X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_Document.cpp;h=ec10e79632777634a6ca203b35b9d2f7edced0b1;hb=4b07d0ae015bc7ed510f8795d9d57d408e0367eb;hp=65d4cb70bb76d66c9d87d07d71f9dcbe82702e46;hpb=6858382d5642a83e6345a32bba1b8b74ec8144df;p=modules%2Fshaper.git diff --git a/src/Model/Model_Document.cpp b/src/Model/Model_Document.cpp index 65d4cb70b..ec10e7963 100644 --- a/src/Model/Model_Document.cpp +++ b/src/Model/Model_Document.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -155,10 +156,14 @@ bool Model_Document::load(const char* theFileName) if (!isError) { myDoc->SetUndoLimit(UNDO_LIMIT); // to avoid the problem that feature is created in the current, not this, document - Model_Session::get()->setActiveDocument(anApp->getDocument(myID), false); + std::shared_ptr aSession = + std::dynamic_pointer_cast(Model_Session::get()); + aSession->setActiveDocument(anApp->getDocument(myID), false); + aSession->setCheckTransactions(false); synchronizeFeatures(false, true); - Model_Session::get()->setActiveDocument(Model_Session::get()->moduleDocument(), false); - Model_Session::get()->setActiveDocument(anApp->getDocument(myID), true); + aSession->setCheckTransactions(true); + aSession->setActiveDocument(Model_Session::get()->moduleDocument(), false); + aSession->setActiveDocument(anApp->getDocument(myID), true); } return !isError; } @@ -237,6 +242,9 @@ void Model_Document::close(const bool theForever) std::shared_ptr aPM = Model_Session::get(); if (this != aPM->moduleDocument().get() && this == aPM->activeDocument().get()) { aPM->setActiveDocument(aPM->moduleDocument()); + } else if (this == aPM->moduleDocument().get()) { + // erase the active document if root is closed + aPM->setActiveDocument(DocumentPtr()); } // close all subs const std::set aSubs = subDocuments(true); @@ -317,15 +325,11 @@ void Model_Document::compactNested() } } -void Model_Document::finishOperation() +bool Model_Document::finishOperation() { bool isNestedClosed = !myDoc->HasOpenCommand() && !myNestedNum.empty(); static std::shared_ptr aSession = std::static_pointer_cast(Model_Session::get()); - // just to be sure that everybody knows that changes were performed - if (isNestedClosed) { - aSession->setCheckTransactions(false); // for nested transaction commit - } synchronizeBackRefs(); Events_Loop* aLoop = Events_Loop::loop(); aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED)); @@ -346,30 +350,40 @@ void Model_Document::finishOperation() // to avoid "updated" message appearance by updater //aLoop->clear(Events_Loop::eventByName(EVENT_OBJECT_UPDATED)); - if (isNestedClosed) { - aSession->setCheckTransactions(true); // for nested transaction commit - } - // finish for all subs first: to avoid nested finishing and "isOperation" calls problems inside + bool aResult = false; const std::set aSubs = subDocuments(true); std::set::iterator aSubIter = aSubs.begin(); for (; aSubIter != aSubs.end(); aSubIter++) - subDoc(*aSubIter)->finishOperation(); + if (subDoc(*aSubIter)->finishOperation()) + aResult = true; - if (myDoc->CommitCommand()) { // if commit is successfull, just increment counters + // 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())++; + aResult = true; } if (isNestedClosed) { compactNested(); } + if (!aResult && !myTransactions.empty() /* it can be for just created part document */) + aResult = *(myTransactions.rbegin()) != 0; + + if (!aResult && Model_Session::get()->moduleDocument().get() == this) { + // nothing inside in all documents, so remove this transaction from the transactions list + undoInternal(true, false); + myDoc->ClearRedos(); + myRedos.clear(); + } + return aResult; } void Model_Document::abortOperation() { if (!myNestedNum.empty() && !myDoc->HasOpenCommand()) { // abort all what was done in nested compactNested(); - undo(); + undoInternal(false, false); myDoc->ClearRedos(); myRedos.clear(); } else { // abort the current @@ -417,7 +431,7 @@ bool Model_Document::canUndo() return false; } -void Model_Document::undo() +void Model_Document::undoInternal(const bool theWithSubs, const bool theSynchronize) { int aNumTransactions = *myTransactions.rbegin(); myTransactions.pop_back(); @@ -428,12 +442,20 @@ void Model_Document::undo() for(int a = 0; a < aNumTransactions; a++) myDoc->Undo(); - synchronizeFeatures(true, true); - // undo for all subs - const std::set aSubs = subDocuments(true); - std::set::iterator aSubIter = aSubs.begin(); - for (; aSubIter != aSubs.end(); aSubIter++) - subDoc(*aSubIter)->undo(); + if (theSynchronize) + synchronizeFeatures(true, true); + if (theWithSubs) { + // undo for all subs + const std::set aSubs = subDocuments(true); + std::set::iterator aSubIter = aSubs.begin(); + for (; aSubIter != aSubs.end(); aSubIter++) + subDoc(*aSubIter)->undoInternal(theWithSubs, theSynchronize); + } +} + +void Model_Document::undo() +{ + undoInternal(true, true); } bool Model_Document::canRedo() @@ -805,8 +827,6 @@ void Model_Document::synchronizeFeatures(const bool theMarkUpdated, const bool t std::shared_ptr aThis = Model_Application::getApplication()->getDocument(myID); // after all updates, sends a message that groups of features were created or updated - std::static_pointer_cast(Model_Session::get()) - ->setCheckTransactions(false); Events_Loop* aLoop = Events_Loop::loop(); aLoop->activateFlushes(false); @@ -844,14 +864,21 @@ void Model_Document::synchronizeFeatures(const bool theMarkUpdated, const bool t } } // update results of thefeatures (after features created because they may be connected, like sketch and sub elements) + std::list aComposites; // composites must be updated after their subs (issue 360) TDF_ChildIDIterator aLabIter2(featuresLabel(), TDataStd_Comment::GetID()); for (; aLabIter2.More(); aLabIter2.Next()) { TDF_Label aFeatureLabel = aLabIter2.Value()->Label(); if (myObjs.IsBound(aFeatureLabel)) { // a new feature is inserted FeaturePtr aFeature = myObjs.Find(aFeatureLabel); + if (std::dynamic_pointer_cast(aFeature).get()) + aComposites.push_back(aFeature); updateResults(aFeature); } } + std::list::iterator aComposite = aComposites.begin(); + for(; aComposite != aComposites.end(); aComposite++) { + updateResults(*aComposite); + } // check all features are checked: if not => it was removed NCollection_DataMap::Iterator aFIter(myObjs); @@ -871,9 +898,9 @@ void Model_Document::synchronizeFeatures(const bool theMarkUpdated, const bool t ModelAPI_EventCreator::get()->sendUpdated(aFeature, EVENT_DISP); aFeature->erase(); // unbind after the "erase" call: on abort sketch is removes sub-objects that corrupts aFIter - TDF_Label aLab = aFIter.Key(); - aFIter.Next(); - myObjs.UnBind(aLab); + myObjs.UnBind(aFIter.Key()); + // reinitialize iterator because unbind may corrupt the previous order in the map + aFIter.Initialize(myObjs); } else aFIter.Next(); } @@ -890,8 +917,6 @@ void Model_Document::synchronizeFeatures(const bool theMarkUpdated, const bool t aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED)); aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); aLoop->flush(Events_Loop::eventByName(EVENT_OBJECT_TOHIDE)); - std::static_pointer_cast(Model_Session::get()) - ->setCheckTransactions(true); myExecuteFeatures = true; }