Salome HOME
Issue #818 - Deletion of a parameter used in a feature -- Replace parameters
authorspo <sergey.pokhodenko@opencascade.com>
Thu, 17 Sep 2015 05:52:19 +0000 (08:52 +0300)
committerspo <sergey.pokhodenko@opencascade.com>
Thu, 17 Sep 2015 05:53:52 +0000 (08:53 +0300)
src/ModelAPI/ModelAPI_Events.cpp
src/ModelAPI/ModelAPI_Events.h
src/ParametersPlugin/ParametersPlugin_EvalListener.cpp
src/ParametersPlugin/ParametersPlugin_EvalListener.h
src/XGUI/XGUI_Workshop.cpp

index 85c6c02b7bad6e0e65224fd0adff8299cff9bd0c..278867e0afd7b814c2564cde0321ade8e84c8b8b 100644 (file)
@@ -195,3 +195,34 @@ void ModelAPI_ObjectRenamedMessage::setNewName(const std::string& theNewName)
 {
   myNewName = theNewName;
 }
+
+ModelAPI_ReplaceParameterMessage::ModelAPI_ReplaceParameterMessage(const Events_ID theID,
+                                                                   const void* theSender)
+: Events_Message(theID, theSender)
+{
+
+}
+
+ModelAPI_ReplaceParameterMessage::~ModelAPI_ReplaceParameterMessage()
+{
+
+}
+
+void ModelAPI_ReplaceParameterMessage::send(ObjectPtr theObject,
+                                            const void* theSender)
+{
+  std::shared_ptr<ModelAPI_ReplaceParameterMessage> aMessage(
+      new ModelAPI_ReplaceParameterMessage(eventId(), theSender));
+  aMessage->setObject(theObject);
+  Events_Loop::loop()->send(aMessage);
+}
+
+ObjectPtr ModelAPI_ReplaceParameterMessage::object() const
+{
+  return myObject;
+}
+
+void ModelAPI_ReplaceParameterMessage::setObject(ObjectPtr theObject)
+{
+  myObject = theObject;
+}
index 4ba952cf5eb0a0d04218b06729cf13a448140bb3..45349a52c3c97fb6415be40b221a9d36e4d3aab6 100644 (file)
@@ -273,4 +273,33 @@ class ModelAPI_ObjectRenamedMessage : public Events_Message
   MODELAPI_EXPORT void setNewName(const std::string& theNewName);
 };
 
+/// Message that the parameter should be replaced with its value
+class ModelAPI_ReplaceParameterMessage : public Events_Message
+{
+  ObjectPtr myObject;
+
+ public:
+  /// Static. Returns EventID of the message.
+  MODELAPI_EXPORT static Events_ID& eventId()
+  {
+    static const char * MY_EVENT_ID("ReplaceParameter");
+    static Events_ID anId = Events_Loop::eventByName(MY_EVENT_ID);
+    return anId;
+  }
+
+  /// Useful method that creates and sends the AttributeEvalMessage event
+  MODELAPI_EXPORT static void send(ObjectPtr theObject,
+                                   const void* theSender);
+
+  /// Creates an empty message
+  MODELAPI_EXPORT ModelAPI_ReplaceParameterMessage(const Events_ID theID, const void* theSender = 0);
+  /// The virtual destructor
+  MODELAPI_EXPORT virtual ~ModelAPI_ReplaceParameterMessage();
+
+  /// Returns an object
+  MODELAPI_EXPORT ObjectPtr object() const;
+  /// Sets an object
+  MODELAPI_EXPORT void setObject(ObjectPtr theObject);
+};
+
 #endif
index 029800afa4e2dcf7315b865d1cf863d20045f0b2..8b5e915eeb7e8738996239d481757839d23f2411 100644 (file)
 #include <set>
 #include <sstream>
 
+//------------------------------------------------------------------------------
+// Tools
+
+std::string toStdString(double theValue)
+{
+  std::ostringstream sstream;
+  sstream << theValue;
+  return sstream.str();
+}
+
+std::set<std::string> toSet(const std::list<std::string>& theContainer)
+{
+  return std::set<std::string>(theContainer.begin(), theContainer.end());
+}
+
+//------------------------------------------------------------------------------
+
 ParametersPlugin_EvalListener::ParametersPlugin_EvalListener()
 {
   Events_Loop* aLoop = Events_Loop::loop();
-  const Events_ID kEvaluationEvent = ModelAPI_AttributeEvalMessage::eventId();
-  aLoop->registerListener(this, kEvaluationEvent, NULL, true);
-  const Events_ID kObjectRenamedEvent = ModelAPI_ObjectRenamedMessage::eventId();
-  aLoop->registerListener(this, kObjectRenamedEvent, NULL, true);
+
+  Events_ID anEvents_IDs[] = {
+      ModelAPI_AttributeEvalMessage::eventId(),
+      ModelAPI_ObjectRenamedMessage::eventId(),
+      ModelAPI_ReplaceParameterMessage::eventId()
+  };
+
+  for (int i = 0; i < sizeof(anEvents_IDs)/sizeof(anEvents_IDs[0]); ++i)
+    aLoop->registerListener(this, anEvents_IDs[i], NULL, true);
 
   myInterp = std::shared_ptr<ParametersPlugin_PyInterp>(new ParametersPlugin_PyInterp());
   myInterp->initialize();
@@ -53,10 +75,14 @@ void ParametersPlugin_EvalListener::processEvent(
 
   const Events_ID kEvaluationEvent = ModelAPI_AttributeEvalMessage::eventId();
   const Events_ID kObjectRenamedEvent = ModelAPI_ObjectRenamedMessage::eventId();
+  const Events_ID kReplaceParameterEvent = ModelAPI_ReplaceParameterMessage::eventId();
+
   if (theMessage->eventID() == kEvaluationEvent) {
     processEvaluationEvent(theMessage);
   } else if (theMessage->eventID() == kObjectRenamedEvent) {
     processObjectRenamedEvent(theMessage);
+  } else if (theMessage->eventID() == kReplaceParameterEvent) {
+    processReplaceParameterEvent(theMessage);
   } else {
     Events_Error::send(std::string("ParametersPlugin python interpreter, unhandled message caught: ")
                        + theMessage->eventID().eventText());
@@ -76,10 +102,7 @@ double ParametersPlugin_EvalListener::evaluate(const std::string& theExpression,
     // If variable does not exist python interpreter will generate an error. It is OK.
     if (!ModelAPI_Tools::findVariable(*it, aValue, aParamRes, theDocument)) continue;
 
-    std::ostringstream sstream;
-    sstream << aValue;
-    std::string aParamValue = sstream.str();
-    aContext.push_back(*it + "=" + aParamValue);
+    aContext.push_back(*it + "=" + toStdString(aValue));
   }
   myInterp->extendLocalContext(aContext);
   double result = myInterp->evaluate(theExpression, theError);
@@ -87,11 +110,6 @@ double ParametersPlugin_EvalListener::evaluate(const std::string& theExpression,
   return result;
 }
 
-std::set<std::string> toSet(const std::list<std::string>& theContainer)
-{
-  return std::set<std::string>(theContainer.begin(), theContainer.end());
-}
-
 void ParametersPlugin_EvalListener::processEvaluationEvent(
     const std::shared_ptr<Events_Message>& theMessage)
 {
@@ -261,6 +279,37 @@ void ParametersPlugin_EvalListener::renameInAttribute(
   }
 }
 
+void ParametersPlugin_EvalListener::renameInDependants(std::shared_ptr<ModelAPI_ResultParameter> theResultParameter,
+                                                       const std::string& theNewName)
+{
+  // get parameter feature for the result
+  std::shared_ptr<ParametersPlugin_Parameter> aParameter =
+      std::dynamic_pointer_cast<ParametersPlugin_Parameter>(
+          ModelAPI_Feature::feature(theResultParameter));
+  if (!aParameter.get())
+    return;
+
+  std::string anOldName = aParameter->string(ParametersPlugin_Parameter::VARIABLE_ID())->value();
+
+  std::set<std::shared_ptr<ModelAPI_Attribute> > anAttributes =
+      theResultParameter->data()->refsToMe();
+  std::set<std::shared_ptr<ModelAPI_Attribute> >::const_iterator anAttributeIt =
+      anAttributes.cbegin();
+  for (; anAttributeIt != anAttributes.cend(); ++anAttributeIt) {
+    const AttributePtr& anAttribute = *anAttributeIt;
+    if (anAttribute->attributeType() == ModelAPI_AttributeRefList::typeId()) {
+      std::shared_ptr<ParametersPlugin_Parameter> aParameter =
+          std::dynamic_pointer_cast<ParametersPlugin_Parameter>(
+              anAttribute->owner());
+      if (aParameter.get())
+        // Rename
+        renameInParameter(aParameter, anOldName, theNewName);
+    } else
+        // Rename
+        renameInAttribute(anAttribute, anOldName, theNewName);
+  }
+}
+
 bool isValidAttribute(const AttributePtr& theAttribute)
 {
   std::string aValidator, anError;
@@ -317,24 +366,30 @@ void ParametersPlugin_EvalListener::processObjectRenamedEvent(
     return;
   }
 
-  std::set<std::shared_ptr<ModelAPI_Attribute> > anAttributes = 
-      aResultParameter->data()->refsToMe();
-  std::set<std::shared_ptr<ModelAPI_Attribute> >::const_iterator anAttributeIt =
-      anAttributes.cbegin();
-  for (; anAttributeIt != anAttributes.cend(); ++anAttributeIt) {
-    const AttributePtr& anAttribute = *anAttributeIt;
-    AttributeRefListPtr anAttributeRefList =
-        std::dynamic_pointer_cast<ModelAPI_AttributeRefList>(anAttribute);
-    if (anAttributeRefList.get()) {
-      std::shared_ptr<ParametersPlugin_Parameter> aParameter =
-          std::dynamic_pointer_cast<ParametersPlugin_Parameter>(
-              anAttributeRefList->owner());
-      if (aParameter.get())
-        // Rename
-        renameInParameter(aParameter, aMessage->oldName(), aMessage->newName());
-    } else
-        // Rename
-        renameInAttribute(anAttribute, aMessage->oldName(), aMessage->newName());
-  }
+  renameInDependants(aResultParameter, aMessage->newName());
 }
 
+void ParametersPlugin_EvalListener::processReplaceParameterEvent(
+    const std::shared_ptr<Events_Message>& theMessage)
+{
+  std::shared_ptr<ModelAPI_ReplaceParameterMessage> aMessage =
+      std::dynamic_pointer_cast<ModelAPI_ReplaceParameterMessage>(theMessage);
+
+  // get parameter feature for the object
+  std::shared_ptr<ParametersPlugin_Parameter> aParameter =
+      std::dynamic_pointer_cast<ParametersPlugin_Parameter>(
+          ModelAPI_Feature::feature(aMessage->object()));
+  if (!aParameter.get())
+    return;
+
+  ResultParameterPtr aResultParameter =
+      std::dynamic_pointer_cast<ModelAPI_ResultParameter>(
+          aParameter->firstResult());
+  if (!aResultParameter.get())
+    return;
+
+  double aRealValue = aResultParameter->data()->real(ModelAPI_ResultParameter::VALUE())->value();
+  std::string aValue = toStdString(aRealValue);
+
+  renameInDependants(aResultParameter, aValue);
+}
index 02b5e6c523d4d717def9b701ad1d800b9b6aa088..56bb88dd47fe12acf9c62121e31fc497b41b7534 100644 (file)
@@ -13,6 +13,7 @@
 
 class ModelAPI_Attribute;
 class ModelAPI_Document;
+class ModelAPI_ResultParameter;
 class ParametersPlugin_Parameter;
 class ParametersPlugin_PyInterp;
 
@@ -30,6 +31,7 @@ class ParametersPlugin_EvalListener : public Events_Listener
 
   void processEvaluationEvent(const std::shared_ptr<Events_Message>& theMessage);
   void processObjectRenamedEvent(const std::shared_ptr<Events_Message>& theMessage);
+  void processReplaceParameterEvent(const std::shared_ptr<Events_Message>& theMessage);
 
   std::string renameInPythonExpression(const std::string& theExpression,
                                        const std::string& theOldName,
@@ -40,6 +42,8 @@ class ParametersPlugin_EvalListener : public Events_Listener
   void renameInAttribute(std::shared_ptr<ModelAPI_Attribute> theAttribute,
                          const std::string& theOldName,
                          const std::string& theNewName);
+  void renameInDependants(std::shared_ptr<ModelAPI_ResultParameter> theResultParameter,
+                          const std::string& theNewName);
 
  private:
   std::shared_ptr<ParametersPlugin_PyInterp> myInterp;
index 5d0e12c5dac6f0f5886beea0559814cfeee1810d..4638e3890644966d206c407481cdb0880fe56043 100644 (file)
@@ -1218,50 +1218,83 @@ bool XGUI_Workshop::deleteFeatures(const QObjectPtrList& theList,
                         std::inserter(aDifference, aDifference.begin()));
     aIndirectRefFeatures = aDifference;
   }
+
+  bool doDeleteReferences = true;
+
   // 2. warn about the references remove, break the delete operation if the user chose it
   if (theAskAboutDeleteReferences && !aDirectRefFeatures.empty()) {
     QStringList aDirectRefNames;
-    foreach(const FeaturePtr& aFeature, aDirectRefFeatures)
+    foreach (const FeaturePtr& aFeature, aDirectRefFeatures)
       aDirectRefNames.append(aFeature->name().c_str());
     QString aDirectNames = aDirectRefNames.join(", ");
 
     QStringList aIndirectRefNames;
-    foreach(const FeaturePtr& aFeature, aIndirectRefFeatures)
+    foreach (const FeaturePtr& aFeature, aIndirectRefFeatures)
       aIndirectRefNames.append(aFeature->name().c_str());
     QString aIndirectNames = aIndirectRefNames.join(", ");
 
-    QMessageBox::StandardButton aRes = QMessageBox::warning(
-        theParent, tr("Delete features"),
-        QString(tr("Selected features are used in the following features: %1.\
- These features will be deleted.\n%2Would you like to continue?")).arg(aDirectNames)
-            .arg(aIndirectNames.isEmpty() ? QString() : QString("Also these features will be deleted: %1.\n").arg(aIndirectNames)),
-        QMessageBox::No | QMessageBox::Yes, QMessageBox::No);
-    if (aRes != QMessageBox::Yes)
+    bool canReplaceParameters = true;
+    foreach (ObjectPtr aObj, theList) {
+      FeaturePtr aFeature = ModelAPI_Feature::feature(aObj);
+      if (aFeature->getKind() != "Parameter") {
+        canReplaceParameters = false;
+        break;
+      }
+    }
+
+    QMessageBox aMessageBox(theParent);
+    aMessageBox.setWindowTitle(tr("Delete features"));
+    aMessageBox.setIcon(QMessageBox::Warning);
+    aMessageBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes);
+    aMessageBox.setDefaultButton(QMessageBox::No);
+
+    QString aText;
+    if (canReplaceParameters) {
+      aText = QString(tr("Selected parameters are used in the following features: %1.\nThese features will be deleted.\n%2Or parameters could be replaced with its values.\nWould you like to continue?"))
+          .arg(aDirectNames).arg(aIndirectNames.isEmpty() ? QString() : QString(tr("(Also these features will be deleted: %1)\n")).arg(aIndirectNames));
+      QPushButton *aReplaceButton = aMessageBox.addButton(tr("Replace"), QMessageBox::ActionRole);
+    } else {
+      aText = QString(tr("Selected features are used in the following features: %1.\nThese features will be deleted.\n%2Would you like to continue?"))
+          .arg(aDirectNames).arg(aIndirectNames.isEmpty() ? QString() : QString(tr("Also these features will be deleted: %1.\n")).arg(aIndirectNames));
+    }
+    aMessageBox.setText(aText);
+    aMessageBox.exec();
+    QMessageBox::ButtonRole aButtonRole = aMessageBox.buttonRole(aMessageBox.clickedButton());
+
+    if (aButtonRole == QMessageBox::NoRole)
       return false;
+
+    if (aButtonRole == QMessageBox::ActionRole) {
+      foreach (ObjectPtr aObj, theList)
+        ModelAPI_ReplaceParameterMessage::send(aObj, this);
+      doDeleteReferences = false;
+    }
   }
 
   // 3. remove referenced features
-  std::set<FeaturePtr> aFeaturesToDelete = aDirectRefFeatures;
-  aFeaturesToDelete.insert(aIndirectRefFeatures.begin(), aIndirectRefFeatures.end());
-  std::set<FeaturePtr>::const_iterator anIt = aFeaturesToDelete.begin(),
-                                       aLast = aFeaturesToDelete.end();
+  if (doDeleteReferences) {
+    std::set<FeaturePtr> aFeaturesToDelete = aDirectRefFeatures;
+    aFeaturesToDelete.insert(aIndirectRefFeatures.begin(), aIndirectRefFeatures.end());
+    std::set<FeaturePtr>::const_iterator anIt = aFeaturesToDelete.begin(),
+                                         aLast = aFeaturesToDelete.end();
 #ifdef DEBUG_DELETE
-  QStringList anInfo;
+    QStringList anInfo;
 #endif
-  for (; anIt != aLast; anIt++) {
-    FeaturePtr aFeature = (*anIt);
-    DocumentPtr aDoc = aFeature->document();
-    if (theIgnoredFeatures.find(aFeature) == theIgnoredFeatures.end()) {
-      aDoc->removeFeature(aFeature);
+    for (; anIt != aLast; anIt++) {
+      FeaturePtr aFeature = (*anIt);
+      DocumentPtr aDoc = aFeature->document();
+      if (theIgnoredFeatures.find(aFeature) == theIgnoredFeatures.end()) {
+        aDoc->removeFeature(aFeature);
 #ifdef DEBUG_DELETE
-      anInfo.append(ModuleBase_Tools::objectInfo(aFeature).toStdString().c_str());
+        anInfo.append(ModuleBase_Tools::objectInfo(aFeature).toStdString().c_str());
 #endif
+      }
     }
-  }
 #ifdef DEBUG_DELETE
-  qDebug(QString("remove references:%1").arg(anInfo.join("; ")).toStdString().c_str());
-  anInfo.clear();
+    qDebug(QString("remove references:%1").arg(anInfo.join("; ")).toStdString().c_str());
+    anInfo.clear();
 #endif
+  }
 
   QString anActionId = "DELETE_CMD";
   QString anId = QString::fromStdString(anActionId.toStdString().c_str());