Basically working model
[pspp] / src / ui / gui / psppire-spreadsheet-model.c
1 /* PSPPIRE - a graphical user interface for PSPP.
2    Copyright (C) 2013  Free Software Foundation
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program 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
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17
18 #include <config.h>
19 #include <glib.h>
20
21 #include "psppire-spreadsheet-model.h"
22
23 #include "data/spreadsheet-reader.h"
24
25 #include "data/gnumeric-reader.h"
26
27 static void psppire_spreadsheet_model_init           (PsppireSpreadsheetModel *spreadsheetModel);
28 static void psppire_spreadsheet_model_class_init     (PsppireSpreadsheetModelClass *class);
29
30 static void psppire_spreadsheet_model_finalize       (GObject   *object);
31 static void psppire_spreadsheet_model_dispose        (GObject   *object);
32
33 static GObjectClass *parent_class = NULL;
34
35
36 static void spreadsheet_tree_model_init (GtkTreeModelIface *iface);
37
38
39 GType
40 psppire_spreadsheet_model_get_type (void)
41 {
42   static GType object_type = 0;
43
44   if (!object_type)
45     {
46       static const GTypeInfo spreadsheet_model_info =
47       {
48         sizeof (PsppireSpreadsheetModelClass),
49         NULL,           /* base_init */
50         NULL,           /* base_finalize */
51         (GClassInitFunc) psppire_spreadsheet_model_class_init,
52         NULL,           /* class_finalize */
53         NULL,           /* class_data */
54         sizeof (PsppireSpreadsheetModel),
55         0,
56         (GInstanceInitFunc) psppire_spreadsheet_model_init,
57       };
58
59       static const GInterfaceInfo tree_model_info = {
60         (GInterfaceInitFunc) spreadsheet_tree_model_init,
61         NULL,
62         NULL
63       };
64       
65       object_type = g_type_register_static (G_TYPE_OBJECT,
66                                                 "PsppireSpreadsheetModel",
67                                                 &spreadsheet_model_info, 0);
68
69       g_type_add_interface_static (object_type, GTK_TYPE_TREE_MODEL,
70                                    &tree_model_info);
71     }
72
73   return object_type;
74 }
75
76
77 /* Properties */
78 enum
79 {
80   PROP_0,
81   PROP_SPREADSHEET
82 };
83
84
85 static void
86 psppire_spreadsheet_model_set_property (GObject         *object,
87                                         guint            prop_id,
88                                         const GValue    *value,
89                                         GParamSpec      *pspec)
90 {
91   PsppireSpreadsheetModel *spreadsheetModel = PSPPIRE_SPREADSHEET_MODEL (object);
92
93   switch (prop_id)
94     {
95     case PROP_SPREADSHEET:
96       spreadsheetModel->spreadsheet = g_value_get_pointer (value);
97       break;
98     default:
99       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
100       break;
101     };
102 }
103
104
105
106 static void
107 psppire_spreadsheet_model_dispose  (GObject *object)
108 {
109 }
110
111 static void
112 psppire_spreadsheet_model_finalize (GObject *object)
113 {
114   //  PsppireSpreadsheetModel *spreadsheetModel = PSPPIRE_SPREADSHEET_MODEL (object);
115 }
116
117 static void
118 psppire_spreadsheet_model_class_init (PsppireSpreadsheetModelClass *class)
119 {
120   GObjectClass *object_class;
121
122   GParamSpec *spreadsheet_spec =
123     g_param_spec_pointer ("spreadsheet",
124                           "Spreadsheet",
125                           "The spreadsheet that this model represents",
126                           G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE);
127
128   parent_class = g_type_class_peek_parent (class);
129   object_class = (GObjectClass*) class;
130
131   object_class->set_property = psppire_spreadsheet_model_set_property;
132
133   g_object_class_install_property (object_class,
134                                    PROP_SPREADSHEET,
135                                    spreadsheet_spec);
136
137
138
139   object_class->finalize = psppire_spreadsheet_model_finalize;
140   object_class->dispose = psppire_spreadsheet_model_dispose;
141 }
142
143
144 static void
145 psppire_spreadsheet_model_init (PsppireSpreadsheetModel *spreadsheetModel)
146 {
147   spreadsheetModel->dispose_has_run = FALSE;
148   spreadsheetModel->stamp = g_random_int ();
149 }
150
151
152 GtkTreeModel*
153 psppire_spreadsheet_model_new (struct spreadsheet *sp)
154 {
155   return g_object_new (psppire_spreadsheet_model_get_type (), 
156                        "spreadsheet", sp,
157                        NULL);
158 }
159
160
161
162
163 \f
164
165 static const gint N_COLS = 2;
166
167 static gint 
168 tree_model_n_columns (GtkTreeModel *model)
169 {
170   return N_COLS;
171 }
172
173 static GtkTreeModelFlags
174 tree_model_get_flags (GtkTreeModel *model)
175 {
176   g_return_val_if_fail (PSPPIRE_IS_SPREADSHEET_MODEL (model), (GtkTreeModelFlags) 0);
177
178   return GTK_TREE_MODEL_LIST_ONLY;
179 }
180
181 static GType
182 tree_model_column_type (GtkTreeModel *model, gint index)
183 {
184   g_return_val_if_fail (PSPPIRE_IS_SPREADSHEET_MODEL (model), (GType) 0);
185   g_return_val_if_fail (index < N_COLS, (GType) 0);
186  
187   return G_TYPE_STRING;
188 }
189
190
191 static gboolean
192 tree_model_get_iter (GtkTreeModel *model, GtkTreeIter *iter, GtkTreePath *path)
193 {
194   PsppireSpreadsheetModel *spreadsheetModel = PSPPIRE_SPREADSHEET_MODEL (model);
195   gint *indices, depth;
196   gint n;
197
198   g_return_val_if_fail (path, FALSE);
199
200   depth = gtk_tree_path_get_depth (path);
201
202   g_return_val_if_fail (depth == 1, FALSE);
203
204   indices = gtk_tree_path_get_indices (path);
205
206   n = indices [0];
207
208   iter->stamp = spreadsheetModel->stamp;
209   iter->user_data = (gpointer) n;
210
211   return TRUE;
212 }
213
214 static gboolean
215 tree_model_iter_next (GtkTreeModel *model, GtkTreeIter *iter)
216 {
217   PsppireSpreadsheetModel *spreadsheetModel = PSPPIRE_SPREADSHEET_MODEL (model);
218   g_return_val_if_fail (iter->stamp == spreadsheetModel->stamp, FALSE);
219
220   if ( iter == NULL)
221     return FALSE;
222
223   if ( (gint) iter->user_data >= spreadsheetModel->spreadsheet->sheets - 1)
224     {
225       iter->user_data = NULL;
226       iter->stamp = 0;
227       return FALSE;
228     }
229
230   iter->user_data++;
231
232   return TRUE;
233 }
234
235
236 static void
237 tree_model_get_value (GtkTreeModel *model, GtkTreeIter *iter,
238                       gint column, GValue *value)
239 {
240   PsppireSpreadsheetModel *spreadsheetModel = PSPPIRE_SPREADSHEET_MODEL (model);
241   g_return_if_fail (column < N_COLS);
242   g_return_if_fail (iter->stamp == spreadsheetModel->stamp);
243
244   g_value_init (value, G_TYPE_STRING);
245   switch (column)
246     {
247     case 0:
248       {
249         char *x = gnumeric_get_sheet_name (spreadsheetModel->spreadsheet, (gint) iter->user_data);
250         g_value_set_string (value, x);
251       }
252       break;
253     case 1:
254       g_value_set_string (value, "bar");
255       break;
256     default:
257       g_critical ("Bad column");
258       break;
259   }
260 }
261
262 static gboolean
263 tree_model_nth_child (GtkTreeModel *model, GtkTreeIter *iter,
264                       GtkTreeIter *parent, gint n)
265 {
266   PsppireSpreadsheetModel *spreadsheetModel = PSPPIRE_SPREADSHEET_MODEL (model);
267
268   if ( parent )
269     return FALSE;
270
271   if ( n >= spreadsheetModel->spreadsheet->sheets)
272     return FALSE;
273
274   iter->stamp = spreadsheetModel->stamp;
275   iter->user_data = (gpointer) n;
276
277   return TRUE;
278 }
279
280 static gint
281 tree_model_n_children (GtkTreeModel *model,
282                        GtkTreeIter  *iter)
283 {
284   PsppireSpreadsheetModel *spreadsheetModel = PSPPIRE_SPREADSHEET_MODEL (model);
285
286   if ( iter == NULL )
287       return spreadsheetModel->spreadsheet->sheets;
288
289   return 0;
290 }
291
292 static gboolean
293 tree_model_iter_has_child  (GtkTreeModel *tree_model,
294                             GtkTreeIter  *iter)
295 {
296   return FALSE;
297 }
298
299 static GtkTreePath *
300 tree_model_get_path (GtkTreeModel *model, GtkTreeIter *iter)
301 {
302   PsppireSpreadsheetModel *spreadsheetModel = PSPPIRE_SPREADSHEET_MODEL (model);
303   GtkTreePath *path;
304   gint index = (gint) iter->user_data;
305
306   g_return_val_if_fail (iter->stamp == spreadsheetModel->stamp, NULL);
307
308   path = gtk_tree_path_new ();
309
310   gtk_tree_path_append_index (path, index);
311
312   return path;
313 }
314
315
316
317 static void
318 spreadsheet_tree_model_init (GtkTreeModelIface *iface)
319 {
320   iface->get_flags = tree_model_get_flags;
321   iface->get_n_columns = tree_model_n_columns;
322   iface->get_column_type = tree_model_column_type;
323   iface->get_iter = tree_model_get_iter;
324   iface->iter_next = tree_model_iter_next;
325   iface->get_value = tree_model_get_value;
326
327   iface->iter_children = NULL;
328   iface->iter_parent = NULL;
329
330   iface->get_path = tree_model_get_path;
331   iface->iter_has_child = tree_model_iter_has_child ;
332   iface->iter_n_children = tree_model_n_children ;
333   iface->iter_nth_child = tree_model_nth_child ;
334 }