Salome HOME
Updated copyright comment
[modules/shaper.git] / src / PartSet / PartSet_OverconstraintListener.cpp
index 656593d9b5348f6c29fc554627f6d406c2002872..b8924b8a27bc59237d8b7a931efaa3dfede4de3a 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2021  CEA/DEN, EDF R&D
+// Copyright (C) 2014-2024  CEA, EDF
 //
 // This library is free software; you can redistribute it and/or
 // modify it under the terms of the GNU Lesser General Public
 #include <ModelAPI_Tools.h>
 #include <ModelAPI_AttributeString.h>
 
+// Attention: keep the next include here,
+// otherwise it causes compilation errors at least on Debian 8
+#include <ModuleBase_Preferences.h>
+
 #include "PartSet_OverconstraintListener.h"
 #include <PartSet_Module.h>
 #include <PartSet_SketcherMgr.h>
@@ -38,6 +42,8 @@
 #include "SketchPlugin_ConstraintHorizontal.h"
 #include "SketchPlugin_ConstraintVertical.h"
 
+#include <SUIT_ResourceMgr.h>
+
 #include "Events_Loop.h"
 
 #include <GeomAPI_IPresentable.h>
@@ -62,6 +68,7 @@ PartSet_OverconstraintListener::PartSet_OverconstraintListener(ModuleBase_IWorks
 
   aLoop->registerListener(this, ModelAPI_EventReentrantMessage::eventId());
   aLoop->registerListener(this, SketchPlugin_MacroArcReentrantMessage::eventId());
+  aLoop->registerListener(this, Events_Loop::eventByName(EVENT_REMOVE_CONSTRAINTS));
 }
 
 void PartSet_OverconstraintListener::setActive(const bool& theActive)
@@ -225,7 +232,35 @@ void PartSet_OverconstraintListener::processEvent(const std::shared_ptr<Events_M
       }
     }
   }
+  else if (anEventID == Events_Loop::eventByName(EVENT_REMOVE_CONSTRAINTS)) {
+    std::shared_ptr<ModelAPI_CheckConstraintsMessage> aConstraintsMsg =
+      std::dynamic_pointer_cast<ModelAPI_CheckConstraintsMessage>(theMessage);
+    if (aConstraintsMsg.get()) {
+      myObjectsToRemove = aConstraintsMsg->constraints();
+
+      std::set<ObjectPtr>::const_iterator anIt = myObjectsToRemove.begin();
+
+      PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
+
+      for (; anIt != myObjectsToRemove.end(); )
+      {
+        ObjectPtr anObject = *anIt;
+        FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anObject);
+        std::string aType = aFeature->getKind();
+        if ((aType == SketchPlugin_ConstraintHorizontal::ID() ||
+             aType == SketchPlugin_ConstraintVertical::ID()) &&
+             !aModule->sketchReentranceMgr()->isLastAutoConstraint(*anIt))
+          anIt = myObjectsToRemove.erase(anIt);
+        else
+          anIt++;
+      }
+
+      if (myObjectsToRemove.empty())
+        return;
 
+      QTimer::singleShot(5, aModule, SLOT(onRemoveConflictingConstraints()));
+    }
+  }
 #ifdef DEBUG_FEATURE_OVERCONSTRAINT_LISTENER
   aCurrentInfoStr = getObjectsInfo(myConflictingObjects);
   qDebug(QString("RESULT: current objects count = %1:%2\n")
@@ -236,40 +271,43 @@ void PartSet_OverconstraintListener::processEvent(const std::shared_ptr<Events_M
 bool PartSet_OverconstraintListener::appendConflictingObjects(
                                                const std::set<ObjectPtr>& theConflictingObjects)
 {
-  std::set<ObjectPtr> aModifiedObjects;
-
-  // set error state for new objects and append them in the internal map of objects
-  std::set<ObjectPtr>::const_iterator
-    anIt = theConflictingObjects.begin(), aLast = theConflictingObjects.end();
-  FeaturePtr aFeature;
-  bool isHVConstraint = false;
-  for (; anIt != aLast; anIt++) {
-    ObjectPtr anObject = *anIt;
-    if (myConflictingObjects.find(anObject) == myConflictingObjects.end()) { // it is not found
-      aModifiedObjects.insert(anObject);
-      myConflictingObjects.insert(anObject);
-    }
-    if (!isHVConstraint) {
-      aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anObject);
-      if (aFeature) {
-        std::string aType = aFeature->getKind();
-        isHVConstraint = (aType == SketchPlugin_ConstraintHorizontal::ID()) ||
-          (aType == SketchPlugin_ConstraintVertical::ID());
+  bool isAllowToChange = ModuleBase_Preferences::resourceMgr()->booleanValue(SKETCH_TAB_NAME,
+                                        "allow_change_constraint");
+  if (isAllowToChange) {
+    std::set<ObjectPtr> aModifiedObjects;
+
+    // set error state for new objects and append them in the internal map of objects
+    std::set<ObjectPtr>::const_iterator
+      anIt = theConflictingObjects.begin(), aLast = theConflictingObjects.end();
+
+    int aCountOfSimilarConstraints = 0;
+    for (; anIt != aLast; anIt++) {
+      ObjectPtr anObject = *anIt;
+      if (myConflictingObjects.find(anObject) == myConflictingObjects.end()) { // it is not found
+        aModifiedObjects.insert(anObject);
+        myConflictingObjects.insert(anObject);
       }
+      else
+        ++aCountOfSimilarConstraints;
     }
-  }
-  bool isUpdated = !aModifiedObjects.empty();
-  if (isUpdated)
-    redisplayObjects(aModifiedObjects);
 
-  // If the conflicting object is an automatic constraint caused the conflict
-  // then it has to be deleted
-  if (isHVConstraint) {
-    PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
-    QTimer::singleShot(5, aModule, SLOT(onConflictingConstraints()));
-  }
+    if (theConflictingObjects.size() == aCountOfSimilarConstraints)
+      return false;
 
-  return isUpdated;
+    std::shared_ptr<ModelAPI_CheckConstraintsMessage> aMessage =
+      std::shared_ptr<ModelAPI_CheckConstraintsMessage>(
+        new ModelAPI_CheckConstraintsMessage(
+          Events_Loop::eventByName(EVENT_CHECK_CONSTRAINTS)));
+    aMessage->setConstraints(theConflictingObjects);
+    Events_Loop::loop()->send(aMessage);
+
+    bool isUpdated = !aModifiedObjects.empty();
+    if (isUpdated)
+      redisplayObjects(aModifiedObjects);
+    return isUpdated;
+  }
+  else
+    return false;
 }
 
 bool PartSet_OverconstraintListener::repairConflictingObjects(