diff --git a/src/Base/Exception.cpp b/src/Base/Exception.cpp index 6179bcc5a..e2fe30c60 100644 --- a/src/Base/Exception.cpp +++ b/src/Base/Exception.cpp @@ -304,6 +304,23 @@ RuntimeError::RuntimeError(const RuntimeError &inst) // --------------------------------------------------------- +NotImplementedError::NotImplementedError(const char * sMessage) + : Exception(sMessage) +{ +} + +NotImplementedError::NotImplementedError(const std::string& sMessage) + : Exception(sMessage) +{ +} + +NotImplementedError::NotImplementedError(const NotImplementedError &inst) + : Exception(inst) +{ +} + +// --------------------------------------------------------- + DivisionByZeroError::DivisionByZeroError(const char * sMessage) : Exception(sMessage) { diff --git a/src/Base/Exception.h b/src/Base/Exception.h index 387d44a02..f17fa71cb 100644 --- a/src/Base/Exception.h +++ b/src/Base/Exception.h @@ -270,6 +270,22 @@ public: virtual ~RuntimeError() throw() {} }; +/** + * The NotImplementedError can be used to indicate that an invoked function is not implemented. + * @author Werner Mayer + */ +class BaseExport NotImplementedError : public Exception +{ +public: + /// Construction + NotImplementedError(const char * sMessage); + NotImplementedError(const std::string& sMessage); + /// Construction + NotImplementedError(const NotImplementedError &inst); + /// Destruction + virtual ~NotImplementedError() throw() {} +}; + /** * The DivisionByZeroError can be used to indicate a division by zero. * @author Werner Mayer diff --git a/src/Gui/ViewProviderPythonFeature.cpp b/src/Gui/ViewProviderPythonFeature.cpp index b6fbe0ec7..5ca106e72 100644 --- a/src/Gui/ViewProviderPythonFeature.cpp +++ b/src/Gui/ViewProviderPythonFeature.cpp @@ -803,6 +803,198 @@ std::string ViewProviderPythonFeatureImp::setDisplayMode(const char* ModeName) return ModeName; } +ViewProviderPythonFeatureImp::ValueT +ViewProviderPythonFeatureImp::canDragObjects() const +{ + // Run the onChanged method of the proxy object. + Base::PyGILStateLocker lock; + try { + App::Property* proxy = object->getPropertyByName("Proxy"); + if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) { + Py::Object vp = static_cast(proxy)->getValue(); + if (vp.hasAttr(std::string("canDragObjects"))) { + Py::Callable method(vp.getAttr(std::string("canDragObjects"))); + Py::Tuple args; + Py::Boolean ok(method.apply(args)); + return static_cast(ok) ? Accepted : Rejected; + } + else { + return NotImplemented; + } + } + } + catch (Py::Exception&) { + Base::PyException e; // extract the Python error text + e.ReportException(); + } + + return Rejected; +} + +ViewProviderPythonFeatureImp::ValueT +ViewProviderPythonFeatureImp::canDragObject(App::DocumentObject* obj) const +{ + // Run the onChanged method of the proxy object. + Base::PyGILStateLocker lock; + try { + App::Property* proxy = object->getPropertyByName("Proxy"); + if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) { + Py::Object vp = static_cast(proxy)->getValue(); + if (vp.hasAttr(std::string("canDragObject"))) { + Py::Callable method(vp.getAttr(std::string("canDragObject"))); + Py::Tuple args(1); + args.setItem(0, Py::Object(obj->getPyObject(), true)); + Py::Boolean ok(method.apply(args)); + return static_cast(ok) ? Accepted : Rejected; + } + else { + return NotImplemented; + } + } + } + catch (Py::Exception&) { + Base::PyException e; // extract the Python error text + e.ReportException(); + } + + return Rejected; +} + +ViewProviderPythonFeatureImp::ValueT +ViewProviderPythonFeatureImp::dragObject(App::DocumentObject* obj) +{ + // Run the onChanged method of the proxy object. + Base::PyGILStateLocker lock; + try { + App::Property* proxy = object->getPropertyByName("Proxy"); + if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) { + Py::Object vp = static_cast(proxy)->getValue(); + if (vp.hasAttr(std::string("dragObject"))) { + if (vp.hasAttr("__object__")) { + Py::Callable method(vp.getAttr(std::string("dragObject"))); + Py::Tuple args(1); + args.setItem(0, Py::Object(obj->getPyObject(), true)); + method.apply(args); + return Accepted; + } + else { + Py::Callable method(vp.getAttr(std::string("dragObject"))); + Py::Tuple args(2); + args.setItem(0, Py::Object(object->getPyObject(), true)); + args.setItem(1, Py::Object(obj->getPyObject(), true)); + method.apply(args); + return Accepted; + } + } + else { + return NotImplemented; + } + } + } + catch (Py::Exception&) { + Base::PyException e; // extract the Python error text + e.ReportException(); + } + + return Rejected; +} + +ViewProviderPythonFeatureImp::ValueT +ViewProviderPythonFeatureImp::canDropObjects() const +{ + // Run the onChanged method of the proxy object. + Base::PyGILStateLocker lock; + try { + App::Property* proxy = object->getPropertyByName("Proxy"); + if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) { + Py::Object vp = static_cast(proxy)->getValue(); + if (vp.hasAttr(std::string("canDropObjects"))) { + Py::Callable method(vp.getAttr(std::string("canDropObjects"))); + Py::Tuple args; + Py::Boolean ok(method.apply(args)); + return static_cast(ok) ? Accepted : Rejected; + } + else { + return NotImplemented; + } + } + } + catch (Py::Exception&) { + Base::PyException e; // extract the Python error text + e.ReportException(); + } + + return Rejected; +} + +ViewProviderPythonFeatureImp::ValueT +ViewProviderPythonFeatureImp::canDropObject(App::DocumentObject* obj) const +{ + // Run the onChanged method of the proxy object. + Base::PyGILStateLocker lock; + try { + App::Property* proxy = object->getPropertyByName("Proxy"); + if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) { + Py::Object vp = static_cast(proxy)->getValue(); + if (vp.hasAttr(std::string("canDropObject"))) { + Py::Callable method(vp.getAttr(std::string("canDropObject"))); + Py::Tuple args(1); + args.setItem(0, Py::Object(obj->getPyObject(), true)); + Py::Boolean ok(method.apply(args)); + return static_cast(ok) ? Accepted : Rejected; + } + else { + return NotImplemented; + } + } + } + catch (Py::Exception&) { + Base::PyException e; // extract the Python error text + e.ReportException(); + } + + return Rejected; +} + +ViewProviderPythonFeatureImp::ValueT +ViewProviderPythonFeatureImp::dropObject(App::DocumentObject* obj) +{ + // Run the onChanged method of the proxy object. + Base::PyGILStateLocker lock; + try { + App::Property* proxy = object->getPropertyByName("Proxy"); + if (proxy && proxy->getTypeId() == App::PropertyPythonObject::getClassTypeId()) { + Py::Object vp = static_cast(proxy)->getValue(); + if (vp.hasAttr(std::string("dropObject"))) { + if (vp.hasAttr("__object__")) { + Py::Callable method(vp.getAttr(std::string("dropObject"))); + Py::Tuple args(1); + args.setItem(0, Py::Object(obj->getPyObject(), true)); + method.apply(args); + return Accepted; + } + else { + Py::Callable method(vp.getAttr(std::string("dropObject"))); + Py::Tuple args(2); + args.setItem(0, Py::Object(object->getPyObject(), true)); + args.setItem(1, Py::Object(obj->getPyObject(), true)); + method.apply(args); + return Accepted; + } + } + else { + return NotImplemented; + } + } + } + catch (Py::Exception&) { + Base::PyException e; // extract the Python error text + e.ReportException(); + } + + return Rejected; +} + // --------------------------------------------------------- namespace Gui { diff --git a/src/Gui/ViewProviderPythonFeature.h b/src/Gui/ViewProviderPythonFeature.h index 193942838..1e0eb82e0 100644 --- a/src/Gui/ViewProviderPythonFeature.h +++ b/src/Gui/ViewProviderPythonFeature.h @@ -38,6 +38,12 @@ namespace Gui { class GuiExport ViewProviderPythonFeatureImp { public: + enum ValueT { + NotImplemented = 0, // not handled + Accepted = 1, // handled and accepted + Rejected = 2 // handled and rejected + }; + /// constructor. ViewProviderPythonFeatureImp(ViewProviderDocumentObject*); /// destructor. @@ -75,6 +81,22 @@ public: std::string setDisplayMode(const char* ModeName); //@} + /** @name Drag and drop */ + //@{ + /// Returns true if the view provider generally supports dragging objects + ValueT canDragObjects() const; + /// Check whether the object can be removed from the view provider by drag and drop + ValueT canDragObject(App::DocumentObject*) const; + /// Starts to drag the object + ValueT dragObject(App::DocumentObject*); + /// Returns true if the view provider generally accepts dropping of objects + ValueT canDropObjects() const; + /// Check whether the object can be dropped to the view provider by drag and drop + ValueT canDropObject(App::DocumentObject*) const; + /// If the dropped object type is accepted the object will be added as child + ValueT dropObject(App::DocumentObject*); + //@} + private: ViewProviderDocumentObject* object; }; @@ -174,6 +196,74 @@ public: } //@} + /** @name Drag and drop */ + //@{ + /// Returns true if the view provider generally supports dragging objects + virtual bool canDragObjects() const { + switch (imp->canDragObjects()) { + case ViewProviderPythonFeatureImp::Accepted: + return true; + case ViewProviderPythonFeatureImp::Rejected: + return false; + default: + return ViewProviderT::canDragObjects(); + } + } + /// Check whether the object can be removed from the view provider by drag and drop + virtual bool canDragObject(App::DocumentObject* obj) const { + switch (imp->canDragObject(obj)) { + case ViewProviderPythonFeatureImp::Accepted: + return true; + case ViewProviderPythonFeatureImp::Rejected: + return false; + default: + return ViewProviderT::canDragObject(obj); + } + } + /// Starts to drag the object + virtual void dragObject(App::DocumentObject* obj) { + switch (imp->dragObject(obj)) { + case ViewProviderPythonFeatureImp::Accepted: + case ViewProviderPythonFeatureImp::Rejected: + return; + default: + return ViewProviderT::dragObject(obj); + } + } + /// Returns true if the view provider generally accepts dropping of objects + virtual bool canDropObjects() const { + switch (imp->canDropObjects()) { + case ViewProviderPythonFeatureImp::Accepted: + return true; + case ViewProviderPythonFeatureImp::Rejected: + return false; + default: + return ViewProviderT::canDropObjects(); + } + } + /// Check whether the object can be dropped to the view provider by drag and drop + virtual bool canDropObject(App::DocumentObject* obj) const { + switch (imp->canDropObject(obj)) { + case ViewProviderPythonFeatureImp::Accepted: + return true; + case ViewProviderPythonFeatureImp::Rejected: + return false; + default: + return ViewProviderT::canDropObject(obj); + } + } + /// If the dropped object type is accepted the object will be added as child + virtual void dropObject(App::DocumentObject* obj) { + switch (imp->dropObject(obj)) { + case ViewProviderPythonFeatureImp::Accepted: + case ViewProviderPythonFeatureImp::Rejected: + return; + default: + return ViewProviderT::dropObject(obj); + } + } + //@} + /** @name Display methods */ //@{ /// get the default display mode