]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
3.9 Clean the history
authornds <nds@opencascade.com>
Wed, 13 Jan 2016 14:52:28 +0000 (17:52 +0300)
committerdbv <dbv@opencascade.com>
Tue, 16 Feb 2016 14:03:02 +0000 (17:03 +0300)
src/XGUI/XGUI_ContextMenuMgr.cpp
src/XGUI/XGUI_OperationMgr.cpp
src/XGUI/XGUI_Tools.cpp
src/XGUI/XGUI_Tools.h
src/XGUI/XGUI_Workshop.cpp

index ea453bb49f8e68805b9af437822054d6283c33e9..648abd6cc7ebe1435ce65bf49e46ae7effc68bab 100644 (file)
@@ -71,6 +71,9 @@ void XGUI_ContextMenuMgr::createActions()
   aAction = new QAction(QIcon(":pictures/move.png"), XGUI_Workshop::MOVE_TO_END_COMMAND, this);
   addAction("MOVE_CMD", aAction);
 
+  aAction = new QAction(QIcon(":pictures/delete.png"), tr("Clean history"), this);
+  addAction("CLEAN_HISTORY_CMD", aAction);
+
   aAction = new QAction(QIcon(":pictures/color.png"), tr("Color..."), this);
   addAction("COLOR_CMD", aAction);
 
@@ -214,6 +217,9 @@ void XGUI_ContextMenuMgr::updateObjectBrowserMenu()
         else if (hasFeature && myWorkshop->canMoveFeature())
           action("MOVE_CMD")->setEnabled(true);
 
+        else if (hasFeature)
+          action("CLEAN_HISTORY_CMD")->setEnabled(true);
+
         if( aMgr->activeDocument() == aObject->document() )
         {
           action("RENAME_CMD")->setEnabled(true);
@@ -240,6 +246,8 @@ void XGUI_ContextMenuMgr::updateObjectBrowserMenu()
       if (hasFeature || hasParameter)
         action("DELETE_CMD")->setEnabled(true);
     }
+    if (allActive && hasFeature)
+      action("CLEAN_HISTORY_CMD")->setEnabled(true);
   }
 
   // Show/Hide command has to be disabled for objects from non active document
@@ -369,6 +377,7 @@ void XGUI_ContextMenuMgr::buildObjBrowserMenu()
   aList.clear();
   aList.append(action("DELETE_CMD"));
   aList.append(action("MOVE_CMD"));
+  aList.append(action("CLEAN_HISTORY_CMD"));
   aList.append(mySeparator);
   aList.append(action("RENAME_CMD"));
   myObjBrowserMenus[ModelAPI_Feature::group()] = aList;
@@ -429,6 +438,7 @@ void XGUI_ContextMenuMgr::addObjBrowserMenu(QMenu* theMenu) const
       aActions.append(mySeparator);
       aActions.append(action("DELETE_CMD"));
       //aActions.append(action("MOVE_CMD"));
+      aActions.append(action("CLEAN_HISTORY_CMD"));
       aActions.append(action("COLOR_CMD"));
   }
   theMenu->addActions(aActions);
index dff53bd91f513595f4a144976506108bd3d3d961..4b6b2257939c0cc975379d3e8c99aacb11a816cb 100644 (file)
@@ -38,7 +38,7 @@ XGUI_OperationMgr::XGUI_OperationMgr(QObject* theParent,
   /// we need to install filter to the application in order to react to 'Delete' key button
   /// this key can not be a short cut for a corresponded action because we need to set
   /// the actions priority
-  qApp->installEventFilter(this);
+  //qApp->installEventFilter(this);
 }
 
 XGUI_OperationMgr::~XGUI_OperationMgr()
index ab9ef819f618481662ef078c9f63979fd9326252..0b77c6c75cfb48c9a65acac5b5e8b0e93eb55905 100644 (file)
@@ -56,6 +56,18 @@ QString addSlash(const QString& path)
   return res;
 }
 
+//******************************************************************
+QString unionOfObjectNames(const QObjectPtrList& theObjects, const QString& theSeparator)
+{
+  QStringList aObjectNames;
+  foreach (ObjectPtr aObj, theObjects) {
+    if (!aObj->data()->isValid())
+      continue;
+    aObjectNames << QString::fromStdString(aObj->data()->name());
+  }
+  return aObjectNames.join(", ");
+}
+
 //******************************************************************
 bool isModelObject(FeaturePtr theFeature)
 {
@@ -190,9 +202,31 @@ bool isSubOfComposite(const ObjectPtr& theObject)
 
 //**************************************************************
 void refsToFeatureInAllDocuments(const ObjectPtr& theSourceObject, const ObjectPtr& theObject,
+                                 const QObjectPtrList& theIgnoreList,
                                  std::set<FeaturePtr>& theDirectRefFeatures, 
                                  std::set<FeaturePtr>& theIndirectRefFeatures,
                                  std::set<FeaturePtr>& theAlreadyProcessed)
+{
+  refsDirectToFeatureInAllDocuments(theSourceObject, theObject, theIgnoreList, theDirectRefFeatures, 
+                                    theAlreadyProcessed);
+
+  // Run recursion. It is possible recursive dependency, like the following: plane, extrusion uses plane,
+  // axis is built on extrusion. Delete of a plane should check the dependency from the axis also.
+  std::set<FeaturePtr>::const_iterator aFeatureIt = theDirectRefFeatures.begin();
+  for (; aFeatureIt != theDirectRefFeatures.end(); ++aFeatureIt) {
+    std::set<FeaturePtr> aRecursiveRefFeatures;
+    refsToFeatureInAllDocuments(theSourceObject, *aFeatureIt, theIgnoreList,
+      aRecursiveRefFeatures, aRecursiveRefFeatures, theAlreadyProcessed);
+    theIndirectRefFeatures.insert(aRecursiveRefFeatures.begin(), aRecursiveRefFeatures.end());
+  }
+
+}
+
+//**************************************************************
+void refsDirectToFeatureInAllDocuments(const ObjectPtr& theSourceObject, const ObjectPtr& theObject,
+                                       const QObjectPtrList& theIgnoreList,
+                                       std::set<FeaturePtr>& theDirectRefFeatures, 
+                                       std::set<FeaturePtr>& theAlreadyProcessed)
 {
   FeaturePtr aFeature = ModelAPI_Feature::feature(theObject);
   if (!aFeature.get())
@@ -209,7 +243,7 @@ void refsToFeatureInAllDocuments(const ObjectPtr& theSourceObject, const ObjectP
                                        aLast = aRefFeatures.end();
   for (; anIt != aLast; anIt++) {
     // composite feature should not be deleted when the sub feature is to be deleted
-    if (!isSubOfComposite(theSourceObject, *anIt))
+    if (!isSubOfComposite(theSourceObject, *anIt) && !theIgnoreList.contains(*anIt))
       theDirectRefFeatures.insert(*anIt);
   }
 
@@ -264,21 +298,12 @@ void refsToFeatureInAllDocuments(const ObjectPtr& theSourceObject, const ObjectP
             }
           }
         }
-        if (aHasReferenceToObject && !isSubOfComposite(theSourceObject, aFeature))
+        if (aHasReferenceToObject && !isSubOfComposite(theSourceObject, aFeature) &&
+            !theIgnoreList.contains(aFeature))
           theDirectRefFeatures.insert(aFeature);
       }
     }
   }
-
-  // Run recursion. It is possible recursive dependency, like the following: plane, extrusion uses plane,
-  // axis is built on extrusion. Delete of a plane should check the dependency from the axis also.
-  std::set<FeaturePtr>::const_iterator aFeatureIt = theDirectRefFeatures.begin();
-  for (; aFeatureIt != theDirectRefFeatures.end(); ++aFeatureIt) {
-    std::set<FeaturePtr> aRecursiveRefFeatures;
-    refsToFeatureInAllDocuments(theSourceObject, *aFeatureIt, 
-      aRecursiveRefFeatures, aRecursiveRefFeatures, theAlreadyProcessed);
-    theIndirectRefFeatures.insert(aRecursiveRefFeatures.begin(), aRecursiveRefFeatures.end());
-  }
 }
 
 }
index 48ab0d57b892676cb315d481eacb94cd627efb9c..b1947fc76e41e6ea70d4ada6bff0282290f2a6eb 100644 (file)
@@ -56,6 +56,12 @@ QString XGUI_EXPORT addSlash(const QString& path);
 
 // The model concerning tools
 
+/*! Unite object names in one string using the separator between values
+ \param theObjects a list of objects
+ \param theSeparator a separator
+ */
+QString unionOfObjectNames(const QObjectPtrList& theObjects, const QString& theSeparator);
+
 /*!
  Returns true if the feature is a model object
  \param theFeature a feature
@@ -110,6 +116,13 @@ void XGUI_EXPORT refsToFeatureInFeatureDocument(const ObjectPtr& theObject,
  */
 bool XGUI_EXPORT isSubOfComposite(const ObjectPtr& theObject, const FeaturePtr& theFeature);
 
+/*!
+*/
+void refsDirectToFeatureInAllDocuments(const ObjectPtr& theSourceObject, const ObjectPtr& theObject,
+                                 const QObjectPtrList& theIgnoreList,
+                                 std::set<FeaturePtr>& theDirectRefFeatures, 
+                                 std::set<FeaturePtr>& theAlreadyProcessed);
+
 /*!
  Returns a container of references feature to the source object. The search happens in the object
  document and in other Part documents if the object belongs to the PartSet. The search is recursive,
@@ -118,13 +131,15 @@ bool XGUI_EXPORT isSubOfComposite(const ObjectPtr& theObject, const FeaturePtr&
  which has the object as a sub object.
  \param theSourceObject an object, which references are searched
  \param theObject an intermediate recursive object, should be set in the source object
+ \param theIgnoreList an ignore list, the found referernces which coincide with the objects are ignored
  \param theDirectRefFeatures direct references
- \param theIndirectRefFeatures indirect references
+ \param theIndirectRefFeatures indirect references. These are features that refers to the direct features
  \param theAlreadyProcessed set of processed elements, used for optimization (do not reanalyse processed)
  \return a boolean value
  */
 void XGUI_EXPORT refsToFeatureInAllDocuments(const ObjectPtr& theSourceObject,
                                              const ObjectPtr& theObject,
+                                             const QObjectPtrList& theIgnoreList,
                                              std::set<FeaturePtr>& theDirectRefFeatures,
                                              std::set<FeaturePtr>& theIndirectRefFeatures,
                                              std::set<FeaturePtr>& theAlreadyProcessed);
index 110d0bcdce48f39644af12cad0f540189bddc889..61d1796be2cc134fe487b0048fe280c19c4127e9 100755 (executable)
@@ -1129,6 +1129,8 @@ 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")
@@ -1187,17 +1189,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)) {
@@ -1208,6 +1203,66 @@ void XGUI_Workshop::deleteObjects()
   }
 }
 
+//**************************************************************
+void XGUI_Workshop::cleanHistory()
+{
+  if (!abortAllOperations())
+    return;
+
+  QObjectPtrList anObjects = mySelector->selection()->selectedObjects();
+
+  // 1. find all referenced features
+  std::set<FeaturePtr> anUnusedFeatures;
+  std::set<FeaturePtr> aDirectRefFeatures;
+  foreach (ObjectPtr anObject, anObjects) {
+    FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(anObject);
+    if (aFeature.get()) {
+      std::set<FeaturePtr> alreadyProcessed;
+      aDirectRefFeatures.clear();
+      XGUI_Tools::refsDirectToFeatureInAllDocuments(anObject, anObject, anObjects,
+                                                    aDirectRefFeatures, alreadyProcessed);
+      if (aDirectRefFeatures.empty() && anUnusedFeatures.find(aFeature) == anUnusedFeatures.end())
+        anUnusedFeatures.insert(aFeature);
+    }
+  }
+
+  // 2. warn about the references remove, break the delete operation if the user chose it
+  if (!anUnusedFeatures.empty()) {
+    QStringList aNames;
+    foreach (const FeaturePtr& aFeature, anUnusedFeatures)
+      aNames.append(aFeature->name().c_str());
+    QString anUnusedNames = aNames.join(", ");
+
+    QString anActionId = "CLEAN_HISTORY_CMD";
+    QString aDescription = contextMenuMgr()->action("DELETE_CMD")->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(anObjects, anIgnoredFeatures, anActionId)) {
+      operationMgr()->commitOperation();
+    }
+    else {
+      operationMgr()->abortOperation(operationMgr()->currentOperation());
+    }
+  }
+}
+
 //**************************************************************
 void XGUI_Workshop::moveObjects()
 {
@@ -1263,8 +1318,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(), 
@@ -1350,7 +1405,17 @@ bool XGUI_Workshop::deleteFeatures(const QObjectPtrList& theList,
   }
 
   QString anActionId = "DELETE_CMD";
-  QString anId = QString::fromStdString(anActionId.toStdString().c_str());
+  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) {
@@ -1375,6 +1440,7 @@ bool XGUI_Workshop::deleteFeatures(const QObjectPtrList& theList,
         qDebug(QString("remove feature :%1").arg(anInfoStr).toStdString().c_str());
 #endif
         aDoc->removeFeature(aFeature);
+        isDone = true;
       }
     }
   }