#include <Model_AttributeBoolean.h>
#include <Model_AttributeString.h>
#include <Model_Events.h>
+#include <ModelAPI_Feature.h>
+#include <ModelAPI_Result.h>
#include <GeomData_Point.h>
#include <GeomData_Point2D.h>
myLab.ForgetAllAttributes();
}
+/// identifeir of the "must be updated" flag in the data tree
Standard_GUID kMustBeUpdatedGUID("baede74c-31a6-4416-9c4d-e48ce65f2005");
void Model_Data::mustBeUpdated(const bool theFlag)
{
return myLab.IsAttribute(kMustBeUpdatedGUID) == Standard_True;
}
+
+bool Model_Data::referencesTo(const boost::shared_ptr<ModelAPI_Feature>& theFeature)
+{
+ // collect results of this feature first to check references quickly in the cycle
+ std::set<ObjectPtr> aFeatureObjs;
+ aFeatureObjs.insert(theFeature);
+ std::list<boost::shared_ptr<ModelAPI_Result> >::const_iterator aRIter =
+ theFeature->results().cbegin();
+ for(; aRIter != theFeature->results().cend(); aRIter++) {
+ if (*aRIter)
+ aFeatureObjs.insert(*aRIter);
+ }
+
+ std::map<std::string, boost::shared_ptr<ModelAPI_Attribute> >::iterator anAttrsIter =
+ myAttrs.begin();
+ for (; anAttrsIter != myAttrs.end(); anAttrsIter++) {
+ if (anAttrsIter->second->attributeType() == ModelAPI_AttributeRefAttr::type()) {
+ boost::shared_ptr<ModelAPI_AttributeRefAttr> aRefAttr =
+ boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(anAttrsIter->second);
+ if (aRefAttr && aRefAttr->isObject()) { // check referenced object
+ if (aFeatureObjs.find(aRefAttr->object()) != aFeatureObjs.end())
+ return true;
+ } else { // check object of referenced attribute
+ boost::shared_ptr<ModelAPI_Attribute> anAttr = aRefAttr->attr();
+ if (anAttr && aFeatureObjs.find(anAttr->owner()) != aFeatureObjs.end())
+ return true;
+ }
+ } else if (anAttrsIter->second->attributeType() == ModelAPI_AttributeReference::type()) {
+ boost::shared_ptr<ModelAPI_AttributeReference> aRef =
+ boost::dynamic_pointer_cast<ModelAPI_AttributeReference>(anAttrsIter->second);
+ if (aFeatureObjs.find(aRef->value()) != aFeatureObjs.end()) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
/// Returns true if feature must be updated (re-executed) on rebuild
MODEL_EXPORT virtual bool mustBeUpdated();
+
+ /// Returns true if this data attributes are referenced to the given feature or its results
+ MODEL_EXPORT virtual bool referencesTo(const boost::shared_ptr<ModelAPI_Feature>& theFeature);
};
#endif
return aResult;
}
-void Model_Document::removeFeature(FeaturePtr theFeature)
-{
- // check the feature: it must have no depended objects on it
- std::list<ResultPtr>::const_iterator aResIter = theFeature->results().cbegin();
- for(; aResIter != theFeature->results().cend(); aResIter++) {
- if (myConcealedResults.find(*aResIter) != myConcealedResults.end()) {
- Events_Error::send("Feature '" + theFeature->data()->name() + "' is used and can not be deleted");
- return;
+void Model_Document::removeFeature(FeaturePtr theFeature, const bool theCheck)
+{
+ if (theCheck) {
+ // check the feature: it must have no depended objects on it
+ std::list<ResultPtr>::const_iterator aResIter = theFeature->results().cbegin();
+ for(; aResIter != theFeature->results().cend(); aResIter++) {
+ if (myConcealedResults.find(*aResIter) != myConcealedResults.end()) {
+ Events_Error::send("Feature '" + theFeature->data()->name() + "' is used and can not be deleted");
+ return;
+ }
+ }
+ NCollection_DataMap<TDF_Label, FeaturePtr>::Iterator anObjIter(myObjs);
+ for(; anObjIter.More(); anObjIter.Next()) {
+ DataPtr aData = anObjIter.Value()->data();
+ if (aData->referencesTo(theFeature)) {
+ Events_Error::send("Feature '" + theFeature->data()->name() + "' is used and can not be deleted");
+ return;
+ }
}
}
+
boost::shared_ptr<Model_Data> aData = boost::static_pointer_cast<Model_Data>(theFeature->data());
TDF_Label aFeatureLabel = aData->label().Father();
if (myObjs.IsBound(aFeatureLabel))
if (aKeptFeatures.find(aFIter.Value()) == aKeptFeatures.end()
&& aNewFeatures.find(aFIter.Value()) == aNewFeatures.end()) {
FeaturePtr aFeature = aFIter.Value();
- TDF_Label aLab = aFIter.Key();
- aFIter.Next();
- myObjs.UnBind(aLab);
// event: model is updated
//if (aFeature->isInHistory()) {
ModelAPI_EventCreator::get()->sendDeleted(aThis, ModelAPI_Feature::group());
// redisplay also removed feature (used for sketch and AISObject)
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);
} else
aFIter.Next();
}
MODEL_EXPORT virtual FeaturePtr addFeature(std::string theID);
//! Removes the feature from the document (with result)
- MODEL_EXPORT virtual void removeFeature(FeaturePtr theFeature);
+ //! \param theCheck if it is false, do not check the references
+ MODEL_EXPORT virtual void removeFeature(FeaturePtr theFeature, const bool theCheck = true);
//! Returns the existing feature by the label
//! \param theLabel base label of the feature
class ModelAPI_AttributeString;
class ModelAPI_Document;
class ModelAPI_Attribute;
+class ModelAPI_Feature;
class GeomAPI_Shape;
/**\class ModelAPI_Data
/// Returns true if feature must be updated (re-executed) on rebuild
virtual bool mustBeUpdated() = 0;
+ /// Returns true if this data attributes are referenced to the given feature or its results
+ virtual bool referencesTo(const boost::shared_ptr<ModelAPI_Feature>& theFeature) = 0;
+
protected:
/// Objects are created for features automatically
ModelAPI_Data()
virtual boost::shared_ptr<ModelAPI_Feature> addFeature(std::string theID) = 0;
//! Removes the feature from the document
- virtual void removeFeature(boost::shared_ptr<ModelAPI_Feature> theFeature) = 0;
+ virtual void removeFeature(
+ boost::shared_ptr<ModelAPI_Feature> theFeature, const bool theCheck = true) = 0;
///! Adds a new sub-document by the identifier, or returns existing one if it is already exist
- virtual boost::shared_ptr<ModelAPI_Document>
- subDocument(std::string theDocID) = 0;
+ virtual boost::shared_ptr<ModelAPI_Document> subDocument(std::string theDocID) = 0;
///! Returns the id of the document
virtual const std::string& id() const = 0;
std::list<ObjectPtr>::const_iterator anIt = aFeatures.begin();
for (; anIt != aFeatures.end(); anIt++) {
FeaturePtr aFeature = boost::dynamic_pointer_cast<ModelAPI_Feature>(*anIt);
- if (aFeature)
- document()->removeFeature(aFeature);
+ if (aFeature) {
+ // subs are referenced from sketch, but must be removed for sure, so not checkings
+ document()->removeFeature(aFeature, false);
+ }
}
SketchPlugin_Feature::erase();
}