Salome HOME
sources v1.2
[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 using namespace std;
30 #include "QAD_PyEditor.h"
31 #include "QAD_PyInterp.h"
32 #include "QAD_Application.h"
33 #include "QAD_Desktop.h"
34 #include "QAD_Config.h"
35 #include "QAD_Tools.h"
36 #include "QAD_MessageBox.h"
37 //#include "QAD_RightFrame.h"
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 scroll the commands stack up
282         if (ctrlPressed) {
283           QString histLine = _currentPrompt;
284           if (! _isInHistory)
285             {
286               _isInHistory = true;
287               _currentCommand = textLine(endLine).remove(0,SIZEPR);
288               SCRUTE(_currentCommand);
289             }
290           QString previousCommand = _interp->getPrevious();
291           if (previousCommand.compare(BEGIN_HISTORY_PY) != 0)
292             {
293               removeLine(endLine);
294               histLine.append(previousCommand);
295               insertLine(histLine);
296             }
297           endLine = numLines() -1;
298           setCursorPosition(endLine, lineLength(endLine));
299         }
300         // if Shift+Key_Up event then move cursor up and select the text
301         else if ( shftPressed && curLine > 0 ){
302            setCursorPosition(curLine-1, curCol, true);
303         }
304         // move cursor up
305         else { QMultiLineEdit::keyPressEvent( e ); }
306         break;
307       }
308     case Key_Down:
309       {
310         // if Cntr+Key_Down event then scroll the commands stack down
311         if (ctrlPressed) {
312           QString histLine = _currentPrompt;
313           QString nextCommand = _interp->getNext();
314           if (nextCommand.compare(TOP_HISTORY_PY) != 0)
315             {
316               removeLine(endLine);
317               histLine.append(nextCommand);
318               insertLine(histLine);
319             }
320           else
321             if (_isInHistory)
322               {
323                 _isInHistory = false;
324                 removeLine(endLine);
325                 histLine.append(_currentCommand);
326                 insertLine(histLine);
327               }
328           endLine = numLines() -1;
329           setCursorPosition(endLine, lineLength(endLine));
330         }
331         // if Shift+Key_Down event then move cursor down and select the text
332         else if ( shftPressed && curLine < endLine ) {
333            setCursorPosition(curLine+1, curCol, true);
334         }
335         //move cursor down
336         else { QMultiLineEdit::keyPressEvent( e ); }
337
338         break;
339       }
340     case Key_Left:
341       {
342         if (!shftPressed && isCommand(textLine(curLine)) && curCol <= SIZEPR )
343           {
344             setCursorPosition((curLine -1), SIZEPR);
345             end();
346           }
347         else QMultiLineEdit::keyPressEvent( e );
348         break;
349       }
350     case Key_Right:
351       {
352         if (!shftPressed && isCommand(textLine(curLine)) 
353             && curCol < SIZEPR) setCursorPosition(curLine, SIZEPR-1);
354         QMultiLineEdit::keyPressEvent( e );
355         break;
356       }
357     case Key_Home: 
358       {
359         if (isCommand(textLine(curLine)) && curCol <= SIZEPR)
360           setCursorPosition(curLine, SIZEPR, shftPressed);
361         else setCursorPosition(curLine, 0, shftPressed);
362         break;
363       }
364     case Key_End:
365       {
366         setCursorPosition(curLine, textLine(curLine).length(), shftPressed);
367         break;
368       }  
369     case Key_Backspace :
370       {
371         if ((curLine == endLine) && (curCol > SIZEPR))
372           QMultiLineEdit::keyPressEvent( e );
373         break;
374       }
375     case Key_Delete :
376       {
377         if ((curLine == endLine) && (curCol > SIZEPR-1))
378           QMultiLineEdit::keyPressEvent( e );
379         break;
380       }
381     }
382   if ( e->key() == Key_C && ( e->state() & ControlButton ) )
383     {
384       _buf.truncate(0);
385       setText("\n");
386       _currentPrompt = ">>> ";
387       setText(_currentPrompt);
388     }
389
390   // NRI : DEBUG PAS TERRIBLE //
391   if (( e->key() == Key_F3) || 
392       ( e->key() == Key_F4) ||
393       ( e->key() == Key_Return) ||
394       ( e->key() == Key_Escape))
395     QAD_Application::getDesktop()->onKeyPress( e );
396   // NRI //
397 }