]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
Fix for issue #562 : correct update by dependencies in the parameters
authormpv <mpv@opencascade.com>
Mon, 25 May 2015 14:53:53 +0000 (17:53 +0300)
committermpv <mpv@opencascade.com>
Mon, 25 May 2015 14:53:53 +0000 (17:53 +0300)
12 files changed:
src/Model/Model_AttributeDouble.cpp
src/Model/Model_AttributeRefList.cpp
src/Model/Model_AttributeRefList.h
src/Model/Model_Update.cpp
src/ModelAPI/ModelAPI_AttributeRefList.h
src/ModelAPI/ModelAPI_Tools.cpp
src/ModelAPI/ModelAPI_Tools.h
src/ModuleBase/ModuleBase_ParamSpinBox.cpp
src/ModuleBase/ModuleBase_WidgetDoubleValue.cpp
src/ParametersPlugin/ParametersPlugin_EvalListener.cpp
src/ParametersPlugin/ParametersPlugin_Parameter.cpp
src/ParametersPlugin/ParametersPlugin_Parameter.h

index c65748dee83f50d4273fd6ccab3b29a8b199487e..3ef3e3c41c1510d217a9efdb6aed4621f4bc4b61 100644 (file)
@@ -7,6 +7,7 @@
 #include "Model_AttributeDouble.h"
 #include <ModelAPI_Feature.h>
 #include <ModelAPI_Data.h>
+#include <ModelAPI_Events.h>
 
 #include <TCollection_AsciiString.hxx>
 #include <TCollection_ExtendedString.hxx>
@@ -46,6 +47,12 @@ void Model_AttributeDouble::setText(const std::string& theValue)
   if (myText->Get() != aValue) {
     myText->Set(aValue);
     owner()->data()->sendAttributeUpdated(this);
+    // 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(owner()->data()->attribute(id())); // to get shared pointer to this
+    Events_Loop::loop()->send(aMessage);
   }
 }
 
@@ -67,5 +74,5 @@ void Model_AttributeDouble::setExpressionInvalid(const bool theFlag)
 
 bool Model_AttributeDouble::expressionInvalid()
 {
-  return myReal->Label().IsAttribute(kInvalidGUID);
+  return myReal->Label().IsAttribute(kInvalidGUID) == Standard_True;
 }
index 3e4f5a21dadb9f9bdce28065578f85e1f863f158..b7719ca78f5011e5b4b32980831b452729c773f8 100644 (file)
@@ -50,6 +50,16 @@ void Model_AttributeRefList::remove(ObjectPtr theObject)
   owner()->data()->sendAttributeUpdated(this);
 }
 
+void Model_AttributeRefList::clear()
+{
+  std::list<ObjectPtr> anOldList = list();
+  myRef->Clear();
+  std::list<ObjectPtr>::iterator anOldIter = anOldList.begin();
+  for(; anOldIter != anOldList.end(); anOldIter++) {
+    REMOVE_BACK_REF((*anOldIter));
+  }
+}
+
 int Model_AttributeRefList::size() const
 {
   return myRef->Extent();
index f59229a1a697f73b231f78e6de162ad8b4a7a334..ebf6ec9c66a9f988557bd1dc4166e4c9ea92e84b 100644 (file)
@@ -31,6 +31,9 @@ class Model_AttributeRefList : public ModelAPI_AttributeRefList
   /// Returns number of features in the list
   MODEL_EXPORT virtual int size() const;
 
+  /// Removes all references from the list
+  MODEL_EXPORT virtual void clear();
+
   /// Returns the list of features
   MODEL_EXPORT virtual std::list<ObjectPtr> list();
 
index be69043e92c72ee0c7b9910ebbbfe954a4d86b1e..502930d93dc69e6b47e8a23bed95a9134f94e00b 100644 (file)
@@ -110,11 +110,13 @@ void Model_Update::processEvent(const std::shared_ptr<Events_Message>& theMessag
     isOperationChanged = true;
   }
   if (isOperationChanged) {
-    // remove all macros before clearing all created
+    // remove all macros before clearing all created and execute all not-previewed
     std::set<ObjectPtr>::iterator aCreatedIter = myJustCreated.begin();
-    for(; aCreatedIter != myJustCreated.end(); aCreatedIter++) {
-      FeaturePtr aFeature = 
-        std::dynamic_pointer_cast<ModelAPI_Feature>(*aCreatedIter);
+    std::set<ObjectPtr>::iterator anUpdatedIter = myJustUpdated.begin();
+    for(; aCreatedIter != myJustCreated.end() || anUpdatedIter != myJustUpdated.end();
+      aCreatedIter == myJustCreated.end() ? anUpdatedIter++ : aCreatedIter++) {
+      FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(*
+        (aCreatedIter == myJustCreated.end() ? anUpdatedIter : aCreatedIter));
       if (aFeature.get()) {
         // execute not-previewed feature on "apply"
         if (!aFeature->isPreviewNeeded() && (myJustCreated.find(aFeature) != myJustCreated.end() ||
@@ -267,8 +269,10 @@ void Model_Update::updateArguments(FeaturePtr theFeature) {
   for(; aDoubleIter != aDoubles.end(); aDoubleIter++) {
     AttributeDoublePtr aDouble = 
       std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(*aDoubleIter);
-    if (aDouble.get() && aDouble->expressionInvalid()) {
-      aState = ModelAPI_StateInvalidArgument;
+    if (aDouble.get() && !aDouble->text().empty()) {
+      if (aDouble->expressionInvalid()) {
+        aState = ModelAPI_StateInvalidArgument;
+      }
     }
   }
 
@@ -371,31 +375,36 @@ void Model_Update::updateFeature(FeaturePtr theFeature)
     //std::cout<<"Update feature "<<theFeature->getKind()<<" must be updated = "<<aMustbeUpdated<<std::endl;
     // execute feature if it must be updated
     if (aJustUpdated) {
-      if ((std::dynamic_pointer_cast<Model_Document>(theFeature->document())->executeFeatures() ||
-          !theFeature->isPersistentResult()) && theFeature->isPreviewNeeded()) {
-        if (aFactory->validate(theFeature)) {
-          if (myIsAutomatic || !theFeature->isPersistentResult() /* execute quick, not persistent results */
-              || (isUpdated(theFeature) && 
-               theFeature == theFeature->document()->currentFeature(false))) // currently edited
-          {
-            if (aState == ModelAPI_StateDone || aState == ModelAPI_StateMustBeUpdated) {
-              executeFeature(theFeature);
-            }
-          } else { // must be updatet, but not updated yet
-            theFeature->data()->execState(ModelAPI_StateMustBeUpdated);
-            const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = theFeature->results();
-            std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
-            for (; aRIter != aResults.cend(); aRIter++) {
-              std::shared_ptr<ModelAPI_Result> aRes = *aRIter;
-              aRes->data()->execState(ModelAPI_StateMustBeUpdated);
+      if (theFeature->isPreviewNeeded()) {
+        if (std::dynamic_pointer_cast<Model_Document>(theFeature->document())->executeFeatures() ||
+            !theFeature->isPersistentResult()) {
+          if (aFactory->validate(theFeature)) {
+            if (myIsAutomatic || !theFeature->isPersistentResult() /* execute quick, not persistent results */
+                || (isUpdated(theFeature) && 
+                 theFeature == theFeature->document()->currentFeature(false))) // currently edited
+            {
+              if (aState == ModelAPI_StateDone || aState == ModelAPI_StateMustBeUpdated) {
+                executeFeature(theFeature);
+              }
+            } else { // must be updatet, but not updated yet
+              theFeature->data()->execState(ModelAPI_StateMustBeUpdated);
+              const std::list<std::shared_ptr<ModelAPI_Result> >& aResults = theFeature->results();
+              std::list<std::shared_ptr<ModelAPI_Result> >::const_iterator aRIter = aResults.begin();
+              for (; aRIter != aResults.cend(); aRIter++) {
+                std::shared_ptr<ModelAPI_Result> aRes = *aRIter;
+                aRes->data()->execState(ModelAPI_StateMustBeUpdated);
+              }
             }
+          } else {
+            theFeature->eraseResults();
+            redisplayWithResults(theFeature, ModelAPI_StateInvalidArgument); // result also must be updated
           }
-        } else {
-          theFeature->eraseResults();
-          redisplayWithResults(theFeature, ModelAPI_StateInvalidArgument); // result also must be updated
+        } else { // for automatically updated features (on abort, etc) it is necessary to redisplay anyway
+          redisplayWithResults(theFeature, ModelAPI_StateNothing);
         }
-      } else { // for automatically updated features (on abort, etc) it is necessary to redisplay anyway
-        redisplayWithResults(theFeature, ModelAPI_StateNothing);
+      } else { // preview is not needed => make state Done
+        if (theFeature->data()->execState() == ModelAPI_StateMustBeUpdated)
+          theFeature->data()->execState(ModelAPI_StateDone);
       }
     }
   }
index 12235c5b8586f68079cb757a2aef474ed9561996..37e9f68de6b1a8a51d85cadfa2d35012da463b04 100644 (file)
@@ -34,6 +34,9 @@ class ModelAPI_AttributeRefList : public ModelAPI_Attribute
   /// Erases the first meet of the feature in the list
   MODELAPI_EXPORT virtual void remove(ObjectPtr theObject) = 0;
 
+  /// Removes all references from the list
+  MODELAPI_EXPORT virtual void clear() = 0;
+
   /// Returns number of features in the list
   MODELAPI_EXPORT virtual int size() const = 0;
 
index 1073922eef634e345372e1020a95115d70df8550..3a16235768086f153cbd7a827527520778865a89 100644 (file)
@@ -36,7 +36,7 @@ std::shared_ptr<GeomAPI_Shape> shape(const ResultPtr& theResult)
   return theResult->shape();
 }
 
-bool findVariable(const std::string& theName, double& outValue)
+bool findVariable(const std::string& theName, double& outValue, ResultParameterPtr& theParam)
 {
   SessionPtr aSession = ModelAPI_Session::get();
   std::list<DocumentPtr> aDocList;
@@ -48,10 +48,10 @@ bool findVariable(const std::string& theName, double& outValue)
   }
   for(std::list<DocumentPtr>::const_iterator it = aDocList.begin(); it != aDocList.end(); ++it) {
     ObjectPtr aParamObj = (*it)->objectByName(ModelAPI_ResultParameter::group(), theName);
-    ResultParameterPtr aParam = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aParamObj);
-    if(!aParam.get())
+    theParam = std::dynamic_pointer_cast<ModelAPI_ResultParameter>(aParamObj);
+    if(!theParam.get())
       continue;
-    AttributeDoublePtr aValueAttribute = aParam->data()->real(ModelAPI_ResultParameter::VALUE());
+    AttributeDoublePtr aValueAttribute = theParam->data()->real(ModelAPI_ResultParameter::VALUE());
     outValue = aValueAttribute->value();
     return true;
   }
index e89a713ce23507f04d22c29243699f2600e14454..9bea2d9cd4ea7f1f3174e4e1af061c69498401d4 100644 (file)
@@ -9,6 +9,7 @@
 
 #include "ModelAPI.h"
 #include <ModelAPI_Result.h>
+#include <ModelAPI_ResultParameter.h>
 #include <GeomAPI_Shape.h>
 
 #include <vector>
@@ -22,7 +23,8 @@ MODELAPI_EXPORT std::shared_ptr<GeomAPI_Shape> shape(const ResultPtr& theResult)
  * in the root document (PartSet). If found, set it value in the \param outValue
  * and returns true.
  */
-MODELAPI_EXPORT bool findVariable(const std::string& theName, double& outValue);
+MODELAPI_EXPORT bool findVariable(const std::string& theName, double& outValue, 
+  ResultParameterPtr& theParam);
 
 /*!
  * Returns the values of the next random color. The values are in range [0, 255]
index 5501b26551f687b66e19c316bc38bf65c22b8981..5b88af890e58418d2afeb1658165f071d781170f 100644 (file)
@@ -164,7 +164,7 @@ bool ModuleBase_ParamSpinBox::hasVariable() const
 
 bool ModuleBase_ParamSpinBox::hasVariable(const QString& theText) const
 {
-  QRegExp varNameMask("[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?");
+  QRegExp varNameMask("[-+]?[0-9]*.?[0-9]+([eE][-+]?[0-9]+)?");
   return !varNameMask.exactMatch(theText);
 }
 
@@ -205,8 +205,8 @@ bool ModuleBase_ParamSpinBox::checkRange(const double theValue) const
 bool ModuleBase_ParamSpinBox::findVariable(const QString& theName,
                                            double& outValue) const
 {
-
-  return ModelAPI_Tools::findVariable(theName.toStdString(), outValue);
+  ResultParameterPtr aParam;
+  return ModelAPI_Tools::findVariable(theName.toStdString(), outValue, aParam);
 }
 
 /*!
index 904df9408166c2cabb180c6daa7e73cf0a2b2d32..d0e7a9c20f831fc97b06d7e8fa6eaec0d3db7f85 100644 (file)
@@ -10,7 +10,6 @@
 #include <ModelAPI_AttributeDouble.h>
 #include <ModelAPI_Data.h>
 #include <ModelAPI_Object.h>
-#include <ModelAPI_Events.h>
 
 #include <ModuleBase_ParamSpinBox.h>
 #include <ModuleBase_Tools.h>
@@ -125,12 +124,6 @@ bool ModuleBase_WidgetDoubleValue::storeValueCustom() const
     // 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);
   }
   updateObject(myFeature);
   return true;
index 06f2ecfa1397be4b00200e56291a5f3ac58560ca..8fa3af26d26559638dbb739d7d1cbdfbf4c483a5 100644 (file)
@@ -66,7 +66,8 @@ double ParametersPlugin_EvalListener::evaluate(const std::string& theExpression,
   std::list<std::string>::iterator it = anExprParams.begin();
   for ( ; it != anExprParams.end(); it++) {
     double aValue;
-    if (!ModelAPI_Tools::findVariable(*it, aValue)) continue;
+    ResultParameterPtr aParamRes;
+    if (!ModelAPI_Tools::findVariable(*it, aValue, aParamRes)) continue;
 
     std::ostringstream sstream;
     sstream << aValue;
@@ -78,4 +79,3 @@ double ParametersPlugin_EvalListener::evaluate(const std::string& theExpression,
   myInterp->clearLocalContext();
   return result;
 }
-
index f9fdc7c6d114d6493101b5874747048e15ffef87..58280994c84c8f539cb36813329816f454046332 100644 (file)
 #include <ModelAPI_AttributeString.h>
 #include <ModelAPI_ResultParameter.h>
 #include <ModelAPI_AttributeDouble.h>
+#include <ModelAPI_AttributeRefList.h>
 #include <ModelAPI_Tools.h>
+#include <ModelAPI_Session.h>
+#include <ModelAPI_Validator.h>
 
 #include <string>
 #include <sstream>
@@ -27,10 +30,10 @@ ParametersPlugin_Parameter::~ParametersPlugin_Parameter()
 
 void ParametersPlugin_Parameter::initAttributes()
 {
-  data()->addAttribute(ParametersPlugin_Parameter::VARIABLE_ID(),
-                       ModelAPI_AttributeString::typeId());
-  data()->addAttribute(ParametersPlugin_Parameter::EXPRESSION_ID(),
-                       ModelAPI_AttributeString::typeId());
+  data()->addAttribute(VARIABLE_ID(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(EXPRESSION_ID(), ModelAPI_AttributeString::typeId());
+  data()->addAttribute(ARGUMENTS_ID(), ModelAPI_AttributeRefList::typeId());
+  ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), ARGUMENTS_ID());
 }
 
 bool ParametersPlugin_Parameter::isInHistory()
@@ -38,40 +41,47 @@ bool ParametersPlugin_Parameter::isInHistory()
   return false;
 }
 
-void ParametersPlugin_Parameter::attributeChanged(const std::string&)
+void ParametersPlugin_Parameter::attributeChanged(const std::string& theID)
 {
-  ResultParameterPtr aParam = document()->createParameter(data());
+  if (theID == EXPRESSION_ID()) { // recompute only on change of the expression
+    ResultParameterPtr aParam = document()->createParameter(data());
 
-  std::string anExpression = string(ParametersPlugin_Parameter::EXPRESSION_ID())->value();
-  if(anExpression.empty()) {
-    // clear error/result if the expression is empty
-    setError("", false);
-    return;
+    std::string anExpression = string(EXPRESSION_ID())->value();
+    if(anExpression.empty()) {
+      // clear error/result if the expression is empty
+      setError("", false);
+      return;
+    }
+    std::string outErrorMessage;
+    double aValue = evaluate(anExpression, outErrorMessage);
+    // Name
+    std::string aName = string(VARIABLE_ID())->value();
+    std::ostringstream sstream;
+    sstream << aValue;
+    std::string aParamValue = sstream.str();
+    data()->setName(aName);
+    aParam->data()->setName(aName);
+    // Error
+    if (!outErrorMessage.empty()) {
+      std::string aStateMsg("Error: " + outErrorMessage);
+      data()->execState(ModelAPI_StateExecFailed);
+      setError(aStateMsg, false);
+    } else {
+      static const std::string anEmptyMsg(""); // it is checked in the validator by the empty message
+      setError(anEmptyMsg, false);
+      data()->execState(ModelAPI_StateDone);
+    }
+    // Value
+    AttributeDoublePtr aValueAttribute = aParam->data()->real(ModelAPI_ResultParameter::VALUE());
+    aValueAttribute->setValue(aValue);
+    setResult(aParam);
   }
-  std::string outErrorMessage;
-  double aValue = evaluate(anExpression, outErrorMessage);
-  // Name
-  std::string aName = string(ParametersPlugin_Parameter::VARIABLE_ID())->value();
-  std::ostringstream sstream;
-  sstream << aValue;
-  std::string aParamValue = sstream.str();
-  data()->setName(aName);
-  aParam->data()->setName(aName);
-  // Error
-  std::string aStateMsg;
-  if (!outErrorMessage.empty()) {
-    aStateMsg = "Error: " + outErrorMessage;
-    data()->execState(ModelAPI_StateExecFailed);
-  } 
-  setError(aStateMsg, false);
-  // Value
-  AttributeDoublePtr aValueAttribute = aParam->data()->real(ModelAPI_ResultParameter::VALUE());
-  aValueAttribute->setValue(aValue);
-  setResult(aParam);
 }
 
 void ParametersPlugin_Parameter::execute()
 {
+  // just call recompute
+  attributeChanged(EXPRESSION_ID());
 }
 
 double ParametersPlugin_Parameter::evaluate(const std::string& theExpression, std::string& theError)
@@ -81,17 +91,45 @@ double ParametersPlugin_Parameter::evaluate(const std::string& theExpression, st
   // find expression's params in the model
   std::list<std::string> aContext;
   std::list<std::string>::iterator it = anExprParams.begin();
+  std::list<ResultParameterPtr> aParamsList;
   for ( ; it != anExprParams.end(); it++) {
     double aValue;
-    if (!ModelAPI_Tools::findVariable(*it, aValue)) continue;
+    ResultParameterPtr aParamRes;
+    if (!ModelAPI_Tools::findVariable(*it, aValue, aParamRes)) continue;
+    aParamsList.push_back(aParamRes);
 
     std::ostringstream sstream;
     sstream << aValue;
     std::string aParamValue = sstream.str();
     aContext.push_back(*it + "=" + aParamValue);
   }
+  // compare the list of parameters to store if changed
+  AttributeRefListPtr aParams = reflist(ARGUMENTS_ID());
+  bool aDifferent = aParams->size() != aParamsList.size();
+  if (!aDifferent) {
+    std::list<ResultParameterPtr>::iterator aNewIter = aParamsList.begin();
+    std::list<ObjectPtr> anOldList = aParams->list();
+    std::list<ObjectPtr>::iterator anOldIter = anOldList.begin();
+    for(; !aDifferent && aNewIter != aParamsList.end(); aNewIter++, anOldIter++) {
+      if (*aNewIter != *anOldIter)
+        aDifferent = true;
+    }
+  }
+  if (aDifferent) {
+    aParams->clear();
+    std::list<ResultParameterPtr>::iterator aNewIter = aParamsList.begin();
+    for(; aNewIter != aParamsList.end(); aNewIter++) {
+      aParams->append(*aNewIter);
+    }
+  }
+
   myInterp->extendLocalContext(aContext);
   double result = myInterp->evaluate(theExpression, theError);
   myInterp->clearLocalContext();
   return result;
 }
+
+bool ParametersPlugin_Parameter::isPreviewNeeded() const
+{
+  return false;
+}
index a65a5ff38005e82ebb6971b70065aad056e48a5d..c348d0f733d257d7bb1820e2a167b668cd769249 100644 (file)
@@ -40,6 +40,13 @@ class ParametersPlugin_Parameter : public ModelAPI_Feature
     return MY_EXPRESSION_ID;
   }
 
+  /// list of references to the arguments of this expression
+  inline static const std::string& ARGUMENTS_ID()
+  {
+    static const std::string MY_VARIABLE_ID("arguments");
+    return MY_VARIABLE_ID;
+  }
+
   /// Returns the kind of a feature
   PARAMETERSPLUGIN_EXPORT virtual const std::string& getKind()
   {
@@ -47,6 +54,9 @@ class ParametersPlugin_Parameter : public ModelAPI_Feature
     return MY_KIND;
   }
 
+  /// Pre-execution is not needed for parameter
+  PARAMETERSPLUGIN_EXPORT virtual bool isPreviewNeeded() const;
+
   /// Creates a new part document if needed
   PARAMETERSPLUGIN_EXPORT virtual void execute();