itom 1.0.14
D:/git-itom/sources/itom/Qitom/python/pythonEngine.h
00001 /* ********************************************************************
00002     itom software
00003     URL: http://www.uni-stuttgart.de/ito
00004     Copyright (C) 2013, Institut für Technische Optik (ITO),
00005     Universität 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 PYTHONENGINE_H
00024 #define PYTHONENGINE_H
00025 
00026 /*if you add any include to this file you will DIE an immediate, horrible, painful death*/
00027 
00028 #include <string>
00029 //#ifndef Q_MOC_RUN
00030 //    #define PY_ARRAY_UNIQUE_SYMBOL itom_ARRAY_API
00031 //    #define NO_IMPORT_ARRAY
00032 //#endif
00033 
00034 //#define NPY_NO_DEPRECATED_API 0x00000007 //see comment in pythonNpDataObject.cpp
00035 
00036 //python
00037 // see http://vtk.org/gitweb?p=VTK.git;a=commitdiff;h=7f3f750596a105d48ea84ebfe1b1c4ca03e0bab3
00038 #ifdef _DEBUG
00039     #undef _DEBUG
00040     #if (defined linux) | (defined CMAKE)
00041         #include "Python.h"
00042         #include "node.h"
00043         #include "numpy/arrayobject.h"
00044     #else
00045         #include "Python.h"
00046         #include "node.h"
00047         #include "../Lib/site-packages/numpy/core/include/numpy/arrayobject.h" //for numpy arrays
00048     #endif
00049     #define _DEBUG
00050 #else
00051 #ifdef linux
00052     #include "Python.h"
00053     #include "node.h"
00054     #include "numpy/arrayobject.h"
00055 #else
00056     #include "Python.h"
00057     #include "node.h"
00058     #include "../Lib/site-packages/numpy/core/include/numpy/arrayobject.h" //for numpy arrays
00059 #endif
00060 #endif
00061 
00062 /* includes */
00063 
00064 #include "pythonNpDataObject.h"
00065 #include "pythonItom.h"
00066 
00067 /*
00068 #ifdef linux
00069     #include "frameobject.h"
00070     #include "traceback.h"
00071 #else
00072     #include "include/frameobject.h" //!< for traceback
00073     #include "include/traceback.h"
00074 #endif
00075 */
00076 
00077 #include "../models/breakPointModel.h"
00078 #include "../../common/sharedStructuresQt.h"
00079 #include "../../common/addInInterface.h"
00080 
00081 #include "pythonWorkspace.h"
00082 
00083 #include <qstringlist.h>
00084 #include <qqueue.h>
00085 #include <qset.h>
00086 
00087 
00088 /* definition and macros */
00089 
00090 /* global variables (avoid) */
00091 
00092 /* content */
00093 
00094 class QDesktopWidget;
00095 class QTimer;
00096 
00097 class PythonEngine : public QObject
00098 {
00099     Q_OBJECT
00100 
00101 public:
00102     PythonEngine();                                 //constructor
00103     ~PythonEngine();                                //destructor
00104 
00105     Q_INVOKABLE void pythonSetup(ito::RetVal *retValue);               //setup
00106     Q_INVOKABLE ito::RetVal scanAndRunAutostartFolder(QString currentDirAfterScan = QString() );
00107     Q_INVOKABLE ito::RetVal pythonShutdown(ItomSharedSemaphore *aimWait = NULL);            //shutdown
00108 
00109     Q_INVOKABLE ito::RetVal stringEncodingChanged();
00110 
00111     inline BreakPointModel *getBreakPointModel() const { return bpModel; }
00112     inline bool isPythonBusy() const { return pythonState != pyStateIdle; }
00113     inline bool isPythonDebugging() const { return (pythonState == pyStateDebuggingWaitingButBusy || pythonState == pyStateDebugging || pythonState == pyStateDebuggingWaiting); }
00114     inline bool isPythonDebuggingAndWaiting() const { return pythonState == pyStateDebuggingWaiting; }
00115     inline bool execInternalCodeByDebugger() const { return m_executeInternalPythonCodeInDebugMode; }
00116     inline void setExecInternalCodeByDebugger(bool value) { m_executeInternalPythonCodeInDebugMode = value; }
00117 
00118     ito::RetVal checkForPyExceptions();
00119     void printPythonErrorWithoutTraceback();
00120 
00121     void pythonDebugFunction(PyObject *callable, PyObject *argTuple);
00122     void pythonRunFunction(PyObject *callable, PyObject *argTuple);
00123 
00124         inline PyObject *getGlobalDictionary()  { return globalDictionary;  }  
00126     static const PythonEngine *getInstance();
00127 
00128     QList<int> parseAndSplitCommandInMainComponents(const char *str, QByteArray &encoding) const; //can be directly called from different thread
00129 
00130 protected:
00131     RetVal syntaxCheck(char* pythonFileName);       // syntaxCheck for file with filename pythonFileName
00132     RetVal runPyFile(char* pythonFileName);         // run file pythonFileName
00133     RetVal debugFile(char* pythonFileName);         // debug file pythonFileName
00134     RetVal runString(const char *command);          // run string command
00135     RetVal debugString(const char *command);        // debug string command
00136     RetVal debugFunction(PyObject *callable, PyObject *argTuple);
00137     RetVal runFunction(PyObject *callable, PyObject *argTuple);
00138 
00139     RetVal modifyTracebackDepth(int NrOfLevelsToPopAtFront = -1, bool showTraceback = true);
00140 
00141 private:
00142     static PythonEngine *getInstanceInternal();
00143 
00144     inline PyObject *getLocalDictionary() { return localDictionary; } 
00146     PyObject *getPyObjectByFullName(bool globalNotLocal, QStringList &fullName);
00147 
00148     void setGlobalDictionary(PyObject* mainDict = NULL);
00149     void setLocalDictionary(PyObject* localDict);
00150 
00151     void emitPythonDictionary(bool emitGlobal, bool emitLocal, PyObject* globalDict, PyObject* localDict);
00152 
00153     RetVal pickleDictionary(PyObject *dict, QString filename);
00154     RetVal unpickleDictionary(PyObject *destinationDict, QString filename, bool overwrite);
00155     RetVal saveDictAsMatlab(PyObject *dict, QString filename);
00156     RetVal loadMatlabToDict(PyObject *destinationDict, QString filename);
00157 
00158     //methods for maintaining python functionality
00159     RetVal addMethodToModule(PyMethodDef* def);
00160     RetVal delMethodFromModule(const char* ml_name);
00161     RetVal pythonAddBuiltinMethods();
00162 
00163     //methods for debugging
00164     void enqueueDbgCmd(tPythonDbgCmd dbgCmd);
00165     tPythonDbgCmd dequeueDbgCmd();
00166     bool DbgCommandsAvailable();
00167     void clearDbgCmdLoop();
00168 
00169     RetVal pythonStateTransition(tPythonTransitions transition);
00170 
00171     //methods for breakpoint
00172     RetVal pythonAddBreakpoint(const QString &filename, const int lineno, const bool enabled, const bool temporary, const QString &condition, const int ignoreCount, int &pyBpNumber);
00173     RetVal pythonEditBreakpoint(const int pyBpNumber, const QString &filename, const int lineno, const bool enabled, const bool temporary, const QString &condition, const int ignoreCount);
00174     RetVal pythonDeleteBreakpoint(const int pyBpNumber);
00175 
00176     //member variables
00177     bool started;
00178 
00179     //PyGILState_STATE threadState;
00180 
00181     QMutex dbgCmdMutex;
00182     QMutex pythonStateChangeMutex;
00183     QMutex dictChangeMutex;
00184     QDesktopWidget *m_pDesktopWidget;
00185     QQueue<tPythonDbgCmd> debugCommandQueue;
00186     tPythonDbgCmd debugCommand;
00187     
00188     tPythonState pythonState;
00189     
00190     BreakPointModel *bpModel;
00191 
00192     PyObject* mainModule;          
00193     PyObject* mainDictionary;      
00194     PyObject* localDictionary;     
00195         PyObject* globalDictionary;    
00196     PyObject *itomDbgModule;       
00197     PyObject *itomDbgInstance;     
00198     PyObject *itomModule;          
00199     PyObject *itomFunctions;       
00200     PyObject *gcModule;
00201     //PyObject *itomReturnException; //!< if this exception is thrown, the execution of the main application is stopped
00202 
00203     PyObject *dictUnicode;
00204 
00205     QSet<PyWorkspaceContainer*> m_mainWorkspaceContainer;
00206     QSet<PyWorkspaceContainer*> m_localWorkspaceContainer;
00207     QHash<QString, QPair<PyObject*,PyObject*> > m_pyFuncWeakRefHashes; 
00208     int m_pyFuncWeakRefHashesAutoInc;
00209     bool m_executeInternalPythonCodeInDebugMode; 
00210     PyMethodDef* PythonAdditionalModuleITOM;
00211 
00213     static PyMethodDef PyMethodItomDbg[];
00214     static PyModuleDef PyModuleItomDbg;
00215     static PyObject* PyInitItomDbg(void);
00216     static PyObject* PyDbgCommandLoop(PyObject *pSelf, PyObject *pArgs);
00217 
00218     //helper methods
00219     //static PyObject* checkForTimeoutHelper(ItomSharedSemaphore* semaphore, int timeout, PyObject *retValueOk);
00220 
00221     //other static members
00222     static QMutex instatiated;
00223     static QMutex instancePtrProtection;
00224 
00225     static PythonEngine* instance;
00226 
00227     // friend class
00228     friend class PythonDataObject;
00229     friend class ito::PythonItom;
00230 
00231 signals:
00232     void pythonDebugPositionChanged(QString filename, int lineNo);
00233     void pythonStateChanged(tPythonTransitions pyTransition);
00234     void pythonModifyLocalDict(PyObject* localDict, ItomSharedSemaphore* semaphore);
00235     void pythonModifyGlobalDict(PyObject* globalDict, ItomSharedSemaphore* semaphore);
00236     void pythonAddToolbarButton(QString toolbarName, QString buttonName, QString buttonIconFilename, QString pythonCode);
00237     void pythonRemoveToolbarButton(QString toolbarName, QString buttonName);
00238     void pythonAddMenuElement(int typeID, QString key, QString name, QString code, QString icon);
00239     void pythonRemoveMenuElement(QString key);
00240     void pythonCurrentDirChanged();
00241         void updateCallStack(QStringList filenames, IntList lines, QStringList methods);
00242         void deleteCallStack();
00243 
00244     void pythonSetCursor(const Qt::CursorShape cursor);
00245     void pythonResetCursor();
00246 
00247 public slots:
00248     void pythonRunString(QString cmd);
00249     void pythonDebugString(QString cmd);
00250     void pythonExecStringFromCommandLine(QString cmd);
00251     void pythonRunFile(QString filename);
00252     void pythonDebugFile(QString filename);
00253     void pythonRunStringOrFunction(QString cmdOrFctHash);
00254     void pythonDebugStringOrFunction(QString cmdOrFctHash);
00255     void pythonInterruptExecution() const;
00256     void pythonDebugCommand(tPythonDbgCmd cmd);
00257 
00258     void pythonGenericSlot(PyObject* callable, PyObject *argumentTuple);
00259 
00261     void breakPointAdded(BreakPointItem bp, int row);
00262     void breakPointDeleted(QString filename, int lineNo, int pyBpNumber);
00263     void breakPointChanged(BreakPointItem oldBp, BreakPointItem newBp);
00264     RetVal setupBreakPointDebugConnections();
00265     RetVal shutdownBreakPointDebugConnections();
00266 
00267     bool renameVariable(bool globalNotLocal, QString oldKey, QString newKey, ItomSharedSemaphore *semaphore = NULL);
00268     bool deleteVariable(bool globalNotLocal, QStringList keys, ItomSharedSemaphore *semaphore = NULL);
00269     RetVal pickleVariables(bool globalNotLocal, QString filename, QStringList varNames, ItomSharedSemaphore *semaphore = NULL);
00270     RetVal unpickleVariables(bool globalNotLocal, QString filename, ItomSharedSemaphore *semaphore = NULL);
00271     RetVal saveMatlabVariables(bool globalNotLocal, QString filename, QStringList varNames, ItomSharedSemaphore *semaphore = NULL);
00272     RetVal loadMatlabVariables(bool globalNotLocal, QString filename, ItomSharedSemaphore *semaphore = NULL);
00273     RetVal registerAddInInstance(QString varname, ito::AddInBase *instance, ItomSharedSemaphore *semaphore = NULL);
00274     RetVal getSysModules(QSharedPointer<QStringList> modNames, QSharedPointer<QStringList> modFilenames, QSharedPointer<IntList> modTypes, ItomSharedSemaphore *semaphore = NULL);
00275     RetVal reloadSysModules(QSharedPointer<QStringList> modNames, ItomSharedSemaphore *semaphore = NULL);
00276 
00277     void registerWorkspaceContainer(PyWorkspaceContainer *container, bool registerNotUnregister, bool globalNotLocal);
00278     void workspaceGetChildNode(ito::PyWorkspaceContainer *container, QString fullNameParentItem);
00279     void workspaceGetValueInformation(PyWorkspaceContainer *container, QString fullItemName, QSharedPointer<QString> extendedValue, ItomSharedSemaphore *semaphore = NULL);
00280 
00281     void putParamsToWorkspace(bool globalNotLocal, QStringList names, QVector<SharedParamBasePointer > values, ItomSharedSemaphore *semaphore = NULL);
00282     void getParamsFromWorkspace(bool globalNotLocal, QStringList names, QVector<int> paramBaseTypes, QSharedPointer<SharedParamBasePointerVector > values, ItomSharedSemaphore *semaphore = NULL);
00283 
00284 private slots:
00285 
00286 };
00287 
00288 
00289 #endif
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends