]> SALOME platform Git repositories - modules/shaper.git/commitdiff
Salome HOME
[bos #41407][CEA](2024-T1) Group feature in error if a group exists with the same... dish/CR41407--Group_feature_error 56/head
authordish <dmitrii.shvydkoi@opencascade.com>
Wed, 11 Sep 2024 05:22:57 +0000 (05:22 +0000)
committerdish <dmitrii.shvydkoi@opencascade.com>
Wed, 11 Sep 2024 05:22:57 +0000 (05:22 +0000)
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.

30 files changed:
src/Model/Model_Data.cpp
src/Model/Model_Data.h
src/Model/Model_Document.h
src/ModelAPI/CMakeLists.txt
src/ModelAPI/ModelAPI_Data.cpp
src/ModelAPI/ModelAPI_Data.h
src/ModelAPI/ModelAPI_Document.h
src/ModelAPI/ModelAPI_Feature.h
src/ModelAPI/ModelAPI_Folder.h
src/ModelAPI/ModelAPI_Object.cpp
src/ModelAPI/ModelAPI_Object.h
src/ModelAPI/ModelAPI_Result.cpp
src/ModelAPI/ModelAPI_Result.h
src/ModelAPI/ModelAPI_ResultBody.cpp
src/ModelAPI/ModelAPI_ResultBody.h
src/ModelAPI/ModelAPI_ResultConstruction.cpp
src/ModelAPI/ModelAPI_ResultConstruction.h
src/ModelAPI/ModelAPI_ResultField.cpp
src/ModelAPI/ModelAPI_ResultField.h
src/ModelAPI/ModelAPI_ResultGroup.cpp
src/ModelAPI/ModelAPI_ResultGroup.h
src/ModelAPI/ModelAPI_ResultParameter.cpp
src/ModelAPI/ModelAPI_ResultParameter.h
src/ModelAPI/ModelAPI_ResultPart.cpp
src/ModelAPI/ModelAPI_ResultPart.h
src/ModelHighAPI/ModelHighAPI_Selection.cpp
src/XGUI/XGUI_ObjectsBrowser.cpp
src/XGUI/XGUI_Tools.cpp
src/XGUI/XGUI_Tools.h
src/XGUI/XGUI_msg_fr.ts

index 2ae9140db19f4c3e53368a9a0005347b58ae2e32..1772647cbc9849a3a9fcd990c3790f0bb67a1f31 100644 (file)
 #include <TDF_ChildIDIterator.hxx>
 
 #include <string>
+#include <QString>
 
 #include <Python.h>
 
-#include <locale>
-#include <codecvt>
-
 // 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<bool, std::pair<const char*, std::list<std::wstring>>> Model_Data::setName(const std::wstring& theName)
+std::pair<bool, QString> Model_Data::setName(const std::wstring& theName, bool theCallFromTUI)
 {
   ModelDataDbg(L"Model_Data::setName(" + theName + L") ENTER");
+  auto res = std::pair<bool, QString>(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<ModelAPI_Result>(myObject);
-    if (result && result->document()) {
-      ResultPtr resultWithTheName = std::dynamic_pointer_cast<Model_Document>(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<wchar_t>;
-        std::wstring_convert<convert_type, wchar_t> 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<const char*, std::list<std::wstring>>("Another result with the name \"%1\" exists.", {theName});
-        return std::pair<bool, std::pair<const char*, std::list<std::wstring>>>(false, msgAndArgs);
-      }
-    }
+    if (!res.first)
+      return res;
+#endif // ALLOW_INVALID_RENAMING_FROM_TUI
   }
 
   bool isModified = false;
@@ -183,15 +199,14 @@ std::pair<bool, std::pair<const char*, std::list<std::wstring>>> Model_Data::set
   if (mySendAttributeUpdated && isModified)
     ModelAPI_ObjectRenamedMessage::send(myObject, anOldName, theName, this);
   if (isModified && myObject && myObject->document()) {
-    std::dynamic_pointer_cast<Model_Document>(myObject->document())->
-      changeNamingName(anOldName, theName, shapeLab());
+    std::dynamic_pointer_cast<Model_Document>(myObject->document())->changeNamingName(anOldName, theName, shapeLab());
   }
 #ifdef DEBUG_NAMES
   myObject->myName = theName;
 #endif
 
   ModelDataDbg(L"Model_Data::setName(" + theName + L") LEAVE");
-  return std::pair<bool, std::pair<const char*, std::list<std::wstring>>>(true, std::pair<const char*, std::list<std::wstring>>("", {}));
+  return res;
 }
 
 bool Model_Data::hasUserDefinedName() const
index b1bf2e759469fbfa1a5c00c704fb503c592b6c9d..4a07e20d2142d9a272b471731dbf5b1165c6bed4 100644 (file)
@@ -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<bool, std::pair<const char*, std::list<std::wstring>>> 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<bool, QString> 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)
index 8cd274d289c84bfaf553bae4e6f3ae6b33c5b103..1b80d9826e36a9beb23565cd395a88db93fc88e6 100644 (file)
@@ -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.
index ff750f796aea94c4ae0935e6db8718541d4eee4c..851e85e508fc9475dc7288077899691352a88f73 100644 (file)
@@ -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})
index 62e15ab98940cc0a1292ce53b0ad8c4deb612a86..e8a934fc72d3ab16a77aae762dfe940525a7d458 100644 (file)
 
 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()) {
index 738b03cc1e305714feff9dfe6f73b627a7a6b484..150037340533036e353f180217d4155dd38192a3 100644 (file)
 #include <set>
 #include <memory>
 #include <utility>
+#include <QString>
 
 
-#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<bool, std::pair<const char*, std::list<std::wstring>>> 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<bool, QString> 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;
 
index acec2b808c16bce4a39f42c46b9697bff251fc6e..b9d896348e736e6faa81bae223cf92b6817b4169 100644 (file)
@@ -223,6 +223,8 @@ public:
       const std::list<std::shared_ptr<ModelAPI_Feature> >& theFeatures,
       const bool theBefore = true) = 0;
 
+  virtual std::shared_ptr<ModelAPI_Result> 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
index 118cc1512b76f86c037955b86ba4c3573f49d4bf..fcf6a8812fc396610a3c727cc815437910518041 100644 (file)
@@ -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();
   }
index 0ba03acdbc365ce8a46399c7aa3109cd78324faa..2490d0ee805b9711c14af7b358420b4b9525505b 100644 (file)
@@ -49,7 +49,7 @@ public:
   }
 
   /// Returns the group identifier of this result
-  virtual std::string groupName()
+  virtual std::string groupName() const
   {
     return group();
   }
index 391d35ae6580fd8ef67a4add3fec4481548de042..5f964ca364bafa54d034c944ccf057dab49e2ee5 100644 (file)
@@ -21,7 +21,8 @@
 #include "ModelAPI_Document.h"
 #include "ModelAPI_Data.h"
 #include "ModelAPI_Events.h"
-#include <Events_Loop.h>
+#include <QString>
+#include <QChar>
 
 bool ModelAPI_Object::isInHistory()
 {
@@ -57,16 +58,44 @@ std::shared_ptr<ModelAPI_Document> ModelAPI_Object::document() const
   return myDoc;
 }
 
-void ModelAPI_Object::attributeChanged(const std::string& /*theID*/)
+std::pair<bool, QString> 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<bool, QString>(false, QString(INVALID_NAME_MSG).arg(QString::fromStdWString(theNewName)));
+
+  return canBeRenamedProtected(theNewName);
+}
+
+std::pair<bool, QString> 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<bool, QString>(false, QString(NAME_ALREADY_ASSIGNED_MSG).arg(QString::fromStdWString(theNewName)).arg(QString::fromStdString(typeName)));
+
+  return std::pair<bool, QString>(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<ModelAPI_Data> theData)
index 0dd99e3849662a40b9ea2a01d14f759b7781ebb9..593ff8ec44428e06120c6013ab03810dc461ba06 100644 (file)
@@ -25,6 +25,9 @@
 #include "ModelAPI_Entity.h"
 
 #include <memory>
+#include <utility>
+#include <string>
+#include <QList>
 
 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<ModelAPI_Data> myData;  ///< manager of the data model of a feature
   std::shared_ptr<ModelAPI_Document> 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<ModelAPI_Document> 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<bool, QString> 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<bool, QString> 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<ModelAPI_Object> ObjectPtr;
index 2c3bdc9f9acaebbc921fc95b367c14249921db77..63852a785e0d1a096b76523194bd863edde06089 100644 (file)
@@ -34,6 +34,7 @@
 
 #include <PyInterp_Interp.h>
 #include <Python.h>
+#include <QString>
 
 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<bool, QString> 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;
+}
index e82ea2f355d123eb0f36f26dd450ecac3567a876..2b84dc8c974582bc25561b40075c0da553d14222 100644 (file)
@@ -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<GeomAPI_Shape> shape(); 
+  MODELAPI_EXPORT virtual std::shared_ptr<GeomAPI_Shape> 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<bool, QString> canBeRenamedProtected(const std::wstring& theNewName) const;
+
 friend class Model_Objects;
 };
 
index f041caacbc6d557a06453b30a789b183f950773a..837e9e36a5178c74d67de3bfdb3ff2fe488ef4e8 100644 (file)
@@ -33,7 +33,7 @@ ModelAPI_ResultBody::~ModelAPI_ResultBody()
 {
 }
 
-std::string ModelAPI_ResultBody::groupName()
+std::string ModelAPI_ResultBody::groupName() const
 {
   return group();
 }
index 223c91d55ea72936d20677622fd33d4ddf6270af..1cee960ba5f8a6ab51cae9ea2ef9dfb76bd699d9 100644 (file)
@@ -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()
index 5f672a144e5883dc4b6eed6637dbcdbb1f26d0bb..5628799855a607e7c212892f21adc646b5030c79 100644 (file)
@@ -20,7 +20,7 @@
 #include "ModelAPI_ResultConstruction.h"
 #include <string>
 
-std::string ModelAPI_ResultConstruction::groupName()
+std::string ModelAPI_ResultConstruction::groupName() const
 {
   return group();
 }
index c16dce30564f3453e4229eae4cf5c8640c9e1814..e577f21fb9e8ddc0d5e034cf24475abb82172949 100644 (file)
@@ -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()
index 81625d7fa1ed70248581421e5161001327d88a35..780e0b6d13629ab76bbd4709411ed1f63b4a915d 100644 (file)
@@ -26,7 +26,7 @@ ModelAPI_ResultField::~ModelAPI_ResultField()
 
 }
 
-std::string ModelAPI_ResultField::groupName()
+std::string ModelAPI_ResultField::groupName() const
 {
   return group();
 }
index 196d54213c378e1ccf4a6e1e378cba27201499ac..830d2029f1710c4c590bd188cc6dac1a044d5c44 100644 (file)
@@ -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()
index c77933b0ca3ee13658b130b8d90375fa76604e2a..0d6971e0af8a2e5767a81cb8218d396b1cc08e7d 100644 (file)
@@ -24,7 +24,7 @@ ModelAPI_ResultGroup::~ModelAPI_ResultGroup()
 
 }
 
-std::string ModelAPI_ResultGroup::groupName()
+std::string ModelAPI_ResultGroup::groupName() const
 {
   return group();
 }
index 60317b95ffc60ae8f1ad85386e76b8cfeb8cb669..0a65826525b8f9e48acb21d7b27faa0805040f16 100644 (file)
@@ -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()
index a5f1d510a08e77853164e0bd7e7ce9186a2df71e..73ddd4766e6195a5b7a7fd326dfa1c360ae10087 100644 (file)
 //
 
 #include "ModelAPI_ResultParameter.h"
+#include "ModelAPI_Tools.h"
 
-ModelAPI_ResultParameter::~ModelAPI_ResultParameter()
+std::pair<bool, QString> 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<bool, QString>(false, QString(NAME_ALREADY_ASSIGNED_MSG).arg(QString::fromStdWString(theNewName)).arg(value));
+
+   return std::pair<bool, QString>(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
index 0a932f7f116c2b79db669a4852d1d5e00d00e2f1..c9bf7eb88c7866752d955a6983ba786f16b8a66f 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <ModelAPI.h>
 #include <ModelAPI_Result.h>
+#include <QString>
 
 /**\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<bool, QString> 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
index 1cfac08334244a97ccce28257bb84cb9f2429fb0..d68b7dbeee5c46fa094174f9dcde4ed7b006a84a 100644 (file)
@@ -21,7 +21,7 @@
 
 #include <string>
 
-std::string ModelAPI_ResultPart::groupName()
+std::string ModelAPI_ResultPart::groupName() const
 {
   return ModelAPI_ResultPart::group();
 }
index 148315a5f89492e837c5b597a0b30e240c8671e5..f37e518795bad1ae0ac6a1c7764e2bfbb0e090f1 100644 (file)
@@ -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()
index 160925e8b3fbc0c98286ffa86b2dcf126d3b33d0..76e17f564853a95e363d3f6e8c71aed61b705ce9 100644 (file)
@@ -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*/);
   }
 }
 
index 4fd9b86b2cf5d10e7128d7e60fafd4f162877e64..8fac2210841ad1af009a54659baaa0259ed62afd 100644 (file)
@@ -50,6 +50,8 @@
 #include <QMessageBox>
 #include <QApplication>
 
+#include <string>
+
 #ifdef DEBUG_INDXES
 #include <QToolTip>
 #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<QLineEdit*>(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();
-        }
       }
     }
   }
index 0b1d37a6433ca1c706d03c550628a4b3d0dd4ca4..4f667406546447a47a7e280959fb8c131c3f5963 100644 (file)
@@ -50,6 +50,7 @@
 #include <iostream>
 #include <sstream>
 #include <string>
+#include <QString>
 
 #ifndef WIN32
 # include <sys/stat.h>
@@ -160,83 +161,16 @@ bool canRemoveOrRename(QWidget* theParent, const std::set<FeaturePtr>& 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;
 }
 
 //**************************************************************
index 7f4073e93bc7d3d237ee24f71aa604c43e3b84e7..5231442ceff2d73e51da8e3f79a3bb7613866bf5 100644 (file)
@@ -102,19 +102,9 @@ std::string XGUI_EXPORT featureInfo(FeaturePtr theFeature);
  */
 bool XGUI_EXPORT canRemoveOrRename(QWidget* theParent, const std::set<FeaturePtr>& 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
index f87efd1f183020fe8740cd00edd5afddd6a0b649..e252ac3f25ae47f9157cfd876641415dc7304787 100644 (file)
@@ -7,10 +7,6 @@
         <source>Warning</source>
         <translation>Attention</translation>
     </message>
-    <message>
-        <source>Name %2 already exists in %1.</source>
-        <translation>Le nom %2 existe déjà dans %1.</translation>
-    </message>
     <message>
         <source>Move to the end</source>
         <translation>Aller à la fin</translation>