]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Issue #905 Update of invalid feature representation in property panel
authornds <nds@opencascade.com>
Wed, 9 Sep 2015 11:09:33 +0000 (14:09 +0300)
committernds <nds@opencascade.com>
Wed, 9 Sep 2015 11:10:11 +0000 (14:10 +0300)
src/ModuleBase/ModuleBase_IErrorMgr.h
src/PartSet/PartSet_WidgetSketchLabel.cpp
src/XGUI/XGUI_ErrorMgr.cpp
src/XGUI/XGUI_ErrorMgr.h
src/XGUI/XGUI_Workshop.cpp
src/XGUI/XGUI_Workshop.h
src/XGUI/XGUI_WorkshopListener.cpp
src/XGUI/XGUI_pictures.qrc
src/XGUI/pictures/button_ok_error.png [new file with mode: 0755]

index c459183335876849d08ee68f1288a1eab7fe2727..d6423725324803ded94e5da83202ec28518b7e3b 100644 (file)
@@ -30,7 +30,7 @@ public:
 
 public slots:
   /// SLOT, that is called after the operation is validated and feature validation errors have changed.
-  virtual void onValidationStateChanged() = 0;
+  //virtual void onValidationStateChanged() = 0;
 
 protected slots:
   /// Process values changed event for processing feature attribute validation errors.
index 57cca495af866d541e1ef4c8f8755d652a06c901..12d720a3c9063cce8343d5dbec2d6e0e568bc06c 100644 (file)
@@ -182,6 +182,7 @@ void PartSet_WidgetSketchLabel::updateByPlaneSelected(const ModuleBase_ViewerPrs
   //XGUI_Displayer* aDisp = workshop()->displayer();
   //aDisp->closeLocalContexts();
   emit planeSelected(plane());
+  emit valuesChanged();
   // after the plane is selected in the sketch, the sketch selection should be activated
   // it can not be performed in the sketch label widget because, we don't need to switch off
   // the selection by any label deactivation, but need to switch it off by stop the sketch
index cd4c50aa60806adab1c569c0ccc626220b06f9c6..8f380127f615b1a1c720252f6aec872d8ccfabf3 100644 (file)
 #include <ModelAPI_Validator.h>
 
 #include <QLabel>
+#include <QAction>
+#include <QApplication>
+#include <QDesktopWidget>
+#include <QDialog>
+#include <QCursor>
+#include <QHBoxLayout>
+#include <QLabel>
+
+const QString INVALID_VALUE = "invalid_action";
+
 
 XGUI_ErrorMgr::XGUI_ErrorMgr(QObject* theParent /*= 0*/)
-  : ModuleBase_IErrorMgr(theParent)
+  : ModuleBase_IErrorMgr(theParent),
+    myErrorDialog(0),
+    myErrorLabel(0)
 {
 
 }
@@ -29,6 +41,55 @@ XGUI_ErrorMgr::~XGUI_ErrorMgr()
 
 }
 
+bool XGUI_ErrorMgr::canProcessClick(QAction* theAction, const FeaturePtr& theFeature)
+{
+  QString aData = theAction->data().toString();
+
+  bool isActionEnabled = theAction->data() != INVALID_VALUE;
+
+  QString anError = getFeatureError(theFeature);
+  if (!isActionEnabled && !anError.isEmpty()) {
+    if (!myErrorDialog) {
+      myErrorDialog = new QDialog(QApplication::desktop(), Qt::Popup);
+      QHBoxLayout* aLay = new QHBoxLayout(myErrorDialog);
+      aLay->setContentsMargins(0, 0, 0, 0);
+
+      QFrame* aMarginWidget = new QFrame(myErrorDialog);
+      aMarginWidget->setFrameStyle(QFrame::Panel | QFrame::Raised);
+
+      aLay->addWidget(aMarginWidget);
+      QHBoxLayout* aMarginLay = new QHBoxLayout(aMarginWidget);
+      aMarginLay->setContentsMargins(4, 4, 4, 4);
+
+      myErrorLabel = new QLabel(aMarginWidget);
+      aMarginLay->addWidget(myErrorLabel);
+    }
+    myErrorLabel->setText(anError);
+    myErrorDialog->move(QCursor::pos());
+    myErrorDialog->show();
+  }
+  return isActionEnabled;
+}
+
+void XGUI_ErrorMgr::updateActionState(QAction* theAction, const FeaturePtr& theFeature,
+                                      const bool theEnabled)
+{
+  bool isActionEnabled = theAction->data() != INVALID_VALUE;
+  if (theEnabled  == isActionEnabled)
+    return;
+
+  theAction->setIcon(theEnabled ? QIcon(":pictures/button_ok.png"): QIcon(":pictures/button_ok_error.png"));
+  QWidget* aWidget = myPropertyPanel->headerWidget();
+  if (theEnabled) {
+    theAction->setData("");
+    aWidget->setToolTip("");
+  }
+  else {
+    theAction->setData(INVALID_VALUE);
+    aWidget->setToolTip(getFeatureError(theFeature));
+  }
+}
+
 const char* toString(ModelAPI_ExecState theExecState) 
 {
 #define TO_STRING(__NAME__) case __NAME__: return #__NAME__;
@@ -43,7 +104,7 @@ const char* toString(ModelAPI_ExecState theExecState)
 #undef TO_STRING
 }
 
-void XGUI_ErrorMgr::onValidationStateChanged()
+/*void XGUI_ErrorMgr::onValidationStateChanged()
 {
   XGUI_OperationMgr* anOperationMgr = dynamic_cast<XGUI_OperationMgr*>(sender());
   if (!anOperationMgr)
@@ -53,25 +114,33 @@ void XGUI_ErrorMgr::onValidationStateChanged()
   if (!myPropertyPanel || !aFOperation)
     return;
 
-  // get feature
   FeaturePtr aFeature = aFOperation->feature();
-  if (!aFeature.get() || !aFeature->data()->isValid())
-    return;
-
-  // set error indication
-  QString anError = QString::fromStdString(aFeature->error());
-  if (anError.isEmpty()) {
-    bool isDone = ( aFeature->data()->execState() == ModelAPI_StateDone
-                 || aFeature->data()->execState() == ModelAPI_StateMustBeUpdated );
-    if (!isDone)
-      anError = toString(aFeature->data()->execState());
-  }
+  QString anError = getFeatureError(aFeature);
 
   QWidget* aWidget = myPropertyPanel->headerWidget();
   if (aWidget) {
     aWidget->setToolTip(anError);
     aWidget->setStyleSheet(anError.isEmpty() ? "" : "background-color:pink;");
   }
+}*/
+
+QString XGUI_ErrorMgr::getFeatureError(const FeaturePtr& theFeature) const
+{
+  QString anError;
+  // get feature
+  if (!theFeature.get() || !theFeature->data()->isValid())
+    return anError;
+
+  // set error indication
+  anError = QString::fromStdString(theFeature->error());
+  if (anError.isEmpty()) {
+    bool isDone = ( theFeature->data()->execState() == ModelAPI_StateDone
+                 || theFeature->data()->execState() == ModelAPI_StateMustBeUpdated );
+    if (!isDone)
+      anError = toString(theFeature->data()->execState());
+  }
+
+  return anError;
 }
 
 void XGUI_ErrorMgr::onWidgetChanged()
index 36644798c5b87ba33f59042a9ff8c99aa9f72d3e..b370da0b7b9cc1e1f6872c9c24de27edc26fbce2 100644 (file)
 #include "XGUI.h"
 
 #include <ModuleBase_IErrorMgr.h>
+#include <ModelAPI_Feature.h>
+
+class QAction;
+class QDialog;
+class QLabel;
 
 class XGUI_EXPORT XGUI_ErrorMgr : public ModuleBase_IErrorMgr
 {
@@ -19,13 +24,36 @@ public:
   /// Virtual destructor
   virtual ~XGUI_ErrorMgr();
 
+  /// It updates the action state according to the given parameter
+  /// \param theAction an action to be changed
+  /// \param theFeature an feature that corresponds to the action
+  /// \param theEnabled an enable state
+  void updateActionState(QAction* theAction, const FeaturePtr& theFeature,
+                         const bool theEnabled);
+
+  /// Return true if the feature has no error. If there is an error and the action
+  /// is not valid, the dialog with the error information is shown.
+  /// \param theAction an action, which is checked on validity
+  /// \param theFeature a feature that provides error information
+  bool canProcessClick(QAction* theAction, const FeaturePtr& theFeature);
+
 public slots:
   /// Reimplemented from ModuleBase_ErrorMgr::onValidationStateChanged().
-  virtual void onValidationStateChanged();
+  //virtual void onValidationStateChanged();
 
 protected slots:
   /// Reimplemented from ModuleBase_ErrorMgr::onWidgetChanged().
   virtual void onWidgetChanged();
+
+private:
+  /// Returns the feature error message
+  /// \param theFeature a feature
+  /// \return the error message
+  QString getFeatureError(const FeaturePtr& theFeature) const;
+
+private:
+  QDialog* myErrorDialog; /// contains the error message
+  QLabel* myErrorLabel; /// contains an error information
 };
 
 #endif // XGUI_ErrorMgr_H
\ No newline at end of file
index ebe199c4be719929259ac2d868e2e013dc1bef7c..abe349cf27e832f596f629a828d1b703de40563a 100644 (file)
@@ -157,8 +157,8 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector)
           SLOT(onOperationCommitted(ModuleBase_Operation*)));
   connect(myOperationMgr, SIGNAL(operationAborted(ModuleBase_Operation*)), 
           SLOT(onOperationAborted(ModuleBase_Operation*)));
-  connect(myOperationMgr, SIGNAL(validationStateChanged(bool)), 
-          myErrorMgr, SLOT(onValidationStateChanged()));
+  //connect(myOperationMgr, SIGNAL(validationStateChanged(bool)), 
+  //        myErrorMgr, SLOT(onValidationStateChanged()));
 
   if (myMainWindow)
     connect(myMainWindow, SIGNAL(exitKeySequence()), SLOT(onExit()));
@@ -376,6 +376,35 @@ void XGUI_Workshop::onStartWaiting()
   }
 }
 
+//******************************************************
+void XGUI_Workshop::onAcceptActionClicked()
+{
+  QAction* anAction = dynamic_cast<QAction*>(sender());
+  XGUI_OperationMgr* anOperationMgr = operationMgr();
+  if (anOperationMgr) {
+    ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+                                                    (anOperationMgr->currentOperation());
+    if (aFOperation) {
+      if (errorMgr()->canProcessClick(anAction, aFOperation->feature()))
+        myOperationMgr->onCommitOperation();
+    }
+  }
+}
+
+//******************************************************
+void XGUI_Workshop::onValidationStateChanged(bool theEnabled)
+{
+  XGUI_OperationMgr* anOperationMgr = operationMgr();
+  if (anOperationMgr) {
+    ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+                                                    (anOperationMgr->currentOperation());
+    if (aFOperation) {
+      QAction* anAction = myActionsMgr->operationStateAction(XGUI_ActionsMgr::Accept);
+      myErrorMgr->updateActionState(anAction, aFOperation->feature(), theEnabled);
+    }
+  }
+}
+
 
 //******************************************************
 void XGUI_Workshop::deactivateActiveObject(const ObjectPtr& theObject, const bool theUpdateViewer)
@@ -941,14 +970,15 @@ void XGUI_Workshop::createDockWidgets()
   myPropertyPanel->installEventFilter(myOperationMgr);
 
   QAction* aOkAct = myActionsMgr->operationStateAction(XGUI_ActionsMgr::Accept);
-  connect(aOkAct, SIGNAL(triggered()), myOperationMgr, SLOT(onCommitOperation()));
+  connect(aOkAct, SIGNAL(triggered()), this, SLOT(onAcceptActionClicked()));
+
   QAction* aCancelAct = myActionsMgr->operationStateAction(XGUI_ActionsMgr::Abort);
   connect(aCancelAct, SIGNAL(triggered()), myOperationMgr, SLOT(onAbortOperation()));
   connect(myPropertyPanel, SIGNAL(noMoreWidgets()), myModule, SLOT(onNoMoreWidgets()));
   connect(myPropertyPanel, SIGNAL(keyReleased(QKeyEvent*)),
           myOperationMgr,  SLOT(onKeyReleased(QKeyEvent*)));
   connect(myOperationMgr,  SIGNAL(validationStateChanged(bool)),
-          aOkAct,          SLOT(setEnabled(bool)));
+          this, SLOT(onValidationStateChanged(bool)));
 }
 
 //******************************************************
index 351149422277926dee96b37af8b04e28976fe8a5..4c8b51c1fc35839bb4c6bf096694d4b3a4e8f89e 100644 (file)
@@ -92,6 +92,12 @@ Q_OBJECT
     return myOperationMgr;
   }
 
+  //! ! Returns error manager.
+  XGUI_ErrorMgr* errorMgr() const
+  {
+    return myErrorMgr;
+  }
+
   //! ! Returns an actions manager
   XGUI_ActionsMgr* actionsMgr() const
   {
@@ -357,6 +363,19 @@ private:
   /// Set waiting cursor
   void onStartWaiting();
 
+  /// Called by Ok button clicked in the property panel. Asks the error manager whether
+  /// the operation can be commited and do it if it returns true.
+  void onAcceptActionClicked();
+
+  /// Listens the corresponded signal from operation manager and send it with the Ok
+  /// action to operation manager.
+  /// \param theEnabled an enabled state for the action
+  void onValidationStateChanged(bool theEnabled);
+
+  //connect(myOperationMgr,  SIGNAL(validationStateChanged(bool)),
+  //        aOkAct,          SLOT(setEnabled(bool)));
+
+
  private:
    /// Init menu
   void initMenu();
index 82620e63501d395c270b632b05e0a4ea3edaae16..ef3c66d553691c63cfae0e23d755f1e12c7bc038 100755 (executable)
@@ -3,6 +3,7 @@
 #include "XGUI_WorkshopListener.h"
 #include "XGUI_Workshop.h"
 #include "XGUI_Displayer.h"
+#include "XGUI_ErrorMgr.h"
 #include "XGUI_OperationMgr.h"
 #include "XGUI_SalomeConnector.h"
 #include "XGUI_ActionsMgr.h"
@@ -394,16 +395,20 @@ void XGUI_WorkshopListener::onNestedStateChanged(const std::string& theFeatureId
   //one button is used for all features, which can have nested actions, so it is obtained from
   // the action manager
   QAction* anAcceptAllAction = aWorkshop->actionsMgr()->operationStateAction(XGUI_ActionsMgr::AcceptAll, NULL);
+  bool aActionToBeUpdated = false;
   if (aWorkshop->isSalomeMode()) {
     XGUI_SalomeConnector* aSalomeConnector = aWorkshop->salomeConnector();
     XGUI_ActionsMgr* anActionsMgr = aWorkshop->actionsMgr();
     if (aSalomeConnector->isNestedFeature(anActionsMgr->action(theFeatureId.c_str())))
-      anAcceptAllAction->setEnabled(theState);
+      aActionToBeUpdated = true;
   } else {
     AppElements_MainMenu* aMenuBar = aWorkshop->mainWindow()->menuObject();
     AppElements_Command* aCommand = aMenuBar->feature(theFeatureId.c_str());
     if (aCommand && aCommand->button()->additionalButtonWidget())
-      anAcceptAllAction->setEnabled(theState);
+      aActionToBeUpdated = true;
+  }
+  if (aActionToBeUpdated) {
+    anAcceptAllAction->setEnabled(theState);
   }
 }
 
index 1f53d95360ab50ac557cc9ed0ae0205426241f9a..cda15df939097dadda6d42b691a6641b1187b8dc 100644 (file)
@@ -30,6 +30,7 @@
      <file>pictures/button_cancel.png</file>
      <file>pictures/button_help.png</file>
      <file>pictures/button_ok.png</file>
+     <file>pictures/button_ok_error.png</file>
    
      <file>pictures/assembly.png</file>
      <file>pictures/delete.png</file>
diff --git a/src/XGUI/pictures/button_ok_error.png b/src/XGUI/pictures/button_ok_error.png
new file mode 100755 (executable)
index 0000000..bdb6191
Binary files /dev/null and b/src/XGUI/pictures/button_ok_error.png differ