From: nds Date: Wed, 26 Aug 2015 09:08:43 +0000 (+0300) Subject: Providing Action class to have a common approach to start/finish/abort model transact... X-Git-Tag: V_1.4.0_beta4~244 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=03936c76cd52c555961e4636e640c12fe2d47f2f;p=modules%2Fshaper.git Providing Action class to have a common approach to start/finish/abort model transactions for such actions as Delete/Detach and others. The common functionality: 1.On the start of the action, the message about aborting the previous operation should be shown. 2. On commit, ApplyAll button[sketch operation] enable state should be updated, SetModified[sketch operation] of the parent operation update[in order to have a message about aborting transaction]. In the current integration, ModuleBase_Operation is separated to ModuleBase_OperationFeature and ModuleBase_OperationAction. --- diff --git a/src/ModuleBase/CMakeLists.txt b/src/ModuleBase/CMakeLists.txt index fd928e6ef..935f742e8 100644 --- a/src/ModuleBase/CMakeLists.txt +++ b/src/ModuleBase/CMakeLists.txt @@ -22,7 +22,9 @@ SET(PROJECT_HEADERS ModuleBase_IWorkshop.h ModuleBase_ModelWidget.h ModuleBase_Operation.h + ModuleBase_OperationAction.h ModuleBase_OperationDescription.h + ModuleBase_OperationFeature.h ModuleBase_PageBase.h ModuleBase_PageGroupBox.h ModuleBase_PageWidget.h @@ -71,7 +73,9 @@ SET(PROJECT_SOURCES ModuleBase_IWorkshop.cpp ModuleBase_ModelWidget.cpp ModuleBase_Operation.cpp - ModuleBase_OperationDescription.cpp + ModuleBase_OperationAction.cpp + ModuleBase_OperationDescription.cpp + ModuleBase_OperationFeature.cpp ModuleBase_PageBase.cpp ModuleBase_PageGroupBox.cpp ModuleBase_PageWidget.cpp diff --git a/src/ModuleBase/ModuleBase_IModule.cpp b/src/ModuleBase/ModuleBase_IModule.cpp index 1c69f0471..3fe2524f3 100644 --- a/src/ModuleBase/ModuleBase_IModule.cpp +++ b/src/ModuleBase/ModuleBase_IModule.cpp @@ -7,6 +7,7 @@ #include "ModuleBase_Operation.h" #include "ModuleBase_ISelection.h" #include "ModuleBase_OperationDescription.h" +#include "ModuleBase_OperationFeature.h" #include @@ -43,11 +44,14 @@ void ModuleBase_IModule::launchOperation(const QString& theCmdId) if (!myWorkshop->canStartOperation(theCmdId)) return; - ModuleBase_Operation* anOperation = createOperation(theCmdId.toStdString()); - ModuleBase_ISelection* aSelection = myWorkshop->selection(); - // Initialise operation with preliminary selection - anOperation->initSelection(aSelection, myWorkshop->viewer()); - sendOperation(anOperation); + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (createOperation(theCmdId.toStdString())); + if (aFOperation) { + ModuleBase_ISelection* aSelection = myWorkshop->selection(); + // Initialise operation with preliminary selection + aFOperation->initSelection(aSelection, myWorkshop->viewer()); + sendOperation(aFOperation); + } } @@ -62,22 +66,23 @@ void ModuleBase_IModule::sendOperation(ModuleBase_Operation* theOperation) ModuleBase_Operation* ModuleBase_IModule::getNewOperation(const std::string& theFeatureId) { - return new ModuleBase_Operation(theFeatureId.c_str(), this); + return new ModuleBase_OperationFeature(theFeatureId.c_str(), this); } ModuleBase_Operation* ModuleBase_IModule::createOperation(const std::string& theFeatureId) { - ModuleBase_Operation* anOperation = getNewOperation(theFeatureId); - + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (getNewOperation(theFeatureId)); // If the operation is launched as sub-operation of another then we have to initialise // parent feature - ModuleBase_Operation* aCurOperation = myWorkshop->currentOperation(); + ModuleBase_OperationFeature* aCurOperation = dynamic_cast + (myWorkshop->currentOperation()); if (aCurOperation) { FeaturePtr aFeature = aCurOperation->feature(); CompositeFeaturePtr aCompFeature = std::dynamic_pointer_cast(aFeature); if (aCompFeature) { - anOperation->setParentFeature(aCompFeature); + aFOperation->setParentFeature(aCompFeature); } } @@ -87,10 +92,10 @@ ModuleBase_Operation* ModuleBase_IModule::createOperation(const std::string& the std::string aXmlCfg = aWdgReader.featureWidgetCfg(theFeatureId); std::string aDescription = aWdgReader.featureDescription(theFeatureId); - anOperation->getDescription()->setDescription(QString::fromStdString(aDescription)); - anOperation->getDescription()->setXmlRepresentation(QString::fromStdString(aXmlCfg)); + aFOperation->getDescription()->setDescription(QString::fromStdString(aDescription)); + aFOperation->getDescription()->setXmlRepresentation(QString::fromStdString(aXmlCfg)); - return anOperation; + return aFOperation; } void ModuleBase_IModule::createFeatures() @@ -156,15 +161,19 @@ void ModuleBase_IModule::editFeature(FeaturePtr theFeature) if (!myWorkshop->canStartOperation(aFeatureId.c_str())) return; - ModuleBase_Operation* anOperation = createOperation(aFeatureId); - anOperation->setFeature(theFeature); - sendOperation(anOperation); + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (createOperation(aFeatureId)); + if (aFOperation) { + aFOperation->setFeature(theFeature); + sendOperation(aFOperation); + } } bool ModuleBase_IModule::canActivateSelection(const ObjectPtr& theObject) const { - ModuleBase_Operation* aOperation = myWorkshop->currentOperation(); - return !aOperation || !aOperation->hasObject(theObject); + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (myWorkshop->currentOperation()); + return !aFOperation || !aFOperation->hasObject(theObject); } void ModuleBase_IModule::onOperationResumed(ModuleBase_Operation* theOperation) diff --git a/src/ModuleBase/ModuleBase_Operation.cpp b/src/ModuleBase/ModuleBase_Operation.cpp index 701b6a0cc..4d54780f9 100644 --- a/src/ModuleBase/ModuleBase_Operation.cpp +++ b/src/ModuleBase/ModuleBase_Operation.cpp @@ -39,7 +39,6 @@ ModuleBase_Operation::ModuleBase_Operation(const QString& theId, QObject* theParent) : QObject(theParent), - myIsEditing(false), myIsModified(false), myPropertyPanel(NULL) { @@ -49,7 +48,6 @@ ModuleBase_Operation::ModuleBase_Operation(const QString& theId, QObject* thePar ModuleBase_Operation::~ModuleBase_Operation() { delete myDescription; - clearPreselection(); } QString ModuleBase_Operation::id() const @@ -57,86 +55,21 @@ QString ModuleBase_Operation::id() const return getDescription()->operationId(); } -FeaturePtr ModuleBase_Operation::feature() const -{ - return myFeature; -} - bool ModuleBase_Operation::isValid() const { - if (!myFeature || !myFeature->data()->isValid()) - return true; // rename operation - if (myFeature->isAction()) - return true; - //Get validators for the Id - SessionPtr aMgr = ModelAPI_Session::get(); - ModelAPI_ValidatorsFactory* aFactory = aMgr->validators(); - bool aValid = aFactory->validate(myFeature); - - // the feature exec state should be checked in order to do not apply features, which result can not - // be built. E.g. extrusion on sketch, where the "to" is a perpendicular plane to the sketch - bool isDone = ( myFeature->data()->execState() == ModelAPI_StateDone - || myFeature->data()->execState() == ModelAPI_StateMustBeUpdated ); - - return aValid && isDone; + return true; } - bool ModuleBase_Operation::canBeCommitted() const { return isValid(); } -FeaturePtr ModuleBase_Operation::createFeature(const bool theFlushMessage) -{ - if (myParentFeature.get()) { - myFeature = myParentFeature->addFeature(getDescription()->operationId().toStdString()); - } else { - std::shared_ptr aDoc = ModelAPI_Session::get()->activeDocument(); - myFeature = aDoc->addFeature(getDescription()->operationId().toStdString()); - } - if (myFeature) { // TODO: generate an error if feature was not created - myIsModified = true; - // Model update should call "execute" of a feature. - //myFeature->execute(); - // Init default values - /*QList aWidgets = getDescription()->modelWidgets(); - QList::const_iterator anIt = aWidgets.begin(), aLast = aWidgets.end(); - for (; anIt != aLast; anIt++) { - (*anIt)->storeValue(aFeature); - }*/ - } - - if (theFlushMessage) - Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED)); - return myFeature; -} - -void ModuleBase_Operation::setFeature(FeaturePtr theFeature) -{ - myFeature = theFeature; - myIsEditing = true; -} - -bool ModuleBase_Operation::hasObject(ObjectPtr theObj) const -{ - FeaturePtr aFeature = feature(); - if (aFeature) { - if (aFeature == theObj) - return true; - std::list aResults = aFeature->results(); - std::list::const_iterator aIt; - for (aIt = aResults.cbegin(); aIt != aResults.cend(); ++aIt) { - if (theObj == (*aIt)) - return true; - } - } - return false; -} void ModuleBase_Operation::start() { myIsModified = false; + /* QString anId = getDescription()->operationId(); if (myIsEditing) { anId = anId.append(EditSuffix()); @@ -164,7 +97,7 @@ void ModuleBase_Operation::start() startOperation(); emit started(); - +*/ } void ModuleBase_Operation::postpone() @@ -181,6 +114,7 @@ void ModuleBase_Operation::resume() void ModuleBase_Operation::abort() { +/* // the viewer update should be blocked in order to avoid the features blinking before they are // hidden std::shared_ptr aMsg = std::shared_ptr( @@ -223,11 +157,12 @@ void ModuleBase_Operation::abort() Events_Loop::loop()->send(aMsg); emit aborted(); +*/ } bool ModuleBase_Operation::commit() { - if (canBeCommitted()) { +/* if (canBeCommitted()) { // 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 @@ -258,6 +193,7 @@ bool ModuleBase_Operation::commit() afterCommitOperation(); return true; } +*/ return false; } @@ -266,143 +202,12 @@ void ModuleBase_Operation::onValuesChanged() myIsModified = true; } -void ModuleBase_Operation::commitOperation() -{ - if(!myPropertyPanel) { - return; - } -} - -void ModuleBase_Operation::activateByPreselection() -{ - if (myPreSelection.empty()) - return; - - ModuleBase_ModelWidget* aFilledWgt = 0; - if (myPropertyPanel) { - const QList& aWidgets = myPropertyPanel->modelWidgets(); - if (!aWidgets.empty()) { - ModuleBase_ModelWidget* aWgt = 0; - QList::const_iterator aWIt; - bool isSet = false; - // 1. apply the selection to controls - for (aWIt = aWidgets.constBegin(); aWIt != aWidgets.constEnd(); ++aWIt) { - aWgt = (*aWIt); - if (!aWgt->canSetValue()) - continue; - myPropertyPanel->setPreselectionWidget(aWgt); - if (!aWgt->setSelection(myPreSelection, true)) { - isSet = false; - break; - } else { - isSet = true; - aFilledWgt = aWgt; - } - } - myPropertyPanel->setPreselectionWidget(NULL); - // in order to redisplay object in the viewer, the update/redisplay signals should be flushed - // it is better to perform it not in setSelection of each widget, but do it here, - // after the preselection is processed - ModuleBase_ModelWidget::updateObject(myFeature); - - // 3. a signal should be emitted before the next widget activation - // because, the activation of the next widget will give a focus to the widget. As a result - // the value of the widget is initialized. And commit may happens until the value is entered. - if (aFilledWgt) - emit activatedByPreselection(); - } - // 4. activate the next obligatory widget - myPropertyPanel->activateNextWidget(aFilledWgt); - } - - clearPreselection(); -} - -void ModuleBase_Operation::setParentFeature(CompositeFeaturePtr theParent) -{ - myParentFeature = theParent; -} - -CompositeFeaturePtr ModuleBase_Operation::parentFeature() const -{ - return myParentFeature; -} - -void ModuleBase_Operation::initSelection(ModuleBase_ISelection* theSelection, - ModuleBase_IViewer* theViewer) -{ - clearPreselection(); - - QList aPreSelected; - // Check that the selected result are not results of operation feature - FeaturePtr aFeature = feature(); - if (aFeature) { - QList aSelected = theSelection->getSelected(ModuleBase_ISelection::AllControls); - - std::list aResults = aFeature->results(); - QObjectPtrList aResList; - std::list::const_iterator aIt; - for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) - aResList.append(*aIt); - - foreach (ModuleBase_ViewerPrs aPrs, aSelected) { - if ((!aResList.contains(aPrs.object())) && (aPrs.object() != aFeature)) - aPreSelected.append(aPrs); - } - } else - aPreSelected = theSelection->getSelected(ModuleBase_ISelection::AllControls); - - // convert the selection values to the values, which are set to the operation widgets - - //Handle(V3d_View) aView = theViewer->activeView(); - //foreach (ModuleBase_ViewerPrs aPrs, aPreSelected) { - // ModuleBase_WidgetValueFeature* aValue = new ModuleBase_WidgetValueFeature(); - // aValue->setObject(aPrs.object()); - - // double aX, anY; - // if (getViewerPoint(aPrs, theViewer, aX, anY)) - // aValue->setPoint(std::shared_ptr(new GeomAPI_Pnt2d(aX, anY))); - // myPreSelection.append(aValue); - //} - myPreSelection = aPreSelected; -} - - -bool ModuleBase_Operation::getViewerPoint(ModuleBase_ViewerPrs thePrs, - ModuleBase_IViewer* theViewer, - double& theX, double& theY) -{ - return false; -} - -void ModuleBase_Operation::clearPreselection() -{ - myPreSelection.clear(); -} - void ModuleBase_Operation::setPropertyPanel(ModuleBase_IPropertyPanel* theProp) { myPropertyPanel = theProp; - myPropertyPanel->setEditingMode(isEditOperation()); - - if (myPropertyPanel) { - const QList& aWidgets = myPropertyPanel->modelWidgets(); - QList::const_iterator aWIt; - for (aWIt = aWidgets.constBegin(); aWIt != aWidgets.constEnd(); ++aWIt) { - ModuleBase_ModelWidget* aWgt = (*aWIt); - connect(aWgt, SIGNAL(valuesChanged()), this, SLOT(onValuesChanged())); - } - } - - // Do not activate widgets by default if the current operation is editing operation - // Because we don't know which widget is going to be edited. - if (!isEditOperation()) { - // 4. activate the first obligatory widget - myPropertyPanel->activateNextWidget(NULL); - } } bool ModuleBase_Operation::isGranted(QString theId) const { - return myNestedFeatures.contains(theId); + return false; } diff --git a/src/ModuleBase/ModuleBase_Operation.h b/src/ModuleBase/ModuleBase_Operation.h index ec6cc4f49..09b625778 100644 --- a/src/ModuleBase/ModuleBase_Operation.h +++ b/src/ModuleBase/ModuleBase_Operation.h @@ -11,10 +11,6 @@ #define ModuleBase_Operation_H #include -#include - -#include -#include #include #include @@ -23,8 +19,6 @@ class ModuleBase_ModelWidget; class ModuleBase_OperationDescription; class ModuleBase_IPropertyPanel; -class ModuleBase_ISelection; -class ModuleBase_IViewer; class QKeyEvent; @@ -50,13 +44,11 @@ class MODULEBASE_EXPORT ModuleBase_Operation : public QObject Q_OBJECT public: - - /// Appends to operation's history id, if it is an "edit" operation (myIsEditing == true) - static QString EditSuffix() { return "_E"; } /// Constructor /// \param theId the operation identifier /// \param theParent the QObject parent ModuleBase_Operation(const QString& theId = "", QObject* theParent = 0); + /// Destructor virtual ~ModuleBase_Operation(); @@ -64,56 +56,25 @@ Q_OBJECT /// /returns the instance of the description class ModuleBase_OperationDescription* getDescription() const { return myDescription; } - /** - * Must return true if this operation can be launched as nested for any current operation - * and it is not necessary to check this operation on validity. By default - * the operation is not granted. - * The method has to be redefined for granted operations. - */ + /// Must return true if this operation can be launched as nested for any current operation + /// and it is not necessary to check this operation on validity. By default + /// the operation is not granted. + /// The method has to be redefined for granted operations. virtual bool isGranted(QString theId) const; - /// Returns True if data of its feature was modified during operation virtual bool isModified() const { return myIsModified; } /// Change the modified state of the operation void setIsModified(const bool theIsModified) { myIsModified = theIsModified; } - /// Returns True id the current operation is launched in editing mode - bool isEditOperation() const { return myIsEditing; } - - /// Returns list of nested features - QStringList nestedFeatures() const { return myNestedFeatures; } - - /// Sets list of nested features - void setNestedFeatures(const QStringList& theList) { myNestedFeatures = theList; } - - /// Returns operations Id from it's description QString id() const; - /// Returns the operation feature - /// \return the feature - FeaturePtr feature() const; - - /** - * Must return True if the operation's feature is valid. - * Since IOperation does not have any feature returns false. - */ + /// Must return True if the operation's feature is valid. + /// Since IOperation does not have any feature returns false. virtual bool isValid() const; - /// Sets the operation feature - void setFeature(FeaturePtr theFeature); - - /// Returns True if the current operation works with the given object (feature or result) - virtual bool hasObject(ObjectPtr theObj) const; - - /// Initialisation of operation with preliminary selection - /// \param theSelection an instance of Selection class - /// \param theViewer a viewer to have the viewer the eye position - virtual void initSelection(ModuleBase_ISelection* theSelection, - ModuleBase_IViewer* theViewer); - /// \brief Set property pane to the operation /// \param theProp a property panel instance virtual void setPropertyPanel(ModuleBase_IPropertyPanel* theProp); @@ -121,38 +82,24 @@ Q_OBJECT /// \return Currently installed property panel ModuleBase_IPropertyPanel* propertyPanel() const { return myPropertyPanel; } - /// Activates widgets by preselection if it is accepted. Emits signal if the activation is correct - virtual void activateByPreselection(); - - /// If the operation works with feature which is sub-feature of another one - /// then this variable has to be initialised by parent feature - /// before operation feature creating - void setParentFeature(CompositeFeaturePtr theParent); - - /// \return Installed parent feature (can be NULL) - CompositeFeaturePtr parentFeature() const; - signals: /// The operation is started - void started(); + void started(); /// The operation is aborted - void aborted(); + void aborted(); /// The operation is committed - void committed(); + void committed(); /// The operation is aborted or committed - void stopped(); + void stopped(); /// The operation is resumed - void resumed(); + void resumed(); /// The operation is postponed - void postponed(); - - /// The operation is filled with existing preselection - void activatedByPreselection(); + void postponed(); public slots: /// Starts operation @@ -161,10 +108,10 @@ signals: /// to change behavior of operation. There is no point in using this method. It would /// be better to inherit own operator from base one and redefine startOperation method /// instead. - void start(); + virtual void start(); /// Deactivates current operation which can be resumed later. - void postpone(); + virtual void postpone(); /// Resumes operation /// Public slot. Verifies whether operation can be started and starts operation. @@ -172,17 +119,17 @@ signals: /// to change behavior of operation. There is no point in using this method. It would /// be better to inherit own operator from base one and redefine startOperation method /// instead. - void resume(); + virtual void resume(); /// Aborts operation /// Public slot. Aborts operation. This slot is not virtual and cannot be redefined. /// Redefine abortOperation method to change behavior of operation instead - void abort(); + virtual void abort(); /// Commits operation /// Public slot. Commits operation. This slot is not virtual and cannot be redefined. /// Redefine commitOperation method to change behavior of operation instead - bool commit(); + virtual bool commit(); /// Changes the modified flag of the operation void onValuesChanged(); @@ -202,7 +149,7 @@ signals: virtual void abortOperation() {} /// Virtual method called when operation committed (see commit() method for more description) - virtual void commitOperation(); + virtual void commitOperation() {}; /// Virtual method called after operation committed (see commit() method for more description) virtual void afterCommitOperation() {} @@ -210,58 +157,19 @@ signals: /// Virtual method called after operation resume (see resume() method for more description) virtual void resumeOperation() {} - /// Creates an operation new feature - /// \param theFlushMessage the flag whether the create message should be flushed - /// \returns the created feature - virtual FeaturePtr createFeature(const bool theFlushMessage = true); - /// Verifies whether this operator can be commited. /// \return Returns TRUE if current operation can be committed, e.g. all parameters are filled virtual bool canBeCommitted() const; - /// Return a widget value point by the selection and the viewer position - /// The default realization returns false - /// \param thePrs the presentation - /// \param theViewer a viewer to have the viewer the eye position - /// \param theX the horizontal coordinate - /// \param theY the vertical coordinate - /// \return true if the point exits in the selection - virtual bool getViewerPoint(ModuleBase_ViewerPrs thePrs, - ModuleBase_IViewer* theViewer, - double& theX, double& theY); - - /// Removes the preselection information and clears the map of preselection - void clearPreselection(); - - protected: - /// The operation feature to be handled - FeaturePtr myFeature; - +private: /// the container to have the operation description - ModuleBase_OperationDescription* myDescription; - - /// Editing feature flag - bool myIsEditing; + ModuleBase_OperationDescription* myDescription; /// Modified feature flag bool myIsModified; - /// List of nested operations IDs - QStringList myNestedFeatures; - - /// List of pre-selected object - QList myPreSelection; - /// Access to property panel ModuleBase_IPropertyPanel* myPropertyPanel; - - /// If the operation works with feature which is sub-feature of another one - /// then this variable has to be initialised by parent feature - /// before operation feature creating - CompositeFeaturePtr myParentFeature; - - /// Last current feature before editing operation - FeaturePtr myCurrentFeature; }; #endif diff --git a/src/ModuleBase/ModuleBase_OperationAction.cpp b/src/ModuleBase/ModuleBase_OperationAction.cpp new file mode 100755 index 000000000..cabc64c79 --- /dev/null +++ b/src/ModuleBase/ModuleBase_OperationAction.cpp @@ -0,0 +1,19 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +/* + * ModuleBase_OperationAction.cpp + * + * Created on: Apr 2, 2014 + * Author: sbh + */ + +#include "ModuleBase_OperationAction.h" + +ModuleBase_OperationAction::ModuleBase_OperationAction(const QString& theId, QObject* theParent) + : ModuleBase_Operation(theId, theParent) +{ +} + +ModuleBase_OperationAction::~ModuleBase_OperationAction() +{ +} diff --git a/src/ModuleBase/ModuleBase_OperationAction.h b/src/ModuleBase/ModuleBase_OperationAction.h new file mode 100755 index 000000000..4667840b0 --- /dev/null +++ b/src/ModuleBase/ModuleBase_OperationAction.h @@ -0,0 +1,43 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +/* + * ModuleBase_OperationAction.h + * + * Created on: Apr 2, 2014 + * Author: sbh + */ + +#ifndef ModuleBase_OperationAction_H +#define ModuleBase_OperationAction_H + +#include + +#include + +/*! + * \class ModuleBase_OperationAction + * \ingroup GUI + * \brief Base class for all operations + * + * Base class for all operations. If you perform an action it is reasonable to create + * operation intended for this. This is a base class for all operations which provides + * mechanism for correct starting operations, starting operations above already started + * ones, committing operations and so on. To create own operation it is reasonable to + * inherit it from this class and redefines virtual methods to provide own behavior + */ + +class MODULEBASE_EXPORT ModuleBase_OperationAction : public ModuleBase_Operation +{ +Q_OBJECT + + public: + + /// Constructor + /// \param theId the operation identifier + /// \param theParent the QObject parent + ModuleBase_OperationAction(const QString& theId = "", QObject* theParent = 0); + /// Destructor + virtual ~ModuleBase_OperationAction(); +}; + +#endif diff --git a/src/ModuleBase/ModuleBase_OperationFeature.cpp b/src/ModuleBase/ModuleBase_OperationFeature.cpp new file mode 100755 index 000000000..ff49f7145 --- /dev/null +++ b/src/ModuleBase/ModuleBase_OperationFeature.cpp @@ -0,0 +1,355 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +/* + * ModuleBase_OperationFeature.cpp + * + * Created on: Apr 2, 2014 + * Author: sbh + */ + +#include "ModuleBase_OperationFeature.h" + +#include "ModuleBase_OperationDescription.h" +#include "ModuleBase_ModelWidget.h" +#include "ModuleBase_ViewerPrs.h" +#include "ModuleBase_IPropertyPanel.h" +#include "ModuleBase_ISelection.h" +#include "ModuleBase_IViewer.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#ifdef _DEBUG +#include +#endif + +ModuleBase_OperationFeature::ModuleBase_OperationFeature(const QString& theId, QObject* theParent) +: ModuleBase_Operation(theId, theParent), + myIsEditing(false) +{ +} + +ModuleBase_OperationFeature::~ModuleBase_OperationFeature() +{ + clearPreselection(); +} + +FeaturePtr ModuleBase_OperationFeature::feature() const +{ + return myFeature; +} + +bool ModuleBase_OperationFeature::isValid() const +{ + if (!myFeature || !myFeature->data()->isValid()) + return true; // rename operation + if (myFeature->isAction()) + return true; + //Get validators for the Id + SessionPtr aMgr = ModelAPI_Session::get(); + ModelAPI_ValidatorsFactory* aFactory = aMgr->validators(); + bool aValid = aFactory->validate(myFeature); + + // the feature exec state should be checked in order to do not apply features, which result can not + // be built. E.g. extrusion on sketch, where the "to" is a perpendicular plane to the sketch + bool isDone = ( myFeature->data()->execState() == ModelAPI_StateDone + || myFeature->data()->execState() == ModelAPI_StateMustBeUpdated ); + + return aValid && isDone; +} + +FeaturePtr ModuleBase_OperationFeature::createFeature(const bool theFlushMessage) +{ + if (myParentFeature.get()) { + myFeature = myParentFeature->addFeature(getDescription()->operationId().toStdString()); + } else { + std::shared_ptr aDoc = ModelAPI_Session::get()->activeDocument(); + myFeature = aDoc->addFeature(getDescription()->operationId().toStdString()); + } + if (myFeature) { // TODO: generate an error if feature was not created + setIsModified(true); + // Model update should call "execute" of a feature. + //myFeature->execute(); + // Init default values + /*QList aWidgets = getDescription()->modelWidgets(); + QList::const_iterator anIt = aWidgets.begin(), aLast = aWidgets.end(); + for (; anIt != aLast; anIt++) { + (*anIt)->storeValue(aFeature); + }*/ + } + + if (theFlushMessage) + Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED)); + return myFeature; +} + +void ModuleBase_OperationFeature::setFeature(FeaturePtr theFeature) +{ + myFeature = theFeature; + myIsEditing = true; +} + +bool ModuleBase_OperationFeature::hasObject(ObjectPtr theObj) const +{ + FeaturePtr aFeature = feature(); + if (aFeature) { + if (aFeature == theObj) + return true; + std::list aResults = aFeature->results(); + std::list::const_iterator aIt; + for (aIt = aResults.cbegin(); aIt != aResults.cend(); ++aIt) { + if (theObj == (*aIt)) + return true; + } + } + return false; +} + +void ModuleBase_OperationFeature::start() +{ + setIsModified(false); + QString anId = getDescription()->operationId(); + if (myIsEditing) { + anId = anId.append(EditSuffix()); + } + ModelAPI_Session::get()->startOperation(anId.toStdString()); + + startOperation(); + + if (!myIsEditing) { + FeaturePtr aFeature = createFeature(); + // if the feature is not created, there is no sense to start the operation + if (aFeature.get() == NULL) { + // it is necessary to abor the operation in the session and emit the aborted signal + // in order to update commands status in the workshop, to be exact the feature action + // to be unchecked + abort(); + return; + } + } + /// Set current feature and remeber old current feature + if (myIsEditing) { + SessionPtr aMgr = ModelAPI_Session::get(); + DocumentPtr aDoc = aMgr->activeDocument(); + myCurrentFeature = aDoc->currentFeature(true); + aDoc->setCurrentFeature(feature(), false); + } + + startOperation(); + emit started(); + +} + +void ModuleBase_OperationFeature::abort() +{ + // the viewer update should be blocked in order to avoid the features blinking before they are + // hidden + std::shared_ptr aMsg = std::shared_ptr( + new Events_Message(Events_Loop::eventByName(EVENT_UPDATE_VIEWER_BLOCKED))); + Events_Loop::loop()->send(aMsg); + + // the widgets of property panel should not process any events come from data mode + // after abort clicked. Some signal such as redisplay/create influence on content + // of the object browser and viewer context. Therefore it influence to the current + // selection and if the active widget listens it, the attribute value is errnoneous + // changed. + ModuleBase_IPropertyPanel* aPropertyPanel = propertyPanel(); + if (aPropertyPanel) + aPropertyPanel->cleanContent(); + + SessionPtr aMgr = ModelAPI_Session::get(); + if (myIsEditing) { + DocumentPtr aDoc = aMgr->activeDocument(); + bool aIsOp = aMgr->isOperation(); + if (!aIsOp) + aMgr->startOperation(); + aDoc->setCurrentFeature(myCurrentFeature, true); + if (!aIsOp) + aMgr->finishOperation(); + myCurrentFeature = FeaturePtr(); + } + abortOperation(); + + stopOperation(); + // is is necessary to deactivate current widgets before the model operation is aborted + // because abort removes the feature and activated filters should not check it + propertyPanel()->cleanContent(); + + aMgr->abortOperation(); + emit stopped(); + // the viewer update should be unblocked in order to avoid the features blinking before they are + // hidden + aMsg = std::shared_ptr( + new Events_Message(Events_Loop::eventByName(EVENT_UPDATE_VIEWER_UNBLOCKED))); + + Events_Loop::loop()->send(aMsg); + + emit aborted(); +} + +bool ModuleBase_OperationFeature::commit() +{ + if (canBeCommitted()) { + // 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 + // selection and if the active widget listens it, the attribute value is errnoneous + // changed. + ModuleBase_IPropertyPanel* aPropertyPanel = propertyPanel(); + if (aPropertyPanel) + aPropertyPanel->cleanContent(); + + SessionPtr aMgr = ModelAPI_Session::get(); + /// Set current feature and remeber old current feature + if (myIsEditing) { + DocumentPtr aDoc = aMgr->activeDocument(); + bool aIsOp = aMgr->isOperation(); + if (!aIsOp) + aMgr->startOperation(); + aDoc->setCurrentFeature(myCurrentFeature, true); + if (!aIsOp) + aMgr->finishOperation(); + myCurrentFeature = FeaturePtr(); + } + commitOperation(); + aMgr->finishOperation(); + + stopOperation(); + emit stopped(); + emit committed(); + + afterCommitOperation(); + return true; + } + return false; +} + +void ModuleBase_OperationFeature::activateByPreselection() +{ + if (myPreSelection.empty()) + return; + + ModuleBase_ModelWidget* aFilledWgt = 0; + ModuleBase_IPropertyPanel* aPropertyPanel = propertyPanel(); + if (aPropertyPanel) { + const QList& aWidgets = aPropertyPanel->modelWidgets(); + if (!aWidgets.empty()) { + ModuleBase_ModelWidget* aWgt = 0; + QList::const_iterator aWIt; + bool isSet = false; + // 1. apply the selection to controls + for (aWIt = aWidgets.constBegin(); aWIt != aWidgets.constEnd(); ++aWIt) { + aWgt = (*aWIt); + if (!aWgt->canSetValue()) + continue; + aPropertyPanel->setPreselectionWidget(aWgt); + if (!aWgt->setSelection(myPreSelection, true)) { + isSet = false; + break; + } else { + isSet = true; + aFilledWgt = aWgt; + } + } + aPropertyPanel->setPreselectionWidget(NULL); + // in order to redisplay object in the viewer, the update/redisplay signals should be flushed + // it is better to perform it not in setSelection of each widget, but do it here, + // after the preselection is processed + ModuleBase_ModelWidget::updateObject(myFeature); + + // 3. a signal should be emitted before the next widget activation + // because, the activation of the next widget will give a focus to the widget. As a result + // the value of the widget is initialized. And commit may happens until the value is entered. + if (aFilledWgt) + emit activatedByPreselection(); + } + // 4. activate the next obligatory widget + aPropertyPanel->activateNextWidget(aFilledWgt); + } + + clearPreselection(); +} + +void ModuleBase_OperationFeature::setParentFeature(CompositeFeaturePtr theParent) +{ + myParentFeature = theParent; +} + +CompositeFeaturePtr ModuleBase_OperationFeature::parentFeature() const +{ + return myParentFeature; +} + +void ModuleBase_OperationFeature::initSelection(ModuleBase_ISelection* theSelection, + ModuleBase_IViewer* theViewer) +{ + clearPreselection(); + + QList aPreSelected; + // Check that the selected result are not results of operation feature + FeaturePtr aFeature = feature(); + if (aFeature) { + QList aSelected = theSelection->getSelected(ModuleBase_ISelection::AllControls); + + std::list aResults = aFeature->results(); + QObjectPtrList aResList; + std::list::const_iterator aIt; + for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) + aResList.append(*aIt); + + foreach (ModuleBase_ViewerPrs aPrs, aSelected) { + if ((!aResList.contains(aPrs.object())) && (aPrs.object() != aFeature)) + aPreSelected.append(aPrs); + } + } else + aPreSelected = theSelection->getSelected(ModuleBase_ISelection::AllControls); + + myPreSelection = aPreSelected; +} + +void ModuleBase_OperationFeature::clearPreselection() +{ + myPreSelection.clear(); +} + +void ModuleBase_OperationFeature::setPropertyPanel(ModuleBase_IPropertyPanel* theProp) +{ + ModuleBase_Operation::setPropertyPanel(theProp); + + theProp->setEditingMode(isEditOperation()); + + if (theProp) { + const QList& aWidgets = theProp->modelWidgets(); + QList::const_iterator aWIt; + for (aWIt = aWidgets.constBegin(); aWIt != aWidgets.constEnd(); ++aWIt) { + ModuleBase_ModelWidget* aWgt = (*aWIt); + connect(aWgt, SIGNAL(valuesChanged()), this, SLOT(onValuesChanged())); + } + } + + // Do not activate widgets by default if the current operation is editing operation + // Because we don't know which widget is going to be edited. + if (!isEditOperation()) { + // 4. activate the first obligatory widget + theProp->activateNextWidget(NULL); + } +} + +bool ModuleBase_OperationFeature::isGranted(QString theId) const +{ + return myNestedFeatures.contains(theId); +} diff --git a/src/ModuleBase/ModuleBase_OperationFeature.h b/src/ModuleBase/ModuleBase_OperationFeature.h new file mode 100755 index 000000000..cc937e1a4 --- /dev/null +++ b/src/ModuleBase/ModuleBase_OperationFeature.h @@ -0,0 +1,172 @@ +// Copyright (C) 2014-20xx CEA/DEN, EDF R&D + +/* + * ModuleBase_OperationFeature.h + * + * Created on: Apr 2, 2014 + * Author: sbh + */ + +#ifndef ModuleBase_OperationFeature_H +#define ModuleBase_OperationFeature_H + +#include +#include +#include + +#include + +#include +#include +#include + +class ModuleBase_ModelWidget; +class ModuleBase_ISelection; +class ModuleBase_IViewer; + +class QKeyEvent; + +/*! + * \class ModuleBase_OperationFeature + * \ingroup GUI + * \brief Base class for all operations + * + * Base class for all operations. If you perform an action it is reasonable to create + * operation intended for this. This is a base class for all operations which provides + * mechanism for correct starting operations, starting operations above already started + * ones, committing operations and so on. To create own operation it is reasonable to + * inherit it from this class and redefines virtual methods to provide own behavior + * Main virtual methods are + * - virtual bool isReadyToStart(); + * - virtual void startOperation(); + * - virtual void abortOperation(); + * - virtual void commitOperation(); + */ + +class MODULEBASE_EXPORT ModuleBase_OperationFeature : public ModuleBase_Operation +{ +Q_OBJECT + + public: + + /// Appends to operation's history id, if it is an "edit" operation (myIsEditing == true) + static QString EditSuffix() { return "_E"; } + /// Constructor + /// \param theId the operation identifier + /// \param theParent the QObject parent + ModuleBase_OperationFeature(const QString& theId = "", QObject* theParent = 0); + /// Destructor + virtual ~ModuleBase_OperationFeature(); + + /** + * Must return true if this operation can be launched as nested for any current operation + * and it is not necessary to check this operation on validity. By default + * the operation is not granted. + * The method has to be redefined for granted operations. + */ + virtual bool isGranted(QString theId) const; + + /// Returns True id the current operation is launched in editing mode + bool isEditOperation() const { return myIsEditing; } + + /// Returns list of nested features + QStringList nestedFeatures() const { return myNestedFeatures; } + + /// Sets list of nested features + void setNestedFeatures(const QStringList& theList) { myNestedFeatures = theList; } + + /// Returns the operation feature + /// \return the feature + FeaturePtr feature() const; + + /** + * Must return True if the operation's feature is valid. + * Since IOperation does not have any feature returns false. + */ + virtual bool isValid() const; + + /// Sets the operation feature + void setFeature(FeaturePtr theFeature); + + /// Returns True if the current operation works with the given object (feature or result) + virtual bool hasObject(ObjectPtr theObj) const; + + /// Initialisation of operation with preliminary selection + /// \param theSelection an instance of Selection class + /// \param theViewer a viewer to have the viewer the eye position + virtual void initSelection(ModuleBase_ISelection* theSelection, + ModuleBase_IViewer* theViewer); + + /// \brief Set property pane to the operation + /// \param theProp a property panel instance + virtual void setPropertyPanel(ModuleBase_IPropertyPanel* theProp); + + /// \return Currently installed property panel + //ModuleBase_IPropertyPanel* propertyPanel() const { return myPropertyPanel; } + + /// Activates widgets by preselection if it is accepted. Emits signal if the activation is correct + virtual void activateByPreselection(); + + /// If the operation works with feature which is sub-feature of another one + /// then this variable has to be initialised by parent feature + /// before operation feature creating + void setParentFeature(CompositeFeaturePtr theParent); + + /// \return Installed parent feature (can be NULL) + CompositeFeaturePtr parentFeature() const; + +signals: + /// The operation is filled with existing preselection + void activatedByPreselection(); + + public slots: + /// Starts operation + /// Public slot. Verifies whether operation can be started and starts operation. + /// This slot is not virtual and cannot be redefined. Redefine startOperation method + /// to change behavior of operation. There is no point in using this method. It would + /// be better to inherit own operator from base one and redefine startOperation method + /// instead. + void start(); + + /// Aborts operation + /// Public slot. Aborts operation. This slot is not virtual and cannot be redefined. + /// Redefine abortOperation method to change behavior of operation instead + void abort(); + + /// Commits operation + /// Public slot. Commits operation. This slot is not virtual and cannot be redefined. + /// Redefine commitOperation method to change behavior of operation instead + bool commit(); + + protected: + /// Creates an operation new feature + /// \param theFlushMessage the flag whether the create message should be flushed + /// \returns the created feature + virtual FeaturePtr createFeature(const bool theFlushMessage = true); + + /// Removes the preselection information and clears the map of preselection + void clearPreselection(); + + protected: + /// The operation feature to be handled + FeaturePtr myFeature; + + /// Editing feature flag + bool myIsEditing; + + /// List of nested operations IDs + QStringList myNestedFeatures; + + /// List of pre-selected object + QList myPreSelection; + + /// If the operation works with feature which is sub-feature of another one + /// then this variable has to be initialised by parent feature + /// before operation feature creating + CompositeFeaturePtr myParentFeature; + + /// Last current feature before editing operation + FeaturePtr myCurrentFeature; +}; + +#endif diff --git a/src/PartSet/PartSet_MenuMgr.cpp b/src/PartSet/PartSet_MenuMgr.cpp index 0d8c0cc9a..d6bd2879e 100644 --- a/src/PartSet/PartSet_MenuMgr.cpp +++ b/src/PartSet/PartSet_MenuMgr.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -343,8 +344,11 @@ void PartSet_MenuMgr::setAuxiliary(const bool isChecked) bool isUseTransaction = false; // 1. change auxiliary type of a created feature if (PartSet_SketcherMgr::isNestedCreateOperation(anOperation) && - PartSet_SketcherMgr::isEntity(anOperation->id().toStdString()) ) { - anObjects.append(anOperation->feature()); + PartSet_SketcherMgr::isEntity(anOperation->id().toStdString()) ) { + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (anOperation); + if (aFOperation) + anObjects.append(aFOperation->feature()); } else { isUseTransaction = true; @@ -405,7 +409,9 @@ bool PartSet_MenuMgr::canSetAuxiliary(bool& theValue) const // 1. change auxiliary type of a created feature if (PartSet_SketcherMgr::isNestedCreateOperation(anOperation) && PartSet_SketcherMgr::isEntity(anOperation->id().toStdString()) ) { - anObjects.append(anOperation->feature()); + ModuleBase_OperationFeature* aFOperation = dynamic_cast(anOperation); + if (aFOperation) + anObjects.append(aFOperation->feature()); } else { /// The operation should not be aborted here, because the method does not changed diff --git a/src/PartSet/PartSet_Module.cpp b/src/PartSet/PartSet_Module.cpp index c23c23beb..54b88f25d 100755 --- a/src/PartSet/PartSet_Module.cpp +++ b/src/PartSet/PartSet_Module.cpp @@ -32,8 +32,9 @@ #include #include #include -#include +#include +#include #include #include #include @@ -246,7 +247,8 @@ void PartSet_Module::onOperationCommitted(ModuleBase_Operation* theOperation) mySketchMgr->commitNestedSketch(theOperation); } - if (theOperation->isEditOperation()) + ModuleBase_OperationFeature* aFOperation = dynamic_cast(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 @@ -256,13 +258,13 @@ void PartSet_Module::onOperationCommitted(ModuleBase_Operation* theOperation) aWorkshop->selector()->clearSelection(); /// Restart sketcher operations automatically - FeaturePtr aFeature = theOperation->feature(); + FeaturePtr aFeature = aFOperation->feature(); std::shared_ptr aSPFeature = std::dynamic_pointer_cast(aFeature); if (aSPFeature && (myRestartingMode == RM_LastFeatureUsed || myRestartingMode == RM_EmptyFeatureUsed)) { - myLastOperationId = theOperation->id(); - myLastFeature = myRestartingMode == RM_LastFeatureUsed ? theOperation->feature() : FeaturePtr(); + myLastOperationId = aFOperation->id(); + myLastFeature = myRestartingMode == RM_LastFeatureUsed ? aFOperation->feature() : FeaturePtr(); launchOperation(myLastOperationId); } @@ -290,7 +292,9 @@ void PartSet_Module::onOperationStarted(ModuleBase_Operation* theOperation) mySketchMgr->startNestedSketch(theOperation); } - myCustomPrs->activate(theOperation->feature()); + ModuleBase_OperationFeature* aFOperation = dynamic_cast(theOperation); + if (aFOperation) + myCustomPrs->activate(aFOperation->feature()); } void PartSet_Module::onOperationStopped(ModuleBase_Operation* theOperation) @@ -371,7 +375,8 @@ bool PartSet_Module::canActivateSelection(const ObjectPtr& theObject) const if (isSketchOp || isNestedOp) { // in active sketch operation it is possible to activate operation object in selection // in the edit operation, e.g. points of the line can be moved when the line is edited - aCanActivate = aCanActivate || anOperation->isEditOperation(); + ModuleBase_OperationFeature* aFOperation = dynamic_cast(anOperation); + aCanActivate = aCanActivate || (aFOperation && aFOperation->isEditOperation()); } return aCanActivate; } @@ -401,17 +406,21 @@ bool PartSet_Module::isMouseOverWindow() void PartSet_Module::propertyPanelDefined(ModuleBase_Operation* theOperation) { - ModuleBase_IPropertyPanel* aPanel = theOperation->propertyPanel(); - if (PartSet_SketcherMgr::isSketchOperation(theOperation) && (theOperation->isEditOperation())) { + ModuleBase_OperationFeature* aFOperation = dynamic_cast(theOperation); + if (!aFOperation) + 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 ((theOperation->id() == myLastOperationId) && myLastFeature) { + if ((aFOperation->id() == myLastOperationId) && myLastFeature) { ModuleBase_ModelWidget* aWgt = aPanel->activeWidget(); - if (theOperation->id().toStdString() == SketchPlugin_Line::ID()) { + if (aFOperation->id().toStdString() == SketchPlugin_Line::ID()) { // Initialise new line with first point equal to end of previous PartSet_WidgetPoint2D* aPnt2dWgt = dynamic_cast(aWgt); if (aPnt2dWgt) { @@ -420,7 +429,7 @@ void PartSet_Module::propertyPanelDefined(ModuleBase_Operation* theOperation) std::dynamic_pointer_cast(aData->attribute(SketchPlugin_Line::END_ID())); if (aPoint) { aPnt2dWgt->setPoint(aPoint->x(), aPoint->y()); - PartSet_Tools::setConstraints(mySketchMgr->activeSketch(), theOperation->feature(), + PartSet_Tools::setConstraints(mySketchMgr->activeSketch(), aFOperation->feature(), aWgt->attributeID(), aPoint->x(), aPoint->y()); aPanel->activateNextWidget(aPnt2dWgt); } diff --git a/src/PartSet/PartSet_SketcherMgr.cpp b/src/PartSet/PartSet_SketcherMgr.cpp index 3840be472..0bea2148a 100644 --- a/src/PartSet/PartSet_SketcherMgr.cpp +++ b/src/PartSet/PartSet_SketcherMgr.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -207,11 +208,13 @@ void PartSet_SketcherMgr::onEnterViewPort() // not accept a signal about the result created. Nothing is shown until mouse is moved out/in view // port. If the isDisplayed flag is true, the presentable feature is displayed as soon as the // presentation becomes valid and redisplay happens - ModuleBase_Operation* aOperation = getCurrentOperation(); - if (aOperation) { - FeaturePtr aFeature = aOperation->feature(); + //ModuleBase_Operation* aOperation = getCurrentOperation(); + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (getCurrentOperation()); + if (aFOperation) { + FeaturePtr aFeature = aFOperation->feature(); if (aFeature.get() && aFeature->data()->isValid()) { - visualizeFeature(aOperation, canDisplayObject(aFeature), false); + visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature), false); } } } @@ -254,8 +257,12 @@ void PartSet_SketcherMgr::onLeaveViewPort() // hides the presentation of the current operation feature // the feature is to be erased here, but it is correct to call canDisplayObject because // there can be additional check (e.g. editor widget in distance constraint) - FeaturePtr aFeature = getCurrentOperation()->feature(); - visualizeFeature(aOperation, canDisplayObject(aFeature)); + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (getCurrentOperation()); + if (aFOperation) { + FeaturePtr aFeature = aFOperation->feature(); + visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature)); + } } void PartSet_SketcherMgr::onBeforeValuesChangedInPropertyPanel() @@ -297,11 +304,14 @@ void PartSet_SketcherMgr::onValuesChangedInPropertyPanel() // visualize the current operation feature myIsResetCurrentValue = false; operationMgr()->onValidateOperation(); - ModuleBase_Operation* aOperation = getCurrentOperation(); // the feature is to be erased here, but it is correct to call canDisplayObject because // there can be additional check (e.g. editor widget in distance constraint) - FeaturePtr aFeature = getCurrentOperation()->feature(); - visualizeFeature(aOperation, canDisplayObject(aFeature)); + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (getCurrentOperation()); + if (aFOperation) { + FeaturePtr aFeature = aFOperation->feature(); + visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature)); + } } void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) @@ -320,9 +330,13 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE if (!aViewer->canDragByMouse()) return; - ModuleBase_Operation* aOperation = getCurrentOperation(); - if (aOperation && aOperation->isEditOperation()) { - ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel(); + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (getCurrentOperation()); + if (!aFOperation) + return; + + if (aFOperation->isEditOperation()) { + ModuleBase_IPropertyPanel* aPanel = aFOperation->propertyPanel(); ModuleBase_ModelWidget* aActiveWgt = aPanel->activeWidget(); // If the current widget is a selector, do nothing, it processes the mouse press if(aActiveWgt && aActiveWgt->isViewerSelector()) { @@ -331,18 +345,18 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE } // Use only for sketch operations - if (aOperation && myCurrentSketch) { + if (myCurrentSketch) { if (!PartSet_Tools::sketchPlane(myCurrentSketch)) return; - bool isSketcher = isSketchOperation(aOperation); - bool isSketchOpe = isNestedSketchOperation(aOperation); + bool isSketcher = isSketchOperation(aFOperation); + bool isSketchOpe = isNestedSketchOperation(aFOperation); // Avoid non-sketch operations if ((!isSketchOpe) && (!isSketcher)) return; - bool isEditing = aOperation->isEditOperation(); + bool isEditing = aFOperation->isEditOperation(); // Ignore creation sketch operation if ((!isSketcher) && (!isEditing)) @@ -360,8 +374,8 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE if (myCurrentSelection.empty()) { if (isSketchOpe && (!isSketcher)) // commit previous operation - if (!aOperation->commit()) - aOperation->abort(); + if (!aFOperation->commit()) + aFOperation->abort(); return; } // Init flyout point for radius rotation @@ -385,7 +399,7 @@ void PartSet_SketcherMgr::onMousePressed(ModuleBase_IViewWindow* theWnd, QMouseE } } else if (isSketchOpe && isEditing) { // If selected another object commit current result - aOperation->commit(); + aFOperation->commit(); myIsDragging = true; get2dPoint(theWnd, theEvent, myCurrentPoint); @@ -450,8 +464,12 @@ void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEve } // the feature is to be erased here, but it is correct to call canDisplayObject because // there can be additional check (e.g. editor widget in distance constraint) - FeaturePtr aFeature = getCurrentOperation()->feature(); - visualizeFeature(aOperation, canDisplayObject(aFeature)); + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (getCurrentOperation()); + if (aFOperation) { + FeaturePtr aFeature = aFOperation->feature(); + visualizeFeature(aFeature, aFOperation->isEditOperation(), canDisplayObject(aFeature)); + } } myClickedPoint.clear(); @@ -549,13 +567,14 @@ void PartSet_SketcherMgr::onMouseMoved(ModuleBase_IViewWindow* theWnd, QMouseEve void PartSet_SketcherMgr::onMouseDoubleClick(ModuleBase_IViewWindow* theWnd, QMouseEvent* theEvent) { - ModuleBase_Operation* aOperation = getCurrentOperation(); - if (aOperation && aOperation->isEditOperation()) { - std::string aId = aOperation->id().toStdString(); - if (isDistanceOperation(aOperation)) + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (getCurrentOperation()); + if (aFOperation && aFOperation->isEditOperation()) { + std::string aId = aFOperation->id().toStdString(); + if (isDistanceOperation(aFOperation)) { // Activate dimension value editing on double click - ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel(); + ModuleBase_IPropertyPanel* aPanel = aFOperation->propertyPanel(); QList aWidgets = aPanel->modelWidgets(); // Find corresponded widget to activate value editing foreach (ModuleBase_ModelWidget* aWgt, aWidgets) { @@ -700,7 +719,9 @@ bool PartSet_SketcherMgr::isNestedSketchOperation(ModuleBase_Operation* theOpera bool PartSet_SketcherMgr::isNestedCreateOperation(ModuleBase_Operation* theOperation) { - return theOperation && !theOperation->isEditOperation() && isNestedSketchOperation(theOperation); + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (theOperation); + return aFOperation && !aFOperation->isEditOperation() && isNestedSketchOperation(aFOperation); } bool PartSet_SketcherMgr::isEntity(const std::string& theId) @@ -723,10 +744,15 @@ bool PartSet_SketcherMgr::isDistanceOperation(ModuleBase_Operation* theOperation void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation) { + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (getCurrentOperation()); + if (!aFOperation) + return; + myModule->onViewTransformed(); // Display all sketcher sub-Objects - myCurrentSketch = std::dynamic_pointer_cast(theOperation->feature()); + myCurrentSketch = std::dynamic_pointer_cast(aFOperation->feature()); XGUI_ModuleConnector* aConnector = dynamic_cast(myModule->workshop()); // Hide sketcher result @@ -755,7 +781,7 @@ void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation) bool aHasPlane = false; std::shared_ptr aPln; - if (theOperation->isEditOperation()) { + if (aFOperation->isEditOperation()) { // If it is editing of sketch then it means that plane is already defined aPln = PartSet_Tools::sketchPlane(myCurrentSketch); if (aPln.get()) @@ -766,11 +792,11 @@ void PartSet_SketcherMgr::startSketch(ModuleBase_Operation* theOperation) Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_TO_REDISPLAY)); // all sketch objects should be activated in the sketch selection modes by edit operation start // in case of creation operation, there is an active widget, which activates own selection mode - if (theOperation->isEditOperation() && aHasPlane) + if (aFOperation->isEditOperation() && aHasPlane) aConnector->activateModuleSelectionModes(); } -void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation* theOperation) +void PartSet_SketcherMgr::stopSketch(ModuleBase_Operation*/* theOperation*/) { myIsMouseOverWindow = false; myIsConstraintsShown = true; @@ -848,11 +874,15 @@ void PartSet_SketcherMgr::stopNestedSketch(ModuleBase_Operation* theOp) void PartSet_SketcherMgr::commitNestedSketch(ModuleBase_Operation* theOperation) { if (isNestedCreateOperation(theOperation)) { - FeaturePtr aFeature = theOperation->feature(); - // it is necessary to check the the feature data validity because - // some kind of features are removed by an operation commit(the macro state of a feature) - if (aFeature.get() && aFeature->data()->isValid()) { - visualizeFeature(theOperation, true); + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (theOperation); + if (aFOperation) { + FeaturePtr aFeature = aFOperation->feature(); + // it is necessary to check the the feature data validity because + // some kind of features are removed by an operation commit(the macro state of a feature) + if (aFeature.get() && aFeature->data()->isValid()) { + visualizeFeature(aFeature, aFOperation->isEditOperation(), true); + } } } } @@ -906,9 +936,10 @@ bool PartSet_SketcherMgr::canDisplayObject(const ObjectPtr& theObject) const // 3. the method should not filter the objects, which are not related to the current operation. // The object is filtered just if it is a current operation feature or this feature result bool isObjectFound = false; - ModuleBase_Operation* anOperation = getCurrentOperation(); - if (anOperation) { - FeaturePtr aFeature = anOperation->feature(); + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (getCurrentOperation()); + if (aFOperation) { + FeaturePtr aFeature = aFOperation->feature(); if (aFeature.get()) { std::list aResults = aFeature->results(); if (theObject == aFeature) @@ -1125,7 +1156,8 @@ ModuleBase_Operation* PartSet_SketcherMgr::getCurrentOperation() const return myModule->workshop()->currentOperation(); } -void PartSet_SketcherMgr::visualizeFeature(ModuleBase_Operation* theOperation, +void PartSet_SketcherMgr::visualizeFeature(const FeaturePtr& theFeature, + const bool isEditOperation, const bool isToDisplay, const bool isFlushRedisplay) { @@ -1133,7 +1165,7 @@ void PartSet_SketcherMgr::visualizeFeature(ModuleBase_Operation* theOperation, return; #endif - if (!theOperation || theOperation->isEditOperation()) + if (isEditOperation || !theFeature.get()) return; ModuleBase_IWorkshop* aWorkshop = myModule->workshop(); @@ -1141,12 +1173,12 @@ void PartSet_SketcherMgr::visualizeFeature(ModuleBase_Operation* theOperation, // 1. change visibility of the object itself, here the presentable object is processed, // e.g. constraints features - FeaturePtr aFeature = theOperation->feature(); - std::list aResults = aFeature->results(); + //FeaturePtr aFeature = aFOperation->feature(); + std::list aResults = theFeature->results(); if (isToDisplay) - aFeature->setDisplayed(true); + theFeature->setDisplayed(true); else - aFeature->setDisplayed(false); + theFeature->setDisplayed(false); // change visibility of the object results, e.g. non-constraint features std::list::const_iterator aIt; diff --git a/src/PartSet/PartSet_SketcherMgr.h b/src/PartSet/PartSet_SketcherMgr.h index fea62f8e8..e108ff999 100644 --- a/src/PartSet/PartSet_SketcherMgr.h +++ b/src/PartSet/PartSet_SketcherMgr.h @@ -265,8 +265,8 @@ private: /// a current value is changed by property panel, the feature is displayed otherwise it is hidden /// \param theOperation an operation which feature is to be displayed, it is nested create operation /// \param isToDisplay a flag about the display or erase the feature - void visualizeFeature(ModuleBase_Operation* theOperation, const bool isToDisplay, - const bool isFlushRedisplay = true); + void visualizeFeature(const FeaturePtr& theFeature, const bool isEditOperation, + const bool isToDisplay, const bool isFlushRedisplay = true); private: /// Gives a debug information about internal flags myIsMouseOverWindow and myIsResetCurrentValue /// \return a string value diff --git a/src/PartSet/PartSet_WidgetSketchCreator.cpp b/src/PartSet/PartSet_WidgetSketchCreator.cpp index 20d602a3a..9781f9cf8 100644 --- a/src/PartSet/PartSet_WidgetSketchCreator.cpp +++ b/src/PartSet/PartSet_WidgetSketchCreator.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -118,9 +119,11 @@ void PartSet_WidgetSketchCreator::onStarted() std::dynamic_pointer_cast(myFeature); FeaturePtr aSketch = aCompFeature->addFeature("Sketch"); - ModuleBase_Operation* anOperation = myModule->createOperation("Sketch"); - anOperation->setFeature(aSketch); - myModule->sendOperation(anOperation); + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (myModule->createOperation("Sketch")); + if (aFOperation) + aFOperation->setFeature(aSketch); + myModule->sendOperation(aFOperation); //connect(anOperation, SIGNAL(aborted()), aWorkshop->operationMgr(), SLOT(abortAllOperations())); } else { // Break current operation diff --git a/src/XGUI/XGUI_ActionsMgr.cpp b/src/XGUI/XGUI_ActionsMgr.cpp index fd872f417..542e1b5e4 100644 --- a/src/XGUI/XGUI_ActionsMgr.cpp +++ b/src/XGUI/XGUI_ActionsMgr.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include @@ -95,15 +96,16 @@ bool XGUI_ActionsMgr::isNested(const QString& theId) const void XGUI_ActionsMgr::update() { FeaturePtr anActiveFeature = FeaturePtr(); - if (myOperationMgr->hasOperation()) { - ModuleBase_Operation* anOperation = myOperationMgr->currentOperation(); - anActiveFeature = anOperation->feature(); + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (myOperationMgr->currentOperation()); + if (aFOperation) { + anActiveFeature = aFOperation->feature(); if(anActiveFeature.get()) { setAllEnabled(false); QString aFeatureId = QString::fromStdString(anActiveFeature->getKind()); setActionEnabled(aFeatureId, true); } - setNestedStackEnabled(anOperation); + setNestedStackEnabled(aFOperation); } else { setAllEnabled(true); setNestedCommandsEnabled(false); @@ -315,9 +317,10 @@ void XGUI_ActionsMgr::setNestedCommandsEnabled(bool theEnabled, const QString& t void XGUI_ActionsMgr::setNestedStackEnabled(ModuleBase_Operation* theOperation) { - if(!theOperation || !theOperation->feature()) + ModuleBase_OperationFeature* anOperation = dynamic_cast(theOperation); + if(!anOperation || !anOperation->feature()) return; - FeaturePtr aFeature = theOperation->feature(); + FeaturePtr aFeature = anOperation->feature(); QString aFeatureId = QString::fromStdString(aFeature->getKind()); setActionEnabled(aFeatureId, true); setNestedCommandsEnabled(true, aFeatureId); diff --git a/src/XGUI/XGUI_ErrorMgr.cpp b/src/XGUI/XGUI_ErrorMgr.cpp index 9dda1abbb..500452a44 100644 --- a/src/XGUI/XGUI_ErrorMgr.cpp +++ b/src/XGUI/XGUI_ErrorMgr.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -45,14 +46,15 @@ const char* toString(ModelAPI_ExecState theExecState) void XGUI_ErrorMgr::onValidationStateChanged() { XGUI_OperationMgr* anOperationMgr = dynamic_cast(sender()); - if (!anOperationMgr || !anOperationMgr->currentOperation()) + if (!anOperationMgr) return; - - if (!myPropertyPanel) + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (anOperationMgr->currentOperation()); + if (!myPropertyPanel || !aFOperation) return; // get feature - FeaturePtr aFeature = anOperationMgr->currentOperation()->feature(); + FeaturePtr aFeature = aFOperation->feature(); if (!aFeature.get() || !aFeature->data()->isValid()) return; diff --git a/src/XGUI/XGUI_OperationMgr.cpp b/src/XGUI/XGUI_OperationMgr.cpp index fe2b72830..52826dc65 100644 --- a/src/XGUI/XGUI_OperationMgr.cpp +++ b/src/XGUI/XGUI_OperationMgr.cpp @@ -10,6 +10,7 @@ #include "ModuleBase_IWorkshop.h" #include "ModuleBase_IModule.h" #include "ModuleBase_OperationDescription.h" +#include "ModuleBase_OperationFeature.h" #include "ModelAPI_CompositeFeature.h" #include "ModelAPI_Session.h" @@ -74,9 +75,12 @@ QStringList XGUI_OperationMgr::operationList() const { QStringList result; foreach(ModuleBase_Operation* eachOperation, myOperations) { - FeaturePtr aFeature = eachOperation->feature(); - if(aFeature) { - result << QString::fromStdString(aFeature->getKind()); + ModuleBase_OperationFeature* aFOperation = dynamic_cast(eachOperation); + if (aFOperation) { + FeaturePtr aFeature = aFOperation->feature(); + if(aFeature) { + result << QString::fromStdString(aFeature->getKind()); + } } } return result; @@ -158,12 +162,16 @@ bool XGUI_OperationMgr::commitAllOperations() } else { abortOperation(anOperation); } - FeaturePtr aFeature = anOperation->feature(); - CompositeFeaturePtr aComposite = - std::dynamic_pointer_cast(aFeature); - isCompositeCommitted = aComposite.get(); - if (isCompositeCommitted) - break; + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (anOperation); + if (aFOperation) { + FeaturePtr aFeature = aFOperation->feature(); + CompositeFeaturePtr aComposite = + std::dynamic_pointer_cast(aFeature); + isCompositeCommitted = aComposite.get(); + if (isCompositeCommitted) + break; + } } return true; } diff --git a/src/XGUI/XGUI_Workshop.cpp b/src/XGUI/XGUI_Workshop.cpp index a66f44598..fc0a66630 100644 --- a/src/XGUI/XGUI_Workshop.cpp +++ b/src/XGUI/XGUI_Workshop.cpp @@ -62,6 +62,7 @@ #include #include #include +#include #include #include @@ -376,24 +377,29 @@ void XGUI_Workshop::onOperationStarted(ModuleBase_Operation* theOperation) { setNestedFeatures(theOperation); - if (theOperation->getDescription()->hasXmlRepresentation()) { //!< No need for property panel - setPropertyPanel(theOperation); + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (theOperation); + if (!aFOperation) + return; + + if (aFOperation->getDescription()->hasXmlRepresentation()) { //!< No need for property panel + setPropertyPanel(aFOperation); // filling the operation values by the current selection // if the operation can be commited after the controls filling, the method perform should // be stopped. Otherwise unnecessary presentations can be shown(e.g. operation prs in sketch) - if (!theOperation->isEditOperation()) { - theOperation->activateByPreselection(); - if (operationMgr()->currentOperation() != theOperation) + if (!aFOperation->isEditOperation()) { + aFOperation->activateByPreselection(); + if (operationMgr()->currentOperation() != aFOperation) return; } } updateCommandStatus(); - myModule->onOperationStarted(theOperation); + myModule->onOperationStarted(aFOperation); // the objects of the current operation should be deactivated QObjectPtrList anObjects; - FeaturePtr aFeature = theOperation->feature(); + FeaturePtr aFeature = aFOperation->feature(); anObjects.append(aFeature); std::list aResults = aFeature->results(); std::list::const_iterator aIt; @@ -424,6 +430,11 @@ void XGUI_Workshop::onOperationResumed(ModuleBase_Operation* theOperation) //****************************************************** void XGUI_Workshop::onOperationStopped(ModuleBase_Operation* theOperation) { + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (theOperation); + if (!aFOperation) + return; + ModuleBase_ISelection* aSel = mySelector->selection(); QObjectPtrList aObj = aSel->selectedPresentations(); //!< No need for property panel @@ -431,12 +442,12 @@ void XGUI_Workshop::onOperationStopped(ModuleBase_Operation* theOperation) hidePropertyPanel(); myPropertyPanel->cleanContent(); - myModule->onOperationStopped(theOperation); + myModule->onOperationStopped(aFOperation); // the deactivated objects of the current operation should be activated back. // They were deactivated on operation start or an object redisplay QObjectPtrList anObjects; - FeaturePtr aFeature = theOperation->feature(); + FeaturePtr aFeature = aFOperation->feature(); if (myDisplayer->isVisible(aFeature) && !myDisplayer->isActive(aFeature)) anObjects.append(aFeature); std::list aResults = aFeature->results(); @@ -465,16 +476,24 @@ void XGUI_Workshop::onOperationAborted(ModuleBase_Operation* theOperation) void XGUI_Workshop::setNestedFeatures(ModuleBase_Operation* theOperation) { - if (this->isSalomeMode()) - theOperation->setNestedFeatures(mySalomeConnector->nestedActions(theOperation->id())); - else - theOperation->setNestedFeatures(myActionsMgr->nestedCommands(theOperation->id())); + ModuleBase_OperationFeature* aFOperation = dynamic_cast(theOperation); + if (!aFOperation) + return; + + if (isSalomeMode()) + aFOperation->setNestedFeatures(mySalomeConnector->nestedActions(theOperation->id())); + else + aFOperation->setNestedFeatures(myActionsMgr->nestedCommands(theOperation->id())); } void XGUI_Workshop::setPropertyPanel(ModuleBase_Operation* theOperation) { + ModuleBase_OperationFeature* aFOperation = dynamic_cast(theOperation); + if (!aFOperation) + return; + showPropertyPanel(); - QString aXmlRepr = theOperation->getDescription()->xmlRepresentation(); + QString aXmlRepr = aFOperation->getDescription()->xmlRepresentation(); ModuleBase_WidgetFactory aFactory = ModuleBase_WidgetFactory(aXmlRepr.toStdString(), myModuleConnector); @@ -483,15 +502,15 @@ void XGUI_Workshop::setPropertyPanel(ModuleBase_Operation* theOperation) QList aWidgets = aFactory.getModelWidgets(); foreach (ModuleBase_ModelWidget* aWidget, aWidgets) { - bool isStoreValue = !theOperation->isEditOperation() && + bool isStoreValue = !aFOperation->isEditOperation() && !aWidget->getDefaultValue().empty() && !aWidget->isComputedDefault(); - aWidget->setFeature(theOperation->feature(), isStoreValue); + aWidget->setFeature(aFOperation->feature(), isStoreValue); aWidget->enableFocusProcessing(); } myPropertyPanel->setModelWidgets(aWidgets); - theOperation->setPropertyPanel(myPropertyPanel); + aFOperation->setPropertyPanel(myPropertyPanel); myModule->propertyPanelDefined(theOperation); @@ -1530,9 +1549,9 @@ QList XGUI_Workshop::processHistoryList(const std::list std::list::const_iterator it = theList.cbegin(); for (; it != theList.cend(); it++) { QString anId = QString::fromStdString(*it); - bool isEditing = anId.endsWith(ModuleBase_Operation::EditSuffix()); + bool isEditing = anId.endsWith(ModuleBase_OperationFeature::EditSuffix()); if (isEditing) { - anId.chop(ModuleBase_Operation::EditSuffix().size()); + anId.chop(ModuleBase_OperationFeature::EditSuffix().size()); } ActionInfo anInfo; QAction* aContextMenuAct = myContextMenuMgr->actionByName(anId); diff --git a/src/XGUI/XGUI_WorkshopListener.cpp b/src/XGUI/XGUI_WorkshopListener.cpp index b55879fae..be913ac98 100755 --- a/src/XGUI/XGUI_WorkshopListener.cpp +++ b/src/XGUI/XGUI_WorkshopListener.cpp @@ -37,6 +37,7 @@ #include #include +#include #include #include #include @@ -154,7 +155,9 @@ void XGUI_WorkshopListener::processEvent(const std::shared_ptr& XGUI_OperationMgr* anOperationMgr = workshop()->operationMgr(); if (anOperationMgr->startOperation(anOperation)) { - workshop()->propertyPanel()->updateContentWidget(anOperation->feature()); + ModuleBase_OperationFeature* aFOperation = dynamic_cast(anOperation); + if (aFOperation) + workshop()->propertyPanel()->updateContentWidget(aFOperation->feature()); if (!anOperation->getDescription()->hasXmlRepresentation()) { if (anOperation->commit()) workshop()->updateCommandStatus(); @@ -196,18 +199,23 @@ void XGUI_WorkshopListener::processEvent(const std::shared_ptr& } //****************************************************** -void XGUI_WorkshopListener::onFeatureUpdatedMsg(const std::shared_ptr& theMsg) +void XGUI_WorkshopListener::onFeatureUpdatedMsg( + const std::shared_ptr& theMsg) { std::set aFeatures = theMsg->objects(); XGUI_OperationMgr* anOperationMgr = workshop()->operationMgr(); if (anOperationMgr->hasOperation()) { - FeaturePtr aCurrentFeature = anOperationMgr->currentOperation()->feature(); - std::set::const_iterator aIt; - for (aIt = aFeatures.begin(); aIt != aFeatures.end(); ++aIt) { - ObjectPtr aNewFeature = (*aIt); - if (aNewFeature == aCurrentFeature) { - workshop()->propertyPanel()->updateContentWidget(aCurrentFeature); - break; + ModuleBase_OperationFeature* aFOperation = dynamic_cast + (anOperationMgr->currentOperation()); + if (aFOperation) { + FeaturePtr aCurrentFeature = aFOperation->feature(); + std::set::const_iterator aIt; + for (aIt = aFeatures.begin(); aIt != aFeatures.end(); ++aIt) { + ObjectPtr aNewFeature = (*aIt); + if (aNewFeature == aCurrentFeature) { + workshop()->propertyPanel()->updateContentWidget(aCurrentFeature); + break; + } } } }