itom 1.1.0
D:/git-itom/sources/itom/Qitom/python/pythonQtSignalMapper.h
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 #endif
00029 
00030 
00031 //python
00032 // see http://vtk.org/gitweb?p=VTK.git;a=commitdiff;h=7f3f750596a105d48ea84ebfe1b1c4ca03e0bab3
00033 #if (defined _DEBUG) && (!defined linux)
00034     #undef _DEBUG
00035     #include "Python.h"
00036     #define _DEBUG
00037 #else
00038     #include "Python.h"
00039 #endif
00040 
00041 #include "../global.h"
00042 
00043 #include <qvariant.h>
00044 #include <qobject.h>
00045 
00046 class PythonQtSignalTarget
00047 {
00048 public:
00049 
00051     PythonQtSignalTarget() :
00052         m_slotId(-1),
00053         m_signalId(-1),
00054         m_function(NULL),
00055         m_boundedInstance(NULL),
00056         m_boundedMethod(false)
00057 
00058     {
00059     };
00060 
00062 
00074     PythonQtSignalTarget(IntList &argTypeList, int slotId, int signalId, PyObject* callable, const char *signal) :
00075             m_slotId(slotId),
00076             m_signalId(signalId),
00077             m_function(NULL),
00078             m_boundedInstance(NULL),
00079             m_boundedMethod(false),
00080             m_signalName(signal)
00081     {
00082         m_argTypeList = argTypeList;
00083         PyObject *temp = NULL;
00084 
00085         if(PyMethod_Check(callable))
00086         {
00087             m_boundedMethod = true;
00088             Py_XDECREF(m_boundedInstance);
00089             Py_XDECREF(m_function);
00090             temp = PyMethod_Self(callable); //borrowed
00091             m_boundedInstance = PyWeakref_NewRef(temp, NULL); //new ref (weak reference used to avoid cyclic garbage collection)
00092             temp = PyMethod_Function(callable); //borrowed
00093             m_function = PyWeakref_NewRef(temp, NULL); //new ref
00094         }
00095         else if(PyFunction_Check(callable))
00096         {
00097             m_boundedMethod = false;
00098             Py_XDECREF(m_boundedInstance);
00099             Py_XDECREF(m_function);
00100             m_function = PyWeakref_NewRef(callable, NULL); //new ref
00101         }
00102     };
00103     
00105     PythonQtSignalTarget(const PythonQtSignalTarget &copy) :
00106         m_slotId(-1),
00107         m_signalId(-1),
00108         m_function(NULL),
00109         m_boundedInstance(NULL),
00110         m_boundedMethod(false),
00111         m_signalName(copy.m_signalName)
00112     {
00113         Py_XDECREF(m_boundedInstance);
00114         Py_XDECREF(m_function);
00115         m_slotId = copy.slotId();
00116         m_signalId = copy.signalId();
00117         m_argTypeList = copy.argTypeList();
00118 
00119         m_boundedMethod = copy.m_boundedMethod;
00120         m_function = copy.m_function;
00121         Py_XINCREF(m_function);
00122         m_boundedInstance = copy.m_boundedInstance;
00123         Py_XINCREF(m_boundedInstance);
00124     }
00125     
00127     ~PythonQtSignalTarget()
00128     {
00129         Py_XDECREF(m_boundedInstance);
00130         Py_XDECREF(m_function);
00131         m_argTypeList.clear();
00132     }
00133 
00135     inline int signalId() const { return m_signalId; }
00136 
00138     inline int slotId()  const { return m_slotId; }
00139 
00140     // call the python callable with the given arguments (docs see source file)
00141     void call(void ** arguments) const;
00142 
00144     inline IntList argTypeList() const { return m_argTypeList; };
00145 
00147 
00154     bool isSame(int signalId, PyObject* callable) const 
00155     { 
00156         if(signalId == m_signalId)
00157         {
00158             if(PyMethod_Check(callable))
00159             {
00160                 return PyMethod_Self(callable) == PyWeakref_GetObject(m_boundedInstance) && PyMethod_Function(callable) == PyWeakref_GetObject(m_function);
00161             }
00162             return callable == PyWeakref_GetObject(m_function);
00163         }
00164         return false;
00165     }
00166 
00167 private:
00168     int m_slotId;                
00169     int m_signalId;                
00170     IntList m_argTypeList;        
00171     PyObject *m_function;        
00172     PyObject *m_boundedInstance; 
00173     bool m_boundedMethod;        
00174     QString m_signalName;        
00175 };
00176 
00193 class PythonQtSignalMapperBase : public QObject 
00194 {
00195     Q_OBJECT
00196 public:
00197     PythonQtSignalMapperBase() {}; 
00198 };
00199 
00200 
00201 class PythonQtSignalMapper : public PythonQtSignalMapperBase
00202 {
00203 
00204 public:
00205     PythonQtSignalMapper(unsigned int initSlotCount); 
00206     ~PythonQtSignalMapper();
00207 
00208     bool addSignalHandler(QObject *obj, const char* signal, int sigId, PyObject* callable, IntList &argTypeList);
00209     bool removeSignalHandler(QObject *obj, const char* signal, int sigId, PyObject* callable);
00210     void removeSignalHandlers();
00211     virtual int qt_metacall(QMetaObject::Call c, int id, void **arguments);
00212    
00213 private:
00214     QList<PythonQtSignalTarget> m_targets;    
00215     int m_slotCount;                        
00216 };
00217 
00218 #endif
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends