Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trying to populate a GtkComboBox with model in C

Tags:

c

gtk

I'm really new to C and GTK+ so my problem might be painfully obvious. I have tried to follow examples and tutorials found all over the net.

I want a combo box with three values, the middle one being the default. I can successfully set it up using Glade but I have decided to rewrite everything in C. The combobox is drawn but it is empty/blank. I don't know what I am doing wrong.

...
GtkTreeIter iter;
GtkListStore *liststore;
GtkWidget *combo;

liststore = gtk_list_store_new(1, G_TYPE_STRING);
gtk_list_store_insert_with_values (liststore, &iter, 0, 0, "Don't install.", -1);
gtk_list_store_insert_with_values (liststore, &iter, 1, 0, "This user only.", -1);
gtk_list_store_insert_with_values (liststore, &iter, 2, 0, "All users.", -1);

combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(liststore));
gtk_combo_box_set_active (GTK_COMBO_BOX(combo), 1);
...
gtk_grid_attach (GTK_GRID(grid), combo, 2, 4, 1, 1);
...
like image 268
beanaroo Avatar asked Dec 16 '22 10:12

beanaroo


1 Answers

In your original code you correctly bound the data model to the combo box but you did not specified how the model should be presented (that is the view part of the whole model-view concept). This is what the GtkCellLayout is supposed to provide.

To give you an idea on why this added complexity is useful, here is an example that shows how to use the model to have custom background (this is bad UX and, depending on your theme, the background color can be totally ignored). I think the most difficult thing is avoiding memory leaks, so I added some comment on this regard:

#include <gtk/gtk.h>

int main(int argc, char **argv)
{
    GtkWidget *window;
    GtkListStore *liststore;
    GtkWidget *combo;
    GtkCellRenderer *column;

    gtk_init(&argc, &argv);

    liststore = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
    gtk_list_store_insert_with_values(liststore, NULL, -1,
                                      0, "red",
                                      1, "Don't install.",
                                      -1);
    gtk_list_store_insert_with_values(liststore, NULL, -1,
                                      0, "green",
                                      1, "This user only.",
                                      -1);
    gtk_list_store_insert_with_values(liststore, NULL, -1,
                                      0, "yellow",
                                      1, "All users.",
                                      -1);

    combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(liststore));

    /* liststore is now owned by combo, so the initial reference can
     * be dropped */
    g_object_unref(liststore);

    column = gtk_cell_renderer_text_new();
    gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), column, TRUE);

    /* column does not need to be g_object_unref()ed because it
     * is GInitiallyUnowned and the floating reference has been
     * passed to combo by the gtk_cell_layout_pack_start() call. */

    gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), column,
                                   "cell-background", 0,
                                   "text", 1,
                                   NULL);

    gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 1);

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_container_add(GTK_CONTAINER(window), combo);

    /* Also combo is GInitiallyUnowned and it is now owned
       by window after the gtk_container_add() call. */

    gtk_widget_show_all(window);
    gtk_main();

    return 0;
}

But if you intend to use only strings in your combo box, the code can be stripped down by leveraging GtkComboBoxText:

#include <gtk/gtk.h>

int main(int argc, char **argv)
{
    GtkWidget *window, *combo;

    gtk_init(&argc, &argv);

    combo = gtk_combo_box_text_new();
    gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo), NULL, "Don't install.");
    gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo), NULL, "This user only.");
    gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo), NULL, "All users");
    gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 1);

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_container_add(GTK_CONTAINER(window), combo);

    gtk_widget_show_all(window);
    gtk_main();

    return 0;
}
like image 157
ntd Avatar answered Jan 02 '23 00:01

ntd