]> SALOME platform Git repositories - modules/gui.git/commitdiff
Salome HOME
PyEditor refactoring
authorvsr <vsr@opencascade.com>
Thu, 28 Jul 2016 13:45:47 +0000 (16:45 +0300)
committervsr <vsr@opencascade.com>
Tue, 2 Aug 2016 12:53:35 +0000 (15:53 +0300)
* Remove dependency on Qtx in PyEditor package
* Redesign editor class;
* Change the way preferences are managed;
* Add main window class for PyEditor;
* Add pyeditor standalone executable;
* Redesign build procedure for PyEditor;
* Move PyEditor to standalone project in tools directory;
* Add Python wrappings (via sip) for PyEditor widget.

88 files changed:
src/CMakeLists.txt
src/LightApp/LightApp_Application.cxx
src/PyEditor/CMakeLists.txt [deleted file]
src/PyEditor/PyEditor.h [deleted file]
src/PyEditor/PyEditor_Editor.cxx [deleted file]
src/PyEditor/PyEditor_Editor.h [deleted file]
src/PyEditor/PyEditor_LineNumberArea.cxx [deleted file]
src/PyEditor/PyEditor_LineNumberArea.h [deleted file]
src/PyEditor/PyEditor_PyHighlighter.cxx [deleted file]
src/PyEditor/PyEditor_PyHighlighter.h [deleted file]
src/PyEditor/PyEditor_Settings.cxx [deleted file]
src/PyEditor/PyEditor_Settings.h [deleted file]
src/PyEditor/PyEditor_SettingsDlg.cxx [deleted file]
src/PyEditor/PyEditor_SettingsDlg.h [deleted file]
src/PyEditor/resources/translations/PyEditor_msg_en.ts [deleted file]
src/PyEditor/resources/translations/PyEditor_msg_fr.ts [deleted file]
src/PyEditor/resources/translations/PyEditor_msg_ja.ts [deleted file]
src/PyViewer/CMakeLists.txt
src/PyViewer/PyViewer.cxx [deleted file]
src/PyViewer/PyViewer_Settings.cxx [new file with mode: 0644]
src/PyViewer/PyViewer_Settings.h [new file with mode: 0644]
src/PyViewer/PyViewer_ViewModel.cxx
src/PyViewer/PyViewer_ViewModel.h
src/PyViewer/PyViewer_ViewWindow.cxx
src/PyViewer/PyViewer_ViewWindow.h
src/PyViewer/resources/PyEditor.qrc [deleted file]
src/PyViewer/resources/PyViewer_images.ts [new file with mode: 0644]
src/PyViewer/resources/PyViewer_msg_en.ts [new file with mode: 0644]
src/PyViewer/resources/PyViewer_msg_fr.ts [new file with mode: 0644]
src/PyViewer/resources/PyViewer_msg_ja.ts [new file with mode: 0644]
src/PyViewer/resources/images/py_browser.png [deleted file]
src/PyViewer/resources/images/py_close.png [deleted file]
src/PyViewer/resources/images/py_copy.png [deleted file]
src/PyViewer/resources/images/py_cut.png [deleted file]
src/PyViewer/resources/images/py_delete.png [deleted file]
src/PyViewer/resources/images/py_new.png [deleted file]
src/PyViewer/resources/images/py_open.png [deleted file]
src/PyViewer/resources/images/py_paste.png [deleted file]
src/PyViewer/resources/images/py_preferences.png [deleted file]
src/PyViewer/resources/images/py_redo.png [deleted file]
src/PyViewer/resources/images/py_save.png [deleted file]
src/PyViewer/resources/images/py_save_as.png [deleted file]
src/PyViewer/resources/images/py_select_all.png [deleted file]
src/PyViewer/resources/images/py_undo.png [deleted file]
src/PyViewer/resources/translations/PyViewer_msg_en.ts [deleted file]
src/PyViewer/resources/translations/PyViewer_msg_fr.ts [deleted file]
src/PyViewer/resources/translations/PyViewer_msg_ja.ts [deleted file]
tools/CMakeLists.txt
tools/PyEditor/CMakeLists.txt [new file with mode: 0644]
tools/PyEditor/src/CMakeLists.txt [new file with mode: 0644]
tools/PyEditor/src/PyEditor.cxx [new file with mode: 0644]
tools/PyEditor/src/PyEditor.h [new file with mode: 0644]
tools/PyEditor/src/PyEditor_Editor.cxx [new file with mode: 0644]
tools/PyEditor/src/PyEditor_Editor.h [new file with mode: 0644]
tools/PyEditor/src/PyEditor_LineNumberArea.cxx [new file with mode: 0644]
tools/PyEditor/src/PyEditor_LineNumberArea.h [new file with mode: 0644]
tools/PyEditor/src/PyEditor_PyHighlighter.cxx [new file with mode: 0644]
tools/PyEditor/src/PyEditor_PyHighlighter.h [new file with mode: 0644]
tools/PyEditor/src/PyEditor_Settings.cxx [new file with mode: 0644]
tools/PyEditor/src/PyEditor_Settings.h [new file with mode: 0644]
tools/PyEditor/src/PyEditor_SettingsDlg.cxx [new file with mode: 0644]
tools/PyEditor/src/PyEditor_SettingsDlg.h [new file with mode: 0644]
tools/PyEditor/src/PyEditor_StdSettings.cxx [new file with mode: 0644]
tools/PyEditor/src/PyEditor_StdSettings.h [new file with mode: 0644]
tools/PyEditor/src/PyEditor_Window.cxx [new file with mode: 0644]
tools/PyEditor/src/PyEditor_Window.h [new file with mode: 0644]
tools/PyEditor/src/python/CMakeLists.txt [new file with mode: 0644]
tools/PyEditor/src/python/PyEditorPy.sip [new file with mode: 0644]
tools/PyEditor/src/resources/PyEditor.qrc [new file with mode: 0644]
tools/PyEditor/src/resources/about.txt [new file with mode: 0644]
tools/PyEditor/src/resources/images/py_copy.png [new file with mode: 0644]
tools/PyEditor/src/resources/images/py_cut.png [new file with mode: 0644]
tools/PyEditor/src/resources/images/py_delete.png [new file with mode: 0644]
tools/PyEditor/src/resources/images/py_editor.png [new file with mode: 0644]
tools/PyEditor/src/resources/images/py_exit.png [new file with mode: 0644]
tools/PyEditor/src/resources/images/py_help.png [new file with mode: 0644]
tools/PyEditor/src/resources/images/py_new.png [new file with mode: 0644]
tools/PyEditor/src/resources/images/py_open.png [new file with mode: 0644]
tools/PyEditor/src/resources/images/py_paste.png [new file with mode: 0644]
tools/PyEditor/src/resources/images/py_preferences.png [new file with mode: 0644]
tools/PyEditor/src/resources/images/py_redo.png [new file with mode: 0644]
tools/PyEditor/src/resources/images/py_save.png [new file with mode: 0644]
tools/PyEditor/src/resources/images/py_save_as.png [new file with mode: 0644]
tools/PyEditor/src/resources/images/py_select_all.png [new file with mode: 0644]
tools/PyEditor/src/resources/images/py_undo.png [new file with mode: 0644]
tools/PyEditor/src/resources/translations/PyEditor_msg_en.ts [new file with mode: 0644]
tools/PyEditor/src/resources/translations/PyEditor_msg_fr.ts [new file with mode: 0644]
tools/PyEditor/src/resources/translations/PyEditor_msg_ja.ts [new file with mode: 0644]

index f7161a9cc471f5fefb2c17e4659b75b19e7e10fc..f4b1b7fed130e67ebe5aae262c256c816fc0635e 100755 (executable)
@@ -119,7 +119,6 @@ ENDIF()
 # Python Viewer
 ##
 IF(SALOME_USE_PYVIEWER)
-  ADD_SUBDIRECTORY(PyEditor)
   ADD_SUBDIRECTORY(PyViewer)
 ENDIF(SALOME_USE_PYVIEWER)
 
index 70ddd87e93ed1a3326146669d049d3423a22da5b..9702d04f255f31b4f83840646924e94d42d7c22d 100644 (file)
@@ -85,6 +85,7 @@
 #include <SUIT_ViewWindow.h>
 
 #include <Qtx.h>
+#include <QtxFontEdit.h>
 #include <QtxToolBar.h>
 #include <QtxTreeView.h>
 #include <QtxMRUAction.h>
@@ -2898,8 +2899,9 @@ void LightApp_Application::createPreferences( LightApp_Preferences* pref )
   int pyeditTab = pref->addPreference( tr( "PREF_TAB_PYEDITOR" ), salomeCat );
   // ... "Font settings" group <<start>>
   int pyFontGroup = pref->addPreference( tr( "PREF_GROUP_PY_FONT" ), pyeditTab );
-  pref->addPreference( tr( "PREF_PY_FONT" ), pyFontGroup,
-    LightApp_Preferences::Font, "PyEditor", "Font" );
+  int pyFont = pref->addPreference( tr( "PREF_PY_FONT" ), pyFontGroup,
+                                    LightApp_Preferences::Font, "PyEditor", "Font" );
+  pref->setItemProperty( "features", QtxFontEdit::Family | QtxFontEdit::Size | QtxFontEdit::UserSize, pyFont );
   // ... "Font settings" group <<end>>
   // ... "Display settings" group <<start>>
   int pyDispGroup = pref->addPreference( tr( "PREF_GROUP_PY_DISPLAY" ), pyeditTab );
@@ -3686,39 +3688,6 @@ void LightApp_Application::preferencesChanged( const QString& sec, const QString
     }
   }
 #endif
-
-#ifndef DISABLE_PYVIEWER
-  if ( sec == QString( "PyViewer" ) && ( param == QString( "HighlightCurrentLine" ) ||
-                                         param == QString( "LineNumberArea" ) ||
-                                         param == QString( "TextWrapping" ) ||
-                                         param == QString( "CenterCursorOnScroll" ) ||
-                                         param == QString( "TabSpaceVisible" ) ||
-                                         param == QString( "TabSize" ) ||
-                                         param == QString( "VerticalEdge" ) ||
-                                         param == QString( "NumberColumns" ) ||
-                                         param == QString( "Font" ) ) )
-  {
-    QList<SUIT_ViewManager*> lst;
-    viewManagers( PyViewer_Viewer::Type(), lst );
-    QListIterator<SUIT_ViewManager*> itPy( lst );
-    while ( itPy.hasNext() )
-    {
-      SUIT_ViewManager* viewMgr = itPy.next();
-      SUIT_ViewModel* vm = viewMgr->getViewModel();
-      if ( !vm || !vm->inherits( "PyViewer_Viewer" ) )
-        continue;
-
-      PyViewer_Viewer* pyEditVM = dynamic_cast<PyViewer_Viewer*>( vm );
-
-      viewMgr->setViewModel( vm );
-      PyViewer_ViewWindow* pyView = dynamic_cast<PyViewer_ViewWindow*>( viewMgr->getActiveView() );
-      if( pyView )
-      {
-        pyView->setPreferences();
-      }
-    }
-  }
-#endif
 }
 
 /*!
diff --git a/src/PyEditor/CMakeLists.txt b/src/PyEditor/CMakeLists.txt
deleted file mode 100644 (file)
index be15881..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-# Copyright (C) 2015-2016  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 : Maxim GLIBIN, Open CASCADE S.A.S. (maxim.glibin@opencascade.com)
-#
-
-INCLUDE(UseQtExt)
-
-# --- options ---
-
-# additional include directories
-INCLUDE_DIRECTORIES(
-  ${QT_INCLUDES}
-  ${PROJECT_SOURCE_DIR}/src/Qtx
-)
-
-# additional preprocessor / compiler flags
-ADD_DEFINITIONS(${QT_DEFINITIONS})
-
-# libraries to link to
-SET(_link_LIBRARIES ${PLATFORM_LIBS} ${QT_LIBRARIES} qtx)
-
-# --- headers ---
-
-# header files / to be processed by moc
-SET(_moc_HEADERS
-  PyEditor_Editor.h
-  PyEditor_LineNumberArea.h
-  PyEditor_PyHighlighter.h
-  PyEditor_SettingsDlg.h
-)
-
-# header files / no moc processing
-SET(_other_HEADERS
-  PyEditor.h
-  PyEditor_Settings.h
-)
-
-# header files / to install
-SET(PyEditor_HEADERS ${_moc_HEADERS} ${_other_HEADERS})
-
-# --- resources ---
-
-# resource files / to be processed by lrelease
-SET(RESOURCES_PATH resources)
-
-SET(_ts_RESOURCES
-  ${RESOURCES_PATH}/translations/PyEditor_msg_en.ts
-  ${RESOURCES_PATH}/translations/PyEditor_msg_fr.ts
-  ${RESOURCES_PATH}/translations/PyEditor_msg_ja.ts
-)
-
-# sources / moc wrappings
-QT_WRAP_MOC(_moc_SOURCES ${_moc_HEADERS})
-
-# sources / static
-SET(_other_SOURCES
-  PyEditor_Editor.cxx
-  PyEditor_LineNumberArea.cxx
-  PyEditor_PyHighlighter.cxx
-  PyEditor_Settings.cxx
-  PyEditor_SettingsDlg.cxx
-)
-
-# sources / to compile
-SET(PyEditor_SOURCES ${_other_SOURCES} ${_moc_SOURCES})
-
-# --- rules ---
-ADD_LIBRARY(PyEditor ${PyEditor_SOURCES})
-TARGET_LINK_LIBRARIES(PyEditor ${_link_LIBRARIES})
-INSTALL(TARGETS PyEditor EXPORT ${PROJECT_NAME}TargetGroup DESTINATION ${SALOME_INSTALL_LIBS})
-
-INSTALL(FILES ${PyEditor_HEADERS} DESTINATION ${SALOME_INSTALL_HEADERS})
-QT_INSTALL_TS_RESOURCES("${_ts_RESOURCES}" "${SALOME_GUI_INSTALL_RES_DATA}")
diff --git a/src/PyEditor/PyEditor.h b/src/PyEditor/PyEditor.h
deleted file mode 100644 (file)
index 165f53a..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (C) 2015-2016  OPEN CASCADE
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-//
-// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
-// File   : PyEditor.h
-// Author : Maxim GLIBIN, Open CASCADE S.A.S. (maxim.glibin@opencascade.com)
-//
-
-#ifdef WIN32
-
-#if defined PYEDITOR_EXPORTS || defined PyEditor_EXPORTS
-#define PYEDITOR_EXPORT __declspec(dllexport)
-#else
-#define PYEDITOR_EXPORT __declspec(dllimport)
-#endif
-
-#else
-#define PYEDITOR_EXPORT
-#endif // WIN32
diff --git a/src/PyEditor/PyEditor_Editor.cxx b/src/PyEditor/PyEditor_Editor.cxx
deleted file mode 100644 (file)
index 141d7ee..0000000
+++ /dev/null
@@ -1,804 +0,0 @@
-// Copyright (C) 2015-2016  OPEN CASCADE
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-//
-// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
-// File   : PyEditor_Editor.cxx
-// Author : Maxim GLIBIN, Open CASCADE S.A.S. (maxim.glibin@opencascade.com)
-//
-
-//Local includes
-#include "PyEditor_Editor.h"
-#include "PyEditor_LineNumberArea.h"
-#include "PyEditor_PyHighlighter.h"
-#include "PyEditor_Settings.h"
-
-//Qtx includes
-#include <QtxResourceMgr.h>
-
-//Qt includes
-#include <QPainter>
-#include <QTextBlock>
-
-/*!
-  \class PyEditor_Editor
-  \brief Viewer/Editor is used to edit and show advanced plain text.
-*/
-
-/*!
-  \brief Constructor.
-  \param isSingle flag determined single application or reccesed.
-  \param theParent parent widget
-*/
-PyEditor_Editor::PyEditor_Editor( bool isSingle, QtxResourceMgr* theMgr, QWidget* theParent )
-  : QPlainTextEdit( theParent )
-{
-  my_Settings = new PyEditor_Settings( theMgr, isSingle );
-
-  // Create line number area
-  my_LineNumberArea = new PyEditor_LineNumberArea( this );
-  my_LineNumberArea->setMouseTracking( true );
-
-  my_SyntaxHighlighter = new PyEditor_PyHighlighter( this->document() );
-
-  // Signals and slots
-  connect( this, SIGNAL( blockCountChanged( int ) ), this, SLOT( updateLineNumberAreaWidth( int ) ) );
-  connect( this, SIGNAL( updateRequest( QRect, int ) ), this, SLOT( updateLineNumberArea( QRect, int ) ) );
-  connect( this, SIGNAL( cursorPositionChanged() ), this, SLOT( updateHighlightCurrentLine() ) );
-  connect( this, SIGNAL( cursorPositionChanged() ), this, SLOT( matchParentheses() ) );
-
-  updateStatement();
-}
-
-/*!
-  \brief Destructor.
-*/
-PyEditor_Editor::~PyEditor_Editor()
-{
-}
-
-/*!
-  Updates editor.
- */
-void PyEditor_Editor::updateStatement()
-{
-  //Set font size
-  QFont aFont = font();
-  aFont.setFamily( settings()->p_Font.family() );
-  aFont.setPointSize( settings()->p_Font.pointSize() );
-  setFont( aFont );
-
-  // Set line wrap mode
-  setLineWrapMode( settings()->p_TextWrapping ? QPlainTextEdit::WidgetWidth : QPlainTextEdit::NoWrap );
-
-  // Center the cursor on screen
-  setCenterOnScroll( settings()->p_CenterCursorOnScroll );
-
-  // Set size white spaces
-  setTabStopWidth( settings()->p_TabSize * 10 );
-
-  // Update current line highlight
-  updateHighlightCurrentLine();
-
-  // Update line numbers area
-  updateLineNumberAreaWidth( 0 );
-
-  my_SyntaxHighlighter->rehighlight();
-  viewport()->update();
-}
-
-/*!
-  SLOT: Delete the current selection's contents
- */
-void PyEditor_Editor::deleteSelected()
-{
-  QTextCursor aCursor = textCursor();
-  if ( aCursor.hasSelection() )
-    aCursor.removeSelectedText();
-  setTextCursor( aCursor );
-}
-
-/*!
-  \brief Reimplemented calss is to receive key press events for the plain text widget.
-  \param theEvent event
- */
-void PyEditor_Editor::keyPressEvent( QKeyEvent* theEvent )
-{
-  if ( theEvent->type() == QEvent::KeyPress )
-  {
-    int aKey = theEvent->key();
-    Qt::KeyboardModifiers aCtrl = theEvent->modifiers() & Qt::ControlModifier;
-    Qt::KeyboardModifiers aShift = theEvent->modifiers() & Qt::ShiftModifier;
-    
-    if ( aKey == Qt::Key_Tab || ( aKey == Qt::Key_Backtab || ( aKey == Qt::Key_Tab && aShift ) ) )
-    {
-      QTextCursor aCursor = textCursor();
-      aCursor.beginEditBlock();
-      tabIndentation( aKey == Qt::Key_Backtab );
-      aCursor.endEditBlock();
-      theEvent->accept();
-    }
-    else if ( aKey == Qt::Key_Enter || aKey == Qt::Key_Return )
-    {
-      QTextCursor aCursor = textCursor();
-      aCursor.beginEditBlock();
-      if ( lineIndent() == 0 )
-      {
-        QPlainTextEdit::keyPressEvent( theEvent );
-      }
-      aCursor.endEditBlock();
-      theEvent->accept();
-    }
-    else if ( theEvent == QKeySequence::MoveToStartOfLine || theEvent == QKeySequence::SelectStartOfLine )
-    {
-      QTextCursor aCursor = this->textCursor();
-      if ( QTextLayout* aLayout = aCursor.block().layout() )
-      {
-        if ( aLayout->lineForTextPosition( aCursor.position() - aCursor.block().position() ).lineNumber() == 0 )
-        {
-          handleHome( theEvent == QKeySequence::SelectStartOfLine );
-        }
-      }
-    }
-    else if ( ( aKey == Qt::Key_Colon || ( aKey == Qt::Key_Space && !aCtrl && !aShift ) ) &&
-              !textCursor().hasSelection() )
-    {
-      QTextCursor aCursor = textCursor();
-      aCursor.movePosition( QTextCursor::StartOfBlock, QTextCursor::KeepAnchor );
-      
-      QString aSelectedText = aCursor.selectedText();
-      int numSpaces = findFirstNonSpace( aSelectedText );
-      int amountChars = aSelectedText.size() - findFirstNonSpace( aSelectedText );
-      QString aLeadingText = aSelectedText.right( amountChars );
-      
-      QStringList aReservedWords;
-      aReservedWords.append( "except" );
-      if ( aKey == Qt::Key_Colon )
-      {
-        aReservedWords.append( "else" );
-        aReservedWords.append( "finally" );
-      }
-      else if ( aKey == Qt::Key_Space )
-      {
-        aReservedWords.append( "elif" );
-      }
-      
-      if ( aReservedWords.contains( aLeadingText ) )
-      {
-        QString aPreviousText = aCursor.block().previous().text();
-        int numSpacesPrevious = findFirstNonSpace( aPreviousText );
-        if ( numSpaces == numSpacesPrevious )
-        {
-          tabIndentation( true );
-          aCursor.movePosition( QTextCursor::EndOfBlock );
-          setTextCursor( aCursor );
-        }
-      }
-      QPlainTextEdit::keyPressEvent( theEvent );
-    }
-    else
-    {
-      QPlainTextEdit::keyPressEvent( theEvent );
-    }
-  }
-}
-
-/*!
-  \brief Reimplemented calss is to receive plain text widget resize events
-  which are passed in the event parameter.
-  \param theEvent event
- */
-void PyEditor_Editor::resizeEvent( QResizeEvent* theEvent )
-{
-  QPlainTextEdit::resizeEvent( theEvent );
-
-  // Change size geometry of line number area
-  QRect aContentsRect = contentsRect();
-  my_LineNumberArea->setGeometry(
-    QRect( aContentsRect.left(),
-           aContentsRect.top(),
-           lineNumberAreaWidth(),
-           aContentsRect.height() ) );
-}
-
-/*!
-  \brief Reimplemented calss is to receive paint events passed in theEvent.
-  \param theEvent event
- */
-void PyEditor_Editor::paintEvent( QPaintEvent* theEvent )
-{
-  QPlainTextEdit::paintEvent( theEvent );
-
-  QTextBlock aBlock( firstVisibleBlock() );
-  QPointF anOffset( contentOffset() );
-  QPainter aPainter( this->viewport() );
-
-  int aTabSpaces = this->tabStopWidth() / 10;
-
-  // Visualization tab spaces
-  if ( settings()->p_TabSpaceVisible )
-  {
-    qreal aTop = blockBoundingGeometry( aBlock ).translated( anOffset ).top();
-    while ( aBlock.isValid() && aTop <= theEvent->rect().bottom() )
-    {
-      if ( aBlock.isVisible() && blockBoundingGeometry( aBlock ).translated( anOffset ).toRect().intersects( theEvent->rect() ) )
-      {
-        QString aText = aBlock.text();
-        if ( aText.contains( QRegExp( "\\w+" ) ) )
-          aText.remove( QRegExp( "(?!\\w+)\\s+$" ) );
-        
-        int aColumn = 0;
-        int anIndex = 0;
-        while ( anIndex != -1 )
-        {
-          anIndex = aText.indexOf( QRegExp( QString( "^\\s{%1}" ).arg( aTabSpaces ) ), 0 );
-          if ( anIndex != -1 )
-          {
-            aColumn = aColumn + aTabSpaces;
-            aText = aText.mid( aTabSpaces );
-    
-            if ( aText.startsWith( ' ' ) )
-            {
-              QTextCursor aCursor( aBlock );
-              aCursor.setPosition( aBlock.position() + aColumn );
-      
-              QRect aRect = cursorRect( aCursor );
-              aPainter.setPen( QPen( Qt::darkGray, 1, Qt::DotLine ) );
-              aPainter.drawLine( aRect.x() + 1, aRect.top(), aRect.x() + 1, aRect.bottom() );
-            }
-          }
-        }
-      }
-      aBlock = aBlock.next();
-    }
-  }
-  
-  // Vertical edge line
-  if ( settings()->p_VerticalEdge )
-  {
-    const QRect aRect = theEvent->rect();
-    const QFont aFont = currentCharFormat().font();
-    int aNumberColumn =  QFontMetrics( aFont ).averageCharWidth() * settings()->p_NumberColumns + anOffset.x() + document()->documentMargin();
-    aPainter.setPen( QPen( Qt::lightGray, 1, Qt::SolidLine ) );
-    aPainter.drawLine( aNumberColumn, aRect.top(), aNumberColumn, aRect.bottom() );
-  }
-}
-
-/*!
-  \return manager of setting values.
- */
-PyEditor_Settings* PyEditor_Editor::settings()
-{
-  return my_Settings;
-}
-
-/*!
-  \brief Indenting and tabbing of the text
-  \param isShift flag defines reverse tab
- */
-void PyEditor_Editor::tabIndentation( bool isShift )
-{
-  QTextCursor aCursor = textCursor();
-  int aTabSpaces = this->tabStopWidth()/10;
-
-  if ( !aCursor.hasSelection() )
-  {
-    if ( !isShift )
-    {
-      int N = aCursor.columnNumber() % aTabSpaces;
-      aCursor.insertText( QString( aTabSpaces - N, QLatin1Char( ' ' ) ) );
-    }
-    else
-    {
-      QTextBlock aCurrentBlock = document()->findBlock( aCursor.position() );
-      int anIndentPos = findFirstNonSpace( aCurrentBlock.text() );
-      aCursor.setPosition( aCurrentBlock.position() + anIndentPos );
-      setTextCursor( aCursor );
-      
-      //if ( aCurrCursorColumnPos <= anIndentPos )
-      //{
-      int aColumnPos = aCursor.columnNumber();
-      if ( aColumnPos != 0 )
-      {
-        int N = aCursor.columnNumber() % aTabSpaces;
-        if ( N == 0 ) N = aTabSpaces;
-        aCursor.movePosition( QTextCursor::Left, QTextCursor::KeepAnchor, N );
-        aCursor.removeSelectedText();
-      }
-      setTextCursor( aCursor );
-      //}
-    }
-  }
-  else
-  {
-    indentSelection( isShift );
-  }
-}
-
-/*!
-  \brief Indenting and tabbing of the selected text
-  \param isShift flag defines reverse tab
- */
-void PyEditor_Editor::indentSelection( bool isShift )
-{
-  QTextCursor aCursor = this->textCursor();
-
-  int aCursorStart = aCursor.selectionStart();
-  int aCursorEnd = aCursor.selectionEnd();
-
-  QTextBlock aStartBlock = document()->findBlock( aCursorStart );
-  QTextBlock anEndBlock = document()->findBlock( aCursorEnd - 1 ).next();
-
-  int aTabSpaces = this->tabStopWidth()/10;
-
-  for ( QTextBlock aBlock = aStartBlock; aBlock.isValid() && aBlock != anEndBlock; aBlock = aBlock.next() )
-  {
-    QString aText = aBlock.text();
-    int anIndentPos = findFirstNonSpace( aText );
-    int N = ( anIndentPos % aTabSpaces );
-    
-    aCursor.setPosition( aBlock.position() + anIndentPos );
-    if ( !isShift )
-    {
-      aCursor.insertText( QString( aTabSpaces - N, QLatin1Char( ' ' ) ) );
-      setTextCursor( aCursor );
-    }
-    else
-    {
-      int aColumnPos = aCursor.columnNumber();
-      if ( aColumnPos != 0 )
-      {
-        int blockN = aColumnPos % aTabSpaces;
-        if ( blockN == 0 ) blockN = aTabSpaces;
-        aCursor.movePosition( QTextCursor::Left, QTextCursor::KeepAnchor, blockN );
-        aCursor.removeSelectedText();
-        setTextCursor( aCursor );
-      }
-    }
-  }
-
-  // Reselect the selected lines
-  aCursor.setPosition( aStartBlock.position() );
-  aCursor.setPosition( anEndBlock.previous().position(), QTextCursor::KeepAnchor );
-  aCursor.movePosition( QTextCursor::EndOfBlock, QTextCursor::KeepAnchor );
-  setTextCursor( aCursor );
-}
-
-/*!
-  \brief Finds the first non-white sapce in theText.
-  \param theText string
-  \return index of the first non-white space
- */
-int PyEditor_Editor::findFirstNonSpace( const QString& theText )
-{
-  int i = 0;
-  while ( i < theText.size() )
-  {
-    if ( !theText.at(i).isSpace() )
-      return i;
-    ++i;
-  }
-  return i;
-}
-
-/*!
-  \brief Auto line indenting
-  \return error code
- */
-int PyEditor_Editor::lineIndent()
-{
-  int aTabSpaces = this->tabStopWidth() / 10;
-
-  QTextCursor aCursor = textCursor();
-  aCursor.insertBlock();
-  setTextCursor( aCursor );
-
-  QTextBlock aCurrentBlock = aCursor.block();
-  if ( aCurrentBlock == document()->begin() )
-    return 0;
-
-  QTextBlock aPreviousBlock = aCurrentBlock.previous();
-
-  QString aPreviousText;
-  forever
-  {
-    if ( aPreviousBlock == document()->begin() )
-    {
-      aPreviousText = aPreviousBlock.text();
-      if ( aPreviousText.isEmpty() && aPreviousText.trimmed().isEmpty() )
-        return -1;
-      break;
-    }
-    
-    // If the text of this block is not empty then break the loop.
-    aPreviousText = aPreviousBlock.text();
-    if ( !aPreviousText.isEmpty() && !aPreviousText.trimmed().isEmpty() )
-      break;
-    
-    aPreviousBlock = aPreviousBlock.previous();
-  }
-  
-  int aTabIndentation = 0;
-  int anAmountIndentation = -1;
-  int i = 0;
-  while ( i < aPreviousText.size() )
-  {
-    if ( !aPreviousText.at(i).isSpace() )
-    {
-      anAmountIndentation = findFirstNonSpace( aPreviousText );
-      break;
-    }
-    else
-    {
-      ++aTabIndentation;
-    }
-    ++i;
-  }
-  
-  if ( anAmountIndentation == -1 )
-  {
-    if ( aTabIndentation > 0 )
-      anAmountIndentation = aTabIndentation;
-    else
-      return 0;
-  }
-  
-  const QString aPreviousTrimmed = aPreviousText.trimmed();
-  if ( aPreviousTrimmed.endsWith( ":" ) )
-  {
-    anAmountIndentation += aTabSpaces;
-  }
-  else
-  {
-    if ( aPreviousTrimmed == "continue"
-      || aPreviousTrimmed == "break"
-      || aPreviousTrimmed == "pass"
-      || aPreviousTrimmed == "return"
-      || aPreviousTrimmed == "raise"
-      || aPreviousTrimmed.startsWith( "raise " )
-      || aPreviousTrimmed.startsWith( "return " ) )
-      anAmountIndentation -= aTabSpaces;
-  }
-  
-  aCursor.insertText( QString( anAmountIndentation, QLatin1Char(' ') ) );
-  setTextCursor( aCursor );
-  
-  return 1;
-}
-
-/*!
-  \brief Set text cursor on home position.
- */
-void PyEditor_Editor::handleHome( bool isExtendLine )
-{
-  QTextCursor aCursor = textCursor();
-  QTextCursor::MoveMode aMode = QTextCursor::MoveAnchor;
-
-  if ( isExtendLine )
-    aMode = QTextCursor::KeepAnchor;
-
-  int anInitPos = aCursor.position();
-  int aBlockPos = aCursor.block().position();
-
-  QChar aCharacter = document()->characterAt( aBlockPos );
-  while ( aCharacter.category() == QChar::Separator_Space )
-  {
-    ++aBlockPos;
-    if ( aBlockPos == anInitPos )
-      break;
-    aCharacter = document()->characterAt( aBlockPos );
-  }
-  
-  if ( aBlockPos == anInitPos )
-    aBlockPos = aCursor.block().position();
-  
-  aCursor.setPosition( aBlockPos, aMode );
-  setTextCursor( aCursor );
-}
-
-/*!
-  SLOT: Updates the highlight current line.
- */
-void PyEditor_Editor::updateHighlightCurrentLine()
-{
-  QList<QTextEdit::ExtraSelection> anExtraSelections;
-  if ( !isReadOnly() && settings()->p_HighlightCurrentLine )
-  {
-    QTextEdit::ExtraSelection selection;
-    
-    QColor lineColor = QColor( Qt::gray ).lighter( 155 );
-    
-    selection.format.setBackground( lineColor );
-    selection.format.setProperty( QTextFormat::FullWidthSelection, QVariant( true ) );
-    selection.cursor = textCursor();
-    selection.cursor.clearSelection();
-    anExtraSelections.append( selection );
-  }
-  setExtraSelections( anExtraSelections );
-}
-
-/*!
-  \brief Creates line number area.
-  \param theEvent event for paint events.
- */
-void PyEditor_Editor::lineNumberAreaPaintEvent( QPaintEvent* theEvent )
-{
-  QPainter aPainter( my_LineNumberArea );
-  aPainter.fillRect( theEvent->rect(), QColor( Qt::lightGray ).lighter( 125 ) );
-
-  QTextBlock aBlock = firstVisibleBlock();
-  int aBlockNumber = aBlock.blockNumber();
-  int aTop = (int)blockBoundingGeometry( aBlock ).translated( contentOffset() ).top();
-  int aBottom = aTop + (int)blockBoundingRect( aBlock ).height();
-  int aCurrentLine = document()->findBlock( textCursor().position() ).blockNumber();
-
-  QFont aFont = aPainter.font();
-  aPainter.setPen( this->palette().color( QPalette::Text ) );
-
-  while ( aBlock.isValid() && aTop <= theEvent->rect().bottom() )
-  {
-    if ( aBlock.isVisible() && aBottom >= theEvent->rect().top() )
-    {
-      if ( aBlockNumber == aCurrentLine )
-      {
-        aPainter.setPen( Qt::darkGray );
-        aFont.setBold( true );
-        aPainter.setFont( aFont );
-      }
-      else
-      {
-        aPainter.setPen( Qt::gray ) ;
-        aFont.setBold( false );
-        aPainter.setFont( aFont );
-      }
-      QString aNumber = QString::number( aBlockNumber + 1 );
-      aPainter.drawText( 0, aTop, my_LineNumberArea->width(), fontMetrics().height(), Qt::AlignRight, aNumber );
-    }
-
-    aBlock = aBlock.next();
-    aTop = aBottom;
-    aBottom = aTop + (int)blockBoundingRect( aBlock ).height();
-    ++aBlockNumber;
-  }
-}
-
-/*!
-  \return width of line number area
- */
-int PyEditor_Editor::lineNumberAreaWidth()
-{
-  int aSpace = 0;
-
-  int aDigits = 1;
-  int aMaximum = qMax( 1, blockCount() );
-  while ( aMaximum >= 10 )
-  {
-    aMaximum /= 10;
-    ++aDigits;
-  }
-
-  if ( settings()->p_LineNumberArea )
-    aSpace += 5 + fontMetrics().width( QLatin1Char( '9' ) ) * aDigits;
-  
-  return aSpace;
-}
-
-/*!
-  SLOT: Updates the width of line number area.
- */
-void PyEditor_Editor::updateLineNumberAreaWidth( int /*theNewBlockCount*/ )
-{
-  setViewportMargins( lineNumberAreaWidth(), 0, 0, 0 );
-}
-
-/*!
-  SLOT: When the editor viewport has been scrolled.
- */
-void PyEditor_Editor::updateLineNumberArea( const QRect& theRect, int theDY )
-{
-  if ( theDY )
-    my_LineNumberArea->scroll( 0, theDY );
-  else
-    my_LineNumberArea->update( 0, theRect.y(), my_LineNumberArea->width(), theRect.height() );
-
-  if ( theRect.contains( viewport()->rect() ) )
-    updateLineNumberAreaWidth( 0 );
-}
-
-/*!
-  \brief Parenthesis management.
-  SLOT: Walk through and check that we don't exceed 80 chars per line.
- */
-void PyEditor_Editor::matchParentheses()
-{
-  PyEditor_PyHighlighter::TextBlockData* data =
-    static_cast<PyEditor_PyHighlighter::TextBlockData*>( textCursor().block().userData() );
-
-  if ( data )
-  {
-    QVector<PyEditor_PyHighlighter::ParenthesisInfo*> infoEntries = data->parentheses();
-    
-    int aPos = textCursor().block().position();
-    bool ignore = false;
-    for ( int i = 0; i < infoEntries.size(); ++i )
-    {
-      PyEditor_PyHighlighter::ParenthesisInfo* info = infoEntries.at(i);
-      
-      int currentColumnPosition = textCursor().columnNumber();
-      if ( info->position == currentColumnPosition - 1 && isLeftBrackets( info->character ) )
-      {
-        if ( matchLeftParenthesis( textCursor().block(), i + 1, 0 ) )
-          createParenthesisSelection( aPos + info->position );
-      }
-      else if ( info->position == currentColumnPosition && isLeftBrackets( info->character ) )
-      {
-        if ( !ignore )
-        {
-          if ( matchLeftParenthesis( textCursor().block(), i + 1, 0 ) )
-            createParenthesisSelection( aPos + info->position );
-        }
-      }
-      else if ( info->position == currentColumnPosition - 1 && isRightBrackets( info->character ) )
-      {
-        if ( matchRightParenthesis( textCursor().block(), i - 1, 0 ) )
-          createParenthesisSelection( aPos + info->position );
-        ignore = true;
-      }
-      else if ( info->position == currentColumnPosition && isRightBrackets( info->character ) )
-      {
-        if ( matchRightParenthesis( textCursor().block(), i - 1, 0 ) )
-          createParenthesisSelection( aPos + info->position );
-      }
-    }
-  }
-}
-
-/*!
-  \brief Matches the left brackets.
-  \param theCurrentBlock text block
-  \param theI index
-  \param theNumLeftParentheses number of left parentheses
-  \return \c true if the left match
- */
-bool PyEditor_Editor::matchLeftParenthesis(
-  const QTextBlock& theCurrentBlock, int theI, int theNumLeftParentheses )
-{
-  PyEditor_PyHighlighter::TextBlockData* data =
-    static_cast<PyEditor_PyHighlighter::TextBlockData*>( theCurrentBlock.userData() );
-  QVector<PyEditor_PyHighlighter::ParenthesisInfo*> infos = data->parentheses();
-
-  int docPos = theCurrentBlock.position();
-  for ( ; theI < infos.size(); ++theI )
-  {
-    PyEditor_PyHighlighter::ParenthesisInfo* info = infos.at(theI);
-
-    if ( isLeftBrackets( info->character ) )
-    {
-      ++theNumLeftParentheses;
-      continue;
-    }
-
-    if ( isRightBrackets( info->character ) && theNumLeftParentheses == 0 )
-    {
-      createParenthesisSelection( docPos + info->position );
-      return true;
-    }
-    else
-      --theNumLeftParentheses;
-  }
-
-  QTextBlock nextBlock = theCurrentBlock.next();
-  if ( nextBlock.isValid() )
-    return matchLeftParenthesis( nextBlock, 0, theNumLeftParentheses );
-
-  return false;
-}
-
-/*!
-  \brief Matches the right brackets.
-  \param theCurrentBlock text block
-  \param theI index
-  \param theNumRightParentheses number of right parentheses
-  \return \c true if the right match
- */
-bool PyEditor_Editor::matchRightParenthesis( const QTextBlock& theCurrentBlock, int theI, int theNumRightParentheses )
-{
-  PyEditor_PyHighlighter::TextBlockData* data = static_cast<PyEditor_PyHighlighter::TextBlockData*>( theCurrentBlock.userData() );
-  QVector<PyEditor_PyHighlighter::ParenthesisInfo*> parentheses = data->parentheses();
-
-  int docPos = theCurrentBlock.position();
-  for ( ; theI > -1 && parentheses.size() > 0; --theI )
-  {
-    PyEditor_PyHighlighter::ParenthesisInfo* info = parentheses.at(theI);
-    if ( isRightBrackets( info->character ) )
-    {
-      ++theNumRightParentheses;
-      continue;
-    }
-    if ( isLeftBrackets( info->character ) && theNumRightParentheses == 0 )
-    {
-      createParenthesisSelection( docPos + info->position );
-      return true;
-    }
-    else
-      --theNumRightParentheses;
-  }
-
-  QTextBlock prevBlock = theCurrentBlock.previous();
-  if ( prevBlock.isValid() )
-  {
-    PyEditor_PyHighlighter::TextBlockData* data = static_cast<PyEditor_PyHighlighter::TextBlockData*>( prevBlock.userData() );
-    QVector<PyEditor_PyHighlighter::ParenthesisInfo*> parentheses = data->parentheses();
-    return matchRightParenthesis( prevBlock, parentheses.size() - 1, theNumRightParentheses );
-  }
-
-  return false;
-}
-
-/*!
-  \brief Creates brackets selection.
-  \param thePosition position
- */
-// Create brackets
-void PyEditor_Editor::createParenthesisSelection( int thePosition )
-{
-  QList<QTextEdit::ExtraSelection> selections = extraSelections();
-
-  QTextEdit::ExtraSelection selection;
-
-  QTextCharFormat format = selection.format;
-  format.setForeground( Qt::red );
-  format.setBackground( Qt::white );
-  selection.format = format;
-
-  QTextCursor cursor = textCursor();
-  cursor.setPosition( thePosition );
-  cursor.movePosition( QTextCursor::NextCharacter, QTextCursor::KeepAnchor );
-  selection.cursor = cursor;
-
-  selections.append( selection );
-  setExtraSelections( selections );
-}
-
-/*!
-  return true whether the left bracket
- */
-bool PyEditor_Editor::isLeftBrackets( QChar theSymbol )
-{
-  return theSymbol == '(' || theSymbol == '{' || theSymbol == '[';
-}
-
-/*!
-  Appends a new paragraph with text to the end of the text edit.
- */
-void PyEditor_Editor::append( const QString & text ) {
-  QPlainTextEdit::appendPlainText(text);
-}
-
-/*!
-  Sets the text edit's text.
-*/
-void PyEditor_Editor::setText( const QString & text ) {
-  QPlainTextEdit::appendPlainText(text);
-}
-
-/*!
-  return true whether the right bracket
- */
-bool PyEditor_Editor::isRightBrackets( QChar theSymbol )
-{
-  return theSymbol == ')' || theSymbol == '}' || theSymbol == ']';
-}
diff --git a/src/PyEditor/PyEditor_Editor.h b/src/PyEditor/PyEditor_Editor.h
deleted file mode 100644 (file)
index 518e568..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (C) 2015-2016  OPEN CASCADE
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-//
-// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
-// File   : PyEditor_Editor.h
-// Author : Maxim GLIBIN, Open CASCADE S.A.S. (maxim.glibin@opencascade.com)
-//
-
-#ifndef PYEDITOR_EDITOR_H
-#define PYEDITOR_EDITOR_H
-
-#include <QPlainTextEdit>
-#include "PyEditor.h"
-
-class PyEditor_PyHighlighter;
-class PyEditor_Settings;
-class QtxResourceMgr;
-
-class PYEDITOR_EXPORT PyEditor_Editor : public QPlainTextEdit
-{
-  Q_OBJECT
-
-public:
-  PyEditor_Editor( bool isSingle = false, QtxResourceMgr* = 0,  QWidget* = 0 );
-  virtual ~PyEditor_Editor();
-  
-  void lineNumberAreaPaintEvent( QPaintEvent* );
-  int  lineNumberAreaWidth();
-
-  void updateStatement();
-  PyEditor_Settings* settings();
-
-public Q_SLOTS:
-  void deleteSelected();
-  void append ( const QString & );  
-  void setText ( const QString & text );
-protected:
-  virtual void keyPressEvent( QKeyEvent* );
-  virtual void resizeEvent( QResizeEvent* );
-  virtual void paintEvent( QPaintEvent* );
-    
-private Q_SLOTS:
-  void updateHighlightCurrentLine();
-  void matchParentheses();
-
-  void updateLineNumberAreaWidth( int );
-  void updateLineNumberArea( const QRect&, int );
-  
-private:
-  bool matchLeftParenthesis( const QTextBlock&, int, int );
-  bool matchRightParenthesis( const QTextBlock&, int, int );
-  void createParenthesisSelection( int );
-  bool isLeftBrackets( QChar );
-  bool isRightBrackets( QChar );
-  
-  void handleHome( bool );
-  int  lineIndent();
-  void tabIndentation( bool );
-  void indentSelection( bool );
-  
-  int findFirstNonSpace( const QString& );
-  
-  QWidget*                my_LineNumberArea;
-  PyEditor_PyHighlighter* my_SyntaxHighlighter;
-  PyEditor_Settings*      my_Settings;
-};
-
-#endif // PYEDITOR_EDITOR_H
diff --git a/src/PyEditor/PyEditor_LineNumberArea.cxx b/src/PyEditor/PyEditor_LineNumberArea.cxx
deleted file mode 100644 (file)
index 0a47c9f..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (C) 2015-2016  OPEN CASCADE
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-//
-// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
-// File   : PyEditor_LineNumberArea.cxx
-// Author : Maxim GLIBIN, Open CASCADE S.A.S. (maxim.glibin@opencascade.com)
-//
-
-#include "PyEditor_LineNumberArea.h"
-
-#include "PyEditor_Editor.h"
-
-/*!
-  \class PyEditor_LineNumberArea
-  \brief Widget shows line number.
-*/
-
-/*!
-  \brief Constructor.
-  \param theCodeEditor parent widget
-*/
-PyEditor_LineNumberArea::PyEditor_LineNumberArea( PyEditor_Editor* theCodeEditor ) :
-  QWidget( theCodeEditor )
-{
-  my_CodeEditor = theCodeEditor;
-}
-
-QSize PyEditor_LineNumberArea::sizeHint() const
-{
-  return QSize( my_CodeEditor->lineNumberAreaWidth(), 0 );
-}
-
-void PyEditor_LineNumberArea::paintEvent( QPaintEvent* theEvent )
-{
-  my_CodeEditor->lineNumberAreaPaintEvent( theEvent );
-  QWidget::paintEvent( theEvent );
-}
diff --git a/src/PyEditor/PyEditor_LineNumberArea.h b/src/PyEditor/PyEditor_LineNumberArea.h
deleted file mode 100644 (file)
index e1b9e30..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (C) 2015-2016  OPEN CASCADE
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-//
-// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
-// File   : PyEditor_LineNumberArea.h
-// Author : Maxim GLIBIN, Open CASCADE S.A.S. (maxim.glibin@opencascade.com)
-//
-
-#ifndef PYEDITOR_LINENUMBERAREA_H
-#define PYEDITOR_LINENUMBERAREA_H
-
-#include <QWidget>
-
-class PyEditor_Editor;
-
-class PyEditor_LineNumberArea : public QWidget
-{
-  Q_OBJECT
-
-public:
-  explicit PyEditor_LineNumberArea( PyEditor_Editor* );
-
-  QSize sizeHint() const;
-  
-protected:
-  void paintEvent( QPaintEvent* );
-  
-private:
-  PyEditor_Editor* my_CodeEditor;
-};
-
-#endif // PYEDITOR_LINENUMBERAREA_H
diff --git a/src/PyEditor/PyEditor_PyHighlighter.cxx b/src/PyEditor/PyEditor_PyHighlighter.cxx
deleted file mode 100644 (file)
index 73ea030..0000000
+++ /dev/null
@@ -1,355 +0,0 @@
-// Copyright (C) 2015-2016  OPEN CASCADE
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-//
-// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
-// File   : PyEditor_PyHighlighter.cxx
-// Author : Maxim GLIBIN, Open CASCADE S.A.S. (maxim.glibin@opencascade.com)
-//
-
-#include "PyEditor_PyHighlighter.h"
-
-#define NORMAL 0
-#define TRIPLESINGLE 1
-#define TRIPLEDOUBLE 2
-
-/*!
-  \class PyEditor_PyHighlighter
-  \brief Python highlighter class defines the syntax highlighting rules.
-*/
-
-PyEditor_PyHighlighter::TextBlockData::TextBlockData()
-{
-}
-
-QVector<PyEditor_PyHighlighter::ParenthesisInfo*> PyEditor_PyHighlighter::TextBlockData::parentheses()
-{
-  return my_Parentheses;
-}
-
-void PyEditor_PyHighlighter::TextBlockData::insert( PyEditor_PyHighlighter::ParenthesisInfo* theInfo )
-{
-  int i = 0;
-  while ( i < my_Parentheses.size() && theInfo->position > my_Parentheses.at(i)->position )
-    ++i;
-
-  my_Parentheses.insert( i, theInfo );
-}
-
-/*!
-  \brief Constructor.
-  \param theDocument container for structured rich text documents.
-*/
-PyEditor_PyHighlighter::PyEditor_PyHighlighter( QTextDocument* theDocument )
-  : QSyntaxHighlighter( theDocument )
-{
-  initialize();
-}
-
-/*!
-  \brief Initialization rules.
- */
-void PyEditor_PyHighlighter::initialize()
-{
-  HighlightingRule aRule;
-
-  // Keywords
-  keywordFormat.setForeground( Qt::blue );
-  QStringList aKeywords = keywords();
-  foreach ( const QString &keyword, aKeywords )
-  {
-    aRule.pattern = QRegExp( QString( "\\b%1\\b" ).arg( keyword ) );
-    aRule.format = keywordFormat;
-    aRule.capture = 0;
-    highlightingRules.append( aRule );
-  }
-
-  // Special keywords
-  specialFromat.setForeground( Qt::magenta );
-  QStringList aSpecialKeywords = specialKeywords();
-  foreach ( const QString &keyword, aSpecialKeywords )
-  {
-    aRule.pattern = QRegExp( QString( "\\b%1\\b" ).arg( keyword ) );
-    aRule.format = specialFromat;
-    aRule.capture = 0;
-    highlightingRules.append( aRule );
-  }
-
-  // Reference to the current instance of the class
-  referenceClassFormat.setForeground( QColor( 179, 143, 0 ) );
-  referenceClassFormat.setFontItalic( true );
-  aRule.pattern = QRegExp( "\\bself\\b" );
-  aRule.format = referenceClassFormat;
-  aRule.capture = 0;
-  highlightingRules.append( aRule );
-
-  // Numbers
-  numberFormat.setForeground( Qt::darkMagenta );
-  aRule.pattern = QRegExp( "\\b([-+])?(\\d+(\\.)?\\d*|\\d*(\\.)?\\d+)(([eE]([-+])?)?\\d+)?\\b" );
-  aRule.format = numberFormat;
-  aRule.capture = 0;
-  highlightingRules.append( aRule );
-
-  // String qoutation
-  quotationFormat.setForeground( Qt::darkGreen );
-  aRule.pattern = QRegExp( "(?:'[^']*'|\"[^\"]*\")" );
-  aRule.pattern.setMinimal( true );
-  aRule.format = quotationFormat;
-  aRule.capture = 0;
-  highlightingRules.append( aRule );
-
-  // Function names
-  functionFormat.setFontWeight( QFont::Bold );
-  aRule.pattern = QRegExp( "(?:def\\s*)(\\b[A-Za-z0-9_]+)(?=[\\W])" );
-  aRule.capture = 1;
-  aRule.format = functionFormat;
-  highlightingRules.append( aRule );
-
-  // Class names
-  classFormat.setForeground( Qt::darkBlue );
-  classFormat.setFontWeight( QFont::Bold );
-  aRule.pattern = QRegExp( "(?:class\\s*)(\\b[A-Za-z0-9_]+)(?=[\\W])" );
-  aRule.capture = 1;
-  aRule.format = classFormat;
-  highlightingRules.append( aRule );
-
-  // Multi line comments
-  multiLineCommentFormat.setForeground( Qt::darkRed );
-  tripleQuotesExpression = QRegExp( "(:?\"[\"]\".*\"[\"]\"|'''.*''')" );
-  aRule.pattern = tripleQuotesExpression;
-  aRule.pattern.setMinimal( true );
-  aRule.format = multiLineCommentFormat;
-  aRule.capture = 0;
-  highlightingRules.append( aRule );
-
-  tripleSingleExpression = QRegExp( "'''(?!\")" );
-  tripleDoubleExpression = QRegExp( "\"\"\"(?!')" );
-
-  // Single comments
-  singleLineCommentFormat.setForeground( Qt::darkGray );
-  aRule.pattern = QRegExp( "#[^\n]*" );
-  aRule.format = singleLineCommentFormat;
-  aRule.capture = 0;
-  highlightingRules.append( aRule );
-}
-
-/*!
-  \return string list of Python keywords.
- */
-QStringList PyEditor_PyHighlighter::keywords()
-{
-  QStringList aKeywords;
-  aKeywords << "and"
-            << "as"
-            << "assert"
-            << "break"
-            << "class"
-            << "continue"
-            << "def"
-            << "elif"
-            << "else"
-            << "except"
-            << "exec"
-            << "finally"
-            << "False"
-            << "for"
-            << "from"
-            << "global"
-            << "if"
-            << "import"
-            << "in"
-            << "is"
-            << "lambda"
-            << "None"
-            << "not"
-            << "or"
-            << "pass"
-            << "print"
-            << "raise"
-            << "return"
-            << "True"
-            << "try"
-            << "while"
-            << "with"
-            << "yield";
-  return aKeywords;
-}
-
-/*!
-  \return string list of special Python keywords.
- */
-QStringList PyEditor_PyHighlighter::specialKeywords()
-{
-  QStringList aSpecialKeywords;
-  aSpecialKeywords << "ArithmeticError"
-                   << "AssertionError"
-                   << "AttributeError"
-                   << "EnvironmentError"
-                   << "EOFError"
-                   << "Exception"
-                   << "FloatingPointError"
-                   << "ImportError"
-                   << "IndentationError"
-                   << "IndexError"
-                   << "IOError"
-                   << "KeyboardInterrupt"
-                   << "KeyError"
-                   << "LookupError"
-                   << "MemoryError"
-                   << "NameError"
-                   << "NotImplementedError"
-                   << "OSError"
-                   << "OverflowError"
-                   << "ReferenceError"
-                   << "RuntimeError"
-                   << "StandardError"
-                   << "StopIteration"
-                   << "SyntaxError"
-                   << "SystemError"
-                   << "SystemExit"
-                   << "TabError"
-                   << "TypeError"
-                   << "UnboundLocalError"
-                   << "UnicodeDecodeError"
-                   << "UnicodeEncodeError"
-                   << "UnicodeError"
-                   << "UnicodeTranslateError"
-                   << "ValueError"
-                   << "WindowsError"
-                   << "ZeroDivisionError"
-                   << "Warning"
-                   << "UserWarning"
-                   << "DeprecationWarning"
-                   << "PendingDeprecationWarning"
-                   << "SyntaxWarning"
-                   << "OverflowWarning"
-                   << "RuntimeWarning"
-                   << "FutureWarning";
-  return aSpecialKeywords;
-}
-
-void PyEditor_PyHighlighter::highlightBlock( const QString& theText )
-{
-  TextBlockData* aData = new TextBlockData;
-  
-  insertBracketsData( RoundBrackets, aData, theText );
-  insertBracketsData( CurlyBrackets, aData, theText );
-  insertBracketsData( SquareBrackets, aData, theText );
-
-  setCurrentBlockUserData( aData );
-
-  foreach ( const HighlightingRule& rule, highlightingRules )
-  {
-    QRegExp expression( rule.pattern );
-    int anIndex = expression.indexIn( theText );
-    while ( anIndex >= 0 )
-    {
-      anIndex = expression.pos( rule.capture );
-      int aLength = expression.cap( rule.capture ).length();
-      setFormat( anIndex, aLength, rule.format );
-      anIndex = expression.indexIn( theText, anIndex + aLength );
-    }
-  }
-
-  setCurrentBlockState( NORMAL );
-
-  if ( theText.indexOf( tripleQuotesExpression ) != -1 )
-    return;
-
-  QList<int> aTripleSingle;
-  aTripleSingle << theText.indexOf( tripleSingleExpression ) << TRIPLESINGLE;
-
-  QList<int> aTripleDouble;
-  aTripleDouble << theText.indexOf( tripleDoubleExpression ) << TRIPLEDOUBLE;
-  QList< QList<int> > aTripleExpressions;
-  aTripleExpressions << aTripleSingle << aTripleDouble;
-
-  for ( int i = 0; i < aTripleExpressions.length(); i++ )
-  {
-    QList<int> aBlock = aTripleExpressions[i];
-    int anIndex = aBlock[0];
-    int aState = aBlock[1];
-    if ( previousBlockState() == aState )
-    {
-      if ( anIndex == -1 )
-      {
-        anIndex = theText.length();
-        setCurrentBlockState( aState );
-      }
-      setFormat( 0, anIndex + 3, multiLineCommentFormat );
-    }
-    else if ( anIndex > -1 )
-    {
-      setCurrentBlockState( aState );
-      setFormat( anIndex, theText.length(), multiLineCommentFormat );
-    }
-  }
-}
-
-void PyEditor_PyHighlighter::insertBracketsData( char theLeftSymbol,
-                                                 char theRightSymbol,
-                                                 TextBlockData* theData,
-                                                 const QString& theText )
-{
-  int leftPosition = theText.indexOf( theLeftSymbol );
-  while( leftPosition != -1 )
-  {
-    ParenthesisInfo* info = new ParenthesisInfo();
-    info->character = theLeftSymbol;
-    info->position = leftPosition;
-
-    theData->insert( info );
-    leftPosition = theText.indexOf( theLeftSymbol, leftPosition + 1 );
-  }
-
-  int rightPosition = theText.indexOf( theRightSymbol );
-  while( rightPosition != -1 )
-  {
-    ParenthesisInfo* info = new ParenthesisInfo();
-    info->character = theRightSymbol;
-    info->position = rightPosition;
-
-    theData->insert( info );
-    rightPosition = theText.indexOf( theRightSymbol, rightPosition + 1 );
-  }
-}
-
-void PyEditor_PyHighlighter::insertBracketsData( Brackets theBrackets,
-                                                 TextBlockData* theData,
-                                                 const QString& theText )
-{
-  char leftChar = '0';
-  char rightChar = '0';
-  
-  switch( theBrackets )
-  {
-  case RoundBrackets:
-    leftChar = '(';
-    rightChar = ')';
-    break;
-  case CurlyBrackets:
-    leftChar = '{';
-    rightChar = '}';
-    break;
-  case SquareBrackets:
-    leftChar = '[';
-    rightChar = ']';
-    break;
-  }
-
-  insertBracketsData( leftChar, rightChar, theData, theText );
-}
diff --git a/src/PyEditor/PyEditor_PyHighlighter.h b/src/PyEditor/PyEditor_PyHighlighter.h
deleted file mode 100644 (file)
index 1256813..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright (C) 2015-2016  OPEN CASCADE
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-//
-// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
-// File   : PyEditor_PyHighlighter.h
-// Author : Maxim GLIBIN, Open CASCADE S.A.S. (maxim.glibin@opencascade.com)
-//
-
-#ifndef PYEDITOR_PYHIGHLIGHTER_H
-#define PYEDITOR_PYHIGHLIGHTER_H
-
-#include <QSyntaxHighlighter>
-
-class QTextDocument;
-
-class PyEditor_PyHighlighter : public QSyntaxHighlighter
-{
-  Q_OBJECT
-
-public:
-
-  struct ParenthesisInfo
-  {
-    char character;
-    int position;
-  };
-
-  class TextBlockData : public QTextBlockUserData
-  {
-  public:
-    TextBlockData();
-
-    QVector<ParenthesisInfo*> parentheses();
-    void insert( ParenthesisInfo* );
-
-  private:
-    QVector<ParenthesisInfo*> my_Parentheses;
-  };
-
-public:
-  PyEditor_PyHighlighter( QTextDocument* = 0 );
-
-  void initialize();
-  QStringList keywords();
-  QStringList specialKeywords();
-
-protected:
-  struct HighlightingRule
-  {
-    QRegExp pattern;
-    QTextCharFormat format;
-    int capture;
-  };
-  QVector<HighlightingRule> highlightingRules;
-
-  enum Brackets { RoundBrackets, CurlyBrackets, SquareBrackets };
-
-  QRegExp tripleQuotesExpression;
-  QRegExp tripleSingleExpression;
-  QRegExp tripleDoubleExpression;
-
-  QTextCharFormat classFormat;
-  QTextCharFormat referenceClassFormat;
-  QTextCharFormat functionFormat;
-  QTextCharFormat keywordFormat;
-  QTextCharFormat specialFromat;
-  QTextCharFormat numberFormat;
-  QTextCharFormat singleLineCommentFormat;
-  QTextCharFormat multiLineCommentFormat;
-  QTextCharFormat quotationFormat;
-
-  void highlightBlock( const QString& );
-  void insertBracketsData( char, char, TextBlockData*, const QString& );
-  void insertBracketsData( Brackets, TextBlockData*, const QString& );
-};
-
-#endif // PYEDITOR_PYHIGHLIGHTER_H
diff --git a/src/PyEditor/PyEditor_Settings.cxx b/src/PyEditor/PyEditor_Settings.cxx
deleted file mode 100644 (file)
index 69309d1..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-// Copyright (C) 2015-2016  OPEN CASCADE
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-//
-// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
-// File   : PyEditor_Settings.cxx
-// Author : Maxim GLIBIN, Open CASCADE S.A.S. (maxim.glibin@opencascade.com)
-//
-
-#include "PyEditor_Settings.h"
-
-#include <QtxResourceMgr.h>
-
-#include <QDir>
-#include <QFile>
-#include <QSettings>
-
-/*!
-  \class PyEditor_Settings
-  \brief Manager of setting values.
-*/
-
-/*!
-  \brief Constructor.
-  \param isSingle flag determined single application or reccesed.
-*/
-PyEditor_Settings::PyEditor_Settings( QtxResourceMgr* theMgr, bool isSingle )
-    : p_HighlightCurrentLine( true ),
-      p_LineNumberArea( true ),
-      p_TextWrapping( false ),
-      p_CenterCursorOnScroll( true ),
-      p_TabSpaceVisible( true ),
-      p_TabSize( 4 ),
-      p_VerticalEdge( true ),
-      p_NumberColumns( 80 ),
-      p_Font( "Courier", 10 ),
-      m_ResourceMgr(theMgr),
-      m_Single(isSingle)
-
-{
-  if ( m_Single )
-  {
-    m_Settings = new QSettings( "config.ini", QSettings::IniFormat );
-    if ( !QFile::exists( m_Settings->fileName() ) )
-      toSettings( PY_EDITOR );
-  }
-
-  readSettings();
-}
-
-/*!
-  \brief Reads the setting values.
- */
-void PyEditor_Settings::readSettings()
-{
-  if ( isSingle() )
-    fromSettings( PY_EDITOR );
-  else
-    readPreferences();
-}
-
-/*!
-  \brief Writes the setting values.
- */
-void PyEditor_Settings::writeSettings()
-{
-  if ( isSingle() )
-    toSettings( PY_EDITOR );
-  else
-    writePreferences();
-}
-
-/*!
-  \return \c true if the application is single
- */
-bool PyEditor_Settings::isSingle()
-{
-  return m_Single;
-}
-
-/*!
-  \brief Loads the setting values from file settings.
- */
-void PyEditor_Settings::fromSettings( const QString &theCategory )
-{
-  QString aGroup = theCategory;
-  aGroup += "/";
-
-  p_HighlightCurrentLine = m_Settings->value(aGroup + QLatin1String( HIGHLIGHT_CURRLINE ), p_HighlightCurrentLine).toBool();
-  p_LineNumberArea       = m_Settings->value(aGroup + QLatin1String( LINE_NUMBER_AREA ), p_LineNumberArea).toBool();
-  p_TextWrapping         = m_Settings->value(aGroup + QLatin1String( TEXT_WRAP ), p_TextWrapping).toBool();
-  p_CenterCursorOnScroll = m_Settings->value(aGroup + QLatin1String( CURSOR_SCROLL ), p_CenterCursorOnScroll).toBool();
-  p_TabSpaceVisible      = m_Settings->value(aGroup + QLatin1String( TAB_WHITESPACES ), p_TabSpaceVisible).toBool();
-  p_TabSize              = m_Settings->value(aGroup + QLatin1String( TAB_SIZE ), p_TabSize).toInt();
-  p_VerticalEdge         = m_Settings->value(aGroup + QLatin1String( VERTICAL_EDGE ), p_VerticalEdge).toBool();
-  p_NumberColumns        = m_Settings->value(aGroup + QLatin1String( NUM_COLUMNS ), p_NumberColumns).toInt();
-  p_Font = QFont( m_Settings->value(aGroup + QLatin1String( FONT_FAMILY ), p_Font.family()).toString(),
-    m_Settings->value(aGroup + QLatin1String( FONT_SIZE ), p_Font.pointSize()).toInt() );
-}
-
-/*!
-  \brief Saves the setting values into file settings.
- */
-void PyEditor_Settings::toSettings( const QString &theCategory ) const
-{
-  m_Settings->beginGroup( theCategory );
-  m_Settings->setValue( QLatin1String( HIGHLIGHT_CURRLINE ), p_HighlightCurrentLine );
-  m_Settings->setValue( QLatin1String( LINE_NUMBER_AREA ),   p_LineNumberArea );
-  m_Settings->setValue( QLatin1String( TEXT_WRAP ),          p_TextWrapping );
-  m_Settings->setValue( QLatin1String( CURSOR_SCROLL ),      p_CenterCursorOnScroll );
-  m_Settings->setValue( QLatin1String( TAB_WHITESPACES ),    p_TabSpaceVisible );
-  m_Settings->setValue( QLatin1String( TAB_SIZE ),           p_TabSize );
-  m_Settings->setValue( QLatin1String( VERTICAL_EDGE ),      p_VerticalEdge );
-  m_Settings->setValue( QLatin1String( NUM_COLUMNS ),        p_NumberColumns );
-  m_Settings->setValue( QLatin1String( FONT_FAMILY ),        p_Font.family() );
-  m_Settings->setValue( QLatin1String( FONT_SIZE ),          p_Font.pointSize() );
-  m_Settings->endGroup();
-}
-
-/*!
-  \brief Loads the setting values from setting resources.
- */
-void PyEditor_Settings::readPreferences()
-{
-  if(m_ResourceMgr) 
-    {
-      p_HighlightCurrentLine = m_ResourceMgr->booleanValue( "PyEditor", "HighlightCurrentLine", p_HighlightCurrentLine );
-      p_LineNumberArea       = m_ResourceMgr->booleanValue( "PyEditor", "LineNumberArea", p_LineNumberArea );
-      p_TextWrapping         = m_ResourceMgr->booleanValue( "PyEditor", "TextWrapping", p_TextWrapping );
-      p_CenterCursorOnScroll = m_ResourceMgr->booleanValue( "PyEditor", "CenterCursorOnScroll", p_CenterCursorOnScroll );
-      p_TabSpaceVisible      = m_ResourceMgr->booleanValue( "PyEditor", "TabSpaceVisible", p_TabSpaceVisible );
-      p_TabSize              = m_ResourceMgr->integerValue( "PyEditor", "TabSize", p_TabSize );
-      p_VerticalEdge         = m_ResourceMgr->booleanValue( "PyEditor", "VerticalEdge", p_VerticalEdge );
-      p_NumberColumns        = m_ResourceMgr->integerValue( "PyEditor", "NumberColumns", p_NumberColumns );
-      p_Font                 = m_ResourceMgr->fontValue( "PyEditor", "Font", p_Font );
-    }
-}
-
-/*!
-  \brief Saves the setting values into setting resources.
- */
-void PyEditor_Settings::writePreferences()
-{
-  if(m_ResourceMgr) 
-    {
-      m_ResourceMgr->setValue( "PyEditor", "HighlightCurrentLine", p_HighlightCurrentLine );
-      m_ResourceMgr->setValue( "PyEditor", "LineNumberArea", p_LineNumberArea );
-      m_ResourceMgr->setValue( "PyEditor", "TextWrapping", p_TextWrapping );
-      m_ResourceMgr->setValue( "PyEditor", "CenterCursorOnScroll", p_CenterCursorOnScroll );
-      m_ResourceMgr->setValue( "PyEditor", "TabSpaceVisible", p_TabSpaceVisible );
-      m_ResourceMgr->setValue( "PyEditor", "TabSize", p_TabSize );
-      m_ResourceMgr->setValue( "PyEditor", "VerticalEdge", p_VerticalEdge );
-      m_ResourceMgr->setValue( "PyEditor", "NumberColumns", p_NumberColumns );
-      m_ResourceMgr->setValue( "PyEditor", "Font", p_Font );
-    }
-}
diff --git a/src/PyEditor/PyEditor_Settings.h b/src/PyEditor/PyEditor_Settings.h
deleted file mode 100644 (file)
index d7b11d8..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright (C) 2015-2016  OPEN CASCADE
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-//
-// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
-// File   : PyEditor_Settings.h
-// Author : Maxim GLIBIN, Open CASCADE S.A.S. (maxim.glibin@opencascade.com)
-//
-
-#ifndef PYEDITOR_SETTINGS_H
-#define PYEDITOR_SETTINGS_H
-
-#include <QFont>
-#include "PyEditor.h"
-
-class QSettings;
-class QtxResourceMgr;
-
-const char* const PY_EDITOR          = "PythonEditor";
-const char* const HIGHLIGHT_CURRLINE = "HighlightCurrentLine";
-const char* const LINE_NUMBER_AREA   = "LineNumberArea";
-const char* const TEXT_WRAP          = "TextWrapping";
-const char* const CURSOR_SCROLL      = "CenterCursorOnScroll";
-const char* const TAB_WHITESPACES    = "TabSpaceVisible";
-const char* const TAB_SIZE           = "TabSize";
-const char* const VERTICAL_EDGE      = "VerticalEdge";
-const char* const NUM_COLUMNS        = "NumberColumns";
-const char* const FONT_FAMILY        = "FontFamily";
-const char* const FONT_SIZE          = "FontSize";
-
-class PYEDITOR_EXPORT PyEditor_Settings
-{
-public:
-  PyEditor_Settings( QtxResourceMgr* = 0 ,  bool isSingle = true );
-
-  void readSettings();
-  void writeSettings();
-
-  void fromSettings( const QString& );
-  void toSettings( const QString& ) const;
-
-  void readPreferences();
-  void writePreferences();
-
-  bool isSingle();
-  
-  // Display settings
-  bool p_HighlightCurrentLine;
-  bool p_TextWrapping;
-  bool p_CenterCursorOnScroll;
-  bool p_LineNumberArea;
-  
-  // Vertical edge settings
-  bool p_VerticalEdge;
-  int  p_NumberColumns;
-  
-  // Tab settings
-  bool p_TabSpaceVisible;
-  int  p_TabSize;
-  
-  // Font settings
-  QFont p_Font;
-
-private:
-  QSettings*      m_Settings;
-  QtxResourceMgr* m_ResourceMgr;
-  bool            m_Single;
-};
-
-#endif // PYEDITOR_SETTINGS_H
diff --git a/src/PyEditor/PyEditor_SettingsDlg.cxx b/src/PyEditor/PyEditor_SettingsDlg.cxx
deleted file mode 100644 (file)
index 47a519f..0000000
+++ /dev/null
@@ -1,228 +0,0 @@
-// Copyright (C) 2015-2016  OPEN CASCADE
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-//
-// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
-// File   : PyEditor_SettingsDlg.cxx
-// Author : Maxim GLIBIN, Open CASCADE S.A.S. (maxim.glibin@opencascade.com)
-//
-
-#include "PyEditor_SettingsDlg.h"
-
-#include "PyEditor_Editor.h"
-#include "PyEditor_Settings.h"
-
-#include <QCheckBox>
-#include <QGroupBox>
-#include <QLabel>
-#include <QPushButton>
-#include <QSpinBox>
-#include <QVBoxLayout>
-#include <QtxFontEdit.h>
-
-/*!
-  \class PyEditor_SettingsDlg
-  \brief Dialog settings for python editor.
-*/
-
-/*!
-  \brief Constructor.
-  \param theEditor widget that is used to edit and display text
-  \param theParent parent widget
-*/
-PyEditor_SettingsDlg::PyEditor_SettingsDlg( PyEditor_Editor* theEditor, QWidget* theParent ) :
-  QDialog( theParent ),
-  my_Editor( theEditor )
-{
-  setWindowTitle( tr("TIT_PY_PREF") );
-  QVBoxLayout* aMainLayout = new QVBoxLayout( this );
-  
-  // . Font settings <start>
-  QGroupBox* aFontSetBox = new QGroupBox( tr( "GR_FONT_SET" ) );
-  QHBoxLayout* aFontSetLayout = new QHBoxLayout( aFontSetBox );
-  w_FontWidget = new QtxFontEdit( QtxFontEdit::Family|QtxFontEdit::Size|QtxFontEdit::UserSize, this );
-  aFontSetLayout->addWidget( w_FontWidget );
-  // . Font settings <end>
-  
-  // . Display settings <start>
-  QGroupBox* aDisplaySetBox = new QGroupBox( tr( "GR_DISP_SET" ) );
-  QVBoxLayout* aDisplaySetLayout = new QVBoxLayout;
-  w_HighlightCurrentLine = new QCheckBox( tr( "LBL_CURRLINE_HIGHLIGHT" ) );
-  w_TextWrapping = new QCheckBox( tr( "LBL_TEXT_WRAP" ) );
-  w_CenterCursorOnScroll = new QCheckBox( tr( "LBL_CURSOR_SCROLL" ) );
-  w_LineNumberArea = new QCheckBox( tr( "LBL_LINE_NUMBS_AREA" ) );
-  aDisplaySetLayout->addWidget( w_HighlightCurrentLine );
-  aDisplaySetLayout->addWidget( w_TextWrapping );
-  aDisplaySetLayout->addWidget( w_CenterCursorOnScroll );
-  aDisplaySetLayout->addWidget( w_LineNumberArea );
-  aDisplaySetLayout->addStretch( 1 );
-  aDisplaySetBox->setLayout( aDisplaySetLayout );
-  // . Display settings <end>
-
-  QHBoxLayout* aTabVertEdgeLayout = new QHBoxLayout;
-
-  // . Tab settings <start>
-  QGroupBox* aTabSetBox = new QGroupBox( tr( "GR_TAB_SET" ) );
-  QVBoxLayout* aTabSetLayout = new QVBoxLayout;
-  w_TabSpaceVisible = new QCheckBox( tr( "LBL_TAB_SPACES" ) );
-  QHBoxLayout* aTabSizeLayout = new QHBoxLayout;
-  QLabel* aTabSizeLabel = new QLabel( tr( "LBL_TAB_SIZE" ) );
-  w_TabSize = new QSpinBox;
-  w_TabSize->setMinimum( 0 );
-  w_TabSize->setSingleStep( 1 );
-  aTabSizeLayout->addWidget( aTabSizeLabel );
-  aTabSizeLayout->addWidget( w_TabSize );
-  aTabSizeLayout->addStretch( 1 );
-  aTabSetLayout->addWidget( w_TabSpaceVisible );
-  aTabSetLayout->addLayout( aTabSizeLayout );
-  aTabSetBox->setLayout( aTabSetLayout );
-  // . Tab settings <end>
-
-  // . Vertical edge settings <start>
-  QGroupBox* aVertEdgeSetBox = new QGroupBox( tr( "GR_VERT_EDGE_SET" ) );
-  QVBoxLayout* aVertEdgeLayout = new QVBoxLayout;
-  w_VerticalEdge = new QCheckBox( tr( "LBL_VERT_EDGE" ) );
-  QHBoxLayout* aNumberColLayout = new QHBoxLayout;
-  lbl_NumColumns = new QLabel( tr( "LBL_NUM_COLUMNS" ) );
-  w_NumberColumns = new QSpinBox;
-  w_NumberColumns->setMinimum( 0 );
-  w_NumberColumns->setSingleStep( 1 );
-  aNumberColLayout->addWidget( lbl_NumColumns );
-  aNumberColLayout->addWidget( w_NumberColumns );
-  aNumberColLayout->addStretch( 1 );
-  aVertEdgeLayout->addWidget( w_VerticalEdge );
-  aVertEdgeLayout->addLayout( aNumberColLayout );
-  aVertEdgeSetBox->setLayout( aVertEdgeLayout );
-  connect( w_VerticalEdge, SIGNAL( clicked( bool ) ), 
-           this, SLOT( onVerticalEdgeChecked( bool ) ) );
-  // . Vertical edge settings <end>
-
-  aTabVertEdgeLayout->addWidget( aTabSetBox );
-  aTabVertEdgeLayout->addWidget( aVertEdgeSetBox );
-
-  // . "Set as default" check box
-  w_DefaultCheck = new QCheckBox( tr( "WDG_SET_AS_DEFAULT_CHECK" ), this );
-  
-  aMainLayout->addWidget( aFontSetBox );
-  aMainLayout->addWidget( aDisplaySetBox );
-  aMainLayout->addLayout( aTabVertEdgeLayout );
-  aMainLayout->addWidget( w_DefaultCheck );
-  aMainLayout->addStretch( 1 );
-  
-  myOkBtn = new QPushButton( tr( "BUT_OK" ), this );
-  myOkBtn->setAutoDefault( true );
-  myOkBtn->setDefault( true );
-  myCancelBtn = new QPushButton( tr( "BUT_CANCEL" ), this );
-  myCancelBtn->setAutoDefault( true );
-  myHelpBtn = new QPushButton( tr( "BUT_HELP" ), this );
-  myHelpBtn->setAutoDefault( true );
-  QHBoxLayout* aButtonLayout = new QHBoxLayout;
-  aButtonLayout->addWidget( myOkBtn );
-  aButtonLayout->addStretch();
-  aButtonLayout->addWidget( myCancelBtn );
-  aButtonLayout->addWidget( myHelpBtn );
-  aMainLayout->addLayout( aButtonLayout );
-
-  connect( myOkBtn,         SIGNAL( clicked() ), this, SLOT( onOk() ) );
-  connect( myCancelBtn,     SIGNAL( clicked() ), this, SLOT( reject() ) );
-  connect( myHelpBtn,       SIGNAL( clicked() ), this, SLOT( onHelp() ) );
-  
-  settingsToGui();
-}
-
-/*!
-  \brief Get "Set settings as default" check box value.
-  \return \c true if "Set settings as default" check box is on
-*/
-bool PyEditor_SettingsDlg::isSetAsDefault()
-{
-  return w_DefaultCheck->isChecked();
-}
-
-/*!
-  SLOT: Changes the widget visibility depending on the set theState flag.
-  \param theState flag of visibility
- */
-void PyEditor_SettingsDlg::onVerticalEdgeChecked( bool theState )
-{
-  lbl_NumColumns->setEnabled( theState );
-  w_NumberColumns->setEnabled( theState );
-}
-
-/*!
-  \brief Sets settings from preferences dialog.
- */
-void PyEditor_SettingsDlg::settingsFromGui()
-{
-  my_Editor->settings()->p_HighlightCurrentLine = w_HighlightCurrentLine->isChecked();
-  my_Editor->settings()->p_TextWrapping = w_TextWrapping->isChecked();
-  my_Editor->settings()->p_CenterCursorOnScroll = w_CenterCursorOnScroll->isChecked();
-  my_Editor->settings()->p_LineNumberArea = w_LineNumberArea->isChecked();
-  my_Editor->settings()->p_TabSpaceVisible = w_TabSpaceVisible->isChecked();
-  my_Editor->settings()->p_TabSize = w_TabSize->value();
-  my_Editor->settings()->p_VerticalEdge = w_VerticalEdge->isChecked();
-  my_Editor->settings()->p_NumberColumns = w_NumberColumns->value();
-  my_Editor->settings()->p_Font = w_FontWidget->currentFont();
-}
-
-/*!
-  \brief Sets settings into preferences dialog.
- */
-void PyEditor_SettingsDlg::settingsToGui()
-{
-  w_HighlightCurrentLine->setChecked( my_Editor->settings()->p_HighlightCurrentLine );
-  w_TextWrapping->setChecked( my_Editor->settings()->p_TextWrapping );
-  w_CenterCursorOnScroll->setChecked( my_Editor->settings()->p_CenterCursorOnScroll );
-  w_LineNumberArea->setChecked( my_Editor->settings()->p_LineNumberArea );
-  w_TabSpaceVisible->setChecked( my_Editor->settings()->p_TabSpaceVisible );
-  w_TabSize->setValue( my_Editor->settings()->p_TabSize );
-  w_VerticalEdge->setChecked( my_Editor->settings()->p_VerticalEdge );
-  w_NumberColumns->setValue( my_Editor->settings()->p_NumberColumns );
-  w_FontWidget->setCurrentFont( my_Editor->settings()->p_Font );
-  w_FontWidget->setSizes();
-
-  onVerticalEdgeChecked( my_Editor->settings()->p_VerticalEdge );
-}
-
-/*!
-  \brief Sets settings into the setting resources or file
-  if the flag is set as default is true.
- */
-void PyEditor_SettingsDlg::setSettings()
-{
-  if ( isSetAsDefault() )
-    my_Editor->settings()->writeSettings();
-
-  my_Editor->updateStatement();
-}
-
-/*!
-  Slot, called when user clicks "OK" button
-*/
-void PyEditor_SettingsDlg::onOk()
-{
-  settingsFromGui();
-  setSettings();
-  accept();
-}
-
-/*!
-  Slot, called when user clicks "Help" button.
-*/
-void PyEditor_SettingsDlg::onHelp()
-{
-  emit onHelpClicked();
-}
diff --git a/src/PyEditor/PyEditor_SettingsDlg.h b/src/PyEditor/PyEditor_SettingsDlg.h
deleted file mode 100644 (file)
index 9c486c4..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (C) 2015-2016  OPEN CASCADE
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-//
-// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
-// File   : PyEditor_SettingsDlg.h
-// Author : Maxim GLIBIN, Open CASCADE S.A.S. (maxim.glibin@opencascade.com)
-//
-
-#ifndef PYEDITOR_SETTINGSDLG_H
-#define PYEDITOR_SETTINGSDLG_H
-
-#include <QDialog>
-#include "PyEditor.h"
-
-class PyEditor_Editor;
-class QCheckBox;
-class QLabel;
-class QPushButton;
-class QSpinBox;
-class QtxFontEdit;
-
-class PYEDITOR_EXPORT PyEditor_SettingsDlg : public QDialog
-{
-  Q_OBJECT
-
-public:
-  PyEditor_SettingsDlg( PyEditor_Editor*, QWidget* = 0 );
-
-  bool    isSetAsDefault();
-
-private Q_SLOTS:
-  void onVerticalEdgeChecked( bool );
-  void onOk();
-  void onHelp();
-
-Q_SIGNALS:
-  void onHelpClicked();
-
-private:
-  void settingsToGui();
-  void settingsFromGui();
-  void setSettings();
-  
-  QCheckBox*        w_HighlightCurrentLine;
-  QCheckBox*        w_TextWrapping;
-  QCheckBox*        w_CenterCursorOnScroll;
-  QCheckBox*        w_LineNumberArea;
-
-  QCheckBox*        w_TabSpaceVisible;
-  QSpinBox*         w_TabSize;
-
-  QCheckBox*        w_VerticalEdge;
-  QSpinBox*         w_NumberColumns;
-  QLabel*           lbl_NumColumns;
-
-  QtxFontEdit*      w_FontWidget;
-
-  QCheckBox*        w_DefaultCheck;
-
-  QPushButton*      myOkBtn;
-  QPushButton*      myCancelBtn;
-  QPushButton*      myHelpBtn;
-
-  PyEditor_Editor*  my_Editor;
-};
-
-#endif // PYEDITOR_SETTINGSDLG_H
diff --git a/src/PyEditor/resources/translations/PyEditor_msg_en.ts b/src/PyEditor/resources/translations/PyEditor_msg_en.ts
deleted file mode 100644 (file)
index 047f661..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE TS>
-<TS version="2.0" language="en">
-  <context>
-    <name>PyEditor_SettingsDlg</name>
-    <message>
-      <source>TIT_PY_PREF</source>
-      <translation>Preferences</translation>
-    </message>
-    <message>
-      <source>GR_FONT_SET</source>
-      <translation>Font settings</translation>
-    </message>
-    <message>
-      <source>LBL_FONT_FAM</source>
-      <translation>Family:</translation>
-    </message>
-    <message>
-      <source>LBL_FONT_SIZE</source>
-      <translation>Size:</translation>
-    </message>
-    <message>
-      <source>GR_DISP_SET</source>
-      <translation>Display settings</translation>
-    </message>
-    <message>
-      <source>LBL_CURRLINE_HIGHLIGHT</source>
-      <translation>Enable current line highlight</translation>
-    </message>
-    <message>
-      <source>LBL_TEXT_WRAP</source>
-      <translation>Enable text wrapping</translation>
-    </message>
-    <message>
-      <source>LBL_CURSOR_SCROLL</source>
-      <translation>Center cursor on scroll</translation>
-    </message>
-    <message>
-      <source>LBL_LINE_NUMBS_AREA</source>
-      <translation>Display line numbers area</translation>
-    </message>
-    <message>
-      <source>GR_TAB_SET</source>
-      <translation>Tab settings</translation>
-    </message>
-    <message>
-      <source>LBL_TAB_SPACES</source>
-      <translation>Display tab white spaces</translation>
-    </message>
-    <message>
-      <source>LBL_TAB_SIZE</source>
-      <translation>Tab size:</translation>
-    </message>
-    <message>
-      <source>GR_VERT_EDGE_SET</source>
-      <translation>Vertical edge settings</translation>
-    </message>
-    <message>
-      <source>LBL_VERT_EDGE</source>
-      <translation>Display vertical edge</translation>
-    </message>
-    <message>
-      <source>LBL_NUM_COLUMNS</source>
-      <translation>Number of columns:</translation>
-    </message>
-    <message>
-      <source>WDG_SET_AS_DEFAULT_CHECK</source>
-      <translation>Save settings as default</translation>
-    </message>
-  </context>
-</TS>
diff --git a/src/PyEditor/resources/translations/PyEditor_msg_fr.ts b/src/PyEditor/resources/translations/PyEditor_msg_fr.ts
deleted file mode 100644 (file)
index 3a2fcfb..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE TS>
-<TS version="2.0" language="fr">
-  <context>
-    <name>PyEditor_SettingsDlg</name>
-    <message>
-      <source>TIT_PY_PREF</source>
-      <translation>Préférences</translation>
-    </message>
-    <message>
-      <source>GR_FONT_SET</source>
-      <translation>Paramètres de la fonte</translation>
-    </message>
-    <message>
-      <source>LBL_FONT_FAM</source>
-      <translation>Famille:</translation>
-    </message>
-    <message>
-      <source>LBL_FONT_SIZE</source>
-      <translation>Taille:</translation>
-    </message>
-    <message>
-      <source>GR_DISP_SET</source>
-      <translation>Paramètres d'affichage</translation>
-    </message>
-    <message>
-      <source>LBL_CURRLINE_HIGHLIGHT</source>
-      <translation>Met en surbrillance de la ligne actuelle</translation>
-    </message>
-    <message>
-      <source>LBL_TEXT_WRAP</source>
-      <translation>Retour à la ligne dynamique</translation>
-    </message>
-    <message>
-      <source>LBL_CURSOR_SCROLL</source>
-      <translation>Centre le curseur lors du scroll</translation>
-    </message>
-    <message>
-      <source>LBL_LINE_NUMBS_AREA</source>
-      <translation>Affiche les numéros de ligne</translation>
-    </message>
-    <message>
-      <source>GR_TAB_SET</source>
-      <translation>Indentation</translation>
-    </message>
-    <message>
-      <source>LBL_TAB_SPACES</source>
-      <translation>Affiche les guides d'indentation</translation>
-    </message>
-    <message>
-      <source>LBL_TAB_SIZE</source>
-      <translation>Largeur d'intentation:</translation>
-    </message>
-    <message>
-      <source>GR_VERT_EDGE_SET</source>
-      <translation>Marqueur de retour à la ligne</translation>
-    </message>
-    <message>
-      <source>LBL_VERT_EDGE</source>
-      <translation>Afficher la ligne verticale</translation>
-    </message>
-    <message>
-      <source>LBL_NUM_COLUMNS</source>
-      <translation>Nombre de colonnes:</translation>
-    </message>
-    <message>
-      <source>WDG_SET_AS_DEFAULT_CHECK</source>
-      <translation>Sauver en tant que paramètres par défaut</translation>
-    </message>
-  </context>
-</TS>
diff --git a/src/PyEditor/resources/translations/PyEditor_msg_ja.ts b/src/PyEditor/resources/translations/PyEditor_msg_ja.ts
deleted file mode 100644 (file)
index 4b32801..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE TS>
-<TS version="2.0" language="ja" sourcelanguage="en">
-  <context>
-    <name>PyEditor_SettingsDlg</name>
-    <message>
-      <source>TIT_PY_PREF</source>
-      <translation>環境設定</translation>
-    </message>
-    <message>
-      <source>GR_FONT_SET</source>
-      <translation>フォント設定</translation>
-    </message>
-    <message>
-      <source>LBL_FONT_FAM</source>
-      <translation>Family:</translation>
-    </message>
-    <message>
-      <source>LBL_FONT_SIZE</source>
-      <translation>Size:</translation>
-    </message>
-    <message>
-      <source>GR_DISP_SET</source>
-      <translation>表示設定</translation>
-    </message>
-    <message>
-      <source>LBL_CURRLINE_HIGHLIGHT</source>
-      <translation>カレントラインのハイライト有効</translation>
-    </message>
-    <message>
-      <source>LBL_TEXT_WRAP</source>
-      <translation>テキストラッピングの有効</translation>
-    </message>
-    <message>
-      <source>LBL_CURSOR_SCROLL</source>
-      <translation>スクロール上の中心カーソル</translation>
-    </message>
-    <message>
-      <source>LBL_LINE_NUMBS_AREA</source>
-      <translation>ライン番号エリアの表示</translation>
-    </message>
-    <message>
-      <source>GR_TAB_SET</source>
-      <translation>タブ設定</translation>
-    </message>
-    <message>
-      <source>LBL_TAB_SPACES</source>
-      <translation>タブ空白の表示</translation>
-    </message>
-    <message>
-      <source>LBL_TAB_SIZE</source>
-      <translation>Tab size:</translation>
-    </message>
-    <message>
-      <source>GR_VERT_EDGE_SET</source>
-      <translation>垂直エッジ設定</translation>
-    </message>
-    <message>
-      <source>LBL_VERT_EDGE</source>
-      <translation>垂直エッジの表示</translation>
-    </message>
-    <message>
-      <source>LBL_NUM_COLUMNS</source>
-      <translation>列数:</translation>
-    </message>
-    <message>
-      <source>WDG_SET_AS_DEFAULT_CHECK</source>
-      <translation>デフォルトとして設定を保存</translation>
-    </message>
-  </context>
-</TS>
index 90c645fc606c9a2ef95f24364ccb783a7819e669..bc4fbe352241854562a013b552301d359d78f50b 100644 (file)
 
 INCLUDE(UseQtExt)
 
+# --- options ---
+
 # additional include directories
 INCLUDE_DIRECTORIES(
   ${QT_INCLUDES}
   ${PROJECT_SOURCE_DIR}/src/Qtx
   ${PROJECT_SOURCE_DIR}/src/SUIT
-  ${PROJECT_SOURCE_DIR}/src/PyEditor
+  ${PROJECT_SOURCE_DIR}/tools/PyEditor/src
 )
 
 # additional preprocessor / compiler flags
@@ -35,6 +37,8 @@ ADD_DEFINITIONS(${QT_DEFINITIONS})
 # libraries to link to
 SET(_link_LIBRARIES ${PLATFORM_LIBS} ${QT_LIBRARIES} qtx suit PyEditor)
 
+# --- headers ---
+
 # header files / to be processed by moc
 SET(_moc_HEADERS
   PyViewer_ViewManager.h
@@ -45,33 +49,46 @@ SET(_moc_HEADERS
 # header files / no moc processing
 SET(_other_HEADERS
   PyViewer.h
+  PyViewer_Settings.h
 )
 
 # header files / to install
 SET(PyViewer_HEADERS ${_moc_HEADERS} ${_other_HEADERS})
 
-# resource files / to be processed by lrelease
-SET(RESOURCES_PATH resources)
+# --- resources ---
 
 SET(_ts_RESOURCES
-  ${RESOURCES_PATH}/translations/PyViewer_msg_en.ts
-  ${RESOURCES_PATH}/translations/PyViewer_msg_fr.ts
-  ${RESOURCES_PATH}/translations/PyViewer_msg_ja.ts
+  resources/PyViewer_msg_en.ts
+  resources/PyViewer_msg_fr.ts
+  resources/PyViewer_msg_ja.ts
+  resources/PyViewer_images.ts
 )
 
-# resource files / to be processed by rcc
-SET(_rcc_RESOURCES ${RESOURCES_PATH}/PyEditor.qrc)
+# resource files / static
+SET(_other_RESOURCES
+  ${PROJECT_SOURCE_DIR}/tools/PyEditor/src/resources/images/py_copy.png
+  ${PROJECT_SOURCE_DIR}/tools/PyEditor/src/resources/images/py_cut.png
+  ${PROJECT_SOURCE_DIR}/tools/PyEditor/src/resources/images/py_delete.png
+  ${PROJECT_SOURCE_DIR}/tools/PyEditor/src/resources/images/py_help.png
+  ${PROJECT_SOURCE_DIR}/tools/PyEditor/src/resources/images/py_new.png
+  ${PROJECT_SOURCE_DIR}/tools/PyEditor/src/resources/images/py_open.png
+  ${PROJECT_SOURCE_DIR}/tools/PyEditor/src/resources/images/py_paste.png
+  ${PROJECT_SOURCE_DIR}/tools/PyEditor/src/resources/images/py_preferences.png
+  ${PROJECT_SOURCE_DIR}/tools/PyEditor/src/resources/images/py_redo.png
+  ${PROJECT_SOURCE_DIR}/tools/PyEditor/src/resources/images/py_save.png
+  ${PROJECT_SOURCE_DIR}/tools/PyEditor/src/resources/images/py_save_as.png
+  ${PROJECT_SOURCE_DIR}/tools/PyEditor/src/resources/images/py_select_all.png
+  ${PROJECT_SOURCE_DIR}/tools/PyEditor/src/resources/images/py_undo.png
+)
 
 # --- sources ---
 
 # sources / moc wrappings
 QT_WRAP_MOC(_moc_SOURCES ${_moc_HEADERS})
 
-# sources / rcc wrappings
-QT_ADD_RESOURCES(_rcc_SOURCES ${_rcc_RESOURCES})
-
 # sources / static
 SET(_other_SOURCES
+  PyViewer_Settings.cxx
   PyViewer_ViewManager.cxx
   PyViewer_ViewModel.cxx
   PyViewer_ViewWindow.cxx
@@ -81,14 +98,11 @@ SET(_other_SOURCES
 SET(PyViewer_SOURCES ${_other_SOURCES} ${_moc_SOURCES})
 
 # --- rules ---
-ADD_LIBRARY(PyViewer ${PyViewer_SOURCES} ${_rcc_SOURCES})
+
+ADD_LIBRARY(PyViewer ${PyViewer_SOURCES})
 TARGET_LINK_LIBRARIES(PyViewer ${_link_LIBRARIES})
 INSTALL(TARGETS PyViewer EXPORT ${PROJECT_NAME}TargetGroup DESTINATION ${SALOME_INSTALL_LIBS})
 
-ADD_EXECUTABLE(DummyPyEditor PyViewer.cxx)
-SET_TARGET_PROPERTIES(DummyPyEditor PROPERTIES OUTPUT_NAME "PyEditor")
-TARGET_LINK_LIBRARIES(DummyPyEditor ${_link_LIBRARIES} PyEditor PyViewer)
-INSTALL(TARGETS DummyPyEditor EXPORT ${PROJECT_NAME}TargetGroup DESTINATION ${SALOME_INSTALL_BINS})
-
 INSTALL(FILES ${PyViewer_HEADERS} DESTINATION ${SALOME_INSTALL_HEADERS})
 QT_INSTALL_TS_RESOURCES("${_ts_RESOURCES}" "${SALOME_GUI_INSTALL_RES_DATA}")
+INSTALL(FILES ${_other_RESOURCES} DESTINATION ${SALOME_GUI_INSTALL_RES_DATA})
diff --git a/src/PyViewer/PyViewer.cxx b/src/PyViewer/PyViewer.cxx
deleted file mode 100644 (file)
index 8106288..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (C) 2015-2016  OPEN CASCADE
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
-//
-// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
-//
-// File   : PyViewer.cxx
-// Author : Maxim GLIBIN, Open CASCADE S.A.S. (maxim.glibin@opencascade.com)
-//
-
-#include <QApplication>
-#include <QDir>
-#include <QLibraryInfo>
-#include <QLocale>
-
-#include "PyViewer_ViewWindow.h"
-
-#include <QtxTranslator.h>
-
-int main( int argc, char *argv[] )
-{
-    QApplication anApplication( argc, argv );
-
-    // Load translations
-    QtxTranslator aTranslatorEd , aTranslatorVi, aTranslatorQt;
-    QString aLanguage = QLocale::system().name().split('_', QString::SkipEmptyParts)[0];
-    if ( !aLanguage.isEmpty() )
-    {
-      if ( aTranslatorQt.load( QString( "qt_%1" ).arg( aLanguage ), QLibraryInfo::location( QLibraryInfo::TranslationsPath ) ) )
-        anApplication.installTranslator( &aTranslatorQt );
-
-      QDir appDir = QApplication::applicationDirPath();
-      appDir.cdUp(); appDir.cdUp();
-
-      if ( aTranslatorEd.load( QString( "PyEditor_msg_%1" ).arg( aLanguage ), appDir.filePath( "share/salome/resources/gui" ) ) )
-        anApplication.installTranslator( &aTranslatorEd );
-    
-      if ( aTranslatorVi.load( QString( "PyViewer_msg_%1" ).arg( aLanguage ), appDir.filePath( "share/salome/resources/gui" ) ) )
-        anApplication.installTranslator( &aTranslatorVi );
-    }
-
-    PyViewer_ViewWindow aViewWin;
-    aViewWin.resize( 650, 700 );
-    aViewWin.show();
-
-    return anApplication.exec();
-}
diff --git a/src/PyViewer/PyViewer_Settings.cxx b/src/PyViewer/PyViewer_Settings.cxx
new file mode 100644 (file)
index 0000000..d86c837
--- /dev/null
@@ -0,0 +1,68 @@
+// Copyright (C) 2015-2016  OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File   : PyViewer_Settings.cxx
+// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
+//
+
+#include "PyViewer_Settings.h"
+
+#include <QtxResourceMgr.h>
+
+PyViewer_Settings::PyViewer_Settings( QtxResourceMgr* resMgr ) :
+  myResMgr( resMgr )
+{
+  load();
+}
+
+PyViewer_Settings::PyViewer_Settings( QtxResourceMgr* resMgr, const QString& group ) :
+  myResMgr( resMgr ),
+  myGroup( group )
+{
+  load();
+}
+
+void PyViewer_Settings::load()
+{
+  if ( !myResMgr ) return;
+  QString group = myGroup.isEmpty() ? option( snEditor ) : myGroup;
+  setHighlightCurrentLine( myResMgr->booleanValue( group, option( snHighlightCurrentLine ), highlightCurrentLine() ) );
+  setTextWrapping( myResMgr->booleanValue( group, option( snTextWrapping ), textWrapping() ) );
+  setCenterCursorOnScroll( myResMgr->booleanValue( group, option( snCenterCursorOnScroll ), centerCursorOnScroll() ) );
+  setLineNumberArea( myResMgr->booleanValue( group, option( snLineNumberArea ), lineNumberArea() ) );
+  setVerticalEdge( myResMgr->booleanValue( group, option( snVerticalEdge  ), verticalEdge() ) );
+  setNumberColumns( myResMgr->integerValue( group, option( snNumberColumns ), numberColumns() ) );
+  setTabSpaceVisible( myResMgr->booleanValue( group, option( snTabSpaceVisible ), tabSpaceVisible() ) );
+  setTabSize( myResMgr->integerValue( group, option( snTabSize ), tabSize() ) );
+  setFont( myResMgr->fontValue( group, option( snFont ), font() ) );
+}
+
+void PyViewer_Settings::save()
+{
+  if ( !myResMgr ) return;
+  QString group = myGroup.isEmpty() ? option( snEditor ) : myGroup;
+  myResMgr->setValue( group, option( snHighlightCurrentLine ), highlightCurrentLine() );
+  myResMgr->setValue( group, option( snTextWrapping ), textWrapping() );
+  myResMgr->setValue( group, option( snCenterCursorOnScroll ), centerCursorOnScroll() );
+  myResMgr->setValue( group, option( snLineNumberArea ), lineNumberArea() );
+  myResMgr->setValue( group, option( snVerticalEdge  ), verticalEdge() );
+  myResMgr->setValue( group, option( snNumberColumns ), numberColumns() );
+  myResMgr->setValue( group, option( snTabSpaceVisible ), tabSpaceVisible() );
+  myResMgr->setValue( group, option( snTabSize ), tabSize() );
+  myResMgr->setValue( group, option( snFont ), font() );
+}
diff --git a/src/PyViewer/PyViewer_Settings.h b/src/PyViewer/PyViewer_Settings.h
new file mode 100644 (file)
index 0000000..2e09552
--- /dev/null
@@ -0,0 +1,45 @@
+// Copyright (C) 2015-2016  OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File   : PyViewer_Settings.h
+// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
+//
+
+#ifndef PYVIEWER_SETTINGS_H
+#define PYVIEWER_SETTINGS_H
+
+#include "PyViewer.h"
+#include "PyEditor_Settings.h"
+
+class QtxResourceMgr;
+
+class PYVIEWER_EXPORT PyViewer_Settings : public PyEditor_Settings
+{
+public:
+  PyViewer_Settings( QtxResourceMgr* );
+  PyViewer_Settings( QtxResourceMgr*, const QString& );
+
+  void load();
+  void save();
+
+private:
+  QtxResourceMgr* myResMgr;
+  QString myGroup;
+};
+
+#endif // PYVIEWER_SETTINGS_H
index c0360da686f377f24ff1b509f5c7b7a53876f03a..1e0be87def1a6c8330fe9cf2dde9cf8ae9fc94a5 100644 (file)
 //
 
 #include "PyViewer_ViewModel.h"
-
 #include "PyViewer_ViewWindow.h"
+#include "PyViewer_Settings.h"
+
+#include "SUIT_ResourceMgr.h"
+#include "SUIT_Session.h"
 
 /*!
   \class PyViewer_Viewer
@@ -34,6 +37,8 @@
 */
 PyViewer_Viewer::PyViewer_Viewer() : SUIT_ViewModel()
 {
+  if ( !PyEditor_Settings::settings() )
+    PyEditor_Settings::setSettings( new PyViewer_Settings( SUIT_Session::session()->resourceMgr(),  "PyEditor" ) );
 }
 
 /*!
@@ -49,17 +54,5 @@ PyViewer_Viewer::~PyViewer_Viewer()
 */
 SUIT_ViewWindow* PyViewer_Viewer::createView( SUIT_Desktop* theDesktop )
 {
-  PyViewer_ViewWindow* aPyViewer = new PyViewer_ViewWindow( theDesktop, this );
-  initView( aPyViewer );
-  return aPyViewer;
-}
-
-/*!
-  Start initialization of view window
-  \param view - view window to be initialized
-*/
-void PyViewer_Viewer::initView( PyViewer_ViewWindow* theViewModel )
-{
-  if ( theViewModel )
-    theViewModel->initLayout();
+  return new PyViewer_ViewWindow( theDesktop );
 }
index 830a16c454b6c499ddea28f8713df0a25994f538..1a519b81725ccf44130cb7217b9c3ef5196f02ee 100644 (file)
@@ -43,9 +43,6 @@ public:
 
   virtual QString getType() const { return Type(); }
   static  QString Type() { return "PyViewer"; }
-
-protected:
-  void initView( PyViewer_ViewWindow* theViewModel );
 };
 
 #endif // PYVIEWER_VIEWMODEL_H
index 5d68c48fb3e14873df95d391f37709b0c09ad5fb..f7c37be7ef38db8dbe6a9ed786a4a63d812f0276 100644 (file)
 #include "PyViewer_ViewWindow.h"
 
 #include "PyEditor_Editor.h"
-#include "PyEditor_Settings.h"
 #include "PyEditor_SettingsDlg.h"
 
-#include <SUIT_Session.h>
-#include <SUIT_ResourceMgr.h>
+#include "SUIT_Session.h"
+#include "SUIT_ResourceMgr.h"
 
-#include <QtxAction.h>
-#include <QtxActionToolMgr.h>
-#include <QtxMultiAction.h>
+#include "QtxAction.h"
+#include "QtxActionToolMgr.h"
 
-#include <QLocale>
+#include <QApplication>
 #include <QFileDialog>
 #include <QMessageBox>
-#include <QApplication>
-#include <QProcess>
-#include <QStatusBar>
 #include <QTextStream>
 
 /*!
 
 /*!
   \brief Constructor.
-  \param theParent parent widget
+  \param desktop SALOME desktop window
 */
-PyViewer_ViewWindow::PyViewer_ViewWindow( SUIT_Desktop* theDesktop , PyViewer_Viewer* theModel ) :
-  SUIT_ViewWindow(theDesktop),
-  myModel(theModel)
-{
-  my_IsExternal = (theDesktop == NULL);
-
-  if( isExternal() )
-    initLayout();
-}
-
-void PyViewer_ViewWindow::initLayout()
+PyViewer_ViewWindow::PyViewer_ViewWindow( SUIT_Desktop* desktop ) :
+  SUIT_ViewWindow( desktop )
 {
-  my_TextEditor = new PyEditor_Editor( my_IsExternal ,SUIT_Session::session()->resourceMgr(), this );
-  setCentralWidget( my_TextEditor );
-
-  createActions();
-  createToolBar();
+  // Create editor and set it as a central widget.
+  myTextEditor = new PyEditor_Editor( this );
+  setCentralWidget( myTextEditor );
+
+  // Create actions.
+  SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
+  QtxAction* action;
+
+  // . New
+  action = new QtxAction( tr( "TTP_NEW" ),
+                          resMgr->loadPixmap( "PyViewer", tr( "ICON_NEW" ) ),
+                          tr( "ACT_NEW" ), 0, this );
+  action->setStatusTip( tr( "DSC_NEW" ) );
+  action->setShortcut( QKeySequence::New );
+  connect( action, SIGNAL( triggered( bool ) ), this, SLOT( onNew() ) );
+  toolMgr()->registerAction( action, NewId );
+  
+  // . Open
+  action = new QtxAction( tr( "TTP_OPEN" ),
+                          resMgr->loadPixmap( "PyViewer", tr( "ICON_OPEN" ) ),
+                          tr( "ACT_OPEN" ), 0, this );
+  action->setStatusTip( tr( "DSC_OPEN" ) );
+  action->setShortcut( QKeySequence::Open );
+  connect( action, SIGNAL( triggered( bool ) ), this, SLOT( onOpen() ) );
+  toolMgr()->registerAction( action, OpenId );
+  
+  // . Save
+  action = new QtxAction( tr( "TTP_SAVE" ),
+                          resMgr->loadPixmap( "PyViewer", tr( "ICON_SAVE" ) ),
+                          tr( "ACT_SAVE" ), 0, this );
+  action->setStatusTip( tr( "DSC_SAVE" ) );
+  action->setShortcut( QKeySequence::Save );
+  connect( action, SIGNAL( triggered( bool ) ), this, SLOT( onSave() ) );
+  action->setEnabled( false );
+  connect( myTextEditor->document(), SIGNAL( modificationChanged( bool ) ),
+           action, SLOT( setEnabled( bool ) ) );
+  toolMgr()->registerAction( action, SaveId );
+  
+  // . SaveAs
+  action = new QtxAction( tr( "TTP_SAVEAS" ),
+                          resMgr->loadPixmap( "PyViewer", tr( "ICON_SAVEAS" ) ),
+                          tr( "ACT_SAVEAS" ), 0, this );
+  action->setStatusTip( tr( "DSC_SAVEAS" ) );
+  action->setShortcut( QKeySequence::SaveAs );
+  connect( action, SIGNAL( triggered( bool ) ), this, SLOT( onSaveAs() ) );
+  toolMgr()->registerAction( action, SaveAsId );
+
+  // . Undo
+  action = new QtxAction( tr( "TTP_UNDO" ),
+                          resMgr->loadPixmap( "PyViewer", tr( "ICON_UNDO" ) ),
+                          tr( "ACT_UNDO" ), 0, this );
+  action->setStatusTip( tr( "DSC_UNDO" ) );
+  action->setShortcut( QKeySequence::Undo );
+  connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( undo() ) );
+  action->setEnabled( false );
+  connect( myTextEditor->document(), SIGNAL( undoAvailable( bool ) ),
+           action, SLOT( setEnabled( bool ) ) );
+  toolMgr()->registerAction( action, UndoId );
+
+  // . Redo
+  action = new QtxAction( tr( "TTP_REDO" ), 
+                          resMgr->loadPixmap( "PyViewer", tr( "ICON_REDO" ) ),
+                          tr( "ACT_REDO" ), 0, this );
+  action->setStatusTip( tr( "DSC_REDO" ) );
+  action->setShortcut( QKeySequence::Redo );
+  connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( redo() ) );
+  action->setEnabled( false );
+  connect( myTextEditor->document(), SIGNAL( redoAvailable( bool ) ),
+           action, SLOT( setEnabled( bool ) ) );
+  toolMgr()->registerAction( action, RedoId );
+
+  // . Cut
+  action = new QtxAction( tr( "TTP_CUT" ),
+                          resMgr->loadPixmap( "PyViewer", tr( "ICON_CUT" ) ),
+                          tr( "ACT_CUT" ), 0, this );
+  action->setStatusTip( tr( "DSC_CUT" ) );
+  action->setShortcut( QKeySequence::Cut );
+  connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( cut() ) );
+  action->setEnabled( false );
+  connect( myTextEditor, SIGNAL( copyAvailable( bool ) ),
+           action, SLOT( setEnabled( bool ) ) );
+  toolMgr()->registerAction( action, CutId );
+
+  // . Copy
+  action = new QtxAction( tr( "TTP_COPY" ), 
+                          resMgr->loadPixmap( "PyViewer", tr( "ICON_COPY" ) ),
+                          tr( "ACT_COPY" ), 0, this );
+  action->setStatusTip( tr( "DSC_COPY" ) );
+  action->setShortcut( QKeySequence::Copy );
+  connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( copy() ) );
+  action->setEnabled( false );
+  connect( myTextEditor, SIGNAL( copyAvailable( bool ) ),
+           action, SLOT( setEnabled( bool ) ) );
+  toolMgr()->registerAction( action, CopyId );
+
+  // . Paste
+  action = new QtxAction( tr( "TTP_PASTE" ),
+                          resMgr->loadPixmap( "PyViewer", tr( "ICON_PASTE" ) ),
+                          tr( "ACT_PASTE" ), 0, this );
+  action->setStatusTip( tr( "DSC_PASTE" ) );
+  action->setShortcut( QKeySequence::Paste );
+  connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( paste() ) );
+  toolMgr()->registerAction( action, PasteId );
+
+  // . Delete
+  action = new QtxAction( tr( "TTP_DELETE" ),
+                          resMgr->loadPixmap( "PyViewer", tr( "ICON_DELETE" ) ),
+                          tr( "ACT_DELETE" ), 0, this );
+  action->setStatusTip( tr( "DSC_DELETE" ) );
+  action->setShortcut( QKeySequence::Delete );
+  connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( deleteSelected() ) );
+  action->setEnabled( false );
+  connect( myTextEditor, SIGNAL( copyAvailable( bool ) ),
+           action, SLOT( setEnabled( bool ) ) );
+  toolMgr()->registerAction( action, DeleteId );
+
+  // . SelectAll
+  action = new QtxAction( tr( "TTP_SELECT_ALL" ),
+                          resMgr->loadPixmap( "PyViewer", tr( "ICON_SELECT_ALL" ) ),
+                          tr( "ACT_SELECT_ALL" ), 0, this );
+  action->setStatusTip( tr( "DSC_SELECT_ALL" ) );
+  action->setShortcut( QKeySequence::SelectAll );
+  connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( selectAll() ) );
+  toolMgr()->registerAction( action, SelectAllId );
+
+  // . Preferences
+  action = new QtxAction( tr( "TTP_PREFERENCES" ),
+                          resMgr->loadPixmap( "PyViewer", tr( "ICON_PREFERENCES" ) ),
+                          tr( "ACT_PREFERENCES" ), 0, this );
+  action->setStatusTip( tr( "DSC_PREFERENCES" ) );
+  connect( action, SIGNAL( triggered( bool ) ), this, SLOT( onPreferences() ) );
+  toolMgr()->registerAction( action, PreferencesId );
+
+  // . Help
+  action = new QtxAction( tr( "TTP_HELP" ),
+                          resMgr->loadPixmap( "PyViewer", tr( "ICON_HELP" ) ),
+                          tr( "ACT_HELP" ), 0, this );
+  action->setStatusTip( tr( "DSC_HELP" ) );
+  connect( action, SIGNAL( triggered() ), this, SLOT( onHelp() ) );
+  toolMgr()->registerAction( action, HelpId );
+
+  // Create toolbar.
+  int idTB = toolMgr()->createToolBar( tr("TOOLBAR_LABEL"), QString( "PythonEditor" ), false );
+  toolMgr()->append( NewId, idTB );
+  toolMgr()->append( OpenId, idTB );
+  toolMgr()->append( SaveId, idTB );
+  toolMgr()->append( SaveAsId, idTB );
+  toolMgr()->append( toolMgr()->separator(), idTB );
+  toolMgr()->append( UndoId, idTB );
+  toolMgr()->append( RedoId, idTB );
+  toolMgr()->append( toolMgr()->separator(), idTB );
+  toolMgr()->append( CutId, idTB );
+  toolMgr()->append( CopyId, idTB );
+  toolMgr()->append( PasteId, idTB );
+  toolMgr()->append( DeleteId, idTB );
+  toolMgr()->append( SelectAllId, idTB );
+  toolMgr()->append( toolMgr()->separator(), idTB );
+  toolMgr()->append( PreferencesId, idTB );
+  toolMgr()->append( toolMgr()->separator(), idTB );
+  toolMgr()->append( HelpId, idTB );
+
+  // Set current file.
   setCurrentFile( QString() );
-    
-  if ( isExternal() )
-    {
-      connect( my_TextEditor->document(), SIGNAL( modificationChanged( bool ) ),
-              this, SLOT( setWindowModified( bool ) ) );
-      
-      statusBar()->showMessage( tr("STS_READY") );
-    }  
 }
 
 /*!
   \brief Destructor.
- */
-PyViewer_ViewWindow::~PyViewer_ViewWindow()
-{
-  my_CurrentFile.clear();
-  delete my_TextEditor;
-}
-
-/*!
-  \return \c true if the application is external
- */
-bool PyViewer_ViewWindow::isExternal()
-{
-  return my_IsExternal;
-}
-
-/*!
-  \brief Creates actions of Python view window.
 */
-void PyViewer_ViewWindow::createActions()
-{
-  QtxActionToolMgr* aMgr = toolMgr();
-  QtxAction* anAction;
-
-  // 1. File operations
-  // 1.1. Create New action
-  anAction = new QtxAction( tr( "MNU_PY_NEW" ), QIcon( ":/images/py_new.png" ),
-                                 tr( "MNU_PY_NEW" ), 0, this );
-  anAction->setStatusTip( tr( "DSC_PY_NEW" ) );
-  anAction->setShortcuts( QKeySequence::New );
-  connect( anAction, SIGNAL( triggered( bool ) ), this, SLOT( onNew() ) );
-  aMgr->registerAction( anAction, NewId );
-
-  // 1.2 Create Open action
-  anAction = new QtxAction( tr( "MNU_PY_OPEN" ), QIcon( ":/images/py_open.png" ),
-                                  tr( "MNU_PY_OPEN" ), 0, this );
-  anAction->setStatusTip( tr( "DSC_PY_OPEN" ) );
-  anAction->setShortcuts( QKeySequence::Open );
-  connect( anAction, SIGNAL( triggered( bool ) ), this, SLOT( onOpen() ) );
-  aMgr->registerAction( anAction, OpenId );
-
-  // 1.3. Create Save action
-  anAction = new QtxAction( tr( "MNU_PY_SAVE" ), QIcon( ":/images/py_save.png" ),
-                                  tr( "MNU_PY_SAVE" ), 0, this );
-  anAction->setStatusTip( tr( "DSC_PY_SAVE" ) );
-  anAction->setShortcuts( QKeySequence::Save );
-  connect( anAction, SIGNAL( triggered( bool ) ), this, SLOT( onSave() ) );
-  aMgr->registerAction( anAction, SaveId );
-  // Set default statement for Save action
-  anAction->setEnabled( my_TextEditor->document()->isModified() );
-  connect( my_TextEditor->document(), SIGNAL( modificationChanged( bool ) ),
-    anAction, SLOT( setEnabled( bool ) ) );
-
-  // 1.4. Create SaveAs action
-  anAction = new QtxAction( tr( "MNU_PY_SAVEAS" ), QIcon( ":/images/py_save_as.png" ),
-                                    tr( "MNU_PY_SAVEAS" ), 0, this );
-  anAction->setStatusTip( tr( "DSC_PY_SAVEAS" ) );
-  anAction->setShortcut( Qt::CTRL + Qt::SHIFT + Qt::Key_S );
-  connect( anAction, SIGNAL( triggered( bool ) ), this, SLOT( onSaveAs() ) );
-  aMgr->registerAction( anAction, SaveAsId );
-
-  // 1.5 Create multi-action for file operations
-  /*QtxMultiAction* aFileAction = new QtxMultiAction( this );
-  aFileAction->insertAction( aMgr->action( NewId ) );
-  aFileAction->insertAction( aMgr->action( OpenId ) );
-  aFileAction->insertAction( aMgr->action( SaveId ) );
-  aFileAction->insertAction( aMgr->action( SaveAsId ) );
-  aMgr->registerAction( aFileAction, FileOpId );*/
-
-  // 1.6. Create Close action
-  if (isExternal())
-  {
-    anAction = new QtxAction( tr( "MNU_PY_CLOSE" ), QIcon( ":/images/py_close.png" ),
-                              tr( "MNU_PY_CLOSE" ), 0, this );
-    anAction->setStatusTip( tr( "DSC_PY_CLOSE" ) );
-    anAction->setShortcut( Qt::CTRL + Qt::Key_Q );
-    connect( anAction, SIGNAL( triggered( bool ) ), this, SLOT( close() ) );
-    aMgr->registerAction( anAction, CloseId );
-  }
-
-  // 2. Edit operations
-  // 2.1. Create Undo action
-  anAction = new QtxAction( tr( "MNU_PY_UNDO" ), QIcon( ":/images/py_undo.png" ),
-                            tr( "MNU_PY_UNDO" ), 0, this );
-  anAction->setStatusTip( tr( "DSC_PY_UNDO" ) );
-  anAction->setShortcuts( QKeySequence::Undo );
-  connect( anAction, SIGNAL( triggered( bool ) ), my_TextEditor, SLOT( undo() ) );
-  aMgr->registerAction( anAction, UndoId );
-  // Set default statement for Undo action
-  anAction->setEnabled( my_TextEditor->document()->isUndoAvailable() );
-  connect( my_TextEditor->document(), SIGNAL( undoAvailable( bool ) ),
-           anAction, SLOT( setEnabled( bool ) ) );
-
-  // 2.2. Create Redo action
-  anAction = new QtxAction( tr( "MNU_PY_REDO" ), QIcon( ":/images/py_redo.png" ),
-                            tr( "MNU_PY_REDO" ), 0, this );
-  anAction->setStatusTip( tr( "DSC_PY_REDO" ) );
-  anAction->setShortcuts( QKeySequence::Redo );
-  connect( anAction, SIGNAL( triggered( bool ) ), my_TextEditor, SLOT( redo() ) );
-  aMgr->registerAction( anAction, RedoId );
-  // Set default statement for Redo action
-  anAction->setEnabled( my_TextEditor->document()->isRedoAvailable() );
-  connect( my_TextEditor->document(), SIGNAL( redoAvailable( bool ) ),
-           anAction, SLOT( setEnabled( bool ) ) );
-
-  // 2.3. Create Cut action
-  anAction = new QtxAction( tr( "MNU_PY_CUT" ), QIcon( ":/images/py_cut.png" ),
-                            tr( "MNU_PY_CUT" ), 0, this );
-  anAction->setStatusTip( tr( "DSC_PY_CUT" ) );
-  anAction->setShortcuts( QKeySequence::Cut );
-  connect( anAction, SIGNAL( triggered( bool ) ), my_TextEditor, SLOT( cut() ) );
-  aMgr->registerAction( anAction, CutId );
-  // Set default statement for Cut action
-  anAction->setEnabled( false );
-  connect( my_TextEditor, SIGNAL( copyAvailable( bool ) ),
-           anAction, SLOT( setEnabled( bool ) ) );
-
-  // 2.4. Create Copy action
-  anAction = new QtxAction( tr( "MNU_PY_COPY" ), QIcon( ":/images/py_copy.png" ),
-                            tr( "MNU_PY_COPY" ), 0, this );
-  anAction->setStatusTip( tr( "DSC_PY_COPY" ) );
-  anAction->setShortcuts( QKeySequence::Copy );
-  connect( anAction, SIGNAL( triggered( bool ) ), my_TextEditor, SLOT( copy() ) );
-  aMgr->registerAction( anAction, CopyId );
-  // Set default statement for Copy action
-  anAction->setEnabled( false );
-  connect( my_TextEditor, SIGNAL( copyAvailable( bool ) ),
-           anAction, SLOT( setEnabled( bool ) ) );
-
-  // 2.5. Create Paste action
-  anAction = new QtxAction( tr( "MNU_PY_PASTE" ), QIcon( ":/images/py_paste.png" ),
-                            tr( "MNU_PY_PASTE" ), 0, this );
-  anAction->setStatusTip( tr( "DSC_PY_PASTE" ) );
-  anAction->setShortcuts( QKeySequence::Paste );
-  connect( anAction, SIGNAL( triggered( bool ) ), my_TextEditor, SLOT( paste() ) );
-  aMgr->registerAction( anAction, PasteId );
-
-  // 2.6. Create Delete action
-  anAction = new QtxAction( tr( "MNU_PY_DELETE" ), QIcon( ":/images/py_delete.png" ),
-                            tr( "MNU_PY_DELETE" ), 0, this );
-  anAction->setStatusTip( tr( "DSC_PY_DELETE" ) );
-  anAction->setShortcuts( QKeySequence::Delete );
-  connect( anAction, SIGNAL( triggered( bool ) ), my_TextEditor, SLOT( deleteSelected() ) );
-  aMgr->registerAction( anAction, DeleteId );
-  // Set default statement for Delete action
-  anAction->setEnabled( false );
-  connect( my_TextEditor, SIGNAL( copyAvailable( bool ) ),
-           anAction, SLOT( setEnabled( bool ) ) );
-
-  // 2.7. Create SelectAll action
-  anAction = new QtxAction( tr( "MNU_PY_SELECTALL" ), QIcon( ":/images/py_select_all.png" ),
-                            tr( "MNU_PY_SELECTALL" ), 0, this );
-  anAction->setStatusTip( tr( "DSC_PY_SELECT_ALL" ) );
-  anAction->setShortcuts( QKeySequence::SelectAll );
-  connect( anAction, SIGNAL( triggered( bool ) ), my_TextEditor, SLOT( selectAll() ) );
-  aMgr->registerAction( anAction, SelectAllId );
-
-  // 2.8. Create multi-action for edit operations
-  /*QtxMultiAction* anEditAction = new QtxMultiAction( this );
-  anEditAction->insertAction( aMgr->action( UndoId ) );
-  anEditAction->insertAction( aMgr->action( RedoId ) );
-  anEditAction->insertAction( aMgr->action( CutId ) );
-  anEditAction->insertAction( aMgr->action( CopyId ) );
-  anEditAction->insertAction( aMgr->action( PasteId ) );
-  anEditAction->insertAction( aMgr->action( DeleteId ) );
-  anEditAction->insertAction( aMgr->action( SelectAllId ) );
-  aMgr->registerAction( anEditAction, EditOpId );*/
-
-  // 3. Create Preference action
-  anAction = new QtxAction( tr( "MNU_PY_PREFERENCES" ), QIcon( ":/images/py_preferences.png" ),
-                            tr( "MNU_PY_PREFERENCES" ), 0, this );
-  anAction->setStatusTip( tr( "DSC_PY_PREFERENCES" ) );
-  connect( anAction, SIGNAL( triggered( bool ) ), this, SLOT( onPreferences() ) );
-  aMgr->registerAction( anAction, PreferencesId );
-
-  // 4. Help operations
-
-  // 4.1. Create Help action
-  anAction = new QtxAction( tr( "MNU_PY_BROWSER" ), QIcon( ":/images/py_browser.png" ),
-                            tr( "MNU_PY_BROWSER" ), 0, this );
-  anAction->setStatusTip( tr( "DSC_PY_BROWSER" ) );
-  connect( anAction, SIGNAL( triggered() ), this, SLOT( onBrowser() ) );
-  //aMgr->registerAction( anAction, BrowserId );
-
-  // 4.2. Create multi-action for help operations
-  /*QtxMultiAction* aHelpAction = new QtxMultiAction( this );
-  aHelpAction->insertAction( aMgr->action( BrowserId ) );
-  aMgr->registerAction( aHelpAction, HelpOpId );*/
-}
-
-/*!
-  \brief Create toolbar for the python view window.
-*/
-void PyViewer_ViewWindow::createToolBar()
+PyViewer_ViewWindow::~PyViewer_ViewWindow()
 {
-  QtxActionToolMgr* aMgr = toolMgr();
-  int idTB = aMgr->createToolBar( tr("LBL_TOOLBAR_LABEL"),         // title (language-dependent)
-                                  QString( "PyEditorOperations" ), // name (language-independent)
-                                  false );                         // disable floatable toolbar
-  aMgr->append( NewId, idTB );
-  aMgr->append( OpenId, idTB );
-  aMgr->append( SaveId, idTB );
-  aMgr->append( SaveAsId, idTB );
-  if ( isExternal() )
-    aMgr->append( CloseId, idTB );
-  aMgr->append( aMgr->separator(), idTB );
-  aMgr->append( UndoId, idTB );
-  aMgr->append( RedoId, idTB );
-  aMgr->append( aMgr->separator(), idTB );
-  aMgr->append( CutId, idTB );
-  aMgr->append( CopyId, idTB );
-  aMgr->append( PasteId, idTB );
-  aMgr->append( DeleteId, idTB );
-  aMgr->append( SelectAllId, idTB );
-  aMgr->append( aMgr->separator(), idTB );
-  aMgr->append( PreferencesId, idTB );
-  aMgr->append( aMgr->separator(), idTB );
-  aMgr->append( BrowserId, idTB );
-
 }
 
 /*!
-  \brief Reimplemented class is to receive a window close request.
-  \param theEvent event
+  \brief Manage window close request.
+  \param event close event
 */
-void PyViewer_ViewWindow::closeEvent( QCloseEvent* theEvent )
+void PyViewer_ViewWindow::closeEvent( QCloseEvent* event )
 {
   if ( whetherSave() )
-    theEvent->accept();
+    event->accept();
   else
-    theEvent->ignore();
+    event->ignore();
 }
 
 /*!
-  SLOT: Creates a new document
- */
+  SLOT: Create new document
+*/
 void PyViewer_ViewWindow::onNew()
 {
   if ( whetherSave() )
   {
-    my_TextEditor->clear();
+    myTextEditor->clear();
     setCurrentFile( QString() );
   }
 }
 
 /*!
-  SLOT: Open an existing python file
- */
+  SLOT: Open existing Python file
+*/
 void PyViewer_ViewWindow::onOpen()
 {
   if ( whetherSave() )
   {
-    QString aFilePath = QFileDialog::getOpenFileName( 
-      this, tr( "TIT_DLG_OPEN" ), QDir::currentPath(), "Python Files (*.py)" );
+    QString filter = tr( "TIT_PY_FILES" );
+    filter += " (*.py)";
+    QString aFilePath = QFileDialog::getOpenFileName( this,
+                                                      tr( "TIT_DLG_OPEN" ),
+                                                      QDir::currentPath(),
+                                                      filter );
 
     if ( !aFilePath.isEmpty() )
       loadFile( aFilePath );
@@ -340,24 +264,29 @@ void PyViewer_ViewWindow::onOpen()
 }
 
 /*!
-  SLOT: Save the current file
- */
+  SLOT: Save current document
+*/
 bool PyViewer_ViewWindow::onSave()
 {
-  if ( my_CurrentFile.isEmpty() )
+  if ( myURL.isEmpty() )
     return onSaveAs();
   else
-    return saveFile( my_CurrentFile );
+    return saveFile( myURL );
 }
 
 
 /*!
-  SLOT: Save the current file under a new name
- */
+  SLOT: Save current document under a new name
+*/
 bool PyViewer_ViewWindow::onSaveAs()
 {
-  QString aFilePath = QFileDialog::getSaveFileName(
-    this, tr( "TIT_DLG_SAVEAS" ), QDir::currentPath(), "Python Files (*.py)" );
+  QString filter = tr( "TIT_PY_FILES" );
+  filter += " (*.py)";
+  QString url = myURL.isEmpty() ? defaultName() : myURL;
+  QString aFilePath = QFileDialog::getSaveFileName( this,
+                                                    tr( "TIT_DLG_SAVE" ),
+                                                    url,
+                                                    filter );
 
   if ( !aFilePath.isEmpty() )
     return saveFile( aFilePath );
@@ -367,143 +296,120 @@ bool PyViewer_ViewWindow::onSaveAs()
 
 /*!
   SLOT: Open preferences dialog
- */
+*/
 void PyViewer_ViewWindow::onPreferences()
 {
-  PyEditor_SettingsDlg* aPage = new PyEditor_SettingsDlg( my_TextEditor, this );
-  connect( aPage, SIGNAL( onHelpClicked() ),
-          this, SLOT( onHelp() ) );
-  aPage->exec();
-  delete aPage;
+  PyEditor_SettingsDlg dlg( myTextEditor, true, this );
+  connect( &dlg, SIGNAL( help() ), this, SLOT( onHelp() ) );
+  dlg.exec();
 }
 
 /*!
-  \brief Set preferece values for view.
- */
-void PyViewer_ViewWindow::setPreferences()
+  \brief Associate \a filePath with the current document
+  \param filePath document's file path
+*/
+void PyViewer_ViewWindow::setCurrentFile( const QString& filePath )
 {
-  my_TextEditor->settings()->readSettings();
-  my_TextEditor->updateStatement();
+  myURL = filePath;
+  myTextEditor->document()->setModified( false );
 }
 
 /*!
-  \brief Associates the theFilePath with the python view.
-  \param theFilePath file path
- */
-void PyViewer_ViewWindow::setCurrentFile( const QString &theFilePath )
-{
-  my_CurrentFile = theFilePath;
-  my_TextEditor->document()->setModified( false );
-
-  if ( isExternal() )
-  {
-    setWindowModified( false );
-
-    QString aShownName = my_CurrentFile;
-    if ( my_CurrentFile.isEmpty() )
-      aShownName = "untitled.py";
-    setWindowFilePath( aShownName );
-
-    // Set window title with associated file path
-    QFileInfo anInfo( aShownName );
-    setWindowTitle( "Python Viewer - " + anInfo.fileName() + "[*]" );
-  }
-}
-
-/*!
-  \brief Checks whether the file is modified.
+  \brief Check whether the file is modified.
   If it has the modifications then ask the user to save it.
   \return true if the document is saved.
- */
+*/
 bool PyViewer_ViewWindow::whetherSave()
 {
-  if ( my_TextEditor->document()->isModified() )
+  if ( myTextEditor->document()->isModified() )
   {
-    QMessageBox::StandardButton aReturn;
-    aReturn = QMessageBox::warning(
-      this, tr( "TIT_DLG_SAVE" ),tr( "WRN_PY_SAVE_FILE" ),
-      QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel );
-
-    if ( aReturn == QMessageBox::Save )
+    QMessageBox::StandardButton answer =  QMessageBox::warning( this,
+                                                                tr( "NAME_PYEDITOR" ),
+                                                                tr( "WRN_SAVE_FILE" ),
+                                                                QMessageBox::Save |
+                                                                QMessageBox::Discard |
+                                                                QMessageBox::Cancel );
+    switch( answer )
+    {
+    case QMessageBox::Save:
       return onSave();
-    else if ( aReturn == QMessageBox::Cancel )
+    case QMessageBox::Cancel:
       return false;
+    default:
+      break;
+    }
   }
   return true;
 }
 
 /*!
-  \brief Opens file.
-  \param theFilePath file path
- */
-void PyViewer_ViewWindow::loadFile( const QString &theFilePath )
+  \brief Open file.
+  \param filePath file path
+*/
+void PyViewer_ViewWindow::loadFile( const QString& filePath )
 {
-  QFile aFile( theFilePath );
+  QFile aFile( filePath );
   if ( !aFile.open(QFile::ReadOnly | QFile::Text) )
   {
     QMessageBox::warning( this, tr( "NAME_PYEDITOR" ),
-      tr( "WRN_PY_READ_FILE" ).arg( theFilePath ).arg( aFile.errorString() ) );
+                          tr( "WRN_READ_FILE" ).arg( filePath ).arg( aFile.errorString() ) );
     return;
   }
 
   QTextStream anInput( &aFile );
   QApplication::setOverrideCursor( Qt::WaitCursor );
-  my_TextEditor->setPlainText( anInput.readAll() );
+  myTextEditor->setPlainText( anInput.readAll() );
   QApplication::restoreOverrideCursor();
 
-  setCurrentFile( theFilePath );
+  setCurrentFile( filePath );
   aFile.close();
-  if ( isExternal() )
-    statusBar()->showMessage( tr( "STS_F_LOADED" ), 2000 );
+
 }
 
 /*!
   \brief Saves file.
   \param theFilePath file path
- */
-bool PyViewer_ViewWindow::saveFile( const QString &theFilePath )
+*/
+bool PyViewer_ViewWindow::saveFile( const QString& filePath )
 {
-  QFile aFile( theFilePath );
+  QFile aFile( filePath );
   if ( !aFile.open( QFile::WriteOnly | QFile::Text ) )
   {
     QMessageBox::warning( this, tr( "NAME_PYEDITOR" ),
-      tr( "WRN_PY_WRITE_FILE" ).arg( theFilePath ).arg( aFile.errorString() ) );
+                          tr( "WRN_WRITE_FILE" ).arg( filePath ).arg( aFile.errorString() ) );
     return false;
   }
 
   QTextStream anOutput( &aFile );
   QApplication::setOverrideCursor( Qt::WaitCursor );
-  anOutput << my_TextEditor->toPlainText();
+  anOutput << myTextEditor->toPlainText();
   QApplication::restoreOverrideCursor();
 
-  setCurrentFile( theFilePath );
+  setCurrentFile( filePath );
   aFile.close();
 
-  if ( isExternal() )
-    statusBar()->showMessage( tr( "STS_F_SAVED" ), 2000 );
-
   return true;
 }
 
 /*!
-  \brief Opens help browser with python view help information.
- */
-void PyViewer_ViewWindow::onBrowser()
+  Slot, called when user clicks "Help" button in "Preferences" dialog box.
+*/
+void PyViewer_ViewWindow::onHelp()
 {
-  QDir appDir = QApplication::applicationDirPath();
-  QStringList parameters;
-  parameters << QString( "--file=%1" ).arg( appDir.filePath( "pyeditor.html" ) );
-  QProcess::startDetached( "HelpBrowser", parameters );
+  SUIT_Application* app = SUIT_Session::session()->activeApplication();
+  if ( app ) {
+    QString page = "python_viewer_page.html";
+    if ( qobject_cast<QWidget*>( sender() ) )
+      page += "#custom_python_preferences";
+    app->onHelpContextModule( "GUI", page );
+  }
 }
 
 /*!
-  Slot, called when user clicks "Help" button in "Preferences" dialog box.
+  Get default name for Python file 
+  \return default name
 */
-void PyViewer_ViewWindow::onHelp()
+QString PyViewer_ViewWindow::defaultName() const
 {
-#ifndef NO_SUIT
-  SUIT_Application* app = SUIT_Session::session()->activeApplication();
-  if ( app )
-    app->onHelpContextModule( "GUI", "python_viewer_page.html", "custom_python_preferences" );
-#endif
+  return tr( "NONAME" );
 }
index c7c207f13ab91db6fc19321570de3ed697be14cd..b96ea8b2c307f7000118566beb8ef4214f6936ac 100644 (file)
 #include <SUIT_ViewWindow.h>
 
 class PyEditor_Editor;
-class PyViewer_Viewer;
 
 class PYVIEWER_EXPORT PyViewer_ViewWindow : public SUIT_ViewWindow
 {
   Q_OBJECT
 
 public:
-  enum { NewId, OpenId, SaveId, SaveAsId, CloseId, FileOpId,
-         UndoId, RedoId, CutId, CopyId, PasteId, DeleteId, SelectAllId, EditOpId,
-         PreferencesId, BrowserId, HelpOpId };
+  enum { NewId, OpenId, SaveId, SaveAsId,
+         UndoId, RedoId, CutId, CopyId, PasteId, DeleteId, SelectAllId,
+         PreferencesId, HelpId };
 
-  PyViewer_ViewWindow( SUIT_Desktop* theDesktop = 0, PyViewer_Viewer* theModel = 0 );
+  PyViewer_ViewWindow( SUIT_Desktop* = 0 );
   ~PyViewer_ViewWindow();
 
-  virtual void initLayout();
-
-  bool         isExternal();
-  void         setPreferences();
-
 protected:
   virtual void closeEvent( QCloseEvent* );
 
@@ -56,7 +50,6 @@ private Q_SLOTS:
   bool        onSave();
   bool        onSaveAs();
   void        onPreferences();
-  void        onBrowser();
   void        onHelp();
 
 private:
@@ -65,16 +58,11 @@ private:
   
   void        setCurrentFile( const QString& );
   bool        whetherSave();
+  QString     defaultName() const;
 
 private:
-  void        createActions();
-  void        createToolBar();
-
-private:
-  PyViewer_Viewer*  myModel;
-  PyEditor_Editor*  my_TextEditor;
-  QString           my_CurrentFile;
-  bool              my_IsExternal;
+  PyEditor_Editor*  myTextEditor;
+  QString           myURL;
 };
 
 #endif // PYVIEWER_VIEWWINDOW_H
diff --git a/src/PyViewer/resources/PyEditor.qrc b/src/PyViewer/resources/PyEditor.qrc
deleted file mode 100644 (file)
index 2f703f9..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE RCC><RCC version="1.0">
-  <qresource>
-    <file>images/py_browser.png</file>
-    <file>images/py_close.png</file>
-    <file>images/py_copy.png</file>
-    <file>images/py_cut.png</file>
-    <file>images/py_delete.png</file>
-    <file>images/py_new.png</file>
-    <file>images/py_open.png</file>
-    <file>images/py_paste.png</file>
-    <file>images/py_preferences.png</file>
-    <file>images/py_redo.png</file>
-    <file>images/py_save.png</file>
-    <file>images/py_save_as.png</file>
-    <file>images/py_select_all.png</file>
-    <file>images/py_undo.png</file>
-  </qresource>
-</RCC>
diff --git a/src/PyViewer/resources/PyViewer_images.ts b/src/PyViewer/resources/PyViewer_images.ts
new file mode 100644 (file)
index 0000000..639f1b5
--- /dev/null
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="en_US">
+<context>
+    <name>PyViewer_ViewWindow</name>
+    <message>
+        <source>ICON_NEW</source>
+        <translation>py_new.png</translation>
+    </message>
+    <message>
+        <source>ICON_OPEN</source>
+        <translation>py_open.png</translation>
+    </message>
+    <message>
+        <source>ICON_SAVE</source>
+        <translation>py_save.png</translation>
+    </message>
+    <message>
+        <source>ICON_SAVEAS</source>
+        <translation>py_save_as.png</translation>
+    </message>
+    <message>
+        <source>ICON_UNDO</source>
+        <translation>py_undo.png</translation>
+    </message>
+    <message>
+        <source>ICON_REDO</source>
+        <translation>py_redo.png</translation>
+    </message>
+    <message>
+        <source>ICON_CUT</source>
+        <translation>py_cut.png</translation>
+    </message>
+    <message>
+        <source>ICON_COPY</source>
+        <translation>py_copy.png</translation>
+    </message>
+    <message>
+        <source>ICON_PASTE</source>
+        <translation>py_paste.png</translation>
+    </message>
+    <message>
+        <source>ICON_DELETE</source>
+        <translation>py_delete.png</translation>
+    </message>
+    <message>
+        <source>ICON_SELECT_ALL</source>
+        <translation>py_select_all.png</translation>
+    </message>
+    <message>
+        <source>ICON_PREFERENCES</source>
+        <translation>py_preferences.png</translation>
+    </message>
+    <message>
+        <source>ICON_HELP</source>
+        <translation>py_help.png</translation>
+    </message>
+</context>
+</TS>
diff --git a/src/PyViewer/resources/PyViewer_msg_en.ts b/src/PyViewer/resources/PyViewer_msg_en.ts
new file mode 100644 (file)
index 0000000..0f4355e
--- /dev/null
@@ -0,0 +1,206 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="en">
+  <context>
+      <name>PyViewer_ViewManager</name>
+      <message>
+          <source>PYVIEWER_VIEW_TITLE</source>
+          <translation>Python viewer:%M - viewer:%V</translation>
+      </message>
+  </context>
+  <context>
+    <name>PyViewer_ViewWindow</name>
+    <message>
+      <source>NAME_PYEDITOR</source>
+      <translation>Python Editor</translation>
+    </message>
+    <message>
+      <source>ACT_NEW</source>
+      <translation>&amp;New</translation>
+    </message>
+    <message>
+      <source>TTP_NEW</source>
+      <translation>New</translation>
+    </message>
+    <message>
+      <source>DSC_NEW</source>
+      <translation>Create new document</translation>
+    </message>
+    <message>
+      <source>ACT_OPEN</source>
+      <translation>&amp;Open...</translation>
+    </message>
+    <message>
+      <source>TTP_OPEN</source>
+      <translation>Open</translation>
+    </message>
+    <message>
+      <source>DSC_OPEN</source>
+      <translation>Open an existing document</translation>
+    </message>
+    <message>
+      <source>ACT_SAVE</source>
+      <translation>&amp;Save</translation>
+    </message>
+    <message>
+      <source>TTP_SAVE</source>
+      <translation>Save</translation>
+    </message>
+    <message>
+      <source>DSC_SAVE</source>
+      <translation>Save the document to a file</translation>
+    </message>
+    <message>
+      <source>ACT_SAVEAS</source>
+      <translation>Save &amp;As...</translation>
+    </message>
+    <message>
+      <source>TTP_SAVEAS</source>
+      <translation>Save As</translation>
+    </message>
+    <message>
+      <source>DSC_SAVEAS</source>
+      <translation>Save the document to a file with the new name</translation>
+    </message>
+    <message>
+      <source>ACT_UNDO</source>
+      <translation>&amp;Undo</translation>
+    </message>
+    <message>
+      <source>TTP_UNDO</source>
+      <translation>Undo</translation>
+    </message>
+    <message>
+      <source>DSC_UNDO</source>
+      <translation>Undo last operation</translation>
+    </message>
+    <message>
+      <source>ACT_REDO</source>
+      <translation>&amp;Redo</translation>
+    </message>
+    <message>
+      <source>TTP_REDO</source>
+      <translation>Redo</translation>
+    </message>
+    <message>
+      <source>DSC_REDO</source>
+      <translation>Redo last undone operation</translation>
+    </message>
+    <message>
+      <source>ACT_CUT</source>
+      <translation>Cu&amp;t</translation>
+    </message>
+    <message>
+      <source>TTP_CUT</source>
+      <translation>Cut</translation>
+    </message>
+    <message>
+      <source>DSC_CUT</source>
+      <translation>Cut the current selection&apos;s contents to the clipboard</translation>
+    </message>
+    <message>
+      <source>ACT_COPY</source>
+      <translation>&amp;Copy</translation>
+    </message>
+    <message>
+      <source>TTP_COPY</source>
+      <translation>Copy</translation>
+    </message>
+    <message>
+      <source>DSC_COPY</source>
+      <translation>Copy the current selection&apos;s contents to the clipboard</translation>
+    </message>
+    <message>
+      <source>ACT_PASTE</source>
+      <translation>&amp;Paste</translation>
+    </message>
+    <message>
+      <source>TTP_PASTE</source>
+      <translation>Paste</translation>
+    </message>
+    <message>
+      <source>DSC_PASTE</source>
+      <translation>Paste the clipboard&apos;s contents into the current selection</translation>
+    </message>
+    <message>
+      <source>ACT_DELETE</source>
+      <translation>&amp;Delete</translation>
+    </message>
+    <message>
+      <source>TTP_DELETE</source>
+      <translation>Delete</translation>
+    </message>
+    <message>
+      <source>DSC_DELETE</source>
+      <translation>Delete the current selection&apos;s contents</translation>
+    </message>
+    <message>
+      <source>ACT_SELECT_ALL</source>
+      <translation>Select &amp;All</translation>
+    </message>
+    <message>
+      <source>TTP_SELECT_ALL</source>
+      <translation>Select All</translation>
+    </message>
+    <message>
+      <source>DSC_SELECT_ALL</source>
+      <translation>Select all the contents</translation>
+    </message>
+    <message>
+      <source>ACT_PREFERENCES</source>
+      <translation>Pre&amp;ferences</translation>
+    </message>
+    <message>
+      <source>TTP_PREFERENCES</source>
+      <translation>Preferences</translation>
+    </message>
+    <message>
+      <source>DSC_PREFERENCES</source>
+      <translation>Show the Preferences dialog</translation>
+    </message>
+    <message>
+      <source>ACT_HELP</source>
+      <translation>&amp;Help</translation>
+    </message>
+    <message>
+      <source>TTP_HELP</source>
+      <translation>Help</translation>
+    </message>
+    <message>
+      <source>DSC_HELP</source>
+      <translation>Show the help on the Python Editor</translation>
+    </message>
+    <message>
+      <source>TOOLBAR_LABEL</source>
+      <translation>Edit Operations</translation>
+    </message>
+    <message>
+      <source>TIT_PY_FILES</source>
+      <translation>Python files</translation>
+    </message>
+    <message>
+      <source>TIT_DLG_OPEN</source>
+      <translation>Open file</translation>
+    </message>
+    <message>
+      <source>TIT_DLG_SAVE</source>
+      <translation>Save file</translation>
+    </message>
+    <message>
+      <source>WRN_SAVE_FILE</source>
+      <translation>The document has been modified.&lt;br&gt;Do you want to save changes?</translation>
+    </message>
+    <message>
+      <source>WRN_READ_FILE</source>
+      <translation>Cannot read file %1:\n%2.</translation>
+    </message>
+    <message>
+      <source>WRN_WRITE_FILE</source>
+      <translation>Cannot write file %1:\n%2.</translation>
+    </message>
+    <message>
+      <source>NONAME</source>
+      <translation>Noname.py</translation>
+    </message>
+  </context>
+</TS>
diff --git a/src/PyViewer/resources/PyViewer_msg_fr.ts b/src/PyViewer/resources/PyViewer_msg_fr.ts
new file mode 100644 (file)
index 0000000..c0fc973
--- /dev/null
@@ -0,0 +1,206 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="fr">
+  <context>
+      <name>PyViewer_ViewManager</name>
+      <message>
+          <source>PYVIEWER_VIEW_TITLE</source>
+          <translation>Editeur Python:%M - visualiseur:%V</translation>
+      </message>
+  </context>
+  <context>
+    <name>PyViewer_ViewWindow</name>
+    <message>
+      <source>NAME_PYEDITOR</source>
+      <translation>Editeur python</translation>
+    </message>
+    <message>
+      <source>ACT_NEW</source>
+      <translation>Nouveau</translation>
+    </message>
+    <message>
+      <source>TTP_NEW</source>
+      <translation>Nouveau</translation>
+    </message>
+    <message>
+      <source>DSC_NEW</source>
+      <translation>Crée un nouveau fichier python</translation>
+    </message>
+    <message>
+      <source>ACT_OPEN</source>
+      <translation>Ouvrir</translation>
+    </message>
+    <message>
+      <source>TTP_OPEN</source>
+      <translation>Ouvrir</translation>
+    </message>
+    <message>
+      <source>DSC_OPEN</source>
+      <translation>Ouvre un fichier python existant</translation>
+    </message>
+    <message>
+      <source>ACT_SAVE</source>
+      <translation>Enregistrer</translation>
+    </message>
+    <message>
+      <source>TTP_SAVE</source>
+      <translation>Enregistrer</translation>
+    </message>
+    <message>
+      <source>DSC_SAVE</source>
+      <translation>Enregistre le fichier python sur le système de fichiers</translation>
+    </message>
+    <message>
+      <source>ACT_SAVEAS</source>
+      <translation>Enregistrer sous...</translation>
+    </message>
+    <message>
+      <source>TTP_SAVEAS</source>
+      <translation>Enregistrer sous...</translation>
+    </message>
+    <message>
+      <source>DSC_SAVEAS</source>
+      <translation>>Enregistre le fichier python sous un nouveau nom</translation>
+    </message>
+    <message>
+      <source>ACT_UNDO</source>
+      <translation>Annuler</translation>
+    </message>
+    <message>
+      <source>TTP_UNDO</source>
+      <translation>Annuler</translation>
+    </message>
+    <message>
+      <source>DSC_UNDO</source>
+      <translation>Annule la dernière opération</translation>
+    </message>
+    <message>
+      <source>ACT_REDO</source>
+      <translation>Refaire</translation>
+    </message>
+    <message>
+      <source>TTP_REDO</source>
+      <translation>Refaire</translation>
+    </message>
+    <message>
+      <source>DSC_REDO</source>
+      <translation>Répète la dernière opération</translation>
+    </message>
+    <message>
+      <source>ACT_CUT</source>
+      <translation>Coupe</translation>
+    </message>
+    <message>
+      <source>TTP_CUT</source>
+      <translation>Coupe</translation>
+    </message>
+    <message>
+      <source>DSC_CUT</source>
+      <translation>Coupe le contenu de la sélection vers le presse-papier</translation>
+    </message>
+    <message>
+      <source>ACT_COPY</source>
+      <translation>Copier</translation>
+    </message>
+    <message>
+      <source>TTP_COPY</source>
+      <translation>Copier</translation>
+    </message>
+    <message>
+      <source>DSC_COPY</source>
+      <translation>Copie le contenu de la sélection vers le presse-papier</translation>
+    </message>
+    <message>
+      <source>ACT_PASTE</source>
+      <translation>Coller</translation>
+    </message>
+    <message>
+      <source>TTP_PASTE</source>
+      <translation>Coller</translation>
+    </message>
+    <message>
+      <source>DSC_PASTE</source>
+      <translation>Colle le contenu de la sélection vers le presse-papier</translation>
+    </message>
+    <message>
+      <source>ACT_DELETE</source>
+      <translation>Supprime</translation>
+    </message>
+    <message>
+      <source>TTP_DELETE</source>
+      <translation>Supprime</translation>
+    </message>
+    <message>
+      <source>DSC_DELETE</source>
+      <translation>Supprime le contenu de la sélection</translation>
+    </message>
+    <message>
+      <source>ACT_SELECT_ALL</source>
+      <translation>Sélectionner tout</translation>
+    </message>
+    <message>
+      <source>TTP_SELECT_ALL</source>
+      <translation>Sélectionner tout</translation>
+    </message>
+    <message>
+      <source>DSC_SELECT_ALL</source>
+      <translation>Sélectionne tout le contenu</translation>
+    </message>
+    <message>
+      <source>ACT_PREFERENCES</source>
+      <translation>Préférences</translation>
+    </message>
+    <message>
+      <source>TTP_PREFERENCES</source>
+      <translation>Préférences</translation>
+    </message>
+    <message>
+      <source>DSC_PREFERENCES</source>
+      <translation>Affiche la boîte de dialogue des préférences</translation>
+    </message>
+    <message>
+      <source>ACT_HELP</source>
+      <translation>Aide</translation>
+    </message>
+    <message>
+      <source>TTP_HELP</source>
+      <translation>Aide</translation>
+    </message>
+    <message>
+      <source>DSC_HELP</source>
+      <translation>Afficher l'aide</translation>
+    </message>
+    <message>
+      <source>TOOLBAR_LABEL</source>
+      <translation>Opérations d'édition</translation>
+    </message>
+    <message>
+      <source>TIT_PY_FILES</source>
+      <translation>Fichiers Python</translation>
+    </message>
+    <message>
+      <source>TIT_DLG_OPEN</source>
+      <translation>Ouvrir le fichier</translation>
+    </message>
+    <message>
+      <source>TIT_DLG_SAVE</source>
+      <translation>Enregistrer le fichier</translation>
+    </message>
+    <message>
+      <source>WRN_SAVE_FILE</source>
+      <translation>Le document a été modifié.&lt;br&gt;Voulez-vous sauvegarder vos changements?</translation>
+    </message>
+    <message>
+      <source>WRN_READ_FILE</source>
+      <translation>Impossible de lire le fichier %1:\n%2.</translation>
+    </message>
+    <message>
+      <source>WRN_WRITE_FILE</source>
+      <translation>Impossible d'écrire le fichier %1:\n%2.</translation>
+    </message>
+    <message>
+      <source>NONAME</source>
+      <translation>Noname.py</translation>
+    </message>
+  </context>
+</TS>
diff --git a/src/PyViewer/resources/PyViewer_msg_ja.ts b/src/PyViewer/resources/PyViewer_msg_ja.ts
new file mode 100644 (file)
index 0000000..38c7a5a
--- /dev/null
@@ -0,0 +1,206 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="ja" sourcelanguage="en">
+  <context>
+    <name>PyViewer_ViewManager</name>
+    <message>
+      <source>PYVIEWER_VIEW_TITLE</source>
+      <translation>Python viewer:%M - viewer:%V</translation>
+    </message>
+  </context>
+  <context>
+    <name>PyViewer_ViewWindow</name>
+    <message>
+      <source>NAME_PYEDITOR</source>
+      <translation>Python Editor</translation>
+    </message>
+    <message>
+      <source>ACT_NEW</source>
+      <translation>新規</translation>
+    </message>
+    <message>
+      <source>TTP_NEW</source>
+      <translation>新規</translation>
+    </message>
+    <message>
+      <source>DSC_NEW</source>
+      <translation>新規 python ファイルの作成</translation>
+    </message>
+    <message>
+      <source>ACT_OPEN</source>
+      <translation>開く</translation>
+    </message>
+    <message>
+      <source>TTP_OPEN</source>
+      <translation>開く</translation>
+    </message>
+    <message>
+      <source>DSC_OPEN</source>
+      <translation>存在する python ファイルを開く</translation>
+    </message>
+    <message>
+      <source>ACT_SAVE</source>
+      <translation>保存</translation>
+    </message>
+    <message>
+      <source>TTP_SAVE</source>
+      <translation>保存</translation>
+    </message>
+    <message>
+      <source>DSC_SAVE</source>
+      <translation>python ドキュメントをディスクに保存</translation>
+    </message>
+    <message>
+      <source>ACT_SAVEAS</source>
+      <translation>別名保存</translation>
+    </message>
+    <message>
+      <source>TTP_SAVEAS</source>
+      <translation>別名保存</translation>
+    </message>
+    <message>
+      <source>DSC_SAVEAS</source>
+      <translation>新しい名前で python ドキュメントを保存</translation>
+    </message>
+    <message>
+      <source>ACT_UNDO</source>
+      <translation>元に戻す</translation>
+    </message>
+    <message>
+      <source>TTP_UNDO</source>
+      <translation>元に戻す</translation>
+    </message>
+    <message>
+      <source>DSC_UNDO</source>
+      <translation>最後の操作を元に戻す</translation>
+    </message>
+    <message>
+      <source>ACT_REDO</source>
+      <translation>やり直し</translation>
+    </message>
+    <message>
+      <source>TTP_REDO</source>
+      <translation>やり直し</translation>
+    </message>
+    <message>
+      <source>DSC_REDO</source>
+      <translation>最後の操作をやり直す</translation>
+    </message>
+    <message>
+      <source>ACT_CUT</source>
+      <translation>カット</translation>
+    </message>
+    <message>
+      <source>TTP_CUT</source>
+      <translation>カット</translation>
+    </message>
+    <message>
+      <source>DSC_CUT</source>
+      <translation>現在選択中の内容をクリップボードにカット</translation>
+    </message>
+    <message>
+      <source>ACT_COPY</source>
+      <translation>コピー</translation>
+    </message>
+    <message>
+      <source>TTP_COPY</source>
+      <translation>コピー</translation>
+    </message>
+    <message>
+      <source>DSC_COPY</source>
+      <translation>現在選択中の内容をクリップボードにコピー</translation>
+    </message>
+    <message>
+      <source>ACT_PASTE</source>
+      <translation>ペースト</translation>
+    </message>
+    <message>
+      <source>TTP_PASTE</source>
+      <translation>ペースト</translation>
+    </message>
+    <message>
+      <source>DSC_PASTE</source>
+      <translation>クリップボードの内容を現在の選択にペースト</translation>
+    </message>
+    <message>
+      <source>ACT_DELETE</source>
+      <translation>削除</translation>
+    </message>
+    <message>
+      <source>TTP_DELETE</source>
+      <translation>削除</translation>
+    </message>
+    <message>
+      <source>DSC_DELETE</source>
+      <translation>現在選択中の内容を削除</translation>
+    </message>
+    <message>
+      <source>ACT_SELECT_ALL</source>
+      <translation>すべて選択</translation>
+    </message>
+    <message>
+      <source>TTP_SELECT_ALL</source>
+      <translation>すべて選択</translation>
+    </message>
+    <message>
+      <source>DSC_SELECT_ALL</source>
+      <translation>すべての内容を選択</translation>
+    </message>
+    <message>
+      <source>ACT_PREFERENCES</source>
+      <translation>環境設定</translation>
+    </message>
+    <message>
+      <source>TTP_PREFERENCES</source>
+      <translation>環境設定</translation>
+    </message>
+    <message>
+      <source>DSC_PREFERENCES</source>
+      <translation>環境設定ボックスの表示</translation>
+    </message>
+    <message>
+      <source>ACT_HELP</source>
+      <translation>ヘルプ</translation>
+    </message>
+    <message>
+      <source>TTP_HELP</source>
+      <translation>ヘルプ</translation>
+    </message>
+    <message>
+      <source>DSC_HELP</source>
+      <translation>ヘルプ</translation>
+    </message>
+    <message>
+      <source>TOOLBAR_LABEL</source>
+      <translation>操作の編集</translation>
+    </message>
+    <message>
+      <source>TIT_PY_FILES</source>
+      <translation>ã..ã.¡ã.¤ã.« Python</translation>
+    </message>
+    <message>
+      <source>TIT_DLG_OPEN</source>
+      <translation>ファイルを開く</translation>
+    </message>
+    <message>
+      <source>TIT_DLG_SAVE</source>
+      <translation>ファイルを保存</translation>
+    </message>
+    <message>
+      <source>WRN_SAVE_FILE</source>
+      <translation>ドキュメントは修正済みです。&lt;br&gt;変更を保存しますか?</translation>
+    </message>
+    <message>
+      <source>WRN_READ_FILE</source>
+      <translation>Cannot read file %1:\n%2.</translation>
+    </message>
+    <message>
+      <source>WRN_WRITE_FILE</source>
+      <translation>Cannot write file %1:\n%2.</translation>
+    </message>
+    <message>
+      <source>NONAME</source>
+      <translation>Noname.py</translation>
+    </message>
+  </context>
+</TS>
diff --git a/src/PyViewer/resources/images/py_browser.png b/src/PyViewer/resources/images/py_browser.png
deleted file mode 100644 (file)
index 6fb0c81..0000000
Binary files a/src/PyViewer/resources/images/py_browser.png and /dev/null differ
diff --git a/src/PyViewer/resources/images/py_close.png b/src/PyViewer/resources/images/py_close.png
deleted file mode 100644 (file)
index 52efbf0..0000000
Binary files a/src/PyViewer/resources/images/py_close.png and /dev/null differ
diff --git a/src/PyViewer/resources/images/py_copy.png b/src/PyViewer/resources/images/py_copy.png
deleted file mode 100644 (file)
index 385b2c4..0000000
Binary files a/src/PyViewer/resources/images/py_copy.png and /dev/null differ
diff --git a/src/PyViewer/resources/images/py_cut.png b/src/PyViewer/resources/images/py_cut.png
deleted file mode 100644 (file)
index 77edc8a..0000000
Binary files a/src/PyViewer/resources/images/py_cut.png and /dev/null differ
diff --git a/src/PyViewer/resources/images/py_delete.png b/src/PyViewer/resources/images/py_delete.png
deleted file mode 100644 (file)
index 38581d1..0000000
Binary files a/src/PyViewer/resources/images/py_delete.png and /dev/null differ
diff --git a/src/PyViewer/resources/images/py_new.png b/src/PyViewer/resources/images/py_new.png
deleted file mode 100644 (file)
index 2a39dff..0000000
Binary files a/src/PyViewer/resources/images/py_new.png and /dev/null differ
diff --git a/src/PyViewer/resources/images/py_open.png b/src/PyViewer/resources/images/py_open.png
deleted file mode 100644 (file)
index 26e0a2c..0000000
Binary files a/src/PyViewer/resources/images/py_open.png and /dev/null differ
diff --git a/src/PyViewer/resources/images/py_paste.png b/src/PyViewer/resources/images/py_paste.png
deleted file mode 100644 (file)
index 09cae75..0000000
Binary files a/src/PyViewer/resources/images/py_paste.png and /dev/null differ
diff --git a/src/PyViewer/resources/images/py_preferences.png b/src/PyViewer/resources/images/py_preferences.png
deleted file mode 100644 (file)
index f8c4c05..0000000
Binary files a/src/PyViewer/resources/images/py_preferences.png and /dev/null differ
diff --git a/src/PyViewer/resources/images/py_redo.png b/src/PyViewer/resources/images/py_redo.png
deleted file mode 100644 (file)
index 8e685b6..0000000
Binary files a/src/PyViewer/resources/images/py_redo.png and /dev/null differ
diff --git a/src/PyViewer/resources/images/py_save.png b/src/PyViewer/resources/images/py_save.png
deleted file mode 100644 (file)
index 7a70c34..0000000
Binary files a/src/PyViewer/resources/images/py_save.png and /dev/null differ
diff --git a/src/PyViewer/resources/images/py_save_as.png b/src/PyViewer/resources/images/py_save_as.png
deleted file mode 100644 (file)
index 4cb1147..0000000
Binary files a/src/PyViewer/resources/images/py_save_as.png and /dev/null differ
diff --git a/src/PyViewer/resources/images/py_select_all.png b/src/PyViewer/resources/images/py_select_all.png
deleted file mode 100644 (file)
index d7b1c73..0000000
Binary files a/src/PyViewer/resources/images/py_select_all.png and /dev/null differ
diff --git a/src/PyViewer/resources/images/py_undo.png b/src/PyViewer/resources/images/py_undo.png
deleted file mode 100644 (file)
index d6701f5..0000000
Binary files a/src/PyViewer/resources/images/py_undo.png and /dev/null differ
diff --git a/src/PyViewer/resources/translations/PyViewer_msg_en.ts b/src/PyViewer/resources/translations/PyViewer_msg_en.ts
deleted file mode 100644 (file)
index 26a7061..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE TS>
-<TS version="2.0" language="en">
-  <context>
-      <name>PyViewer_ViewManager</name>
-      <message>
-          <source>PYVIEWER_VIEW_TITLE</source>
-          <translation>Python viewer:%M - viewer:%V</translation>
-      </message>
-  </context>
-  <context>
-    <name>PyViewer_ViewWindow</name>
-    <message>
-        <source>NAME_PYEDITOR</source>
-        <translation>Python Viewer</translation>
-    </message>
-    <message>
-        <source>LBL_TOOLBAR_LABEL</source>
-        <translation>Edit Operations</translation>
-    </message>
-    <message>
-        <source>MNU_PY_NEW</source>
-        <translation>New</translation>
-    </message>
-    <message>
-        <source>DSC_PY_NEW</source>
-        <translation>Create a new python file</translation>
-    </message>
-    <message>
-        <source>MNU_PY_OPEN</source>
-        <translation>Open</translation>
-    </message>
-    <message>
-        <source>DSC_PY_OPEN</source>
-        <translation>Open an existing python file</translation>
-    </message>
-    <message>
-        <source>MNU_PY_SAVE</source>
-        <translation>Save</translation>
-    </message>
-    <message>
-        <source>DSC_PY_SAVE</source>
-        <translation>Save the python document to disk</translation>
-    </message>
-    <message>
-        <source>MNU_PY_SAVEAS</source>
-        <translation>Save As...</translation>
-    </message>
-    <message>
-        <source>DSC_PY_SAVEAS</source>
-        <translation>Save the python document under a new name</translation>
-    </message>
-    <message>
-        <source>MNU_PY_CLOSE</source>
-        <translation>Close</translation>
-    </message>
-    <message>
-        <source>DSC_PY_CLOSE</source>
-        <translation>Close the python document</translation>
-    </message>
-    <message>
-        <source>MNU_PY_UNDO</source>
-        <translation>Undo</translation>
-    </message>
-    <message>
-        <source>DSC_PY_UNDO</source>
-        <translation>Undoes the last operation</translation>
-    </message>
-    <message>
-        <source>MNU_PY_REDO</source>
-        <translation>Redo</translation>
-    </message>
-    <message>
-        <source>DSC_PY_REDO</source>
-        <translation>Redoes the last operation</translation>
-    </message>
-    <message>
-        <source>MNU_PY_CUT</source>
-        <translation>Cut</translation>
-    </message>
-    <message>
-        <source>DSC_PY_CUT</source>
-        <translation>Cut the current selection&apos;s contents to the clipboard</translation>
-    </message>
-    <message>
-        <source>MNU_PY_COPY</source>
-        <translation>Copy</translation>
-    </message>
-    <message>
-        <source>DSC_PY_COPY</source>
-        <translation>Copy the current selection&apos;s contents to the clipboard</translation>
-    </message>
-    <message>
-        <source>MNU_PY_PASTE</source>
-        <translation>Paste</translation>
-    </message>
-    <message>
-        <source>DSC_PY_PASTE</source>
-        <translation>Paste the clipboard&apos;s contents into the current selection</translation>
-    </message>
-    <message>
-        <source>MNU_PY_DELETE</source>
-        <translation>Delete</translation>
-    </message>
-    <message>
-        <source>DSC_PY_DELETE</source>
-        <translation>Delete the current selection&apos;s contents</translation>
-    </message>
-    <message>
-        <source>MNU_PY_SELECTALL</source>
-        <translation>Select All</translation>
-    </message>
-    <message>
-        <source>DSC_PY_SELECT_ALL</source>
-        <translation>Select all the contents</translation>
-    </message>
-    <message>
-        <source>MNU_PY_PREFERENCES</source>
-        <translation>Preferences</translation>
-    </message>
-    <message>
-        <source>DSC_PY_PREFERENCES</source>
-        <translation>Show the Preferences box</translation>
-    </message>
-    <message>
-      <source>MNU_PY_BROWSER</source>
-      <translation>Help Browser</translation>
-    </message>
-    <message>
-      <source>DSC_PY_BROWSER</source>
-      <translation>Show the Help browser</translation>
-    </message>
-    <message>
-        <source>WRN_PY_READ_FILE</source>
-        <translation>Cannot read file %1:\n%2.</translation>
-    </message>
-    <message>
-        <source>WRN_PY_WRITE_FILE</source>
-        <translation>Cannot write file %1:\n%2.</translation>
-    </message>
-    <message>
-        <source>WRN_PY_SAVE_FILE</source>
-        <translation>The document has been modified.&lt;br&gt;Do you want to save your changes?</translation>
-    </message>
-    <message>
-        <source>TIT_DLG_SAVE</source>
-        <translation>Save file</translation>
-    </message>
-    <message>
-        <source>TIT_DLG_SAVEAS</source>
-        <translation>Save file as</translation>
-    </message>
-    <message>
-        <source>TIT_DLG_OPEN</source>
-        <translation>Open file</translation>
-    </message>
-    <message>
-      <source>STS_READY</source>
-      <translation>Ready</translation>
-    </message>
-    <message>
-      <source>STS_F_LOADED</source>
-      <translation>File is loaded</translation>
-    </message>
-    <message>
-      <source>STS_F_SAVED</source>
-      <translation>File is saved</translation>
-    </message>
-  </context>
-</TS>
diff --git a/src/PyViewer/resources/translations/PyViewer_msg_fr.ts b/src/PyViewer/resources/translations/PyViewer_msg_fr.ts
deleted file mode 100644 (file)
index 117b517..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE TS>
-<TS version="2.0" language="fr">
-  <context>
-      <name>PyViewer_ViewManager</name>
-      <message>
-          <source>PYVIEWER_VIEW_TITLE</source>
-          <translation>Editeur Python:%M - visualiseur:%V</translation>
-      </message>
-  </context>
-  <context>
-    <name>PyViewer_ViewWindow</name>
-    <message>
-        <source>NAME_PYEDITOR</source>
-        <translation>Editeur python</translation>
-    </message>
-    <message>
-        <source>LBL_TOOLBAR_LABEL</source>
-        <translation>Opérations d'édition</translation>
-    </message>
-    <message>
-        <source>MNU_PY_NEW</source>
-        <translation>Nouveau</translation>
-    </message>
-    <message>
-        <source>DSC_PY_NEW</source>
-        <translation>Crée un nouveau fichier python</translation>
-    </message>
-    <message>
-        <source>MNU_PY_OPEN</source>
-        <translation>Ouvrir</translation>
-    </message>
-    <message>
-        <source>DSC_PY_OPEN</source>
-        <translation>Ouvre un fichier python existant</translation>
-    </message>
-    <message>
-        <source>MNU_PY_SAVE</source>
-        <translation>Enregistrer</translation>
-    </message>
-    <message>
-        <source>DSC_PY_SAVE</source>
-        <translation>Enregistre le fichier python sur le système de fichiers</translation>
-    </message>
-    <message>
-        <source>MNU_PY_SAVEAS</source>
-        <translation>Enregistrer sous...</translation>
-    </message>
-    <message>
-        <source>DSC_PY_SAVEAS</source>
-        <translation>>Enregistre le fichier python sous un nouveau nom</translation>
-    </message>
-    <message>
-        <source>MNU_PY_CLOSE</source>
-        <translation>Fermer</translation>
-    </message>
-    <message>
-        <source>DSC_PY_CLOSE</source>
-        <translation>Ferme le fichier python</translation>
-    </message>
-    <message>
-        <source>MNU_PY_UNDO</source>
-        <translation>Annuler</translation>
-    </message>
-    <message>
-        <source>DSC_PY_UNDO</source>
-        <translation>Annule la dernière opération</translation>
-    </message>
-    <message>
-        <source>MNU_PY_REDO</source>
-        <translation>Refaire</translation>
-    </message>
-    <message>
-        <source>DSC_PY_REDO</source>
-        <translation>Répète la dernière opération</translation>
-    </message>
-    <message>
-        <source>MNU_PY_CUT</source>
-        <translation>Coupe</translation>
-    </message>
-    <message>
-        <source>DSC_PY_CUT</source>
-        <translation>Coupe le contenu de la sélection vers le presse-papier</translation>
-    </message>
-    <message>
-        <source>MNU_PY_COPY</source>
-        <translation>Copier</translation>
-    </message>
-    <message>
-        <source>DSC_PY_COPY</source>
-        <translation>Copie le contenu de la sélection vers le presse-papier</translation>
-    </message>
-    <message>
-        <source>MNU_PY_PASTE</source>
-        <translation>Coller</translation>
-    </message>
-    <message>
-        <source>DSC_PY_PASTE</source>
-        <translation>Colle le contenu de la sélection vers le presse-papier</translation>
-    </message>
-    <message>
-        <source>MNU_PY_DELETE</source>
-        <translation>Supprime</translation>
-    </message>
-    <message>
-        <source>DSC_PY_DELETE</source>
-        <translation>Supprime le contenu de la sélection</translation>
-    </message>
-    <message>
-        <source>MNU_PY_SELECTALL</source>
-        <translation>Sélectionner tout</translation>
-    </message>
-    <message>
-        <source>DSC_PY_SELECT_ALL</source>
-        <translation>Sélectionne tout le contenu</translation>
-    </message>
-    <message>
-        <source>MNU_PY_PREFERENCES</source>
-        <translation>Préférences</translation>
-    </message>
-    <message>
-        <source>DSC_PY_PREFERENCES</source>
-        <translation>Affiche la boîte de dialogue des préférences</translation>
-    </message>
-    <message>
-      <source>MNU_PY_BROWSER</source>
-      <translation>Aide</translation>
-    </message>
-    <message>
-      <source>DSC_PY_BROWSER</source>
-      <translation>Afficher l'aide</translation>
-    </message>
-    <message>
-        <source>WRN_PY_READ_FILE</source>
-        <translation>Impossible de lire le fichier %1:\n%2.</translation>
-    </message>
-    <message>
-        <source>WRN_PY_WRITE_FILE</source>
-        <translation>Impossible d'écrire le fichier %1:\n%2.</translation>
-    </message>
-    <message>
-        <source>WRN_PY_SAVE_FILE</source>
-        <translation>Le document a été modifié.&lt;br&gt;Voulez-vous sauvegarder vos changements?</translation>
-    </message>
-    <message>
-        <source>TIT_DLG_SAVE</source>
-        <translation>Enregistrer le fichier</translation>
-    </message>
-    <message>
-        <source>TIT_DLG_SAVEAS</source>
-        <translation>Enregistrer le fichier sous</translation>
-    </message>
-    <message>
-        <source>TIT_DLG_OPEN</source>
-        <translation>Ouvrir le fichier</translation>
-    </message>
-    <message>
-      <source>STS_READY</source>
-      <translation>Prêt</translation>
-    </message>
-    <message>
-      <source>STS_F_LOADED</source>
-      <translation>Le fichier est chargé</translation>
-    </message>
-    <message>
-      <source>STS_F_SAVED</source>
-      <translation>Le fichier est sauvé</translation>
-    </message>
-  </context>
-</TS>
diff --git a/src/PyViewer/resources/translations/PyViewer_msg_ja.ts b/src/PyViewer/resources/translations/PyViewer_msg_ja.ts
deleted file mode 100644 (file)
index 4747251..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE TS>
-<TS version="2.0" language="ja" sourcelanguage="en">
-  <context>
-    <name>PyViewer_ViewManager</name>
-    <message>
-      <source>PYVIEWER_VIEW_TITLE</source>
-      <translation>Python viewer:%M - viewer:%V</translation>
-    </message>
-  </context>
-  <context>
-    <name>PyViewer_ViewWindow</name>
-    <message>
-      <source>NAME_PYEDITOR</source>
-      <translation>Python Viewer</translation>
-    </message>
-    <message>
-      <source>LBL_TOOLBAR_LABEL</source>
-      <translation>操作の編集</translation>
-    </message>
-    <message>
-      <source>MNU_PY_NEW</source>
-      <translation>新規</translation>
-    </message>
-    <message>
-      <source>DSC_PY_NEW</source>
-      <translation>新規 python ファイルの作成</translation>
-    </message>
-    <message>
-      <source>MNU_PY_OPEN</source>
-      <translation>開く</translation>
-    </message>
-    <message>
-      <source>DSC_PY_OPEN</source>
-      <translation>存在する python ファイルを開く</translation>
-    </message>
-    <message>
-      <source>MNU_PY_SAVE</source>
-      <translation>保存</translation>
-    </message>
-    <message>
-      <source>DSC_PY_SAVE</source>
-      <translation>python ドキュメントをディスクに保存</translation>
-    </message>
-    <message>
-      <source>MNU_PY_SAVEAS</source>
-      <translation>別名保存</translation>
-    </message>
-    <message>
-      <source>DSC_PY_SAVEAS</source>
-      <translation>新しい名前で python ドキュメントを保存</translation>
-    </message>
-    <message>
-      <source>MNU_PY_CLOSE</source>
-      <translation>閉じる</translation>
-    </message>
-    <message>
-      <source>DSC_PY_CLOSE</source>
-      <translation>python ドキュメントを閉じる</translation>
-    </message>
-    <message>
-      <source>MNU_PY_UNDO</source>
-      <translation>元に戻す</translation>
-    </message>
-    <message>
-      <source>DSC_PY_UNDO</source>
-      <translation>最後の操作を元に戻す</translation>
-    </message>
-    <message>
-      <source>MNU_PY_REDO</source>
-      <translation>やり直し</translation>
-    </message>
-    <message>
-      <source>DSC_PY_REDO</source>
-      <translation>最後の操作をやり直す</translation>
-    </message>
-    <message>
-      <source>MNU_PY_CUT</source>
-      <translation>カット</translation>
-    </message>
-    <message>
-      <source>DSC_PY_CUT</source>
-      <translation>現在選択中の内容をクリップボードにカット</translation>
-    </message>
-    <message>
-      <source>MNU_PY_COPY</source>
-      <translation>コピー</translation>
-    </message>
-    <message>
-      <source>DSC_PY_COPY</source>
-      <translation>現在選択中の内容をクリップボードにコピー</translation>
-    </message>
-    <message>
-      <source>MNU_PY_PASTE</source>
-      <translation>ペースト</translation>
-    </message>
-    <message>
-      <source>DSC_PY_PASTE</source>
-      <translation>クリップボードの内容を現在の選択にペースト</translation>
-    </message>
-    <message>
-      <source>MNU_PY_DELETE</source>
-      <translation>削除</translation>
-    </message>
-    <message>
-      <source>DSC_PY_DELETE</source>
-      <translation>現在選択中の内容を削除</translation>
-    </message>
-    <message>
-      <source>MNU_PY_SELECTALL</source>
-      <translation>すべて選択</translation>
-    </message>
-    <message>
-      <source>DSC_PY_SELECT_ALL</source>
-      <translation>すべての内容を選択</translation>
-    </message>
-    <message>
-      <source>MNU_PY_PREFERENCES</source>
-      <translation>環境設定</translation>
-    </message>
-    <message>
-      <source>DSC_PY_PREFERENCES</source>
-      <translation>環境設定ボックスの表示</translation>
-    </message>
-    <message>
-      <source>MNU_PY_BROWSER</source>
-      <translation>ヘルプブラウザ</translation>
-    </message>
-    <message>
-      <source>DSC_PY_BROWSER</source>
-      <translation>ヘルプブラウザの表示</translation>
-    </message>
-    <message>
-      <source>WRN_PY_READ_FILE</source>
-      <translation>Cannot read file %1:\n%2.</translation>
-    </message>
-    <message>
-      <source>WRN_PY_WRITE_FILE</source>
-      <translation>Cannot write file %1:\n%2.</translation>
-    </message>
-    <message>
-      <source>WRN_PY_SAVE_FILE</source>
-      <translation>ドキュメントは修正済みです。&lt;br&gt;変更を保存しますか?</translation>
-    </message>
-    <message>
-      <source>TIT_DLG_SAVE</source>
-      <translation>ファイルを保存</translation>
-    </message>
-    <message>
-      <source>TIT_DLG_SAVEAS</source>
-      <translation>別名でファイルを保存</translation>
-    </message>
-    <message>
-      <source>TIT_DLG_OPEN</source>
-      <translation>ファイルを開く</translation>
-    </message>
-    <message>
-      <source>STS_READY</source>
-      <translation>準備</translation>
-    </message>
-    <message>
-      <source>STS_F_LOADED</source>
-      <translation>ファイルは読み込まれました</translation>
-    </message>
-    <message>
-      <source>STS_F_SAVED</source>
-      <translation>ファイルは保存されました</translation>
-    </message>
-  </context>
-</TS>
index 8013abd2d2d6d5d2957f2a6962c9b5a7c4ee7088..8d608b708b54ac1db9d729aabaede724bc55d5ae 100755 (executable)
@@ -26,14 +26,26 @@ ENDIF()
 ##
 # Python-based packages, part 1 (generic)
 ##
+
 IF(SALOME_USE_PYCONSOLE)
   # Include sub-project PyConsole:
   SET(TOOLS_EXPORT_NAME ${PROJECT_NAME})
   SET(PYCONSOLE_INSTALL_LIBS "${SALOME_INSTALL_LIBS}" CACHE PATH "")
   SET(PYCONSOLE_INSTALL_HEADERS "${SALOME_INSTALL_HEADERS}" CACHE PATH "") 
   SET(PYCONSOLE_INSTALL_RES "${SALOME_GUI_INSTALL_RES_DATA}" CACHE PATH "")
-  OPTION(PYCONSOLE_BUILD_WITH_QT5 "Build PYCONSOLE with Qt 5" ${SALOME_BUILD_WITH_QT5})
+  OPTION(PYCONSOLE_BUILD_WITH_QT5 "Build PyConsole with Qt 5" ${SALOME_BUILD_WITH_QT5})
      
   ADD_SUBDIRECTORY(../tools/PyConsole) # will bring in PyInterp automatically
 ENDIF(SALOME_USE_PYCONSOLE)
 
+IF(SALOME_USE_PYVIEWER)
+  # Include sub-project PyEditor:
+  SET(TOOLS_EXPORT_NAME ${PROJECT_NAME})
+  SET(PYEDITOR_INSTALL_BINS "${SALOME_INSTALL_BINS}" CACHE PATH "")
+  SET(PYEDITOR_INSTALL_LIBS "${SALOME_INSTALL_LIBS}" CACHE PATH "")
+  SET(PYEDITOR_INSTALL_HEADERS "${SALOME_INSTALL_HEADERS}" CACHE PATH "") 
+  SET(PYEDITOR_INSTALL_RES "${SALOME_GUI_INSTALL_RES_DATA}" CACHE PATH "")
+  OPTION(PYEDITOR_BUILD_WITH_QT5 "Build PyEditor with Qt 5" ${SALOME_BUILD_WITH_QT5})
+  ADD_SUBDIRECTORY(PyEditor)
+ENDIF(SALOME_USE_PYVIEWER)
+
diff --git a/tools/PyEditor/CMakeLists.txt b/tools/PyEditor/CMakeLists.txt
new file mode 100644 (file)
index 0000000..3a7f378
--- /dev/null
@@ -0,0 +1,104 @@
+# Copyright (C) 2015-2016  CEA/DEN, EDF R&D
+#
+# 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
+#
+
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12 FATAL_ERROR)
+PROJECT(PyEditor C CXX)
+
+# Versioning
+# ===========
+# Project name, upper case
+STRING(TOUPPER ${PROJECT_NAME} PROJECT_NAME_UC)
+
+# To be changed once externalized CMake procedure:
+###################
+SET(KERNEL_ROOT_DIR $ENV{KERNEL_ROOT_DIR} CACHE PATH "Path to the Salome KERNEL")
+IF(EXISTS ${KERNEL_ROOT_DIR})
+  LIST(APPEND CMAKE_MODULE_PATH "${KERNEL_ROOT_DIR}/salome_adm/cmake_files")
+  INCLUDE(SalomeMacros)
+ELSE(EXISTS ${KERNEL_ROOT_DIR})
+  MESSAGE(FATAL_ERROR "We absolutely need a Salome KERNEL, please define KERNEL_ROOT_DIR")
+ENDIF(EXISTS ${KERNEL_ROOT_DIR})
+# From GUI - again to be changed once externalized:
+LIST(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/../../adm_local/cmake_files")
+###################
+
+# Platform setup
+# ==============
+INCLUDE(SalomeSetupPlatform)
+
+# Options
+# =======
+OPTION(PYEDITOR_BUILD_WITH_QT5 "Build PyEditor with Qt 5" ON)
+OPTION(PYEDITOR_BUILD_SHARED_LIBS "Build shared libraries for PyEditor" ON)
+OPTION(PYEDITOR_BUILD_EXE "Build PyEditor's executable" ON)
+OPTION(PYEDITOR_BUILD_PYTHON "Build Python wrapping for PyEditor" ON)
+
+#
+# Set list of prerequisites
+# =========================
+
+IF(PYEDITOR_BUILD_SHARED_LIBS)
+  SET(BUILD_SHARED_LIBS TRUE)
+ELSE(PYEDITOR_BUILD_SHARED_LIBS)
+  SET(BUILD_SHARED_LIBS FALSE)
+ENDIF(PYEDITOR_BUILD_SHARED_LIBS)
+
+# Qt
+IF(NOT PYEDITOR_BUILD_WITH_QT5)
+  FIND_PACKAGE(SalomeQt4 REQUIRED)
+ELSE()
+  FIND_PACKAGE(SalomeQt5 REQUIRED)
+ENDIF()
+
+IF(PYEDITOR_BUILD_PYTHON)
+  # Python
+  FIND_PACKAGE(SalomePythonInterp REQUIRED)
+  FIND_PACKAGE(SalomePythonLibs REQUIRED)
+  SALOME_LOG_OPTIONAL_PACKAGE(SalomePythonInterp PYEDITOR_BUILD_PYTHON)
+  SALOME_LOG_OPTIONAL_PACKAGE(SalomePythonLibs PYEDITOR_BUILD_PYTHON)
+  # Sip
+  FIND_PACKAGE(SalomeSIP REQUIRED)  # should come after Python and before PyQt
+  SALOME_LOG_OPTIONAL_PACKAGE(SalomeSIP PYEDITOR_BUILD_PYTHON)
+  # PyQt
+  IF (NOT PYEDITOR_BUILD_WITH_QT5)
+    FIND_PACKAGE(SalomePyQt4 REQUIRED)
+    SALOME_LOG_OPTIONAL_PACKAGE(SalomePyQt4 PYEDITOR_BUILD_PYTHON)
+  ELSE()
+    FIND_PACKAGE(SalomePyQt5 REQUIRED)
+    SALOME_LOG_OPTIONAL_PACKAGE(SalomePyQt5 PYEDITOR_BUILD_PYTHON)
+  ENDIF()
+ENDIF(PYEDITOR_BUILD_PYTHON)
+
+# Detection report
+SALOME_PACKAGE_REPORT_AND_CHECK()
+
+# Directories
+#
+# Directories have to be given after prerequisites (to be able to use
+# Python version string for example).
+# ===========
+SET(PYEDITOR_INSTALL_BINS bin CACHE PATH "Install path: PyEditor binaries")
+SET(PYEDITOR_INSTALL_LIBS lib CACHE PATH "Install path: PyEditor libraries")
+SET(PYEDITOR_INSTALL_HEADERS include CACHE PATH "Install path: PyEditor headers")
+SET(PYEDITOR_INSTALL_RES share/resources CACHE PATH "Install path: PyEditor resources")
+
+# Sources
+# ========
+ADD_SUBDIRECTORY(src)
+
diff --git a/tools/PyEditor/src/CMakeLists.txt b/tools/PyEditor/src/CMakeLists.txt
new file mode 100644 (file)
index 0000000..b8e10e4
--- /dev/null
@@ -0,0 +1,113 @@
+# Copyright (C) 2015-2016  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 : Maxim GLIBIN, Open CASCADE S.A.S. (maxim.glibin@opencascade.com)
+#
+
+INCLUDE(UseQtExt)
+
+IF(PYEDITOR_BUILD_PYTHON)
+  ADD_SUBDIRECTORY(python)
+ENDIF(PYEDITOR_BUILD_PYTHON)
+
+# --- options ---
+
+# additional include directories
+INCLUDE_DIRECTORIES(
+  ${QT_INCLUDES}
+)
+
+# additional preprocessor / compiler flags
+ADD_DEFINITIONS(${QT_DEFINITIONS})
+
+# libraries to link to
+SET(_link_LIBRARIES ${PLATFORM_LIBS} ${QT_LIBRARIES})
+
+# --- headers ---
+
+# header files / to be processed by moc
+SET(_moc_HEADERS
+  PyEditor_Editor.h
+  PyEditor_LineNumberArea.h
+  PyEditor_PyHighlighter.h
+  PyEditor_SettingsDlg.h
+  PyEditor_Window.h
+)
+
+# header files / no moc processing
+SET(_other_HEADERS
+  PyEditor.h
+  PyEditor_Settings.h
+  PyEditor_StdSettings.h
+)
+
+# header files / to install
+SET(PyEditor_HEADERS ${_moc_HEADERS} ${_other_HEADERS})
+
+# --- resources ---
+
+# resource files / to be processed by lrelease
+SET(_ts_RESOURCES
+  resources/translations/PyEditor_msg_en.ts
+  resources/translations/PyEditor_msg_fr.ts
+  resources/translations/PyEditor_msg_ja.ts
+)
+
+# resource files / to be processed by rcc
+SET(_rcc_RESOURCES resources/PyEditor.qrc)
+
+# --- sources ---
+
+# sources / moc wrappings
+QT_WRAP_MOC(_moc_SOURCES ${_moc_HEADERS})
+
+# sources / rcc wrappings
+QT_ADD_RESOURCES(_rcc_SOURCES ${_rcc_RESOURCES})
+
+# sources / static
+SET(_other_SOURCES
+  PyEditor_Editor.cxx
+  PyEditor_LineNumberArea.cxx
+  PyEditor_PyHighlighter.cxx
+  PyEditor_Settings.cxx
+  PyEditor_SettingsDlg.cxx
+  PyEditor_StdSettings.cxx
+  PyEditor_Window.cxx
+)
+
+# sources / to compile
+# - for library
+SET(PyEditor_SOURCES ${_other_SOURCES} ${_moc_SOURCES} ${_rcc_SOURCES})
+# - for executable
+SET(pyeditorexe_SOURCES ${PyEditor_SOURCES} PyEditor.cxx)
+
+# --- rules ---
+
+ADD_LIBRARY(PyEditor ${PyEditor_SOURCES})
+TARGET_LINK_LIBRARIES(PyEditor ${_link_LIBRARIES})
+INSTALL(TARGETS PyEditor EXPORT ${TOOLS_EXPORT_NAME}TargetGroup DESTINATION ${PYEDITOR_INSTALL_LIBS})
+
+IF(PYEDITOR_BUILD_EXE)
+  ADD_EXECUTABLE(pyeditorexe ${pyeditorexe_SOURCES})
+  SET_TARGET_PROPERTIES(pyeditorexe PROPERTIES OUTPUT_NAME "pyeditor")
+  TARGET_LINK_LIBRARIES(pyeditorexe ${_link_LIBRARIES})
+  INSTALL(TARGETS pyeditorexe EXPORT ${TOOLS_EXPORT_NAME}TargetGroup DESTINATION ${PYEDITOR_INSTALL_BINS})
+ENDIF(PYEDITOR_BUILD_EXE)
+
+INSTALL(FILES ${PyEditor_HEADERS} DESTINATION ${PYEDITOR_INSTALL_HEADERS})
+QT_INSTALL_TS_RESOURCES("${_ts_RESOURCES}" "${PYEDITOR_INSTALL_RES}")
diff --git a/tools/PyEditor/src/PyEditor.cxx b/tools/PyEditor/src/PyEditor.cxx
new file mode 100644 (file)
index 0000000..03a29b8
--- /dev/null
@@ -0,0 +1,109 @@
+// Copyright (C) 2015-2016  OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File   : PyEditor.cxx
+// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
+//
+
+#include "PyEditor_Window.h"
+#include "PyEditor_StdSettings.h"
+
+#include <QApplication>
+#include <QDir>
+#include <QLibraryInfo>
+#include <QLocale>
+#include <QStringList>
+#include <QTranslator>
+
+QString qtTrDir()
+{
+  const char* vars[] = { "QT5_ROOT_DIR", "QT_ROOT_DIR", "QTDIR" };
+  QString qtPath;
+  for ( uint i = 0; i < sizeof( vars ) / sizeof( vars[0] ) && qtPath.isEmpty(); i++ )
+    qtPath = qgetenv( vars[i] );
+  if ( !qtPath.isEmpty() )
+    qtPath = QDir( qtPath ).absoluteFilePath( "translations" );
+  return qtPath;
+}
+
+QString resourceDir()
+{
+  // Try standalone application's dir.
+  QDir appDir = QApplication::applicationDirPath();
+  appDir.cdUp();
+  QFileInfo resFile( appDir.filePath( "share/resources/PyEditor_msg_en.qm" ) );
+  if ( resFile.exists() )
+    return resFile.absolutePath();
+
+  // Try salome dir.
+  appDir = QApplication::applicationDirPath();
+  appDir.cdUp(); appDir.cdUp();
+  resFile.setFile( appDir.filePath( "share/salome/resources/gui/PyEditor_msg_en.qm" ) );
+  if ( resFile.exists() )
+    return resFile.absolutePath();
+
+  return QString();
+}
+
+int main( int argc, char *argv[] )
+{
+  QApplication app( argc, argv );
+  app.setOrganizationName( "salome" );
+  app.setOrganizationDomain( "www.salome-platform.org" );
+  app.setApplicationName( "pyeditor" );
+  
+  PyEditor_StdSettings* settings = new PyEditor_StdSettings();
+  PyEditor_Settings::setSettings( settings );
+  
+  QString language = settings->language();
+  
+  // Load Qt translations.
+  QString qtDirTrSet = QLibraryInfo::location( QLibraryInfo::TranslationsPath );
+  QString qtDirTrEnv = qtTrDir();
+  
+  QStringList qtTrFiles;
+  qtTrFiles << "qt" << "qtbase";
+  QStringList qtTrDirs;
+  qtTrDirs << QLibraryInfo::location( QLibraryInfo::TranslationsPath );
+  qtTrDirs << qtTrDir();
+  
+  foreach( QString qtTrFile, qtTrFiles ) {
+    foreach ( QString qtTrDir, qtTrDirs ) {
+      QTranslator* translator = new QTranslator;
+      if ( translator->load( QString("%1_%2").arg( qtTrFile ).arg( language ), qtTrDir ) ) {
+        app.installTranslator( translator );
+        break;
+      }
+      else {
+        delete translator;
+      }
+    }
+  }
+  
+  // Load application's translations.
+  QTranslator translator;
+  if ( translator.load( QString( "PyEditor_msg_%1" ).arg( language ), resourceDir() ) )
+    app.installTranslator( &translator );
+  
+  PyEditor_Window window;
+  window.setWindowIcon( QIcon( ":/images/py_editor.png" ) );
+  window.resize( 650, 700 );
+  window.show();
+  
+  return app.exec();
+}
diff --git a/tools/PyEditor/src/PyEditor.h b/tools/PyEditor/src/PyEditor.h
new file mode 100644 (file)
index 0000000..165f53a
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright (C) 2015-2016  OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File   : PyEditor.h
+// Author : Maxim GLIBIN, Open CASCADE S.A.S. (maxim.glibin@opencascade.com)
+//
+
+#ifdef WIN32
+
+#if defined PYEDITOR_EXPORTS || defined PyEditor_EXPORTS
+#define PYEDITOR_EXPORT __declspec(dllexport)
+#else
+#define PYEDITOR_EXPORT __declspec(dllimport)
+#endif
+
+#else
+#define PYEDITOR_EXPORT
+#endif // WIN32
diff --git a/tools/PyEditor/src/PyEditor_Editor.cxx b/tools/PyEditor/src/PyEditor_Editor.cxx
new file mode 100644 (file)
index 0000000..fff2e04
--- /dev/null
@@ -0,0 +1,826 @@
+// Copyright (C) 2015-2016  OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File   : PyEditor_Editor.cxx
+// Author : Maxim GLIBIN, Open CASCADE S.A.S. (maxim.glibin@opencascade.com)
+//
+
+#include "PyEditor_Editor.h"
+#include "PyEditor_LineNumberArea.h"
+#include "PyEditor_PyHighlighter.h"
+#include "PyEditor_Settings.h"
+
+#include <QPainter>
+#include <QTextBlock>
+
+/*!
+  \class PyEditor_Editor
+  \brief Widget to show / edit Python scripts.
+*/
+
+/*!
+  \brief Constructor.
+  \param parent parent widget
+*/
+PyEditor_Editor::PyEditor_Editor( QWidget* parent )
+  : QPlainTextEdit( parent )
+{
+  // Set up line number area
+  myLineNumberArea = new PyEditor_LineNumberArea( this );
+  myLineNumberArea->setMouseTracking( true );
+
+  // Set up syntax highighter
+  mySyntaxHighlighter = new PyEditor_PyHighlighter( this->document() );
+
+  // Set-up settings
+  PyEditor_Settings* settings = PyEditor_Settings::settings();
+  if ( settings )
+    setSettings( *settings );
+
+  // Connect signals
+  connect( this, SIGNAL( blockCountChanged( int ) ), this, SLOT( updateLineNumberAreaWidth( int ) ) );
+  connect( this, SIGNAL( updateRequest( QRect, int ) ), this, SLOT( updateLineNumberArea( QRect, int ) ) );
+  connect( this, SIGNAL( cursorPositionChanged() ), this, SLOT( updateHighlightCurrentLine() ) );
+  connect( this, SIGNAL( cursorPositionChanged() ), this, SLOT( matchParentheses() ) );
+}
+
+/*!
+  \brief Destructor.
+*/
+PyEditor_Editor::~PyEditor_Editor()
+{
+}
+
+/*!
+  \brief Get editor settings.
+  \return settings object
+*/
+const PyEditor_Settings& PyEditor_Editor::settings() const
+{
+  return mySettings;
+}
+
+/*!
+  \brief Set editor settings.
+  \param settings new settings
+*/
+void PyEditor_Editor::setSettings( const PyEditor_Settings& settings )
+{
+  mySettings.copyFrom( settings );
+
+  // Set font size
+  QFont aFont = font();
+  aFont.setFamily( mySettings.font().family() );
+  aFont.setPointSize( mySettings.font().pointSize() );
+  setFont( aFont );
+
+  // Set line wrap mode
+  setLineWrapMode( mySettings.textWrapping() ? QPlainTextEdit::WidgetWidth : QPlainTextEdit::NoWrap );
+
+  // Center the cursor on screen
+  setCenterOnScroll( mySettings.centerCursorOnScroll() );
+
+  // Set size white spaces
+  setTabStopWidth( mySettings.tabSize() * 10 );
+
+  // Update current line highlight
+  updateHighlightCurrentLine();
+
+  // Update line numbers area
+  updateLineNumberAreaWidth( 0 );
+
+  mySyntaxHighlighter->rehighlight();
+  viewport()->update();
+}
+
+/*!
+  Delete current selection contents.
+*/
+void PyEditor_Editor::deleteSelected()
+{
+  QTextCursor aCursor = textCursor();
+  if ( aCursor.hasSelection() )
+    aCursor.removeSelectedText();
+  setTextCursor( aCursor );
+}
+
+/*!
+  \brief Process key press event.
+  Reimplemented from QPlainTextEdit.
+  \param event key press event
+*/
+void PyEditor_Editor::keyPressEvent( QKeyEvent* event )
+{
+  if ( event->type() == QEvent::KeyPress )
+  {
+    int aKey = event->key();
+    Qt::KeyboardModifiers aCtrl = event->modifiers() & Qt::ControlModifier;
+    Qt::KeyboardModifiers aShift = event->modifiers() & Qt::ShiftModifier;
+    
+    if ( aKey == Qt::Key_Tab || ( aKey == Qt::Key_Backtab || ( aKey == Qt::Key_Tab && aShift ) ) )
+    {
+      QTextCursor aCursor = textCursor();
+      aCursor.beginEditBlock();
+      tabIndentation( aKey == Qt::Key_Backtab );
+      aCursor.endEditBlock();
+      event->accept();
+    }
+    else if ( aKey == Qt::Key_Enter || aKey == Qt::Key_Return )
+    {
+      QTextCursor aCursor = textCursor();
+      aCursor.beginEditBlock();
+      if ( lineIndent() == 0 )
+      {
+        QPlainTextEdit::keyPressEvent( event );
+      }
+      aCursor.endEditBlock();
+      event->accept();
+    }
+    else if ( event == QKeySequence::MoveToStartOfLine || event == QKeySequence::SelectStartOfLine )
+    {
+      QTextCursor aCursor = this->textCursor();
+      if ( QTextLayout* aLayout = aCursor.block().layout() )
+      {
+        if ( aLayout->lineForTextPosition( aCursor.position() - aCursor.block().position() ).lineNumber() == 0 )
+        {
+          handleHome( event == QKeySequence::SelectStartOfLine );
+        }
+      }
+    }
+    else if ( ( aKey == Qt::Key_Colon || ( aKey == Qt::Key_Space && !aCtrl && !aShift ) ) &&
+              !textCursor().hasSelection() )
+    {
+      QTextCursor aCursor = textCursor();
+      aCursor.movePosition( QTextCursor::StartOfBlock, QTextCursor::KeepAnchor );
+      
+      QString aSelectedText = aCursor.selectedText();
+      int numSpaces = findFirstNonSpace( aSelectedText );
+      int amountChars = aSelectedText.size() - findFirstNonSpace( aSelectedText );
+      QString aLeadingText = aSelectedText.right( amountChars );
+      
+      QStringList aReservedWords;
+      aReservedWords.append( "except" );
+      if ( aKey == Qt::Key_Colon )
+      {
+        aReservedWords.append( "else" );
+        aReservedWords.append( "finally" );
+      }
+      else if ( aKey == Qt::Key_Space )
+      {
+        aReservedWords.append( "elif" );
+      }
+      
+      if ( aReservedWords.contains( aLeadingText ) )
+      {
+        QString aPreviousText = aCursor.block().previous().text();
+        int numSpacesPrevious = findFirstNonSpace( aPreviousText );
+        if ( numSpaces == numSpacesPrevious )
+        {
+          tabIndentation( true );
+          aCursor.movePosition( QTextCursor::EndOfBlock );
+          setTextCursor( aCursor );
+        }
+      }
+      QPlainTextEdit::keyPressEvent( event );
+    }
+    else
+    {
+      QPlainTextEdit::keyPressEvent( event );
+    }
+  }
+}
+
+/*!
+  \brief Handle resize event.
+  Reimplemented from QPlainTextEdit.
+  \param event resize event
+*/
+void PyEditor_Editor::resizeEvent( QResizeEvent* event )
+{
+  QPlainTextEdit::resizeEvent( event );
+
+  // Change size geometry of line number area
+  QRect aContentsRect = contentsRect();
+  myLineNumberArea->setGeometry( QRect( aContentsRect.left(),
+                                        aContentsRect.top(),
+                                        lineNumberAreaWidth(),
+                                        aContentsRect.height() ) );
+}
+
+/*!
+  \brief Paint event.
+  Reimplemented from QPlainTextEdit.
+  \param event paint event
+*/
+void PyEditor_Editor::paintEvent( QPaintEvent* event )
+{
+  QPlainTextEdit::paintEvent( event );
+
+  QTextBlock aBlock( firstVisibleBlock() );
+  QPointF anOffset( contentOffset() );
+  QPainter aPainter( this->viewport() );
+
+  int aTabSpaces = this->tabStopWidth() / 10;
+
+  // Visualization tab spaces
+  if ( mySettings.tabSpaceVisible() )
+  {
+    qreal aTop = blockBoundingGeometry( aBlock ).translated( anOffset ).top();
+    while ( aBlock.isValid() && aTop <= event->rect().bottom() )
+    {
+      if ( aBlock.isVisible() && blockBoundingGeometry( aBlock ).translated( anOffset ).toRect().intersects( event->rect() ) )
+      {
+        QString aText = aBlock.text();
+        if ( aText.contains( QRegExp( "\\w+" ) ) )
+          aText.remove( QRegExp( "(?!\\w+)\\s+$" ) );
+        
+        int aColumn = 0;
+        int anIndex = 0;
+        while ( anIndex != -1 )
+        {
+          anIndex = aText.indexOf( QRegExp( QString( "^\\s{%1}" ).arg( aTabSpaces ) ), 0 );
+          if ( anIndex != -1 )
+          {
+            aColumn = aColumn + aTabSpaces;
+            aText = aText.mid( aTabSpaces );
+    
+            if ( aText.startsWith( ' ' ) )
+            {
+              QTextCursor aCursor( aBlock );
+              aCursor.setPosition( aBlock.position() + aColumn );
+      
+              QRect aRect = cursorRect( aCursor );
+              aPainter.setPen( QPen( Qt::darkGray, 1, Qt::DotLine ) );
+              aPainter.drawLine( aRect.x() + 1, aRect.top(), aRect.x() + 1, aRect.bottom() );
+            }
+          }
+        }
+      }
+      aBlock = aBlock.next();
+    }
+  }
+  
+  // Vertical edge line
+  if ( mySettings.verticalEdge() )
+  {
+    const QRect aRect = event->rect();
+    const QFont aFont = currentCharFormat().font();
+    int aNumberColumn =  QFontMetrics( aFont ).averageCharWidth() * mySettings.numberColumns() + anOffset.x() + document()->documentMargin();
+    aPainter.setPen( QPen( Qt::lightGray, 1, Qt::SolidLine ) );
+    aPainter.drawLine( aNumberColumn, aRect.top(), aNumberColumn, aRect.bottom() );
+  }
+}
+
+/*!
+  \brief Indent and tab text.
+  \param isShift flag defines reverse tab direction
+*/
+void PyEditor_Editor::tabIndentation( bool isShift )
+{
+  QTextCursor aCursor = textCursor();
+  int aTabSpaces = this->tabStopWidth()/10;
+
+  if ( !aCursor.hasSelection() )
+  {
+    if ( !isShift )
+    {
+      int N = aCursor.columnNumber() % aTabSpaces;
+      aCursor.insertText( QString( aTabSpaces - N, QLatin1Char( ' ' ) ) );
+    }
+    else
+    {
+      QTextBlock aCurrentBlock = document()->findBlock( aCursor.position() );
+      int anIndentPos = findFirstNonSpace( aCurrentBlock.text() );
+      aCursor.setPosition( aCurrentBlock.position() + anIndentPos );
+      setTextCursor( aCursor );
+      
+      //if ( aCurrCursorColumnPos <= anIndentPos )
+      //{
+      int aColumnPos = aCursor.columnNumber();
+      if ( aColumnPos != 0 )
+      {
+        int N = aCursor.columnNumber() % aTabSpaces;
+        if ( N == 0 ) N = aTabSpaces;
+        aCursor.movePosition( QTextCursor::Left, QTextCursor::KeepAnchor, N );
+        aCursor.removeSelectedText();
+      }
+      setTextCursor( aCursor );
+      //}
+    }
+  }
+  else
+  {
+    indentSelection( isShift );
+  }
+}
+
+/*!
+  \brief Indent and tab selected text.
+  \param isShift flag defines reverse tab direction
+*/
+void PyEditor_Editor::indentSelection( bool isShift )
+{
+  QTextCursor aCursor = this->textCursor();
+
+  int aCursorStart = aCursor.selectionStart();
+  int aCursorEnd = aCursor.selectionEnd();
+
+  QTextBlock aStartBlock = document()->findBlock( aCursorStart );
+  QTextBlock anEndBlock = document()->findBlock( aCursorEnd - 1 ).next();
+
+  int aTabSpaces = this->tabStopWidth()/10;
+
+  for ( QTextBlock aBlock = aStartBlock; aBlock.isValid() && aBlock != anEndBlock; aBlock = aBlock.next() )
+  {
+    QString aText = aBlock.text();
+    int anIndentPos = findFirstNonSpace( aText );
+    int N = ( anIndentPos % aTabSpaces );
+    
+    aCursor.setPosition( aBlock.position() + anIndentPos );
+    if ( !isShift )
+    {
+      aCursor.insertText( QString( aTabSpaces - N, QLatin1Char( ' ' ) ) );
+      setTextCursor( aCursor );
+    }
+    else
+    {
+      int aColumnPos = aCursor.columnNumber();
+      if ( aColumnPos != 0 )
+      {
+        int blockN = aColumnPos % aTabSpaces;
+        if ( blockN == 0 ) blockN = aTabSpaces;
+        aCursor.movePosition( QTextCursor::Left, QTextCursor::KeepAnchor, blockN );
+        aCursor.removeSelectedText();
+        setTextCursor( aCursor );
+      }
+    }
+  }
+
+  // Reselect the selected lines
+  aCursor.setPosition( aStartBlock.position() );
+  aCursor.setPosition( anEndBlock.previous().position(), QTextCursor::KeepAnchor );
+  aCursor.movePosition( QTextCursor::EndOfBlock, QTextCursor::KeepAnchor );
+  setTextCursor( aCursor );
+}
+
+/*!
+  \brief Find first non white-space symbol in text.
+  \param text input text
+  \return index of first non white-space symbol
+*/
+int PyEditor_Editor::findFirstNonSpace( const QString& text )
+{
+  int i = 0;
+  while ( i < text.size() )
+  {
+    if ( !text.at(i).isSpace() )
+      return i;
+    ++i;
+  }
+  return i;
+}
+
+/*!
+  \brief Indent line.
+  \return error code
+*/
+int PyEditor_Editor::lineIndent()
+{
+  int aTabSpaces = this->tabStopWidth() / 10;
+
+  QTextCursor aCursor = textCursor();
+  aCursor.insertBlock();
+  setTextCursor( aCursor );
+
+  QTextBlock aCurrentBlock = aCursor.block();
+  if ( aCurrentBlock == document()->begin() )
+    return 0;
+
+  QTextBlock aPreviousBlock = aCurrentBlock.previous();
+
+  QString aPreviousText;
+  forever
+  {
+    if ( aPreviousBlock == document()->begin() )
+    {
+      aPreviousText = aPreviousBlock.text();
+      if ( aPreviousText.isEmpty() && aPreviousText.trimmed().isEmpty() )
+        return -1;
+      break;
+    }
+    
+    // If the text of this block is not empty then break the loop.
+    aPreviousText = aPreviousBlock.text();
+    if ( !aPreviousText.isEmpty() && !aPreviousText.trimmed().isEmpty() )
+      break;
+    
+    aPreviousBlock = aPreviousBlock.previous();
+  }
+  
+  int aTabIndentation = 0;
+  int anAmountIndentation = -1;
+  int i = 0;
+  while ( i < aPreviousText.size() )
+  {
+    if ( !aPreviousText.at(i).isSpace() )
+    {
+      anAmountIndentation = findFirstNonSpace( aPreviousText );
+      break;
+    }
+    else
+    {
+      ++aTabIndentation;
+    }
+    ++i;
+  }
+  
+  if ( anAmountIndentation == -1 )
+  {
+    if ( aTabIndentation > 0 )
+      anAmountIndentation = aTabIndentation;
+    else
+      return 0;
+  }
+  
+  const QString aPreviousTrimmed = aPreviousText.trimmed();
+  if ( aPreviousTrimmed.endsWith( ":" ) )
+  {
+    anAmountIndentation += aTabSpaces;
+  }
+  else
+  {
+    if ( aPreviousTrimmed == "continue"
+      || aPreviousTrimmed == "break"
+      || aPreviousTrimmed == "pass"
+      || aPreviousTrimmed == "return"
+      || aPreviousTrimmed == "raise"
+      || aPreviousTrimmed.startsWith( "raise " )
+      || aPreviousTrimmed.startsWith( "return " ) )
+      anAmountIndentation -= aTabSpaces;
+  }
+  
+  aCursor.insertText( QString( anAmountIndentation, QLatin1Char(' ') ) );
+  setTextCursor( aCursor );
+  
+  return 1;
+}
+
+/*!
+  \brief Set text cursor on home position.
+  \param isExtendLine \c true to keep current anchor position
+*/
+void PyEditor_Editor::handleHome( bool isExtendLine )
+{
+  QTextCursor aCursor = textCursor();
+  QTextCursor::MoveMode aMode = QTextCursor::MoveAnchor;
+
+  if ( isExtendLine )
+    aMode = QTextCursor::KeepAnchor;
+
+  int anInitPos = aCursor.position();
+  int aBlockPos = aCursor.block().position();
+
+  QChar aCharacter = document()->characterAt( aBlockPos );
+  while ( aCharacter.category() == QChar::Separator_Space )
+  {
+    ++aBlockPos;
+    if ( aBlockPos == anInitPos )
+      break;
+    aCharacter = document()->characterAt( aBlockPos );
+  }
+  
+  if ( aBlockPos == anInitPos )
+    aBlockPos = aCursor.block().position();
+  
+  aCursor.setPosition( aBlockPos, aMode );
+  setTextCursor( aCursor );
+}
+
+/*!
+  \brief Update current line highlighting.
+*/
+void PyEditor_Editor::updateHighlightCurrentLine()
+{
+  QList<QTextEdit::ExtraSelection> anExtraSelections;
+  if ( !isReadOnly() && mySettings.highlightCurrentLine() )
+  {
+    QTextEdit::ExtraSelection selection;
+    
+    QColor lineColor = QColor( Qt::gray ).lighter( 155 );
+    
+    selection.format.setBackground( lineColor );
+    selection.format.setProperty( QTextFormat::FullWidthSelection, QVariant( true ) );
+    selection.cursor = textCursor();
+    selection.cursor.clearSelection();
+    anExtraSelections.append( selection );
+  }
+  setExtraSelections( anExtraSelections );
+}
+
+/*!
+  \brief Draw linne number area.
+  \param event paint event
+*/
+void PyEditor_Editor::lineNumberAreaPaintEvent( QPaintEvent* event )
+{
+  QPainter aPainter( myLineNumberArea );
+  aPainter.fillRect( event->rect(), QColor( Qt::lightGray ).lighter( 125 ) );
+
+  QTextBlock aBlock = firstVisibleBlock();
+  int aBlockNumber = aBlock.blockNumber();
+  int aTop = (int)blockBoundingGeometry( aBlock ).translated( contentOffset() ).top();
+  int aBottom = aTop + (int)blockBoundingRect( aBlock ).height();
+  int aCurrentLine = document()->findBlock( textCursor().position() ).blockNumber();
+
+  QFont aFont = aPainter.font();
+  aPainter.setPen( this->palette().color( QPalette::Text ) );
+
+  while ( aBlock.isValid() && aTop <= event->rect().bottom() )
+  {
+    if ( aBlock.isVisible() && aBottom >= event->rect().top() )
+    {
+      if ( aBlockNumber == aCurrentLine )
+      {
+        aPainter.setPen( Qt::darkGray );
+        aFont.setBold( true );
+        aPainter.setFont( aFont );
+      }
+      else
+      {
+        aPainter.setPen( Qt::gray ) ;
+        aFont.setBold( false );
+        aPainter.setFont( aFont );
+      }
+      QString aNumber = QString::number( aBlockNumber + 1 );
+      aPainter.drawText( 0, aTop, myLineNumberArea->width(), fontMetrics().height(), Qt::AlignRight, aNumber );
+    }
+
+    aBlock = aBlock.next();
+    aTop = aBottom;
+    aBottom = aTop + (int)blockBoundingRect( aBlock ).height();
+    ++aBlockNumber;
+  }
+}
+
+/*!
+  \brief Get with of line number area.
+  \return width of line number area
+*/
+int PyEditor_Editor::lineNumberAreaWidth()
+{
+  int aSpace = 0;
+
+  int aDigits = 1;
+  int aMaximum = qMax( 1, blockCount() );
+  while ( aMaximum >= 10 )
+  {
+    aMaximum /= 10;
+    ++aDigits;
+  }
+
+  if ( mySettings.lineNumberArea() )
+    aSpace += 5 + fontMetrics().width( QLatin1Char( '9' ) ) * aDigits;
+  
+  return aSpace;
+}
+
+/*!
+  \brief Update width of the line number area.
+  \param newBlockCount (not used)
+*/
+void PyEditor_Editor::updateLineNumberAreaWidth( int /*newBlockCount*/ )
+{
+  setViewportMargins( lineNumberAreaWidth(), 0, 0, 0 );
+}
+
+/*!
+  \brief Update line number area (when editor viewport is scrolled).
+  \param rect area being updated
+  \param dy scroll factor
+*/
+void PyEditor_Editor::updateLineNumberArea( const QRect& rect, int dy )
+{
+  if ( dy )
+    myLineNumberArea->scroll( 0, dy );
+  else
+    myLineNumberArea->update( 0, rect.y(), myLineNumberArea->width(), rect.height() );
+
+  if ( rect.contains( viewport()->rect() ) )
+    updateLineNumberAreaWidth( 0 );
+}
+
+/*!
+  \brief Manage parentheses.
+*/
+void PyEditor_Editor::matchParentheses()
+{
+  PyEditor_PyHighlighter::TextBlockData* data =
+    static_cast<PyEditor_PyHighlighter::TextBlockData*>( textCursor().block().userData() );
+
+  if ( data )
+  {
+    QVector<PyEditor_PyHighlighter::ParenthesisInfo*> infoEntries = data->parentheses();
+    
+    int aPos = textCursor().block().position();
+    bool ignore = false;
+    for ( int i = 0; i < infoEntries.size(); ++i )
+    {
+      PyEditor_PyHighlighter::ParenthesisInfo* info = infoEntries.at(i);
+      
+      int currentColumnPosition = textCursor().columnNumber();
+      if ( info->position == currentColumnPosition - 1 && isLeftBrackets( info->character ) )
+      {
+        if ( matchLeftParenthesis( textCursor().block(), i + 1, 0 ) )
+          createParenthesisSelection( aPos + info->position );
+      }
+      else if ( info->position == currentColumnPosition && isLeftBrackets( info->character ) )
+      {
+        if ( !ignore )
+        {
+          if ( matchLeftParenthesis( textCursor().block(), i + 1, 0 ) )
+            createParenthesisSelection( aPos + info->position );
+        }
+      }
+      else if ( info->position == currentColumnPosition - 1 && isRightBrackets( info->character ) )
+      {
+        if ( matchRightParenthesis( textCursor().block(), i - 1, 0 ) )
+          createParenthesisSelection( aPos + info->position );
+        ignore = true;
+      }
+      else if ( info->position == currentColumnPosition && isRightBrackets( info->character ) )
+      {
+        if ( matchRightParenthesis( textCursor().block(), i - 1, 0 ) )
+          createParenthesisSelection( aPos + info->position );
+      }
+    }
+  }
+}
+
+/*!
+  \brief Match left brackets.
+  \param currentBlock text block
+  \param idx index
+  \param numLeftParentheses number of left parentheses
+  \return \c true if the left match
+*/
+bool PyEditor_Editor::matchLeftParenthesis( const QTextBlock& currentBlock,
+                                            int idx, int numLeftParentheses )
+{
+  PyEditor_PyHighlighter::TextBlockData* data =
+    static_cast<PyEditor_PyHighlighter::TextBlockData*>( currentBlock.userData() );
+  QVector<PyEditor_PyHighlighter::ParenthesisInfo*> infos = data->parentheses();
+
+  int docPos = currentBlock.position();
+  for ( ; idx < infos.size(); ++idx )
+  {
+    PyEditor_PyHighlighter::ParenthesisInfo* info = infos.at( idx );
+
+    if ( isLeftBrackets( info->character ) )
+    {
+      ++numLeftParentheses;
+      continue;
+    }
+
+    if ( isRightBrackets( info->character ) && numLeftParentheses == 0 )
+    {
+      createParenthesisSelection( docPos + info->position );
+      return true;
+    }
+    else
+      --numLeftParentheses;
+  }
+
+  QTextBlock nextBlock = currentBlock.next();
+  if ( nextBlock.isValid() )
+    return matchLeftParenthesis( nextBlock, 0, numLeftParentheses );
+
+  return false;
+}
+
+/*!
+  \brief Match right brackets.
+  \param currentBlock text block
+  \param idx index
+  \param numRightParentheses number of right parentheses
+  \return \c true if the right match
+*/
+bool PyEditor_Editor::matchRightParenthesis( const QTextBlock& currentBlock,
+                                             int idx, int numRightParentheses )
+{
+  PyEditor_PyHighlighter::TextBlockData* data = static_cast<PyEditor_PyHighlighter::TextBlockData*>( currentBlock.userData() );
+  QVector<PyEditor_PyHighlighter::ParenthesisInfo*> parentheses = data->parentheses();
+
+  int docPos = currentBlock.position();
+  for ( ; idx > -1 && parentheses.size() > 0; --idx )
+  {
+    PyEditor_PyHighlighter::ParenthesisInfo* info = parentheses.at( idx );
+    if ( isRightBrackets( info->character ) )
+    {
+      ++numRightParentheses;
+      continue;
+    }
+    if ( isLeftBrackets( info->character ) && numRightParentheses == 0 )
+    {
+      createParenthesisSelection( docPos + info->position );
+      return true;
+    }
+    else
+      --numRightParentheses;
+  }
+
+  QTextBlock prevBlock = currentBlock.previous();
+  if ( prevBlock.isValid() )
+  {
+    PyEditor_PyHighlighter::TextBlockData* data = static_cast<PyEditor_PyHighlighter::TextBlockData*>( prevBlock.userData() );
+    QVector<PyEditor_PyHighlighter::ParenthesisInfo*> parentheses = data->parentheses();
+    return matchRightParenthesis( prevBlock, parentheses.size() - 1, numRightParentheses );
+  }
+
+  return false;
+}
+
+/*!
+  \brief Create brackets selection.
+  \param position cursor position
+*/
+void PyEditor_Editor::createParenthesisSelection( int position )
+{
+  QList<QTextEdit::ExtraSelection> selections = extraSelections();
+
+  QTextEdit::ExtraSelection selection;
+
+  QTextCharFormat format = selection.format;
+  format.setForeground( Qt::red );
+  format.setBackground( Qt::white );
+  selection.format = format;
+
+  QTextCursor cursor = textCursor();
+  cursor.setPosition( position );
+  cursor.movePosition( QTextCursor::NextCharacter, QTextCursor::KeepAnchor );
+  selection.cursor = cursor;
+
+  selections.append( selection );
+  setExtraSelections( selections );
+}
+
+/*!
+  \brief Check if symbol is a left bracket.
+  \param symbol text symbol
+  \return \c true if symbol is any left bracket
+*/
+bool PyEditor_Editor::isLeftBrackets( QChar symbol )
+{
+  return symbol == '(' || symbol == '{' || symbol == '[';
+}
+
+/*!
+  \brief Check if symbol is a right bracket.
+  \param symbol text symbol
+  \return \c true if symbol is any right bracket
+*/
+bool PyEditor_Editor::isRightBrackets( QChar symbol )
+{
+  return symbol == ')' || symbol == '}' || symbol == ']';
+}
+
+/*!
+  \brief Append new paragraph to the end of the editor's text.
+  \param text paragraph text
+*/
+void PyEditor_Editor::append( const QString& text )
+{
+  appendPlainText( text );
+}
+
+/*!
+  \brief Set text to the editor.
+  \param text new text
+*/
+void PyEditor_Editor::setText( const QString& text )
+{
+  setPlainText( text );
+}
+
+/*!
+  \brief Get current editor's content.
+  \return current text
+*/
+QString PyEditor_Editor::text() const
+{
+  return toPlainText();
+}
diff --git a/tools/PyEditor/src/PyEditor_Editor.h b/tools/PyEditor/src/PyEditor_Editor.h
new file mode 100644 (file)
index 0000000..0266356
--- /dev/null
@@ -0,0 +1,85 @@
+// Copyright (C) 2015-2016  OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File   : PyEditor_Editor.h
+// Author : Maxim GLIBIN, Open CASCADE S.A.S. (maxim.glibin@opencascade.com)
+//
+
+#ifndef PYEDITOR_EDITOR_H
+#define PYEDITOR_EDITOR_H
+
+#include "PyEditor.h"
+#include "PyEditor_Settings.h"
+
+#include <QPlainTextEdit>
+
+class PyEditor_PyHighlighter;
+
+class PYEDITOR_EXPORT PyEditor_Editor : public QPlainTextEdit
+{
+  Q_OBJECT
+
+public:
+  PyEditor_Editor( QWidget* = 0 );
+  virtual ~PyEditor_Editor();
+  
+  void setSettings( const PyEditor_Settings& );
+  const PyEditor_Settings& settings() const;
+  QString text() const;
+
+public Q_SLOTS:
+  void deleteSelected();
+  void append( const QString& );  
+  void setText( const QString& text );
+
+protected:
+  virtual void keyPressEvent( QKeyEvent* );
+  virtual void resizeEvent( QResizeEvent* );
+  virtual void paintEvent( QPaintEvent* );
+    
+private Q_SLOTS:
+  void updateHighlightCurrentLine();
+  void matchParentheses();
+
+  void updateLineNumberAreaWidth( int );
+  void updateLineNumberArea( const QRect&, int );
+  
+private:
+  bool matchLeftParenthesis( const QTextBlock&, int, int );
+  bool matchRightParenthesis( const QTextBlock&, int, int );
+  void createParenthesisSelection( int );
+  bool isLeftBrackets( QChar );
+  bool isRightBrackets( QChar );
+  void lineNumberAreaPaintEvent( QPaintEvent* );
+  int  lineNumberAreaWidth();
+
+  void handleHome( bool );
+  int  lineIndent();
+  void tabIndentation( bool );
+  void indentSelection( bool );
+  
+  int findFirstNonSpace( const QString& );
+  
+  QWidget*                myLineNumberArea;
+  PyEditor_PyHighlighter* mySyntaxHighlighter;
+  PyEditor_Settings       mySettings;
+
+  friend class PyEditor_LineNumberArea;
+};
+
+#endif // PYEDITOR_EDITOR_H
diff --git a/tools/PyEditor/src/PyEditor_LineNumberArea.cxx b/tools/PyEditor/src/PyEditor_LineNumberArea.cxx
new file mode 100644 (file)
index 0000000..066ad4e
--- /dev/null
@@ -0,0 +1,51 @@
+// Copyright (C) 2015-2016  OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File   : PyEditor_LineNumberArea.cxx
+// Author : Maxim GLIBIN, Open CASCADE S.A.S. (maxim.glibin@opencascade.com)
+//
+
+#include "PyEditor_LineNumberArea.h"
+
+#include "PyEditor_Editor.h"
+
+/*!
+  \class PyEditor_LineNumberArea
+  \brief Widget shows line number.
+*/
+
+/*!
+  \brief Constructor.
+  \param theCodeEditor parent widget
+*/
+PyEditor_LineNumberArea::PyEditor_LineNumberArea( PyEditor_Editor* theCodeEditor ) :
+  QWidget( theCodeEditor )
+{
+  myCodeEditor = theCodeEditor;
+}
+
+QSize PyEditor_LineNumberArea::sizeHint() const
+{
+  return QSize( myCodeEditor->lineNumberAreaWidth(), 0 );
+}
+
+void PyEditor_LineNumberArea::paintEvent( QPaintEvent* theEvent )
+{
+  myCodeEditor->lineNumberAreaPaintEvent( theEvent );
+  QWidget::paintEvent( theEvent );
+}
diff --git a/tools/PyEditor/src/PyEditor_LineNumberArea.h b/tools/PyEditor/src/PyEditor_LineNumberArea.h
new file mode 100644 (file)
index 0000000..e009269
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright (C) 2015-2016  OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File   : PyEditor_LineNumberArea.h
+// Author : Maxim GLIBIN, Open CASCADE S.A.S. (maxim.glibin@opencascade.com)
+//
+
+#ifndef PYEDITOR_LINENUMBERAREA_H
+#define PYEDITOR_LINENUMBERAREA_H
+
+#include <QWidget>
+
+class PyEditor_Editor;
+
+class PyEditor_LineNumberArea : public QWidget
+{
+  Q_OBJECT
+
+public:
+  explicit PyEditor_LineNumberArea( PyEditor_Editor* );
+
+  QSize sizeHint() const;
+  
+protected:
+  void paintEvent( QPaintEvent* );
+  
+private:
+  PyEditor_Editor* myCodeEditor;
+};
+
+#endif // PYEDITOR_LINENUMBERAREA_H
diff --git a/tools/PyEditor/src/PyEditor_PyHighlighter.cxx b/tools/PyEditor/src/PyEditor_PyHighlighter.cxx
new file mode 100644 (file)
index 0000000..70ff018
--- /dev/null
@@ -0,0 +1,355 @@
+// Copyright (C) 2015-2016  OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File   : PyEditor_PyHighlighter.cxx
+// Author : Maxim GLIBIN, Open CASCADE S.A.S. (maxim.glibin@opencascade.com)
+//
+
+#include "PyEditor_PyHighlighter.h"
+
+#define NORMAL 0
+#define TRIPLESINGLE 1
+#define TRIPLEDOUBLE 2
+
+/*!
+  \class PyEditor_PyHighlighter
+  \brief Python highlighter class defines the syntax highlighting rules.
+*/
+
+PyEditor_PyHighlighter::TextBlockData::TextBlockData()
+{
+}
+
+QVector<PyEditor_PyHighlighter::ParenthesisInfo*> PyEditor_PyHighlighter::TextBlockData::parentheses()
+{
+  return myParentheses;
+}
+
+void PyEditor_PyHighlighter::TextBlockData::insert( PyEditor_PyHighlighter::ParenthesisInfo* theInfo )
+{
+  int i = 0;
+  while ( i < myParentheses.size() && theInfo->position > myParentheses.at(i)->position )
+    ++i;
+
+  myParentheses.insert( i, theInfo );
+}
+
+/*!
+  \brief Constructor.
+  \param theDocument container for structured rich text documents.
+*/
+PyEditor_PyHighlighter::PyEditor_PyHighlighter( QTextDocument* theDocument )
+  : QSyntaxHighlighter( theDocument )
+{
+  initialize();
+}
+
+/*!
+  \brief Initialization rules.
+*/
+void PyEditor_PyHighlighter::initialize()
+{
+  HighlightingRule aRule;
+
+  // Keywords
+  keywordFormat.setForeground( Qt::blue );
+  QStringList aKeywords = keywords();
+  foreach ( const QString& keyword, aKeywords )
+  {
+    aRule.pattern = QRegExp( QString( "\\b%1\\b" ).arg( keyword ) );
+    aRule.format = keywordFormat;
+    aRule.capture = 0;
+    highlightingRules.append( aRule );
+  }
+
+  // Special keywords
+  specialFromat.setForeground( Qt::magenta );
+  QStringList aSpecialKeywords = specialKeywords();
+  foreach ( const QString& keyword, aSpecialKeywords )
+  {
+    aRule.pattern = QRegExp( QString( "\\b%1\\b" ).arg( keyword ) );
+    aRule.format = specialFromat;
+    aRule.capture = 0;
+    highlightingRules.append( aRule );
+  }
+
+  // Reference to the current instance of the class
+  referenceClassFormat.setForeground( QColor( 179, 143, 0 ) );
+  referenceClassFormat.setFontItalic( true );
+  aRule.pattern = QRegExp( "\\bself\\b" );
+  aRule.format = referenceClassFormat;
+  aRule.capture = 0;
+  highlightingRules.append( aRule );
+
+  // Numbers
+  numberFormat.setForeground( Qt::darkMagenta );
+  aRule.pattern = QRegExp( "\\b([-+])?(\\d+(\\.)?\\d*|\\d*(\\.)?\\d+)(([eE]([-+])?)?\\d+)?\\b" );
+  aRule.format = numberFormat;
+  aRule.capture = 0;
+  highlightingRules.append( aRule );
+
+  // String qoutation
+  quotationFormat.setForeground( Qt::darkGreen );
+  aRule.pattern = QRegExp( "(?:'[^']*'|\"[^\"]*\")" );
+  aRule.pattern.setMinimal( true );
+  aRule.format = quotationFormat;
+  aRule.capture = 0;
+  highlightingRules.append( aRule );
+
+  // Function names
+  functionFormat.setFontWeight( QFont::Bold );
+  aRule.pattern = QRegExp( "(?:def\\s*)(\\b[A-Za-z0-9_]+)(?=[\\W])" );
+  aRule.capture = 1;
+  aRule.format = functionFormat;
+  highlightingRules.append( aRule );
+
+  // Class names
+  classFormat.setForeground( Qt::darkBlue );
+  classFormat.setFontWeight( QFont::Bold );
+  aRule.pattern = QRegExp( "(?:class\\s*)(\\b[A-Za-z0-9_]+)(?=[\\W])" );
+  aRule.capture = 1;
+  aRule.format = classFormat;
+  highlightingRules.append( aRule );
+
+  // Multi line comments
+  multiLineCommentFormat.setForeground( Qt::darkRed );
+  tripleQuotesExpression = QRegExp( "(:?\"[\"]\".*\"[\"]\"|'''.*''')" );
+  aRule.pattern = tripleQuotesExpression;
+  aRule.pattern.setMinimal( true );
+  aRule.format = multiLineCommentFormat;
+  aRule.capture = 0;
+  highlightingRules.append( aRule );
+
+  tripleSingleExpression = QRegExp( "'''(?!\")" );
+  tripleDoubleExpression = QRegExp( "\"\"\"(?!')" );
+
+  // Single comments
+  singleLineCommentFormat.setForeground( Qt::darkGray );
+  aRule.pattern = QRegExp( "#[^\n]*" );
+  aRule.format = singleLineCommentFormat;
+  aRule.capture = 0;
+  highlightingRules.append( aRule );
+}
+
+/*!
+  \return string list of Python keywords.
+ */
+QStringList PyEditor_PyHighlighter::keywords()
+{
+  QStringList aKeywords;
+  aKeywords << "and"
+            << "as"
+            << "assert"
+            << "break"
+            << "class"
+            << "continue"
+            << "def"
+            << "elif"
+            << "else"
+            << "except"
+            << "exec"
+            << "finally"
+            << "False"
+            << "for"
+            << "from"
+            << "global"
+            << "if"
+            << "import"
+            << "in"
+            << "is"
+            << "lambda"
+            << "None"
+            << "not"
+            << "or"
+            << "pass"
+            << "print"
+            << "raise"
+            << "return"
+            << "True"
+            << "try"
+            << "while"
+            << "with"
+            << "yield";
+  return aKeywords;
+}
+
+/*!
+  \return string list of special Python keywords.
+*/
+QStringList PyEditor_PyHighlighter::specialKeywords()
+{
+  QStringList aSpecialKeywords;
+  aSpecialKeywords << "ArithmeticError"
+                   << "AssertionError"
+                   << "AttributeError"
+                   << "EnvironmentError"
+                   << "EOFError"
+                   << "Exception"
+                   << "FloatingPointError"
+                   << "ImportError"
+                   << "IndentationError"
+                   << "IndexError"
+                   << "IOError"
+                   << "KeyboardInterrupt"
+                   << "KeyError"
+                   << "LookupError"
+                   << "MemoryError"
+                   << "NameError"
+                   << "NotImplementedError"
+                   << "OSError"
+                   << "OverflowError"
+                   << "ReferenceError"
+                   << "RuntimeError"
+                   << "StandardError"
+                   << "StopIteration"
+                   << "SyntaxError"
+                   << "SystemError"
+                   << "SystemExit"
+                   << "TabError"
+                   << "TypeError"
+                   << "UnboundLocalError"
+                   << "UnicodeDecodeError"
+                   << "UnicodeEncodeError"
+                   << "UnicodeError"
+                   << "UnicodeTranslateError"
+                   << "ValueError"
+                   << "WindowsError"
+                   << "ZeroDivisionError"
+                   << "Warning"
+                   << "UserWarning"
+                   << "DeprecationWarning"
+                   << "PendingDeprecationWarning"
+                   << "SyntaxWarning"
+                   << "OverflowWarning"
+                   << "RuntimeWarning"
+                   << "FutureWarning";
+  return aSpecialKeywords;
+}
+
+void PyEditor_PyHighlighter::highlightBlock( const QString& theText )
+{
+  TextBlockData* aData = new TextBlockData;
+  
+  insertBracketsData( RoundBrackets, aData, theText );
+  insertBracketsData( CurlyBrackets, aData, theText );
+  insertBracketsData( SquareBrackets, aData, theText );
+
+  setCurrentBlockUserData( aData );
+
+  foreach ( const HighlightingRule& rule, highlightingRules )
+  {
+    QRegExp expression( rule.pattern );
+    int anIndex = expression.indexIn( theText );
+    while ( anIndex >= 0 )
+    {
+      anIndex = expression.pos( rule.capture );
+      int aLength = expression.cap( rule.capture ).length();
+      setFormat( anIndex, aLength, rule.format );
+      anIndex = expression.indexIn( theText, anIndex + aLength );
+    }
+  }
+
+  setCurrentBlockState( NORMAL );
+
+  if ( theText.indexOf( tripleQuotesExpression ) != -1 )
+    return;
+
+  QList<int> aTripleSingle;
+  aTripleSingle << theText.indexOf( tripleSingleExpression ) << TRIPLESINGLE;
+
+  QList<int> aTripleDouble;
+  aTripleDouble << theText.indexOf( tripleDoubleExpression ) << TRIPLEDOUBLE;
+  QList< QList<int> > aTripleExpressions;
+  aTripleExpressions << aTripleSingle << aTripleDouble;
+
+  for ( int i = 0; i < aTripleExpressions.length(); i++ )
+  {
+    QList<int> aBlock = aTripleExpressions[i];
+    int anIndex = aBlock[0];
+    int aState = aBlock[1];
+    if ( previousBlockState() == aState )
+    {
+      if ( anIndex == -1 )
+      {
+        anIndex = theText.length();
+        setCurrentBlockState( aState );
+      }
+      setFormat( 0, anIndex + 3, multiLineCommentFormat );
+    }
+    else if ( anIndex > -1 )
+    {
+      setCurrentBlockState( aState );
+      setFormat( anIndex, theText.length(), multiLineCommentFormat );
+    }
+  }
+}
+
+void PyEditor_PyHighlighter::insertBracketsData( char theLeftSymbol,
+                                                 char theRightSymbol,
+                                                 TextBlockData* theData,
+                                                 const QString& theText )
+{
+  int leftPosition = theText.indexOf( theLeftSymbol );
+  while( leftPosition != -1 )
+  {
+    ParenthesisInfo* info = new ParenthesisInfo();
+    info->character = theLeftSymbol;
+    info->position = leftPosition;
+
+    theData->insert( info );
+    leftPosition = theText.indexOf( theLeftSymbol, leftPosition + 1 );
+  }
+
+  int rightPosition = theText.indexOf( theRightSymbol );
+  while( rightPosition != -1 )
+  {
+    ParenthesisInfo* info = new ParenthesisInfo();
+    info->character = theRightSymbol;
+    info->position = rightPosition;
+
+    theData->insert( info );
+    rightPosition = theText.indexOf( theRightSymbol, rightPosition + 1 );
+  }
+}
+
+void PyEditor_PyHighlighter::insertBracketsData( Brackets theBrackets,
+                                                 TextBlockData* theData,
+                                                 const QString& theText )
+{
+  char leftChar = '0';
+  char rightChar = '0';
+  
+  switch( theBrackets )
+  {
+  case RoundBrackets:
+    leftChar = '(';
+    rightChar = ')';
+    break;
+  case CurlyBrackets:
+    leftChar = '{';
+    rightChar = '}';
+    break;
+  case SquareBrackets:
+    leftChar = '[';
+    rightChar = ']';
+    break;
+  }
+
+  insertBracketsData( leftChar, rightChar, theData, theText );
+}
diff --git a/tools/PyEditor/src/PyEditor_PyHighlighter.h b/tools/PyEditor/src/PyEditor_PyHighlighter.h
new file mode 100644 (file)
index 0000000..961616f
--- /dev/null
@@ -0,0 +1,91 @@
+// Copyright (C) 2015-2016  OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File   : PyEditor_PyHighlighter.h
+// Author : Maxim GLIBIN, Open CASCADE S.A.S. (maxim.glibin@opencascade.com)
+//
+
+#ifndef PYEDITOR_PYHIGHLIGHTER_H
+#define PYEDITOR_PYHIGHLIGHTER_H
+
+#include <QSyntaxHighlighter>
+
+class QTextDocument;
+
+class PyEditor_PyHighlighter : public QSyntaxHighlighter
+{
+  Q_OBJECT
+
+public:
+
+  struct ParenthesisInfo
+  {
+    char character;
+    int position;
+  };
+
+  class TextBlockData : public QTextBlockUserData
+  {
+  public:
+    TextBlockData();
+
+    QVector<ParenthesisInfo*> parentheses();
+    void insert( ParenthesisInfo* );
+
+  private:
+    QVector<ParenthesisInfo*> myParentheses;
+  };
+
+public:
+  PyEditor_PyHighlighter( QTextDocument* = 0 );
+
+  void initialize();
+  QStringList keywords();
+  QStringList specialKeywords();
+
+protected:
+  struct HighlightingRule
+  {
+    QRegExp pattern;
+    QTextCharFormat format;
+    int capture;
+  };
+  QVector<HighlightingRule> highlightingRules;
+
+  enum Brackets { RoundBrackets, CurlyBrackets, SquareBrackets };
+
+  QRegExp tripleQuotesExpression;
+  QRegExp tripleSingleExpression;
+  QRegExp tripleDoubleExpression;
+
+  QTextCharFormat classFormat;
+  QTextCharFormat referenceClassFormat;
+  QTextCharFormat functionFormat;
+  QTextCharFormat keywordFormat;
+  QTextCharFormat specialFromat;
+  QTextCharFormat numberFormat;
+  QTextCharFormat singleLineCommentFormat;
+  QTextCharFormat multiLineCommentFormat;
+  QTextCharFormat quotationFormat;
+
+  void highlightBlock( const QString& );
+  void insertBracketsData( char, char, TextBlockData*, const QString& );
+  void insertBracketsData( Brackets, TextBlockData*, const QString& );
+};
+
+#endif // PYEDITOR_PYHIGHLIGHTER_H
diff --git a/tools/PyEditor/src/PyEditor_Settings.cxx b/tools/PyEditor/src/PyEditor_Settings.cxx
new file mode 100644 (file)
index 0000000..d9fd52f
--- /dev/null
@@ -0,0 +1,283 @@
+// Copyright (C) 2015-2016  OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File   : PyEditor_Settings.cxx
+// Author : Maxim GLIBIN, Open CASCADE S.A.S. (maxim.glibin@opencascade.com)
+//
+
+#include "PyEditor_Settings.h"
+
+/*!
+  \class PyEditor_Settings
+  \brief Manager of setting values.
+*/
+
+PyEditor_Settings* PyEditor_Settings::myGlobalSettings = 0;
+
+/*!
+  Get global settings.
+  \return reference to global settings object
+*/
+PyEditor_Settings* PyEditor_Settings::settings()
+{
+  return myGlobalSettings;
+}
+
+/*!
+  Set global settings.
+  \param settings reference to global settings object
+*/
+void PyEditor_Settings::setSettings( PyEditor_Settings* settings )
+{
+  if ( myGlobalSettings )
+    delete myGlobalSettings;
+  myGlobalSettings = settings;
+}
+
+/*!
+  \brief Constructor.
+*/
+PyEditor_Settings::PyEditor_Settings()
+  : myHighlightCurrentLine( true ),
+    myTextWrapping( false ),
+    myCenterCursorOnScroll( true ),
+    myLineNumberArea( true ),
+    myVerticalEdge( true ),
+    myNumberColumns( 80 ),
+    myTabSpaceVisible( true ),
+    myTabSize( 4 ),
+    myFont( "Courier", 10 )
+{
+}
+
+/*!
+  \brief Set "highlight current line" option.
+  \param on option value
+*/
+void PyEditor_Settings::setHighlightCurrentLine( bool on )
+{
+  myHighlightCurrentLine = on;
+}
+
+/*!
+  \brief Get "highlight current line" option.
+  \return option value
+*/
+bool PyEditor_Settings::highlightCurrentLine() const
+{
+  return myHighlightCurrentLine;
+}
+
+/*!
+  \brief Set "text wrapping" option.
+  \param on option value
+*/
+void PyEditor_Settings::setTextWrapping( bool on )
+{
+  myTextWrapping = on;
+}
+
+/*!
+  \brief Get "text wrapping line" option.
+  \return option value
+*/
+bool PyEditor_Settings::textWrapping() const
+{
+  return myTextWrapping;
+}
+
+/*!
+  \brief Set "center cursor on scroll" option.
+  \param on option value
+*/
+void PyEditor_Settings::setCenterCursorOnScroll( bool on )
+{
+  myCenterCursorOnScroll = on;
+}
+
+/*!
+  \brief Get "center cursor on scroll" option.
+  \return option value
+*/
+bool PyEditor_Settings::centerCursorOnScroll() const
+{
+  return myCenterCursorOnScroll;
+}
+
+/*!
+  \brief Set "show line number area" option.
+  \param on option value
+*/
+void PyEditor_Settings::setLineNumberArea( bool on )
+{
+  myLineNumberArea = on;
+}
+
+/*!
+  \brief Get "show line number area" option.
+  \return option value
+*/
+bool PyEditor_Settings::lineNumberArea() const
+{
+  return myLineNumberArea;
+}
+
+/*!
+  \brief Set "show vertical edge" option.
+  \param on option value
+*/
+void PyEditor_Settings::setVerticalEdge( bool on )
+{
+  myVerticalEdge = on;
+}
+
+/*!
+  \brief Get "show vertical edge" option.
+  \return option value
+*/
+bool PyEditor_Settings::verticalEdge() const
+{
+  return myVerticalEdge;
+}
+
+/*!
+  \brief Set "number of columns" option.
+  \param value option value
+*/
+void PyEditor_Settings::setNumberColumns( int value )
+{
+  myNumberColumns = value;
+}
+
+/*!
+  \brief Get "number of columns" option.
+  \return option value
+*/
+int PyEditor_Settings::numberColumns() const
+{
+  return myNumberColumns;
+}
+
+/*!
+  \brief Set "show tab spaces" option.
+  \param on option value
+*/
+void PyEditor_Settings::setTabSpaceVisible( bool on )
+{
+  myTabSpaceVisible = on;
+}
+
+/*!
+  \brief Get "show tab spaces" option.
+  \return option value
+*/
+bool PyEditor_Settings::tabSpaceVisible() const
+{
+  return myTabSpaceVisible;
+}
+
+/*!
+  \brief Set "tab size" option.
+  \param value option value
+*/
+void PyEditor_Settings::setTabSize( int value )
+{
+  myTabSize = value;
+}
+
+/*!
+  \brief Get "tab size" option.
+  \return option value
+*/
+int PyEditor_Settings::tabSize() const
+{
+  return myTabSize;
+}
+
+/*!
+  \brief Set "font" option.
+  \param font option value
+*/
+void PyEditor_Settings::setFont( const QFont& font )
+{
+  myFont = font;
+}
+
+/*!
+  \brief Get "font" option.
+  \return option value
+*/
+QFont PyEditor_Settings::font() const
+{
+  return myFont;
+}
+
+/*!
+  \brief Read settings from the persistence storage.
+  Base implementation does nothing; it should be reimplemented in successors.
+*/
+void PyEditor_Settings::load()
+{
+}
+
+/*!
+  \brief Write settings to the persistence storage.
+  Base implementation does nothing; it should be reimplemented in successors.
+*/
+void PyEditor_Settings::save()
+{
+}
+
+/*!
+  \brief Copy settings from another object.
+  \param other source settings object
+*/
+void PyEditor_Settings::copyFrom( const PyEditor_Settings& other )
+{
+  setHighlightCurrentLine( other.highlightCurrentLine() );
+  setTextWrapping( other.textWrapping() );
+  setCenterCursorOnScroll( other.centerCursorOnScroll() );
+  setLineNumberArea( other.lineNumberArea() );
+  setTabSpaceVisible( other.tabSpaceVisible() );
+  setTabSize( other.tabSize() );
+  setVerticalEdge( other.verticalEdge() );
+  setNumberColumns( other.numberColumns() );
+  setFont( other.font() );
+  save();
+}
+
+/*!
+  \brief Get preference item's identifier.
+  \return string identifier
+*/
+QString PyEditor_Settings::option( Option option )
+{
+  static const char* options[] = {
+    "PythonEditor",
+    "HighlightCurrentLine",
+    "TextWrapping",
+    "CenterCursorOnScroll",
+    "LineNumberArea",
+    "VerticalEdge",
+    "NumberColumns",
+    "TabSpaceVisible",
+    "TabSize",
+    "Font",
+  };
+  return option >= 0 && option <= snFont ? options[option] : "Unknown";
+}
diff --git a/tools/PyEditor/src/PyEditor_Settings.h b/tools/PyEditor/src/PyEditor_Settings.h
new file mode 100644 (file)
index 0000000..2f1c9be
--- /dev/null
@@ -0,0 +1,106 @@
+// Copyright (C) 2015-2016  OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File   : PyEditor_Settings.h
+// Author : Maxim GLIBIN, Open CASCADE S.A.S. (maxim.glibin@opencascade.com)
+//
+
+#ifndef PYEDITOR_SETTINGS_H
+#define PYEDITOR_SETTINGS_H
+
+#include "PyEditor.h"
+
+#include <QFont>
+
+class PYEDITOR_EXPORT PyEditor_Settings
+{
+protected:
+  enum Option { snEditor, 
+               snHighlightCurrentLine,
+               snTextWrapping,
+               snCenterCursorOnScroll,
+               snLineNumberArea,
+               snVerticalEdge,
+               snNumberColumns,
+               snTabSpaceVisible,
+               snTabSize,
+               snFont };
+
+public:
+  static PyEditor_Settings* settings();
+  static void setSettings( PyEditor_Settings* );
+  
+  PyEditor_Settings();
+
+  void setHighlightCurrentLine( bool );
+  bool highlightCurrentLine() const;
+
+  void setTextWrapping( bool );
+  bool textWrapping() const;
+
+  void setCenterCursorOnScroll( bool );
+  bool centerCursorOnScroll() const;
+
+  void setLineNumberArea( bool );
+  bool lineNumberArea() const;
+
+  void setVerticalEdge( bool );
+  bool verticalEdge() const;
+
+  void setNumberColumns( int );
+  int numberColumns() const;
+
+  void setTabSpaceVisible( bool );
+  bool tabSpaceVisible() const;
+
+  void setTabSize( int );
+  int tabSize() const;
+
+  void setFont( const QFont& );
+  QFont font() const;
+
+  virtual void load();
+  virtual void save();
+
+  void copyFrom( const PyEditor_Settings& );
+  
+protected:
+  QString option( Option );
+
+private:
+  // Display settings
+  bool myHighlightCurrentLine;
+  bool myTextWrapping;
+  bool myCenterCursorOnScroll;
+  bool myLineNumberArea;
+  
+  // Vertical edge settings
+  bool myVerticalEdge;
+  int  myNumberColumns;
+  
+  // Tab settings
+  bool myTabSpaceVisible;
+  int  myTabSize;
+  
+  // Font settings
+  QFont myFont;
+
+  static PyEditor_Settings* myGlobalSettings;
+};
+
+#endif // PYEDITOR_SETTINGS_H
diff --git a/tools/PyEditor/src/PyEditor_SettingsDlg.cxx b/tools/PyEditor/src/PyEditor_SettingsDlg.cxx
new file mode 100644 (file)
index 0000000..fc2c94b
--- /dev/null
@@ -0,0 +1,326 @@
+// Copyright (C) 2015-2016  OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File   : PyEditor_SettingsDlg.cxx
+// Author : Maxim GLIBIN, Open CASCADE S.A.S. (maxim.glibin@opencascade.com)
+//
+
+#include "PyEditor_SettingsDlg.h"
+
+#include "PyEditor_Editor.h"
+#include "PyEditor_Settings.h"
+
+#include <QCheckBox>
+#include <QComboBox>
+#include <QFontComboBox>
+#include <QGroupBox>
+#include <QLabel>
+#include <QPushButton>
+#include <QSpinBox>
+#include <QVBoxLayout>
+
+/*!
+  \class PyEditor_SettingsDlg
+  \brief Dialog settings for python editor.
+*/
+
+/*!
+  \brief Constructor.
+  \param theEditor widget that is used to edit and display text
+  \param theParent parent widget
+*/
+PyEditor_SettingsDlg::PyEditor_SettingsDlg( PyEditor_Editor* theEditor,
+                                            bool showHelp, QWidget* theParent ) :
+  QDialog( theParent ),
+  myEditor( theEditor )
+{
+  setWindowTitle( tr("TIT_PREFERENCES") );
+  QVBoxLayout* aMainLayout = new QVBoxLayout( this );
+  
+  // . Font settings <start>
+  QGroupBox* aFontSetBox = new QGroupBox( tr( "GR_FONT_SET" ), this );
+  QHBoxLayout* aFontSetLayout = new QHBoxLayout( aFontSetBox );
+  myFontFamily = new QFontComboBox( aFontSetBox );
+  myFontFamily->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
+  myFontSize = new QComboBox( aFontSetBox );
+  myFontSize->setInsertPolicy( QComboBox::NoInsert );
+  myFontSize->setEditable( true );
+  myFontSize->setValidator( new QIntValidator( 1, 250, myFontSize ) );
+  myFontSize->setSizeAdjustPolicy( QComboBox::AdjustToContents );
+  myFontSize->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed );
+  aFontSetLayout->addWidget( myFontFamily );
+  aFontSetLayout->addWidget( myFontSize );
+  connect( myFontFamily, SIGNAL( currentFontChanged( QFont ) ),
+           this, SLOT( onFontChanged() ) );
+  aMainLayout->addWidget( aFontSetBox );
+  // . Font settings <end>
+  
+  // . Display settings <start>
+  QGroupBox* aDisplaySetBox = new QGroupBox( tr( "GR_DISP_SET" ), this );
+  QVBoxLayout* aDisplaySetLayout = new QVBoxLayout( aDisplaySetBox );
+  myHighlightCurrentLine = new QCheckBox( tr( "LBL_CURRLINE_HIGHLIGHT" ), aDisplaySetBox );
+  myTextWrapping = new QCheckBox( tr( "LBL_TEXT_WRAP" ), aDisplaySetBox );
+  myCenterCursorOnScroll = new QCheckBox( tr( "LBL_CURSOR_SCROLL" ), aDisplaySetBox );
+  myLineNumberArea = new QCheckBox( tr( "LBL_LINE_NUMBS_AREA" ), aDisplaySetBox );
+  aDisplaySetLayout->addWidget( myHighlightCurrentLine );
+  aDisplaySetLayout->addWidget( myTextWrapping );
+  aDisplaySetLayout->addWidget( myCenterCursorOnScroll );
+  aDisplaySetLayout->addWidget( myLineNumberArea );
+  aDisplaySetLayout->addStretch( 1 );
+  aMainLayout->addWidget( aDisplaySetBox );
+  // . Display settings <end>
+
+  // . Tab settings <start>
+  QGroupBox* aTabSetBox = new QGroupBox( tr( "GR_TAB_SET" ), this );
+  QVBoxLayout* aTabSetLayout = new QVBoxLayout( aTabSetBox );
+  myTabSpaceVisible = new QCheckBox( tr( "LBL_TAB_SPACES" ), aTabSetBox );
+  QHBoxLayout* aTabSizeLayout = new QHBoxLayout;
+  QLabel* aTabSizeLabel = new QLabel( tr( "LBL_TAB_SIZE" ), aTabSetBox );
+  myTabSize = new QSpinBox( aTabSetBox );
+  myTabSize->setMinimum( 0 );
+  myTabSize->setSingleStep( 1 );
+  aTabSizeLayout->addWidget( aTabSizeLabel );
+  aTabSizeLayout->addWidget( myTabSize );
+  aTabSizeLayout->addStretch( 1 );
+  aTabSetLayout->addWidget( myTabSpaceVisible );
+  aTabSetLayout->addLayout( aTabSizeLayout );
+  // . Tab settings <end>
+
+  // . Vertical edge settings <start>
+  QGroupBox* aVertEdgeSetBox = new QGroupBox( tr( "GR_VERT_EDGE_SET" ), this );
+  QVBoxLayout* aVertEdgeLayout = new QVBoxLayout( aVertEdgeSetBox );
+  myVerticalEdge = new QCheckBox( tr( "LBL_VERT_EDGE" ), aVertEdgeSetBox );
+  QHBoxLayout* aNumberColLayout = new QHBoxLayout;
+  myNumberColumnsLbl = new QLabel( tr( "LBL_NUM_COLUMNS" ), aVertEdgeSetBox );
+  myNumberColumns = new QSpinBox( aVertEdgeSetBox );
+  myNumberColumns->setMinimum( 0 );
+  myNumberColumns->setSingleStep( 1 );
+  aNumberColLayout->addWidget( myNumberColumnsLbl );
+  aNumberColLayout->addWidget( myNumberColumns );
+  aNumberColLayout->addStretch( 1 );
+  aVertEdgeLayout->addWidget( myVerticalEdge );
+  aVertEdgeLayout->addLayout( aNumberColLayout );
+  connect( myVerticalEdge, SIGNAL( clicked( bool ) ), 
+           this, SLOT( onVerticalEdgeChecked() ) );
+  // . Vertical edge settings <end>
+
+  QHBoxLayout* aTabVertEdgeLayout = new QHBoxLayout;
+  aTabVertEdgeLayout->addWidget( aTabSetBox );
+  aTabVertEdgeLayout->addWidget( aVertEdgeSetBox );
+  aMainLayout->addLayout( aTabVertEdgeLayout );
+
+  // . "Set as default" check box <start>
+  if ( PyEditor_Settings::settings() )
+  {
+    myDefaultCheck = new QCheckBox( tr( "WDG_SET_AS_DEFAULT_CHECK" ), this );
+    aMainLayout->addWidget( myDefaultCheck );
+  }
+  else
+  {
+    myDefaultCheck = 0;
+  }
+  // . "Set as default" check box <end>
+
+  // . Control buttons <start>
+  QHBoxLayout* aButtonLayout = new QHBoxLayout;
+
+  QPushButton* okBtn = new QPushButton( tr( "BUT_OK" ), this );
+  okBtn->setAutoDefault( true );
+  okBtn->setDefault( true );
+  connect( okBtn, SIGNAL( clicked() ), this, SLOT( onOk() ) );
+  aButtonLayout->addWidget( okBtn );
+
+  if ( PyEditor_Settings::settings() )
+  {
+    QPushButton* defBtn = new QPushButton( tr( "BUT_DEFAULTS" ), this );
+    defBtn->setAutoDefault( true );
+    connect( defBtn, SIGNAL( clicked() ), this, SLOT( onDefault() ) );
+    aButtonLayout->addStretch();
+    aButtonLayout->addWidget( defBtn );
+  }
+
+  QPushButton* cancelBtn = new QPushButton( tr( "BUT_CANCEL" ), this );
+  cancelBtn->setAutoDefault( true );
+  connect( cancelBtn, SIGNAL( clicked() ), this, SLOT( reject() ) );
+  aButtonLayout->addStretch();
+  aButtonLayout->addWidget( cancelBtn );
+
+  if ( showHelp )
+  {
+    QPushButton* helpBtn = new QPushButton( tr( "BUT_HELP" ), this );
+    helpBtn->setAutoDefault( true );
+    connect( helpBtn, SIGNAL( clicked() ), this, SLOT( onHelp() ) );
+    aButtonLayout->addWidget( helpBtn );
+  }
+  aMainLayout->addStretch( 1 );
+  aMainLayout->addLayout( aButtonLayout );
+  // . Control buttons <end>
+  
+  settingsToGui();
+}
+
+/*!
+  Destructor.
+*/
+PyEditor_SettingsDlg::~PyEditor_SettingsDlg()
+{
+}
+
+/*!
+  SLOT: Changes the widget visibility depending on the set theState flag.
+  \param theState flag of visibility
+ */
+void PyEditor_SettingsDlg::onVerticalEdgeChecked()
+{
+  myNumberColumnsLbl->setEnabled( myVerticalEdge->isChecked() );
+  myNumberColumns->setEnabled( myVerticalEdge->isChecked() );
+}
+
+/*!
+  SLOT: Fills font sizesc combo-box with available values depending on the
+  chosen font family.
+ */
+void PyEditor_SettingsDlg::onFontChanged()
+{
+  bool blocked = myFontSize->blockSignals( true );
+
+  QString oldSize = myFontSize->currentText();
+
+  QList<int> szList = QFontDatabase().pointSizes( myFontFamily->currentFont().family() );
+  QStringList sizes;
+  foreach ( int size, szList )
+    sizes.append( QString::number( size ) );
+
+  myFontSize->clear();
+  myFontSize->addItems( sizes );
+  setFontSize( oldSize );
+
+  myFontSize->blockSignals( blocked );
+}
+
+/*!
+  \brief Sets settings from preferences dialog.
+ */
+void PyEditor_SettingsDlg::settingsFromGui()
+{
+  const PyEditor_Settings& oldSettings = myEditor->settings();
+  PyEditor_Settings settings;
+  
+  QFont font = oldSettings.font();
+  font.setFamily( myFontFamily->currentFont().family() );
+  bool ok;
+  int size = myFontSize->currentText().toInt( &ok );
+  if ( ok )
+    font.setPointSize( size );
+
+  settings.setHighlightCurrentLine( myHighlightCurrentLine->isChecked() );
+  settings.setTextWrapping( myTextWrapping->isChecked() );
+  settings.setCenterCursorOnScroll( myCenterCursorOnScroll->isChecked() );
+  settings.setLineNumberArea( myLineNumberArea->isChecked() );
+  settings.setTabSpaceVisible( myTabSpaceVisible->isChecked() );
+  settings.setTabSize( myTabSize->value() );
+  settings.setVerticalEdge( myVerticalEdge->isChecked() );
+  settings.setNumberColumns( myNumberColumns->value() );
+  settings.setFont( font );
+  myEditor->setSettings(settings); // updateContent()
+
+  PyEditor_Settings* globals = PyEditor_Settings::settings();
+  if ( globals && myDefaultCheck && myDefaultCheck->isChecked() )
+    globals->copyFrom( settings );
+}
+
+/*!
+  \brief Sets settings into preferences dialog.
+ */
+void PyEditor_SettingsDlg::settingsToGui()
+{
+  const PyEditor_Settings& settings = myEditor->settings();
+
+  myHighlightCurrentLine->setChecked( settings.highlightCurrentLine() );
+  myTextWrapping->setChecked( settings.textWrapping() );
+  myCenterCursorOnScroll->setChecked( settings.centerCursorOnScroll() );
+  myLineNumberArea->setChecked( settings.lineNumberArea() );
+  myTabSpaceVisible->setChecked( settings.tabSpaceVisible() );
+  myTabSize->setValue( settings.tabSize() );
+  myVerticalEdge->setChecked( settings.verticalEdge() );
+  myNumberColumns->setValue( settings.numberColumns() );
+  myFontFamily->setCurrentFont( settings.font() );
+  setFontSize( QString::number( settings.font().pointSize() ) );
+
+  onVerticalEdgeChecked();
+  onFontChanged();
+}
+
+/*!
+  \brief Set font size value to the combo box.
+  \param size new size value
+*/
+void PyEditor_SettingsDlg::setFontSize( const QString& size )
+{
+  int idx = myFontSize->findText( size );
+  if ( idx != -1 )
+    myFontSize->setCurrentIndex( idx );
+  else
+    myFontSize->setEditText( size );
+}
+
+/*!
+  Slot, called when user clicks "OK" button
+*/
+void PyEditor_SettingsDlg::onOk()
+{
+  settingsFromGui();
+  accept();
+}
+
+/*!
+  Slot, called when user clicks "Defaults" button
+*/
+void PyEditor_SettingsDlg::onDefault()
+{
+  PyEditor_Settings* settings = PyEditor_Settings::settings();
+  if ( settings )
+  {
+    settings->load(); // to reload from the resources
+    
+    QFont font = settings->font();
+
+    myHighlightCurrentLine->setChecked( settings->highlightCurrentLine() );
+    myTextWrapping->setChecked( settings->textWrapping() );
+    myCenterCursorOnScroll->setChecked( settings->centerCursorOnScroll() );
+    myLineNumberArea->setChecked( settings->lineNumberArea() );
+    myTabSpaceVisible->setChecked( settings->tabSpaceVisible() );
+    myTabSize->setValue( settings->tabSize() );
+    myVerticalEdge->setChecked( settings->verticalEdge() );
+    myNumberColumns->setValue( settings->numberColumns() );
+    myFontFamily->setCurrentFont( font );
+    setFontSize( QString::number( font.pointSize() ) );
+    
+    onVerticalEdgeChecked();
+    onFontChanged();
+  }
+}
+
+/*!
+  Slot, called when user clicks "Help" button.
+  Emits help() signal.
+*/
+void PyEditor_SettingsDlg::onHelp()
+{
+  emit help();
+}
diff --git a/tools/PyEditor/src/PyEditor_SettingsDlg.h b/tools/PyEditor/src/PyEditor_SettingsDlg.h
new file mode 100644 (file)
index 0000000..9f3dfa9
--- /dev/null
@@ -0,0 +1,79 @@
+// Copyright (C) 2015-2016  OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File   : PyEditor_SettingsDlg.h
+// Author : Maxim GLIBIN, Open CASCADE S.A.S. (maxim.glibin@opencascade.com)
+//
+
+#ifndef PYEDITOR_SETTINGSDLG_H
+#define PYEDITOR_SETTINGSDLG_H
+
+#include <QDialog>
+#include "PyEditor.h"
+
+class PyEditor_Editor;
+class QCheckBox;
+class QComboBox;
+class QFontComboBox;
+class QLabel;
+class QSpinBox;
+
+class PYEDITOR_EXPORT PyEditor_SettingsDlg : public QDialog
+{
+  Q_OBJECT
+
+public:
+  PyEditor_SettingsDlg( PyEditor_Editor*, bool = false, QWidget* = 0 );
+  ~PyEditor_SettingsDlg();
+
+private Q_SLOTS:
+  void onVerticalEdgeChecked();
+  void onFontChanged();
+  void onOk();
+  void onDefault();
+  void onHelp();
+
+Q_SIGNALS:
+  void help();
+
+private:
+  void settingsToGui();
+  void settingsFromGui();
+  void setFontSize( const QString& );
+  
+  QCheckBox*        myHighlightCurrentLine;
+  QCheckBox*        myTextWrapping;
+  QCheckBox*        myCenterCursorOnScroll;
+  QCheckBox*        myLineNumberArea;
+
+  QCheckBox*        myTabSpaceVisible;
+  QSpinBox*         myTabSize;
+
+  QCheckBox*        myVerticalEdge;
+  QSpinBox*         myNumberColumns;
+  QLabel*           myNumberColumnsLbl;
+
+  QFontComboBox*    myFontFamily;
+  QComboBox*        myFontSize;
+
+  QCheckBox*        myDefaultCheck;
+
+  PyEditor_Editor*  myEditor;
+};
+
+#endif // PYEDITOR_SETTINGSDLG_H
diff --git a/tools/PyEditor/src/PyEditor_StdSettings.cxx b/tools/PyEditor/src/PyEditor_StdSettings.cxx
new file mode 100644 (file)
index 0000000..816db36
--- /dev/null
@@ -0,0 +1,92 @@
+// Copyright (C) 2015-2016  OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File   : PyEditor_StdSettings.cxx
+// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
+//
+
+#include "PyEditor_StdSettings.h"
+
+PyEditor_StdSettings::PyEditor_StdSettings() :
+  myLanguage( "en" )
+{
+  load();
+}
+
+PyEditor_StdSettings::PyEditor_StdSettings( const QString& group ) :
+  myGroup( group ),
+  myLanguage( "en" )
+{
+  load();
+}
+
+PyEditor_StdSettings::PyEditor_StdSettings( const QString& group,
+                                            const QString& filename,
+                                            QSettings::Format format ) :
+  mySettings( filename, format ),
+  myGroup( group ),
+  myLanguage( "en" )
+{
+  load();
+}
+
+void PyEditor_StdSettings::setLanguage( const QString& language )
+{
+  myLanguage = language;
+}
+
+QString PyEditor_StdSettings::language() const
+{
+  return myLanguage;
+}
+
+void PyEditor_StdSettings::load()
+{
+  mySettings.beginGroup( myGroup.isEmpty() ? option( snEditor ) : myGroup );
+
+  setHighlightCurrentLine( mySettings.value( option( snHighlightCurrentLine ), highlightCurrentLine() ).toBool() );
+  setTextWrapping( mySettings.value( option( snTextWrapping ), textWrapping() ).toBool() );
+  setCenterCursorOnScroll( mySettings.value( option( snCenterCursorOnScroll ), centerCursorOnScroll() ).toBool() );
+  setLineNumberArea( mySettings.value( option( snLineNumberArea ), lineNumberArea() ).toBool() );
+  setVerticalEdge( mySettings.value( option( snVerticalEdge  ), verticalEdge() ).toBool() );
+  setNumberColumns( mySettings.value( option( snNumberColumns ), numberColumns() ).toInt() );
+  setTabSpaceVisible( mySettings.value( option( snTabSpaceVisible ), tabSpaceVisible() ).toBool() );
+  setTabSize( mySettings.value( option( snTabSize ), tabSize() ).toInt() );
+  setFont( mySettings.value( option( snFont ), font() ).value<QFont>() );
+  setLanguage( mySettings.value( "language", language() ).toString() );
+
+  mySettings.endGroup();
+}
+
+void PyEditor_StdSettings::save()
+{
+  mySettings.beginGroup( myGroup.isEmpty() ? option( snEditor ) : myGroup );
+
+  mySettings.setValue( option( snHighlightCurrentLine ), highlightCurrentLine() );
+  mySettings.setValue( option( snTextWrapping ), textWrapping() );
+  mySettings.setValue( option( snCenterCursorOnScroll ), centerCursorOnScroll() );
+  mySettings.setValue( option( snLineNumberArea ), lineNumberArea() );
+  mySettings.setValue( option( snVerticalEdge  ), verticalEdge() );
+  mySettings.setValue( option( snNumberColumns ), numberColumns() );
+  mySettings.setValue( option( snTabSpaceVisible ), tabSpaceVisible() );
+  mySettings.setValue( option( snTabSize ), tabSize() );
+  mySettings.setValue( option( snFont ), font() );
+  mySettings.setValue( "language", language() );
+
+  mySettings.endGroup();
+}
diff --git a/tools/PyEditor/src/PyEditor_StdSettings.h b/tools/PyEditor/src/PyEditor_StdSettings.h
new file mode 100644 (file)
index 0000000..dc102fd
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright (C) 2015-2016  OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File   : PyEditor_StdSettings.h
+// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
+//
+
+#ifndef PYEDITOR_STDSETTINGS_H
+#define PYEDITOR_STDSETTINGS_H
+
+#include "PyEditor.h"
+#include "PyEditor_Settings.h"
+
+#include <QSettings>
+
+class PYEDITOR_EXPORT PyEditor_StdSettings : public PyEditor_Settings
+{
+public:
+  PyEditor_StdSettings();
+  PyEditor_StdSettings( const QString& );
+  PyEditor_StdSettings( const QString&, const QString&, QSettings::Format = QSettings::IniFormat );
+
+  void setLanguage( const QString& );
+  QString language() const;
+
+  void load();
+  void save();
+
+private:
+  QSettings mySettings;
+  QString myGroup;
+  QString myLanguage;
+};
+
+#endif // PYEDITOR_STDSETTINGS_H
diff --git a/tools/PyEditor/src/PyEditor_Window.cxx b/tools/PyEditor/src/PyEditor_Window.cxx
new file mode 100644 (file)
index 0000000..74c0be0
--- /dev/null
@@ -0,0 +1,467 @@
+// Copyright (C) 2015-2016  OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File   : PyEditor_Window.cxx
+// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
+//
+
+#include "PyEditor_Window.h"
+#include "PyEditor_Editor.h"
+#include "PyEditor_Settings.h"
+#include "PyEditor_SettingsDlg.h"
+
+#include <QAction>
+#include <QApplication>
+#include <QFileDialog>
+#include <QMenuBar>
+#include <QMessageBox>
+#include <QStatusBar>
+#include <QTextStream>
+#include <QToolBar>
+
+/*!
+  \class PyEditor_Window
+  \brief Python view window.
+*/
+
+/*!
+  \brief Constructor.
+  \param parent parent widget
+*/
+PyEditor_Window::PyEditor_Window( QWidget* parent ) :
+  QMainWindow( parent )
+{
+  Q_INIT_RESOURCE( PyEditor );
+
+  // Create editor and set it as a central widget.
+  myTextEditor = new PyEditor_Editor( this );
+  setCentralWidget( myTextEditor );
+
+  // Create actions.
+  QAction* action;
+
+  // . New
+  action = new QAction( QIcon( ":/images/py_new.png" ),
+                        tr( "ACT_NEW" ), this );
+  action->setToolTip( tr( "TTP_NEW" ) );
+  action->setStatusTip( tr( "DSC_NEW" ) );
+  action->setShortcut( QKeySequence::New );
+  connect( action, SIGNAL( triggered( bool ) ), this, SLOT( onNew() ) );
+  myActions[ NewId ] = action;
+
+  // . Open
+  action = new QAction( QIcon( ":/images/py_open.png" ),
+                        tr( "ACT_OPEN" ), this );
+  action->setToolTip( tr( "TTP_OPEN" ) );
+  action->setStatusTip( tr( "DSC_OPEN" ) );
+  action->setShortcut( QKeySequence::Open );
+  connect( action, SIGNAL( triggered( bool ) ), this, SLOT( onOpen() ) );
+  myActions[ OpenId ] = action;
+
+  // . Save
+  action = new QAction( QIcon( ":/images/py_save.png" ),
+                        tr( "ACT_SAVE" ), this );
+  action->setToolTip( tr( "TTP_SAVE" ) );
+  action->setStatusTip( tr( "DSC_SAVE" ) );
+  action->setShortcut( QKeySequence::Save );
+  connect( action, SIGNAL( triggered( bool ) ), this, SLOT( onSave() ) );
+  action->setEnabled( false );
+  connect( myTextEditor->document(), SIGNAL( modificationChanged( bool ) ),
+           action, SLOT( setEnabled( bool ) ) );
+  myActions[ SaveId ] = action;
+
+  // . SaveAs
+  action = new QAction( QIcon( ":/images/py_save_as.png" ),
+                        tr( "ACT_SAVEAS" ), this );
+  action->setToolTip( tr( "TTP_SAVEAS" ) );
+  action->setStatusTip( tr( "DSC_SAVEAS" ) );
+  action->setShortcut( QKeySequence::SaveAs );
+  connect( action, SIGNAL( triggered( bool ) ), this, SLOT( onSaveAs() ) );
+  myActions[ SaveAsId ] = action;
+
+  // . Exit
+  action = new QAction( QIcon( ":/images/py_exit.png" ),
+                        tr( "ACT_EXIT" ), this );
+  action->setToolTip( tr( "TTP_EXIT" ) );
+  action->setStatusTip( tr( "DSC_EXIT" ) );
+  action->setShortcut( QKeySequence::Quit );
+  connect( action, SIGNAL( triggered( bool ) ), this, SLOT( close() ) );
+  myActions[ ExitId ] = action;
+
+  // . Undo
+  action = new QAction( QIcon( ":/images/py_undo.png" ),
+                        tr( "ACT_UNDO" ), this );
+  action->setToolTip( tr( "TTP_UNDO" ) );
+  action->setStatusTip( tr( "DSC_UNDO" ) );
+  action->setShortcut( QKeySequence::Undo );
+  connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( undo() ) );
+  action->setEnabled( false );
+  connect( myTextEditor->document(), SIGNAL( undoAvailable( bool ) ),
+           action, SLOT( setEnabled( bool ) ) );
+  myActions[ UndoId ] = action;
+
+  // . Redo
+  action = new QAction( QIcon( ":/images/py_redo.png" ),
+                        tr( "ACT_REDO" ), this );
+  action->setToolTip( tr( "TTP_REDO" ) );
+  action->setStatusTip( tr( "DSC_REDO" ) );
+  action->setShortcut( QKeySequence::Redo );
+  connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( redo() ) );
+  action->setEnabled( false );
+  connect( myTextEditor->document(), SIGNAL( redoAvailable( bool ) ),
+           action, SLOT( setEnabled( bool ) ) );
+  myActions[ RedoId ] = action;
+
+  // . Cut
+  action = new QAction( QIcon( ":/images/py_cut.png" ),
+                        tr( "ACT_CUT" ), this );
+  action->setToolTip( tr( "TTP_CUT" ) );
+  action->setStatusTip( tr( "DSC_CUT" ) );
+  action->setShortcut( QKeySequence::Cut );
+  connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( cut() ) );
+  action->setEnabled( false );
+  connect( myTextEditor, SIGNAL( copyAvailable( bool ) ),
+           action, SLOT( setEnabled( bool ) ) );
+  myActions[ CutId ] = action;
+
+  // . Copy
+  action = new QAction( QIcon( ":/images/py_copy.png" ),
+                        tr( "ACT_COPY" ), this );
+  action->setToolTip( tr( "TTP_COPY" ) );
+  action->setStatusTip( tr( "DSC_COPY" ) );
+  action->setShortcut( QKeySequence::Copy );
+  connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( copy() ) );
+  action->setEnabled( false );
+  connect( myTextEditor, SIGNAL( copyAvailable( bool ) ),
+           action, SLOT( setEnabled( bool ) ) );
+  myActions[ CopyId ] = action;
+
+  // . Paste
+  action = new QAction( QIcon( ":/images/py_paste.png" ),
+                        tr( "ACT_PASTE" ), this );
+  action->setToolTip( tr( "TTP_PASTE" ) );
+  action->setStatusTip( tr( "DSC_PASTE" ) );
+  action->setShortcut( QKeySequence::Paste );
+  connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( paste() ) );
+  myActions[ PasteId ] = action;
+
+  // . Delete
+  action = new QAction( QIcon( ":/images/py_delete.png" ),
+                        tr( "ACT_DELETE" ), this );
+  action->setToolTip( tr( "TTP_DELETE" ) );
+  action->setStatusTip( tr( "DSC_DELETE" ) );
+  action->setShortcut( QKeySequence::Delete );
+  connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( deleteSelected() ) );
+  action->setEnabled( false );
+  connect( myTextEditor, SIGNAL( copyAvailable( bool ) ),
+           action, SLOT( setEnabled( bool ) ) );
+  myActions[ DeleteId ] = action;
+
+  // . SelectAll
+  action = new QAction( QIcon( ":/images/py_select_all.png" ),
+                        tr( "ACT_SELECT_ALL" ), this );
+  action->setToolTip( tr( "TTP_SELECT_ALL" ) );
+  action->setStatusTip( tr( "DSC_SELECT_ALL" ) );
+  action->setShortcut( QKeySequence::SelectAll );
+  connect( action, SIGNAL( triggered( bool ) ), myTextEditor, SLOT( selectAll() ) );
+  myActions[ SelectAllId ] = action;
+
+  // . Preferences
+  action = new QAction( QIcon( ":/images/py_preferences.png" ),
+                        tr( "ACT_PREFERENCES" ), this );
+  action->setToolTip( tr( "TTP_PREFERENCES" ) );
+  action->setStatusTip( tr( "DSC_PREFERENCES" ) );
+  connect( action, SIGNAL( triggered( bool ) ), this, SLOT( onPreferences() ) );
+  myActions[ PreferencesId ] = action;
+
+  // . Help
+  action = new QAction( QIcon( ":/images/py_help.png" ),
+                        tr( "ACT_HELP" ), this );
+  action->setToolTip( tr( "TTP_HELP" ) );
+  action->setStatusTip( tr( "DSC_HELP" ) );
+  connect( action, SIGNAL( triggered() ), this, SLOT( onHelp() ) );
+  myActions[ HelpId ] = action;
+
+  // Create menu.
+  QMenu* menu = menuBar()->addMenu( tr( "MNU_FILE" ) );
+  menu->addAction( myActions[ NewId ] );
+  menu->addAction( myActions[ OpenId ] );
+  menu->addSeparator();
+  menu->addAction( myActions[ SaveId ] );
+  menu->addAction( myActions[ SaveAsId ] );
+  menu->addSeparator();
+  menu->addAction( myActions[ ExitId ] );
+
+  menu = menuBar()->addMenu( tr( "MNU_EDIT" ) );
+  menu->addAction( myActions[ UndoId ] );
+  menu->addAction( myActions[ RedoId ] );
+  menu->addSeparator();
+  menu->addAction( myActions[ CutId ] );
+  menu->addAction( myActions[ CopyId ] );
+  menu->addAction( myActions[ PasteId ] );
+  menu->addAction( myActions[ DeleteId ] );
+  menu->addSeparator();
+  menu->addAction( myActions[ SelectAllId ] );
+  menu->addSeparator();
+  menu->addAction( myActions[ PreferencesId ] );
+
+  menu = menuBar()->addMenu( tr( "MNU_HELP" ) );
+  menu->addAction( myActions[ HelpId ] );
+
+  // Create toolbar.
+  QToolBar* toolbar = addToolBar( tr( "TOOLBAR_LABEL" ) );
+  toolbar->setObjectName("PythonEditor");
+  toolbar->addAction( myActions[ NewId ] );
+  toolbar->addAction( myActions[ OpenId ] );
+  toolbar->addAction( myActions[ SaveId ] );
+  toolbar->addAction( myActions[ SaveAsId ] );
+  toolbar->addSeparator();
+  toolbar->addAction( myActions[ ExitId ] );
+  toolbar->addSeparator();
+  toolbar->addAction( myActions[ UndoId ] );
+  toolbar->addAction( myActions[ RedoId ] );
+  toolbar->addSeparator();
+  toolbar->addAction( myActions[ CutId ] );
+  toolbar->addAction( myActions[ CopyId ] );
+  toolbar->addAction( myActions[ PasteId ] );
+  toolbar->addAction( myActions[ DeleteId ] );
+  toolbar->addAction( myActions[ SelectAllId ] );
+  toolbar->addSeparator();
+  toolbar->addAction( myActions[ PreferencesId ] );
+  toolbar->addSeparator();
+  toolbar->addAction( myActions[ HelpId ] );
+
+  // Set current file.
+  setCurrentFile( QString() );
+
+  // Additional set-up for main window.
+  connect( myTextEditor->document(), SIGNAL( modificationChanged( bool ) ),
+           this, SLOT( setWindowModified( bool ) ) );
+
+  // Initialize status bar.
+  statusBar()->showMessage( tr( "STS_READY" ) );
+}
+
+/*!
+  \brief Destructor.
+*/
+PyEditor_Window::~PyEditor_Window()
+{
+}
+
+/*!
+  \brief Manage window close request.
+  \param event close event
+*/
+void PyEditor_Window::closeEvent( QCloseEvent* event )
+{
+  if ( whetherSave() )
+    event->accept();
+  else
+    event->ignore();
+}
+
+/*!
+  SLOT: Create new document
+*/
+void PyEditor_Window::onNew()
+{
+  if ( whetherSave() )
+  {
+    myTextEditor->clear();
+    setCurrentFile( QString() );
+  }
+}
+
+/*!
+  SLOT: Open existing Python file
+*/
+void PyEditor_Window::onOpen()
+{
+  if ( whetherSave() )
+  {
+    QString filter = tr( "TIT_PY_FILES" );
+    filter += " (*.py)";
+    QString aFilePath = QFileDialog::getOpenFileName( this,
+                                                      tr( "TIT_DLG_OPEN" ),
+                                                      QDir::currentPath(),
+                                                      filter );
+
+    if ( !aFilePath.isEmpty() )
+      loadFile( aFilePath );
+  }
+}
+
+/*!
+  SLOT: Save current document
+*/
+bool PyEditor_Window::onSave()
+{
+  if ( myURL.isEmpty() )
+    return onSaveAs();
+  else
+    return saveFile( myURL );
+}
+
+
+/*!
+  SLOT: Save current document under a new name
+*/
+bool PyEditor_Window::onSaveAs()
+{
+  QString filter = tr( "TIT_PY_FILES" );
+  filter += " (*.py)";
+  QString url = myURL.isEmpty() ? defaultName() : myURL;
+  QString aFilePath = QFileDialog::getSaveFileName( this,
+                                                    tr( "TIT_DLG_SAVE" ),
+                                                    url,
+                                                    filter );
+
+  if ( !aFilePath.isEmpty() )
+    return saveFile( aFilePath );
+
+  return false;
+}
+
+/*!
+  SLOT: Open preferences dialog
+*/
+void PyEditor_Window::onPreferences()
+{
+  PyEditor_SettingsDlg dlg( myTextEditor, true, this );
+  connect( &dlg, SIGNAL( help() ), this, SLOT( onHelp() ) );
+  dlg.exec();
+}
+
+/*!
+  \brief Associate \a filePath with the current document
+  \param filePath document's file path
+*/
+void PyEditor_Window::setCurrentFile( const QString& filePath )
+{
+  myURL = filePath;
+  myTextEditor->document()->setModified( false );
+
+  setWindowModified( false );
+
+  setWindowFilePath( myURL.isEmpty() ? defaultName() : myURL );
+}
+
+/*!
+  \brief Check whether the file is modified.
+  If it has the modifications then ask the user to save it.
+  \return true if the document is saved.
+*/
+bool PyEditor_Window::whetherSave()
+{
+  if ( myTextEditor->document()->isModified() )
+  {
+    QMessageBox::StandardButton answer =  QMessageBox::warning( this,
+                                                                tr( "NAME_PYEDITOR" ),
+                                                                tr( "WRN_SAVE_FILE" ),
+                                                                QMessageBox::Save |
+                                                                QMessageBox::Discard |
+                                                                QMessageBox::Cancel );
+    switch( answer )
+    {
+    case QMessageBox::Save:
+      return onSave();
+    case QMessageBox::Cancel:
+      return false;
+    default:
+      break;
+    }
+  }
+  return true;
+}
+
+/*!
+  \brief Open file.
+  \param filePath file path
+*/
+void PyEditor_Window::loadFile( const QString& filePath )
+{
+  QFile aFile( filePath );
+  if ( !aFile.open(QFile::ReadOnly | QFile::Text) )
+  {
+    QMessageBox::warning( this, tr( "NAME_PYEDITOR" ),
+                          tr( "WRN_READ_FILE" ).arg( filePath ).arg( aFile.errorString() ) );
+    return;
+  }
+
+  QTextStream anInput( &aFile );
+  QApplication::setOverrideCursor( Qt::WaitCursor );
+  myTextEditor->setPlainText( anInput.readAll() );
+  QApplication::restoreOverrideCursor();
+
+  setCurrentFile( filePath );
+  aFile.close();
+
+  statusBar()->showMessage( tr( "STS_F_LOADED" ), 2000 );
+}
+
+/*!
+  \brief Save file.
+  \param filePath file path
+*/
+bool PyEditor_Window::saveFile( const QString& filePath )
+{
+  QFile aFile( filePath );
+  if ( !aFile.open( QFile::WriteOnly | QFile::Text ) )
+  {
+    QMessageBox::warning( this, tr( "NAME_PYEDITOR" ),
+                          tr( "WRN_WRITE_FILE" ).arg( filePath ).arg( aFile.errorString() ) );
+    return false;
+  }
+
+  QTextStream anOutput( &aFile );
+  QApplication::setOverrideCursor( Qt::WaitCursor );
+  anOutput << myTextEditor->toPlainText();
+  QApplication::restoreOverrideCursor();
+
+  setCurrentFile( filePath );
+  aFile.close();
+
+  statusBar()->showMessage( tr( "STS_F_SAVED" ), 2000 );
+
+  return true;
+}
+
+/*!
+  Slot, called when user clicks "Help" button in "Preferences" dialog box.
+*/
+void PyEditor_Window::onHelp()
+{
+  QWidget* w = qobject_cast<QWidget*>( sender() );
+  if ( !w ) w = this;
+  QFile file(":/about.txt");
+  file.open(QFile::ReadOnly | QFile::Text);
+  QTextStream stream( &file );
+  QString about = stream.readAll();
+  file.close();
+  QMessageBox::about( w, tr( "NAME_PYEDITOR" ), about );
+}
+
+/*!
+  Get default name for Python file 
+  \return default name
+*/
+QString PyEditor_Window::defaultName() const
+{
+  return tr( "NONAME" );
+}
diff --git a/tools/PyEditor/src/PyEditor_Window.h b/tools/PyEditor/src/PyEditor_Window.h
new file mode 100644 (file)
index 0000000..209739e
--- /dev/null
@@ -0,0 +1,71 @@
+// Copyright (C) 2015-2016  OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File   : PyEditor_Window.h
+// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
+//
+
+#ifndef PYEDITOR_WINDOW_H
+#define PYEDITOR_WINDOW_H
+
+#include "PyEditor.h"
+
+#include <QMainWindow>
+#include <QMap>
+
+class QAction;
+class PyEditor_Editor;
+
+class PYEDITOR_EXPORT PyEditor_Window : public QMainWindow
+{
+  Q_OBJECT
+
+public:
+  enum { NewId, OpenId, SaveId, SaveAsId, ExitId,
+         UndoId, RedoId, CutId, CopyId, PasteId, DeleteId, SelectAllId,
+         PreferencesId, HelpId };
+
+  PyEditor_Window( QWidget* = 0 );
+  ~PyEditor_Window();
+
+protected:
+  virtual void closeEvent( QCloseEvent* );
+
+private Q_SLOTS:
+  void        onNew();
+  void        onOpen();
+  bool        onSave();
+  bool        onSaveAs();
+  void        onPreferences();
+  void        onHelp();
+
+private:
+  void        loadFile( const QString& );
+  bool        saveFile( const QString& );
+  
+  void        setCurrentFile( const QString& );
+  bool        whetherSave();
+  QString     defaultName() const;
+
+private:
+  PyEditor_Editor*    myTextEditor;
+  QString             myURL;
+  QMap<int, QAction*> myActions;
+};
+
+#endif // PYEDITOR_WINDOW_H
diff --git a/tools/PyEditor/src/python/CMakeLists.txt b/tools/PyEditor/src/python/CMakeLists.txt
new file mode 100644 (file)
index 0000000..fcde6e1
--- /dev/null
@@ -0,0 +1,62 @@
+# Copyright (C) 2015-2016  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 : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
+#
+
+INCLUDE(UseQtExt)
+INCLUDE(UsePyQt)
+
+# --- options ---
+
+# additional include directories
+INCLUDE_DIRECTORIES(
+  $(QT_INCLUDES)
+  ${PYTHON_INCLUDE_DIRS}
+  ${SIP_INCLUDE_DIR}
+  ${PROJECT_BINARY_DIR}
+  ${CMAKE_CURRENT_SOURCE_DIR}/..
+)
+
+# additional preprocessor / compiler flags
+ADD_DEFINITIONS(${QT_DEFINITIONS})
+
+# libraries to link to
+SET(_link_LIBRARIES ${QT_LIBRARIES} ${PYTHON_LIBRARIES} PyEditor)
+
+# --- sources ---
+
+# sip files / to be processed by sip
+SET(_sip_files PyEditorPy.sip)
+
+# sources / sip wrappings
+PYQT_WRAP_SIP(_sip_SOURCES ${_sip_files})
+
+# sources / to compile
+SET(PyEditorPy_SOURCES ${_sip_SOURCES})
+
+# --- rules ---
+
+ADD_LIBRARY(PyEditorPy ${PyEditorPy_SOURCES})
+IF(WIN32)
+  SET_TARGET_PROPERTIES(PyEditorPy PROPERTIES SUFFIX ".pyd" DEBUG_OUTPUT_NAME PyEditorPy_d RELEASE_OUTPUT_NAME PyEditorPy)
+ELSE()
+  SET_TARGET_PROPERTIES(PyEditorPy PROPERTIES PREFIX "")
+ENDIF()
+TARGET_LINK_LIBRARIES(PyEditorPy ${_link_LIBRARIES})
+INSTALL(TARGETS PyEditorPy EXPORT ${TOOLS_EXPORT_NAME}TargetGroup DESTINATION ${PYEDITOR_INSTALL_LIBS})
diff --git a/tools/PyEditor/src/python/PyEditorPy.sip b/tools/PyEditor/src/python/PyEditorPy.sip
new file mode 100644 (file)
index 0000000..372cc28
--- /dev/null
@@ -0,0 +1,98 @@
+// Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File   : SalomePyQt.sip
+// Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
+//
+
+%Module PyEditorPy
+
+%Import QtCore/QtCoremod.sip
+%Import QtGui/QtGuimod.sip
+%If (Qt_5_0_0 -)
+%Import QtWidgets/QtWidgetsmod.sip
+%End
+
+class PyEditor_Settings
+{
+%TypeHeaderCode
+#include <PyEditor_Settings.h>
+%End
+
+public:
+  PyEditor_Settings();
+
+  void setHighlightCurrentLine( bool );
+  bool highlightCurrentLine() const;
+
+  void setTextWrapping( bool );
+  bool textWrapping() const;
+
+  void setCenterCursorOnScroll( bool );
+  bool centerCursorOnScroll() const;
+
+  void setLineNumberArea( bool );
+  bool lineNumberArea() const;
+
+  void setVerticalEdge( bool );
+  bool verticalEdge() const;
+
+  void setNumberColumns( int );
+  int numberColumns() const;
+
+  void setTabSpaceVisible( bool );
+  bool tabSpaceVisible() const;
+
+  void setTabSize( int );
+  int tabSize() const;
+
+  void setFont( const QFont& );
+  QFont font() const;
+};
+
+class PyEditor_Editor : QPlainTextEdit
+{ 
+%TypeHeaderCode
+#include <PyEditor_Editor.h>
+%End
+
+public:
+  explicit PyEditor_Editor( QWidget* /TransferThis/ = 0 );
+  virtual ~PyEditor_Editor();
+
+  void setSettings( const PyEditor_Settings& );
+  const PyEditor_Settings& settings() const;
+  QString text() const;
+
+public slots:
+  void deleteSelected();
+  void append( const QString& );  
+  void setText( const QString& text );
+
+protected:
+  virtual void keyPressEvent( QKeyEvent* );
+  virtual void resizeEvent( QResizeEvent* );
+  virtual void paintEvent( QPaintEvent* );
+
+private:
+  PyEditor_Editor( const PyEditor_Editor& );
+  PyEditor_Editor& operator=( const PyEditor_Editor& );
+};
diff --git a/tools/PyEditor/src/resources/PyEditor.qrc b/tools/PyEditor/src/resources/PyEditor.qrc
new file mode 100644 (file)
index 0000000..7df3d32
--- /dev/null
@@ -0,0 +1,20 @@
+<!DOCTYPE RCC><RCC version="1.0">
+  <qresource>
+    <file>images/py_copy.png</file>
+    <file>images/py_cut.png</file>
+    <file>images/py_delete.png</file>
+    <file>images/py_editor.png</file>
+    <file>images/py_exit.png</file>
+    <file>images/py_help.png</file>
+    <file>images/py_new.png</file>
+    <file>images/py_open.png</file>
+    <file>images/py_paste.png</file>
+    <file>images/py_preferences.png</file>
+    <file>images/py_redo.png</file>
+    <file>images/py_save.png</file>
+    <file>images/py_save_as.png</file>
+    <file>images/py_select_all.png</file>
+    <file>images/py_undo.png</file>
+    <file>about.txt</file>
+  </qresource>
+</RCC>
diff --git a/tools/PyEditor/src/resources/about.txt b/tools/PyEditor/src/resources/about.txt
new file mode 100644 (file)
index 0000000..8fe8dc6
--- /dev/null
@@ -0,0 +1,36 @@
+<b>Python Editor</b>
+<hr>
+
+Python Editor is a simple program for writing Python scripts.
+Program provides standard editing operations like copy/cut/paste, undo/redo, select all, delete, etc.
+Also it supports syntax highlighting and auto-indentation of Python code.
+
+Most often used editing operations are available via the toolbar:
+<ul>
+<li><b>New</b>: creates new document.</li>
+<li><b>Open</b>: opens existing Python script for editing.</li>
+<li><b>Save</b>: saves current document to a file.</li>
+<li><b>Save As</b>: allows saving current document with a new name.</li>
+<li><b>Exit</b>: quits application.</li>
+<li><b>Undo</b>: undoes the last operation.</li>
+<li><b>Redo</b>: redoes the previously undone operation.</li>
+<li><b>Cut</b>: cuts selected text into the clipboard.</li>
+<li><b>Copy</b>: copies selected text into the clipboard.</li>
+<li><b>Paste</b>: pastes text from the clipboard into the current cursor position.</li>
+<li><b>Delete</b>: removes selected text.</li>
+<li><b>Select All</b>: selects the whole text in the editor.</li>
+<li><b>Preferences</b>: opens Preferences dialog that allows specifying advanced parameters for the program.</li>
+<li><b>Help</b>: shows this help information.</li>
+</ul>
+
+The behavior of the editor can be customized via the <b>Preferences</b> dialog. The following options can be customized:
+<ul>
+<li><b>Font settings</b>: choose the font.</li>
+<li><b>Enable current line highlight</b>: switches on background coloring of the line under the cursor.</li>
+<li><b>Enable text wrapping</b>: allows wrapping text at the border of the editor's window.</li>
+<li><b>Center cursor on scroll</b>: allows scrolling the script vertically to make the cursor visible at the center of the viewer.</li>
+<li><b>Display line numbers area</b>: shows line numbers at the left border of the editor.</li>
+<li><b>Vertical edge settings</b>: draws vertical line at the specified column of the viewer.</li>
+<li><b>Display tab white spaces</b>: displays tab indentations at a given number of white spaces.</li>
+<li><b>Save settings as default</b>: saves chosen options as a default ones. These settings will be restored after application restart.</li>
+</ul>
diff --git a/tools/PyEditor/src/resources/images/py_copy.png b/tools/PyEditor/src/resources/images/py_copy.png
new file mode 100644 (file)
index 0000000..385b2c4
Binary files /dev/null and b/tools/PyEditor/src/resources/images/py_copy.png differ
diff --git a/tools/PyEditor/src/resources/images/py_cut.png b/tools/PyEditor/src/resources/images/py_cut.png
new file mode 100644 (file)
index 0000000..77edc8a
Binary files /dev/null and b/tools/PyEditor/src/resources/images/py_cut.png differ
diff --git a/tools/PyEditor/src/resources/images/py_delete.png b/tools/PyEditor/src/resources/images/py_delete.png
new file mode 100644 (file)
index 0000000..38581d1
Binary files /dev/null and b/tools/PyEditor/src/resources/images/py_delete.png differ
diff --git a/tools/PyEditor/src/resources/images/py_editor.png b/tools/PyEditor/src/resources/images/py_editor.png
new file mode 100644 (file)
index 0000000..183e139
Binary files /dev/null and b/tools/PyEditor/src/resources/images/py_editor.png differ
diff --git a/tools/PyEditor/src/resources/images/py_exit.png b/tools/PyEditor/src/resources/images/py_exit.png
new file mode 100644 (file)
index 0000000..52efbf0
Binary files /dev/null and b/tools/PyEditor/src/resources/images/py_exit.png differ
diff --git a/tools/PyEditor/src/resources/images/py_help.png b/tools/PyEditor/src/resources/images/py_help.png
new file mode 100644 (file)
index 0000000..6fb0c81
Binary files /dev/null and b/tools/PyEditor/src/resources/images/py_help.png differ
diff --git a/tools/PyEditor/src/resources/images/py_new.png b/tools/PyEditor/src/resources/images/py_new.png
new file mode 100644 (file)
index 0000000..2a39dff
Binary files /dev/null and b/tools/PyEditor/src/resources/images/py_new.png differ
diff --git a/tools/PyEditor/src/resources/images/py_open.png b/tools/PyEditor/src/resources/images/py_open.png
new file mode 100644 (file)
index 0000000..26e0a2c
Binary files /dev/null and b/tools/PyEditor/src/resources/images/py_open.png differ
diff --git a/tools/PyEditor/src/resources/images/py_paste.png b/tools/PyEditor/src/resources/images/py_paste.png
new file mode 100644 (file)
index 0000000..09cae75
Binary files /dev/null and b/tools/PyEditor/src/resources/images/py_paste.png differ
diff --git a/tools/PyEditor/src/resources/images/py_preferences.png b/tools/PyEditor/src/resources/images/py_preferences.png
new file mode 100644 (file)
index 0000000..f8c4c05
Binary files /dev/null and b/tools/PyEditor/src/resources/images/py_preferences.png differ
diff --git a/tools/PyEditor/src/resources/images/py_redo.png b/tools/PyEditor/src/resources/images/py_redo.png
new file mode 100644 (file)
index 0000000..8e685b6
Binary files /dev/null and b/tools/PyEditor/src/resources/images/py_redo.png differ
diff --git a/tools/PyEditor/src/resources/images/py_save.png b/tools/PyEditor/src/resources/images/py_save.png
new file mode 100644 (file)
index 0000000..7a70c34
Binary files /dev/null and b/tools/PyEditor/src/resources/images/py_save.png differ
diff --git a/tools/PyEditor/src/resources/images/py_save_as.png b/tools/PyEditor/src/resources/images/py_save_as.png
new file mode 100644 (file)
index 0000000..4cb1147
Binary files /dev/null and b/tools/PyEditor/src/resources/images/py_save_as.png differ
diff --git a/tools/PyEditor/src/resources/images/py_select_all.png b/tools/PyEditor/src/resources/images/py_select_all.png
new file mode 100644 (file)
index 0000000..d7b1c73
Binary files /dev/null and b/tools/PyEditor/src/resources/images/py_select_all.png differ
diff --git a/tools/PyEditor/src/resources/images/py_undo.png b/tools/PyEditor/src/resources/images/py_undo.png
new file mode 100644 (file)
index 0000000..d6701f5
Binary files /dev/null and b/tools/PyEditor/src/resources/images/py_undo.png differ
diff --git a/tools/PyEditor/src/resources/translations/PyEditor_msg_en.ts b/tools/PyEditor/src/resources/translations/PyEditor_msg_en.ts
new file mode 100644 (file)
index 0000000..ed2e321
--- /dev/null
@@ -0,0 +1,310 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="en">
+  <context>
+    <name>PyEditor_SettingsDlg</name>
+    <message>
+      <source>TIT_PREFERENCES</source>
+      <translation>Preferences</translation>
+    </message>
+    <message>
+      <source>GR_FONT_SET</source>
+      <translation>Font settings</translation>
+    </message>
+    <message>
+      <source>GR_DISP_SET</source>
+      <translation>Display settings</translation>
+    </message>
+    <message>
+      <source>LBL_CURRLINE_HIGHLIGHT</source>
+      <translation>Enable current line highlight</translation>
+    </message>
+    <message>
+      <source>LBL_TEXT_WRAP</source>
+      <translation>Enable text wrapping</translation>
+    </message>
+    <message>
+      <source>LBL_CURSOR_SCROLL</source>
+      <translation>Center cursor on scroll</translation>
+    </message>
+    <message>
+      <source>LBL_LINE_NUMBS_AREA</source>
+      <translation>Display line numbers area</translation>
+    </message>
+    <message>
+      <source>GR_TAB_SET</source>
+      <translation>Tab settings</translation>
+    </message>
+    <message>
+      <source>LBL_TAB_SPACES</source>
+      <translation>Display tab white spaces</translation>
+    </message>
+    <message>
+      <source>LBL_TAB_SIZE</source>
+      <translation>Tab size:</translation>
+    </message>
+    <message>
+      <source>GR_VERT_EDGE_SET</source>
+      <translation>Vertical edge settings</translation>
+    </message>
+    <message>
+      <source>LBL_VERT_EDGE</source>
+      <translation>Display vertical edge</translation>
+    </message>
+    <message>
+      <source>LBL_NUM_COLUMNS</source>
+      <translation>Number of columns:</translation>
+    </message>
+    <message>
+      <source>WDG_SET_AS_DEFAULT_CHECK</source>
+      <translation>Save settings as default</translation>
+    </message>
+    <message>
+      <source>BUT_OK</source>
+      <translation>&amp;OK</translation>
+    </message>
+    <message>
+      <source>BUT_DEFAULTS</source>
+      <translation>&amp;Defaults</translation>
+    </message>
+    <message>
+      <source>BUT_CANCEL</source>
+      <translation>&amp;Cancel</translation>
+    </message>
+    <message>
+      <source>BUT_HELP</source>
+      <translation>&amp;Help</translation>
+    </message>
+  </context>
+  <context>
+    <name>PyEditor_Window</name>
+    <message>
+      <source>NAME_PYEDITOR</source>
+      <translation>Python Editor</translation>
+    </message>
+    <message>
+      <source>ACT_NEW</source>
+      <translation>&amp;New</translation>
+    </message>
+    <message>
+      <source>TTP_NEW</source>
+      <translation>New</translation>
+    </message>
+    <message>
+      <source>DSC_NEW</source>
+      <translation>Create new document</translation>
+    </message>
+    <message>
+      <source>ACT_OPEN</source>
+      <translation>&amp;Open...</translation>
+    </message>
+    <message>
+      <source>TTP_OPEN</source>
+      <translation>Open</translation>
+    </message>
+    <message>
+      <source>DSC_OPEN</source>
+      <translation>Open an existing document</translation>
+    </message>
+    <message>
+      <source>ACT_SAVE</source>
+      <translation>&amp;Save</translation>
+    </message>
+    <message>
+      <source>TTP_SAVE</source>
+      <translation>Save</translation>
+    </message>
+    <message>
+      <source>DSC_SAVE</source>
+      <translation>Save the document to a file</translation>
+    </message>
+    <message>
+      <source>ACT_SAVEAS</source>
+      <translation>Save &amp;As...</translation>
+    </message>
+    <message>
+      <source>TTP_SAVEAS</source>
+      <translation>Save As</translation>
+    </message>
+    <message>
+      <source>DSC_SAVEAS</source>
+      <translation>Save the document to a file with the new name</translation>
+    </message>
+    <message>
+      <source>ACT_EXIT</source>
+      <translation>E&amp;xit</translation>
+    </message>
+    <message>
+      <source>TTP_EXIT</source>
+      <translation>Exit</translation>
+    </message>
+    <message>
+      <source>DSC_EXIT</source>
+      <translation>Exit application</translation>
+    </message>
+    <message>
+      <source>ACT_UNDO</source>
+      <translation>&amp;Undo</translation>
+    </message>
+    <message>
+      <source>TTP_UNDO</source>
+      <translation>Undo</translation>
+    </message>
+    <message>
+      <source>DSC_UNDO</source>
+      <translation>Undo last operation</translation>
+    </message>
+    <message>
+      <source>ACT_REDO</source>
+      <translation>&amp;Redo</translation>
+    </message>
+    <message>
+      <source>TTP_REDO</source>
+      <translation>Redo</translation>
+    </message>
+    <message>
+      <source>DSC_REDO</source>
+      <translation>Redo last undone operation</translation>
+    </message>
+    <message>
+      <source>ACT_CUT</source>
+      <translation>Cu&amp;t</translation>
+    </message>
+    <message>
+      <source>TTP_CUT</source>
+      <translation>Cut</translation>
+    </message>
+    <message>
+      <source>DSC_CUT</source>
+      <translation>Cut the current selection&apos;s contents to the clipboard</translation>
+    </message>
+    <message>
+      <source>ACT_COPY</source>
+      <translation>&amp;Copy</translation>
+    </message>
+    <message>
+      <source>TTP_COPY</source>
+      <translation>Copy</translation>
+    </message>
+    <message>
+      <source>DSC_COPY</source>
+      <translation>Copy the current selection&apos;s contents to the clipboard</translation>
+    </message>
+    <message>
+      <source>ACT_PASTE</source>
+      <translation>&amp;Paste</translation>
+    </message>
+    <message>
+      <source>TTP_PASTE</source>
+      <translation>Paste</translation>
+    </message>
+    <message>
+      <source>DSC_PASTE</source>
+      <translation>Paste the clipboard&apos;s contents into the current selection</translation>
+    </message>
+    <message>
+      <source>ACT_DELETE</source>
+      <translation>&amp;Delete</translation>
+    </message>
+    <message>
+      <source>TTP_DELETE</source>
+      <translation>Delete</translation>
+    </message>
+    <message>
+      <source>DSC_DELETE</source>
+      <translation>Delete the current selection&apos;s contents</translation>
+    </message>
+    <message>
+      <source>ACT_SELECT_ALL</source>
+      <translation>Select &amp;All</translation>
+    </message>
+    <message>
+      <source>TTP_SELECT_ALL</source>
+      <translation>Select All</translation>
+    </message>
+    <message>
+      <source>DSC_SELECT_ALL</source>
+      <translation>Select all the contents</translation>
+    </message>
+    <message>
+      <source>ACT_PREFERENCES</source>
+      <translation>Pre&amp;ferences</translation>
+    </message>
+    <message>
+      <source>TTP_PREFERENCES</source>
+      <translation>Preferences</translation>
+    </message>
+    <message>
+      <source>DSC_PREFERENCES</source>
+      <translation>Show the Preferences dialog</translation>
+    </message>
+    <message>
+      <source>ACT_HELP</source>
+      <translation>&amp;Help</translation>
+    </message>
+    <message>
+      <source>TTP_HELP</source>
+      <translation>Help</translation>
+    </message>
+    <message>
+      <source>DSC_HELP</source>
+      <translation>Show the help on the Python Editor</translation>
+    </message>
+    <message>
+      <source>MNU_FILE</source>
+      <translation>&amp;File</translation>
+    </message>
+    <message>
+      <source>MNU_EDIT</source>
+      <translation>&amp;Edit</translation>
+    </message>
+    <message>
+      <source>MNU_HELP</source>
+      <translation>&amp;Help</translation>
+    </message>
+    <message>
+      <source>TOOLBAR_LABEL</source>
+      <translation>Edit Operations</translation>
+    </message>
+    <message>
+      <source>TIT_PY_FILES</source>
+      <translation>Python files</translation>
+    </message>
+    <message>
+      <source>TIT_DLG_OPEN</source>
+      <translation>Open file</translation>
+    </message>
+    <message>
+      <source>TIT_DLG_SAVE</source>
+      <translation>Save file</translation>
+    </message>
+    <message>
+      <source>WRN_SAVE_FILE</source>
+      <translation>The document has been modified.&lt;br&gt;Do you want to save changes?</translation>
+    </message>
+    <message>
+      <source>WRN_READ_FILE</source>
+      <translation>Cannot read file %1:\n%2.</translation>
+    </message>
+    <message>
+      <source>WRN_WRITE_FILE</source>
+      <translation>Cannot write file %1:\n%2.</translation>
+    </message>
+    <message>
+      <source>STS_READY</source>
+      <translation>Ready</translation>
+    </message>
+    <message>
+      <source>STS_F_LOADED</source>
+      <translation>Document is loaded</translation>
+    </message>
+    <message>
+      <source>STS_F_SAVED</source>
+      <translation>Document is saved</translation>
+    </message>
+    <message>
+      <source>NONAME</source>
+      <translation>Noname.py</translation>
+    </message>
+  </context>
+</TS>
diff --git a/tools/PyEditor/src/resources/translations/PyEditor_msg_fr.ts b/tools/PyEditor/src/resources/translations/PyEditor_msg_fr.ts
new file mode 100644 (file)
index 0000000..96cd1e0
--- /dev/null
@@ -0,0 +1,310 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="fr">
+  <context>
+    <name>PyEditor_SettingsDlg</name>
+    <message>
+      <source>TIT_PREFERENCES</source>
+      <translation>Préférences</translation>
+    </message>
+    <message>
+      <source>GR_FONT_SET</source>
+      <translation>Paramètres de la fonte</translation>
+    </message>
+    <message>
+      <source>GR_DISP_SET</source>
+      <translation>Paramètres d'affichage</translation>
+    </message>
+    <message>
+      <source>LBL_CURRLINE_HIGHLIGHT</source>
+      <translation>Met en surbrillance de la ligne actuelle</translation>
+    </message>
+    <message>
+      <source>LBL_TEXT_WRAP</source>
+      <translation>Retour à la ligne dynamique</translation>
+    </message>
+    <message>
+      <source>LBL_CURSOR_SCROLL</source>
+      <translation>Centre le curseur lors du scroll</translation>
+    </message>
+    <message>
+      <source>LBL_LINE_NUMBS_AREA</source>
+      <translation>Affiche les numéros de ligne</translation>
+    </message>
+    <message>
+      <source>GR_TAB_SET</source>
+      <translation>Indentation</translation>
+    </message>
+    <message>
+      <source>LBL_TAB_SPACES</source>
+      <translation>Affiche les guides d'indentation</translation>
+    </message>
+    <message>
+      <source>LBL_TAB_SIZE</source>
+      <translation>Largeur d'intentation:</translation>
+    </message>
+    <message>
+      <source>GR_VERT_EDGE_SET</source>
+      <translation>Marqueur de retour à la ligne</translation>
+    </message>
+    <message>
+      <source>LBL_VERT_EDGE</source>
+      <translation>Afficher la ligne verticale</translation>
+    </message>
+    <message>
+      <source>LBL_NUM_COLUMNS</source>
+      <translation>Nombre de colonnes:</translation>
+    </message>
+    <message>
+      <source>WDG_SET_AS_DEFAULT_CHECK</source>
+      <translation>Sauver en tant que paramètres par défaut</translation>
+    </message>
+    <message>
+      <source>BUT_OK</source>
+      <translation>&amp;OK</translation>
+    </message>
+    <message>
+      <source>BUT_DEFAULTS</source>
+      <translation>Défauts</translation>
+    </message>
+    <message>
+      <source>BUT_CANCEL</source>
+      <translation>&amp;Annuler</translation>
+    </message>
+    <message>
+      <source>BUT_HELP</source>
+      <translation>A&amp;ide</translation>
+    </message>
+  </context>
+  <context>
+    <name>PyEditor_Window</name>
+    <message>
+      <source>NAME_PYEDITOR</source>
+      <translation>Editeur python</translation>
+    </message>
+    <message>
+      <source>ACT_NEW</source>
+      <translation>Nouveau</translation>
+    </message>
+    <message>
+      <source>TTP_NEW</source>
+      <translation>Nouveau</translation>
+    </message>
+    <message>
+      <source>DSC_NEW</source>
+      <translation>Crée un nouveau fichier python</translation>
+    </message>
+    <message>
+      <source>ACT_OPEN</source>
+      <translation>Ouvrir</translation>
+    </message>
+    <message>
+      <source>TTP_OPEN</source>
+      <translation>Ouvrir</translation>
+    </message>
+    <message>
+      <source>DSC_OPEN</source>
+      <translation>Ouvre un fichier python existant</translation>
+    </message>
+    <message>
+      <source>ACT_SAVE</source>
+      <translation>Enregistrer</translation>
+    </message>
+    <message>
+      <source>TTP_SAVE</source>
+      <translation>Enregistrer</translation>
+    </message>
+    <message>
+      <source>DSC_SAVE</source>
+      <translation>Enregistre le fichier python sur le système de fichiers</translation>
+    </message>
+    <message>
+      <source>ACT_SAVEAS</source>
+      <translation>Enregistrer sous...</translation>
+    </message>
+    <message>
+      <source>TTP_SAVEAS</source>
+      <translation>Enregistrer sous...</translation>
+    </message>
+    <message>
+      <source>DSC_SAVEAS</source>
+      <translation>>Enregistre le fichier python sous un nouveau nom</translation>
+    </message>
+    <message>
+      <source>ACT_EXIT</source>
+      <translation>Fermer</translation>
+    </message>
+    <message>
+      <source>TTP_EXIT</source>
+      <translation>Fermer</translation>
+    </message>
+    <message>
+      <source>DSC_EXIT</source>
+      <translation>Ferme le fichier python</translation>
+    </message>
+    <message>
+      <source>ACT_UNDO</source>
+      <translation>Annuler</translation>
+    </message>
+    <message>
+      <source>TTP_UNDO</source>
+      <translation>Annuler</translation>
+    </message>
+    <message>
+      <source>DSC_UNDO</source>
+      <translation>Annule la dernière opération</translation>
+    </message>
+    <message>
+      <source>ACT_REDO</source>
+      <translation>Refaire</translation>
+    </message>
+    <message>
+      <source>TTP_REDO</source>
+      <translation>Refaire</translation>
+    </message>
+    <message>
+      <source>DSC_REDO</source>
+      <translation>Répète la dernière opération</translation>
+    </message>
+    <message>
+      <source>ACT_CUT</source>
+      <translation>Coupe</translation>
+    </message>
+    <message>
+      <source>TTP_CUT</source>
+      <translation>Coupe</translation>
+    </message>
+    <message>
+      <source>DSC_CUT</source>
+      <translation>Coupe le contenu de la sélection vers le presse-papier</translation>
+    </message>
+    <message>
+      <source>ACT_COPY</source>
+      <translation>Copier</translation>
+    </message>
+    <message>
+      <source>TTP_COPY</source>
+      <translation>Copier</translation>
+    </message>
+    <message>
+      <source>DSC_COPY</source>
+      <translation>Copie le contenu de la sélection vers le presse-papier</translation>
+    </message>
+    <message>
+      <source>ACT_PASTE</source>
+      <translation>Coller</translation>
+    </message>
+    <message>
+      <source>TTP_PASTE</source>
+      <translation>Coller</translation>
+    </message>
+    <message>
+      <source>DSC_PASTE</source>
+      <translation>Colle le contenu de la sélection vers le presse-papier</translation>
+    </message>
+    <message>
+      <source>ACT_DELETE</source>
+      <translation>Supprime</translation>
+    </message>
+    <message>
+      <source>TTP_DELETE</source>
+      <translation>Supprime</translation>
+    </message>
+    <message>
+      <source>DSC_DELETE</source>
+      <translation>Supprime le contenu de la sélection</translation>
+    </message>
+    <message>
+      <source>ACT_SELECT_ALL</source>
+      <translation>Sélectionner tout</translation>
+    </message>
+    <message>
+      <source>TTP_SELECT_ALL</source>
+      <translation>Sélectionner tout</translation>
+    </message>
+    <message>
+      <source>DSC_SELECT_ALL</source>
+      <translation>Sélectionne tout le contenu</translation>
+    </message>
+    <message>
+      <source>ACT_PREFERENCES</source>
+      <translation>Préférences</translation>
+    </message>
+    <message>
+      <source>TTP_PREFERENCES</source>
+      <translation>Préférences</translation>
+    </message>
+    <message>
+      <source>DSC_PREFERENCES</source>
+      <translation>Affiche la boîte de dialogue des préférences</translation>
+    </message>
+    <message>
+      <source>ACT_HELP</source>
+      <translation>Aide</translation>
+    </message>
+    <message>
+      <source>TTP_HELP</source>
+      <translation>Aide</translation>
+    </message>
+    <message>
+      <source>DSC_HELP</source>
+      <translation>Afficher l'aide</translation>
+    </message>
+    <message>
+      <source>MNU_FILE</source>
+      <translation>Fic&amp;hier</translation>
+    </message>
+    <message>
+      <source>MNU_EDIT</source>
+      <translation>&amp;Edition</translation>
+    </message>
+    <message>
+      <source>MNU_HELP</source>
+      <translation>A&amp;ide</translation>
+    </message>
+    <message>
+      <source>TOOLBAR_LABEL</source>
+      <translation>Opérations d'édition</translation>
+    </message>
+    <message>
+      <source>TIT_PY_FILES</source>
+      <translation>Fichiers Python</translation>
+    </message>
+    <message>
+      <source>TIT_DLG_OPEN</source>
+      <translation>Ouvrir le fichier</translation>
+    </message>
+    <message>
+      <source>TIT_DLG_SAVE</source>
+      <translation>Enregistrer le fichier</translation>
+    </message>
+    <message>
+      <source>WRN_SAVE_FILE</source>
+      <translation>Le document a été modifié.&lt;br&gt;Voulez-vous sauvegarder vos changements?</translation>
+    </message>
+    <message>
+      <source>WRN_READ_FILE</source>
+      <translation>Impossible de lire le fichier %1:\n%2.</translation>
+    </message>
+    <message>
+      <source>WRN_WRITE_FILE</source>
+      <translation>Impossible d'écrire le fichier %1:\n%2.</translation>
+    </message>
+    <message>
+      <source>STS_READY</source>
+      <translation>Prêt</translation>
+    </message>
+    <message>
+      <source>STS_F_LOADED</source>
+      <translation>Le fichier est chargé</translation>
+    </message>
+    <message>
+      <source>STS_F_SAVED</source>
+      <translation>Le fichier est sauvé</translation>
+    </message>
+    <message>
+      <source>NONAME</source>
+      <translation>Noname.py</translation>
+    </message>
+  </context>
+</TS>
diff --git a/tools/PyEditor/src/resources/translations/PyEditor_msg_ja.ts b/tools/PyEditor/src/resources/translations/PyEditor_msg_ja.ts
new file mode 100644 (file)
index 0000000..6851ed7
--- /dev/null
@@ -0,0 +1,310 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE TS>
+<TS version="2.0" language="ja" sourcelanguage="en">
+  <context>
+    <name>PyEditor_SettingsDlg</name>
+    <message>
+      <source>TIT_PREFERENCES</source>
+      <translation>環境設定</translation>
+    </message>
+    <message>
+      <source>GR_FONT_SET</source>
+      <translation>フォント設定</translation>
+    </message>
+    <message>
+      <source>GR_DISP_SET</source>
+      <translation>表示設定</translation>
+    </message>
+    <message>
+      <source>LBL_CURRLINE_HIGHLIGHT</source>
+      <translation>カレントラインのハイライト有効</translation>
+    </message>
+    <message>
+      <source>LBL_TEXT_WRAP</source>
+      <translation>テキストラッピングの有効</translation>
+    </message>
+    <message>
+      <source>LBL_CURSOR_SCROLL</source>
+      <translation>スクロール上の中心カーソル</translation>
+    </message>
+    <message>
+      <source>LBL_LINE_NUMBS_AREA</source>
+      <translation>ライン番号エリアの表示</translation>
+    </message>
+    <message>
+      <source>GR_TAB_SET</source>
+      <translation>タブ設定</translation>
+    </message>
+    <message>
+      <source>LBL_TAB_SPACES</source>
+      <translation>タブ空白の表示</translation>
+    </message>
+    <message>
+      <source>LBL_TAB_SIZE</source>
+      <translation>Tab size:</translation>
+    </message>
+    <message>
+      <source>GR_VERT_EDGE_SET</source>
+      <translation>垂直エッジ設定</translation>
+    </message>
+    <message>
+      <source>LBL_VERT_EDGE</source>
+      <translation>垂直エッジの表示</translation>
+    </message>
+    <message>
+      <source>LBL_NUM_COLUMNS</source>
+      <translation>列数:</translation>
+    </message>
+    <message>
+      <source>WDG_SET_AS_DEFAULT_CHECK</source>
+      <translation>デフォルトとして設定を保存</translation>
+    </message>
+    <message>
+      <source>BUT_OK</source>
+      <translation>&amp;OK</translation>
+    </message>
+    <message>
+      <source>BUT_DEFAULTS</source>
+      <translation>デフォルト(&amp;D)</translation>
+    </message>
+    <message>
+      <source>BUT_CANCEL</source>
+      <translation>キャンセル(&amp;C)</translation>
+    </message>
+    <message>
+      <source>BUT_HELP</source>
+      <translation>ヘルプ(&amp;H)</translation>
+    </message>
+  </context>
+  <context>
+    <name>PyEditor_Window</name>
+    <message>
+      <source>NAME_PYEDITOR</source>
+      <translation>Python Editor</translation>
+    </message>
+    <message>
+      <source>ACT_NEW</source>
+      <translation>新規</translation>
+    </message>
+    <message>
+      <source>TTP_NEW</source>
+      <translation>新規</translation>
+    </message>
+    <message>
+      <source>DSC_NEW</source>
+      <translation>新規 python ファイルの作成</translation>
+    </message>
+    <message>
+      <source>ACT_OPEN</source>
+      <translation>開く</translation>
+    </message>
+    <message>
+      <source>TTP_OPEN</source>
+      <translation>開く</translation>
+    </message>
+    <message>
+      <source>DSC_OPEN</source>
+      <translation>存在する python ファイルを開く</translation>
+    </message>
+    <message>
+      <source>ACT_SAVE</source>
+      <translation>保存</translation>
+    </message>
+    <message>
+      <source>TTP_SAVE</source>
+      <translation>保存</translation>
+    </message>
+    <message>
+      <source>DSC_SAVE</source>
+      <translation>python ドキュメントをディスクに保存</translation>
+    </message>
+    <message>
+      <source>ACT_SAVEAS</source>
+      <translation>別名保存</translation>
+    </message>
+    <message>
+      <source>TTP_SAVEAS</source>
+      <translation>別名保存</translation>
+    </message>
+    <message>
+      <source>DSC_SAVEAS</source>
+      <translation>新しい名前で python ドキュメントを保存</translation>
+    </message>
+    <message>
+      <source>ACT_EXIT</source>
+      <translation>終</translation>
+    </message>
+    <message>
+      <source>TTP_EXIT</source>
+      <translation>終</translation>
+    </message>
+    <message>
+      <source>DSC_EXIT</source>
+      <translation>アプリケーションを終了</translation>
+    </message>
+    <message>
+      <source>ACT_UNDO</source>
+      <translation>元に戻す</translation>
+    </message>
+    <message>
+      <source>TTP_UNDO</source>
+      <translation>元に戻す</translation>
+    </message>
+    <message>
+      <source>DSC_UNDO</source>
+      <translation>最後の操作を元に戻す</translation>
+    </message>
+    <message>
+      <source>ACT_REDO</source>
+      <translation>やり直し</translation>
+    </message>
+    <message>
+      <source>TTP_REDO</source>
+      <translation>やり直し</translation>
+    </message>
+    <message>
+      <source>DSC_REDO</source>
+      <translation>最後の操作をやり直す</translation>
+    </message>
+    <message>
+      <source>ACT_CUT</source>
+      <translation>カット</translation>
+    </message>
+    <message>
+      <source>TTP_CUT</source>
+      <translation>カット</translation>
+    </message>
+    <message>
+      <source>DSC_CUT</source>
+      <translation>現在選択中の内容をクリップボードにカット</translation>
+    </message>
+    <message>
+      <source>ACT_COPY</source>
+      <translation>コピー</translation>
+    </message>
+    <message>
+      <source>TTP_COPY</source>
+      <translation>コピー</translation>
+    </message>
+    <message>
+      <source>DSC_COPY</source>
+      <translation>現在選択中の内容をクリップボードにコピー</translation>
+    </message>
+    <message>
+      <source>ACT_PASTE</source>
+      <translation>ペースト</translation>
+    </message>
+    <message>
+      <source>TTP_PASTE</source>
+      <translation>ペースト</translation>
+    </message>
+    <message>
+      <source>DSC_PASTE</source>
+      <translation>クリップボードの内容を現在の選択にペースト</translation>
+    </message>
+    <message>
+      <source>ACT_DELETE</source>
+      <translation>削除</translation>
+    </message>
+    <message>
+      <source>TTP_DELETE</source>
+      <translation>削除</translation>
+    </message>
+    <message>
+      <source>DSC_DELETE</source>
+      <translation>現在選択中の内容を削除</translation>
+    </message>
+    <message>
+      <source>ACT_SELECT_ALL</source>
+      <translation>すべて選択</translation>
+    </message>
+    <message>
+      <source>TTP_SELECT_ALL</source>
+      <translation>すべて選択</translation>
+    </message>
+    <message>
+      <source>DSC_SELECT_ALL</source>
+      <translation>すべての内容を選択</translation>
+    </message>
+    <message>
+      <source>ACT_PREFERENCES</source>
+      <translation>環境設定</translation>
+    </message>
+    <message>
+      <source>TTP_PREFERENCES</source>
+      <translation>環境設定</translation>
+    </message>
+    <message>
+      <source>DSC_PREFERENCES</source>
+      <translation>環境設定ボックスの表示</translation>
+    </message>
+    <message>
+      <source>ACT_HELP</source>
+      <translation>ヘルプ</translation>
+    </message>
+    <message>
+      <source>TTP_HELP</source>
+      <translation>ヘルプ</translation>
+    </message>
+    <message>
+      <source>DSC_HELP</source>
+      <translation>ヘルプ</translation>
+    </message>
+    <message>
+      <source>MNU_FILE</source>
+      <translation>ファイル(&amp;F)</translation>
+    </message>
+    <message>
+      <source>MNU_EDIT</source>
+      <translation>編集(&amp;E)</translation>
+    </message>
+    <message>
+      <source>MNU_HELP</source>
+      <translation>ヘルプ(&amp;H)</translation>
+    </message>
+    <message>
+      <source>TOOLBAR_LABEL</source>
+      <translation>操作の編集</translation>
+    </message>
+    <message>
+      <source>TIT_PY_FILES</source>
+      <translation>ã..ã.¡ã.¤ã.« Python</translation>
+    </message>
+    <message>
+      <source>TIT_DLG_OPEN</source>
+      <translation>ファイルを開く</translation>
+    </message>
+    <message>
+      <source>TIT_DLG_SAVE</source>
+      <translation>ファイルを保存</translation>
+    </message>
+    <message>
+      <source>WRN_SAVE_FILE</source>
+      <translation>ドキュメントは修正済みです。&lt;br&gt;変更を保存しますか?</translation>
+    </message>
+    <message>
+      <source>WRN_READ_FILE</source>
+      <translation>Cannot read file %1:\n%2.</translation>
+    </message>
+    <message>
+      <source>WRN_WRITE_FILE</source>
+      <translation>Cannot write file %1:\n%2.</translation>
+    </message>
+    <message>
+      <source>STS_READY</source>
+      <translation>準備</translation>
+    </message>
+    <message>
+      <source>STS_F_LOADED</source>
+      <translation>ファイルは読み込まれました</translation>
+    </message>
+    <message>
+      <source>STS_F_SAVED</source>
+      <translation>ファイルは保存されました</translation>
+    </message>
+    <message>
+      <source>NONAME</source>
+      <translation>Noname.py</translation>
+    </message>
+  </context>
+</TS>