]> SALOME platform Git repositories - modules/gui.git/commitdiff
Salome HOME
Merge branch 'master' of ssh://git.salome-platform.org/modules/gui
authorabn <adrien.bruneton@cea.fr>
Thu, 25 Sep 2014 07:20:58 +0000 (09:20 +0200)
committerabn <adrien.bruneton@cea.fr>
Thu, 25 Sep 2014 07:20:58 +0000 (09:20 +0200)
src/PyConsole/PyConsole_Console.cxx
src/PyConsole/PyConsole_Console.h
src/PyConsole/PyConsole_Editor.cxx
src/PyConsole/PyConsole_Editor.h
src/PyConsole/resources/PyConsole_msg_en.ts
src/PyConsole/resources/PyConsole_msg_fr.ts
src/PyConsole/resources/PyConsole_msg_ja.ts
src/SALOME_PYQT/SalomePyQt/CMakeLists.txt
src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx
src/SALOME_PYQT/SalomePyQt/SalomePyQt.h
src/SALOME_PYQT/SalomePyQt/SalomePyQt.sip

index c613866d1e10cadf7cec28eb0739f42e6a8eba8e..a3991bf88a8885103e52a684776b8716e737f344 100644 (file)
@@ -248,7 +248,10 @@ void PyConsole_Console::contextMenuPopup( QMenu* menu )
   menu->addAction( myActions[SelectAllId] );
   menu->addSeparator();
   menu->addAction( myActions[DumpCommandsId] );
-  menu->addAction( myActions[SaveLogId] );
+  if ( !myEditor->isLogging() )
+    menu->addAction( myActions[StartLogId] );
+  else
+    menu->addAction( myActions[StopLogId] );
 
   Qtx::simplifySeparators( menu );
 
@@ -270,7 +273,8 @@ void PyConsole_Console::setMenuActions( const int flags )
   myActions[ClearId]->setVisible( flags & ClearId );
   myActions[SelectAllId]->setVisible( flags & SelectAllId );
   myActions[DumpCommandsId]->setVisible( flags & DumpCommandsId );
-  myActions[SaveLogId]->setVisible( flags & SaveLogId );
+  myActions[StartLogId]->setVisible( flags & StartLogId );
+  myActions[StopLogId]->setVisible( flags & StopLogId );
 }
 
 /*!
@@ -286,7 +290,8 @@ int PyConsole_Console::menuActions() const
   ret = ret | ( myActions[ClearId]->isVisible() ? ClearId : 0 );
   ret = ret | ( myActions[SelectAllId]->isVisible() ? SelectAllId : 0 );
   ret = ret | ( myActions[DumpCommandsId]->isVisible() ? DumpCommandsId : 0 );
-  ret = ret | ( myActions[SaveLogId]->isVisible() ? SaveLogId : 0 );
+  ret = ret | ( myActions[StartLogId]->isVisible() ? StartLogId : 0 );
+  ret = ret | ( myActions[StopLogId]->isVisible() ? StopLogId : 0 );
   return ret;
 }
 
@@ -322,10 +327,15 @@ void PyConsole_Console::createActions()
   connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( dump() ) );
   myActions.insert( DumpCommandsId, a );
 
-  a = new QAction( tr( "EDIT_SAVELOG_CMD" ), this );
-  a->setStatusTip( tr( "EDIT_SAVELOG_CMD" ) );
-  connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( saveLog() ) );
-  myActions.insert( SaveLogId, a );
+  a = new QAction( tr( "EDIT_STARTLOG_CMD" ), this );
+  a->setStatusTip( tr( "EDIT_STARTLOG_CMD" ) );
+  connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( startLog() ) );
+  myActions.insert( StartLogId, a );
+
+  a = new QAction( tr( "EDIT_STOPLOG_CMD" ), this );
+  a->setStatusTip( tr( "EDIT_STOPLOG_CMD" ) );
+  connect( a, SIGNAL( triggered( bool ) ), myEditor, SLOT( stopLog() ) );
+  myActions.insert( StopLogId, a );
 }
 
 /*!
@@ -340,6 +350,23 @@ void PyConsole_Console::updateActions()
   myActions[SelectAllId]->setEnabled( !myEditor->document()->isEmpty() );
 }
 
+/*!
+  \brief Start python trace logging
+  \param fileName the path to the log file
+*/
+void PyConsole_Console::startLog( const QString& fileName )
+{
+  myEditor->startLog( fileName );
+}
+
+/*!
+  \brief Stop python trace logging
+*/
+void PyConsole_Console::stopLog()
+{
+  myEditor->stopLog();
+}
+
 /**
  * Similar to constructor of the base class but using enhanced objects.
  * TODO: this should really be done in a factory to avoid code duplication.
index 783c6567a1b7cec292a18863ba329d37e6cf9f1b..54442c2cd9c162cf2ed847410406789064866075 100644 (file)
@@ -44,13 +44,14 @@ public:
   //! Context popup menu actions flags
   enum
   {
-    CopyId         = 0x01,                                                      //!< "Copy" menu action
-    PasteId        = 0x02,                                                      //!< "Paste" menu action
-    ClearId        = 0x04,                                                      //!< "Clear" menu action
-    SelectAllId    = 0x08,                                                      //!< "Select All" menu action
-    DumpCommandsId = 0x10,                                                      //!< "DumpCommands" menu action
-    SaveLogId      = 0x20,                                                      //!< "Save log" menu action
-    All = CopyId | PasteId | ClearId | SelectAllId | DumpCommandsId | SaveLogId //!< all menu actions
+    CopyId         = 0x01,  //!< "Copy" menu action
+    PasteId        = 0x02,  //!< "Paste" menu action
+    ClearId        = 0x04,  //!< "Clear" menu action
+    SelectAllId    = 0x08,  //!< "Select All" menu action
+    DumpCommandsId = 0x10,  //!< "DumpCommands" menu action
+    StartLogId     = 0x20,  //!< "Start log" menu action
+    StopLogId      = 0x40,  //!< "Stop log" menu action
+    All            = 0xFF,  //!< all menu actions 
   };
 
 public:
@@ -83,6 +84,9 @@ public:
   void                setMenuActions( const int );
   int                 menuActions() const;
 
+  void                startLog( const QString& );
+  void                stopLog();
+
 protected:
   void                createActions();
   void                updateActions();
index 29c8d1ade656e92f2b9b74a7834035daaa5a82ea..300915c70af1ed2098ebefdb08b1874f5b7db456 100644 (file)
@@ -138,14 +138,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( QString::fromUtf8(c) );
+    QApplication::postEvent( e, new PrintEvent( QString::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( QString::fromUtf8(c) );
+    QApplication::postEvent( e, new PrintEvent( QString::fromUtf8(c), true ) );
+  }
 }
 
 
@@ -272,6 +278,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,12 +356,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];
-      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 );
@@ -412,11 +427,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;
-    myHistory.append( aCommand );
-  }
+  if ( !cmd.trimmed().isEmpty() )
+    myHistory.push_back( cmd );
+  putLog( QString( "%1%2\n" ).arg( myPrompt ).arg( cmd ) );
 
   // IPAL19397
   addText( "", true ); 
@@ -602,7 +615,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 );
@@ -639,7 +652,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
@@ -746,7 +759,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 );
@@ -941,7 +954,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:
@@ -1123,43 +1135,90 @@ void PyConsole_Editor::dump()
   aFilters.append( tr( "PYTHON_FILES_FILTER" ) );
   
   QString fileName = SUIT_FileDlg::getFileName( this, QString(),
-                                    aFilters, tr( "TOT_DUMP_PYCOMMANDS" ),
-                                    false, true, new DumpCommandsFileValidator( this ) );
-  if ( fileName != "" ) {
+                                               aFilters, tr( "TOT_DUMP_PYCOMMANDS" ),
+                                               false, true, new DumpCommandsFileValidator( this ) );
+  if ( !fileName.isEmpty() ) {
     QFile file( fileName ); 
     if ( !file.open( QFile::WriteOnly ) )
       return;
 
     QTextStream out (&file);
   
-    for( int i=0; i<myHistory.count(); i++ ) {
-         out<<myHistory.at(i).command<<endl;
+    for ( int i=0; i<myHistory.count(); i++ ) {
+      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( "PYTHON_FILES_FILTER" ) );
+  aFilters.append( tr( "LOG_FILES_FILTER" ) );
+
+  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;
+    }
+  }
+}
 
-  QString fileName = SUIT_FileDlg::getFileName( this, QString(),
-                     aFilters, tr( "TOT_SAVE_PYLOG" ),
-                 false, true, new DumpCommandsFileValidator( this ) );
-  if ( fileName != "" ) {
+/*!
+  \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).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();
   }
 }
index e9d5ad2ccaefbacd4e382d340123268701294a1b..c939ef1b7da3e9fd78f947738427b11222426a42 100644 (file)
@@ -35,10 +35,6 @@ class PyConsole_Interp;
 class PyInterp_Request;
 class QEventLoop;
 
-typedef struct {
-  QString command, output;
-} PyCommand;
-
 class PYCONSOLE_EXPORT PyConsole_Editor : public QTextEdit
 {
   Q_OBJECT;
@@ -62,6 +58,8 @@ public:
   bool           isShowBanner() const;
   void           setIsShowBanner( const bool );
 
+  bool           isLogging() const;
+
   virtual QSize  sizeHint() const;
 
 public slots:
@@ -71,7 +69,10 @@ public slots:
     void           handleReturn();
     void           onPyInterpChanged( PyConsole_Interp* );
     void           dump();
-    void           saveLog();
+    bool           startLog( const QString& );
+    void           startLog();
+    void           stopLog();
+    void           putLog( const QString& );
 
 protected:
   virtual void   dropEvent( QDropEvent* event );
@@ -90,7 +91,8 @@ protected:
   QString           myCurrentCommand;   //!< currently being printed command
   QString           myPrompt;           //!< current command line prompt
   int               myCmdInHistory;     //!< current history command index
-  QList<PyCommand>  myHistory;          //!< commands history buffer
+  QString           myLogFile;          //!< current output log
+  QStringList       myHistory;          //!< commands history buffer
   QEventLoop*       myEventLoop;        //!< internal event loop
   QString           myBanner;           //!< current banner
   bool              myShowBanner;       //!< 'show banner' flag
index bb060d8a2bc89f8124961c2027ba2d3d3f254ac5..3a3b89bd94a077e4af5f6f7e2b2a10674d86dfbf 100644 (file)
     </message>
     <message>
         <source>EDIT_DUMPCOMMANDS_CMD</source>
-        <translation>D&amp;ump commands</translation>
+        <translation>D&amp;ump Commands</translation>
     </message>
     <message>
-        <source>EDIT_SAVELOG_CMD</source>
-        <translation>&amp;Save log</translation>
+      <source>EDIT_STARTLOG_CMD</source>
+        <translation>Start &amp;Log</translation>
+    </message>
+    <message>
+      <source>EDIT_STOPLOG_CMD</source>
+        <translation>Stop &amp;Log</translation>
     </message>
 </context>
 <context>
         <source>PYTHON_FILES_FILTER</source>
         <translation>PYTHON Files (*.py)</translation>
     </message>
+    <message>
+        <source>LOG_FILES_FILTER</source>
+        <translation>Log files (*.log *.txt)</translation>
+    </message>
+    <message>
+        <source>ERR_FILE_NOT_WRITABLE</source>
+        <translation>File is not writable!</translation>
+    </message>
 </context>
 </TS>
index 5c7ba5fe1ad4b490e9a5595271d73a5a03805684..4446aa9bdd2857109409b613bdc82733cd76cb74 100755 (executable)
         <translation>&amp;Générer le script des commandes</translation>
     </message>
     <message>
-        <source>EDIT_SAVELOG_CMD</source>
-        <translation type="unfinished">&amp;Save log</translation>
+        <source>EDIT_STARTLOG_CMD</source>
+        <translation type="unfinished">Start &amp;Log</translation>
+    </message>
+    <message>
+        <source>EDIT_STOPLOG_CMD</source>
+        <translation type="unfinished">Stop &amp;Log</translation>
     </message>
 </context>
 <context>
         <source>PYTHON_FILES_FILTER</source>
         <translation>Fichiers PYTHON (*.py)</translation>
     </message>
+    <message>
+        <source>LOG_FILES_FILTER</source>
+        <translation type="unfinished">Log files (*.log *.txt)</translation>
+    </message>
+    <message>
+        <source>ERR_FILE_NOT_WRITABLE</source>
+        <translation type="unfinished">File is not writable!</translation>
+    </message>
 </context>
 </TS>
index 82c2bbdb50352c1b0261d7d23025c976ca9f7596..c993c7cc5e3b735b80514c4e0f1eec75eb837cc6 100644 (file)
       <translation>スクリプト コマンドを生成します。(&amp;u)</translation>
     </message>
     <message>
-        <source>EDIT_SAVELOG_CMD</source>
-        <translation type="unfinished">&amp;Save log</translation>
+        <source>EDIT_STARTLOG_CMD</source>
+        <translation type="unfinished">Start &amp;Log</translation>
+    </message>
+    <message>
+        <source>EDIT_STOPLOG_CMD</source>
+        <translation type="unfinished">Stop &amp;Log</translation>
     </message>
   </context>
   <context>
       <source>PYTHON_FILES_FILTER</source>
       <translation>ファイル (*.py) PYTHON</translation>
     </message>
+    <message>
+        <source>LOG_FILES_FILTER</source>
+        <translation type="unfinished">Log files (*.log *.txt)</translation>
+    </message>
+    <message>
+        <source>ERR_FILE_NOT_WRITABLE</source>
+        <translation type="unfinished">File is not writable!</translation>
+    </message>
   </context>
 </TS>
index 692883aac15a6d27a3e49a917d4082a23ff5ab23..540c27514ec55ce3f4c40b9fec443d482e0fcdfa 100755 (executable)
@@ -42,6 +42,7 @@ INCLUDE_DIRECTORIES(
   ${PROJECT_SOURCE_DIR}/src/ObjBrowser
   ${PROJECT_SOURCE_DIR}/src/Plot2d
   ${PROJECT_SOURCE_DIR}/src/PyInterp
+  ${PROJECT_SOURCE_DIR}/src/PyConsole
   ${PROJECT_SOURCE_DIR}/src/Qtx
   ${PROJECT_SOURCE_DIR}/src/SALOME_PYQT/SALOME_PYQT_GUILight
   ${PROJECT_SOURCE_DIR}/src/STD
index 46cffcc0ca965738d112c36d2fabf673618f68f8..75642bf48cc6c3bfe231bdb2af8d4748e37954e6 100644 (file)
@@ -50,6 +50,7 @@
 #include "SUIT_ResourceMgr.h"
 #include "SUIT_Session.h"
 #include "SUIT_Tools.h"
+#include "PyConsole_Console.h"
 
 #include <QAction>
 #include <QApplication>
@@ -3907,3 +3908,39 @@ int SalomePyQt::getObjectPosition( const QString& theEntry )
 {
   return ProcessEvent( new TGetObjectPositionEvent(theEntry) );
 }
+
+void SalomePyQt::startPyLog(const QString& theFileName)
+{
+  class TEvent: public SALOME_Event
+  {
+    QString myFileName;
+  public:
+    TEvent( const QString& theFileName ):
+      myFileName( theFileName ) {}
+    virtual void Execute() 
+    {
+      if ( getApplication() ) {
+       PyConsole_Console* pyConsole = getApplication()->pythonConsole( false );
+       if ( pyConsole ) pyConsole->startLog( myFileName );
+      }
+    }
+  };
+  ProcessVoidEvent( new TEvent( theFileName ) );
+}
+
+void SalomePyQt::stopPyLog()
+{
+  class TEvent: public SALOME_Event
+  {
+  public:
+    TEvent() {}
+    virtual void Execute() 
+    {
+      if ( getApplication() ) {
+       PyConsole_Console* pyConsole = getApplication()->pythonConsole( false );
+       if ( pyConsole ) pyConsole->stopLog();
+      }
+    }
+  };
+  ProcessVoidEvent( new TEvent() );
+}
index 2747c0f7c1a271aa71c09820bf3862eed0d7ef63..68be1fafcdec7d4e9629dd94d6fab7cbaf0f6510 100644 (file)
@@ -304,6 +304,9 @@ public:
   static QString           getSetting      ( const QString& );
 
   static void              removeChild( const QString& = QString() );
+
+  static void              startPyLog(const QString&);
+  static void              stopPyLog();
 };
 
 #endif // SALOME_PYQT_H
index 4da473a0aa7c4e794b1200fb0cb9f241914046f4..7759940000deba804a487e38807df5f65b448832 100644 (file)
@@ -464,4 +464,7 @@ public:
   static QList<double>     getPlot2dFitRangeByCurves(const int) /ReleaseGIL/ ;
   static QList<double>     getPlot2dFitRangeCurrent(const int) /ReleaseGIL/ ;
   static void              setPlot2dFitRange(const int, const double XMin, const double XMax, const double YMin, const double YMax ) /ReleaseGIL/ ;
+
+  static void              startPyLog(const QString&) /ReleaseGIL/ ;
+  static void              stopPyLog() /ReleaseGIL/ ;
 };