Salome HOME
Clean up Python features
authorvsr <vsr@opencascade.com>
Wed, 16 Mar 2016 13:50:07 +0000 (16:50 +0300)
committervsr <vsr@opencascade.com>
Fri, 18 Mar 2016 13:27:19 +0000 (16:27 +0300)
74 files changed:
CMakeLists.txt
SalomeGUIConfig.cmake.in
adm_local/cmake_files/FindGUI.cmake
adm_local/cmake_files/deprecated/FindGUI.cmake
src/CMakeLists.txt
src/LightApp/CMakeLists.txt
src/LightApp/LightApp_Application.cxx
src/LightApp/LightApp_Application.h
src/LightApp/LightApp_FileValidator.cxx [new file with mode: 0644]
src/LightApp/LightApp_FileValidator.h [new file with mode: 0644]
src/LightApp/LightApp_PyEditor.cxx [new file with mode: 0644]
src/LightApp/LightApp_PyEditor.h [new file with mode: 0644]
src/LightApp/LightApp_PyInterp.cxx [deleted file]
src/LightApp/LightApp_PyInterp.h [deleted file]
src/LightApp/resources/LightApp.xml
src/LightApp/resources/LightApp_msg_en.ts
src/LightApp/resources/LightApp_msg_fr.ts
src/LightApp/resources/LightApp_msg_ja.ts
src/PyConsole/CMakeLists.txt
src/PyConsole/PyConsole.h
src/PyConsole/PyConsole_Console.cxx [new file with mode: 0644]
src/PyConsole/PyConsole_Console.h [new file with mode: 0644]
src/PyConsole/PyConsole_ConsoleBase.cxx [deleted file]
src/PyConsole/PyConsole_ConsoleBase.h [deleted file]
src/PyConsole/PyConsole_Editor.cxx [new file with mode: 0644]
src/PyConsole/PyConsole_Editor.h [new file with mode: 0644]
src/PyConsole/PyConsole_EditorBase.cxx [deleted file]
src/PyConsole/PyConsole_EditorBase.h [deleted file]
src/PyConsole/PyConsole_EnhEditorBase.cxx [deleted file]
src/PyConsole/PyConsole_EnhEditorBase.h [deleted file]
src/PyConsole/PyConsole_EnhInterp.cxx [deleted file]
src/PyConsole/PyConsole_EnhInterp.h [deleted file]
src/PyConsole/PyConsole_Event.cxx
src/PyConsole/PyConsole_Event.h
src/PyConsole/PyConsole_Interp.cxx
src/PyConsole/PyConsole_Interp.h
src/PyConsole/PyConsole_Request.cxx
src/PyConsole/PyConsole_Request.h
src/PyConsole/resources/PyConsole_msg_en.ts
src/PyConsole/resources/PyConsole_msg_fr.ts
src/PyConsole/resources/PyConsole_msg_ja.ts
src/PyInterp/CMakeLists.txt
src/PyInterp/PyInterp.h
src/PyInterp/PyInterp_Dispatcher.cxx
src/PyInterp/PyInterp_Dispatcher.h
src/PyInterp/PyInterp_Event.cxx
src/PyInterp/PyInterp_Event.h
src/PyInterp/PyInterp_Interp.cxx
src/PyInterp/PyInterp_Interp.h
src/PyInterp/PyInterp_Request.cxx
src/PyInterp/PyInterp_Request.h
src/PyInterp/PyInterp_Utils.h
src/PyInterp/PyInterp_Watcher.h [deleted file]
src/SALOME_PYQT/SalomePyQt/CMakeLists.txt
src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx
src/SalomeApp/CMakeLists.txt
src/SalomeApp/SalomeApp_Application.cxx
src/SalomeApp/SalomeApp_NoteBook.cxx
src/SalomeApp/SalomeApp_PyInterp.cxx
src/SalomeApp/SalomeApp_PyInterp.h
src/SalomeApp/resources/SalomeApp_msg_en.ts
src/SalomeApp/resources/SalomeApp_msg_fr.ts
src/SalomeApp/resources/SalomeApp_msg_ja.ts
src/SalomePyConsole/CMakeLists.txt [deleted file]
src/SalomePyConsole/SalomePyConsole.h [deleted file]
src/SalomePyConsole/SalomePyConsole_Console.cxx [deleted file]
src/SalomePyConsole/SalomePyConsole_Console.h [deleted file]
src/SalomePyConsole/SalomePyConsole_Editor.cxx [deleted file]
src/SalomePyConsole/SalomePyConsole_Editor.h [deleted file]
src/SalomePyConsole/SalomePyConsole_EnhEditor.cxx [deleted file]
src/SalomePyConsole/SalomePyConsole_EnhEditor.h [deleted file]
src/SalomePyConsole/resources/SalomePyConsole_msg_en.ts [deleted file]
src/SalomePyConsole/resources/SalomePyConsole_msg_fr.ts [deleted file]
src/SalomePyConsole/resources/SalomePyConsole_msg_ja.ts [deleted file]

index 419d7fa34974ae60e0edbf956b79f0dc7ca544dd..0f392c83534c0cecd83a03a55c2a2b93a4a10362 100755 (executable)
@@ -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()
index 71831b1e1af6d15c6882f37c6f6de2b3295aff2a..94483ffcf6d7a1e573e86902c8f228d57d2af249 100644 (file)
@@ -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)
index 7d7b3b101d6b1a121997999aa3509d0946bdf86b..55d26381c33000a632fe18e5a53f325ec3b740f1 100644 (file)
@@ -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)
index eec0114864e1afbb82dbbff9b0c36c6757c14e62..ef595dd54386a5b6e0c9d40ceed1f9b166a65032 100644 (file)
@@ -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)
index cb92cbb5ac771c2e8b0c94ec1639f16cd592f654..052ae86c5881c3beb8330f145f0342d82ece131e 100755 (executable)
@@ -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)
 
index f37381f249b66f5acf00a556e0fd7a87b8ee89c2..d4a69eab3c388fd5c48bd43e2e8a305f340c11d5 100755 (executable)
@@ -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
index dfb449153b98a69ad0ab7159c1ffdd20f52871a0..4bf97d8ca2e815371ad2ad487afc1f9bd555de95 100644 (file)
@@ -35,8 +35,9 @@
 #endif
 
 #ifndef DISABLE_PYCONSOLE
-  #include "LightApp_PyInterp.h" // WARNING! This include must be the first!
-  #include <SalomePyConsole_Console.h>
+  #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<SalomePyConsole_Console*>( wid );
+  return qobject_cast<PyConsole_Console*>( 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 <<start>>
   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 <<end>>
 
   // ... "MRU" preferences group <<start>>
@@ -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
index 9284aa2fbedf2783592437aa89142c88f839c589..92654622873d8cb04626f4c85317dbe4d863fd89 100644 (file)
@@ -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 (file)
index 0000000..4f8179c
--- /dev/null
@@ -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 <QFileInfo>
+
+/*!
+  \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_FileValidator.h b/src/LightApp/LightApp_FileValidator.h
new file mode 100644 (file)
index 0000000..eff8390
--- /dev/null
@@ -0,0 +1,36 @@
+// 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.h
+// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
+
+#ifndef LIGHTAPP_FILEVALIDATOR_H
+#define LIGHTAPP_FILEVALIDATOR_H
+
+#include "LightApp.h"
+#include "SUIT_FileValidator.h"
+
+class LIGHTAPP_EXPORT LightApp_PyFileValidator : public SUIT_FileValidator
+{
+public:
+  LightApp_PyFileValidator( QWidget* );
+
+  virtual bool canSave( const QString&, bool );
+};
+
+#endif // LIGHTAPP_FILEVALIDATOR_H
diff --git a/src/LightApp/LightApp_PyEditor.cxx b/src/LightApp/LightApp_PyEditor.cxx
new file mode 100644 (file)
index 0000000..7d71b8d
--- /dev/null
@@ -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/LightApp/LightApp_PyEditor.h b/src/LightApp/LightApp_PyEditor.h
new file mode 100644 (file)
index 0000000..4dbdb29
--- /dev/null
@@ -0,0 +1,41 @@
+// 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.h
+// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
+
+#ifndef LIGHTAPP_PYEDITOR_H
+#define LIGHTAPP_PYEDITOR_H
+
+#include "LightApp.h"
+#include "PyConsole_Editor.h"
+
+class LIGHTAPP_EXPORT LightApp_PyEditor : public PyConsole_Editor
+{
+  Q_OBJECT
+
+public:
+  LightApp_PyEditor( PyConsole_Interp*, QWidget* = 0 );
+  ~LightApp_PyEditor();
+
+protected:
+  virtual QString getDumpFileName();
+  virtual QString getLogFileName();
+};
+
+#endif // LIGHTAPP_PYEDITOR_H
diff --git a/src/LightApp/LightApp_PyInterp.cxx b/src/LightApp/LightApp_PyInterp.cxx
deleted file mode 100644 (file)
index 63cdc92..0000000
+++ /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/LightApp_PyInterp.h b/src/LightApp/LightApp_PyInterp.h
deleted file mode 100644 (file)
index 7ffdcc4..0000000
+++ /dev/null
@@ -1,40 +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
-//
-#ifndef _LIGHTAPP_PYINTERP_H_
-#define _LIGHTAPP_PYINTERP_H_
-
-#include <PyConsole_EnhInterp.h> // this include must be first (see PyInterp_base.h)!
-
-class LightApp_PyInterp : public PyConsole_EnhInterp
-{
-  friend class LightApp_Application;
-
-public:
-  virtual ~LightApp_PyInterp();
-  
-protected:
-  LightApp_PyInterp();
-  virtual void initPython();
-};
-
-#endif //_LIGHTAPP_PYINTERP_H_
index ba939a280b69c586df74ea309a44a82fcf7e9f9d..eee9a6d6fd73c6b44d42a0f38c7b22bf7813a7d9 100644 (file)
@@ -73,7 +73,6 @@
     <parameter name="PyEditor"      value="${GUI_ROOT_DIR}/share/salome/resources/gui"/>
     <parameter name="PyViewer"      value="${GUI_ROOT_DIR}/share/salome/resources/gui"/>
     <parameter name="PyConsole"     value="${GUI_ROOT_DIR}/share/salome/resources/gui"/>
-    <parameter name="SalomePyConsole" value="${GUI_ROOT_DIR}/share/salome/resources/gui"/>
     <parameter name="SalomeApp"     value="${GUI_ROOT_DIR}/share/salome/resources/gui"/>
     <parameter name="OB"            value="${GUI_ROOT_DIR}/share/salome/resources/gui"/>
     <parameter name="CAM"           value="${GUI_ROOT_DIR}/share/salome/resources/gui"/>
@@ -89,6 +88,7 @@
   </section>
   <section name="PyConsole">
     <!-- Python console preferences -->
+    <parameter name="auto_completion"     value="true" />
     <parameter name="show_banner"         value="false" />
     <parameter name="font"                value="Sans Serif,12" />
     <parameter name="additional_families" value="Helvetic;Helvetica;Helvetica[Adobe];Times;Times[Adobe];Sans Serif;Serif;Monospace;Lucida"/>
index 61ac28d7c592f31f2b4c8fd19c43891418dad494..8035492e3270e0315c0a6a471b77efed6b82bc6b 100644 (file)
@@ -70,6 +70,19 @@ CEA/DEN, CEDRAT, EDF R&amp;D, LEG, PRINCIPIA R&amp;D, BUREAU VERITAS</translatio
         <source>APPCLOSE_CANCEL</source>
         <translation>&amp;Cancel</translation>
     </message>
+    <message>
+        <source>WRN_PYTHON_FILE_NAME_BAD</source>
+        <translation>Please enter correct file name.
+Python file must include only letters, digits and underscores and start from letter or underscore.</translation>
+    </message>
+    <message>
+        <source>PYTHON_FILES_FILTER</source>
+        <translation>Python Files (*.py)</translation>
+    </message>
+    <message>
+        <source>LOG_FILES_FILTER</source>
+        <translation>Log files (*.log *.txt)</translation>
+    </message>
 </context>
 <context>
     <name>LightApp_Application</name>
@@ -411,6 +424,10 @@ The changes will be applied on the next application session.</translation>
         <source>PREF_SHOW_BANNER</source>
         <translation>Show banner</translation>
     </message>
+    <message>
+        <source>PREF_AUTO_COMPLETION</source>
+        <translation>Command auto-completion</translation>
+    </message>
     <message>
         <source>PREF_GROUP_STYLE</source>
         <translation>Salome style</translation>
@@ -1169,4 +1186,15 @@ File does not exist</translation>
         <translation>Activate/deactivate %1 module</translation>
     </message>
 </context>
+<context>
+    <name>LightApp_PyEditor</name>
+    <message>
+        <source>TOT_DUMP_PYCOMMANDS</source>
+        <translation>Dump commands</translation>
+    </message>
+    <message>
+        <source>TOT_SAVE_PYLOG</source>
+        <translation>Save log</translation>
+    </message>
+</context>
 </TS>
index 4a474b5979976963354e7b3f7dd9e097d7083275..5d65e3449ef0e5c9e494f67494fcec765acd8f68 100755 (executable)
@@ -70,6 +70,19 @@ CEA/DEN, CEDRAT, EDF R&amp;D, LEG, PRINCIPIA R&amp;D, BUREAU VERITAS</translatio
         <source>APPCLOSE_CANCEL</source>
         <translation>&amp;Annuler</translation>
     </message>
+    <message>
+        <source>WRN_PYTHON_FILE_NAME_BAD</source>
+        <translation>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.</translation>
+    </message>
+    <message>
+        <source>PYTHON_FILES_FILTER</source>
+        <translation>Fichiers Python (*.py)</translation>
+    </message>
+    <message>
+        <source>LOG_FILES_FILTER</source>
+        <translation>Fichiers de trace (*.log *.txt)</translation>
+    </message>
 </context>
 <context>
     <name>LightApp_Application</name>
@@ -411,6 +424,10 @@ Les modifications seront appliquées à la prochaine session.</translation>
         <source>PREF_SHOW_BANNER</source>
         <translation>Afficher la bannière</translation>
     </message>
+    <message>
+        <source>PREF_AUTO_COMPLETION</source>
+        <translation type="unfinished">Command auto-completion</translation>
+    </message>
     <message>
         <source>PREF_GROUP_STYLE</source>
         <translation>Style Salomé</translation>
@@ -1169,4 +1186,15 @@ Le fichier n&apos;existe pas</translation>
         <translation>Activer/désactiver le module %1</translation>
     </message>
 </context>
+<context>
+    <name>LightApp_PyEditor</name>
+    <message>
+        <source>TOT_DUMP_PYCOMMANDS</source>
+        <translation>&amp;Générer le script des commandes</translation>
+    </message>
+    <message>
+        <source>TOT_SAVE_PYLOG</source>
+        <translation>Sauver la trace</translation>
+    </message>
+</context>
 </TS>
index caae2fb55de2be787fc9a24d2ae16834277898c7..6c6ccaf504cb5d709809f81b77bec0c27b3562c1 100644 (file)
@@ -56,8 +56,7 @@ CEA/DEN, CEDRAT, EDF R&amp;D, LEG, PRINCIPIA R&amp;D, BUREAU VERITAS</translatio
     </message>
     <message>
       <source>STUDYCLOSE_DESCRIPTION</source>
-      <translation>既存のスタディを閉じる必要があります。閉じますか?
-</translation>
+      <translation>既存のスタディを閉じる必要があります。閉じますか?</translation>
     </message>
     <message>
       <source>APPCLOSE_SAVE</source>
@@ -71,6 +70,18 @@ CEA/DEN, CEDRAT, EDF R&amp;D, LEG, PRINCIPIA R&amp;D, BUREAU VERITAS</translatio
       <source>APPCLOSE_CANCEL</source>
       <translation>キャンセル(&amp;C)</translation>
     </message>
+    <message>
+      <source>WRN_PYTHON_FILE_NAME_BAD</source>
+      <translation>有効なファイル名を入力してください。Pythonのファイル名は、文字、数字、およびアンダー スコアで構成され、文字かアンダー スコアで始まる必要があります。</translation>
+    </message>
+    <message>
+      <source>PYTHON_FILES_FILTER</source>
+      <translation>ファイル (*.py) Python</translation>
+    </message>
+    <message>
+      <source>LOG_FILES_FILTER</source>
+      <translation>ログファイル (*.log *.txt)</translation>
+    </message>
   </context>
   <context>
     <name>LightApp_Application</name>
@@ -411,6 +422,10 @@ CEA/DEN, CEDRAT, EDF R&amp;D, LEG, PRINCIPIA R&amp;D, BUREAU VERITAS</translatio
       <source>PREF_SHOW_BANNER</source>
       <translation>バナーの表示</translation>
     </message>
+    <message>
+      <source>PREF_AUTO_COMPLETION</source>
+      <translation type="unfinished">Command auto-completion</translation>
+    </message>
     <message>
       <source>PREF_GROUP_STYLE</source>
       <translation>Salomeスタイル</translation>
@@ -1167,4 +1182,15 @@ CEA/DEN, CEDRAT, EDF R&amp;D, LEG, PRINCIPIA R&amp;D, BUREAU VERITAS</translatio
       <translation>モジュール %1 の有効/無効にします。</translation>
     </message>
   </context>
+  <context>
+    <name>LightApp_PyEditor</name>
+    <message>
+      <source>TOT_DUMP_PYCOMMANDS</source>
+      <translation>スクリプト コマンドを生成します。</translation>
+    </message>
+    <message>
+      <source>TOT_SAVE_PYLOG</source>
+      <translation>ログの保存</translation>
+    </message>
+  </context>
 </TS>
index 950888f38d16d8e8d42dd06d3abe2e577480eccd..bc49aebc68abd454f5c8a18458ddbfdaf22cc96e 100755 (executable)
@@ -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
index e313cdf5ef20c77c656da0a7b57eed9b6230d3ce..4c72bdfb9d291100197b8af4d1f0494cbea743ec 100644 (file)
 //
 // 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_Console.cxx b/src/PyConsole/PyConsole_Console.cxx
new file mode 100644 (file)
index 0000000..3aaa52c
--- /dev/null
@@ -0,0 +1,383 @@
+// 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)
+
+#include "PyConsole_Console.h"
+#include "PyConsole_Interp.h"
+#include "PyConsole_Editor.h"
+
+#include <QAction>
+#include <QApplication>
+#include <QClipboard>
+#include <QContextMenuEvent>
+#include <QMenu>
+#include <QVBoxLayout>
+
+/*!
+  \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
+
+  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.
+
+  Creates new python console widget.
+  \param parent parent widget
+  \param interp python interpreter
+*/
+PyConsole_Console::PyConsole_Console( QWidget* parent, PyConsole_Editor* editor )
+: QWidget( parent )
+{
+  // initialize Python interpretator
+  PyConsole_Interp* interp = editor ? editor->getInterp() : new PyConsole_Interp();
+  interp->initialize();
+  
+  // create editor console
+  QVBoxLayout* lay = new QVBoxLayout( this );
+  lay->setMargin( 0 );
+  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();
+}
+
+/*!
+  \brief Destructor.
+*/
+PyConsole_Console::~PyConsole_Console()
+{
+}
+
+/*!
+  \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_Console::exec( const QString& command )
+{
+  if ( myEditor )
+    myEditor->exec( command );
+}
+
+/*!
+  \brief Execute python command in the interpreter 
+         and wait until it is finished.
+  
+  Block execution of main application until the python command is executed.
+  \param command string with command and arguments
+*/
+void PyConsole_Console::execAndWait( const QString& command )
+{
+  if ( myEditor )
+    myEditor->execAndWait( command );
+}
+
+/*!
+  \brief Get synchronous mode flag value.
+  
+  \sa setIsSync()
+  \return \c true if python console works in synchronous mode
+*/
+bool PyConsole_Console::isSync() const
+{
+  return myEditor ? myEditor->isSync() : false;
+}
+
+/*!
+  \brief Set synchronous mode flag value.
+
+  In synhronous mode the Python commands are executed in the GUI thread
+  and the GUI is blocked until the command is finished. In the asynchronous
+  mode each Python command is executed in the separate thread that does not
+  block the main GUI loop.
+
+  \param on synhronous mode flag
+*/
+void PyConsole_Console::setIsSync( const bool on )
+{
+  if ( myEditor ) 
+    myEditor->setIsSync( on );
+}
+
+/*!
+  \brief Get suppress output flag value.
+  
+  \sa setIsSuppressOutput()
+  \return \c true if python console output is suppressed.
+*/
+bool PyConsole_Console::isSuppressOutput() const
+{
+  return myEditor ? myEditor->isSuppressOutput() : false;
+}
+
+/*!
+  \brief Set suppress output flag value.
+
+  In case if suppress output flag is \c true, the python 
+  console output suppressed.
+
+  \param on suppress output flag
+*/
+void PyConsole_Console::setIsSuppressOutput( const bool on )
+{
+  if ( myEditor )
+    myEditor->setIsSuppressOutput( on );
+}
+
+/*!
+  \brief Get 'show banner' flag value.
+  
+  \sa setIsShowBanner()
+  \return \c true if python console shows banner
+*/
+bool PyConsole_Console::isShowBanner() const
+{
+  return myEditor ? myEditor->isShowBanner() : false;
+}
+
+/*!
+  \brief Set 'show banner' flag value.
+
+  The banner is shown in the top of the python console window.
+
+  \sa isShowBanner()
+  \param on 'show banner' flag
+*/
+void PyConsole_Console::setIsShowBanner( const bool on )
+{
+  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_Console::setFont( const QFont& f )
+{
+  if ( myEditor )
+    myEditor->setFont( f );
+}
+
+/*!
+  \brief Get python console font.
+  \return current python console font
+*/
+QFont PyConsole_Console::font() const
+{
+  return myEditor ? myEditor->font() : QFont();
+}
+
+/*!
+  \brief Set actions to be visible in the context popup menu.
+  
+  Actions, which IDs are set in \a flags parameter, will be shown in the 
+  context popup menu. Other actions will not be shown.
+
+  \param flags ORed together actions flags
+*/
+void PyConsole_Console::setMenuActions( const int flags )
+{
+  myActions[CopyId]->setVisible( flags & CopyId );
+  myActions[PasteId]->setVisible( flags & PasteId );
+  myActions[ClearId]->setVisible( flags & ClearId );
+  myActions[SelectAllId]->setVisible( flags & SelectAllId );
+  myActions[DumpCommandsId]->setVisible( flags & DumpCommandsId );
+  myActions[StartLogId]->setVisible( flags & StartLogId );
+  myActions[StopLogId]->setVisible( flags & StopLogId );
+}
+
+/*!
+  \brief Get menu actions which are currently visible in the context popup menu.
+  \return ORed together actions flags
+  \sa setMenuActions()
+*/
+int PyConsole_Console::menuActions() const
+{
+  int ret = 0;
+  ret = ret | ( myActions[CopyId]->isVisible() ? CopyId : 0 );
+  ret = ret | ( myActions[PasteId]->isVisible() ? PasteId : 0 );
+  ret = ret | ( myActions[ClearId]->isVisible() ? ClearId : 0 );
+  ret = ret | ( myActions[SelectAllId]->isVisible() ? SelectAllId : 0 );
+  ret = ret | ( myActions[DumpCommandsId]->isVisible() ? DumpCommandsId : 0 );
+  ret = ret | ( myActions[StartLogId]->isVisible() ? StartLogId : 0 );
+  ret = ret | ( myActions[StopLogId]->isVisible() ? StopLogId : 0 );
+  return ret;
+}
+
+/*!
+  \brief Create menu actions.
+
+  Create context popup menu actions.
+*/
+void PyConsole_Console::createActions()
+{
+  QAction* a = new QAction( tr( "EDIT_COPY_CMD" ), this );
+  a->setStatusTip( tr( "EDIT_COPY_CMD" ) );
+  connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( copy() ) );
+  myActions.insert( CopyId, a );
+
+  a = new QAction( tr( "EDIT_PASTE_CMD" ), this );
+  a->setStatusTip( tr( "EDIT_PASTE_CMD" ) );
+  connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( paste() ) );
+  myActions.insert( PasteId, a );
+
+  a = new QAction( tr( "EDIT_CLEAR_CMD" ), this );
+  a->setStatusTip( tr( "EDIT_CLEAR_CMD" ) );
+  connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( clear() ) );
+  myActions.insert( ClearId, a );
+
+  a = new QAction( tr( "EDIT_SELECTALL_CMD" ), this );
+  a->setStatusTip( tr( "EDIT_SELECTALL_CMD" ) );
+  connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( selectAll() ) );
+  myActions.insert( SelectAllId, a );
+  
+  a = new QAction( tr( "EDIT_DUMPCOMMANDS_CMD" ), this );
+  a->setStatusTip( tr( "EDIT_DUMPCOMMANDS_CMD" ) );
+  connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( dump() ) );
+  myActions.insert( DumpCommandsId, a );
+
+  a = new QAction( tr( "EDIT_STARTLOG_CMD" ), this );
+  a->setStatusTip( tr( "EDIT_STARTLOG_CMD" ) );
+  connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( startLog() ) );
+  myActions.insert( StartLogId, a );
+
+  a = new QAction( tr( "EDIT_STOPLOG_CMD" ), this );
+  a->setStatusTip( tr( "EDIT_STOPLOG_CMD" ) );
+  connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( stopLog() ) );
+  myActions.insert( StopLogId, a );
+}
+
+/*!
+  \brief Update menu actions.
+
+  Update context popup menu action state.
+*/
+void PyConsole_Console::updateActions()
+{
+  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_Console::startLog( const QString& fileName )
+{
+  if ( myEditor ) 
+    myEditor->startLog( fileName );
+}
+
+/*!
+  \brief Stop python trace logging
+*/
+void PyConsole_Console::stopLog()
+{
+  if ( myEditor ) 
+    myEditor->stopLog();
+}
+
+/*!
+  \brief Process context popup menu request
+
+  Show the context popup menu.
+
+  \param event context popup menu event
+*/
+void PyConsole_Console::contextMenuEvent( QContextMenuEvent* event )
+{
+  if ( !myEditor || myEditor->isReadOnly() )
+    return;
+
+  QMenu* menu = new QMenu( this );
+  menu->addAction( myActions[CopyId] );
+  menu->addAction( myActions[PasteId] );
+  menu->addAction( myActions[ClearId] );
+  menu->addSeparator();
+  menu->addAction( myActions[SelectAllId] );
+  menu->addSeparator();
+  menu->addAction( myActions[DumpCommandsId] );
+  if ( !myEditor->isLogging() )
+    menu->addAction( myActions[StartLogId] );
+  else
+    menu->addAction( myActions[StopLogId] );
+
+  updateActions();
+
+  menu->exec( event->globalPos());
+
+  delete menu;
+}
diff --git a/src/PyConsole/PyConsole_Console.h b/src/PyConsole/PyConsole_Console.h
new file mode 100644 (file)
index 0000000..e0b111e
--- /dev/null
@@ -0,0 +1,97 @@
+// 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 PYCONSOLE_CONSOLE_H
+#define PYCONSOLE_CONSOLE_H
+
+#include "PyConsole.h"
+
+#include <QWidget>
+#include <QMap>
+
+class QMenu;
+
+class PyConsole_Interp;
+class PyConsole_Editor;
+
+class PYCONSOLE_EXPORT PyConsole_Console : public QWidget
+{
+  Q_OBJECT
+
+public:
+  //! Context popup menu actions flags
+  enum
+  {
+    CopyId         = 0x01,  //!< "Copy" menu action
+    PasteId        = 0x02,  //!< "Paste" menu action
+    ClearId        = 0x04,  //!< "Clear" menu action
+    SelectAllId    = 0x08,  //!< "Select All" menu action
+    DumpCommandsId = 0x10,  //!< "DumpCommands" menu action
+    StartLogId     = 0x20,  //!< "Start log" menu action
+    StopLogId      = 0x40,  //!< "Stop log" menu action
+    All            = 0xFF,  //!< all menu actions 
+  };
+
+public:
+  PyConsole_Console( QWidget* parent, PyConsole_Editor* editor = 0 );
+  virtual ~PyConsole_Console();
+
+  PyConsole_Interp*   getInterp() const;
+
+  QFont               font() const;
+  virtual void        setFont( const QFont& );
+
+  bool                isSync() const;
+  void                setIsSync( const bool );
+
+  bool                isSuppressOutput() const;
+  void                setIsSuppressOutput( const bool );
+
+  bool                isShowBanner() const;
+  void                setIsShowBanner( const bool );
+
+  void                setAutoCompletion( bool );
+  bool                autoCompletion() const;
+
+  void                exec( const QString& );
+  void                execAndWait( const QString& );
+
+  void                setMenuActions( const int );
+  int                 menuActions() const;
+
+  void                startLog( const QString& );
+  void                stopLog();
+
+protected:
+  void                createActions();
+  void                updateActions();
+
+  virtual void        contextMenuEvent( QContextMenuEvent* );
+
+protected:
+  PyConsole_Editor*   myEditor;    //!< python console editor widget
+  QMap<int, QAction*> myActions;   //!< menu actions list
+};
+
+#endif // PYCONSOLE_CONSOLE_H
diff --git a/src/PyConsole/PyConsole_ConsoleBase.cxx b/src/PyConsole/PyConsole_ConsoleBase.cxx
deleted file mode 100644 (file)
index 3311511..0000000
+++ /dev/null
@@ -1,413 +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_ConsoleBase.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 <QAction>
-#include <QApplication>
-#include <QClipboard>
-#include <QEvent>
-#include <QMenu>
-#include <QContextMenuEvent>
-#include <QVBoxLayout>
-
-PyConsole_EditorBase *PyConsole_ConsoleBase::PyConsole_Interp_CreatorBase::createEditor( PyConsole_Interp *interp, PyConsole_ConsoleBase *console ) const
-{ return new PyConsole_EditorBase(interp,console); }
-
-PyConsole_Interp *PyConsole_ConsoleBase::PyConsole_Interp_CreatorBase::createInterp( ) const
-{ return new PyConsole_Interp; }
-
-/*!
-  \brief Constructor.
-
-  Creates new python console widget.
-  \param parent parent widget
-  \param interp python interpreter
-*/
-PyConsole_ConsoleBase::PyConsole_ConsoleBase( QWidget* parent, PyConsole_Interp* interp )
-: 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();
-  
-  // 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 );
-  lay->addWidget( myEditor );
-
-  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_Interp* PyConsole_ConsoleBase::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 )
-{
-  if ( myEditor )
-    myEditor->exec( command );
-}
-
-/*!
-  \brief Execute python command in the interpreter 
-         and wait until it is finished.
-  
-  Block execution of main application until the python command is executed.
-  \param command string with command and arguments
-*/
-void PyConsole_ConsoleBase::execAndWait( const QString& command )
-{
-  if ( myEditor )
-    myEditor->execAndWait( command );
-}
-
-/*!
-  \brief Get synchronous mode flag value.
-  
-  \sa setIsSync()
-  \return True if python console works in synchronous mode
-*/
-bool PyConsole_ConsoleBase::isSync() const
-{
-  return myEditor->isSync();
-}
-
-/*!
-  \brief Set synchronous mode flag value.
-
-  In synhronous mode the Python commands are executed in the GUI thread
-  and the GUI is blocked until the command is finished. In the asynchronous
-  mode each Python command is executed in the separate thread that does not
-  block the main GUI loop.
-
-  \param on synhronous mode flag
-*/
-void PyConsole_ConsoleBase::setIsSync( const bool on )
-{
-  myEditor->setIsSync( on );
-}
-
-/*!
-  \brief Get suppress output flag value.
-  
-  \sa setIsSuppressOutput()
-  \return True if python console output is suppressed.
-*/
-bool PyConsole_ConsoleBase::isSuppressOutput() const
-{
-  return myEditor->isSuppressOutput();
-}
-
-/*!
-  \brief Set suppress output flag value.
-
-  In case if suppress output flag is true, the python 
-  console output suppressed.
-
-  \param on suppress output flag
-*/
-void PyConsole_ConsoleBase::setIsSuppressOutput( const bool on )
-{
-  myEditor->setIsSuppressOutput(on);
-}
-
-/*!
-  \brief Get 'show banner' flag value.
-  
-  \sa setIsShowBanner()
-  \return \c true if python console shows banner
-*/
-bool PyConsole_ConsoleBase::isShowBanner() const
-{
-  return myEditor->isShowBanner();
-}
-
-/*!
-  \brief Set 'show banner' flag value.
-
-  The banner is shown in the top of the python console window.
-
-  \sa isShowBanner()
-  \param on 'show banner' flag
-*/
-void PyConsole_ConsoleBase::setIsShowBanner( const bool on )
-{
-  myEditor->setIsShowBanner( on );
-}
-
-/*!
-  \brief Change the python console's font.
-  \param f new font
-*/
-void PyConsole_ConsoleBase::setFont( const QFont& f )
-{
-  if( myEditor )
-    myEditor->setFont( f );
-}
-
-/*!
-  \brief Get python console font.
-  \return current python console's font
-*/
-QFont PyConsole_ConsoleBase::font() const
-{
-  QFont res;
-  if( myEditor )
-    res = myEditor->font();
-  return res;
-}
-
-/*!
-  \brief Set actions to be visible in the context popup menu.
-  
-  Actions, which IDs are set in \a flags parameter, will be shown in the 
-  context popup menu. Other actions will not be shown.
-
-  \param flags ORed together actions flags
-*/
-void PyConsole_ConsoleBase::setMenuActions( const int flags )
-{
-  myActions[CopyId]->setVisible( flags & CopyId );
-  myActions[PasteId]->setVisible( flags & PasteId );
-  myActions[ClearId]->setVisible( flags & ClearId );
-  myActions[SelectAllId]->setVisible( flags & SelectAllId );
-  myActions[DumpCommandsId]->setVisible( flags & DumpCommandsId );
-  myActions[StartLogId]->setVisible( flags & StartLogId );
-  myActions[StopLogId]->setVisible( flags & StopLogId );
-}
-
-/*!
-  \brief Get menu actions which are currently visible in the context popup menu.
-  \return ORed together actions flags
-  \sa setMenuActions()
-*/
-int PyConsole_ConsoleBase::menuActions() const
-{
-  int ret = 0;
-  ret = ret | ( myActions[CopyId]->isVisible() ? CopyId : 0 );
-  ret = ret | ( myActions[PasteId]->isVisible() ? PasteId : 0 );
-  ret = ret | ( myActions[ClearId]->isVisible() ? ClearId : 0 );
-  ret = ret | ( myActions[SelectAllId]->isVisible() ? SelectAllId : 0 );
-  ret = ret | ( myActions[DumpCommandsId]->isVisible() ? DumpCommandsId : 0 );
-  ret = ret | ( myActions[StartLogId]->isVisible() ? StartLogId : 0 );
-  ret = ret | ( myActions[StopLogId]->isVisible() ? StopLogId : 0 );
-  return ret;
-}
-
-/*!
-  \brief Create menu actions.
-
-  Create context popup menu actions.
-*/
-void PyConsole_ConsoleBase::createActions()
-{
-  QAction* a = new QAction( tr( "EDIT_COPY_CMD" ), this );
-  a->setStatusTip( tr( "EDIT_COPY_CMD" ) );
-  connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( copy() ) );
-  myActions.insert( CopyId, a );
-
-  a = new QAction( tr( "EDIT_PASTE_CMD" ), this );
-  a->setStatusTip( tr( "EDIT_PASTE_CMD" ) );
-  connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( paste() ) );
-  myActions.insert( PasteId, a );
-
-  a = new QAction( tr( "EDIT_CLEAR_CMD" ), this );
-  a->setStatusTip( tr( "EDIT_CLEAR_CMD" ) );
-  connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( clear() ) );
-  myActions.insert( ClearId, a );
-
-  a = new QAction( tr( "EDIT_SELECTALL_CMD" ), this );
-  a->setStatusTip( tr( "EDIT_SELECTALL_CMD" ) );
-  connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( selectAll() ) );
-  myActions.insert( SelectAllId, a );
-  
-  a = new QAction( tr( "EDIT_DUMPCOMMANDS_CMD" ), this );
-  a->setStatusTip( tr( "EDIT_DUMPCOMMANDS_CMD" ) );
-  connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( dump() ) );
-  myActions.insert( DumpCommandsId, a );
-
-  a = new QAction( tr( "EDIT_STARTLOG_CMD" ), this );
-  a->setStatusTip( tr( "EDIT_STARTLOG_CMD" ) );
-  connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( startLog() ) );
-  myActions.insert( StartLogId, a );
-
-  a = new QAction( tr( "EDIT_STOPLOG_CMD" ), this );
-  a->setStatusTip( tr( "EDIT_STOPLOG_CMD" ) );
-  connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( stopLog() ) );
-  myActions.insert( StopLogId, a );
-}
-
-/*!
-  \brief Update menu actions.
-
-  Update context popup menu action state.
-*/
-void PyConsole_ConsoleBase::updateActions()
-{
-  myActions[CopyId]->setEnabled( myEditor->textCursor().hasSelection() );
-  myActions[PasteId]->setEnabled( !myEditor->isReadOnly() && !QApplication::clipboard()->text().isEmpty() );
-  myActions[SelectAllId]->setEnabled( !myEditor->document()->isEmpty() );
-}
-
-/*!
-  \brief Start python trace logging
-  \param fileName the path to the log file
-*/
-void PyConsole_ConsoleBase::startLog( const QString& fileName )
-{
-  myEditor->startLog( fileName );
-}
-
-/*!
-  \brief Stop python trace logging
-*/
-void PyConsole_ConsoleBase::stopLog()
-{
-  myEditor->stopLog();
-}
-
-/*!
-  \brief Create the context popup menu.
-
-  Fill in the popup menu with the commands.
-
-  \param menu context popup menu
-*/
-void PyConsole_ConsoleBase::contextMenuPopup( QMenu *menu )
-{
-  if ( myEditor->isReadOnly() )
-    return;
-
-  menu->addAction( myActions[CopyId] );
-  menu->addAction( myActions[PasteId] );
-  menu->addAction( myActions[ClearId] );
-  menu->addSeparator();
-  menu->addAction( myActions[SelectAllId] );
-  menu->addSeparator();
-  menu->addAction( myActions[DumpCommandsId] );
-  if ( !myEditor->isLogging() )
-    menu->addAction( myActions[StartLogId] );
-  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.
-
-  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();
-}
diff --git a/src/PyConsole/PyConsole_ConsoleBase.h b/src/PyConsole/PyConsole_ConsoleBase.h
deleted file mode 100644 (file)
index 0cef8f7..0000000
+++ /dev/null
@@ -1,127 +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 PYCONSOLE_CONSOLEBASE_H
-#define PYCONSOLE_CONSOLEBASE_H
-
-#include "PyConsole.h"
-
-#include <QWidget>
-#include <QMenu>
-#include <QMap>
-
-class PyConsole_Interp;
-class PyConsole_EditorBase;
-
-class PYCONSOLE_EXPORT PyConsole_ConsoleBase : 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
-  {
-    CopyId         = 0x01,  //!< "Copy" menu action
-    PasteId        = 0x02,  //!< "Paste" menu action
-    ClearId        = 0x04,  //!< "Clear" menu action
-    SelectAllId    = 0x08,  //!< "Select All" menu action
-    DumpCommandsId = 0x10,  //!< "DumpCommands" menu action
-    StartLogId     = 0x20,  //!< "Start log" menu action
-    StopLogId      = 0x40,  //!< "Stop log" menu action
-    All            = 0xFF,  //!< all menu actions 
-  };
-
-public:
-  PyConsole_ConsoleBase( QWidget* parent, PyConsole_Interp* interp = 0 );
-  virtual ~PyConsole_ConsoleBase();
-
-  //! \brief Get python interperter
-  PyConsole_Interp*   getInterp() const;
-  QFont               font() const;
-  virtual void        setFont( const QFont& );
-
-  bool                isSync() const;
-  void                setIsSync( const bool );
-
-  bool                isSuppressOutput() const;
-  void                setIsSuppressOutput( const bool );
-
-  bool                isShowBanner() const;
-  void                setIsShowBanner( const bool );
-
-  void                exec( const QString& );
-  void                execAndWait( const QString& );
-
-  void                setMenuActions( const int );
-  int                 menuActions() const;
-
-  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<int, QAction*> myActions;   //!< menu actions list
-};
-
-/**
- * Enhance console object providing auto-completion.
- * Similar to PyConsole_Console except that an enhanced interpreter and enhanced editor
- * are encapsulated.
- */
-class PYCONSOLE_EXPORT PyConsole_EnhConsoleBase : public PyConsole_ConsoleBase
-{
-  Q_OBJECT
-public:
-
-  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 ) ;
-};
-
-#endif // PYCONSOLE_CONSOLEBASE_H
diff --git a/src/PyConsole/PyConsole_Editor.cxx b/src/PyConsole/PyConsole_Editor.cxx
new file mode 100644 (file)
index 0000000..7d540f6
--- /dev/null
@@ -0,0 +1,1700 @@
+// 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.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:
+  - <Enter>              : execute current command
+  - <Ctrl><Break>        : clear current command
+  - <Escape>             : clear current command
+  - <Up>                 : previous command in the history
+  - <Shift><Up>          : move cursor one row up with selection
+  - <Ctrl><Up>           : move cursor one row up without selection
+  - <Ctrl><Shift><Up>    : move cursor one row up with selection
+  - <Down>               : next command in the history
+  - <Shift><Down>        : move cursor one row down with selection
+  - <Ctrl><Down>         : move cursor one row down without selection
+  - <Ctrl><Shift><Down>  : move cursor one row down with selection
+  - <Left>               : move one symbol left without selection
+  - <Shift><Left>        : move one symbol left with selection
+  - <Ctrl><Left>         : move one word left without selection
+  - <Ctrl><Shift><Left>  : move one word left with selection
+  - <Right>              : move one symbol right without selection
+  - <Shift><Right>       : move one symbol right with selection
+  - <Ctrl><Right>        : move one word right without selection
+  - <Ctrl><Shift><Right> : move one word right with selection
+  - <PgUp>               : first command in the history
+  - <Shift><PgUp>        : move one page up with selection
+  - <Ctrl><PgUp>         : move one page up without selection
+  - <Ctrl><Shift><PgUp>  : scroll one page up
+  - <PgDn>               : last command in the history
+  - <Shift><PgDn>        : move one page down with selection
+  - <Ctrl><PgDn>         : move one page down without selection
+  - <Ctrl><Shift><PgDn>  : scroll one page down
+  - <Home>               : move to the beginning of the line without selection
+  - <Shift><Home>        : move to the beginning of the line with selection
+  - <Ctrl><Home>         : move to the very first symbol without selection
+  - <Ctrl><Shift><Home>  : move to the very first symbol with selection
+  - <End>                : move to the end of the line without selection
+  - <Shift><End>         : move to the end of the line with selection
+  - <Ctrl><End>          : move to the very last symbol without selection
+  - <Ctrl><Shift><End>   : move to the very last symbol with selection
+  - <Backspace>          : delete symbol before the cursor
+                           / remove selected text and put it to the clipboard (cut)
+  - <Shift><Backspace>   : delete previous word
+                           / remove selected text and put it to the clipboard (cut)
+  - <Ctrl><Backspace>    : delete text from the cursor to the beginning of the line 
+                           / remove selected text and put it to the clipboard (cut)
+  - <Delete>             : delete symbol after the cursor 
+                           / remove selected text and put it to the clipboard (cut)
+  - <Shift><Delete>      : delete next word
+                           / remove selected text and put it to the clipboard (cut)
+  - <Ctrl><Delete>       : delete text from the cursor to the end of the line
+                           / remove selected text and put it to the clipboard (cut)
+  - <Ctrl><Insert>       : copy
+  - <Shift><Insert>      : paste
+  - <Ctrl><V>            : paste
+  - <Ctrl><C>            : copy
+  - <Ctrl><X>            : cut
+  - <Ctrl><V>            : paste
+  - <Tab>                : performs auto-completion
+  - <Ctrl><Tab>          : undoes auto-completion
+*/
+
+#include "PyConsole_Editor.h"
+#include "PyConsole_Interp.h"
+#include "PyConsole_Event.h"
+#include "PyInterp_Dispatcher.h"
+#include "PyConsole_Request.h"
+
+#include <QApplication>
+#include <QClipboard>
+#include <QDropEvent>
+#include <QEvent>
+#include <QKeyEvent>
+#include <QMimeData>
+#include <QMouseEvent>
+#include <QScrollBar>
+#include <QTextBlock>
+#include <QTextCursor>
+#include <QTextStream>
+#include <QChar>
+#include <QFileDialog>
+#include <QMessageBox>
+
+//VSR: uncomment below macro to support unicode text properly in SALOME
+//     current commented out due to regressions
+//#define PAL22528_UNICODE
+
+namespace
+{
+  QString fromUtf8( const char* txt )
+  {
+#ifdef PAL22528_UNICODE
+    return QString::fromUtf8( txt );
+#else
+    return QString( txt );
+#endif
+  }
+}
+
+static QString READY_PROMPT = ">>> ";
+static QString DOTS_PROMPT  = "... ";
+
+void staticCallbackStdout( void* data, char* c )
+{
+  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_Editor*)data)->isSuppressOutput()) {
+    PyConsole_Editor* e = (PyConsole_Editor*)data;
+    QApplication::postEvent( e, new PyConsole_PrintEvent( fromUtf8(c), true ) );
+  }
+}
+
+/*!
+  \brief Constructor. 
+  
+  Creates python editor window.
+  \param theInterp python interper
+  \param theParent parent widget
+*/
+PyConsole_Editor::PyConsole_Editor( PyConsole_Interp* theInterp, 
+                                    QWidget*          theParent )
+: QTextEdit( theParent ),
+  myInterp( theInterp ),
+  myCmdInHistory( -1 ),
+  myEventLoop( 0 ),
+  myShowBanner( true ),
+  myIsSync( true ),
+  myIsSuppressOutput( false ),
+  myMultiLinePaste( false ),
+  myAutoCompletion( false ),
+  myTabMode( false ),
+  myComplCursorPos( -1 )
+{
+  setFont( QFont( "Courier", 11 ) ); // default font
+  setUndoRedoEnabled( false );
+
+  myPrompt = READY_PROMPT;
+  setLineWrapMode( QTextEdit::WidgetWidth );
+  setWordWrapMode( QTextOption::WrapAnywhere );
+  setAcceptRichText( false );
+
+  // 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_Editor::~PyConsole_Editor()
+{
+  myInterp = 0;
+}
+
+/*!
+  \brief Get Python interpreter
+*/
+PyConsole_Interp* PyConsole_Editor::getInterp() const
+{
+  return myInterp;
+}
+
+/*!
+  \brief Get synchronous mode flag value.
+  
+  \sa setIsSync()
+  \return \c true if python console works in synchronous mode
+*/
+bool PyConsole_Editor::isSync() const
+{
+  return myIsSync;
+}
+
+/*!
+  \brief Set synchronous mode flag value.
+
+  In synhronous mode the Python commands are executed in the GUI thread
+  and the GUI is blocked until the command is finished. In the asynchronous
+  mode each Python command is executed in the separate thread that does not
+  block the main GUI loop.
+
+  \param on synhronous mode flag
+*/
+void PyConsole_Editor::setIsSync( const bool on )
+{
+  myIsSync = on;
+}
+
+/*!
+  \brief Get suppress output flag value.
+  
+  \sa setIsSuppressOutput()
+  \return \c true if python console output is suppressed.
+*/
+bool PyConsole_Editor::isSuppressOutput() const
+{
+  return myIsSuppressOutput;
+}
+
+/*!
+  \brief Set suppress output flag value.
+
+  In case if suppress output flag is \c true, the python 
+  console output suppressed.
+
+  \param on suppress output flag
+*/
+void PyConsole_Editor::setIsSuppressOutput( const bool on )
+{
+  myIsSuppressOutput = on;
+}
+
+/*!
+  \brief Get 'show banner' flag value.
+  
+  \sa setIsShowBanner()
+  \return \c true if python console shows banner
+*/
+bool PyConsole_Editor::isShowBanner() const
+{
+  return myShowBanner;
+}
+
+/*!
+  \brief Set 'show banner' flag value.
+
+  The banner is shown in the top of the python console window.
+
+  \sa isShowBanner()
+  \param on 'show banner' flag
+*/
+void PyConsole_Editor::setIsShowBanner( const bool on )
+{
+  if ( myShowBanner != on ) {
+    myShowBanner = on;
+    clear();
+  }
+}
+
+/*!
+  \brief 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_Editor::isLogging() const
+{
+  return !myLogFile.isEmpty();
+}
+
+/*!
+  \brief Get size hint for the Python console window
+  \return size hint value
+*/
+QSize PyConsole_Editor::sizeHint() const
+{
+  QFontMetrics fm( font() );
+  int nbLines = ( isShowBanner() ? banner().split("\n").count() : 0 ) + 1;
+  QSize s(100, fm.lineSpacing()*nbLines);
+  return s;
+}
+
+/*!
+  \brief Put the string \a str to the python editor.
+  \param str string to be put in the command line of the editor
+  \param newBlock if \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_Editor::addText( const QString& str, 
+                                const bool     newBlock,
+                                const bool     isError )
+{
+  QTextCursor aCursor = textCursor();
+  QTextCharFormat cf;
+
+  moveCursor( QTextCursor::End );
+  if ( newBlock )
+    aCursor.insertBlock();
+  if ( isError )
+    cf.setForeground( QBrush( Qt::red ) );
+  else
+    cf.setForeground( QBrush( Qt::black ) );
+  aCursor.insertText( str, cf );
+  moveCursor( QTextCursor::End );
+  ensureCursorVisible();
+}
+
+/*!
+  \brief Convenient method for executing a Python command,
+  as if the user typed it manually.
+  \param command python command to be executed
+
+  !!! WARNING: doesn't work properly with multi-line commands. !!!
+*/
+void PyConsole_Editor::exec( const QString& command )
+{
+  if ( isReadOnly() ) {
+    // some interactive command is being executed in this editor...
+    // shedule the command to the queue
+    myQueue.push_back( command );
+    return;
+  }
+
+  // remove last line
+  moveCursor( QTextCursor::End );
+  moveCursor( QTextCursor::StartOfBlock, QTextCursor::KeepAnchor );
+  textCursor().removeSelectedText();
+
+  // set "ready" prompt
+  myPrompt = READY_PROMPT;
+
+  // clear command buffer
+  myCommandBuffer.truncate( 0 );
+
+  // unset history browsing mode
+  myCmdInHistory = -1;
+
+  // print command line by line
+  QString cmd = command;
+  if ( !cmd.endsWith( "\n" ) ) cmd += "\n";
+  QStringList lines = command.split( "\n" );
+  for ( int i = 0; i < lines.size(); i++ ) {
+    if ( !lines[i].trimmed().isEmpty() )
+      myHistory.push_back( lines[i] );
+    addText( ( i == 0 ? READY_PROMPT : DOTS_PROMPT ) + lines[i], i != 0 );
+    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( createCmdRequest( cmd ) );
+}
+
+/*!
+  \brief Create request to the python dispatcher for the command execution.
+  \param command python command to be executed
+ */
+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 <TAB> was pressed
+  \return completion command
+  \sa CompletionCommand
+*/
+PyInterp_Request* PyConsole_Editor::createTabRequest( const QString& input )
+{
+  // 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() );
+}
+
+/*!
+  \brief Execute command in the python interpreter
+  and wait until it is finished.
+
+  \param command python command to be executed
+ */
+void PyConsole_Editor::execAndWait( const QString& command )
+{
+  // already running ?
+  if ( myEventLoop )
+    return;
+
+  // create new event loop
+  bool sync = isSync();
+  if ( !sync ) {
+    myEventLoop = new QEventLoop( this );
+  }
+
+  // execute command
+  exec( command );
+
+  if ( !sync ) {
+    // run event loop
+    myEventLoop->exec();
+    // delete event loop after command is processed
+    delete myEventLoop;
+    myEventLoop = 0;
+  }
+}
+
+/*!
+  \brief Process <Enter> key press event. 
+  
+  Execute the command entered by the user.
+*/
+void PyConsole_Editor::handleReturn()
+{
+  // Position cursor at the end
+  QTextCursor aCursor = textCursor();
+  aCursor.movePosition( QTextCursor::End );
+  setTextCursor( aCursor );
+
+  // get last line
+  QTextBlock par = document()->end().previous();
+  if ( !par.isValid() ) return;
+
+  // get command
+  QString cmd = par.text().remove( 0, promptSize() );
+
+  // extend the command buffer with the current command 
+  myCommandBuffer.append( cmd );
+
+  // add command to the history
+  if ( !cmd.trimmed().isEmpty() )
+    myHistory.push_back( cmd );
+  putLog( QString( "%1%2\n" ).arg( myPrompt ).arg( cmd ) );
+
+  // IPAL19397
+  addText( "", true ); 
+  
+  // set read-only mode
+  setReadOnly( true );
+
+  // set busy cursor
+  setCursor( Qt::BusyCursor );
+  
+  // post a request to execute Python command;
+  // editor will be informed via a custom event that execution has been completed
+  PyInterp_Dispatcher::Get()->Exec( createCmdRequest( myCommandBuffer ) );
+}
+
+/*!
+  \brief Process <Tab> 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 <Ctrl><Tab> 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;
+}
+
+/*!
+  \brief Process drop event.
+
+  Paste dragged text.
+  \param event drop event
+*/
+void PyConsole_Editor::dropEvent( QDropEvent* event )
+{
+  // get the initial drop position
+  QPoint pos = event->pos();
+  QTextCursor aCursor = cursorForPosition( event->pos() );
+
+  // if the position is not in the last line move it to the end of the command line
+  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(),
+                 event->mimeData(),
+                 event->mouseButtons(),
+                 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_Editor::mouseReleaseEvent( QMouseEvent* event )
+{
+  if ( event->button() == Qt::LeftButton ) {
+    QTextEdit::mouseReleaseEvent( event );
+  }
+  else if ( event->button() == Qt::MidButton ) {
+    QTextCursor aCursor = cursorForPosition( event->pos() );
+    // if the position is not in the last line move it to the end of the command line
+    if ( aCursor.position() < document()->end().previous().position() + promptSize() ) {
+      moveCursor( QTextCursor::End );
+    }
+    else {
+      setTextCursor( aCursor );
+    }
+    const QMimeData* md = QApplication::clipboard()->mimeData( QApplication::clipboard()->supportsSelection() ? 
+                                                              QClipboard::Selection : QClipboard::Clipboard );
+    if ( md )
+      insertFromMimeData( md );
+  }
+  else {
+    QTextEdit::mouseReleaseEvent( event );
+  }
+}
+
+/*!
+  \brief Check if the string is command.
+  
+  Return \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_Editor::isCommand( const QString& str ) const
+{
+  return str.startsWith( READY_PROMPT ) || str.startsWith( DOTS_PROMPT );
+}
+
+/*!
+  \brief Handle keyboard event.
+
+  Implement navigation, history browsing, copy/paste and other common
+  operations.
+
+  \param event keyboard event
+*/
+void PyConsole_Editor::keyPressEvent( QKeyEvent* event )
+{
+  // get cursor position
+  QTextCursor aCursor = textCursor();
+  int curLine = aCursor.blockNumber();
+  int curCol  = aCursor.columnNumber();
+
+  // get last edited line
+  int endLine = document()->blockCount()-1;
+
+  // get pressed key code
+  int aKey = event->key();
+
+  // check if <Ctrl> is pressed
+  bool ctrlPressed = event->modifiers() & Qt::ControlModifier;
+  // check if <Shift> is pressed
+  bool shftPressed = event->modifiers() & Qt::ShiftModifier;
+
+  if ( autoCompletion() ) {
+    // auto-completion support
+    if ( aKey == Qt::Key_Tab && !shftPressed ) {
+      // process <Tab> key
+      if ( !ctrlPressed ) {
+        handleTab();
+      }
+      else {
+        clearCompletion();
+        handleBackTab();
+      }
+      return;
+    }
+
+    // If <Ctrl> is not pressed (or if something else is pressed with <Ctrl>),
+    // or if <Ctrl> is not pressed alone, we have to clear completion
+    if ( !ctrlPressed || ( ctrlPressed && aKey != Qt::Key_Control ) ) {
+      clearCompletion();
+      myComplCursorPos = -1;
+    }
+    
+    // Discard <Ctrl> pressed alone:
+    if ( aKey == Qt::Key_Control )
+      return;
+  }
+
+  if ( aKey == Qt::Key_Escape || ( ctrlPressed && aKey == -1 ) ) {
+    // process <Ctrl>+<Break> key-binding and <Escape> key: clear current command
+    myCommandBuffer.truncate( 0 );
+    myPrompt = READY_PROMPT;
+    addText( myPrompt, true );
+    horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
+    return;
+  }
+  else if ( ctrlPressed && aKey == Qt::Key_C ) {
+    // process <Ctrl>+<C> key-binding : copy
+    copy();
+    return;
+  }
+  else if ( ctrlPressed && aKey == Qt::Key_X ) {
+    // process <Ctrl>+<X> key-binding : cut
+    cut();
+    return;
+  }
+  else if ( ctrlPressed && aKey == Qt::Key_V ) {
+    // process <Ctrl>+<V> key-binding : paste
+    paste();
+    return;
+  }
+
+  // check for printed key
+  // #### aKey = ( aKey < Qt::Key_Space || aKey > Qt::Key_ydiaeresis ) ? aKey : 0;
+  // Better:
+  aKey = !(QChar(aKey).isPrint()) ? aKey : 0;
+
+  switch ( aKey ) {
+  case 0 :
+    // any printed key: just print it
+    {
+      if ( curLine < endLine || curCol < promptSize() ) {
+        moveCursor( QTextCursor::End );
+      }
+      QTextEdit::keyPressEvent( event );
+      break;
+    }
+  case Qt::Key_Return:
+  case Qt::Key_Enter:
+    // <Enter> key: process the current command
+    {
+      handleReturn();
+      break;
+    }
+  case Qt::Key_Up:
+    // <Up> arrow key: process as follows:
+    // - without <Ctrl>, <Shift> modifiers: previous command in history
+    // - with <Ctrl> modifier key pressed:  move cursor one row up without selection
+    // - with <Shift> modifier key pressed: move cursor one row up with selection
+    // - with <Ctrl>+<Shift> modifier keys pressed: scroll one row up
+    {
+      if ( ctrlPressed && shftPressed ) {
+        int value   = verticalScrollBar()->value();
+        int spacing = fontMetrics().lineSpacing();
+        verticalScrollBar()->setValue( value > spacing ? value-spacing : 0 );
+      }
+      else if ( shftPressed || ctrlPressed ) {
+        if ( curLine > 0 )
+          moveCursor( QTextCursor::Up, 
+                      shftPressed ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor );
+      }
+      else { 
+        if ( myCmdInHistory < 0 && myHistory.count() > 0 ) {
+          // set history browsing mode
+          myCmdInHistory = myHistory.count();
+          // remember current command
+          QTextBlock par = document()->end().previous();
+          myCurrentCommand = par.text().remove( 0, promptSize() );
+        }
+        if ( myCmdInHistory > 0 ) {
+          myCmdInHistory--;
+          // get previous command in the history
+          QString previousCommand = myHistory.at( myCmdInHistory );
+          // print previous command
+          moveCursor( QTextCursor::End );
+          moveCursor( QTextCursor::StartOfBlock, QTextCursor::KeepAnchor );
+          textCursor().removeSelectedText();
+          addText( myPrompt + previousCommand ); 
+          // move cursor to the end
+          moveCursor( QTextCursor::End );
+        }
+      }
+      break;
+    }
+  case Qt::Key_Down:
+    // <Down> arrow key: process as follows:
+    // - without <Ctrl>, <Shift> modifiers: next command in history
+    // - with <Ctrl> modifier key pressed:  move cursor one row down without selection
+    // - with <Shift> modifier key pressed: move cursor one row down with selection
+    // - with <Ctrl>+<Shift> modifier keys pressed: scroll one row down
+    {
+      if ( ctrlPressed && shftPressed ) {
+        int value   = verticalScrollBar()->value();
+        int maxval  = verticalScrollBar()->maximum();
+        int spacing = fontMetrics().lineSpacing();
+        verticalScrollBar()->setValue( value+spacing < maxval ? value+spacing : maxval );
+      }
+      else if ( shftPressed || ctrlPressed) {
+        if ( curLine < endLine )
+          moveCursor( QTextCursor::Down, 
+                      shftPressed ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor );
+      }
+      else { 
+        if ( myCmdInHistory >= 0 ) {
+          // get next command in the history
+          myCmdInHistory++;
+          QString nextCommand;
+          if ( myCmdInHistory < myHistory.count() ) {
+            // next command in history
+            nextCommand = myHistory.at( myCmdInHistory );
+          }
+          else {
+            // end of history is reached
+            // last printed command
+            nextCommand = myCurrentCommand;
+            // unset history browsing mode
+            myCmdInHistory = -1;
+          }
+          // print next or current command
+          moveCursor( QTextCursor::End );
+          moveCursor( QTextCursor::StartOfBlock, QTextCursor::KeepAnchor );
+          textCursor().removeSelectedText();
+          addText( myPrompt + nextCommand );
+          // move cursor to the end
+          moveCursor( QTextCursor::End );
+        }
+      }
+      break;
+    }
+  case Qt::Key_Left:
+    // <Left> arrow key: process as follows:
+    // - without <Ctrl>, <Shift> modifiers: move one symbol left (taking into account prompt)
+    // - with <Ctrl> modifier key pressed:  move one word left (taking into account prompt)
+    // - with <Shift> modifier key pressed: move one symbol left with selection
+    // - with <Ctrl>+<Shift> modifier keys pressed: move one word left with selection
+    {
+      QString txt = textCursor().block().text();
+      if ( !shftPressed && isCommand( txt ) && curCol <= promptSize() ) {
+        moveCursor( QTextCursor::Up );
+        moveCursor( QTextCursor::EndOfBlock );
+      }
+      else {
+        QTextEdit::keyPressEvent( event );
+      }
+      break;
+    }
+  case Qt::Key_Right:
+    // <Right> arrow key: process as follows:
+    // - without <Ctrl>, <Shift> modifiers: move one symbol right (taking into account prompt)
+    // - with <Ctrl> modifier key pressed:  move one word right (taking into account prompt)
+    // - with <Shift> modifier key pressed: move one symbol right with selection
+    // - with <Ctrl>+<Shift> modifier keys pressed: move one word right with selection
+    {
+      QString txt = textCursor().block().text();
+      if ( !shftPressed ) {
+        if ( curCol < txt.length() ) {
+          if ( isCommand( txt ) && curCol < promptSize() ) {
+            aCursor.setPosition( aCursor.block().position() + promptSize() );
+            setTextCursor( aCursor );
+            break;
+          }
+        }
+        else {
+          if ( curLine < endLine && isCommand( textCursor().block().next().text() ) ) {
+            aCursor.setPosition( aCursor.position() + promptSize()+1 );
+            setTextCursor( aCursor );
+            horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
+            break;
+          }
+        }
+      }
+      QTextEdit::keyPressEvent( event );
+      break;
+    }
+  case Qt::Key_PageUp:
+    // <PageUp> key: process as follows:
+    // - without <Ctrl>, <Shift> modifiers: first command in history
+    // - with <Ctrl> modifier key pressed:  move cursor one page up without selection
+    // - with <Shift> modifier key pressed: move cursor one page up with selection
+    // - with <Ctrl>+<Shift> modifier keys pressed: scroll one page up
+    {
+      if ( ctrlPressed && shftPressed ) {
+        verticalScrollBar()->triggerAction(QAbstractSlider::SliderPageStepSub);
+      }
+      else if ( shftPressed || ctrlPressed ) {
+        bool moved = false;
+        qreal lastY = cursorRect( aCursor ).top();
+        qreal distance = 0;
+        // move using movePosition to keep the cursor's x
+        do {
+          qreal y = cursorRect( aCursor ).top();
+          distance += qAbs( y - lastY );
+          lastY = y;
+          moved = aCursor.movePosition( QTextCursor::Up, 
+                                        shftPressed ? QTextCursor::KeepAnchor : 
+                                        QTextCursor::MoveAnchor );
+        } while ( moved && distance < viewport()->height() );
+        if ( moved ) {
+          aCursor.movePosition( QTextCursor::Down, 
+                                shftPressed ? QTextCursor::KeepAnchor : 
+                                QTextCursor::MoveAnchor );
+          verticalScrollBar()->triggerAction( QAbstractSlider::SliderPageStepSub );
+        }
+        setTextCursor( aCursor );
+      }
+      else { 
+        if ( myCmdInHistory < 0 && myHistory.count() > 0 ) {
+          // set history browsing mode
+          myCmdInHistory = myHistory.count();
+          // remember current command
+          QTextBlock par = document()->end().previous();
+          myCurrentCommand = par.text().remove( 0, promptSize() );
+        }
+        if ( myCmdInHistory > 0 ) {
+          myCmdInHistory = 0;
+          // get very first command in the history
+          QString firstCommand = myHistory.at( myCmdInHistory );
+          // print first command
+          moveCursor( QTextCursor::End );
+          moveCursor( QTextCursor::StartOfBlock, QTextCursor::KeepAnchor );
+          textCursor().removeSelectedText();
+          addText( myPrompt + firstCommand ); 
+          // move cursor to the end
+          moveCursor( QTextCursor::End );
+        }
+      }
+      break;
+    }
+  case Qt::Key_PageDown:
+    // <PageDown> key: process as follows:
+    // - without <Ctrl>, <Shift> modifiers: last command in history
+    // - with <Ctrl> modifier key pressed:  move cursor one page down without selection
+    // - with <Shift> modifier key pressed: move cursor one page down with selection
+    // - with <Ctrl>+<Shift> modifier keys pressed: scroll one page down
+    {
+      if ( ctrlPressed && shftPressed ) {
+        verticalScrollBar()->triggerAction(QAbstractSlider::SliderPageStepAdd);
+      }
+      else if ( shftPressed || ctrlPressed ) {
+        bool moved = false;
+        qreal lastY = cursorRect( aCursor ).top();
+        qreal distance = 0;
+        // move using movePosition to keep the cursor's x
+        do {
+          qreal y = cursorRect( aCursor ).top();
+          distance += qAbs( y - lastY );
+          lastY = y;
+          moved = aCursor.movePosition( QTextCursor::Down, 
+                                        shftPressed ? QTextCursor::KeepAnchor : 
+                                        QTextCursor::MoveAnchor );
+        } while ( moved && distance < viewport()->height() );
+        if ( moved ) {
+          aCursor.movePosition( QTextCursor::Up, 
+                                shftPressed ? QTextCursor::KeepAnchor : 
+                                QTextCursor::MoveAnchor );
+          verticalScrollBar()->triggerAction( QAbstractSlider::SliderPageStepSub );
+        }
+        setTextCursor( aCursor );
+      }
+      else { 
+        if ( myCmdInHistory >= 0 ) {
+          // unset history browsing mode
+          myCmdInHistory = -1;
+          // print current command
+          moveCursor( QTextCursor::End );
+          moveCursor( QTextCursor::StartOfBlock, QTextCursor::KeepAnchor );
+          textCursor().removeSelectedText();
+          addText( myPrompt + myCurrentCommand ); 
+          // move cursor to the end
+          moveCursor( QTextCursor::End );
+        }
+      }
+      break;
+    }
+  case Qt::Key_Home: 
+    // <Home> key: process as follows:
+    // - without <Ctrl>, <Shift> modifiers: move cursor to the beginning of the current line without selection
+    // - with <Ctrl> modifier key pressed:  move cursor to the very first symbol without selection
+    // - with <Shift> modifier key pressed: move cursor to the beginning of the current line with selection
+    // - with <Ctrl>+<Shift> modifier keys pressed: move cursor to the very first symbol with selection
+    {
+      if ( ctrlPressed ) { 
+        moveCursor( QTextCursor::Start, 
+                    shftPressed ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor );
+      }
+      else {
+        QString txt = textCursor().block().text();
+        if ( isCommand( txt ) ) {
+          if ( shftPressed ) {
+            if ( curCol > promptSize() ) {
+              aCursor.movePosition( QTextCursor::StartOfLine, QTextCursor::KeepAnchor );
+              aCursor.movePosition( QTextCursor::Right, QTextCursor::KeepAnchor, promptSize() );
+            }
+          }
+          else {
+            aCursor.movePosition( QTextCursor::StartOfLine );
+            aCursor.movePosition( QTextCursor::Right, QTextCursor::MoveAnchor, promptSize() );
+          }
+          setTextCursor( aCursor );
+        }
+        else {
+          moveCursor( QTextCursor::StartOfBlock, 
+                      shftPressed ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor );
+        }
+        horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
+      }
+      break;
+    }
+  case Qt::Key_End:
+    // <End> key: process as follows:
+    // - without <Ctrl>, <Shift> modifiers: move cursor to the end of the current line without selection
+    // - with <Ctrl> modifier key pressed:  move cursor to the very last symbol without selection
+    // - with <Shift> modifier key pressed: move cursor to the end of the current line with selection
+    // - with <Ctrl>+<Shift> modifier keys pressed: move cursor to the very last symbol with selection
+    {
+      moveCursor( ctrlPressed ? QTextCursor::End : QTextCursor::EndOfBlock, 
+                  shftPressed ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor );
+      break;
+    }  
+  case Qt::Key_Backspace :
+    // <Backspace> key: process as follows
+    // - without any modifiers : delete symbol before the cursor / selection (taking into account prompt)
+    // - with <Shift> modifier key pressed: delete previous word
+    // - with <Ctrl> modifier key pressed: delete text from the cursor to the line beginning
+    // works only for last (command) line
+    {
+      if ( aCursor.hasSelection() ) {
+        cut();
+      }
+      else if ( aCursor.position() > document()->end().previous().position() + promptSize() ) {
+        if ( shftPressed ) {
+          moveCursor( QTextCursor::PreviousWord, QTextCursor::KeepAnchor );
+          textCursor().removeSelectedText();
+        }
+        else if ( ctrlPressed ) {
+          aCursor.setPosition( document()->end().previous().position() + promptSize(),
+                               QTextCursor::KeepAnchor );
+          setTextCursor( aCursor );
+          textCursor().removeSelectedText();
+        }
+        else {
+          QTextEdit::keyPressEvent( event );
+        }
+      }
+      else {
+        aCursor.setPosition( document()->end().previous().position() + promptSize() );
+        setTextCursor( aCursor );
+        horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
+      }
+      break;
+    }
+  case Qt::Key_Delete :
+    // <Delete> key: process as follows
+    // - without any modifiers : delete symbol after the cursor / selection (taking into account prompt)
+    // - with <Shift> modifier key pressed: delete next word
+    // - with <Ctrl> modifier key pressed: delete text from the cursor to the end of line
+    // works only for last (command) line
+    {
+      if ( aCursor.hasSelection() ) {
+        cut();
+      }
+      else if ( aCursor.position() > document()->end().previous().position() + promptSize()-1 ) {
+        if ( shftPressed ) {
+          moveCursor( QTextCursor::NextWord, QTextCursor::KeepAnchor );
+          textCursor().removeSelectedText();
+        }
+        else if ( ctrlPressed ) {
+          moveCursor( QTextCursor::EndOfBlock, QTextCursor::KeepAnchor );
+          textCursor().removeSelectedText();
+        }
+        else {
+          QTextEdit::keyPressEvent( event );
+        }
+      }
+      else {
+        aCursor.setPosition( document()->end().previous().position() + promptSize() );
+        setTextCursor( aCursor );
+        horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
+      }
+      break;
+    }
+  case Qt::Key_Insert :
+    // <Insert> key: process as follows
+    // - with <Ctrl> modifier key pressed:  copy()
+    // - with <Shift> modifier key pressed: paste() to the command line
+    {
+      if ( ctrlPressed ) {
+        copy();
+      }
+      else if ( shftPressed ) {
+        paste();
+      }
+      else
+        QTextEdit::keyPressEvent( event );
+      break;
+    }
+  default:
+    break;
+  }
+}
+
+/*!
+  \brief Handle notification event coming from Python dispatcher.
+  \param event notification event
+*/
+void PyConsole_Editor::customEvent( QEvent* event )
+{
+  switch( event->type() )
+  {
+  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:
+  {
+    // clear command buffer
+    myCommandBuffer.truncate( 0 );
+    // add caret return line if necessary
+    QTextBlock par = document()->end().previous();
+    QString txt = par.text();
+    txt.truncate( txt.length() - 1 );
+    // IPAL19397 : addText moved to handleReturn() method
+    //if ( !txt.isEmpty() )
+    //  addText( "", true );
+    // set "ready" prompt
+    myPrompt = READY_PROMPT;
+    addText( myPrompt );
+    // unset busy cursor
+    unsetCursor();
+    // stop event loop (if running)
+    if ( myEventLoop )
+      myEventLoop->exit();
+    // if we are in multi_paste_mode, process the next item
+    multiLineProcessNextLine();
+    break;
+  }
+  case PyInterp_Event::ES_INCOMPLETE:
+  {
+    // extend command buffer (multi-line command)
+    myCommandBuffer.append( "\n" );
+    // add caret return line if necessary
+    QTextBlock par = document()->end().previous();
+    QString txt = par.text();
+    txt.truncate( txt.length() - 1 );
+    // IPAL19397 : addText moved to handleReturn() method
+    //if ( !txt.isEmpty() )
+    //  addText( "", true );
+    // set "dot" prompt
+    myPrompt = DOTS_PROMPT;
+    addText( myPrompt/*, true*/ ); // IPAL19397
+    // unset busy cursor
+    unsetCursor();
+    // stop event loop (if running)
+    if ( myEventLoop )
+      myEventLoop->exit();
+    // if we are in multi_paste_mode, process the next item
+    multiLineProcessNextLine();
+    break;
+  }
+  default:
+    QTextEdit::customEvent( event );
+  }
+  
+  // unset read-only state
+  setReadOnly( false );
+  // unset history browsing mode
+  myCmdInHistory = -1;
+
+  if ( (int)event->type() == (int)PyInterp_Event::ES_OK && myQueue.count() > 0 )
+  {
+    // process the next sheduled command from the queue (if there is any)
+    QString nextcmd = myQueue[0];
+    myQueue.pop_front();
+    exec( nextcmd );
+  }
+}
+
+/*!
+  \brief "Copy" operation.
+  
+  Reimplemented from Qt.
+  Warning! In Qt this method is not virtual.
+*/
+void PyConsole_Editor::cut()
+{
+  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 = aCursor.selectionEnd();
+    if ( endSelection < document()->end().previous().position() + promptSize() )
+      endSelection = document()->end().previous().position() + promptSize();
+    aCursor.setPosition( startSelection );
+    aCursor.setPosition( endSelection, QTextCursor::KeepAnchor );
+    horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
+    setTextCursor( aCursor );
+    textCursor().removeSelectedText();
+  }
+}
+
+/*!
+  \brief "Paste" operation.
+
+  Reimplemented from Qt.
+  Warning! In Qt this method is not virtual.
+*/
+void PyConsole_Editor::paste()
+{
+  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 = aCursor.selectionEnd();
+    if ( endSelection < document()->end().previous().position() + promptSize() )
+      endSelection = document()->end().previous().position() + promptSize();
+    aCursor.setPosition( startSelection );
+    aCursor.setPosition( endSelection, QTextCursor::KeepAnchor );
+    horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
+    setTextCursor( aCursor );
+    textCursor().removeSelectedText();
+  }
+  if ( textCursor().position() < document()->end().previous().position() + promptSize() )
+    moveCursor( QTextCursor::End );
+  QTextEdit::paste();
+}
+
+/*!
+  \brief "Clear" operation.
+
+  Reimplemented from Qt.
+  Warning! In Qt this method is not virtual.
+*/
+void PyConsole_Editor::clear()
+{
+  QTextEdit::clear();
+  if ( isShowBanner() )
+    addText( banner() );
+  myPrompt = READY_PROMPT;
+  addText( myPrompt );
+}
+
+/*!
+  \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 ) ) {
+      QTextStream out( &file );
+      for ( int i = 0; i < myHistory.count(); i++ ) {
+        out << myHistory[i] << endl;
+      }
+      file.close();
+      ok = true;
+    }
+  }
+  return ok;
+}
+
+/*!
+  \brief Dump menu action slot
+*/
+void PyConsole_Editor::dump()
+{
+  forever {
+    // get file name
+    QString fileName = getDumpFileName();
+
+    if ( fileName.isEmpty() )
+      break; // cancelled
+    
+    if ( dump( fileName ) )
+      break;
+    else
+      QMessageBox::warning( this,
+                            tr( "WARNING" ),
+                            tr( "ERR_FILE_NOT_WRITEABLE" ) );
+  }
+}
+
+/*!
+  \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 PyConsole_Editor::getDumpFileName()
+{
+  return QFileDialog::getSaveFileName( this,
+                                       tr( "GET_DUMP_COMMANDS_FILENAME" ),
+                                       QString(),
+                                       QString( "%1 (*.py)" ).arg( tr( "PYTHON_SCRIPTS" ) ) );
+}
+
+/*!
+  \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 PyConsole_Editor::getLogFileName()
+{
+  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_Editor::startLog( const QString& fileName )
+{
+  // stop possibly already running logging
+  if ( isLogging() )
+    stopLog();
+
+  bool ok = false;
+  if ( !fileName.isEmpty() ) {
+    QFile file( fileName );
+    if ( file.open( QFile::WriteOnly ) ) {
+      file.close();
+      myLogFile = fileName;
+      ok = true;
+    }
+  }
+  return ok;
+}
+
+/*!
+  \brief Start log action slot
+*/
+void PyConsole_Editor::startLog()
+{
+  forever {
+    // get file name
+    QString fileName = getLogFileName();
+
+    if ( fileName.isEmpty() )
+      break; // cancelled
+    
+    if ( startLog( fileName ) )
+      break;
+    else
+      QMessageBox::warning( this,
+                            tr( "WARNING" ),
+                            tr( "File is not writable" ) );
+  }
+}
+
+/*!
+  \brief Stop log action slot
+  
+  Stops Python trace logging.
+*/
+void PyConsole_Editor::stopLog()
+{
+  myLogFile = QString();
+}
+
+/*!
+  \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 );
+    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 <RETURN> 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 <Tab> 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 = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" " \
+    "\"http://www.w3.org/TR/REC-html40/strict.dtd\">\n" \
+    "<html><head><meta name=\"qrichtext\" content=\"1\" /> " \
+    "<style type=\"text/css\">\np, li { white-space: pre-wrap; }\n</style> " \
+    "</head><body style=\" font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;\">\n" \
+    "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"> " \
+    "<span style=\" font-weight:600; color:#0000ff;\">%1</span></p> " \
+    "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">%2</p> " \
+    "</body></html>";
+  
+  QString fst, rest("");
+
+  // Extract first line of doc
+  int idx = doc.indexOf( "\n" );
+  if ( idx > 0 ) {
+    fst = doc.left( idx );
+    rest = doc.mid( idx+1 );
+  }
+  else {
+    fst = doc;
+  }
+
+  fst = fst.replace( "\n", " " );
+  rest = rest.replace(" \n", " " );
+  return 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 (file)
index 0000000..774e101
--- /dev/null
@@ -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 <QTextEdit>
+#include <QQueue>
+
+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<QString>   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 <TAB> is hit
+
+};
+
+#endif // PYCONSOLE_EDITOR_H
diff --git a/src/PyConsole/PyConsole_EditorBase.cxx b/src/PyConsole/PyConsole_EditorBase.cxx
deleted file mode 100644 (file)
index 0c5e915..0000000
+++ /dev/null
@@ -1,1260 +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:
-  - <Enter>              : execute current command
-  - <Ctrl><Break>        : clear current command
-  - <Escape>             : clear current command
-  - <Up>                 : previous command in the history
-  - <Shift><Up>          : move cursor one row up with selection
-  - <Ctrl><Up>           : move cursor one row up without selection
-  - <Ctrl><Shift><Up>    : move cursor one row up with selection
-  - <Down>               : next command in the history
-  - <Shift><Down>        : move cursor one row down with selection
-  - <Ctrl><Down>         : move cursor one row down without selection
-  - <Ctrl><Shift><Down>  : move cursor one row down with selection
-  - <Left>               : move one symbol left without selection
-  - <Shift><Left>        : move one symbol left with selection
-  - <Ctrl><Left>         : move one word left without selection
-  - <Ctrl><Shift><Left>  : move one word left with selection
-  - <Right>              : move one symbol right without selection
-  - <Shift><Right>       : move one symbol right with selection
-  - <Ctrl><Right>        : move one word right without selection
-  - <Ctrl><Shift><Right> : move one word right with selection
-  - <PgUp>               : first command in the history
-  - <Shift><PgUp>        : move one page up with selection
-  - <Ctrl><PgUp>         : move one page up without selection
-  - <Ctrl><Shift><PgUp>  : scroll one page up
-  - <PgDn>               : last command in the history
-  - <Shift><PgDn>        : move one page down with selection
-  - <Ctrl><PgDn>         : move one page down without selection
-  - <Ctrl><Shift><PgDn>  : scroll one page down
-  - <Home>               : move to the beginning of the line without selection
-  - <Shift><Home>        : move to the beginning of the line with selection
-  - <Ctrl><Home>         : move to the very first symbol without selection
-  - <Ctrl><Shift><Home>  : move to the very first symbol with selection
-  - <End>                : move to the end of the line without selection
-  - <Shift><End>         : move to the end of the line with selection
-  - <Ctrl><End>          : move to the very last symbol without selection
-  - <Ctrl><Shift><End>   : move to the very last symbol with selection
-  - <Backspace>          : delete symbol before the cursor
-                           / remove selected text and put it to the clipboard (cut)
-  - <Shift><Backspace>   : delete previous word
-                           / remove selected text and put it to the clipboard (cut)
-  - <Ctrl><Backspace>    : delete text from the cursor to the beginning of the line 
-                           / remove selected text and put it to the clipboard (cut)
-  - <Delete>             : delete symbol after the cursor 
-                           / remove selected text and put it to the clipboard (cut)
-  - <Shift><Delete>      : delete next word
-                           / remove selected text and put it to the clipboard (cut)
-  - <Ctrl><Delete>       : delete text from the cursor to the end of the line
-                           / remove selected text and put it to the clipboard (cut)
-  - <Ctrl><Insert>       : copy
-  - <Shift><Insert>      : paste
-  - <Ctrl><V>            : paste
-  - <Ctrl><C>            : copy
-  - <Ctrl><X>            : cut
-  - <Ctrl><V>            : paste
-*/
-
-#include "PyConsole_Interp.h"   // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!!
-#include "PyConsole_EditorBase.h"
-#include "PyConsole_Event.h"
-#include "PyInterp_Event.h"
-#include "PyInterp_Dispatcher.h"
-#include "PyConsole_Request.h"
-
-#include <Qtx.h>
-
-#include <QApplication>
-#include <QClipboard>
-#include <QDropEvent>
-#include <QEvent>
-#include <QKeyEvent>
-#include <QMouseEvent>
-#include <QScrollBar>
-#include <QTextBlock>
-#include <QTextCursor>
-#include <QTextDocument>
-#include <QTextStream>
-#include <QChar>
-#include <QFileInfo>
-#include <QFileDialog>
-#include <QMessageBox>
-
-//VSR: uncomment below macro to support unicode text properly in SALOME
-//     current commented out due to regressions
-//#define PAL22528_UNICODE
-
-namespace
-{
-  QString fromUtf8( const char* txt )
-  {
-#ifdef PAL22528_UNICODE
-    return QString::fromUtf8( txt );
-#else
-    return QString( txt );
-#endif
-  }
-}
-
-static QString READY_PROMPT = ">>> ";
-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 ) );
-  }
-}
-
-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 ) );
-  }
-}
-
-
-/*!
-  \brief Constructor. 
-  
-  Creates python editor window.
-  \param theInterp python interper
-  \param theParent parent widget
-*/
-PyConsole_EditorBase::PyConsole_EditorBase( PyConsole_Interp* theInterp, 
-                                            QWidget*          theParent )
-: QTextEdit( theParent ),
-  myInterp( 0 ),
-  myCmdInHistory( -1 ),
-  myEventLoop( 0 ),
-  myShowBanner( true ),
-  myIsSync( true ),
-  myIsSuppressOutput( false )
-{
-  QString fntSet( "" );
-  QFont aFont ( Qtx::stringToFont(fntSet) );
-  setFont( aFont );
-  setUndoRedoEnabled( false );
-
-  myPrompt = READY_PROMPT;
-  setLineWrapMode( QTextEdit::WidgetWidth );
-  setWordWrapMode( QTextOption::WrapAnywhere );
-  setAcceptRichText( false );
-
-  theInterp->setvoutcb( staticCallbackStdout, this );
-  theInterp->setverrcb( staticCallbackStderr, this );
-
-  // san - This is necessary for troubleless initialization
-  onPyInterpChanged( theInterp );
-}
-
-/*!
-  \brief Destructor.
-*/
-PyConsole_EditorBase::~PyConsole_EditorBase()
-{
-  myInterp = 0;
-}
-
-/*!
-  \brief Get Python interpreter
-*/
-PyConsole_Interp* PyConsole_EditorBase::getInterp() const
-{
-  return myInterp;
-}
-
-/*!
-  \brief Get synchronous mode flag value.
-  
-  \sa setIsSync()
-  \return True if python console works in synchronous mode
-*/
-bool PyConsole_EditorBase::isSync() const
-{
-  return myIsSync;
-}
-
-/*!
-  \brief Set synchronous mode flag value.
-
-  In synhronous mode the Python commands are executed in the GUI thread
-  and the GUI is blocked until the command is finished. In the asynchronous
-  mode each Python command is executed in the separate thread that does not
-  block the main GUI loop.
-
-  \param on synhronous mode flag
-*/
-void PyConsole_EditorBase::setIsSync( const bool on )
-{
-  myIsSync = on;
-}
-
-/*!
-  \brief Get suppress output flag value.
-  
-  \sa setIsSuppressOutput()
-  \return \c true if python console output is suppressed.
-*/
-bool PyConsole_EditorBase::isSuppressOutput() const
-{
-  return myIsSuppressOutput;
-}
-
-/*!
-  \brief Set suppress output flag value.
-
-  In case if suppress output flag is true, the python 
-  console output suppressed.
-
-  \param on suppress output flag
-*/
-void PyConsole_EditorBase::setIsSuppressOutput( const bool on )
-{
-  myIsSuppressOutput = on;
-}
-
-/*!
-  \brief Get 'show banner' flag value.
-  
-  \sa setIsShowBanner()
-  \return \c true if python console shows banner
-*/
-bool PyConsole_EditorBase::isShowBanner() const
-{
-  return myShowBanner;
-}
-
-/*!
-  \brief Set 'show banner' flag value.
-
-  The banner is shown in the top of the python console window.
-
-  \sa isShowBanner()
-  \param on 'show banner' flag
-*/
-void PyConsole_EditorBase::setIsShowBanner( const bool on )
-{
-  if ( myShowBanner != on ) {
-    myShowBanner = on;
-    clear();
-  }
-}
-
-/*!
-  \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
-{
-  return !myLogFile.isEmpty();
-}
-
-/*!
-  \brief Get size hint for the Python console window
-  \return size hint value
-*/
-QSize PyConsole_EditorBase::sizeHint() const
-{
-  QFontMetrics fm( font() );
-  int nbLines = ( isShowBanner() ? myBanner.split("\n").count() : 0 ) + 1;
-  QSize s(100, fm.lineSpacing()*nbLines);
-  return s;
-}
-
-/*!
-  \brief Put the string \a str to the python editor.
-  \param str string to be put in the command line of the editor
-  \param newBlock if True, then the string is printed on a new line
-  \param isError if true, the text is printed in dark red
-*/
-void PyConsole_EditorBase::addText( const QString& str, 
-                                const bool     newBlock,
-                                const bool    isError)
-{
-  QTextCursor theCursor(textCursor());
-  QTextCharFormat cf;
-
-  moveCursor( QTextCursor::End );
-  if ( newBlock )
-    theCursor.insertBlock();
-  if (isError)
-      cf.setForeground(QBrush(Qt::red));
-  else
-      cf.setForeground(QBrush(Qt::black));
-  theCursor.insertText( str, cf);
-  moveCursor( QTextCursor::End );
-  ensureCursorVisible();
-}
-
-/*!
-  \brief Convenient method for executing a Python command,
-  as if the user typed it manually.
-  \param command python command to be executed
-
-  !!! WARNING: doesn't work properly with multi-line commands. !!!
-*/
-void PyConsole_EditorBase::exec( const QString& command )
-{
-  if ( isReadOnly() ) {
-    // some interactive command is being executed in this editor...
-    // shedule the command to the queue
-    myQueue.push_back( command );
-    return;
-  }
-  // remove last line
-  moveCursor( QTextCursor::End );
-  moveCursor( QTextCursor::StartOfBlock, QTextCursor::KeepAnchor );
-  textCursor().removeSelectedText();
-  // set "ready" prompt
-  myPrompt = READY_PROMPT;
-  // clear command buffer
-  myCommandBuffer.truncate( 0 );
-  // unset history browsing mode
-  myCmdInHistory = -1;
-  // print command line by line
-  QString cmd = command;
-  if ( !cmd.endsWith( "\n" ) ) cmd += "\n";
-  QStringList lines = command.split( "\n" );
-  for ( int i = 0; i < lines.size(); i++ ) {
-    if ( !lines[i].trimmed().isEmpty() )
-      myHistory.push_back( lines[i] );
-    addText( ( i == 0 ? READY_PROMPT : DOTS_PROMPT ) + lines[i], i != 0 );
-    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 ) );
-}
-
-/*!
-  \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 )
-{
-  return new ExecCommand( myInterp, command, this, isSync() );
-}
-
-/*!
-  \brief Execute command in the python interpreter
-  and wait until it is finished.
-
-  \param command python command to be executed
- */
-void PyConsole_EditorBase::execAndWait( const QString& command )
-{
-  // already running ?
-  if( myEventLoop )
-    return;
-
-  // create new event loop
-  bool sync = isSync();
-  if ( !sync ) {
-    myEventLoop = new QEventLoop( this );
-  }
-
-  // execute command
-  exec( command );
-
-  if ( !sync ) {
-    // run event loop
-    myEventLoop->exec();
-    // delete event loop after command is processed
-    delete myEventLoop;
-    myEventLoop = 0;
-  }
-}
-
-/*!
-  \brief Process "Enter" key press event. 
-  
-  Execute the command entered by the user.
-*/
-void PyConsole_EditorBase::handleReturn()
-{
-  // Position cursor at the end
-  QTextCursor curs(textCursor());
-  curs.movePosition(QTextCursor::End);
-  setTextCursor(curs);
-
-  // get last line
-  QTextBlock par = document()->end().previous();
-  if ( !par.isValid() ) return;
-
-  // get command
-  QString cmd = par.text().remove( 0, promptSize() );
-  // extend the command buffer with the current command 
-  myCommandBuffer.append( cmd );
-  // add command to the history
-  if ( !cmd.trimmed().isEmpty() )
-    myHistory.push_back( cmd );
-  putLog( QString( "%1%2\n" ).arg( myPrompt ).arg( cmd ) );
-
-  // IPAL19397
-  addText( "", true ); 
-  
-  // set read-only mode
-  setReadOnly( true );
-  // set busy cursor
-  setCursor( Qt::BusyCursor );
-  
-  // post a request to execute Python command;
-  // editor will be informed via a custom event that execution has been completed
-  PyInterp_Dispatcher::Get()->Exec( createRequest( myCommandBuffer ) );
-}
-
-/*!
-  \brief Process drop event.
-
-  Paste dragged text.
-  \param event drop event
-*/
-void PyConsole_EditorBase::dropEvent( QDropEvent* event )
-{
-  // get the initial drop position
-  QPoint pos = event->pos();
-  QTextCursor cur = cursorForPosition( event->pos() );
-  // if the position is not in the last line move it to the end of the command line
-  if ( cur.position() < document()->end().previous().position() + promptSize() ) {
-    moveCursor( QTextCursor::End );
-    pos = cursorRect().center();
-  }
-  // create new drop event and use it instead of the original
-  QDropEvent de( pos,
-                 event->possibleActions(),
-                 event->mimeData(),
-                 event->mouseButtons(),
-                 event->keyboardModifiers(),
-                 event->type() );
-  QTextEdit::dropEvent( &de );
-  // accept the original event
-  event->acceptProposedAction();
-}
-
-/*!
-  \brief Process mouse button release event.
-
-  Left mouse button: copy selection to the clipboard.
-  Middle mouse button: paste clipboard's contents.
-  \param event mouse event
-*/
-void PyConsole_EditorBase::mouseReleaseEvent( QMouseEvent* event )
-{
-  if ( event->button() == Qt::LeftButton ) {
-    QTextEdit::mouseReleaseEvent( event );
-    //copy();
-  }
-  else if ( event->button() == Qt::MidButton ) {
-    QTextCursor cur = cursorForPosition( event->pos() );
-    // if the position is not in the last line move it to the end of the command line
-    if ( cur.position() < document()->end().previous().position() + promptSize() ) {
-      moveCursor( QTextCursor::End );
-    }
-    else {
-      setTextCursor( cur );
-    }
-    const QMimeData* md = QApplication::clipboard()->mimeData( QApplication::clipboard()->supportsSelection() ? 
-                                                              QClipboard::Selection : QClipboard::Clipboard );
-    if ( md )
-      insertFromMimeData( md );
-  }
-  else {
-    QTextEdit::mouseReleaseEvent( event );
-  }
-}
-
-/*!
-  \brief Check if the string is command.
-  
-  Return True if the string \a str is likely to be the command
-  (i.e. it is started from the '>>>' or '...').
-  \param str string to be checked
-*/
-bool PyConsole_EditorBase::isCommand( const QString& str ) const
-{
-  return str.startsWith( READY_PROMPT ) || str.startsWith( DOTS_PROMPT );
-}
-
-/*!
-  \brief Handle keyboard event.
-
-  Implement navigation, history browsing, copy/paste and other common
-  operations.
-  \param event keyboard event
-*/
-void PyConsole_EditorBase::keyPressEvent( QKeyEvent* event )
-{
-  // get cursor position
-  QTextCursor cur = textCursor();
-  int curLine = cur.blockNumber();
-  int curCol  = cur.columnNumber();
-
-  // get last edited line
-  int endLine = document()->blockCount()-1;
-
-  // get pressed key code
-  int aKey = event->key();
-
-  // check if <Ctrl> is pressed
-  bool ctrlPressed = event->modifiers() & Qt::ControlModifier;
-  // check if <Shift> is pressed
-  bool shftPressed = event->modifiers() & Qt::ShiftModifier;
-
-  if ( aKey == Qt::Key_Escape || ( ctrlPressed && aKey == -1 ) ) {
-    // process <Ctrl>+<Break> key-binding and <Escape> key: clear current command
-    myCommandBuffer.truncate( 0 );
-    myPrompt = READY_PROMPT;
-    addText( myPrompt, true );
-    horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
-    return;
-  }
-  else if ( ctrlPressed && aKey == Qt::Key_C ) {
-    // process <Ctrl>+<C> key-binding : copy
-    copy();
-    return;
-  }
-  else if ( ctrlPressed && aKey == Qt::Key_X ) {
-    // process <Ctrl>+<X> key-binding : cut
-    cut();
-    return;
-  }
-  else if ( ctrlPressed && aKey == Qt::Key_V ) {
-    // process <Ctrl>+<V> key-binding : paste
-    paste();
-    return;
-  }
-
-  // check for printed key
-  // #### aKey = ( aKey < Qt::Key_Space || aKey > Qt::Key_ydiaeresis ) ? aKey : 0;
-  // Better:
-  aKey = !(QChar(aKey).isPrint()) ? aKey : 0;
-
-  switch ( aKey ) {
-  case 0 :
-    // any printed key: just print it
-    {
-      if ( curLine < endLine || curCol < promptSize() ) {
-        moveCursor( QTextCursor::End );
-      }
-      QTextEdit::keyPressEvent( event );
-      break;
-    }
-  case Qt::Key_Return:
-  case Qt::Key_Enter:
-    // <Enter> key: process the current command
-    {
-      handleReturn();
-      break;
-    }
-  case Qt::Key_Up:
-    // <Up> arrow key: process as follows:
-    // - without <Ctrl>, <Shift> modifiers: previous command in history
-    // - with <Ctrl> modifier key pressed:  move cursor one row up without selection
-    // - with <Shift> modifier key pressed: move cursor one row up with selection
-    // - with <Ctrl>+<Shift> modifier keys pressed: scroll one row up
-    {
-      if ( ctrlPressed && shftPressed ) {
-        int value   = verticalScrollBar()->value();
-        int spacing = fontMetrics().lineSpacing();
-        verticalScrollBar()->setValue( value > spacing ? value-spacing : 0 );
-      }
-      else if ( shftPressed || ctrlPressed ) {
-        if ( curLine > 0 )
-          moveCursor( QTextCursor::Up, 
-                      shftPressed ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor );
-      }
-      else { 
-        if ( myCmdInHistory < 0 && myHistory.count() > 0 ) {
-          // set history browsing mode
-          myCmdInHistory = myHistory.count();
-          // remember current command
-          QTextBlock par = document()->end().previous();
-          myCurrentCommand = par.text().remove( 0, promptSize() );
-        }
-        if ( myCmdInHistory > 0 ) {
-          myCmdInHistory--;
-          // get previous command in the history
-          QString previousCommand = myHistory.at( myCmdInHistory );
-          // print previous command
-          moveCursor( QTextCursor::End );
-          moveCursor( QTextCursor::StartOfBlock, QTextCursor::KeepAnchor );
-          textCursor().removeSelectedText();
-          addText( myPrompt + previousCommand ); 
-          // move cursor to the end
-          moveCursor( QTextCursor::End );
-        }
-      }
-      break;
-    }
-  case Qt::Key_Down:
-    // <Down> arrow key: process as follows:
-    // - without <Ctrl>, <Shift> modifiers: next command in history
-    // - with <Ctrl> modifier key pressed:  move cursor one row down without selection
-    // - with <Shift> modifier key pressed: move cursor one row down with selection
-    // - with <Ctrl>+<Shift> modifier keys pressed: scroll one row down
-    {
-      if ( ctrlPressed && shftPressed ) {
-        int value   = verticalScrollBar()->value();
-        int maxval  = verticalScrollBar()->maximum();
-        int spacing = fontMetrics().lineSpacing();
-        verticalScrollBar()->setValue( value+spacing < maxval ? value+spacing : maxval );
-      }
-      else if ( shftPressed || ctrlPressed) {
-        if ( curLine < endLine )
-          moveCursor( QTextCursor::Down, 
-                      shftPressed ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor );
-      }
-      else { 
-        if ( myCmdInHistory >= 0 ) {
-          // get next command in the history
-          myCmdInHistory++;
-          QString nextCommand;
-          if ( myCmdInHistory < myHistory.count() ) {
-            // next command in history
-            nextCommand = myHistory.at( myCmdInHistory );
-          }
-          else {
-            // end of history is reached
-            // last printed command
-            nextCommand = myCurrentCommand;
-            // unset history browsing mode
-            myCmdInHistory = -1;
-          }
-          // print next or current command
-          moveCursor( QTextCursor::End );
-          moveCursor( QTextCursor::StartOfBlock, QTextCursor::KeepAnchor );
-          textCursor().removeSelectedText();
-          addText( myPrompt + nextCommand );
-          // move cursor to the end
-          moveCursor( QTextCursor::End );
-        }
-      }
-      break;
-    }
-  case Qt::Key_Left:
-    // <Left> arrow key: process as follows:
-    // - without <Ctrl>, <Shift> modifiers: move one symbol left (taking into account prompt)
-    // - with <Ctrl> modifier key pressed:  move one word left (taking into account prompt)
-    // - with <Shift> modifier key pressed: move one symbol left with selection
-    // - with <Ctrl>+<Shift> modifier keys pressed: move one word left with selection
-    {
-      QString txt = textCursor().block().text();
-      if ( !shftPressed && isCommand( txt ) && curCol <= promptSize() ) {
-        moveCursor( QTextCursor::Up );
-        moveCursor( QTextCursor::EndOfBlock );
-      }
-      else {
-        QTextEdit::keyPressEvent( event );
-      }
-      break;
-    }
-  case Qt::Key_Right:
-    // <Right> arrow key: process as follows:
-    // - without <Ctrl>, <Shift> modifiers: move one symbol right (taking into account prompt)
-    // - with <Ctrl> modifier key pressed:  move one word right (taking into account prompt)
-    // - with <Shift> modifier key pressed: move one symbol right with selection
-    // - with <Ctrl>+<Shift> modifier keys pressed: move one word right with selection
-    {
-      QString txt = textCursor().block().text();
-      if ( !shftPressed ) {
-        if ( curCol < txt.length() ) {
-          if ( isCommand( txt ) && curCol < promptSize() ) {
-            cur.setPosition( cur.block().position() + promptSize() );
-            setTextCursor( cur );
-            break;
-          }
-        }
-        else {
-          if ( curLine < endLine && isCommand( textCursor().block().next().text() ) ) {
-            cur.setPosition( cur.position() + promptSize()+1 );
-            setTextCursor( cur );
-            horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
-            break;
-          }
-        }
-      }
-      QTextEdit::keyPressEvent( event );
-      break;
-    }
-  case Qt::Key_PageUp:
-    // <PageUp> key: process as follows:
-    // - without <Ctrl>, <Shift> modifiers: first command in history
-    // - with <Ctrl> modifier key pressed:  move cursor one page up without selection
-    // - with <Shift> modifier key pressed: move cursor one page up with selection
-    // - with <Ctrl>+<Shift> modifier keys pressed: scroll one page up
-    {
-      if ( ctrlPressed && shftPressed ) {
-        verticalScrollBar()->triggerAction(QAbstractSlider::SliderPageStepSub);
-      }
-      else if ( shftPressed || ctrlPressed ) {
-        bool moved = false;
-        qreal lastY = cursorRect( cur ).top();
-        qreal distance = 0;
-        // move using movePosition to keep the cursor's x
-        do {
-          qreal y = cursorRect( cur ).top();
-          distance += qAbs( y - lastY );
-          lastY = y;
-          moved = cur.movePosition( QTextCursor::Up, 
-                                    shftPressed ? QTextCursor::KeepAnchor : 
-                                                  QTextCursor::MoveAnchor );
-        } while ( moved && distance < viewport()->height() );
-        if ( moved ) {
-          cur.movePosition( QTextCursor::Down, 
-                            shftPressed ? QTextCursor::KeepAnchor : 
-                                          QTextCursor::MoveAnchor );
-          verticalScrollBar()->triggerAction( QAbstractSlider::SliderPageStepSub );
-        }
-        setTextCursor( cur );
-      }
-      else { 
-        if ( myCmdInHistory < 0 && myHistory.count() > 0 ) {
-          // set history browsing mode
-          myCmdInHistory = myHistory.count();
-          // remember current command
-          QTextBlock par = document()->end().previous();
-          myCurrentCommand = par.text().remove( 0, promptSize() );
-        }
-        if ( myCmdInHistory > 0 ) {
-          myCmdInHistory = 0;
-          // get very first command in the history
-          QString firstCommand = myHistory.at( myCmdInHistory );
-          // print first command
-          moveCursor( QTextCursor::End );
-          moveCursor( QTextCursor::StartOfBlock, QTextCursor::KeepAnchor );
-          textCursor().removeSelectedText();
-          addText( myPrompt + firstCommand ); 
-          // move cursor to the end
-          moveCursor( QTextCursor::End );
-        }
-      }
-      break;
-    }
-  case Qt::Key_PageDown:
-    // <PageDown> key: process as follows:
-    // - without <Ctrl>, <Shift> modifiers: last command in history
-    // - with <Ctrl> modifier key pressed:  move cursor one page down without selection
-    // - with <Shift> modifier key pressed: move cursor one page down with selection
-    // - with <Ctrl>+<Shift> modifier keys pressed: scroll one page down
-    {
-      if ( ctrlPressed && shftPressed ) {
-        verticalScrollBar()->triggerAction(QAbstractSlider::SliderPageStepAdd);
-      }
-      else if ( shftPressed || ctrlPressed ) {
-        bool moved = false;
-        qreal lastY = cursorRect( cur ).top();
-        qreal distance = 0;
-        // move using movePosition to keep the cursor's x
-        do {
-          qreal y = cursorRect( cur ).top();
-          distance += qAbs( y - lastY );
-          lastY = y;
-          moved = cur.movePosition( QTextCursor::Down, 
-                                    shftPressed ? QTextCursor::KeepAnchor : 
-                                                  QTextCursor::MoveAnchor );
-        } while ( moved && distance < viewport()->height() );
-        if ( moved ) {
-          cur.movePosition( QTextCursor::Up, 
-                            shftPressed ? QTextCursor::KeepAnchor : 
-                                          QTextCursor::MoveAnchor );
-          verticalScrollBar()->triggerAction( QAbstractSlider::SliderPageStepSub );
-        }
-        setTextCursor( cur );
-      }
-      else { 
-        if ( myCmdInHistory >= 0 ) {
-          // unset history browsing mode
-          myCmdInHistory = -1;
-          // print current command
-          moveCursor( QTextCursor::End );
-          moveCursor( QTextCursor::StartOfBlock, QTextCursor::KeepAnchor );
-          textCursor().removeSelectedText();
-          addText( myPrompt + myCurrentCommand ); 
-          // move cursor to the end
-          moveCursor( QTextCursor::End );
-        }
-      }
-      break;
-    }
-  case Qt::Key_Home: 
-    // <Home> key: process as follows:
-    // - without <Ctrl>, <Shift> modifiers: move cursor to the beginning of the current line without selection
-    // - with <Ctrl> modifier key pressed:  move cursor to the very first symbol without selection
-    // - with <Shift> modifier key pressed: move cursor to the beginning of the current line with selection
-    // - with <Ctrl>+<Shift> modifier keys pressed: move cursor to the very first symbol with selection
-    {
-      if ( ctrlPressed ) { 
-        moveCursor( QTextCursor::Start, 
-                    shftPressed ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor );
-      }
-      else {
-        QString txt = textCursor().block().text();
-        if ( isCommand( txt ) ) {
-          if ( shftPressed ) {
-            if ( curCol > promptSize() ) {
-              cur.movePosition( QTextCursor::StartOfLine, QTextCursor::KeepAnchor );
-              cur.movePosition( QTextCursor::Right, QTextCursor::KeepAnchor, promptSize() );
-            }
-          }
-          else {
-            cur.movePosition( QTextCursor::StartOfLine );
-            cur.movePosition( QTextCursor::Right, QTextCursor::MoveAnchor, promptSize() );
-          }
-          setTextCursor( cur );
-        }
-        else {
-          moveCursor( QTextCursor::StartOfBlock, 
-                      shftPressed ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor );
-        }
-        horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
-      }
-      break;
-    }
-  case Qt::Key_End:
-    // <End> key: process as follows:
-    // - without <Ctrl>, <Shift> modifiers: move cursor to the end of the current line without selection
-    // - with <Ctrl> modifier key pressed:  move cursor to the very last symbol without selection
-    // - with <Shift> modifier key pressed: move cursor to the end of the current line with selection
-    // - with <Ctrl>+<Shift> modifier keys pressed: move cursor to the very last symbol with selection
-    {
-      moveCursor( ctrlPressed ? QTextCursor::End : QTextCursor::EndOfBlock, 
-                  shftPressed ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor );
-      break;
-    }  
-  case Qt::Key_Backspace :
-    // <Backspace> key: process as follows
-    // - without any modifiers : delete symbol before the cursor / selection (taking into account prompt)
-    // - with <Shift> modifier key pressed: delete previous word
-    // - with <Ctrl> modifier key pressed: delete text from the cursor to the line beginning
-    // works only for last (command) line
-    {
-      if ( cur.hasSelection() ) {
-        cut();
-      }
-      else if ( cur.position() > document()->end().previous().position() + promptSize() ) {
-        if ( shftPressed ) {
-          moveCursor( QTextCursor::PreviousWord, QTextCursor::KeepAnchor );
-          textCursor().removeSelectedText();
-        }
-        else if ( ctrlPressed ) {
-          cur.setPosition( document()->end().previous().position() + promptSize(),
-                           QTextCursor::KeepAnchor );
-          setTextCursor( cur );
-          textCursor().removeSelectedText();
-        }
-        else {
-          QTextEdit::keyPressEvent( event );
-        }
-      }
-      else {
-        cur.setPosition( document()->end().previous().position() + promptSize() );
-        setTextCursor( cur );
-        horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
-      }
-      break;
-    }
-  case Qt::Key_Delete :
-    // <Delete> key: process as follows
-    // - without any modifiers : delete symbol after the cursor / selection (taking into account prompt)
-    // - with <Shift> modifier key pressed: delete next word
-    // - with <Ctrl> modifier key pressed: delete text from the cursor to the end of line
-    // works only for last (command) line
-    {
-      if ( cur.hasSelection() ) {
-        cut();
-      }
-      else if ( cur.position() > document()->end().previous().position() + promptSize()-1 ) {
-        if ( shftPressed ) {
-          moveCursor( QTextCursor::NextWord, QTextCursor::KeepAnchor );
-          textCursor().removeSelectedText();
-        }
-        else if ( ctrlPressed ) {
-          moveCursor( QTextCursor::EndOfBlock, QTextCursor::KeepAnchor );
-          textCursor().removeSelectedText();
-        }
-        else {
-          QTextEdit::keyPressEvent( event );
-        }
-      }
-      else {
-        cur.setPosition( document()->end().previous().position() + promptSize() );
-        setTextCursor( cur );
-        horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
-      }
-      break;
-    }
-  case Qt::Key_Insert :
-    // <Insert> key: process as follows
-    // - with <Ctrl> modifier key pressed:  copy()
-    // - with <Shift> modifier key pressed: paste() to the command line
-    {
-      if ( ctrlPressed ) {
-        copy();
-      }
-      else if ( shftPressed ) {
-        paste();
-      }
-      else
-        QTextEdit::keyPressEvent( event );
-      break;
-    }
-  }
-}
-
-/*!
-  \brief Handle notification event coming from Python dispatcher.
-  \param event notification event
-*/
-void PyConsole_EditorBase::customEvent( QEvent* event )
-{
-  switch( event->type() )
-  {
-  case PrintEvent::EVENT_ID:
-    {
-      PrintEvent* pe=(PrintEvent*)event;
-      addText( pe->text(), false, pe->isError());
-      return;
-    }
-  case PyInterp_Event::ES_OK:
-  case PyInterp_Event::ES_ERROR:
-  {
-    // clear command buffer
-    myCommandBuffer.truncate( 0 );
-    // add caret return line if necessary
-    QTextBlock par = document()->end().previous();
-    QString txt = par.text();
-    txt.truncate( txt.length() - 1 );
-    // IPAL19397 : addText moved to handleReturn() method
-    //if ( !txt.isEmpty() )
-    //  addText( "", true );
-    // set "ready" prompt
-    myPrompt = READY_PROMPT;
-    addText( myPrompt );
-    // unset busy cursor
-    unsetCursor();
-    // stop event loop (if running)
-    if ( myEventLoop )
-      myEventLoop->exit();
-    break;
-  }
-  case PyInterp_Event::ES_INCOMPLETE:
-  {
-    // extend command buffer (multi-line command)
-    myCommandBuffer.append( "\n" );
-    // add caret return line if necessary
-    QTextBlock par = document()->end().previous();
-    QString txt = par.text();
-    txt.truncate( txt.length() - 1 );
-    // IPAL19397 : addText moved to handleReturn() method
-    //if ( !txt.isEmpty() )
-    //  addText( "", true );
-    // set "dot" prompt
-    myPrompt = DOTS_PROMPT;
-    addText( myPrompt/*, true*/ ); // IPAL19397
-    // unset busy cursor
-    unsetCursor();
-    // stop event loop (if running)
-    if ( myEventLoop )
-      myEventLoop->exit();
-    break;
-  }
-  default:
-    QTextEdit::customEvent( event );
-  }
-  
-  // unset read-only state
-  setReadOnly( false );
-  // unset history browsing mode
-  myCmdInHistory = -1;
-
-  if ( (int)event->type() == (int)PyInterp_Event::ES_OK && myQueue.count() > 0 )
-  {
-    // process the next sheduled command from the queue (if there is any)
-    QString nextcmd = myQueue[0];
-    myQueue.pop_front();
-    exec( nextcmd );
-  }
-}
-
-/*!
-  \brief Handle Python interpreter change.
-
-  Perform initialization actions if the interpreter is changed.
-  \param interp python interpreter is being set
-*/
-void PyConsole_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()
-{
-  QTextCursor cur = textCursor();
-  if ( cur.hasSelection() ) {
-    QApplication::clipboard()->setText( cur.selectedText() );
-    int startSelection = cur.selectionStart();
-    if ( startSelection < document()->end().previous().position() + promptSize() )
-      startSelection = document()->end().previous().position() + promptSize();
-    int endSelection = cur.selectionEnd();
-    if ( endSelection < document()->end().previous().position() + promptSize() )
-      endSelection = document()->end().previous().position() + promptSize();
-    cur.setPosition( startSelection );
-    cur.setPosition( endSelection, QTextCursor::KeepAnchor );
-    horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
-    setTextCursor( cur );
-    textCursor().removeSelectedText();
-  }
-}
-
-/*!
-  \brief "Paste" operation.
-
-  Reimplemented from Qt.
-  Warning! In Qt4 this method is not virtual.
- */
-void PyConsole_EditorBase::paste()
-{
-  QTextCursor cur = textCursor();
-  if ( cur.hasSelection() ) {
-    int startSelection = cur.selectionStart();
-    if ( startSelection < document()->end().previous().position() + promptSize() )
-      startSelection = document()->end().previous().position() + promptSize();
-    int endSelection = cur.selectionEnd();
-    if ( endSelection < document()->end().previous().position() + promptSize() )
-      endSelection = document()->end().previous().position() + promptSize();
-    cur.setPosition( startSelection );
-    cur.setPosition( endSelection, QTextCursor::KeepAnchor );
-    horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
-    setTextCursor( cur );
-    textCursor().removeSelectedText();
-  }
-  if ( textCursor().position() < document()->end().previous().position() + promptSize() )
-    moveCursor( QTextCursor::End );
-  QTextEdit::paste();
-}
-
-/*!
-  \brief "Clear" operation.
-
-  Reimplemented from Qt.
-  Warning! In Qt4 this method is not virtual.
- */
-void PyConsole_EditorBase::clear()
-{
-  QTextEdit::clear();
-  if ( isShowBanner() )
-    addText( myBanner );
-  myPrompt = READY_PROMPT;
-  addText( myPrompt );
-}
-
-/*!
-  \brief "Dump commands" operation.
- */
-void PyConsole_EditorBase::dumpImpl(const QString& fileName)
-{
-  if ( !fileName.isEmpty() ) {
-    QFile file( fileName ); 
-    if ( !file.open( QFile::WriteOnly ) )
-      return;
-
-    QTextStream out (&file);
-  
-    for ( int i=0; i<myHistory.count(); i++ ) {
-      out << myHistory[i] << endl;
-    }
-    file.close();
-  }
-}
-
-/*!
-  \brief "Dump commands" operation.
- */
-void PyConsole_EditorBase::dump(const QString& fileName)
-{
-  dumpImpl(fileName);
-}
-
-/*!
-  \brief "Dump commands" operation.
- */
-void PyConsole_EditorBase::dump()
-{
-  dumpSlot();
-}
-
-void PyConsole_EditorBase::dumpSlot()
-{
-  QString fileName(QFileDialog::getSaveFileName(this,tr("Choose python file where to store"),QString(),tr("Python scripts ext (*.py)")));
-  if ( !fileName.isEmpty() )
-    this->dump( fileName );
-  else
-    QMessageBox::warning(this,tr("WARNING"),tr("Python file has not been written"));
-}
-
-/*!
-  \brief Start python trace logging
-  \param fileName the path to the log file
-  \sa stopLog()
- */
-bool PyConsole_EditorBase::startLogImpl( const QString& fileName )
-{
-  bool ok = false;
-  if ( !fileName.isEmpty() ) {
-    QFile file( fileName );
-    if ( file.open( QFile::WriteOnly ) ) {
-      file.close();
-      myLogFile = fileName;
-      ok = true;
-    }
-  }
-  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()
-{
-  startLogSlot();
-}
-
-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;
-    }
-}
-
-/*!
-  \brief "Stop log" operation.
-  \sa startLog()
- */
-void PyConsole_EditorBase::stopLog()
-{
-  myLogFile = QString();
-}
-
-/*!
-  \brief Put string to the log file
- */
-void PyConsole_EditorBase::putLog( const QString& s )
-{
-  if ( !myLogFile.isEmpty() ) {
-    QFile file( myLogFile );
-    if ( !file.open( QFile::Append ) )
-      return;
-    
-    QTextStream out (&file);
-    out << s;
-    
-    file.close();
-  }
-}
diff --git a/src/PyConsole/PyConsole_EditorBase.h b/src/PyConsole/PyConsole_EditorBase.h
deleted file mode 100644 (file)
index 78ff8c5..0000000
+++ /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 <QTextEdit>
-
-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 (file)
index b22a7fa..0000000
+++ /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 <Python.h>
-
-#include <QKeyEvent>
-#include <QTextBlock>
-#include <QTextCursor>
-#include <QTextCharFormat>
-#include <QRegExp>
-#include <QMimeData>
-
-#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<QString> PyConsole_EnhEditorBase::SEPARATORS = \
-    std::vector<QString>(tmp_a, tmp_a + sizeof(tmp_a)/sizeof(tmp_a[0]));
-
-/**
- * Constructor.
- * @param interp the interpreter linked to the editor
- * @param parent parent widget
- */
-PyConsole_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 <Ctrl> is pressed
-  bool ctrlPressed = event->modifiers() & Qt::ControlModifier;
-  // check if <Shift> is pressed
-  bool shftPressed = event->modifiers() & Qt::ShiftModifier;
-
-  if (event->key() == Qt::Key_Tab && !shftPressed)
-    {
-      if (!ctrlPressed)
-        handleTab();
-      else
-        {
-          clearCompletion();
-          handleBackTab();
-        }
-      PyConsole_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 <TAB>.
- */
-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 <TAB>
- */
-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<QString>::const_iterator i = SEPARATORS.begin(); i != SEPARATORS.end(); i++)
-    {
-      int j = input2.lastIndexOf(*i);
-      if (j > lastSp)
-        lastSp = j;
-    }
-  if (lastSp >= 0)
-    input2 = input.mid(lastSp+1);
-
-  // Detect a qualified name (with a point)
-  int lastPt = input2.lastIndexOf(QString("."));
-
-  // Split the 2 surrounding parts of the qualified name
-  if (lastPt != -1)
-    {
-      _compl_before_point = input2.left(lastPt);
-      _compl_after_point = input2.mid(lastPt+1);
-    }
-  else
-    {
-      // No point found - do a global matching -
-      // (the following will call dir() with an empty string)
-      _compl_after_point = input2;
-      _compl_before_point = QString("");
-    }
-
-  return new CompletionCommand( 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("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" ") +
-      QString(" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n ") +
-      QString("<html><head><meta name=\"qrichtext\" content=\"1\" /> ") +
-      QString("<style type=\"text/css\">\np, li { white-space: pre-wrap; }\n</style> ") +
-      QString("</head><body style=\" font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;\">\n") +
-      QString("<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">") +
-      QString("<span style=\" font-weight:600; color:#0000ff;\">%1</span></p>") +
-      QString("<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">%2</p>") +
-      QString("</body></html>");
-
-  QString fst, rest("");
-
-  // Extract first line of doc
-  int idx = doc.indexOf("\n");
-  if (idx > 0)
-    {
-      fst = doc.left(idx);
-      rest = doc.mid(idx+1);
-    }
-  else
-    {
-      fst = doc;
-    }
-
-  fst = fst.replace("\n", " ");
-  rest = rest.replace("\n", " ");
-  return templ.arg(fst).arg(rest);
-}
-
-/**
- * Handle properly multi-line pasting. Qt4 doc recommends overriding this function.
- * If the pasted text doesn't contain a line return, no special treatment is done.
- * @param source
- */
-void PyConsole_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<QString>();
-  for (int i = 1; i < lst.size(); ++i)
-    _multi_line_content.push(lst[i]);
-
-  // Trigger the execution of the first (mixed) line
-  handleReturn();
-
-  // See customEvent() and multiLineProcessNext() for the rest of the handling.
-}
-
-/**
- * Process the next line in the queue of a multiple copy/paste:
- */
-void PyConsole_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 <RETURN> 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 (file)
index 67fe5e1..0000000
+++ /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 <QObject>
-#include <queue>
-
-/**
- * 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<QString> SEPARATORS;
-
-  /** Maximum number of completions shown at once */
-  static const int MAX_COMPLETIONS = 70;
-
-  /** Are we in completion mode */
-  bool _tab_mode;
-
-  /** String on which the dir() comamnd is executed */
-  QString _compl_before_point;
-  /** String on which the results of the dir() are matched */
-  QString _compl_after_point;
-
-  /** Cursor position when <TAB> is hit */
-  int _cursor_pos;
-
-  /** Are we currently pasting several lines */
-  bool _multi_line_paste;
-
-  /** Queue of lines being pasted */
-  std::queue<QString> _multi_line_content;
-
-  // Overrides:
-  virtual void   keyPressEvent ( QKeyEvent* event);
-  virtual void   customEvent( QEvent* event);
-  virtual void   mousePressEvent( QMouseEvent* event );
-  virtual void   insertFromMimeData(const QMimeData* source);
-
-  virtual PyInterp_Request* createTabRequest( const QString& input );
-  virtual void handleTab();
-  virtual void handleBackTab();
-  virtual void clearCompletion();
-  virtual void formatCompletion(const 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 (file)
index 91b839c..0000000
+++ /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 <pythonrun.h>
-#include <string>
-#include <QRegExp>
-
-static const char * tmp_k[] = {"and",  "as", "assert", "break",  "class",
-    "continue", "def",  "del",
-    "elif", "else", "except", "exec", "finally",  "for",  "from", "global", "if",
-    "import", "in", "is", "lambda", "not",  "or", "pass", "print",  "raise",
-    "return", "try",  "while",  "with", "yield"};
-
-const std::vector<QString> PyConsole_EnhInterp::PYTHON_KEYWORDS = \
-      std::vector<QString>(tmp_k, tmp_k+sizeof(tmp_k)/sizeof(tmp_k[0]));
-
-/*!
-  \brief 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 <TAB>", this is "rsp".
-  \return command exit status - 0 = success
-*/
-int PyConsole_EnhInterp::runDirCommand(const QString& dirArgument, const QString& startMatch)
-{
-  int ret;
-  std::vector<QString> v;
-
-  clearCompletion();
-  if ( (ret = runDirAndExtract(dirArgument, startMatch, _last_matches)) )
-      return ret;
-
-  // If dirArgument is empty, we append the __builtins__
-  if (dirArgument.isEmpty())
-    {
-      if ( (ret = runDirAndExtract(QString("__builtins__"), startMatch, _last_matches, false)) )
-            return ret;
-
-      // ... and we match on Python's keywords as well:
-      for (std::vector<QString>::const_iterator it = PYTHON_KEYWORDS.begin(); it != PYTHON_KEYWORDS.end(); it++)
-          if ((*it).startsWith(startMatch))
-            _last_matches.push_back(*it);
-    }
-
-  // Try to get doc string of the first match
-  if (_last_matches.size() > 0)
-    {
-      QString cmd("");
-      if (dirArgument.trimmed() != "")
-        cmd = dirArgument + ".";
-      cmd += _last_matches[0] + ".__doc__";
-      PyObject * str = PyRun_String(cmd.toStdString().c_str(), Py_eval_input, _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 (file)
index 3fe66fd..0000000
+++ /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 <Python.h>
-#include "PyConsole_Interp.h"
-
-#include <vector>
-#include <QString>
-
-/**
- * Enhanced Python interpreter used for auto-completion.
- * This extends PyConsole_Interp with an API wrapping the Python dir() command nicely.
- */
-class PYCONSOLE_EXPORT PyConsole_EnhInterp: public PyConsole_Interp
-{
-public:
-  PyConsole_EnhInterp();
-  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<QString> 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_ */
index 382b39a06fa9de5d274b63a377283bd9e1522787..5c3f1fdf9581b32b53591504752f812240ef3aba 100644 (file)
 //
 // 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;
+}
index 4f9a7fe8d82fd9302df99ade2f357377463966d9..d22b78b1a41607fd51274ea57ab037edb25419d5 100644 (file)
 //
 // 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 <QEvent>
 #include <QString>
+#include <QStringList>
 
-/*!
-  \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
index 7d52bbee5c49087829f92b44c1e5ccb9da23d3c9..7224136868f91715b3d7d3edaecb490bcda37005 100644 (file)
@@ -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.
 */
 
 /*!
 
   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 <TAB>", 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;
 }
index 14c8404a3847f1d66220154281ef0570ab7d8704..4275c350f6aa590fad518deb6551ec4ea5414ba1 100644 (file)
 //
 // 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 <QStringList>
 
 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
index e28a05e147fb53da1ab6f1ce48a9ca7c6e753a2d..aa41c259ec1753d09ab02aea575a24e88b28877c 100644 (file)
 //
 // 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 <QCoreApplication>
 
-/**
- * Constructor.
- * @param theInterp interpreter that will execute the command
- * @param theCommand command text
- * @param theListener editor object that will receive the response events after execution
- * of the request
- * @param sync
- */
-ExecCommand::ExecCommand( PyInterp_Interp*        theInterp,
-                         const QString&          theCommand,
-                         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<PyConsole_Interp*>(getInterp())->runDirCommand( _dirArg,  _startMatch );
-  _tabSuccess = ret == 0;
+  myStatus = static_cast<PyConsole_Interp*>( 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 );
 }
index 93ba66226697321154a80c8160410b07cf4c6194..827823b60adcd8f3f09c8aeeb3ac1046402ecff8 100644 (file)
 //
 // 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 <vector>
 #include <QString>
-#include <QEvent>
+#include <QStringList>
 
+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<QString> SEPARATORS;
-
-  /** String to be passed to the dir() command */
-  QString _dirArg;
-  /** Begining of the command (as typed by the user) */
-  QString _startMatch;
-  /** was the completion command successful */
-  bool _tabSuccess;
-
   virtual void execute();
   virtual QEvent* createEvent();
+
+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
index 1586df26661b154b961a4d85cb2d443a6c3b68b0..7fac57c1dc6c565b4ca364f4485766e45da3ff1a 100644 (file)
@@ -2,24 +2,24 @@
 <!DOCTYPE TS>
 <TS version="2.0" language="en_US">
 <context>
-    <name>PyConsole_ConsoleBase</name>
+    <name>PyConsole_Console</name>
     <message>
-        <location filename="../PyConsole_ConsoleBase.cxx" line="216"/>
+        <location filename="../PyConsole_Console.cxx" line="216"/>
         <source>EDIT_COPY_CMD</source>
         <translation>&amp;Copy</translation>
     </message>
     <message>
-        <location filename="../PyConsole_ConsoleBase.cxx" line="221"/>
+        <location filename="../PyConsole_Console.cxx" line="221"/>
         <source>EDIT_PASTE_CMD</source>
         <translation>&amp;Paste</translation>
     </message>
     <message>
-        <location filename="../PyConsole_ConsoleBase.cxx" line="226"/>
+        <location filename="../PyConsole_Console.cxx" line="226"/>
         <source>EDIT_CLEAR_CMD</source>
         <translation>Clea&amp;r</translation>
     </message>
     <message>
-        <location filename="../PyConsole_ConsoleBase.cxx" line="231"/>
+        <location filename="../PyConsole_Console.cxx" line="231"/>
         <source>EDIT_SELECTALL_CMD</source>
         <translation>Select &amp;All</translation>
     </message>
@@ -28,7 +28,7 @@
         <translation>D&amp;ump Commands</translation>
     </message>
     <message>
-      <source>EDIT_STARTLOG_CMD</source>
+        <source>EDIT_STARTLOG_CMD</source>
         <translation>Start &amp;Log</translation>
     </message>
     <message>
     </message>
 </context>
 <context>
-    <name>PyConsole_EditorBase</name>
+    <name>PyConsole_Editor</name>
     <message>
-        <source>Choose python file where to store</source>
-        <translation>Choose python file where to store dump</translation>
+        <source>GET_DUMP_COMMANDS_FILENAME</source>
+        <translation>Dump commands to file</translation>
     </message>
     <message>
-        <source>Python scripts ext (*.py)</source>
-        <translation>Python scripts (*.py)</translation>
+        <source>GET_PYTHON_TRACE_FILENAME</source>
+        <translation>Save Python trace to file</translation>
+    </message>
+    <message>
+        <source>PYTHON_SCRIPTS</source>
+        <translation>Python scripts</translation>
     </message>
     <message>
         <source>WARNING</source>
-        <translation>WARNING !</translation>
+        <translation>Warning!</translation>
     </message>
     <message>
-        <source>Python file has not been written</source>
-        <translation>Python file has not been written !</translation>
+        <source>LOG_FILES</source>
+        <translation>Log files</translation>
     </message>
     <message>
-        <source>Choose python file where to store log</source>
-        <translation>Choose python file where to store log</translation>
+        <source>ERR_FILE_NOT_WRITEABLE</source>
+        <translation>File is not writeable!</translation>
     </message>
     <message>
-        <source>Log files ext (*.log *.txt)</source>
-        <translation>Log files extension (*.log *.txt)</translation>
+        <source>TOO_MANY_MATCHES</source>
+        <translation>Too many matches! Displaying first ones only...</translation>
     </message>
     <message>
-        <source>Log file is not writable</source>
-        <translation>Log file is not writable !</translation>
+        <source>NO_DOC_AVAILABLE</source>
+        <translation>no documentation available</translation>
     </message>
 </context>
 </TS>
index ff40a32c501a8b5ec762b1b9089b65bf0d976d1f..9eaf24482202a5bc515e895b63f9dc2cd2501eec 100644 (file)
@@ -2,24 +2,24 @@
 <!DOCTYPE TS>
 <TS version="2.0" language="fr_FR">
 <context>
-    <name>PyConsole_ConsoleBase</name>
+    <name>PyConsole_Console</name>
     <message>
-        <location filename="../PyConsole_ConsoleBase.cxx" line="216"/>
+        <location filename="../PyConsole_Console.cxx" line="216"/>
         <source>EDIT_COPY_CMD</source>
         <translation>&amp;Copier</translation>
     </message>
     <message>
-        <location filename="../PyConsole_ConsoleBase.cxx" line="221"/>
+        <location filename="../PyConsole_Console.cxx" line="221"/>
         <source>EDIT_PASTE_CMD</source>
         <translation>C&amp;oller</translation>
     </message>
     <message>
-        <location filename="../PyConsole_ConsoleBase.cxx" line="226"/>
+        <location filename="../PyConsole_Console.cxx" line="226"/>
         <source>EDIT_CLEAR_CMD</source>
         <translation>&amp;Effacer</translation>
     </message>
     <message>
-        <location filename="../PyConsole_ConsoleBase.cxx" line="231"/>
+        <location filename="../PyConsole_Console.cxx" line="231"/>
         <source>EDIT_SELECTALL_CMD</source>
         <translation>&amp;Tout sélectionner</translation>
     </message>
     </message>
 </context>
 <context>
-    <name>PyConsole_EditorBase</name>
+    <name>PyConsole_Editor</name>
     <message>
-        <source>Choose python file where to store</source>
+        <source>GET_DUMP_COMMANDS_FILENAME</source>
         <translation>Choisissez un fichier python où sauver le dump</translation>
     </message>
     <message>
-        <source>Python scripts ext (*.py)</source>
-        <translation>Scripts Python (*.py)</translation>
+        <source>GET_PYTHON_TRACE_FILENAME</source>
+        <translation>Choisissez un fichier où sauver le log</translation>
+    </message>
+    <message>
+        <source>PYTHON_SCRIPTS</source>
+        <translation>Scripts Python</translation>
     </message>
     <message>
         <source>WARNING</source>
         <translation>Attention !</translation>
     </message>
     <message>
-        <source>Python file has not been written</source>
-        <translation>Le fichier Python n'a pas été écrit !</translation>
+        <source>LOG_FILES</source>
+        <translation>Fichiers log</translation>
     </message>
     <message>
-        <source>Choose python file where to store log</source>
-        <translation>Choisissez un fichier python où sauver le log</translation>
+        <source>ERR_FILE_NOT_WRITEABLE</source>
+        <translation>Le fichier n'a pas été écrit !</translation>
     </message>
     <message>
-        <source>Log files ext (*.log *.txt)</source>
-        <translation>Extensions possible des fichiers log (*.log *.txt)</translation>
+        <source>TOO_MANY_MATCHES</source>
+        <translation type="unfinished">Too many matches! Displaying first ones only...</translation>
     </message>
     <message>
-        <source>Log file is not writable</source>
-        <translation>Le fichier log sélectionné n'est pas writable !</translation>
+        <source>NO_DOC_AVAILABLE</source>
+        <translation type="unfinished">no documentation available</translation>
     </message>
 </context>
 </TS>
index ca1aacee3267c0e236ac7b72e97769967051b9e5..8861d5ed5f30ccdd67b3efa27dcc1673aae58755 100644 (file)
@@ -2,24 +2,24 @@
 <!DOCTYPE TS>
 <TS version="2.0" language="ja" sourcelanguage="en">
   <context>
-    <name>PyConsole_ConsoleBase</name>
+    <name>PyConsole_Console</name>
     <message>
-      <location filename="../PyConsole_ConsoleBase.cxx" line="216"/>
+      <location filename="../PyConsole_Console.cxx" line="216"/>
       <source>EDIT_COPY_CMD</source>
       <translation>コピー(&amp;C)</translation>
     </message>
     <message>
-      <location filename="../PyConsole_ConsoleBase.cxx" line="221"/>
+      <location filename="../PyConsole_Console.cxx" line="221"/>
       <source>EDIT_PASTE_CMD</source>
       <translation>貼り付け(&amp;P)</translation>
     </message>
     <message>
-      <location filename="../PyConsole_ConsoleBase.cxx" line="226"/>
+      <location filename="../PyConsole_Console.cxx" line="226"/>
       <source>EDIT_CLEAR_CMD</source>
       <translation>削除(&amp;r)</translation>
     </message>
     <message>
-      <location filename="../PyConsole_ConsoleBase.cxx" line="231"/>
+      <location filename="../PyConsole_Console.cxx" line="231"/>
       <source>EDIT_SELECTALL_CMD</source>
       <translation>すべて選択します。(&amp;A)</translation>
     </message>
     </message>
   </context>
   <context>
-    <name>PyConsole_EditorBase</name>
+    <name>PyConsole_Editor</name>
     <message>
-        <source>Choose python file where to store</source>
-        <translation>Choose python file where to store dump</translation>
+      <source>GET_DUMP_COMMANDS_FILENAME</source>
+      <translation type="unfinished">Dump commands to file</translation>
     </message>
     <message>
-        <source>Python scripts ext (*.py)</source>
-        <translation>Python scripts (*.py)</translation>
+      <source>GET_PYTHON_TRACE_FILENAME</source>
+      <translation type="unfinished">Save Python trace to file</translation>
     </message>
     <message>
-        <source>WARNING</source>
-        <translation>WARNING !</translation>
+      <source>PYTHON_SCRIPTS</source>
+      <translation type="unfinished">Python scripts</translation>
     </message>
     <message>
-        <source>Python file has not been written</source>
-        <translation>Python file has not been written !</translation>
+      <source>WARNING</source>
+      <translation type="unfinished">Warning!</translation>
     </message>
     <message>
-        <source>Choose python file where to store log</source>
-        <translation>Choose python file where to store log</translation>
+      <source>LOG_FILES</source>
+      <translation type="unfinished">Log files</translation>
     </message>
     <message>
-        <source>Log files ext (*.log *.txt)</source>
-        <translation>Log files extension (*.log *.txt)</translation>
+      <source>ERR_FILE_NOT_WRITEABLE</source>
+      <translation type="unfinished">File is not writeable!</translation>
     </message>
     <message>
-        <source>Log file is not writable</source>
-        <translation>Log file is not writable !</translation>
+      <source>TOO_MANY_MATCHES</source>
+      <translation type="unfinished">Too many matches! Displaying first ones only...</translation>
     </message>
-</context>
+    <message>
+      <source>NO_DOC_AVAILABLE</source>
+      <translation type="unfinished">no documentation available</translation>
+    </message>
+  </context>
 </TS>
index dd4c3c23e305885f2dd4cacc1b90ce87386b0d63..987380dac8d9457b5126b735c5f38ac1f7b121ff 100755 (executable)
@@ -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
index 965e8127310e6ce87df392d02a20abf637f01294..1ac25a1bb956f163903fbd609952aa1856df3e35 100755 (executable)
 //
 // 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
 
index 6728155bace77784acf8c2249984f6781265c26e..b70214481012c17303c8cf20ceaf6e251a83042b 100755 (executable)
 //
 // 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 <QObject>
-#include <QCoreApplication>
+/**
+   \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();
index c3c22d73ea75d70479aa4615db9fad34e8dec976..c9b83847a628662d7e41a03d235cf85765417202 100755 (executable)
 //
 // 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
 
 #include <QThread>
 #include <QQueue>
 
-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<RequestPtr>          myQueue;
   QMutex                      myQueueMutex;
-  PyInterp_Watcher*           myWatcher;
 
   static PyInterp_Dispatcher* myInstance;
-
-  friend class PyInterp_Watcher;
 };
 
 #endif // PYINTERP_DISPATCHER_H
index f0f81bae6b3760d479bfc4e8940890892927cd6a..478eb2c36b538b8b1f342f8c53af156493777859 100644 (file)
 //
 // 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;
 }
index 25a841ad0de526a52a32fd1b3939e822732c3755..e812adbe1b0a2eb4a612a3f08fffefed91b14992 100644 (file)
 //
 // 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 <SALOME_Event.h>
-
 #include <QEvent>
 
 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;
index eba98d507549f7ee3f011b754c939dea2441f695..5946e8d7f65c74ee48e5ee29acf717ca49553d1a 100644 (file)
 //
 // 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 <pythread.h>
 
+#include <pythread.h>
 #include <cStringIO.h>
 #include <structmember.h>
-
 #include <string>
 #include <vector>
 #include <map>
@@ -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, "<salome_input>", 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;
+}
index c545d8cd15280218fac9d4aa3c9cd46ec7c04ba0..88e5519166450fe10e93ed39061f5a36636343bb 100644 (file)
 //
 // 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<std::string> _history;
   std::list<std::string>::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
index 0efbda1185666dc3f47a50c6bfea777337530e22..f8227f09cde7c150b9b22fe381784272876a96e6 100644 (file)
 // 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 <QCoreApplication>
 
 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();
 }
index 0ac90d55269084e8df61891d3a6953fbf771ab6b..cabb3d6b01493937787fca709892d8e69e3b460a 100644 (file)
@@ -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
 #include "PyInterp_Event.h"
 
 #include <QMutex>
-#include <QObject>
 
+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:
index f6f67b29d4b83e0f50ff413ecfe5e151726a04d4..8d6ce8c638acbc9b7dec862399d32a1e9b860aad 100644 (file)
 //
 // 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 <Python.h>
+
 #ifdef _DEBUG_
   #include <iostream>
 #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 (executable)
index 8ae8618..0000000
+++ /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 <QObject>
-
-// Private class that keeps track of destructions of request listeners
-class PYINTERP_EXPORT PyInterp_Watcher : public QObject
-{                                           
-  Q_OBJECT
-
-public:
-  PyInterp_Watcher() : QObject( 0 ) {}
-  virtual ~PyInterp_Watcher() {}
-
-public slots:
-  void onDestroyed( QObject* o ) { PyInterp_Dispatcher::Get()->objectDestroyed( o ); }
-};
-
-#endif // PYINTERP_WATCHER_H
index f12e57d83bdb406f939052d933009895da3a93ba..c8c88d5b5c2efa4ab7f249810a6a444226a92976 100755 (executable)
@@ -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
index 9cb8b540b758d86bfcbd66cbc29cbab67e1409c3..10dc383804e197bbd51f25ecbde1ebfa118eff2a 100644 (file)
@@ -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 <QAction>
 #include <QApplication>
@@ -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();
       }
     }
index 4423d8d7d9b5ae9a58c186ef3de6e2529db6d232..8296bfccac5f8d98203e800465b45f8eaea323d2 100755 (executable)
@@ -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)
index 32f9e37fba2aafea5b450658e7550d4c30d82812..eaec2acdeb3e7d91c20c81c446b34dbed6c7e80f 100644 (file)
 #endif
 
 #ifndef DISABLE_PYCONSOLE
-  #include "SalomeApp_PyInterp.h" // WARNING! This include must be the first!
-  #include <SalomePyConsole_Console.h>
+  #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 <LightApp_Application.h>
+#include <LightApp_FileValidator.h>
 #include <LightApp_Module.h>
 #include <LightApp_Preferences.h>
 #include <LightApp_SelectionMgr.h>
@@ -62,7 +64,6 @@
 #include <SUIT_Desktop.h>
 #include <SUIT_DataBrowser.h>
 #include <SUIT_FileDlg.h>
-#include <SUIT_FileValidator.h>
 #include <SUIT_MessageBox.h>
 #include <SUIT_ResourceMgr.h>
 #include <SUIT_TreeModel.h>
@@ -253,7 +254,7 @@ void SalomeApp_Application::start()
     // import/execute python scripts
     if ( pyfiles.count() > 0 && activeStudy() ) {
       SalomeApp_Study* appStudy = dynamic_cast<SalomeApp_Study*>( 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
index 7d3c79c991f07414be80dc6853a8e92edbf5e89b..749ce3798668a83ef6875d19cd658b77da672908 100644 (file)
@@ -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<SalomeApp_Application*>( 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<SalomeApp_Application*>( 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 ; ";
index f27a0d2c47e062ba932fa12b4a5df444278736f5..e79c8361320ee59144b9e24e8b788871890e92c7 100755 (executable)
 //
 // 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 <utilities.h>
-#include <Container_init_python.hxx>
-
-#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;
index c1e8773e14a181ac5c7fd9a6b3f8e4832ee31ef2..567b25235af1736ec1c25c16a1837cbe3adb6524 100755 (executable)
 //
 // 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 <PyConsole_EnhInterp.h> // this include must be first (see PyInterp_base.h)!
+#include <PyConsole_Interp.h>
 
-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
index 59eb414fa79a145e316170f492c6b7aa9efd4567..58fb8acedeb01f3203b83f1eb74a87827c125942 100644 (file)
@@ -3,11 +3,6 @@
 <TS version="2.0" language="en_US">
 <context>
     <name>@default</name>
-    <message>
-        <source>WRN_FILE_NAME_BAD</source>
-        <translation>Please enter correct file name.
-Python file must include only letters, digits and underscores and start from letter or underscore.</translation>
-    </message>
     <message>
         <source>WRN_FILE_NOT_EXIST</source>
         <translation>The file %1 does not exist.</translation>
@@ -246,10 +241,6 @@ Do you want to reload it ?</translation>
         <source>PRP_DESK_REGISTRY_DISPLAY</source>
         <translation>Displays content of the Registry CORBA server</translation>
     </message>
-    <message>
-        <source>PYTHON_FILES_FILTER</source>
-        <translation>PYTHON Files (*.py)</translation>
-    </message>
     <message>
         <source>APPCLOSE_DESCRIPTION</source>
         <translation>Do you want to save study before closing?</translation>
index c25adc908a97843a987d61e0bdaaa25ea417b2ac..5709c9727c75adfc75adf614a05e8fe35a1f7d5f 100755 (executable)
@@ -3,11 +3,6 @@
 <TS version="2.0" language="fr_FR">
 <context>
     <name>@default</name>
-    <message>
-        <source>WRN_FILE_NAME_BAD</source>
-        <translation>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.</translation>
-    </message>
     <message>
         <source>WRN_FILE_NOT_EXIST</source>
         <translation>Le fichier %1 n&apos;existe pas.</translation>
@@ -246,10 +241,6 @@ Voulez-vous le recharger ?</translation>
         <source>PRP_DESK_REGISTRY_DISPLAY</source>
         <translation>Visualiser le contenu du registre du serveur CORBA</translation>
     </message>
-    <message>
-        <source>PYTHON_FILES_FILTER</source>
-        <translation>Fichiers PYTHON (*.py)</translation>
-    </message>
     <message>
         <source>APPCLOSE_DESCRIPTION</source>
         <translation>Voulez-vous fermer ou décharger l&apos;étude avant de la fermer ?</translation>
index fe8c7708f9ed7433f2809a119d33b6bcc0bd77eb..1d9a98edb8b613b61d1a692509929afcc8e1ba78 100644 (file)
@@ -3,10 +3,6 @@
 <TS version="2.0" language="ja" sourcelanguage="en">
   <context>
     <name>@default</name>
-    <message>
-      <source>WRN_FILE_NAME_BAD</source>
-      <translation>有効なファイル名を入力してください。Pythonのファイル名は、文字、数字、およびアンダー スコアで構成され、文字かアンダー スコアで始まる必要があります。</translation>
-    </message>
     <message>
       <source>WRN_FILE_NOT_EXIST</source>
       <translation>ファイル %1 は存在しません。</translation>
       <source>PRP_DESK_REGISTRY_DISPLAY</source>
       <translation>CORBAサーバーの登録内容を表示</translation>
     </message>
-    <message>
-      <source>PYTHON_FILES_FILTER</source>
-      <translation>ファイル (*.py) PYTHON</translation>
-    </message>
     <message>
       <source>APPCLOSE_DESCRIPTION</source>
       <translation>閉じる、または閉じる前にスタディをアンロードしますか?</translation>
diff --git a/src/SalomePyConsole/CMakeLists.txt b/src/SalomePyConsole/CMakeLists.txt
deleted file mode 100755 (executable)
index 25e3c49..0000000
+++ /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 (file)
index fba1243..0000000
+++ /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 (file)
index 163e29c..0000000
+++ /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 <Qtx.h>
-
-#include <QAction>
-#include <QApplication>
-#include <QClipboard>
-#include <QEvent>
-#include <QMenu>
-#include <QVBoxLayout>
-
-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 (file)
index d797c42..0000000
+++ /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 <PyConsole_ConsoleBase.h>
-#include <SUIT_PopupClient.h>
-#include <QWidget>
-#include <QMap>
-
-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 (file)
index f55eb7a..0000000
+++ /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:
-  - <Enter>              : execute current command
-  - <Ctrl><Break>        : clear current command
-  - <Escape>             : clear current command
-  - <Up>                 : previous command in the history
-  - <Shift><Up>          : move cursor one row up with selection
-  - <Ctrl><Up>           : move cursor one row up without selection
-  - <Ctrl><Shift><Up>    : move cursor one row up with selection
-  - <Down>               : next command in the history
-  - <Shift><Down>        : move cursor one row down with selection
-  - <Ctrl><Down>         : move cursor one row down without selection
-  - <Ctrl><Shift><Down>  : move cursor one row down with selection
-  - <Left>               : move one symbol left without selection
-  - <Shift><Left>        : move one symbol left with selection
-  - <Ctrl><Left>         : move one word left without selection
-  - <Ctrl><Shift><Left>  : move one word left with selection
-  - <Right>              : move one symbol right without selection
-  - <Shift><Right>       : move one symbol right with selection
-  - <Ctrl><Right>        : move one word right without selection
-  - <Ctrl><Shift><Right> : move one word right with selection
-  - <PgUp>               : first command in the history
-  - <Shift><PgUp>        : move one page up with selection
-  - <Ctrl><PgUp>         : move one page up without selection
-  - <Ctrl><Shift><PgUp>  : scroll one page up
-  - <PgDn>               : last command in the history
-  - <Shift><PgDn>        : move one page down with selection
-  - <Ctrl><PgDn>         : move one page down without selection
-  - <Ctrl><Shift><PgDn>  : scroll one page down
-  - <Home>               : move to the beginning of the line without selection
-  - <Shift><Home>        : move to the beginning of the line with selection
-  - <Ctrl><Home>         : move to the very first symbol without selection
-  - <Ctrl><Shift><Home>  : move to the very first symbol with selection
-  - <End>                : move to the end of the line without selection
-  - <Shift><End>         : move to the end of the line with selection
-  - <Ctrl><End>          : move to the very last symbol without selection
-  - <Ctrl><Shift><End>   : move to the very last symbol with selection
-  - <Backspace>          : delete symbol before the cursor
-                           / remove selected text and put it to the clipboard (cut)
-  - <Shift><Backspace>   : delete previous word
-                           / remove selected text and put it to the clipboard (cut)
-  - <Ctrl><Backspace>    : delete text from the cursor to the beginning of the line 
-                           / remove selected text and put it to the clipboard (cut)
-  - <Delete>             : delete symbol after the cursor 
-                           / remove selected text and put it to the clipboard (cut)
-  - <Shift><Delete>      : delete next word
-                           / remove selected text and put it to the clipboard (cut)
-  - <Ctrl><Delete>       : delete text from the cursor to the end of the line
-                           / remove selected text and put it to the clipboard (cut)
-  - <Ctrl><Insert>       : copy
-  - <Shift><Insert>      : paste
-  - <Ctrl><V>            : paste
-  - <Ctrl><C>            : copy
-  - <Ctrl><X>            : cut
-  - <Ctrl><V>            : paste
-*/
-
-#include "PyConsole_Interp.h"   // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!!
-#include "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 <QApplication>
-#include <QClipboard>
-#include <QDropEvent>
-#include <QEvent>
-#include <QKeyEvent>
-#include <QMouseEvent>
-#include <QScrollBar>
-#include <QTextBlock>
-#include <QTextCursor>
-#include <QTextDocument>
-#include <QTextStream>
-#include <QChar>
-#include <QFileInfo>
-
-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 (file)
index 9d38de0..0000000
+++ /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 <QTextEdit>
-
-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 (file)
index be02e7c..0000000
+++ /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 <Python.h>
-
-#include <QKeyEvent>
-#include <QTextBlock>
-#include <QTextCursor>
-#include <QTextCharFormat>
-#include <QRegExp>
-#include <QMimeData>
-
-#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/SalomePyConsole_EnhEditor.h b/src/SalomePyConsole/SalomePyConsole_EnhEditor.h
deleted file mode 100644 (file)
index af4b8f0..0000000
+++ /dev/null
@@ -1,45 +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 SALOMEPYCONSOLE_ENHEDITOR_H_
-#define SALOMEPYCONSOLE_ENHEDITOR_H_
-
-#include "SalomePyConsole.h"
-#include "PyConsole_EnhEditorBase.h"
-
-#include <QObject>
-#include <queue>
-
-/**
- * Enhanced Python editor handling tab completion.
- */
-class PYCONSOLE_EXPORT SalomePyConsole_EnhEditor : public PyConsole_EnhEditorBase
-{
-  Q_OBJECT;
-public:
-  SalomePyConsole_EnhEditor(PyConsole_Interp* interp, QWidget* parent = 0);
-  virtual ~SalomePyConsole_EnhEditor() {}
-protected:
-  virtual void dumpSlot();
-  virtual void startLogSlot();
-};
-
-#endif /* PYCONSOLE_ENHEDITOR_H_ */
diff --git a/src/SalomePyConsole/resources/SalomePyConsole_msg_en.ts b/src/SalomePyConsole/resources/SalomePyConsole_msg_en.ts
deleted file mode 100644 (file)
index 7fcc5bc..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE TS>
-<TS version="2.0" language="en_US">
-<context>
-    <name>SalomePyConsole_Editor</name>
-    <message>
-        <source>TOT_DUMP_PYCOMMANDS</source>
-        <translation>Dump commands</translation>
-    </message>
-    <message>
-        <source>TOT_SAVE_PYLOG</source>
-        <translation>Save log</translation>
-    </message>
-    <message>
-        <source>PYTHON_FILES_FILTER</source>
-        <translation>PYTHON Files (*.py)</translation>
-    </message>
-    <message>
-        <source>LOG_FILES_FILTER</source>
-        <translation>Log files (*.log *.txt)</translation>
-    </message>
-    <message>
-        <source>ERR_FILE_NOT_WRITABLE</source>
-        <translation>File is not writable!</translation>
-    </message>
-</context>
-</TS>
diff --git a/src/SalomePyConsole/resources/SalomePyConsole_msg_fr.ts b/src/SalomePyConsole/resources/SalomePyConsole_msg_fr.ts
deleted file mode 100644 (file)
index 3626118..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE TS>
-<TS version="2.0" language="fr_FR">
-<context>
-    <name>SalomePyConsole_Editor</name>
-    <message>
-        <source>TOT_DUMP_PYCOMMANDS</source>
-        <translation>&amp;Générer le script des commandes</translation>
-    </message>
-    <message>
-        <source>TOT_SAVE_PYLOG</source>
-        <translation>Sauver la trace</translation>
-    </message>
-    <message>
-        <source>PYTHON_FILES_FILTER</source>
-        <translation>Fichiers PYTHON (*.py)</translation>
-    </message>
-    <message>
-        <source>LOG_FILES_FILTER</source>
-        <translation>Fichiers de trace (*.log *.txt)</translation>
-    </message>
-    <message>
-        <source>ERR_FILE_NOT_WRITABLE</source>
-        <translation>Le fichier n'est pas accessible en écriture!</translation>
-    </message>
-</context>
-</TS>
diff --git a/src/SalomePyConsole/resources/SalomePyConsole_msg_ja.ts b/src/SalomePyConsole/resources/SalomePyConsole_msg_ja.ts
deleted file mode 100644 (file)
index 3f579c6..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE TS>
-<TS version="2.0" language="ja" sourcelanguage="en">
-  <context>
-    <name>SalomePyConsole_Editor</name>
-    <message>
-      <source>TOT_DUMP_PYCOMMANDS</source>
-      <translation>スクリプト コマンドを生成します。</translation>
-    </message>
-    <message>
-      <source>TOT_SAVE_PYLOG</source>
-      <translation>ログの保存</translation>
-    </message>
-    <message>
-      <source>PYTHON_FILES_FILTER</source>
-      <translation>ファイル (*.py) PYTHON</translation>
-    </message>
-    <message>
-      <source>LOG_FILES_FILTER</source>
-      <translation>ログファイル (*.log *.txt)</translation>
-    </message>
-    <message>
-      <source>ERR_FILE_NOT_WRITABLE</source>
-      <translation>ファイルが書き込み禁止です!</translation>
-    </message>
-  </context>
-</TS>