Thursday, 15 December 2011

My first Gtk+ application

Hi everyone :)
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;
}

9 comments:

  1. Are you just starting to learn programming? What motivated you?

    ReplyDelete
  2. Nice! 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 :-)

    ReplyDelete
  3. venky80 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.
    Tiffany do you remember which the book was??

    ReplyDelete
  4. "The Official GNOME 2 Developer's Guide":
    http://www.dgsiegel.net/files/tog2dg.pdf

    ReplyDelete
  5. Try vala It looks much more clean and modern.
    https://live.gnome.org/Vala

    Gedit plugin in Vala:
    https://github.com/jessevdk/gedit-code-assistance

    ReplyDelete
  6. Hello, Is this a joke?.
    As Atono said, try vala, Vala really rocks :)

    ReplyDelete
  7. Great stuff. Keep it up
    @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?

    ReplyDelete
  8. Nice !

    Second 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).

    ReplyDelete
  9. Congratulations.

    But in future, when you are pasting code snippets, use gist.github.com so that it is easier to read.

    ReplyDelete