diff --git a/src/Gui/Application.cpp b/src/Gui/Application.cpp index 3082a548f1..2da5437b61 100644 --- a/src/Gui/Application.cpp +++ b/src/Gui/Application.cpp @@ -93,6 +93,7 @@ #include "DocumentRecovery.h" #include "TransactionObject.h" #include "FileDialog.h" +#include "ExpressionBindingPy.h" #include "TextDocumentEditorView.h" #include "SplitView3DInventor.h" @@ -384,6 +385,10 @@ Application::Application(bool GUIenabled) Py_INCREF(pySide->module().ptr()); PyModule_AddObject(module, "PySideUic", pySide->module().ptr()); + ExpressionBindingPy::init_type(); + Base::Interpreter().addType(ExpressionBindingPy::type_object(), + module,"ExpressionBinding"); + //insert Selection module #if PY_MAJOR_VERSION >= 3 static struct PyModuleDef SelectionModuleDef = { diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt index dc0ca11da2..6f3b925a70 100644 --- a/src/Gui/CMakeLists.txt +++ b/src/Gui/CMakeLists.txt @@ -1223,6 +1223,7 @@ SET(FreeCADGui_CPP_SRCS DocumentObserver.cpp DocumentObserverPython.cpp ExpressionBinding.cpp + ExpressionBindingPy.cpp GraphicsViewZoom.cpp ExpressionCompleter.cpp GuiApplication.cpp @@ -1249,7 +1250,8 @@ SET(FreeCADGui_SRCS DocumentModel.h DocumentObserver.h DocumentObserverPython.h - ExpressionBinding.cpp + ExpressionBinding.h + ExpressionBindingPy.h ExpressionCompleter.h FreeCADGuiInit.py GraphicsViewZoom.h diff --git a/src/Gui/ExpressionBindingPy.cpp b/src/Gui/ExpressionBindingPy.cpp new file mode 100644 index 0000000000..6899a59177 --- /dev/null +++ b/src/Gui/ExpressionBindingPy.cpp @@ -0,0 +1,168 @@ +/*************************************************************************** + * Copyright (c) 2020 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 51 Franklin Street, * + * Fifth Floor, Boston, MA 02110-1301, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" +#ifndef _PreComp_ +#endif +#include "ExpressionBindingPy.h" +#include "ExpressionBinding.h" +#include "WidgetFactory.h" +#include "QuantitySpinBox.h" +#include "InputField.h" +#include + +using namespace Gui; + +void ExpressionBindingPy::init_type() +{ + behaviors().name("ExpressionBinding"); + behaviors().doc("Python interface class for ExpressionBinding"); + // you must have overwritten the virtual functions + behaviors().supportRepr(); + behaviors().supportGetattr(); + behaviors().supportSetattr(); + behaviors().set_tp_new(PyMake); + behaviors().readyType(); + + add_varargs_method("bind",&ExpressionBindingPy::bind,"Bind with an expression"); + add_varargs_method("isBound",&ExpressionBindingPy::isBound,"Check if already bound with an expression"); + add_varargs_method("apply",&ExpressionBindingPy::apply,"apply"); + add_varargs_method("hasExpression",&ExpressionBindingPy::hasExpression,"hasExpression"); + add_varargs_method("autoApply",&ExpressionBindingPy::autoApply,"autoApply"); + add_varargs_method("setAutoApply",&ExpressionBindingPy::setAutoApply,"setAutoApply"); +} + +PyObject *ExpressionBindingPy::PyMake(struct _typeobject *, PyObject * args, PyObject *) +{ + Py::Tuple tuple(args); + + ExpressionBinding* expr = nullptr; + PythonWrapper wrap; + wrap.loadWidgetsModule(); + + QWidget* obj = dynamic_cast(wrap.toQObject(tuple.getItem(0))); + if (obj) { + do { + QuantitySpinBox* sb = qobject_cast(obj); + if (sb) { + expr = sb; + break; + } + InputField* le = qobject_cast(obj); + if (le) { + expr = le; + break; + } + } + while(false); + } + + if (!expr) { + PyErr_SetString(PyExc_TypeError, "Wrong type"); + return nullptr; + } + + return new ExpressionBindingPy(expr); +} + +ExpressionBindingPy::ExpressionBindingPy(ExpressionBinding* expr) + : expr(expr) +{ +} + +ExpressionBindingPy::~ExpressionBindingPy() +{ +} + +Py::Object ExpressionBindingPy::repr() +{ + std::stringstream s; + s << ""; + return Py::String(s.str()); +} + +Py::Object ExpressionBindingPy::bind(const Py::Tuple& args) +{ + PyObject* py; + const char* str; + if (!PyArg_ParseTuple(args.ptr(), "O!s", &App::DocumentObjectPy::Type, &py, &str)) + throw Py::Exception(); + + try { + App::DocumentObject* obj = static_cast(py)->getDocumentObjectPtr(); + App::ObjectIdentifier id(App::ObjectIdentifier::parse(obj, str)); + if (!id.getProperty()) { + throw Base::AttributeError("Wrong property"); + } + + expr->bind(id); + return Py::None(); + } + catch (const Base::Exception& e) { + e.setPyException(); + throw Py::Exception(); + } + catch (...) { + throw Py::RuntimeError("Cannot bind to object"); + } +} + +Py::Object ExpressionBindingPy::isBound(const Py::Tuple& args) +{ + if (!PyArg_ParseTuple(args.ptr(), "")) + throw Py::Exception(); + return Py::Boolean(expr->isBound()); +} + +Py::Object ExpressionBindingPy::apply(const Py::Tuple& args) +{ + const char* str; + if (!PyArg_ParseTuple(args.ptr(), "s", &str)) + throw Py::Exception(); + + return Py::Boolean(expr->apply(str)); +} + +Py::Object ExpressionBindingPy::hasExpression(const Py::Tuple& args) +{ + if (!PyArg_ParseTuple(args.ptr(), "")) + throw Py::Exception(); + return Py::Boolean(expr->hasExpression()); +} + +Py::Object ExpressionBindingPy::autoApply(const Py::Tuple& args) +{ + if (!PyArg_ParseTuple(args.ptr(), "")) + throw Py::Exception(); + return Py::Boolean(expr->autoApply()); +} + +Py::Object ExpressionBindingPy::setAutoApply(const Py::Tuple& args) +{ + PyObject* b; + if (!PyArg_ParseTuple(args.ptr(), "O!", &PyBool_Type, &b)) + throw Py::Exception(); + + bool value = PyObject_IsTrue(b) ? true : false; + expr->setAutoApply(value); + return Py::None(); +} diff --git a/src/Gui/ExpressionBindingPy.h b/src/Gui/ExpressionBindingPy.h new file mode 100644 index 0000000000..b02f52a873 --- /dev/null +++ b/src/Gui/ExpressionBindingPy.h @@ -0,0 +1,57 @@ +/*************************************************************************** + * Copyright (c) 2020 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 51 Franklin Street, * + * Fifth Floor, Boston, MA 02110-1301, USA * + * * + ***************************************************************************/ + +#ifndef EXPRESSIONBINDINGPY_H +#define EXPRESSIONBINDINGPY_H + +#include + +namespace Gui { +class ExpressionBinding; + +class ExpressionBindingPy : public Py::PythonExtension +{ +public: + static void init_type(void); // announce properties and methods + + ExpressionBindingPy(ExpressionBinding*); + ~ExpressionBindingPy(); + + Py::Object repr(); + + Py::Object bind(const Py::Tuple&); + Py::Object isBound(const Py::Tuple&); + Py::Object apply(const Py::Tuple&); + Py::Object hasExpression(const Py::Tuple&); + Py::Object autoApply(const Py::Tuple&); + Py::Object setAutoApply(const Py::Tuple&); + +private: + static PyObject *PyMake(struct _typeobject *, PyObject *, PyObject *); + +private: + ExpressionBinding* expr; +}; + +} + +#endif // EXPRESSIONBINDING_H