]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Issue #2250 Fatal error or sigsegv when I use the "Echap" key.
authornds <nds@opencascade.com>
Tue, 26 Sep 2017 10:41:01 +0000 (13:41 +0300)
committernds <nds@opencascade.com>
Tue, 26 Sep 2017 10:41:40 +0000 (13:41 +0300)
additional correction for case: Escape click in Abort operation dialog did not close this dialog.

src/ModuleBase/ModuleBase_ModelWidget.cpp
src/ModuleBase/ModuleBase_ModelWidget.h
src/ModuleBase/ModuleBase_WidgetEditor.cpp
src/ModuleBase/ModuleBase_WidgetEditor.h
src/XGUI/XGUI_MenuMgr.cpp
src/XGUI/XGUI_OperationMgr.cpp
src/XGUI/XGUI_OperationMgr.h

index fcba4e0c4b194ca241bfa5dfdd2eee8e9e8897f1..7e914b1bc9f9d42bdf5b7d2bdca3004e2c476329 100644 (file)
@@ -425,6 +425,11 @@ bool ModuleBase_ModelWidget::processEnter()
   return false;
 }
 
+bool ModuleBase_ModelWidget::processEscape()
+{
+  return false;
+}
+
 bool ModuleBase_ModelWidget::processDelete()
 {
   // we consider that model objects eats delete key in order to
index 29dc34733703637174f7e38f1a32ced3624fb384..8a8dfdf7b13ec15952968c59a8a7d2e91f606d9d 100644 (file)
@@ -243,6 +243,9 @@ Q_OBJECT
   /// 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();
 
index e70fcbb8137fecfcc11e867a21897812bb7ca5b2..6fcd6cf784993c810673e7768dfa7223868b3d0f 100644 (file)
@@ -36,6 +36,7 @@
 #include <GeomDataAPI_Point2D.h>
 
 #include <QApplication>
+#include <QKeyEvent>
 #include <QLineEdit>
 #include <QMenu>
 #include <QWidget>
 #include <QDialog>
 #include <QLayout>
 
+// Dialog is redefined to avoid Escape key processing
+class ModuleBase_EditorDialog : public QDialog
+{
+public:
+  ModuleBase_EditorDialog(QWidget* theParent, Qt::WindowFlags theFlags)
+    : QDialog(theParent, theFlags) {}
+  ~ModuleBase_EditorDialog() {}
+
+protected:
+  // Do nothing if key pressed because it is processing on operation manager level
+  virtual void keyPressEvent(QKeyEvent* theEvent) {
+    if (theEvent->key() == Qt::Key_Escape)
+        return;
+    QDialog::keyPressEvent(theEvent);
+  }
+};
+
 ModuleBase_WidgetEditor::ModuleBase_WidgetEditor(QWidget* theParent,
                                                  const Config_WidgetAPI* theData)
 : ModuleBase_WidgetDoubleValue(theParent, theData),
@@ -61,7 +79,7 @@ bool ModuleBase_WidgetEditor::editedValue(double& outValue, QString& outText)
 {
   bool isValueAccepted = false;
 
-  myEditorDialog = new QDialog(QApplication::desktop(), Qt::FramelessWindowHint);
+  myEditorDialog = new ModuleBase_EditorDialog(QApplication::desktop(), Qt::FramelessWindowHint);
 
   QHBoxLayout* aLay = new QHBoxLayout(myEditorDialog);
   aLay->setContentsMargins(2, 2, 2, 2);
@@ -146,9 +164,9 @@ bool ModuleBase_WidgetEditor::showPopupEditor(const bool theSendSignals)
   }
   ModuleBase_Tools::setFocus(mySpinBox, "ModuleBase_WidgetEditor::editedValue");
   mySpinBox->selectAll();
-
-  if (theSendSignals && !myIsEditing)
-    emit enterClicked(this);
+  // enter is processed, so we need not anymore emit clicked signal
+  //if (theSendSignals && !myIsEditing && isValueAccepted)
+  //  emit enterClicked(this);
 
   return isValueAccepted;
 }
@@ -168,3 +186,13 @@ bool ModuleBase_WidgetEditor::processEnter()
 
   return ModuleBase_WidgetDoubleValue::processEnter();
 }
+
+bool ModuleBase_WidgetEditor::processEscape()
+{
+  if (myEditorDialog) {
+    myEditorDialog->reject();
+    return true;
+  }
+
+  return ModuleBase_WidgetDoubleValue::processEscape();
+}
index 84fb045d6f2589f10a56a49325e7e3681266d0f6..809ccd4ec94ee38ed5e66db241608e92179a3f2a 100644 (file)
@@ -71,6 +71,9 @@ Q_OBJECT
   /// Returns true if the event is processed.
   virtual bool processEnter();
 
+  /// Reject the current editor dialog if it is shown and returns true.
+  virtual bool processEscape();
+
 private:
   /// Show editor
   /// \param theOutValue a result value
index fdb129faa151144ab62b56f27fda7406159d83d4..42253d5df696ed9fda86869f130d9ded9056275b 100755 (executable)
@@ -170,7 +170,7 @@ void XGUI_MenuMgr::createFeatureActions()
         aGroup->featuresInfo();
       std::list<std::shared_ptr<Config_FeatureMessage> >::const_iterator aFIt =
         aFeaturesInfo.begin(), aFLast = aFeaturesInfo.end();
-      int aFSize = aFeaturesInfo.size();
+      size_t aFSize = aFeaturesInfo.size();
       for(int i = 0; aFIt != aFLast; aFIt++, i++) {
         std::shared_ptr<Config_FeatureMessage> aMessage = *aFIt;
         bool aUseSeparator = i == aFSize-1;
index 42f892d212103f2d37bebefb575461c1d6c767d5..8fa2501ec7a74c2415e8db584aa9542e2cb88182 100644 (file)
@@ -90,6 +90,13 @@ public:
       else if (theEvent->type() == QEvent::KeyPress) {
         QKeyEvent* aKeyEvent = dynamic_cast<QKeyEvent*>(theEvent);
         myOperationMgr->setSHIFTPressed(aKeyEvent->modifiers() & Qt::ShiftModifier);
+        switch (aKeyEvent->key()) {
+          case Qt::Key_Escape:
+            isAccepted = myOperationMgr->onKeyPressed(theObject, aKeyEvent);
+          break;
+          default:
+            break;
+        }
       }
     }
     if (!isAccepted)
@@ -104,7 +111,7 @@ private:
 
 XGUI_OperationMgr::XGUI_OperationMgr(QObject* theParent,
                                      ModuleBase_IWorkshop* theWorkshop)
-: QObject(theParent), myWorkshop(theWorkshop), mySHIFTPressed(false)
+: QObject(theParent), myWorkshop(theWorkshop), mySHIFTPressed(false), myActiveMessageBox(0)
 {
   /// we need to install filter to the application in order to react to 'Delete' key button
   /// this key can not be a short cut for a corresponded action because we need to set
@@ -233,11 +240,9 @@ bool XGUI_OperationMgr::abortAllOperations()
       aResult = false;
   }
   else {
-    aResult = QMessageBox::question(qApp->activeWindow(),
-                                    tr("Abort operation"),
-                                    tr("All active operations will be aborted."),
-                                    QMessageBox::Ok | QMessageBox::Cancel,
-                                    QMessageBox::Cancel) == QMessageBox::Ok;
+    myActiveMessageBox = createMessageBox(tr("All active operations will be aborted."));
+    aResult = myActiveMessageBox->exec() == QMessageBox::Ok;
+    myActiveMessageBox = 0;
     while(aResult && hasOperation()) {
       abortOperation(currentOperation());
     }
@@ -312,12 +317,11 @@ bool XGUI_OperationMgr::canStopOperation(ModuleBase_Operation* theOperation)
     return true;
   if (theOperation && theOperation->isModified()) {
     QString aMessage = tr("%1 operation will be aborted.").arg(theOperation->id());
-    int anAnswer = QMessageBox::question(qApp->activeWindow(),
-                                         tr("Abort operation"),
-                                         aMessage,
-                                         QMessageBox::Ok | QMessageBox::Cancel,
-                                         QMessageBox::Cancel);
-    return anAnswer == QMessageBox::Ok;
+
+    myActiveMessageBox = createMessageBox(aMessage);
+    int anAnswer = myActiveMessageBox->exec() == QMessageBox::Ok;
+    myActiveMessageBox = 0;
+    return anAnswer;
   }
   return true;
 }
@@ -610,14 +614,6 @@ 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:
     {
@@ -669,6 +665,38 @@ bool XGUI_OperationMgr::onKeyReleased(QObject *theObject, QKeyEvent* theEvent)
   return isAccepted;
 }
 
+bool XGUI_OperationMgr::onKeyPressed(QObject *theObject, QKeyEvent* theEvent)
+{
+  // Let the manager decide what to do with the given key combination.
+  ModuleBase_Operation* anOperation = currentOperation();
+  bool isAccepted = false;
+  switch (theEvent->key()) {
+    case Qt::Key_Escape: {
+      // processing in message box
+      if (myActiveMessageBox)
+      {
+        myActiveMessageBox->reject();
+        isAccepted = true;
+      }
+      // processing in the active widget
+      ModuleBase_Operation* aOperation = currentOperation();
+      if (!isAccepted && aOperation) {
+        ModuleBase_IPropertyPanel* aPanel = aOperation->propertyPanel();
+        ModuleBase_ModelWidget* anActiveWgt = aPanel->activeWidget();
+        if (anActiveWgt)
+          isAccepted = anActiveWgt && anActiveWgt->processEscape();
+      }
+      // default Escape button functionality
+      if (!isAccepted && aOperation) {
+        onAbortOperation();
+        isAccepted = true;
+      }
+    }
+    break;
+  }
+  return isAccepted;
+}
+
 bool XGUI_OperationMgr::onProcessEnter(QObject* theObject)
 {
   bool isAccepted = false;
@@ -797,3 +825,14 @@ bool XGUI_OperationMgr::isChildObject(const QObject* theObject, const QObject* t
   }
   return isPPChild;
 }
+
+QMessageBox* XGUI_OperationMgr::createMessageBox(const QString& theMessage)
+{
+  QMessageBox * aMessageBox = new QMessageBox(QMessageBox::Question,
+    QObject::tr("Abort operation"), theMessage, QMessageBox::Ok | QMessageBox::Cancel,
+    qApp->activeWindow());
+  aMessageBox->setDefaultButton(QMessageBox::Cancel);
+  aMessageBox->setEscapeButton(QMessageBox::No); // operation manager should process Esc key
+
+  return aMessageBox;
+}
\ No newline at end of file
index 3e6f3b099a86378a1d7250d9b24f7ee59adc0c73..ab282335eedd992c6dd2278b3f5654d12a7a8e3c 100755 (executable)
@@ -31,6 +31,7 @@
 #include <QStringList>
 
 class QKeyEvent;
+class QMessageBox;
 
 class ModuleBase_IWorkshop;
 class XGUI_Workshop;
@@ -192,6 +193,11 @@ protected: // TEMPORARY
   /// \param theEvent the mouse event
   bool onKeyReleased(QObject *theObject, QKeyEvent* theEvent);
 
+  /// SLOT, that is called by the key in the property panel is clicked.
+  /// \param theObject a sender of the event
+  /// \param theEvent the mouse event
+  bool onKeyPressed(QObject *theObject, QKeyEvent* theEvent);
+
   /// The functionaly, that should be done by delete click
   /// Fistly the active widget processes it, then workshop. If no one does not
   /// process it, do nothing
@@ -238,6 +244,12 @@ private:
   /// \param theParent a candidate to be a parent
   static bool isChildObject(const QObject* theObject, const QObject* theParent);
 
+  /// Creates question message box with OK/Cancel buttons, where Cancel is default button,
+  /// Escape is Null button
+  /// \param theMessage text of the message
+  /// \return message box
+  static QMessageBox* createMessageBox(const QString& theMessage);
+
  private:
   typedef QList<ModuleBase_Operation*> Operations;  ///< definition for a list of operations
   Operations myOperations;  ///< a stack of started operations. The active operation is on top,
@@ -245,7 +257,7 @@ private:
 
   /// Current workshop
   ModuleBase_IWorkshop* myWorkshop;
-
+  QMessageBox* myActiveMessageBox;
   XGUI_ShortCutListener* myShortCutListener;
   bool mySHIFTPressed;
 };