From 7064022fb8cf17d48094dfb6d1c3597fe2a9c1fc 2010-03-05 22:04:35 From: florianlink Date: 2010-03-05 22:04:35 Subject: [PATCH] added support for passing a parent python module when registering a class and allow to change the name of the PythonQt module git-svn-id: svn://svn.code.sf.net/p/pythonqt/code/trunk@146 ea8d5007-eb21-0410-b261-ccb3ea6e24a9 --- diff --git a/src/PythonQt.cpp b/src/PythonQt.cpp index 8ef5fe2..eeecd4a 100644 --- a/src/PythonQt.cpp +++ b/src/PythonQt.cpp @@ -56,79 +56,79 @@ PythonQt* PythonQt::_self = NULL; int PythonQt::_uniqueModuleCount = 0; -void PythonQt_init_QtGuiBuiltin(); -void PythonQt_init_QtCoreBuiltin(); +void PythonQt_init_QtGuiBuiltin(PyObject*); +void PythonQt_init_QtCoreBuiltin(PyObject*); -void PythonQt::init(int flags) +void PythonQt::init(int flags, const QByteArray& pythonQtModuleName) { if (!_self) { - _self = new PythonQt(flags); - } + _self = new PythonQt(flags, pythonQtModuleName); - PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList"); - qRegisterMetaType >("QList"); + PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList"); + qRegisterMetaType >("QList"); - PythonQtRegisterToolClassesTemplateConverter(int); - PythonQtRegisterToolClassesTemplateConverter(float); - PythonQtRegisterToolClassesTemplateConverter(double); - PythonQtRegisterToolClassesTemplateConverter(qint32); - PythonQtRegisterToolClassesTemplateConverter(quint32); - PythonQtRegisterToolClassesTemplateConverter(qint64); - PythonQtRegisterToolClassesTemplateConverter(quint64); - // TODO: which other POD types should be available for QList etc. + PythonQtRegisterToolClassesTemplateConverter(int); + PythonQtRegisterToolClassesTemplateConverter(float); + PythonQtRegisterToolClassesTemplateConverter(double); + PythonQtRegisterToolClassesTemplateConverter(qint32); + PythonQtRegisterToolClassesTemplateConverter(quint32); + PythonQtRegisterToolClassesTemplateConverter(qint64); + PythonQtRegisterToolClassesTemplateConverter(quint64); + // TODO: which other POD types should be available for QList etc. - PythonQt::self()->addDecorators(new PythonQtStdDecorators()); + PythonQt::self()->addDecorators(new PythonQtStdDecorators()); - PythonQt_init_QtCoreBuiltin(); - PythonQt_init_QtGuiBuiltin(); + PythonQt_init_QtCoreBuiltin(NULL); + PythonQt_init_QtGuiBuiltin(NULL); - PythonQtRegisterToolClassesTemplateConverter(QDate); - PythonQtRegisterToolClassesTemplateConverter(QTime); - PythonQtRegisterToolClassesTemplateConverter(QDateTime); - PythonQtRegisterToolClassesTemplateConverter(QUrl); - PythonQtRegisterToolClassesTemplateConverter(QLocale); - PythonQtRegisterToolClassesTemplateConverter(QRect); - PythonQtRegisterToolClassesTemplateConverter(QRectF); - PythonQtRegisterToolClassesTemplateConverter(QSize); - PythonQtRegisterToolClassesTemplateConverter(QSizeF); - PythonQtRegisterToolClassesTemplateConverter(QLine); - PythonQtRegisterToolClassesTemplateConverter(QLineF); - PythonQtRegisterToolClassesTemplateConverter(QPoint); - PythonQtRegisterToolClassesTemplateConverter(QPointF); - PythonQtRegisterToolClassesTemplateConverter(QRegExp); - - PythonQtRegisterToolClassesTemplateConverter(QFont); - PythonQtRegisterToolClassesTemplateConverter(QPixmap); - PythonQtRegisterToolClassesTemplateConverter(QBrush); - PythonQtRegisterToolClassesTemplateConverter(QColor); - PythonQtRegisterToolClassesTemplateConverter(QPalette); - PythonQtRegisterToolClassesTemplateConverter(QIcon); - PythonQtRegisterToolClassesTemplateConverter(QImage); - PythonQtRegisterToolClassesTemplateConverter(QPolygon); - PythonQtRegisterToolClassesTemplateConverter(QRegion); - PythonQtRegisterToolClassesTemplateConverter(QBitmap); - PythonQtRegisterToolClassesTemplateConverter(QCursor); - PythonQtRegisterToolClassesTemplateConverter(QSizePolicy); - PythonQtRegisterToolClassesTemplateConverter(QKeySequence); - PythonQtRegisterToolClassesTemplateConverter(QPen); - PythonQtRegisterToolClassesTemplateConverter(QTextLength); - PythonQtRegisterToolClassesTemplateConverter(QTextFormat); - PythonQtRegisterToolClassesTemplateConverter(QMatrix); - - - PyObject* pack = PythonQt::priv()->packageByName("QtCore"); - PyObject* pack2 = PythonQt::priv()->packageByName("Qt"); - PyObject* qtNamespace = PythonQt::priv()->getClassInfo("Qt")->pythonQtClassWrapper(); - const char* names[16] = {"SIGNAL", "SLOT", "qAbs", "qBound","qDebug","qWarning","qCritical","qFatal" + PythonQtRegisterToolClassesTemplateConverter(QDate); + PythonQtRegisterToolClassesTemplateConverter(QTime); + PythonQtRegisterToolClassesTemplateConverter(QDateTime); + PythonQtRegisterToolClassesTemplateConverter(QUrl); + PythonQtRegisterToolClassesTemplateConverter(QLocale); + PythonQtRegisterToolClassesTemplateConverter(QRect); + PythonQtRegisterToolClassesTemplateConverter(QRectF); + PythonQtRegisterToolClassesTemplateConverter(QSize); + PythonQtRegisterToolClassesTemplateConverter(QSizeF); + PythonQtRegisterToolClassesTemplateConverter(QLine); + PythonQtRegisterToolClassesTemplateConverter(QLineF); + PythonQtRegisterToolClassesTemplateConverter(QPoint); + PythonQtRegisterToolClassesTemplateConverter(QPointF); + PythonQtRegisterToolClassesTemplateConverter(QRegExp); + + PythonQtRegisterToolClassesTemplateConverter(QFont); + PythonQtRegisterToolClassesTemplateConverter(QPixmap); + PythonQtRegisterToolClassesTemplateConverter(QBrush); + PythonQtRegisterToolClassesTemplateConverter(QColor); + PythonQtRegisterToolClassesTemplateConverter(QPalette); + PythonQtRegisterToolClassesTemplateConverter(QIcon); + PythonQtRegisterToolClassesTemplateConverter(QImage); + PythonQtRegisterToolClassesTemplateConverter(QPolygon); + PythonQtRegisterToolClassesTemplateConverter(QRegion); + PythonQtRegisterToolClassesTemplateConverter(QBitmap); + PythonQtRegisterToolClassesTemplateConverter(QCursor); + PythonQtRegisterToolClassesTemplateConverter(QSizePolicy); + PythonQtRegisterToolClassesTemplateConverter(QKeySequence); + PythonQtRegisterToolClassesTemplateConverter(QPen); + PythonQtRegisterToolClassesTemplateConverter(QTextLength); + PythonQtRegisterToolClassesTemplateConverter(QTextFormat); + PythonQtRegisterToolClassesTemplateConverter(QMatrix); + + + PyObject* pack = PythonQt::priv()->packageByName("QtCore"); + PyObject* pack2 = PythonQt::priv()->packageByName("Qt"); + PyObject* qtNamespace = PythonQt::priv()->getClassInfo("Qt")->pythonQtClassWrapper(); + const char* names[16] = {"SIGNAL", "SLOT", "qAbs", "qBound","qDebug","qWarning","qCritical","qFatal" ,"qFuzzyCompare", "qMax","qMin","qRound","qRound64","qVersion","qrand","qsrand"}; - for (unsigned int i = 0;i<16; i++) { - PyObject* obj = PyObject_GetAttrString(qtNamespace, names[i]); - if (obj) { - PyModule_AddObject(pack, names[i], obj); - Py_INCREF(obj); - PyModule_AddObject(pack2, names[i], obj); - } else { - std::cerr << "method not found " << names[i]; + for (unsigned int i = 0;i<16; i++) { + PyObject* obj = PyObject_GetAttrString(qtNamespace, names[i]); + if (obj) { + PyModule_AddObject(pack, names[i], obj); + Py_INCREF(obj); + PyModule_AddObject(pack2, names[i], obj); + } else { + std::cerr << "method not found " << names[i]; + } } } } @@ -141,7 +141,7 @@ void PythonQt::cleanup() } } -PythonQt::PythonQt(int flags) +PythonQt::PythonQt(int flags, const QByteArray& pythonQtModuleName) { _p = new PythonQtPrivate; _p->_initFlags = flags; @@ -182,7 +182,7 @@ PythonQt::PythonQt(int flags) } Py_INCREF(&PythonQtStdOutRedirectType); - initPythonQtModule(flags & RedirectStdOut); + initPythonQtModule(flags & RedirectStdOut, pythonQtModuleName); _p->setupSharedLibrarySuffixes(); @@ -227,7 +227,7 @@ void PythonQt::registerClass(const QMetaObject* metaobject, const char* package, _p->registerClass(metaobject, package, wrapperCreator, shell); } -void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell) +void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module) { // we register all classes in the hierarchy const QMetaObject* m = metaobject; @@ -236,7 +236,7 @@ void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* p PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(m->className()); if (!info->pythonQtClassWrapper()) { info->setupQObject(m); - createPythonQtClassWrapper(info, package); + createPythonQtClassWrapper(info, package, module); if (m->superClass()) { PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(m->superClass()->className()); info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo)); @@ -255,12 +255,12 @@ void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* p } } -void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package) +void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module) { - PyObject* pack = packageByName(package); - PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info, package); + PyObject* pack = module?module:packageByName(package); + PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info, pack); PyModule_AddObject(pack, info->className(), pyobj); - if (package && strncmp(package,"Qt",2)==0) { + if (!module && package && strncmp(package,"Qt",2)==0) { // since PyModule_AddObject steals the reference, we need a incref once more... Py_INCREF(pyobj); // put all qt objects into Qt as well @@ -393,7 +393,7 @@ PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObje return result; } -PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, const char* package) { +PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* parentModule) { PythonQtClassWrapper* result; PyObject* className = PyString_FromString(info->className()); @@ -402,12 +402,8 @@ PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtCla PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type); PyObject* typeDict = PyDict_New(); - QByteArray moduleName("PythonQt"); - if (package && strcmp(package, "")!=0) { - moduleName += "."; - moduleName += package; - } - PyDict_SetItemString(typeDict, "__module__", PyString_FromString(moduleName.constData())); + PyObject* moduleName = PyObject_GetAttrString(parentModule, "__name__"); + PyDict_SetItemString(typeDict, "__module__", moduleName); PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict); @@ -1064,10 +1060,15 @@ static PyMethodDef PythonQtMethods[] = { {NULL, NULL, 0, NULL} }; -void PythonQt::initPythonQtModule(bool redirectStdOut) +void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName) { - _p->_pythonQtModule = Py_InitModule("PythonQt", PythonQtMethods); - + QByteArray name = "PythonQt"; + if (!pythonQtModuleName.isEmpty()) { + name = pythonQtModuleName; + } + _p->_pythonQtModule = Py_InitModule(name.constData(), PythonQtMethods); + _p->_pythonQtModuleName = name; + if (redirectStdOut) { PythonQtObjectPtr sys; PythonQtObjectPtr out; @@ -1129,12 +1130,12 @@ bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTyp } } -void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell) +void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module) { PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName); if (!info->pythonQtClassWrapper()) { info->setupCPPObject(typeName); - createPythonQtClassWrapper(info, package); + createPythonQtClassWrapper(info, package, module); } if (parentTypeName && strcmp(parentTypeName,"")!=0) { addParentClass(typeName, parentTypeName, 0); @@ -1154,7 +1155,7 @@ PyObject* PythonQtPrivate::packageByName(const char* name) } PyObject* v = _packages.value(name); if (!v) { - v = PyImport_AddModule((QByteArray("PythonQt.") + name).constData()); + v = PyImport_AddModule((_pythonQtModuleName + "." + name).constData()); _packages.insert(name, v); // AddObject steals the reference, so increment it! Py_INCREF(v); diff --git a/src/PythonQt.h b/src/PythonQt.h index 1e98d92..2aa3c0b 100644 --- a/src/PythonQt.h +++ b/src/PythonQt.h @@ -96,8 +96,10 @@ public: ExternalHelp = 4 //!<< sets if help() calls on PythonQt modules are forwarded to the pythonHelpRequest() signal }; - //! initialize the python qt binding (flags are a or combination of InitFlags) - static void init(int flags = IgnoreSiteModule | RedirectStdOut); + //! initialize the python qt binding (flags are a or combination of InitFlags), if \c pythonQtModuleName is given + //! it defines the name of the python module that PythonQt will add, otherwise "PythonQt" is used. + //! This can be used to e.g. pass in PySide or PyQt4 to make it more compatible. + static void init(int flags = IgnoreSiteModule | RedirectStdOut, const QByteArray& pythonQtModuleName = QByteArray()); //! cleanup static void cleanup(); @@ -361,7 +363,7 @@ public: PythonQtObjectPtr lookupObject(PyObject* module, const QString& name); private: - void initPythonQtModule(bool redirectStdOut); + void initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName); //! callback for stdout redirection, emits pythonStdOut signal static void stdOutRedirectCB(const QString& str); @@ -371,7 +373,7 @@ private: //! get (and create if not available) the signal receiver of that QObject, signal receiver is made child of the passed \c obj PythonQtSignalReceiver* getSignalReceiver(QObject* obj); - PythonQt(int flags); + PythonQt(int flags, const QByteArray& pythonQtModuleName); ~PythonQt(); static PythonQt* _self; @@ -430,7 +432,7 @@ public: //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well) /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject, you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */ - void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL); + void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL); //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants //! (ownership of wrapper is passed to PythonQt) @@ -440,7 +442,7 @@ public: All slots that take a pointer to typeName as the first argument will be callable from Python on a variant object that contains such a type. */ - void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL); + void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL); //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes //! and it will register the classes when it first sees a pointer to such a derived class @@ -450,7 +452,7 @@ public: void addDecorators(QObject* o, int decoTypes); //! helper method that creates a PythonQtClassWrapper object (returns a new reference) - PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, const char* package = NULL); + PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* module); //! create a new instance of the given enum type with given value (returns a new reference) static PyObject* createEnumValueInstance(PyObject* enumType, unsigned int enumValue); @@ -487,7 +489,7 @@ private: void setupSharedLibrarySuffixes(); //! create a new pythonqt class wrapper and place it in the pythonqt module - void createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package); + void createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module = NULL); //! get/create new package module (the returned object is a borrowed reference) PyObject* packageByName(const char* name); @@ -510,6 +512,9 @@ private: //! the PythonQt python module PythonQtObjectPtr _pythonQtModule; + //! the name of the PythonQt python module + QByteArray _pythonQtModuleName; + //! the importer interface (if set) PythonQtImportFileInterface* _importInterface;