Today, after struggling, I finished my first Gtk+ application in C.
It is a simple application that has an entry widget and a button. When it is pressed, it counts the number of characters introduced by the user in the entry widget and shows it in a statusbar. Also, it has a menubar with two options: Clear -that clears the entry and statusbar widgets- and Quit, which opens a dialog box asking the user if they are sure about leaving.
This is how it looks:
I wanted to thank my mentor and the guys in #gtk+ because they helped me a lot :).
Here is the code:
#include
#include
#include
struct clear_window_data
{
GtkWidget * entry;
GtkWidget * statusbar;
gint context_id;
};
/******** callback functions **********/
void quit_dialog(GtkWidget *widget, gpointer window)
{
GtkWidget *dialog;
GtkResponseType result;
dialog = gtk_message_dialog_new(GTK_WINDOW(window),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_QUESTION,
GTK_BUTTONS_YES_NO,
"Are you sure to quit?");
gtk_window_set_title(GTK_WINDOW(dialog), "Question");
result= gtk_dialog_run(GTK_DIALOG(dialog));
if (result == GTK_RESPONSE_YES)
{
gtk_widget_destroy (window);
}
gtk_widget_destroy(dialog);
}
void clear_window(GtkWidget *widget, gpointer data)
{
struct clear_window_data * structData;
GtkWidget * entry;
GtkWidget * statusbar;
gint context_id;
structData = data;
entry = structData ->entry;
statusbar =structData ->statusbar;
context_id =structData -> context_id;
gtk_entry_set_text(GTK_ENTRY(entry), "");
gtk_statusbar_push(GTK_STATUSBAR(statusbar),
context_id," ");
}
void button_count(GtkWidget *widget, gpointer data)
{
struct clear_window_data * structData;
GtkWidget * entry;
GtkWidget * statusbar;
gint context_id;
const gchar *str;
char message[100];
int length;
structData = data;
entry = structData ->entry;
statusbar =structData ->statusbar;
context_id =structData -> context_id;
str = gtk_entry_get_text(GTK_ENTRY(entry));
length = strlen(str);
sprintf( message, "Number of chars: %d",length);
gtk_statusbar_push(GTK_STATUSBAR(statusbar),
context_id,message);
}
/********* main program **************/
int main( int argc, char *argv[])
{
struct clear_window_data data;
GtkWidget *window;
GtkWidget *table;
GtkWidget *button;
GtkWidget *entry;
GtkWidget *halign;
GtkWidget *halign2;
GtkWidget *statusbar;
GtkWidget *vbox;
GtkWidget *menubar;
GtkWidget *filemenu;
GtkWidget *file;
GtkWidget *quit;
GtkWidget *clear;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_widget_set_size_request (window, 300, 250);
gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
gtk_window_set_title(GTK_WINDOW(window), "Character counter");
menubar = gtk_menu_bar_new();
filemenu = gtk_menu_new();
file = gtk_menu_item_new_with_label("Options");
clear = gtk_menu_item_new_with_label("Clear");
quit = gtk_menu_item_new_with_label("Quit");
gtk_menu_item_set_submenu(GTK_MENU_ITEM(file), filemenu);
gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), clear);
gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), quit);
gtk_menu_shell_append(GTK_MENU_SHELL(menubar), file);
button = gtk_button_new_with_label("Count");
gtk_widget_set_size_request(button, 80, 35);
table = gtk_table_new(1, 3, FALSE);
gtk_table_set_col_spacings(GTK_TABLE(table), 3);
entry = gtk_entry_new();
halign = gtk_alignment_new(125, 0, 0, 0);
gtk_container_add(GTK_CONTAINER(halign), entry);
gtk_table_attach(GTK_TABLE(table), halign, 0, 2, 2, 3,
GTK_FILL, GTK_FILL, 0, 0);
halign2 = gtk_alignment_new(0, 100, 0, 0);
gtk_container_add(GTK_CONTAINER(halign2), button);
gtk_table_attach(GTK_TABLE(table), halign2, 2, 3,2, 3,
GTK_FILL, GTK_FILL, 0, 0);
statusbar = gtk_statusbar_new();
data.context_id = gtk_statusbar_get_context_id(GTK_STATUSBAR(statusbar),
"My statusbar");
gtk_statusbar_push(GTK_STATUSBAR(statusbar),data.context_id
, "My statusbar");
vbox = gtk_vbox_new(FALSE, 2);
gtk_container_add(GTK_CONTAINER(window), vbox);
gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 3);
gtk_box_pack_start(GTK_BOX(vbox), table, TRUE, TRUE, 1);
gtk_box_pack_start(GTK_BOX(vbox), statusbar, TRUE, TRUE, 1);
g_signal_connect(G_OBJECT(quit), "activate",
G_CALLBACK(quit_dialog), (gpointer) window);
data.entry = entry;
data.statusbar = statusbar;
g_signal_connect(G_OBJECT(clear),"activate",
G_CALLBACK(clear_window), (gpointer) &data);
g_signal_connect(button, "clicked", G_CALLBACK(button_count),
(gpointer) &data);
g_signal_connect_swapped(G_OBJECT(window), "destroy",
G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all(window);
gtk_main();
return 0;
}

Are you just starting to learn programming? What motivated you?
ReplyDeleteNice! Gtk+ is fun. When I was learning it during gsoc there was a book I followed which was quite good, but it was about Gtk2, which meant I had to make adjustments. Thanks for the post :-)
ReplyDeletevenky80 I'm participating in GNOME Outreach Program for Wome where I will be portin gplugins for Gedit, so one of the APIs I have to learn is Gtk+. I did the application just to practise.
ReplyDeleteTiffany do you remember which the book was??
"The Official GNOME 2 Developer's Guide":
ReplyDeletehttp://www.dgsiegel.net/files/tog2dg.pdf
Try vala It looks much more clean and modern.
ReplyDeletehttps://live.gnome.org/Vala
Gedit plugin in Vala:
https://github.com/jessevdk/gedit-code-assistance
Hello, Is this a joke?.
ReplyDeleteAs Atono said, try vala, Vala really rocks :)
Great stuff. Keep it up
ReplyDelete@antono @Jose
She needs to learn GTK+ in C to port stuff, so suggesting Vala (while more modern) will not really help learning GTK+ in C, or will it?
Am I right?
Nice !
ReplyDeleteSecond exercise:
1. add words count
2. remove the button and update the status bar on the fly instead.
BTW, your #include lines are incomplete (eaten in the copy/paste I suppose).
Congratulations.
ReplyDeleteBut in future, when you are pasting code snippets, use gist.github.com so that it is easier to read.