X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_Objects.cpp;h=0b7678a5d532144cacb2b60ed48d64fe43b01631;hb=8193b76f73047e852eaecfb4c0ff86cf44e1f8c9;hp=87848db8410b9d1cf6944865403f915a564819ad;hpb=8c9e4d2c24439731a871adbbac624d75e201e2d1;p=modules%2Fshaper.git diff --git a/src/Model/Model_Objects.cpp b/src/Model/Model_Objects.cpp index 87848db84..0b7678a5d 100644 --- a/src/Model/Model_Objects.cpp +++ b/src/Model/Model_Objects.cpp @@ -20,7 +20,7 @@ #include #include -#include +#include #include #include @@ -54,7 +54,7 @@ void Model_Objects::setOwner(DocumentPtr theDoc) myDoc = theDoc; // update all fields and recreate features and result objects if needed TDF_LabelList aNoUpdated; - synchronizeFeatures(aNoUpdated, true, true); + synchronizeFeatures(aNoUpdated, true, true, true); myHistory.clear(); } @@ -139,13 +139,19 @@ void Model_Objects::addFeature(FeaturePtr theFeature, const FeaturePtr theAfterT myFeatures.Bind(aFeatureLab, theFeature); // must be before the event sending: for OB the feature is already added updateHistory(ModelAPI_Feature::group()); + // do not change the order: + // initData() + // sendUpdated() + // during python script with fillet constraint feature data should be + // initialized before using it in GUI + + // must be after binding to the map because of "Box" macro feature that + // creates other features in "initData" + initData(theFeature, aFeatureLab, TAG_FEATURE_ARGUMENTS); // event: feature is added, mist be before "initData" to update OB correctly on Duplicate: // first new part, then the content static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED); ModelAPI_EventCreator::get()->sendUpdated(theFeature, anEvent); - // must be after binding to the map because of "Box" macro feature that - // creates other features in "initData" - initData(theFeature, aFeatureLab, TAG_FEATURE_ARGUMENTS); } else { // make feature has not-null data anyway theFeature->setData(Model_Data::invalidData()); theFeature->setDoc(myDoc); @@ -189,8 +195,10 @@ void Model_Objects::refsToFeature(FeaturePtr theFeature, { // 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++) { + std::list aResults; + ModelAPI_Tools::allResults(theFeature, aResults); + std::list::const_iterator aResIter = aResults.cbegin(); + for (; aResIter != aResults.cend(); aResIter++) { ResultPtr aResult = (*aResIter); std::shared_ptr aData = std::dynamic_pointer_cast(aResult->data()); @@ -218,8 +226,8 @@ void Model_Objects::refsToFeature(FeaturePtr theFeature, } if (!theRefs.empty() && isSendError) { - Events_Error::send( - "Feature '" + theFeature->data()->name() + "' is used and can not be deleted"); + Events_InfoMessage("Model_Objects", + "Feature '%1' is used and can not be deleted").arg(theFeature->data()->name()).send(); } } @@ -234,7 +242,7 @@ void Model_Objects::removeFeature(FeaturePtr theFeature) for(; aRefIter != aRefs.end(); aRefIter++) { std::shared_ptr aComposite = std::dynamic_pointer_cast(*aRefIter); - if (aComposite.get()) { + if (aComposite.get() && aComposite->isSub(theFeature)) { aComposite->removeFeature(theFeature); } } @@ -257,8 +265,6 @@ void Model_Objects::removeFeature(FeaturePtr theFeature) RemoveFromRefArray(featuresLabel(), aFeatureLabel); // event: feature is deleted ModelAPI_EventCreator::get()->sendDeleted(theFeature->document(), ModelAPI_Feature::group()); - // the redisplay signal should be flushed in order to erase the feature presentation in the viewer - Events_Loop::loop()->flush(EVENT_DISP); updateHistory(ModelAPI_Feature::group()); } } @@ -298,10 +304,10 @@ void Model_Objects::moveFeature(FeaturePtr theMoved, FeaturePtr theAfterThis) if (!aPassedMovedFrom || !aPassedMovedTo) {// not found: unknown situation if (!aPassedMovedFrom) { static std::string aMovedFromError("The moved feature is not found"); - Events_Error::send(aMovedFromError); + Events_InfoMessage("Model_Objects", aMovedFromError).send(); } else { static std::string aMovedToError("The 'after' feature for movement is not found"); - Events_Error::send(aMovedToError); + Events_InfoMessage("Model_Objects", aMovedToError).send(); } return; } @@ -310,10 +316,9 @@ void Model_Objects::moveFeature(FeaturePtr theMoved, FeaturePtr theAfterThis) // update the feature and the history clearHistory(theMoved); // make sure all (selection) attributes of moved feature will be updated - theMoved->data()->setUpdateID(0); - static Events_ID EVENT_UPD = Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED); - ModelAPI_EventCreator::get()->sendUpdated(theMoved, EVENT_UPD); - ModelAPI_EventCreator::get()->sendReordered(theMoved->document(), theMoved->groupName()); + static Events_ID kUpdateSelection = Events_Loop::loop()->eventByName(EVENT_UPDATE_SELECTION); + ModelAPI_EventCreator::get()->sendUpdated(theMoved, kUpdateSelection, false); + ModelAPI_EventCreator::get()->sendReordered(theMoved); } void Model_Objects::clearHistory(ObjectPtr theObj) @@ -340,8 +345,7 @@ void Model_Objects::createHistory(const std::string& theGroupID) { std::map >::iterator aHIter = myHistory.find(theGroupID); if (aHIter == myHistory.end()) { - myHistory[theGroupID] = std::vector(); - std::vector& aResult = myHistory[theGroupID]; + std::vector aResult = std::vector(); // iterate the array of references and get feature by feature from the array bool isFeature = theGroupID == ModelAPI_Feature::group(); Handle(TDataStd_ReferenceArray) aRefs; @@ -350,13 +354,16 @@ void Model_Objects::createHistory(const std::string& theGroupID) FeaturePtr aFeature = feature(aRefs->Value(a)); if (aFeature.get()) { // if feature is in sub-component, remove it from history: it is in sub-tree of sub-component - if (!ModelAPI_Tools::compositeOwner(aFeature).get()) { - if (isFeature) { // here may be also disabled features - if (aFeature->isInHistory()) { - aResult.push_back(aFeature); - } - } else if (!aFeature->isDisabled()) { // iterate all results of not-disabled feature - const std::list >& aResults = aFeature->results(); + bool isSub = ModelAPI_Tools::compositeOwner(aFeature).get() != NULL; + if (isFeature) { // here may be also disabled features + if (!isSub && aFeature->isInHistory()) { + aResult.push_back(aFeature); + } + } else if (!aFeature->isDisabled()) { // iterate all results of not-disabled feature + // construction results of sub-features should not be in the tree + if (!isSub || theGroupID != ModelAPI_ResultConstruction::group()) { + // do not use reference to the list here since results can be changed by "isConcealed" + const std::list > aResults = aFeature->results(); std::list >::const_iterator aRIter = aResults.begin(); for (; aRIter != aResults.cend(); aRIter++) { ResultPtr aRes = *aRIter; @@ -370,6 +377,9 @@ void Model_Objects::createHistory(const std::string& theGroupID) } } } + // to be sure that isConcealed did not update the history (issue 1089) during the iteration + if (myHistory.find(theGroupID) == myHistory.end()) + myHistory[theGroupID] = aResult; } } @@ -500,7 +510,7 @@ const int Model_Objects::index(std::shared_ptr theObject) int Model_Objects::size(const std::string& theGroupID) { createHistory(theGroupID); - return myHistory[theGroupID].size(); + return int(myHistory[theGroupID].size()); } void Model_Objects::allResults(const std::string& theGroupID, std::list& theResults) @@ -559,6 +569,7 @@ void Model_Objects::setUniqueName(FeaturePtr theFeature) isSameName = (*aRIter)->data()->name() == aName; } } + if (isSameName) { aNumObjects++; std::stringstream aNameStream; @@ -586,8 +597,18 @@ void Model_Objects::initData(ObjectPtr theObj, TDF_Label theLab, const int theTa theObj->initAttributes(); } +std::shared_ptr Model_Objects::featureById(const int theId) +{ + if (theId > 0) { + TDF_Label aLab = featuresLabel().FindChild(theId, Standard_False); + return feature(aLab); + } + return std::shared_ptr(); // not found +} + void Model_Objects::synchronizeFeatures( - const TDF_LabelList& theUpdated, const bool theUpdateReferences, const bool theFlush) + const TDF_LabelList& theUpdated, const bool theUpdateReferences, + const bool theOpen, const bool theFlush) { Model_Document* anOwner = std::dynamic_pointer_cast(myDoc).get(); if (!anOwner) // this may happen on creation of document: nothing there, so nothing to synchronize @@ -625,7 +646,7 @@ void Model_Objects::synchronizeFeatures( TCollection_AsciiString(Handle(TDataStd_Comment)::DownCast(aLabIter.Value())->Get()) .ToCString(), anOwner); if (!aFeature.get()) { // somethig is wrong, most probably, the opened document has invalid structure - Events_Error::send("Invalid type of object in the document"); + Events_InfoMessage("Model_Objects", "Invalid type of object in the document").send(); aLabIter.Value()->Label().ForgetAllAttributes(); continue; } @@ -642,6 +663,12 @@ void Model_Objects::synchronizeFeatures( aFeature = myFeatures.Find(aFeatureLabel); aKeptFeatures.insert(aFeature); if (anUpdatedMap.Contains(aFeatureLabel)) { + if (!theOpen) { // on abort/undo/redo reinitialize attributes is something is changed + std::list > anAttrs = aFeature->data()->attributes(""); + std::list >::iterator anAttr = anAttrs.begin(); + for(; anAttr != anAttrs.end(); anAttr++) + (*anAttr)->reinit(); + } ModelAPI_EventCreator::get()->sendUpdated(aFeature, anUpdateEvent); if (aFeature->getKind() == "Parameter") { // if parameters are changed, update the results (issue 937) const std::list >& aResults = aFeature->results(); @@ -672,6 +699,7 @@ void Model_Objects::synchronizeFeatures( ModelAPI_EventCreator::get()->sendUpdated(aFeature, aRedispEvent); updateHistory(aFeature); aFeature->erase(); + // unbind after the "erase" call: on abort sketch is removes sub-objects that corrupts aFIter myFeatures.UnBind(aFIter.Key()); // reinitialize iterator because unbind may corrupt the previous order in the map @@ -693,7 +721,8 @@ void Model_Objects::synchronizeFeatures( FeaturePtr aFeature = myFeatures.Find(aFeatureLabel); if (std::dynamic_pointer_cast(aFeature).get()) aComposites.push_back(aFeature); - updateResults(aFeature); + else + updateResults(aFeature); } } std::list::iterator aComposite = aComposites.begin(); @@ -709,19 +738,21 @@ void Model_Objects::synchronizeFeatures( myHistory.clear(); } - anOwner->executeFeatures() = false; + if (theOpen) + anOwner->executeFeatures() = false; aLoop->activateFlushes(isActive); if (theFlush) { - aLoop->flush(aCreateEvent); aLoop->flush(aDeleteEvent); + aLoop->flush(aCreateEvent); // delete should be emitted before create to reacts to aborted feature aLoop->flush(anUpdateEvent); aLoop->flush(aCreateEvent); // after update of features, there could be results created aLoop->flush(aDeleteEvent); // or deleted aLoop->flush(aRedispEvent); aLoop->flush(aToHideEvent); } - anOwner->executeFeatures() = true; + if (theOpen) + anOwner->executeFeatures() = true; } /// synchronises back references for the given object basing on the collected data @@ -743,8 +774,30 @@ void Model_Objects::synchronizeBackRefsForObject(const std::set& t std::set::iterator aCurrentIter = aData->refsToMe().begin(); while(aCurrentIter != aData->refsToMe().end()) { if (theNewRefs.find(*aCurrentIter) == theNewRefs.end()) { - aData->removeBackReference(*aCurrentIter); - aCurrentIter = aData->refsToMe().begin(); // reinitialize iteration after delete + // for external references from other documents this system is not working: refs are collected from + // different Model_Objects, so before remove check this external object exists and still referenced + bool aLeaveIt = false; + if ((*aCurrentIter)->owner().get() && (*aCurrentIter)->owner()->document() != myDoc && + (*aCurrentIter)->owner()->data().get() && (*aCurrentIter)->owner()->data()->isValid()) { + std::list > > > aRefs; + (*aCurrentIter)->owner()->data()->referencesToObjects(aRefs); + std::list > > >::iterator + aRefIter = aRefs.begin(); + for(; aRefIter != aRefs.end(); aRefIter++) { + if ((*aCurrentIter)->id() == aRefIter->first) { + std::list >::iterator anOIt; + for(anOIt = aRefIter->second.begin(); anOIt != aRefIter->second.end(); anOIt++) { + if (*anOIt == theObject) { + aLeaveIt = true; + } + } + } + } + } + if (!aLeaveIt) { + aData->removeBackReference(*aCurrentIter); + aCurrentIter = aData->refsToMe().begin(); // reinitialize iteration after delete + } else aCurrentIter++; } else aCurrentIter++; } } @@ -790,19 +843,37 @@ void Model_Objects::synchronizeBackRefs() synchronizeBackRefsForObject(anEmpty, aFeature); } else { synchronizeBackRefsForObject(aFound->second, aFeature); + allRefs.erase(aFound); // to check that all refs are counted } // also for results - const std::list >& aResults = aFeature->results(); - std::list >::const_iterator aRes = aResults.cbegin(); - for(; aRes != aResults.cend(); aRes++) { - aFound = allRefs.find(*aRes); + std::list aResults; + ModelAPI_Tools::allResults(aFeature, aResults); + std::list::iterator aRIter = aResults.begin(); + for(; aRIter != aResults.cend(); aRIter++) { + aFound = allRefs.find(*aRIter); if (aFound == allRefs.end()) { // not found => erase all back references - synchronizeBackRefsForObject(anEmpty, *aRes); + synchronizeBackRefsForObject(anEmpty, *aRIter); } else { - synchronizeBackRefsForObject(aFound->second, *aRes); + synchronizeBackRefsForObject(aFound->second, *aRIter); + allRefs.erase(aFound); // to check that all refs are counted } } } + for(aFeatures.Initialize(myFeatures); aFeatures.More(); aFeatures.Next()) { + FeaturePtr aFeature = aFeatures.Value(); + std::list aResults; + ModelAPI_Tools::allResults(aFeature, aResults); + // update the concealment status for disply in isConcealed of ResultBody + std::list::iterator aRIter = aResults.begin(); + for(; aRIter != aResults.cend(); aRIter++) { + (*aRIter)->isConcealed(); + } + } + // the rest all refs means that feature references to the external document feature: process also them + std::map >::iterator anExtIter = allRefs.begin(); + for(; anExtIter != allRefs.end(); anExtIter++) { + synchronizeBackRefsForObject(anExtIter->second, anExtIter->first); + } } TDF_Label Model_Objects::resultLabel( @@ -993,7 +1064,7 @@ void Model_Objects::updateResults(FeaturePtr theFeature) if (!theFeature->data() || !theFeature->data()->isValid() || theFeature->isDisabled()) return; // check that results are presented on all labels - int aResSize = theFeature->results().size(); + int aResSize = int(theFeature->results().size()); TDF_ChildIterator aLabIter(resultLabel(theFeature->data(), 0).Father()); for(; aLabIter.More(); aLabIter.Next()) { // here must be GUID of the feature @@ -1021,8 +1092,8 @@ void Model_Objects::updateResults(FeaturePtr theFeature) theFeature->attributeChanged("expression"); // just produce a value break; } else { - Events_Error::send(std::string("Unknown type of result is found in the document:") + - TCollection_AsciiString(aGroup->Get()).ToCString()); + Events_InfoMessage("Model_Objects", "Unknown type of result is found in the document:") + .arg(TCollection_AsciiString(aGroup->Get()).ToCString()).send(); } } if (aNewBody && !aNewBody->data()->isDeleted()) { @@ -1039,9 +1110,10 @@ ResultPtr Model_Objects::findByName(const std::string theName) FeaturePtr& aFeature = anObjIter.ChangeValue(); if (!aFeature.get() || aFeature->isDisabled()) // may be on close continue; - const std::list >& aResults = aFeature->results(); - std::list >::const_iterator aRIter = aResults.begin(); - for (; aRIter != aResults.cend(); aRIter++) { + std::list allResults; + ModelAPI_Tools::allResults(aFeature, allResults); + std::list::iterator aRIter = allResults.begin(); + for (; aRIter != allResults.cend(); aRIter++) { ResultPtr aRes = *aRIter; if (aRes.get() && aRes->data() && aRes->data()->isValid() && !aRes->isDisabled() && aRes->data()->name() == theName) {