1 /*
2 * Copyright (C) 2009 - 2011 Vivien Malerba <malerba@gnome-db.org>
3 * Copyright (C) 2010 David King <davidk@openismus.com>
4 * Copyright (C) 2011 Murray Cumming <murrayc@murrayc.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library 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 GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 */
21
22 #include <string.h>
23 #include <glib/gi18n-lib.h>
24 #include <libgda/libgda.h>
25 #include "gdaui-grid.h"
26 #include "gdaui-data-proxy.h"
27 #include "gdaui-data-selector.h"
28 #include "gdaui-raw-grid.h"
29 #include "gdaui-data-proxy-info.h"
30 #include "gdaui-enum-types.h"
31
32 static void gdaui_grid_class_init (GdauiGridClass * class);
33 static void gdaui_grid_init (GdauiGrid *wid);
34 static void gdaui_grid_dispose (GObject *object);
35
36 static void gdaui_grid_set_property (GObject *object,
37 guint param_id,
38 const GValue *value,
39 GParamSpec *pspec);
40 static void gdaui_grid_get_property (GObject *object,
41 guint param_id,
42 GValue *value,
43 GParamSpec *pspec);
44
45 /* GdauiDataProxy interface */
46 static void gdaui_grid_widget_init (GdauiDataProxyIface *iface);
47 static GdaDataProxy *gdaui_grid_get_proxy (GdauiDataProxy *iface);
48 static void gdaui_grid_set_column_editable (GdauiDataProxy *iface, gint column, gboolean editable);
49 static void gdaui_grid_show_column_actions (GdauiDataProxy *iface, gint column, gboolean show_actions);
50 static GtkActionGroup *gdaui_grid_get_actions_group (GdauiDataProxy *iface);
51 static gboolean gdaui_grid_widget_set_write_mode (GdauiDataProxy *iface, GdauiDataProxyWriteMode mode);
52 static GdauiDataProxyWriteMode gdaui_grid_widget_get_write_mode (GdauiDataProxy *iface);
53
54 /* GdauiDataSelector interface */
55 static void gdaui_grid_selector_init (GdauiDataSelectorIface *iface);
56 static GdaDataModel *gdaui_grid_selector_get_model (GdauiDataSelector *iface);
57 static void gdaui_grid_selector_set_model (GdauiDataSelector *iface, GdaDataModel *model);
58 static GArray *gdaui_grid_selector_get_selected_rows (GdauiDataSelector *iface);
59 static GdaDataModelIter *gdaui_grid_selector_get_data_set (GdauiDataSelector *iface);
60 static gboolean gdaui_grid_selector_select_row (GdauiDataSelector *iface, gint row);
61 static void gdaui_grid_selector_unselect_row (GdauiDataSelector *iface, gint row);
62 static void gdaui_grid_selector_set_column_visible (GdauiDataSelector *iface, gint column, gboolean visible);
63
64 struct _GdauiGridPriv
65 {
66 GtkWidget *raw_grid;
67 GtkWidget *info;
68 };
69
70 /* get a pointer to the parents to be able to call their destructor */
71 static GObjectClass *parent_class = NULL;
72
73 /* properties */
74 enum {
75 PROP_0,
76 PROP_RAW_GRID,
77 PROP_INFO,
78 PROP_MODEL,
79 PROP_INFO_FLAGS
80 };
81
82 GType
gdaui_grid_get_type(void)83 gdaui_grid_get_type (void)
84 {
85 static GType type = 0;
86
87 if (G_UNLIKELY (type == 0)) {
88 static const GTypeInfo info = {
89 sizeof (GdauiGridClass),
90 (GBaseInitFunc) NULL,
91 (GBaseFinalizeFunc) NULL,
92 (GClassInitFunc) gdaui_grid_class_init,
93 NULL,
94 NULL,
95 sizeof (GdauiGrid),
96 0,
97 (GInstanceInitFunc) gdaui_grid_init,
98 0
99 };
100
101 static const GInterfaceInfo proxy_info = {
102 (GInterfaceInitFunc) gdaui_grid_widget_init,
103 NULL,
104 NULL
105 };
106
107 static const GInterfaceInfo selector_info = {
108 (GInterfaceInitFunc) gdaui_grid_selector_init,
109 NULL,
110 NULL
111 };
112
113 type = g_type_register_static (GTK_TYPE_BOX, "GdauiGrid", &info, 0);
114 g_type_add_interface_static (type, GDAUI_TYPE_DATA_PROXY, &proxy_info);
115 g_type_add_interface_static (type, GDAUI_TYPE_DATA_SELECTOR, &selector_info);
116
117 }
118
119 return type;
120 }
121
122 static void
gdaui_grid_widget_init(GdauiDataProxyIface * iface)123 gdaui_grid_widget_init (GdauiDataProxyIface *iface)
124 {
125 iface->get_proxy = gdaui_grid_get_proxy;
126 iface->set_column_editable = gdaui_grid_set_column_editable;
127 iface->show_column_actions = gdaui_grid_show_column_actions;
128 iface->get_actions_group = gdaui_grid_get_actions_group;
129 iface->set_write_mode = gdaui_grid_widget_set_write_mode;
130 iface->get_write_mode = gdaui_grid_widget_get_write_mode;
131 }
132
133 static void
gdaui_grid_selector_init(GdauiDataSelectorIface * iface)134 gdaui_grid_selector_init (GdauiDataSelectorIface *iface)
135 {
136 iface->get_model = gdaui_grid_selector_get_model;
137 iface->set_model = gdaui_grid_selector_set_model;
138 iface->get_selected_rows = gdaui_grid_selector_get_selected_rows;
139 iface->get_data_set = gdaui_grid_selector_get_data_set;
140 iface->select_row = gdaui_grid_selector_select_row;
141 iface->unselect_row = gdaui_grid_selector_unselect_row;
142 iface->set_column_visible = gdaui_grid_selector_set_column_visible;
143 }
144
145 static void
gdaui_grid_class_init(GdauiGridClass * class)146 gdaui_grid_class_init (GdauiGridClass *class)
147 {
148 GObjectClass *object_class = G_OBJECT_CLASS (class);
149
150 parent_class = g_type_class_peek_parent (class);
151 object_class->dispose = gdaui_grid_dispose;
152
153 /* Properties */
154 object_class->set_property = gdaui_grid_set_property;
155 object_class->get_property = gdaui_grid_get_property;
156 g_object_class_install_property (object_class, PROP_RAW_GRID,
157 g_param_spec_object ("raw-grid", NULL, NULL,
158 GDAUI_TYPE_RAW_GRID,
159 G_PARAM_READABLE));
160 g_object_class_install_property (object_class, PROP_INFO,
161 g_param_spec_object ("info", NULL, NULL,
162 GDAUI_TYPE_DATA_PROXY_INFO,
163 G_PARAM_READABLE));
164 g_object_class_install_property (object_class, PROP_INFO_FLAGS,
165 g_param_spec_flags ("info-flags", NULL, NULL,
166 GDAUI_TYPE_DATA_PROXY_INFO_FLAG,
167 GDAUI_DATA_PROXY_INFO_CURRENT_ROW,
168 G_PARAM_READABLE | G_PARAM_WRITABLE));
169 g_object_class_install_property (object_class, PROP_MODEL,
170 g_param_spec_object ("model", NULL, NULL,
171 GDA_TYPE_DATA_MODEL,
172 G_PARAM_READWRITE));
173 }
174
175 static void
raw_grid_selection_changed_cb(G_GNUC_UNUSED GdauiRawGrid * rawgrid,GdauiGrid * grid)176 raw_grid_selection_changed_cb (G_GNUC_UNUSED GdauiRawGrid *rawgrid, GdauiGrid *grid)
177 {
178 g_signal_emit_by_name (G_OBJECT (grid), "selection-changed");
179 }
180
181 static void
gdaui_grid_init(GdauiGrid * grid)182 gdaui_grid_init (GdauiGrid *grid)
183 {
184 GtkWidget *sw;
185
186 grid->priv = g_new0 (GdauiGridPriv, 1);
187 grid->priv->raw_grid = NULL;
188 grid->priv->info = NULL;
189
190 gtk_orientable_set_orientation (GTK_ORIENTABLE (grid), GTK_ORIENTATION_VERTICAL);
191
192 sw = gtk_scrolled_window_new (NULL, NULL);
193 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
194 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN);
195 gtk_box_pack_start (GTK_BOX (grid), sw, TRUE, TRUE, 0);
196 gtk_widget_show (sw);
197
198 grid->priv->raw_grid = gdaui_raw_grid_new (NULL);
199 gtk_container_add (GTK_CONTAINER (sw), grid->priv->raw_grid);
200 gtk_widget_show (grid->priv->raw_grid);
201 g_signal_connect (grid->priv->raw_grid, "selection-changed",
202 G_CALLBACK (raw_grid_selection_changed_cb), grid);
203
204 grid->priv->info = gdaui_data_proxy_info_new (GDAUI_DATA_PROXY (grid->priv->raw_grid),
205 GDAUI_DATA_PROXY_INFO_CURRENT_ROW);
206 gtk_box_pack_start (GTK_BOX (grid), grid->priv->info, FALSE, TRUE, 0);
207 gtk_widget_show (grid->priv->info);
208 }
209
210 static void
gdaui_grid_dispose(GObject * object)211 gdaui_grid_dispose (GObject *object)
212 {
213 GdauiGrid *grid;
214
215 g_return_if_fail (GDAUI_IS_GRID (object));
216 grid = GDAUI_GRID (object);
217
218 if (grid->priv) {
219 g_signal_handlers_disconnect_by_func (grid->priv->raw_grid,
220 G_CALLBACK (raw_grid_selection_changed_cb), grid);
221
222 /* the private area itself */
223 g_free (grid->priv);
224 grid->priv = NULL;
225 }
226
227 /* for the parent class */
228 parent_class->dispose (object);
229 }
230
231 /**
232 * gdaui_grid_new:
233 * @model: (allow-none): a #GdaDataModel, or %NULL
234 *
235 * Creates a new #GdauiGrid widget suitable to display the data in @model
236 *
237 * Returns: (transfer full): the new widget
238 *
239 * Since: 4.2
240 */
241 GtkWidget *
gdaui_grid_new(GdaDataModel * model)242 gdaui_grid_new (GdaDataModel *model)
243 {
244 GdauiGrid *grid;
245
246 g_return_val_if_fail (!model || GDA_IS_DATA_MODEL (model), NULL);
247
248 grid = (GdauiGrid *) g_object_new (GDAUI_TYPE_GRID,
249 "model", model, NULL);
250
251 return (GtkWidget *) grid;
252 }
253
254
255 static void
gdaui_grid_set_property(GObject * object,guint param_id,const GValue * value,GParamSpec * pspec)256 gdaui_grid_set_property (GObject *object,
257 guint param_id,
258 const GValue *value,
259 GParamSpec *pspec)
260 {
261 GdauiGrid *grid;
262 GdaDataModel *model;
263
264 grid = GDAUI_GRID (object);
265
266 switch (param_id) {
267 case PROP_MODEL:
268 model = GDA_DATA_MODEL (g_value_get_object (value));
269 g_object_set (G_OBJECT (grid->priv->raw_grid), "model", model, NULL);
270 break;
271 case PROP_INFO_FLAGS:
272 g_object_set (G_OBJECT (grid->priv->info), "flags", g_value_get_flags (value), NULL);
273 break;
274 default:
275 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
276 break;
277 }
278 }
279
280 static void
gdaui_grid_get_property(GObject * object,guint param_id,GValue * value,GParamSpec * pspec)281 gdaui_grid_get_property (GObject *object,
282 guint param_id,
283 GValue *value,
284 GParamSpec *pspec)
285 {
286 GdauiGrid *grid;
287 GdaDataModel *model;
288
289 grid = GDAUI_GRID (object);
290
291 switch (param_id) {
292 case PROP_RAW_GRID:
293 g_value_set_object (value, grid->priv->raw_grid);
294 break;
295 case PROP_INFO:
296 g_value_set_object (value, grid->priv->info);
297 break;
298 case PROP_INFO_FLAGS: {
299 GdauiDataProxyInfoFlag flags;
300 g_object_get (G_OBJECT (grid->priv->info), "flags", &flags, NULL);
301 g_value_set_flags (value, flags);
302 break;
303 }
304 case PROP_MODEL:
305 g_object_get (G_OBJECT (grid->priv->raw_grid), "model", &model, NULL);
306 g_value_take_object (value, G_OBJECT (model));
307 break;
308 default:
309 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
310 break;
311 }
312 }
313
314 /**
315 * gdaui_grid_set_sample_size:
316 * @grid: a #GdauiGrid widget
317 * @sample_size: the size of the sample displayed in @grid
318 *
319 * Sets the size of each chunk of data to display: the maximum number of rows which
320 * can be displayed at a time. See gdaui_raw_grid_set_sample_size() and gda_data_proxy_set_sample_size()
321 *
322 * Since: 4.2
323 */
324 void
gdaui_grid_set_sample_size(GdauiGrid * grid,gint sample_size)325 gdaui_grid_set_sample_size (GdauiGrid *grid, gint sample_size)
326 {
327 g_return_if_fail (grid && GDAUI_IS_GRID (grid));
328 g_return_if_fail (grid->priv);
329
330 gdaui_raw_grid_set_sample_size (GDAUI_RAW_GRID (grid->priv->raw_grid), sample_size);
331 }
332
333 /* GdauiDataProxy interface */
334 static GdaDataProxy *
gdaui_grid_get_proxy(GdauiDataProxy * iface)335 gdaui_grid_get_proxy (GdauiDataProxy *iface)
336 {
337 return gdaui_data_proxy_get_proxy ((GdauiDataProxy*) GDAUI_GRID (iface)->priv->raw_grid);
338 }
339
340 static void
gdaui_grid_set_column_editable(GdauiDataProxy * iface,gint column,gboolean editable)341 gdaui_grid_set_column_editable (GdauiDataProxy *iface, gint column, gboolean editable)
342 {
343 gdaui_data_proxy_column_set_editable ((GdauiDataProxy*) GDAUI_GRID (iface)->priv->raw_grid,
344 column, editable);
345 }
346
347 static void
gdaui_grid_show_column_actions(GdauiDataProxy * iface,gint column,gboolean show_actions)348 gdaui_grid_show_column_actions (GdauiDataProxy *iface, gint column, gboolean show_actions)
349 {
350 gdaui_data_proxy_column_show_actions ((GdauiDataProxy*) GDAUI_GRID (iface)->priv->raw_grid,
351 column, show_actions);
352 }
353
354 static GtkActionGroup *
gdaui_grid_get_actions_group(GdauiDataProxy * iface)355 gdaui_grid_get_actions_group (GdauiDataProxy *iface)
356 {
357 return gdaui_data_proxy_get_actions_group ((GdauiDataProxy*) GDAUI_GRID (iface)->priv->raw_grid);
358 }
359
360 static gboolean
gdaui_grid_widget_set_write_mode(GdauiDataProxy * iface,GdauiDataProxyWriteMode mode)361 gdaui_grid_widget_set_write_mode (GdauiDataProxy *iface, GdauiDataProxyWriteMode mode)
362 {
363 return gdaui_data_proxy_set_write_mode ((GdauiDataProxy*) GDAUI_GRID (iface)->priv->raw_grid, mode);
364 }
365
366 static GdauiDataProxyWriteMode
gdaui_grid_widget_get_write_mode(GdauiDataProxy * iface)367 gdaui_grid_widget_get_write_mode (GdauiDataProxy *iface)
368 {
369 return gdaui_data_proxy_get_write_mode ((GdauiDataProxy*) GDAUI_GRID (iface)->priv->raw_grid);
370 }
371
372 /* GdauiDataSelector interface */
373 static GdaDataModel *
gdaui_grid_selector_get_model(GdauiDataSelector * iface)374 gdaui_grid_selector_get_model (GdauiDataSelector *iface)
375 {
376 return gdaui_data_selector_get_model ((GdauiDataSelector*) GDAUI_GRID (iface)->priv->raw_grid);
377 }
378
379 static void
gdaui_grid_selector_set_model(GdauiDataSelector * iface,GdaDataModel * model)380 gdaui_grid_selector_set_model (GdauiDataSelector *iface, GdaDataModel *model)
381 {
382 gdaui_data_selector_set_model ((GdauiDataSelector*) GDAUI_GRID (iface)->priv->raw_grid, model);
383 }
384
385 static GArray *
gdaui_grid_selector_get_selected_rows(GdauiDataSelector * iface)386 gdaui_grid_selector_get_selected_rows (GdauiDataSelector *iface)
387 {
388 return gdaui_data_selector_get_selected_rows ((GdauiDataSelector*) GDAUI_GRID (iface)->priv->raw_grid);
389 }
390
391 static GdaDataModelIter *
gdaui_grid_selector_get_data_set(GdauiDataSelector * iface)392 gdaui_grid_selector_get_data_set (GdauiDataSelector *iface)
393 {
394 return gdaui_data_selector_get_data_set ((GdauiDataSelector*) GDAUI_GRID (iface)->priv->raw_grid);
395 }
396
397 static gboolean
gdaui_grid_selector_select_row(GdauiDataSelector * iface,gint row)398 gdaui_grid_selector_select_row (GdauiDataSelector *iface, gint row)
399 {
400 return gdaui_data_selector_select_row ((GdauiDataSelector*) GDAUI_GRID (iface)->priv->raw_grid, row);
401 }
402
403 static void
gdaui_grid_selector_unselect_row(GdauiDataSelector * iface,gint row)404 gdaui_grid_selector_unselect_row (GdauiDataSelector *iface, gint row)
405 {
406 gdaui_data_selector_unselect_row ((GdauiDataSelector*) GDAUI_GRID (iface)->priv->raw_grid, row);
407 }
408
409 static void
gdaui_grid_selector_set_column_visible(GdauiDataSelector * iface,gint column,gboolean visible)410 gdaui_grid_selector_set_column_visible (GdauiDataSelector *iface, gint column, gboolean visible)
411 {
412 gdaui_data_selector_set_column_visible ((GdauiDataSelector*) GDAUI_GRID (iface)->priv->raw_grid,
413 column, visible);
414 }
415