QPy
Python-Qt dynamic bindings
|
00001 #pragma once 00002 // QPy - Copyright (c) 2012,2013 Ugo Varetto 00003 // All rights reserved. 00004 // 00005 // Redistribution and use in source and binary forms, with or without 00006 // modification, are permitted provided that the following conditions are met: 00007 // * Redistributions of source code must retain the above copyright 00008 // notice, this list of conditions and the following disclaimer. 00009 // * Redistributions in binary form must reproduce the above copyright 00010 // notice, this list of conditions and the following disclaimer in the 00011 // documentation and/or other materials provided with the distribution. 00012 // * Neither the name of the author and copyright holder nor the 00013 // names of contributors to the project may be used to endorse or promote products 00014 // derived from this software without specific prior written permission. 00015 // 00016 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 00017 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00018 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00019 // DISCLAIMED. IN NO EVENT SHALL UGO VARETTO BE LIABLE FOR ANY 00020 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00021 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00022 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00023 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00024 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00025 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00026 00029 #include <Python.h> 00030 #include <QObject> 00031 #include <QMap> 00032 #include <QList> 00033 00034 namespace qpy { 00035 00036 class PyContext; 00037 00038 typedef QList< PyArgWrapper > CBackParameterTypes; 00039 00040 //------------------------------------------------------------------------------ 00047 class PyCBackMethod { 00048 public: 00055 PyCBackMethod( PyContext* pc, PyObject* pm, const CBackParameterTypes& p, PyObject* pyCBack ) 00056 : pc_( pc ), pyModule_( pm ), paramTypes_( p ), pyCBack_( pyCBack ) {} 00064 void Invoke( void **arguments ); 00066 PyObject* CBack() const{ return pyCBack_; } 00070 void DeleteCBack() { 00071 Py_XDECREF( pyCBack_ ); 00072 pyCBack_ = 0; 00073 } 00074 private: 00076 PyContext* pc_; 00078 CBackParameterTypes paramTypes_; 00080 PyObject* pyCBack_; 00082 PyObject* pyModule_; 00083 }; 00084 00085 00086 typedef PyObject* PyCBack; 00087 typedef int MethodId; 00088 00089 //------------------------------------------------------------------------------ 00103 class PyCallbackDispatcher : public QObject { 00104 public: 00106 PyCallbackDispatcher( QObject* parent = 0 ) 00107 : QObject( parent ), pc_( 0 ) {} 00109 PyCallbackDispatcher( PyContext* pc, PyObject* pm, QObject* parent = 0 ) 00110 : pc_( pc ), QObject( parent ) {} 00113 int qt_metacall( QMetaObject::Call c, int id, void **arguments ); 00121 bool Connect( QObject *obj, 00122 int signalIdx, 00123 const CBackParameterTypes& paramTypes, 00124 PyCBack pyCBack, 00125 PyObject* module ); 00130 bool Disconnect( QObject *obj, 00131 int signalIdx, 00132 PyCBack pyCBack ); 00134 void SetPyContext( PyContext* pc ) { pc_ = pc; }; 00136 virtual ~PyCallbackDispatcher() { 00137 for( QMap< int, PyCBackMethod* >::iterator i = pyCBackMethods_.begin(); 00138 i != pyCBackMethods_.end(); ++i ) { 00139 Py_XDECREF( i.value()->CBack() ); 00140 delete *i; 00141 } 00142 } 00143 private: 00144 int GetMethodIndex() const { 00145 return methodIdx_++; 00146 } 00147 private: 00149 PyContext* pc_; 00151 //QList< PyCBackMethod* > pyCBackMethods_; 00152 QMap< int, PyCBackMethod* > pyCBackMethods_; 00154 QMap< PyCBack, MethodId > cbackToMethodIndex_; 00155 00156 static int methodIdx_; //thread_local 00157 00158 }; 00159 }