From 34a92fc418be76c4fb5fa5a442d6725f38d9503e Mon Sep 17 00:00:00 2001 From: vsv Date: Fri, 1 Aug 2014 12:26:47 +0400 Subject: [PATCH] Reusing SUIT libraries --- CMakeCommon/FindSUIT.cmake | 14 + CMakeCommon/FindSalome.cmake | 1 + CMakeLists.txt | 7 +- msvc10_env.bat | 7 + src/PyConsole/CMakeLists.txt | 70 -- src/PyConsole/PyConsole.h | 24 - src/PyConsole/PyConsole_Console.cpp | 341 -------- src/PyConsole/PyConsole_Console.h | 89 -- src/PyConsole/PyConsole_Editor.cpp | 1105 ------------------------- src/PyConsole/PyConsole_Editor.h | 72 -- src/PyConsole/PyConsole_EnhEditor.cpp | 464 ----------- src/PyConsole/PyConsole_EnhEditor.h | 78 -- src/PyConsole/PyConsole_EnhInterp.cpp | 135 --- src/PyConsole/PyConsole_EnhInterp.h | 47 -- src/PyConsole/PyConsole_Event.cpp | 3 - src/PyConsole/PyConsole_Event.h | 48 -- src/PyConsole/PyConsole_Interp.cpp | 118 --- src/PyConsole/PyConsole_Interp.h | 20 - src/PyConsole/PyConsole_Request.cpp | 99 --- src/PyConsole/PyConsole_Request.h | 86 -- src/PyEvent/CMakeLists.txt | 24 - src/PyEvent/PyEvent.h | 19 - src/PyEvent/PyEvent_Event.cpp | 287 ------- src/PyEvent/PyEvent_Event.h | 204 ----- src/PyEvent/PyEvent_EventFilter.cpp | 60 -- src/PyEvent/PyEvent_EventFilter.h | 43 - src/PyInterp/CMakeLists.txt | 47 -- src/PyInterp/PyInterp.h | 40 - src/PyInterp/PyInterp_Dispatcher.cpp | 199 ----- src/PyInterp/PyInterp_Dispatcher.h | 46 - src/PyInterp/PyInterp_Event.cpp | 9 - src/PyInterp/PyInterp_Event.h | 53 -- src/PyInterp/PyInterp_Interp.cpp | 533 ------------ src/PyInterp/PyInterp_Interp.h | 95 --- src/PyInterp/PyInterp_Request.cpp | 4 - src/PyInterp/PyInterp_Request.h | 81 -- src/PyInterp/PyInterp_Watcher.h | 24 - src/XGUI/CMakeLists.txt | 10 +- 38 files changed, 30 insertions(+), 4576 deletions(-) create mode 100644 CMakeCommon/FindSUIT.cmake delete mode 100644 src/PyConsole/CMakeLists.txt delete mode 100644 src/PyConsole/PyConsole.h delete mode 100644 src/PyConsole/PyConsole_Console.cpp delete mode 100644 src/PyConsole/PyConsole_Console.h delete mode 100644 src/PyConsole/PyConsole_Editor.cpp delete mode 100644 src/PyConsole/PyConsole_Editor.h delete mode 100644 src/PyConsole/PyConsole_EnhEditor.cpp delete mode 100644 src/PyConsole/PyConsole_EnhEditor.h delete mode 100644 src/PyConsole/PyConsole_EnhInterp.cpp delete mode 100644 src/PyConsole/PyConsole_EnhInterp.h delete mode 100644 src/PyConsole/PyConsole_Event.cpp delete mode 100644 src/PyConsole/PyConsole_Event.h delete mode 100644 src/PyConsole/PyConsole_Interp.cpp delete mode 100644 src/PyConsole/PyConsole_Interp.h delete mode 100644 src/PyConsole/PyConsole_Request.cpp delete mode 100644 src/PyConsole/PyConsole_Request.h delete mode 100644 src/PyEvent/CMakeLists.txt delete mode 100644 src/PyEvent/PyEvent.h delete mode 100644 src/PyEvent/PyEvent_Event.cpp delete mode 100644 src/PyEvent/PyEvent_Event.h delete mode 100644 src/PyEvent/PyEvent_EventFilter.cpp delete mode 100644 src/PyEvent/PyEvent_EventFilter.h delete mode 100644 src/PyInterp/CMakeLists.txt delete mode 100644 src/PyInterp/PyInterp.h delete mode 100644 src/PyInterp/PyInterp_Dispatcher.cpp delete mode 100644 src/PyInterp/PyInterp_Dispatcher.h delete mode 100644 src/PyInterp/PyInterp_Event.cpp delete mode 100644 src/PyInterp/PyInterp_Event.h delete mode 100644 src/PyInterp/PyInterp_Interp.cpp delete mode 100644 src/PyInterp/PyInterp_Interp.h delete mode 100644 src/PyInterp/PyInterp_Request.cpp delete mode 100644 src/PyInterp/PyInterp_Request.h delete mode 100644 src/PyInterp/PyInterp_Watcher.h diff --git a/CMakeCommon/FindSUIT.cmake b/CMakeCommon/FindSUIT.cmake new file mode 100644 index 000000000..54940d7d4 --- /dev/null +++ b/CMakeCommon/FindSUIT.cmake @@ -0,0 +1,14 @@ + +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}) diff --git a/CMakeCommon/FindSalome.cmake b/CMakeCommon/FindSalome.cmake index 5b4ba143f..114b1e745 100644 --- a/CMakeCommon/FindSalome.cmake +++ b/CMakeCommon/FindSalome.cmake @@ -2,6 +2,7 @@ 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) diff --git a/CMakeLists.txt b/CMakeLists.txt index b4b8c4783..de2256284 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,10 @@ INCLUDE(FindSalome) 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 @@ -53,9 +57,6 @@ ADD_SUBDIRECTORY (src/SketchPlugin) 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) diff --git a/msvc10_env.bat b/msvc10_env.bat index ab394bec9..064ec4e30 100644 --- a/msvc10_env.bat +++ b/msvc10_env.bat @@ -135,6 +135,13 @@ set PATH=%CMAKEDIR%\bin;%PATH% @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 diff --git a/src/PyConsole/CMakeLists.txt b/src/PyConsole/CMakeLists.txt deleted file mode 100644 index aa79a1dc4..000000000 --- a/src/PyConsole/CMakeLists.txt +++ /dev/null @@ -1,70 +0,0 @@ - -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) - - diff --git a/src/PyConsole/PyConsole.h b/src/PyConsole/PyConsole.h deleted file mode 100644 index 1df9180c1..000000000 --- a/src/PyConsole/PyConsole.h +++ /dev/null @@ -1,24 +0,0 @@ - -#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 diff --git a/src/PyConsole/PyConsole_Console.cpp b/src/PyConsole/PyConsole_Console.cpp deleted file mode 100644 index 79ae485e9..000000000 --- a/src/PyConsole/PyConsole_Console.cpp +++ /dev/null @@ -1,341 +0,0 @@ - -/*! - \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 - -#include -#include -#include -#include -#include -#include - -/*! - \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(myInterp), this ); - char* synchronous = getenv("PYTHON_CONSOLE_SYNC"); - if (synchronous && atoi(synchronous)) - { - myEditor->setIsSync(true); - } - myEditor->viewport()->installEventFilter( this ); - lay->addWidget( myEditor ); - - createActions(); -} diff --git a/src/PyConsole/PyConsole_Console.h b/src/PyConsole/PyConsole_Console.h deleted file mode 100644 index 7f109eb3e..000000000 --- a/src/PyConsole/PyConsole_Console.h +++ /dev/null @@ -1,89 +0,0 @@ - -#ifndef PYCONSOLE_CONSOLE_H -#define PYCONSOLE_CONSOLE_H - -#include "PyConsole.h" - -//#include -#include -#include - -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 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 diff --git a/src/PyConsole/PyConsole_Editor.cpp b/src/PyConsole/PyConsole_Editor.cpp deleted file mode 100644 index 62ef9e8c3..000000000 --- a/src/PyConsole/PyConsole_Editor.cpp +++ /dev/null @@ -1,1105 +0,0 @@ - -/*! - \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: - - : execute current command - - : clear current command - - : clear current command - - : previous command in the history - - : move cursor one row up with selection - - : move cursor one row up without selection - - : move cursor one row up with selection - - : next command in the history - - : move cursor one row down with selection - - : move cursor one row down without selection - - : move cursor one row down with selection - - : move one symbol left without selection - - : move one symbol left with selection - - : move one word left without selection - - : move one word left with selection - - : move one symbol right without selection - - : move one symbol right with selection - - : move one word right without selection - - : move one word right with selection - - : first command in the history - - : move one page up with selection - - : move one page up without selection - - : scroll one page up - - : last command in the history - - : move one page down with selection - - : move one page down without selection - - : scroll one page down - - : move to the beginning of the line without selection - - : move to the beginning of the line with selection - - : move to the very first symbol without selection - - : move to the very first symbol with selection - - : move to the end of the line without selection - - : move to the end of the line with selection - - : move to the very last symbol without selection - - : move to the very last symbol with selection - - : delete symbol before the cursor - / remove selected text and put it to the clipboard (cut) - - : delete previous word - / remove selected text and put it to the clipboard (cut) - - : delete text from the cursor to the beginning of the line - / remove selected text and put it to the clipboard (cut) - - : delete symbol after the cursor - / remove selected text and put it to the clipboard (cut) - - : delete next word - / remove selected text and put it to the clipboard (cut) - - : delete text from the cursor to the end of the line - / remove selected text and put it to the clipboard (cut) - - : copy - - : paste - - : paste - - : copy - - : cut - - : 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 -//#include -//#include -//#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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 is pressed - bool ctrlPressed = event->modifiers() & Qt::ControlModifier; - // check if is pressed - bool shftPressed = event->modifiers() & Qt::ShiftModifier; - - if ( aKey == Qt::Key_Escape || ( ctrlPressed && aKey == -1 ) ) { - // process + key-binding and 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 + key-binding : copy - copy(); - return; - } - else if ( ctrlPressed && aKey == Qt::Key_X ) { - // process + key-binding : cut - cut(); - return; - } - else if ( ctrlPressed && aKey == Qt::Key_V ) { - // process + 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: - // key: process the current command - { - handleReturn(); - break; - } - case Qt::Key_Up: - // arrow key: process as follows: - // - without , modifiers: previous command in history - // - with modifier key pressed: move cursor one row up without selection - // - with modifier key pressed: move cursor one row up with selection - // - with + 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: - // arrow key: process as follows: - // - without , modifiers: next command in history - // - with modifier key pressed: move cursor one row down without selection - // - with modifier key pressed: move cursor one row down with selection - // - with + 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: - // arrow key: process as follows: - // - without , modifiers: move one symbol left (taking into account prompt) - // - with modifier key pressed: move one word left (taking into account prompt) - // - with modifier key pressed: move one symbol left with selection - // - with + 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: - // arrow key: process as follows: - // - without , modifiers: move one symbol right (taking into account prompt) - // - with modifier key pressed: move one word right (taking into account prompt) - // - with modifier key pressed: move one symbol right with selection - // - with + 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: - // key: process as follows: - // - without , modifiers: first command in history - // - with modifier key pressed: move cursor one page up without selection - // - with modifier key pressed: move cursor one page up with selection - // - with + 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: - // key: process as follows: - // - without , modifiers: last command in history - // - with modifier key pressed: move cursor one page down without selection - // - with modifier key pressed: move cursor one page down with selection - // - with + 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: - // key: process as follows: - // - without , modifiers: move cursor to the beginning of the current line without selection - // - with modifier key pressed: move cursor to the very first symbol without selection - // - with modifier key pressed: move cursor to the beginning of the current line with selection - // - with + 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: - // key: process as follows: - // - without , modifiers: move cursor to the end of the current line without selection - // - with modifier key pressed: move cursor to the very last symbol without selection - // - with modifier key pressed: move cursor to the end of the current line with selection - // - with + 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 : - // key: process as follows - // - without any modifiers : delete symbol before the cursor / selection (taking into account prompt) - // - with modifier key pressed: delete previous word - // - with 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 : - // key: process as follows - // - without any modifiers : delete symbol after the cursor / selection (taking into account prompt) - // - with modifier key pressed: delete next word - // - with 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 : - // key: process as follows - // - with modifier key pressed: copy() - // - with 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 - -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 diff --git a/src/PyConsole/PyConsole_EnhEditor.cpp b/src/PyConsole/PyConsole_EnhEditor.cpp deleted file mode 100644 index d5c47dff3..000000000 --- a/src/PyConsole/PyConsole_EnhEditor.cpp +++ /dev/null @@ -1,464 +0,0 @@ - - -#include "PyConsole.h" -#include - -#include -#include -#include -#include -#include -#include - -#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 PyConsole_EnhEditor::SEPARATORS = \ - std::vector(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 is pressed - bool ctrlPressed = event->modifiers() & Qt::ControlModifier; - // check if 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 . - */ -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(myInterp)->clearCompletion(); - } - _tab_mode = false; -} - -/** - * Handle the sequence of events after having hit - */ -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::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(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 & 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 matches; - QString first_match, comple_text, doc, base; - QTextCursor cursor(textCursor()); - QTextBlockFormat bf; - QTextCharFormat cf; - PyConsole_EnhInterp * interp = static_cast(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 & 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("\n ") + - QString(" ") + - QString(" ") + - QString("\n") + - QString("

") + - QString("%1

") + - QString("

%2

") + - QString(""); - - 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(); - 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 key stroke - addText(line, false, false); - handleReturn(); - } -} diff --git a/src/PyConsole/PyConsole_EnhEditor.h b/src/PyConsole/PyConsole_EnhEditor.h deleted file mode 100644 index 03b5e19a1..000000000 --- a/src/PyConsole/PyConsole_EnhEditor.h +++ /dev/null @@ -1,78 +0,0 @@ - - -#ifndef PYCONSOLE_ENHEDITOR_H_ -#define PYCONSOLE_ENHEDITOR_H_ - -#include "PyConsole.h" - -#include "PyConsole_Editor.h" -#include -#include - -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 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 is hit */ - int _cursor_pos; - - /** Are we currently pasting several lines */ - bool _multi_line_paste; - - /** Queue of lines being pasted */ - std::queue _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 & 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 & matches, QString & result) const; - -}; - -#endif /* PYCONSOLE_ENHEDITOR_H_ */ diff --git a/src/PyConsole/PyConsole_EnhInterp.cpp b/src/PyConsole/PyConsole_EnhInterp.cpp deleted file mode 100644 index 4332f3112..000000000 --- a/src/PyConsole/PyConsole_EnhInterp.cpp +++ /dev/null @@ -1,135 +0,0 @@ - - - -#include "PyConsole.h" - -#include "PyConsole_EnhInterp.h" - -#include -#include -#include - -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 PyConsole_EnhInterp::PYTHON_KEYWORDS = \ - std::vector(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 ", this is "rsp". - \return command exit status - 0 = success -*/ -int PyConsole_EnhInterp::runDirCommand(const QString & dirArgument, const QString & startMatch) -{ - int ret; - std::vector 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::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 & 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(""); -} - - - diff --git a/src/PyConsole/PyConsole_EnhInterp.h b/src/PyConsole/PyConsole_EnhInterp.h deleted file mode 100644 index 1af977cc0..000000000 --- a/src/PyConsole/PyConsole_EnhInterp.h +++ /dev/null @@ -1,47 +0,0 @@ - - -#ifndef PYCONSOLE_ENHINTERP_H_ -#define PYCONSOLE_ENHINTERP_H_ - -#include "PyConsole.h" - -#include -#include "PyConsole_Interp.h" - -#include -#include - -/** - * 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& 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 PYTHON_KEYWORDS; - - /** Last computed matches */ - std::vector _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 & result, bool discardSwig=true) const; - -}; - -#endif /* PYCONSOLE_ENHINTERP_H_ */ diff --git a/src/PyConsole/PyConsole_Event.cpp b/src/PyConsole/PyConsole_Event.cpp deleted file mode 100644 index a3e2b05ae..000000000 --- a/src/PyConsole/PyConsole_Event.cpp +++ /dev/null @@ -1,3 +0,0 @@ - - -#include "PyConsole_Event.h" diff --git a/src/PyConsole/PyConsole_Event.h b/src/PyConsole/PyConsole_Event.h deleted file mode 100644 index 84771b85c..000000000 --- a/src/PyConsole/PyConsole_Event.h +++ /dev/null @@ -1,48 +0,0 @@ - - -#ifndef PYCONSOLE_EVENT_H -#define PYCONSOLE_EVENT_H - -#include "PyConsole.h" - -#include -#include - -/*! - \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 diff --git a/src/PyConsole/PyConsole_Interp.cpp b/src/PyConsole/PyConsole_Interp.cpp deleted file mode 100644 index 21af783d1..000000000 --- a/src/PyConsole/PyConsole_Interp.cpp +++ /dev/null @@ -1,118 +0,0 @@ - -#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. - - But 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. - - But 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; -} diff --git a/src/PyConsole/PyConsole_Interp.h b/src/PyConsole/PyConsole_Interp.h deleted file mode 100644 index d65c9e620..000000000 --- a/src/PyConsole/PyConsole_Interp.h +++ /dev/null @@ -1,20 +0,0 @@ - -#ifndef PYCONSOLE_INTERP_H -#define PYCONSOLE_INTERP_H - -#include "PyConsole.h" - -#include /// !!! 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 diff --git a/src/PyConsole/PyConsole_Request.cpp b/src/PyConsole/PyConsole_Request.cpp deleted file mode 100644 index 3e31b90eb..000000000 --- a/src/PyConsole/PyConsole_Request.cpp +++ /dev/null @@ -1,99 +0,0 @@ - - -#include "PyConsole_Request.h" - -#include "PyInterp_Event.h" -#include "PyConsole_Event.h" -#include "PyConsole_EnhInterp.h" -#include "PyConsole_EnhEditor.h" - -#include - -/** - * 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(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); -} - - - diff --git a/src/PyConsole/PyConsole_Request.h b/src/PyConsole/PyConsole_Request.h deleted file mode 100644 index da5f94a79..000000000 --- a/src/PyConsole/PyConsole_Request.h +++ /dev/null @@ -1,86 +0,0 @@ - - - -#ifndef PYCONSOLE_REQUEST_H_ -#define PYCONSOLE_REQUEST_H_ - -#include "PyConsole.h" -#include "PyInterp_Request.h" - -#include -#include -#include - -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 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_ */ diff --git a/src/PyEvent/CMakeLists.txt b/src/PyEvent/CMakeLists.txt deleted file mode 100644 index 0b54ed93e..000000000 --- a/src/PyEvent/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ - -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) diff --git a/src/PyEvent/PyEvent.h b/src/PyEvent/PyEvent.h deleted file mode 100644 index 9c2f34fc3..000000000 --- a/src/PyEvent/PyEvent.h +++ /dev/null @@ -1,19 +0,0 @@ - -#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 diff --git a/src/PyEvent/PyEvent_Event.cpp b/src/PyEvent/PyEvent_Event.cpp deleted file mode 100644 index fef847f5c..000000000 --- a/src/PyEvent/PyEvent_Event.cpp +++ /dev/null @@ -1,287 +0,0 @@ - -#include "PyEvent_Event.h" - -#include -#include - -// 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 -static DWORD myThread; -#else -#include -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 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. -*/ diff --git a/src/PyEvent/PyEvent_Event.h b/src/PyEvent/PyEvent_Event.h deleted file mode 100644 index ed1ea7b74..000000000 --- a/src/PyEvent/PyEvent_Event.h +++ /dev/null @@ -1,204 +0,0 @@ - -#ifndef PyEvent_PYEVENT_H -#define PyEvent_PYEVENT_H - -#include "PyEvent.h" - -#include - -//! 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 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 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 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 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 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 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 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 diff --git a/src/PyEvent/PyEvent_EventFilter.cpp b/src/PyEvent/PyEvent_EventFilter.cpp deleted file mode 100644 index ac12e2013..000000000 --- a/src/PyEvent/PyEvent_EventFilter.cpp +++ /dev/null @@ -1,60 +0,0 @@ - -#include "PyEvent_EventFilter.h" -#include "PyEvent_Event.h" - -#include - -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; - } -} diff --git a/src/PyEvent/PyEvent_EventFilter.h b/src/PyEvent/PyEvent_EventFilter.h deleted file mode 100644 index 23132de7e..000000000 --- a/src/PyEvent/PyEvent_EventFilter.h +++ /dev/null @@ -1,43 +0,0 @@ - -#ifndef PyEvent_EVENTFILTER_H -#define PyEvent_EVENTFILTER_H - -#include "PyEvent.h" -#include - -#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 diff --git a/src/PyInterp/CMakeLists.txt b/src/PyInterp/CMakeLists.txt deleted file mode 100644 index b540f098b..000000000 --- a/src/PyInterp/CMakeLists.txt +++ /dev/null @@ -1,47 +0,0 @@ - -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) diff --git a/src/PyInterp/PyInterp.h b/src/PyInterp/PyInterp.h deleted file mode 100644 index 4977fce11..000000000 --- a/src/PyInterp/PyInterp.h +++ /dev/null @@ -1,40 +0,0 @@ - -#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 - -#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 diff --git a/src/PyInterp/PyInterp_Dispatcher.cpp b/src/PyInterp/PyInterp_Dispatcher.cpp deleted file mode 100644 index 1999e716f..000000000 --- a/src/PyInterp/PyInterp_Dispatcher.cpp +++ /dev/null @@ -1,199 +0,0 @@ - -#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 -#include - -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 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 it( myQueue ); - while ( it.hasNext() ) - { - RequestPtr r = it.next(); - if ( o == r->listener() ) - { - r->setListener( 0 ); // to prevent event posting - it.remove(); - } - } - - myQueueMutex.unlock(); -} diff --git a/src/PyInterp/PyInterp_Dispatcher.h b/src/PyInterp/PyInterp_Dispatcher.h deleted file mode 100644 index fa98d30b0..000000000 --- a/src/PyInterp/PyInterp_Dispatcher.h +++ /dev/null @@ -1,46 +0,0 @@ - -#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 -#include -#include - -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 myQueue; - QMutex myQueueMutex; - PyInterp_Watcher* myWatcher; - - static PyInterp_Dispatcher* myInstance; - - friend class PyInterp_Watcher; -}; - -#endif // PYINTERP_DISPATCHER_H diff --git a/src/PyInterp/PyInterp_Event.cpp b/src/PyInterp/PyInterp_Event.cpp deleted file mode 100644 index 524d06a08..000000000 --- a/src/PyInterp/PyInterp_Event.cpp +++ /dev/null @@ -1,9 +0,0 @@ - - -#include "PyInterp_Event.h" -#include "PyInterp_Request.h" - -void PyInterp_ExecuteEvent::Execute() -{ - myRequest->execute(); -} diff --git a/src/PyInterp/PyInterp_Event.h b/src/PyInterp/PyInterp_Event.h deleted file mode 100644 index 9fdc9ebcb..000000000 --- a/src/PyInterp/PyInterp_Event.h +++ /dev/null @@ -1,53 +0,0 @@ - - -#ifndef PYINTERP_EVENT_H -#define PYINTERP_EVENT_H - -#include "PyInterp.h" - -#include - -#include - -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 diff --git a/src/PyInterp/PyInterp_Interp.cpp b/src/PyInterp/PyInterp_Interp.cpp deleted file mode 100644 index 7e633b59f..000000000 --- a/src/PyInterp/PyInterp_Interp.cpp +++ /dev/null @@ -1,533 +0,0 @@ - -#include "PyInterp_Interp.h" // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!! -#include - -#include -#include - -#include -#include -#include -#include -#include - -#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 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; -} diff --git a/src/PyInterp/PyInterp_Interp.h b/src/PyInterp/PyInterp_Interp.h deleted file mode 100644 index d92bc4fc9..000000000 --- a/src/PyInterp/PyInterp_Interp.h +++ /dev/null @@ -1,95 +0,0 @@ - -#ifndef PYINTERP_INTERP_H -#define PYINTERP_INTERP_H - -#include "PyInterp.h" // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!! - -#include -#include - -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 _history; - std::list::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 diff --git a/src/PyInterp/PyInterp_Request.cpp b/src/PyInterp/PyInterp_Request.cpp deleted file mode 100644 index a4ce0992f..000000000 --- a/src/PyInterp/PyInterp_Request.cpp +++ /dev/null @@ -1,4 +0,0 @@ - - -#include "PyInterp_Request.h" - diff --git a/src/PyInterp/PyInterp_Request.h b/src/PyInterp/PyInterp_Request.h deleted file mode 100644 index 9cc3a68ac..000000000 --- a/src/PyInterp/PyInterp_Request.h +++ /dev/null @@ -1,81 +0,0 @@ - - -#ifndef PYINTERP_REQUEST_H -#define PYINTERP_REQUEST_H - -#include "PyInterp.h" -#include "PyInterp_Event.h" - -#include -#include - -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 diff --git a/src/PyInterp/PyInterp_Watcher.h b/src/PyInterp/PyInterp_Watcher.h deleted file mode 100644 index 91126b7e9..000000000 --- a/src/PyInterp/PyInterp_Watcher.h +++ /dev/null @@ -1,24 +0,0 @@ - -#ifndef PYINTERP_WATCHER_H -#define PYINTERP_WATCHER_H - -#include "PyInterp.h" // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!! - -#include "PyInterp_Dispatcher.h" - -#include - -// 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 diff --git a/src/XGUI/CMakeLists.txt b/src/XGUI/CMakeLists.txt index 67ba7629d..307dbff6b 100644 --- a/src/XGUI/CMakeLists.txt +++ b/src/XGUI/CMakeLists.txt @@ -80,9 +80,8 @@ SET(PROJECT_LIBRARIES ${QT_LIBRARIES} ${CAS_VIEWER} ${CAS_KERNEL} - PyConsole - PyInterp - PyEvent + ${PyConsole} + ${PyInterp} ModelAPI ModuleBase ) @@ -111,13 +110,12 @@ ADD_DEFINITIONS( -DXGUI_EXPORTS ${CAS_DEFINITIONS} ) 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}) -- 2.39.2