From 93082f88dd1092fbf6ebc525610982f886b7ce0f Mon Sep 17 00:00:00 2001 From: nds Date: Thu, 25 May 2017 17:23:40 +0300 Subject: [PATCH] Issues #2173, #2169: processing focus in widget by SHAPER loop (instead of Qt loop). Reason, to process it in Qt loop we need to have Property Panel always as active. --- src/ModuleBase/ModuleBase_ModelWidget.cpp | 27 ++++++++++++++++++-- src/ModuleBase/ModuleBase_ModelWidget.h | 10 ++++++++ src/ModuleBase/ModuleBase_WidgetEditor.cpp | 2 +- src/PartSet/PartSet_SketcherReentrantMgr.cpp | 4 +-- src/XGUI/XGUI_ActionsMgr.cpp | 3 --- src/XGUI/XGUI_OperationMgr.cpp | 21 +++++++++++++++ src/XGUI/XGUI_PropertyPanel.cpp | 15 ++++++++--- src/XGUI/XGUI_PropertyPanel.h | 7 ++--- src/XGUI/XGUI_Workshop.cpp | 8 +++--- 9 files changed, 79 insertions(+), 18 deletions(-) diff --git a/src/ModuleBase/ModuleBase_ModelWidget.cpp b/src/ModuleBase/ModuleBase_ModelWidget.cpp index f0be4ae9e..3194f9afc 100644 --- a/src/ModuleBase/ModuleBase_ModelWidget.cpp +++ b/src/ModuleBase/ModuleBase_ModelWidget.cpp @@ -5,6 +5,7 @@ // Author: Natalia ERMOLAEVA #include "ModuleBase_ModelWidget.h" +#include "ModuleBase_IPropertyPanel.h" #include "ModuleBase_ViewerPrs.h" #include "ModuleBase_Tools.h" #include "ModuleBase_WidgetValidator.h" @@ -426,8 +427,14 @@ bool ModuleBase_ModelWidget::eventFilter(QObject* theObject, QEvent *theEvent) QFocusEvent* aFocusEvent = dynamic_cast(theEvent); bool isWinFocus = aFocusEvent->reason() == Qt::ActiveWindowFocusReason; #endif - if (getControls().contains(aWidget)) { - emit focusInWidget(this); + Qt::FocusReason aReason = aFocusEvent->reason(); + bool aMouseOrKey = aReason == Qt::MouseFocusReason/* || + //aReason == Qt::TabFocusReason || + //aReason == Qt::BacktabFocusReason /*|| + aReason == Qt::OtherFocusReason*/; // to process widget->setFocus() + if (aMouseOrKey && getControls().contains(aWidget)) { + //if (getControls().contains(aWidget)) { + emitFocusInWidget(); } } else if (theEvent->type() == QEvent::FocusOut) { @@ -461,7 +468,23 @@ void ModuleBase_ModelWidget::onWidgetValuesModified() setValueState(ModifiedInPP); } +//************************************************************** QString ModuleBase_ModelWidget::translate(const std::string& theStr) const { return ModuleBase_Tools::translate(context(), theStr); } + +//************************************************************** +ModuleBase_ModelWidget* ModuleBase_ModelWidget::findModelWidget(ModuleBase_IPropertyPanel* theProp, + QWidget* theWidget) +{ + ModuleBase_ModelWidget* aModelWidget; + QObject* aParent = theWidget->parent(); + while (aParent) { + aModelWidget = qobject_cast(aParent); + if (aModelWidget) + break; + aParent = aParent->parent(); + } + return aModelWidget; +} diff --git a/src/ModuleBase/ModuleBase_ModelWidget.h b/src/ModuleBase/ModuleBase_ModelWidget.h index 0b409e6fe..603e0d97a 100644 --- a/src/ModuleBase/ModuleBase_ModelWidget.h +++ b/src/ModuleBase/ModuleBase_ModelWidget.h @@ -17,6 +17,7 @@ class Config_WidgetAPI; class Events_InfoMessage; +class ModuleBase_IPropertyPanel; class ModuleBase_IWorkshop; class ModuleBase_ViewerPrs; class ModuleBase_WidgetValidator; @@ -242,6 +243,15 @@ Q_OBJECT /// Translate passed string with widget context() virtual QString translate(const std::string& theStr) const; + /// Emit focus in widget to set this control as active in propety panel + void emitFocusInWidget() { emit focusInWidget(this); } + + /// Finds model widget parent of the given sub widget + /// \param theWidget a candidate to be a child of the model widget + /// \param theProp a property panel instance + /// \return a model widget or NULL + static ModuleBase_ModelWidget* findModelWidget(ModuleBase_IPropertyPanel* theProp, + QWidget* theWidget); signals: /// The signal about widget values are to be changed void beforeValuesChanged(); diff --git a/src/ModuleBase/ModuleBase_WidgetEditor.cpp b/src/ModuleBase/ModuleBase_WidgetEditor.cpp index edaecab32..406c6343f 100644 --- a/src/ModuleBase/ModuleBase_WidgetEditor.cpp +++ b/src/ModuleBase/ModuleBase_WidgetEditor.cpp @@ -98,7 +98,7 @@ bool ModuleBase_WidgetEditor::showPopupEditor(const bool theSendSignals) // in the property panel before the mouse leave event happens in the viewer. The module // ask an active widget and change the feature visualization if the widget is not the current one. if (theSendSignals) - emit focusInWidget(this); + emitFocusInWidget(); // nds: it seems, that the envents processing is not necessary anymore // White while all events will be processed diff --git a/src/PartSet/PartSet_SketcherReentrantMgr.cpp b/src/PartSet/PartSet_SketcherReentrantMgr.cpp index 35fbf3e41..a98087127 100644 --- a/src/PartSet/PartSet_SketcherReentrantMgr.cpp +++ b/src/PartSet/PartSet_SketcherReentrantMgr.cpp @@ -175,9 +175,8 @@ bool PartSet_SketcherReentrantMgr::processMouseMoved(ModuleBase_IViewWindow* the myPreviousFeature = FeaturePtr(); anActiveWidget = module()->activeWidget(); - aCurrentFeature = anActiveWidget->feature(); aProcessed = true; - if (anActiveWidget->attributeID() == anAttributeOnStart) { + if (anActiveWidget && anActiveWidget->attributeID() == anAttributeOnStart) { // it was not deactivated by preselection processing aPanel->activateNextWidget(anActiveWidget); } @@ -501,6 +500,7 @@ bool PartSet_SketcherReentrantMgr::startInternalEdit(const std::string& thePrevi if (aPreviousAttributeWidget) { if (!aPreviousAttributeWidget->isViewerSelector()) { aPreviousAttributeWidget->focusTo(); + aPreviousAttributeWidget->emitFocusInWidget(); aPreviousAttributeWidget->selectContent(); } else { diff --git a/src/XGUI/XGUI_ActionsMgr.cpp b/src/XGUI/XGUI_ActionsMgr.cpp index d9b264bab..ae30f613d 100644 --- a/src/XGUI/XGUI_ActionsMgr.cpp +++ b/src/XGUI/XGUI_ActionsMgr.cpp @@ -241,9 +241,6 @@ QAction* XGUI_ActionsMgr::operationStateAction(OperationStateActionId theId) case AbortAll: { aResult = ModuleBase_Tools::createAction(QIcon(":pictures/button_cancel.png"), "Cancel", aParent); - if (theId == Abort) { - aResult->setShortcut(QKeySequence(Qt::Key_Escape)); - } } break; case Help: { diff --git a/src/XGUI/XGUI_OperationMgr.cpp b/src/XGUI/XGUI_OperationMgr.cpp index d7aa1f858..ac052a4d6 100644 --- a/src/XGUI/XGUI_OperationMgr.cpp +++ b/src/XGUI/XGUI_OperationMgr.cpp @@ -600,6 +600,27 @@ bool XGUI_OperationMgr::onKeyReleased(QObject *theObject, QKeyEvent* theEvent) ModuleBase_Operation* anOperation = currentOperation(); bool isAccepted = false; switch (theEvent->key()) { + case Qt::Key_Escape: { + ModuleBase_Operation* aOperation = currentOperation(); + if (aOperation) { + onAbortOperation(); + isAccepted = true; + } + } + break; + case Qt::Key_Tab: + case Qt::Key_Backtab: + { + ModuleBase_Operation* aOperation = currentOperation(); + if (aOperation) { + ModuleBase_IPropertyPanel* aPanel = anOperation->propertyPanel(); + if (aPanel) { // check for case when the operation is started but property panel is not filled + XGUI_PropertyPanel* aPP = dynamic_cast(aPanel); + aPP->focusNextPrevChild_(theEvent->key() == Qt::Key_Tab); + } + } + } + break; case Qt::Key_Return: case Qt::Key_Enter: { isAccepted = onProcessEnter(theObject); diff --git a/src/XGUI/XGUI_PropertyPanel.cpp b/src/XGUI/XGUI_PropertyPanel.cpp index be453d93c..3ccea3360 100755 --- a/src/XGUI/XGUI_PropertyPanel.cpp +++ b/src/XGUI/XGUI_PropertyPanel.cpp @@ -244,7 +244,7 @@ void XGUI_PropertyPanel::activateNextWidget(ModuleBase_ModelWidget* theWidget, QList::const_iterator anIt = myWidgets.begin(), aLast = myWidgets.end(); bool isFoundWidget = false; - ModuleBase_Tools::activateWindow(this, "XGUI_PropertyPanel::activateNextWidget()"); + //ModuleBase_Tools::activateWindow(this, "XGUI_PropertyPanel::activateNextWidget()"); for (; anIt != aLast; anIt++) { ModuleBase_ModelWidget* aCurrentWidget = *anIt; if (isFoundWidget || !theWidget) { @@ -262,6 +262,7 @@ void XGUI_PropertyPanel::activateNextWidget(ModuleBase_ModelWidget* theWidget, continue; // do not set focus if it can not be accepted, case: optional choice if (aCurrentWidget->focusTo()) { + aCurrentWidget->emitFocusInWidget(); return; } } @@ -341,7 +342,7 @@ void findDirectChildren(QWidget* theParent, QList& theWidgets, const b #endif } -bool XGUI_PropertyPanel::focusNextPrevChild(bool theIsNext) +bool XGUI_PropertyPanel::focusNextPrevChild_(bool theIsNext) { // it wraps the Tabs clicking to follow in the chain: // controls, last control, Apply, Cancel, first control, controls @@ -354,6 +355,10 @@ bool XGUI_PropertyPanel::focusNextPrevChild(bool theIsNext) qDebug(anInfo.toStdString().c_str()); } #endif + ModuleBase_ModelWidget* aFocusMWidget = ModuleBase_ModelWidget::findModelWidget(this, + aFocusWidget); + if (aFocusMWidget) + aFocusMWidget->setHighlighted(false); QWidget* aNewFocusWidget = 0; if (aFocusWidget) { @@ -398,7 +403,6 @@ bool XGUI_PropertyPanel::focusNextPrevChild(bool theIsNext) } if (aNewFocusWidget) { if (myActiveWidget) { - myActiveWidget->getControls(); bool isFirstControl = !theIsNext; QWidget* aLastFocusControl = myActiveWidget->getControlAcceptingFocus(isFirstControl); if (aFocusWidget == aLastFocusControl) { @@ -408,6 +412,11 @@ bool XGUI_PropertyPanel::focusNextPrevChild(bool theIsNext) //ModuleBase_Tools::setFocus(aNewFocusWidget, "XGUI_PropertyPanel::focusNextPrevChild()"); aNewFocusWidget->setFocus(theIsNext ? Qt::TabFocusReason : Qt::BacktabFocusReason); + + ModuleBase_ModelWidget* aNewFocusMWidget = ModuleBase_ModelWidget::findModelWidget(this, + aNewFocusWidget); + if (aNewFocusMWidget) + aNewFocusMWidget->emitFocusInWidget(); isChangedFocus = true; } return isChangedFocus; diff --git a/src/XGUI/XGUI_PropertyPanel.h b/src/XGUI/XGUI_PropertyPanel.h index 7743a0ffc..0b508df96 100644 --- a/src/XGUI/XGUI_PropertyPanel.h +++ b/src/XGUI/XGUI_PropertyPanel.h @@ -151,12 +151,13 @@ protected: /// Makes the widget active, deactivate the previous, activate and hightlight the given one /// \param theWidget a widget bool setActiveWidget(ModuleBase_ModelWidget* theWidget); - +public: /// The parent method that processes the "Tab"/"SHIF + Tab" keyboard events /// Emits a signal about focus change /// If theIsNext is true, this function searches forward, if next is false, it searches backward. - virtual bool focusNextPrevChild(bool theIsNext); - + virtual bool focusNextPrevChild_(bool theIsNext); +protected: + virtual bool focusNextPrevChild(bool theIsNext) { return true; } /// Activate the next widget in the property panel /// \param theWidget a widget. The next widget should be activated /// \param isCheckVisibility flag whether the next widget visibility is checked diff --git a/src/XGUI/XGUI_Workshop.cpp b/src/XGUI/XGUI_Workshop.cpp index 855abacc1..abbc09841 100755 --- a/src/XGUI/XGUI_Workshop.cpp +++ b/src/XGUI/XGUI_Workshop.cpp @@ -1275,7 +1275,7 @@ void XGUI_Workshop::showPropertyPanel() // in order to operation manager could process key events of the panel. // otherwise they are ignored. It happens only if the same(activateWindow) is // not happened by property panel activation(e.g. resume operation of Sketch) - ModuleBase_Tools::activateWindow(myPropertyPanel, "XGUI_Workshop::showPropertyPanel()"); + //ModuleBase_Tools::activateWindow(myPropertyPanel, "XGUI_Workshop::showPropertyPanel()"); ModuleBase_Tools::setFocus(myPropertyPanel, "XGUI_Workshop::showPropertyPanel()"); } @@ -1294,9 +1294,9 @@ void XGUI_Workshop::hidePropertyPanel() // set the focus on it. As a result, shortcuts of the application, like // are processed by this console. For example Undo actions. // It is possible that this code is to be moved to SHAPER package - QMainWindow* aDesktop = desktop(); - ModuleBase_Tools::activateWindow(aDesktop, "XGUI_Workshop::hidePropertyPanel()"); - ModuleBase_Tools::setFocus(aDesktop, "XGUI_Workshop::showPropertyPanel()"); + //QMainWindow* aDesktop = desktop(); + //ModuleBase_Tools::activateWindow(aDesktop, "XGUI_Workshop::hidePropertyPanel()"); + //ModuleBase_Tools::setFocus(aDesktop, "XGUI_Workshop::showPropertyPanel()"); } //****************************************************** -- 2.39.2