PropertyExpressionEngine/DocumentObject: Track object deletes and update dependencies accordingly.
This commit is contained in:
parent
7b25d454b5
commit
df660dc280
|
@ -305,6 +305,10 @@ void DocumentObject::connectRelabelSignals()
|
|||
if (!onRelabledObjectConnection.connected())
|
||||
onRelabledObjectConnection = getDocument()->signalRelabelObject.connect(boost::bind(&PropertyExpressionEngine::slotObjectRenamed, &ExpressionEngine, _1));
|
||||
|
||||
// Connect to signalDeletedObject, to properly track deletion of other objects that might be referenced in an expression
|
||||
if (!onDeletedObjectConnection.connected())
|
||||
onDeletedObjectConnection = getDocument()->signalDeletedObject.connect(boost::bind(&PropertyExpressionEngine::slotObjectDeleted, &ExpressionEngine, _1));
|
||||
|
||||
try {
|
||||
// Crude method to resolve all expression dependencies
|
||||
ExpressionEngine.execute();
|
||||
|
@ -317,5 +321,6 @@ void DocumentObject::connectRelabelSignals()
|
|||
// Disconnect signals; nothing to track now
|
||||
onRelabledObjectConnection.disconnect();
|
||||
onRelabledDocumentConnection.disconnect();
|
||||
onDeletedObjectConnection.disconnect();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -223,6 +223,7 @@ protected: // attributes
|
|||
// Connections to track relabeling of document and document objects
|
||||
boost::BOOST_SIGNALS_NAMESPACE::scoped_connection onRelabledDocumentConnection;
|
||||
boost::BOOST_SIGNALS_NAMESPACE::scoped_connection onRelabledObjectConnection;
|
||||
boost::BOOST_SIGNALS_NAMESPACE::scoped_connection onDeletedObjectConnection;
|
||||
|
||||
/// Old label; used for renaming expressions
|
||||
std::string oldLabel;
|
||||
|
|
|
@ -94,6 +94,34 @@ private:
|
|||
int changed;
|
||||
};
|
||||
|
||||
class ObjectDeletedExpressionVisitor : public ExpressionVisitor {
|
||||
public:
|
||||
|
||||
ObjectDeletedExpressionVisitor(const App::DocumentObject * _obj)
|
||||
: obj(_obj)
|
||||
, found(false)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Visit each node in the expression, and if it is a VariableExpression object check if it references obj
|
||||
* @param node Node to visit
|
||||
*/
|
||||
|
||||
void visit(Expression * node) {
|
||||
VariableExpression *expr = freecad_dynamic_cast<VariableExpression>(node);
|
||||
|
||||
if (expr && expr->getPath().getDocumentObject() == obj)
|
||||
found = true;
|
||||
}
|
||||
|
||||
bool isFound() const { return found; }
|
||||
|
||||
private:
|
||||
const App::DocumentObject * obj;
|
||||
bool found;
|
||||
};
|
||||
|
||||
TYPESYSTEM_SOURCE(App::PropertyExpressionEngine , App::Property);
|
||||
|
||||
/**
|
||||
|
@ -315,6 +343,26 @@ void PropertyExpressionEngine::slotObjectRenamed(const DocumentObject &obj)
|
|||
}
|
||||
}
|
||||
|
||||
void PropertyExpressionEngine::slotObjectDeleted(const DocumentObject &obj)
|
||||
{
|
||||
DocumentObject * docObj = freecad_dynamic_cast<DocumentObject>(getContainer());
|
||||
|
||||
/* In a document object, and on undo stack? */
|
||||
if (!docObj || docObj->getNameInDocument() == 0)
|
||||
return;
|
||||
|
||||
ObjectDeletedExpressionVisitor v(&obj);
|
||||
|
||||
for (ExpressionMap::iterator it = expressions.begin(); it != expressions.end(); ++it) {
|
||||
it->second.expression->visit(v);
|
||||
|
||||
if (v.isFound()) {
|
||||
touch(); // Touch to force recompute; that will trigger a proper error
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get expression for \a path.
|
||||
* @param path ObjectIndentifier to query for.
|
||||
|
|
|
@ -118,6 +118,8 @@ public:
|
|||
size_t numExpressions() const;
|
||||
|
||||
void slotObjectRenamed(const App::DocumentObject & obj);
|
||||
|
||||
void slotObjectDeleted(const DocumentObject &obj);
|
||||
|
||||
///signal called when a expression was changed
|
||||
boost::signal<void (const App::ObjectIdentifier &)> expressionChanged;
|
||||
|
|
Loading…
Reference in New Issue
Block a user