X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_Document.cpp;h=d9905674765c0b51a5160b603ac36c6f21124c49;hb=46a28bd54e9ce0937d87d305202ab6912c1f5cd2;hp=f1f10b103763dca05342c19888f0d014678b9146;hpb=f37788c806a371d84963c1fd72e1a2050258372b;p=modules%2Fshaper.git diff --git a/src/Model/Model_Document.cpp b/src/Model/Model_Document.cpp index f1f10b103..d99056747 100644 --- a/src/Model/Model_Document.cpp +++ b/src/Model/Model_Document.cpp @@ -156,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; } @@ -238,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); @@ -318,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)); @@ -347,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(); - undoInternal(false); + undoInternal(false, false); myDoc->ClearRedos(); myRedos.clear(); } else { // abort the current @@ -418,7 +431,7 @@ bool Model_Document::canUndo() return false; } -void Model_Document::undoInternal(const bool theWithSubs) +void Model_Document::undoInternal(const bool theWithSubs, const bool theSynchronize) { int aNumTransactions = *myTransactions.rbegin(); myTransactions.pop_back(); @@ -429,19 +442,20 @@ void Model_Document::undoInternal(const bool theWithSubs) for(int a = 0; a < aNumTransactions; a++) myDoc->Undo(); - if (theWithSubs) { + 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)->undo(); + subDoc(*aSubIter)->undoInternal(theWithSubs, theSynchronize); } } void Model_Document::undo() { - undoInternal(true); + undoInternal(true, true); } bool Model_Document::canRedo() @@ -560,22 +574,48 @@ static int RemoveFromRefArray(TDF_Label theArrayLab, TDF_Label theReferenced, co return aResult; } -void Model_Document::removeFeature(FeaturePtr theFeature, const bool theCheck) +void Model_Document::refsToFeature(FeaturePtr theFeature, + std::set >& theRefs, + const bool isSendError) { - if (theCheck) { - // check the feature: it must have no depended objects on it - std::list::const_iterator aResIter = theFeature->results().cbegin(); - for(; aResIter != theFeature->results().cend(); aResIter++) { - std::shared_ptr aData = - std::dynamic_pointer_cast((*aResIter)->data()); - if (aData && !aData->refsToMe().empty()) { - Events_Error::send( - "Feature '" + theFeature->data()->name() + "' is used and can not be deleted"); - return; + // check the feature: it must have no depended objects on it + // the dependencies can be in the feature results + std::list::const_iterator aResIter = theFeature->results().cbegin(); + for(; aResIter != theFeature->results().cend(); aResIter++) { + ResultPtr aResult = (*aResIter); + std::shared_ptr aData = + std::dynamic_pointer_cast(aResult->data()); + if (aData.get() != NULL) { + const std::set& aRefs = aData->refsToMe(); + std::set::const_iterator aRefIt = aRefs.begin(), aRefLast = aRefs.end(); + for(; aRefIt != aRefLast; aRefIt++) { + FeaturePtr aFeature = std::dynamic_pointer_cast((*aRefIt)->owner()); + if (aFeature.get() != NULL) + theRefs.insert(aFeature); + } + + if (!aRefs.empty()) { + FeaturePtr aFeature = ModelAPI_Feature::feature(aResult); + if (aFeature.get() != NULL) + theRefs.insert(aFeature); } } } + // the dependencies can be in the feature itself + std::shared_ptr aData = + std::dynamic_pointer_cast(theFeature->data()); + if (aData && !aData->refsToMe().empty()) { + theRefs.insert(theFeature); + } + + if (!theRefs.empty() && isSendError) { + Events_Error::send( + "Feature '" + theFeature->data()->name() + "' is used and can not be deleted"); + } +} +void Model_Document::removeFeature(FeaturePtr theFeature/*, const bool theCheck*/) +{ std::shared_ptr aData = std::static_pointer_cast(theFeature->data()); if (aData) { TDF_Label aFeatureLabel = aData->label().Father(); @@ -813,8 +853,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); @@ -886,9 +924,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(); } @@ -905,8 +943,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; }