From e7f8f2f48c2e05d8209180705c63306e3fd39b36 Mon Sep 17 00:00:00 2001 From: Pieter Hijma Date: Sun, 18 May 2025 14:58:53 +0200 Subject: [PATCH] Core: Add logic to rename dynamic properties --- src/App/Application.h | 2 ++ src/App/DynamicProperty.cpp | 45 +++++++++++++++++++++++++++++++++++++ src/App/DynamicProperty.h | 2 ++ src/App/PropertyContainer.h | 13 +++++++++++ 4 files changed, 62 insertions(+) diff --git a/src/App/Application.h b/src/App/Application.h index f6eef0365a..4aa70c85e0 100644 --- a/src/App/Application.h +++ b/src/App/Application.h @@ -305,6 +305,8 @@ public: //@{ /// signal on adding a dynamic property boost::signals2::signal signalAppendDynamicProperty; + /// signal on renaming a dynamic property + boost::signals2::signal signalRenameDynamicProperty; /// signal on about removing a dynamic property boost::signals2::signal signalRemoveDynamicProperty; /// signal on about changing the editor mode of a property diff --git a/src/App/DynamicProperty.cpp b/src/App/DynamicProperty.cpp index c2d58b758c..18f5c5ac9b 100644 --- a/src/App/DynamicProperty.cpp +++ b/src/App/DynamicProperty.cpp @@ -413,6 +413,51 @@ bool DynamicProperty::changeDynamicProperty(const Property* prop, return true; } +bool DynamicProperty::renameDynamicProperty(Property* prop, + const char* newName) +{ + auto& propIndex = props.get<1>(); + auto propIt = propIndex.find(prop); + if (propIt == propIndex.end()) { + return false; + } + const PropData& data = *propIt; + + if (propIt->property->testStatus(Property::LockDynamic)) { + FC_THROWM(Base::RuntimeError, "Property " << prop->getName() << " is locked"); + } + + PropertyContainer* container = prop->getContainer(); + if (container->getPropertyByName(newName) != nullptr) { + FC_THROWM(Base::NameError, + "Property " << container->getFullName() << '.' << newName << " already exists"); + } + + if (Base::Tools::getIdentifier(newName) != newName) { + FC_THROWM(Base::NameError, "Invalid property name '" << newName << "'"); + } + + std::string oldName{data.getName()}; + auto& nameIndex = props.get<0>(); + auto nameIt = nameIndex.find(data.getName()); + if (nameIt == nameIndex.end()) { + // This should never happen + FC_THROWM(Base::RuntimeError, + "Property " << data.getName() << " not found in index"); + } + nameIndex.modify(nameIt, [&](PropData& d) { + d.name = newName; + d.pName = nullptr; + // make sure that the property's name points to PropData.name that + // manages the memory. + d.property->myName = d.name.c_str(); + }); + + GetApplication().signalRenameDynamicProperty(*prop, oldName.c_str()); + + return true; +} + const char* DynamicProperty::getPropertyName(const Property* prop) const { auto& index = props.get<1>(); diff --git a/src/App/DynamicProperty.h b/src/App/DynamicProperty.h index 1a0c0a42f9..c066e8bf0d 100644 --- a/src/App/DynamicProperty.h +++ b/src/App/DynamicProperty.h @@ -210,6 +210,8 @@ public: bool changeDynamicProperty(const Property* prop, const char* group, const char* doc); + bool renameDynamicProperty(Property* prop, const char* newName); + private: std::string getUniquePropertyName(const PropertyContainer& pc, const char* Name) const; diff --git a/src/App/PropertyContainer.h b/src/App/PropertyContainer.h index 646834378f..c673c0b500 100644 --- a/src/App/PropertyContainer.h +++ b/src/App/PropertyContainer.h @@ -539,6 +539,19 @@ public: return dynamicProps.changeDynamicProperty(prop,group,doc); } + /** + * @brief Rename the dynamic property. + * + * @param[in] prop The property to rename. + * @param[in] name The new name for the property. + * + * @return `true` if the property was renamed; `false` otherwise. + * @throw Base::NameError If the new name is invalid or already exists. + */ + bool renameDynamicProperty(Property *prop, const char *name) { + return dynamicProps.renameDynamicProperty(prop,name); + } + /** * @brief Remove a dynamic property. *