]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Issues #2173, #2169: processing focus in widget by SHAPER loop (instead of Qt loop...
authornds <nds@opencascade.com>
Thu, 25 May 2017 14:23:40 +0000 (17:23 +0300)
committernds <nds@opencascade.com>
Mon, 29 May 2017 11:55:29 +0000 (14:55 +0300)
13 files changed:
src/ModuleBase/ModuleBase_DoubleSpinBox.cpp
src/ModuleBase/ModuleBase_DoubleSpinBox.h
src/ModuleBase/ModuleBase_ModelWidget.cpp
src/ModuleBase/ModuleBase_ModelWidget.h
src/ModuleBase/ModuleBase_WidgetEditor.cpp
src/ModuleBase/ModuleBase_WidgetEditor.h
src/PartSet/PartSet_SketcherReentrantMgr.cpp
src/XGUI/XGUI_ActionsMgr.cpp
src/XGUI/XGUI_OperationMgr.cpp
src/XGUI/XGUI_OperationMgr.h
src/XGUI/XGUI_PropertyPanel.cpp
src/XGUI/XGUI_PropertyPanel.h
src/XGUI/XGUI_Workshop.cpp

index b5af3da5403a93398878c9f581c3f389e69242d5..d1b8efa1744000e19d8317ac5613096ead016e97 100644 (file)
@@ -59,8 +59,7 @@ const double PSEUDO_ZERO = 1.e-20;
  */
 ModuleBase_DoubleSpinBox::ModuleBase_DoubleSpinBox(QWidget* theParent, int thePrecision)
     : QDoubleSpinBox(theParent),
-      myCleared(false),
-      myIsEmitKeyPressEvent(false)
+      myCleared(false)
 {
   setLocale(ModuleBase_Tools::doubleLocale());
 
@@ -198,42 +197,6 @@ QString ModuleBase_DoubleSpinBox::removeTrailingZeroes(const QString& src) const
   return res;
 }
 
-void ModuleBase_DoubleSpinBox::keyPressEvent(QKeyEvent* theEvent)
-{
-  switch (theEvent->key()) {
-    case Qt::Key_Enter:
-    case Qt::Key_Return: {
-      // do not react to the Enter key, the property panel processes it
-      if (!myIsEmitKeyPressEvent)
-        return;
-    }
-    break;
-    default:
-      break;
-  }
-  QDoubleSpinBox::keyPressEvent(theEvent);
-}
-
-void ModuleBase_DoubleSpinBox::keyReleaseEvent(QKeyEvent* theEvent)
-{
-  switch (theEvent->key()) {
-    case Qt::Key_Enter:
-    case Qt::Key_Return: {
-      // the enter has already been processed when key is pressed,
-      // key release should not be processed in operation manager
-      if (myIsEmitKeyPressEvent) {
-        theEvent->accept();
-        emit enterReleased();
-        return;
-      }
-    }
-    break;
-    default:
-      break;
-  }
-  QDoubleSpinBox::keyReleaseEvent(theEvent);
-}
-
 /*!
  \brief Perform \a steps increment/decrement steps.
 
@@ -348,14 +311,6 @@ void ModuleBase_DoubleSpinBox::onTextChanged(const QString& )
   myCleared = false;
 }
 
-bool ModuleBase_DoubleSpinBox::enableKeyPressEvent(const bool& theEnable)
-{
-  bool aPreviousValue = myIsEmitKeyPressEvent;
-  myIsEmitKeyPressEvent = theEnable;
-
-  return aPreviousValue;
-}
-
 void ModuleBase_DoubleSpinBox::setValueEnabled(const bool& theEnable)
 {
   setReadOnly(!theEnable);
index 982b1088d264ec4a9d1d5fea2e636ae913e9c164..237bd704f757122fe70501dba8d0e466d0ba0919 100644 (file)
@@ -51,19 +51,10 @@ Q_OBJECT
   /// Validate current value
   virtual QValidator::State validate(QString&, int&) const;
 
-  /// Change enable/disable internal state to emit key press event
-  /// \param theEnable if true, the signal is emitted
-  /// \return the previous value
-  bool enableKeyPressEvent(const bool& theEnable);
-
   /// Imitation of disable control value. If theEnable is false, the control becomes
   /// read only and base color is disabled.
   void setValueEnabled(const bool& theEnable);
 
-signals:
-  /// The signal about key release on the control, that corresponds to the attribute
-  void enterReleased();
-
  protected slots:
    /// Called on text changed
   virtual void onTextChanged(const QString&);
@@ -71,11 +62,6 @@ signals:
  protected:
    /// Removes extra trailing zero symbols
   QString removeTrailingZeroes(const QString&) const;
-  /// Called on key press event
-  virtual void keyReleaseEvent(QKeyEvent* theEvent);
-
-  /// Called on key press event
-  virtual void keyPressEvent(QKeyEvent* theEvent);
 
  private:
   // boolen flag whether the key event is emitted. The default value is false
index f0be4ae9e58002dba8ddb0082c929506c0d2b1a0..01eeccac4fd3e4de52231525e369edb932662dd7 100644 (file)
@@ -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<QFocusEvent*>(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<ModuleBase_ModelWidget*>(aParent);
+    if (aModelWidget)
+      break;
+    aParent = aParent->parent();
+  }
+  return aModelWidget;
+}
index 0b409e6feedb9ce02cd32e60c6224b8e84a938e1..603e0d97a653ac04c26f8930842ce1530438e22c 100644 (file)
@@ -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();
index edaecab322fb33046cfac59a720cb7528f5b364a..2725012c32e1d31c46427612ece7a6951dc79492 100644 (file)
@@ -35,7 +35,7 @@
 ModuleBase_WidgetEditor::ModuleBase_WidgetEditor(QWidget* theParent,
                                                  const Config_WidgetAPI* theData)
 : ModuleBase_WidgetDoubleValue(theParent, theData),
-  myXPosition(-1), myYPosition(-1)
+  myXPosition(-1), myYPosition(-1), myEditorDialog(0)
 {
 }
 
@@ -47,13 +47,12 @@ bool ModuleBase_WidgetEditor::editedValue(double& outValue, QString& outText)
 {
   bool isValueAccepted = false;
 
-  QDialog aDlg(QApplication::desktop(), Qt::FramelessWindowHint);
-  QHBoxLayout* aLay = new QHBoxLayout(&aDlg);
-  aLay->setContentsMargins(2, 2, 2, 2);
+  myEditorDialog = new QDialog(QApplication::desktop(), Qt::FramelessWindowHint);
 
-  ModuleBase_ParamSpinBox* anEditor = new ModuleBase_ParamSpinBox(&aDlg);
-  anEditor->enableKeyPressEvent(true);
+  QHBoxLayout* aLay = new QHBoxLayout(myEditorDialog);
+  aLay->setContentsMargins(2, 2, 2, 2);
 
+  ModuleBase_ParamSpinBox* anEditor = new ModuleBase_ParamSpinBox(myEditorDialog);
   anEditor->setMinimum(0);
   anEditor->setMaximum(DBL_MAX);
   if (outText.isEmpty())
@@ -65,14 +64,13 @@ bool ModuleBase_WidgetEditor::editedValue(double& outValue, QString& outText)
 
   ModuleBase_Tools::setFocus(anEditor, "ModuleBase_WidgetEditor::editedValue");
   anEditor->selectAll();
-  QObject::connect(anEditor, SIGNAL(enterReleased()), &aDlg, SLOT(accept()));
 
   QPoint aPoint = QCursor::pos();
   if (myXPosition >= 0 && myYPosition >= 0)
     aPoint = QPoint(myXPosition, myYPosition);
 
-  aDlg.move(aPoint);
-  isValueAccepted = aDlg.exec() == QDialog::Accepted;
+  myEditorDialog->move(aPoint);
+  isValueAccepted = myEditorDialog->exec() == QDialog::Accepted;
   if (isValueAccepted) {
     outText = anEditor->text();
     bool isDouble;
@@ -82,6 +80,8 @@ bool ModuleBase_WidgetEditor::editedValue(double& outValue, QString& outText)
       outText = ""; // return empty string, if it's can be converted to a double
     }
   }
+  delete myEditorDialog;
+  myEditorDialog = 0;
   return isValueAccepted;
 }
 
@@ -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
@@ -141,3 +141,13 @@ void ModuleBase_WidgetEditor::setCursorPosition(const int theX, const int theY)
   myXPosition = theX;
   myYPosition = theY;
 }
+
+bool ModuleBase_WidgetEditor::processEnter()
+{
+  if (myEditorDialog) {
+    myEditorDialog->accept();
+    return true;
+  }
+
+  return ModuleBase_WidgetDoubleValue::processEnter();
+}
index 51d7eff6095781c08fcc254a43c4fcb298bdf3d6..1232a1dec55eaa5a39d4648ee59140465879307d 100644 (file)
@@ -14,6 +14,7 @@
 #include <QStringList>
 
 class ModelAPI_Feature;
+class QDialog;
 class QLineEdit;
 
 /**\class ModuleBase_WidgetEditor
@@ -53,6 +54,9 @@ Q_OBJECT
   /// \param theY the Y coordinate
   void setCursorPosition(const int theX, const int theY);
 
+  /// Returns true if the event is processed.
+  virtual bool processEnter();
+
 private:
   /// Show editor
   /// \param theOutValue a result value
@@ -68,6 +72,8 @@ private:
    QStringList myFeatureKinds;
 
    int myXPosition, myYPosition;
+
+   QDialog* myEditorDialog;
 };
 
 #endif
index 35fbf3e41c975d6e68ea328bfc30b5fc3d59027a..a9808712708913d610b983e7d3500bba44151126 100644 (file)
@@ -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 {
index d9b264babd7bef0cbb61edd5c1c9ba816374bcd9..ae30f613d3869a4f7910dfd6f1637b791e917e85 100644 (file)
@@ -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: {
index d7aa1f8583bbce65d64e014d1a5d84c839f388c4..17e7ae51f46eb799fc19eca9da2b60e29d46cdfc 100644 (file)
@@ -60,11 +60,15 @@ public:
     bool isAccepted = false;
     if (myIsActive && theEvent->type() == QEvent::KeyRelease) {
       QKeyEvent* aKeyEvent = dynamic_cast<QKeyEvent*>(theEvent);
-      if(aKeyEvent) {
+      if (aKeyEvent) {
         switch (aKeyEvent->key()) {
-          case Qt::Key_Delete: {
+          case Qt::Key_Delete:
             isAccepted = myOperationMgr->onProcessDelete(theObject);
-          }
+          break;
+          default:
+            myOperationMgr->onKeyReleased(theObject, aKeyEvent);
+            isAccepted = true;
+            break;
         }
       }
     }
@@ -171,20 +175,6 @@ ModuleBase_Operation* XGUI_OperationMgr::previousOperation(ModuleBase_Operation*
   return myOperations.at(idx - 1);
 }
 
-bool XGUI_OperationMgr::eventFilter(QObject *theObject, QEvent *theEvent)
-{
-  bool isAccepted = false;
-  if (theEvent->type() == QEvent::KeyRelease) {
-    QKeyEvent* aKeyEvent = dynamic_cast<QKeyEvent*>(theEvent);
-    if(aKeyEvent)
-      isAccepted = onKeyReleased(theObject, aKeyEvent);
-  }
-  if (!isAccepted)
-    isAccepted = QObject::eventFilter(theObject, theEvent);
-
-  return isAccepted;
-}
-
 bool XGUI_OperationMgr::startOperation(ModuleBase_Operation* theOperation)
 {
   if (hasOperation())
@@ -600,6 +590,28 @@ 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<XGUI_PropertyPanel*>(aPanel);
+          aPP->focusNextPrevChild_(theEvent->key() == Qt::Key_Tab);
+          isAccepted = true;
+        }
+      }
+    }
+    break;
     case Qt::Key_Return:
     case Qt::Key_Enter: {
       isAccepted = onProcessEnter(theObject);
@@ -640,10 +652,11 @@ bool XGUI_OperationMgr::onProcessEnter(QObject* theObject)
   if (!aOperation)
     return isAccepted;
   ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel();
+  // the next code is obsolete as we want to process Enter in property panel always
   // only property panel enter is processed in order to do not process enter in application dialogs
-  bool isPPChild = isChildObject(theObject, aPanel);
-  if (!isPPChild)
-    return isAccepted;
+  //bool isPPChild = isChildObject(theObject, aPanel);
+  //if (!isPPChild)
+  //  return isAccepted;
 
   ModuleBase_ModelWidget* anActiveWgt = aPanel->activeWidget();
   bool isAborted = false;
index c8ccf9d08a7b2d1380db13cfe2f550e6f21ca277..f1106c342b4114d61a79e1de890fa382dfd0ac69 100755 (executable)
@@ -88,11 +88,6 @@ Q_OBJECT
   /// else, or if there is no parent - returns NULL
   ModuleBase_Operation* previousOperation(ModuleBase_Operation* theOperation) const;
 
-  /// Redefinition of virtual function
-  /// \param theObject a sender of the event
-  /// \param theEvent the event
-  virtual bool eventFilter(QObject *theObject, QEvent *theEvent);
-
   /// 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
index be453d93c502db76f62425deb4b2e12d159884d9..3ccea336032f6e8cb801e770ab07d61dcdcbb851 100755 (executable)
@@ -244,7 +244,7 @@ void XGUI_PropertyPanel::activateNextWidget(ModuleBase_ModelWidget* theWidget,
 
   QList<ModuleBase_ModelWidget*>::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<QWidget*>& 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;
index 7743a0ffcb1390de50993063a7c86dcdceb05bb3..0b508df963726d6d3044313b9ac8c5cd84714cae 100644 (file)
@@ -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
index 855abacc1a005df52eb3dc1f472729e95ba88dc8..abbc09841816ef5ebd14489893ba186a1b4efbef 100755 (executable)
@@ -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()");
 }
 
 //******************************************************