[SOLVED] Streaming Text Continuously to QTextEdit Without Creating File



  • I want to make a GUI with a QTextEdit to show

    @sudo apt-get update@

    command standard output (Ubuntu) continuously. In short, I want to make my program looks like Synaptic Package Manager when doing installation:

    !http://malsasa.files.wordpress.com/2014/03/apt-get-okular112.png!

    I want my program to start apt-get command (have done) then read all the standar output + standard error, and show them all in QTextEdit continuously. I want to do it without creating a temporary file or any text file. Any solution to do it? I have used these classes:

    • QTextStream
    • QFile

    Here is my approach until now (code + screenshot):

    @void MainWindow::redirect_output()
    {
    QProcess Proses;
    Proses.readAllStandardError();
    Proses.readAllStandardOutput();
    Proses.setStandardOutputFile("update.txt", QIODevice::Append);
    Proses.setStandardErrorFile("update.txt", QIODevice::Append);
    Proses.start("sh", QStringList() << "-c" << "gksudo apt-get update");
    QFile data("update.txt");
    QTextStream streamer(&data);
    if(data.open(QFile::ReadOnly))
    {
    QString penampung;
    penampung = streamer.readAll();
    this->keluaranKonsol->setText(penampung);
    }
    Proses.waitForFinished(-1);
    Proses.close();
    }@

    !http://malsasa.files.wordpress.com/2014/03/apt-get-okular113.png!

    Weakness:

    My code above only creates a file named update.txt, then do apt-get command, then save all standard output and standard error to update.txt, then read the update.txt to QTextEdit. My code doesn't delete update.txt or at least empty that file.

    Questions:

    If using my code: how to delete the update.txt (or empty the content) when program exit?

    If using another solution: how to transfer continuously text from standard output/standard error to my QTextEdit?

    Thank you so much.



  • Disclamer: I have not tried it. Just my guess.

    You may use "QProcess":http://qt-project.org/doc/qt-5/QProcess.html#communicating-via-channels
    channels to read data as soon as it is available.
    Connect your MainWindow to @QProcess::readyReadStandardOutput()@

    and to @QProcess::readyReadStandardError()@

    When the signals are emitted read all available data using

    @QProcess::readAllStandardOutput()@

    or

    @QProcess::readAllStandardError()@

    and display whatever you've got to

    @QTextStream@

    or other output widget.



  • So fast! Thank you for your response. I will try your solution.



  • [quote author="andreyc" date="1395637332"]

    [/quote]
    I have edited my code until this:

    @void MainWindow::redirect_output()
    {
    QProcess Proses;
    Proses.readAllStandardError();
    Proses.readAllStandardOutput();
    Proses.readyReadStandardError(); //here
    Proses.readyReadStandardOutput(); //and here
    Proses.setStandardOutputFile("update.txt", QIODevice::Append);
    Proses.setStandardErrorFile("update.txt", QIODevice::Append);
    Proses.start("sh", QStringList() << "-c" << "gksudo apt-get update");
    QFile data("update.txt");
    QTextStream streamer(&data);
    if(data.open(QFile::ReadOnly))
    {
    QString penampung;
    penampung = streamer.readAll();
    this->keluaranKonsol->setText(penampung);
    }
    Proses.waitForFinished(-1);
    Proses.close();
    }@

    but my Qt Creator says:

    @error: 'void QProcess::readyReadStandardError()' is protected@

    and same with Standard Output. Actually I have low experience with Qt and C++. Maybe my code was wrong. How to write the correct code? Thank you.



  • readyReadStandardError() and readyReadStandardOutput() are the signals you should not call them. The QProcess object will emit these signals and your MainWindow object should connect its slots to these signals.
    Inside the slots you will call Proses.readAllStandardError() and Proses.readAllStandardOutput() to get data.

    I would suggest you to read about "Signal and Slots in Qt":http://qt-project.org/doc/qt-5/signalsandslots.html first and try the simple examples.



  • [quote author="andreyc" date="1395760308"]...[/quote]

    Thank you, Mr Andrey. My problem was solved by searching on Google for this problem and I found a biggest clue at http://minhazulhaque.blogspot.com/2012/07/read-shell-command-output-using.html and I have modificated the code to suit my need. Once again: SOLVED.

    Here is my complete code now.

    mainwindow.h

    @#ifndef MAINWINDOW_H
    #define MAINWINDOW_H

    #include <QtGui>

    namespace Ui {
    class MainWindow;
    }

    class MainWindow : public QMainWindow
    {
    Q_OBJECT

    public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    QPushButton *tombolOke;
    QWidget *widgetUtama;
    QVBoxLayout *layoutUtama;
    QTextEdit *keluaranKonsol;

    public slots:
    void redirect_output();
    void hapus_isi_teks();
    void tunjukkan_bahwa_kamu_mati();

    private slots:
    void ambillah_datanya();

    private:
    Ui::MainWindow *ui;
    QProcess *prosesku;
    };

    #endif // MAINWINDOW_H@

    mainwindow.cpp

    @#include "mainwindow.h"
    #include "ui_mainwindow.h"

    MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    this->setGeometry(333, 333, 355, 355);
    QPushButton *tombolOke = new QPushButton;
    QVBoxLayout *layoutUtama = new QVBoxLayout;
    QWidget *widgetUtama = new QWidget;
    keluaranKonsol = new QTextEdit;
    prosesku = new QProcess;

    tombolOke->setText("NOTHING TO SAY");
    

    // keluaranKonsol->setTextBackgroundColor("RED");

    layoutUtama->addWidget(tombolOke);
    layoutUtama->addWidget(keluaranKonsol);
    
    prosesku->setProcessChannelMode(QProcess::MergedChannels);
    
    //menghitamkan background dari QTextEdit dengan CSS
    keluaranKonsol->setStyleSheet("QTextEdit { background-color : black; color : white; }");
    
    //membuat scrollbar selalu otomatis mengikuti kursor terbawah
    //dipasang pada Wednesday, March 26, 2014 05:39 PM dari dokumentasi Qt
    keluaranKonsol->ensureCursorVisible();
    
    widgetUtama->setLayout(layoutUtama);
    this->setCentralWidget(widgetUtama);
    
    connect(tombolOke, SIGNAL(clicked()), this, SLOT(redirect_output()));
    //teknik S&S baru ini didapatkan pada Tuesday, March 25, 2014 dari http://minhazulhaque.blogspot.com/2012/07/read-shell-command-output-using.html
    //juga bisa didapatkan dari http://www.qtcentre.org/threads/47538-QProcess-read-from-stdout-lively
    connect(prosesku, SIGNAL(readyRead()), this, SLOT(ambillah_datanya()));
    //teknik pembacaan kematian proses ini ditemukan pada Wednesday, March 26, 2014 05:18 PM dari perkiraan dan dokumentasi Qt
    connect(prosesku, SIGNAL(finished(int)), this, SLOT(tunjukkan_bahwa_kamu_mati()));
    

    // connect(prosesku, SIGNAL(readyReadStandardError()), this, SLOT(ambillah_datanya()));

    }

    //satu
    MainWindow::~MainWindow()
    {
    delete ui;
    }

    //dua
    void MainWindow::hapus_isi_teks()
    {

    }

    //tiga
    void MainWindow::redirect_output()
    {
    prosesku->start("sh", QStringList() << "-c" << "apt-get update");
    // prosesku->start("sh", QStringList() << "-c" << "tailf /var/log/syslog");
    }

    //empat
    void MainWindow::ambillah_datanya()
    {
    //teknik appending ini ditemukan pada Tuesday, March 25, 2014 05:07 PM dari http://www.jcjc-dev.com/2013/03/qt-48-appending-text-to-qtextedit.html
    this->keluaranKonsol->moveCursor(QTextCursor::End);
    this->keluaranKonsol->insertPlainText(prosesku->readAll());
    this->keluaranKonsol->moveCursor(QTextCursor::End);
    // this->keluaranKonsol->setPlainText(prosesku->readAllStandardError());
    }

    void MainWindow::tunjukkan_bahwa_kamu_mati()
    {
    this->keluaranKonsol->insertPlainText("\n\n===PROSES SELESAI===\n\n");
    }@

    This is the screenshot of the result:

    !http://i.imgur.com/0VMb0zC.png!

    Do you know? Perfectly what I want.

    Sorry for late response here. Actually I have solved this problem completely at Tuesday, March 25, 2014 ago but just now I come back. And finally my conclusion is: the realtime reading for standard output (and error too) in Linux by using QProcess is by using SIGNAL AND SLOT between the QProcess object and function to do readAll(). The reading function not related directly to the button click function, different with what I thought before I made this thread. Now I understand, at least more than before. Thank you for all your supports.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.