Salome HOME
Issue #1489 Multi-rotation problem if there is a reference to copied objects
authornds <nds@opencascade.com>
Thu, 19 May 2016 08:24:33 +0000 (11:24 +0300)
committernds <nds@opencascade.com>
Thu, 19 May 2016 08:24:57 +0000 (11:24 +0300)
16 files changed:
src/Model/Model_Objects.cpp
src/ModelAPI/ModelAPI_Tools.cpp
src/ModelAPI/ModelAPI_Tools.h
src/ModuleBase/ModuleBase_IModule.h
src/ModuleBase/ModuleBase_Tools.cpp
src/ModuleBase/ModuleBase_Tools.h
src/ParametersPlugin/ParametersPlugin_WidgetParamsMgr.cpp
src/PartSet/PartSet_ExternalObjectsMgr.cpp
src/PartSet/PartSet_Module.cpp
src/PartSet/PartSet_Module.h
src/PartSet/PartSet_SketcherMgr.cpp
src/PartSet/PartSet_SketcherMgr.h
src/PartSet/PartSet_WidgetSketchCreator.cpp
src/SketchPlugin/SketchPlugin_MultiRotation.cpp
src/XGUI/XGUI_Workshop.cpp
src/XGUI/XGUI_Workshop.h

index fa69915828b7bc6bf24d2161bc682ee5a25404ab..44ab4cf593c62d5a50744a031a5511382d9b2663 100644 (file)
@@ -240,7 +240,7 @@ void Model_Objects::removeFeature(FeaturePtr theFeature)
     for(; aRefIter != aRefs.end(); aRefIter++) {
       std::shared_ptr<ModelAPI_CompositeFeature> aComposite = 
         std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*aRefIter);
-      if (aComposite.get()) {
+      if (aComposite.get() && aComposite->isSub(theFeature)) {
         aComposite->removeFeature(theFeature);
       }
     }
index 20073da7c1a3242720678a5ede3933833a6fe404..658def2ef133c08390ec5b53cda62c6861b08f35 100755 (executable)
 #include <ModelAPI_AttributeDocRef.h>
 #include <list>
 #include <map>
+#include <iostream>
+
+#include <Events_Loop.h>
+#include <ModelAPI_Events.h>
+
+//#define DEBUG_REMOVE_FEATURES
+
+#ifdef DEBUG_REMOVE_FEATURES
+void printMapInfo(const std::map<FeaturePtr, std::set<FeaturePtr> >& theMainList,
+                  const std::string& thePrefix)
+{
+  std::map<FeaturePtr, std::set<FeaturePtr> >::const_iterator aMainIt = theMainList.begin(),
+                                                              aMainLast = theMainList.end();
+  std::string anInfo;
+  for (; aMainIt != aMainLast; aMainIt++) {
+    FeaturePtr aMainListFeature = aMainIt->first;
+    std::set<FeaturePtr> aMainRefList = aMainIt->second;
+    std::set<FeaturePtr>::const_iterator anIt = aMainRefList.begin(), aLast = aMainRefList.end();
+    std::string aRefsInfo;
+    for (; anIt != aLast; anIt++) {
+      aRefsInfo += (*anIt)->name().c_str();
+      if (anIt != aLast)
+        aRefsInfo += ", ";
+    }
+    if (!aRefsInfo.empty()) {
+      anInfo = anInfo + aMainListFeature->name().c_str() + ": " + aRefsInfo + "\n";
+    }
+  }
+  std::cout << thePrefix.c_str() << ": " << anInfo.c_str() << std::endl;
+}
+
+void printListInfo(const std::set<FeaturePtr>& theMainList,
+                  const std::string& thePrefix)
+{
+  std::set<FeaturePtr>::const_iterator aMainIt = theMainList.begin(),
+                                       aMainLast = theMainList.end();
+  std::string anInfo;
+  for (; aMainIt != aMainLast; aMainIt++) {
+    FeaturePtr aRefFeature = *aMainIt;
+    anInfo += aRefFeature->name().c_str();
+    if (aMainIt != aMainLast)
+      anInfo += ", ";
+  }
+  std::cout << thePrefix.c_str() << ": " << anInfo.c_str() << std::endl;
+}
+#endif
 
 namespace ModelAPI_Tools {
 
@@ -312,6 +358,196 @@ void allResults(const FeaturePtr& theFeature, std::list<ResultPtr>& theResults)
   }
 }
 
+bool removeFeaturesAndReferences(const std::set<FeaturePtr>& theFeatures,
+                                 const bool theFlushRedisplay,
+                                 const bool theUseComposite,
+                                 const bool theUseRecursion)
+{
+#ifdef DEBUG_REMOVE_FEATURES
+  printListInfo(theFeatures, "selection: ");
+#endif
+
+  std::map<FeaturePtr, std::set<FeaturePtr> > aReferences;
+  ModelAPI_Tools::findAllReferences(theFeatures, aReferences, theUseComposite, theUseRecursion);
+#ifdef DEBUG_REMOVE_FEATURES
+  printMapInfo(aReferences, "allDependencies: ");
+#endif
+
+  std::set<FeaturePtr> aFeaturesRefsTo;
+  ModelAPI_Tools::findRefsToFeatures(theFeatures, aReferences, aFeaturesRefsTo);
+#ifdef DEBUG_REMOVE_FEATURES
+  printListInfo(aFeaturesRefsTo, "references: ");
+#endif
+
+  std::set<FeaturePtr> aFeatures = theFeatures;
+  if (!aFeaturesRefsTo.empty())
+    aFeatures.insert(aFeaturesRefsTo.begin(), aFeaturesRefsTo.end());
+#ifdef DEBUG_REMOVE_FEATURES
+  printListInfo(aFeatures, "removeFeatures: ");
+#endif
+
+  return ModelAPI_Tools::removeFeatures(aFeatures, false);
+}
+
+bool removeFeatures(const std::set<FeaturePtr>& theFeatures,
+                    const bool theFlushRedisplay)
+{
+  bool isDone = false;
+  std::set<FeaturePtr>::const_iterator anIt = theFeatures.begin(),
+                                       aLast = theFeatures.end();
+  for (; anIt != aLast; anIt++) {
+    FeaturePtr aFeature = *anIt;
+    if (aFeature.get()) {
+      DocumentPtr aDoc = aFeature->document();
+      // flush REDISPLAY signal after remove feature
+      aDoc->removeFeature(aFeature);
+      isDone = true;
+    }
+  }
+  if (isDone && theFlushRedisplay) {
+    // the redisplay signal should be flushed in order to erase the feature presentation in the viewer
+    // if should be done after removeFeature() of document
+    Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY));
+  }
+  return true;
+}
+
+// Fills the references list by all references of the feature from the references map.
+// This is a recusive method to find references by next found feature in the map of references.
+// \param theFeature a feature to find references
+// \param theReferencesMap a map of references
+// \param theReferences an out container of references
+void addRefsToFeature(const FeaturePtr& theFeature,
+                      const std::map<FeaturePtr, std::set<FeaturePtr> >& theReferencesMap,
+                      std::set<FeaturePtr>& theReferences)
+{
+  if (theReferencesMap.find(theFeature) == theReferencesMap.end())
+    return; // this feature is not in the selection list, so exists without references to it
+  std::set<FeaturePtr> aMainReferences = theReferencesMap.at(theFeature);
+
+  std::set<FeaturePtr>::const_iterator anIt = aMainReferences.begin(),
+                                       aLast = aMainReferences.end();
+  for (; anIt != aLast; anIt++) {
+    FeaturePtr aRefFeature = *anIt;
+    if (theReferences.find(aRefFeature) == theReferences.end())
+      theReferences.insert(aRefFeature);
+    addRefsToFeature(aRefFeature, theReferencesMap, theReferences);
+  }
+}
+
+// For each feature from the feature list it searches references to the feature and append them
+// to the references map. This is a recusive method.
+// \param theFeature a feature to find references
+// \param theReferencesMap a map of references
+// \param theReferences an out container of references
+void findReferences(const std::set<FeaturePtr>& theFeatures,
+                    std::map<FeaturePtr, std::set<FeaturePtr> >& theReferences,
+                    const bool theUseComposite, const bool theUseRecursion)
+{
+  std::set<FeaturePtr>::const_iterator anIt = theFeatures.begin(),
+                                        aLast = theFeatures.end();
+  for (; anIt != aLast; anIt++) {
+    FeaturePtr aFeature = *anIt;
+    if (aFeature.get() && theReferences.find(aFeature) == theReferences.end()) {
+      DocumentPtr aSelFeatureDoc = aFeature->document();
+      std::set<FeaturePtr> aSelRefFeatures;
+      aSelFeatureDoc->refsToFeature(aFeature, aSelRefFeatures, false/*do not emit signals*/);
+      if (theUseComposite) { // do not filter selection
+        theReferences[aFeature] = aSelRefFeatures;
+      }
+      else { // filter references to skip composition features of the current feature
+        std::set<FeaturePtr> aFilteredFeatures;
+        std::set<FeaturePtr>::const_iterator anIt = aSelRefFeatures.begin(),
+                                             aLast = aSelRefFeatures.end();
+        for (; anIt != aLast; anIt++) {
+          FeaturePtr aCFeature = *anIt;
+          CompositeFeaturePtr aComposite = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aCFeature);
+          if (aComposite.get() && aComposite->isSub(aFeature))
+            continue; /// composite of the current feature should be skipped
+          aFilteredFeatures.insert(aCFeature);
+        }
+        theReferences[aFeature] = aFilteredFeatures;
+      }
+      if (theUseRecursion)
+        findReferences(aSelRefFeatures, theReferences, theUseComposite, theUseRecursion);
+    }
+  }
+}
+
+void findAllReferences(const std::set<FeaturePtr>& theFeatures,
+                       std::map<FeaturePtr, std::set<FeaturePtr> >& theReferences,
+                       const bool theUseComposite,
+                       const bool theUseRecursion)
+{
+  // For dependencies, find main_list:
+  // sk_1(ext_1, vertex_1)
+  // ext_1(bool_1, sk_3)
+  // vertex_1()
+  // sk_2(ext_2)
+  // ext_2(bool_2)
+  // sk_3()
+  // Information: bool_1 is not selected, ext_2(bool_2) exists
+  // find all referenced features
+  std::map<FeaturePtr, std::set<FeaturePtr> > aMainList;
+  findReferences(theFeatures, aMainList, theUseComposite, theUseRecursion);
+
+#ifdef DEBUG_REMOVE_FEATURES
+  printMapInfo(aMainList, "firstDependencies");
+#endif
+  // find all dependencies for each object:
+  // sk_1(ext_1, vertex_1) + (sk_3, bool_1)
+  // ext_1(bool_1, sk_3)
+  // vertex_1()
+  // sk_2(ext_2) + (bool_1)
+  // ext_2(bool_1)
+  // sk_3()
+  std::map<FeaturePtr, std::set<FeaturePtr> >::const_iterator aMainIt = aMainList.begin(),
+                                                              aMainLast = aMainList.end();
+  for (; aMainIt != aMainLast; aMainIt++) {
+    FeaturePtr aMainListFeature = aMainIt->first;
+    //std::string aName = aMainListFeature->name();
+    std::set<FeaturePtr> aMainRefList = aMainIt->second;
+    std::set<FeaturePtr> anAddRefFeatures;
+
+    std::set<FeaturePtr>::const_iterator anIt = aMainRefList.begin(),
+                                         aLast = aMainRefList.end();
+    for (; anIt != aLast; anIt++) {
+      FeaturePtr aFeature = *anIt;
+      addRefsToFeature(aFeature, aMainList, aMainRefList);
+    }
+    theReferences[aMainListFeature] = aMainRefList;
+  }
+
+#ifdef DEBUG_REMOVE_FEATURES
+  printMapInfo(theReferences, "allDependencies");
+#endif
+}
+
+void findRefsToFeatures(const std::set<FeaturePtr>& theFeatures,
+                        const std::map<FeaturePtr, std::set<FeaturePtr> >& theReferences,
+                        std::set<FeaturePtr>& theFeaturesRefsTo)
+{
+  std::set<FeaturePtr>::const_iterator anIt = theFeatures.begin(),
+                                       aLast = theFeatures.end();
+  for (; anIt != aLast; anIt++) {
+    FeaturePtr aFeature = *anIt;
+    if (theReferences.find(aFeature) == theReferences.end())
+      continue;
+    std::set<FeaturePtr> aRefList = theReferences.at(aFeature);
+    std::set<FeaturePtr>::const_iterator aRefIt = aRefList.begin(), aRefLast = aRefList.end();
+    for (; aRefIt != aRefLast; aRefIt++) {
+      FeaturePtr aRefFeature = *aRefIt;
+      CompositeFeaturePtr aComposite = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aRefFeature);
+      if (aComposite.get() && aComposite->isSub(aFeature))
+        continue; /// composite of the current feature should not be removed
+
+      if (theFeatures.find(aRefFeature) == theFeatures.end() && // it is not selected
+          theFeaturesRefsTo.find(aRefFeature) == theFeaturesRefsTo.end()) // it is not added
+        theFeaturesRefsTo.insert(aRefFeature);
+    }
+  }
+}
+
 } // namespace ModelAPI_Tools
 
 
index 02090e51604dbd6e5f5081db8c66154125ede186..9085e6d776d699c2f02be326e3c303ab42112011 100755 (executable)
@@ -19,6 +19,8 @@
 #include <GeomAPI_Shape.h>
 
 #include <vector>
+#include <map>
+#include <set>
 
 namespace ModelAPI_Tools {
 /// Returns shape from the given Result object
@@ -98,6 +100,46 @@ MODELAPI_EXPORT bool hasSubResults(const ResultPtr& theResult);
 */
 MODELAPI_EXPORT void allResults(const FeaturePtr& theFeature, std::list<ResultPtr>& theResults);
 
+
+/*! Removes features from the document
+* \param theFeatures a list of features to be removed
+* \param theFlushRedisplay a boolean value if the redisplay signal should be flushed
+* \return true if at least one feature is removed
+*/
+MODELAPI_EXPORT bool removeFeaturesAndReferences(const std::set<FeaturePtr>& theFeatures,
+                                                 const bool theFlushRedisplay = false,
+                                                 const bool theUseComposite = false,
+                                                 const bool theUseRecursion = true);
+
+/*! Removes features from the document
+* \param theFeatures a list of features to be removed
+* \param theFlushRedisplay a boolean value if the redisplay signal should be flushed
+* \return true if at least one feature is removed
+*/
+MODELAPI_EXPORT bool removeFeatures(const std::set<FeaturePtr>& theFeatures,
+                                    const bool theFlushRedisplay);
+
+/*! Build a map of references for the given set of features
+* \param theFeatures a list of features
+* \param theReferences a map of all references to the features
+* \param theUseComposite state if the composite features of the reference should be in the map
+* \param theUseRecursion state if references for features out of the sources feature
+         list are put into the result container. E.g. if theFeatures contains "Sketch_2", map will
+         contain references to this feature also.
+*/
+MODELAPI_EXPORT void findAllReferences(const std::set<FeaturePtr>& theFeatures,
+                                       std::map<FeaturePtr, std::set<FeaturePtr> >& theReferences,
+                                       const bool theUseComposite = true,
+                                       const bool theUseRecursion = true);
+
+/*! In the map of references find all features referenced to the source feature
+* \param theFeatures a list of features to find references
+* \param theReferences a map of all references to the features
+* \param theFeaturesRefsTo an out list of referenced features
+*/
+MODELAPI_EXPORT void findRefsToFeatures(const std::set<FeaturePtr>& aFeatures,
+                                        const std::map<FeaturePtr, std::set<FeaturePtr> >& aReferences,
+                                        std::set<FeaturePtr>& aFeaturesRefsTo);
 }
 
 #endif
index 769af80dc43f302a7e168acf2e6b03255da48426..f9b5868b7c973c01ed39fc4517ec281a620c9249 100755 (executable)
@@ -176,7 +176,7 @@ class MODULEBASE_EXPORT ModuleBase_IModule : public QObject
 \r
   /// Make some functionality after the objects are hidden in viewer\r
   /// \param theObjects a list of hidden objects\r
-  virtual void processHiddenObject(const std::list<ObjectPtr>& theObjects) {};\r
+  //virtual void processHiddenObject(const std::list<ObjectPtr>& theObjects) {};\r
 \r
   /// Returns true if selection for the object can be activate.\r
   /// By default a result or feature of the current operation can not be activated\r
index 3211a935a2c596e6a2998519435143525bef774f..a3a62f4e264a3df4d75f0b8b14028803c37cd453 100755 (executable)
@@ -657,144 +657,6 @@ QString wrapTextByWords(const QString& theValue, QWidget* theWidget,
   return aResult;
 }
 
-void findReferences(const QObjectPtrList& theList,
-                    std::set<FeaturePtr>& aDirectRefFeatures,
-                    std::set<FeaturePtr>& aIndirectRefFeatures)
-{
-  foreach (ObjectPtr aDeletedObj, theList) {
-    std::set<FeaturePtr> alreadyProcessed;
-    refsToFeatureInAllDocuments(aDeletedObj, aDeletedObj, theList, aDirectRefFeatures,
-                                            aIndirectRefFeatures, alreadyProcessed);
-    std::set<FeaturePtr> aDifference;
-    std::set_difference(aIndirectRefFeatures.begin(), aIndirectRefFeatures.end(), 
-                        aDirectRefFeatures.begin(), aDirectRefFeatures.end(), 
-                        std::inserter(aDifference, aDifference.begin()));
-    aIndirectRefFeatures = aDifference;
-  }
-}
-
-//**************************************************************
-void refsToFeatureInAllDocuments(const ObjectPtr& theSourceObject, const ObjectPtr& theObject,
-                                 const QObjectPtrList& theIgnoreList,
-                                 std::set<FeaturePtr>& theDirectRefFeatures, 
-                                 std::set<FeaturePtr>& theIndirectRefFeatures,
-                                 std::set<FeaturePtr>& theAlreadyProcessed)
-{
-  refsDirectToFeatureInAllDocuments(theSourceObject, theObject, theIgnoreList, theDirectRefFeatures, 
-                                    theAlreadyProcessed);
-
-  // Run recursion. It is possible recursive dependency, like the following: plane, extrusion uses plane,
-  // axis is built on extrusion. Delete of a plane should check the dependency from the axis also.
-  std::set<FeaturePtr>::const_iterator aFeatureIt = theDirectRefFeatures.begin();
-  for (; aFeatureIt != theDirectRefFeatures.end(); ++aFeatureIt) {
-    std::set<FeaturePtr> aRecursiveRefFeatures;
-    refsToFeatureInAllDocuments(theSourceObject, *aFeatureIt, theIgnoreList,
-      aRecursiveRefFeatures, aRecursiveRefFeatures, theAlreadyProcessed);
-    theIndirectRefFeatures.insert(aRecursiveRefFeatures.begin(), aRecursiveRefFeatures.end());
-  }
-
-}
-
-
-
-//**************************************************************
-void refsDirectToFeatureInAllDocuments(const ObjectPtr& theSourceObject, const ObjectPtr& theObject,
-                                       const QObjectPtrList& theIgnoreList,
-                                       std::set<FeaturePtr>& theDirectRefFeatures, 
-                                       std::set<FeaturePtr>& theAlreadyProcessed)
-{
-  FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
-  if (!aFeature.get())
-    return;
-  if (theAlreadyProcessed.find(aFeature) != theAlreadyProcessed.end())
-    return;
-  theAlreadyProcessed.insert(aFeature);
-
-  //convert ignore object list to containt sub-features if the composite feature is in the list
-  QObjectPtrList aFullIgnoreList;
-  QObjectPtrList::const_iterator anIIt = theIgnoreList.begin(), anILast = theIgnoreList.end();
-  for (; anIIt != anILast; anIIt++) {
-    aFullIgnoreList.append(*anIIt);
-    CompositeFeaturePtr aComposite = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*anIIt);
-    // if the current feature is aborted, the composite is removed and has invalid data
-    if (aComposite.get() && aComposite->data()->isValid()) {
-      int aNbSubs = aComposite->numberOfSubs();
-      for (int aSub = 0; aSub < aNbSubs; aSub++) {
-        aFullIgnoreList.append(aComposite->subFeature(aSub));
-      }
-    }
-  }
-
-  // 1. find references in the current document
-  std::set<FeaturePtr> aRefFeatures;
-  refsToFeatureInFeatureDocument(theObject, aRefFeatures);
-  std::set<FeaturePtr>::const_iterator anIt = aRefFeatures.begin(),
-                                       aLast = aRefFeatures.end();
-  for (; anIt != aLast; anIt++) {
-    // composite feature should not be deleted when the sub feature is to be deleted
-    if (!isSubOfComposite(theSourceObject, *anIt) && !aFullIgnoreList.contains(*anIt))
-      theDirectRefFeatures.insert(*anIt);
-  }
-
-  // 2. find references in all documents if the document of the feature is
-  // "PartSet". Features of this document can be used in all other documents
-  DocumentPtr aFeatureDoc = aFeature->document();
-
-  SessionPtr aMgr = ModelAPI_Session::get();
-  DocumentPtr aModuleDoc = aMgr->moduleDocument();
-  if (aFeatureDoc == aModuleDoc) {
-    // the feature and results of the feature should be found in references
-    std::list<ObjectPtr> aObjects;
-    aObjects.push_back(aFeature);
-    typedef std::list<std::shared_ptr<ModelAPI_Result> > ResultsList;
-    const ResultsList& aResults = aFeature->results();
-    ResultsList::const_iterator aRIter = aResults.begin();
-    for (; aRIter != aResults.cend(); aRIter++) {
-      ResultPtr aRes = *aRIter;
-      if (aRes.get())
-        aObjects.push_back(aRes);
-    }
-    // get all opened documents; found features in the documents;
-    // get a list of objects where a feature refers;
-    // search in these objects the deleted objects.
-    SessionPtr aMgr = ModelAPI_Session::get();
-    std::list<DocumentPtr> anOpenedDocs = aMgr->allOpenedDocuments();
-    std::list<DocumentPtr>::const_iterator anIt = anOpenedDocs.begin(),
-                                            aLast = anOpenedDocs.end();
-    std::list<std::pair<std::string, std::list<ObjectPtr> > > aRefs;
-    for (; anIt != aLast; anIt++) {
-      DocumentPtr aDocument = *anIt;
-      if (aDocument == aFeatureDoc)
-        continue; // this document has been already processed in 1.1
-
-      int aFeaturesCount = aDocument->size(ModelAPI_Feature::group());
-      for (int aId = 0; aId < aFeaturesCount; aId++) {
-        ObjectPtr anObject = aDocument->object(ModelAPI_Feature::group(), aId);
-        FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anObject);
-        if (!aFeature.get())
-          continue;
-
-        aRefs.clear();
-        aFeature->data()->referencesToObjects(aRefs);
-        std::list<std::pair<std::string, std::list<ObjectPtr> > >::iterator aRef = aRefs.begin();
-        bool aHasReferenceToObject = false;
-        for(; aRef != aRefs.end() && !aHasReferenceToObject; aRef++) {
-          std::list<ObjectPtr>::iterator aRefObj = aRef->second.begin();
-          for(; aRefObj != aRef->second.end() && !aHasReferenceToObject; aRefObj++) {
-            std::list<ObjectPtr>::const_iterator aObjIt = aObjects.begin();
-            for(; aObjIt != aObjects.end() && !aHasReferenceToObject; aObjIt++) {
-              aHasReferenceToObject = *aObjIt == *aRefObj;
-            }
-          }
-        }
-        if (aHasReferenceToObject && !isSubOfComposite(theSourceObject, aFeature) &&
-            !theIgnoreList.contains(aFeature))
-          theDirectRefFeatures.insert(aFeature);
-      }
-    }
-  }
-}
-
 //**************************************************************
 void refsToFeatureInFeatureDocument(const ObjectPtr& theObject, std::set<FeaturePtr>& theRefFeatures)
 {
@@ -840,49 +702,84 @@ bool isSubOfComposite(const ObjectPtr& theObject, const FeaturePtr& theFeature)
   return isSub;
 }
 
+//**************************************************************
+bool isFeatureOfResult(const FeaturePtr& theFeature, const std::string& theGroupOfResult)
+{
+  bool isResult = false;
+
+  if (!theFeature->data()->isValid())
+    return isResult;
+
+  ResultPtr aFirstResult = theFeature->firstResult();
+  if (!aFirstResult.get())
+    return isResult;
+
+  return aFirstResult->groupName() == theGroupOfResult;
+}
 
 //**************************************************************
-bool isDeleteFeatureWithReferences(const QObjectPtrList& theList,
-                                   const std::set<FeaturePtr>& aDirectRefFeatures,
-                                   const std::set<FeaturePtr>& aIndirectRefFeatures,
-                                   QWidget* theParent,
-                                   bool& doDeleteReferences)
-{
-  doDeleteReferences = true;
-
-  QString aDirectNames, aIndirectNames;
-  if (!aDirectRefFeatures.empty()) {
-    QStringList aDirectRefNames;
-    foreach (const FeaturePtr& aFeature, aDirectRefFeatures)
-      aDirectRefNames.append(aFeature->name().c_str());
-    aDirectNames = aDirectRefNames.join(", ");
-
-    QStringList aIndirectRefNames;
-    foreach (const FeaturePtr& aFeature, aIndirectRefFeatures)
-      aIndirectRefNames.append(aFeature->name().c_str());
-    aIndirectNames = aIndirectRefNames.join(", ");
-  }
-
-  bool aCanReplaceParameters = !aDirectRefFeatures.empty();
-  QStringList aPartFeatureNames;
-  foreach (ObjectPtr aObj, theList) {
-    FeaturePtr aFeature = ModelAPI_Feature::feature(aObj);
-    // invalid feature data means that the feature is already removed in model,
-    // we needn't process it. E.g. delete of feature from create operation. The operation abort
-    // will delete the operation
-    if (!aFeature->data()->isValid())
-      continue;
-    ResultPtr aFirstResult = aFeature->firstResult();
-    if (!aFirstResult.get())
+bool askToDelete(const std::set<FeaturePtr> theFeatures,
+                 const std::map<FeaturePtr, std::set<FeaturePtr> >& theReferences,
+                 QWidget* theParent,
+                 std::set<FeaturePtr>& theReferencesToDelete)
+{
+  std::set<FeaturePtr> aFeaturesRefsTo;
+  std::set<FeaturePtr> aFeaturesRefsToParameter;
+  std::set<FeaturePtr> aParameterFeatures;
+  std::set<FeaturePtr>::const_iterator anIt = theFeatures.begin(),
+                                       aLast = theFeatures.end();
+  // separate features to references to parameter features and references to others
+  for (; anIt != aLast; anIt++) {
+    FeaturePtr aFeature = *anIt;
+    if (theReferences.find(aFeature) == theReferences.end())
       continue;
-    std::string aResultGroupName = aFirstResult->groupName();
-    if (aResultGroupName == ModelAPI_ResultPart::group())
-      aPartFeatureNames.append(aFeature->name().c_str());
 
-    if (aCanReplaceParameters && aResultGroupName != ModelAPI_ResultParameter::group())
-      aCanReplaceParameters = false;
+    std::set<FeaturePtr> aRefFeatures;
+    std::set<FeaturePtr> aRefList = theReferences.at(aFeature);
+    std::set<FeaturePtr>::const_iterator aRefIt = aRefList.begin(), aRefLast = aRefList.end();
+    for (; aRefIt != aRefLast; aRefIt++) {
+      FeaturePtr aRefFeature = *aRefIt;
+      if (theFeatures.find(aRefFeature) == theFeatures.end() && // it is not selected
+          aRefFeatures.find(aRefFeature) == aRefFeatures.end()) // it is not added
+        aRefFeatures.insert(aRefFeature);
+    }
+
+    if (isFeatureOfResult(aFeature, ModelAPI_ResultParameter::group())) {
+      aFeaturesRefsToParameter.insert(aRefFeatures.begin(), aRefFeatures.end());
+      aParameterFeatures.insert(aFeature);
+    }
+    else {
+      theReferencesToDelete.insert(aRefFeatures.begin(), aRefFeatures.end());
+    }
+  }
+
+  std::set<FeaturePtr> aFeaturesRefsToParameterOnly;
+  anIt = aFeaturesRefsToParameter.begin();
+  aLast = aFeaturesRefsToParameter.end();
+  // separate features to references to parameter features and references to others
+  QStringList aParamFeatureNames;
+  for (; anIt != aLast; anIt++) {
+    FeaturePtr aFeature = *anIt;
+    if (theReferencesToDelete.find(aFeature) == theReferencesToDelete.end()) {
+      aFeaturesRefsToParameterOnly.insert(aFeature);
+      aParamFeatureNames.append(aFeature->name().c_str());
+    }
+  }
+  aParamFeatureNames.sort();
+  QStringList aPartFeatureNames, anOtherFeatureNames;
+  anIt = theReferencesToDelete.begin();
+  aLast = theReferencesToDelete.end();
+  for (; anIt != aLast; anIt++) {
+    FeaturePtr aFeature = *anIt;
+    if (isFeatureOfResult(aFeature, ModelAPI_ResultPart::group()))
+      aPartFeatureNames.append(aFeature->name().c_str());
+    else
+      anOtherFeatureNames.append(aFeature->name().c_str());
   }
-  QString aPartNames = aPartFeatureNames.join(", ");
+  aPartFeatureNames.sort();
+  anOtherFeatureNames.sort();
+
+  bool aCanReplaceParameters = !aFeaturesRefsToParameterOnly.empty();
 
   QMessageBox aMessageBox(theParent);
   aMessageBox.setWindowTitle(QObject::tr("Delete features"));
@@ -891,21 +788,17 @@ bool isDeleteFeatureWithReferences(const QObjectPtrList& theList,
   aMessageBox.setDefaultButton(QMessageBox::No);
 
   QString aText;
-  if (!aDirectNames.isEmpty() || !aIndirectNames.isEmpty()) {
-    if (aCanReplaceParameters) {
-      aText = QString(QObject::tr("Selected parameters are used in the following features: %1.\nThese features will be deleted.\nOr parameters could be replaced by their values.\n")
-                      .arg(aDirectNames));
-      if (!aIndirectNames.isEmpty())
-        aText += QString(QObject::tr("(Also these features will be deleted: %1)\n")).arg(aIndirectNames);
-      QPushButton *aReplaceButton = aMessageBox.addButton(QObject::tr("Replace"), QMessageBox::ActionRole);
-    } else {
-      aText = QString(QObject::tr("Selected features are used in the following features: %1.\nThese features will be deleted.\n")).arg(aDirectNames);
-      if (!aIndirectNames.isEmpty())
-        aText += QString(QObject::tr("(Also these features will be deleted: %1)\n")).arg(aIndirectNames);
-    }
+  QString aSep = ", ";
+  if (!aPartFeatureNames.empty())
+    aText += QString(QObject::tr("The following parts will be deleted: %1.\n")).arg(aPartFeatureNames.join(aSep));
+  if (!anOtherFeatureNames.empty())
+    aText += QString(QObject::tr("Selected features are used in the following features: %1.\nThese features will be deleted.\n"))
+                     .arg(anOtherFeatureNames.join(aSep));
+  if (!aParamFeatureNames.empty()) {
+    aText += QString(QObject::tr("Selected parameters are used in the following features: %1.\nThese features will be deleted.\nOr parameters could be replaced by their values.\n"))
+                     .arg(aParamFeatureNames.join(aSep));
+    QPushButton *aReplaceButton = aMessageBox.addButton(QObject::tr("Replace"), QMessageBox::ActionRole);
   }
-  if (!aPartNames.isEmpty())
-    aText += QString(QObject::tr("The following parts will be deleted: %1.\n")).arg(aPartNames);
 
   if (!aText.isEmpty()) {
     aText += "Would you like to continue?";
@@ -917,14 +810,30 @@ bool isDeleteFeatureWithReferences(const QObjectPtrList& theList,
       return false;
 
     if (aButtonRole == QMessageBox::ActionRole) {
-      foreach (ObjectPtr aObj, theList)
+      foreach (FeaturePtr aObj, aParameterFeatures)
         ModelAPI_ReplaceParameterMessage::send(aObj, 0);
-      doDeleteReferences = false;
     }
+    else
+      theReferencesToDelete.insert(aFeaturesRefsToParameterOnly.begin(), aFeaturesRefsToParameterOnly.end());
   }
   return true;
 }
 
+//**************************************************************
+void convertToFeatures(const QObjectPtrList& theObjects, std::set<FeaturePtr>& theFeatures)
+{
+  QObjectPtrList::const_iterator anIt = theObjects.begin(), aLast = theObjects.end();
+  for(; anIt != aLast; anIt++) {
+    ObjectPtr anObject = *anIt;
+    FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anObject);
+    // for parameter result, use the corresponded reature to be removed
+    if (!aFeature.get() && anObject->groupName() == ModelAPI_ResultParameter::group()) {
+      aFeature = ModelAPI_Feature::feature(anObject);
+    }
+    theFeatures.insert(aFeature);
+  }
+}
+
 } // namespace ModuleBase_Tools
 
 
index a9b38bd8055a11c701f88a01f9cbfd789ad48ddd..d053d279b6b39cb62692c9cba48e2426ab30fed0 100755 (executable)
@@ -21,6 +21,8 @@
 
 #include <QPixmap>
 
+#include <map>
+
 class QWidget;
 class QLayout;
 class QDoubleSpinBox;
@@ -229,42 +231,6 @@ MODULEBASE_EXPORT void blockUpdateViewer(const bool theValue);
 MODULEBASE_EXPORT QString wrapTextByWords(const QString& theValue, QWidget* theWidget,
                                              int theMaxLineInPixels = 150);
 
-//! Find all referenced features. Return direct and indirect lists of referenced object
-//! \param theList an objects to be checked
-//! \param aDirectRefFeatures a list of direct reference features
-//! \param aIndirectRefFeatures a list of features which depend on the feature through others
-MODULEBASE_EXPORT void findReferences(const QObjectPtrList& theList,
-                                      std::set<FeaturePtr>& aDirectRefFeatures,
-                                      std::set<FeaturePtr>& aIndirectRefFeatures);
-/*!
- Returns a container of references feature to the source object. The search happens in the object
- document and in other Part documents if the object belongs to the PartSet. The search is recursive,
- in other words it is applyed to set of the found objects until it is possible.
- It do not returns the referenced features to the object if this references is a composite feature
- which has the object as a sub object.
- \param theSourceObject an object, which references are searched
- \param theObject an intermediate recursive object, should be set in the source object
- \param theIgnoreList an ignore list, the found referernces which coincide with the objects are ignored
- \param theDirectRefFeatures direct references
- \param theIndirectRefFeatures indirect references. These are features that refers to the direct features
- \param theAlreadyProcessed set of processed elements, used for optimization (do not reanalyse processed)
- \return a boolean value
- */
-void MODULEBASE_EXPORT refsToFeatureInAllDocuments(const ObjectPtr& theSourceObject,
-                                                   const ObjectPtr& theObject,
-                                                   const QObjectPtrList& theIgnoreList,
-                                                   std::set<FeaturePtr>& theDirectRefFeatures,
-                                                   std::set<FeaturePtr>& theIndirectRefFeatures,
-                                                   std::set<FeaturePtr>& theAlreadyProcessed);
-
-/*!
-*/
-void MODULEBASE_EXPORT refsDirectToFeatureInAllDocuments(const ObjectPtr& theSourceObject, 
-                                                         const ObjectPtr& theObject,
-                                                         const QObjectPtrList& theIgnoreList,
-                                                         std::set<FeaturePtr>& theDirectRefFeatures, 
-                                                         std::set<FeaturePtr>& theAlreadyProcessed);
-
 /*!
   Returns a container of referenced feature to the current object in the object document.
   \param theObject an object, which will be casted to a feature type
@@ -293,19 +259,28 @@ bool MODULEBASE_EXPORT isSubOfComposite(const ObjectPtr& theObject, const Featur
 bool MODULEBASE_EXPORT isSubOfComposite(const ObjectPtr& theObject);
 
 
-//! Shows a dialog box about references. Ask whether they should be also removed.
-//! \param theList an objects to be checked
-//! \param aDirectRefFeatures a list of direct reference features
-//! \param aIndirectRefFeatures a list of features which depend on the feature through others
-//! \param theParent a parent widget for the question message box
-//! \param doDeleteReferences if there are parameters between features, ask if they should be
-//! replaced to their meaning without corresponded features remove
-//! \return true if in message box answer is Yes
-bool MODULEBASE_EXPORT isDeleteFeatureWithReferences(const QObjectPtrList& theList,
-                                                     const std::set<FeaturePtr>& aDirectRefFeatures,
-                                                     const std::set<FeaturePtr>& aIndirectRefFeatures,
-                                                     QWidget* theParent,
-                                                     bool& doDeleteReferences);
+/*!
+* Shows a dialog box about references. Ask whether they should be also removed.
+* \param theFeatures a list of features
+* \param theReferences a map of all references to the features
+* \param theParent a parent widget for the question message box
+* \param theReferencesToDelete an out set for references features to be removed
+* \return true if in message box answer is Yes
+*/
+bool MODULEBASE_EXPORT askToDelete(const std::set<FeaturePtr> aFeatures,
+                                   const std::map<FeaturePtr, std::set<FeaturePtr> >& theReferences,
+                                   QWidget* theParent,
+                                   std::set<FeaturePtr>& theReferencesToDelete);
+
+/*!
+* Converts a list of objects to set of corresponded features. If object is result, it is ingored
+* because the feauture only might be removed. But if result is in a parameter group, the feature
+* of this parameter is to be removed
+* \param theObjects a list of objects
+* \param theFeatures an out conteiner of features
+*/
+void MODULEBASE_EXPORT convertToFeatures(const QObjectPtrList& theObjects, std::set<FeaturePtr>& theFeatures);
+
 }
 
 #endif
index 679d42896eb06ba690bb2fde4bd5e6fbc8edc11c..26f185358b61f055b99308a5100eccb50ec69139 100644 (file)
@@ -15,6 +15,7 @@
 #include <ModelAPI_AttributeInteger.h>
 #include <ModelAPI_Events.h>
 #include <ModelAPI_Session.h>
+#include <ModelAPI_Tools.h>
 
 #include <ModuleBase_Tools.h>
 
@@ -588,26 +589,16 @@ void ParametersPlugin_WidgetParamsMgr::onRemove()
   QObjectPtrList anObjects;
   anObjects.append(aCurFeature);
 
-  std::set<FeaturePtr> aDirectRefFeatures, aIndirectRefFeatures;
-  ModuleBase_Tools::findReferences(anObjects, aDirectRefFeatures, aIndirectRefFeatures);
+  std::map<FeaturePtr, std::set<FeaturePtr> > aReferences;
+  std::set<FeaturePtr> aFeatures;
+  ModuleBase_Tools::convertToFeatures(anObjects, aFeatures);
+  ModelAPI_Tools::findAllReferences(aFeatures, aReferences);
 
-  bool doDeleteReferences = true;
-  if (ModuleBase_Tools::isDeleteFeatureWithReferences(anObjects, aDirectRefFeatures, 
-      aIndirectRefFeatures, this, doDeleteReferences)) {
-
-    std::set<FeaturePtr> aFeaturesToDelete;
-    if (doDeleteReferences) {
-      aFeaturesToDelete = aDirectRefFeatures;
-      aFeaturesToDelete.insert(aIndirectRefFeatures.begin(), aIndirectRefFeatures.end());
-    }
-    aDoc->removeFeature(aCurFeature);
-    std::set<FeaturePtr>::const_iterator anIt = aFeaturesToDelete.begin(),
-                                         aLast = aFeaturesToDelete.end();
-    for (; anIt != aLast; anIt++) {
-      FeaturePtr aFeature = (*anIt);
-      DocumentPtr aDoc = aFeature->document();
-      aDoc->removeFeature(aFeature);
-    }
+  std::set<FeaturePtr> aFeatureRefsToDelete;
+  if (ModuleBase_Tools::askToDelete(aFeatures, aReferences, this, aFeatureRefsToDelete)) {
+    if (!aFeatureRefsToDelete.empty())
+      aFeatures.insert(aFeatureRefsToDelete.begin(), aFeatureRefsToDelete.end());
+    ModelAPI_Tools::removeFeatures(aFeatures, false);
 
     Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED));
     Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY));
index 54608476b671021210654dc4ff9ca73fe3a3b1fc..98bcf3d1c727541a48c1407333260fc9cd7df7db 100755 (executable)
@@ -78,14 +78,8 @@ void PartSet_ExternalObjectsMgr::removeExternalObject(const ObjectPtr& theObject
     if (aFeature.get() != NULL) {
       QObjectPtrList anObjects;
       anObjects.append(aFeature);
-      // the external feature should be removed with all references, sketch feature should be ignored
-      std::set<FeaturePtr> anIgnoredFeatures;
-      // the current feature should be ignored, because it can use the external feature in the
-      // attributes and, therefore have a references to it. So, the delete functionality tries
-      // to delete this feature. Test case is creation of a constraint on external point,
-      // use in this control after an external point, the point of the sketch.
-      anIgnoredFeatures.insert(theFeature);
-      workshop(theWorkshop)->deleteFeatures(anObjects, anIgnoredFeatures);
+      // the external feature should be removed with all references, composite sketch feature will be ignored
+      workshop(theWorkshop)->deleteFeatures(anObjects);
     }
   }
 }
index ab3bca3caff1cd8d7b798c8bf3145cf1ee16c9b0..2c127173d9a4f79e97afcdbcb90ac0a02c55e7e1 100755 (executable)
@@ -466,10 +466,10 @@ bool PartSet_Module::canDisplayObject(const ObjectPtr& theObject) const
   return mySketchMgr->canDisplayObject(theObject);
 }
 
-void PartSet_Module::processHiddenObject(const std::list<ObjectPtr>& theObjects)
+/*void PartSet_Module::processHiddenObject(const std::list<ObjectPtr>& theObjects)
 {
   mySketchMgr->processHiddenObject(theObjects);
-}
+}*/
 
 bool PartSet_Module::canActivateSelection(const ObjectPtr& theObject) const
 {
index eb5e317c2136739fe5d6abb83c7e740965991f1b..bca62aaa916128df1897fe791271054c75495905 100755 (executable)
@@ -164,7 +164,7 @@ public:
 
   /// Make some functionality after the objects are hidden in viewer
   /// \param theObjects a list of hidden objects
-  virtual void processHiddenObject(const std::list<ObjectPtr>& theObjects);
+  //virtual void processHiddenObject(const std::list<ObjectPtr>& theObjects);
 
   /// Returns true if selection for the object can be activate.
   /// For sketch operation allow the selection activation if the operation is edit, for other
index c6746b0cd3b79cda4df7b8ad20e7ebd6f85b04a3..1a07384b7fa79a6b0f58f12322f1cd4f67b65fd7 100755 (executable)
@@ -1212,7 +1212,7 @@ bool PartSet_SketcherMgr::canDisplayConstraint(const FeaturePtr& theFeature,
   return aSwitchedOn;
 }
 
-void PartSet_SketcherMgr::processHiddenObject(const std::list<ObjectPtr>& theObjects)
+/*void PartSet_SketcherMgr::processHiddenObject(const std::list<ObjectPtr>& theObjects)
 {
   ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
                                                                            (getCurrentOperation());
@@ -1288,7 +1288,7 @@ will be hidden: %1. Would you like to delete them?")
       }
     }
   }
-}
+}*/
 
 bool PartSet_SketcherMgr::canDisplayCurrentCreatedFeature() const
 {
index c739c2852540327f8a4d019cd1b235a46df4a1e8..ed60f1ae16b806644a03ac99d3d1b2282b0ea725 100644 (file)
@@ -190,7 +190,7 @@ public:
   /// Check the given objects either there are some results of the current sketch. If so,
   /// it suggests to delete them as there are no functionality to show back hidden sketch objects
   /// \param theObjects a list of hidden objects
-  virtual void processHiddenObject(const std::list<ObjectPtr>& theObjects);
+  //virtual void processHiddenObject(const std::list<ObjectPtr>& theObjects);
 
   /// Returns true if the mouse is over viewer or property panel value is changed
   /// \return boolean result
index d42cc1ee07ef721e9e2ee17d4fdf361697ab75f5..2f5d4bf7b66dd703027ab81fd1fc386ea87a1655 100644 (file)
@@ -404,7 +404,7 @@ void PartSet_WidgetSketchCreator::onResumed(ModuleBase_Operation* theOp)
       anObjects.append(aSketchFeature);
 
       XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myModule->workshop());
-      aWorkshop->deleteFeatures(anObjects, std::set<FeaturePtr>());
+      aWorkshop->deleteFeatures(anObjects);
 
       aMgr->finishOperation();
 #endif
index fcfd0262485515979dc1ff078482ac9c0e0f2fff..4737cd1724dcd34bec5e059d89bd7e2958ec1e09 100755 (executable)
@@ -18,6 +18,7 @@
 #include <ModelAPI_Events.h>
 #include <ModelAPI_Session.h>
 #include <ModelAPI_Validator.h>
+#include <ModelAPI_Tools.h>
 
 #include <SketchPlugin_SketchEntity.h>
 
@@ -106,6 +107,7 @@ void SketchPlugin_MultiRotation::execute()
   std::list<ObjectPtr>::iterator anInitIter = anInitialList.begin();
   std::list<ObjectPtr>::iterator aTargetIter = aTargetList.begin();
   std::vector<bool>::iterator aUsedIter = isUsed.begin();
+  std::set<FeaturePtr> aFeaturesToBeRemoved;
   for (; aUsedIter != isUsed.end(); aUsedIter++) {
     if (!(*aUsedIter)) {
       aRefListOfShapes->remove(*anInitIter);
@@ -118,7 +120,8 @@ void SketchPlugin_MultiRotation::execute()
         DocumentPtr aDoc = aRC ? aRC->document() : DocumentPtr();
         FeaturePtr aFeature =  aDoc ? aDoc->feature(aRC) : FeaturePtr();
         if (aFeature)
-          aDoc->removeFeature(aFeature);
+          aFeaturesToBeRemoved.insert(aFeature);
+          //aDoc->removeFeature(aFeature);
       }
     } else {
       for (int i = 0; i <= aNbCopies && aTargetIter != aTargetList.end(); i++)
@@ -127,6 +130,7 @@ void SketchPlugin_MultiRotation::execute()
     if (anInitIter != anInitialList.end())
       anInitIter++;
   }
+  ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToBeRemoved);
   // change number of copies
   if (aCurrentNbCopies != 0 && aNbCopies != aCurrentNbCopies) {
     bool isAdd = aNbCopies > aCurrentNbCopies;
@@ -137,6 +141,7 @@ void SketchPlugin_MultiRotation::execute()
     aTargetList = aRefListOfRotated->list();
     aTargetIter = aTargetList.begin();
     ObjectPtr anObjToCopy = *aTargetIter;
+    std::set<FeaturePtr> aFeaturesToBeRemoved;
     while (aTargetIter != aTargetList.end()) {
       aRefListOfRotated->remove(*aTargetIter);
       aTargetIter++;
@@ -159,7 +164,8 @@ void SketchPlugin_MultiRotation::execute()
             DocumentPtr aDoc = aRC ? aRC->document() : DocumentPtr();
             FeaturePtr aFeature =  aDoc ? aDoc->feature(aRC) : FeaturePtr();
             if (aFeature)
-              aDoc->removeFeature(aFeature);
+              aFeaturesToBeRemoved.insert(aFeature);
+              //aDoc->removeFeature(aFeature);
           }
           ind++;
         }
@@ -168,6 +174,7 @@ void SketchPlugin_MultiRotation::execute()
           anObjToCopy = *aTargetIter;
       }
     }
+    ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToBeRemoved);
 
     for (aTargetIter = aTargetList.begin(); aTargetIter != aTargetList.end(); aTargetIter++)
       aRefListOfRotated->append(*aTargetIter);
@@ -331,6 +338,7 @@ void SketchPlugin_MultiRotation::attributeChanged(const std::string& theID)
           data()->attribute(SketchPlugin_Constraint::ENTITY_B()));
       std::list<ObjectPtr> aTargetList = aRefListOfRotated->list();
       std::list<ObjectPtr>::iterator aTargetIter = aTargetList.begin();
+      std::set<FeaturePtr> aFeaturesToBeRemoved;
       while (aTargetIter != aTargetList.end()) {
         aTargetIter++;
         for (int i = 0; i < aNbCopies && aTargetIter != aTargetList.end(); i++, aTargetIter++) {
@@ -341,9 +349,12 @@ void SketchPlugin_MultiRotation::attributeChanged(const std::string& theID)
           DocumentPtr aDoc = aRC ? aRC->document() : DocumentPtr();
           FeaturePtr aFeature =  aDoc ? aDoc->feature(aRC) : FeaturePtr();
           if (aFeature)
-            aDoc->removeFeature(aFeature);
+            aFeaturesToBeRemoved.insert(aFeature);
+            //aDoc->removeFeature(aFeature);
         }
       }
+      ModelAPI_Tools::removeFeaturesAndReferences(aFeaturesToBeRemoved);
+
       aRefListOfRotated->clear();
       std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(
         data()->attribute(SketchPlugin_Constraint::ENTITY_A()))->clear();
index ec47de5242a4ce85db6ade62e39c38c830ae93ae..8e8b92f5faeda6eb176a4215495a10fa0c121341 100755 (executable)
@@ -98,8 +98,6 @@
 
 #include <iterator>
 
-//#define DEBUG_CLEAN_HISTORY
-
 #ifdef _DEBUG
 #include <QDebug>
 #include <iostream>
 #include <dlfcn.h>
 #endif
 
-
 QString XGUI_Workshop::MOVE_TO_END_COMMAND = QObject::tr("Move to the end");
 
 //#define DEBUG_DELETE
 //#define DEBUG_FEATURE_NAME
+//#define DEBUG_CLEAN_HISTORY
 
 XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector)
     : QObject(),
@@ -1268,12 +1266,11 @@ void XGUI_Workshop::activateObjectsSelection(const QObjectPtrList& theList)
   myDisplayer->activateObjects(aModes, theList);
 }
 
-
 //**************************************************************
 void XGUI_Workshop::deleteObjects()
 {
   ModuleBase_IModule* aModule = module();
-  // 1. allow the module to delete objects, do nothing if it has succeed
+  // allow the module to delete objects, do nothing if it has succeed
   if (aModule->deleteObjects()) {
     updateCommandStatus();
     return;
@@ -1294,32 +1291,34 @@ void XGUI_Workshop::deleteObjects()
   if (!(hasFeature || hasParameter))
     return;
 
-  // 3. delete objects
-  std::set<FeaturePtr> anIgnoredFeatures;
-  std::set<FeaturePtr> aDirectRefFeatures, aIndirectRefFeatures;
-  ModuleBase_Tools::findReferences(anObjects, aDirectRefFeatures, aIndirectRefFeatures);
-
-  bool doDeleteReferences = true;
-  if (ModuleBase_Tools::isDeleteFeatureWithReferences(anObjects, aDirectRefFeatures, 
-      aIndirectRefFeatures, desktop(), doDeleteReferences)) {
-    // start operation
-    QString aDescription = contextMenuMgr()->action("DELETE_CMD")->text() + " %1";
-    aDescription = aDescription.arg(XGUI_Tools::unionOfObjectNames(anObjects, ", "));
-    ModuleBase_OperationAction* anOpAction = new ModuleBase_OperationAction(aDescription, module());
-    operationMgr()->startOperation(anOpAction);
+  // delete objects
+  std::map<FeaturePtr, std::set<FeaturePtr> > aReferences;
+  std::set<FeaturePtr> aFeatures;
+  ModuleBase_Tools::convertToFeatures(anObjects, aFeatures);
+  ModelAPI_Tools::findAllReferences(aFeatures, aReferences);
+
+  bool aDone = false;
+  QString aDescription = contextMenuMgr()->action("DELETE_CMD")->text() + " %1";
+  aDescription = aDescription.arg(XGUI_Tools::unionOfObjectNames(anObjects, ", "));
+  ModuleBase_OperationAction* anOpAction = new ModuleBase_OperationAction(aDescription, module());
+
+  operationMgr()->startOperation(anOpAction);
 
+  std::set<FeaturePtr> aFeatureRefsToDelete;
+  if (ModuleBase_Tools::askToDelete(aFeatures, aReferences, desktop(), aFeatureRefsToDelete)) {
     // WORKAROUND, should be done before each object remove, if it presents in XGUI_DataModel tree
     // It is necessary to clear selection in order to avoid selection changed event during
     // deletion and negative consequences connected with processing of already deleted items
     mySelector->clearSelection();
 
-    // delete and commit/abort operation in model
-    if (deleteFeaturesInternal(anObjects, aDirectRefFeatures, aIndirectRefFeatures,
-                               anIgnoredFeatures, doDeleteReferences))
-      operationMgr()->commitOperation();
-    else
-      operationMgr()->abortOperation(operationMgr()->currentOperation());
+    if (!aFeatureRefsToDelete.empty())
+      aFeatures.insert(aFeatureRefsToDelete.begin(), aFeatureRefsToDelete.end());
+    aDone = ModelAPI_Tools::removeFeatures(aFeatures, false);
   }
+  if (aDone)
+    operationMgr()->commitOperation();
+  else
+    operationMgr()->abortOperation(operationMgr()->currentOperation());
 }
 
 //**************************************************************
@@ -1343,24 +1342,6 @@ void addRefsToFeature(const FeaturePtr& theFeature,
   }
 }
 
-void printMapInfo(const std::map<FeaturePtr, std::set<FeaturePtr> >& theMainList,
-                  const QString& thePrefix)
-{
-  std::map<FeaturePtr, std::set<FeaturePtr> >::const_iterator aMainIt = theMainList.begin(),
-                                                              aMainLast = theMainList.end();
-  QStringList aMapInfo;
-  for (; aMainIt != aMainLast; aMainIt++) {
-    QStringList anInfo;
-    FeaturePtr aMainListFeature = aMainIt->first;
-    std::set<FeaturePtr> aMainRefList = aMainIt->second;
-    foreach (FeaturePtr aRefFeature, aMainRefList) {
-      anInfo.append(aRefFeature->name().c_str());
-    }
-    aMapInfo.append(QString("%1: %2\n").arg(aMainListFeature->name().c_str()).arg(anInfo.join(",")));
-  }
-  qDebug(QString("%1: %2\n%3").arg(thePrefix).arg(aMapInfo.size()).arg(aMapInfo.join("\n")).toStdString().c_str());
-}
-
 //**************************************************************
 void XGUI_Workshop::cleanHistory()
 {
@@ -1368,19 +1349,12 @@ void XGUI_Workshop::cleanHistory()
     return;
 
   QObjectPtrList anObjects = mySelector->selection()->selectedObjects();
-  QObjectPtrList aFeatures;
-  foreach (ObjectPtr anObject, anObjects) {
-    FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anObject);
-    // for parameter result, use the corresponded reature to be removed
-    if (!aFeature.get() && anObject->groupName() == ModelAPI_ResultParameter::group()) {
-      aFeature = ModelAPI_Feature::feature(anObject);
-    }
-    aFeatures.append(aFeature);
-  }
+  std::set<FeaturePtr> aFeatures;
+  ModuleBase_Tools::convertToFeatures(anObjects, aFeatures);
 
 #ifdef DEBUG_CLEAN_HISTORY
-  QObjectPtrList::const_iterator aFIt;
   QStringList anInfo;
+  std::set<FeaturePtr>::const_iterator aFIt;
   for (aFIt = aFeatures.begin(); aFIt != aFeatures.end(); ++aFIt) {
     FeaturePtr aFeature = ModelAPI_Feature::feature(*aFIt);
     anInfo.append(aFeature->name().c_str());
@@ -1389,56 +1363,8 @@ void XGUI_Workshop::cleanHistory()
   qDebug(QString("cleanHistory for: [%1] - %2").arg(aFeatures.size()).arg(anInfoStr).toStdString().c_str());
 #endif
 
-  // For dependencies, find main_list:
-  // sk_1(ext_1, vertex_1)
-  // ext_1(bool_1, sk_3)
-  // vertex_1()
-  // sk_2(ext_2)
-  // ext_2(bool_2)
-  // sk_3()
-  // Information: bool_1 is not selected
-  // find all referenced features
-  std::map<FeaturePtr, std::set<FeaturePtr> > aMainList;
-  foreach(ObjectPtr anObject, aFeatures) {
-    FeaturePtr aSelFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anObject);
-    /// composite ??? see refsDirectToFeatureInAllDocuments
-    /// other documents ???
-    if (aSelFeature.get()) {
-      DocumentPtr aSelFeatureDoc = aSelFeature->document();
-      std::set<FeaturePtr> aSelRefFeatures;
-      // 1. find references in the current document
-      aSelFeatureDoc->refsToFeature(aSelFeature, aSelRefFeatures, false/*do not emit signals*/);
-      //if (aMainList.find(aSelFeature) != aMainList.end())
-        aMainList[aSelFeature] = aSelRefFeatures;
-    }
-  }
-#ifdef DEBUG_CLEAN_HISTORY
-  printMapInfo(aMainList, "firstDependencies");
-#endif
-  // find all dependencies for each object:
-  // sk_1(ext_1, vertex_1) + (sk_3, bool_1)
-  // ext_1(bool_1, sk_3)
-  // vertex_1()
-  // sk_2(ext_2) + (bool_1)
-  // ext_2(bool_1)
-  // sk_3()
-  std::map<FeaturePtr, std::set<FeaturePtr> > anExtendedMainList;
-  std::map<FeaturePtr, std::set<FeaturePtr> >::const_iterator aMainIt = aMainList.begin(),
-                                                              aMainLast = aMainList.end();
-  for (; aMainIt != aMainLast; aMainIt++) {
-    FeaturePtr aMainListFeature = aMainIt->first;
-    //std::string aName = aMainListFeature->name();
-    std::set<FeaturePtr> aMainRefList = aMainIt->second;
-    std::set<FeaturePtr> anAddRefFeatures;
-    foreach (FeaturePtr aRefFeature, aMainRefList) {
-      addRefsToFeature(aRefFeature, aMainList, aMainRefList);
-    }
-    anExtendedMainList[aMainListFeature] = aMainRefList;
-  }
-
-#ifdef DEBUG_CLEAN_HISTORY
-  printMapInfo(anExtendedMainList, "allDependencies");
-#endif
+  std::map<FeaturePtr, std::set<FeaturePtr> > aReferences;
+  ModelAPI_Tools::findAllReferences(aFeatures, aReferences, true, false);
   // find for each object whether all reference values are in the map as key, that means that there is
   // no other reference in the model to this object, so it might be removed by cleaning history
   // sk_1(ext_1, vertex_1) + (sk_3, bool_1) - cann't be deleted, dependency to bool_1
@@ -1448,8 +1374,9 @@ void XGUI_Workshop::cleanHistory()
   // ext_2(bool_1)  - cann't be deleted, dependency to bool_1
   // sk_3()
   // Information: bool_1 is not selected
-  QList<ObjectPtr> anUnusedObjects;
-  aMainIt = anExtendedMainList.begin(), aMainLast = anExtendedMainList.end();
+  std::set<FeaturePtr> anUnusedObjects;
+  std::map<FeaturePtr, std::set<FeaturePtr> >::const_iterator aMainIt = aReferences.begin(),
+                                                              aMainLast = aReferences.end();
   for (; aMainIt != aMainLast; aMainIt++) {
     FeaturePtr aMainListFeature = aMainIt->first;
     std::set<FeaturePtr> aMainRefList = aMainIt->second;
@@ -1457,16 +1384,16 @@ void XGUI_Workshop::cleanHistory()
     bool aFeatureOutOfTheList = false;
     for (; aRefIt != aRefLast && !aFeatureOutOfTheList; aRefIt++) {
       FeaturePtr aRefFeature = *aRefIt;
-      aFeatureOutOfTheList = anExtendedMainList.find(aRefFeature) == anExtendedMainList.end();
+      aFeatureOutOfTheList = aReferences.find(aRefFeature) == aReferences.end();
     }
     if (!aFeatureOutOfTheList)
-      anUnusedObjects.append(aMainListFeature);
+      anUnusedObjects.insert(aMainListFeature);
   }
 
 #ifdef DEBUG_CLEAN_HISTORY
   anInfo.clear();
   for (aFIt = anUnusedObjects.begin(); aFIt != anUnusedObjects.end(); ++aFIt) {
-    FeaturePtr aFeature = ModelAPI_Feature::feature(*aFIt);
+    FeaturePtr aFeature = *aFIt;
     anInfo.append(aFeature->name().c_str());
   }
   qDebug(QString("unused objects: [%1] - %2").arg(anInfo.size()).arg(anInfo.join(";\t")).toStdString().c_str());
@@ -1475,10 +1402,10 @@ void XGUI_Workshop::cleanHistory()
   // warn about the references remove, break the delete operation if the user chose it
   if (!anUnusedObjects.empty()) {
     QStringList aNames;
-    foreach (const ObjectPtr& anObject, anUnusedObjects) {
-      FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anObject);
+    foreach (const FeaturePtr& aFeature, anUnusedObjects) {
       aNames.append(aFeature->name().c_str());
     }
+    aNames.sort();
     QString anUnusedNames = aNames.join(", ");
 
     QString anActionId = "CLEAN_HISTORY_CMD";
@@ -1507,7 +1434,7 @@ void XGUI_Workshop::cleanHistory()
     mySelector->clearSelection();
 
     std::set<FeaturePtr> anIgnoredFeatures;
-    if (removeFeatures(anUnusedObjects, anIgnoredFeatures, anActionId, true)) {
+    if (ModelAPI_Tools::removeFeatures(anUnusedObjects, true)) {
       operationMgr()->commitOperation();
     }
     else {
@@ -1572,107 +1499,13 @@ void XGUI_Workshop::moveObjects()
 }
 
 //**************************************************************
-bool XGUI_Workshop::deleteFeatures(const QObjectPtrList& theFeatures,
-                                   const std::set<FeaturePtr>& theIgnoredFeatures)
-{
-  std::set<FeaturePtr> aDirectRefFeatures, aIndirectRefFeatures;
-  ModuleBase_Tools::findReferences(theFeatures, aDirectRefFeatures, aIndirectRefFeatures);
-  return deleteFeaturesInternal(theFeatures, aDirectRefFeatures, aIndirectRefFeatures,
-                                theIgnoredFeatures);
-}
-
-bool XGUI_Workshop::deleteFeaturesInternal(const QObjectPtrList& theList,
-                                           const std::set<FeaturePtr>& aDirectRefFeatures,
-                                           const std::set<FeaturePtr>& aIndirectRefFeatures,
-                                           const std::set<FeaturePtr>& theIgnoredFeatures,
-                                           const bool doDeleteReferences)
-{
-  bool isDone = false;
-  if (doDeleteReferences) {
-    std::set<FeaturePtr> aFeaturesToDelete = aDirectRefFeatures;
-    aFeaturesToDelete.insert(aIndirectRefFeatures.begin(), aIndirectRefFeatures.end());
-    std::set<FeaturePtr>::const_iterator anIt = aFeaturesToDelete.begin(),
-                                         aLast = aFeaturesToDelete.end();
-#ifdef DEBUG_DELETE
-    QStringList anInfo;
-#endif
-    for (; anIt != aLast; anIt++) {
-      FeaturePtr aFeature = (*anIt);
-      DocumentPtr aDoc = aFeature->document();
-      if (theIgnoredFeatures.find(aFeature) == theIgnoredFeatures.end()) {
-        // flush REDISPLAY signal after remove feature
-        aDoc->removeFeature(aFeature);
-        isDone = true;
-#ifdef DEBUG_DELETE
-        anInfo.append(ModuleBase_Tools::objectInfo(aFeature).toStdString().c_str());
-#endif
-      }
-    }
-#ifdef DEBUG_DELETE
-    qDebug(QString("remove references:%1").arg(anInfo.join("; ")).toStdString().c_str());
-    anInfo.clear();
-#endif
-  }
-
-  QString anActionId = "DELETE_CMD";
-  isDone = removeFeatures(theList, theIgnoredFeatures, anActionId, false) || isDone;
-
-  if (isDone) {
-    // the redisplay signal should be flushed in order to erase the feature presentation in the viewer
-    // if should be done after removeFeature() of document
-    Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY));
-  }
-  return isDone;
-}
-
-//**************************************************************
-bool XGUI_Workshop::removeFeatures(const QObjectPtrList& theList,
-                                   const std::set<FeaturePtr>& theIgnoredFeatures,
-                                   const QString& theActionId,
-                                   const bool theFlushRedisplay)
+bool XGUI_Workshop::deleteFeatures(const QObjectPtrList& theObjects)
 {
-  bool isDone = false;
-
-  QString anId = QString::fromStdString(theActionId.toStdString().c_str());
-  QStringList anObjectGroups = contextMenuMgr()->actionObjectGroups(anId);
-  // 4. remove the parameter features
-  foreach (ObjectPtr aObj, theList) {
-    // features and parameters can be removed here,
-    // the results are removed only by a corresponded feature remove
-    std::string aGroupName = aObj->groupName();
-    if (!anObjectGroups.contains(aGroupName.c_str()))
-      continue;
-
-    FeaturePtr aFeature = ModelAPI_Feature::feature(aObj);
-    if (aFeature) {
-      /*// TODO: to learn the workshop to delegate the Part object deletion to the PartSet module
-      // part features are removed in the PartSet module. This condition should be moved there
-      if (aFeature->getKind() == "Part")
-        continue;
-        */
-      DocumentPtr aDoc = aObj->document();
-      if (theIgnoredFeatures.find(aFeature) == theIgnoredFeatures.end()) {
-#ifdef DEBUG_DELETE
-        QString anInfoStr = ModuleBase_Tools::objectInfo(aFeature);
-        anInfo.append(anInfoStr);
-        qDebug(QString("remove feature :%1").arg(anInfoStr).toStdString().c_str());
-#endif
-        // flush REDISPLAY signal after remove feature
-        aDoc->removeFeature(aFeature);
-        isDone = true;
-      }
-    }
-  }
-  if (isDone && theFlushRedisplay) {
-    // the redisplay signal should be flushed in order to erase the feature presentation in the viewer
-    // if should be done after removeFeature() of document
-    Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY));
-  }
+  std::map<FeaturePtr, std::set<FeaturePtr> > aReferences;
+  std::set<FeaturePtr> aFeatures;
+  ModuleBase_Tools::convertToFeatures(theObjects, aFeatures);
 
-#ifdef DEBUG_DELETE
-  qDebug(QString("remove features:%1").arg(anInfo.join("; ")).toStdString().c_str());
-#endif
-  return true;
+  return ModelAPI_Tools::removeFeaturesAndReferences(aFeatures);
 }
 
 bool hasResults(QObjectPtrList theObjects, const std::set<std::string>& theTypes)
index 74269e898aa7e563a277cf3e067975076136175a..c969da8c046b8ffb776da98681e9afc0a5e46336 100755 (executable)
@@ -249,9 +249,7 @@ Q_OBJECT
   //! Delete features. Delete the referenced features. There can be a question with a list of
   //! referenced objects.
   //! \param theFeatures a list of objects to be deleted
-  //! \param theIgnoredFeatures a list of features to be ignored during delete
-  bool deleteFeatures(const QObjectPtrList& theFeatures,
-                      const std::set<FeaturePtr>& theIgnoredFeatures = std::set<FeaturePtr>());
+  bool deleteFeatures(const QObjectPtrList& theFeatures);
 
   /// Deactivates the object, if it is active and the module returns that the activation
   /// of selection for the object is not possible currently(the current operation uses it)
@@ -391,17 +389,6 @@ signals:
   /// \param theOperation an operation
    void setGrantedFeatures(ModuleBase_Operation* theOperation);
 
-  //! \param theIgnoredFeatures a list of features to be ignored during delete
-  //! \param theList an objects to be checked
-  //! \param aDirectRefFeatures a list of direct reference features
-  //! \param aIndirectRefFeatures a list of features which depend on the feature through others
-  //! \param doDeleteReferences flag if referenced features should be removed also
-  bool deleteFeaturesInternal(const QObjectPtrList& theList,
-                              const std::set<FeaturePtr>& aDirectRefFeatures,
-                              const std::set<FeaturePtr>& aIndirectRefFeatures,
-                              const std::set<FeaturePtr>& theIgnoredFeatures,
-                              const bool doDeleteReferences = true);
-
 private:
   /// Display all results
   //void displayAllResults();
@@ -485,17 +472,6 @@ private:
   //! \param theSlot - onUndo(int) or onRedo(int) SLOT
   void addHistoryMenu(QObject* theObject, const char* theSignal, const char* theSlot);
 
-
-  /// Calls removeFeature of the document for each object in the list
-  //! \param theList an objects to be deleted
-  //! \param theIgnoredFeatures a list of features to be ignored during delete
-  //! \param theActionId an action command key to find context menu object types enabled for remove
-  //! \param theFlushRedisplay a boolean value if the redisplay signal should be flushed
-  bool removeFeatures(const QObjectPtrList& theList,
-                      const std::set<FeaturePtr>& theIgnoredFeatures,
-                      const QString& theActionId,
-                      const bool theFlushRedisplay);
-
   //! Creates list of actions (commands) by given history list from session
   QList<ActionInfo> processHistoryList(const std::list<std::string>&) const;