itom 1.3.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 
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 &copy) :
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
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends