]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Merge remote-tracking branch 'remotes/origin/occ/eliminateWarnings'
authorArtem Zhidkov <Artem.Zhidkov@opencascade.com>
Mon, 18 May 2020 03:23:20 +0000 (06:23 +0300)
committerArtem Zhidkov <Artem.Zhidkov@opencascade.com>
Mon, 18 May 2020 03:27:00 +0000 (06:27 +0300)
15 files changed:
src/Model/Model_Update.cpp
src/ModuleBase/ModuleBase_Dialog.cpp
src/ModuleBase/ModuleBase_Dialog.h
src/ModuleBase/ModuleBase_IModule.cpp
src/ModuleBase/ModuleBase_IWorkshop.h
src/ModuleBase/ModuleBase_ParamSpinBox.cpp
src/PartSet/PartSet_WidgetSketchLabel.cpp
src/SketchPlugin/CMakeLists.txt
src/SketchPlugin/SketchPlugin_Validators.cpp
src/SketchPlugin/Test/Test19101.py [new file with mode: 0644]
src/SketchSolver/SketchSolver_Group.cpp
src/XGUI/XGUI_ModuleConnector.cpp
src/XGUI/XGUI_ModuleConnector.h
src/XGUI/XGUI_Workshop.cpp
src/XGUI/XGUI_Workshop.h

index 5d0eca89ff710e9762bfb2e19c5731214ca8f02d..659b7ca9a2764290a121241f5f7ea5da83cba458 100644 (file)
@@ -913,6 +913,8 @@ void Model_Update::updateArguments(FeaturePtr theFeature) {
       std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(*aRefsIter);
     // #19071 : avoid sending of update event in cycle
     bool aWasBlocked = theFeature->data()->blockSendAttributeUpdated(true);
+    // list to keep the shared pointers while update is blocked (in messages raw poiters are used)
+    std::list<AttributeSelectionPtr> anAttrList;
     for(int a = aSel->size() - 1; a >= 0; a--) {
       std::shared_ptr<ModelAPI_AttributeSelection> aSelAttr =
         std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(aSel->value(a));
@@ -921,6 +923,7 @@ void Model_Update::updateArguments(FeaturePtr theFeature) {
         // update argument only if the referenced object is ready to use
         if (aContext.get() && !aContext->isDisabled()) {
           if (isReason(theFeature, aContext)) {
+            anAttrList.push_back(aSelAttr);
             if (!aSelAttr->update()) {
               bool isObligatory = !aFactory->isNotObligatory(
                 theFeature->getKind(), theFeature->data()->id(aSel)) &&
index 18766dd99a870a07ce9934ab7ff2099c8a4ce511..0b1d254592c00be097ff02da5d17380f1848e14f 100644 (file)
 #include <QPushButton>
 
 
-ModuleBase_Dialog::ModuleBase_Dialog(ModuleBase_IWorkshop* theParent, const QString& theId,
-                                     const std::string& theDescription) :
+ModuleBase_Dialog::ModuleBase_Dialog(ModuleBase_IWorkshop* theParent,
+  const std::string& theDescription) :
   QDialog(theParent->desktop(),
     Qt::Dialog | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowCloseButtonHint),
-  myId(theId),
   myDescription(theDescription),
   myWorkshop(theParent),
   myActiveWidget(0)
 {
+  Config_WidgetAPI aApi(myDescription, "");
+  myId = aApi.getProperty("id");
+
+  std::shared_ptr<Config_FeatureMessage> aFeatureInfo = myWorkshop->featureInfo(myId.c_str());
+  myHelpPage = aFeatureInfo->helpFileName();
+
   ModuleBase_WidgetFactory aFactory(myDescription, myWorkshop);
   QString aTitle = ModuleBase_Tools::translate("ModuleBase_Dialog",
       aFactory.widgetAPI()->getProperty(FEATURE_TEXT));
@@ -56,7 +61,7 @@ ModuleBase_Dialog::ModuleBase_Dialog(ModuleBase_IWorkshop* theParent, const QStr
   SessionPtr aMgr = ModelAPI_Session::get();
   std::shared_ptr<ModelAPI_Document> aDoc = aMgr->activeDocument();
 
-  myFeature = aDoc->addFeature(myId.toStdString());
+  myFeature = aDoc->addFeature(myId);
   if (!myFeature.get())
     return;
   Events_Loop::loop()->flush(Events_Loop::eventByName(EVENT_OBJECT_CREATED));
@@ -65,7 +70,6 @@ ModuleBase_Dialog::ModuleBase_Dialog(ModuleBase_IWorkshop* theParent, const QStr
   QVBoxLayout* aLayout = new QVBoxLayout(this);
   aLayout->setContentsMargins(0, 0, 0, 0);
   aLayout->setSpacing(1);
-  //setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
 
   ModuleBase_PageWidget* aPage = new ModuleBase_PageWidget(this);
   aLayout->addWidget(aPage);
@@ -81,14 +85,17 @@ ModuleBase_Dialog::ModuleBase_Dialog(ModuleBase_IWorkshop* theParent, const QStr
   ModuleBase_Tools::adjustMargins(aBtnLayout);
 
   myButtonsBox = new QDialogButtonBox(
-    QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, aFrame);
+    QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Help,
+    Qt::Horizontal, aFrame);
   aBtnLayout->addWidget(myButtonsBox);
 
   myButtonsBox->button(QDialogButtonBox::Ok)->setIcon(QIcon(":pictures/button_ok.png"));
   myButtonsBox->button(QDialogButtonBox::Cancel)->setIcon(QIcon(":pictures/button_cancel.png"));
+  myButtonsBox->button(QDialogButtonBox::Help)->setIcon(QIcon(":pictures/button_help.png"));
 
   connect(myButtonsBox, SIGNAL(accepted()), this, SLOT(accept()));
   connect(myButtonsBox, SIGNAL(rejected()), this, SLOT(reject()));
+  connect(myButtonsBox, SIGNAL(helpRequested()), this, SLOT(onHelpRequest()));
 
   foreach (ModuleBase_ModelWidget* aWidget, myWidgets) {
     initializeWidget(aWidget);
@@ -122,3 +129,8 @@ void ModuleBase_Dialog::accept()
   }
   QDialog::accept();
 }
+
+void ModuleBase_Dialog::onHelpRequest()
+{
+  myWorkshop->showHelpPage(myHelpPage.c_str());
+}
index 7ef0b6e6bb36e953d636286eba7c0b767930c3d9..46f0e7068b12aa2e0c4649a341b15813f8e707e3 100644 (file)
@@ -44,8 +44,7 @@ public:
   /// \param theParent a workshop object instance
   /// \param theId an Id of a feature
   /// \param theDescription an XML description of the feature
-  ModuleBase_Dialog(ModuleBase_IWorkshop* theParent, const QString& theId,
-                    const std::string& theDescription);
+  ModuleBase_Dialog(ModuleBase_IWorkshop* theParent, const std::string& theDescription);
 
   /// Redefinition of virtual method
   virtual void accept();
@@ -54,12 +53,15 @@ protected:
   /// Redefinition of virtual method
   virtual void showEvent(QShowEvent* theEvent);
 
+private slots:
+  void onHelpRequest();
+
 private:
   /// Initialising of the widget
   void initializeWidget(ModuleBase_ModelWidget* theWidget);
 
   /// Id of the feature
-  QString myId;
+  std::string myId;
 
   /// XML description of the feature
   std::string myDescription;
@@ -78,6 +80,8 @@ private:
 
   /// Buttons of the dialog
   QDialogButtonBox* myButtonsBox;
+
+  std::string myHelpPage;
 };
 
 #endif
index 9b584ab63961c1b5c9de35fccd2fbec9f31ce7fc..082df98c177a874bf94e2920b561bf9ace97025d 100644 (file)
@@ -95,7 +95,7 @@ void ModuleBase_IModule::launchModal(const QString& theCmdId)
   SessionPtr aMgr = ModelAPI_Session::get();
   aMgr->startOperation(theCmdId.toStdString());
 
-  ModuleBase_Dialog aDlg(myWorkshop, theCmdId, aXmlCfg);
+  ModuleBase_Dialog aDlg(myWorkshop, aXmlCfg);
   if (aDlg.exec() == QDialog::Accepted)
     aMgr->finishOperation();
   else
index c49dda4ff947cd8ca49ce3b55dede6cc36f64d26..d7480c10e9c986f9160f6a17a657a69e9694735c 100644 (file)
@@ -161,6 +161,9 @@ Q_OBJECT
   //! Returns current state of cancel button
   virtual bool isCancelEnabled() const = 0;
 
+  //! Show help of a current operation
+  virtual void showHelpPage(const QString& thePage) const = 0;
+
 signals:
   /// Signal selection changed.
   void selectionChanged();
index 5d48ad9a81edab5bab1f47f165fdf44cb4f56bb2..e9c87937401bdfde2d6b04245493b1e10d93b957 100644 (file)
@@ -81,6 +81,17 @@ void ModuleBase_ParamSpinBox::setCompletionList(QStringList& theList)
   theList.removeDuplicates();
   theList.sort();
   myCompleterModel->setStringList(theList);
+
+  QAbstractItemView* aPopup = myCompleter->popup();
+  QFontMetrics aMetric = aPopup->fontMetrics();
+  int aWidth = 0;
+  QRect aRect;
+  foreach(QString aStr, theList) {
+    aRect = aMetric.boundingRect(aStr);
+    if (aRect.width() > aWidth)
+      aWidth = aRect.width();
+  }
+  aPopup->setMinimumWidth(aWidth + 25);
 }
 
 /*!
index a076560ada3a4e099a2183e85da3e77982f0b7af..234a7699d3097e8013fd3e31e789a7d141876d1e 100644 (file)
@@ -39,6 +39,7 @@
 #include <ModelAPI_Tools.h>
 #include <ModelAPI_AttributeString.h>
 #include <ModelAPI_Events.h>
+#include <ModelAPI_ResultConstruction.h>
 
 #include <ModuleBase_Operation.h>
 #include <ModuleBase_ViewerPrs.h>
@@ -505,48 +506,61 @@ bool PartSet_WidgetSketchLabel::fillSketchPlaneBySelection(const ModuleBase_View
 {
   bool isOwnerSet = false;
 
-  const GeomShapePtr& aShape = thePrs->shape();
+  GeomShapePtr aShape = thePrs->shape();
   std::shared_ptr<GeomAPI_Dir> aDir;
 
+  if (!aShape.get() || aShape->isNull()) {
+    if (thePrs->object() && (feature() != thePrs->object())) {
+      if (thePrs->object()->groupName() == ModelAPI_ResultConstruction::group()) {
+        ResultConstructionPtr aConstruction =
+          std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(thePrs->object());
+        if (aConstruction.get())
+          aShape = aConstruction->shape();
+      }
+    }
+  }
+
   if (aShape.get() && !aShape->isNull()) {
     const TopoDS_Shape& aTDShape = aShape->impl<TopoDS_Shape>();
     aDir = setSketchPlane(aTDShape);
     isOwnerSet = aDir.get();
   }
   if (thePrs->object() && (feature() != thePrs->object())) {
-    FeaturePtr aFeature = ModelAPI_Feature::feature(thePrs->object());
-    DataPtr aData = feature()->data();
-    AttributeSelectionPtr aSelAttr =
-      std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
-      (aData->attribute(SketchPlugin_SketchEntity::EXTERNAL_ID()));
-    if (aSelAttr.get()) {
-      ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(thePrs->object());
-      if (aRes.get()) {
-        GeomShapePtr aShapePtr;
-        if (!aShape.get() || aShape->isNull()) {  // selection happens in the OCC viewer
-          aShapePtr = ModelAPI_Tools::shape(aRes);
-        }
-        else { // selection happens in OB browser
-          aShapePtr = aShape;
-        }
-        if (aShapePtr.get() && aShapePtr->isFace()) {
-          const TopoDS_Shape& aTDShape = aShapePtr->impl<TopoDS_Shape>();
-          setSketchPlane(aTDShape);
-          aSelAttr->setValue(aRes, aShapePtr);
-          isOwnerSet = true;
-        }
-      }
-      else {
-        aSelAttr->setValue(aFeature, GeomShapePtr());
-        GeomShapePtr aSelShape = aSelAttr->value();
-        if (!aSelShape.get() && aSelAttr->contextFeature().get() &&
-          aSelAttr->contextFeature()->firstResult().get()) {
-          aSelShape = aSelAttr->contextFeature()->firstResult()->shape();
+    if (thePrs->object()->groupName() != ModelAPI_ResultConstruction::group()) {
+      FeaturePtr aFeature = ModelAPI_Feature::feature(thePrs->object());
+      DataPtr aData = feature()->data();
+      AttributeSelectionPtr aSelAttr =
+        std::dynamic_pointer_cast<ModelAPI_AttributeSelection>
+        (aData->attribute(SketchPlugin_SketchEntity::EXTERNAL_ID()));
+      if (aSelAttr.get()) {
+        ResultPtr aRes = std::dynamic_pointer_cast<ModelAPI_Result>(thePrs->object());
+        if (aRes.get()) {
+          GeomShapePtr aShapePtr;
+          if (!aShape.get() || aShape->isNull()) {  // selection happens in the OCC viewer
+            aShapePtr = ModelAPI_Tools::shape(aRes);
+          }
+          else { // selection happens in OB browser
+            aShapePtr = aShape;
+          }
+          if (aShapePtr.get() && aShapePtr->isFace()) {
+            const TopoDS_Shape& aTDShape = aShapePtr->impl<TopoDS_Shape>();
+            setSketchPlane(aTDShape);
+            aSelAttr->setValue(aRes, aShapePtr);
+            isOwnerSet = true;
+          }
         }
-        if (aSelShape.get() && aSelShape->isPlanar()) {
-          const TopoDS_Shape& aTDShape = aSelShape->impl<TopoDS_Shape>();
-          setSketchPlane(aTDShape);
-          isOwnerSet = true;
+        else {
+          aSelAttr->setValue(aFeature, GeomShapePtr());
+          GeomShapePtr aSelShape = aSelAttr->value();
+          if (!aSelShape.get() && aSelAttr->contextFeature().get() &&
+            aSelAttr->contextFeature()->firstResult().get()) {
+            aSelShape = aSelAttr->contextFeature()->firstResult()->shape();
+          }
+          if (aSelShape.get() && aSelShape->isPlanar()) {
+            const TopoDS_Shape& aTDShape = aSelShape->impl<TopoDS_Shape>();
+            setSketchPlane(aTDShape);
+            isOwnerSet = true;
+          }
         }
       }
     }
index 23e34d4d5bee873c4b365b3bba698479941cdb44..0a4a01218f701def724beb73a58fc4fdd1eeb0be 100644 (file)
@@ -227,6 +227,7 @@ ADD_UNIT_TESTS(
   Test3154.py
   Test3170.py
   Test19089.py
+  Test19101.py
   TestArcBehavior.py
   TestBSplineAddPole.py
   TestChangeSketchPlane1.py
index 078c87f76371d66131fd28700ba381a17a6f2daa..22c0d2fe16da2e632babd286fee65c9613e571ec 100644 (file)
@@ -1157,20 +1157,21 @@ bool SketchPlugin_ProjectionValidator::isValid(const AttributePtr& theAttribute,
 
   AttributeSelectionPtr aFeatureAttr =
       std::dynamic_pointer_cast<ModelAPI_AttributeSelection>(theAttribute);
+  std::shared_ptr<GeomAPI_Vertex> aVertex;
   std::shared_ptr<GeomAPI_Edge> anEdge;
   std::shared_ptr<SketchPlugin_Feature> aSketchFeature;
   if (aFeatureAttr.get()) {
     GeomShapePtr aVal = aFeatureAttr->value();
     ResultPtr aRes = aFeatureAttr->context();
     if (aVal && aVal->isVertex())
-      return true; // vertex is always could be projected
-    if (aVal && aVal->isEdge()) {
-      anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aFeatureAttr->value()));
+      aVertex = std::shared_ptr<GeomAPI_Vertex>(new GeomAPI_Vertex(aVal));
+    else if (aVal && aVal->isEdge()) {
+      anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aVal));
     } else if(aRes && aRes->shape()) {
       if (aRes->shape()->isVertex())
-        return true; // vertex is always could be projected
+        aVertex = std::shared_ptr<GeomAPI_Vertex>(new GeomAPI_Vertex(aRes->shape()));
       else if (aRes->shape()->isEdge())
-        anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aFeatureAttr->context()->shape()));
+        anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(aRes->shape()));
     }
 
     // try to convert result to sketch feature
@@ -1179,7 +1180,7 @@ bool SketchPlugin_ProjectionValidator::isValid(const AttributePtr& theAttribute,
         std::dynamic_pointer_cast<SketchPlugin_Feature>(ModelAPI_Feature::feature(aRes));
     }
   }
-  if (!anEdge) {
+  if (!aVertex && !anEdge) {
     theError = "The attribute %1 should be an edge or vertex";
     theError.arg(theAttribute->id());
     return false;
@@ -1211,7 +1212,9 @@ bool SketchPlugin_ProjectionValidator::isValid(const AttributePtr& theAttribute,
   std::shared_ptr<GeomAPI_Pnt> anOrigin = aPlane->location();
 
   bool aValid = true;
-  if (anEdge->isLine()) {
+  if (aVertex)
+    aValid = true; // vertex is always could be projected
+  else if (anEdge->isLine()) {
     std::shared_ptr<GeomAPI_Lin> aLine = anEdge->line();
     std::shared_ptr<GeomAPI_Dir> aLineDir = aLine->direction();
     double aDot = fabs(aNormal->dot(aLineDir));
diff --git a/src/SketchPlugin/Test/Test19101.py b/src/SketchPlugin/Test/Test19101.py
new file mode 100644 (file)
index 0000000..a44bbc8
--- /dev/null
@@ -0,0 +1,44 @@
+# Copyright (C) 2020  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
+#
+
+from salome.shaper import model
+
+model.begin()
+partSet = model.moduleDocument()
+Part_1 = model.addPart(partSet)
+Part_1_doc = Part_1.document()
+Box_1 = model.addBox(Part_1_doc, 10, 10, 10)
+Sketch_1 = model.addSketch(Part_1_doc, model.selection("FACE", "Box_1_1/Top"))
+SketchLine_1 = Sketch_1.addLine(3.455185109181585, 2.504529791754867, 6.714574768930328, 7.155950452021305)
+SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "[Box_1_1/Front][Box_1_1/Right][Box_1_1/Top]"), True)
+SketchPoint_1 = SketchProjection_1.createdFeature()
+SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "[Box_1_1/Left][Box_1_1/Top]"), True)
+SketchLine_2 = SketchProjection_2.createdFeature()
+SketchProjection_3 = Sketch_1.addProjection(model.selection("EDGE", "Sketch_1/SketchLine_1"), True)
+SketchProjection_4 = Sketch_1.addProjection(model.selection("VERTEX", "Sketch_1/SketchLine_1_EndVertex"), True)
+model.do()
+
+model.end()
+
+from ModelAPI import *
+validators = ModelAPI_Session.get().validators()
+assert(validators.validate(SketchProjection_1.feature()))
+assert(validators.validate(SketchProjection_2.feature()))
+assert(not validators.validate(SketchProjection_3.feature()))
+assert(not validators.validate(SketchProjection_4.feature()))
index 82bf9a1f7e3973da8716c346b12edfb64162a3b4..3ea7ade275d687c30a4c4f64ee4fbbcfe8a2313b 100644 (file)
@@ -335,8 +335,9 @@ bool SketchSolver_Group::resolveConstraints()
         }
       }
 
-      // show degrees of freedom only if the degenerated geometry appears
-      if (aResult == PlaneGCSSolver_Solver::STATUS_DEGENERATED)
+      // show degrees of freedom only if the degenerated geometry appears,
+      // or if DoF is not computed yet
+      if (aResult == PlaneGCSSolver_Solver::STATUS_DEGENERATED || myDOF < 0)
         computeDoF();
     }
 
index 8ea40ee6aa25902c6df59ab9434e47c859e2bfee..c024b7447bbf012c232667fe3ddd1b780de01cd2 100644 (file)
@@ -260,3 +260,8 @@ bool XGUI_ModuleConnector::isCancelEnabled() const
   }
   return isEnabled;
 }
+
+void XGUI_ModuleConnector::showHelpPage(const QString& thePage) const
+{
+  workshop()->showHelpPage(thePage);
+}
index f21b6e803b5a75c4f87b1fd2cab54b3263138638..f504abfa19c089556f99ac6a92edc0e6e0ef9567 100644 (file)
@@ -145,6 +145,9 @@ Q_OBJECT
   //! Returns current state of cancel button
   virtual bool isCancelEnabled() const;
 
+  //! Show help of a current operation
+  virtual void showHelpPage(const QString& thePage) const;
+
 private:
   QObjectPtrList activeObjects(const QObjectPtrList& theObjList) const;
 
index 415cd1635b75b920fe89b10abf10b8f44404b67c..bca2c85b32608781aa20c1b6fee858db37f718b3 100644 (file)
@@ -636,16 +636,22 @@ void XGUI_Workshop::onPreviewActionClicked()
 
 
 //******************************************************
-void XGUI_Workshop::onHelpActionClicked()
+void XGUI_Workshop::onHelpActionClicked() const
 {
   XGUI_OperationMgr* anOperationMgr = operationMgr();
   if (anOperationMgr) {
     ModuleBase_Operation* aOperation = anOperationMgr->currentOperation();
     if (aOperation) {
-      QString aHelpPage = aOperation->helpFileName();
-      if (!aHelpPage.isEmpty()) {
-        QString aDocDir;
-        const QChar aSep = QDir::separator();
+      showHelpPage(aOperation->helpFileName());
+    }
+  }
+}
+
+void XGUI_Workshop::showHelpPage(const QString& thePage) const
+{
+  if (!thePage.isEmpty()) {
+    QString aDocDir;
+    const QChar aSep = QDir::separator();
 //        QString platform;
 //        SUIT_ResourceMgr* aResMgr = ModuleBase_Preferences::resourceMgr();
 //#ifdef WIN32
@@ -656,21 +662,19 @@ void XGUI_Workshop::onHelpActionClicked()
 //        QString aBrowserName = aResMgr->stringValue("ExternalBrowser", platform);
 
 #ifdef HAVE_SALOME
-        QString aDir(getenv("SHAPER_ROOT_DIR"));
-        if (!aDir.isEmpty()) {
-          aDocDir = aDir + aSep + "share" + aSep + "doc" + aSep +
-            "salome" + aSep + "gui" + aSep + "SHAPER";
-        }
+    QString aDir(getenv("SHAPER_ROOT_DIR"));
+    if (!aDir.isEmpty()) {
+      aDocDir = aDir + aSep + "share" + aSep + "doc" + aSep +
+        "salome" + aSep + "gui" + aSep + "SHAPER";
+    }
 #else
-        QString aDir(getenv("CADBUILDER_ROOT_DIR"));
-        aDocDir = aDir + aSep + "doc" + aSep + "gui";
+    QString aDir(getenv("CADBUILDER_ROOT_DIR"));
+    aDocDir = aDir + aSep + "doc" + aSep + "gui";
 #endif
-        QString aFileName = aDocDir + aSep + aHelpPage;
-        if (QFile::exists(aFileName)) {
-          QUrl aUrl = QUrl::fromLocalFile(aFileName);
-          QDesktopServices::openUrl(aUrl);
-        }
-      }
+    QString aFileName = aDocDir + aSep + thePage;
+    if (QFile::exists(aFileName)) {
+      QUrl aUrl = QUrl::fromLocalFile(aFileName);
+      QDesktopServices::openUrl(aUrl);
     }
   }
 }
@@ -1216,14 +1220,17 @@ void XGUI_Workshop::processUndoRedo(const ModuleBase_ActionType theActionType, i
   // until redo of all possible objects happens
   bool isUpdateEnabled = myDisplayer->enableUpdateViewer(false);
 
+  int aTimes = theTimes;
   SessionPtr aMgr = ModelAPI_Session::get();
   if (aMgr->isOperation()) {
     XGUI_OperationMgr* aOpMgr = operationMgr();
     /// this is important for nested operations
     /// when sketch operation is active, this condition is false and
     /// the sketch operation is not aborted
-    if (aOpMgr->canStopOperation(aOpMgr->currentOperation()))
+    if (aOpMgr->canStopOperation(aOpMgr->currentOperation())) {
       aOpMgr->abortOperation(aOpMgr->currentOperation());
+      aTimes--;
+    }
     else
     {
       myDisplayer->enableUpdateViewer(isUpdateEnabled);
@@ -1234,7 +1241,7 @@ void XGUI_Workshop::processUndoRedo(const ModuleBase_ActionType theActionType, i
   std::list<std::string> anActionList = theActionType == ActionUndo ? aMgr->undoList()
     : aMgr->redoList();
   std::list<std::string>::const_iterator aIt = anActionList.cbegin();
-  for (int i = 0; (i < theTimes) && (aIt != anActionList.cend()); ++i, ++aIt) {
+  for (int i = 0; (i < aTimes) && (aIt != anActionList.cend()); ++i, ++aIt) {
     if (theActionType == ActionUndo)
       aMgr->undo();
     else
index 7b69f0341739aca87b8a6634dd3ce0c15c796245..c503990f9671babb5fb79093e419705d31d0d3f5 100644 (file)
@@ -335,6 +335,8 @@ Q_OBJECT
   /// The method updates a Color Scale object in the viewer
   void updateColorScaleVisibility();
 
+  void showHelpPage(const QString& thePage) const;
+
 signals:
   /// Emitted when selection happens in Salome viewer
   void salomeViewerSelection();
@@ -494,7 +496,7 @@ private:
   void onPreviewActionClicked();
 
   /// Called on help button clicked in the property panel.
-  void onHelpActionClicked();
+  void onHelpActionClicked() const;
 
   //! The slot is called only once on resizing of Object Browser
   void onDockSizeChanged();