From 9052dd81667d6a0555330c6a475b9e8e86a7c4de Mon Sep 17 00:00:00 2001 From: vsr Date: Wed, 16 Mar 2016 16:50:07 +0300 Subject: [PATCH] Clean up Python features --- CMakeLists.txt | 2 +- SalomeGUIConfig.cmake.in | 1 - adm_local/cmake_files/FindGUI.cmake | 1 - .../cmake_files/deprecated/FindGUI.cmake | 1 - src/CMakeLists.txt | 1 - src/LightApp/CMakeLists.txt | 13 +- src/LightApp/LightApp_Application.cxx | 30 +- src/LightApp/LightApp_Application.h | 4 +- src/LightApp/LightApp_FileValidator.cxx | 62 ++ ...pp_PyInterp.h => LightApp_FileValidator.h} | 26 +- src/LightApp/LightApp_PyEditor.cxx | 77 ++ .../LightApp_PyEditor.h} | 34 +- src/LightApp/LightApp_PyInterp.cxx | 52 - src/LightApp/resources/LightApp.xml | 2 +- src/LightApp/resources/LightApp_msg_en.ts | 28 + src/LightApp/resources/LightApp_msg_fr.ts | 28 + src/LightApp/resources/LightApp_msg_ja.ts | 30 +- src/PyConsole/CMakeLists.txt | 17 +- src/PyConsole/PyConsole.h | 3 +- ..._ConsoleBase.cxx => PyConsole_Console.cxx} | 246 ++--- ...sole_ConsoleBase.h => PyConsole_Console.h} | 66 +- ...le_EditorBase.cxx => PyConsole_Editor.cxx} | 956 +++++++++++++----- src/PyConsole/PyConsole_Editor.h | 137 +++ src/PyConsole/PyConsole_EditorBase.h | 110 -- src/PyConsole/PyConsole_EnhEditorBase.cxx | 491 --------- src/PyConsole/PyConsole_EnhEditorBase.h | 95 -- src/PyConsole/PyConsole_EnhInterp.cxx | 177 ---- src/PyConsole/PyConsole_EnhInterp.h | 63 -- src/PyConsole/PyConsole_Event.cxx | 85 +- src/PyConsole/PyConsole_Event.h | 54 +- src/PyConsole/PyConsole_Interp.cxx | 147 ++- src/PyConsole/PyConsole_Interp.h | 16 +- src/PyConsole/PyConsole_Request.cxx | 114 ++- src/PyConsole/PyConsole_Request.h | 71 +- src/PyConsole/resources/PyConsole_msg_en.ts | 44 +- src/PyConsole/resources/PyConsole_msg_fr.ts | 38 +- src/PyConsole/resources/PyConsole_msg_ja.ts | 46 +- src/PyInterp/CMakeLists.txt | 15 +- src/PyInterp/PyInterp.h | 3 +- src/PyInterp/PyInterp_Dispatcher.cxx | 49 +- src/PyInterp/PyInterp_Dispatcher.h | 18 +- src/PyInterp/PyInterp_Event.cxx | 25 +- src/PyInterp/PyInterp_Event.h | 43 +- src/PyInterp/PyInterp_Interp.cxx | 38 +- src/PyInterp/PyInterp_Interp.h | 32 +- src/PyInterp/PyInterp_Request.cxx | 12 +- src/PyInterp/PyInterp_Request.h | 36 +- src/PyInterp/PyInterp_Utils.h | 11 +- src/PyInterp/PyInterp_Watcher.h | 49 - src/SALOME_PYQT/SalomePyQt/CMakeLists.txt | 1 - src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx | 6 +- src/SalomeApp/CMakeLists.txt | 3 +- src/SalomeApp/SalomeApp_Application.cxx | 42 +- src/SalomeApp/SalomeApp_NoteBook.cxx | 6 +- src/SalomeApp/SalomeApp_PyInterp.cxx | 47 +- src/SalomeApp/SalomeApp_PyInterp.h | 13 +- src/SalomeApp/resources/SalomeApp_msg_en.ts | 9 - src/SalomeApp/resources/SalomeApp_msg_fr.ts | 9 - src/SalomeApp/resources/SalomeApp_msg_ja.ts | 8 - src/SalomePyConsole/CMakeLists.txt | 90 -- src/SalomePyConsole/SalomePyConsole.h | 48 - .../SalomePyConsole_Console.cxx | 131 --- src/SalomePyConsole/SalomePyConsole_Console.h | 81 -- .../SalomePyConsole_Editor.cxx | 207 ---- src/SalomePyConsole/SalomePyConsole_Editor.h | 52 - .../SalomePyConsole_EnhEditor.cxx | 53 - .../resources/SalomePyConsole_msg_en.ts | 27 - .../resources/SalomePyConsole_msg_fr.ts | 27 - .../resources/SalomePyConsole_msg_ja.ts | 27 - 69 files changed, 1820 insertions(+), 2766 deletions(-) create mode 100644 src/LightApp/LightApp_FileValidator.cxx rename src/LightApp/{LightApp_PyInterp.h => LightApp_FileValidator.h} (65%) create mode 100644 src/LightApp/LightApp_PyEditor.cxx rename src/{SalomePyConsole/SalomePyConsole_EnhEditor.h => LightApp/LightApp_PyEditor.h} (60%) delete mode 100644 src/LightApp/LightApp_PyInterp.cxx rename src/PyConsole/{PyConsole_ConsoleBase.cxx => PyConsole_Console.cxx} (58%) rename src/PyConsole/{PyConsole_ConsoleBase.h => PyConsole_Console.h} (60%) rename src/PyConsole/{PyConsole_EditorBase.cxx => PyConsole_Editor.cxx} (57%) create mode 100644 src/PyConsole/PyConsole_Editor.h delete mode 100644 src/PyConsole/PyConsole_EditorBase.h delete mode 100644 src/PyConsole/PyConsole_EnhEditorBase.cxx delete mode 100644 src/PyConsole/PyConsole_EnhEditorBase.h delete mode 100644 src/PyConsole/PyConsole_EnhInterp.cxx delete mode 100644 src/PyConsole/PyConsole_EnhInterp.h delete mode 100755 src/PyInterp/PyInterp_Watcher.h delete mode 100755 src/SalomePyConsole/CMakeLists.txt delete mode 100644 src/SalomePyConsole/SalomePyConsole.h delete mode 100644 src/SalomePyConsole/SalomePyConsole_Console.cxx delete mode 100644 src/SalomePyConsole/SalomePyConsole_Console.h delete mode 100644 src/SalomePyConsole/SalomePyConsole_Editor.cxx delete mode 100644 src/SalomePyConsole/SalomePyConsole_Editor.h delete mode 100644 src/SalomePyConsole/SalomePyConsole_EnhEditor.cxx delete mode 100644 src/SalomePyConsole/resources/SalomePyConsole_msg_en.ts delete mode 100644 src/SalomePyConsole/resources/SalomePyConsole_msg_fr.ts delete mode 100644 src/SalomePyConsole/resources/SalomePyConsole_msg_ja.ts diff --git a/CMakeLists.txt b/CMakeLists.txt index 419d7fa34..0f392c835 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -377,7 +377,7 @@ ENDIF() # Python-based packages specific targets: IF(SALOME_USE_PYCONSOLE) LIST(APPEND _${PROJECT_NAME}_exposed_targets - PyInterp PyConsole SalomePyConsole SalomePyQtGUILight) + PyInterp PyConsole SalomePyQtGUILight) IF(SALOME_USE_PLOT2DVIEWER) LIST(APPEND _${PROJECT_NAME}_exposed_targets SalomePyQt) ENDIF() diff --git a/SalomeGUIConfig.cmake.in b/SalomeGUIConfig.cmake.in index 71831b1e1..94483ffcf 100644 --- a/SalomeGUIConfig.cmake.in +++ b/SalomeGUIConfig.cmake.in @@ -193,7 +193,6 @@ SET(GUI_OCCViewer OCCViewer) SET(GUI_OpenGLUtils OpenGLUtils) SET(GUI_Plot2d Plot2d) SET(GUI_PyConsole PyConsole) -SET(GUI_SalomePyConsole SalomePyConsole) SET(GUI_PyInterp PyInterp) SET(GUI_PyEditor PyEditor) SET(GUI_PyViewer PyViewer) diff --git a/adm_local/cmake_files/FindGUI.cmake b/adm_local/cmake_files/FindGUI.cmake index 7d7b3b101..55d26381c 100644 --- a/adm_local/cmake_files/FindGUI.cmake +++ b/adm_local/cmake_files/FindGUI.cmake @@ -36,7 +36,6 @@ FIND_LIBRARY(OCCViewer OCCViewer ${GUI_ROOT_DIR}/lib/salome) FIND_LIBRARY(OpenGLUtils OpenGLUtils ${GUI_ROOT_DIR}/lib/salome) FIND_LIBRARY(Plot2d Plot2d ${GUI_ROOT_DIR}/lib/salome) FIND_LIBRARY(PyConsole PyConsole ${GUI_ROOT_DIR}/lib/salome) -FIND_LIBRARY(SalomePyConsole SalomePyConsole ${GUI_ROOT_DIR}/lib/salome) FIND_LIBRARY(PyInterp PyInterp ${GUI_ROOT_DIR}/lib/salome) FIND_LIBRARY(QDS QDS ${GUI_ROOT_DIR}/lib/salome) FIND_LIBRARY(qtx qtx ${GUI_ROOT_DIR}/lib/salome) diff --git a/adm_local/cmake_files/deprecated/FindGUI.cmake b/adm_local/cmake_files/deprecated/FindGUI.cmake index eec011486..ef595dd54 100644 --- a/adm_local/cmake_files/deprecated/FindGUI.cmake +++ b/adm_local/cmake_files/deprecated/FindGUI.cmake @@ -32,7 +32,6 @@ FIND_LIBRARY(OCCViewer OCCViewer ${GUI_ROOT_DIR}/lib/salome) FIND_LIBRARY(OpenGLUtils OpenGLUtils ${GUI_ROOT_DIR}/lib/salome) FIND_LIBRARY(Plot2d Plot2d ${GUI_ROOT_DIR}/lib/salome) FIND_LIBRARY(PyConsole PyConsole ${GUI_ROOT_DIR}/lib/salome) -FIND_LIBRARY(SalomePyConsole SalomePyConsole ${GUI_ROOT_DIR}/lib/salome) FIND_LIBRARY(PyInterp PyInterp ${GUI_ROOT_DIR}/lib/salome) FIND_LIBRARY(QDS QDS ${GUI_ROOT_DIR}/lib/salome) FIND_LIBRARY(qtx qtx ${GUI_ROOT_DIR}/lib/salome) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cb92cbb5a..052ae86c5 100755 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -125,7 +125,6 @@ ENDIF(SALOME_USE_PYVIEWER) IF(SALOME_USE_PYCONSOLE) ADD_SUBDIRECTORY(PyInterp) ADD_SUBDIRECTORY(PyConsole) - ADD_SUBDIRECTORY(SalomePyConsole) ADD_SUBDIRECTORY(SALOME_PYQT) ENDIF(SALOME_USE_PYCONSOLE) diff --git a/src/LightApp/CMakeLists.txt b/src/LightApp/CMakeLists.txt index f37381f24..d4a69eab3 100755 --- a/src/LightApp/CMakeLists.txt +++ b/src/LightApp/CMakeLists.txt @@ -81,7 +81,6 @@ ENDIF() IF(SALOME_USE_PYCONSOLE) INCLUDE_DIRECTORIES( ${PYTHON_INCLUDE_DIRS} - ${PROJECT_SOURCE_DIR}/src/SalomePyConsole ${PROJECT_SOURCE_DIR}/src/PyConsole ${PROJECT_SOURCE_DIR}/src/PyInterp ${PROJECT_SOURCE_DIR}/src/SUITApp @@ -142,7 +141,7 @@ IF(SALOME_USE_PVVIEWER) LIST(APPEND _link_LIBRARIES PVViewer) ENDIF() IF(SALOME_USE_PYCONSOLE) - LIST(APPEND _link_LIBRARIES PyInterp SalomePyConsole SUITApp) + LIST(APPEND _link_LIBRARIES PyInterp PyConsole SUITApp) ENDIF() # --- headers --- @@ -184,6 +183,9 @@ IF(SALOME_USE_VTKVIEWER) LIST(APPEND _moc_HEADERS LightApp_VTKSelector.h) ENDIF() ENDIF() +IF(SALOME_USE_PYCONSOLE) + LIST(APPEND _moc_HEADERS LightApp_PyEditor.h) +ENDIF() # header files / no moc processing SET(_other_HEADERS @@ -194,14 +196,12 @@ SET(_other_HEADERS LightApp_Displayer.h LightApp_Driver.h LightApp_EventFilter.h + LightApp_FileValidator.h LightApp_FullScreenHelper.h LightApp_HDFDriver.h LightApp_Selection.h LightApp_UpdateFlags.h ) -IF(SALOME_USE_PYCONSOLE) - LIST(APPEND _other_HEADERS LightApp_PyInterp.h) -ENDIF() # header files / to install SET(LightApp_HEADERS ${_moc_HEADERS} ${_other_HEADERS}) @@ -251,6 +251,7 @@ SET(_other_SOURCES LightApp_Displayer.cxx LightApp_Driver.cxx LightApp_EventFilter.cxx + LightApp_FileValidator.cxx LightApp_FullScreenHelper.cxx LightApp_HDFDriver.cxx LightApp_Module.cxx @@ -286,7 +287,7 @@ IF(SALOME_USE_VTKVIEWER) ENDIF() ENDIF() IF(SALOME_USE_PYCONSOLE) - LIST(APPEND _other_SOURCES LightApp_PyInterp.cxx) + LIST(APPEND _other_SOURCES LightApp_PyEditor.cxx) ENDIF() # sources / to compile diff --git a/src/LightApp/LightApp_Application.cxx b/src/LightApp/LightApp_Application.cxx index dfb449153..4bf97d8ca 100644 --- a/src/LightApp/LightApp_Application.cxx +++ b/src/LightApp/LightApp_Application.cxx @@ -35,8 +35,9 @@ #endif #ifndef DISABLE_PYCONSOLE - #include "LightApp_PyInterp.h" // WARNING! This include must be the first! - #include + #include "LightApp_PyEditor.h" + #include "PyConsole_Interp.h" + #include "PyConsole_Console.h" #endif #include "LightApp_Application.h" @@ -1366,13 +1367,13 @@ LogWindow* LightApp_Application::logWindow() \param force - if true, the pythonConsole is created if it does not exist yet \return Python Console */ -SalomePyConsole_Console* LightApp_Application::pythonConsole(const bool force) +PyConsole_Console* LightApp_Application::pythonConsole(const bool force) { QWidget* wid = dockWindow( WT_PyConsole ); if ( !wid && force==true) { wid = getWindow(WT_PyConsole); } - return qobject_cast( wid ); + return qobject_cast( wid ); } #endif @@ -2026,15 +2027,14 @@ QWidget* LightApp_Application::createWindow( const int flag ) #ifndef DISABLE_PYCONSOLE else if ( flag == WT_PyConsole ) { - SalomePyConsole_Console* pyCons = new SalomePyConsole_EnhConsole( desktop(), getPyInterp() ); + PyConsole_Console* pyCons = new PyConsole_Console( desktop(), new LightApp_PyEditor( getPyInterp() ) ); pyCons->setObjectName( "pythonConsole" ); pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) ); - pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" )); - pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true )); + pyCons->setFont( resMgr->fontValue( "PyConsole", "font" ) ); + pyCons->setIsShowBanner( resMgr->booleanValue( "PyConsole", "show_banner", true ) ); + pyCons->setAutoCompletion( resMgr->booleanValue( "PyConsole", "auto_completion", true ) ); pyCons->setProperty( "shortcut", QKeySequence( "Alt+Shift+P" ) ); - wid = pyCons; - pyCons->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) ); } #endif else if ( flag == WT_LogWindow ) @@ -2269,10 +2269,13 @@ void LightApp_Application::createPreferences( LightApp_Preferences* pref ) // ... "Python console properties" group <> int pythonConsoleGroup = pref->addPreference( tr( "PREF_GROUP_PY_CONSOLE" ), genTab ); + pref->setItemProperty( "columns", 2, pythonConsoleGroup ); // .... -> font pref->addPreference( tr( "PREF_FONT" ), pythonConsoleGroup, LightApp_Preferences::Font, "PyConsole", "font" ); // .... -> show banner pref->addPreference( tr( "PREF_SHOW_BANNER" ), pythonConsoleGroup, LightApp_Preferences::Bool, "PyConsole", "show_banner" ); + // .... -> auto-completion + pref->addPreference( tr( "PREF_AUTO_COMPLETION" ), pythonConsoleGroup, LightApp_Preferences::Bool, "PyConsole", "auto_completion" ); // ... "Python console properties" group <> // ... "MRU" preferences group <> @@ -3575,6 +3578,9 @@ void LightApp_Application::preferencesChanged( const QString& sec, const QString else if ( param=="show_banner" ) { pythonConsole()->setIsShowBanner( resMgr->booleanValue( "PyConsole", "show_banner", true ) ); } + else if ( param=="auto_completion" ) { + pythonConsole()->setAutoCompletion( resMgr->booleanValue( "PyConsole", "auto_completion", true ) ); + } } #endif @@ -5125,14 +5131,16 @@ bool LightApp_Application::checkExistingDoc() PyConsole_Interp* LightApp_Application::getPyInterp() { static PyConsole_Interp* myInterp = 0; - if ( !myInterp ) + if ( !myInterp ) { myInterp = createPyInterp(); + myInterp->initialize(); + } return myInterp; } PyConsole_Interp* LightApp_Application::createPyInterp() { - return new LightApp_PyInterp(); + return new PyConsole_Interp(); } #endif // DISABLE_PYCONSOLE diff --git a/src/LightApp/LightApp_Application.h b/src/LightApp/LightApp_Application.h index 9284aa2fb..926546228 100644 --- a/src/LightApp/LightApp_Application.h +++ b/src/LightApp/LightApp_Application.h @@ -41,7 +41,7 @@ class LogWindow; #ifndef DISABLE_PYCONSOLE -class SalomePyConsole_Console; +class PyConsole_Console; class PyConsole_Interp; #endif class LightApp_WidgetContainer; @@ -111,7 +111,7 @@ public: LogWindow* logWindow(); SUIT_DataBrowser* objectBrowser(); #ifndef DISABLE_PYCONSOLE - SalomePyConsole_Console* pythonConsole(const bool force = false); + PyConsole_Console* pythonConsole(const bool force = false); #endif virtual void updateObjectBrowser( const bool = true ); diff --git a/src/LightApp/LightApp_FileValidator.cxx b/src/LightApp/LightApp_FileValidator.cxx new file mode 100644 index 000000000..4f8179c12 --- /dev/null +++ b/src/LightApp/LightApp_FileValidator.cxx @@ -0,0 +1,62 @@ +// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// File : LightApp_FileValidator.cxx +// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) + +#include "LightApp_FileValidator.h" +#include "SUIT_MessageBox.h" + +#include + +/*! + \class LightApp_PyFileValidator + \brief Validator for Python scripts file names. +*/ + +/*! + \brief Constructor + \param parent parent widget +*/ +LightApp_PyFileValidator::LightApp_PyFileValidator( QWidget* parent ) + : SUIT_FileValidator ( parent ) +{ +} + +/*! + \brief Check if the specified file can be written. + + Checks if file name is valid for Python script. + + \param fileName file path + \param checkPermission if \c true (default) check also file permissions + \return \c false if file exists and user rejects file overwriting + or if file does not have write permissions (if \a checkPermission is \c true) + \sa SUIT_FileValidator +*/ +bool LightApp_PyFileValidator::canSave( const QString& fileName, bool checkPermission ) +{ + QFileInfo fi( fileName ); + if ( !QRegExp( "[A-Za-z_][A-Za-z0-9_]*" ).exactMatch( fi.completeBaseName() ) ) { + SUIT_MessageBox::critical( parent(), + QObject::tr( "WRN_WARNING" ), + QObject::tr( "WRN_PYTHON_FILE_NAME_BAD" ) ); + return false; + } + return SUIT_FileValidator::canSave( fileName, checkPermission ); +} diff --git a/src/LightApp/LightApp_PyInterp.h b/src/LightApp/LightApp_FileValidator.h similarity index 65% rename from src/LightApp/LightApp_PyInterp.h rename to src/LightApp/LightApp_FileValidator.h index 7ffdcc48c..eff839046 100644 --- a/src/LightApp/LightApp_PyInterp.h +++ b/src/LightApp/LightApp_FileValidator.h @@ -16,25 +16,21 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // +// File : LightApp_FileValidator.h +// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) -// Author : Roman NIKOLAEV, Open CASCADE S.A.S. (roman.nikolaev@opencascade.com) -// Date : 22/06/2007 -// -#ifndef _LIGHTAPP_PYINTERP_H_ -#define _LIGHTAPP_PYINTERP_H_ +#ifndef LIGHTAPP_FILEVALIDATOR_H +#define LIGHTAPP_FILEVALIDATOR_H -#include // this include must be first (see PyInterp_base.h)! +#include "LightApp.h" +#include "SUIT_FileValidator.h" -class LightApp_PyInterp : public PyConsole_EnhInterp +class LIGHTAPP_EXPORT LightApp_PyFileValidator : public SUIT_FileValidator { - friend class LightApp_Application; - public: - virtual ~LightApp_PyInterp(); - -protected: - LightApp_PyInterp(); - virtual void initPython(); + LightApp_PyFileValidator( QWidget* ); + + virtual bool canSave( const QString&, bool ); }; -#endif //_LIGHTAPP_PYINTERP_H_ +#endif // LIGHTAPP_FILEVALIDATOR_H diff --git a/src/LightApp/LightApp_PyEditor.cxx b/src/LightApp/LightApp_PyEditor.cxx new file mode 100644 index 000000000..7d71b8de0 --- /dev/null +++ b/src/LightApp/LightApp_PyEditor.cxx @@ -0,0 +1,77 @@ +// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// File : LightApp_PyEditor.cxx +// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) + +#include "LightApp_PyEditor.h" +#include "LightApp_FileValidator.h" +#include "SUIT_FileDlg.h" + +/*! + \brief Constructor. + \param interp python interper + \param parent parent widget +*/ +LightApp_PyEditor::LightApp_PyEditor( PyConsole_Interp* interp, QWidget* parent ) + : PyConsole_Editor( interp, parent ) +{ +} + +/*! + \brief Destructor +*/ +LightApp_PyEditor::~LightApp_PyEditor() +{ +} + +/*! + \brief Get file name for Dump commands operation. + + This function can be redefined in successor classes to show application + specific dialog box. + + \return path to the dump file +*/ +QString LightApp_PyEditor::getDumpFileName() +{ + QStringList aFilters; + aFilters.append( tr( "PYTHON_FILES_FILTER" ) ); + + return SUIT_FileDlg::getFileName( this, QString(), + aFilters, tr( "TOT_DUMP_PYCOMMANDS" ), + false, true, new LightApp_PyFileValidator( this ) ); +} + +/*! + \brief Get file name for Log Python trace operation. + + This function can be redefined in successor classes to show application + specific dialog box. + + \return path to the log file +*/ +QString LightApp_PyEditor::getLogFileName() +{ + QStringList aFilters; + aFilters.append( tr( "LOG_FILES_FILTER" ) ); + + return SUIT_FileDlg::getFileName( this, QString(), + aFilters, tr( "TOT_SAVE_PYLOG" ), + false, true ); +} diff --git a/src/SalomePyConsole/SalomePyConsole_EnhEditor.h b/src/LightApp/LightApp_PyEditor.h similarity index 60% rename from src/SalomePyConsole/SalomePyConsole_EnhEditor.h rename to src/LightApp/LightApp_PyEditor.h index af4b8f083..4dbdb2931 100644 --- a/src/SalomePyConsole/SalomePyConsole_EnhEditor.h +++ b/src/LightApp/LightApp_PyEditor.h @@ -16,30 +16,26 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -// Author : Adrien Bruneton (CEA/DEN) -// Created on: 4 avr. 2013 +// File : LightApp_PyEditor.h +// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) -#ifndef SALOMEPYCONSOLE_ENHEDITOR_H_ -#define SALOMEPYCONSOLE_ENHEDITOR_H_ +#ifndef LIGHTAPP_PYEDITOR_H +#define LIGHTAPP_PYEDITOR_H -#include "SalomePyConsole.h" -#include "PyConsole_EnhEditorBase.h" +#include "LightApp.h" +#include "PyConsole_Editor.h" -#include -#include - -/** - * Enhanced Python editor handling tab completion. - */ -class PYCONSOLE_EXPORT SalomePyConsole_EnhEditor : public PyConsole_EnhEditorBase +class LIGHTAPP_EXPORT LightApp_PyEditor : public PyConsole_Editor { - Q_OBJECT; + Q_OBJECT + public: - SalomePyConsole_EnhEditor(PyConsole_Interp* interp, QWidget* parent = 0); - virtual ~SalomePyConsole_EnhEditor() {} + LightApp_PyEditor( PyConsole_Interp*, QWidget* = 0 ); + ~LightApp_PyEditor(); + protected: - virtual void dumpSlot(); - virtual void startLogSlot(); + virtual QString getDumpFileName(); + virtual QString getLogFileName(); }; -#endif /* PYCONSOLE_ENHEDITOR_H_ */ +#endif // LIGHTAPP_PYEDITOR_H diff --git a/src/LightApp/LightApp_PyInterp.cxx b/src/LightApp/LightApp_PyInterp.cxx deleted file mode 100644 index 63cdc9235..000000000 --- a/src/LightApp/LightApp_PyInterp.cxx +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// - -// Author : Roman NIKOLAEV, Open CASCADE S.A.S. (roman.nikolaev@opencascade.com) -// Date : 22/06/2007 -// -#include "LightApp_PyInterp.h" - -/*! - * constructor : Python interpreter. - */ -LightApp_PyInterp::LightApp_PyInterp(): PyConsole_EnhInterp() -{ -} - -/*! - * Destructor. - */ -LightApp_PyInterp::~LightApp_PyInterp() -{ -} - -/*!\class LightApp_PyInterp - * [ABN] : there is now a single Python interpreter for the whole SALOME run. - * Different execution environment are provided to emulate independent - * "virtual" Python interpreters. - */ - - -/*! - Do nothing - The initialization has been done in main - see SUITApp/SUITApp.cxx - main() - */ -void LightApp_PyInterp::initPython() -{ -} diff --git a/src/LightApp/resources/LightApp.xml b/src/LightApp/resources/LightApp.xml index ba939a280..eee9a6d6f 100644 --- a/src/LightApp/resources/LightApp.xml +++ b/src/LightApp/resources/LightApp.xml @@ -73,7 +73,6 @@ - @@ -89,6 +88,7 @@
+ diff --git a/src/LightApp/resources/LightApp_msg_en.ts b/src/LightApp/resources/LightApp_msg_en.ts index 61ac28d7c..8035492e3 100644 --- a/src/LightApp/resources/LightApp_msg_en.ts +++ b/src/LightApp/resources/LightApp_msg_en.ts @@ -70,6 +70,19 @@ CEA/DEN, CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITASAPPCLOSE_CANCEL &Cancel + + WRN_PYTHON_FILE_NAME_BAD + Please enter correct file name. +Python file must include only letters, digits and underscores and start from letter or underscore. + + + PYTHON_FILES_FILTER + Python Files (*.py) + + + LOG_FILES_FILTER + Log files (*.log *.txt) + LightApp_Application @@ -411,6 +424,10 @@ The changes will be applied on the next application session. PREF_SHOW_BANNER Show banner + + PREF_AUTO_COMPLETION + Command auto-completion + PREF_GROUP_STYLE Salome style @@ -1169,4 +1186,15 @@ File does not exist Activate/deactivate %1 module + + LightApp_PyEditor + + TOT_DUMP_PYCOMMANDS + Dump commands + + + TOT_SAVE_PYLOG + Save log + + diff --git a/src/LightApp/resources/LightApp_msg_fr.ts b/src/LightApp/resources/LightApp_msg_fr.ts index 4a474b597..5d65e3449 100755 --- a/src/LightApp/resources/LightApp_msg_fr.ts +++ b/src/LightApp/resources/LightApp_msg_fr.ts @@ -70,6 +70,19 @@ CEA/DEN, CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITASAPPCLOSE_CANCEL &Annuler + + WRN_PYTHON_FILE_NAME_BAD + Indiquez un nom de fichier correct. +Un fichier Python ne doit être composé que de lettres, chiffres et tirets bas et doit commencer avec une lettre ou un tiret bas. + + + PYTHON_FILES_FILTER + Fichiers Python (*.py) + + + LOG_FILES_FILTER + Fichiers de trace (*.log *.txt) + LightApp_Application @@ -411,6 +424,10 @@ Les modifications seront appliquées à la prochaine session. PREF_SHOW_BANNER Afficher la bannière + + PREF_AUTO_COMPLETION + Command auto-completion + PREF_GROUP_STYLE Style Salomé @@ -1169,4 +1186,15 @@ Le fichier n'existe pas Activer/désactiver le module %1 + + LightApp_PyEditor + + TOT_DUMP_PYCOMMANDS + &Générer le script des commandes + + + TOT_SAVE_PYLOG + Sauver la trace + + diff --git a/src/LightApp/resources/LightApp_msg_ja.ts b/src/LightApp/resources/LightApp_msg_ja.ts index caae2fb55..6c6ccaf50 100644 --- a/src/LightApp/resources/LightApp_msg_ja.ts +++ b/src/LightApp/resources/LightApp_msg_ja.ts @@ -56,8 +56,7 @@ CEA/DEN, CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS STUDYCLOSE_DESCRIPTION - 既存のスタディを閉じる必要があります。閉じますか? - + 既存のスタディを閉じる必要があります。閉じますか? APPCLOSE_SAVE @@ -71,6 +70,18 @@ CEA/DEN, CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITASAPPCLOSE_CANCEL キャンセル(&C) + + WRN_PYTHON_FILE_NAME_BAD + 有効なファイル名を入力してください。Pythonのファイル名は、文字、数字、およびアンダー スコアで構成され、文字かアンダー スコアで始まる必要があります。 + + + PYTHON_FILES_FILTER + ファイル (*.py) Python + + + LOG_FILES_FILTER + ログファイル (*.log *.txt) + LightApp_Application @@ -411,6 +422,10 @@ CEA/DEN, CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITASPREF_SHOW_BANNER バナーの表示 + + PREF_AUTO_COMPLETION + Command auto-completion + PREF_GROUP_STYLE Salomeスタイル @@ -1167,4 +1182,15 @@ CEA/DEN, CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITASモジュール %1 の有効/無効にします。 + + LightApp_PyEditor + + TOT_DUMP_PYCOMMANDS + スクリプト コマンドを生成します。 + + + TOT_SAVE_PYLOG + ログの保存 + + diff --git a/src/PyConsole/CMakeLists.txt b/src/PyConsole/CMakeLists.txt index 950888f38..bc49aebc6 100755 --- a/src/PyConsole/CMakeLists.txt +++ b/src/PyConsole/CMakeLists.txt @@ -25,9 +25,6 @@ INCLUDE(UseQt4Ext) INCLUDE_DIRECTORIES( ${QT_INCLUDES} ${PYTHON_INCLUDE_DIRS} - ${PROJECT_SOURCE_DIR}/src/Qtx - ${PROJECT_SOURCE_DIR}/src/PyConsole - ${PROJECT_SOURCE_DIR}/src/Event ${PROJECT_SOURCE_DIR}/src/PyInterp ) @@ -35,21 +32,19 @@ INCLUDE_DIRECTORIES( ADD_DEFINITIONS(${QT_DEFINITIONS} ${PYTHON_DEFINITIONS}) # libraries to link to -SET(_link_LIBRARIES ${QT_LIBRARIES} ${PYTHON_LIBRARIES} PyInterp Event qtx) +SET(_link_LIBRARIES ${QT_LIBRARIES} ${PYTHON_LIBRARIES} PyInterp) # --- headers --- # header files / to be processed by moc SET(_moc_HEADERS - PyConsole_ConsoleBase.h - PyConsole_EditorBase.h - PyConsole_EnhEditorBase.h + PyConsole_Console.h + PyConsole_Editor.h ) # header files / no moc processing SET(_other_HEADERS PyConsole.h - PyConsole_EnhInterp.h PyConsole_Event.h PyConsole_Interp.h PyConsole_Request.h @@ -74,13 +69,11 @@ QT4_WRAP_CPP(_moc_SOURCES ${_moc_HEADERS}) # sources / static SET(_other_SOURCES - PyConsole_ConsoleBase.cxx - PyConsole_EnhInterp.cxx + PyConsole_Console.cxx PyConsole_Event.cxx PyConsole_Interp.cxx PyConsole_Request.cxx - PyConsole_EditorBase.cxx - PyConsole_EnhEditorBase.cxx + PyConsole_Editor.cxx ) # sources / to compile diff --git a/src/PyConsole/PyConsole.h b/src/PyConsole/PyConsole.h index e313cdf5e..4c72bdfb9 100644 --- a/src/PyConsole/PyConsole.h +++ b/src/PyConsole/PyConsole.h @@ -19,10 +19,9 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // - // File : PyConsole.h // Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) -// + #if !defined ( PYCONSOLE_H ) #define PYCONSOLE_H diff --git a/src/PyConsole/PyConsole_ConsoleBase.cxx b/src/PyConsole/PyConsole_Console.cxx similarity index 58% rename from src/PyConsole/PyConsole_ConsoleBase.cxx rename to src/PyConsole/PyConsole_Console.cxx index 331151197..3aaa52ccb 100644 --- a/src/PyConsole/PyConsole_ConsoleBase.cxx +++ b/src/PyConsole/PyConsole_Console.cxx @@ -19,35 +19,39 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // - -// File : PyConsole_ConsoleBase.cxx +// File : PyConsole_Console.cxx // Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) -// -/*! - \class PyConsole_Console - \brief Python console widget. -*/ - -#include "PyConsole_Interp.h" /// !!! WARNING !!! THIS INCLUDE MUST BE VERY FIRST !!! -#include "PyConsole_ConsoleBase.h" -#include "PyConsole_EnhEditorBase.h" -#include "PyConsole_EnhInterp.h" -#include "Qtx.h" +#include "PyConsole_Console.h" +#include "PyConsole_Interp.h" +#include "PyConsole_Editor.h" #include #include #include -#include -#include #include +#include #include -PyConsole_EditorBase *PyConsole_ConsoleBase::PyConsole_Interp_CreatorBase::createEditor( PyConsole_Interp *interp, PyConsole_ConsoleBase *console ) const -{ return new PyConsole_EditorBase(interp,console); } +/*! + \class PyConsole_Console + \brief Python console widget. + + To create a Python console, just use default contstructor, specifying only a parent widget: + \code + PyConsole_Console c(myWindow); + \endcode -PyConsole_Interp *PyConsole_ConsoleBase::PyConsole_Interp_CreatorBase::createInterp( ) const -{ return new PyConsole_Interp; } + This will create a console with default editor and interpreter. + + To use custom editor and/or interpreter class with the console, you can use additional parameter + of the constructor; in this case you have to ensure that Python interpeter is initialized properly: + \code + PyConsole_Interp* interp = new PyConsole_Interp(); + interp->initialize(); + PyConsole_Console c(myWindow, new MyEditor(interp)); + \endcode +*/ /*! \brief Constructor. @@ -56,64 +60,50 @@ PyConsole_Interp *PyConsole_ConsoleBase::PyConsole_Interp_CreatorBase::createInt \param parent parent widget \param interp python interpreter */ -PyConsole_ConsoleBase::PyConsole_ConsoleBase( QWidget* parent, PyConsole_Interp* interp ) +PyConsole_Console::PyConsole_Console( QWidget* parent, PyConsole_Editor* editor ) : QWidget( parent ) { - PyConsole_ConsoleBase::PyConsole_Interp_CreatorBase crea; - defaultConstructor(interp,crea); -} - -/*! - * MUST BE NON VIRTUAL ! (called from constructor !!!!) - */ -void PyConsole_ConsoleBase::defaultConstructor( PyConsole_Interp* interp, const PyConsole_Interp_CreatorBase& crea ) -{ - PyConsole_Interp *anInterp = interp ? interp : crea.createInterp(); - // initialize Python interpretator - anInterp->initialize(); + PyConsole_Interp* interp = editor ? editor->getInterp() : new PyConsole_Interp(); + interp->initialize(); // create editor console QVBoxLayout* lay = new QVBoxLayout( this ); lay->setMargin( 0 ); - myEditor = crea.createEditor( anInterp, this ); - char* synchronous = getenv("PYTHON_CONSOLE_SYNC"); - if (synchronous && atoi(synchronous)) - { - myEditor->setIsSync(true); - } - myEditor->viewport()->installEventFilter( this ); + myEditor = editor ? editor : new PyConsole_Editor( interp, this ); + myEditor->setContextMenuPolicy( Qt::NoContextMenu ); lay->addWidget( myEditor ); + // force synchronous mode + QString synchronous = qgetenv( "PYTHON_CONSOLE_SYNC" ); + if ( !synchronous.isEmpty() && synchronous.toInt() > 0 ) + setIsSync( true ); + + // create actions createActions(); } -/** - * Protected constructor. - */ -PyConsole_ConsoleBase::PyConsole_ConsoleBase( QWidget* parent, PyConsole_Interp* /*i*/, PyConsole_EditorBase* e ) - : QWidget (parent), myEditor(e) -{} - /*! \brief Destructor. - - Does nothing for the moment. */ -PyConsole_ConsoleBase::~PyConsole_ConsoleBase() +PyConsole_Console::~PyConsole_Console() { } -PyConsole_Interp* PyConsole_ConsoleBase::getInterp() const +/*! + \brief Get Python interpreter + \return pointer to Python interpreter +*/ +PyConsole_Interp* PyConsole_Console::getInterp() const { return myEditor ? myEditor->getInterp() : 0; -} +} /*! \brief Execute python command in the interpreter. \param command string with command and arguments */ -void PyConsole_ConsoleBase::exec( const QString& command ) +void PyConsole_Console::exec( const QString& command ) { if ( myEditor ) myEditor->exec( command ); @@ -126,7 +116,7 @@ void PyConsole_ConsoleBase::exec( const QString& command ) Block execution of main application until the python command is executed. \param command string with command and arguments */ -void PyConsole_ConsoleBase::execAndWait( const QString& command ) +void PyConsole_Console::execAndWait( const QString& command ) { if ( myEditor ) myEditor->execAndWait( command ); @@ -136,11 +126,11 @@ void PyConsole_ConsoleBase::execAndWait( const QString& command ) \brief Get synchronous mode flag value. \sa setIsSync() - \return True if python console works in synchronous mode + \return \c true if python console works in synchronous mode */ -bool PyConsole_ConsoleBase::isSync() const +bool PyConsole_Console::isSync() const { - return myEditor->isSync(); + return myEditor ? myEditor->isSync() : false; } /*! @@ -153,33 +143,35 @@ bool PyConsole_ConsoleBase::isSync() const \param on synhronous mode flag */ -void PyConsole_ConsoleBase::setIsSync( const bool on ) +void PyConsole_Console::setIsSync( const bool on ) { - myEditor->setIsSync( on ); + if ( myEditor ) + myEditor->setIsSync( on ); } /*! \brief Get suppress output flag value. \sa setIsSuppressOutput() - \return True if python console output is suppressed. + \return \c true if python console output is suppressed. */ -bool PyConsole_ConsoleBase::isSuppressOutput() const +bool PyConsole_Console::isSuppressOutput() const { - return myEditor->isSuppressOutput(); + return myEditor ? myEditor->isSuppressOutput() : false; } /*! \brief Set suppress output flag value. - In case if suppress output flag is true, the python + In case if suppress output flag is \c true, the python console output suppressed. \param on suppress output flag */ -void PyConsole_ConsoleBase::setIsSuppressOutput( const bool on ) +void PyConsole_Console::setIsSuppressOutput( const bool on ) { - myEditor->setIsSuppressOutput(on); + if ( myEditor ) + myEditor->setIsSuppressOutput( on ); } /*! @@ -188,9 +180,9 @@ void PyConsole_ConsoleBase::setIsSuppressOutput( const bool on ) \sa setIsShowBanner() \return \c true if python console shows banner */ -bool PyConsole_ConsoleBase::isShowBanner() const +bool PyConsole_Console::isShowBanner() const { - return myEditor->isShowBanner(); + return myEditor ? myEditor->isShowBanner() : false; } /*! @@ -201,31 +193,49 @@ bool PyConsole_ConsoleBase::isShowBanner() const \sa isShowBanner() \param on 'show banner' flag */ -void PyConsole_ConsoleBase::setIsShowBanner( const bool on ) +void PyConsole_Console::setIsShowBanner( const bool on ) { - myEditor->setIsShowBanner( on ); + if ( myEditor ) + myEditor->setIsShowBanner( on ); +} + +/*! + \brief Returns \c true if auto-completion feature is switched on + or \c false otherwise + \sa setAutoCompletion() +*/ +bool PyConsole_Console::autoCompletion() const +{ + return myEditor ? myEditor->autoCompletion() : false; +} + +/*! + \brief Switch on/off commands auto-completion feature + \sa autoCompletion() +*/ +void PyConsole_Console::setAutoCompletion( const bool on ) +{ + if ( myEditor ) + myEditor->setAutoCompletion( on ); } /*! \brief Change the python console's font. \param f new font */ -void PyConsole_ConsoleBase::setFont( const QFont& f ) +void PyConsole_Console::setFont( const QFont& f ) { - if( myEditor ) + if ( myEditor ) myEditor->setFont( f ); } /*! \brief Get python console font. - \return current python console's font + \return current python console font */ -QFont PyConsole_ConsoleBase::font() const +QFont PyConsole_Console::font() const { - QFont res; - if( myEditor ) - res = myEditor->font(); - return res; + return myEditor ? myEditor->font() : QFont(); } /*! @@ -236,7 +246,7 @@ QFont PyConsole_ConsoleBase::font() const \param flags ORed together actions flags */ -void PyConsole_ConsoleBase::setMenuActions( const int flags ) +void PyConsole_Console::setMenuActions( const int flags ) { myActions[CopyId]->setVisible( flags & CopyId ); myActions[PasteId]->setVisible( flags & PasteId ); @@ -252,7 +262,7 @@ void PyConsole_ConsoleBase::setMenuActions( const int flags ) \return ORed together actions flags \sa setMenuActions() */ -int PyConsole_ConsoleBase::menuActions() const +int PyConsole_Console::menuActions() const { int ret = 0; ret = ret | ( myActions[CopyId]->isVisible() ? CopyId : 0 ); @@ -270,7 +280,7 @@ int PyConsole_ConsoleBase::menuActions() const Create context popup menu actions. */ -void PyConsole_ConsoleBase::createActions() +void PyConsole_Console::createActions() { QAction* a = new QAction( tr( "EDIT_COPY_CMD" ), this ); a->setStatusTip( tr( "EDIT_COPY_CMD" ) ); @@ -313,42 +323,46 @@ void PyConsole_ConsoleBase::createActions() Update context popup menu action state. */ -void PyConsole_ConsoleBase::updateActions() +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() ); + myActions[CopyId]->setEnabled( myEditor && myEditor->textCursor().hasSelection() ); + myActions[PasteId]->setEnabled( myEditor && !myEditor->isReadOnly() && !QApplication::clipboard()->text().isEmpty() ); + myActions[SelectAllId]->setEnabled( myEditor && !myEditor->document()->isEmpty() ); } /*! \brief Start python trace logging \param fileName the path to the log file */ -void PyConsole_ConsoleBase::startLog( const QString& fileName ) +void PyConsole_Console::startLog( const QString& fileName ) { - myEditor->startLog( fileName ); + if ( myEditor ) + myEditor->startLog( fileName ); } /*! \brief Stop python trace logging */ -void PyConsole_ConsoleBase::stopLog() +void PyConsole_Console::stopLog() { - myEditor->stopLog(); + if ( myEditor ) + myEditor->stopLog(); } /*! - \brief Create the context popup menu. + \brief Process context popup menu request - Fill in the popup menu with the commands. + Show the context popup menu. - \param menu context popup menu + \param event context popup menu event */ -void PyConsole_ConsoleBase::contextMenuPopup( QMenu *menu ) +void PyConsole_Console::contextMenuEvent( QContextMenuEvent* event ) { - if ( myEditor->isReadOnly() ) + if ( !myEditor || myEditor->isReadOnly() ) return; + QMenu* menu = new QMenu( this ); + menu->addAction( myActions[CopyId] ); menu->addAction( myActions[PasteId] ); menu->addAction( myActions[ClearId] ); @@ -361,53 +375,9 @@ void PyConsole_ConsoleBase::contextMenuPopup( QMenu *menu ) else menu->addAction( myActions[StopLogId] ); - Qtx::simplifySeparators( menu ); - updateActions(); -} - -PyConsole_EditorBase *PyConsole_EnhConsoleBase::PyConsole_Interp_EnhCreatorBase::createEditor( PyConsole_Interp *interp, PyConsole_ConsoleBase *console ) const -{ return new PyConsole_EnhEditorBase(interp,console); } -PyConsole_Interp *PyConsole_EnhConsoleBase::PyConsole_Interp_EnhCreatorBase::createInterp( ) const -{ return new PyConsole_EnhInterp; } - -/** - * 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_EnhConsoleBase::PyConsole_EnhConsoleBase( QWidget* parent, PyConsole_Interp* interp ) - : PyConsole_ConsoleBase( parent, interp, 0 ) -{ - PyConsole_Interp_EnhCreatorBase crea; - defaultConstructor(interp,crea); -} - -/*! - \brief Event handler. + menu->exec( event->globalPos()); - 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_EnhConsoleBase::eventFilter( QObject* o, QEvent* e ) -{ - if ( o == myEditor->viewport() && e->type() == QEvent::ContextMenu ) - { - contextMenuRequest( (QContextMenuEvent*)e ); - return true; - } - return QWidget::eventFilter( o, e ); -} - -void PyConsole_EnhConsoleBase::contextMenuRequest( QContextMenuEvent * e ) -{ - QMenu *menu(new QMenu(this)); - contextMenuPopup(menu); - menu->move(e->globalPos()); - menu->show(); + delete menu; } diff --git a/src/PyConsole/PyConsole_ConsoleBase.h b/src/PyConsole/PyConsole_Console.h similarity index 60% rename from src/PyConsole/PyConsole_ConsoleBase.h rename to src/PyConsole/PyConsole_Console.h index 0cef8f7e0..e0b111e53 100644 --- a/src/PyConsole/PyConsole_ConsoleBase.h +++ b/src/PyConsole/PyConsole_Console.h @@ -19,34 +19,26 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // - // File : PyConsole_Console.h // Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) -// -#ifndef PYCONSOLE_CONSOLEBASE_H -#define PYCONSOLE_CONSOLEBASE_H + +#ifndef PYCONSOLE_CONSOLE_H +#define PYCONSOLE_CONSOLE_H #include "PyConsole.h" #include -#include #include +class QMenu; + class PyConsole_Interp; -class PyConsole_EditorBase; +class PyConsole_Editor; -class PYCONSOLE_EXPORT PyConsole_ConsoleBase : public QWidget +class PYCONSOLE_EXPORT PyConsole_Console : public QWidget { Q_OBJECT -public: - - struct PyConsole_Interp_CreatorBase - { - virtual PyConsole_EditorBase *createEditor( PyConsole_Interp *interp, PyConsole_ConsoleBase *console ) const; - virtual PyConsole_Interp *createInterp( ) const; - }; - public: //! Context popup menu actions flags enum @@ -62,11 +54,11 @@ public: }; public: - PyConsole_ConsoleBase( QWidget* parent, PyConsole_Interp* interp = 0 ); - virtual ~PyConsole_ConsoleBase(); + PyConsole_Console( QWidget* parent, PyConsole_Editor* editor = 0 ); + virtual ~PyConsole_Console(); - //! \brief Get python interperter PyConsole_Interp* getInterp() const; + QFont font() const; virtual void setFont( const QFont& ); @@ -79,6 +71,9 @@ public: bool isShowBanner() const; void setIsShowBanner( const bool ); + void setAutoCompletion( bool ); + bool autoCompletion() const; + void exec( const QString& ); void execAndWait( const QString& ); @@ -88,40 +83,15 @@ public: void startLog( const QString& ); void stopLog(); - virtual void contextMenuPopup( QMenu* ); - protected: void createActions(); void updateActions(); - //! MUST BE NON VIRTUAL ! (called from constructor !!!!) - void defaultConstructor( PyConsole_Interp* interp, const PyConsole_Interp_CreatorBase& crea ); - PyConsole_ConsoleBase( QWidget* parent, PyConsole_Interp*, PyConsole_EditorBase*); - PyConsole_EditorBase* 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_EnhConsoleBase : public PyConsole_ConsoleBase -{ - Q_OBJECT -public: + virtual void contextMenuEvent( QContextMenuEvent* ); - struct PyConsole_Interp_EnhCreatorBase : public PyConsole_Interp_CreatorBase - { - virtual PyConsole_EditorBase *createEditor( PyConsole_Interp *interp, PyConsole_ConsoleBase *console ) const; - virtual PyConsole_Interp *createInterp( ) const; - }; - -public: - PyConsole_EnhConsoleBase( QWidget* parent, PyConsole_Interp* interp = 0 ); - virtual ~PyConsole_EnhConsoleBase() {} - virtual bool eventFilter( QObject * o, QEvent * e ); - virtual void contextMenuRequest( QContextMenuEvent * e ) ; +protected: + PyConsole_Editor* myEditor; //!< python console editor widget + QMap myActions; //!< menu actions list }; -#endif // PYCONSOLE_CONSOLEBASE_H +#endif // PYCONSOLE_CONSOLE_H diff --git a/src/PyConsole/PyConsole_EditorBase.cxx b/src/PyConsole/PyConsole_Editor.cxx similarity index 57% rename from src/PyConsole/PyConsole_EditorBase.cxx rename to src/PyConsole/PyConsole_Editor.cxx index 0c5e915c0..7d540f62f 100644 --- a/src/PyConsole/PyConsole_EditorBase.cxx +++ b/src/PyConsole/PyConsole_Editor.cxx @@ -19,11 +19,9 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // - -// SALOME SALOMEGUI : implementation of desktop and GUI kernel // File : PyConsole_Editor.cxx // Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) -// + /*! \class PyConsole_Editor \brief Python command line interpreter front-end GUI widget. @@ -86,30 +84,28 @@ - : copy - : cut - : paste + - : performs auto-completion + - : undoes auto-completion */ -#include "PyConsole_Interp.h" // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!! -#include "PyConsole_EditorBase.h" +#include "PyConsole_Editor.h" +#include "PyConsole_Interp.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 #include @@ -134,23 +130,20 @@ static QString DOTS_PROMPT = "... "; void staticCallbackStdout( void* data, char* c ) { - if(!((PyConsole_EditorBase*)data)->isSuppressOutput()) { - PyConsole_EditorBase* e = (PyConsole_EditorBase*)data; - e->putLog( fromUtf8(c) ); - QApplication::postEvent( e, new PrintEvent( fromUtf8(c), false ) ); + if(!((PyConsole_Editor*)data)->isSuppressOutput()) { + PyConsole_Editor* e = (PyConsole_Editor*)data; + QApplication::postEvent( e, new PyConsole_PrintEvent( fromUtf8(c), false ) ); } } void staticCallbackStderr( void* data, char* c ) { - if(!((PyConsole_EditorBase*)data)->isSuppressOutput()) { - PyConsole_EditorBase* e = (PyConsole_EditorBase*)data; - e->putLog( fromUtf8(c) ); - QApplication::postEvent( e, new PrintEvent( fromUtf8(c), true ) ); + if(!((PyConsole_Editor*)data)->isSuppressOutput()) { + PyConsole_Editor* e = (PyConsole_Editor*)data; + QApplication::postEvent( e, new PyConsole_PrintEvent( fromUtf8(c), true ) ); } } - /*! \brief Constructor. @@ -158,19 +151,21 @@ void staticCallbackStderr( void* data, char* c ) \param theInterp python interper \param theParent parent widget */ -PyConsole_EditorBase::PyConsole_EditorBase( PyConsole_Interp* theInterp, - QWidget* theParent ) +PyConsole_Editor::PyConsole_Editor( PyConsole_Interp* theInterp, + QWidget* theParent ) : QTextEdit( theParent ), - myInterp( 0 ), + myInterp( theInterp ), myCmdInHistory( -1 ), myEventLoop( 0 ), myShowBanner( true ), myIsSync( true ), - myIsSuppressOutput( false ) + myIsSuppressOutput( false ), + myMultiLinePaste( false ), + myAutoCompletion( false ), + myTabMode( false ), + myComplCursorPos( -1 ) { - QString fntSet( "" ); - QFont aFont ( Qtx::stringToFont(fntSet) ); - setFont( aFont ); + setFont( QFont( "Courier", 11 ) ); // default font setUndoRedoEnabled( false ); myPrompt = READY_PROMPT; @@ -178,17 +173,28 @@ PyConsole_EditorBase::PyConsole_EditorBase( PyConsole_Interp* theInterp, setWordWrapMode( QTextOption::WrapAnywhere ); setAcceptRichText( false ); - theInterp->setvoutcb( staticCallbackStdout, this ); - theInterp->setverrcb( staticCallbackStderr, this ); - - // san - This is necessary for troubleless initialization - onPyInterpChanged( theInterp ); + // set callbacks to interpeter + myInterp->setvoutcb( staticCallbackStdout, this ); + myInterp->setverrcb( staticCallbackStderr, this ); + // print banner + if ( isShowBanner() ) + addText( banner() ); + // 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(); } /*! \brief Destructor. */ -PyConsole_EditorBase::~PyConsole_EditorBase() +PyConsole_Editor::~PyConsole_Editor() { myInterp = 0; } @@ -196,7 +202,7 @@ PyConsole_EditorBase::~PyConsole_EditorBase() /*! \brief Get Python interpreter */ -PyConsole_Interp* PyConsole_EditorBase::getInterp() const +PyConsole_Interp* PyConsole_Editor::getInterp() const { return myInterp; } @@ -205,9 +211,9 @@ PyConsole_Interp* PyConsole_EditorBase::getInterp() const \brief Get synchronous mode flag value. \sa setIsSync() - \return True if python console works in synchronous mode + \return \c true if python console works in synchronous mode */ -bool PyConsole_EditorBase::isSync() const +bool PyConsole_Editor::isSync() const { return myIsSync; } @@ -222,7 +228,7 @@ bool PyConsole_EditorBase::isSync() const \param on synhronous mode flag */ -void PyConsole_EditorBase::setIsSync( const bool on ) +void PyConsole_Editor::setIsSync( const bool on ) { myIsSync = on; } @@ -233,7 +239,7 @@ void PyConsole_EditorBase::setIsSync( const bool on ) \sa setIsSuppressOutput() \return \c true if python console output is suppressed. */ -bool PyConsole_EditorBase::isSuppressOutput() const +bool PyConsole_Editor::isSuppressOutput() const { return myIsSuppressOutput; } @@ -241,12 +247,12 @@ bool PyConsole_EditorBase::isSuppressOutput() const /*! \brief Set suppress output flag value. - In case if suppress output flag is true, the python + In case if suppress output flag is \c true, the python console output suppressed. \param on suppress output flag */ -void PyConsole_EditorBase::setIsSuppressOutput( const bool on ) +void PyConsole_Editor::setIsSuppressOutput( const bool on ) { myIsSuppressOutput = on; } @@ -257,7 +263,7 @@ void PyConsole_EditorBase::setIsSuppressOutput( const bool on ) \sa setIsShowBanner() \return \c true if python console shows banner */ -bool PyConsole_EditorBase::isShowBanner() const +bool PyConsole_Editor::isShowBanner() const { return myShowBanner; } @@ -270,7 +276,7 @@ bool PyConsole_EditorBase::isShowBanner() const \sa isShowBanner() \param on 'show banner' flag */ -void PyConsole_EditorBase::setIsShowBanner( const bool on ) +void PyConsole_Editor::setIsShowBanner( const bool on ) { if ( myShowBanner != on ) { myShowBanner = on; @@ -278,13 +284,33 @@ void PyConsole_EditorBase::setIsShowBanner( const bool on ) } } +/*! + \brief Switch on/off commands auto-completion feature + \sa autoCompletion() +*/ +void PyConsole_Editor::setAutoCompletion( bool on ) +{ + myAutoCompletion = on; + document()->setUndoRedoEnabled( myAutoCompletion ); +} + +/*! + \brief Returns \c true if auto-completion feature is switched on + or \c false otherwise + \sa setAutoCompletion() +*/ +bool PyConsole_Editor::autoCompletion() const +{ + return myAutoCompletion; +} + /*! \brief Check if trace logging is switched on. \sa startLog(), stopLog() \return \c true if trace logging is switched on */ -bool PyConsole_EditorBase::isLogging() const +bool PyConsole_Editor::isLogging() const { return !myLogFile.isEmpty(); } @@ -293,10 +319,10 @@ bool PyConsole_EditorBase::isLogging() const \brief Get size hint for the Python console window \return size hint value */ -QSize PyConsole_EditorBase::sizeHint() const +QSize PyConsole_Editor::sizeHint() const { QFontMetrics fm( font() ); - int nbLines = ( isShowBanner() ? myBanner.split("\n").count() : 0 ) + 1; + int nbLines = ( isShowBanner() ? banner().split("\n").count() : 0 ) + 1; QSize s(100, fm.lineSpacing()*nbLines); return s; } @@ -304,24 +330,24 @@ QSize PyConsole_EditorBase::sizeHint() const /*! \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 + \param newBlock if \c true, then the string is printed on a new line + \param isError if \c true, the text is printed in dark red */ -void PyConsole_EditorBase::addText( const QString& str, +void PyConsole_Editor::addText( const QString& str, const bool newBlock, - const bool isError) + const bool isError ) { - QTextCursor theCursor(textCursor()); + QTextCursor aCursor = textCursor(); QTextCharFormat cf; moveCursor( QTextCursor::End ); if ( newBlock ) - theCursor.insertBlock(); - if (isError) - cf.setForeground(QBrush(Qt::red)); + aCursor.insertBlock(); + if ( isError ) + cf.setForeground( QBrush( Qt::red ) ); else - cf.setForeground(QBrush(Qt::black)); - theCursor.insertText( str, cf); + cf.setForeground( QBrush( Qt::black ) ); + aCursor.insertText( str, cf ); moveCursor( QTextCursor::End ); ensureCursorVisible(); } @@ -333,7 +359,7 @@ void PyConsole_EditorBase::addText( const QString& str, !!! WARNING: doesn't work properly with multi-line commands. !!! */ -void PyConsole_EditorBase::exec( const QString& command ) +void PyConsole_Editor::exec( const QString& command ) { if ( isReadOnly() ) { // some interactive command is being executed in this editor... @@ -341,16 +367,21 @@ void PyConsole_EditorBase::exec( const QString& command ) 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"; @@ -361,26 +392,76 @@ void PyConsole_EditorBase::exec( const QString& command ) addText( ( i == 0 ? READY_PROMPT : DOTS_PROMPT ) + lines[i], i != 0 ); putLog( QString( "%1%2\n" ).arg( i == 0 ? READY_PROMPT : DOTS_PROMPT ).arg( lines[i] ) ); } + // 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 ) ); + PyInterp_Dispatcher::Get()->Exec( createCmdRequest( cmd ) ); } /*! \brief Create request to the python dispatcher for the command execution. - \param command python command to be executed */ -PyInterp_Request* PyConsole_EditorBase::createRequest( const QString& command ) +PyInterp_Request* PyConsole_Editor::createCmdRequest( const QString& command ) +{ + return new PyConsole_ExecCommand( myInterp, command, this, isSync() ); +} + +/*! + \brief Create the Python request that will be posted to the interpreter to + get the completions. + \param input line entered by the user at the time was pressed + \return completion command + \sa CompletionCommand +*/ +PyInterp_Request* PyConsole_Editor::createTabRequest( const QString& input ) { - return new ExecCommand( myInterp, command, this, isSync() ); + // valid separators + static QStringList separators; + if ( separators.isEmpty() ) { + separators << " " << "(" << "[" << "+" << "-" << "*" << "/" << ";" << "^" << "="; + } + + // 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; + foreach ( QString separator, separators ) { + int j = input2.lastIndexOf( separator ); + if ( j > lastSp ) + lastSp = j; + } + if ( lastSp >= 0 ) + input2 = input.mid( lastSp + 1 ); + + // detect a qualified name (with a point) + int lastPt = input2.lastIndexOf( "." ); + + if ( lastPt != -1 ) { + // split the 2 surrounding parts of the qualified name + myComplBeforePoint = input2.left( lastPt ); + myComplAfterPoint = input2.mid( lastPt+1 ); + } + else { + // no point found - do a global matching + // (the following will call dir() with an empty string) + myComplAfterPoint = input2; + myComplBeforePoint = ""; + } + + return new PyConsole_CompletionCommand( myInterp, myComplBeforePoint, + myComplAfterPoint, this, isSync() ); } /*! @@ -389,10 +470,10 @@ PyInterp_Request* PyConsole_EditorBase::createRequest( const QString& command ) \param command python command to be executed */ -void PyConsole_EditorBase::execAndWait( const QString& command ) +void PyConsole_Editor::execAndWait( const QString& command ) { // already running ? - if( myEventLoop ) + if ( myEventLoop ) return; // create new event loop @@ -414,16 +495,16 @@ void PyConsole_EditorBase::execAndWait( const QString& command ) } /*! - \brief Process "Enter" key press event. + \brief Process key press event. Execute the command entered by the user. */ -void PyConsole_EditorBase::handleReturn() +void PyConsole_Editor::handleReturn() { // Position cursor at the end - QTextCursor curs(textCursor()); - curs.movePosition(QTextCursor::End); - setTextCursor(curs); + QTextCursor aCursor = textCursor(); + aCursor.movePosition( QTextCursor::End ); + setTextCursor( aCursor ); // get last line QTextBlock par = document()->end().previous(); @@ -431,8 +512,10 @@ void PyConsole_EditorBase::handleReturn() // 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 ); @@ -443,12 +526,78 @@ void PyConsole_EditorBase::handleReturn() // 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 ) ); + PyInterp_Dispatcher::Get()->Exec( createCmdRequest( myCommandBuffer ) ); +} + +/*! + \brief Process key press event. + + Perform auto-completion of the currently entered command, if this feature is enabled +*/ +void PyConsole_Editor::handleTab() +{ + if ( !autoCompletion() ) + return; // auto-completion feature is disabled + + if ( myTabMode ) + return; // already in tab mode + + QTextCursor aCursor = textCursor(); + + // move cursor to the end of input + aCursor.movePosition( QTextCursor::End ); + setTextCursor( aCursor ); + + // save cursor position if needed + if ( myComplCursorPos == -1 ) + myComplCursorPos = textCursor().position(); + + // get last line + QTextBlock par = document()->end().previous(); + if ( !par.isValid() ) return; // empty line + + // switch to completion mode + myTabMode = true; + + // get currently entered command + QString cmd = par.text().mid( promptSize() ); + + // post completion request + // editor will be informed that completion has been done via a custom event + PyInterp_Dispatcher::Get()->Exec( createTabRequest( cmd ) ); +} + +/*! + \brief Process key press event. + + Undoe last auto-completion +*/ +void PyConsole_Editor::handleBackTab() +{ + if ( !autoCompletion() ) + return; // auto-completion feature is disabled + + QTextCursor aCursor = textCursor(); + + if ( myComplCursorPos == -1 ) + return; // invalid cursor position + + // ensure cursor is at the end of command line + aCursor.setPosition( myComplCursorPos ); + aCursor.movePosition( QTextCursor::EndOfLine ); + //setCursor( aCursor ); + + // delete last completed text + int i = aCursor.position() - myComplCursorPos; + aCursor.movePosition( QTextCursor::Left, QTextCursor::KeepAnchor, i ); + aCursor.removeSelectedText(); + myComplCursorPos = -1; } /*! @@ -457,16 +606,18 @@ void PyConsole_EditorBase::handleReturn() Paste dragged text. \param event drop event */ -void PyConsole_EditorBase::dropEvent( QDropEvent* event ) +void PyConsole_Editor::dropEvent( QDropEvent* event ) { // get the initial drop position QPoint pos = event->pos(); - QTextCursor cur = cursorForPosition( event->pos() ); + QTextCursor aCursor = 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() ) { + if ( aCursor.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(), @@ -475,31 +626,48 @@ void PyConsole_EditorBase::dropEvent( QDropEvent* event ) event->keyboardModifiers(), event->type() ); QTextEdit::dropEvent( &de ); + // accept the original event event->acceptProposedAction(); } +/*! + \brief Process mouse press event + + Clear the completion when any mouse button is pressed. + + \param e mouse press event +*/ +void PyConsole_Editor::mousePressEvent( QMouseEvent* event ) +{ + if ( autoCompletion() ) { + clearCompletion(); + myComplCursorPos = -1; + } + QTextEdit::mousePressEvent( event ); +} + /*! \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_EditorBase::mouseReleaseEvent( QMouseEvent* 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() ); + QTextCursor aCursor = 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() ) { + if ( aCursor.position() < document()->end().previous().position() + promptSize() ) { moveCursor( QTextCursor::End ); } else { - setTextCursor( cur ); + setTextCursor( aCursor ); } const QMimeData* md = QApplication::clipboard()->mimeData( QApplication::clipboard()->supportsSelection() ? QClipboard::Selection : QClipboard::Clipboard ); @@ -514,11 +682,11 @@ void PyConsole_EditorBase::mouseReleaseEvent( QMouseEvent* event ) /*! \brief Check if the string is command. - Return True if the string \a str is likely to be the command + Return \c 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_EditorBase::isCommand( const QString& str ) const +bool PyConsole_Editor::isCommand( const QString& str ) const { return str.startsWith( READY_PROMPT ) || str.startsWith( DOTS_PROMPT ); } @@ -528,14 +696,15 @@ bool PyConsole_EditorBase::isCommand( const QString& str ) const Implement navigation, history browsing, copy/paste and other common operations. + \param event keyboard event */ -void PyConsole_EditorBase::keyPressEvent( QKeyEvent* event ) +void PyConsole_Editor::keyPressEvent( QKeyEvent* event ) { // get cursor position - QTextCursor cur = textCursor(); - int curLine = cur.blockNumber(); - int curCol = cur.columnNumber(); + QTextCursor aCursor = textCursor(); + int curLine = aCursor.blockNumber(); + int curCol = aCursor.columnNumber(); // get last edited line int endLine = document()->blockCount()-1; @@ -548,6 +717,32 @@ void PyConsole_EditorBase::keyPressEvent( QKeyEvent* event ) // check if is pressed bool shftPressed = event->modifiers() & Qt::ShiftModifier; + if ( autoCompletion() ) { + // auto-completion support + if ( aKey == Qt::Key_Tab && !shftPressed ) { + // process key + if ( !ctrlPressed ) { + handleTab(); + } + else { + clearCompletion(); + handleBackTab(); + } + return; + } + + // If is not pressed (or if something else is pressed with ), + // or if is not pressed alone, we have to clear completion + if ( !ctrlPressed || ( ctrlPressed && aKey != Qt::Key_Control ) ) { + clearCompletion(); + myComplCursorPos = -1; + } + + // Discard pressed alone: + if ( aKey == Qt::Key_Control ) + return; + } + if ( aKey == Qt::Key_Escape || ( ctrlPressed && aKey == -1 ) ) { // process + key-binding and key: clear current command myCommandBuffer.truncate( 0 ); @@ -707,15 +902,15 @@ void PyConsole_EditorBase::keyPressEvent( QKeyEvent* event ) if ( !shftPressed ) { if ( curCol < txt.length() ) { if ( isCommand( txt ) && curCol < promptSize() ) { - cur.setPosition( cur.block().position() + promptSize() ); - setTextCursor( cur ); + aCursor.setPosition( aCursor.block().position() + promptSize() ); + setTextCursor( aCursor ); break; } } else { if ( curLine < endLine && isCommand( textCursor().block().next().text() ) ) { - cur.setPosition( cur.position() + promptSize()+1 ); - setTextCursor( cur ); + aCursor.setPosition( aCursor.position() + promptSize()+1 ); + setTextCursor( aCursor ); horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() ); break; } @@ -736,24 +931,24 @@ void PyConsole_EditorBase::keyPressEvent( QKeyEvent* event ) } else if ( shftPressed || ctrlPressed ) { bool moved = false; - qreal lastY = cursorRect( cur ).top(); + qreal lastY = cursorRect( aCursor ).top(); qreal distance = 0; // move using movePosition to keep the cursor's x do { - qreal y = cursorRect( cur ).top(); + qreal y = cursorRect( aCursor ).top(); distance += qAbs( y - lastY ); lastY = y; - moved = cur.movePosition( QTextCursor::Up, - shftPressed ? QTextCursor::KeepAnchor : - QTextCursor::MoveAnchor ); + moved = aCursor.movePosition( QTextCursor::Up, + shftPressed ? QTextCursor::KeepAnchor : + QTextCursor::MoveAnchor ); } while ( moved && distance < viewport()->height() ); if ( moved ) { - cur.movePosition( QTextCursor::Down, - shftPressed ? QTextCursor::KeepAnchor : - QTextCursor::MoveAnchor ); + aCursor.movePosition( QTextCursor::Down, + shftPressed ? QTextCursor::KeepAnchor : + QTextCursor::MoveAnchor ); verticalScrollBar()->triggerAction( QAbstractSlider::SliderPageStepSub ); } - setTextCursor( cur ); + setTextCursor( aCursor ); } else { if ( myCmdInHistory < 0 && myHistory.count() > 0 ) { @@ -790,24 +985,24 @@ void PyConsole_EditorBase::keyPressEvent( QKeyEvent* event ) } else if ( shftPressed || ctrlPressed ) { bool moved = false; - qreal lastY = cursorRect( cur ).top(); + qreal lastY = cursorRect( aCursor ).top(); qreal distance = 0; // move using movePosition to keep the cursor's x do { - qreal y = cursorRect( cur ).top(); + qreal y = cursorRect( aCursor ).top(); distance += qAbs( y - lastY ); lastY = y; - moved = cur.movePosition( QTextCursor::Down, - shftPressed ? QTextCursor::KeepAnchor : - QTextCursor::MoveAnchor ); + moved = aCursor.movePosition( QTextCursor::Down, + shftPressed ? QTextCursor::KeepAnchor : + QTextCursor::MoveAnchor ); } while ( moved && distance < viewport()->height() ); if ( moved ) { - cur.movePosition( QTextCursor::Up, - shftPressed ? QTextCursor::KeepAnchor : - QTextCursor::MoveAnchor ); + aCursor.movePosition( QTextCursor::Up, + shftPressed ? QTextCursor::KeepAnchor : + QTextCursor::MoveAnchor ); verticalScrollBar()->triggerAction( QAbstractSlider::SliderPageStepSub ); } - setTextCursor( cur ); + setTextCursor( aCursor ); } else { if ( myCmdInHistory >= 0 ) { @@ -840,15 +1035,15 @@ void PyConsole_EditorBase::keyPressEvent( QKeyEvent* event ) if ( isCommand( txt ) ) { if ( shftPressed ) { if ( curCol > promptSize() ) { - cur.movePosition( QTextCursor::StartOfLine, QTextCursor::KeepAnchor ); - cur.movePosition( QTextCursor::Right, QTextCursor::KeepAnchor, promptSize() ); + aCursor.movePosition( QTextCursor::StartOfLine, QTextCursor::KeepAnchor ); + aCursor.movePosition( QTextCursor::Right, QTextCursor::KeepAnchor, promptSize() ); } } else { - cur.movePosition( QTextCursor::StartOfLine ); - cur.movePosition( QTextCursor::Right, QTextCursor::MoveAnchor, promptSize() ); + aCursor.movePosition( QTextCursor::StartOfLine ); + aCursor.movePosition( QTextCursor::Right, QTextCursor::MoveAnchor, promptSize() ); } - setTextCursor( cur ); + setTextCursor( aCursor ); } else { moveCursor( QTextCursor::StartOfBlock, @@ -876,18 +1071,18 @@ void PyConsole_EditorBase::keyPressEvent( QKeyEvent* event ) // - with modifier key pressed: delete text from the cursor to the line beginning // works only for last (command) line { - if ( cur.hasSelection() ) { + if ( aCursor.hasSelection() ) { cut(); } - else if ( cur.position() > document()->end().previous().position() + promptSize() ) { + else if ( aCursor.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 ); + aCursor.setPosition( document()->end().previous().position() + promptSize(), + QTextCursor::KeepAnchor ); + setTextCursor( aCursor ); textCursor().removeSelectedText(); } else { @@ -895,8 +1090,8 @@ void PyConsole_EditorBase::keyPressEvent( QKeyEvent* event ) } } else { - cur.setPosition( document()->end().previous().position() + promptSize() ); - setTextCursor( cur ); + aCursor.setPosition( document()->end().previous().position() + promptSize() ); + setTextCursor( aCursor ); horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() ); } break; @@ -908,10 +1103,10 @@ void PyConsole_EditorBase::keyPressEvent( QKeyEvent* event ) // - with modifier key pressed: delete text from the cursor to the end of line // works only for last (command) line { - if ( cur.hasSelection() ) { + if ( aCursor.hasSelection() ) { cut(); } - else if ( cur.position() > document()->end().previous().position() + promptSize()-1 ) { + else if ( aCursor.position() > document()->end().previous().position() + promptSize()-1 ) { if ( shftPressed ) { moveCursor( QTextCursor::NextWord, QTextCursor::KeepAnchor ); textCursor().removeSelectedText(); @@ -925,8 +1120,8 @@ void PyConsole_EditorBase::keyPressEvent( QKeyEvent* event ) } } else { - cur.setPosition( document()->end().previous().position() + promptSize() ); - setTextCursor( cur ); + aCursor.setPosition( document()->end().previous().position() + promptSize() ); + setTextCursor( aCursor ); horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() ); } break; @@ -946,6 +1141,8 @@ void PyConsole_EditorBase::keyPressEvent( QKeyEvent* event ) QTextEdit::keyPressEvent( event ); break; } + default: + break; } } @@ -953,16 +1150,81 @@ void PyConsole_EditorBase::keyPressEvent( QKeyEvent* event ) \brief Handle notification event coming from Python dispatcher. \param event notification event */ -void PyConsole_EditorBase::customEvent( QEvent* 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 PyConsole_PrintEvent::EVENT_ID: + { + PyConsole_PrintEvent* pe = (PyConsole_PrintEvent*)event; + putLog( pe->text()); + addText( pe->text(), false, pe->isError() ); + return; + } + case PyConsole_CompletionEvent::EVENT_ID: + { + PyConsole_CompletionEvent* ce = (PyConsole_CompletionEvent*)event; + bool status = ce->status(); + QStringList matches = ce->matches(); + QString doc = ce->doc(); + + if ( status ) { + // completion was successful + QTextCursor aCursor = textCursor(); + + if ( matches.isEmpty() ) { + // completion successful but there are no matches. + myTabMode = false; + myComplCursorPos = -1; + return; + } + + if ( matches.size() == 1 ) { + // there's only one match - complete directly and update doc string window + aCursor.insertText( matches[0].mid( myComplAfterPoint.size() ) ); + myTabMode = false; + if ( doc.isEmpty() ) + emit updateDoc( formatDocHTML( QString( "(%1)\n" ).arg( tr( "NO_DOC_AVAILABLE" ) ) ) ); + else + emit updateDoc( formatDocHTML( doc ) ); + } + else { + // there are several matches + + // detect if there is a common base to all available completion + // in this case append this base to the text + QString base = extractCommon( matches ); + aCursor.insertText( base.mid( myComplAfterPoint.size() ) ); + + // if this happens to match exactly the first completion + // also provide doc + if ( base == matches[0] ) + emit updateDoc( formatDocHTML( doc ) ); + + // print all matching completion in a "undo-able" block + int cursorPos = aCursor.position(); + aCursor.insertBlock(); + aCursor.beginEditBlock(); + + // insert all matches + QTextCharFormat cf; + cf.setForeground( QBrush( Qt::darkGreen ) ); + aCursor.setCharFormat( cf ); + aCursor.insertText( formatCompletion( matches ) ); + aCursor.endEditBlock(); + + // position cursor where it was before inserting the completion list + aCursor.setPosition( cursorPos ); + setTextCursor( aCursor ); + } + } + else { + // completion failed + myTabMode = false; + myComplCursorPos = -1; } + return; + } case PyInterp_Event::ES_OK: case PyInterp_Event::ES_ERROR: { @@ -983,6 +1245,8 @@ void PyConsole_EditorBase::customEvent( QEvent* event ) // stop event loop (if running) if ( myEventLoop ) myEventLoop->exit(); + // if we are in multi_paste_mode, process the next item + multiLineProcessNextLine(); break; } case PyInterp_Event::ES_INCOMPLETE: @@ -1004,6 +1268,8 @@ void PyConsole_EditorBase::customEvent( QEvent* event ) // stop event loop (if running) if ( myEventLoop ) myEventLoop->exit(); + // if we are in multi_paste_mode, process the next item + multiLineProcessNextLine(); break; } default: @@ -1024,69 +1290,27 @@ void PyConsole_EditorBase::customEvent( QEvent* event ) } } -/*! - \brief Handle Python interpreter change. - - Perform initialization actions if the interpreter is changed. - \param interp python interpreter is being set -*/ -void PyConsole_EditorBase::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_EditorBase::cut() + Warning! In Qt this method is not virtual. +*/ +void PyConsole_Editor::cut() { - QTextCursor cur = textCursor(); - if ( cur.hasSelection() ) { - QApplication::clipboard()->setText( cur.selectedText() ); - int startSelection = cur.selectionStart(); + QTextCursor aCursor = textCursor(); + if ( aCursor.hasSelection() ) { + QApplication::clipboard()->setText( aCursor.selectedText() ); + int startSelection = aCursor.selectionStart(); if ( startSelection < document()->end().previous().position() + promptSize() ) startSelection = document()->end().previous().position() + promptSize(); - int endSelection = cur.selectionEnd(); + int endSelection = aCursor.selectionEnd(); if ( endSelection < document()->end().previous().position() + promptSize() ) endSelection = document()->end().previous().position() + promptSize(); - cur.setPosition( startSelection ); - cur.setPosition( endSelection, QTextCursor::KeepAnchor ); + aCursor.setPosition( startSelection ); + aCursor.setPosition( endSelection, QTextCursor::KeepAnchor ); horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() ); - setTextCursor( cur ); + setTextCursor( aCursor ); textCursor().removeSelectedText(); } } @@ -1095,22 +1319,22 @@ void PyConsole_EditorBase::cut() \brief "Paste" operation. Reimplemented from Qt. - Warning! In Qt4 this method is not virtual. - */ -void PyConsole_EditorBase::paste() + Warning! In Qt this method is not virtual. +*/ +void PyConsole_Editor::paste() { - QTextCursor cur = textCursor(); - if ( cur.hasSelection() ) { - int startSelection = cur.selectionStart(); + QTextCursor aCursor = textCursor(); + if ( aCursor.hasSelection() ) { + int startSelection = aCursor.selectionStart(); if ( startSelection < document()->end().previous().position() + promptSize() ) startSelection = document()->end().previous().position() + promptSize(); - int endSelection = cur.selectionEnd(); + int endSelection = aCursor.selectionEnd(); if ( endSelection < document()->end().previous().position() + promptSize() ) endSelection = document()->end().previous().position() + promptSize(); - cur.setPosition( startSelection ); - cur.setPosition( endSelection, QTextCursor::KeepAnchor ); + aCursor.setPosition( startSelection ); + aCursor.setPosition( endSelection, QTextCursor::KeepAnchor ); horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() ); - setTextCursor( cur ); + setTextCursor( aCursor ); textCursor().removeSelectedText(); } if ( textCursor().position() < document()->end().previous().position() + promptSize() ) @@ -1122,68 +1346,105 @@ void PyConsole_EditorBase::paste() \brief "Clear" operation. Reimplemented from Qt. - Warning! In Qt4 this method is not virtual. - */ -void PyConsole_EditorBase::clear() + Warning! In Qt this method is not virtual. +*/ +void PyConsole_Editor::clear() { QTextEdit::clear(); if ( isShowBanner() ) - addText( myBanner ); + addText( banner() ); myPrompt = READY_PROMPT; addText( myPrompt ); } /*! - \brief "Dump commands" operation. - */ -void PyConsole_EditorBase::dumpImpl(const QString& fileName) + \brief Dumps recorded Python commands to the file + \param fileName path to the dump file + \return \c true if dump operation succeeded or \c false otherwise +*/ +bool PyConsole_Editor::dump( const QString& fileName ) { + bool ok = false; if ( !fileName.isEmpty() ) { QFile file( fileName ); - if ( !file.open( QFile::WriteOnly ) ) - return; - - QTextStream out (&file); - - for ( int i=0; idump( fileName ); - else - QMessageBox::warning(this,tr("WARNING"),tr("Python file has not been written")); + return QFileDialog::getSaveFileName( this, + tr( "GET_PYTHON_TRACE_FILENAME" ), + QString(), + QString( "%1 (*.log *.txt)" ).arg( tr( "LOG_FILES" ) ) ); } /*! \brief Start python trace logging \param fileName the path to the log file + \return \c true if operation succeeded or \c false otherwise + (for example, if file is not writeable) \sa stopLog() */ -bool PyConsole_EditorBase::startLogImpl( const QString& fileName ) +bool PyConsole_Editor::startLog( const QString& fileName ) { + // stop possibly already running logging + if ( isLogging() ) + stopLog(); + bool ok = false; if ( !fileName.isEmpty() ) { QFile file( fileName ); @@ -1196,65 +1457,244 @@ bool PyConsole_EditorBase::startLogImpl( const QString& fileName ) return ok; } - -/*! - \brief Start python trace logging - \param fileName the path to the log file - \sa stopLog() - */ -bool PyConsole_EditorBase::startLog( const QString& fileName ) -{ - return startLogImpl(fileName); -} - /*! - \brief Start python trace logging - \sa stopLog() - */ -void PyConsole_EditorBase::startLog() + \brief Start log action slot +*/ +void PyConsole_Editor::startLog() { - startLogSlot(); -} + forever { + // get file name + QString fileName = getLogFileName(); -void PyConsole_EditorBase::startLogSlot() -{ - while (1) - { - QString fileName(QFileDialog::getSaveFileName(this,tr("Choose python file where to store log"),QString(),tr("Log files ext (*.log *.txt)"))); - if ( !fileName.isEmpty() ) - { - if ( startLogImpl( fileName ) ) - break; - else - QMessageBox::warning(this,tr("WARNING"),tr("Log file is not writable")); - } - else - break; - } + if ( fileName.isEmpty() ) + break; // cancelled + + if ( startLog( fileName ) ) + break; + else + QMessageBox::warning( this, + tr( "WARNING" ), + tr( "File is not writable" ) ); + } } /*! - \brief "Stop log" operation. - \sa startLog() - */ -void PyConsole_EditorBase::stopLog() + \brief Stop log action slot + + Stops Python trace logging. +*/ +void PyConsole_Editor::stopLog() { myLogFile = QString(); } /*! - \brief Put string to the log file - */ -void PyConsole_EditorBase::putLog( const QString& s ) + \brief Put data to the log file +*/ +void PyConsole_Editor::putLog( const QString& s ) { if ( !myLogFile.isEmpty() ) { QFile file( myLogFile ); if ( !file.open( QFile::Append ) ) return; - QTextStream out (&file); + QTextStream out( &file ); out << s; file.close(); } } + +/*! + \brief Handle properly multi-line pasting. Qt documentation recommends overriding this function. + If the pasted text doesn't contain a line return, no special treatment is done. + \param source +*/ +void PyConsole_Editor::insertFromMimeData(const QMimeData* source) +{ + if ( myMultiLinePaste ) + return; + + if ( source->hasText() ) { + QString s = source->text(); + if ( s.contains( "\n" ) ) + multilinePaste( s ); + else + QTextEdit::insertFromMimeData( source ); + } + else { + QTextEdit::insertFromMimeData( source ); + } +} + +/*! + Start multi-line paste operation + \internal +*/ +void PyConsole_Editor::multilinePaste( const QString& s ) +{ + // Turn on multi line pasting mode + myMultiLinePaste = true; + + // Split string data to lines + 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 + // something was already there + QMimeData source; + source.setText( lst[0] ); + QTextEdit::insertFromMimeData( &source ); + + // Prepare what will have to be executed after the first line + myMultiLineContent.clear(); + for ( int i = 1; i < lst.size(); ++i ) + myMultiLineContent.enqueue( lst[i] ); + + // Trigger the execution of the first (mixed) line + handleReturn(); + + // See customEvent() and multiLineProcessNext() for the rest of the handling. +} + +/*! + \brief Process the next line in the queue of multi-line paste operation; called + from customEvent() function + \internal +*/ +void PyConsole_Editor::multiLineProcessNextLine() +{ + // not in multi-line paste mode + if ( !myMultiLinePaste || myMultiLineContent.isEmpty() ) + return; + + QString line = myMultiLineContent.dequeue(); + if ( myMultiLineContent.empty() ) + { + // this isa last line in the queue, just paste it + addText( line, false, false ); + myMultiLinePaste = false; + } + else + { + // paste the line and simulate a key stroke + addText( line, false, false ); + handleReturn(); + } +} + +/*! + \brief Clear results of completion +*/ +void PyConsole_Editor::clearCompletion() +{ + // delete completion text if present + if ( myTabMode ) { + // 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 event to be completed + } + myTabMode = false; +} + +/*! + \brief Format completion results - this is where we should create 3 columns etc ... + \param matches list of possible completions + \return result string +*/ +QString PyConsole_Editor::formatCompletion( const QStringList& matches ) const +{ + static const int MAX_COMPLETIONS = 70; + + QStringList result; + int sz = matches.size(); + + if ( sz > MAX_COMPLETIONS ) + result.append( QString( "[%1]" ).arg( tr( "TOO_MANY_MATCHES" ) ) ); + + for ( int i = 0; i < qMin( sz, MAX_COMPLETIONS); ++i ) + result.append( matches[i] ); + + return result.join( "\n" ); +} + +/*! + \brief Format the doc string in HTML format with the first line in bold blue + \param doc initial doc string + \return HTML string +*/ +QString PyConsole_Editor::formatDocHTML( const QString& doc ) const +{ + static const char* templ = "\n" \ + " " \ + " " \ + "\n" \ + "

" \ + "%1

" \ + "

%2

" \ + ""; + + 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 QString( templ ).arg( fst ).arg( rest ); +} + +/*! + \fn void PyConsole_Editor::updateDoc( const QString& doc); + \brief Signal emitted by the editor widget when the doc string should be updated. + \param doc a HTML block with the formatted doc string. + \todo currently this signal is left uncaught. +*/ + +/*! + \brief Extract the common leading part of all strings in matches. + \param matches + \param result +*/ +QString PyConsole_Editor::extractCommon( const QStringList& matches ) const +{ + QString result = ""; + + if ( matches.size() > 1 ) { + int l = 0; + bool ok = true; + while ( ok && l+1 < matches[0].size() ) { + QString match = matches[0].left( l+1 ); + for ( int j = 1; j < matches.size() && ok; j++ ) + ok = matches[j].startsWith( match ); + if ( ok ) + l++; + } + result = matches[0].left( l ); + } + + return result; +} + +/*! + \brief Useful method to get banner from Python interpreter + \return banner +*/ +QString PyConsole_Editor::banner() const +{ + return myInterp->getBanner().c_str(); +} diff --git a/src/PyConsole/PyConsole_Editor.h b/src/PyConsole/PyConsole_Editor.h new file mode 100644 index 000000000..774e101af --- /dev/null +++ b/src/PyConsole/PyConsole_Editor.h @@ -0,0 +1,137 @@ +// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// File : PyConsole_Editor.h +// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) + +#ifndef PYCONSOLE_EDITOR_H +#define PYCONSOLE_EDITOR_H + +#include "PyConsole.h" + +#include +#include + +class PyConsole_Interp; +class PyInterp_Request; +class QEventLoop; + +class PYCONSOLE_EXPORT PyConsole_Editor : public QTextEdit +{ + Q_OBJECT; + +public: + PyConsole_Editor( PyConsole_Interp*, QWidget* = 0 ); + ~PyConsole_Editor(); + + PyConsole_Interp* getInterp() const; + + virtual void addText( const QString&, const bool = false, const bool = false ); + bool isCommand( const QString& ) const; + + virtual void exec( const QString& ); + void execAndWait( const QString& ); + + bool isSync() const; + void setIsSync( const bool ); + + bool isSuppressOutput() const; + void setIsSuppressOutput( const bool ); + + bool isShowBanner() const; + void setIsShowBanner( const bool ); + + void setAutoCompletion( bool ); + bool autoCompletion() const; + + bool isLogging() const; + + virtual QSize sizeHint() const; + + bool startLog( const QString& ); + bool dump( const QString& ); + +signals: + void updateDoc( const QString& ); + +public slots: + void cut(); + void paste(); + void clear(); + void dump(); + void startLog(); + void stopLog(); + +protected: + virtual void dropEvent( QDropEvent* ); + virtual void mousePressEvent( QMouseEvent* ); + virtual void mouseReleaseEvent( QMouseEvent* ); + virtual void keyPressEvent ( QKeyEvent* ); + virtual void customEvent( QEvent* ); + + virtual void insertFromMimeData( const QMimeData* ); + + void putLog( const QString& ); + + virtual QString getDumpFileName(); + virtual QString getLogFileName(); + +private: + void multilinePaste( const QString& ); + void multiLineProcessNextLine(); + + void handleReturn(); + void handleTab(); + void handleBackTab(); + void clearCompletion(); + QString formatCompletion( const QStringList& ) const; + QString formatDocHTML( const QString& ) const; + QString extractCommon( const QStringList& ) const; + + PyInterp_Request* createCmdRequest( const QString& ); + PyInterp_Request* createTabRequest( const QString& ); + + QString banner() const; + 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 + QString myLogFile; //!< current output log + QStringList myHistory; //!< commands history buffer + QEventLoop* myEventLoop; //!< internal event loop + bool myShowBanner; //!< 'show banner' flag + QStringList myQueue; //!< python commands queue + bool myIsSync; //!< synchronous mode flag + bool myIsSuppressOutput; //!< suppress output flag + bool myMultiLinePaste; //!< true when pasting several lines + QQueue myMultiLineContent; //!< queue of lines being pasted + bool myAutoCompletion; //!< auto-completion mode flag + bool myTabMode; //!< flag that is \c true when editor performs completion + QString myComplBeforePoint; //!< string on which the dir() command is executed + QString myComplAfterPoint; //!< string on which the results of the dir() are matched + int myComplCursorPos; //!< cursor position when is hit + +}; + +#endif // PYCONSOLE_EDITOR_H diff --git a/src/PyConsole/PyConsole_EditorBase.h b/src/PyConsole/PyConsole_EditorBase.h deleted file mode 100644 index 78ff8c5ea..000000000 --- a/src/PyConsole/PyConsole_EditorBase.h +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE -// -// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// - -// SALOME SALOMEGUI : implementation of desktop and GUI kernel -// File : PyConsole_Editor.h -// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) -// -#ifndef PYCONSOLE_EDITORBASE_H -#define PYCONSOLE_EDITORBASE_H - -#include "PyConsole.h" - -#include - -class PyConsole_Interp; -class PyInterp_Request; -class QEventLoop; - -class PYCONSOLE_EXPORT PyConsole_EditorBase : public QTextEdit -{ - Q_OBJECT; - -public: - PyConsole_EditorBase( PyConsole_Interp* theInterp, QWidget *theParent = 0 ); - ~PyConsole_EditorBase(); - - PyConsole_Interp* getInterp() const; - - 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 ); - - bool isLogging() const; - - virtual QSize sizeHint() const; - void dumpImpl(const QString& fileName); - bool startLogImpl( const QString& ); -public slots: - void cut(); - void paste(); - void clear(); - void handleReturn(); - void onPyInterpChanged( PyConsole_Interp* ); - void dump(const QString& fileName); - void dump(); - void startLog(); - bool startLog( const QString& ); - void stopLog(); - void putLog( const QString& ); - -protected: - virtual void dropEvent( QDropEvent* event ); - virtual void mouseReleaseEvent( QMouseEvent* event ); - virtual void keyPressEvent ( QKeyEvent* event); - virtual void customEvent( QEvent* event); - virtual void dumpSlot(); - virtual void startLogSlot(); - - 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 - QString myLogFile; //!< current output log - 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_EDITORBASE_H diff --git a/src/PyConsole/PyConsole_EnhEditorBase.cxx b/src/PyConsole/PyConsole_EnhEditorBase.cxx deleted file mode 100644 index b22a7fa23..000000000 --- a/src/PyConsole/PyConsole_EnhEditorBase.cxx +++ /dev/null @@ -1,491 +0,0 @@ -// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// -// Author : Adrien Bruneton (CEA/DEN) -// Created on: 4 avr. 2013 - -#include "PyConsole.h" -#include - -#include -#include -#include -#include -#include -#include - -#include "PyConsole_EnhEditorBase.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_EnhEditorBase::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_EnhEditorBase::PyConsole_EnhEditorBase(PyConsole_Interp* interp, QWidget* parent) : - PyConsole_EditorBase(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_EnhEditorBase::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_EditorBase::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_EditorBase::keyPressEvent(event); - } -} - -/** - * Whenever the mouse is clicked, clear the completion. - * @param e - */ -void PyConsole_EnhEditorBase::mousePressEvent(QMouseEvent* e) -{ - clearCompletion(); - _cursor_pos = -1; - PyConsole_EditorBase::mousePressEvent(e); -} - -/** - * Clear in the editor the block of text displayed after having hit . - */ -void PyConsole_EnhEditorBase::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 - if ( myInterp ) - myInterp->clearCompletion(); - } - _tab_mode = false; -} - -/** - * Handle the sequence of events after having hit - */ -void PyConsole_EnhEditorBase::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_EnhEditorBase::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_EnhEditorBase::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( 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_EnhEditorBase::formatCompletion(const QStringList& 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_EnhEditorBase::customEvent( QEvent* event ) -{ - QStringList matches; - QString first_match, comple_text, doc, base; - QTextCursor cursor(textCursor()); - QTextBlockFormat bf; - QTextCharFormat cf; - int cursorPos; - - switch( event->type() ) - { - case PyInterp_Event::ES_TAB_COMPLETE_OK: - { - // Extract corresponding matches from the interpreter - matches = getInterp()->getLastMatches(); - doc = getInterp()->getDocStr(); - - 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 - if (matches.size() == 1) - { - first_match = matches[0].mid(_compl_after_point.size()); - cursor.insertText(first_match); - _tab_mode = false; - if (doc.isEmpty()) - 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_EditorBase::customEvent(event); - // If we are in multi_paste_mode, process the next item: - multiLineProcessNextLine(); - break; - } - default: - { - PyConsole_EditorBase::customEvent( event ); - break; - } - } -} - -/** - * Extract the common leading part of all strings in matches. - * @param matches - * @param result - */ -void PyConsole_EnhEditorBase::extractCommon(const QStringList& 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 (int 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_EnhEditorBase::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_EnhEditorBase::insertFromMimeData(const QMimeData* source) -{ - if (_multi_line_paste) - return; - - if (source->hasText()) - { - QString s = source->text(); - if (s.contains("\n")) - multilinePaste(s); - else - PyConsole_EditorBase::insertFromMimeData(source); - } - else - { - PyConsole_EditorBase::insertFromMimeData(source); - } -} - - -void PyConsole_EnhEditorBase::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_EditorBase::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_EnhEditorBase::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_EnhEditorBase.h b/src/PyConsole/PyConsole_EnhEditorBase.h deleted file mode 100644 index 67fe5e19e..000000000 --- a/src/PyConsole/PyConsole_EnhEditorBase.h +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// -// Author : Adrien Bruneton (CEA/DEN) -// Created on: 4 avr. 2013 - -#ifndef PYCONSOLE_ENHEDITORBASE_H_ -#define PYCONSOLE_ENHEDITORBASE_H_ - -#include "PyConsole.h" -#include "PyConsole_EditorBase.h" - -#include -#include - -/** - * Enhanced Python editor handling tab completion. - */ -class PYCONSOLE_EXPORT PyConsole_EnhEditorBase : public PyConsole_EditorBase -{ - Q_OBJECT; - -public: - PyConsole_EnhEditorBase(PyConsole_Interp* interp, QWidget* parent = 0); - virtual ~PyConsole_EnhEditorBase() {} - -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 QStringList& matches, QString& result) const; - virtual QString formatDocHTML(const QString & doc) const; - - virtual void multilinePaste(const QString & s); - virtual void multiLineProcessNextLine(); - -private: - void extractCommon(const QStringList& matches, QString& result) const; - -}; - -#endif /* PYCONSOLE_ENHEDITORBASE_H_ */ diff --git a/src/PyConsole/PyConsole_EnhInterp.cxx b/src/PyConsole/PyConsole_EnhInterp.cxx deleted file mode 100644 index 91b839c34..000000000 --- a/src/PyConsole/PyConsole_EnhInterp.cxx +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// -// Author : Adrien Bruneton (CEA/DEN) -// Created on: 4 avr. 2013 - - -#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 Constructor -*/ -PyConsole_EnhInterp::PyConsole_EnhInterp() - : PyConsole_Interp() -{ -} - -/*! - \brief Destructor -*/ -PyConsole_EnhInterp::~PyConsole_EnhInterp() -{ -} - -QStringList PyConsole_EnhInterp::getLastMatches() const -{ - return _last_matches; -} - -QString PyConsole_EnhInterp::getDocStr() const -{ - return _doc_str; -} - -/*! - \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, _global_context, _local_context); - 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, - QStringList& 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, _global_context, _local_context); - 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.clear(); - _doc_str = ""; -} diff --git a/src/PyConsole/PyConsole_EnhInterp.h b/src/PyConsole/PyConsole_EnhInterp.h deleted file mode 100644 index 3fe66fd8b..000000000 --- a/src/PyConsole/PyConsole_EnhInterp.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// -// Author : Adrien Bruneton (CEA/DEN) -// Created on: 4 avr. 2013 - - -#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(); - virtual ~PyConsole_EnhInterp(); - - virtual QStringList getLastMatches() const; - virtual QString getDocStr() const; - - 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 */ - QStringList _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, - QStringList& result, bool discardSwig=true) const; -}; - -#endif /* PYCONSOLE_ENHINTERP_H_ */ diff --git a/src/PyConsole/PyConsole_Event.cxx b/src/PyConsole/PyConsole_Event.cxx index 382b39a06..5c3f1fdf9 100644 --- a/src/PyConsole/PyConsole_Event.cxx +++ b/src/PyConsole/PyConsole_Event.cxx @@ -19,6 +19,89 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -// Author : Vadim SANDLER (Open CASCADE S.A.S), Adrien Bruneton (CEA/DEN) +// File : PyConsole_Event.cxx +// Author : Vadim SANDLER (Open CASCADE S.A.S), Adrien Bruneton (CEA/DEN) #include "PyConsole_Event.h" + +/*! + \class PyConsole_PrintEvent + \brief Python command output backend event. + \internal +*/ + +/*! + \brief Constructor + \param message message text (python trace) + \param isError default to \c false - if \c true indicates that an error is being printed. +*/ +PyConsole_PrintEvent::PyConsole_PrintEvent( const QString& message, bool isError ) + : QEvent( (QEvent::Type)EVENT_ID ), myText( message ), myError( isError ) +{ +} + +/*! + \brief Get message + \return message text (python trace) +*/ +QString PyConsole_PrintEvent::text() const +{ + return myText; +} + +/*! + \brief Get error flag + \return \c true if this is an error message +*/ +bool PyConsole_PrintEvent::isError() const +{ + return myError; +} + +/*! + \class PyConsole_CompletionEvent + \brief Python command completion event. + \internal +*/ + +/*! + \brief Constructor + \param request python request + \param s status of execution of completion command + \param ms command matches (completions) + \param d docstring of the match (in case if there is sinlge match) +*/ +PyConsole_CompletionEvent::PyConsole_CompletionEvent( PyInterp_Request* request, + bool s, + const QStringList& ms, + const QString& d ) + : PyInterp_Event( (QEvent::Type)EVENT_ID, request ), + myStatus( s ), myMatches( ms ), myDoc( d ) +{} + +/*! + \brief Get status of execution of completion command + \return execution status +*/ +bool PyConsole_CompletionEvent::status() const +{ + return myStatus; +} + +/*! + \brief Get matches (completions) + \return detected command matches (completions) +*/ +QStringList PyConsole_CompletionEvent::matches() const +{ + return myMatches; +} + +/*! + \brief Get docstring + \return docstring of the match (in case if there is sinlge match) +*/ +QString PyConsole_CompletionEvent::doc() const +{ + return myDoc; +} diff --git a/src/PyConsole/PyConsole_Event.h b/src/PyConsole/PyConsole_Event.h index 4f9a7fe8d..d22b78b1a 100644 --- a/src/PyConsole/PyConsole_Event.h +++ b/src/PyConsole/PyConsole_Event.h @@ -19,51 +19,49 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -// Author : Vadim SANDLER (Open CASCADE S.A.S), Adrien Bruneton (CEA/DEN) +// File : PyConsole_Event.h +// Author : Vadim SANDLER (Open CASCADE S.A.S), Adrien Bruneton (CEA/DEN) #ifndef PYCONSOLE_EVENT_H #define PYCONSOLE_EVENT_H #include "PyConsole.h" +#include "PyInterp_Event.h" #include #include +#include -/*! - \class PrintEvent - \brief Python command output backend event. - \internal -*/ -class PrintEvent : public QEvent +class PyConsole_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 QString& c, bool isError = false) : - QEvent( (QEvent::Type)EVENT_ID ), myText( c ), errorFlag(isError) - {} + PyConsole_PrintEvent( const QString&, bool = false ); - /*! - \brief Get message - \return message text (python trace) - */ - QString text() const { return myText; } + QString text() const; + bool isError() const; - /** - * @return true if this is an error message - */ - bool isError() const { return errorFlag; } +private: + QString myText; //!< Event message (python trace) + bool myError; //!< Set to \c true if an error msg is to be displayed +}; -protected: - QString myText; //!< Event message (python trace) +class PyConsole_CompletionEvent : public PyInterp_Event +{ +public: + static const int EVENT_ID = 65433; + + PyConsole_CompletionEvent( PyInterp_Request*, bool, const QStringList&, const QString& ); + + bool status() const; + QStringList matches() const; + QString doc() const; - /** Set to true if an error msg is to be displayed */ - bool errorFlag; +protected: + bool myStatus; //!< Status of execution + QStringList myMatches; //!< Command matches (completions) + QString myDoc; //!< Docstring of the match (in case if there is sinlge match) }; #endif // PYCONSOLE_EVENT_H diff --git a/src/PyConsole/PyConsole_Interp.cxx b/src/PyConsole/PyConsole_Interp.cxx index 7d52bbee5..722413686 100644 --- a/src/PyConsole/PyConsole_Interp.cxx +++ b/src/PyConsole/PyConsole_Interp.cxx @@ -19,8 +19,8 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -// File : PyConsole_Interp.cxx -// Author : Nicolas REJNERI, Adrien BRUNETON +// File : PyConsole_Interp.cxx +// Author : Nicolas REJNERI (OPEN CASCADE), Adrien BRUNETON (CEA/DEN), Vadim SANDLER (OPEN CASCADE) #include "PyConsole_Interp.h" @@ -37,6 +37,8 @@ - initPython() to initialize global Python interpreter - initContext() to initialize interpreter internal context - initRun() to prepare interpreter for running commands + + See PyInterp_Interp class for more details. */ /*! @@ -44,50 +46,153 @@ Creates new python interpreter. */ -PyConsole_Interp::PyConsole_Interp(): PyInterp_Interp() +PyConsole_Interp::PyConsole_Interp() + : PyInterp_Interp() { } /*! \brief Destructor. - - Does nothing for the moment. */ PyConsole_Interp::~PyConsole_Interp() { } -/*! Sets the variable "__IN_SALOME_GUI_CONSOLE" to True. -* This is not attached to a module (like salome_iapp.IN_SALOME_GUI_CONSOLE) -* since modules are shared across all interpreters in SALOME. -* -* (GIL is already acquired here) +/*! + \brief Performs specific actions before each Python command + + Sets the variable "__IN_SALOME_GUI_CONSOLE" to True. + This is not attached to a module (like salome_iapp.IN_SALOME_GUI_CONSOLE) + since modules are shared across all interpreters in SALOME. + + \note GIL is already acquired here. */ int PyConsole_Interp::beforeRun() { return PyRun_SimpleString("__builtins__.__IN_SALOME_GUI_CONSOLE=True"); } +/*! + \brief Performs specific actions after each Python command + + Sets the variable "__IN_SALOME_GUI_CONSOLE" to False. + \sa beforeRun() + + \note GIL is already acquired here. +*/ int PyConsole_Interp::afterRun() { return PyRun_SimpleString("__builtins__.__IN_SALOME_GUI_CONSOLE=False"); } -QStringList PyConsole_Interp::getLastMatches() const +/*! + \brief Run Python dir() command to get matches. + \internal + \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". + \param[out] matches resulting list of matches + \param[out] docString resulting docstring of single match + \return \true if completion succeeded, \c false otherwise +*/ +bool PyConsole_Interp::runDirCommand( const QString& dirArgument, const QString& startMatch, + QStringList& matches, QString& docString ) { - return QStringList(); + static QStringList keywords; + if ( keywords.isEmpty() ) { + keywords << "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"; + } + + // run dir() command and extract completions + if ( !runDirAndExtract( dirArgument, startMatch, matches ) ) + return false; + + // If dirArgument is empty, we append the __builtins__ + if ( dirArgument.isEmpty() ) { + if ( !runDirAndExtract( QString( "__builtins__" ), startMatch, matches, false ) ) + return false; + + // ... and we match on Python's keywords as well + foreach( QString keyword, keywords ) { + if ( keyword.startsWith( startMatch ) ) + matches.append( keyword ); + } + } + + // Try to get doc string of the first match + if ( matches.size() > 0 ) { + QString cmd = QString( "%1.__doc__" ).arg( matches[0] ); + if ( !dirArgument.trimmed().isEmpty() ) + cmd.prepend( QString( "%1." ).arg( dirArgument ) ); + + PyObject* str = PyRun_String( cmd.toStdString().c_str(), Py_eval_input, _global_context, _local_context ); + if ( !str || str == Py_None || !PyString_Check( str ) ) + { + if ( !str ) + PyErr_Clear(); + } + else { + docString = QString( PyString_AsString( str ) ); + } + Py_XDECREF( str ); + } + return true; } -QString PyConsole_Interp::getDocStr() const +/*! + \internal + \sa runDirCommand() + \param dirArgument see runDirCommand() + \param startMatch see runDirCommand() + \param[out] result resulting list of matches + \param discardSwig if \c true, a regular expression is used to discard all static method generated + by SWIG. Typically: MEDCouplingUMesh_Blabla + \return \c true if the call to dir() and parsing of the result succeeded, \false otherwise. +*/ +bool PyConsole_Interp::runDirAndExtract( const QString& dirArgument, + const QString& startMatch, + QStringList& result, + bool discardSwig ) const { - return QString(); -} + QRegExp re( "^[A-Z].+_[A-Z]+[a-z]+.+$" ); // REX to discard SWIG static method, e.g. MEDCouplingUMesh_Blabla -int PyConsole_Interp::runDirCommand(const QString&, const QString& ) -{ - return 0; -} + // Execute dir() command + QString command( "dir(" + dirArgument + ")" ); + PyObject* plst = PyRun_String( command.toStdString().c_str(), Py_eval_input, _global_context, _local_context ); + if ( !plst || plst == Py_None ) { + if ( !plst ) + PyErr_Clear(); + Py_XDECREF( plst ); + return false; + } -void PyConsole_Interp::clearCompletion() -{ + // Check result + if ( !PySequence_Check( plst ) ) { + // Should never happen ... + Py_XDECREF( plst ); + return false; + } + + // Extract the returned list + 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.append( s ); + } + Py_DECREF( it ); + } + Py_DECREF( plst ); + + return true; } diff --git a/src/PyConsole/PyConsole_Interp.h b/src/PyConsole/PyConsole_Interp.h index 14c8404a3..4275c350f 100644 --- a/src/PyConsole/PyConsole_Interp.h +++ b/src/PyConsole/PyConsole_Interp.h @@ -19,19 +19,21 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -// File : PyConsole_Interp.h -// Author : Nicolas REJNERI, Adrien BRUNETON +// File : PyConsole_Interp.h +// Author : Nicolas REJNERI (OPEN CASCADE), Adrien BRUNETON (CEA/DEN), Vadim SANDLER (OPEN CASCADE) #ifndef PYCONSOLE_INTERP_H #define PYCONSOLE_INTERP_H #include "PyConsole.h" -#include "PyInterp_Interp.h" /// !!! WARNING !!! THIS INCLUDE MUST BE VERY FIRST !!! +#include "PyInterp_Interp.h" #include class PYCONSOLE_EXPORT PyConsole_Interp : public PyInterp_Interp { + friend class PyConsole_CompletionCommand; + public: PyConsole_Interp(); ~PyConsole_Interp(); @@ -39,11 +41,9 @@ public: virtual int afterRun(); virtual int beforeRun(); - virtual QStringList getLastMatches() const; - virtual QString getDocStr() const; - - virtual int runDirCommand(const QString&, const QString&); - virtual void clearCompletion(); +private: + bool runDirCommand( const QString&, const QString&, QStringList&, QString& ); + bool runDirAndExtract( const QString&, const QString&, QStringList&, bool = true ) const; }; #endif // PYCONSOLE_INTERP_H diff --git a/src/PyConsole/PyConsole_Request.cxx b/src/PyConsole/PyConsole_Request.cxx index e28a05e14..aa41c259e 100644 --- a/src/PyConsole/PyConsole_Request.cxx +++ b/src/PyConsole/PyConsole_Request.cxx @@ -16,39 +16,46 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -// Author : Adrien Bruneton (CEA/DEN) -// Created on: 3 avr. 2013 +// File : PyConsole_Request.cxx +// Author : Vadim SANDLER (OPEN CASCADE), Adrien Bruneton (CEA/DEN) #include "PyConsole_Request.h" #include "PyConsole_Interp.h" #include "PyConsole_Event.h" -#include "PyInterp_Event.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, - QObject* theListener, - bool theSync ) +/*! + \class PyConsole_ExecCommand + \brief Python command execution request. + \internal +*/ + +/*! + \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 theSync if \c true, the request is processed synchronously +*/ +PyConsole_ExecCommand::PyConsole_ExecCommand( PyInterp_Interp* theInterp, + const QString& theCommand, + QObject* theListener, + bool theSync ) : PyInterp_LockRequest( theInterp, theListener, theSync ), myCommand( theCommand ), myState( PyInterp_Event::ES_OK ) {} -/** - * Execute the command by calling the run() method of the embedded interpreter. - */ -void ExecCommand::execute() +/*! + \brief Execute the python command in the interpreter and + get its execution status. +*/ +void PyConsole_ExecCommand::execute() { - if ( myCommand != "" ) - { + if ( myCommand != "" ) { int ret = getInterp()->run( myCommand.toLatin1().data() ); if ( ret < 0 ) myState = PyInterp_Event::ES_ERROR; @@ -57,52 +64,57 @@ void ExecCommand::execute() } } -/** - * Create the event indicating the status of the request execution. - * @return a QEvent - */ -QEvent* ExecCommand::createEvent() +/*! + \brief Create and return a notification event. + \return new notification event +*/ +QEvent* PyConsole_ExecCommand::createEvent() { if ( IsSync() ) - QCoreApplication::sendPostedEvents( listener(), PrintEvent::EVENT_ID ); + QCoreApplication::sendPostedEvents( listener(), PyConsole_PrintEvent::EVENT_ID ); return new PyInterp_Event( myState, this ); } +/*! + \class PyConsole_CompletionCommand + \brief Python command completion request. + \internal +*/ /*! - Constructor. + \brief 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 theInterp python interpreter + \param theInput string containing the dir() command to be executed + \param theStartMatch 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 + \param theSync if \c true the request is processed synchronously */ -CompletionCommand::CompletionCommand( PyInterp_Interp* theInterp, - const QString& theInput, - const QString& theStartMatch, - QObject* theListener, - bool theSync ) +PyConsole_CompletionCommand::PyConsole_CompletionCommand( PyInterp_Interp* theInterp, + const QString& theInput, + const QString& theStartMatch, + QObject* theListener, + bool theSync ) : PyInterp_LockRequest( theInterp, theListener, theSync ), - _tabSuccess(false), _dirArg(theInput), _startMatch(theStartMatch) + myDirArg( theInput ), myStartMatch( theStartMatch ), myStatus( false ) {} -/** - * Execute the completion command by wrapping the runDirCommand() of the - * embedded enhanced interpreter. - */ -void CompletionCommand::execute() +/*! + \brief Execute the completion command by invoking runDirCommand() function + of interpreter. +*/ +void PyConsole_CompletionCommand::execute() { - int ret = static_cast(getInterp())->runDirCommand( _dirArg, _startMatch ); - _tabSuccess = ret == 0; + myStatus = static_cast( getInterp() )->runDirCommand( myDirArg, myStartMatch, myMatches, myDoc ); } -/** - * Create the event indicating the return value of the completion command. - * @return +/*! + \brief Create and return completion event + \return new completion event */ -QEvent* CompletionCommand::createEvent() +QEvent* PyConsole_CompletionCommand::createEvent() { - int typ = _tabSuccess ? PyInterp_Event::ES_TAB_COMPLETE_OK : PyInterp_Event::ES_TAB_COMPLETE_ERR; - return new PyInterp_Event( typ, this); + return new PyConsole_CompletionEvent( this, myStatus, myMatches, myDoc ); } diff --git a/src/PyConsole/PyConsole_Request.h b/src/PyConsole/PyConsole_Request.h index 93ba66226..827823b60 100644 --- a/src/PyConsole/PyConsole_Request.h +++ b/src/PyConsole/PyConsole_Request.h @@ -16,54 +16,27 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -// Author : Adrien Bruneton (CEA/DEN) -// Created on: 3 avr. 2013 +// File : PyConsole_Request.h +// Author : Vadim SANDLER (OPEN CASCADE), Adrien Bruneton (CEA/DEN) - -#ifndef PYCONSOLE_REQUEST_H_ -#define PYCONSOLE_REQUEST_H_ +#ifndef PYCONSOLE_REQUEST_H +#define PYCONSOLE_REQUEST_H #include "PyInterp_Request.h" -#include #include -#include +#include +class QEvent; class PyInterp_Interp; -/*! - \class ExecCommand - \brief Python command execution request. - \internal -*/ -class ExecCommand : public PyInterp_LockRequest +class PyConsole_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, - QObject* theListener, - bool theSync = false ); + PyConsole_ExecCommand( PyInterp_Interp*, const QString&, QObject*, bool = 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: @@ -71,29 +44,21 @@ private: int myState; //!< Python command execution status }; -class CompletionCommand : public PyInterp_LockRequest +class PyConsole_CompletionCommand : public PyInterp_LockRequest { public: - CompletionCommand( PyInterp_Interp* theInterp, - const QString& theInput, - const QString& theStartMatch, - QObject* theListener, - bool theSync = false ); - + PyConsole_CompletionCommand( PyInterp_Interp*, const QString&, const QString&, QObject*, bool = 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(); + +private: + QString myDirArg; //!< String to be passed to the dir() comman + QString myStartMatch; //!< Begining of the command (as typed by the user) + bool myStatus; //!< Status of completion command execution + QStringList myMatches; //!< Matches + QString myDoc; //!< Docstring of single match }; -#endif /* PYCONSOLE_REQUEST_H_ */ +#endif // PYCONSOLE_REQUEST_H diff --git a/src/PyConsole/resources/PyConsole_msg_en.ts b/src/PyConsole/resources/PyConsole_msg_en.ts index 1586df266..7fac57c1d 100644 --- a/src/PyConsole/resources/PyConsole_msg_en.ts +++ b/src/PyConsole/resources/PyConsole_msg_en.ts @@ -2,24 +2,24 @@ - PyConsole_ConsoleBase + PyConsole_Console - + EDIT_COPY_CMD &Copy - + EDIT_PASTE_CMD &Paste - + EDIT_CLEAR_CMD Clea&r - + EDIT_SELECTALL_CMD Select &All @@ -28,7 +28,7 @@ D&ump Commands - EDIT_STARTLOG_CMD + EDIT_STARTLOG_CMD Start &Log @@ -37,34 +37,38 @@ - PyConsole_EditorBase + PyConsole_Editor - Choose python file where to store - Choose python file where to store dump + GET_DUMP_COMMANDS_FILENAME + Dump commands to file - Python scripts ext (*.py) - Python scripts (*.py) + GET_PYTHON_TRACE_FILENAME + Save Python trace to file + + + PYTHON_SCRIPTS + Python scripts WARNING - WARNING ! + Warning! - Python file has not been written - Python file has not been written ! + LOG_FILES + Log files - Choose python file where to store log - Choose python file where to store log + ERR_FILE_NOT_WRITEABLE + File is not writeable! - Log files ext (*.log *.txt) - Log files extension (*.log *.txt) + TOO_MANY_MATCHES + Too many matches! Displaying first ones only... - Log file is not writable - Log file is not writable ! + NO_DOC_AVAILABLE + no documentation available diff --git a/src/PyConsole/resources/PyConsole_msg_fr.ts b/src/PyConsole/resources/PyConsole_msg_fr.ts index ff40a32c5..9eaf24482 100644 --- a/src/PyConsole/resources/PyConsole_msg_fr.ts +++ b/src/PyConsole/resources/PyConsole_msg_fr.ts @@ -2,24 +2,24 @@ - PyConsole_ConsoleBase + PyConsole_Console - + EDIT_COPY_CMD &Copier - + EDIT_PASTE_CMD C&oller - + EDIT_CLEAR_CMD &Effacer - + EDIT_SELECTALL_CMD &Tout sélectionner @@ -37,34 +37,38 @@ - PyConsole_EditorBase + PyConsole_Editor - Choose python file where to store + GET_DUMP_COMMANDS_FILENAME Choisissez un fichier python où sauver le dump - Python scripts ext (*.py) - Scripts Python (*.py) + GET_PYTHON_TRACE_FILENAME + Choisissez un fichier où sauver le log + + + PYTHON_SCRIPTS + Scripts Python WARNING Attention ! - Python file has not been written - Le fichier Python n'a pas été écrit ! + LOG_FILES + Fichiers log - Choose python file where to store log - Choisissez un fichier python où sauver le log + ERR_FILE_NOT_WRITEABLE + Le fichier n'a pas été écrit ! - Log files ext (*.log *.txt) - Extensions possible des fichiers log (*.log *.txt) + TOO_MANY_MATCHES + Too many matches! Displaying first ones only... - Log file is not writable - Le fichier log sélectionné n'est pas writable ! + NO_DOC_AVAILABLE + no documentation available diff --git a/src/PyConsole/resources/PyConsole_msg_ja.ts b/src/PyConsole/resources/PyConsole_msg_ja.ts index ca1aacee3..8861d5ed5 100644 --- a/src/PyConsole/resources/PyConsole_msg_ja.ts +++ b/src/PyConsole/resources/PyConsole_msg_ja.ts @@ -2,24 +2,24 @@ - PyConsole_ConsoleBase + PyConsole_Console - + EDIT_COPY_CMD コピー(&C) - + EDIT_PASTE_CMD 貼り付け(&P) - + EDIT_CLEAR_CMD 削除(&r) - + EDIT_SELECTALL_CMD すべて選択します。(&A) @@ -37,34 +37,38 @@ - PyConsole_EditorBase + PyConsole_Editor - Choose python file where to store - Choose python file where to store dump + GET_DUMP_COMMANDS_FILENAME + Dump commands to file - Python scripts ext (*.py) - Python scripts (*.py) + GET_PYTHON_TRACE_FILENAME + Save Python trace to file - WARNING - WARNING ! + PYTHON_SCRIPTS + Python scripts - Python file has not been written - Python file has not been written ! + WARNING + Warning! - Choose python file where to store log - Choose python file where to store log + LOG_FILES + Log files - Log files ext (*.log *.txt) - Log files extension (*.log *.txt) + ERR_FILE_NOT_WRITEABLE + File is not writeable! - Log file is not writable - Log file is not writable ! + TOO_MANY_MATCHES + Too many matches! Displaying first ones only... - + + NO_DOC_AVAILABLE + no documentation available + + diff --git a/src/PyInterp/CMakeLists.txt b/src/PyInterp/CMakeLists.txt index dd4c3c23e..987380dac 100755 --- a/src/PyInterp/CMakeLists.txt +++ b/src/PyInterp/CMakeLists.txt @@ -25,25 +25,24 @@ INCLUDE(UseQt4Ext) INCLUDE_DIRECTORIES( ${QT_INCLUDES} ${PYTHON_INCLUDE_DIRS} - ${PROJECT_SOURCE_DIR}/src/Event ) # additional preprocessor / compiler flags ADD_DEFINITIONS(${QT_DEFINITIONS} ${PYTHON_DEFINITIONS}) # libraries to link to -SET(_link_LIBRARIES ${QT_LIBRARIES} ${PYTHON_LIBRARIES} Event) +SET(_link_LIBRARIES ${QT_LIBRARIES} ${PYTHON_LIBRARIES}) # --- headers --- -# header files / to be processed by moc / internal -# TODO: check for MSVS project -SET(_moc_internal_HEADERS PyInterp_Watcher.h) +# header files / to be processed by moc +SET(_moc_HEADERS + PyInterp_Dispatcher.h +) # header files / no moc processing SET(_other_HEADERS PyInterp.h - PyInterp_Dispatcher.h PyInterp_Event.h PyInterp_Interp.h PyInterp_Request.h @@ -51,12 +50,12 @@ SET(_other_HEADERS ) # header files / to install -SET(PyInterp_HEADERS ${_other_HEADERS}) +SET(PyInterp_HEADERS ${_moc_HEADERS} ${_other_HEADERS}) # --- sources --- # sources / moc wrappings -QT4_WRAP_CPP(_moc_SOURCES ${_moc_internal_HEADERS}) +QT4_WRAP_CPP(_moc_SOURCES ${_moc_HEADERS}) # sources / static SET(_other_SOURCES diff --git a/src/PyInterp/PyInterp.h b/src/PyInterp/PyInterp.h index 965e81273..1ac25a1bb 100755 --- a/src/PyInterp/PyInterp.h +++ b/src/PyInterp/PyInterp.h @@ -19,10 +19,9 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // - // File : PyInterp.h // Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) -// + #if !defined ( PYINTERP_H ) #define PYINTERP_H diff --git a/src/PyInterp/PyInterp_Dispatcher.cxx b/src/PyInterp/PyInterp_Dispatcher.cxx index 6728155ba..b70214481 100755 --- a/src/PyInterp/PyInterp_Dispatcher.cxx +++ b/src/PyInterp/PyInterp_Dispatcher.cxx @@ -19,18 +19,15 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // - // File : PyInterp_Dispatcher.cxx -// Author : Sergey ANIKIN, OCC -// Module : GUI -// +// Author : Sergey Anikin (OPEN CASCADE S.A.S.) + #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 +/** + \class PyInterp_Dispatcher + \brief Dispatcher of Python events; used to serialize requests to Python interpreter. +*/ PyInterp_Dispatcher* PyInterp_Dispatcher::myInstance = 0; @@ -44,7 +41,6 @@ PyInterp_Dispatcher* PyInterp_Dispatcher::Get() PyInterp_Dispatcher::PyInterp_Dispatcher() : QThread() { - myWatcher = new PyInterp_Watcher(); } PyInterp_Dispatcher::~PyInterp_Dispatcher() @@ -61,9 +57,6 @@ PyInterp_Dispatcher::~PyInterp_Dispatcher() // Wait for run() to finish wait(); - - delete myWatcher; - myWatcher = 0; } bool PyInterp_Dispatcher::IsBusy() const @@ -76,15 +69,22 @@ 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 + if ( theRequest->IsSync() /*&& !IsBusy()*/) + { + // synchronous processing processRequest( theRequest ); - else // asynchronous processing + } + else { + // asynchronous processing myQueueMutex.lock(); + myQueue.enqueue( theRequest ); - if ( theRequest->listener() ) - QObject::connect( theRequest->listener(), SIGNAL( destroyed( QObject* ) ), myWatcher, SLOT( onDestroyed( QObject* ) ) ); + if ( theRequest->listener() ) { + connect( theRequest->listener(), SIGNAL( destroyed( QObject* ) ), + this, SLOT( objectDestroyed( QObject* ) ) ); + } + myQueueMutex.unlock(); if ( !IsBusy() ) @@ -94,14 +94,13 @@ void PyInterp_Dispatcher::Exec( PyInterp_Request* theRequest ) 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") + while ( myQueue.size() ) + { aRequest = myQueue.head(); // let other threads append their requests to the end of the queue @@ -113,15 +112,13 @@ void PyInterp_Dispatcher::run() // prepare for removal of the first request in the queue myQueueMutex.lock(); + // IMPORTANT: the first item could have been removed by objectDestroyed() --> we have to check it - if ( myQueue.head() == aRequest ) // It's still here --> remove it + if ( myQueue.head() == aRequest ) // if it is 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 ) @@ -129,7 +126,7 @@ void PyInterp_Dispatcher::processRequest( PyInterp_Request* theRequest ) theRequest->process(); } -void PyInterp_Dispatcher::objectDestroyed( const QObject* o ) +void PyInterp_Dispatcher::objectDestroyed( QObject* o ) { // prepare for modification of the queue myQueueMutex.lock(); diff --git a/src/PyInterp/PyInterp_Dispatcher.h b/src/PyInterp/PyInterp_Dispatcher.h index c3c22d73e..c9b83847a 100755 --- a/src/PyInterp/PyInterp_Dispatcher.h +++ b/src/PyInterp/PyInterp_Dispatcher.h @@ -19,11 +19,9 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // - // File : PyInterp_Dispatcher.h -// Author : Sergey Anikin, OCC -// Module : GUI -// +// Author : Sergey Anikin (OPEN CASCADE S.A.S.) + #ifndef PYINTERP_DISPATCHER_H #define PYINTERP_DISPATCHER_H @@ -36,13 +34,10 @@ #include #include -class QObject; -class PyInterp_Watcher; - class PYINTERP_EXPORT PyInterp_Dispatcher : protected QThread { PyInterp_Dispatcher(); // private constructor - + Q_OBJECT public: static PyInterp_Dispatcher* Get(); @@ -54,18 +49,17 @@ public: private: virtual void run(); void processRequest( PyInterp_Request* ); - void objectDestroyed( const QObject* ); + +private slots: + void objectDestroyed( 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.cxx b/src/PyInterp/PyInterp_Event.cxx index f0f81bae6..478eb2c36 100644 --- a/src/PyInterp/PyInterp_Event.cxx +++ b/src/PyInterp/PyInterp_Event.cxx @@ -19,20 +19,35 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -// File : PyInterp_Request.h -// Author : Sergey Anikin, OCC, Adrien Bruneton (CEA/DEN) -// Module : GUI +// File : PyInterp_Event.cxx +// Author : Sergey Anikin (OPEN CASCADE S.A.S.), Adrien Bruneton (CEA/DEN) #include "PyInterp_Event.h" #include "PyInterp_Request.h" +/** + \class PyInterp_Event + \brief Events thrown by the interpreter having executed a command and indicating + the return status. +*/ + +PyInterp_Event::PyInterp_Event( int type, PyInterp_Request* request ) + : QEvent( (QEvent::Type)type ), myRequest( request ) +{ +} + PyInterp_Event::~PyInterp_Event() { PyInterp_Request::Destroy( myRequest ); myRequest = 0; } -void PyInterp_ExecuteEvent::Execute() +PyInterp_Request* PyInterp_Event::GetRequest() const +{ + return myRequest; +} + +PyInterp_Event::operator PyInterp_Request*() const { - myRequest->execute(); + return myRequest; } diff --git a/src/PyInterp/PyInterp_Event.h b/src/PyInterp/PyInterp_Event.h index 25a841ad0..e812adbe1 100644 --- a/src/PyInterp/PyInterp_Event.h +++ b/src/PyInterp/PyInterp_Event.h @@ -19,54 +19,37 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -// File : PyInterp_Request.h -// Author : Sergey Anikin, OCC, Adrien Bruneton (CEA/DEN) -// Module : GUI +// File : PyInterp_Event.h +// Author : Sergey Anikin (OPEN CASCADE S.A.S.), Adrien Bruneton (CEA/DEN) #ifndef PYINTERP_EVENT_H #define PYINTERP_EVENT_H #include "PyInterp.h" -#include - #include class PyInterp_Request; -class PyInterp_ExecuteEvent: public SALOME_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 ) {} - + // Execution state + enum { + ES_NOTIFY = QEvent::User + 5000, + ES_OK, + ES_ERROR, + ES_INCOMPLETE, + ES_LAST }; + + PyInterp_Event( int type, PyInterp_Request* request ); virtual ~PyInterp_Event(); - PyInterp_Request* GetRequest() const { return myRequest; } - operator PyInterp_Request*() const { return myRequest; } + PyInterp_Request* GetRequest() const; + operator PyInterp_Request*() const; private: PyInterp_Request* myRequest; diff --git a/src/PyInterp/PyInterp_Interp.cxx b/src/PyInterp/PyInterp_Interp.cxx index eba98d507..5946e8d7f 100644 --- a/src/PyInterp/PyInterp_Interp.cxx +++ b/src/PyInterp/PyInterp_Interp.cxx @@ -19,18 +19,15 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // - // File : PyInterp_Interp.cxx // Author : Christian CAREMOLI, Paul RASCLE, Adrien BRUNETON -// Module : SALOME -// + #include "PyInterp_Interp.h" // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!! #include "PyInterp_Utils.h" -#include +#include #include #include - #include #include #include @@ -170,12 +167,10 @@ char* PyInterp_Interp::_argv[] = {(char*)""}; must call virtual method initalize(). */ PyInterp_Interp::PyInterp_Interp(): - _vout(0), _verr(0), _local_context(0), _global_context(0) + _vout(0), _verr(0), _local_context(0), _global_context(0), _initialized(false) { } - - /*! \brief Destructor. */ @@ -197,13 +192,16 @@ PyInterp_Interp::~PyInterp_Interp() */ void PyInterp_Interp::initialize() { + if ( initialized() ) + return; // prevent repeating intitialization + + _initialized = true; + _history.clear(); // start a new list of user's commands _ith = _history.begin(); initPython(); // This also inits the multi-threading for Python (but w/o acquiring GIL) - //initState(); // [ABN] OBSOLETE - // ---- The rest of the initialisation process is done hodling the GIL PyLockWrapper lck; @@ -257,7 +255,7 @@ void PyInterp_Interp::initPython() \brief Get embedded Python interpreter banner. \return banner string */ -std::string PyInterp_Interp::getbanner() const +std::string PyInterp_Interp::getBanner() const { PyLockWrapper lck; std::string aBanner("Python "); @@ -308,8 +306,9 @@ bool PyInterp_Interp::initContext() void PyInterp_Interp::closeContext() { Py_XDECREF(_global_context); - // both _global and _local point to the same Python object: - // Py_XDECREF(_local_context); + // both _global_context and _local_context may point to the same Python object + if ( _global_context != _local_context) + Py_XDECREF(_local_context); } /*! @@ -324,12 +323,12 @@ void PyInterp_Interp::closeContext() static int run_command(const char *command, PyObject * global_ctxt, PyObject * local_ctxt) { PyObject *m = PyImport_AddModule("codeop"); - if(!m) { // Fatal error. No way to go on. + if(!m) { + // Fatal error. No way to go on. PyErr_Print(); return -1; } -// PyObjWrapper v(Py_CompileString(command, "", Py_file_input)); PyObjWrapper v(PyObject_CallMethod(m,(char*)"compile_command",(char*)"s",command)); if(!v) { // Error encountered. It should be SyntaxError, @@ -597,3 +596,12 @@ void PyInterp_Interp::setverrcb(PyOutChanged* cb, void* data) ((PyStdOut*)_verr)->_cb=cb; ((PyStdOut*)_verr)->_data=data; } + +/*! + \bried Check if the interpreter is initialized + \internal +*/ +bool PyInterp_Interp::initialized() const +{ + return _initialized; +} diff --git a/src/PyInterp/PyInterp_Interp.h b/src/PyInterp/PyInterp_Interp.h index c545d8cd1..88e551916 100644 --- a/src/PyInterp/PyInterp_Interp.h +++ b/src/PyInterp/PyInterp_Interp.h @@ -19,11 +19,9 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // - // File : PyInterp_Interp.h // Author : Christian CAREMOLI, Paul RASCLE, Adrien BRUNETON -// Module : SALOME -// + #ifndef PYINTERP_INTERP_H #define PYINTERP_INTERP_H @@ -65,25 +63,22 @@ public: void destroy(); virtual int run(const char *command); - virtual void initStudy(){}; + virtual void initStudy() {}; - // [ABN] - the PyLockWrapper is no more attached to the interpreter - // PyLockWrapper GetLockWrapper() const; + std::string getBanner() const; + void setverrcb(PyOutChanged*, void*); + void setvoutcb(PyOutChanged*, void*); - std::string getbanner() const; - void setverrcb(PyOutChanged*,void*); - void setvoutcb(PyOutChanged*,void*); - - const char * getPrevious(); - const char * getNext(); + const char* getPrevious(); + const char* getNext(); protected: /** Redirection of stdout and stderr */ - PyObject * _vout; - PyObject * _verr; + PyObject* _vout; + PyObject* _verr; /** Execution context (local and global variables) */ - PyObject * _global_context; - PyObject * _local_context; + PyObject* _global_context; + PyObject* _local_context; std::list _history; std::list::iterator _ith; @@ -98,6 +93,11 @@ protected: virtual bool initContext(); virtual bool initRun(); virtual void closeContext(); + + bool initialized() const; + +private: + bool _initialized; }; #endif // PYINTERP_INTERP_H diff --git a/src/PyInterp/PyInterp_Request.cxx b/src/PyInterp/PyInterp_Request.cxx index 0efbda118..f8227f09c 100644 --- a/src/PyInterp/PyInterp_Request.cxx +++ b/src/PyInterp/PyInterp_Request.cxx @@ -20,11 +20,11 @@ // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // // File : PyInterp_Request.h -// Author : Sergey Anikin, OCC, Adrien Bruneton (CEA/DEN) -// Module : GUI +// Author : Sergey Anikin (OPEN CASCADE S.A.S.), Adrien Bruneton (CEA/DEN) #include "PyInterp_Request.h" #include "PyInterp_Utils.h" + #include void PyInterp_Request::process() @@ -45,7 +45,6 @@ void PyInterp_Request::process() void PyInterp_Request::safeExecute() { - //ProcessVoidEvent( new PyInterp_ExecuteEvent( this ) ); execute(); } @@ -89,9 +88,6 @@ void PyInterp_Request::setListener( QObject* o ) void PyInterp_LockRequest::safeExecute() { - //if ( getInterp() ){ // No need to have an interpreter now! we can simply run in a empty context - PyLockWrapper aLock; // Acquire GIL - //ProcessVoidEvent( new PyInterp_ExecuteEvent( this ) ); - execute(); - //} + PyLockWrapper aLock; // Acquire GIL + execute(); } diff --git a/src/PyInterp/PyInterp_Request.h b/src/PyInterp/PyInterp_Request.h index 0ac90d552..cabb3d6b0 100644 --- a/src/PyInterp/PyInterp_Request.h +++ b/src/PyInterp/PyInterp_Request.h @@ -20,8 +20,7 @@ // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // // File : PyInterp_Request.h -// Author : Sergey Anikin (OCC), Adrien Bruneton (CEA/DEN) -// Module : GUI +// Author : Sergey Anikin (OPEN CASCADE S.A.S.), Adrien Bruneton (CEA/DEN) #ifndef PYINTERP_REQUEST_H #define PYINTERP_REQUEST_H @@ -30,53 +29,56 @@ #include "PyInterp_Event.h" #include -#include +class QObject; class PyInterp_Interp; -class PyInterp_Watcher; -class PyInterp_Dispatcher; -class PyInterp_ExecuteEvent; -class PyConsole_Editor; +/** + \class PyInterp_Request + \brief Base Python interpreter request; does not not acquire GIL during execution. + */ class PYINTERP_EXPORT PyInterp_Request { friend class PyInterp_Dispatcher; - friend class PyInterp_ExecuteEvent; private: PyInterp_Request(); PyInterp_Request( const PyInterp_Request& ); protected: - virtual ~PyInterp_Request() {}; // protected destructor - to control deletion of requests + virtual ~PyInterp_Request() {}; public: + // Constructor PyInterp_Request( QObject* listener, bool sync = true ) : myIsSync( sync ), myListener( listener ) {}; - static void Destroy( PyInterp_Request* ); // Deletes a request + static void Destroy( PyInterp_Request* ); - bool IsSync() const { return myIsSync; } // Returns true if this request should be processed synchronously, // without putting it to a queue + bool IsSync() const { return myIsSync; } protected: + // Performs safe execution of the request virtual void safeExecute(); - virtual void execute() = 0; // Should be redefined in successors, contains actual request code + virtual void execute() = 0; - virtual QEvent* createEvent(); // This method can be overridden to customize notification event creation + virtual QEvent* createEvent(); virtual void processEvent( QObject* ); + // Provide access to the listener of this request QObject* listener() const { return myListener; } void setListener( QObject* ); private: + // Process request, invoked from Dispatcher void process(); private: @@ -85,17 +87,23 @@ private: QObject* myListener; }; +/** + \class PyInterp_LockRequest + \brief Python interpreter request; automatically acquires GIL during execution. + */ class PYINTERP_EXPORT PyInterp_LockRequest : public PyInterp_Request { public: - + // Constructor PyInterp_LockRequest( PyInterp_Interp* interp, QObject* listener=0, bool sync=true ) : PyInterp_Request( listener, sync ), myInterp( interp ) {} protected: + // Get interpreter PyInterp_Interp* getInterp() const { return myInterp; } + // Performs safe execution of the request virtual void safeExecute(); private: diff --git a/src/PyInterp/PyInterp_Utils.h b/src/PyInterp/PyInterp_Utils.h index f6f67b29d..8d6ce8c63 100644 --- a/src/PyInterp/PyInterp_Utils.h +++ b/src/PyInterp/PyInterp_Utils.h @@ -19,14 +19,14 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -// Author : Adrien BRUNETON -// +// File : PyInterp_Utils.h +// Author : Christian CAREMOLI, Paul RASCLE, Adrien BRUNETON #ifndef PYINTERP_UTILS_H #define PYINTERP_UTILS_H #include "PyInterp.h" -#include + #ifdef _DEBUG_ #include #endif @@ -43,7 +43,6 @@ */ class PYINTERP_EXPORT PyLockWrapper { - public: /** * \brief Constructor. Automatically acquires GIL. @@ -80,7 +79,6 @@ private: const PyLockWrapper & operator=(const PyLockWrapper & another); }; - /** * \class PyObjWrapper * \brief Utility class to properly handle the reference counting required on Python objects. @@ -107,5 +105,4 @@ public: } }; -#endif - +#endif // PYINTERP_UTILS_H diff --git a/src/PyInterp/PyInterp_Watcher.h b/src/PyInterp/PyInterp_Watcher.h deleted file mode 100755 index 8ae86180d..000000000 --- a/src/PyInterp/PyInterp_Watcher.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE -// -// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// - -// File : PyInterp_Watcher.h -// Author : Sergey Anikin, OCC -// Module : SALOME -// -#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/SALOME_PYQT/SalomePyQt/CMakeLists.txt b/src/SALOME_PYQT/SalomePyQt/CMakeLists.txt index f12e57d83..c8c88d5b5 100755 --- a/src/SALOME_PYQT/SalomePyQt/CMakeLists.txt +++ b/src/SALOME_PYQT/SalomePyQt/CMakeLists.txt @@ -42,7 +42,6 @@ INCLUDE_DIRECTORIES( ${PROJECT_SOURCE_DIR}/src/ObjBrowser ${PROJECT_SOURCE_DIR}/src/PyInterp ${PROJECT_SOURCE_DIR}/src/PyConsole - ${PROJECT_SOURCE_DIR}/src/SalomePyConsole ${PROJECT_SOURCE_DIR}/src/Qtx ${PROJECT_SOURCE_DIR}/src/SALOME_PYQT/SALOME_PYQT_GUILight ${PROJECT_SOURCE_DIR}/src/STD diff --git a/src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx b/src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx index 9cb8b540b..10dc38380 100644 --- a/src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx +++ b/src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx @@ -61,7 +61,7 @@ #include "SUIT_Tools.h" #include "SUIT_ViewManager.h" #include "SUIT_ViewWindow.h" -#include "SalomePyConsole_Console.h" +#include "PyConsole_Console.h" #include #include @@ -4001,7 +4001,7 @@ void SalomePyQt::startPyLog( const QString& theFileName ) virtual void Execute() { if ( getApplication() ) { - SalomePyConsole_Console* pyConsole = getApplication()->pythonConsole( false ); + PyConsole_Console* pyConsole = getApplication()->pythonConsole( false ); if ( pyConsole ) pyConsole->startLog( myFileName ); } } @@ -4021,7 +4021,7 @@ void SalomePyQt::stopPyLog() virtual void Execute() { if ( getApplication() ) { - SalomePyConsole_Console* pyConsole = getApplication()->pythonConsole( false ); + PyConsole_Console* pyConsole = getApplication()->pythonConsole( false ); if ( pyConsole ) pyConsole->stopLog(); } } diff --git a/src/SalomeApp/CMakeLists.txt b/src/SalomeApp/CMakeLists.txt index 4423d8d7d..8296bfcca 100755 --- a/src/SalomeApp/CMakeLists.txt +++ b/src/SalomeApp/CMakeLists.txt @@ -56,7 +56,6 @@ INCLUDE_DIRECTORIES( IF(SALOME_USE_PYCONSOLE) INCLUDE_DIRECTORIES( ${PYTHON_INCLUDE_DIRS} - ${PROJECT_SOURCE_DIR}/src/SalomePyConsole ${PROJECT_SOURCE_DIR}/src/PyConsole ${PROJECT_SOURCE_DIR}/src/PyInterp ) @@ -90,7 +89,7 @@ IF(SALOME_USE_VTKVIEWER) ENDIF() IF(SALOME_USE_PYCONSOLE) - LIST(APPEND _link_LIBRARIES PyInterp SalomePyConsole) + LIST(APPEND _link_LIBRARIES PyInterp PyConsole) ENDIF() IF(SALOME_USE_GLVIEWER) diff --git a/src/SalomeApp/SalomeApp_Application.cxx b/src/SalomeApp/SalomeApp_Application.cxx index 32f9e37fb..eaec2acde 100644 --- a/src/SalomeApp/SalomeApp_Application.cxx +++ b/src/SalomeApp/SalomeApp_Application.cxx @@ -35,9 +35,10 @@ #endif #ifndef DISABLE_PYCONSOLE - #include "SalomeApp_PyInterp.h" // WARNING! This include must be the first! - #include + #include "SalomeApp_PyInterp.h" #include "SalomeApp_NoteBook.h" + #include "LightApp_PyEditor.h" + #include "PyConsole_Console.h" #endif #include "SalomeApp_Application.h" #include "SalomeApp_Study.h" @@ -49,6 +50,7 @@ #include "SalomeApp_ExitDlg.h" #include +#include #include #include #include @@ -62,7 +64,6 @@ #include #include #include -#include #include #include #include @@ -253,7 +254,7 @@ void SalomeApp_Application::start() // import/execute python scripts if ( pyfiles.count() > 0 && activeStudy() ) { SalomeApp_Study* appStudy = dynamic_cast( activeStudy() ); - SalomePyConsole_Console* pyConsole = pythonConsole(); + PyConsole_Console* pyConsole = pythonConsole(); if ( appStudy && pyConsole ) { _PTR(Study) aStudy = appStudy->studyDS(); if ( !aStudy->GetProperties()->IsLocked() ) { @@ -505,7 +506,7 @@ void SalomeApp_Application::onNewWithScript() QString command = QString("execfile(r\"%1\")").arg(aFile); #ifndef DISABLE_PYCONSOLE - SalomePyConsole_Console* pyConsole = pythonConsole(); + PyConsole_Console* pyConsole = pythonConsole(); if ( pyConsole ) pyConsole->exec( command ); @@ -853,26 +854,6 @@ public: QCheckBox* mySaveGUIChk; }; -class DumpStudyFileValidator : public SUIT_FileValidator -{ - public: - DumpStudyFileValidator( QWidget* parent) : SUIT_FileValidator ( parent ) {}; - virtual ~DumpStudyFileValidator() {}; - virtual bool canSave( const QString& file, bool permissions ); -}; - -bool DumpStudyFileValidator::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); -} - /*!Private SLOT. On dump study.*/ void SalomeApp_Application::onDumpStudy( ) { @@ -894,7 +875,7 @@ void SalomeApp_Application::onDumpStudy( ) } DumpStudyFileDlg fd( desktop() ); - fd.setValidator( new DumpStudyFileValidator( &fd ) ); + fd.setValidator( new LightApp_PyFileValidator( &fd ) ); fd.setWindowTitle( tr( "TOT_DESK_FILE_DUMP_STUDY" ) ); fd.setNameFilters( aFilters ); fd.myPublishChk->setChecked( anIsPublish ); @@ -956,7 +937,7 @@ void SalomeApp_Application::onLoadScript( ) QString command = QString("execfile(r\"%1\")").arg(aFile); #ifndef DISABLE_PYCONSOLE - SalomePyConsole_Console* pyConsole = pythonConsole(); + PyConsole_Console* pyConsole = pythonConsole(); if ( pyConsole ) pyConsole->exec( command ); @@ -1076,15 +1057,14 @@ QWidget* SalomeApp_Application::createWindow( const int flag ) #ifndef DISABLE_PYCONSOLE else if ( flag == WT_PyConsole ) { - SalomePyConsole_Console* pyCons = new SalomePyConsole_EnhConsole( desktop(), getPyInterp() ); + PyConsole_Console* pyCons = new PyConsole_Console( desktop(), new LightApp_PyEditor( getPyInterp() ) ); pyCons->setObjectName( "pythonConsole" ); pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) ); pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" )); pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true )); + pyCons->setAutoCompletion( resMgr->booleanValue( "PyConsole", "auto_completion", true ) ); pyCons->setProperty( "shortcut", QKeySequence( "Alt+Shift+P" ) ); wid = pyCons; - //pyCons->resize( pyCons->width(), desktop()->height()/4 ); - pyCons->connectPopupRequest( this, SLOT( onConnectPopupRequest( SUIT_PopupClient*, QContextMenuEvent* ) ) ); } else if ( flag == WT_NoteBook ) { @@ -2028,7 +2008,7 @@ bool SalomeApp_Application::onRestoreStudy( const QString& theDumpScript, QString command = QString( "execfile(r\"%1\")" ).arg( theDumpScript ); #ifndef DISABLE_PYCONSOLE - SalomePyConsole_Console* pyConsole = app->pythonConsole(); + PyConsole_Console* pyConsole = app->pythonConsole(); if ( pyConsole ) pyConsole->execAndWait( command ); #endif diff --git a/src/SalomeApp/SalomeApp_NoteBook.cxx b/src/SalomeApp/SalomeApp_NoteBook.cxx index 7d3c79c99..749ce3798 100644 --- a/src/SalomeApp/SalomeApp_NoteBook.cxx +++ b/src/SalomeApp/SalomeApp_NoteBook.cxx @@ -22,7 +22,7 @@ // Module : GUI // #include "PyConsole_Interp.h" // this include must be first (see PyInterp_base.h)! -#include "SalomePyConsole_Console.h" +#include "PyConsole_Console.h" #include "SalomeApp_NoteBook.h" #include "SalomeApp_Application.h" @@ -284,7 +284,7 @@ bool NoteBook_TableRow::IsValidStringValue(const QString theValue) myParentTable->myRows[ aNumRows - 1 ]->GetValue().isEmpty(); SalomeApp_Application* app = dynamic_cast( SUIT_Session::session()->activeApplication() ); - SalomePyConsole_Console* pyConsole = app->pythonConsole(); + PyConsole_Console* pyConsole = app->pythonConsole(); PyConsole_Interp* pyInterp = app->getPyInterp(); PyLockWrapper aLock; // Acquire GIL std::string command = "import salome_notebook ; "; @@ -458,7 +458,7 @@ bool NoteBook_Table::IsValid() const return false; SalomeApp_Application* app = dynamic_cast( SUIT_Session::session()->activeApplication() ); - SalomePyConsole_Console* pyConsole = app->pythonConsole(); + PyConsole_Console* pyConsole = app->pythonConsole(); PyConsole_Interp* pyInterp = app->getPyInterp(); PyLockWrapper aLock; // Acquire GIL std::string command = "import salome_notebook ; "; diff --git a/src/SalomeApp/SalomeApp_PyInterp.cxx b/src/SalomeApp/SalomeApp_PyInterp.cxx index f27a0d2c4..e79c83613 100755 --- a/src/SalomeApp/SalomeApp_PyInterp.cxx +++ b/src/SalomeApp/SalomeApp_PyInterp.cxx @@ -19,47 +19,28 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // - -// SALOME SALOMEGUI : implementation of desktop and GUI kernel // File : SalomeApp_PyInterp.cxx // Author : Nicolas REJNERI #include "SalomeApp_PyInterp.h" -#include -#include - -#include "PyInterp.h" // this include must be first (see PyInterp_base.h)! - /*! - * constructor : multi Python interpreter, one per SALOME study. - * calls initialize method defined in base class, which calls virtual methods - * initstate & initcontext redefined here. - */ -SalomeApp_PyInterp::SalomeApp_PyInterp(): - PyConsole_EnhInterp(), myFirstRun( true ), myFirstInitStudy( false ) + \brief Constructor +*/ +SalomeApp_PyInterp::SalomeApp_PyInterp() + : PyConsole_Interp(), myFirstRun( true ), myFirstInitStudy( false ) { } /*! - * Destructor. - */ + \brief Destructor. +*/ SalomeApp_PyInterp::~SalomeApp_PyInterp() { } /*! - Do nothing (we could rely on the test done in the implementation of this method in the super - class PyInterp_Interp, but in this context we are sure the initialization has been done in main() - of SALOME_Session_Server) - */ -void SalomeApp_PyInterp::initPython() -{ - MESSAGE("SalomeApp_PyInterp::initPython - does nothing"); -} - -/*! - Called before each Python command running. + \brief Called before each Python command running. */ int SalomeApp_PyInterp::beforeRun() { @@ -69,23 +50,29 @@ int SalomeApp_PyInterp::beforeRun() if ( ret ) return ret; } - if( myFirstInitStudy ) { + if ( myFirstInitStudy ) { myFirstInitStudy = false; int ret = simpleRun( "import salome", false ); - if (ret) + if ( ret ) return ret; ret = simpleRun( "salome.salome_init(0,1)", false ); - if (ret) + if ( ret ) return ret; } - return PyConsole_EnhInterp::beforeRun(); + return PyConsole_Interp::beforeRun(); } +/*! + \brief Called when study is initialized + */ void SalomeApp_PyInterp::initStudy() { myFirstInitStudy = true; } +/*! + \brief Called when study is closed +*/ void SalomeApp_PyInterp::closeContext() { myFirstInitStudy = false; diff --git a/src/SalomeApp/SalomeApp_PyInterp.h b/src/SalomeApp/SalomeApp_PyInterp.h index c1e8773e1..567b25235 100755 --- a/src/SalomeApp/SalomeApp_PyInterp.h +++ b/src/SalomeApp/SalomeApp_PyInterp.h @@ -19,24 +19,21 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // - -// SALOME SALOMEGUI : implementation of desktop and GUI kernel // File : SalomeApp_PyInterp.h // Author : Nicolas REJNERI -#ifndef _SalomeApp_PYINTERP_H_ -#define _SalomeApp_PYINTERP_H_ +#ifndef SALOMEAPP_PYINTERP_H +#define SALOMEAPP_PYINTERP_H -#include // this include must be first (see PyInterp_base.h)! +#include -class SalomeApp_PyInterp : public PyConsole_EnhInterp +class SalomeApp_PyInterp : public PyConsole_Interp { friend class SalomeApp_Application; public: virtual ~SalomeApp_PyInterp(); - virtual void initPython(); virtual void initStudy(); virtual void closeContext(); @@ -49,4 +46,4 @@ private: bool myFirstInitStudy; }; -#endif +#endif // SALOMEAPP_PYINTERP_H diff --git a/src/SalomeApp/resources/SalomeApp_msg_en.ts b/src/SalomeApp/resources/SalomeApp_msg_en.ts index 59eb414fa..58fb8aced 100644 --- a/src/SalomeApp/resources/SalomeApp_msg_en.ts +++ b/src/SalomeApp/resources/SalomeApp_msg_en.ts @@ -3,11 +3,6 @@ @default - - WRN_FILE_NAME_BAD - Please enter correct file name. -Python file must include only letters, digits and underscores and start from letter or underscore. - WRN_FILE_NOT_EXIST The file %1 does not exist. @@ -246,10 +241,6 @@ Do you want to reload it ? PRP_DESK_REGISTRY_DISPLAY Displays content of the Registry CORBA server - - PYTHON_FILES_FILTER - PYTHON Files (*.py) - APPCLOSE_DESCRIPTION Do you want to save study before closing? diff --git a/src/SalomeApp/resources/SalomeApp_msg_fr.ts b/src/SalomeApp/resources/SalomeApp_msg_fr.ts index c25adc908..5709c9727 100755 --- a/src/SalomeApp/resources/SalomeApp_msg_fr.ts +++ b/src/SalomeApp/resources/SalomeApp_msg_fr.ts @@ -3,11 +3,6 @@ @default - - WRN_FILE_NAME_BAD - Indiquez un nom de fichier correct. -Un fichier Python ne doit être composé que de lettres, chiffres et tirets bas et doit commencer avec une lettre ou un tiret bas. - WRN_FILE_NOT_EXIST Le fichier %1 n'existe pas. @@ -246,10 +241,6 @@ Voulez-vous le recharger ? PRP_DESK_REGISTRY_DISPLAY Visualiser le contenu du registre du serveur CORBA - - PYTHON_FILES_FILTER - Fichiers PYTHON (*.py) - APPCLOSE_DESCRIPTION Voulez-vous fermer ou décharger l'étude avant de la fermer ? diff --git a/src/SalomeApp/resources/SalomeApp_msg_ja.ts b/src/SalomeApp/resources/SalomeApp_msg_ja.ts index fe8c7708f..1d9a98edb 100644 --- a/src/SalomeApp/resources/SalomeApp_msg_ja.ts +++ b/src/SalomeApp/resources/SalomeApp_msg_ja.ts @@ -3,10 +3,6 @@ @default - - WRN_FILE_NAME_BAD - 有効なファイル名を入力してください。Pythonのファイル名は、文字、数字、およびアンダー スコアで構成され、文字かアンダー スコアで始まる必要があります。 - WRN_FILE_NOT_EXIST ファイル %1 は存在しません。 @@ -245,10 +241,6 @@ PRP_DESK_REGISTRY_DISPLAY CORBAサーバーの登録内容を表示 - - PYTHON_FILES_FILTER - ファイル (*.py) PYTHON - APPCLOSE_DESCRIPTION 閉じる、または閉じる前にスタディをアンロードしますか? diff --git a/src/SalomePyConsole/CMakeLists.txt b/src/SalomePyConsole/CMakeLists.txt deleted file mode 100755 index 25e3c4972..000000000 --- a/src/SalomePyConsole/CMakeLists.txt +++ /dev/null @@ -1,90 +0,0 @@ -# Copyright (C) 2012-2016 CEA/DEN, EDF R&D, OPEN CASCADE -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -# - -INCLUDE(UseQt4Ext) - -# --- options --- - -# additional include directories -INCLUDE_DIRECTORIES( - ${QT_INCLUDES} - ${PYTHON_INCLUDE_DIRS} - ${PROJECT_SOURCE_DIR}/src/SalomePyConsole - ${PROJECT_SOURCE_DIR}/src/PyConsole - ${PROJECT_SOURCE_DIR}/src/Qtx - ${PROJECT_SOURCE_DIR}/src/SUIT - ${PROJECT_SOURCE_DIR}/src/Event - ${PROJECT_SOURCE_DIR}/src/PyInterp -) - -# additional preprocessor / compiler flags -ADD_DEFINITIONS(${QT_DEFINITIONS} ${PYTHON_DEFINITIONS}) - -# libraries to link to -SET(_link_LIBRARIES ${QT_LIBRARIES} ${PYTHON_LIBRARIES} qtx suit PyConsole) - -# --- headers --- - -# header files / to be processed by moc -SET(_moc_HEADERS - SalomePyConsole_Console.h - SalomePyConsole_Editor.h - SalomePyConsole_EnhEditor.h -) - -# header files / no moc processing -SET(_other_HEADERS - SalomePyConsole.h -) - -# header files / to install -SET(SalomePyConsole_HEADERS ${_moc_HEADERS} ${_other_HEADERS}) - -# --- resources --- - -# --- sources --- -# resource files / to be processed by lrelease - -SET(_ts_RESOURCES - resources/SalomePyConsole_msg_en.ts - resources/SalomePyConsole_msg_fr.ts - resources/SalomePyConsole_msg_ja.ts -) - -# sources / moc wrappings -QT4_WRAP_CPP(_moc_SOURCES ${_moc_HEADERS}) - -# sources / static -SET(_other_SOURCES - SalomePyConsole_Console.cxx - SalomePyConsole_EnhEditor.cxx - SalomePyConsole_Editor.cxx -) - -# sources / to compile -SET(PyConsole_SOURCES ${_other_SOURCES} ${_moc_SOURCES}) - -# --- rules --- - -ADD_LIBRARY(SalomePyConsole ${PyConsole_SOURCES}) -TARGET_LINK_LIBRARIES(SalomePyConsole ${_link_LIBRARIES}) -INSTALL(TARGETS SalomePyConsole EXPORT ${PROJECT_NAME}TargetGroup DESTINATION ${SALOME_INSTALL_LIBS}) - -INSTALL(FILES ${SalomePyConsole_HEADERS} DESTINATION ${SALOME_INSTALL_HEADERS}) -QT4_INSTALL_TS_RESOURCES("${_ts_RESOURCES}" "${SALOME_GUI_INSTALL_RES_DATA}") diff --git a/src/SalomePyConsole/SalomePyConsole.h b/src/SalomePyConsole/SalomePyConsole.h deleted file mode 100644 index fba1243e2..000000000 --- a/src/SalomePyConsole/SalomePyConsole.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE -// -// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// - -// File : PyConsole.h -// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) -// -#if !defined ( SALOMEPYCONSOLE_H ) -#define SALOMEPYCONSOLE_H - -// ======================================================== -// set dllexport type for Win platform -#ifdef WIN32 -# if defined SALOMEPYCONSOLE_EXPORTS || defined SalomePyConsole_EXPORTS -# define SALOMEPYCONSOLE_EXPORT __declspec(dllexport) -# else -# define SALOMEPYCONSOLE_EXPORT __declspec(dllimport) -# endif -#else // WIN32 -# define SALOMEPYCONSOLE_EXPORT -#endif // WIN32 - -// ======================================================== -// avoid warning messages -#ifdef WIN32 -#pragma warning (disable : 4786) -#pragma warning (disable : 4251) -#endif - -#endif // SALOMEPYCONSOLE_H diff --git a/src/SalomePyConsole/SalomePyConsole_Console.cxx b/src/SalomePyConsole/SalomePyConsole_Console.cxx deleted file mode 100644 index 163e29c8a..000000000 --- a/src/SalomePyConsole/SalomePyConsole_Console.cxx +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE -// -// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// - -// File : PyConsole_Console.cxx -// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) -// -/*! - \class PyConsole_Console - \brief Python console widget. -*/ - -#include "PyConsole_Interp.h" /// !!! WARNING !!! THIS INCLUDE MUST BE VERY FIRST !!! -#include "SalomePyConsole_Console.h" -#include "SalomePyConsole_Editor.h" -#include "SalomePyConsole_EnhEditor.h" -#include "PyConsole_EnhInterp.h" - -#include - -#include -#include -#include -#include -#include -#include - -PyConsole_EditorBase *SalomePyConsole_Console::SalomePyConsole_Interp_Creator::createEditor( PyConsole_Interp *interp, PyConsole_ConsoleBase *console ) const -{ return new SalomePyConsole_Editor(interp,console); } - -PyConsole_Interp *SalomePyConsole_Console::SalomePyConsole_Interp_Creator::createInterp( ) const -{ return new PyConsole_Interp; } - -/*! - \brief Constructor. - - Creates new python console widget. - \param parent parent widget - \param interp python interpreter -*/ -SalomePyConsole_Console::SalomePyConsole_Console( QWidget* parent, PyConsole_Interp* interp ) - : PyConsole_ConsoleBase( parent, interp, 0 ) -{ - SalomePyConsole_Interp_Creator crea; - defaultConstructor(interp,crea); -} - -/** - * Protected constructor. - */ -SalomePyConsole_Console::SalomePyConsole_Console( QWidget* parent, PyConsole_Interp* i, SalomePyConsole_Editor* e ) - : PyConsole_ConsoleBase(parent,i,e) -{ -} - -/*! - \brief Destructor. - - Does nothing for the moment. -*/ -SalomePyConsole_Console::~SalomePyConsole_Console() -{ -} - -/*! - \brief Create the context popup menu. - - Fill in the popup menu with the commands. - - \param menu context popup menu -*/ -void SalomePyConsole_Console::contextMenuPopup( QMenu *menu ) -{ - PyConsole_ConsoleBase::contextMenuPopup(menu); -} - -/*! - \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 SalomePyConsole_Console::eventFilter( QObject* o, QEvent* e ) -{ - if ( o == myEditor->viewport() && e->type() == QEvent::ContextMenu ) - { - contextMenuRequest( (QContextMenuEvent*)e ); - return true; - } - return QWidget::eventFilter( o, e ); -} - -PyConsole_EditorBase *SalomePyConsole_EnhConsole::SalomePyConsole_Interp_EnhCreator::createEditor( PyConsole_Interp *interp, PyConsole_ConsoleBase *console ) const -{ return new SalomePyConsole_EnhEditor(interp,console); } - -PyConsole_Interp *SalomePyConsole_EnhConsole::SalomePyConsole_Interp_EnhCreator::createInterp( ) const -{ return new PyConsole_EnhInterp; } - -/** - * 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 - */ -SalomePyConsole_EnhConsole::SalomePyConsole_EnhConsole( QWidget* parent, PyConsole_Interp* interp ) - : SalomePyConsole_Console( parent, interp, 0 ) -{ - SalomePyConsole_Interp_EnhCreator crea; - defaultConstructor(interp,crea); -} diff --git a/src/SalomePyConsole/SalomePyConsole_Console.h b/src/SalomePyConsole/SalomePyConsole_Console.h deleted file mode 100644 index d797c42a3..000000000 --- a/src/SalomePyConsole/SalomePyConsole_Console.h +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE -// -// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// - -// File : PyConsole_Console.h -// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) -// -#ifndef SALOMEPYCONSOLE_CONSOLE_H -#define SALOMEPYCONSOLE_CONSOLE_H - -#include "SalomePyConsole.h" -#include -#include -#include -#include - -class SalomePyConsole_Interp; -class SalomePyConsole_Editor; - -class SALOMEPYCONSOLE_EXPORT SalomePyConsole_Console : public PyConsole_ConsoleBase, public SUIT_PopupClient -{ - Q_OBJECT -public: - - struct SalomePyConsole_Interp_Creator : public PyConsole_Interp_CreatorBase - { - virtual PyConsole_EditorBase *createEditor( PyConsole_Interp *interp, PyConsole_ConsoleBase *console ) const; - virtual PyConsole_Interp *createInterp( ) const; - }; - -public: - SalomePyConsole_Console( QWidget* parent, PyConsole_Interp* interp = 0 ); - virtual ~SalomePyConsole_Console(); - //! \brief Get popup client symbolic name - virtual QString popupClientType() const { return QString( "PyConsole" ); } - virtual void contextMenuPopup( QMenu* ); - virtual bool eventFilter( QObject*, QEvent* ); -protected: - SalomePyConsole_Console( QWidget* parent, PyConsole_Interp*, SalomePyConsole_Editor*); -}; - -/** - * Enhance console object providing auto-completion. - * Similar to PyConsole_Console except that an enhanced interpreter and enhanced editor - * are encapsulated. - */ -class PYCONSOLE_EXPORT SalomePyConsole_EnhConsole : public SalomePyConsole_Console -{ - Q_OBJECT -public: - - struct SalomePyConsole_Interp_EnhCreator : public PyConsole_Interp_CreatorBase - { - virtual PyConsole_EditorBase *createEditor( PyConsole_Interp *interp, PyConsole_ConsoleBase *console ) const; - virtual PyConsole_Interp *createInterp( ) const; - }; - -public: - SalomePyConsole_EnhConsole( QWidget* parent, PyConsole_Interp* interp = 0 ); - virtual ~SalomePyConsole_EnhConsole() {} -}; - -#endif // SALOMEPYCONSOLE_CONSOLE_H diff --git a/src/SalomePyConsole/SalomePyConsole_Editor.cxx b/src/SalomePyConsole/SalomePyConsole_Editor.cxx deleted file mode 100644 index f55eb7a16..000000000 --- a/src/SalomePyConsole/SalomePyConsole_Editor.cxx +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE -// -// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// - -// SALOME SALOMEGUI : implementation of desktop and GUI kernel -// File : PyConsole_Editor.cxx -// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) -// -/*! - \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 "SalomePyConsole_Editor.h" -#include "PyConsole_Event.h" -#include "PyInterp_Event.h" -#include "PyInterp_Dispatcher.h" -#include "PyConsole_Request.h" - -#include "SUIT_FileValidator.h" -#include "SUIT_MessageBox.h" -#include "SUIT_FileDlg.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -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); -} - -/*! - \brief Constructor. - - Creates python editor window. - \param theInterp python interper - \param theParent parent widget -*/ -SalomePyConsole_Editor::SalomePyConsole_Editor( PyConsole_Interp* theInterp, - QWidget* theParent ) - : PyConsole_EditorBase(theInterp,theParent) -{ -} - -/*! - \brief Destructor. -*/ -SalomePyConsole_Editor::~SalomePyConsole_Editor() -{ -} - - -void SalomePyConsole_Editor::StaticDumpSlot(PyConsole_EditorBase *base) -{ - QStringList aFilters; - aFilters.append( tr( "PYTHON_FILES_FILTER" ) ); - - QString fileName = SUIT_FileDlg::getFileName( base, QString(), - aFilters, tr( "TOT_DUMP_PYCOMMANDS" ), - false, true, new DumpCommandsFileValidator( base ) ); - base->dumpImpl(fileName); -} - -/*! - \brief "Dump commands" operation. - */ -void SalomePyConsole_Editor::dumpSlot() -{ - SalomePyConsole_Editor::StaticDumpSlot(this); -} - -void SalomePyConsole_Editor::StaticStartLogSlot(PyConsole_EditorBase *base) -{ - QStringList aFilters; - aFilters.append( tr( "LOG_FILES_FILTER" ) ); - - while (1) { - QString fileName = SUIT_FileDlg::getFileName( base, QString(), - aFilters, tr( "TOT_SAVE_PYLOG" ), - false, true ); - if ( !fileName.isEmpty() ) { - if ( base->startLogImpl( fileName ) ) { - break; - } - else { - SUIT_MessageBox::critical( base, - QObject::tr("ERR_ERROR"), - QObject::tr("ERR_FILE_NOT_WRITABLE") ); - } - } - else { - break; - } - } -} - -/*! - \brief "Start log" operation. - */ -void SalomePyConsole_Editor::startLogSlot() -{ - StaticStartLogSlot(this); -} diff --git a/src/SalomePyConsole/SalomePyConsole_Editor.h b/src/SalomePyConsole/SalomePyConsole_Editor.h deleted file mode 100644 index 9d38de07b..000000000 --- a/src/SalomePyConsole/SalomePyConsole_Editor.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE -// -// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// - -// SALOME SALOMEGUI : implementation of desktop and GUI kernel -// File : PyConsole_Editor.h -// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) -// -#ifndef SALOMEPYCONSOLE_EDITOR_H -#define SALOMEPYCONSOLE_EDITOR_H - -#include "SalomePyConsole.h" -#include "PyConsole_EditorBase.h" - -#include - -class PyConsole_Interp; -class PyInterp_Request; -class QEventLoop; - -class PYCONSOLE_EXPORT SalomePyConsole_Editor : public PyConsole_EditorBase -{ - Q_OBJECT; -public: - SalomePyConsole_Editor( PyConsole_Interp* theInterp, QWidget *theParent = 0 ); - ~SalomePyConsole_Editor(); - static void StaticDumpSlot(PyConsole_EditorBase *base); - static void StaticStartLogSlot(PyConsole_EditorBase *base); -protected: - virtual void dumpSlot(); - virtual void startLogSlot(); -}; - -#endif // SALOMEPYCONSOLE_EDITOR_H diff --git a/src/SalomePyConsole/SalomePyConsole_EnhEditor.cxx b/src/SalomePyConsole/SalomePyConsole_EnhEditor.cxx deleted file mode 100644 index be02e7cf2..000000000 --- a/src/SalomePyConsole/SalomePyConsole_EnhEditor.cxx +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com -// -// Author : Adrien Bruneton (CEA/DEN) -// Created on: 4 avr. 2013 - -#include "SalomePyConsole.h" -#include - -#include -#include -#include -#include -#include -#include - -#include "SalomePyConsole_EnhEditor.h" -#include "SalomePyConsole_Editor.h" - -/** - * Constructor. - * @param interp the interpreter linked to the editor - * @param parent parent widget - */ -SalomePyConsole_EnhEditor::SalomePyConsole_EnhEditor(PyConsole_Interp* interp, QWidget* parent) : - PyConsole_EnhEditorBase(interp, parent) -{ -} - -void SalomePyConsole_EnhEditor::dumpSlot() -{ - SalomePyConsole_Editor::StaticDumpSlot(this); -} - -void SalomePyConsole_EnhEditor::startLogSlot() -{ - SalomePyConsole_Editor::StaticStartLogSlot(this); -} diff --git a/src/SalomePyConsole/resources/SalomePyConsole_msg_en.ts b/src/SalomePyConsole/resources/SalomePyConsole_msg_en.ts deleted file mode 100644 index 7fcc5bc60..000000000 --- a/src/SalomePyConsole/resources/SalomePyConsole_msg_en.ts +++ /dev/null @@ -1,27 +0,0 @@ - - - - - SalomePyConsole_Editor - - TOT_DUMP_PYCOMMANDS - Dump commands - - - TOT_SAVE_PYLOG - Save log - - - PYTHON_FILES_FILTER - PYTHON Files (*.py) - - - LOG_FILES_FILTER - Log files (*.log *.txt) - - - ERR_FILE_NOT_WRITABLE - File is not writable! - - - diff --git a/src/SalomePyConsole/resources/SalomePyConsole_msg_fr.ts b/src/SalomePyConsole/resources/SalomePyConsole_msg_fr.ts deleted file mode 100644 index 3626118fa..000000000 --- a/src/SalomePyConsole/resources/SalomePyConsole_msg_fr.ts +++ /dev/null @@ -1,27 +0,0 @@ - - - - - SalomePyConsole_Editor - - TOT_DUMP_PYCOMMANDS - &Générer le script des commandes - - - TOT_SAVE_PYLOG - Sauver la trace - - - PYTHON_FILES_FILTER - Fichiers PYTHON (*.py) - - - LOG_FILES_FILTER - Fichiers de trace (*.log *.txt) - - - ERR_FILE_NOT_WRITABLE - Le fichier n'est pas accessible en écriture! - - - diff --git a/src/SalomePyConsole/resources/SalomePyConsole_msg_ja.ts b/src/SalomePyConsole/resources/SalomePyConsole_msg_ja.ts deleted file mode 100644 index 3f579c626..000000000 --- a/src/SalomePyConsole/resources/SalomePyConsole_msg_ja.ts +++ /dev/null @@ -1,27 +0,0 @@ - - - - - SalomePyConsole_Editor - - TOT_DUMP_PYCOMMANDS - スクリプト コマンドを生成します。 - - - TOT_SAVE_PYLOG - ログの保存 - - - PYTHON_FILES_FILTER - ファイル (*.py) PYTHON - - - LOG_FILES_FILTER - ログファイル (*.log *.txt) - - - ERR_FILE_NOT_WRITABLE - ファイルが書き込み禁止です! - - - -- 2.30.2