GNOME Bugzilla – Bug 324282
add selected signal to cell renderer combo
Last modified: 2008-05-28 11:55:56 UTC
Here's a patch (based on gtk+-2.8.6) for the cell renderer combo that will add a "selected" signal when the renderer doesn't have an entry. The "selected" signal is emitted when the user chooses an item in the popup menu and sends the path in the tree view store and an iterator to the cell renderer's store (the one that defines the popup menu). This allows the application to access more data from the renderer's model. A small test application is also supplied. --- --- gtkcellrenderercombo.h.orig 2005-12-16 10:25:13.918172000 -0600 +++ gtkcellrenderercombo.h 2005-12-16 10:33:50.476049000 -0600 @@ -51,6 +51,10 @@ struct _GtkCellRendererComboClass { GtkCellRendererTextClass parent; + + void (* selected) (GtkCellRendererCombo *cell_renderer_combo, + const gchar *path, + GtkTreeIter *riter); }; GType gtk_cell_renderer_combo_get_type (void) G_GNUC_CONST; --- gtkcellrenderercombo.c.orig 2005-12-16 10:25:07.121590000 -0600 +++ gtkcellrenderercombo.c 2005-12-16 10:30:48.842937000 -0600 @@ -20,6 +20,7 @@ #include <config.h> #include <string.h> +#include "gtkmarshalers.h" #include "gtkintl.h" #include "gtkbin.h" #include "gtkentry.h" @@ -59,6 +60,13 @@ PROP_HAS_ENTRY }; +enum { + SELECTED, + LAST_SIGNAL +}; + +static guint combo_cell_renderer_signals[LAST_SIGNAL]; + #define GTK_CELL_RENDERER_COMBO_PATH "gtk-cell-renderer-combo-path" G_DEFINE_TYPE (GtkCellRendererCombo, gtk_cell_renderer_combo, GTK_TYPE_CELL_RENDERER_TEXT); @@ -130,6 +138,16 @@ TRUE, GTK_PARAM_READWRITE)); + combo_cell_renderer_signals[SELECTED] = + g_signal_new("selected", + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GtkCellRendererComboClass, selected), + NULL, NULL, + _gtk_marshal_VOID__STRING_BOXED, + G_TYPE_NONE, 2, + G_TYPE_STRING, + GTK_TYPE_TREE_ITER); } static void @@ -270,6 +288,8 @@ if (canceled) return; + path = g_object_get_data (G_OBJECT (combo), GTK_CELL_RENDERER_COMBO_PATH); + if (GTK_IS_COMBO_BOX_ENTRY (combo)) { entry = GTK_ENTRY (gtk_bin_get_child (GTK_BIN (combo))); @@ -279,10 +299,12 @@ { model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo)); if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter)) + { + g_signal_emit( cell, combo_cell_renderer_signals[SELECTED], 0, path, &iter ); gtk_tree_model_get (model, &iter, cell->text_column, &new_text, -1); + } } - path = g_object_get_data (G_OBJECT (combo), GTK_CELL_RENDERER_COMBO_PATH); g_signal_emit_by_name (cell, "edited", path, new_text); g_free (new_text); --- gtkmarshalers.list.orig 2005-12-16 10:27:32.741536000 -0600 +++ gtkmarshalers.list 2005-12-16 10:27:49.847567000 -0600 @@ -92,6 +92,7 @@ VOID:POINTER,POINTER,POINTER VOID:POINTER,UINT VOID:STRING +VOID:STRING,BOXED VOID:STRING,STRING VOID:STRING,INT,POINTER VOID:STRING,UINT,FLAGS ---- #include <gtk/gtk.h> static void destroy( GtkWidget *widget, gpointer data ) { gtk_main_quit(); } static selected( GtkCellRenderer *renderer, gchar *path, GtkTreeIter *riter, gpointer user_data ) { GtkTreeModel *rstore; char *v1, *v2; GtkListStore *store = user_data; GtkTreeIter iter; g_object_get( renderer, "model", &rstore, NULL ); gtk_tree_model_get( rstore, riter, 0, &v1, 1, &v2, -1 ); if( gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(store),&iter,path) ) { gtk_list_store_set( store, &iter, 0, v1, 1, v2, -1 ); } } int main( int argc, char **argv ) { GtkWidget *window; GtkWidget *tree; GtkListStore *treestore, *store; GtkCellRenderer *renderer; GtkTreeIter iter; char *value; gtk_init( &argc, &argv ); window = gtk_window_new( GTK_WINDOW_TOPLEVEL ); treestore = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING); gtk_list_store_insert_with_values( treestore, &iter, 0, 0, "0", 1, "A", -1); gtk_list_store_insert_with_values( treestore, &iter, 1, 0, "1", 1, "B", -1); tree = gtk_tree_view_new_with_model( GTK_TREE_MODEL(treestore) ); store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING); gtk_list_store_insert_with_values( store, &iter, 0, 0, "0", 1, "A", -1 ); gtk_list_store_insert_with_values( store, &iter, 1, 0, "1", 1, "B", -1 ); gtk_list_store_insert_with_values( store, &iter, 2, 0, "2", 1, "C", -1 ); renderer = gtk_cell_renderer_combo_new(); g_object_set( renderer, "model", store, "text-column", 0, "has-entry", 0, "editable", 1, NULL ); g_signal_connect( renderer, "selected", G_CALLBACK(selected), treestore ); gtk_tree_view_append_column( GTK_TREE_VIEW(tree), gtk_tree_view_column_new_with_attributes("Index", renderer, "text", 0, NULL) ); gtk_tree_view_append_column( GTK_TREE_VIEW(tree), gtk_tree_view_column_new_with_attributes("Value", gtk_cell_renderer_text_new(), "text", 1, NULL) ); gtk_container_add( GTK_CONTAINER(window), tree ); g_signal_connect( G_OBJECT(window), "delete_event", G_CALLBACK(destroy), NULL); gtk_widget_show_all(window); gtk_main(); return 0; }
Could you please _attach_ that patch after adding a ChangeLog entry to it. The new signal also needs gtk-doc documentation comments, even if some existing signals are missing that. I would find this very useful, because it allows application developers to use a chosen ID while the user just chooses a text name for the ID, as is already possible with a regular GtkComboBox.
Created attachment 85192 [details] [review] add "selected" signal
Created attachment 85193 [details] [review] add signature for "selected" signal
Created attachment 85194 [details] ChangeLog for "selected" signal
Something to consider about this patch: When I designed this signal I made it so that it only fires if the GtkCellRendererCombo does not have an entry. Since there is no good way to detect if the user has type in the same value that is in the popup menu, I didn't feel that there was a reliable way for the signal to work if the user was allowed to type something in, thus decided to eliminate that case. Since, in bug #408291, it has been discussed that another combo renderer without an entry may be added, this signal might be better suited for that object instead. Also (and I apologize for this), I currently have no easy way to build this patch (our environment is still on gtk+-2.6), so the attached patch has not been compiled or tested with gtk+-2.10.11.
Please create one patch file. You do not need to patch each file individually. A simple "svn diff > something.patch" will create that file if you have checked the source code out of svn and made your changes. By the way, you can get help with this kind of thing from the gnome-love group.
Created attachment 85203 [details] [review] selected signal patch for GtkCellRendererCombo
Could we apply this to svn trunk? It seems genuinely useful. We have a gtkmm request for this too.
+ g_signal_new("selected", Needs a space before the bracket. if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter)) + { + g_signal_emit( cell, combo_cell_renderer_signals[SELECTED], 0, path, &iter ); gtk_tree_model_get (model, &iter, cell->text_column, &new_text, -1); + } With GTK+'s code, curly brackets for if statements are indented by two spaces relative to the if statement, and the spacing around the opening bracket after "g_signal_emit" is wrong. The docs for the new signal should also have a "Since: 2.12" line. Other than that, the patch looks good to me!
Created attachment 89461 [details] [review] other patch I made a couple of changes to the patch: - Renamed signal to changed, since the signal is named changed on GtkComboBox too. - We *cannot* add this signal to GtkComboBoxClass, since it doesn't have padding for extra signal handlers ... - The signal will emit on every selection of a combo box item while the combo box is visible (see 317387 for some related discussion) - As noted in the documentation of the signal, you most probably want to delay actually updating the model until edited is fired ... You'll see that editing will be stopped as soon as you change the model. - Also this patch cannot detect if a user entered a value which is the same as one of the values in the list. If we really need support for this, it needs to be in GtkComboBox and not here.
GtkComboBoxClass should be GtkCellRendererComboClass of course ...
*** Bug 534029 has been marked as a duplicate of this bug. ***
What is preventing this patch from being committed? It looks straight-forward to me...
I have an updated version of this patch. Lemme check what changed there and then I will commit in time for 2.14.
A problem that is left is when you "commit" the selected value from the edited or editing_canceled (you probably want to commit this value when the view loses focus, but this is currently considered a cancellation) callback, the Esc key is not properly handled. Esc cancels editing and this goes through editing_canceled. How exactly the developer wants the setup to behave is something that can be controlled/implemented outside of GTK+. I committed this signal (finally) in r20206. The behavioral issues (also what is being discussed in 317387) are pending on basically a redesign of the CellEditable interface -- this is on my list to properly tackle at some point.