harry courtice
harry courtice

Reputation: 209

how to get selection from a gtk3 combobox with tree model

I'm new to GTK. The last GUI application I wrote used the text mode GUI in Turbo C, so I have a little catching up to do.

I'm using GTK to write a test harness for some code that will eventually be in an embedded system. I'm using a combobox with a tree model to provide a 2-level selection. I got the combobox to display as I wanted, although I don't have a good understaning of the cell_renderer parts that I just copied and pasted from another stack overflow question.

GtkTreeStore* model = gtk_tree_store_new(1,G_TYPE_STRING)
(Initilise model to hold desired strings using 
   gtk_tree_store_append and gtk_tree_store_set)

GtkWidget* combobox = gtk_combo_box_new_with_model(model);
gtk_combo_box_set_entry_text_column(combobox, 0);

GtkCellRenderer *column = gtk_cell_renderer_text_new();
gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combobox),column,TRUE);
gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combobox), column,"text", 0,NULL);

This code worked to display the combobox. Now I needed to get the selection from the combobox. I tried getting an index from the combobox using gtk_combo_box_get_active (). The index returned didn't help me. For sub-tree items, It only showed the position relative to the parent. So, I tried to pull out the text of the selected option. A bit more searching found me this line to pull the text from the combobox:

gchar * selection = gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(MyCombobox))));

however, calling this gave me the following error, and returned (null).

(test.exe:3040): GLib-GObject-WARNING **: invalid cast from `GtkCellView' to `GtkEntry'
(test.exe:3040): Gtk-CRITICAL **: gtk_entry_get_text: assertion `GTK_IS_ENTRY (entry)' failed

So, a bit more googling indicated that I need to initialise the combobox with an "entry", so updated my initialisation of the combobox to:

combobox = gtk_combo_box_new_with_model_and_entry(model);

And partial success!!. Now I can pull the text from the combobox, but it displays the selection text twice, on the combobox drop-down. Once the selection is made, it displays single in the box itself. so, if my model text is:

opt10  
    opt11  
opt20  
    opt21  

The tree displays each item twice (selecting first opt11)

[opt10 opt10] >  opt10  opt10  
                [opt11  opt11]  
 opt20 opt20 >  

Once I make my selection, (say opt11) the combobox shows the selected text correctly, and my call to gtk_entry_get_text(.....) returns the text "opt11" like I expect.

So, I'm at a dead-end. I want to query the combobox to get either an index that uniquely identifies the item in the tree, or a text string. I have the text string method working, but it makes the combobox options display twice.

Help?

Thanks,

Upvotes: 1

Views: 1883

Answers (1)

jcoppens
jcoppens

Reputation: 5440

This should work... Compile this code with the command in the comments. This is the 'full' version, using a model and such... If you just want to select a name from a list, you can use GtkComboBoxText, which is easier to use...

/*
 * main.c
 * Copyright (C) 2015 John Coppens <[email protected]>
 * 
 * standalone_filechooser is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * standalone_filechooser is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *   gcc -o main `pkg-config --libs --cflags gtk+-3.0` main.c
 */

#include <stdio.h>
#include <gtk/gtk.h>

int
on_destroy(GtkWidget *win, gpointer data)
{
  gtk_main_quit();
  return FALSE;
}

void
sel_changed(GtkComboBox *cbbox, gpointer data)
{
  GtkListStore *store;
  GtkTreeIter iter;
  int item_nr, ok;
  char *item;

  ok = gtk_combo_box_get_active_iter(cbbox, &iter);
  printf("%i\n", ok);
  store = GTK_LIST_STORE(gtk_combo_box_get_model(cbbox));
  gtk_tree_model_get(GTK_TREE_MODEL(store), &iter,
    0, &item_nr,
    1, &item,
    -1);

  printf("Item: %s, nr: %d\n", item, item_nr);
  g_free(item);
}

int main(int argc, char *argv[])
{
  GtkWidget *win, *cbbox;
  GtkCellRenderer *col;
  GtkListStore *store;
  GtkTreeIter iter;
  int i;
  char *items[] = {"Thingie 1", "Thingie 2", "Thingie 3"};

  gtk_init(&argc, &argv);

  win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  g_signal_connect(G_OBJECT(win), "destroy", G_CALLBACK(on_destroy), NULL);

  store = gtk_list_store_new(2, G_TYPE_INT, G_TYPE_STRING);
  for (i = 0; i < sizeof(items)/sizeof(char *); i++) {
    gtk_list_store_append(store, &iter);
    gtk_list_store_set(store, &iter,
        0, i,
        1, items[i],
        -1);
  }

  cbbox = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store));
  g_object_unref(store);
  col = gtk_cell_renderer_text_new();
  gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(cbbox), col, TRUE);
  gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(cbbox), col, 
        "text", 1,
        NULL);

  gtk_combo_box_set_id_column(GTK_COMBO_BOX(cbbox), 1);
  g_signal_connect(G_OBJECT(cbbox), "changed", G_CALLBACK(sel_changed), NULL);


  gtk_container_add(GTK_CONTAINER(win), cbbox);

  gtk_widget_show_all(win);

  gtk_main();

  return 0;
}

Upvotes: 1

Related Questions