Salome HOME
Merge from V6_main 01/04/2013
[modules/gui.git] / src / PyConsole / PyConsole_Console.cxx
1 // Copyright (C) 2007-2013  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
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_Editor.h"
34
35 #include <Qtx.h>
36
37 #include <QAction>
38 #include <QApplication>
39 #include <QClipboard>
40 #include <QEvent>
41 #include <QMenu>
42 #include <QVBoxLayout>
43
44 /*!
45   \brief Constructor.
46
47   Creates new python console widget.
48   \param parent parent widget
49   \param interp python interpreter
50 */
51 PyConsole_Console::PyConsole_Console( QWidget* parent, PyConsole_Interp* interp )
52 : QWidget( parent ),
53   myEditor( 0 )
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   \brief Destructor.
80
81   Does nothing for the moment.
82 */
83 PyConsole_Console::~PyConsole_Console()
84 {
85 }
86
87 /*!
88   \brief Execute python command in the interpreter.
89   \param command string with command and arguments
90 */
91 void PyConsole_Console::exec( const QString& command )
92 {
93   if ( myEditor )
94     myEditor->exec( command );
95 }
96
97 /*!
98   \brief Execute python command in the interpreter 
99          and wait until it is finished.
100   
101   Block execution of main application until the python command is executed.
102   \param command string with command and arguments
103 */
104 void PyConsole_Console::execAndWait( const QString& command )
105 {
106   if ( myEditor )
107     myEditor->execAndWait( command );
108 }
109
110 /*!
111   \brief Get synchronous mode flag value.
112   
113   \sa setIsSync()
114   \return True if python console works in synchronous mode
115 */
116 bool PyConsole_Console::isSync() const
117 {
118   return myEditor->isSync();
119 }
120
121 /*!
122   \brief Set synchronous mode flag value.
123
124   In synhronous mode the Python commands are executed in the GUI thread
125   and the GUI is blocked until the command is finished. In the asynchronous
126   mode each Python command is executed in the separate thread that does not
127   block the main GUI loop.
128
129   \param on synhronous mode flag
130 */
131 void PyConsole_Console::setIsSync( const bool on )
132 {
133   myEditor->setIsSync( on );
134 }
135
136 /*!
137   \brief Get suppress output flag value.
138   
139   \sa setIsSuppressOutput()
140   \return True if python console output is suppressed.
141 */
142 bool PyConsole_Console::isSuppressOutput() const
143 {
144   return myEditor->isSuppressOutput();
145 }
146
147 /*!
148   \brief Set suppress output flag value.
149
150   In case if suppress output flag is true, the python 
151   console output suppressed.
152
153   \param on suppress output flag
154 */
155 void PyConsole_Console::setIsSuppressOutput( const bool on )
156 {
157   myEditor->setIsSuppressOutput(on);
158 }
159
160 /*!
161   \brief Get 'show banner' flag value.
162   
163   \sa setIsShowBanner()
164   \return \c true if python console shows banner
165 */
166 bool PyConsole_Console::isShowBanner() const
167 {
168   return myEditor->isShowBanner();
169 }
170
171 /*!
172   \brief Set 'show banner' flag value.
173
174   The banner is shown in the top of the python console window.
175
176   \sa isShowBanner()
177   \param on 'show banner' flag
178 */
179 void PyConsole_Console::setIsShowBanner( const bool on )
180 {
181   myEditor->setIsShowBanner( on );
182 }
183
184 /*!
185   \brief Change the python console's font.
186   \param f new font
187 */
188 void PyConsole_Console::setFont( const QFont& f )
189 {
190   if( myEditor )
191     myEditor->setFont( f );
192 }
193
194 /*!
195   \brief Get python console font.
196   \return current python console's font
197 */
198 QFont PyConsole_Console::font() const
199 {
200   QFont res;
201   if( myEditor )
202     res = myEditor->font();
203   return res;
204 }
205
206 /*!
207   \brief Event handler.
208
209   Handles context menu request event.
210
211   \param o object
212   \param e event
213   \return True if the event is processed and further processing should be stopped
214 */
215 bool PyConsole_Console::eventFilter( QObject* o, QEvent* e )
216 {
217   if ( o == myEditor->viewport() && e->type() == QEvent::ContextMenu )
218   {
219     contextMenuRequest( (QContextMenuEvent*)e );
220     return true;
221   }
222   return QWidget::eventFilter( o, e );
223 }
224
225 /*!
226   \brief Create the context popup menu.
227
228   Fill in the popup menu with the commands.
229
230   \param menu context popup menu
231 */
232 void PyConsole_Console::contextMenuPopup( QMenu* menu )
233 {
234   if ( myEditor->isReadOnly() )
235     return;
236
237   menu->addAction( myActions[CopyId] );
238   menu->addAction( myActions[PasteId] );
239   menu->addAction( myActions[ClearId] );
240   menu->addSeparator();
241   menu->addAction( myActions[SelectAllId] );
242   menu->addSeparator();
243   menu->addAction( myActions[DumpCommandsId] );
244
245   Qtx::simplifySeparators( menu );
246
247   updateActions();
248 }
249
250 /*!
251   \brief Set actions to be visible in the context popup menu.
252   
253   Actions, which IDs are set in \a flags parameter, will be shown in the 
254   context popup menu. Other actions will not be shown.
255
256   \param flags ORed together actions flags
257 */
258 void PyConsole_Console::setMenuActions( const int flags )
259 {
260   myActions[CopyId]->setVisible( flags & CopyId );
261   myActions[PasteId]->setVisible( flags & PasteId );
262   myActions[ClearId]->setVisible( flags & ClearId );
263   myActions[SelectAllId]->setVisible( flags & SelectAllId );
264   myActions[DumpCommandsId]->setVisible( flags & DumpCommandsId );
265 }
266
267 /*!
268   \brief Get menu actions which are currently visible in the context popup menu.
269   \return ORed together actions flags
270   \sa setMenuActions()
271 */
272 int PyConsole_Console::menuActions() const
273 {
274   int ret = 0;
275   ret = ret | ( myActions[CopyId]->isVisible() ? CopyId : 0 );
276   ret = ret | ( myActions[PasteId]->isVisible() ? PasteId : 0 );
277   ret = ret | ( myActions[ClearId]->isVisible() ? ClearId : 0 );
278   ret = ret | ( myActions[SelectAllId]->isVisible() ? SelectAllId : 0 );
279   ret = ret | ( myActions[DumpCommandsId]->isVisible() ? DumpCommandsId : 0 );
280   return ret;
281 }
282
283 /*!
284   \brief Create menu actions.
285
286   Create context popup menu actions.
287 */
288 void PyConsole_Console::createActions()
289 {
290   QAction* a = new QAction( tr( "EDIT_COPY_CMD" ), this );
291   a->setStatusTip( tr( "EDIT_COPY_CMD" ) );
292   connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( copy() ) );
293   myActions.insert( CopyId, a );
294
295   a = new QAction( tr( "EDIT_PASTE_CMD" ), this );
296   a->setStatusTip( tr( "EDIT_PASTE_CMD" ) );
297   connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( paste() ) );
298   myActions.insert( PasteId, a );
299
300   a = new QAction( tr( "EDIT_CLEAR_CMD" ), this );
301   a->setStatusTip( tr( "EDIT_CLEAR_CMD" ) );
302   connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( clear() ) );
303   myActions.insert( ClearId, a );
304
305   a = new QAction( tr( "EDIT_SELECTALL_CMD" ), this );
306   a->setStatusTip( tr( "EDIT_SELECTALL_CMD" ) );
307   connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( selectAll() ) );
308   myActions.insert( SelectAllId, a );
309   
310   a = new QAction( tr( "EDIT_DUMPCOMMANDS_CMD" ), this );
311   a->setStatusTip( tr( "EDIT_DUMPCOMMANDS_CMD" ) );
312   connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( dump() ) );
313   myActions.insert( DumpCommandsId, a );
314 }
315
316 /*!
317   \brief Update menu actions.
318
319   Update context popup menu action state.
320 */
321 void PyConsole_Console::updateActions()
322 {
323   myActions[CopyId]->setEnabled( myEditor->textCursor().hasSelection() );
324   myActions[PasteId]->setEnabled( !myEditor->isReadOnly() && !QApplication::clipboard()->text().isEmpty() );
325   myActions[SelectAllId]->setEnabled( !myEditor->document()->isEmpty() );
326 }