diff options
author | Federico Mena Quintero <federico@novell.com> | 2010-04-10 07:23:49 +0800 |
---|---|---|
committer | Federico Mena Quintero <federico@novell.com> | 2010-04-14 04:41:46 +0800 |
commit | 886a208b1c624a76e2dc3ad5fd90a6534eb0e30d (patch) | |
tree | d562f19f1ed45842593a5bb11547733e0968f51d /e-util | |
parent | dae9d2e575e0a239c53d3079b8e20bd17f6c37b4 (diff) | |
download | gsoc2013-evolution-886a208b1c624a76e2dc3ad5fd90a6534eb0e30d.tar.gz gsoc2013-evolution-886a208b1c624a76e2dc3ad5fd90a6534eb0e30d.tar.zst gsoc2013-evolution-886a208b1c624a76e2dc3ad5fd90a6534eb0e30d.zip |
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 <federico@novell.com>
Diffstat (limited to 'e-util')
-rw-r--r-- | e-util/e-config.c | 92 |
1 files 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)); |