From 88e6607f0b144ea77928192796a18f64fc75ee09 Mon Sep 17 00:00:00 2001 From: mpv Date: Fri, 29 Apr 2016 14:00:49 +0300 Subject: [PATCH] Fix for the issue #1444 : correct checking of upper and lower parameters, current feature processing, flush events after movements of parameters in the parameters table. --- src/Model/Model_Data.cpp | 12 +++++----- src/Model/Model_Document.cpp | 18 ++++++++++++--- src/Model/Model_Document.h | 3 +++ src/ModelAPI/ModelAPI_Document.h | 3 +++ src/ModelAPI/ModelAPI_Tools.cpp | 23 +++++++++++-------- src/ModelAPI/ModelAPI_Tools.h | 11 +++++---- src/ModuleBase/ModuleBase_ParamIntSpinBox.cpp | 2 +- src/ModuleBase/ModuleBase_ParamSpinBox.cpp | 2 +- .../ParametersPlugin_EvalListener.cpp | 17 ++++++++------ .../ParametersPlugin_EvalListener.h | 5 ++-- .../ParametersPlugin_Parameter.cpp | 3 ++- .../ParametersPlugin_WidgetParamsMgr.cpp | 13 +++++++++-- src/XGUI/XGUI_Tools.cpp | 3 ++- 13 files changed, 78 insertions(+), 37 deletions(-) diff --git a/src/Model/Model_Data.cpp b/src/Model/Model_Data.cpp index 02e9b7add..1bb1fd147 100644 --- a/src/Model/Model_Data.cpp +++ b/src/Model/Model_Data.cpp @@ -497,7 +497,7 @@ std::set usedParameters(const AttributePoint2DPtr& theAttribute) } std::list findVariables(const std::set& theParameters, - const DocumentPtr& theDocument) + const FeaturePtr& theParam) { std::list aResult; std::set::const_iterator aParamIt = theParameters.cbegin(); @@ -505,7 +505,7 @@ std::list findVariables(const std::set& thePara const std::string& aName = *aParamIt; double aValue; ResultParameterPtr aParam; - if (ModelAPI_Tools::findVariable(aName, aValue, aParam, theDocument)) + if (ModelAPI_Tools::findVariable(theParam, aName, aValue, aParam)) aResult.push_back(aParam); } return aResult; @@ -565,25 +565,25 @@ void Model_Data::referencesToObjects( AttributeIntegerPtr anAttribute = std::dynamic_pointer_cast(anAttr->second); std::set anUsedParameters = anAttribute->usedParameters(); - std::list aParameters = findVariables(anUsedParameters, aMyFeature->document()); + std::list aParameters = findVariables(anUsedParameters, aMyFeature); aReferenced.insert(aReferenced.end(), aParameters.begin(), aParameters.end()); } else if (aType == ModelAPI_AttributeDouble::typeId()) { // double attribute AttributeDoublePtr anAttribute = std::dynamic_pointer_cast(anAttr->second); std::set anUsedParameters = anAttribute->usedParameters(); - std::list aParameters = findVariables(anUsedParameters, aMyFeature->document()); + std::list aParameters = findVariables(anUsedParameters, aMyFeature); aReferenced.insert(aReferenced.end(), aParameters.begin(), aParameters.end()); } else if (aType == GeomDataAPI_Point::typeId()) { // point attribute AttributePointPtr anAttribute = std::dynamic_pointer_cast(anAttr->second); std::set anUsedParameters = usedParameters(anAttribute); - std::list aParameters = findVariables(anUsedParameters, aMyFeature->document()); + std::list aParameters = findVariables(anUsedParameters, aMyFeature); aReferenced.insert(aReferenced.end(), aParameters.begin(), aParameters.end()); } else if (aType == GeomDataAPI_Point2D::typeId()) { // point attribute AttributePoint2DPtr anAttribute = std::dynamic_pointer_cast(anAttr->second); std::set anUsedParameters = usedParameters(anAttribute); - std::list aParameters = findVariables(anUsedParameters, aMyFeature->document()); + std::list aParameters = findVariables(anUsedParameters, aMyFeature); aReferenced.insert(aReferenced.end(), aParameters.begin(), aParameters.end()); } else continue; // nothing to do, not reference diff --git a/src/Model/Model_Document.cpp b/src/Model/Model_Document.cpp index a1cb443fb..a55b7c4dd 100755 --- a/src/Model/Model_Document.cpp +++ b/src/Model/Model_Document.cpp @@ -832,11 +832,18 @@ void Model_Document::removeFeature(FeaturePtr theFeature) void Model_Document::moveFeature(FeaturePtr theMoved, FeaturePtr theAfterThis) { - if (theAfterThis == currentFeature(false)) - setCurrentFeature(theMoved, true); - else if (theMoved == currentFeature(false)) + bool aCurrentUp = theMoved == currentFeature(false); + if (aCurrentUp) { setCurrentFeatureUp(); + } + myObjs->moveFeature(theMoved, theAfterThis); + if (aCurrentUp) { // make the moved feature enabled or disabled due to the real status + setCurrentFeature(currentFeature(false), false); + } else if (theAfterThis == currentFeature(false)) { + // must be after move to make enabled all features which are before theMoved + setCurrentFeature(theMoved, true); + } } void Model_Document::updateHistory(const std::shared_ptr theObject) @@ -1383,3 +1390,8 @@ std::shared_ptr Model_Document::producedByFeature( } return aResult; } + +bool Model_Document::isLater(FeaturePtr theLater, FeaturePtr theCurrent) const +{ + return myObjs->isLater(theLater, theCurrent); +} diff --git a/src/Model/Model_Document.h b/src/Model/Model_Document.h index f76c3cf27..f00d87a01 100644 --- a/src/Model/Model_Document.h +++ b/src/Model/Model_Document.h @@ -216,6 +216,9 @@ class Model_Document : public ModelAPI_Document std::shared_ptr theResult, const std::shared_ptr& theShape); + /// Returns true if theLater is in history of features creation later than theCurrent + MODEL_EXPORT virtual bool isLater(FeaturePtr theLater, FeaturePtr theCurrent) const; + protected: //! Returns (creates if needed) the general label TDF_Label generalLabel() const; diff --git a/src/ModelAPI/ModelAPI_Document.h b/src/ModelAPI/ModelAPI_Document.h index cd13996dc..f8e53575d 100644 --- a/src/ModelAPI/ModelAPI_Document.h +++ b/src/ModelAPI/ModelAPI_Document.h @@ -164,6 +164,9 @@ public: std::shared_ptr theResult, const std::shared_ptr& theShape) = 0; + /// Returns true if theLater is in history of features creation later than theCurrent + virtual bool isLater(std::shared_ptr theLater, + std::shared_ptr theCurrent) const = 0; protected: //! Only for SWIG wrapping it is here diff --git a/src/ModelAPI/ModelAPI_Tools.cpp b/src/ModelAPI/ModelAPI_Tools.cpp index 3f823dcb2..acec054da 100755 --- a/src/ModelAPI/ModelAPI_Tools.cpp +++ b/src/ModelAPI/ModelAPI_Tools.cpp @@ -88,32 +88,37 @@ ObjectPtr objectByName(const DocumentPtr& theDocument, const std::string& theGro return ObjectPtr(); } -bool findVariable(const DocumentPtr& theDocument, +bool findVariable(const DocumentPtr& theDocument, FeaturePtr theSearcher, const std::string& theName, double& outValue, ResultParameterPtr& theParam) { ObjectPtr aParamObj = objectByName(theDocument, ModelAPI_ResultParameter::group(), theName); theParam = std::dynamic_pointer_cast(aParamObj); if (!theParam.get()) return false; + // avoid usage of parameters created later than the initial parameter + if (theSearcher.get() && theDocument->isLater(theDocument->feature(theParam), theSearcher)) + return false; AttributeDoublePtr aValueAttribute = theParam->data()->real(ModelAPI_ResultParameter::VALUE()); outValue = aValueAttribute->value(); return true; } -bool findVariable(const std::string& theName, double& outValue, ResultParameterPtr& theParam, - const DocumentPtr& theDocument /*= DocumentPtr()*/) +bool findVariable(FeaturePtr theSearcher, const std::string& theName, double& outValue, ResultParameterPtr& theParam, + const DocumentPtr& theDocument) { SessionPtr aSession = ModelAPI_Session::get(); std::list aDocList; DocumentPtr aDocument = theDocument.get() ? theDocument : aSession->activeDocument(); + if (findVariable(aDocument, theSearcher, theName, outValue, theParam)) + return true; DocumentPtr aRootDocument = aSession->moduleDocument(); - aDocList.push_back(aDocument); if (aDocument != aRootDocument) { - aDocList.push_back(aRootDocument); - } - for(std::list::const_iterator it = aDocList.begin(); it != aDocList.end(); ++it) { - if (findVariable(*it, theName, outValue, theParam)) - return true; + ResultPtr aPartResult = findPartResult(aRootDocument, aDocument); + if (aPartResult.get()) { + FeaturePtr aPartFeature = aRootDocument->feature(aPartResult); + if (findVariable(aRootDocument, aPartFeature, theName, outValue, theParam)) + return true; + } } return false; } diff --git a/src/ModelAPI/ModelAPI_Tools.h b/src/ModelAPI/ModelAPI_Tools.h index 1d86a03cc..02090e516 100755 --- a/src/ModelAPI/ModelAPI_Tools.h +++ b/src/ModelAPI/ModelAPI_Tools.h @@ -33,17 +33,20 @@ MODELAPI_EXPORT std::string getFeatureError(const FeaturePtr& theFeature); /*! * Searches for variable with name \param theName in \param theDocument. * If found, set it value in the \param outValue and returns true. + * theSearcher must be located later in the history than the found variable. */ -MODELAPI_EXPORT bool findVariable(const DocumentPtr& theDocument, - const std::string& theName, double& outValue, ResultParameterPtr& theParam); +MODELAPI_EXPORT bool findVariable(const DocumentPtr& theDocument, FeaturePtr theSearcher, + const std::string& theName, double& outValue, ResultParameterPtr& theParam); /*! * Searches for variable with name \param theName in the active document (Part), when * in the root document (PartSet). If found, set it value in the \param outValue * and returns true. If \param theDocument is empty active document is used. + * theSearcher must be located later in the history than the found variable. */ -MODELAPI_EXPORT bool findVariable(const std::string& theName, double& outValue, ResultParameterPtr& theParam, - const DocumentPtr& theDocument = DocumentPtr()); +MODELAPI_EXPORT bool findVariable(FeaturePtr theSearcher, const std::string& theName, + double& outValue, ResultParameterPtr& theParam, + const DocumentPtr& theDocument = DocumentPtr()); /*! * Returns the values of the next random color. The values are in range [0, 255] diff --git a/src/ModuleBase/ModuleBase_ParamIntSpinBox.cpp b/src/ModuleBase/ModuleBase_ParamIntSpinBox.cpp index b3f286dc2..a2c41692e 100644 --- a/src/ModuleBase/ModuleBase_ParamIntSpinBox.cpp +++ b/src/ModuleBase/ModuleBase_ParamIntSpinBox.cpp @@ -193,7 +193,7 @@ bool ModuleBase_ParamIntSpinBox::findVariable(const QString& theName, double& outValue) const { ResultParameterPtr aParam; - return ModelAPI_Tools::findVariable(theName.toStdString(), outValue, aParam); + return ModelAPI_Tools::findVariable(FeaturePtr(), theName.toStdString(), outValue, aParam); } /*! diff --git a/src/ModuleBase/ModuleBase_ParamSpinBox.cpp b/src/ModuleBase/ModuleBase_ParamSpinBox.cpp index f559eb68a..9916aec51 100644 --- a/src/ModuleBase/ModuleBase_ParamSpinBox.cpp +++ b/src/ModuleBase/ModuleBase_ParamSpinBox.cpp @@ -243,7 +243,7 @@ bool ModuleBase_ParamSpinBox::findVariable(const QString& theName, double& outValue) const { ResultParameterPtr aParam; - return ModelAPI_Tools::findVariable(theName.toStdString(), outValue, aParam); + return ModelAPI_Tools::findVariable(FeaturePtr(), theName.toStdString(), outValue, aParam); } /*! diff --git a/src/ParametersPlugin/ParametersPlugin_EvalListener.cpp b/src/ParametersPlugin/ParametersPlugin_EvalListener.cpp index 6fd145fec..8f91a78c2 100644 --- a/src/ParametersPlugin/ParametersPlugin_EvalListener.cpp +++ b/src/ParametersPlugin/ParametersPlugin_EvalListener.cpp @@ -94,8 +94,8 @@ void ParametersPlugin_EvalListener::processEvent( } } -double ParametersPlugin_EvalListener::evaluate(const std::string& theExpression, std::string& theError, - const std::shared_ptr& theDocument) +double ParametersPlugin_EvalListener::evaluate(FeaturePtr theParameter, + const std::string& theExpression, std::string& theError) { std::list anExprParams = myInterp->compile(theExpression); // find expression's params in the model @@ -105,7 +105,8 @@ double ParametersPlugin_EvalListener::evaluate(const std::string& theExpression, double aValue; 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; + if (!ModelAPI_Tools::findVariable(theParameter, *it, aValue, aParamRes, theParameter->document())) + continue; aContext.push_back(*it + "=" + toStdString(aValue)); } @@ -121,11 +122,13 @@ void ParametersPlugin_EvalListener::processEvaluationEvent( std::shared_ptr aMessage = std::dynamic_pointer_cast(theMessage); + FeaturePtr aParamFeature = + std::dynamic_pointer_cast(aMessage->attribute()->owner()); if (aMessage->attribute()->attributeType() == ModelAPI_AttributeInteger::typeId()) { AttributeIntegerPtr anAttribute = std::dynamic_pointer_cast(aMessage->attribute()); std::string anError; - int aValue = (int)evaluate(anAttribute->text(), anError, anAttribute->owner()->document()); + int aValue = (int)evaluate(aParamFeature, anAttribute->text(), anError); bool isValid = anError.empty(); if (isValid) anAttribute->setCalculatedValue(aValue); @@ -137,7 +140,7 @@ void ParametersPlugin_EvalListener::processEvaluationEvent( AttributeDoublePtr anAttribute = std::dynamic_pointer_cast(aMessage->attribute()); std::string anError; - double aValue = evaluate(anAttribute->text(), anError, anAttribute->owner()->document()); + double aValue = evaluate(aParamFeature, anAttribute->text(), anError); bool isValid = anError.empty(); if (isValid) anAttribute->setCalculatedValue(aValue); @@ -160,7 +163,7 @@ void ParametersPlugin_EvalListener::processEvaluationEvent( }; for (int i = 0; i < 3; ++i) { std::string anError; - double aValue = evaluate(aText[i], anError, anAttribute->owner()->document()); + double aValue = evaluate(aParamFeature, aText[i], anError); bool isValid = anError.empty(); if (isValid) aCalculatedValue[i] = aValue; anAttribute->setUsedParameters(i, isValid ? toSet(myInterp->compile(aText[i])) : std::set()); @@ -184,7 +187,7 @@ void ParametersPlugin_EvalListener::processEvaluationEvent( }; for (int i = 0; i < 2; ++i) { std::string anError; - double aValue = evaluate(aText[i], anError, anAttribute->owner()->document()); + double aValue = evaluate(aParamFeature, aText[i], anError); bool isValid = anError.empty(); if (isValid) aCalculatedValue[i] = aValue; anAttribute->setUsedParameters(i, isValid ? toSet(myInterp->compile(aText[i])) : std::set()); diff --git a/src/ParametersPlugin/ParametersPlugin_EvalListener.h b/src/ParametersPlugin/ParametersPlugin_EvalListener.h index 96181169a..76639caef 100644 --- a/src/ParametersPlugin/ParametersPlugin_EvalListener.h +++ b/src/ParametersPlugin/ParametersPlugin_EvalListener.h @@ -13,6 +13,7 @@ class ModelAPI_Attribute; class ModelAPI_Document; +class ModelAPI_Feature; class ModelAPI_ResultParameter; class ParametersPlugin_Parameter; class ParametersPlugin_PyInterp; @@ -33,8 +34,8 @@ class ParametersPlugin_EvalListener : public Events_Listener protected: /// Evaluates theExpression and returns its value. - double evaluate(const std::string& theExpression, std::string& theError, - const std::shared_ptr& theDocument); + double evaluate(std::shared_ptr theParameter, + const std::string& theExpression, std::string& theError); /// Processes Evaluation event. void processEvaluationEvent(const std::shared_ptr& theMessage); diff --git a/src/ParametersPlugin/ParametersPlugin_Parameter.cpp b/src/ParametersPlugin/ParametersPlugin_Parameter.cpp index 5d99ee00b..4428be15b 100644 --- a/src/ParametersPlugin/ParametersPlugin_Parameter.cpp +++ b/src/ParametersPlugin/ParametersPlugin_Parameter.cpp @@ -117,7 +117,8 @@ double ParametersPlugin_Parameter::evaluate(const std::string& theExpression, st double aValue; ResultParameterPtr aParamRes; - if (!ModelAPI_Tools::findVariable(aVariableName, aValue, aParamRes, aDocument)) continue; + if (!ModelAPI_Tools::findVariable(std::dynamic_pointer_cast(data()->owner()), + aVariableName, aValue, aParamRes, aDocument)) continue; aParamsList.push_back(aParamRes); std::ostringstream sstream; diff --git a/src/ParametersPlugin/ParametersPlugin_WidgetParamsMgr.cpp b/src/ParametersPlugin/ParametersPlugin_WidgetParamsMgr.cpp index 6dc416d93..4978f2a9b 100644 --- a/src/ParametersPlugin/ParametersPlugin_WidgetParamsMgr.cpp +++ b/src/ParametersPlugin/ParametersPlugin_WidgetParamsMgr.cpp @@ -619,8 +619,12 @@ void ParametersPlugin_WidgetParamsMgr::onUp() else aDoc->moveFeature(aCurFeature, myParametersList.at(aCurrentPos - 2)); - - Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED)); + // add the updated also the feature that goes down + Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)); + static Events_ID EVENT_UPD = Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED); + ModelAPI_EventCreator::get()->sendUpdated(myParametersList.at(aCurrentPos - 1), EVENT_UPD); + Events_Loop::loop()->flush(EVENT_UPD); + Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)); Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)); Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY)); updateParametersFeatures(); @@ -648,8 +652,13 @@ void ParametersPlugin_WidgetParamsMgr::onDown() SessionPtr aMgr = ModelAPI_Session::get(); std::shared_ptr aDoc = aMgr->activeDocument(); aDoc->moveFeature(aCurFeature, myParametersList.at(aCurrentPos + 1)); + // add the updated also the feature that goes up + static Events_ID EVENT_UPD = Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED); + ModelAPI_EventCreator::get()->sendUpdated(myParametersList.at(aCurrentPos + 1), EVENT_UPD); + Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)); Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_UPDATED)); + Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_CREATED)); Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_DELETED)); Events_Loop::loop()->flush(Events_Loop::loop()->eventByName(EVENT_OBJECT_TO_REDISPLAY)); updateParametersFeatures(); diff --git a/src/XGUI/XGUI_Tools.cpp b/src/XGUI/XGUI_Tools.cpp index e9000eff1..9a7556e40 100644 --- a/src/XGUI/XGUI_Tools.cpp +++ b/src/XGUI/XGUI_Tools.cpp @@ -132,7 +132,8 @@ bool canRename(const ObjectPtr& theObject, const QString& theName) if (std::dynamic_pointer_cast(theObject).get()) { double aValue; ResultParameterPtr aParam; - if (ModelAPI_Tools::findVariable(theObject->document(), qPrintable(theName), aValue, aParam)) { + if (ModelAPI_Tools::findVariable(theObject->document(), + FeaturePtr(), qPrintable(theName), aValue, aParam)) { QString aErrMsg(QObject::tr("Selected parameter can not be renamed to: %1. \ There is a parameter with the same name. Its value is: %2.").arg(qPrintable(theName)).arg(aValue)); // We can not use here a dialog box for message - it will crash editing process in ObjectBrowser -- 2.39.2