Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/ElmerGUI/PythonQt/src/PythonQtWrapper.cpp
3206 views
1
/*
2
*
3
* Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
4
*
5
* This library is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU Lesser General Public
7
* License as published by the Free Software Foundation; either
8
* version 2.1 of the License, or (at your option) any later version.
9
*
10
* This library is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* Lesser General Public License for more details.
14
*
15
* Further, this software is distributed without any warranty that it is
16
* free of the rightful claim of any third person regarding infringement
17
* or the like. Any license provided herein, whether implied or
18
* otherwise, applies only to this software file. Patent licenses, if
19
* any, provided herein do not apply to combinations of this program with
20
* other software, or any other product whatsoever.
21
*
22
* You should have received a copy of the GNU Lesser General Public
23
* License along with this library; if not, write to the Free Software
24
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
*
26
* Contact information: MeVis Research GmbH, Universitaetsallee 29,
27
* 28359 Bremen, Germany or:
28
*
29
* http://www.mevis.de
30
*
31
*/
32
33
//----------------------------------------------------------------------------------
34
/*!
35
// \file PythonQtWrapper.cpp
36
// \author Florian Link
37
// \author Last changed by $Author: florian $
38
// \date 2006-05
39
*/
40
//----------------------------------------------------------------------------------
41
42
#include "PythonQtWrapper.h"
43
#include <QObject>
44
#include "PythonQt.h"
45
#include "PythonQtSlot.h"
46
#include "PythonQtClassInfo.h"
47
#include "PythonQtConversion.h"
48
49
static void PythonQtWrapper_dealloc(PythonQtWrapper* self)
50
{
51
if (self->_wrappedPtr) {
52
53
//mlabDebugConst("Python","c++ wrapper removed " << self->_wrappedPtr << " " << self->_obj->className() << " " << self->_info->wrappedClassName().latin1());
54
55
PythonQt::priv()->removeWrapperPointer(self->_wrappedPtr);
56
// we own our qobject, so we delete it now:
57
delete self->_obj;
58
self->_obj = NULL;
59
if (self->_ownedByPythonQt) {
60
PythonQtSlotInfo* slot = PythonQt::priv()->getDestructorSlot(self->_info->wrappedCPPClassName());
61
if (slot) {
62
void* args[2];
63
args[0] = NULL;
64
args[1] = &self->_wrappedPtr;
65
slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, slot->slotIndex(), args);
66
self->_wrappedPtr = NULL;
67
} else {
68
// TODO: print a warning? we can not destroy that object
69
}
70
}
71
} else if (self->_obj) {
72
//mlabDebugConst("Python","qobject wrapper removed " << self->_obj->className() << " " << self->_info->wrappedClassName().latin1());
73
PythonQt::priv()->removeWrapperPointer(self->_obj);
74
if (self->_ownedByPythonQt) {
75
if (!self->_obj->parent()) {
76
delete self->_obj;
77
self->_obj = NULL;
78
}
79
}
80
}
81
self->ob_type->tp_free((PyObject*)self);
82
}
83
84
static PyObject* PythonQtWrapper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
85
{
86
PythonQtWrapper *self;
87
88
self = (PythonQtWrapper *)type->tp_alloc(type, 0);
89
if (self != NULL) {
90
self->_info = NULL;
91
self->_obj = NULL;
92
self->_wrappedPtr = NULL;
93
self->_ownedByPythonQt = false;
94
}
95
return (PyObject *)self;
96
}
97
98
static int PythonQtWrapper_init(PythonQtWrapper *self, PyObject *args, PyObject *kwds)
99
{
100
return 0;
101
}
102
103
static PyObject *PythonQtWrapper_classname(PythonQtWrapper* type)
104
{
105
return PyString_FromString(type->_info->className());
106
}
107
108
static PyObject *PythonQtWrapper_help(PythonQtWrapper* type)
109
{
110
return PythonQt::self()->helpCalled(type->_info);
111
}
112
113
114
static PyMethodDef PythonQtWrapper_methods[] = {
115
{"className", (PyCFunction)PythonQtWrapper_classname, METH_NOARGS,
116
"Return the classname of the object"
117
},
118
{"help", (PyCFunction)PythonQtWrapper_help, METH_NOARGS,
119
"Shows the help of available methods for this class"
120
},
121
{NULL} /* Sentinel */
122
};
123
124
125
static PyObject *PythonQtWrapper_getattro(PyObject *obj,PyObject *name)
126
{
127
const char *attributeName;
128
PythonQtWrapper *wt = (PythonQtWrapper *)obj;
129
130
if ((attributeName = PyString_AsString(name)) == NULL) {
131
return NULL;
132
}
133
134
if (!wt->_obj && !wt->_wrappedPtr) {
135
QString error = QString("Trying to read attribute '") + attributeName + "' from a destroyed " + wt->_info->className() + " object";
136
PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
137
return NULL;
138
}
139
140
// mlabDebugConst("Python","get " << attributeName);
141
142
// TODO: dynamic properties are missing
143
144
PythonQtMemberInfo member = wt->_info->member(attributeName);
145
switch (member._type) {
146
case PythonQtMemberInfo::Property:
147
if (wt->_obj) {
148
return PythonQtConv::QVariantToPyObject(member._property.read(wt->_obj));
149
}
150
break;
151
case PythonQtMemberInfo::Slot:
152
return PythonQtSlotFunction_New(member._slot, obj, NULL);
153
break;
154
case PythonQtMemberInfo::EnumValue:
155
return PyInt_FromLong(member._enumValue);
156
break;
157
}
158
159
// look for the internal methods (className(), help())
160
PyObject* internalMethod = Py_FindMethod( PythonQtWrapper_methods, obj, (char*)attributeName);
161
if (internalMethod) {
162
return internalMethod;
163
}
164
PyErr_Clear();
165
166
if (wt->_obj) {
167
// look for a child
168
QObjectList children = wt->_obj->children();
169
for (int i = 0; i < children.count(); i++) {
170
QObject *child = children.at(i);
171
if (child->objectName() == attributeName) {
172
return PythonQt::self()->priv()->wrapQObject(child);
173
}
174
}
175
}
176
177
if (qstrcmp(attributeName, "__dict__")==0) {
178
QStringList l = wt->_info->memberList(false);
179
PyObject* dict = PyDict_New();
180
foreach (QString name, l) {
181
//PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
182
PyDict_SetItemString(dict, name.toLatin1().data(), Py_None);
183
//Py_DECREF(o);
184
}
185
// Note: we do not put children into the dict, is would look confusing?!
186
return dict;
187
}
188
189
190
QString error = QString(wt->_info->className()) + " has no attribute named '" + QString(attributeName) + "'";
191
PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
192
return NULL;
193
}
194
195
static int PythonQtWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
196
{
197
QString error;
198
char *attributeName;
199
PythonQtWrapper *wt = (PythonQtWrapper *)obj;
200
201
if ((attributeName = PyString_AsString(name)) == NULL)
202
return -1;
203
204
if (!wt->_obj) {
205
error = QString("Trying to set attribute '") + attributeName + "' on a destroyed " + wt->_info->className() + " object";
206
PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
207
return -1;
208
}
209
210
PythonQtMemberInfo member = wt->_info->member(attributeName);
211
if (member._type == PythonQtMemberInfo::Property) {
212
QMetaProperty prop = member._property;
213
if (prop.isWritable()) {
214
QVariant v;
215
if (prop.isEnumType()) {
216
// this will give us either a string or an int, everything else will probably be an error
217
v = PythonQtConv::PyObjToQVariant(value);
218
} else {
219
int t = prop.userType();
220
v = PythonQtConv::PyObjToQVariant(value, t);
221
}
222
bool success = false;
223
if (v.isValid()) {
224
success = prop.write(wt->_obj, v);
225
}
226
if (success) {
227
return 0;
228
} else {
229
error = QString("Property '") + attributeName + "' of type '" +
230
prop.typeName() + "' does not accept an object of type "
231
+ QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
232
}
233
} else {
234
error = QString("Property '") + attributeName + "' of " + wt->_info->className() + " object is not writable";
235
}
236
} else {
237
if (member._type == PythonQtMemberInfo::Slot) {
238
error = QString("Slot '") + attributeName + "' can not be overwritten on " + wt->_info->className() + " object";
239
} else if (member._type == PythonQtMemberInfo::EnumValue) {
240
error = QString("EnumValue '") + attributeName + "' can not be overwritten on " + wt->_info->className() + " object";
241
}
242
}
243
244
PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
245
return -1;
246
}
247
248
static PyObject * PythonQtWrapper_repr(PyObject * obj)
249
{
250
PythonQtWrapper* wt = (PythonQtWrapper*)obj;
251
if (wt->_wrappedPtr) {
252
if (wt->_obj) {
253
return PyString_FromFormat("%s (C++ Object 0x%x wrapped by %s 0x%x))", wt->_info->className(), wt->_wrappedPtr, wt->_obj->metaObject()->className(), wt->_obj);
254
} else {
255
return PyString_FromFormat("%s (C++ Object 0x%x unwrapped)", wt->_info->className(), wt->_wrappedPtr);
256
}
257
} else {
258
return PyString_FromFormat("%s (QObject 0x%x)", wt->_info->className(), wt->_obj, wt->_wrappedPtr);
259
}
260
}
261
262
static int PythonQtWrapper_compare(PyObject * obj1, PyObject * obj2)
263
{
264
if (obj1->ob_type == &PythonQtWrapper_Type &&
265
obj2->ob_type == &PythonQtWrapper_Type) {
266
267
PythonQtWrapper* w1 = (PythonQtWrapper*)obj1;
268
PythonQtWrapper* w2 = (PythonQtWrapper*)obj2;
269
if (w1->_wrappedPtr != NULL) {
270
if (w1->_wrappedPtr == w1->_wrappedPtr) {
271
return 0;
272
} else {
273
return -1;
274
}
275
} else if (w1->_obj == w2->_obj) {
276
return 0;
277
} else {
278
return -1;
279
}
280
} else {
281
return -1;
282
}
283
}
284
285
static int PythonQtWrapper_nonzero(PyObject *obj)
286
{
287
PythonQtWrapper* wt = (PythonQtWrapper*)obj;
288
return (wt->_wrappedPtr == NULL && wt->_obj == NULL)?0:1;
289
}
290
291
// we override nb_nonzero, so that one can do 'if' expressions to test for a NULL ptr
292
static PyNumberMethods PythonQtWrapper_as_number = {
293
0, /* nb_add */
294
0, /* nb_subtract */
295
0, /* nb_multiply */
296
0, /* nb_divide */
297
0, /* nb_remainder */
298
0, /* nb_divmod */
299
0, /* nb_power */
300
0, /* nb_negative */
301
0, /* nb_positive */
302
0, /* nb_absolute */
303
PythonQtWrapper_nonzero, /* nb_nonzero */
304
0, /* nb_invert */
305
0, /* nb_lshift */
306
0, /* nb_rshift */
307
0, /* nb_and */
308
0, /* nb_xor */
309
0, /* nb_or */
310
0, /* nb_coerce */
311
0, /* nb_int */
312
0, /* nb_long */
313
0, /* nb_float */
314
0, /* nb_oct */
315
0, /* nb_hex */
316
0, /* nb_inplace_add */
317
0, /* nb_inplace_subtract */
318
0, /* nb_inplace_multiply */
319
0, /* nb_inplace_divide */
320
0, /* nb_inplace_remainder */
321
0, /* nb_inplace_power */
322
0, /* nb_inplace_lshift */
323
0, /* nb_inplace_rshift */
324
0, /* nb_inplace_and */
325
0, /* nb_inplace_xor */
326
0, /* nb_inplace_or */
327
0, /* nb_floor_divide */
328
0, /* nb_true_divide */
329
0, /* nb_inplace_floor_divide */
330
0, /* nb_inplace_true_divide */
331
};
332
333
PyTypeObject PythonQtWrapper_Type = {
334
PyObject_HEAD_INIT(NULL)
335
0, /*ob_size*/
336
"PythonQt.PythonQtWrapper", /*tp_name*/
337
sizeof(PythonQtWrapper), /*tp_basicsize*/
338
0, /*tp_itemsize*/
339
(destructor)PythonQtWrapper_dealloc, /*tp_dealloc*/
340
0, /*tp_print*/
341
0, /*tp_getattr*/
342
0, /*tp_setattr*/
343
PythonQtWrapper_compare, /*tp_compare*/
344
PythonQtWrapper_repr, /*tp_repr*/
345
&PythonQtWrapper_as_number, /*tp_as_number*/
346
0, /*tp_as_sequence*/
347
0, /*tp_as_mapping*/
348
0, /*tp_hash */
349
0, /*tp_call*/
350
0, /*tp_str*/
351
PythonQtWrapper_getattro, /*tp_getattro*/
352
PythonQtWrapper_setattro, /*tp_setattro*/
353
0, /*tp_as_buffer*/
354
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
355
"PythonQtWrapper object", /* tp_doc */
356
0, /* tp_traverse */
357
0, /* tp_clear */
358
0, /* tp_richcompare */
359
0, /* tp_weaklistoffset */
360
0, /* tp_iter */
361
0, /* tp_iternext */
362
0, /* tp_methods */
363
0, /* tp_members */
364
0, /* tp_getset */
365
0, /* tp_base */
366
0, /* tp_dict */
367
0, /* tp_descr_get */
368
0, /* tp_descr_set */
369
0, /* tp_dictoffset */
370
(initproc)PythonQtWrapper_init, /* tp_init */
371
0, /* tp_alloc */
372
PythonQtWrapper_new, /* tp_new */
373
};
374
375
//-------------------------------------------------------
376
377
378