Salome HOME
Boost has been removed from code
[modules/shaper.git] / src / PartSet / PartSet_OperationFeatureEdit.cpp
index 7a16b92405ee559a0fda5f0009e1e0970e8f6193..d44dfa3d7f8d51084ac72356951b69aacf3334a8 100644 (file)
@@ -5,12 +5,14 @@
 #include <PartSet_OperationFeatureEdit.h>
 #include <PartSet_Tools.h>
 #include <PartSet_OperationSketch.h>
-
 #include <SketchPlugin_Constraint.h>
 
 #include <ModuleBase_OperationDescription.h>
 #include <ModuleBase_WidgetEditor.h>
 #include <ModuleBase_ViewerPrs.h>
+#include <ModuleBase_IPropertyPanel.h>
+#include <ModuleBase_ISelection.h>
+#include <ModuleBase_IViewer.h>
 
 #include <ModelAPI_Events.h>
 
 
 using namespace std;
 
-PartSet_OperationFeatureEdit::PartSet_OperationFeatureEdit(const QString& theId, QObject* theParent,
-                                                           FeaturePtr theFeature)
-    : PartSet_OperationSketchBase(theId, theParent),
-      mySketch(theFeature),
-      myIsBlockedSelection(false)
+PartSet_OperationFeatureEdit::PartSet_OperationFeatureEdit(const QString& theId,
+                                                           QObject* theParent,
+                                                           CompositeFeaturePtr theFeature)
+    : PartSet_OperationFeatureBase(theId, theParent, theFeature),
+      myIsBlockedSelection(false), myIsBlockedByDoubleClick(false)
 {
+  myIsEditing = true;
 }
 
 PartSet_OperationFeatureEdit::~PartSet_OperationFeatureEdit()
 {
 }
 
-std::list<int> PartSet_OperationFeatureEdit::getSelectionModes(ObjectPtr theFeature) const
+void PartSet_OperationFeatureEdit::initSelection(ModuleBase_ISelection* theSelection,
+                                                 ModuleBase_IViewer* theViewer)
 {
-  return PartSet_OperationSketchBase::getSelectionModes(theFeature);
-}
+  // the method of the parent should is useless here because it processes the given
+  // selection in different way
+  //PartSet_OperationFeatureBase::initSelection(theSelection, theViewer);
+
+  QList<ModuleBase_ViewerPrs> aSelected = theSelection->getSelected();
+  QList<ModuleBase_ViewerPrs> aHighlighted = theSelection->getHighlighted();
+
+  // there is a bug in OCC, where the highlighted objects are repeated and should be
+  // filtered on the unique state here
+  QList<ModuleBase_ViewerPrs> anUniqueHighlighted;
+  foreach (ModuleBase_ViewerPrs aPrs, aHighlighted) {
+    if (!PartSet_Tools::isContainPresentation(anUniqueHighlighted, aPrs))
+      anUniqueHighlighted.append(aPrs);
+  }
+  fillFeature2Attribute(anUniqueHighlighted, theViewer, myHighlightedFeature2Attribute);
 
-void PartSet_OperationFeatureEdit::initFeature(FeaturePtr theFeature)
-{
-  setEditingFeature(theFeature);
+  foreach (ModuleBase_ViewerPrs aPrs, anUniqueHighlighted) {
+    if (!PartSet_Tools::isContainPresentation(aSelected, aPrs))
+      aSelected.append(aPrs);
+  }
+  fillFeature2Attribute(aSelected, theViewer, myAllFeature2Attribute);
 }
 
-FeaturePtr PartSet_OperationFeatureEdit::sketch() const
+void PartSet_OperationFeatureEdit::fillFeature2Attribute(
+                                    const QList<ModuleBase_ViewerPrs>& thePresentations,
+                                    ModuleBase_IViewer* theViewer,
+                                    std::map<FeaturePtr, std::list<std::string> >& theFeature2Attribute)
 {
-  return mySketch;
+  // 1. find all features with skipping features with selected vertex shapes
+  theFeature2Attribute.clear();
+  // firstly, collect the features without local selection
+  double aX, anY;
+  foreach (ModuleBase_ViewerPrs aPrs, thePresentations) {
+    if (getViewerPoint(aPrs, theViewer, aX, anY))
+      continue;
+    else {
+      ObjectPtr aObject = aPrs.object();
+      if (!aObject)
+        continue;
+      FeaturePtr aFeature = ModelAPI_Feature::feature(aObject);
+      if (aFeature && theFeature2Attribute.find(aFeature) == theFeature2Attribute.end()) {
+        std::list<std::string> aList;
+        // using an empty list as a sign, that this feature should be moved itself
+        theFeature2Attribute[aFeature] = aList;
+      }
+    }
+  }
+  // 2. collect the features with a local selection on them.
+  // if the list already has this feature, the local selection is skipped
+  // that means that if the selection contains a feature and a feature with local selected point,
+  // the edit is performed for a full feature
+  foreach (ModuleBase_ViewerPrs aPrs, thePresentations) {
+    if (getViewerPoint(aPrs, theViewer, aX, anY)) {
+      ObjectPtr aObject = aPrs.object();
+      if (!aObject)
+        continue;
+      FeaturePtr aFeature = ModelAPI_Feature::feature(aObject);
+      if (!aFeature)
+        continue;
+
+      // append the attribute of the vertex if it is found on the current feature
+      std::shared_ptr<GeomDataAPI_Point2D> aPoint2D = PartSet_Tools::getFeaturePoint(
+                                                                    aFeature, aX, anY);
+      std::string anAttribute = aFeature->data()->id(aPoint2D);
+      std::list<std::string> aList;
+      if (theFeature2Attribute.find(aFeature) != theFeature2Attribute.end())
+        aList = theFeature2Attribute[aFeature];
+
+      aList.push_back(anAttribute);
+      theFeature2Attribute[aFeature] = aList;
+    }
+  }
 }
 
-void PartSet_OperationFeatureEdit::mousePressed(
-    QMouseEvent* theEvent, Handle(V3d_View) theView,
-    const std::list<ModuleBase_ViewerPrs>& theSelected,
-    const std::list<ModuleBase_ViewerPrs>& theHighlighted)
+void PartSet_OperationFeatureEdit::mousePressed(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer, ModuleBase_ISelection* theSelection)
 {
-  ObjectPtr aObject;
-  if (!theHighlighted.empty())
-    aObject = theHighlighted.front().object();
-  if (!aObject && !theSelected.empty())  // changed for a constrain
-    aObject = theSelected.front().object();
-
-  FeaturePtr aFeature = ModelAPI_Feature::feature(aObject);
-  if (!aFeature || aFeature != feature()) {
-    if (commit()) {
-      emit featureConstructed(feature(), FM_Deactivation);
-
-      bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier);
-      if (aHasShift && !theHighlighted.empty()) {
-        QList<ObjectPtr> aSelected;
-        std::list<ModuleBase_ViewerPrs>::const_iterator aIt;
-        for (aIt = theSelected.cbegin(); aIt != theSelected.cend(); ++aIt)
-          aSelected.append((*aIt).object());
-        /*for (aIt = theHighlighted.cbegin(); aIt != theHighlighted.cend(); ++aIt) {
-         if (!aSelected.contains((*aIt).object()))
-         aSelected.append((*aIt).object());
-         }*/
-        //aSelected.push_back(feature());
-        //aSelected.push_back(theHighlighted.front().object());
-        emit setSelection(aSelected);
-      } else if (aFeature) {
-        restartOperation(PartSet_OperationFeatureEdit::Type(), aFeature);
-      }
+  ModuleBase_ModelWidget* aActiveWgt = myPropertyPanel->activeWidget();
+  if(aActiveWgt && aActiveWgt->isViewerSelector()) {
+    // Almost do nothing, all stuff in on PartSet_OperationFeatureBase::mouseReleased
+    PartSet_OperationFeatureBase::mousePressed(theEvent, theViewer, theSelection);
+    // the current point should be cleared because it is saved from the previous move and 
+    // should be reinitialized after the start moving. It is important for example for the lenght
+    // constraint where the first widget is a viewer selector.
+    myCurPoint.clear();
+  }
+  else {
+    // commit always until the selection restore is realized (for feature and local selection)
+    // TODO: check whether the selection is changed and restart the operation only if it is modified
+    commit();
+    emitFeaturesDeactivation();
+    // find nearest feature and restart the operation for it
+    Handle(V3d_View) aView = theViewer->activeView();
+    QList<ModuleBase_ViewerPrs> aSelected = theSelection->getSelected();
+    QList<ModuleBase_ViewerPrs> aHighlighted = theSelection->getHighlighted();
+
+    ObjectPtr aFeature = PartSet_Tools::nearestFeature(theEvent->pos(), aView, sketch(),
+                                                       aSelected, aHighlighted);
+    if (aFeature) {
+      restartOperation(PartSet_OperationFeatureEdit::Type(), aFeature);
     }
   }
+  // the next code is commented because the new attempt to commit/restart operation implementation:
+  //QList<ModuleBase_ViewerPrs> aSelected = theSelection->getSelected();
+  //QList<ModuleBase_ViewerPrs> aHighlighted = theSelection->getHighlighted();
+  //bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier);
+  //if (aHasShift && !aHighlighted.empty()) {
+  //  foreach (ModuleBase_ViewerPrs aPrs, aHighlighted) {
+  //    aSelected.append(aPrs);
+  //  }
+  //}
+  //ObjectPtr aObject;
+  ///*if (!aSelected.empty()) {
+  //  aObject = aSelected.first().object();
+  //} else {   
+  //  if (!aHighlighted.empty())
+  //    aObject = aHighlighted.first().object();
+  //}*/
+  //// the priority to a highlighted object in order to edit it, even if the selected object is
+  //// the feature of this operation. Otherwise, the highlighting is ignored and the selected
+  //// object is moved
+  //if (!aHighlighted.empty()) {
+  //  aObject = aHighlighted.front().object();
+  //}
+  //if (!aObject && !aSelected.empty())  // changed for a constrain
+  //  aObject = aSelected.front().object();
+
+  //FeaturePtr aFeature = ModelAPI_Feature::feature(aObject);
+  //if (!aFeature || aFeature != feature() || (aSelected.size() > 1)) {
+  //  if (commit()) {
+  //    theViewer->enableSelection(true);
+  //    emit featureConstructed(feature(), FM_Deactivation);
+
+  //    // If we have selection and prehilighting with shift pressed 
+  //    // Then we have to select all these objects and restart as multi edit operfation
+  //    //bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier);
+  //    //if (aHasShift && !theHighlighted.empty()) {
+  //    //  QList<ObjectPtr> aSelected;
+  //    //  std::list<ModuleBase_ViewerPrs>::const_iterator aIt;
+  //    //  for (aIt = theSelected.cbegin(); aIt != theSelected.cend(); ++aIt)
+  //    //    aSelected.append((*aIt).object());
+
+  //    //  for (aIt = theHighlighted.cbegin(); aIt != theHighlighted.cend(); ++aIt) {
+  //    //    if (!aSelected.contains((*aIt).object()))
+  //    //      aSelected.append((*aIt).object());
+  //    //  }
+  //    //  emit setSelection(aSelected);
+  //    //} else 
+  //    if (aFeature) {
+  //      std::string anOperationType = PartSet_OperationFeatureEdit::Type();
+  //      restartOperation(anOperationType, aFeature);
+  //    }
+  //    //}
+  //  }
+  //}
 }
 
-void PartSet_OperationFeatureEdit::mouseMoved(QMouseEvent* theEvent, Handle(V3d_View) theView)
+void PartSet_OperationFeatureEdit::mouseMoved(QMouseEvent* theEvent, ModuleBase_IViewer* theViewer)
 {
   if (!(theEvent->buttons() & Qt::LeftButton))
     return;
+  Handle(V3d_View) aView = theViewer->activeView();
+  gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), aView);
 
-  gp_Pnt aPoint = PartSet_Tools::convertClickToPoint(theEvent->pos(), theView);
+  theViewer->enableSelection(false);
 
-  blockSelection(true);
+  //blockSelection(true);
   if (myCurPoint.myIsInitialized) {
     double aCurX, aCurY;
-    PartSet_Tools::convertTo2D(myCurPoint.myPoint, sketch(), theView, aCurX, aCurY);
+    PartSet_Tools::convertTo2D(myCurPoint.myPoint, sketch(), aView, aCurX, aCurY);
 
     double aX, anY;
-    PartSet_Tools::convertTo2D(aPoint, sketch(), theView, aX, anY);
+    PartSet_Tools::convertTo2D(aPoint, sketch(), aView, aX, anY);
 
     double aDeltaX = aX - aCurX;
     double aDeltaY = anY - aCurY;
 
-    boost::shared_ptr<SketchPlugin_Feature> aSketchFeature = boost::dynamic_pointer_cast<
-        SketchPlugin_Feature>(feature());
-    aSketchFeature->move(aDeltaX, aDeltaY);
-    static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);
-    ModelAPI_EventCreator::get()->sendUpdated(feature(), anEvent);
+    // the next code is commented because it is obsolete by the multi edit operation realization here
+    //if (myIsMultiOperation) {
+    //  std::map<FeaturePtr, std::list<std::string>>::iterator aFeatIter = myFeature2Attribute.begin();
+    //  while (aFeatIter != myFeature2Attribute.end()) {
+    //    FeaturePtr aFeature = aFeatIter->first;
+    //    std::list<std::string> anAttributes = aFeatIter->second;
+    //    // perform edit for the feature
+    //    if (anAttributes.empty()) {
+    //      std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
+    //                                     std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
+    //      if (aSketchFeature) {
+    //        aSketchFeature->move(aDeltaX, aDeltaY);
+    //      }
+    //    }
+    //    // perform edit for the feature's attribute
+    //    else {
+    //      std::list<std::string>::const_iterator anAttrIter = anAttributes.begin(),
+    //                                             anAttrEnd = anAttributes.end();
+    //      for (; anAttrIter != anAttrEnd; anAttrIter++) {
+    //        std::shared_ptr<GeomDataAPI_Point2D> aPointAttr = std::dynamic_pointer_cast<
+    //                         GeomDataAPI_Point2D>(aFeature->data()->attribute(*anAttrIter));
+    //        if (aPointAttr) {
+    //          aPointAttr->move(aDeltaX, aDeltaY);
+    //        }
+    //      }      
+    //    }
+    //    aFeatIter++;
+    //  }
+    //}
+    //else { // multieditoperation
+
+    //std::shared_ptr<SketchPlugin_Feature> aSketchFeature = std::dynamic_pointer_cast<
+    //    SketchPlugin_Feature>(feature());
+
+    bool isMoved = false;
+    bool aHasShift = (theEvent->modifiers() & Qt::ShiftModifier);
+
+    // the functionality to move the feature attribute if it exists in the internal map
+    std::map<FeaturePtr, std::list<std::string>>::iterator aFeatIter, aFeatLast;
+    if (aHasShift || myHighlightedFeature2Attribute.empty()) {
+      aFeatIter = myAllFeature2Attribute.begin();
+      aFeatLast = myAllFeature2Attribute.end();
+    }
+    else {
+      aFeatIter = myHighlightedFeature2Attribute.begin();
+      aFeatLast = myHighlightedFeature2Attribute.end();
+    }
+
+    while (aFeatIter != aFeatLast) {
+      FeaturePtr aFeature = aFeatIter->first;
+      // MPV: added condition because it could be external edge of some object, not sketch
+      if (aFeature && !sketch()->isSub(aFeature)) {
+        aFeatIter++;
+        continue;
+      }
+
+      std::list<std::string> anAttributes = aFeatIter->second;
+      // perform edit for the feature
+      if (anAttributes.empty()) {
+        std::shared_ptr<SketchPlugin_Feature> aSketchFeature =
+                                       std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
+        if (aSketchFeature) {
+          aSketchFeature->move(aDeltaX, aDeltaY);
+          isMoved = true;
+        }
+      }
+      // perform edit for the feature's attribute
+      else {
+        std::list<std::string>::const_iterator anAttrIter = anAttributes.begin(),
+                                               anAttrEnd = anAttributes.end();
+        for (; anAttrIter != anAttrEnd; anAttrIter++) {
+          std::shared_ptr<GeomDataAPI_Point2D> aPointAttr = std::dynamic_pointer_cast<
+                           GeomDataAPI_Point2D>(aFeature->data()->attribute(*anAttrIter));
+          if (aPointAttr) {
+            aPointAttr->move(aDeltaX, aDeltaY);
+            isMoved = true;
+          }
+        }      
+      }
+      aFeatIter++;
+    }
+    // the next code is commented because it is obsolete by the multi edit operation realization here
+    // the feature is moved only if there is no a local selection on this feature
+    //if (!isMoved) {
+    //  // MPV: added condition because it could be external edge of some object, not sketch
+    //  if (aSketchFeature && sketch()->isSub(aSketchFeature)) {
+    //   aSketchFeature->move(aDeltaX, aDeltaY);
+    //    static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY);
+    //   ModelAPI_EventCreator::get()->sendUpdated(feature(), anEvent);
+    //  }
+    // }
+    //} // multieditoperation
+    sendFeatures(aHasShift);
   }
-  sendFeatures();
 
   myCurPoint.setPoint(aPoint);
 }
 
 void PartSet_OperationFeatureEdit::mouseReleased(
-    QMouseEvent* theEvent, Handle(V3d_View) theView,
-    const std::list<ModuleBase_ViewerPrs>& /*theSelected*/,
-    const std::list<ModuleBase_ViewerPrs>& /*theHighlighted*/)
+    QMouseEvent* theEvent, ModuleBase_IViewer* theViewer,
+    ModuleBase_ISelection* theSelection)
 {
-  blockSelection(false);
+  // the block is processed in order to do not commit the transaction until the started
+  // double click functionality is performed. It is reproduced on Linux only
+  if (myIsBlockedByDoubleClick)
+    return;
+
+  theViewer->enableSelection(true);
+  // the next code is commented because it is obsolete by the multi edit operation realization here
+  //if (myIsMultiOperation) {
+  //  if (commit()) {
+  //    std::map<FeaturePtr, std::list<std::string>>::iterator aFeatIter = myFeature2Attribute.begin();
+  //    while (aFeatIter != myFeature2Attribute.end()) {
+  //      FeaturePtr aFeature = aFeatIter->first;
+  //      if (aFeature) {
+  //        emit featureConstructed(aFeature, FM_Deactivation);
+  //      }
+  //      aFeatIter++;
+  //    }
+  //  }
+  //}
+  //else { // multieditoperation
+  ModuleBase_ModelWidget* aActiveWgt = 0;
+  if (myPropertyPanel)
+    aActiveWgt = myPropertyPanel->activeWidget();
+  if(aActiveWgt && aActiveWgt->isViewerSelector()) {
+    // Almost do nothing, all stuff in on PartSet_OperationFeatureBase::mouseReleased
+    PartSet_OperationFeatureBase::mouseReleased(theEvent, theViewer, theSelection);
+  //}// else {
+  ////blockSelection(false);
+  ////}
+  //} // multieditoperation
+  }
+  else {
+    theViewer->enableSelection(true);
+
+    // commit operation if there is no selected an highlighted objects anymore
+    Handle(V3d_View) aView = theViewer->activeView();
+    QList<ModuleBase_ViewerPrs> aSelected = theSelection->getSelected();
+    QList<ModuleBase_ViewerPrs> aHighlighted = theSelection->getHighlighted();
+
+    if (aSelected.empty() && aHighlighted.empty()) {
+      commit();
+      emitFeaturesDeactivation();
+    }
+    else if (aSelected.size() == 1) {
+     /// TODO: OCC bug: 25034 - the highlighted list should be filled not only for AIS_Shape
+     /// but for other IO, for example constraint dimensions.
+     /// It is empty and we have to use the process mouse release to start edition operation
+     /// for these objects
+      ObjectPtr anObject = aSelected.first().object();
+      FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
+      if (aFeature && PartSet_Tools::isConstraintFeature(aFeature->getKind()) &&
+          aFeature != feature()) {
+        restartOperation(PartSet_OperationFeatureEdit::Type(), aFeature);
+      }
+    }
+  }
 }
 
 void PartSet_OperationFeatureEdit::mouseDoubleClick(
     QMouseEvent* theEvent, Handle_V3d_View theView,
-    const std::list<ModuleBase_ViewerPrs>& theSelected,
-    const std::list<ModuleBase_ViewerPrs>& theHighlighted)
+    ModuleBase_ISelection* theSelection)
 {
   // TODO the functionality is important only for constraint feature. Should be moved in another place
-  if (!theSelected.empty()) {
-    ModuleBase_ViewerPrs aFeaturePrs = theSelected.front();
+  QList<ModuleBase_ViewerPrs> aSelected = theSelection->getSelected();
+  // in case when the double click happens on another constraint feature when selection control is active
+  // we should not perform the double click functionality
+  // if there is no the viewer selector widget active, the operation is restarted with a correct feature
+  ModuleBase_ModelWidget* aActiveWgt = myPropertyPanel->activeWidget();
+  if(aActiveWgt && aActiveWgt->isViewerSelector()) {
+    if (!aSelected.empty()) {
+      if (aSelected.size() == 1) {
+       /// TODO: OCC bug: 25034 - the highlighted list should be filled not only for AIS_Shape
+       /// but for other IO, for example constraint dimensions.
+       /// It is empty and we have to use the process mouse release to start edition operation
+       /// for these objects
+        ObjectPtr anObject = aSelected.first().object();
+        FeaturePtr aFeature = ModelAPI_Feature::feature(anObject);
+        if (aFeature && PartSet_Tools::isConstraintFeature(aFeature->getKind()) &&
+            aFeature != feature()) {
+          return;
+        }
+      }
+    }
+  }
+
+  myIsBlockedByDoubleClick = true;
+  if (!aSelected.empty()) {
+    ModuleBase_ViewerPrs aFeaturePrs = aSelected.first();
     if (!aFeaturePrs.owner().IsNull()) {
       Handle(AIS_DimensionOwner) anOwner = Handle(AIS_DimensionOwner)::DownCast(
           aFeaturePrs.owner());
@@ -159,56 +435,87 @@ void PartSet_OperationFeatureEdit::mouseDoubleClick(
       }
     }
   }
+  myIsBlockedByDoubleClick  = false;
 }
 
 void PartSet_OperationFeatureEdit::startOperation()
 {
   PartSet_OperationSketchBase::startOperation();
-  emit multiSelectionEnabled(false);
+  //emit multiSelectionEnabled(false);
 
   myCurPoint.clear();
 }
 
 void PartSet_OperationFeatureEdit::stopOperation()
 {
-  emit multiSelectionEnabled(true);
+  //emit multiSelectionEnabled(true);
 
-  blockSelection(false, false);
-}
+  //blockSelection(false, false);
 
-void PartSet_OperationFeatureEdit::blockSelection(bool isBlocked, const bool isRestoreSelection)
-{
-  if (myIsBlockedSelection == isBlocked)
-    return;
-
-  myIsBlockedSelection = isBlocked;
-  QList<ObjectPtr> aFeatureList;
-  aFeatureList.append(feature());
-
-  if (isBlocked) {
-    emit setSelection(QList<ObjectPtr>());
-    emit stopSelection(aFeatureList, true);
-  } else {
-    emit stopSelection(aFeatureList, false);
-    if (isRestoreSelection)
-      emit setSelection(aFeatureList);
-  }
+  myHighlightedFeature2Attribute.clear();
+  myAllFeature2Attribute.clear();
 }
 
-FeaturePtr PartSet_OperationFeatureEdit::createFeature(const bool /*theFlushMessage*/)
+//void PartSet_OperationFeatureEdit::blockSelection(bool isBlocked, const bool isRestoreSelection)
+//{
+//  if (myIsBlockedSelection == isBlocked)
+//    return;
+//
+//  myIsBlockedSelection = isBlocked;
+//  QList<ObjectPtr> aFeatureList;
+//  aFeatureList.append(feature());
+//
+//  //if (isBlocked) {
+//  //  emit setSelection(QList<ObjectPtr>());
+//  //  emit stopSelection(aFeatureList, true);
+//  //} else {
+//  //  emit stopSelection(aFeatureList, false);
+//  //  if (isRestoreSelection)
+//  //    emit setSelection(aFeatureList);
+//  //}
+//}
+
+FeaturePtr PartSet_OperationFeatureEdit::createFeature(const bool theFlushMessage,
+  CompositeFeaturePtr theCompositeFeature)
 {
   // do nothing in order to do not create a new feature
   return FeaturePtr();
 }
 
-void PartSet_OperationFeatureEdit::sendFeatures()
+void PartSet_OperationFeatureEdit::sendFeatures(const bool theIsAllFeatures)
 {
   static Events_ID anEvent = Events_Loop::eventByName(EVENT_OBJECT_MOVED);
 
-  FeaturePtr aFeature = feature();
-  ModelAPI_EventCreator::get()->sendUpdated(aFeature, anEvent);
+  std::map<FeaturePtr, std::list<std::string>>::iterator aFeatIter, aFeatLast;
+  if (theIsAllFeatures || myHighlightedFeature2Attribute.empty()) {
+    aFeatIter = myAllFeature2Attribute.begin();
+    aFeatLast = myAllFeature2Attribute.end();
+  }
+  else {
+    aFeatIter = myHighlightedFeature2Attribute.begin();
+    aFeatLast = myHighlightedFeature2Attribute.end();
+  }
+  while (aFeatIter != aFeatLast) {
+    FeaturePtr aFeature = aFeatIter->first;
+    if (aFeature) {
+      ModelAPI_EventCreator::get()->sendUpdated(aFeature, anEvent);
+    }
+    aFeatIter++;
+  }
 
   Events_Loop::loop()->flush(anEvent);
   flushUpdated();
 }
 
+void PartSet_OperationFeatureEdit::emitFeaturesDeactivation()
+{
+  std::map<FeaturePtr, std::list<std::string>>::iterator aFeatIter = myAllFeature2Attribute.begin();
+  while (aFeatIter != myAllFeature2Attribute.end()) {
+    FeaturePtr aFeature = aFeatIter->first;
+    if (aFeature) {
+      emit featureConstructed(aFeature, FM_Deactivation);
+    }
+    aFeatIter++;
+  }
+}
+