From: nds Date: Thu, 23 Mar 2017 08:33:32 +0000 (+0300) Subject: Issue #2024 - Redesign of circle and arc of circle: fill Reference Attribute X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=b27efa6a0937f73f5b80205fc13dd817844aa116;p=modules%2Fshaper.git Issue #2024 - Redesign of circle and arc of circle: fill Reference Attribute Type of Circle macro feature should be saved by restarting of operation. --- diff --git a/src/Config/Config_Keywords.h b/src/Config/Config_Keywords.h index 6b4a1312f..befdd08e5 100644 --- a/src/Config/Config_Keywords.h +++ b/src/Config/Config_Keywords.h @@ -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; diff --git a/src/ModuleBase/ModuleBase_ModelWidget.cpp b/src/ModuleBase/ModuleBase_ModelWidget.cpp index db9908a41..aa0470f7a 100644 --- a/src/ModuleBase/ModuleBase_ModelWidget.cpp +++ b/src/ModuleBase/ModuleBase_ModelWidget.cpp @@ -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; diff --git a/src/ModuleBase/ModuleBase_ModelWidget.h b/src/ModuleBase/ModuleBase_ModelWidget.h index 25db7bcfc..fcd2ad508 100644 --- a/src/ModuleBase/ModuleBase_ModelWidget.h +++ b/src/ModuleBase/ModuleBase_ModelWidget.h @@ -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 diff --git a/src/ModuleBase/ModuleBase_PagedContainer.cpp b/src/ModuleBase/ModuleBase_PagedContainer.cpp index 42d48907f..8723cbd77 100644 --- a/src/ModuleBase/ModuleBase_PagedContainer.cpp +++ b/src/ModuleBase/ModuleBase_PagedContainer.cpp @@ -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(); } diff --git a/src/PartSet/CMakeLists.txt b/src/PartSet/CMakeLists.txt index bb1035a06..3793d26af 100644 --- a/src/PartSet/CMakeLists.txt +++ b/src/PartSet/CMakeLists.txt @@ -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 diff --git a/src/PartSet/PartSet_Module.cpp b/src/PartSet/PartSet_Module.cpp index 14f18c942..67b4adf85 100755 --- a/src/PartSet/PartSet_Module.cpp +++ b/src/PartSet/PartSet_Module.cpp @@ -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(theWshop); XGUI_Workshop* aWorkshop = aConnector->workshop(); diff --git a/src/PartSet/PartSet_Module.h b/src/PartSet/PartSet_Module.h index ed00ebef5..3c7316458 100755 --- a/src/PartSet/PartSet_Module.h +++ b/src/PartSet/PartSet_Module.h @@ -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; diff --git a/src/PartSet/PartSet_SketcherMgr.cpp b/src/PartSet/PartSet_SketcherMgr.cpp index 5497da37a..1fd62e95d 100755 --- a/src/PartSet/PartSet_SketcherMgr.cpp +++ b/src/PartSet/PartSet_SketcherMgr.cpp @@ -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(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 index 000000000..45547cb74 --- /dev/null +++ b/src/PartSet/PartSet_SketcherReentrantMgr.cpp @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include "ModuleBase_ToolBox.h" +#include "ModuleBase_ISelection.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +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 + (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( + 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 + (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(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 + (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 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( + module()->activeWidget()); + //PartSet_WidgetPoint2D* aPoint2DWdg = + // dynamic_cast(module()->activeWidget()); + PartSet_MouseProcessor* aFirstWidget = dynamic_cast( + aPanel->findFirstAcceptingValueWidget()); + //if (aPoint2DWdg && aPoint2DWdg == aFirstWidget) { + if (aMouseProcessor && aMouseProcessor == aFirstWidget) { + std::shared_ptr 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(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 + (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 + (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& aWidgets = aPanel->modelWidgets(); + QList::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 + (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 + (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 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(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 + (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( + 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& aWidgets = aPanel->modelWidgets(); + QList 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( + 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 + (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 + (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 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(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 aSFData = theSourceFeature->data(); + std::shared_ptr aSPoint = std::dynamic_pointer_cast( + aSFData->attribute(SketchPlugin_Line::END_ID())); + std::shared_ptr aNFData = theNewFeature->data(); + std::shared_ptr aNPoint = std::dynamic_pointer_cast( + aNFData->attribute(SketchPlugin_Line::START_ID())); + aNPoint->setValue(aSPoint->x(), aSPoint->y()); + PartSet_Tools::createConstraint(theSketch, aSPoint, aNPoint); + + aNPoint = std::dynamic_pointer_cast( + 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 aSData = theSourceFeature->data(); + std::shared_ptr aSPointAttr = + std::dynamic_pointer_cast( + 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 aNPointAttr = + std::dynamic_pointer_cast( + 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 + (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(myWorkshop); + return aConnector->workshop(); +} + +PartSet_Module* PartSet_SketcherReentrantMgr::module() const +{ + return dynamic_cast(myWorkshop->module()); +} diff --git a/src/PartSet/PartSet_SketcherReentrantMgr.h b/src/PartSet/PartSet_SketcherReentrantMgr.h new file mode 100644 index 000000000..b430c2389 --- /dev/null +++ b/src/PartSet/PartSet_SketcherReentrantMgr.h @@ -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 + +#include + +#include + +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& 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& /*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 index 36ae78513..000000000 --- a/src/PartSet/PartSet_SketcherReetntrantMgr.cpp +++ /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 -#include -#include -#include -#include -#include -#include -#include -#include -#include "ModuleBase_ToolBox.h" -#include "ModuleBase_ISelection.h" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -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 - (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( - 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 - (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(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 - (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 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( - module()->activeWidget()); - //PartSet_WidgetPoint2D* aPoint2DWdg = - // dynamic_cast(module()->activeWidget()); - PartSet_MouseProcessor* aFirstWidget = dynamic_cast( - aPanel->findFirstAcceptingValueWidget()); - //if (aPoint2DWdg && aPoint2DWdg == aFirstWidget) { - if (aMouseProcessor && aMouseProcessor == aFirstWidget) { - std::shared_ptr 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(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 - (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 - (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& aWidgets = aPanel->modelWidgets(); - QList::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 - (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 - (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 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(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 - (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( - 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 - (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 - (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 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(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 aSFData = theSourceFeature->data(); - std::shared_ptr aSPoint = std::dynamic_pointer_cast( - aSFData->attribute(SketchPlugin_Line::END_ID())); - std::shared_ptr aNFData = theNewFeature->data(); - std::shared_ptr aNPoint = std::dynamic_pointer_cast( - aNFData->attribute(SketchPlugin_Line::START_ID())); - aNPoint->setValue(aSPoint->x(), aSPoint->y()); - PartSet_Tools::createConstraint(theSketch, aSPoint, aNPoint); - - aNPoint = std::dynamic_pointer_cast( - 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 aSData = theSourceFeature->data(); - std::shared_ptr aSPointAttr = - std::dynamic_pointer_cast( - 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 aNPointAttr = - std::dynamic_pointer_cast( - 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 - (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(myWorkshop); - return aConnector->workshop(); -} - -PartSet_Module* PartSet_SketcherReetntrantMgr::module() const -{ - return dynamic_cast(myWorkshop->module()); -} - diff --git a/src/PartSet/PartSet_SketcherReetntrantMgr.h b/src/PartSet/PartSet_SketcherReetntrantMgr.h deleted file mode 100755 index 5ae8a76b7..000000000 --- a/src/PartSet/PartSet_SketcherReetntrantMgr.h +++ /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 - -#include - -#include - -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& 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& /*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 diff --git a/src/PartSet/PartSet_WidgetPoint2d.cpp b/src/PartSet/PartSet_WidgetPoint2d.cpp index cb727289e..cf095fe0c 100644 --- a/src/PartSet/PartSet_WidgetPoint2d.cpp +++ b/src/PartSet/PartSet_WidgetPoint2d.cpp @@ -7,7 +7,7 @@ #include "PartSet_WidgetPoint2d.h" #include #include -#include +#include #include #include diff --git a/src/SketchPlugin/plugin-Sketch.xml b/src/SketchPlugin/plugin-Sketch.xml index ed46c351b..6ad5fdc9a 100644 --- a/src/SketchPlugin/plugin-Sketch.xml +++ b/src/SketchPlugin/plugin-Sketch.xml @@ -76,7 +76,7 @@ icon="icons/Sketch/circle.png" title="Circle" tooltip="Create circle"> - +