Merge pull request #22985 from pieterhijma/fix-rename-prop-with-expr

Core: Fix renaming a property with an expression
This commit is contained in:
Chris Hennes
2025-08-11 11:13:54 -05:00
committed by GitHub
2 changed files with 62 additions and 1 deletions

View File

@@ -32,16 +32,17 @@
#include <string>
#endif
#include <App/DocumentObjectPy.h>
#include <Base/Console.h>
#include <Base/Matrix.h>
#include <Base/Tools.h>
#include <Base/Writer.h>
#include "Expression.h"
#include "Application.h"
#include "ElementNamingUtils.h"
#include "Document.h"
#include "DocumentObject.h"
#include "DocumentObjectPy.h"
#include "DocumentObjectExtension.h"
#include "DocumentObjectGroup.h"
#include "GeoFeatureGroupExtension.h"
@@ -715,10 +716,33 @@ bool DocumentObject::removeDynamicProperty(const char* name)
bool DocumentObject::renameDynamicProperty(Property* prop, const char* name)
{
std::string oldName = prop->getName();
auto expressions = ExpressionEngine.getExpressions();
std::vector<std::shared_ptr<Expression>> expressionsToMove;
std::vector<App::ObjectIdentifier> idsWithExprsToRemove;
for (const auto& [id, expr] : expressions) {
if (id.getProperty() == prop) {
idsWithExprsToRemove.push_back(id);
expressionsToMove.emplace_back(expr->copy());
}
}
for (const auto& it : idsWithExprsToRemove) {
ExpressionEngine.setValue(it, std::shared_ptr<Expression>());
}
bool renamed = TransactionalObject::renameDynamicProperty(prop, name);
if (renamed && _pDoc) {
_pDoc->renamePropertyOfObject(this, prop, oldName.c_str());
}
App::ObjectIdentifier idNewProp(prop->getContainer(), std::string(name));
for (auto& exprToMove : expressionsToMove) {
ExpressionEngine.setValue(idNewProp, exprToMove);
}
return renamed;
}

View File

@@ -321,6 +321,43 @@ TEST_F(RenameProperty, updateExpressionDifferentDocument)
doc->removeObject(varSet2->getNameInDocument());
}
// Test if we can rename a property which value is the result of an expression
TEST_F(RenameProperty, renamePropertyWithExpression)
{
// Arrange
auto* prop2 = freecad_cast<App::PropertyInteger*>(
varSet->addDynamicProperty("App::PropertyInteger", "Variable2", "Variables"));
prop2->setValue(Value);
App::ObjectIdentifier path(*prop);
std::shared_ptr<App::Expression> expr(App::Expression::parse(varSet, "Variable2"));
varSet->setExpression(path, expr);
varSet->ExpressionEngine.execute();
// Assert before the rename
EXPECT_EQ(prop2->getValue(), Value);
EXPECT_EQ(prop->getValue(), Value);
// Act
bool isRenamed = varSet->renameDynamicProperty(prop, "NewName");
varSet->ExpressionEngine.execute();
// Assert after the rename
EXPECT_TRUE(isRenamed);
EXPECT_STREQ(varSet->getPropertyName(prop), "NewName");
EXPECT_EQ(prop->getValue(), Value);
EXPECT_EQ(varSet->getDynamicPropertyByName("Variable"), nullptr);
EXPECT_EQ(varSet->getDynamicPropertyByName("NewName"), prop);
// Act
prop2->setValue(Value + 1);
varSet->ExpressionEngine.execute();
// Assert
EXPECT_EQ(prop2->getValue(), Value + 1);
EXPECT_EQ(prop->getValue(), Value + 1);
}
// Tests whether we can rename a property and undo it
TEST_F(RenameProperty, undoRenameProperty)
{