aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFederico Mena Quintero <federico@novell.com>2010-04-10 07:23:49 +0800
committerFederico Mena Quintero <federico@novell.com>2010-04-14 04:41:46 +0800
commit886a208b1c624a76e2dc3ad5fd90a6534eb0e30d (patch)
treed562f19f1ed45842593a5bb11547733e0968f51d
parentdae9d2e575e0a239c53d3079b8e20bd17f6c37b4 (diff)
downloadgsoc2013-evolution-886a208b1c624a76e2dc3ad5fd90a6534eb0e30d.tar
gsoc2013-evolution-886a208b1c624a76e2dc3ad5fd90a6534eb0e30d.tar.gz
gsoc2013-evolution-886a208b1c624a76e2dc3ad5fd90a6534eb0e30d.tar.bz2
gsoc2013-evolution-886a208b1c624a76e2dc3ad5fd90a6534eb0e30d.tar.lz
gsoc2013-evolution-886a208b1c624a76e2dc3ad5fd90a6534eb0e30d.tar.xz
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>
-rw-r--r--e-util/e-config.c92
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));