Python feature/observer related changes

* Add new API and signal handler in document observer

* Pre initialize python handler function to improve performance. In
  case Python code use dynamic patching, i.e. add class method at
  runtime (which is rare and should be discouraged), the python feature
  can be re-initialized by simply assign proeprty Proxy again.

* Add property tracking in DocumentObjectT

* WidgetFactory adds support for accepting python QIcon, which is used
  by ViewProviderPythonFeature
This commit is contained in:
Zheng, Lei
2019-07-11 13:57:53 +08:00
committed by wmayer
parent f7edaabe43
commit ad57821cf9
12 changed files with 1875 additions and 950 deletions

View File

@@ -24,9 +24,12 @@
#ifndef GUI_VIEWPROVIDERPYTHONFEATURE_H
#define GUI_VIEWPROVIDERPYTHONFEATURE_H
#include <App/Application.h>
#include <Gui/ViewProviderGeometryObject.h>
#include <Gui/Document.h>
#include <App/PropertyPythonObject.h>
#include <App/DynamicProperty.h>
#include <App/FeaturePython.h>
class SoSensor;
class SoDragger;
@@ -44,19 +47,23 @@ public:
};
/// constructor.
ViewProviderPythonFeatureImp(ViewProviderDocumentObject*);
ViewProviderPythonFeatureImp(ViewProviderDocumentObject*, App::PropertyPythonObject &);
/// destructor.
~ViewProviderPythonFeatureImp();
// Returns the icon
QIcon getIcon() const;
std::vector<App::DocumentObject*> claimChildren(const std::vector<App::DocumentObject*>&) const;
std::vector<App::DocumentObject*> claimChildren(std::vector<App::DocumentObject*>&&) const;
bool useNewSelectionModel() const;
ValueT getElementPicked(const SoPickedPoint *pp, std::string &subname) const;
std::string getElement(const SoDetail *det) const;
SoDetail* getDetail(const char*) const;
ValueT getDetailPath(const char *name, SoFullPath *path, bool append, SoDetail *&det) const;
std::vector<Base::Vector3d> getSelectionShape(const char* Element) const;
ValueT setEdit(int ModNum);
ValueT unsetEdit(int ModNum);
bool setEditViewer(View3DInventorViewer*, int ModNum);
bool unsetEditViewer(View3DInventorViewer*);
ValueT doubleClicked(void);
void setupContextMenu(QMenu* menu);
@@ -68,6 +75,7 @@ public:
void startRestoring();
void finishRestoring();
bool onDelete(const std::vector<std::string> & sub);
ValueT canDelete(App::DocumentObject *obj) const;
//@}
/** @name Display methods */
@@ -82,6 +90,8 @@ public:
std::string setDisplayMode(const char* ModeName);
//@}
ValueT canRemoveChildrenFromRoot() const;
/** @name Drag and drop */
//@{
/// Returns true if the view provider generally supports dragging objects
@@ -96,10 +106,86 @@ public:
ValueT canDropObject(App::DocumentObject*) const;
/// If the dropped object type is accepted the object will be added as child
ValueT dropObject(App::DocumentObject*);
/** Return false to force drop only operation for a give object*/
ValueT canDragAndDropObject(App::DocumentObject*) const;
/** Query object dropping with full quanlified name */
ValueT canDropObjectEx(App::DocumentObject *obj, App::DocumentObject *,
const char *,const std::vector<std::string> &elements) const;
/** Add an object with full quanlified name to the view provider by drag and drop */
ValueT dropObjectEx(App::DocumentObject *obj, App::DocumentObject *,
const char *, const std::vector<std::string> &elements, std::string &ret);
ValueT replaceObject(App::DocumentObject *, App::DocumentObject *);
//@}
ViewProviderDocumentObject *getLinkedViewProvider(bool recursive) const;
bool canAddToSceneGraph() const;
bool getDropPrefix(std::string &prefix) const;
private:
ViewProviderDocumentObject* object;
App::PropertyPythonObject &Proxy;
bool has__object__;
#define FC_PY_VIEW_OBJECT \
FC_PY_ELEMENT(getIcon) \
FC_PY_ELEMENT(claimChildren) \
FC_PY_ELEMENT(useNewSelectionModel) \
FC_PY_ELEMENT(getElementPicked) \
FC_PY_ELEMENT(getElement) \
FC_PY_ELEMENT(getDetail) \
FC_PY_ELEMENT(getDetailPath) \
FC_PY_ELEMENT(getSelectionShape) \
FC_PY_ELEMENT(setEdit) \
FC_PY_ELEMENT(unsetEdit) \
FC_PY_ELEMENT(setEditViewer) \
FC_PY_ELEMENT(unsetEditViewer) \
FC_PY_ELEMENT(doubleClicked) \
FC_PY_ELEMENT(setupContextMenu) \
FC_PY_ELEMENT(attach) \
FC_PY_ELEMENT(updateData) \
FC_PY_ELEMENT(onChanged) \
FC_PY_ELEMENT(startRestoring) \
FC_PY_ELEMENT(finishRestoring) \
FC_PY_ELEMENT(onDelete) \
FC_PY_ELEMENT(canDelete) \
FC_PY_ELEMENT(isShow) \
FC_PY_ELEMENT(getDefaultDisplayMode) \
FC_PY_ELEMENT(getDisplayModes) \
FC_PY_ELEMENT(setDisplayMode) \
FC_PY_ELEMENT(canRemoveChildrenFromRoot) \
FC_PY_ELEMENT(canDragObjects) \
FC_PY_ELEMENT(canDragObject) \
FC_PY_ELEMENT(dragObject) \
FC_PY_ELEMENT(canDropObjects) \
FC_PY_ELEMENT(canDropObject) \
FC_PY_ELEMENT(dropObject) \
FC_PY_ELEMENT(canDragAndDropObject) \
FC_PY_ELEMENT(canDropObjectEx) \
FC_PY_ELEMENT(dropObjectEx) \
FC_PY_ELEMENT(canAddToSceneGraph) \
FC_PY_ELEMENT(getDropPrefix) \
FC_PY_ELEMENT(replaceObject) \
FC_PY_ELEMENT(getLinkedViewProvider) \
#undef FC_PY_ELEMENT
#define FC_PY_ELEMENT(_name) FC_PY_ELEMENT_DEFINE(_name)
FC_PY_VIEW_OBJECT
#undef FC_PY_ELEMENT
#define FC_PY_ELEMENT(_name) FC_PY_ELEMENT_FLAG(_name)
enum Flag {
FC_PY_VIEW_OBJECT
FlagMax,
};
typedef std::bitset<FlagMax> Flags;
mutable Flags _Flags;
public:
void init(PyObject *pyobj);
};
template <class ViewProviderT>
@@ -111,7 +197,7 @@ public:
/// constructor.
ViewProviderPythonFeatureT() : _attached(false) {
ADD_PROPERTY(Proxy,(Py::Object()));
imp = new ViewProviderPythonFeatureImp(this);
imp = new ViewProviderPythonFeatureImp(this,Proxy);
}
/// destructor.
virtual ~ViewProviderPythonFeatureT() {
@@ -149,6 +235,14 @@ public:
virtual bool useNewSelectionModel() const {
return imp->useNewSelectionModel();
}
virtual bool getElementPicked(const SoPickedPoint *pp, std::string &subname) const {
auto ret = imp->getElementPicked(pp,subname);
if(ret == ViewProviderPythonFeatureImp::NotImplemented)
return ViewProviderT::getElementPicked(pp,subname);
else if(ret == ViewProviderPythonFeatureImp::Accepted)
return true;
return false;
}
virtual std::string getElement(const SoDetail *det) const {
std::string name = imp->getElement(det);
if (!name.empty()) return name;
@@ -159,6 +253,12 @@ public:
if (det) return det;
return ViewProviderT::getDetail(name);
}
virtual bool getDetailPath(const char *name, SoFullPath *path, bool append,SoDetail *&det) const {
auto ret = imp->getDetailPath(name,path,append,det);
if(ret == ViewProviderPythonFeatureImp::NotImplemented)
return ViewProviderT::getDetailPath(name,path,append,det);
return ret == ViewProviderPythonFeatureImp::Accepted;
}
virtual std::vector<Base::Vector3d> getSelectionShape(const char* Element) const {
return ViewProviderT::getSelectionShape(Element);
};
@@ -183,15 +283,27 @@ public:
if (!ok) return ok;
return ViewProviderT::onDelete(sub);
}
virtual bool canDelete(App::DocumentObject *obj) const override {
switch(imp->canDelete(obj)) {
case ViewProviderPythonFeatureImp::Accepted:
return true;
case ViewProviderPythonFeatureImp::Rejected:
return false;
default:
return ViewProviderT::canDelete(obj);
}
}
//@}
/** @name Restoring view provider from document load */
//@{
virtual void startRestoring() {
ViewProviderT::startRestoring();
imp->startRestoring();
}
virtual void finishRestoring() {
imp->finishRestoring();
ViewProviderT::finishRestoring();
}
//@}
@@ -221,6 +333,7 @@ public:
}
/// Starts to drag the object
virtual void dragObject(App::DocumentObject* obj) {
App::AutoTransaction committer;
switch (imp->dragObject(obj)) {
case ViewProviderPythonFeatureImp::Accepted:
case ViewProviderPythonFeatureImp::Rejected:
@@ -253,6 +366,7 @@ public:
}
/// If the dropped object type is accepted the object will be added as child
virtual void dropObject(App::DocumentObject* obj) {
App::AutoTransaction committer;
switch (imp->dropObject(obj)) {
case ViewProviderPythonFeatureImp::Accepted:
case ViewProviderPythonFeatureImp::Rejected:
@@ -261,6 +375,44 @@ public:
return ViewProviderT::dropObject(obj);
}
}
/** Return false to force drop only operation for a give object*/
virtual bool canDragAndDropObject(App::DocumentObject *obj) const override {
switch (imp->canDragAndDropObject(obj)) {
case ViewProviderPythonFeatureImp::Accepted:
return true;
case ViewProviderPythonFeatureImp::Rejected:
return false;
default:
return ViewProviderT::canDragAndDropObject(obj);
}
}
virtual bool canDropObjectEx(App::DocumentObject *obj, App::DocumentObject *owner,
const char *subname, const std::vector<std::string> &elements) const override
{
switch (imp->canDropObjectEx(obj,owner,subname,elements)) {
case ViewProviderPythonFeatureImp::Accepted:
return true;
case ViewProviderPythonFeatureImp::Rejected:
return false;
default:
return ViewProviderT::canDropObjectEx(obj,owner,subname,elements);
}
}
/** Add an object with full quanlified name to the view provider by drag and drop */
virtual std::string dropObjectEx(App::DocumentObject *obj, App::DocumentObject *owner,
const char *subname, const std::vector<std::string> &elements)
{
App::AutoTransaction committer;
std::string ret;
switch (imp->dropObjectEx(obj,owner,subname,elements,ret)) {
case ViewProviderPythonFeatureImp::NotImplemented:
ret = ViewProviderT::dropObjectEx(obj,owner,subname,elements);
break;
default:
break;
}
return ret;
}
//@}
/** @name Display methods */
@@ -290,14 +442,29 @@ public:
}
//@}
virtual bool canRemoveChildrenFromRoot() const override {
switch(imp->canRemoveChildrenFromRoot()) {
case ViewProviderPythonFeatureImp::NotImplemented:
return ViewProviderT::canRemoveChildrenFromRoot();
case ViewProviderPythonFeatureImp::Accepted:
return true;
default:
return false;
}
}
PyObject* getPyObject() {
return ViewProviderT::getPyObject();
}
virtual bool canAddToSceneGraph() const override {
return ViewProviderT::canAddToSceneGraph() && imp->canAddToSceneGraph();
}
protected:
virtual void onChanged(const App::Property* prop) {
if (prop == &Proxy) {
imp->init(Proxy.getValue().ptr());
if (ViewProviderT::pcObject && !Proxy.getValue().is(Py::_None())) {
if (!_attached) {
_attached = true;
@@ -307,6 +474,12 @@ protected:
ViewProviderT::DisplayMode.touch();
ViewProviderT::setOverrideMode(viewerMode);
}
if(!this->testStatus(Gui::isRestoring) &&
ViewProviderT::canAddToSceneGraph() &&
!imp->canAddToSceneGraph())
{
this->getDocument()->toggleInSceneGraph(this);
}
ViewProviderT::updateView();
}
}
@@ -338,6 +511,40 @@ protected:
return ViewProviderT::unsetEdit(ModNum);
}
}
virtual void setEditViewer(View3DInventorViewer *viewer, int ModNum) {
if(!imp->setEditViewer(viewer,ModNum))
ViewProviderT::setEditViewer(viewer,ModNum);
}
virtual void unsetEditViewer(View3DInventorViewer *viewer) {
if(!imp->unsetEditViewer(viewer))
ViewProviderT::unsetEditViewer(viewer);
}
virtual std::string getDropPrefix() const {
std::string prefix;
if(!imp->getDropPrefix(prefix))
return ViewProviderT::getDropPrefix();
return prefix;
}
virtual int replaceObject(App::DocumentObject *oldObj, App::DocumentObject *newObj) {
App::AutoTransaction committer;
switch (imp->replaceObject(oldObj,newObj)) {
case ViewProviderPythonFeatureImp::Accepted:
return 1;
case ViewProviderPythonFeatureImp::Rejected:
return 0;
default:
return ViewProviderT::replaceObject(oldObj,newObj);
}
}
virtual ViewProviderDocumentObject *getLinkedViewProvider(bool recursive=false) const {
auto res = imp->getLinkedViewProvider(recursive);
if(!res)
res = ViewProviderT::getLinkedViewProvider();
return res;
}
public:
virtual void setupContextMenu(QMenu* menu, QObject* recipient, const char* member)
@@ -349,6 +556,7 @@ public:
protected:
virtual bool doubleClicked(void)
{
App::AutoTransaction committer;
switch (imp->doubleClicked()) {
case ViewProviderPythonFeatureImp::Accepted:
return true;