From 72e856947e9d6183b2d04cffd65805fa7426caeb Mon Sep 17 00:00:00 2001 From: Matthew Brush Date: Wed, 19 Oct 2011 00:35:24 -0700 Subject: [PATCH] Rework GtkBuilder code to behave more like old Glade 2 code * Put back ui_hookup_widget and ui_lookup_widget functions * Put back lookup_widget code in stash.c * Emulate old create_*() functions from interface.[ch]. * Hookup all the GtkBuilder widget's to their top widgets like Glade 2 generated code would've done. * Misc changes to accomodate the above. --- plugins/geanyfunctions.h | 4 - src/main.c | 8 +- src/plugindata.h | 2 - src/plugins.c | 4 +- src/prefs.c | 2 +- src/project.c | 2 +- src/stash.c | 26 +++-- src/ui_utils.c | 198 ++++++++++++++++++++++++--------------- src/ui_utils.h | 20 ++-- src/vte.c | 16 ++-- 10 files changed, 166 insertions(+), 116 deletions(-) diff --git a/plugins/geanyfunctions.h b/plugins/geanyfunctions.h index 0f57b156..5af341ed 100644 --- a/plugins/geanyfunctions.h +++ b/plugins/geanyfunctions.h @@ -302,10 +302,6 @@ geany_functions->p_ui->ui_combo_box_add_to_history #define ui_menu_add_document_items_sorted \ geany_functions->p_ui->ui_menu_add_document_items_sorted -#define ui_hookup_object \ - geany_functions->p_ui->ui_hookup_object -#define ui_lookup_object \ - geany_functions->p_ui->ui_lookup_object #define dialogs_show_question \ geany_functions->p_dialogs->dialogs_show_question #define dialogs_show_msgbox \ diff --git a/src/main.c b/src/main.c index 07d7d051..1d18f442 100644 --- a/src/main.c +++ b/src/main.c @@ -241,7 +241,7 @@ static void main_init(void) ui_init_stock_items(); - main_widgets.window = ui_lookup_widget(NULL, "window1"); + main_widgets.window = create_window1(); /* add recent projects to the Project menu */ ui_widgets.recent_projects_menuitem = ui_lookup_widget(main_widgets.window, "recent_projects1"); @@ -253,12 +253,12 @@ static void main_init(void) main_widgets.toolbar = toolbar_init(); main_widgets.sidebar_notebook = ui_lookup_widget(main_widgets.window, "notebook3"); main_widgets.notebook = ui_lookup_widget(main_widgets.window, "notebook1"); - main_widgets.editor_menu = ui_lookup_widget(NULL, "edit_menu1"); + main_widgets.editor_menu = create_edit_menu1(); main_widgets.tools_menu = ui_lookup_widget(main_widgets.window, "tools1_menu"); main_widgets.message_window_notebook = ui_lookup_widget(main_widgets.window, "notebook_info"); main_widgets.project_menu = ui_lookup_widget(main_widgets.window, "menu_project1_menu"); - ui_widgets.toolbar_menu = ui_lookup_widget(NULL, "toolbar_popup_menu1"); + ui_widgets.toolbar_menu = create_toolbar_popup_menu1(); ui_init(); /* set widget names for matching with .gtkrc-2.0 */ @@ -1237,7 +1237,7 @@ void main_quit() g_free(app); - ui_finalize_builder(); /* After all widgets are cleaned up */ + ui_finalize_builder(); gtk_main_quit(); } diff --git a/src/plugindata.h b/src/plugindata.h index 7ee3c322..54da4b52 100644 --- a/src/plugindata.h +++ b/src/plugindata.h @@ -477,8 +477,6 @@ typedef struct UIUtilsFuncs const gchar *text, gint history_len); void (*ui_menu_add_document_items_sorted) (GtkMenu *menu, struct GeanyDocument *active, GCallback callback, GCompareFunc compare_func); - void (*ui_hookup_object) (GObject *obj, const gchar *object_name); - GObject* (*ui_lookup_object) (const gchar *object_name); } UIUtilsFuncs; diff --git a/src/plugins.c b/src/plugins.c index 543aa5a5..03efa8aa 100644 --- a/src/plugins.c +++ b/src/plugins.c @@ -246,9 +246,7 @@ static UIUtilsFuncs uiutils_funcs = { &ui_is_keyval_enter_or_return, &ui_get_gtk_settings_integer, &ui_combo_box_add_to_history, - &ui_menu_add_document_items_sorted, - &ui_hookup_object, - &ui_lookup_object + &ui_menu_add_document_items_sorted }; static DialogFuncs dialog_funcs = { diff --git a/src/prefs.c b/src/prefs.c index 1bb51e11..c65808f9 100644 --- a/src/prefs.c +++ b/src/prefs.c @@ -1629,7 +1629,7 @@ void prefs_show_dialog(void) gchar *encoding_string; GdkPixbuf *pb; - ui_widgets.prefs_dialog = ui_lookup_widget(NULL, "prefs_dialog"); + ui_widgets.prefs_dialog = create_prefs_dialog(); gtk_widget_set_name(ui_widgets.prefs_dialog, "GeanyPrefsDialog"); gtk_window_set_transient_for(GTK_WINDOW(ui_widgets.prefs_dialog), GTK_WINDOW(main_widgets.window)); pb = ui_new_pixbuf_from_inline(GEANY_IMAGE_LOGO); diff --git a/src/project.c b/src/project.c index 26ce0fd6..77b82abb 100644 --- a/src/project.c +++ b/src/project.c @@ -402,7 +402,7 @@ static void create_properties_dialog(PropertyDialogElements *e) GeanyDocument *doc = document_get_current(); GeanyFiletype *ft = NULL; - e->dialog = ui_lookup_widget(NULL, "project_dialog"); + e->dialog = create_project_dialog(); gtk_window_set_transient_for(GTK_WINDOW(e->dialog), GTK_WINDOW(main_widgets.window)); gtk_window_set_destroy_with_parent(GTK_WINDOW(e->dialog), TRUE); gtk_widget_set_name(e->dialog, "GeanyDialogProject"); diff --git a/src/stash.c b/src/stash.c index 8b77e5f3..6f266e87 100644 --- a/src/stash.c +++ b/src/stash.c @@ -86,7 +86,6 @@ #include /* only for strcmp() */ #include "support.h" /* only for _("text") */ #include "utils.h" /* only for foreach_*, utils_get_setting_*(). Stash should not depend on Geany. */ -#include "ui_utils.h" /* only for ui_lookup_object(). Stash should not depend on Geany. */ #include "stash.h" @@ -526,18 +525,31 @@ static void handle_combo_box_entry(GtkWidget *widget, StashPref *entry, } -/* FIXME */ /* taken from Glade 2.x generated support.c */ static GtkWidget* lookup_widget(GtkWidget *widget, const gchar *widget_name) { - GtkWidget *found_widget; + GtkWidget *parent, *found_widget; - (void) widget; /* not used anymore */ + g_return_val_if_fail(widget != NULL, NULL); + g_return_val_if_fail(widget_name != NULL, NULL); - found_widget = GTK_WIDGET(ui_lookup_object(widget_name)); - if (!found_widget) - g_warning ("Widget not found: %s", widget_name); + for (;;) + { + if (GTK_IS_MENU(widget)) + parent = gtk_menu_get_attach_widget(GTK_MENU(widget)); + else + parent = widget->parent; + if (parent == NULL) + parent = (GtkWidget*) g_object_get_data(G_OBJECT(widget), "GladeParentKey"); + if (parent == NULL) + break; + widget = parent; + } + + found_widget = (GtkWidget*) g_object_get_data(G_OBJECT(widget), widget_name); + if (G_UNLIKELY(found_widget == NULL)) + g_warning("Widget not found: %s", widget_name); return found_widget; } diff --git a/src/ui_utils.c b/src/ui_utils.c index 21073a78..2a8f70c8 100644 --- a/src/ui_utils.c +++ b/src/ui_utils.c @@ -63,7 +63,12 @@ GeanyMainWidgets main_widgets; UIPrefs ui_prefs; UIWidgets ui_widgets; -static GHashTable *objects_table = NULL; +static GtkBuilder *builder = NULL; +static GtkWidget* window1 = NULL; +static GtkWidget* toolbar_popup_menu1 = NULL; +static GtkWidget* edit_menu1 = NULL; +static GtkWidget* prefs_dialog = NULL; +static GtkWidget* project_dialog = NULL; static struct { @@ -2113,14 +2118,72 @@ static const gchar *ui_guess_object_name(GObject *obj) } +/* Compatibility functions */ +GtkWidget *create_edit_menu1(void) +{ + return edit_menu1; +} + + +GtkWidget *create_prefs_dialog(void) +{ + return prefs_dialog; +} + + +GtkWidget *create_project_dialog(void) +{ + return project_dialog; +} + + +GtkWidget *create_toolbar_popup_menu1(void) +{ + return toolbar_popup_menu1; +} + + +GtkWidget *create_window1(void) +{ + return window1; +} + + +static GtkWidget *ui_get_top_parent(GtkWidget *widget) +{ + GtkWidget *parent, *found_widget; + + g_return_val_if_fail(GTK_IS_WIDGET(widget), NULL); + + for (;;) + { + if (GTK_IS_MENU(widget)) + parent = gtk_menu_get_attach_widget(GTK_MENU(widget)); + else + parent = gtk_widget_get_parent(widget); + if (parent == NULL) + parent = (GtkWidget*) g_object_get_data(G_OBJECT(widget), "GladeParentKey"); + if (parent == NULL) + break; + widget = parent; + } + + return widget; +} + + void ui_init_builder(void) { gchar *interface_file; - const gchar *name; + const gchar *name, *toplevel_name; GError *error; GSList *iter, *all_objects; - GtkBuilder *builder; GtkCellRenderer *renderer; + GtkWidget *widget, *toplevel; + + /* prevent function from being called twice */ + if (GTK_IS_BUILDER(builder)) + return; builder = gtk_builder_new(); if (! builder) @@ -2143,33 +2206,52 @@ void ui_init_builder(void) gtk_builder_connect_signals(builder, NULL); - objects_table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_object_unref); + edit_menu1 = GTK_WIDGET(gtk_builder_get_object(builder, "edit_menu1")); + prefs_dialog = GTK_WIDGET(gtk_builder_get_object(builder, "prefs_dialog")); + project_dialog = GTK_WIDGET(gtk_builder_get_object(builder, "project_dialog")); + toolbar_popup_menu1 = GTK_WIDGET(gtk_builder_get_object(builder, "toolbar_popup_menu1")); + window1 = GTK_WIDGET(gtk_builder_get_object(builder, "window1")); + + g_object_set_data(G_OBJECT(edit_menu1), "edit_menu1", edit_menu1); + g_object_set_data(G_OBJECT(prefs_dialog), "prefs_dialog", prefs_dialog); + g_object_set_data(G_OBJECT(project_dialog), "project_dialog", project_dialog); + g_object_set_data(G_OBJECT(toolbar_popup_menu1), "toolbar_popup_menu1", toolbar_popup_menu1); + g_object_set_data(G_OBJECT(window1), "window1", window1); all_objects = gtk_builder_get_objects(builder); for (iter = all_objects; iter != NULL; iter = g_slist_next(iter)) { - name = ui_guess_object_name(iter->data); + if (! GTK_IS_WIDGET(iter->data)) + continue; + + widget = GTK_WIDGET(iter->data); + + name = ui_guess_object_name(G_OBJECT(widget)); if (! name) { g_warning("Unable to get name from GtkBuilder object"); continue; } - ui_hookup_object(iter->data, name); + toplevel = ui_get_top_parent(widget); + if (toplevel) + ui_hookup_widget(toplevel, widget, name); /* Glade doesn't seem to add cell renderers for the combo boxes, * so they are added here. */ - if (GTK_IS_COMBO_BOX(iter->data)) + if (GTK_IS_COMBO_BOX(widget)) { renderer = gtk_cell_renderer_text_new(); - gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(iter->data), renderer, TRUE); - gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(iter->data), + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget), renderer, TRUE); + gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(widget), renderer, "text", 0, NULL); } } g_slist_free(all_objects); - g_object_unref(builder); + /* FIXME: we don't want to loose all the unpacked GObjects which + * gets destroyed here, so we'll free the builder at the end */ + //g_object_unref(builder); } @@ -2226,8 +2308,20 @@ void ui_init(void) void ui_finalize_builder(void) { - if (objects_table != NULL) - g_hash_table_destroy(objects_table); + if (GTK_IS_BUILDER(builder)) + g_object_unref(builder); + + /* cleanup refs lingering even after GtkBuilder is destroyed */ + if (GTK_IS_WIDGET(edit_menu1)) + gtk_widget_destroy(edit_menu1); + if (GTK_IS_WIDGET(prefs_dialog)) + gtk_widget_destroy(prefs_dialog); + if (GTK_IS_WIDGET(project_dialog)) + gtk_widget_destroy(project_dialog); + if (GTK_IS_WIDGET(toolbar_popup_menu1)) + gtk_widget_destroy(toolbar_popup_menu1); + if (GTK_IS_WIDGET(window1)) + gtk_widget_destroy(window1); } @@ -2311,86 +2405,40 @@ void ui_widget_set_tooltip_text(GtkWidget *widget, const gchar *text) * Call it with the toplevel widget in the component (i.e. a window/dialog), * or alternatively any widget in the component, and the name of the widget * you want returned. - * - * @note Since 0.21 the @a widget parameter is not used and can be set - * to NULL if you like. - * * @param widget Widget with the @a widget_name property set. * @param widget_name Name to lookup. * @return The widget found. - * @see ui_hookup_object(). - * @see ui_lookup_object(). - * @deprecated Use ui_lookup_object instead. + * @see ui_hookup_widget(). * * @since 0.16 */ GtkWidget *ui_lookup_widget(GtkWidget *widget, const gchar *widget_name) { - GtkWidget *found_widget; - - (void) widget; /* not used anymore */ + GtkWidget *parent, *found_widget; + g_return_val_if_fail(widget != NULL, NULL); g_return_val_if_fail(widget_name != NULL, NULL); - found_widget = GTK_WIDGET(ui_lookup_object(widget_name)); + for (;;) + { + if (GTK_IS_MENU(widget)) + parent = gtk_menu_get_attach_widget(GTK_MENU(widget)); + else + parent = widget->parent; + if (parent == NULL) + parent = (GtkWidget*) g_object_get_data(G_OBJECT(widget), "GladeParentKey"); + if (parent == NULL) + break; + widget = parent; + } + + found_widget = (GtkWidget*) g_object_get_data(G_OBJECT(widget), widget_name); if (G_UNLIKELY(found_widget == NULL)) g_warning("Widget not found: %s", widget_name); - return found_widget; } -/** Returns a widget from a name. - * - * Call it with the name of the GObject you want returned. - * - * @note The GObject must either be in the GtkBuilder/Glade file or - * have been added with the function @a ui_hookup_object. - * - * @param widget Widget with the @a widget_name property set. - * @param widget_name Name to lookup. - * @return The widget found. - * - * @see ui_hookup_object() - * @since 0.21 - */ -GObject *ui_lookup_object(const gchar *object_name) -{ - gpointer *found; - - g_return_val_if_fail(object_name != NULL, NULL); - g_return_val_if_fail(objects_table != NULL, NULL); - - found = g_hash_table_lookup(objects_table, (gconstpointer) object_name); - - if (found == NULL) - return NULL; - - return G_OBJECT(found); -} - - -/** Sets a name to lookup GObject @a obj. - * - * The GObject can later be looked-up by the @a name using the - * @a ui_lookup_object() function. - * - * @param obj GObject. - * @param name Name. - * - * @see ui_lookup_object() - * @since 0.21 - **/ -void ui_hookup_object(GObject *obj, const gchar *object_name) -{ - g_return_if_fail(G_IS_OBJECT(obj)); - g_return_if_fail(object_name != NULL); - g_return_if_fail(objects_table != NULL); - - g_hash_table_insert(objects_table, g_strdup(object_name), g_object_ref(obj)); -} - - /* Progress Bar */ static guint progress_bar_timer_id = (guint) -1; diff --git a/src/ui_utils.h b/src/ui_utils.h index 892690dc..1742a70b 100644 --- a/src/ui_utils.h +++ b/src/ui_utils.h @@ -24,21 +24,16 @@ /** Sets a name to lookup @a widget from @a owner. - * - * @note Since 0.21 the @a owner parameter is not used and can be set - * to NULL if you like. - * * @param owner Usually a window, dialog or popup menu. * @param widget Widget. * @param widget_name Name. - * @see ui_hookup_object(). - * @see ui_lookup_object(). - * @deprecated Use ui_hookup_object() instead. + * @see ui_lookup_widget(). * * @since 0.16 **/ #define ui_hookup_widget(owner, widget, widget_name) \ - ui_hookup_object(G_OBJECT(widget), widget_name) + g_object_set_data_full(G_OBJECT(owner), widget_name, \ + g_object_ref(widget), (GDestroyNotify)g_object_unref); /** Interface preferences */ @@ -214,9 +209,12 @@ void ui_widget_set_tooltip_text(GtkWidget *widget, const gchar *text); GtkWidget *ui_lookup_widget(GtkWidget *widget, const gchar *widget_name); -GObject *ui_lookup_object(const gchar *object_name); - -void ui_hookup_object(GObject *obj, const gchar *object_name); +/* Compatibility functions */ +GtkWidget *create_edit_menu1(void); +GtkWidget *create_prefs_dialog(void); +GtkWidget *create_project_dialog(void); +GtkWidget *create_toolbar_popup_menu1(void); +GtkWidget *create_window1(void); void ui_widget_set_sensitive(GtkWidget *widget, gboolean set); diff --git a/src/vte.c b/src/vte.c index ef8d11d0..01e02523 100644 --- a/src/vte.c +++ b/src/vte.c @@ -489,12 +489,12 @@ static void vte_popup_menu_clicked(GtkMenuItem *menuitem, gpointer user_data) } case POPUP_PREFERENCES: { - GObject *notebook, *tab_page; + GtkWidget *notebook, *tab_page; prefs_show_dialog(); - notebook = ui_lookup_object("notebook2"); - tab_page = ui_lookup_object("frame_term"); + notebook = ui_lookup_widget(ui_widgets.prefs_dialog, "notebook2"); + tab_page = ui_lookup_widget(ui_widgets.prefs_dialog, "frame_term"); gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), gtk_notebook_page_num(GTK_NOTEBOOK(notebook), GTK_WIDGET(tab_page))); @@ -737,7 +737,7 @@ void vte_append_preferences_tab(void) { GtkWidget *frame_term, *button_shell, *entry_shell; GtkWidget *check_run_in_vte, *check_skip_script; - GObject *font_button, *fg_color_button, *bg_color_button; + GtkWidget *font_button, *fg_color_button, *bg_color_button; button_shell = GTK_WIDGET(ui_lookup_widget(ui_widgets.prefs_dialog, "button_term_shell")); entry_shell = GTK_WIDGET(ui_lookup_widget(ui_widgets.prefs_dialog, "entry_shell")); @@ -751,16 +751,16 @@ void vte_append_preferences_tab(void) g_signal_connect(G_OBJECT(check_run_in_vte), "toggled", G_CALLBACK(on_check_run_in_vte_toggled), check_skip_script); - font_button = ui_lookup_object("font_term"); + font_button = ui_lookup_widget(ui_widgets.prefs_dialog, "font_term"); g_signal_connect(font_button, "font-set", G_CALLBACK(on_term_font_set), NULL); - fg_color_button = ui_lookup_object("color_fore"); + fg_color_button = ui_lookup_widget(ui_widgets.prefs_dialog, "color_fore"); g_signal_connect(fg_color_button, "color-set", G_CALLBACK(on_term_fg_color_set), NULL); - bg_color_button = ui_lookup_object("color_back"); + bg_color_button = ui_lookup_widget(ui_widgets.prefs_dialog, "color_back"); g_signal_connect(bg_color_button, "color-set", G_CALLBACK(on_term_bg_color_set), NULL); - frame_term = GTK_WIDGET(ui_lookup_widget(ui_widgets.prefs_dialog, "frame_term")); + frame_term = ui_lookup_widget(ui_widgets.prefs_dialog, "frame_term"); gtk_widget_show_all(frame_term); } }