##// END OF EJS Templates
fixed initialization order, the importer needs to be store BEFORE the import module is initialized...
fixed initialization order, the importer needs to be store BEFORE the import module is initialized git-svn-id: svn://svn.code.sf.net/p/pythonqt/code/trunk@120 ea8d5007-eb21-0410-b261-ccb3ea6e24a9

File last commit:

r69:5f2efada2db6
r84:8f25be796564
Show More
PythonQtClassInfo.cpp
843 lines | 25.1 KiB | text/x-c | CppLexer
/ src / PythonQtClassInfo.cpp
ezust
reorganized SVN tree into branches, tags and trunk...
r0 /*
*
* Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 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
* Lesser General Public License for more details.
*
* Further, this software is distributed without any warranty that it is
* free of the rightful claim of any third person regarding infringement
* or the like. Any license provided herein, whether implied or
* otherwise, applies only to this software file. Patent licenses, if
* any, provided herein do not apply to combinations of this program with
* other software, or any other product whatsoever.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Contact information: MeVis Research GmbH, Universitaetsallee 29,
* 28359 Bremen, Germany or:
*
* http://www.mevis.de
*
*/
//----------------------------------------------------------------------------------
/*!
// \file PythonQt.cpp
// \author Florian Link
// \author Last changed by $Author: florian $
// \date 2006-05
*/
//----------------------------------------------------------------------------------
#include "PythonQtClassInfo.h"
#include "PythonQtMethodInfo.h"
#include "PythonQt.h"
#include <QMetaMethod>
florianlink
added enum wrapper classes derived from python int, so that enums are distinguishable from normal python integers. This will allow better overload handling e.g. of QColor constructors in the future...
r51 #include <QMetaObject>
#include <QMetaEnum>
ezust
reorganized SVN tree into branches, tags and trunk...
r0
QHash<QByteArray, int> PythonQtMethodInfo::_parameterTypeDict;
florianlink
- added support for deriving CPP classes in Python and to override all public and protected virtual functions from PythonQt...
r24 PythonQtClassInfo::PythonQtClassInfo() {
_meta = NULL;
ezust
reorganized SVN tree into branches, tags and trunk...
r0 _constructors = NULL;
florianlink
- added support for deriving CPP classes in Python and to override all public and protected virtual functions from PythonQt...
r24 _destructor = NULL;
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 _decoratorProvider = NULL;
_decoratorProviderCB = NULL;
florianlink
- wrapped instances are now wrapped by class specific subtypes to facilitate future deriving from python...
r18 _pythonQtClassWrapper = NULL;
florianlink
- added support for deriving CPP classes in Python and to override all public and protected virtual functions from PythonQt...
r24 _shellSetInstanceWrapperCB = NULL;
_metaTypeId = -1;
_isQObject = false;
florianlink
added enum wrapper classes derived from python int, so that enums are distinguishable from normal python integers. This will allow better overload handling e.g. of QColor constructors in the future...
r51 _enumsCreated = false;
ezust
reorganized SVN tree into branches, tags and trunk...
r0 }
PythonQtClassInfo::~PythonQtClassInfo()
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 {
clearCachedMembers();
florianlink
- added support for deriving CPP classes in Python and to override all public and protected virtual functions from PythonQt...
r24
if (_constructors) {
_constructors->deleteOverloadsAndThis();
}
if (_destructor) {
_destructor->deleteOverloadsAndThis();
}
foreach(PythonQtSlotInfo* info, _decoratorSlots) {
info->deleteOverloadsAndThis();
}
}
void PythonQtClassInfo::setupQObject(const QMetaObject* meta)
{
// _wrappedClassName is already set earlier in the class setup
_isQObject = true;
_meta = meta;
}
void PythonQtClassInfo::setupCPPObject(const QByteArray& classname)
{
_isQObject = false;
_wrappedClassName = classname;
_metaTypeId = QMetaType::type(classname);
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 }
void PythonQtClassInfo::clearCachedMembers()
ezust
reorganized SVN tree into branches, tags and trunk...
r0 {
QHashIterator<QByteArray, PythonQtMemberInfo> i(_cachedMembers);
while (i.hasNext()) {
PythonQtMemberInfo member = i.next().value();
if (member._type== PythonQtMemberInfo::Slot) {
PythonQtSlotInfo* info = member._slot;
while (info) {
PythonQtSlotInfo* next = info->nextInfo();
delete info;
info = next;
}
}
}
}
int PythonQtClassInfo::findCharOffset(const char* sigStart, char someChar)
{
const char* sigEnd = sigStart;
char c;
do {
c = *sigEnd++;
} while (c!=someChar && c!=0);
return sigEnd-sigStart-1;
}
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 bool PythonQtClassInfo::lookForPropertyAndCache(const char* memberName)
{
bool found = false;
bool nameMapped = false;
const char* attributeName = memberName;
// look for properties
int i = _meta->indexOfProperty(attributeName);
if (i==-1) {
// try to map name to objectName
if (qstrcmp(attributeName, "name")==0) {
attributeName = "objectName";
nameMapped = true;
i = _meta->indexOfProperty(attributeName);
}
}
if (i!=-1) {
PythonQtMemberInfo newInfo(_meta->property(i));
_cachedMembers.insert(attributeName, newInfo);
if (nameMapped) {
_cachedMembers.insert(memberName, newInfo);
}
#ifdef PYTHONQT_DEBUG
std::cout << "caching property " << memberName << " on " << _meta->className() << std::endl;
#endif
found = true;
}
return found;
}
florianlink
- added support for deriving CPP classes in Python and to override all public and protected virtual functions from PythonQt...
r24 PythonQtSlotInfo* PythonQtClassInfo::recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
{
inputInfo = findDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset);
foreach(const ParentClassInfo& info, _parentClasses) {
inputInfo = info._parent->recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset+info._upcastingOffset);
}
return inputInfo;
}
PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset) {
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 QObject* decoratorProvider = decorator();
florianlink
- added support for deriving CPP classes in Python and to override all public and protected virtual functions from PythonQt...
r24 int memberNameLen = strlen(memberName);
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 if (decoratorProvider) {
florianlink
- added support for deriving CPP classes in Python and to override all public and protected virtual functions from PythonQt...
r24 //qDebug()<< "looking " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 const QMetaObject* meta = decoratorProvider->metaObject();
int numMethods = meta->methodCount();
int startFrom = QObject::staticMetaObject.methodCount();
for (int i = startFrom; i < numMethods; i++) {
QMetaMethod m = meta->method(i);
if ((m.methodType() == QMetaMethod::Method ||
m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
const char* sigStart = m.signature();
bool isClassDeco = false;
if (qstrncmp(sigStart, "static_", 7)==0) {
// skip the static_classname_ part of the string
sigStart += 7 + 1 + strlen(className());
isClassDeco = true;
} else if (qstrncmp(sigStart, "new_", 4)==0) {
isClassDeco = true;
} else if (qstrncmp(sigStart, "delete_", 7)==0) {
isClassDeco = true;
}
// find the first '('
int offset = findCharOffset(sigStart, '(');
// XXX no checking is currently done if the slots have correct first argument or not...
// check if same length and same name
if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
found = true;
florianlink
cleanup of code and addition of (yet unused) classinfo passed to method/slot info to allow local enum support on creation...
r54 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i, decoratorProvider, isClassDeco?PythonQtSlotInfo::ClassDecorator:PythonQtSlotInfo::InstanceDecorator);
florianlink
- added support for deriving CPP classes in Python and to override all public and protected virtual functions from PythonQt...
r24 info->setUpcastingOffset(upcastingOffset);
//qDebug()<< "adding " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 if (tail) {
tail->setNextInfo(info);
} else {
PythonQtMemberInfo newInfo(info);
memberCache.insert(memberName, newInfo);
}
tail = info;
}
}
}
}
florianlink
- added support for deriving CPP classes in Python and to override all public and protected virtual functions from PythonQt...
r24
tail = findDecoratorSlots(memberName, memberNameLen, tail, found, memberCache, upcastingOffset);
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 return tail;
}
bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName)
{
bool found = false;
int memberNameLen = strlen(memberName);
PythonQtSlotInfo* tail = NULL;
if (_meta) {
int numMethods = _meta->methodCount();
for (int i = 0; i < numMethods; i++) {
QMetaMethod m = _meta->method(i);
florianlink
enabled signals to be emitted by simply calling them...
r69 if (((m.methodType() == QMetaMethod::Method ||
m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
|| m.methodType()==QMetaMethod::Signal) {
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10
const char* sigStart = m.signature();
// find the first '('
int offset = findCharOffset(sigStart, '(');
// check if same length and same name
if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
found = true;
florianlink
cleanup of code and addition of (yet unused) classinfo passed to method/slot info to allow local enum support on creation...
r54 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i);
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 if (tail) {
tail->setNextInfo(info);
} else {
PythonQtMemberInfo newInfo(info);
_cachedMembers.insert(memberName, newInfo);
}
tail = info;
}
}
}
}
// look for dynamic decorators in this class and in derived classes
florianlink
- added support for deriving CPP classes in Python and to override all public and protected virtual functions from PythonQt...
r24 tail = recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers, 0);
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10
return found;
}
bool PythonQtClassInfo::lookForEnumAndCache(const QMetaObject* meta, const char* memberName)
{
bool found = false;
// look for enum values
int enumCount = meta->enumeratorCount();
for (int i=0;i<enumCount; i++) {
QMetaEnum e = meta->enumerator(i);
florianlink
cache enumWrappers in method infos and make use of the extra information for better enum overloading...
r55 // we do not want flags, they will cause our values to appear two times
if (e.isFlag()) continue;
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 for (int j=0; j < e.keyCount(); j++) {
if (qstrcmp(e.key(j), memberName)==0) {
florianlink
added enum wrapper classes derived from python int, so that enums are distinguishable from normal python integers. This will allow better overload handling e.g. of QColor constructors in the future...
r51 PyObject* enumType = findEnumWrapper(e.name());
if (enumType) {
PythonQtObjectPtr enumValuePtr;
florianlink
support enum values on signals as well, all tests should succeed now...
r56 enumValuePtr.setNewRef(PythonQtPrivate::createEnumValueInstance(enumType, e.value(j)));
florianlink
added enum wrapper classes derived from python int, so that enums are distinguishable from normal python integers. This will allow better overload handling e.g. of QColor constructors in the future...
r51 PythonQtMemberInfo newInfo(enumValuePtr);
_cachedMembers.insert(memberName, newInfo);
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 #ifdef PYTHONQT_DEBUG
florianlink
added enum wrapper classes derived from python int, so that enums are distinguishable from normal python integers. This will allow better overload handling e.g. of QColor constructors in the future...
r51 std::cout << "caching enum " << memberName << " on " << meta->className() << std::endl;
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 #endif
florianlink
added enum wrapper classes derived from python int, so that enums are distinguishable from normal python integers. This will allow better overload handling e.g. of QColor constructors in the future...
r51 found = true;
break;
} else {
std::cout << "enum " << e.name() << " not found on " << className() << std::endl;
}
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 }
}
}
return found;
}
ezust
reorganized SVN tree into branches, tags and trunk...
r0 PythonQtMemberInfo PythonQtClassInfo::member(const char* memberName)
{
PythonQtMemberInfo info = _cachedMembers.value(memberName);
if (info._type != PythonQtMemberInfo::Invalid) {
return info;
} else {
bool found = false;
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10
found = lookForPropertyAndCache(memberName);
if (!found) {
found = lookForMethodAndCache(memberName);
ezust
reorganized SVN tree into branches, tags and trunk...
r0 }
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 if (!found) {
if (_meta) {
// check enums in our meta object directly
found = lookForEnumAndCache(_meta, memberName);
ezust
reorganized SVN tree into branches, tags and trunk...
r0 }
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 if (!found) {
// check enums in the class hierachy of CPP classes
// look for dynamic decorators in this class and in derived classes
florianlink
- added support for deriving CPP classes in Python and to override all public and protected virtual functions from PythonQt...
r24 QList<QObject*> decoObjects;
recursiveCollectDecoratorObjects(decoObjects);
foreach(QObject* deco, decoObjects) {
// call on ourself for caching, but with different metaObject():
found = lookForEnumAndCache(deco->metaObject(), memberName);
if (found) {
break;
ezust
reorganized SVN tree into branches, tags and trunk...
r0 }
}
}
}
florianlink
added enum wrapper classes derived from python int, so that enums are distinguishable from normal python integers. This will allow better overload handling e.g. of QColor constructors in the future...
r51 if (!found) {
florianlink
added error handling for virtual method overloads, added more global functions (qsrand etc.), added support for exec_ etc (python keyword overlap resolution), change virtual method handling, this will require code regeneration (I will do that tomorrow)...
r67 // maybe it is an enum wrapper?
florianlink
added enum wrapper classes derived from python int, so that enums are distinguishable from normal python integers. This will allow better overload handling e.g. of QColor constructors in the future...
r51 PyObject* p = findEnumWrapper(memberName);
if (p) {
info._type = PythonQtMemberInfo::EnumWrapper;
info._enumWrapper = p;
_cachedMembers.insert(memberName, info);
found = true;
}
}
florianlink
added error handling for virtual method overloads, added more global functions (qsrand etc.), added support for exec_ etc (python keyword overlap resolution), change virtual method handling, this will require code regeneration (I will do that tomorrow)...
r67 if (!found) {
// since python keywords can not be looked up, we check if the name contains a single trailing _
// and remove that and look again, so that we e.g. find exec on an exec_ lookup
QByteArray mbrName(memberName);
if ((mbrName.length()>2) &&
(mbrName.at(mbrName.length()-1) == '_') &&
(mbrName.at(mbrName.length()-2) != '_')) {
mbrName = mbrName.mid(0,mbrName.length()-1);
found = lookForMethodAndCache(mbrName.constData());
if (found) {
return _cachedMembers.value(mbrName);
}
}
}
ezust
reorganized SVN tree into branches, tags and trunk...
r0 if (!found) {
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 // we store a NotFound member, so that we get a quick result for non existing members (e.g. operator_equal lookup)
info._type = PythonQtMemberInfo::NotFound;
_cachedMembers.insert(memberName, info);
ezust
reorganized SVN tree into branches, tags and trunk...
r0 }
}
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10
return _cachedMembers.value(memberName);
ezust
reorganized SVN tree into branches, tags and trunk...
r0 }
florianlink
- added support for deriving CPP classes in Python and to override all public and protected virtual functions from PythonQt...
r24 void PythonQtClassInfo::recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects) {
QObject* deco = decorator();
if (deco) {
decoratorObjects.append(deco);
}
foreach(const ParentClassInfo& info, _parentClasses) {
info._parent->recursiveCollectDecoratorObjects(decoratorObjects);
}
}
void PythonQtClassInfo::recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects) {
classInfoObjects.append(this);
foreach(const ParentClassInfo& info, _parentClasses) {
info._parent->recursiveCollectClassInfos(classInfoObjects);
}
}
PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
ezust
reorganized SVN tree into branches, tags and trunk...
r0 {
florianlink
- added support for deriving CPP classes in Python and to override all public and protected virtual functions from PythonQt...
r24 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
ezust
reorganized SVN tree into branches, tags and trunk...
r0 while (it.hasNext()) {
PythonQtSlotInfo* infoOrig = it.next();
const char* sigStart = infoOrig->metaMethod()->signature();
if (qstrncmp("static_", sigStart, 7)==0) {
sigStart += 7;
sigStart += findCharOffset(sigStart, '_')+1;
}
int offset = findCharOffset(sigStart, '(');
if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
//make a copy, otherwise we will have trouble on overloads!
PythonQtSlotInfo* info = new PythonQtSlotInfo(*infoOrig);
florianlink
- added support for deriving CPP classes in Python and to override all public and protected virtual functions from PythonQt...
r24 info->setUpcastingOffset(upcastingOffset);
ezust
reorganized SVN tree into branches, tags and trunk...
r0 found = true;
if (tail) {
tail->setNextInfo(info);
} else {
PythonQtMemberInfo newInfo(info);
florianlink
- added support for deriving CPP classes in Python and to override all public and protected virtual functions from PythonQt...
r24 memberCache.insert(memberName, newInfo);
ezust
reorganized SVN tree into branches, tags and trunk...
r0 }
tail = info;
}
}
return tail;
}
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 void PythonQtClassInfo::listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly) {
QObject* decoratorProvider = decorator();
if (decoratorProvider) {
const QMetaObject* meta = decoratorProvider->metaObject();
int numMethods = meta->methodCount();
int startFrom = QObject::staticMetaObject.methodCount();
for (int i = startFrom; i < numMethods; i++) {
QMetaMethod m = meta->method(i);
if ((m.methodType() == QMetaMethod::Method ||
m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
const char* sigStart = m.signature();
bool isClassDeco = false;
if (qstrncmp(sigStart, "static_", 7)==0) {
// skip the static_classname_ part of the string
sigStart += 7 + 1 + strlen(className());
isClassDeco = true;
} else if (qstrncmp(sigStart, "new_", 4)==0) {
florianlink
code cleanup and rename of PythonQtWrapper to PythonQtInstanceWrapper and PythonQtMetaObjectWrapper to PythonQtClassWrapper, since these names match much better what these classes wrap, regarding that we are wrapping CPP objects as well...
r16 continue;
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
florianlink
code cleanup and rename of PythonQtWrapper to PythonQtInstanceWrapper and PythonQtMetaObjectWrapper to PythonQtClassWrapper, since these names match much better what these classes wrap, regarding that we are wrapping CPP objects as well...
r16 continue;
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 }
// find the first '('
int offset = findCharOffset(sigStart, '(');
// XXX no checking is currently done if the slots have correct first argument or not...
if (!metaOnly || isClassDeco) {
list << QString::fromLatin1(sigStart, offset);
}
}
}
}
florianlink
- added support for deriving CPP classes in Python and to override all public and protected virtual functions from PythonQt...
r24
// look for global decorator slots
QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
while (it.hasNext()) {
PythonQtSlotInfo* slot = it.next();
if (metaOnly) {
if (slot->isClassDecorator()) {
QByteArray first = slot->slotName();
if (first.startsWith("static_")) {
int idx = first.indexOf('_');
idx = first.indexOf('_', idx+1);
first = first.mid(idx+1);
}
list << first;
}
} else {
list << slot->slotName();
}
}
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 }
florianlink
improved so that dict contains properties and that dir() shows all available things, including the derived base attributes...
r34 QStringList PythonQtClassInfo::propertyList()
{
ezust
reorganized SVN tree into branches, tags and trunk...
r0 QStringList l;
florianlink
improved so that dict contains properties and that dir() shows all available things, including the derived base attributes...
r34 if (_isQObject && _meta) {
ezust
reorganized SVN tree into branches, tags and trunk...
r0 int i;
int numProperties = _meta->propertyCount();
for (i = 0; i < numProperties; i++) {
QMetaProperty p = _meta->property(i);
l << QString(p.name());
}
}
florianlink
improved so that dict contains properties and that dir() shows all available things, including the derived base attributes...
r34 return l;
}
QStringList PythonQtClassInfo::memberList(bool metaOnly)
{
decorator();
QStringList l;
QString h;
if (_isQObject && _meta && !metaOnly) {
l = propertyList();
}
ezust
reorganized SVN tree into branches, tags and trunk...
r0
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 // normal slots of QObject (or wrapper QObject)
if (!metaOnly && _meta) {
ezust
reorganized SVN tree into branches, tags and trunk...
r0 int numMethods = _meta->methodCount();
florianlink
- added support for deriving CPP classes in Python and to override all public and protected virtual functions from PythonQt...
r24 bool skipQObj = !_isQObject;
ezust
reorganized SVN tree into branches, tags and trunk...
r0 for (int i = skipQObj?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
QMetaMethod m = _meta->method(i);
florianlink
enabled signals to be emitted by simply calling them...
r69 if (((m.methodType() == QMetaMethod::Method ||
m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
|| m.methodType()==QMetaMethod::Signal) {
florianlink
cleanup of code and addition of (yet unused) classinfo passed to method/slot info to allow local enum support on creation...
r54 QByteArray signa(m.signature());
signa = signa.left(signa.indexOf('('));
l << signa;
ezust
reorganized SVN tree into branches, tags and trunk...
r0 }
}
}
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10
{
// look for dynamic decorators in this class and in derived classes
florianlink
- added support for deriving CPP classes in Python and to override all public and protected virtual functions from PythonQt...
r24 QList<PythonQtClassInfo*> infos;
recursiveCollectClassInfos(infos);
foreach(PythonQtClassInfo* info, infos) {
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 info->listDecoratorSlotsFromDecoratorProvider(l, metaOnly);
ezust
reorganized SVN tree into branches, tags and trunk...
r0 }
}
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10
// List enumerator keys...
QList<const QMetaObject*> enumMetaObjects;
if (_meta) {
enumMetaObjects << _meta;
}
// check enums in the class hierachy of CPP classes
florianlink
- added support for deriving CPP classes in Python and to override all public and protected virtual functions from PythonQt...
r24 QList<QObject*> decoObjects;
recursiveCollectDecoratorObjects(decoObjects);
foreach(QObject* deco, decoObjects) {
enumMetaObjects << deco->metaObject();
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 }
foreach(const QMetaObject* meta, enumMetaObjects) {
for (int i = 0; i<meta->enumeratorCount(); i++) {
QMetaEnum e = meta->enumerator(i);
florianlink
added enum wrapper classes derived from python int, so that enums are distinguishable from normal python integers. This will allow better overload handling e.g. of QColor constructors in the future...
r51 l << e.name();
florianlink
cache enumWrappers in method infos and make use of the extra information for better enum overloading...
r55 // we do not want flags, they will cause our values to appear two times
if (e.isFlag()) continue;
ezust
reorganized SVN tree into branches, tags and trunk...
r0 for (int j=0; j < e.keyCount(); j++) {
l << QString(e.key(j));
}
}
}
florianlink
added support for downcasting via polymorphic handlers...
r26
return QSet<QString>::fromList(l).toList();
ezust
reorganized SVN tree into branches, tags and trunk...
r0 }
const char* PythonQtClassInfo::className()
{
florianlink
- added support for deriving CPP classes in Python and to override all public and protected virtual functions from PythonQt...
r24 return _wrappedClassName.constData();
}
void* PythonQtClassInfo::castTo(void* ptr, const char* classname)
{
if (ptr==NULL) {
return NULL;
}
if (_wrappedClassName == classname) {
return ptr;
}
foreach(const ParentClassInfo& info, _parentClasses) {
void* result = info._parent->castTo((char*)ptr + info._upcastingOffset, classname);
if (result) {
return result;
}
ezust
reorganized SVN tree into branches, tags and trunk...
r0 }
florianlink
- added support for deriving CPP classes in Python and to override all public and protected virtual functions from PythonQt...
r24 return NULL;
ezust
reorganized SVN tree into branches, tags and trunk...
r0 }
bool PythonQtClassInfo::inherits(const char* name)
{
florianlink
- added support for deriving CPP classes in Python and to override all public and protected virtual functions from PythonQt...
r24 if (_wrappedClassName == name) {
return true;
}
foreach(const ParentClassInfo& info, _parentClasses) {
if (info._parent->inherits(name)) {
return true;
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 }
florianlink
- added support for deriving CPP classes in Python and to override all public and protected virtual functions from PythonQt...
r24 }
return false;
}
bool PythonQtClassInfo::inherits(PythonQtClassInfo* classInfo)
{
if (classInfo == this) {
return true;
}
foreach(const ParentClassInfo& info, _parentClasses) {
if (info._parent->inherits(classInfo)) {
return true;
ezust
reorganized SVN tree into branches, tags and trunk...
r0 }
}
return false;
}
QString PythonQtClassInfo::help()
{
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 decorator();
ezust
reorganized SVN tree into branches, tags and trunk...
r0 QString h;
h += QString("--- ") + QString(className()) + QString(" ---\n");
florianlink
- added support for deriving CPP classes in Python and to override all public and protected virtual functions from PythonQt...
r24 if (_isQObject) {
ezust
reorganized SVN tree into branches, tags and trunk...
r0 h += "Properties:\n";
int i;
int numProperties = _meta->propertyCount();
for (i = 0; i < numProperties; i++) {
QMetaProperty p = _meta->property(i);
h += QString(p.name()) + " (" + QString(p.typeName()) + " )\n";
}
}
if (constructors()) {
h += "Constructors:\n";
PythonQtSlotInfo* constr = constructors();
while (constr) {
florianlink
- removed argument to fullSignature...
r23 h += constr->fullSignature() + "\n";
ezust
reorganized SVN tree into branches, tags and trunk...
r0 constr = constr->nextInfo();
}
}
h += "Slots:\n";
h += "QString help()\n";
h += "QString className()\n";
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 if (_meta) {
int numMethods = _meta->methodCount();
for (int i = 0; i < numMethods; i++) {
QMetaMethod m = _meta->method(i);
if ((m.methodType() == QMetaMethod::Method ||
m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
florianlink
cleanup of code and addition of (yet unused) classinfo passed to method/slot info to allow local enum support on creation...
r54 PythonQtSlotInfo slot(this, m, i);
florianlink
- removed argument to fullSignature...
r23 h += slot.fullSignature()+ "\n";
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 }
ezust
reorganized SVN tree into branches, tags and trunk...
r0 }
}
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10
// TODO xxx : decorators and enums from decorator() are missing...
// maybe we can reuse memberlist()?
if (_meta && _meta->enumeratorCount()) {
ezust
reorganized SVN tree into branches, tags and trunk...
r0 h += "Enums:\n";
for (int i = 0; i<_meta->enumeratorCount(); i++) {
QMetaEnum e = _meta->enumerator(i);
h += QString(e.name()) + " {";
for (int j=0; j < e.keyCount(); j++) {
if (j) { h+= ", "; }
h += e.key(j);
}
h += " }\n";
}
}
florianlink
- added support for deriving CPP classes in Python and to override all public and protected virtual functions from PythonQt...
r24 if (_isQObject && _meta) {
ezust
reorganized SVN tree into branches, tags and trunk...
r0 int numMethods = _meta->methodCount();
if (numMethods>0) {
h += "Signals:\n";
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 for (int i = 0; i < numMethods; i++) {
ezust
reorganized SVN tree into branches, tags and trunk...
r0 QMetaMethod m = _meta->method(i);
if (m.methodType() == QMetaMethod::Signal) {
h += QString(m.signature()) + "\n";
}
}
}
}
return h;
}
PythonQtSlotInfo* PythonQtClassInfo::constructors()
{
if (!_constructors) {
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 // force creation of lazy decorator, which will register the decorators
decorator();
ezust
reorganized SVN tree into branches, tags and trunk...
r0 }
return _constructors;
}
florianlink
- added support for deriving CPP classes in Python and to override all public and protected virtual functions from PythonQt...
r24 PythonQtSlotInfo* PythonQtClassInfo::destructor()
{
if (!_destructor) {
// force creation of lazy decorator, which will register the decorators
decorator();
}
return _destructor;
}
void PythonQtClassInfo::addConstructor(PythonQtSlotInfo* info)
{
PythonQtSlotInfo* prev = constructors();
if (prev) {
info->setNextInfo(prev->nextInfo());
prev->setNextInfo(info);
} else {
_constructors = info;
}
}
void PythonQtClassInfo::addDecoratorSlot(PythonQtSlotInfo* info)
{
_decoratorSlots.append(info);
}
void PythonQtClassInfo::setDestructor(PythonQtSlotInfo* info)
{
if (_destructor) {
_destructor->deleteOverloadsAndThis();
}
_destructor = info;
}
ezust
reorganized SVN tree into branches, tags and trunk...
r0 void PythonQtClassInfo::setMetaObject(const QMetaObject* meta)
{
_meta = meta;
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 clearCachedMembers();
}
QObject* PythonQtClassInfo::decorator()
{
if (!_decoratorProvider && _decoratorProviderCB) {
_decoratorProvider = (*_decoratorProviderCB)();
if (_decoratorProvider) {
_decoratorProvider->setParent(PythonQt::priv());
florianlink
cleanup of code and addition of (yet unused) classinfo passed to method/slot info to allow local enum support on creation...
r54 // setup enums early, since they might be needed by the constructor decorators:
if (!_enumsCreated) {
createEnumWrappers();
}
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
}
}
florianlink
cleanup of code and addition of (yet unused) classinfo passed to method/slot info to allow local enum support on creation...
r54 // check if enums need to be created and create them if they are not yet created
florianlink
added enum wrapper classes derived from python int, so that enums are distinguishable from normal python integers. This will allow better overload handling e.g. of QColor constructors in the future...
r51 if (!_enumsCreated) {
createEnumWrappers();
}
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 return _decoratorProvider;
ezust
reorganized SVN tree into branches, tags and trunk...
r0 }
florianlink
- added hasOwner method to manage ownership more nicely...
r15
bool PythonQtClassInfo::hasOwnerMethodButNoOwner(void* object)
{
PythonQtMemberInfo info = member("hasOwner");
if (info._type == PythonQtMemberInfo::Slot) {
void* obj = object;
bool result = false;
void* args[2];
args[0] = &result;
args[1] = &obj;
info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
return !result;
} else {
return false;
}
}
florianlink
added support for downcasting via polymorphic handlers...
r26
void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, char** resultClassName)
{
if (!_polymorphicHandlers.isEmpty()) {
foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
void* resultPtr = (*cb)(ptr, resultClassName);
if (resultPtr) {
return resultPtr;
}
}
}
foreach(const ParentClassInfo& info, _parentClasses) {
if (!info._parent->isQObject()) {
void* resultPtr = info._parent->recursiveCastDownIfPossible((char*)ptr + info._upcastingOffset, resultClassName);
if (resultPtr) {
return resultPtr;
}
}
}
return NULL;
}
void* PythonQtClassInfo::castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo)
{
char* className;
florianlink
enabled downcasting only on base classes...
r31 // this would do downcasting recursively...
// void* resultPtr = recursiveCastDownIfPossible(ptr, &className);
// we only do downcasting on the base object, not on the whole inheritance tree...
void* resultPtr = NULL;
if (!_polymorphicHandlers.isEmpty()) {
foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
resultPtr = (*cb)(ptr, &className);
if (resultPtr) {
break;
}
}
}
florianlink
added support for downcasting via polymorphic handlers...
r26 if (resultPtr) {
*resultClassInfo = PythonQt::priv()->getClassInfo(className);
} else {
*resultClassInfo = this;
resultPtr = ptr;
}
return resultPtr;
}
florianlink
fixed enum handling for static methods calls and added correct support for decorated enum detection...
r41
florianlink
added automatic conversion to QColor,QPen,QCursor and QBrush from enums and colors...
r64 PyObject* PythonQtClassInfo::findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum)
florianlink
fixed enum handling for static methods calls and added correct support for decorated enum detection...
r41 {
florianlink
added automatic conversion to QColor,QPen,QCursor and QBrush from enums and colors...
r64 if (isLocalEnum) {
*isLocalEnum = true;
}
florianlink
fixed enum handling for static methods calls and added correct support for decorated enum detection...
r41 int scopePos = name.lastIndexOf("::");
if (scopePos != -1) {
florianlink
added automatic conversion to QColor,QPen,QCursor and QBrush from enums and colors...
r64 if (isLocalEnum) {
*isLocalEnum = false;
}
// split into scope and enum name
florianlink
fixed enum handling for static methods calls and added correct support for decorated enum detection...
r41 QByteArray enumScope = name.mid(0,scopePos);
QByteArray enumName = name.mid(scopePos+2);
PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(enumScope);
if (info) {
florianlink
cache enumWrappers in method infos and make use of the extra information for better enum overloading...
r55 return info->findEnumWrapper(enumName);
florianlink
fixed enum handling for static methods calls and added correct support for decorated enum detection...
r41 } else{
florianlink
cache enumWrappers in method infos and make use of the extra information for better enum overloading...
r55 return NULL;
florianlink
fixed enum handling for static methods calls and added correct support for decorated enum detection...
r41 }
}
if (localScope) {
florianlink
cache enumWrappers in method infos and make use of the extra information for better enum overloading...
r55 return localScope->findEnumWrapper(name);
florianlink
fixed enum handling for static methods calls and added correct support for decorated enum detection...
r41 } else {
florianlink
cache enumWrappers in method infos and make use of the extra information for better enum overloading...
r55 return NULL;
florianlink
fixed enum handling for static methods calls and added correct support for decorated enum detection...
r41 }
}
florianlink
added enum wrapper classes derived from python int, so that enums are distinguishable from normal python integers. This will allow better overload handling e.g. of QColor constructors in the future...
r51 void PythonQtClassInfo::createEnumWrappers(const QMetaObject* meta)
{
for (int i = meta->enumeratorOffset();i<meta->enumeratorCount();i++) {
QMetaEnum e = meta->enumerator(i);
PythonQtObjectPtr p;
florianlink
support enum values on signals as well, all tests should succeed now...
r56 p.setNewRef(PythonQtPrivate::createNewPythonQtEnumWrapper(e.name(), _pythonQtClassWrapper));
florianlink
added enum wrapper classes derived from python int, so that enums are distinguishable from normal python integers. This will allow better overload handling e.g. of QColor constructors in the future...
r51 _enumWrappers.append(p);
}
}
void PythonQtClassInfo::createEnumWrappers()
{
if (!_enumsCreated) {
_enumsCreated = true;
if (_meta) {
createEnumWrappers(_meta);
}
if (decorator()) {
createEnumWrappers(decorator()->metaObject());
}
foreach(const ParentClassInfo& info, _parentClasses) {
info._parent->createEnumWrappers();
}
}
}
PyObject* PythonQtClassInfo::findEnumWrapper(const char* name) {
florianlink
support enum values on signals as well, all tests should succeed now...
r56 // force enum creation
if (!_enumsCreated) {
createEnumWrappers();
}
florianlink
added enum wrapper classes derived from python int, so that enums are distinguishable from normal python integers. This will allow better overload handling e.g. of QColor constructors in the future...
r51 foreach(const PythonQtObjectPtr& p, _enumWrappers) {
const char* className = ((PyTypeObject*)p.object())->tp_name;
if (qstrcmp(className, name)==0) {
return p.object();
}
}
foreach(const ParentClassInfo& info, _parentClasses) {
PyObject* p = info._parent->findEnumWrapper(name);
if (p) return p;
}
return NULL;
}