From 0fb08f3ff81575a4749d851404233f34252dd2f2 Mon Sep 17 00:00:00 2001 From: Ettore Perazzoli Date: Tue, 21 Oct 2003 18:28:34 +0000 Subject: Merge new-ui-branch to the trunk. svn path=/trunk/; revision=22964 --- widgets/misc/ChangeLog | 50 +++ widgets/misc/Makefile.am | 14 + widgets/misc/e-source-selector.c | 682 ++++++++++++++++++++++++++++++++++++ widgets/misc/e-source-selector.h | 80 +++++ widgets/misc/test-source-selector.c | 131 +++++++ 5 files changed, 957 insertions(+) create mode 100644 widgets/misc/e-source-selector.c create mode 100644 widgets/misc/e-source-selector.h create mode 100644 widgets/misc/test-source-selector.c (limited to 'widgets') diff --git a/widgets/misc/ChangeLog b/widgets/misc/ChangeLog index ddf64a7889..fe4bcd24fa 100644 --- a/widgets/misc/ChangeLog +++ b/widgets/misc/ChangeLog @@ -4,6 +4,56 @@ * e-combo-cell-editable.* : new, GtkCellEditable for combo cells * Makefile.am : build the new files +2003-08-18 Ettore Perazzoli + + * e-source-selector.c (e_source_selector_selection_shown) + (e_source_selector_show_selection): Add precondition. + +2003-08-18 Ettore Perazzoli + + * test-source-selector.c (on_idle_create_widget): Add a + checkbutton to the test window for toggling the checkboxes on and + off. Also, put the list in a scrolled window and set a default + size for the main window. + (check_toggled_callback): Callback for the checkbutton. + + * e-source-selector.c: New member checkboxes_shown in struct + ESourceSelectorPrivate. + (init): Set to TRUE. + (e_source_selector_show_selection): New. + (e_source_selector_selection_shown): New. + (toggle_cell_data_func): Don't show the toggle if checkboxes_shown + is FALSE. + +2003-08-17 Ettore Perazzoli + + * e-source-selector.c: New signal "primary_selection_changed", + removed members list_changed_callback_id and + selection_changed_callback_id in ESourceSelectorPrivate. + (rebuild_model): If the new set of selected sources is smaller + than the old one, emit "selection_changed". + (e_source_selector_peek_primary_selection): New. + (e_source_selector_set_primary_selection): New. + (selection_changed_callback): New callback for the "changed" + signal on our associated GtkTreeSelection. + (init): Connect. + (impl_dispose): Disconnect. + (setup_model): Use signal_connect_object() instead of saving the + ID. + +2003-08-15 Ettore Perazzoli + + * e-source-selector.c (cell_toggled_callback): Call + gtk_tree_model_row_changed() to let the model know that we changed + the data. + +2003-08-15 Ettore Perazzoli + + * test-source-selector.c: New test program. + + * e-source-selector.c: New file. + * e-source-selector.h: New file. + 2003-07-23 Dan Winship * Makefile.am: use EVO_MARSHAL_RULE diff --git a/widgets/misc/Makefile.am b/widgets/misc/Makefile.am index 7efeebb86f..f4d2cac974 100644 --- a/widgets/misc/Makefile.am +++ b/widgets/misc/Makefile.am @@ -31,6 +31,7 @@ widgetsinclude_HEADERS = \ e-map.h \ e-multi-config-dialog.h \ e-search-bar.h \ + e-source-selector.h \ e-title-bar.h \ e-url-entry.h @@ -51,6 +52,7 @@ libemiscwidgets_la_SOURCES = \ e-map.c \ e-multi-config-dialog.c \ e-search-bar.c \ + e-source-selector.c \ e-title-bar.c \ e-url-entry.c \ e-util-marshal.c @@ -72,6 +74,7 @@ noinst_PROGRAMS = \ test-dateedit \ test-dropdown-button \ test-multi-config-dialog \ + test-source-selector \ test-title-bar # test-calendar @@ -122,6 +125,17 @@ test_title_bar_LDADD = \ $(GNOME_FULL_LIBS) +# test-source-list-selector + +test_source_selector_SOURCES = \ + test-source-selector.c + +test_source_selector_LDADD = \ + ../../e-util/libeutil.la \ + ./libemiscwidgets.la \ + $(GNOME_FULL_LIBS) + + BUILT_SOURCES = $(MARSHAL_GENERATED) CLEANFILES = $(BUILT_SOURCES) diff --git a/widgets/misc/e-source-selector.c b/widgets/misc/e-source-selector.c new file mode 100644 index 0000000000..5bc12bcd39 --- /dev/null +++ b/widgets/misc/e-source-selector.c @@ -0,0 +1,682 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-source-selector.c + * + * Copyright (C) 2003 Ximian, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * 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 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. + * + * Author: Ettore Perazzoli + */ + +#include + +#include "e-source-selector.h" + +#include "e-util-marshal.h" + +#include + +#include +#include +#include +#include + + +#define PARENT_TYPE gtk_tree_view_get_type () +static GtkTreeViewClass *parent_class = NULL; + + +struct _ESourceSelectorPrivate { + ESourceList *list; + + GtkTreeStore *tree_store; + + GHashTable *selected_sources; + + int rebuild_model_idle_id; + + gboolean checkboxes_shown; +}; + + +enum { + SELECTION_CHANGED, + PRIMARY_SELECTION_CHANGED, + NUM_SIGNALS +}; +static unsigned int signals[NUM_SIGNALS] = { 0 }; + + +/* Selection management. */ + +static GHashTable * +create_selected_sources_hash (void) +{ + return g_hash_table_new_full (g_direct_hash, g_direct_equal, + (GDestroyNotify) g_object_unref, NULL); +} + +static gboolean +source_is_selected (ESourceSelector *selector, + ESource *source) +{ + if (g_hash_table_lookup (selector->priv->selected_sources, source) == NULL) + return FALSE; + else + return TRUE; +} + +static void +select_source (ESourceSelector *selector, + ESource *source) +{ + if (g_hash_table_lookup (selector->priv->selected_sources, source) != NULL) + return; + + g_hash_table_insert (selector->priv->selected_sources, source, source); + g_object_ref (source); +} + +static void +unselect_source (ESourceSelector *selector, + ESource *source) +{ + if (g_hash_table_lookup (selector->priv->selected_sources, source) == NULL) + return; + + /* (This will unref the source.) */ + g_hash_table_remove (selector->priv->selected_sources, source); +} + + +/* Setting up the model. */ + +static void +rebuild_model (ESourceSelector *selector) +{ + GtkTreeStore *tree_store; + GtkTreeIter iter; + GSList *groups, *p; + GHashTable *new_selected_sources; + + new_selected_sources = create_selected_sources_hash (); + + tree_store = selector->priv->tree_store; + gtk_tree_store_clear (GTK_TREE_STORE (tree_store)); + + groups = e_source_list_peek_groups (selector->priv->list); + for (p = groups; p != NULL; p = p->next) { + ESourceGroup *group = E_SOURCE_GROUP (p->data); + GSList *sources, *q; + + gtk_tree_store_append (GTK_TREE_STORE (tree_store), &iter, NULL); + gtk_tree_store_set (GTK_TREE_STORE (tree_store), &iter, 0, group, -1); + + sources = e_source_group_peek_sources (group); + for (q = sources; q != NULL; q = q->next) { + ESource *source = E_SOURCE (q->data); + GtkTreeIter child_iter; + + gtk_tree_store_append (GTK_TREE_STORE (tree_store), &child_iter, &iter); + gtk_tree_store_set (GTK_TREE_STORE (tree_store), &child_iter, 0, source, -1); + + if (g_hash_table_lookup (selector->priv->selected_sources, source) != NULL) { + g_hash_table_insert (new_selected_sources, source, source); + g_object_ref (source); + } + } + } + + /* Since new_selected_sources is a subset of selected_sources, we can tell whether the overall + selection has changed just by comparing the sizes of the hash tables. */ + if (g_hash_table_size (selector->priv->selected_sources) != g_hash_table_size (new_selected_sources)) + g_signal_emit (selector, signals[SELECTION_CHANGED], 0); + + g_hash_table_destroy (selector->priv->selected_sources); + selector->priv->selected_sources = new_selected_sources; +} + +static int +on_idle_rebuild_model_callback (ESourceSelector *selector) +{ + rebuild_model (selector); + selector->priv->rebuild_model_idle_id = 0; + + return FALSE; +} + +static void +list_changed_callback (ESourceList *list, + ESourceSelector *selector) +{ + ESourceSelectorPrivate *priv = selector->priv; + + if (priv->rebuild_model_idle_id == 0) + priv->rebuild_model_idle_id = g_idle_add ((GSourceFunc) on_idle_rebuild_model_callback, + selector); +} + +static void +setup_model (ESourceSelector *selector) +{ + rebuild_model (selector); + + g_signal_connect_object (selector->priv->list, "changed", G_CALLBACK (list_changed_callback), G_OBJECT (selector), 0); +} + + +/* Data functions for rendering the model. */ + +static void +toggle_cell_data_func (GtkTreeViewColumn *column, + GtkCellRenderer *renderer, + GtkTreeModel *model, + GtkTreeIter *iter, + ESourceSelector *selector) +{ + void *data; + + gtk_tree_model_get (model, iter, 0, &data, -1); + + if (E_IS_SOURCE_GROUP (data)) { + g_object_set (renderer, "visible", FALSE, NULL); + } else { + g_assert (E_IS_SOURCE (data)); + + g_object_set (renderer, "visible", selector->priv->checkboxes_shown, NULL); + if (source_is_selected (selector, E_SOURCE (data))) + g_object_set (renderer, "active", TRUE, NULL); + else + g_object_set (renderer, "active", FALSE, NULL); + } +} + +static void +text_cell_data_func (GtkTreeViewColumn *column, + GtkCellRenderer *renderer, + GtkTreeModel *model, + GtkTreeIter *iter, + ESourceSelector *selector) +{ + void *data; + + gtk_tree_model_get (model, iter, 0, &data, -1); + + if (E_IS_SOURCE_GROUP (data)) { + g_object_set (renderer, + "text", e_source_group_peek_name (E_SOURCE_GROUP (data)), + "weight", PANGO_WEIGHT_BOLD, + "foreground_set", FALSE, + NULL); + } else { + ESource *source; + guint32 color; + gboolean has_color; + + g_assert (E_IS_SOURCE (data)); + source = E_SOURCE (data); + + g_object_set (renderer, + "text", e_source_peek_name (source), + "weight", PANGO_WEIGHT_NORMAL, + NULL); + + has_color = e_source_get_color (source, &color); + if (!has_color) { + g_object_set (renderer, + "foreground_set", FALSE, + NULL); + } else { + char *color_string = g_strdup_printf ("#%06x", color); + g_object_set (renderer, + "foreground_set", TRUE, + "foreground", color_string, + NULL); + g_free (color_string); + } + } +} + +/* Custom selection function to make groups non selectable. */ +static gboolean +selection_func (GtkTreeSelection *selection, + GtkTreeModel *model, + GtkTreePath *path, + gboolean path_currently_selected, + ESourceSelector *selector) +{ + GtkTreeIter iter; + void *data; + + if (! gtk_tree_model_get_iter (model, &iter, path)) + return FALSE; + + gtk_tree_model_get (model, &iter, 0, &data, -1); + if (E_IS_SOURCE_GROUP (data)) + return FALSE; + else + return TRUE; +} + + +/* Callbacks. */ + +static void +cell_toggled_callback (GtkCellRendererToggle *renderer, + const char *path_string, + ESourceSelector *selector) +{ + GtkTreeModel *model = GTK_TREE_MODEL (selector->priv->tree_store); + GtkTreePath *path = gtk_tree_path_new_from_string (path_string); + GtkTreeIter iter; + ESource *source; + void *data; + + if (! gtk_tree_model_get_iter (model, &iter, path)) { + gtk_tree_path_free (path); + return; + } + + gtk_tree_model_get (model, &iter, 0, &data, -1); + if (! E_IS_SOURCE (data)) { + gtk_tree_path_free (path); + return; + } + + source = E_SOURCE (data); + if (source_is_selected (selector, source)) + unselect_source (selector, source); + else + select_source (selector, source); + + gtk_tree_model_row_changed (model, path, &iter); + g_signal_emit (selector, signals[SELECTION_CHANGED], 0); + + gtk_tree_path_free (path); +} + +static void +selection_changed_callback (GtkTreeSelection *selection, + ESourceSelector *selector) +{ + g_signal_emit (selector, signals[PRIMARY_SELECTION_CHANGED], 0); +} + + +/* GObject methods. */ + +static void +impl_dispose (GObject *object) +{ + ESourceSelectorPrivate *priv = E_SOURCE_SELECTOR (object)->priv; + + if (priv->selected_sources != NULL) { + g_hash_table_destroy (priv->selected_sources); + priv->selected_sources = NULL; + } + + if (priv->rebuild_model_idle_id != 0) { + g_source_remove (priv->rebuild_model_idle_id); + priv->rebuild_model_idle_id = 0; + } + + if (priv->list != NULL) { + g_object_unref (priv->list); + priv->list = NULL; + } + + if (priv->tree_store != NULL) { + g_object_unref (priv->tree_store); + priv->tree_store = NULL; + } + + (* G_OBJECT_CLASS (parent_class)->dispose) (object); +} + +static void +impl_finalize (GObject *object) +{ + ESourceSelectorPrivate *priv = E_SOURCE_SELECTOR (object)->priv; + + g_free (priv); + + (* G_OBJECT_CLASS (parent_class)->finalize) (object); +} + + +/* Initialization. */ + +static void +class_init (ESourceSelectorClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + object_class->dispose = impl_dispose; + object_class->finalize = impl_finalize; + + parent_class = g_type_class_peek_parent (class); + + signals[SELECTION_CHANGED] = + g_signal_new ("selection_changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ESourceSelectorClass, selection_changed), + NULL, NULL, + e_util_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[PRIMARY_SELECTION_CHANGED] = + g_signal_new ("primary_selection_changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ESourceSelectorClass, primary_selection_changed), + NULL, NULL, + e_util_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +init (ESourceSelector *selector) +{ + ESourceSelectorPrivate *priv; + GtkTreeViewColumn *column; + GtkCellRenderer *cell_renderer; + GtkTreeSelection *selection; + + priv = g_new0 (ESourceSelectorPrivate, 1); + selector->priv = priv; + + priv->checkboxes_shown = TRUE; + + priv->selected_sources = create_selected_sources_hash (); + + priv->tree_store = gtk_tree_store_new (1, G_TYPE_POINTER); + gtk_tree_view_set_model (GTK_TREE_VIEW (selector), GTK_TREE_MODEL (priv->tree_store)); + + column = gtk_tree_view_column_new (); + gtk_tree_view_append_column (GTK_TREE_VIEW (selector), column); + + cell_renderer = gtk_cell_renderer_toggle_new (); + gtk_tree_view_column_pack_start (column, cell_renderer, FALSE); + gtk_tree_view_column_set_cell_data_func (column, cell_renderer, (GtkTreeCellDataFunc) toggle_cell_data_func, selector, NULL); + g_signal_connect (cell_renderer, "toggled", G_CALLBACK (cell_toggled_callback), selector); + + cell_renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_column_pack_start (column, cell_renderer, TRUE); + gtk_tree_view_column_set_cell_data_func (column, cell_renderer, (GtkTreeCellDataFunc) text_cell_data_func, selector, NULL); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (selector)); + gtk_tree_selection_set_select_function (selection, (GtkTreeSelectionFunc) selection_func, selector, NULL); + g_signal_connect_object (selection, "changed", G_CALLBACK (selection_changed_callback), G_OBJECT (selector), 0); + + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (selector), FALSE); +} + + +/* Public API. */ + +/** + * e_source_selector_new: + * @list: A source list. + * + * Create a new view for @list. The view will update automatically when @list + * changes. + * + * Return value: The newly created widget. + **/ +GtkWidget * +e_source_selector_new (ESourceList *list) +{ + ESourceSelector *selector; + + g_return_val_if_fail (E_IS_SOURCE_LIST (list), NULL); + + selector = g_object_new (e_source_selector_get_type (), NULL); + + selector->priv->list = list; + g_object_ref (list); + + setup_model (selector); + + return GTK_WIDGET (selector); +} + + +/** + * e_source_selector_get_selection: + * @selector: + * + * Get the list of selected sources, i.e. those that were enabled through the + * corresponding checkboxes in the tree. + * + * Return value: A list of the ESources currently selected. The sources will + * be in the same order as they appear on the screen, and the list should be + * freed using e_source_selector_free_selection(). + **/ +GSList * +e_source_selector_get_selection (ESourceSelector *selector) +{ + GSList *selection_list; + GSList *groups; + GSList *p; + + g_return_val_if_fail (E_IS_SOURCE_SELECTOR (selector), NULL); + + selection_list = NULL; + + groups = e_source_list_peek_groups (selector->priv->list); + for (p = groups; p != NULL; p = p->next) { + ESourceGroup *group = E_SOURCE_GROUP (p->data); + GSList *sources; + GSList *q; + + sources = e_source_group_peek_sources (group); + for (q = sources; q != NULL; q = q->next) { + ESource *source = E_SOURCE (q->data); + + if (source_is_selected (selector, source)) { + selection_list = g_slist_prepend (selection_list, source); + g_object_ref (source); + } + } + } + + return g_slist_reverse (selection_list); +} + +/** + * e_source_list_free_selection: + * @list: A selection list returned by e_source_selector_get_selection(). + * + * Free the selection list. + **/ +void +e_source_selector_free_selection (GSList *list) +{ + g_slist_foreach (list, (GFunc) g_object_unref, NULL); + g_slist_free (list); +} + + +/** + * e_source_selector_show_selection: + * @selector: An ESourceSelector widget + * + * Specify whether the checkboxes in the ESourceSelector should be shown or + * not. + **/ +void +e_source_selector_show_selection (ESourceSelector *selector, + gboolean show) +{ + g_return_if_fail (E_IS_SOURCE_SELECTOR (selector)); + + show = !! show; + if (show == selector->priv->checkboxes_shown) + return; + + selector->priv->checkboxes_shown = show; + + gtk_tree_model_foreach (GTK_TREE_MODEL (selector->priv->tree_store), + (GtkTreeModelForeachFunc) gtk_tree_model_row_changed, + NULL); +} + +/** + * e_source_selector_selection_shown: + * @selector: + * + * Check whether the checkboxes in the ESourceSelector are being shown or not. + * + * Return value: %TRUE if the checkboxes are shown, %FALSE otherwise. + **/ +gboolean +e_source_selector_selection_shown (ESourceSelector *selector) +{ + g_return_if_fail (E_IS_SOURCE_SELECTOR (selector)); + + return selector->priv->checkboxes_shown; +} + +/** + * e_source_selector_select_source: + * @selector: An ESourceSelector widget + * @source: An ESource. + * + * Select @source in @selector. + **/ +void +e_source_selector_select_source (ESourceSelector *selector, + ESource *source) +{ + g_return_if_fail (E_IS_SOURCE_SELECTOR (selector)); + g_return_if_fail (E_IS_SOURCE (source)); + + if (source_is_selected (selector, source)) + return; + + select_source (selector, source); + g_signal_emit (selector, signals[SELECTION_CHANGED], 0); +} + +/** + * e_source_selector_unselect_source: + * @selector: An ESourceSelector widget + * @source: An ESource. + * + * Unselect @source in @selector. + **/ +void +e_source_selector_unselect_source (ESourceSelector *selector, + ESource *source) +{ + g_return_if_fail (E_IS_SOURCE_SELECTOR (selector)); + g_return_if_fail (E_IS_SOURCE (source)); + + if (! source_is_selected (selector, source)) + return; + + unselect_source (selector, source); + g_signal_emit (selector, signals[SELECTION_CHANGED], 0); +} + +/** + * e_source_selector_source_is_selected: + * @selector: An ESourceSelector widget + * @source: An ESource. + * + * Check whether @source is selected in @selector. + * + * Return value: %TRUE if @source is currently selected, %FALSE otherwise. + **/ +gboolean +e_source_selector_source_is_selected (ESourceSelector *selector, + ESource *source) +{ + g_return_val_if_fail (E_IS_SOURCE_SELECTOR (selector), FALSE); + g_return_val_if_fail (E_IS_SOURCE (source), FALSE); + + return source_is_selected (selector, source); +} + +/** + * e_source_selector_peek_primary_selection: + * @selector: An ESourceSelector widget + * + * Get the primary selected source. The primary selection is the one that is + * highlighted through the normal GtkTreeView selection mechanism (as opposed + * to the "normal" selection, which is the set of source whose checkboxes are + * checked). + * + * Return value: The selected source. + **/ +ESource * +e_source_selector_peek_primary_selection (ESourceSelector *selector) +{ + GtkTreeModel *model = GTK_TREE_MODEL (selector->priv->tree_store); + GtkTreeIter iter; + void *data; + + if (! gtk_tree_selection_get_selected (gtk_tree_view_get_selection (GTK_TREE_VIEW (selector)), NULL, &iter)) + return NULL; + + gtk_tree_model_get (model, &iter, 0, &data, -1); + if (! E_IS_SOURCE (data)) + return NULL; + + return E_SOURCE (data); +} + +/** + * e_source_selector_set_primary_selection: + * @selector: An ESourceSelector widget + * @source: Source to select + * + * Set the primary selected source. + **/ +void +e_source_selector_set_primary_selection (ESourceSelector *selector, + ESource *source) +{ + GtkTreeModel *model = GTK_TREE_MODEL (selector->priv->tree_store); + GtkTreeIter iter; + + if (gtk_tree_model_get_iter_first (model, &iter)) { + do { + GtkTreeIter children_iter; + + if (gtk_tree_model_iter_children (model, &children_iter, &iter)) { + do { + void *data; + + gtk_tree_model_get (model, &iter, 0, &data, -1); + g_assert (E_IS_SOURCE (data)); + + if (E_SOURCE (data) == source) { + GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (selection)); + gtk_tree_selection_select_iter (selection, &children_iter); + return; + } + } while (gtk_tree_model_iter_next (model, &iter)); + } + } while (gtk_tree_model_iter_next (model, &iter)); + } + + g_warning (G_GNUC_FUNCTION ": Cannot find source %p (%s) in selector %p", source, e_source_peek_name (source), selector); +} + + +E_MAKE_TYPE (e_source_selector, "ESourceSelector", ESourceSelector, class_init, init, PARENT_TYPE) diff --git a/widgets/misc/e-source-selector.h b/widgets/misc/e-source-selector.h new file mode 100644 index 0000000000..02b1356e08 --- /dev/null +++ b/widgets/misc/e-source-selector.h @@ -0,0 +1,80 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-source-selector.h + * + * Copyright (C) 2003 Ximian, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * 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 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. + * + * Author: Ettore Perazzoli + */ + +#ifndef _E_SOURCE_SELECTOR_H_ +#define _E_SOURCE_SELECTOR_H_ + +#include "e-util/e-source-list.h" + +#include + + +#define E_TYPE_SOURCE_SELECTOR (e_source_selector_get_type ()) +#define E_SOURCE_SELECTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_SOURCE_SELECTOR, ESourceSelector)) +#define E_SOURCE_SELECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_SOURCE_SELECTOR, ESourceSelectorClass)) +#define E_IS_SOURCE_SELECTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_SOURCE_SELECTOR)) +#define E_IS_SOURCE_SELECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_SOURCE_SELECTOR)) + + +typedef struct _ESourceSelector ESourceSelector; +typedef struct _ESourceSelectorPrivate ESourceSelectorPrivate; +typedef struct _ESourceSelectorClass ESourceSelectorClass; + +struct _ESourceSelector { + GtkTreeView parent; + + ESourceSelectorPrivate *priv; +}; + +struct _ESourceSelectorClass { + GtkTreeViewClass parent_class; + + void (* selection_changed) (ESourceSelector *selector); + void (* primary_selection_changed) (ESourceSelector *selector); +}; + + +GType e_source_selector_get_type (void); + +GtkWidget *e_source_selector_new (ESourceList *list); + +void e_source_selector_select_source (ESourceSelector *selector, + ESource *source); +void e_source_selector_unselect_source (ESourceSelector *selector, + ESource *source); +gboolean e_source_selector_source_is_selected (ESourceSelector *selector, + ESource *source); + +GSList *e_source_selector_get_selection (ESourceSelector *selector); +void e_source_selector_free_selection (GSList *list); + +void e_source_selector_show_selection (ESourceSelector *selector, + gboolean show); +gboolean e_source_selector_selection_shown (ESourceSelector *selector); + +ESource *e_source_selector_peek_primary_selection (ESourceSelector *selector); +void e_source_selector_set_primary_selection (ESourceSelector *selector, + ESource *source); + + +#endif /* _E_SOURCE_SELECTOR_H_ */ diff --git a/widgets/misc/test-source-selector.c b/widgets/misc/test-source-selector.c new file mode 100644 index 0000000000..3120f0c948 --- /dev/null +++ b/widgets/misc/test-source-selector.c @@ -0,0 +1,131 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* test-source-list-selector.c - Test program for the ESourceListSelector + * widget. + * + * Copyright (C) 2002 Ximian, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU 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 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. + * + * Author: Ettore Perazzoli + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "e-source-selector.h" + +#include +#include +#include +#include +#include + +#include + + +static void +dump_selection (ESourceSelector *selector) +{ + GSList *selection = e_source_selector_get_selection (selector); + + g_print ("Current selection:\n"); + if (selection == NULL) { + g_print ("\t(None)\n"); + } else { + GSList *p; + + for (p = selection; p != NULL; p = p->next) { + ESource *source = E_SOURCE (p->data); + + g_print ("\tSource %s (group %s)\n", + e_source_peek_name (source), + e_source_group_peek_name (e_source_peek_group (source))); + } + } + + e_source_selector_free_selection (selection); +} + +static void +selection_changed_callback (ESourceSelector *selector, + void *unused_data) +{ + g_print ("Selection changed!\n"); + dump_selection (selector); +} + +static void +check_toggled_callback (GtkToggleButton *button, + ESourceSelector *selector) +{ + e_source_selector_show_selection (selector, gtk_toggle_button_get_active (button)); +} + +static int +on_idle_create_widget (void *unused_data) +{ + GtkWidget *window; + GtkWidget *vbox; + GtkWidget *selector; + GtkWidget *scrolled_window; + GtkWidget *check; + ESourceList *list; + GConfClient *gconf_client; + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_default_size (GTK_WINDOW (window), 200, 300); + + vbox = gtk_vbox_new (FALSE, 3); + gtk_container_add (GTK_CONTAINER (window), vbox); + + gconf_client = gconf_client_get_default (); + list = e_source_list_new_for_gconf (gconf_client, "/apps/evolution/test/source_list"); + selector = e_source_selector_new (list); + g_signal_connect (selector, "selection_changed", G_CALLBACK (selection_changed_callback), NULL); + + scrolled_window = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_IN); + gtk_container_add (GTK_CONTAINER (scrolled_window), selector); + gtk_box_pack_start (GTK_BOX (vbox), scrolled_window, TRUE, TRUE, 3); + + check = gtk_check_button_new_with_label ("Show checkboxes"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), + e_source_selector_selection_shown (E_SOURCE_SELECTOR (selector))); + g_signal_connect (check, "toggled", G_CALLBACK (check_toggled_callback), selector); + gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, TRUE, 3); + + gtk_widget_show_all (window); + + g_object_unref (gconf_client); + return FALSE; +} + + +int +main (int argc, char **argv) +{ + GnomeProgram *program; + + program = gnome_program_init ("test-source-list", "0.0", + LIBGNOMEUI_MODULE, argc, argv, + NULL); + + g_idle_add (on_idle_create_widget, NULL); + gtk_main (); + + return 0; +} -- cgit