Salome HOME
Synchronize adm files
[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
252   Qtx::simplifySeparators( menu );
253
254   updateActions();
255 }
256
257 /*!
258   \brief Set actions to be visible in the context popup menu.
259   
260   Actions, which IDs are set in \a flags parameter, will be shown in the 
261   context popup menu. Other actions will not be shown.
262
263   \param flags ORed together actions flags
264 */
265 void PyConsole_Console::setMenuActions( const int flags )
266 {
267   myActions[CopyId]->setVisible( flags & CopyId );
268   myActions[PasteId]->setVisible( flags & PasteId );
269   myActions[ClearId]->setVisible( flags & ClearId );
270   myActions[SelectAllId]->setVisible( flags & SelectAllId );
271   myActions[DumpCommandsId]->setVisible( flags & DumpCommandsId );
272 }
273
274 /*!
275   \brief Get menu actions which are currently visible in the context popup menu.
276   \return ORed together actions flags
277   \sa setMenuActions()
278 */
279 int PyConsole_Console::menuActions() const
280 {
281   int ret = 0;
282   ret = ret | ( myActions[CopyId]->isVisible() ? CopyId : 0 );
283   ret = ret | ( myActions[PasteId]->isVisible() ? PasteId : 0 );
284   ret = ret | ( myActions[ClearId]->isVisible() ? ClearId : 0 );
285   ret = ret | ( myActions[SelectAllId]->isVisible() ? SelectAllId : 0 );
286   ret = ret | ( myActions[DumpCommandsId]->isVisible() ? DumpCommandsId : 0 );
287   return ret;
288 }
289
290 /*!
291   \brief Create menu actions.
292
293   Create context popup menu actions.
294 */
295 void PyConsole_Console::createActions()
296 {
297   QAction* a = new QAction( tr( "EDIT_COPY_CMD" ), this );
298   a->setStatusTip( tr( "EDIT_COPY_CMD" ) );
299   connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( copy() ) );
300   myActions.insert( CopyId, a );
301
302   a = new QAction( tr( "EDIT_PASTE_CMD" ), this );
303   a->setStatusTip( tr( "EDIT_PASTE_CMD" ) );
304   connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( paste() ) );
305   myActions.insert( PasteId, a );
306
307   a = new QAction( tr( "EDIT_CLEAR_CMD" ), this );
308   a->setStatusTip( tr( "EDIT_CLEAR_CMD" ) );
309   connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( clear() ) );
310   myActions.insert( ClearId, a );
311
312   a = new QAction( tr( "EDIT_SELECTALL_CMD" ), this );
313   a->setStatusTip( tr( "EDIT_SELECTALL_CMD" ) );
314   connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( selectAll() ) );
315   myActions.insert( SelectAllId, a );
316   
317   a = new QAction( tr( "EDIT_DUMPCOMMANDS_CMD" ), this );
318   a->setStatusTip( tr( "EDIT_DUMPCOMMANDS_CMD" ) );
319   connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( dump() ) );
320   myActions.insert( DumpCommandsId, a );
321 }
322
323 /*!
324   \brief Update menu actions.
325
326   Update context popup menu action state.
327 */
328 void PyConsole_Console::updateActions()
329 {
330   myActions[CopyId]->setEnabled( myEditor->textCursor().hasSelection() );
331   myActions[PasteId]->setEnabled( !myEditor->isReadOnly() && !QApplication::clipboard()->text().isEmpty() );
332   myActions[SelectAllId]->setEnabled( !myEditor->document()->isEmpty() );
333 }
334
335 /**
336  * Similar to constructor of the base class but using enhanced objects.
337  * TODO: this should really be done in a factory to avoid code duplication.
338  * @param parent
339  * @param interp
340  */
341 PyConsole_EnhConsole::PyConsole_EnhConsole( QWidget* parent, PyConsole_EnhInterp* interp)
342   : PyConsole_Console(parent, interp, 0)
343 {
344   // create python interpreter
345   myInterp = interp;
346   if ( !myInterp )
347     myInterp = new PyConsole_EnhInterp();
348
349   // initialize Python interpretator
350   myInterp->initialize();
351
352   // create editor console
353   QVBoxLayout* lay = new QVBoxLayout( this );
354   lay->setMargin( 0 );
355   myEditor = new PyConsole_EnhEditor( static_cast<PyConsole_EnhInterp*>(myInterp), this );
356   char* synchronous = getenv("PYTHON_CONSOLE_SYNC");
357   if (synchronous && atoi(synchronous))
358   {
359       myEditor->setIsSync(true);
360   }
361   myEditor->viewport()->installEventFilter( this );
362   lay->addWidget( myEditor );
363
364   createActions();
365 }