From: sbh Date: Thu, 30 Apr 2015 14:32:02 +0000 (+0300) Subject: EvalListener to evaluate expression from inputs X-Git-Tag: V_1.2.0~179 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=f6e1c2edc336a593bfab00c3402920e378a903d1;p=modules%2Fshaper.git EvalListener to evaluate expression from inputs --- diff --git a/src/ModelAPI/ModelAPI_Events.cpp b/src/ModelAPI/ModelAPI_Events.cpp index 5127ad2b6..dbd088755 100644 --- a/src/ModelAPI/ModelAPI_Events.cpp +++ b/src/ModelAPI/ModelAPI_Events.cpp @@ -85,7 +85,8 @@ std::list 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; +} diff --git a/src/ModelAPI/ModelAPI_Events.h b/src/ModelAPI/ModelAPI_Events.h index 00e61330a..69153a988 100644 --- a/src/ModelAPI/ModelAPI_Events.h +++ b/src/ModelAPI/ModelAPI_Events.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -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 diff --git a/src/ModuleBase/ModuleBase_ParamSpinBox.cpp b/src/ModuleBase/ModuleBase_ParamSpinBox.cpp index 1fdad51d3..41f697bf6 100644 --- a/src/ModuleBase/ModuleBase_ParamSpinBox.cpp +++ b/src/ModuleBase/ModuleBase_ParamSpinBox.cpp @@ -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); } /*! diff --git a/src/ModuleBase/ModuleBase_WidgetDoubleValue.cpp b/src/ModuleBase/ModuleBase_WidgetDoubleValue.cpp index b7faf46d6..6aa383688 100644 --- a/src/ModuleBase/ModuleBase_WidgetDoubleValue.cpp +++ b/src/ModuleBase/ModuleBase_WidgetDoubleValue.cpp @@ -4,27 +4,27 @@ // Created: 04 June 2014 // Author: Vitaly Smetannikov -#include -#include -#include - -#include -#include -#include - #include #include -#include +#include +#include +#include #include -#include +#include +#include +#include + #include #include -#include -#include +#include +#include +#include +#include -#include +#include +#include #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 aMessage = + std::shared_ptr(new ModelAPI_AttributeEvalMessage(anId, this)); + aMessage->setAttribute(aData->attribute(attributeID())); + Events_Loop::loop()->send(aMessage); } - aReal->setText(aTextRepr); updateObject(myFeature); return true; } diff --git a/src/ModuleBase/ModuleBase_WidgetEditor.cpp b/src/ModuleBase/ModuleBase_WidgetEditor.cpp index 29e07a1f3..1c26b11eb 100644 --- a/src/ModuleBase/ModuleBase_WidgetEditor.cpp +++ b/src/ModuleBase/ModuleBase_WidgetEditor.cpp @@ -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(); } diff --git a/src/ParametersPlugin/CMakeLists.txt b/src/ParametersPlugin/CMakeLists.txt index f3f6dd255..4111075fb 100644 --- a/src/ParametersPlugin/CMakeLists.txt +++ b/src/ParametersPlugin/CMakeLists.txt @@ -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 index 000000000..ff05cd510 --- /dev/null +++ b/src/ParametersPlugin/ParametersPlugin_EvalListener.cpp @@ -0,0 +1,78 @@ +/* + * ParametersPlugin_EvalListener.cpp + * + * Created on: Apr 28, 2015 + * Author: sbh + */ + +#include + +#include + +#include +#include +#include + +#include +#include + +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(new ParametersPlugin_PyInterp()); + myInterp->initialize(); +} + +ParametersPlugin_EvalListener::~ParametersPlugin_EvalListener() +{ +} + +void ParametersPlugin_EvalListener::processEvent(const std::shared_ptr& theMessage) +{ + if (!theMessage.get()) + return; + + const Events_ID kEvaluationEvent = ModelAPI_AttributeEvalMessage::eventId(); + if (theMessage->eventID() == kEvaluationEvent) { + std::shared_ptr aMessage = + std::dynamic_pointer_cast(theMessage); + AttributeDoublePtr aDoubleAttribute = + std::dynamic_pointer_cast(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 anExprParams = myInterp->compile(theExpression); + // find expression's params in the model + std::list aContext; + std::list::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 index 000000000..057ca7924 --- /dev/null +++ b/src/ParametersPlugin/ParametersPlugin_EvalListener.h @@ -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 +#include +#include + +class PARAMETERSPLUGIN_EXPORT ParametersPlugin_EvalListener : public Events_Listener +{ + public: + ParametersPlugin_EvalListener(); + virtual ~ParametersPlugin_EvalListener(); + + virtual void processEvent(const std::shared_ptr& theMessage); + + protected: + double evaluate(const std::string& theExpression, + std::string& theError) ; + + private: + std::shared_ptr myInterp; +}; + +#endif /* SRC_PARAMETERSPLUGIN_PARAMETERSPLUGIN_EVALLISTENER_H_ */ diff --git a/src/ParametersPlugin/ParametersPlugin_Parameter.cpp b/src/ParametersPlugin/ParametersPlugin_Parameter.cpp index 48f5d7312..f9fdc7c6d 100644 --- a/src/ParametersPlugin/ParametersPlugin_Parameter.cpp +++ b/src/ParametersPlugin/ParametersPlugin_Parameter.cpp @@ -17,13 +17,12 @@ ParametersPlugin_Parameter::ParametersPlugin_Parameter() { - myInterp = new ParametersPlugin_PyInterp(); + myInterp = std::shared_ptr(new ParametersPlugin_PyInterp()); myInterp->initialize(); } ParametersPlugin_Parameter::~ParametersPlugin_Parameter() { - delete myInterp; } void ParametersPlugin_Parameter::initAttributes() diff --git a/src/ParametersPlugin/ParametersPlugin_Parameter.h b/src/ParametersPlugin/ParametersPlugin_Parameter.h index db6c54c51..a65a5ff38 100644 --- a/src/ParametersPlugin/ParametersPlugin_Parameter.h +++ b/src/ParametersPlugin/ParametersPlugin_Parameter.h @@ -10,6 +10,8 @@ #include "ParametersPlugin.h" #include +#include + 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 myInterp; }; #endif diff --git a/src/ParametersPlugin/ParametersPlugin_Plugin.cpp b/src/ParametersPlugin/ParametersPlugin_Plugin.cpp index 97fa7a9fd..e80aa1b69 100644 --- a/src/ParametersPlugin/ParametersPlugin_Plugin.cpp +++ b/src/ParametersPlugin/ParametersPlugin_Plugin.cpp @@ -23,6 +23,8 @@ ParametersPlugin_Plugin::ParametersPlugin_Plugin() new ParametersPlugin_VariableValidator); aFactory->registerValidator("Parameters_ExpressionValidator", new ParametersPlugin_ExpressionValidator); + + myEvalListener = std::shared_ptr(new ParametersPlugin_EvalListener()); } FeaturePtr ParametersPlugin_Plugin::createFeature(std::string theFeatureID) diff --git a/src/ParametersPlugin/ParametersPlugin_Plugin.h b/src/ParametersPlugin/ParametersPlugin_Plugin.h index d82198f60..d4d35283f 100644 --- a/src/ParametersPlugin/ParametersPlugin_Plugin.h +++ b/src/ParametersPlugin/ParametersPlugin_Plugin.h @@ -4,6 +4,8 @@ #define PARAMETERSPLUGIN_PLUGIN_H_ #include +#include + #include #include @@ -18,6 +20,8 @@ class PARAMETERSPLUGIN_EXPORT ParametersPlugin_Plugin : public ModelAPI_Plugin public: ParametersPlugin_Plugin(); + + std::shared_ptr myEvalListener; }; #endif