itom 1.3.0
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 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 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 #ifndef ITOM_NPDATAOBJECT
00035     #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION //see comment in pythonNpDataObject.cpp
00036 #endif
00037 
00038 #ifndef Q_MOC_RUN
00039     //python
00040     // see http://vtk.org/gitweb?p=VTK.git;a=commitdiff;h=7f3f750596a105d48ea84ebfe1b1c4ca03e0bab3
00041     #if (defined _DEBUG) && (!defined linux)
00042         #undef _DEBUG
00043         #if (defined linux) | (defined CMAKE)
00044             #include "Python.h"
00045             #include "node.h"
00046             #include "numpy/arrayobject.h"
00047         #else
00048             #include "Python.h"
00049             #include "node.h"
00050             #include "../Lib/site-packages/numpy/core/include/numpy/arrayobject.h" //for numpy arrays
00051         #endif
00052         #define _DEBUG
00053     #else
00054     #ifdef linux
00055         #include "Python.h"
00056         #include "node.h"
00057         #include "numpy/arrayobject.h"
00058     #else
00059         #include "Python.h"
00060         #include "node.h"
00061         #include "../Lib/site-packages/numpy/core/include/numpy/arrayobject.h" //for numpy arrays
00062     #endif
00063     #endif
00064 #endif // Q_MOC_RUN
00065 
00066 /* includes */
00067 
00068 #include "pythonNpDataObject.h"
00069 #include "pythonItom.h"
00070 
00071 /*
00072 #ifdef linux
00073     #include "frameobject.h"
00074     #include "traceback.h"
00075 #else
00076     #include "include/frameobject.h" //!< for traceback
00077     #include "include/traceback.h"
00078 #endif
00079 */
00080 
00081 #include "../models/breakPointModel.h"
00082 #include "../../common/sharedStructuresQt.h"
00083 #include "../../common/addInInterface.h"
00084 
00085 #include "pythonWorkspace.h"
00086 
00087 #include <qstringlist.h>
00088 #include <qqueue.h>
00089 #include <qset.h>
00090 #include <qpointer.h>
00091 
00092 
00093 /* definition and macros */
00094 
00095 /* global variables (avoid) */
00096 
00097 /* content */
00098 
00099 class QDesktopWidget;
00100 class QTimer;
00101 
00102 namespace ito
00103 {
00104 
00105 class PythonEngine : public QObject
00106 {
00107     Q_OBJECT
00108 
00109 public:
00110     PythonEngine();                                 //constructor
00111     ~PythonEngine();                                //destructor
00112 
00113     Q_INVOKABLE void pythonSetup(ito::RetVal *retValue);               //setup
00114     Q_INVOKABLE ito::RetVal scanAndRunAutostartFolder(QString currentDirAfterScan = QString() );
00115     Q_INVOKABLE ito::RetVal pythonShutdown(ItomSharedSemaphore *aimWait = NULL);            //shutdown
00116 
00117     Q_INVOKABLE ito::RetVal stringEncodingChanged();
00118 
00119     inline ito::BreakPointModel *getBreakPointModel() const { return bpModel; }
00120     inline bool isPythonBusy() const                { return pythonState != ito::pyStateIdle; }
00121     inline bool isPythonDebugging() const           { return (pythonState == ito::pyStateDebuggingWaitingButBusy || pythonState == ito::pyStateDebugging || pythonState == ito::pyStateDebuggingWaiting); }
00122     inline bool isPythonDebuggingAndWaiting() const { return pythonState == ito::pyStateDebuggingWaiting; }
00123     inline bool execInternalCodeByDebugger() const  { return m_executeInternalPythonCodeInDebugMode; }
00124     inline void setExecInternalCodeByDebugger(bool value) { m_executeInternalPythonCodeInDebugMode = value; }
00125 
00126     ito::RetVal checkForPyExceptions();
00127     void printPythonErrorWithoutTraceback();
00128 
00129     void pythonDebugFunction(PyObject *callable, PyObject *argTuple);
00130     void pythonRunFunction(PyObject *callable, PyObject *argTuple);
00131 
00132     inline PyObject *getGlobalDictionary()  const { return globalDictionary;  }  
00134     inline bool pySyntaxCheckAvailable() const { return (m_pyModSyntaxCheck != NULL); }
00135 
00136     static const PythonEngine *getInstance();
00137 
00138     QList<int> parseAndSplitCommandInMainComponents(const char *str, QByteArray &encoding) const; //can be directly called from different thread
00139 
00140 protected:
00141     //RetVal syntaxCheck(char* pythonFileName);       // syntaxCheck for file with filename pythonFileName
00142     ito::RetVal runPyFile(const QString &pythonFileName);         // run file pythonFileName
00143     ito::RetVal debugFile(const QString &pythonFileName);         // debug file pythonFileName
00144     ito::RetVal runString(const QString &command);          // run string command
00145     ito::RetVal debugString(const QString &command);        // debug string command
00146     ito::RetVal debugFunction(PyObject *callable, PyObject *argTuple);
00147     ito::RetVal runFunction(PyObject *callable, PyObject *argTuple);
00148 
00149     ito::RetVal modifyTracebackDepth(int NrOfLevelsToPopAtFront = -1, bool showTraceback = true);
00150 
00151     void connectNotify(const char* signal);
00152 
00153 private:
00154     static PythonEngine *getInstanceInternal();
00155 
00156     inline PyObject *getLocalDictionary() { return localDictionary; } 
00158     PyObject *getPyObjectByFullName(bool globalNotLocal, const QStringList &fullName);
00159 
00160     void setGlobalDictionary(PyObject* mainDict = NULL);
00161     void setLocalDictionary(PyObject* localDict);
00162 
00163     void emitPythonDictionary(bool emitGlobal, bool emitLocal, PyObject* globalDict, PyObject* localDict);
00164 
00165     ito::RetVal pickleDictionary(PyObject *dict, const QString &filename);
00166     ito::RetVal unpickleDictionary(PyObject *destinationDict, const QString &filename, bool overwrite);
00167 
00168     //methods for maintaining python functionality
00169     ito::RetVal addMethodToModule(PyMethodDef* def);
00170     ito::RetVal delMethodFromModule(const char* ml_name);
00171     ito::RetVal pythonAddBuiltinMethods();
00172 
00173     //methods for debugging
00174     void enqueueDbgCmd(ito::tPythonDbgCmd dbgCmd);
00175     ito::tPythonDbgCmd dequeueDbgCmd();
00176     bool DbgCommandsAvailable();
00177     void clearDbgCmdLoop();
00178 
00179     ito::RetVal pythonStateTransition(tPythonTransitions transition);
00180 
00181     //methods for breakpoint
00182     ito::RetVal pythonAddBreakpoint(const QString &filename, const int lineno, const bool enabled, const bool temporary, const QString &condition, const int ignoreCount, int &pyBpNumber);
00183     ito::RetVal pythonEditBreakpoint(const int pyBpNumber, const QString &filename, const int lineno, const bool enabled, const bool temporary, const QString &condition, const int ignoreCount);
00184     ito::RetVal pythonDeleteBreakpoint(const int pyBpNumber);
00185 
00186     ito::RetVal autoReloaderCheck();
00187 
00188     //member variables
00189     bool m_started;
00190     //QString m_itomMemberClasses;
00191 
00192     //PyGILState_STATE threadState;
00193 
00194     QMutex dbgCmdMutex;
00195     QMutex pythonStateChangeMutex;
00196     QMutex dictChangeMutex;
00197     QDesktopWidget *m_pDesktopWidget;
00198     QQueue<ito::tPythonDbgCmd> debugCommandQueue;
00199     ito::tPythonDbgCmd debugCommand;
00200     
00201     ito::tPythonState pythonState;
00202     
00203     ito::BreakPointModel *bpModel;
00204 
00205     PyObject* mainModule;          
00206     PyObject* mainDictionary;      
00207     PyObject* localDictionary;     
00208     PyObject* globalDictionary;    
00209     PyObject *itomDbgModule;       
00210     PyObject *itomDbgInstance;     
00211     PyObject *itomModule;          
00212     PyObject *itomFunctions;       
00213     PyObject *m_pyModGC;
00214     PyObject *m_pyModSyntaxCheck;
00215     //PyObject *itomReturnException; //!< if this exception is thrown, the execution of the main application is stopped
00216 
00217     PyObject *dictUnicode;
00218 
00219     QSet<ito::PyWorkspaceContainer*> m_mainWorkspaceContainer;
00220     QSet<ito::PyWorkspaceContainer*> m_localWorkspaceContainer;
00221     QHash<QString, QPair<PyObject*,PyObject*> > m_pyFuncWeakRefHashes; 
00222     int m_pyFuncWeakRefHashesAutoInc;
00223     bool m_executeInternalPythonCodeInDebugMode; 
00224     PyMethodDef* PythonAdditionalModuleITOM;
00225 
00226     // decides if itom is automatically included in every source file before itīs handed to the syntax checker
00227     bool m_includeItom;
00228 
00229     struct AutoReload
00230     {
00231         PyObject *modAutoReload;
00232         PyObject *classAutoReload;
00233         bool enabled;
00234         bool checkFileExec;
00235         bool checkStringExec;
00236         bool checkFctExec;
00237     };
00238 
00239     AutoReload m_autoReload;
00240 
00242     static PyMethodDef PyMethodItomDbg[];
00243     static PyModuleDef PyModuleItomDbg;
00244     static PyObject* PyInitItomDbg(void);
00245     static PyObject* PyDbgCommandLoop(PyObject *pSelf, PyObject *pArgs);
00246 
00247     //helper methods
00248     //static PyObject* checkForTimeoutHelper(ItomSharedSemaphore* semaphore, int timeout, PyObject *retValueOk);
00249 
00250     //other static members
00251     static QMutex instatiated;
00252     static QMutex instancePtrProtection;
00253 
00254     static PythonEngine* instance;
00255 
00256     // friend class
00257     friend class ito::PythonItom;
00258 
00259 signals:
00260     void pythonDebugPositionChanged(QString filename, int lineNo);
00261     void pythonStateChanged(tPythonTransitions pyTransition);
00262     void pythonModifyLocalDict(PyObject* localDict, ItomSharedSemaphore* semaphore);
00263     void pythonModifyGlobalDict(PyObject* globalDict, ItomSharedSemaphore* semaphore);
00264     void pythonAddToolbarButton(QString toolbarName, QString buttonName, QString buttonIconFilename, QString pythonCode);
00265     void pythonRemoveToolbarButton(QString toolbarName, QString buttonName);
00266     void pythonAddMenuElement(int typeID, QString key, QString name, QString code, QString icon);
00267     void pythonRemoveMenuElement(QString key);
00268     void pythonCurrentDirChanged();
00269     void updateCallStack(QStringList filenames, IntList lines, QStringList methods);
00270     void deleteCallStack();
00271 
00272     void pythonSetCursor(const Qt::CursorShape cursor);
00273     void pythonResetCursor();
00274     void pythonAutoReloadChanged(bool enabled, bool checkFile, bool checkCmd, bool checkFct);
00275     void clearCommandLine();
00276 
00277 public slots:
00278     void pythonRunString(QString cmd);
00279     void pythonDebugString(QString cmd);
00280     void pythonExecStringFromCommandLine(QString cmd);
00281     void pythonRunFile(QString filename);
00282     void pythonDebugFile(QString filename);
00283     void pythonRunStringOrFunction(QString cmdOrFctHash);
00284     void pythonDebugStringOrFunction(QString cmdOrFctHash);
00285     void pythonInterruptExecution() const;
00286     void pythonDebugCommand(tPythonDbgCmd cmd);
00287 
00288     void setAutoReloader(bool enabled, bool checkFile, bool checkCmd, bool checkFct);
00289 
00290     // Settings are neccesary for automatic itom inclusion and syntax check
00291     void readSettings();
00292     void propertiesChanged();
00293 
00294     void pythonSyntaxCheck(const QString &code, QPointer<QObject> sender);
00295 
00296     void pythonGenericSlot(PyObject* callable, PyObject *argumentTuple);
00297 
00299     void breakPointAdded(BreakPointItem bp, int row);
00300     void breakPointDeleted(QString filename, int lineNo, int pyBpNumber);
00301     void breakPointChanged(BreakPointItem oldBp, BreakPointItem newBp);
00302     ito::RetVal setupBreakPointDebugConnections();
00303     ito::RetVal shutdownBreakPointDebugConnections();
00304 
00305     bool renameVariable(bool globalNotLocal, QString oldKey, QString newKey, ItomSharedSemaphore *semaphore = NULL);
00306     bool deleteVariable(bool globalNotLocal, QStringList keys, ItomSharedSemaphore *semaphore = NULL);
00307     ito::RetVal pickleVariables(bool globalNotLocal, QString filename, QStringList varNames, ItomSharedSemaphore *semaphore = NULL);
00308     ito::RetVal unpickleVariables(bool globalNotLocal, QString filename, ItomSharedSemaphore *semaphore = NULL);
00309     ito::RetVal saveMatlabVariables(bool globalNotLocal, QString filename, QStringList varNames, ItomSharedSemaphore *semaphore = NULL);
00310     ito::RetVal loadMatlabVariables(bool globalNotLocal, QString filename, ItomSharedSemaphore *semaphore = NULL);
00311     ito::RetVal registerAddInInstance(QString varname, ito::AddInBase *instance, ItomSharedSemaphore *semaphore = NULL);
00312     ito::RetVal getSysModules(QSharedPointer<QStringList> modNames, QSharedPointer<QStringList> modFilenames, QSharedPointer<IntList> modTypes, ItomSharedSemaphore *semaphore = NULL);
00313     ito::RetVal reloadSysModules(QSharedPointer<QStringList> modNames, ItomSharedSemaphore *semaphore = NULL);
00314 
00315     void registerWorkspaceContainer(PyWorkspaceContainer *container, bool registerNotUnregister, bool globalNotLocal);
00316     void workspaceGetChildNode(PyWorkspaceContainer *container, QString fullNameParentItem);
00317     void workspaceGetValueInformation(PyWorkspaceContainer *container, QString fullItemName, QSharedPointer<QString> extendedValue, ItomSharedSemaphore *semaphore = NULL);
00318 
00319     void putParamsToWorkspace(bool globalNotLocal, QStringList names, QVector<SharedParamBasePointer > values, ItomSharedSemaphore *semaphore = NULL);
00320     void getParamsFromWorkspace(bool globalNotLocal, QStringList names, QVector<int> paramBaseTypes, QSharedPointer<SharedParamBasePointerVector > values, ItomSharedSemaphore *semaphore = NULL);
00321 
00322 private slots:
00323 
00324 };
00325 
00326 } //end namespace ito
00327 
00328 
00329 #endif
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends