Salome HOME
EvalListener to evaluate expression from inputs
authorsbh <sergey.belash@opencascade.com>
Thu, 30 Apr 2015 14:32:02 +0000 (17:32 +0300)
committersbh <sergey.belash@opencascade.com>
Thu, 30 Apr 2015 14:32:02 +0000 (17:32 +0300)
12 files changed:
src/ModelAPI/ModelAPI_Events.cpp
src/ModelAPI/ModelAPI_Events.h
src/ModuleBase/ModuleBase_ParamSpinBox.cpp
src/ModuleBase/ModuleBase_WidgetDoubleValue.cpp
src/ModuleBase/ModuleBase_WidgetEditor.cpp
src/ParametersPlugin/CMakeLists.txt
src/ParametersPlugin/ParametersPlugin_EvalListener.cpp [new file with mode: 0644]
src/ParametersPlugin/ParametersPlugin_EvalListener.h [new file with mode: 0644]
src/ParametersPlugin/ParametersPlugin_Parameter.cpp
src/ParametersPlugin/ParametersPlugin_Parameter.h
src/ParametersPlugin/ParametersPlugin_Plugin.cpp
src/ParametersPlugin/ParametersPlugin_Plugin.h

index 5127ad2b623fa1e9b044fdec42201226982f9a29..dbd088755502206ef3ce57e1cf4390110422115d 100644 (file)
@@ -85,7 +85,8 @@ std::list<std::string> ModelAPI_FeatureStateMessage::features() const
 }
 
 
-ModelAPI_DocumentCreatedMessage::ModelAPI_DocumentCreatedMessage(const Events_ID theID, const void* theSender)
+ModelAPI_DocumentCreatedMessage::ModelAPI_DocumentCreatedMessage(const Events_ID theID,
+                                                                 const void* theSender)
 : Events_Message(theID, theSender)
 {
 
@@ -105,3 +106,25 @@ void ModelAPI_DocumentCreatedMessage::setDocument(DocumentPtr theDocument)
 {
   myDocument = theDocument;
 }
+
+ModelAPI_AttributeEvalMessage::ModelAPI_AttributeEvalMessage(const Events_ID theID,
+                                                                         const void* theSender)
+: Events_Message(theID, theSender)
+{
+
+}
+
+ModelAPI_AttributeEvalMessage::~ModelAPI_AttributeEvalMessage()
+{
+
+}
+
+AttributePtr ModelAPI_AttributeEvalMessage::attribute() const
+{
+  return myAttribute;
+}
+
+void ModelAPI_AttributeEvalMessage::setAttribute(AttributePtr theDocument)
+{
+  myAttribute = theDocument;
+}
index 00e61330a7634b121fe47a5fc8361fe63229b7c1..69153a98847fc449c4962a6aeb0145a27ae4983d 100644 (file)
@@ -10,6 +10,7 @@
 #include <ModelAPI.h>
 #include <ModelAPI_Object.h>
 #include <ModelAPI_Feature.h>
+#include <ModelAPI_Attribute.h>
 #include <Events_MessageGroup.h>
 #include <Events_Loop.h>
 
@@ -167,4 +168,27 @@ class ModelAPI_DocumentCreatedMessage : public Events_Message
   MODELAPI_EXPORT void setDocument(DocumentPtr theDocument);
 };
 
+/// Message that attribute text should be evaluated in the attribute value
+class ModelAPI_AttributeEvalMessage : public Events_Message
+{
+  AttributePtr myAttribute;
+
+ public:
+  /// Creates an empty message
+  MODELAPI_EXPORT ModelAPI_AttributeEvalMessage(const Events_ID theID, const void* theSender = 0);
+  /// The virtual destructor
+  MODELAPI_EXPORT virtual ~ModelAPI_AttributeEvalMessage();
+  /// Static. Returns EventID of the message.
+  MODELAPI_EXPORT static Events_ID eventId()
+  {
+    static const char * MY_ATTRIBUTE_EVALUATION_EVENT_ID("AttributeEvaluationRequest");
+    return Events_Loop::eventByName(MY_ATTRIBUTE_EVALUATION_EVENT_ID);
+  }
+
+  /// Returns a document stored in the message
+  MODELAPI_EXPORT AttributePtr attribute() const;
+  /// Sets a document to the message
+  MODELAPI_EXPORT void setAttribute(AttributePtr theDocument);
+};
+
 #endif
index 1fdad51d3682ff889c22d401bd96be370ce285e5..41f697bf6875506aba537e2d6aff7eba253a15db 100644 (file)
@@ -83,12 +83,11 @@ void ModuleBase_ParamSpinBox::onTextChanged(const QString& text)
  */
 double ModuleBase_ParamSpinBox::valueFromText(const QString& theText) const
 {
-  if (!hasVariable(theText))
+  if (!hasVariable(theText)) {
     return ModuleBase_DoubleSpinBox::valueFromText(theText);
-
-  double aValue = 0;
-  findVariable(theText, aValue);
-  return aValue;
+  }
+  // small hack: return length of the string to iniiate valuesChanged signal
+  return theText.length();
 }
 
 QString ModuleBase_ParamSpinBox::textFromValue (double theValue) const
@@ -112,21 +111,8 @@ QValidator::State ModuleBase_ParamSpinBox::validate(QString& str, int& pos) cons
     return ModuleBase_DoubleSpinBox::validate(str, pos);
 
   QValidator::State res = QValidator::Invalid;
-
-  // Considering the input text as a variable name
-  // Applying Python identifier syntax:
-  // either a string starting with a letter, or a string starting with
-  // an underscore followed by at least one alphanumeric character
   if (isAcceptVariables()) {
-    QRegExp varNameMask("[_a-zA-Z][a-zA-Z0-9_]*");
-    if (varNameMask.exactMatch(str))
-      res = QValidator::Acceptable;
-
-    if (res == QValidator::Invalid) {
-      varNameMask.setPattern("_");
-      if (varNameMask.exactMatch(str))
-        res = QValidator::Intermediate;
-    }
+    res = QValidator::Acceptable;
   }
   return res;
 }
@@ -176,8 +162,8 @@ bool ModuleBase_ParamSpinBox::hasVariable() const
 
 bool ModuleBase_ParamSpinBox::hasVariable(const QString& theText) const
 {
-  QRegExp varNameMask("([a-z]|[A-Z]|_).*");
-  return varNameMask.exactMatch(theText);
+  QRegExp varNameMask("[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?");
+  return !varNameMask.exactMatch(theText);
 }
 
 /*!
index b7faf46d67d51fac88ebdc595b7f35379b4df1c3..6aa383688e69272c252472f1fcbfb9075fb0a418 100644 (file)
@@ -4,27 +4,27 @@
 // Created:     04 June 2014
 // Author:      Vitaly Smetannikov
 
-#include <ModuleBase_WidgetDoubleValue.h>
-#include <ModuleBase_ParamSpinBox.h>
-#include <ModuleBase_Tools.h>
-
-#include <ModelAPI_AttributeDouble.h>
-#include <ModelAPI_AttributeString.h>
-#include <ModelAPI_Data.h>
-
 #include <Config_Keywords.h>
 #include <Config_WidgetAPI.h>
 
-#include <Events_Loop.h>
+#include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_Data.h>
+#include <ModelAPI_Object.h>
 #include <ModelAPI_Events.h>
 
-#include <QWidget>
+#include <ModuleBase_ParamSpinBox.h>
+#include <ModuleBase_Tools.h>
+#include <ModuleBase_WidgetDoubleValue.h>
+
 #include <QFormLayout>
 #include <QLabel>
-#include <QEvent>
-#include <QTimer>
+#include <QList>
+#include <QObject>
+#include <QPixmap>
+#include <QString>
 
-#include <math.h>
+#include <cfloat>
+#include <xstring>
 
 #ifndef DBL_MAX
 #define DBL_MAX 1.7976931348623158e+308 
@@ -87,7 +87,7 @@ ModuleBase_WidgetDoubleValue::ModuleBase_WidgetDoubleValue(QWidget* theParent,
   mySpinBox->setToolTip(aTTip);
 
   aControlLay->addRow(myLabel, mySpinBox);
-  connect(mySpinBox, SIGNAL(valueChanged(double)), this, SIGNAL(valuesChanged()));
+  connect(mySpinBox, SIGNAL(valueChanged(const QString&)), this, SIGNAL(valuesChanged()));
 }
 
 ModuleBase_WidgetDoubleValue::~ModuleBase_WidgetDoubleValue()
@@ -116,14 +116,19 @@ bool ModuleBase_WidgetDoubleValue::storeValueCustom() const
 {
   DataPtr aData = myFeature->data();
   AttributeDoublePtr aReal = aData->real(attributeID());
-  aReal->setValue(mySpinBox->value());
-  std::string aTextRepr = aReal->text();
-  if (mySpinBox->hasVariable()) {
-    aTextRepr = mySpinBox->text().toStdString();
+  if (!mySpinBox->hasVariable()) {
+    aReal->setValue(mySpinBox->value());
   } else {
-    aTextRepr = "";
+    // Here is a text of a real value or an expression.
+    std::string aText = mySpinBox->text().toStdString();
+    aReal->setText(aText);
+    // Send it to evaluator to convert into the double and store in the attribute
+    static Events_ID anId = ModelAPI_AttributeEvalMessage::eventId();
+    std::shared_ptr<ModelAPI_AttributeEvalMessage> aMessage =
+      std::shared_ptr<ModelAPI_AttributeEvalMessage>(new ModelAPI_AttributeEvalMessage(anId, this));
+    aMessage->setAttribute(aData->attribute(attributeID()));
+    Events_Loop::loop()->send(aMessage);
   }
-  aReal->setText(aTextRepr);
   updateObject(myFeature);
   return true;
 }
index 29e07a1f3efb95bb39f6d5c61e9c620b4abc08ac..1c26b11ebf3b0aa43ee8ac060a66976cfa7c160a 100644 (file)
@@ -62,7 +62,7 @@ void editedValue(double& outValue, QString& outText)
   double aValue = outText.toDouble(&isDouble);
   if (isDouble) {
     outValue = aValue;
-    outText = ""; // return empty string, if it's can be converted to a double
+  //  outText = ""; // return empty string, if it's can be converted to a double
   }
   aPopup->deleteLater();
 }
index f3f6dd255f5530db09cef7b3c955b120a49a4184..4111075fb0ab39f2ec3faa817342ecfa30de24da 100644 (file)
@@ -8,6 +8,7 @@ SET(PROJECT_HEADERS
     ParametersPlugin_Parameter.h
     ParametersPlugin_PyInterp.h
     ParametersPlugin_Validators.h
+    ParametersPlugin_EvalListener.h
 )
  
 SET(PROJECT_SOURCES
@@ -15,6 +16,7 @@ SET(PROJECT_SOURCES
     ParametersPlugin_Parameter.cpp
     ParametersPlugin_PyInterp.cpp
     ParametersPlugin_Validators.cpp
+    ParametersPlugin_EvalListener.cpp
 )
 
 SET(XML_RESOURCES
diff --git a/src/ParametersPlugin/ParametersPlugin_EvalListener.cpp b/src/ParametersPlugin/ParametersPlugin_EvalListener.cpp
new file mode 100644 (file)
index 0000000..ff05cd5
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * ParametersPlugin_EvalListener.cpp
+ *
+ *  Created on: Apr 28, 2015
+ *      Author: sbh
+ */
+
+#include <ParametersPlugin_EvalListener.h>
+
+#include <Events_Error.h>
+
+#include <ModelAPI_Events.h>
+#include <ModelAPI_Tools.h>
+#include <ModelAPI_AttributeDouble.h>
+
+#include <string>
+#include <sstream>
+
+ParametersPlugin_EvalListener::ParametersPlugin_EvalListener()
+{
+  Events_Loop* aLoop = Events_Loop::loop();
+  const Events_ID kEvaluationEvent = ModelAPI_AttributeEvalMessage::eventId();
+  aLoop->registerListener(this, kEvaluationEvent, NULL, true);
+
+  myInterp = std::shared_ptr<ParametersPlugin_PyInterp>(new ParametersPlugin_PyInterp());
+  myInterp->initialize();
+}
+
+ParametersPlugin_EvalListener::~ParametersPlugin_EvalListener()
+{
+}
+
+void ParametersPlugin_EvalListener::processEvent(const std::shared_ptr<Events_Message>& theMessage)
+{
+  if (!theMessage.get())
+    return;
+
+  const Events_ID kEvaluationEvent = ModelAPI_AttributeEvalMessage::eventId();
+  if (theMessage->eventID() == kEvaluationEvent) {
+    std::shared_ptr<ModelAPI_AttributeEvalMessage> aMessage =
+        std::dynamic_pointer_cast<ModelAPI_AttributeEvalMessage>(theMessage);
+    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);
+      }
+    }
+  } else {
+    Events_Error::send(std::string("ParametersPlugin python interpreter, unhandled message caught: ")
+                       + theMessage->eventID().eventText());
+  }
+}
+
+double ParametersPlugin_EvalListener::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;
+  std::list<std::string>::iterator it = anExprParams.begin();
+  for ( ; it != anExprParams.end(); it++) {
+    double aValue;
+    if (!ModelAPI_Tools::findVariable(*it, aValue)) continue;
+
+    std::ostringstream sstream;
+    sstream << aValue;
+    std::string aParamValue = sstream.str();
+    aContext.push_back(*it + "=" + aParamValue);
+  }
+  myInterp->extendLocalContext(aContext);
+  double result = myInterp->evaluate(theExpression, theError);
+  myInterp->clearLocalContext();
+  return result;
+}
+
diff --git a/src/ParametersPlugin/ParametersPlugin_EvalListener.h b/src/ParametersPlugin/ParametersPlugin_EvalListener.h
new file mode 100644 (file)
index 0000000..057ca79
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * ParametersPlugin_EvalListener.h
+ *
+ *  Created on: Apr 28, 2015
+ *      Author: sbh
+ */
+
+#ifndef SRC_PARAMETERSPLUGIN_EVALLISTENER_H_
+#define SRC_PARAMETERSPLUGIN_EVALLISTENER_H_
+
+#include <ParametersPlugin.h>
+#include <Events_Loop.h>
+#include <ParametersPlugin_PyInterp.h>
+
+class PARAMETERSPLUGIN_EXPORT ParametersPlugin_EvalListener : public Events_Listener
+{
+ public:
+  ParametersPlugin_EvalListener();
+  virtual ~ParametersPlugin_EvalListener();
+
+  virtual void processEvent(const std::shared_ptr<Events_Message>& theMessage);
+
+ protected:
+  double evaluate(const std::string& theExpression,
+                  std::string& theError) ;
+
+ private:
+  std::shared_ptr<ParametersPlugin_PyInterp> myInterp;
+};
+
+#endif /* SRC_PARAMETERSPLUGIN_PARAMETERSPLUGIN_EVALLISTENER_H_ */
index 48f5d731236e99c4d008b66a7bccb0206c73d53f..f9fdc7c6d114d6493101b5874747048e15ffef87 100644 (file)
 
 ParametersPlugin_Parameter::ParametersPlugin_Parameter()
 {
-  myInterp = new ParametersPlugin_PyInterp();
+  myInterp = std::shared_ptr<ParametersPlugin_PyInterp>(new ParametersPlugin_PyInterp());
   myInterp->initialize();
 }
 
 ParametersPlugin_Parameter::~ParametersPlugin_Parameter()
 {
-  delete myInterp;
 }
 
 void ParametersPlugin_Parameter::initAttributes()
index db6c54c515a77955022ff06eb31c2448a653c394..a65a5ff38005e82ebb6971b70065aad056e48a5d 100644 (file)
@@ -10,6 +10,8 @@
 #include "ParametersPlugin.h"
 #include <ModelAPI_Feature.h>
 
+#include <memory>
+
 class ParametersPlugin_PyInterp;
 
 class ParametersPlugin_Parameter : public ModelAPI_Feature
@@ -62,7 +64,7 @@ class ParametersPlugin_Parameter : public ModelAPI_Feature
   double evaluate(const std::string& theExpression, std::string& theError);
 
  private:
-  ParametersPlugin_PyInterp* myInterp;
+  std::shared_ptr<ParametersPlugin_PyInterp> myInterp;
 };
 
 #endif
index 97fa7a9fdd795f27fd0e09d3323f7bce50bebffe..e80aa1b69c32e47652491f31936e6f435c11aa7f 100644 (file)
@@ -23,6 +23,8 @@ ParametersPlugin_Plugin::ParametersPlugin_Plugin()
                               new ParametersPlugin_VariableValidator);
   aFactory->registerValidator("Parameters_ExpressionValidator",
                               new ParametersPlugin_ExpressionValidator);
+
+  myEvalListener = std::shared_ptr<ParametersPlugin_EvalListener>(new ParametersPlugin_EvalListener());
 }
 
 FeaturePtr ParametersPlugin_Plugin::createFeature(std::string theFeatureID)
index d82198f60ed0db673ba03da83f1d0f8cc9e7c157..d4d35283fe705245ca095c054f700fcef2959978 100644 (file)
@@ -4,6 +4,8 @@
 #define PARAMETERSPLUGIN_PLUGIN_H_
 
 #include <ParametersPlugin.h>
+#include <ParametersPlugin_EvalListener.h>
+
 #include <ModelAPI_Plugin.h>
 #include <ModelAPI_Feature.h>
 
@@ -18,6 +20,8 @@ class PARAMETERSPLUGIN_EXPORT ParametersPlugin_Plugin : public ModelAPI_Plugin
 
  public:
   ParametersPlugin_Plugin();
+
+  std::shared_ptr<ParametersPlugin_EvalListener> myEvalListener;
 };
 
 #endif