[libgda/gtk3] GdaBrowser: enable using defined actions



commit 6e2bc1b359590f489b018bcf83116fccc58b19d1
Author: Vivien Malerba <malerba gnome-db org>
Date:   Tue Jan 18 20:45:35 2011 +0100

    GdaBrowser: enable using defined actions

 tools/browser/Makefile.am                          |    1 +
 tools/browser/browser-connection.h                 |    4 +-
 tools/browser/browser-favorites.c                  |  154 +++++++++++-
 tools/browser/browser-favorites.h                  |   16 +-
 tools/browser/common/ui-formgrid.c                 |  270 ++++++++++++++++++--
 tools/browser/common/ui-formgrid.h                 |    4 +-
 tools/browser/doc/tmpl/browser-favorites.sgml      |    1 +
 tools/browser/gda-browser-action.png               |  Bin 0 -> 656 bytes
 tools/browser/mgr-favorites.c                      |   37 +++-
 tools/browser/query-exec/query-favorite-selector.c |   24 +-
 tools/browser/support.c                            |   43 +++
 tools/browser/support.h                            |    2 +
 12 files changed, 512 insertions(+), 44 deletions(-)
---
diff --git a/tools/browser/Makefile.am b/tools/browser/Makefile.am
index f12866a..1e9e3a1 100644
--- a/tools/browser/Makefile.am
+++ b/tools/browser/Makefile.am
@@ -151,6 +151,7 @@ icons_DATA= \
 	gda-browser-reference.png \
 	gda-browser-diagram.png \
 	gda-browser-query.png \
+	gda-browser-action.png \
 	gda-browser-form.png \
 	gda-browser-grid.png \
 	gda-browser-menu-ind.png
diff --git a/tools/browser/browser-connection.h b/tools/browser/browser-connection.h
index dc078d2..603ec19 100644
--- a/tools/browser/browser-connection.h
+++ b/tools/browser/browser-connection.h
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2009 Vivien Malerba
+ * Copyright (C) 2009 - 2011 Vivien Malerba
  *
  * This Library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public License as
@@ -101,6 +101,8 @@ gboolean            browser_connection_check_sql_statement_validify (BrowserConn
  *
  * Callback function called by browser_connection_execute_statement_cb(). If you need to keep
  * some of the arguments for a later usage, you need to ref/copy them.
+ *
+ * None of the passed arguments must not be modified
  */
 typedef void (*BrowserConnectionExecuteCallback) (BrowserConnection *bcnc,
 						  guint exec_id,
diff --git a/tools/browser/browser-favorites.c b/tools/browser/browser-favorites.c
index 7c5b2e5..d90587f 100644
--- a/tools/browser/browser-favorites.c
+++ b/tools/browser/browser-favorites.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 Vivien Malerba
+ * Copyright (C) 2009 - 2011 Vivien Malerba
  *
  * This Library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public License as
@@ -24,6 +24,7 @@
 #include "support.h"
 #include "marshal.h"
 #include <libgda/gda-sql-builder.h>
+#include <sql-parser/gda-sql-parser.h>
 
 struct _BrowserFavoritesPrivate {
 	GdaMetaStore  *store;
@@ -1150,3 +1151,154 @@ browser_favorites_get (BrowserFavorites *bfav, gint fav_id,
 	g_object_unref (G_OBJECT (model));
 	return retval;
 }
+
+static gint
+actions_sort_func (BrowserFavoriteAction *act1, BrowserFavoriteAction *act2)
+{
+	return act2->nb_bound - act1->nb_bound;
+}
+
+/**
+ * browser_favorites_get_actions
+ * @bfav: a #BrowserFavorites
+ * @bcnc: a #BrowserConnection
+ * @set: a #GdaSet
+ *
+ * Get a list of #BrowserFavoriteAction which can be executed with the data in @set.
+ *
+ * Returns: a new list of #BrowserFavoriteAction, free list with browser_favorites_free_actions()
+ */
+GSList *
+browser_favorites_get_actions (BrowserFavorites *bfav, BrowserConnection *bcnc, GdaSet *set)
+{
+	GSList *fav_list, *list, *retlist = NULL;
+	g_return_val_if_fail (BROWSER_IS_FAVORITES (bfav), NULL);
+	g_return_val_if_fail (BROWSER_IS_CONNECTION (bcnc), NULL);
+	g_return_val_if_fail (!set || GDA_IS_SET (set), NULL);
+
+	fav_list = browser_favorites_list (bfav, 0, BROWSER_FAVORITES_ACTIONS, -1, NULL);
+	if (! fav_list)
+		return NULL;
+
+	for (list = fav_list; list; list = list->next) {
+		BrowserFavoritesAttributes *fa = (BrowserFavoritesAttributes*) list->data;
+		BrowserFavoritesAttributes qfa;
+		if (! g_str_has_prefix (fa->contents, "QUERY")) {
+			g_warning ("Malformed action contents '%s', please report error to "
+				   "http://bugzilla.gnome.org/ for the \"libgda\" product",
+				   fa->contents);
+			continue;
+		}
+		if (browser_favorites_get (bfav, atoi (fa->contents + 5), &qfa, NULL)) {
+			GdaSet *params;
+			GSList *plist;
+			GdaBatch *batch;
+			GdaStatement *stmt = NULL;
+			GdaSqlParser *parser;
+			const gchar *remain;
+			const GSList *stmt_list;
+			gint nb_bound = 0;
+
+			parser = browser_connection_create_parser (bcnc);
+			batch = gda_sql_parser_parse_string_as_batch (parser, qfa.contents, &remain, NULL);
+			g_object_unref (parser);
+			if (!batch) {
+				browser_favorites_reset_attributes (&qfa);
+				continue;
+			}
+			stmt_list = gda_batch_get_statements (batch);
+			for (plist = (GSList*) stmt_list; plist; plist = plist->next) {
+				if (! gda_statement_is_useless (GDA_STATEMENT (plist->data))) {
+					if (stmt)
+						break;
+					else
+						stmt = g_object_ref (GDA_STATEMENT (plist->data));
+				}
+			}
+			g_object_unref (batch);
+			if (!stmt || plist) {
+				browser_favorites_reset_attributes (&qfa);
+				continue;
+			}
+			
+			if (! gda_statement_get_parameters (stmt, &params, NULL) || !params) {
+				g_object_unref (stmt);
+				browser_favorites_reset_attributes (&qfa);
+				continue;
+			}
+			browser_connection_define_ui_plugins_for_stmt (bcnc, stmt, params);
+			
+			for (plist = params->holders; plist; plist = plist->next) {
+				/* try to find holder in @set */
+				GdaHolder *req_holder, *in_holder;
+				req_holder = GDA_HOLDER (plist->data);
+				in_holder = gda_set_get_holder (set, gda_holder_get_id (req_holder));
+				if (in_holder && gda_holder_set_bind (req_holder, in_holder, NULL)) {
+					/* bound this holder to the oune found */
+					nb_bound++;
+				}
+			}
+
+			if (nb_bound > 0) {
+				/* at least 1 holder was found=> keep the action */
+				BrowserFavoriteAction *act;
+				act = g_new0 (BrowserFavoriteAction, 1);
+				retlist = g_slist_insert_sorted (retlist, act,
+								 (GCompareFunc) actions_sort_func);
+				act->params = g_object_ref (params);
+				act->id = fa->id;
+				act->name = g_strdup (fa->name);
+				act->stmt = g_object_ref (stmt);
+				act->nb_bound = nb_bound;
+
+				/*g_print ("Action identified: ID=%d Bound=%d name=[%s] SQL=[%s]\n",
+				  act->id, act->nb_bound,
+				  act->name, qfa.contents);*/
+			}
+
+			g_object_unref (stmt);
+			g_object_unref (params);
+			browser_favorites_reset_attributes (&qfa);
+		}
+	}
+	browser_favorites_free_list (fav_list);
+
+	return retlist;
+}
+
+/**
+ * browser_favorites_free_action
+ * @action: a #BrowserFavoriteAction, or %NULL
+ *
+ * Frees @action
+ */
+void
+browser_favorites_free_action (BrowserFavoriteAction *action)
+{
+	if (! action)
+		return;
+	g_free (action->name);
+	if (action->stmt)
+		g_object_unref (action->stmt);
+	if (action->params)
+		g_object_unref (action->params);
+	g_free (action);
+}
+
+/**
+ * browser_favorites_free_actions_list
+ * @actions_list: a list of #BrowserFavoriteAction, or %NULL
+ *
+ * Free a list of #BrowserFavoriteAction (frees the list and each #BrowserFavoriteAction)
+ */
+void
+browser_favorites_free_actions_list (GSList *actions_list)
+{
+	GSList *list;
+	if (!actions_list)
+		return;
+
+	for (list = actions_list; list; list = list->next)
+		browser_favorites_free_action ((BrowserFavoriteAction*) list->data);
+	g_slist_free (actions_list);
+}
diff --git a/tools/browser/browser-favorites.h b/tools/browser/browser-favorites.h
index 92985e1..65e3756 100644
--- a/tools/browser/browser-favorites.h
+++ b/tools/browser/browser-favorites.h
@@ -1,5 +1,5 @@
 /* 
- * Copyright (C) 2009 Vivien Malerba
+ * Copyright (C) 2009 - 2011 Vivien Malerba
  *
  * This Library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public License as
@@ -101,6 +101,20 @@ gint                browser_favorites_find         (BrowserFavorites *bfav, guin
 						    BrowserFavoritesAttributes *out_fav, GError **error);
 gboolean            browser_favorites_get          (BrowserFavorites *bfav, gint fav_id,
 						    BrowserFavoritesAttributes *out_fav, GError **error);
+
+typedef struct {
+	gint                  id;
+	gchar                *name;
+	GdaStatement         *stmt;
+	GdaSet               *params;
+	gint                  nb_bound; /* number of GdaHolders in @params which are bound 
+					 * to another GdaHolder */
+} BrowserFavoriteAction;
+
+GSList             *browser_favorites_get_actions  (BrowserFavorites *bfav, BrowserConnection *bcnc, GdaSet *set);
+void                browser_favorites_free_action  (BrowserFavoriteAction *action);
+void                browser_favorites_free_actions_list (GSList *actions_list);
+
 G_END_DECLS
 
 #endif
diff --git a/tools/browser/common/ui-formgrid.c b/tools/browser/common/ui-formgrid.c
index 4f4ee7e..378a7fa 100644
--- a/tools/browser/common/ui-formgrid.c
+++ b/tools/browser/common/ui-formgrid.c
@@ -1,6 +1,6 @@
 /* ui-formgrid.c
  *
- * Copyright (C) 2010 Vivien Malerba
+ * Copyright (C) 2010 - 2011 Vivien Malerba
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -26,18 +26,21 @@
 #include <libgda-ui/gdaui-raw-form.h>
 #include <libgda-ui/gdaui-data-selector.h>
 #include "../support.h"
+#include "../browser-window.h"
 
 static void ui_formgrid_class_init (UiFormGridClass * class);
 static void ui_formgrid_init (UiFormGrid *wid);
+static void ui_formgrid_dispose (GObject *object);
 
 static void ui_formgrid_set_property (GObject *object,
-					    guint param_id,
-					    const GValue *value,
-					    GParamSpec *pspec);
+				      guint param_id,
+				      const GValue *value,
+				      GParamSpec *pspec);
 static void ui_formgrid_get_property (GObject *object,
-					    guint param_id,
-					    GValue *value,
-					    GParamSpec *pspec);
+				      guint param_id,
+				      GValue *value,
+				      GParamSpec *pspec);
+static BrowserConnection *get_browser_connection (UiFormGrid *formgrid);
 
 struct _UiFormGridPriv
 {
@@ -47,6 +50,8 @@ struct _UiFormGridPriv
 	GtkWidget   *raw_grid;
 	GtkWidget   *info;
 	GdauiDataProxyInfoFlag flags;
+	
+	BrowserConnection *bcnc;
 };
 
 /* get a pointer to the parents to be able to call their destructor */
@@ -88,9 +93,10 @@ ui_formgrid_get_type (void)
 static void
 ui_formgrid_class_init (UiFormGridClass *class)
 {
-	GObjectClass   *object_class = G_OBJECT_CLASS (class);
+	GObjectClass *object_class = G_OBJECT_CLASS (class);
 	
 	parent_class = g_type_class_peek_parent (class);
+	object_class->dispose = ui_formgrid_dispose;
 
 	/* Properties */
         object_class->set_property = ui_formgrid_set_property;
@@ -109,7 +115,26 @@ ui_formgrid_class_init (UiFormGridClass *class)
 							      G_PARAM_READABLE));
 }
 
+static void
+ui_formgrid_dispose (GObject *object)
+{
+        UiFormGrid *formgrid;
+
+        formgrid = UI_FORMGRID (object);
+        if (formgrid->priv) {
+                if (formgrid->priv->bcnc)
+                        g_object_unref (formgrid->priv->bcnc);
+
+                g_free (formgrid->priv);
+                formgrid->priv = NULL;
+        }
+
+        /* parent class */
+        parent_class->dispose (object);
+}
+
 static void form_grid_toggled_cb (GtkToggleButton *button, UiFormGrid *formgrid);
+static void raw_grid_populate_popup_cb (GdauiRawGrid *gdauirawgrid, GtkMenu *menu, UiFormGrid *formgrid);
 
 static void
 ui_formgrid_init (UiFormGrid *formgrid)
@@ -121,6 +146,7 @@ ui_formgrid_init (UiFormGrid *formgrid)
 	formgrid->priv->raw_grid = NULL;
 	formgrid->priv->info = NULL;
 	formgrid->priv->flags = GDAUI_DATA_PROXY_INFO_CURRENT_ROW;
+	formgrid->priv->bcnc = NULL;
 
 	/* notebook */
 	formgrid->priv->nb = gtk_notebook_new ();
@@ -140,6 +166,8 @@ ui_formgrid_init (UiFormGrid *formgrid)
 	gdaui_data_proxy_column_show_actions (GDAUI_DATA_PROXY (formgrid->priv->raw_grid), -1, FALSE);
 	gtk_container_add (GTK_CONTAINER (sw), formgrid->priv->raw_grid);
 	gtk_widget_show (formgrid->priv->raw_grid);
+	g_signal_connect (formgrid->priv->raw_grid, "populate-popup",
+			  G_CALLBACK (raw_grid_populate_popup_cb), formgrid);
 
 	/* form on the 2nd page of the notebook */
 	formgrid->priv->sw = gtk_scrolled_window_new (NULL, NULL);
@@ -191,8 +219,8 @@ form_grid_toggled_cb (GtkToggleButton *button, UiFormGrid *formgrid)
 			      "flags", formgrid->priv->flags | GDAUI_DATA_PROXY_INFO_CURRENT_ROW |
 			      GDAUI_DATA_PROXY_INFO_ROW_MOVE_BUTTONS
 			      /*GDAUI_DATA_PROXY_INFO_CURRENT_ROW |
-			      GDAUI_DATA_PROXY_INFO_ROW_MODIFY_BUTTONS |
-			      GDAUI_DATA_PROXY_INFO_ROW_MOVE_BUTTONS*/, NULL);
+				GDAUI_DATA_PROXY_INFO_ROW_MODIFY_BUTTONS |
+				GDAUI_DATA_PROXY_INFO_ROW_MOVE_BUTTONS*/, NULL);
 
 		GdkPixbuf *pixbuf = browser_get_pixbuf_icon (BROWSER_ICON_FORM);
 		gtk_button_set_image (GTK_BUTTON (button), gtk_image_new_from_pixbuf (pixbuf));
@@ -209,8 +237,8 @@ form_grid_toggled_cb (GtkToggleButton *button, UiFormGrid *formgrid)
 			      "flags", formgrid->priv->flags | GDAUI_DATA_PROXY_INFO_CURRENT_ROW |
 			      GDAUI_DATA_PROXY_INFO_CHUNCK_CHANGE_BUTTONS
 			      /*GDAUI_DATA_PROXY_INFO_CURRENT_ROW |
-			      GDAUI_DATA_PROXY_INFO_ROW_MODIFY_BUTTONS |
-			      GDAUI_DATA_PROXY_INFO_CHUNCK_CHANGE_BUTTONS*/, NULL);
+				GDAUI_DATA_PROXY_INFO_ROW_MODIFY_BUTTONS |
+				GDAUI_DATA_PROXY_INFO_CHUNCK_CHANGE_BUTTONS*/, NULL);
 
 		GdkPixbuf *pixbuf = browser_get_pixbuf_icon (BROWSER_ICON_GRID);
 		gtk_button_set_image (GTK_BUTTON (button), gtk_image_new_from_pixbuf (pixbuf));
@@ -223,6 +251,175 @@ form_grid_toggled_cb (GtkToggleButton *button, UiFormGrid *formgrid)
 	gda_data_model_iter_move_to_row (iter, row >= 0 ? row : 0);
 }
 
+static BrowserConnection *
+get_browser_connection (UiFormGrid *formgrid)
+{
+	if (formgrid->priv->bcnc)
+		return formgrid->priv->bcnc;
+	else {
+		GtkWidget *toplevel;
+		
+		toplevel = gtk_widget_get_toplevel (GTK_WIDGET (formgrid));
+		if (BROWSER_IS_WINDOW (toplevel))
+			return browser_window_get_connection (BROWSER_WINDOW (toplevel));
+	}
+	return NULL;
+}
+
+
+static void execute_action_mitem_cb (GtkMenuItem *menuitem, UiFormGrid *formgrid);
+
+static void
+raw_grid_populate_popup_cb (GdauiRawGrid *gdauirawgrid, GtkMenu *menu, UiFormGrid *formgrid)
+{
+	/* add actions to execute to menu */
+	GdaDataModelIter *iter;
+	GSList *actions_list, *list;
+	BrowserConnection *bcnc = NULL;
+
+	bcnc = get_browser_connection (formgrid);
+	if (!bcnc)
+		return;
+	
+	iter = gdaui_data_selector_get_data_set (GDAUI_DATA_SELECTOR (formgrid->priv->raw_grid));
+	actions_list = browser_favorites_get_actions (browser_connection_get_favorites (bcnc),
+						      bcnc, GDA_SET (iter));
+	if (! actions_list)
+		return;
+
+	GtkWidget *mitem, *submenu;
+	mitem = gtk_menu_item_new_with_label (_("Execute action"));
+	gtk_widget_show (mitem);
+	gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), mitem);
+
+	submenu = gtk_menu_new ();
+	gtk_menu_item_set_submenu (GTK_MENU_ITEM (mitem), submenu);
+	for (list = actions_list; list; list = list->next) {
+		BrowserFavoriteAction *act = (BrowserFavoriteAction*) list->data;
+		mitem = gtk_menu_item_new_with_label (act->name);
+		gtk_widget_show (mitem);
+		gtk_menu_shell_append (GTK_MENU_SHELL (submenu), mitem);
+		g_object_set_data_full (G_OBJECT (mitem), "action", act,
+					(GDestroyNotify) browser_favorites_free_action);
+		g_signal_connect (mitem, "activate",
+				  G_CALLBACK (execute_action_mitem_cb), formgrid);
+	}
+
+	g_slist_free (actions_list);
+}
+
+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,
+		       UiFormGrid *formgrid)
+{
+	GtkWidget *toplevel;
+	toplevel = gtk_widget_get_toplevel (GTK_WIDGET (formgrid));
+        if (error)
+                browser_show_error (GTK_WINDOW (toplevel),
+                                    _("Error executing query:\n%s"),
+                                    error->message ?
+                                    error->message : _("No detail"));
+	else if (out_result && GDA_IS_DATA_MODEL (out_result)) {
+		GtkWidget *dialog, *toplevel, *label, *fg;
+		GtkWidget *dcontents;
+		
+		gchar *tmp;
+		toplevel = gtk_widget_get_toplevel (GTK_WIDGET (formgrid));
+		dialog = gtk_dialog_new_with_buttons (_("Action executed"),
+						      GTK_WINDOW (toplevel),
+						      GTK_DIALOG_NO_SEPARATOR,
+						      GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, NULL);
+#if GTK_CHECK_VERSION(2,18,0)
+		dcontents = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+#else
+		dcontents = GTK_DIALOG (dialog)->vbox;
+#endif
+		gtk_box_set_spacing (GTK_BOX (dcontents), 5);
+		gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE, TRUE);
+		
+		tmp = g_strdup_printf ("<b>%s</b>", _("Action executed"));
+		label = gtk_label_new ("");
+		gtk_label_set_markup (GTK_LABEL (label), tmp);
+		g_free (tmp);
+		gtk_misc_set_alignment (GTK_MISC (label), 0., 0.);
+		gtk_box_pack_start (GTK_BOX (dcontents), label, FALSE, FALSE, 0);
+		
+		fg = ui_formgrid_new (GDA_DATA_MODEL (out_result),
+				      GDAUI_DATA_PROXY_INFO_CURRENT_ROW);
+		ui_formgrid_set_connection (UI_FORMGRID (fg), get_browser_connection (formgrid));
+
+		if (GDA_IS_DATA_SELECT (out_result)) {
+			GdaStatement *stmt;
+			g_object_get (G_OBJECT (out_result), "select-stmt", &stmt, NULL);
+			if (stmt) {
+				ui_formgrid_handle_user_prefs (UI_FORMGRID (fg), NULL, stmt);
+				g_object_unref (stmt);
+			}
+		}
+		gtk_box_pack_start (GTK_BOX (dcontents), fg, TRUE, TRUE, 0);
+		
+		gtk_window_set_default_size (GTK_WINDOW (dialog), 400, 600);
+		gtk_widget_show_all (dialog);
+		
+		g_signal_connect (dialog, "response",
+				  G_CALLBACK (gtk_widget_destroy), NULL);
+		g_signal_connect (dialog, "close",
+				  G_CALLBACK (gtk_widget_destroy), NULL);
+	}
+        else if (BROWSER_IS_WINDOW (toplevel)) {
+		browser_window_show_notice_printf (BROWSER_WINDOW (toplevel),
+						   GTK_MESSAGE_INFO,
+						   "ActionExecution",
+						   "%s", _("Action successfully executed"));
+	}
+	else
+		browser_show_message (GTK_WINDOW (toplevel),
+				      "%s", _("Action successfully executed"));
+}
+
+static void
+execute_action_mitem_cb (GtkMenuItem *menuitem, UiFormGrid *formgrid)
+{
+	BrowserFavoriteAction *act;
+	GtkWidget *dlg;
+	gchar *tmp;
+	gint response;
+	GtkWidget *toplevel;
+
+	act = (BrowserFavoriteAction*) g_object_get_data (G_OBJECT (menuitem), "action");
+	toplevel = gtk_widget_get_toplevel ((GtkWidget*) formgrid);
+	tmp = g_strdup_printf (_("Set or confirm the parameters to execute\n"
+				 "action '%s'"), act->name);
+	dlg = gdaui_basic_form_new_in_dialog (act->params,
+					      (GtkWindow*) toplevel,
+					      _("Execution of action"), tmp);
+	g_free (tmp);
+	response = gtk_dialog_run (GTK_DIALOG (dlg));
+	gtk_widget_destroy (dlg);
+	if (response == GTK_RESPONSE_ACCEPT) {
+                GError *lerror = NULL;
+		BrowserConnection *bcnc;
+		
+		bcnc = get_browser_connection (formgrid);
+		g_assert (bcnc);
+		
+                if (! browser_connection_execute_statement_cb (bcnc,
+                                                               act->stmt, act->params,
+                                                               GDA_STATEMENT_MODEL_RANDOM_ACCESS,
+                                                               FALSE,
+                                                               (BrowserConnectionExecuteCallback) statement_executed_cb,
+                                                               formgrid, &lerror)) {
+                        browser_show_error (GTK_WINDOW (toplevel),
+                                            _("Error executing query: %s"),
+                                            lerror && lerror->message ? lerror->message : _("No detail"));
+                        g_clear_error (&lerror);
+                }
+	}
+}
+
 /**
  * ui_formgrid_new
  * @model: a #GdaDataModel
@@ -261,7 +458,7 @@ ui_formgrid_new (GdaDataModel *model, GdauiDataProxyInfoFlag flags)
 /**
  * ui_formgrid_handle_user_prefs
  * @formgrid: a #UiFormGrid widget
- * @bcnc: a #BrowserConnection
+ * @bcnc: a #BrowserConnection, or %NULL to let @formgrid determine it itself
  * @stmt: the #GdaStatement which has been executed to produce the #GdaDataModel displayed in @formgrid
  *
  * Takes into account the UI preferences of the user
@@ -272,8 +469,11 @@ ui_formgrid_handle_user_prefs (UiFormGrid *formgrid, BrowserConnection *bcnc, Gd
 	g_return_if_fail (UI_IS_FORMGRID (formgrid));
 	if (bcnc)
 		g_return_if_fail (BROWSER_IS_CONNECTION (bcnc));
-	else
-		return;
+	else {
+		bcnc = get_browser_connection (formgrid);
+		if (!bcnc)
+			return;
+	}
 	if (stmt)
 		g_return_if_fail (GDA_IS_STATEMENT (stmt));
 	else
@@ -329,9 +529,9 @@ ui_formgrid_handle_user_prefs (UiFormGrid *formgrid, BrowserConnection *bcnc, Gd
 
 static void
 ui_formgrid_set_property (GObject *object,
-				guint param_id,
-				G_GNUC_UNUSED const GValue *value,
-				GParamSpec *pspec)
+			  guint param_id,
+			  G_GNUC_UNUSED const GValue *value,
+			  GParamSpec *pspec)
 {
 	UiFormGrid *formgrid;
 	
@@ -347,9 +547,9 @@ ui_formgrid_set_property (GObject *object,
 
 static void
 ui_formgrid_get_property (GObject *object,
-				guint param_id,
-				GValue *value,
-				GParamSpec *pspec)
+			  guint param_id,
+			  GValue *value,
+			  GParamSpec *pspec)
 {
 	UiFormGrid *formgrid;
 
@@ -420,9 +620,9 @@ ui_formgrid_get_grid_data_set (UiFormGrid *formgrid)
 /**
  * ui_formgrid_set_sample_size
  * @formgrid: a #UiFormGrid widget
- * @sample_size:
- *
+ * @sample_size: the sample size
  *
+ * Set the size of the sample displayed in @formgrid, see gdaui_raw_grid_set_sample_size()
  */
 void
 ui_formgrid_set_sample_size (UiFormGrid *formgrid, gint sample_size)
@@ -435,6 +635,9 @@ ui_formgrid_set_sample_size (UiFormGrid *formgrid, gint sample_size)
 
 /**
  * ui_formgrid_get_grid_widget
+ * @formgrid: a #UiFormGrid widget
+ *
+ * Returns: the #GdauiRawGrid embedded in @formgrid
  */
 GdauiRawGrid *
 ui_formgrid_get_grid_widget (UiFormGrid *formgrid)
@@ -444,3 +647,24 @@ ui_formgrid_get_grid_widget (UiFormGrid *formgrid)
 
 	return GDAUI_RAW_GRID (formgrid->priv->raw_grid);
 }
+
+/**
+ * ui_formgrid_set_connection
+ * @formgrid: a #UiFormGrid widget
+ * @bcnc: a #BrowserConnection, or %NULL
+ *
+ * Tells @formgrid to use @bcnc as connection when actions have to be executed
+ */
+void
+ui_formgrid_set_connection (UiFormGrid *formgrid, BrowserConnection *bcnc)
+{
+	g_return_if_fail (UI_IS_FORMGRID (formgrid));
+	g_return_if_fail (!bcnc || BROWSER_IS_CONNECTION (bcnc));
+
+	if (formgrid->priv->bcnc) {
+		g_object_unref (formgrid->priv->bcnc);
+		formgrid->priv->bcnc = NULL;
+	}
+	if (bcnc)
+		formgrid->priv->bcnc = g_object_ref (bcnc);
+}
diff --git a/tools/browser/common/ui-formgrid.h b/tools/browser/common/ui-formgrid.h
index fe69ff4..6216b45 100644
--- a/tools/browser/common/ui-formgrid.h
+++ b/tools/browser/common/ui-formgrid.h
@@ -1,6 +1,6 @@
 /* ui-formgrid.h
  *
- * Copyright (C) 2010 Vivien Malerba
+ * Copyright (C) 2010 - 2011 Vivien Malerba
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -68,6 +68,8 @@ GdaDataModelIter *ui_formgrid_get_grid_data_set   (UiFormGrid *formgrid);
 void              ui_formgrid_set_sample_size     (UiFormGrid *formgrid, gint sample_size);
 GdauiRawGrid     *ui_formgrid_get_grid_widget     (UiFormGrid *formgrid);
 
+void              ui_formgrid_set_connection      (UiFormGrid *formgrid, BrowserConnection *bcnc);
+
 G_END_DECLS
 
 #endif
diff --git a/tools/browser/doc/tmpl/browser-favorites.sgml b/tools/browser/doc/tmpl/browser-favorites.sgml
index 3fb1440..28c29b5 100644
--- a/tools/browser/doc/tmpl/browser-favorites.sgml
+++ b/tools/browser/doc/tmpl/browser-favorites.sgml
@@ -38,6 +38,7 @@ Favorites management
 @BROWSER_FAVORITES_DIAGRAMS: 
 @BROWSER_FAVORITES_QUERIES: 
 @BROWSER_FAVORITES_DATA_MANAGERS: 
+ BROWSER_FAVORITES_ACTIONS: 
 
 <!-- ##### MACRO BROWSER_FAVORITES_NB_TYPES ##### -->
 <para>
diff --git a/tools/browser/gda-browser-action.png b/tools/browser/gda-browser-action.png
new file mode 100644
index 0000000..c27565d
Binary files /dev/null and b/tools/browser/gda-browser-action.png differ
diff --git a/tools/browser/mgr-favorites.c b/tools/browser/mgr-favorites.c
index f16b584..52a796a 100644
--- a/tools/browser/mgr-favorites.c
+++ b/tools/browser/mgr-favorites.c
@@ -463,15 +463,38 @@ mgr_favorites_update_children (GdaTreeManager *manager, GdaTreeNode *node, const
 									  MGR_FAVORITES_POSITION_ATT_NAME,
 									  av, NULL);
 					gda_value_free (av);
+				}
 
-					/* icon */
-					GdkPixbuf *pixbuf;
-					pixbuf = browser_get_pixbuf_icon (BROWSER_ICON_QUERY);
-					av = gda_value_new (G_TYPE_OBJECT);
-					g_value_set_object (av, pixbuf);
-					gda_tree_node_set_node_attribute (snode, "icon", av, NULL);
-					gda_value_free (av);
+				/* is action */
+				gboolean is_action = FALSE;
+				GSList *favlist;
+				GdkPixbuf *pixbuf;
+				favlist = browser_favorites_list (browser_connection_get_favorites (bcnc),
+								  0, BROWSER_FAVORITES_ACTIONS,
+								  -1, NULL);
+				if (favlist) {
+					gchar *tmp;
+					tmp = g_strdup_printf ("QUERY%d", fav->id);
+					GSList *list;
+					for (list = favlist; list; list = list->next) {
+						BrowserFavoritesAttributes *afav;
+						afav = (BrowserFavoritesAttributes*) list->data;
+						if (!strcmp (afav->contents, tmp)) {
+							is_action = TRUE;
+							break;
+						}
+					}
+					g_free (tmp);
+					browser_favorites_free_list (favlist);
 				}
+				if (is_action)
+					pixbuf = browser_get_pixbuf_icon (BROWSER_ICON_ACTION);
+				else
+					pixbuf = browser_get_pixbuf_icon (BROWSER_ICON_QUERY);
+				av = gda_value_new (G_TYPE_OBJECT);
+				g_value_set_object (av, pixbuf);
+				gda_tree_node_set_node_attribute (snode, "icon", av, NULL);
+				gda_value_free (av);
 
 				/* summary */
 				g_value_take_string ((av = gda_value_new (G_TYPE_STRING)),
diff --git a/tools/browser/query-exec/query-favorite-selector.c b/tools/browser/query-exec/query-favorite-selector.c
index ac23095..8b98ec0 100644
--- a/tools/browser/query-exec/query-favorite-selector.c
+++ b/tools/browser/query-exec/query-favorite-selector.c
@@ -271,13 +271,13 @@ prop_save_timeout (QueryFavoriteSelector *tsel)
 	g_free (fav.contents);
 
 	if (allok && (fav.id >= 0)) {
-		const gchar *action;
+		gboolean is_action;
 		gint qid = fav.id;
-		action = gtk_entry_get_text (GTK_ENTRY (tsel->priv->properties_action));
-		if (action && *action) {
+		is_action = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (tsel->priv->properties_action));
+		if (is_action) {
 			fav.id = -1;
 			fav.type = BROWSER_FAVORITES_ACTIONS;
-			fav.name = (gchar*) action;
+			fav.name = (gchar*) gtk_entry_get_text (GTK_ENTRY (tsel->priv->properties_name));
 			fav.descr = NULL;
 			fav.contents = g_strdup_printf ("QUERY%d", qid);
 			allok = browser_favorites_add (bfav, 0, &fav, -1,
@@ -365,9 +365,13 @@ properties_activated_cb (GtkMenuItem *mitem, QueryFavoriteSelector *tsel)
 		gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
 
 		label = gtk_label_new ("");
-		str = g_strdup_printf ("<b>%s:</b>", _("Action name"));
+		str = g_strdup_printf ("<b>%s:</b>", _("Is action"));
 		gtk_label_set_markup (GTK_LABEL (label), str);
 		g_free (str);
+		gtk_widget_set_tooltip_text (label, _("Check this option to make this favorite an action\n"
+						      "which can be proposed for execution from grids\n"
+						      "containing data. The parameters required to execute\n"
+						      "the query will be defined from the row selected in the grid"));
 		gtk_misc_get_alignment (GTK_MISC (label), NULL, &align);
 		gtk_misc_set_alignment (GTK_MISC (label), 0., align);
 		gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3, GTK_FILL, GTK_FILL, 0, 0);
@@ -386,10 +390,10 @@ properties_activated_cb (GtkMenuItem *mitem, QueryFavoriteSelector *tsel)
 		g_signal_connect (text, "changed",
 				  G_CALLBACK (property_changed_cb), tsel);
 
-		entry = gtk_entry_new ();
+		entry = gtk_check_button_new ();
 		gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 2, 3, GTK_EXPAND | GTK_FILL, GTK_SHRINK, 0, 0);
 		tsel->priv->properties_action = entry;
-		g_signal_connect (entry, "changed",
+		g_signal_connect (entry, "toggled",
 				  G_CALLBACK (property_changed_cb), tsel);
 
 		tsel->priv->popup_properties = pcont;
@@ -427,7 +431,7 @@ properties_activated_cb (GtkMenuItem *mitem, QueryFavoriteSelector *tsel)
 		/* action, if any */
 		g_signal_handlers_block_by_func (tsel->priv->properties_action,
 						 G_CALLBACK (property_changed_cb), tsel);
-		gtk_entry_set_text (GTK_ENTRY (tsel->priv->properties_action), "");
+		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tsel->priv->properties_action), FALSE);
 		if (tsel->priv->properties_id >= 0) {
 			gint id;
 			gchar *tmp;
@@ -437,7 +441,8 @@ properties_activated_cb (GtkMenuItem *mitem, QueryFavoriteSelector *tsel)
 			tmp = g_strdup_printf ("QUERY%d", tsel->priv->properties_id);
 			id = browser_favorites_find (bfav, 0, tmp, &fav, NULL);
 			if (id >= 0) {
-				gtk_entry_set_text (GTK_ENTRY (tsel->priv->properties_action), fav.name);
+				gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (tsel->priv->properties_action),
+							      TRUE);
 				/*g_print ("ACTION_USED %d: %s\n", fav.id, tmp);*/
 			}
 			g_free (tmp);
@@ -445,7 +450,6 @@ properties_activated_cb (GtkMenuItem *mitem, QueryFavoriteSelector *tsel)
 		g_signal_handlers_unblock_by_func (tsel->priv->properties_action,
 						   G_CALLBACK (property_changed_cb), tsel);
 
-
 		gtk_widget_show (tsel->priv->popup_properties);
 	}
 }
diff --git a/tools/browser/support.c b/tools/browser/support.c
index 820c966..be31cfc 100644
--- a/tools/browser/support.c
+++ b/tools/browser/support.c
@@ -159,6 +159,48 @@ browser_show_error (GtkWindow *parent, const gchar *format, ...)
         gtk_widget_destroy (dialog);
 }
 
+/**
+ * browser_show_message
+ * @parent: a #GtkWindow
+ * @format: printf() style format string
+ * @...: arguments for @format
+ *
+ * Displays an error message until the user aknowledges it. I @parent is a #BrowserWindow, then
+ * the error message is displayed in the window if possible
+ */
+void
+browser_show_message (GtkWindow *parent, const gchar *format, ...)
+{
+        va_list args;
+        gchar sz[2048];
+        GtkWidget *dialog;
+	gchar *tmp;
+
+        /* build the message string */
+        va_start (args, format);
+        vsnprintf (sz, sizeof (sz), format, args);
+        va_end (args);
+
+	if (BROWSER_IS_WINDOW (parent)) {
+		browser_window_show_notice (BROWSER_WINDOW (parent), GTK_MESSAGE_INFO,
+					    NULL, sz);
+		return;
+	}
+
+        /* create the error message dialog */
+	dialog = gtk_message_dialog_new (parent,
+					 GTK_DIALOG_DESTROY_WITH_PARENT |
+					 GTK_DIALOG_MODAL, GTK_MESSAGE_INFO,
+					 GTK_BUTTONS_CLOSE, NULL);
+	tmp = g_strdup_printf ("<span weight=\"bold\">%s</span>\n%s", _("Information:"), sz);
+	gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), tmp);
+	g_free (tmp);
+
+        gtk_widget_show_all (dialog);
+        gtk_dialog_run (GTK_DIALOG (dialog));
+        gtk_widget_destroy (dialog);
+}
+
 #ifdef HAVE_GDU
 /**
  * browser_show_help
@@ -339,6 +381,7 @@ browser_get_pixbuf_icon (BrowserIconType type)
 		"gda-browser-reference.png",
 		"gda-browser-diagram.png",
 		"gda-browser-query.png",
+		"gda-browser-action.png",
 		"gda-browser-grid.png",
 		"gda-browser-form.png",
 		"gda-browser-menu-ind.png",
diff --git a/tools/browser/support.h b/tools/browser/support.h
index 667739b..eec7e75 100644
--- a/tools/browser/support.h
+++ b/tools/browser/support.h
@@ -36,6 +36,7 @@ G_BEGIN_DECLS
 BrowserConnection *browser_connection_open (GError **error);
 gboolean           browser_connection_close (GtkWindow *parent, BrowserConnection *bcnc);
 void               browser_show_error (GtkWindow *parent, const gchar *format, ...);
+void               browser_show_message (GtkWindow *parent, const gchar *format, ...);
 #ifdef HAVE_GDU
 void               browser_show_help (GtkWindow *parent, const gchar *topic);
 #endif
@@ -72,6 +73,7 @@ typedef enum {
 	BROWSER_ICON_REFERENCE,
 	BROWSER_ICON_DIAGRAM,
 	BROWSER_ICON_QUERY,
+	BROWSER_ICON_ACTION,
 	
 	BROWSER_ICON_GRID,
 	BROWSER_ICON_FORM,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]