]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Improvement for key "Delete" processing: should be done only on possible objects...
authornds <nds@opencascade.com>
Fri, 3 Jun 2016 11:39:03 +0000 (14:39 +0300)
committernds <nds@opencascade.com>
Fri, 3 Jun 2016 11:39:03 +0000 (14:39 +0300)
Also possible show of two warnings is united in one warning: the first is about not loaded parts, the second is usual delete message.

src/ModuleBase/ModuleBase_Tools.cpp
src/ModuleBase/ModuleBase_Tools.h
src/PartSet/PartSet_Module.cpp
src/XGUI/XGUI_ContextMenuMgr.h
src/XGUI/XGUI_ObjectsBrowser.cpp
src/XGUI/XGUI_OperationMgr.cpp
src/XGUI/XGUI_Tools.cpp
src/XGUI/XGUI_Tools.h
src/XGUI/XGUI_Workshop.cpp

index 6b83432a85131b859b5f7ac4116080022575021c..d9114ea820ed8070291c58f1e927dd174df6cf36 100755 (executable)
@@ -961,6 +961,18 @@ bool isSubOfComposite(const ObjectPtr& theObject, const FeaturePtr& theFeature)
   return isSub;
 }
 
+//**************************************************************
+ResultPtr firstResult(const ObjectPtr& theObject)
+{
+  ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
+  if (!aResult.get()) {
+    FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
+    if (aFeature.get())
+      aResult = aFeature->firstResult();
+  }
+  return aResult;
+}
+
 //**************************************************************
 bool isFeatureOfResult(const FeaturePtr& theFeature, const std::string& theGroupOfResult)
 {
@@ -976,15 +988,42 @@ bool isFeatureOfResult(const FeaturePtr& theFeature, const std::string& theGroup
   return aFirstResult->groupName() == theGroupOfResult;
 }
 
+//**************************************************************
+bool hasModuleDocumentFeature(const std::set<FeaturePtr>& theFeatures)
+{
+  bool aFoundModuleDocumentObject = false;
+  DocumentPtr aModuleDoc = ModelAPI_Session::get()->moduleDocument();
+
+  std::set<FeaturePtr>::const_iterator anIt = theFeatures.begin(), aLast = theFeatures.end();
+  for (; anIt != aLast && !aFoundModuleDocumentObject; anIt++) {
+    FeaturePtr aFeature = *anIt;
+    ResultPtr aResult = ModuleBase_Tools::firstResult(aFeature);
+    if (aResult.get() && aResult->groupName() == ModelAPI_ResultPart::group())
+      continue;
+    aFoundModuleDocumentObject = aFeature->document() == aModuleDoc;
+  }
+
+  return aFoundModuleDocumentObject;
+}
+
 //**************************************************************
 bool askToDelete(const std::set<FeaturePtr> theFeatures,
                  const std::map<FeaturePtr, std::set<FeaturePtr> >& theReferences,
                  QWidget* theParent,
                  std::set<FeaturePtr>& theReferencesToDelete)
 {
+  QString aNotActivatedDocWrn;
+  std::string aNotActivatedNames;
+  if (!ModelAPI_Tools::allDocumentsActivated(aNotActivatedNames)) {
+    if (ModuleBase_Tools::hasModuleDocumentFeature(theFeatures))
+      aNotActivatedDocWrn = QObject::tr("Selected objects can be used in Part documents which are not loaded:%1.\n")
+                            .arg(aNotActivatedNames.c_str());
+  }
+  
   std::set<FeaturePtr> aFeaturesRefsTo;
   std::set<FeaturePtr> aFeaturesRefsToParameter;
   std::set<FeaturePtr> aParameterFeatures;
+  QStringList aPartFeatureNames;
   std::set<FeaturePtr>::const_iterator anIt = theFeatures.begin(),
                                        aLast = theFeatures.end();
   // separate features to references to parameter features and references to others
@@ -993,6 +1032,9 @@ bool askToDelete(const std::set<FeaturePtr> theFeatures,
     if (theReferences.find(aFeature) == theReferences.end())
       continue;
 
+    if (isFeatureOfResult(aFeature, ModelAPI_ResultPart::group()))
+      aPartFeatureNames.append(aFeature->name().c_str());
+
     std::set<FeaturePtr> aRefFeatures;
     std::set<FeaturePtr> aRefList = theReferences.at(aFeature);
     std::set<FeaturePtr>::const_iterator aRefIt = aRefList.begin(), aRefLast = aRefList.end();
@@ -1025,7 +1067,7 @@ bool askToDelete(const std::set<FeaturePtr> theFeatures,
     }
   }
   aParamFeatureNames.sort();
-  QStringList aPartFeatureNames, anOtherFeatureNames;
+  QStringList anOtherFeatureNames;
   anIt = theReferencesToDelete.begin();
   aLast = theReferencesToDelete.end();
   for (; anIt != aLast; anIt++) {
@@ -1050,6 +1092,8 @@ bool askToDelete(const std::set<FeaturePtr> theFeatures,
   QString aSep = ", ";
   if (!aPartFeatureNames.empty())
     aText += QString(QObject::tr("The following parts will be deleted: %1.\n")).arg(aPartFeatureNames.join(aSep));
+  if (!aNotActivatedDocWrn.isEmpty())
+    aText += aNotActivatedDocWrn;
   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));
index 49128e4a58a9bb300deca4b1197934d879d67fc8..2e19e0f731e873527fc0d12da6d466a4447bc039 100755 (executable)
@@ -38,63 +38,55 @@ class GeomAPI_Shape;
 
 namespace ModuleBase_Tools {
 
-/*
- * Methods to adjust margins and spacings.
- */
+/// Methods to adjust margins and spacings.
 MODULEBASE_EXPORT void adjustMargins(QWidget* theWidget);
 MODULEBASE_EXPORT void adjustMargins(QLayout* theLayout);
 
 MODULEBASE_EXPORT void zeroMargins(QWidget* theWidget);
 MODULEBASE_EXPORT void zeroMargins(QLayout* theLayout);
 
-/*
- * Calls the same-named Qt method for the given widget.
- * It sets the top-level widget containing this widget to be the active window.
- * An active window is a visible top-level window that has the keyboard input focus.
- * \param theWidget a widget to be activated
- * \param theIndo a debug information
- */
+/// Calls the same-named Qt method for the given widget.
+/// It sets the top-level widget containing this widget to be the active window.
+/// An active window is a visible top-level window that has the keyboard input focus.
+/// \param theWidget a widget to be activated
+/// \param theIndo a debug information
 MODULEBASE_EXPORT void activateWindow(QWidget* theWidget, const QString& theInfo = QString());
 
-/*
- * Calls the same-named Qt method for the given widget.
- * Gives the keyboard input focus to this widget (or its focus proxy) if this widget or
- * one of its parents is the active window.
- * \param theWidget a widget to be activated
- * \param theIndo a debug information
- */
+/// Calls the same-named Qt method for the given widget.
+/// Gives the keyboard input focus to this widget (or its focus proxy) if this widget or
+/// one of its parents is the active window.
+/// \param theWidget a widget to be activated
+/// \param theIndo a debug information
 MODULEBASE_EXPORT void setFocus(QWidget* theWidget, const QString& theInfo = QString());
 
 
-//! Sets or removes the shadow effect to the widget
-//! \param theWidget a widget to be styled
-//! \param isSetEffect if true, the shadow effect is set, overwise cleared
-//! \return resulting pixmap
+/// Sets or removes the shadow effect to the widget
+/// \param theWidget a widget to be styled
+/// \param isSetEffect if true, the shadow effect is set, overwise cleared
+/// \return resulting pixmap
 MODULEBASE_EXPORT void setShadowEffect(QWidget* theWidget, const bool isSetEffect);
 
-/**
- * \ingroup GUI
- * Methods to modify a resource pixmap
- */
+/// \ingroup GUI
+/// Methods to modify a resource pixmap
 
-//! Create composite pixmap. 
-//! Pixmap \a theAdditionalIcon is drawn over pixmap \a dest with coordinates
-//! specified relatively to the upper left corner of \a theIcon.
+/// Create composite pixmap. 
+/// Pixmap \a theAdditionalIcon is drawn over pixmap \a dest with coordinates
+/// specified relatively to the upper left corner of \a theIcon.
 
-//! \param theAdditionalIcon resource text of the additional pixmap
-//! \param theIcon resource text of the background pixmap
-//! \return resulting pixmap
+/// \param theAdditionalIcon resource text of the additional pixmap
+/// \param theIcon resource text of the background pixmap
+/// \return resulting pixmap
 MODULEBASE_EXPORT QPixmap composite(const QString& theAdditionalIcon, const QString& theIcon);
 
-//! Generates the pixmap lighter than the resources pixmap. 
-//! Pixmap \a theIcon is lighted according to the given value.
-//! If the lighter value is greater than 100, this functions returns a lighter pixmap.
-//! Setting lighter value to 150 returns a color that is 50% brighter. If the factor is less than 100,
-//! the return pixmap is darker. If the factor is 0 or negative, the return pixmap is unspecified.
+/// Generates the pixmap lighter than the resources pixmap. 
+/// Pixmap \a theIcon is lighted according to the given value.
+/// If the lighter value is greater than 100, this functions returns a lighter pixmap.
+/// Setting lighter value to 150 returns a color that is 50% brighter. If the factor is less than 100,
+/// the return pixmap is darker. If the factor is 0 or negative, the return pixmap is unspecified.
 
-//! \param resource text of the pixmap
-//! \param theLighterValue a lighter factor
-//! \return resulting pixmap
+/// \param resource text of the pixmap
+/// \param theLighterValue a lighter factor
+/// \return resulting pixmap
 MODULEBASE_EXPORT QPixmap lighter(const QString& theIcon, const int theLighterValue = 200);
 
 /// Sets programmatically the value to the spin box without emitting any signals(e.g. valueChanged)
@@ -158,45 +150,39 @@ MODULEBASE_EXPORT TopAbs_ShapeEnum shapeType(const QString& theType);
 /// \return boolean result
 MODULEBASE_EXPORT bool isSubResult(ObjectPtr theObject);
 
-/*!
-Check types of objects which are in the given list
-\param theObjects the list of objects
-\param hasResult will be set to true if list contains Result objects
-\param hasFeature will be set to true if list contains Feature objects
-\param hasParameter will be set to true if list contains Parameter objects
-\param hasCompositeOwner will be set to true if list contains Sub-Feature objects
-*/
+/// Check types of objects which are in the given list
+/// \param theObjects the list of objects
+/// \param hasResult will be set to true if list contains Result objects
+/// \param hasFeature will be set to true if list contains Feature objects
+/// \param hasParameter will be set to true if list contains Parameter objects
+/// \param hasCompositeOwner will be set to true if list contains Sub-Feature objects
 MODULEBASE_EXPORT void checkObjects(const QObjectPtrList& theObjects, bool& hasResult,
                            bool& hasFeature, bool& hasParameter, bool& hasCompositeOwner);
 
-/*! Sets the default coeffient into the driver calculated accordingly the shape type.
-It provides 1.e-4 for results of construction type
-\param theResult a result object to define the deviation coeffient
-\param theDrawer a drawer
-*/
+/// Sets the default coeffient into the driver calculated accordingly the shape type.
+/// It provides 1.e-4 for results of construction type
+/// \param theResult a result object to define the deviation coeffient
+/// \param theDrawer a drawer
 MODULEBASE_EXPORT void setDefaultDeviationCoefficient(
                            const std::shared_ptr<ModelAPI_Result>& theResult,
                            const Handle(Prs3d_Drawer)& theDrawer);
 
-/*! Sets the default coeffient into the driver calculated accordingly the shape type.
-It provides 1.e-4 for a shape withe Edge shape type
-\param theShape a shape to define the deviation coeffient, 
-\param theDrawer a drawer
-*/
+/// Sets the default coeffient into the driver calculated accordingly the shape type.
+/// It provides 1.e-4 for a shape withe Edge shape type
+/// \param theShape a shape to define the deviation coeffient, 
+/// \param theDrawer a drawer
 MODULEBASE_EXPORT void setDefaultDeviationCoefficient(const TopoDS_Shape& theShape,
                                                       const Handle(Prs3d_Drawer)& theDrawer);
 
-/*! Obtains the color from the property manager and converts it to the OCCT color
-\param theSection a property section
-\param theName a property item name
-\param theDefault a default color value
-\return quantity color
-*/
+/// Obtains the color from the property manager and converts it to the OCCT color
+/// \param theSection a property section
+/// \param theName a property item name
+/// \param theDefault a default color value
+/// \return quantity color
 MODULEBASE_EXPORT Quantity_Color color(const std::string& theSection,
                                        const std::string& theName,
                                        const std::string& theDefault);
 
-
 /// Returns the object from the attribute
 /// \param theObj an object
 MODULEBASE_EXPORT ObjectPtr getObject(const AttributePtr& theAttribute);
@@ -264,54 +250,56 @@ MODULEBASE_EXPORT void blockUpdateViewer(const bool theValue);
 MODULEBASE_EXPORT QString wrapTextByWords(const QString& theValue, QWidget* theWidget,
                                              int theMaxLineInPixels = 150);
 
-/*!
-  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
-  \param theRefFeatures an output container
- */
+/// 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
+/// \param theRefFeatures an output container
 void MODULEBASE_EXPORT refsToFeatureInFeatureDocument(const ObjectPtr& theObject,
                                                       std::set<FeaturePtr>& theRefFeatures);
 
 
-/*!
- Returns true if the object if a sub child of the feature. The feature is casted to the
- composite one. If it is possible, the sub object check happens. The method is applyed
- recursively to the feature subs.
- \param theObject a candidate to be a sub object
- \param theFeature a candidate to be a composite feature
- \return a boolean value
- */
+/// Returns true if the object if a sub child of the feature. The feature is casted to the
+/// composite one. If it is possible, the sub object check happens. The method is applyed
+/// recursively to the feature subs.
+/// \param theObject a candidate to be a sub object
+/// \param theFeature a candidate to be a composite feature
+/// \return a boolean value
 bool MODULEBASE_EXPORT isSubOfComposite(const ObjectPtr& theObject, const FeaturePtr& theFeature);
 
 
-/*!
-* Returns true if the result is a sub object of some composite object
-* \param theObject a result object
-* \returns boolean value
-*/
+/// Returns true if the result is a sub object of some composite object
+/// \param theObject a result object
+/// \returns boolean value
 bool MODULEBASE_EXPORT isSubOfComposite(const ObjectPtr& theObject);
 
 
-/*!
-* 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
-*/
+/// Returns first result of the feature: the object itself if it is a result of
+/// first result of the object's feature
+/// \param theObject an object
+/// \return first result or NULL
+std::shared_ptr<ModelAPI_Result> MODULEBASE_EXPORT firstResult(const ObjectPtr& theObject);
+
+/// Returns true if the list contains at least one feature from the module document(PartSet)
+/// The Part features are skipped.
+/// \param theFeatures a list of features
+/// \bool true if it is found
+bool MODULEBASE_EXPORT hasModuleDocumentFeature(const std::set<FeaturePtr>& theFeatures);
+
+/// 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
-*/
+/// 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);
 
 }
index 936a1ab0150b15775116c99dbbdb3e6cc6221d82..f53edf79b0b553ce577e56f3702a4375b11d7592 100755 (executable)
@@ -446,8 +446,9 @@ bool PartSet_Module::canApplyAction(const ObjectPtr& theObject, const QString& t
   if (theActionId == "MOVE_CMD") {
     FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
     if (aFeature) {
+      ResultPtr aResult = ModuleBase_Tools::firstResult(aFeature);
       // part features can not be moved in the history.
-      if (aFeature->getKind() == PartSetPlugin_Part::ID())
+      if (aResult.get() && aResult->groupName() == ModelAPI_ResultPart::group())
         aValid = false;
     }
   }
index 321c9641e4d84e8d369a75a7001078984280b8c6..53399babb70db7716b96b24eb39dc856f81a2ddb 100644 (file)
@@ -61,6 +61,9 @@ Q_OBJECT
   /// \return a list of group names
   QStringList actionObjectGroups(const QString& theName);
 
+  /// Updates menu for object browser
+  void updateObjectBrowserMenu();
+
   /// Updates menu for viewer
   void updateViewerMenu();
 
@@ -103,9 +106,6 @@ signals:
 
   void addFeatures(QMenu* theMenu) const;
 
-  /// Updates menu for object browser
-  void updateObjectBrowserMenu();
-
   /// Creates menu for object browser
   void buildObjBrowserMenu();
 
index 7d6410a49eed6162e1e89f6cb7a3aaa89ab905e3..df30667eb7e0881fc99ad190c0b0bff46d0ac8c4 100644 (file)
@@ -424,19 +424,19 @@ void XGUI_ObjectsBrowser::onEditItem()
 {
   QObjectPtrList aSelectedData = selectedObjects();
   if (aSelectedData.size() > 0) {
-    ObjectPtr aFeature = aSelectedData.first();
-    if (aFeature) {  // Selection happens in TreeView
-      QObjectPtrList aList;
-      aList.append(aFeature);
-      // check whether the object can be deleted. There should not be parts which are not loaded
-      if (!XGUI_Tools::canRemoveOrRename((QWidget*)parent(), aList))
+    ObjectPtr anObject = aSelectedData.first();
+    if (anObject.get()) {  // Selection happens in TreeView
+      // check whether the object can be renamed. There should not be parts which are not loaded
+      std::set<FeaturePtr> aFeatures;
+      aFeatures.insert(ModelAPI_Feature::feature(anObject));
+      if (!XGUI_Tools::canRemoveOrRename((QWidget*)parent(), aFeatures))
         return;
 
       // Find index which corresponds the feature
       QModelIndex aIndex;
       foreach(QModelIndex aIdx, selectedIndexes()) {
         ObjectPtr aFea = dataModel()->object(aIdx);
-        if (dataModel()->object(aIdx)->isSame(aFeature)) {
+        if (dataModel()->object(aIdx)->isSame(anObject)) {
           aIndex = aIdx;
           break;
         }
index 3a98d98e9fff1808d0ac74d23ca6719b21fedd9b..b41264d77b160e08096eb11793e6e8ba74ed6d24 100644 (file)
@@ -10,6 +10,7 @@
 #include "XGUI_ErrorMgr.h"
 #include "XGUI_Tools.h"
 #include "XGUI_ObjectsBrowser.h"
+#include "XGUI_ContextMenuMgr.h"
 
 #include <ModuleBase_IPropertyPanel.h>
 #include <ModuleBase_ModelWidget.h>
@@ -686,12 +687,25 @@ bool XGUI_OperationMgr::onProcessDelete(QObject* theObject)
     /// processing delete by workshop
     XGUI_ObjectsBrowser* aBrowser = XGUI_Tools::workshop(myWorkshop)->objectBrowser();
     QWidget* aViewPort = myWorkshop->viewer()->activeViewPort();
-    // property panel child object is processed to process delete performed on Apply button of PP
-    if (theObject == aBrowser->treeView() ||
-        isChildObject(theObject, aViewPort) ||
-        isPPChildObject)
-      XGUI_Tools::workshop(myWorkshop)->deleteObjects();
-    isAccepted = true;
+    bool isToDeleteObject = false;
+    XGUI_Workshop* aWorkshop = XGUI_Tools::workshop(myWorkshop);
+    XGUI_ContextMenuMgr* aContextMenuMgr = aWorkshop->contextMenuMgr();
+    if (theObject == aBrowser->treeView()) {
+      aContextMenuMgr->updateObjectBrowserMenu();
+      isToDeleteObject = aContextMenuMgr->action("DELETE_CMD")->isEnabled();
+    }
+    else if (isChildObject(theObject, aViewPort)) {
+      aContextMenuMgr->updateViewerMenu();
+      isToDeleteObject = aContextMenuMgr->action("DELETE_CMD")->isEnabled();
+    }
+    else if (isPPChildObject) {
+      // property panel child object is processed to process delete performed on Apply button of PP
+      isToDeleteObject = true;
+    }
+    if (isToDeleteObject) {
+      aWorkshop->deleteObjects();
+      isAccepted = true;
+    }
   }
 
   return isAccepted;
index 64982ec4f29ca2a3c0edd6477ee95acd0ce0a74b..c0bfb2685b2e6ac858a56ab72cc1714444b527c0 100644 (file)
@@ -6,6 +6,7 @@
 #include "XGUI_Workshop.h"
 
 #include "ModuleBase_IWorkshop.h"
+#include "ModuleBase_Tools.h"
 
 #include <TopoDS_Shape.hxx>
 #include <ModelAPI_Object.h>
@@ -103,19 +104,14 @@ std::string featureInfo(FeaturePtr theFeature)
  }
  }*/
 
+
 //******************************************************************
-bool canRemoveOrRename(QWidget* theParent, const QObjectPtrList& theObjects)
+bool canRemoveOrRename(QWidget* theParent, const std::set<FeaturePtr>& theFeatures)
 {
   bool aResult = true;
   std::string aNotActivatedNames;
   if (!ModelAPI_Tools::allDocumentsActivated(aNotActivatedNames)) {
-    DocumentPtr aModuleDoc = ModelAPI_Session::get()->moduleDocument();
-    bool aFoundPartSetObject = false;
-    foreach (ObjectPtr aObj, theObjects) {
-      if (aObj->groupName() == ModelAPI_ResultPart::group())
-        continue;
-      aFoundPartSetObject = aObj->document() == aModuleDoc;
-    }
+    bool aFoundPartSetObject = ModuleBase_Tools::hasModuleDocumentFeature(theFeatures);
     if (aFoundPartSetObject) {
       QMessageBox::StandardButton aRes = QMessageBox::warning(theParent, QObject::tr("Warning"),
                QObject::tr("Selected objects can be used in Part documents which are not loaded: \
index 924454cf77f8627930813de1f55ccac5106a0f72..a8d51f2d505745c77f0074bbd656050d32c254ac 100644 (file)
@@ -81,10 +81,10 @@ std::string XGUI_EXPORT featureInfo(FeaturePtr theFeature);
  all objects in the list are not PartSet document.
  It shows the warning control if the result is false.
  \param theParent a parent for the warning control
- \param aList a list of object
+ \param theFeatures a list of checked features
  \return a boolean value
  */
-bool XGUI_EXPORT canRemoveOrRename(QWidget* theParent, const QObjectPtrList& aList);
+bool XGUI_EXPORT canRemoveOrRename(QWidget* theParent, const std::set<FeaturePtr>& theFeatures);
 
 /*! 
  Check possibility to rename object
index 17b753910276d400c834896850bd92824099b03e..3dfe3076d82fa2832cb9784cceeb5b61682d271c 100755 (executable)
@@ -1279,9 +1279,6 @@ void XGUI_Workshop::deleteObjects()
   QObjectPtrList anObjects = mySelector->selection()->selectedObjects();
   if (!abortAllOperations())
     return;
-  // check whether the object can be deleted. There should not be parts which are not loaded
-  if (!XGUI_Tools::canRemoveOrRename(desktop(), anObjects))
-    return;
 
   bool hasResult = false;
   bool hasFeature = false;
@@ -1480,20 +1477,21 @@ void XGUI_Workshop::moveObjects()
   // moving and negative consequences connected with processing of already moved items
   mySelector->clearSelection();
   // check whether the object can be moved. There should not be parts which are not loaded
-  if (!XGUI_Tools::canRemoveOrRename(desktop(), anObjects))
+  std::set<FeaturePtr> aFeatures;
+  ModuleBase_Tools::convertToFeatures(anObjects, aFeatures);
+  if (!XGUI_Tools::canRemoveOrRename(desktop(), aFeatures))
     return;
 
   DocumentPtr anActiveDocument = aMgr->activeDocument();
   FeaturePtr aCurrentFeature = anActiveDocument->currentFeature(true);
-  foreach (ObjectPtr aObject, anObjects) {
-    if (!myModule->canApplyAction(aObject, anActionId))
+  std::set<FeaturePtr>::const_iterator anIt = aFeatures.begin(), aLast = aFeatures.end();
+  for (; anIt != aLast; anIt++) {
+    FeaturePtr aFeature = *anIt;
+    if (!aFeature.get() || !myModule->canApplyAction(aFeature, anActionId))
       continue;
 
-    FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObject);
-    if (aFeature.get()) {
-      anActiveDocument->moveFeature(aFeature, aCurrentFeature);
-      aCurrentFeature = anActiveDocument->currentFeature(true);
-    }
+    anActiveDocument->moveFeature(aFeature, aCurrentFeature);
+    aCurrentFeature = anActiveDocument->currentFeature(true);
   }
   aMgr->finishOperation();
 }