April 5, 2012

52GE 52GE
Lab Rat
6 posts

how to use QProcess to show tail command output of a log file on QTextEdit Window?

 

Hi all,

I am new to Qt and C++.I need to show the contents of a log file using tail command on QTextEdit window.For this i am using QProcess,please let me know how to use QProcess to show tail command output of a log file on QTextEdit Window or is there any other way apart from using QProcess? The .cpp and .h code for the same is given below:-

LOGFILE.cpp

  1. logFile::logFile(QWidget *parent):QMainWindow(parent),ui(new Ui::logFile)
  2. {
  3. ui->setupUi(this);
  4.  
  5. loadTextFile();
  6.  
  7. }
  8.  
  9. void logFile::on_findButton_clicked()
  10. {
  11. QString searchString=ui->lineEdit->text();
  12. ui->logTextEdit->find(searchString,QTextDocument::FindWholeWords);
  13. }
  14.  
  15. void logFile::loadTextFile()
  16. {
  17. QFile file("/var/log/system.log");
  18. file.open(QIODevice::ReadOnly|QIODevice::Text);
  19.  
  20. QTextStream in(&file);
  21. //QString line=in.readAll();
  22.  
  23. QString cmd("tail");
  24. QProcess* process=new QProcess(this);
  25. process->start(QFile::encodeName(cmd).data(),QStringList()<<"-f"<</var/log/sys.log");
  26. process->waitForReadyRead() or waitForFinished;
  27. QString tmp=process->readAll();
  28. qdebug()<<tmp;
  29.  
  30. file.close();
  31.  
  32. ui->logTextEdit->setPlainText(tmp);
  33.  
  34. QTextCursor cursor->logTextEdit->textCursor();
  35. cursor.movePosition(QTextCursor:: Start,QTextCursor::MoveAnchor,1);
  36. }

LOGFILE.h
  1. class logFile:public QMainWindow
  2. {
  3. Q_OBJECT
  4. public:
  5. logFile(QWidget *parent =0);
  6. ~logFile();
  7.  
  8. public slots:
  9.  
  10. void loadTextFile();
  11.  
  12. private slots:
  13. void on_findButton_clicked();
  14. };

Here the problem is that i get tailed output but only of the previous command i.e only once the application is closed and reopened ,i can see the output.But i want to see the output then and there.Please help.I don’t know where i am going wrong!

13 replies

April 5, 2012

koahnig koahnig
Mad Scientist
2112 posts

welcome to devnet

Please use code wrappers [qt-project.org] This improves the readability of your code sections. I have introduced them for you this time.

April 5, 2012

koahnig koahnig
Mad Scientist
2112 posts

The waitForReadyRead is certainly not sufficient. Your program will continue as soon as some information may be read. The waitForFinished may have a similar problem when the command you are executing is taking longer than 30 sec (30000 msec is the default).

In general it will be better to use with the signals emitted. You should have a look to the communicating-via-channels [qt-project.org] section of the documentation. This might be a start for you.

April 9, 2012

52GE 52GE
Lab Rat
6 posts

this is the modification that i did,but now it doesn’t give any output on the window!
Isn’t readyReadStandardOutput() an appropriate signal?

  1. logFile::logFile(QWidget *parent):QMainWindow(parent),ui(new Ui::logFile)
  2. {
  3.   *process=new QProcess();*
  4.   *connect(process,SIGNAL(readyReadStandardOutput()),this,SLOT(loadTextFile()));*
  5.   ui->setupUi(this);
  6.   loadTextFile();
  7. }
  8.  
  9. void logFile::on_findButton_clicked()
  10. {
  11.   QString searchString=ui->lineEdit->text();
  12.   ui->logTextEdit->find(searchString,QTextDocument::FindWholeWords);
  13. }
  14.  
  15. void logFile::loadTextFile()
  16. {
  17.   QFile file("/var/log/system.log");
  18.   file.open(QIODevice::ReadOnly|QIODevice::Text);
  19.   QTextStream in(&file);
  20.   //QString line=in.readAll();
  21.   QString cmd("tail");
  22.   QProcess* process=new QProcess(this);
  23.   process->start(QFile::encodeName(cmd).data(),QStringList()<<"-f"<<"/var/log/sys.log");
  24.   //process->waitForReadyRead() or waitForFinished;
  25.   QString tmp=process->readAll();
  26.   qdebug()<<tmp;
  27.   file.close();
  28.   ui->logTextEdit->setPlainText(tmp);
  29.   QTextCursor cursor->logTextEdit->textCursor();
  30.   cursor.movePosition(QTextCursor:: Start,QTextCursor::MoveAnchor,1);
  31. }

LOGFILE.H

  1. class logFile:public QMainWindow
  2. {
  3.   Q_OBJECT
  4. public:
  5.   logFile(QWidget *parent =0);
  6.   ~logFile();
  7.   *QProcess *process;*
  8. public slots:
  9.   void loadTextFile();
  10.   private slots:
  11.   void on_findButton_clicked();
  12. };

Edit: code formatting. Please format your code in a readable manner yourself next time. If you want to get help, it helps if you make it easy on the people that might be able to help you…; Andre

April 9, 2012

52GE 52GE
Lab Rat
6 posts

I have even tried using,but i can’t see any output!

  1. *connect(ui->logTextEdit,SIGNAL(readyReadStandardOutput()),this,SLOT(loadTextFile()));*

logTextEdit is the object name for the QTextEdit

April 9, 2012

Andre Andre
Area 51 Engineer
6031 posts

There are so many problems in this piece of code, that I don’t know where to begin. To name a few:

  1. You are connecting to the signal of an empty QProcess instance, that is not doing anything
  2. In your loadTextFile function, you create a new QProcess on each invokation
  3. That new instance is not the one declared in your class under the same name…
  4. The new process isn’t connected to anything

You should really create one QProcess instance, connect to that objects signals, and work from there.

Alternatively, you might look into using QFileSystemWatcher on that file instead of using tail via QProcess.

 Signature 

Looking for Qt developers to join our team @ i-Optics: https://qt-project.org/forums/viewthread/25393/

April 11, 2012

52GE 52GE
Lab Rat
6 posts

But will QFileSystemWatcher facilitate the usage of tail, i mean i have to show tailed output only,so will the same be possible using QFileSystemWatcher?

April 11, 2012

Andre Andre
Area 51 Engineer
6031 posts

No, QFileSystemWatcher is obviously no tail command. It just notifies you when a file is modified. You can use that to read any new data that was appended since the last time you read the file. Isn’t that what tail does too?

 Signature 

Looking for Qt developers to join our team @ i-Optics: https://qt-project.org/forums/viewthread/25393/

April 11, 2012

Volker Volker
Robot Herder
5428 posts

You can mimic part of tail -f by holding a QTimer that for example fires every second. In a slot connected to the timout signal of that timer, you just check the still open file for new data and read that.

  1. class logFile: QObject (or QWidget) {
  2. public:
  3.     logFile(QObject *parent);
  4.  
  5. protected slots:
  6.     readData();
  7.  
  8. private:
  9.     QTimer timer;
  10.     QFile logFile;
  11.     QTextStream logStream;
  12. };
  13.  
  14.  
  15. logFile::logFile(QObject *parent)
  16. {
  17.     logFile.setFileName("/var/log/system.log");
  18.     logFile.open(QIODevice::ReadOnly|QIODevice::Text);
  19.     logStream.setDevice(logFile);
  20.     // read the current file contents here if needed
  21.  
  22.     connect(&timer, SIGNAL(timeout()), this, SLOT(readData()));
  23.     timer.start(1000);
  24. }
  25.  
  26. void logFile::readData()
  27. {
  28.     while(!logStream.atEnd()) {
  29.         QString line = logStream.readLine();
  30.         // supposing logTextEdit is a QPlainTextEdit
  31.         ui->logTextEdit->appendPlainText(line);
  32.         ui->logTextEdit->appendPlainText("\n");
  33.     }
  34. }

[Brain to terminal, not tested.]

April 11, 2012

Andre Andre
Area 51 Engineer
6031 posts

In that case, I think I’d simply use QFileSystemWatcher. No timer needed, just get notified when the file actually changes…

 Signature 

Looking for Qt developers to join our team @ i-Optics: https://qt-project.org/forums/viewthread/25393/

April 11, 2012

52GE 52GE
Lab Rat
6 posts

as suggested i have changed the code and am using QFileSystemWatcher.But i am still not getting the result,i think there is some mistake somewhere in my code,i can’t figure out.

Ui form appears for a fraction of second and then the application terminates unexpectedly.

here’s the code:-

LOGFILE.h

  1.  public slots:
  2.  void readContents(QString);

LOGFILE.cpp

  1. logFile::logFile(QWidget *parent):QMainWindow(parent),ui(new Ui::logFile)
  2.    {
  3.      QFile *logFile = new QFile("/path/to/log/file");
  4.      new QTextStream(logFile);
  5.      QFileSystemWatcher fileWatcher = new QFileSystemWatcher(this)  ;
  6.      fileWatcher->addPath("/path/to/log/file");
  7.      QObject::connect(fileWatcher, SIGNAL(fileChanged(QString)), this, SLOT(readContents(QString))) ;
  8.    }
  9.  
  10. void logFile::readContents(QString path)
  11.    {
  12.       QFile *logFile;
  13.       QString textAppended ;
  14.       int newSize = logFile->size();
  15.       int oldSize;
  16.         if(newSize > oldSize)
  17.               {
  18.                   if(!logFile->open(QIODevice::ReadOnly))
  19.                      {
  20.                             textAppended = "Error in opening the File";
  21.                             //showOutput();
  22.                             ui->logTextEdit->setPlainText(textAppended);
  23.                             return;
  24.                      }
  25.                   else
  26.                      {
  27.                             logFile->seek((logFile->size() - 1) - (newSize - oldSize));
  28.                             QTextStream txtStream(logFile);
  29.                             while(!txtStream.atEnd())
  30.                                 {
  31.                                       textAppended = txtStream.readLine();
  32.                                 }
  33.                                 // showOutput();
  34.                                 ui->logTextEdit->setPlainText(textAppended);
  35.                      }
  36.  oldSize = newSize;
  37.  logFile->close();
  38.              }
  39. }

April 11, 2012

52GE 52GE
Lab Rat
6 posts

the file path is same as before i.e /var/log/system.log

April 11, 2012

Andre Andre
Area 51 Engineer
6031 posts

Please use proper code indentation. I have a hard time reading unindented code, and that’s not effort I want to spend. Use the edit link next to the message to adapt it please.

Edit: thanks for updating, much easier to read.

 Signature 

Looking for Qt developers to join our team @ i-Optics: https://qt-project.org/forums/viewthread/25393/

April 11, 2012

Volker Volker
Robot Herder
5428 posts

In readContents(), logFile is not initialized. Your program crashes.

In the constructor, you create a QTextStream, but don’t keep it anywhere.

May I ask if you have any experience with C++ at all? It dosen’t look so, and I would suggest to take the time for some online tutorial on C++ before you continue with Qt.

 
  ‹‹ [solved] Changing row background of tableview afterwards      [SOLVED]QProcess get RAM usage of a program ››

You must log in to post a reply. Not a member yet? Register here!