Added PropertyExpressionEngine to DocumentObject class.
This commit is contained in:
parent
8259ec6764
commit
fb2b1a6ec0
|
@ -1191,6 +1191,7 @@ void Document::restore (void)
|
||||||
|
|
||||||
// reset all touched
|
// reset all touched
|
||||||
for (std::map<std::string,DocumentObject*>::iterator It= d->objectMap.begin();It!=d->objectMap.end();++It) {
|
for (std::map<std::string,DocumentObject*>::iterator It= d->objectMap.begin();It!=d->objectMap.end();++It) {
|
||||||
|
It->second->connectRelabelSignals();
|
||||||
It->second->onDocumentRestored();
|
It->second->onDocumentRestored();
|
||||||
It->second->purgeTouched();
|
It->second->purgeTouched();
|
||||||
}
|
}
|
||||||
|
@ -1362,6 +1363,29 @@ Document::getDependencyList(const std::vector<App::DocumentObject*>& objs) const
|
||||||
return ary;
|
return ary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Signal that object identifiers, typically a property or document object has been renamed.
|
||||||
|
*
|
||||||
|
* This function iterates through all document object in the document, and calls its
|
||||||
|
* renameObjectIdentifiers functions.
|
||||||
|
*
|
||||||
|
* @param paths Map with current and new names
|
||||||
|
*/
|
||||||
|
|
||||||
|
void Document::renameObjectIdentifiers(const std::map<App::ObjectIdentifier, App::ObjectIdentifier> &paths)
|
||||||
|
{
|
||||||
|
std::map<App::ObjectIdentifier, App::ObjectIdentifier> extendedPaths;
|
||||||
|
|
||||||
|
std::map<App::ObjectIdentifier, App::ObjectIdentifier>::const_iterator it = paths.begin();
|
||||||
|
while (it != paths.end()) {
|
||||||
|
extendedPaths[it->first.canonicalPath()] = it->second.canonicalPath();
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::vector<DocumentObject*>::iterator it = d->objectArray.begin(); it != d->objectArray.end(); ++it)
|
||||||
|
(*it)->renameObjectIdentifiers(extendedPaths);
|
||||||
|
}
|
||||||
|
|
||||||
void Document::_rebuildDependencyList(void)
|
void Document::_rebuildDependencyList(void)
|
||||||
{
|
{
|
||||||
d->VertexObjectList.clear();
|
d->VertexObjectList.clear();
|
||||||
|
|
|
@ -279,6 +279,9 @@ public:
|
||||||
//void setChanged(DocumentObject* change);
|
//void setChanged(DocumentObject* change);
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
|
/// Function called to signal that an object identifier has been renamed
|
||||||
|
void renameObjectIdentifiers(const std::map<App::ObjectIdentifier, App::ObjectIdentifier> & paths);
|
||||||
|
|
||||||
virtual PyObject *getPyObject(void);
|
virtual PyObject *getPyObject(void);
|
||||||
|
|
||||||
friend class Application;
|
friend class Application;
|
||||||
|
|
|
@ -33,6 +33,9 @@
|
||||||
#include "DocumentObjectPy.h"
|
#include "DocumentObjectPy.h"
|
||||||
#include "DocumentObjectGroup.h"
|
#include "DocumentObjectGroup.h"
|
||||||
#include "PropertyLinks.h"
|
#include "PropertyLinks.h"
|
||||||
|
#include "PropertyExpressionEngine.h"
|
||||||
|
#include <boost/signals/connection.hpp>
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
|
||||||
using namespace App;
|
using namespace App;
|
||||||
|
|
||||||
|
@ -46,10 +49,11 @@ DocumentObjectExecReturn *DocumentObject::StdReturn = 0;
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
DocumentObject::DocumentObject(void)
|
DocumentObject::DocumentObject(void)
|
||||||
: _pDoc(0),pcNameInDocument(0)
|
: ExpressionEngine(),_pDoc(0),pcNameInDocument(0)
|
||||||
{
|
{
|
||||||
// define Label of type 'Output' to avoid being marked as touched after relabeling
|
// define Label of type 'Output' to avoid being marked as touched after relabeling
|
||||||
ADD_PROPERTY_TYPE(Label,("Unnamed"),"Base",Prop_Output,"User name of the object (UTF8)");
|
ADD_PROPERTY_TYPE(Label,("Unnamed"),"Base",Prop_Output,"User name of the object (UTF8)");
|
||||||
|
ADD_PROPERTY_TYPE(ExpressionEngine,(),"Base",Prop_Hidden,"Property expressions");
|
||||||
}
|
}
|
||||||
|
|
||||||
DocumentObject::~DocumentObject(void)
|
DocumentObject::~DocumentObject(void)
|
||||||
|
@ -88,7 +92,7 @@ App::DocumentObjectExecReturn *DocumentObject::recompute(void)
|
||||||
|
|
||||||
DocumentObjectExecReturn *DocumentObject::execute(void)
|
DocumentObjectExecReturn *DocumentObject::execute(void)
|
||||||
{
|
{
|
||||||
return DocumentObject::StdReturn;
|
return StdReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
short DocumentObject::mustExecute(void) const
|
short DocumentObject::mustExecute(void) const
|
||||||
|
@ -148,6 +152,10 @@ std::vector<DocumentObject*> DocumentObject::getOutList(void) const
|
||||||
ret.push_back(static_cast<PropertyLinkSub*>(*It)->getValue());
|
ret.push_back(static_cast<PropertyLinkSub*>(*It)->getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get document objects that this document object relies on
|
||||||
|
ExpressionEngine.getDocumentObjectDeps(ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,8 +235,87 @@ void DocumentObject::touch(void)
|
||||||
StatusBits.set(0);
|
StatusBits.set(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check whether the document object is touched or not.
|
||||||
|
* @return true if document object is touched, false if not.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool DocumentObject::isTouched() const
|
||||||
|
{
|
||||||
|
return ExpressionEngine.isTouched() || StatusBits.test(0);
|
||||||
|
}
|
||||||
|
|
||||||
void DocumentObject::Save (Base::Writer &writer) const
|
void DocumentObject::Save (Base::Writer &writer) const
|
||||||
{
|
{
|
||||||
writer.ObjectName = this->getNameInDocument();
|
writer.ObjectName = this->getNameInDocument();
|
||||||
App::PropertyContainer::Save(writer);
|
App::PropertyContainer::Save(writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Associate the expression \expr with the object identifier \a path in this document object.
|
||||||
|
* @param path Target object identifier for the result of the expression
|
||||||
|
* @param expr Expression tree
|
||||||
|
* @param comment Optional comment describing the expression
|
||||||
|
*/
|
||||||
|
|
||||||
|
void DocumentObject::setExpression(const ObjectIdentifier &path, boost::shared_ptr<Expression> expr, const char * comment)
|
||||||
|
{
|
||||||
|
ExpressionEngine.setValue(path, expr, comment);
|
||||||
|
connectRelabelSignals();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get expression information associated with \a path.
|
||||||
|
* @param path Object identifier
|
||||||
|
* @return Expression info, containing expression and optional comment.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const PropertyExpressionEngine::ExpressionInfo DocumentObject::getExpression(const ObjectIdentifier &path) const
|
||||||
|
{
|
||||||
|
boost::any value = ExpressionEngine.getValue(path);
|
||||||
|
|
||||||
|
if (value.type() == typeid(PropertyExpressionEngine::ExpressionInfo))
|
||||||
|
return boost::any_cast<PropertyExpressionEngine::ExpressionInfo>(value);
|
||||||
|
else
|
||||||
|
return PropertyExpressionEngine::ExpressionInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Invoke ExpressionEngine's renameObjectIdentifier, to possibly rewrite expressions using
|
||||||
|
* the \a paths map with current and new identifiers.
|
||||||
|
*
|
||||||
|
* @param paths
|
||||||
|
*/
|
||||||
|
|
||||||
|
void DocumentObject::renameObjectIdentifiers(const std::map<ObjectIdentifier, ObjectIdentifier> &paths)
|
||||||
|
{
|
||||||
|
ExpressionEngine.renameObjectIdentifiers(paths);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Helper function that sets up a signal to track document object renames.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void DocumentObject::connectRelabelSignals()
|
||||||
|
{
|
||||||
|
// Only keep signal if the ExpressionEngine has at least one expression
|
||||||
|
if (ExpressionEngine.numExpressions() > 0) {
|
||||||
|
|
||||||
|
// Not already connected?
|
||||||
|
if (!onRelabledObjectConnection.connected())
|
||||||
|
onRelabledObjectConnection = getDocument()->signalRenamedObject.connect(boost::bind(&PropertyExpressionEngine::slotObjectRenamed, &ExpressionEngine, _1));
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Crude method to resolve all expression dependencies
|
||||||
|
ExpressionEngine.execute();
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
// Ignore any error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Disconnect signals; nothing to track now
|
||||||
|
onRelabledObjectConnection.disconnect();
|
||||||
|
onRelabledDocumentConnection.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -26,18 +26,20 @@
|
||||||
|
|
||||||
#include <App/PropertyContainer.h>
|
#include <App/PropertyContainer.h>
|
||||||
#include <App/PropertyStandard.h>
|
#include <App/PropertyStandard.h>
|
||||||
|
#include <App/PropertyExpressionEngine.h>
|
||||||
|
|
||||||
#include <Base/TimeInfo.h>
|
#include <Base/TimeInfo.h>
|
||||||
#include <CXX/Objects.hxx>
|
#include <CXX/Objects.hxx>
|
||||||
|
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
|
#include <boost/signals.hpp>
|
||||||
|
|
||||||
namespace App
|
namespace App
|
||||||
{
|
{
|
||||||
class Document;
|
class Document;
|
||||||
class DocumentObjectGroup;
|
class DocumentObjectGroup;
|
||||||
class DocumentObjectPy;
|
class DocumentObjectPy;
|
||||||
|
class Expression;
|
||||||
|
|
||||||
enum ObjectStatus {
|
enum ObjectStatus {
|
||||||
Touch = 0,
|
Touch = 0,
|
||||||
|
@ -79,6 +81,7 @@ class AppExport DocumentObject: public App::PropertyContainer
|
||||||
public:
|
public:
|
||||||
|
|
||||||
PropertyString Label;
|
PropertyString Label;
|
||||||
|
PropertyExpressionEngine ExpressionEngine;
|
||||||
|
|
||||||
/// returns the type name of the ViewProvider
|
/// returns the type name of the ViewProvider
|
||||||
virtual const char* getViewProviderName(void) const {
|
virtual const char* getViewProviderName(void) const {
|
||||||
|
@ -99,7 +102,7 @@ public:
|
||||||
/// set this feature touched (cause recomputation on depndend features)
|
/// set this feature touched (cause recomputation on depndend features)
|
||||||
void touch(void);
|
void touch(void);
|
||||||
/// test if this feature is touched
|
/// test if this feature is touched
|
||||||
bool isTouched(void) const {return StatusBits.test(0);}
|
bool isTouched(void) const;
|
||||||
/// reset this feature touched
|
/// reset this feature touched
|
||||||
void purgeTouched(void){StatusBits.reset(0);setPropertyStatus(0,false);}
|
void purgeTouched(void){StatusBits.reset(0);setPropertyStatus(0,false);}
|
||||||
/// set this feature to error
|
/// set this feature to error
|
||||||
|
@ -160,6 +163,16 @@ public:
|
||||||
|
|
||||||
virtual void Save (Base::Writer &writer) const;
|
virtual void Save (Base::Writer &writer) const;
|
||||||
|
|
||||||
|
/* Expression support */
|
||||||
|
|
||||||
|
virtual void setExpression(const ObjectIdentifier & path, boost::shared_ptr<App::Expression> expr, const char *comment = 0);
|
||||||
|
|
||||||
|
virtual const PropertyExpressionEngine::ExpressionInfo getExpression(const ObjectIdentifier &path) const;
|
||||||
|
|
||||||
|
virtual void renameObjectIdentifiers(const std::map<App::ObjectIdentifier, App::ObjectIdentifier> & paths);
|
||||||
|
|
||||||
|
virtual void connectRelabelSignals();
|
||||||
|
|
||||||
const std::string & getOldLabel() const { return oldLabel; }
|
const std::string & getOldLabel() const { return oldLabel; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -207,6 +220,10 @@ protected: // attributes
|
||||||
/// pointer to the document this object belongs to
|
/// pointer to the document this object belongs to
|
||||||
App::Document* _pDoc;
|
App::Document* _pDoc;
|
||||||
|
|
||||||
|
// Connections to track relabeling of document and document objects
|
||||||
|
boost::BOOST_SIGNALS_NAMESPACE::scoped_connection onRelabledDocumentConnection;
|
||||||
|
boost::BOOST_SIGNALS_NAMESPACE::scoped_connection onRelabledObjectConnection;
|
||||||
|
|
||||||
/// Old label; used for renaming expressions
|
/// Old label; used for renaming expressions
|
||||||
std::string oldLabel;
|
std::string oldLabel;
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,11 @@
|
||||||
<UserDocu>Mark the object as unchanged</UserDocu>
|
<UserDocu>Mark the object as unchanged</UserDocu>
|
||||||
</Documentation>
|
</Documentation>
|
||||||
</Methode>
|
</Methode>
|
||||||
|
<Methode Name="setExpression">
|
||||||
|
<Documentation>
|
||||||
|
<UserDocu>Register an expression for a property</UserDocu>
|
||||||
|
</Documentation>
|
||||||
|
</Methode>
|
||||||
<Attribute Name="OutList" ReadOnly="true">
|
<Attribute Name="OutList" ReadOnly="true">
|
||||||
<Documentation>
|
<Documentation>
|
||||||
<UserDocu>A list of all objects this object links to.</UserDocu>
|
<UserDocu>A list of all objects this object links to.</UserDocu>
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
// inclusion of the generated files (generated out of DocumentObjectPy.xml)
|
// inclusion of the generated files (generated out of DocumentObjectPy.xml)
|
||||||
#include "DocumentObjectPy.h"
|
#include "DocumentObjectPy.h"
|
||||||
#include "DocumentObjectPy.cpp"
|
#include "DocumentObjectPy.cpp"
|
||||||
|
#include "Expression.h"
|
||||||
|
|
||||||
using namespace App;
|
using namespace App;
|
||||||
|
|
||||||
|
@ -152,6 +153,31 @@ Py::List DocumentObjectPy::getOutList(void) const
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyObject* DocumentObjectPy::setExpression(PyObject * args)
|
||||||
|
{
|
||||||
|
char * path = NULL;
|
||||||
|
PyObject * expr;
|
||||||
|
char * comment = 0;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, "sO|s", &path, &expr, &comment)) // convert args: Python->C
|
||||||
|
return NULL; // NULL triggers exception
|
||||||
|
|
||||||
|
App::ObjectIdentifier p(ObjectIdentifier::parse(getDocumentObjectPtr(), path));
|
||||||
|
|
||||||
|
if (Py::Object(expr).isNone())
|
||||||
|
getDocumentObjectPtr()->setExpression(p, boost::shared_ptr<Expression>());
|
||||||
|
else if (PyString_Check(expr)) {
|
||||||
|
const char * exprStr = PyString_AsString(expr);
|
||||||
|
boost::shared_ptr<Expression> shared_expr(ExpressionParser::parse(getDocumentObjectPtr(), exprStr));
|
||||||
|
|
||||||
|
getDocumentObjectPtr()->setExpression(p, shared_expr, comment);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw Py::TypeError("String or None expected.");
|
||||||
|
Py_Return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PyObject *DocumentObjectPy::getCustomAttributes(const char* /*attr*/) const
|
PyObject *DocumentObjectPy::getCustomAttributes(const char* /*attr*/) const
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user