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