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