Salome HOME
2.5. Select the point of a sketch entity must display the editing point panel
[modules/shaper.git] / src / XGUI / XGUI_Workshop.cpp
index 3e1eff31c320ec4fdf51f7022522796bb920e683..eebe7c38bc7354caad96142ce4e277105f1b7231 100755 (executable)
 #include <dlfcn.h>
 #endif
 
+
+QString XGUI_Workshop::MOVE_TO_END_COMMAND = QObject::tr("Move to the end");
+
 //#define DEBUG_DELETE
+//#define DEBUG_FEATURE_NAME
 
 XGUI_Workshop::XGUI_Workshop(XGUI_SalomeConnector* theConnector)
     : QObject(),
@@ -160,11 +164,10 @@ 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()));
 
 #ifndef HAVE_SALOME
   connect(myMainWindow, SIGNAL(exitKeySequence()), SLOT(onExit()));
+  onTrihedronVisibilityChanged(true);
 #endif
 
   connect(this, SIGNAL(errorOccurred(const QString&)), myErrorDlg, SLOT(addError(const QString&)));
@@ -215,6 +218,10 @@ void XGUI_Workshop::startApplication()
   
   onNew();
 
+  myViewerProxy->connectViewProxy();
+  connect(myViewerProxy, SIGNAL(trihedronVisibilityChanged(bool)),
+          SLOT(onTrihedronVisibilityChanged(bool)));
+
   emit applicationStarted();
 }
 
@@ -235,6 +242,7 @@ void XGUI_Workshop::activateModule()
   QIntList aModes;
   module()->activeSelectionModes(aModes);
   aDisplayer->activateObjects(aModes, aDisplayed);
+  myOperationMgr->activate();
 }
 
 void XGUI_Workshop::deactivateModule()
@@ -252,6 +260,8 @@ void XGUI_Workshop::deactivateModule()
   XGUI_Displayer* aDisplayer = displayer();
   QObjectPtrList aDisplayed = aDisplayer->displayedObjects();
   aDisplayer->deactivateObjects(aDisplayed, true);
+
+  myOperationMgr->deactivate();
 }
 
 //******************************************************
@@ -393,21 +403,6 @@ void XGUI_Workshop::onAcceptActionClicked()
   }
 }
 
-//******************************************************
-/*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)
 {
@@ -572,13 +567,15 @@ void XGUI_Workshop::setPropertyPanel(ModuleBase_Operation* theOperation)
     return;
 
   showPropertyPanel();
-  QString aXmlRepr = aFOperation->getDescription()->xmlRepresentation();
-  ModuleBase_WidgetFactory aFactory(aXmlRepr.toStdString(), myModuleConnector);
-
   myPropertyPanel->cleanContent();
-  aFactory.createWidget(myPropertyPanel->contentWidget());
 
-  QList<ModuleBase_ModelWidget*> aWidgets = aFactory.getModelWidgets();
+  QList<ModuleBase_ModelWidget*> aWidgets;
+  if (!module()->createWidgets(theOperation, aWidgets)) {
+    QString aXmlRepr = aFOperation->getDescription()->xmlRepresentation();
+    ModuleBase_WidgetFactory aFactory(aXmlRepr.toStdString(), myModuleConnector);
+    aFactory.createWidget(myPropertyPanel->contentWidget());
+    aWidgets = aFactory.getModelWidgets();
+  }
 
   // check compatibility of feature and widgets
   FeaturePtr aFeature = aFOperation->feature();
@@ -606,7 +603,13 @@ void XGUI_Workshop::setPropertyPanel(ModuleBase_Operation* theOperation)
 
   myModule->propertyPanelDefined(theOperation);
 
+#ifndef DEBUG_FEATURE_NAME
   myPropertyPanel->setWindowTitle(theOperation->getDescription()->description());
+#else
+  std::string aFeatureName = aFeature->name();
+  myPropertyPanel->setWindowTitle(QString("%1: %2").arg(theOperation->getDescription()->description())
+                                                  .arg(aFeatureName.c_str()));
+#endif
 
   myErrorMgr->setPropertyPanel(myPropertyPanel);
 }
@@ -745,6 +748,14 @@ void XGUI_Workshop::onPreferences()
 }
 #endif
 
+//******************************************************
+void XGUI_Workshop::onTrihedronVisibilityChanged(bool theState)
+{
+  XGUI_Displayer* aDisplayer = displayer();
+  if (aDisplayer)
+    aDisplayer->displayTrihedron(theState);
+}
+
 //******************************************************
 bool XGUI_Workshop::onSave()
 {
@@ -804,14 +815,18 @@ void XGUI_Workshop::onUndo(int theTimes)
 {
   objectBrowser()->treeView()->setCurrentIndex(QModelIndex());
   SessionPtr aMgr = ModelAPI_Session::get();
+  std::list<std::string> aUndoList = aMgr->undoList();
   if (aMgr->isOperation()) {
     /// this is important for nested operations
     /// when sketch operation is active, this condition is false and
     /// the sketch operation is not aborted
     operationMgr()->onAbortOperation();
   }
-  for (int i = 0; i < theTimes; ++i) {
+  std::list<std::string>::const_iterator aIt = aUndoList.cbegin();
+  for (int i = 0; (i < theTimes) && (aIt != aUndoList.cend()); ++i, ++aIt) {
     aMgr->undo();
+    if (QString((*aIt).c_str()) == MOVE_TO_END_COMMAND)
+      myObjectBrowser->rebuildDataTree();
   }
 
   operationMgr()->updateApplyOfOperations();
@@ -829,14 +844,18 @@ void XGUI_Workshop::onRedo(int theTimes)
 
   objectBrowser()->treeView()->setCurrentIndex(QModelIndex());
   SessionPtr aMgr = ModelAPI_Session::get();
+  std::list<std::string> aRedoList = aMgr->redoList();
   if (aMgr->isOperation()) {
     /// this is important for nested operations
     /// when sketch operation is active, this condition is false and
     /// the sketch operation is not aborted
     operationMgr()->onAbortOperation();
   }
-  for (int i = 0; i < theTimes; ++i) {
+  std::list<std::string>::const_iterator aIt = aRedoList.cbegin();
+  for (int i = 0; (i < theTimes) && (aIt != aRedoList.cend()); ++i, ++aIt) {
     aMgr->redo();
+    if (QString((*aIt).c_str()) == MOVE_TO_END_COMMAND)
+      myObjectBrowser->rebuildDataTree();
   }
   operationMgr()->updateApplyOfOperations();
   updateCommandStatus();
@@ -1046,13 +1065,11 @@ void XGUI_Workshop::createDockWidgets()
 
   QAction* aCancelAct = myActionsMgr->operationStateAction(XGUI_ActionsMgr::Abort);
   connect(aCancelAct, SIGNAL(triggered()), myOperationMgr, SLOT(onAbortOperation()));
-  connect(myPropertyPanel, SIGNAL(keyReleased(QKeyEvent*)),
-          myOperationMgr,  SLOT(onKeyReleased(QKeyEvent*)));
+  connect(myPropertyPanel, SIGNAL(keyReleased(QObject*, QKeyEvent*)),
+          myOperationMgr,  SLOT(onKeyReleased(QObject*, QKeyEvent*)));
 
-  connect(myPropertyPanel, SIGNAL(enterClicked()),
-          myOperationMgr,  SLOT(onProcessEnter()));
-  //connect(myOperationMgr,  SIGNAL(validationStateChanged(bool)),
-  //        this, SLOT(onValidationStateChanged(bool)));
+  connect(myPropertyPanel, SIGNAL(enterClicked(QObject*)),
+          myOperationMgr,  SLOT(onProcessEnter(QObject*)));
 }
 
 //******************************************************
@@ -1068,8 +1085,8 @@ void XGUI_Workshop::showPropertyPanel()
   // in order to operation manager could process key events of the panel.
   // otherwise they are ignored. It happens only if the same(activateWindow) is
   // not happened by property panel activation(e.g. resume operation of Sketch)
-  myPropertyPanel->activateWindow();
-  myPropertyPanel->setFocus();
+  ModuleBase_Tools::activateWindow(myPropertyPanel, "XGUI_Workshop::showPropertyPanel()");
+  ModuleBase_Tools::setFocus(myPropertyPanel, "XGUI_Workshop::showPropertyPanel()");
 }
 
 //******************************************************
@@ -1088,20 +1105,22 @@ void XGUI_Workshop::hidePropertyPanel()
   // are processed by this console. For example Undo actions.
   // It is possible that this code is to be moved to NewGeom package
   QMainWindow* aDesktop = desktop();
-  aDesktop->activateWindow();
-  aDesktop->setFocus();
+  ModuleBase_Tools::activateWindow(aDesktop, "XGUI_Workshop::hidePropertyPanel()");
+  ModuleBase_Tools::setFocus(aDesktop, "XGUI_Workshop::showPropertyPanel()");
 }
 
 //******************************************************
 void XGUI_Workshop::showObjectBrowser()
 {
-  myObjectBrowser->parentWidget()->show();
+  if (!isSalomeMode())
+    myObjectBrowser->parentWidget()->show();
 }
 
 //******************************************************
 void XGUI_Workshop::hideObjectBrowser()
 {
-  myObjectBrowser->parentWidget()->hide();
+  if (!isSalomeMode())
+    myObjectBrowser->parentWidget()->hide();
 }
 
 //******************************************************
@@ -1122,16 +1141,22 @@ void XGUI_Workshop::onContextMenuCommand(const QString& theId, bool isChecked)
   QObjectPtrList aObjects = mySelector->selection()->selectedObjects();
   if (theId == "DELETE_CMD")
     deleteObjects();
+  else if (theId == "CLEAN_HISTORY_CMD")
+    cleanHistory();
   else if (theId == "MOVE_CMD")
     moveObjects();
   else if (theId == "COLOR_CMD")
     changeColor(aObjects);
-  else if (theId == "SHOW_CMD")
+  else if (theId == "SHOW_CMD") {
     showObjects(aObjects, true);
+    mySelector->updateSelectionBy(ModuleBase_ISelection::Browser);
+  }
   else if (theId == "HIDE_CMD")
     showObjects(aObjects, false);
-  else if (theId == "SHOW_ONLY_CMD")
+  else if (theId == "SHOW_ONLY_CMD") {
     showOnlyObjects(aObjects);
+    mySelector->updateSelectionBy(ModuleBase_ISelection::Browser);
+  }
   else if (theId == "SHADING_CMD")
     setDisplayMode(aObjects, XGUI_Displayer::Shading);
   else if (theId == "WIREFRAME_CMD")
@@ -1159,9 +1184,6 @@ void XGUI_Workshop::deleteObjects()
   QObjectPtrList anObjects = mySelector->selection()->selectedObjects();
   if (!abortAllOperations())
     return;
-  // It is necessary to clear selection in order to avoid selection changed event during
-  // deletion and negative consequences connected with processing of already deleted items
-  mySelector->clearSelection();
   // check whether the object can be deleted. There should not be parts which are not loaded
   if (!XGUI_Tools::canRemoveOrRename(desktop(), anObjects))
     return;
@@ -1176,24 +1198,102 @@ void XGUI_Workshop::deleteObjects()
 
   // 1. start operation
   QString aDescription = contextMenuMgr()->action("DELETE_CMD")->text();
-  aDescription += tr(" %1");
-  QStringList aObjectNames;
-  foreach (ObjectPtr aObj, anObjects) {
-    if (!aObj->data()->isValid())
-      continue;
-    aObjectNames << QString::fromStdString(aObj->data()->name());
-  }
-  aDescription = aDescription.arg(aObjectNames.join(", "));
+  aDescription += " " + aDescription.arg(XGUI_Tools::unionOfObjectNames(anObjects, ", "));
   ModuleBase_OperationAction* anOpAction = new ModuleBase_OperationAction(aDescription, module());
-
   operationMgr()->startOperation(anOpAction);
+
   // 3. delete objects
   std::set<FeaturePtr> anIgnoredFeatures;
-  if (deleteFeatures(anObjects, anIgnoredFeatures, desktop(), true)) {
-    operationMgr()->commitOperation();
+  std::set<FeaturePtr> aDirectRefFeatures, aIndirectRefFeatures;
+  findReferences(anObjects, aDirectRefFeatures, aIndirectRefFeatures);
+
+  bool doDeleteReferences = true;
+  if (isDeleteFeatureWithReferences(anObjects, aDirectRefFeatures, aIndirectRefFeatures,
+                                    desktop(), doDeleteReferences)) {
+    // It is necessary to clear selection in order to avoid selection changed event during
+    // deletion and negative consequences connected with processing of already deleted items
+    mySelector->clearSelection();
+    if (deleteFeaturesInternal(anObjects, aDirectRefFeatures, aIndirectRefFeatures,
+                               anIgnoredFeatures, doDeleteReferences))
+      operationMgr()->commitOperation();
+    else
+      operationMgr()->abortOperation(operationMgr()->currentOperation());
   }
-  else {
-    operationMgr()->abortOperation(operationMgr()->currentOperation());
+}
+
+//**************************************************************
+void XGUI_Workshop::cleanHistory()
+{
+  if (!abortAllOperations())
+    return;
+
+  QObjectPtrList anObjects = mySelector->selection()->selectedObjects();
+  QObjectPtrList aFeatures;
+  foreach (ObjectPtr anObject, anObjects) {
+    FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anObject);
+    // for parameter result, use the corresponded reature to be removed
+    if (!aFeature.get() && anObject->groupName() == ModelAPI_ResultParameter::group()) {
+      aFeature = ModelAPI_Feature::feature(anObject);
+    }
+    aFeatures.append(aFeature);
+  }
+
+  // 1. find all referenced features
+  QList<ObjectPtr> anUnusedObjects;
+  std::set<FeaturePtr> aDirectRefFeatures;
+  //foreach (ObjectPtr anObject, anObjects) {
+  foreach (ObjectPtr anObject, aFeatures) {
+    FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anObject);
+    // for parameter result, use the corresponded reature to be removed
+    //if (!aFeature.get() && anObject->groupName() == ModelAPI_ResultParameter::group()) {
+    //  aFeature = ModelAPI_Feature::feature(anObject);
+    //}
+    if (aFeature.get()) {
+      std::set<FeaturePtr> alreadyProcessed;
+      aDirectRefFeatures.clear();
+      XGUI_Tools::refsDirectToFeatureInAllDocuments(aFeature, aFeature, aFeatures,
+                                                    aDirectRefFeatures, alreadyProcessed);
+      if (aDirectRefFeatures.empty() && !anUnusedObjects.contains(aFeature))
+        anUnusedObjects.append(aFeature);
+    }
+  }
+
+  // 2. warn about the references remove, break the delete operation if the user chose it
+  if (!anUnusedObjects.empty()) {
+    QStringList aNames;
+    foreach (const ObjectPtr& anObject, anUnusedObjects) {
+      FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anObject);
+      aNames.append(aFeature->name().c_str());
+    }
+    QString anUnusedNames = aNames.join(", ");
+
+    QString anActionId = "CLEAN_HISTORY_CMD";
+    QString aDescription = contextMenuMgr()->action(anActionId)->text();
+
+    QMessageBox aMessageBox(desktop());
+    aMessageBox.setWindowTitle(aDescription);
+    aMessageBox.setIcon(QMessageBox::Warning);
+    aMessageBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
+    aMessageBox.setDefaultButton(QMessageBox::No);
+
+    QString aText = QString(tr("Unused features are the following: %1.\nThese features will be deleted.\nWould you like to continue?")
+                   .arg(anUnusedNames));
+    aMessageBox.setText(aText);
+    if (aMessageBox.exec() == QMessageBox::No)
+      return;
+
+    // 1. start operation
+    aDescription += "by deleting of " + aDescription.arg(XGUI_Tools::unionOfObjectNames(anObjects, ", "));
+    ModuleBase_OperationAction* anOpAction = new ModuleBase_OperationAction(aDescription, module());
+    operationMgr()->startOperation(anOpAction);
+
+    std::set<FeaturePtr> anIgnoredFeatures;
+    if (removeFeatures(anUnusedObjects, anIgnoredFeatures, anActionId)) {
+      operationMgr()->commitOperation();
+    }
+    else {
+      operationMgr()->abortOperation(operationMgr()->currentOperation());
+    }
   }
 }
 
@@ -1233,38 +1333,31 @@ void XGUI_Workshop::moveObjects()
 }
 
 //**************************************************************
-bool XGUI_Workshop::deleteFeatures(const QObjectPtrList& theList,
-                                   const std::set<FeaturePtr>& theIgnoredFeatures,
-                                   QWidget* theParent,
-                                   const bool theAskAboutDeleteReferences)
+void XGUI_Workshop::findReferences(const QObjectPtrList& theList,
+                                   std::set<FeaturePtr>& aDirectRefFeatures,
+                                   std::set<FeaturePtr>& aIndirectRefFeatures)
 {
-#ifdef DEBUG_DELETE
-  QStringList aDInfo;
-  QObjectPtrList::const_iterator aDIt = theList.begin(), aDLast = theList.end();
-  for (; aDIt != aDLast; ++aDIt) {
-    aDInfo.append(ModuleBase_Tools::objectInfo((*aDIt)));
-  }
-  QString anInfoStr = aDInfo.join(", ");
-  qDebug(QString("deleteFeatures: %1, %2").arg(theList.size()).arg(anInfoStr).toStdString().c_str());
-#endif
-
-  // 1. find all referenced features
-  std::set<FeaturePtr> aDirectRefFeatures, aIndirectRefFeatures;
   foreach (ObjectPtr aDeletedObj, theList) {
     std::set<FeaturePtr> alreadyProcessed;
-    XGUI_Tools::refsToFeatureInAllDocuments(
-      aDeletedObj, aDeletedObj, aDirectRefFeatures, aIndirectRefFeatures, alreadyProcessed);
+    XGUI_Tools::refsToFeatureInAllDocuments(aDeletedObj, aDeletedObj, theList, aDirectRefFeatures,
+                                            aIndirectRefFeatures, alreadyProcessed);
     std::set<FeaturePtr> aDifference;
     std::set_difference(aIndirectRefFeatures.begin(), aIndirectRefFeatures.end(), 
                         aDirectRefFeatures.begin(), aDirectRefFeatures.end(), 
                         std::inserter(aDifference, aDifference.begin()));
     aIndirectRefFeatures = aDifference;
   }
+}
 
-  bool doDeleteReferences = true;
+bool XGUI_Workshop::isDeleteFeatureWithReferences(const QObjectPtrList& theList,
+                                   const std::set<FeaturePtr>& aDirectRefFeatures,
+                                   const std::set<FeaturePtr>& aIndirectRefFeatures,
+                                   QWidget* theParent,
+                                   bool& doDeleteReferences)
+{
+  doDeleteReferences = true;
 
-  // 2. warn about the references remove, break the delete operation if the user chose it
-  if (theAskAboutDeleteReferences && !aDirectRefFeatures.empty()) {
+  if (!aDirectRefFeatures.empty()) {
     QStringList aDirectRefNames;
     foreach (const FeaturePtr& aFeature, aDirectRefFeatures)
       aDirectRefNames.append(aFeature->name().c_str());
@@ -1312,8 +1405,24 @@ bool XGUI_Workshop::deleteFeatures(const QObjectPtrList& theList,
       doDeleteReferences = false;
     }
   }
+  return true;
+}
 
-  // 3. remove referenced features
+bool XGUI_Workshop::deleteFeatures(const QObjectPtrList& theFeatures,
+                                   const std::set<FeaturePtr>& theIgnoredFeatures)
+{
+  std::set<FeaturePtr> aDirectRefFeatures, aIndirectRefFeatures;
+  findReferences(theFeatures, aDirectRefFeatures, aIndirectRefFeatures);
+  return deleteFeaturesInternal(theFeatures, aDirectRefFeatures, aIndirectRefFeatures,
+                                theIgnoredFeatures);
+}
+
+bool XGUI_Workshop::deleteFeaturesInternal(const QObjectPtrList& theList,
+                                           const std::set<FeaturePtr>& aDirectRefFeatures,
+                                           const std::set<FeaturePtr>& aIndirectRefFeatures,
+                                           const std::set<FeaturePtr>& theIgnoredFeatures,
+                                           const bool doDeleteReferences)
+{
   if (doDeleteReferences) {
     std::set<FeaturePtr> aFeaturesToDelete = aDirectRefFeatures;
     aFeaturesToDelete.insert(aIndirectRefFeatures.begin(), aIndirectRefFeatures.end());
@@ -1339,7 +1448,17 @@ bool XGUI_Workshop::deleteFeatures(const QObjectPtrList& theList,
   }
 
   QString anActionId = "DELETE_CMD";
-  QString anId = QString::fromStdString(anActionId.toStdString().c_str());
+  return removeFeatures(theList, theIgnoredFeatures, anActionId);
+}
+
+//**************************************************************
+bool XGUI_Workshop::removeFeatures(const QObjectPtrList& theList,
+                                   const std::set<FeaturePtr>& theIgnoredFeatures,
+                                   const QString& theActionId)
+{
+  bool isDone = false;
+
+  QString anId = QString::fromStdString(theActionId.toStdString().c_str());
   QStringList anObjectGroups = contextMenuMgr()->actionObjectGroups(anId);
   // 4. remove the parameter features
   foreach (ObjectPtr aObj, theList) {
@@ -1349,9 +1468,6 @@ bool XGUI_Workshop::deleteFeatures(const QObjectPtrList& theList,
     if (!anObjectGroups.contains(aGroupName.c_str()))
       continue;
 
-    if (!myModule->canApplyAction(aObj, anActionId))
-      continue;
-
     FeaturePtr aFeature = ModelAPI_Feature::feature(aObj);
     if (aFeature) {
       /*// TODO: to learn the workshop to delegate the Part object deletion to the PartSet module
@@ -1367,6 +1483,7 @@ bool XGUI_Workshop::deleteFeatures(const QObjectPtrList& theList,
         qDebug(QString("remove feature :%1").arg(anInfoStr).toStdString().c_str());
 #endif
         aDoc->removeFeature(aFeature);
+        isDone = true;
       }
     }
   }