Salome HOME
Copyright update 2020
[modules/shaper.git] / src / PartSet / PartSet_WidgetSketchLabel.cpp
index 14c7fbe576df29fc159cde3c618d86a771cc4900..171cf3abc09f3d1a10a6eb922479634c4d94857d 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2014-2017  CEA/DEN, EDF R&D
+// Copyright (C) 2014-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
 //
 // 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
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 //
-// See http://www.salome-platform.org/ or
-// email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
 
 #include "PartSet_WidgetSketchLabel.h"
 #include "PartSet_Tools.h"
 #include "PartSet_Module.h"
 #include "PartSet_PreviewPlanes.h"
+#include "PartSet_SketcherReentrantMgr.h"
 
 #include "SketchPlugin_SketchEntity.h"
 
 
 #include <ModelAPI_ResultBody.h>
 #include <ModelAPI_Tools.h>
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_Events.h>
 
 #include <ModuleBase_Operation.h>
 #include <ModuleBase_ViewerPrs.h>
 #include <ModuleBase_Tools.h>
 #include <ModuleBase_IModule.h>
+#include <ModuleBase_IPropertyPanel.h>
 
 #include <GeomAlgoAPI_FaceBuilder.h>
 #include <GeomAlgoAPI_ShapeTools.h>
 #include <QCheckBox>
 #include <QGroupBox>
 #include <QPushButton>
-#include <QStackedWidget>
 #include <QLineEdit>
 #include <QDoubleValidator>
+#include <QDialog>
+#include <QTimer>
 
 #ifndef DBL_MAX
 #define DBL_MAX 1.7976931348623158e+308
@@ -85,7 +89,8 @@ PartSet_WidgetSketchLabel::PartSet_WidgetSketchLabel(QWidget* theParent,
                         ModuleBase_IWorkshop* theWorkshop,
                         const Config_WidgetAPI* theData,
                         const QMap<PartSet_Tools::ConstraintVisibleState, bool>& toShowConstraints)
-: ModuleBase_WidgetValidated(theParent, theWorkshop, theData)
+: ModuleBase_WidgetValidated(theParent, theWorkshop, theData), myOpenTransaction(false),
+myIsSelection(false)
 {
   QVBoxLayout* aLayout = new QVBoxLayout(this);
   ModuleBase_Tools::zeroMargins(aLayout);
@@ -100,7 +105,7 @@ PartSet_WidgetSketchLabel::PartSet_WidgetSketchLabel(QWidget* theParent,
   // Size of the View control
   mySizeOfViewWidget = new QWidget(aFirstWgt);
   QHBoxLayout* aSizeLayout = new QHBoxLayout(mySizeOfViewWidget);
-  aSizeLayout->addWidget(new QLabel("Size of the view", mySizeOfViewWidget));
+  aSizeLayout->addWidget(new QLabel(tr("Size of the view"), mySizeOfViewWidget));
   mySizeOfView = new QLineEdit(mySizeOfViewWidget);
 
   QDoubleValidator* aValidator = new QDoubleValidator(0, DBL_MAX, 12, mySizeOfView);
@@ -109,10 +114,27 @@ PartSet_WidgetSketchLabel::PartSet_WidgetSketchLabel(QWidget* theParent,
   mySizeOfView->setValidator(aValidator);
   aSizeLayout->addWidget(mySizeOfView);
 
-  QString aText = QString::fromStdString(theData->getProperty("title"));
+  myPartSetMessage = new QDialog(this, Qt::ToolTip);
+  myPartSetMessage->setModal(false);
+  myPartSetMessage->setStyleSheet("background-color:lightyellow;");
+  QVBoxLayout* aMsgLay = new QVBoxLayout(myPartSetMessage);
+  QString aMsg = tr("The Sketch is created in PartSet.\n"
+    "It will be necessary to create a Part in order to use this sketch for body creation");
+  aMsgLay->addWidget(new QLabel(aMsg, myPartSetMessage));
+  myPartSetMessage->hide();
+
+  mySizeMessage = new QDialog(mySizeOfView, Qt::ToolTip);
+  mySizeMessage->setModal(false);
+  mySizeMessage->setStyleSheet("background-color:lightyellow;");
+  aMsgLay = new QVBoxLayout(mySizeMessage);
+  aMsg = tr("A size of Sketch view can be defined here.");
+  aMsgLay->addWidget(new QLabel(aMsg, mySizeMessage));
+  mySizeMessage->hide();
+
+  QString aText = translate(theData->getProperty("title"));
   QLabel* aLabel = new QLabel(aText, aFirstWgt);
   aLabel->setWordWrap(true);
-  QString aTooltip = QString::fromStdString(theData->getProperty("tooltip"));
+  QString aTooltip = translate(theData->getProperty("tooltip"));
   aLabel->setToolTip(aTooltip);
   aLabel->setIndent(5);
 
@@ -120,6 +142,12 @@ PartSet_WidgetSketchLabel::PartSet_WidgetSketchLabel(QWidget* theParent,
   ModuleBase_Tools::zeroMargins(aLayout);
   aLayout->addWidget(mySizeOfViewWidget);
   aLayout->addWidget(aLabel);
+
+  myRemoveExternal = new QCheckBox(tr("Remove external dependencies"), aFirstWgt);
+  myRemoveExternal->setChecked(false);
+  aLayout->addWidget(myRemoveExternal);
+  myRemoveExternal->setVisible(false);
+
   aLayout->addStretch(1);
 
   myStackWidget->addWidget(aFirstWgt);
@@ -160,6 +188,28 @@ PartSet_WidgetSketchLabel::PartSet_WidgetSketchLabel(QWidget* theParent,
     if (toShowConstraints.contains(aState))
       aShowConstraints->setChecked(toShowConstraints[aState]);
   }
+  myShowPoints = new QCheckBox(tr("Show free points"), this);
+  connect(myShowPoints, SIGNAL(toggled(bool)), this, SIGNAL(showFreePoints(bool)));
+  aLayout->addWidget(myShowPoints);
+
+  myAutoConstraints = new QCheckBox(tr("Automatic constraints"), this);
+  myAutoConstraints->setToolTip(tr("Automatic vertical and horizontal constraints"));
+  connect(myAutoConstraints, SIGNAL(toggled(bool)), this, SIGNAL(autoConstraints(bool)));
+  aLayout->addWidget(myAutoConstraints);
+
+  QPushButton* aPlaneBtn = new QPushButton(tr("Change sketch plane"), aSecondWgt);
+  connect(aPlaneBtn, SIGNAL(clicked(bool)), SLOT(onChangePlane()));
+  aLayout->addWidget(aPlaneBtn);
+
+  aLayout->addSpacing(15);
+
+  myDoFLabel = new QLabel("", aSecondWgt);
+  aLayout->addWidget(myDoFLabel);
+
+  myShowDOFBtn = new QPushButton(tr("Show remaining DoFs"), aSecondWgt);
+  aLayout->addWidget(myShowDOFBtn);
+  myShowDOFBtn->setEnabled(false);
+  connect(myShowDOFBtn, SIGNAL(clicked(bool)), SLOT(onShowDOF()));
 
   myStackWidget->addWidget(aSecondWgt);
   //setLayout(aLayout);
@@ -270,8 +320,11 @@ bool PartSet_WidgetSketchLabel::setSelectionInternal(
   else {
     // it removes the processed value from the parameters list
     ModuleBase_ViewerPrsPtr aValue = theValues.first();//.takeFirst();
-    if (!theToValidate || isValidInFilters(aValue))
+    if (!theToValidate || isValidInFilters(aValue)) {
+      myIsSelection = true;
       aDone = setSelectionCustom(aValue);
+      myIsSelection = false;
+    }
   }
 
   return aDone;
@@ -279,9 +332,17 @@ bool PartSet_WidgetSketchLabel::setSelectionInternal(
 
 void PartSet_WidgetSketchLabel::updateByPlaneSelected(const ModuleBase_ViewerPrsPtr& thePrs)
 {
+  // Nullify a temporary remembered plane
+  if (myTmpPlane.get())
+    myTmpPlane.reset();
+
   GeomPlanePtr aPlane = plane();
   if (!aPlane.get())
     return;
+
+  myPartSetMessage->hide();
+  mySizeMessage->hide();
+
   // 1. hide main planes if they have been displayed and display sketch preview plane
   myPreviewPlanes->erasePreviewPlanes(myWorkshop);
 
@@ -297,11 +358,8 @@ void PartSet_WidgetSketchLabel::updateByPlaneSelected(const ModuleBase_ViewerPrs
         isSetSizeOfView = false;
       }
     }
-    if (isSetSizeOfView)
-      aModule->sketchMgr()->previewSketchPlane()->setSizeOfView(aSizeOfView, true);
+    aModule->sketchMgr()->previewSketchPlane()->setSizeOfView(aSizeOfView, isSetSizeOfView);
     aModule->sketchMgr()->previewSketchPlane()->createSketchPlane(aSketch, myWorkshop);
-    if (isSetSizeOfView)
-      aModule->sketchMgr()->previewSketchPlane()->setSizeOfView(aSizeOfView, false);
   }
   // 2. if the planes were displayed, change the view projection
 
@@ -329,9 +387,11 @@ void PartSet_WidgetSketchLabel::updateByPlaneSelected(const ModuleBase_ViewerPrs
       }
     }
   }
-  if (aModule)
-    aModule->onViewTransformed();
-
+  if (myOpenTransaction) {
+    SessionPtr aMgr = ModelAPI_Session::get();
+    aMgr->finishOperation();
+    myOpenTransaction = false;
+  }
   // 3. Clear text in the label
   myStackWidget->setCurrentIndex(1);
   //myLabel->setText("");
@@ -346,12 +406,17 @@ void PartSet_WidgetSketchLabel::updateByPlaneSelected(const ModuleBase_ViewerPrs
   myWorkshop->selectionActivate()->updateSelectionFilters();
   myWorkshop->selectionActivate()->updateSelectionModes();
 
+  if (aModule)
+    aModule->onViewTransformed();
+
   // 6. Update sketcher actions
   XGUI_ActionsMgr* anActMgr = aWorkshop->actionsMgr();
 
   myWorkshop->updateCommandStatus();
   aWorkshop->selector()->clearSelection();
   myWorkshop->viewer()->update();
+
+  myRemoveExternal->setVisible(false);
 }
 
 std::shared_ptr<GeomAPI_Pln> PartSet_WidgetSketchLabel::plane() const
@@ -390,10 +455,24 @@ void PartSet_WidgetSketchLabel::restoreAttributeValue(const AttributePtr& theAtt
     GeomShapePtr anEmptyShape;
     aSelAttr->setValue(anEmptyResult, anEmptyShape);
   }
+  std::shared_ptr<GeomDataAPI_Point> anOrigin = std::dynamic_pointer_cast<GeomDataAPI_Point>(
+    aData->attribute(SketchPlugin_Sketch::ORIGIN_ID()));
+  anOrigin->reset();
+  std::shared_ptr<GeomDataAPI_Dir> aNormal = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+    aData->attribute(SketchPlugin_Sketch::NORM_ID()));
+  aNormal->reset();
+  std::shared_ptr<GeomDataAPI_Dir> aDirX = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
+    aData->attribute(SketchPlugin_Sketch::DIRX_ID()));
+  aDirX->reset();
 }
 
 bool PartSet_WidgetSketchLabel::setSelectionCustom(const ModuleBase_ViewerPrsPtr& thePrs)
 {
+  if (myIsSelection && myRemoveExternal->isVisible()) {
+    if (myRemoveExternal->isChecked()) {
+      myFeature->customAction(SketchPlugin_Sketch::ACTION_REMOVE_EXTERNAL());
+    }
+  }
   return fillSketchPlaneBySelection(thePrs);
 }
 
@@ -482,6 +561,17 @@ bool PartSet_WidgetSketchLabel::fillSketchPlaneBySelection(const ModuleBase_View
 
 void PartSet_WidgetSketchLabel::activateCustom()
 {
+  QWidget* aTopWidget = window();
+  if (aTopWidget)
+    aTopWidget->installEventFilter(this);
+
+  PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
+  if (aModule) {
+    bool isBlocked = myAutoConstraints->blockSignals(true);
+    myAutoConstraints->setChecked(aModule->sketchReentranceMgr()->isAutoConstraints());
+    myAutoConstraints->blockSignals(isBlocked);
+  }
+
   std::shared_ptr<GeomAPI_Pln> aPlane = plane();
   if (aPlane.get()) {
     myStackWidget->setCurrentIndex(1);
@@ -505,14 +595,63 @@ void PartSet_WidgetSketchLabel::activateCustom()
     mySizeOfViewWidget->setVisible(false);
 }
 
+void PartSet_WidgetSketchLabel::showEvent(QShowEvent* theEvent)
+{
+  ModuleBase_WidgetValidated::showEvent(theEvent);
+  QTimer::singleShot(10, this, SLOT(onShowPanel()));
+}
+
+void PartSet_WidgetSketchLabel::hideEvent(QHideEvent* theEvent)
+{
+  ModuleBase_WidgetValidated::hideEvent(theEvent);
+  if (myPartSetMessage->isVisible())
+    myPartSetMessage->hide();
+  if (mySizeMessage->isVisible())
+    mySizeMessage->hide();
+}
+
+
+void PartSet_WidgetSketchLabel::onShowPanel()
+{
+  //if (mySizeOfViewWidget->isVisible()) {
+  if (myStackWidget->currentIndex() == 0) {
+    DocumentPtr aDoc = feature()->document();
+    DocumentPtr aModDoc = ModelAPI_Session::get()->moduleDocument();
+    if (aModDoc == aDoc) {
+      myPartSetMessage->move(mapToGlobal(geometry().bottomLeft()));
+      myPartSetMessage->show();
+    }
+    if (mySizeOfViewWidget->isVisible()) {
+      QPoint aPnt = mySizeOfView->mapToGlobal(mySizeOfView->geometry().center());
+      mySizeMessage->move(aPnt);
+      mySizeMessage->show();
+    }
+  }
+}
+
 void PartSet_WidgetSketchLabel::deactivate()
 {
+  QWidget* aTopWidget = window();
+  if (aTopWidget)
+    aTopWidget->removeEventFilter(this);
+
+  if (myTmpPlane.get()) {
+    setSketchPlane(myTmpPlane);
+    myTmpPlane.reset();
+  }
+
   ModuleBase_WidgetValidated::deactivate();
   bool aHidePreview = myPreviewPlanes->isPreviewDisplayed();
   myPreviewPlanes->erasePreviewPlanes(myWorkshop);
 
   if (aHidePreview)
     myWorkshop->viewer()->update();
+
+  if (myOpenTransaction) {
+    SessionPtr aMgr = ModelAPI_Session::get();
+    aMgr->finishOperation();
+    myOpenTransaction = false;
+  }
 }
 
 void PartSet_WidgetSketchLabel::selectionModes(int& theModuleSelectionModes, QIntList& theModes)
@@ -644,3 +783,110 @@ QList<std::shared_ptr<ModuleBase_ViewerPrs>> PartSet_WidgetSketchLabel::findCirc
   }
   return aResult;
 }
+
+//******************************************************
+void PartSet_WidgetSketchLabel::onChangePlane()
+{
+  PartSet_Module* aModule = dynamic_cast<PartSet_Module*>(myWorkshop->module());
+  if (aModule) {
+    mySizeOfViewWidget->setVisible(false);
+    myRemoveExternal->setVisible(true);
+    myStackWidget->setCurrentIndex(0);
+
+    bool aBodyIsVisualized = myPreviewPlanes->hasVisualizedBodies(myWorkshop);
+
+    if (!aBodyIsVisualized) {
+      // We have to select a plane before any operation
+      myPreviewPlanes->showPreviewPlanes(myWorkshop);
+    }
+
+    CompositeFeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
+    myTmpPlane = PartSet_Tools::sketchPlane(aSketch);
+    PartSet_Tools::nullifySketchPlane(aSketch);
+
+    Handle(SelectMgr_Filter) aFilter = aModule->selectionFilter(SF_SketchPlaneFilter);
+    if (!aFilter.IsNull()) {
+      std::shared_ptr<GeomAPI_Pln> aPln;
+      Handle(ModuleBase_ShapeInPlaneFilter)::DownCast(aFilter)->setPlane(aPln);
+    }
+    XGUI_Workshop* aWorkshop = aModule->getWorkshop();
+
+    aWorkshop->selectionActivate()->updateSelectionFilters();
+    aWorkshop->selectionActivate()->updateSelectionModes();
+
+    SessionPtr aMgr = ModelAPI_Session::get();
+    aMgr->startOperation("Change Sketch plane");
+    myOpenTransaction = true;
+    myWorkshop->viewer()->update();
+  }
+}
+
+void PartSet_WidgetSketchLabel::setShowPointsState(bool theState)
+{
+  bool aBlock = myShowPoints->blockSignals(true);
+  myShowPoints->setChecked(theState);
+  myShowPoints->blockSignals(aBlock);
+}
+
+bool PartSet_WidgetSketchLabel::restoreValueCustom()
+{
+  if (myFeature.get()) {
+    CompositeFeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
+    if (aSketch.get() && (aSketch->numberOfSubs() > 0)) {
+      AttributeStringPtr aDOFStr = aSketch->string("SolverDOF");
+      if (aDOFStr.get()) {
+        QString aVal(aDOFStr->value().c_str());
+        if (aVal.contains('=')) {
+          // to support old data
+          aVal = aVal.right(aVal.length() - aVal.lastIndexOf('='));
+        }
+        int aDoF = aVal.toInt();
+        if (aDoF == 0) {
+          myDoFLabel->setText(tr("Sketch is fully fixed (DoF = 0)"));
+          myShowDOFBtn->setEnabled(false);
+        } else {
+          myDoFLabel->setText(tr("DoF (degrees of freedom) = ") + aVal);
+          myShowDOFBtn->setEnabled(true);
+        }
+      }
+    }
+    else {
+      myDoFLabel->setText("");
+      myShowDOFBtn->setEnabled(false);
+    }
+  }
+  return true;
+}
+
+
+void PartSet_WidgetSketchLabel::onShowDOF()
+{
+  CompositeFeaturePtr aCompFeature =
+    std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(myFeature);
+  if (aCompFeature.get()) {
+    static const Events_ID anEvent = Events_Loop::eventByName(EVENT_GET_DOF_OBJECTS);
+    ModelAPI_EventCreator::get()->sendUpdated(aCompFeature, anEvent);
+    Events_Loop::loop()->flush(anEvent);
+
+    // Transfer focus to the current viewport for correct processing of a key event
+    QWidget* aViewPort = myWorkshop->viewer()->activeViewPort();
+    if (aViewPort)
+      aViewPort->setFocus();
+  }
+}
+
+bool PartSet_WidgetSketchLabel::eventFilter(QObject* theObj, QEvent* theEvent)
+{
+  if (theObj == window()) {
+    int aType = theEvent->type();
+    if ((aType == QEvent::Hide) || (aType == QEvent::WindowDeactivate)) {
+      if (myPartSetMessage->isVisible())
+        myPartSetMessage->hide();
+      if (mySizeMessage->isVisible())
+        mySizeMessage->hide();
+    }
+    else if ((aType == QEvent::Show) || (aType == QEvent::WindowActivate))
+      onShowPanel();
+  }
+  return ModuleBase_WidgetValidated::eventFilter(theObj, theEvent);
+}
\ No newline at end of file