Salome HOME
Issue #2024 - Redesign of circle and arc of circle: fill Reference Attribute
authornds <nds@opencascade.com>
Thu, 23 Mar 2017 08:33:32 +0000 (11:33 +0300)
committerdbv <dbv@opencascade.com>
Mon, 27 Mar 2017 06:56:54 +0000 (09:56 +0300)
Type of Circle macro feature should be saved by restarting of operation.

14 files changed:
src/Config/Config_Keywords.h
src/ModuleBase/ModuleBase_ModelWidget.cpp
src/ModuleBase/ModuleBase_ModelWidget.h
src/ModuleBase/ModuleBase_PagedContainer.cpp
src/PartSet/CMakeLists.txt
src/PartSet/PartSet_Module.cpp
src/PartSet/PartSet_Module.h
src/PartSet/PartSet_SketcherMgr.cpp
src/PartSet/PartSet_SketcherReentrantMgr.cpp [new file with mode: 0644]
src/PartSet/PartSet_SketcherReentrantMgr.h [new file with mode: 0644]
src/PartSet/PartSet_SketcherReetntrantMgr.cpp [deleted file]
src/PartSet/PartSet_SketcherReetntrantMgr.h [deleted file]
src/PartSet/PartSet_WidgetPoint2d.cpp
src/SketchPlugin/plugin-Sketch.xml

index 6b4a1312f49a902d794ae9ce18e1d68c4b9dc260..befdd08e58dd4068b309fbe9aed46ab3ac942b51 100644 (file)
@@ -80,6 +80,7 @@ const static char* ATTR_OBLIGATORY = "obligatory";
 const static char* ATTR_CONCEALMENT = "concealment";
 const static char* ATTR_USE_RESET = "use_reset";
 const static char* ATTR_GREED = "greed";
+const static char* ATTR_MODIFIED_IN_EDIT = "modified_in_edit";
 
 // WDG_INFO properties
 const static char* INFO_WDG_TEXT = FEATURE_TEXT;
index db9908a41da042ddfb9ca90f48b5799b48ddf1e5..aa0470f7a6c2faca5ef62048f679b1df740ff546 100644 (file)
@@ -51,6 +51,8 @@ ModuleBase_ModelWidget::ModuleBase_ModelWidget(QWidget* theParent,
 
   myIsInternal = theData->getBooleanAttribute(ATTR_INTERNAL, false);
 
+  myIsModifiedInEdit = theData->getBooleanAttribute(ATTR_MODIFIED_IN_EDIT, true);
+
   myDefaultValue = theData->getProperty(ATTR_DEFAULT);
   myUseReset = theData->getBooleanAttribute(ATTR_USE_RESET, true);
   myIsComputedDefault = theData->getProperty(ATTR_DEFAULT) == DOUBLE_WDG_DEFAULT_COMPUTED;
@@ -310,7 +312,12 @@ bool ModuleBase_ModelWidget::storeValue()
   setValueState(Stored);
 
   emit beforeValuesChanged();
-  bool isDone = storeValueCustom();
+  bool isDone = false;
+  // value is stored only in creation mode and in edition if there is not
+  // XML flag prohibited modification in edit mode(macro feature circle/arc)
+  if (!isEditingMode() || isModifiedInEdit())
+    isDone = storeValueCustom();
+
   emit afterValuesChanged();
 
   return isDone;
index 25db7bcfce3ca4be4388b04609374bb89eeebc8d..fcd2ad508b81e1218ea686d5031162f8c49cbee6 100644 (file)
@@ -93,6 +93,10 @@ Q_OBJECT
   /// \return the boolean result
   bool isUseReset() const { return myUseReset; }
 
+  /// Returns this parameter value in the xml file
+  /// \return the boolean result
+  bool isModifiedInEdit() const { return myIsModifiedInEdit; }
+
   /// Returns this widget value state
   /// \return the enumeration result
   ValueState getValueState() const { return myState; }
@@ -359,6 +363,9 @@ private:
   /// an XML internal state
   bool myIsInternal;
 
+  // an XML state, the value is not stored into model if the widget is in edit mode
+  bool myIsModifiedInEdit;
+
   /// the reset state. If it is false, the reset method of the widget is not performed
   bool myUseReset;
   /// blocked flag of modification of the value state
index 42d48907f6a4cead710bdbf9253e6de3be06e751..8723cbd778aad168f207e7025d1925b8f62c75bd 100644 (file)
@@ -111,8 +111,13 @@ bool ModuleBase_PagedContainer::storeValueCustom()
 
 void ModuleBase_PagedContainer::onPageChanged()
 {
-  storeValue();
-  if (myIsFocusOnCurrentPage) focusTo();
+  if (!storeValue())
+    return;
+  // focus might be changed only if the value is correcly stored
+  // if it is not stored, reentrant manager will handle by this widget
+  // after it will restart operation, the widget might be removed
+  if (myIsFocusOnCurrentPage)
+    focusTo();
 }
 
 
index bb1035a06463121b15bc08604a1547dcfdd6c6ae..3793d26af3cedf97e975bf6435939841bb201f13 100644 (file)
@@ -25,7 +25,7 @@ SET(PROJECT_HEADERS
     PartSet_PreviewPlanes.h
     PartSet_ResultSketchPrs.h
     PartSet_SketcherMgr.h
-    PartSet_SketcherReetntrantMgr.h
+    PartSet_SketcherReentrantMgr.h
     PartSet_Tools.h
     PartSet_Validators.h
     PartSet_WidgetChoice.h
@@ -47,7 +47,7 @@ SET(PROJECT_MOC_HEADERS
     PartSet_MenuMgr.h
     PartSet_Module.h
     PartSet_SketcherMgr.h
-    PartSet_SketcherReetntrantMgr.h
+    PartSet_SketcherReentrantMgr.h
     PartSet_WidgetChoice.h
     PartSet_WidgetEditor.h
     PartSet_WidgetFeaturePointSelector.h
@@ -75,7 +75,7 @@ SET(PROJECT_SOURCES
     PartSet_PreviewPlanes.cpp
     PartSet_ResultSketchPrs.cpp
     PartSet_SketcherMgr.cpp
-    PartSet_SketcherReetntrantMgr.cpp
+    PartSet_SketcherReentrantMgr.cpp
     PartSet_Tools.cpp
     PartSet_Validators.cpp
     PartSet_WidgetEditor.cpp
index 14f18c9422e0cd84ed0076042b8fbb90f54b43de..67b4adf8539c41ef39681973a6ef60ab8de6255d 100755 (executable)
@@ -16,7 +16,7 @@
 #include "PartSet_WidgetFileSelector.h"
 #include "PartSet_WidgetSketchCreator.h"
 #include "PartSet_SketcherMgr.h"
-#include "PartSet_SketcherReetntrantMgr.h"
+#include "PartSet_SketcherReentrantMgr.h"
 #include "PartSet_ResultSketchPrs.h"
 #include "PartSet_MenuMgr.h"
 #include "PartSet_CustomPrs.h"
@@ -132,7 +132,7 @@ PartSet_Module::PartSet_Module(ModuleBase_IWorkshop* theWshop)
   new PartSet_IconFactory();
 
   mySketchMgr = new PartSet_SketcherMgr(this);
-  mySketchReentrantMgr = new PartSet_SketcherReetntrantMgr(theWshop);
+  mySketchReentrantMgr = new PartSet_SketcherReentrantMgr(theWshop);
 
   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(theWshop);
   XGUI_Workshop* aWorkshop = aConnector->workshop();
index ed00ebef5a55129b9a54dd6286a2b17de5ce806f..3c7316458e02a0cfc32b22ab124bbd53574f3fa4 100755 (executable)
@@ -34,7 +34,7 @@ class XGUI_Workshop;
 class PartSet_MenuMgr;
 class PartSet_CustomPrs;
 class PartSet_SketcherMgr;
-class PartSet_SketcherReetntrantMgr;
+class PartSet_SketcherReentrantMgr;
 class ModelAPI_Result;
 
 class QAction;
@@ -203,7 +203,7 @@ public:
   PartSet_SketcherMgr* sketchMgr() const { return mySketchMgr; }
 
   /// Returns sketch reentrant manager
-  PartSet_SketcherReetntrantMgr* sketchReentranceMgr() const { return mySketchReentrantMgr; }
+  PartSet_SketcherReentrantMgr* sketchReentranceMgr() const { return mySketchReentrantMgr; }
 
   /// Returns listener of overconstraint signal
   /// \return the listener
@@ -408,7 +408,7 @@ private:
   SelectMgr_ListOfFilter mySelectionFilters;
 
   PartSet_SketcherMgr* mySketchMgr;
-  PartSet_SketcherReetntrantMgr* mySketchReentrantMgr;
+  PartSet_SketcherReentrantMgr* mySketchReentrantMgr;
   PartSet_MenuMgr* myMenuMgr;
   /// A default custom presentation, which is used for references objects of started operation
   PartSet_CustomPrs* myCustomPrs;
index 5497da37a30250a710f08e7ef658a7a6965d37ff..1fd62e95de79c6560fb1c7a72182491811dfdd66 100755 (executable)
@@ -5,7 +5,7 @@
 // Author:      Vitaly SMETANNIKOV
 
 #include "PartSet_SketcherMgr.h"
-#include "PartSet_SketcherReetntrantMgr.h"
+#include "PartSet_SketcherReentrantMgr.h"
 #include "PartSet_Module.h"
 #include "PartSet_MouseProcessor.h"
 #include "PartSet_Tools.h"
@@ -615,7 +615,7 @@ void PartSet_SketcherMgr::onApplicationStarted()
   ModuleBase_IWorkshop* anIWorkshop = myModule->workshop();
   XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(anIWorkshop);
   XGUI_Workshop* aWorkshop = aConnector->workshop();
-  PartSet_SketcherReetntrantMgr* aReentranceMgr = myModule->sketchReentranceMgr();
+  PartSet_SketcherReentrantMgr* aReentranceMgr = myModule->sketchReentranceMgr();
 
   XGUI_PropertyPanel* aPropertyPanel = aWorkshop->propertyPanel();
   if (aPropertyPanel) {
@@ -1540,19 +1540,23 @@ void PartSet_SketcherMgr::getSelectionOwners(const FeaturePtr& theFeature,
 void PartSet_SketcherMgr::connectToPropertyPanel(ModuleBase_ModelWidget* theWidget,
                                                  const bool isToConnect)
 {
-  /*Temporary commented as we do not modify values in property panel
+  //Temporary commented as we do not modify values in property panel
   if (isToConnect) {
-    connect(theWidget, SIGNAL(beforeValuesChanged()),
-            this, SLOT(onBeforeValuesChangedInPropertyPanel()));
+    //connect(theWidget, SIGNAL(beforeValuesChanged()),
+    //        this, SLOT(onBeforeValuesChangedInPropertyPanel()));
+    //connect(theWidget, SIGNAL(afterValuesChanged()),
+    //        this, SLOT(onAfterValuesChangedInPropertyPanel()));
     connect(theWidget, SIGNAL(afterValuesChanged()),
-            this, SLOT(onAfterValuesChangedInPropertyPanel()));
+            myModule->sketchReentranceMgr(), SLOT(onAfterValuesChangedInPropertyPanel()));
   }
   else {
-    disconnect(theWidget, SIGNAL(beforeValuesChanged()),
-                this, SLOT(onBeforeValuesChangedInPropertyPanel()));
+    //disconnect(theWidget, SIGNAL(beforeValuesChanged()),
+    //            this, SLOT(onBeforeValuesChangedInPropertyPanel()));
+    //disconnect(theWidget, SIGNAL(afterValuesChanged()),
+    //            this, SLOT(onAfterValuesChangedInPropertyPanel()));
     disconnect(theWidget, SIGNAL(afterValuesChanged()),
-                this, SLOT(onAfterValuesChangedInPropertyPanel()));
-  }*/
+               myModule->sketchReentranceMgr(), SLOT(onAfterValuesChangedInPropertyPanel()));
+  }
 }
 
 void PartSet_SketcherMgr::widgetStateChanged(int thePreviousState)
diff --git a/src/PartSet/PartSet_SketcherReentrantMgr.cpp b/src/PartSet/PartSet_SketcherReentrantMgr.cpp
new file mode 100644 (file)
index 0000000..45547cb
--- /dev/null
@@ -0,0 +1,724 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+#include "PartSet_SketcherReentrantMgr.h"
+#include "PartSet_Module.h"
+#include "PartSet_SketcherMgr.h"
+#include "PartSet_WidgetPoint2d.h"
+
+#include "ModelAPI_Session.h"
+#include "ModelAPI_AttributeString.h"
+#include "ModelAPI_AttributeRefAttr.h"
+
+#include "GeomDataAPI_Point2D.h"
+
+#include <ModuleBase_IPropertyPanel.h>
+#include <ModuleBase_OperationFeature.h>
+#include <ModuleBase_ModelWidget.h>
+#include <ModuleBase_ViewerPrs.h>
+#include <ModuleBase_WidgetSelector.h>
+#include <ModuleBase_PageWidget.h>
+#include <ModuleBase_PageBase.h>
+#include <ModuleBase_WidgetFactory.h>
+#include <ModuleBase_OperationDescription.h>
+#include "ModuleBase_ToolBox.h"
+#include "ModuleBase_ISelection.h"
+
+#include <SketchPlugin_Feature.h>
+#include <SketchPlugin_Line.h>
+#include <SketchPlugin_Arc.h>
+#include <SketchPlugin_MacroCircle.h>
+#include <SketchPlugin_Point.h>
+
+#include <XGUI_Workshop.h>
+#include <XGUI_ModuleConnector.h>
+#include <XGUI_OperationMgr.h>
+#include <XGUI_PropertyPanel.h>
+#include <XGUI_ErrorMgr.h>
+#include <XGUI_SelectionMgr.h>
+
+#include <QToolButton>
+
+PartSet_SketcherReentrantMgr::PartSet_SketcherReentrantMgr(ModuleBase_IWorkshop* theWorkshop)
+: QObject(theWorkshop),
+  myWorkshop(theWorkshop),
+  myRestartingMode(RM_None),
+  myIsFlagsBlocked(false),
+  myIsInternalEditOperation(false),
+  myIsValueChangedBlocked(false),
+  myInternalActiveWidget(0),
+  myNoMoreWidgetsAttribute("")
+{
+}
+
+PartSet_SketcherReentrantMgr::~PartSet_SketcherReentrantMgr()
+{
+}
+
+ModuleBase_ModelWidget* PartSet_SketcherReentrantMgr::internalActiveWidget() const
+{
+  ModuleBase_ModelWidget* aWidget = 0;
+  if (!isActiveMgr())
+    return aWidget;
+
+  ModuleBase_Operation* anOperation = myWorkshop->currentOperation();
+  if (anOperation) {
+    ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel();
+    if (aPanel) { // check for case when the operation is started but property panel is not filled
+      ModuleBase_ModelWidget* anActiveWidget = aPanel->activeWidget();
+      if (myIsInternalEditOperation && (!anActiveWidget || !anActiveWidget->isViewerSelector()))
+        aWidget = myInternalActiveWidget;
+    }
+  }
+  return aWidget;
+}
+
+bool PartSet_SketcherReentrantMgr::isInternalEditActive() const
+{
+  return myIsInternalEditOperation;
+}
+
+void PartSet_SketcherReentrantMgr::updateInternalEditActiveState()
+{
+  if  (myIsInternalEditOperation) {
+    ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+                                                         (myWorkshop->currentOperation());
+    if (aFOperation) {
+      FeaturePtr aFeature = aFOperation->feature();
+      QString anError = myWorkshop->module()->getFeatureError(aFeature);
+      // stop started internal edit operation as soon as the operation becomes invalid
+      // it is especially important for the sketch tangent arc feature
+      if (!anError.isEmpty()) {
+        aFOperation->setEditOperation(false);
+        //workshop()->operationMgr()->updateApplyOfOperations();
+        myIsInternalEditOperation = false;
+        updateAcceptAllAction();
+      }
+    }
+  }
+}
+
+bool PartSet_SketcherReentrantMgr::operationCommitted(ModuleBase_Operation* theOperation)
+{
+  bool aProcessed = false;
+  if (!isActiveMgr())
+    return aProcessed;
+
+  aProcessed = myIsInternalEditOperation;
+  resetFlags();
+
+  return aProcessed;
+}
+
+void PartSet_SketcherReentrantMgr::operationStarted(ModuleBase_Operation* theOperation)
+{
+  if (!isActiveMgr())
+    return;
+
+  if (myPreviousFeature.get() && myRestartingMode == RM_LastFeatureUsed) {
+    ModuleBase_OperationFeature* aCurrentOperation = dynamic_cast<ModuleBase_OperationFeature*>(
+                                                                myWorkshop->currentOperation());
+    CompositeFeaturePtr aSketch = module()->sketchMgr()->activeSketch();
+    copyReetntrantAttributes(myPreviousFeature, aCurrentOperation->feature(), aSketch);
+  }
+  resetFlags();
+}
+
+void PartSet_SketcherReentrantMgr::operationAborted(ModuleBase_Operation* theOperation)
+{
+  if (!isActiveMgr())
+    return;
+
+  resetFlags();
+}
+
+bool PartSet_SketcherReentrantMgr::processMouseMoved(ModuleBase_IViewWindow* theWnd,
+                                                      QMouseEvent* theEvent)
+{
+  bool aProcessed = false;
+  if (!isActiveMgr())
+    return aProcessed;
+
+  if  (myIsInternalEditOperation) {
+    ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+                                                         (myWorkshop->currentOperation());
+    FeaturePtr aLastFeature = myRestartingMode == RM_LastFeatureUsed ? aFOperation->feature()
+                                                                     : FeaturePtr();
+    if (aLastFeature) {
+      ModuleBase_ModelWidget* anActiveWidget = module()->activeWidget();
+      ModuleBase_IPropertyPanel* aPanel = myWorkshop->currentOperation()->propertyPanel();
+
+      FeaturePtr aCurrentFeature = aFOperation->feature();
+      bool isLineFeature = false, isArcFeature = false;
+      std::string anAttributeOnStart;
+      if (aCurrentFeature->getKind() == SketchPlugin_Line::ID()) {
+        anAttributeOnStart = SketchPlugin_Line::START_ID();
+        isLineFeature = anActiveWidget->attributeID() == anAttributeOnStart;
+      }
+      else if (isTangentArc(aFOperation, module()->sketchMgr()->activeSketch())) {
+        anAttributeOnStart = SketchPlugin_Arc::TANGENT_POINT_ID();
+        isArcFeature = anActiveWidget->attributeID() == anAttributeOnStart;
+      }
+      bool aCanBeActivatedByMove = isLineFeature || isArcFeature;
+      if (aCanBeActivatedByMove) {
+        /// before restarting of operation we need to clear selection, as it may take part in
+        /// new feature creation, e.g. tangent arc. But it is not necessary as it was processed
+        /// by mouse release when the operation was restarted.
+        workshop()->selector()->clearSelection();
+
+        myPreviousFeature = aFOperation->feature();
+        restartOperation();
+        myPreviousFeature = FeaturePtr();
+
+        anActiveWidget = module()->activeWidget();
+        aCurrentFeature = anActiveWidget->feature();
+        aProcessed = true;
+        if (anActiveWidget->attributeID() == anAttributeOnStart) {
+          // it was not deactivated by preselection processing
+          aPanel->activateNextWidget(anActiveWidget);
+        }
+      } else {
+        // processing mouse move in active widget of restarted operation
+        ModuleBase_ModelWidget* anActiveWidget = module()->activeWidget();
+        PartSet_MouseProcessor* aProcessor = dynamic_cast<PartSet_MouseProcessor*>(anActiveWidget);
+        if (aProcessor)
+          aProcessor->mouseMoved(theWnd, theEvent);
+      }
+    }
+  }
+  return aProcessed;
+}
+
+bool PartSet_SketcherReentrantMgr::processMousePressed(ModuleBase_IViewWindow* /* theWnd*/,
+                                                        QMouseEvent* /* theEvent*/)
+{
+  return isActiveMgr() && myIsInternalEditOperation;
+}
+
+bool PartSet_SketcherReentrantMgr::processMouseReleased(ModuleBase_IViewWindow* theWnd,
+                                                         QMouseEvent* theEvent)
+{
+  bool aProcessed = false;
+  if (!isActiveMgr())
+    return aProcessed;
+
+  if (myIsInternalEditOperation) {
+    ModuleBase_Operation* anOperation = myWorkshop->currentOperation();
+    ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel();
+
+    ModuleBase_ModelWidget* anActiveWidget = aPanel->activeWidget();
+    if (!anActiveWidget || !anActiveWidget->isViewerSelector()) {
+
+      // block of viewer update
+      // we need to block update content of the viewer because of Sketch Point feature
+      // in activate() the value of the point is initialized and it can be displayed
+      // but the default value is [0, 0]. So, we block update viewer contentent until
+      // onMouseRelease happens, which correct the point position
+      ModuleBase_Tools::blockUpdateViewer(true);
+
+      ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+                                                           (myWorkshop->currentOperation());
+      myPreviousFeature = aFOperation->feature();
+
+      /// selection should be obtained from workshop before ask if the operation can be started as
+      /// the canStartOperation method performs commit/abort of previous operation.
+      /// Sometimes commit/abort
+      /// may cause selection clear(Sketch operation) as a result
+      /// it will be lost and is not used for preselection.
+      ModuleBase_ISelection* aSelection = myWorkshop->selection();
+      QList<ModuleBase_ViewerPrsPtr> aPreSelected =
+        aSelection->getSelected(ModuleBase_ISelection::AllControls);
+
+      restartOperation();
+      myPreviousFeature = FeaturePtr();
+      aProcessed = true;
+
+      // fill the first widget by the mouse event point
+      // if the active widget is not the first, it means that the restarted operation is filled by
+      // the current preselection.
+      PartSet_MouseProcessor* aMouseProcessor = dynamic_cast<PartSet_MouseProcessor*>(
+                                                                       module()->activeWidget());
+      //PartSet_WidgetPoint2D* aPoint2DWdg =
+      //  dynamic_cast<PartSet_WidgetPoint2D*>(module()->activeWidget());
+      PartSet_MouseProcessor* aFirstWidget = dynamic_cast<PartSet_MouseProcessor*>(
+                                                        aPanel->findFirstAcceptingValueWidget());
+      //if (aPoint2DWdg && aPoint2DWdg == aFirstWidget) {
+      if (aMouseProcessor && aMouseProcessor == aFirstWidget) {
+        std::shared_ptr<ModuleBase_ViewerPrs> aSelectedPrs;
+        if (!aPreSelected.empty())
+          aSelectedPrs = aPreSelected.front();
+        aMouseProcessor->setPreSelection(aSelectedPrs, theWnd, theEvent);
+        //aPoint2DWdg->mouseReleased(theWnd, theEvent);
+        //if (!aPreSelected.empty())
+        //  aPoint2DWdg->setPreSelection(ModuleBase_ViewerPrsPtr());
+      }
+      // unblock viewer update
+      ModuleBase_Tools::blockUpdateViewer(false);
+    }
+  }
+
+  return aProcessed;
+}
+
+void PartSet_SketcherReentrantMgr::onWidgetActivated()
+{
+  if (!isActiveMgr())
+    return;
+  if (!myIsInternalEditOperation)
+    return;
+
+  PartSet_Module* aModule = module();
+  ModuleBase_ModelWidget* aFirstWidget = aModule->activeWidget();
+  ModuleBase_IPropertyPanel* aPanel = aModule->currentOperation()->propertyPanel();
+  if (aFirstWidget != aPanel->activeWidget()) {
+    ModuleBase_WidgetSelector* aWSelector = dynamic_cast<ModuleBase_WidgetSelector*>(aFirstWidget);
+    if (aWSelector)
+      aWSelector->activateSelectionAndFilters(true);
+  }
+}
+
+void PartSet_SketcherReentrantMgr::onNoMoreWidgets(const std::string& thePreviousAttributeID)
+{
+  if (!isActiveMgr())
+    return;
+
+  // we should avoid processing of the signal about no more widgets attributes and
+  // do this after the restart operaion is finished if it was called
+  // onNoMoreWidgets depends on myIsFlagsBlocked and fill myNoMoreWidgetsAttribute
+  // if it should be called after restart
+  if (myIsFlagsBlocked) {
+    myNoMoreWidgetsAttribute = thePreviousAttributeID;
+    return;
+  }
+
+  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+                                                       (myWorkshop->currentOperation());
+  if (!myWorkshop->module()->getFeatureError(aFOperation->feature()).isEmpty())
+    return;
+
+  if (aFOperation && module()->sketchMgr()->isNestedSketchOperation(aFOperation)) {
+    bool isStarted = false;
+    if (!module()->sketchMgr()->sketchSolverError()) {
+      if (myRestartingMode != RM_Forbided) {
+        myRestartingMode = RM_LastFeatureUsed;
+        isStarted = startInternalEdit(thePreviousAttributeID);
+      }
+    }
+    if (!isStarted)
+      aFOperation->commit();
+  }
+}
+
+bool PartSet_SketcherReentrantMgr::processEnter(const std::string& thePreviousAttributeID)
+{
+  bool isDone = false;
+
+  if (!isActiveMgr())
+    return isDone;
+
+  // empty previous attribute means that the Apply/Ok button has focus and the enter
+  // should not lead to start edition mode of the previous operation
+  if (thePreviousAttributeID.empty())
+    return isDone;
+
+  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+                                                       (myWorkshop->currentOperation());
+  if (!myWorkshop->module()->getFeatureError(aFOperation->feature()).isEmpty())
+    return isDone;
+
+  bool isSketchSolverError = module()->sketchMgr()->sketchSolverError();
+
+  if (!isSketchSolverError) {
+    myRestartingMode = RM_EmptyFeatureUsed;
+    isDone = startInternalEdit(thePreviousAttributeID);
+  }
+
+  return isDone;
+}
+
+void PartSet_SketcherReentrantMgr::onVertexSelected()
+{
+  if (!isActiveMgr())
+    return;
+
+  ModuleBase_Operation* anOperation = myWorkshop->currentOperation();
+  std::string anOperationId = anOperation->id().toStdString();
+  if (anOperationId == SketchPlugin_Line::ID() ||
+      isTangentArc(anOperation, module()->sketchMgr()->activeSketch())) {
+    /// If last line finished on vertex the lines creation sequence has to be break
+    ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel();
+    ModuleBase_ModelWidget* anActiveWidget = aPanel->activeWidget();
+    const QList<ModuleBase_ModelWidget*>& aWidgets = aPanel->modelWidgets();
+    QList<ModuleBase_ModelWidget*>::const_iterator anIt = aWidgets.begin(), aLast = aWidgets.end();
+    bool aFoundWidget = false;
+    bool aFoundObligatory = false;
+    for (; anIt != aLast && !aFoundObligatory; anIt++) {
+      if (!aFoundWidget)
+        aFoundWidget = *anIt == anActiveWidget;
+      else
+        aFoundObligatory = (*anIt)->isObligatory();
+    }
+    if (!aFoundObligatory)
+      myRestartingMode = RM_Forbided;
+  }
+}
+
+void PartSet_SketcherReentrantMgr::onAfterValuesChangedInPropertyPanel()
+{
+  // blocked flag in order to avoid circling when storeValue will be applied in
+  // this method to cached widget
+  if (myIsValueChangedBlocked)
+    return;
+
+  if (isInternalEditActive()) {
+    ModuleBase_ModelWidget* aWidget = (ModuleBase_ModelWidget*)sender();
+    if (!aWidget->isModifiedInEdit())
+      restartOperation();
+  }
+}
+
+void PartSet_SketcherReentrantMgr::onBeforeStopped()
+{
+  if (!isActiveMgr() || !myIsInternalEditOperation)
+    return;
+
+  beforeStopInternalEdit();
+}
+
+bool PartSet_SketcherReentrantMgr::canBeCommittedByPreselection()
+{
+  return !isActiveMgr() || myRestartingMode == RM_None;
+}
+
+bool PartSet_SketcherReentrantMgr::isInternalEditStarted() const
+{
+  return myIsInternalEditOperation;
+}
+
+bool PartSet_SketcherReentrantMgr::isActiveMgr() const
+{
+  ModuleBase_Operation* aCurrentOperation = myWorkshop->currentOperation();
+
+  bool anActive = PartSet_SketcherMgr::isSketchOperation(aCurrentOperation);
+  if (!anActive) {
+    anActive = module()->sketchMgr()->isNestedSketchOperation(aCurrentOperation);
+    if (anActive) { // the manager is not active when the current operation is a usual Edit
+      ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+                                                       (myWorkshop->currentOperation());
+      if (aFOperation->isEditOperation())
+        anActive = myIsInternalEditOperation;
+    }
+  }
+  return anActive;
+}
+
+bool PartSet_SketcherReentrantMgr::startInternalEdit(const std::string& thePreviousAttributeID)
+{
+  bool isDone = false;
+  /// this is workaround for ModuleBase_WidgetEditor, used in SALOME mode. Sometimes key enter
+  /// event comes two times, so we should not start another internal edit operation
+  /// the Apply button becomes disabled becase the second additional internal feature is created
+  if (myIsInternalEditOperation)
+    return true;
+
+  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+                                                     (myWorkshop->currentOperation());
+
+  if (aFOperation && module()->sketchMgr()->isNestedSketchOperation(aFOperation)) {
+    aFOperation->setEditOperation(true/*, false*/);
+    createInternalFeature();
+
+    myIsInternalEditOperation = true;
+    updateAcceptAllAction();
+
+    isDone = true;
+    connect(aFOperation, SIGNAL(beforeCommitted()), this, SLOT(onBeforeStopped()));
+    connect(aFOperation, SIGNAL(beforeAborted()), this, SLOT(onBeforeStopped()));
+
+    // activate selection filters of the first widget in the viewer
+    onWidgetActivated();
+
+    // activate the last active widget in the Property Panel
+    if (!thePreviousAttributeID.empty()) {
+      ModuleBase_Operation* anEditOperation = module()->currentOperation();
+      if (anEditOperation) {
+        ModuleBase_IPropertyPanel* aPanel = aFOperation->propertyPanel();
+        ModuleBase_ModelWidget* aPreviousAttributeWidget = 0;
+        QList<ModuleBase_ModelWidget*> aWidgets = aPanel->modelWidgets();
+        for (int i = 0, aNb = aWidgets.size(); i < aNb && !aPreviousAttributeWidget; i++) {
+          if (aWidgets[i]->attributeID() == thePreviousAttributeID) {
+          /// workaround for the same attributes used in different stacked widgets(attribute types)
+          if (ModuleBase_ToolBox::isOffToolBoxParent(aWidgets[i]))
+            continue;
+            aPreviousAttributeWidget = aWidgets[i];
+          }
+        }
+        // If the current widget is a selector, do nothing, it processes the mouse press
+        if (aPreviousAttributeWidget) {
+          if (!aPreviousAttributeWidget->isViewerSelector()) {
+            aPreviousAttributeWidget->focusTo();
+            aPreviousAttributeWidget->selectContent();
+          }
+          else {
+            // in case of shape multi selector, the widget does not lose focus by filling
+            // like it is in shape selector. So, if enter is pressed, the multi shape selector
+            // control should be deactivated. The focus is moved to Apply button and there
+            // should not be active control visualized in property panel
+            if (aPreviousAttributeWidget == aPanel->activeWidget()) {
+              aPanel->activateWidget(NULL, false);
+            }
+            // if there is no the next widget to be automatically activated,
+            // the Ok button in property
+            // panel should accept the focus(example is parallel constraint on sketch lines)
+            QToolButton* anOkBtn =
+              dynamic_cast<XGUI_PropertyPanel*>(aPanel)->findButton(PROP_PANEL_OK);
+            if (anOkBtn)
+              anOkBtn->setFocus(Qt::TabFocusReason);
+          }
+        }
+      }
+    }
+  }
+  if (isDone)
+    module()->sketchMgr()->clearClickedFlags();
+
+  return isDone;
+}
+
+void PartSet_SketcherReentrantMgr::beforeStopInternalEdit()
+{
+  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+                                                      (myWorkshop->currentOperation());
+  if (aFOperation) {
+    disconnect(aFOperation, SIGNAL(beforeCommitted()), this, SLOT(onBeforeStopped()));
+    disconnect(aFOperation, SIGNAL(beforeAborted()), this, SLOT(onBeforeStopped()));
+  }
+
+  deleteInternalFeature();
+}
+
+void PartSet_SketcherReentrantMgr::restartOperation()
+{
+  if (myIsInternalEditOperation) {
+    ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>(
+                                                                  myWorkshop->currentOperation());
+    if (aFOperation) {
+      // obtain widgets(attributes) which content should be applied to attributes of new feature
+      ModuleBase_IPropertyPanel* aPanel = aFOperation->propertyPanel();
+      ModuleBase_ModelWidget* anActiveWidget = aPanel->activeWidget();
+      const QList<ModuleBase_ModelWidget*>& aWidgets = aPanel->modelWidgets();
+      QList<ModuleBase_ModelWidget*> aValueWidgets;
+      for (int i = 0, aSize = aWidgets.size(); i < aSize; i++) {
+        ModuleBase_ModelWidget* aWidget = aWidgets[i];
+        if (!aWidget->isModifiedInEdit()) {
+          aValueWidgets.append(aWidget);
+          // the widget is cashed to fill feature of new operation by the current widget value
+          // we set empty parent to the widget in order to remove it ourselves. Reason: restart
+          // operation will clear property panel and delete all widgets. This widget should be
+          // removed only after applying value of the widget to new created feature.
+          aWidget->setParent(0);
+        }
+      }
+
+      myNoMoreWidgetsAttribute = "";
+      myIsFlagsBlocked = true;
+      module()->launchOperation(aFOperation->id());
+      myIsFlagsBlocked = false;
+      resetFlags();
+      // we should avoid processing of the signal about no more widgets attributes and
+      // do this after the restart operaion is finished if it was called
+      // onNoMoreWidgets depends on myIsFlagsBlocked and fill myNoMoreWidgetsAttribute
+      // if it should be called after restart
+      if (!myNoMoreWidgetsAttribute.empty()) {
+        onNoMoreWidgets(myNoMoreWidgetsAttribute);
+        myNoMoreWidgetsAttribute = "";
+      }
+
+      // filling new feature by the previous value of active widget
+      // (e.g. circle_type in macro Circle)
+      ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>(
+                                                                myWorkshop->currentOperation());
+      myIsValueChangedBlocked = true; // flag to avoid onAfterValuesChangedInPropertyPanel slot
+      for (int i = 0, aSize = aValueWidgets.size(); i < aSize; i++) {
+        ModuleBase_ModelWidget* aWidget = aValueWidgets[i];
+        aWidget->setEditingMode(false);
+        aWidget->setFeature(aFOperation->feature());
+        aWidget->storeValue();
+        // we must delete this widget
+        delete aWidget;
+      }
+      myIsValueChangedBlocked = false;
+    }
+  }
+}
+
+void PartSet_SketcherReentrantMgr::createInternalFeature()
+{
+  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+                                                     (myWorkshop->currentOperation());
+
+  if (aFOperation && module()->sketchMgr()->isNestedSketchOperation(aFOperation)) {
+    FeaturePtr anOperationFeature = aFOperation->feature();
+
+    CompositeFeaturePtr aSketch = module()->sketchMgr()->activeSketch();
+    myInternalFeature = aSketch->addFeature(anOperationFeature->getKind());
+
+    bool isFeatureChanged = copyReetntrantAttributes(anOperationFeature, myInternalFeature,
+                                                     aSketch, false);
+    XGUI_PropertyPanel* aPropertyPanel = dynamic_cast<XGUI_PropertyPanel*>
+                                                  (aFOperation->propertyPanel());
+
+    myInternalWidget = new QWidget(aPropertyPanel->contentWidget()->pageWidget());
+    myInternalWidget->setVisible(false);
+
+    ModuleBase_PageWidget* anInternalPage = new ModuleBase_PageWidget(myInternalWidget);
+
+    QString aXmlRepr = aFOperation->getDescription()->xmlRepresentation();
+    ModuleBase_WidgetFactory aFactory(aXmlRepr.toStdString(), myWorkshop);
+
+    aFactory.createWidget(anInternalPage);
+    QList<ModuleBase_ModelWidget*> aWidgets = aFactory.getModelWidgets();
+
+    foreach (ModuleBase_ModelWidget* aWidget, aWidgets) {
+      bool isStoreValue = !aFOperation->isEditOperation() &&
+                          !aWidget->getDefaultValue().empty() &&
+                          !aWidget->isComputedDefault();
+      aWidget->setFeature(myInternalFeature, isStoreValue);
+      if (!isStoreValue && isFeatureChanged)
+        aWidget->restoreValue();
+    }
+
+    ModuleBase_ModelWidget* aFirstWidget = ModuleBase_IPropertyPanel::findFirstAcceptingValueWidget
+                                                                                        (aWidgets);
+    if (aFirstWidget)
+      myInternalActiveWidget = aFirstWidget;
+  }
+}
+
+void PartSet_SketcherReentrantMgr::deleteInternalFeature()
+{
+  if (myInternalActiveWidget) {
+    ModuleBase_WidgetSelector* aWSelector =
+      dynamic_cast<ModuleBase_WidgetSelector*>(myInternalActiveWidget);
+    if (aWSelector)
+      aWSelector->activateSelectionAndFilters(false);
+    myInternalActiveWidget = 0;
+  }
+  delete myInternalWidget;
+  myInternalWidget = 0;
+
+  QObjectPtrList anObjects;
+  anObjects.append(myInternalFeature);
+  workshop()->deleteFeatures(anObjects);
+  myInternalFeature = FeaturePtr();
+}
+
+void PartSet_SketcherReentrantMgr::resetFlags()
+{
+  if (!myIsFlagsBlocked) {
+    myIsInternalEditOperation = false;
+    updateAcceptAllAction();
+    myRestartingMode = RM_None;
+  }
+}
+
+bool PartSet_SketcherReentrantMgr::copyReetntrantAttributes(const FeaturePtr& theSourceFeature,
+                                                             const FeaturePtr& theNewFeature,
+                                                             const CompositeFeaturePtr& theSketch,
+                                                             const bool isTemporary)
+{
+  bool aChanged = false;
+  if (!theSourceFeature.get() || !theSourceFeature->data().get() ||
+      !theSourceFeature->data()->isValid())
+    return aChanged;
+
+  std::string aFeatureKind = theSourceFeature->getKind();
+  if (aFeatureKind == SketchPlugin_Line::ID()) {
+    // Initialize new line with first point equal to end of previous
+    std::shared_ptr<ModelAPI_Data> aSFData = theSourceFeature->data();
+    std::shared_ptr<GeomDataAPI_Point2D> aSPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+                                                 aSFData->attribute(SketchPlugin_Line::END_ID()));
+    std::shared_ptr<ModelAPI_Data> aNFData = theNewFeature->data();
+    std::shared_ptr<GeomDataAPI_Point2D> aNPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+                                                 aNFData->attribute(SketchPlugin_Line::START_ID()));
+    aNPoint->setValue(aSPoint->x(), aSPoint->y());
+    PartSet_Tools::createConstraint(theSketch, aSPoint, aNPoint);
+
+    aNPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+                                                 aSFData->attribute(SketchPlugin_Line::END_ID()));
+    aNPoint->setValue(aSPoint->x(), aSPoint->y());
+  }
+  else if (aFeatureKind == SketchPlugin_MacroCircle::ID()) {
+    // set circle type
+    std::string aTypeAttributeId = SketchPlugin_MacroCircle::CIRCLE_TYPE();
+    AttributeStringPtr aSourceFeatureTypeAttr = theSourceFeature->data()->string(aTypeAttributeId);
+    AttributeStringPtr aNewFeatureTypeAttr = theNewFeature->data()->string(aTypeAttributeId);
+    aNewFeatureTypeAttr->setValue(aSourceFeatureTypeAttr->value());
+    //ModuleBase_Tools::flushUpdated(theNewFeature);
+    aChanged = true;
+  }
+  else if (aFeatureKind == SketchPlugin_Arc::ID()) {
+    // set arc type
+    std::string aTypeAttributeId = SketchPlugin_Arc::ARC_TYPE();
+    AttributeStringPtr aSourceFeatureTypeAttr = theSourceFeature->data()->string(aTypeAttributeId);
+    AttributeStringPtr aNewFeatureTypeAttr = theNewFeature->data()->string(aTypeAttributeId);
+    aNewFeatureTypeAttr->setValue(aSourceFeatureTypeAttr->value());
+
+    // if the arc is tangent, set coincidence to end point of the previous arc
+    std::string anArcType = aSourceFeatureTypeAttr->value();
+    if (anArcType == SketchPlugin_Arc::ARC_TYPE_TANGENT()) {
+      // get the last point of the previuos arc feature(geom point 2d)
+      std::shared_ptr<ModelAPI_Data> aSData = theSourceFeature->data();
+      std::shared_ptr<GeomDataAPI_Point2D> aSPointAttr =
+                                      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+                                      aSData->attribute(SketchPlugin_Arc::END_ID()));
+      // get point attribute on the current feature
+      AttributeRefAttrPtr aTangentPointAttr = theNewFeature->data()->refattr(
+                                                    SketchPlugin_Arc::TANGENT_POINT_ID());
+      aTangentPointAttr->setAttr(aSPointAttr);
+
+      std::shared_ptr<GeomDataAPI_Point2D> aNPointAttr =
+                                    std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+                                    theNewFeature->data()->attribute(SketchPlugin_Arc::END_ID()));
+      aNPointAttr->setValue(aSPointAttr->x(), aSPointAttr->y());
+
+    }
+    //ModuleBase_Tools::flushUpdated(theNewFeature);
+    aChanged = true;
+  }
+  return aChanged;
+}
+
+bool PartSet_SketcherReentrantMgr::isTangentArc(ModuleBase_Operation* theOperation,
+                                                 const CompositeFeaturePtr& /*theSketch*/) const
+{
+  bool aTangentArc = false;
+  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+                                                                        (theOperation);
+  if (aFOperation && module()->sketchMgr()->isNestedSketchOperation(aFOperation)) {
+    FeaturePtr aFeature = aFOperation->feature();
+    if (aFeature.get() && aFeature->getKind() == SketchPlugin_Arc::ID()) {
+      AttributeStringPtr aTypeAttr = aFeature->data()->string(SketchPlugin_Arc::ARC_TYPE());
+      std::string anArcType = aTypeAttr.get() ? aTypeAttr->value() : "";
+      aTangentArc = anArcType == SketchPlugin_Arc::ARC_TYPE_TANGENT();
+    }
+  }
+  return aTangentArc;
+}
+
+void PartSet_SketcherReentrantMgr::updateAcceptAllAction()
+{
+  CompositeFeaturePtr aSketch = module()->sketchMgr()->activeSketch();
+  if (aSketch.get())
+    workshop()->errorMgr()->updateAcceptAllAction(aSketch);
+}
+
+XGUI_Workshop* PartSet_SketcherReentrantMgr::workshop() const
+{
+  XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myWorkshop);
+  return aConnector->workshop();
+}
+
+PartSet_Module* PartSet_SketcherReentrantMgr::module() const
+{
+  return dynamic_cast<PartSet_Module*>(myWorkshop->module());
+}
diff --git a/src/PartSet/PartSet_SketcherReentrantMgr.h b/src/PartSet/PartSet_SketcherReentrantMgr.h
new file mode 100644 (file)
index 0000000..b430c23
--- /dev/null
@@ -0,0 +1,201 @@
+// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
+
+#ifndef PartSet_SketcherReentrantMgr_H
+#define PartSet_SketcherReentrantMgr_H
+
+#include "PartSet.h"
+
+#include <ModelAPI_Feature.h>
+
+#include <string>
+
+#include <QObject>
+
+class ModuleBase_IWorkshop;
+class ModuleBase_Operation;
+class ModuleBase_ModelWidget;
+class ModuleBase_IViewWindow;
+
+class ModelAPI_CompositeFeature;
+
+class QMouseEvent;
+
+class XGUI_Workshop;
+class PartSet_Module;
+
+/// \ingroup PartSet_SketcherReentrantMgr
+/// It provides reentrant create operations in sketch, that is when all inputs are valid,
+/// automatic validation of the creation and switch the created entity to edit mode
+/// ('internal' edit operation), with the ability to simultaneously create the next entity
+/// of same type (re-entrance of the operation).
+/// OK valids the current edition and exits from the operation (no re-entrance).
+/// Cancel removes (undo) the entity currently edited and
+/// exits from the operation (no re-entrance).
+class PARTSET_EXPORT PartSet_SketcherReentrantMgr : public QObject
+{
+Q_OBJECT
+
+/// Enumeration to specify the restart operation properties.
+enum RestartingMode {
+  RM_None, /// the operation should not be restarted
+  RM_Forbided, /// the operation should not be restarted after there is no active widget
+  RM_LastFeatureUsed, /// the operation is restarted and use
+                      /// the previous feature for own initialization
+  RM_EmptyFeatureUsed /// the operation is restarted and does not use the previous feature
+};
+
+public:
+  /// Constructor
+  /// \param theWorkshop a workshop instance
+  PartSet_SketcherReentrantMgr(ModuleBase_IWorkshop* theWorkshop);
+  virtual ~PartSet_SketcherReentrantMgr();
+
+public:
+  /// Returns a first widget of the current opeation if the internal edit operation is active
+  /// or return null. If the current widget of the operation is a viewer selector, it returns null.
+  ModuleBase_ModelWidget* internalActiveWidget() const;
+
+  /// Return true if the current edit operation is an internal
+  bool isInternalEditActive() const;
+
+  /// Stop internal edit if the operation feature is invalid
+  void updateInternalEditActiveState();
+
+  /// if the internal flags allow it and the manager is active, it starts an internal edit operation
+  /// for the created operation.
+  /// \param thePreviousAttributeID an index of the previous active attribute
+  //bool restartOperation(const std::string& thePreviousAttributeID);
+  bool processEnter(const std::string& thePreviousAttributeID);
+
+  /// Resets the internal flags
+  /// \param theOperation a started operation
+  void operationStarted(ModuleBase_Operation* theOperation);
+
+  /// Resets the internal flags
+  /// \param theOperation a started operation
+  /// \return state whether the internal edit operation was active
+  bool operationCommitted(ModuleBase_Operation* theOperation);
+
+  /// Resets the internal flags
+  /// \param theOperation a started operation
+  void operationAborted(ModuleBase_Operation* theOperation);
+
+  /// Return true if the manager processes the mouse move event
+  /// It happens if the current operation is an internal edit operation and the first
+  /// control can be filled by the mouse move event. The operation is restarted.
+  /// \return true if operation is committed.
+  bool processMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent);
+
+  /// Return true if the manager processes the mouse press event
+  /// \return true if the current operation is an internal edit operation.
+  bool processMousePressed(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent);
+
+  /// Return true if the manager processes the mouse enter event
+  /// It happens if the current operation is an internal edit operation.
+  /// The operation is restarted. If the first widget of the started operation is
+  /// the point 2d, it processes this mouse event
+  /// \return true if operation is committed.
+  bool processMouseReleased(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent);
+
+  /// It is called by the current operation filling with the preselection.
+  /// Returns false if the reentrant mode of the operation is not empty.
+  bool canBeCommittedByPreselection();
+
+  /// returns true if an internal edit operation is started
+  /// \return boolean value
+  bool isInternalEditStarted() const;
+
+private slots:
+  /// SLOT, that is called by a widget activating in the property panel
+  /// If the 'internal' edit operation is started, it activates the first widget selection
+  void onWidgetActivated();
+
+  /// SLOT, that is called by no more widget signal emitted by property panel
+  /// Start an internal edit operation or, if the internal flag is forbided, commits
+  /// the current operation
+  /// \param thePreviousAttributeID an index of the previous active attribute
+  void onNoMoreWidgets(const std::string& thePreviousAttributeID);
+
+  /// Processing of vertex selected. Set an internal reentrant flag to forbiddent state if
+  /// the current feature is a line and there are not obligate widgets anymore
+  void onVertexSelected();
+
+  /// Listens to the signal about the modification of the values
+  /// have been done in the property panel. If the manager has active edit operation and
+  /// the active widget does not process the modification of value, the manager will
+  /// restart current operation and fill a new feature attribute by the value of current
+  /// widget
+  void onAfterValuesChangedInPropertyPanel();
+
+  /// Deactivates selection and filters of the first operation widget if it is an internal
+  /// 'edit' operation
+  void onBeforeStopped();
+
+private:
+  /// Returns true if the current operation is a sketch or a nested sketch operation
+  bool isActiveMgr() const;
+
+  /// Sets the focus to the last control of the property panel and activates selection
+  /// of the first widget to can select first value of the next create operation
+  /// \param thePreviousAttributeID an index of the previous attribute to set focus to this widget
+  /// \return true if it is started
+  bool startInternalEdit(const std::string& thePreviousAttributeID);
+
+  /// Disconnects this manager from operation signals, deactivate selection of the first control
+  /// in the viewer.
+  void beforeStopInternalEdit();
+
+  /// Commits the current operation and launches a new with the commited operation feature index
+  void restartOperation();
+
+  /// Creates an internal feature and controls to process it
+  void createInternalFeature();
+
+  /// A pair method for an internal creation to remove it and clear all created controls
+  void deleteInternalFeature();
+
+  /// Breaks sequense of automatically resterted operations
+  void resetFlags();
+
+  /// Copy some feature specific attributes from the source to a new feature
+  /// This is type for Circle and Arc features
+  /// \param theSourceFeature a source feature
+  /// \param theNewFeature a new feature
+  /// \param theSketch an active sketch
+  /// \param isTemporary is used to do not create additional features(e.g. coicidence for line)
+  /// \return true is something is copied
+  static bool copyReetntrantAttributes(const FeaturePtr& theSourceFeature,
+                                      const FeaturePtr& theNewFeature,
+                                      const std::shared_ptr<ModelAPI_CompositeFeature>& theSketch,
+                                      const bool isTemporary = false);
+
+  /// Checks whethe the feature of the given operation has kind an arc and the arc type is tangent
+  bool isTangentArc(ModuleBase_Operation* theOperation,
+                    const std::shared_ptr<ModelAPI_CompositeFeature>& /*theSketch*/) const;
+
+  /// Accept All action is enabled if an internal edit is started.
+  /// It updates the state of the button
+  void updateAcceptAllAction();
+
+  /// Returns the workshop
+  XGUI_Workshop* workshop() const;
+
+  /// Returns the workshop module
+  PartSet_Module* module() const;
+
+private:
+  ModuleBase_IWorkshop* myWorkshop; /// the workshop
+
+  RestartingMode myRestartingMode;  /// automatical restarting mode flag
+  bool myIsFlagsBlocked; /// true when reset of flags should not be perfromed
+  bool myIsInternalEditOperation; /// true when the 'internal' edit is started
+  bool myIsValueChangedBlocked; /// blocked flag to avoid circling by value changed
+
+  FeaturePtr myPreviousFeature; /// feature of the previous operation, which is restarted
+  FeaturePtr myInternalFeature;
+  QWidget* myInternalWidget;
+  ModuleBase_ModelWidget* myInternalActiveWidget;
+  std::string myNoMoreWidgetsAttribute;
+};
+
+#endif
diff --git a/src/PartSet/PartSet_SketcherReetntrantMgr.cpp b/src/PartSet/PartSet_SketcherReetntrantMgr.cpp
deleted file mode 100755 (executable)
index 36ae785..0000000
+++ /dev/null
@@ -1,677 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-#include "PartSet_SketcherReetntrantMgr.h"
-#include "PartSet_Module.h"
-#include "PartSet_SketcherMgr.h"
-#include "PartSet_WidgetPoint2d.h"
-
-#include "ModelAPI_Session.h"
-#include "ModelAPI_AttributeString.h"
-#include "ModelAPI_AttributeRefAttr.h"
-
-#include "GeomDataAPI_Point2D.h"
-
-#include <ModuleBase_IPropertyPanel.h>
-#include <ModuleBase_OperationFeature.h>
-#include <ModuleBase_ModelWidget.h>
-#include <ModuleBase_ViewerPrs.h>
-#include <ModuleBase_WidgetSelector.h>
-#include <ModuleBase_PageWidget.h>
-#include <ModuleBase_PageBase.h>
-#include <ModuleBase_WidgetFactory.h>
-#include <ModuleBase_OperationDescription.h>
-#include "ModuleBase_ToolBox.h"
-#include "ModuleBase_ISelection.h"
-
-#include <SketchPlugin_Feature.h>
-#include <SketchPlugin_Line.h>
-#include <SketchPlugin_Arc.h>
-#include <SketchPlugin_MacroCircle.h>
-#include <SketchPlugin_Point.h>
-
-#include <XGUI_Workshop.h>
-#include <XGUI_ModuleConnector.h>
-#include <XGUI_OperationMgr.h>
-#include <XGUI_PropertyPanel.h>
-#include <XGUI_ErrorMgr.h>
-#include <XGUI_SelectionMgr.h>
-
-#include <QToolButton>
-
-PartSet_SketcherReetntrantMgr::PartSet_SketcherReetntrantMgr(ModuleBase_IWorkshop* theWorkshop)
-: QObject(theWorkshop),
-  myWorkshop(theWorkshop),
-  myRestartingMode(RM_None),
-  myIsFlagsBlocked(false),
-  myIsInternalEditOperation(false),
-  myNoMoreWidgetsAttribute("")
-{
-}
-
-PartSet_SketcherReetntrantMgr::~PartSet_SketcherReetntrantMgr()
-{
-}
-
-ModuleBase_ModelWidget* PartSet_SketcherReetntrantMgr::internalActiveWidget() const
-{
-  ModuleBase_ModelWidget* aWidget = 0;
-  if (!isActiveMgr())
-    return aWidget;
-
-  ModuleBase_Operation* anOperation = myWorkshop->currentOperation();
-  if (anOperation) {
-    ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel();
-    if (aPanel) { // check for case when the operation is started but property panel is not filled
-      ModuleBase_ModelWidget* anActiveWidget = aPanel->activeWidget();
-      if (myIsInternalEditOperation && (!anActiveWidget || !anActiveWidget->isViewerSelector()))
-        aWidget = myInternalActiveWidget;
-    }
-  }
-  return aWidget;
-}
-
-bool PartSet_SketcherReetntrantMgr::isInternalEditActive() const
-{
-  return myIsInternalEditOperation;
-}
-
-void PartSet_SketcherReetntrantMgr::updateInternalEditActiveState()
-{
-  if  (myIsInternalEditOperation) {
-    ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
-                                                         (myWorkshop->currentOperation());
-    if (aFOperation) {
-      FeaturePtr aFeature = aFOperation->feature();
-      QString anError = myWorkshop->module()->getFeatureError(aFeature);
-      // stop started internal edit operation as soon as the operation becomes invalid
-      // it is especially important for the sketch tangent arc feature
-      if (!anError.isEmpty()) {
-        aFOperation->setEditOperation(false);
-        //workshop()->operationMgr()->updateApplyOfOperations();
-        myIsInternalEditOperation = false;
-        updateAcceptAllAction();
-      }
-    }
-  }
-}
-
-bool PartSet_SketcherReetntrantMgr::operationCommitted(ModuleBase_Operation* theOperation)
-{
-  bool aProcessed = false;
-  if (!isActiveMgr())
-    return aProcessed;
-
-  aProcessed = myIsInternalEditOperation;
-  resetFlags();
-
-  return aProcessed;
-}
-
-void PartSet_SketcherReetntrantMgr::operationStarted(ModuleBase_Operation* theOperation)
-{
-  if (!isActiveMgr())
-    return;
-
-  if (myPreviousFeature.get() && myRestartingMode == RM_LastFeatureUsed) {
-    ModuleBase_OperationFeature* aCurrentOperation = dynamic_cast<ModuleBase_OperationFeature*>(
-                                                                myWorkshop->currentOperation());
-    CompositeFeaturePtr aSketch = module()->sketchMgr()->activeSketch();
-    copyReetntrantAttributes(myPreviousFeature, aCurrentOperation->feature(), aSketch);
-  }
-  resetFlags();
-}
-
-void PartSet_SketcherReetntrantMgr::operationAborted(ModuleBase_Operation* theOperation)
-{
-  if (!isActiveMgr())
-    return;
-
-  resetFlags();
-}
-
-bool PartSet_SketcherReetntrantMgr::processMouseMoved(ModuleBase_IViewWindow* theWnd,
-                                                      QMouseEvent* theEvent)
-{
-  bool aProcessed = false;
-  if (!isActiveMgr())
-    return aProcessed;
-
-  if  (myIsInternalEditOperation) {
-    ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
-                                                         (myWorkshop->currentOperation());
-    FeaturePtr aLastFeature = myRestartingMode == RM_LastFeatureUsed ? aFOperation->feature()
-                                                                     : FeaturePtr();
-    if (aLastFeature) {
-      ModuleBase_ModelWidget* anActiveWidget = module()->activeWidget();
-      ModuleBase_IPropertyPanel* aPanel = myWorkshop->currentOperation()->propertyPanel();
-
-      FeaturePtr aCurrentFeature = aFOperation->feature();
-      bool isLineFeature = false, isArcFeature = false;
-      std::string anAttributeOnStart;
-      if (aCurrentFeature->getKind() == SketchPlugin_Line::ID()) {
-        anAttributeOnStart = SketchPlugin_Line::START_ID();
-        isLineFeature = anActiveWidget->attributeID() == anAttributeOnStart;
-      }
-      else if (isTangentArc(aFOperation, module()->sketchMgr()->activeSketch())) {
-        anAttributeOnStart = SketchPlugin_Arc::TANGENT_POINT_ID();
-        isArcFeature = anActiveWidget->attributeID() == anAttributeOnStart;
-      }
-      bool aCanBeActivatedByMove = isLineFeature || isArcFeature;
-      if (aCanBeActivatedByMove) {
-        /// before restarting of operation we need to clear selection, as it may take part in
-        /// new feature creation, e.g. tangent arc. But it is not necessary as it was processed
-        /// by mouse release when the operation was restarted.
-        workshop()->selector()->clearSelection();
-
-        myPreviousFeature = aFOperation->feature();
-        restartOperation();
-        myPreviousFeature = FeaturePtr();
-
-        anActiveWidget = module()->activeWidget();
-        aCurrentFeature = anActiveWidget->feature();
-        aProcessed = true;
-        if (anActiveWidget->attributeID() == anAttributeOnStart) {
-          // it was not deactivated by preselection processing
-          aPanel->activateNextWidget(anActiveWidget);
-        }
-      } else {
-        // processing mouse move in active widget of restarted operation
-        ModuleBase_ModelWidget* anActiveWidget = module()->activeWidget();
-        PartSet_MouseProcessor* aProcessor = dynamic_cast<PartSet_MouseProcessor*>(anActiveWidget);
-        if (aProcessor)
-          aProcessor->mouseMoved(theWnd, theEvent);
-      }
-    }
-  }
-  return aProcessed;
-}
-
-bool PartSet_SketcherReetntrantMgr::processMousePressed(ModuleBase_IViewWindow* /* theWnd*/,
-                                                        QMouseEvent* /* theEvent*/)
-{
-  return isActiveMgr() && myIsInternalEditOperation;
-}
-
-bool PartSet_SketcherReetntrantMgr::processMouseReleased(ModuleBase_IViewWindow* theWnd,
-                                                         QMouseEvent* theEvent)
-{
-  bool aProcessed = false;
-  if (!isActiveMgr())
-    return aProcessed;
-
-  if (myIsInternalEditOperation) {
-    ModuleBase_Operation* anOperation = myWorkshop->currentOperation();
-    ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel();
-
-    ModuleBase_ModelWidget* anActiveWidget = aPanel->activeWidget();
-    if (!anActiveWidget || !anActiveWidget->isViewerSelector()) {
-
-      // block of viewer update
-      // we need to block update content of the viewer because of Sketch Point feature
-      // in activate() the value of the point is initialized and it can be displayed
-      // but the default value is [0, 0]. So, we block update viewer contentent until
-      // onMouseRelease happens, which correct the point position
-      ModuleBase_Tools::blockUpdateViewer(true);
-
-      ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
-                                                           (myWorkshop->currentOperation());
-      myPreviousFeature = aFOperation->feature();
-
-      /// selection should be obtained from workshop before ask if the operation can be started as
-      /// the canStartOperation method performs commit/abort of previous operation.
-      /// Sometimes commit/abort
-      /// may cause selection clear(Sketch operation) as a result
-      /// it will be lost and is not used for preselection.
-      ModuleBase_ISelection* aSelection = myWorkshop->selection();
-      QList<ModuleBase_ViewerPrsPtr> aPreSelected =
-        aSelection->getSelected(ModuleBase_ISelection::AllControls);
-
-      restartOperation();
-      myPreviousFeature = FeaturePtr();
-      aProcessed = true;
-
-      // fill the first widget by the mouse event point
-      // if the active widget is not the first, it means that the restarted operation is filled by
-      // the current preselection.
-      PartSet_MouseProcessor* aMouseProcessor = dynamic_cast<PartSet_MouseProcessor*>(
-                                                                       module()->activeWidget());
-      //PartSet_WidgetPoint2D* aPoint2DWdg =
-      //  dynamic_cast<PartSet_WidgetPoint2D*>(module()->activeWidget());
-      PartSet_MouseProcessor* aFirstWidget = dynamic_cast<PartSet_MouseProcessor*>(
-                                                        aPanel->findFirstAcceptingValueWidget());
-      //if (aPoint2DWdg && aPoint2DWdg == aFirstWidget) {
-      if (aMouseProcessor && aMouseProcessor == aFirstWidget) {
-        std::shared_ptr<ModuleBase_ViewerPrs> aSelectedPrs;
-        if (!aPreSelected.empty())
-          aSelectedPrs = aPreSelected.front();
-        aMouseProcessor->setPreSelection(aSelectedPrs, theWnd, theEvent);
-        //aPoint2DWdg->mouseReleased(theWnd, theEvent);
-        //if (!aPreSelected.empty())
-        //  aPoint2DWdg->setPreSelection(ModuleBase_ViewerPrsPtr());
-      }
-      // unblock viewer update
-      ModuleBase_Tools::blockUpdateViewer(false);
-    }
-  }
-
-  return aProcessed;
-}
-
-void PartSet_SketcherReetntrantMgr::onWidgetActivated()
-{
-  if (!isActiveMgr())
-    return;
-  if (!myIsInternalEditOperation)
-    return;
-
-  PartSet_Module* aModule = module();
-  ModuleBase_ModelWidget* aFirstWidget = aModule->activeWidget();
-  ModuleBase_IPropertyPanel* aPanel = aModule->currentOperation()->propertyPanel();
-  if (aFirstWidget != aPanel->activeWidget()) {
-    ModuleBase_WidgetSelector* aWSelector = dynamic_cast<ModuleBase_WidgetSelector*>(aFirstWidget);
-    if (aWSelector)
-      aWSelector->activateSelectionAndFilters(true);
-  }
-}
-
-void PartSet_SketcherReetntrantMgr::onNoMoreWidgets(const std::string& thePreviousAttributeID)
-{
-  if (!isActiveMgr())
-    return;
-
-  // we should avoid processing of the signal about no more widgets attributes and
-  // do this after the restart operaion is finished if it was called
-  // onNoMoreWidgets depends on myIsFlagsBlocked and fill myNoMoreWidgetsAttribute
-  // if it should be called after restart
-  if (myIsFlagsBlocked) {
-    myNoMoreWidgetsAttribute = thePreviousAttributeID;
-    return;
-  }
-
-  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
-                                                       (myWorkshop->currentOperation());
-  if (!myWorkshop->module()->getFeatureError(aFOperation->feature()).isEmpty())
-    return;
-
-  if (aFOperation && module()->sketchMgr()->isNestedSketchOperation(aFOperation)) {
-    bool isStarted = false;
-    if (!module()->sketchMgr()->sketchSolverError()) {
-      if (myRestartingMode != RM_Forbided) {
-        myRestartingMode = RM_LastFeatureUsed;
-        isStarted = startInternalEdit(thePreviousAttributeID);
-      }
-    }
-    if (!isStarted)
-      aFOperation->commit();
-  }
-}
-
-bool PartSet_SketcherReetntrantMgr::processEnter(const std::string& thePreviousAttributeID)
-{
-  bool isDone = false;
-
-  if (!isActiveMgr())
-    return isDone;
-
-  // empty previous attribute means that the Apply/Ok button has focus and the enter
-  // should not lead to start edition mode of the previous operation
-  if (thePreviousAttributeID.empty())
-    return isDone;
-
-  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
-                                                       (myWorkshop->currentOperation());
-  if (!myWorkshop->module()->getFeatureError(aFOperation->feature()).isEmpty())
-    return isDone;
-
-  bool isSketchSolverError = module()->sketchMgr()->sketchSolverError();
-
-  if (!isSketchSolverError) {
-    myRestartingMode = RM_EmptyFeatureUsed;
-    isDone = startInternalEdit(thePreviousAttributeID);
-  }
-
-  return isDone;
-}
-
-void PartSet_SketcherReetntrantMgr::onVertexSelected()
-{
-  if (!isActiveMgr())
-    return;
-
-  ModuleBase_Operation* anOperation = myWorkshop->currentOperation();
-  std::string anOperationId = anOperation->id().toStdString();
-  if (anOperationId == SketchPlugin_Line::ID() ||
-      isTangentArc(anOperation, module()->sketchMgr()->activeSketch())) {
-    /// If last line finished on vertex the lines creation sequence has to be break
-    ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel();
-    ModuleBase_ModelWidget* anActiveWidget = aPanel->activeWidget();
-    const QList<ModuleBase_ModelWidget*>& aWidgets = aPanel->modelWidgets();
-    QList<ModuleBase_ModelWidget*>::const_iterator anIt = aWidgets.begin(), aLast = aWidgets.end();
-    bool aFoundWidget = false;
-    bool aFoundObligatory = false;
-    for (; anIt != aLast && !aFoundObligatory; anIt++) {
-      if (!aFoundWidget)
-        aFoundWidget = *anIt == anActiveWidget;
-      else
-        aFoundObligatory = (*anIt)->isObligatory();
-    }
-    if (!aFoundObligatory)
-      myRestartingMode = RM_Forbided;
-  }
-}
-
-void PartSet_SketcherReetntrantMgr::onBeforeStopped()
-{
-  if (!isActiveMgr() || !myIsInternalEditOperation)
-    return;
-
-  beforeStopInternalEdit();
-}
-
-bool PartSet_SketcherReetntrantMgr::canBeCommittedByPreselection()
-{
-  return !isActiveMgr() || myRestartingMode == RM_None;
-}
-
-bool PartSet_SketcherReetntrantMgr::isInternalEditStarted() const
-{
-  return myIsInternalEditOperation;
-}
-
-bool PartSet_SketcherReetntrantMgr::isActiveMgr() const
-{
-  ModuleBase_Operation* aCurrentOperation = myWorkshop->currentOperation();
-
-  bool anActive = PartSet_SketcherMgr::isSketchOperation(aCurrentOperation);
-  if (!anActive) {
-    anActive = module()->sketchMgr()->isNestedSketchOperation(aCurrentOperation);
-    if (anActive) { // the manager is not active when the current operation is a usual Edit
-      ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
-                                                       (myWorkshop->currentOperation());
-      if (aFOperation->isEditOperation())
-        anActive = myIsInternalEditOperation;
-    }
-  }
-  return anActive;
-}
-
-bool PartSet_SketcherReetntrantMgr::startInternalEdit(const std::string& thePreviousAttributeID)
-{
-  bool isDone = false;
-  /// this is workaround for ModuleBase_WidgetEditor, used in SALOME mode. Sometimes key enter
-  /// event comes two times, so we should not start another internal edit operation
-  /// the Apply button becomes disabled becase the second additional internal feature is created
-  if (myIsInternalEditOperation)
-    return true;
-
-  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
-                                                     (myWorkshop->currentOperation());
-
-  if (aFOperation && module()->sketchMgr()->isNestedSketchOperation(aFOperation)) {
-    aFOperation->setEditOperation(true/*, false*/);
-    createInternalFeature();
-
-    myIsInternalEditOperation = true;
-    updateAcceptAllAction();
-
-    isDone = true;
-    connect(aFOperation, SIGNAL(beforeCommitted()), this, SLOT(onBeforeStopped()));
-    connect(aFOperation, SIGNAL(beforeAborted()), this, SLOT(onBeforeStopped()));
-
-    // activate selection filters of the first widget in the viewer
-    onWidgetActivated();
-
-    // activate the last active widget in the Property Panel
-    if (!thePreviousAttributeID.empty()) {
-      ModuleBase_Operation* anEditOperation = module()->currentOperation();
-      if (anEditOperation) {
-        ModuleBase_IPropertyPanel* aPanel = aFOperation->propertyPanel();
-        ModuleBase_ModelWidget* aPreviousAttributeWidget = 0;
-        QList<ModuleBase_ModelWidget*> aWidgets = aPanel->modelWidgets();
-        for (int i = 0, aNb = aWidgets.size(); i < aNb && !aPreviousAttributeWidget; i++) {
-          if (aWidgets[i]->attributeID() == thePreviousAttributeID) {
-          /// workaround for the same attributes used in different stacked widgets(attribute types)
-          if (ModuleBase_ToolBox::isOffToolBoxParent(aWidgets[i]))
-            continue;
-            aPreviousAttributeWidget = aWidgets[i];
-          }
-        }
-        // If the current widget is a selector, do nothing, it processes the mouse press
-        if (aPreviousAttributeWidget) {
-          if (!aPreviousAttributeWidget->isViewerSelector()) {
-            aPreviousAttributeWidget->focusTo();
-            aPreviousAttributeWidget->selectContent();
-          }
-          else {
-            // in case of shape multi selector, the widget does not lose focus by filling
-            // like it is in shape selector. So, if enter is pressed, the multi shape selector
-            // control should be deactivated. The focus is moved to Apply button and there
-            // should not be active control visualized in property panel
-            if (aPreviousAttributeWidget == aPanel->activeWidget()) {
-              aPanel->activateWidget(NULL, false);
-            }
-            // if there is no the next widget to be automatically activated,
-            // the Ok button in property
-            // panel should accept the focus(example is parallel constraint on sketch lines)
-            QToolButton* anOkBtn =
-              dynamic_cast<XGUI_PropertyPanel*>(aPanel)->findButton(PROP_PANEL_OK);
-            if (anOkBtn)
-              anOkBtn->setFocus(Qt::TabFocusReason);
-          }
-        }
-      }
-    }
-  }
-  if (isDone)
-    module()->sketchMgr()->clearClickedFlags();
-
-  return isDone;
-}
-
-void PartSet_SketcherReetntrantMgr::beforeStopInternalEdit()
-{
-  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
-                                                      (myWorkshop->currentOperation());
-  if (aFOperation) {
-    disconnect(aFOperation, SIGNAL(beforeCommitted()), this, SLOT(onBeforeStopped()));
-    disconnect(aFOperation, SIGNAL(beforeAborted()), this, SLOT(onBeforeStopped()));
-  }
-
-  deleteInternalFeature();
-}
-
-void PartSet_SketcherReetntrantMgr::restartOperation()
-{
-  if (myIsInternalEditOperation) {
-    ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>(
-                                                                  myWorkshop->currentOperation());
-    if (aFOperation) {
-      myNoMoreWidgetsAttribute = "";
-      myIsFlagsBlocked = true;
-      module()->launchOperation(aFOperation->id());
-      myIsFlagsBlocked = false;
-      resetFlags();
-      // we should avoid processing of the signal about no more widgets attributes and
-      // do this after the restart operaion is finished if it was called
-      // onNoMoreWidgets depends on myIsFlagsBlocked and fill myNoMoreWidgetsAttribute
-      // if it should be called after restart
-      if (!myNoMoreWidgetsAttribute.empty()) {
-        onNoMoreWidgets(myNoMoreWidgetsAttribute);
-        myNoMoreWidgetsAttribute = "";
-      }
-    }
-  }
-}
-
-void PartSet_SketcherReetntrantMgr::createInternalFeature()
-{
-  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
-                                                     (myWorkshop->currentOperation());
-
-  if (aFOperation && module()->sketchMgr()->isNestedSketchOperation(aFOperation)) {
-    FeaturePtr anOperationFeature = aFOperation->feature();
-
-    CompositeFeaturePtr aSketch = module()->sketchMgr()->activeSketch();
-    myInternalFeature = aSketch->addFeature(anOperationFeature->getKind());
-
-    bool isFeatureChanged = copyReetntrantAttributes(anOperationFeature, myInternalFeature,
-                                                     aSketch, false);
-    XGUI_PropertyPanel* aPropertyPanel = dynamic_cast<XGUI_PropertyPanel*>
-                                                  (aFOperation->propertyPanel());
-
-    myInternalWidget = new QWidget(aPropertyPanel->contentWidget()->pageWidget());
-    myInternalWidget->setVisible(false);
-
-    ModuleBase_PageWidget* anInternalPage = new ModuleBase_PageWidget(myInternalWidget);
-
-    QString aXmlRepr = aFOperation->getDescription()->xmlRepresentation();
-    ModuleBase_WidgetFactory aFactory(aXmlRepr.toStdString(), myWorkshop);
-
-    aFactory.createWidget(anInternalPage);
-    QList<ModuleBase_ModelWidget*> aWidgets = aFactory.getModelWidgets();
-
-    foreach (ModuleBase_ModelWidget* aWidget, aWidgets) {
-      bool isStoreValue = !aFOperation->isEditOperation() &&
-                          !aWidget->getDefaultValue().empty() &&
-                          !aWidget->isComputedDefault();
-      aWidget->setFeature(myInternalFeature, isStoreValue);
-      if (!isStoreValue && isFeatureChanged)
-        aWidget->restoreValue();
-    }
-
-    ModuleBase_ModelWidget* aFirstWidget = ModuleBase_IPropertyPanel::findFirstAcceptingValueWidget
-                                                                                        (aWidgets);
-    if (aFirstWidget)
-      myInternalActiveWidget = aFirstWidget;
-  }
-}
-
-void PartSet_SketcherReetntrantMgr::deleteInternalFeature()
-{
-  if (myInternalActiveWidget) {
-    ModuleBase_WidgetSelector* aWSelector =
-      dynamic_cast<ModuleBase_WidgetSelector*>(myInternalActiveWidget);
-    if (aWSelector)
-      aWSelector->activateSelectionAndFilters(false);
-    myInternalActiveWidget = 0;
-  }
-  delete myInternalWidget;
-  myInternalWidget = 0;
-
-  QObjectPtrList anObjects;
-  anObjects.append(myInternalFeature);
-  workshop()->deleteFeatures(anObjects);
-  myInternalFeature = FeaturePtr();
-}
-
-void PartSet_SketcherReetntrantMgr::resetFlags()
-{
-  if (!myIsFlagsBlocked) {
-    myIsInternalEditOperation = false;
-    updateAcceptAllAction();
-    myRestartingMode = RM_None;
-  }
-}
-
-bool PartSet_SketcherReetntrantMgr::copyReetntrantAttributes(const FeaturePtr& theSourceFeature,
-                                                             const FeaturePtr& theNewFeature,
-                                                             const CompositeFeaturePtr& theSketch,
-                                                             const bool isTemporary)
-{
-  bool aChanged = false;
-  if (!theSourceFeature.get() || !theSourceFeature->data().get() ||
-      !theSourceFeature->data()->isValid())
-    return aChanged;
-
-  std::string aFeatureKind = theSourceFeature->getKind();
-  if (aFeatureKind == SketchPlugin_Line::ID()) {
-    // Initialize new line with first point equal to end of previous
-    std::shared_ptr<ModelAPI_Data> aSFData = theSourceFeature->data();
-    std::shared_ptr<GeomDataAPI_Point2D> aSPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-                                                 aSFData->attribute(SketchPlugin_Line::END_ID()));
-    std::shared_ptr<ModelAPI_Data> aNFData = theNewFeature->data();
-    std::shared_ptr<GeomDataAPI_Point2D> aNPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-                                                 aNFData->attribute(SketchPlugin_Line::START_ID()));
-    aNPoint->setValue(aSPoint->x(), aSPoint->y());
-    PartSet_Tools::createConstraint(theSketch, aSPoint, aNPoint);
-
-    aNPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-                                                 aSFData->attribute(SketchPlugin_Line::END_ID()));
-    aNPoint->setValue(aSPoint->x(), aSPoint->y());
-  }
-  else if (aFeatureKind == SketchPlugin_MacroCircle::ID()) {
-    // set circle type
-    std::string aTypeAttributeId = SketchPlugin_MacroCircle::CIRCLE_TYPE();
-    AttributeStringPtr aSourceFeatureTypeAttr = theSourceFeature->data()->string(aTypeAttributeId);
-    AttributeStringPtr aNewFeatureTypeAttr = theNewFeature->data()->string(aTypeAttributeId);
-    aNewFeatureTypeAttr->setValue(aSourceFeatureTypeAttr->value());
-    //ModuleBase_Tools::flushUpdated(theNewFeature);
-    aChanged = true;
-  }
-  else if (aFeatureKind == SketchPlugin_Arc::ID()) {
-    // set arc type
-    std::string aTypeAttributeId = SketchPlugin_Arc::ARC_TYPE();
-    AttributeStringPtr aSourceFeatureTypeAttr = theSourceFeature->data()->string(aTypeAttributeId);
-    AttributeStringPtr aNewFeatureTypeAttr = theNewFeature->data()->string(aTypeAttributeId);
-    aNewFeatureTypeAttr->setValue(aSourceFeatureTypeAttr->value());
-
-    // if the arc is tangent, set coincidence to end point of the previous arc
-    std::string anArcType = aSourceFeatureTypeAttr->value();
-    if (anArcType == SketchPlugin_Arc::ARC_TYPE_TANGENT()) {
-      // get the last point of the previuos arc feature(geom point 2d)
-      std::shared_ptr<ModelAPI_Data> aSData = theSourceFeature->data();
-      std::shared_ptr<GeomDataAPI_Point2D> aSPointAttr =
-                                      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-                                      aSData->attribute(SketchPlugin_Arc::END_ID()));
-      // get point attribute on the current feature
-      AttributeRefAttrPtr aTangentPointAttr = theNewFeature->data()->refattr(
-                                                    SketchPlugin_Arc::TANGENT_POINT_ID());
-      aTangentPointAttr->setAttr(aSPointAttr);
-
-      std::shared_ptr<GeomDataAPI_Point2D> aNPointAttr =
-                                    std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
-                                    theNewFeature->data()->attribute(SketchPlugin_Arc::END_ID()));
-      aNPointAttr->setValue(aSPointAttr->x(), aSPointAttr->y());
-
-    }
-    //ModuleBase_Tools::flushUpdated(theNewFeature);
-    aChanged = true;
-  }
-  return aChanged;
-}
-
-bool PartSet_SketcherReetntrantMgr::isTangentArc(ModuleBase_Operation* theOperation,
-                                                 const CompositeFeaturePtr& /*theSketch*/) const
-{
-  bool aTangentArc = false;
-  ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
-                                                                        (theOperation);
-  if (aFOperation && module()->sketchMgr()->isNestedSketchOperation(aFOperation)) {
-    FeaturePtr aFeature = aFOperation->feature();
-    if (aFeature.get() && aFeature->getKind() == SketchPlugin_Arc::ID()) {
-      AttributeStringPtr aTypeAttr = aFeature->data()->string(SketchPlugin_Arc::ARC_TYPE());
-      std::string anArcType = aTypeAttr.get() ? aTypeAttr->value() : "";
-      aTangentArc = anArcType == SketchPlugin_Arc::ARC_TYPE_TANGENT();
-    }
-  }
-  return aTangentArc;
-}
-
-void PartSet_SketcherReetntrantMgr::updateAcceptAllAction()
-{
-  CompositeFeaturePtr aSketch = module()->sketchMgr()->activeSketch();
-  if (aSketch.get())
-    workshop()->errorMgr()->updateAcceptAllAction(aSketch);
-}
-
-XGUI_Workshop* PartSet_SketcherReetntrantMgr::workshop() const
-{
-  XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(myWorkshop);
-  return aConnector->workshop();
-}
-
-PartSet_Module* PartSet_SketcherReetntrantMgr::module() const
-{
-  return dynamic_cast<PartSet_Module*>(myWorkshop->module());
-}
-
diff --git a/src/PartSet/PartSet_SketcherReetntrantMgr.h b/src/PartSet/PartSet_SketcherReetntrantMgr.h
deleted file mode 100755 (executable)
index 5ae8a76..0000000
+++ /dev/null
@@ -1,193 +0,0 @@
-// Copyright (C) 2014-20xx CEA/DEN, EDF R&D
-
-#ifndef PartSet_SketcherReetntrantMgr_H
-#define PartSet_SketcherReetntrantMgr_H
-
-#include "PartSet.h"
-
-#include <ModelAPI_Feature.h>
-
-#include <string>
-
-#include <QObject>
-
-class ModuleBase_IWorkshop;
-class ModuleBase_Operation;
-class ModuleBase_ModelWidget;
-class ModuleBase_IViewWindow;
-
-class ModelAPI_CompositeFeature;
-
-class QMouseEvent;
-
-class XGUI_Workshop;
-class PartSet_Module;
-
-/// \ingroup PartSet_SketcherReetntrantMgr
-/// It provides reentrant create operations in sketch, that is when all inputs are valid,
-/// automatic validation of the creation and switch the created entity to edit mode
-/// ('internal' edit operation), with the ability to simultaneously create the next entity
-/// of same type (re-entrance of the operation).
-/// OK valids the current edition and exits from the operation (no re-entrance).
-/// Cancel removes (undo) the entity currently edited and
-/// exits from the operation (no re-entrance).
-class PARTSET_EXPORT PartSet_SketcherReetntrantMgr : public QObject
-{
-Q_OBJECT
-
-/// Enumeration to specify the restart operation properties.
-enum RestartingMode {
-  RM_None, /// the operation should not be restarted
-  RM_Forbided, /// the operation should not be restarted after there is no active widget
-  RM_LastFeatureUsed, /// the operation is restarted and use
-                      /// the previous feature for own initialization
-  RM_EmptyFeatureUsed /// the operation is restarted and does not use the previous feature
-};
-
-public:
-  /// Constructor
-  /// \param theWorkshop a workshop instance
-  PartSet_SketcherReetntrantMgr(ModuleBase_IWorkshop* theWorkshop);
-  virtual ~PartSet_SketcherReetntrantMgr();
-
-public:
-  /// Returns a first widget of the current opeation if the internal edit operation is active
-  /// or return null. If the current widget of the operation is a viewer selector, it returns null.
-  ModuleBase_ModelWidget* internalActiveWidget() const;
-
-  /// Return true if the current edit operation is an internal
-  bool isInternalEditActive() const;
-
-  /// Stop internal edit if the operation feature is invalid
-  void updateInternalEditActiveState();
-
-  /// if the internal flags allow it and the manager is active, it starts an internal edit operation
-  /// for the created operation.
-  /// \param thePreviousAttributeID an index of the previous active attribute
-  //bool restartOperation(const std::string& thePreviousAttributeID);
-  bool processEnter(const std::string& thePreviousAttributeID);
-
-  /// Resets the internal flags
-  /// \param theOperation a started operation
-  void operationStarted(ModuleBase_Operation* theOperation);
-
-  /// Resets the internal flags
-  /// \param theOperation a started operation
-  /// \return state whether the internal edit operation was active
-  bool operationCommitted(ModuleBase_Operation* theOperation);
-
-  /// Resets the internal flags
-  /// \param theOperation a started operation
-  void operationAborted(ModuleBase_Operation* theOperation);
-
-  /// Return true if the manager processes the mouse move event
-  /// It happens if the current operation is an internal edit operation and the first
-  /// control can be filled by the mouse move event. The operation is restarted.
-  /// \return true if operation is committed.
-  bool processMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent);
-
-  /// Return true if the manager processes the mouse press event
-  /// \return true if the current operation is an internal edit operation.
-  bool processMousePressed(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent);
-
-  /// Return true if the manager processes the mouse enter event
-  /// It happens if the current operation is an internal edit operation.
-  /// The operation is restarted. If the first widget of the started operation is
-  /// the point 2d, it processes this mouse event
-  /// \return true if operation is committed.
-  bool processMouseReleased(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent);
-
-  /// It is called by the current operation filling with the preselection.
-  /// Returns false if the reentrant mode of the operation is not empty.
-  bool canBeCommittedByPreselection();
-
-  /// returns true if an internal edit operation is started
-  /// \return boolean value
-  bool isInternalEditStarted() const;
-
-private slots:
-  /// SLOT, that is called by a widget activating in the property panel
-  /// If the 'internal' edit operation is started, it activates the first widget selection
-  void onWidgetActivated();
-
-  /// SLOT, that is called by no more widget signal emitted by property panel
-  /// Start an internal edit operation or, if the internal flag is forbided, commits
-  /// the current operation
-  /// \param thePreviousAttributeID an index of the previous active attribute
-  void onNoMoreWidgets(const std::string& thePreviousAttributeID);
-
-  /// Processing of vertex selected. Set an internal reentrant flag to forbiddent state if
-  /// the current feature is a line and there are not obligate widgets anymore
-  void onVertexSelected();
-
-  /// Deactivates selection and filters of the first operation widget if it is an internal
-  /// 'edit' operation
-  void onBeforeStopped();
-
-private:
-  /// Returns true if the current operation is a sketch or a nested sketch operation
-  bool isActiveMgr() const;
-
-  /// Sets the focus to the last control of the property panel and activates selection
-  /// of the first widget to can select first value of the next create operation
-  /// \param thePreviousAttributeID an index of the previous attribute to set focus to this widget
-  /// \return true if it is started
-  bool startInternalEdit(const std::string& thePreviousAttributeID);
-
-  /// Disconnects this manager from operation signals, deactivate selection of the first control
-  /// in the viewer.
-  void beforeStopInternalEdit();
-
-  /// Commits the current operation and launches a new with the commited operation feature index
-  void restartOperation();
-
-  /// Creates an internal feature and controls to process it
-  void createInternalFeature();
-
-  /// A pair method for an internal creation to remove it and clear all created controls
-  void deleteInternalFeature();
-
-  /// Breaks sequense of automatically resterted operations
-  void resetFlags();
-
-  /// Copy some feature specific attributes from the source to a new feature
-  /// This is type for Circle and Arc features
-  /// \param theSourceFeature a source feature
-  /// \param theNewFeature a new feature
-  /// \param theSketch an active sketch
-  /// \param isTemporary is used to do not create additional features(e.g. coicidence for line)
-  /// \return true is something is copied
-  static bool copyReetntrantAttributes(const FeaturePtr& theSourceFeature,
-                                      const FeaturePtr& theNewFeature,
-                                      const std::shared_ptr<ModelAPI_CompositeFeature>& theSketch,
-                                      const bool isTemporary = false);
-
-  /// Checks whethe the feature of the given operation has kind an arc and the arc type is tangent
-  bool isTangentArc(ModuleBase_Operation* theOperation,
-                    const std::shared_ptr<ModelAPI_CompositeFeature>& /*theSketch*/) const;
-
-  /// Accept All action is enabled if an internal edit is started.
-  /// It updates the state of the button
-  void updateAcceptAllAction();
-
-  /// Returns the workshop
-  XGUI_Workshop* workshop() const;
-
-  /// Returns the workshop module
-  PartSet_Module* module() const;
-
-private:
-  ModuleBase_IWorkshop* myWorkshop; /// the workshop
-
-  RestartingMode myRestartingMode;  /// automatical restarting mode flag
-  bool myIsFlagsBlocked; /// true when reset of flags should not be perfromed
-  bool myIsInternalEditOperation; /// true when the 'internal' edit is started
-
-  FeaturePtr myPreviousFeature; /// feature of the previous operation, which is restarted
-  FeaturePtr myInternalFeature;
-  QWidget* myInternalWidget;
-  ModuleBase_ModelWidget* myInternalActiveWidget;
-  std::string myNoMoreWidgetsAttribute;
-};
-
-#endif
index cb727289ee6c9dd6eb9ef888354566e4c89037d9..cf095fe0ccd90aeb9103300154314d28f0453209 100644 (file)
@@ -7,7 +7,7 @@
 #include "PartSet_WidgetPoint2d.h"
 #include <PartSet_Tools.h>
 #include <PartSet_Module.h>
-#include <PartSet_SketcherReetntrantMgr.h>
+#include <PartSet_SketcherReentrantMgr.h>
 
 #include <XGUI_Tools.h>
 #include <XGUI_Workshop.h>
index fa03e34aee9e0f7d259238b1d77f2c8f89a59546..e2492432ad546b74767f4ff964ede119dd1cdffd 100644 (file)
@@ -76,7 +76,7 @@
                icon="icons/Sketch/circle.png"
                title="Circle"
                tooltip="Create circle">
-        <toolbox id="circle_type">
+        <toolbox id="circle_type" modified_in_edit="false">
           <box id="circle_type_by_center_and_passed_points"
                icon="icons/Sketch/circle_pt_rad_32x32.png"
                title="Center and passed points">