X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_Document.cpp;h=e0ae73e76109b438637f051a4f49870317863581;hb=7cb6ac084270943d926ec7ef35bf9e63d6a3eaf5;hp=b160e375259d2b04afbf57cac3d00620ab834600;hpb=470905ace04b0b7345038bb2277050a6c8fcc585;p=modules%2Fshaper.git diff --git a/src/Model/Model_Document.cpp b/src/Model/Model_Document.cpp index b160e3752..e0ae73e76 100644 --- a/src/Model/Model_Document.cpp +++ b/src/Model/Model_Document.cpp @@ -28,8 +28,13 @@ #include #include #include +#include #include #include +#include +#include +#include +#include #include #ifndef WIN32 @@ -63,6 +68,8 @@ Model_Document::Model_Document(const std::string theID, const std::string theKin // in transaction for nesting correct working myDoc->NewCommand(); TDataStd_Integer::Set(myDoc->Main().Father(), 0); + // this to avoid creation of integer attribute outside the transaction after undo + transactionID(); myDoc->CommitCommand(); } @@ -98,8 +105,9 @@ bool Model_Document::load(const char* theFileName, DocumentPtr theThis) } TCollection_ExtendedString aPath(DocFileName(theFileName, myID)); PCDM_ReaderStatus aStatus = (PCDM_ReaderStatus) -1; + Handle(TDocStd_Document) aLoaded; try { - aStatus = anApp->Open(aPath, myDoc); + aStatus = anApp->Open(aPath, aLoaded); } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); Events_Error::send( @@ -160,11 +168,12 @@ bool Model_Document::load(const char* theFileName, DocumentPtr theThis) break; } } + std::shared_ptr aSession = + std::dynamic_pointer_cast(Model_Session::get()); if (!isError) { + myDoc = aLoaded; myDoc->SetUndoLimit(UNDO_LIMIT); // to avoid the problem that feature is created in the current, not this, document - std::shared_ptr aSession = - std::dynamic_pointer_cast(Model_Session::get()); aSession->setActiveDocument(anApp->getDocument(myID), false); aSession->setCheckTransactions(false); if (myObjs) @@ -177,7 +186,9 @@ bool Model_Document::load(const char* theFileName, DocumentPtr theThis) aSession->setActiveDocument(Model_Session::get()->moduleDocument(), false); // this is done in Part result "activate", so no needed here. Causes not-blue active part. // aSession->setActiveDocument(anApp->getDocument(myID), true); - } + } else { // open failed, but new documnet was created to work with it: inform the model + aSession->setActiveDocument(Model_Session::get()->moduleDocument(), false); + } return !isError; } @@ -273,6 +284,7 @@ void Model_Document::close(const bool theForever) // close all only if it is really asked, otherwise it can be undoed/redoed if (theForever) { + // flush everything to avoid messages with bad objects delete myObjs; myObjs = 0; if (myDoc->CanClose() == CDM_CCS_OK) @@ -383,10 +395,41 @@ bool Model_Document::finishOperation() return aResult; } +/// Returns in theDelta labels that has been modified in the latest transaction of theDoc +static void modifiedLabels(const Handle(TDocStd_Document)& theDoc, TDF_LabelList& theDelta, + const bool isRedo = false) { + Handle(TDF_Delta) aDelta; + if (isRedo) + aDelta = theDoc->GetRedos().First(); + else + aDelta = theDoc->GetUndos().Last(); + TDF_LabelList aDeltaList; + aDelta->Labels(aDeltaList); // it clears list, so, use new one and then append to the result + for(TDF_ListIteratorOfLabelList aListIter(aDeltaList); aListIter.More(); aListIter.Next()) { + theDelta.Append(aListIter.Value()); + } + // add also label of the modified attributes + const TDF_AttributeDeltaList& anAttrs = aDelta->AttributeDeltas(); + for (TDF_ListIteratorOfAttributeDeltaList anAttr(anAttrs); anAttr.More(); anAttr.Next()) { + theDelta.Append(anAttr.Value()->Label()); + } +} + void Model_Document::abortOperation() { + TDF_LabelList aDeltaLabels; // labels that are updated during "abort" if (!myNestedNum.empty() && !myDoc->HasOpenCommand()) { // abort all what was done in nested compactNested(); + // store undo-delta here as undo actually does in the method later + int a, aNumTransactions = myTransactions.rbegin()->myOCAFNum; + for(a = 0; a < aNumTransactions; a++) { + modifiedLabels(myDoc, aDeltaLabels); + myDoc->Undo(); + } + for(a = 0; a < aNumTransactions; a++) { + myDoc->Redo(); + } + undoInternal(false, false); myDoc->ClearRedos(); myRedos.clear(); @@ -396,9 +439,16 @@ void Model_Document::abortOperation() if (!myNestedNum.empty()) (*myNestedNum.rbegin())--; // roll back the needed number of transactions - myDoc->AbortCommand(); - for(int a = 0; a < aNumTransactions; a++) + // make commit/undo to get the modification delta + //myDoc->AbortCommand(); + if (myDoc->CommitCommand()) { + modifiedLabels(myDoc, aDeltaLabels); + myDoc->Undo(); + } + for(int a = 0; a < aNumTransactions; a++) { + modifiedLabels(myDoc, aDeltaLabels); myDoc->Undo(); + } myDoc->ClearRedos(); } // abort for all subs, flushes will be later, in the end of root abort @@ -407,7 +457,7 @@ void Model_Document::abortOperation() for (; aSubIter != aSubs.end(); aSubIter++) subDoc(*aSubIter)->abortOperation(); // references may be changed because they are set in attributes on the fly - myObjs->synchronizeFeatures(true, true, isRoot()); + myObjs->synchronizeFeatures(aDeltaLabels, true, isRoot()); } bool Model_Document::isOperation() const @@ -452,8 +502,12 @@ void Model_Document::undoInternal(const bool theWithSubs, const bool theSynchron if (!myNestedNum.empty()) (*myNestedNum.rbegin())--; // roll back the needed number of transactions - for(int a = 0; a < aNumTransactions; a++) + TDF_LabelList aDeltaLabels; + for(int a = 0; a < aNumTransactions; a++) { + if (theSynchronize) + modifiedLabels(myDoc, aDeltaLabels); myDoc->Undo(); + } if (theWithSubs) { // undo for all subs @@ -465,9 +519,9 @@ void Model_Document::undoInternal(const bool theWithSubs, const bool theSynchron subDoc(*aSubIter)->undoInternal(theWithSubs, theSynchronize); } } - // after redo of all sub-documents to avoid updates on not-modified data (issue 370) + // after undo of all sub-documents to avoid updates on not-modified data (issue 370) if (theSynchronize) { - myObjs->synchronizeFeatures(true, true, isRoot()); + myObjs->synchronizeFeatures(aDeltaLabels, true, isRoot()); // update the current features status setCurrentFeature(currentFeature(false), false); } @@ -501,8 +555,11 @@ void Model_Document::redo() int aNumRedos = myRedos.rbegin()->myOCAFNum; myTransactions.push_back(*myRedos.rbegin()); myRedos.pop_back(); - for(int a = 0; a < aNumRedos; a++) + TDF_LabelList aDeltaLabels; + for(int a = 0; a < aNumRedos; a++) { + modifiedLabels(myDoc, aDeltaLabels, true); myDoc->Redo(); + } // redo for all subs const std::set aSubs = subDocuments(true); @@ -511,7 +568,7 @@ void Model_Document::redo() subDoc(*aSubIter)->redo(); // after redo of all sub-documents to avoid updates on not-modified data (issue 370) - myObjs->synchronizeFeatures(true, true, isRoot()); + myObjs->synchronizeFeatures(aDeltaLabels, true, isRoot()); // update the current features status setCurrentFeature(currentFeature(false), false); } @@ -554,6 +611,7 @@ FeaturePtr Model_Document::addFeature(std::string theID, const bool theMakeCurre FeaturePtr aFeature = aSession->createFeature(theID, this); if (!aFeature) return aFeature; + aFeature->init(); Model_Document* aDocToAdd; if (!aFeature->documentToAdd().empty()) { // use the customized document to add if (aFeature->documentToAdd() != kind()) { // the root document by default @@ -565,7 +623,24 @@ FeaturePtr Model_Document::addFeature(std::string theID, const bool theMakeCurre aDocToAdd = this; } if (aFeature) { - aDocToAdd->myObjs->addFeature(aFeature, aDocToAdd->currentFeature(false)); + // searching for feature after which must be added the next feature: this is the current feature + // but also all sub-features of this feature + FeaturePtr aCurrent = aDocToAdd->currentFeature(false); + bool isModified = true; + for(CompositeFeaturePtr aComp = std::dynamic_pointer_cast(aCurrent); + aComp.get() && isModified; + aComp = std::dynamic_pointer_cast(aCurrent)) { + isModified = false; + int aSubs = aComp->numberOfSubs(false); + for(int a = 0; a < aSubs; a++) { + FeaturePtr aSub = aComp->subFeature(a, false); + if (myObjs->isLater(aSub, aCurrent)) { + isModified = true; + aCurrent = aSub; + } + } + } + aDocToAdd->myObjs->addFeature(aFeature, aCurrent); if (!aFeature->isAction()) { // do not add action to the data model if (theMakeCurrent) // after all this feature stays in the document, so make it current aDocToAdd->setCurrentFeature(aFeature, false); @@ -592,6 +667,8 @@ void Model_Document::removeFeature(FeaturePtr theFeature) void Model_Document::moveFeature(FeaturePtr theMoved, FeaturePtr theAfterThis) { myObjs->moveFeature(theMoved, theAfterThis); + if (theAfterThis == currentFeature(true)) + setCurrentFeature(theMoved, true); } void Model_Document::updateHistory(const std::shared_ptr theObject) @@ -617,8 +694,9 @@ const std::set Model_Document::subDocuments(const bool theActivated std::list::iterator aPartRes = aPartResults.begin(); for(; aPartRes != aPartResults.end(); aPartRes++) { ResultPartPtr aPart = std::dynamic_pointer_cast(*aPartRes); - if (aPart && (!theActivatedOnly || aPart->isActivated())) - aResult.insert(aPart->data()->name()); + if (aPart && (!theActivatedOnly || aPart->isActivated())) { + aResult.insert(aPart->original()->data()->name()); + } } return aResult; } @@ -671,8 +749,8 @@ std::shared_ptr Model_Document::currentFeature(const bool theV return std::shared_ptr(); // null feature means the higher than first } -void Model_Document::setCurrentFeature(std::shared_ptr theCurrent, - const bool theVisible) +void Model_Document::setCurrentFeature( + std::shared_ptr theCurrent, const bool theVisible) { // blocks the flush signals to avoid each objects visualization in the viewer // they should not be shown once after all modifications are performed @@ -766,10 +844,6 @@ void Model_Document::setCurrentFeature(std::shared_ptr theCurr } // unblock the flush signals and up them after this aLoop->activateFlushes(isActive); - - aLoop->flush(aCreateEvent); - aLoop->flush(aRedispEvent); - aLoop->flush(aDeleteEvent); } void Model_Document::setCurrentFeatureUp() @@ -779,6 +853,7 @@ void Model_Document::setCurrentFeatureUp() FeaturePtr aCurrent = currentFeature(false); if (aCurrent.get()) { // if not, do nothing because null is the upper FeaturePtr aPrev = myObjs->nextFeature(aCurrent, true); + // do not flush: it is called only on remove, it will be flushed in the end of transaction setCurrentFeature(aPrev, false); } } @@ -800,12 +875,6 @@ std::shared_ptr Model_Document::createBody( return myObjs->createBody(theFeatureData, theIndex); } -std::shared_ptr Model_Document::createCompSolid( - const std::shared_ptr& theFeatureData, const int theIndex) -{ - return myObjs->createCompSolid(theFeatureData, theIndex); -} - std::shared_ptr Model_Document::createPart( const std::shared_ptr& theFeatureData, const int theIndex) { @@ -813,11 +882,10 @@ std::shared_ptr Model_Document::createPart( } std::shared_ptr Model_Document::copyPart( - const std::shared_ptr& theOldPart, - const std::shared_ptr& theOrigin, - const int theIndex) + const std::shared_ptr& theOrigin, + const std::shared_ptr& theFeatureData, const int theIndex) { - return myObjs->copyPart(theOldPart, theOrigin, theIndex); + return myObjs->copyPart(theOrigin, theFeatureData, theIndex); } std::shared_ptr Model_Document::createGroup( @@ -835,12 +903,7 @@ std::shared_ptr Model_Document::createParameter( std::shared_ptr Model_Document::feature( const std::shared_ptr& theResult) { - std::shared_ptr aData = std::dynamic_pointer_cast(theResult->data()); - if (aData) { - TDF_Label aFeatureLab = aData->label().Father().Father().Father(); - return myObjs->feature(aFeatureLab); - } - return FeaturePtr(); + return myObjs->feature(theResult); } Standard_Integer HashCode(const TDF_Label& theLab, const Standard_Integer theUpper) @@ -939,7 +1002,27 @@ std::shared_ptr Model_Document::internalFeature(const int theI return myObjs->internalFeature(theIndex); } -// Feature that is used for selection in the Part document by the external request +void Model_Document::synchronizeTransactions() +{ + Model_Document* aRoot = + std::dynamic_pointer_cast(ModelAPI_Session::get()->moduleDocument()).get(); + if (aRoot == this) + return; // don't need to synchronise root with root + + std::shared_ptr aSession = + std::dynamic_pointer_cast(Model_Session::get()); + while(myRedos.size() > aRoot->myRedos.size()) { // remove redos in this + aSession->setCheckTransactions(false); + redo(); + aSession->setCheckTransactions(true); + } + /* this case can not be reproduced in any known case for the current moment, so, just comment + while(myRedos.size() < aRoot->myRedos.size()) { // add more redos in this + undoInternal(false, true); + }*/ +} + +/// Feature that is used for selection in the Part document by the external request class Model_SelectionInPartFeature : public ModelAPI_Feature { public: /// Nothing to do in constructor