X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModel%2FModel_Objects.cpp;h=949f99b927d30c4a2cd4e9f2b4e309d240d3c41a;hb=fe8cab988ae59927f68da8e184cce6767e052206;hp=fa69915828b7bc6bf24d2161bc682ee5a25404ab;hpb=388af8d735d040dd4861b8b2e6e0e7980b9feaa9;p=modules%2Fshaper.git diff --git a/src/Model/Model_Objects.cpp b/src/Model/Model_Objects.cpp index fa6991582..949f99b92 100644 --- a/src/Model/Model_Objects.cpp +++ b/src/Model/Model_Objects.cpp @@ -14,13 +14,14 @@ #include #include #include +#include #include #include #include #include #include -#include +#include #include #include @@ -54,7 +55,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, true); + synchronizeFeatures(aNoUpdated, true, true, true, true); myHistory.clear(); } @@ -74,7 +75,6 @@ Model_Objects::~Model_Objects() ModelAPI_EventCreator::get()->sendDeleted(myDoc, ModelAPI_Feature::group()); ModelAPI_EventCreator::get()->sendUpdated(aFeature, EVENT_DISP); aFeature->removeResults(0, false); - //aFeature->eraseResults(); aFeature->erase(); myFeatures.UnBind(aFeaturesIter.Key()); } @@ -126,7 +126,7 @@ void Model_Objects::addFeature(FeaturePtr theFeature, const FeaturePtr theAfterT // in initData it creates new features, appeared later than this TDF_Label aPrevFeateureLab; if (theAfterThis.get()) { // searching for the previous feature label - std::shared_ptr aPrevData = + std::shared_ptr aPrevData = std::dynamic_pointer_cast(theAfterThis->data()); if (aPrevData.get()) { aPrevFeateureLab = aPrevData->label().Father(); @@ -161,7 +161,7 @@ void Model_Objects::addFeature(FeaturePtr theFeature, const FeaturePtr theAfterT /// Appends to the array of references a new referenced label. /// If theIndex is not -1, removes element at this index, not theReferenced. /// \returns the index of removed element -static int RemoveFromRefArray(TDF_Label theArrayLab, TDF_Label theReferenced, +static int RemoveFromRefArray(TDF_Label theArrayLab, TDF_Label theReferenced, const int theIndex = -1) { int aResult = -1; // no returned @@ -195,10 +195,12 @@ 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::shared_ptr aData = std::dynamic_pointer_cast(aResult->data()); if (aData.get() != NULL) { const std::set& aRefs = aData->refsToMe(); @@ -211,7 +213,7 @@ void Model_Objects::refsToFeature(FeaturePtr theFeature, } } // the dependencies can be in the feature itself - std::shared_ptr aData = + std::shared_ptr aData = std::dynamic_pointer_cast(theFeature->data()); if (aData.get() && !aData->refsToMe().empty()) { const std::set& aRefs = aData->refsToMe(); @@ -224,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(); } } @@ -238,9 +240,9 @@ void Model_Objects::removeFeature(FeaturePtr theFeature) refsToFeature(theFeature, aRefs, false); std::set >::iterator aRefIter = aRefs.begin(); for(; aRefIter != aRefs.end(); aRefIter++) { - std::shared_ptr aComposite = + std::shared_ptr aComposite = std::dynamic_pointer_cast(*aRefIter); - if (aComposite.get()) { + if (aComposite.get() && aComposite->isSub(theFeature)) { aComposite->removeFeature(theFeature); } } @@ -267,18 +269,46 @@ void Model_Objects::removeFeature(FeaturePtr theFeature) } } +void Model_Objects::eraseAllFeatures() +{ + static Events_ID kDispEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY); + static const ModelAPI_EventCreator* kCreator = ModelAPI_EventCreator::get(); + // make all features invalid (like deleted) + NCollection_DataMap::Iterator aFIter(myFeatures); + for(; aFIter.More(); aFIter.Next()) { + FeaturePtr aFeature = aFIter.Value(); + std::list aResList; + ModelAPI_Tools::allResults(aFeature, aResList); + std::list::iterator aRIter = aResList.begin(); + for(; aRIter != aResList.end(); aRIter++) { + ResultPtr aRes = *aRIter; + if (aRes && aRes->data()->isValid()) { + kCreator->sendDeleted(myDoc, aRes->groupName()); + kCreator->sendUpdated(aRes, kDispEvent); + aRes->setData(aRes->data()->invalidPtr()); + + } + } + kCreator->sendUpdated(aFeature, kDispEvent); + aFeature->setData(aFeature->data()->invalidPtr()); + } + kCreator->sendDeleted(myDoc, ModelAPI_Feature::group()); + myFeatures.Clear(); // just remove features without modification of DS + updateHistory(ModelAPI_Feature::group()); +} + void Model_Objects::moveFeature(FeaturePtr theMoved, FeaturePtr theAfterThis) { TDF_Label aFeaturesLab = featuresLabel(); Handle(TDataStd_ReferenceArray) aRefs; if (!aFeaturesLab.FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) return; - TDF_Label anAfterLab, aMovedLab = + TDF_Label anAfterLab, aMovedLab = std::dynamic_pointer_cast(theMoved->data())->label().Father(); if (theAfterThis.get()) anAfterLab = std::dynamic_pointer_cast(theAfterThis->data())->label().Father(); - Handle(TDataStd_HLabelArray1) aNewArray = + Handle(TDataStd_HLabelArray1) aNewArray = new TDataStd_HLabelArray1(aRefs->Lower(), aRefs->Upper()); int aPassedMovedFrom = 0; // the prev feature location is found and passed int aPassedMovedTo = 0; // the feature is added and this location is passed @@ -302,10 +332,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; } @@ -314,10 +344,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) @@ -331,7 +360,7 @@ void Model_Objects::clearHistory(ObjectPtr theObj) FeaturePtr aFeature = std::dynamic_pointer_cast(theObj); std::string aResultGroup = featureResultGroup(aFeature); if (!aResultGroup.empty()) { - std::map >::iterator aHIter = + std::map >::iterator aHIter = myHistory.find(aResultGroup); if (aHIter != myHistory.end()) myHistory.erase(aHIter); // erase from map => this means that it is not synchronized @@ -352,16 +381,20 @@ void Model_Objects::createHistory(const std::string& theGroupID) for(int a = aRefs->Lower(); a <= aRefs->Upper(); a++) { 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 + // if feature is in sub-component, remove it from history: + // it is in sub-tree of sub-component + 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(); + std::list >::const_iterator + aRIter = aResults.begin(); for (; aRIter != aResults.cend(); aRIter++) { ResultPtr aRes = *aRIter; if (aRes->groupName() != theGroupID) break; // feature have only same group results @@ -471,7 +504,8 @@ std::shared_ptr Model_Objects::objectByName( if (aRIter->get() && (*aRIter)->groupName() == theGroupID) { if ((*aRIter)->data()->name() == theName) return *aRIter; - ResultCompSolidPtr aCompRes = std::dynamic_pointer_cast(*aRIter); + ResultCompSolidPtr aCompRes = + std::dynamic_pointer_cast(*aRIter); if (aCompRes.get()) { int aNumSubs = aCompRes->numberOfSubs(); for(int a = 0; a < aNumSubs; a++) { @@ -604,8 +638,8 @@ std::shared_ptr Model_Objects::featureById(const int theId) } void Model_Objects::synchronizeFeatures( - const TDF_LabelList& theUpdated, const bool theUpdateReferences, - const bool theOpen, const bool theFlush) + const TDF_LabelList& theUpdated, const bool theUpdateReferences, + const bool theExecuteFeatures, 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 @@ -642,8 +676,9 @@ void Model_Objects::synchronizeFeatures( aFeature = std::dynamic_pointer_cast(ModelAPI_Session::get())->createFeature( 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"); + if (!aFeature.get()) { + // somethig is wrong, most probably, the opened document has invalid structure + Events_InfoMessage("Model_Objects", "Invalid type of object in the document").send(); aLabIter.Value()->Label().ForgetAllAttributes(); continue; } @@ -660,8 +695,16 @@ void Model_Objects::synchronizeFeatures( aFeature = myFeatures.Find(aFeatureLabel); aKeptFeatures.insert(aFeature); if (anUpdatedMap.Contains(aFeatureLabel)) { + if (!theOpen) { // on abort/undo/redo reinitialize attributes if 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) + if (aFeature->getKind() == "Parameter") { + // if parameters are changed, update the results (issue 937) const std::list >& aResults = aFeature->results(); std::list >::const_iterator aRIter = aResults.begin(); for (; aRIter != aResults.cend(); aRIter++) { @@ -691,7 +734,8 @@ void Model_Objects::synchronizeFeatures( updateHistory(aFeature); aFeature->erase(); - // unbind after the "erase" call: on abort sketch is removes sub-objects that corrupts aFIter + // 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 aFIter.Initialize(myFeatures); @@ -702,52 +746,50 @@ void Model_Objects::synchronizeFeatures( if (theUpdateReferences) { synchronizeBackRefs(); } - // update results of the features (after features created because they may be connected, like sketch and sub elements) - // After synchronisation of back references because sketch must be set in sub-elements before "execute" by updateResults - std::list aComposites; // composites must be updated after their subs (issue 360) + // update results of the features (after features created because + // they may be connected, like sketch and sub elements) + // After synchronisation of back references because sketch + // must be set in sub-elements before "execute" by updateResults + std::set aProcessed; // 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 (myFeatures.IsBound(aFeatureLabel)) { // a new feature is inserted FeaturePtr aFeature = myFeatures.Find(aFeatureLabel); - if (std::dynamic_pointer_cast(aFeature).get()) - aComposites.push_back(aFeature); - updateResults(aFeature); + updateResults(aFeature, aProcessed); } } - std::list::iterator aComposite = aComposites.begin(); - for(; aComposite != aComposites.end(); aComposite++) { - updateResults(*aComposite); - } - - // the synchronize should be done after updateResults in order to correct back references of updated results + // the synchronize should be done after updateResults + // in order to correct back references of updated results if (theUpdateReferences) { synchronizeBackRefs(); } - if (!theUpdated.IsEmpty()) { // this means there is no control what was modified => remove history cash + if (!theUpdated.IsEmpty()) { + // this means there is no control what was modified => remove history cash myHistory.clear(); } - if (theOpen) + if (theExecuteFeatures) anOwner->executeFeatures() = false; aLoop->activateFlushes(isActive); if (theFlush) { aLoop->flush(aDeleteEvent); - aLoop->flush(aCreateEvent); // delete should be emitted before create to reacts to aborted feature + // delete should be emitted before create to reacts to aborted feature + aLoop->flush(aCreateEvent); 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); } - if (theOpen) + if (theExecuteFeatures) anOwner->executeFeatures() = true; } /// synchronises back references for the given object basing on the collected data void Model_Objects::synchronizeBackRefsForObject(const std::set& theNewRefs, - ObjectPtr theObject) + ObjectPtr theObject) { if (!theObject.get() || !theObject->data()->isValid()) return; // invalid @@ -764,14 +806,16 @@ 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()) { - // 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 + // 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 + std::list >>>::iterator aRefIter = aRefs.begin(); for(; aRefIter != aRefs.end(); aRefIter++) { if ((*aCurrentIter)->id() == aRefIter->first) { @@ -859,7 +903,8 @@ void Model_Objects::synchronizeBackRefs() (*aRIter)->isConcealed(); } } - // the rest all refs means that feature references to the external document feature: process also them + // 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); @@ -867,9 +912,9 @@ void Model_Objects::synchronizeBackRefs() } TDF_Label Model_Objects::resultLabel( - const std::shared_ptr& theFeatureData, const int theResultIndex) + const std::shared_ptr& theFeatureData, const int theResultIndex) { - const std::shared_ptr& aData = + const std::shared_ptr& aData = std::dynamic_pointer_cast(theFeatureData); return aData->label().Father().FindChild(TAG_FEATURE_RESULTS).FindChild(theResultIndex + 1); } @@ -881,10 +926,12 @@ void Model_Objects::storeResult(std::shared_ptr theFeatureData, theResult->init(); theResult->setDoc(myDoc); initData(theResult, resultLabel(theFeatureData, theResultIndex), TAG_FEATURE_ARGUMENTS); - if (theResult->data()->name().empty()) { // if was not initialized, generate event and set a name + if (theResult->data()->name().empty()) { + // if was not initialized, generate event and set a name std::stringstream aNewName; aNewName<name(); - // if there are several results (issue #899: any number of result), add unique prefix starting from second + // if there are several results (issue #899: any number of result), + // add unique prefix starting from second if (theResultIndex > 0 || theResult->groupName() == ModelAPI_ResultBody::group()) aNewName<<"_"<data()->setName(aNewName.str()); @@ -912,7 +959,7 @@ std::shared_ptr Model_Objects::createBody( const std::shared_ptr& theFeatureData, const int theIndex) { TDF_Label aLab = resultLabel(theFeatureData, theIndex); - // for feature create compsolid, but for result sub create body: + // for feature create compsolid, but for result sub create body: // only one level of recursion is supported now ResultPtr aResultOwner = std::dynamic_pointer_cast(theFeatureData->owner()); ObjectPtr anOldObject; @@ -981,6 +1028,23 @@ std::shared_ptr Model_Objects::createGroup( return aResult; } +std::shared_ptr Model_Objects::createField( + const std::shared_ptr& theFeatureData, const int theIndex) +{ + TDF_Label aLab = resultLabel(theFeatureData, theIndex); + TDataStd_Comment::Set(aLab, ModelAPI_ResultField::group().c_str()); + ObjectPtr anOldObject = object(aLab); + std::shared_ptr aResult; + if (anOldObject.get()) { + aResult = std::dynamic_pointer_cast(anOldObject); + } + if (!aResult.get()) { + aResult = std::shared_ptr(new Model_ResultField(theFeatureData)); + storeResult(theFeatureData, aResult, theIndex); + } + return aResult; +} + std::shared_ptr Model_Objects::createParameter( const std::shared_ptr& theFeatureData, const int theIndex) { @@ -1030,8 +1094,22 @@ std::string Model_Objects::featureResultGroup(FeaturePtr theFeature) return anEmpty; // not found } -void Model_Objects::updateResults(FeaturePtr theFeature) +void Model_Objects::updateResults(FeaturePtr theFeature, std::set& theProcessed) { + if (theProcessed.find(theFeature) != theProcessed.end()) + return; + theProcessed.insert(theFeature); + // for composites update subs recursively (sketch elements results are needed for the sketch) + CompositeFeaturePtr aComp = std::dynamic_pointer_cast(theFeature); + if (aComp.get() && aComp->getKind() != "Part") { // don't go inside of parts sub-features + // update subs of composites first + int aSubNum = aComp->numberOfSubs(); + for(int a = 0; a < aSubNum; a++) { + FeaturePtr aSub = aComp->subFeature(a); + updateResults(aComp->subFeature(a), theProcessed); + } + } + // for not persistent is will be done by parametric updater automatically //if (!theFeature->isPersistentResult()) return; // check the existing results and remove them if there is nothing on the label @@ -1040,7 +1118,7 @@ void Model_Objects::updateResults(FeaturePtr theFeature) ResultPtr aBody = std::dynamic_pointer_cast(*aResIter); if (aBody.get()) { std::shared_ptr aData = std::dynamic_pointer_cast(aBody->data()); - if (!aData.get() || !aData->isValid() || (!aBody->isDisabled() && aData->isDeleted())) { + if (!aData.get() || !aData->isValid() || (!aBody->isDisabled() && aData->isDeleted())) { // found a disappeared result => remove it theFeature->eraseResultFromList(aBody); // start iterate from beginning because iterator is corrupted by removing @@ -1064,26 +1142,26 @@ void Model_Objects::updateResults(FeaturePtr theFeature) TDF_Label anArgLab = aLabIter.Value(); Handle(TDataStd_Comment) aGroup; if (anArgLab.FindAttribute(TDataStd_Comment::GetID(), aGroup)) { - if (aGroup->Get() == ModelAPI_ResultBody::group().c_str() || + if (aGroup->Get() == ModelAPI_ResultBody::group().c_str() || aGroup->Get() == ModelAPI_ResultCompSolid::group().c_str()) { aNewBody = createBody(theFeature->data(), aResIndex); } else if (aGroup->Get() == ModelAPI_ResultPart::group().c_str()) { - std::shared_ptr aNewP = createPart(theFeature->data(), aResIndex); + std::shared_ptr aNewP = createPart(theFeature->data(), aResIndex); theFeature->setResult(aNewP, aResIndex); if (!aNewP->partDoc().get()) - theFeature->execute(); // create the part result: it is better to restore the previous result if it is possible - break; + // create the part result: it is better to restore the previous result if it is possible + theFeature->execute(); } else if (aGroup->Get() == ModelAPI_ResultConstruction::group().c_str()) { theFeature->execute(); // construction shapes are needed for sketch solver - break; } else if (aGroup->Get() == ModelAPI_ResultGroup::group().c_str()) { aNewBody = createGroup(theFeature->data(), aResIndex); + } else if (aGroup->Get() == ModelAPI_ResultField::group().c_str()) { + aNewBody = createField(theFeature->data(), aResIndex); } else if (aGroup->Get() == ModelAPI_ResultParameter::group().c_str()) { 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()) { @@ -1100,9 +1178,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) {