GTK+ Forums

Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
It is currently Tue Sep 23, 2014 8:24 pm

All times are UTC




Post new topic Reply to topic  [ 28 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Execute command into a GtkTextView (C and Libglade)
PostPosted: Fri Nov 30, 2007 9:39 pm 
Offline
Never Seen the Sunlight

Joined: Wed Sep 21, 2005 12:07 am
Posts: 563
Location: Portland, OR USA
This is in response to a question I saw on Ubuntu Forums. Figured it'd be a good example. Shows how to use g_command_line_sync() to output a command into a GtkTextView.

Image

main.c
Code:
/*
Example running a command into a GtkTextView by Micah Carrick
Written for www.gtkforums.com
Compile using:
gcc -Wall -g main.c -o example `pkg-config --cflags --libs gtk+-2.0 libglade-2.0` 
*/

#include <gtk/gtk.h>
#include <glade/glade.h>

/* structure to hold references to our widgets */
typedef struct
{       
        GtkWidget               *entry;
        GtkWidget               *textview;
} MyWidgets;
               
/* call back function for when the button is pressed */
static void
on_execute_button_clicked (GtkWidget* widget, gpointer user_data)
{
        MyWidgets               *widgets;
        gchar                   *output;       
        const gchar             *command;       
        GError                  *error = NULL; 
        GtkTextBuffer           *buffer;
             
        widgets = (MyWidgets *)user_data;
        command = gtk_entry_get_text (GTK_ENTRY (widgets->entry));
       
        /* execute command */     
        g_spawn_command_line_sync (command, &output, NULL, NULL, &error);
       
        if (error != NULL)
        {
                GtkWidget *dialog;
               
                /* create an error dialog containing the error message */
                dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_DESTROY_WITH_PARENT,
                                                GTK_MESSAGE_ERROR,
                                                GTK_BUTTONS_OK,
                                                error->message);
                gtk_window_set_title (GTK_WINDOW (dialog), "Error");
               
                /* run the dialog */
                gtk_dialog_run (GTK_DIALOG (dialog));
               
                /* clean up memory used by dialog and error */
                gtk_widget_destroy (dialog);   
                g_error_free(error);
               
                return;
        }
       
        /* get the text buffer */
        buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widgets->textview));
       
        /* set the text in the buffer to the output */
        gtk_text_buffer_set_text (buffer, output, -1);
       
        /* free the output string */
        g_free (output);   
}

int
main (int argc, char *argv[])
{
       
        GtkWidget               *window;
        GladeXML                *gxml;
        MyWidgets               *widgets;
        PangoFontDescription    *font_desc;
       
        widgets = g_slice_new (MyWidgets);
       
        /* initialize the GTK+ library */
        gtk_init (&argc, &argv);

        /* build GladeXML object from the glade XML file */
        gxml = glade_xml_new ("example.glade", NULL, NULL);

        /* get widgets from GladeXML object */
        window = glade_xml_get_widget (gxml, "window");
        widgets->entry = glade_xml_get_widget (gxml, "execute_entry");
        widgets->textview = glade_xml_get_widget (gxml, "output_textview");
       
        /* call gtk_main_quit() when the window's "x" is clicked */
        glade_xml_signal_connect (gxml, "gtk_main_quit",
            G_CALLBACK (gtk_main_quit));

        /*
        Call on_button_clicked() when execute_button is clicked, passing the
        MyWidget struct to the function as the user_data
        */
        glade_xml_signal_connect_data (gxml, "on_execute_button_clicked",
            G_CALLBACK (on_execute_button_clicked), widgets);

        /* free GladeXML object */
        g_object_unref (G_OBJECT (gxml));
             
        /* use a fixed width font on the text view so the output looks proper */
       
        font_desc = pango_font_description_from_string ("monospace 10");
        gtk_widget_modify_font (widgets->textview, font_desc);     
        pango_font_description_free (font_desc);     
             
        /* show the main window */
        gtk_widget_show (window);

        gtk_main ();
       
        return 0;     
}



example.glade

Code:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
<!--Generated with glade3 3.4.0 on Fri Nov 30 13:06:29 2007 -->
<glade-interface>
  <widget class="GtkWindow" id="window">
    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
    <property name="border_width">10</property>
    <signal name="destroy" handler="gtk_main_quit"/>
    <child>
      <widget class="GtkVBox" id="vbox1">
        <property name="visible">True</property>
        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
        <child>
          <widget class="GtkHBox" id="hbox1">
            <property name="visible">True</property>
            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
            <property name="spacing">5</property>
            <child>
              <widget class="GtkEntry" id="execute_entry">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
              </widget>
            </child>
            <child>
              <widget class="GtkButton" id="execute_button">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="receives_default">True</property>
                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                <property name="label" translatable="yes">gtk-execute</property>
                <property name="use_stock">True</property>
                <property name="response_id">0</property>
                <signal name="clicked" handler="on_execute_button_clicked"/>
              </widget>
              <packing>
                <property name="expand">False</property>
                <property name="position">1</property>
              </packing>
            </child>
          </widget>
          <packing>
            <property name="expand">False</property>
          </packing>
        </child>
        <child>
          <widget class="GtkScrolledWindow" id="scrolledwindow1">
            <property name="visible">True</property>
            <property name="can_focus">True</property>
            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
            <property name="border_width">2</property>
            <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
            <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
            <property name="shadow_type">GTK_SHADOW_ETCHED_IN</property>
            <child>
              <widget class="GtkTextView" id="output_textview">
                <property name="visible">True</property>
                <property name="can_focus">True</property>
                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
              </widget>
            </child>
          </widget>
          <packing>
            <property name="position">1</property>
          </packing>
        </child>
      </widget>
    </child>
  </widget>
</glade-interface>

_________________
Micah Carrick - Forum Administrator
http://www.micahcarrick.com


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 07, 2007 8:58 am 
Offline

Joined: Thu Jan 04, 2007 9:59 am
Posts: 3
Location: France
Hello,

Some comments :
  • Why use Libglade and not new GtkBuilder Widget?
  • If command takes times, it's worth a better use g_spawn_command_line_async


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 07, 2007 4:09 pm 
Offline
Never Seen the Sunlight

Joined: Wed Sep 21, 2005 12:07 am
Posts: 563
Location: Portland, OR USA
Quote:
Why use Libglade and not new GtkBuilder Widget?


Because I have not yet learned anything about GtkBuilder, but it's on my TODO list. :)

Quote:
If command takes times, it's worth a better use g_spawn_command_line_async


Very true. I was just doing a very, very simple example. Readers will want to look over the Spawning Processes documentation.

_________________
Micah Carrick - Forum Administrator
http://www.micahcarrick.com


Top
 Profile  
 
 Post subject:
PostPosted: Mon Dec 10, 2007 3:13 pm 
Offline

Joined: Thu Jan 04, 2007 9:59 am
Posts: 3
Location: France
Micah Carrick wrote:
Because I have not yet learned anything about GtkBuilder, but it's on my TODO list. :)

GtkBuilder is "juste" a libglade integration in GTK+.

First delete line 33 in example.glade (bug #496344) :
Code:
<property name="response_id">0</property>


Convert .glade file in GtkBuilder XML format :
Code:
gtk-builder-convert example.glade example.xml


And remplace glade_* functions :
Code:
/*
Example running a command into a GtkTextView by Micah Carrick
Written for www.gtkforums.com
Compile using:
gcc -Wall -g main.c -o example `pkg-config --cflags --libs gtk+-2.0 libglade-2.0`
*/

#include <gtk/gtk.h>

/* structure to hold references to our widgets */
typedef struct
{
        GtkWidget               *entry;
        GtkWidget               *textview;
} MyWidgets;

/* call back function for when the button is pressed */
static void
on_execute_button_clicked (GtkWidget* widget, gpointer user_data)
{
        MyWidgets               *widgets;
        gchar                   *output;
        const gchar             *command;
        GError                  *error = NULL;
        GtkTextBuffer           *buffer;

        widgets = (MyWidgets *)user_data;
        command = gtk_entry_get_text (GTK_ENTRY (widgets->entry));

        /* execute command */
        g_spawn_command_line_sync (command, &output, NULL, NULL, &error);

        if (error != NULL)
        {
                GtkWidget *dialog;

                /* create an error dialog containing the error message */
                dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_DESTROY_WITH_PARENT,
                                                GTK_MESSAGE_ERROR,
                                                GTK_BUTTONS_OK,
                                                error->message);
                gtk_window_set_title (GTK_WINDOW (dialog), "Error");

                /* run the dialog */
                gtk_dialog_run (GTK_DIALOG (dialog));

                /* clean up memory used by dialog and error */
                gtk_widget_destroy (dialog);
                g_error_free(error);

                return;
        }

        /* get the text buffer */
        buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widgets->textview));

        /* set the text in the buffer to the output */
        gtk_text_buffer_set_text (buffer, output, -1);

        /* free the output string */
        g_free (output);
}

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

        GtkWidget               *window;
        GtkBuilder              *gxml;
        MyWidgets               *widgets;
        PangoFontDescription    *font_desc;

        widgets = g_slice_new (MyWidgets);

        /* initialize the GTK+ library */
        gtk_init (&argc, &argv);

        /* build GladeXML object from the glade XML file */
        gxml = gtk_builder_new ();
        gtk_builder_add_from_file (gxml, "example.xml", NULL);

        /* get widgets from GladeXML object */
        window = GTK_WIDGET (gtk_builder_get_object (gxml, "window"));
        widgets->entry = GTK_WIDGET (gtk_builder_get_object (gxml, "execute_entry"));
        widgets->textview = GTK_WIDGET (gtk_builder_get_object (gxml, "output_textview"));

        /* call gtk_main_quit() when the window's "x" is clicked */
        g_signal_connect (G_OBJECT (window), "delete-event", gtk_main_quit,
                          NULL);

        /*
        Call on_button_clicked() when execute_button is clicked, passing the
        MyWidget struct to the function as the user_data
        */
        g_signal_connect (gtk_builder_get_object (gxml, "execute_button"),
                          "clicked", G_CALLBACK (on_execute_button_clicked),
                          widgets);

        /* free GladeXML object */
        g_object_unref (G_OBJECT (gxml));

        /* use a fixed width font on the text view so the output looks proper */

        font_desc = pango_font_description_from_string ("monospace 10");
        gtk_widget_modify_font (widgets->textview, font_desc);
        pango_font_description_free (font_desc);

        /* show the main window */
        gtk_widget_show (window);

        gtk_main ();

        return 0;
}


;)


Top
 Profile  
 
 Post subject:
PostPosted: Sat Aug 22, 2009 4:24 pm 
Offline
Familiar Face

Joined: Thu Aug 20, 2009 1:54 pm
Posts: 42
Location: Belgium
Thank you for the example.

I have a little problem with some commands:
Quote:
Gtk-CRITICAL **: gtk_text_buffer_emit_insert: assertion `g_utf8_validate (text, len, NULL)' failed

The output of the command is not showed in the GtkTextView.
It seems that the output is not UTF-8, so I have tried to convert it with g_locale_to_utf8 () but it didn't work.

The command output which produce the error contains some � characters when I run it in a terminal.

The command which produce the error : "latex foo.tex" or "pdflatex foo.tex" where foo.tex is a French document which produce some warnings at the compilation. The encoding of foo.tex is UTF-8.


An other question: is it possible to show the command output progressively?


Top
 Profile  
 
 Post subject:
PostPosted: Sun Sep 06, 2009 8:13 am 
Offline
Never Seen the Sunlight

Joined: Wed Jul 23, 2008 10:31 am
Posts: 2406
Location: Slovenia
Hello and sorry for the nasty delay, but I managed to miss this post completely.
swilmet wrote:
The output of the command is not showed in the GtkTextView.
It seems that the output is not UTF-8, so I have tried to convert it with g_locale_to_utf8 () but it didn't work.

The command output which produce the error contains some � characters when I run it in a terminal.

The command which produce the error : "latex foo.tex" or "pdflatex foo.tex" where foo.tex is a French document which produce some warnings at the compilation. The encoding of foo.tex is UTF-8.
What locale are you using (run "locale" in terminal if you don't know)? And in what encoding does latex report stuff (my guess would be iso-8859-1, but you should verify this)? There must be some collision here, meaning that some link in your chain is not outputting text in expected encoding.

swilmet wrote:
An other question: is it possible to show the command output progressively?
It is. I wrote blog post about this issue some time ago. You can find it here: http://tadeboro.blogspot.com/2009/07/spawning-processes-using-glib.html. Hope you'll find it useful.

Tadej


Top
 Profile  
 
 Post subject:
PostPosted: Sun Sep 06, 2009 12:12 pm 
Offline
Familiar Face

Joined: Thu Aug 20, 2009 1:54 pm
Posts: 42
Location: Belgium
My locale is en_US.UTF-8. For the encoding of the output of the latex command, I don't know how to find that... The man page doesn't speak about that.

I tried to run my program with an other LANG value, but it seems that GTK works only with UTF-8:
Quote:
$ LANG=en_US.ISO-8859-1 ./latexila

(process:4305): Gtk-WARNING **: Locale not supported by C library.
Using the fallback 'C' locale.


And thank you very much for the blog post, it will be useful :)


Top
 Profile  
 
 Post subject:
PostPosted: Sun Sep 06, 2009 1:51 pm 
Offline
Never Seen the Sunlight

Joined: Wed Jul 23, 2008 10:31 am
Posts: 2406
Location: Slovenia
Hi.

Now I'm almost sure latex is the problematic link here. I thought you're using some other locale on your system that would cause troubles, but since you're using UTF-8 locale, this scenario is out of the question. Maybe you should ask about this on some latex support mailing list or forums. (I never really used tex related software, so I cannot help you much here.)

As for the warning you get when trying to run your application in different locale, is is not directly related to GTK+. You don't have ISO-8859-1 locale for libc generated on your system. To see what locales are available on your system, try looking at "/etc/locale.gen" file, where all locales that are generated should be listed (this file is read by localegen application, which is responsible for creating locales). GTK+ does support other locales, but you need to have them generated.

Tadej


Top
 Profile  
 
 Post subject:
PostPosted: Sun Sep 06, 2009 4:01 pm 
Offline
Familiar Face

Joined: Thu Aug 20, 2009 1:54 pm
Posts: 42
Location: Belgium
tadeboro wrote:
Hi.

Now I'm almost sure latex is the problematic link here. I thought you're using some other locale on your system that would cause troubles, but since you're using UTF-8 locale, this scenario is out of the question. Maybe you should ask about this on some latex support mailing list or forums. (I never really used tex related software, so I cannot help you much here.)

OK, so when I will know which encoding latex use, how do I show the output in a GtkTextView in a portable way (so I want it to work both on UTF-8 systems and on systems which are not UTF-8)?
I will read the source code of Winefish (a GTK LaTeX editor) to see how they solved that problem. But in winefish the output is filtered, so it's not exactly the same.

tadeboro wrote:
As for the warning you get when trying to run your application in different locale, is is not directly related to GTK+. You don't have ISO-8859-1 locale for libc generated on your system. To see what locales are available on your system, try looking at "/etc/locale.gen" file, where all locales that are generated should be listed (this file is read by localegen application, which is responsible for creating locales). GTK+ does support other locales, but you need to have them generated.

Tadej

OK, on my system (Ubuntu 9.04) I can see the generated locales by running "locale -a", the file /etc/locale.gen does not exist.

Thanks for your replies.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Sep 06, 2009 4:17 pm 
Offline
Never Seen the Sunlight

Joined: Wed Jul 23, 2008 10:31 am
Posts: 2406
Location: Slovenia
Hello.

Glib has some nice wrappers around character conversion functions. Have a look here for more info: http://library.gnome.org/devel/glib/stable/glib-Character-Set-Conversion.html.

Tadej


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 08, 2009 10:24 pm 
Offline
Familiar Face

Joined: Thu Aug 20, 2009 1:54 pm
Posts: 42
Location: Belgium
The encoding of the output of the latex and pdflatex commands is ISO-8859-1, so your guess was right.
Using g_convert (), or g_io_channel_set_encoding () works fine.
Thanks for your help.


Top
 Profile  
 
 Post subject: UTF8 Conversion
PostPosted: Fri Nov 27, 2009 10:20 am 
Offline
Familiar Face

Joined: Mon Nov 16, 2009 8:37 am
Posts: 26
Hi guys, I can't seen to convert my string using g_locale_to_utf8 and g_convert. Both are returning null. Please advise!


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 31, 2009 10:08 pm 
Offline
Familiar Face

Joined: Thu Dec 31, 2009 9:54 pm
Posts: 5
Location: Argentina
Does anyone knows if this function works fine on Windows? I can't get it to work, and I don't know if I'm missing something :?
Here's my code:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <glib.h>

int main(int argc, char** argv)
{
   gchar* std_out = NULL;
   gchar* std_err = NULL;
   gint exit_status;
   GError* error = NULL;
   
   gchar* cmd = "'C:\\Archivos de programa\\nasm-2.05.01-dos\\nasm.exe'";
   g_spawn_command_line_sync(cmd, &std_out, &std_err, &exit_status, &error);
   
   if(error)
   {
      g_print("error: %s\n\n", error->message);
      g_error_free(error);
      system("pause");
      exit(EXIT_FAILURE);
   }
   
   if(std_out)
   {
      g_free(std_out);
   }
   
   if(std_err)
   {
      g_free(std_err);
   }

   system("pause");
        return EXIT_SUCCESS;
}

And the program's output:
Code:
error: Failed to execute helper program (Invalid argument)

Any help will be appreciated.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Dec 31, 2009 10:37 pm 
Offline
Never Seen the Sunlight

Joined: Wed Jul 23, 2008 10:31 am
Posts: 2406
Location: Slovenia
Hello and welcome to the GTK+ forums.

You're most probably having troubles because of spaces in path names. Try replacing your line 12 with this:
Code:
gchar* cmd = "\"C:\\Archivos\ de\ programa\\nasm-2.05.01-dos\\nasm.exe\"";

Does it work?

Tadej


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jan 01, 2010 6:41 pm 
Offline
Familiar Face

Joined: Thu Dec 31, 2009 9:54 pm
Posts: 5
Location: Argentina
Thanks for the reply. Unfortunally it didn't work, and I also tried changing the binarie to another directory but it didn't work neither.
These are some code snippets that I've tried without any success:
Code:
gchar* cmd = "'C:\\nasm.exe'";
gchar* cmd = "C:\\nasm.exe";
gchar* cmd = "C:/nasm.exe";
gchar* cmd = "'C:/nasm.exe'";
gchar* cmd = "nasm"; /* nasm is in my PATH variable */

So I'm confused, and I really want to avoid writting my own function with the ugly Windows API :P. BTW, happy new year to everyone :)


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 28 posts ]  Go to page 1, 2  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group