It is necessary to add/remove back references during set an object to the attribute.
The external object should not be removed by widget if there is a feature, which already uses this object.
An additional check for the feature's data during analize the creation event from the model.
void Model_AttributeRefAttr::setObject(ObjectPtr theObject)
{
+ // the back reference from the previous object to the attribute should be removed
+ ObjectPtr anObject = object();
+ if (anObject.get() && anObject != theObject) {
+ FeaturePtr anOwnerFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(owner());
+ if (anOwnerFeature.get()) {
+ std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(
+ anObject->data());
+ aData->removeBackReference(anOwnerFeature, id());
+ }
+ }
+
if (theObject && (!myIsInitialized || myID->Get().Length() != 0 || object() != theObject)) {
std::shared_ptr<Model_Data> aData = std::dynamic_pointer_cast<Model_Data>(
theObject->data());
myRef->Set(aData->label().Father());
myID->Set(""); // feature is identified by the empty ID
+
+ // do it before the transaction finish to make just created/removed objects know dependencies
+ // and reference from composite feature is removed automatically
+ FeaturePtr anOwnerFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(owner());
+ if (anOwnerFeature.get()) {
+ aData->addBackReference(anOwnerFeature, id(), false);
+ }
owner()->data()->sendAttributeUpdated(this);
} else if (theObject.get() == NULL) {
myRef->Set(myRef->Label()); // reference to itself means that object is null
aRes->setIsConcealed(false);
}
+void Model_Data::removeBackReference(FeaturePtr theFeature, std::string theAttrID)
+{
+ AttributePtr anAttribute = theFeature->data()->attribute(theAttrID);
+ if (myRefsToMe.find(anAttribute) == myRefsToMe.end())
+ return;
+
+ myRefsToMe.erase(anAttribute);
+ // TODO: check whether the concealed should be thrown down to the false value
+ std::shared_ptr<ModelAPI_Result> aRes =
+ std::dynamic_pointer_cast<ModelAPI_Result>(myObject);
+ if (aRes)
+ aRes->setIsConcealed(false);
+}
+
void Model_Data::addBackReference(FeaturePtr theFeature, std::string theAttrID,
const bool theApplyConcealment)
{
+ // do not add the same attribute twice
+ AttributePtr anAttribute = theFeature->data()->attribute(theAttrID);
+ if (myRefsToMe.find(anAttribute) != myRefsToMe.end())
+ return;
+
myRefsToMe.insert(theFeature->data()->attribute(theAttrID));
if (theApplyConcealment &&
ModelAPI_Session::get()->validators()->isConcealed(theFeature->getKind(), theAttrID)) {
/// Adds a back reference (with identifier which attribute references to this object
/// \param theFeature feature referenced to this
/// \param theAttrID identifier of the attribute that is references from theFeature to this
+ void removeBackReference(FeaturePtr theFeature, std::string theAttrID);
+ /// Adds a back reference (with identifier which attribute references to this object
+ /// \param theFeature feature referenced to this
+ /// \param theAttrID identifier of the attribute that is references from theFeature to this
/// \param theApplyConcealment applies consealment flag changes
void addBackReference(FeaturePtr theFeature, std::string theAttrID,
const bool theApplyConcealment = true);
#include <PartSet_Tools.h>
#include <SketchPlugin_Feature.h>
+#include <SketchPlugin_ConstraintRigid.h>
+
#include <XGUI_Workshop.h>
PartSet_WidgetShapeSelector::PartSet_WidgetShapeSelector(QWidget* theParent,
DocumentPtr aDoc = myExternalObject->document();
FeaturePtr aFeature = ModelAPI_Feature::feature(myExternalObject);
if (aFeature.get() != NULL) {
+ // 1. check whether the external object can be deleted
+ // It should not be deleted if there are references to the object from other features,
+ // which are not the sketch or a rigid constraints.
+ std::set<FeaturePtr> aRefFeatures;
+ aFeature->document()->refsToFeature(aFeature, aRefFeatures, false);
+ std::set<FeaturePtr>::const_iterator anIt = aRefFeatures.begin(),
+ aLast = aRefFeatures.end();
+ bool aReferenceExist = false;
+ CompositeFeaturePtr aSketch = sketch();
+ for (; anIt != aLast && !aReferenceExist; anIt++) {
+ FeaturePtr aFeature = (*anIt);
+ aReferenceExist = aFeature != aSketch &&
+ aFeature->getKind() != SketchPlugin_ConstraintRigid::ID();
+ }
+ if (aReferenceExist)
+ return;
+
+ // 2. delete external object
QObjectPtrList anObjects;
anObjects.append(aFeature);
// the external feature should be removed with all references, sketch feature should be ignored
// Redisplay the visible object or the object of the current operation
bool isVisibleObject = myDisplayer->isVisible(aObj);
#ifdef DEBUG_FEATURE_REDISPLAY
- QString anObjInfo = objectInfo((aObj));
- qDebug(QString("visible=%1 : display= %2").arg(isVisibleObject).arg(anObjInfo).toStdString().c_str());
+ //QString anObjInfo = objectInfo((aObj));
+ //qDebug(QString("visible=%1 : display= %2").arg(isVisibleObject).arg(anObjInfo).toStdString().c_str());
#endif
if (isVisibleObject) { // redisplay visible object
//bool aHasPart = false;
bool isDisplayed = false;
for (aIt = aObjects.begin(); aIt != aObjects.end(); ++aIt) {
-
+ ObjectPtr anObject = *aIt;
+ // the validity of the data should be checked here in order to avoid display of the objects,
+ // which were created, then deleted, but flush for the creation event happens after that
+ if (!anObject->data() || !anObject->data()->isValid())
+ continue;
//ResultPartPtr aPart = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aIt);
//if (aPart) {
//aHasPart = true;
aDoc->removeFeature(aFeature);
}
}
+ // the update signal should be emitted obligatory in order to have a redisplay
+ // signal and hide the removed presentations in the viewer
+ Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
return true;
}