#ifndef DISABLE_PYCONSOLE
else if ( flag == WT_PyConsole )
{
- PyConsole_Console* pyCons = new PyConsole_Console( desktop(),new LightApp_PyInterp());
+ PyConsole_Console* pyCons = new PyConsole_EnhConsole( desktop(),new LightApp_PyInterp());
pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" ));
pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true ));
* calls initialize method defined in base class, which calls virtual methods
* initstate & initcontext redefined here.
*/
-LightApp_PyInterp::LightApp_PyInterp(): PyConsole_Interp()
+LightApp_PyInterp::LightApp_PyInterp(): PyConsole_EnhInterp()
{
}
#ifndef _LIGHTAPP_PYINTERP_H_
#define _LIGHTAPP_PYINTERP_H_
-#include <PyConsole_Interp.h> // this include must be first (see PyInterp_base.h)!
+#include <PyConsole_EnhInterp.h> // this include must be first (see PyInterp_base.h)!
-class LightApp_PyInterp : public PyConsole_Interp
+class LightApp_PyInterp : public PyConsole_EnhInterp
{
public:
LightApp_PyInterp();
${CMAKE_CURRENT_SOURCE_DIR}/../Qtx
${CMAKE_CURRENT_SOURCE_DIR}/../SUIT
${CMAKE_CURRENT_SOURCE_DIR}/../PyInterp
+ ${CMAKE_CURRENT_SOURCE_DIR}/../Event
)
-SET(COMMON_LIBS ${PYTHON_LIBRARIES} ${QT_LIBRARIES} ${SALOMELocalTrace} qtx suit PyInterp)
+SET(COMMON_LIBS ${PYTHON_LIBRARIES} ${QT_LIBRARIES} ${SALOMELocalTrace} qtx suit PyInterp Event)
SET(GUI_HEADERS
PyConsole_Editor.h
+ PyConsole_EnhEditor.h
PyConsole_Console.h
)
QT4_WRAP_CPP(GUI_HEADERS_MOC ${GUI_HEADERS})
SET(PyConsole_SOURCES
PyConsole_Console.cxx
PyConsole_Editor.cxx
+ PyConsole_EnhEditor.cxx
PyConsole_Interp.cxx
+ PyConsole_EnhInterp.cxx
+ PyConsole_Event.cxx
+ PyConsole_Request.cxx
)
SET(GUITS_SOURCES
PyConsole.h
PyConsole_Console.h
PyConsole_Editor.h
+ PyConsole_EnhEditor.h
PyConsole_Interp.h
+ PyConsole_EnhInterp.h
+ PyConsole_Event.h
+ PyConsole_Request.h
)
INSTALL(FILES ${COMMON_HEADERS_H} DESTINATION ${GUI_salomeinclude_HEADERS})
QT4_INSTALL_TS_RESOURCES("${GUITS_SOURCES}" "${GUI_salomeres_DATA}")
PyConsole.h \
PyConsole_Console.h \
PyConsole_Editor.h \
- PyConsole_Interp.h
+ PyConsole_EnhEditor.h \
+ PyConsole_EnhInterp.h \
+ PyConsole_Event.h \
+ PyConsole_Request.h \
+ PyConsole_Interp.h
dist_libPyConsole_la_SOURCES = \
PyConsole_Console.cxx \
PyConsole_Editor.cxx \
- PyConsole_Interp.cxx
+ PyConsole_EnhEditor.cxx \
+ PyConsole_Event.cxx \
+ PyConsole_Request.cxx \
+ PyConsole_Interp.cxx \
+ PyConsole_EnhInterp.cxx
MOC_FILES = \
PyConsole_Editor_moc.cxx \
+ PyConsole_EnhEditor_moc.cxx \
PyConsole_Console_moc.cxx
nodist_libPyConsole_la_SOURCES = $(MOC_FILES)
PyConsole_msg_fr.qm
libPyConsole_la_CPPFLAGS = $(PYTHON_INCLUDES) $(QT_INCLUDES) \
- -I$(srcdir)/../PyInterp -I$(srcdir)/../SUIT -I$(srcdir)/../Qtx
+ -I$(srcdir)/../PyInterp -I$(srcdir)/../SUIT -I$(srcdir)/../Qtx -I$(srcdir)/../Event
libPyConsole_la_LDFLAGS = $(PYTHON_LIBS) $(QT_MT_LIBS) $(KERNEL_LDFLAGS) -lSALOMELocalTrace
-libPyConsole_la_LIBADD = ../Qtx/libqtx.la ../SUIT/libsuit.la ../PyInterp/libPyInterp.la
+libPyConsole_la_LIBADD = ../Qtx/libqtx.la ../SUIT/libsuit.la ../Event/libEvent.la ../PyInterp/libPyInterp.la
#include "PyConsole_Interp.h" /// !!! WARNING !!! THIS INCLUDE MUST BE VERY FIRST !!!
#include "PyConsole_Console.h"
-#include "PyConsole_Editor.h"
+#include "PyConsole_EnhEditor.h"
+#include "PyConsole_EnhInterp.h"
#include <Qtx.h>
\param interp python interpreter
*/
PyConsole_Console::PyConsole_Console( QWidget* parent, PyConsole_Interp* interp )
-: QWidget( parent ),
- myEditor( 0 )
+: QWidget( parent )
{
// create python interpreter
myInterp = interp;
createActions();
}
+/**
+ * Protected constructor.
+ */
+PyConsole_Console::PyConsole_Console( QWidget* parent, PyConsole_Interp* i, PyConsole_Editor* e)
+ : QWidget (parent), myEditor(e), myInterp(i)
+{}
+
/*!
\brief Destructor.
myActions[PasteId]->setEnabled( !myEditor->isReadOnly() && !QApplication::clipboard()->text().isEmpty() );
myActions[SelectAllId]->setEnabled( !myEditor->document()->isEmpty() );
}
+
+/**
+ * Similar to constructor of the base class but using enhanced objects.
+ * TODO: this should really be done in a factory to avoid code duplication.
+ * @param parent
+ * @param interp
+ */
+PyConsole_EnhConsole::PyConsole_EnhConsole( QWidget* parent, PyConsole_EnhInterp* interp)
+ : PyConsole_Console(parent, interp, 0)
+{
+ // create python interpreter
+ myInterp = interp;
+ if ( !myInterp )
+ myInterp = new PyConsole_EnhInterp();
+
+ // initialize Python interpretator
+ myInterp->initialize();
+
+ // create editor console
+ QVBoxLayout* lay = new QVBoxLayout( this );
+ lay->setMargin( 0 );
+ myEditor = new PyConsole_EnhEditor( static_cast<PyConsole_EnhInterp*>(myInterp), this );
+ char* synchronous = getenv("PYTHON_CONSOLE_SYNC");
+ if (synchronous && atoi(synchronous))
+ {
+ myEditor->setIsSync(true);
+ }
+ myEditor->viewport()->installEventFilter( this );
+ lay->addWidget( myEditor );
+
+ createActions();
+}
class PyConsole_Interp;
class PyConsole_Editor;
+class PyConsole_EnhInterp;
class PYCONSOLE_EXPORT PyConsole_Console : public QWidget, public SUIT_PopupClient
{
void setMenuActions( const int );
int menuActions() const;
-private:
+protected:
void createActions();
void updateActions();
-private:
+ PyConsole_Console( QWidget* parent, PyConsole_Interp*, PyConsole_Editor*);
+
+
PyConsole_Interp* myInterp; //!< python interpreter
PyConsole_Editor* myEditor; //!< python console editor widget
QMap<int, QAction*> myActions; //!< menu actions list
};
+/**
+ * Enhance console object providing auto-completion.
+ * Similar to PyConsole_Console except that an enhanced interpreter and enhanced editor
+ * are encapsulated.
+ */
+class PYCONSOLE_EXPORT PyConsole_EnhConsole: public PyConsole_Console
+{
+ Q_OBJECT
+
+public:
+ PyConsole_EnhConsole( QWidget* parent, PyConsole_EnhInterp* interp = 0);
+ virtual ~PyConsole_EnhConsole() {}
+};
+
#endif // PYCONSOLE_CONSOLE_H
- <Ctrl><C> : copy
- <Ctrl><X> : cut
- <Ctrl><V> : paste
-
- TODO:
- - paste multiline text: process each line as separate command
- (including mouse middle-button click pasting)
- - the same for drag-n-drop of multiline text
*/
#include "PyConsole_Interp.h" // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!!
#include "PyConsole_Editor.h"
-#include <PyInterp_Dispatcher.h>
+#include "PyConsole_Event.h"
+#include "PyInterp_Event.h"
+#include "PyInterp_Dispatcher.h"
+#include "PyConsole_Request.h"
#include <SUIT_Tools.h>
#include <SUIT_FileDlg.h>
#include <QTextCursor>
#include <QTextDocument>
#include <QTextStream>
+#include <QChar>
static QString READY_PROMPT = ">>> ";
static QString DOTS_PROMPT = "... ";
-#define PROMPT_SIZE myPrompt.length()
-
-#define PRINT_EVENT 65432
-
class DumpCommandsFileValidator : public SUIT_FileValidator
{
return SUIT_FileValidator::canSave( file, permissions);
}
-/*!
- \class ExecCommand
- \brief Python command execution request.
- \internal
-*/
-
-class ExecCommand : public PyInterp_LockRequest
-{
-public:
- /*!
- \brief Constructor.
-
- Creates new python command execution request.
- \param theInterp python interpreter
- \param theCommand python command
- \param theListener widget to get the notification messages
- \param sync if True the request is processed synchronously
- */
- ExecCommand( PyInterp_Interp* theInterp,
- const QString& theCommand,
- PyConsole_Editor* theListener,
- bool sync = false )
- : PyInterp_LockRequest( theInterp, theListener, sync ),
- myCommand( theCommand ), myState( PyInterp_Event::ES_OK )
- {}
-
-protected:
- /*!
- \brief Execute the python command in the interpreter and
- get its execution status.
- */
- virtual void execute()
- {
- if ( myCommand != "" )
- {
- int ret = getInterp()->run( myCommand.toUtf8().data() );
- if ( ret < 0 )
- myState = PyInterp_Event::ES_ERROR;
- else if ( ret > 0 )
- myState = PyInterp_Event::ES_INCOMPLETE;
- }
- }
-
- /*!
- \brief Create and return a notification event.
- \return new notification event
- */
- virtual QEvent* createEvent() const
- {
- if ( IsSync() )
- QCoreApplication::sendPostedEvents( listener(), PRINT_EVENT );
- return new PyInterp_Event( myState, (PyInterp_Request*)this );
- }
-
-private:
- QString myCommand; //!< Python command
- int myState; //!< Python command execution status
-};
-
-/*!
- \class PrintEvent
- \brief Python command output backend event.
- \internal
-*/
-
-class PrintEvent : public QEvent
+void staticCallbackStdout( void* data, char* c )
{
-public:
- /*!
- \brief Constructor
- \param c message text (python trace)
- */
- PrintEvent( const char* c ) : QEvent( (QEvent::Type)PRINT_EVENT ), myText( c ) {}
- /*!
- \brief Get message
- \return message text (python trace)
- */
- QString text() const { return myText; }
-
-private:
- QString myText; //!< Event message (python trace)
-};
+ if(!((PyConsole_Editor*)data)->isSuppressOutput())
+ QApplication::postEvent( (PyConsole_Editor*)data, new PrintEvent( c, false ) );
+}
-void staticCallback( void* data, char* c )
+void staticCallbackStderr( void* data, char* c )
{
if(!((PyConsole_Editor*)data)->isSuppressOutput())
- QApplication::postEvent( (PyConsole_Editor*)data, new PrintEvent( c ) );
+ QApplication::postEvent( (PyConsole_Editor*)data, new PrintEvent( c, true ) );
}
+
/*!
\brief Constructor.
setWordWrapMode( QTextOption::WrapAnywhere );
setAcceptRichText( false );
- theInterp->setvoutcb( staticCallback, this );
- theInterp->setverrcb( staticCallback, this );
+ theInterp->setvoutcb( staticCallbackStdout, this );
+ theInterp->setverrcb( staticCallbackStderr, this );
// san - This is necessary for troubleless initialization
onPyInterpChanged( theInterp );
\brief Put the string \a str to the python editor.
\param str string to be put in the command line of the editor
\param newBlock if True, then the string is printed on a new line
+ \param isError if true, the text is printed in dark red
*/
void PyConsole_Editor::addText( const QString& str,
- const bool newBlock )
+ const bool newBlock,
+ const bool isError)
{
+ QTextCursor theCursor(textCursor());
+ QTextCharFormat cf;
+
moveCursor( QTextCursor::End );
if ( newBlock )
- textCursor().insertBlock();
- textCursor().insertText( str );
+ theCursor.insertBlock();
+ if (isError)
+ cf.setForeground(QBrush(Qt::red));
+ else
+ cf.setForeground(QBrush(Qt::black));
+ theCursor.insertText( str, cf);
moveCursor( QTextCursor::End );
ensureCursorVisible();
}
\brief Convenient method for executing a Python command,
as if the user typed it manually.
\param command python command to be executed
+
+ !!! WARNING: doesn't work properly with multi-line commands. !!!
*/
void PyConsole_Editor::exec( const QString& command )
{
*/
void PyConsole_Editor::handleReturn()
{
+ // Position cursor at the end
+ QTextCursor curs(textCursor());
+ curs.movePosition(QTextCursor::End);
+ setTextCursor(curs);
+
// get last line
QTextBlock par = document()->end().previous();
if ( !par.isValid() ) return;
// get command
- QString cmd = par.text().remove( 0, PROMPT_SIZE );
+ QString cmd = par.text().remove( 0, promptSize() );
// extend the command buffer with the current command
myCommandBuffer.append( cmd );
// add command to the history
QPoint pos = event->pos();
QTextCursor cur = cursorForPosition( event->pos() );
// if the position is not in the last line move it to the end of the command line
- if ( cur.position() < document()->end().previous().position() + PROMPT_SIZE ) {
+ if ( cur.position() < document()->end().previous().position() + promptSize() ) {
moveCursor( QTextCursor::End );
pos = cursorRect().center();
}
//copy();
}
else if ( event->button() == Qt::MidButton ) {
- QString text;
- if ( QApplication::clipboard()->supportsSelection() )
- text = QApplication::clipboard()->text( QClipboard::Selection );
- if ( text.isEmpty() )
- text = QApplication::clipboard()->text( QClipboard::Clipboard );
QTextCursor cur = cursorForPosition( event->pos() );
// if the position is not in the last line move it to the end of the command line
- if ( cur.position() < document()->end().previous().position() + PROMPT_SIZE ) {
+ if ( cur.position() < document()->end().previous().position() + promptSize() ) {
moveCursor( QTextCursor::End );
}
else {
setTextCursor( cur );
}
- textCursor().clearSelection();
- textCursor().insertText( text );
+ const QMimeData* md = QApplication::clipboard()->mimeData( QApplication::clipboard()->supportsSelection() ?
+ QClipboard::Selection : QClipboard::Clipboard );
+ if ( md )
+ insertFromMimeData( md );
}
else {
QTextEdit::mouseReleaseEvent( event );
}
// check for printed key
- aKey = ( aKey < Qt::Key_Space || aKey > Qt::Key_ydiaeresis ) ? aKey : 0;
+ // #### aKey = ( aKey < Qt::Key_Space || aKey > Qt::Key_ydiaeresis ) ? aKey : 0;
+ // Better:
+ aKey = !(QChar(aKey).isPrint()) ? aKey : 0;
switch ( aKey ) {
case 0 :
// any printed key: just print it
{
- if ( curLine < endLine || curCol < PROMPT_SIZE ) {
+ if ( curLine < endLine || curCol < promptSize() ) {
moveCursor( QTextCursor::End );
}
QTextEdit::keyPressEvent( event );
myCmdInHistory = myHistory.count();
// remember current command
QTextBlock par = document()->end().previous();
- myCurrentCommand = par.text().remove( 0, PROMPT_SIZE );
+ myCurrentCommand = par.text().remove( 0, promptSize() );
}
if ( myCmdInHistory > 0 ) {
myCmdInHistory--;
// - with <Ctrl>+<Shift> modifier keys pressed: move one word left with selection
{
QString txt = textCursor().block().text();
- if ( !shftPressed && isCommand( txt ) && curCol <= PROMPT_SIZE ) {
+ if ( !shftPressed && isCommand( txt ) && curCol <= promptSize() ) {
moveCursor( QTextCursor::Up );
moveCursor( QTextCursor::EndOfBlock );
}
QString txt = textCursor().block().text();
if ( !shftPressed ) {
if ( curCol < txt.length() ) {
- if ( isCommand( txt ) && curCol < PROMPT_SIZE ) {
- cur.setPosition( cur.block().position() + PROMPT_SIZE );
+ if ( isCommand( txt ) && curCol < promptSize() ) {
+ cur.setPosition( cur.block().position() + promptSize() );
setTextCursor( cur );
break;
}
}
else {
if ( curLine < endLine && isCommand( textCursor().block().next().text() ) ) {
- cur.setPosition( cur.position() + PROMPT_SIZE+1 );
+ cur.setPosition( cur.position() + promptSize()+1 );
setTextCursor( cur );
horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
break;
myCmdInHistory = myHistory.count();
// remember current command
QTextBlock par = document()->end().previous();
- myCurrentCommand = par.text().remove( 0, PROMPT_SIZE );
+ myCurrentCommand = par.text().remove( 0, promptSize() );
}
if ( myCmdInHistory > 0 ) {
myCmdInHistory = 0;
QString txt = textCursor().block().text();
if ( isCommand( txt ) ) {
if ( shftPressed ) {
- if ( curCol > PROMPT_SIZE ) {
+ if ( curCol > promptSize() ) {
cur.movePosition( QTextCursor::StartOfLine, QTextCursor::KeepAnchor );
- cur.movePosition( QTextCursor::Right, QTextCursor::KeepAnchor, PROMPT_SIZE );
+ cur.movePosition( QTextCursor::Right, QTextCursor::KeepAnchor, promptSize() );
}
}
else {
cur.movePosition( QTextCursor::StartOfLine );
- cur.movePosition( QTextCursor::Right, QTextCursor::MoveAnchor, PROMPT_SIZE );
+ cur.movePosition( QTextCursor::Right, QTextCursor::MoveAnchor, promptSize() );
}
setTextCursor( cur );
}
if ( cur.hasSelection() ) {
cut();
}
- else if ( cur.position() > document()->end().previous().position() + PROMPT_SIZE ) {
+ else if ( cur.position() > document()->end().previous().position() + promptSize() ) {
if ( shftPressed ) {
moveCursor( QTextCursor::PreviousWord, QTextCursor::KeepAnchor );
textCursor().removeSelectedText();
}
else if ( ctrlPressed ) {
- cur.setPosition( document()->end().previous().position() + PROMPT_SIZE,
+ cur.setPosition( document()->end().previous().position() + promptSize(),
QTextCursor::KeepAnchor );
setTextCursor( cur );
textCursor().removeSelectedText();
}
}
else {
- cur.setPosition( document()->end().previous().position() + PROMPT_SIZE );
+ cur.setPosition( document()->end().previous().position() + promptSize() );
setTextCursor( cur );
horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
}
if ( cur.hasSelection() ) {
cut();
}
- else if ( cur.position() > document()->end().previous().position() + PROMPT_SIZE-1 ) {
+ else if ( cur.position() > document()->end().previous().position() + promptSize()-1 ) {
if ( shftPressed ) {
moveCursor( QTextCursor::NextWord, QTextCursor::KeepAnchor );
textCursor().removeSelectedText();
}
}
else {
- cur.setPosition( document()->end().previous().position() + PROMPT_SIZE );
+ cur.setPosition( document()->end().previous().position() + promptSize() );
setTextCursor( cur );
horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
}
{
switch( event->type() )
{
- case PRINT_EVENT:
+ case PrintEvent::EVENT_ID:
{
PrintEvent* pe=(PrintEvent*)event;
- addText( pe->text() );
+ addText( pe->text(), false, pe->isError());
return;
}
case PyInterp_Event::ES_OK:
if ( cur.hasSelection() ) {
QApplication::clipboard()->setText( cur.selectedText() );
int startSelection = cur.selectionStart();
- if ( startSelection < document()->end().previous().position() + PROMPT_SIZE )
- startSelection = document()->end().previous().position() + PROMPT_SIZE;
+ if ( startSelection < document()->end().previous().position() + promptSize() )
+ startSelection = document()->end().previous().position() + promptSize();
int endSelection = cur.selectionEnd();
- if ( endSelection < document()->end().previous().position() + PROMPT_SIZE )
- endSelection = document()->end().previous().position() + PROMPT_SIZE;
+ if ( endSelection < document()->end().previous().position() + promptSize() )
+ endSelection = document()->end().previous().position() + promptSize();
cur.setPosition( startSelection );
cur.setPosition( endSelection, QTextCursor::KeepAnchor );
horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
QTextCursor cur = textCursor();
if ( cur.hasSelection() ) {
int startSelection = cur.selectionStart();
- if ( startSelection < document()->end().previous().position() + PROMPT_SIZE )
- startSelection = document()->end().previous().position() + PROMPT_SIZE;
+ if ( startSelection < document()->end().previous().position() + promptSize() )
+ startSelection = document()->end().previous().position() + promptSize();
int endSelection = cur.selectionEnd();
- if ( endSelection < document()->end().previous().position() + PROMPT_SIZE )
- endSelection = document()->end().previous().position() + PROMPT_SIZE;
+ if ( endSelection < document()->end().previous().position() + promptSize() )
+ endSelection = document()->end().previous().position() + promptSize();
cur.setPosition( startSelection );
cur.setPosition( endSelection, QTextCursor::KeepAnchor );
horizontalScrollBar()->setValue( horizontalScrollBar()->minimum() );
setTextCursor( cur );
textCursor().removeSelectedText();
}
- if ( textCursor().position() < document()->end().previous().position() + PROMPT_SIZE )
+ if ( textCursor().position() < document()->end().previous().position() + promptSize() )
moveCursor( QTextCursor::End );
QTextEdit::paste();
}
PyConsole_Editor( PyConsole_Interp* theInterp, QWidget *theParent = 0 );
~PyConsole_Editor();
- virtual void addText( const QString& str, const bool newBlock = false );
+ virtual void addText( const QString& str, const bool newBlock = false, const bool isError = false );
bool isCommand( const QString& str ) const;
virtual void exec( const QString& command );
virtual QSize sizeHint() const;
+public slots:
+ void cut();
+ void paste();
+ void clear();
+ void handleReturn();
+ void onPyInterpChanged( PyConsole_Interp* );
+ void dump();
+
protected:
virtual void dropEvent( QDropEvent* event );
virtual void mouseReleaseEvent( QMouseEvent* event );
virtual PyInterp_Request* createRequest( const QString& );
-public slots:
- void cut();
- void paste();
- void clear();
- void handleReturn();
- void onPyInterpChanged( PyConsole_Interp* );
- void dump();
-
-private:
+ /** Convenience function */
+ inline int promptSize() const { return myPrompt.size(); }
+
PyConsole_Interp* myInterp; //!< python interpreter
QString myCommandBuffer; //!< python command buffer
--- /dev/null
+// Copyright (C) 2007-2013 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.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// Author : Adrien Bruneton (CEA/DEN)
+// Created on: 4 avr. 2013
+
+#include "PyConsole.h"
+#include <Python.h>
+
+#include <QKeyEvent>
+#include <QTextBlock>
+#include <QTextCursor>
+#include <QTextCharFormat>
+#include <QRegExp>
+
+#include "PyConsole_EnhEditor.h"
+#include "PyConsole_EnhInterp.h"
+#include "PyConsole_Request.h"
+#include "PyInterp_Dispatcher.h"
+
+// Initialize list of valid separators
+static const char * tmp_a[] = {" ", "(", "[","+", "-", "*", "/", ";", "^", "="};
+const std::vector<QString> PyConsole_EnhEditor::SEPARATORS = \
+ std::vector<QString>(tmp_a, tmp_a + sizeof(tmp_a)/sizeof(tmp_a[0]));
+
+/**
+ * Constructor.
+ * @param interp the interpreter linked to the editor
+ * @param parent parent widget
+ */
+PyConsole_EnhEditor::PyConsole_EnhEditor(PyConsole_EnhInterp * interp, QWidget * parent) :
+ PyConsole_Editor(interp, parent),
+ _tab_mode(false),
+ _cursor_pos(-1),
+ _multi_line_paste(false),
+ _multi_line_content()
+{
+ document()->setUndoRedoEnabled(true);
+}
+
+/**
+ * Overrides. Catches the TAB and Ctrl+TAB combinations.
+ * @param event
+ */
+void PyConsole_EnhEditor::keyPressEvent ( QKeyEvent* event)
+{
+ // check if <Ctrl> is pressed
+ bool ctrlPressed = event->modifiers() & Qt::ControlModifier;
+ // check if <Shift> is pressed
+ bool shftPressed = event->modifiers() & Qt::ShiftModifier;
+
+ if (event->key() == Qt::Key_Tab && !shftPressed)
+ {
+ if (!ctrlPressed)
+ handleTab();
+ else
+ {
+ clearCompletion();
+ handleBackTab();
+ }
+ PyConsole_Editor::keyPressEvent(event);
+ }
+ else
+ {
+ // If ctrl is not pressed (and sth else is pressed with it),
+ // or if ctrl is not pressed alone
+ if (!ctrlPressed || (ctrlPressed && event->key() != Qt::Key_Control))
+ {
+ clearCompletion();
+ _cursor_pos = -1;
+ }
+ // Discard ctrl pressed alone:
+ if (event->key() != Qt::Key_Control)
+ PyConsole_Editor::keyPressEvent(event);
+ }
+}
+
+/**
+ * Whenever the mouse is clicked, clear the completion.
+ * @param e
+ */
+void PyConsole_EnhEditor::mousePressEvent(QMouseEvent* e)
+{
+ clearCompletion();
+ _cursor_pos = -1;
+ PyConsole_Editor::mousePressEvent(e);
+}
+
+/**
+ * Clear in the editor the block of text displayed after having hit <TAB>.
+ */
+void PyConsole_EnhEditor::clearCompletion()
+{
+ // Delete completion text if present
+ if (_tab_mode)
+ {
+ // Remove completion display
+ document()->undo();
+ // Remove trailing line return:
+ QTextCursor tc(textCursor());
+ tc.setPosition(document()->characterCount()-1);
+ setTextCursor(tc);
+ textCursor().deletePreviousChar();
+ // TODO: before wait for any TAB event to be completed
+ static_cast<PyConsole_EnhInterp *>(myInterp)->clearCompletion();
+ }
+ _tab_mode = false;
+}
+
+/**
+ * Handle the sequence of events after having hit <TAB>
+ */
+void PyConsole_EnhEditor::handleTab()
+{
+ if (_tab_mode)
+ {
+ // Already tab mode - nothing to do !
+ return;
+ }
+
+ QTextCursor cursor(textCursor());
+
+ // Cursor at end of input
+ cursor.movePosition(QTextCursor::End);
+ setTextCursor(cursor);
+
+ // Save cursor position if needed
+ if (_cursor_pos == -1)
+ _cursor_pos = textCursor().position();
+
+ // get last line
+ QTextBlock par = document()->end().previous();
+ if ( !par.isValid() ) return;
+
+ // Switch to completion mode
+ _tab_mode = true;
+
+ QString cmd = par.text().mid(promptSize());
+
+ // Post completion request
+ // Editor will be informed via a custom event that completion has been run
+ PyInterp_Request* req = createTabRequest(cmd);
+ PyInterp_Dispatcher::Get()->Exec(req);
+}
+
+/**
+ * Handles what happens after hitting Ctrl-TAB
+ */
+void PyConsole_EnhEditor::handleBackTab()
+{
+ QTextCursor cursor(textCursor());
+
+ if (_cursor_pos == -1)
+ {
+ // Invalid cursor position - we can't do anything:
+ return;
+ }
+ // Ensure cursor is at the end of command line
+ cursor.setPosition(_cursor_pos);
+ cursor.movePosition(QTextCursor::EndOfLine);
+ //setCursor(cursor);
+
+ // Delete last completed text
+ int i = cursor.position() - _cursor_pos;
+ cursor.movePosition(QTextCursor::Left, QTextCursor::KeepAnchor, i);
+ cursor.removeSelectedText();
+ _cursor_pos = -1;
+}
+
+/**
+ * Create the Python requested that will be posted to the interpreter to
+ * get the completions.
+ * @param input line typed by the user at the time TAB was hit
+ * @return a CompletionCommand
+ * @sa CompletionCommand
+ */
+PyInterp_Request* PyConsole_EnhEditor::createTabRequest( const QString& input )
+{
+ // Parse input to extract on what part the dir() has to be executed
+ QString input2(input);
+
+ // Split up to the last syntaxical separator
+ int lastSp = -1;
+ for (std::vector<QString>::const_iterator i = SEPARATORS.begin(); i != SEPARATORS.end(); i++)
+ {
+ int j = input2.lastIndexOf(*i);
+ if (j > lastSp)
+ lastSp = j;
+ }
+ if (lastSp >= 0)
+ input2 = input.mid(lastSp+1);
+
+ // Detect a qualified name (with a point)
+ int lastPt = input2.lastIndexOf(QString("."));
+
+ // Split the 2 surrounding parts of the qualified name
+ if (lastPt != -1)
+ {
+ _compl_before_point = input2.left(lastPt);
+ _compl_after_point = input2.mid(lastPt+1);
+ }
+ else
+ {
+ // No point found - do a global matching -
+ // (the following will call dir() with an empty string)
+ _compl_after_point = input2;
+ _compl_before_point = QString("");
+ }
+
+ return new CompletionCommand( static_cast<PyConsole_EnhInterp *>(myInterp), _compl_before_point,
+ _compl_after_point, this, isSync() );
+}
+
+/**
+ * Format completion results - this is where we should create 3 columns etc ...
+ * @param matches list of possible completions
+ * @param result return value
+ */
+void PyConsole_EnhEditor::formatCompletion(const std::vector<QString> & matches, QString & result) const
+{
+ int sz = matches.size();
+
+ if (sz > MAX_COMPLETIONS)
+ {
+ sz = MAX_COMPLETIONS;
+ result.append("[Too many matches! Displaying first ones only ...]\n");
+ }
+
+ for (int i = 0; i < sz; ++i)
+ {
+ result.append(matches[i]);
+ result.append("\n");
+ }
+}
+
+/**
+ * Override. Catches the events generated by the enhanced interpreter after the execution
+ * of a completion request.
+ * @param event
+ */
+void PyConsole_EnhEditor::customEvent( QEvent* event )
+{
+ std::vector<QString> matches;
+ QString first_match, comple_text, doc, base;
+ QTextCursor cursor(textCursor());
+ QTextBlockFormat bf;
+ QTextCharFormat cf;
+ PyConsole_EnhInterp * interp = static_cast<PyConsole_EnhInterp *>(myInterp);
+ int cursorPos;
+
+ switch( event->type() )
+ {
+ case PyInterp_Event::ES_TAB_COMPLETE_OK:
+ // Extract corresponding matches from the interpreter
+ matches = interp->getLastMatches();
+
+ if (matches.size() == 0)
+ {
+ // Completion successful but nothing returned.
+ _tab_mode = false;
+ _cursor_pos = -1;
+ return;
+ }
+
+ // Only one match - complete directly and update doc string window
+ doc = interp->getDocStr();
+ if (matches.size() == 1)
+ {
+ first_match = matches[0].mid(_compl_after_point.size());
+ cursor.insertText(first_match);
+ _tab_mode = false;
+ if (doc == QString(""))
+ emit updateDoc(formatDocHTML("(no documentation available)\n"));
+ else
+ emit updateDoc(formatDocHTML(doc));
+ }
+ else
+ {
+ // Detect if there is a common base to all available completion
+ // In this case append this base to the text already
+ extractCommon(matches, base);
+ first_match = base.mid(_compl_after_point.size());
+ cursor.insertText(first_match);
+
+ // If this happens to match exaclty the first completion
+ // also provide doc
+ if (base == matches[0])
+ {
+ doc = formatDocHTML(doc);
+ emit updateDoc(doc);
+ }
+
+ // Print all matching completion in a "undo-able" block
+ cursorPos = cursor.position();
+ cursor.insertBlock();
+ cursor.beginEditBlock();
+
+ // Insert all matches
+ QTextCharFormat cf;
+ cf.setForeground(QBrush(Qt::darkGreen));
+ cursor.setCharFormat(cf);
+ formatCompletion(matches, comple_text);
+ cursor.insertText(comple_text);
+ cursor.endEditBlock();
+
+ // Position cursor where it was before inserting the completion list:
+ cursor.setPosition(cursorPos);
+ setTextCursor(cursor);
+ }
+ break;
+ case PyInterp_Event::ES_TAB_COMPLETE_ERR:
+ // Tab completion was unsuccessful, switch off mode:
+ _tab_mode = false;
+ _cursor_pos = -1;
+ break;
+ case PyInterp_Event::ES_OK:
+ case PyInterp_Event::ES_ERROR:
+ case PyInterp_Event::ES_INCOMPLETE:
+ // Before everything else, call super()
+ PyConsole_Editor::customEvent(event);
+ // If we are in multi_paste_mode, process the next item:
+ multiLineProcessNextLine();
+ break;
+ default:
+ PyConsole_Editor::customEvent( event );
+ break;
+ }
+}
+
+/**
+ * Extract the common leading part of all strings in matches.
+ * @param matches
+ * @param result
+ */
+void PyConsole_EnhEditor::extractCommon(const std::vector<QString> & matches, QString & result) const
+{
+ result = "";
+ int charIdx = 0;
+
+ if (matches.size() < 2)
+ return;
+
+ while (true)
+ {
+ if (charIdx >= matches[0].size())
+ return;
+ QChar ch = matches[0][charIdx];
+ for (int j = 1; j < matches.size(); j++)
+ if (charIdx >= matches[j].size() || matches[j][charIdx] != ch)
+ return;
+ result += ch;
+ charIdx++;
+ }
+}
+
+/**
+ * Format the doc string in HTML format with the first line in bold blue
+ * @param doc initial doc string
+ * @return HTML string
+ */
+QString PyConsole_EnhEditor::formatDocHTML(const QString & doc) const
+{
+ QString templ = QString("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" ") +
+ QString(" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n ") +
+ QString("<html><head><meta name=\"qrichtext\" content=\"1\" /> ") +
+ QString("<style type=\"text/css\">\np, li { white-space: pre-wrap; }\n</style> ") +
+ QString("</head><body style=\" font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;\">\n") +
+ QString("<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">") +
+ QString("<span style=\" font-weight:600; color:#0000ff;\">%1</span></p>") +
+ QString("<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">%2</p>") +
+ QString("</body></html>");
+
+ QString fst, rest("");
+
+ // Extract first line of doc
+ int idx = doc.indexOf("\n");
+ if (idx > 0)
+ {
+ fst = doc.left(idx);
+ rest = doc.mid(idx+1);
+ }
+ else
+ {
+ fst = doc;
+ }
+
+ fst = fst.replace("\n", " ");
+ rest = rest.replace("\n", " ");
+ return templ.arg(fst).arg(rest);
+}
+
+/**
+ * Handle properly multi-line pasting. Qt4 doc recommends overriding this function.
+ * If the pasted text doesn't contain a line return, no special treatment is done.
+ * @param source
+ */
+void PyConsole_EnhEditor::insertFromMimeData(const QMimeData * source)
+{
+ if (_multi_line_paste)
+ return;
+
+ if (source->hasText())
+ {
+ QString s = source->text();
+ if (s.contains("\n"))
+ multilinePaste(s);
+ else
+ PyConsole_Editor::insertFromMimeData(source);
+ }
+ else
+ {
+ PyConsole_Editor::insertFromMimeData(source);
+ }
+}
+
+
+void PyConsole_EnhEditor::multilinePaste(const QString & s)
+{
+ // Turn on multi line pasting mode
+ _multi_line_paste = true;
+
+ // Split the string:
+ QString s2 = s;
+ s2.replace("\r", ""); // Windows string format converted to Unix style
+
+ QStringList lst = s2.split(QChar('\n'), QString::KeepEmptyParts);
+
+ // Perform the proper paste operation for the first line to handle the case where
+ // sth was already there:
+ QMimeData source;
+ source.setText(lst[0]);
+ PyConsole_Editor::insertFromMimeData(&source);
+
+ // Prepare what will have to be executed after the first line:
+ _multi_line_content = std::queue<QString>();
+ for (int i = 1; i < lst.size(); ++i)
+ _multi_line_content.push(lst[i]);
+
+ // Trigger the execution of the first (mixed) line
+ handleReturn();
+
+ // See customEvent() and multiLineProcessNext() for the rest of the handling.
+}
+
+/**
+ * Process the next line in the queue of a multiple copy/paste:
+ */
+void PyConsole_EnhEditor::multiLineProcessNextLine()
+{
+ if (!_multi_line_paste)
+ return;
+
+ QString line(_multi_line_content.front());
+ _multi_line_content.pop();
+ if (!_multi_line_content.size())
+ {
+ // last line in the queue, just paste it
+ addText(line, false, false);
+ _multi_line_paste = false;
+ }
+ else
+ {
+ // paste the line and simulate a <RETURN> key stroke
+ addText(line, false, false);
+ handleReturn();
+ }
+}
--- /dev/null
+// Copyright (C) 2007-2013 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.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// Author : Adrien Bruneton (CEA/DEN)
+// Created on: 4 avr. 2013
+
+#ifndef PYCONSOLE_ENHEDITOR_H_
+#define PYCONSOLE_ENHEDITOR_H_
+
+#include "PyConsole.h"
+
+#include "PyConsole_Editor.h"
+#include <QObject>
+#include <queue>
+
+class PyConsole_EnhInterp;
+
+/**
+ * Enhanced Python editor handling tab completion.
+ */
+class PYCONSOLE_EXPORT PyConsole_EnhEditor: public PyConsole_Editor
+{
+ Q_OBJECT;
+
+public:
+ PyConsole_EnhEditor(PyConsole_EnhInterp * interp, QWidget * parent=0);
+ virtual ~PyConsole_EnhEditor() {}
+
+signals:
+ /**
+ * Signal emitted by the editor widget when the doc string should be updated.
+ * @param doc a HTML block with the formatted doc string.
+ * TODO: for now this signal is left uncaught.
+ */
+ void updateDoc(QString doc);
+
+protected:
+ /** List of separators identifying the last parsable token for completion */
+ static const std::vector<QString> SEPARATORS;
+
+ /** Maximum number of completions shown at once */
+ static const int MAX_COMPLETIONS = 70;
+
+ /** Are we in completion mode */
+ bool _tab_mode;
+
+ /** String on which the dir() comamnd is executed */
+ QString _compl_before_point;
+ /** String on which the results of the dir() are matched */
+ QString _compl_after_point;
+
+ /** Cursor position when <TAB> is hit */
+ int _cursor_pos;
+
+ /** Are we currently pasting several lines */
+ bool _multi_line_paste;
+
+ /** Queue of lines being pasted */
+ std::queue<QString> _multi_line_content;
+
+ // Overrides:
+ virtual void keyPressEvent ( QKeyEvent* event);
+ virtual void customEvent( QEvent* event);
+ virtual void mousePressEvent( QMouseEvent* event );
+ virtual void insertFromMimeData(const QMimeData * source);
+
+ virtual PyInterp_Request* createTabRequest( const QString& input );
+ virtual void handleTab();
+ virtual void handleBackTab();
+ virtual void clearCompletion();
+ virtual void formatCompletion(const std::vector<QString> & matches, QString & result) const;
+ virtual QString formatDocHTML(const QString & doc) const;
+
+ virtual void multilinePaste(const QString & s);
+ virtual void multiLineProcessNextLine();
+
+private:
+ void extractCommon(const std::vector<QString> & matches, QString & result) const;
+
+};
+
+#endif /* PYCONSOLE_ENHEDITOR_H_ */
--- /dev/null
+// Copyright (C) 2007-2013 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.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// Author : Adrien Bruneton (CEA/DEN)
+// Created on: 4 avr. 2013
+
+
+#include "PyConsole.h"
+
+#include "PyConsole_EnhInterp.h"
+
+#include <pythonrun.h>
+#include <string>
+#include <QRegExp>
+
+static const char * tmp_k[] = {"and", "as", "assert", "break", "class",
+ "continue", "def", "del",
+ "elif", "else", "except", "exec", "finally", "for", "from", "global", "if",
+ "import", "in", "is", "lambda", "not", "or", "pass", "print", "raise",
+ "return", "try", "while", "with", "yield"};
+
+const std::vector<QString> PyConsole_EnhInterp::PYTHON_KEYWORDS = \
+ std::vector<QString>(tmp_k, tmp_k+sizeof(tmp_k)/sizeof(tmp_k[0]));
+
+/*!
+ \brief Run Python dir() command and saves the result internally in _lastPy
+ \param dirArgument Python expression to pass to the dir command. The parsing of what the
+ user actually started typing is dedicated to the caller
+ \param startMatch string representing the begining of the patter to be completed. For example when
+ the user types "a_string_variable.rsp <TAB>", this is "rsp".
+ \return command exit status - 0 = success
+*/
+int PyConsole_EnhInterp::runDirCommand(const QString & dirArgument, const QString & startMatch)
+{
+ int ret;
+ std::vector<QString> v;
+
+ clearCompletion();
+ if ( (ret = runDirAndExtract(dirArgument, startMatch, _last_matches)) )
+ return ret;
+
+ // If dirArgument is empty, we append the __builtins__
+ if (dirArgument.isEmpty())
+ {
+ if ( (ret = runDirAndExtract(QString("__builtins__"), startMatch, _last_matches, false)) )
+ return ret;
+
+ // ... and we match on Python's keywords as well:
+ for (std::vector<QString>::const_iterator it = PYTHON_KEYWORDS.begin(); it != PYTHON_KEYWORDS.end(); it++)
+ if ((*it).startsWith(startMatch))
+ _last_matches.push_back(*it);
+ }
+
+ // Try to get doc string of the first match
+ if (_last_matches.size() > 0)
+ {
+ QString cmd("");
+ if (dirArgument.trimmed() != "")
+ cmd = dirArgument + ".";
+ cmd += _last_matches[0] + ".__doc__";
+ PyObject * str = PyRun_String(cmd.toStdString().c_str(), Py_eval_input, _g, _g);
+ if (!str || str == Py_None || !PyString_Check(str))
+ {
+ if (!str)
+ PyErr_Clear();
+ _doc_str = "";
+ }
+ else
+ _doc_str = QString(PyString_AsString(str));
+ Py_XDECREF(str);
+ }
+
+ // The command has been successfully executed
+ return 0;
+}
+
+/**
+ * See runDirCommand().
+ * @param dirArgument see runDirCommand()
+ * @param startMatch see runDirCommand()
+ * @param[out] result the list of matches
+ * @param discardSwig if true a regular expression is used to discard all static method generated
+ * by SWIG. typically: MEDCouplingUMesh_Blabla
+ * @return -1 if the call to dir() or the parsing of the result failed, 0 otherwise.
+ */
+int PyConsole_EnhInterp::runDirAndExtract(const QString& dirArgument,
+ const QString & startMatch, std::vector<QString> & result,
+ bool discardSwig) const
+{
+ QRegExp re("^[A-Z].+_[A-Z]+[a-z]+.+$"); // discard SWIG static method, e.g. MEDCouplingUMesh_Blabla
+ QString command("dir(" + dirArgument + ")");
+ PyObject * plst = PyRun_String(command.toStdString().c_str(), Py_eval_input, _g, _g);
+ if(!plst || plst == Py_None) {
+ if(!plst)
+ PyErr_Clear();
+
+ Py_XDECREF(plst);
+ return -1;
+ }
+
+ // Extract the returned list and convert it to a vector<>
+ if (!PySequence_Check(plst))
+ {
+ // Should never happen ...
+ //std::cerr << "not a list!" << std::endl;
+ Py_XDECREF(plst);
+ return -1;
+ }
+
+ // Convert plst to a vector of QString
+ int n = PySequence_Length(plst);
+ for (int i = 0; i < n; i++)
+ {
+ PyObject * it;
+ it = PySequence_GetItem(plst, i);
+ QString s(PyString_AsString(it));
+ // if the method is not from swig, not static (guessed from the reg exp) and matches
+ // what is already there
+ if (s.startsWith(startMatch))
+ if(!discardSwig || (!re.exactMatch(s) && !s.contains("swig")))
+ result.push_back(s);
+ Py_DECREF(it);
+ }
+ Py_DECREF(plst);
+
+ return 0;
+}
+
+/**
+ * Clear internal members containing the last completion results.
+ */
+void PyConsole_EnhInterp::clearCompletion()
+{
+ _last_matches.resize(0);
+ _doc_str = QString("");
+}
+
+
+
--- /dev/null
+// Copyright (C) 2007-2013 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.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// Author : Adrien Bruneton (CEA/DEN)
+// Created on: 4 avr. 2013
+
+
+#ifndef PYCONSOLE_ENHINTERP_H_
+#define PYCONSOLE_ENHINTERP_H_
+
+#include "PyConsole.h"
+
+#include <Python.h>
+#include "PyConsole_Interp.h"
+
+#include <vector>
+#include <QString>
+
+/**
+ * Enhanced Python interpreter used for auto-completion.
+ * This extends PyConsole_Interp with an API wrapping the Python dir() command nicely.
+ */
+class PYCONSOLE_EXPORT PyConsole_EnhInterp: public PyConsole_Interp
+{
+public:
+ PyConsole_EnhInterp()
+ : PyConsole_Interp(), _last_matches(0), _doc_str("")
+ {}
+
+ virtual ~PyConsole_EnhInterp() {}
+
+ const std::vector<QString>& getLastMatches() const { return _last_matches; }
+ const QString & getDocStr() const { return _doc_str; }
+
+ virtual int runDirCommand(const QString& dirArgument, const QString& startMatch);
+ virtual void clearCompletion();
+
+protected:
+ /** Hard coded list of Python keywords */
+ static const std::vector<QString> PYTHON_KEYWORDS;
+
+ /** Last computed matches */
+ std::vector<QString> _last_matches;
+ /** Doc string of the first match - when only one match it will be displayed by the Editor*/
+ QString _doc_str;
+
+ virtual int runDirAndExtract(const QString& dirArgument, const QString & startMatch,
+ std::vector<QString> & result, bool discardSwig=true) const;
+
+};
+
+#endif /* PYCONSOLE_ENHINTERP_H_ */
--- /dev/null
+// Copyright (C) 2007-2013 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.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// Author : Vadim SANDLER (Open CASCADE S.A.S), Adrien Bruneton (CEA/DEN)
+
+#include "PyConsole_Event.h"
--- /dev/null
+// Copyright (C) 2007-2013 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.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// Author : Vadim SANDLER (Open CASCADE S.A.S), Adrien Bruneton (CEA/DEN)
+
+#ifndef PYCONSOLE_EVENT_H
+#define PYCONSOLE_EVENT_H
+
+#include "PyConsole.h"
+
+#include <QEvent>
+#include <QString>
+
+/*!
+ \class PrintEvent
+ \brief Python command output backend event.
+ \internal
+*/
+class PrintEvent : public QEvent
+{
+public:
+ static const int EVENT_ID = 65432;
+
+ /*!
+ \brief Constructor
+ \param c message text (python trace)
+ \param isError default to false - if true indicates that an error is being printed.
+ */
+ PrintEvent( const char* c, bool isError = false) :
+ QEvent( (QEvent::Type)EVENT_ID ), myText( c ), errorFlag(isError)
+ {}
+
+ /*!
+ \brief Get message
+ \return message text (python trace)
+ */
+ QString text() const { return myText; }
+
+ /**
+ * @return true if this is an error message
+ */
+ bool isError() const { return errorFlag; }
+
+protected:
+ QString myText; //!< Event message (python trace)
+
+ /** Set to true if an error msg is to be displayed */
+ bool errorFlag;
+};
+
+#endif // PYCONSOLE_EVENT_H
--- /dev/null
+// Copyright (C) 2007-2013 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.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// Author : Adrien Bruneton (CEA/DEN)
+// Created on: 3 avr. 2013
+
+#include "PyConsole_Request.h"
+
+#include "PyInterp_Event.h"
+#include "PyConsole_Event.h"
+#include "PyConsole_EnhInterp.h"
+#include "PyConsole_EnhEditor.h"
+
+#include <QCoreApplication>
+
+/**
+ * Constructor.
+ * @param theInterp interpreter that will execute the command
+ * @param theCommand command text
+ * @param theListener editor object that will receive the response events after execution
+ * of the request
+ * @param sync
+ */
+ExecCommand::ExecCommand( PyInterp_Interp* theInterp,
+ const QString& theCommand,
+ PyConsole_Editor* theListener,
+ bool sync )
+ : PyInterp_LockRequest( theInterp, theListener, sync ),
+ myCommand( theCommand ), myState( PyInterp_Event::ES_OK )
+ {}
+
+/**
+ * Execute the command by calling the run() method of the embedded interpreter.
+ */
+void ExecCommand::execute()
+{
+ if ( myCommand != "" )
+ {
+ int ret = getInterp()->run( myCommand.toUtf8().data() );
+ if ( ret < 0 )
+ myState = PyInterp_Event::ES_ERROR;
+ else if ( ret > 0 )
+ myState = PyInterp_Event::ES_INCOMPLETE;
+ }
+}
+
+/**
+ * Create the event indicating the status of the request execution.
+ * @return a QEvent
+ */
+QEvent* ExecCommand::createEvent()
+{
+ if ( IsSync() )
+ QCoreApplication::sendPostedEvents( listener(), PrintEvent::EVENT_ID );
+ return new PyInterp_Event( myState, this );
+}
+
+
+/*!
+ Constructor.
+ Creates a new python completion request.
+ \param theInterp python interpreter
+ \param input string containing the dir() command to be executed
+ \param startMatch part to be matched with the results of the dir() command
+ \param theListener widget to get the notification messages
+ \param sync if True the request is processed synchronously
+*/
+CompletionCommand::CompletionCommand( PyConsole_EnhInterp* theInterp,
+ const QString& input,
+ const QString& startMatch,
+ PyConsole_EnhEditor* theListener,
+ bool sync)
+ : PyInterp_LockRequest( theInterp, theListener, sync ),
+ _tabSuccess(false), _dirArg(input), _startMatch(startMatch)
+{}
+
+/**
+ * Execute the completion command by wrapping the runDirCommand() of the
+ * embedded enhanced interpreter.
+ */
+void CompletionCommand::execute()
+{
+ PyConsole_EnhInterp * interp = static_cast<PyConsole_EnhInterp *>(getInterp());
+ int ret = interp->runDirCommand( _dirArg, _startMatch);
+ if (ret == 0)
+ _tabSuccess = true;
+ else
+ _tabSuccess = false;
+}
+
+/**
+ * Create the event indicating the return value of the completion command.
+ * @return
+ */
+QEvent* CompletionCommand::createEvent()
+{
+ int typ = _tabSuccess ? PyInterp_Event::ES_TAB_COMPLETE_OK : PyInterp_Event::ES_TAB_COMPLETE_ERR;
+
+ return new PyInterp_Event( typ, this);
+}
+
+
+
--- /dev/null
+// Copyright (C) 2007-2013 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.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// Author : Adrien Bruneton (CEA/DEN)
+// Created on: 3 avr. 2013
+
+
+#ifndef PYCONSOLE_REQUEST_H_
+#define PYCONSOLE_REQUEST_H_
+
+#include "PyConsole.h"
+#include "PyInterp_Request.h"
+
+#include <vector>
+#include <QString>
+#include <QEvent>
+
+class PyInterp_Interp;
+class PyConsole_Editor;
+
+/*!
+ \class ExecCommand
+ \brief Python command execution request.
+ \internal
+*/
+class ExecCommand : public PyInterp_LockRequest
+{
+public:
+ /*!
+ \brief Constructor.
+
+ Creates new python command execution request.
+ \param theInterp python interpreter
+ \param theCommand python command
+ \param theListener widget to get the notification messages
+ \param sync if True the request is processed synchronously
+ */
+ ExecCommand( PyInterp_Interp* theInterp,
+ const QString& theCommand,
+ PyConsole_Editor* theListener,
+ bool sync = false );
+
+protected:
+ /*!
+ \brief Execute the python command in the interpreter and
+ get its execution status.
+ */
+ virtual void execute();
+
+ /*!
+ \brief Create and return a notification event.
+ \return new notification event
+ */
+ virtual QEvent* createEvent();
+
+private:
+ QString myCommand; //!< Python command
+ int myState; //!< Python command execution status
+};
+
+class PyConsole_EnhInterp;
+class PyConsole_EnhEditor;
+
+class CompletionCommand : public PyInterp_LockRequest
+{
+public:
+ CompletionCommand( PyConsole_EnhInterp* theInterp,
+ const QString& input,
+ const QString& startMatch,
+ PyConsole_EnhEditor* theListener,
+ bool sync = false );
+
+
+protected:
+ /** List of separators identifying the last parsable token for completion */
+ static const std::vector<QString> SEPARATORS;
+
+ /** String to be passed to the dir() command */
+ QString _dirArg;
+ /** Begining of the command (as typed by the user) */
+ QString _startMatch;
+ /** was the completion command successful */
+ bool _tabSuccess;
+
+ virtual void execute();
+ virtual QEvent* createEvent();
+
+};
+
+#endif /* PYCONSOLE_REQUEST_H_ */
SET(PyInterp_SOURCES
PyInterp_Interp.cxx
PyInterp_Dispatcher.cxx
+ PyInterp_Event.cxx
+ PyInterp_Request.cxx
)
ADD_DEFINITIONS(${QT_DEFINITIONS} ${PYTHON_DEFINITIONS})
PyInterp.h
PyInterp_Interp.h
PyInterp_Dispatcher.h
+ PyInterp_Event.h
+ PyInterp_Request.h
)
INSTALL(FILES ${COMMON_HEADERS_H} DESTINATION ${GUI_salomeinclude_HEADERS})
salomeinclude_HEADERS = \
PyInterp.h \
PyInterp_Interp.h \
+ PyInterp_Event.h \
+ PyInterp_Request.h \
PyInterp_Dispatcher.h
dist_libPyInterp_la_SOURCES = \
PyInterp_Interp.cxx \
+ PyInterp_Event.cxx \
+ PyInterp_Request.cxx \
PyInterp_Dispatcher.cxx
MOC_FILES = PyInterp_Watcher_moc.cxx
#include "PyInterp_Dispatcher.h" // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!!
#include "PyInterp_Interp.h"
#include "PyInterp_Watcher.h"
-#include <SALOME_Event.h>
+#include "PyInterp_Request.h"
#include <QObject>
#include <QCoreApplication>
-class PyInterp_ExecuteEvent: public SALOME_Event
-{
-public:
- PyInterp_Request* myRequest;
- PyInterp_ExecuteEvent( PyInterp_Request* r )
- : myRequest( r ) {}
- virtual void Execute()
- {
- myRequest->execute();
- }
-};
-
PyInterp_Dispatcher* PyInterp_Dispatcher::myInstance = 0;
void PyInterp_Request::process()
delete request;
}
-QEvent* PyInterp_Request::createEvent() const
+QEvent* PyInterp_Request::createEvent()
{
- return new PyInterp_Event( PyInterp_Event::ES_NOTIFY, (PyInterp_Request*)this );
+ return new PyInterp_Event( PyInterp_Event::ES_NOTIFY, this );
}
void PyInterp_Request::processEvent( QObject* o )
// File : PyInterp_Dispatcher.h
// Author : Sergey Anikin, OCC
-// Module : SALOME
+// Module : GUI
//
#ifndef PYINTERP_DISPATCHER_H
#define PYINTERP_DISPATCHER_H
#include "PyInterp.h" // !!! WARNING !!! THIS INCLUDE MUST BE THE VERY FIRST !!!
+#include "PyInterp_Request.h" // full include instead of forward declaration
+ // everyone inc'ing the Dispatcher will get the requests for free.
+
#include <QMutex>
#include <QThread>
-#include <QEvent>
#include <QQueue>
class QObject;
-
-class PyInterp_Interp;
class PyInterp_Watcher;
-class PyInterp_Dispatcher;
-class PyInterp_ExecuteEvent;
-
-class PYINTERP_EXPORT PyInterp_Request
-{
- friend class PyInterp_Dispatcher;
- friend class PyInterp_ExecuteEvent;
-
- PyInterp_Request();
- PyInterp_Request( const PyInterp_Request& );
-
-protected:
- virtual ~PyInterp_Request() {};
- // protected destructor - to control deletion of requests
-
-public:
- PyInterp_Request( QObject* listener, bool sync = false )
- : myIsSync( sync ), myListener( listener ) {};
-
- static void Destroy( PyInterp_Request* );
- // Deletes a request
-
- bool IsSync() const { return myIsSync; }
- // Returns true if this request should be processed synchronously,
- // without putting it to a queue
-
-protected:
- virtual void safeExecute();
-
- virtual void execute() = 0;
- // Should be redefined in successors, contains actual request code
-
- virtual QEvent* createEvent() const;
- // This method can be overridden to customize notification event creation
-
- virtual void processEvent( QObject* );
-
- QObject* listener() const { return myListener; }
- void setListener( QObject* );
-
-private:
- void process();
-
-private:
- QMutex myMutex;
- bool myIsSync;
- QObject* myListener;
-};
-
-class PYINTERP_EXPORT PyInterp_LockRequest : public PyInterp_Request
-{
-public:
- PyInterp_LockRequest( PyInterp_Interp* interp, QObject* listener = 0, bool sync = false )
- : PyInterp_Request( listener, sync ), myInterp( interp ) {}
-
-protected:
- PyInterp_Interp* getInterp() const { return myInterp; }
-
- virtual void safeExecute();
-
-private:
- PyInterp_Interp* myInterp;
-};
-
-class PYINTERP_EXPORT PyInterp_Event : public QEvent
-{
- PyInterp_Event();
- PyInterp_Event( const PyInterp_Event& );
-
-public:
- //Execution state
- enum { ES_NOTIFY = QEvent::User + 5000, ES_OK, ES_ERROR, ES_INCOMPLETE, ES_LAST };
-
- PyInterp_Event( int type, PyInterp_Request* request )
- : QEvent( (QEvent::Type)type ), myRequest( request ) {}
-
- virtual ~PyInterp_Event();
-
- PyInterp_Request* GetRequest() const { return myRequest; }
- operator PyInterp_Request*() const { return myRequest; }
-
-private:
- PyInterp_Request* myRequest;
-};
class PYINTERP_EXPORT PyInterp_Dispatcher : protected QThread
{
--- /dev/null
+// Copyright (C) 2007-2013 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.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File : PyInterp_Request.h
+// Author : Sergey Anikin, OCC, Adrien Bruneton (CEA/DEN)
+// Module : GUI
+
+#include "PyInterp_Event.h"
+#include "PyInterp_Request.h"
+
+void PyInterp_ExecuteEvent::Execute()
+{
+ myRequest->execute();
+}
--- /dev/null
+
+// Copyright (C) 2007-2013 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.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File : PyInterp_Request.h
+// Author : Sergey Anikin, OCC, Adrien Bruneton (CEA/DEN)
+// Module : GUI
+
+#ifndef PYINTERP_EVENT_H
+#define PYINTERP_EVENT_H
+
+#include "PyInterp.h"
+
+#include <SALOME_Event.h>
+
+#include <QEvent>
+
+class PyInterp_Request;
+
+class PyInterp_ExecuteEvent: public SALOME_Event
+{
+public:
+ PyInterp_ExecuteEvent( PyInterp_Request* r )
+ : myRequest( r ) {}
+
+ virtual void Execute();
+
+protected:
+ PyInterp_Request* myRequest;
+};
+
+/**
+ * Events thrown by the interpreter having executed a command and indicating
+ * the return status.
+ */
+class PYINTERP_EXPORT PyInterp_Event : public QEvent
+{
+ PyInterp_Event();
+ PyInterp_Event( const PyInterp_Event& );
+
+public:
+ //Execution state
+ enum { ES_NOTIFY = QEvent::User + 5000, ES_OK, ES_ERROR, ES_INCOMPLETE,
+ ES_TAB_COMPLETE_OK, ES_TAB_COMPLETE_ERR, ES_LAST };
+
+ PyInterp_Event( int type, PyInterp_Request* request )
+ : QEvent( (QEvent::Type)type ), myRequest( request ) {}
+
+ virtual ~PyInterp_Event();
+
+ PyInterp_Request* GetRequest() const { return myRequest; }
+ operator PyInterp_Request*() const { return myRequest; }
+
+private:
+ PyInterp_Request* myRequest;
+};
+
+#endif // PYINTERP_EVENT_H
--- /dev/null
+// Copyright (C) 2007-2013 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.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File : PyInterp_Request.h
+// Author : Sergey Anikin, OCC, Adrien Bruneton (CEA/DEN)
+// Module : GUI
+
+#include "PyInterp_Request.h"
+
--- /dev/null
+// Copyright (C) 2007-2013 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.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File : PyInterp_Request.h
+// Author : Sergey Anikin (OCC), Adrien Bruneton (CEA/DEN)
+// Module : GUI
+
+#ifndef PYINTERP_REQUEST_H
+#define PYINTERP_REQUEST_H
+
+#include "PyInterp.h"
+#include "PyInterp_Event.h"
+
+#include <QMutex>
+#include <QObject>
+
+class PyInterp_Interp;
+class PyInterp_Watcher;
+class PyInterp_Dispatcher;
+class PyInterp_ExecuteEvent;
+class PyConsole_Editor;
+
+class PYINTERP_EXPORT PyInterp_Request
+{
+ friend class PyInterp_Dispatcher;
+ friend class PyInterp_ExecuteEvent;
+
+ PyInterp_Request();
+ PyInterp_Request( const PyInterp_Request& );
+
+protected:
+ virtual ~PyInterp_Request() {};
+ // protected destructor - to control deletion of requests
+
+public:
+ PyInterp_Request( QObject* listener, bool sync = false )
+ : myIsSync( sync ), myListener( listener ) {};
+
+ static void Destroy( PyInterp_Request* );
+ // Deletes a request
+
+ bool IsSync() const { return myIsSync; }
+ // Returns true if this request should be processed synchronously,
+ // without putting it to a queue
+
+protected:
+ virtual void safeExecute();
+
+ virtual void execute() = 0;
+ // Should be redefined in successors, contains actual request code
+
+ virtual QEvent* createEvent();
+ // This method can be overridden to customize notification event creation
+
+ virtual void processEvent( QObject* );
+
+ QObject* listener() const { return myListener; }
+ void setListener( QObject* );
+
+private:
+ void process();
+
+private:
+ QMutex myMutex;
+ bool myIsSync;
+ QObject* myListener;
+};
+
+class PYINTERP_EXPORT PyInterp_LockRequest : public PyInterp_Request
+{
+public:
+
+ PyInterp_LockRequest( PyInterp_Interp* interp, QObject* listener = 0, bool sync = false )
+ : PyInterp_Request( listener, sync ), myInterp( interp )
+ {}
+
+protected:
+ PyInterp_Interp* getInterp() const { return myInterp; }
+
+ virtual void safeExecute();
+
+private:
+ PyInterp_Interp* myInterp;
+};
+
+#endif // PYINTERP_REQUEST_H
${CMAKE_CURRENT_SOURCE_DIR}/../../SUITApp
${CMAKE_CURRENT_SOURCE_DIR}/../../CAM
${CMAKE_CURRENT_SOURCE_DIR}/../../STD
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../Event
)
SET(COMMON_LIBS ${PYTHON_LIBRARIES} ${PYQT_LIBRARIES} ${VTK_LIBRARIES} ${OPENGL_LIBRARIES} PyInterp LightApp)
-I$(srcdir)/../../Plot2d -I$(srcdir)/../../OCCViewer \
-I$(srcdir)/../../CAM -I$(srcdir)/../../STD \
-I$(srcdir)/../../SUITApp \
- -I$(srcdir)/../../CAM -I$(srcdir)/../../STD
+ -I$(srcdir)/../../CAM -I$(srcdir)/../../STD -I$(srcdir)/../../Event
if GUI_ENABLE_CORBA
libSalomePyQtGUILight_la_CPPFLAGS += -I$(srcdir)/../../SalomeApp \
//Handle(SALOME_InteractiveObject) anObj = anAct->getIO();
//if(!anObj.IsNull() && anObj->hasEntry() && aStudy)
// ToolsGUI::SetVisibility(aStudy,anObj->getEntry(),false,this);
- if(forced)
+ if(forced){
if(SVTK_Renderer* aRnd = aView->GetRenderer())
aRnd->RemoveActor(anAct);
- else{
+ }else{
// just erase actor
anAct->SetVisibility( false );
// erase dependent actors
}
else if ( flag == WT_PyConsole )
{
- PyConsole_Console* pyCons = new PyConsole_Console( desktop(), new SalomeApp_PyInterp() );
+ PyConsole_Console* pyCons = new PyConsole_EnhConsole( desktop(), new SalomeApp_PyInterp() );
pyCons->setWindowTitle( tr( "PYTHON_CONSOLE" ) );
pyCons->setFont(resourceMgr()->fontValue( "PyConsole", "font" ));
pyCons->setIsShowBanner(resourceMgr()->booleanValue( "PyConsole", "show_banner", true ));
* initstate & initcontext redefined here.
*/
SalomeApp_PyInterp::SalomeApp_PyInterp():
- PyConsole_Interp(), myFirstRun( true )
+ PyConsole_EnhInterp(), myFirstRun( true )
{
}
#ifndef _SalomeApp_PYINTERP_H_
#define _SalomeApp_PYINTERP_H_
-#include <PyConsole_Interp.h> // this include must be first (see PyInterp_base.h)!
+#include <PyConsole_EnhInterp.h> // this include must be first (see PyInterp_base.h)!
-class SalomeApp_PyInterp : public PyConsole_Interp
+class SalomeApp_PyInterp : public PyConsole_EnhInterp
{
public:
SalomeApp_PyInterp();