From 886a208b1c624a76e2dc3ad5fd90a6534eb0e30d Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Fri, 9 Apr 2010 18:23:49 -0500 Subject: Hide EConfig sections that have no visible widgets The EConfig code that creates widgets based on .eplug descriptions will already hide sections that end up containing no child widgets. Here we also make that code hide sections that end up containing only invisible child widgets. We will use this from the actual plugins, so that if they decide not to show any widgets in Express mode, then the corresponding configuration sections will not show up in the preferences dialog. EConfig types 'section' and 'section-table' have an internal factory function, which doesn't return the actual GtkFrame that they create. Instead, they return a GtkContainer which is the actual vbox or table used to insert child widgets. Here we modify the internal factory function to also return the actual GtkFrame that it creates, so that the calling code can hide *that* frame properly. Signed-off-by: Federico Mena Quintero --- e-util/e-config.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 77 insertions(+), 15 deletions(-) diff --git a/e-util/e-config.c b/e-util/e-config.c index 613971fba5..e8eedffef8 100644 --- a/e-util/e-config.c +++ b/e-util/e-config.c @@ -41,6 +41,8 @@ #define d(x) +typedef GtkWidget * (*EConfigItemSectionFactoryFunc)(EConfig *ec, EConfigItem *, GtkWidget *parent, GtkWidget *old, gpointer data, GtkWidget **real_frame); + struct _EConfigFactory { gchar *id; EConfigFactoryFunc func; @@ -62,6 +64,7 @@ struct _widget_node { EConfigItem *item; GtkWidget *widget; /* widget created by the factory, if any */ GtkWidget *frame; /* if created by us */ + GtkWidget *real_frame; /* used for sections and section tables, this is the real GtkFrame (whereas "frame" above is the internal vbox/table) */ guint empty:1; /* set if empty (i.e. hidden) */ }; @@ -87,6 +90,8 @@ struct _EConfigPrivate { static gpointer parent_class; +static GtkWidget *ech_config_section_factory (EConfig *config, EConfigItem *item, GtkWidget *parent, GtkWidget *old, gpointer data, GtkWidget **real_frame); + static void config_finalize (GObject *object) { @@ -94,7 +99,7 @@ config_finalize (GObject *object) EConfigPrivate *p = emp->priv; GList *link; - d(printf("finalising EConfig %p\n", o)); + d(printf("finalising EConfig %p\n", object)); g_free(emp->id); @@ -519,6 +524,7 @@ ec_rebuild (EConfig *emp) struct _widget_node *sectionnode = NULL, *pagenode = NULL; GtkWidget *book = NULL, *page = NULL, *section = NULL, *root = NULL, *assistant = NULL; gint pageno = 0, sectionno = 0, itemno = 0; + gint n_visible_widgets = 0; struct _widget_node *last_active_page = NULL; gboolean is_assistant; GList *link; @@ -550,7 +556,7 @@ ec_rebuild (EConfig *emp) if (item->label != NULL) translated_label = gettext (item->label); - /* If the last section doesn't contain anything, hide it */ + /* If the last section doesn't contain any visible widgets, hide it */ if (sectionnode != NULL && sectionnode->frame != NULL && (item->type == E_CONFIG_PAGE_START @@ -558,11 +564,22 @@ ec_rebuild (EConfig *emp) || item->type == E_CONFIG_PAGE || item->type == E_CONFIG_SECTION || item->type == E_CONFIG_SECTION_TABLE)) { - if ((sectionnode->empty = itemno == 0)) { - gtk_widget_hide(sectionnode->frame); + if ((sectionnode->empty = (itemno == 0 || n_visible_widgets == 0))) { + if (sectionnode->real_frame) + gtk_widget_hide(sectionnode->real_frame); + + if (sectionnode->frame) + gtk_widget_hide(sectionnode->frame); + sectionno--; - } else - gtk_widget_show(sectionnode->frame); + } else { + if (sectionnode->real_frame) + gtk_widget_show(sectionnode->real_frame); + + if (sectionnode->frame) + gtk_widget_show(sectionnode->frame); + } + d(printf("%s section '%s' [sections=%d]\n", sectionnode->empty?"hiding":"showing", sectionnode->item->path, sectionno)); } @@ -791,12 +808,35 @@ ec_rebuild (EConfig *emp) } itemno = 0; + n_visible_widgets = 0; + + d(printf("Building section %s - '%s' - %s factory\n", item->path, item->label, item->factory ? "with" : "without")); + if (item->factory) { - section = item->factory(emp, item, page, wn->widget, wn->context->data); + /* For sections, we pass an extra argument to the usual EConfigItemFactoryFunc. + * If this is an automatically-generated section, that extra argument (real_frame from + * EConfigItemSectionFactoryFunc) will contain the actual GtkFrame upon returning. + */ + EConfigItemSectionFactoryFunc factory = (EConfigItemSectionFactoryFunc) item->factory; + + section = factory(emp, item, page, wn->widget, wn->context->data, &wn->real_frame); wn->frame = section; if (section) itemno = 1; + if (factory != ech_config_section_factory) { + /* This means there is a section that came from a user-specified factory, + * so we don't know what is inside the section. In that case, we increment + * n_visible_widgets so that the section will not get hidden later (we don't know + * if the section is empty or not, so we cannot decide to hide it). + * + * For automatically-generated sections, we use a special ech_config_section_factory() - + * see emph_construct_item(). + */ + n_visible_widgets++; + d(printf (" n_visible_widgets++ because there is a section factory -> frame=%p\n", section)); + } + if (section && ((item->type == E_CONFIG_SECTION && !GTK_IS_BOX(section)) || (item->type == E_CONFIG_SECTION_TABLE && !GTK_IS_TABLE(section)))) @@ -878,6 +918,11 @@ ec_rebuild (EConfig *emp) d(printf("item %d:%s widget %p\n", itemno, item->path, w)); + d(printf (" item %s: (%s - %s)\n", + item->path, + g_type_name_from_instance ((GTypeInstance *) w), + gtk_widget_get_visible (w) ? "visible" : "invisible")); + if (wn->widget && wn->widget != w) { d(printf("destroy old widget for item '%s'\n", item->path)); gtk_widget_destroy(wn->widget); @@ -887,18 +932,32 @@ ec_rebuild (EConfig *emp) if (w) { g_signal_connect(w, "destroy", G_CALLBACK(gtk_widget_destroyed), &wn->widget); itemno++; + + if (gtk_widget_get_visible (w)) + n_visible_widgets++; } break; } } - /* If the last section doesn't contain anything, hide it */ + /* If the last section doesn't contain any visible widgets, hide it */ if (sectionnode != NULL && sectionnode->frame != NULL) { - if ((sectionnode->empty = itemno == 0)) { - gtk_widget_hide(sectionnode->frame); + d(printf ("Section %s - %d visible widgets (frame=%p)\n", sectionnode->item->path, n_visible_widgets, sectionnode->frame)); + if ((sectionnode->empty = (itemno == 0 || n_visible_widgets == 0))) { + if (sectionnode->real_frame) + gtk_widget_hide(sectionnode->real_frame); + + if (sectionnode->frame) + gtk_widget_hide(sectionnode->frame); + sectionno--; - } else - gtk_widget_show(sectionnode->frame); + } else { + if (sectionnode->real_frame) + gtk_widget_show(sectionnode->real_frame); + + if (sectionnode->frame) + gtk_widget_show(sectionnode->frame); + } d(printf("%s section '%s' [sections=%d]\n", sectionnode->empty?"hiding":"showing", sectionnode->item->path, sectionno)); } @@ -1585,7 +1644,8 @@ ech_config_section_factory (EConfig *config, EConfigItem *item, GtkWidget *parent, GtkWidget *old, - gpointer data) + gpointer data, + GtkWidget **real_frame) { struct _EConfigHookGroup *group = data; GtkWidget *label = NULL; @@ -1612,6 +1672,8 @@ ech_config_section_factory (EConfig *config, gtk_frame_set_shadow_type (GTK_FRAME (widget), GTK_SHADOW_NONE); gtk_box_pack_start (GTK_BOX (parent), widget, FALSE, FALSE, 0); + *real_frame = widget; + /* This is why we have a custom factory for sections. * When the plugin is disabled the frame is invisible. */ plugin = group->hook->hook.plugin; @@ -1667,9 +1729,9 @@ emph_construct_item(EPluginHook *eph, EConfigHookGroup *menu, xmlNodePtr root, E if (item->user_data) item->factory = ech_config_widget_factory; else if (item->type == E_CONFIG_SECTION) - item->factory = ech_config_section_factory; + item->factory = (EConfigItemFactoryFunc) ech_config_section_factory; else if (item->type == E_CONFIG_SECTION_TABLE) - item->factory = ech_config_section_factory; + item->factory = (EConfigItemFactoryFunc) ech_config_section_factory; d(printf(" path=%s label=%s factory=%s\n", item->path, item->label, (gchar *)item->user_data)); -- cgit v1.2.3 From 476bead4e5fce5b87ceb275a9b4861735f9d20da Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Fri, 9 Apr 2010 18:34:45 -0500 Subject: Hide the junk plugin options in Express mode Signed-off-by: Federico Mena Quintero --- plugins/bogo-junk-plugin/bf-junk-filter.c | 12 ++++++++++-- plugins/sa-junk-plugin/em-junk-filter.c | 12 ++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/plugins/bogo-junk-plugin/bf-junk-filter.c b/plugins/bogo-junk-plugin/bf-junk-filter.c index 6d315da575..4190eebe86 100644 --- a/plugins/bogo-junk-plugin/bf-junk-filter.c +++ b/plugins/bogo-junk-plugin/bf-junk-filter.c @@ -51,6 +51,7 @@ #include #include #include +#include "shell/e-shell.h" #ifndef BOGOFILTER_BINARY #define BOGOFILTER_BINARY "/usr/bin/bogofilter" @@ -388,6 +389,7 @@ convert_unicode_cb (GtkWidget *widget, gpointer data) GtkWidget * org_gnome_bogo_convert_unicode (struct _EPlugin *epl, struct _EConfigHookItemFactoryData *data) { + EShell *shell; GtkWidget *check; guint i = ((GtkTable *)data->parent)->nrows; @@ -399,7 +401,13 @@ org_gnome_bogo_convert_unicode (struct _EPlugin *epl, struct _EConfigHookItemFac gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), em_junk_bf_unicode); g_signal_connect (GTK_TOGGLE_BUTTON (check), "toggled", G_CALLBACK (convert_unicode_cb), (gpointer) "/apps/evolution/mail/junk/bogofilter/unicode"); gtk_table_attach((GtkTable *)data->parent, check, 0, 1, i, i+1, 0, 0, 0, 0); - gtk_widget_show (check); - return (GtkWidget *)check; + + shell = e_shell_get_default (); + if (e_shell_get_express_mode (shell)) + gtk_widget_hide (check); + else + gtk_widget_show (check); + + return check; } diff --git a/plugins/sa-junk-plugin/em-junk-filter.c b/plugins/sa-junk-plugin/em-junk-filter.c index c0b59891a1..c8c53c6169 100644 --- a/plugins/sa-junk-plugin/em-junk-filter.c +++ b/plugins/sa-junk-plugin/em-junk-filter.c @@ -47,6 +47,7 @@ #include #include "mail/em-config.h" +#include "shell/e-shell.h" #include @@ -926,6 +927,7 @@ use_remote_tests_cb (GtkWidget *widget, gpointer data) GtkWidget * org_gnome_sa_use_remote_tests (struct _EPlugin *epl, struct _EConfigHookItemFactoryData *data) { + EShell *shell; GtkWidget *check, *vbox, *label; gchar *text = g_strdup_printf (" %s", _("This will make SpamAssassin more reliable, but slower")); guint i = ((GtkTable *)data->parent)->nrows; @@ -944,7 +946,13 @@ org_gnome_sa_use_remote_tests (struct _EPlugin *epl, struct _EConfigHookItemFact gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), !em_junk_sa_local_only); g_signal_connect (GTK_TOGGLE_BUTTON (check), "toggled", G_CALLBACK (use_remote_tests_cb), (gpointer) "/apps/evolution/mail/junk/sa/local_only"); gtk_table_attach((GtkTable *)data->parent, vbox, 0, 1, i, i+1, 0, 0, 0, 0); - gtk_widget_show_all (vbox); - return (GtkWidget *)vbox; + + shell = e_shell_get_default (); + if (e_shell_get_express_mode (shell)) + gtk_widget_hide (vbox); + else + gtk_widget_show_all (vbox); + + return vbox; } -- cgit v1.2.3