Search code examples
c++qtscreen-captureterminal-emulator

Qt - get output from running process


I would like to get output from running process on Linux in Qt.

My code looks like this:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <qprocess.h>
#include <qthread.h>

QProcess process;

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    process.start("htop");

    connect(&process, SIGNAL(readyReadStandardOutput()), this, SLOT(getData()));
}

void getData(){

    QByteArray out;
    out = process.readAllStandardOutput();
}

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

But I want to get realtime (changing) output for example from htop and save it to string.


Solution

  • Because the sample "htop" interests me, here's a hint.

    htop is an "interactive" terminal application (using curses to "draw" a animated terminal image), as opposed to a run-of-the-mill UNIX-style filter (that takes input from a file-like source, and provides a sequential output stream to any file-like destination).

    So it's not quite as easy to "capture" it live. In fact the only class of application that supports this is called a terminal emulator. Let's use tmux as a terminal emulator that is capable of writing "screenshots" to a file.

    $ SESS_ID=$(uuidgen)
    $ COLUMNS=80 LINES=25 tmux new-session -s "$SESS_ID" -d htop
    

    This starts a new session, running htop in the background. We generated a unique ID so we can control it without interfering with other tmux sessions. You can list it to check what the name is:

    $ tmux list-sessions
    a9946cbf-9863-4ac1-a063-02724e580f88: 1 windows (created Wed Dec 14 21:10:42 2016) [170x42]
    

    Now you can use capture-pane to get the contents of that window:

    $ tmux capture-pane -t "$SESS_ID" -p
    

    In fact, running it repeatedly gives you a (monochrome) live mirror of the htop (every 2 seconds, by default):

    $ watch tmux capture-pane -t "$SESS_ID" -p
    

    Now. You want color, of course. Use ansifilter:

    $ tmux capture-pane -t "$SESS_ID" -p -e | ansifilter -H > shot.html
    

    Voila. I'm sure Qt has a nice Widget to display HTML content. I tested it running this

    $ while sleep 1; do tmux capture-pane -t "$SESS_ID" -p -e | ansifilter -H > shot.html; done
    

    And opening shot.html in my browser. Every time I reload, I get an up-to-date screenshot:

    enter image description here

    Oh, PS when you're done clean up that session using

    $ tmux kill-session -t "$SESS_ID"