 |
GTK+ Forums Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
|
|
|
| Author |
Message |
|
|
Micah Carrick Never Seen the Sunlight
Joined: 21 Sep 2005 Posts: 546 Location: Portland, OR USA
|
Posted: Fri Nov 30, 2007 9:39 pm Post subject: Execute command into a GtkTextView (C and Libglade) |
|
|
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
|
Posted: Fri Dec 07, 2007 8:58 am Post subject: |
|
|
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
|
Posted: Fri Dec 07, 2007 4:09 pm Post subject: |
|
|
| 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
|
Posted: Mon Dec 10, 2007 3:13 pm Post subject: |
|
|
| 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
|
Posted: Sat Aug 22, 2009 4:24 pm Post subject: |
|
|
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
|
Posted: Sun Sep 06, 2009 8:13 am Post subject: |
|
|
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
|
Posted: Sun Sep 06, 2009 12:12 pm Post subject: |
|
|
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
|
Posted: Sun Sep 06, 2009 1:51 pm Post subject: |
|
|
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
|
Posted: Sun Sep 06, 2009 4:01 pm Post subject: |
|
|
| 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
|
|
| Back to top |
|
 |
swilmet Familiar Face
Joined: 20 Aug 2009 Posts: 20 Location: Belgium
|
Posted: Tue Sep 08, 2009 10:24 pm Post subject: |
|
|
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
|
Posted: Fri Nov 27, 2009 10:20 am Post subject: UTF8 Conversion |
|
|
| 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
|
Posted: Thu Dec 31, 2009 10:08 pm Post subject: |
|
|
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
|
Posted: Thu Dec 31, 2009 10:37 pm Post subject: |
|
|
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
|
Posted: Fri Jan 01, 2010 6:41 pm Post subject: |
|
|
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 |
|
 |
|
Powered by phpBB © 2001, 2005 phpBB Group CodeBB 1.0 Beta 2
|