itom 1.4.0
|
00001 /* ******************************************************************** 00002 itom software 00003 URL: http://www.uni-stuttgart.de/ito 00004 Copyright (C) 2013, Institut fuer Technische Optik (ITO), 00005 Universitaet Stuttgart, Germany 00006 00007 This file is part of itom. 00008 00009 itom is free software; you can redistribute it and/or modify it 00010 under the terms of the GNU Library General Public Licence as published by 00011 the Free Software Foundation; either version 2 of the Licence, or (at 00012 your option) any later version. 00013 00014 itom is distributed in the hope that it will be useful, but 00015 WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library 00017 General Public Licence for more details. 00018 00019 You should have received a copy of the GNU Library General Public License 00020 along with itom. If not, see <http://www.gnu.org/licenses/>. 00021 *********************************************************************** */ 00022 00023 #ifndef PYTHONQTSIGNALMAPPER_H 00024 #define PYTHONQTSIGNALMAPPER_H 00025 00026 #ifndef Q_MOC_RUN 00027 #define PY_ARRAY_UNIQUE_SYMBOL itom_ARRAY_API 00028 00029 //python 00030 // see http://vtk.org/gitweb?p=VTK.git;a=commitdiff;h=7f3f750596a105d48ea84ebfe1b1c4ca03e0bab3 00031 #if (defined _DEBUG) && (!defined linux) 00032 #undef _DEBUG 00033 #include "Python.h" 00034 #define _DEBUG 00035 #else 00036 #include "Python.h" 00037 #endif 00038 #endif 00039 00040 #include "../global.h" 00041 00042 #include <qvariant.h> 00043 #include <qobject.h> 00044 00045 namespace ito 00046 { 00047 00048 class PythonQtSignalTarget 00049 { 00050 public: 00051 00053 PythonQtSignalTarget() : 00054 m_slotId(-1), 00055 m_signalId(-1), 00056 m_function(NULL), 00057 m_boundedInstance(NULL), 00058 m_boundedMethod(false) 00059 00060 { 00061 }; 00062 00064 00076 PythonQtSignalTarget(IntList &argTypeList, int slotId, int signalId, PyObject* callable, const char *signal) : 00077 m_slotId(slotId), 00078 m_signalId(signalId), 00079 m_function(NULL), 00080 m_boundedInstance(NULL), 00081 m_boundedMethod(false), 00082 m_signalName(signal) 00083 { 00084 m_argTypeList = argTypeList; 00085 PyObject *temp = NULL; 00086 00087 if(PyMethod_Check(callable)) 00088 { 00089 m_boundedMethod = true; 00090 Py_XDECREF(m_boundedInstance); 00091 Py_XDECREF(m_function); 00092 temp = PyMethod_Self(callable); //borrowed 00093 m_boundedInstance = PyWeakref_NewRef(temp, NULL); //new ref (weak reference used to avoid cyclic garbage collection) 00094 temp = PyMethod_Function(callable); //borrowed 00095 m_function = PyWeakref_NewRef(temp, NULL); //new ref 00096 } 00097 else if(PyFunction_Check(callable)) 00098 { 00099 m_boundedMethod = false; 00100 Py_XDECREF(m_boundedInstance); 00101 Py_XDECREF(m_function); 00102 m_function = PyWeakref_NewRef(callable, NULL); //new ref 00103 } 00104 }; 00105 00107 PythonQtSignalTarget(const PythonQtSignalTarget ©) : 00108 m_slotId(-1), 00109 m_signalId(-1), 00110 m_function(NULL), 00111 m_boundedInstance(NULL), 00112 m_boundedMethod(false), 00113 m_signalName(copy.m_signalName) 00114 { 00115 Py_XDECREF(m_boundedInstance); 00116 Py_XDECREF(m_function); 00117 m_slotId = copy.slotId(); 00118 m_signalId = copy.signalId(); 00119 m_argTypeList = copy.argTypeList(); 00120 00121 m_boundedMethod = copy.m_boundedMethod; 00122 m_function = copy.m_function; 00123 Py_XINCREF(m_function); 00124 m_boundedInstance = copy.m_boundedInstance; 00125 Py_XINCREF(m_boundedInstance); 00126 } 00127 00129 ~PythonQtSignalTarget() 00130 { 00131 Py_XDECREF(m_boundedInstance); 00132 Py_XDECREF(m_function); 00133 m_argTypeList.clear(); 00134 } 00135 00137 inline int signalId() const { return m_signalId; } 00138 00140 inline int slotId() const { return m_slotId; } 00141 00142 // call the python callable with the given arguments (docs see source file) 00143 void call(void ** arguments) const; 00144 00146 inline IntList argTypeList() const { return m_argTypeList; }; 00147 00149 00156 bool isSame(int signalId, PyObject* callable) const 00157 { 00158 if(signalId == m_signalId) 00159 { 00160 if(PyMethod_Check(callable)) 00161 { 00162 return PyMethod_Self(callable) == PyWeakref_GetObject(m_boundedInstance) && PyMethod_Function(callable) == PyWeakref_GetObject(m_function); 00163 } 00164 return callable == PyWeakref_GetObject(m_function); 00165 } 00166 return false; 00167 } 00168 00169 private: 00170 int m_slotId; 00171 int m_signalId; 00172 IntList m_argTypeList; 00173 PyObject *m_function; 00174 PyObject *m_boundedInstance; 00175 bool m_boundedMethod; 00176 QString m_signalName; 00177 }; 00178 00195 class PythonQtSignalMapperBase : public QObject 00196 { 00197 Q_OBJECT 00198 public: 00199 PythonQtSignalMapperBase() {}; 00200 }; 00201 00202 00203 class PythonQtSignalMapper : public PythonQtSignalMapperBase 00204 { 00205 00206 public: 00207 PythonQtSignalMapper(unsigned int initSlotCount); 00208 ~PythonQtSignalMapper(); 00209 00210 bool addSignalHandler(QObject *obj, const char* signal, int sigId, PyObject* callable, IntList &argTypeList); 00211 bool removeSignalHandler(QObject *obj, const char* signal, int sigId, PyObject* callable); 00212 void removeSignalHandlers(); 00213 virtual int qt_metacall(QMetaObject::Call c, int id, void **arguments); 00214 00215 private: 00216 QList<PythonQtSignalTarget> m_targets; 00217 int m_slotCount; 00218 }; 00219 00220 } //end namespace ito 00221 00222 #endif