Salome HOME
Merge branch 'BR_EDF_2018_Lot1'
[modules/shaper.git] / src / XGUI / XGUI_Workshop.cpp
index 2e7c4e7702af76198a509735e1be301f0fe483db..0a1b1570ca901a64d408103893edbf3050ec8f3b 100755 (executable)
@@ -41,6 +41,7 @@
 #include "XGUI_PropertyDialog.h"
 #include "XGUI_SalomeConnector.h"
 #include "XGUI_Selection.h"
+#include "XGUI_SelectionActivate.h"
 #include "XGUI_SelectionMgr.h"
 #include "XGUI_Tools.h"
 #include "XGUI_ViewerProxy.h"
@@ -49,6 +50,7 @@
 #include <XGUI_HistoryMenu.h>
 #include <XGUI_QtEvents.h>
 #include <XGUI_DataModel.h>
+#include <XGUI_InspectionPanel.h>
 
 #ifndef HAVE_SALOME
 #include <AppElements_Button.h>
@@ -173,6 +175,7 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector)
       myModule(NULL),
       mySalomeConnector(theConnector),
       myPropertyPanel(0),
+      myInspectionPanel(0),
       myFacesPanel(0),
       myObjectBrowser(0),
       myDisplayer(0)
@@ -184,6 +187,7 @@ XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector)
   ModuleBase_IWorkshop* aWorkshop = moduleConnector();
   // Has to be defined first in order to get errors and messages from other components
   myEventsListener = new XGUI_WorkshopListener(aWorkshop);
+  mySelectionActivate = new XGUI_SelectionActivate(aWorkshop);
 
   SUIT_ResourceMgr* aResMgr = ModuleBase_Preferences::resourceMgr();
 #ifndef HAVE_SALOME
@@ -350,7 +354,7 @@ void XGUI_Workshop::startApplication()
 //******************************************************
 void XGUI_Workshop::activateModule()
 {
-  myModule->activateSelectionFilters();
+  selectionActivate()->updateSelectionFilters();
 
   connect(myDisplayer, SIGNAL(objectDisplayed(ObjectPtr, AISObjectPtr)),
     myModule, SLOT(onObjectDisplayed(ObjectPtr, AISObjectPtr)));
@@ -369,10 +373,8 @@ void XGUI_Workshop::activateModule()
 //******************************************************
 void XGUI_Workshop::deactivateModule()
 {
-  myModule->deactivateSelectionFilters();
-
   // remove internal displayer filter
-  displayer()->deactivateSelectionFilters();
+  displayer()->deactivateSelectionFilters(false);
 
   disconnect(myDisplayer, SIGNAL(objectDisplayed(ObjectPtr, AISObjectPtr)),
     myModule, SLOT(onObjectDisplayed(ObjectPtr, AISObjectPtr)));
@@ -382,17 +384,10 @@ void XGUI_Workshop::deactivateModule()
   XGUI_Displayer* aDisplayer = displayer();
   QObjectPtrList aDisplayed = aDisplayer->displayedObjects();
   aDisplayer->deactivateObjects(aDisplayed, true);
-  Handle(AIS_InteractiveContext) aContext = viewer()->AISContext();
-  Handle(AIS_Trihedron) aTrihedron = Handle(AIS_Trihedron)::DownCast(aDisplayer->getTrihedron());
-  /// deactivate trihedron in selection modes
-  TColStd_ListOfInteger aTColModes;
-  aContext->ActivatedModes(aTrihedron, aTColModes);
-  TColStd_ListIteratorOfListOfInteger itr( aTColModes );
-  for (; itr.More(); itr.Next() ) {
-    Standard_Integer aMode = itr.Value();
-    aContext->Deactivate(aTrihedron, aMode);
-  }
+  selectionActivate()->deactivateTrihedronInSelectionModes();
+
 #ifdef BEFORE_TRIHEDRON_PATCH
+  //Handle(AIS_Trihedron) aTrihedron = Handle(AIS_Trihedron)::DownCast(aDisplayer->getTrihedron());
   /// Trihedron problem: objects stayed in the viewer, should be removed manually
   /// otherwise in SALOME happens crash by HideAll in the viewer
   aContext->Remove(aTrihedron->Position(), true);
@@ -534,6 +529,21 @@ void XGUI_Workshop::onAcceptActionClicked()
   }
 }
 
+//******************************************************
+void XGUI_Workshop::onAcceptPlusActionClicked()
+{
+  QAction* anAction = dynamic_cast<QAction*>(sender());
+  XGUI_OperationMgr* anOperationMgr = operationMgr();
+  if (anOperationMgr) {
+    ModuleBase_OperationFeature* aFOperation = dynamic_cast<ModuleBase_OperationFeature*>
+                                                    (anOperationMgr->currentOperation());
+    if (aFOperation) {
+      if (myOperationMgr->commitOperation())
+        module()->launchOperation(aFOperation->id(), false);
+    }
+  }
+}
+
 //******************************************************
 void XGUI_Workshop::onPreviewActionClicked()
 {
@@ -553,7 +563,7 @@ void XGUI_Workshop::onPreviewActionClicked()
 void XGUI_Workshop::deactivateActiveObject(const ObjectPtr& theObject, const bool theUpdateViewer)
 {
   if (!myModule->canActivateSelection(theObject)) {
-    if (myDisplayer->isActive(theObject)) {
+    if (selectionActivate()->isActive(theObject)) {
       QObjectPtrList anObjects;
       anObjects.append(theObject);
       myDisplayer->deactivateObjects(anObjects, theUpdateViewer);
@@ -602,13 +612,15 @@ void XGUI_Workshop::fillPropertyPanel(ModuleBase_Operation* theOperation)
   FeaturePtr aFeature = aFOperation->feature();
   std::string aFeatureKind = aFeature->getKind();
   foreach (ModuleBase_ModelWidget* aWidget, aWidgets) {
-    if (!aWidget->attributeID().empty() && !aFeature->attribute(aWidget->attributeID()).get()) {
-      std::string anErrorMsg = "The feature '%1' has no attribute '%2' used by widget '%3'.";
-      Events_InfoMessage("XGUI_Workshop", anErrorMsg)
-        .arg(aFeatureKind).arg(aWidget->attributeID())
-        .arg(aWidget->metaObject()->className()).send();
-      myPropertyPanel->cleanContent();
-      return;
+    if (aWidget->usesAttribute()) {
+      if (!aWidget->attributeID().empty() && !aFeature->attribute(aWidget->attributeID()).get()) {
+        std::string anErrorMsg = "The feature '%1' has no attribute '%2' used by widget '%3'.";
+        Events_InfoMessage("XGUI_Workshop", anErrorMsg)
+          .arg(aFeatureKind).arg(aWidget->attributeID())
+          .arg(aWidget->metaObject()->className()).send();
+        myPropertyPanel->cleanContent();
+        return;
+      }
     }
   }
   // for performance purpose, flush should be done after all controls are filled
@@ -707,7 +719,6 @@ void XGUI_Workshop::onOperationResumed(ModuleBase_Operation* theOperation)
   myModule->operationResumed(theOperation);
 }
 
-
 //******************************************************
 void XGUI_Workshop::onOperationStopped(ModuleBase_Operation* theOperation)
 {
@@ -732,14 +743,14 @@ void XGUI_Workshop::onOperationStopped(ModuleBase_Operation* theOperation)
   QObjectPtrList anObjects;
   FeaturePtr aFeature = aFOperation->feature();
   if (aFeature.get()) { // feature may be not created (plugin load fail)
-    if (myDisplayer->isVisible(aFeature) && !myDisplayer->isActive(aFeature))
+    if (myDisplayer->isVisible(aFeature) && !selectionActivate()->isActive(aFeature))
       anObjects.append(aFeature);
     std::list<ResultPtr> aResults;
     ModelAPI_Tools::allResults(aFeature, aResults);
     std::list<ResultPtr>::const_iterator aIt;
     for (aIt = aResults.begin(); aIt != aResults.end(); ++aIt) {
       ResultPtr anObject = *aIt;
-      if (myDisplayer->isVisible(anObject) && !myDisplayer->isActive(anObject)) {
+      if (myDisplayer->isVisible(anObject) && !selectionActivate()->isActive(anObject)) {
         anObjects.append(anObject);
       }
     }
@@ -1026,12 +1037,14 @@ bool XGUI_Workshop::onSaveAs()
 void XGUI_Workshop::onUndo(int theTimes)
 {
   processUndoRedo(ActionUndo, theTimes);
+  myObjectBrowser->updateAllIndexes(1);
 }
 
 //******************************************************
 void XGUI_Workshop::onRedo(int theTimes)
 {
   processUndoRedo(ActionRedo, theTimes);
+  myObjectBrowser->updateAllIndexes(1);
 }
 
 //******************************************************
@@ -1058,7 +1071,10 @@ void XGUI_Workshop::processUndoRedo(const ModuleBase_ActionType theActionType, i
     if (aOpMgr->canStopOperation(aOpMgr->currentOperation()))
       aOpMgr->abortOperation(aOpMgr->currentOperation());
     else
+    {
+      myDisplayer->enableUpdateViewer(isUpdateEnabled);
       return;
+    }
   }
   objectBrowser()->treeView()->setCurrentIndex(QModelIndex());
   std::list<std::string> anActionList = theActionType == ActionUndo ? aMgr->undoList()
@@ -1078,10 +1094,10 @@ void XGUI_Workshop::processUndoRedo(const ModuleBase_ActionType theActionType, i
   updateCommandStatus();
 
   // unblock the viewer update functionality and make update on purpose
-  if (theActionType == ActionRedo) {
-    myDisplayer->enableUpdateViewer(isUpdateEnabled);
-    myDisplayer->updateViewer();
-  }
+  myDisplayer->enableUpdateViewer(isUpdateEnabled);
+  myDisplayer->updateViewer();
+  // Clear messages in status bar from previous operations if exists
+  setStatusBarMessage("");
 }
 
 //******************************************************
@@ -1329,6 +1345,11 @@ void XGUI_Workshop::createDockWidgets()
                                 Qt::BottomDockWidgetArea);
   connect(myFacesPanel, SIGNAL(closed()), myFacesPanel, SLOT(onClosed()));
 
+  myInspectionPanel = new XGUI_InspectionPanel(aDesktop, mySelector);
+  myInspectionPanel->setAllowedAreas(Qt::LeftDockWidgetArea |
+    Qt::RightDockWidgetArea);
+  aDesktop->addDockWidget(Qt::RightDockWidgetArea, myInspectionPanel);
+
   aDesktop->addDockWidget(
 #ifdef HAVE_SALOME
     Qt::RightDockWidgetArea,
@@ -1365,6 +1386,9 @@ void XGUI_Workshop::createDockWidgets()
   QAction* aOkAct = myActionsMgr->operationStateAction(XGUI_ActionsMgr::Accept);
   connect(aOkAct, SIGNAL(triggered()), this, SLOT(onAcceptActionClicked()));
 
+  QAction* aOkContAct = myActionsMgr->operationStateAction(XGUI_ActionsMgr::AcceptPlus);
+  connect(aOkContAct, SIGNAL(triggered()), this, SLOT(onAcceptPlusActionClicked()));
+
   QAction* aCancelAct = myActionsMgr->operationStateAction(XGUI_ActionsMgr::Abort);
   connect(aCancelAct, SIGNAL(triggered()), myOperationMgr, SLOT(onAbortOperation()));
 
@@ -1535,7 +1559,7 @@ void XGUI_Workshop::onContextMenuCommand(const QString& theId, bool isChecked)
 
 #ifdef DEBUG_WITH_MESSAGE_REPORT
         Handle(Message_Report) aContextReport = aContext->GetReport();
-        aContextReport->SetActive (Standard_True);
+        aContext->SetReportActive (Standard_True);
         aContextReport->SetLimit (1000);
         if (!aContextReport.IsNull())
           aParameters.Append(aContextReport);
@@ -1579,10 +1603,6 @@ void XGUI_Workshop::onContextMenuCommand(const QString& theId, bool isChecked)
 //**************************************************************
 void XGUI_Workshop::setViewerSelectionMode(int theMode)
 {
-  XGUI_ActiveControlSelector* anActiveSelector = activeControlMgr()->activeSelector();
-  if (anActiveSelector && anActiveSelector->getType() == XGUI_FacesPanelSelector::Type())
-    facesPanel()->setActivePanel(false);
-
   if (theMode == -1)
     myViewerSelMode.clear();
   else {
@@ -1591,7 +1611,7 @@ void XGUI_Workshop::setViewerSelectionMode(int theMode)
     else
       myViewerSelMode.append(theMode);
   }
-  activateObjectsSelection(myDisplayer->displayedObjects());
+  selectionActivate()->updateSelectionModes();
 }
 
 //**************************************************************
@@ -1601,12 +1621,15 @@ void XGUI_Workshop::activateObjectsSelection(const QObjectPtrList& theList)
   module()->activeSelectionModes(aModes);
   if (aModes.isEmpty() && (myViewerSelMode.length() > 0))
     aModes.append(myViewerSelMode);
-  myDisplayer->activateObjects(aModes, theList);
+  selectionActivate()->activateObjects(aModes, theList);
 }
 
 //**************************************************************
 bool XGUI_Workshop::prepareForDisplay(const std::set<ObjectPtr>& theObjects) const
 {
+  if (facesPanel()->isEmpty())
+    return true;
+
   // generate container of objects taking into account sub elments of compsolid
   std::set<ObjectPtr> anAllProcessedObjects;
   for (std::set<ObjectPtr>::const_iterator anObjectsIt = theObjects.begin();
@@ -1637,14 +1660,14 @@ bool XGUI_Workshop::prepareForDisplay(const std::set<ObjectPtr>& theObjects) con
     aHiddenObjects.insert(*anObjectsIt);
     aHiddenObjectNames.append((*anObjectsIt)->data()->name().c_str());
   }
-  if (aHiddenObjects.empty())
+  if (aHiddenObjects.empty()) // in parameter objects there are no hidden objects in hide face
     return true;
 
   int anAnswer = QMessageBox::question(
         desktop(), tr("Show object"),
         tr("'%1'\n are hidden by %2:\nRemove objects from the panel to be displayed?")
-        .arg(aHiddenObjectNames.join(',')).arg(facesPanel()->windowTitle(),
-        QMessageBox::Yes | QMessageBox::No, QMessageBox::No));
+        .arg(aHiddenObjectNames.join(", ")).arg(facesPanel()->windowTitle()),
+        QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
 
   bool aToBeDisplayed = anAnswer == QMessageBox::Yes;
   if (aToBeDisplayed)
@@ -1909,7 +1932,6 @@ void XGUI_Workshop::moveObjects()
 //**************************************************************
 bool XGUI_Workshop::deleteFeatures(const QObjectPtrList& theObjects)
 {
-  std::map<FeaturePtr, std::set<FeaturePtr> > aReferences;
   std::set<FeaturePtr> aFeatures;
   ModuleBase_Tools::convertToFeatures(theObjects, aFeatures);
 
@@ -2013,6 +2035,17 @@ bool XGUI_Workshop::canMoveFeature()
   QObjectPtrList::const_iterator anIt = aObjects.begin(), aLast = aObjects.end();
   for (; anIt != aLast && aCanMove; anIt++) {
     ObjectPtr aObject = *anIt;
+    if (!aObject.get() || !aObject->data().get() || !aObject->data()->isValid()) {
+      aCanMove = false;
+      break;
+    }
+    FeaturePtr aFeat = std::dynamic_pointer_cast<ModelAPI_Feature>(aObject);
+    // only groups can be moved to the end for now (#2451)
+    if (aFeat.get() && aFeat->getKind() != "Group") {
+      aCanMove = false;
+      break;
+    }
+
     // 1. Get features placed between selected and current in the document
     std::list<FeaturePtr> aFeaturesBetween = toCurrentFeatures(aObject);
     // if aFeaturesBetween is empty it means wrong order or aObject is the current feature
@@ -2577,6 +2610,7 @@ void XGUI_Workshop::highlightResults(const QObjectPtrList& theObjects)
 {
   FeaturePtr aFeature;
   QObjectPtrList aSelList = theObjects;
+  QObjectPtrList aNewSel;
   bool aHasHidden = false;
   foreach(ObjectPtr aObj, theObjects) {
     aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aObj);
@@ -2587,6 +2621,7 @@ void XGUI_Workshop::highlightResults(const QObjectPtrList& theObjects)
       for(aIt = aResults.cbegin(); aIt != aResults.cend(); aIt++) {
         aHasHidden |= (*aIt)->isConcealed();
         aSelList.append(*aIt);
+        aNewSel.append(*aIt);
       }
     }
   }
@@ -2595,6 +2630,7 @@ void XGUI_Workshop::highlightResults(const QObjectPtrList& theObjects)
     bool aBlocked = objectBrowser()->blockSignals(true);
     objectBrowser()->setObjectsSelected(aSelList);
     objectBrowser()->blockSignals(aBlocked);
+    objectBrowser()->ensureVisible(aNewSel.first());
   }
   if (aHasHidden)
     QMessageBox::information(desktop(), tr("Find results"),
@@ -2606,6 +2642,7 @@ void XGUI_Workshop::highlightFeature(const QObjectPtrList& theObjects)
 {
   ResultPtr aResult;
   QObjectPtrList aSelList = theObjects;
+  QObjectPtrList aNewSel;
   FeaturePtr aFeature;
   foreach(ObjectPtr aObj, theObjects) {
     aResult = std::dynamic_pointer_cast<ModelAPI_Result>(aObj);
@@ -2613,6 +2650,7 @@ void XGUI_Workshop::highlightFeature(const QObjectPtrList& theObjects)
       aFeature = ModelAPI_Feature::feature(aResult);
       if (aFeature.get()) {
         aSelList.append(aFeature);
+        aNewSel.append(aFeature);
       }
     }
   }
@@ -2621,6 +2659,7 @@ void XGUI_Workshop::highlightFeature(const QObjectPtrList& theObjects)
     bool aBlocked = objectBrowser()->blockSignals(true);
     objectBrowser()->setObjectsSelected(aSelList);
     objectBrowser()->blockSignals(aBlocked);
+    objectBrowser()->ensureVisible(aNewSel.first());
   }
 }
 
@@ -2636,9 +2675,13 @@ void XGUI_Workshop::insertFeatureFolder()
   SessionPtr aMgr = ModelAPI_Session::get();
   DocumentPtr aDoc = aMgr->activeDocument();
 
-  aMgr->startOperation();
+  QString aDescription = contextMenuMgr()->action("INSERT_FOLDER_CMD")->text();
+
+  aMgr->startOperation(aDescription.toStdString());
   aDoc->addFolder(aFeature);
   aMgr->finishOperation();
+
+  updateCommandStatus();
 }
 
 
@@ -2656,9 +2699,18 @@ void XGUI_Workshop::insertToFolder(bool isBefore)
   if (!aFolder.get())
     return;
 
-  aMgr->startOperation();
+  QString aDescription = contextMenuMgr()->action(
+    isBefore ? "ADD_TO_FOLDER_BEFORE_CMD" : "ADD_TO_FOLDER_AFTER_CMD")->text();
+
+  QMap<ObjectPtr, bool> aStates = myObjectBrowser->getFoldersState(aDoc);
+
+  aMgr->startOperation(aDescription.toStdString());
   aDoc->moveToFolder(aFeatures, aFolder);
   aMgr->finishOperation();
+
+  myObjectBrowser->setFoldersState(aStates);
+
+  updateCommandStatus();
 }
 
 void XGUI_Workshop::moveOutFolder(bool isBefore)
@@ -2670,7 +2722,16 @@ void XGUI_Workshop::moveOutFolder(bool isBefore)
   SessionPtr aMgr = ModelAPI_Session::get();
   DocumentPtr aDoc = aMgr->activeDocument();
 
-  aMgr->startOperation();
+  QString aDescription = contextMenuMgr()->action(
+    isBefore ? "ADD_OUT_FOLDER_BEFORE_CMD" : "ADD_OUT_FOLDER_AFTER_CMD")->text();
+
+  QMap<ObjectPtr, bool> aStates = myObjectBrowser->getFoldersState(aDoc);
+
+  aMgr->startOperation(aDescription.toStdString());
   aDoc->removeFromFolder(aFeatures, isBefore);
   aMgr->finishOperation();
+
+  myObjectBrowser->setFoldersState(aStates);
+
+  updateCommandStatus();
 }