fix bug 19819
[pspp] / lib / gtksheet / gsheetmodel.c
1 /* GSheetModel --- an abstract model for the GSheet widget.
2  * Copyright (C) 2006 Free Software Foundation
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18
19 #include <config.h>
20
21 #include <glib.h>
22 #include "gsheetmodel.h"
23 #include "gtkextra-marshal.h"
24
25 enum {
26   RANGE_CHANGED,
27   ROWS_INSERTED,
28   ROWS_DELETED,
29   COLUMNS_INSERTED,
30   COLUMNS_DELETED,
31   LAST_SIGNAL
32 };
33
34 static guint sheet_model_signals[LAST_SIGNAL] = { 0 };
35
36
37 static void      g_sheet_model_base_init   (gpointer           g_class);
38
39
40 inline GType
41 g_sheet_model_get_type (void)
42 {
43   static GType sheet_model_type = 0;
44
45   if (! sheet_model_type)
46     {
47       static const GTypeInfo sheet_model_info =
48       {
49         sizeof (GSheetModelIface), /* class_size */
50         g_sheet_model_base_init,   /* base_init */
51         NULL,           /* base_finalize */
52         NULL,
53         NULL,           /* class_finalize */
54         NULL,           /* class_data */
55         0,
56         0,              /* n_preallocs */
57         NULL
58       };
59
60       sheet_model_type =
61         g_type_register_static (G_TYPE_INTERFACE, "GSheetModel",
62                                 &sheet_model_info, 0);
63
64       g_type_interface_add_prerequisite (sheet_model_type, G_TYPE_OBJECT);
65     }
66
67   return sheet_model_type;
68 }
69
70 static void
71 g_sheet_model_base_init (gpointer g_class)
72 {
73   static gboolean initialized = FALSE;
74
75   if (! initialized)
76     {
77       sheet_model_signals[RANGE_CHANGED] =
78         g_signal_new ("range_changed",
79                       G_TYPE_SHEET_MODEL,
80                       G_SIGNAL_RUN_LAST,
81                       G_STRUCT_OFFSET (GSheetModelIface, range_changed),
82                       NULL, NULL,
83                       gtkextra_VOID__INT_INT_INT_INT,
84                       G_TYPE_NONE, 4,
85                       G_TYPE_INT,
86                       G_TYPE_INT,
87                       G_TYPE_INT,
88                       G_TYPE_INT);
89
90
91
92       sheet_model_signals[ROWS_INSERTED] =
93         g_signal_new ("rows_inserted",
94                       G_TYPE_SHEET_MODEL,
95                       G_SIGNAL_RUN_LAST,
96                       G_STRUCT_OFFSET (GSheetModelIface, rows_inserted),
97                       NULL, NULL,
98                       gtkextra_VOID__INT_INT,
99                       G_TYPE_NONE, 2,
100                       G_TYPE_INT,
101                       G_TYPE_INT);
102
103
104       sheet_model_signals[ROWS_DELETED] =
105         g_signal_new ("rows_deleted",
106                       G_TYPE_SHEET_MODEL,
107                       G_SIGNAL_RUN_LAST,
108                       G_STRUCT_OFFSET (GSheetModelIface, rows_deleted),
109                       NULL, NULL,
110                       gtkextra_VOID__INT_INT,
111                       G_TYPE_NONE, 2,
112                       G_TYPE_INT,
113                       G_TYPE_INT);
114
115       sheet_model_signals[COLUMNS_INSERTED] =
116         g_signal_new ("columns_inserted",
117                       G_TYPE_SHEET_MODEL,
118                       G_SIGNAL_RUN_LAST,
119                       G_STRUCT_OFFSET (GSheetModelIface, columns_inserted),
120                       NULL, NULL,
121                       gtkextra_VOID__INT_INT,
122                       G_TYPE_NONE, 2,
123                       G_TYPE_INT,
124                       G_TYPE_INT);
125
126
127       sheet_model_signals[COLUMNS_DELETED] =
128         g_signal_new ("columns_deleted",
129                       G_TYPE_SHEET_MODEL,
130                       G_SIGNAL_RUN_LAST,
131                       G_STRUCT_OFFSET (GSheetModelIface, columns_deleted),
132                       NULL, NULL,
133                       gtkextra_VOID__INT_INT,
134                       G_TYPE_NONE, 2,
135                       G_TYPE_INT,
136                       G_TYPE_INT);
137
138
139       initialized = TRUE;
140     }
141 }
142
143
144 /**
145  * g_sheet_model_free_strings
146  * @sheet_model: A #GSheetModel
147  *
148  * Returns: True if strings obtained with get_string should be freed by the
149  * sheet when no longer required.
150  **/
151 inline  gboolean
152 g_sheet_model_free_strings (const GSheetModel *sheet_model)
153 {
154   g_return_val_if_fail (G_IS_SHEET_MODEL (sheet_model), FALSE);
155
156   return G_SHEET_MODEL_GET_IFACE (sheet_model)->free_strings;
157 }
158
159
160 /**
161  * g_sheet_model_get_string:
162  * @sheet_model: A #GSheetModel
163  * @row: The row of the cell to be retrieved.
164  * @column: The column of the cell to be retrieved.
165  *
166  * Retrieves the datum at location ROW, COLUMN in the form of a string.
167  * Returns: The string representation of the datum, or NULL on error.
168  **/
169 inline gchar *
170 g_sheet_model_get_string (const GSheetModel *sheet_model,
171                           glong row, glong column)
172 {
173   g_return_val_if_fail (G_IS_SHEET_MODEL (sheet_model), 0);
174
175   g_assert (G_SHEET_MODEL_GET_IFACE (sheet_model)->get_string);
176
177   return (G_SHEET_MODEL_GET_IFACE (sheet_model)->get_string) (sheet_model, row, column);
178 }
179
180 /**
181  * g_sheet_model_set_string
182  * @sheet_model: A #GSheetModel
183  * @text: The text describing the datum to be set.
184  * @row: The row of the cell to be cleared.
185  * @column: The column of the cell to be cleared.
186  *
187  * Sets the datum at a location from a string.
188  * Returns: TRUE if the datum was changed, FALSE otherwise.
189  **/
190 gboolean
191 g_sheet_model_set_string      (GSheetModel *sheet_model,
192                                  const gchar *text,
193                                  glong row, glong column)
194 {
195   g_return_val_if_fail (G_IS_SHEET_MODEL (sheet_model), FALSE);
196
197   g_assert (G_SHEET_MODEL_GET_IFACE (sheet_model)->set_string);
198
199   return G_SHEET_MODEL_GET_IFACE (sheet_model)->set_string (sheet_model,
200                                                             text, row, column);
201 }
202
203
204
205 /**
206  * g_sheet_model_datum_clear:
207  * @sheet_model: A #GSheetModel
208  * @row: The row of the cell to be cleared.
209  * @column: The column of the cell to be cleared.
210  *
211  * Called when the datum at a location is to be cleared.
212  * Returns: TRUE if the datum was cleared, FALSE otherwise.
213  **/
214 gboolean
215 g_sheet_model_datum_clear    (GSheetModel *sheet_model,
216                                 glong row, glong column)
217 {
218   g_return_val_if_fail (G_IS_SHEET_MODEL (sheet_model), FALSE);
219
220   g_assert (G_SHEET_MODEL_GET_IFACE (sheet_model)->clear_datum);
221
222   return G_SHEET_MODEL_GET_IFACE (sheet_model)->clear_datum (sheet_model,
223                                                                 row, column);
224 }
225
226
227 /**
228  * g_sheet_model_range_changed:
229  * @sheet_model: A #GSheetModel
230  * @range: The #GSheetRange range of cells which have changed.
231  *
232  * Emits the "range_changed" signal on @sheet_model.
233  **/
234 void
235 g_sheet_model_range_changed (GSheetModel *sheet_model,
236                                glong row0, glong col0,
237                                glong rowi, glong coli)
238 {
239   g_return_if_fail (G_IS_SHEET_MODEL (sheet_model));
240
241   g_signal_emit (sheet_model, sheet_model_signals[RANGE_CHANGED], 0,
242                  row0, col0, rowi, coli);
243 }
244
245
246
247
248 /**
249  * g_sheet_model_rows_inserted:
250  * @sheet_model: A #GSheetModel
251  * @row: The row before which the new rows should be inserted.
252  * @n_rows: The number of rows to insert.
253  *
254  * Emits the "rows_inserted" signal on @sheet_model.
255  **/
256 void
257 g_sheet_model_rows_inserted (GSheetModel *sheet_model,
258                                glong row, glong n_rows)
259 {
260   g_return_if_fail (G_IS_SHEET_MODEL (sheet_model));
261
262   g_signal_emit (sheet_model, sheet_model_signals[ROWS_INSERTED], 0,
263                  row, n_rows);
264 }
265
266
267 /**
268  * g_sheet_model_columns_inserted:
269  * @sheet_model: A #GSheetModel
270  * @column: The column before which the new columns should be inserted.
271  * @n_columns: The number of columns to insert.
272  *
273  * Emits the "columns_inserted" signal on @sheet_model.
274  **/
275 void
276 g_sheet_model_columns_inserted (GSheetModel *sheet_model,
277                                glong column, glong n_columns)
278 {
279   g_return_if_fail (G_IS_SHEET_MODEL (sheet_model));
280
281   g_signal_emit (sheet_model, sheet_model_signals[COLUMNS_INSERTED], 0,
282                  column, n_columns);
283 }
284
285
286
287
288 /**
289  * g_sheet_model_rows_deleted:
290  * @sheet_model: A #GSheetModel
291  * @row: The first row to be deleted.
292  * @n_rows: The number of rows to delete.
293  *
294  * Emits the "rows_deleted" signal on @sheet_model.
295  **/
296 void
297 g_sheet_model_rows_deleted (GSheetModel *sheet_model,
298                                glong row, glong n_rows)
299 {
300   g_return_if_fail (G_IS_SHEET_MODEL (sheet_model));
301
302   g_signal_emit (sheet_model, sheet_model_signals[ROWS_DELETED], 0,
303                  row, n_rows);
304 }
305
306
307
308 /**
309  * g_sheet_model_columns_deleted:
310  * @sheet_model: A #GSheetModel
311  * @column: The first column to be deleted.
312  * @n_columns: The number of columns to delete.
313  *
314  * Emits the "columns_deleted" signal on @sheet_model.
315  **/
316 void
317 g_sheet_model_columns_deleted (GSheetModel *sheet_model,
318                                glong column, glong n_columns)
319 {
320   g_return_if_fail (G_IS_SHEET_MODEL (sheet_model));
321
322   g_signal_emit (sheet_model, sheet_model_signals[COLUMNS_DELETED], 0,
323                  column, n_columns);
324 }
325
326
327
328
329
330 /**
331  * g_sheet_model_is_editable:
332  * @sheet_model: A #GSheetModel
333  * @row: The row
334  * @column: The column
335  *
336  * Returns: TRUE if the cell is editable, FALSE otherwise
337  **/
338 inline gboolean
339 g_sheet_model_is_editable (const GSheetModel *model,
340                              glong row, glong column)
341 {
342   g_return_val_if_fail (G_IS_SHEET_MODEL (model), TRUE);
343
344   if ( ! G_SHEET_MODEL_GET_IFACE (model)->is_editable )
345     return TRUE;
346
347   return G_SHEET_MODEL_GET_IFACE (model)->is_editable (model,
348                                                           row, column);
349 }
350
351 /**
352  * g_sheet_model_is_visible:
353  * @sheet_model: A #GSheetModel
354  * @row: The row
355  * @column: The column
356  *
357  * Returns: TRUE if the cell is visible, FALSE otherwise
358  **/
359 inline gboolean
360 g_sheet_model_is_visible (const GSheetModel *model,
361                           glong row, glong column)
362 {
363   g_return_val_if_fail (G_IS_SHEET_MODEL (model), TRUE);
364
365   if ( ! G_SHEET_MODEL_GET_IFACE (model)->is_visible )
366     return TRUE;
367
368   return G_SHEET_MODEL_GET_IFACE (model)->is_visible (model,
369                                                         row, column);
370 }
371
372
373 /**
374  * g_sheet_model_get_foreground:
375  * @sheet_model: A #GSheetModel
376  * @row: The row
377  * @column: The column
378  *
379  * Returns the foreground colour of the cell at @row, @column
380  * Returns: the foreground colour, or NULL on error.
381  **/
382 inline const GdkColor *
383 g_sheet_model_get_foreground (const GSheetModel *model,
384                                 glong row, glong column)
385 {
386   g_return_val_if_fail (G_IS_SHEET_MODEL (model), NULL);
387
388   if ( ! G_SHEET_MODEL_GET_IFACE (model)->get_foreground )
389     return NULL;
390
391   return G_SHEET_MODEL_GET_IFACE (model)->get_foreground (model,
392                                                             row, column);
393 }
394
395 /**
396  * g_sheet_model_get_background:
397  * @sheet_model: A #GSheetModel
398  * @row: The row
399  * @column: The column
400  *
401  * Returns the background colour of the cell at @row, @column
402  * Returns: the background colour, or NULL on error.
403  **/
404 inline const GdkColor *
405 g_sheet_model_get_background (const GSheetModel *model,
406                                 glong row, glong column)
407 {
408   g_return_val_if_fail (G_IS_SHEET_MODEL (model), NULL);
409
410   if ( ! G_SHEET_MODEL_GET_IFACE (model)->get_background )
411     return NULL;
412
413   return G_SHEET_MODEL_GET_IFACE (model)->get_background (model,
414                                                             row, column);
415 }
416
417 /**
418  * g_sheet_model_get_justification:
419  * @sheet_model: A #GSheetModel
420  * @row: The row
421  * @column: The column
422  *
423  * Returns the justification of the cell at @row, @column
424  * Returns: the justification, or NULL on error.
425  **/
426 inline const GtkJustification *
427 g_sheet_model_get_justification (const GSheetModel *model,
428                                    glong row, glong column)
429 {
430   g_return_val_if_fail (G_IS_SHEET_MODEL (model), NULL);
431
432   if ( ! G_SHEET_MODEL_GET_IFACE (model)->get_justification)
433     return NULL;
434
435   return G_SHEET_MODEL_GET_IFACE (model)->get_justification (model,
436                                                                row, column);
437 }
438
439 /**
440  * g_sheet_model_get_font_desc:
441  * @sheet_model: A #GSheetModel
442  * @row: The row
443  * @column: The column
444  *
445  * Returns the font description of the cell at @row, @column
446  * Returns: the font description, or NULL on error.
447  **/
448 inline const PangoFontDescription *
449 g_sheet_model_get_font_desc(const GSheetModel *model,
450                               glong row, glong column)
451 {
452   g_return_val_if_fail (G_IS_SHEET_MODEL (model), NULL);
453   if ( ! G_SHEET_MODEL_GET_IFACE (model)->get_font_desc)
454     return NULL;
455
456   return G_SHEET_MODEL_GET_IFACE (model)->get_font_desc (model,
457                                                            row, column);
458 }
459
460 /**
461  * g_sheet_model_get_cell_border:
462  * @sheet_model: A #GSheetModel
463  * @row: The row
464  * @column: The column
465  *
466  * Returns the cell border of the cell at @row, @column
467  * Returns: the cell border, or NULL on error.
468  **/
469 inline const GtkSheetCellBorder *
470 g_sheet_model_get_cell_border (const GSheetModel *model,
471                                  glong row, glong column)
472 {
473   g_return_val_if_fail (G_IS_SHEET_MODEL (model), NULL);
474   if ( ! G_SHEET_MODEL_GET_IFACE (model)->get_cell_border)
475     return NULL;
476
477   return G_SHEET_MODEL_GET_IFACE (model)->get_cell_border (model,
478                                                            row, column);
479 }
480
481
482
483 /**
484  * g_sheet_model_get_column_count:
485  * @model: A #GSheetModel
486  *
487  * Returns the total number of columns represented by the model
488  **/
489 inline glong
490 g_sheet_model_get_column_count (const GSheetModel *model)
491 {
492   g_return_val_if_fail (G_IS_SHEET_MODEL (model), -1);
493
494   return G_SHEET_MODEL_GET_IFACE (model)->get_column_count (model);
495 }
496
497 /**
498  * g_sheet_model_get_row_count:
499  * @model: A #GSheetModel
500  *
501  * Returns the total number of rows represented by the model
502  **/
503 inline gint
504 g_sheet_model_get_row_count(const GSheetModel *model)
505 {
506   g_return_val_if_fail (G_IS_SHEET_MODEL (model), -1);
507
508
509   return G_SHEET_MODEL_GET_IFACE (model)->get_row_count (model);
510 }