Search code examples
cgtk3

How to print an output from a terminal-only command in a GTK3 window?


I have the following GTK3 code:

#include <gtk/gtk.h>

void show(GtkWidget *window, gpointer ptr) {}

void activate(GtkApplication *tmp, gpointer ptr) {

    GtkWidget *scrolled_window;
    GtkWidget *window;
    GtkWidget *button_box;
    GtkWidget *button;
    GtkWidget *box;
    GtkWidget *view;
    GtkTextBuffer *buffer;

    window = gtk_application_window_new(tmp);

    gtk_window_set_title(GTK_WINDOW(window), "tmp");
    gtk_window_set_default_size(GTK_WINDOW(window), 500, 500);
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);

    scrolled_window = gtk_scrolled_window_new(NULL, NULL);

    buffer = gtk_text_buffer_new(NULL);

    view = gtk_text_view_new_with_buffer(buffer);

    gtk_widget_set_margin_start(view, 10);
    gtk_widget_set_margin_end(view, 10);
    gtk_widget_set_margin_top(view, 10);
    gtk_widget_set_margin_bottom(view, 10);

    gtk_text_view_set_editable(GTK_TEXT_VIEW(view), FALSE);
    gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(view), FALSE);
    gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(view), GTK_WRAP_WORD);

    button = gtk_button_new_with_label("Show");

    button_box = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);

    gtk_widget_set_halign(button_box, GTK_ALIGN_END);
    gtk_widget_set_valign(button_box, GTK_ALIGN_END);
    gtk_widget_set_margin_start(button_box, 10);
    gtk_widget_set_margin_end(button_box, 10);
    gtk_widget_set_margin_top(button_box, 0);
    gtk_widget_set_margin_bottom(button_box, 10);

    box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);

    gtk_box_pack_start(GTK_BOX(box), scrolled_window, TRUE, TRUE, 0);
    gtk_box_pack_start(GTK_BOX(box), button_box, FALSE, FALSE, 0);

    gtk_container_add(GTK_CONTAINER(scrolled_window), view);
    gtk_container_add(GTK_CONTAINER(button_box), button);
    gtk_container_add(GTK_CONTAINER(window), box);

    g_signal_connect(button, "clicked", G_CALLBACK(show), NULL);

    gtk_widget_show_all(window);
}

int main(int argc, char *argv[]) {

    GtkApplication *tmp;
    int status;

    tmp = gtk_application_new("org.gtk.tmp", G_APPLICATION_FLAGS_NONE);
    g_signal_connect(tmp, "activate", G_CALLBACK(activate), NULL);
    status = g_application_run(G_APPLICATION(tmp), argc, argv);
    g_object_unref(tmp);

    return status;
}

My question is: How do I print the output of a terminal-only command (like "ps aux") in this window after I click "Run"?

I have never written anything with GTK3 so, please, do not point me to https://developer.gnome.org/gtk3/stable/ as it's a reference and not a tutorial so to use it, one needs to already know some GTK3.

Thanks in advance!


Solution

  • Instead of copying the above code (which I have modified twice to add what I have learned since I asked my question) with the solution, I'll just paste the difference between it and the final version of the code:

     3c3,14
    < void show(GtkWidget *window, gpointer ptr) {}
    ---
    > void show(GtkWidget *window, gpointer buffer) {
    > 
    >   gchar *argv[] = { "/bin/df", "--human-readable", NULL };
    >   gchar *output;
    >   gchar *error;
    > 
    >   gtk_text_buffer_set_text(buffer, "", -1);
    > 
    >   g_spawn_sync(NULL, argv, NULL, G_SPAWN_DEFAULT, NULL, NULL, &output, &error, NULL, NULL);
    > 
    >   gtk_text_buffer_insert_at_cursor(buffer, output, -1);
    > }
    56c67
    <     g_signal_connect(button, "clicked", G_CALLBACK(show), NULL);
    ---
    >     g_signal_connect(button, "clicked", G_CALLBACK(show), buffer);
    

    (thanks to the busybee for valuable pointers!)

    The downside of this solution is that the output of the command you run will not be delivered in real time but only when the command finishes. So, if it takes 30 seconds to complete, your GUI will show nothing for 30 seconds and then print everything in one go. I have read that https://developer.gnome.org/gio/stable/GSubprocess.html may be the answer but I have not checked it out yet.