Salome HOME
No automatic rebuild: only on preview. Update of visualization behavior due to the...
authormpv <mikhail.ponikarov@opencascade.com>
Fri, 19 Sep 2014 12:40:10 +0000 (16:40 +0400)
committermpv <mikhail.ponikarov@opencascade.com>
Fri, 19 Sep 2014 12:40:10 +0000 (16:40 +0400)
19 files changed:
src/Model/Model_AttributeReference.cpp
src/Model/Model_AttributeReference.h
src/Model/Model_Document.cpp
src/Model/Model_Events.cpp
src/Model/Model_Events.h
src/Model/Model_Session.cpp
src/Model/Model_Update.cpp
src/Model/Model_Update.h
src/ModelAPI/ModelAPI_Attribute.h
src/ModelAPI/ModelAPI_Events.h
src/ModelAPI/ModelAPI_Feature.cpp
src/ModelAPI/ModelAPI_Feature.h
src/ModelAPI/ModelAPI_Object.h
src/SketchSolver/SketchSolver_ConstraintGroup.cpp
src/SketchSolver/SketchSolver_ConstraintGroup.h
src/XGUI/XGUI_OperationMgr.cpp
src/XGUI/XGUI_PartDataModel.cpp
src/XGUI/XGUI_pictures.qrc
src/XGUI/pictures/constr_object_modified.png [new file with mode: 0644]

index 4e14efc0af9c9c79dfb6575bc1b4c9075fb195c5..134516972b2a2eecfacab366f3bb46f9204d5a8c 100644 (file)
@@ -20,7 +20,7 @@ void Model_AttributeReference::setValue(ObjectPtr theObject)
 
     boost::shared_ptr<Model_Document> aDoc =
       boost::dynamic_pointer_cast<Model_Document>(owner()->document());
-    if (aDoc) aDoc->objectIsNotReferenced(aDoc->object(myRef->Label()));
+    if (aDoc) aDoc->objectIsNotReferenced(aDoc->object(myRef->Get()));
     myRef->Set(aData->label().Father());  // references to the feature label
     boost::shared_dynamic_cast<Model_Document>(owner()->document())->objectIsReferenced(theObject);
 
@@ -48,9 +48,21 @@ Model_AttributeReference::Model_AttributeReference(TDF_Label& theLabel)
   if (!myIsInitialized) {
     myRef = TDF_Reference::Set(theLabel, theLabel);  // not initialized references to itself
   } else {
+    if (owner()) {
+      boost::shared_ptr<Model_Document> aDoc =
+        boost::dynamic_pointer_cast<Model_Document>(owner()->document());
+      if (aDoc) aDoc->objectIsReferenced(aDoc->object(myRef->Get()));
+    }
+  }
+}
+
+void Model_AttributeReference::setObject(const boost::shared_ptr<ModelAPI_Object>& theObject)
+{
+  if (owner() != theObject) {
+    ModelAPI_AttributeReference::setObject(theObject);
     boost::shared_ptr<Model_Document> aDoc =
       boost::dynamic_pointer_cast<Model_Document>(owner()->document());
-    if (aDoc) aDoc->objectIsReferenced(aDoc->object(myRef->Label()));
+    if (aDoc) aDoc->objectIsReferenced(aDoc->object(myRef->Get()));
   }
 }
 
@@ -58,5 +70,6 @@ Model_AttributeReference::~Model_AttributeReference()
 {
   boost::shared_ptr<Model_Document> aDoc =
     boost::dynamic_pointer_cast<Model_Document>(owner()->document());
-  if (aDoc) aDoc->objectIsNotReferenced(aDoc->object(myRef->Label()));
+  TDF_Label aLab = myRef->Get();
+  if (aDoc && !aLab.IsNull()) aDoc->objectIsNotReferenced(aDoc->object(myRef->Get()));
 }
index e8f9c9997f45169bf31a51572817c839fc189180..d9993f99a6049a57a0beb97ee7a3ca7b5e84c08a 100644 (file)
@@ -28,6 +28,8 @@ class Model_AttributeReference : public ModelAPI_AttributeReference
 
   MODEL_EXPORT ~Model_AttributeReference();
 
+  MODEL_EXPORT virtual void setObject(const boost::shared_ptr<ModelAPI_Object>& theObject);
+
 protected:
   /// Objects are created for features automatically
   MODEL_EXPORT Model_AttributeReference(TDF_Label& theLabel);
index 4adcc0aa63996ff4489df3f22358d6906aa46ab7..57241b6b52926fa23f5ac029c2628988f5a2ee36 100644 (file)
@@ -461,13 +461,22 @@ static int RemoveFromRefArray(TDF_Label theArrayLab, TDF_Label theReferenced, co
 
 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;
+    }
+  }
   boost::shared_ptr<Model_Data> aData = boost::static_pointer_cast<Model_Data>(theFeature->data());
   TDF_Label aFeatureLabel = aData->label().Father();
   if (myObjs.IsBound(aFeatureLabel))
     myObjs.UnBind(aFeatureLabel);
   else
     return;  // not found feature => do not remove
-
+  // erase fields
+  theFeature->erase();
   // erase all attributes under the label of feature
   aFeatureLabel.ForgetAllAttributes();
   // remove it from the references array
@@ -475,6 +484,7 @@ void Model_Document::removeFeature(FeaturePtr theFeature)
 
   // event: feature is deleted
   ModelAPI_EventCreator::get()->sendDeleted(theFeature->document(), ModelAPI_Feature::group());
+  /* this is in "erase"
   // results of this feature must be redisplayed
   static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
   const std::list<boost::shared_ptr<ModelAPI_Result> >& aResults = theFeature->results();
@@ -485,6 +495,7 @@ void Model_Document::removeFeature(FeaturePtr theFeature)
     ModelAPI_EventCreator::get()->sendUpdated(aRes, EVENT_DISP);
     ModelAPI_EventCreator::get()->sendDeleted(theFeature->document(), aRes->groupName());
   }
+  */
 }
 
 FeaturePtr Model_Document::feature(TDF_Label& theLabel)
@@ -745,14 +756,17 @@ void Model_Document::synchronizeFeatures(const bool theMarkUpdated)
       static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
       const std::list<boost::shared_ptr<ModelAPI_Result> >& aResults = aFeature->results();
       std::list<boost::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
+      /*
       for (; aRIter != aResults.cend(); aRIter++) {
         boost::shared_ptr<ModelAPI_Result> aRes = *aRIter;
         //aRes->setData(boost::shared_ptr<ModelAPI_Data>()); // deleted flag
         ModelAPI_EventCreator::get()->sendUpdated(aRes, EVENT_DISP);
         ModelAPI_EventCreator::get()->sendDeleted(aThis, aRes->groupName());
       }
+      */
       // redisplay also removed feature (used for sketch and AISObject)
       ModelAPI_EventCreator::get()->sendUpdated(aFeature, EVENT_DISP);
+      aFeature->erase();
     } else
       aFIter.Next();
   }
@@ -913,6 +927,11 @@ void Model_Document::objectIsReferenced(const ObjectPtr& theObject)
       boost::shared_ptr<ModelAPI_Document> aThis = 
         Model_Application::getApplication()->getDocument(myID);
       ModelAPI_EventCreator::get()->sendDeleted(aThis, ModelAPI_ResultBody::group());
+
+      static Events_Loop* aLoop = Events_Loop::loop();
+      static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+      static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
+      aECreator->sendUpdated(aResult, EVENT_DISP);
     }
   }
 }
@@ -924,11 +943,12 @@ void Model_Document::objectIsNotReferenced(const ObjectPtr& theObject)
   if (aResult) {
     std::set<ResultPtr>::iterator aFind = myConcealedResults.find(aResult);
     if (aFind != myConcealedResults.end()) {
+      ResultPtr aFeature = *aFind;
       myConcealedResults.erase(aFind);
       boost::shared_ptr<ModelAPI_Document> aThis = 
         Model_Application::getApplication()->getDocument(myID);
       static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_CREATED);
-      ModelAPI_EventCreator::get()->sendUpdated(*aFind, anEvent, false);
+      ModelAPI_EventCreator::get()->sendUpdated(aFeature, anEvent, false);
     } else {
       Events_Error::send(std::string("The object '") + aResult->data()->name() +
         "' was not referenced '");
index 0d421704ba56c4eac5ecf8b8cafe0212d2a4ec83..421c493e27f8ee577ba7ce00695ae54b87be8f31 100644 (file)
@@ -39,7 +39,7 @@ Model_ObjectUpdatedMessage::Model_ObjectUpdatedMessage(const ObjectPtr& theObjec
     myObjects.insert(theObject);
 }
 
-std::set<ObjectPtr> Model_ObjectUpdatedMessage::objects() const
+const std::set<ObjectPtr>& Model_ObjectUpdatedMessage::objects() const
 {
   return myObjects;
 }
index 74d38a7fdebe194b74d132f1526dd4ba4242fd6a..f30c447904ecd73694bb3796e5fda090b6297861 100644 (file)
@@ -36,7 +36,7 @@ class Model_ObjectUpdatedMessage : public ModelAPI_ObjectUpdatedMessage
  public:
 
   /// Returns the feature that has been updated
-  virtual std::set<ObjectPtr> objects() const;
+  virtual const std::set<ObjectPtr>& objects() const;
 
   //! Creates a new empty group (to store it in the loop before flush)
   virtual boost::shared_ptr<Events_MessageGroup> newEmpty();
index d6503ee7622f8d372afcb0281e9ab2710a55eaa8..51f97e0f717c628408167d9eb638e4798cd07433 100644 (file)
@@ -46,11 +46,17 @@ void Model_Session::startOperation()
 void Model_Session::finishOperation()
 {
   ROOT_DOC->finishOperation();
+  static boost::shared_ptr<Events_Message> aFinishMsg
+    (new Events_Message(Events_Loop::eventByName("FinishOperation")));
+  Events_Loop::loop()->send(aFinishMsg);
 }
 
 void Model_Session::abortOperation()
 {
   ROOT_DOC->abortOperation();
+  static boost::shared_ptr<Events_Message> anAbortMsg
+    (new Events_Message(Events_Loop::eventByName("AbortOperation")));
+  Events_Loop::loop()->send(anAbortMsg);
 }
 
 bool Model_Session::isOperation()
index 70d97733047d062ec3e411032b61fae96c7fba0a..34637a08cbec2f3b3211c7331991a50bc2ae0572 100644 (file)
@@ -22,14 +22,22 @@ using namespace std;
 
 Model_Update MY_INSTANCE;  /// the only one instance initialized on load of the library
 
-Model_Update::Model_Update() : isCreated(false)
+Model_Update::Model_Update()
 {
-  static const Events_ID kChangedEvent = Events_Loop::loop()->eventByName("PreferenceChanged");
-  Events_Loop::loop()->registerListener(this, kChangedEvent);
-  static const Events_ID kRebuildEvent = Events_Loop::loop()->eventByName("Rebuild");
-  Events_Loop::loop()->registerListener(this, kRebuildEvent);
-  Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_CREATED));
-  Events_Loop::loop()->registerListener(this, Events_Loop::eventByName(EVENT_OBJECT_UPDATED));
+  Events_Loop* aLoop = Events_Loop::loop();
+  static const Events_ID kChangedEvent = aLoop->eventByName("PreferenceChanged");
+  aLoop->registerListener(this, kChangedEvent);
+  static const Events_ID kRebuildEvent = aLoop->eventByName("Rebuild");
+  aLoop->registerListener(this, kRebuildEvent);
+  static const Events_ID kCreatedEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED);
+  aLoop->registerListener(this, kCreatedEvent);
+  static const Events_ID kUpdatedEvent = Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED);
+  aLoop->registerListener(this, kUpdatedEvent);
+  static const Events_ID kOpFinishEvent = aLoop->eventByName("FinishOperation");
+  aLoop->registerListener(this, kOpFinishEvent);
+  static const Events_ID kOpAbortEvent = aLoop->eventByName("AbortOperation");
+  aLoop->registerListener(this, kOpAbortEvent);
+
   Config_PropManager::registerProp("Model update", "automatic_rebuild", "Rebuild automatically",
                                    Config_Prop::Bool, "false");
   isAutomatic = Config_PropManager::findProp("Model update", "automatic_rebuild")->value() == "true";
@@ -37,8 +45,13 @@ Model_Update::Model_Update() : isCreated(false)
 
 void Model_Update::processEvent(const boost::shared_ptr<Events_Message>& theMessage)
 {
-  static const Events_ID kChangedEvent = Events_Loop::loop()->eventByName("PreferenceChanged");
-  static const Events_ID kRebuildEvent = Events_Loop::loop()->eventByName("Rebuild");
+  static Events_Loop* aLoop = Events_Loop::loop();
+  static const Events_ID kChangedEvent = aLoop->eventByName("PreferenceChanged");
+  static const Events_ID kRebuildEvent = aLoop->eventByName("Rebuild");
+  static const Events_ID kCreatedEvent = aLoop->eventByName(EVENT_OBJECT_CREATED);
+  static const Events_ID kUpdatedEvent = aLoop->eventByName(EVENT_OBJECT_UPDATED);
+  static const Events_ID kOpFinishEvent = aLoop->eventByName("FinishOperation");
+  static const Events_ID kOpAbortEvent = aLoop->eventByName("AbortOperation");
   bool isAutomaticChanged = false;
   if (theMessage->eventID() == kChangedEvent) { // automatic and manual rebuild flag is changed
     isAutomatic = 
@@ -48,12 +61,20 @@ void Model_Update::processEvent(const boost::shared_ptr<Events_Message>& theMess
       isAutomaticChanged = true;
       isAutomatic = true;
     }
+  } else if (theMessage->eventID() == kCreatedEvent || theMessage->eventID() == kUpdatedEvent) {
+    boost::shared_ptr<ModelAPI_ObjectUpdatedMessage> aMsg =
+        boost::dynamic_pointer_cast<ModelAPI_ObjectUpdatedMessage>(theMessage);
+    const std::set<ObjectPtr>& anObjs = aMsg->objects();
+    std::set<ObjectPtr>::const_iterator anObjIter = anObjs.cbegin();
+    for(; anObjIter != anObjs.cend(); anObjIter++)
+      myJustCreatedOrUpdated.insert(*anObjIter);
+  } else if (theMessage->eventID() == kOpFinishEvent || theMessage->eventID() == kOpAbortEvent) {
+    myJustCreatedOrUpdated.clear();
+    return;
   }
 
   if (isExecuted)
     return;  // nothing to do: it is executed now
-  // execute just created features anyway
-  isCreated = theMessage->eventID() == Events_Loop::eventByName(EVENT_OBJECT_CREATED);
 
   //Events_LongOp::start(this);
   isExecuted = true;
@@ -86,11 +107,10 @@ void Model_Update::processEvent(const boost::shared_ptr<Events_Message>& theMess
   }
   myUpdated.clear();
   // flush
-  static Events_ID EVENT_DISP = Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY);
-  Events_Loop::loop()->flush(EVENT_DISP);
+  static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+  aLoop->flush(EVENT_DISP);
   //Events_LongOp::end(this);
   if (isAutomaticChanged) isAutomatic = false;
-  isCreated = false;
   isExecuted = false;
 }
 
@@ -153,18 +173,30 @@ bool Model_Update::updateFeature(FeaturePtr theFeature)
           !theFeature->isPersistentResult()) {
         ModelAPI_ValidatorsFactory* aFactory = ModelAPI_Session::get()->validators();
         if (aFactory->validate(theFeature)) {
-          if (isAutomatic || (isCreated && myInitial.find(theFeature) != myInitial.end()) ||
+          if (isAutomatic || (myJustCreatedOrUpdated.find(theFeature) != myJustCreatedOrUpdated.end()) ||
             !theFeature->isPersistentResult() /* execute quick, not persistent results */) {
             try {
               theFeature->execute();
-              theFeature->data()->mustBeUpdated(false);
             } catch(...) {
               Events_Error::send(
                 "Feature " + theFeature->getKind() + " has failed during the execution");
               theFeature->eraseResults();
             }
+            theFeature->data()->mustBeUpdated(false);
+            const std::list<boost::shared_ptr<ModelAPI_Result> >& aResults = theFeature->results();
+            std::list<boost::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
+            for (; aRIter != aResults.cend(); aRIter++) {
+              boost::shared_ptr<ModelAPI_Result> aRes = *aRIter;
+              aRes->data()->mustBeUpdated(false);
+            }
           } else {
             theFeature->data()->mustBeUpdated(true);
+            const std::list<boost::shared_ptr<ModelAPI_Result> >& aResults = theFeature->results();
+            std::list<boost::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
+            for (; aRIter != aResults.cend(); aRIter++) {
+              boost::shared_ptr<ModelAPI_Result> aRes = *aRIter;
+              aRes->data()->mustBeUpdated(true);
+            }
             aMustbeUpdated = false;
           }
         } else {
index ff3e67660b3b4875ad31bb3c8a1def6fe30fa858..f73378580918531e8c17f3e28da3cbce8eb18fda 100644 (file)
@@ -28,8 +28,9 @@ class Model_Update : public Events_Listener
   bool isExecuted;
   /// to know execute or not automatically all update
   bool isAutomatic;
-  /// execute just created features for sure
-  bool isCreated;
+  /// just created features: they must be updated immideately even in not-automatic mode for 
+  /// preview; cleared on commit operations
+  std::set<boost::shared_ptr<ModelAPI_Object> > myJustCreatedOrUpdated;
 
  public:
   /// Is called only once, on startup of the application
index a73044d4a1ebcd57319cc2cd3548bb3ef7e55f9f..c54b395561b908739737abb7ba47674b92e11f43 100644 (file)
@@ -34,7 +34,7 @@ class ModelAPI_Attribute
   }
 
   /// Sets the owner of this attribute
-  MODELAPI_EXPORT void setObject(const boost::shared_ptr<ModelAPI_Object>& theObject)
+  MODELAPI_EXPORT virtual void setObject(const boost::shared_ptr<ModelAPI_Object>& theObject)
   {
     myObject = theObject;
   }
index b2b9add754c302610ffcf72e5e768c3b6294a2a8..7345815e22a1079a3eceacdecf47a4e3c5c0e7a5 100644 (file)
@@ -41,7 +41,7 @@ class ModelAPI_ObjectUpdatedMessage : public Events_MessageGroup
 
  public:
   /// Returns the feature that has been updated
-  virtual std::set<ObjectPtr> objects() const = 0;
+  virtual const std::set<ObjectPtr>& objects() const = 0;
 
   //! Creates a new empty group (to store it in the loop before flush)
   virtual boost::shared_ptr<Events_MessageGroup> newEmpty() = 0;
index aec952e79bd94dfee020e27ef64785f0cd13c393..b3dc06045a0461975b881b84a58398613e2281ab 100644 (file)
@@ -64,12 +64,18 @@ void ModelAPI_Feature::removeResult(const boost::shared_ptr<ModelAPI_Result>& th
 {
   std::list<boost::shared_ptr<ModelAPI_Result> >::iterator aResIter = myResults.begin();
   for(; aResIter != myResults.end(); aResIter++) {
-    if (*aResIter == theResult) {
-      std::string aGroup = (*aResIter)->groupName();
-      (*aResIter)->data()->erase();
+    ResultPtr aRes = *aResIter;
+    if (aRes == theResult) {
+      std::string aGroup = aRes->groupName();
+      aRes->data()->erase();
       myResults.erase(aResIter);
+
       static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED);
+      static Events_Loop* aLoop = Events_Loop::loop();
+      static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+      static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
       ModelAPI_EventCreator::get()->sendDeleted(document(), aGroup);
+      aECreator->sendUpdated(aRes, EVENT_DISP);
       break;
     }
   }
@@ -78,14 +84,19 @@ void ModelAPI_Feature::removeResult(const boost::shared_ptr<ModelAPI_Result>& th
 void ModelAPI_Feature::eraseResults()
 {
   if (!myResults.empty()) {
-    static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED);
+    static Events_Loop* aLoop = Events_Loop::loop();
+    static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+    static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
+
     std::list<boost::shared_ptr<ModelAPI_Result> >::iterator aResIter = myResults.begin();
     for(; aResIter != myResults.end(); aResIter++) {
-        (*aResIter)->data()->erase();
-        ModelAPI_EventCreator::get()->sendDeleted(document(), (*aResIter)->groupName());
+      (*aResIter)->data()->erase();
+      ModelAPI_EventCreator::get()->sendDeleted(document(), (*aResIter)->groupName());
+      aECreator->sendUpdated(*aResIter, EVENT_DISP);
     }
     myResults.clear();
     // flush it to avoid left presentations after input of invalid arguments (radius=0)
+    static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_DELETED);
     Events_Loop::loop()->flush(anEvent);
   }
 }
@@ -95,13 +106,24 @@ boost::shared_ptr<ModelAPI_Document> ModelAPI_Feature::documentToAdd()
   return ModelAPI_Session::get()->activeDocument();
 }
 
-ModelAPI_Feature::~ModelAPI_Feature()
+void ModelAPI_Feature::erase()
 {
+  static Events_Loop* aLoop = Events_Loop::loop();
+  static Events_ID EVENT_DISP = aLoop->eventByName(EVENT_OBJECT_TO_REDISPLAY);
+  static const ModelAPI_EventCreator* aECreator = ModelAPI_EventCreator::get();
+
   while (!myResults.empty()) {  // remove one by one with messages
     boost::shared_ptr<ModelAPI_Result> aRes = *(myResults.begin());
     myResults.erase(myResults.begin());
-    ModelAPI_EventCreator::get()->sendDeleted(aRes->document(), aRes->groupName());
+    aECreator->sendDeleted(aRes->document(), aRes->groupName());
+    aECreator->sendUpdated(aRes, EVENT_DISP);
   }
+  ModelAPI_Object::erase();
+}
+
+ModelAPI_Feature::~ModelAPI_Feature()
+{
+  erase();
 }
 
 FeaturePtr ModelAPI_Feature::feature(ObjectPtr theObject)
index 2c252429df3943d7e9530b33a8945a6bd7f58975..a6c51d0407958d4831cc29773cc8e127aec5e9d1 100644 (file)
@@ -61,6 +61,8 @@ class ModelAPI_Feature : public ModelAPI_Object
   MODELAPI_EXPORT void removeResult(const boost::shared_ptr<ModelAPI_Result>& theResult);
   /// removes all results from the feature
   MODELAPI_EXPORT void eraseResults();
+  /// removes all fields from this feature: results, data, etc
+  MODELAPI_EXPORT virtual void erase();
 
   /// Returns true if result is persistent (stored in document) and on undo-redo, save-open
   /// it is not needed to recompute it.
index 2d4838c17252f4feed9cfb8d078d21e0514f01ad..9241d9b6545310c70a13dd62e1e65d30186314d4 100644 (file)
@@ -6,6 +6,7 @@
 #define ModelAPI_Object_H_
 
 #include "ModelAPI.h"
+#include "ModelAPI_Data.h"
 
 #include <boost/shared_ptr.hpp>
 
@@ -66,7 +67,14 @@ class ModelAPI_Object
     myDoc = theDoc;
   }
 
+  /// removes all fields from this feature
+  MODELAPI_EXPORT virtual void erase() {
+    if (myData) myData->erase();
+    setData(DataPtr());
+  }
+
   friend class Model_Document;
+
 };
 
 typedef boost::shared_ptr<ModelAPI_Object> ObjectPtr;
index 53a16851c72c609538a10a423a3af80a5bbbbba3..81a812ca5b619950684d85b871356739ffaaeeca 100644 (file)
@@ -798,7 +798,7 @@ bool SketchSolver_ConstraintGroup::updateGroup()
   bool isAllValid = true;
   bool isCCRemoved = false;  // indicates that at least one of coincidence constraints was removed
   while (isAllValid && aConstrIter != myConstraintMap.rend()) {
-    if (!aConstrIter->first->data()->isValid()) {
+    if (!aConstrIter->first->data() || !aConstrIter->first->data()->isValid()) {
       if (aConstrIter->first->getKind().compare(SketchPlugin_ConstraintCoincidence::ID()) == 0)
         isCCRemoved = true;
       std::map<boost::shared_ptr<SketchPlugin_Constraint>, Slvs_hConstraint>::reverse_iterator aCopyIter =
index 26b577201d40140aa6e68280cff0e162e49c4997..42ce8ddd522d7cc56c0be21367fef0ae1b64ba23 100644 (file)
@@ -46,7 +46,7 @@ class SketchSolver_ConstraintGroup
   /// \brief Check for valid sketch data
   inline bool isWorkplaneValid() const
   {
-    return mySketch->data()->isValid();
+    return mySketch->data() && mySketch->data()->isValid();
   }
 
   /** \brief Adds or updates a constraint in the group
index e0692fc0b9bf860cd3ce672ae82adc46e14cc92e..58260b79c6cd24bce86d4a53a138de985531c0a4 100644 (file)
@@ -114,6 +114,7 @@ bool XGUI_OperationMgr::validateOperation(ModuleBase_Operation* theOperation)
 {
   //Get operation feature to validate
   FeaturePtr aFeature = theOperation->feature();
+  if (!aFeature) return true; // rename operation
   //Get validators for the Id
   SessionPtr aMgr = ModelAPI_Session::get();
   ModelAPI_ValidatorsFactory* aFactory = aMgr->validators();
index c492229c9a54e67712a8cecaefbc503da1e921d6..66f8d8b961ef4ef8d6ebe489fc439ffe04d5734b 100644 (file)
@@ -78,8 +78,16 @@ QVariant XGUI_TopDataModel::data(const QModelIndex& theIndex, int theRole) const
         case ConstructFolder:
           return QIcon(":pictures/constr_folder.png");
         case ConstructObject:
-        case BodiesObject:
+        case BodiesObject: {
+          DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument();
+          std::string aGroup = theIndex.internalId() == ConstructObject ?
+            ModelAPI_ResultConstruction::group() : ModelAPI_ResultBody::group();
+          ObjectPtr anObject = aRootDoc->object(aGroup, theIndex.row());
+          if (anObject && anObject->data() && anObject->data()->mustBeUpdated()) {
+            return QIcon(":pictures/constr_object_modified.png");
+          }
           return QIcon(":pictures/constr_object.png");
+        }
       }
       break;
 
@@ -297,8 +305,15 @@ QVariant XGUI_PartDataModel::data(const QModelIndex& theIndex, int theRole) cons
         case BodiesFolder:
           return QIcon(":pictures/constr_folder.png");
         case ConstructObject:
-        case BodiesObject:
+        case BodiesObject: {
+          std::string aGroup = theIndex.internalId() == ConstructObject ?
+            ModelAPI_ResultConstruction::group() : ModelAPI_ResultBody::group();
+          ObjectPtr anObject = partDocument()->object(aGroup, theIndex.row());
+          if (anObject && anObject->data() && anObject->data()->mustBeUpdated()) {
+            return QIcon(":pictures/constr_object_modified.png");
+          }
           return QIcon(":pictures/constr_object.png");
+        }
         case HistoryObject: {
           ObjectPtr aObject = partDocument()->object(ModelAPI_Feature::group(), theIndex.row() - 3);
           FeaturePtr aFeature = boost::dynamic_pointer_cast<ModelAPI_Feature>(aObject);
index 07c5f4c9222fa875710815a3b5b4b1ba7aedc259..dd4aa4808ef04660fb4f30c95921bef074af6a4a 100644 (file)
@@ -34,6 +34,7 @@
      <file>pictures/params_folder.png</file>
      <file>pictures/constr_folder.png</file>
      <file>pictures/constr_object.png</file>
+     <file>pictures/constr_object_modified.png</file>
      <file>pictures/part_ico.png</file>
      <file>pictures/properties.png</file>
      <file>pictures/features.png</file>
diff --git a/src/XGUI/pictures/constr_object_modified.png b/src/XGUI/pictures/constr_object_modified.png
new file mode 100644 (file)
index 0000000..966a6c9
Binary files /dev/null and b/src/XGUI/pictures/constr_object_modified.png differ