PropertyExpressionEngine/DocumentObject: Track object deletes and update dependencies accordingly.

This commit is contained in:
Eivind Kvedalen 2015-12-20 01:15:22 +01:00 committed by wmayer
parent 7b25d454b5
commit df660dc280
4 changed files with 56 additions and 0 deletions

View File

@ -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();
}
}

View File

@ -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;

View File

@ -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.

View File

@ -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;