Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/ElmerGUI/PythonQt/src/PythonQtClassInfo.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 PythonQt.cpp
36
// \author Florian Link
37
// \author Last changed by $Author: florian $
38
// \date 2006-05
39
*/
40
//----------------------------------------------------------------------------------
41
42
#include "PythonQtClassInfo.h"
43
#include "PythonQtMethodInfo.h"
44
#include "PythonQt.h"
45
#include <QMetaMethod>
46
47
QHash<QByteArray, int> PythonQtMethodInfo::_parameterTypeDict;
48
49
PythonQtClassInfo::PythonQtClassInfo(const QMetaObject* meta, const QByteArray& wrappedClassName) {
50
_meta = meta;
51
_wrappedClassName = wrappedClassName;
52
_constructors = NULL;
53
}
54
55
PythonQtClassInfo::~PythonQtClassInfo()
56
{
57
QHashIterator<QByteArray, PythonQtMemberInfo> i(_cachedMembers);
58
while (i.hasNext()) {
59
PythonQtMemberInfo member = i.next().value();
60
if (member._type== PythonQtMemberInfo::Slot) {
61
PythonQtSlotInfo* info = member._slot;
62
while (info) {
63
PythonQtSlotInfo* next = info->nextInfo();
64
delete info;
65
info = next;
66
}
67
}
68
}
69
}
70
71
int PythonQtClassInfo::findCharOffset(const char* sigStart, char someChar)
72
{
73
const char* sigEnd = sigStart;
74
char c;
75
do {
76
c = *sigEnd++;
77
} while (c!=someChar && c!=0);
78
return sigEnd-sigStart-1;
79
}
80
81
PythonQtMemberInfo PythonQtClassInfo::member(const char* memberName)
82
{
83
PythonQtMemberInfo info = _cachedMembers.value(memberName);
84
if (info._type != PythonQtMemberInfo::Invalid) {
85
return info;
86
} else {
87
bool found = false;
88
const char* attributeName = memberName;
89
bool nameMapped = false;
90
// look for properties
91
int i = _meta->indexOfProperty(attributeName);
92
if (i==-1) {
93
// try to map name to objectName
94
if (qstrcmp(attributeName, "name")==0) {
95
attributeName = "objectName";
96
nameMapped = true;
97
i = _meta->indexOfProperty(attributeName);
98
}
99
}
100
if (i!=-1) {
101
PythonQtMemberInfo newInfo(_meta->property(i));
102
_cachedMembers.insert(attributeName, newInfo);
103
if (nameMapped) {
104
_cachedMembers.insert(memberName, newInfo);
105
}
106
#ifdef PYTHONQT_DEBUG
107
std::cout << "caching property " << memberName << " on " << _meta->className() << std::endl;
108
#endif
109
found = true;
110
} else {
111
int memberNameLen = strlen(memberName);
112
// if it is not a property, look for slots
113
PythonQtSlotInfo* tail = NULL;
114
int numMethods = _meta->methodCount();
115
for (int i = 0; i < numMethods; i++) {
116
QMetaMethod m = _meta->method(i);
117
if ((m.methodType() == QMetaMethod::Method ||
118
m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
119
120
const char* sigStart = m.signature();
121
// find the first '('
122
int offset = findCharOffset(sigStart, '(');
123
124
// check if same length and same name
125
if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
126
found = true;
127
PythonQtSlotInfo* info = new PythonQtSlotInfo(m, i);
128
if (tail) {
129
tail->setNextInfo(info);
130
} else {
131
PythonQtMemberInfo newInfo(info);
132
_cachedMembers.insert(memberName, newInfo);
133
}
134
tail = info;
135
}
136
}
137
}
138
139
// look for decorators
140
if (!_wrappedClassName.isEmpty()) {
141
tail = findDecoratorSlots(_wrappedClassName.constData(), memberName, memberNameLen, tail, found);
142
}
143
const QMetaObject* meta = _meta;
144
while (meta) {
145
tail = findDecoratorSlots(meta->className(), memberName, memberNameLen, tail, found);
146
meta = meta->superClass();
147
}
148
149
}
150
if (!found) {
151
// look for enum values
152
int enumCount = _meta->enumeratorCount();
153
for (i=0;i<enumCount; i++) {
154
QMetaEnum e = _meta->enumerator(i);
155
for (int j=0; j < e.keyCount(); j++) {
156
if (qstrcmp(e.key(j), attributeName)==0) {
157
PythonQtMemberInfo newInfo(e.value(j));
158
_cachedMembers.insert(memberName, newInfo);
159
#ifdef PYTHONQT_DEBUG
160
std::cout << "caching enum " << memberName << " on " << _meta->className() << std::endl;
161
#endif
162
found = true;
163
}
164
}
165
}
166
}
167
return _cachedMembers.value(memberName);
168
}
169
}
170
171
PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlots(const char* classname, const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool& found)
172
{
173
QListIterator<PythonQtSlotInfo*> it(PythonQt::priv()->getDecoratorSlots(classname));
174
while (it.hasNext()) {
175
176
PythonQtSlotInfo* infoOrig = it.next();
177
178
const char* sigStart = infoOrig->metaMethod()->signature();
179
if (qstrncmp("static_", sigStart, 7)==0) {
180
sigStart += 7;
181
sigStart += findCharOffset(sigStart, '_')+1;
182
}
183
int offset = findCharOffset(sigStart, '(');
184
if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
185
//make a copy, otherwise we will have trouble on overloads!
186
PythonQtSlotInfo* info = new PythonQtSlotInfo(*infoOrig);
187
found = true;
188
if (tail) {
189
tail->setNextInfo(info);
190
} else {
191
PythonQtMemberInfo newInfo(info);
192
_cachedMembers.insert(memberName, newInfo);
193
}
194
tail = info;
195
}
196
}
197
return tail;
198
}
199
200
201
QStringList PythonQtClassInfo::memberList(bool metaOnly)
202
{
203
QStringList l;
204
QString h;
205
if (_wrappedClassName.isEmpty()) {
206
int i;
207
int numProperties = _meta->propertyCount();
208
for (i = 0; i < numProperties; i++) {
209
QMetaProperty p = _meta->property(i);
210
l << QString(p.name());
211
}
212
}
213
214
if (!metaOnly) {
215
int numMethods = _meta->methodCount();
216
bool skipQObj = !_wrappedClassName.isEmpty();
217
for (int i = skipQObj?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
218
QMetaMethod m = _meta->method(i);
219
if ((m.methodType() == QMetaMethod::Method ||
220
m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
221
QByteArray signa(m.signature());
222
if (signa.startsWith("new_")) continue;
223
if (signa.startsWith("delete_")) continue;
224
if (signa.startsWith("static_")) continue;
225
PythonQtSlotInfo slot(m, i);
226
l << slot.slotName();
227
}
228
}
229
}
230
// look for decorators
231
QList<const char*> names;
232
if (!_wrappedClassName.isEmpty()) {
233
names << _wrappedClassName.constData();
234
}
235
const QMetaObject* meta = _meta;
236
while (meta) {
237
if (meta==&QObject::staticMetaObject && !_wrappedClassName.isEmpty()) break;
238
names << meta->className();
239
meta = meta->superClass();
240
}
241
242
QListIterator<const char*> nameIt(names);
243
while (nameIt.hasNext()) {
244
QListIterator<PythonQtSlotInfo*> it(PythonQt::priv()->getDecoratorSlots(nameIt.next()));
245
while (it.hasNext()) {
246
PythonQtSlotInfo* slot = it.next();
247
if (metaOnly) {
248
if (slot->isClassDecorator()) {
249
QByteArray first = slot->slotName();
250
if (first.startsWith("static_")) {
251
int idx = first.indexOf('_');
252
idx = first.indexOf('_', idx+1);
253
first = first.mid(idx+1);
254
}
255
l << first;
256
}
257
} else {
258
l << slot->slotName();
259
}
260
}
261
}
262
263
if (_meta->enumeratorCount()) {
264
for (int i = 0; i<_meta->enumeratorCount(); i++) {
265
QMetaEnum e = _meta->enumerator(i);
266
for (int j=0; j < e.keyCount(); j++) {
267
l << QString(e.key(j));
268
}
269
}
270
}
271
return l;
272
}
273
274
const char* PythonQtClassInfo::className()
275
{
276
if (!_wrappedClassName.isEmpty()) {
277
return _wrappedClassName.constData();
278
} else {
279
return _meta->className();
280
}
281
}
282
283
bool PythonQtClassInfo::inherits(const char* name)
284
{
285
const QMetaObject* m = _meta;
286
while (m) {
287
if (strcmp(name, m->className())==0) {
288
return true;
289
}
290
m = m->superClass();
291
}
292
return false;
293
}
294
295
const QByteArray& PythonQtClassInfo::wrappedCPPClassName()
296
{
297
return _wrappedClassName;
298
}
299
300
QString PythonQtClassInfo::help()
301
{
302
QString h;
303
bool isVariant = QMetaType::type(className())!=QMetaType::Void;
304
h += QString("--- ") + QString(className()) + QString(" ---\n");
305
306
if (_wrappedClassName.isEmpty()) {
307
h += "Properties:\n";
308
309
int i;
310
int numProperties = _meta->propertyCount();
311
for (i = 0; i < numProperties; i++) {
312
QMetaProperty p = _meta->property(i);
313
h += QString(p.name()) + " (" + QString(p.typeName()) + " )\n";
314
}
315
}
316
317
if (constructors()) {
318
h += "Constructors:\n";
319
PythonQtSlotInfo* constr = constructors();
320
while (constr) {
321
h += constr->fullSignature(false) + "\n";
322
constr = constr->nextInfo();
323
}
324
}
325
326
h += "Slots:\n";
327
h += "QString help()\n";
328
h += "QString className()\n";
329
330
int numMethods = _meta->methodCount();
331
for (int i = isVariant?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
332
QMetaMethod m = _meta->method(i);
333
if ((m.methodType() == QMetaMethod::Method ||
334
m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
335
QByteArray signa(m.signature());
336
if (signa.startsWith("new_")) continue;
337
if (signa.startsWith("delete_")) continue;
338
if (signa.startsWith("static_")) continue;
339
PythonQtSlotInfo slot(m, i);
340
h += slot.fullSignature(isVariant)+ "\n";
341
}
342
}
343
// look for decorators
344
QList<const char*> names;
345
if (!_wrappedClassName.isEmpty()) {
346
names << _wrappedClassName.constData();
347
}
348
const QMetaObject* meta = _meta;
349
while (meta) {
350
names << meta->className();
351
meta = meta->superClass();
352
if (isVariant && meta==&QObject::staticMetaObject) break;
353
}
354
355
QListIterator<const char*> nameIt(names);
356
while (nameIt.hasNext()) {
357
QListIterator<PythonQtSlotInfo*> it(PythonQt::priv()->getDecoratorSlots(nameIt.next()));
358
while (it.hasNext()) {
359
PythonQtSlotInfo* slot = it.next();
360
h += slot->fullSignature(slot->isInstanceDecorator()) + "\n";
361
}
362
}
363
364
if (_meta->enumeratorCount()) {
365
h += "Enums:\n";
366
for (int i = 0; i<_meta->enumeratorCount(); i++) {
367
QMetaEnum e = _meta->enumerator(i);
368
h += QString(e.name()) + " {";
369
for (int j=0; j < e.keyCount(); j++) {
370
if (j) { h+= ", "; }
371
h += e.key(j);
372
}
373
h += " }\n";
374
}
375
}
376
377
if (_wrappedClassName.isEmpty()) {
378
int numMethods = _meta->methodCount();
379
if (numMethods>0) {
380
h += "Signals:\n";
381
for (int i = isVariant?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
382
QMetaMethod m = _meta->method(i);
383
if (m.methodType() == QMetaMethod::Signal) {
384
h += QString(m.signature()) + "\n";
385
}
386
}
387
}
388
}
389
return h;
390
}
391
392
PythonQtSlotInfo* PythonQtClassInfo::constructors()
393
{
394
if (!_constructors) {
395
_constructors = PythonQt::priv()->getConstructorSlot(!_wrappedClassName.isEmpty()?_wrappedClassName:QByteArray(_meta->className()));
396
}
397
return _constructors;
398
}
399
400
void PythonQtClassInfo::setMetaObject(const QMetaObject* meta)
401
{
402
_meta = meta;
403
_cachedMembers.clear();
404
}
405
406