evolution-3.6.4/widgets/table/e-table-sorted-variable.c

No issues found

  1 /*
  2  * This program is free software; you can redistribute it and/or
  3  * modify it under the terms of the GNU Lesser General Public
  4  * License as published by the Free Software Foundation; either
  5  * version 2 of the License, or (at your option) version 3.
  6  *
  7  * This program is distributed in the hope that it will be useful,
  8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 10  * Lesser General Public License for more details.
 11  *
 12  * You should have received a copy of the GNU Lesser General Public
 13  * License along with the program; if not, see <http://www.gnu.org/licenses/>
 14  *
 15  *
 16  * Authors:
 17  *		Chris Lahey <clahey@ximian.com>
 18  *
 19  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
 20  *
 21  */
 22 
 23 #ifdef HAVE_CONFIG_H
 24 #include <config.h>
 25 #endif
 26 
 27 #include <stdlib.h>
 28 #include <string.h>
 29 
 30 #include "e-util/e-util.h"
 31 
 32 #include "e-table-sorted-variable.h"
 33 #include "e-table-sorting-utils.h"
 34 
 35 #define d(x)
 36 
 37 #define INCREMENT_AMOUNT 100
 38 
 39 /* maximum insertions between an idle event that we will do without scheduling an idle sort */
 40 #define ETSV_INSERT_MAX (4)
 41 
 42 /* workaround for avoiding API breakage */
 43 #define etsv_get_type e_table_sorted_variable_get_type
 44 G_DEFINE_TYPE (ETableSortedVariable, etsv, E_TYPE_TABLE_SUBSET_VARIABLE)
 45 
 46 static void etsv_sort_info_changed        (ETableSortInfo *info, ETableSortedVariable *etsv);
 47 static void etsv_sort                     (ETableSortedVariable *etsv);
 48 static void etsv_add                      (ETableSubsetVariable *etssv, gint                  row);
 49 static void etsv_add_all                  (ETableSubsetVariable *etssv);
 50 
 51 static void
 52 etsv_dispose (GObject *object)
 53 {
 54 	ETableSortedVariable *etsv = E_TABLE_SORTED_VARIABLE (object);
 55 
 56 	if (etsv->sort_info_changed_id)
 57 		g_signal_handler_disconnect (
 58 			etsv->sort_info,
 59 			etsv->sort_info_changed_id);
 60 	etsv->sort_info_changed_id = 0;
 61 
 62 	if (etsv->sort_idle_id) {
 63 		g_source_remove (etsv->sort_idle_id);
 64 		etsv->sort_idle_id = 0;
 65 	}
 66 	if (etsv->insert_idle_id) {
 67 		g_source_remove (etsv->insert_idle_id);
 68 		etsv->insert_idle_id = 0;
 69 	}
 70 
 71 	if (etsv->sort_info)
 72 		g_object_unref (etsv->sort_info);
 73 	etsv->sort_info = NULL;
 74 
 75 	if (etsv->full_header)
 76 		g_object_unref (etsv->full_header);
 77 	etsv->full_header = NULL;
 78 
 79 	G_OBJECT_CLASS (etsv_parent_class)->dispose (object);
 80 }
 81 
 82 static void
 83 etsv_class_init (ETableSortedVariableClass *class)
 84 {
 85 	ETableSubsetVariableClass *etssv_class = E_TABLE_SUBSET_VARIABLE_CLASS (class);
 86 	GObjectClass *object_class = G_OBJECT_CLASS (class);
 87 
 88 	object_class->dispose = etsv_dispose;
 89 
 90 	etssv_class->add = etsv_add;
 91 	etssv_class->add_all = etsv_add_all;
 92 }
 93 
 94 static void
 95 etsv_init (ETableSortedVariable *etsv)
 96 {
 97 	etsv->full_header = NULL;
 98 	etsv->sort_info = NULL;
 99 
100 	etsv->sort_info_changed_id = 0;
101 
102 	etsv->sort_idle_id = 0;
103 	etsv->insert_count = 0;
104 }
105 
106 static gboolean
107 etsv_sort_idle (ETableSortedVariable *etsv)
108 {
109 	g_object_ref (etsv);
110 	etsv_sort (etsv);
111 	etsv->sort_idle_id = 0;
112 	etsv->insert_count = 0;
113 	g_object_unref (etsv);
114 	return FALSE;
115 }
116 
117 static gboolean
118 etsv_insert_idle (ETableSortedVariable *etsv)
119 {
120 	etsv->insert_count = 0;
121 	etsv->insert_idle_id = 0;
122 	return FALSE;
123 }
124 
125 static void
126 etsv_add (ETableSubsetVariable *etssv,
127           gint row)
128 {
129 	ETableModel *etm = E_TABLE_MODEL (etssv);
130 	ETableSubset *etss = E_TABLE_SUBSET (etssv);
131 	ETableSortedVariable *etsv = E_TABLE_SORTED_VARIABLE (etssv);
132 	gint i;
133 
134 	e_table_model_pre_change (etm);
135 
136 	if (etss->n_map + 1 > etssv->n_vals_allocated) {
137 		etssv->n_vals_allocated += INCREMENT_AMOUNT;
138 		etss->map_table = g_realloc (etss->map_table, (etssv->n_vals_allocated) * sizeof (gint));
139 	}
140 	i = etss->n_map;
141 	if (etsv->sort_idle_id == 0) {
142 		/* this is to see if we're inserting a lot of things between idle loops.
143 		 * If we are, we're busy, its faster to just append and perform a full sort later */
144 		etsv->insert_count++;
145 		if (etsv->insert_count > ETSV_INSERT_MAX) {
146 			/* schedule a sort, and append instead */
147 			etsv->sort_idle_id = g_idle_add_full (50, (GSourceFunc) etsv_sort_idle, etsv, NULL);
148 		} else {
149 			/* make sure we have an idle handler to reset the count every now and then */
150 			if (etsv->insert_idle_id == 0) {
151 				etsv->insert_idle_id = g_idle_add_full (40, (GSourceFunc) etsv_insert_idle, etsv, NULL);
152 			}
153 			i = e_table_sorting_utils_insert (etss->source, etsv->sort_info, etsv->full_header, etss->map_table, etss->n_map, row);
154 			memmove (etss->map_table + i + 1, etss->map_table + i, (etss->n_map - i) * sizeof (gint));
155 		}
156 	}
157 	etss->map_table[i] = row;
158 	etss->n_map++;
159 
160 	e_table_model_row_inserted (etm, i);
161 }
162 
163 static void
164 etsv_add_all (ETableSubsetVariable *etssv)
165 {
166 	ETableModel *etm = E_TABLE_MODEL (etssv);
167 	ETableSubset *etss = E_TABLE_SUBSET (etssv);
168 	ETableSortedVariable *etsv = E_TABLE_SORTED_VARIABLE (etssv);
169 	gint rows;
170 	gint i;
171 
172 	e_table_model_pre_change (etm);
173 
174 	rows = e_table_model_row_count (etss->source);
175 
176 	if (etss->n_map + rows > etssv->n_vals_allocated) {
177 		etssv->n_vals_allocated += MAX (INCREMENT_AMOUNT, rows);
178 		etss->map_table = g_realloc (etss->map_table, etssv->n_vals_allocated * sizeof (gint));
179 	}
180 	for (i = 0; i < rows; i++)
181 		etss->map_table[etss->n_map++] = i;
182 
183 	if (etsv->sort_idle_id == 0) {
184 		etsv->sort_idle_id = g_idle_add_full (50, (GSourceFunc) etsv_sort_idle, etsv, NULL);
185 	}
186 
187 	e_table_model_changed (etm);
188 }
189 
190 ETableModel *
191 e_table_sorted_variable_new (ETableModel *source,
192                              ETableHeader *full_header,
193                              ETableSortInfo *sort_info)
194 {
195 	ETableSortedVariable *etsv = g_object_new (E_TYPE_TABLE_SORTED_VARIABLE, NULL);
196 	ETableSubsetVariable *etssv = E_TABLE_SUBSET_VARIABLE (etsv);
197 
198 	if (e_table_subset_variable_construct (etssv, source) == NULL) {
199 		g_object_unref (etsv);
200 		return NULL;
201 	}
202 
203 	etsv->sort_info = sort_info;
204 	g_object_ref (etsv->sort_info);
205 	etsv->full_header = full_header;
206 	g_object_ref (etsv->full_header);
207 
208 	etsv->sort_info_changed_id = g_signal_connect (
209 		sort_info, "sort_info_changed",
210 		G_CALLBACK (etsv_sort_info_changed), etsv);
211 
212 	return E_TABLE_MODEL (etsv);
213 }
214 
215 static void
216 etsv_sort_info_changed (ETableSortInfo *info,
217                         ETableSortedVariable *etsv)
218 {
219 	etsv_sort (etsv);
220 }
221 
222 static void
223 etsv_sort (ETableSortedVariable *etsv)
224 {
225 	ETableSubset *etss = E_TABLE_SUBSET (etsv);
226 	static gint reentering = 0;
227 	if (reentering)
228 		return;
229 	reentering = 1;
230 
231 	e_table_model_pre_change (E_TABLE_MODEL (etsv));
232 
233 	e_table_sorting_utils_sort (etss->source, etsv->sort_info, etsv->full_header, etss->map_table, etss->n_map);
234 
235 	e_table_model_changed (E_TABLE_MODEL (etsv));
236 	reentering = 0;
237 }