Path: blob/devel/ElmerGUI/PythonQt/src/PythonQtClassInfo.cpp
3206 views
/*1*2* Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.3*4* This library is free software; you can redistribute it and/or5* modify it under the terms of the GNU Lesser General Public6* License as published by the Free Software Foundation; either7* version 2.1 of the License, or (at your option) any later version.8*9* This library is distributed in the hope that it will be useful,10* but WITHOUT ANY WARRANTY; without even the implied warranty of11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU12* Lesser General Public License for more details.13*14* Further, this software is distributed without any warranty that it is15* free of the rightful claim of any third person regarding infringement16* or the like. Any license provided herein, whether implied or17* otherwise, applies only to this software file. Patent licenses, if18* any, provided herein do not apply to combinations of this program with19* other software, or any other product whatsoever.20*21* You should have received a copy of the GNU Lesser General Public22* License along with this library; if not, write to the Free Software23* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA24*25* Contact information: MeVis Research GmbH, Universitaetsallee 29,26* 28359 Bremen, Germany or:27*28* http://www.mevis.de29*30*/3132//----------------------------------------------------------------------------------33/*!34// \file PythonQt.cpp35// \author Florian Link36// \author Last changed by $Author: florian $37// \date 2006-0538*/39//----------------------------------------------------------------------------------4041#include "PythonQtClassInfo.h"42#include "PythonQtMethodInfo.h"43#include "PythonQt.h"44#include <QMetaMethod>4546QHash<QByteArray, int> PythonQtMethodInfo::_parameterTypeDict;4748PythonQtClassInfo::PythonQtClassInfo(const QMetaObject* meta, const QByteArray& wrappedClassName) {49_meta = meta;50_wrappedClassName = wrappedClassName;51_constructors = NULL;52}5354PythonQtClassInfo::~PythonQtClassInfo()55{56QHashIterator<QByteArray, PythonQtMemberInfo> i(_cachedMembers);57while (i.hasNext()) {58PythonQtMemberInfo member = i.next().value();59if (member._type== PythonQtMemberInfo::Slot) {60PythonQtSlotInfo* info = member._slot;61while (info) {62PythonQtSlotInfo* next = info->nextInfo();63delete info;64info = next;65}66}67}68}6970int PythonQtClassInfo::findCharOffset(const char* sigStart, char someChar)71{72const char* sigEnd = sigStart;73char c;74do {75c = *sigEnd++;76} while (c!=someChar && c!=0);77return sigEnd-sigStart-1;78}7980PythonQtMemberInfo PythonQtClassInfo::member(const char* memberName)81{82PythonQtMemberInfo info = _cachedMembers.value(memberName);83if (info._type != PythonQtMemberInfo::Invalid) {84return info;85} else {86bool found = false;87const char* attributeName = memberName;88bool nameMapped = false;89// look for properties90int i = _meta->indexOfProperty(attributeName);91if (i==-1) {92// try to map name to objectName93if (qstrcmp(attributeName, "name")==0) {94attributeName = "objectName";95nameMapped = true;96i = _meta->indexOfProperty(attributeName);97}98}99if (i!=-1) {100PythonQtMemberInfo newInfo(_meta->property(i));101_cachedMembers.insert(attributeName, newInfo);102if (nameMapped) {103_cachedMembers.insert(memberName, newInfo);104}105#ifdef PYTHONQT_DEBUG106std::cout << "caching property " << memberName << " on " << _meta->className() << std::endl;107#endif108found = true;109} else {110int memberNameLen = strlen(memberName);111// if it is not a property, look for slots112PythonQtSlotInfo* tail = NULL;113int numMethods = _meta->methodCount();114for (int i = 0; i < numMethods; i++) {115QMetaMethod m = _meta->method(i);116if ((m.methodType() == QMetaMethod::Method ||117m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {118119const char* sigStart = m.signature();120// find the first '('121int offset = findCharOffset(sigStart, '(');122123// check if same length and same name124if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {125found = true;126PythonQtSlotInfo* info = new PythonQtSlotInfo(m, i);127if (tail) {128tail->setNextInfo(info);129} else {130PythonQtMemberInfo newInfo(info);131_cachedMembers.insert(memberName, newInfo);132}133tail = info;134}135}136}137138// look for decorators139if (!_wrappedClassName.isEmpty()) {140tail = findDecoratorSlots(_wrappedClassName.constData(), memberName, memberNameLen, tail, found);141}142const QMetaObject* meta = _meta;143while (meta) {144tail = findDecoratorSlots(meta->className(), memberName, memberNameLen, tail, found);145meta = meta->superClass();146}147148}149if (!found) {150// look for enum values151int enumCount = _meta->enumeratorCount();152for (i=0;i<enumCount; i++) {153QMetaEnum e = _meta->enumerator(i);154for (int j=0; j < e.keyCount(); j++) {155if (qstrcmp(e.key(j), attributeName)==0) {156PythonQtMemberInfo newInfo(e.value(j));157_cachedMembers.insert(memberName, newInfo);158#ifdef PYTHONQT_DEBUG159std::cout << "caching enum " << memberName << " on " << _meta->className() << std::endl;160#endif161found = true;162}163}164}165}166return _cachedMembers.value(memberName);167}168}169170PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlots(const char* classname, const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool& found)171{172QListIterator<PythonQtSlotInfo*> it(PythonQt::priv()->getDecoratorSlots(classname));173while (it.hasNext()) {174175PythonQtSlotInfo* infoOrig = it.next();176177const char* sigStart = infoOrig->metaMethod()->signature();178if (qstrncmp("static_", sigStart, 7)==0) {179sigStart += 7;180sigStart += findCharOffset(sigStart, '_')+1;181}182int offset = findCharOffset(sigStart, '(');183if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {184//make a copy, otherwise we will have trouble on overloads!185PythonQtSlotInfo* info = new PythonQtSlotInfo(*infoOrig);186found = true;187if (tail) {188tail->setNextInfo(info);189} else {190PythonQtMemberInfo newInfo(info);191_cachedMembers.insert(memberName, newInfo);192}193tail = info;194}195}196return tail;197}198199200QStringList PythonQtClassInfo::memberList(bool metaOnly)201{202QStringList l;203QString h;204if (_wrappedClassName.isEmpty()) {205int i;206int numProperties = _meta->propertyCount();207for (i = 0; i < numProperties; i++) {208QMetaProperty p = _meta->property(i);209l << QString(p.name());210}211}212213if (!metaOnly) {214int numMethods = _meta->methodCount();215bool skipQObj = !_wrappedClassName.isEmpty();216for (int i = skipQObj?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {217QMetaMethod m = _meta->method(i);218if ((m.methodType() == QMetaMethod::Method ||219m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {220QByteArray signa(m.signature());221if (signa.startsWith("new_")) continue;222if (signa.startsWith("delete_")) continue;223if (signa.startsWith("static_")) continue;224PythonQtSlotInfo slot(m, i);225l << slot.slotName();226}227}228}229// look for decorators230QList<const char*> names;231if (!_wrappedClassName.isEmpty()) {232names << _wrappedClassName.constData();233}234const QMetaObject* meta = _meta;235while (meta) {236if (meta==&QObject::staticMetaObject && !_wrappedClassName.isEmpty()) break;237names << meta->className();238meta = meta->superClass();239}240241QListIterator<const char*> nameIt(names);242while (nameIt.hasNext()) {243QListIterator<PythonQtSlotInfo*> it(PythonQt::priv()->getDecoratorSlots(nameIt.next()));244while (it.hasNext()) {245PythonQtSlotInfo* slot = it.next();246if (metaOnly) {247if (slot->isClassDecorator()) {248QByteArray first = slot->slotName();249if (first.startsWith("static_")) {250int idx = first.indexOf('_');251idx = first.indexOf('_', idx+1);252first = first.mid(idx+1);253}254l << first;255}256} else {257l << slot->slotName();258}259}260}261262if (_meta->enumeratorCount()) {263for (int i = 0; i<_meta->enumeratorCount(); i++) {264QMetaEnum e = _meta->enumerator(i);265for (int j=0; j < e.keyCount(); j++) {266l << QString(e.key(j));267}268}269}270return l;271}272273const char* PythonQtClassInfo::className()274{275if (!_wrappedClassName.isEmpty()) {276return _wrappedClassName.constData();277} else {278return _meta->className();279}280}281282bool PythonQtClassInfo::inherits(const char* name)283{284const QMetaObject* m = _meta;285while (m) {286if (strcmp(name, m->className())==0) {287return true;288}289m = m->superClass();290}291return false;292}293294const QByteArray& PythonQtClassInfo::wrappedCPPClassName()295{296return _wrappedClassName;297}298299QString PythonQtClassInfo::help()300{301QString h;302bool isVariant = QMetaType::type(className())!=QMetaType::Void;303h += QString("--- ") + QString(className()) + QString(" ---\n");304305if (_wrappedClassName.isEmpty()) {306h += "Properties:\n";307308int i;309int numProperties = _meta->propertyCount();310for (i = 0; i < numProperties; i++) {311QMetaProperty p = _meta->property(i);312h += QString(p.name()) + " (" + QString(p.typeName()) + " )\n";313}314}315316if (constructors()) {317h += "Constructors:\n";318PythonQtSlotInfo* constr = constructors();319while (constr) {320h += constr->fullSignature(false) + "\n";321constr = constr->nextInfo();322}323}324325h += "Slots:\n";326h += "QString help()\n";327h += "QString className()\n";328329int numMethods = _meta->methodCount();330for (int i = isVariant?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {331QMetaMethod m = _meta->method(i);332if ((m.methodType() == QMetaMethod::Method ||333m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {334QByteArray signa(m.signature());335if (signa.startsWith("new_")) continue;336if (signa.startsWith("delete_")) continue;337if (signa.startsWith("static_")) continue;338PythonQtSlotInfo slot(m, i);339h += slot.fullSignature(isVariant)+ "\n";340}341}342// look for decorators343QList<const char*> names;344if (!_wrappedClassName.isEmpty()) {345names << _wrappedClassName.constData();346}347const QMetaObject* meta = _meta;348while (meta) {349names << meta->className();350meta = meta->superClass();351if (isVariant && meta==&QObject::staticMetaObject) break;352}353354QListIterator<const char*> nameIt(names);355while (nameIt.hasNext()) {356QListIterator<PythonQtSlotInfo*> it(PythonQt::priv()->getDecoratorSlots(nameIt.next()));357while (it.hasNext()) {358PythonQtSlotInfo* slot = it.next();359h += slot->fullSignature(slot->isInstanceDecorator()) + "\n";360}361}362363if (_meta->enumeratorCount()) {364h += "Enums:\n";365for (int i = 0; i<_meta->enumeratorCount(); i++) {366QMetaEnum e = _meta->enumerator(i);367h += QString(e.name()) + " {";368for (int j=0; j < e.keyCount(); j++) {369if (j) { h+= ", "; }370h += e.key(j);371}372h += " }\n";373}374}375376if (_wrappedClassName.isEmpty()) {377int numMethods = _meta->methodCount();378if (numMethods>0) {379h += "Signals:\n";380for (int i = isVariant?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {381QMetaMethod m = _meta->method(i);382if (m.methodType() == QMetaMethod::Signal) {383h += QString(m.signature()) + "\n";384}385}386}387}388return h;389}390391PythonQtSlotInfo* PythonQtClassInfo::constructors()392{393if (!_constructors) {394_constructors = PythonQt::priv()->getConstructorSlot(!_wrappedClassName.isEmpty()?_wrappedClassName:QByteArray(_meta->className()));395}396return _constructors;397}398399void PythonQtClassInfo::setMetaObject(const QMetaObject* meta)400{401_meta = meta;402_cachedMembers.clear();403}404405406