GTK+ Forums Forum Index GTK+ Forums
Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Execute command into a GtkTextView (C and Libglade)
Goto page 1, 2  Next
 
Post new topic   Reply to topic    GTK+ Forums Forum Index -> GTK+ Example Code
Author Message
Micah Carrick
Never Seen the Sunlight


Joined: 21 Sep 2005
Posts: 546
Location: Portland, OR USA

PostPosted: Fri Nov 30, 2007 9:39 pm    Post subject: Execute command into a GtkTextView (C and Libglade) Reply with quote

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.



main.c
Code: (C)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/*
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/HTML)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<?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>
Back to top
gege2061



Joined: 04 Jan 2007
Posts: 3
Location: France

PostPosted: Fri Dec 07, 2007 8:58 am    Post subject: Reply with quote

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
Back to top
Micah Carrick
Never Seen the Sunlight


Joined: 21 Sep 2005
Posts: 546
Location: Portland, OR USA

PostPosted: Fri Dec 07, 2007 4:09 pm    Post subject: Reply with quote

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.
Back to top
gege2061



Joined: 04 Jan 2007
Posts: 3
Location: France

PostPosted: Mon Dec 10, 2007 3:13 pm    Post subject: Reply with quote

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: (XML/HTML)
1
<property name="response_id">0</property>


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


And remplace glade_* functions :
Code: (C)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/*
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;
}


;)
Back to top
swilmet
Familiar Face


Joined: 20 Aug 2009
Posts: 20
Location: Belgium

PostPosted: Sat Aug 22, 2009 4:24 pm    Post subject: Reply with quote

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?
Back to top
tadeboro
Never Seen the Sunlight


Joined: 23 Jul 2008
Posts: 2114
Location: Slovenia

PostPosted: Sun Sep 06, 2009 8:13 am    Post subject: Reply with quote

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
Back to top
swilmet
Familiar Face


Joined: 20 Aug 2009
Posts: 20
Location: Belgium

PostPosted: Sun Sep 06, 2009 12:12 pm    Post subject: Reply with quote

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 :)
Back to top
tadeboro
Never Seen the Sunlight


Joined: 23 Jul 2008
Posts: 2114
Location: Slovenia

PostPosted: Sun Sep 06, 2009 1:51 pm    Post subject: Reply with quote

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
Back to top
swilmet
Familiar Face


Joined: 20 Aug 2009
Posts: 20
Location: Belgium

PostPosted: Sun Sep 06, 2009 4:01 pm    Post subject: Reply with quote

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.
Back to top
tadeboro
Never Seen the Sunlight


Joined: 23 Jul 2008
Posts: 2114
Location: Slovenia

PostPosted: Sun Sep 06, 2009 4:17 pm    Post subject: Reply with quote

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
Back to top
swilmet
Familiar Face


Joined: 20 Aug 2009
Posts: 20
Location: Belgium

PostPosted: Tue Sep 08, 2009 10:24 pm    Post subject: Reply with quote

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.
Back to top
EeeK
Familiar Face


Joined: 16 Nov 2009
Posts: 26

PostPosted: Fri Nov 27, 2009 10:20 am    Post subject: UTF8 Conversion Reply with quote

Hi guys, I can't seen to convert my string using g_locale_to_utf8 and g_convert. Both are returning null. Please advise!
Back to top
LGV
Familiar Face


Joined: 31 Dec 2009
Posts: 5
Location: Argentina

PostPosted: Thu Dec 31, 2009 10:08 pm    Post subject: Reply with quote

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: (C)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#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: (Plaintext)
1
error: Failed to execute helper program (Invalid argument)

Any help will be appreciated.
Back to top
tadeboro
Never Seen the Sunlight


Joined: 23 Jul 2008
Posts: 2114
Location: Slovenia

PostPosted: Thu Dec 31, 2009 10:37 pm    Post subject: Reply with quote

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: (C)
1
gchar* cmd = "\"C:\\Archivos\ de\ programa\\nasm-2.05.01-dos\\nasm.exe\"";

Does it work?

Tadej
Back to top
LGV
Familiar Face


Joined: 31 Dec 2009
Posts: 5
Location: Argentina

PostPosted: Fri Jan 01, 2010 6:41 pm    Post subject: Reply with quote

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: (C)
1
2
3
4
5
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 :)
Back to top
Display posts from previous:   
Post new topic   Reply to topic    GTK+ Forums Forum Index -> GTK+ Example Code All times are GMT
Goto page 1, 2  Next
Page 1 of 2

 


Powered by phpBB © 2001, 2005 phpBB Group
CodeBB 1.0 Beta 2
Protected by Anti-Spam ACP