evolution-3.6.4/widgets/table/e-table-subset.c

No issues found

  1 /*
  2  *
  3  * This program is free software; you can redistribute it and/or
  4  * modify it under the terms of the GNU Lesser General Public
  5  * License as published by the Free Software Foundation; either
  6  * version 2 of the License, or (at your option) version 3.
  7  *
  8  * This program is distributed in the hope that it will be useful,
  9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 11  * Lesser General Public License for more details.
 12  *
 13  * You should have received a copy of the GNU Lesser General Public
 14  * License along with the program; if not, see <http://www.gnu.org/licenses/>
 15  *
 16  *
 17  * Authors:
 18  *		Chris Lahey <clahey@ximian.com>
 19  *		Miguel de Icaza <miguel@ximian.com>
 20  *
 21  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
 22  *
 23  */
 24 
 25 #ifdef HAVE_CONFIG_H
 26 #include <config.h>
 27 #endif
 28 
 29 #include <stdlib.h>
 30 
 31 #include "e-util/e-util.h"
 32 
 33 #include "e-table-subset.h"
 34 
 35 static void	etss_proxy_model_pre_change_real
 36 						(ETableSubset *etss,
 37 						 ETableModel *etm);
 38 static void	etss_proxy_model_no_change_real	(ETableSubset *etss,
 39 						 ETableModel *etm);
 40 static void	etss_proxy_model_changed_real	(ETableSubset *etss,
 41 						 ETableModel *etm);
 42 static void	etss_proxy_model_row_changed_real
 43 						(ETableSubset *etss,
 44 						 ETableModel *etm,
 45 						 gint row);
 46 static void	etss_proxy_model_cell_changed_real
 47 						(ETableSubset *etss,
 48 						 ETableModel *etm,
 49 						 gint col,
 50 						 gint row);
 51 static void	etss_proxy_model_rows_inserted_real
 52 						(ETableSubset *etss,
 53 						 ETableModel *etm,
 54 						 gint row,
 55 						 gint count);
 56 static void	etss_proxy_model_rows_deleted_real
 57 						(ETableSubset *etss,
 58 						 ETableModel *etm,
 59 						 gint row,
 60 						 gint count);
 61 
 62 #define d(x)
 63 
 64 /* workaround for avoding API breakage */
 65 #define etss_get_type e_table_subset_get_type
 66 G_DEFINE_TYPE (ETableSubset, etss, E_TYPE_TABLE_MODEL)
 67 
 68 #define ETSS_CLASS(object) (E_TABLE_SUBSET_GET_CLASS(object))
 69 
 70 #define VALID_ROW(etss, row) (row >= -1 && row < etss->n_map)
 71 #define MAP_ROW(etss, row) (row == -1 ? -1 : etss->map_table[row])
 72 
 73 static gint
 74 etss_get_view_row (ETableSubset *etss,
 75                    gint row)
 76 {
 77 	const gint n = etss->n_map;
 78 	const gint * const map_table = etss->map_table;
 79 	gint i;
 80 
 81 	gint end = MIN (etss->n_map, etss->last_access + 10);
 82 	gint start = MAX (0, etss->last_access - 10);
 83 	gint initial = MAX (MIN (etss->last_access, end), start);
 84 
 85 	for (i = initial; i < end; i++) {
 86 		if (map_table[i] == row) {
 87 			d (g_print ("a) Found %d from %d\n", i, etss->last_access));
 88 			etss->last_access = i;
 89 			return i;
 90 		}
 91 	}
 92 
 93 	for (i = initial - 1; i >= start; i--) {
 94 		if (map_table[i] == row) {
 95 			d (g_print ("b) Found %d from %d\n", i, etss->last_access));
 96 			etss->last_access = i;
 97 			return i;
 98 		}
 99 	}
100 
101 	for (i = 0; i < n; i++) {
102 		if (map_table[i] == row) {
103 			d (g_print ("c) Found %d from %d\n", i, etss->last_access));
104 			etss->last_access = i;
105 			return i;
106 		}
107 	}
108 	return -1;
109 }
110 
111 static void
112 etss_dispose (GObject *object)
113 {
114 	ETableSubset *etss = E_TABLE_SUBSET (object);
115 
116 	if (etss->source) {
117 		g_signal_handler_disconnect (
118 			etss->source,
119 			etss->table_model_pre_change_id);
120 		g_signal_handler_disconnect (
121 			etss->source,
122 			etss->table_model_no_change_id);
123 		g_signal_handler_disconnect (
124 			etss->source,
125 			etss->table_model_changed_id);
126 		g_signal_handler_disconnect (
127 			etss->source,
128 			etss->table_model_row_changed_id);
129 		g_signal_handler_disconnect (
130 			etss->source,
131 			etss->table_model_cell_changed_id);
132 		g_signal_handler_disconnect (
133 			etss->source,
134 			etss->table_model_rows_inserted_id);
135 		g_signal_handler_disconnect (
136 			etss->source,
137 			etss->table_model_rows_deleted_id);
138 
139 		g_object_unref (etss->source);
140 		etss->source = NULL;
141 
142 		etss->table_model_changed_id = 0;
143 		etss->table_model_row_changed_id = 0;
144 		etss->table_model_cell_changed_id = 0;
145 		etss->table_model_rows_inserted_id = 0;
146 		etss->table_model_rows_deleted_id = 0;
147 	}
148 
149 	G_OBJECT_CLASS (etss_parent_class)->dispose (object);
150 }
151 
152 static void
153 etss_finalize (GObject *object)
154 {
155 	ETableSubset *etss = E_TABLE_SUBSET (object);
156 
157 	g_free (etss->map_table);
158 	etss->map_table = NULL;
159 
160 	G_OBJECT_CLASS (etss_parent_class)->finalize (object);
161 }
162 
163 static gint
164 etss_column_count (ETableModel *etm)
165 {
166 	ETableSubset *etss = (ETableSubset *) etm;
167 
168 	return e_table_model_column_count (etss->source);
169 }
170 
171 static gint
172 etss_row_count (ETableModel *etm)
173 {
174 	ETableSubset *etss = (ETableSubset *) etm;
175 
176 	return etss->n_map;
177 }
178 
179 static gpointer
180 etss_value_at (ETableModel *etm,
181                gint col,
182                gint row)
183 {
184 	ETableSubset *etss = (ETableSubset *) etm;
185 
186 	g_return_val_if_fail (VALID_ROW (etss, row), NULL);
187 
188 	etss->last_access = row;
189 	d (g_print ("g) Setting last_access to %d\n", row));
190 	return e_table_model_value_at (etss->source, col, MAP_ROW (etss, row));
191 }
192 
193 static void
194 etss_set_value_at (ETableModel *etm,
195                    gint col,
196                    gint row,
197                    gconstpointer val)
198 {
199 	ETableSubset *etss = (ETableSubset *) etm;
200 
201 	g_return_if_fail (VALID_ROW (etss, row));
202 
203 	etss->last_access = row;
204 	d (g_print ("h) Setting last_access to %d\n", row));
205 	e_table_model_set_value_at (etss->source, col, MAP_ROW (etss, row), val);
206 }
207 
208 static gboolean
209 etss_is_cell_editable (ETableModel *etm,
210                        gint col,
211                        gint row)
212 {
213 	ETableSubset *etss = (ETableSubset *) etm;
214 
215 	g_return_val_if_fail (VALID_ROW (etss, row), FALSE);
216 
217 	return e_table_model_is_cell_editable (etss->source, col, MAP_ROW (etss, row));
218 }
219 
220 static gboolean
221 etss_has_save_id (ETableModel *etm)
222 {
223 	return TRUE;
224 }
225 
226 static gchar *
227 etss_get_save_id (ETableModel *etm,
228                   gint row)
229 {
230 	ETableSubset *etss = (ETableSubset *) etm;
231 
232 	g_return_val_if_fail (VALID_ROW (etss, row), NULL);
233 
234 	if (e_table_model_has_save_id (etss->source))
235 		return e_table_model_get_save_id (etss->source, MAP_ROW (etss, row));
236 	else
237 		return g_strdup_printf ("%d", MAP_ROW (etss, row));
238 }
239 
240 static void
241 etss_append_row (ETableModel *etm,
242                  ETableModel *source,
243                  gint row)
244 {
245 	ETableSubset *etss = (ETableSubset *) etm;
246 	e_table_model_append_row (etss->source, source, row);
247 }
248 
249 static gpointer
250 etss_duplicate_value (ETableModel *etm,
251                       gint col,
252                       gconstpointer value)
253 {
254 	ETableSubset *etss = (ETableSubset *) etm;
255 
256 	return e_table_model_duplicate_value (etss->source, col, value);
257 }
258 
259 static void
260 etss_free_value (ETableModel *etm,
261                  gint col,
262                  gpointer value)
263 {
264 	ETableSubset *etss = (ETableSubset *) etm;
265 
266 	e_table_model_free_value (etss->source, col, value);
267 }
268 
269 static gpointer
270 etss_initialize_value (ETableModel *etm,
271                        gint col)
272 {
273 	ETableSubset *etss = (ETableSubset *) etm;
274 
275 	return e_table_model_initialize_value (etss->source, col);
276 }
277 
278 static gboolean
279 etss_value_is_empty (ETableModel *etm,
280                      gint col,
281                      gconstpointer value)
282 {
283 	ETableSubset *etss = (ETableSubset *) etm;
284 
285 	return e_table_model_value_is_empty (etss->source, col, value);
286 }
287 
288 static gchar *
289 etss_value_to_string (ETableModel *etm,
290                       gint col,
291                       gconstpointer value)
292 {
293 	ETableSubset *etss = (ETableSubset *) etm;
294 
295 	return e_table_model_value_to_string (etss->source, col, value);
296 }
297 
298 static void
299 etss_class_init (ETableSubsetClass *class)
300 {
301 	ETableModelClass *table_class    = E_TABLE_MODEL_CLASS (class);
302 	GObjectClass *object_class       = G_OBJECT_CLASS (class);
303 
304 	object_class->dispose            = etss_dispose;
305 	object_class->finalize           = etss_finalize;
306 
307 	table_class->column_count        = etss_column_count;
308 	table_class->row_count           = etss_row_count;
309 	table_class->append_row          = etss_append_row;
310 
311 	table_class->value_at            = etss_value_at;
312 	table_class->set_value_at        = etss_set_value_at;
313 	table_class->is_cell_editable    = etss_is_cell_editable;
314 
315 	table_class->has_save_id         = etss_has_save_id;
316 	table_class->get_save_id         = etss_get_save_id;
317 
318 	table_class->duplicate_value     = etss_duplicate_value;
319 	table_class->free_value          = etss_free_value;
320 	table_class->initialize_value    = etss_initialize_value;
321 	table_class->value_is_empty      = etss_value_is_empty;
322 	table_class->value_to_string     = etss_value_to_string;
323 
324 	class->proxy_model_pre_change    = etss_proxy_model_pre_change_real;
325 	class->proxy_model_no_change     = etss_proxy_model_no_change_real;
326 	class->proxy_model_changed       = etss_proxy_model_changed_real;
327 	class->proxy_model_row_changed   = etss_proxy_model_row_changed_real;
328 	class->proxy_model_cell_changed  = etss_proxy_model_cell_changed_real;
329 	class->proxy_model_rows_inserted = etss_proxy_model_rows_inserted_real;
330 	class->proxy_model_rows_deleted  = etss_proxy_model_rows_deleted_real;
331 }
332 
333 static void
334 etss_init (ETableSubset *etss)
335 {
336 	etss->last_access = 0;
337 }
338 
339 static void
340 etss_proxy_model_pre_change_real (ETableSubset *etss,
341                                   ETableModel *etm)
342 {
343 	e_table_model_pre_change (E_TABLE_MODEL (etss));
344 }
345 
346 static void
347 etss_proxy_model_no_change_real (ETableSubset *etss,
348                                  ETableModel *etm)
349 {
350 	e_table_model_no_change (E_TABLE_MODEL (etss));
351 }
352 
353 static void
354 etss_proxy_model_changed_real (ETableSubset *etss,
355                                ETableModel *etm)
356 {
357 	e_table_model_changed (E_TABLE_MODEL (etss));
358 }
359 
360 static void
361 etss_proxy_model_row_changed_real (ETableSubset *etss,
362                                    ETableModel *etm,
363                                    gint row)
364 {
365 	gint view_row = etss_get_view_row (etss, row);
366 	if (view_row != -1)
367 		e_table_model_row_changed (E_TABLE_MODEL (etss), view_row);
368 	else
369 		e_table_model_no_change (E_TABLE_MODEL (etss));
370 }
371 
372 static void
373 etss_proxy_model_cell_changed_real (ETableSubset *etss,
374                                     ETableModel *etm,
375                                     gint col,
376                                     gint row)
377 {
378 	gint view_row = etss_get_view_row (etss, row);
379 	if (view_row != -1)
380 		e_table_model_cell_changed (E_TABLE_MODEL (etss), col, view_row);
381 	else
382 		e_table_model_no_change (E_TABLE_MODEL (etss));
383 }
384 
385 static void
386 etss_proxy_model_rows_inserted_real (ETableSubset *etss,
387                                      ETableModel *etm,
388                                      gint row,
389                                      gint count)
390 {
391 	e_table_model_no_change (E_TABLE_MODEL (etss));
392 }
393 
394 static void
395 etss_proxy_model_rows_deleted_real (ETableSubset *etss,
396                                     ETableModel *etm,
397                                     gint row,
398                                     gint count)
399 {
400 	e_table_model_no_change (E_TABLE_MODEL (etss));
401 }
402 
403 static void
404 etss_proxy_model_pre_change (ETableModel *etm,
405                              ETableSubset *etss)
406 {
407 	if (ETSS_CLASS (etss)->proxy_model_pre_change)
408 		(ETSS_CLASS (etss)->proxy_model_pre_change) (etss, etm);
409 }
410 
411 static void
412 etss_proxy_model_no_change (ETableModel *etm,
413                             ETableSubset *etss)
414 {
415 	if (ETSS_CLASS (etss)->proxy_model_no_change)
416 		(ETSS_CLASS (etss)->proxy_model_no_change) (etss, etm);
417 }
418 
419 static void
420 etss_proxy_model_changed (ETableModel *etm,
421                           ETableSubset *etss)
422 {
423 	if (ETSS_CLASS (etss)->proxy_model_changed)
424 		(ETSS_CLASS (etss)->proxy_model_changed) (etss, etm);
425 }
426 
427 static void
428 etss_proxy_model_row_changed (ETableModel *etm,
429                               gint row,
430                               ETableSubset *etss)
431 {
432 	if (ETSS_CLASS (etss)->proxy_model_row_changed)
433 		(ETSS_CLASS (etss)->proxy_model_row_changed) (etss, etm, row);
434 }
435 
436 static void
437 etss_proxy_model_cell_changed (ETableModel *etm,
438                                gint col,
439                                gint row,
440                                ETableSubset *etss)
441 {
442 	if (ETSS_CLASS (etss)->proxy_model_cell_changed)
443 		(ETSS_CLASS (etss)->proxy_model_cell_changed) (etss, etm, col, row);
444 }
445 
446 static void
447 etss_proxy_model_rows_inserted (ETableModel *etm,
448                                 gint row,
449                                 gint col,
450                                 ETableSubset *etss)
451 {
452 	if (ETSS_CLASS (etss)->proxy_model_rows_inserted)
453 		(ETSS_CLASS (etss)->proxy_model_rows_inserted) (etss, etm, row, col);
454 }
455 
456 static void
457 etss_proxy_model_rows_deleted (ETableModel *etm,
458                                gint row,
459                                gint col,
460                                ETableSubset *etss)
461 {
462 	if (ETSS_CLASS (etss)->proxy_model_rows_deleted)
463 		(ETSS_CLASS (etss)->proxy_model_rows_deleted) (etss, etm, row, col);
464 }
465 
466 ETableModel *
467 e_table_subset_construct (ETableSubset *etss,
468                           ETableModel *source,
469                           gint nvals)
470 {
471 	guint *buffer;
472 	gint i;
473 
474 	if (nvals) {
475 		buffer = (guint *) g_malloc (sizeof (guint) * nvals);
476 		if (buffer == NULL)
477 			return NULL;
478 	} else
479 		buffer = NULL;
480 	etss->map_table = (gint *) buffer;
481 	etss->n_map = nvals;
482 	etss->source = source;
483 	g_object_ref (source);
484 
485 	/* Init */
486 	for (i = 0; i < nvals; i++)
487 		etss->map_table[i] = i;
488 
489 	etss->table_model_pre_change_id = g_signal_connect (
490 		source, "model_pre_change",
491 		G_CALLBACK (etss_proxy_model_pre_change), etss);
492 	etss->table_model_no_change_id = g_signal_connect (
493 		source, "model_no_change",
494 		G_CALLBACK (etss_proxy_model_no_change), etss);
495 	etss->table_model_changed_id = g_signal_connect (
496 		source, "model_changed",
497 		G_CALLBACK (etss_proxy_model_changed), etss);
498 	etss->table_model_row_changed_id = g_signal_connect (
499 		source, "model_row_changed",
500 		G_CALLBACK (etss_proxy_model_row_changed), etss);
501 	etss->table_model_cell_changed_id = g_signal_connect (
502 		source, "model_cell_changed",
503 		G_CALLBACK (etss_proxy_model_cell_changed), etss);
504 	etss->table_model_rows_inserted_id = g_signal_connect (
505 		source, "model_rows_inserted",
506 		G_CALLBACK (etss_proxy_model_rows_inserted), etss);
507 	etss->table_model_rows_deleted_id = g_signal_connect (
508 		source, "model_rows_deleted",
509 		G_CALLBACK (etss_proxy_model_rows_deleted), etss);
510 
511 	return E_TABLE_MODEL (etss);
512 }
513 
514 ETableModel *
515 e_table_subset_new (ETableModel *source,
516                     const gint nvals)
517 {
518 	ETableSubset *etss = g_object_new (E_TYPE_TABLE_SUBSET, NULL);
519 
520 	if (e_table_subset_construct (etss, source, nvals) == NULL) {
521 		g_object_unref (etss);
522 		return NULL;
523 	}
524 
525 	return (ETableModel *) etss;
526 }
527 
528 gint
529 e_table_subset_model_to_view_row (ETableSubset *ets,
530                                   gint model_row)
531 {
532 	gint i;
533 	for (i = 0; i < ets->n_map; i++) {
534 		if (ets->map_table[i] == model_row)
535 			return i;
536 	}
537 	return -1;
538 }
539 
540 gint
541 e_table_subset_view_to_model_row (ETableSubset *ets,
542                                   gint view_row)
543 {
544 	if (view_row >= 0 && view_row < ets->n_map)
545 		return ets->map_table[view_row];
546 	else
547 		return -1;
548 }
549 
550 ETableModel *
551 e_table_subset_get_toplevel (ETableSubset *table)
552 {
553 	g_return_val_if_fail (table != NULL, NULL);
554 	g_return_val_if_fail (E_IS_TABLE_SUBSET (table), NULL);
555 
556 	if (E_IS_TABLE_SUBSET (table->source))
557 		return e_table_subset_get_toplevel (E_TABLE_SUBSET (table->source));
558 	else
559 		return table->source;
560 }
561 
562 void
563 e_table_subset_print_debugging (ETableSubset *table_model)
564 {
565 	gint i;
566 	for (i = 0; i < table_model->n_map; i++) {
567 		g_print ("%8d\n", table_model->map_table[i]);
568 	}
569 }