From: nds Date: Mon, 27 Nov 2017 09:47:53 +0000 (+0300) Subject: Improvement of the Group Feature (Undo-Redo functionality inside the multiple selecti... X-Git-Tag: V_2.10.0RC~137 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=82e5b8212960f00bb388f60650cd464696ef464d;p=modules%2Fshaper.git Improvement of the Group Feature (Undo-Redo functionality inside the multiple selection widget) --- diff --git a/src/ModuleBase/CMakeLists.txt b/src/ModuleBase/CMakeLists.txt index 48070d0ad..cb40f7222 100644 --- a/src/ModuleBase/CMakeLists.txt +++ b/src/ModuleBase/CMakeLists.txt @@ -32,6 +32,7 @@ ADD_DEFINITIONS(${QT_DEFINITIONS}) SET(PROJECT_HEADERS ModuleBase.h ModuleBase_ActionInfo.h + ModuleBase_ActionType.h ModuleBase_Definitions.h ModuleBase_DoubleSpinBox.h ModuleBase_Events.h diff --git a/src/ModuleBase/ModuleBase_ActionType.h b/src/ModuleBase/ModuleBase_ActionType.h new file mode 100644 index 000000000..864c5e64a --- /dev/null +++ b/src/ModuleBase/ModuleBase_ActionType.h @@ -0,0 +1,38 @@ +// Copyright (C) 2014-2017 CEA/DEN, EDF R&D +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or +// email : webmaster.salome@opencascade.com +// + +#ifndef ModuleBase_ActionType_H_ +#define ModuleBase_ActionType_H_ + +#include + +/*! + * Structure to describe widget processed types of actions. + */ +enum MODULEBASE_EXPORT ModuleBase_ActionType +{ + ActionEnter, + ActionEscape, + ActionDelete, + ActionUndo, + ActionRedo +}; + +#endif /* ModuleBase_ActionType_H_ */ diff --git a/src/ModuleBase/ModuleBase_ModelWidget.cpp b/src/ModuleBase/ModuleBase_ModelWidget.cpp index 3fa0b14d0..ff4f88a9d 100644 --- a/src/ModuleBase/ModuleBase_ModelWidget.cpp +++ b/src/ModuleBase/ModuleBase_ModelWidget.cpp @@ -406,6 +406,37 @@ void ModuleBase_ModelWidget::updateObject(ObjectPtr theObject) } } +bool ModuleBase_ModelWidget::canProcessAction(ModuleBase_ActionType theActionType, + bool& isActionEnabled) +{ + isActionEnabled = false; + switch (theActionType) { + case ActionEnter: return false; + case ActionEscape: return false; + case ActionDelete: return true; + case ActionUndo: + case ActionRedo: + default: + return false; + } +} + +bool ModuleBase_ModelWidget::processAction(ModuleBase_ActionType theActionType) +{ + switch (theActionType) { + case ActionEnter: + return processEnter(); + case ActionEscape: + return processEscape(); + case ActionDelete: + return processDelete(); + case ActionUndo: + case ActionRedo: + default: + return false; + } +} + bool ModuleBase_ModelWidget::processEnter() { return false; diff --git a/src/ModuleBase/ModuleBase_ModelWidget.h b/src/ModuleBase/ModuleBase_ModelWidget.h index fbd0d6e11..c536b0622 100644 --- a/src/ModuleBase/ModuleBase_ModelWidget.h +++ b/src/ModuleBase/ModuleBase_ModelWidget.h @@ -22,6 +22,7 @@ #define MODULEBASE_MODELWIDGET_H #include +#include #include #include @@ -240,14 +241,13 @@ Q_OBJECT /// \return Current Editing mode bool isEditingMode() const { return myIsEditing; } - /// Returns true if the event is processed. The default implementation is empty, returns false. - virtual bool processEnter(); - - /// Returns true if the event is processed. The default implementation is empty, returns false. - virtual bool processEscape(); + /// Returns true if the action can be processed. The default implementation is empty, returns false. + /// \param theActionType an action type + /// \param isActionEnabled if true, the enable state of the action + virtual bool canProcessAction(ModuleBase_ActionType theActionType, bool& isActionEnabled); /// Returns true if the event is processed. The default implementation is empty, returns false. - virtual bool processDelete(); + virtual bool processAction(ModuleBase_ActionType theActionType); /// Sends Update and Redisplay for the given object /// \param theObj is updating object @@ -343,6 +343,15 @@ protected: /// The method called when widget is activated virtual void activateCustom() {}; + //// Returns true if the event is processed. The default implementation is empty, returns false. + virtual bool processEnter(); + + //// Returns true if the event is processed. The default implementation is empty, returns false. + virtual bool processEscape(); + + //// Returns true if the event is processed. The default implementation is empty, returns false. + virtual bool processDelete(); + protected slots: /// Processing of values changed in model widget by store the current value to the feature void onWidgetValuesChanged(); diff --git a/src/ModuleBase/ModuleBase_WidgetDoubleValue.h b/src/ModuleBase/ModuleBase_WidgetDoubleValue.h index 07a22802d..347f3ca99 100644 --- a/src/ModuleBase/ModuleBase_WidgetDoubleValue.h +++ b/src/ModuleBase/ModuleBase_WidgetDoubleValue.h @@ -59,15 +59,15 @@ Q_OBJECT /// \return a control list virtual QList getControls() const; - /// Returns true if the event is processed. - virtual bool processEnter(); - public slots: // Delayed value chnged: when user starts typing something, // it gives him a 0,5 second to finish typing, when sends valueChnaged() signal // void onValueChanged(); protected: + /// Returns true if the event is processed. + virtual bool processEnter(); + /// Saves the internal parameters to the given feature /// \return True in success virtual bool storeValueCustom(); diff --git a/src/ModuleBase/ModuleBase_WidgetEditor.h b/src/ModuleBase/ModuleBase_WidgetEditor.h index 757165744..4c485d199 100644 --- a/src/ModuleBase/ModuleBase_WidgetEditor.h +++ b/src/ModuleBase/ModuleBase_WidgetEditor.h @@ -68,6 +68,7 @@ Q_OBJECT /// \param theY the Y coordinate void setCursorPosition(const int theX, const int theY); +protected: /// Returns true if the event is processed. virtual bool processEnter(); diff --git a/src/ModuleBase/ModuleBase_WidgetExprEditor.h b/src/ModuleBase/ModuleBase_WidgetExprEditor.h index 8099dd026..310021975 100644 --- a/src/ModuleBase/ModuleBase_WidgetExprEditor.h +++ b/src/ModuleBase/ModuleBase_WidgetExprEditor.h @@ -123,14 +123,14 @@ class MODULEBASE_EXPORT ModuleBase_WidgetExprEditor : public ModuleBase_ModelWid /// Redefinition of virtual method virtual QList getControls() const; - /// Returns true if the event is processed. - virtual bool processEnter(); - protected slots: /// A slot for processing text changed event void onTextChanged(); protected: + /// Returns true if the event is processed. + virtual bool processEnter(); + /// Do not initialize value on the widget activation virtual void initializeValueByActivate(); diff --git a/src/ModuleBase/ModuleBase_WidgetFileSelector.h b/src/ModuleBase/ModuleBase_WidgetFileSelector.h index be59f13b4..e337845e9 100644 --- a/src/ModuleBase/ModuleBase_WidgetFileSelector.h +++ b/src/ModuleBase/ModuleBase_WidgetFileSelector.h @@ -66,9 +66,6 @@ class MODULEBASE_EXPORT ModuleBase_WidgetFileSelector : public ModuleBase_ModelW /// exists and has supported format bool isCurrentPathValid(); - /// Reject the current editor dialog if it is shown and returns true. - virtual bool processEscape(); - public slots: /// Processing of path selection button press void onPathSelectionBtn(); @@ -77,6 +74,9 @@ public slots: void onPathChanged(); protected: + /// Reject the current editor dialog if it is shown and returns true. + virtual bool processEscape(); + /// Saves the internal parameters to the given feature /// \return True in success virtual bool storeValueCustom(); diff --git a/src/ModuleBase/ModuleBase_WidgetIntValue.h b/src/ModuleBase/ModuleBase_WidgetIntValue.h index 4a13ed442..0394458c9 100644 --- a/src/ModuleBase/ModuleBase_WidgetIntValue.h +++ b/src/ModuleBase/ModuleBase_WidgetIntValue.h @@ -56,10 +56,10 @@ Q_OBJECT /// \return a control list virtual QList getControls() const; +protected: /// Returns true if the event is processed. virtual bool processEnter(); -protected: /// Saves the internal parameters to the given feature /// \return True in success virtual bool storeValueCustom(); diff --git a/src/ModuleBase/ModuleBase_WidgetLineEdit.h b/src/ModuleBase/ModuleBase_WidgetLineEdit.h index ac67b8713..aee98f9f4 100644 --- a/src/ModuleBase/ModuleBase_WidgetLineEdit.h +++ b/src/ModuleBase/ModuleBase_WidgetLineEdit.h @@ -52,10 +52,10 @@ class MODULEBASE_EXPORT ModuleBase_WidgetLineEdit : public ModuleBase_ModelWidge /// Redefinition of virtual method virtual QList getControls() const; +protected: /// Returns true if the event is processed. virtual bool processEnter(); -protected: /// Saves the internal parameters to the given feature /// \return True in success virtual bool storeValueCustom(); diff --git a/src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp b/src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp index d144f3382..409c2949b 100755 --- a/src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp +++ b/src/ModuleBase/ModuleBase_WidgetMultiSelector.cpp @@ -58,6 +58,8 @@ const int ATTRIBUTE_SELECTION_INDEX_ROLE = Qt::UserRole + 1; +//#define DEBUG_UNDO_REDO + /** * Customization of a List Widget to make it to be placed on full width of container */ @@ -99,11 +101,27 @@ protected: #endif }; +#ifdef DEBUG_UNDO_REDO +void printHistoryInfo(const QString& theMethodName, int theCurrentHistoryIndex, + QList > > theSelectedHistoryValues) +{ + QStringList aSizes; + for (int i = 0; i < theSelectedHistoryValues.size(); i++) + aSizes.append(QString::number(theSelectedHistoryValues[i].size())); + + std::cout << theMethodName.toStdString() + << " current = " << theCurrentHistoryIndex + << " size(history) = " << theSelectedHistoryValues.size() + << " (" << aSizes.join(", ").toStdString() << ")" + << std::endl; +} +#endif + ModuleBase_WidgetMultiSelector::ModuleBase_WidgetMultiSelector(QWidget* theParent, ModuleBase_IWorkshop* theWorkshop, const Config_WidgetAPI* theData) : ModuleBase_WidgetSelector(theParent, theWorkshop, theData), - myIsSetSelectionBlocked(false) + myIsSetSelectionBlocked(false), myCurrentHistoryIndex(-1) { QGridLayout* aMainLay = new QGridLayout(this); ModuleBase_Tools::adjustMargins(aMainLay); @@ -186,6 +204,8 @@ void ModuleBase_WidgetMultiSelector::activateCustom() myWorkshop->module()->activateCustomPrs(myFeature, ModuleBase_IModule::CustomizeHighlightedObjects, true); + clearSelectedHistory(); + myWorkshop->updateCommandStatus(); } //******************************************************************** @@ -194,6 +214,8 @@ void ModuleBase_WidgetMultiSelector::deactivate() ModuleBase_WidgetSelector::deactivate(); myWorkshop->module()->deactivateCustomPrs(ModuleBase_IModule::CustomizeHighlightedObjects, true); + clearSelectedHistory(); + myWorkshop->updateCommandStatus(); } //******************************************************************** @@ -309,6 +331,63 @@ void ModuleBase_WidgetMultiSelector::getHighlighted(QList 0 + : (mySelectedHistoryValues.size() > 0 && + myCurrentHistoryIndex < mySelectedHistoryValues.size() - 1); + } + break; + default: + break; + } + return aCanProcess; +} + +//******************************************************************** +bool ModuleBase_WidgetMultiSelector::processAction(ModuleBase_ActionType theActionType) +{ + switch (theActionType) { + case ActionUndo: + case ActionRedo: { + if (theActionType == ActionUndo) + myCurrentHistoryIndex--; + else + myCurrentHistoryIndex++; + QList aSelected = mySelectedHistoryValues[myCurrentHistoryIndex]; + // equal vertices should not be used here + ModuleBase_ISelection::filterSelectionOnEqualPoints(aSelected); + bool isDone = setSelection(aSelected, + false /*need not validate because values already was in list*/); + updateOnSelectionChanged(isDone); + + myWorkshop->updateCommandStatus(); +#ifdef DEBUG_UNDO_REDO + printHistoryInfo(QString("processAction %1").arg(theActionType == ActionUndo ? "Undo" : "Redo"), + myCurrentHistoryIndex, mySelectedHistoryValues); +#endif + return true; + } + default: + return ModuleBase_ModelWidget::processAction(theActionType); + } +} + +//******************************************************************** +bool ModuleBase_WidgetMultiSelector::activateSelectionAndFilters(bool toActivate) +{ + myWorkshop->updateCommandStatus(); // update enable state of Undo/Redo application actions + return ModuleBase_WidgetSelector::activateSelectionAndFilters(toActivate); +} + //******************************************************************** bool ModuleBase_WidgetMultiSelector::isValidSelectionCustom(const ModuleBase_ViewerPrsPtr& thePrs) { @@ -340,6 +419,8 @@ bool ModuleBase_WidgetMultiSelector::isValidSelectionCustom(const ModuleBase_Vie //******************************************************************** bool ModuleBase_WidgetMultiSelector::processDelete() { + appendFirstSelectionInHistory(); + // find attribute indices to delete std::set anAttributeIds; getSelectedAttributeIndices(anAttributeIds); @@ -392,6 +473,7 @@ bool ModuleBase_WidgetMultiSelector::processDelete() } } } + appendSelectionInHistory(); return aDone; } @@ -443,6 +525,8 @@ void ModuleBase_WidgetMultiSelector::onSelectionTypeChanged() // may be the feature's result is not displayed, but attributes should be myWorkshop->module()->customizeObject(myFeature, ModuleBase_IModule::CustomizeArguments, true); /// hope that something is redisplayed by object updated + // clear history should follow after set selected to do not increase history by setSelected + clearSelectedHistory(); } //******************************************************************** @@ -462,7 +546,47 @@ void ModuleBase_WidgetMultiSelector::onSelectionChanged() } } } + appendFirstSelectionInHistory(); ModuleBase_WidgetSelector::onSelectionChanged(); + appendSelectionInHistory(); +} + +void ModuleBase_WidgetMultiSelector::appendFirstSelectionInHistory() +{ + if (mySelectedHistoryValues.empty()) { + myCurrentHistoryIndex++; + mySelectedHistoryValues.append(getAttributeSelection()); + +#ifdef DEBUG_UNDO_REDO + printHistoryInfo("appendSelectionInHistory", myCurrentHistoryIndex, mySelectedHistoryValues); +#endif + } +} + +void ModuleBase_WidgetMultiSelector::appendSelectionInHistory() +{ + while (myCurrentHistoryIndex != mySelectedHistoryValues.count() - 1) + mySelectedHistoryValues.removeLast(); + + QList aSelected = getFilteredSelected(); + myCurrentHistoryIndex++; + mySelectedHistoryValues.append(aSelected); + myWorkshop->updateCommandStatus(); + +#ifdef DEBUG_UNDO_REDO + printHistoryInfo("appendSelectionInHistory", myCurrentHistoryIndex, mySelectedHistoryValues); +#endif +} + +void ModuleBase_WidgetMultiSelector::clearSelectedHistory() +{ + mySelectedHistoryValues.clear(); + myCurrentHistoryIndex = -1; + myWorkshop->updateCommandStatus(); + +#ifdef DEBUG_UNDO_REDO + printHistoryInfo("clearSelectedHistory", myCurrentHistoryIndex, mySelectedHistoryValues); +#endif } void ModuleBase_WidgetMultiSelector::updateFocus() diff --git a/src/ModuleBase/ModuleBase_WidgetMultiSelector.h b/src/ModuleBase/ModuleBase_WidgetMultiSelector.h index 2e43e575d..128aae9bc 100755 --- a/src/ModuleBase/ModuleBase_WidgetMultiSelector.h +++ b/src/ModuleBase/ModuleBase_WidgetMultiSelector.h @@ -88,14 +88,23 @@ class MODULEBASE_EXPORT ModuleBase_WidgetMultiSelector : public ModuleBase_Widge /// \param theValues a list of presentations virtual void getHighlighted(QList>& theValues); + /// Returns true if the action can be processed. The default implementation is empty, returns false. + /// \param theActionType an action type + /// \param isActionEnabled if true, the enable state of the action + virtual bool canProcessAction(ModuleBase_ActionType theActionType, bool& isActionEnabled); + + /// Returns true if the event is processed. The default implementation is empty, returns false. + virtual bool processAction(ModuleBase_ActionType theActionType); + + /// Activate or deactivate selection and selection filters + /// \return true if the selection filter of the widget is activated in viewer context + virtual bool activateSelectionAndFilters(bool toActivate); + /// Checks the widget validity. By default, it returns true. /// \param thePrs a selected presentation in the view /// \return a boolean value virtual bool isValidSelectionCustom(const std::shared_ptr& thePrs); - /// Returns true if the event is processed. The default implementation is empty, returns false. - virtual bool processDelete(); - public slots: /// Slot is called on selection type changed void onSelectionTypeChanged(); @@ -115,6 +124,9 @@ protected slots: void onListSelection(); protected: + /// Returns true if the event is processed. The default implementation is empty, returns false. + virtual bool processDelete(); + /// The methiod called when widget is activated virtual void activateCustom(); @@ -122,8 +134,19 @@ protected: /// \return True in success virtual bool storeValueCustom(); + /// restire type of selection by feature attribute virtual bool restoreValueCustom(); + /// Creates an element of the attribute current selection if history is empty + virtual void appendFirstSelectionInHistory(); + + /// Create an element in the history that stores the current selection, + /// position in the history is incremented + void appendSelectionInHistory(); + + /// Clear list of stored selected items, reset current position into '-1' + void clearSelectedHistory(); + /// Set the focus on the last item in the list virtual void updateFocus(); @@ -215,6 +238,11 @@ protected: /// A flag to block set selection perform if the method is in process bool myIsSetSelectionBlocked; + + /// A container of selected objects + QList > > mySelectedHistoryValues; + /// Position in a container of selected values + int myCurrentHistoryIndex; }; #endif /* MODULEBASE_WIDGETFILESELECTOR_H_ */ diff --git a/src/XGUI/XGUI_OperationMgr.cpp b/src/XGUI/XGUI_OperationMgr.cpp index cfdf13912..50f690425 100644 --- a/src/XGUI/XGUI_OperationMgr.cpp +++ b/src/XGUI/XGUI_OperationMgr.cpp @@ -202,6 +202,18 @@ ModuleBase_Operation* XGUI_OperationMgr::previousOperation(ModuleBase_Operation* return myOperations.at(idx - 1); } +ModuleBase_ModelWidget* XGUI_OperationMgr::activeWidget() const +{ + ModuleBase_ModelWidget* anActiveWidget = 0; + ModuleBase_Operation* anOperation = currentOperation(); + if (anOperation) { + ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel(); + if (aPanel) + anActiveWidget = aPanel->activeWidget(); + } + return anActiveWidget; +} + bool XGUI_OperationMgr::startOperation(ModuleBase_Operation* theOperation) { if (hasOperation()) @@ -697,7 +709,7 @@ bool XGUI_OperationMgr::onKeyPressed(QObject *theObject, QKeyEvent* theEvent) ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel(); ModuleBase_ModelWidget* anActiveWgt = aPanel->activeWidget(); if (anActiveWgt) - isAccepted = anActiveWgt && anActiveWgt->processEscape(); + isAccepted = anActiveWgt && anActiveWgt->processAction(ActionEscape); } // default Escape button functionality if (!isAccepted && aOperation) { @@ -737,7 +749,7 @@ bool XGUI_OperationMgr::onProcessEnter(QObject* theObject) } } if (!isAborted) { - isAccepted = anActiveWgt && anActiveWgt->processEnter(); + isAccepted = anActiveWgt && anActiveWgt->processAction(ActionEnter); if (!isAccepted) { isAccepted = myWorkshop->module()->processEnter(anActiveWgt ? anActiveWgt->attributeID() : ""); @@ -784,7 +796,7 @@ bool XGUI_OperationMgr::onProcessDelete(QObject* theObject) if (isPPChildObject) { anActiveWgt = aPanel->activeWidget(); if (anActiveWgt) { - isAccepted = anActiveWgt->processDelete(); + isAccepted = anActiveWgt->processAction(ActionDelete); } } } diff --git a/src/XGUI/XGUI_OperationMgr.h b/src/XGUI/XGUI_OperationMgr.h index 2c5eb0075..a2e2f0ed0 100755 --- a/src/XGUI/XGUI_OperationMgr.h +++ b/src/XGUI/XGUI_OperationMgr.h @@ -113,6 +113,10 @@ public: /// else, or if there is no parent - returns NULL ModuleBase_Operation* previousOperation(ModuleBase_Operation* theOperation) const; + /// Returns an active widget of the current operation. + /// \return widget or NULL + ModuleBase_ModelWidget* activeWidget() const; + /// Start the operation and append it to the stack of operations /// \param theOperation the started operation /// \return the state whether the current operation is started diff --git a/src/XGUI/XGUI_Workshop.cpp b/src/XGUI/XGUI_Workshop.cpp index d6791ab65..cc6ea32c5 100755 --- a/src/XGUI/XGUI_Workshop.cpp +++ b/src/XGUI/XGUI_Workshop.cpp @@ -327,7 +327,7 @@ void XGUI_Workshop::startApplication() #ifdef _DEBUG bool aNewPart = Config_PropManager::boolean("Plugins", "create_part_by_start"); if (aNewPart) { - module()->launchOperation("Part", false); + module()->launchOperation("Part", false); // PartSetPlugin_Part::ID() } #endif } @@ -870,6 +870,22 @@ void XGUI_Workshop::openDirectory(const QString& theDirectory) #ifndef HAVE_SALOME myMainWindow->setCurrentDir(myCurrentDir, true); #endif + +#ifdef _DEBUG + bool aNewPart = Config_PropManager::boolean("Plugins", "create_part_by_start"); + if (aNewPart) { + + DocumentPtr aRootDoc = ModelAPI_Session::get()->moduleDocument(); + int aSize = aRootDoc->size(ModelAPI_ResultPart::group()); + if (aSize > 0 ) { + ObjectPtr aObject = aRootDoc->object(ModelAPI_ResultPart::group(), 0); + ResultPartPtr aPart = std::dynamic_pointer_cast(aObject); + if (aPart.get()) + aPart->activate(); + } + } +#endif + QApplication::restoreOverrideCursor(); } @@ -1001,6 +1017,10 @@ bool XGUI_Workshop::onSaveAs() //****************************************************** void XGUI_Workshop::onUndo(int theTimes) { + ModuleBase_ModelWidget* anActiveWidget = myOperationMgr->activeWidget(); + if (anActiveWidget && anActiveWidget->processAction(ActionUndo)) + return; + objectBrowser()->treeView()->setCurrentIndex(QModelIndex()); SessionPtr aMgr = ModelAPI_Session::get(); std::list aUndoList = aMgr->undoList(); @@ -1024,6 +1044,10 @@ void XGUI_Workshop::onUndo(int theTimes) //****************************************************** void XGUI_Workshop::onRedo(int theTimes) { + ModuleBase_ModelWidget* anActiveWidget = myOperationMgr->activeWidget(); + if (anActiveWidget && anActiveWidget->processAction(ActionRedo)) + return; + // the viewer update should be blocked in order to avoid the features blinking. For the created // feature a results are created, the flush of the created signal caused the viewer redisplay for // each created result. After a redisplay signal is flushed. So, the viewer update is blocked @@ -1073,13 +1097,13 @@ void XGUI_Workshop::onRedo(int theTimes) //****************************************************** void XGUI_Workshop::onWidgetStateChanged(int thePreviousState) { - ModuleBase_ModelWidget* anActiveWidget = 0; - ModuleBase_Operation* anOperation = myOperationMgr->currentOperation(); - if (anOperation) { - ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel(); - if (aPanel) - anActiveWidget = aPanel->activeWidget(); - } + ModuleBase_ModelWidget* anActiveWidget = myOperationMgr->activeWidget(); + //ModuleBase_Operation* anOperation = myOperationMgr->currentOperation(); + //if (anOperation) { + // ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel(); + // if (aPanel) + // anActiveWidget = aPanel->activeWidget(); + //} if (anActiveWidget) operationMgr()->onValidateOperation(); @@ -1208,10 +1232,24 @@ void XGUI_Workshop::updateCommandStatus() if (aMgr->hasModuleDocument()) { foreach(QAction* aCmd, aCommands) { QString aId = aCmd->data().toString(); - if (aId == "UNDO_CMD") - aCmd->setEnabled(myModule->canUndo()); - else if (aId == "REDO_CMD") - aCmd->setEnabled(myModule->canRedo()); + if (aId == "UNDO_CMD") { + bool isActionEnabled = false; + // if ultimate is true -> using result of operation only, or using OR combination + ModuleBase_ModelWidget* anActiveWidget = myOperationMgr->activeWidget(); + if (anActiveWidget && anActiveWidget->canProcessAction(ActionUndo, isActionEnabled)) + aCmd->setEnabled(isActionEnabled); + else + aCmd->setEnabled(myModule->canUndo()); + } + else if (aId == "REDO_CMD") { + bool isActionEnabled = false; + // if ultimate is true -> using result of operation only, or using OR combination + ModuleBase_ModelWidget* anActiveWidget = myOperationMgr->activeWidget(); + if (anActiveWidget && anActiveWidget->canProcessAction(ActionRedo, isActionEnabled)) + aCmd->setEnabled(isActionEnabled); + else + aCmd->setEnabled(myModule->canRedo()); + } else // Enable all commands aCmd->setEnabled(true);