Skip to content

Commit

Permalink
Evaluate expressions in the annotation (#9730)
Browse files Browse the repository at this point in the history
* Evaluate expressions in the annotation

Fixes #6111, fixes #9453

* Fix build

* Fix ExpressionTest

* Catch exception

Print space only for not operator

* Look for the variable binding value in components and in extends
  • Loading branch information
adeas31 committed Nov 22, 2022
1 parent 9644352 commit 3caf7a9
Show file tree
Hide file tree
Showing 15 changed files with 199 additions and 83 deletions.
1 change: 1 addition & 0 deletions OMEdit/OMEditLIB/Annotations/BitmapAnnotation.cpp
Expand Up @@ -168,6 +168,7 @@ void BitmapAnnotation::parseShapeAnnotation()
GraphicItem::parseShapeAnnotation(mpBitmap);

mExtent = mpBitmap->getExtent();
mExtent.evaluate(mpBitmap->getParentModel());
setFileName(StringHandler::removeFirstLastQuotes(stripDynamicSelect(mpBitmap->getFileName())));
mImageSource = StringHandler::removeFirstLastQuotes(stripDynamicSelect(mpBitmap->getImageSource()));
if (!mImageSource.isEmpty()) {
Expand Down
47 changes: 38 additions & 9 deletions OMEdit/OMEditLIB/Annotations/DynamicAnnotation.cpp
Expand Up @@ -2,6 +2,7 @@

#include "Element/Element.h"
#include "Plotting/VariablesWidget.h"
#include "Modeling/Model.h"

DynamicAnnotation::DynamicAnnotation() = default;

Expand Down Expand Up @@ -52,26 +53,54 @@ bool DynamicAnnotation::deserialize(const QJsonValue &value)
*/
bool DynamicAnnotation::update(double time, Element *parent)
{
if (mState != State::None) {
if (isDynamicSelectExpression()) {
mState = State::Dynamic;

fromExp(mExp.arg(1).evaluate([&] (std::string name) {
auto vname = QString::fromStdString(name);
// the instance api returns the qualified cref
vname = StringHandler::getLastWordAfterDot(vname);
auto vname = QString::fromStdString(name);
// the instance api returns the qualified cref
vname = StringHandler::getLastWordAfterDot(vname);

if (parent) {
vname = QString("%1.%2").arg(parent->getName(), vname);
}
if (parent) {
vname = QString("%1.%2").arg(parent->getName(), vname);
}

return MainWindow::instance()->getVariablesWidget()->readVariableValue(vname, time);
}));
return FlatModelica::Expression(MainWindow::instance()->getVariablesWidget()->readVariableValue(vname, time));
}));
return true;
}

return false;
}

/*!
* \brief DynamicAnnotation::evaluate
* Evaluates the expression using the containing model.
* Containing model provides the binding variable value.
* If expression is DynamicSelect then use the static part of the expression.
* \param pModel
*/
void DynamicAnnotation::evaluate(ModelInstance::Model *pModel)
{
try {
FlatModelica::Expression expression;
if (isDynamicSelectExpression()) {
expression = mExp.arg(0);
} else {
expression = mExp;
}
fromExp(expression.evaluate([&] (std::string name) {
auto vname = QString::fromStdString(name);
// the instance api returns the qualified cref
vname = StringHandler::getLastWordAfterDot(vname);
return pModel->getVariableBinding(vname);
}));
} catch (const std::exception &e) {
qDebug() << "Failed to evaluate expression.";
qDebug() << e.what();
}
}

/*!
* \brief DynamicAnnotation::reset
* Calls the derived class' fromExp method with either the static or the dynamic
Expand Down
5 changes: 5 additions & 0 deletions OMEdit/OMEditLIB/Annotations/DynamicAnnotation.h
Expand Up @@ -5,6 +5,10 @@
#include "FlatModelica/Expression.h"

class Element;
namespace ModelInstance
{
class Model;
}

/*!
* \class DynamicAnnotation
Expand Down Expand Up @@ -42,6 +46,7 @@ class DynamicAnnotation
bool parse(const QString &str);
bool deserialize(const QJsonValue &value);
bool update(double time, Element *parent);
void evaluate(ModelInstance::Model *pModel);
void reset();
void resetDynamicToStatic();
virtual void clear() = 0;
Expand Down
7 changes: 5 additions & 2 deletions OMEdit/OMEditLIB/Annotations/EllipseAnnotation.cpp
Expand Up @@ -125,8 +125,11 @@ void EllipseAnnotation::parseShapeAnnotation()
FilledShape::parseShapeAnnotation(mpEllipse);

mExtent = mpEllipse->getExtent();
mExtent.evaluate(mpEllipse->getParentModel());
mStartAngle = mpEllipse->getStartAngle();
mStartAngle.evaluate(mpEllipse->getParentModel());
mEndAngle = mpEllipse->getEndAngle();
mEndAngle.evaluate(mpEllipse->getParentModel());
mClosure = StringHandler::getClosureType(stripDynamicSelect(mpEllipse->getClosure()));
}

Expand Down Expand Up @@ -221,11 +224,11 @@ QString EllipseAnnotation::getShapeAnnotation()
annotationString.append(QString("extent=%1").arg(mExtent.toQString()));
}
// get the start angle
if (mStartAngle.isDynamicSelectExpression() || mStartAngle != 0) {
if (mStartAngle.isDynamicSelectExpression() || mStartAngle.toQString().compare(QStringLiteral("0")) != 0) {
annotationString.append(QString("startAngle=%1").arg(mStartAngle.toQString()));
}
// get the end angle
if (mEndAngle.isDynamicSelectExpression() || mEndAngle != 360) {
if (mEndAngle.isDynamicSelectExpression() || mEndAngle.toQString().compare(QStringLiteral("360")) != 0) {
annotationString.append(QString("endAngle=%1").arg(mEndAngle.toQString()));
}
// get the closure
Expand Down
13 changes: 8 additions & 5 deletions OMEdit/OMEditLIB/Annotations/LineAnnotation.cpp
Expand Up @@ -646,11 +646,14 @@ void LineAnnotation::parseShapeAnnotation()
addPoint(QPointF(point.x(), point.y()));
}
mLineColor = mpLine->getColor();
mLineColor.evaluate(mpLine->getParentModel());
mLinePattern = StringHandler::getLinePatternType(stripDynamicSelect(mpLine->getPattern()));
mLineThickness = mpLine->getLineThickness();
mLineThickness.evaluate(mpLine->getParentModel());
mArrow.replace(0, StringHandler::getArrowType(mpLine->getStartArrow()));
mArrow.replace(1, StringHandler::getArrowType(mpLine->getEndArrow()));
mArrowSize = mpLine->getArrowSize();
mArrowSize.evaluate(mpLine->getParentModel());
mSmooth = StringHandler::getSmoothType(stripDynamicSelect(mpLine->getSmooth()));
}

Expand Down Expand Up @@ -993,15 +996,15 @@ QString LineAnnotation::getShapeAnnotation()
annotationString.append(pointsString);
}
// get the line color
if (mLineColor.isDynamicSelectExpression() || mLineColor != Qt::black) {
if (mLineColor.isDynamicSelectExpression() || mLineColor.toQString().compare(QStringLiteral("{0,0,0}")) != 0) {
annotationString.append(QString("color=%1").arg(mLineColor.toQString()));
}
// get the line pattern
if (mLinePattern != StringHandler::LineSolid) {
annotationString.append(QString("pattern=").append(StringHandler::getLinePatternString(mLinePattern)));
}
// get the thickness
if (mLineThickness.isDynamicSelectExpression() || mLineThickness != 0.25) {
if (mLineThickness.isDynamicSelectExpression() || mLineThickness.toQString().compare(QStringLiteral("0.25")) != 0) {
annotationString.append(QString("thickness=%1").arg(mLineThickness.toQString()));
}
// get the start and end arrow
Expand All @@ -1013,7 +1016,7 @@ QString LineAnnotation::getShapeAnnotation()
annotationString.append(arrowString);
}
// get the arrow size
if (mArrowSize.isDynamicSelectExpression() || mArrowSize != 3) {
if (mArrowSize.isDynamicSelectExpression() || mArrowSize.toQString().compare(QStringLiteral("3")) != 0) {
annotationString.append(QString("arrowSize=%1").arg(mArrowSize.toQString()));
}
// get the smooth
Expand Down Expand Up @@ -2468,7 +2471,7 @@ void CreateConnectionDialog::createConnection()
mpConnectionLineAnnotation->setStartElementName(startElementName);
mpConnectionLineAnnotation->setEndElementName(endElementName);
if (mpGraphicsView->getModelWidget()->isNewApi()) {
mpConnectionLineAnnotation->setLine(new ModelInstance::Line);
mpConnectionLineAnnotation->setLine(new ModelInstance::Line(mpGraphicsView->getModelWidget()->getModelInstance()));
mpConnectionLineAnnotation->updateLine();
mpConnectionLineAnnotation->drawCornerItems();
mpConnectionLineAnnotation->setCornerItemsActiveOrPassive();
Expand Down Expand Up @@ -2600,7 +2603,7 @@ void CreateOrEditTransitionDialog::createOrEditTransition()
mpTransitionLineAnnotation->getOMCShapeAnnotation()));
} else {
if (mpGraphicsView->getModelWidget()->isNewApi()) {
mpTransitionLineAnnotation->setLine(new ModelInstance::Line);
mpTransitionLineAnnotation->setLine(new ModelInstance::Line(mpGraphicsView->getModelWidget()->getModelInstance()));
mpTransitionLineAnnotation->updateLine();
mpTransitionLineAnnotation->drawCornerItems();
mpTransitionLineAnnotation->setCornerItemsActiveOrPassive();
Expand Down
4 changes: 3 additions & 1 deletion OMEdit/OMEditLIB/Annotations/RectangleAnnotation.cpp
Expand Up @@ -166,7 +166,9 @@ void RectangleAnnotation::parseShapeAnnotation()

mBorderPattern = StringHandler::getBorderPatternType(stripDynamicSelect(mpRectangle->getBorderPattern()));
mExtent = mpRectangle->getExtent();
mExtent.evaluate(mpRectangle->getParentModel());
mRadius = mpRectangle->getRadius();
mRadius.evaluate(mpRectangle->getParentModel());
}

QRectF RectangleAnnotation::boundingRect() const
Expand Down Expand Up @@ -258,7 +260,7 @@ QString RectangleAnnotation::getShapeAnnotation()
annotationString.append(QString("extent=%1").arg(mExtent.toQString()));
}
// get the radius
if (mRadius.isDynamicSelectExpression() || mRadius != 0) {
if (mRadius.isDynamicSelectExpression() || mRadius.toQString().compare(QStringLiteral("0")) != 0) {
annotationString.append(QString("radius=%1").arg(mRadius.toQString()));
}
return QString("Rectangle(").append(annotationString.join(",")).append(")");
Expand Down
44 changes: 25 additions & 19 deletions OMEdit/OMEditLIB/Annotations/ShapeAnnotation.cpp
Expand Up @@ -91,14 +91,17 @@ void GraphicItem::parseShapeAnnotation(QString annotation)
mRotation.parse(list.at(2));
}

void GraphicItem::parseShapeAnnotation(ModelInstance::GraphicItem *pGraphicItem)
void GraphicItem::parseShapeAnnotation(ModelInstance::Shape *pShape)
{
// if first item of list is true then the shape should be visible.
mVisible = pGraphicItem->getVisible();
mVisible = pShape->getVisible();
mVisible.evaluate(pShape->getParentModel());
// 2nd item is the origin
mOrigin = pGraphicItem->getOrigin();
mOrigin = pShape->getOrigin();
mOrigin.evaluate(pShape->getParentModel());
// 3rd item is the rotation
mRotation = pGraphicItem->getRotation();
mRotation = pShape->getRotation();
mRotation.evaluate(pShape->getParentModel());
}

/*!
Expand Down Expand Up @@ -127,15 +130,15 @@ QStringList GraphicItem::getShapeAnnotation()
{
QStringList annotationString;
/* get visible */
if (mVisible.isDynamicSelectExpression() || !mVisible) {
if (mVisible.isDynamicSelectExpression() || mVisible.toQString().compare(QStringLiteral("true")) != 0) {
annotationString.append(QString("visible=%1").arg(mVisible.toQString()));
}
/* get origin */
if (mOrigin.isDynamicSelectExpression() || mOrigin != QPointF(0, 0)) {
if (mOrigin.isDynamicSelectExpression() || mOrigin.toQString().compare(QStringLiteral("{0,0}")) != 0) {
annotationString.append(QString("origin=%1").arg(mOrigin.toQString()));
}
/* get rotation */
if (mRotation.isDynamicSelectExpression() || mRotation != 0) {
if (mRotation.isDynamicSelectExpression() || mRotation.toQString().compare(QStringLiteral("0")) != 0) {
annotationString.append(QString("rotation=%1").arg(mRotation.toQString()));
}
return annotationString;
Expand Down Expand Up @@ -191,13 +194,16 @@ void FilledShape::parseShapeAnnotation(QString annotation)
mLineThickness.parse(list.at(7));
}

void FilledShape::parseShapeAnnotation(ModelInstance::FilledShape *pFilledShape)
void FilledShape::parseShapeAnnotation(ModelInstance::Shape *pShape)
{
mLineColor = pFilledShape->getLineColor();
mFillColor = pFilledShape->getFillColor();
mLinePattern = StringHandler::getLinePatternType(stripDynamicSelect(pFilledShape->getPattern()));
mFillPattern = StringHandler::getFillPatternType(stripDynamicSelect(pFilledShape->getFillPattern()));
mLineThickness = pFilledShape->getLineThickness();
mLineColor = pShape->getLineColor();
mLineColor.evaluate(pShape->getParentModel());
mFillColor = pShape->getFillColor();
mFillColor.evaluate(pShape->getParentModel());
mLinePattern = StringHandler::getLinePatternType(stripDynamicSelect(pShape->getPattern()));
mFillPattern = StringHandler::getFillPatternType(stripDynamicSelect(pShape->getFillPattern()));
mLineThickness = pShape->getLineThickness();
mLineThickness.evaluate(pShape->getParentModel());
}

/*!
Expand Down Expand Up @@ -230,11 +236,11 @@ QStringList FilledShape::getShapeAnnotation()
{
QStringList annotationString;
/* get the line color */
if (mLineColor.isDynamicSelectExpression() || mLineColor != Qt::black) {
if (mLineColor.isDynamicSelectExpression() || mLineColor.toQString().compare(QStringLiteral("{0,0,0}")) != 0) {
annotationString.append(QString("lineColor=%1").arg(mLineColor.toQString()));
}
/* get the fill color */
if (mFillColor.isDynamicSelectExpression() || mFillColor != Qt::black) {
if (mFillColor.isDynamicSelectExpression() || mFillColor.toQString().compare(QStringLiteral("{0,0,0}")) != 0) {
annotationString.append(QString("fillColor=%1").arg(mFillColor.toQString()));
}
/* get the line pattern */
Expand All @@ -246,7 +252,7 @@ QStringList FilledShape::getShapeAnnotation()
annotationString.append(QString("fillPattern=").append(StringHandler::getFillPatternString(mFillPattern)));
}
// get the thickness
if (mLineThickness.isDynamicSelectExpression() || mLineThickness != 0.25) {
if (mLineThickness.isDynamicSelectExpression() || mLineThickness.toQString().compare(QStringLiteral("0.25")) != 0) {
annotationString.append(QString("lineThickness=%1").arg(mLineThickness.toQString()));
}
return annotationString;
Expand All @@ -262,7 +268,7 @@ QStringList FilledShape::getTextShapeAnnotation()
{
QStringList annotationString;
/* get the text color */
if (mLineColor.isDynamicSelectExpression() || mLineColor != Qt::black) {
if (mLineColor.isDynamicSelectExpression() || mLineColor.toQString().compare(QStringLiteral("{0,0,0}")) != 0) {
annotationString.append(QString("textColor=%1").arg(mLineColor.toQString()));
}
return annotationString;
Expand Down Expand Up @@ -744,7 +750,7 @@ void ShapeAnnotation::drawCornerItems()
void ShapeAnnotation::setCornerItemsActiveOrPassive()
{
foreach (CornerItem *pCornerItem, mCornerItemsList) {
if (isSelected()) {
if (mVisible && isSelected()) {
pCornerItem->setToolTip(Helper::clickAndDragToResize);
pCornerItem->setVisible(true);
} else {
Expand All @@ -753,7 +759,7 @@ void ShapeAnnotation::setCornerItemsActiveOrPassive()
}
}
if (mpOriginItem) {
if (isSelected()) {
if (mVisible && isSelected()) {
mpOriginItem->setActive();
} else {
mpOriginItem->setPassive();
Expand Down
4 changes: 2 additions & 2 deletions OMEdit/OMEditLIB/Annotations/ShapeAnnotation.h
Expand Up @@ -70,7 +70,7 @@ class GraphicItem
void setDefaults();
void setDefaults(ShapeAnnotation *pShapeAnnotation);
void parseShapeAnnotation(QString annotation);
void parseShapeAnnotation(ModelInstance::GraphicItem *pGraphicItem);
void parseShapeAnnotation(ModelInstance::Shape *pShape);
QStringList getOMCShapeAnnotation();
QStringList getShapeAnnotation();
void setOrigin(QPointF origin) {mOrigin = origin;}
Expand All @@ -90,7 +90,7 @@ class FilledShape
void setDefaults();
void setDefaults(ShapeAnnotation *pShapeAnnotation);
void parseShapeAnnotation(QString annotation);
void parseShapeAnnotation(ModelInstance::FilledShape *pFilledShape);
void parseShapeAnnotation(ModelInstance::Shape *pShape);
QStringList getOMCShapeAnnotation();
QStringList getShapeAnnotation();
QStringList getTextShapeAnnotation();
Expand Down
5 changes: 4 additions & 1 deletion OMEdit/OMEditLIB/Annotations/TextAnnotation.cpp
Expand Up @@ -267,13 +267,16 @@ void TextAnnotation::parseShapeAnnotation()
FilledShape::parseShapeAnnotation(mpText);

mExtent = mpText->getExtent();
mExtent.evaluate(mpText->getParentModel());
mTextString = mpText->getTextString();
mOriginalTextString = mTextString;
initUpdateTextString();

mFontSize = mpText->getFontSize();
mFontSize.evaluate(mpText->getParentModel());
if (mpText->getTextColor().isValid()) {
mLineColor = mpText->getTextColor();
mLineColor.evaluate(mpText->getParentModel());
}
if (!mpText->getFontName().isEmpty()) {
mFontName = mpText->getFontName().isEmpty();
Expand Down Expand Up @@ -525,7 +528,7 @@ QString TextAnnotation::getShapeAnnotation()
// get the text string
annotationString.append(QString("textString=%1").arg(mOriginalTextString.toQString()));
// get the font size
if (mFontSize.isDynamicSelectExpression() || mFontSize != 0) {
if (mFontSize.isDynamicSelectExpression() || mFontSize.toQString().compare(QStringLiteral("0")) != 0) {
annotationString.append(QString("fontSize=%1").arg(mFontSize.toQString()));
}
// get the font name
Expand Down
7 changes: 6 additions & 1 deletion OMEdit/OMEditLIB/FlatModelica/Expression.cpp
Expand Up @@ -1629,7 +1629,12 @@ namespace FlatModelica

void Unary::print(std::ostream &os) const
{
os << _op << _e;
os << _op;
// add space for not operator
if (_op.type() == Operator::Not) {
os << " ";
}
os << _e;
}

QJsonValue Unary::serialize() const
Expand Down
2 changes: 1 addition & 1 deletion OMEdit/OMEditLIB/FlatModelica/Expression.h
Expand Up @@ -42,7 +42,7 @@ namespace FlatModelica
class Expression
{
public:
using VariableEvaluator = std::function<double(std::string cref_name)>;
using VariableEvaluator = std::function<Expression(std::string cref_name)>;

public:
Expression();
Expand Down

0 comments on commit 3caf7a9

Please sign in to comment.