Expose dynamic property signals to python observer
This commit is contained in:
@@ -96,6 +96,13 @@ DocumentObserverPython::DocumentObserverPython(const Py::Object& obj) : inst(obj
|
||||
(&DocumentObserverPython::slotCommitTransaction, this, _1));
|
||||
this->connectDocumentAbortTransaction = App::GetApplication().signalAbortTransaction.connect(boost::bind
|
||||
(&DocumentObserverPython::slotAbortTransaction, this, _1));
|
||||
|
||||
this->connectObjectAppendDynamicProperty = App::GetApplication().signalAppendDynamicProperty.connect(boost::bind
|
||||
(&DocumentObserverPython::slotAppendDynamicProperty, this, _1));
|
||||
this->connectObjectRemoveDynamicProperty = App::GetApplication().signalRemoveDynamicProperty.connect(boost::bind
|
||||
(&DocumentObserverPython::slotRemoveDynamicProperty, this, _1));
|
||||
this->connectObjectChangePropertyEditor = App::GetApplication().signalChangePropertyEditor.connect(boost::bind
|
||||
(&DocumentObserverPython::slotChangePropertyEditor, this, _1));
|
||||
}
|
||||
|
||||
DocumentObserverPython::~DocumentObserverPython()
|
||||
@@ -118,6 +125,10 @@ DocumentObserverPython::~DocumentObserverPython()
|
||||
this->connectDocumentOpenTransaction.disconnect();
|
||||
this->connectDocumentCommitTransaction.disconnect();
|
||||
this->connectDocumentAbortTransaction.disconnect();
|
||||
|
||||
this->connectObjectAppendDynamicProperty.disconnect();
|
||||
this->connectObjectRemoveDynamicProperty.disconnect();
|
||||
this->connectObjectChangePropertyEditor.disconnect();
|
||||
}
|
||||
|
||||
void DocumentObserverPython::slotCreatedDocument(const App::Document& Doc)
|
||||
@@ -435,3 +446,75 @@ void DocumentObserverPython::slotAbortTransaction(const App::Document& doc)
|
||||
e.ReportException();
|
||||
}
|
||||
}
|
||||
|
||||
void DocumentObserverPython::slotAppendDynamicProperty(const App::Property& Prop)
|
||||
{
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
if (this->inst.hasAttr(std::string("slotAppendDynamicProperty"))) {
|
||||
auto container = Prop.getContainer();
|
||||
Py::Callable method(this->inst.getAttr(std::string("slotAppendDynamicProperty")));
|
||||
Py::Tuple args(2);
|
||||
args.setItem(0, Py::Object(static_cast<App::DocumentObject*>(container)->getPyObject(), true));
|
||||
// If a property is touched but not part of a document object then its name is null.
|
||||
// In this case the slot function must not be called.
|
||||
const char* prop_name = container->getPropertyName(&Prop);
|
||||
if (prop_name) {
|
||||
args.setItem(1, Py::String(prop_name));
|
||||
method.apply(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Py::Exception&) {
|
||||
Base::PyException e; // extract the Python error text
|
||||
e.ReportException();
|
||||
}
|
||||
}
|
||||
|
||||
void DocumentObserverPython::slotRemoveDynamicProperty(const App::Property& Prop)
|
||||
{
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
if (this->inst.hasAttr(std::string("slotRemoveDynamicProperty"))) {
|
||||
auto container = Prop.getContainer();
|
||||
Py::Callable method(this->inst.getAttr(std::string("slotRemoveDynamicProperty")));
|
||||
Py::Tuple args(2);
|
||||
args.setItem(0, Py::Object(static_cast<App::DocumentObject*>(container)->getPyObject(), true));
|
||||
// If a property is touched but not part of a document object then its name is null.
|
||||
// In this case the slot function must not be called.
|
||||
const char* prop_name = container->getPropertyName(&Prop);
|
||||
if (prop_name) {
|
||||
args.setItem(1, Py::String(prop_name));
|
||||
method.apply(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Py::Exception&) {
|
||||
Base::PyException e; // extract the Python error text
|
||||
e.ReportException();
|
||||
}
|
||||
}
|
||||
|
||||
void DocumentObserverPython::slotChangePropertyEditor(const App::Property& Prop)
|
||||
{
|
||||
Base::PyGILStateLocker lock;
|
||||
try {
|
||||
if (this->inst.hasAttr(std::string("slotChangePropertyEditor"))) {
|
||||
auto container = Prop.getContainer();
|
||||
Py::Callable method(this->inst.getAttr(std::string("slotChangePropertyEditor")));
|
||||
Py::Tuple args(2);
|
||||
args.setItem(0, Py::Object(static_cast<App::DocumentObject*>(container)->getPyObject(), true));
|
||||
// If a property is touched but not part of a document object then its name is null.
|
||||
// In this case the slot function must not be called.
|
||||
const char* prop_name = container->getPropertyName(&Prop);
|
||||
if (prop_name) {
|
||||
args.setItem(1, Py::String(prop_name));
|
||||
method.apply(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Py::Exception&) {
|
||||
Base::PyException e; // extract the Python error text
|
||||
e.ReportException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,6 +85,12 @@ private:
|
||||
void slotCommitTransaction(const App::Document& Doc);
|
||||
/** Called when a observed document aborts a transaction */
|
||||
void slotAbortTransaction(const App::Document& Doc);
|
||||
/** Called when a object get a new dynamic property added*/
|
||||
void slotAppendDynamicProperty(const App::Property& Prop);
|
||||
/** Called when a object get a dynamic property removed*/
|
||||
void slotRemoveDynamicProperty(const App::Property& Prop);
|
||||
/** Called when a object property get a new editor relevant status like hidden or read only*/
|
||||
void slotChangePropertyEditor(const App::Property& Prop);
|
||||
|
||||
private:
|
||||
Py::Object inst;
|
||||
@@ -108,6 +114,9 @@ private:
|
||||
Connection connectDocumentOpenTransaction;
|
||||
Connection connectDocumentCommitTransaction;
|
||||
Connection connectDocumentAbortTransaction;
|
||||
Connection connectObjectAppendDynamicProperty;
|
||||
Connection connectObjectRemoveDynamicProperty;
|
||||
Connection connectObjectChangePropertyEditor;
|
||||
};
|
||||
|
||||
} //namespace App
|
||||
|
||||
@@ -1392,6 +1392,21 @@ class DocumentObserverCases(unittest.TestCase):
|
||||
self.signal.append('ObjRecomputed');
|
||||
self.parameter.append(obj)
|
||||
|
||||
def slotAppendDynamicProperty(self, obj, prop):
|
||||
self.signal.append('ObjAddDynProp');
|
||||
self.parameter.append(obj)
|
||||
self.parameter2.append(prop)
|
||||
|
||||
def slotRemoveDynamicProperty(self, obj, prop):
|
||||
self.signal.append('ObjRemoveDynProp');
|
||||
self.parameter.append(obj)
|
||||
self.parameter2.append(prop)
|
||||
|
||||
def slotChangePropertyEditor(self, obj, prop):
|
||||
self.signal.append('ObjChangePropEdit');
|
||||
self.parameter.append(obj)
|
||||
self.parameter2.append(prop)
|
||||
|
||||
|
||||
def setUp(self):
|
||||
self.Obs = self.Observer();
|
||||
@@ -1529,8 +1544,32 @@ class DocumentObserverCases(unittest.TestCase):
|
||||
self.failUnless(self.Obs.parameter.pop() is obj)
|
||||
self.failUnless(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2)
|
||||
|
||||
pyobj = self.Doc1.addObject("App::FeaturePython","pyobj")
|
||||
self.Obs.signal = []
|
||||
self.Obs.parameter = []
|
||||
self.Obs.parameter2 = []
|
||||
pyobj.addProperty("App::PropertyLength","Prop","Group","test property")
|
||||
self.failUnless(self.Obs.signal.pop() == 'ObjAddDynProp')
|
||||
self.failUnless(self.Obs.parameter.pop() is pyobj)
|
||||
self.failUnless(self.Obs.parameter2.pop() == 'Prop')
|
||||
self.failUnless(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2)
|
||||
|
||||
pyobj.setEditorMode('Prop', ['ReadOnly'])
|
||||
self.failUnless(self.Obs.signal.pop() == 'ObjChangePropEdit')
|
||||
self.failUnless(self.Obs.parameter.pop() is pyobj)
|
||||
self.failUnless(self.Obs.parameter2.pop() == 'Prop')
|
||||
self.failUnless(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2)
|
||||
|
||||
pyobj.removeProperty('Prop')
|
||||
self.failUnless(self.Obs.signal.pop() == 'ObjRemoveDynProp')
|
||||
self.failUnless(self.Obs.parameter.pop() is pyobj)
|
||||
self.failUnless(self.Obs.parameter2.pop() == 'Prop')
|
||||
self.failUnless(not self.Obs.signal and not self.Obs.parameter and not self.Obs.parameter2)
|
||||
|
||||
FreeCAD.closeDocument('Observer1')
|
||||
self.Obs.signal = []
|
||||
self.Obs.parameter = []
|
||||
self.Obs.parameter2 = []
|
||||
|
||||
def testUndoDisabledDocument(self):
|
||||
|
||||
|
||||
Reference in New Issue
Block a user