Salome HOME
PR: mergefrom_BSEC_br1_14Mar04
[modules/kernel.git] / src / SALOMEGUI / QAD_PyEditor.cxx
1 //  SALOME SALOMEGUI : implementation of desktop and GUI kernel
2 //
3 //  Copyright (C) 2003  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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : QAD_PyEditor.cxx
25 //  Author : Nicolas REJNERI
26 //  Module : SALOME
27 //  $Header$
28
29 #include "QAD_PyEditor.h"
30 #include "QAD_PyInterp.h"
31 #include "QAD_Application.h"
32 #include "QAD_Desktop.h"
33 #include "QAD_Config.h"
34 #include "QAD_Tools.h"
35 #include "QAD_MessageBox.h"
36 //#include "QAD_RightFrame.h"
37 using namespace std;
38
39 #include <qapplication.h>
40 #include <qmap.h>
41 #include <qclipboard.h>
42
43 // NRI : Temporary added
44 // IDL Headers
45 #include <SALOMEconfig.h>
46 #include CORBA_SERVER_HEADER(SALOMEDS)
47 #include CORBA_SERVER_HEADER(SALOMEDS_Attributes)
48 //NRI
49
50 #define SIZEPR 4
51 enum { IdCopy, IdPaste, IdClear, IdSelectAll };
52
53 /*!
54     Constructor
55 */
56 QAD_PyEditor::QAD_PyEditor(QAD_PyInterp* interp, 
57                            QWidget *parent, const char *name)
58   : QMultiLineEdit(parent,name)
59 {
60   QString fntSet = QAD_CONFIG->getSetting("Viewer:ConsoleFont");
61   QFont myFont = QAD_Tools::stringToFont( fntSet );
62 //  QFont myFont("Courier",11);
63   setFont(myFont);
64   _interp = interp;
65   string banner = _interp->getbanner();
66   setText(banner.c_str());
67   _isInHistory = false;
68   _currentPrompt = ">>> ";
69   // put error messages of interpreter if they exist.
70   _buf.truncate(0);
71   setText(_interp->getverr());
72   setText(_currentPrompt);
73   setPalette( QAD_Application::getPalette(true) );
74   setWordWrap(NoWrap);
75   connect(this,SIGNAL(returnPressed()),this,SLOT(handleReturn()) );
76 }
77
78 /*!
79     Destructor
80 */
81 QAD_PyEditor::~QAD_PyEditor()
82 {
83 }
84
85 /*!
86     Called to insert a string s 
87 */
88 void QAD_PyEditor::setText(QString s)
89 {
90 //   MESSAGE("setText");
91   int line=numLines()-1;
92   int col=lineLength(line);
93   insertAt(s,line,col);
94   int n = numLines()-1;  
95   setCursorPosition( n, textLine(n).length()); 
96 }
97
98 /*!
99     Called when an handleReturn
100 */
101 void QAD_PyEditor::handleReturn()
102 {
103   QApplication::setOverrideCursor( Qt::waitCursor );
104   int ret;
105   int line=numLines()-2;
106
107   // NRI : Temporary added
108   SALOMEDS::Study_var aStudy = QAD_Application::getDesktop()->getActiveStudy()->getStudyDocument();
109   
110   if ( aStudy->GetProperties()->IsLocked() ) {
111     QApplication::restoreOverrideCursor();
112     QAD_MessageBox::warn1 ( (QWidget*)QAD_Application::getDesktop(),
113                             QObject::tr("WARNING"), 
114                             QObject::tr("WRN_STUDY_LOCKED"),
115                             QObject::tr("BUT_OK") );
116
117     _currentPrompt = ">>> ";
118     setText(_currentPrompt);
119     
120     return;
121   }  
122   // NRI
123
124   _buf.append(textLine(line).remove(0,SIZEPR));
125   ret = _interp->run(_buf);
126   if(ret <= 0)
127     {
128       _buf.truncate(0);
129       setText(_interp->getvout());
130       setText(_interp->getverr());
131       _currentPrompt = ">>> ";
132       setText(_currentPrompt);
133     }
134   if(ret == 1)
135     {
136       _buf.append("\n");
137       _currentPrompt = "... ";
138       setText(_currentPrompt);
139     }
140   _isInHistory = false;
141   QApplication::restoreOverrideCursor();
142 }
143
144 /*
145    Processes own popup menu
146 */
147 void QAD_PyEditor::mousePressEvent (QMouseEvent * event)
148 {
149   if ( event->button() == RightButton ) {
150     QPopupMenu *popup = new QPopupMenu( this );
151     QMap<int, int> idMap;
152
153     int line1, col1, line2, col2;
154     getMarkedRegion(&line1, &col1, &line2, &col2);
155     bool allSelected = getMarkedRegion(&line1, &col1, &line2, &col2) &&
156       line1 == 0 && line2 == numLines()-1 && col1 == 0 && col2 == lineLength(line2);
157     int id;
158     id = popup->insertItem( tr( "EDIT_COPY_CMD" ) );
159     idMap.insert(IdCopy, id);
160     id = popup->insertItem( tr( "EDIT_PASTE_CMD" ) );
161     idMap.insert(IdPaste, id);
162     id = popup->insertItem( tr( "EDIT_CLEAR_CMD" ) );
163     idMap.insert(IdClear, id);
164     popup->insertSeparator();
165     id = popup->insertItem( tr( "EDIT_SELECTALL_CMD" ) );
166     idMap.insert(IdSelectAll, id);
167     popup->setItemEnabled( idMap[ IdCopy ],  hasMarkedText() );
168     popup->setItemEnabled( idMap[ IdPaste ],
169                           !isReadOnly() && (bool)QApplication::clipboard()->text().length() );
170     popup->setItemEnabled( idMap[ IdSelectAll ],
171                           (bool)text().length() && !allSelected );
172     
173     int r = popup->exec( event->globalPos() );
174     delete popup;
175     
176     if ( r == idMap[ IdCopy ] ) {
177       copy();
178     }
179     else if ( r == idMap[ IdPaste ] ) {
180       paste();
181     }
182     else if ( r == idMap[ IdClear ] ) {
183       clear();
184       string banner = _interp->getbanner();
185       setText(banner.c_str());
186       setText(_currentPrompt);
187     }
188     else if ( r == idMap[ IdSelectAll ] ) {
189       selectAll();
190     }
191     return;
192   }
193   else {
194     QMultiLineEdit::mousePressEvent(event);
195   }
196 }
197
198 /*!
199     Called when a Mouse release event
200 */
201 void QAD_PyEditor::mouseReleaseEvent ( QMouseEvent * e )
202 {
203   //  MESSAGE("mouseReleaseEvent");
204   int curLine, curCol; // for cursor position
205   int endLine, endCol; // for last edited line
206   getCursorPosition(&curLine, &curCol);
207   endLine = numLines() -1;
208   if (e->button() != MidButton)
209     QMultiLineEdit::mouseReleaseEvent(e);
210   else if ((curLine == endLine) && (curCol >= SIZEPR))
211     QMultiLineEdit::mouseReleaseEvent(e);
212 }
213
214 /*!
215     Called when a drop event (Drag & Drop)
216 */
217   void QAD_PyEditor::dropEvent (QDropEvent *e)
218 {
219   INFOS("dropEvent : not handled");
220 }
221
222 /*!
223    Checks, is the string a command line or not.
224 */
225
226 bool QAD_PyEditor::isCommand( const QString& str) const
227 {
228   if (str.find(_currentPrompt)==0)
229     return true;
230   return false;
231 }
232
233
234 /*!
235     Called when a keyPress event
236 */
237 void QAD_PyEditor::keyPressEvent( QKeyEvent *e )
238 {
239   int curLine, curCol; // for cursor position
240   int endLine, endCol; // for last edited line
241   getCursorPosition(&curLine, &curCol);
242   endLine = numLines() -1;
243   //MESSAGE("current position " << curLine << ", " << curCol);
244   //MESSAGE("last line " << endLine);
245   //MESSAGE(e->key());
246   int aKey=e->key();
247   int keyRange=0;
248   if ((aKey >= Key_Space) && (aKey <= Key_ydiaeresis))
249     keyRange = 0;
250   else
251     keyRange = aKey;
252
253   bool ctrlPressed = ( (e->state() & ControlButton) == ControlButton );
254   bool shftPressed = ( (e->state() & ShiftButton) ==  ShiftButton );
255
256   switch (keyRange)
257     {
258     case 0 :
259       {
260         if (curLine <endLine)
261           {
262             setCursorPosition(endLine, SIZEPR);
263             end();
264           }
265         QMultiLineEdit::keyPressEvent( e );
266         break;
267       }
268     case Key_Return:
269     case Key_Enter:
270       {
271         if (curLine <endLine)
272           {
273             setCursorPosition(endLine, SIZEPR);
274           }
275         end();
276         QMultiLineEdit::keyPressEvent( e );
277         break;
278       }
279     case Key_Up:
280       {
281         // if Cntr+Key_Up event then move cursor up
282         if (ctrlPressed) {
283           QMultiLineEdit::cursorUp( );
284         }
285         // if Shift+Key_Up event then move cursor up and select the text
286         else if ( shftPressed && curLine > 0 ){
287            setCursorPosition(curLine-1, curCol, true);
288         }
289         // scroll the commands stack up
290         else { 
291            QString histLine = _currentPrompt;
292           if (! _isInHistory)
293             {
294               _isInHistory = true;
295               _currentCommand = textLine(endLine).remove(0,SIZEPR);
296               SCRUTE(_currentCommand);
297             }
298           QString previousCommand = _interp->getPrevious();
299           if (previousCommand.compare(BEGIN_HISTORY_PY) != 0)
300             {
301               removeLine(endLine);
302               histLine.append(previousCommand);
303               insertLine(histLine);
304             }
305           endLine = numLines() -1;
306           setCursorPosition(endLine, lineLength(endLine));
307         }
308         break;
309       }
310     case Key_Down:
311       {
312         // if Cntr+Key_Down event then move cursor down
313         if (ctrlPressed) {
314           QMultiLineEdit::cursorDown( );
315         }
316         // if Shift+Key_Down event then move cursor down and select the text
317         else if ( shftPressed && curLine < endLine ) {
318            setCursorPosition(curLine+1, curCol, true);
319         }
320         // scroll the commands stack down
321         else {
322         QString histLine = _currentPrompt;
323           QString nextCommand = _interp->getNext();
324           if (nextCommand.compare(TOP_HISTORY_PY) != 0)
325             {
326               removeLine(endLine);
327               histLine.append(nextCommand);
328               insertLine(histLine);
329             }
330           else
331             if (_isInHistory)
332               {
333                 _isInHistory = false;
334                 removeLine(endLine);
335                 histLine.append(_currentCommand);
336                 insertLine(histLine);
337               }
338           endLine = numLines() -1;
339           setCursorPosition(endLine, lineLength(endLine));
340         }
341         break;
342       }
343     case Key_Left:
344       {
345         if (!shftPressed && isCommand(textLine(curLine)) && curCol <= SIZEPR )
346           {
347             setCursorPosition((curLine -1), SIZEPR);
348             end();
349           }
350         else QMultiLineEdit::keyPressEvent( e );
351         break;
352       }
353     case Key_Right:
354       {
355         if (!shftPressed && isCommand(textLine(curLine)) 
356             && curCol < SIZEPR) setCursorPosition(curLine, SIZEPR-1);
357         QMultiLineEdit::keyPressEvent( e );
358         break;
359       }
360     case Key_Home: 
361       {
362         if (isCommand(textLine(curLine)) && curCol <= SIZEPR)
363           setCursorPosition(curLine, SIZEPR, shftPressed);
364         else setCursorPosition(curLine, 0, shftPressed);
365         break;
366       }
367     case Key_End:
368       {
369         setCursorPosition(curLine, textLine(curLine).length(), shftPressed);
370         break;
371       }  
372     case Key_Backspace :
373       {
374         if ((curLine == endLine) && (curCol > SIZEPR))
375           QMultiLineEdit::keyPressEvent( e );
376         break;
377       }
378     case Key_Delete :
379       {
380         if ((curLine == endLine) && (curCol > SIZEPR-1))
381           QMultiLineEdit::keyPressEvent( e );
382         break;
383       }
384     }
385   if ( e->key() == Key_C && ( e->state() & ControlButton ) )
386     {
387       _buf.truncate(0);
388       setText("\n");
389       _currentPrompt = ">>> ";
390       setText(_currentPrompt);
391     }
392
393   // NRI : DEBUG PAS TERRIBLE //
394   if (( e->key() == Key_F3) || 
395       ( e->key() == Key_F4) ||
396       ( e->key() == Key_Return) ||
397       ( e->key() == Key_Escape))
398     QAD_Application::getDesktop()->onKeyPress( e );
399   // NRI //
400 }