]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Issue #588: Renaming a parameter used in an expression Dev_1.2.1
authorspo <sergey.pokhodenko@opencascade.com>
Fri, 5 Jun 2015 10:45:13 +0000 (13:45 +0300)
committerspo <sergey.pokhodenko@opencascade.com>
Fri, 5 Jun 2015 10:45:31 +0000 (13:45 +0300)
src/Model/Model_Data.cpp
src/Model/Model_Update.cpp
src/ModelAPI/ModelAPI_Events.cpp
src/ModelAPI/ModelAPI_Events.h
src/ModelAPI/ModelAPI_Tools.h
src/NewGeom/NewGeom_Module.cpp
src/ParametersPlugin/ParametersPlugin_EvalListener.cpp
src/ParametersPlugin/ParametersPlugin_EvalListener.h
src/ParametersPlugin/ParametersPlugin_Parameter.cpp
src/ParametersPlugin/ParametersPlugin_PyInterp.cpp
src/ParametersPlugin/ParametersPlugin_PyInterp.h

index 05b276c97b422e8975c9ae259afc06c86510e9d6..1c6e6660e68db5ddd2bbba3b240a203346129951 100644 (file)
@@ -75,6 +75,7 @@ std::string Model_Data::name()
 void Model_Data::setName(const std::string& theName)
 {
   bool isModified = false;
+  std::string anOldName = name();
   Handle(TDataStd_Name) aName;
   if (!myLab.FindAttribute(TDataStd_Name::GetID(), aName)) {
     TDataStd_Name::Set(myLab, theName.c_str());
@@ -84,6 +85,8 @@ void Model_Data::setName(const std::string& theName)
     if (isModified)
       aName->Set(theName.c_str());
   }
+  if (isModified)
+    ModelAPI_ObjectRenamedMessage::send(myObject, anOldName, theName, this);
 }
 
 AttributePtr Model_Data::addAttribute(const std::string& theID, const std::string theAttrType)
index e937f38ef48de360a731647ef8e88d2b398b64a7..de514b6bf60b3aac70326079be5aa3914f090e12 100644 (file)
@@ -277,13 +277,13 @@ void Model_Update::updateArguments(FeaturePtr theFeature) {
     theFeature->data()->attributes(ModelAPI_AttributeDouble::typeId());
   std::list<AttributePtr>::iterator aDoubleIter = aDoubles.begin();
   for(; aDoubleIter != aDoubles.end(); aDoubleIter++) {
-    AttributeDoublePtr aDouble =
+    AttributeDoublePtr aDoubleAttribute =
       std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(*aDoubleIter);
-    if (aDouble.get() && !aDouble->text().empty()) {
+    if (aDoubleAttribute.get() && !aDoubleAttribute->text().empty()) {
       if (myIsParamUpdated) {
-        ModelAPI_AttributeEvalMessage::send(aDouble, this);
+        ModelAPI_AttributeEvalMessage::send(aDoubleAttribute, this);
       }
-      if (aDouble->expressionInvalid()) {
+      if (aDoubleAttribute->expressionInvalid()) {
         aState = ModelAPI_StateInvalidArgument;
       }
     }
index dbd088755502206ef3ce57e1cf4390110422115d..7c81efe539a70bbe17630b806d912ac49964634a 100644 (file)
@@ -108,7 +108,7 @@ void ModelAPI_DocumentCreatedMessage::setDocument(DocumentPtr theDocument)
 }
 
 ModelAPI_AttributeEvalMessage::ModelAPI_AttributeEvalMessage(const Events_ID theID,
-                                                                         const void* theSender)
+                                                             const void* theSender)
 : Events_Message(theID, theSender)
 {
 
@@ -128,3 +128,58 @@ void ModelAPI_AttributeEvalMessage::setAttribute(AttributePtr theDocument)
 {
   myAttribute = theDocument;
 }
+
+ModelAPI_ObjectRenamedMessage::ModelAPI_ObjectRenamedMessage(const Events_ID theID,
+                                                             const void* theSender)
+: Events_Message(theID, theSender)
+{
+
+}
+
+ModelAPI_ObjectRenamedMessage::~ModelAPI_ObjectRenamedMessage()
+{
+
+}
+
+void ModelAPI_ObjectRenamedMessage::send(ObjectPtr theObject,
+                                         const std::string& theOldName,
+                                         const std::string& theNewName,
+                                         const void* theSender)
+{
+  std::shared_ptr<ModelAPI_ObjectRenamedMessage> aMessage(
+    new ModelAPI_ObjectRenamedMessage(eventId(), theSender));
+  aMessage->setObject(theObject);
+  aMessage->setOldName(theOldName);
+  aMessage->setNewName(theNewName);
+  Events_Loop::loop()->send(aMessage);
+}
+
+ObjectPtr ModelAPI_ObjectRenamedMessage::object() const
+{
+  return myObject;
+}
+
+void ModelAPI_ObjectRenamedMessage::setObject(ObjectPtr theObject)
+{
+  myObject = theObject;
+}
+
+std::string ModelAPI_ObjectRenamedMessage::oldName() const
+{
+  return myOldName;
+}
+
+void ModelAPI_ObjectRenamedMessage::setOldName(const std::string& theOldName)
+{
+  myOldName = theOldName;
+}
+
+std::string ModelAPI_ObjectRenamedMessage::newName() const
+{
+  return myNewName;
+}
+
+void ModelAPI_ObjectRenamedMessage::setNewName(const std::string& theNewName)
+{
+  myNewName = theNewName;
+}
index e41c0999f917ff496f5418011038233e6018bebf..8b880e227a76f8426b7a54f14e672b148534ebf1 100644 (file)
@@ -28,6 +28,8 @@ static const char * EVENT_OBJECT_CREATED = "ObjectCreated";
 static const char * EVENT_OBJECT_UPDATED = "ObjectUpdated";
 /// Event ID that data of feature is deleted (comes with Model_ObjectDeletedMessage)
 static const char * EVENT_OBJECT_DELETED = "ObjectDeleted";
+/// Event ID that name of feature is changed (comes with Model_ObjectRenamedMessage)
+static const char * EVENT_OBJECT_RENAMED = "ObjectRenamed";
 /// Event ID that data of feature is updated (comes with ModelAPI_ObjectUpdatedMessage)
 static const char * EVENT_OBJECT_MOVED = "ObjectsMoved";
 /// Event ID that visualization must be redisplayed (comes with ModelAPI_ObjectUpdatedMessage)
@@ -112,7 +114,7 @@ public:
 
 // TODO(sbh): Move this message into a separate package, like "GuiAPI"
 /// Contains the state information about the feature: is it enabled or disabled.
-class ModelAPI_FeatureStateMessage : public Events_Message
+class MODELAPI_EXPORT ModelAPI_FeatureStateMessage : public Events_Message
 {
 public:
   /// Creates an empty message
@@ -142,7 +144,7 @@ public:
 };
 
 /// Message that document (Part, PartSet) was created
-class ModelAPI_DocumentCreatedMessage : public Events_Message
+class MODELAPI_EXPORT ModelAPI_DocumentCreatedMessage : public Events_Message
 {
   DocumentPtr myDocument;
 
@@ -165,7 +167,7 @@ class ModelAPI_DocumentCreatedMessage : public Events_Message
 };
 
 /// Message that attribute text should be evaluated in the attribute value
-class ModelAPI_AttributeEvalMessage : public Events_Message
+class MODELAPI_EXPORT ModelAPI_AttributeEvalMessage : public Events_Message
 {
   AttributePtr myAttribute;
 
@@ -181,8 +183,7 @@ class ModelAPI_AttributeEvalMessage : public Events_Message
   /// Useful method that creates and sends the AttributeEvalMessage event
   MODELAPI_EXPORT static void send(AttributePtr theAttribute, const void* theSender)
   {
-    std::shared_ptr<ModelAPI_AttributeEvalMessage> aMessage =
-      std::shared_ptr<ModelAPI_AttributeEvalMessage>(
+    std::shared_ptr<ModelAPI_AttributeEvalMessage> aMessage(
       new ModelAPI_AttributeEvalMessage(eventId(), theSender));
     aMessage->setAttribute(theAttribute);
     Events_Loop::loop()->send(aMessage);
@@ -199,4 +200,45 @@ class ModelAPI_AttributeEvalMessage : public Events_Message
   MODELAPI_EXPORT void setAttribute(AttributePtr theAttribute);
 };
 
+/// Message that the object is renamed
+class MODELAPI_EXPORT ModelAPI_ObjectRenamedMessage : public Events_Message
+{
+  ObjectPtr myObject;
+  std::string myOldName;
+  std::string myNewName;
+
+ public:
+  /// Static. Returns EventID of the message.
+  MODELAPI_EXPORT static Events_ID& eventId()
+  {
+    static const char * MY_OBJECT_RENAMED_EVENT_ID("ObjectRenamed");
+    static Events_ID anId = Events_Loop::eventByName(MY_OBJECT_RENAMED_EVENT_ID);
+    return anId;
+  }
+
+  /// Useful method that creates and sends the AttributeEvalMessage event
+  MODELAPI_EXPORT static void send(ObjectPtr theObject,
+                                   const std::string& theOldName,
+                                   const std::string& theNewName,
+                                   const void* theSender);
+
+  /// Creates an empty message
+  MODELAPI_EXPORT ModelAPI_ObjectRenamedMessage(const Events_ID theID, const void* theSender = 0);
+  /// The virtual destructor
+  MODELAPI_EXPORT virtual ~ModelAPI_ObjectRenamedMessage();
+
+  /// Returns an object
+  MODELAPI_EXPORT ObjectPtr object() const;
+  /// Sets an object
+  MODELAPI_EXPORT void setObject(ObjectPtr theObject);
+  /// Returns an old name
+  MODELAPI_EXPORT std::string oldName() const;
+  /// Sets an old name
+  MODELAPI_EXPORT void setOldName(const std::string& theOldName);
+  /// Returns a new name
+  MODELAPI_EXPORT std::string newName() const;
+  /// Sets a new name
+  MODELAPI_EXPORT void setNewName(const std::string& theNewName);
+};
+
 #endif
index 9bea2d9cd4ea7f1f3174e4e1af061c69498401d4..7b1f26bb061ba8c9ec72a220589f4299ba32427b 100644 (file)
@@ -23,8 +23,9 @@ MODELAPI_EXPORT std::shared_ptr<GeomAPI_Shape> shape(const ResultPtr& theResult)
  * in the root document (PartSet). If found, set it value in the \param outValue
  * and returns true.
  */
-MODELAPI_EXPORT bool findVariable(const std::string& theName, double& outValue, 
-  ResultParameterPtr& theParam);
+MODELAPI_EXPORT bool findVariable(const std::string& theName,
+                                  double& outValue,
+                                  ResultParameterPtr& theParam);
 
 /*!
  * Returns the values of the next random color. The values are in range [0, 255]
index 8265e654c66668f3b30c4acf870cb8d99f3b802a..e398f96ce3fc46dfbc18832666c118d3b802206d 100644 (file)
@@ -49,7 +49,7 @@ NewGeom_EXPORT CAM_Module* createModule()
   return new NewGeom_Module();
 }
 
-NewGeom_EXPORT char* getModuleVersion()
+NewGeom_EXPORT const char* getModuleVersion()
 {
   return "0.0";
 }
index 968c167696992d9599da1d20a57756b88352eff9..ae849a983d0c7a06caa1f35dc4f4479c812fd57c 100644 (file)
@@ -8,24 +8,35 @@
 #include <pyconfig.h>
 
 #include <ParametersPlugin_EvalListener.h>
+#include <ParametersPlugin_Parameter.h>
 #include <ParametersPlugin_PyInterp.h>
 
 #include <Events_Error.h>
 
+#include <ModelAPI_AttributeString.h>
+#include <ModelAPI_Document.h>
 #include <ModelAPI_Events.h>
+#include <ModelAPI_Session.h>
 #include <ModelAPI_Tools.h>
+
 #include <ModelAPI_AttributeDouble.h>
 #include <GeomDataAPI_Point.h>
 #include <GeomDataAPI_Point2D.h>
 
 #include <string>
 #include <sstream>
+#include <regex>
+
+//debug
+#include <iostream>
 
 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);
 
   myInterp = std::shared_ptr<ParametersPlugin_PyInterp>(new ParametersPlugin_PyInterp());
   myInterp->initialize();
@@ -35,77 +46,18 @@ ParametersPlugin_EvalListener::~ParametersPlugin_EvalListener()
 {
 }
 
-void ParametersPlugin_EvalListener::processEvent(const std::shared_ptr<Events_Message>& theMessage)
+void ParametersPlugin_EvalListener::processEvent(
+    const std::shared_ptr<Events_Message>& theMessage)
 {
   if (!theMessage.get())
     return;
 
   const Events_ID kEvaluationEvent = ModelAPI_AttributeEvalMessage::eventId();
+  const Events_ID kObjectRenamedEvent = ModelAPI_ObjectRenamedMessage::eventId();
   if (theMessage->eventID() == kEvaluationEvent) {
-    std::shared_ptr<ModelAPI_AttributeEvalMessage> aMessage =
-        std::dynamic_pointer_cast<ModelAPI_AttributeEvalMessage>(theMessage);
-
-    // Double
-    AttributeDoublePtr aDoubleAttribute =
-        std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(aMessage->attribute());
-    if (aDoubleAttribute.get()) {
-      std::string anError;
-      double aValue = evaluate(aDoubleAttribute->text(), anError);
-      if (anError.empty()) {
-        aDoubleAttribute->setValue(aValue);
-        aDoubleAttribute->setExpressionInvalid(false);
-      } else { // set feature as invalid-parameter arguments
-        aDoubleAttribute->setExpressionInvalid(true);
-      }
-    }
-
-    // Point
-    AttributePointPtr aPointAttribute =
-        std::dynamic_pointer_cast<GeomDataAPI_Point>(aMessage->attribute());
-    if (aPointAttribute.get()) {
-      std::string anError[3];
-      double aValue[3] = {
-          evaluate(aPointAttribute->textX(), anError[0]),
-          evaluate(aPointAttribute->textY(), anError[1]),
-          evaluate(aPointAttribute->textZ(), anError[2])
-      };
-      bool isValid[3] = {
-          anError[0].empty(),
-          anError[1].empty(),
-          anError[2].empty()
-      };
-      aPointAttribute->setExpressionInvalid(0, !isValid[0]);
-      aPointAttribute->setExpressionInvalid(1, !isValid[1]);
-      aPointAttribute->setExpressionInvalid(2, !isValid[2]);
-
-      aPointAttribute->setValue(
-          isValid[0] ? aValue[0] : aPointAttribute->x(),
-          isValid[1] ? aValue[1] : aPointAttribute->y(),
-          isValid[2] ? aValue[2] : aPointAttribute->z()
-      );
-    }
-
-    // Point2D
-    AttributePoint2DPtr aPoint2DAttribute =
-        std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aMessage->attribute());
-    if (aPoint2DAttribute.get()) {
-      std::string anError[2];
-      double aValue[2] = {
-          evaluate(aPoint2DAttribute->textX(), anError[0]),
-          evaluate(aPoint2DAttribute->textY(), anError[1])
-      };
-      bool isValid[2] = {
-          anError[0].empty(),
-          anError[1].empty()
-      };
-      aPoint2DAttribute->setExpressionInvalid(0, !isValid[0]);
-      aPoint2DAttribute->setExpressionInvalid(1, !isValid[1]);
-
-      aPoint2DAttribute->setValue(
-          isValid[0] ? aValue[0] : aPoint2DAttribute->x(),
-          isValid[1] ? aValue[1] : aPoint2DAttribute->y()
-      );
-    }
+    processEvaluationEvent(theMessage);
+  } else if (theMessage->eventID() == kObjectRenamedEvent) {
+    processObjectRenamedEvent(theMessage);
   } else {
     Events_Error::send(std::string("ParametersPlugin python interpreter, unhandled message caught: ")
                        + theMessage->eventID().eventText());
@@ -134,3 +86,207 @@ double ParametersPlugin_EvalListener::evaluate(const std::string& theExpression,
   myInterp->clearLocalContext();
   return result;
 }
+
+void ParametersPlugin_EvalListener::processEvaluationEvent(
+    const std::shared_ptr<Events_Message>& theMessage)
+{
+  std::shared_ptr<ModelAPI_AttributeEvalMessage> aMessage =
+      std::dynamic_pointer_cast<ModelAPI_AttributeEvalMessage>(theMessage);
+
+  // Double
+  AttributeDoublePtr aDoubleAttribute =
+      std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(aMessage->attribute());
+  if (aDoubleAttribute.get()) {
+    std::string anError;
+    double aValue = evaluate(aDoubleAttribute->text(), anError);
+    if (anError.empty()) {
+      aDoubleAttribute->setValue(aValue);
+      aDoubleAttribute->setExpressionInvalid(false);
+    } else { // set feature as invalid-parameter arguments
+      aDoubleAttribute->setExpressionInvalid(true);
+    }
+  }
+
+  // Point
+  AttributePointPtr aPointAttribute =
+      std::dynamic_pointer_cast<GeomDataAPI_Point>(aMessage->attribute());
+  if (aPointAttribute.get()) {
+    std::string anError[3];
+    double aValue[3] = {
+        evaluate(aPointAttribute->textX(), anError[0]),
+        evaluate(aPointAttribute->textY(), anError[1]),
+        evaluate(aPointAttribute->textZ(), anError[2])
+    };
+    bool isValid[3] = {
+        anError[0].empty(),
+        anError[1].empty(),
+        anError[2].empty()
+    };
+    aPointAttribute->setExpressionInvalid(0, !isValid[0]);
+    aPointAttribute->setExpressionInvalid(1, !isValid[1]);
+    aPointAttribute->setExpressionInvalid(2, !isValid[2]);
+
+    aPointAttribute->setValue(
+        isValid[0] ? aValue[0] : aPointAttribute->x(),
+        isValid[1] ? aValue[1] : aPointAttribute->y(),
+        isValid[2] ? aValue[2] : aPointAttribute->z()
+    );
+  }
+
+  // Point2D
+  AttributePoint2DPtr aPoint2DAttribute =
+      std::dynamic_pointer_cast<GeomDataAPI_Point2D>(aMessage->attribute());
+  if (aPoint2DAttribute.get()) {
+    std::string anError[2];
+    double aValue[2] = {
+        evaluate(aPoint2DAttribute->textX(), anError[0]),
+        evaluate(aPoint2DAttribute->textY(), anError[1])
+    };
+    bool isValid[2] = {
+        anError[0].empty(),
+        anError[1].empty()
+    };
+    aPoint2DAttribute->setExpressionInvalid(0, !isValid[0]);
+    aPoint2DAttribute->setExpressionInvalid(1, !isValid[1]);
+
+    aPoint2DAttribute->setValue(
+        isValid[0] ? aValue[0] : aPoint2DAttribute->x(),
+        isValid[1] ? aValue[1] : aPoint2DAttribute->y()
+    );
+  }
+}
+
+std::string ParametersPlugin_EvalListener::renameInPythonExpression(
+    const std::string& theExpression,
+    const std::string& theOldName,
+    const std::string& theNewName)
+{
+  std::string anExpressionString = theExpression;
+
+  std::list<std::pair<int, int> > aPositions =
+      myInterp->positions(anExpressionString, theOldName);
+
+  if (aPositions.empty())
+    return anExpressionString;
+
+  std::map<int, std::list<int> > aLines;
+  std::list<std::pair<int, int> >::const_iterator it = aPositions.begin();
+  for (; it != aPositions.end(); ++it)
+    aLines[it->first].push_back(it->second);
+
+  // Start renaming from the end to keep indexes if theNewName is longer then theOldName
+  std::map<int, std::list<int> >::const_reverse_iterator ritLine = aLines.rbegin();
+  for (; ritLine != aLines.rend(); ++ritLine) {
+    // Calculate the start of the line (find the aLineNo occurrence of "\n" )
+    int aLineNo = ritLine->first - 1;
+    size_t aLineStart = 0;
+    for (int i = 0; i < aLineNo; ++i)
+      aLineStart = anExpressionString.find("\n", aLineStart) + 1;
+
+    const std::list<int>& aColOffsets = ritLine->second;
+    std::list<int>::const_reverse_iterator ritOffset = aColOffsets.rbegin();
+    for (; ritOffset != aColOffsets.rend(); ++ritOffset) {
+      int anOffset = *ritOffset;
+      anExpressionString.replace(aLineStart + anOffset, theOldName.size(), theNewName);
+    }
+  }
+
+  return anExpressionString;
+}
+
+void ParametersPlugin_EvalListener::renameInParameter(
+    std::shared_ptr<ParametersPlugin_Parameter> theParameter,
+    const std::string& theOldName,
+    const std::string& theNewName)
+{
+  std::shared_ptr<ModelAPI_AttributeString> anExpressionAttribute =
+      theParameter->string(ParametersPlugin_Parameter::EXPRESSION_ID());
+
+  std::string anExpressionString = anExpressionAttribute->value();
+  anExpressionString = renameInPythonExpression(anExpressionString,
+                                                theOldName,
+                                                theNewName);
+  anExpressionAttribute->setValue(anExpressionString);
+}
+
+void renameInAttribute(std::shared_ptr<ModelAPI_Attribute> theAttribute,
+                       const std::string& theOldName,
+                       const std::string& theNewName)
+{
+  // TODO: implement
+
+  // dynamic_cast<Double, Point, Point2D>(attribute)
+  // rename(attribute)
+}
+
+void ParametersPlugin_EvalListener::processObjectRenamedEvent(
+    const std::shared_ptr<Events_Message>& theMessage)
+{
+  std::shared_ptr<ModelAPI_ObjectRenamedMessage> aMessage =
+      std::dynamic_pointer_cast<ModelAPI_ObjectRenamedMessage>(theMessage);
+
+  // List of documents to process
+  std::list<DocumentPtr> aDocList;
+  SessionPtr aSession = ModelAPI_Session::get();
+  DocumentPtr aDocument = aSession->activeDocument();
+  DocumentPtr aRootDocument = aSession->moduleDocument();
+  aDocList.push_back(aDocument);
+  if (aDocument != aRootDocument) {
+    aDocList.push_back(aRootDocument);
+  }
+  // Find parameters
+  for (std::list<DocumentPtr>::const_iterator it = aDocList.begin(); it != aDocList.end(); ++it) {
+    DocumentPtr aDocument = *it;
+
+    for (int anIndex = 0, aSize = aDocument->size(ModelAPI_ResultParameter::group());
+         anIndex < aSize; ++anIndex) {
+      std::shared_ptr<ModelAPI_ResultParameter> aResultParameter =
+          std::dynamic_pointer_cast<ModelAPI_ResultParameter>(
+              aDocument->object(ModelAPI_ResultParameter::group(), anIndex));
+      if (!aResultParameter.get())
+        continue;
+
+      std::shared_ptr<ParametersPlugin_Parameter> aParameter =
+          std::dynamic_pointer_cast<ParametersPlugin_Parameter>(
+              aDocument->feature(aResultParameter));
+      if (!aParameter.get())
+        continue;
+
+//      std::cout << "Rename expression of parameter " << aParameter->string(ParametersPlugin_Parameter::VARIABLE_ID())->value()
+//          << " (" << aMessage->oldName() << ", " << aMessage->newName() << ")" << std::endl;
+
+      // Rename
+      renameInParameter(aParameter, aMessage->oldName(), aMessage->newName());
+    }
+  }
+// TODO: implement renaming in attributes for the next version
+/*
+  // Find features
+  for (std::list<DocumentPtr>::const_iterator it = aDocList.begin(); it != aDocList.end(); ++it) {
+    DocumentPtr aDocument = *it;
+    for (int anIndex = 0, aSize = aDocument->size(ModelAPI_Feature::group());
+         anIndex < aSize; ++anIndex) {
+      std::shared_ptr<ModelAPI_Feature> aFeature =
+          std::dynamic_pointer_cast<ModelAPI_Feature>(
+              aDocument->object(ModelAPI_Feature::group(), anIndex));
+      if (!aFeature.get())
+        continue;
+
+      std::list<std::shared_ptr<ModelAPI_Attribute> > anAttributes =
+          aFeature->data()->attributes(std::string());
+
+      std::list<std::shared_ptr<ModelAPI_Attribute> >::const_iterator it =
+          anAttributes.begin();
+      for (; it != anAttributes.end(); ++it) {
+
+        std::cout << "Rename expression of attribute " << aFeature->data()->id(*it)
+            << " (" << aMessage->oldName() << ", " << aMessage->newName() << ")" << std::endl;
+
+        // Rename
+        renameInAttribute(*it, aMessage->oldName(), aMessage->newName());
+      }
+    }
+  }
+*/
+}
+
index 50c5727f2e195f097f48642872c0adea63b6aefc..cc754a0d8c307dafae20c396de627a2aa8e317db 100644 (file)
@@ -11,6 +11,7 @@
 #include <ParametersPlugin.h>
 #include <Events_Loop.h>
 
+class ParametersPlugin_Parameter;
 class ParametersPlugin_PyInterp;
 
 class PARAMETERSPLUGIN_EXPORT ParametersPlugin_EvalListener : public Events_Listener
@@ -22,8 +23,17 @@ class PARAMETERSPLUGIN_EXPORT ParametersPlugin_EvalListener : public Events_List
   virtual void processEvent(const std::shared_ptr<Events_Message>& theMessage);
 
  protected:
-  double evaluate(const std::string& theExpression,
-                  std::string& theError) ;
+  double evaluate(const std::string& theExpression, std::string& theError);
+
+  void processEvaluationEvent(const std::shared_ptr<Events_Message>& theMessage);
+  void processObjectRenamedEvent(const std::shared_ptr<Events_Message>& theMessage);
+
+  std::string renameInPythonExpression(const std::string& theExpression,
+                                       const std::string& theOldName,
+                                       const std::string& theNewName);
+  void renameInParameter(std::shared_ptr<ParametersPlugin_Parameter> theParameter,
+                         const std::string& theOldName,
+                         const std::string& theNewName);
 
  private:
   std::shared_ptr<ParametersPlugin_PyInterp> myInterp;
index 9d64cef324a22e09e892f139bbd54aabded6c348..dcf69dda6840748e0ba53e33c12d5097ab69ca9d 100644 (file)
@@ -48,7 +48,7 @@ void ParametersPlugin_Parameter::attributeChanged(const std::string& theID)
   if (theID == EXPRESSION_ID()) { // recompute only on change of the expression
     ResultParameterPtr aParam = document()->createParameter(data());
 
-    std::string anExpression = string(EXPRESSION_ID())->value();
+    std::string anExpression = this->string(EXPRESSION_ID())->value();
     if(anExpression.empty()) {
       // clear error/result if the expression is empty
       setError("", false);
@@ -57,7 +57,7 @@ void ParametersPlugin_Parameter::attributeChanged(const std::string& theID)
     std::string outErrorMessage;
     double aValue = evaluate(anExpression, outErrorMessage);
     // Name
-    std::string aName = string(VARIABLE_ID())->value();
+    std::string aName = this->string(VARIABLE_ID())->value();
     std::ostringstream sstream;
     sstream << aValue;
     std::string aParamValue = sstream.str();
@@ -88,7 +88,6 @@ void ParametersPlugin_Parameter::execute()
 
 double ParametersPlugin_Parameter::evaluate(const std::string& theExpression, std::string& theError)
 {
-
   std::list<std::string> anExprParams = myInterp->compile(theExpression);
   // find expression's params in the model
   std::list<std::string> aContext;
index 53659f23fdbd89ab61bc1438f5a380aa2575e536..ae82e5dfcaa58aa43d04d3c649b1f25bbc17a14d 100644 (file)
@@ -10,6 +10,8 @@
 #include <string>
 #include <stdexcept>
 
+#include <iostream>
+
 ParametersPlugin_PyInterp::ParametersPlugin_PyInterp()
 : PyInterp_Interp()
 {
@@ -19,6 +21,54 @@ ParametersPlugin_PyInterp::~ParametersPlugin_PyInterp()
 {
 }
 
+const char* aSearchCode =
+  "import ast\n"
+  "class FindName(ast.NodeVisitor):\n"
+  "    def __init__(self, name):\n"
+  "        self.name = name\n"
+  "    def visit_Name(self, node):\n"
+  "        if node.id == self.name:\n"
+  "            positions.append((node.lineno, node.col_offset))\n"
+  "FindName(name).visit(ast.parse(expression))";
+
+std::list<std::pair<int, int> >
+ParametersPlugin_PyInterp::positions(const std::string& theExpression,
+                                     const std::string& theName)
+{
+  PyLockWrapper lck; // Acquire GIL until the end of the method
+
+  std::list<std::pair<int, int> > aResult;
+
+  PyObject* aContext = PyDict_New();
+
+  PyObject* aBuiltinModule = PyImport_AddModule("__builtin__");
+  PyDict_SetItemString(aContext, "__builtins__", aBuiltinModule);
+  Py_DECREF(aBuiltinModule);
+
+  PyDict_SetItemString(aContext, "expression", PyString_FromString(theExpression.c_str()));
+  PyDict_SetItemString(aContext, "name", PyString_FromString(theName.c_str()));
+  PyDict_SetItemString(aContext, "positions", Py_BuildValue("[]"));
+
+  PyObject* aExecResult = PyRun_String(aSearchCode, Py_file_input, aContext, aContext);
+  Py_XDECREF(aExecResult);
+
+  PyObject* aPositions = PyDict_GetItemString(aContext, "positions");
+  for (int anIndex = 0; anIndex < PyList_Size(aPositions); ++anIndex) {
+    PyObject* aPosition = PyList_GetItem(aPositions, anIndex);
+    PyObject* aLineNo = PyTuple_GetItem(aPosition, 0);
+    PyObject* aColOffset = PyTuple_GetItem(aPosition, 1);
+
+    aResult.push_back(
+        std::pair<int, int>((int)PyInt_AsLong(aLineNo),
+                            (int)PyInt_AsLong(aColOffset)));
+  }
+
+  Py_DECREF(aContext);
+
+  return aResult;
+}
+
+
 std::list<std::string> ParametersPlugin_PyInterp::compile(const std::string& theExpression)
 {
   PyLockWrapper lck; // Acquire GIL until the end of the method
index 0a631f6e22f42ce3e30251ad9869bc29efd3f12a..32b5c6d31a7fc19de72e355af8290405a7ad7722 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <list>
 #include <string>
+#include <utility>
 
 class PARAMETERSPLUGIN_EXPORT ParametersPlugin_PyInterp : public PyInterp_Interp
 {
@@ -20,6 +21,8 @@ class PARAMETERSPLUGIN_EXPORT ParametersPlugin_PyInterp : public PyInterp_Interp
   ParametersPlugin_PyInterp();
   virtual ~ParametersPlugin_PyInterp();
 
+  std::list<std::pair<int, int> > positions(const std::string& theExpression,
+                                            const std::string& theName);
   std::list<std::string> compile(const std::string&);
   void extendLocalContext(const std::list<std::string>&);
   void clearLocalContext();