From a1e049bc8a687c52d82baa6e96d2f31d2a3f5862 Mon Sep 17 00:00:00 2001 From: wmayer Date: Thu, 3 Apr 2014 13:57:57 +0200 Subject: [PATCH] + extend Python API of selection gate --- src/Gui/Selection.cpp | 71 +++++++++++++++++++++--------------- src/Gui/SelectionFilter.cpp | 72 +++++++++++++++++++++++++++++++++++-- src/Gui/SelectionFilter.h | 37 ++++++++++++++++++- src/Gui/SelectionObject.cpp | 15 -------- 4 files changed, 148 insertions(+), 47 deletions(-) diff --git a/src/Gui/Selection.cpp b/src/Gui/Selection.cpp index a8d078b42..05a62ed45 100644 --- a/src/Gui/Selection.cpp +++ b/src/Gui/Selection.cpp @@ -907,7 +907,6 @@ SelectionSingleton::~SelectionSingleton() { } - SelectionSingleton* SelectionSingleton::_pcSingleton = NULL; SelectionSingleton& SelectionSingleton::instance(void) @@ -923,21 +922,6 @@ void SelectionSingleton::destruct (void) delete _pcSingleton; _pcSingleton = 0; } -/* -void SelectionSingleton::addObject(App::DocumentObject *f) -{ - _ObjectSet.insert(f); - -} - -void SelectionSingleton::removeObject(App::DocumentObject *f) -{ - _ObjectSet.erase(f); - - -} -*/ - //************************************************************************** // Python stuff @@ -977,13 +961,25 @@ PyMethodDef SelectionSingleton::Methods[] = { {"removeObserver", (PyCFunction) SelectionSingleton::sRemSelObserver, 1, "removeObserver(Object) -- Uninstall an observer\n"}, {"addSelectionGate", (PyCFunction) SelectionSingleton::sAddSelectionGate, 1, - "addSelectionGate(String) -- activate the selection gate.\n" - "The selection gate will prohibit all selections which do not match\n" - "the given selection filter string. Examples strings are:\n" - "'SELECT Part::Feature SUBELEMENT Edge',\n" - "'SELECT Robot::RobotObject'\n"}, + "addSelectionGate(String|Filter|Gate) -- activate the selection gate.\n" + "The selection gate will prohibit all selections which do not match\n" + "the given selection filter string.\n" + " Examples strings are:\n" + "'SELECT Part::Feature SUBELEMENT Edge',\n" + "'SELECT Robot::RobotObject'\n" + "\n" + "You can also set an instance of SelectionFilter:\n" + "filter = Gui.Selection.Filter('SELECT Part::Feature SUBELEMENT Edge')\n" + "Gui.Selection.addSelectionGate(filter)\n" + "\n" + "And the most flexible approach is to write your own selection gate class\n" + "that implements the method 'allow'\n" + "class Gate:\n" + " def allow(self,doc,obj,sub):\n" + " return (sub[0:4] == 'Face')\n" + "Gui.Selection.addSelectionGate(Gate())"}, {"removeSelectionGate", (PyCFunction) SelectionSingleton::sRemoveSelectionGate, 1, - "removeSelectionGate() -- remove the active slection gate\n"}, + "removeSelectionGate() -- remove the active selection gate\n"}, {NULL, NULL, 0, NULL} /* Sentinel */ }; @@ -1167,14 +1163,33 @@ PyObject *SelectionSingleton::sRemSelObserver(PyObject * /*self*/, PyObject *arg PyObject *SelectionSingleton::sAddSelectionGate(PyObject * /*self*/, PyObject *args, PyObject * /*kwd*/) { char* filter; - if (!PyArg_ParseTuple(args, "s",&filter)) - return NULL; // NULL triggers exception + if (PyArg_ParseTuple(args, "s",&filter)) { + PY_TRY { + Selection().addSelectionGate(new SelectionFilterGate(filter)); + Py_Return; + } PY_CATCH; + } - PY_TRY { - Selection().addSelectionGate(new SelectionFilterGate(filter)); - } PY_CATCH; + PyErr_Clear(); + PyObject* filterPy; + if (PyArg_ParseTuple(args, "O!",SelectionFilterPy::type_object(),&filterPy)) { + PY_TRY { + Selection().addSelectionGate(new SelectionFilterGatePython(static_cast(filterPy))); + Py_Return; + } PY_CATCH; + } - Py_Return; + PyErr_Clear(); + PyObject* gate; + if (PyArg_ParseTuple(args, "O",&gate)) { + PY_TRY { + Selection().addSelectionGate(new SelectionGatePython(Py::Object(gate, false))); + Py_Return; + } PY_CATCH; + } + + PyErr_SetString(PyExc_ValueError, "Argument is neither string nor SelectionFiler nor SelectionGate"); + return 0; } PyObject *SelectionSingleton::sRemoveSelectionGate(PyObject * /*self*/, PyObject *args, PyObject * /*kwd*/) diff --git a/src/Gui/SelectionFilter.cpp b/src/Gui/SelectionFilter.cpp index d13f89177..8d2cbbf35 100644 --- a/src/Gui/SelectionFilter.cpp +++ b/src/Gui/SelectionFilter.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include "Selection.h" #include "SelectionFilter.h" @@ -73,6 +74,63 @@ bool SelectionFilterGate::allow(App::Document*pDoc,App::DocumentObject*pObj, con // ---------------------------------------------------------------------------- +SelectionGatePython::SelectionGatePython(const Py::Object& obj) + : gate(obj) +{ +} + +SelectionGatePython::~SelectionGatePython() +{ +} + +bool SelectionGatePython::allow(App::Document* doc, App::DocumentObject* obj, const char* sub) +{ + Base::PyGILStateLocker lock; + try { + if (this->gate.hasAttr(std::string("allow"))) { + Py::Callable method(this->gate.getAttr(std::string("allow"))); + Py::Object pyDoc = Py::asObject(doc->getPyObject()); + Py::Object pyObj = Py::asObject(obj->getPyObject()); + Py::String pySub; + if (sub) + pySub = std::string(sub); + Py::Tuple args(3); + args.setItem(0, pyDoc); + args.setItem(1, pyObj); + args.setItem(2, pySub); + Py::Boolean ok(method.apply(args)); + return (bool)ok; + } + } + catch (Py::Exception&) { + Base::PyException e; // extract the Python error text + e.ReportException(); + } + + return true; +} + +// ---------------------------------------------------------------------------- + +SelectionFilterGatePython::SelectionFilterGatePython(SelectionFilterPy* obj) : filter(obj) +{ + Base::PyGILStateLocker lock; + Py_INCREF(filter); +} + +SelectionFilterGatePython::~SelectionFilterGatePython() +{ + Base::PyGILStateLocker lock; + Py_DECREF(filter); +} + +bool SelectionFilterGatePython::allow(App::Document*, App::DocumentObject* obj, const char* sub) +{ + return filter->filter.test(obj, sub); +} + +// ---------------------------------------------------------------------------- + SelectionFilter::SelectionFilter(const char* filter) : Ast(0) { @@ -185,6 +243,7 @@ void SelectionFilterPy::init_type() add_varargs_method("match",&SelectionFilterPy::match,"match()"); add_varargs_method("result",&SelectionFilterPy::result,"result()"); add_varargs_method("test",&SelectionFilterPy::test,"test()"); + add_varargs_method("setFilter",&SelectionFilterPy::setFilter,"setFilter()"); } PyObject *SelectionFilterPy::PyMake(struct _typeobject *, PyObject *args, PyObject *) @@ -219,7 +278,7 @@ Py::Object SelectionFilterPy::match(const Py::Tuple& args) Py::Object SelectionFilterPy::test(const Py::Tuple& args) { - PyObject * pcObj ; + PyObject * pcObj; char* text=0; if (!PyArg_ParseTuple(args.ptr(), "O!|s",&(App::DocumentObjectPy::Type),&pcObj,&text)) throw Py::Exception(); @@ -238,14 +297,21 @@ Py::Object SelectionFilterPy::result(const Py::Tuple&) Py::Tuple tuple(it->size()); int index=0; for (jt = it->begin(); jt != it->end(); ++jt) { - tuple[index++] = Py::asObject(jt->getObject()->getPyObject()); + tuple[index++] = Py::asObject(jt->getPyObject()); } list.append(tuple); } return list; } - +Py::Object SelectionFilterPy::setFilter(const Py::Tuple& args) +{ + char* text=0; + if (!PyArg_ParseTuple(args.ptr(), "s",&text)) + throw Py::Exception(); + filter.setFilter(text); + return Py::None(); +} // === Parser & Scanner stuff =============================================== diff --git a/src/Gui/SelectionFilter.h b/src/Gui/SelectionFilter.h index 77e3395d6..1b7a485da 100644 --- a/src/Gui/SelectionFilter.h +++ b/src/Gui/SelectionFilter.h @@ -109,6 +109,23 @@ protected: SelectionFilter *Filter; }; +/** + * A wrapper around a Python class that implements the SelectionGate interface + * @author Werner Mayer + */ +class SelectionGatePython : public SelectionGate +{ +public: + /// Constructor + SelectionGatePython(const Py::Object& obj); + virtual ~SelectionGatePython(); + + bool allow(App::Document*, App::DocumentObject*, const char*); + +private: + Py::Object gate; +}; + /** * Python binding for SelectionFilter class. * @see SelectionFilter @@ -116,7 +133,7 @@ protected: */ class SelectionFilterPy : public Py::PythonExtension { -private: +public: SelectionFilter filter; public: @@ -129,11 +146,29 @@ public: Py::Object match(const Py::Tuple&); Py::Object result(const Py::Tuple&); Py::Object test(const Py::Tuple&); + Py::Object setFilter(const Py::Tuple&); private: static PyObject *PyMake(struct _typeobject *, PyObject *, PyObject *); }; +/** + * A Python wrapper around SelectionFilterPy to implement the SelectionGate interface + * @author Werner Mayer + */ +class SelectionFilterGatePython : public SelectionGate +{ +public: + /// Constructor + SelectionFilterGatePython(SelectionFilterPy* obj); + virtual ~SelectionFilterGatePython(); + + bool allow(App::Document*, App::DocumentObject*, const char*); + +private: + SelectionFilterPy* filter; +}; + // === Abstract syntax tree (AST) =========================================== struct Node_Slice diff --git a/src/Gui/SelectionObject.cpp b/src/Gui/SelectionObject.cpp index 85fb22e6b..f055e7d8d 100644 --- a/src/Gui/SelectionObject.cpp +++ b/src/Gui/SelectionObject.cpp @@ -43,21 +43,6 @@ SelectionObject::SelectionObject() { } -//SelectionObject::SelectionObject( const Gui::SelectionSingleton::SelObj &Obj ) -//{ -// // moving the information over -// // no pointer is copied, cause is to dangerous to keep pointers to -// // the document outside.... -// DocName = Obj.DocName; -// FeatName = Obj.FeatName; -// SubName = Obj.SubName; -// TypeName = Obj.TypeName; -// x = Obj.x; -// y = Obj.y; -// z = Obj.z; -// -//} - SelectionObject::~SelectionObject() { }