From b1bf2510e71fcc2b61105a82798d09e43590a8a7 Mon Sep 17 00:00:00 2001 From: dish Date: Wed, 11 Sep 2024 05:22:57 +0000 Subject: [PATCH] [bos #41407][CEA](2024-T1) Group feature in error if a group exists with the same name as a result. Perform the same name checks on renaming from TUI as they are during renaming from GUI. ModelAPI_Object refactoring. Add a macro, configuring whether or not perform name checks on renaming from TUI. Add a macro, configuring whether or not perform a check if another ModelAPI_Result with the same name exists in a document on renaming both from TUI and GUI. --- src/Model/Model_Data.cpp | 67 +++++++++------- src/Model/Model_Data.h | 5 +- src/Model/Model_Document.h | 2 +- src/ModelAPI/CMakeLists.txt | 11 +-- src/ModelAPI/ModelAPI_Data.cpp | 9 +++ src/ModelAPI/ModelAPI_Data.h | 23 +++++- src/ModelAPI/ModelAPI_Document.h | 2 + src/ModelAPI/ModelAPI_Feature.h | 2 +- src/ModelAPI/ModelAPI_Folder.h | 2 +- src/ModelAPI/ModelAPI_Object.cpp | 37 ++++++++- src/ModelAPI/ModelAPI_Object.h | 31 ++++++-- src/ModelAPI/ModelAPI_Result.cpp | 27 +++++++ src/ModelAPI/ModelAPI_Result.h | 6 +- src/ModelAPI/ModelAPI_ResultBody.cpp | 2 +- src/ModelAPI/ModelAPI_ResultBody.h | 2 +- src/ModelAPI/ModelAPI_ResultConstruction.cpp | 2 +- src/ModelAPI/ModelAPI_ResultConstruction.h | 2 +- src/ModelAPI/ModelAPI_ResultField.cpp | 2 +- src/ModelAPI/ModelAPI_ResultField.h | 4 +- src/ModelAPI/ModelAPI_ResultGroup.cpp | 2 +- src/ModelAPI/ModelAPI_ResultGroup.h | 2 +- src/ModelAPI/ModelAPI_ResultParameter.cpp | 39 +++++++++- src/ModelAPI/ModelAPI_ResultParameter.h | 17 ++++- src/ModelAPI/ModelAPI_ResultPart.cpp | 2 +- src/ModelAPI/ModelAPI_ResultPart.h | 2 +- src/ModelHighAPI/ModelHighAPI_Selection.cpp | 2 +- src/XGUI/XGUI_ObjectsBrowser.cpp | 17 ++--- src/XGUI/XGUI_Tools.cpp | 80 ++------------------ src/XGUI/XGUI_Tools.h | 12 +-- src/XGUI/XGUI_msg_fr.ts | 4 - 30 files changed, 247 insertions(+), 170 deletions(-) diff --git a/src/Model/Model_Data.cpp b/src/Model/Model_Data.cpp index 2ae9140db..1772647cb 100644 --- a/src/Model/Model_Data.cpp +++ b/src/Model/Model_Data.cpp @@ -67,12 +67,10 @@ #include #include +#include #include -#include -#include - // myLab contains: // TDataStd_Name - name of the object // TDataStd_IntegerArray - state of the object execution, transaction ID of update @@ -126,32 +124,50 @@ std::wstring Model_Data::name() return L""; // not defined } -std::pair>> Model_Data::setName(const std::wstring& theName) +std::pair Model_Data::setName(const std::wstring& theName, bool theCallFromTUI) { ModelDataDbg(L"Model_Data::setName(" + theName + L") ENTER"); + auto res = std::pair(true, ""); + + const auto canRenameAndMessage = myObject->canBeRenamed(theName); + + if (!canRenameAndMessage.first || !canRenameAndMessage.second.isEmpty()) { + const QString& message = canRenameAndMessage.second; + ModelDataDbg(L"Model_Data::setName(" + theName + L"): " + message.toStdWString()); +#ifndef ALLOW_INVALID_RENAMING_FROM_TUI + if (canRenameAndMessage.first) { + res.first = true; + res.second = "Error-prone renaming. " + canRenameAndMessage.second + "\n"; + + // Just print warning about error-prone renaming. + PyGILState_STATE gstate = PyGILState_Ensure(); + PySys_WriteStdout(res.second.toStdString().c_str()); + PyGILState_Release(gstate); + } + else { + res.first = false; + res.second = canRenameAndMessage.second; - { // Halt renaming, if document has another ModelAPI_Result with the same name. - const auto result = std::dynamic_pointer_cast(myObject); - if (result && result->document()) { - ResultPtr resultWithTheName = std::dynamic_pointer_cast(result->document())->findResultByName(theName); - if (resultWithTheName && resultWithTheName != result) { - ModelDataDbg(L"Model_Data::setName(" + theName + L"). Another result with the same name exists."); - - const std::wstring message_wstr = L"Another result with the same name exists: \"" + theName + L"\""; - using convert_type = std::codecvt_utf8; - std::wstring_convert converter; + // Stop TUI-script execution. + PyGILState_STATE gstate = PyGILState_Ensure(); + PyErr_SetString(PyExc_RuntimeError, message.toStdString().c_str()); + PyGILState_Release(gstate); - const std::string message_str = converter.to_bytes(message_wstr); + ModelDataDbg(L"Model_Data::setName(" + theName + L") LEAVE"); + return res; + } +#else // ifdef ALLOW_INVALID_RENAMING_FROM_TUI + res.first = theCallFromTUI ? true : canRenameAndMessage.first; + res.second = "Error-prone or invalid renaming. " + canRenameAndMessage.second + "\n"; - // Stop TUI-script execution. - PyGILState_STATE gstate = PyGILState_Ensure(); - PyErr_SetString(PyExc_RuntimeError, message_str.c_str()); - PyGILState_Release(gstate); + // Just print warning about invalid renaming. + PyGILState_STATE gstate = PyGILState_Ensure(); + PySys_WriteStdout(res.second.toStdString().c_str()); + PyGILState_Release(gstate); - const auto msgAndArgs = std::pair>("Another result with the name \"%1\" exists.", {theName}); - return std::pair>>(false, msgAndArgs); - } - } + if (!res.first) + return res; +#endif // ALLOW_INVALID_RENAMING_FROM_TUI } bool isModified = false; @@ -183,15 +199,14 @@ std::pair>> Model_Data::set if (mySendAttributeUpdated && isModified) ModelAPI_ObjectRenamedMessage::send(myObject, anOldName, theName, this); if (isModified && myObject && myObject->document()) { - std::dynamic_pointer_cast(myObject->document())-> - changeNamingName(anOldName, theName, shapeLab()); + std::dynamic_pointer_cast(myObject->document())->changeNamingName(anOldName, theName, shapeLab()); } #ifdef DEBUG_NAMES myObject->myName = theName; #endif ModelDataDbg(L"Model_Data::setName(" + theName + L") LEAVE"); - return std::pair>>(true, std::pair>("", {})); + return res; } bool Model_Data::hasUserDefinedName() const diff --git a/src/Model/Model_Data.h b/src/Model/Model_Data.h index b1bf2e759..4a07e20d2 100644 --- a/src/Model/Model_Data.h +++ b/src/Model/Model_Data.h @@ -106,8 +106,9 @@ class Model_Data : public ModelAPI_Data Model_Data(); /// Returns the name of the feature visible by the user in the object browser MODEL_EXPORT virtual std::wstring name(); - /// Defines the name of the feature visible by the user in the object browser - MODEL_EXPORT virtual std::pair>> setName(const std::wstring& theName); + /// Defines the name of the feature visible by the user in the object browser. + /// Returns {false, _ } on failure. Returns { _ , message} anyway. Success with non-empty message means error-prone renaming. + MODEL_EXPORT virtual std::pair setName(const std::wstring& theName, bool theCallFromTUI = false); /// Return \c true if the object has been renamed by the user MODEL_EXPORT virtual bool hasUserDefinedName() const; /// Returns version of the feature (empty string if not applicable) diff --git a/src/Model/Model_Document.h b/src/Model/Model_Document.h index 8cd274d28..1b80d9826 100644 --- a/src/Model/Model_Document.h +++ b/src/Model/Model_Document.h @@ -290,7 +290,7 @@ class Model_Document : public ModelAPI_Document std::wstring& theSubShapeName, bool& theUniqueContext); - ResultPtr findResultByName(const std::wstring& theName) const; + virtual ResultPtr findResultByName(const std::wstring& theName) const; ///! Returns all features of the document including the hidden features which are not in ///! history. Not very fast method, for calling once, not in big cycles. diff --git a/src/ModelAPI/CMakeLists.txt b/src/ModelAPI/CMakeLists.txt index ff750f796..851e85e50 100644 --- a/src/ModelAPI/CMakeLists.txt +++ b/src/ModelAPI/CMakeLists.txt @@ -19,7 +19,7 @@ FIND_PACKAGE(SWIG REQUIRED) INCLUDE(${SWIG_USE_FILE}) -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR} ${QT_INCLUDES}) INCLUDE(UnitTest) SET(PROJECT_HEADERS @@ -122,9 +122,10 @@ SET(PROJECT_LIBRARIES Locale ${PyInterp} ${PYTHON_LIBRARIES} + ${QT_LIBRARIES} ) SET(CMAKE_SWIG_FLAGS -threads -w325,321,362,383,302,403,451,473) -ADD_DEFINITIONS(-DMODELAPI_EXPORTS) +ADD_DEFINITIONS(-DMODELAPI_EXPORTS ${QT_DEFINITIONS}) ADD_LIBRARY(ModelAPI SHARED ${PROJECT_SOURCES} ${PROJECT_HEADERS}) SET_TARGET_PROPERTIES(ModelAPI PROPERTIES LINKER_LANGUAGE CXX) @@ -178,16 +179,16 @@ ADD_UNIT_TESTS(${TEST_NAMES}) if(${HAVE_SALOME}) enable_testing() set(TEST_INSTALL_DIRECTORY "${SALOME_SHAPER_INSTALL_TESTS}/ModelAPI") - + install(FILES CTestTestfileInstall.cmake DESTINATION ${TEST_INSTALL_DIRECTORY} RENAME CTestTestfile.cmake) install(FILES tests.set DESTINATION ${TEST_INSTALL_DIRECTORY}) - + set(TMP_TESTS_NAMES) foreach(tfile ${TEST_NAMES}) list(APPEND TMP_TESTS_NAMES "Test/${tfile}") endforeach(tfile ${TEST_NAMES}) - + install(FILES ${TMP_TESTS_NAMES} DESTINATION ${TEST_INSTALL_DIRECTORY}) endif(${HAVE_SALOME}) diff --git a/src/ModelAPI/ModelAPI_Data.cpp b/src/ModelAPI/ModelAPI_Data.cpp index 62e15ab98..e8a934fc7 100644 --- a/src/ModelAPI/ModelAPI_Data.cpp +++ b/src/ModelAPI/ModelAPI_Data.cpp @@ -23,6 +23,15 @@ const std::wstring MODEL_DATA_DBG_LOG_PREFIX = L"MODEL_DATA_DBG: "; +bool ModelDataDbg(const QString& theString) +{ + if (ModelDataDbg()) { + std::wcout << MODEL_DATA_DBG_LOG_PREFIX << theString.toStdWString() << std::endl; + return true; + } + return false; +} + bool ModelDataDbg(const std::wstring& theString) { if (ModelDataDbg()) { diff --git a/src/ModelAPI/ModelAPI_Data.h b/src/ModelAPI/ModelAPI_Data.h index 738b03cc1..150037340 100644 --- a/src/ModelAPI/ModelAPI_Data.h +++ b/src/ModelAPI/ModelAPI_Data.h @@ -30,9 +30,24 @@ #include #include #include +#include -#define MODEL_DATA_DBG +/** \brief Name validity check was and is performed, if ModelAPI_Object renaming was/is initiated from GUI. + * But the check had not been performed, if "Object.setName(theName)" was called from python script (until the release TODO). + * Also, It was/is possible to merge results of SHAPER script execution into SALOME document. + * It means, there are user-made SALOME documents and SHAPER scripts in existence with invalid object names. + * + * If the macro is defined, invalid renaming is still allowed from TUI, only warning message is shown. + * Otherwise, python exception is thrown, if invalid renaming occurs.*/ +#define ALLOW_INVALID_RENAMING_FROM_TUI + +/** \brief If the macro is defined, names of instances of ModelAPI_Result (and subclasses) must be unique within a document. + * Otherwise only names of instances of classes, returning the same groupName(), must be unique within a document. */ +// #define REQUIRE_UNIQUE_RESULT_NAMES + + +// #define MODEL_DATA_DBG extern inline bool ModelDataDbg() { #ifdef MODEL_DATA_DBG return true; @@ -41,8 +56,8 @@ extern inline bool ModelDataDbg() { #endif } +extern bool ModelDataDbg(const QString& theString); extern bool ModelDataDbg(const std::wstring& theString); - extern bool ModelDataDbg(const char* theString); class ModelAPI_Attribute; @@ -90,8 +105,8 @@ class MODELAPI_EXPORT ModelAPI_Data /// Returns the name of the feature visible by the user in the object browser virtual std::wstring name() = 0; /// Defines the name of the feature visible by the user in the object browser. - /// Returns {false, errorMessage} on failure. The error message is composed of the message template and arguments. - virtual std::pair>> setName(const std::wstring& theName) = 0; + /// Returns {false, _ } on failure. Returns { _ , message} anyway. Success with non-empty message means error-prone renaming. + virtual std::pair setName(const std::wstring& theName, bool theCallFromTUI = false) = 0; /// Return \c true if the object has been renamed by the user virtual bool hasUserDefinedName() const = 0; diff --git a/src/ModelAPI/ModelAPI_Document.h b/src/ModelAPI/ModelAPI_Document.h index acec2b808..b9d896348 100644 --- a/src/ModelAPI/ModelAPI_Document.h +++ b/src/ModelAPI/ModelAPI_Document.h @@ -223,6 +223,8 @@ public: const std::list >& theFeatures, const bool theBefore = true) = 0; + virtual std::shared_ptr findResultByName(const std::wstring& theName) const = 0; + //! Informs the document that it becomes active and some actions must be performed virtual void setActive(const bool theFlag) = 0; //! Returns true if this document is currently active diff --git a/src/ModelAPI/ModelAPI_Feature.h b/src/ModelAPI/ModelAPI_Feature.h index 118cc1512..fcf6a8812 100644 --- a/src/ModelAPI/ModelAPI_Feature.h +++ b/src/ModelAPI/ModelAPI_Feature.h @@ -64,7 +64,7 @@ class ModelAPI_Feature : public ModelAPI_Object } /// Returns the group identifier of this result - virtual std::string groupName() + virtual std::string groupName() const { return group(); } diff --git a/src/ModelAPI/ModelAPI_Folder.h b/src/ModelAPI/ModelAPI_Folder.h index 0ba03acdb..2490d0ee8 100644 --- a/src/ModelAPI/ModelAPI_Folder.h +++ b/src/ModelAPI/ModelAPI_Folder.h @@ -49,7 +49,7 @@ public: } /// Returns the group identifier of this result - virtual std::string groupName() + virtual std::string groupName() const { return group(); } diff --git a/src/ModelAPI/ModelAPI_Object.cpp b/src/ModelAPI/ModelAPI_Object.cpp index 391d35ae6..5f964ca36 100644 --- a/src/ModelAPI/ModelAPI_Object.cpp +++ b/src/ModelAPI/ModelAPI_Object.cpp @@ -21,7 +21,8 @@ #include "ModelAPI_Document.h" #include "ModelAPI_Data.h" #include "ModelAPI_Events.h" -#include +#include +#include bool ModelAPI_Object::isInHistory() { @@ -57,16 +58,44 @@ std::shared_ptr ModelAPI_Object::document() const return myDoc; } -void ModelAPI_Object::attributeChanged(const std::string& /*theID*/) +std::pair ModelAPI_Object::canBeRenamed(const std::wstring& theNewName) const { + static const char* const INVALID_NAME_MSG = "Name \"%1\" is invalid."; + if (!isNameValid(theNewName)) + return std::pair(false, QString(INVALID_NAME_MSG).arg(QString::fromStdWString(theNewName))); + + return canBeRenamedProtected(theNewName); +} + +std::pair ModelAPI_Object::canBeRenamedProtected(const std::wstring& theNewName) const +{ + static const char* const NAME_ALREADY_ASSIGNED_MSG = "Name \"%1\" is already assigned to another instance of \"%2\"."; + + const std::string typeName = groupName(); + const ObjectPtr aObj = document()->objectByName(typeName, theNewName); + if (aObj && this != aObj.get()) + return std::pair(false, QString(NAME_ALREADY_ASSIGNED_MSG).arg(QString::fromStdWString(theNewName)).arg(QString::fromStdString(typeName))); + + return std::pair(true, ""); } -ModelAPI_Object::ModelAPI_Object() +/*static*/ bool ModelAPI_Object::IS_NAME_VALID(const std::wstring& theName) { + const QString name = QString::fromStdWString(theName); + QChar aChar; + for (int i = 0; i < name.length(); i++) { + aChar = name[i]; + if (!aChar.isLetterOrNumber()) { + if ((aChar != "_") && (!aChar.isSpace())) + return false; + } + } + return true; } -ModelAPI_Object::~ModelAPI_Object() +bool ModelAPI_Object::isNameValid(const std::wstring& theName) const { + return ModelAPI_Object::IS_NAME_VALID(theName); } void ModelAPI_Object::setData(std::shared_ptr theData) diff --git a/src/ModelAPI/ModelAPI_Object.h b/src/ModelAPI/ModelAPI_Object.h index 0dd99e384..593ff8ec4 100644 --- a/src/ModelAPI/ModelAPI_Object.h +++ b/src/ModelAPI/ModelAPI_Object.h @@ -25,6 +25,9 @@ #include "ModelAPI_Entity.h" #include +#include +#include +#include class ModelAPI_Data; class ModelAPI_Document; @@ -38,16 +41,17 @@ class ModelAPI_Document; * * It may be feature or result of the feature. User just may set name for it * or change this name later. Generic class for Feature, Body, Parameter and other - * objects related to the features and their results. Contains attributes of this + * objects related to the features and their results. Contains attributes of this * object in the "Data". */ class ModelAPI_Object: public ModelAPI_Entity { std::shared_ptr myData; ///< manager of the data model of a feature std::shared_ptr myDoc; ///< document this object belongs to - public: + +public: #ifdef DEBUG_NAMES - std::wstring myName; // name of this object + std::wstring myName; // name of this object // TODO Make names of type QString. #endif /// By default object is displayed in the object browser. MODELAPI_EXPORT virtual bool isInHistory(); @@ -68,7 +72,7 @@ class ModelAPI_Object: public ModelAPI_Entity MODELAPI_EXPORT virtual std::shared_ptr document() const; /// Returns the group identifier of this object - virtual std::string groupName() = 0; + virtual std::string groupName() const = 0; /// Request for initialization of data model of the object: adding all attributes virtual void initAttributes() = 0; @@ -81,15 +85,27 @@ class ModelAPI_Object: public ModelAPI_Entity std::string& /*theName*/, std::string& /*theDefault*/) {} + /// Returns { canBeRenamed, message }. canBeRenamed == true with non-empty message means error-prone renaming. + std::pair canBeRenamed(const std::wstring& theNewName) const; + +protected: + /// Returns { canBeRenamed, message }. canBeRenamed == true with non-empty message means error-prone renaming. + /// Does not check name validity. + virtual std::pair canBeRenamedProtected(const std::wstring& theNewName) const; + +public: + static bool IS_NAME_VALID(const std::wstring& theName); + virtual bool isNameValid(const std::wstring& theName) const; + /// Called on change of any argument-attribute of this object /// \param theID identifier of changed attribute - MODELAPI_EXPORT virtual void attributeChanged(const std::string& theID); + MODELAPI_EXPORT virtual void attributeChanged(const std::string& theID) { (void)theID; }; /// Initializes the default states of the object - MODELAPI_EXPORT ModelAPI_Object(); + MODELAPI_EXPORT ModelAPI_Object() = default; /// To use virtuality for destructors - MODELAPI_EXPORT virtual ~ModelAPI_Object(); + MODELAPI_EXPORT virtual ~ModelAPI_Object() = default; /// Returns true if object must be displayed in the viewer: flag is stored in the /// data model, so on undo/redo, open/save or recreation of object by history-playing it keeps @@ -122,7 +138,6 @@ class ModelAPI_Object: public ModelAPI_Entity friend class Model_Objects; friend class ModelAPI_Feature; friend class Model_Document; - }; typedef std::shared_ptr ObjectPtr; diff --git a/src/ModelAPI/ModelAPI_Result.cpp b/src/ModelAPI/ModelAPI_Result.cpp index 2c3bdc9f9..63852a785 100644 --- a/src/ModelAPI/ModelAPI_Result.cpp +++ b/src/ModelAPI/ModelAPI_Result.cpp @@ -34,6 +34,7 @@ #include #include +#include ModelAPI_Result::~ModelAPI_Result() { @@ -199,3 +200,29 @@ void ModelAPI_Result::init() myIsDisabled = true; // by default it is not initialized and false to be after created myIsConcealed = false; } + +std::pair ModelAPI_Result::canBeRenamedProtected(const std::wstring& theNewName) const +{ + auto res = ModelAPI_Object::canBeRenamedProtected(theNewName); + if (!res.first) + return res; + + { + const auto doc = document(); + if (doc) { + ResultPtr resultWithTheName = doc->findResultByName(theNewName); + if (resultWithTheName && resultWithTheName.get() != this) { + ModelDataDbg(L"ModelAPI_Result::canBeRenamedProtected(" + theNewName + L"). Another result with the same name exists."); +#ifdef REQUIRE_UNIQUE_RESULT_NAMES + res.first = false; +#else + res.first = true; +#endif //REQUIRE_UNIQUE_RESULT_NAMES + res.second = "Another result with the name \"" + QString::fromStdWString(theNewName) + "\" exists."; + return res; + } + } + } + + return res; +} diff --git a/src/ModelAPI/ModelAPI_Result.h b/src/ModelAPI/ModelAPI_Result.h index e82ea2f35..2b84dc8c9 100644 --- a/src/ModelAPI/ModelAPI_Result.h +++ b/src/ModelAPI/ModelAPI_Result.h @@ -122,7 +122,7 @@ class ModelAPI_Result : public ModelAPI_Object MODELAPI_EXPORT virtual ~ModelAPI_Result(); /// Returns the shape-result produced by this feature (or null if no shapes) - MODELAPI_EXPORT virtual std::shared_ptr shape(); + MODELAPI_EXPORT virtual std::shared_ptr shape(); /// Returns all the vertices of this result MODELAPI_EXPORT virtual ListOfShape @@ -161,6 +161,10 @@ protected: /// all fields, normally initialized in the constructor MODELAPI_EXPORT virtual void init(); + /// Returns { canBeRenamed, message }. canBeRenamed == true with non-empty message means error-prone renaming. + /// Does not check name validity. + virtual std::pair canBeRenamedProtected(const std::wstring& theNewName) const; + friend class Model_Objects; }; diff --git a/src/ModelAPI/ModelAPI_ResultBody.cpp b/src/ModelAPI/ModelAPI_ResultBody.cpp index f041caacb..837e9e36a 100644 --- a/src/ModelAPI/ModelAPI_ResultBody.cpp +++ b/src/ModelAPI/ModelAPI_ResultBody.cpp @@ -33,7 +33,7 @@ ModelAPI_ResultBody::~ModelAPI_ResultBody() { } -std::string ModelAPI_ResultBody::groupName() +std::string ModelAPI_ResultBody::groupName() const { return group(); } diff --git a/src/ModelAPI/ModelAPI_ResultBody.h b/src/ModelAPI/ModelAPI_ResultBody.h index 223c91d55..1cee960ba 100644 --- a/src/ModelAPI/ModelAPI_ResultBody.h +++ b/src/ModelAPI/ModelAPI_ResultBody.h @@ -66,7 +66,7 @@ public: } /// Returns the group identifier of this result - MODELAPI_EXPORT virtual std::string groupName(); + MODELAPI_EXPORT virtual std::string groupName() const; /// Returns the group identifier of this result inline static std::string group() diff --git a/src/ModelAPI/ModelAPI_ResultConstruction.cpp b/src/ModelAPI/ModelAPI_ResultConstruction.cpp index 5f672a144..562879985 100644 --- a/src/ModelAPI/ModelAPI_ResultConstruction.cpp +++ b/src/ModelAPI/ModelAPI_ResultConstruction.cpp @@ -20,7 +20,7 @@ #include "ModelAPI_ResultConstruction.h" #include -std::string ModelAPI_ResultConstruction::groupName() +std::string ModelAPI_ResultConstruction::groupName() const { return group(); } diff --git a/src/ModelAPI/ModelAPI_ResultConstruction.h b/src/ModelAPI/ModelAPI_ResultConstruction.h index c16dce305..e577f21fb 100644 --- a/src/ModelAPI/ModelAPI_ResultConstruction.h +++ b/src/ModelAPI/ModelAPI_ResultConstruction.h @@ -37,7 +37,7 @@ class ModelAPI_ResultConstruction : public ModelAPI_Result { public: /// Returns the group identifier of this result - MODELAPI_EXPORT virtual std::string groupName(); + MODELAPI_EXPORT virtual std::string groupName() const; /// Returns the group identifier of this result inline static std::string group() diff --git a/src/ModelAPI/ModelAPI_ResultField.cpp b/src/ModelAPI/ModelAPI_ResultField.cpp index 81625d7fa..780e0b6d1 100644 --- a/src/ModelAPI/ModelAPI_ResultField.cpp +++ b/src/ModelAPI/ModelAPI_ResultField.cpp @@ -26,7 +26,7 @@ ModelAPI_ResultField::~ModelAPI_ResultField() } -std::string ModelAPI_ResultField::groupName() +std::string ModelAPI_ResultField::groupName() const { return group(); } diff --git a/src/ModelAPI/ModelAPI_ResultField.h b/src/ModelAPI/ModelAPI_ResultField.h index 196d54213..830d2029f 100644 --- a/src/ModelAPI/ModelAPI_ResultField.h +++ b/src/ModelAPI/ModelAPI_ResultField.h @@ -50,7 +50,7 @@ public: } /// Returns the group identifier of this object - virtual std::string groupName() { return group(); } + virtual std::string groupName() const { return group(); } /// Request for initialization of data model of the object: adding all attributes virtual void initAttributes() {} @@ -81,7 +81,7 @@ public: MODELAPI_EXPORT virtual ~ModelAPI_ResultField(); /// Returns the group identifier of this result - MODELAPI_EXPORT virtual std::string groupName(); + MODELAPI_EXPORT virtual std::string groupName() const; /// Returns the group identifier of this result inline static std::string group() diff --git a/src/ModelAPI/ModelAPI_ResultGroup.cpp b/src/ModelAPI/ModelAPI_ResultGroup.cpp index c77933b0c..0d6971e0a 100644 --- a/src/ModelAPI/ModelAPI_ResultGroup.cpp +++ b/src/ModelAPI/ModelAPI_ResultGroup.cpp @@ -24,7 +24,7 @@ ModelAPI_ResultGroup::~ModelAPI_ResultGroup() } -std::string ModelAPI_ResultGroup::groupName() +std::string ModelAPI_ResultGroup::groupName() const { return group(); } diff --git a/src/ModelAPI/ModelAPI_ResultGroup.h b/src/ModelAPI/ModelAPI_ResultGroup.h index 60317b95f..0a6582652 100644 --- a/src/ModelAPI/ModelAPI_ResultGroup.h +++ b/src/ModelAPI/ModelAPI_ResultGroup.h @@ -36,7 +36,7 @@ class ModelAPI_ResultGroup : public ModelAPI_Result public: MODELAPI_EXPORT virtual ~ModelAPI_ResultGroup(); /// Returns the group identifier of this result - MODELAPI_EXPORT virtual std::string groupName(); + MODELAPI_EXPORT virtual std::string groupName() const; /// Returns the group identifier of this result inline static std::string group() diff --git a/src/ModelAPI/ModelAPI_ResultParameter.cpp b/src/ModelAPI/ModelAPI_ResultParameter.cpp index a5f1d510a..73ddd4766 100644 --- a/src/ModelAPI/ModelAPI_ResultParameter.cpp +++ b/src/ModelAPI/ModelAPI_ResultParameter.cpp @@ -18,7 +18,44 @@ // #include "ModelAPI_ResultParameter.h" +#include "ModelAPI_Tools.h" -ModelAPI_ResultParameter::~ModelAPI_ResultParameter() +std::pair ModelAPI_ResultParameter::canBeRenamedProtected(const std::wstring& theNewName) const { + static const char* const NAME_ALREADY_ASSIGNED_MSG = "The parameter can not be renamed to: \"%1\". " + "There is a parameter with the same name. Its value is: %2."; + + double value; + ResultParameterPtr param; + if (ModelAPI_Tools::findVariable(document(), FeaturePtr(), theNewName, value, param)) + return std::pair(false, QString(NAME_ALREADY_ASSIGNED_MSG).arg(QString::fromStdWString(theNewName)).arg(value)); + + return std::pair(true, ""); } + +/*static*/ bool ModelAPI_ResultParameter::IS_NAME_VALID(const std::wstring& theName) +{ + const QString name = QString::fromStdWString(theName); + char aCh; + for (int i = 0; i < name.length(); i++) { + aCh = name[i].toLatin1(); + if (aCh == 0) + return false; + if ((aCh >= 0x30) && (aCh <= 0x39)) + continue; + else if ((aCh >= 0x41) && (aCh <= 0x5A)) + continue; + else if ((aCh >= 0x61) && (aCh <= 0x7A)) + continue; + else if (aCh == 0x5f) + continue; + else + return false; + } + return true; +} + +bool ModelAPI_ResultParameter::isNameValid(const std::wstring& theName) const +{ + return ModelAPI_ResultParameter::IS_NAME_VALID(theName); +} \ No newline at end of file diff --git a/src/ModelAPI/ModelAPI_ResultParameter.h b/src/ModelAPI/ModelAPI_ResultParameter.h index 0a932f7f1..c9bf7eb88 100644 --- a/src/ModelAPI/ModelAPI_ResultParameter.h +++ b/src/ModelAPI/ModelAPI_ResultParameter.h @@ -22,6 +22,7 @@ #include #include +#include /**\class ModelAPI_ResultParameter * \ingroup DataModel @@ -32,9 +33,9 @@ */ class ModelAPI_ResultParameter : public ModelAPI_Result { - public: +public: /// Returns the group identifier of this result - virtual std::string groupName() + virtual std::string groupName() const { return group(); } @@ -62,9 +63,17 @@ class ModelAPI_ResultParameter : public ModelAPI_Result /// The generic initialization of attributes virtual void initAttributes() = 0; - /// Destructor - MODELAPI_EXPORT ~ModelAPI_ResultParameter(); +protected: + /// Returns { canBeRenamed, message }. canBeRenamed == true with non-empty message means error-prone renaming. + virtual std::pair canBeRenamedProtected(const std::wstring& theNewName) const; +public: + static bool IS_NAME_VALID(const std::wstring& theName); + + /// Parameter name must be composed of ASCII-characters only. + virtual bool isNameValid(const std::wstring& theName) const; + + MODELAPI_EXPORT ~ModelAPI_ResultParameter() = default; }; //! Pointer on feature object diff --git a/src/ModelAPI/ModelAPI_ResultPart.cpp b/src/ModelAPI/ModelAPI_ResultPart.cpp index 1cfac0833..d68b7dbee 100644 --- a/src/ModelAPI/ModelAPI_ResultPart.cpp +++ b/src/ModelAPI/ModelAPI_ResultPart.cpp @@ -21,7 +21,7 @@ #include -std::string ModelAPI_ResultPart::groupName() +std::string ModelAPI_ResultPart::groupName() const { return ModelAPI_ResultPart::group(); } diff --git a/src/ModelAPI/ModelAPI_ResultPart.h b/src/ModelAPI/ModelAPI_ResultPart.h index 148315a5f..f37e51879 100644 --- a/src/ModelAPI/ModelAPI_ResultPart.h +++ b/src/ModelAPI/ModelAPI_ResultPart.h @@ -36,7 +36,7 @@ class ModelAPI_ResultPart : public ModelAPI_Result { public: /// Returns the group identifier of this result - MODELAPI_EXPORT virtual std::string groupName(); + MODELAPI_EXPORT virtual std::string groupName() const; /// Returns the group identifier of this result inline static std::string group() diff --git a/src/ModelHighAPI/ModelHighAPI_Selection.cpp b/src/ModelHighAPI/ModelHighAPI_Selection.cpp index 160925e8b..76e17f564 100644 --- a/src/ModelHighAPI/ModelHighAPI_Selection.cpp +++ b/src/ModelHighAPI/ModelHighAPI_Selection.cpp @@ -195,7 +195,7 @@ void ModelHighAPI_Selection::setName(const std::wstring& theName) if(!aResult.get()) { return; } - aResult->data()->setName(theName); + aResult->data()->setName(theName, true /*theCallFromTUI*/); } } diff --git a/src/XGUI/XGUI_ObjectsBrowser.cpp b/src/XGUI/XGUI_ObjectsBrowser.cpp index 4fd9b86b2..8fac22108 100644 --- a/src/XGUI/XGUI_ObjectsBrowser.cpp +++ b/src/XGUI/XGUI_ObjectsBrowser.cpp @@ -50,6 +50,8 @@ #include #include +#include + #ifdef DEBUG_INDXES #include #endif @@ -132,8 +134,8 @@ void XGUI_DataTree::commitData(QWidget* theEditor) { static int aEntrance = 0; if (aEntrance == 0) { - // We have to check number of enter and exit of this function because it can be called - // recursively by Qt in order to avoid double modifying of a data + // Amount of enters and exits to the block must be counted to avoid repeated modification of a data, + // because it can be executed recursively. aEntrance = 1; QLineEdit* aEditor = dynamic_cast(theEditor); if (aEditor) { @@ -145,17 +147,8 @@ void XGUI_DataTree::commitData(QWidget* theEditor) if (XGUI_Tools::canRename(aObj, aName)) { SessionPtr aMgr = ModelAPI_Session::get(); aMgr->startOperation("Rename"); - const auto renameRes = aObj->data()->setName(aName.toStdWString()); + aObj->data()->setName(aName.toStdWString()); aMgr->finishOperation(); - - if (!renameRes.first) { - const auto& msgAndArgs = renameRes.second; - QString msg = tr(msgAndArgs.first); - for (const std::wstring& arg : msgAndArgs.second) { - msg = msg.arg(QString::fromStdWString(arg)); - } - Events_InfoMessage("XGUI_Tools", msg.toStdString()).send(); - } } } } diff --git a/src/XGUI/XGUI_Tools.cpp b/src/XGUI/XGUI_Tools.cpp index 0b1d37a64..4f6674065 100644 --- a/src/XGUI/XGUI_Tools.cpp +++ b/src/XGUI/XGUI_Tools.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #ifndef WIN32 # include @@ -160,83 +161,16 @@ bool canRemoveOrRename(QWidget* theParent, const std::set& theFeatur return aResult; } -//****************************************************************** -bool isAscii(const QString& theStr) -{ - char aCh; - for (int i = 0; i < theStr.size(); i++) { - aCh = theStr[i].toLatin1(); - if (aCh == 0) - return false; - if ((aCh >= 0x30) && (aCh <= 0x39)) - continue; - else if ((aCh >= 0x41) && (aCh <= 0x5A)) - continue; - else if ((aCh >= 0x61) && (aCh <= 0x7A)) - continue; - else if (aCh == 0x5f) - continue; - else - return false; - } - return true; -} - -//****************************************************************** -bool isValidName(const QString& theName) -{ - QChar aChar; - for (int i = 0; i < theName.size(); i++) { - aChar = theName[i]; - if (!aChar.isLetterOrNumber()) { - if ((aChar != "_") && (!aChar.isSpace())) - return false; - } - } - return true; -} - //****************************************************************** bool canRename(const ObjectPtr& theObject, const QString& theName) { - std::string aType = theObject->groupName(); - if (aType == ModelAPI_ResultParameter::group()) { - // For parameters names only ASCII symbols have to be used - if (!isAscii(theName)) - return false; - - double aValue; - ResultParameterPtr aParam; - if (ModelAPI_Tools::findVariable(theObject->document(), - FeaturePtr(), theName.toStdWString(), aValue, aParam)) { - const char* aKeyStr = "Selected parameter can not be renamed to: %1. " - "There is a parameter with the same name. Its value is: %2."; - QString aErrMsg(QObject::tr(aKeyStr).arg(theName).arg(aValue)); - // We can not use here a dialog box for message - - // it will crash editing process in ObjectBrowser - Events_InfoMessage("XGUI_Tools", aErrMsg.toStdString()).send(); - return false; - } - } - else { - if (!isValidName(theName)) - return false; - - DocumentPtr aDoc = theObject->document(); - ObjectPtr aObj = - aDoc->objectByName(aType, theName.toStdWString()); - - if (aObj.get() && theObject != aObj) { - QString aErrMsg(QObject::tr("Name %2 already exists in %1."). - arg(aType.c_str()).arg(theName)); - // We can not use here a dialog box for message - - // it will crash editing process in ObjectBrowser - Events_InfoMessage("XGUI_Tools", aErrMsg.toStdString()).send(); - return false; - } - } + ModelDataDbg("XGUI_Tools::canRename(const ObjectPtr& theObject, \"" + theName + "\")"); + + const auto canRenameAndMessage = theObject->canBeRenamed(theName.toStdWString()); + if (!canRenameAndMessage.second.isEmpty()) + Events_InfoMessage("XGUI_Tools", canRenameAndMessage.second.toStdString()).send(); - return true; + return canRenameAndMessage.first; } //************************************************************** diff --git a/src/XGUI/XGUI_Tools.h b/src/XGUI/XGUI_Tools.h index 7f4073e93..5231442ce 100644 --- a/src/XGUI/XGUI_Tools.h +++ b/src/XGUI/XGUI_Tools.h @@ -102,19 +102,9 @@ std::string XGUI_EXPORT featureInfo(FeaturePtr theFeature); */ bool XGUI_EXPORT canRemoveOrRename(QWidget* theParent, const std::set& theFeatures); -/*! - Check possibility to rename object - \param theObject an object to rename - \param theName a name - */ +/*! \brief Call theObject->canBeRenamed(theName) and sends event-message with description why renaming failed or why it is error-prone. */ bool canRename(const ObjectPtr& theObject, const QString& theName); -/*! - Checks that the given string contains only ASCII symbols - \param theStr a string to check - */ -bool isAscii(const QString& theStr); - /*! Returns converted workshop \param theWorkshop an interface workshop diff --git a/src/XGUI/XGUI_msg_fr.ts b/src/XGUI/XGUI_msg_fr.ts index f87efd1f1..e252ac3f2 100644 --- a/src/XGUI/XGUI_msg_fr.ts +++ b/src/XGUI/XGUI_msg_fr.ts @@ -7,10 +7,6 @@ Warning Attention - - Name %2 already exists in %1. - Le nom %2 existe déjà dans %1. - Move to the end Aller à la fin -- 2.39.2