|
PythonQt
|
00001 #ifndef _PYTHONQT_H 00002 #define _PYTHONQT_H 00003 00004 /* 00005 * 00006 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved. 00007 * 00008 * This library is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * This library is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * Further, this software is distributed without any warranty that it is 00019 * free of the rightful claim of any third person regarding infringement 00020 * or the like. Any license provided herein, whether implied or 00021 * otherwise, applies only to this software file. Patent licenses, if 00022 * any, provided herein do not apply to combinations of this program with 00023 * other software, or any other product whatsoever. 00024 * 00025 * You should have received a copy of the GNU Lesser General Public 00026 * License along with this library; if not, write to the Free Software 00027 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00028 * 00029 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29, 00030 * 28359 Bremen, Germany or: 00031 * 00032 * http://www.mevis.de 00033 * 00034 */ 00035 00036 //---------------------------------------------------------------------------------- 00043 //---------------------------------------------------------------------------------- 00044 00045 #include "PythonQtSystem.h" 00046 #include "PythonQtInstanceWrapper.h" 00047 #include "PythonQtClassWrapper.h" 00048 #include "PythonQtSlot.h" 00049 #include "PythonQtObjectPtr.h" 00050 #include "PythonQtStdIn.h" 00051 #include <QObject> 00052 #include <QVariant> 00053 #include <QList> 00054 #include <QHash> 00055 #include <QByteArray> 00056 #include <QStringList> 00057 #include <QtDebug> 00058 #include <iostream> 00059 00060 00061 class PythonQtClassInfo; 00062 class PythonQtPrivate; 00063 class PythonQtMethodInfo; 00064 class PythonQtSignalReceiver; 00065 class PythonQtImportFileInterface; 00066 class PythonQtCppWrapperFactory; 00067 class PythonQtForeignWrapperFactory; 00068 class PythonQtQFileImporter; 00069 00070 typedef void PythonQtQObjectWrappedCB(QObject* object); 00071 typedef void PythonQtQObjectNoLongerWrappedCB(QObject* object); 00072 typedef void* PythonQtPolymorphicHandlerCB(const void *ptr, const char **class_name); 00073 00074 typedef void PythonQtShellSetInstanceWrapperCB(void* object, PythonQtInstanceWrapper* wrapper); 00075 00076 template<class T> void PythonQtSetInstanceWrapperOnShell(void* object, PythonQtInstanceWrapper* wrapper) { 00077 (reinterpret_cast<T*>(object))->_wrapper = wrapper; 00078 } 00079 00081 template<class T1, class T2> int PythonQtUpcastingOffset() { 00082 return ((reinterpret_cast<char*>(static_cast<T2*>(reinterpret_cast<T1*>(0x100)))) 00083 - (reinterpret_cast<char*>(reinterpret_cast<T1*>(0x100)))); 00084 } 00085 00087 typedef QObject* PythonQtQObjectCreatorFunctionCB(); 00088 00090 template<class T> QObject* PythonQtCreateObject() { return new T(); }; 00091 00093 00101 class PYTHONQT_EXPORT PythonQt : public QObject { 00102 00103 Q_OBJECT 00104 00105 public: 00106 00108 enum InitFlags { 00109 RedirectStdOut = 1, 00110 IgnoreSiteModule = 2, 00111 ExternalHelp = 4, 00112 PythonAlreadyInitialized = 8 00113 }; 00114 00116 enum TypeSlots { 00117 Type_Add = 1, 00118 Type_Subtract = 1 << 1, 00119 Type_Multiply = 1 << 2, 00120 Type_Divide = 1 << 3, 00121 Type_Mod = 1 << 4, 00122 Type_And = 1 << 5, 00123 Type_Or = 1 << 6, 00124 Type_Xor = 1 << 7, 00125 Type_LShift = 1 << 8, 00126 Type_RShift = 1 << 9, 00127 00128 Type_InplaceAdd = 1 << 10, 00129 Type_InplaceSubtract = 1 << 11, 00130 Type_InplaceMultiply = 1 << 12, 00131 Type_InplaceDivide = 1 << 13, 00132 Type_InplaceMod = 1 << 14, 00133 Type_InplaceAnd = 1 << 15, 00134 Type_InplaceOr = 1 << 16, 00135 Type_InplaceXor = 1 << 17, 00136 Type_InplaceLShift = 1 << 18, 00137 Type_InplaceRShift = 1 << 19, 00138 00139 // Not yet needed/nicely mappable/generated... 00140 //Type_Positive = 1 << 29, 00141 //Type_Negative = 1 << 29, 00142 //Type_Abs = 1 << 29, 00143 //Type_Hash = 1 << 29, 00144 00145 Type_Invert = 1 << 29, 00146 Type_RichCompare = 1 << 30, 00147 Type_NonZero = 1 << 31, 00148 00149 }; 00150 00152 enum ProfilingCallbackState { 00153 Enter = 1, 00154 Leave = 2 00155 }; 00156 00159 typedef void ProfilingCB(ProfilingCallbackState state, const char* className, const char* methodName); 00160 00161 //--------------------------------------------------------------------------- 00163 00164 00168 static void init(int flags = IgnoreSiteModule | RedirectStdOut, const QByteArray& pythonQtModuleName = QByteArray()); 00169 00171 static void cleanup(); 00172 00174 static PythonQt* self(); 00175 00177 00179 enum ObjectType { 00180 Class, 00181 Function, 00182 Variable, 00183 Module, 00184 Anything, 00185 CallOverloads 00186 }; 00187 00188 00189 //--------------------------------------------------------------------------- 00191 00192 00195 void setRedirectStdInCallback(PythonQtInputChangedCB* callback, void * callbackData = 0); 00196 00199 void setRedirectStdInCallbackEnabled(bool enabled); 00200 00202 00203 //--------------------------------------------------------------------------- 00205 00206 00208 PythonQtObjectPtr getMainModule(); 00209 00212 PythonQtObjectPtr importModule(const QString& name); 00213 00218 PythonQtObjectPtr createModuleFromFile(const QString& name, const QString& filename); 00219 00224 PythonQtObjectPtr createModuleFromScript(const QString& name, const QString& script = QString()); 00225 00228 PythonQtObjectPtr createUniqueModule(); 00229 00231 00232 //--------------------------------------------------------------------------- 00234 00235 00237 void overwriteSysPath(const QStringList& paths); 00238 00240 void addSysPath(const QString& path); 00241 00243 void setModuleImportPath(PyObject* module, const QStringList& paths); 00244 00246 00247 //--------------------------------------------------------------------------- 00249 00250 00252 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject, 00253 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */ 00254 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL); 00255 00258 00264 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL); 00265 00268 void registerQObjectClassNames(const QStringList& names); 00269 00274 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset=0); 00275 00277 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb); 00278 00280 00281 //--------------------------------------------------------------------------- 00283 00284 00286 PythonQtObjectPtr parseFile(const QString& filename); 00287 00290 QVariant evalCode(PyObject* object, PyObject* pycode); 00291 00293 QVariant evalScript(PyObject* object, const QString& script, int start = Py_file_input); 00294 00296 void evalFile(PyObject* object, const QString& filename); 00297 00299 00300 //--------------------------------------------------------------------------- 00302 00303 00305 bool addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname); 00306 00308 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname); 00309 00311 bool addSignalHandler(QObject* obj, const char* signal, PyObject* receiver); 00312 00314 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver); 00315 00317 00318 //--------------------------------------------------------------------------- 00320 00321 00323 void addObject(PyObject* object, const QString& name, QObject* qObject); 00324 00326 void addVariable(PyObject* object, const QString& name, const QVariant& v); 00327 00329 void removeVariable(PyObject* module, const QString& name); 00330 00332 QVariant getVariable(PyObject* object, const QString& name); 00333 00335 QStringList introspection(PyObject* object, const QString& objectname, ObjectType type); 00337 QStringList introspectObject(PyObject* object, ObjectType type); 00342 QStringList introspectType(const QString& typeName, ObjectType type); 00343 00346 PythonQtObjectPtr lookupCallable(PyObject* object, const QString& name); 00347 00349 QString getReturnTypeOfWrappedMethod(PyObject* module, const QString& objectname); 00351 QString getReturnTypeOfWrappedMethod(const QString& typeName, const QString& methodName); 00353 00354 //--------------------------------------------------------------------------- 00356 00357 00359 QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList()); 00360 00362 QVariant call(PyObject* callable, const QVariantList& args = QVariantList()); 00363 00365 PyObject* callAndReturnPyObject(PyObject* callable, const QVariantList& args = QVariantList()); 00366 00368 00369 //--------------------------------------------------------------------------- 00371 00372 00377 00398 void addInstanceDecorators(QObject* o); 00399 00402 00416 void addClassDecorators(QObject* o); 00417 00419 void addDecorators(QObject* o); 00420 00422 void addWrapperFactory(PythonQtCppWrapperFactory* factory); 00423 00425 void addWrapperFactory(PythonQtForeignWrapperFactory* factory); 00426 00428 void removeWrapperFactory(PythonQtCppWrapperFactory* factory); 00429 00431 void removeWrapperFactory(PythonQtForeignWrapperFactory* factory); 00432 00434 00435 //--------------------------------------------------------------------------- 00437 00438 00448 void setImporter(PythonQtImportFileInterface* importInterface); 00449 00456 void installDefaultImporter() { setImporter(NULL); } 00457 00459 void setImporterIgnorePaths(const QStringList& paths); 00460 00462 const QStringList& getImporterIgnorePaths(); 00463 00465 static PythonQtImportFileInterface* importInterface(); 00466 00468 00469 //--------------------------------------------------------------------------- 00471 00472 00474 static PythonQtPrivate* priv() { return _self->_p; } 00475 00478 bool handleError(); 00479 00482 void clearNotFoundCachedMembers(); 00483 00485 void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb); 00487 void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb); 00488 00490 static void qObjectNoLongerWrappedCB(QObject* o); 00491 00493 PyObject* helpCalled(PythonQtClassInfo* info); 00494 00497 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name); 00498 00500 void setProfilingCallback(ProfilingCB* cb); 00501 00503 00504 signals: 00506 void pythonStdOut(const QString& str); 00508 void pythonStdErr(const QString& str); 00509 00511 void pythonHelpRequest(const QByteArray& cppClassName); 00512 00513 private: 00514 void initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName); 00515 00516 QString getReturnTypeOfWrappedMethodHelper(const PythonQtObjectPtr& variableObject, const QString& methodName, const QString& context); 00517 00518 PyObject* getObjectByType(const QString& typeName); 00519 00521 static void stdOutRedirectCB(const QString& str); 00523 static void stdErrRedirectCB(const QString& str); 00524 00526 PythonQtSignalReceiver* getSignalReceiver(QObject* obj); 00527 00528 PythonQt(int flags, const QByteArray& pythonQtModuleName); 00529 ~PythonQt(); 00530 00531 static PythonQt* _self; 00532 static int _uniqueModuleCount; 00533 00534 PythonQtPrivate* _p; 00535 00536 }; 00537 00539 class PYTHONQT_EXPORT PythonQtPrivate : public QObject { 00540 00541 Q_OBJECT 00542 00543 public: 00544 PythonQtPrivate(); 00545 ~PythonQtPrivate(); 00546 00547 enum DecoratorTypes { 00548 StaticDecorator = 1, 00549 ConstructorDecorator = 2, 00550 DestructorDecorator = 4, 00551 InstanceDecorator = 8, 00552 AllDecorators = 0xffff 00553 }; 00554 00556 const QStringList& sharedLibrarySuffixes() { return _sharedLibrarySuffixes; } 00557 00559 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; } 00560 00562 void addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper); 00564 void removeWrapperPointer(void* obj); 00565 00567 void shellClassDeleted(void* shellClass); 00568 00570 void* unwrapForeignWrapper(const QByteArray& classname, PyObject* obj); 00571 00573 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset); 00574 00576 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb); 00577 00579 PythonQtClassInfo* lookupClassInfoAndCreateIfNotPresent(const char* typeName); 00580 00582 void removeSignalEmitter(QObject* obj); 00583 00585 PyObject* wrapQObject(QObject* obj); 00586 00588 PyObject* wrapPtr(void* ptr, const QByteArray& name); 00589 00591 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject, 00592 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */ 00593 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0); 00594 00597 00603 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0); 00604 00607 void registerQObjectClassNames(const QStringList& names); 00608 00610 void addDecorators(QObject* o, int decoTypes); 00611 00613 PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* module); 00614 00616 static PyObject* createEnumValueInstance(PyObject* enumType, unsigned int enumValue); 00617 00619 static PyObject* createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject); 00620 00622 PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL); 00623 00625 PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownClassInfos.value(meta->className()); } 00626 00628 PythonQtClassInfo* getClassInfo(const QByteArray& className) { return _knownClassInfos.value(className); } 00629 00631 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode); 00632 00634 PythonQtClassInfo* currentClassInfoForClassWrapperCreation(); 00635 00637 static PyObject* dummyTuple(); 00638 00640 void handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result); 00641 00643 PythonQtObjectPtr pythonQtModule() const { return _pythonQtModule; } 00644 00646 PythonQt::ProfilingCB* profilingCB() const { return _profilingCB; } 00647 00649 QString getSignature(PyObject* object); 00650 00652 bool isMethodDescriptor(PyObject* object) const; 00653 00654 private: 00656 void setupSharedLibrarySuffixes(); 00657 00659 void createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module = NULL); 00660 00662 PyObject* packageByName(const char* name); 00663 00665 PythonQtInstanceWrapper* findWrapperAndRemoveUnused(void* obj); 00666 00668 QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects; 00669 00671 QHash<QByteArray, PythonQtClassInfo *> _knownClassInfos; 00672 00674 QHash<QByteArray, bool> _knownQObjectClassNames; 00675 00677 QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers; 00678 00680 PythonQtObjectPtr _pythonQtModule; 00681 00683 QByteArray _pythonQtModuleName; 00684 00686 PythonQtImportFileInterface* _importInterface; 00687 00689 PythonQtQFileImporter* _defaultImporter; 00690 00691 PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB; 00692 PythonQtQObjectWrappedCB* _wrappedCB; 00693 00694 QStringList _importIgnorePaths; 00695 QStringList _sharedLibrarySuffixes; 00696 00698 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories; 00699 00700 QList<PythonQtForeignWrapperFactory*> _foreignWrapperFactories; 00701 00702 QHash<QByteArray, PyObject*> _packages; 00703 00704 PythonQtClassInfo* _currentClassInfoForClassWrapperCreation; 00705 00706 PythonQt::ProfilingCB* _profilingCB; 00707 00708 int _initFlags; 00709 int _PythonQtObjectPtr_metaId; 00710 00711 friend class PythonQt; 00712 }; 00713 00714 #endif
1.7.4