# Python Viewer
##
IF(SALOME_USE_PYVIEWER)
- ADD_SUBDIRECTORY(PyEditor)
ADD_SUBDIRECTORY(PyViewer)
ENDIF(SALOME_USE_PYVIEWER)
#include <SUIT_ViewWindow.h>
#include <Qtx.h>
+#include <QtxFontEdit.h>
#include <QtxToolBar.h>
#include <QtxTreeView.h>
#include <QtxMRUAction.h>
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 );
}
}
#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
}
/*!
+++ /dev/null
-# 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}")
+++ /dev/null
-// 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
+++ /dev/null
-// 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 == ']';
-}
+++ /dev/null
-// 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
+++ /dev/null
-// 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 );
-}
+++ /dev/null
-// 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
+++ /dev/null
-// 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 );
-}
+++ /dev/null
-// 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
+++ /dev/null
-// 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 );
- }
-}
+++ /dev/null
-// 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
+++ /dev/null
-// 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();
-}
+++ /dev/null
-// 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
+++ /dev/null
-<?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>
+++ /dev/null
-<?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>
+++ /dev/null
-<?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>
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
# 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
# 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
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})
+++ /dev/null
-// 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();
-}
--- /dev/null
+// 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() );
+}
--- /dev/null
+// 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
//
#include "PyViewer_ViewModel.h"
-
#include "PyViewer_ViewWindow.h"
+#include "PyViewer_Settings.h"
+
+#include "SUIT_ResourceMgr.h"
+#include "SUIT_Session.h"
/*!
\class PyViewer_Viewer
*/
PyViewer_Viewer::PyViewer_Viewer() : SUIT_ViewModel()
{
+ if ( !PyEditor_Settings::settings() )
+ PyEditor_Settings::setSettings( new PyViewer_Settings( SUIT_Session::session()->resourceMgr(), "PyEditor" ) );
}
/*!
*/
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 );
}
virtual QString getType() const { return Type(); }
static QString Type() { return "PyViewer"; }
-
-protected:
- void initView( PyViewer_ViewWindow* theViewModel );
};
#endif // PYVIEWER_VIEWMODEL_H
#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 );
}
/*!
- 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 );
/*!
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" );
}
#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* );
bool onSave();
bool onSaveAs();
void onPreferences();
- void onBrowser();
void onHelp();
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
+++ /dev/null
-<!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>
--- /dev/null
+<?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>
--- /dev/null
+<?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>&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>&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>&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 &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>&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>&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&t</translation>
+ </message>
+ <message>
+ <source>TTP_CUT</source>
+ <translation>Cut</translation>
+ </message>
+ <message>
+ <source>DSC_CUT</source>
+ <translation>Cut the current selection's contents to the clipboard</translation>
+ </message>
+ <message>
+ <source>ACT_COPY</source>
+ <translation>&Copy</translation>
+ </message>
+ <message>
+ <source>TTP_COPY</source>
+ <translation>Copy</translation>
+ </message>
+ <message>
+ <source>DSC_COPY</source>
+ <translation>Copy the current selection's contents to the clipboard</translation>
+ </message>
+ <message>
+ <source>ACT_PASTE</source>
+ <translation>&Paste</translation>
+ </message>
+ <message>
+ <source>TTP_PASTE</source>
+ <translation>Paste</translation>
+ </message>
+ <message>
+ <source>DSC_PASTE</source>
+ <translation>Paste the clipboard's contents into the current selection</translation>
+ </message>
+ <message>
+ <source>ACT_DELETE</source>
+ <translation>&Delete</translation>
+ </message>
+ <message>
+ <source>TTP_DELETE</source>
+ <translation>Delete</translation>
+ </message>
+ <message>
+ <source>DSC_DELETE</source>
+ <translation>Delete the current selection's contents</translation>
+ </message>
+ <message>
+ <source>ACT_SELECT_ALL</source>
+ <translation>Select &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&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>&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.<br>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>
--- /dev/null
+<?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é.<br>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>
--- /dev/null
+<?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>ドキュメントは修正済みです。<br>変更を保存しますか?</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>
+++ /dev/null
-<?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'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'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'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'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.<br>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>
+++ /dev/null
-<?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é.<br>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>
+++ /dev/null
-<?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>ドキュメントは修正済みです。<br>変更を保存しますか?</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>
##
# 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)
+
--- /dev/null
+# 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)
+
--- /dev/null
+# 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}")
--- /dev/null
+// 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();
+}
--- /dev/null
+// 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
--- /dev/null
+// 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();
+}
--- /dev/null
+// 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
--- /dev/null
+// 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 );
+}
--- /dev/null
+// 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
--- /dev/null
+// 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 );
+}
--- /dev/null
+// 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
--- /dev/null
+// 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";
+}
--- /dev/null
+// 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
--- /dev/null
+// 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();
+}
--- /dev/null
+// 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
--- /dev/null
+// 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();
+}
--- /dev/null
+// 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
--- /dev/null
+// 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" );
+}
--- /dev/null
+// 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
--- /dev/null
+# 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})
--- /dev/null
+// 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& );
+};
--- /dev/null
+<!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>
--- /dev/null
+<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>
--- /dev/null
+<?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>&OK</translation>
+ </message>
+ <message>
+ <source>BUT_DEFAULTS</source>
+ <translation>&Defaults</translation>
+ </message>
+ <message>
+ <source>BUT_CANCEL</source>
+ <translation>&Cancel</translation>
+ </message>
+ <message>
+ <source>BUT_HELP</source>
+ <translation>&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>&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>&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>&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 &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&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>&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>&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&t</translation>
+ </message>
+ <message>
+ <source>TTP_CUT</source>
+ <translation>Cut</translation>
+ </message>
+ <message>
+ <source>DSC_CUT</source>
+ <translation>Cut the current selection's contents to the clipboard</translation>
+ </message>
+ <message>
+ <source>ACT_COPY</source>
+ <translation>&Copy</translation>
+ </message>
+ <message>
+ <source>TTP_COPY</source>
+ <translation>Copy</translation>
+ </message>
+ <message>
+ <source>DSC_COPY</source>
+ <translation>Copy the current selection's contents to the clipboard</translation>
+ </message>
+ <message>
+ <source>ACT_PASTE</source>
+ <translation>&Paste</translation>
+ </message>
+ <message>
+ <source>TTP_PASTE</source>
+ <translation>Paste</translation>
+ </message>
+ <message>
+ <source>DSC_PASTE</source>
+ <translation>Paste the clipboard's contents into the current selection</translation>
+ </message>
+ <message>
+ <source>ACT_DELETE</source>
+ <translation>&Delete</translation>
+ </message>
+ <message>
+ <source>TTP_DELETE</source>
+ <translation>Delete</translation>
+ </message>
+ <message>
+ <source>DSC_DELETE</source>
+ <translation>Delete the current selection's contents</translation>
+ </message>
+ <message>
+ <source>ACT_SELECT_ALL</source>
+ <translation>Select &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&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>&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>&File</translation>
+ </message>
+ <message>
+ <source>MNU_EDIT</source>
+ <translation>&Edit</translation>
+ </message>
+ <message>
+ <source>MNU_HELP</source>
+ <translation>&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.<br>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>
--- /dev/null
+<?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>&OK</translation>
+ </message>
+ <message>
+ <source>BUT_DEFAULTS</source>
+ <translation>Défauts</translation>
+ </message>
+ <message>
+ <source>BUT_CANCEL</source>
+ <translation>&Annuler</translation>
+ </message>
+ <message>
+ <source>BUT_HELP</source>
+ <translation>A&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&hier</translation>
+ </message>
+ <message>
+ <source>MNU_EDIT</source>
+ <translation>&Edition</translation>
+ </message>
+ <message>
+ <source>MNU_HELP</source>
+ <translation>A&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é.<br>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>
--- /dev/null
+<?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>&OK</translation>
+ </message>
+ <message>
+ <source>BUT_DEFAULTS</source>
+ <translation>デフォルト(&D)</translation>
+ </message>
+ <message>
+ <source>BUT_CANCEL</source>
+ <translation>キャンセル(&C)</translation>
+ </message>
+ <message>
+ <source>BUT_HELP</source>
+ <translation>ヘルプ(&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>ファイル(&F)</translation>
+ </message>
+ <message>
+ <source>MNU_EDIT</source>
+ <translation>編集(&E)</translation>
+ </message>
+ <message>
+ <source>MNU_HELP</source>
+ <translation>ヘルプ(&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>ドキュメントは修正済みです。<br>変更を保存しますか?</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>