From d09d8de870b6697c8a8b262e7e077b871a69b315 Mon Sep 17 00:00:00 2001 From: Matthew Barnes Date: Mon, 10 Dec 2012 08:09:59 -0500 Subject: 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. --- e-util/e-categories-editor.c | 435 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 435 insertions(+) create mode 100644 e-util/e-categories-editor.c (limited to 'e-util/e-categories-editor.c') diff --git a/e-util/e-categories-editor.c b/e-util/e-categories-editor.c new file mode 100644 index 0000000000..ecbebf6083 --- /dev/null +++ b/e-util/e-categories-editor.c @@ -0,0 +1,435 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + * This library 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 library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include + +#include + +#include "e-categories-editor.h" +#include "e-categories-selector.h" +#include "e-category-completion.h" +#include "e-category-editor.h" + +#define E_CATEGORIES_EDITOR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_CATEGORIES_EDITOR, ECategoriesEditorPrivate)) + +struct _ECategoriesEditorPrivate { + ECategoriesSelector *categories_list; + GtkWidget *categories_entry; + GtkWidget *categories_entry_label; + GtkWidget *new_button; + GtkWidget *edit_button; + GtkWidget *delete_button; + + guint ignore_category_changes : 1; +}; + +enum { + COLUMN_ACTIVE, + COLUMN_ICON, + COLUMN_CATEGORY, + N_COLUMNS +}; + +enum { + PROP_0, + PROP_ENTRY_VISIBLE +}; + +enum { + ENTRY_CHANGED, + LAST_SIGNAL +}; + +static gint signals[LAST_SIGNAL] = {0}; + +G_DEFINE_TYPE (ECategoriesEditor, e_categories_editor, GTK_TYPE_GRID) + +static void +entry_changed_cb (GtkEntry *entry, + ECategoriesEditor *editor) +{ + g_signal_emit (editor, signals[ENTRY_CHANGED], 0); +} + +static void +categories_editor_selection_changed_cb (ECategoriesEditor *editor, + GtkTreeSelection *selection) +{ + GtkWidget *widget; + gint n_rows; + + n_rows = gtk_tree_selection_count_selected_rows (selection); + + widget = editor->priv->edit_button; + gtk_widget_set_sensitive (widget, n_rows == 1); + + widget = editor->priv->delete_button; + gtk_widget_set_sensitive (widget, n_rows >= 1); +} + +static void +category_checked_cb (ECategoriesSelector *selector, + const gchar *category, + const gboolean checked, + ECategoriesEditor *editor) +{ + GtkEntry *entry; + gchar *categories; + + entry = GTK_ENTRY (editor->priv->categories_entry); + categories = e_categories_selector_get_checked (selector); + + gtk_entry_set_text (entry, categories); + + g_free (categories); +} + +static void +new_button_clicked_cb (GtkButton *button, + ECategoriesEditor *editor) +{ + ECategoryEditor *cat_editor = e_category_editor_new (); + + e_category_editor_create_category (cat_editor); + + gtk_widget_destroy (GTK_WIDGET (cat_editor)); +} + +static void +edit_button_clicked_cb (GtkButton *button, + ECategoriesEditor *editor) +{ + ECategoryEditor *cat_editor = e_category_editor_new (); + gchar *category; + + category = e_categories_selector_get_selected ( + editor->priv->categories_list); + + e_category_editor_edit_category (cat_editor, category); + + gtk_widget_destroy (GTK_WIDGET (cat_editor)); + g_free (category); +} + +static void +categories_editor_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ENTRY_VISIBLE: + e_categories_editor_set_entry_visible ( + E_CATEGORIES_EDITOR (object), + g_value_get_boolean (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +categories_editor_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ENTRY_VISIBLE: + g_value_set_boolean ( + value, e_categories_editor_get_entry_visible ( + E_CATEGORIES_EDITOR (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +e_categories_editor_class_init (ECategoriesEditorClass *class) +{ + GObjectClass *object_class; + + g_type_class_add_private (class, sizeof (ECategoriesEditorPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = categories_editor_set_property; + object_class->get_property = categories_editor_get_property; + + g_object_class_install_property ( + object_class, + PROP_ENTRY_VISIBLE, + g_param_spec_boolean ( + "entry-visible", + NULL, + NULL, + TRUE, + G_PARAM_READWRITE)); + + signals[ENTRY_CHANGED] = g_signal_new ( + "entry-changed", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (ECategoriesEditorClass, entry_changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +e_categories_editor_init (ECategoriesEditor *editor) +{ + GtkEntryCompletion *completion; + GtkGrid *grid; + GtkWidget *entry_categories; + GtkWidget *label_header; + GtkWidget *label2; + GtkWidget *scrolledwindow1; + GtkWidget *categories_list; + GtkWidget *hbuttonbox1; + GtkWidget *button_new; + GtkWidget *button_edit; + GtkWidget *button_delete; + + gtk_widget_set_size_request (GTK_WIDGET (editor), -1, 400); + + grid = GTK_GRID (editor); + + gtk_grid_set_row_spacing (grid, 6); + gtk_grid_set_column_spacing (grid, 6); + + label_header = gtk_label_new_with_mnemonic ( + _("Currently _used categories:")); + gtk_widget_set_halign (label_header, GTK_ALIGN_FILL); + gtk_grid_attach (grid, label_header, 0, 0, 1, 1); + gtk_label_set_justify (GTK_LABEL (label_header), GTK_JUSTIFY_CENTER); + gtk_misc_set_alignment (GTK_MISC (label_header), 0, 0.5); + + entry_categories = gtk_entry_new (); + gtk_widget_set_hexpand (entry_categories, TRUE); + gtk_widget_set_halign (entry_categories, GTK_ALIGN_FILL); + gtk_grid_attach (grid, entry_categories, 0, 1, 1, 1); + + label2 = gtk_label_new_with_mnemonic (_("_Available Categories:")); + gtk_widget_set_halign (label2, GTK_ALIGN_FILL); + gtk_grid_attach (grid, label2, 0, 2, 1, 1); + gtk_label_set_justify (GTK_LABEL (label2), GTK_JUSTIFY_CENTER); + gtk_misc_set_alignment (GTK_MISC (label2), 0, 0.5); + + scrolledwindow1 = gtk_scrolled_window_new (NULL, NULL); + g_object_set (G_OBJECT (scrolledwindow1), + "hexpand", TRUE, + "halign", GTK_ALIGN_FILL, + "vexpand", TRUE, + "valign", GTK_ALIGN_FILL, + NULL); + gtk_grid_attach (grid, scrolledwindow1, 0, 3, 1, 1); + gtk_scrolled_window_set_policy ( + GTK_SCROLLED_WINDOW (scrolledwindow1), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type ( + GTK_SCROLLED_WINDOW (scrolledwindow1), GTK_SHADOW_IN); + + categories_list = GTK_WIDGET (e_categories_selector_new ()); + gtk_container_add (GTK_CONTAINER (scrolledwindow1), categories_list); + gtk_widget_set_size_request (categories_list, -1, 350); + gtk_tree_view_set_headers_visible ( + GTK_TREE_VIEW (categories_list), FALSE); + gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (categories_list), TRUE); + g_signal_connect ( + G_OBJECT (categories_list), "category-checked", + G_CALLBACK (category_checked_cb), editor); + + hbuttonbox1 = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL); + g_object_set (G_OBJECT (hbuttonbox1), + "hexpand", TRUE, + "halign", GTK_ALIGN_FILL, + NULL); + gtk_grid_attach (grid, hbuttonbox1, 0, 4, 1, 1); + gtk_box_set_spacing (GTK_BOX (hbuttonbox1), 6); + + button_new = gtk_button_new_from_stock (GTK_STOCK_NEW); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), button_new); + gtk_widget_set_can_default (button_new, TRUE); + + button_edit = gtk_button_new_from_stock (GTK_STOCK_EDIT); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), button_edit); + gtk_widget_set_can_default (button_edit, TRUE); + + button_delete = gtk_button_new_from_stock (GTK_STOCK_DELETE); + gtk_container_add (GTK_CONTAINER (hbuttonbox1), button_delete); + gtk_widget_set_can_default (button_delete, TRUE); + + gtk_label_set_mnemonic_widget ( + GTK_LABEL (label_header), entry_categories); + gtk_label_set_mnemonic_widget ( + GTK_LABEL (label2), categories_list); + + editor->priv = E_CATEGORIES_EDITOR_GET_PRIVATE (editor); + + editor->priv->categories_list = E_CATEGORIES_SELECTOR (categories_list); + editor->priv->categories_entry = entry_categories; + editor->priv->categories_entry_label = label_header; + + g_signal_connect_swapped ( + editor->priv->categories_list, "selection-changed", + G_CALLBACK (categories_editor_selection_changed_cb), editor); + + completion = e_category_completion_new (); + gtk_entry_set_completion ( + GTK_ENTRY (editor->priv->categories_entry), completion); + g_object_unref (completion); + + editor->priv->new_button = button_new; + g_signal_connect ( + editor->priv->new_button, "clicked", + G_CALLBACK (new_button_clicked_cb), editor); + + editor->priv->edit_button = button_edit; + g_signal_connect ( + editor->priv->edit_button, "clicked", + G_CALLBACK (edit_button_clicked_cb), editor); + + editor->priv->delete_button = button_delete; + g_signal_connect_swapped ( + editor->priv->delete_button, "clicked", + G_CALLBACK (e_categories_selector_delete_selection), + editor->priv->categories_list); + + g_signal_connect ( + editor->priv->categories_entry, "changed", + G_CALLBACK (entry_changed_cb), editor); + + gtk_widget_show_all (GTK_WIDGET (editor)); +} + +/** + * e_categories_editor_new: + * + * Creates a new #ECategoriesEditor widget. + * + * Returns: a new #ECategoriesEditor + * + * Since: 3.2 + **/ +GtkWidget * +e_categories_editor_new (void) +{ + return g_object_new (E_TYPE_CATEGORIES_EDITOR, NULL); +} + +/** + * e_categories_editor_get_categories: + * @editor: an #ECategoriesEditor + * + * Gets a comma-separated list of the categories currently selected + * in the editor. + * + * Returns: a comma-separated list of categories. Free returned + * pointer with g_free(). + * + * Since: 3.2 + **/ +gchar * +e_categories_editor_get_categories (ECategoriesEditor *editor) +{ + ECategoriesSelector *categories_list; + + g_return_val_if_fail (E_IS_CATEGORIES_EDITOR (editor), NULL); + + categories_list = editor->priv->categories_list; + + return e_categories_selector_get_checked (categories_list); +} + +/** + * e_categories_editor_set_categories: + * @editor: an #ECategoriesEditor + * @categories: comma-separated list of categories + * + * Sets the list of categories selected on the editor. + * + * Since: 3.2 + **/ +void +e_categories_editor_set_categories (ECategoriesEditor *editor, + const gchar *categories) +{ + ECategoriesSelector *categories_list; + + g_return_if_fail (E_IS_CATEGORIES_EDITOR (editor)); + + categories_list = editor->priv->categories_list; + + e_categories_selector_set_checked (categories_list, categories); + category_checked_cb (categories_list, NULL, FALSE, editor); +} + +/** + * e_categories_editor_get_entry_visible: + * @editor: an #ECategoriesEditor + * + * Return the visibility of the category input entry. + * + * Returns: whether the entry is visible + * + * Since: 3.2 + **/ +gboolean +e_categories_editor_get_entry_visible (ECategoriesEditor *editor) +{ + g_return_val_if_fail (E_IS_CATEGORIES_EDITOR (editor), TRUE); + + return gtk_widget_get_visible (editor->priv->categories_entry); +} + +/** + * e_categories_editor_set_entry_visible: + * @editor: an #ECategoriesEditor + * @entry_visible: whether to make the entry visible + * + * Sets the visibility of the category input entry. + * + * Since: 3.2 + **/ +void +e_categories_editor_set_entry_visible (ECategoriesEditor *editor, + gboolean entry_visible) +{ + g_return_if_fail (E_IS_CATEGORIES_EDITOR (editor)); + + if ((gtk_widget_get_visible (editor->priv->categories_entry) ? 1 : 0) == + (entry_visible ? 1 : 0)) + return; + + gtk_widget_set_visible ( + editor->priv->categories_entry, entry_visible); + gtk_widget_set_visible ( + editor->priv->categories_entry_label, entry_visible); + e_categories_selector_set_items_checkable ( + editor->priv->categories_list, entry_visible); + + g_object_notify (G_OBJECT (editor), "entry-visible"); +} -- cgit