diff options
Diffstat (limited to 'e-util/e-table-sort-info.c')
-rw-r--r-- | e-util/e-table-sort-info.c | 482 |
1 files changed, 482 insertions, 0 deletions
diff --git a/e-util/e-table-sort-info.c b/e-util/e-table-sort-info.c new file mode 100644 index 0000000000..d2654c55b4 --- /dev/null +++ b/e-util/e-table-sort-info.c @@ -0,0 +1,482 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) version 3. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the program; if not, see <http://www.gnu.org/licenses/> + * + * + * Authors: + * Chris Lahey <clahey@ximian.com> + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "e-table-sort-info.h" + +#include <string.h> + +#include "e-xml-utils.h" + +#define ETM_CLASS(e) (E_TABLE_SORT_INFO_GET_CLASS (e)) + +G_DEFINE_TYPE (ETableSortInfo , e_table_sort_info, G_TYPE_OBJECT) + +enum { + SORT_INFO_CHANGED, + GROUP_INFO_CHANGED, + LAST_SIGNAL +}; + +static guint e_table_sort_info_signals[LAST_SIGNAL] = { 0, }; + +static void +etsi_finalize (GObject *object) +{ + ETableSortInfo *etsi = E_TABLE_SORT_INFO (object); + + if (etsi->groupings) + g_free (etsi->groupings); + etsi->groupings = NULL; + + if (etsi->sortings) + g_free (etsi->sortings); + etsi->sortings = NULL; + + G_OBJECT_CLASS (e_table_sort_info_parent_class)->finalize (object); +} + +static void +e_table_sort_info_init (ETableSortInfo *info) +{ + info->group_count = 0; + info->groupings = NULL; + info->sort_count = 0; + info->sortings = NULL; + info->frozen = 0; + info->sort_info_changed = 0; + info->group_info_changed = 0; + info->can_group = 1; +} + +static void +e_table_sort_info_class_init (ETableSortInfoClass *class) +{ + GObjectClass * object_class = G_OBJECT_CLASS (class); + + object_class->finalize = etsi_finalize; + + e_table_sort_info_signals[SORT_INFO_CHANGED] = g_signal_new ( + "sort_info_changed", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ETableSortInfoClass, sort_info_changed), + (GSignalAccumulator) NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + e_table_sort_info_signals[GROUP_INFO_CHANGED] = g_signal_new ( + "group_info_changed", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ETableSortInfoClass, group_info_changed), + (GSignalAccumulator) NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + class->sort_info_changed = NULL; + class->group_info_changed = NULL; +} + +static void +e_table_sort_info_sort_info_changed (ETableSortInfo *info) +{ + g_return_if_fail (info != NULL); + g_return_if_fail (E_IS_TABLE_SORT_INFO (info)); + + if (info->frozen) { + info->sort_info_changed = 1; + } else { + g_signal_emit (info, e_table_sort_info_signals[SORT_INFO_CHANGED], 0); + } +} + +static void +e_table_sort_info_group_info_changed (ETableSortInfo *info) +{ + g_return_if_fail (info != NULL); + g_return_if_fail (E_IS_TABLE_SORT_INFO (info)); + + if (info->frozen) { + info->group_info_changed = 1; + } else { + g_signal_emit (info, e_table_sort_info_signals[GROUP_INFO_CHANGED], 0); + } +} + +/** + * e_table_sort_info_freeze: + * @info: The ETableSortInfo object + * + * This functions allows the programmer to cluster various changes to the + * ETableSortInfo (grouping and sorting) without having the object emit + * "group_info_changed" or "sort_info_changed" signals on each change. + * + * To thaw, invoke the e_table_sort_info_thaw() function, which will + * trigger any signals that might have been queued. + */ +void +e_table_sort_info_freeze (ETableSortInfo *info) +{ + info->frozen++; +} + +/** + * e_table_sort_info_thaw: + * @info: The ETableSortInfo object + * + * This functions allows the programmer to cluster various changes to the + * ETableSortInfo (grouping and sorting) without having the object emit + * "group_info_changed" or "sort_info_changed" signals on each change. + * + * This function will flush any pending signals that might be emited by + * this object. + */ +void +e_table_sort_info_thaw (ETableSortInfo *info) +{ + info->frozen--; + if (info->frozen != 0) + return; + + if (info->sort_info_changed) { + info->sort_info_changed = 0; + e_table_sort_info_sort_info_changed (info); + } + if (info->group_info_changed) { + info->group_info_changed = 0; + e_table_sort_info_group_info_changed (info); + } +} + +/** + * e_table_sort_info_grouping_get_count: + * @info: The ETableSortInfo object + * + * Returns: the number of grouping criteria in the object. + */ +guint +e_table_sort_info_grouping_get_count (ETableSortInfo *info) +{ + if (info->can_group) + return info->group_count; + else + return 0; +} + +static void +e_table_sort_info_grouping_real_truncate (ETableSortInfo *info, + gint length) +{ + if (length < info->group_count) { + info->group_count = length; + } + if (length > info->group_count) { + info->groupings = g_realloc (info->groupings, length * sizeof (ETableSortColumn)); + info->group_count = length; + } +} + +/** + * e_table_sort_info_grouping_truncate: + * @info: The ETableSortInfo object + * @lenght: position where the truncation happens. + * + * This routine can be used to reduce or grow the number of grouping + * criteria in the object. + */ +void +e_table_sort_info_grouping_truncate (ETableSortInfo *info, + gint length) +{ + e_table_sort_info_grouping_real_truncate (info, length); + e_table_sort_info_group_info_changed (info); +} + +/** + * e_table_sort_info_grouping_get_nth: + * @info: The ETableSortInfo object + * @n: Item information to fetch. + * + * Returns: the description of the @n-th grouping criteria in the @info object. + */ +ETableSortColumn +e_table_sort_info_grouping_get_nth (ETableSortInfo *info, + gint n) +{ + if (info->can_group && n < info->group_count) { + return info->groupings[n]; + } else { + ETableSortColumn fake = {0, 0}; + return fake; + } +} + +/** + * e_table_sort_info_grouping_set_nth: + * @info: The ETableSortInfo object + * @n: Item information to fetch. + * @column: new values for the grouping + * + * Sets the grouping criteria for index @n to be given by @column (a column number and + * whether it is ascending or descending). + */ +void +e_table_sort_info_grouping_set_nth (ETableSortInfo *info, + gint n, + ETableSortColumn column) +{ + if (n >= info->group_count) { + e_table_sort_info_grouping_real_truncate (info, n + 1); + } + info->groupings[n] = column; + e_table_sort_info_group_info_changed (info); +} + +/** + * e_table_sort_info_get_count: + * @info: The ETableSortInfo object + * + * Returns: the number of sorting criteria in the object. + */ +guint +e_table_sort_info_sorting_get_count (ETableSortInfo *info) +{ + return info->sort_count; +} + +static void +e_table_sort_info_sorting_real_truncate (ETableSortInfo *info, + gint length) +{ + if (length < info->sort_count) { + info->sort_count = length; + } + if (length > info->sort_count) { + info->sortings = g_realloc (info->sortings, length * sizeof (ETableSortColumn)); + info->sort_count = length; + } +} + +/** + * e_table_sort_info_sorting_truncate: + * @info: The ETableSortInfo object + * @lenght: position where the truncation happens. + * + * This routine can be used to reduce or grow the number of sort + * criteria in the object. + */ +void +e_table_sort_info_sorting_truncate (ETableSortInfo *info, + gint length) +{ + e_table_sort_info_sorting_real_truncate (info, length); + e_table_sort_info_sort_info_changed (info); +} + +/** + * e_table_sort_info_sorting_get_nth: + * @info: The ETableSortInfo object + * @n: Item information to fetch. + * + * Returns: the description of the @n-th grouping criteria in the @info object. + */ +ETableSortColumn +e_table_sort_info_sorting_get_nth (ETableSortInfo *info, + gint n) +{ + if (n < info->sort_count) { + return info->sortings[n]; + } else { + ETableSortColumn fake = {0, 0}; + return fake; + } +} + +/** + * e_table_sort_info_sorting_get_nth: + * @info: The ETableSortInfo object + * @n: Item information to fetch. + * @column: new values for the sorting + * + * Sets the sorting criteria for index @n to be given by @column (a + * column number and whether it is ascending or descending). + */ +void +e_table_sort_info_sorting_set_nth (ETableSortInfo *info, + gint n, + ETableSortColumn column) +{ + if (n >= info->sort_count) { + e_table_sort_info_sorting_real_truncate (info, n + 1); + } + info->sortings[n] = column; + e_table_sort_info_sort_info_changed (info); +} + +/** + * e_table_sort_info_new: + * + * This creates a new e_table_sort_info object that contains no + * grouping and no sorting defined as of yet. This object is used + * to keep track of multi-level sorting and multi-level grouping of + * the ETable. + * + * Returns: A new %ETableSortInfo object + */ +ETableSortInfo * +e_table_sort_info_new (void) +{ + return g_object_new (E_TYPE_TABLE_SORT_INFO, NULL); +} + +/** + * e_table_sort_info_load_from_node: + * @info: The ETableSortInfo object + * @node: pointer to the xmlNode that describes the sorting and grouping information + * @state_version: + * + * This loads the state for the %ETableSortInfo object @info from the + * xml node @node. + */ +void +e_table_sort_info_load_from_node (ETableSortInfo *info, + xmlNode *node, + gdouble state_version) +{ + gint i; + xmlNode *grouping; + + if (state_version <= 0.05) { + i = 0; + for (grouping = node->xmlChildrenNode; grouping && !strcmp ((gchar *) grouping->name, "group"); grouping = grouping->xmlChildrenNode) { + ETableSortColumn column; + column.column = e_xml_get_integer_prop_by_name (grouping, (const guchar *)"column"); + column.ascending = e_xml_get_bool_prop_by_name (grouping, (const guchar *)"ascending"); + e_table_sort_info_grouping_set_nth (info, i++, column); + } + i = 0; + for (; grouping && !strcmp ((gchar *) grouping->name, "leaf"); grouping = grouping->xmlChildrenNode) { + ETableSortColumn column; + column.column = e_xml_get_integer_prop_by_name (grouping, (const guchar *)"column"); + column.ascending = e_xml_get_bool_prop_by_name (grouping, (const guchar *)"ascending"); + e_table_sort_info_sorting_set_nth (info, i++, column); + } + } else { + gint gcnt = 0; + gint scnt = 0; + for (grouping = node->children; grouping; grouping = grouping->next) { + ETableSortColumn column; + + if (grouping->type != XML_ELEMENT_NODE) + continue; + + if (!strcmp ((gchar *) grouping->name, "group")) { + column.column = e_xml_get_integer_prop_by_name (grouping, (const guchar *)"column"); + column.ascending = e_xml_get_bool_prop_by_name (grouping, (const guchar *)"ascending"); + e_table_sort_info_grouping_set_nth (info, gcnt++, column); + } else if (!strcmp ((gchar *) grouping->name, "leaf")) { + column.column = e_xml_get_integer_prop_by_name (grouping, (const guchar *)"column"); + column.ascending = e_xml_get_bool_prop_by_name (grouping, (const guchar *)"ascending"); + e_table_sort_info_sorting_set_nth (info, scnt++, column); + } + } + } + g_signal_emit (info, e_table_sort_info_signals[SORT_INFO_CHANGED], 0); +} + +/** + * e_table_sort_info_save_to_node: + * @info: The ETableSortInfo object + * @parent: xmlNode that will be hosting the saved state of the @info object. + * + * This function is used + * + * Returns: the node that has been appended to @parent as a child containing + * the sorting and grouping information for this ETableSortInfo object. + */ +xmlNode * +e_table_sort_info_save_to_node (ETableSortInfo *info, + xmlNode *parent) +{ + xmlNode *grouping; + gint i; + const gint sort_count = e_table_sort_info_sorting_get_count (info); + const gint group_count = e_table_sort_info_grouping_get_count (info); + + grouping = xmlNewChild (parent, NULL, (const guchar *)"grouping", NULL); + + for (i = 0; i < group_count; i++) { + ETableSortColumn column = e_table_sort_info_grouping_get_nth (info, i); + xmlNode *new_node = xmlNewChild (grouping, NULL, (const guchar *)"group", NULL); + + e_xml_set_integer_prop_by_name (new_node, (const guchar *)"column", column.column); + e_xml_set_bool_prop_by_name (new_node, (const guchar *)"ascending", column.ascending); + } + + for (i = 0; i < sort_count; i++) { + ETableSortColumn column = e_table_sort_info_sorting_get_nth (info, i); + xmlNode *new_node = xmlNewChild (grouping, NULL, (const guchar *)"leaf", NULL); + + e_xml_set_integer_prop_by_name (new_node, (const guchar *)"column", column.column); + e_xml_set_bool_prop_by_name (new_node, (const guchar *)"ascending", column.ascending); + } + + return grouping; +} + +ETableSortInfo * +e_table_sort_info_duplicate (ETableSortInfo *info) +{ + ETableSortInfo *new_info; + + new_info = e_table_sort_info_new (); + + new_info->group_count = info->group_count; + new_info->groupings = g_new (ETableSortColumn, new_info->group_count); + memmove (new_info->groupings, info->groupings, sizeof (ETableSortColumn) * new_info->group_count); + + new_info->sort_count = info->sort_count; + new_info->sortings = g_new (ETableSortColumn, new_info->sort_count); + memmove (new_info->sortings, info->sortings, sizeof (ETableSortColumn) * new_info->sort_count); + + new_info->can_group = info->can_group; + + return new_info; +} + +void +e_table_sort_info_set_can_group (ETableSortInfo *info, + gboolean can_group) +{ + info->can_group = can_group; +} + +gboolean +e_table_sort_info_get_can_group (ETableSortInfo *info) +{ + return info->can_group; +} + |