#include <TDataStd_Comment.hxx>
#include <TDF_ChildIDIterator.hxx>
#include <TDataStd_ReferenceArray.hxx>
+#include <TDataStd_ReferenceList.hxx>
#include <TDataStd_IntegerArray.hxx>
#include <TDataStd_HLabelArray1.hxx>
#include <TDataStd_Name.hxx>
+#include <TDataStd_AsciiString.hxx>
#include <TDF_Reference.hxx>
#include <TDF_ChildIDIterator.hxx>
#include <TDF_LabelMapHasher.hxx>
return false;
if (anArr1->Lower() == anArr2->Lower() && anArr1->Upper() == anArr2->Upper()) {
for(int a = anArr1->Lower(); a <= anArr1->Upper(); a++)
- if (anArr1->Value(a) != anArr2->Value(a))
+ if (a != 1 && anArr1->Value(a) != anArr2->Value(a)) // second is for display
return false;
return true;
}
}
return true;
}
+ } else if (Standard_GUID::IsEqual(theAttr1->ID(), TDataStd_ReferenceArray::GetID())) {
+ Handle(TDataStd_ReferenceArray) anArr1 = Handle(TDataStd_ReferenceArray)::DownCast(theAttr1);
+ Handle(TDataStd_ReferenceArray) anArr2 = Handle(TDataStd_ReferenceArray)::DownCast(theAttr2);
+ if (anArr1.IsNull() && anArr2.IsNull())
+ return true;
+ if (anArr1.IsNull() || anArr2.IsNull())
+ return false;
+ if (anArr1->Lower() == anArr2->Lower() && anArr1->Upper() == anArr2->Upper()) {
+ for(int a = anArr1->Lower(); a <= anArr1->Upper(); a++)
+ if (anArr1->Value(a) != anArr2->Value(a)) {
+ // avoid the transaction ID checking
+ if (a == 2 && anArr1->Upper() == 2 && anArr2->Label().Tag() == 1 &&
+ (anArr2->Label().Depth() == 4 || anArr2->Label().Depth() == 6))
+ continue;
+ return false;
+ }
+ return true;
+ }
+ } else if (Standard_GUID::IsEqual(theAttr1->ID(), TDataStd_ReferenceList::GetID())) {
+ Handle(TDataStd_ReferenceList) aList1 = Handle(TDataStd_ReferenceList)::DownCast(theAttr1);
+ Handle(TDataStd_ReferenceList) aList2= Handle(TDataStd_ReferenceList)::DownCast(theAttr2);
+ if (aList1.IsNull() && aList2.IsNull())
+ return true;
+ if (aList1.IsNull() || aList2.IsNull())
+ return false;
+ const TDF_LabelList& aLList1 = aList1->List();
+ const TDF_LabelList& aLList2 = aList2->List();
+ TDF_ListIteratorOfLabelList aLIter1(aLList1);
+ TDF_ListIteratorOfLabelList aLIter2(aLList2);
+ for(; aLIter1.More() && aLIter2.More(); aLIter1.Next(), aLIter2.Next()) {
+ if (aLIter1.Value() != aLIter2.Value())
+ return false;
+ }
+ return !aLIter1.More() && !aLIter2.More(); // both lists are with the same size
+ } else if (Standard_GUID::IsEqual(theAttr1->ID(), TDF_TagSource::GetID())) {
+ return true; // it just for created and removed feature: nothing is changed
}
return false;
}
if (isEqualContent(anADelta->Attribute(), aCurrentAttr)) {
continue; // attribute is not changed actually
}
+ } else if (Standard_GUID::IsEqual(anADelta->Attribute()->ID(), TDataStd_AsciiString::GetID())) {
+ continue; // error message is disappeared
}
}
return false;
ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel();
ModuleBase_ModelWidget* aCurrentWidget = aPanel->preselectionWidget();
if (!aCurrentWidget)
- aCurrentWidget = aPanel->activeWidget();
+ aCurrentWidget = myWorkshop->module()->activeWidget();
ModuleBase_WidgetValidated* aWidgetValidated = dynamic_cast<ModuleBase_WidgetValidated*>
(aCurrentWidget);
ModuleBase_ViewerPrs aPrs;
#undef TO_STRING
}
-QString ModuleBase_IModule::getFeatureError(const FeaturePtr& theFeature)
+QString ModuleBase_IModule::getFeatureError(const FeaturePtr& theFeature, const bool isCheckGUI)
{
QString anError;
if (!theFeature.get() || !theFeature->data()->isValid() || theFeature->isAction())
return 0;\r
}\r
\r
+ /// Returns the active widget, by default it is the property panel active widget\r
+ virtual ModuleBase_ModelWidget* activeWidget() const = 0;\r
+\r
/// Returns current workshop\r
ModuleBase_IWorkshop* workshop() const { return myWorkshop; }\r
\r
//! Returns the feature error if the current state of the feature in the module is not correct\r
//! If the feature is correct, it returns an empty value\r
//! \return string value\r
- virtual QString getFeatureError(const FeaturePtr& theFeature);\r
+ virtual QString getFeatureError(const FeaturePtr& theFeature, const bool isCheckGUI = true);\r
\r
/// Returns list of granted operation indices\r
virtual void grantedOperationIds(ModuleBase_Operation* theOperation, QStringList& theIds) const;\r
/// \param thePreviousState the previous state of the widget\r
virtual void widgetStateChanged(int thePreviousState) {};\r
\r
+ /// Returns true if the event is processed.\r
+ /// \param thePreviousAttributeID an index of the previous active attribute\r
+ virtual bool processEnter(const std::string& thePreviousAttributeID) { return false; };\r
+\r
signals:\r
/// Signal which is emitted when operation is launched\r
void operationLaunched();\r
*/
#include "ModuleBase_IPropertyPanel.h"
+#include "ModuleBase_ModelWidget.h"
ModuleBase_IPropertyPanel::ModuleBase_IPropertyPanel(QWidget* theParent) : QDockWidget(theParent), myIsEditing(false)
{
}
+
+ModuleBase_ModelWidget* ModuleBase_IPropertyPanel::findFirstAcceptingValueWidget()
+{
+ return ModuleBase_IPropertyPanel::findFirstAcceptingValueWidget(modelWidgets());
+}
+
+ModuleBase_ModelWidget* ModuleBase_IPropertyPanel::findFirstAcceptingValueWidget(
+ const QList<ModuleBase_ModelWidget*>& theWidgets)
+{
+ ModuleBase_ModelWidget* aFirstWidget = 0;
+
+ ModuleBase_ModelWidget* aWgt;
+ QList<ModuleBase_ModelWidget*>::const_iterator aWIt;
+ for (aWIt = theWidgets.begin(); aWIt != theWidgets.end() && !aFirstWidget; ++aWIt) {
+ aWgt = (*aWIt);
+ if (aWgt->canSetValue())
+ aFirstWidget = aWgt;
+ }
+ return aFirstWidget;
+}
/// Sets widget processed by preselection
virtual void setPreselectionWidget(ModuleBase_ModelWidget* theWidget) = 0;
+ /// Returns the first widget, where canSetValue returns true
+ /// \return a widget or null
+ ModuleBase_ModelWidget* findFirstAcceptingValueWidget();
+
+ /// Returns the first widget, where canSetValue returns true
+ /// \return a widget or null
+ static ModuleBase_ModelWidget* findFirstAcceptingValueWidget(
+ const QList<ModuleBase_ModelWidget*>& theWidgets);
+
signals:
/// The signal about key release on the control, that corresponds to the attribute
/// \param theEvent key release event
void widgetActivated(ModuleBase_ModelWidget* theWidget);
/// Emited when there is no next widget
- void noMoreWidgets();
+ /// \param thePreviousAttributeID an attribute key of the previous active widget
+ void noMoreWidgets(const std::string& thePreviousAttributeID);
public slots:
/// Activate the next widget in the property panel
/// \return the state whether the widget can accept the focus
virtual bool focusTo();
+ /// Select the internal content if it can be selected. It is empty in the default realization
+ virtual void selectContent() {}
+
/// The method called when widget is activated
void activate();
clearPreselection();
}
+void ModuleBase_OperationFeature::setEditOperation(const bool theRestartTransaction)
+{
+ if (isEditOperation())
+ return;
+
+ if (theRestartTransaction) {
+ // finsh previous create operation
+ emit beforeCommitted();
+ SessionPtr aMgr = ModelAPI_Session::get();
+ ModelAPI_Session::get()->finishOperation();
+
+ // start new edit operation
+ myIsEditing = true;
+ QString anId = getDescription()->operationId();
+ if (myIsEditing) {
+ anId = anId.append(EditSuffix());
+ }
+ ModelAPI_Session::get()->startOperation(anId.toStdString());
+ emit beforeStarted();
+ }
+ else
+ myIsEditing = true;
+
+ propertyPanel()->setEditingMode(isEditOperation());
+}
+
FeaturePtr ModuleBase_OperationFeature::feature() const
{
return myFeature;
bool ModuleBase_OperationFeature::commit()
{
if (canBeCommitted()) {
+ emit beforeCommitted();
// the widgets of property panel should not process any events come from data mode
// after commit clicked. Some signal such as redisplay/create influence on content
// of the object browser and viewer context. Therefore it influence to the current
SessionPtr aMgr = ModelAPI_Session::get();
/// Set current feature and remeber old current feature
- emit beforeCommitted();
commitOperation();
aMgr->finishOperation();
/// Returns True id the current operation is launched in editing mode
bool isEditOperation() const { return myIsEditing; }
+ /// Change the operation mode from create to edit.
+ /// The transaction and the operation name in the model history of transaction are the same.
+ /// It updates the edit state in the widgets of property panel
+ /// \param theRestartTransaction if true, the current model transaction is committed and
+ /// the new one is started
+ void setEditOperation(const bool theRestartTransaction);
+
/// Returns the operation feature
/// \return the feature
FeaturePtr feature() const;
return true;
}
+void ModuleBase_WidgetDoubleValue::selectContent()
+{
+ mySpinBox->selectAll();
+}
+
QList<QWidget*> ModuleBase_WidgetDoubleValue::getControls() const
{
QList<QWidget*> aList;
virtual ~ModuleBase_WidgetDoubleValue();
+ /// Select the internal content if it can be selected. It is empty in the default realization
+ virtual void selectContent();
+
/// Returns list of widget controls
/// \return a control list
virtual QList<QWidget*> getControls() const;
/// \return the state whether the widget can accept the focus
virtual bool focusTo();
- private slots:
/// Shous popup window under cursor for data editing
void showPopupEditor();
//********************************************************************
void ModuleBase_WidgetMultiSelector::onSelectionTypeChanged()
{
- activateSelection(true);
- activateFilters(true);
+ activateSelectionAndFilters(true);
QList<ModuleBase_ViewerPrs> anEmptyList;
// This method will call Selection changed event which will call onSelectionChanged
// To clear mySelection, myListControl and storeValue()
aShapeTypeName = myTypeCombo->itemText(idx);
TopAbs_ShapeEnum aRefType = ModuleBase_Tools::shapeType(aShapeTypeName);
if(aRefType == theShapeType && idx != myTypeCombo->currentIndex()) {
- activateSelection(false);
- activateFilters(false);
+ activateSelectionAndFilters(false);
bool isBlocked = myTypeCombo->blockSignals(true);
myTypeCombo->setCurrentIndex(idx);
myTypeCombo->blockSignals(isBlocked);
- activateSelection(true);
- activateFilters(true);
+ activateSelectionAndFilters(true);
break;
}
}
}
//********************************************************************
-void ModuleBase_WidgetSelector::activateSelection(bool toActivate)
+void ModuleBase_WidgetSelector::activateSelectionAndFilters(bool toActivate)
{
updateSelectionName();
} else {
myWorkshop->deactivateSubShapesSelection();
}
+ activateFilters(toActivate);
}
//********************************************************************
connect(myWorkshop, SIGNAL(selectionChanged()), this,
SLOT(onSelectionChanged()), Qt::UniqueConnection);
- activateSelection(true);
+ activateSelectionAndFilters(true);
// Restore selection in the viewer by the attribute selection list
myWorkshop->setSelected(getAttributeSelection());
-
- activateFilters(true);
}
//********************************************************************
{
ModuleBase_ModelWidget::deactivate();
disconnect(myWorkshop, SIGNAL(selectionChanged()), this, SLOT(onSelectionChanged()));
- activateSelection(false);
- activateFilters(false);
+ activateSelectionAndFilters(false);
+ ModuleBase_ModelWidget::deactivate();
}
/// Defines if it is supposed that the widget should interact with the viewer.
virtual bool isViewerSelector() { return true; }
+ /// Activate or deactivate selection and selection filters
+ void activateSelectionAndFilters(bool toActivate);
+
/// Checks the widget validity. By default, it returns true.
/// \param thePrs a selected presentation in the view
/// \return a boolean value
/// The methiod called when widget is deactivated
virtual void deactivate();
-protected:
- /// Activate or deactivate selection
- void activateSelection(bool toActivate);
-
private slots:
/// Slot which is called on selection event
void onSelectionChanged();
//! Returns data object by AIS
ObjectPtr findPresentedObject(const AISObjectPtr& theAIS) const;
- /// It obtains selection filters from the workshop and activates them in the active viewer
- /// \param toActivate a flag about activation or deactivation the filters
- void activateFilters(const bool toActivate);
-
protected:
/// Creates a backup of the current values of the attribute
/// It should be realized in the specific widget because of different
/// \param theValues a list of presentations.
void filterPresentations(QList<ModuleBase_ViewerPrs>& theValues);
+ /// It obtains selection filters from the workshop and activates them in the active viewer
+ /// \param toActivate a flag about activation or deactivation the filters
+ void activateFilters(const bool toActivate);
+
protected:
/// Reference to workshop
ModuleBase_IWorkshop* myWorkshop;
PartSet_Filters.h
PartSet_FilterInfinite.h
PartSet_SketcherMgr.h
+ PartSet_SketcherReetntrantMgr.h
PartSet_MenuMgr.h
PartSet_WidgetSketchCreator.h
PartSet_IconFactory.h
PartSet_Filters.cpp
PartSet_FilterInfinite.cpp
PartSet_SketcherMgr.cpp
+ PartSet_SketcherReetntrantMgr.cpp
PartSet_MenuMgr.cpp
PartSet_WidgetSketchCreator.cpp
PartSet_IconFactory.cpp
#include "PartSet_WidgetFileSelector.h"
#include "PartSet_WidgetSketchCreator.h"
#include "PartSet_SketcherMgr.h"
+#include "PartSet_SketcherReetntrantMgr.h"
#include "PartSet_MenuMgr.h"
#include "PartSet_CustomPrs.h"
#include "PartSet_IconFactory.h"
#include <SketchPlugin_Feature.h>
#include <SketchPlugin_Sketch.h>
-#include <SketchPlugin_Line.h>
-#include <SketchPlugin_Arc.h>
-#include <SketchPlugin_Circle.h>
-#include <SketchPlugin_Point.h>
#include <SketchPlugin_ConstraintAngle.h>
#include <SketchPlugin_ConstraintLength.h>
#include <SketchPlugin_ConstraintDistance.h>
}
PartSet_Module::PartSet_Module(ModuleBase_IWorkshop* theWshop)
- : ModuleBase_IModule(theWshop),
- myRestartingMode(RM_None), myVisualLayerId(0), myHasConstraintShown(true)
+: ModuleBase_IModule(theWshop),
+ myVisualLayerId(0), myHasConstraintShown(true)
{
new PartSet_IconFactory();
mySketchMgr = new PartSet_SketcherMgr(this);
+ mySketchReentrantMgr = new PartSet_SketcherReetntrantMgr(theWshop);
XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(theWshop);
XGUI_Workshop* aWorkshop = aConnector->workshop();
XGUI_OperationMgr* anOpMgr = aWorkshop->operationMgr();
- connect(anOpMgr, SIGNAL(keyEnterReleased()), this, SLOT(onEnterReleased()));
connect(anOpMgr, SIGNAL(operationActivatedByPreselection()),
this, SLOT(onOperationActivatedByPreselection()));
mySketchMgr->commitNestedSketch(theOperation);
}
- ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
- if (!aFOperation || aFOperation->isEditOperation())
- return;
- // the selection is cleared after commit the create operation
- // in order to do not use the same selected objects in the restarted operation
- // for common behaviour, the selection is cleared even if the operation is not restarted
- XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(workshop());
- XGUI_Workshop* aWorkshop = aConnector->workshop();
- aWorkshop->selector()->clearSelection();
-
/// Restart sketcher operations automatically
- FeaturePtr aFeature = aFOperation->feature();
- std::shared_ptr<SketchPlugin_Feature> aSPFeature =
- std::dynamic_pointer_cast<SketchPlugin_Feature>(aFeature);
- if (aSPFeature && (myRestartingMode == RM_LastFeatureUsed ||
- myRestartingMode == RM_EmptyFeatureUsed)) {
- myLastOperationId = aFOperation->id();
- myLastFeature = myRestartingMode == RM_LastFeatureUsed ? aFOperation->feature() : FeaturePtr();
- if (!sketchMgr()->sketchSolverError())
- launchOperation(myLastOperationId);
+ if (!mySketchReentrantMgr->operationCommitted(theOperation)) {
+ // the selection is cleared after commit the create operation
+ // in order to do not use the same selected objects in the restarted operation
+ // for common behaviour, the selection is cleared even if the operation is not restarted
+ XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(workshop());
+ XGUI_Workshop* aWorkshop = aConnector->workshop();
+ aWorkshop->selector()->clearSelection();
}
- breakOperationSequence();
-}
-
-void PartSet_Module::breakOperationSequence()
-{
- myLastOperationId = "";
- myLastFeature = FeaturePtr();
- myRestartingMode = RM_None;
}
void PartSet_Module::operationAborted(ModuleBase_Operation* theOperation)
{
- breakOperationSequence();
+ /// Restart sketcher operations automatically
+ mySketchReentrantMgr->operationAborted(theOperation);
}
void PartSet_Module::operationStarted(ModuleBase_Operation* theOperation)
{
+ /// Restart sketcher operations automatically
+ mySketchReentrantMgr->operationStarted(theOperation);
+
if (PartSet_SketcherMgr::isSketchOperation(theOperation)) {
mySketchMgr->startSketch(theOperation);
}
myMenuMgr->updateViewerMenu(theStdActions);
}
-QString PartSet_Module::getFeatureError(const FeaturePtr& theFeature)
+QString PartSet_Module::getFeatureError(const FeaturePtr& theFeature, const bool isCheckGUI)
{
- QString anError = ModuleBase_IModule::getFeatureError(theFeature);
+ QString anError = ModuleBase_IModule::getFeatureError(theFeature, isCheckGUI);
if (anError.isEmpty())
- anError = sketchMgr()->getFeatureError(theFeature);
+ anError = sketchMgr()->getFeatureError(theFeature, isCheckGUI);
return anError;
}
return;
ModuleBase_IPropertyPanel* aPanel = aFOperation->propertyPanel();
- if (PartSet_SketcherMgr::isSketchOperation(aFOperation) && (aFOperation->isEditOperation())) {
- // we have to manually activate the sketch label in edit mode
- aPanel->activateWidget(aPanel->modelWidgets().first());
- return;
- }
-
- // Restart last operation type
- if ((aFOperation->id() == myLastOperationId) && myLastFeature) {
- ModuleBase_ModelWidget* aWgt = aPanel->activeWidget();
- if (aFOperation->id().toStdString() == SketchPlugin_Line::ID()) {
- // Initialise new line with first point equal to end of previous
- PartSet_WidgetPoint2D* aPnt2dWgt = dynamic_cast<PartSet_WidgetPoint2D*>(aWgt);
- if (aPnt2dWgt) {
- std::shared_ptr<ModelAPI_Data> aData = myLastFeature->data();
- std::shared_ptr<GeomDataAPI_Point2D> aPoint =
- std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aData->attribute(SketchPlugin_Line::END_ID()));
- if (aPoint) {
- aPnt2dWgt->setPoint(aPoint->x(), aPoint->y());
- PartSet_Tools::setConstraints(mySketchMgr->activeSketch(), aFOperation->feature(),
- aWgt->attributeID(), aPoint->x(), aPoint->y());
- aPanel->activateNextWidget(aPnt2dWgt);
- }
- }
- }
- }
+ // we have to manually activate the sketch label in edit mode
+ if (PartSet_SketcherMgr::isSketchOperation(aFOperation) && (aFOperation->isEditOperation()))
+ aPanel->activateWidget(aPanel->modelWidgets().first());
}
anOpMgr->onKeyReleased(theEvent);
}
-void PartSet_Module::onEnterReleased()
-{
- myRestartingMode = RM_EmptyFeatureUsed;
-}
-
void PartSet_Module::onOperationActivatedByPreselection()
{
+ if (!mySketchReentrantMgr->canBeCommittedByPreselection())
+ return;
+
ModuleBase_Operation* anOperation = myWorkshop->currentOperation();
if(anOperation && PartSet_SketcherMgr::isNestedSketchOperation(anOperation)) {
// Set final definitions if they are necessary
}
}
-void PartSet_Module::onNoMoreWidgets()
-{
- ModuleBase_Operation* anOperation = myWorkshop->currentOperation();
- if (anOperation) {
- if (PartSet_SketcherMgr::isNestedSketchOperation(anOperation)) {
- if (myRestartingMode != RM_Forbided)
- myRestartingMode = RM_LastFeatureUsed;
- XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(workshop());
- XGUI_Workshop* aWorkshop = aConnector->workshop();
- XGUI_OperationMgr* anOpMgr = aWorkshop->operationMgr();
- // do nothing if the feature can not be applyed
- if (anOpMgr->isApplyEnabled())
- anOperation->commit();
- }
- }
-}
-
-void PartSet_Module::onVertexSelected()
-{
- ModuleBase_Operation* aOperation = myWorkshop->currentOperation();
- if (aOperation->id().toStdString() == SketchPlugin_Line::ID()) {
- /// If last line finished on vertex the lines creation sequence has to be break
- ModuleBase_IPropertyPanel* aPanel = aOperation->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;
- }
-}
-
ModuleBase_ModelWidget* PartSet_Module::createWidgetByType(const std::string& theType, QWidget* theParent,
Config_WidgetAPI* theWidgetApi, std::string theParentId)
{
PartSet_WidgetPoint2D* aPointWgt = new PartSet_WidgetPoint2D(theParent, aWorkshop,
theWidgetApi, theParentId);
aPointWgt->setSketch(mySketchMgr->activeSketch());
- connect(aPointWgt, SIGNAL(vertexSelected()), this, SLOT(onVertexSelected()));
+ connect(aPointWgt, SIGNAL(vertexSelected()), sketchReentranceMgr(), SLOT(onVertexSelected()));
aWgt = aPointWgt;
} else if (theType == "sketch-2dpoint_flyout_selector") {
PartSet_WidgetPoint2DFlyout* aPointWgt = new PartSet_WidgetPoint2DFlyout(theParent, aWorkshop,
theWidgetApi, theParentId);
aPointWgt->setSketch(mySketchMgr->activeSketch());
- connect(aPointWgt, SIGNAL(vertexSelected()), this, SLOT(onVertexSelected()));
+ connect(aPointWgt, SIGNAL(vertexSelected()), sketchReentranceMgr(), SLOT(onVertexSelected()));
aWgt = aPointWgt;
} else if (theType == "point2ddistance") {
PartSet_WidgetPoint2dDistance* aDistanceWgt = new PartSet_WidgetPoint2dDistance(theParent,
return aWgt;
}
+ModuleBase_ModelWidget* PartSet_Module::activeWidget() const
+{
+ ModuleBase_ModelWidget* anActiveWidget = 0;
+
+ anActiveWidget = mySketchReentrantMgr->internalActiveWidget();
+ if (!anActiveWidget) {
+ ModuleBase_Operation* aOperation = myWorkshop->currentOperation();
+ if (aOperation) {
+ ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel();
+ anActiveWidget = aPanel->activeWidget();
+ }
+ }
+ return anActiveWidget;
+}
bool PartSet_Module::deleteObjects()
{
// the filters of this widget should be activated in the created view
ModuleBase_Operation* aOperation = myWorkshop->currentOperation();
if (aOperation) {
- ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel();
- ModuleBase_ModelWidget* anActiveWidget = aPanel->activeWidget();
+ ModuleBase_ModelWidget* anActiveWidget = activeWidget();
if (anActiveWidget) {
- ModuleBase_WidgetValidated* aWidgetValidated = dynamic_cast<ModuleBase_WidgetValidated*>
- (anActiveWidget);
- if (aWidgetValidated)
- aWidgetValidated->activateFilters(true);
+ ModuleBase_WidgetSelector* aWSelector = dynamic_cast<ModuleBase_WidgetSelector*>(anActiveWidget);
+ if (aWSelector)
+ aWSelector->activateSelectionAndFilters(true);
}
}
}
{
mySketchMgr->widgetStateChanged(thePreviousState);
}
+
+bool PartSet_Module::processEnter(const std::string& thePreviousAttributeID)
+{
+ return mySketchReentrantMgr->processEnter(thePreviousAttributeID);
+}
class PartSet_MenuMgr;
class PartSet_CustomPrs;
class PartSet_SketcherMgr;
+class PartSet_SketcherReetntrantMgr;
class QAction;
virtual ModuleBase_ModelWidget* createWidgetByType(const std::string& theType, QWidget* theParent,
Config_WidgetAPI* theWidgetApi, std::string theParentId);
+ /// Returns the active widget, by default it is the property panel active widget
+ /// If the internal edit operation is started, this is the first widget of the operation
+ virtual ModuleBase_ModelWidget* activeWidget() const;
+
/// Call back forlast tuning of property panel before operation performance
virtual void propertyPanelDefined(ModuleBase_Operation* theOperation);
/// Returns sketch manager object
PartSet_SketcherMgr* sketchMgr() const { return mySketchMgr; }
+ /// Returns sketch reentrant manager
+ PartSet_SketcherReetntrantMgr* sketchReentranceMgr() { return mySketchReentrantMgr; }
+
/// Performs functionality on closing document
virtual void closeDocument();
//! Returns the feature error if the current state of the feature in the module is not correct
//! If the feature is correct, it returns an empty value
//! \return string value
- virtual QString getFeatureError(const FeaturePtr& theFeature);
+ virtual QString getFeatureError(const FeaturePtr& theFeature, const bool isCheckGUI = true);
/// Returns list of granted operation indices
virtual void grantedOperationIds(ModuleBase_Operation* theOperation, QStringList& theIds) const;
/// \param thePreviousState the previous widget value state
virtual void widgetStateChanged(int thePreviousState);
-public slots:
- /// SLOT, that is called by no more widget signal emitted by property panel
- /// Set a specific flag to restart the sketcher operation
- void onNoMoreWidgets();
+ /// Returns true if the event is processed. It gives the reentrance manager to process the enter.
+ /// \param thePreviousAttributeID an index of the previous active attribute
+ virtual bool processEnter(const std::string& thePreviousAttributeID);
+public slots:
/// Redefines the parent method in order to customize the next case:
/// If the sketch nested operation is active and the presentation is not visualized in the viewer,
/// the operation should be always aborted.
/// \param theEvent the key event
void onKeyRelease(ModuleBase_IViewWindow* theWnd, QKeyEvent* theEvent);
- /// SLOT, that is called by enter key released
- /// Set a specific type of restarting the current operation
- void onEnterReleased();
-
/// SLOT, that is called by the current operation filling with the preselection.
/// It commits the operation of it is can be committed
void onOperationActivatedByPreselection();
virtual void connectToPropertyPanel(ModuleBase_ModelWidget* theWidget, const bool isToConnect);
private slots:
- /// Processing of vertex selected
- void onVertexSelected();
-
void onTreeViewDoubleClick(const QModelIndex&);
void onActiveDocPopup(const QPoint&);
private:
- /// Breaks sequense of automatically resterted operations
- void breakOperationSequence();
//! Delete features
virtual bool deleteObjects();
private:
- QString myLastOperationId;
- FeaturePtr myLastFeature;
-
- // Automatical restarting mode flag
- RestartingMode myRestartingMode;
-
SelectMgr_ListOfFilter mySelectionFilters;
PartSet_SketcherMgr* mySketchMgr;
+ PartSet_SketcherReetntrantMgr* mySketchReentrantMgr;
PartSet_MenuMgr* myMenuMgr;
/// A default custom presentation, which is used for references objects of started operation
PartSet_CustomPrs* myCustomPrs;
// Author: Vitaly SMETANNIKOV
#include "PartSet_SketcherMgr.h"
+#include "PartSet_SketcherReetntrantMgr.h"
#include "PartSet_Module.h"
#include "PartSet_WidgetPoint2d.h"
#include "PartSet_WidgetPoint2dDistance.h"
#include "PartSet_Tools.h"
#include "PartSet_WidgetSketchLabel.h"
+#include "PartSet_WidgetEditor.h"
#include <XGUI_ModuleConnector.h>
#include <XGUI_Displayer.h>
void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
{
+ if (myModule->sketchReentranceMgr()->processMousePressed(theWnd, theEvent))
+ return;
+
get2dPoint(theWnd, theEvent, myClickedPoint);
if (!(theEvent->buttons() & Qt::LeftButton))
void PartSet_SketcherMgr::onMouseReleased(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
{
+ if (myModule->sketchReentranceMgr()->processMouseReleased(theWnd, theEvent))
+ return;
+
ModuleBase_IWorkshop* aWorkshop = myModule->workshop();
ModuleBase_IViewer* aViewer = aWorkshop->viewer();
if (!aViewer->canDragByMouse())
void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent)
{
+ if (myModule->sketchReentranceMgr()->processMouseMoved(theWnd, theEvent))
+ return;
+
if (isNestedCreateOperation(getCurrentOperation()) && !myIsMouseOverViewProcessed) {
myIsMouseOverViewProcessed = true;
// 1. perform the widget mouse move functionality and display the presentation
// Find corresponded widget to activate value editing
foreach (ModuleBase_ModelWidget* aWgt, aWidgets) {
if (aWgt->attributeID() == "ConstraintValue") {
- aWgt->focusTo();
+ PartSet_WidgetEditor* anEditor = dynamic_cast<PartSet_WidgetEditor*>(aWgt);
+ if (anEditor)
+ anEditor->showPopupEditor();
return;
}
}
ModuleBase_IWorkshop* anIWorkshop = myModule->workshop();
XGUI_ModuleConnector* aConnector = dynamic_cast<XGUI_ModuleConnector*>(anIWorkshop);
XGUI_Workshop* aWorkshop = aConnector->workshop();
+ PartSet_SketcherReetntrantMgr* aReentranceMgr = myModule->sketchReentranceMgr();
+
XGUI_PropertyPanel* aPropertyPanel = aWorkshop->propertyPanel();
if (aPropertyPanel) {
connect(aPropertyPanel, SIGNAL(beforeWidgetActivated(ModuleBase_ModelWidget*)),
this, SLOT(onBeforeWidgetActivated(ModuleBase_ModelWidget*)));
+
+ connect(aPropertyPanel, SIGNAL(noMoreWidgets(const std::string&)),
+ aReentranceMgr, SLOT(onNoMoreWidgets(const std::string&)));
+ connect(aPropertyPanel, SIGNAL(widgetActivated(ModuleBase_ModelWidget*)),
+ aReentranceMgr, SLOT(onWidgetActivated()));
}
XGUI_ViewerProxy* aViewerProxy = aWorkshop->viewer();
return anError;
}
-QString PartSet_SketcherMgr::getFeatureError(const FeaturePtr& theFeature)
+QString PartSet_SketcherMgr::getFeatureError(const FeaturePtr& theFeature, const bool isCheckGUI)
{
QString anError = "";
if (!theFeature.get() || !theFeature->data()->isValid())
}
else {
ModuleBase_ModelWidget* anActiveWidget = getActiveWidget();
- if (anActiveWidget) {
+ if (isCheckGUI && anActiveWidget) {
ModuleBase_ModelWidget::ValueState aState = anActiveWidget->getValueState();
if (aState != ModuleBase_ModelWidget::Stored) {
AttributePtr anAttr = anActiveWidget->feature()->attribute(anActiveWidget->attributeID());
{
myIsMouseOverViewProcessed = true;
operationMgr()->onValidateOperation();
- if (isNestedCreateOperation(theOp))
+ if (isNestedCreateOperation(theOp) || myModule->sketchReentranceMgr()->isInternalEditActive())
QApplication::restoreOverrideCursor();
}
//! Incorrect states: the feature is sketch, the solver error value
//! The feature value is reset, this is the flag of sketch mgr
//! \return string value
- QString getFeatureError(const FeaturePtr& theFeature);
+ QString getFeatureError(const FeaturePtr& theFeature, const bool isCheckGUI = true);
/// Returns list of strings which contains id's of sketch operations
static const QStringList& sketchOperationIdList();
--- /dev/null
+// 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 <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 <SketchPlugin_Feature.h>
+#include <SketchPlugin_Line.h>
+
+#include <XGUI_Workshop.h>
+#include <XGUI_ModuleConnector.h>
+#include <XGUI_OperationMgr.h>
+#include <XGUI_PropertyPanel.h>
+
+PartSet_SketcherReetntrantMgr::PartSet_SketcherReetntrantMgr(ModuleBase_IWorkshop* theWorkshop)
+: QObject(theWorkshop),
+ myWorkshop(theWorkshop),
+ myRestartingMode(RM_None),
+ myIsFlagsBlocked(false),
+ myIsInternalEditOperation(false)
+{
+}
+
+PartSet_SketcherReetntrantMgr::~PartSet_SketcherReetntrantMgr()
+{
+}
+
+ModuleBase_ModelWidget* PartSet_SketcherReetntrantMgr::internalActiveWidget() const
+{
+ ModuleBase_ModelWidget* aWidget = 0;
+ if (!isActiveMgr())
+ return aWidget;
+
+ ModuleBase_Operation* aOperation = myWorkshop->currentOperation();
+ if (aOperation) {
+ ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel();
+ ModuleBase_ModelWidget* anActiveWidget = aPanel->activeWidget();
+ if (myIsInternalEditOperation && (!anActiveWidget || !anActiveWidget->isViewerSelector()))
+ aWidget = myInternalActiveWidget;
+ }
+ return aWidget;
+}
+
+bool PartSet_SketcherReetntrantMgr::isInternalEditActive() const
+{
+ return myIsInternalEditOperation;
+}
+
+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;
+
+ 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) {
+ PartSet_WidgetPoint2D* aPoint2DWdg = dynamic_cast<PartSet_WidgetPoint2D*>(module()->activeWidget());
+ if (aPoint2DWdg && aPoint2DWdg->canBeActivatedByMove()) {
+ ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+ (myWorkshop->currentOperation());
+ FeaturePtr aLastFeature = myRestartingMode == RM_LastFeatureUsed ? aFOperation->feature() : FeaturePtr();
+ restartOperation();
+ aProcessed = true;
+
+ if (aLastFeature) {
+ ModuleBase_IPropertyPanel* aPanel = myWorkshop->currentOperation()->propertyPanel();
+ PartSet_WidgetPoint2D* aPoint2DWdg = dynamic_cast<PartSet_WidgetPoint2D*>(aPanel->activeWidget());
+ if (aPoint2DWdg && aPoint2DWdg->canBeActivatedByMove()) {
+ QList<ModuleBase_ViewerPrs> aSelection;
+ aSelection.append(ModuleBase_ViewerPrs(aLastFeature, TopoDS_Shape(), NULL));
+ if (aPoint2DWdg->setSelection(aSelection, true))
+ aPanel->activateNextWidget(aPoint2DWdg);
+ }
+ }
+ }
+ }
+ 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()) {
+ restartOperation();
+ 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_WidgetPoint2D* aPoint2DWdg = dynamic_cast<PartSet_WidgetPoint2D*>(module()->activeWidget());
+ ModuleBase_ModelWidget* aFirstWidget = aPanel->findFirstAcceptingValueWidget();
+ if (aPoint2DWdg && aPoint2DWdg == aFirstWidget) {
+ aPoint2DWdg->onMouseRelease(theWnd, theEvent);
+ }
+ }
+ }
+
+ 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;
+
+ ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+ (myWorkshop->currentOperation());
+ if (!myWorkshop->module()->getFeatureError(aFOperation->feature(), false).isEmpty())
+ return;
+
+ if (aFOperation && PartSet_SketcherMgr::isNestedSketchOperation(aFOperation)) {
+ bool isStarted = false;
+ 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;
+
+ ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+ (myWorkshop->currentOperation());
+ if (!myWorkshop->module()->getFeatureError(aFOperation->feature(), false).isEmpty())
+ return isDone;
+
+ myRestartingMode = RM_EmptyFeatureUsed;
+ isDone = startInternalEdit(thePreviousAttributeID);
+
+ return isDone;
+}
+
+void PartSet_SketcherReetntrantMgr::onVertexSelected()
+{
+ if (!isActiveMgr())
+ return;
+
+ ModuleBase_Operation* aOperation = myWorkshop->currentOperation();
+ if (aOperation->id().toStdString() == SketchPlugin_Line::ID()) {
+ /// If last line finished on vertex the lines creation sequence has to be break
+ ModuleBase_IPropertyPanel* aPanel = aOperation->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::isActiveMgr() const
+{
+ ModuleBase_Operation* aCurrentOperation = myWorkshop->currentOperation();
+
+ bool anActive = PartSet_SketcherMgr::isSketchOperation(aCurrentOperation);
+ if (!anActive) {
+ anActive = PartSet_SketcherMgr::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;
+ ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+ (myWorkshop->currentOperation());
+
+ if (aFOperation && PartSet_SketcherMgr::isNestedSketchOperation(aFOperation)) {
+ aFOperation->setEditOperation(false);
+ workshop()->operationMgr()->updateApplyOfOperations();
+
+ createInternalFeature();
+
+ myIsInternalEditOperation = true;
+ 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)
+ aPreviousAttributeWidget = aWidgets[i];
+ }
+ // If the current widget is a selector, do nothing, it processes the mouse press
+ if (aPreviousAttributeWidget && !aPreviousAttributeWidget->isViewerSelector()) {
+ aPreviousAttributeWidget->focusTo();
+ aPreviousAttributeWidget->selectContent();
+ }
+ }
+ }
+ }
+ 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) {
+ myIsFlagsBlocked = true;
+ aFOperation->commit();
+ module()->launchOperation(aFOperation->id());
+ myIsFlagsBlocked = false;
+ resetFlags();
+ }
+ }
+}
+
+void PartSet_SketcherReetntrantMgr::createInternalFeature()
+{
+ ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+ (myWorkshop->currentOperation());
+
+ if (aFOperation && PartSet_SketcherMgr::isNestedSketchOperation(aFOperation)) {
+ FeaturePtr anOperationFeature = aFOperation->feature();
+
+ CompositeFeaturePtr aSketch = module()->sketchMgr()->activeSketch();
+ myInternalFeature = aSketch->addFeature(anOperationFeature->getKind());
+ 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) {
+ aWidget->setFeature(myInternalFeature, true);
+ }
+ 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);
+}
+
+void PartSet_SketcherReetntrantMgr::resetFlags()
+{
+ if (!myIsFlagsBlocked) {
+ myIsInternalEditOperation = false;
+ myRestartingMode = RM_None;
+ }
+}
+
+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());
+}
+
--- /dev/null
+// 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 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 theParent a parent object
+ 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;
+
+ /// 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();
+
+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();
+
+ /// 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 myInternalFeature;
+ QWidget* myInternalWidget;
+ ModuleBase_ModelWidget* myInternalActiveWidget;
+};
+
+#endif
#include "PartSet_Validators.h"
#include "PartSet_Tools.h"
+#include "PartSet_SketcherMgr.h"
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
bool isEmptySelectionValid(ModuleBase_Operation* theOperation)
{
ModuleBase_OperationFeature* aFeatureOp = dynamic_cast<ModuleBase_OperationFeature*>(theOperation);
+ // during the create operation empty selection is always valid
if (!aFeatureOp->isEditOperation()) {
return true;
}
- std::shared_ptr<GeomAPI_Pln> aPlane = sketcherPlane(theOperation);
- if (aPlane.get())
- return true;
- else
- return false;
+ else {
+ if (PartSet_SketcherMgr::isSketchOperation(aFeatureOp)) {
+ std::shared_ptr<GeomAPI_Pln> aPlane = sketcherPlane(theOperation);
+ if (aPlane.get())
+ return true;
+ else
+ return false;
+ }
+ else// in edit operation an empty selection is always valid, performed for re-entrant operrations
+ return true;
+ }
}
bool PartSet_DistanceSelection::isValid(const ModuleBase_ISelection* theSelection, ModuleBase_Operation* theOperation) const
bool PartSet_WidgetEditor::focusTo()
{
PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
- if (aModule->isMouseOverWindow())
+ if (aModule->isMouseOverWindow() && !isEditingMode())
return ModuleBase_WidgetEditor::focusTo();
else {
return ModuleBase_WidgetDoubleValue::focusTo();
bool PartSet_WidgetPoint2D::setSelection(QList<ModuleBase_ViewerPrs>& theValues,
const bool theToValidate)
{
+ bool isDone = false;
if (theValues.empty())
- return false;
+ return isDone;
ModuleBase_ViewerPrs aValue = theValues.takeFirst();
-
- Handle(V3d_View) aView = myWorkshop->viewer()->activeView();
- bool isDone = false;
TopoDS_Shape aShape = aValue.shape();
- double aX, aY;
- if (getPoint2d(aView, aShape, aX, aY)) {
- isDone = setPoint(aX, aY);
+ if (!aShape.IsNull()) {
+ Handle(V3d_View) aView = myWorkshop->viewer()->activeView();
+ double aX, aY;
+ if (getPoint2d(aView, aShape, aX, aY)) {
+ isDone = setPoint(aX, aY);
+ }
+ }
+ else if (canBeActivatedByMove()) {
+ if (feature()->getKind() == SketchPlugin_Line::ID()) {
+ FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aValue.object());
+ // Initialise new line with first point equal to end of previous
+ if (aFeature.get()) {
+ std::shared_ptr<ModelAPI_Data> aData = aFeature->data();
+ std::shared_ptr<GeomDataAPI_Point2D> aPoint =
+ std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
+ aData->attribute(SketchPlugin_Line::END_ID()));
+ if (aPoint) {
+ setPoint(aPoint->x(), aPoint->y());
+ PartSet_Tools::setConstraints(mySketch, feature(), attributeID(), aPoint->x(),
+ aPoint->y());
+ isDone = true;
+ }
+ }
+ }
}
return isDone;
}
+void PartSet_WidgetPoint2D::selectContent()
+{
+ myXSpin->selectAll();
+}
+
bool PartSet_WidgetPoint2D::setPoint(double theX, double theY)
{
if (fabs(theX) >= MaxCoordinate)
myWorkshop->activateSubShapesSelection(aModes);
}
+bool PartSet_WidgetPoint2D::canBeActivatedByMove()
+{
+ bool aCanBeActivated = false;
+ if (feature()->getKind() == SketchPlugin_Line::ID() &&
+ attributeID() == SketchPlugin_Line::START_ID())
+ aCanBeActivated = true;
+
+ return aCanBeActivated;
+}
+
void PartSet_WidgetPoint2D::deactivate()
{
ModuleBase_ModelWidget::deactivate();
virtual bool setSelection(QList<ModuleBase_ViewerPrs>& theValues,
const bool theToValidate);
+ /// Select the internal content if it can be selected. It is empty in the default realization
+ virtual void selectContent();
+
/// Returns list of widget controls
/// \return a control list
virtual QList<QWidget*> getControls() const;
//bool initFromPrevious(ObjectPtr theObject);
+ /// Defines if the widget can be activated by mouse move.
+ /// By default it returns false
+ virtual bool canBeActivatedByMove();
+
/// The methiod called when widget is deactivated
virtual void deactivate();
/// \param theEvent a mouse event
void onMouseMove(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent);
-protected slots:
/// Process mouse release event
/// \param theWnd a view window
/// \param theEvent a mouse event
{
if (!data()->isValid()) // sketch is already removed (case on undo of sketch), sync is not needed
return;
- // to keep the persistent sub-elements indexing, do not remove elements from list,
- // but substitute by nulls
- reflist(SketchPlugin_Sketch::FEATURES_ID())->substitute(theFeature, ObjectPtr());
+ AttributeRefListPtr aList = reflist(SketchPlugin_Sketch::FEATURES_ID());
+ // if the object is last, remove it from the list (needed to skip empty transaction on edit of sketch feature)
+ if (aList->object(aList->size(true) - 1, true) == theFeature) {
+ aList->remove(theFeature);
+ } else {
+ // to keep the persistent sub-elements indexing, do not remove elements from list,
+ // but substitute by nulls
+ aList->substitute(theFeature, ObjectPtr());
+ }
}
int SketchPlugin_Sketch::numberOfSubs(bool forTree) const
#include <ModuleBase_IViewer.h>
#include "ModuleBase_OperationDescription.h"
#include "ModuleBase_OperationFeature.h"
+#include "ModuleBase_Tools.h"
#include "ModelAPI_CompositeFeature.h"
#include "ModelAPI_Session.h"
#include <QApplication>
#include <QKeyEvent>
+//#define DEBUG_CURRENT_FEATURE
+
XGUI_OperationMgr::XGUI_OperationMgr(QObject* theParent,
ModuleBase_IWorkshop* theWorkshop)
: QObject(theParent), myIsApplyEnabled(false), myWorkshop(theWorkshop)
QListIterator<ModuleBase_Operation*> anIt(myOperations);
anIt.toBack();
ModuleBase_Operation* aPreviousOperation = 0;
- while (anIt.hasPrevious()) {
+ while (anIt.hasPrevious() && !isGranted) {
ModuleBase_Operation* anOp = anIt.previous();
if (anOp)
isGranted = anOp->isGranted(theId);
// is disabled, sketch entity is disabled as extrusion cut is created earliest then sketch.
// As a result the sketch disappears from the viewer. However after commit it is displayed back.
aFOperation->setPreviousCurrentFeature(aDoc->currentFeature(false));
+
+#ifdef DEBUG_CURRENT_FEATURE
+ FeaturePtr aFeature = aFOperation->feature();
+ QString aKind = aFeature ? aFeature->getKind().c_str() : "";
+ qDebug(QString("onBeforeOperationStarted(), edit operation = %1, feature = %2")
+ .arg(aFOperation->isEditOperation())
+ .arg(ModuleBase_Tools::objectInfo(aFeature)).toStdString().c_str());
+
+ qDebug(QString("\tdocument->currentFeature(false) = %1").arg(
+ ModuleBase_Tools::objectInfo(ModelAPI_Session::get()->activeDocument()->currentFeature(false))).toStdString().c_str());
+#endif
+
if (aFOperation->isEditOperation()) // it should be performed by the feature edit only
// in create operation, the current feature is changed by addFeature()
aDoc->setCurrentFeature(aFOperation->feature(), false);
+
+#ifdef DEBUG_CURRENT_FEATURE
+ qDebug("\tdocument->setCurrentFeature");
+ qDebug(QString("\tdocument->currentFeature(false) = %1").arg(
+ ModuleBase_Tools::objectInfo(ModelAPI_Session::get()->activeDocument()->currentFeature(false))).toStdString().c_str());
+#endif
}
}
/// Restore the previous current feature
ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>(aCurrentOperation);
if (aFOperation) {
+#ifdef DEBUG_CURRENT_FEATURE
+ QString aKind = aFOperation->feature()->getKind().c_str();
+ qDebug(QString("onBeforeOperationCommitted(), edit operation = %1, feature = %2")
+ .arg(aFOperation->isEditOperation())
+ .arg(ModuleBase_Tools::objectInfo(aFOperation->feature())).toStdString().c_str());
+
+ qDebug(QString("\tdocument->currentFeature(false) = %1").arg(
+ ModuleBase_Tools::objectInfo(ModelAPI_Session::get()->activeDocument()->currentFeature(false))).toStdString().c_str());
+#endif
+
if (aFOperation->isEditOperation()) {
/// Restore the previous current feature
setCurrentFeature(aFOperation->previousCurrentFeature());
if (myOperations.front() != aFOperation)
setCurrentFeature(aFOperation->previousCurrentFeature());
}
+#ifdef DEBUG_CURRENT_FEATURE
+ qDebug("\tdocument->setCurrentFeature");
+ qDebug(QString("\tdocument->currentFeature(false) = %1").arg(
+ ModuleBase_Tools::objectInfo(ModelAPI_Session::get()->activeDocument()->currentFeature(false))).toStdString().c_str());
+#endif
}
}
ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel();
ModuleBase_ModelWidget* aActiveWgt = aPanel->activeWidget();
if (!aActiveWgt || !aActiveWgt->processEnter()) {
- ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>(currentOperation());
- if (!aFOperation || myWorkshop->module()->getFeatureError(aFOperation->feature()).isEmpty()) {
- emit keyEnterReleased();
- commitOperation();
+ if (!myWorkshop->module()->processEnter(aActiveWgt ? aActiveWgt->attributeID() : "")) {
+ ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>(currentOperation());
+ if (!aFOperation || myWorkshop->module()->getFeatureError(aFOperation->feature(), false).isEmpty()) {
+ emit keyEnterReleased();
+ commitOperation();
+ }
+ else
+ isAccepted = false;
}
- else
- isAccepted = false;
}
}
break;
void XGUI_PropertyPanel::activateWidget(ModuleBase_ModelWidget* theWidget)
{
+ std::string aPreviosAttributeID;
+ if(myActiveWidget)
+ aPreviosAttributeID = myActiveWidget->attributeID();
+
// Avoid activation of already actve widget. It could happen on focusIn event many times
if (setActiveWidget(theWidget)) {
- if (myActiveWidget) {
- emit widgetActivated(myActiveWidget);
- } else if (!isEditingMode()) {
- emit noMoreWidgets();
- //setFocusOnOkButton();
+ emit widgetActivated(myActiveWidget);
+ if (!myActiveWidget && !isEditingMode()) {
+ emit noMoreWidgets(aPreviosAttributeID);
}
}
}
if (theWidget == myActiveWidget) {
return false;
}
+ std::string aPreviosAttributeID;
if(myActiveWidget) {
+ aPreviosAttributeID = myActiveWidget->attributeID();
myActiveWidget->deactivate();
myActiveWidget->setHighlighted(false);
}
if (theOperation->getDescription()->hasXmlRepresentation()) { //!< No need for property panel
setPropertyPanel(theOperation);
+ connectToPropertyPanel(true);
}
updateCommandStatus();
QAction* aCancelAct = myActionsMgr->operationStateAction(XGUI_ActionsMgr::Abort);
connect(aCancelAct, SIGNAL(triggered()), myOperationMgr, SLOT(onAbortOperation()));
- connect(myPropertyPanel, SIGNAL(noMoreWidgets()), myModule, SLOT(onNoMoreWidgets()));
connect(myPropertyPanel, SIGNAL(keyReleased(QKeyEvent*)),
myOperationMgr, SLOT(onKeyReleased(QKeyEvent*)));
//connect(myOperationMgr, SIGNAL(validationStateChanged(bool)),