ModelAPI_EventCreator::get()->sendUpdated(theFeature, anEvent);
theFeature->setDisabled(false); // by default created feature is enabled
updateHistory(ModelAPI_Feature::group());
+ } else { // make feature has not-null data anyway
+ theFeature->setData(Model_Data::invalidData());
+ theFeature->setDoc(myDoc);
}
}
void Model_Objects::removeFeature(FeaturePtr theFeature)
{
std::shared_ptr<Model_Data> aData = std::static_pointer_cast<Model_Data>(theFeature->data());
- if (aData) {
- TDF_Label aFeatureLabel = aData->label().Father();
- if (myFeatures.IsBound(aFeatureLabel))
- myFeatures.UnBind(aFeatureLabel);
- else
- return; // not found feature => do not remove
-
- clearHistory(theFeature);
+ if (aData && aData->isValid()) {
// checking that the sub-element of composite feature is removed: if yes, inform the owner
std::set<std::shared_ptr<ModelAPI_Feature> > aRefs;
refsToFeature(theFeature, aRefs, false);
aComposite->removeFeature(theFeature);
}
}
+ // this must be before erase since theFeature erasing removes all information about
+ // the feature results and groups of results
+ // To reproduce: create sketch, extrusion, remove sketch => constructions tree is not updated
+ clearHistory(theFeature);
// erase fields
theFeature->erase();
+
+ TDF_Label aFeatureLabel = aData->label().Father();
+ if (myFeatures.IsBound(aFeatureLabel))
+ myFeatures.UnBind(aFeatureLabel);
+
static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
ModelAPI_EventCreator::get()->sendUpdated(theFeature, EVENT_DISP);
// erase all attributes under the label of feature
myHistory.erase(aHIter); // erase from map => this means that it is not synchronized
if (theObj->groupName() == ModelAPI_Feature::group()) { // clear results group of the feature
FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObj);
- if (aFeature->firstResult().get())
- clearHistory(aFeature->firstResult());
+ std::string aResultGroup = featureResultGroup(aFeature);
+ if (!aResultGroup.empty()) {
+ std::map<std::string, std::vector<ObjectPtr> >::iterator aHIter =
+ myHistory.find(aResultGroup);
+ if (aHIter != myHistory.end())
+ myHistory.erase(aHIter); // erase from map => this means that it is not synchronized
+ }
}
}
}
ObjectPtr Model_Objects::object(const std::string& theGroupID, const int theIndex)
{
createHistory(theGroupID);
+ //TODO: mpv stabilization hotfix
+ if (myHistory[theGroupID].size() <= (const unsigned int)theIndex)
+ return ObjectPtr();
return myHistory[theGroupID][theIndex];
}
static Events_ID aRedispEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
static Events_ID aDeleteEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED);
static Events_ID aToHideEvent = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
- aLoop->activateFlushes(false);
+ bool isActive = aLoop->activateFlushes(false);
// update all objects by checking are they on labels or not
std::set<FeaturePtr> aNewFeatures, aKeptFeatures;
}
anOwner->executeFeatures() = false;
- aLoop->activateFlushes(true);
+ aLoop->activateFlushes(isActive);
if (theFlush) {
aLoop->flush(aCreateEvent);
return FeaturePtr();
}
+std::string Model_Objects::featureResultGroup(FeaturePtr theFeature)
+{
+ if (theFeature->data()->isValid()) {
+ TDF_ChildIterator aLabIter(resultLabel(theFeature->data(), 0).Father());
+ if (aLabIter.More()) {
+ TDF_Label anArgLab = aLabIter.Value();
+ Handle(TDataStd_Comment) aGroup;
+ if (aLabIter.Value().FindAttribute(TDataStd_Comment::GetID(), aGroup)) {
+ return TCollection_AsciiString(aGroup->Get()).ToCString();
+ }
+ }
+ }
+ static std::string anEmpty;
+ return anEmpty; // not found
+}
+
void Model_Objects::updateResults(FeaturePtr theFeature)
{
// for not persistent is will be done by parametric updater automatically
std::list<ResultPtr>::const_iterator aResIter = theFeature->results().cbegin();
while(aResIter != theFeature->results().cend()) {
ResultPtr aBody = std::dynamic_pointer_cast<ModelAPI_Result>(*aResIter);
- if (aBody) {
+ if (aBody.get()) {
if (!aBody->data()->isValid()) {
// found a disappeared result => remove it
- theFeature->removeResult(aBody);
+ theFeature->eraseResultFromList(aBody);
// start iterate from beginning because iterator is corrupted by removing
aResIter = theFeature->results().cbegin();
continue;
if (aGroup->Get() == ModelAPI_ResultBody::group().c_str()) {
aNewBody = createBody(theFeature->data(), aResIndex);
} else if (aGroup->Get() == ModelAPI_ResultPart::group().c_str()) {
- //aNewBody = createPart(theFeature->data(), aResIndex);
- theFeature->execute(); // create the part result
+ std::shared_ptr<ModelAPI_ResultPart> 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;
} else if (aGroup->Get() == ModelAPI_ResultConstruction::group().c_str()) {
theFeature->execute(); // construction shapes are needed for sketch solver
FeaturePtr Model_Objects::nextFeature(FeaturePtr theCurrent, const bool theReverse)
{
std::shared_ptr<Model_Data> aData = std::static_pointer_cast<Model_Data>(theCurrent->data());
- if (aData) {
+ if (aData && aData->isValid()) {
TDF_Label aFeatureLabel = aData->label().Father();
Handle(TDataStd_ReferenceArray) aRefs;
if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
return FeaturePtr(); // no features at all
}
+std::list<std::shared_ptr<ModelAPI_Feature> > Model_Objects::allFeatures()
+{
+ std::list<std::shared_ptr<ModelAPI_Feature> > aResult;
+ Handle(TDataStd_ReferenceArray) aRefs;
+ if (featuresLabel().FindAttribute(TDataStd_ReferenceArray::GetID(), aRefs)) {
+ for(int a = aRefs->Lower(); a <= aRefs->Upper(); a++) {
+ FeaturePtr aFeature = feature(aRefs->Value(a));
+ if (aFeature.get())
+ aResult.push_back(aFeature);
+ }
+ }
+ return aResult;
+}
+
Standard_Integer HashCode(const TDF_Label& theLab, const Standard_Integer theUpper)
{
return TDF_LabelMapHasher::HashCode(theLab, theUpper);