]> SALOME platform Git repositories - modules/shaper.git/blobdiff - src/ModelAPI/ModelAPI_Tools.cpp
Salome HOME
#29481: Show parts in study tree (parts drag and drop)
[modules/shaper.git] / src / ModelAPI / ModelAPI_Tools.cpp
index dda65e007eb6440f843479ccee8b2efdbb8d70d8..7034040690eb6cfe492ffd152aea248116ce1c68 100644 (file)
@@ -1441,4 +1441,127 @@ void findRandomColor(std::vector<int>& theValues, bool theReset)
 
 // LCOV_EXCL_STOP
 
+/// Returns name of the higher level feature (Part or feature of PartSet).
+static FeaturePtr topOwner(const FeaturePtr& theFeature)
+{
+  FeaturePtr anOwner = theFeature;
+  while (anOwner.get())
+  {
+    FeaturePtr aNextOwner = compositeOwner(anOwner);
+    if (aNextOwner.get())
+      anOwner = aNextOwner;
+    else
+      break;
+  }
+  if (anOwner->document() != ModelAPI_Session::get()->moduleDocument()) // the part-owner name
+    anOwner = findPartFeature(ModelAPI_Session::get()->moduleDocument(), anOwner->document());
+  return anOwner;
+}
+
+std::wstring validateMovement(const FeaturePtr& theAfter, const std::list<FeaturePtr> theMoved)
+{
+  std::wstring aResult;
+  if (theMoved.empty())
+    return aResult; // nothing to move, nothing to check, ok
+  DocumentPtr aDoc = theAfter.get() ? theAfter->document() : (*(theMoved.cbegin()))->document();
+  std::set<FeaturePtr> aMoved(theMoved.begin(), theMoved.end()); // fast access to moved
+  std::set<FeaturePtr> aPassed, aPassedMoved; // all features and all moved before the current one
+  std::set<FeaturePtr> aPassedAfter; // all passed features after theAfter
+  bool anAfterIsPassed = theAfter.get() == 0; // flag that iterator already passed theAfter
+  std::list<FeaturePtr> allFeat = aDoc->allFeatures();
+  for (std::list<FeaturePtr>::iterator aFeat = allFeat.begin(); aFeat != allFeat.end(); aFeat++)
+  {
+    if (!anAfterIsPassed)
+    {
+      if (aMoved.count(*aFeat))
+        aPassedMoved.insert(*aFeat);
+      else // check aPassedMoved are not referenced by the current feature
+        aPassed.insert(*aFeat);
+
+      anAfterIsPassed = *aFeat == theAfter;
+      if (anAfterIsPassed && !aPassedMoved.empty())
+      { // check dependencies of moved relatively to the passed
+        std::map<FeaturePtr, std::set<FeaturePtr> > aReferences;
+        findAllReferences(aPassedMoved, aReferences);
+        std::map<FeaturePtr, std::set<FeaturePtr> >::iterator aRefIter = aReferences.begin();
+        for (; aRefIter != aReferences.end(); aRefIter++)
+        {
+          if (aPassed.count(aRefIter->first))
+          {
+            aResult += topOwner(aRefIter->first)->name() + L" -> ";
+            // iterate all passed moved to check is it referenced by described feature or not
+            std::set<FeaturePtr>::iterator aMovedIter = aPassedMoved.begin();
+            for (; aMovedIter != aPassedMoved.end(); aMovedIter++)
+            {
+              std::map<FeaturePtr, std::set<FeaturePtr> > aPassedRefs;
+              std::set<FeaturePtr> aMovedOne;
+              aMovedOne.insert(*aMovedIter);
+              findAllReferences(aMovedOne, aPassedRefs);
+              if (aPassedRefs.count(aRefIter->first))
+                aResult += topOwner(*aMovedIter)->name() + L" ";
+            }
+            aResult += L"\n";
+          }
+        }
+      }
+    }
+    else // iteration after theAfter
+    {
+      if (aMoved.count(*aFeat)) { // check dependencies of moved relatively to ones after theAfter
+        std::map<FeaturePtr, std::set<FeaturePtr> > aReferences;
+        findAllReferences(aPassedAfter, aReferences);
+        bool aFoundRef = aReferences.find(*aFeat) != aReferences.end();
+        if (!aFoundRef && !(*aFeat)->results().empty()) // reference may be a feature in moved part
+        {
+          ResultPartPtr aFeatPart =
+            std::dynamic_pointer_cast<ModelAPI_ResultPart>((*aFeat)->firstResult());
+          if (aFeatPart.get() && aFeatPart->partDoc().get())
+          {
+            std::map<FeaturePtr, std::set<FeaturePtr> >::iterator aRef = aReferences.begin();
+            for (; aRef != aReferences.end() && !aFoundRef; aRef++)
+              aFoundRef = aRef->first->document() == aFeatPart->partDoc();
+          }
+        }
+
+        if (aFoundRef)
+        {
+          aResult += topOwner(*aFeat)->name() + L" -> ";
+          std::set<FeaturePtr> aReferencedCount; // to avoid duplicates in the displayed references
+          // iterate all passed after theAfter to check refers it described feature or not
+          FeaturePtr aFeatTop = topOwner(*aFeat);
+          std::set<FeaturePtr>::iterator aPassedIter = aPassedAfter.begin();
+          for (; aPassedIter != aPassedAfter.end(); aPassedIter++)
+          {
+            FeaturePtr aPassedTop = topOwner(*aPassedIter);
+            if (aReferencedCount.count(aPassedTop))
+              continue;
+            std::map<FeaturePtr, std::set<FeaturePtr> > aPassedRefs;
+            std::set<FeaturePtr> aPassedOne;
+            aPassedOne.insert(*aPassedIter);
+            findAllReferences(aPassedOne, aPassedRefs);
+            std::map<FeaturePtr, std::set<FeaturePtr> >::iterator aPRIter = aPassedRefs.begin();
+            for (; aPRIter != aPassedRefs.end(); aPRIter++)
+            {
+              FeaturePtr aPRTop = topOwner(aPRIter->first);
+              if (aPRIter->first == *aFeat || aPRIter->first == aFeatTop ||
+                  aPRTop == *aFeat || aPRTop == aFeatTop)
+              {
+                aResult += aPassedTop->name() + L" ";
+                aReferencedCount.insert(aPassedTop);
+                break;
+              }
+            }
+          }
+          aResult += L"\n";
+        }
+      }
+      else {
+        aPassedAfter.insert(*aFeat);
+      }
+    }
+
+  }
+  return aResult;
+}
+
 } // namespace ModelAPI_Tools