Salome HOME
Delete key regression corrections: in previous implementation sketch entities did...
[modules/shaper.git] / src / XGUI / XGUI_Workshop.cpp
index 3e1eff31c320ec4fdf51f7022522796bb920e683..754778afe4d78e018e07881bd554d44e57e2c1d1 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();
 }
 
@@ -393,21 +400,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)
 {
@@ -606,7 +598,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 +743,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 +810,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 +839,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();
@@ -1051,8 +1065,6 @@ void XGUI_Workshop::createDockWidgets()
 
   connect(myPropertyPanel, SIGNAL(enterClicked()),
           myOperationMgr,  SLOT(onProcessEnter()));
-  //connect(myOperationMgr,  SIGNAL(validationStateChanged(bool)),
-  //        this, SLOT(onValidationStateChanged(bool)));
 }
 
 //******************************************************
@@ -1068,8 +1080,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 +1100,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 +1136,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")
@@ -1176,17 +1196,10 @@ 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)) {
@@ -1197,6 +1210,72 @@ void XGUI_Workshop::deleteObjects()
   }
 }
 
+//**************************************************************
+void XGUI_Workshop::cleanHistory()
+{
+  if (!abortAllOperations())
+    return;
+
+  QObjectPtrList anObjects = mySelector->selection()->selectedObjects();
+
+  // 1. find all referenced features
+  QList<ObjectPtr> anUnusedObjects;
+  std::set<FeaturePtr> aDirectRefFeatures;
+  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);
+    }
+    if (aFeature.get()) {
+      std::set<FeaturePtr> alreadyProcessed;
+      aDirectRefFeatures.clear();
+      XGUI_Tools::refsDirectToFeatureInAllDocuments(aFeature, aFeature, anObjects,
+                                                    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());
+    }
+  }
+}
+
 //**************************************************************
 void XGUI_Workshop::moveObjects()
 {
@@ -1252,8 +1331,8 @@ bool XGUI_Workshop::deleteFeatures(const QObjectPtrList& theList,
   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(), 
@@ -1339,7 +1418,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 +1438,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 +1453,7 @@ bool XGUI_Workshop::deleteFeatures(const QObjectPtrList& theList,
         qDebug(QString("remove feature :%1").arg(anInfoStr).toStdString().c_str());
 #endif
         aDoc->removeFeature(aFeature);
+        isDone = true;
       }
     }
   }