1 /********************************************************************\
2 * table-model.c -- 2D grid table object model *
3 * Copyright (c) 2001 Free Software Foundation *
4 * Author: Dave Peticolas <dave@krondo.com> *
5 * *
6 * This program is free software; you can redistribute it and/or *
7 * modify it under the terms of the GNU General Public License as *
8 * published by the Free Software Foundation; either version 2 of *
9 * the License, or (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License*
17 * along with this program; if not, contact: *
18 * *
19 * Free Software Foundation Voice: +1-617-542-5942 *
20 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
21 * Boston, MA 02110-1301, USA gnu@gnu.org *
22 * *
23 \********************************************************************/
24
25 #include <config.h>
26
27 #include <glib.h>
28
29 #include "table-model.h"
30
31
32 #define DEFAULT_HANDLER ""
33
34 typedef struct
35 {
36 char *cell_name;
37 gpointer handler;
38 } HandlerNode;
39
40
41 static GHashTable *
gnc_table_model_handler_hash_new(void)42 gnc_table_model_handler_hash_new (void)
43 {
44 return g_hash_table_new (g_str_hash, g_str_equal);
45 }
46
47 static void
hash_destroy_helper(gpointer key,gpointer value,gpointer user_data)48 hash_destroy_helper (gpointer key, gpointer value, gpointer user_data)
49 {
50 HandlerNode *node = value;
51
52 g_free (node->cell_name);
53 node->cell_name = NULL;
54
55 g_free (node);
56 }
57
58 static void
gnc_table_model_handler_hash_destroy(GHashTable * hash)59 gnc_table_model_handler_hash_destroy (GHashTable *hash)
60 {
61 if (!hash) return;
62
63 g_hash_table_foreach (hash, hash_destroy_helper, NULL);
64 g_hash_table_destroy (hash);
65 }
66
67 static void
gnc_table_model_handler_hash_remove(GHashTable * hash,const char * cell_name)68 gnc_table_model_handler_hash_remove (GHashTable *hash, const char *cell_name)
69 {
70 HandlerNode *node;
71
72 if (!hash) return;
73
74 node = g_hash_table_lookup (hash, cell_name);
75 if (!node) return;
76
77 g_hash_table_remove (hash, cell_name);
78
79 g_free (node->cell_name);
80 node->cell_name = NULL;
81
82 g_free (node);
83 }
84
85 static void
gnc_table_model_handler_hash_insert(GHashTable * hash,const char * cell_name,gpointer handler)86 gnc_table_model_handler_hash_insert (GHashTable *hash,
87 const char *cell_name,
88 gpointer handler)
89 {
90 HandlerNode *node;
91
92 g_return_if_fail (hash != NULL);
93 g_return_if_fail (cell_name != NULL);
94
95 gnc_table_model_handler_hash_remove (hash, cell_name);
96 if (!handler) return;
97
98 node = g_new0 (HandlerNode, 1);
99
100 node->cell_name = g_strdup (cell_name);
101 node->handler = handler;
102
103 g_hash_table_insert (hash, node->cell_name, node);
104 }
105
106 static gpointer
gnc_table_model_handler_hash_lookup(GHashTable * hash,const char * cell_name)107 gnc_table_model_handler_hash_lookup (GHashTable *hash, const char *cell_name)
108 {
109 HandlerNode *node;
110
111 if (!hash) return NULL;
112
113 if (cell_name)
114 {
115 node = g_hash_table_lookup (hash, cell_name);
116 if (node) return node->handler;
117 }
118
119 cell_name = DEFAULT_HANDLER;
120 node = g_hash_table_lookup (hash, cell_name);
121 if (node) return node->handler;
122
123 return NULL;
124 }
125
126 TableModel *
gnc_table_model_new(void)127 gnc_table_model_new (void)
128 {
129 TableModel *model;
130
131 model = g_new0 (TableModel, 1);
132
133 model->entry_handlers = gnc_table_model_handler_hash_new ();
134 model->label_handlers = gnc_table_model_handler_hash_new ();
135 model->help_handlers = gnc_table_model_handler_hash_new ();
136 model->tooltip_handlers = gnc_table_model_handler_hash_new ();
137 model->io_flags_handlers = gnc_table_model_handler_hash_new ();
138 model->cell_color_handlers = gnc_table_model_handler_hash_new ();
139 model->cell_border_handlers = gnc_table_model_handler_hash_new ();
140 model->confirm_handlers = gnc_table_model_handler_hash_new ();
141 model->save_handlers = gnc_table_model_handler_hash_new ();
142
143 model->read_only = FALSE;
144 model->dividing_row_upper = -1;
145 model->dividing_row = -1;
146 model->dividing_row_lower = -1;
147
148 return model;
149 }
150
151 void
gnc_table_model_destroy(TableModel * model)152 gnc_table_model_destroy (TableModel *model)
153 {
154 if (!model) return;
155
156 gnc_table_model_handler_hash_destroy (model->entry_handlers);
157 model->entry_handlers = NULL;
158
159 gnc_table_model_handler_hash_destroy (model->label_handlers);
160 model->label_handlers = NULL;
161
162 gnc_table_model_handler_hash_destroy (model->tooltip_handlers);
163 model->tooltip_handlers = NULL;
164
165 gnc_table_model_handler_hash_destroy (model->help_handlers);
166 model->help_handlers = NULL;
167
168 gnc_table_model_handler_hash_destroy (model->io_flags_handlers);
169 model->io_flags_handlers = NULL;
170
171 gnc_table_model_handler_hash_destroy (model->cell_color_handlers);
172 model->cell_color_handlers = NULL;
173
174 gnc_table_model_handler_hash_destroy (model->cell_border_handlers);
175 model->cell_border_handlers = NULL;
176
177 gnc_table_model_handler_hash_destroy (model->confirm_handlers);
178 model->confirm_handlers = NULL;
179
180 gnc_table_model_handler_hash_destroy (model->save_handlers);
181 model->save_handlers = NULL;
182
183 g_free (model);
184 }
185
186 void
gnc_table_model_set_read_only(TableModel * model,gboolean read_only)187 gnc_table_model_set_read_only (TableModel *model, gboolean read_only)
188 {
189 g_return_if_fail (model);
190
191 model->read_only = read_only;
192 }
193
194 gboolean
gnc_table_model_read_only(TableModel * model)195 gnc_table_model_read_only (TableModel *model)
196 {
197 g_return_val_if_fail (model, FALSE);
198
199 return model->read_only;
200 }
201
202 void
gnc_table_model_set_entry_handler(TableModel * model,TableGetEntryHandler entry_handler,const char * cell_name)203 gnc_table_model_set_entry_handler (TableModel *model,
204 TableGetEntryHandler entry_handler,
205 const char * cell_name)
206 {
207 g_return_if_fail (model != NULL);
208 g_return_if_fail (cell_name != NULL);
209
210 gnc_table_model_handler_hash_insert (model->entry_handlers,
211 cell_name,
212 entry_handler);
213 }
214
215 void
gnc_table_model_set_default_entry_handler(TableModel * model,TableGetEntryHandler entry_handler)216 gnc_table_model_set_default_entry_handler
217 (TableModel *model, TableGetEntryHandler entry_handler)
218 {
219 g_return_if_fail (model != NULL);
220
221 gnc_table_model_handler_hash_insert (model->entry_handlers,
222 DEFAULT_HANDLER,
223 entry_handler);
224 }
225
226 TableGetEntryHandler
gnc_table_model_get_entry_handler(TableModel * model,const char * cell_name)227 gnc_table_model_get_entry_handler (TableModel *model, const char * cell_name)
228 {
229 g_return_val_if_fail (model != NULL, NULL);
230
231 return gnc_table_model_handler_hash_lookup (model->entry_handlers,
232 cell_name);
233 }
234
235 void
gnc_table_model_set_label_handler(TableModel * model,TableGetLabelHandler label_handler,const char * cell_name)236 gnc_table_model_set_label_handler (TableModel *model,
237 TableGetLabelHandler label_handler,
238 const char * cell_name)
239 {
240 g_return_if_fail (model != NULL);
241 g_return_if_fail (cell_name != NULL);
242
243 gnc_table_model_handler_hash_insert (model->label_handlers,
244 cell_name,
245 label_handler);
246 }
247
248 void
gnc_table_model_set_default_label_handler(TableModel * model,TableGetLabelHandler label_handler)249 gnc_table_model_set_default_label_handler
250 (TableModel *model, TableGetLabelHandler label_handler)
251 {
252 g_return_if_fail (model != NULL);
253
254 gnc_table_model_handler_hash_insert (model->label_handlers,
255 DEFAULT_HANDLER,
256 label_handler);
257 }
258
259 TableGetLabelHandler
gnc_table_model_get_label_handler(TableModel * model,const char * cell_name)260 gnc_table_model_get_label_handler (TableModel *model, const char * cell_name)
261 {
262 g_return_val_if_fail (model != NULL, NULL);
263
264 return gnc_table_model_handler_hash_lookup (model->label_handlers,
265 cell_name);
266 }
267
268 void
gnc_table_model_set_tooltip_handler(TableModel * model,TableGetTooltipHandler tooltip_handler,const char * cell_name)269 gnc_table_model_set_tooltip_handler (TableModel *model,
270 TableGetTooltipHandler tooltip_handler,
271 const char * cell_name)
272 {
273 g_return_if_fail (model != NULL);
274 g_return_if_fail (cell_name != NULL);
275
276 gnc_table_model_handler_hash_insert (model->tooltip_handlers,
277 cell_name,
278 tooltip_handler);
279 }
280
281 void
gnc_table_model_set_default_tooltip_handler(TableModel * model,TableGetTooltipHandler tooltip_handler)282 gnc_table_model_set_default_tooltip_handler
283 (TableModel *model, TableGetTooltipHandler tooltip_handler)
284 {
285 g_return_if_fail (model != NULL);
286
287 gnc_table_model_handler_hash_insert (model->tooltip_handlers,
288 DEFAULT_HANDLER,
289 tooltip_handler);
290 }
291
292 TableGetTooltipHandler
gnc_table_model_get_tooltip_handler(TableModel * model,const char * cell_name)293 gnc_table_model_get_tooltip_handler (TableModel *model, const char * cell_name)
294 {
295 g_return_val_if_fail (model != NULL, NULL);
296
297 return gnc_table_model_handler_hash_lookup (model->tooltip_handlers,
298 cell_name);
299 }
300
301 void
gnc_table_model_set_help_handler(TableModel * model,TableGetHelpHandler help_handler,const char * cell_name)302 gnc_table_model_set_help_handler (TableModel *model,
303 TableGetHelpHandler help_handler,
304 const char * cell_name)
305 {
306 g_return_if_fail (model != NULL);
307 g_return_if_fail (cell_name != NULL);
308
309 gnc_table_model_handler_hash_insert (model->help_handlers,
310 cell_name,
311 help_handler);
312 }
313
314 void
gnc_table_model_set_default_help_handler(TableModel * model,TableGetHelpHandler help_handler)315 gnc_table_model_set_default_help_handler (TableModel *model,
316 TableGetHelpHandler help_handler)
317 {
318 g_return_if_fail (model != NULL);
319
320 gnc_table_model_handler_hash_insert (model->help_handlers,
321 DEFAULT_HANDLER,
322 help_handler);
323 }
324
325 TableGetHelpHandler
gnc_table_model_get_help_handler(TableModel * model,const char * cell_name)326 gnc_table_model_get_help_handler (TableModel *model, const char * cell_name)
327 {
328 g_return_val_if_fail (model != NULL, NULL);
329
330 return gnc_table_model_handler_hash_lookup (model->help_handlers, cell_name);
331 }
332
333 void
gnc_table_model_set_io_flags_handler(TableModel * model,TableGetCellIOFlagsHandler io_flags_handler,const char * cell_name)334 gnc_table_model_set_io_flags_handler
335 (TableModel *model,
336 TableGetCellIOFlagsHandler io_flags_handler,
337 const char * cell_name)
338 {
339 g_return_if_fail (model != NULL);
340 g_return_if_fail (cell_name != NULL);
341
342 gnc_table_model_handler_hash_insert (model->io_flags_handlers,
343 cell_name,
344 io_flags_handler);
345 }
346
347 void
gnc_table_model_set_default_io_flags_handler(TableModel * model,TableGetCellIOFlagsHandler io_flags_handler)348 gnc_table_model_set_default_io_flags_handler
349 (TableModel *model,
350 TableGetCellIOFlagsHandler io_flags_handler)
351 {
352 g_return_if_fail (model != NULL);
353
354 gnc_table_model_handler_hash_insert (model->io_flags_handlers,
355 DEFAULT_HANDLER,
356 io_flags_handler);
357 }
358
359 TableGetCellIOFlagsHandler
gnc_table_model_get_io_flags_handler(TableModel * model,const char * cell_name)360 gnc_table_model_get_io_flags_handler (TableModel *model,
361 const char * cell_name)
362 {
363 g_return_val_if_fail (model != NULL, NULL);
364
365 return gnc_table_model_handler_hash_lookup (model->io_flags_handlers,
366 cell_name);
367 }
368
369 void
gnc_table_model_set_cell_color_handler(TableModel * model,TableGetCellColorHandler color_handler,const char * cell_name)370 gnc_table_model_set_cell_color_handler
371 (TableModel *model,
372 TableGetCellColorHandler color_handler,
373 const char * cell_name)
374 {
375 g_return_if_fail (model != NULL);
376 g_return_if_fail (cell_name != NULL);
377
378 gnc_table_model_handler_hash_insert (model->cell_color_handlers,
379 cell_name,
380 color_handler);
381 }
382
383 void
gnc_table_model_set_default_cell_color_handler(TableModel * model,TableGetCellColorHandler color_handler)384 gnc_table_model_set_default_cell_color_handler
385 (TableModel *model,
386 TableGetCellColorHandler color_handler)
387 {
388 g_return_if_fail (model != NULL);
389
390 gnc_table_model_handler_hash_insert (model->cell_color_handlers,
391 DEFAULT_HANDLER,
392 color_handler);
393 }
394
395 TableGetCellColorHandler
gnc_table_model_get_cell_color_handler(TableModel * model,const char * cell_name)396 gnc_table_model_get_cell_color_handler (TableModel *model,
397 const char * cell_name)
398 {
399 g_return_val_if_fail (model != NULL, NULL);
400
401 return gnc_table_model_handler_hash_lookup (model->cell_color_handlers,
402 cell_name);
403 }
404
405 void
gnc_table_model_set_cell_border_handler(TableModel * model,TableGetCellBorderHandler cell_border_handler,const char * cell_name)406 gnc_table_model_set_cell_border_handler
407 (TableModel *model,
408 TableGetCellBorderHandler cell_border_handler,
409 const char * cell_name)
410 {
411 g_return_if_fail (model != NULL);
412 g_return_if_fail (cell_name != NULL);
413
414 gnc_table_model_handler_hash_insert (model->cell_border_handlers,
415 cell_name,
416 cell_border_handler);
417 }
418
419 void
gnc_table_model_set_default_cell_border_handler(TableModel * model,TableGetCellBorderHandler cell_border_handler)420 gnc_table_model_set_default_cell_border_handler
421 (TableModel *model,
422 TableGetCellBorderHandler cell_border_handler)
423 {
424 g_return_if_fail (model != NULL);
425
426 gnc_table_model_handler_hash_insert (model->cell_border_handlers,
427 DEFAULT_HANDLER,
428 cell_border_handler);
429 }
430
431 TableGetCellBorderHandler
gnc_table_model_get_cell_border_handler(TableModel * model,const char * cell_name)432 gnc_table_model_get_cell_border_handler (TableModel *model,
433 const char * cell_name)
434 {
435 g_return_val_if_fail (model != NULL, NULL);
436
437 return gnc_table_model_handler_hash_lookup (model->cell_border_handlers,
438 cell_name);
439 }
440
441 void
gnc_table_model_set_confirm_handler(TableModel * model,TableConfirmHandler confirm_handler,const char * cell_name)442 gnc_table_model_set_confirm_handler
443 (TableModel *model,
444 TableConfirmHandler confirm_handler,
445 const char * cell_name)
446 {
447 g_return_if_fail (model != NULL);
448 g_return_if_fail (cell_name != NULL);
449
450 gnc_table_model_handler_hash_insert (model->confirm_handlers,
451 cell_name,
452 confirm_handler);
453 }
454
455 void
gnc_table_model_set_default_confirm_handler(TableModel * model,TableConfirmHandler confirm_handler)456 gnc_table_model_set_default_confirm_handler
457 (TableModel *model,
458 TableConfirmHandler confirm_handler)
459 {
460 g_return_if_fail (model != NULL);
461
462 gnc_table_model_handler_hash_insert (model->confirm_handlers,
463 DEFAULT_HANDLER,
464 confirm_handler);
465 }
466
467 TableConfirmHandler
gnc_table_model_get_confirm_handler(TableModel * model,const char * cell_name)468 gnc_table_model_get_confirm_handler (TableModel *model,
469 const char * cell_name)
470 {
471 g_return_val_if_fail (model != NULL, NULL);
472
473 return gnc_table_model_handler_hash_lookup (model->confirm_handlers,
474 cell_name);
475 }
476
477 void
gnc_table_model_set_save_handler(TableModel * model,TableSaveCellHandler save_handler,const char * cell_name)478 gnc_table_model_set_save_handler
479 (TableModel *model,
480 TableSaveCellHandler save_handler,
481 const char * cell_name)
482 {
483 g_return_if_fail (model != NULL);
484 g_return_if_fail (cell_name != NULL);
485
486 gnc_table_model_handler_hash_insert (model->save_handlers,
487 cell_name,
488 save_handler);
489 }
490
491 void
gnc_table_model_set_pre_save_handler(TableModel * model,TableSaveHandler save_handler)492 gnc_table_model_set_pre_save_handler
493 (TableModel *model,
494 TableSaveHandler save_handler)
495 {
496 g_return_if_fail (model != NULL);
497
498 model->pre_save_handler = save_handler;
499 }
500
501 void
gnc_table_model_set_post_save_handler(TableModel * model,TableSaveHandler save_handler)502 gnc_table_model_set_post_save_handler
503 (TableModel *model,
504 TableSaveHandler save_handler)
505 {
506 g_return_if_fail (model != NULL);
507
508 model->post_save_handler = save_handler;
509 }
510
511 TableSaveCellHandler
gnc_table_model_get_save_handler(TableModel * model,const char * cell_name)512 gnc_table_model_get_save_handler
513 (TableModel *model,
514 const char * cell_name)
515 {
516 g_return_val_if_fail (model != NULL, NULL);
517
518 return gnc_table_model_handler_hash_lookup (model->save_handlers, cell_name);
519 }
520
521 TableSaveHandler
gnc_table_model_get_pre_save_handler(TableModel * model)522 gnc_table_model_get_pre_save_handler
523 (TableModel *model)
524 {
525 g_return_val_if_fail (model != NULL, NULL);
526
527 return model->pre_save_handler;
528 }
529
530 TableSaveHandler
gnc_table_model_get_post_save_handler(TableModel * model)531 gnc_table_model_get_post_save_handler
532 (TableModel *model)
533 {
534 g_return_val_if_fail (model != NULL, NULL);
535
536 return model->post_save_handler;
537 }
538