+ else
+ operationMgr()->abortOperation(operationMgr()->currentOperation());
+}
+
+//**************************************************************
+void addRefsToFeature(const FeaturePtr& theFeature,
+ const std::map<FeaturePtr, std::set<FeaturePtr> >& theMainList,
+ std::set<FeaturePtr>& theReferences)
+{
+ //if (theReferences.find(theFeature) != theReferences.end())
+ // return;
+ if (theMainList.find(theFeature) == theMainList.end())
+ return; // this feature is not in the selection list, so exists without references to it
+ std::set<FeaturePtr> aMainReferences = theMainList.at(theFeature);
+
+ std::set<FeaturePtr>::const_iterator anIt = aMainReferences.begin(),
+ aLast = aMainReferences.end();
+ for (; anIt != aLast; anIt++) {
+ FeaturePtr aRefFeature = *anIt;
+ if (theReferences.find(aRefFeature) == theReferences.end())
+ theReferences.insert(aRefFeature);
+ addRefsToFeature(aRefFeature, theMainList, theReferences);
+ }
+}
+
+//**************************************************************
+void XGUI_Workshop::cleanHistory()
+{
+ if (!abortAllOperations())
+ return;
+
+ QObjectPtrList anObjects = mySelector->selection()->selectedObjects();
+ std::set<FeaturePtr> aFeatures;
+ ModuleBase_Tools::convertToFeatures(anObjects, aFeatures);
+
+#ifdef DEBUG_CLEAN_HISTORY
+ QStringList anInfo;
+ std::set<FeaturePtr>::const_iterator aFIt;
+ for (aFIt = aFeatures.begin(); aFIt != aFeatures.end(); ++aFIt) {
+ FeaturePtr aFeature = ModelAPI_Feature::feature(*aFIt);
+ anInfo.append(aFeature->name().c_str());
+ }
+ QString anInfoStr = anInfo.join(";\t");
+ qDebug(QString("cleanHistory for: [%1] - %2").
+ arg(aFeatures.size()).arg(anInfoStr).toStdString().c_str());
+#endif
+
+ std::map<FeaturePtr, std::set<FeaturePtr> > aReferences;
+ ModelAPI_Tools::findAllReferences(aFeatures, aReferences, true, false);
+ // find for each object whether all reference values are in the map as key, that means that there
+ // is no other reference in the model to this object, so it might be removed by cleaning history
+ // sk_1(ext_1, vertex_1) + (sk_3, bool_1) - cann't be deleted, dependency to bool_1
+ // ext_1(bool_1, sk_3) - cann't be deleted, dependency to bool_1
+ // vertex_1()
+ // sk_2(ext_2) + (bool_1) - cann't be deleted, dependency to bool_1
+ // ext_2(bool_1) - cann't be deleted, dependency to bool_1
+ // sk_3()
+ // Information: bool_1 is not selected
+ std::set<FeaturePtr> anUnusedObjects;
+ std::map<FeaturePtr, std::set<FeaturePtr> >::const_iterator aMainIt = aReferences.begin(),
+ aMainLast = aReferences.end();
+ for (; aMainIt != aMainLast; aMainIt++) {
+ FeaturePtr aMainListFeature = aMainIt->first;
+ std::set<FeaturePtr> aMainRefList = aMainIt->second;
+ std::set<FeaturePtr>::const_iterator aRefIt = aMainRefList.begin(),
+ aRefLast = aMainRefList.end();
+ bool aFeatureOutOfTheList = false;
+ for (; aRefIt != aRefLast && !aFeatureOutOfTheList; aRefIt++) {
+ FeaturePtr aRefFeature = *aRefIt;
+ aFeatureOutOfTheList = aReferences.find(aRefFeature) == aReferences.end();
+ }
+ if (!aFeatureOutOfTheList)
+ anUnusedObjects.insert(aMainListFeature);
+ }
+
+#ifdef DEBUG_CLEAN_HISTORY
+ anInfo.clear();
+ for (aFIt = anUnusedObjects.begin(); aFIt != anUnusedObjects.end(); ++aFIt) {
+ FeaturePtr aFeature = *aFIt;
+ anInfo.append(aFeature->name().c_str());
+ }
+ qDebug(QString("unused objects: [%1] - %2").
+ arg(anInfo.size()).arg(anInfo.join(";\t")).toStdString().c_str());
+#endif
+
+ // warn about the references remove, break the delete operation if the user chose it
+ if (!anUnusedObjects.empty()) {
+ QStringList aNames;
+ foreach (const FeaturePtr& aFeature, anUnusedObjects) {
+ aNames.append(aFeature->name().c_str());
+ }
+ aNames.sort();
+ 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);
+
+ const char* aKeyStr = "Unused features are the following: "
+ "%1.\nThese features will be deleted.\nWould you like to continue?";
+ QString aText = QString(tr(aKeyStr).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);
+
+ // WORKAROUND, should be done before each object remove, if it presents in XGUI_DataModel tree
+ // 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();
+
+ std::set<FeaturePtr> anIgnoredFeatures;
+ if (ModelAPI_Tools::removeFeatures(anUnusedObjects, true)) {
+ operationMgr()->commitOperation();
+ }
+ else {
+ operationMgr()->abortOperation(operationMgr()->currentOperation());
+ }