[libgda] GdaBrowser: added support to save queries as favorites



commit fd47ad490481b2c9decccf38a97757075a368fa5
Author: Vivien Malerba <malerba gnome-db org>
Date:   Fri Sep 18 20:35:07 2009 +0200

    GdaBrowser: added support to save queries as favorites

 tools/browser/Makefile.am                          |    3 +-
 tools/browser/browser-favorites.c                  |   15 +-
 tools/browser/browser-favorites.h                  |    5 +-
 tools/browser/decl.h                               |    1 +
 tools/browser/doc/tmpl/browser-connection.sgml     |    2 +
 tools/browser/doc/tmpl/browser-favorites.sgml      |    1 +
 tools/browser/gda-browser-query.png                |  Bin 0 -> 656 bytes
 tools/browser/mgr-favorites.c                      |   63 ++-
 tools/browser/mgr-favorites.h                      |    7 +-
 tools/browser/query-exec/Makefile.am               |   20 +-
 tools/browser/query-exec/marshal.list              |   26 +
 tools/browser/query-exec/query-console.c           |   45 ++
 tools/browser/query-exec/query-console.h           |    1 +
 tools/browser/query-exec/query-editor.c            |   22 +
 tools/browser/query-exec/query-editor.h            |    1 +
 tools/browser/query-exec/query-exec-perspective.c  |   31 +-
 tools/browser/query-exec/query-favorite-selector.c |  632 ++++++++++++++++++++
 tools/browser/query-exec/query-favorite-selector.h |   59 ++
 tools/browser/schema-browser/favorite-selector.c   |    3 +-
 tools/browser/support.c                            |    3 +-
 tools/browser/support.h                            |    1 +
 21 files changed, 915 insertions(+), 26 deletions(-)
---
diff --git a/tools/browser/Makefile.am b/tools/browser/Makefile.am
index b4e1d29..d8b19e5 100644
--- a/tools/browser/Makefile.am
+++ b/tools/browser/Makefile.am
@@ -136,7 +136,8 @@ icons_DATA= \
 	gda-browser-column-nn.png \
 	gda-browser-column-pk.png \
 	gda-browser-reference.png \
-	gda-browser-diagram.png
+	gda-browser-diagram.png \
+	gda-browser-query.png
 
 # app icon
 appiconsdir=$(datadir)/pixmaps
diff --git a/tools/browser/browser-favorites.c b/tools/browser/browser-favorites.c
index e721924..f574b88 100644
--- a/tools/browser/browser-favorites.c
+++ b/tools/browser/browser-favorites.c
@@ -207,8 +207,10 @@ favorite_type_to_string (BrowserFavoritesType type)
 		return "TABLE";
 	case BROWSER_FAVORITES_DIAGRAMS:
 		return "DIAGRAM";
+	case BROWSER_FAVORITES_QUERIES:
+		return "QUERY";
 	default:
-		g_warning ("Unknow type of favorite");
+		g_warning ("Unknown type of favorite");
 	}
 
 	return "";
@@ -221,8 +223,10 @@ favorite_string_to_type (const gchar *str)
 		return BROWSER_FAVORITES_TABLES;
 	else if (*str == 'D')
 		return BROWSER_FAVORITES_DIAGRAMS;
+	else if (*str == 'Q')
+		return BROWSER_FAVORITES_QUERIES;
 	else
-		g_warning ("Unknow type '%s' of favorite", str);
+		g_warning ("Unknown type '%s' of favorite", str);
 	return 0;
 }
 
@@ -860,6 +864,13 @@ browser_favorites_list (BrowserFavorites *bfav, guint session_id, BrowserFavorit
 	if (!stmt)
 		goto out;
 
+#ifdef GDA_DEBUG_NO
+	{
+		g_print ("=>%s\n", gda_statement_to_sql (stmt, NULL, NULL));
+	}
+#endif
+
+
 	params = gda_set_new_inline (2,
 				     "session", G_TYPE_INT, session_id,
 				     "okey", G_TYPE_INT, order_key);
diff --git a/tools/browser/browser-favorites.h b/tools/browser/browser-favorites.h
index 6609bec..e87d298 100644
--- a/tools/browser/browser-favorites.h
+++ b/tools/browser/browser-favorites.h
@@ -44,9 +44,10 @@ typedef struct _BrowserFavoritesPrivate BrowserFavoritesPrivate;
  */
 typedef enum {
         BROWSER_FAVORITES_TABLES   = 1 << 0,
-	BROWSER_FAVORITES_DIAGRAMS = 1 << 1
+	BROWSER_FAVORITES_DIAGRAMS = 1 << 1,
+	BROWSER_FAVORITES_QUERIES  = 1 << 2
 } BrowserFavoritesType;
-#define BROWSER_FAVORITES_NB_TYPES 2
+#define BROWSER_FAVORITES_NB_TYPES 3
 
 /**
  * BrowserFavoritesAttributes:
diff --git a/tools/browser/decl.h b/tools/browser/decl.h
index ceebe93..d93976e 100644
--- a/tools/browser/decl.h
+++ b/tools/browser/decl.h
@@ -45,6 +45,7 @@ typedef struct {
 #define BROWSER_PERSPECTIVE_FACTORY(x) ((BrowserPerspectiveFactory*)(x))
 
 #define ORDER_KEY_SCHEMA 1
+#define ORDER_KEY_QUERIES 2
 
 G_END_DECLS
 
diff --git a/tools/browser/doc/tmpl/browser-connection.sgml b/tools/browser/doc/tmpl/browser-connection.sgml
index 034fad7..b7352be 100644
--- a/tools/browser/doc/tmpl/browser-connection.sgml
+++ b/tools/browser/doc/tmpl/browser-connection.sgml
@@ -59,6 +59,8 @@ An opened connection
 
 </para>
 
+@:
+
 @browserconnection: the object which received the signal.
 
 <!-- ##### FUNCTION browser_connection_new ##### -->
diff --git a/tools/browser/doc/tmpl/browser-favorites.sgml b/tools/browser/doc/tmpl/browser-favorites.sgml
index 0bb3b00..5878868 100644
--- a/tools/browser/doc/tmpl/browser-favorites.sgml
+++ b/tools/browser/doc/tmpl/browser-favorites.sgml
@@ -33,6 +33,7 @@ Favorites management
 
 @BROWSER_FAVORITES_TABLES: 
 @BROWSER_FAVORITES_DIAGRAMS: 
+ BROWSER_FAVORITES_QUERIES: 
 
 <!-- ##### MACRO BROWSER_FAVORITES_NB_TYPES ##### -->
 <para>
diff --git a/tools/browser/gda-browser-query.png b/tools/browser/gda-browser-query.png
new file mode 100644
index 0000000..33da8cb
Binary files /dev/null and b/tools/browser/gda-browser-query.png differ
diff --git a/tools/browser/mgr-favorites.c b/tools/browser/mgr-favorites.c
index 40a4d17..6a171d6 100644
--- a/tools/browser/mgr-favorites.c
+++ b/tools/browser/mgr-favorites.c
@@ -29,6 +29,7 @@
 struct _MgrFavoritesPriv {
 	BrowserConnection    *bcnc;
 	BrowserFavoritesType  fav_type;
+	gint                  order_key;
 };
 
 static void mgr_favorites_class_init (MgrFavoritesClass *klass);
@@ -178,13 +179,14 @@ mgr_favorites_get_property (GObject *object,
  * mgr_favorites_new
  * @bcnc: a #BrowserConnection object
  * @type: the type of favorites to handle
+ * @order_key: ordering key, see browser_favorites_add()
  *
  * Creates a new #GdaTreeManager object which will add one tree node for each favorite of the @type type
  *
  * Returns: a new #GdaTreeManager object
  */
 GdaTreeManager*
-mgr_favorites_new (BrowserConnection *bcnc, BrowserFavoritesType type)
+mgr_favorites_new (BrowserConnection *bcnc, BrowserFavoritesType type, gint order_key)
 {
 	MgrFavorites *mgr;
 	g_return_val_if_fail (BROWSER_IS_CONNECTION (bcnc), NULL);
@@ -192,6 +194,7 @@ mgr_favorites_new (BrowserConnection *bcnc, BrowserFavoritesType type)
 	mgr = (MgrFavorites*) g_object_new (MGR_FAVORITES_TYPE,
 					    "browser-connection", bcnc, NULL);
 	mgr->priv->fav_type = type;
+	mgr->priv->order_key = order_key;
 	return (GdaTreeManager*) mgr;
 }
 
@@ -239,11 +242,12 @@ mgr_favorites_update_children (GdaTreeManager *manager, GdaTreeNode *node, const
 		ehash = hash_for_existing_nodes (children_nodes);
 
 	fav_list = browser_favorites_list (browser_connection_get_favorites (mgr->priv->bcnc),
-					   0, BROWSER_FAVORITES_TABLES | BROWSER_FAVORITES_DIAGRAMS,
-					   ORDER_KEY_SCHEMA, &lerror);
+					   0, mgr->priv->fav_type,
+					   mgr->priv->order_key, &lerror);
 	if (fav_list) {
 		GSList *list;
-		for (list = fav_list; list; list = list->next) {
+		gint pos;
+		for (list = fav_list, pos = 0; list; list = list->next, pos ++) {
 			BrowserFavoritesAttributes *fav = (BrowserFavoritesAttributes *) list->data;
 			GdaTreeNode* snode = NULL;
 			GValue *av;
@@ -318,7 +322,6 @@ mgr_favorites_update_children (GdaTreeManager *manager, GdaTreeNode *node, const
 									  MGR_FAVORITES_TYPE_ATT_NAME,
 									  av, NULL);
 					gda_value_free (av);
-
 					
 					/* icon */
 					GdkPixbuf *pixbuf;
@@ -340,9 +343,45 @@ mgr_favorites_update_children (GdaTreeManager *manager, GdaTreeNode *node, const
 				gda_tree_node_set_node_attribute (snode, "markup", av, NULL);
 				gda_value_free (av);
 			}
+			else if (fav->type == BROWSER_FAVORITES_QUERIES) {
+				if (!snode) {
+					snode = gda_tree_manager_create_node (manager, node, NULL);
+					
+					g_value_set_int ((av = gda_value_new (G_TYPE_INT)), fav->id);
+					gda_tree_node_set_node_attribute (snode,
+									  MGR_FAVORITES_ID_ATT_NAME,
+									  av, NULL);
+					gda_value_free (av);
 
+					g_value_set_int ((av = gda_value_new (G_TYPE_INT)), pos);
+					gda_tree_node_set_node_attribute (snode,
+									  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);
+				}
+
+				g_value_set_string ((av = gda_value_new (G_TYPE_STRING)),
+						    fav->contents);
+				gda_tree_node_set_node_attribute (snode,
+								  MGR_FAVORITES_CONTENTS_ATT_NAME,
+								  av, NULL);
+				gda_value_free (av);
+
+				g_value_set_string ((av = gda_value_new (G_TYPE_STRING)), fav->name);
+				gda_tree_node_set_node_attribute (snode, MGR_FAVORITES_NAME_ATT_NAME,
+								  av, NULL);
+				gda_value_free (av);
+			}
 			else {
-				
+				TO_IMPLEMENT;
 			}
 			if (snode)
 				nodes_list = g_slist_prepend (nodes_list, snode);
@@ -369,11 +408,13 @@ mgr_favorites_update_children (GdaTreeManager *manager, GdaTreeNode *node, const
 		gchar *str;
 		GValue *value;
 
-		str = g_strdup_printf ("<i>%s</i>", _("No favorite:\ndrag item to\ndefine one"));
-		snode = gda_tree_manager_create_node (manager, node, str);
-		g_value_take_string ((value = gda_value_new (G_TYPE_STRING)), str);
-		gda_tree_node_set_node_attribute (snode, "markup", value, NULL);
-		nodes_list = g_slist_prepend (nodes_list, snode);
+		if (mgr->priv->fav_type & BROWSER_FAVORITES_TABLES) {
+			str = g_strdup_printf ("<i>%s</i>", _("No favorite:\ndrag item to\ndefine one"));
+			snode = gda_tree_manager_create_node (manager, node, str);
+			g_value_take_string ((value = gda_value_new (G_TYPE_STRING)), str);
+			gda_tree_node_set_node_attribute (snode, "markup", value, NULL);
+			nodes_list = g_slist_prepend (nodes_list, snode);
+		}
 	}
 
 	if (ehash)
diff --git a/tools/browser/mgr-favorites.h b/tools/browser/mgr-favorites.h
index 45b9c18..46c4740 100644
--- a/tools/browser/mgr-favorites.h
+++ b/tools/browser/mgr-favorites.h
@@ -48,14 +48,19 @@ struct _MgrFavoritesClass {
 };
 
 GType           mgr_favorites_get_type                 (void) G_GNUC_CONST;
-GdaTreeManager* mgr_favorites_new                      (BrowserConnection *bcnc, BrowserFavoritesType type);
+GdaTreeManager* mgr_favorites_new                      (BrowserConnection *bcnc, BrowserFavoritesType type,
+							gint order_key);
 
+/* name of the attribute which stores the favorite name */
+#define MGR_FAVORITES_NAME_ATT_NAME "fav_name"
 /* name of the attribute which stores the favorite's contents */
 #define MGR_FAVORITES_CONTENTS_ATT_NAME "fav_contents"
 /* name of the attribute which stores the favorite's id */
 #define MGR_FAVORITES_ID_ATT_NAME "fav_id"
 /* name of the attribute which stores the favorite type */
 #define MGR_FAVORITES_TYPE_ATT_NAME "fav_type"
+/* name of the attribute which stores the favorite's position */
+#define MGR_FAVORITES_POSITION_ATT_NAME "fav_pos"
 
 G_END_DECLS
 
diff --git a/tools/browser/query-exec/Makefile.am b/tools/browser/query-exec/Makefile.am
index 6bc0d75..10bf6c1 100644
--- a/tools/browser/query-exec/Makefile.am
+++ b/tools/browser/query-exec/Makefile.am
@@ -9,11 +9,20 @@ AM_CPPFLAGS = \
 	$(GTK_CFLAGS) \
 	$(GTKSOURCEVIEW_CFLAGS)
 
+marshal.h: marshal.list $(GLIB_GENMARSHAL)
+	$(GLIB_GENMARSHAL) $< --header --prefix=_qe_marshal > $@
+marshal.c: marshal.list $(GLIB_GENMARSHAL) marshal.h
+	$(GLIB_GENMARSHAL) $< --body --prefix=_qe_marshal > $@
+
 libperspective_la_SOURCES = \
+        marshal.c \
+        marshal.h \
 	query-console.c \
 	query-console.h \
 	query-editor.c \
 	query-editor.h \
+	query-favorite-selector.c \
+	query-favorite-selector.h \
 	query-result.c \
 	query-result.h \
 	perspective-main.c \
@@ -21,8 +30,17 @@ libperspective_la_SOURCES = \
 	query-exec-perspective.h \
 	query-exec-perspective.c
 
+$(OBJECTS): marshal.c marshal.h
+
 langspecdir=$(datadir)/libgda-$(GDA_ABI_MAJOR_VERSION).$(GDA_ABI_MINOR_VERSION)/language-specs
 langspec_DATA= \
 	gda-sql.lang
 
-EXTRA_DIST=$(langspec_DATA)
+EXTRA_DIST= \
+	$(langspec_DATA) \
+	marshal.list
+
+
+CLEANFILES = \
+	marshal.h \
+	marshal.c
diff --git a/tools/browser/query-exec/marshal.list b/tools/browser/query-exec/marshal.list
new file mode 100644
index 0000000..d9ba6de
--- /dev/null
+++ b/tools/browser/query-exec/marshal.list
@@ -0,0 +1,26 @@
+# see glib-genmarshal(1) for a detailed description of the file format,
+# possible parameter types are:
+#   VOID        indicates   no   return   type,  or  no  extra
+#               parameters. if VOID is used as  the  parameter
+#               list, no additional parameters may be present.
+#   BOOLEAN     for boolean types (gboolean)
+#   CHAR        for signed char types (gchar)
+#   UCHAR       for unsigned char types (guchar)
+#   INT         for signed integer types (gint)
+#   UINT        for unsigned integer types (guint)
+#   LONG        for signed long integer types (glong)
+#   ULONG       for unsigned long integer types (gulong)
+#   ENUM        for enumeration types (gint)
+#   FLAGS       for flag enumeration types (guint)
+#   FLOAT       for single-precision float types (gfloat)
+#   DOUBLE      for double-precision float types (gdouble)
+#   STRING      for string types (gchar*)
+#   PARAM       for GParamSpec or derived types  (GParamSpec*)
+#   BOXED       for boxed (anonymous but reference counted) types (GBoxed*)
+#   POINTER     for anonymous pointer types (gpointer)
+#   OBJECT      for GObject or derived types (GObject*)
+#   NONE        deprecated alias for VOID
+#   BOOL        deprecated alias for BOOLEAN
+
+VOID:ENUM,STRING
+VOID:INT,ENUM,STRING
diff --git a/tools/browser/query-exec/query-console.c b/tools/browser/query-exec/query-console.c
index 6c96c15..12bb3b7 100644
--- a/tools/browser/query-exec/query-console.c
+++ b/tools/browser/query-exec/query-console.c
@@ -268,6 +268,7 @@ static void sql_clear_clicked_cb (GtkButton *button, QueryConsole *tconsole);
 static void sql_variables_clicked_cb (GtkToggleButton *button, QueryConsole *tconsole);
 static void sql_execute_clicked_cb (GtkButton *button, QueryConsole *tconsole);
 static void sql_indent_clicked_cb (GtkButton *button, QueryConsole *tconsole);
+static void sql_favorite_clicked_cb (GtkButton *button, QueryConsole *tconsole);
 
 static void history_copy_clicked_cb (GtkButton *button, QueryConsole *tconsole);
 static void history_delete_clicked_cb (GtkButton *button, QueryConsole *tconsole);
@@ -387,6 +388,11 @@ query_console_new (BrowserConnection *bcnc)
 	g_signal_connect (button, "clicked",
 			  G_CALLBACK (sql_indent_clicked_cb), tconsole);
 
+	button = make_small_button (FALSE, _("Favorite"), STOCK_ADD_BOOKMARK, _("Add SQL to favorite"));
+	gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 0);
+	g_signal_connect (button, "clicked",
+			  G_CALLBACK (sql_favorite_clicked_cb), tconsole);
+
 	/* bottom paned for the results and history */
 	hpaned = gtk_hpaned_new ();
 	gtk_paned_add2 (GTK_PANED (vpaned), hpaned);
@@ -723,6 +729,31 @@ sql_indent_clicked_cb (GtkButton *button, QueryConsole *tconsole)
 }
 
 static void
+sql_favorite_clicked_cb (GtkButton *button, QueryConsole *tconsole)
+{
+	BrowserFavorites *bfav;
+	BrowserFavoritesAttributes fav;
+	GError *error = NULL;
+
+	memset (&fav, 0, sizeof (fav));
+	fav.id = -1;
+	fav.type = BROWSER_FAVORITES_QUERIES;
+	fav.contents = query_editor_get_all_text (tconsole->priv->editor);
+	fav.name = _("Unnamed query");
+
+	bfav = browser_connection_get_favorites (tconsole->priv->bcnc);
+
+	if (! browser_favorites_add (bfav, 0, &fav, ORDER_KEY_QUERIES, G_MAXINT, &error)) {
+		browser_show_error ((GtkWindow*) gtk_widget_get_toplevel ((GtkWidget*) tconsole),
+                                    _("Could not add favorite: %s"),
+                                    error && error->message ? error->message : _("No detail"));
+                if (error)
+                        g_error_free (error);
+	}
+	g_free (fav.contents);
+}
+
+static void
 popup_container_position_func (PopupContainer *cont, gint *out_x, gint *out_y)
 {
 	GtkWidget *console, *top;
@@ -997,6 +1028,20 @@ query_exec_fetch_cb (QueryConsole *tconsole)
 	return !alldone;
 }
 
+/**
+ * query_console_set_text
+ * @console:
+ * @text:
+ *
+ * Replaces the edited SQL with @text in @console
+ */
+void
+query_console_set_text (QueryConsole *console, const gchar *text)
+{
+	g_return_if_fail (IS_QUERY_CONSOLE (console));
+	query_editor_set_text (console->priv->editor, text);
+}
+
 /*
  * UI actions
  */
diff --git a/tools/browser/query-exec/query-console.h b/tools/browser/query-exec/query-console.h
index d038d29..7b8bbeb 100644
--- a/tools/browser/query-exec/query-console.h
+++ b/tools/browser/query-exec/query-console.h
@@ -50,6 +50,7 @@ struct _QueryConsoleClass {
 GType                    query_console_get_type (void) G_GNUC_CONST;
 
 GtkWidget               *query_console_new      (BrowserConnection *bcnc);
+void                     query_console_set_text (QueryConsole *console, const gchar *text);
 
 G_END_DECLS
 
diff --git a/tools/browser/query-exec/query-editor.c b/tools/browser/query-exec/query-editor.c
index cbdcf57..be0c55d 100644
--- a/tools/browser/query-exec/query-editor.c
+++ b/tools/browser/query-exec/query-editor.c
@@ -675,6 +675,7 @@ query_editor_set_mode (QueryEditor *editor, QueryEditorMode mode)
 		hist_data_free_all (editor);
 
 	editor->priv->mode = mode;
+	
 	buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->priv->text));
 	if (clean) {
 		GtkTextIter start, end;
@@ -685,11 +686,13 @@ query_editor_set_mode (QueryEditor *editor, QueryEditorMode mode)
 
 	switch (mode) {
 	case QUERY_EDITOR_READWRITE:
+		gtk_widget_set_tooltip_markup (editor->priv->text, QUERY_EDITOR_TOOLTIP);
 		gtk_text_view_set_editable (GTK_TEXT_VIEW (editor->priv->text), TRUE);
 		gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (editor->priv->text), TRUE);
 		break;
 	case QUERY_EDITOR_READONLY:
 	case QUERY_EDITOR_HISTORY:
+		gtk_widget_set_tooltip_markup (editor->priv->text, NULL);
 		gtk_text_view_set_editable (GTK_TEXT_VIEW (editor->priv->text), FALSE);
 		gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (editor->priv->text), FALSE);
 		break;
@@ -852,6 +855,25 @@ query_editor_append_note (QueryEditor *editor, const gchar *text, gint level)
 	}	
 }
 
+/**
+ * query_editor_show_tooltip
+ * @editor: a #QueryEditor
+ * @show_tooltip:
+ *
+ * Defines if tooltip can be shown or not
+ */
+void
+query_editor_show_tooltip (QueryEditor *editor, gboolean show_tooltip)
+{
+	g_return_if_fail (QUERY_IS_EDITOR (editor));
+	g_return_if_fail (editor->priv->mode == QUERY_EDITOR_READWRITE);
+	
+	if (show_tooltip)
+		gtk_widget_set_tooltip_markup (editor->priv->text, QUERY_EDITOR_TOOLTIP);
+	else
+		gtk_widget_set_tooltip_markup (editor->priv->text, NULL);
+}
+
 static void
 focus_on_hist_data (QueryEditor *editor, HistItemData *hdata)
 {
diff --git a/tools/browser/query-exec/query-editor.h b/tools/browser/query-exec/query-editor.h
index 11d4e1a..63cb018 100644
--- a/tools/browser/query-exec/query-editor.h
+++ b/tools/browser/query-exec/query-editor.h
@@ -123,6 +123,7 @@ void       query_editor_set_text (QueryEditor *editor, const gchar *text);
 void       query_editor_append_text (QueryEditor *editor, const gchar *text);
 void       query_editor_keep_current_state (QueryEditor *editor);
 void       query_editor_append_note (QueryEditor *editor, const gchar *text, gint level);
+void       query_editor_show_tooltip (QueryEditor *editor, gboolean show_tooltip);
 
 /* history API */
 void       query_editor_start_history_batch (QueryEditor *editor, QueryEditorHistoryBatch *hist_batch);
diff --git a/tools/browser/query-exec/query-exec-perspective.c b/tools/browser/query-exec/query-exec-perspective.c
index 0550f7a..24acee3 100644
--- a/tools/browser/query-exec/query-exec-perspective.c
+++ b/tools/browser/query-exec/query-exec-perspective.c
@@ -25,6 +25,8 @@
 #include "query-console.h"
 #include "../browser-stock-icons.h"
 #include "../support.h"
+#include "query-favorite-selector.h"
+#include "query-editor.h"
 
 /* 
  * Main static functions 
@@ -124,6 +126,8 @@ query_exec_perspective_init (QueryExecPerspective *perspective)
 	perspective->priv->action_group = NULL;
 }
 
+static void fav_selection_changed_cb (GtkWidget *widget, gint fav_id, BrowserFavoritesType fav_type,
+                                      const gchar *selection, QueryExecPerspective *perspective);
 static void nb_switch_page_cb (GtkNotebook *nb, GtkNotebookPage *page, gint page_num,
 			       QueryExecPerspective *perspective);
 static void nb_page_removed_cb (GtkNotebook *nb, GtkNotebookPage *page, gint page_num,
@@ -152,18 +156,16 @@ query_exec_perspective_new (BrowserWindow *bwin)
 	perspective->priv->bcnc = g_object_ref (bcnc);
 
 	/* contents */
-	GtkWidget *paned, *nb;
+	GtkWidget *paned, *nb, *wid;
 	paned = gtk_hpaned_new ();
-	/*
-	wid = favorite_selector_new (bcnc);
+	wid = query_favorite_selector_new (bcnc);
 	g_signal_connect (wid, "selection-changed",
 			  G_CALLBACK (fav_selection_changed_cb), bpers);
-	gtk_paned_add1 (GTK_PANED (paned), wid);
-	*/
+	gtk_paned_pack1 (GTK_PANED (paned), wid, FALSE, TRUE);
 
 	nb = gtk_notebook_new ();
 	perspective->priv->notebook = nb;
-	gtk_paned_add2 (GTK_PANED (paned), nb);
+	gtk_paned_pack2 (GTK_PANED (paned), nb, TRUE, TRUE);
 	gtk_notebook_set_scrollable (GTK_NOTEBOOK (nb), TRUE);
 	gtk_notebook_popup_enable (GTK_NOTEBOOK (nb));
 	g_signal_connect (G_OBJECT (nb), "switch-page",
@@ -201,6 +203,23 @@ query_exec_perspective_new (BrowserWindow *bwin)
 }
 
 static void
+fav_selection_changed_cb (GtkWidget *widget, gint fav_id, BrowserFavoritesType fav_type,
+			  const gchar *selection, QueryExecPerspective *perspective)
+{
+	GtkNotebook *nb;
+	GtkWidget *page;
+
+	nb = GTK_NOTEBOOK (perspective->priv->notebook);
+	page = gtk_notebook_get_nth_page (nb, gtk_notebook_get_current_page (nb));
+	if (IS_QUERY_CONSOLE (page)) {
+		query_console_set_text (QUERY_CONSOLE (page), selection);	
+	}
+	else {
+		TO_IMPLEMENT;
+	}
+}
+
+static void
 nb_switch_page_cb (GtkNotebook *nb, GtkNotebookPage *page, gint page_num,
 		   QueryExecPerspective *perspective)
 {
diff --git a/tools/browser/query-exec/query-favorite-selector.c b/tools/browser/query-exec/query-favorite-selector.c
new file mode 100644
index 0000000..f9fbaa7
--- /dev/null
+++ b/tools/browser/query-exec/query-favorite-selector.c
@@ -0,0 +1,632 @@
+/*
+ * Copyright (C) 2009 The GNOME Foundation
+ *
+ * AUTHORS:
+ *      Vivien Malerba <malerba gnome-db org>
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <glib/gi18n-lib.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <libgda/gda-tree.h>
+#include "query-favorite-selector.h"
+#include "../mgr-favorites.h"
+#include <libgda-ui/gdaui-tree-store.h>
+#include "../dnd.h"
+#include "../support.h"
+#include "marshal.h"
+#include "../cc-gray-bar.h"
+#include "../browser-favorites.h"
+#include <gdk/gdkkeysyms.h>
+#include "../common/popup-container.h"
+#include "query-editor.h"
+
+struct _QueryFavoriteSelectorPrivate {
+	BrowserConnection *bcnc;
+	GdaTree *tree;
+	GtkWidget *treeview;
+	guint idle_update_favorites;
+
+	GtkWidget *popup_menu;
+	GtkWidget *popup_properties;
+	GtkWidget *properties_name;
+	GtkWidget *properties_text;
+	gint       properties_id;
+	gint       properties_position;
+	guint      prop_save_timeout;
+};
+
+static void query_favorite_selector_class_init (QueryFavoriteSelectorClass *klass);
+static void query_favorite_selector_init       (QueryFavoriteSelector *tsel,
+				       QueryFavoriteSelectorClass *klass);
+static void query_favorite_selector_dispose   (GObject *object);
+
+static void favorites_changed_cb (BrowserFavorites *bfav, QueryFavoriteSelector *tsel);
+
+enum {
+	SELECTION_CHANGED,
+	LAST_SIGNAL
+};
+
+static guint query_favorite_selector_signals[LAST_SIGNAL] = { 0 };
+static GObjectClass *parent_class = NULL;
+
+/* columns of the resulting GtkTreeModel */
+enum {
+	COLUMN_POSITION = 0,
+	COLUMN_ICON = 1,
+	COLUMN_CONTENTS = 2,
+	COLUMN_TYPE = 3,
+	COLUMN_ID = 4,
+	COLUMN_NAME = 5
+};
+
+
+/*
+ * QueryFavoriteSelector class implementation
+ */
+
+static void
+query_favorite_selector_class_init (QueryFavoriteSelectorClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	parent_class = g_type_class_peek_parent (klass);
+
+	/* signals */
+	query_favorite_selector_signals [SELECTION_CHANGED] =
+                g_signal_new ("selection-changed",
+                              G_TYPE_FROM_CLASS (object_class),
+                              G_SIGNAL_RUN_FIRST,
+                              G_STRUCT_OFFSET (QueryFavoriteSelectorClass, selection_changed),
+                              NULL, NULL,
+                              _qe_marshal_VOID__INT_ENUM_STRING, G_TYPE_NONE,
+                              3, G_TYPE_INT, G_TYPE_UINT, G_TYPE_STRING);
+	klass->selection_changed = NULL;
+
+	object_class->dispose = query_favorite_selector_dispose;
+}
+
+
+static void
+query_favorite_selector_init (QueryFavoriteSelector *tsel,	QueryFavoriteSelectorClass *klass)
+{
+	tsel->priv = g_new0 (QueryFavoriteSelectorPrivate, 1);
+	tsel->priv->idle_update_favorites = 0;
+	tsel->priv->prop_save_timeout = 0;
+}
+
+static void
+query_favorite_selector_dispose (GObject *object)
+{
+	QueryFavoriteSelector *tsel = (QueryFavoriteSelector *) object;
+
+	/* free memory */
+	if (tsel->priv) {
+		if (tsel->priv->idle_update_favorites != 0)
+			g_source_remove (tsel->priv->idle_update_favorites);
+		if (tsel->priv->tree)
+			g_object_unref (tsel->priv->tree);
+
+		if (tsel->priv->bcnc) {
+			g_signal_handlers_disconnect_by_func (browser_connection_get_favorites (tsel->priv->bcnc),
+							      G_CALLBACK (favorites_changed_cb), tsel);
+			g_object_unref (tsel->priv->bcnc);
+		}
+		
+		if (tsel->priv->popup_properties)
+			gtk_widget_destroy (tsel->priv->popup_properties);
+		if (tsel->priv->popup_menu)
+			gtk_widget_destroy (tsel->priv->popup_menu);
+		if (tsel->priv->prop_save_timeout)
+			g_source_remove (tsel->priv->prop_save_timeout);
+
+		g_free (tsel->priv);
+		tsel->priv = NULL;
+	}
+
+	parent_class->dispose (object);
+}
+
+GType
+query_favorite_selector_get_type (void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY (type == 0)) {
+		static const GTypeInfo info = {
+			sizeof (QueryFavoriteSelectorClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) query_favorite_selector_class_init,
+			NULL,
+			NULL,
+			sizeof (QueryFavoriteSelector),
+			0,
+			(GInstanceInitFunc) query_favorite_selector_init
+		};
+		type = g_type_register_static (GTK_TYPE_VBOX, "QueryFavoriteSelector",
+					       &info, 0);
+	}
+	return type;
+}
+
+static gboolean
+key_press_event_cb (GtkTreeView *treeview, GdkEventKey *event, QueryFavoriteSelector *tsel)
+{
+	if (event->keyval == GDK_Delete) {
+		GtkTreeModel *model;
+		GtkTreeSelection *select;
+		GtkTreeIter iter;
+		
+		select = gtk_tree_view_get_selection (treeview);
+		if (gtk_tree_selection_get_selected (select, &model, &iter)) {
+			BrowserFavorites *bfav;
+			BrowserFavoritesAttributes fav;
+			GError *lerror = NULL;
+
+			memset (&fav, 0, sizeof (BrowserFavoritesAttributes));
+			gtk_tree_model_get (model, &iter,
+					    COLUMN_ID, &(fav.id), -1);
+			bfav = browser_connection_get_favorites (tsel->priv->bcnc);
+			if (!browser_favorites_delete (bfav, 0, &fav, NULL)) {
+				browser_show_error ((GtkWindow*) gtk_widget_get_toplevel ((GtkWidget*)tsel),
+						    _("Could not remove favorite: %s"),
+						    lerror && lerror->message ? lerror->message : _("No detail"));
+				if (lerror)
+					g_error_free (lerror);
+			}
+		}
+		
+		return TRUE;
+	}
+	return FALSE; /* not handled */
+}
+
+
+static void
+selection_changed_cb (GtkTreeView *treeview, GtkTreePath *path,
+		      GtkTreeViewColumn *column, QueryFavoriteSelector *tsel)
+{
+	GtkTreeModel *model;
+	GtkTreeSelection *select;
+	GtkTreeIter iter;
+	
+	select = gtk_tree_view_get_selection (treeview);
+	if (gtk_tree_selection_get_selected (select, &model, &iter)) {
+		gchar *str;
+		guint type;
+		gint fav_id;
+		gtk_tree_model_get (model, &iter,
+				    COLUMN_ID, &fav_id,
+				    COLUMN_TYPE, &type,
+				    COLUMN_CONTENTS, &str, -1);
+		g_signal_emit (tsel, query_favorite_selector_signals [SELECTION_CHANGED], 0, fav_id, type, str);
+		g_free (str);
+	}
+}
+
+static gboolean
+prop_save_timeout (QueryFavoriteSelector *tsel)
+{
+	BrowserFavorites *bfav;
+	BrowserFavoritesAttributes fav;
+	GError *error = NULL;
+
+	memset (&fav, 0, sizeof (BrowserFavoritesAttributes));
+	fav.id = tsel->priv->properties_id;
+	fav.type = BROWSER_FAVORITES_QUERIES;
+	fav.name = (gchar*) gtk_entry_get_text (GTK_ENTRY (tsel->priv->properties_name));
+	fav.descr = NULL;
+	fav.contents = query_editor_get_all_text (QUERY_EDITOR (tsel->priv->properties_text));
+
+	bfav = browser_connection_get_favorites (tsel->priv->bcnc);
+	if (! browser_favorites_add (bfav, 0, &fav, ORDER_KEY_QUERIES, tsel->priv->properties_position, &error)) {
+		browser_show_error ((GtkWindow*) gtk_widget_get_toplevel ((GtkWidget*) tsel),
+				    _("Could not add favorite: %s"),
+				    error && error->message ? error->message : _("No detail"));
+		if (error)
+			g_error_free (error);
+	}
+
+	tsel->priv->prop_save_timeout = 0;
+	return FALSE; /* remove timeout */
+}
+
+static void
+property_changed_cb (GtkWidget *multiple, QueryFavoriteSelector *tsel)
+{
+	if (tsel->priv->prop_save_timeout)
+		g_source_remove (tsel->priv->prop_save_timeout);
+	tsel->priv->prop_save_timeout = g_timeout_add (100, (GSourceFunc) prop_save_timeout, tsel);
+}
+
+static void
+properties_activated_cb (GtkMenuItem *mitem, QueryFavoriteSelector *tsel)
+{
+	if (! tsel->priv->popup_properties) {
+		GtkWidget *pcont, *vbox, *hbox, *label, *entry, *text, *table;
+		gchar *str;
+		
+		pcont = popup_container_new (GTK_WIDGET (mitem));
+		vbox = gtk_vbox_new (FALSE, 0);
+		gtk_container_add (GTK_CONTAINER (pcont), vbox);
+		
+		label = gtk_label_new ("");
+		str = g_strdup_printf ("<b>%s:</b>", _("Favorite's properties"));
+		gtk_label_set_markup (GTK_LABEL (label), str);
+		g_free (str);
+		gtk_misc_set_alignment (GTK_MISC (label), 0., -1);
+		gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+		
+		hbox = gtk_hbox_new (FALSE, 0); /* HIG */
+		gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 5);
+		label = gtk_label_new ("      ");
+		gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+		
+		table = gtk_table_new (2, 2, FALSE);
+		gtk_box_pack_start (GTK_BOX (hbox), table, TRUE, TRUE, 0);
+		
+		label = gtk_label_new ("");
+		str = g_strdup_printf ("<b>%s:</b>", _("Name"));
+		gtk_label_set_markup (GTK_LABEL (label), str);
+		g_free (str);
+		gtk_misc_set_alignment (GTK_MISC (label), 0., -1);
+		gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0);
+		
+		label = gtk_label_new ("");
+		str = g_strdup_printf ("<b>%s:</b>", _("SQL Code"));
+		gtk_label_set_markup (GTK_LABEL (label), str);
+		g_free (str);
+		gtk_misc_set_alignment (GTK_MISC (label), 0., 0.);
+		gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0);
+		
+		entry = gtk_entry_new ();
+		gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_SHRINK, 0, 0);
+		tsel->priv->properties_name = entry;
+		g_signal_connect (entry, "changed",
+				  G_CALLBACK (property_changed_cb), tsel);
+		
+		text = query_editor_new ();
+		query_editor_show_tooltip (QUERY_EDITOR (text), FALSE);
+		gtk_widget_set_size_request (GTK_WIDGET (text), 400, 300);
+		gtk_table_attach_defaults (GTK_TABLE (table), text, 1, 2, 1, 2);
+		tsel->priv->properties_text = text;
+		g_signal_connect (text, "changed",
+				  G_CALLBACK (property_changed_cb), tsel);
+
+		tsel->priv->popup_properties = pcont;
+		gtk_widget_show_all (vbox);
+	}
+
+	/* adjust contents */
+	GtkTreeSelection *selection;
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tsel->priv->treeview));
+	if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
+		gchar *name, *contents;
+		
+		gtk_tree_model_get (model, &iter,
+				    COLUMN_ID, &(tsel->priv->properties_id),
+				    COLUMN_POSITION, &(tsel->priv->properties_position),
+				    COLUMN_NAME, &name,
+				    COLUMN_CONTENTS, &contents, -1);
+
+		g_signal_handlers_block_by_func (tsel->priv->properties_name,
+						 G_CALLBACK (property_changed_cb), tsel);
+		gtk_entry_set_text (GTK_ENTRY (tsel->priv->properties_name), name);
+		g_signal_handlers_unblock_by_func (tsel->priv->properties_name,
+						   G_CALLBACK (property_changed_cb), tsel);
+		g_free (name);
+
+		g_signal_handlers_block_by_func (tsel->priv->properties_text,
+						 G_CALLBACK (property_changed_cb), tsel);
+		query_editor_set_text (QUERY_EDITOR (tsel->priv->properties_text), contents);
+		g_signal_handlers_unblock_by_func (tsel->priv->properties_text,
+						   G_CALLBACK (property_changed_cb), tsel);
+		g_free (contents);
+
+		gtk_widget_show (tsel->priv->popup_properties);
+	}
+}
+
+static void
+do_popup_menu (GtkWidget *widget, GdkEventButton *event, QueryFavoriteSelector *tsel)
+{
+	int button, event_time;
+
+	if (! tsel->priv->popup_menu) {
+		GtkWidget *menu, *mitem;
+		
+		menu = gtk_menu_new ();
+		g_signal_connect (menu, "deactivate", 
+				  G_CALLBACK (gtk_widget_hide), NULL);
+		
+		mitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_PROPERTIES, NULL);
+		gtk_menu_shell_append (GTK_MENU_SHELL (menu), mitem);
+		gtk_widget_show (mitem);
+		g_signal_connect (mitem, "activate",
+				  G_CALLBACK (properties_activated_cb), tsel);
+
+		tsel->priv->popup_menu = menu;
+	}
+		
+	if (event) {
+		button = event->button;
+		event_time = event->time;
+	}
+	else {
+		button = 0;
+		event_time = gtk_get_current_event_time ();
+	}
+
+	gtk_menu_popup (GTK_MENU (tsel->priv->popup_menu), NULL, NULL, NULL, NULL, 
+			button, event_time);
+}
+
+
+static gboolean
+popup_menu_cb (GtkWidget *widget, QueryFavoriteSelector *tsel)
+{
+	do_popup_menu (widget, NULL, tsel);
+	return TRUE;
+}
+
+static gboolean
+button_press_event_cb (GtkTreeView *treeview, GdkEventButton *event, QueryFavoriteSelector *tsel)
+{
+	if (event->button == 3 && event->type == GDK_BUTTON_PRESS) {
+		do_popup_menu ((GtkWidget*) treeview, event, tsel);
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+static void cell_data_func (GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
+			    GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data);
+static gboolean idle_update_favorites (QueryFavoriteSelector *tsel);
+static gboolean tree_store_drag_drop_cb (GdauiTreeStore *store, const gchar *path,
+					 GtkSelectionData *selection_data, QueryFavoriteSelector *tsel);
+static gboolean tree_store_drag_can_drag_cb (GdauiTreeStore *store, const gchar *path,
+					     QueryFavoriteSelector *tsel);
+static gboolean tree_store_drag_get_cb (GdauiTreeStore *store, const gchar *path,
+					GtkSelectionData *selection_data, QueryFavoriteSelector *tsel);
+static void trash_data_received_cb (GtkWidget *widget, GdkDragContext *context, gint x, gint y,
+				    GtkSelectionData *selection_data, guint target_type, guint time,
+				    QueryFavoriteSelector *tsel);
+/**
+ * query_favorite_selector_new
+ *
+ * Returns: a new #GtkWidget
+ */
+GtkWidget *
+query_favorite_selector_new (BrowserConnection *bcnc)
+{
+	QueryFavoriteSelector *tsel;
+	GdaTreeManager *manager;
+
+	g_return_val_if_fail (BROWSER_IS_CONNECTION (bcnc), NULL);
+	tsel = QUERY_FAVORITE_SELECTOR (g_object_new (QUERY_FAVORITE_SELECTOR_TYPE, NULL));
+
+	tsel->priv->bcnc = g_object_ref (bcnc);
+	g_signal_connect (browser_connection_get_favorites (tsel->priv->bcnc), "favorites-changed",
+			  G_CALLBACK (favorites_changed_cb), tsel);
+	
+	/* create tree managers */
+	tsel->priv->tree = gda_tree_new ();
+	manager = mgr_favorites_new (bcnc, BROWSER_FAVORITES_QUERIES, ORDER_KEY_QUERIES);
+        gda_tree_add_manager (tsel->priv->tree, manager);
+	g_object_unref (manager);
+
+	/* update the tree's contents */
+	if (! gda_tree_update_all (tsel->priv->tree, NULL)) {
+		if (tsel->priv->idle_update_favorites == 0)
+			tsel->priv->idle_update_favorites = g_idle_add ((GSourceFunc) idle_update_favorites, tsel);
+	}
+
+	/* header */
+	GtkWidget *label;
+	gchar *str;
+	str = g_strdup_printf ("<b>%s</b>", _("Favorites"));
+	label = cc_gray_bar_new (str);
+	g_free (str);
+	cc_gray_bar_set_icon_from_pixbuf (CC_GRAY_BAR (label), browser_get_pixbuf_icon (BROWSER_ICON_BOOKMARK));
+        gtk_box_pack_start (GTK_BOX (tsel), label, FALSE, FALSE, 0);
+        gtk_widget_show (label);
+
+	/* tree model */
+	GtkTreeModel *model;
+	GtkWidget *treeview;
+	GtkCellRenderer *renderer;
+	GtkTreeViewColumn *column;
+
+	model = gdaui_tree_store_new (tsel->priv->tree, 6,
+				      G_TYPE_INT, MGR_FAVORITES_POSITION_ATT_NAME,
+				      G_TYPE_OBJECT, "icon",
+				      G_TYPE_STRING, MGR_FAVORITES_CONTENTS_ATT_NAME,
+				      G_TYPE_UINT, MGR_FAVORITES_TYPE_ATT_NAME,
+				      G_TYPE_INT, MGR_FAVORITES_ID_ATT_NAME,
+				      G_TYPE_STRING, MGR_FAVORITES_NAME_ATT_NAME);
+	treeview = gtk_tree_view_new_with_model (model);
+	tsel->priv->treeview = treeview;
+	g_object_unref (model);
+
+	/* icon */
+	column = gtk_tree_view_column_new ();
+
+	renderer = gtk_cell_renderer_pixbuf_new ();
+	gtk_tree_view_column_pack_start (column, renderer, FALSE);
+	gtk_tree_view_column_add_attribute (column, renderer, "pixbuf", COLUMN_ICON);
+	g_object_set ((GObject*) renderer, "yalign", 0., NULL);
+
+	/* text */
+	renderer = gtk_cell_renderer_text_new ();
+	gtk_tree_view_column_pack_start (column, renderer, TRUE);
+	gtk_tree_view_column_set_cell_data_func (column, renderer, (GtkTreeCellDataFunc) cell_data_func,
+						 NULL, NULL);
+	gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+	gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED);
+	
+	/* scrolled window packing */
+	GtkWidget *sw;
+	sw = gtk_scrolled_window_new (NULL, NULL);
+	gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
+					     GTK_SHADOW_ETCHED_IN);
+	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+					GTK_POLICY_NEVER,
+					GTK_POLICY_AUTOMATIC);
+	gtk_container_add (GTK_CONTAINER (sw), treeview);
+	gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);	
+
+	gtk_box_pack_start (GTK_BOX (tsel), sw, TRUE, TRUE, 0);
+	gtk_widget_show_all (sw);
+	g_signal_connect (G_OBJECT (treeview), "row-activated",
+			  G_CALLBACK (selection_changed_cb), tsel);
+	g_signal_connect (G_OBJECT (treeview), "key-press-event",
+			  G_CALLBACK (key_press_event_cb), tsel);
+	g_signal_connect (G_OBJECT (treeview), "popup-menu",
+			  G_CALLBACK (popup_menu_cb), tsel);
+	g_signal_connect (G_OBJECT (treeview), "button-press-event",
+			  G_CALLBACK (button_press_event_cb), tsel);
+
+	/* DnD */
+	gtk_tree_view_enable_model_drag_dest (GTK_TREE_VIEW (treeview), dbo_table, G_N_ELEMENTS (dbo_table),
+					      GDK_ACTION_COPY);
+	gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (treeview), GDK_BUTTON1_MASK,
+						dbo_table, G_N_ELEMENTS (dbo_table),
+						GDK_ACTION_COPY | GDK_ACTION_MOVE);
+	g_signal_connect (model, "drag-drop",
+			  G_CALLBACK (tree_store_drag_drop_cb), tsel);
+	g_signal_connect (model, "drag-can-drag",
+			  G_CALLBACK (tree_store_drag_can_drag_cb), tsel);
+	g_signal_connect (model, "drag-get",
+			  G_CALLBACK (tree_store_drag_get_cb), tsel);
+
+	return (GtkWidget*) tsel;
+}
+
+static void
+cell_data_func (GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
+		GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
+{
+	gchar *name, *contents;
+	gchar *markup, *tmp1, *tmp2;
+
+	gtk_tree_model_get (tree_model, iter,
+			    COLUMN_NAME, &name, COLUMN_CONTENTS, &contents, -1);
+	tmp1 = g_markup_printf_escaped ("%s", name);
+	tmp2 = g_markup_printf_escaped ("%s", contents);
+	markup = g_strdup_printf ("%s\n<small>%s</small>", tmp1, tmp2);
+	g_object_set ((GObject*) cell, "markup", markup, NULL);
+	g_free (tmp1);
+	g_free (tmp2);
+	g_free (name);
+	g_free (contents);
+}
+
+
+static gboolean
+idle_update_favorites (QueryFavoriteSelector *tsel)
+{
+	gboolean done;
+	done = gda_tree_update_all (tsel->priv->tree, NULL);
+	if (done)
+		tsel->priv->idle_update_favorites = 0;
+	else
+		tsel->priv->idle_update_favorites = g_timeout_add_seconds (1, (GSourceFunc) idle_update_favorites,
+									   tsel);
+	return FALSE;
+}
+
+static gboolean
+tree_store_drag_drop_cb (GdauiTreeStore *store, const gchar *path, GtkSelectionData *selection_data,
+			 QueryFavoriteSelector *tsel)
+{
+	BrowserFavorites *bfav;
+	BrowserFavoritesAttributes fav;
+	GError *error = NULL;
+	gint pos;
+
+	memset (&fav, 0, sizeof (BrowserFavoritesAttributes));
+	fav.id = -1;
+	fav.type = BROWSER_FAVORITES_QUERIES;
+	fav.name = _("Unnamed query");
+	fav.descr = NULL;
+	fav.contents = (gchar*) selection_data->data;
+
+	pos = atoi (path);
+	g_print ("%s() path => %s, pos: %d\n", __FUNCTION__, path, pos);
+	
+	bfav = browser_connection_get_favorites (tsel->priv->bcnc);
+	if (! browser_favorites_add (bfav, 0, &fav, ORDER_KEY_QUERIES, pos, &error)) {
+		browser_show_error ((GtkWindow*) gtk_widget_get_toplevel ((GtkWidget*) tsel),
+				    _("Could not add favorite: %s"),
+				    error && error->message ? error->message : _("No detail"));
+		if (error)
+			g_error_free (error);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static gboolean
+tree_store_drag_can_drag_cb (GdauiTreeStore *store, const gchar *path, QueryFavoriteSelector *tsel)
+{
+	GdaTreeNode *node;
+	node = gda_tree_get_node (tsel->priv->tree, path, FALSE);
+	if (node) {
+		const GValue *cvalue;
+		cvalue = gda_tree_node_get_node_attribute (node, "fav_contents");
+		if (cvalue)
+			return TRUE;
+	}
+	return FALSE;
+}
+
+static gboolean
+tree_store_drag_get_cb (GdauiTreeStore *store, const gchar *path, GtkSelectionData *selection_data,
+			QueryFavoriteSelector *tsel)
+{
+	GdaTreeNode *node;
+	node = gda_tree_get_node (tsel->priv->tree, path, FALSE);
+	if (node) {
+		const GValue *cvalue;
+		cvalue = gda_tree_node_get_node_attribute (node, "fav_contents");
+		if (cvalue) {
+			const gchar *str;
+			str = g_value_get_string (cvalue);
+			gtk_selection_data_set (selection_data, selection_data->target, 8,
+						(guchar*) str, strlen (str));
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+static void
+favorites_changed_cb (BrowserFavorites *bfav, QueryFavoriteSelector *tsel)
+{
+	if (! gda_tree_update_all (tsel->priv->tree, NULL)) {
+		if (tsel->priv->idle_update_favorites == 0)
+			tsel->priv->idle_update_favorites = g_idle_add ((GSourceFunc) idle_update_favorites, tsel);
+
+	}
+}
diff --git a/tools/browser/query-exec/query-favorite-selector.h b/tools/browser/query-exec/query-favorite-selector.h
new file mode 100644
index 0000000..45cada1
--- /dev/null
+++ b/tools/browser/query-exec/query-favorite-selector.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2009 The GNOME Foundation
+ *
+ * AUTHORS:
+ *      Vivien Malerba <malerba gnome-db org>
+ *
+ * This Library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This Library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this Library; see the file COPYING.LIB.  If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __QUERY_FAVORITE_SELECTOR_H__
+#define __QUERY_FAVORITE_SELECTOR_H__
+
+#include <gtk/gtkvbox.h>
+#include "../browser-connection.h"
+
+G_BEGIN_DECLS
+
+#define QUERY_FAVORITE_SELECTOR_TYPE            (query_favorite_selector_get_type())
+#define QUERY_FAVORITE_SELECTOR(obj)            (G_TYPE_CHECK_INSTANCE_CAST (obj, QUERY_FAVORITE_SELECTOR_TYPE, QueryFavoriteSelector))
+#define QUERY_FAVORITE_SELECTOR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST (klass, QUERY_FAVORITE_SELECTOR_TYPE, QueryFavoriteSelectorClass))
+#define IS_QUERY_FAVORITE_SELECTOR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE (obj, QUERY_FAVORITE_SELECTOR_TYPE))
+#define IS_QUERY_FAVORITE_SELECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), QUERY_FAVORITE_SELECTOR_TYPE))
+
+typedef struct _QueryFavoriteSelector        QueryFavoriteSelector;
+typedef struct _QueryFavoriteSelectorClass   QueryFavoriteSelectorClass;
+typedef struct _QueryFavoriteSelectorPrivate QueryFavoriteSelectorPrivate;
+
+struct _QueryFavoriteSelector {
+	GtkVBox               parent;
+	QueryFavoriteSelectorPrivate *priv;
+};
+
+struct _QueryFavoriteSelectorClass {
+	GtkVBoxClass          parent_class;
+
+	void                (*selection_changed) (QueryFavoriteSelector *sel, gint fav_id,
+						  BrowserFavoritesType fav_type, const gchar *fav_contents);
+};
+
+GType                    query_favorite_selector_get_type (void) G_GNUC_CONST;
+
+GtkWidget               *query_favorite_selector_new      (BrowserConnection *bcnc);
+
+G_END_DECLS
+
+#endif
diff --git a/tools/browser/schema-browser/favorite-selector.c b/tools/browser/schema-browser/favorite-selector.c
index 3aa24aa..6084e46 100644
--- a/tools/browser/schema-browser/favorite-selector.c
+++ b/tools/browser/schema-browser/favorite-selector.c
@@ -232,7 +232,8 @@ favorite_selector_new (BrowserConnection *bcnc)
 	
 	/* create tree managers */
 	tsel->priv->tree = gda_tree_new ();
-	manager = mgr_favorites_new (bcnc, BROWSER_FAVORITES_TABLES);
+	manager = mgr_favorites_new (bcnc, BROWSER_FAVORITES_TABLES | BROWSER_FAVORITES_DIAGRAMS,
+				     ORDER_KEY_SCHEMA);
         gda_tree_add_manager (tsel->priv->tree, manager);
 	g_object_unref (manager);
 
diff --git a/tools/browser/support.c b/tools/browser/support.c
index a9f4594..013880e 100644
--- a/tools/browser/support.c
+++ b/tools/browser/support.c
@@ -237,7 +237,8 @@ browser_get_pixbuf_icon (BrowserIconType type)
 		"gda-browser-column-fknn.png",
 		"gda-browser-column-nn.png",
 		"gda-browser-reference.png",
-		"gda-browser-diagram.png"
+		"gda-browser-diagram.png",
+		"gda-browser-query.png"
 	};
 
 	if (!array)
diff --git a/tools/browser/support.h b/tools/browser/support.h
index 264fd67..2752605 100644
--- a/tools/browser/support.h
+++ b/tools/browser/support.h
@@ -58,6 +58,7 @@ typedef enum {
 	BROWSER_ICON_COLUMN_NN,
 	BROWSER_ICON_REFERENCE,
 	BROWSER_ICON_DIAGRAM,
+	BROWSER_ICON_QUERY,
 
 	BROWSER_ICON_LAST
 } BrowserIconType;



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