1 /*
2 * Copyright (C) 2010 David King <davidk@openismus.com>
3 * Copyright (C) 2010 - 2012 Vivien Malerba <malerba@gnome-db.org>
4 * Copyright (C) 2011 Murray Cumming <murrayc@murrayc.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
8 * as published by the Free Software Foundation; either version 2
9 * of 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, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20
21 #include <string.h>
22 #include <glib/gi18n-lib.h>
23 #include <libgda/libgda.h>
24 #include "ui-formgrid.h"
25 #include <libgda-ui/gdaui-data-proxy.h>
26 #include <libgda-ui/gdaui-raw-form.h>
27 #include <libgda-ui/gdaui-data-selector.h>
28 #include "../support.h"
29 #include "../browser-window.h"
30 #include "../browser-stock-icons.h"
31 #include "widget-overlay.h"
32 #include <libgda/gda-data-model-extra.h>
33 #include "favorites-actions.h"
34 #ifdef HAVE_LDAP
35 #include "../ldap-browser/ldap-browser-perspective.h"
36 #endif
37 #include "../../tool-utils.h"
38
39 static void ui_formgrid_class_init (UiFormGridClass * class);
40 static void ui_formgrid_init (UiFormGrid *wid);
41 static void ui_formgrid_dispose (GObject *object);
42
43 static void ui_formgrid_set_property (GObject *object,
44 guint param_id,
45 const GValue *value,
46 GParamSpec *pspec);
47 static void ui_formgrid_get_property (GObject *object,
48 guint param_id,
49 GValue *value,
50 GParamSpec *pspec);
51 static void ui_formgrid_show (GtkWidget *widget);
52 static BrowserConnection *get_browser_connection (UiFormGrid *formgrid);
53 static void compute_modification_statements (UiFormGrid *formgrid, GdaDataModel *model);
54
55 #define GRID_FLAGS (GDAUI_DATA_PROXY_INFO_CURRENT_ROW | GDAUI_DATA_PROXY_INFO_CHUNCK_CHANGE_BUTTONS)
56 #define FORM_FLAGS (GDAUI_DATA_PROXY_INFO_CURRENT_ROW | GDAUI_DATA_PROXY_INFO_ROW_MOVE_BUTTONS)
57
58 typedef enum {
59 MOD_INSERT,
60 MOD_UPDATE,
61 MOD_DELETE,
62 MOD_LAST
63 } ModType;
64
65 struct _UiFormGridPriv
66 {
67 GtkWidget *nb;
68 GtkWidget *raw_form;
69 GtkWidget *raw_grid;
70 GtkWidget *info;
71 GtkWidget *overlay_form;
72 GtkWidget *overlay_grid;
73 GtkWidget *autoupdate_toggle;
74 gboolean autoupdate;
75 gboolean autoupdate_possible;
76 GdauiDataProxyInfoFlag flags;
77
78 BrowserConnection *bcnc;
79 gboolean scroll_form;
80
81 /* modifications to the data */
82 gboolean compute_mod_stmt; /* if %TRUE, then the INSERT, UPDATE and DELETE
83 * statements are automatically computed, see the PROP_AUTOMOD property */
84 gboolean mod_stmt_auto_computed; /* %TRUE if mod_stmt[*] have automatically
85 * been computed */
86 GdaStatement *mod_stmt[MOD_LAST];
87 };
88
89 /* get a pointer to the parents to be able to call their destructor */
90 static GObjectClass *parent_class = NULL;
91
92 /* signals */
93 enum {
94 DATA_SET_CHANGED,
95 LAST_SIGNAL
96 };
97
98 gint ui_formgrid_signals [LAST_SIGNAL] = { 0 };
99
100 /* properties */
101 enum {
102 PROP_0,
103 PROP_RAW_GRID,
104 PROP_RAW_FORM,
105 PROP_INFO,
106 PROP_SCROLL_FORM,
107 PROP_AUTOMOD
108 };
109
110 GType
ui_formgrid_get_type(void)111 ui_formgrid_get_type (void)
112 {
113 static GType type = 0;
114
115 if (!type) {
116 static const GTypeInfo info = {
117 sizeof (UiFormGridClass),
118 (GBaseInitFunc) NULL,
119 (GBaseFinalizeFunc) NULL,
120 (GClassInitFunc) ui_formgrid_class_init,
121 NULL,
122 NULL,
123 sizeof (UiFormGrid),
124 0,
125 (GInstanceInitFunc) ui_formgrid_init,
126 0
127 };
128
129 type = g_type_register_static (GTK_TYPE_BOX, "UiFormGrid", &info, 0);
130 }
131
132 return type;
133 }
134
135 static void
ui_formgrid_class_init(UiFormGridClass * klass)136 ui_formgrid_class_init (UiFormGridClass *klass)
137 {
138 GObjectClass *object_class = G_OBJECT_CLASS (klass);
139
140 parent_class = g_type_class_peek_parent (klass);
141 object_class->dispose = ui_formgrid_dispose;
142 GTK_WIDGET_CLASS (klass)->show = ui_formgrid_show;
143
144 /* signals */
145 ui_formgrid_signals [DATA_SET_CHANGED] =
146 g_signal_new ("data-set-changed",
147 G_TYPE_FROM_CLASS (object_class),
148 G_SIGNAL_RUN_FIRST,
149 G_STRUCT_OFFSET (UiFormGridClass, data_set_changed),
150 NULL, NULL,
151 g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
152 klass->data_set_changed = NULL;
153
154 /* Properties */
155 object_class->set_property = ui_formgrid_set_property;
156 object_class->get_property = ui_formgrid_get_property;
157 g_object_class_install_property (object_class, PROP_RAW_GRID,
158 g_param_spec_object ("raw_grid", NULL, NULL,
159 GDAUI_TYPE_RAW_GRID,
160 G_PARAM_READABLE));
161 g_object_class_install_property (object_class, PROP_RAW_FORM,
162 g_param_spec_object ("raw_form", NULL, NULL,
163 GDAUI_TYPE_RAW_GRID,
164 G_PARAM_READABLE));
165 g_object_class_install_property (object_class, PROP_INFO,
166 g_param_spec_object ("widget_info", NULL, NULL,
167 GDAUI_TYPE_DATA_PROXY_INFO,
168 G_PARAM_READABLE));
169 g_object_class_install_property (object_class, PROP_SCROLL_FORM,
170 g_param_spec_boolean ("scroll-form", NULL, NULL,
171 FALSE,
172 G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
173 g_object_class_install_property (object_class, PROP_AUTOMOD,
174 g_param_spec_boolean ("compute-mod-statements", NULL, NULL,
175 FALSE,
176 G_PARAM_WRITABLE | G_PARAM_CONSTRUCT));
177 }
178
179 static void
ui_formgrid_dispose(GObject * object)180 ui_formgrid_dispose (GObject *object)
181 {
182 UiFormGrid *formgrid;
183
184 formgrid = UI_FORMGRID (object);
185 if (formgrid->priv) {
186 if (formgrid->priv->bcnc)
187 g_object_unref (formgrid->priv->bcnc);
188
189 ModType mod;
190 for (mod = MOD_INSERT; mod < MOD_LAST; mod++) {
191 if (formgrid->priv->mod_stmt[mod]) {
192 g_object_unref (formgrid->priv->mod_stmt[mod]);
193 formgrid->priv->mod_stmt[mod] = NULL;
194 }
195 }
196
197 g_free (formgrid->priv);
198 formgrid->priv = NULL;
199 }
200
201 /* parent class */
202 parent_class->dispose (object);
203 }
204
205 static void
ui_formgrid_show(GtkWidget * widget)206 ui_formgrid_show (GtkWidget *widget)
207 {
208 UiFormGrid *formgrid;
209 GtkWidget *ovl, *packed;
210 formgrid = UI_FORMGRID (widget);
211
212 if (! formgrid->priv->overlay_grid) {
213 /* finalize packing */
214 GtkWidget *sw, *vp;
215 sw = gtk_scrolled_window_new (NULL, NULL);
216 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
217 GTK_POLICY_AUTOMATIC,
218 GTK_POLICY_AUTOMATIC);
219 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
220 GTK_SHADOW_NONE);
221 gtk_container_add (GTK_CONTAINER (sw), formgrid->priv->raw_grid);
222 gtk_widget_show_all (sw);
223 packed = sw;
224
225 /* overlay */
226 ovl = widget_overlay_new ();
227 formgrid->priv->overlay_grid = ovl;
228 g_object_set (G_OBJECT (ovl), "add-scale", TRUE, NULL);
229 g_object_set (G_OBJECT (ovl), "add-scale", FALSE, NULL);
230 gtk_container_add (GTK_CONTAINER (ovl), packed);
231 widget_overlay_set_child_props (WIDGET_OVERLAY (ovl), packed,
232 WIDGET_OVERLAY_CHILD_HALIGN,
233 WIDGET_OVERLAY_ALIGN_FILL,
234 WIDGET_OVERLAY_CHILD_VALIGN,
235 WIDGET_OVERLAY_ALIGN_FILL,
236 WIDGET_OVERLAY_CHILD_SCALE, .9,
237 -1);
238 gtk_widget_show (ovl);
239 gtk_notebook_append_page (GTK_NOTEBOOK (formgrid->priv->nb), ovl, NULL);
240 }
241
242 if (! formgrid->priv->overlay_form) {
243 /* finalize packing */
244 if (formgrid->priv->scroll_form) {
245 GtkWidget *sw, *vp;
246 sw = gtk_scrolled_window_new (NULL, NULL);
247 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
248 GTK_POLICY_AUTOMATIC,
249 GTK_POLICY_AUTOMATIC);
250 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
251 GTK_SHADOW_NONE);
252 vp = gtk_viewport_new (NULL, NULL);
253 gtk_widget_set_name (vp, "gdaui-transparent-background");
254 gtk_container_add (GTK_CONTAINER (sw), vp);
255 gtk_viewport_set_shadow_type (GTK_VIEWPORT (vp), GTK_SHADOW_NONE);
256 gtk_container_add (GTK_CONTAINER (vp), formgrid->priv->raw_form);
257 gtk_widget_show_all (sw);
258 packed = sw;
259 }
260 else {
261 gtk_widget_show (formgrid->priv->raw_form);
262 packed = formgrid->priv->raw_form;
263 }
264
265 /* overlay */
266 ovl = widget_overlay_new ();
267 formgrid->priv->overlay_form = ovl;
268 g_object_set (G_OBJECT (ovl), "add-scale", TRUE, NULL);
269 g_object_set (G_OBJECT (ovl), "add-scale", FALSE, NULL);
270 gtk_container_add (GTK_CONTAINER (ovl), packed);
271 widget_overlay_set_child_props (WIDGET_OVERLAY (ovl), packed,
272 WIDGET_OVERLAY_CHILD_HALIGN,
273 WIDGET_OVERLAY_ALIGN_FILL,
274 WIDGET_OVERLAY_CHILD_VALIGN,
275 WIDGET_OVERLAY_ALIGN_FILL,
276 WIDGET_OVERLAY_CHILD_SCALE, 1.,
277 -1);
278 gtk_widget_show (ovl);
279 gtk_notebook_append_page (GTK_NOTEBOOK (formgrid->priv->nb), ovl, NULL);
280 gtk_notebook_set_current_page (GTK_NOTEBOOK (formgrid->priv->nb),
281 0);
282 }
283
284 ((GtkWidgetClass *)parent_class)->show (widget);
285 if (! formgrid->priv->autoupdate_possible)
286 gtk_widget_hide (formgrid->priv->autoupdate_toggle);
287 }
288
289 static void form_grid_autoupdate_cb (GtkToggleButton *button, UiFormGrid *formgrid);
290 static void form_grid_toggled_cb (GtkToggleAction *action, UiFormGrid *formgrid);
291 static void form_grid_populate_popup_cb (GtkWidget *wid, GtkMenu *menu, UiFormGrid *formgrid);
292 static void selection_changed_cb (GdauiDataSelector *sel, UiFormGrid *formgrid);
293
294 static void
ui_formgrid_init(UiFormGrid * formgrid)295 ui_formgrid_init (UiFormGrid *formgrid)
296 {
297 GtkWidget *sw;
298 GtkWidget *hbox, *button;
299
300 formgrid->priv = g_new0 (UiFormGridPriv, 1);
301 formgrid->priv->raw_grid = NULL;
302 formgrid->priv->info = NULL;
303 formgrid->priv->flags = GDAUI_DATA_PROXY_INFO_CURRENT_ROW | GDAUI_DATA_PROXY_INFO_ROW_MODIFY_BUTTONS;
304 formgrid->priv->bcnc = NULL;
305 formgrid->priv->autoupdate = TRUE;
306 formgrid->priv->autoupdate_possible = FALSE;
307 formgrid->priv->scroll_form = FALSE;
308 formgrid->priv->compute_mod_stmt = FALSE;
309
310 gtk_orientable_set_orientation (GTK_ORIENTABLE (formgrid), GTK_ORIENTATION_VERTICAL);
311
312 /* notebook */
313 formgrid->priv->nb = gtk_notebook_new ();
314 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (formgrid->priv->nb), FALSE);
315 gtk_notebook_set_show_border (GTK_NOTEBOOK (formgrid->priv->nb), FALSE);
316 gtk_box_pack_start (GTK_BOX (formgrid), formgrid->priv->nb, TRUE, TRUE, 0);
317 gtk_widget_show (formgrid->priv->nb);
318
319 /* grid on 1st page of notebook, not added there */
320 formgrid->priv->raw_grid = gdaui_raw_grid_new (NULL);
321 gdaui_data_proxy_column_show_actions (GDAUI_DATA_PROXY (formgrid->priv->raw_grid), -1, FALSE);
322 g_signal_connect (formgrid->priv->raw_grid, "populate-popup",
323 G_CALLBACK (form_grid_populate_popup_cb), formgrid);
324
325 /* form on the 2nd page of the notebook, not added there */
326 formgrid->priv->raw_form = gdaui_raw_form_new (NULL);
327 gdaui_data_proxy_column_show_actions (GDAUI_DATA_PROXY (formgrid->priv->raw_form), -1, FALSE);
328 g_signal_connect (formgrid->priv->raw_form, "populate-popup",
329 G_CALLBACK (form_grid_populate_popup_cb), formgrid);
330
331 /* info widget and toggle button at last */
332 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
333 gtk_box_pack_start (GTK_BOX (formgrid), hbox, FALSE, TRUE, 0);
334 gtk_widget_show (hbox);
335
336 /* button to toggle between auto update and not */
337 button = gtk_toggle_button_new ();
338 GtkWidget *img = gtk_image_new_from_stock (GTK_STOCK_EXECUTE, GTK_ICON_SIZE_MENU);
339 gtk_button_set_image (GTK_BUTTON (button), img);
340 formgrid->priv->autoupdate_toggle = button;
341
342 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), formgrid->priv->autoupdate);
343 gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, TRUE, 0);
344 g_signal_connect (G_OBJECT (button), "toggled",
345 G_CALLBACK (form_grid_autoupdate_cb), formgrid);
346 gtk_widget_set_tooltip_text (button, _("Enable or disable auto update of data"));
347
348 /* Proxy info */
349 formgrid->priv->info = gdaui_data_proxy_info_new (GDAUI_DATA_PROXY (formgrid->priv->raw_grid),
350 formgrid->priv->flags |
351 GDAUI_DATA_PROXY_INFO_CURRENT_ROW |
352 GDAUI_DATA_PROXY_INFO_CHUNCK_CHANGE_BUTTONS);
353
354 GtkUIManager *uimanager;
355 GtkActionGroup *agroup;
356 GtkAction *action;
357 guint mid;
358
359 g_object_get (G_OBJECT (formgrid->priv->info), "ui-manager", &uimanager, NULL);
360 agroup = gtk_action_group_new ("FormGrid");
361 gtk_action_group_set_translation_domain (agroup, GETTEXT_PACKAGE);
362
363 action = GTK_ACTION (gtk_toggle_action_new ("FGToggle", "FGToggle",
364 _("Toggle between grid and form presentations"),
365 BROWSER_STOCK_GRID));
366 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE);
367 gtk_action_group_add_action (agroup, action);
368 g_signal_connect (G_OBJECT (action), "toggled",
369 G_CALLBACK (form_grid_toggled_cb), formgrid);
370 g_object_unref (action);
371 gtk_ui_manager_insert_action_group (uimanager, agroup, 0);
372 g_object_unref (agroup);
373
374 mid = gtk_ui_manager_new_merge_id (uimanager);
375 gtk_ui_manager_add_ui (uimanager, mid, "/ToolBar", "FGToggle", "FGToggle",
376 GTK_UI_MANAGER_AUTO, TRUE);
377 gtk_ui_manager_ensure_update (uimanager);
378 gtk_box_pack_start (GTK_BOX (hbox), formgrid->priv->info, TRUE, TRUE, 0);
379 gtk_widget_show (formgrid->priv->info);
380 g_object_unref (G_OBJECT (uimanager));
381
382
383 /*gchar *tmp;
384 g_object_get (uimanager, "ui", &tmp, NULL);
385 g_print ("==>[%s]\n", tmp);
386 g_free (tmp);
387 */
388
389 /* keep data in sync */
390 g_signal_connect (formgrid->priv->raw_grid, "selection-changed",
391 G_CALLBACK (selection_changed_cb), formgrid);
392 g_signal_connect (formgrid->priv->raw_form, "selection-changed",
393 G_CALLBACK (selection_changed_cb), formgrid);
394 }
395
396 /**
397 * ui_formgrid_get_ui_manager:
398 *
399 * Returns: (transfer none): the #GtkUIManager
400 */
401 GtkUIManager *
ui_formgrid_get_ui_manager(UiFormGrid * formgrid)402 ui_formgrid_get_ui_manager (UiFormGrid *formgrid)
403 {
404 GtkUIManager *uimanager;
405 g_return_val_if_fail (UI_IS_FORMGRID (formgrid), NULL);
406 g_object_get (G_OBJECT (formgrid->priv->info), "ui-manager", &uimanager, NULL);
407 g_object_unref (uimanager);
408 return uimanager;
409 }
410
411 static void
selection_changed_cb(GdauiDataSelector * sel,UiFormGrid * formgrid)412 selection_changed_cb (GdauiDataSelector *sel, UiFormGrid *formgrid)
413 {
414 GdaDataModelIter *iter;
415 GdauiDataSelector *tosel;
416 gint row;
417 if (sel == (GdauiDataSelector*) formgrid->priv->raw_grid)
418 tosel = (GdauiDataSelector*) formgrid->priv->raw_form;
419 else
420 tosel = (GdauiDataSelector*) formgrid->priv->raw_grid;
421
422 iter = gdaui_data_selector_get_data_set (sel);
423 g_assert (iter);
424 row = gda_data_model_iter_get_row (iter);
425 /*g_print ("Moved %s to row %d\n", sel == (GdauiDataSelector*) formgrid->priv->raw_grid ? "grid" : "form", row);*/
426 iter = gdaui_data_selector_get_data_set (tosel);
427 if (iter) {
428 g_signal_handlers_block_by_func (tosel, G_CALLBACK (selection_changed_cb), formgrid);
429 gda_data_model_iter_move_to_row (iter, row >= 0 ? row : 0);
430 g_signal_handlers_unblock_by_func (tosel, G_CALLBACK (selection_changed_cb), formgrid);
431 }
432 }
433
434 static void
form_grid_autoupdate_cb(GtkToggleButton * button,UiFormGrid * formgrid)435 form_grid_autoupdate_cb (GtkToggleButton *button, UiFormGrid *formgrid)
436 {
437 formgrid->priv->autoupdate = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
438 }
439
440 static void
form_grid_toggled_cb(GtkToggleAction * action,UiFormGrid * formgrid)441 form_grid_toggled_cb (GtkToggleAction *action, UiFormGrid *formgrid)
442 {
443 if (!gtk_toggle_action_get_active (action)) {
444 /* switch to form view */
445 gtk_notebook_set_current_page (GTK_NOTEBOOK (formgrid->priv->nb), 1);
446 g_object_set (G_OBJECT (formgrid->priv->info),
447 "data-proxy", formgrid->priv->raw_form,
448 "flags", formgrid->priv->flags | FORM_FLAGS, NULL);
449
450 g_object_set (G_OBJECT (action), "stock-id", BROWSER_STOCK_FORM, NULL);
451 }
452 else {
453 /* switch to grid view */
454 gtk_notebook_set_current_page (GTK_NOTEBOOK (formgrid->priv->nb), 0);
455 g_object_set (G_OBJECT (formgrid->priv->info),
456 "data-proxy", formgrid->priv->raw_grid,
457 "flags", formgrid->priv->flags | GRID_FLAGS, NULL);
458
459 g_object_set (G_OBJECT (action), "stock-id", BROWSER_STOCK_GRID, NULL);
460 }
461 }
462
463 static BrowserConnection *
get_browser_connection(UiFormGrid * formgrid)464 get_browser_connection (UiFormGrid *formgrid)
465 {
466 if (formgrid->priv->bcnc)
467 return formgrid->priv->bcnc;
468 else {
469 GtkWidget *toplevel;
470
471 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (formgrid));
472 if (BROWSER_IS_WINDOW (toplevel))
473 return browser_window_get_connection (BROWSER_WINDOW (toplevel));
474 }
475 return NULL;
476 }
477
478
479 static void execute_action_mitem_cb (GtkMenuItem *menuitem, UiFormGrid *formgrid);
480 #ifdef HAVE_LDAP
481 static void ldap_view_dn_mitem_cb (GtkMenuItem *menuitem, UiFormGrid *formgrid);
482 #endif
483 static void zoom_form_mitem_cb (GtkCheckMenuItem *checkmenuitem, UiFormGrid *formgrid);
484 static void zoom_grid_mitem_cb (GtkCheckMenuItem *checkmenuitem, UiFormGrid *formgrid);
485
486 static void
form_grid_populate_popup_cb(GtkWidget * wid,GtkMenu * menu,UiFormGrid * formgrid)487 form_grid_populate_popup_cb (GtkWidget *wid, GtkMenu *menu, UiFormGrid *formgrid)
488 {
489 /* add actions to execute to menu */
490 GdaDataModelIter *iter;
491 BrowserConnection *bcnc = NULL;
492
493 bcnc = get_browser_connection (formgrid);
494 if (!bcnc)
495 return;
496
497 iter = gdaui_data_selector_get_data_set (GDAUI_DATA_SELECTOR (formgrid->priv->raw_grid));
498
499 /* actions */
500 GSList *actions_list, *list;
501 actions_list = gda_tools_favorites_get_actions (browser_connection_get_favorites (bcnc),
502 bcnc, GDA_SET (iter));
503 if (actions_list) {
504 GtkWidget *mitem, *submenu;
505 mitem = gtk_menu_item_new_with_label (_("Execute action"));
506 gtk_widget_show (mitem);
507 gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), mitem);
508
509 submenu = gtk_menu_new ();
510 gtk_menu_item_set_submenu (GTK_MENU_ITEM (mitem), submenu);
511 for (list = actions_list; list; list = list->next) {
512 ToolsFavoriteAction *act = (ToolsFavoriteAction*) list->data;
513 mitem = gtk_menu_item_new_with_label (act->name);
514 gtk_widget_show (mitem);
515 gtk_menu_shell_append (GTK_MENU_SHELL (submenu), mitem);
516 g_object_set_data_full (G_OBJECT (mitem), "action", act,
517 (GDestroyNotify) gda_tools_favorites_free_action);
518 g_signal_connect (mitem, "activate",
519 G_CALLBACK (execute_action_mitem_cb), formgrid);
520 }
521 g_slist_free (actions_list);
522 }
523
524 #ifdef HAVE_LDAP
525 /* LDAP specific */
526 if (browser_connection_is_ldap (bcnc)) {
527 GdaHolder *dnh;
528 dnh = gda_set_get_holder (GDA_SET (iter), "dn");
529 if (dnh) {
530 const GValue *cvalue;
531 cvalue = gda_holder_get_value (GDA_HOLDER (dnh));
532 if (!cvalue && (G_VALUE_TYPE (cvalue) != G_TYPE_STRING))
533 dnh = NULL;
534 }
535 if (!dnh) {
536 GSList *list;
537 for (list = GDA_SET (iter)->holders; list; list = list->next) {
538 const GValue *cvalue;
539 cvalue = gda_holder_get_value (GDA_HOLDER (list->data));
540 if (cvalue && (G_VALUE_TYPE (cvalue) == G_TYPE_STRING) &&
541 gda_ldap_is_dn (g_value_get_string (cvalue))) {
542 dnh = GDA_HOLDER (list->data);
543 break;
544 }
545 }
546 }
547
548 if (dnh) {
549 const GValue *cvalue;
550 cvalue = gda_holder_get_value (dnh);
551
552 GtkWidget *mitem;
553 mitem = gtk_menu_item_new_with_label (_("View LDAP entry's details"));
554 gtk_widget_show (mitem);
555 gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), mitem);
556 g_object_set_data_full (G_OBJECT (mitem), "dn",
557 g_value_dup_string (cvalue), g_free);
558 g_signal_connect (mitem, "activate",
559 G_CALLBACK (ldap_view_dn_mitem_cb), formgrid);
560 }
561 }
562 #endif
563
564 if (wid == formgrid->priv->raw_form) {
565 GtkWidget *mitem;
566 gboolean add_scale;
567 g_object_get (G_OBJECT (formgrid->priv->overlay_form), "add-scale", &add_scale, NULL);
568 mitem = gtk_check_menu_item_new_with_label (_("Zoom..."));
569 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mitem), add_scale);
570 gtk_widget_show (mitem);
571 gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), mitem);
572 g_signal_connect (mitem, "toggled",
573 G_CALLBACK (zoom_form_mitem_cb), formgrid);
574 }
575 else if (wid == formgrid->priv->raw_grid) {
576 GtkWidget *mitem;
577 gboolean add_scale;
578 g_object_get (G_OBJECT (formgrid->priv->overlay_grid), "add-scale", &add_scale, NULL);
579 mitem = gtk_check_menu_item_new_with_label (_("Zoom..."));
580 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mitem), add_scale);
581 gtk_widget_show (mitem);
582 gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), mitem);
583 g_signal_connect (mitem, "toggled",
584 G_CALLBACK (zoom_grid_mitem_cb), formgrid);
585 }
586 }
587
588 static void
zoom_form_mitem_cb(GtkCheckMenuItem * checkmenuitem,UiFormGrid * formgrid)589 zoom_form_mitem_cb (GtkCheckMenuItem *checkmenuitem, UiFormGrid *formgrid)
590 {
591 g_object_set (G_OBJECT (formgrid->priv->overlay_form), "add-scale",
592 gtk_check_menu_item_get_active (checkmenuitem), NULL);
593 }
594
595 static void
zoom_grid_mitem_cb(GtkCheckMenuItem * checkmenuitem,UiFormGrid * formgrid)596 zoom_grid_mitem_cb (GtkCheckMenuItem *checkmenuitem, UiFormGrid *formgrid)
597 {
598 g_object_set (G_OBJECT (formgrid->priv->overlay_grid), "add-scale",
599 gtk_check_menu_item_get_active (checkmenuitem), NULL);
600 }
601
602 typedef struct {
603 BrowserConnection *bcnc; /* ref held */
604 UiFormGrid *formgrid; /* ref held */
605 gchar *name;
606 GdaStatement *stmt; /* ref held */
607 GdaSet *params; /* ref held */
608 GdaDataModel *model; /* ref held */
609 guint exec_id;
610 guint timer_id;
611 } ActionExecutedData;
612
613 static void action_executed_holder_changed_cb (G_GNUC_UNUSED GdaSet *params, G_GNUC_UNUSED GdaHolder *holder,
614 ActionExecutedData *aed);
615 static void
action_executed_data_free(ActionExecutedData * data)616 action_executed_data_free (ActionExecutedData *data)
617 {
618 g_object_unref ((GObject*) data->bcnc);
619 if (data->formgrid)
620 g_object_unref ((GObject*) data->formgrid);
621 g_free (data->name);
622 g_object_unref ((GObject*) data->stmt);
623
624 if (data->params) {
625 g_signal_handlers_disconnect_by_func (data->params,
626 G_CALLBACK (action_executed_holder_changed_cb), data);
627 g_object_unref ((GObject*) data->params);
628 }
629 if (data->model)
630 g_object_unref ((GObject*) data->model);
631 if (data->timer_id)
632 g_source_remove (data->timer_id);
633 g_free (data);
634 }
635
636 static gboolean
exec_end_timeout_cb(ActionExecutedData * aed)637 exec_end_timeout_cb (ActionExecutedData *aed)
638 {
639 GError *error = NULL;
640 GObject *obj;
641 obj = browser_connection_execution_get_result (aed->bcnc, aed->exec_id,
642 NULL, &error);
643 if (obj) {
644 if (GDA_IS_DATA_MODEL (obj)) {
645 g_assert (aed->model == (GdaDataModel*) obj);
646 gda_data_model_thaw (aed->model);
647 gda_data_model_reset (aed->model);
648
649 aed->exec_id = 0;
650 aed->timer_id = 0;
651 return FALSE;
652 }
653 else {
654 g_object_unref (obj);
655 g_set_error (&error, GDA_TOOLS_ERROR, GDA_TOOLS_COMMAND_ARGUMENTS_ERROR,
656 "%s", _("Statement to execute is not a selection statement"));
657 }
658 }
659
660 if (error) {
661 GtkWidget *toplevel;
662 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (aed->formgrid));
663 browser_show_error (GTK_WINDOW (toplevel),
664 _("Error executing query:\n%s"),
665 error->message ?
666 error->message : _("No detail"));
667 g_clear_error (&error);
668 gda_data_model_thaw (aed->model);
669 aed->exec_id = 0;
670 aed->timer_id = 0;
671 return FALSE;
672 }
673 else
674 return TRUE; /* keep timer */
675 }
676
677 static void
action_executed_holder_changed_cb(G_GNUC_UNUSED GdaSet * params,G_GNUC_UNUSED GdaHolder * holder,ActionExecutedData * aed)678 action_executed_holder_changed_cb (G_GNUC_UNUSED GdaSet *params, G_GNUC_UNUSED GdaHolder *holder,
679 ActionExecutedData *aed)
680 {
681 if (! aed->formgrid->priv->autoupdate || ! aed->formgrid->priv->autoupdate_possible)
682 return;
683
684 GError *error = NULL;
685 guint jid;
686 gda_data_model_freeze (aed->model);
687 jid = browser_connection_rerun_select (aed->bcnc, aed->model, &error);
688 if (!jid) {
689 GtkWidget *toplevel;
690 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (aed->formgrid));
691 browser_show_error (GTK_WINDOW (toplevel),
692 _("Error executing query:\n%s"),
693 error->message ?
694 error->message : _("No detail"));
695 gda_data_model_thaw (aed->model);
696 }
697 else {
698 /* watch the end of execution */
699 aed->exec_id = jid;
700 if (! aed->timer_id)
701 aed->timer_id = g_timeout_add (50, (GSourceFunc) exec_end_timeout_cb, aed);
702 }
703 }
704
705 /*
706 * Called after an action's statement has been executed
707 */
708 static void
statement_executed_cb(G_GNUC_UNUSED BrowserConnection * bcnc,G_GNUC_UNUSED guint exec_id,GObject * out_result,G_GNUC_UNUSED GdaSet * out_last_inserted_row,GError * error,ActionExecutedData * aed)709 statement_executed_cb (G_GNUC_UNUSED BrowserConnection *bcnc,
710 G_GNUC_UNUSED guint exec_id,
711 GObject *out_result,
712 G_GNUC_UNUSED GdaSet *out_last_inserted_row, GError *error,
713 ActionExecutedData *aed)
714 {
715 GtkWidget *toplevel;
716
717 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (aed->formgrid));
718 g_object_unref (aed->formgrid);
719 aed->formgrid = NULL;
720
721 if (error)
722 browser_show_error (GTK_WINDOW (toplevel),
723 _("Error executing query:\n%s"),
724 error->message ?
725 error->message : _("No detail"));
726 else if (out_result && GDA_IS_DATA_MODEL (out_result)) {
727 GtkWidget *dialog, *label, *fg;
728 GtkWidget *dcontents;
729
730 gchar *tmp;
731 dialog = gtk_dialog_new_with_buttons (aed->name,
732 NULL,
733 0,
734 GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL);
735 dcontents = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
736 gtk_box_set_spacing (GTK_BOX (dcontents), 5);
737 gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE, TRUE);
738
739 tmp = g_markup_printf_escaped ("<b>%s:</b>", aed->name);
740 label = gtk_label_new ("");
741 gtk_label_set_markup (GTK_LABEL (label), tmp);
742 g_free (tmp);
743 gtk_misc_set_alignment (GTK_MISC (label), 0., 0.);
744 gtk_box_pack_start (GTK_BOX (dcontents), label, FALSE, FALSE, 5);
745
746 fg = ui_formgrid_new (GDA_DATA_MODEL (out_result), TRUE,
747 GDAUI_DATA_PROXY_INFO_CURRENT_ROW);
748 ui_formgrid_set_connection (UI_FORMGRID (fg), aed->bcnc);
749
750 if (GDA_IS_DATA_SELECT (out_result)) {
751 GdaStatement *stmt;
752 g_object_get (G_OBJECT (out_result), "select-stmt", &stmt, NULL);
753 if (stmt) {
754 ui_formgrid_handle_user_prefs (UI_FORMGRID (fg), NULL, stmt);
755 g_object_unref (stmt);
756 }
757 aed->model = g_object_ref (out_result);
758 g_signal_connect (aed->params, "holder-changed",
759 G_CALLBACK (action_executed_holder_changed_cb), aed);
760
761 aed->formgrid = g_object_ref (fg);
762 aed->formgrid->priv->autoupdate_possible = TRUE;
763 gtk_widget_show (aed->formgrid->priv->autoupdate_toggle);
764 }
765 gtk_box_pack_start (GTK_BOX (dcontents), fg, TRUE, TRUE, 0);
766
767 gtk_window_set_default_size (GTK_WINDOW (dialog), 400, 600);
768 gtk_widget_show_all (dialog);
769
770 g_signal_connect (dialog, "response",
771 G_CALLBACK (gtk_widget_destroy), NULL);
772 g_signal_connect (dialog, "close",
773 G_CALLBACK (gtk_widget_destroy), NULL);
774 g_object_set_data_full (G_OBJECT (dialog), "aed", aed,
775 (GDestroyNotify) action_executed_data_free);
776 aed = NULL; /* don't free it yet */
777 }
778 else if (BROWSER_IS_WINDOW (toplevel)) {
779 browser_window_show_notice_printf (BROWSER_WINDOW (toplevel),
780 GTK_MESSAGE_INFO,
781 "ActionExecution",
782 "%s", _("Action successfully executed"));
783 }
784 else
785 browser_show_message (GTK_WINDOW (toplevel),
786 "%s", _("Action successfully executed"));
787
788 if (aed)
789 action_executed_data_free (aed);
790 }
791
792 static void
execute_action_mitem_cb(GtkMenuItem * menuitem,UiFormGrid * formgrid)793 execute_action_mitem_cb (GtkMenuItem *menuitem, UiFormGrid *formgrid)
794 {
795 ToolsFavoriteAction *act;
796 GtkWidget *dlg;
797 gchar *tmp;
798 gint response;
799 GtkWidget *toplevel;
800
801 act = (ToolsFavoriteAction*) g_object_get_data (G_OBJECT (menuitem), "action");
802 toplevel = gtk_widget_get_toplevel ((GtkWidget*) formgrid);
803 tmp = g_strdup_printf (_("Set or confirm the parameters to execute\n"
804 "action '%s'"), act->name);
805 dlg = gdaui_basic_form_new_in_dialog (act->params,
806 (GtkWindow*) toplevel,
807 _("Execution of action"), tmp);
808 g_free (tmp);
809 response = gtk_dialog_run (GTK_DIALOG (dlg));
810 gtk_widget_destroy (dlg);
811 if (response == GTK_RESPONSE_ACCEPT) {
812 GError *lerror = NULL;
813 BrowserConnection *bcnc;
814 ActionExecutedData *aed;
815
816 bcnc = get_browser_connection (formgrid);
817 g_assert (bcnc);
818
819 aed = g_new0 (ActionExecutedData, 1);
820 aed->formgrid = g_object_ref (formgrid);
821 aed->bcnc = g_object_ref (bcnc);
822 if (act->name)
823 aed->name = g_strdup (act->name);
824 aed->stmt = g_object_ref (act->stmt);
825 aed->params = g_object_ref (act->params);
826
827 if (! browser_connection_execute_statement_cb (bcnc,
828 act->stmt, act->params,
829 GDA_STATEMENT_MODEL_RANDOM_ACCESS,
830 FALSE,
831 (BrowserConnectionExecuteCallback) statement_executed_cb,
832 aed, &lerror)) {
833 browser_show_error (GTK_WINDOW (toplevel),
834 _("Error executing query: %s"),
835 lerror && lerror->message ? lerror->message : _("No detail"));
836 g_clear_error (&lerror);
837 action_executed_data_free (aed);
838 }
839 }
840 }
841
842 #ifdef HAVE_LDAP
ldap_view_dn_mitem_cb(GtkMenuItem * menuitem,UiFormGrid * formgrid)843 static void ldap_view_dn_mitem_cb (GtkMenuItem *menuitem, UiFormGrid *formgrid)
844 {
845 const gchar *dn;
846 BrowserWindow *bwin;
847 BrowserPerspective *pers;
848
849 dn = g_object_get_data (G_OBJECT (menuitem), "dn");
850 bwin = (BrowserWindow*) gtk_widget_get_toplevel ((GtkWidget*) formgrid);
851 pers = browser_window_change_perspective (bwin, _("LDAP browser"));
852
853 ldap_browser_perspective_display_ldap_entry (LDAP_BROWSER_PERSPECTIVE (pers), dn);
854 }
855 #endif
856
857 static void
proxy_changed_cb(G_GNUC_UNUSED GdauiDataProxy * dp,G_GNUC_UNUSED GdaDataProxy * proxy,UiFormGrid * formgrid)858 proxy_changed_cb (G_GNUC_UNUSED GdauiDataProxy *dp, G_GNUC_UNUSED GdaDataProxy *proxy, UiFormGrid *formgrid)
859 {
860 g_signal_emit (formgrid, ui_formgrid_signals [DATA_SET_CHANGED], 0);
861 }
862
863 /**
864 * ui_formgrid_new
865 * @model: a #GdaDataModel
866 * @scroll_form: set to %TRUE to wrap the embedded form in a scrolled window
867 * @flags: the #GdauiDataProxyInfoFlag, specifying what to display in the new widget
868 *
869 * Creates a new #UiFormGrid widget suitable to display the data in @model
870 *
871 * Returns: the new widget
872 */
873 GtkWidget *
ui_formgrid_new(GdaDataModel * model,gboolean scroll_form,GdauiDataProxyInfoFlag flags)874 ui_formgrid_new (GdaDataModel *model, gboolean scroll_form, GdauiDataProxyInfoFlag flags)
875 {
876 UiFormGrid *formgrid;
877 GdaDataProxy *proxy;
878
879 g_return_val_if_fail (!model || GDA_IS_DATA_MODEL (model), NULL);
880
881 formgrid = (UiFormGrid *) g_object_new (UI_TYPE_FORMGRID, "scroll-form", scroll_form, NULL);
882 formgrid->priv->flags = flags;
883
884 /* a raw form and a raw grid for the same proxy */
885 g_object_set (formgrid->priv->raw_grid, "model", model, NULL);
886 proxy = gdaui_data_proxy_get_proxy (GDAUI_DATA_PROXY (formgrid->priv->raw_grid));
887 g_object_set (formgrid->priv->raw_form, "model", proxy, NULL);
888 gdaui_data_proxy_set_write_mode (GDAUI_DATA_PROXY (formgrid->priv->raw_form),
889 GDAUI_DATA_PROXY_WRITE_ON_DEMAND);
890 g_object_set (G_OBJECT (formgrid->priv->info),
891 "flags", formgrid->priv->flags | GRID_FLAGS, NULL);
892
893 g_signal_connect (formgrid->priv->raw_grid, "proxy-changed",
894 G_CALLBACK (proxy_changed_cb), formgrid);
895
896 /* no more than 300 rows at a time */
897 if (model) {
898 gda_data_proxy_set_sample_size (proxy, 300);
899 if (flags & GDAUI_DATA_PROXY_INFO_ROW_MODIFY_BUTTONS)
900 g_object_set (G_OBJECT (formgrid), "compute-mod-statements", TRUE, NULL);
901 }
902
903
904 return (GtkWidget *) formgrid;
905 }
906
907 static void
handle_user_prefs_for_sql_statement(UiFormGrid * formgrid,BrowserConnection * bcnc,GdaSqlStatement * sqlst)908 handle_user_prefs_for_sql_statement (UiFormGrid *formgrid, BrowserConnection *bcnc,
909 GdaSqlStatement *sqlst)
910 {
911 g_assert (sqlst);
912 if (sqlst->stmt_type == GDA_SQL_STATEMENT_COMPOUND) {
913 GdaSqlStatementCompound *comp;
914 GSList *list;
915 comp = (GdaSqlStatementCompound*) sqlst->contents;
916 for (list = comp->stmt_list; list; list = list->next)
917 handle_user_prefs_for_sql_statement (formgrid, bcnc,
918 (GdaSqlStatement *) list->data);
919 }
920 else {
921 GdaSet *set;
922 set = (GdaSet*) ui_formgrid_get_form_data_set (UI_FORMGRID (formgrid));
923
924 GdaSqlStatementSelect *sel;
925 GSList *list;
926 gint pos;
927 sel = (GdaSqlStatementSelect*) sqlst->contents;
928 for (pos = 0, list = sel->expr_list; list; pos ++, list = list->next) {
929 GdaSqlSelectField *field = (GdaSqlSelectField*) list->data;
930 if (! field->validity_meta_object ||
931 (field->validity_meta_object->obj_type != GDA_META_DB_TABLE) ||
932 !field->validity_meta_table_column)
933 continue;
934
935 gchar *plugin;
936 plugin = browser_connection_get_table_column_attribute (bcnc,
937 GDA_META_TABLE (field->validity_meta_object),
938 field->validity_meta_table_column,
939 BROWSER_CONNECTION_COLUMN_PLUGIN, NULL);
940 if (!plugin)
941 continue;
942
943 GdaHolder *holder;
944 holder = gda_set_get_nth_holder (set, pos);
945 if (holder) {
946 GValue *value;
947 value = gda_value_new_from_string (plugin, G_TYPE_STRING);
948 gda_holder_set_attribute_static (holder, GDAUI_ATTRIBUTE_PLUGIN, value);
949 gda_value_free (value);
950 }
951 g_free (plugin);
952 }
953 }
954 }
955
956 /**
957 * ui_formgrid_handle_user_prefs
958 * @formgrid: a #UiFormGrid widget
959 * @bcnc: (allow-none): a #BrowserConnection, or %NULL to let @formgrid determine it itself
960 * @stmt: the #GdaStatement which has been executed to produce the #GdaDataModel displayed in @formgrid
961 *
962 * Takes into account the UI preferences of the user
963 */
964 void
ui_formgrid_handle_user_prefs(UiFormGrid * formgrid,BrowserConnection * bcnc,GdaStatement * stmt)965 ui_formgrid_handle_user_prefs (UiFormGrid *formgrid, BrowserConnection *bcnc, GdaStatement *stmt)
966 {
967 g_return_if_fail (UI_IS_FORMGRID (formgrid));
968 if (bcnc)
969 g_return_if_fail (BROWSER_IS_CONNECTION (bcnc));
970 else {
971 bcnc = get_browser_connection (formgrid);
972 if (!bcnc)
973 return;
974 }
975 if (stmt)
976 g_return_if_fail (GDA_IS_STATEMENT (stmt));
977 else
978 return;
979
980 GdaSqlStatement *sqlst;
981 g_object_get ((GObject*) stmt, "structure", &sqlst, NULL);
982 if (!sqlst)
983 return;
984
985 GError *lerror = NULL;
986 if (((sqlst->stmt_type != GDA_SQL_STATEMENT_SELECT) &&
987 (sqlst->stmt_type != GDA_SQL_STATEMENT_COMPOUND)) ||
988 !browser_connection_normalize_sql_statement (bcnc, sqlst, &lerror)) {
989 if (lerror)
990 g_print ("[%s]\n", lerror->message);
991 goto out;
992 }
993
994 handle_user_prefs_for_sql_statement (formgrid, bcnc, sqlst);
995 out:
996 gda_sql_statement_free (sqlst);
997 }
998
999
1000
1001 static void
ui_formgrid_set_property(GObject * object,guint param_id,G_GNUC_UNUSED const GValue * value,GParamSpec * pspec)1002 ui_formgrid_set_property (GObject *object,
1003 guint param_id,
1004 G_GNUC_UNUSED const GValue *value,
1005 GParamSpec *pspec)
1006 {
1007 UiFormGrid *formgrid;
1008
1009 formgrid = UI_FORMGRID (object);
1010
1011 switch (param_id) {
1012 case PROP_SCROLL_FORM:
1013 formgrid->priv->scroll_form = g_value_get_boolean (value);
1014 break;
1015 case PROP_AUTOMOD:
1016 formgrid->priv->compute_mod_stmt = g_value_get_boolean (value);
1017 if (formgrid->priv->mod_stmt_auto_computed && !formgrid->priv->compute_mod_stmt) {
1018 /* clean up the mod stmt */
1019 ModType mod;
1020 GdaDataModel *model;
1021 g_object_get (formgrid->priv->raw_grid, "model", &model, NULL);
1022 for (mod = MOD_INSERT; mod < MOD_LAST; mod++) {
1023 if (! formgrid->priv->mod_stmt[mod])
1024 continue;
1025 g_object_unref (formgrid->priv->mod_stmt [mod]);
1026 }
1027 g_object_set (model, "delete-stmt", NULL,
1028 "insert-stmt", NULL, NULL,
1029 "update-stmt", NULL, NULL);
1030 g_object_unref (model);
1031 formgrid->priv->mod_stmt_auto_computed = FALSE;
1032 }
1033 else if (!formgrid->priv->mod_stmt_auto_computed && formgrid->priv->compute_mod_stmt) {
1034 GdaDataModel *model;
1035 g_object_get (formgrid->priv->raw_grid, "model", &model, NULL);
1036 compute_modification_statements (formgrid, model);
1037 g_object_unref (model);
1038 }
1039 break;
1040 default:
1041 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
1042 break;
1043 }
1044 }
1045
1046 static void
ui_formgrid_get_property(GObject * object,guint param_id,GValue * value,GParamSpec * pspec)1047 ui_formgrid_get_property (GObject *object,
1048 guint param_id,
1049 GValue *value,
1050 GParamSpec *pspec)
1051 {
1052 UiFormGrid *formgrid;
1053
1054 formgrid = UI_FORMGRID (object);
1055
1056 switch (param_id) {
1057 case PROP_RAW_GRID:
1058 g_value_set_object (value, formgrid->priv->raw_grid);
1059 break;
1060 case PROP_RAW_FORM:
1061 g_value_set_object (value, formgrid->priv->raw_form);
1062 break;
1063 case PROP_INFO:
1064 g_value_set_object (value, formgrid->priv->info);
1065 break;
1066 case PROP_AUTOMOD:
1067 g_value_set_boolean (value, formgrid->priv->compute_mod_stmt);
1068 break;
1069 default:
1070 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
1071 break;
1072 }
1073 }
1074
1075 /**
1076 * ui_formgrid_get_selection
1077 * @formgrid: a #UiFormGrid widget
1078 *
1079 * Returns the list of the currently selected rows in a #UiFormGrid widget.
1080 * The returned value is a list of integers, which represent each of the selected rows.
1081 *
1082 * If new rows have been inserted, then those new rows will have a row number equal to -1.
1083 * This function is a wrapper around the gdaui_raw_grid_get_selection() function.
1084 *
1085 * Returns: a new array, should be freed (by calling g_array_free() and passing %TRUE as last argument) when no longer needed.
1086 */
1087 GArray *
ui_formgrid_get_selection(UiFormGrid * formgrid)1088 ui_formgrid_get_selection (UiFormGrid *formgrid)
1089 {
1090 g_return_val_if_fail (UI_IS_FORMGRID (formgrid), NULL);
1091 g_return_val_if_fail (formgrid->priv, NULL);
1092
1093 return gdaui_data_selector_get_selected_rows (GDAUI_DATA_SELECTOR (formgrid->priv->raw_grid));
1094 }
1095
1096 /**
1097 * ui_formgrid_get_form_data_set
1098 */
1099 GdaDataModelIter *
ui_formgrid_get_form_data_set(UiFormGrid * formgrid)1100 ui_formgrid_get_form_data_set (UiFormGrid *formgrid)
1101 {
1102 g_return_val_if_fail (UI_IS_FORMGRID (formgrid), NULL);
1103 g_return_val_if_fail (formgrid->priv, NULL);
1104
1105 return gdaui_data_selector_get_data_set (GDAUI_DATA_SELECTOR (formgrid->priv->raw_form));
1106 }
1107
1108 /**
1109 * ui_formgrid_get_grid_data_set
1110 */
1111 GdaDataModelIter *
ui_formgrid_get_grid_data_set(UiFormGrid * formgrid)1112 ui_formgrid_get_grid_data_set (UiFormGrid *formgrid)
1113 {
1114 g_return_val_if_fail (UI_IS_FORMGRID (formgrid), NULL);
1115 g_return_val_if_fail (formgrid->priv, NULL);
1116
1117 return gdaui_data_selector_get_data_set (GDAUI_DATA_SELECTOR (formgrid->priv->raw_grid));
1118 }
1119
1120
1121 /**
1122 * ui_formgrid_set_sample_size
1123 * @formgrid: a #UiFormGrid widget
1124 * @sample_size: the sample size
1125 *
1126 * Set the size of the sample displayed in @formgrid, see gdaui_raw_grid_set_sample_size()
1127 */
1128 void
ui_formgrid_set_sample_size(UiFormGrid * formgrid,gint sample_size)1129 ui_formgrid_set_sample_size (UiFormGrid *formgrid, gint sample_size)
1130 {
1131 g_return_if_fail (UI_IS_FORMGRID (formgrid));
1132 g_return_if_fail (formgrid->priv);
1133
1134 gdaui_raw_grid_set_sample_size (GDAUI_RAW_GRID (formgrid->priv->raw_grid), sample_size);
1135 }
1136
1137 /**
1138 * ui_formgrid_get_grid_widget
1139 * @formgrid: a #UiFormGrid widget
1140 *
1141 * Returns: the #GdauiRawGrid embedded in @formgrid
1142 */
1143 GdauiRawGrid *
ui_formgrid_get_grid_widget(UiFormGrid * formgrid)1144 ui_formgrid_get_grid_widget (UiFormGrid *formgrid)
1145 {
1146 g_return_val_if_fail (UI_IS_FORMGRID (formgrid), NULL);
1147 g_return_val_if_fail (formgrid->priv, NULL);
1148
1149 return GDAUI_RAW_GRID (formgrid->priv->raw_grid);
1150 }
1151
1152 /**
1153 * ui_formgrid_set_connection
1154 * @formgrid: a #UiFormGrid widget
1155 * @bcnc: (allow-none): a #BrowserConnection, or %NULL
1156 *
1157 * Tells @formgrid to use @bcnc as connection when actions have to be executed
1158 */
1159 void
ui_formgrid_set_connection(UiFormGrid * formgrid,BrowserConnection * bcnc)1160 ui_formgrid_set_connection (UiFormGrid *formgrid, BrowserConnection *bcnc)
1161 {
1162 g_return_if_fail (UI_IS_FORMGRID (formgrid));
1163 g_return_if_fail (!bcnc || BROWSER_IS_CONNECTION (bcnc));
1164
1165 if (formgrid->priv->bcnc) {
1166 g_object_unref (formgrid->priv->bcnc);
1167 formgrid->priv->bcnc = NULL;
1168 }
1169 if (bcnc)
1170 formgrid->priv->bcnc = g_object_ref (bcnc);
1171 }
1172
1173 static void
compute_modification_statements(UiFormGrid * formgrid,GdaDataModel * model)1174 compute_modification_statements (UiFormGrid *formgrid, GdaDataModel *model)
1175 {
1176 /* clear existing modification statements */
1177 ModType mod;
1178 for (mod = MOD_INSERT; mod < MOD_LAST; mod++) {
1179 if (formgrid->priv->mod_stmt[mod]) {
1180 g_object_unref (formgrid->priv->mod_stmt[mod]);
1181 formgrid->priv->mod_stmt[mod] = NULL;
1182 }
1183 }
1184
1185 if (!model || !GDA_IS_DATA_SELECT (model))
1186 return;
1187
1188 if (! formgrid->priv->compute_mod_stmt)
1189 return;
1190
1191 gda_data_select_compute_modification_statements_ext (GDA_DATA_SELECT (model),
1192 GDA_DATA_SELECT_COND_ALL_COLUMNS, NULL);
1193
1194 formgrid->priv->mod_stmt_auto_computed = TRUE;
1195 g_object_get (model,
1196 "insert-stmt", &formgrid->priv->mod_stmt[MOD_INSERT],
1197 "update-stmt", &formgrid->priv->mod_stmt[MOD_UPDATE],
1198 "delete-stmt", &formgrid->priv->mod_stmt[MOD_DELETE], NULL);
1199
1200 /*
1201 for (mod = MOD_INSERT; mod < MOD_LAST; mod++) {
1202 if (formgrid->priv->mod_stmt[mod]) {
1203 gchar *sql;
1204 GError *lerror = NULL;
1205 sql = gda_statement_to_sql_extended (formgrid->priv->mod_stmt[mod], NULL, NULL,
1206 GDA_STATEMENT_SQL_PARAMS_LONG, NULL, &lerror);
1207 g_print ("STMT[%d] = [%s]", mod, sql ? sql : "ERR");
1208 if (!sql)
1209 g_print (" --- %s", lerror && lerror->message ? lerror->message : "No detail");
1210 g_clear_error (&lerror);
1211 g_print ("\n");
1212 g_free (sql);
1213 }
1214 else
1215 g_print ("STMT[%d] = ---\n", mod);
1216 }
1217 */
1218 }
1219