X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FParametersPlugin%2FParametersPlugin_EvalListener.cpp;h=029800afa4e2dcf7315b865d1cf863d20045f0b2;hb=853e0eec6016120b641efa6adf427a239cf203cf;hp=ff05cd51027ccdcd8c5a95ee0ed2b7cfe392c386;hpb=fccb11b890bf75fde316cd0dbc911fa001368062;p=modules%2Fshaper.git diff --git a/src/ParametersPlugin/ParametersPlugin_EvalListener.cpp b/src/ParametersPlugin/ParametersPlugin_EvalListener.cpp index ff05cd510..029800afa 100644 --- a/src/ParametersPlugin/ParametersPlugin_EvalListener.cpp +++ b/src/ParametersPlugin/ParametersPlugin_EvalListener.cpp @@ -5,15 +5,28 @@ * Author: sbh */ +#include + #include +#include +#include #include +#include +#include +#include +#include #include +#include #include + #include +#include +#include #include +#include #include ParametersPlugin_EvalListener::ParametersPlugin_EvalListener() @@ -21,6 +34,8 @@ 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(new ParametersPlugin_PyInterp()); myInterp->initialize(); @@ -30,32 +45,26 @@ ParametersPlugin_EvalListener::~ParametersPlugin_EvalListener() { } -void ParametersPlugin_EvalListener::processEvent(const std::shared_ptr& theMessage) +void ParametersPlugin_EvalListener::processEvent( + const std::shared_ptr& 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 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); - } - } + processEvaluationEvent(theMessage); + } else if (theMessage->eventID() == kObjectRenamedEvent) { + processObjectRenamedEvent(theMessage); } 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) +double ParametersPlugin_EvalListener::evaluate(const std::string& theExpression, std::string& theError, + const std::shared_ptr& theDocument) { std::list anExprParams = myInterp->compile(theExpression); // find expression's params in the model @@ -63,7 +72,9 @@ double ParametersPlugin_EvalListener::evaluate(const std::string& theExpression, std::list::iterator it = anExprParams.begin(); for ( ; it != anExprParams.end(); it++) { double aValue; - if (!ModelAPI_Tools::findVariable(*it, aValue)) continue; + ResultParameterPtr aParamRes; + // 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; @@ -76,3 +87,254 @@ double ParametersPlugin_EvalListener::evaluate(const std::string& theExpression, return result; } +std::set toSet(const std::list& theContainer) +{ + return std::set(theContainer.begin(), theContainer.end()); +} + +void ParametersPlugin_EvalListener::processEvaluationEvent( + const std::shared_ptr& theMessage) +{ + std::shared_ptr aMessage = + std::dynamic_pointer_cast(theMessage); + + if (aMessage->attribute()->attributeType() == ModelAPI_AttributeDouble::typeId()) { + AttributeDoublePtr anAttribute = + std::dynamic_pointer_cast(aMessage->attribute()); + std::string anError; + double aValue = evaluate(anAttribute->text(), anError, anAttribute->owner()->document()); + bool isValid = anError.empty(); + if (isValid) + anAttribute->setCalculatedValue(aValue); + anAttribute->setUsedParameters(isValid ? toSet(myInterp->compile(anAttribute->text())) : std::set()); + anAttribute->setExpressionInvalid(!isValid); + anAttribute->setExpressionError(anAttribute->text().empty() ? "" : anError); + } else + if (aMessage->attribute()->attributeType() == GeomDataAPI_Point::typeId()) { + AttributePointPtr anAttribute = + std::dynamic_pointer_cast(aMessage->attribute()); + std::string aText[] = { + anAttribute->textX(), + anAttribute->textY(), + anAttribute->textZ() + }; + double aCalculatedValue[] = { + anAttribute->x(), + anAttribute->y(), + anAttribute->z() + }; + for (int i = 0; i < 3; ++i) { + std::string anError; + double aValue = evaluate(aText[i], anError, anAttribute->owner()->document()); + bool isValid = anError.empty(); + if (isValid) aCalculatedValue[i] = aValue; + anAttribute->setUsedParameters(i, isValid ? toSet(myInterp->compile(aText[i])) : std::set()); + anAttribute->setExpressionInvalid(i, !isValid); + anAttribute->setExpressionError(i, aText[i].empty() ? "" : anError); + } + anAttribute->setCalculatedValue(aCalculatedValue[0], + aCalculatedValue[1], + aCalculatedValue[2]); + } else + if (aMessage->attribute()->attributeType() == GeomDataAPI_Point2D::typeId()) { + AttributePoint2DPtr anAttribute = + std::dynamic_pointer_cast(aMessage->attribute()); + std::string aText[] = { + anAttribute->textX(), + anAttribute->textY() + }; + double aCalculatedValue[] = { + anAttribute->x(), + anAttribute->y() + }; + for (int i = 0; i < 2; ++i) { + std::string anError; + double aValue = evaluate(aText[i], anError, anAttribute->owner()->document()); + bool isValid = anError.empty(); + if (isValid) aCalculatedValue[i] = aValue; + anAttribute->setUsedParameters(i, isValid ? toSet(myInterp->compile(aText[i])) : std::set()); + anAttribute->setExpressionInvalid(i, !isValid); + anAttribute->setExpressionError(i, aText[i].empty() ? "" : anError); + } + anAttribute->setCalculatedValue(aCalculatedValue[0], + aCalculatedValue[1]); + } +} + +std::string ParametersPlugin_EvalListener::renameInPythonExpression( + const std::string& theExpression, + const std::string& theOldName, + const std::string& theNewName) +{ + std::string anExpressionString = theExpression; + + std::list > aPositions = + myInterp->positions(anExpressionString, theOldName); + + if (aPositions.empty()) + return anExpressionString; + + std::map > aLines; + std::list >::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 >::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& aColOffsets = ritLine->second; + std::list::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 theParameter, + const std::string& theOldName, + const std::string& theNewName) +{ + std::shared_ptr anExpressionAttribute = + theParameter->string(ParametersPlugin_Parameter::EXPRESSION_ID()); + + std::string anExpressionString = anExpressionAttribute->value(); + anExpressionString = renameInPythonExpression(anExpressionString, + theOldName, + theNewName); + // Issue #588. No need for reevaluating expression. + // Moreover, current history may not contain necessary parameters. + anExpressionAttribute->owner()->data()->blockSendAttributeUpdated(true); + anExpressionAttribute->setValue(anExpressionString); + anExpressionAttribute->owner()->data()->blockSendAttributeUpdated(false); +} + +void ParametersPlugin_EvalListener::renameInAttribute( + std::shared_ptr theAttribute, + const std::string& theOldName, + const std::string& theNewName) +{ + if (theAttribute->attributeType() == ModelAPI_AttributeDouble::typeId()) { + AttributeDoublePtr anAttribute = + std::dynamic_pointer_cast(theAttribute); + std::string anExpressionString = anAttribute->text(); + anExpressionString = renameInPythonExpression(anExpressionString, + theOldName, theNewName); + anAttribute->setText(anExpressionString); + } else + if (theAttribute->attributeType() == GeomDataAPI_Point::typeId()) { + AttributePointPtr anAttribute = + std::dynamic_pointer_cast(theAttribute); + std::string anExpressionString[3] = { + anAttribute->textX(), + anAttribute->textY(), + anAttribute->textZ() + }; + for (int i = 0; i < 3; ++i) + anExpressionString[i] = renameInPythonExpression(anExpressionString[i], + theOldName, theNewName); + anAttribute->setText(anExpressionString[0], + anExpressionString[1], + anExpressionString[2]); + } else + if (theAttribute->attributeType() == GeomDataAPI_Point2D::typeId()) { + AttributePoint2DPtr anAttribute = + std::dynamic_pointer_cast(theAttribute); + std::string anExpressionString[2] = { + anAttribute->textX(), + anAttribute->textY() + }; + for (int i = 0; i < 2; ++i) + anExpressionString[i] = renameInPythonExpression(anExpressionString[i], + theOldName, theNewName); + anAttribute->setText(anExpressionString[0], + anExpressionString[1]); + } +} + +bool isValidAttribute(const AttributePtr& theAttribute) +{ + std::string aValidator, anError; + return ModelAPI_Session::get()->validators()->validate(theAttribute, aValidator, anError); +} + +void setParameterName(ResultParameterPtr theResultParameter, const std::string& theName) +{ + theResultParameter->data()->blockSendAttributeUpdated(true); + theResultParameter->data()->setName(theName); + theResultParameter->data()->blockSendAttributeUpdated(false); + + std::shared_ptr aParameter = + std::dynamic_pointer_cast( + ModelAPI_Feature::feature(theResultParameter)); + + aParameter->data()->blockSendAttributeUpdated(true); + aParameter->data()->setName(theName); + aParameter->string(ParametersPlugin_Parameter::VARIABLE_ID())->setValue(theName); + aParameter->data()->blockSendAttributeUpdated(false); +} + +void ParametersPlugin_EvalListener::processObjectRenamedEvent( + const std::shared_ptr& theMessage) +{ + std::shared_ptr aMessage = + std::dynamic_pointer_cast(theMessage); + + // Empty new name is not available too but it will be rejected by + // name validator in isValidAttribute. + if (!aMessage.get() || aMessage->oldName().empty()) + return; + + // check if the renamed object is a result parameter + ResultParameterPtr aResultParameter = + std::dynamic_pointer_cast(aMessage->object()); + if (!aResultParameter.get()) + return; + + // get parameter feature for the result + std::shared_ptr aParameter = + std::dynamic_pointer_cast( + ModelAPI_Feature::feature(aResultParameter)); + if (!aParameter.get()) + return; + + // try to update the parameter feature according the new name + setParameterName(aResultParameter, aMessage->newName()); + // TODO(spo): replace with ModelAPI_Session::get()->validators()->validate(aParameter, ParametersPlugin_Parameter::VARIABLE_ID()) + // when ModelAPI_ValidatorsFactory::validate(const std::shared_ptr& theFeature, const std::string& theAttribute) const + // is ready + if (!isValidAttribute(aParameter->string(ParametersPlugin_Parameter::VARIABLE_ID()))) { + setParameterName(aResultParameter, aMessage->oldName()); + return; + } + + std::set > anAttributes = + aResultParameter->data()->refsToMe(); + std::set >::const_iterator anAttributeIt = + anAttributes.cbegin(); + for (; anAttributeIt != anAttributes.cend(); ++anAttributeIt) { + const AttributePtr& anAttribute = *anAttributeIt; + AttributeRefListPtr anAttributeRefList = + std::dynamic_pointer_cast(anAttribute); + if (anAttributeRefList.get()) { + std::shared_ptr aParameter = + std::dynamic_pointer_cast( + anAttributeRefList->owner()); + if (aParameter.get()) + // Rename + renameInParameter(aParameter, aMessage->oldName(), aMessage->newName()); + } else + // Rename + renameInAttribute(anAttribute, aMessage->oldName(), aMessage->newName()); + } +} +