diff options
author | Matthew Barnes <mbarnes@redhat.com> | 2012-12-10 21:09:59 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@redhat.com> | 2012-12-13 03:33:43 +0800 |
commit | d09d8de870b6697c8a8b262e7e077b871a69b315 (patch) | |
tree | 3b718882e7a0bb0a996daf2967a033d91714c9b5 /e-util/e-source-combo-box.c | |
parent | b61331ed03ac1c7a9b8614e25510040b9c60ae02 (diff) | |
download | gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.tar.gz gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.tar.zst gsoc2013-evolution-d09d8de870b6697c8a8b262e7e077b871a69b315.zip |
Consolidate base utility libraries into libeutil.
Evolution consists of entirely too many small utility libraries, which
increases linking and loading time, places a burden on higher layers of
the application (e.g. modules) which has to remember to link to all the
small in-tree utility libraries, and makes it difficult to generate API
documentation for these utility libraries in one Gtk-Doc module.
Merge the following utility libraries under the umbrella of libeutil,
and enforce a single-include policy on libeutil so we can reorganize
the files as desired without disrupting its pseudo-public API.
libemail-utils/libemail-utils.la
libevolution-utils/libevolution-utils.la
filter/libfilter.la
widgets/e-timezone-dialog/libetimezonedialog.la
widgets/menus/libmenus.la
widgets/misc/libemiscwidgets.la
widgets/table/libetable.la
widgets/text/libetext.la
This also merges libedataserverui from the Evolution-Data-Server module,
since Evolution is its only consumer nowadays, and I'd like to make some
improvements to those APIs without concern for backward-compatibility.
And finally, start a Gtk-Doc module for libeutil. It's going to be a
project just getting all the symbols _listed_ much less _documented_.
But the skeletal structure is in place and I'm off to a good start.
Diffstat (limited to 'e-util/e-source-combo-box.c')
-rw-r--r-- | e-util/e-source-combo-box.c | 701 |
1 files changed, 701 insertions, 0 deletions
diff --git a/e-util/e-source-combo-box.c b/e-util/e-source-combo-box.c new file mode 100644 index 0000000000..d8d2273527 --- /dev/null +++ b/e-util/e-source-combo-box.c @@ -0,0 +1,701 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-source-combo-box.c + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU Lesser General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "e-source-combo-box.h" +#include "e-cell-renderer-color.h" + +#define E_SOURCE_COMBO_BOX_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_SOURCE_COMBO_BOX, ESourceComboBoxPrivate)) + +struct _ESourceComboBoxPrivate { + ESourceRegistry *registry; + gchar *extension_name; + + gulong source_added_handler_id; + gulong source_removed_handler_id; + gulong source_enabled_handler_id; + gulong source_disabled_handler_id; + + gboolean show_colors; +}; + +enum { + PROP_0, + PROP_EXTENSION_NAME, + PROP_REGISTRY, + PROP_SHOW_COLORS +}; + +enum { + COLUMN_COLOR, /* GDK_TYPE_COLOR */ + COLUMN_NAME, /* G_TYPE_STRING */ + COLUMN_SENSITIVE, /* G_TYPE_BOOLEAN */ + COLUMN_UID, /* G_TYPE_STRING */ + NUM_COLUMNS +}; + +G_DEFINE_TYPE (ESourceComboBox, e_source_combo_box, GTK_TYPE_COMBO_BOX) + +static gboolean +source_combo_box_traverse (GNode *node, + ESourceComboBox *combo_box) +{ + ESource *source; + ESourceSelectable *extension = NULL; + GtkTreeModel *model; + GtkTreeIter iter; + GString *indented; + GdkColor color; + const gchar *ext_name; + const gchar *display_name; + const gchar *uid; + gboolean sensitive = FALSE; + gboolean use_color = FALSE; + guint depth; + + /* Skip the root node. */ + if (G_NODE_IS_ROOT (node)) + return FALSE; + + ext_name = e_source_combo_box_get_extension_name (combo_box); + + model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box)); + gtk_list_store_append (GTK_LIST_STORE (model), &iter); + + source = E_SOURCE (node->data); + uid = e_source_get_uid (source); + display_name = e_source_get_display_name (source); + + indented = g_string_new (NULL); + + depth = g_node_depth (node); + g_warn_if_fail (depth > 1); + while (--depth > 1) + g_string_append (indented, " "); + g_string_append (indented, display_name); + + if (ext_name != NULL && e_source_has_extension (source, ext_name)) { + extension = e_source_get_extension (source, ext_name); + sensitive = TRUE; + } + + if (E_IS_SOURCE_SELECTABLE (extension)) { + const gchar *color_spec; + + color_spec = e_source_selectable_get_color (extension); + if (color_spec != NULL && *color_spec != '\0') + use_color = gdk_color_parse (color_spec, &color); + } + + gtk_list_store_set ( + GTK_LIST_STORE (model), &iter, + COLUMN_COLOR, use_color ? &color : NULL, + COLUMN_NAME, indented->str, + COLUMN_SENSITIVE, sensitive, + COLUMN_UID, uid, + -1); + + g_string_free (indented, TRUE); + + return FALSE; +} + +static void +source_combo_box_build_model (ESourceComboBox *combo_box) +{ + ESourceRegistry *registry; + GtkComboBox *gtk_combo_box; + GtkTreeModel *model; + GNode *root; + const gchar *active_id; + const gchar *extension_name; + + registry = e_source_combo_box_get_registry (combo_box); + extension_name = e_source_combo_box_get_extension_name (combo_box); + + gtk_combo_box = GTK_COMBO_BOX (combo_box); + model = gtk_combo_box_get_model (gtk_combo_box); + + /* Constructor properties trigger this function before the + * list store is configured. Detect it and return silently. */ + if (model == NULL) + return; + + /* Remember the active ID so we can try to restore it. */ + active_id = gtk_combo_box_get_active_id (gtk_combo_box); + + gtk_list_store_clear (GTK_LIST_STORE (model)); + + /* If we have no registry, leave the combo box empty. */ + if (registry == NULL) + return; + + /* If we have no extension name, leave the combo box empty. */ + if (extension_name == NULL) + return; + + root = e_source_registry_build_display_tree (registry, extension_name); + + g_node_traverse ( + root, G_PRE_ORDER, G_TRAVERSE_ALL, -1, + (GNodeTraverseFunc) source_combo_box_traverse, + combo_box); + + e_source_registry_free_display_tree (root); + + /* Restore the active ID, or else set it to something reasonable. */ + gtk_combo_box_set_active_id (gtk_combo_box, active_id); + if (gtk_combo_box_get_active_id (gtk_combo_box) == NULL) { + ESource *source; + + source = e_source_registry_ref_default_for_extension_name ( + registry, extension_name); + if (source != NULL) { + e_source_combo_box_set_active (combo_box, source); + g_object_unref (source); + } + } +} + +static void +source_combo_box_source_added_cb (ESourceRegistry *registry, + ESource *source, + ESourceComboBox *combo_box) +{ + source_combo_box_build_model (combo_box); +} + +static void +source_combo_box_source_removed_cb (ESourceRegistry *registry, + ESource *source, + ESourceComboBox *combo_box) +{ + source_combo_box_build_model (combo_box); +} + +static void +source_combo_box_source_enabled_cb (ESourceRegistry *registry, + ESource *source, + ESourceComboBox *combo_box) +{ + source_combo_box_build_model (combo_box); +} + +static void +source_combo_box_source_disabled_cb (ESourceRegistry *registry, + ESource *source, + ESourceComboBox *combo_box) +{ + source_combo_box_build_model (combo_box); +} + +static void +source_combo_box_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_EXTENSION_NAME: + e_source_combo_box_set_extension_name ( + E_SOURCE_COMBO_BOX (object), + g_value_get_string (value)); + return; + + case PROP_REGISTRY: + e_source_combo_box_set_registry ( + E_SOURCE_COMBO_BOX (object), + g_value_get_object (value)); + return; + + case PROP_SHOW_COLORS: + e_source_combo_box_set_show_colors ( + E_SOURCE_COMBO_BOX (object), + g_value_get_boolean (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +source_combo_box_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_EXTENSION_NAME: + g_value_set_string ( + value, + e_source_combo_box_get_extension_name ( + E_SOURCE_COMBO_BOX (object))); + return; + + case PROP_REGISTRY: + g_value_set_object ( + value, + e_source_combo_box_get_registry ( + E_SOURCE_COMBO_BOX (object))); + return; + + case PROP_SHOW_COLORS: + g_value_set_boolean ( + value, + e_source_combo_box_get_show_colors ( + E_SOURCE_COMBO_BOX (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +source_combo_box_dispose (GObject *object) +{ + ESourceComboBoxPrivate *priv; + + priv = E_SOURCE_COMBO_BOX_GET_PRIVATE (object); + + if (priv->registry != NULL) { + g_signal_handler_disconnect ( + priv->registry, + priv->source_added_handler_id); + g_signal_handler_disconnect ( + priv->registry, + priv->source_removed_handler_id); + g_signal_handler_disconnect ( + priv->registry, + priv->source_enabled_handler_id); + g_signal_handler_disconnect ( + priv->registry, + priv->source_disabled_handler_id); + g_object_unref (priv->registry); + priv->registry = NULL; + } + + /* Chain up to parent's "dispose" method. */ + G_OBJECT_CLASS (e_source_combo_box_parent_class)->dispose (object); +} + +static void +source_combo_box_finalize (GObject *object) +{ + ESourceComboBoxPrivate *priv; + + priv = E_SOURCE_COMBO_BOX_GET_PRIVATE (object); + + g_free (priv->extension_name); + + /* Chain up to parent's "finalize" method. */ + G_OBJECT_CLASS (e_source_combo_box_parent_class)->finalize (object); +} + +static void +source_combo_box_constructed (GObject *object) +{ + ESourceComboBox *combo_box; + GtkCellRenderer *renderer; + GtkCellLayout *layout; + GtkListStore *store; + + combo_box = E_SOURCE_COMBO_BOX (object); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (e_source_combo_box_parent_class)->constructed (object); + + store = gtk_list_store_new ( + NUM_COLUMNS, + GDK_TYPE_COLOR, /* COLUMN_COLOR */ + G_TYPE_STRING, /* COLUMN_NAME */ + G_TYPE_BOOLEAN, /* COLUMN_SENSITIVE */ + G_TYPE_STRING); /* COLUMN_UID */ + gtk_combo_box_set_model ( + GTK_COMBO_BOX (combo_box), + GTK_TREE_MODEL (store)); + g_object_unref (store); + + gtk_combo_box_set_id_column (GTK_COMBO_BOX (combo_box), COLUMN_UID); + + layout = GTK_CELL_LAYOUT (combo_box); + + renderer = e_cell_renderer_color_new (); + gtk_cell_layout_pack_start (layout, renderer, FALSE); + gtk_cell_layout_set_attributes ( + layout, renderer, + "color", COLUMN_COLOR, + "sensitive", COLUMN_SENSITIVE, + NULL); + + g_object_bind_property ( + combo_box, "show-colors", + renderer, "visible", + G_BINDING_SYNC_CREATE); + + renderer = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_start (layout, renderer, TRUE); + gtk_cell_layout_set_attributes ( + layout, renderer, + "text", COLUMN_NAME, + "sensitive", COLUMN_SENSITIVE, + NULL); + + source_combo_box_build_model (combo_box); +} + +static void +e_source_combo_box_class_init (ESourceComboBoxClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + g_type_class_add_private (class, sizeof (ESourceComboBoxPrivate)); + + object_class->set_property = source_combo_box_set_property; + object_class->get_property = source_combo_box_get_property; + object_class->dispose = source_combo_box_dispose; + object_class->finalize = source_combo_box_finalize; + object_class->constructed = source_combo_box_constructed; + + g_object_class_install_property ( + object_class, + PROP_EXTENSION_NAME, + g_param_spec_string ( + "extension-name", + "Extension Name", + "ESource extension name to filter", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + /* XXX Don't use G_PARAM_CONSTRUCT_ONLY here. We need to allow + * for this class to be instantiated by a GtkBuilder with no + * special construct parameters, and then subsequently give + * it an ESourceRegistry. */ + g_object_class_install_property ( + object_class, + PROP_REGISTRY, + g_param_spec_object ( + "registry", + "Registry", + "Data source registry", + E_TYPE_SOURCE_REGISTRY, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property ( + object_class, + PROP_SHOW_COLORS, + g_param_spec_boolean ( + "show-colors", + "Show Colors", + "Whether to show colors next to names", + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); +} + +static void +e_source_combo_box_init (ESourceComboBox *combo_box) +{ + combo_box->priv = E_SOURCE_COMBO_BOX_GET_PRIVATE (combo_box); + +} + +/** + * e_source_combo_box_new: + * @registry: an #ESourceRegistry, or %NULL + * @extension_name: an #ESource extension name + * + * Creates a new #ESourceComboBox widget that lets the user pick an #ESource + * from the provided #ESourceRegistry. The displayed sources are restricted + * to those which have an @extension_name extension. + * + * Returns: a new #ESourceComboBox + * + * Since: 2.22 + **/ +GtkWidget * +e_source_combo_box_new (ESourceRegistry *registry, + const gchar *extension_name) +{ + if (registry != NULL) + g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL); + + return g_object_new ( + E_TYPE_SOURCE_COMBO_BOX, "registry", registry, + "extension-name", extension_name, NULL); +} + +/** + * e_source_combo_box_get_registry: + * @combo_box: an #ESourceComboBox + * + * Returns the #ESourceRegistry used to populate @combo_box. + * + * Returns: the #ESourceRegistry, or %NULL + * + * Since: 3.6 + **/ +ESourceRegistry * +e_source_combo_box_get_registry (ESourceComboBox *combo_box) +{ + g_return_val_if_fail (E_IS_SOURCE_COMBO_BOX (combo_box), NULL); + + return combo_box->priv->registry; +} + +/** + * e_source_combo_box_set_registry: + * @combo_box: an #ESourceComboBox + * @registry: an #ESourceRegistry + * + * Sets the #ESourceRegistry used to populate @combo_box. + * + * This function is intended for cases where @combo_box is instantiated + * by a #GtkBuilder and has to be given an #ESourceRegistry after it is + * fully constructed. + * + * Since: 3.6 + **/ +void +e_source_combo_box_set_registry (ESourceComboBox *combo_box, + ESourceRegistry *registry) +{ + g_return_if_fail (E_IS_SOURCE_COMBO_BOX (combo_box)); + + if (combo_box->priv->registry == registry) + return; + + if (registry != NULL) { + g_return_if_fail (E_IS_SOURCE_REGISTRY (registry)); + g_object_ref (registry); + } + + if (combo_box->priv->registry != NULL) { + g_signal_handler_disconnect ( + combo_box->priv->registry, + combo_box->priv->source_added_handler_id); + g_signal_handler_disconnect ( + combo_box->priv->registry, + combo_box->priv->source_removed_handler_id); + g_signal_handler_disconnect ( + combo_box->priv->registry, + combo_box->priv->source_enabled_handler_id); + g_signal_handler_disconnect ( + combo_box->priv->registry, + combo_box->priv->source_disabled_handler_id); + g_object_unref (combo_box->priv->registry); + } + + combo_box->priv->registry = registry; + + combo_box->priv->source_added_handler_id = 0; + combo_box->priv->source_removed_handler_id = 0; + combo_box->priv->source_enabled_handler_id = 0; + combo_box->priv->source_disabled_handler_id = 0; + + if (registry != NULL) { + gulong handler_id; + + handler_id = g_signal_connect ( + registry, "source-added", + G_CALLBACK (source_combo_box_source_added_cb), + combo_box); + combo_box->priv->source_added_handler_id = handler_id; + + handler_id = g_signal_connect ( + registry, "source-removed", + G_CALLBACK (source_combo_box_source_removed_cb), + combo_box); + combo_box->priv->source_removed_handler_id = handler_id; + + handler_id = g_signal_connect ( + registry, "source-enabled", + G_CALLBACK (source_combo_box_source_enabled_cb), + combo_box); + combo_box->priv->source_enabled_handler_id = handler_id; + + handler_id = g_signal_connect ( + registry, "source-disabled", + G_CALLBACK (source_combo_box_source_disabled_cb), + combo_box); + combo_box->priv->source_disabled_handler_id = handler_id; + } + + source_combo_box_build_model (combo_box); + + g_object_notify (G_OBJECT (combo_box), "registry"); +} + +/** + * e_source_combo_box_get_extension_name: + * @combo_box: an #ESourceComboBox + * + * Returns the extension name used to filter which data sources are + * shown in @combo_box. + * + * Returns: the #ESource extension name + * + * Since: 3.6 + **/ +const gchar * +e_source_combo_box_get_extension_name (ESourceComboBox *combo_box) +{ + g_return_val_if_fail (E_IS_SOURCE_COMBO_BOX (combo_box), NULL); + + return combo_box->priv->extension_name; +} + +/** + * e_source_combo_box_set_extension_name: + * @combo_box: an #ESourceComboBox + * @extension_name: an #ESource extension name + * + * Sets the extension name used to filter which data sources are shown in + * @combo_box. + * + * Since: 3.6 + **/ +void +e_source_combo_box_set_extension_name (ESourceComboBox *combo_box, + const gchar *extension_name) +{ + g_return_if_fail (E_IS_SOURCE_COMBO_BOX (combo_box)); + + if (g_strcmp0 (combo_box->priv->extension_name, extension_name) == 0) + return; + + g_free (combo_box->priv->extension_name); + combo_box->priv->extension_name = g_strdup (extension_name); + + source_combo_box_build_model (combo_box); + + g_object_notify (G_OBJECT (combo_box), "extension-name"); +} + +/** + * e_source_combo_box_get_show_colors: + * @combo_box: an #ESourceComboBox + * + * Returns whether colors are shown next to data sources. + * + * Returns: %TRUE if colors are being shown + * + * Since: 3.6 + **/ +gboolean +e_source_combo_box_get_show_colors (ESourceComboBox *combo_box) +{ + g_return_val_if_fail (E_IS_SOURCE_COMBO_BOX (combo_box), FALSE); + + return combo_box->priv->show_colors; +} + +/** + * e_source_combo_box_set_show_colors: + * @combo_box: an #ESourceComboBox + * @show_colors: whether to show colors + * + * Sets whether to show colors next to data sources. + * + * Since: 3.6 + **/ +void +e_source_combo_box_set_show_colors (ESourceComboBox *combo_box, + gboolean show_colors) +{ + g_return_if_fail (E_IS_SOURCE_COMBO_BOX (combo_box)); + + if ((show_colors ? 1 : 0) == (combo_box->priv->show_colors ? 1 : 0)) + return; + + combo_box->priv->show_colors = show_colors; + + source_combo_box_build_model (combo_box); + + g_object_notify (G_OBJECT (combo_box), "show-colors"); +} + +/** + * e_source_combo_box_ref_active: + * @combo_box: an #ESourceComboBox + * + * Returns the #ESource corresponding to the currently active item, + * or %NULL if there is no active item. + * + * The returned #ESource is referenced for thread-safety and must be + * unreferenced with g_object_unref() when finished with it. + * + * Returns: an #ESource or %NULL + * + * Since: 3.6 + **/ +ESource * +e_source_combo_box_ref_active (ESourceComboBox *combo_box) +{ + ESourceRegistry *registry; + GtkComboBox *gtk_combo_box; + const gchar *active_id; + + g_return_val_if_fail (E_IS_SOURCE_COMBO_BOX (combo_box), NULL); + + registry = e_source_combo_box_get_registry (combo_box); + + gtk_combo_box = GTK_COMBO_BOX (combo_box); + active_id = gtk_combo_box_get_active_id (gtk_combo_box); + + if (active_id == NULL) + return NULL; + + return e_source_registry_ref_source (registry, active_id); +} + +/** + * e_source_combo_box_set_active: + * @combo_box: an #ESourceComboBox + * @source: an #ESource + * + * Sets the active item to the one corresponding to @source. + * + * Since: 2.22 + **/ +void +e_source_combo_box_set_active (ESourceComboBox *combo_box, + ESource *source) +{ + GtkComboBox *gtk_combo_box; + const gchar *uid; + + g_return_if_fail (E_IS_SOURCE_COMBO_BOX (combo_box)); + g_return_if_fail (E_IS_SOURCE (source)); + + uid = e_source_get_uid (source); + + gtk_combo_box = GTK_COMBO_BOX (combo_box); + gtk_combo_box_set_active_id (gtk_combo_box, uid); +} + |