]> SALOME platform Git repositories - modules/gui.git/blob - src/PyConsole/PyConsole_Console.cxx
Salome HOME
0022652: [CEA 1194] Redirect the traces from embedded Python console in a log file
[modules/gui.git] / src / PyConsole / PyConsole_Console.cxx
1 // Copyright (C) 2007-2014  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, or (at your option) any later version.
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
23 // File   : PyConsole_Console.cxx
24 // Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
25 //
26 /*!
27   \class PyConsole_Console
28   \brief Python console widget.
29 */  
30
31 #include "PyConsole_Interp.h"   /// !!! WARNING !!! THIS INCLUDE MUST BE VERY FIRST !!!
32 #include "PyConsole_Console.h"
33 #include "PyConsole_EnhEditor.h"
34 #include "PyConsole_EnhInterp.h"
35
36 #include <Qtx.h>
37
38 #include <QAction>
39 #include <QApplication>
40 #include <QClipboard>
41 #include <QEvent>
42 #include <QMenu>
43 #include <QVBoxLayout>
44
45 /*!
46   \brief Constructor.
47
48   Creates new python console widget.
49   \param parent parent widget
50   \param interp python interpreter
51 */
52 PyConsole_Console::PyConsole_Console( QWidget* parent, PyConsole_Interp* interp )
53 : QWidget( parent )
54 {
55   // create python interpreter
56   myInterp = interp;
57   if ( !myInterp )
58     myInterp = new PyConsole_Interp();
59   
60   // initialize Python interpretator
61   myInterp->initialize();
62   
63   // create editor console
64   QVBoxLayout* lay = new QVBoxLayout( this );
65   lay->setMargin( 0 );
66   myEditor = new PyConsole_Editor( myInterp, this );
67   char* synchronous = getenv("PYTHON_CONSOLE_SYNC");
68   if (synchronous && atoi(synchronous))
69   {
70       myEditor->setIsSync(true);
71   }
72   myEditor->viewport()->installEventFilter( this );
73   lay->addWidget( myEditor );
74
75   createActions();
76 }
77
78 /**
79  * Protected constructor.
80  */
81 PyConsole_Console::PyConsole_Console( QWidget* parent, PyConsole_Interp* i,  PyConsole_Editor* e)
82   : QWidget (parent), myEditor(e), myInterp(i)
83 {}
84
85 /*!
86   \brief Destructor.
87
88   Does nothing for the moment.
89 */
90 PyConsole_Console::~PyConsole_Console()
91 {
92 }
93
94 /*!
95   \brief Execute python command in the interpreter.
96   \param command string with command and arguments
97 */
98 void PyConsole_Console::exec( const QString& command )
99 {
100   if ( myEditor )
101     myEditor->exec( command );
102 }
103
104 /*!
105   \brief Execute python command in the interpreter 
106          and wait until it is finished.
107   
108   Block execution of main application until the python command is executed.
109   \param command string with command and arguments
110 */
111 void PyConsole_Console::execAndWait( const QString& command )
112 {
113   if ( myEditor )
114     myEditor->execAndWait( command );
115 }
116
117 /*!
118   \brief Get synchronous mode flag value.
119   
120   \sa setIsSync()
121   \return True if python console works in synchronous mode
122 */
123 bool PyConsole_Console::isSync() const
124 {
125   return myEditor->isSync();
126 }
127
128 /*!
129   \brief Set synchronous mode flag value.
130
131   In synhronous mode the Python commands are executed in the GUI thread
132   and the GUI is blocked until the command is finished. In the asynchronous
133   mode each Python command is executed in the separate thread that does not
134   block the main GUI loop.
135
136   \param on synhronous mode flag
137 */
138 void PyConsole_Console::setIsSync( const bool on )
139 {
140   myEditor->setIsSync( on );
141 }
142
143 /*!
144   \brief Get suppress output flag value.
145   
146   \sa setIsSuppressOutput()
147   \return True if python console output is suppressed.
148 */
149 bool PyConsole_Console::isSuppressOutput() const
150 {
151   return myEditor->isSuppressOutput();
152 }
153
154 /*!
155   \brief Set suppress output flag value.
156
157   In case if suppress output flag is true, the python 
158   console output suppressed.
159
160   \param on suppress output flag
161 */
162 void PyConsole_Console::setIsSuppressOutput( const bool on )
163 {
164   myEditor->setIsSuppressOutput(on);
165 }
166
167 /*!
168   \brief Get 'show banner' flag value.
169   
170   \sa setIsShowBanner()
171   \return \c true if python console shows banner
172 */
173 bool PyConsole_Console::isShowBanner() const
174 {
175   return myEditor->isShowBanner();
176 }
177
178 /*!
179   \brief Set 'show banner' flag value.
180
181   The banner is shown in the top of the python console window.
182
183   \sa isShowBanner()
184   \param on 'show banner' flag
185 */
186 void PyConsole_Console::setIsShowBanner( const bool on )
187 {
188   myEditor->setIsShowBanner( on );
189 }
190
191 /*!
192   \brief Change the python console's font.
193   \param f new font
194 */
195 void PyConsole_Console::setFont( const QFont& f )
196 {
197   if( myEditor )
198     myEditor->setFont( f );
199 }
200
201 /*!
202   \brief Get python console font.
203   \return current python console's font
204 */
205 QFont PyConsole_Console::font() const
206 {
207   QFont res;
208   if( myEditor )
209     res = myEditor->font();
210   return res;
211 }
212
213 /*!
214   \brief Event handler.
215
216   Handles context menu request event.
217
218   \param o object
219   \param e event
220   \return True if the event is processed and further processing should be stopped
221 */
222 bool PyConsole_Console::eventFilter( QObject* o, QEvent* e )
223 {
224   if ( o == myEditor->viewport() && e->type() == QEvent::ContextMenu )
225   {
226     contextMenuRequest( (QContextMenuEvent*)e );
227     return true;
228   }
229   return QWidget::eventFilter( o, e );
230 }
231
232 /*!
233   \brief Create the context popup menu.
234
235   Fill in the popup menu with the commands.
236
237   \param menu context popup menu
238 */
239 void PyConsole_Console::contextMenuPopup( QMenu* menu )
240 {
241   if ( myEditor->isReadOnly() )
242     return;
243
244   menu->addAction( myActions[CopyId] );
245   menu->addAction( myActions[PasteId] );
246   menu->addAction( myActions[ClearId] );
247   menu->addSeparator();
248   menu->addAction( myActions[SelectAllId] );
249   menu->addSeparator();
250   menu->addAction( myActions[DumpCommandsId] );
251   menu->addAction( myActions[SaveLogId] );
252
253   Qtx::simplifySeparators( menu );
254
255   updateActions();
256 }
257
258 /*!
259   \brief Set actions to be visible in the context popup menu.
260   
261   Actions, which IDs are set in \a flags parameter, will be shown in the 
262   context popup menu. Other actions will not be shown.
263
264   \param flags ORed together actions flags
265 */
266 void PyConsole_Console::setMenuActions( const int flags )
267 {
268   myActions[CopyId]->setVisible( flags & CopyId );
269   myActions[PasteId]->setVisible( flags & PasteId );
270   myActions[ClearId]->setVisible( flags & ClearId );
271   myActions[SelectAllId]->setVisible( flags & SelectAllId );
272   myActions[DumpCommandsId]->setVisible( flags & DumpCommandsId );
273   myActions[SaveLogId]->setVisible( flags & SaveLogId );
274 }
275
276 /*!
277   \brief Get menu actions which are currently visible in the context popup menu.
278   \return ORed together actions flags
279   \sa setMenuActions()
280 */
281 int PyConsole_Console::menuActions() const
282 {
283   int ret = 0;
284   ret = ret | ( myActions[CopyId]->isVisible() ? CopyId : 0 );
285   ret = ret | ( myActions[PasteId]->isVisible() ? PasteId : 0 );
286   ret = ret | ( myActions[ClearId]->isVisible() ? ClearId : 0 );
287   ret = ret | ( myActions[SelectAllId]->isVisible() ? SelectAllId : 0 );
288   ret = ret | ( myActions[DumpCommandsId]->isVisible() ? DumpCommandsId : 0 );
289   ret = ret | ( myActions[SaveLogId]->isVisible() ? SaveLogId : 0 );
290   return ret;
291 }
292
293 /*!
294   \brief Create menu actions.
295
296   Create context popup menu actions.
297 */
298 void PyConsole_Console::createActions()
299 {
300   QAction* a = new QAction( tr( "EDIT_COPY_CMD" ), this );
301   a->setStatusTip( tr( "EDIT_COPY_CMD" ) );
302   connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( copy() ) );
303   myActions.insert( CopyId, a );
304
305   a = new QAction( tr( "EDIT_PASTE_CMD" ), this );
306   a->setStatusTip( tr( "EDIT_PASTE_CMD" ) );
307   connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( paste() ) );
308   myActions.insert( PasteId, a );
309
310   a = new QAction( tr( "EDIT_CLEAR_CMD" ), this );
311   a->setStatusTip( tr( "EDIT_CLEAR_CMD" ) );
312   connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( clear() ) );
313   myActions.insert( ClearId, a );
314
315   a = new QAction( tr( "EDIT_SELECTALL_CMD" ), this );
316   a->setStatusTip( tr( "EDIT_SELECTALL_CMD" ) );
317   connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( selectAll() ) );
318   myActions.insert( SelectAllId, a );
319   
320   a = new QAction( tr( "EDIT_DUMPCOMMANDS_CMD" ), this );
321   a->setStatusTip( tr( "EDIT_DUMPCOMMANDS_CMD" ) );
322   connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( dump() ) );
323   myActions.insert( DumpCommandsId, a );
324
325   a = new QAction( tr( "EDIT_SAVELOG_CMD" ), this );
326   a->setStatusTip( tr( "EDIT_SAVELOG_CMD" ) );
327   connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( saveLog() ) );
328   myActions.insert( SaveLogId, a );
329 }
330
331 /*!
332   \brief Update menu actions.
333
334   Update context popup menu action state.
335 */
336 void PyConsole_Console::updateActions()
337 {
338   myActions[CopyId]->setEnabled( myEditor->textCursor().hasSelection() );
339   myActions[PasteId]->setEnabled( !myEditor->isReadOnly() && !QApplication::clipboard()->text().isEmpty() );
340   myActions[SelectAllId]->setEnabled( !myEditor->document()->isEmpty() );
341 }
342
343 /**
344  * Similar to constructor of the base class but using enhanced objects.
345  * TODO: this should really be done in a factory to avoid code duplication.
346  * @param parent
347  * @param interp
348  */
349 PyConsole_EnhConsole::PyConsole_EnhConsole( QWidget* parent, PyConsole_EnhInterp* interp)
350   : PyConsole_Console(parent, interp, 0)
351 {
352   // create python interpreter
353   myInterp = interp;
354   if ( !myInterp )
355     myInterp = new PyConsole_EnhInterp();
356
357   // initialize Python interpretator
358   myInterp->initialize();
359
360   // create editor console
361   QVBoxLayout* lay = new QVBoxLayout( this );
362   lay->setMargin( 0 );
363   myEditor = new PyConsole_EnhEditor( static_cast<PyConsole_EnhInterp*>(myInterp), this );
364   char* synchronous = getenv("PYTHON_CONSOLE_SYNC");
365   if (synchronous && atoi(synchronous))
366   {
367       myEditor->setIsSync(true);
368   }
369   myEditor->viewport()->installEventFilter( this );
370   lay->addWidget( myEditor );
371
372   createActions();
373 }