]> SALOME platform Git repositories - modules/gui.git/commitdiff
Salome HOME
Step 3
authorAnthony Geay <anthony.geay@edf.fr>
Mon, 22 Feb 2016 17:08:14 +0000 (18:08 +0100)
committerAnthony Geay <anthony.geay@edf.fr>
Mon, 22 Feb 2016 17:08:14 +0000 (18:08 +0100)
54 files changed:
CMakeLists.txt
SalomeGUIConfig.cmake.in
src/CMakeLists.txt
src/LightApp/CMakeLists.txt
src/PyConsole/CMakeLists.txt
src/PyConsole/PyConsole_Console.cxx
src/PyConsole/PyConsole_ConsoleBase.cxx [deleted file]
src/PyConsole/PyConsole_ConsoleBase.h [deleted file]
src/PyConsole/PyConsole_Editor.cxx
src/PyConsole/PyConsole_Editor.h
src/PyConsole/PyConsole_EnhEditor.cxx
src/PyConsole/PyConsole_EnhEditor.h
src/PyConsole/PyConsole_EnhInterp.cxx [deleted file]
src/PyConsole/PyConsole_EnhInterp.h [deleted file]
src/PyConsole/PyConsole_Event.cxx [deleted file]
src/PyConsole/PyConsole_Event.h [deleted file]
src/PyConsole/PyConsole_Interp.cxx [deleted file]
src/PyConsole/PyConsole_Interp.h [deleted file]
src/PyConsole/PyConsole_Request.cxx [deleted file]
src/PyConsole/PyConsole_Request.h [deleted file]
src/PyConsole/resources/PyConsole_msg_en.ts [deleted file]
src/PyConsole/resources/PyConsole_msg_fr.ts [deleted file]
src/PyConsole/resources/PyConsole_msg_ja.ts [deleted file]
src/PyConsoleBase/CMakeLists.txt [new file with mode: 0755]
src/PyConsoleBase/PyConsoleBase.h [new file with mode: 0644]
src/PyConsoleBase/PyConsole_ConsoleBase.cxx [new file with mode: 0644]
src/PyConsoleBase/PyConsole_ConsoleBase.h [new file with mode: 0644]
src/PyConsoleBase/PyConsole_EditorBase.cxx [new file with mode: 0644]
src/PyConsoleBase/PyConsole_EditorBase.h [new file with mode: 0644]
src/PyConsoleBase/PyConsole_EnhEditorBase.cxx [new file with mode: 0644]
src/PyConsoleBase/PyConsole_EnhEditorBase.h [new file with mode: 0644]
src/PyConsoleBase/PyConsole_EnhInterp.cxx [new file with mode: 0644]
src/PyConsoleBase/PyConsole_EnhInterp.h [new file with mode: 0644]
src/PyConsoleBase/PyConsole_Event.cxx [new file with mode: 0644]
src/PyConsoleBase/PyConsole_Event.h [new file with mode: 0644]
src/PyConsoleBase/PyConsole_Interp.cxx [new file with mode: 0644]
src/PyConsoleBase/PyConsole_Interp.h [new file with mode: 0644]
src/PyConsoleBase/PyConsole_Request.cxx [new file with mode: 0644]
src/PyConsoleBase/PyConsole_Request.h [new file with mode: 0644]
src/PyConsoleBase/resources/PyConsole_msg_en.ts [new file with mode: 0644]
src/PyConsoleBase/resources/PyConsole_msg_fr.ts [new file with mode: 0755]
src/PyConsoleBase/resources/PyConsole_msg_ja.ts [new file with mode: 0644]
src/SALOME_PYQT/SalomePyQt/CMakeLists.txt
src/SUITT/CMakeLists.txt [new file with mode: 0644]
src/SUITT/Qtxx.cxx [new file with mode: 0755]
src/SUITT/Qtxx.h [new file with mode: 0755]
src/SUITT/SUIT.h [new file with mode: 0755]
src/SUITT/SUIT_FileValidator.cxx [new file with mode: 0755]
src/SUITT/SUIT_FileValidator.h [new file with mode: 0755]
src/SUITT/SUIT_MessageBox.cxx [new file with mode: 0755]
src/SUITT/SUIT_MessageBox.h [new file with mode: 0755]
src/SUITT/SUIT_OverrideCursor.cxx [new file with mode: 0755]
src/SUITT/SUIT_OverrideCursor.h [new file with mode: 0755]
src/SalomeApp/CMakeLists.txt

index 16a00d96bd0ce8f90fea402abbd031669ba23484..251f606458ccddc22148864ed1278eb4c5c182db 100755 (executable)
@@ -310,7 +310,7 @@ INCLUDE(CMakePackageConfigHelpers)
 # They all have to be INSTALL'd with the option "EXPORT ${PROJECT_NAME}TargetGroup"
 SET(_${PROJECT_NAME}_exposed_targets 
     caf CAM CASCatch DDS Event LightApp LogWindow ObjBrowser
-    QDS qtx SalomePrs SalomeStyle std SUITApp suit ViewerTools ViewerData
+    QDS qtx suitt SalomePrs SalomeStyle std SUITApp suit ViewerTools ViewerData
     ImageComposer
 )
 
@@ -387,7 +387,7 @@ ENDIF()
 # Python-based packages specific targets:
 IF(SALOME_USE_PYCONSOLE)
   LIST(APPEND _${PROJECT_NAME}_exposed_targets 
-       PyInterp PyConsole  SalomePyQtGUILight)
+       PyInterp PyConsoleBase PyConsole SalomePyQtGUILight)
   IF(SALOME_USE_PLOT2DVIEWER)
     LIST(APPEND _${PROJECT_NAME}_exposed_targets SalomePyQt)
   ENDIF()
index d99916d856b3d708cb9517f18f2587944c957319..d52f4269324bccf7daec8989fbcf1572bf4abd24 100644 (file)
@@ -198,6 +198,7 @@ SET(GUI_ObjBrowser ObjBrowser)
 SET(GUI_OCCViewer OCCViewer)
 SET(GUI_OpenGLUtils OpenGLUtils)
 SET(GUI_Plot2d Plot2d)
+SET(GUI_PyConsoleBase PyConsoleBase)
 SET(GUI_PyConsole PyConsole)
 SET(GUI_PyInterp PyInterp)
 SET(GUI_PyEditor PyEditor)
index 6435a1ccfc526556a126ea66364d8818b3ae237c..05d331cc1b3c785fe8ad200aba91e3230c1b1ef8 100755 (executable)
@@ -21,6 +21,7 @@
 # Common packages
 ##
 ADD_SUBDIRECTORY(CASCatch)
+ADD_SUBDIRECTORY(SUITT)
 ADD_SUBDIRECTORY(Qtx)
 ADD_SUBDIRECTORY(HelpBrowser)
 ADD_SUBDIRECTORY(Style)
@@ -124,6 +125,7 @@ ENDIF(SALOME_USE_PYVIEWER)
 ##
 IF(SALOME_USE_PYCONSOLE) 
   ADD_SUBDIRECTORY(PyInterp)
+  ADD_SUBDIRECTORY(PyConsoleBase)
   ADD_SUBDIRECTORY(PyConsole)
   ADD_SUBDIRECTORY(SALOME_PYQT)
 ENDIF(SALOME_USE_PYCONSOLE)
index 04e309b4aa64b34fb62ee70bde2d6b1e9e1190a4..3171c6c935e77808f261bd60a9ae433a18c1f2dc 100755 (executable)
@@ -82,6 +82,7 @@ IF(SALOME_USE_PYCONSOLE)
   INCLUDE_DIRECTORIES(
     ${PYTHON_INCLUDE_DIRS}
     ${PROJECT_SOURCE_DIR}/src/PyConsole
+    ${PROJECT_SOURCE_DIR}/src/PyConsoleBase
     ${PROJECT_SOURCE_DIR}/src/PyInterp
     ${PROJECT_SOURCE_DIR}/src/SUITApp
   )
index aebd5fd6faf5eb2a1fa629b4b460fc68dee3ec6c..8516a1280331b500de1376f4734a7d66629df17b 100755 (executable)
@@ -26,6 +26,7 @@ INCLUDE_DIRECTORIES(
   ${QT_INCLUDES}
   ${PYTHON_INCLUDE_DIRS}
   ${PROJECT_SOURCE_DIR}/src/PyConsole
+  ${PROJECT_SOURCE_DIR}/src/PyConsoleBase
   ${PROJECT_SOURCE_DIR}/src/Qtx
   ${PROJECT_SOURCE_DIR}/src/SUIT
   ${PROJECT_SOURCE_DIR}/src/Event
@@ -36,25 +37,20 @@ INCLUDE_DIRECTORIES(
 ADD_DEFINITIONS(${QT_DEFINITIONS} ${PYTHON_DEFINITIONS})
 
 # libraries to link to
-SET(_link_LIBRARIES ${QT_LIBRARIES} ${PYTHON_LIBRARIES} qtx suit PyInterp Event)
+SET(_link_LIBRARIES ${QT_LIBRARIES} ${PYTHON_LIBRARIES} qtx suit PyConsoleBase)
 
 # --- headers ---
 
 # header files / to be processed by moc
 SET(_moc_HEADERS
   PyConsole_Console.h
-  PyConsole_ConsoleBase.h
   PyConsole_Editor.h
   PyConsole_EnhEditor.h
 )
 
 # header files / no moc processing
 SET(_other_HEADERS
-  PyConsole.h
-  PyConsole_EnhInterp.h
-  PyConsole_Event.h
-  PyConsole_Interp.h
-  PyConsole_Request.h
+  
 )
 
 # header files / to install
@@ -62,13 +58,6 @@ SET(PyConsole_HEADERS ${_moc_HEADERS} ${_other_HEADERS})
 
 # --- resources ---
 
-# resource files / to be processed by lrelease
-SET(_ts_RESOURCES
-  resources/PyConsole_msg_en.ts
-  resources/PyConsole_msg_fr.ts
-  resources/PyConsole_msg_ja.ts
-)
-
 # --- sources ---
 
 # sources / moc wrappings
@@ -77,13 +66,8 @@ QT_WRAP_MOC(_moc_SOURCES ${_moc_HEADERS})
 # sources / static
 SET(_other_SOURCES
   PyConsole_Console.cxx
-  PyConsole_ConsoleBase.cxx
-  PyConsole_Editor.cxx
   PyConsole_EnhEditor.cxx
-  PyConsole_EnhInterp.cxx
-  PyConsole_Event.cxx
-  PyConsole_Interp.cxx
-  PyConsole_Request.cxx
+  PyConsole_Editor.cxx
 )
 
 # sources / to compile
@@ -96,5 +80,4 @@ TARGET_LINK_LIBRARIES(PyConsole ${_link_LIBRARIES})
 INSTALL(TARGETS PyConsole EXPORT ${PROJECT_NAME}TargetGroup DESTINATION ${SALOME_INSTALL_LIBS})
 
 INSTALL(FILES ${PyConsole_HEADERS} DESTINATION ${SALOME_INSTALL_HEADERS})
-QT_INSTALL_TS_RESOURCES("${_ts_RESOURCES}" "${SALOME_GUI_INSTALL_RES_DATA}")
 
index f315800e611411880e05ea401b5de683372d4ffa..ad41a0aa8b30602608a22736d0a3152542d12d07 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "PyConsole_Interp.h"   /// !!! WARNING !!! THIS INCLUDE MUST BE VERY FIRST !!!
 #include "PyConsole_Console.h"
+#include "PyConsole_Editor.h"
 #include "PyConsole_EnhEditor.h"
 #include "PyConsole_EnhInterp.h"
 
diff --git a/src/PyConsole/PyConsole_ConsoleBase.cxx b/src/PyConsole/PyConsole_ConsoleBase.cxx
deleted file mode 100644 (file)
index 79b7170..0000000
+++ /dev/null
@@ -1,349 +0,0 @@
-// Copyright (C) 2007-2015  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_EnhEditor.h"
-#include "PyConsole_EnhInterp.h"
-
-#include <QAction>
-#include <QApplication>
-#include <QClipboard>
-#include <QEvent>
-#include <QMenu>
-#include <QVBoxLayout>
-
-/*!
-  \brief Constructor.
-
-  Creates new python console widget.
-  \param parent parent widget
-  \param interp python interpreter
-*/
-PyConsole_ConsoleBase::PyConsole_ConsoleBase( QWidget* parent, PyConsole_Interp* interp )
-: QWidget( parent )
-{
-  PyConsole_Interp* anInterp = interp ? interp : new PyConsole_Interp();
-  
-  // initialize Python interpretator
-  anInterp->initialize();
-  
-  // create editor console
-  QVBoxLayout* lay = new QVBoxLayout( this );
-  lay->setMargin( 0 );
-  myEditor = new PyConsole_Editor( 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_Editor* 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();
-}
-
-/**
- * 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* anInterp = interp ? interp : new PyConsole_EnhInterp();
-
-  // initialize Python interpretator
-  anInterp->initialize();
-
-  // create editor console
-  QVBoxLayout* lay = new QVBoxLayout( this );
-  lay->setMargin( 0 );
-  myEditor = new PyConsole_EnhEditor( anInterp, this );
-  char* synchronous = getenv("PYTHON_CONSOLE_SYNC");
-  if (synchronous && atoi(synchronous))
-  {
-      myEditor->setIsSync(true);
-  }
-  myEditor->viewport()->installEventFilter( this );
-  lay->addWidget( myEditor );
-
-  createActions();
-}
diff --git a/src/PyConsole/PyConsole_ConsoleBase.h b/src/PyConsole/PyConsole_ConsoleBase.h
deleted file mode 100644 (file)
index 2add981..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright (C) 2007-2015  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 <SUIT_PopupClient.h>
-#include <QWidget>
-#include <QMap>
-
-class PyConsole_Interp;
-class PyConsole_Editor;
-
-class PYCONSOLE_EXPORT PyConsole_ConsoleBase : 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_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();
-
-protected:
-  void                createActions();
-  void                updateActions();
-
-  PyConsole_ConsoleBase( QWidget* parent, PyConsole_Interp*,  PyConsole_Editor*);
-
-  PyConsole_Editor*   myEditor;    //!< python console editor widget
-  QMap<int, QAction*> myActions;   //!< menu actions list
-};
-
-/**
- * Enhance console object providing auto-completion.
- * Similar to PyConsole_Console except that an enhanced interpreter and enhanced editor
- * are encapsulated.
- */
-class PYCONSOLE_EXPORT PyConsole_EnhConsoleBase : public PyConsole_ConsoleBase
-{
-  Q_OBJECT
-
-public:
-  PyConsole_EnhConsoleBase( QWidget* parent, PyConsole_Interp* interp = 0 );
-  virtual ~PyConsole_EnhConsoleBase() {}
-};
-
-#endif // PYCONSOLE_CONSOLE_H
index 2311b58d46bb29a3e2b48be8b4b7cd2020572401..7dbc93f8cb5d53e61bbe4ade13325f70ae824f1d 100644 (file)
 #include "PyInterp_Dispatcher.h"
 #include "PyConsole_Request.h"
 
-#include <SUIT_Tools.h>
-#include <SUIT_FileDlg.h>
-#include <SUIT_MessageBox.h>
-#include <SUIT_FileValidator.h>
+#include "SUIT_FileValidator.h"
+#include "SUIT_MessageBox.h"
+#include "SUIT_FileDlg.h"
 
 #include <QApplication>
 #include <QClipboard>
 #include <QTextDocument>
 #include <QTextStream>
 #include <QChar>
-
-//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  = "... ";
+#include <QFileInfo>
 
 class DumpCommandsFileValidator : public SUIT_FileValidator
 {
@@ -152,25 +133,6 @@ bool DumpCommandsFileValidator::canSave(const QString& file, bool permissions)
   return SUIT_FileValidator::canSave( file, permissions);
 }
 
-void staticCallbackStdout( void* data, char* c )
-{
-  if(!((PyConsole_Editor*)data)->isSuppressOutput()) {
-    PyConsole_Editor* e = (PyConsole_Editor*)data;
-    e->putLog( fromUtf8(c) );
-    QApplication::postEvent( e, new PrintEvent( fromUtf8(c), false ) );
-  }
-}
-
-void staticCallbackStderr( void* data, char* c )
-{
-  if(!((PyConsole_Editor*)data)->isSuppressOutput()) {
-    PyConsole_Editor* e = (PyConsole_Editor*)data;
-    e->putLog( fromUtf8(c) );
-    QApplication::postEvent( e, new PrintEvent( fromUtf8(c), true ) );
-  }
-}
-
-
 /*!
   \brief Constructor. 
   
@@ -180,29 +142,8 @@ void staticCallbackStderr( void* data, char* c )
 */
 PyConsole_Editor::PyConsole_Editor( PyConsole_Interp* theInterp, 
                                     QWidget*          theParent )
-: QTextEdit( theParent ),
-  myInterp( 0 ),
-  myCmdInHistory( -1 ),
-  myEventLoop( 0 ),
-  myShowBanner( true ),
-  myIsSync( true ),
-  myIsSuppressOutput( false )
+  : PyConsole_EditorBase(theInterp,theParent)
 {
-  QString fntSet( "" );
-  QFont aFont = SUIT_Tools::stringToFont( fntSet );
-  setFont( aFont );
-  setUndoRedoEnabled( false );
-
-  myPrompt = READY_PROMPT;
-  setLineWrapMode( QTextEdit::WidgetWidth );
-  setWordWrapMode( QTextOption::WrapAnywhere );
-  setAcceptRichText( false );
-
-  theInterp->setvoutcb( staticCallbackStdout, this );
-  theInterp->setverrcb( staticCallbackStderr, this );
-
-  // san - This is necessary for troubleless initialization
-  onPyInterpChanged( theInterp );
 }
 
 /*!
@@ -210,947 +151,6 @@ PyConsole_Editor::PyConsole_Editor( PyConsole_Interp* theInterp,
 */
 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 True if python console works in synchronous mode
-*/
-bool PyConsole_Editor::isSync() const
-{
-  return myIsSync;
-}
-
-/*!
-  \brief Set synchronous mode flag value.
-
-  In synhronous mode the Python commands are executed in the GUI thread
-  and the GUI is blocked until the command is finished. In the asynchronous
-  mode each Python command is executed in the separate thread that does not
-  block the main GUI loop.
-
-  \param on synhronous mode flag
-*/
-void PyConsole_Editor::setIsSync( const bool on )
-{
-  myIsSync = on;
-}
-
-/*!
-  \brief Get suppress output flag value.
-  
-  \sa setIsSuppressOutput()
-  \return \c true if python console output is suppressed.
-*/
-bool PyConsole_Editor::isSuppressOutput() const
-{
-  return myIsSuppressOutput;
-}
-
-/*!
-  \brief Set suppress output flag value.
-
-  In case if suppress output flag is true, the python 
-  console output suppressed.
-
-  \param on suppress output flag
-*/
-void PyConsole_Editor::setIsSuppressOutput( const bool on )
-{
-  myIsSuppressOutput = on;
-}
-
-/*!
-  \brief Get 'show banner' flag value.
-  
-  \sa setIsShowBanner()
-  \return \c true if python console shows banner
-*/
-bool PyConsole_Editor::isShowBanner() const
-{
-  return myShowBanner;
-}
-
-/*!
-  \brief Set 'show banner' flag value.
-
-  The banner is shown in the top of the python console window.
-
-  \sa isShowBanner()
-  \param on 'show banner' flag
-*/
-void PyConsole_Editor::setIsShowBanner( const bool on )
-{
-  if ( myShowBanner != on ) {
-    myShowBanner = on;
-    clear();
-  }
-}
-
-/*!
-  \brief 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() ? myBanner.split("\n").count() : 0 ) + 1;
-  QSize s(100, fm.lineSpacing()*nbLines);
-  return s;
-}
-
-/*!
-  \brief Put the string \a str to the python editor.
-  \param str string to be put in the command line of the editor
-  \param newBlock if True, then the string is printed on a new line
-  \param isError if true, the text is printed in dark red
-*/
-void PyConsole_Editor::addText( const QString& str, 
-                                const bool     newBlock,
-                                const bool    isError)
-{
-  QTextCursor theCursor(textCursor());
-  QTextCharFormat cf;
-
-  moveCursor( QTextCursor::End );
-  if ( newBlock )
-    theCursor.insertBlock();
-  if (isError)
-      cf.setForeground(QBrush(Qt::red));
-  else
-      cf.setForeground(QBrush(Qt::black));
-  theCursor.insertText( str, cf);
-  moveCursor( QTextCursor::End );
-  ensureCursorVisible();
-}
-
-/*!
-  \brief Convenient method for executing a Python command,
-  as if the user typed it manually.
-  \param command python command to be executed
-
-  !!! WARNING: doesn't work properly with multi-line commands. !!!
-*/
-void PyConsole_Editor::exec( const QString& command )
-{
-  if ( isReadOnly() ) {
-    // some interactive command is being executed in this editor...
-    // shedule the command to the queue
-    myQueue.push_back( command );
-    return;
-  }
-  // remove last line
-  moveCursor( QTextCursor::End );
-  moveCursor( QTextCursor::StartOfBlock, QTextCursor::KeepAnchor );
-  textCursor().removeSelectedText();
-  // set "ready" prompt
-  myPrompt = READY_PROMPT;
-  // clear command buffer
-  myCommandBuffer.truncate( 0 );
-  // unset history browsing mode
-  myCmdInHistory = -1;
-  // print command line by line
-  QString cmd = command;
-  if ( !cmd.endsWith( "\n" ) ) cmd += "\n";
-  QStringList lines = command.split( "\n" );
-  for ( int i = 0; i < lines.size(); i++ ) {
-    if ( !lines[i].trimmed().isEmpty() )
-      myHistory.push_back( lines[i] );
-    addText( ( i == 0 ? READY_PROMPT : DOTS_PROMPT ) + lines[i], i != 0 );
-    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_Editor::createRequest( const QString& command )
-{
-  return new ExecCommand( myInterp, command, this, isSync() );
-}
-
-/*!
-  \brief Execute command in the python interpreter
-  and wait until it is finished.
-
-  \param command python command to be executed
- */
-void PyConsole_Editor::execAndWait( const QString& command )
-{
-  // already running ?
-  if( myEventLoop )
-    return;
-
-  // create new event loop
-  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 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_Editor::dropEvent( QDropEvent* event )
-{
-  // get the initial drop position
-  QPoint pos = event->pos();
-  QTextCursor cur = cursorForPosition( event->pos() );
-  // if the position is not in the last line move it to the end of the command line
-  if ( cur.position() < document()->end().previous().position() + promptSize() ) {
-    moveCursor( QTextCursor::End );
-    pos = cursorRect().center();
-  }
-  // create new drop event and use it instead of the original
-  QDropEvent de( pos,
-                 event->possibleActions(),
-                 event->mimeData(),
-                 event->mouseButtons(),
-                 event->keyboardModifiers(),
-                 event->type() );
-  QTextEdit::dropEvent( &de );
-  // accept the original event
-  event->acceptProposedAction();
-}
-
-/*!
-  \brief Process mouse button release event.
-
-  Left mouse button: copy selection to the clipboard.
-  Middle mouse button: paste clipboard's contents.
-  \param event mouse event
-*/
-void PyConsole_Editor::mouseReleaseEvent( QMouseEvent* event )
-{
-  if ( event->button() == Qt::LeftButton ) {
-    QTextEdit::mouseReleaseEvent( event );
-    //copy();
-  }
-  else if ( event->button() == Qt::MidButton ) {
-    QTextCursor cur = cursorForPosition( event->pos() );
-    // if the position is not in the last line move it to the end of the command line
-    if ( cur.position() < document()->end().previous().position() + promptSize() ) {
-      moveCursor( QTextCursor::End );
-    }
-    else {
-      setTextCursor( cur );
-    }
-    const QMimeData* md = QApplication::clipboard()->mimeData( QApplication::clipboard()->supportsSelection() ? 
-                                                              QClipboard::Selection : QClipboard::Clipboard );
-    if ( md )
-      insertFromMimeData( md );
-  }
-  else {
-    QTextEdit::mouseReleaseEvent( event );
-  }
-}
-
-/*!
-  \brief Check if the string is command.
-  
-  Return True if the string \a str is likely to be the command
-  (i.e. it is started from the '>>>' or '...').
-  \param str string to be checked
-*/
-bool PyConsole_Editor::isCommand( const QString& str ) const
-{
-  return str.startsWith( READY_PROMPT ) || str.startsWith( DOTS_PROMPT );
-}
-
-/*!
-  \brief Handle keyboard event.
-
-  Implement navigation, history browsing, copy/paste and other common
-  operations.
-  \param event keyboard event
-*/
-void PyConsole_Editor::keyPressEvent( QKeyEvent* event )
-{
-  // get cursor position
-  QTextCursor cur = textCursor();
-  int curLine = cur.blockNumber();
-  int curCol  = cur.columnNumber();
-
-  // get last edited line
-  int endLine = document()->blockCount()-1;
-
-  // get pressed key code
-  int aKey = event->key();
-
-  // check if <Ctrl> is pressed
-  bool ctrlPressed = event->modifiers() & Qt::ControlModifier;
-  // check if <Shift> is pressed
-  bool shftPressed = event->modifiers() & Qt::ShiftModifier;
-
-  if ( aKey == Qt::Key_Escape || ( ctrlPressed && aKey == -1 ) ) {
-    // process <Ctrl>+<Break> key-binding and <Escape> key: clear current command
-    myCommandBuffer.truncate( 0 );
-    myPrompt = READY_PROMPT;
-    addText( myPrompt, true );
-    horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
-    return;
-  }
-  else if ( ctrlPressed && aKey == Qt::Key_C ) {
-    // process <Ctrl>+<C> key-binding : copy
-    copy();
-    return;
-  }
-  else if ( ctrlPressed && aKey == Qt::Key_X ) {
-    // process <Ctrl>+<X> key-binding : cut
-    cut();
-    return;
-  }
-  else if ( ctrlPressed && aKey == Qt::Key_V ) {
-    // process <Ctrl>+<V> key-binding : paste
-    paste();
-    return;
-  }
-
-  // check for printed key
-  // #### aKey = ( aKey < Qt::Key_Space || aKey > Qt::Key_ydiaeresis ) ? aKey : 0;
-  // Better:
-  aKey = !(QChar(aKey).isPrint()) ? aKey : 0;
-
-  switch ( aKey ) {
-  case 0 :
-    // any printed key: just print it
-    {
-      if ( curLine < endLine || curCol < promptSize() ) {
-        moveCursor( QTextCursor::End );
-      }
-      QTextEdit::keyPressEvent( event );
-      break;
-    }
-  case Qt::Key_Return:
-  case Qt::Key_Enter:
-    // <Enter> key: process the current command
-    {
-      handleReturn();
-      break;
-    }
-  case Qt::Key_Up:
-    // <Up> arrow key: process as follows:
-    // - without <Ctrl>, <Shift> modifiers: previous command in history
-    // - with <Ctrl> modifier key pressed:  move cursor one row up without selection
-    // - with <Shift> modifier key pressed: move cursor one row up with selection
-    // - with <Ctrl>+<Shift> modifier keys pressed: scroll one row up
-    {
-      if ( ctrlPressed && shftPressed ) {
-        int value   = verticalScrollBar()->value();
-        int spacing = fontMetrics().lineSpacing();
-        verticalScrollBar()->setValue( value > spacing ? value-spacing : 0 );
-      }
-      else if ( shftPressed || ctrlPressed ) {
-        if ( curLine > 0 )
-          moveCursor( QTextCursor::Up, 
-                      shftPressed ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor );
-      }
-      else { 
-        if ( myCmdInHistory < 0 && myHistory.count() > 0 ) {
-          // set history browsing mode
-          myCmdInHistory = myHistory.count();
-          // remember current command
-          QTextBlock par = document()->end().previous();
-          myCurrentCommand = par.text().remove( 0, promptSize() );
-        }
-        if ( myCmdInHistory > 0 ) {
-          myCmdInHistory--;
-          // get previous command in the history
-          QString previousCommand = myHistory.at( myCmdInHistory );
-          // print previous command
-          moveCursor( QTextCursor::End );
-          moveCursor( QTextCursor::StartOfBlock, QTextCursor::KeepAnchor );
-          textCursor().removeSelectedText();
-          addText( myPrompt + previousCommand ); 
-          // move cursor to the end
-          moveCursor( QTextCursor::End );
-        }
-      }
-      break;
-    }
-  case Qt::Key_Down:
-    // <Down> arrow key: process as follows:
-    // - without <Ctrl>, <Shift> modifiers: next command in history
-    // - with <Ctrl> modifier key pressed:  move cursor one row down without selection
-    // - with <Shift> modifier key pressed: move cursor one row down with selection
-    // - with <Ctrl>+<Shift> modifier keys pressed: scroll one row down
-    {
-      if ( ctrlPressed && shftPressed ) {
-        int value   = verticalScrollBar()->value();
-        int maxval  = verticalScrollBar()->maximum();
-        int spacing = fontMetrics().lineSpacing();
-        verticalScrollBar()->setValue( value+spacing < maxval ? value+spacing : maxval );
-      }
-      else if ( shftPressed || ctrlPressed) {
-        if ( curLine < endLine )
-          moveCursor( QTextCursor::Down, 
-                      shftPressed ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor );
-      }
-      else { 
-        if ( myCmdInHistory >= 0 ) {
-          // get next command in the history
-          myCmdInHistory++;
-          QString nextCommand;
-          if ( myCmdInHistory < myHistory.count() ) {
-            // next command in history
-            nextCommand = myHistory.at( myCmdInHistory );
-          }
-          else {
-            // end of history is reached
-            // last printed command
-            nextCommand = myCurrentCommand;
-            // unset history browsing mode
-            myCmdInHistory = -1;
-          }
-          // print next or current command
-          moveCursor( QTextCursor::End );
-          moveCursor( QTextCursor::StartOfBlock, QTextCursor::KeepAnchor );
-          textCursor().removeSelectedText();
-          addText( myPrompt + nextCommand );
-          // move cursor to the end
-          moveCursor( QTextCursor::End );
-        }
-      }
-      break;
-    }
-  case Qt::Key_Left:
-    // <Left> arrow key: process as follows:
-    // - without <Ctrl>, <Shift> modifiers: move one symbol left (taking into account prompt)
-    // - with <Ctrl> modifier key pressed:  move one word left (taking into account prompt)
-    // - with <Shift> modifier key pressed: move one symbol left with selection
-    // - with <Ctrl>+<Shift> modifier keys pressed: move one word left with selection
-    {
-      QString txt = textCursor().block().text();
-      if ( !shftPressed && isCommand( txt ) && curCol <= promptSize() ) {
-        moveCursor( QTextCursor::Up );
-        moveCursor( QTextCursor::EndOfBlock );
-      }
-      else {
-        QTextEdit::keyPressEvent( event );
-      }
-      break;
-    }
-  case Qt::Key_Right:
-    // <Right> arrow key: process as follows:
-    // - without <Ctrl>, <Shift> modifiers: move one symbol right (taking into account prompt)
-    // - with <Ctrl> modifier key pressed:  move one word right (taking into account prompt)
-    // - with <Shift> modifier key pressed: move one symbol right with selection
-    // - with <Ctrl>+<Shift> modifier keys pressed: move one word right with selection
-    {
-      QString txt = textCursor().block().text();
-      if ( !shftPressed ) {
-        if ( curCol < txt.length() ) {
-          if ( isCommand( txt ) && curCol < promptSize() ) {
-            cur.setPosition( cur.block().position() + promptSize() );
-            setTextCursor( cur );
-            break;
-          }
-        }
-        else {
-          if ( curLine < endLine && isCommand( textCursor().block().next().text() ) ) {
-            cur.setPosition( cur.position() + promptSize()+1 );
-            setTextCursor( cur );
-            horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
-            break;
-          }
-        }
-      }
-      QTextEdit::keyPressEvent( event );
-      break;
-    }
-  case Qt::Key_PageUp:
-    // <PageUp> key: process as follows:
-    // - without <Ctrl>, <Shift> modifiers: first command in history
-    // - with <Ctrl> modifier key pressed:  move cursor one page up without selection
-    // - with <Shift> modifier key pressed: move cursor one page up with selection
-    // - with <Ctrl>+<Shift> modifier keys pressed: scroll one page up
-    {
-      if ( ctrlPressed && shftPressed ) {
-        verticalScrollBar()->triggerAction(QAbstractSlider::SliderPageStepSub);
-      }
-      else if ( shftPressed || ctrlPressed ) {
-        bool moved = false;
-        qreal lastY = cursorRect( cur ).top();
-        qreal distance = 0;
-        // move using movePosition to keep the cursor's x
-        do {
-          qreal y = cursorRect( cur ).top();
-          distance += qAbs( y - lastY );
-          lastY = y;
-          moved = cur.movePosition( QTextCursor::Up, 
-                                    shftPressed ? QTextCursor::KeepAnchor : 
-                                                  QTextCursor::MoveAnchor );
-        } while ( moved && distance < viewport()->height() );
-        if ( moved ) {
-          cur.movePosition( QTextCursor::Down, 
-                            shftPressed ? QTextCursor::KeepAnchor : 
-                                          QTextCursor::MoveAnchor );
-          verticalScrollBar()->triggerAction( QAbstractSlider::SliderPageStepSub );
-        }
-        setTextCursor( cur );
-      }
-      else { 
-        if ( myCmdInHistory < 0 && myHistory.count() > 0 ) {
-          // set history browsing mode
-          myCmdInHistory = myHistory.count();
-          // remember current command
-          QTextBlock par = document()->end().previous();
-          myCurrentCommand = par.text().remove( 0, promptSize() );
-        }
-        if ( myCmdInHistory > 0 ) {
-          myCmdInHistory = 0;
-          // get very first command in the history
-          QString firstCommand = myHistory.at( myCmdInHistory );
-          // print first command
-          moveCursor( QTextCursor::End );
-          moveCursor( QTextCursor::StartOfBlock, QTextCursor::KeepAnchor );
-          textCursor().removeSelectedText();
-          addText( myPrompt + firstCommand ); 
-          // move cursor to the end
-          moveCursor( QTextCursor::End );
-        }
-      }
-      break;
-    }
-  case Qt::Key_PageDown:
-    // <PageDown> key: process as follows:
-    // - without <Ctrl>, <Shift> modifiers: last command in history
-    // - with <Ctrl> modifier key pressed:  move cursor one page down without selection
-    // - with <Shift> modifier key pressed: move cursor one page down with selection
-    // - with <Ctrl>+<Shift> modifier keys pressed: scroll one page down
-    {
-      if ( ctrlPressed && shftPressed ) {
-        verticalScrollBar()->triggerAction(QAbstractSlider::SliderPageStepAdd);
-      }
-      else if ( shftPressed || ctrlPressed ) {
-        bool moved = false;
-        qreal lastY = cursorRect( cur ).top();
-        qreal distance = 0;
-        // move using movePosition to keep the cursor's x
-        do {
-          qreal y = cursorRect( cur ).top();
-          distance += qAbs( y - lastY );
-          lastY = y;
-          moved = cur.movePosition( QTextCursor::Down, 
-                                    shftPressed ? QTextCursor::KeepAnchor : 
-                                                  QTextCursor::MoveAnchor );
-        } while ( moved && distance < viewport()->height() );
-        if ( moved ) {
-          cur.movePosition( QTextCursor::Up, 
-                            shftPressed ? QTextCursor::KeepAnchor : 
-                                          QTextCursor::MoveAnchor );
-          verticalScrollBar()->triggerAction( QAbstractSlider::SliderPageStepSub );
-        }
-        setTextCursor( cur );
-      }
-      else { 
-        if ( myCmdInHistory >= 0 ) {
-          // unset history browsing mode
-          myCmdInHistory = -1;
-          // print current command
-          moveCursor( QTextCursor::End );
-          moveCursor( QTextCursor::StartOfBlock, QTextCursor::KeepAnchor );
-          textCursor().removeSelectedText();
-          addText( myPrompt + myCurrentCommand ); 
-          // move cursor to the end
-          moveCursor( QTextCursor::End );
-        }
-      }
-      break;
-    }
-  case Qt::Key_Home: 
-    // <Home> key: process as follows:
-    // - without <Ctrl>, <Shift> modifiers: move cursor to the beginning of the current line without selection
-    // - with <Ctrl> modifier key pressed:  move cursor to the very first symbol without selection
-    // - with <Shift> modifier key pressed: move cursor to the beginning of the current line with selection
-    // - with <Ctrl>+<Shift> modifier keys pressed: move cursor to the very first symbol with selection
-    {
-      if ( ctrlPressed ) { 
-        moveCursor( QTextCursor::Start, 
-                    shftPressed ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor );
-      }
-      else {
-        QString txt = textCursor().block().text();
-        if ( isCommand( txt ) ) {
-          if ( shftPressed ) {
-            if ( curCol > promptSize() ) {
-              cur.movePosition( QTextCursor::StartOfLine, QTextCursor::KeepAnchor );
-              cur.movePosition( QTextCursor::Right, QTextCursor::KeepAnchor, promptSize() );
-            }
-          }
-          else {
-            cur.movePosition( QTextCursor::StartOfLine );
-            cur.movePosition( QTextCursor::Right, QTextCursor::MoveAnchor, promptSize() );
-          }
-          setTextCursor( cur );
-        }
-        else {
-          moveCursor( QTextCursor::StartOfBlock, 
-                      shftPressed ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor );
-        }
-        horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
-      }
-      break;
-    }
-  case Qt::Key_End:
-    // <End> key: process as follows:
-    // - without <Ctrl>, <Shift> modifiers: move cursor to the end of the current line without selection
-    // - with <Ctrl> modifier key pressed:  move cursor to the very last symbol without selection
-    // - with <Shift> modifier key pressed: move cursor to the end of the current line with selection
-    // - with <Ctrl>+<Shift> modifier keys pressed: move cursor to the very last symbol with selection
-    {
-      moveCursor( ctrlPressed ? QTextCursor::End : QTextCursor::EndOfBlock, 
-                  shftPressed ? QTextCursor::KeepAnchor : QTextCursor::MoveAnchor );
-      break;
-    }  
-  case Qt::Key_Backspace :
-    // <Backspace> key: process as follows
-    // - without any modifiers : delete symbol before the cursor / selection (taking into account prompt)
-    // - with <Shift> modifier key pressed: delete previous word
-    // - with <Ctrl> modifier key pressed: delete text from the cursor to the line beginning
-    // works only for last (command) line
-    {
-      if ( cur.hasSelection() ) {
-        cut();
-      }
-      else if ( cur.position() > document()->end().previous().position() + promptSize() ) {
-        if ( shftPressed ) {
-          moveCursor( QTextCursor::PreviousWord, QTextCursor::KeepAnchor );
-          textCursor().removeSelectedText();
-        }
-        else if ( ctrlPressed ) {
-          cur.setPosition( document()->end().previous().position() + promptSize(),
-                           QTextCursor::KeepAnchor );
-          setTextCursor( cur );
-          textCursor().removeSelectedText();
-        }
-        else {
-          QTextEdit::keyPressEvent( event );
-        }
-      }
-      else {
-        cur.setPosition( document()->end().previous().position() + promptSize() );
-        setTextCursor( cur );
-        horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
-      }
-      break;
-    }
-  case Qt::Key_Delete :
-    // <Delete> key: process as follows
-    // - without any modifiers : delete symbol after the cursor / selection (taking into account prompt)
-    // - with <Shift> modifier key pressed: delete next word
-    // - with <Ctrl> modifier key pressed: delete text from the cursor to the end of line
-    // works only for last (command) line
-    {
-      if ( cur.hasSelection() ) {
-        cut();
-      }
-      else if ( cur.position() > document()->end().previous().position() + promptSize()-1 ) {
-        if ( shftPressed ) {
-          moveCursor( QTextCursor::NextWord, QTextCursor::KeepAnchor );
-          textCursor().removeSelectedText();
-        }
-        else if ( ctrlPressed ) {
-          moveCursor( QTextCursor::EndOfBlock, QTextCursor::KeepAnchor );
-          textCursor().removeSelectedText();
-        }
-        else {
-          QTextEdit::keyPressEvent( event );
-        }
-      }
-      else {
-        cur.setPosition( document()->end().previous().position() + promptSize() );
-        setTextCursor( cur );
-        horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
-      }
-      break;
-    }
-  case Qt::Key_Insert :
-    // <Insert> key: process as follows
-    // - with <Ctrl> modifier key pressed:  copy()
-    // - with <Shift> modifier key pressed: paste() to the command line
-    {
-      if ( ctrlPressed ) {
-        copy();
-      }
-      else if ( shftPressed ) {
-        paste();
-      }
-      else
-        QTextEdit::keyPressEvent( event );
-      break;
-    }
-  }
-}
-
-/*!
-  \brief Handle notification event coming from Python dispatcher.
-  \param event notification event
-*/
-void PyConsole_Editor::customEvent( QEvent* event )
-{
-  switch( event->type() )
-  {
-  case PrintEvent::EVENT_ID:
-    {
-      PrintEvent* pe=(PrintEvent*)event;
-      addText( pe->text(), false, pe->isError());
-      return;
-    }
-  case PyInterp_Event::ES_OK:
-  case PyInterp_Event::ES_ERROR:
-  {
-    // clear command buffer
-    myCommandBuffer.truncate( 0 );
-    // add caret return line if necessary
-    QTextBlock par = document()->end().previous();
-    QString txt = par.text();
-    txt.truncate( txt.length() - 1 );
-    // IPAL19397 : addText moved to handleReturn() method
-    //if ( !txt.isEmpty() )
-    //  addText( "", true );
-    // set "ready" prompt
-    myPrompt = READY_PROMPT;
-    addText( myPrompt );
-    // unset busy cursor
-    unsetCursor();
-    // stop event loop (if running)
-    if ( myEventLoop )
-      myEventLoop->exit();
-    break;
-  }
-  case PyInterp_Event::ES_INCOMPLETE:
-  {
-    // extend command buffer (multi-line command)
-    myCommandBuffer.append( "\n" );
-    // add caret return line if necessary
-    QTextBlock par = document()->end().previous();
-    QString txt = par.text();
-    txt.truncate( txt.length() - 1 );
-    // IPAL19397 : addText moved to handleReturn() method
-    //if ( !txt.isEmpty() )
-    //  addText( "", true );
-    // set "dot" prompt
-    myPrompt = DOTS_PROMPT;
-    addText( myPrompt/*, true*/ ); // IPAL19397
-    // unset busy cursor
-    unsetCursor();
-    // stop event loop (if running)
-    if ( myEventLoop )
-      myEventLoop->exit();
-    break;
-  }
-  default:
-    QTextEdit::customEvent( event );
-  }
-  
-  // unset read-only state
-  setReadOnly( false );
-  // unset history browsing mode
-  myCmdInHistory = -1;
-
-  if ( (int)event->type() == (int)PyInterp_Event::ES_OK && myQueue.count() > 0 )
-  {
-    // process the next sheduled command from the queue (if there is any)
-    QString nextcmd = myQueue[0];
-    myQueue.pop_front();
-    exec( nextcmd );
-  }
-}
-
-/*!
-  \brief Handle Python interpreter change.
-
-  Perform initialization actions if the interpreter is changed.
-  \param interp python interpreter is being set
-*/
-void PyConsole_Editor::onPyInterpChanged( PyConsole_Interp* interp )
-{
-  if ( myInterp != interp 
-       // Force read-only state and wait cursor when myInterp is NULL
-      || !myInterp ) {
-    myInterp = interp;
-    if ( myInterp ) {
-      // print banner
-      myBanner = myInterp->getbanner().c_str();
-      if ( isShowBanner() )
-       addText( myBanner );
-      // clear command buffer
-      myCommandBuffer.truncate(0);
-      // unset read-only state
-      setReadOnly( false );
-      // unset history browsing mode
-      myCmdInHistory = -1;
-      // add prompt
-      addText( myPrompt );
-      // unset busy cursor
-      viewport()->unsetCursor();
-      // stop event loop (if running)
-      if( myEventLoop)
-        myEventLoop->exit();
-    }
-    else {
-      // clear contents
-      clear();
-      // set read-only state
-      setReadOnly( true );
-      // set busy cursor
-      setCursor( Qt::WaitCursor );
-    }
-  }
-}
-
-/*!
-  \brief "Copy" operation.
-  
-  Reimplemented from Qt.
-  Warning! In Qt4 this method is not virtual.
- */
-void PyConsole_Editor::cut()
-{
-  QTextCursor cur = textCursor();
-  if ( cur.hasSelection() ) {
-    QApplication::clipboard()->setText( cur.selectedText() );
-    int startSelection = cur.selectionStart();
-    if ( startSelection < document()->end().previous().position() + promptSize() )
-      startSelection = document()->end().previous().position() + promptSize();
-    int endSelection = cur.selectionEnd();
-    if ( endSelection < document()->end().previous().position() + promptSize() )
-      endSelection = document()->end().previous().position() + promptSize();
-    cur.setPosition( startSelection );
-    cur.setPosition( endSelection, QTextCursor::KeepAnchor );
-    horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
-    setTextCursor( cur );
-    textCursor().removeSelectedText();
-  }
-}
-
-/*!
-  \brief "Paste" operation.
-
-  Reimplemented from Qt.
-  Warning! In Qt4 this method is not virtual.
- */
-void PyConsole_Editor::paste()
-{
-  QTextCursor cur = textCursor();
-  if ( cur.hasSelection() ) {
-    int startSelection = cur.selectionStart();
-    if ( startSelection < document()->end().previous().position() + promptSize() )
-      startSelection = document()->end().previous().position() + promptSize();
-    int endSelection = cur.selectionEnd();
-    if ( endSelection < document()->end().previous().position() + promptSize() )
-      endSelection = document()->end().previous().position() + promptSize();
-    cur.setPosition( startSelection );
-    cur.setPosition( endSelection, QTextCursor::KeepAnchor );
-    horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
-    setTextCursor( cur );
-    textCursor().removeSelectedText();
-  }
-  if ( textCursor().position() < document()->end().previous().position() + promptSize() )
-    moveCursor( QTextCursor::End );
-  QTextEdit::paste();
-}
-
-/*!
-  \brief "Clear" operation.
-
-  Reimplemented from Qt.
-  Warning! In Qt4 this method is not virtual.
- */
-void PyConsole_Editor::clear()
-{
-  QTextEdit::clear();
-  if ( isShowBanner() )
-    addText( myBanner );
-  myPrompt = READY_PROMPT;
-  addText( myPrompt );
 }
 
 /*!
@@ -1164,18 +164,7 @@ void PyConsole_Editor::dump()
   QString fileName = SUIT_FileDlg::getFileName( this, QString(),
                                                aFilters, tr( "TOT_DUMP_PYCOMMANDS" ),
                                                false, true, new DumpCommandsFileValidator( this ) );
-  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();
-  }
+  dumpImpl(fileName);
 }
 /*!
   \brief "Start log" operation.
@@ -1190,7 +179,7 @@ void PyConsole_Editor::startLog()
                                                  aFilters, tr( "TOT_SAVE_PYLOG" ),
                                                  false, true );
     if ( !fileName.isEmpty() ) {
-      if ( startLog( fileName ) ) {
+      if ( startLogImpl( fileName ) ) {
        break;
       }
       else {
@@ -1204,48 +193,3 @@ void PyConsole_Editor::startLog()
     }
   }
 }
-
-/*!
-  \brief Start python trace logging
-  \param fileName the path to the log file
-  \sa stopLog()
- */
-bool PyConsole_Editor::startLog( 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 "Stop log" operation.
-  \sa startLog()
- */
-void PyConsole_Editor::stopLog()
-{
-  myLogFile = QString();
-}
-
-/*!
-  \brief Put string 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();
-  }
-}
index 5dbc8d15e3636b2f876dfc91a75f6879c0ab7d77..4180589421ba7d45ee69074957b8b5c49f30b4a5 100644 (file)
@@ -28,6 +28,7 @@
 #define PYCONSOLE_EDITOR_H
 
 #include "PyConsole.h"
+#include "PyConsole_EditorBase.h"
 
 #include <QTextEdit>
 
@@ -35,72 +36,16 @@ class PyConsole_Interp;
 class PyInterp_Request;
 class QEventLoop;
 
-class PYCONSOLE_EXPORT PyConsole_Editor : public QTextEdit
+class PYCONSOLE_EXPORT PyConsole_Editor : public PyConsole_EditorBase
 {
   Q_OBJECT;
 
 public:
   PyConsole_Editor( PyConsole_Interp* theInterp, QWidget *theParent = 0 );
   ~PyConsole_Editor();
-
-  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;
-
 public slots:
-    void           cut();
-    void           paste();
-    void           clear();
-    void           handleReturn();
-    void           onPyInterpChanged( PyConsole_Interp* );
     void           dump();
-    bool           startLog( const QString& );
     void           startLog();
-    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 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_EDITOR_H
index d4cf274a222026cdc66ea393d2d9c784ab95f88b..ffca890aff7cd5a0ba37cee6de173618f25d746e 100644 (file)
 #include <QMimeData>
 
 #include "PyConsole_EnhEditor.h"
-#include "PyConsole_EnhInterp.h"
-#include "PyConsole_Request.h"
-#include "PyInterp_Dispatcher.h"
-
-// Initialize list of valid separators
-static const char * tmp_a[] = {" ", "(", "[","+", "-", "*", "/", ";", "^", "="};
-const std::vector<QString> PyConsole_EnhEditor::SEPARATORS = \
-    std::vector<QString>(tmp_a, tmp_a + sizeof(tmp_a)/sizeof(tmp_a[0]));
 
 /**
  * Constructor.
@@ -45,447 +37,6 @@ const std::vector<QString> PyConsole_EnhEditor::SEPARATORS = \
  * @param parent parent widget
  */
 PyConsole_EnhEditor::PyConsole_EnhEditor(PyConsole_Interp* interp, QWidget* parent) :
-     PyConsole_Editor(interp, parent),
-     _tab_mode(false),
-     _cursor_pos(-1),
-     _multi_line_paste(false),
-     _multi_line_content()
-{
-  document()->setUndoRedoEnabled(true);
-}
-
-/**
- * Overrides. Catches the TAB and Ctrl+TAB combinations.
- * @param event
- */
-void PyConsole_EnhEditor::keyPressEvent ( QKeyEvent* event)
-{
-  // check if <Ctrl> is pressed
-  bool ctrlPressed = event->modifiers() & Qt::ControlModifier;
-  // check if <Shift> is pressed
-  bool shftPressed = event->modifiers() & Qt::ShiftModifier;
-
-  if (event->key() == Qt::Key_Tab && !shftPressed)
-    {
-      if (!ctrlPressed)
-        handleTab();
-      else
-        {
-          clearCompletion();
-          handleBackTab();
-        }
-      PyConsole_Editor::keyPressEvent(event);
-    }
-  else
-    {
-      // If ctrl is not pressed (and sth else is pressed with it),
-      // or if ctrl is not pressed alone
-      if (!ctrlPressed || (ctrlPressed && event->key() != Qt::Key_Control))
-        {
-          clearCompletion();
-          _cursor_pos = -1;
-        }
-      // Discard ctrl pressed alone:
-      if (event->key() != Qt::Key_Control)
-        PyConsole_Editor::keyPressEvent(event);
-    }
-}
-
-/**
- * Whenever the mouse is clicked, clear the completion.
- * @param e
- */
-void PyConsole_EnhEditor::mousePressEvent(QMouseEvent* e)
-{
-  clearCompletion();
-  _cursor_pos = -1;
-  PyConsole_Editor::mousePressEvent(e);
-}
-
-/**
- * Clear in the editor the block of text displayed after having hit <TAB>.
- */
-void PyConsole_EnhEditor::clearCompletion()
-{
-  // Delete completion text if present
-  if (_tab_mode)
-    {
-      // Remove completion display
-      document()->undo();
-      // Remove trailing line return:
-      QTextCursor tc(textCursor());
-      tc.setPosition(document()->characterCount()-1);
-      setTextCursor(tc);
-      textCursor().deletePreviousChar();
-      // TODO: before wait for any TAB event to be completed
-      if ( myInterp ) 
-       myInterp->clearCompletion();
-    }
-  _tab_mode = false;
-}
-
-/**
- * Handle the sequence of events after having hit <TAB>
- */
-void PyConsole_EnhEditor::handleTab()
-{
-  if (_tab_mode)
-    {
-      // Already tab mode - nothing to do !
-      return;
-    }
-
-  QTextCursor cursor(textCursor());
-
-  // Cursor at end of input
-  cursor.movePosition(QTextCursor::End);
-  setTextCursor(cursor);
-
-  // Save cursor position if needed
-  if (_cursor_pos == -1)
-    _cursor_pos = textCursor().position();
-
-  // get last line
-  QTextBlock par = document()->end().previous();
-  if ( !par.isValid() ) return;
-
-  // Switch to completion mode
-  _tab_mode = true;
-
-  QString cmd = par.text().mid(promptSize());
-
-  // Post completion request
-  // Editor will be informed via a custom event that completion has been run
-  PyInterp_Request* req = createTabRequest(cmd);
-  PyInterp_Dispatcher::Get()->Exec(req);
-}
-
-/**
- * Handles what happens after hitting Ctrl-TAB
- */
-void PyConsole_EnhEditor::handleBackTab()
-{
-  QTextCursor cursor(textCursor());
-
-  if (_cursor_pos == -1)
-    {
-      // Invalid cursor position - we can't do anything:
-      return;
-    }
-  // Ensure cursor is at the end of command line
-  cursor.setPosition(_cursor_pos);
-  cursor.movePosition(QTextCursor::EndOfLine);
-  //setCursor(cursor);
-
-  // Delete last completed text
-  int i = cursor.position() - _cursor_pos;
-  cursor.movePosition(QTextCursor::Left, QTextCursor::KeepAnchor, i);
-  cursor.removeSelectedText();
-  _cursor_pos = -1;
-}
-
-/**
- * Create the Python requested that will be posted to the interpreter to
- * get the completions.
- * @param input line typed by the user at the time TAB was hit
- * @return a CompletionCommand
- * @sa CompletionCommand
- */
-PyInterp_Request* PyConsole_EnhEditor::createTabRequest( const QString& input )
-{
-  // Parse input to extract on what part the dir() has to be executed
-  QString input2(input);
-
-  // Split up to the last syntaxical separator
-  int lastSp = -1;
-  for (std::vector<QString>::const_iterator i = SEPARATORS.begin(); i != SEPARATORS.end(); i++)
-    {
-      int j = input2.lastIndexOf(*i);
-      if (j > lastSp)
-        lastSp = j;
-    }
-  if (lastSp >= 0)
-    input2 = input.mid(lastSp+1);
-
-  // Detect a qualified name (with a point)
-  int lastPt = input2.lastIndexOf(QString("."));
-
-  // Split the 2 surrounding parts of the qualified name
-  if (lastPt != -1)
-    {
-      _compl_before_point = input2.left(lastPt);
-      _compl_after_point = input2.mid(lastPt+1);
-    }
-  else
-    {
-      // No point found - do a global matching -
-      // (the following will call dir() with an empty string)
-      _compl_after_point = input2;
-      _compl_before_point = QString("");
-    }
-
-  return new CompletionCommand( myInterp, _compl_before_point,
-                               _compl_after_point, this, isSync() );
-}
-
-/**
- * Format completion results - this is where we should create 3 columns etc ...
- * @param matches list of possible completions
- * @param result return value
- */
-void PyConsole_EnhEditor::formatCompletion(const 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_EnhEditor::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_Editor::customEvent(event);
-      // If we are in multi_paste_mode, process the next item:
-      multiLineProcessNextLine();
-      break;
-    }
-    default:
-    {
-      PyConsole_Editor::customEvent( event );
-      break;
-    }
-  }
-}
-
-/**
- * Extract the common leading part of all strings in matches.
- * @param matches
- * @param result
- */
-void PyConsole_EnhEditor::extractCommon(const 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_EnhEditor::formatDocHTML(const QString & doc) const
-{
-  QString templ = QString("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" ") +
-      QString(" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n ") +
-      QString("<html><head><meta name=\"qrichtext\" content=\"1\" /> ") +
-      QString("<style type=\"text/css\">\np, li { white-space: pre-wrap; }\n</style> ") +
-      QString("</head><body style=\" font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;\">\n") +
-      QString("<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">") +
-      QString("<span style=\" font-weight:600; color:#0000ff;\">%1</span></p>") +
-      QString("<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">%2</p>") +
-      QString("</body></html>");
-
-  QString fst, rest("");
-
-  // Extract first line of doc
-  int idx = doc.indexOf("\n");
-  if (idx > 0)
-    {
-      fst = doc.left(idx);
-      rest = doc.mid(idx+1);
-    }
-  else
-    {
-      fst = doc;
-    }
-
-  fst = fst.replace("\n", " ");
-  rest = rest.replace("\n", " ");
-  return templ.arg(fst).arg(rest);
-}
-
-/**
- * Handle properly multi-line pasting. Qt4 doc recommends overriding this function.
- * If the pasted text doesn't contain a line return, no special treatment is done.
- * @param source
- */
-void PyConsole_EnhEditor::insertFromMimeData(const QMimeData* source)
-{
-  if (_multi_line_paste)
-    return;
-
-  if (source->hasText())
-    {
-      QString s = source->text();
-      if (s.contains("\n"))
-        multilinePaste(s);
-      else
-        PyConsole_Editor::insertFromMimeData(source);
-    }
-  else
-    {
-      PyConsole_Editor::insertFromMimeData(source);
-    }
-}
-
-
-void PyConsole_EnhEditor::multilinePaste(const QString & s)
+     PyConsole_EnhEditorBase(interp, parent)
 {
-  // Turn on multi line pasting mode
-  _multi_line_paste = true;
-
-  // Split the string:
-  QString s2 = s;
-  s2.replace("\r", ""); // Windows string format converted to Unix style
-
-  QStringList lst = s2.split(QChar('\n'), QString::KeepEmptyParts);
-
-  // Perform the proper paste operation for the first line to handle the case where
-  // sth was already there:
-  QMimeData source;
-  source.setText(lst[0]);
-  PyConsole_Editor::insertFromMimeData(&source);
-
-  // Prepare what will have to be executed after the first line:
-  _multi_line_content = std::queue<QString>();
-  for (int i = 1; i < lst.size(); ++i)
-    _multi_line_content.push(lst[i]);
-
-  // Trigger the execution of the first (mixed) line
-  handleReturn();
-
-  // See customEvent() and multiLineProcessNext() for the rest of the handling.
-}
-
-/**
- * Process the next line in the queue of a multiple copy/paste:
- */
-void PyConsole_EnhEditor::multiLineProcessNextLine()
-{
-  if (!_multi_line_paste)
-    return;
-
-  QString line(_multi_line_content.front());
-  _multi_line_content.pop();
-  if (!_multi_line_content.size())
-    {
-      // last line in the queue, just paste it
-      addText(line, false, false);
-      _multi_line_paste = false;
-    }
-  else
-    {
-      // paste the line and simulate a <RETURN> key stroke
-      addText(line, false, false);
-      handleReturn();
-    }
 }
index f505066d32aa1f94a792fa773f7f2974868a38b7..ea20d1b3f03447cbd23a5d9edecc024b18733771 100644 (file)
@@ -23,7 +23,7 @@
 #define PYCONSOLE_ENHEDITOR_H_
 
 #include "PyConsole.h"
-#include "PyConsole_Editor.h"
+#include "PyConsole_EnhEditorBase.h"
 
 #include <QObject>
 #include <queue>
 /**
  * Enhanced Python editor handling tab completion.
  */
-class PYCONSOLE_EXPORT PyConsole_EnhEditor: public PyConsole_Editor
+class PYCONSOLE_EXPORT PyConsole_EnhEditor : public PyConsole_EnhEditorBase
 {
   Q_OBJECT;
-
 public:
   PyConsole_EnhEditor(PyConsole_Interp* interp, QWidget* parent = 0);
   virtual ~PyConsole_EnhEditor() {}
-
-signals:
-  /**
-   * Signal emitted by the editor widget when the doc string should be updated.
-   * @param doc a HTML block with the formatted doc string.
-   * TODO: for now this signal is left uncaught.
-   */
-  void updateDoc(QString doc);
-
-protected:
-  /** List of separators identifying the last parsable token for completion */
-  static const std::vector<QString> SEPARATORS;
-
-  /** Maximum number of completions shown at once */
-  static const int MAX_COMPLETIONS = 70;
-
-  /** Are we in completion mode */
-  bool _tab_mode;
-
-  /** String on which the dir() comamnd is executed */
-  QString _compl_before_point;
-  /** String on which the results of the dir() are matched */
-  QString _compl_after_point;
-
-  /** Cursor position when <TAB> is hit */
-  int _cursor_pos;
-
-  /** Are we currently pasting several lines */
-  bool _multi_line_paste;
-
-  /** Queue of lines being pasted */
-  std::queue<QString> _multi_line_content;
-
-  // Overrides:
-  virtual void   keyPressEvent ( QKeyEvent* event);
-  virtual void   customEvent( QEvent* event);
-  virtual void   mousePressEvent( QMouseEvent* event );
-  virtual void   insertFromMimeData(const QMimeData* source);
-
-  virtual PyInterp_Request* createTabRequest( const QString& input );
-  virtual void handleTab();
-  virtual void handleBackTab();
-  virtual void clearCompletion();
-  virtual void formatCompletion(const 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_ENHEDITOR_H_ */
diff --git a/src/PyConsole/PyConsole_EnhInterp.cxx b/src/PyConsole/PyConsole_EnhInterp.cxx
deleted file mode 100644 (file)
index bb32304..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-// Copyright (C) 2007-2015  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 b8fb04a..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (C) 2007-2015  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_ */
diff --git a/src/PyConsole/PyConsole_Event.cxx b/src/PyConsole/PyConsole_Event.cxx
deleted file mode 100644 (file)
index aaeb257..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (C) 2007-2015  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
-//
-//  Author : Vadim SANDLER (Open CASCADE S.A.S), Adrien Bruneton (CEA/DEN)
-
-#include "PyConsole_Event.h"
diff --git a/src/PyConsole/PyConsole_Event.h b/src/PyConsole/PyConsole_Event.h
deleted file mode 100644 (file)
index 6ec1d51..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright (C) 2007-2015  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
-//
-//  Author : Vadim SANDLER (Open CASCADE S.A.S), Adrien Bruneton (CEA/DEN)
-
-#ifndef PYCONSOLE_EVENT_H
-#define PYCONSOLE_EVENT_H
-
-#include "PyConsole.h"
-
-#include <QEvent>
-#include <QString>
-
-/*!
-  \class PrintEvent
-  \brief Python command output backend event.
-  \internal
-*/
-class PrintEvent : public QEvent
-{
-public:
-  static const int EVENT_ID = 65432;
-
-  /*!
-    \brief Constructor
-    \param c message text (python trace)
-    \param isError default to false - if true indicates that an error is being printed.
-  */
-  PrintEvent( const QString& c, bool isError = false) :
-    QEvent( (QEvent::Type)EVENT_ID ), myText( c ), errorFlag(isError)
-  {}
-
-  /*!
-    \brief Get message
-    \return message text (python trace)
-  */
-  QString text() const { return myText; }
-
-  /**
-   * @return true if this is an error message
-   */
-  bool isError() const { return errorFlag; }
-
-protected:
-  QString myText; //!< Event message (python trace)
-
-  /** Set to true if an error msg is to be displayed */
-  bool errorFlag;
-};
-
-#endif // PYCONSOLE_EVENT_H
diff --git a/src/PyConsole/PyConsole_Interp.cxx b/src/PyConsole/PyConsole_Interp.cxx
deleted file mode 100644 (file)
index ca459b5..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright (C) 2007-2015  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_Interp.cxx
-//  Author : Nicolas REJNERI, Adrien BRUNETON
-
-#include "PyConsole_Interp.h"
-
-/*!
-  \class PyConsole_Interp
-  \brief Python interpreter to be embedded to the SALOME study's GUI.
-
-  There is only one Python interpreter for the whole SALOME environment.
-
-  Call the initialize() method defined in the base class PyInterp_Interp,
-  to initialize the interpreter after instance creation.
-
-  The method initialize() calls virtuals methods
-  - initPython()  to initialize global Python interpreter
-  - initContext() to initialize interpreter internal context
-  - initRun()     to prepare interpreter for running commands
-*/
-
-/*!
-  \brief Constructor.
-
-  Creates new python interpreter.
-*/
-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)
-*/
-int PyConsole_Interp::beforeRun()
-{
-  return PyRun_SimpleString("__builtins__.__IN_SALOME_GUI_CONSOLE=True");
-}
-int PyConsole_Interp::afterRun()
-{
-  return PyRun_SimpleString("__builtins__.__IN_SALOME_GUI_CONSOLE=False");
-}
-
-QStringList PyConsole_Interp::getLastMatches() const
-{
-  return QStringList();
-}
-
-QString PyConsole_Interp::getDocStr() const
-{
-  return QString();
-}
-
-int PyConsole_Interp::runDirCommand(const QString&, const QString& )
-{
-  return 0;
-}
-
-void PyConsole_Interp::clearCompletion()
-{
-}
diff --git a/src/PyConsole/PyConsole_Interp.h b/src/PyConsole/PyConsole_Interp.h
deleted file mode 100644 (file)
index 1aac736..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (C) 2007-2015  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_Interp.h
-//  Author : Nicolas REJNERI, Adrien BRUNETON
-
-#ifndef PYCONSOLE_INTERP_H
-#define PYCONSOLE_INTERP_H
-
-#include "PyConsole.h"
-#include "PyInterp_Interp.h"   /// !!! WARNING !!! THIS INCLUDE MUST BE VERY FIRST !!!
-
-#include <QStringList>
-
-class PYCONSOLE_EXPORT PyConsole_Interp : public PyInterp_Interp
-{
-public:
-  PyConsole_Interp();
-  ~PyConsole_Interp();
-
-  virtual int afterRun();
-  virtual int beforeRun();
-
-  virtual QStringList getLastMatches() const;
-  virtual QString getDocStr() const;
-
-  virtual int runDirCommand(const QString&, const QString&);
-  virtual void clearCompletion();
-};
-
-#endif // PYCONSOLE_INTERP_H
diff --git a/src/PyConsole/PyConsole_Request.cxx b/src/PyConsole/PyConsole_Request.cxx
deleted file mode 100644 (file)
index 5c67b8b..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright (C) 2007-2015  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: 3 avr. 2013
-
-#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 )
-  : 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()
-{
-  if ( myCommand != "" )
-  {
-    int ret = getInterp()->run( myCommand.toLatin1().data() );
-    if ( ret < 0 )
-      myState = PyInterp_Event::ES_ERROR;
-    else if ( ret > 0 )
-      myState = PyInterp_Event::ES_INCOMPLETE;
-  }
-}
-
-/**
- * Create the event indicating the status of the request execution.
- * @return a QEvent
- */
-QEvent* ExecCommand::createEvent()
-{
-  if ( IsSync() )
-    QCoreApplication::sendPostedEvents( listener(), PrintEvent::EVENT_ID );
-  return new PyInterp_Event( myState, this );
-}
-
-
-/*!
-  Constructor.
-  Creates a new python completion request.
-  \param theInterp   python interpreter
-  \param input  string containing the dir() command to be executed
-  \param startMatch  part to be matched with the results of the dir() command
-  \param theListener widget to get the notification messages
-  \param sync        if True the request is processed synchronously
-*/
-CompletionCommand::CompletionCommand( PyInterp_Interp*   theInterp,
-                                     const QString&     theInput,
-                                     const QString&     theStartMatch,
-                                     QObject*           theListener,
-                                     bool               theSync )
-  : PyInterp_LockRequest( theInterp, theListener, theSync ),
-    _tabSuccess(false), _dirArg(theInput), _startMatch(theStartMatch)
-{}
-
-/**
- * Execute the completion command by wrapping the runDirCommand() of the
- * embedded enhanced interpreter.
- */
-void CompletionCommand::execute()
-{
-  int ret = static_cast<PyConsole_Interp*>(getInterp())->runDirCommand( _dirArg,  _startMatch );
-  _tabSuccess = ret == 0;
-}
-
-/**
- * Create the event indicating the return value of the completion command.
- * @return
- */
-QEvent* CompletionCommand::createEvent()
-{
-  int typ = _tabSuccess ? PyInterp_Event::ES_TAB_COMPLETE_OK : PyInterp_Event::ES_TAB_COMPLETE_ERR;
-  return new PyInterp_Event( typ, this);
-}
diff --git a/src/PyConsole/PyConsole_Request.h b/src/PyConsole/PyConsole_Request.h
deleted file mode 100644 (file)
index a0ed598..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright (C) 2007-2015  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: 3 avr. 2013
-
-
-#ifndef PYCONSOLE_REQUEST_H_
-#define PYCONSOLE_REQUEST_H_
-
-#include "PyInterp_Request.h"
-
-#include <vector>
-#include <QString>
-#include <QEvent>
-
-class PyInterp_Interp;
-
-/*!
-  \class ExecCommand
-  \brief Python command execution request.
-  \internal
-*/
-class ExecCommand : public PyInterp_LockRequest
-{
-public:
-  /*!
-    \brief Constructor.
-
-    Creates new python command execution request.
-    \param theInterp   python interpreter
-    \param theCommand  python command
-    \param theListener widget to get the notification messages
-    \param sync        if True the request is processed synchronously
-  */
-  ExecCommand( PyInterp_Interp*        theInterp,
-               const QString&          theCommand,
-               QObject*                theListener,
-               bool                    theSync = false );
-
-protected:
-  /*!
-    \brief Execute the python command in the interpreter and
-           get its execution status.
-  */
-  virtual void execute();
-
-  /*!
-    \brief Create and return a notification event.
-    \return new notification event
-  */
-  virtual QEvent* createEvent();
-
-private:
-  QString myCommand;   //!< Python command
-  int     myState;     //!< Python command execution status
-};
-
-class CompletionCommand : public PyInterp_LockRequest
-{
-public:
-  CompletionCommand( PyInterp_Interp*     theInterp,
-                    const QString&       theInput,
-                    const QString&       theStartMatch,
-                    QObject*             theListener,
-                    bool                 theSync = false );
-
-
-protected:
-  /** List of separators identifying the last parsable token for completion */
-  static const std::vector<QString> SEPARATORS;
-
-  /** String to be passed to the dir() command */
-  QString _dirArg;
-  /** Begining of the command (as typed by the user) */
-  QString _startMatch;
-  /** was the completion command successful */
-  bool _tabSuccess;
-
-  virtual void execute();
-  virtual QEvent* createEvent();
-};
-
-#endif /* PYCONSOLE_REQUEST_H_ */
diff --git a/src/PyConsole/resources/PyConsole_msg_en.ts b/src/PyConsole/resources/PyConsole_msg_en.ts
deleted file mode 100644 (file)
index f8ce305..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE TS>
-<TS version="2.0" language="en_US">
-<context>
-    <name>PyConsole_ConsoleBase</name>
-    <message>
-        <location filename="../PyConsole_ConsoleBase.cxx" line="216"/>
-        <source>EDIT_COPY_CMD</source>
-        <translation>&amp;Copy</translation>
-    </message>
-    <message>
-        <location filename="../PyConsole_ConsoleBase.cxx" line="221"/>
-        <source>EDIT_PASTE_CMD</source>
-        <translation>&amp;Paste</translation>
-    </message>
-    <message>
-        <location filename="../PyConsole_ConsoleBase.cxx" line="226"/>
-        <source>EDIT_CLEAR_CMD</source>
-        <translation>Clea&amp;r</translation>
-    </message>
-    <message>
-        <location filename="../PyConsole_ConsoleBase.cxx" line="231"/>
-        <source>EDIT_SELECTALL_CMD</source>
-        <translation>Select &amp;All</translation>
-    </message>
-    <message>
-        <source>EDIT_DUMPCOMMANDS_CMD</source>
-        <translation>D&amp;ump Commands</translation>
-    </message>
-    <message>
-      <source>EDIT_STARTLOG_CMD</source>
-        <translation>Start &amp;Log</translation>
-    </message>
-    <message>
-      <source>EDIT_STOPLOG_CMD</source>
-        <translation>Stop &amp;Log</translation>
-    </message>
-</context>
-<context>
-    <name>PyConsole_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/PyConsole/resources/PyConsole_msg_fr.ts b/src/PyConsole/resources/PyConsole_msg_fr.ts
deleted file mode 100755 (executable)
index bab57bf..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE TS>
-<TS version="2.0" language="fr_FR">
-<context>
-    <name>PyConsole_ConsoleBase</name>
-    <message>
-        <location filename="../PyConsole_ConsoleBase.cxx" line="216"/>
-        <source>EDIT_COPY_CMD</source>
-        <translation>&amp;Copier</translation>
-    </message>
-    <message>
-        <location filename="../PyConsole_ConsoleBase.cxx" line="221"/>
-        <source>EDIT_PASTE_CMD</source>
-        <translation>C&amp;oller</translation>
-    </message>
-    <message>
-        <location filename="../PyConsole_ConsoleBase.cxx" line="226"/>
-        <source>EDIT_CLEAR_CMD</source>
-        <translation>&amp;Effacer</translation>
-    </message>
-    <message>
-        <location filename="../PyConsole_ConsoleBase.cxx" line="231"/>
-        <source>EDIT_SELECTALL_CMD</source>
-        <translation>&amp;Tout sélectionner</translation>
-    </message>
-    <message>
-        <source>EDIT_DUMPCOMMANDS_CMD</source>
-        <translation>&amp;Générer le script des commandes</translation>
-    </message>
-    <message>
-        <source>EDIT_STARTLOG_CMD</source>
-        <translation>Démarrer une &amp;trace</translation>
-    </message>
-    <message>
-        <source>EDIT_STOPLOG_CMD</source>
-        <translation>Arrêter la &amp;trace</translation>
-    </message>
-</context>
-<context>
-    <name>PyConsole_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/PyConsole/resources/PyConsole_msg_ja.ts b/src/PyConsole/resources/PyConsole_msg_ja.ts
deleted file mode 100644 (file)
index c36cf6a..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE TS>
-<TS version="2.0" language="ja" sourcelanguage="en">
-  <context>
-    <name>PyConsole_ConsoleBase</name>
-    <message>
-      <location filename="../PyConsole_ConsoleBase.cxx" line="216"/>
-      <source>EDIT_COPY_CMD</source>
-      <translation>コピー(&amp;C)</translation>
-    </message>
-    <message>
-      <location filename="../PyConsole_ConsoleBase.cxx" line="221"/>
-      <source>EDIT_PASTE_CMD</source>
-      <translation>貼り付け(&amp;P)</translation>
-    </message>
-    <message>
-      <location filename="../PyConsole_ConsoleBase.cxx" line="226"/>
-      <source>EDIT_CLEAR_CMD</source>
-      <translation>削除(&amp;r)</translation>
-    </message>
-    <message>
-      <location filename="../PyConsole_ConsoleBase.cxx" line="231"/>
-      <source>EDIT_SELECTALL_CMD</source>
-      <translation>すべて選択します。(&amp;A)</translation>
-    </message>
-    <message>
-      <source>EDIT_DUMPCOMMANDS_CMD</source>
-      <translation>スクリプト コマンドを生成します。(&amp;u)</translation>
-    </message>
-    <message>
-      <source>EDIT_STARTLOG_CMD</source>
-      <translation>ログの開始 (&amp;L)</translation>
-    </message>
-    <message>
-      <source>EDIT_STOPLOG_CMD</source>
-      <translation>ログの停止 (&amp;L)</translation>
-    </message>
-  </context>
-  <context>
-    <name>PyConsole_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>
diff --git a/src/PyConsoleBase/CMakeLists.txt b/src/PyConsoleBase/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..d70defa
--- /dev/null
@@ -0,0 +1,97 @@
+# Copyright (C) 2012-2015  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(UseQtExt)
+
+# --- options ---
+
+# additional include directories
+INCLUDE_DIRECTORIES(
+  ${QT_INCLUDES}
+  ${PYTHON_INCLUDE_DIRS}
+  ${PROJECT_SOURCE_DIR}/src/SUITT
+  ${PROJECT_SOURCE_DIR}/src/PyConsoleBase
+  ${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} PyInterp Event suitt)
+
+# --- headers ---
+
+# header files / to be processed by moc
+SET(_moc_HEADERS
+  PyConsole_ConsoleBase.h
+  PyConsole_EditorBase.h
+  PyConsole_EnhEditorBase.h
+)
+
+# header files / no moc processing
+SET(_other_HEADERS
+  PyConsoleBase.h
+  PyConsole_EnhInterpBase.h
+  PyConsole_Event.h
+  PyConsole_Interp.h
+  PyConsole_Request.h
+)
+
+# header files / to install
+SET(PyConsoleBase_HEADERS ${_moc_HEADERS} ${_other_HEADERS})
+
+# --- resources ---
+
+# resource files / to be processed by lrelease
+SET(_ts_RESOURCES
+  resources/PyConsole_msg_en.ts
+  resources/PyConsole_msg_fr.ts
+  resources/PyConsole_msg_ja.ts
+)
+
+# --- sources ---
+
+# sources / moc wrappings
+QT_WRAP_MOC(_moc_SOURCES ${_moc_HEADERS})
+
+# sources / static
+SET(_other_SOURCES
+  PyConsole_ConsoleBase.cxx
+  PyConsole_EnhInterp.cxx
+  PyConsole_Event.cxx
+  PyConsole_Interp.cxx
+  PyConsole_Request.cxx
+  PyConsole_EditorBase.cxx
+  PyConsole_EnhEditorBase.cxx
+)
+
+# sources / to compile
+SET(PyConsoleBase_SOURCES ${_other_SOURCES} ${_moc_SOURCES})
+
+# --- rules ---
+
+ADD_LIBRARY(PyConsoleBase ${PyConsoleBase_SOURCES})
+TARGET_LINK_LIBRARIES(PyConsoleBase ${_link_LIBRARIES})
+INSTALL(TARGETS PyConsoleBase EXPORT ${PROJECT_NAME}TargetGroup DESTINATION ${SALOME_INSTALL_LIBS})
+
+INSTALL(FILES ${PyConsoleBase_HEADERS} DESTINATION ${SALOME_INSTALL_HEADERS})
+QT_INSTALL_TS_RESOURCES("${_ts_RESOURCES}" "${SALOME_GUI_INSTALL_RES_DATA}")
+
diff --git a/src/PyConsoleBase/PyConsoleBase.h b/src/PyConsoleBase/PyConsoleBase.h
new file mode 100644 (file)
index 0000000..fcef126
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright (C) 2007-2015  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   : PyConsoleBase.h
+// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
+//
+#if !defined ( PYCONSOLEBASE_H )
+#define PYCONSOLEBASE_H
+
+// ========================================================
+// set dllexport type for Win platform 
+#ifdef WIN32
+#  if defined PYCONSOLEBASE_EXPORTS || defined PyConsoleBase_EXPORTS
+#    define PYCONSOLEBASE_EXPORT __declspec(dllexport)
+#  else
+#    define PYCONSOLEBASE_EXPORT __declspec(dllimport)
+#  endif
+#else   // WIN32
+#  define PYCONSOLEBASE_EXPORT
+#endif  // WIN32
+
+// ========================================================
+// avoid warning messages
+#ifdef WIN32
+#pragma warning (disable : 4786)
+#pragma warning (disable : 4251)
+#endif
+
+#endif // PYCONSOLEBASE_H
diff --git a/src/PyConsoleBase/PyConsole_ConsoleBase.cxx b/src/PyConsoleBase/PyConsole_ConsoleBase.cxx
new file mode 100644 (file)
index 0000000..3e49f2f
--- /dev/null
@@ -0,0 +1,349 @@
+// Copyright (C) 2007-2015  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 <QAction>
+#include <QApplication>
+#include <QClipboard>
+#include <QEvent>
+#include <QMenu>
+#include <QVBoxLayout>
+
+/*!
+  \brief Constructor.
+
+  Creates new python console widget.
+  \param parent parent widget
+  \param interp python interpreter
+*/
+PyConsole_ConsoleBase::PyConsole_ConsoleBase( QWidget* parent, PyConsole_Interp* interp )
+: QWidget( parent )
+{
+  PyConsole_Interp* anInterp = interp ? interp : new PyConsole_Interp();
+  
+  // initialize Python interpretator
+  anInterp->initialize();
+  
+  // create editor console
+  QVBoxLayout* lay = new QVBoxLayout( this );
+  lay->setMargin( 0 );
+  myEditor = new PyConsole_EditorBase( 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();
+}
+
+/**
+ * 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* anInterp = interp ? interp : new PyConsole_EnhInterp();
+
+  // initialize Python interpretator
+  anInterp->initialize();
+
+  // create editor console
+  QVBoxLayout* lay = new QVBoxLayout( this );
+  lay->setMargin( 0 );
+  myEditor = new PyConsole_EnhEditorBase( anInterp, this );
+  char* synchronous = getenv("PYTHON_CONSOLE_SYNC");
+  if (synchronous && atoi(synchronous))
+  {
+      myEditor->setIsSync(true);
+  }
+  myEditor->viewport()->installEventFilter( this );
+  lay->addWidget( myEditor );
+
+  createActions();
+}
diff --git a/src/PyConsoleBase/PyConsole_ConsoleBase.h b/src/PyConsoleBase/PyConsole_ConsoleBase.h
new file mode 100644 (file)
index 0000000..615400d
--- /dev/null
@@ -0,0 +1,106 @@
+// Copyright (C) 2007-2015  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 "PyConsoleBase.h"
+
+#include <QWidget>
+#include <QMap>
+
+class PyConsole_Interp;
+class PyConsole_EditorBase;
+
+class PYCONSOLEBASE_EXPORT PyConsole_ConsoleBase : 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_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();
+
+protected:
+  void                createActions();
+  void                updateActions();
+
+  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 PYCONSOLEBASE_EXPORT PyConsole_EnhConsoleBase : public PyConsole_ConsoleBase
+{
+  Q_OBJECT
+
+public:
+  PyConsole_EnhConsoleBase( QWidget* parent, PyConsole_Interp* interp = 0 );
+  virtual ~PyConsole_EnhConsoleBase() {}
+};
+
+#endif // PYCONSOLE_CONSOLEBASE_H
diff --git a/src/PyConsoleBase/PyConsole_EditorBase.cxx b/src/PyConsoleBase/PyConsole_EditorBase.cxx
new file mode 100644 (file)
index 0000000..cf95a29
--- /dev/null
@@ -0,0 +1,1217 @@
+// Copyright (C) 2007-2015  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 "SUIT_FileValidator.h"
+#include "SUIT_MessageBox.h"
+#include "Qtxx.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>
+
+//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 ( Qtxx::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 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 "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/PyConsoleBase/PyConsole_EditorBase.h b/src/PyConsoleBase/PyConsole_EditorBase.h
new file mode 100644 (file)
index 0000000..288ad36
--- /dev/null
@@ -0,0 +1,106 @@
+// Copyright (C) 2007-2015  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 "PyConsoleBase.h"
+
+#include <QTextEdit>
+
+class PyConsole_Interp;
+class PyInterp_Request;
+class QEventLoop;
+
+class PYCONSOLEBASE_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);
+    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 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/PyConsoleBase/PyConsole_EnhEditorBase.cxx b/src/PyConsoleBase/PyConsole_EnhEditorBase.cxx
new file mode 100644 (file)
index 0000000..54bf7fd
--- /dev/null
@@ -0,0 +1,491 @@
+// Copyright (C) 2007-2015  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 "PyConsoleBase.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/PyConsoleBase/PyConsole_EnhEditorBase.h b/src/PyConsoleBase/PyConsole_EnhEditorBase.h
new file mode 100644 (file)
index 0000000..6c91a3d
--- /dev/null
@@ -0,0 +1,95 @@
+// Copyright (C) 2007-2015  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 "PyConsoleBase.h"
+#include "PyConsole_EditorBase.h"
+
+#include <QObject>
+#include <queue>
+
+/**
+ * Enhanced Python editor handling tab completion.
+ */
+class PYCONSOLEBASE_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/PyConsoleBase/PyConsole_EnhInterp.cxx b/src/PyConsoleBase/PyConsole_EnhInterp.cxx
new file mode 100644 (file)
index 0000000..eab44af
--- /dev/null
@@ -0,0 +1,177 @@
+// Copyright (C) 2007-2015  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 "PyConsoleBase.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/PyConsoleBase/PyConsole_EnhInterp.h b/src/PyConsoleBase/PyConsole_EnhInterp.h
new file mode 100644 (file)
index 0000000..57a483b
--- /dev/null
@@ -0,0 +1,63 @@
+// Copyright (C) 2007-2015  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 "PyConsoleBase.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 PYCONSOLEBASE_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_ */
diff --git a/src/PyConsoleBase/PyConsole_Event.cxx b/src/PyConsoleBase/PyConsole_Event.cxx
new file mode 100644 (file)
index 0000000..aaeb257
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright (C) 2007-2015  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
+//
+//  Author : Vadim SANDLER (Open CASCADE S.A.S), Adrien Bruneton (CEA/DEN)
+
+#include "PyConsole_Event.h"
diff --git a/src/PyConsoleBase/PyConsole_Event.h b/src/PyConsoleBase/PyConsole_Event.h
new file mode 100644 (file)
index 0000000..28db824
--- /dev/null
@@ -0,0 +1,69 @@
+// Copyright (C) 2007-2015  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
+//
+//  Author : Vadim SANDLER (Open CASCADE S.A.S), Adrien Bruneton (CEA/DEN)
+
+#ifndef PYCONSOLE_EVENT_H
+#define PYCONSOLE_EVENT_H
+
+#include "PyConsoleBase.h"
+
+#include <QEvent>
+#include <QString>
+
+/*!
+  \class PrintEvent
+  \brief Python command output backend event.
+  \internal
+*/
+class PrintEvent : public QEvent
+{
+public:
+  static const int EVENT_ID = 65432;
+
+  /*!
+    \brief Constructor
+    \param c message text (python trace)
+    \param isError default to false - if true indicates that an error is being printed.
+  */
+  PrintEvent( const QString& c, bool isError = false) :
+    QEvent( (QEvent::Type)EVENT_ID ), myText( c ), errorFlag(isError)
+  {}
+
+  /*!
+    \brief Get message
+    \return message text (python trace)
+  */
+  QString text() const { return myText; }
+
+  /**
+   * @return true if this is an error message
+   */
+  bool isError() const { return errorFlag; }
+
+protected:
+  QString myText; //!< Event message (python trace)
+
+  /** Set to true if an error msg is to be displayed */
+  bool errorFlag;
+};
+
+#endif // PYCONSOLE_EVENT_H
diff --git a/src/PyConsoleBase/PyConsole_Interp.cxx b/src/PyConsoleBase/PyConsole_Interp.cxx
new file mode 100644 (file)
index 0000000..ca459b5
--- /dev/null
@@ -0,0 +1,93 @@
+// Copyright (C) 2007-2015  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_Interp.cxx
+//  Author : Nicolas REJNERI, Adrien BRUNETON
+
+#include "PyConsole_Interp.h"
+
+/*!
+  \class PyConsole_Interp
+  \brief Python interpreter to be embedded to the SALOME study's GUI.
+
+  There is only one Python interpreter for the whole SALOME environment.
+
+  Call the initialize() method defined in the base class PyInterp_Interp,
+  to initialize the interpreter after instance creation.
+
+  The method initialize() calls virtuals methods
+  - initPython()  to initialize global Python interpreter
+  - initContext() to initialize interpreter internal context
+  - initRun()     to prepare interpreter for running commands
+*/
+
+/*!
+  \brief Constructor.
+
+  Creates new python interpreter.
+*/
+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)
+*/
+int PyConsole_Interp::beforeRun()
+{
+  return PyRun_SimpleString("__builtins__.__IN_SALOME_GUI_CONSOLE=True");
+}
+int PyConsole_Interp::afterRun()
+{
+  return PyRun_SimpleString("__builtins__.__IN_SALOME_GUI_CONSOLE=False");
+}
+
+QStringList PyConsole_Interp::getLastMatches() const
+{
+  return QStringList();
+}
+
+QString PyConsole_Interp::getDocStr() const
+{
+  return QString();
+}
+
+int PyConsole_Interp::runDirCommand(const QString&, const QString& )
+{
+  return 0;
+}
+
+void PyConsole_Interp::clearCompletion()
+{
+}
diff --git a/src/PyConsoleBase/PyConsole_Interp.h b/src/PyConsoleBase/PyConsole_Interp.h
new file mode 100644 (file)
index 0000000..34f251d
--- /dev/null
@@ -0,0 +1,49 @@
+// Copyright (C) 2007-2015  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_Interp.h
+//  Author : Nicolas REJNERI, Adrien BRUNETON
+
+#ifndef PYCONSOLE_INTERP_H
+#define PYCONSOLE_INTERP_H
+
+#include "PyConsoleBase.h"
+#include "PyInterp_Interp.h"   /// !!! WARNING !!! THIS INCLUDE MUST BE VERY FIRST !!!
+
+#include <QStringList>
+
+class PYCONSOLEBASE_EXPORT PyConsole_Interp : public PyInterp_Interp
+{
+public:
+  PyConsole_Interp();
+  ~PyConsole_Interp();
+
+  virtual int afterRun();
+  virtual int beforeRun();
+
+  virtual QStringList getLastMatches() const;
+  virtual QString getDocStr() const;
+
+  virtual int runDirCommand(const QString&, const QString&);
+  virtual void clearCompletion();
+};
+
+#endif // PYCONSOLE_INTERP_H
diff --git a/src/PyConsoleBase/PyConsole_Request.cxx b/src/PyConsoleBase/PyConsole_Request.cxx
new file mode 100644 (file)
index 0000000..5c67b8b
--- /dev/null
@@ -0,0 +1,108 @@
+// Copyright (C) 2007-2015  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: 3 avr. 2013
+
+#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 )
+  : 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()
+{
+  if ( myCommand != "" )
+  {
+    int ret = getInterp()->run( myCommand.toLatin1().data() );
+    if ( ret < 0 )
+      myState = PyInterp_Event::ES_ERROR;
+    else if ( ret > 0 )
+      myState = PyInterp_Event::ES_INCOMPLETE;
+  }
+}
+
+/**
+ * Create the event indicating the status of the request execution.
+ * @return a QEvent
+ */
+QEvent* ExecCommand::createEvent()
+{
+  if ( IsSync() )
+    QCoreApplication::sendPostedEvents( listener(), PrintEvent::EVENT_ID );
+  return new PyInterp_Event( myState, this );
+}
+
+
+/*!
+  Constructor.
+  Creates a new python completion request.
+  \param theInterp   python interpreter
+  \param input  string containing the dir() command to be executed
+  \param startMatch  part to be matched with the results of the dir() command
+  \param theListener widget to get the notification messages
+  \param sync        if True the request is processed synchronously
+*/
+CompletionCommand::CompletionCommand( PyInterp_Interp*   theInterp,
+                                     const QString&     theInput,
+                                     const QString&     theStartMatch,
+                                     QObject*           theListener,
+                                     bool               theSync )
+  : PyInterp_LockRequest( theInterp, theListener, theSync ),
+    _tabSuccess(false), _dirArg(theInput), _startMatch(theStartMatch)
+{}
+
+/**
+ * Execute the completion command by wrapping the runDirCommand() of the
+ * embedded enhanced interpreter.
+ */
+void CompletionCommand::execute()
+{
+  int ret = static_cast<PyConsole_Interp*>(getInterp())->runDirCommand( _dirArg,  _startMatch );
+  _tabSuccess = ret == 0;
+}
+
+/**
+ * Create the event indicating the return value of the completion command.
+ * @return
+ */
+QEvent* CompletionCommand::createEvent()
+{
+  int typ = _tabSuccess ? PyInterp_Event::ES_TAB_COMPLETE_OK : PyInterp_Event::ES_TAB_COMPLETE_ERR;
+  return new PyInterp_Event( typ, this);
+}
diff --git a/src/PyConsoleBase/PyConsole_Request.h b/src/PyConsoleBase/PyConsole_Request.h
new file mode 100644 (file)
index 0000000..a0ed598
--- /dev/null
@@ -0,0 +1,99 @@
+// Copyright (C) 2007-2015  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: 3 avr. 2013
+
+
+#ifndef PYCONSOLE_REQUEST_H_
+#define PYCONSOLE_REQUEST_H_
+
+#include "PyInterp_Request.h"
+
+#include <vector>
+#include <QString>
+#include <QEvent>
+
+class PyInterp_Interp;
+
+/*!
+  \class ExecCommand
+  \brief Python command execution request.
+  \internal
+*/
+class ExecCommand : public PyInterp_LockRequest
+{
+public:
+  /*!
+    \brief Constructor.
+
+    Creates new python command execution request.
+    \param theInterp   python interpreter
+    \param theCommand  python command
+    \param theListener widget to get the notification messages
+    \param sync        if True the request is processed synchronously
+  */
+  ExecCommand( PyInterp_Interp*        theInterp,
+               const QString&          theCommand,
+               QObject*                theListener,
+               bool                    theSync = false );
+
+protected:
+  /*!
+    \brief Execute the python command in the interpreter and
+           get its execution status.
+  */
+  virtual void execute();
+
+  /*!
+    \brief Create and return a notification event.
+    \return new notification event
+  */
+  virtual QEvent* createEvent();
+
+private:
+  QString myCommand;   //!< Python command
+  int     myState;     //!< Python command execution status
+};
+
+class CompletionCommand : public PyInterp_LockRequest
+{
+public:
+  CompletionCommand( PyInterp_Interp*     theInterp,
+                    const QString&       theInput,
+                    const QString&       theStartMatch,
+                    QObject*             theListener,
+                    bool                 theSync = false );
+
+
+protected:
+  /** List of separators identifying the last parsable token for completion */
+  static const std::vector<QString> SEPARATORS;
+
+  /** String to be passed to the dir() command */
+  QString _dirArg;
+  /** Begining of the command (as typed by the user) */
+  QString _startMatch;
+  /** was the completion command successful */
+  bool _tabSuccess;
+
+  virtual void execute();
+  virtual QEvent* createEvent();
+};
+
+#endif /* PYCONSOLE_REQUEST_H_ */
diff --git a/src/PyConsoleBase/resources/PyConsole_msg_en.ts b/src/PyConsoleBase/resources/PyConsole_msg_en.ts
new file mode 100644 (file)
index 0000000..af33f0b
--- /dev/null
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="en_US">
+<context>
+    <name>PyConsole_ConsoleBase</name>
+    <message>
+        <location filename="../PyConsole_ConsoleBase.cxx" line="216"/>
+        <source>EDIT_COPY_CMD</source>
+        <translation>&amp;Copy</translation>
+    </message>
+    <message>
+        <location filename="../PyConsole_ConsoleBase.cxx" line="221"/>
+        <source>EDIT_PASTE_CMD</source>
+        <translation>&amp;Paste</translation>
+    </message>
+    <message>
+        <location filename="../PyConsole_ConsoleBase.cxx" line="226"/>
+        <source>EDIT_CLEAR_CMD</source>
+        <translation>Clea&amp;r</translation>
+    </message>
+    <message>
+        <location filename="../PyConsole_ConsoleBase.cxx" line="231"/>
+        <source>EDIT_SELECTALL_CMD</source>
+        <translation>Select &amp;All</translation>
+    </message>
+    <message>
+        <source>EDIT_DUMPCOMMANDS_CMD</source>
+        <translation>D&amp;ump Commands</translation>
+    </message>
+    <message>
+      <source>EDIT_STARTLOG_CMD</source>
+        <translation>Start &amp;Log</translation>
+    </message>
+    <message>
+      <source>EDIT_STOPLOG_CMD</source>
+        <translation>Stop &amp;Log</translation>
+    </message>
+</context>
+<context>
+    <name>PyConsole_EditorBase</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/PyConsoleBase/resources/PyConsole_msg_fr.ts b/src/PyConsoleBase/resources/PyConsole_msg_fr.ts
new file mode 100755 (executable)
index 0000000..bab57bf
--- /dev/null
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="fr_FR">
+<context>
+    <name>PyConsole_ConsoleBase</name>
+    <message>
+        <location filename="../PyConsole_ConsoleBase.cxx" line="216"/>
+        <source>EDIT_COPY_CMD</source>
+        <translation>&amp;Copier</translation>
+    </message>
+    <message>
+        <location filename="../PyConsole_ConsoleBase.cxx" line="221"/>
+        <source>EDIT_PASTE_CMD</source>
+        <translation>C&amp;oller</translation>
+    </message>
+    <message>
+        <location filename="../PyConsole_ConsoleBase.cxx" line="226"/>
+        <source>EDIT_CLEAR_CMD</source>
+        <translation>&amp;Effacer</translation>
+    </message>
+    <message>
+        <location filename="../PyConsole_ConsoleBase.cxx" line="231"/>
+        <source>EDIT_SELECTALL_CMD</source>
+        <translation>&amp;Tout sélectionner</translation>
+    </message>
+    <message>
+        <source>EDIT_DUMPCOMMANDS_CMD</source>
+        <translation>&amp;Générer le script des commandes</translation>
+    </message>
+    <message>
+        <source>EDIT_STARTLOG_CMD</source>
+        <translation>Démarrer une &amp;trace</translation>
+    </message>
+    <message>
+        <source>EDIT_STOPLOG_CMD</source>
+        <translation>Arrêter la &amp;trace</translation>
+    </message>
+</context>
+<context>
+    <name>PyConsole_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/PyConsoleBase/resources/PyConsole_msg_ja.ts b/src/PyConsoleBase/resources/PyConsole_msg_ja.ts
new file mode 100644 (file)
index 0000000..c36cf6a
--- /dev/null
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="ja" sourcelanguage="en">
+  <context>
+    <name>PyConsole_ConsoleBase</name>
+    <message>
+      <location filename="../PyConsole_ConsoleBase.cxx" line="216"/>
+      <source>EDIT_COPY_CMD</source>
+      <translation>コピー(&amp;C)</translation>
+    </message>
+    <message>
+      <location filename="../PyConsole_ConsoleBase.cxx" line="221"/>
+      <source>EDIT_PASTE_CMD</source>
+      <translation>貼り付け(&amp;P)</translation>
+    </message>
+    <message>
+      <location filename="../PyConsole_ConsoleBase.cxx" line="226"/>
+      <source>EDIT_CLEAR_CMD</source>
+      <translation>削除(&amp;r)</translation>
+    </message>
+    <message>
+      <location filename="../PyConsole_ConsoleBase.cxx" line="231"/>
+      <source>EDIT_SELECTALL_CMD</source>
+      <translation>すべて選択します。(&amp;A)</translation>
+    </message>
+    <message>
+      <source>EDIT_DUMPCOMMANDS_CMD</source>
+      <translation>スクリプト コマンドを生成します。(&amp;u)</translation>
+    </message>
+    <message>
+      <source>EDIT_STARTLOG_CMD</source>
+      <translation>ログの開始 (&amp;L)</translation>
+    </message>
+    <message>
+      <source>EDIT_STOPLOG_CMD</source>
+      <translation>ログの停止 (&amp;L)</translation>
+    </message>
+  </context>
+  <context>
+    <name>PyConsole_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>
index bba191dd1418fca2eed1f569d233255e407385fd..ee6a6feaee49d01385b6c07b62d18e13b1e84a38 100755 (executable)
@@ -41,6 +41,7 @@ INCLUDE_DIRECTORIES(
   ${PROJECT_SOURCE_DIR}/src/OBJECT
   ${PROJECT_SOURCE_DIR}/src/ObjBrowser
   ${PROJECT_SOURCE_DIR}/src/PyInterp
+  ${PROJECT_SOURCE_DIR}/src/PyConsoleBase
   ${PROJECT_SOURCE_DIR}/src/PyConsole
   ${PROJECT_SOURCE_DIR}/src/Qtx
   ${PROJECT_SOURCE_DIR}/src/SALOME_PYQT/SALOME_PYQT_GUILight
diff --git a/src/SUITT/CMakeLists.txt b/src/SUITT/CMakeLists.txt
new file mode 100644 (file)
index 0000000..fcff36a
--- /dev/null
@@ -0,0 +1,95 @@
+# Copyright (C) 2012-2015  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(UseQtExt)
+
+# --- options ---
+
+# additional include directories
+INCLUDE_DIRECTORIES(
+  ${QT_INCLUDES}
+)
+
+# additional preprocessor / compiler flags
+ADD_DEFINITIONS(${QT_DEFINITIONS})
+IF(ENABLE_TESTRECORDER)
+  ADD_DEFINITIONS("-DENABLE_TESTRECORDER ${TESTRECORDER_DEFINITIONS}")
+ENDIF()
+
+# libraries to link to
+SET(_link_LIBRARIES ${PLATFORM_LIBS} ${QT_LIBRARIES} qtx ObjBrowser)
+IF(ENABLE_TESTRECORDER)
+  LIST(APPEND _link_LIBRARIES ${TESTRECORDER_LIBS})
+ENDIF()
+
+# --- headers ---
+
+# header files / to be processed by moc
+SET(_moc_HEADERS
+  SUIT_MessageBox.h
+)
+
+# header files / no moc processing
+SET(_other_HEADERS
+  SUIT_OverrideCursor.h
+  SUIT_FileValidator.h
+  Qtxx.h
+  SUIT.h
+)
+
+# header files / to install
+SET(suitt_HEADERS ${_moc_HEADERS} ${_other_HEADERS})
+
+# --- resources ---
+
+# resource files / to be processed by lrelease
+
+# resource files / static
+SET(_other_RESOURCES
+  resources/icon_visibility_on.png
+  resources/icon_visibility_off.png
+  resources/view_sync.png
+)
+
+# --- sources ---
+
+# sources / moc wrappings
+QT_WRAP_MOC(_moc_SOURCES ${_moc_HEADERS})
+
+# sources / static
+SET(_other_SOURCES
+  SUIT_OverrideCursor.cxx
+  SUIT_MessageBox.cxx
+  SUIT_FileValidator.cxx
+  Qtxx.cxx
+)
+
+# sources / to compile
+SET(suitt_SOURCES ${_other_SOURCES} ${_moc_SOURCES})
+
+# --- rules ---
+
+ADD_LIBRARY(suitt ${suitt_SOURCES})
+TARGET_LINK_LIBRARIES(suitt ${_link_LIBRARIES})
+INSTALL(TARGETS suitt EXPORT ${PROJECT_NAME}TargetGroup DESTINATION ${SALOME_INSTALL_LIBS})
+
+INSTALL(FILES ${suitt_HEADERS} DESTINATION ${SALOME_INSTALL_HEADERS})
+
+INSTALL(FILES ${_other_RESOURCES} DESTINATION ${SALOME_GUI_INSTALL_RES_DATA})
+
diff --git a/src/SUITT/Qtxx.cxx b/src/SUITT/Qtxx.cxx
new file mode 100755 (executable)
index 0000000..3186a11
--- /dev/null
@@ -0,0 +1,75 @@
+// Copyright (C) 2007-2015  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:      Qtxx.cxx
+// Author:    Sergey TELKOV
+//
+#include "Qtxx.h"
+
+#include <QDir>
+#include <QMenu>
+#include <QRegExp>
+#include <QBitmap>
+#include <QWidget>
+#include <QLayout>
+#include <QPainter>
+#include <QDirModel>
+#include <QFileInfo>
+#include <QCompleter>
+#include <QApplication>
+#include <QDesktopWidget>
+#include <QtDebug>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <clocale>
+
+/*!
+  \brief Return directory part of the file path.
+
+  If the file path does not include directory part (the file is in the
+  current directory), null string is returned.
+
+  \param path file path
+  \param abs if true (default) \a path parameter is treated as absolute file path
+  \return directory part of the file path
+*/
+QString Qtxx::dir( const QString& path, const bool abs )
+{
+  QDir aDir = QFileInfo( path ).dir();
+  QString dirPath = abs ? aDir.absolutePath() : aDir.path();
+  if ( dirPath == QString( "." ) )
+    dirPath = QString();
+  return dirPath;
+}
+
+/*!
+  Creates font from string description
+*/
+QFont Qtxx::stringToFont( const QString& fontDescription )
+{
+  QFont font;
+  if ( fontDescription.trimmed().isEmpty() || !font.fromString( fontDescription ) )
+    font = QFont( "Courier", 11 );
+  return font;
+}
diff --git a/src/SUITT/Qtxx.h b/src/SUITT/Qtxx.h
new file mode 100755 (executable)
index 0000000..5d31747
--- /dev/null
@@ -0,0 +1,68 @@
+// Copyright (C) 2007-2015  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:      Qtx.h
+// Author:    Sergey TELKOV
+//
+#ifndef QTXX_H
+#define QTXX_H
+
+#if defined WIN32
+#  if defined QTXX_EXPORTS || defined qtxx_EXPORTS
+#    define QTX_EXPORT _declspec( dllexport )
+#  else
+#    define QTX_EXPORT _declspec( dllimport )
+#  endif
+#else
+#  define QTX_EXPORT  
+#endif
+
+#if defined SOLARIS
+#define bool  int
+#define false 0
+#define true  1
+#endif
+
+#include <QString>
+#include <QList>
+#include <QColor>
+#include <QImage>
+#include <QPixmap>
+#include <QGradient>
+
+class QObject;
+class QWidget;
+class QCompleter;
+
+typedef QList<int>    QIntList;       //!< list of int values
+typedef QList<short>  QShortList;     //!< list of short int values
+typedef QList<double> QDoubleList;    //!< list of double values
+typedef QList<QColor> QColorList;     //!< list of colors
+
+class QTX_EXPORT Qtxx
+{
+public:
+  static QString     dir( const QString&, const bool = true );
+  static QFont   stringToFont( const QString& fontDescription );
+};
+
+#endif
diff --git a/src/SUITT/SUIT.h b/src/SUITT/SUIT.h
new file mode 100755 (executable)
index 0000000..392e987
--- /dev/null
@@ -0,0 +1,58 @@
+// Copyright (C) 2007-2015  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   : SUIT.h
+// Author : 
+//
+#ifndef SUIT_H
+#define SUIT_H
+
+#if defined WIN32
+#  if defined SUIT_EXPORTS || defined suit_EXPORTS
+#    define SUIT_EXPORT __declspec( dllexport )
+#  else
+#    define SUIT_EXPORT __declspec( dllimport )
+#  endif
+#else
+#  define SUIT_EXPORT
+#endif
+
+#if defined SOLARIS
+#define bool  int
+#define false 0
+#define true  1
+#endif
+
+#if defined WIN32
+#pragma warning ( disable: 4251 )
+#endif
+
+#if defined ( _DEBUG ) || defined ( DEBUG )
+#include <assert.h>
+#define SUIT_VERIFY(x) assert( x );
+#define SUIT_ASSERT(x) assert( x );
+#else
+#define SUIT_VERIFY(x) x
+#define SUIT_ASSERT(x)
+#endif
+
+#endif  // SUIT_H
diff --git a/src/SUITT/SUIT_FileValidator.cxx b/src/SUITT/SUIT_FileValidator.cxx
new file mode 100755 (executable)
index 0000000..1fc1b40
--- /dev/null
@@ -0,0 +1,201 @@
+// Copyright (C) 2007-2015  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   : SUIT_FileValidator.cxx
+// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
+//
+#include "SUIT_FileValidator.h"
+#include "SUIT_MessageBox.h"
+#include "Qtxx.h"   
+#include <QFileInfo>
+
+/*!
+  \class SUIT_FileValidator
+  \brief Provides functionality to check the file or directory
+  existance and permissions.
+  \sa SUIT_FileDlg class
+*/
+
+/*!
+  \brief Constructor.
+  \param parent parent widget (used as parent when displaying 
+  information message boxes)
+*/
+SUIT_FileValidator::SUIT_FileValidator( QWidget* parent )
+: myParent( parent ) 
+{
+}
+  
+/*!
+  \brief Check if the specified file exists and (optionally) can be read.
+
+  If file does not exists or can not be read (if \a checkPermission is \c true)
+  and parent() is not null, shows error message box.
+
+  \param fileName file path
+  \param checkPermission if \c true (default) check also file permissions
+  \return \c false if file does not exist or if it does not have 
+  read permissions (if \a checkPermission is \c true)
+*/
+bool SUIT_FileValidator::canOpen( const QString& fileName, bool checkPermission ) 
+{
+  if ( !QFile::exists( fileName ) ) {
+    if ( parent() )
+      SUIT_MessageBox::critical( parent(), QObject::tr( "ERR_ERROR" ),
+                                 QObject::tr( "ERR_FILE_NOT_EXIST" ).arg( fileName ) );
+    return false;
+  }
+  if ( checkPermission && !QFileInfo( fileName ).isReadable() ) {
+    if ( parent() )
+      SUIT_MessageBox::critical( parent(), QObject::tr( "ERR_ERROR" ),
+                                 QObject::tr( "ERR_OPEN_PERMISSION_DENIED" ).arg( fileName ) );
+    return false; 
+  }
+  return true;
+}
+
+/*!
+  \brief Check if the specified file can be written.
+
+  If file already exists and parent() is not null, prompts
+  question message box to the user to confirm file overwriting.
+
+  If file can not be written (if \a checkPermission is \c true)
+  and parent() is not null, shows error message box.
+
+  \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)
+*/
+bool SUIT_FileValidator::canSave( const QString& fileName, bool checkPermission ) 
+{
+  if ( QFile::exists( fileName ) ) {
+    if ( parent() )
+      if ( SUIT_MessageBox::question( parent(), QObject::tr( "WRN_WARNING" ),
+                                      QObject::tr( "QUE_DOC_FILEEXISTS" ).arg( fileName ),
+                                      SUIT_MessageBox::Yes | SUIT_MessageBox::No,
+                                      SUIT_MessageBox::No ) != SUIT_MessageBox::Yes )
+        return false;
+    
+    if ( checkPermission && !QFileInfo( fileName ).isWritable() ) {
+      if ( parent() ) 
+        SUIT_MessageBox::critical( myParent, QObject::tr( "ERR_ERROR" ),
+                                   QObject::tr( "ERR_PERMISSION_DENIED" ).arg( fileName ) );
+      return false; 
+    }
+  }
+  else {
+    QString dirName = Qtxx::dir( fileName );
+    if ( !QFile::exists( dirName ) ) {
+      SUIT_MessageBox::critical( parent(), QObject::tr( "WRN_WARNING" ),
+                                 QObject::tr( "ERR_DIR_NOT_EXIST" ).arg( dirName ) );
+      return false;
+    }
+    if ( checkPermission && !QFileInfo( dirName ).isWritable() ) {
+      if ( parent() )
+        SUIT_MessageBox::critical( parent(), QObject::tr( "ERR_ERROR" ),
+                                   QObject::tr( "ERR_PERMISSION_DENIED" ).arg( fileName ) );
+      return false;
+    }
+  }
+  return true;
+}
+
+/*!
+  \brief Check if the specified directory exists and (optionally) can be read.
+
+  If directory does not exists or can not be read (if \a checkPermission is \c true)
+  and parent() is not null, shows error message box.
+
+  \param dirName directory path
+  \param checkPermission if \c true (default) check also directory permissions
+  \return \c false if directory does not exist or if it does not have 
+  read permissions (if \a checkPermission is \c true)
+*/
+bool SUIT_FileValidator::canReadDir( const QString& dirName, bool checkPermission )
+{
+  QFileInfo info( dirName );
+  if ( !info.exists() ) {
+    if ( parent() )
+      SUIT_MessageBox::critical( parent(), QObject::tr( "ERR_ERROR" ),
+                                 QObject::tr( "ERR_DIR_NOT_EXIST" ).arg( dirName ) );
+    return false;
+  }
+  if ( !info.isDir() ) {
+    if ( parent() )
+      SUIT_MessageBox::critical( parent(), QObject::tr( "ERR_ERROR" ),
+                                 QObject::tr( "ERR_FILE_NOT_DIR" ).arg( dirName ) );
+    return false;
+  }
+  if ( checkPermission && !info.isReadable() ) {
+    if ( parent() )
+      SUIT_MessageBox::critical( parent(), QObject::tr( "ERR_ERROR" ),
+                                 QObject::tr( "ERR_DIR_READ_PERMISSION_DENIED" ).arg( dirName ) );
+    return false; 
+  }
+  return true;
+}
+
+/*!
+  \brief Check if the specified directory can be written.
+
+  If directory does not exists or can not be modified (if \a checkPermission is \c true)
+  and parent() is not null, shows error message box.
+
+  \param dirName directory path
+  \param checkPermission if \c true (default) check also directory permissions
+  \return \c false if directory does not exist or if it does not have 
+  write permissions (if \a checkPermission is \c true)
+*/
+bool SUIT_FileValidator::canWriteDir( const QString& dirName, bool checkPermission )
+{
+  QFileInfo info( dirName );
+  if ( !info.exists() ) {
+    if ( parent() )
+      SUIT_MessageBox::critical( parent(), QObject::tr( "ERR_ERROR" ),
+                                 QObject::tr( "ERR_DIR_NOT_EXIST" ).arg( dirName ) );
+    return false;
+  }
+  if ( !info.isDir() ) {
+    if ( parent() )
+      SUIT_MessageBox::critical( parent(), QObject::tr( "ERR_ERROR" ),
+                                 QObject::tr( "ERR_FILE_NOT_DIR" ).arg( dirName ) );
+    return false;
+  }
+  if ( checkPermission && !info.isWritable() ) {
+    if ( parent() )
+      SUIT_MessageBox::critical( parent(), QObject::tr( "ERR_ERROR" ),
+                                 QObject::tr( "ERR_DIR_WRITE_PERMISSION_DENIED" ).arg( dirName ) );
+    return false; 
+  }
+  return true;
+}
+
+/*!
+  \brief Get parent widget.
+  \return parent widget
+*/
+QWidget* SUIT_FileValidator::parent() const
+{ 
+  return myParent; 
+}
diff --git a/src/SUITT/SUIT_FileValidator.h b/src/SUITT/SUIT_FileValidator.h
new file mode 100755 (executable)
index 0000000..4c59b02
--- /dev/null
@@ -0,0 +1,51 @@
+// Copyright (C) 2007-2015  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   : SUIT_FileValidator.h
+// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
+//
+#ifndef SUIT_FILEVALIDATOR_H
+#define SUIT_FILEVALIDATOR_H
+
+#include "SUIT.h"
+
+class QWidget;
+class QString;
+
+class SUIT_EXPORT SUIT_FileValidator
+{
+public:
+  SUIT_FileValidator( QWidget* = 0 );
+  
+  virtual bool    canOpen( const QString&, bool = true );
+  virtual bool    canSave( const QString&, bool = true );
+
+  virtual bool    canReadDir( const QString&, bool = true );
+  virtual bool    canWriteDir( const QString&, bool = true );
+
+  QWidget*        parent() const;
+  
+private:
+  QWidget*        myParent;
+};
+
+#endif // SUIT_FILEVALIDATOR_H
diff --git a/src/SUITT/SUIT_MessageBox.cxx b/src/SUITT/SUIT_MessageBox.cxx
new file mode 100755 (executable)
index 0000000..348d8a8
--- /dev/null
@@ -0,0 +1,1131 @@
+// Copyright (C) 2007-2015  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
+//
+
+#include "SUIT_MessageBox.h"
+
+#include "SUIT_OverrideCursor.h"
+
+#include <QMessageBox>
+#include <QPushButton>
+#include <QApplication>
+#include <QString>
+
+#include <stdarg.h>
+
+/*!
+  \class SUIT_MessageBox
+  \brief Message dialog box for SUIT-based application
+
+  The class provides a modal dialog with a short message, an icon, 
+  and buttons laid out depending on the current style.
+  
+  Message boxes are used to provide informative messages and to ask 
+  simple questions.
+
+  The easiest way to pop up a message box is to call one of the static
+  functions information(), question(), critical(), and warning().
+
+  The class provides the static functions to show message boxes with
+  standard buttons (like \c Ok, \c Cancel, \c Apply, \c Close, \c Yes, 
+  \c No, \c Abort, \c Retry, etc). These methods accept ORed buttons
+  flags as one of the parameters. The buttons layouting type and order
+  is system-dependant and defined by the current style. In addition,
+  these methods allow to define default button (where input focus is
+  set by default and which is clicked when user presses \c Enter key).
+
+  Another set of static functions allows to show message boxes with 
+  up to four user-defined buttons. It is possible to define default 
+  and escape buttons using additional parameters.
+
+  And finally, the last group of static functions allow displaying
+  the message boxes with an arbitrary number of buttons.
+
+  For example:
+  \code
+  // show question message box with two standard buttons
+  int result = SUIT_MessageBox::question(desktop(), "Error",
+                                         "File already exists? Overwrite?",
+                                         SUIT_MessageBox::Yes | SUIT_MessageBox::No,
+                                         SUIT_MessageBox::No );
+  if ( result == SUIT_MessageBox::Yes )
+    overwriteFileFunction();
+
+  // show critical message box with user-defined buttons
+  // default is second button and escape is third button
+  int result = SUIT_MessageBox::critical(desktop(), "Hazard!",
+                                         "The situation is critical! What to do?",
+                                         "Hide", "Run Away", "Stand still", 1, 2);
+  switch ( result )
+  {
+  case 0:
+    hideMyself(); break;
+  case 1:
+    runAwayFromHere(); break;
+  case 2:
+    sitDownAndPray(); break;
+  default:
+    break;
+  }
+
+  // show message box with 6 buttons
+  // both default and escape buttons are set to first button ("Zero")
+  int result = SUIT_MessageBox::information(desktop(), "Question",
+                                            "Select your favourite number",
+                                            0, 0,
+                                            "Zero", "One", "Two", "Three", "Four", "Five");
+  useMyFavouriteNumberSomewhere( result );
+  \endcode
+*/
+
+/*!
+  \brief Constructor.
+  \param parent parent widget
+*/
+SUIT_MessageBox::SUIT_MessageBox( QWidget* parent )
+: QMessageBox( parent )
+{
+}
+
+/*!
+  \brief Constructor.
+  \param icon message box icon (QMessageBox::Icon)
+  \param title message box title
+  \param text message box text
+  \param buttons ORed message box standard buttons (QMessageBox::StandardButton)
+  \param parent parent widget
+  \param f window flags
+*/
+SUIT_MessageBox::SUIT_MessageBox( Icon icon, const QString& title, const QString& text,
+                                  StandardButtons buttons, QWidget* parent, Qt::WindowFlags f )
+: QMessageBox( icon, title, text, buttons, parent, f )
+{
+}
+
+/*!
+  \brief Destructor.
+*/
+SUIT_MessageBox::~SUIT_MessageBox()
+{
+}
+
+/*!
+  \brief Get the standard button text.
+  \param btn standard button id
+  \return button text
+*/
+QString SUIT_MessageBox::buttonText( StandardButton btn ) const
+{
+  QString res;
+  QAbstractButton* b = button( btn );
+  if ( b )
+    res = b->text();
+  return res;
+}
+
+/*!
+  \brief Set the standard button text.
+  \param btn standard button id
+  \param text new button text
+*/
+void SUIT_MessageBox::setButtonText( StandardButton btn, const QString& text )
+{
+  QAbstractButton* b = button( btn );
+  if ( b )
+    b->setText( text );
+}
+
+/*!
+  \brief Show critical message box with specified standard buttons.
+  \param parent parent widget
+  \param title message box title
+  \param text message box text
+  \param buttons ORed message box buttons (QMessageBox::StandardButton)
+  \param defaultButton default button (QMessageBox::StandardButton)
+  \return button id clicked by the user (QMessageBox::StandardButton)
+*/
+SUIT_MessageBox::StandardButton SUIT_MessageBox::critical( QWidget* parent, const QString& title, const QString& text,
+                                                           StandardButtons buttons, StandardButton defaultButton )
+{
+  SUIT_OverrideCursor cw( parent ? parent->cursor() : Qt::ArrowCursor );
+  return QMessageBox::critical( parent, title, text, buttons, defaultButton );
+}
+
+/*!
+  \brief Show warning message box with specified standard buttons.
+  \param parent parent widget
+  \param title message box title
+  \param text message box text
+  \param buttons ORed message box buttons (QMessageBox::StandardButton)
+  \param defaultButton default button (QMessageBox::StandardButton)
+  \return button id clicked by the user (QMessageBox::StandardButton)
+*/
+SUIT_MessageBox::StandardButton SUIT_MessageBox::warning( QWidget* parent, const QString& title, const QString& text,
+                                                          SUIT_MessageBox::StandardButtons buttons, StandardButton defaultButton )
+{
+  SUIT_OverrideCursor cw( parent ? parent->cursor() : Qt::ArrowCursor );
+  return QMessageBox::warning( parent, title, text, buttons, defaultButton );
+}
+
+/*!
+  \brief Show information message box with specified standard buttons.
+  \param parent parent widget
+  \param title message box title
+  \param text message box text
+  \param buttons ORed message box buttons (QMessageBox::StandardButton)
+  \param defaultButton default button (QMessageBox::StandardButton)
+  \return button id clicked by the user (QMessageBox::StandardButton)
+*/
+SUIT_MessageBox::StandardButton SUIT_MessageBox::information( QWidget* parent, const QString& title, const QString& text,
+                                                              StandardButtons buttons, StandardButton defaultButton )
+{
+  SUIT_OverrideCursor cw( parent ? parent->cursor() : Qt::ArrowCursor );
+  return QMessageBox::information( parent, title, text, buttons, defaultButton );
+}
+
+/*!
+  \brief Show question message box with specified standard buttons.
+  \param parent parent widget
+  \param title message box title
+  \param text message box text
+  \param buttons ORed message box buttons (QMessageBox::StandardButton)
+  \param defaultButton default button (QMessageBox::StandardButton)
+  \return button id clicked by the user (QMessageBox::StandardButton)
+*/
+SUIT_MessageBox::StandardButton SUIT_MessageBox::question( QWidget* parent, const QString& title, const QString& text,
+                                                           StandardButtons buttons, StandardButton defaultButton )
+{
+  SUIT_OverrideCursor cw( parent ? parent->cursor() : Qt::ArrowCursor );
+  return QMessageBox::question( parent, title, text, buttons, defaultButton );
+}
+
+/*!
+  \brief Show critical message box with one custom button.
+
+  Specified button becomes "default" button and "escape" button, i.e.
+  pressing \c Return or \c Enter and \c Escape keys is equivalent to clicking
+  this button.
+
+  \param parent parent widget
+  \param title message box title
+  \param text message box text
+  \param button button text
+  \return button id clicked by the user (QMessageBox::StandardButton)
+*/
+int SUIT_MessageBox::critical( QWidget* parent, const QString& title, const QString& text,
+                               const QString& button )
+{
+  ButtonInfos lst;
+  lst.append( ButtonInfo( 0, button ) );
+  return messageBox( SUIT_MessageBox::Critical, parent, title, text, lst );
+}
+
+/*!
+  \brief Show warning message box with one custom button.
+  
+  Specified button becomes "default" button and "escape" button, i.e.
+  pressing \c Return or \c Enter and \c Escape keys is equivalent to clicking
+  this button.
+
+  \param parent parent widget
+  \param title message box title
+  \param text message box text
+  \param button button text
+  \return button id clicked by the user (QMessageBox::StandardButton)
+*/
+int SUIT_MessageBox::warning( QWidget* parent, const QString& title, const QString& text,
+                              const QString& button )
+{
+  ButtonInfos lst;
+  lst.append( ButtonInfo( 0, button ) );
+  return messageBox( SUIT_MessageBox::Warning, parent, title, text, lst );
+}
+
+/*!
+  \brief Show information message box with one custom button.
+
+  Specified button becomes "default" button and "escape" button, i.e.
+  pressing \c Return or \c Enter and \c Escape keys is equivalent to clicking
+  this button.
+
+  \param parent parent widget
+  \param title message box title
+  \param text message box text
+  \param button button text
+  \return button id clicked by the user (QMessageBox::StandardButton)
+*/
+int SUIT_MessageBox::information( QWidget* parent, const QString& title, const QString& text,
+                                  const QString& button )
+{
+  ButtonInfos lst;
+  lst.append( ButtonInfo( 0, button ) );
+  return messageBox( SUIT_MessageBox::Information, parent, title, text, lst );
+}
+
+/*!
+  \brief Show question message box with one custom button.
+
+  \warning This function does not make a lot of sense because it provides
+  message box with only one  button, i.e. it is impossible to give several
+  answers for the question (at least 'yes'/'no').
+  This function is implemented only for completeness.
+
+  Specified button becomes "default" button and "escape" button, i.e.
+  pressing \c Return or \c Enter and \c Escape keys is equivalent to clicking
+  this button.
+
+  \param parent parent widget
+  \param title message box title
+  \param text message box text
+  \param button button text
+  \return button id clicked by the user (QMessageBox::StandardButton)
+*/
+int SUIT_MessageBox::question( QWidget* parent, const QString& title, const QString& text,
+                               const QString& button )
+{
+  ButtonInfos lst;
+  lst.append( ButtonInfo( 0, button ) );
+  return messageBox( SUIT_MessageBox::Question, parent, title, text, lst );
+}
+
+/*!
+  \brief Show critical message box with two custom buttons.
+
+  Parameters \a button1 and \a button2 specify the buttons text.
+  The function returns clicked button id. The identifiers for the buttons
+  are assigned automatically. The first button is identified as 0, the
+  second one as 1.
+
+  The \a defaultButton parameter allows to specify the button which is assigned
+  for the \c Return or \c Enter key. Similarly, \a escapeButton parameter
+  allows specifing the button which is assigned for \c Escape key.
+  If these parameters are not specified (-1 by default), the first button
+  is set as default button and the second one is defined as escape button.
+
+  \param parent parent widget
+  \param title message box title
+  \param text message box text
+  \param button1 first button text
+  \param button2 second button text
+  \param defaultButton default button
+  \param escapeButton escape button
+  \return button used button id
+*/
+int SUIT_MessageBox::critical( QWidget* parent, const QString& title, const QString& text,
+                               const QString& button1, const QString& button2,
+                               const int defaultButton, const int escapeButton )
+{
+  ButtonInfos lst;
+  int id = 0;
+  lst.append( ButtonInfo( id++, button1 ) );
+  lst.append( ButtonInfo( id++, button2 ) );
+  return messageBox( SUIT_MessageBox::Critical, parent, title, text, lst, 
+                     defaultButton, escapeButton );
+}
+
+/*!
+  \brief Show warning message box with two custom buttons.
+
+  Parameters \a button1 and \a button2 specify the buttons text.
+  The function returns clicked button id. The identifiers for the buttons
+  are assigned automatically. The first button is identified as 0, the
+  second one as 1.
+
+  The \a defaultButton parameter allows to specify the button which is assigned
+  for the \c Return or \c Enter key. Similarly, \a escapeButton parameter
+  allows specifing the button which is assigned for \c Escape key.
+  If these parameters are not specified (-1 by default), the first button
+  is set as default button and the second one is defined as escape button.
+
+  \param parent parent widget
+  \param title message box title
+  \param text message box text
+  \param button1 first button text
+  \param button2 second button text
+  \param defaultButton default button
+  \param escapeButton escape button
+  \return button used button id
+*/
+int SUIT_MessageBox::warning( QWidget* parent, const QString& title, const QString& text,
+                              const QString& button1, const QString& button2,
+                              const int defaultButton, const int escapeButton )
+{
+  ButtonInfos lst;
+  int id = 0;
+  lst.append( ButtonInfo( id++, button1 ) );
+  lst.append( ButtonInfo( id++, button2 ) );
+  return messageBox( SUIT_MessageBox::Warning, parent, title, text, lst, 
+                     defaultButton, escapeButton );
+}
+
+/*!
+  \brief Show information message box with two custom buttons.
+
+  Parameters \a button1 and \a button2 specify the buttons text.
+  The function returns clicked button id. The identifiers for the buttons
+  are assigned automatically. The first button is identified as 0, the
+  second one as 1.
+
+  The \a defaultButton parameter allows to specify the button which is assigned
+  for the \c Return or \c Enter key. Similarly, \a escapeButton parameter
+  allows specifing the button which is assigned for \c Escape key.
+  If these parameters are not specified (-1 by default), the first button
+  is set as default button and the second one is defined as escape button.
+
+  \param parent parent widget
+  \param title message box title
+  \param text message box text
+  \param button1 first button text
+  \param button2 second button text
+  \param defaultButton default button
+  \param escapeButton escape button
+  \return button used button id
+*/
+int SUIT_MessageBox::information( QWidget* parent, const QString& title, const QString& text,
+                                  const QString& button1, const QString& button2,
+                                  const int defaultButton, const int escapeButton )
+{
+  ButtonInfos lst;
+  int id = 0;
+  lst.append( ButtonInfo( id++, button1 ) );
+  lst.append( ButtonInfo( id++, button2 ) );
+  return messageBox( SUIT_MessageBox::Information, parent, title, text, lst, 
+                     defaultButton, escapeButton );
+}
+
+/*!
+  \brief Show question message box with two custom buttons.
+
+  Parameters \a button1 and \a button2 specify the buttons text.
+  The function returns clicked button id. The identifiers for the buttons
+  are assigned automatically. The first button is identified as 0, the
+  second one as 1.
+
+  The \a defaultButton parameter allows to specify the button which is assigned
+  for the \c Return or \c Enter key. Similarly, \a escapeButton parameter
+  allows specifing the button which is assigned for \c Escape key.
+  If these parameters are not specified (-1 by default), the first button
+  is set as default button and the second one is defined as escape button.
+
+  \param parent parent widget
+  \param title message box title
+  \param text message box text
+  \param button1 first button text
+  \param button2 second button text
+  \param defaultButton default button
+  \param escapeButton escape button
+  \return button used button id
+*/
+int SUIT_MessageBox::question( QWidget* parent, const QString& title, const QString& text,
+                               const QString& button1, const QString& button2,
+                               const int defaultButton, const int escapeButton )
+{
+  ButtonInfos lst;
+  int id = 0;
+  lst.append( ButtonInfo( id++, button1 ) );
+  lst.append( ButtonInfo( id++, button2 ) );
+  return messageBox( SUIT_MessageBox::Question, parent, title, text, lst, 
+                     defaultButton, escapeButton );
+}
+
+/*!
+  \brief Show critical message box with three custom buttons.
+
+  Parameters \a button1, \a button2 and \a button3 specify the buttons text.
+  The function returns clicked button id. The identifiers for the buttons
+  are assigned automatically. The first button is identified as 0, the
+  second one as 1, etc.
+
+  The \a defaultButton parameter allows to specify the button which is assigned
+  for the \c Return or \c Enter key. Similarly, \a escapeButton parameter
+  allows specifing the button which is assigned for \c Escape key.
+  If these parameters are not specified (-1 by default), the first button
+  is set as default button and the last one is defined as escape button.
+
+  \param parent parent widget
+  \param title message box title
+  \param text message box text
+  \param button1 first button text
+  \param button2 second button text
+  \param button3 third button text
+  \param defaultButton default button
+  \param escapeButton escape button
+  \return button used button id
+*/
+int SUIT_MessageBox::critical( QWidget* parent, const QString& title, const QString& text,
+                               const QString& button1, const QString& button2, 
+                               const QString& button3,
+                               const int defaultButton, const int escapeButton )
+{
+  ButtonInfos lst;
+  int id = 0;
+  lst.append( ButtonInfo( id++, button1 ) );
+  lst.append( ButtonInfo( id++, button2 ) );
+  lst.append( ButtonInfo( id++, button3 ) );
+  return messageBox( SUIT_MessageBox::Critical, parent, title, text, lst, 
+                     defaultButton, escapeButton );
+}
+
+/*!
+  \brief Show warning message box with three custom buttons.
+
+  Parameters \a button1, \a button2 and \a button3 specify the buttons text.
+  The function returns clicked button id. The identifiers for the buttons
+  are assigned automatically. The first button is identified as 0, the
+  second one as 1, etc.
+
+  The \a defaultButton parameter allows to specify the button which is assigned
+  for the \c Return or \c Enter key. Similarly, \a escapeButton parameter
+  allows specifing the button which is assigned for \c Escape key.
+  If these parameters are not specified (-1 by default), the first button
+  is set as default button and the last one is defined as escape button.
+
+  \param parent parent widget
+  \param title message box title
+  \param text message box text
+  \param button1 first button text
+  \param button2 second button text
+  \param button3 third button text
+  \param defaultButton default button
+  \param escapeButton escape button
+  \return button used button id
+*/
+int SUIT_MessageBox::warning( QWidget* parent, const QString& title, const QString& text,
+                              const QString& button1, const QString& button2,
+                              const QString& button3,
+                              const int defaultButton, const int escapeButton )
+{
+  ButtonInfos lst;
+  int id = 0;
+  lst.append( ButtonInfo( id++, button1 ) );
+  lst.append( ButtonInfo( id++, button2 ) );
+  lst.append( ButtonInfo( id++, button3 ) );
+  return messageBox( SUIT_MessageBox::Warning, parent, title, text, lst, 
+                     defaultButton, escapeButton );
+}
+
+/*!
+  \brief Show information message box with three custom buttons.
+
+  Parameters \a button1, \a button2 and \a button3 specify the buttons text.
+  The function returns clicked button id. The identifiers for the buttons
+  are assigned automatically. The first button is identified as 0, the
+  second one as 1, etc.
+
+  The \a defaultButton parameter allows to specify the button which is assigned
+  for the \c Return or \c Enter key. Similarly, \a escapeButton parameter
+  allows specifing the button which is assigned for \c Escape key.
+  If these parameters are not specified (-1 by default), the first button
+  is set as default button and the last one is defined as escape button.
+
+  \param parent parent widget
+  \param title message box title
+  \param text message box text
+  \param button1 first button text
+  \param button2 second button text
+  \param button3 third button text
+  \param defaultButton default button
+  \param escapeButton escape button
+  \return button used button id
+*/
+int SUIT_MessageBox::information( QWidget* parent, const QString& title, const QString& text,
+                                  const QString& button1, const QString& button2,
+                                  const QString& button3,
+                                  const int defaultButton, const int escapeButton )
+{
+  ButtonInfos lst;
+  int id = 0;
+  lst.append( ButtonInfo( id++, button1 ) );
+  lst.append( ButtonInfo( id++, button2 ) );
+  lst.append( ButtonInfo( id++, button3 ) );
+  return messageBox( SUIT_MessageBox::Information, parent, title, text, lst, 
+                     defaultButton, escapeButton );
+}
+
+/*!
+  \brief Show question message box with three custom buttons.
+
+  Parameters \a button1, \a button2 and \a button3 specify the buttons text.
+  The function returns clicked button id. The identifiers for the buttons
+  are assigned automatically. The first button is identified as 0, the
+  second one as 1, etc.
+
+  The \a defaultButton parameter allows to specify the button which is assigned
+  for the \c Return or \c Enter key. Similarly, \a escapeButton parameter
+  allows specifing the button which is assigned for \c Escape key.
+  If these parameters are not specified (-1 by default), the first button
+  is set as default button and the last one is defined as escape button.
+
+  \param parent parent widget
+  \param title message box title
+  \param text message box text
+  \param button1 first button text
+  \param button2 second button text
+  \param button3 third button text
+  \param defaultButton default button
+  \param escapeButton escape button
+  \return button used button id
+*/
+int SUIT_MessageBox::question( QWidget* parent, const QString& title, const QString& text,
+                               const QString& button1, const QString& button2,
+                               const QString& button3,
+                               const int defaultButton, const int escapeButton )
+{
+  ButtonInfos lst;
+  int id = 0;
+  lst.append( ButtonInfo( id++, button1 ) );
+  lst.append( ButtonInfo( id++, button2 ) );
+  lst.append( ButtonInfo( id++, button3 ) );
+  return messageBox( SUIT_MessageBox::Question, parent, title, text, lst, 
+                     defaultButton, escapeButton );
+}
+
+/*!
+  \brief Show critical message box with four custom buttons.
+
+  Parameters \a button1, \a button2, \a button3 and \a button4 specify 
+  the buttons text.
+  The function returns clicked button id. The identifiers for the buttons
+  are assigned automatically. The first button is identified as 0, the
+  second one as 1, etc.
+
+  The \a defaultButton parameter allows to specify the button which is assigned
+  for the \c Return or \c Enter key. Similarly, \a escapeButton parameter
+  allows specifing the button which is assigned for \c Escape key.
+  If these parameters are not specified (-1 by default), the first button
+  is set as default button and the last one is defined as escape button.
+
+  \param parent parent widget
+  \param title message box title
+  \param text message box text
+  \param button1 first button text
+  \param button2 second button text
+  \param button3 third button text
+  \param button4 fourth button text
+  \param defaultButton default button
+  \param escapeButton escape button
+  \return button used button id
+*/
+int SUIT_MessageBox::critical( QWidget* parent, const QString& title, const QString& text,
+                               const QString& button1, const QString& button2, 
+                               const QString& button3, const QString& button4,
+                               const int defaultButton, const int escapeButton )
+{
+  ButtonInfos lst;
+  int id = 0;
+  lst.append( ButtonInfo( id++, button1 ) );
+  lst.append( ButtonInfo( id++, button2 ) );
+  lst.append( ButtonInfo( id++, button3 ) );
+  lst.append( ButtonInfo( id++, button4 ) );
+  return messageBox( SUIT_MessageBox::Critical, parent, title, text, lst, 
+                     defaultButton, escapeButton );
+}
+
+/*!
+  \brief Show warning message box with four custom buttons.
+
+  Parameters \a button1, \a button2, \a button3 and \a button4 specify 
+  the buttons text.
+  The function returns clicked button id. The identifiers for the buttons
+  are assigned automatically. The first button is identified as 0, the
+  second one as 1, etc.
+
+  The \a defaultButton parameter allows to specify the button which is assigned
+  for the \c Return or \c Enter key. Similarly, \a escapeButton parameter
+  allows specifing the button which is assigned for \c Escape key.
+  If these parameters are not specified (-1 by default), the first button
+  is set as default button and the last one is defined as escape button.
+
+  \param parent parent widget
+  \param title message box title
+  \param text message box text
+  \param button1 first button text
+  \param button2 second button text
+  \param button3 third button text
+  \param button4 fourth button text
+  \param defaultButton default button
+  \param escapeButton escape button
+  \return button used button id
+*/
+int SUIT_MessageBox::warning( QWidget* parent, const QString& title, const QString& text,
+                              const QString& button1, const QString& button2, 
+                              const QString& button3, const QString& button4,
+                              const int defaultButton, const int escapeButton )
+{
+  ButtonInfos lst;
+  int id = 0;
+  lst.append( ButtonInfo( id++, button1 ) );
+  lst.append( ButtonInfo( id++, button2 ) );
+  lst.append( ButtonInfo( id++, button3 ) );
+  lst.append( ButtonInfo( id++, button4 ) );
+  return messageBox( SUIT_MessageBox::Warning, parent, title, text, lst, 
+                     defaultButton, escapeButton );
+}
+
+/*!
+  \brief Show information message box with four custom buttons.
+
+  Parameters \a button1, \a button2, \a button3 and \a button4 specify 
+  the buttons text.
+  The function returns clicked button id. The identifiers for the buttons
+  are assigned automatically. The first button is identified as 0, the
+  second one as 1, etc.
+
+  The \a defaultButton parameter allows to specify the button which is assigned
+  for the \c Return or \c Enter key. Similarly, \a escapeButton parameter
+  allows specifing the button which is assigned for \c Escape key.
+  If these parameters are not specified (-1 by default), the first button
+  is set as default button and the last one is defined as escape button.
+
+  \param parent parent widget
+  \param title message box title
+  \param text message box text
+  \param button1 first button text
+  \param button2 second button text
+  \param button3 third button text
+  \param button4 fourth button text
+  \param defaultButton default button
+  \param escapeButton escape button
+  \return button used button id
+*/
+int SUIT_MessageBox::information( QWidget* parent, const QString& title, const QString& text,
+                                  const QString& button1, const QString& button2, 
+                                  const QString& button3, const QString& button4,
+                                  const int defaultButton, const int escapeButton )
+{
+  ButtonInfos lst;
+  int id = 0;
+  lst.append( ButtonInfo( id++, button1 ) );
+  lst.append( ButtonInfo( id++, button2 ) );
+  lst.append( ButtonInfo( id++, button3 ) );
+  lst.append( ButtonInfo( id++, button4 ) );
+  return messageBox( SUIT_MessageBox::Information, parent, title, text, lst, 
+                     defaultButton, escapeButton );
+}
+
+/*!
+  \brief Show question message box with four custom buttons.
+
+  Parameters \a button1, \a button2, \a button3 and \a button4 specify 
+  the buttons text.
+  The function returns clicked button id. The identifiers for the buttons
+  are assigned automatically. The first button is identified as 0, the
+  second one as 1, etc.
+
+  The \a defaultButton parameter allows to specify the button which is assigned
+  for the \c Return or \c Enter key. Similarly, \a escapeButton parameter
+  allows specifing the button which is assigned for \c Escape key.
+  If these parameters are not specified (-1 by default), the first button
+  is set as default button and the last one is defined as escape button.
+
+  \param parent parent widget
+  \param title message box title
+  \param text message box text
+  \param button1 first button text
+  \param button2 second button text
+  \param button3 third button text
+  \param button4 fourth button text
+  \param defaultButton default button
+  \param escapeButton escape button
+  \return button used button id
+*/
+int SUIT_MessageBox::question( QWidget* parent, const QString& title, const QString& text,
+                               const QString& button1, const QString& button2, 
+                               const QString& button3, const QString& button4,
+                               const int defaultButton, const int escapeButton )
+{
+  ButtonInfos lst;
+  int id = 0;
+  lst.append( ButtonInfo( id++, button1 ) );
+  lst.append( ButtonInfo( id++, button2 ) );
+  lst.append( ButtonInfo( id++, button3 ) );
+  lst.append( ButtonInfo( id++, button4 ) );
+  return messageBox( SUIT_MessageBox::Question, parent, title, text, lst, 
+                     defaultButton, escapeButton );
+}
+
+/*!
+  \brief Show critical message box with arbitrary number of user-specified
+         buttons.
+
+  List of buttons to be shown is specified via \a buttons parameter.
+  
+  The function returns clicked button id. The identifiers for the buttons
+  are assigned automatically. The first button is identified as 0, the
+  second one as 1, etc.
+
+  The \a defaultButton parameter allows to specify the button which is assigned
+  for the \c Return or \c Enter key. Similarly, \a escapeButton parameter
+  allows specifing the button which is assigned for \c Escape key.
+  If these parameters are not specified (-1 by default), the first button
+  is set as default button and the last one is defined as escape button.
+
+  \param parent parent widget
+  \param title message box title
+  \param text message box text
+  \param defaultButton default button
+  \param escapeButton escape button
+  \param buttons list of buttons to be shown
+  \return button used button id
+*/
+int SUIT_MessageBox::critical( QWidget* parent, const QString& title, const QString& text,
+                              const QStringList& buttons,
+                              const int defaultButton, const int escapeButton )
+{
+  ButtonInfos lst;
+  int id = 0;
+  Q_FOREACH( QString button, buttons )
+    lst.append( ButtonInfo( id++, button ) );
+  return messageBox( SUIT_MessageBox::Critical, parent, title, text, lst,
+                     defaultButton, escapeButton );
+}
+
+/*!
+  \brief Show warning message box with arbitrary number of user-specified
+         buttons.
+
+  List of buttons to be shown is specified via \a buttons parameter.
+  
+  The function returns clicked button id. The identifiers for the buttons
+  are assigned automatically. The first button is identified as 0, the
+  second one as 1, etc.
+
+  The \a defaultButton parameter allows to specify the button which is assigned
+  for the \c Return or \c Enter key. Similarly, \a escapeButton parameter
+  allows specifing the button which is assigned for \c Escape key.
+  If these parameters are not specified (-1 by default), the first button
+  is set as default button and the last one is defined as escape button.
+
+  \param parent parent widget
+  \param title message box title
+  \param text message box text
+  \param defaultButton default button
+  \param escapeButton escape button
+  \param buttons list of buttons to be shown
+  \return button used button id
+*/
+int SUIT_MessageBox::warning( QWidget* parent, const QString& title, const QString& text,
+                             const QStringList& buttons,
+                             const int defaultButton, const int escapeButton )
+{
+  ButtonInfos lst;
+  int id = 0;
+  Q_FOREACH( QString button, buttons )
+    lst.append( ButtonInfo( id++, button ) );
+  return messageBox( SUIT_MessageBox::Warning, parent, title, text, lst,
+                     defaultButton, escapeButton );
+}
+
+/*!
+  \brief Show information message box with arbitrary number of user-specified
+         buttons.
+
+  List of buttons to be shown is specified via \a buttons parameter.
+  
+  The function returns clicked button id. The identifiers for the buttons
+  are assigned automatically. The first button is identified as 0, the
+  second one as 1, etc.
+
+  The \a defaultButton parameter allows to specify the button which is assigned
+  for the \c Return or \c Enter key. Similarly, \a escapeButton parameter
+  allows specifing the button which is assigned for \c Escape key.
+  If these parameters are not specified (-1 by default), the first button
+  is set as default button and the last one is defined as escape button.
+
+  \param parent parent widget
+  \param title message box title
+  \param text message box text
+  \param defaultButton default button
+  \param escapeButton escape button
+  \param buttons list of buttons to be shown
+  \return button used button id
+*/
+int SUIT_MessageBox::information( QWidget* parent, const QString& title, const QString& text,
+                                 const QStringList& buttons,
+                                 const int defaultButton, const int escapeButton )
+{
+  ButtonInfos lst;
+  int id = 0;
+  Q_FOREACH( QString button, buttons )
+    lst.append( ButtonInfo( id++, button ) );
+  return messageBox( SUIT_MessageBox::Information, parent, title, text, lst,
+                     defaultButton, escapeButton );
+}
+
+/*!
+  \brief Show question message box with arbitrary number of user-specified
+         buttons.
+
+  List of buttons to be shown is specified via \a buttons parameter.
+  
+  The function returns clicked button id. The identifiers for the buttons
+  are assigned automatically. The first button is identified as 0, the
+  second one as 1, etc.
+
+  The \a defaultButton parameter allows to specify the button which is assigned
+  for the \c Return or \c Enter key. Similarly, \a escapeButton parameter
+  allows specifing the button which is assigned for \c Escape key.
+  If these parameters are not specified (-1 by default), the first button
+  is set as default button and the last one is defined as escape button.
+
+  \param parent parent widget
+  \param title message box title
+  \param text message box text
+  \param defaultButton default button
+  \param escapeButton escape button
+  \param buttons list of buttons to be shown
+  \return button used button id
+*/
+int SUIT_MessageBox::question( QWidget* parent, const QString& title, const QString& text,
+                              const QStringList& buttons,
+                              const int defaultButton, const int escapeButton )
+{
+  ButtonInfos lst;
+  int id = 0;
+  Q_FOREACH( QString button, buttons )
+    lst.append( ButtonInfo( id++, button ) );
+  return messageBox( SUIT_MessageBox::Question, parent, title, text, lst,
+                     defaultButton, escapeButton );
+}
+
+/*!
+  \brief Show critical message box with arbitrary number of user-specified
+         buttons.
+
+  The function accepts arbitrary number of parameters. Each parameter starting
+  from \a btn should be of type const char* to specify the button text.
+  After the last button parameter and additional 0 (zero) value should be 
+  specified.
+  
+  The function returns clicked button id. The identifiers for the buttons
+  are assigned automatically. The first button is identified as 0, the
+  second one as 1, etc.
+
+  The \a defaultButton parameter allows to specify the button which is assigned
+  for the \c Return or \c Enter key. Similarly, \a escapeButton parameter
+  allows specifing the button which is assigned for \c Escape key.
+  If these parameters are not specified (-1 by default), the first button
+  is set as default button and the last one is defined as escape button.
+
+  \param parent parent widget
+  \param title message box title
+  \param text message box text
+  \param defaultButton default button
+  \param escapeButton escape button
+  \param btn first button text
+  \return button used button id
+*/
+int SUIT_MessageBox::critical( QWidget* parent, const QString& title, const QString& text, 
+                               const int defaultButton, const int escapeButton, 
+                               char* btn, ... )
+{
+  va_list args;
+  va_start( args, btn );
+  return messageBox( SUIT_MessageBox::Critical, parent, title, text,
+                     messageList( btn, args ),
+                     defaultButton, escapeButton );
+}
+
+/*!
+  \brief Show warning message box with arbitrary number of user-specified
+         buttons.
+
+  The function accepts arbitrary number of parameters. Each parameter starting
+  from \a btn should be of type const char* to specify the button text.
+  After the last button parameter and additional 0 (zero) value should be 
+  specified.
+  
+  The function returns clicked button id. The identifiers for the buttons
+  are assigned automatically. The first button is identified as 0, the
+  second one as 1, etc.
+
+  The \a defaultButton parameter allows to specify the button which is assigned
+  for the \c Return or \c Enter key. Similarly, \a escapeButton parameter
+  allows specifing the button which is assigned for \c Escape key.
+  If these parameters are not specified (-1 by default), the first button
+  is set as default button and the last one is defined as escape button.
+
+  \param parent parent widget
+  \param title message box title
+  \param text message box text
+  \param defaultButton default button
+  \param escapeButton escape button
+  \param btn first button text
+  \return button used button id
+*/
+int SUIT_MessageBox::warning( QWidget* parent, const QString& title, const QString& text, 
+                              const int defaultButton, const int escapeButton, 
+                              char* btn, ... )
+{
+  va_list args;
+  va_start( args, btn );
+  return messageBox( SUIT_MessageBox::Warning, parent, title, text,
+                     messageList( btn, args ),
+                     defaultButton, escapeButton );
+}
+
+/*!
+  \brief Show information message box with arbitrary number of user-specified
+         buttons.
+
+  The function accepts arbitrary number of parameters. Each parameter starting
+  from \a btn should be of type const char* to specify the button text.
+  After the last button parameter and additional 0 (zero) value should be 
+  specified.
+  
+  The function returns clicked button id. The identifiers for the buttons
+  are assigned automatically. The first button is identified as 0, the
+  second one as 1, etc.
+
+  The \a defaultButton parameter allows to specify the button which is assigned
+  for the \c Return or \c Enter key. Similarly, \a escapeButton parameter
+  allows specifing the button which is assigned for \c Escape key.
+  If these parameters are not specified (-1 by default), the first button
+  is set as default button and the last one is defined as escape button.
+
+  \param parent parent widget
+  \param title message box title
+  \param text message box text
+  \param defaultButton default button
+  \param escapeButton escape button
+  \param btn first button text
+  \return button used button id
+*/
+int SUIT_MessageBox::information( QWidget* parent, const QString& title, const QString& text, 
+                                  const int defaultButton, const int escapeButton, 
+                                  char* btn, ... )
+{
+  va_list args;
+  va_start( args, btn );
+  return messageBox( SUIT_MessageBox::Information, parent, title, text,
+                     messageList( btn, args ),
+                     defaultButton, escapeButton );
+}
+
+/*!
+  \brief Show question message box with arbitrary number of user-specified
+         buttons.
+
+  The function accepts arbitrary number of parameters. Each parameter starting
+  from \a btn should be of type const char* to specify the button text.
+  After the last button parameter and additional 0 (zero) value should be 
+  specified.
+  
+  The function returns clicked button id. The identifiers for the buttons
+  are assigned automatically. The first button is identified as 0, the
+  second one as 1, etc.
+
+  The \a defaultButton parameter allows to specify the button which is assigned
+  for the \c Return or \c Enter key. Similarly, \a escapeButton parameter
+  allows specifing the button which is assigned for \c Escape key.
+  If these parameters are not specified (-1 by default), the first button
+  is set as default button and the last one is defined as escape button.
+
+  \param parent parent widget
+  \param title message box title
+  \param text message box text
+  \param defaultButton default button
+  \param escapeButton escape button
+  \param btn first button text
+  \return button used button id
+*/
+int SUIT_MessageBox::question( QWidget* parent, const QString& title, const QString& text, 
+                               const int defaultButton, const int escapeButton, 
+                               char* btn, ... )
+{
+  va_list args;
+  va_start( args, btn );
+  return messageBox( SUIT_MessageBox::Question, parent, title, text,
+                     messageList( btn, args ),
+                     defaultButton, escapeButton );
+}
+
+/*!
+  \brief Parse arbitrary arguments list.
+
+  The last parameter in a sequence should be 0 (zero) value.
+
+  \param txt first argument which starts arbitrary sequence
+  \param args arguments list from the stack
+  \return list of buttons infos
+*/
+SUIT_MessageBox::ButtonInfos SUIT_MessageBox::messageList( char* txt, va_list& args )
+{
+  int i = 0;
+  ButtonInfos lst;
+  char* cur = txt;
+  while ( cur )
+  {
+    lst.append( ButtonInfo( i++, cur ) );
+    cur = va_arg( args, char* );
+  }
+
+  va_end( args );
+
+  return lst;
+}
+
+/*!
+  \brief Create and show the message box.
+  \param icon icon type
+  \param parent parent widget
+  \param title message box title
+  \param text message box text
+  \param lst list of buttons infos
+  \param defaultButton default button
+  \param escapeButton escape button
+  \return button used button id
+*/
+int SUIT_MessageBox::messageBox( Icon icon, QWidget* parent, 
+                                 const QString& title, const QString& text, 
+                                 const ButtonInfos& lst, 
+                                 const int defaultButton, 
+                                 const int escapeButton )
+{
+  SUIT_MessageBox msgBox( icon, title, text, NoButton, parent );
+
+  QMap<QAbstractButton*, int> bm;
+  for ( int i = 0; i < lst.count(); i++ )
+  {
+    int btn         = lst[i].id();
+    QString txt     = lst[i].text();
+    ButtonRole role = lst[i].role();
+
+    QPushButton* pb = msgBox.addButton( txt, role );
+    bm.insert( pb, btn );
+
+    if ( ( defaultButton == -1 && i == 0 ) || btn == defaultButton )
+      msgBox.setDefaultButton( pb );
+    if ( ( escapeButton == -1 && i == lst.count() - 1 ) || btn == escapeButton )
+      msgBox.setEscapeButton( pb );
+  }
+    
+  SUIT_OverrideCursor cw( parent ? parent->cursor() : Qt::ArrowCursor );
+
+  int res = msgBox.exec();
+  if ( res != -1 )
+    res = bm[msgBox.clickedButton()];
+
+  QApplication::processEvents();
+
+  return res;
+}
+
diff --git a/src/SUITT/SUIT_MessageBox.h b/src/SUITT/SUIT_MessageBox.h
new file mode 100755 (executable)
index 0000000..b00040c
--- /dev/null
@@ -0,0 +1,167 @@
+// Copyright (C) 2007-2015  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
+//
+
+#ifndef SUIT_MESSAGEBOX_H
+#define SUIT_MESSAGEBOX_H
+
+#include "SUIT.h"
+
+#include <QMap>
+#include <QList>
+#include <QMessageBox>
+
+class SUIT_EXPORT SUIT_MessageBox : public QMessageBox
+{
+  Q_OBJECT
+public:
+  // construction/destruction
+  SUIT_MessageBox( QWidget* = 0 );
+  SUIT_MessageBox( Icon, const QString&, const QString&, StandardButtons buttons = NoButton,
+                   QWidget* = 0, Qt::WindowFlags = Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint );
+  ~SUIT_MessageBox();
+
+  // customize the standard buttons text
+  QString               buttonText( StandardButton ) const;
+  void                  setButtonText( StandardButton, const QString& );
+
+  // message box with standard buttons
+  static StandardButton critical( QWidget* parent, const QString& title, const QString& text,
+                                  StandardButtons buttons = Ok, StandardButton defaultButton = NoButton );
+  static StandardButton warning( QWidget* parent, const QString& title, const QString& text,
+                                 StandardButtons buttons = Ok, StandardButton defaultButton = NoButton );
+  static StandardButton information( QWidget* parent, const QString& title, const QString& text,
+                                     StandardButtons buttons = Ok, StandardButton defaultButton = NoButton );
+  static StandardButton question( QWidget* parent, const QString& title, const QString& text,
+                                  StandardButtons buttons = Ok, StandardButton defaultButton = NoButton );
+  
+  // message boxes with one custom button
+  static int            critical( QWidget* parent, const QString& title, const QString& text,
+                                  const QString& button );
+  static int            warning( QWidget* parent, const QString& title, const QString& text,
+                                 const QString& button );
+  static int            information( QWidget* parent, const QString& title, const QString& text,
+                                     const QString& button );
+  static int            question( QWidget* parent, const QString& title, const QString& text,
+                                  const QString& button );
+
+  // message boxes with two custom buttons
+  static int            critical( QWidget* parent, const QString& title, const QString& text,
+                                  const QString& button1, const QString& button2, 
+                                  const int defaultButton = -1, const int escapeButton = -1 );
+  static int            warning( QWidget* parent, const QString& title, const QString& text,
+                                 const QString& button1, const QString& button2, 
+                                 const int defaultButton = -1, const int escapeButton = -1 );
+  static int            information( QWidget* parent, const QString& title, const QString& text,
+                                     const QString& button1, const QString& button2, 
+                                     const int defaultButton = -1, const int escapeButton = -1 );
+  static int            question( QWidget* parent, const QString& title, const QString& text,
+                                  const QString& button1, const QString& button2, 
+                                  const int defaultButton = -1, const int escapeButton = -1 );
+  
+  // message boxes with three custom buttons
+  static int            critical( QWidget* parent, const QString& title, const QString& text,
+                                  const QString& button1, const QString& button2, const QString& button3,
+                                  const int defaultButton = -1, const int escapeButton = -1 );
+  static int            warning( QWidget* parent, const QString& title, const QString& text,
+                                 const QString& button1, const QString& button2, const QString& button3,
+                                 const int defaultButton = -1, const int escapeButton = -1 );
+  static int            information( QWidget* parent, const QString& title, const QString& text,
+                                     const QString& button1, const QString& button2, const QString& button3,
+                                     const int defaultButton = -1, const int escapeButton = -1 );
+  static int            question( QWidget* parent, const QString& title, const QString& text,
+                                  const QString& button1, const QString& button2, const QString& button3,
+                                  const int defaultButton = -1, const int escapeButton = -1 );
+  
+  // message boxes with four custom buttons
+  static int            critical( QWidget* parent, const QString& title, const QString& text,
+                                  const QString& button1, const QString& button2,
+                                  const QString& button3, const QString& button4,
+                                  const int defaultButton = -1, const int escapeButton = -1 );
+  static int            warning( QWidget* parent, const QString& title, const QString& text,
+                                 const QString& button1, const QString& button2,
+                                 const QString& button3, const QString& button4,
+                                 const int defaultButton = -1, const int escapeButton = -1 );
+  static int            information( QWidget* parent, const QString& title, const QString& text,
+                                     const QString& button1, const QString& button2,
+                                     const QString& button3, const QString& button4,
+                                     const int defaultButton = -1, const int escapeButton = -1 );
+  static int            question( QWidget* parent, const QString& title, const QString& text,
+                                  const QString& button1, const QString& button2,
+                                  const QString& button3, const QString& button4,
+                                  const int defaultButton = -1, const int escapeButton = -1 );
+  
+  // message boxes with arbitrary number of buttons
+  static int            critical( QWidget* parent, const QString& title, const QString& text,
+                                  const QStringList& buttons,
+                                  const int defaultButton = -1, const int escapeButton = -1 );
+  static int            warning( QWidget* parent, const QString& title, const QString& text,
+                                const QStringList& buttons,
+                                 const int defaultButton = -1, const int escapeButton = -1 );
+  static int            information( QWidget* parent, const QString& title, const QString& text,
+                                    const QStringList& buttons,
+                                     const int defaultButton = -1, const int escapeButton = -1 );
+  static int            question( QWidget* parent, const QString& title, const QString& text,
+                                  const QStringList& buttons,
+                                  const int defaultButton = -1, const int escapeButton = -1 );
+
+  static int            critical( QWidget* parent, const QString& title, const QString& text, 
+                                  const int defaultButton, const int escapeButton, 
+                                  char*, ... );
+  static int            warning( QWidget* parent, const QString& title, const QString& text,
+                                 const int defaultButton, const int escapeButton, 
+                                 char*, ... );
+  static int            information( QWidget* parent, const QString& title, const QString& text,
+                                     const int defaultButton, const int escapeButton, 
+                                     char*, ... );
+  static int            question( QWidget* parent, const QString& title, const QString& text,
+                                  const int defaultButton, const int escapeButton, 
+                                  char*, ... );
+
+private:
+  class ButtonInfo
+  {
+  public:
+    ButtonInfo( const int id, 
+                const QString& text, 
+                const ButtonRole role = ActionRole )
+      : myId( id ), myText( text ), myRole( role ) {}
+    int        id()   const { return myId;   }
+    QString    text() const { return myText; }
+    ButtonRole role() const { return myRole; }
+  private:
+    int        myId;      //!< button id
+    QString    myText;    //!< button text
+    ButtonRole myRole;    //!< button role
+  };
+
+  typedef QList<ButtonInfo> ButtonInfos;
+
+private:
+  static int          messageBox( SUIT_MessageBox::Icon icon, QWidget* parent, 
+                                  const QString& title, const QString& text, 
+                                  const ButtonInfos& lst, 
+                                  const int defaultButton = -1, 
+                                  const int escapeButton  = -1 );
+  static ButtonInfos  messageList( char*, va_list& );
+};
+
+#endif
diff --git a/src/SUITT/SUIT_OverrideCursor.cxx b/src/SUITT/SUIT_OverrideCursor.cxx
new file mode 100755 (executable)
index 0000000..aaf5090
--- /dev/null
@@ -0,0 +1,74 @@
+// Copyright (C) 2007-2015  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
+//
+
+#include "SUIT_OverrideCursor.h"
+
+#include <QApplication>
+
+/*!Constructor. Initialize wait cursor.*/
+SUIT_OverrideCursor::SUIT_OverrideCursor()
+{
+  QApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) );
+}
+
+/*!Copy constructor.*/
+SUIT_OverrideCursor::SUIT_OverrideCursor( const QCursor& cursor )
+{
+  QApplication::setOverrideCursor( cursor );
+}
+
+/*!Destructor. restoring override cursor.*/
+SUIT_OverrideCursor::~SUIT_OverrideCursor()
+{
+  QApplication::restoreOverrideCursor();
+}
+
+/*! Check cursors is empty */
+bool SUIT_OverrideCursor::isActive() const
+{
+  return myCursors.isEmpty();
+}
+
+/*!Suspend cursors.*/
+void SUIT_OverrideCursor::suspend()
+{
+  if ( !isActive() )
+    return;
+
+  while ( QApplication::overrideCursor() )
+  {
+    myCursors.prepend( *QApplication::overrideCursor() );
+    QApplication::restoreOverrideCursor();
+  }
+}
+
+/*!Resume cursors.*/
+void SUIT_OverrideCursor::resume()
+{
+  if ( isActive() )
+    return;
+
+  for ( QList<QCursor>::const_iterator it = myCursors.begin(); it != myCursors.end(); ++it )
+    QApplication::setOverrideCursor( *it );
+
+  myCursors.clear();
+}
diff --git a/src/SUITT/SUIT_OverrideCursor.h b/src/SUITT/SUIT_OverrideCursor.h
new file mode 100755 (executable)
index 0000000..d5f4d5b
--- /dev/null
@@ -0,0 +1,47 @@
+// Copyright (C) 2007-2015  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
+//
+
+#ifndef SUIT_OVERRIDECURSOR_H
+#define SUIT_OVERRIDECURSOR_H
+
+#include "SUIT.h"
+
+#include <QList>
+#include <QCursor>
+
+/*! \brief Class used for management cursors.*/
+class SUIT_EXPORT SUIT_OverrideCursor
+{
+public:
+  SUIT_OverrideCursor();
+  SUIT_OverrideCursor( const QCursor& );
+  virtual ~SUIT_OverrideCursor();
+
+  bool isActive() const;
+  void suspend();
+  void resume();
+
+private:
+  QList<QCursor> myCursors;
+};
+
+#endif
index 8c29843b48cb7a24af048184d5fa4a941ce87d9b..5e8ff2e0b07a21d4130225a4c0ccc7360329197a 100755 (executable)
@@ -57,6 +57,7 @@ IF(SALOME_USE_PYCONSOLE)
   INCLUDE_DIRECTORIES(
     ${PYTHON_INCLUDE_DIRS}
     ${PROJECT_SOURCE_DIR}/src/PyConsole
+    ${PROJECT_SOURCE_DIR}/src/PyConsoleBase
     ${PROJECT_SOURCE_DIR}/src/PyInterp
   )
 ENDIF()