]> SALOME platform Git repositories - modules/gui.git/commitdiff
Salome HOME
Win32 porting.
authornds <nds@opencascade.com>
Fri, 29 Aug 2008 08:59:11 +0000 (08:59 +0000)
committernds <nds@opencascade.com>
Fri, 29 Aug 2008 08:59:11 +0000 (08:59 +0000)
25 files changed:
src/ObjBrowser/ObjBrowser.pro
src/Plot2d/Plot2d.pro
src/Plot2d/Plot2d_HistogramItem.h
src/Plot2d/Plot2d_Object.h
src/Plot2d/Plot2d_ViewFrame.h
src/Prs/Prs.pro
src/PyConsole/PyConsole.h
src/PyConsole/PyConsole.pro
src/PyConsole/PyConsole_Console.cxx
src/PyConsole/PyConsole_Console.h
src/PyConsole/PyConsole_Editor.cxx
src/PyConsole/PyConsole_Editor.h
src/PyConsole/PyConsole_Interp.cxx
src/PyConsole/PyConsole_Interp.h
src/PyInterp/PyInterp.h
src/PyInterp/PyInterp.pro
src/PyInterp/PyInterp_Dispatcher.cxx
src/PyInterp/PyInterp_Dispatcher.h
src/PyInterp/PyInterp_Interp.cxx [new file with mode: 0644]
src/PyInterp/PyInterp_Interp.h [new file with mode: 0644]
src/PyInterp/PyInterp_Watcher.h
src/PyInterp/PyInterp_base.cxx [deleted file]
src/PyInterp/PyInterp_base.h [deleted file]
src/Qtx/Qtx.pro
src/STD/STD.pro

index 61bf93c5bd9bfdaa6f959008b0da065d8e0fa9aa..ff7dd2bd0ddd3fbd0047ccc1c3cdf0dcfdb31328 100644 (file)
@@ -1,4 +1,7 @@
-TEMPLATE = lib
+unix:TEMPLATE = lib
+win32:TEMPLATE = vclib
+
+win32:QMAKE_MOC=$(QTDIR)\bin\moc.exe
 
 DESTDIR = ../../$(CONFIG_ID)/lib
 MOC_DIR = ../../moc
@@ -6,12 +9,14 @@ OBJECTS_DIR = ../../$(CONFIG_ID)/obj/$$TARGET
 
 INCLUDEPATH += ../../include ../Qtx
 LIBS += -L../../$(CONFIG_ID)/lib -lQtx
+win32:LIBS *= -L$(QTLIB)
+win32:INCLUDEPATH *= $(QTINC) $(QTINC)\QtCore $(QTINC)\QtGui $(QTINC)\QtXml
 
 CONFIG -= debug release debug_and_release
 CONFIG += qt thread debug dll shared
 
-win32:DEFINES += WIN32
-DEFINES += LOGWINDOW_EXPORTS
+win32:DEFINES += WNT WIN32
+DEFINES += OB_EXPORTS
 
 HEADERS = *.h
 
@@ -24,7 +29,7 @@ win32:GUIResources = ..\\..\\resources
 
 lrelease.name = LRELASE ${QMAKE_FILE_IN}
 unix:lrelease.commands = $(QTDIR)/bin/lrelease ${QMAKE_FILE_NAME} -qm $${GUIResources}/${QMAKE_FILE_BASE}.qm
-win32:lrelease.commands = $(QTDIR)\\bin\\lrelease ${QMAKE_FILE_NAME} -qm $${GUIResources}\\${QMAKE_FILE_BASE}.qm
+win32:lrelease.commands = $(QTDIR)\\bin\\lrelease ${QMAKE_FILE_IN} -qm $${GUIResources}\\${QMAKE_FILE_BASE}.qm
 unix:lrelease.output = $${GUIResources}/${QMAKE_FILE_BASE}.qm
 win32:lrelease.output = $${GUIResources}\\${QMAKE_FILE_BASE}.qm
 lrelease.input = TRANSLATIONS
@@ -33,6 +38,13 @@ win32:lrelease.clean = $${GUIResources}\\${QMAKE_FILE_BASE}.qm
 lrelease.CONFIG += no_link target_predeps
 QMAKE_EXTRA_COMPILERS += lrelease
 
+win32:copy_hdr.name = Install ${QMAKE_FILE_IN}
+win32:copy_hdr.commands = type ${QMAKE_FILE_IN} > ../../include/${QMAKE_FILE_BASE}.h
+win32:copy_hdr.output = ../../include/${QMAKE_FILE_BASE}.h
+win32:copy_hdr.input = HEADERS
+win32:QMAKE_EXTRA_COMPILERS += copy_hdr
+
+
 includes.files = $$HEADERS
 includes.path = ../../include
 
index 9a06a130f1fefc409ef620efef077ec59fa26cdf..976b8d7c13e1eed981115a969994ffb06a2b47ee 100644 (file)
@@ -1,4 +1,7 @@
-TEMPLATE = lib
+unix:TEMPLATE = lib
+win32:TEMPLATE = vclib
+
+win32:QMAKE_MOC=$(QTDIR)\bin\moc.exe
 
 DESTDIR = ../../$(CONFIG_ID)/lib
 MOC_DIR = ../../moc
@@ -7,13 +10,15 @@ OBJECTS_DIR = ../../$(CONFIG_ID)/obj/$$TARGET
 INCLUDEPATH += ../../include $$(QWTINC) $$(PYTHONINC)
 INCLUDEPATH += ../Qtx ../SUIT
 unix:LIBS  += -L$$(QWTLIB) -lqwt
-win32:LIBS += /LIBPATH:$$(QWTLIB)
+win32:LIBS += /LIBPATH:$$(QWTLIB) -lqwt5
 LIBS += -L../../$(CONFIG_ID)/lib -lQtx -lSUIT
+win32:LIBS *= -L$(QTLIB)
+win32:INCLUDEPATH *= $(QTINC) $(QTINC)\QtCore $(QTINC)\QtGui $(QTINC)\QtXml
 
 CONFIG -= debug release debug_and_release
 CONFIG += qt thread debug dll shared
 
-win32:DEFINES += WIN32
+win32:DEFINES += WNT WIN32 QWT_DLL
 DEFINES += PLOT2D_EXPORTS
 
 HEADERS  = *.h
@@ -26,9 +31,15 @@ TRANSLATIONS = resources/Plot2d_msg_en.ts \
 unix:GUIResources = ../../resources
 win32:GUIResources = ..\\..\\resources
 
+win32:copy_hdr.name = Install headers ${QMAKE_FILE_IN}
+win32:copy_hdr.commands = type ${QMAKE_FILE_IN} > ${QMAKE_FILE_OUT}
+win32:copy_hdr.output = ../../include/${QMAKE_FILE_BASE}.h
+win32:copy_hdr.input = HEADERS
+win32:QMAKE_EXTRA_COMPILERS += copy_hdr
+
 lrelease.name = LRELASE ${QMAKE_FILE_IN}
-unix:lrelease.commands = $(QTDIR)/bin/lrelease ${QMAKE_FILE_NAME} -qm $${GUIResources}/${QMAKE_FILE_BASE}.qm
-win32:lrelease.commands = $(QTDIR)\\bin\\lrelease ${QMAKE_FILE_NAME} -qm $${GUIResources}\\${QMAKE_FILE_BASE}.qm
+unix:lrelease.commands = $(QTDIR)/bin/lrelease ${QMAKE_FILE_NAME} -qm ${QMAKE_FILE_OUT}
+win32:lrelease.commands = $(QTDIR)\\bin\\lrelease ${QMAKE_FILE_IN} -qm ${QMAKE_FILE_OUT}
 unix:lrelease.output = $${GUIResources}/${QMAKE_FILE_BASE}.qm
 win32:lrelease.output = $${GUIResources}\\${QMAKE_FILE_BASE}.qm
 lrelease.input = TRANSLATIONS
@@ -39,6 +50,14 @@ QMAKE_EXTRA_COMPILERS += lrelease
 
 ICONS = resources/*.png
 
+win32:SOURCES+=$$ICONS
+win32:Resource=$$ICONS
+win32:copy_res.name = Install resources ${QMAKE_FILE_IN}
+win32:copy_res.commands = type ${QMAKE_FILE_IN} > ${QMAKE_FILE_OUT}
+win32:copy_res.output = $${GUIResources}\\${QMAKE_FILE_BASE}.png
+win32:copy_res.input = Resource
+win32:QMAKE_EXTRA_COMPILERS += copy_res
+
 includes.files = $$HEADERS
 includes.path = ../../include
 
index 0e62a72937a9d484cd097b4484e69d5551041a58..889e829bb6f2c7a151b50349baae52c023fe062d 100644 (file)
@@ -66,7 +66,6 @@ protected:
 protected:
   void init();
 
-  class PrivateData;
   PrivateData* m_pData;
 };
 
index 3db5b1b915f518c9e5efd0ce836a18f3d87c4224..da2ea362d227fa4569393dade761f9115e7b4548 100755 (executable)
 #include <QList>
 #include <qwt_plot.h>
 
-typedef struct
+struct PLOT2D_EXPORT Plot2d_Point
 {
   double x;
   double y;
   QString text;
-} Plot2d_Point;
+};
 
 typedef QList<Plot2d_Point> pointList;
 
index 2637a16ab4980208bd2184d39eda672795dbc2cf..ced090ea868eec15e1699a767c0cedf4663588ab 100755 (executable)
@@ -225,6 +225,7 @@ class Plot2d_Plot2d : public QwtPlot
   Q_OBJECT
 public:
   Plot2d_Plot2d( QWidget* parent );
+  virtual ~Plot2d_Plot2d() {};
 
   void       setLogScale( int axisId, bool log10 );
 
index 06b1455390ea28863d323aa1ffccaeff1f335413..b4fe7e1fcbe6f905b17f812235db48d704b7d1b6 100644 (file)
@@ -1,19 +1,31 @@
-TEMPLATE = lib
+unix:TEMPLATE = lib
+win32:TEMPLATE = vclib
+
+win32:QMAKE_MOC=$(QTDIR)\bin\moc.exe
 
 DESTDIR = ../../$(CONFIG_ID)/lib
 MOC_DIR = ../../moc
 OBJECTS_DIR = ../../$(CONFIG_ID)/obj/$$TARGET
 
+win32:LIBS *= -L$(QTLIB)
+win32:INCLUDEPATH *= $(QTINC) $(QTINC)\QtCore $(QTINC)\QtGui $(QTINC)\QtXml
+
 CONFIG -= debug release debug_and_release
 CONFIG += qt thread debug dll shared
 
-win32:DEFINES += WIN32
+win32:DEFINES += WNT WIN32
 DEFINES += PRS_EXPORTS
 
 HEADERS  = *.h
 
 SOURCES  = *.cxx
 
+win32:copy_hdr.name = Install ${QMAKE_FILE_IN}
+win32:copy_hdr.commands = type ${QMAKE_FILE_IN} > ../../include/${QMAKE_FILE_BASE}.h
+win32:copy_hdr.output = ../../include/${QMAKE_FILE_BASE}.h
+win32:copy_hdr.input = HEADERS
+win32:QMAKE_EXTRA_COMPILERS += copy_hdr
+
 includes.files = $$HEADERS
 includes.path = ../../include
 
index 10a7106f6494243d5415c01784726ba6fcbb6bc9..d27c40c0fe21fcd2938ffbf1eb29132b6d9f3714 100644 (file)
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
-#if !defined ( _PYTHONCONSOLE_H )
-#define _PYTHONCONSOLE_H
+// File   : PyConsole.h
+// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
+//
+
+#if !defined ( PYCONSOLE_H )
+#define PYCONSOLE_H
 
 // ========================================================
 // set dllexport type for Win platform 
 #ifdef WIN32
-
-#ifdef PYCONSOLE_EXPORTS
-#define PYCONSOLE_EXPORT __declspec(dllexport)
-#else
-#define PYCONSOLE_EXPORT __declspec(dllimport)
-#endif
-
+#  ifdef PYCONSOLE_EXPORTS
+#    define PYCONSOLE_EXPORT __declspec(dllexport)
+#  else
+#    define PYCONSOLE_EXPORT __declspec(dllimport)
+#  endif
 #else   // WIN32
-
-#define PYCONSOLE_EXPORT
-
+#  define PYCONSOLE_EXPORT
 #endif  // WIN32
 
-// ========================================================
-// little trick - we do not have debug python libraries
-#ifdef _DEBUG
-
-#undef _DEBUG
-//#include <Python.h>
-#define _DEBUG
-
-#else  // _DEBUG
-
-//#include <Python.h>
-
-#endif // _DEBUG
-
 // ========================================================
 // avoid warning messages
 #ifdef WIN32
@@ -56,4 +42,4 @@
 #pragma warning (disable : 4251)
 #endif
 
-#endif // _PYTHONCONSOLE_H
+#endif // PYCONSOLE_H
index a4fd5061b3a257fb23bf2cb20acdf317ea5b0d6b..04e08a5e902eeea75dea25496bc37916b7cff8bc 100644 (file)
@@ -1,4 +1,7 @@
-TEMPLATE = lib
+unix:TEMPLATE = lib
+win32:TEMPLATE = vclib
+
+win32:QMAKE_MOC=$(QTDIR)\bin\moc.exe
 
 DESTDIR = ../../$(CONFIG_ID)/lib
 MOC_DIR = ../../moc
@@ -6,12 +9,14 @@ OBJECTS_DIR = ../../$(CONFIG_ID)/obj/$$TARGET
 
 INCLUDEPATH += ../../include $$(PYTHONINC)
 unix:LIBS  += -L../../$(CONFIG_ID)/lib -L$$(PYTHONLIB) -lpython2.5 -lSUIT -lPyInterp
-win32:LIBS += /LIBPATH:$$(PYTHONLIB) ../../lib/pyinterp.lib ../../lib/suit.lib
+win32:LIBS  += -L../../$(CONFIG_ID)/lib -L$$(PYTHONLIB) -lpython25_d -lSUIT -lPyInterp -lQtx
+win32:LIBS *= -L$(QTLIB)
+win32:INCLUDEPATH *= $(QTINC) $(QTINC)\QtCore $(QTINC)\QtGui $(QTINC)\QtXml
 
 CONFIG -= debug release debug_and_release
 CONFIG += qt thread debug dll shared
 
-win32:DEFINES += WIN32
+win32:DEFINES += WNT WIN32 HAVE_DEBUG_PYTHON
 DEFINES += PYCONSOLE_EXPORTS
 
 HEADERS = *.h
@@ -25,7 +30,7 @@ win32:GUIResources = ..\\..\\resources
 
 lrelease.name = LRELASE ${QMAKE_FILE_IN}
 unix:lrelease.commands = $(QTDIR)/bin/lrelease ${QMAKE_FILE_NAME} -qm $${GUIResources}/${QMAKE_FILE_BASE}.qm
-win32:lrelease.commands = $(QTDIR)\\bin\\lrelease ${QMAKE_FILE_NAME} -qm $${GUIResources}\\${QMAKE_FILE_BASE}.qm
+win32:lrelease.commands = $(QTDIR)\\bin\\lrelease ${QMAKE_FILE_IN} ${QMAKE_FILE_NAME} -qm $${GUIResources}\\${QMAKE_FILE_BASE}.qm
 unix:lrelease.output = $${GUIResources}/${QMAKE_FILE_BASE}.qm
 win32:lrelease.output = $${GUIResources}\\${QMAKE_FILE_BASE}.qm
 lrelease.input = TRANSLATIONS
@@ -34,6 +39,12 @@ win32:lrelease.clean = $${GUIResources}\\${QMAKE_FILE_BASE}.qm
 lrelease.CONFIG += no_link target_predeps
 QMAKE_EXTRA_COMPILERS += lrelease
 
+win32:copy_hdr.name = Install ${QMAKE_FILE_IN}
+win32:copy_hdr.commands = type ${QMAKE_FILE_IN} > ../../include/${QMAKE_FILE_BASE}.h
+win32:copy_hdr.output = ../../include/${QMAKE_FILE_BASE}.h
+win32:copy_hdr.input = HEADERS
+win32:QMAKE_EXTRA_COMPILERS += copy_hdr
+
 includes.files = $$HEADERS
 includes.path = ../../include
 
index 85ba6c722115b64837ddebcd53a95c996e1d0da2..85df7307abe5c4a0d80e225efeced83bab95c4be 100644 (file)
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
-//  File   : PythonConsole_PyConcole.cxx
-//  Author : Vadim SANDLER
-//  Module : SALOME
+// File   : PyConsole_Console.cxx
+// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
+//
 
 /*!
-  \class PythonConsole
+  \class PyConsole_Console
   \brief Python console widget.
 */  
 
-#include <Python.h>
-
+#include "PyConsole_Interp.h"   /// !!! WARNING !!! THIS INCLUDE MUST BE VERY FIRST !!!
 #include "PyConsole_Console.h"
 #include "PyConsole_Editor.h"
 
-#include <PyInterp_base.h>
-
-#include <QtGui/qmenu.h>
-#include <QtGui/qevent.h>
-#include <QtGui/qaction.h>
-#include <QtGui/qlayout.h>
-#include <QtGui/qclipboard.h>
-#include <QtGui/qapplication.h>
+#include <Qtx.h>
 
-using namespace std;
+#include <QAction>
+#include <QApplication>
+#include <QClipboard>
+#include <QEvent>
+#include <QMenu>
+#include <QVBoxLayout>
 
 /*!
   \brief Constructor.
@@ -48,9 +45,9 @@ using namespace std;
   \param parent parent widget
   \param interp python interpreter
 */
-PythonConsole::PythonConsole( QWidget* parent, PyInterp_base* interp )
-: QFrame( parent ),
-myEditor( 0 )
+PyConsole_Console::PyConsole_Console( QWidget* parent, PyConsole_Interp* interp )
+: QWidget( parent ),
+  myEditor( 0 )
 {
   // create python interpreter
   myInterp = interp;
@@ -62,7 +59,7 @@ myEditor( 0 )
   
   // create editor console
   QVBoxLayout* lay = new QVBoxLayout( this );
-  lay->setMargin( 5 );
+  lay->setMargin( 0 );
   myEditor = new PyConsole_Editor( myInterp, this );
   myEditor->viewport()->installEventFilter( this );
   lay->addWidget( myEditor );
@@ -75,15 +72,15 @@ myEditor( 0 )
 
   Does nothing for the moment.
 */
-PythonConsole::~PythonConsole()
+PyConsole_Console::~PyConsole_Console()
 {
 }
 
 /*!
   \brief Execute python command in the interpreter.
-  \param command string with command and arguments
+  \param command string with command and arguments
 */
-void PythonConsole::exec( const QString& command )
+void PyConsole_Console::exec( const QString& command )
 {
   if ( myEditor )
     myEditor->exec( command );
@@ -94,29 +91,45 @@ void PythonConsole::exec( const QString& command )
          and wait until it is finished.
   
   Block execution of main application until the python command is executed.
-  \param command string with command and arguments
+  \param command string with command and arguments
 */
-void PythonConsole::execAndWait( const QString& command )
+void PyConsole_Console::execAndWait( const QString& command )
 {
   if ( myEditor )
     myEditor->execAndWait( command );
 }
 
-bool PythonConsole::isSync() const
+/*!
+  \brief Get synchronous mode flag value.
+  
+  \sa setIsSync()
+  \return True if python console works in synchronous mode
+*/
+bool PyConsole_Console::isSync() const
 {
   return myEditor->isSync();
 }
 
-void PythonConsole::setIsSync( const bool s )
+/*!
+  \brief Set synchronous mode flag value.
+
+  In synhronous mode the Python commands are executed in the GUI thread
+  and the GUI is blocked until the command is finished. In the asynchronous
+  mode each Python command is executed in the separate thread that does not
+  block the main GUI loop.
+
+  \param on synhronous mode flag
+*/
+void PyConsole_Console::setIsSync( const bool on )
 {
-  myEditor->setIsSync( s );
+  myEditor->setIsSync( on );
 }
 
 /*!
   \brief Change the python console's font.
-  \param f new font
+  \param f new font
 */
-void PythonConsole::setFont( const QFont& f )
+void PyConsole_Console::setFont( const QFont& f )
 {
   if( myEditor )
     myEditor->setFont( f );
@@ -126,7 +139,7 @@ void PythonConsole::setFont( const QFont& f )
   \brief Get python console font.
   \return current python console's font
 */
-QFont PythonConsole::font() const
+QFont PyConsole_Console::font() const
 {
   QFont res;
   if( myEditor )
@@ -135,60 +148,112 @@ QFont PythonConsole::font() const
 }
 
 /*!
-  Custom event handler
+  \brief Event handler.
+
+  Handles context menu request event.
+
+  \param o object
+  \param e event
+  \return True if the event is processed and further processing should be stopped
 */
-bool PythonConsole::eventFilter( QObject* o, QEvent* e )
+bool PyConsole_Console::eventFilter( QObject* o, QEvent* e )
 {
   if ( o == myEditor->viewport() && e->type() == QEvent::ContextMenu )
   {
     contextMenuRequest( (QContextMenuEvent*)e );
     return true;
   }
-  return QFrame::eventFilter( o, e );
+  return QWidget::eventFilter( o, e );
 }
 
 /*!
-  \brief Process context popup menu event.
+  \brief Create the context popup menu.
+
+  Fill in the popup menu with the commands.
 
-  Show popup menu which includes standard copy/paste operations.
-  \param event context menu event
+  \param menu context popup menu
 */
-void PythonConsole::contextMenuPopup( QMenu* menu )
+void PyConsole_Console::contextMenuPopup( QMenu* menu )
 {
   if ( myEditor->isReadOnly() )
     return;
 
-  updateActions();
-
   menu->addAction( myActions[CopyId] );
   menu->addAction( myActions[PasteId] );
   menu->addAction( myActions[ClearId] );
-
   menu->addSeparator();
-
   menu->addAction( myActions[SelectAllId] );
+
+  Qtx::simplifySeparators( menu );
+
+  updateActions();
 }
 
-void PythonConsole::createActions()
+/*!
+  \brief Set actions to be visible in the context popup menu.
+  
+  Actions, which IDs are set in \a flags parameter, will be shown in the 
+  context popup menu. Other actions will not be shown.
+
+  \param flags ORed together actions flags
+*/
+void PyConsole_Console::setMenuActions( const int flags )
 {
-  QAction* copyAction = new QAction( tr( "EDIT_COPY_CMD" ), this );
-  connect( copyAction, SIGNAL( triggered( bool ) ), myEditor, SLOT( copy() ) );
-  myActions.insert( CopyId, copyAction );
+  myActions[CopyId]->setVisible( flags & CopyId );
+  myActions[PasteId]->setVisible( flags & PasteId );
+  myActions[ClearId]->setVisible( flags & ClearId );
+  myActions[SelectAllId]->setVisible( flags & SelectAllId );
+}
 
-  QAction* pasteAction = new QAction( tr( "EDIT_PASTE_CMD" ), this );
-  connect( pasteAction, SIGNAL( triggered( bool ) ), myEditor, SLOT( paste() ) );
-  myActions.insert( PasteId, pasteAction );
+/*!
+  \brief Get menu actions which are currently visible in the context popup menu.
+  \return ORed together actions flags
+  \sa setMenuActions()
+*/
+int PyConsole_Console::menuActions() const
+{
+  int ret = 0;
+  ret = ret | ( myActions[CopyId]->isVisible() ? CopyId : 0 );
+  ret = ret | ( myActions[PasteId]->isVisible() ? PasteId : 0 );
+  ret = ret | ( myActions[ClearId]->isVisible() ? ClearId : 0 );
+  ret = ret | ( myActions[SelectAllId]->isVisible() ? SelectAllId : 0 );
+  return ret;
+}
 
-  QAction* clearAction = new QAction( tr( "EDIT_CLEAR_CMD" ), this );
-  connect( clearAction, SIGNAL( triggered( bool ) ), myEditor, SLOT( clear() ) );
-  myActions.insert( ClearId, clearAction );
+/*!
+  \brief Create menu actions.
+
+  Create context popup menu actions.
+*/
+void PyConsole_Console::createActions()
+{
+  QAction* a = new QAction( tr( "EDIT_COPY_CMD" ), this );
+  a->setStatusTip( tr( "EDIT_COPY_CMD" ) );
+  connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( copy() ) );
+  myActions.insert( CopyId, a );
+
+  a = new QAction( tr( "EDIT_PASTE_CMD" ), this );
+  a->setStatusTip( tr( "EDIT_PASTE_CMD" ) );
+  connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( paste() ) );
+  myActions.insert( PasteId, a );
 
-  QAction* selAllAction = new QAction( tr( "EDIT_SELECTALL_CMD" ), this );
-  connect( selAllAction, SIGNAL( triggered( bool ) ), myEditor, SLOT( selectAll() ) );
-  myActions.insert( SelectAllId, selAllAction );
+  a = new QAction( tr( "EDIT_CLEAR_CMD" ), this );
+  a->setStatusTip( tr( "EDIT_CLEAR_CMD" ) );
+  connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( clear() ) );
+  myActions.insert( ClearId, a );
+
+  a = new QAction( tr( "EDIT_SELECTALL_CMD" ), this );
+  a->setStatusTip( tr( "EDIT_SELECTALL_CMD" ) );
+  connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( selectAll() ) );
+  myActions.insert( SelectAllId, a );
 }
 
-void PythonConsole::updateActions()
+/*!
+  \brief Update menu actions.
+
+  Update context popup menu action state.
+*/
+void PyConsole_Console::updateActions()
 {
   myActions[CopyId]->setEnabled( myEditor->textCursor().hasSelection() );
   myActions[PasteId]->setEnabled( !myEditor->isReadOnly() && !QApplication::clipboard()->text().isEmpty() );
index b25f4d1913f0ebf128129a50489c4517d3751844..ed1203b83e144776ebc350464ac6f356b1c9e5ab 100644 (file)
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
-//  File   : PythonConsole_PyConsole.h
-//  Author : Vadim SANDLER
-//  Module : SALOME
+// File   : PyConsole_Console.h
+// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
+//
 
 #ifndef PYCONSOLE_CONSOLE_H
 #define PYCONSOLE_CONSOLE_H
 
 #include "PyConsole.h"
 
-#include <QtCore/qmap.h>
-#include <QtGui/qframe.h>
-
 #include <SUIT_PopupClient.h>
+#include <QWidget>
+#include <QMap>
 
-class PyInterp_base;
+class PyConsole_Interp;
 class PyConsole_Editor;
 
-class PYCONSOLE_EXPORT PythonConsole : public QFrame, public SUIT_PopupClient
+class PYCONSOLE_EXPORT PyConsole_Console : public QWidget, public SUIT_PopupClient
 {
   Q_OBJECT
 
 public:
+  //! Context popup menu actions flags
   enum
   {
-    CopyId = 0x01,
-    PasteId = 0x02,
-    ClearId = 0x04,
-    SelectAllId = 0x08,
-    All = CopyId | PasteId | ClearId | SelectAllId
+    CopyId      = 0x01,                            //!< "Copy" menu action
+    PasteId     = 0x02,                            //!< "Paste" menu action
+    ClearId     = 0x04,                            //!< "Clear" menu action
+    SelectAllId = 0x08,                            //!< "Select All" menu action
+    All = CopyId | PasteId | ClearId | SelectAllId //!< all menu actions
   };
 
 public:
-  PythonConsole( QWidget* parent, PyInterp_base* interp = 0 );
-  virtual ~PythonConsole();
+  PyConsole_Console( QWidget* parent, PyConsole_Interp* interp = 0 );
+  virtual ~PyConsole_Console();
 
   //! \brief Get python interperter
-  PyInterp_base* getInterp() { return myInterp; } 
-  QFont          font() const;
-  virtual void   setFont( const QFont& );
+  PyConsole_Interp*   getInterp() { return myInterp; } 
+  QFont               font() const;
+  virtual void        setFont( const QFont& );
+
+  bool                isSync() const;
+  void                setIsSync( const bool );
 
-  bool           isSync() const;
-  void           setIsSync( const bool );
+  void                exec( const QString& );
+  void                execAndWait( const QString& );
 
-  void           exec( const QString& command );
-  void           execAndWait( const QString& command );
+  virtual bool        eventFilter( QObject*, QEvent* );
 
-  virtual bool   eventFilter( QObject* o, QEvent* e );
+  //! \brief Get popup client symbolic name
+  virtual QString     popupClientType() const { return QString( "PyConsole" ); }
+  virtual void        contextMenuPopup( QMenu* );
 
-  virtual QString popupClientType() const { return QString( "PyConsole" ); }
-  virtual void    contextMenuPopup( QMenu* );
+  void                setMenuActions( const int );
+  int                 menuActions() const;
 
 private:
   void                createActions();
   void                updateActions();
 
 private:
-  PyInterp_base*      myInterp;    //!< python interpreter
+  PyConsole_Interp*   myInterp;    //!< python interpreter
   PyConsole_Editor*   myEditor;    //!< python console editor widget
-  QMap<int, QAction*> myActions;
+  QMap<int, QAction*> myActions;   //!< menu actions list
 };
 
-#endif
+#endif // PYCONSOLE_CONSOLE_H
index 23268097ea5860b5ca0f44fef5ef7f1e7c455865..fea5d6804604178ef75d6115f5db99fc23c3634f 100644 (file)
@@ -19,9 +19,9 @@
 // 
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
-//  File   : PyConsole_Editor.cxx
-//  Author : Vadim SANDLER
-//  Module : SALOME
+// File   : PyConsole_Editor.cxx
+// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
+//
 
 /*!
   \class PyConsole_Editor
   - the same for drag-n-drop of multiline text
 */
 
-#include "PyConsole_Editor.h" // this include must be first (see PyInterp_base.h)!
-
+#include "PyConsole_Interp.h"   // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!!
+#include "PyConsole_Editor.h"
 #include <PyInterp_Dispatcher.h>
 
 #include <SUIT_Tools.h>
-#include <SUIT_Session.h>
-
-#include <QtGui/qmenu.h>
-#include <QtGui/qevent.h>
-#include <QtGui/qclipboard.h>
-#include <QtGui/qscrollbar.h>
-#include <QtGui/qtextobject.h>
-#include <QtGui/qtextcursor.h>
-#include <QtGui/qapplication.h>
-#include <QtGui/qtextdocument.h>
 
-using namespace std;
+#include <QApplication>
+#include <QClipboard>
+#include <QDropEvent>
+#include <QEvent>
+#include <QKeyEvent>
+#include <QMouseEvent>
+#include <QScrollBar>
+#include <QTextBlock>
+#include <QTextCursor>
+#include <QTextDocument>
 
 static QString READY_PROMPT = ">>> ";
 static QString DOTS_PROMPT  = "... ";
 #define PROMPT_SIZE myPrompt.length()
 
+#define PRINT_EVENT 65432
+
 /*!
   \class ExecCommand
-  \brief Python command execution request [internal].
- */
+  \brief Python command execution request.
+  \internal
+*/
+
 class ExecCommand : public PyInterp_LockRequest
 {
 public:
@@ -130,7 +133,7 @@ public:
     \param theListener widget to get the notification messages
     \param sync        if True the request is processed synchronously 
   */
-  ExecCommand( PyInterp_base*          theInterp, 
+  ExecCommand( PyInterp_Interp*        theInterp, 
               const QString&          theCommand,
               PyConsole_Editor*       theListener, 
               bool                    sync = false )
@@ -147,21 +150,12 @@ protected:
   {
     if ( myCommand != "" )
     {
-//      SUIT_Session::SetPythonExecuted( true ); // disable GUI user actions
       int ret = getInterp()->run( myCommand.toLatin1() );
-//      SUIT_Session::SetPythonExecuted(false); // enable GUI user actions
       if ( ret < 0 )
-             myState = PyInterp_Event::ERROR;
+       myState = PyInterp_Event::ERROR;
       else if ( ret > 0 )
-             myState = PyInterp_Event::INCOMPLETE;
-      myError  = getInterp()->getverr().c_str();
-      myOutput = getInterp()->getvout().c_str();
+       myState = PyInterp_Event::INCOMPLETE;
     } 
-    else
-    {
-      myError = "";
-      myOutput = "";
-    }
   }
 
   /*!
@@ -170,18 +164,45 @@ protected:
   */
   virtual QEvent* createEvent() const
   {
+    if ( IsSync() )
+      QCoreApplication::sendPostedEvents( listener(), PRINT_EVENT );
     return new PyInterp_Event( myState, (PyInterp_Request*)this );    
   }
 
-public:
-  QString myError;     //!< Python command error message
-  QString myOutput;    //!< Python command output log
-
 private:
   QString myCommand;   //!< Python command
   int     myState;     //!< Python command execution status
 };
 
+/*!
+  \class PrintEvent
+  \brief Python command output backend event.
+  \internal
+*/
+
+class PrintEvent : public QEvent
+{
+public:
+  /*!
+    \brief Constructor
+    \param c message text (python trace)
+  */
+  PrintEvent( const char* c ) : QEvent( (QEvent::Type)PRINT_EVENT ), myText( c ) {}
+  /*!
+    \brief Get message
+    \return message text (python trace)
+  */
+  QString text() const { return myText; }
+
+private:
+  QString myText; //!< Event message (python trace)
+};
+
+void staticCallback( void* data, char* c )
+{
+  QApplication::postEvent( (PyConsole_Editor*)data, new PrintEvent( c ) ); 
+}
+
 /*!
   \brief Constructor. 
   
@@ -189,8 +210,8 @@ private:
   \param theInterp python interper
   \param theParent parent widget
 */
-PyConsole_Editor::PyConsole_Editor( PyInterp_base* theInterp, 
-                                   QWidget*       theParent )
+PyConsole_Editor::PyConsole_Editor( PyConsole_Interp* theInterp, 
+                                   QWidget*          theParent )
 : QTextEdit( theParent ),
   myInterp( 0 ),
   myCmdInHistory( -1 ),
@@ -203,10 +224,13 @@ PyConsole_Editor::PyConsole_Editor( PyInterp_base* theInterp,
   setUndoRedoEnabled( false );
 
   myPrompt = READY_PROMPT;
-  setLineWrapMode( QTextEdit::NoWrap );
-  setWordWrapMode( QTextOption::NoWrap );
+  setLineWrapMode( QTextEdit::WidgetWidth );
+  setWordWrapMode( QTextOption::WrapAnywhere );
   setAcceptRichText( false );
 
+  theInterp->setvoutcb( staticCallback, this );
+  theInterp->setverrcb( staticCallback, this );
+
   // san - This is necessary for troubleless initialization
   onPyInterpChanged( theInterp );
 }
@@ -220,14 +244,30 @@ PyConsole_Editor::~PyConsole_Editor()
 {
 }
 
+/*!
+  \brief Get synchronous mode flag value.
+  
+  \sa setIsSync()
+  \return True if python console works in synchronous mode
+*/
 bool PyConsole_Editor::isSync() const
 {
   return myIsSync;
 }
 
-void PyConsole_Editor::setIsSync( const bool s )
+/*!
+  \brief Set synchronous mode flag value.
+
+  In synhronous mode the Python commands are executed in the GUI thread
+  and the GUI is blocked until the command is finished. In the asynchronous
+  mode each Python command is executed in the separate thread that does not
+  block the main GUI loop.
+
+  \param on synhronous mode flag
+*/
+void PyConsole_Editor::setIsSync( const bool on )
 {
-  myIsSync = s;
+  myIsSync = on;
 }
 
 /*!
@@ -236,7 +276,7 @@ void PyConsole_Editor::setIsSync( const bool s )
   \param newBlock if True, then the string is printed on a new line
 */
 void PyConsole_Editor::addText( const QString& str, 
-                                     const bool     newBlock )
+                               const bool     newBlock )
 {
   moveCursor( QTextCursor::End );
   if ( newBlock )
@@ -288,14 +328,20 @@ void PyConsole_Editor::exec( const QString& command )
   PyInterp_Dispatcher::Get()->Exec( createRequest( cmd ) );
 }
 
-PyInterp_Request* PyConsole_Editor::createRequest( const QString& cmd )
+/*!
+  \brief Create request to the python dispatcher for the command execution.
+
+  \param command python command to be executed
+ */
+PyInterp_Request* PyConsole_Editor::createRequest( const QString& command )
 {
-  return new ExecCommand( myInterp, cmd, this, isSync() );
+  return new ExecCommand( myInterp, command, this, isSync() );
 }
 
 /*!
   \brief Execute command in the python interpreter
   and wait until it is finished.
+
   \param command python command to be executed
  */
 void PyConsole_Editor::execAndWait( const QString& command )
@@ -333,6 +379,9 @@ void PyConsole_Editor::handleReturn()
   // add command to the history
   if ( !cmd.trimmed().isEmpty() )
     myHistory.push_back( cmd );
+
+  // IPAL19397
+  addText( "", true ); 
   
   // set read-only mode
   setReadOnly( true );
@@ -566,7 +615,7 @@ void PyConsole_Editor::keyPressEvent( QKeyEvent* event )
          moveCursor( QTextCursor::End );
          moveCursor( QTextCursor::StartOfBlock, QTextCursor::KeepAnchor );
          textCursor().removeSelectedText();
-         addText( myPrompt + ( nextCommand != TOP_HISTORY_PY ? nextCommand : myCurrentCommand ) ); 
+         addText( myPrompt + nextCommand );
          // move cursor to the end
          moveCursor( QTextCursor::End );
        }
@@ -851,25 +900,24 @@ void PyConsole_Editor::customEvent( QEvent* event )
 {
   switch( event->type() )
   {
+  case PRINT_EVENT:
+    {
+      PrintEvent* pe=(PrintEvent*)event;
+      addText( pe->text() );
+      return;
+    }
   case PyInterp_Event::OK:
   case PyInterp_Event::ERROR:
   {
-    PyInterp_Event* pe = dynamic_cast<PyInterp_Event*>( event );
-    if ( pe )
-    {
-      ExecCommand* ec = dynamic_cast<ExecCommand*>( pe->GetRequest() );
-      if ( ec )
-      {
-       // The next line has appeared dangerous in case if
-       // Python command execution has produced very large output.
-       // A more clever approach is needed...
-       // print python output
-       addText( ec->myOutput, true );
-       addText( ec->myError );
-      }
-    }
     // clear command buffer
     myCommandBuffer.truncate( 0 );
+    // add caret return line if necessary
+    QTextBlock par = document()->end().previous();
+    QString txt = par.text();
+    txt.truncate( txt.length() - 1 );
+    // IPAL19397 : addText moved to handleReturn() method
+    //if ( !txt.isEmpty() )
+    //  addText( "", true );
     // set "ready" prompt
     myPrompt = READY_PROMPT;
     addText( myPrompt );
@@ -884,9 +932,16 @@ void PyConsole_Editor::customEvent( QEvent* event )
   {
     // extend command buffer (multi-line command)
     myCommandBuffer.append( "\n" );
+    // add caret return line if necessary
+    QTextBlock par = document()->end().previous();
+    QString txt = par.text();
+    txt.truncate( txt.length() - 1 );
+    // IPAL19397 : addText moved to handleReturn() method
+    //if ( !txt.isEmpty() )
+    //  addText( "", true );
     // set "dot" prompt
     myPrompt = DOTS_PROMPT;
-    addText( myPrompt, true );
+    addText( myPrompt/*, true*/ ); // IPAL19397
     // unset busy cursor
     unsetCursor();
     // stop event loop (if running)
@@ -918,7 +973,7 @@ void PyConsole_Editor::customEvent( QEvent* event )
   Perform initialization actions if the interpreter is changed.
   \param interp python interpreter is being set
 */
-void PyConsole_Editor::onPyInterpChanged( PyInterp_base* interp )
+void PyConsole_Editor::onPyInterpChanged( PyConsole_Interp* interp )
 {
   if ( myInterp != interp 
        // Force read-only state and wait cursor when myInterp is NULL
index 12deee059f8ecd2cbdc2c4d9753d1f4051017e12..222708c6ecc113b2e455a896c0e01e849b3859b2 100644 (file)
 // 
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
-//  File   : PyConsole_Editor.h
-//  Author : Vadim SANDLER
-//  Module : SALOME
+// File   : PyConsole_Editor.h
+// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
+//
 
 #ifndef PYCONSOLE_EDITOR_H
 #define PYCONSOLE_EDITOR_H
 
-#include "PyConsole_Interp.h" // this include must be first (see PyInterp_base.h)!
+#include "PyConsole.h"
 
-#include <QtGui/qtextedit.h>
+#include <QTextEdit>
 
-class QMenu;
-class QEventLoop;
 class PyConsole_Interp;
 class PyInterp_Request;
+class QEventLoop;
 
 class PYCONSOLE_EXPORT PyConsole_Editor : public QTextEdit
 {
   Q_OBJECT;
 
 public:
-  PyConsole_Editor( PyInterp_base* theInterp, QWidget *theParent = 0 );
+  PyConsole_Editor( PyConsole_Interp* theInterp, QWidget *theParent = 0 );
   ~PyConsole_Editor();
   
   virtual void   addText( const QString& str, const bool newBlock = false ); 
@@ -59,26 +58,26 @@ protected:
   virtual void   customEvent( QEvent* event);
 
   virtual PyInterp_Request* createRequest( const QString& );
-  
+
 public slots:
   void           cut();
   void           paste();
   void           clear();
   void           handleReturn();
-  void           onPyInterpChanged( PyInterp_base* );
+  void           onPyInterpChanged( PyConsole_Interp* );
   
 private:
-  PyInterp_base* myInterp;           //!< python interpreter
+  PyConsole_Interp* myInterp;           //!< python interpreter
 
-  QString        myCommandBuffer;    //!< python comman buffer
-  QString        myCurrentCommand;   //!< currently being printed command
-  QString        myPrompt;           //!< current command line prompt
-  int            myCmdInHistory;     //!< current history command index
-  QStringList    myHistory;          //!< commands history buffer
-  QEventLoop*    myEventLoop;        //!< internal event loop
-  QString        myBanner;           //!< current banner
-  QStringList    myQueue;            //!< python commands queue
-  bool           myIsSync;
+  QString           myCommandBuffer;    //!< python comman buffer
+  QString           myCurrentCommand;   //!< currently being printed command
+  QString           myPrompt;           //!< current command line prompt
+  int               myCmdInHistory;     //!< current history command index
+  QStringList       myHistory;          //!< commands history buffer
+  QEventLoop*       myEventLoop;        //!< internal event loop
+  QString           myBanner;           //!< current banner
+  QStringList       myQueue;            //!< python commands queue
+  bool              myIsSync;           //!< synchronous mode flag
 };
 
-#endif
+#endif // PYCONSOLE_EDITOR_H
index b71c02178ddbd383b72e888ab48962c25d97f763..234e55973401f34581d8f000c91fe5ef10025267 100644 (file)
   \brief Python interpreter to be embedded to the SALOME study's GUI.
 
   Python interpreter is created one per SALOME study.
-  Calls initialize method defined in the base class, which calls redefined 
-  virtual methods initState() & initContext().
+
+  Call initialize method defined in the base class PyInterp_Interp,
+  to intialize interpreter after instance creation.
+
+  The method initialize() calls virtuals methods
+  - initPython()  to initialize global Python interpreter
+  - initState()   to initialize embedded interpreter state
+  - initContext() to initialize interpreter internal context
+  - initRun()     to prepare interpreter for running commands
 
   /EDF-CCAR/
   When SALOME uses multi Python interpreter feature, 
   every study has its own interpreter and thread state (_tstate = Py_NewInterpreter()).
-  This is fine because every study has its own modules (sys.modules) stdout and stderr.<br>
+  This is fine because every study has its own modules (sys.modules) stdout and stderr.
+
   <b>But</b> some Python modules must be imported only once. In multi interpreter 
   context Python modules (*.py) are imported several times.
-  For example, the pyqt module must be imported only once because 
+  For example, the PyQt module must be imported only once because 
   it registers classes in a C module.
+
   It's quite the same with omniorb modules (internals and generated with omniidl).
+
   This problem is handled with "shared modules" defined in salome_shared_modules.py.
   These "shared modules" are imported only once and only copied in all 
-  the other interpreters.<br>
+  the other interpreters.
+
   <b>But</b> it's not the only problem. Every interpreter has its own 
   __builtin__ module. That's fine but if we have copied some modules 
   and imported others problems may arise with operations that are not allowed
   have identical __builtin__ module.
 */
 
-using namespace std;
-
 /*!
   \brief Constructor.
 
   Creates new python interpreter.
 */
-PyConsole_Interp::PyConsole_Interp(): PyInterp_base()
+PyConsole_Interp::PyConsole_Interp(): PyInterp_Interp()
 {
 }
 
@@ -74,32 +83,15 @@ PyConsole_Interp::~PyConsole_Interp()
  
 /*!
   \brief Initialize internal Python interpreter state.
+  \return \c true on success
 */
 bool PyConsole_Interp::initState()
 {
   // The GIL is acquired and will be held on initState output
   // It is the caller responsability to release the lock if needed
-
-/* LLS
   PyEval_AcquireLock();
   _tstate = Py_NewInterpreter(); // create an interpreter and save current state
-  PySys_SetArgv(PyInterp_base::_argc,PyInterp_base::_argv); // initialize sys.argv
-*/
-
-  PyEval_AcquireLock();
-#ifdef WIN32 
-  _tstate = PyGILState_GetThisThreadState();
-  // if no thread state defined
-  if ( _tstate )
-    PyThreadState_Swap(_tstate);
-  else
-#endif
-  {
-    _tstate = Py_NewInterpreter(); // create an interpreter and save current state
-    PySys_SetArgv(PyInterp_base::_argc,PyInterp_base::_argv); // initialize sys.argv
-    //if(MYDEBUG) MESSAGE("PythonConsole_PyInterp::initState - this = "<<this<<"; _tstate = "<<_tstate);
-  }
-
+  PySys_SetArgv(PyInterp_Interp::_argc,PyInterp_Interp::_argv); // initialize sys.argv
   
   //If builtinmodule has been initialized all the sub interpreters
   // will have the same __builtin__ module
@@ -119,6 +111,8 @@ bool PyConsole_Interp::initState()
   The GIL is assumed to be held.
   It is the caller responsability caller to acquire the GIL.
   It will still be held on initContext() exit.
+
+  \return \c true on success
 */
 bool PyConsole_Interp::initContext()
 {
index 3d1ed03fa5989a158372b62a5bdee7eb940b68ef..5e0b1f645ab399c4c676d3bea3111dd91a25218e 100644 (file)
@@ -28,9 +28,9 @@
 
 #include "PyConsole.h"
 
-#include <PyInterp_base.h> // this include must be first (see PyInterp_base.h)!
+#include <PyInterp_Interp.h>   /// !!! WARNING !!! THIS INCLUDE MUST BE VERY FIRST !!!
 
-class PYCONSOLE_EXPORT PyConsole_Interp : public PyInterp_base
+class PYCONSOLE_EXPORT PyConsole_Interp : public PyInterp_Interp
 {
 public:
   PyConsole_Interp();
@@ -41,4 +41,4 @@ protected:
   virtual bool initContext();  
 };
 
-#endif
+#endif // PYCONSOLE_INTERP_H
index 86772a12415394961be117a6497dca4ad45ba100..eab58424eb4c797ba86fb9be924cf6ade10e18f6 100755 (executable)
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
-#if !defined ( _PYINTERP_H )
-#define _PYINTERP_H
+// File   : PyInterp.h
+// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
+//
+
+#if !defined ( PYINTERP_H )
+#define PYINTERP_H
 
 // ========================================================
 // set dllexport type for Win platform 
 #ifdef WIN32
-
-#ifdef PYINTERP_EXPORTS
-#define PYINTERP_EXPORT __declspec(dllexport)
-#else
-#define PYINTERP_EXPORT __declspec(dllimport)
-#endif
-
+# ifdef PYINTERP_EXPORTS
+#  define PYINTERP_EXPORT __declspec(dllexport)
+# else
+#  define PYINTERP_EXPORT __declspec(dllimport)
+# endif
 #else   // WIN32
-
-#define PYINTERP_EXPORT
-
+# define PYINTERP_EXPORT
 #endif  // WIN32
 
 // ========================================================
-// little trick - we do not have debug python libraries
+// little trick - if we do not have debug python libraries
 #ifdef _DEBUG
-
-#undef _DEBUG
-#include <Python.h>
-#define _DEBUG
-
-#else  // _DEBUG
+ #ifndef HAVE_DEBUG_PYTHON
+  #undef _DEBUG
+ #endif
+#endif
 
 #include <Python.h>
 
-#endif // _DEBUG
+#ifdef _DEBUG
+ #ifndef HAVE_DEBUG_PYTHON
+  #define _DEBUG
+ #endif
+#endif
 
 // ========================================================
 // avoid warning messages
@@ -56,4 +58,4 @@
 #pragma warning (disable : 4251)
 #endif
 
-#endif // _PYINTERP_H
+#endif // PYINTERP_H
index 8ee7c1f25e8663d5475642ee2889e2aabc0c1be5..bc1afac7995890e226be70382ae08337e82462fe 100644 (file)
@@ -1,4 +1,7 @@
-TEMPLATE = lib
+unix:TEMPLATE = lib
+win32:TEMPLATE = vclib
+
+win32:QMAKE_MOC=$(QTDIR)\bin\moc.exe
 
 DESTDIR = ../../$(CONFIG_ID)/lib
 MOC_DIR = ../../moc
@@ -6,18 +9,26 @@ OBJECTS_DIR = ../../$(CONFIG_ID)/obj/$$TARGET
 
 INCLUDEPATH += ../../include $$(PYTHONINC)
 unix:LIBS  += -L$$(PYTHONLIB) -lpython2.5
-win32:LIBS += /LIBPATH:$$(PYTHONLIB)
+win32:LIBS  += -L$$(PYTHONLIB) -lpython25_d
+win32:LIBS *= -L$(QTLIB)
+win32:INCLUDEPATH *= $(QTINC) $(QTINC)\QtCore $(QTINC)\QtGui $(QTINC)\QtXml
 
 CONFIG -= debug release debug_and_release
 CONFIG += qt thread debug dll shared
 
-win32:DEFINES += WIN32
+win32:DEFINES += WNT WIN32 HAVE_DEBUG_PYTHON
 DEFINES += PYINTERP_EXPORTS
 
 HEADERS = *.h
 
 SOURCES = *.cxx
 
+win32:copy_hdr.name = Install ${QMAKE_FILE_IN}
+win32:copy_hdr.commands = type ${QMAKE_FILE_IN} > ../../include/${QMAKE_FILE_BASE}.h
+win32:copy_hdr.output = ../../include/${QMAKE_FILE_BASE}.h
+win32:copy_hdr.input = HEADERS
+win32:QMAKE_EXTRA_COMPILERS += copy_hdr
+
 includes.files = $$HEADERS
 includes.path = ../../include
 
index 917298417922d03ea1b154a5c50269944b34fe4e..e3adb001d7f0ee33789b683ef02856a4784bc994 100755 (executable)
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
-//  SALOME SALOMEGUI : implementation of desktop and GUI kernel
-//
 //  File   : PyInterp_Dispatcher.cxx
 //  Author : Sergey ANIKIN, OCC
 //  Module : GUI
-//  $Header$
-
 
-#include "PyInterp_base.h"
+#include "PyInterp_Dispatcher.h"   // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!!
+#include "PyInterp_Interp.h"
 #include "PyInterp_Watcher.h"
-#include "PyInterp_Dispatcher.h"
 
-#include <QtCore/qobject.h>
-#include <QtCore/qcoreapplication.h>
+#include <QObject>
+#include <QCoreApplication>
 
 using namespace std;
 
@@ -126,8 +122,9 @@ PyInterp_Dispatcher::~PyInterp_Dispatcher()
   // Clear the request queue
   myQueueMutex.lock();
 
-  for ( std::list<PyInterp_Request*>::iterator it = myQueue.begin(); it != myQueue.end(); ++it )
-    PyInterp_Request::Destroy( *it );
+  QListIterator<RequestPtr> it( myQueue );
+  while ( it.hasNext() )
+    PyInterp_Request::Destroy( it.next() );
   myQueue.clear();
 
   myQueueMutex.unlock();
@@ -155,7 +152,7 @@ void PyInterp_Dispatcher::Exec( PyInterp_Request* theRequest )
   else // asynchronous processing
   {
     myQueueMutex.lock();
-    myQueue.push_back( theRequest );
+    myQueue.enqueue( theRequest );
     if ( theRequest->listener() )
       QObject::connect( theRequest->listener(), SIGNAL( destroyed( QObject* ) ), myWatcher, SLOT( onDestroyed( QObject* ) ) );
     myQueueMutex.unlock();  
@@ -175,7 +172,7 @@ void PyInterp_Dispatcher::run()
 
   while( myQueue.size() ) {
 //    MESSAGE("*** PyInterp_Dispatcher::run(): next request taken from the queue")
-    aRequest = myQueue.front();
+    aRequest = myQueue.head();
 
     // let other threads append their requests to the end of the queue
     myQueueMutex.unlock();
@@ -187,8 +184,8 @@ void PyInterp_Dispatcher::run()
     // prepare for removal of the first request in the queue
     myQueueMutex.lock();
     // IMPORTANT: the first item could have been removed by objectDestroyed() --> we have to check it
-    if ( myQueue.front() == aRequest ) // It's still here --> remove it
-      myQueue.pop_front();
+    if ( myQueue.head() == aRequest ) // It's still here --> remove it
+      myQueue.dequeue();
 
 //    MESSAGE("*** PyInterp_Dispatcher::run(): request processed")
   }
@@ -207,12 +204,14 @@ void PyInterp_Dispatcher::objectDestroyed( const QObject* o )
   // prepare for modification of the queue
   myQueueMutex.lock();
 
-  for ( std::list<RequestPtr>::iterator it = myQueue.begin(); it != myQueue.end(); ++it )
+  QMutableListIterator<RequestPtr> it( myQueue );
+  while ( it.hasNext() )
   {
-    if ( o == (*it)->listener() )
+    RequestPtr r = it.next();
+    if ( o == r->listener() )
     {
-      (*it)->setListener( 0 ); // to prevent event posting
-      it = myQueue.erase( it );
+      r->setListener( 0 ); // to prevent event posting
+      it.remove();
     }
   }
 
index 6f6240794dc8e66fdc8bfc3eb3ec270eac37af68..cf46694e41f22d7eb1b0d89d12eab5bd3d63e1e0 100755 (executable)
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
-//  SALOME SALOMEGUI : implementation of desktop and GUI kernel
-//
 //  File   : PyInterp_Dispatcher.h
 //  Author : Sergey Anikin, OCC
 //  Module : SALOME
 
-#ifndef _PYINTERP_DISPATCHER_H_
-#define _PYINTERP_DISPATCHER_H_
-
-#include "PyInterp.h"
-
-#include <QtCore/qmutex.h>
-#include <QtCore/qthread.h>
+#ifndef PYINTERP_DISPATCHER_H
+#define PYINTERP_DISPATCHER_H
 
-#include <QtGui/qevent.h>
+#include "PyInterp.h"   // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!!
 
-#include <list>
+#include <QMutex>
+#include <QThread>
+#include <QEvent>
+#include <QQueue>
 
 class QObject;
 
-class PyInterp_base;
+class PyInterp_Interp;
 class PyInterp_Watcher;
 class PyInterp_Dispatcher;
 
@@ -73,11 +69,12 @@ protected:
 
   virtual void    processEvent( QObject* );
 
-private:
-  void            process();
   QObject*        listener() const { return myListener; }
   void            setListener( QObject* );
 
+private:
+  void            process();
+
 private:
   QMutex          myMutex;
   bool            myIsSync;
@@ -87,16 +84,16 @@ private:
 class PYINTERP_EXPORT PyInterp_LockRequest : public PyInterp_Request
 {
 public:
-  PyInterp_LockRequest( PyInterp_base* interp, QObject* listener = 0, bool sync = false )
+  PyInterp_LockRequest( PyInterp_Interp* interp, QObject* listener = 0, bool sync = false )
     : PyInterp_Request( listener, sync ), myInterp( interp ) {}
 
 protected:
-  PyInterp_base*  getInterp() const { return myInterp; }
+  PyInterp_Interp*  getInterp() const { return myInterp; }
 
-  virtual void    safeExecute();
+  virtual void      safeExecute();
 
 private:
-  PyInterp_base*  myInterp;
+  PyInterp_Interp*  myInterp;
 };
 
 class PYINTERP_EXPORT PyInterp_Event : public QEvent
@@ -139,7 +136,7 @@ private:
 private:
   typedef PyInterp_Request*   RequestPtr;
 
-  std::list<RequestPtr>       myQueue;
+  QQueue<RequestPtr>          myQueue;
   QMutex                      myQueueMutex;
   PyInterp_Watcher*           myWatcher;
 
@@ -148,4 +145,4 @@ private:
   friend class PyInterp_Watcher;
 };
 
-#endif
+#endif // PYINTERP_DISPATCHER_H
diff --git a/src/PyInterp/PyInterp_Interp.cxx b/src/PyInterp/PyInterp_Interp.cxx
new file mode 100644 (file)
index 0000000..891d029
--- /dev/null
@@ -0,0 +1,449 @@
+// Copyright (C) 2005  OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either 
+// version 2.1 of the License.
+// 
+// This library is distributed in the hope that it will be useful 
+// but WITHOUT ANY WARRANTY; without even the implied warranty of 
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public  
+// License along with this library; if not, write to the Free Software 
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+//  File   : PyInterp_Interp.cxx
+//  Author : Christian CAREMOLI, Paul RASCLE, EDF
+//  Module : SALOME
+
+#include "PyInterp_Interp.h"  // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!!
+
+#include <cStringIO.h>
+#include <structmember.h>
+
+#include <string>
+#include <vector>
+#include <iostream>
+
+#define TOP_HISTORY_PY   "--- top of history ---"
+#define BEGIN_HISTORY_PY "--- begin of history ---"
+
+/*!
+  \class PyLockWrapper
+  \brief Python GIL wrapper.
+*/
+
+/*!
+  \brief Constructor. Automatically acquires GIL.
+  \param theThreadState python thread state
+*/
+PyLockWrapper::PyLockWrapper(PyThreadState* theThreadState): 
+  myThreadState(theThreadState),
+  mySaveThreadState(0)
+{
+  if (myThreadState->interp == PyInterp_Interp::_interp)
+    _savestate = PyGILState_Ensure();
+  else
+    PyEval_AcquireThread(myThreadState);
+}
+
+/*!
+  \brief Desstructor. Automatically releases GIL.
+*/
+PyLockWrapper::~PyLockWrapper()
+{
+  if (myThreadState->interp == PyInterp_Interp::_interp)
+    PyGILState_Release(_savestate);
+  else
+    PyEval_ReleaseThread(myThreadState);
+}
+
+/*!
+  \brief Get Python GIL wrapper.
+  \return GIL lock wrapper (GIL is automatically acquired here)
+*/
+PyLockWrapper PyInterp_Interp::GetLockWrapper()
+{
+  return _tstate;
+}
+
+/*
+  The following functions are used to hook the Python 
+  interpreter output.
+*/
+
+static void
+PyStdOut_dealloc(PyStdOut *self)
+{
+  PyObject_Del(self);
+}
+
+static PyObject*
+PyStdOut_write(PyStdOut *self, PyObject *args)
+{
+  char *c;
+  int l;
+  if (!PyArg_ParseTuple(args, "t#:write",&c, &l))
+    return NULL;
+  if(self->_cb==NULL) {
+    if ( self->_iscerr )
+      std::cerr << c ;
+    else
+      std::cout << c ;
+  }
+  else {
+    self->_cb(self->_data,c);
+  }
+  Py_INCREF(Py_None);
+  return Py_None;
+}
+
+static PyMethodDef PyStdOut_methods[] = {
+  {"write",  (PyCFunction)PyStdOut_write,  METH_VARARGS,
+    PyDoc_STR("write(string) -> None")},
+  {NULL,    NULL}   /* sentinel */
+};
+
+static PyMemberDef PyStdOut_memberlist[] = {
+  {"softspace", T_INT,  offsetof(PyStdOut, softspace), 0,
+   "flag indicating that a space needs to be printed; used by print"},
+  {NULL} /* Sentinel */
+};
+
+static PyTypeObject PyStdOut_Type = {
+  /* The ob_type field must be initialized in the module init function
+   * to be portable to Windows without using C++. */
+  PyObject_HEAD_INIT(NULL)
+  0,                            /*ob_size*/
+  "PyOut",                      /*tp_name*/
+  sizeof(PyStdOut),             /*tp_basicsize*/
+  0,                            /*tp_itemsize*/
+  /* methods */
+  (destructor)PyStdOut_dealloc, /*tp_dealloc*/
+  0,                            /*tp_print*/
+  0,                            /*tp_getattr*/
+  0,                            /*tp_setattr*/
+  0,                            /*tp_compare*/
+  0,                            /*tp_repr*/
+  0,                            /*tp_as_number*/
+  0,                            /*tp_as_sequence*/
+  0,                            /*tp_as_mapping*/
+  0,                            /*tp_hash*/
+  0,                            /*tp_call*/
+  0,                            /*tp_str*/
+  PyObject_GenericGetAttr,      /*tp_getattro*/
+  /* softspace is writable:  we must supply tp_setattro */
+  PyObject_GenericSetAttr,      /* tp_setattro */
+  0,                            /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT,           /*tp_flags*/
+  0,                            /*tp_doc*/
+  0,                            /*tp_traverse*/
+  0,                            /*tp_clear*/
+  0,                            /*tp_richcompare*/
+  0,                            /*tp_weaklistoffset*/
+  0,                            /*tp_iter*/
+  0,                            /*tp_iternext*/
+  PyStdOut_methods,             /*tp_methods*/
+  PyStdOut_memberlist,          /*tp_members*/
+  0,                            /*tp_getset*/
+  0,                            /*tp_base*/
+  0,                            /*tp_dict*/
+  0,                            /*tp_descr_get*/
+  0,                            /*tp_descr_set*/
+  0,                            /*tp_dictoffset*/
+  0,                            /*tp_init*/
+  0,                            /*tp_alloc*/
+  0,                            /*tp_new*/
+  0,                            /*tp_free*/
+  0,                            /*tp_is_gc*/
+};
+
+#define PyStdOut_Check(v)  ((v)->ob_type == &PyStdOut_Type)
+
+static PyStdOut* newPyStdOut( bool iscerr )
+{
+  PyStdOut *self;
+  self = PyObject_New(PyStdOut, &PyStdOut_Type);
+  if (self == NULL)
+    return NULL;
+  self->softspace = 0;
+  self->_cb = NULL;
+  self->_iscerr = iscerr;
+  return self;
+}
+
+/*!
+  \class PyInterp_Interp
+  \brief Generic embedded Python interpreter.
+*/
+
+int   PyInterp_Interp::_argc   = 1;
+char* PyInterp_Interp::_argv[] = {""};
+PyObject*           PyInterp_Interp::builtinmodule = NULL;
+PyThreadState*      PyInterp_Interp::_gtstate      = NULL;
+PyInterpreterState* PyInterp_Interp::_interp       = NULL;
+
+/*!
+  \brief Basic constructor.
+  
+  After construction the interpreter instance successor classes 
+  must call virtual method initalize().
+*/
+PyInterp_Interp::PyInterp_Interp(): 
+  _tstate(0), _vout(0), _verr(0), _g(0)
+{
+}
+
+/*!
+  \brief Destructor.
+*/
+PyInterp_Interp::~PyInterp_Interp()
+{
+}
+
+/*!
+  \brief Initialize embedded interpreter.
+  
+  This method shoud be called after construction of the interpreter.
+  The method initialize() calls virtuals methods
+  - initPython()  to initialize global Python interpreter
+  - initState()   to initialize embedded interpreter state
+  - initContext() to initialize interpreter internal context
+  - initRun()     to prepare interpreter for running commands
+  which should be implemented in the successor classes, according to the
+  embedded Python interpreter policy (mono or multi interpreter, etc).
+*/
+void PyInterp_Interp::initialize()
+{
+  _history.clear();       // start a new list of user's commands 
+  _ith = _history.begin();
+
+  initPython();
+  // Here the global lock is released
+
+  initState();
+
+  PyLockWrapper aLock = GetLockWrapper();
+
+  initContext();
+
+  // used to interpret & compile commands
+  PyObjWrapper m(PyImport_ImportModule("codeop"));
+  if(!m) {
+    PyErr_Print();
+    return;
+  }
+
+  // Create python objects to capture stdout and stderr
+  _vout=(PyObject*)newPyStdOut( false ); // stdout 
+  _verr=(PyObject*)newPyStdOut( true );  // stderr
+
+  // All the initRun outputs are redirected to the standard output (console)
+  initRun();
+}
+
+/*!
+  \brief Initialize Python interpreter.
+
+  Set program name, initialize interpreter, set program arguments,
+  initiaize threads.
+ */
+void PyInterp_Interp::initPython()
+{
+  if (Py_IsInitialized())
+    return;
+
+  // Python is not initialized
+  Py_SetProgramName(_argv[0]);
+  Py_Initialize(); // Initialize the interpreter
+  PySys_SetArgv(_argc, _argv);
+  PyEval_InitThreads(); // Create (and acquire) the interpreter lock
+  _interp = PyThreadState_Get()->interp;
+  if (PyType_Ready(&PyStdOut_Type) < 0) {
+    PyErr_Print();
+  }
+  _gtstate = PyEval_SaveThread(); // Release global thread state
+}
+
+/*!
+  \brief Get embedded Python interpreter banner.
+  \return banner string
+ */
+std::string PyInterp_Interp::getbanner()
+{
+ // Should we take the lock ?
+ // PyEval_RestoreThread(_tstate);
+  std::string aBanner("Python ");
+  aBanner = aBanner + Py_GetVersion() + " on " + Py_GetPlatform() ;
+  aBanner = aBanner + "\ntype help to get general information on environment\n";
+  //PyEval_SaveThread();
+  return aBanner;
+}
+
+/*!
+  \brief Initialize run command.
+  This method is used to prepare interpreter for running 
+  Python commands.
+  
+  \return \c true on success and \c false on error
+*/
+bool PyInterp_Interp::initRun()
+{
+  // 
+  // probably all below code isn't required
+  //
+  /*
+  PySys_SetObject("stderr",_verr);
+  PySys_SetObject("stdout",_vout);
+
+  //PyObject *m = PyImport_GetModuleDict();
+  
+  PySys_SetObject("stdout",PySys_GetObject("__stdout__"));
+  PySys_SetObject("stderr",PySys_GetObject("__stderr__"));
+  */
+  return true;
+}
+
+/*!
+  \brief Compile Python command and evaluate it in the 
+         python dictionary context if possible.
+  \internal
+  \param command Python command string
+  \param context Python context (dictionary)
+  \return -1 on fatal error, 1 if command is incomplete and 0
+         if command is executed successfully
+ */
+static int compile_command(const char *command,PyObject *context)
+{
+  PyObject *m = PyImport_AddModule("codeop");
+  if(!m) { // Fatal error. No way to go on.
+    PyErr_Print();
+    return -1;
+  }
+  PyObjWrapper v(PyObject_CallMethod(m,"compile_command","s",command));
+  if(!v) {
+    // Error encountered. It should be SyntaxError,
+    //so we don't write out traceback
+    PyObjWrapper exception, value, tb;
+    PyErr_Fetch(&exception, &value, &tb);
+    PyErr_NormalizeException(&exception, &value, &tb);
+    PyErr_Display(exception, value, NULL);
+    return -1;
+  }
+  else if (v == Py_None) {
+    // Incomplete text we return 1 : we need a complete text to execute
+    return 1;
+  }
+  else {
+    // Complete and correct text. We evaluate it.
+    //#if PY_VERSION_HEX < 0x02040000 // python version earlier than 2.4.0
+    //    PyObjWrapper r(PyEval_EvalCode(v,context,context));
+    //#else
+    PyObjWrapper r(PyEval_EvalCode((PyCodeObject *)(void *)v,context,context));
+    //#endif
+    if(!r) {
+      // Execution error. We return -1
+      PyErr_Print();
+      return -1;
+    }
+    // The command has been successfully executed. Return 0
+    return 0;
+  }
+}
+
+/*!
+  \brief Run Python command.
+  \param command Python command
+  \return command status
+*/
+int PyInterp_Interp::run(const char *command)
+{
+  beforeRun();
+  return simpleRun(command);
+}
+
+/*!
+  \brief Run Python command (used internally).
+  \param command Python command
+  \param addToHistory if \c true (default), the command is added to the commands history
+  \return command status
+*/
+int PyInterp_Interp::simpleRun(const char *command, const bool addToHistory)
+{
+  if( addToHistory && strcmp(command,"") != 0 ) {
+    _history.push_back(command);
+    _ith = _history.end();
+  }
+
+  // We come from C++ to enter Python world
+  // We need to acquire the Python global lock
+  //PyLockWrapper aLock(_tstate); // san - lock is centralized now
+
+  // Reset redirected outputs before treatment
+  PySys_SetObject("stderr",_verr);
+  PySys_SetObject("stdout",_vout);
+
+  int ier = compile_command(command,_g);
+
+  // Outputs are redirected on standards outputs (console)
+  PySys_SetObject("stdout",PySys_GetObject("__stdout__"));
+  PySys_SetObject("stderr",PySys_GetObject("__stderr__"));
+
+  return ier;
+}
+
+/*!
+  \brief Get previous command in the commands history.
+  \return previous command
+*/
+const char * PyInterp_Interp::getPrevious()
+{
+  if(_ith != _history.begin()){
+    _ith--;
+    return (*_ith).c_str();
+  }
+  else
+    return BEGIN_HISTORY_PY;
+}
+
+/*!
+  \brief Get next command in the commands history.
+  \return next command
+*/
+const char * PyInterp_Interp::getNext()
+{
+  if(_ith != _history.end()){
+    _ith++;
+  }
+  if (_ith == _history.end())
+    return TOP_HISTORY_PY;
+  else
+    return (*_ith).c_str();
+}
+
+/*!
+  \brief Set Python standard output device hook.
+  \param cb callback function
+  \param data callback function parameters
+*/
+void PyInterp_Interp::setvoutcb(PyOutChanged* cb, void* data)
+{  
+  ((PyStdOut*)_vout)->_cb=cb;
+  ((PyStdOut*)_vout)->_data=data;
+}
+
+/*!
+  \brief Set Python standard error device hook.
+  \param cb callback function
+  \param data callback function parameters
+*/
+void PyInterp_Interp::setverrcb(PyOutChanged* cb, void* data)
+{  
+  ((PyStdOut*)_verr)->_cb=cb;
+  ((PyStdOut*)_verr)->_data=data;
+}
diff --git a/src/PyInterp/PyInterp_Interp.h b/src/PyInterp/PyInterp_Interp.h
new file mode 100644 (file)
index 0000000..397a791
--- /dev/null
@@ -0,0 +1,116 @@
+// Copyright (C) 2005  OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
+// 
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either 
+// version 2.1 of the License.
+// 
+// This library is distributed in the hope that it will be useful 
+// but WITHOUT ANY WARRANTY; without even the implied warranty of 
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public  
+// License along with this library; if not, write to the Free Software 
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+//  File   : PyInterp_Interp.h
+//  Author : Christian CAREMOLI, Paul RASCLE, EDF
+//  Module : SALOME
+
+#ifndef PYINTERP_INTERP_H
+#define PYINTERP_INTERP_H
+
+#include "PyInterp.h"   // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!!
+
+#include <list>
+#include <string>
+
+class PYINTERP_EXPORT PyLockWrapper
+{
+  PyThreadState* myThreadState;
+  PyThreadState* mySaveThreadState;
+  PyGILState_STATE _savestate;
+public:
+  PyLockWrapper(PyThreadState* theThreadState);
+  ~PyLockWrapper();
+};
+
+typedef void PyOutChanged(void* data,char * c);
+
+class PYINTERP_EXPORT PyInterp_Interp
+{
+public:
+  static int _argc;
+  static char* _argv[];
+  static PyObject *builtinmodule;
+  static PyThreadState *_gtstate;
+  static PyInterpreterState *_interp;
+  
+  PyInterp_Interp();
+  virtual ~PyInterp_Interp();
+  
+  void initialize();
+
+  virtual int run(const char *command); 
+
+  PyLockWrapper GetLockWrapper();
+
+  std::string getbanner(); 
+  void setverrcb(PyOutChanged*,void*);
+  void setvoutcb(PyOutChanged*,void*);
+
+  const char * getPrevious();
+  const char * getNext();    
+
+protected:
+  PyThreadState * _tstate;
+  PyObject * _vout;
+  PyObject * _verr;
+  PyObject * _g;
+  PyObject * _codeop;
+  std::list<std::string> _history;
+  std::list<std::string>::iterator _ith;
+
+  virtual int beforeRun() { return 0; }
+  int simpleRun(const char* command, const bool addToHistory = true);
+
+  virtual bool initRun();
+  virtual void initPython();
+  virtual bool initState() = 0;
+  virtual bool initContext() = 0;  
+};
+
+class PYINTERP_EXPORT PyObjWrapper
+{
+  PyObject* myObject;
+public:
+  PyObjWrapper(PyObject* theObject) : myObject(theObject) {}
+  PyObjWrapper() : myObject(0) {}
+  virtual ~PyObjWrapper() { Py_XDECREF(myObject); }
+
+  operator PyObject*()    { return myObject;  }
+  PyObject* operator->()  { return myObject;  }
+  PyObject* get()         { return myObject;  }
+  bool operator!()        { return !myObject; }
+  bool operator==(PyObject* theObject) { return myObject == theObject; }
+  PyObject** operator&()  { return &myObject; }
+  PyObjWrapper& operator=(PyObjWrapper* theObjWrapper)
+  {
+    Py_XDECREF(myObject);
+    myObject = theObjWrapper->myObject;
+    return *this;
+  }
+};
+
+typedef struct {
+  PyObject_HEAD
+  int softspace;
+  PyOutChanged* _cb;
+  void* _data;
+  bool _iscerr;
+} PyStdOut;
+
+#endif // PYINTERP_INTERP_H
index f5d7760346a1c2a7c2f68b8a840e1caa17898caa..1d50f5bf8392564f05e7d617cd3e183eb1326d2b 100755 (executable)
 //
 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
 //
-#ifndef _PYINTERP_WATCHER_H_
-#define _PYINTERP_WATCHER_H_
+//  File   : PyInterp_Watcher.h
+//  Author : Sergey Anikin, OCC
+//  Module : SALOME
 
-#include "PyInterp.h"
+#ifndef PYINTERP_WATCHER_H
+#define PYINTERP_WATCHER_H
+
+#include "PyInterp.h"   // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!!
 
 #include "PyInterp_Dispatcher.h"
 
-#include <QtCore/qobject.h>
+#include <QObject>
 
 // Private class that keeps track of destructions of request listeners
 class PYINTERP_EXPORT PyInterp_Watcher : public QObject
@@ -38,4 +42,4 @@ public slots:
   void onDestroyed( QObject* o ) { PyInterp_Dispatcher::Get()->objectDestroyed( o ); }
 };
 
-#endif // _PYINTERP_WATCHER_H_
+#endif // PYINTERP_WATCHER_H
diff --git a/src/PyInterp/PyInterp_base.cxx b/src/PyInterp/PyInterp_base.cxx
deleted file mode 100644 (file)
index 1ff7cd2..0000000
+++ /dev/null
@@ -1,317 +0,0 @@
-// Copyright (C) 2005  OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
-// 
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either 
-// version 2.1 of the License.
-// 
-// This library is distributed in the hope that it will be useful 
-// but WITHOUT ANY WARRANTY; without even the implied warranty of 
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public  
-// License along with this library; if not, write to the Free Software 
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-//
-// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
-//  SALOME SALOMEGUI : implementation of desktop and GUI kernel
-//
-//  File   : PyInterp_base.cxx
-//  Author : Christian CAREMOLI, Paul RASCLE, EDF
-//  Module : SALOME
-//  $Header$
-
-
-#include "PyInterp_base.h" // this include must be first (see PyInterp_base.h)!
-
-#include <cStringIO.h>
-
-#include <string>
-#include <vector>
-
-using namespace std;
-
-PyLockWrapper::PyLockWrapper(PyThreadState* theThreadState): 
-  myThreadState(theThreadState),
-  mySaveThreadState(0)
-{
-#if defined(USE_GILSTATE)
-  if (myThreadState->interp == PyInterp_base::_interp) {
-    _savestate = PyGILState_Ensure();
-  } else {
-    PyEval_AcquireThread(myThreadState);
-  }
-#else 
-  PyEval_AcquireThread(myThreadState);
-#endif
-}
-
-PyLockWrapper::~PyLockWrapper()
-{
-#if defined(USE_GILSTATE)
-  if (myThreadState->interp == PyInterp_base::_interp) {
-    PyGILState_Release(_savestate);
-  } else {
-    PyEval_ReleaseThread(myThreadState);
-  }
-#else 
-  PyEval_ReleaseThread(myThreadState);
-#endif
-}
-
-class PyReleaseLock{
-public:
-  ~PyReleaseLock(){
-    PyEval_ReleaseLock();
-  }
-};
-
-
-PyLockWrapper PyInterp_base::GetLockWrapper(){
-  return _tstate;
-}
-
-
-// main python interpreter (static attributes)
-
-int PyInterp_base::_argc = 1;
-char* PyInterp_base::_argv[] = {""};
-
-PyObject *PyInterp_base::builtinmodule = NULL;
-
-PyThreadState *PyInterp_base::_gtstate = NULL;
-PyInterpreterState *PyInterp_base::_interp = NULL;
-
-
-/*!
- * basic constructor here : herited classes constructors must call initalize() method
- * defined here.
- */
-PyInterp_base::PyInterp_base(): _tstate(0), _vout(0), _verr(0), _g(0), _atFirst(true)
-{
-}
-
-PyInterp_base::~PyInterp_base()
-{
-}
-
-
-/*!
- * Must be called by herited classes constructors. initialize() calls virtuals methods
- * initstate & initcontext, not defined here in base class. initstate & initcontext methods
- * must be implemented in herited classes, following the Python interpreter policy
- * (mono or multi interpreter...).
- */
-void PyInterp_base::initialize()
-{
-  _history.clear();       // start a new list of user's commands 
-  _ith = _history.begin();
-
-  init_python();
-  // Here the global lock is released
-
-  initState();
-
-  PyLockWrapper aLock= GetLockWrapper();
-
-  initContext();
-
-  // used to interpret & compile commands
-  PyObjWrapper m(PyImport_ImportModule("codeop"));
-  if(!m){
-    PyErr_Print();
-    return;
-  }
-
-  // Create cStringIO to capture stdout and stderr
-  PycString_IMPORT;
-  if (PycStringIO) { // CTH11627 : additional check
-    _vout = PycStringIO->NewOutput(128);
-    _verr = PycStringIO->NewOutput(128);
-  }
-
-  // All the initRun outputs are redirected to the standard output (console)
-  initRun();
-}
-
-void PyInterp_base::init_python()
-{
-  _atFirst = false;
-  if (Py_IsInitialized())
-    return;
-
-  // Python is not initialized
-  Py_SetProgramName(_argv[0]);
-  Py_Initialize(); // Initialize the interpreter
-  PySys_SetArgv(_argc, _argv);
-  PyEval_InitThreads(); // Create (and acquire) the interpreter lock
-  _interp = PyThreadState_Get()->interp;
-  _gtstate = PyEval_SaveThread(); // Release global thread state
-}
-
-string PyInterp_base::getbanner()
-{
- // Should we take the lock ?
- // PyEval_RestoreThread(_tstate);
-  string aBanner("Python ");
-  aBanner = aBanner + Py_GetVersion() + " on " + Py_GetPlatform() ;
-  aBanner = aBanner + "\ntype help to get general information on environment\n";
-  //PyEval_SaveThread();
-  return aBanner;
-}
-
-
-int PyInterp_base::initRun()
-{
-  PySys_SetObject("stderr",_verr);
-  PySys_SetObject("stdout",_vout);
-
-  PyObjWrapper verr(PyObject_CallMethod(_verr,"reset",""));
-  PyObjWrapper vout(PyObject_CallMethod(_vout,"reset",""));
-
-  //PyObject *m = PyImport_GetModuleDict();
-  
-  PySys_SetObject("stdout",PySys_GetObject("__stdout__"));
-  PySys_SetObject("stderr",PySys_GetObject("__stderr__"));
-
-  return 0;
-}
-
-
-/*!
- * This function compiles a string (command) and then evaluates it in the dictionnary
- * context if possible.
- * Returns :
- * -1 : fatal error 
- *  1 : incomplete text
- *  0 : complete text executed with success
- */
-int compile_command(const char *command,PyObject *context)
-{
-  PyObject *m = PyImport_AddModule("codeop");
-  if(!m){ // Fatal error. No way to go on.
-    PyErr_Print();
-    return -1;
-  }
-  PyObjWrapper v(PyObject_CallMethod(m,"compile_command","s",command));
-  if(!v){
-    // Error encountered. It should be SyntaxError,
-    //so we don't write out traceback
-    PyObjWrapper exception, value, tb;
-    PyErr_Fetch(&exception, &value, &tb);
-    PyErr_NormalizeException(&exception, &value, &tb);
-    PyErr_Display(exception, value, NULL);
-    return -1;
-  }else if (v == Py_None){
-    // Incomplete text we return 1 : we need a complete text to execute
-    return 1;
-  }else{
-    // Complete and correct text. We evaluate it.
-    //#if PY_VERSION_HEX < 0x02040000 // python version earlier than 2.4.0
-    //    PyObjWrapper r(PyEval_EvalCode(v,context,context));
-    //#else
-    PyObjWrapper r(PyEval_EvalCode((PyCodeObject *)(void *)v,context,context));
-    //#endif
-    if(!r){
-      // Execution error. We return -1
-      PyErr_Print();
-      return -1;
-    }
-    // The command has been successfully executed. Return 0
-    return 0;
-  }
-}
-
-
-int PyInterp_base::run(const char *command)
-{
-  if(_atFirst){
-    int ret = 0;
-    ret = simpleRun("from Help import *");
-    if (ret) { 
-      _atFirst = false;
-      return ret;
-    }
-    ret = simpleRun("import salome");
-    if (ret) { 
-      _atFirst = false;
-      return ret;
-    }
-    ret = simpleRun("salome.salome_init(0,1)");
-    if (ret) { 
-      _atFirst = false;
-      return ret;
-    }
-    _atFirst = false;
-  }
-  return simpleRun(command);
-}
-
-
-int PyInterp_base::simpleRun(const char *command)
-{
-  if( !_atFirst && strcmp(command,"") != 0 ) {
-    _history.push_back(command);
-    _ith = _history.end();
-  }
-
-  // We come from C++ to enter Python world
-  // We need to acquire the Python global lock
-  //PyLockWrapper aLock(_tstate); // san - lock is centralized now
-
-  // Reset redirected outputs before treatment
-  PySys_SetObject("stderr",_verr);
-  PySys_SetObject("stdout",_vout);
-
-  PyObjWrapper verr(PyObject_CallMethod(_verr,"reset",""));
-  PyObjWrapper vout(PyObject_CallMethod(_vout,"reset",""));
-
-  int ier = compile_command(command,_g);
-
-  // Outputs are redirected on standards outputs (console)
-  PySys_SetObject("stdout",PySys_GetObject("__stdout__"));
-  PySys_SetObject("stderr",PySys_GetObject("__stderr__"));
-
-  return ier;
-}
-
-
-const char * PyInterp_base::getPrevious()
-{
-  if(_ith != _history.begin()){
-    _ith--;
-    return (*_ith).c_str();
-  }
-  else
-    return BEGIN_HISTORY_PY;
-}
-
-
-const char * PyInterp_base::getNext()
-{
-  if(_ith != _history.end()){
-    _ith++;
-  }
-  if (_ith == _history.end())
-    return TOP_HISTORY_PY;
-  else
-    return (*_ith).c_str();
-}
-
-
-string PyInterp_base::getverr(){ 
-  //PyLockWrapper aLock(_tstate);
-  PyObjWrapper v(PycStringIO->cgetvalue(_verr));
-  string aRet(PyString_AsString(v));
-  return aRet;
-}
-
-
-string PyInterp_base::getvout(){  
-  //PyLockWrapper aLock(_tstate);
-  PyObjWrapper v(PycStringIO->cgetvalue(_vout));
-  string aRet(PyString_AsString(v));
-  return aRet;
-}
diff --git a/src/PyInterp/PyInterp_base.h b/src/PyInterp/PyInterp_base.h
deleted file mode 100644 (file)
index a00056e..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright (C) 2005  OPEN CASCADE, CEA/DEN, EDF R&D, PRINCIPIA R&D
-// 
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either 
-// version 2.1 of the License.
-// 
-// This library is distributed in the hope that it will be useful 
-// but WITHOUT ANY WARRANTY; without even the implied warranty of 
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public  
-// License along with this library; if not, write to the Free Software 
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-//
-// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
-//  SALOME SALOMEGUI : implementation of desktop and GUI kernel
-//
-//  File   : PyInterp_base.h
-//  Author : Christian CAREMOLI, Paul RASCLE, EDF
-//  Module : SALOME
-
-#ifndef _PYINTERP_BASE_H_
-#define _PYINTERP_BASE_H_
-
-#include "PyInterp.h"
-
-#include <list>
-#include <string>
-#include <iostream>
-
-// include order important!
-// pthread then python then qt
-//#include <pthread.h>  // must be before Python.h !
-
-#include <Python.h>   // must be before qt includes ...
-#include <compile.h>   // Python include needed for versions before 2.4. Included in Python.h now.
-#include <eval.h>   // Python include needed for versions before 2.4. Included in Python.h now.
-
-//#if PY_VERSION_HEX < 0x02040000 // python version earlier than 2.4.0
-//extern "C" PyObject * PyEval_EvalCode(PyObject *co, PyObject *g, PyObject *l);
-//#endif
-
-/* For 2.3, use the PyGILState_ calls */
-#if (PY_VERSION_HEX >= 0x02030000)
-#define USE_GILSTATE
-#endif
-
-#define TOP_HISTORY_PY "--- top of history ---"
-#define BEGIN_HISTORY_PY "--- begin of history ---"
-
-class PYINTERP_EXPORT PyLockWrapper
-{
-  PyThreadState* myThreadState;
-  PyThreadState* mySaveThreadState;
-#if defined(USE_GILSTATE)
-  PyGILState_STATE _savestate ;
-#endif
- public:
-  PyLockWrapper(PyThreadState* theThreadState);
-  ~PyLockWrapper();
-};
-
-class PYINTERP_EXPORT PyInterp_base{
- public:
-  static int _argc;
-  static char* _argv[];
-  static PyObject *builtinmodule;
-  static PyThreadState *_gtstate;
-  static PyInterpreterState *_interp;
-  
-  PyInterp_base();
-  virtual ~PyInterp_base();
-  
-  virtual void initialize();
-  virtual void init_python();
-  // init_python() made virtual to:
-  // 1. Remove dependency on KERNEL in light SALOME configuration
-  // 2. Allow redefinition of this method in SalomeApp_PyInterp class (it should be empty there and rely on KERNEL_PYTHON)
-
-  virtual int run(const char *command); 
-
-  PyLockWrapper GetLockWrapper();
-
-  std::string getbanner(); 
-  std::string getverr();
-  std::string getvout();  
-
-  const char * getPrevious();
-  const char * getNext();    
-
- protected:
-  PyThreadState * _tstate;
-  PyObject * _vout;
-  PyObject * _verr;
-  PyObject * _g;
-  PyObject * _codeop;
-  std::list<std::string> _history;
-  std::list<std::string>::iterator _ith;
-  bool _atFirst;
-
-  int simpleRun(const char* command);
-  int initRun();
-
-  virtual bool initState() = 0;
-  virtual bool initContext() = 0;  
-};
-
-
-class PYINTERP_EXPORT PyObjWrapper{
-  PyObject* myObject;
-public:
-  PyObjWrapper(PyObject* theObject): myObject(theObject) {}
-  PyObjWrapper(): myObject(0) {}
-  operator PyObject*(){
-    return myObject;
-  }
-  PyObject* operator->(){
-    return myObject;
-  }
-  PyObject* get(){
-    return myObject;
-  }
-  bool operator!(){
-    return !myObject;
-  }
-  bool operator==(PyObject* theObject){
-    return myObject == theObject;
-  }
-  PyObject** operator&(){
-    return &myObject;
-  }
-  PyObjWrapper& operator=(PyObjWrapper* theObjWrapper){
-    Py_XDECREF(myObject);
-    myObject = theObjWrapper->myObject;
-    return *this;
-  }
-  virtual ~PyObjWrapper(){ 
-    Py_XDECREF(myObject);
-  }
-};
-
-#endif
index 2d1eaeee6def78046834d908f63d6ef28a0ff91a..f0dcfcb17500c57b7a95b8cf499e22e098fc1190 100644 (file)
@@ -1,20 +1,34 @@
-TEMPLATE = lib
+win32:TEMPLATE = vclib
+unix:TEMPLATE = lib
+
+CONFIG += embed_manifest_exe
+
+win32:QMAKE_MOC=$(QTDIR)\bin\moc.exe
 
 DESTDIR = ../../$(CONFIG_ID)/lib
 MOC_DIR = ../../moc
 OBJECTS_DIR = ../../$(CONFIG_ID)/obj/$$TARGET
 
+win32:LIBS *= -L$(QTLIB)
+win32:INCLUDEPATH *= $(QTINC) $(QTINC)\QtCore $(QTINC)\QtGui $(QTINC)\QtXml
+
 QT += xml
 CONFIG -= debug release debug_and_release
 CONFIG += qt thread debug dll shared
 
-win32:DEFINES += WIN32
+win32:DEFINES += WNT WIN32
 DEFINES += QTX_EXPORTS
 
 HEADERS     = *.h
 
 SOURCES     = *.cxx
 
+win32:copy_hdr.name = Install ${QMAKE_FILE_IN}
+win32:copy_hdr.commands = type ${QMAKE_FILE_IN} > ../../include/${QMAKE_FILE_BASE}.h
+win32:copy_hdr.output = ../../include/${QMAKE_FILE_BASE}.h
+win32:copy_hdr.input = HEADERS
+win32:QMAKE_EXTRA_COMPILERS += copy_hdr
+
 includes.files = $$HEADERS
 includes.path = ../../include
 
index 5d283c7580e3646cc1051243ee3dd1d52a2f3e1c..06b048327c8369aeea317c44a38ae74ca258edea 100644 (file)
@@ -1,4 +1,7 @@
-TEMPLATE = lib
+unix:TEMPLATE = lib
+win32:TEMPLATE = vclib
+
+win32:QMAKE_MOC=$(QTDIR)\bin\moc.exe
 
 DESTDIR = ../../$(CONFIG_ID)/lib
 MOC_DIR = ../../moc
@@ -6,11 +9,13 @@ OBJECTS_DIR = ../../$(CONFIG_ID)/obj/$$TARGET
 
 INCLUDEPATH = ../../include
 LIBS += -L../../$(CONFIG_ID)/lib -lSUIT -lQtx
+win32:LIBS *= -L$(QTLIB)
+win32:INCLUDEPATH *= $(QTINC) $(QTINC)\QtCore $(QTINC)\QtGui $(QTINC)\QtXml
 
 CONFIG -= debug release debug_and_release
 CONFIG += qt thread debug dll shared
 
-win32:DEFINES += WIN32
+win32:DEFINES += WNT WIN32
 DEFINES += STD_EXPORTS
 
 HEADERS = *.h
@@ -25,7 +30,7 @@ win32:GUIResources = ..\\..\\resources
 
 lrelease.name = LRELASE ${QMAKE_FILE_IN}
 unix:lrelease.commands = $(QTDIR)/bin/lrelease ${QMAKE_FILE_NAME} -qm $${GUIResources}/${QMAKE_FILE_BASE}.qm
-win32:lrelease.commands = $(QTDIR)\\bin\\lrelease ${QMAKE_FILE_NAME} -qm $${GUIResources}\\${QMAKE_FILE_BASE}.qm
+win32:lrelease.commands = $(QTDIR)\\bin\\lrelease ${QMAKE_FILE_IN} -qm $${GUIResources}\\${QMAKE_FILE_BASE}.qm
 unix:lrelease.output = $${GUIResources}/${QMAKE_FILE_BASE}.qm
 win32:lrelease.output = $${GUIResources}\\${QMAKE_FILE_BASE}.qm
 lrelease.input = TRANSLATIONS
@@ -34,8 +39,22 @@ win32:lrelease.clean = $${GUIResources}\\${QMAKE_FILE_BASE}.qm
 lrelease.CONFIG += no_link target_predeps
 QMAKE_EXTRA_COMPILERS += lrelease
 
+win32:copy_hdr.name = Install ${QMAKE_FILE_IN}
+win32:copy_hdr.commands = type ${QMAKE_FILE_IN} > ../../include/${QMAKE_FILE_BASE}.h
+win32:copy_hdr.output = ../../include/${QMAKE_FILE_BASE}.h
+win32:copy_hdr.input = HEADERS
+win32:QMAKE_EXTRA_COMPILERS += copy_hdr
+
 ICONS   = resources/*.png
 
+win32:SOURCES+=$$ICONS
+win32:Resource=$$ICONS
+win32:copy_res.name = Install resources ${QMAKE_FILE_IN}
+win32:copy_res.commands = type ${QMAKE_FILE_IN} > ${QMAKE_FILE_OUT}
+win32:copy_res.output = $${GUIResources}\\${QMAKE_FILE_BASE}.png
+win32:copy_res.input = Resource
+win32:QMAKE_EXTRA_COMPILERS += copy_res
+
 includes.files = $$HEADERS
 includes.path = ../../include