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 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 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 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 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 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 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 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 * 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 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 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 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 * 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 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 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 * 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 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 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 * 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 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 * 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 * 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 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 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 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