--- /dev/null
+
+SET(SUIT_DIR $ENV{SUIT_DIR} CACHE PATH "Path to the SUIT libraries")
+IF(EXISTS ${SUIT_DIR})
+ MESSAGE("-- SUIT found at " ${SUIT_DIR})
+
+ FIND_LIBRARY(Event Event ${SUIT_DIR}/lib)
+ FIND_LIBRARY(PyConsole PyConsole ${SUIT_DIR}/lib)
+ FIND_LIBRARY(PyInterp PyInterp ${SUIT_DIR}/lib)
+ FIND_LIBRARY(qtx qtx ${SUIT_DIR}/lib)
+ FIND_LIBRARY(suit suit ${SUIT_DIR}/lib)
+
+ SET(SUIT_INCLUDE ${SUIT_DIR}/include)
+
+ENDIF(EXISTS ${SUIT_DIR})
SET(KERNEL_ROOT_DIR $ENV{KERNEL_ROOT_DIR} CACHE PATH "Path to the Salome KERNEL directory")
SET(GUI_ROOT_DIR $ENV{GUI_ROOT_DIR} CACHE PATH "Path to the Salome GUI directory")
+SET(HAVE_SALOME NO)
IF(EXISTS ${GUI_ROOT_DIR})
MESSAGE("-- SALOME found at " ${GUI_ROOT_DIR})
SET(HAVE_SALOME YES)
INCLUDE(FindSolveSpace)
INCLUDE(FindCAS)
+IF(NOT ${HAVE_SALOME})
+ INCLUDE(FindSUIT)
+ENDIF(NOT ${HAVE_SALOME})
+
IF(UNIX)
IF(CMAKE_COMPILER_IS_GNUCC)
#C++11 is not supported on some platforms, disable it
ADD_SUBDIRECTORY (src/SketchSolver)
ADD_SUBDIRECTORY (src/ModuleBase)
ADD_SUBDIRECTORY (src/PartSet)
-ADD_SUBDIRECTORY (src/PyConsole)
-ADD_SUBDIRECTORY (src/PyEvent)
-ADD_SUBDIRECTORY (src/PyInterp)
ADD_SUBDIRECTORY (src/XGUI)
ADD_SUBDIRECTORY (src/GeomApp)
@SET PATH=%ROOT_DIR%\install\plugins;%ROOT_DIR%\install\bin;%PATH%
@SET PYTHONPATH=%ROOT_DIR%\install\swig;%PYTHONPATH%
+@REM -------------------------
+@REM SUIT
+@SET SUIT_DIR=%PDIR%\suit
+@SET PATH=%SUIT_DIR%\bin;%PATH%
+@REM -------------------------
+
+
@REM -------------------------
if "%GUI_ROOT_DIR%" == "" (
@SET GUI_ROOT_DIR=%ROOT_DIR%\SALOME\GUI\DEBUG\GUI_INSTALL
+++ /dev/null
-
-SET(CMAKE_AUTOMOC ON)
-
-# header files
-SET(PROJECT_HEADERS
- PyConsole.h
- PyConsole_Console.h
- PyConsole_Editor.h
- PyConsole_EnhEditor.h
- PyConsole_EnhInterp.h
- PyConsole_Event.h
- PyConsole_Interp.h
- PyConsole_Request.h
-)
-
-SET(PROJECT_AUTOMOC
- ${CMAKE_CURRENT_BINARY_DIR}/PyConsole_automoc.cpp
-)
-
-# resource files / to be processed by lrelease
-SET(TEXT_RESOURCES
- PyConsole_msg_fr.ts
-)
-
-# sources / static
-SET(PROJECT_SOURCES
- PyConsole_Console.cpp
- PyConsole_Editor.cpp
- PyConsole_EnhEditor.cpp
- PyConsole_EnhInterp.cpp
- PyConsole_Event.cpp
- PyConsole_Interp.cpp
- PyConsole_Request.cpp
-)
-
-SET(PROJECT_LIBRARIES
- PyInterp
- ${QT_LIBRARIES}
- ${PYTHON_LIBRARIES}
-)
-
-#QT4_ADD_TRANSLATION(QM_RESOURCES ${TEXT_RESOURCES})
-QT4_CREATE_TRANSLATION(QM_RESOURCES
- ${PROJECT_SOURCES}
- ${TEXT_RESOURCES}
- OPTIONS -extensions cpp -no-recursive
- )
-
-SOURCE_GROUP ("Generated Files" FILES ${PROJECT_AUTOMOC} ${QM_RESOURCES})
-
-INCLUDE_DIRECTORIES(
- ${PROJECT_SOURCE_DIR}/src/PyEvent
- ${PROJECT_SOURCE_DIR}/src/PyInterp
-)
-
-ADD_DEFINITIONS(-DPYCONSOLE_EXPORTS -DHAVE_DEBUG_PYTHON)
-
-ADD_LIBRARY(PyConsole SHARED
- ${PROJECT_HEADERS}
- ${PROJECT_SOURCES}
- ${TEXT_RESOURCES}
- ${QM_RESOURCES}
-)
-
-TARGET_LINK_LIBRARIES(PyConsole ${PROJECT_LIBRARIES})
-
-INSTALL(TARGETS PyConsole DESTINATION bin)
-INSTALL(FILES ${QM_RESOURCES} DESTINATION bin)
-
-
+++ /dev/null
-
-#if !defined ( PYCONSOLE_H )
-#define PYCONSOLE_H
-
-// ========================================================
-// set dllexport type for Win platform
-#ifdef WIN32
-# if defined PYCONSOLE_EXPORTS || defined PyConsole_EXPORTS
-# define PYCONSOLE_EXPORT __declspec(dllexport)
-# else
-# define PYCONSOLE_EXPORT __declspec(dllimport)
-# endif
-#else // WIN32
-# define PYCONSOLE_EXPORT
-#endif // WIN32
-
-// ========================================================
-// avoid warning messages
-#ifdef WIN32
-#pragma warning (disable : 4786)
-#pragma warning (disable : 4251)
-#endif
-
-#endif // PYCONSOLE_H
+++ /dev/null
-
-/*!
- \class PyConsole_Console
- \brief Python console widget.
-*/
-
-#include "PyConsole_Interp.h" /// !!! WARNING !!! THIS INCLUDE MUST BE VERY FIRST !!!
-#include "PyConsole_Console.h"
-#include "PyConsole_EnhEditor.h"
-#include "PyConsole_EnhInterp.h"
-
-//#include <Qtx.h>
-
-#include <QAction>
-#include <QApplication>
-#include <QClipboard>
-#include <QEvent>
-#include <QMenu>
-#include <QVBoxLayout>
-
-/*!
- \brief Constructor.
-
- Creates new python console widget.
- \param parent parent widget
- \param interp python interpreter
-*/
-PyConsole_Console::PyConsole_Console( QWidget* parent, PyConsole_Interp* interp )
-: QWidget( parent )
-{
- // create python interpreter
- myInterp = interp;
- if ( !myInterp )
- myInterp = new PyConsole_Interp();
-
- // initialize Python interpretator
- myInterp->initialize();
-
- // create editor console
- QVBoxLayout* lay = new QVBoxLayout( this );
- lay->setMargin( 0 );
- myEditor = new PyConsole_Editor( myInterp, this );
- char* synchronous = getenv("PYTHON_CONSOLE_SYNC");
- if (synchronous && atoi(synchronous))
- {
- myEditor->setIsSync(true);
- }
- myEditor->viewport()->installEventFilter( this );
- lay->addWidget( myEditor );
-
- createActions();
-}
-
-/**
- * Protected constructor.
- */
-PyConsole_Console::PyConsole_Console( QWidget* parent, PyConsole_Interp* i, PyConsole_Editor* e)
- : QWidget (parent), myEditor(e), myInterp(i)
-{}
-
-/*!
- \brief Destructor.
-
- Does nothing for the moment.
-*/
-PyConsole_Console::~PyConsole_Console()
-{
-}
-
-/*!
- \brief Execute python command in the interpreter.
- \param command string with command and arguments
-*/
-void PyConsole_Console::exec( const QString& command )
-{
- if ( myEditor )
- myEditor->exec( command );
-}
-
-/*!
- \brief Execute python command in the interpreter
- and wait until it is finished.
-
- Block execution of main application until the python command is executed.
- \param command string with command and arguments
-*/
-void PyConsole_Console::execAndWait( const QString& command )
-{
- if ( myEditor )
- myEditor->execAndWait( command );
-}
-
-/*!
- \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();
-}
-
-/*!
- \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( on );
-}
-
-/*!
- \brief Get suppress output flag value.
-
- \sa setIsSuppressOutput()
- \return True if python console output is suppressed.
-*/
-bool PyConsole_Console::isSuppressOutput() const
-{
- return myEditor->isSuppressOutput();
-}
-
-/*!
- \brief Set suppress output flag value.
-
- In case if suppress output flag is true, the python
- console output suppressed.
-
- \param on suppress output flag
-*/
-void PyConsole_Console::setIsSuppressOutput( const bool on )
-{
- myEditor->setIsSuppressOutput(on);
-}
-
-/*!
- \brief Get 'show banner' flag value.
-
- \sa setIsShowBanner()
- \return \c true if python console shows banner
-*/
-bool PyConsole_Console::isShowBanner() const
-{
- return myEditor->isShowBanner();
-}
-
-/*!
- \brief Set 'show banner' flag value.
-
- The banner is shown in the top of the python console window.
-
- \sa isShowBanner()
- \param on 'show banner' flag
-*/
-void PyConsole_Console::setIsShowBanner( const bool on )
-{
- myEditor->setIsShowBanner( on );
-}
-
-/*!
- \brief Change the python console's font.
- \param f new font
-*/
-void PyConsole_Console::setFont( const QFont& f )
-{
- if( myEditor )
- myEditor->setFont( f );
-}
-
-/*!
- \brief Get python console font.
- \return current python console's font
-*/
-QFont PyConsole_Console::font() const
-{
- QFont res;
- if( myEditor )
- res = myEditor->font();
- return res;
-}
-
-/*!
- \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 PyConsole_Console::eventFilter( QObject* o, QEvent* e )
-{
- if ( o == myEditor->viewport() && e->type() == QEvent::ContextMenu )
- {
- //contextMenuRequest( (QContextMenuEvent*)e );
- return true;
- }
- return QWidget::eventFilter( o, e );
-}
-
-/*!
- \brief Create the context popup menu.
-
- Fill in the popup menu with the commands.
-
- \param menu context popup menu
-*/
-void PyConsole_Console::contextMenuPopup( QMenu* menu )
-{
- if ( myEditor->isReadOnly() )
- return;
-
- menu->addAction( myActions[CopyId] );
- menu->addAction( myActions[PasteId] );
- menu->addAction( myActions[ClearId] );
- menu->addSeparator();
- menu->addAction( myActions[SelectAllId] );
- menu->addSeparator();
- menu->addAction( myActions[DumpCommandsId] );
-
- //Qtx::simplifySeparators( menu );
-
- updateActions();
-}
-
-/*!
- \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 )
-{
- myActions[CopyId]->setVisible( flags & CopyId );
- myActions[PasteId]->setVisible( flags & PasteId );
- myActions[ClearId]->setVisible( flags & ClearId );
- myActions[SelectAllId]->setVisible( flags & SelectAllId );
- myActions[DumpCommandsId]->setVisible( flags & DumpCommandsId );
-}
-
-/*!
- \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 );
- ret = ret | ( myActions[DumpCommandsId]->isVisible() ? DumpCommandsId : 0 );
- return ret;
-}
-
-/*!
- \brief Create menu actions.
-
- Create context popup menu actions.
-*/
-void PyConsole_Console::createActions()
-{
- QAction* a = new QAction( tr( "&Copy" ), this );
- a->setStatusTip( tr( "Copy" ) );
- connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( copy() ) );
- myActions.insert( CopyId, a );
-
- a = new QAction( tr( "&Paste" ), this );
- a->setStatusTip( tr( "Paste" ) );
- connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( paste() ) );
- myActions.insert( PasteId, a );
-
- a = new QAction( tr( "Clea&r" ), this );
- a->setStatusTip( tr( "Clear" ) );
- connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( clear() ) );
- myActions.insert( ClearId, a );
-
- a = new QAction( tr( "Select &All" ), this );
- a->setStatusTip( tr( "Select all" ) );
- connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( selectAll() ) );
- myActions.insert( SelectAllId, a );
-
-// a = new QAction( tr( "EDIT_DUMPCOMMANDS_CMD" ), this );
-// a->setStatusTip( tr( "EDIT_DUMPCOMMANDS_CMD" ) );
-// connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( dump() ) );
-// myActions.insert( DumpCommandsId, a );
-}
-
-/*!
- \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() );
- myActions[SelectAllId]->setEnabled( !myEditor->document()->isEmpty() );
-}
-
-/**
- * Similar to constructor of the base class but using enhanced objects.
- * TODO: this should really be done in a factory to avoid code duplication.
- * @param parent
- * @param interp
- */
-PyConsole_EnhConsole::PyConsole_EnhConsole( QWidget* parent, PyConsole_EnhInterp* interp)
- : PyConsole_Console(parent, interp, 0)
-{
- // create python interpreter
- myInterp = interp;
- if ( !myInterp )
- myInterp = new PyConsole_EnhInterp();
-
- // initialize Python interpretator
- myInterp->initialize();
-
- // create editor console
- QVBoxLayout* lay = new QVBoxLayout( this );
- lay->setMargin( 0 );
- myEditor = new PyConsole_EnhEditor( static_cast<PyConsole_EnhInterp*>(myInterp), this );
- char* synchronous = getenv("PYTHON_CONSOLE_SYNC");
- if (synchronous && atoi(synchronous))
- {
- myEditor->setIsSync(true);
- }
- myEditor->viewport()->installEventFilter( this );
- lay->addWidget( myEditor );
-
- createActions();
-}
+++ /dev/null
-
-#ifndef PYCONSOLE_CONSOLE_H
-#define PYCONSOLE_CONSOLE_H
-
-#include "PyConsole.h"
-
-//#include <SUIT_PopupClient.h>
-#include <QWidget>
-#include <QMap>
-
-class PyConsole_Interp;
-class PyConsole_Editor;
-class PyConsole_EnhInterp;
-class QMenu;
-
-class PYCONSOLE_EXPORT PyConsole_Console : public QWidget//, public SUIT_PopupClient
-{
- Q_OBJECT
-
-public:
- //! Context popup menu actions flags
- enum
- {
- CopyId = 0x01, //!< "Copy" menu action
- PasteId = 0x02, //!< "Paste" menu action
- ClearId = 0x04, //!< "Clear" menu action
- SelectAllId = 0x08, //!< "Select All" menu action
- DumpCommandsId = 0x16, //!< "DumpCommands" menu action
- All = CopyId | PasteId | ClearId | SelectAllId | DumpCommandsId //!< all menu actions
- };
-
-public:
- PyConsole_Console( QWidget* parent, PyConsole_Interp* interp = 0 );
- virtual ~PyConsole_Console();
-
- //! \brief Get python interperter
- PyConsole_Interp* getInterp() { return myInterp; }
- QFont font() const;
- virtual void setFont( const QFont& );
-
- bool isSync() const;
- void setIsSync( const bool );
-
- bool isSuppressOutput() const;
- void setIsSuppressOutput( const bool );
-
- bool isShowBanner() const;
- void setIsShowBanner( const bool );
-
- void exec( const QString& );
- void execAndWait( const QString& );
-
- virtual bool eventFilter( QObject*, QEvent* );
-
- //! \brief Get popup client symbolic name
- virtual QString popupClientType() const { return QString( "PyConsole" ); }
- virtual void contextMenuPopup( QMenu* );
-
- void setMenuActions( const int );
- int menuActions() const;
-
-protected:
- void createActions();
- void updateActions();
-
- PyConsole_Console( QWidget* parent, PyConsole_Interp*, PyConsole_Editor*);
-
-
- PyConsole_Interp* myInterp; //!< python interpreter
- PyConsole_Editor* myEditor; //!< python console editor widget
- QMap<int, QAction*> myActions; //!< menu actions list
-};
-
-/**
- * Enhance console object providing auto-completion.
- * Similar to PyConsole_Console except that an enhanced interpreter and enhanced editor
- * are encapsulated.
- */
-//
-class PYCONSOLE_EXPORT PyConsole_EnhConsole: public PyConsole_Console
-{
- Q_OBJECT
-
-public:
- PyConsole_EnhConsole( QWidget* parent, PyConsole_EnhInterp* interp = 0);
- virtual ~PyConsole_EnhConsole() {}
-};
-
-#endif // PYCONSOLE_CONSOLE_H
+++ /dev/null
-
-/*!
- \class PyConsole_Editor
- \brief Python command line interpreter front-end GUI widget.
-
- This class provides simple GUI interface to the Python interpreter, including basic
- navigation operations, executing commands (both interactively and programmatically),
- copy-paste operations, history of the commands and so on.
-
- Here below is the shortcut keyboard boundings used for navigation and other operations:
- - <Enter> : execute current command
- - <Ctrl><Break> : clear current command
- - <Escape> : clear current command
- - <Up> : previous command in the history
- - <Shift><Up> : move cursor one row up with selection
- - <Ctrl><Up> : move cursor one row up without selection
- - <Ctrl><Shift><Up> : move cursor one row up with selection
- - <Down> : next command in the history
- - <Shift><Down> : move cursor one row down with selection
- - <Ctrl><Down> : move cursor one row down without selection
- - <Ctrl><Shift><Down> : move cursor one row down with selection
- - <Left> : move one symbol left without selection
- - <Shift><Left> : move one symbol left with selection
- - <Ctrl><Left> : move one word left without selection
- - <Ctrl><Shift><Left> : move one word left with selection
- - <Right> : move one symbol right without selection
- - <Shift><Right> : move one symbol right with selection
- - <Ctrl><Right> : move one word right without selection
- - <Ctrl><Shift><Right> : move one word right with selection
- - <PgUp> : first command in the history
- - <Shift><PgUp> : move one page up with selection
- - <Ctrl><PgUp> : move one page up without selection
- - <Ctrl><Shift><PgUp> : scroll one page up
- - <PgDn> : last command in the history
- - <Shift><PgDn> : move one page down with selection
- - <Ctrl><PgDn> : move one page down without selection
- - <Ctrl><Shift><PgDn> : scroll one page down
- - <Home> : move to the beginning of the line without selection
- - <Shift><Home> : move to the beginning of the line with selection
- - <Ctrl><Home> : move to the very first symbol without selection
- - <Ctrl><Shift><Home> : move to the very first symbol with selection
- - <End> : move to the end of the line without selection
- - <Shift><End> : move to the end of the line with selection
- - <Ctrl><End> : move to the very last symbol without selection
- - <Ctrl><Shift><End> : move to the very last symbol with selection
- - <Backspace> : delete symbol before the cursor
- / remove selected text and put it to the clipboard (cut)
- - <Shift><Backspace> : delete previous word
- / remove selected text and put it to the clipboard (cut)
- - <Ctrl><Backspace> : delete text from the cursor to the beginning of the line
- / remove selected text and put it to the clipboard (cut)
- - <Delete> : delete symbol after the cursor
- / remove selected text and put it to the clipboard (cut)
- - <Shift><Delete> : delete next word
- / remove selected text and put it to the clipboard (cut)
- - <Ctrl><Delete> : delete text from the cursor to the end of the line
- / remove selected text and put it to the clipboard (cut)
- - <Ctrl><Insert> : copy
- - <Shift><Insert> : paste
- - <Ctrl><V> : paste
- - <Ctrl><C> : copy
- - <Ctrl><X> : cut
- - <Ctrl><V> : paste
-*/
-
-#include "PyConsole_Interp.h" // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!!
-#include "PyConsole_Editor.h"
-#include "PyConsole_Event.h"
-#include "PyInterp_Event.h"
-#include "PyInterp_Dispatcher.h"
-#include "PyConsole_Request.h"
-
-//#include <SUIT_Tools.h>
-//#include <SUIT_FileDlg.h>
-//#include <SUIT_MessageBox.h>
-//#include <SUIT_FileValidator.h>
-
-#include <QApplication>
-#include <QClipboard>
-#include <QDropEvent>
-#include <QEvent>
-#include <QKeyEvent>
-#include <QMouseEvent>
-#include <QScrollBar>
-#include <QTextBlock>
-#include <QTextCursor>
-#include <QTextDocument>
-#include <QTextStream>
-#include <QChar>
-
-static QString READY_PROMPT = ">>> ";
-static QString DOTS_PROMPT = "... ";
-
-/*class DumpCommandsFileValidator : public SUIT_FileValidator
-{
- public:
- DumpCommandsFileValidator( QWidget* parent = 0 ) : SUIT_FileValidator ( parent ) {};
- virtual ~DumpCommandsFileValidator() {};
- virtual bool canSave( const QString& file, bool permissions );
-};
-
-bool DumpCommandsFileValidator::canSave(const QString& file, bool permissions)
-{
- QFileInfo fi( file );
- if ( !QRegExp( "[A-Za-z_][A-Za-z0-9_]*" ).exactMatch( fi.completeBaseName() ) ) {
- SUIT_MessageBox::critical( parent(),
- QObject::tr("WRN_WARNING"),
- QObject::tr("WRN_FILE_NAME_BAD") );
- return false;
- }
- return SUIT_FileValidator::canSave( file, permissions);
-}
-*/
-void staticCallbackStdout( void* data, char* c )
-{
- if(!((PyConsole_Editor*)data)->isSuppressOutput())
- QApplication::postEvent( (PyConsole_Editor*)data, new PrintEvent( c, false ) );
-}
-
-void staticCallbackStderr( void* data, char* c )
-{
- if(!((PyConsole_Editor*)data)->isSuppressOutput())
- QApplication::postEvent( (PyConsole_Editor*)data, new PrintEvent( c, true ) );
-}
-
-
-/*!
- \brief Constructor.
-
- Creates python editor window.
- \param theInterp python interper
- \param theParent parent widget
-*/
-PyConsole_Editor::PyConsole_Editor( PyConsole_Interp* theInterp,
- QWidget* theParent )
-: QTextEdit( theParent ),
- myInterp( 0 ),
- myCmdInHistory( -1 ),
- myEventLoop( 0 ),
- myShowBanner( true ),
- myIsSync( false ),
- myIsSuppressOutput( false )
-{
- //QString fntSet( "" );
- QFont aFont = QFont( "Courier", 11 );//SUIT_Tools::stringToFont( fntSet );
- setFont( aFont );
- setUndoRedoEnabled( false );
-
- myPrompt = READY_PROMPT;
- setLineWrapMode( QTextEdit::WidgetWidth );
- setWordWrapMode( QTextOption::WrapAnywhere );
- setAcceptRichText( false );
-
- theInterp->setvoutcb( staticCallbackStdout, this );
- theInterp->setverrcb( staticCallbackStderr, this );
-
- // san - This is necessary for troubleless initialization
- onPyInterpChanged( theInterp );
-}
-
-/*!
- \brief Destructor.
-
- Does nothing for the moment.
-*/
-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;
-}
-
-/*!
- \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 = on;
-}
-
-/*!
- \brief Get suppress output flag value.
-
- \sa setIsSuppressOutput()
- \return \c true if python console output is suppressed.
-*/
-bool PyConsole_Editor::isSuppressOutput() const
-{
- return myIsSuppressOutput;
-}
-
-/*!
- \brief Set suppress output flag value.
-
- In case if suppress output flag is true, the python
- console output suppressed.
-
- \param on suppress output flag
-*/
-void PyConsole_Editor::setIsSuppressOutput( const bool on )
-{
- myIsSuppressOutput = on;
-}
-
-/*!
- \brief Get 'show banner' flag value.
-
- \sa setIsShowBanner()
- \return \c true if python console shows banner
-*/
-bool PyConsole_Editor::isShowBanner() const
-{
- return myShowBanner;
-}
-
-/*!
- \brief Set 'show banner' flag value.
-
- The banner is shown in the top of the python console window.
-
- \sa isShowBanner()
- \param on 'show banner' flag
-*/
-void PyConsole_Editor::setIsShowBanner( const bool on )
-{
- if ( myShowBanner != on ) {
- myShowBanner = on;
- clear();
- }
-}
-
-/*!
- \brief Get size hint for the Python console window
- \return size hint value
-*/
-QSize PyConsole_Editor::sizeHint() const
-{
- QFontMetrics fm( font() );
- int nbLines = ( isShowBanner() ? myBanner.split("\n").count() : 0 ) + 1;
- QSize s(100, fm.lineSpacing()*nbLines);
- return s;
-}
-
-/*!
- \brief Put the string \a str to the python editor.
- \param str string to be put in the command line of the editor
- \param newBlock if True, then the string is printed on a new line
- \param isError if true, the text is printed in dark red
-*/
-void PyConsole_Editor::addText( const QString& str,
- const bool newBlock,
- const bool isError)
-{
- QTextCursor theCursor(textCursor());
- QTextCharFormat cf;
-
- moveCursor( QTextCursor::End );
- if ( newBlock )
- theCursor.insertBlock();
- if (isError)
- cf.setForeground(QBrush(Qt::red));
- else
- cf.setForeground(QBrush(Qt::black));
- theCursor.insertText( str, cf);
- moveCursor( QTextCursor::End );
- ensureCursorVisible();
-}
-
-/*!
- \brief Convenient method for executing a Python command,
- as if the user typed it manually.
- \param command python command to be executed
-
- !!! WARNING: doesn't work properly with multi-line commands. !!!
-*/
-void PyConsole_Editor::exec( const QString& command )
-{
- if ( isReadOnly() ) {
- // some interactive command is being executed in this editor...
- // shedule the command to the queue
- myQueue.push_back( command );
- return;
- }
- // remove last line
- moveCursor( QTextCursor::End );
- moveCursor( QTextCursor::StartOfBlock, QTextCursor::KeepAnchor );
- textCursor().removeSelectedText();
- // set "ready" prompt
- myPrompt = READY_PROMPT;
- // clear command buffer
- myCommandBuffer.truncate( 0 );
- // unset history browsing mode
- myCmdInHistory = -1;
- // print command line by line
- QString cmd = command;
- if ( !cmd.endsWith( "\n" ) ) cmd += "\n";
- QStringList lines = command.split( "\n" );
- for ( int i = 0; i < lines.size(); i++ ) {
- if ( !lines[i].trimmed().isEmpty() )
- myHistory.push_back( lines[i] );
- addText( ( i == 0 ? READY_PROMPT : DOTS_PROMPT ) + lines[i], i != 0 );
- }
- // IPAL20182
- addText( "", true );
- // set read-only mode
- setReadOnly( true );
- // set busy cursor
- setCursor( Qt::BusyCursor );
-
- // post a request to execute Python command;
- // editor will be informed via a custom event that execution has been completed
- PyInterp_Dispatcher::Get()->Exec( createRequest( 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, 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 )
-{
- // already running ?
- if( myEventLoop )
- return;
-
- // create new event loop
- myEventLoop = new QEventLoop( this );
- // execute command
- exec( command );
- // run event loop
- myEventLoop->exec();
- // delete event loop after command is processed
- delete myEventLoop;
- myEventLoop = 0;
-}
-
-/*!
- \brief Process "Enter" key press event.
-
- Execute the command entered by the user.
-*/
-void PyConsole_Editor::handleReturn()
-{
- // Position cursor at the end
- QTextCursor curs(textCursor());
- curs.movePosition(QTextCursor::End);
- setTextCursor(curs);
-
- // get last line
- QTextBlock par = document()->end().previous();
- if ( !par.isValid() ) return;
-
- // get command
- QString cmd = par.text().remove( 0, promptSize() );
- // extend the command buffer with the current command
- myCommandBuffer.append( cmd );
- // add command to the history
- if ( !cmd.trimmed().isEmpty() )
- myHistory.push_back( cmd );
-
- // IPAL19397
- addText( "", true );
-
- // set read-only mode
- setReadOnly( true );
- // set busy cursor
- setCursor( Qt::BusyCursor );
-
- // post a request to execute Python command;
- // editor will be informed via a custom event that execution has been completed
- PyInterp_Dispatcher::Get()->Exec( createRequest( myCommandBuffer ) );
-}
-
-/*!
- \brief Process drop event.
-
- Paste dragged text.
- \param event drop event
-*/
-void PyConsole_Editor::dropEvent( QDropEvent* event )
-{
- // get the initial drop position
- QPoint pos = event->pos();
- QTextCursor cur = cursorForPosition( event->pos() );
- // if the position is not in the last line move it to the end of the command line
- if ( cur.position() < document()->end().previous().position() + promptSize() ) {
- moveCursor( QTextCursor::End );
- pos = cursorRect().center();
- }
- // create new drop event and use it instead of the original
- QDropEvent de( pos,
- event->possibleActions(),
- event->mimeData(),
- event->mouseButtons(),
- event->keyboardModifiers(),
- event->type() );
- QTextEdit::dropEvent( &de );
- // accept the original event
- event->acceptProposedAction();
-}
-
-/*!
- \brief Process mouse button release event.
-
- Left mouse button: copy selection to the clipboard.
- Middle mouse button: paste clipboard's contents.
- \param event mouse event
-*/
-void PyConsole_Editor::mouseReleaseEvent( QMouseEvent* event )
-{
- if ( event->button() == Qt::LeftButton ) {
- QTextEdit::mouseReleaseEvent( event );
- //copy();
- }
- else if ( event->button() == Qt::MidButton ) {
- QTextCursor cur = cursorForPosition( event->pos() );
- // if the position is not in the last line move it to the end of the command line
- if ( cur.position() < document()->end().previous().position() + promptSize() ) {
- moveCursor( QTextCursor::End );
- }
- else {
- setTextCursor( cur );
- }
- const QMimeData* md = QApplication::clipboard()->mimeData( QApplication::clipboard()->supportsSelection() ?
- QClipboard::Selection : QClipboard::Clipboard );
- if ( md )
- insertFromMimeData( md );
- }
- else {
- QTextEdit::mouseReleaseEvent( event );
- }
-}
-
-/*!
- \brief Check if the string is command.
-
- Return True if the string \a str is likely to be the command
- (i.e. it is started from the '>>>' or '...').
- \param str string to be checked
-*/
-bool PyConsole_Editor::isCommand( const QString& str ) const
-{
- return str.startsWith( READY_PROMPT ) || str.startsWith( DOTS_PROMPT );
-}
-
-/*!
- \brief Handle keyboard event.
-
- Implement navigation, history browsing, copy/paste and other common
- operations.
- \param event keyboard event
-*/
-void PyConsole_Editor::keyPressEvent( QKeyEvent* event )
-{
- // get cursor position
- QTextCursor cur = textCursor();
- int curLine = cur.blockNumber();
- int curCol = cur.columnNumber();
-
- // get last edited line
- int endLine = document()->blockCount()-1;
-
- // get pressed key code
- int aKey = event->key();
-
- // check if <Ctrl> is pressed
- bool ctrlPressed = event->modifiers() & Qt::ControlModifier;
- // check if <Shift> is pressed
- bool shftPressed = event->modifiers() & Qt::ShiftModifier;
-
- if ( aKey == Qt::Key_Escape || ( ctrlPressed && aKey == -1 ) ) {
- // process <Ctrl>+<Break> key-binding and <Escape> key: clear current command
- myCommandBuffer.truncate( 0 );
- myPrompt = READY_PROMPT;
- addText( myPrompt, true );
- horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
- return;
- }
- else if ( ctrlPressed && aKey == Qt::Key_C ) {
- // process <Ctrl>+<C> key-binding : copy
- copy();
- return;
- }
- else if ( ctrlPressed && aKey == Qt::Key_X ) {
- // process <Ctrl>+<X> key-binding : cut
- cut();
- return;
- }
- else if ( ctrlPressed && aKey == Qt::Key_V ) {
- // process <Ctrl>+<V> key-binding : paste
- paste();
- return;
- }
-
- // check for printed key
- // #### aKey = ( aKey < Qt::Key_Space || aKey > Qt::Key_ydiaeresis ) ? aKey : 0;
- // Better:
- aKey = !(QChar(aKey).isPrint()) ? aKey : 0;
-
- switch ( aKey ) {
- case 0 :
- // any printed key: just print it
- {
- if ( curLine < endLine || curCol < promptSize() ) {
- moveCursor( QTextCursor::End );
- }
- QTextEdit::keyPressEvent( event );
- break;
- }
- case Qt::Key_Return:
- case Qt::Key_Enter:
- // <Enter> key: process the current command
- {
- handleReturn();
- break;
- }
- case Qt::Key_Up:
- // <Up> arrow key: process as follows:
- // - without <Ctrl>, <Shift> modifiers: previous command in history
- // - with <Ctrl> modifier key pressed: move cursor one row up without selection
- // - with <Shift> modifier key pressed: move cursor one row up with selection
- // - with <Ctrl>+<Shift> modifier keys pressed: scroll one row up
- {
- if ( ctrlPressed && shftPressed ) {
- int value = verticalScrollBar()->value();
- int spacing = fontMetrics().lineSpacing();
- verticalScrollBar()->setValue( value > spacing ? value-spacing : 0 );
- }
- else if ( shftPressed || ctrlPressed ) {
- if ( curLine > 0 )
- moveCursor( QTextCursor::Up,
- shftPressed ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor );
- }
- else {
- if ( myCmdInHistory < 0 && myHistory.count() > 0 ) {
- // set history browsing mode
- myCmdInHistory = myHistory.count();
- // remember current command
- QTextBlock par = document()->end().previous();
- myCurrentCommand = par.text().remove( 0, promptSize() );
- }
- if ( myCmdInHistory > 0 ) {
- myCmdInHistory--;
- // get previous command in the history
- QString previousCommand = myHistory.at( myCmdInHistory );
- // print previous command
- moveCursor( QTextCursor::End );
- moveCursor( QTextCursor::StartOfBlock, QTextCursor::KeepAnchor );
- textCursor().removeSelectedText();
- addText( myPrompt + previousCommand );
- // move cursor to the end
- moveCursor( QTextCursor::End );
- }
- }
- break;
- }
- case Qt::Key_Down:
- // <Down> arrow key: process as follows:
- // - without <Ctrl>, <Shift> modifiers: next command in history
- // - with <Ctrl> modifier key pressed: move cursor one row down without selection
- // - with <Shift> modifier key pressed: move cursor one row down with selection
- // - with <Ctrl>+<Shift> modifier keys pressed: scroll one row down
- {
- if ( ctrlPressed && shftPressed ) {
- int value = verticalScrollBar()->value();
- int maxval = verticalScrollBar()->maximum();
- int spacing = fontMetrics().lineSpacing();
- verticalScrollBar()->setValue( value+spacing < maxval ? value+spacing : maxval );
- }
- else if ( shftPressed || ctrlPressed) {
- if ( curLine < endLine )
- moveCursor( QTextCursor::Down,
- shftPressed ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor );
- }
- else {
- if ( myCmdInHistory >= 0 ) {
- // get next command in the history
- myCmdInHistory++;
- QString nextCommand;
- if ( myCmdInHistory < myHistory.count() ) {
- // next command in history
- nextCommand = myHistory.at( myCmdInHistory );
- }
- else {
- // end of history is reached
- // last printed command
- nextCommand = myCurrentCommand;
- // unset history browsing mode
- myCmdInHistory = -1;
- }
- // print next or current command
- moveCursor( QTextCursor::End );
- moveCursor( QTextCursor::StartOfBlock, QTextCursor::KeepAnchor );
- textCursor().removeSelectedText();
- addText( myPrompt + nextCommand );
- // move cursor to the end
- moveCursor( QTextCursor::End );
- }
- }
- break;
- }
- case Qt::Key_Left:
- // <Left> arrow key: process as follows:
- // - without <Ctrl>, <Shift> modifiers: move one symbol left (taking into account prompt)
- // - with <Ctrl> modifier key pressed: move one word left (taking into account prompt)
- // - with <Shift> modifier key pressed: move one symbol left with selection
- // - with <Ctrl>+<Shift> modifier keys pressed: move one word left with selection
- {
- QString txt = textCursor().block().text();
- if ( !shftPressed && isCommand( txt ) && curCol <= promptSize() ) {
- moveCursor( QTextCursor::Up );
- moveCursor( QTextCursor::EndOfBlock );
- }
- else {
- QTextEdit::keyPressEvent( event );
- }
- break;
- }
- case Qt::Key_Right:
- // <Right> arrow key: process as follows:
- // - without <Ctrl>, <Shift> modifiers: move one symbol right (taking into account prompt)
- // - with <Ctrl> modifier key pressed: move one word right (taking into account prompt)
- // - with <Shift> modifier key pressed: move one symbol right with selection
- // - with <Ctrl>+<Shift> modifier keys pressed: move one word right with selection
- {
- QString txt = textCursor().block().text();
- if ( !shftPressed ) {
- if ( curCol < txt.length() ) {
- if ( isCommand( txt ) && curCol < promptSize() ) {
- cur.setPosition( cur.block().position() + promptSize() );
- setTextCursor( cur );
- break;
- }
- }
- else {
- if ( curLine < endLine && isCommand( textCursor().block().next().text() ) ) {
- cur.setPosition( cur.position() + promptSize()+1 );
- setTextCursor( cur );
- horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
- break;
- }
- }
- }
- QTextEdit::keyPressEvent( event );
- break;
- }
- case Qt::Key_PageUp:
- // <PageUp> key: process as follows:
- // - without <Ctrl>, <Shift> modifiers: first command in history
- // - with <Ctrl> modifier key pressed: move cursor one page up without selection
- // - with <Shift> modifier key pressed: move cursor one page up with selection
- // - with <Ctrl>+<Shift> modifier keys pressed: scroll one page up
- {
- if ( ctrlPressed && shftPressed ) {
- verticalScrollBar()->triggerAction(QAbstractSlider::SliderPageStepSub);
- }
- else if ( shftPressed || ctrlPressed ) {
- bool moved = false;
- qreal lastY = cursorRect( cur ).top();
- qreal distance = 0;
- // move using movePosition to keep the cursor's x
- do {
- qreal y = cursorRect( cur ).top();
- distance += qAbs( y - lastY );
- lastY = y;
- moved = cur.movePosition( QTextCursor::Up,
- shftPressed ? QTextCursor::KeepAnchor :
- QTextCursor::MoveAnchor );
- } while ( moved && distance < viewport()->height() );
- if ( moved ) {
- cur.movePosition( QTextCursor::Down,
- shftPressed ? QTextCursor::KeepAnchor :
- QTextCursor::MoveAnchor );
- verticalScrollBar()->triggerAction( QAbstractSlider::SliderPageStepSub );
- }
- setTextCursor( cur );
- }
- else {
- if ( myCmdInHistory < 0 && myHistory.count() > 0 ) {
- // set history browsing mode
- myCmdInHistory = myHistory.count();
- // remember current command
- QTextBlock par = document()->end().previous();
- myCurrentCommand = par.text().remove( 0, promptSize() );
- }
- if ( myCmdInHistory > 0 ) {
- myCmdInHistory = 0;
- // get very first command in the history
- QString firstCommand = myHistory.at( myCmdInHistory );
- // print first command
- moveCursor( QTextCursor::End );
- moveCursor( QTextCursor::StartOfBlock, QTextCursor::KeepAnchor );
- textCursor().removeSelectedText();
- addText( myPrompt + firstCommand );
- // move cursor to the end
- moveCursor( QTextCursor::End );
- }
- }
- break;
- }
- case Qt::Key_PageDown:
- // <PageDown> key: process as follows:
- // - without <Ctrl>, <Shift> modifiers: last command in history
- // - with <Ctrl> modifier key pressed: move cursor one page down without selection
- // - with <Shift> modifier key pressed: move cursor one page down with selection
- // - with <Ctrl>+<Shift> modifier keys pressed: scroll one page down
- {
- if ( ctrlPressed && shftPressed ) {
- verticalScrollBar()->triggerAction(QAbstractSlider::SliderPageStepAdd);
- }
- else if ( shftPressed || ctrlPressed ) {
- bool moved = false;
- qreal lastY = cursorRect( cur ).top();
- qreal distance = 0;
- // move using movePosition to keep the cursor's x
- do {
- qreal y = cursorRect( cur ).top();
- distance += qAbs( y - lastY );
- lastY = y;
- moved = cur.movePosition( QTextCursor::Down,
- shftPressed ? QTextCursor::KeepAnchor :
- QTextCursor::MoveAnchor );
- } while ( moved && distance < viewport()->height() );
- if ( moved ) {
- cur.movePosition( QTextCursor::Up,
- shftPressed ? QTextCursor::KeepAnchor :
- QTextCursor::MoveAnchor );
- verticalScrollBar()->triggerAction( QAbstractSlider::SliderPageStepSub );
- }
- setTextCursor( cur );
- }
- else {
- if ( myCmdInHistory >= 0 ) {
- // unset history browsing mode
- myCmdInHistory = -1;
- // print current command
- moveCursor( QTextCursor::End );
- moveCursor( QTextCursor::StartOfBlock, QTextCursor::KeepAnchor );
- textCursor().removeSelectedText();
- addText( myPrompt + myCurrentCommand );
- // move cursor to the end
- moveCursor( QTextCursor::End );
- }
- }
- break;
- }
- case Qt::Key_Home:
- // <Home> key: process as follows:
- // - without <Ctrl>, <Shift> modifiers: move cursor to the beginning of the current line without selection
- // - with <Ctrl> modifier key pressed: move cursor to the very first symbol without selection
- // - with <Shift> modifier key pressed: move cursor to the beginning of the current line with selection
- // - with <Ctrl>+<Shift> modifier keys pressed: move cursor to the very first symbol with selection
- {
- if ( ctrlPressed ) {
- moveCursor( QTextCursor::Start,
- shftPressed ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor );
- }
- else {
- QString txt = textCursor().block().text();
- if ( isCommand( txt ) ) {
- if ( shftPressed ) {
- if ( curCol > promptSize() ) {
- cur.movePosition( QTextCursor::StartOfLine, QTextCursor::KeepAnchor );
- cur.movePosition( QTextCursor::Right, QTextCursor::KeepAnchor, promptSize() );
- }
- }
- else {
- cur.movePosition( QTextCursor::StartOfLine );
- cur.movePosition( QTextCursor::Right, QTextCursor::MoveAnchor, promptSize() );
- }
- setTextCursor( cur );
- }
- else {
- moveCursor( QTextCursor::StartOfBlock,
- shftPressed ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor );
- }
- horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
- }
- break;
- }
- case Qt::Key_End:
- // <End> key: process as follows:
- // - without <Ctrl>, <Shift> modifiers: move cursor to the end of the current line without selection
- // - with <Ctrl> modifier key pressed: move cursor to the very last symbol without selection
- // - with <Shift> modifier key pressed: move cursor to the end of the current line with selection
- // - with <Ctrl>+<Shift> modifier keys pressed: move cursor to the very last symbol with selection
- {
- moveCursor( ctrlPressed ? QTextCursor::End : QTextCursor::EndOfBlock,
- shftPressed ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor );
- break;
- }
- case Qt::Key_Backspace :
- // <Backspace> key: process as follows
- // - without any modifiers : delete symbol before the cursor / selection (taking into account prompt)
- // - with <Shift> modifier key pressed: delete previous word
- // - with <Ctrl> modifier key pressed: delete text from the cursor to the line beginning
- // works only for last (command) line
- {
- if ( cur.hasSelection() ) {
- cut();
- }
- else if ( cur.position() > document()->end().previous().position() + promptSize() ) {
- if ( shftPressed ) {
- moveCursor( QTextCursor::PreviousWord, QTextCursor::KeepAnchor );
- textCursor().removeSelectedText();
- }
- else if ( ctrlPressed ) {
- cur.setPosition( document()->end().previous().position() + promptSize(),
- QTextCursor::KeepAnchor );
- setTextCursor( cur );
- textCursor().removeSelectedText();
- }
- else {
- QTextEdit::keyPressEvent( event );
- }
- }
- else {
- cur.setPosition( document()->end().previous().position() + promptSize() );
- setTextCursor( cur );
- horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
- }
- break;
- }
- case Qt::Key_Delete :
- // <Delete> key: process as follows
- // - without any modifiers : delete symbol after the cursor / selection (taking into account prompt)
- // - with <Shift> modifier key pressed: delete next word
- // - with <Ctrl> modifier key pressed: delete text from the cursor to the end of line
- // works only for last (command) line
- {
- if ( cur.hasSelection() ) {
- cut();
- }
- else if ( cur.position() > document()->end().previous().position() + promptSize()-1 ) {
- if ( shftPressed ) {
- moveCursor( QTextCursor::NextWord, QTextCursor::KeepAnchor );
- textCursor().removeSelectedText();
- }
- else if ( ctrlPressed ) {
- moveCursor( QTextCursor::EndOfBlock, QTextCursor::KeepAnchor );
- textCursor().removeSelectedText();
- }
- else {
- QTextEdit::keyPressEvent( event );
- }
- }
- else {
- cur.setPosition( document()->end().previous().position() + promptSize() );
- setTextCursor( cur );
- horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
- }
- break;
- }
- case Qt::Key_Insert :
- // <Insert> key: process as follows
- // - with <Ctrl> modifier key pressed: copy()
- // - with <Shift> modifier key pressed: paste() to the command line
- {
- if ( ctrlPressed ) {
- copy();
- }
- else if ( shftPressed ) {
- paste();
- }
- else
- QTextEdit::keyPressEvent( event );
- break;
- }
- }
-}
-
-/*!
- \brief Handle notification event coming from Python dispatcher.
- \param event notification event
-*/
-void PyConsole_Editor::customEvent( QEvent* event )
-{
- switch( event->type() )
- {
- case PrintEvent::EVENT_ID:
- {
- PrintEvent* pe=(PrintEvent*)event;
- addText( pe->text(), false, pe->isError());
- return;
- }
- case PyInterp_Event::ES_OK:
- case PyInterp_Event::ES_ERROR:
- {
- // 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 );
- // unset busy cursor
- unsetCursor();
- // stop event loop (if running)
- if ( myEventLoop )
- myEventLoop->exit();
- break;
- }
- case PyInterp_Event::ES_INCOMPLETE:
- {
- // 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*/ ); // IPAL19397
- // unset busy cursor
- unsetCursor();
- // stop event loop (if running)
- if ( myEventLoop )
- myEventLoop->exit();
- break;
- }
- default:
- QTextEdit::customEvent( event );
- }
-
- // unset read-only state
- setReadOnly( false );
- // unset history browsing mode
- myCmdInHistory = -1;
-
- if ( (int)event->type() == (int)PyInterp_Event::ES_OK && myQueue.count() > 0 )
- {
- // process the next sheduled command from the queue (if there is any)
- QString nextcmd = myQueue[0];
- myQueue.pop_front();
- exec( nextcmd );
- }
-}
-
-/*!
- \brief Handle Python interpreter change.
-
- Perform initialization actions if the interpreter is changed.
- \param interp python interpreter is being set
-*/
-void PyConsole_Editor::onPyInterpChanged( PyConsole_Interp* interp )
-{
- if ( myInterp != interp
- // Force read-only state and wait cursor when myInterp is NULL
- || !myInterp ) {
- myInterp = interp;
- if ( myInterp ) {
- // print banner
- myBanner = myInterp->getbanner().c_str();
- if ( isShowBanner() )
- addText( myBanner );
- // clear command buffer
- myCommandBuffer.truncate(0);
- // unset read-only state
- setReadOnly( false );
- // unset history browsing mode
- myCmdInHistory = -1;
- // add prompt
- addText( myPrompt );
- // unset busy cursor
- viewport()->unsetCursor();
- // stop event loop (if running)
- if( myEventLoop)
- myEventLoop->exit();
- }
- else {
- // clear contents
- clear();
- // set read-only state
- setReadOnly( true );
- // set busy cursor
- setCursor( Qt::WaitCursor );
- }
- }
-}
-
-/*!
- \brief "Copy" operation.
-
- Reimplemented from Qt.
- Warning! In Qt4 this method is not virtual.
- */
-void PyConsole_Editor::cut()
-{
- QTextCursor cur = textCursor();
- if ( cur.hasSelection() ) {
- QApplication::clipboard()->setText( cur.selectedText() );
- int startSelection = cur.selectionStart();
- if ( startSelection < document()->end().previous().position() + promptSize() )
- startSelection = document()->end().previous().position() + promptSize();
- int endSelection = cur.selectionEnd();
- if ( endSelection < document()->end().previous().position() + promptSize() )
- endSelection = document()->end().previous().position() + promptSize();
- cur.setPosition( startSelection );
- cur.setPosition( endSelection, QTextCursor::KeepAnchor );
- horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
- setTextCursor( cur );
- textCursor().removeSelectedText();
- }
-}
-
-/*!
- \brief "Paste" operation.
-
- Reimplemented from Qt.
- Warning! In Qt4 this method is not virtual.
- */
-void PyConsole_Editor::paste()
-{
- QTextCursor cur = textCursor();
- if ( cur.hasSelection() ) {
- int startSelection = cur.selectionStart();
- if ( startSelection < document()->end().previous().position() + promptSize() )
- startSelection = document()->end().previous().position() + promptSize();
- int endSelection = cur.selectionEnd();
- if ( endSelection < document()->end().previous().position() + promptSize() )
- endSelection = document()->end().previous().position() + promptSize();
- cur.setPosition( startSelection );
- cur.setPosition( endSelection, QTextCursor::KeepAnchor );
- horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
- setTextCursor( cur );
- textCursor().removeSelectedText();
- }
- if ( textCursor().position() < document()->end().previous().position() + promptSize() )
- moveCursor( QTextCursor::End );
- QTextEdit::paste();
-}
-
-/*!
- \brief "Clear" operation.
-
- Reimplemented from Qt.
- Warning! In Qt4 this method is not virtual.
- */
-void PyConsole_Editor::clear()
-{
- QTextEdit::clear();
- if ( isShowBanner() )
- addText( myBanner );
- myPrompt = READY_PROMPT;
- addText( myPrompt );
-}
-
-/*!
- \brief "Dump commands" operation.
- */
-/*void PyConsole_Editor::dump()
-{
- QStringList aFilters;
- aFilters.append( tr( "PYTHON_FILES_FILTER" ) );
-
- QString fileName = SUIT_FileDlg::getFileName( this, QString(),
- aFilters, tr( "TOT_DUMP_PYCOMMANDS" ),
- false, true, new DumpCommandsFileValidator( this ) );
- if ( fileName != "" ) {
- QFile file( fileName );
- if ( !file.open( QFile::WriteOnly ) )
- return;
-
- QTextStream out (&file);
-
- for( int i=0; i<myHistory.count(); i++ ) {
- out<<myHistory[i]<<endl;
- }
- file.close();
- }
-}*/
+++ /dev/null
-
-#ifndef PYCONSOLE_EDITOR_H
-#define PYCONSOLE_EDITOR_H
-
-#include "PyConsole.h"
-
-#include <QTextEdit>
-
-class PyConsole_Interp;
-class PyInterp_Request;
-class QEventLoop;
-
-class PYCONSOLE_EXPORT PyConsole_Editor : public QTextEdit
-{
- Q_OBJECT;
-
-public:
- PyConsole_Editor( PyConsole_Interp* theInterp, QWidget *theParent = 0 );
- ~PyConsole_Editor();
-
- virtual void addText( const QString& str, const bool newBlock = false, const bool isError = false );
- bool isCommand( const QString& str ) const;
-
- virtual void exec( const QString& command );
- void execAndWait( const QString& command );
-
- bool isSync() const;
- void setIsSync( const bool );
-
- bool isSuppressOutput() const;
- void setIsSuppressOutput(const bool);
-
- bool isShowBanner() const;
- void setIsShowBanner( const bool );
-
- virtual QSize sizeHint() const;
-
-public slots:
- void cut();
- void paste();
- void clear();
- void handleReturn();
- void onPyInterpChanged( PyConsole_Interp* );
- //.void dump();
-
-protected:
- virtual void dropEvent( QDropEvent* event );
- virtual void mouseReleaseEvent( QMouseEvent* event );
- virtual void keyPressEvent ( QKeyEvent* event);
- virtual void customEvent( QEvent* event);
-
- virtual PyInterp_Request* createRequest( const QString& );
-
- /** Convenience function */
- inline int promptSize() const { return myPrompt.size(); }
-
- PyConsole_Interp* myInterp; //!< python interpreter
-
- QString myCommandBuffer; //!< python command 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
- bool myShowBanner; //!< 'show banner' flag
- QStringList myQueue; //!< python commands queue
- bool myIsSync; //!< synchronous mode flag
- bool myIsSuppressOutput; //!< suppress output flag
-};
-
-#endif // PYCONSOLE_EDITOR_H
+++ /dev/null
-
-
-#include "PyConsole.h"
-#include <Python.h>
-
-#include <QKeyEvent>
-#include <QTextBlock>
-#include <QTextCursor>
-#include <QTextCharFormat>
-#include <QRegExp>
-#include <QMimeData>
-
-#include "PyConsole_EnhEditor.h"
-#include "PyConsole_EnhInterp.h"
-#include "PyConsole_Request.h"
-#include "PyInterp_Dispatcher.h"
-
-// Initialize list of valid separators
-static const char * tmp_a[] = {" ", "(", "[","+", "-", "*", "/", ";", "^", "="};
-const std::vector<QString> PyConsole_EnhEditor::SEPARATORS = \
- std::vector<QString>(tmp_a, tmp_a + sizeof(tmp_a)/sizeof(tmp_a[0]));
-
-/**
- * Constructor.
- * @param interp the interpreter linked to the editor
- * @param parent parent widget
- */
-PyConsole_EnhEditor::PyConsole_EnhEditor(PyConsole_EnhInterp * interp, QWidget * parent) :
- PyConsole_Editor(interp, parent),
- _tab_mode(false),
- _cursor_pos(-1),
- _multi_line_paste(false),
- _multi_line_content()
-{
- document()->setUndoRedoEnabled(true);
-}
-
-/**
- * Overrides. Catches the TAB and Ctrl+TAB combinations.
- * @param event
- */
-void PyConsole_EnhEditor::keyPressEvent ( QKeyEvent* event)
-{
- // check if <Ctrl> is pressed
- bool ctrlPressed = event->modifiers() & Qt::ControlModifier;
- // check if <Shift> is pressed
- bool shftPressed = event->modifiers() & Qt::ShiftModifier;
-
- if (event->key() == Qt::Key_Tab && !shftPressed)
- {
- if (!ctrlPressed)
- handleTab();
- else
- {
- clearCompletion();
- handleBackTab();
- }
- PyConsole_Editor::keyPressEvent(event);
- }
- else
- {
- // If ctrl is not pressed (and sth else is pressed with it),
- // or if ctrl is not pressed alone
- if (!ctrlPressed || (ctrlPressed && event->key() != Qt::Key_Control))
- {
- clearCompletion();
- _cursor_pos = -1;
- }
- // Discard ctrl pressed alone:
- if (event->key() != Qt::Key_Control)
- PyConsole_Editor::keyPressEvent(event);
- }
-}
-
-/**
- * Whenever the mouse is clicked, clear the completion.
- * @param e
- */
-void PyConsole_EnhEditor::mousePressEvent(QMouseEvent* e)
-{
- clearCompletion();
- _cursor_pos = -1;
- PyConsole_Editor::mousePressEvent(e);
-}
-
-/**
- * Clear in the editor the block of text displayed after having hit <TAB>.
- */
-void PyConsole_EnhEditor::clearCompletion()
-{
- // Delete completion text if present
- if (_tab_mode)
- {
- // Remove completion display
- document()->undo();
- // Remove trailing line return:
- QTextCursor tc(textCursor());
- tc.setPosition(document()->characterCount()-1);
- setTextCursor(tc);
- textCursor().deletePreviousChar();
- // TODO: before wait for any TAB event to be completed
- static_cast<PyConsole_EnhInterp *>(myInterp)->clearCompletion();
- }
- _tab_mode = false;
-}
-
-/**
- * Handle the sequence of events after having hit <TAB>
- */
-void PyConsole_EnhEditor::handleTab()
-{
- if (_tab_mode)
- {
- // Already tab mode - nothing to do !
- return;
- }
-
- QTextCursor cursor(textCursor());
-
- // Cursor at end of input
- cursor.movePosition(QTextCursor::End);
- setTextCursor(cursor);
-
- // Save cursor position if needed
- if (_cursor_pos == -1)
- _cursor_pos = textCursor().position();
-
- // get last line
- QTextBlock par = document()->end().previous();
- if ( !par.isValid() ) return;
-
- // Switch to completion mode
- _tab_mode = true;
-
- QString cmd = par.text().mid(promptSize());
-
- // Post completion request
- // Editor will be informed via a custom event that completion has been run
- PyInterp_Request* req = createTabRequest(cmd);
- PyInterp_Dispatcher::Get()->Exec(req);
-}
-
-/**
- * Handles what happens after hitting Ctrl-TAB
- */
-void PyConsole_EnhEditor::handleBackTab()
-{
- QTextCursor cursor(textCursor());
-
- if (_cursor_pos == -1)
- {
- // Invalid cursor position - we can't do anything:
- return;
- }
- // Ensure cursor is at the end of command line
- cursor.setPosition(_cursor_pos);
- cursor.movePosition(QTextCursor::EndOfLine);
- //setCursor(cursor);
-
- // Delete last completed text
- int i = cursor.position() - _cursor_pos;
- cursor.movePosition(QTextCursor::Left, QTextCursor::KeepAnchor, i);
- cursor.removeSelectedText();
- _cursor_pos = -1;
-}
-
-/**
- * Create the Python requested that will be posted to the interpreter to
- * get the completions.
- * @param input line typed by the user at the time TAB was hit
- * @return a CompletionCommand
- * @sa CompletionCommand
- */
-PyInterp_Request* PyConsole_EnhEditor::createTabRequest( const QString& input )
-{
- // Parse input to extract on what part the dir() has to be executed
- QString input2(input);
-
- // Split up to the last syntaxical separator
- int lastSp = -1;
- for (std::vector<QString>::const_iterator i = SEPARATORS.begin(); i != SEPARATORS.end(); i++)
- {
- int j = input2.lastIndexOf(*i);
- if (j > lastSp)
- lastSp = j;
- }
- if (lastSp >= 0)
- input2 = input.mid(lastSp+1);
-
- // Detect a qualified name (with a point)
- int lastPt = input2.lastIndexOf(QString("."));
-
- // Split the 2 surrounding parts of the qualified name
- if (lastPt != -1)
- {
- _compl_before_point = input2.left(lastPt);
- _compl_after_point = input2.mid(lastPt+1);
- }
- else
- {
- // No point found - do a global matching -
- // (the following will call dir() with an empty string)
- _compl_after_point = input2;
- _compl_before_point = QString("");
- }
-
- return new CompletionCommand( static_cast<PyConsole_EnhInterp *>(myInterp), _compl_before_point,
- _compl_after_point, this, isSync() );
-}
-
-/**
- * Format completion results - this is where we should create 3 columns etc ...
- * @param matches list of possible completions
- * @param result return value
- */
-void PyConsole_EnhEditor::formatCompletion(const std::vector<QString> & matches, QString & result) const
-{
- int sz = matches.size();
-
- if (sz > MAX_COMPLETIONS)
- {
- sz = MAX_COMPLETIONS;
- result.append("[Too many matches! Displaying first ones only ...]\n");
- }
-
- for (int i = 0; i < sz; ++i)
- {
- result.append(matches[i]);
- result.append("\n");
- }
-}
-
-/**
- * Override. Catches the events generated by the enhanced interpreter after the execution
- * of a completion request.
- * @param event
- */
-void PyConsole_EnhEditor::customEvent( QEvent* event )
-{
- std::vector<QString> matches;
- QString first_match, comple_text, doc, base;
- QTextCursor cursor(textCursor());
- QTextBlockFormat bf;
- QTextCharFormat cf;
- PyConsole_EnhInterp * interp = static_cast<PyConsole_EnhInterp *>(myInterp);
- int cursorPos;
-
- switch( event->type() )
- {
- case PyInterp_Event::ES_TAB_COMPLETE_OK:
- // Extract corresponding matches from the interpreter
- matches = interp->getLastMatches();
-
- if (matches.size() == 0)
- {
- // Completion successful but nothing returned.
- _tab_mode = false;
- _cursor_pos = -1;
- return;
- }
-
- // Only one match - complete directly and update doc string window
- doc = interp->getDocStr();
- if (matches.size() == 1)
- {
- first_match = matches[0].mid(_compl_after_point.size());
- cursor.insertText(first_match);
- _tab_mode = false;
- if (doc == QString(""))
- emit updateDoc(formatDocHTML("(no documentation available)\n"));
- else
- emit updateDoc(formatDocHTML(doc));
- }
- else
- {
- // Detect if there is a common base to all available completion
- // In this case append this base to the text already
- extractCommon(matches, base);
- first_match = base.mid(_compl_after_point.size());
- cursor.insertText(first_match);
-
- // If this happens to match exaclty the first completion
- // also provide doc
- if (base == matches[0])
- {
- doc = formatDocHTML(doc);
- emit updateDoc(doc);
- }
-
- // Print all matching completion in a "undo-able" block
- cursorPos = cursor.position();
- cursor.insertBlock();
- cursor.beginEditBlock();
-
- // Insert all matches
- QTextCharFormat cf;
- cf.setForeground(QBrush(Qt::darkGreen));
- cursor.setCharFormat(cf);
- formatCompletion(matches, comple_text);
- cursor.insertText(comple_text);
- cursor.endEditBlock();
-
- // Position cursor where it was before inserting the completion list:
- cursor.setPosition(cursorPos);
- setTextCursor(cursor);
- }
- break;
- case PyInterp_Event::ES_TAB_COMPLETE_ERR:
- // Tab completion was unsuccessful, switch off mode:
- _tab_mode = false;
- _cursor_pos = -1;
- break;
- case PyInterp_Event::ES_OK:
- case PyInterp_Event::ES_ERROR:
- case PyInterp_Event::ES_INCOMPLETE:
- // Before everything else, call super()
- PyConsole_Editor::customEvent(event);
- // If we are in multi_paste_mode, process the next item:
- multiLineProcessNextLine();
- break;
- default:
- PyConsole_Editor::customEvent( event );
- break;
- }
-}
-
-/**
- * Extract the common leading part of all strings in matches.
- * @param matches
- * @param result
- */
-void PyConsole_EnhEditor::extractCommon(const std::vector<QString> & matches, QString & result) const
-{
- result = "";
- int charIdx = 0;
-
- if (matches.size() < 2)
- return;
-
- while (true)
- {
- if (charIdx >= matches[0].size())
- return;
- QChar ch = matches[0][charIdx];
- for (size_t j = 1; j < matches.size(); j++)
- if (charIdx >= matches[j].size() || matches[j][charIdx] != ch)
- return;
- result += ch;
- charIdx++;
- }
-}
-
-/**
- * Format the doc string in HTML format with the first line in bold blue
- * @param doc initial doc string
- * @return HTML string
- */
-QString PyConsole_EnhEditor::formatDocHTML(const QString & doc) const
-{
- QString templ = QString("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" ") +
- QString(" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n ") +
- QString("<html><head><meta name=\"qrichtext\" content=\"1\" /> ") +
- QString("<style type=\"text/css\">\np, li { white-space: pre-wrap; }\n</style> ") +
- QString("</head><body style=\" font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;\">\n") +
- QString("<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">") +
- QString("<span style=\" font-weight:600; color:#0000ff;\">%1</span></p>") +
- QString("<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">%2</p>") +
- QString("</body></html>");
-
- QString fst, rest("");
-
- // Extract first line of doc
- int idx = doc.indexOf("\n");
- if (idx > 0)
- {
- fst = doc.left(idx);
- rest = doc.mid(idx+1);
- }
- else
- {
- fst = doc;
- }
-
- fst = fst.replace("\n", " ");
- rest = rest.replace("\n", " ");
- return templ.arg(fst).arg(rest);
-}
-
-/**
- * Handle properly multi-line pasting. Qt4 doc recommends overriding this function.
- * If the pasted text doesn't contain a line return, no special treatment is done.
- * @param source
- */
-void PyConsole_EnhEditor::insertFromMimeData(const QMimeData * source)
-{
- if (_multi_line_paste)
- return;
-
- if (source->hasText())
- {
- QString s = source->text();
- if (s.contains("\n"))
- multilinePaste(s);
- else
- PyConsole_Editor::insertFromMimeData(source);
- }
- else
- {
- PyConsole_Editor::insertFromMimeData(source);
- }
-}
-
-
-void PyConsole_EnhEditor::multilinePaste(const QString & s)
-{
- // Turn on multi line pasting mode
- _multi_line_paste = true;
-
- // Split the string:
- QString s2 = s;
- s2.replace("\r", ""); // Windows string format converted to Unix style
-
- QStringList lst = s2.split(QChar('\n'), QString::KeepEmptyParts);
-
- // Perform the proper paste operation for the first line to handle the case where
- // sth was already there:
- QMimeData source;
- source.setText(lst[0]);
- PyConsole_Editor::insertFromMimeData(&source);
-
- // Prepare what will have to be executed after the first line:
- _multi_line_content = std::queue<QString>();
- for (int i = 1; i < lst.size(); ++i)
- _multi_line_content.push(lst[i]);
-
- // Trigger the execution of the first (mixed) line
- handleReturn();
-
- // See customEvent() and multiLineProcessNext() for the rest of the handling.
-}
-
-/**
- * Process the next line in the queue of a multiple copy/paste:
- */
-void PyConsole_EnhEditor::multiLineProcessNextLine()
-{
- if (!_multi_line_paste)
- return;
-
- QString line(_multi_line_content.front());
- _multi_line_content.pop();
- if (!_multi_line_content.size())
- {
- // last line in the queue, just paste it
- addText(line, false, false);
- _multi_line_paste = false;
- }
- else
- {
- // paste the line and simulate a <RETURN> key stroke
- addText(line, false, false);
- handleReturn();
- }
-}
+++ /dev/null
-
-
-#ifndef PYCONSOLE_ENHEDITOR_H_
-#define PYCONSOLE_ENHEDITOR_H_
-
-#include "PyConsole.h"
-
-#include "PyConsole_Editor.h"
-#include <QObject>
-#include <queue>
-
-class PyConsole_EnhInterp;
-
-/**
- * Enhanced Python editor handling tab completion.
- */
-class PYCONSOLE_EXPORT PyConsole_EnhEditor: public PyConsole_Editor
-{
- Q_OBJECT;
-
-public:
- PyConsole_EnhEditor(PyConsole_EnhInterp * interp, QWidget * parent=0);
- virtual ~PyConsole_EnhEditor() {}
-
-signals:
- /**
- * Signal emitted by the editor widget when the doc string should be updated.
- * @param doc a HTML block with the formatted doc string.
- * TODO: for now this signal is left uncaught.
- */
- void updateDoc(QString doc);
-
-protected:
- /** List of separators identifying the last parsable token for completion */
- static const std::vector<QString> SEPARATORS;
-
- /** Maximum number of completions shown at once */
- static const int MAX_COMPLETIONS = 70;
-
- /** Are we in completion mode */
- bool _tab_mode;
-
- /** String on which the dir() comamnd is executed */
- QString _compl_before_point;
- /** String on which the results of the dir() are matched */
- QString _compl_after_point;
-
- /** Cursor position when <TAB> is hit */
- int _cursor_pos;
-
- /** Are we currently pasting several lines */
- bool _multi_line_paste;
-
- /** Queue of lines being pasted */
- std::queue<QString> _multi_line_content;
-
- // Overrides:
- virtual void keyPressEvent ( QKeyEvent* event);
- virtual void customEvent( QEvent* event);
- virtual void mousePressEvent( QMouseEvent* event );
- virtual void insertFromMimeData(const QMimeData * source);
-
- virtual PyInterp_Request* createTabRequest( const QString& input );
- virtual void handleTab();
- virtual void handleBackTab();
- virtual void clearCompletion();
- virtual void formatCompletion(const std::vector<QString> & matches, QString & result) const;
- virtual QString formatDocHTML(const QString & doc) const;
-
- virtual void multilinePaste(const QString & s);
- virtual void multiLineProcessNextLine();
-
-private:
- void extractCommon(const std::vector<QString> & matches, QString & result) const;
-
-};
-
-#endif /* PYCONSOLE_ENHEDITOR_H_ */
+++ /dev/null
-
-
-
-#include "PyConsole.h"
-
-#include "PyConsole_EnhInterp.h"
-
-#include <pythonrun.h>
-#include <string>
-#include <QRegExp>
-
-static const char * tmp_k[] = {"and", "as", "assert", "break", "class",
- "continue", "def", "del",
- "elif", "else", "except", "exec", "finally", "for", "from", "global", "if",
- "import", "in", "is", "lambda", "not", "or", "pass", "print", "raise",
- "return", "try", "while", "with", "yield"};
-
-const std::vector<QString> PyConsole_EnhInterp::PYTHON_KEYWORDS = \
- std::vector<QString>(tmp_k, tmp_k+sizeof(tmp_k)/sizeof(tmp_k[0]));
-
-/*!
- \brief Run Python dir() command and saves the result internally in _lastPy
- \param dirArgument Python expression to pass to the dir command. The parsing of what the
- user actually started typing is dedicated to the caller
- \param startMatch string representing the begining of the patter to be completed. For example when
- the user types "a_string_variable.rsp <TAB>", this is "rsp".
- \return command exit status - 0 = success
-*/
-int PyConsole_EnhInterp::runDirCommand(const QString & dirArgument, const QString & startMatch)
-{
- int ret;
- std::vector<QString> v;
-
- clearCompletion();
- if ( (ret = runDirAndExtract(dirArgument, startMatch, _last_matches)) )
- return ret;
-
- // If dirArgument is empty, we append the __builtins__
- if (dirArgument.isEmpty())
- {
- if ( (ret = runDirAndExtract(QString("__builtins__"), startMatch, _last_matches, false)) )
- return ret;
-
- // ... and we match on Python's keywords as well:
- for (std::vector<QString>::const_iterator it = PYTHON_KEYWORDS.begin(); it != PYTHON_KEYWORDS.end(); it++)
- if ((*it).startsWith(startMatch))
- _last_matches.push_back(*it);
- }
-
- // Try to get doc string of the first match
- if (_last_matches.size() > 0)
- {
- QString cmd("");
- if (dirArgument.trimmed() != "")
- cmd = dirArgument + ".";
- cmd += _last_matches[0] + ".__doc__";
- PyObject * str = PyRun_String(cmd.toStdString().c_str(), Py_eval_input, _g, _g);
- if (!str || str == Py_None || !PyString_Check(str))
- {
- if (!str)
- PyErr_Clear();
- _doc_str = "";
- }
- else
- _doc_str = QString(PyString_AsString(str));
- Py_XDECREF(str);
- }
-
- // The command has been successfully executed
- return 0;
-}
-
-/**
- * See runDirCommand().
- * @param dirArgument see runDirCommand()
- * @param startMatch see runDirCommand()
- * @param[out] result the list of matches
- * @param discardSwig if true a regular expression is used to discard all static method generated
- * by SWIG. typically: MEDCouplingUMesh_Blabla
- * @return -1 if the call to dir() or the parsing of the result failed, 0 otherwise.
- */
-int PyConsole_EnhInterp::runDirAndExtract(const QString& dirArgument,
- const QString & startMatch, std::vector<QString> & result,
- bool discardSwig) const
-{
- QRegExp re("^[A-Z].+_[A-Z]+[a-z]+.+$"); // discard SWIG static method, e.g. MEDCouplingUMesh_Blabla
- QString command("dir(" + dirArgument + ")");
- PyObject * plst = PyRun_String(command.toStdString().c_str(), Py_eval_input, _g, _g);
- if(!plst || plst == Py_None) {
- if(!plst)
- PyErr_Clear();
-
- Py_XDECREF(plst);
- return -1;
- }
-
- // Extract the returned list and convert it to a vector<>
- if (!PySequence_Check(plst))
- {
- // Should never happen ...
- //std::cerr << "not a list!" << std::endl;
- Py_XDECREF(plst);
- return -1;
- }
-
- // Convert plst to a vector of QString
- int n = PySequence_Length(plst);
- for (int i = 0; i < n; i++)
- {
- PyObject * it;
- it = PySequence_GetItem(plst, i);
- QString s(PyString_AsString(it));
- // if the method is not from swig, not static (guessed from the reg exp) and matches
- // what is already there
- if (s.startsWith(startMatch))
- if(!discardSwig || (!re.exactMatch(s) && !s.contains("swig")))
- result.push_back(s);
- Py_DECREF(it);
- }
- Py_DECREF(plst);
-
- return 0;
-}
-
-/**
- * Clear internal members containing the last completion results.
- */
-void PyConsole_EnhInterp::clearCompletion()
-{
- _last_matches.resize(0);
- _doc_str = QString("");
-}
-
-
-
+++ /dev/null
-
-
-#ifndef PYCONSOLE_ENHINTERP_H_
-#define PYCONSOLE_ENHINTERP_H_
-
-#include "PyConsole.h"
-
-#include <Python.h>
-#include "PyConsole_Interp.h"
-
-#include <vector>
-#include <QString>
-
-/**
- * Enhanced Python interpreter used for auto-completion.
- * This extends PyConsole_Interp with an API wrapping the Python dir() command nicely.
- */
-class PYCONSOLE_EXPORT PyConsole_EnhInterp: public PyConsole_Interp
-{
-public:
- PyConsole_EnhInterp()
- : PyConsole_Interp(), _last_matches(0), _doc_str("")
- {}
-
- virtual ~PyConsole_EnhInterp() {}
-
- const std::vector<QString>& getLastMatches() const { return _last_matches; }
- const QString & getDocStr() const { return _doc_str; }
-
- virtual int runDirCommand(const QString& dirArgument, const QString& startMatch);
- virtual void clearCompletion();
-
-protected:
- /** Hard coded list of Python keywords */
- static const std::vector<QString> PYTHON_KEYWORDS;
-
- /** Last computed matches */
- std::vector<QString> _last_matches;
- /** Doc string of the first match - when only one match it will be displayed by the Editor*/
- QString _doc_str;
-
- virtual int runDirAndExtract(const QString& dirArgument, const QString & startMatch,
- std::vector<QString> & result, bool discardSwig=true) const;
-
-};
-
-#endif /* PYCONSOLE_ENHINTERP_H_ */
+++ /dev/null
-
-
-#include "PyConsole_Event.h"
+++ /dev/null
-
-
-#ifndef PYCONSOLE_EVENT_H
-#define PYCONSOLE_EVENT_H
-
-#include "PyConsole.h"
-
-#include <QEvent>
-#include <QString>
-
-/*!
- \class PrintEvent
- \brief Python command output backend event.
- \internal
-*/
-class PrintEvent : public QEvent
-{
-public:
- static const int EVENT_ID = 65432;
-
- /*!
- \brief Constructor
- \param c message text (python trace)
- \param isError default to false - if true indicates that an error is being printed.
- */
- PrintEvent( const char* c, bool isError = false) :
- QEvent( (QEvent::Type)EVENT_ID ), myText( c ), errorFlag(isError)
- {}
-
- /*!
- \brief Get message
- \return message text (python trace)
- */
- QString text() const { return myText; }
-
- /**
- * @return true if this is an error message
- */
- bool isError() const { return errorFlag; }
-
-protected:
- QString myText; //!< Event message (python trace)
-
- /** Set to true if an error msg is to be displayed */
- bool errorFlag;
-};
-
-#endif // PYCONSOLE_EVENT_H
+++ /dev/null
-
-#include "PyConsole_Interp.h"
-
-/*!
- \class PyConsole_Interp
- \brief Python interpreter to be embedded to the SALOME study's GUI.
-
- Python interpreter is created one per SALOME study.
-
- 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.
-
- <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
- 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.
-
- <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
- in restricted execution environment. So we must impose that all interpreters
- have identical __builtin__ module.
-*/
-
-/*!
- \brief Constructor.
-
- Creates new python interpreter.
-*/
-PyConsole_Interp::PyConsole_Interp(): PyInterp_Interp()
-{
-}
-
-/*!
- \brief Destructor.
-
- Does nothing for the moment.
-*/
-PyConsole_Interp::~PyConsole_Interp()
-{
-}
-
-/*!
- \brief Initialize internal Python interpreter state.
-
- When calling initState the GIL is not held
- It must not be held on exit
-
- \return \c true on success
-*/
-bool PyConsole_Interp::initState()
-{
- PyEval_AcquireLock();
- _tstate = Py_NewInterpreter(); // create an interpreter and save current state
- PySys_SetArgv(PyInterp_Interp::_argc,PyInterp_Interp::_argv); // initialize sys.argv
-
- if(!builtinmodule) // PAL18041: deepcopy function don't work in Salome
- {
- //builtinmodule is static member of PyInterp class
- //If it is not NULL (initialized to the builtin module of the main interpreter
- //all the sub interpreters will have the same builtin
- //_interp is a static member and is the main interpreter
- //The first time we initialized it to the builtin of main interpreter
- builtinmodule=PyDict_GetItemString(_interp->modules, "__builtin__");
- }
-
- //If builtinmodule has been initialized all the sub interpreters
- // will have the same __builtin__ module
- if(builtinmodule){
- PyObject *m = PyImport_GetModuleDict();
- PyDict_SetItemString(m, "__builtin__", builtinmodule);
- _tstate->interp->builtins = PyModule_GetDict(builtinmodule);
- Py_INCREF(_tstate->interp->builtins);
- }
- PyEval_ReleaseThread(_tstate);
- return true;
-}
-
-/*!
- \brief Initialize python interpeter context.
-
- The GIL is assumed to be held.
- It is the caller responsability to acquire the GIL.
- It must still be held on initContext() exit.
-
- \return \c true on success
-*/
-bool PyConsole_Interp::initContext()
-{
- PyObject *m = PyImport_AddModule("__main__"); // interpreter main module (module context)
- if(!m){
- PyErr_Print();
- return false;
- }
- _g = PyModule_GetDict(m); // get interpreter dictionnary context
-
- if(builtinmodule){
- PyDict_SetItemString(_g, "__builtins__", builtinmodule); // assign singleton __builtin__ module
- }
- return true;
-}
+++ /dev/null
-
-#ifndef PYCONSOLE_INTERP_H
-#define PYCONSOLE_INTERP_H
-
-#include "PyConsole.h"
-
-#include <PyInterp_Interp.h> /// !!! WARNING !!! THIS INCLUDE MUST BE VERY FIRST !!!
-
-class PYCONSOLE_EXPORT PyConsole_Interp : public PyInterp_Interp
-{
-public:
- PyConsole_Interp();
- ~PyConsole_Interp();
-
-protected:
- virtual bool initState();
- virtual bool initContext();
-};
-
-#endif // PYCONSOLE_INTERP_H
+++ /dev/null
-
-
-#include "PyConsole_Request.h"
-
-#include "PyInterp_Event.h"
-#include "PyConsole_Event.h"
-#include "PyConsole_EnhInterp.h"
-#include "PyConsole_EnhEditor.h"
-
-#include <QCoreApplication>
-
-/**
- * Constructor.
- * @param theInterp interpreter that will execute the command
- * @param theCommand command text
- * @param theListener editor object that will receive the response events after execution
- * of the request
- * @param sync
- */
-ExecCommand::ExecCommand( PyInterp_Interp* theInterp,
- const QString& theCommand,
- PyConsole_Editor* theListener,
- bool sync )
- : PyInterp_LockRequest( theInterp, theListener, sync ),
- myCommand( theCommand ), myState( PyInterp_Event::ES_OK )
- {}
-
-/**
- * Execute the command by calling the run() method of the embedded interpreter.
- */
-void ExecCommand::execute()
-{
- if ( myCommand != "" )
- {
- int ret = getInterp()->run( myCommand.toUtf8().data() );
- if ( ret < 0 )
- myState = PyInterp_Event::ES_ERROR;
- else if ( ret > 0 )
- myState = PyInterp_Event::ES_INCOMPLETE;
- }
-}
-
-/**
- * Create the event indicating the status of the request execution.
- * @return a QEvent
- */
-QEvent* ExecCommand::createEvent()
-{
- if ( IsSync() )
- QCoreApplication::sendPostedEvents( listener(), PrintEvent::EVENT_ID );
- return new PyInterp_Event( myState, this );
-}
-
-
-/*!
- Constructor.
- Creates a new python completion request.
- \param theInterp python interpreter
- \param input string containing the dir() command to be executed
- \param startMatch part to be matched with the results of the dir() command
- \param theListener widget to get the notification messages
- \param sync if True the request is processed synchronously
-*/
-CompletionCommand::CompletionCommand( PyConsole_EnhInterp* theInterp,
- const QString& input,
- const QString& startMatch,
- PyConsole_EnhEditor* theListener,
- bool sync)
- : PyInterp_LockRequest( theInterp, theListener, sync ),
- _tabSuccess(false), _dirArg(input), _startMatch(startMatch)
-{}
-
-/**
- * Execute the completion command by wrapping the runDirCommand() of the
- * embedded enhanced interpreter.
- */
-void CompletionCommand::execute()
-{
- PyConsole_EnhInterp * interp = static_cast<PyConsole_EnhInterp *>(getInterp());
- int ret = interp->runDirCommand( _dirArg, _startMatch);
- if (ret == 0)
- _tabSuccess = true;
- else
- _tabSuccess = false;
-}
-
-/**
- * Create the event indicating the return value of the completion command.
- * @return
- */
-QEvent* CompletionCommand::createEvent()
-{
- int typ = _tabSuccess ? PyInterp_Event::ES_TAB_COMPLETE_OK : PyInterp_Event::ES_TAB_COMPLETE_ERR;
-
- return new PyInterp_Event( typ, this);
-}
-
-
-
+++ /dev/null
-
-
-
-#ifndef PYCONSOLE_REQUEST_H_
-#define PYCONSOLE_REQUEST_H_
-
-#include "PyConsole.h"
-#include "PyInterp_Request.h"
-
-#include <vector>
-#include <QString>
-#include <QEvent>
-
-class PyInterp_Interp;
-class PyConsole_Editor;
-
-/*!
- \class ExecCommand
- \brief Python command execution request.
- \internal
-*/
-class ExecCommand : public PyInterp_LockRequest
-{
-public:
- /*!
- \brief Constructor.
-
- Creates new python command execution request.
- \param theInterp python interpreter
- \param theCommand python command
- \param theListener widget to get the notification messages
- \param sync if True the request is processed synchronously
- */
- ExecCommand( PyInterp_Interp* theInterp,
- const QString& theCommand,
- PyConsole_Editor* theListener,
- bool sync = false );
-
-protected:
- /*!
- \brief Execute the python command in the interpreter and
- get its execution status.
- */
- virtual void execute();
-
- /*!
- \brief Create and return a notification event.
- \return new notification event
- */
- virtual QEvent* createEvent();
-
-private:
- QString myCommand; //!< Python command
- int myState; //!< Python command execution status
-};
-
-class PyConsole_EnhInterp;
-class PyConsole_EnhEditor;
-
-class CompletionCommand : public PyInterp_LockRequest
-{
-public:
- CompletionCommand( PyConsole_EnhInterp* theInterp,
- const QString& input,
- const QString& startMatch,
- PyConsole_EnhEditor* theListener,
- bool sync = false );
-
-
-protected:
- /** List of separators identifying the last parsable token for completion */
- static const std::vector<QString> SEPARATORS;
-
- /** String to be passed to the dir() command */
- QString _dirArg;
- /** Begining of the command (as typed by the user) */
- QString _startMatch;
- /** was the completion command successful */
- bool _tabSuccess;
-
- virtual void execute();
- virtual QEvent* createEvent();
-
-};
-
-#endif /* PYCONSOLE_REQUEST_H_ */
+++ /dev/null
-
-SET(PROJECT_HEADERS
- PyEvent.h
- PyEvent_Event.h
- PyEvent_EventFilter.h
-)
-
-SET(PROJECT_SOURCES
- PyEvent_Event.cpp
- PyEvent_EventFilter.cpp
-)
-
-#INCLUDE_DIRECTORIES(${Qt5Widgets_INCLUDES})
-
-ADD_DEFINITIONS(-DPYEVENT_EXPORTS)
-
-ADD_LIBRARY(PyEvent SHARED
- ${PROJECT_SOURCES}
- ${PROJECT_HEADERS}
-)
-
-TARGET_LINK_LIBRARIES(PyEvent ${QT_LIBRARIES})
-
-INSTALL(TARGETS PyEvent DESTINATION bin)
+++ /dev/null
-
-#if !defined ( PYEVENT_H )
-#define PYEVENT_H
-
-#ifdef WIN32
-# if defined PYEVENT_EXPORTS || defined PyEvent_EXPORTS
-# define PYEVENT_EXPORT __declspec(dllexport)
-# else
-# define PYEVENT_EXPORT __declspec(dllimport)
-# endif
-#else //WIN32
-# define PYEVENT_EXPORT
-#endif //WIN32
-
-#if defined WIN32
-#pragma warning ( disable: 4251 )
-#endif
-
-#endif // PYEVENT_H
+++ /dev/null
-
-#include "PyEvent_Event.h"
-
-#include <QSemaphore>
-#include <QApplication>
-
-// asv 21.02.05 : introducing multi-platform approach of thread comparison
-// - on Unix using pthread_t type for storing ThreadId
-// - on Win32 using integer type for storing ThreadId
-// NOT using integer ThreadId on both Unix and Win32 because (from documentation):
-// "...Do not allow your program to rely on the internal structure or size of the pthread_t..."
-
-#ifdef WIN32
-#include <windows.h>
-static DWORD myThread;
-#else
-#include <pthread.h>
-static pthread_t myThread;
-#endif
-
-/*!
- \class InitEvent
- \brief Helper event class responsible for initializing PyEvent_Event
- mechanism by the main thread ID
- */
-class InitEvent : public PyEvent_Event
-{
-public:
- InitEvent();
- virtual ~InitEvent();
- virtual void Execute();
-};
-
-/*!
- \brief Constructor, initializes the event mechanism by the current thread ID.
- It is asssumed to be the main thread ID, so be careful!
-*/
-InitEvent::InitEvent()
-{
- GetSessionThread();
-}
-
-/*!
- \brief Destructor, does nothing.
-*/
-InitEvent::~InitEvent()
-{
-}
-
-/*!
- \brief Nothing to be executed for this kind of event.
-*/
-void InitEvent::Execute()
-{
-}
-
-// NOTE: Here the SALOME event mechanism is initalized by the
-// current thread ID that is always assumed to be the main thread ID.
-// This should be revised as soon as the application library is no longer
-// linked against the Event library (i.e. this static object is not created or created
-// outside the main thread).
-static InitEvent myInitEvent;
-
-/*!
- \class PyEvent_CustomEvent
- \brief Generic event class for user-defined events
-
- This class contains a generic void* data member that may be used
- for transferring event-specific data to the receiver.
-
- \warning The internal data is not destroyed by the class destructor.
-*/
-
-/*!
- \brief Constructor.
- \param type event type
-*/
-PyEvent_CustomEvent::PyEvent_CustomEvent( int type )
-: QEvent( (QEvent::Type)type ), d( 0 )
-{
-}
-
-/*!
- \brief Constructor.
- \param type event type
- \param data custom data
-*/
-PyEvent_CustomEvent::PyEvent_CustomEvent( QEvent::Type type, void* data )
-: QEvent( type ), d( data )
-{
-}
-
-/*!
- \brief Get custom data.
- \return pointer to the internal data
-*/
-void* PyEvent_CustomEvent::data() const
-{
- return d;
-}
-
-/*!
- \brief Set custom data.
- \param data pointer to the internal data
-*/
-void PyEvent_CustomEvent::setData( void* data )
-{
- d = data;
-}
-
-/*!
- \class PyEvent_Event
- \brief The class which encapsulates data and functionality required for
- posting component-specific events to perform arbitrary operations
- in the main GUI thread.
-
- PyEvent_Event objects can be posted by any thread belonging to the GUI process.
-
- It is necessary to derive a custom event class from PyEvent_Event and
- re-implement virtual Execute() method. This method should actually perform
- the desirable operation. To pass all the required data to Execute() and
- store a return value, arbitrary data fields can be added to the custom
- event class. There is no need to protect such fields with a mutex, for only
- one thread working with a PyEvent_Event object is active at any moment.
-
- Usage:
- - Create PyEvent_Event. Components can derive their own event class from
- PyEvent_Event in order to pass custom data to the event handler.
- - Call process() method to post the event. After process() execution
- it is possible to examine fields of your custom event object.
- - Perform delete operator on the event to wake up the desktop (you can also
- set <autoRelease> parameter to \c true to automatically wake up desktop after
- process().
-
- The method processed() is used by the desktop to signal that event processing
- has been completed.
-
- To make all this work, it is necessary to call static method GetSessionThread()
- during the application initialization, i.e. from main() function.
- It is important to call this method from the primary application thread.
-
- Caveats:
- - there are no.
-*/
-
-//! Total number of semaphore resources
-const int NumberOfResources = 2;
-
-/*!
- \brief Initialize event mechanism.
-
- This function sets up the main application thread. It should be called
- during the application initialization, i.e. main() function.
-*/
-void PyEvent_Event::GetSessionThread(){
-#ifdef WIN32
- myThread = ::GetCurrentThreadId();
-#else
- myThread = pthread_self();
-#endif
-}
-
-/*!
- \brief Check if the processing is in the main application thread.
- \return \c true if this method is called from the main application thread
-*/
-bool PyEvent_Event::IsSessionThread(){
- bool aResult = false;
-#ifdef WIN32
- aResult = myThread == ::GetCurrentThreadId();
-#else
- aResult = myThread == pthread_self();
-#endif
- return aResult;
-}
-
-/*!
- \brief Constructor.
-*/
-PyEvent_Event::PyEvent_Event(){
- // Prepare the semaphore
- mySemaphore = new QSemaphore( NumberOfResources );
- mySemaphore->acquire( NumberOfResources );
-}
-
-/*!
- \brief Destructor.
-*/
-PyEvent_Event::~PyEvent_Event(){
- if ( mySemaphore->available() < NumberOfResources )
- mySemaphore->release( NumberOfResources - mySemaphore->available() );
- delete mySemaphore;
-}
-
-/*!
- \brief This method should be called by the main GUI thread
- in order to execute the code specific for this event and finally
- to inform the calling thread that the event
- has been processed waking it up with help of the semaphore .
- */
-void PyEvent_Event::ExecutePostedEvent()
-{
- // Diagnose incorrect usage of PyEvent_Event API
- if ( !IsSessionThread() ){
- qWarning( "PyEvent_Event::ExecutePostedEvent() is called from a secondary thread that might mean an error in application logic!" );
- }
- // Actual execution specific for particular kind of event
- Execute();
- // Signal the calling thread that the event has been processed
- processed();
-}
-
-/*!
- \brief Post the event and wait for its completion.
- process() should be called from a secondary thread only.
- \sa processed()
-*/
-void PyEvent_Event::process()
-{
- // Diagnose incorrect usage of PyEvent_Event API
- if ( IsSessionThread() ){
- qWarning( "PyEvent_Event::process() is called from the main GUI thread that might mean an error in application logic!" );
- }
-
- QApplication::postEvent( qApp, new PyEvent_CustomEvent( PyEvent_EVENT, (void*)this ) );
- mySemaphore->acquire( 1 );
-}
-
-/*!
- \brief Use this method to signal that this event has been processed.
-*/
-void PyEvent_Event::processed()
-{
- mySemaphore->release( 1 );
-}
-
-/*!
- \fn virtual void PyEvent_Event::Execute();
- \brief This method should be redefined in the successor classes
- to do real work.
-*/
-
-/*!
- \class TMemFunEvent
- \brief Template class for event which calls the function
- without arguments and returning result.
-*/
-
-/*!
- \class TVoidMemFunEvent
- \brief Template class for event which calls the function
- without arguments and without return value.
-*/
-
-/*!
- \class TMemFun1ArgEvent
- \brief Template class for event which calls the function
- with one argument and returning result.
-*/
-
-/*!
- \class TVoidMemFun1ArgEvent
- \brief Template class for event which calls the function
- with one argument and without return value.
-*/
-
-/*!
- \class TMemFun2ArgEvent
- \brief Template class for event which calls the function
- with two arguments and returning result.
-*/
-
-/*!
- \class TVoidMemFun2ArgEvent
- \brief Template class for event which calls the function
- with two arguments and without return value.
-*/
-
-/*!
- \fn ProcessEvent
- \brief Template function for processing events with return value.
-*/
-
-/*!
- \fn ProcessVoidEvent
- \brief Template function for processing events without return value.
-*/
+++ /dev/null
-
-#ifndef PyEvent_PYEVENT_H
-#define PyEvent_PYEVENT_H
-
-#include "PyEvent.h"
-
-#include <QEvent>
-
-//! SALOME custom event type
-#define PyEvent_EVENT QEvent::Type( QEvent::User + 10000 )
-
-class PYEVENT_EXPORT PyEvent_CustomEvent : public QEvent
-{
-public:
- PyEvent_CustomEvent( int type );
- PyEvent_CustomEvent( QEvent::Type type, void* data );
-
- void* data() const;
- void setData( void* data );
-
-private:
- void *d; //!< internal data
-};
-
-class QSemaphore;
-
-class PYEVENT_EXPORT PyEvent_Event
-{
-public:
- PyEvent_Event();
- virtual ~PyEvent_Event();
-
- void ExecutePostedEvent();
- virtual void Execute() = 0;
-
- static bool IsSessionThread();
- void process();
-
-protected:
- void processed();
- static void GetSessionThread();
-
-private:
- QSemaphore* mySemaphore; //!< internal semaphore
-};
-
-template<class TObject, typename TRes> class TMemFunEvent : public PyEvent_Event
-{
-public:
- typedef TRes TResult;
- TResult myResult;
- typedef TResult (TObject::* TAction)();
- TMemFunEvent(TObject* theObject, TAction theAction,
- TResult theResult = TResult()):
- myObject(theObject),
- myAction(theAction),
- myResult(theResult)
- {}
- virtual void Execute()
- {
- myResult = (myObject->*myAction)();
- }
-private:
- TObject* myObject;
- TAction myAction;
-};
-
-template<class TObject> class TVoidMemFunEvent : public PyEvent_Event
-{
-public:
- typedef void (TObject::* TAction)();
- TVoidMemFunEvent(TObject* theObject, TAction theAction):
- myObject(theObject),
- myAction(theAction)
- {}
- virtual void Execute()
- {
- (myObject->*myAction)();
- }
-private:
- TObject* myObject;
- TAction myAction;
-};
-
-template<class TObject, typename TRes, typename TArg, typename TStoreArg = TArg>
-class TMemFun1ArgEvent : public PyEvent_Event
-{
-public:
- typedef TRes TResult;
- TResult myResult;
- typedef TResult (TObject::* TAction)(TArg);
- TMemFun1ArgEvent(TObject* theObject, TAction theAction, TArg theArg,
- TResult theResult = TResult()):
- myObject(theObject),
- myAction(theAction),
- myResult(theResult),
- myArg(theArg)
- {}
- virtual void Execute()
- {
- myResult = (myObject->*myAction)(myArg);
- }
-private:
- TObject* myObject;
- TAction myAction;
- TStoreArg myArg;
-};
-
-template<class TObject, typename TArg, typename TStoreArg = TArg>
-class TVoidMemFun1ArgEvent : public PyEvent_Event
-{
-public:
- typedef void (TObject::* TAction)(TArg);
- TVoidMemFun1ArgEvent(TObject* theObject, TAction theAction, TArg theArg):
- myObject(theObject),
- myAction(theAction),
- myArg(theArg)
- {}
- virtual void Execute()
- {
- (myObject->*myAction)(myArg);
- }
-private:
- TObject* myObject;
- TAction myAction;
- TStoreArg myArg;
-};
-
-template<class TObject, typename TRes, typename TArg, typename TArg1, typename TStoreArg = TArg, typename TStoreArg1 = TArg1>
-class TMemFun2ArgEvent: public PyEvent_Event
-{
-public:
- typedef TRes TResult;
- TResult myResult;
- typedef TResult (TObject::* TAction)(TArg,TArg1);
- TMemFun2ArgEvent(TObject* theObject, TAction theAction,
- TArg theArg, TArg1 theArg1,
- TResult theResult = TResult()):
- myObject(theObject),
- myAction(theAction),
- myResult(theResult),
- myArg(theArg),
- myArg1(theArg1)
- {}
- virtual void Execute()
- {
- myResult = (myObject->*myAction)(myArg,myArg1);
- }
-private:
- TObject* myObject;
- TAction myAction;
- TStoreArg myArg;
- TStoreArg1 myArg1;
-};
-
-template<class TObject, typename TArg, typename TArg1, typename TStoreArg = TArg, typename TStoreArg1 = TArg1>
-class TVoidMemFun2ArgEvent : public PyEvent_Event
-{
-public:
- typedef void (TObject::* TAction)(TArg,TArg1);
- TVoidMemFun2ArgEvent(TObject* theObject, TAction theAction, TArg theArg, TArg1 theArg1):
- myObject(theObject),
- myAction(theAction),
- myArg(theArg),
- myArg1(theArg1)
- {}
- virtual void Execute()
- {
- (myObject->*myAction)(myArg,myArg1);
- }
-private:
- TObject* myObject;
- TAction myAction;
- TStoreArg myArg;
- TStoreArg1 myArg1;
-};
-
-template<class TEvent> inline typename TEvent::TResult ProcessEvent(TEvent* theEvent)
-{
- typename TEvent::TResult aResult;
- if(PyEvent_Event::IsSessionThread()) {
- theEvent->Execute();
- aResult = theEvent->myResult;
- }
- else {
- theEvent->process();
- aResult = theEvent->myResult;
- }
- delete theEvent;
- return aResult;
-}
-
-inline void ProcessVoidEvent(PyEvent_Event* theEvent)
-{
- if(PyEvent_Event::IsSessionThread()) {
- theEvent->Execute();
- }
- else {
- theEvent->process();
- }
- delete theEvent;
-}
-
-#endif // PyEvent_PYEVENT_H
+++ /dev/null
-
-#include "PyEvent_EventFilter.h"
-#include "PyEvent_Event.h"
-
-#include <QApplication>
-
-PyEvent_EventFilter* PyEvent_EventFilter::myFilter = NULL;
-
-/*!Constructor.*/
-PyEvent_EventFilter::PyEvent_EventFilter()
-: QObject()
-{
- /* VSR 13/01/03 : installing global event filter for the application */
- qApp->installEventFilter( this );
-}
-
-/*!Destructor.*/
-PyEvent_EventFilter::~PyEvent_EventFilter()
-{
- qApp->removeEventFilter( this );
-}
-
-/*!
- Custom event filter
-*/
-bool PyEvent_EventFilter::eventFilter( QObject* o, QEvent* e )
-{
- if ( e->type() == PyEvent_EVENT )
- {
- PyEvent_Event* aSE = (PyEvent_Event*)((PyEvent_CustomEvent*)e)->data();
- processEvent(aSE);
- ((PyEvent_CustomEvent*)e)->setData( 0 );
- return true;
- }
- return QObject::eventFilter( o, e );
-}
-
-/*!Process event.*/
-void PyEvent_EventFilter::processEvent( PyEvent_Event* theEvent )
-{
- if(theEvent)
- theEvent->ExecutePostedEvent();
-}
-
-/*!Create new instance of PyEvent_EventFilter*/
-void PyEvent_EventFilter::Init()
-{
- if( myFilter==NULL )
- myFilter = new PyEvent_EventFilter();
-}
-
-/*!Destroy filter.*/
-void PyEvent_EventFilter::Destroy()
-{
- if( myFilter )
- {
- delete myFilter;
- myFilter = NULL;
- }
-}
+++ /dev/null
-
-#ifndef PyEvent_EVENTFILTER_H
-#define PyEvent_EVENTFILTER_H
-
-#include "PyEvent.h"
-#include <QObject>
-
-#if defined WIN32
-#pragma warning( disable: 4251 )
-#endif
-
-class PyEvent_Event;
-
-/*!
- Event filter class for QApplication object that handles custom events posted by PyEvent_Event objects.
- It assumes that such custom events are alwys posted, not sent.
- This event filter can be installed by any application that intends to use PyEvent_Event mechanism asynchronously.
- This class replaced SalomeApp_EventFilter.
-*/
-class PYEVENT_EXPORT PyEvent_EventFilter: public QObject
-{
-public:
- static void Init();
- static void Destroy();
-
-protected:
- PyEvent_EventFilter();
- virtual ~PyEvent_EventFilter();
-
-private:
- /*! global event filter for qapplication */
- virtual bool eventFilter( QObject* o, QEvent* e );
- void processEvent( PyEvent_Event* );
-
-private:
- static PyEvent_EventFilter* myFilter;
-};
-
-#if defined WIN32
-#pragma warning( default: 4251 )
-#endif
-
-#endif
+++ /dev/null
-
-SET(CMAKE_AUTOMOC ON)
-
-# header files
-SET(PROJECT_HEADERS
- PyInterp.h
- PyInterp_Dispatcher.h
- PyInterp_Event.h
- PyInterp_Interp.h
- PyInterp_Request.h
- PyInterp_Watcher.h
-)
-
-SET(PROJECT_AUTOMOC
- ${CMAKE_CURRENT_BINARY_DIR}/PyInterp_automoc.cpp
-)
-
-# sources / static
-SET(PROJECT_SOURCES
- PyInterp_Dispatcher.cpp
- PyInterp_Event.cpp
- PyInterp_Interp.cpp
- PyInterp_Request.cpp
-)
-
-SET(PROJECT_LIBRARIES
- PyEvent
- ${QT_LIBRARIES}
- ${PYTHON_LIBRARIES}
-)
-
-SOURCE_GROUP ("Generated Files" FILES ${PROJECT_AUTOMOC})
-
-ADD_DEFINITIONS(-DPYINTERP_EXPORTS -DHAVE_DEBUG_PYTHON)
-
-INCLUDE_DIRECTORIES(
- ${PROJECT_SOURCE_DIR}/src/PyEvent
-)
-
-ADD_LIBRARY(PyInterp SHARED
- ${PROJECT_SOURCES}
- ${PROJECT_HEADERS}
-)
-
-TARGET_LINK_LIBRARIES(PyInterp ${PROJECT_LIBRARIES})
-
-INSTALL(TARGETS PyInterp DESTINATION bin)
+++ /dev/null
-
-#if !defined ( PYINTERP_H )
-#define PYINTERP_H
-
-// ========================================================
-// set dllexport type for Win platform
-#ifdef WIN32
-# if defined PYINTERP_EXPORTS || defined PyInterp_EXPORTS
-# define PYINTERP_EXPORT __declspec(dllexport)
-# else
-# define PYINTERP_EXPORT __declspec(dllimport)
-# endif
-#else // WIN32
-# define PYINTERP_EXPORT
-#endif // WIN32
-
-// ========================================================
-// little trick - if we do not have debug python libraries
-#ifdef _DEBUG
- #ifndef HAVE_DEBUG_PYTHON
- #undef _DEBUG
- #endif
-#endif
-
-#include <Python.h>
-
-#ifdef _DEBUG
- #ifndef HAVE_DEBUG_PYTHON
- #define _DEBUG
- #endif
-#endif
-
-// ========================================================
-// avoid warning messages
-#ifdef WIN32
-#pragma warning (disable : 4786)
-#pragma warning (disable : 4251)
-#endif
-
-#endif // PYINTERP_H
+++ /dev/null
-
-#include "PyInterp_Dispatcher.h" // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!!
-#include "PyInterp_Interp.h"
-#include "PyInterp_Watcher.h"
-#include "PyInterp_Request.h"
-
-#include <QObject>
-#include <QCoreApplication>
-
-PyInterp_Dispatcher* PyInterp_Dispatcher::myInstance = 0;
-
-void PyInterp_Request::process()
-{
- safeExecute();
-
- bool isSync = IsSync();
-
- if ( !isSync )
- myMutex.lock();
-
- if ( listener() )
- processEvent( listener() );
-
- if ( !isSync )
- myMutex.unlock();
-}
-
-void PyInterp_Request::safeExecute()
-{
- //ProcessVoidEvent( new PyInterp_ExecuteEvent( this ) );
- execute();
-}
-
-void PyInterp_Request::Destroy( PyInterp_Request* request )
-{
- // Lock and unlock the mutex to avoid errors on its deletion
- request->myMutex.lock();
- request->myMutex.unlock();
- delete request;
-}
-
-QEvent* PyInterp_Request::createEvent()
-{
- return new PyInterp_Event( PyInterp_Event::ES_NOTIFY, this );
-}
-
-void PyInterp_Request::processEvent( QObject* o )
-{
- if ( !o )
- return;
-
- QEvent* e = createEvent();
- if ( !e )
- return;
-
- if ( !IsSync() )
- QCoreApplication::postEvent( o, e );
- else
- {
- QCoreApplication::sendEvent( o, e );
- delete e;
- }
-}
-
-void PyInterp_Request::setListener( QObject* o )
-{
- myMutex.lock();
- myListener = o;
- myMutex.unlock();
-}
-
-void PyInterp_LockRequest::safeExecute()
-{
- if ( getInterp() ){
- PyLockWrapper aLock = getInterp()->GetLockWrapper();
- //ProcessVoidEvent( new PyInterp_ExecuteEvent( this ) );
- execute();
- }
-}
-
-PyInterp_Event::~PyInterp_Event()
-{
- PyInterp_Request::Destroy( myRequest );
- myRequest = 0;
-}
-
-PyInterp_Dispatcher* PyInterp_Dispatcher::Get()
-{
- if ( !myInstance )
- myInstance = new PyInterp_Dispatcher();
- return myInstance;
-}
-
-PyInterp_Dispatcher::PyInterp_Dispatcher()
-: QThread()
-{
- myWatcher = new PyInterp_Watcher();
-}
-
-PyInterp_Dispatcher::~PyInterp_Dispatcher()
-{
- // Clear the request queue
- myQueueMutex.lock();
-
- QListIterator<RequestPtr> it( myQueue );
- while ( it.hasNext() )
- PyInterp_Request::Destroy( it.next() );
- myQueue.clear();
-
- myQueueMutex.unlock();
-
- // Wait for run() to finish
- wait();
-
- delete myWatcher;
- myWatcher = 0;
-}
-
-bool PyInterp_Dispatcher::IsBusy() const
-{
- return isRunning();
-}
-
-void PyInterp_Dispatcher::Exec( PyInterp_Request* theRequest )
-{
- if ( !theRequest )
- return;
-
- //if ( theRequest->IsSync() && !IsBusy() ) // synchronous processing - nothing is done if dispatcher is busy!
- if ( theRequest->IsSync() ) // synchronous processing
- processRequest( theRequest );
- else // asynchronous processing
- {
- myQueueMutex.lock();
- myQueue.enqueue( theRequest );
- if ( theRequest->listener() )
- QObject::connect( theRequest->listener(), SIGNAL( destroyed( QObject* ) ), myWatcher, SLOT( onDestroyed( QObject* ) ) );
- myQueueMutex.unlock();
-
- if ( !IsBusy() )
- start();
- }
-}
-
-void PyInterp_Dispatcher::run()
-{
-// MESSAGE("*** PyInterp_Dispatcher::run(): STARTED")
- PyInterp_Request* aRequest;
-
- // prepare for queue size check
- myQueueMutex.lock();
-
- while( myQueue.size() ) {
-// MESSAGE("*** PyInterp_Dispatcher::run(): next request taken from the queue")
- aRequest = myQueue.head();
-
- // let other threads append their requests to the end of the queue
- myQueueMutex.unlock();
-
- // processRequest() may delete a request, so this pointer must not be used
- // after request is processed!
- processRequest( aRequest );
-
- // 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.head() == aRequest ) // It's still here --> remove it
- myQueue.dequeue();
-
-// MESSAGE("*** PyInterp_Dispatcher::run(): request processed")
- }
-
- myQueueMutex.unlock();
-// MESSAGE("*** PyInterp_Dispatcher::run(): FINISHED")
-}
-
-void PyInterp_Dispatcher::processRequest( PyInterp_Request* theRequest )
-{
- theRequest->process();
-}
-
-void PyInterp_Dispatcher::objectDestroyed( const QObject* o )
-{
- // prepare for modification of the queue
- myQueueMutex.lock();
-
- QMutableListIterator<RequestPtr> it( myQueue );
- while ( it.hasNext() )
- {
- RequestPtr r = it.next();
- if ( o == r->listener() )
- {
- r->setListener( 0 ); // to prevent event posting
- it.remove();
- }
- }
-
- myQueueMutex.unlock();
-}
+++ /dev/null
-
-#ifndef PYINTERP_DISPATCHER_H
-#define PYINTERP_DISPATCHER_H
-
-#include "PyInterp.h" // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!!
-
-#include "PyInterp_Request.h" // full include instead of forward declaration
- // everyone inc'ing the Dispatcher will get the requests for free.
-
-#include <QMutex>
-#include <QThread>
-#include <QQueue>
-
-class QObject;
-class PyInterp_Watcher;
-
-class PYINTERP_EXPORT PyInterp_Dispatcher : protected QThread
-{
- PyInterp_Dispatcher(); // private constructor
-
-public:
- static PyInterp_Dispatcher* Get();
-
- virtual ~PyInterp_Dispatcher();
-
- bool IsBusy() const;
- void Exec( PyInterp_Request* );
-
-private:
- virtual void run();
- void processRequest( PyInterp_Request* );
- void objectDestroyed( const QObject* );
-
-private:
- typedef PyInterp_Request* RequestPtr;
-
- QQueue<RequestPtr> myQueue;
- QMutex myQueueMutex;
- PyInterp_Watcher* myWatcher;
-
- static PyInterp_Dispatcher* myInstance;
-
- friend class PyInterp_Watcher;
-};
-
-#endif // PYINTERP_DISPATCHER_H
+++ /dev/null
-
-
-#include "PyInterp_Event.h"
-#include "PyInterp_Request.h"
-
-void PyInterp_ExecuteEvent::Execute()
-{
- myRequest->execute();
-}
+++ /dev/null
-
-
-#ifndef PYINTERP_EVENT_H
-#define PYINTERP_EVENT_H
-
-#include "PyInterp.h"
-
-#include <PyEvent_Event.h>
-
-#include <QEvent>
-
-class PyInterp_Request;
-
-class PyInterp_ExecuteEvent: public PyEvent_Event
-{
-public:
- PyInterp_ExecuteEvent( PyInterp_Request* r )
- : myRequest( r ) {}
-
- virtual void Execute();
-
-protected:
- PyInterp_Request* myRequest;
-};
-
-/**
- * Events thrown by the interpreter having executed a command and indicating
- * the return status.
- */
-//
-class PYINTERP_EXPORT PyInterp_Event : public QEvent
-{
- PyInterp_Event();
- PyInterp_Event( const PyInterp_Event& );
-
-public:
- //Execution state
- enum { ES_NOTIFY = QEvent::User + 5000, ES_OK, ES_ERROR, ES_INCOMPLETE,
- ES_TAB_COMPLETE_OK, ES_TAB_COMPLETE_ERR, ES_LAST };
-
- PyInterp_Event( int type, PyInterp_Request* request )
- : QEvent( (QEvent::Type)type ), myRequest( request ) {}
-
- virtual ~PyInterp_Event();
-
- PyInterp_Request* GetRequest() const { return myRequest; }
- operator PyInterp_Request*() const { return myRequest; }
-
-private:
- PyInterp_Request* myRequest;
-};
-
-#endif // PYINTERP_EVENT_H
+++ /dev/null
-
-#include "PyInterp_Interp.h" // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!!
-#include <pythread.h>
-
-#include <cStringIO.h>
-#include <structmember.h>
-
-#include <string>
-#include <vector>
-#include <map>
-#include <iostream>
-#include <algorithm>
-
-#define TOP_HISTORY_PY "--- top of history ---"
-#define BEGIN_HISTORY_PY "--- begin of history ---"
-
-// a map to store python thread states that have been created for a given system thread (key=thread id,value=thread state)
-std::map<long,PyThreadState*> currentThreadMap;
-
-/*!
- \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 Destructor. 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()
-{
- if (_tstate->interp == PyInterp_Interp::_interp)
- return _tstate;
-
- // If we are here, we have a secondary python interpreter. Try to get a thread state synchronized with the system thread
- long currentThreadid=PyThread_get_thread_ident(); // the system thread id
- PyThreadState* theThreadState;
- if(currentThreadMap.count(currentThreadid) != 0)
- {
- //a thread state exists for this thread id
- PyThreadState* oldThreadState=currentThreadMap[currentThreadid];
- if(_tstate->interp ==oldThreadState->interp)
- {
- //The old thread state has the same python interpreter as this one : reuse the threadstate
- theThreadState=oldThreadState;
- }
- else
- {
- //The old thread state has not the same python interpreter as this one : delete the old threadstate and create a new one
- PyEval_AcquireLock();
- PyThreadState_Clear(oldThreadState);
- PyThreadState_Delete(oldThreadState);
- PyEval_ReleaseLock();
- theThreadState=PyThreadState_New(_tstate->interp);
- currentThreadMap[currentThreadid]=theThreadState;
- }
- }
- else
- {
- // no old thread state for this thread id : create a new one
- theThreadState=PyThreadState_New(_tstate->interp);
- currentThreadMap[currentThreadid]=theThreadState;
- }
- return theThreadState;
-}
-
-/*
- 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 PyObject*
-PyStdOut_flush(PyStdOut *self)
-{
- Py_INCREF(Py_None);
- return Py_None;
-}
-
-static PyMethodDef PyStdOut_methods[] = {
- {"write", (PyCFunction)PyStdOut_write, METH_VARARGS, PyDoc_STR("write(string) -> None")},
- {"flush", (PyCFunction)PyStdOut_flush, METH_NOARGS, PyDoc_STR("flush() -> None")},
- {NULL, NULL} /* sentinel */
-};
-
-static PyMemberDef PyStdOut_memberlist[] = {
- {(char*)"softspace", T_INT, offsetof(PyStdOut, softspace), 0,
- (char*)"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[] = {(char*)""};
-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();
-
- PyEval_AcquireThread(_tstate);
-
- initContext();
-
- // used to interpret & compile commands
- PyObjWrapper m(PyImport_ImportModule("codeop"));
- if(!m) {
- PyErr_Print();
- PyEval_ReleaseThread(_tstate);
- 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();
- PyEval_ReleaseThread(_tstate);
-}
-
-/*!
- \brief Initialize Python interpreter.
-
- In case if Python is not initialized, it sets program name, initializes the interpreter, sets program arguments,
- initializes threads.
- Otherwise, it just obtains the global interpreter and thread states. This is important for light SALOME configuration,
- as in full SALOME this is done at SalomeApp level.
- \sa SalomeApp_PyInterp class
- */
-void PyInterp_Interp::initPython()
-{
- if (!Py_IsInitialized()){
- // 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
- }
-
- if ( _interp == NULL )
- _interp = PyThreadState_Get()->interp;
- if (PyType_Ready(&PyStdOut_Type) < 0) {
- PyErr_Print();
- }
- if ( _gtstate == NULL )
- _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 run_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,(char*)"compile_command",(char*)"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;
- }
-}
-
-void replaceAll(std::string& str, const std::string& from, const std::string& to) {
- if(from.empty())
- return;
- size_t start_pos = 0;
- while((start_pos = str.find(from, start_pos)) != std::string::npos) {
- str.replace(start_pos, from.length(), to);
- start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx'
- }
-}
-/*!
- \brief Compile Python command and evaluate it in the
- python dictionary context if possible. Command might correspond to
- the execution of a script with optional arguments.
- In this case, command is:
- execfile(r"/absolute/path/to/script.py [args:arg1,...,argn]")
- \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)
-{
- // First guess if command is execution of a script with args, or a simple Python command
- std::string singleCommand = command;
- std::string commandArgs = "";
-
- std::size_t pos = std::string(command).find("args:");
- if (pos != std::string::npos) {
- commandArgs = singleCommand.substr(pos+5);
- commandArgs = commandArgs.substr(0, commandArgs.length()-3);
- singleCommand = singleCommand.substr(0, pos-1)+"\")";
- }
-
- if (commandArgs.empty()) {
- // process command: expression
- // process command: execfile(r"/absolute/path/to/script.py") (no args)
- return run_command(singleCommand.c_str(), context);
- }
- else {
- // process command: execfile(r"/absolute/path/to/script.py [args:arg1,...,argn]")
- std::string script = singleCommand.substr(11); // remove leading execfile(r"
- script = script.substr(0, script.length()-2); // remove trailing ")
-
- std::string preCommandBegin = "import sys; save_argv = sys.argv; sys.argv=[";
- std::string preCommandEnd = "];";
- replaceAll(commandArgs, ",", "\",\"");
- commandArgs = "\""+commandArgs+"\"";
- std::string completeCommand = preCommandBegin+"\""+script+"\","+commandArgs+preCommandEnd+singleCommand+";sys.argv=save_argv";
- return run_command(completeCommand.c_str(), context);
- }
-}
-
-/*!
- \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((char*)"stderr",_verr);
- PySys_SetObject((char*)"stdout",_vout);
-
- int ier = compile_command(command,_g);
-
- // Outputs are redirected on standards outputs (console)
- PySys_SetObject((char*)"stdout",PySys_GetObject((char*)"__stdout__"));
- PySys_SetObject((char*)"stderr",PySys_GetObject((char*)"__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;
-}
+++ /dev/null
-
-#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
+++ /dev/null
-
-
-#include "PyInterp_Request.h"
-
+++ /dev/null
-
-
-#ifndef PYINTERP_REQUEST_H
-#define PYINTERP_REQUEST_H
-
-#include "PyInterp.h"
-#include "PyInterp_Event.h"
-
-#include <QMutex>
-#include <QObject>
-
-class PyInterp_Interp;
-class PyInterp_Watcher;
-class PyInterp_Dispatcher;
-class PyInterp_ExecuteEvent;
-class PyConsole_Editor;
-
-class PYINTERP_EXPORT PyInterp_Request
-{
- friend class PyInterp_Dispatcher;
- friend class PyInterp_ExecuteEvent;
-
- PyInterp_Request();
- PyInterp_Request( const PyInterp_Request& );
-
-protected:
- virtual ~PyInterp_Request() {};
- // protected destructor - to control deletion of requests
-
-public:
- PyInterp_Request( QObject* listener, bool sync = false )
- : myIsSync( sync ), myListener( listener ) {};
-
- static void Destroy( PyInterp_Request* );
- // Deletes a request
-
- bool IsSync() const { return myIsSync; }
- // Returns true if this request should be processed synchronously,
- // without putting it to a queue
-
-protected:
- virtual void safeExecute();
-
- virtual void execute() = 0;
- // Should be redefined in successors, contains actual request code
-
- virtual QEvent* createEvent();
- // This method can be overridden to customize notification event creation
-
- virtual void processEvent( QObject* );
-
- QObject* listener() const { return myListener; }
- void setListener( QObject* );
-
-private:
- void process();
-
-private:
- QMutex myMutex;
- bool myIsSync;
- QObject* myListener;
-};
-
-class PYINTERP_EXPORT PyInterp_LockRequest : public PyInterp_Request
-{
-public:
-
- PyInterp_LockRequest( PyInterp_Interp* interp, QObject* listener = 0, bool sync = false )
- : PyInterp_Request( listener, sync ), myInterp( interp )
- {}
-
-protected:
- PyInterp_Interp* getInterp() const { return myInterp; }
-
- virtual void safeExecute();
-
-private:
- PyInterp_Interp* myInterp;
-};
-
-#endif // PYINTERP_REQUEST_H
+++ /dev/null
-
-#ifndef PYINTERP_WATCHER_H
-#define PYINTERP_WATCHER_H
-
-#include "PyInterp.h" // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!!
-
-#include "PyInterp_Dispatcher.h"
-
-#include <QObject>
-
-// Private class that keeps track of destructions of request listeners
-class PYINTERP_EXPORT PyInterp_Watcher : public QObject
-{
- Q_OBJECT
-
-public:
- PyInterp_Watcher() : QObject( 0 ) {}
- virtual ~PyInterp_Watcher() {}
-
-public slots:
- void onDestroyed( QObject* o ) { PyInterp_Dispatcher::Get()->objectDestroyed( o ); }
-};
-
-#endif // PYINTERP_WATCHER_H
${QT_LIBRARIES}
${CAS_VIEWER}
${CAS_KERNEL}
- PyConsole
- PyInterp
- PyEvent
+ ${PyConsole}
+ ${PyInterp}
ModelAPI
ModuleBase
)
INCLUDE_DIRECTORIES (${PROJECT_SOURCE_DIR}/src/Events
${PROJECT_SOURCE_DIR}/src/Config
- ${PROJECT_SOURCE_DIR}/src/PyInterp
- ${PROJECT_SOURCE_DIR}/src/PyConsole
${PROJECT_SOURCE_DIR}/src/ModelAPI
${PROJECT_SOURCE_DIR}/src/GeomAPI
${PROJECT_SOURCE_DIR}/src/ModuleBase
${PROJECT_SOURCE_DIR}/src/PartSetPlugin
- ${CAS_INCLUDE_DIRS})
+ ${CAS_INCLUDE_DIRS}
+ ${SUIT_INCLUDE})
LINK_DIRECTORIES($ENV{PYTHON_LIB_DIR})