Salome HOME
Update from BR_V5_DEV 13Feb2009
[modules/gui.git] / src / PyConsole / PyConsole_Console.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 // File   : PyConsole_Console.cxx
23 // Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
24 //
25 /*!
26   \class PyConsole_Console
27   \brief Python console widget.
28 */  
29
30 #include "PyConsole_Interp.h"   /// !!! WARNING !!! THIS INCLUDE MUST BE VERY FIRST !!!
31 #include "PyConsole_Console.h"
32 #include "PyConsole_Editor.h"
33
34 #include <Qtx.h>
35
36 #include <QAction>
37 #include <QApplication>
38 #include <QClipboard>
39 #include <QEvent>
40 #include <QMenu>
41 #include <QVBoxLayout>
42
43 /*!
44   \brief Constructor.
45
46   Creates new python console widget.
47   \param parent parent widget
48   \param interp python interpreter
49 */
50 PyConsole_Console::PyConsole_Console( QWidget* parent, PyConsole_Interp* interp )
51 : QWidget( parent ),
52   myEditor( 0 )
53 {
54   // create python interpreter
55   myInterp = interp;
56   if ( !myInterp )
57     myInterp = new PyConsole_Interp();
58   
59   // initialize Python interpretator
60   myInterp->initialize();
61   
62   // create editor console
63   QVBoxLayout* lay = new QVBoxLayout( this );
64   lay->setMargin( 0 );
65   myEditor = new PyConsole_Editor( myInterp, this );
66   myEditor->viewport()->installEventFilter( this );
67   lay->addWidget( myEditor );
68
69   createActions();
70 }
71
72 /*!
73   \brief Destructor.
74
75   Does nothing for the moment.
76 */
77 PyConsole_Console::~PyConsole_Console()
78 {
79 }
80
81 /*!
82   \brief Execute python command in the interpreter.
83   \param command string with command and arguments
84 */
85 void PyConsole_Console::exec( const QString& command )
86 {
87   if ( myEditor )
88     myEditor->exec( command );
89 }
90
91 /*!
92   \brief Execute python command in the interpreter 
93          and wait until it is finished.
94   
95   Block execution of main application until the python command is executed.
96   \param command string with command and arguments
97 */
98 void PyConsole_Console::execAndWait( const QString& command )
99 {
100   if ( myEditor )
101     myEditor->execAndWait( command );
102 }
103
104 /*!
105   \brief Get synchronous mode flag value.
106   
107   \sa setIsSync()
108   \return True if python console works in synchronous mode
109 */
110 bool PyConsole_Console::isSync() const
111 {
112   return myEditor->isSync();
113 }
114
115 /*!
116   \brief Set synchronous mode flag value.
117
118   In synhronous mode the Python commands are executed in the GUI thread
119   and the GUI is blocked until the command is finished. In the asynchronous
120   mode each Python command is executed in the separate thread that does not
121   block the main GUI loop.
122
123   \param on synhronous mode flag
124 */
125 void PyConsole_Console::setIsSync( const bool on )
126 {
127   myEditor->setIsSync( on );
128 }
129
130 /*!
131   \brief Change the python console's font.
132   \param f new font
133 */
134 void PyConsole_Console::setFont( const QFont& f )
135 {
136   if( myEditor )
137     myEditor->setFont( f );
138 }
139
140 /*!
141   \brief Get python console font.
142   \return current python console's font
143 */
144 QFont PyConsole_Console::font() const
145 {
146   QFont res;
147   if( myEditor )
148     res = myEditor->font();
149   return res;
150 }
151
152 /*!
153   \brief Event handler.
154
155   Handles context menu request event.
156
157   \param o object
158   \param e event
159   \return True if the event is processed and further processing should be stopped
160 */
161 bool PyConsole_Console::eventFilter( QObject* o, QEvent* e )
162 {
163   if ( o == myEditor->viewport() && e->type() == QEvent::ContextMenu )
164   {
165     contextMenuRequest( (QContextMenuEvent*)e );
166     return true;
167   }
168   return QWidget::eventFilter( o, e );
169 }
170
171 /*!
172   \brief Create the context popup menu.
173
174   Fill in the popup menu with the commands.
175
176   \param menu context popup menu
177 */
178 void PyConsole_Console::contextMenuPopup( QMenu* menu )
179 {
180   if ( myEditor->isReadOnly() )
181     return;
182
183   menu->addAction( myActions[CopyId] );
184   menu->addAction( myActions[PasteId] );
185   menu->addAction( myActions[ClearId] );
186   menu->addSeparator();
187   menu->addAction( myActions[SelectAllId] );
188
189   Qtx::simplifySeparators( menu );
190
191   updateActions();
192 }
193
194 /*!
195   \brief Set actions to be visible in the context popup menu.
196   
197   Actions, which IDs are set in \a flags parameter, will be shown in the 
198   context popup menu. Other actions will not be shown.
199
200   \param flags ORed together actions flags
201 */
202 void PyConsole_Console::setMenuActions( const int flags )
203 {
204   myActions[CopyId]->setVisible( flags & CopyId );
205   myActions[PasteId]->setVisible( flags & PasteId );
206   myActions[ClearId]->setVisible( flags & ClearId );
207   myActions[SelectAllId]->setVisible( flags & SelectAllId );
208 }
209
210 /*!
211   \brief Get menu actions which are currently visible in the context popup menu.
212   \return ORed together actions flags
213   \sa setMenuActions()
214 */
215 int PyConsole_Console::menuActions() const
216 {
217   int ret = 0;
218   ret = ret | ( myActions[CopyId]->isVisible() ? CopyId : 0 );
219   ret = ret | ( myActions[PasteId]->isVisible() ? PasteId : 0 );
220   ret = ret | ( myActions[ClearId]->isVisible() ? ClearId : 0 );
221   ret = ret | ( myActions[SelectAllId]->isVisible() ? SelectAllId : 0 );
222   return ret;
223 }
224
225 /*!
226   \brief Create menu actions.
227
228   Create context popup menu actions.
229 */
230 void PyConsole_Console::createActions()
231 {
232   QAction* a = new QAction( tr( "EDIT_COPY_CMD" ), this );
233   a->setStatusTip( tr( "EDIT_COPY_CMD" ) );
234   connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( copy() ) );
235   myActions.insert( CopyId, a );
236
237   a = new QAction( tr( "EDIT_PASTE_CMD" ), this );
238   a->setStatusTip( tr( "EDIT_PASTE_CMD" ) );
239   connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( paste() ) );
240   myActions.insert( PasteId, a );
241
242   a = new QAction( tr( "EDIT_CLEAR_CMD" ), this );
243   a->setStatusTip( tr( "EDIT_CLEAR_CMD" ) );
244   connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( clear() ) );
245   myActions.insert( ClearId, a );
246
247   a = new QAction( tr( "EDIT_SELECTALL_CMD" ), this );
248   a->setStatusTip( tr( "EDIT_SELECTALL_CMD" ) );
249   connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( selectAll() ) );
250   myActions.insert( SelectAllId, a );
251 }
252
253 /*!
254   \brief Update menu actions.
255
256   Update context popup menu action state.
257 */
258 void PyConsole_Console::updateActions()
259 {
260   myActions[CopyId]->setEnabled( myEditor->textCursor().hasSelection() );
261   myActions[PasteId]->setEnabled( !myEditor->isReadOnly() && !QApplication::clipboard()->text().isEmpty() );
262   myActions[SelectAllId]->setEnabled( !myEditor->document()->isEmpty() );
263 }