Skip to content

Commit ce3eadf

Browse files
committed
Gui: [skip ci] implement Python wrapper for ExpressionBinding
1 parent e21342d commit ce3eadf

File tree

4 files changed

+233
-1
lines changed

4 files changed

+233
-1
lines changed

src/Gui/Application.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
#include "DocumentRecovery.h"
9494
#include "TransactionObject.h"
9595
#include "FileDialog.h"
96+
#include "ExpressionBindingPy.h"
9697

9798
#include "TextDocumentEditorView.h"
9899
#include "SplitView3DInventor.h"
@@ -384,6 +385,10 @@ Application::Application(bool GUIenabled)
384385
Py_INCREF(pySide->module().ptr());
385386
PyModule_AddObject(module, "PySideUic", pySide->module().ptr());
386387

388+
ExpressionBindingPy::init_type();
389+
Base::Interpreter().addType(ExpressionBindingPy::type_object(),
390+
module,"ExpressionBinding");
391+
387392
//insert Selection module
388393
#if PY_MAJOR_VERSION >= 3
389394
static struct PyModuleDef SelectionModuleDef = {

src/Gui/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1223,6 +1223,7 @@ SET(FreeCADGui_CPP_SRCS
12231223
DocumentObserver.cpp
12241224
DocumentObserverPython.cpp
12251225
ExpressionBinding.cpp
1226+
ExpressionBindingPy.cpp
12261227
GraphicsViewZoom.cpp
12271228
ExpressionCompleter.cpp
12281229
GuiApplication.cpp
@@ -1249,7 +1250,8 @@ SET(FreeCADGui_SRCS
12491250
DocumentModel.h
12501251
DocumentObserver.h
12511252
DocumentObserverPython.h
1252-
ExpressionBinding.cpp
1253+
ExpressionBinding.h
1254+
ExpressionBindingPy.h
12531255
ExpressionCompleter.h
12541256
FreeCADGuiInit.py
12551257
GraphicsViewZoom.h

src/Gui/ExpressionBindingPy.cpp

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
/***************************************************************************
2+
* Copyright (c) 2020 Werner Mayer <wmayer[at]users.sourceforge.net> *
3+
* *
4+
* This file is part of the FreeCAD CAx development system. *
5+
* *
6+
* This library is free software; you can redistribute it and/or *
7+
* modify it under the terms of the GNU Library General Public *
8+
* License as published by the Free Software Foundation; either *
9+
* version 2 of the License, or (at your option) any later version. *
10+
* *
11+
* This library is distributed in the hope that it will be useful, *
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14+
* GNU Library General Public License for more details. *
15+
* *
16+
* You should have received a copy of the GNU Library General Public *
17+
* License along with this library; see the file COPYING.LIB. If not, *
18+
* write to the Free Software Foundation, Inc., 51 Franklin Street, *
19+
* Fifth Floor, Boston, MA 02110-1301, USA *
20+
* *
21+
***************************************************************************/
22+
23+
#include "PreCompiled.h"
24+
#ifndef _PreComp_
25+
#endif
26+
#include "ExpressionBindingPy.h"
27+
#include "ExpressionBinding.h"
28+
#include "WidgetFactory.h"
29+
#include "QuantitySpinBox.h"
30+
#include "InputField.h"
31+
#include <App/DocumentObjectPy.h>
32+
33+
using namespace Gui;
34+
35+
void ExpressionBindingPy::init_type()
36+
{
37+
behaviors().name("ExpressionBinding");
38+
behaviors().doc("Python interface class for ExpressionBinding");
39+
// you must have overwritten the virtual functions
40+
behaviors().supportRepr();
41+
behaviors().supportGetattr();
42+
behaviors().supportSetattr();
43+
behaviors().set_tp_new(PyMake);
44+
behaviors().readyType();
45+
46+
add_varargs_method("bind",&ExpressionBindingPy::bind,"Bind with an expression");
47+
add_varargs_method("isBound",&ExpressionBindingPy::isBound,"Check if already bound with an expression");
48+
add_varargs_method("apply",&ExpressionBindingPy::apply,"apply");
49+
add_varargs_method("hasExpression",&ExpressionBindingPy::hasExpression,"hasExpression");
50+
add_varargs_method("autoApply",&ExpressionBindingPy::autoApply,"autoApply");
51+
add_varargs_method("setAutoApply",&ExpressionBindingPy::setAutoApply,"setAutoApply");
52+
}
53+
54+
PyObject *ExpressionBindingPy::PyMake(struct _typeobject *, PyObject * args, PyObject *)
55+
{
56+
Py::Tuple tuple(args);
57+
58+
ExpressionBinding* expr = nullptr;
59+
PythonWrapper wrap;
60+
wrap.loadWidgetsModule();
61+
62+
QWidget* obj = dynamic_cast<QWidget*>(wrap.toQObject(tuple.getItem(0)));
63+
if (obj) {
64+
do {
65+
QuantitySpinBox* sb = qobject_cast<QuantitySpinBox*>(obj);
66+
if (sb) {
67+
expr = sb;
68+
break;
69+
}
70+
InputField* le = qobject_cast<InputField*>(obj);
71+
if (le) {
72+
expr = le;
73+
break;
74+
}
75+
}
76+
while(false);
77+
}
78+
79+
if (!expr) {
80+
PyErr_SetString(PyExc_TypeError, "Wrong type");
81+
return nullptr;
82+
}
83+
84+
return new ExpressionBindingPy(expr);
85+
}
86+
87+
ExpressionBindingPy::ExpressionBindingPy(ExpressionBinding* expr)
88+
: expr(expr)
89+
{
90+
}
91+
92+
ExpressionBindingPy::~ExpressionBindingPy()
93+
{
94+
}
95+
96+
Py::Object ExpressionBindingPy::repr()
97+
{
98+
std::stringstream s;
99+
s << "<ExpressionBinding at " << this << ">";
100+
return Py::String(s.str());
101+
}
102+
103+
Py::Object ExpressionBindingPy::bind(const Py::Tuple& args)
104+
{
105+
PyObject* py;
106+
const char* str;
107+
if (!PyArg_ParseTuple(args.ptr(), "O!s", &App::DocumentObjectPy::Type, &py, &str))
108+
throw Py::Exception();
109+
110+
try {
111+
App::DocumentObject* obj = static_cast<App::DocumentObjectPy*>(py)->getDocumentObjectPtr();
112+
App::ObjectIdentifier id(App::ObjectIdentifier::parse(obj, str));
113+
if (!id.getProperty()) {
114+
throw Base::AttributeError("Wrong property");
115+
}
116+
117+
expr->bind(id);
118+
return Py::None();
119+
}
120+
catch (const Base::Exception& e) {
121+
e.setPyException();
122+
throw Py::Exception();
123+
}
124+
catch (...) {
125+
throw Py::RuntimeError("Cannot bind to object");
126+
}
127+
}
128+
129+
Py::Object ExpressionBindingPy::isBound(const Py::Tuple& args)
130+
{
131+
if (!PyArg_ParseTuple(args.ptr(), ""))
132+
throw Py::Exception();
133+
return Py::Boolean(expr->isBound());
134+
}
135+
136+
Py::Object ExpressionBindingPy::apply(const Py::Tuple& args)
137+
{
138+
const char* str;
139+
if (!PyArg_ParseTuple(args.ptr(), "s", &str))
140+
throw Py::Exception();
141+
142+
return Py::Boolean(expr->apply(str));
143+
}
144+
145+
Py::Object ExpressionBindingPy::hasExpression(const Py::Tuple& args)
146+
{
147+
if (!PyArg_ParseTuple(args.ptr(), ""))
148+
throw Py::Exception();
149+
return Py::Boolean(expr->hasExpression());
150+
}
151+
152+
Py::Object ExpressionBindingPy::autoApply(const Py::Tuple& args)
153+
{
154+
if (!PyArg_ParseTuple(args.ptr(), ""))
155+
throw Py::Exception();
156+
return Py::Boolean(expr->autoApply());
157+
}
158+
159+
Py::Object ExpressionBindingPy::setAutoApply(const Py::Tuple& args)
160+
{
161+
PyObject* b;
162+
if (!PyArg_ParseTuple(args.ptr(), "O!", &PyBool_Type, &b))
163+
throw Py::Exception();
164+
165+
bool value = PyObject_IsTrue(b) ? true : false;
166+
expr->setAutoApply(value);
167+
return Py::None();
168+
}

src/Gui/ExpressionBindingPy.h

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/***************************************************************************
2+
* Copyright (c) 2020 Werner Mayer <wmayer[at]users.sourceforge.net> *
3+
* *
4+
* This file is part of the FreeCAD CAx development system. *
5+
* *
6+
* This library is free software; you can redistribute it and/or *
7+
* modify it under the terms of the GNU Library General Public *
8+
* License as published by the Free Software Foundation; either *
9+
* version 2 of the License, or (at your option) any later version. *
10+
* *
11+
* This library is distributed in the hope that it will be useful, *
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14+
* GNU Library General Public License for more details. *
15+
* *
16+
* You should have received a copy of the GNU Library General Public *
17+
* License along with this library; see the file COPYING.LIB. If not, *
18+
* write to the Free Software Foundation, Inc., 51 Franklin Street, *
19+
* Fifth Floor, Boston, MA 02110-1301, USA *
20+
* *
21+
***************************************************************************/
22+
23+
#ifndef EXPRESSIONBINDINGPY_H
24+
#define EXPRESSIONBINDINGPY_H
25+
26+
#include <CXX/Extensions.hxx>
27+
28+
namespace Gui {
29+
class ExpressionBinding;
30+
31+
class ExpressionBindingPy : public Py::PythonExtension<ExpressionBindingPy>
32+
{
33+
public:
34+
static void init_type(void); // announce properties and methods
35+
36+
ExpressionBindingPy(ExpressionBinding*);
37+
~ExpressionBindingPy();
38+
39+
Py::Object repr();
40+
41+
Py::Object bind(const Py::Tuple&);
42+
Py::Object isBound(const Py::Tuple&);
43+
Py::Object apply(const Py::Tuple&);
44+
Py::Object hasExpression(const Py::Tuple&);
45+
Py::Object autoApply(const Py::Tuple&);
46+
Py::Object setAutoApply(const Py::Tuple&);
47+
48+
private:
49+
static PyObject *PyMake(struct _typeobject *, PyObject *, PyObject *);
50+
51+
private:
52+
ExpressionBinding* expr;
53+
};
54+
55+
}
56+
57+
#endif // EXPRESSIONBINDING_H

0 commit comments

Comments
 (0)