From: Alexey Kondratyev Date: Mon, 11 Oct 2021 07:33:06 +0000 (+0300) Subject: bos #26444 Improve treatment of parameters X-Git-Tag: V9_8_0b1^2 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=accd372f85e4c22be316348c94192ebb43fb4add;p=modules%2Fshaper.git bos #26444 Improve treatment of parameters Add python function to import parameters from file. Add test for checking importing parameters. Add "Import file" button in parameter manager to import parameters. Update documentation. --- diff --git a/src/InitializationPlugin/InitializationPlugin_EvalListener.cpp b/src/InitializationPlugin/InitializationPlugin_EvalListener.cpp index 76a388ee5..26126b8f5 100644 --- a/src/InitializationPlugin/InitializationPlugin_EvalListener.cpp +++ b/src/InitializationPlugin/InitializationPlugin_EvalListener.cpp @@ -78,6 +78,7 @@ InitializationPlugin_EvalListener::InitializationPlugin_EvalListener() aLoop->registerListener(this, ModelAPI_ParameterEvalMessage::eventId(), NULL, true); aLoop->registerListener(this, ModelAPI_BuildEvalMessage::eventId(), NULL, true); aLoop->registerListener(this, ModelAPI_ComputePositionsMessage::eventId(), NULL, true); + aLoop->registerListener(this, ModelAPI_ImportParametersMessage::eventId(), NULL, true); myInterp = std::shared_ptr(new InitializationPlugin_PyInterp()); myInterp->initialize(); @@ -179,6 +180,16 @@ void InitializationPlugin_EvalListener::processEvent( } aMsg->setResults(aParamsList, anError); } + else if (theMessage->eventID() == ModelAPI_ImportParametersMessage::eventId()) + { + std::shared_ptr aMsg = + std::dynamic_pointer_cast(theMessage); + std::string anImportScript("from salome.shaper import model;"); + std::string aDocScript("doc = model.activeDocument();"); + std::string anParamImpScript("model.importParameters(doc, \""); + std::string aPath = aMsg->filename(); + myInterp->runString(anImportScript + aDocScript + anParamImpScript + aPath + "\")"); + } } //================================================================================================= diff --git a/src/ModelAPI/ModelAPI_Events.cpp b/src/ModelAPI/ModelAPI_Events.cpp index 6b0ea3ef5..506b26189 100644 --- a/src/ModelAPI/ModelAPI_Events.cpp +++ b/src/ModelAPI/ModelAPI_Events.cpp @@ -188,6 +188,27 @@ const std::string& ModelAPI_ParameterEvalMessage::error() const return myError; } +/// Creates an empty message +ModelAPI_ImportParametersMessage::ModelAPI_ImportParametersMessage(const Events_ID theID, const void* theSender) + :Events_Message(theID, theSender) +{ + +} + +ModelAPI_ImportParametersMessage::~ModelAPI_ImportParametersMessage() +{ +} + +std::string ModelAPI_ImportParametersMessage::filename() const +{ + return myFilename; +} + +void ModelAPI_ImportParametersMessage::setFilename(std::string theFilename) +{ + myFilename = theFilename; +} + ModelAPI_BuildEvalMessage::ModelAPI_BuildEvalMessage( const Events_ID theID, const void* theSender) : Events_Message(theID, theSender), myIsProcessed(false) diff --git a/src/ModelAPI/ModelAPI_Events.h b/src/ModelAPI/ModelAPI_Events.h index a5dc0dde9..2ebd25b0f 100644 --- a/src/ModelAPI/ModelAPI_Events.h +++ b/src/ModelAPI/ModelAPI_Events.h @@ -352,6 +352,44 @@ class ModelAPI_ParameterEvalMessage : public Events_Message MODELAPI_EXPORT const std::string& error() const; }; +class ModelAPI_ImportParametersMessage : public Events_Message +{ + std::string myFilename; ///< filename where where parameters are stored + std::string myError; ///< error of processing, empty if there is no error + +public: + /// Static. Returns EventID of the message. + MODELAPI_EXPORT static Events_ID& eventId() + { + static const char* MY_PARAMETER_EVALUATION_EVENT_ID("ImportParametersMessage"); + static Events_ID anId = Events_Loop::eventByName(MY_PARAMETER_EVALUATION_EVENT_ID); + return anId; + } + + /// Useful method that creates and sends the event. + /// Returns the message, processed, with the resulting fields filled. + MODELAPI_EXPORT static std::shared_ptr + send(std::string theParameter, const void* theSender) + { + std::shared_ptr aMessage = + std::shared_ptr( + new ModelAPI_ImportParametersMessage(eventId(), theSender)); + aMessage->setFilename(theParameter); + Events_Loop::loop()->send(aMessage); + return aMessage; + } + + /// Creates an empty message + MODELAPI_EXPORT ModelAPI_ImportParametersMessage(const Events_ID theID, const void* theSender = 0); + /// The virtual destructor + MODELAPI_EXPORT virtual ~ModelAPI_ImportParametersMessage(); + + /// Returns a filename stored in the message + MODELAPI_EXPORT std::string filename() const; + /// Sets a filename to the message + MODELAPI_EXPORT void setFilename(std::string theFilename); +}; + class ModelAPI_BuildEvalMessage : public Events_Message { FeaturePtr myParam; ///< parameters that should be evaluated diff --git a/src/ModelHighAPI/ModelHighAPI_Dumper.cpp b/src/ModelHighAPI/ModelHighAPI_Dumper.cpp index 6110bf89e..09900d6b8 100644 --- a/src/ModelHighAPI/ModelHighAPI_Dumper.cpp +++ b/src/ModelHighAPI/ModelHighAPI_Dumper.cpp @@ -1275,7 +1275,14 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<( ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<( const std::shared_ptr& theAttrStr) { - *myDumpStorage << "\"" << theAttrStr->value() << "\""; + // escaping the quote sign in the string under dumping + std::string aStr = theAttrStr->value(); + size_t aPos = aStr.find("\""); + while (aPos != std::string::npos) { + aStr.insert(aPos, "\\"); + aPos = aStr.find("\"", aPos + 2); + } + *myDumpStorage << "'" << aStr << "'"; return *this; } diff --git a/src/ModelHighAPI/ModelHighAPI_Tools.cpp b/src/ModelHighAPI/ModelHighAPI_Tools.cpp index 8208eba76..14ab98878 100644 --- a/src/ModelHighAPI/ModelHighAPI_Tools.cpp +++ b/src/ModelHighAPI/ModelHighAPI_Tools.cpp @@ -224,6 +224,13 @@ void fillAttribute(const std::string & theValue, theAttribute->setValue(theValue); } +//-------------------------------------------------------------------------------------- +void fillAttribute(const std::wstring & theValue, + const std::shared_ptr & theAttribute) +{ + theAttribute->setValue(theValue); +} + //-------------------------------------------------------------------------------------- void fillAttribute(const char * theValue, const std::shared_ptr & theAttribute) diff --git a/src/ModelHighAPI/ModelHighAPI_Tools.h b/src/ModelHighAPI/ModelHighAPI_Tools.h index 7f0e1c896..a476721a6 100644 --- a/src/ModelHighAPI/ModelHighAPI_Tools.h +++ b/src/ModelHighAPI/ModelHighAPI_Tools.h @@ -136,6 +136,11 @@ void fillAttribute(const std::list & theValue, MODELHIGHAPI_EXPORT void fillAttribute(const std::string & theValue, const std::shared_ptr & theAttribute); + +MODELHIGHAPI_EXPORT +void fillAttribute(const std::wstring & theValue, + const std::shared_ptr & theAttribute); + MODELHIGHAPI_EXPORT void fillAttribute(const char * theValue, const std::shared_ptr & theAttribute); diff --git a/src/ParametersAPI/ParametersAPI.i b/src/ParametersAPI/ParametersAPI.i index 6922c1f96..66ba5fb3d 100644 --- a/src/ParametersAPI/ParametersAPI.i +++ b/src/ParametersAPI/ParametersAPI.i @@ -23,6 +23,11 @@ %{ #include "ParametersAPI_swig.h" + + // fix for SWIG v2.0.4 + #define SWIGPY_SLICE_ARG(obj) ((PyObject*)(obj)) + + #define SWIGPY_UNICODE_ARG(obj) ((PyObject*) (obj)) %} %include "doxyhelp.i" @@ -40,5 +45,15 @@ // shared pointers %shared_ptr(ParametersAPI_Parameter) +// exception handler +%exception addParameter { + try { + $action + } catch (const std::string& str) { + PyErr_SetString(PyExc_SyntaxError, str.c_str()); + return NULL; + } +} + // all supported interfaces %include "ParametersAPI_Parameter.h" diff --git a/src/ParametersAPI/ParametersAPI_Parameter.cpp b/src/ParametersAPI/ParametersAPI_Parameter.cpp index 27c687ad3..5c2c7130c 100644 --- a/src/ParametersAPI/ParametersAPI_Parameter.cpp +++ b/src/ParametersAPI/ParametersAPI_Parameter.cpp @@ -35,7 +35,7 @@ ParametersAPI_Parameter::ParametersAPI_Parameter( const std::shared_ptr & theFeature, const std::string & theName, const std::string & theExpression, - const std::string & theComment) + const std::wstring & theComment) : ModelHighAPI_Interface(theFeature) { if (initialize()) { @@ -87,10 +87,18 @@ void ParametersAPI_Parameter::dump(ModelHighAPI_Dumper& theDumper) const ParameterPtr addParameter(const std::shared_ptr & thePart, const std::string & theName, const std::string & theExpression, - const std::string & theComment) + const std::wstring & theComment) { std::shared_ptr aFeature = thePart->addFeature(ParametersAPI_Parameter::ID()); - return ParameterPtr(new ParametersAPI_Parameter(aFeature, theName, theExpression, theComment)); + ParameterPtr aParam(new ParametersAPI_Parameter(aFeature, theName, theExpression, theComment)); + + if (!aParam->feature()->error().empty()) + { + std::string anError("Error with parameter \""); + anError += theName + "\": " + aParam->feature()->error(); + throw anError; + } + return aParam; } //-------------------------------------------------------------------------------------- diff --git a/src/ParametersAPI/ParametersAPI_Parameter.h b/src/ParametersAPI/ParametersAPI_Parameter.h index 50bb1d3b8..8295db3cc 100644 --- a/src/ParametersAPI/ParametersAPI_Parameter.h +++ b/src/ParametersAPI/ParametersAPI_Parameter.h @@ -45,7 +45,7 @@ public: explicit ParametersAPI_Parameter(const std::shared_ptr & theFeature, const std::string & theName, const std::string & theExpression, - const std::string & theComment = std::string()); + const std::wstring & theComment = std::wstring()); /// Destructor PARAMETERSAPI_EXPORT virtual ~ParametersAPI_Parameter(); @@ -80,7 +80,7 @@ PARAMETERSAPI_EXPORT ParameterPtr addParameter(const std::shared_ptr & thePart, const std::string & theName, const std::string & theExpression, - const std::string & theComment = std::string()); + const std::wstring & theComment = std::wstring()); /**\ingroup CPPHighAPI * \brief Remove Parameter feature and substitute it by the value in referred features diff --git a/src/ParametersPlugin/CMakeLists.txt b/src/ParametersPlugin/CMakeLists.txt index 9f1140baa..bd37033bd 100644 --- a/src/ParametersPlugin/CMakeLists.txt +++ b/src/ParametersPlugin/CMakeLists.txt @@ -137,4 +137,5 @@ if(${HAVE_SALOME}) endforeach(tfile ${TEST_NAMES}) install(FILES ${TMP_TESTS_NAMES} DESTINATION ${TEST_INSTALL_DIRECTORY}) + install(DIRECTORY Test/data DESTINATION ${TEST_INSTALL_DIRECTORY}) endif(${HAVE_SALOME}) diff --git a/src/ParametersPlugin/ParametersPlugin_WidgetParamsMgr.cpp b/src/ParametersPlugin/ParametersPlugin_WidgetParamsMgr.cpp index 62a432a8b..6cad00013 100644 --- a/src/ParametersPlugin/ParametersPlugin_WidgetParamsMgr.cpp +++ b/src/ParametersPlugin/ParametersPlugin_WidgetParamsMgr.cpp @@ -54,6 +54,7 @@ #include #include #include +#include enum ColumnType { Col_Name, @@ -253,6 +254,10 @@ ParametersPlugin_WidgetParamsMgr::ParametersPlugin_WidgetParamsMgr(QWidget* theP connect(myInsertBtn, SIGNAL(clicked(bool)), SLOT(onInsert())); aBtnLayout->addWidget(myInsertBtn); + myImportBtn = new QPushButton(translate("Import file"), this); + connect(myImportBtn, SIGNAL(clicked(bool)), SLOT(onImport())); + aBtnLayout->addWidget(myImportBtn); + myRemoveBtn = new QPushButton(translate("Remove"), this); connect(myRemoveBtn, SIGNAL(clicked(bool)), SLOT(onRemove())); aBtnLayout->addWidget(myRemoveBtn); @@ -484,6 +489,7 @@ void ParametersPlugin_WidgetParamsMgr::onCloseEditor(QWidget* theEditor, FeaturePtr aFeature = myParametersList.at(myDelegate->editIndex().row()); QTreeWidgetItem* aItem = myParameters->child(myDelegate->editIndex().row()); int aColumn = myDelegate->editIndex().column(); + int aRow = myDelegate->editIndex().row(); QString aText = aItem->text(aColumn); bool isModified = false; @@ -495,7 +501,7 @@ void ParametersPlugin_WidgetParamsMgr::onCloseEditor(QWidget* theEditor, while (aText.indexOf(" ") != -1) { aText.replace(" ", ""); } - if (hasName(aText)) { + if (hasName(aText, aRow)) { myMessage = translate("Name '%1' already exists.").arg(aText); QTimer::singleShot(50, this, SLOT(sendWarning())); return; @@ -521,7 +527,7 @@ void ParametersPlugin_WidgetParamsMgr::onCloseEditor(QWidget* theEditor, case Col_Comment: { AttributeStringPtr aStringAttr = aFeature->string(ParametersPlugin_Parameter::COMMENT_ID()); - aStringAttr->setValue(aText.toStdString()); + aStringAttr->setValue(aText.toStdWString()); isModified = true; } break; @@ -691,6 +697,27 @@ void ParametersPlugin_WidgetParamsMgr::onRemove() } } +void ParametersPlugin_WidgetParamsMgr::onImport() +{ + std::string aWinText("Select txt file"); + std::string aFileType("Text files (*.txt);;All files (*.*)"); + QString aQPath = QFileDialog::getOpenFileName(nullptr, + aWinText.c_str(), "", + aFileType.c_str()); + if (aQPath.size() == 0) + return; + + std::string aPath(aQPath.toStdString()); + std::shared_ptr aMessage = + std::shared_ptr( + new ModelAPI_ImportParametersMessage(ModelAPI_ImportParametersMessage::eventId())); + aMessage->setFilename(aPath); + Events_Loop::loop()->send(aMessage); + + updateParametersFeatures(); + updateParametersPart(); +} + void ParametersPlugin_WidgetParamsMgr::onUp() { QTreeWidgetItem* aCurrentItem = selectedItem(); @@ -764,12 +791,11 @@ void ParametersPlugin_WidgetParamsMgr::onDown() } -bool ParametersPlugin_WidgetParamsMgr::hasName(const QString& theName) const +bool ParametersPlugin_WidgetParamsMgr::hasName(const QString& theName, int theIndex) const { - int aCurrent = myDelegate->editIndex().row(); int i = 0; foreach(FeaturePtr aFeature, myParametersList) { - if ((i != aCurrent) && (aFeature->data()->name() == theName.toStdWString())) + if ((i != theIndex) && (aFeature->data()->name() == theName.toStdWString())) return true; i++; } @@ -800,11 +826,13 @@ void ParametersPlugin_WidgetParamsMgr::onSelectionChanged() //myRemoveBtn->setEnabled(isParameter); myUpBtn->setEnabled(isParameter); myDownBtn->setEnabled(isParameter); + myImportBtn->setEnabled(true); } else { myInsertBtn->setEnabled(false); //myRemoveBtn->setEnabled(false); myUpBtn->setEnabled(false); myDownBtn->setEnabled(false); + myImportBtn->setEnabled(false); } myRemoveBtn->setEnabled(!aItemsList.isEmpty()); } @@ -819,6 +847,7 @@ void ParametersPlugin_WidgetParamsMgr::enableButtons(bool theEnable) //myRemoveBtn->setEnabled(theEnable); myUpBtn->setEnabled(theEnable); myDownBtn->setEnabled(theEnable); + myImportBtn->setEnabled(theEnable); } myOkCancelBtn->button(QDialogButtonBox::Ok)->setEnabled(theEnable); } @@ -830,7 +859,8 @@ bool ParametersPlugin_WidgetParamsMgr::isValid() aItem = myParameters->child(i); if ((aItem->text(Col_Name) == NoName) || (aItem->text(Col_Equation) == translate(NoValue)) || - (!ModelAPI_Expression::isVariable(aItem->text(Col_Name).toStdString())) ) { + (!ModelAPI_Expression::isVariable(aItem->text(Col_Name).toStdString())) || + (hasName(aItem->text(Col_Name), i)) ) { return false; } } diff --git a/src/ParametersPlugin/ParametersPlugin_WidgetParamsMgr.h b/src/ParametersPlugin/ParametersPlugin_WidgetParamsMgr.h index 58f717e45..6cc543d0d 100644 --- a/src/ParametersPlugin/ParametersPlugin_WidgetParamsMgr.h +++ b/src/ParametersPlugin/ParametersPlugin_WidgetParamsMgr.h @@ -109,6 +109,9 @@ private slots: /// Slot for reaction on remove parameter void onRemove(); + /// Slot for reaction on import parameter + void onImport(); + /// Slot for reaction on shift up void onUp(); @@ -148,7 +151,7 @@ private: bool isValid(); /// Returns true if parameter with the given name already exists - bool hasName(const QString& theName) const; + bool hasName(const QString& theName, int theIndex) const; /// Enable or disable buttons for parameters managemnt void enableButtons(bool theEnable); @@ -173,6 +176,7 @@ private: QPushButton* myAddBtn; QPushButton* myInsertBtn; QPushButton* myRemoveBtn; + QPushButton* myImportBtn; QToolButton* myUpBtn; QToolButton* myDownBtn; diff --git a/src/ParametersPlugin/Test/TestImportInvalidParameters.py b/src/ParametersPlugin/Test/TestImportInvalidParameters.py new file mode 100644 index 000000000..61b9751d1 --- /dev/null +++ b/src/ParametersPlugin/Test/TestImportInvalidParameters.py @@ -0,0 +1,36 @@ +# Copyright (C) 2014-2021 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +from salome.shaper import model +import inspect, os + +data_dir = os.path.join(os.path.dirname(inspect.getfile(lambda: None)), "data") + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() + +nameFile = "invalid_parameters.txt" + +aDir = os.path.join(data_dir, nameFile) + +aListOfParameters = model.importParameters(Part_1_doc, aDir) + +assert(len(aListOfParameters) == 0) diff --git a/src/ParametersPlugin/Test/TestImportParameters.py b/src/ParametersPlugin/Test/TestImportParameters.py new file mode 100644 index 000000000..29fbf7f68 --- /dev/null +++ b/src/ParametersPlugin/Test/TestImportParameters.py @@ -0,0 +1,40 @@ +# Copyright (C) 2014-2021 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +from salome.shaper import model +import inspect, os + +data_dir = os.path.join(os.path.dirname(inspect.getfile(lambda: None)), "data") + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() + +nameFile = "parameters.txt" + +aDir = os.path.join(data_dir, nameFile) + +aListOfParameters = model.importParameters(Part_1_doc, aDir) + +Box_1 = model.addBox(Part_1_doc, "Longueur", "Largeur", "Hauteur") + +assert(len(Box_1.feature().error()) == 0) +assert(len(aListOfParameters) == 5) +assert(model.checkPythonDump()) diff --git a/src/ParametersPlugin/Test/TestParameterCreationError.py b/src/ParametersPlugin/Test/TestParameterCreationError.py new file mode 100644 index 000000000..45da43336 --- /dev/null +++ b/src/ParametersPlugin/Test/TestParameterCreationError.py @@ -0,0 +1,35 @@ +# Copyright (C) 2014-2021 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +from salome.shaper import model + +model.begin() +partSet = model.moduleDocument() + +### Create Part +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +aPart1 = model.addParameter(Part_1_doc, "Doing", "123", "Longueur de la pièce") +try: + aPart2 = model.addParameter(Part_1_doc, "Doing", "323", "Long") +except SyntaxError as anError: + assert(anError != "") + assert(str(anError).find("Variable name is not unique.") != -1) + +model.end() diff --git a/src/ParametersPlugin/Test/TestParameterErrorMsg.py b/src/ParametersPlugin/Test/TestParameterErrorMsg.py index bc7443528..d21b360de 100644 --- a/src/ParametersPlugin/Test/TestParameterErrorMsg.py +++ b/src/ParametersPlugin/Test/TestParameterErrorMsg.py @@ -22,15 +22,23 @@ from salome.shaper import model model.begin() partSet = model.moduleDocument() # check error on empty name -Param1 = model.addParameter(partSet, "", "100") -assert(Param1.feature().error() != "") +try: + Param1 = model.addParameter(partSet, "", "100") +except SyntaxError as anError: + assert(str(anError).find("Attribute \"variable\" value is empty.") != -1) # check error on empty value -Param2 = model.addParameter(partSet, "L", "") -assert(Param2.feature().error() != "") +try: + Param2 = model.addParameter(partSet, "L", "") +except SyntaxError as anError: + assert(str(anError).find("Expression is empty.") != -1) # check error if name is not variable -Param3 = model.addParameter(partSet, "100", "100") -assert(Param3.feature().error() != "") +try: + Param3 = model.addParameter(partSet, "100", "100") +except SyntaxError as anError: + assert(str(anError).find("Incorrect variable name.") != -1) # check error on wrong value expression -Param4 = model.addParameter(partSet, "N", "+-.so&@") -assert(Param4.feature().error() != "") +try: + Param4 = model.addParameter(partSet, "N", "+-.so&@") +except SyntaxError as anError: + assert(str(anError).find("invalid syntax") != -1) model.end() diff --git a/src/ParametersPlugin/Test/data/invalid_parameters.txt b/src/ParametersPlugin/Test/data/invalid_parameters.txt new file mode 100644 index 000000000..c119a86f8 --- /dev/null +++ b/src/ParametersPlugin/Test/data/invalid_parameters.txt @@ -0,0 +1,5 @@ +Hauteur Longueur*Largeur + +Largeur3 #Comment +# Comment + # Comm diff --git a/src/ParametersPlugin/Test/data/parameters.txt b/src/ParametersPlugin/Test/data/parameters.txt new file mode 100644 index 000000000..ca3185fdb --- /dev/null +++ b/src/ParametersPlugin/Test/data/parameters.txt @@ -0,0 +1,5 @@ +Longueur 36. # "Longueur de la pièce" +Largeur 24. # Largeur de la pièce +Hauteur Longueur*Largeur +A12 5. * 5. +Longueur2 36. #\"Comment\" #Comm #Comm \ No newline at end of file diff --git a/src/ParametersPlugin/doc/TUI_parameterFeature.rst b/src/ParametersPlugin/doc/TUI_parameterFeature.rst index bf120a891..04480ce43 100644 --- a/src/ParametersPlugin/doc/TUI_parameterFeature.rst +++ b/src/ParametersPlugin/doc/TUI_parameterFeature.rst @@ -9,4 +9,5 @@ Create Parameter :language: python :download:`Download this script ` +:download:`Download parameters file sample ` diff --git a/src/ParametersPlugin/doc/examples/File.txt b/src/ParametersPlugin/doc/examples/File.txt new file mode 100644 index 000000000..5ab7e7825 --- /dev/null +++ b/src/ParametersPlugin/doc/examples/File.txt @@ -0,0 +1,3 @@ +Width 10.0 #Width of square +Height 15.0 # Height of square +Area Width*Height # Area of square \ No newline at end of file diff --git a/src/ParametersPlugin/doc/examples/parameter.py b/src/ParametersPlugin/doc/examples/parameter.py index dc269a6e0..39d6fdb45 100644 --- a/src/ParametersPlugin/doc/examples/parameter.py +++ b/src/ParametersPlugin/doc/examples/parameter.py @@ -3,4 +3,5 @@ from salome.shaper import model model.begin() partSet = model.moduleDocument() model.addParameter(partSet, "angle", "60*3.141/180", "main angle") +model.importParameters(partSet, "File.txt") model.end() diff --git a/src/ParametersPlugin/doc/images/Manager.png b/src/ParametersPlugin/doc/images/Manager.png index a7e812d67..99d0c1e69 100644 Binary files a/src/ParametersPlugin/doc/images/Manager.png and b/src/ParametersPlugin/doc/images/Manager.png differ diff --git a/src/ParametersPlugin/doc/images/parameters.png b/src/ParametersPlugin/doc/images/parameters.png index 4f1e1f66c..fbf1d7b57 100755 Binary files a/src/ParametersPlugin/doc/images/parameters.png and b/src/ParametersPlugin/doc/images/parameters.png differ diff --git a/src/ParametersPlugin/doc/managerFeature.rst b/src/ParametersPlugin/doc/managerFeature.rst index 7575ee81e..fe1ed998d 100644 --- a/src/ParametersPlugin/doc/managerFeature.rst +++ b/src/ParametersPlugin/doc/managerFeature.rst @@ -20,6 +20,8 @@ The following dialog box with parameter table appears: .. |param_up| image:: images/parameters_up.png .. |param_down| image:: images/parameters_down.png +To edit a parameter, double-click on parameter in object browser. + **Input fields**: - **Name** defines parameter name. Name follows the naming rules of the python language for variables; @@ -29,9 +31,23 @@ The following dialog box with parameter table appears: - **Add** button adds a new empty string in the end of table. Default **Name** is **, **Expression** is ** - **Insert** button adds a new empty string before the selected parameter; - **Delete** button removes the selected parameter from the table; +- **Import** button import parameters from .txt files. Parameters must be written in file in separate lines like example: **Name** **Expression** #**Comment** +Sample.txt: +''Longueur 36. # Longueur de la pièce'' +''Largeur 24 #Largeur de la pièce'' +''Hauteur Longueur * Largeur'' - **Modify parameter position** button moves the selected parameter | |param_up| one string higher in the table, | |param_down| one string lower in the table. +**TUI Command**: + +.. py:function:: model.importParameters(Part_doc, filename) + + :param part: The current part object + :param filename: The txt file with parameters + :return: Created objects. + +**See Also** a sample TUI Script of a :ref:`tui_parameterFeature` operation. **See Also** :ref:`parameter` operation. diff --git a/src/ParametersPlugin/doc/parameterFeature.rst b/src/ParametersPlugin/doc/parameterFeature.rst index 757a023f0..24e6bc06a 100644 --- a/src/ParametersPlugin/doc/parameterFeature.rst +++ b/src/ParametersPlugin/doc/parameterFeature.rst @@ -41,6 +41,11 @@ The property panel checks validity of the expression. For an invalid expression :param string: The parameter comment :return: Created object. +Write error in Python console if: +- parameter name is empty. +- parameter don't have unique name. +- parameter expression is empty or incorrect. + **See Also** a sample TUI Script of a :ref:`tui_parameterFeature` operation. Result diff --git a/src/ParametersPlugin/tests.set b/src/ParametersPlugin/tests.set index 48514ff6b..668f4668f 100644 --- a/src/ParametersPlugin/tests.set +++ b/src/ParametersPlugin/tests.set @@ -28,4 +28,6 @@ SET(TEST_NAMES Test2392.py Test2474.py Test19036.py + TestImportParameters.py + TestImportInvalidParameters.py ) diff --git a/src/PartSet/PartSet_Module.cpp b/src/PartSet/PartSet_Module.cpp index a3095a374..c648cc072 100644 --- a/src/PartSet/PartSet_Module.cpp +++ b/src/PartSet/PartSet_Module.cpp @@ -83,6 +83,7 @@ #include #include #include +#include #include #include @@ -1739,6 +1740,25 @@ void PartSet_Module::onTreeViewDoubleClick(const QModelIndex& theIndex) if (aPartFeature.get() && (aPartFeature->getKind() == PartSetPlugin_Part::ID())) { aPart = std::dynamic_pointer_cast(aPartFeature->firstResult()); } + if (aObj.get()) + { + if (!aPart.get() && aObj->groupName() == ModelAPI_ResultParameter::group()) + { + QObjectPtrList aObjects = aWorkshop->objectBrowser()->selectedObjects(); + FeaturePtr aFeature; + ResultParameterPtr aParam; + foreach(ObjectPtr aObj, aObjects) { + aParam = std::dynamic_pointer_cast(aObj); + if (aParam.get()) + break; + } + if (aParam.get()) + aFeature = ModelAPI_Feature::feature(aParam); + + if (aFeature.get()) + editFeature(aFeature); + } + } } if (aPart.get()) { // if this is a part if (aPart->partDoc() == aMgr->activeDocument()) { diff --git a/src/PythonAPI/model/parameter/__init__.py b/src/PythonAPI/model/parameter/__init__.py index f0c7b22e8..0f0f64a18 100644 --- a/src/PythonAPI/model/parameter/__init__.py +++ b/src/PythonAPI/model/parameter/__init__.py @@ -19,4 +19,6 @@ """Package for Parameter plugin for the Parametric Geometry API of the Modeler. """ -from ParametersAPI import addParameter, removeParameter \ No newline at end of file +from ParametersAPI import addParameter, removeParameter + +from .import_parameter import * diff --git a/src/PythonAPI/model/parameter/import_parameter.py b/src/PythonAPI/model/parameter/import_parameter.py new file mode 100644 index 000000000..3b2a25c06 --- /dev/null +++ b/src/PythonAPI/model/parameter/import_parameter.py @@ -0,0 +1,64 @@ +# Copyright (C) 2014-2021 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +from salome.shaper import model +import codecs, sys + +def changeTab(theLine): + aResult = theLine.split("#")[0].replace("\t"," ") + aResult += theLine[len(aResult):] + return aResult + +def importParameters(theDocument, theFileName): + + aResult = [] + try: + aFile = codecs.open(theFileName, 'r', encoding = 'utf_8_sig') + except IOError: + return aResult + + for aLine in aFile: + aLine = aLine.rstrip("\n") + aLine = changeTab(aLine) + + aName = "" + aParameter = "" + aComment = "" + + aFirstText = aLine.split(" ")[0] + + aName = aFirstText.split("#")[0].strip() + + aLine = aLine.lstrip(aName) + + aParameter = aLine.split("#")[0] + + aLine = aLine.lstrip(aParameter) + aLine = aLine.lstrip("#") + + aComment = aLine + + if(len(aName) > 0): + try: + aResult.append(model.addParameter(theDocument, aName, aParameter.strip(), aComment.strip())) + except SyntaxError as anError: + print(anError, file = sys.stderr) + + aFile.close() + return aResult