Salome HOME
Merge remote branch 'origin/master'
[modules/gui.git] / src / PyConsole / PyConsole_Editor.cxx
index c9542464aa7ec3ab7d24d1785fc7e9233ab7e353..2311b58d46bb29a3e2b48be8b4b7cd2020572401 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
 #include <QTextStream>
 #include <QChar>
 
+//VSR: uncomment below macro to support unicode text properly in SALOME
+//     current commented out due to regressions
+//#define PAL22528_UNICODE
+
+namespace
+{
+  QString fromUtf8( const char* txt )
+  {
+#ifdef PAL22528_UNICODE
+    return QString::fromUtf8( txt );
+#else
+    return QString( txt );
+#endif
+  }
+}
+
 static QString READY_PROMPT = ">>> ";
 static QString DOTS_PROMPT  = "... ";
 
@@ -138,14 +154,20 @@ bool DumpCommandsFileValidator::canSave(const QString& file, bool permissions)
 
 void staticCallbackStdout( void* data, char* c )
 {
-  if(!((PyConsole_Editor*)data)->isSuppressOutput())
-    QApplication::postEvent( (PyConsole_Editor*)data, new PrintEvent( QString::fromUtf8(c), false ) );
+  if(!((PyConsole_Editor*)data)->isSuppressOutput()) {
+    PyConsole_Editor* e = (PyConsole_Editor*)data;
+    e->putLog( fromUtf8(c) );
+    QApplication::postEvent( e, new PrintEvent( fromUtf8(c), false ) );
+  }
 }
 
 void staticCallbackStderr( void* data, char* c )
 {
-  if(!((PyConsole_Editor*)data)->isSuppressOutput())
-    QApplication::postEvent( (PyConsole_Editor*)data, new PrintEvent( QString::fromUtf8(c), true ) );
+  if(!((PyConsole_Editor*)data)->isSuppressOutput()) {
+    PyConsole_Editor* e = (PyConsole_Editor*)data;
+    e->putLog( fromUtf8(c) );
+    QApplication::postEvent( e, new PrintEvent( fromUtf8(c), true ) );
+  }
 }
 
 
@@ -185,16 +207,20 @@ PyConsole_Editor::PyConsole_Editor( PyConsole_Interp* theInterp,
 
 /*!
   \brief Destructor.
-
-  Does nothing for the moment.
 */
 PyConsole_Editor::~PyConsole_Editor()
 {
-  myInterp->destroy();
-  delete myInterp;
   myInterp = 0;
 }
 
+/*!
+  \brief Get Python interpreter
+*/
+PyConsole_Interp* PyConsole_Editor::getInterp() const
+{
+  return myInterp;
+}
+
 /*!
   \brief Get synchronous mode flag value.
   
@@ -272,6 +298,17 @@ void PyConsole_Editor::setIsShowBanner( const bool on )
   }
 }
 
+/*!
+  \brief Check if trace logging is switched on.
+  
+  \sa startLog(), stopLog()
+  \return \c true if trace logging is switched on
+*/
+bool PyConsole_Editor::isLogging() const
+{
+  return !myLogFile.isEmpty();
+}
+
 /*!
   \brief Get size hint for the Python console window
   \return size hint value
@@ -339,13 +376,10 @@ void PyConsole_Editor::exec( const QString& command )
   if ( !cmd.endsWith( "\n" ) ) cmd += "\n";
   QStringList lines = command.split( "\n" );
   for ( int i = 0; i < lines.size(); i++ ) {
-    if ( !lines[i].trimmed().isEmpty() ) {
-      PyCommand aCommand;
-      aCommand.command = lines[i];
-      aCommand.prompt = i == 0 ? READY_PROMPT : DOTS_PROMPT;
-      myHistory.append( aCommand );
-    }
+    if ( !lines[i].trimmed().isEmpty() )
+      myHistory.push_back( lines[i] );
     addText( ( i == 0 ? READY_PROMPT : DOTS_PROMPT ) + lines[i], i != 0 );
+    putLog( QString( "%1%2\n" ).arg( i == 0 ? READY_PROMPT : DOTS_PROMPT ).arg( lines[i] ) );
   }
   // IPAL20182
   addText( "", true );
@@ -382,14 +416,21 @@ void PyConsole_Editor::execAndWait( const QString& command )
     return;
 
   // create new event loop
-  myEventLoop = new QEventLoop( this );
+  bool sync = isSync();
+  if ( !sync ) {
+    myEventLoop = new QEventLoop( this );
+  }
+
   // execute command
   exec( command );
-  // run event loop
-  myEventLoop->exec();
-  // delete event loop after command is processed
-  delete myEventLoop;
-  myEventLoop = 0;
+
+  if ( !sync ) {
+    // run event loop
+    myEventLoop->exec();
+    // delete event loop after command is processed
+    delete myEventLoop;
+    myEventLoop = 0;
+  }
 }
 
 /*!
@@ -413,12 +454,9 @@ void PyConsole_Editor::handleReturn()
   // extend the command buffer with the current command 
   myCommandBuffer.append( cmd );
   // add command to the history
-  if ( !cmd.trimmed().isEmpty() ) {
-    PyCommand aCommand;
-    aCommand.command = cmd;
-    aCommand.prompt = myPrompt;
-    myHistory.append( aCommand );
-  }
+  if ( !cmd.trimmed().isEmpty() )
+    myHistory.push_back( cmd );
+  putLog( QString( "%1%2\n" ).arg( myPrompt ).arg( cmd ) );
 
   // IPAL19397
   addText( "", true ); 
@@ -604,7 +642,7 @@ void PyConsole_Editor::keyPressEvent( QKeyEvent* event )
         if ( myCmdInHistory > 0 ) {
           myCmdInHistory--;
           // get previous command in the history
-          QString previousCommand = myHistory.at( myCmdInHistory ).command;
+          QString previousCommand = myHistory.at( myCmdInHistory );
           // print previous command
           moveCursor( QTextCursor::End );
           moveCursor( QTextCursor::StartOfBlock, QTextCursor::KeepAnchor );
@@ -641,7 +679,7 @@ void PyConsole_Editor::keyPressEvent( QKeyEvent* event )
           QString nextCommand;
           if ( myCmdInHistory < myHistory.count() ) {
             // next command in history
-            nextCommand = myHistory.at( myCmdInHistory ).command;
+            nextCommand = myHistory.at( myCmdInHistory );
           }
           else {
             // end of history is reached
@@ -748,7 +786,7 @@ void PyConsole_Editor::keyPressEvent( QKeyEvent* event )
         if ( myCmdInHistory > 0 ) {
           myCmdInHistory = 0;
           // get very first command in the history
-          QString firstCommand = myHistory.at( myCmdInHistory ).command;
+          QString firstCommand = myHistory.at( myCmdInHistory );
           // print first command
           moveCursor( QTextCursor::End );
           moveCursor( QTextCursor::StartOfBlock, QTextCursor::KeepAnchor );
@@ -943,7 +981,6 @@ void PyConsole_Editor::customEvent( QEvent* event )
     {
       PrintEvent* pe=(PrintEvent*)event;
       addText( pe->text(), false, pe->isError());
-      myHistory.last().output = myHistory.last().output + pe->text();
       return;
     }
   case PyInterp_Event::ES_OK:
@@ -1135,33 +1172,80 @@ void PyConsole_Editor::dump()
     QTextStream out (&file);
   
     for ( int i=0; i<myHistory.count(); i++ ) {
-      out << myHistory.at(i).command << endl;
+      out << myHistory[i] << endl;
     }
     file.close();
   }
 }
 /*!
-  \brief "Save log" operation.
+  \brief "Start log" operation.
  */
-void PyConsole_Editor::saveLog()
+void PyConsole_Editor::startLog()
 {
   QStringList aFilters;
   aFilters.append( tr( "LOG_FILES_FILTER" ) );
 
-  QString fileName = SUIT_FileDlg::getFileName( this, QString(),
-                                               aFilters, tr( "TOT_SAVE_PYLOG" ),
-                                               false, true );
+  while (1) {
+    QString fileName = SUIT_FileDlg::getFileName( this, QString(),
+                                                 aFilters, tr( "TOT_SAVE_PYLOG" ),
+                                                 false, true );
+    if ( !fileName.isEmpty() ) {
+      if ( startLog( fileName ) ) {
+       break;
+      }
+      else {
+       SUIT_MessageBox::critical( this,
+                                  QObject::tr("ERR_ERROR"),
+                                  QObject::tr("ERR_FILE_NOT_WRITABLE") );
+      }
+    }
+    else {
+      break;
+    }
+  }
+}
+
+/*!
+  \brief Start python trace logging
+  \param fileName the path to the log file
+  \sa stopLog()
+ */
+bool PyConsole_Editor::startLog( const QString& fileName )
+{
+  bool ok = false;
   if ( !fileName.isEmpty() ) {
     QFile file( fileName );
-    if ( !file.open( QFile::WriteOnly ) )
-      return;
+    if ( file.open( QFile::WriteOnly ) ) {
+      file.close();
+      myLogFile = fileName;
+      ok = true;
+    }
+  }
+  return ok;
+}
 
-    QTextStream out (&file);
+/*!
+  \brief "Stop log" operation.
+  \sa startLog()
+ */
+void PyConsole_Editor::stopLog()
+{
+  myLogFile = QString();
+}
 
-     for( int i = 0; i < myHistory.count(); i++ ) {
-      out << myHistory.at(i).prompt << myHistory.at(i).command << endl;
-      out << myHistory.at(i).output;
-    }
+/*!
+  \brief Put string to the log file
+ */
+void PyConsole_Editor::putLog( const QString& s )
+{
+  if ( !myLogFile.isEmpty() ) {
+    QFile file( myLogFile );
+    if ( !file.open( QFile::Append ) )
+      return;
+    
+    QTextStream out (&file);
+    out << s;
+    
     file.close();
   }
 }