[libgda] GdaBrowser: started work on a query execution perspective



commit 1ce2e47b58da45fec68028345fe7cc457fc946b2
Author: Vivien Malerba <malerba gnome-db org>
Date:   Sun Aug 30 22:33:10 2009 +0200

    GdaBrowser: started work on a query execution perspective

 configure.in                                       |   22 +
 tools/browser/Makefile.am                          |    6 +-
 tools/browser/browser-connection.c                 |   19 +
 tools/browser/browser-connection.h                 |    1 +
 tools/browser/browser-core.c                       |   11 +-
 tools/browser/browser-stock-icons.h                |    2 +
 tools/browser/browser-window.c                     |    5 +-
 tools/browser/doc/gda-browser-sections.txt         |    1 +
 tools/browser/main.c                               |    2 +
 tools/browser/query-exec/Makefile.am               |   20 +
 tools/browser/query-exec/perspective-main.c        |   36 ++
 tools/browser/query-exec/perspective-main.h        |   29 ++
 tools/browser/query-exec/query-console.c           |  268 ++++++++++++
 tools/browser/query-exec/query-console.h           |   56 +++
 tools/browser/query-exec/query-editor.c            |  451 ++++++++++++++++++++
 tools/browser/query-exec/query-editor.h            |   73 ++++
 tools/browser/query-exec/query-exec-perspective.c  |  318 ++++++++++++++
 tools/browser/query-exec/query-exec-perspective.h  |   56 +++
 .../schema-browser/schema-browser-perspective.c    |    7 +-
 tools/browser/support.c                            |   22 +-
 20 files changed, 1390 insertions(+), 15 deletions(-)
---
diff --git a/configure.in b/configure.in
index 79f1b94..52d8273 100644
--- a/configure.in
+++ b/configure.in
@@ -145,6 +145,7 @@ dnl ******************************
 have_ui=no
 have_goocanvas=no
 have_graphviz=no
+have_sourceview=no
 AC_ARG_WITH(ui,
 	AS_HELP_STRING([--with-ui], [Enable GTK+ extension and tools]),
 	,with_ui=auto)
@@ -165,6 +166,10 @@ AM_CONDITIONAL(HAVE_UI, test x"$have_ui" = "xyes")
 AC_SUBST(GTK_CFLAGS)
 AC_SUBST(GTK_LIBS)
 
+AC_ARG_WITH(gtksourceview,
+AS_HELP_STRING([--with-gtksourceview], [Enable using GtkSourceView]),
+	,with_sourceview=auto)
+
 AC_ARG_WITH(goocanvas,
 AS_HELP_STRING([--with-goocanvas], [Enable using GooCanvas]),
 	,with_goo=auto)
@@ -175,6 +180,18 @@ AS_HELP_STRING([--with-graphviz], [Enable using Graphviz]),
 
 if test x"$have_ui" = "xyes"
 then
+	if test "$with_sourceview" = "auto" -o "$with_sourceview" = "yes"
+	then
+		PKG_CHECK_MODULES(GTKSOURCEVIEW, "gtksourceview-2.0", [
+			AC_DEFINE(HAVE_GTKSOURCEVIEW, [1], [GtkSourceView support enabled])
+			have_sourceview=yes], [
+			if test "$with_sourceview" = "yes"
+			then
+				AC_MSG_ERROR([GtkSourceview support requested but not found.])
+			fi
+			have_sourceview=no])
+	fi
+
 	if test "$with_goo" = "auto" -o "$with_goo" = "yes"
 	then
 		PKG_CHECK_MODULES(GOOCANVAS, "goocanvas", [
@@ -200,6 +217,10 @@ then
 	fi
 fi
 
+AM_CONDITIONAL(HAVE_GTKSOURCEVIEW, test x"$have_gtksourceview" = "xyes")
+AC_SUBST(GTKSOURCEVIEW_CFLAGS)
+AC_SUBST(GTKSOURCEVIEW_LIBS)
+
 AM_CONDITIONAL(HAVE_GOOCANVAS, test x"$have_goocanvas" = "xyes")
 AC_SUBST(GOOCANVAS_CFLAGS)
 AC_SUBST(GOOCANVAS_LIBS)
@@ -1728,6 +1749,7 @@ tools/browser/Makefile
 tools/browser/data/Makefile
 tools/browser/common/Makefile
 tools/browser/schema-browser/Makefile
+tools/browser/query-exec/Makefile
 tools/browser/dummy-perspective/Makefile
 tools/browser/canvas/Makefile
 tools/browser/doc/Makefile
diff --git a/tools/browser/Makefile.am b/tools/browser/Makefile.am
index ed53931..0e62382 100644
--- a/tools/browser/Makefile.am
+++ b/tools/browser/Makefile.am
@@ -1,7 +1,7 @@
 bin_PROGRAMS=gda-browser-4.0
 noinst_LTLIBRARIES = libbrowser.la
 
-SUBDIRS = data common schema-browser dummy-perspective
+SUBDIRS = data common schema-browser query-exec dummy-perspective
 if HAVE_GOOCANVAS
 SUBDIRS+=canvas
 noinst_PROGRAMS=canvas-example
@@ -14,6 +14,7 @@ AM_CPPFLAGS = \
         -I$(top_builddir) \
         $(LIBGDA_CFLAGS) \
         $(GTK_CFLAGS) \
+        $(GTKSOURCEVIEW_CFLAGS) \
         -DPREFIX=\""$(prefix)"\" \
         -DSYSCONFDIR=\""$(sysconfdir)"\" \
         -DDATADIR=\""$(datadir)"\" \
@@ -86,13 +87,14 @@ browser-res.o: browser-res.rc
 gda_browser_4_0_LDFLAGS = $(EXTRALDFLAGS)
 gda_browser_4_0_LDADD=\
 	$(top_builddir)/tools/browser/schema-browser/libperspective.la \
+	$(top_builddir)/tools/browser/query-exec/libperspective.la \
 	$(top_builddir)/tools/browser/dummy-perspective/libperspective.la \
 	$(top_builddir)/tools/browser/libbrowser.la \
 	$(CANVAS_LDADD) \
 	$(top_builddir)/tools/browser/common/libcommon.la \
 	$(top_builddir)/libgda/libgda-4.0.la \
 	$(top_builddir)/libgda-ui/libgda-ui-4.0.la \
-	$(LIBGDA_LIBS) $(GTK_LIBS)
+	$(LIBGDA_LIBS) $(GTK_LIBS) $(GTKSOURCEVIEW_LIBS)
 
 
 @INTLTOOL_DESKTOP_RULE@
diff --git a/tools/browser/browser-connection.c b/tools/browser/browser-connection.c
index bbae519..6fe8c5f 100644
--- a/tools/browser/browser-connection.c
+++ b/tools/browser/browser-connection.c
@@ -656,3 +656,22 @@ browser_connection_get_favorites (BrowserConnection *bcnc)
 	return bcnc->priv->bfav;
 }
 
+/**
+ * browser_connection_create_parser
+ * @bcnc: a #BrowserConnection
+ *
+ * Get a new #GdaSqlParser object for @bcnc
+ *
+ * Returns: a new #GdaSqlParser
+ */
+GdaSqlParser *
+browser_connection_create_parser (BrowserConnection *bcnc)
+{
+	GdaSqlParser *parser;
+	g_return_val_if_fail (BROWSER_IS_CONNECTION (bcnc), NULL);
+	
+	parser = gda_connection_create_parser (bcnc->priv->cnc);
+	if (!parser)
+		parser = gda_sql_parser_new ();
+	return parser;
+}
diff --git a/tools/browser/browser-connection.h b/tools/browser/browser-connection.h
index ed934ec..b6f95e4 100644
--- a/tools/browser/browser-connection.h
+++ b/tools/browser/browser-connection.h
@@ -70,6 +70,7 @@ BrowserFavorites   *browser_connection_get_favorites          (BrowserConnection
 /*
  * statements's execution
  */
+GdaSqlParser       *browser_connection_create_parser          (BrowserConnection *bcnc);
 /* TODO */
 
 G_END_DECLS
diff --git a/tools/browser/browser-core.c b/tools/browser/browser-core.c
index f1f5921..417f5b8 100644
--- a/tools/browser/browser-core.c
+++ b/tools/browser/browser-core.c
@@ -320,18 +320,27 @@ void
 browser_core_set_default_factory (const gchar *factory)
 {
 	GSList *list;
+	gchar *lc2;
 	_bcore = browser_core_get ();
 
 	if (!factory)
 		return;
 
+	lc2 = g_utf8_strdown (factory, -1);
 	for (list = _bcore->priv->factories; list; list = list->next) {
 		BrowserPerspectiveFactory *fact = (BrowserPerspectiveFactory*) list->data;
-		if (strstr (fact->perspective_name, factory)) {
+		gchar *lc1;
+		lc1 = g_utf8_strdown (fact->perspective_name, -1);
+
+		if (strstr (lc1, lc2)) {
 			_bcore->priv->default_factory = fact;
+			g_free (lc1);
 			break;
 		}
+
+		g_free (lc1);
 	}
+	g_free (lc2);
 }
 
 /**
diff --git a/tools/browser/browser-stock-icons.h b/tools/browser/browser-stock-icons.h
index 021030e..0691e94 100644
--- a/tools/browser/browser-stock-icons.h
+++ b/tools/browser/browser-stock-icons.h
@@ -30,6 +30,8 @@ G_BEGIN_DECLS
 #define STOCK_ADD_BOOKMARK         "bookmark-new"
 #define STOCK_PRINT_SETUP          "document-page-setup"
 
+#define STOCK_CONSOLE              "accessories-text-editor"
+
 void browser_stock_icons_init (void);
 
 G_END_DECLS
diff --git a/tools/browser/browser-window.c b/tools/browser/browser-window.c
index fd444db..73b4c58 100644
--- a/tools/browser/browser-window.c
+++ b/tools/browser/browser-window.c
@@ -206,6 +206,7 @@ static const GtkActionEntry ui_actions[] = {
         { "ConnectionMetaSync", GTK_STOCK_REFRESH, "_Fetch meta data", NULL, "Fetch meta data", G_CALLBACK (connection_meta_update_cb)},
         { "ConnectionClose", GTK_STOCK_CLOSE, "_Close connection", NULL, "Close this connection", G_CALLBACK (connection_close_cb)},
         { "Quit", GTK_STOCK_QUIT, "_Quit", NULL, "Quit", G_CALLBACK (quit_cb)},
+        { "Edit", NULL, "_Edit", NULL, "Edit", NULL },
         { "Perspective", NULL, "_Perspective", NULL, "Perspective", NULL },
         { "Window", NULL, "_Window", NULL, "Window", NULL },
         { "WindowNew", STOCK_NEW_WINDOW, "_New window", NULL, "Open a new window for current connection", G_CALLBACK (window_new_cb)},
@@ -227,6 +228,8 @@ static const gchar *ui_actions_info =
         "      <menuitem name='Quit' action= 'Quit'/>"
         "      <separator/>"
         "    </menu>"
+        "    <menu name='Edit' action='Edit'>"
+        "    </menu>"
         "    <menu name='Perspective' action='Perspective'>"
         "      <placeholder name='PersList'/>"
         "    </menu>"
@@ -929,7 +932,6 @@ browser_window_customize_perspective_ui (BrowserWindow *bwin, BrowserPerspective
 	if (pdata->customized_merge_id) {
 		gtk_ui_manager_remove_ui (bwin->priv->ui_manager, pdata->customized_merge_id);
 		pdata->customized_merge_id = 0;
-		gtk_ui_manager_ensure_update (bwin->priv->ui_manager);
 	}
 	if (pdata->customized_actions) {
 		gtk_ui_manager_remove_action_group (bwin->priv->ui_manager, pdata->customized_actions);
@@ -938,6 +940,7 @@ browser_window_customize_perspective_ui (BrowserWindow *bwin, BrowserPerspective
 	}
 	g_free (pdata->customized_ui);
 	pdata->customized_ui = NULL;
+	gtk_ui_manager_ensure_update (bwin->priv->ui_manager);
 
 	if (actions_group) {
 		g_return_if_fail (GTK_IS_ACTION_GROUP (actions_group));
diff --git a/tools/browser/doc/gda-browser-sections.txt b/tools/browser/doc/gda-browser-sections.txt
index 8032f8c..1974a8b 100644
--- a/tools/browser/doc/gda-browser-sections.txt
+++ b/tools/browser/doc/gda-browser-sections.txt
@@ -148,6 +148,7 @@ browser_connection_get_meta_struct
 browser_connection_get_meta_store
 browser_connection_get_dictionary_file
 browser_connection_get_favorites
+browser_connection_create_parser
 <SUBSECTION Standard>
 BROWSER_CONNECTION
 BROWSER_IS_CONNECTION
diff --git a/tools/browser/main.c b/tools/browser/main.c
index 1505276..ab9e4d1 100644
--- a/tools/browser/main.c
+++ b/tools/browser/main.c
@@ -33,6 +33,7 @@
 
 /* Perspectives' factories */
 #include "schema-browser/perspective-main.h"
+#include "query-exec/perspective-main.h"
 #include "dummy-perspective/perspective-main.h"
 
 
@@ -43,6 +44,7 @@ main_browser_core_init_factories (void)
 {
 	GSList *factories = NULL;
 	factories = g_slist_append (factories, schema_browser_perspective_get_factory ());
+	factories = g_slist_append (factories, query_exec_perspective_get_factory ());
 	factories = g_slist_append (factories, dummy_perspective_get_factory ());
 	return factories;
 }
diff --git a/tools/browser/query-exec/Makefile.am b/tools/browser/query-exec/Makefile.am
new file mode 100644
index 0000000..79345f9
--- /dev/null
+++ b/tools/browser/query-exec/Makefile.am
@@ -0,0 +1,20 @@
+noinst_LTLIBRARIES = libperspective.la
+
+AM_CPPFLAGS = \
+	-I$(top_srcdir)/tools/browser \
+	-I$(top_builddir) \
+	-I$(top_srcdir) \
+	-I$(top_srcdir)/libgda \
+	$(LIBGDA_CFLAGS) \
+	$(GTK_CFLAGS) \
+	$(GTKSOURCEVIEW_CFLAGS)
+
+libperspective_la_SOURCES = \
+	query-console.c \
+	query-console.h \
+	query-editor.c \
+	query-editor.h \
+	perspective-main.c \
+	perspective-main.h \
+	query-exec-perspective.h \
+	query-exec-perspective.c
diff --git a/tools/browser/query-exec/perspective-main.c b/tools/browser/query-exec/perspective-main.c
new file mode 100644
index 0000000..f10faf9
--- /dev/null
+++ b/tools/browser/query-exec/perspective-main.c
@@ -0,0 +1,36 @@
+/* GDA Postgres Provider
+ * Copyright (C) 2008 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; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glib/gi18n-lib.h>
+#include <gmodule.h>
+#include "perspective-main.h"
+#include "query-exec-perspective.h"
+
+static BrowserPerspectiveFactory bfact;
+
+BrowserPerspectiveFactory *
+query_exec_perspective_get_factory (void)
+{
+	bfact.perspective_name = "Query execution";
+	bfact.perspective_create = query_exec_perspective_new;
+
+	return &bfact;
+}
diff --git a/tools/browser/query-exec/perspective-main.h b/tools/browser/query-exec/perspective-main.h
new file mode 100644
index 0000000..4904810
--- /dev/null
+++ b/tools/browser/query-exec/perspective-main.h
@@ -0,0 +1,29 @@
+/* 
+ * Copyright (C) 2009 The GNOME Foundation.
+ *
+ * AUTHORS:
+ * 	Vivien Malerba <malerba gnome-db org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "../decl.h"
+
+G_BEGIN_DECLS
+
+BrowserPerspectiveFactory *query_exec_perspective_get_factory (void);
+
+G_END_DECLS
+
diff --git a/tools/browser/query-exec/query-console.c b/tools/browser/query-exec/query-console.c
new file mode 100644
index 0000000..9b5944c
--- /dev/null
+++ b/tools/browser/query-exec/query-console.c
@@ -0,0 +1,268 @@
+/*
+ * 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 "query-console.h"
+#include "../dnd.h"
+#include "../support.h"
+#include "../cc-gray-bar.h"
+#include "query-exec-perspective.h"
+#include "../browser-page.h"
+#include "../browser-stock-icons.h"
+#include "query-editor.h"
+#include <libgda/sql-parser/gda-sql-parser.h>
+
+struct _QueryConsolePrivate {
+	BrowserConnection *bcnc;
+	GdaSqlParser *parser;
+
+	CcGrayBar *header;
+	GtkWidget *vpaned; /* top=>query editor, bottom=>results */
+	QueryEditor *editor;
+};
+
+static void query_console_class_init (QueryConsoleClass *klass);
+static void query_console_init       (QueryConsole *tconsole, QueryConsoleClass *klass);
+static void query_console_dispose   (GObject *object);
+
+/* BrowserPage interface */
+static void                 query_console_page_init (BrowserPageIface *iface);
+static GtkActionGroup      *query_console_page_get_actions_group (BrowserPage *page);
+static const gchar         *query_console_page_get_actions_ui (BrowserPage *page);
+static GtkWidget           *query_console_page_get_tab_label (BrowserPage *page, GtkWidget **out_close_button);
+
+enum {
+	LAST_SIGNAL
+};
+
+static guint query_console_signals[LAST_SIGNAL] = { };
+static GObjectClass *parent_class = NULL;
+
+/*
+ * QueryConsole class implementation
+ */
+
+static void
+query_console_class_init (QueryConsoleClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	parent_class = g_type_class_peek_parent (klass);
+
+	object_class->dispose = query_console_dispose;
+}
+
+static void
+query_console_page_init (BrowserPageIface *iface)
+{
+	iface->i_get_actions_group = query_console_page_get_actions_group;
+	iface->i_get_actions_ui = query_console_page_get_actions_ui;
+	iface->i_get_tab_label = query_console_page_get_tab_label;
+}
+
+static void
+query_console_init (QueryConsole *tconsole, QueryConsoleClass *klass)
+{
+	tconsole->priv = g_new0 (QueryConsolePrivate, 1);
+	tconsole->priv->parser = NULL;
+}
+
+static void
+query_console_dispose (GObject *object)
+{
+	QueryConsole *tconsole = (QueryConsole *) object;
+
+	/* free memory */
+	if (tconsole->priv) {
+		if (tconsole->priv->bcnc)
+			g_object_unref (tconsole->priv->bcnc);
+		if (tconsole->priv->parser)
+			g_object_unref (tconsole->priv->parser);
+
+		g_free (tconsole->priv);
+		tconsole->priv = NULL;
+	}
+
+	parent_class->dispose (object);
+}
+
+GType
+query_console_get_type (void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY (type == 0)) {
+		static const GTypeInfo console = {
+			sizeof (QueryConsoleClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) query_console_class_init,
+			NULL,
+			NULL,
+			sizeof (QueryConsole),
+			0,
+			(GInstanceInitFunc) query_console_init
+		};
+
+		static GInterfaceInfo page_console = {
+                        (GInterfaceInitFunc) query_console_page_init,
+			NULL,
+                        NULL
+                };
+
+		type = g_type_register_static (GTK_TYPE_VBOX, "QueryConsole", &console, 0);
+		g_type_add_interface_static (type, BROWSER_PAGE_TYPE, &page_console);
+	}
+	return type;
+}
+
+/**
+ * query_console_new
+ *
+ * Returns: a new #GtkWidget
+ */
+GtkWidget *
+query_console_new (BrowserConnection *bcnc)
+{
+	QueryConsole *tconsole;
+
+	g_return_val_if_fail (BROWSER_IS_CONNECTION (bcnc), NULL);
+
+	tconsole = QUERY_CONSOLE (g_object_new (QUERY_CONSOLE_TYPE, NULL));
+
+	tconsole->priv->bcnc = g_object_ref (bcnc);
+	
+	/* header */
+        GtkWidget *label;
+	gchar *str;
+	str = g_strdup_printf ("<b>%s</b>", _("Query editor"));
+	label = cc_gray_bar_new (str);
+	g_free (str);
+        gtk_box_pack_start (GTK_BOX (tconsole), label, FALSE, FALSE, 0);
+        gtk_widget_show (label);
+	tconsole->priv->header = CC_GRAY_BAR (label);
+
+	/* main contents */
+	GtkWidget *vpaned;
+	vpaned = gtk_vpaned_new ();
+	tconsole->priv->vpaned = NULL;
+	gtk_box_pack_start (GTK_BOX (tconsole), vpaned, TRUE, TRUE, 0);	
+
+	GtkWidget *wid;
+	wid = query_editor_new ();
+	tconsole->priv->editor = QUERY_EDITOR (wid);
+	gtk_paned_add1 (GTK_PANED (vpaned), wid);
+
+	/* show everything */
+        gtk_widget_show_all (vpaned);
+
+	return (GtkWidget*) tconsole;
+}
+
+/*
+ * UI actions
+ */
+static void
+query_execute_cb (GtkAction *action, QueryConsole *tconsole)
+{
+	gchar *sql;
+	const gchar *remain;
+	GdaBatch *batch;
+	GError *error = NULL;
+
+	if (!tconsole->priv->parser)
+		tconsole->priv->parser = browser_connection_create_parser (tconsole->priv->bcnc);
+
+	sql = query_editor_get_all_text (tconsole->priv->editor);
+	batch = gda_sql_parser_parse_string_as_batch (tconsole->priv->parser, sql, &remain, &error);
+	if (!batch) {
+		browser_show_error (GTK_WINDOW (gtk_widget_get_toplevel ((GtkWidget*) tconsole)),
+				    _("Error while parsing code: %s"),
+				    error && error->message ? error->message : _("No detail"));
+		g_clear_error (&error);
+		g_free (sql);
+		return;
+	}
+
+	g_free (sql);
+	TO_IMPLEMENT;
+}
+
+#ifdef HAVE_GTKSOURCEVIEW
+static void
+editor_undo_cb (GtkAction *action, QueryConsole *tconsole)
+{
+	TO_IMPLEMENT;
+}
+#endif
+
+static GtkActionEntry ui_actions[] = {
+	{ "ExecuteQuery", GTK_STOCK_EXECUTE, N_("_Execute"), NULL, N_("Execute query"),
+	  G_CALLBACK (query_execute_cb)},
+#ifdef HAVE_GTKSOURCEVIEW
+	{ "EditorUndo", GTK_STOCK_UNDO, N_("_Undo"), NULL, N_("Undo last change"),
+	  G_CALLBACK (editor_undo_cb)},
+#endif
+};
+static const gchar *ui_actions_console =
+	"<ui>"
+	"  <menubar name='MenuBar'>"
+	"      <menu name='Edit' action='Edit'>"
+        "        <menuitem name='EditorUndo' action= 'EditorUndo'/>"
+        "      </menu>"
+	"  </menubar>"
+	"  <toolbar name='ToolBar'>"
+	"    <separator/>"
+	"    <toolitem action='ExecuteQuery'/>"
+	"  </toolbar>"
+	"</ui>";
+
+static GtkActionGroup *
+query_console_page_get_actions_group (BrowserPage *page)
+{
+	GtkActionGroup *agroup;
+	agroup = gtk_action_group_new ("QueryExecConsoleActions");
+	gtk_action_group_add_actions (agroup, ui_actions, G_N_ELEMENTS (ui_actions), page);
+	
+	return agroup;
+}
+
+static const gchar *
+query_console_page_get_actions_ui (BrowserPage *page)
+{
+	return ui_actions_console;
+}
+
+static GtkWidget *
+query_console_page_get_tab_label (BrowserPage *page, GtkWidget **out_close_button)
+{
+	QueryConsole *tconsole;
+	const gchar *tab_name;
+
+	tconsole = QUERY_CONSOLE (page);
+	tab_name = _("Query editor");
+	return browser_make_tab_label_with_stock (tab_name,
+						  STOCK_CONSOLE,
+						  out_close_button ? TRUE : FALSE, out_close_button);
+}
diff --git a/tools/browser/query-exec/query-console.h b/tools/browser/query-exec/query-console.h
new file mode 100644
index 0000000..d038d29
--- /dev/null
+++ b/tools/browser/query-exec/query-console.h
@@ -0,0 +1,56 @@
+/*
+ * 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_INFO_H__
+#define __QUERY_CONSOLE_H__
+
+#include <gtk/gtkvbox.h>
+#include "../browser-connection.h"
+
+G_BEGIN_DECLS
+
+#define QUERY_CONSOLE_TYPE            (query_console_get_type())
+#define QUERY_CONSOLE(obj)            (G_TYPE_CHECK_INSTANCE_CAST (obj, QUERY_CONSOLE_TYPE, QueryConsole))
+#define QUERY_CONSOLE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST (klass, QUERY_CONSOLE_TYPE, QueryConsoleClass))
+#define IS_QUERY_CONSOLE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE (obj, QUERY_CONSOLE_TYPE))
+#define IS_QUERY_CONSOLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), QUERY_CONSOLE_TYPE))
+
+typedef struct _QueryConsole        QueryConsole;
+typedef struct _QueryConsoleClass   QueryConsoleClass;
+typedef struct _QueryConsolePrivate QueryConsolePrivate;
+
+struct _QueryConsole {
+	GtkVBox               parent;
+	QueryConsolePrivate     *priv;
+};
+
+struct _QueryConsoleClass {
+	GtkVBoxClass          parent_class;
+};
+
+GType                    query_console_get_type (void) G_GNUC_CONST;
+
+GtkWidget               *query_console_new      (BrowserConnection *bcnc);
+
+G_END_DECLS
+
+#endif
diff --git a/tools/browser/query-exec/query-editor.c b/tools/browser/query-exec/query-editor.c
new file mode 100644
index 0000000..27349c9
--- /dev/null
+++ b/tools/browser/query-exec/query-editor.c
@@ -0,0 +1,451 @@
+/* GNOME DB library
+ * Copyright (C) 1999 - 2008 The GNOME Foundation.
+ *
+ * AUTHORS:
+ *      Rodrigo Moya <rodrigo gnome-db org>
+ *      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 <string.h>
+#include <gtk/gtk.h>
+#ifdef HAVE_GTKSOURCEVIEW
+  #include <gtksourceview/gtksourceview.h>
+  #include <gtksourceview/gtksourcelanguagemanager.h>
+  #include <gtksourceview/gtksourcebuffer.h>
+#endif
+#include "query-editor.h"
+
+#define PARENT_TYPE GTK_TYPE_VBOX
+
+typedef void (* CreateTagsFunc) (QueryEditor *editor, const gchar *language);
+
+struct _QueryEditorPrivate {
+	GtkWidget *scrolled_window;
+	GtkWidget *text;
+	guint config_lid;
+};
+
+static void query_editor_class_init (QueryEditorClass *klass);
+static void query_editor_init       (QueryEditor *editor, QueryEditorClass *klass);
+static void query_editor_finalize   (GObject *object);
+
+static GObjectClass *parent_class = NULL;
+static GHashTable *supported_languages = NULL;
+static gint number_of_objects = 0;
+
+/*
+ * Private functions
+ */
+static void
+create_tags_for_sql (QueryEditor *editor, const gchar *language)
+{
+	GtkTextBuffer *buffer;
+#ifdef HAVE_GTKSOURCEVIEW
+	GtkSourceLanguageManager *mgr;
+	GtkSourceLanguage *lang;
+#endif
+
+	g_return_if_fail (language != NULL);
+	g_return_if_fail (!strcmp (language, QUERY_EDITOR_LANGUAGE_SQL));
+
+	buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->priv->text));
+#ifdef HAVE_GTKSOURCEVIEW
+	mgr = gtk_source_language_manager_new ();
+	lang = gtk_source_language_manager_get_language (mgr, "sql");
+
+	if (lang) {
+		gtk_source_buffer_set_language (GTK_SOURCE_BUFFER (buffer), lang);
+		/* FIXME: extend for Gda's variables syntax */
+	}
+
+	g_object_unref (mgr);
+#endif
+}
+
+/*
+ * QueryEditor class implementation
+ */
+
+static void
+query_editor_class_init (QueryEditorClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	parent_class = g_type_class_peek_parent (klass);
+
+	object_class->finalize = query_editor_finalize;
+}
+
+#ifdef HAVE_GCONF
+static void
+configuration_changed_cb (GConfClient *conf_client, guint cnxn_id, GConfEntry *entry, gpointer user_data)
+{
+	QueryEditor *editor = (QueryEditor *) user_data;
+
+	g_return_if_fail (QUERY_IS_EDITOR (editor));
+
+	if (!strcmp (entry->key, QUERY_CONFIG_KEY_EDITOR_SHOW_LINE_NUMBERS)) {
+#ifdef HAVE_GTKSOURCEVIEW
+		gtk_source_view_set_show_line_numbers (
+			GTK_SOURCE_VIEW (editor->priv->text),
+			gconf_client_get_bool (gconf_client_get_default (), QUERY_CONFIG_KEY_EDITOR_SHOW_LINE_NUMBERS, NULL));
+#else
+#endif
+	} else if (!strcmp (entry->key, QUERY_CONFIG_KEY_EDITOR_TAB_STOP)) {
+#ifdef HAVE_GTKSOURCEVIEW
+		int tab = gconf_client_get_int (gconf_client_get_default (), QUERY_CONFIG_KEY_EDITOR_TAB_STOP, NULL);
+		gtk_source_view_set_tab_width (GTK_SOURCE_VIEW (editor->priv->text),
+					       tab ? tab : 8);
+#else
+#endif
+	} else if (!strcmp (entry->key, QUERY_CONFIG_KEY_EDITOR_HIGHLIGHT)) {
+		query_editor_set_highlight_syntax (editor,
+					       gconf_client_get_bool (gconf_client_get_default (), 
+								      QUERY_CONFIG_KEY_EDITOR_HIGHLIGHT, NULL));
+	}
+}
+#endif
+
+static void
+query_editor_init (QueryEditor *editor, QueryEditorClass *klass)
+{
+	int tab = 8;
+	gboolean highlight = TRUE;
+	gboolean showlinesno = FALSE;
+
+	g_return_if_fail (QUERY_IS_EDITOR (editor));
+
+	/* allocate private structure */
+	editor->priv = g_new0 (QueryEditorPrivate, 1);
+
+	/* set up widgets */
+	editor->priv->scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+        gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (editor->priv->scrolled_window),
+                                        GTK_POLICY_AUTOMATIC,
+                                        GTK_POLICY_AUTOMATIC);
+        gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (editor->priv->scrolled_window),
+					     GTK_SHADOW_NONE);
+	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (editor->priv->scrolled_window),
+					GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+	gtk_box_pack_start (GTK_BOX (editor), editor->priv->scrolled_window, TRUE, TRUE, 2);
+
+#ifdef HAVE_GTKSOURCEVIEW
+	editor->priv->text = gtk_source_view_new ();
+	gtk_source_buffer_set_highlight_syntax (GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->priv->text))),
+					 highlight);
+	gtk_source_view_set_show_line_numbers (GTK_SOURCE_VIEW (editor->priv->text), showlinesno);
+	gtk_source_view_set_tab_width (GTK_SOURCE_VIEW (editor->priv->text), tab);
+#else
+	editor->priv->text = gtk_text_view_new ();
+#endif
+	gtk_widget_show (editor->priv->text);
+
+	gtk_container_add (GTK_CONTAINER (editor->priv->scrolled_window), editor->priv->text);
+
+	/* initialize common data */
+	number_of_objects++;
+	if (!supported_languages) {
+		supported_languages = g_hash_table_new (g_str_hash, g_str_equal);
+
+		/* add the built-in languages */
+		g_hash_table_insert (supported_languages, QUERY_EDITOR_LANGUAGE_SQL, create_tags_for_sql);
+	}
+
+	create_tags_for_sql (editor, QUERY_EDITOR_LANGUAGE_SQL);
+}
+
+static void
+query_editor_finalize (GObject *object)
+{
+	QueryEditor *editor = (QueryEditor *) object;
+
+	g_return_if_fail (QUERY_IS_EDITOR (editor));
+
+	/* free memory */
+#ifdef HAVE_GCONF
+	gconf_client_notify_remove (gconf_client_get_default (), editor->priv->config_lid);
+#endif
+	g_free (editor->priv);
+	editor->priv = NULL;
+
+	parent_class->finalize (object);
+
+	/* update common data */
+	number_of_objects--;
+	if (number_of_objects == 0) {
+		g_hash_table_destroy (supported_languages);
+		supported_languages = NULL;
+	}
+}
+
+GType
+query_editor_get_type (void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY (type == 0)) {
+		static const GTypeInfo info = {
+			sizeof (QueryEditorClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) query_editor_class_init,
+			NULL,
+			NULL,
+			sizeof (QueryEditor),
+			0,
+			(GInstanceInitFunc) query_editor_init
+		};
+		type = g_type_register_static (PARENT_TYPE, "QueryEditor", &info, 0);
+	}
+	return type;
+}
+
+/**
+ * query_editor_new
+ *
+ * Create a new #QueryEditor widget, which is a multiline text widget
+ * with support for several languages used to write database stored
+ * procedures and functions. If libgnomedb was compiled with gtksourceview
+ * in, this widget will support syntax highlighting for all supported
+ * languages.
+ *
+ * Returns: the newly created widget.
+ */
+GtkWidget *
+query_editor_new (void)
+{
+	QueryEditor *editor;
+
+	editor = g_object_new (QUERY_TYPE_EDITOR, NULL);
+
+	return GTK_WIDGET (editor);
+}
+
+/**
+ * query_editor_get_editable
+ * @editor: a #QueryEditor widget.
+ *
+ * Retrieve the editable status of the given editor widget.
+ *
+ * Returns: the editable status.
+ */
+gboolean
+query_editor_get_editable (QueryEditor *editor)
+{
+        g_return_val_if_fail (QUERY_IS_EDITOR (editor), FALSE);
+
+        return gtk_text_view_get_editable (GTK_TEXT_VIEW (editor->priv->text));
+}
+
+/**
+ * query_editor_set_editable
+ * @editor: a #QueryEditor widget.
+ * @editable: editable state.
+ *
+ * Set the editable state of the given editor widget.
+ */
+void
+query_editor_set_editable (QueryEditor *editor, gboolean editable)
+{
+	g_return_if_fail (QUERY_IS_EDITOR (editor));
+	gtk_text_view_set_editable (GTK_TEXT_VIEW (editor->priv->text), editable);
+}
+
+/**
+ * query_editor_get_highlight
+ * @editor: a #QueryEditor widget.
+ *
+ * Retrieve the highlighting status of the given editor widget.
+ *
+ * Returns: the highlighting status.
+ */
+gboolean
+query_editor_get_highlight (QueryEditor *editor)
+{
+	g_return_val_if_fail (QUERY_IS_EDITOR (editor), FALSE);
+
+#ifdef HAVE_GTKSOURCEVIEW
+	return gtk_source_buffer_get_highlight_syntax (
+		GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->priv->text))));
+#else
+	return FALSE;
+#endif
+}
+
+/**
+ * query_editor_set_highlight
+ * @editor: a #QueryEditor widget.
+ * @highlight: highlighting status.
+ *
+ * Set the highlighting status on the given editor widget.
+ */
+void
+query_editor_set_highlight (QueryEditor *editor, gboolean highlight)
+{
+	g_return_if_fail (QUERY_IS_EDITOR (editor));
+
+#ifdef HAVE_GTKSOURCEVIEW
+	gtk_source_buffer_set_highlight_syntax (
+		GTK_SOURCE_BUFFER (gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->priv->text))), highlight);
+#endif
+}
+
+/**
+ * query_editor_set_text
+ * @editor: a #QueryEditor widget.
+ * @text: text to display in the editor.
+ * @len: length of @text.
+ *
+ * Set the contents of the given editor widget.
+ */
+void
+query_editor_set_text (QueryEditor *editor, const gchar *text, gint len)
+{
+	g_return_if_fail (QUERY_IS_EDITOR (editor));
+	gtk_text_buffer_set_text (gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->priv->text)),
+				  text, len);
+}
+
+/**
+ * query_editor_get_all_text
+ * @editor: a #QueryEditor widget.
+ *
+ * Retrieve the full contents of the given editor widget.
+ *
+ * Returns: the current contents of the editor buffer. You must free
+ * the returned value when no longer needed.
+ */
+gchar *
+query_editor_get_all_text (QueryEditor *editor)
+{
+	g_return_val_if_fail (QUERY_IS_EDITOR (editor), NULL);
+
+	GtkTextBuffer *buffer;
+        GtkTextIter start;
+        GtkTextIter end;
+
+        buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->priv->text));
+
+	gtk_text_buffer_get_start_iter (buffer, &start);
+	gtk_text_buffer_get_end_iter (buffer, &end);
+
+        return gtk_text_buffer_get_text (gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->priv->text)),
+                                         &start, &end, FALSE);
+}
+
+/**
+ * query_editor_load_from_file
+ * @editor: a #QueryEditor widget.
+ * @filename: the file to be loaded.
+ *
+ * Load the given filename into the editor widget.
+ *
+ * Returns: TRUE if successful, FALSE otherwise.
+ */
+gboolean
+query_editor_load_from_file (QueryEditor *editor, const gchar *filename)
+{
+	gboolean retval = TRUE;
+	gchar *contents;
+
+	g_return_val_if_fail (QUERY_IS_EDITOR (editor), FALSE);
+	g_return_val_if_fail (filename != NULL, FALSE);
+
+	if (g_file_get_contents (filename, &contents, NULL, NULL)) {
+		query_editor_set_text (editor, contents, -1);
+		g_free (contents);
+	}
+	else 
+		retval = FALSE;
+
+	return retval;
+}
+
+/**
+ * query_editor_save_to_file
+ * @editor: a #QueryEditor widget.
+ * @filename: the file to save to.
+ *
+ * Save the current editor contents to the given file.
+ *
+ * Returns: TRUE if successful, FALSE otherwise.
+ */
+gboolean
+query_editor_save_to_file (QueryEditor *editor, const gchar *filename)
+{
+	gchar *contents;
+	gboolean retval = TRUE;
+
+	g_return_val_if_fail (QUERY_IS_EDITOR (editor), FALSE);
+	g_return_val_if_fail (filename != NULL, FALSE);
+
+	contents = query_editor_get_all_text (editor);
+	if (!g_file_set_contents (filename, contents, strlen (contents), NULL))
+		retval = FALSE;
+
+	g_free (contents);
+
+	return retval;
+}
+
+/**
+ * query_editor_copy_clipboard
+ * @editor: a #QueryEditor widget.
+ *
+ * Copy currently selected text in the given editor widget to the clipboard.
+ */
+void
+query_editor_copy_clipboard (QueryEditor *editor)
+{
+	g_return_if_fail (QUERY_IS_EDITOR (editor));
+	gtk_text_buffer_copy_clipboard (gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->priv->text)),
+                                        gtk_clipboard_get (GDK_SELECTION_CLIPBOARD));
+}
+
+/**
+ * query_editor_cut_clipboard
+ * @editor: a #QueryEditor widget.
+ *
+ * Moves currently selected text in the given editor widget to the clipboard.
+ */
+void
+query_editor_cut_clipboard (QueryEditor *editor)
+{
+	g_return_if_fail (QUERY_IS_EDITOR (editor));
+
+	gtk_text_buffer_cut_clipboard (gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->priv->text)),
+                                       gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
+				       gtk_text_view_get_editable (GTK_TEXT_VIEW (editor->priv->text)));
+}
+
+/**
+ * query_editor_paste_clipboard
+ * @editor: a #QueryEditor widget.
+ *
+ * Paste clipboard contents into editor widget, at the current position.
+ */
+void
+query_editor_paste_clipboard (QueryEditor *editor)
+{
+	g_return_if_fail (QUERY_IS_EDITOR (editor));
+
+	gtk_text_buffer_paste_clipboard (gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->priv->text)),
+                                         gtk_clipboard_get (GDK_SELECTION_CLIPBOARD),
+                                         NULL,
+                                         gtk_text_view_get_editable (GTK_TEXT_VIEW (editor->priv->text)));
+}
diff --git a/tools/browser/query-exec/query-editor.h b/tools/browser/query-exec/query-editor.h
new file mode 100644
index 0000000..e55e386
--- /dev/null
+++ b/tools/browser/query-exec/query-editor.h
@@ -0,0 +1,73 @@
+/* GNOME DB library
+ * Copyright (C) 1999 - 2009 The GNOME Foundation.
+ *
+ * AUTHORS:
+ *      Rodrigo Moya <rodrigo gnome-db org>
+ *      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_EDITOR_H__
+#define __QUERY_EDITOR_H__
+
+#include <gtk/gtkvbox.h>
+
+G_BEGIN_DECLS
+
+#define QUERY_TYPE_EDITOR            (query_editor_get_type())
+#define QUERY_EDITOR(obj)            (G_TYPE_CHECK_INSTANCE_CAST (obj, QUERY_TYPE_EDITOR, QueryEditor))
+#define QUERY_EDITOR_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST (klass, QUERY_TYPE_EDITOR, QueryEditorClass))
+#define QUERY_IS_EDITOR(obj)         (G_TYPE_CHECK_INSTANCE_TYPE (obj, QUERY_TYPE_EDITOR))
+#define QUERY_IS_EDITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), QUERY_TYPE_EDITOR))
+
+typedef struct _QueryEditor        QueryEditor;
+typedef struct _QueryEditorClass   QueryEditorClass;
+typedef struct _QueryEditorPrivate QueryEditorPrivate;
+
+struct _QueryEditor {
+	GtkVBox parent;
+	QueryEditorPrivate *priv;
+};
+
+struct _QueryEditorClass {
+	GtkVBoxClass parent_class;
+
+	/* signals */
+	void (* text_changed) (QueryEditor editor);
+};
+
+#define QUERY_EDITOR_LANGUAGE_SQL "sql"
+
+GType      query_editor_get_type (void) G_GNUC_CONST;
+GtkWidget *query_editor_new (void);
+
+gboolean   query_editor_get_editable (QueryEditor *editor);
+void       query_editor_set_editable (QueryEditor *editor, gboolean editable);
+gboolean   query_editor_get_highlight (QueryEditor *editor);
+void       query_editor_set_highlight (QueryEditor *editor, gboolean highlight);
+void       query_editor_set_text (QueryEditor *editor, const gchar *text, gint len);
+gchar     *query_editor_get_all_text (QueryEditor *editor);
+gboolean   query_editor_load_from_file (QueryEditor *editor, const gchar *filename);
+gboolean   query_editor_save_to_file (QueryEditor *editor, const gchar *filename);
+
+void       query_editor_copy_clipboard (QueryEditor *editor);
+void       query_editor_cut_clipboard (QueryEditor *editor);
+void       query_editor_paste_clipboard (QueryEditor *editor);
+
+G_END_DECLS
+
+#endif
diff --git a/tools/browser/query-exec/query-exec-perspective.c b/tools/browser/query-exec/query-exec-perspective.c
new file mode 100644
index 0000000..bca6a1b
--- /dev/null
+++ b/tools/browser/query-exec/query-exec-perspective.c
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2009 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
+ * 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 <string.h>
+#include <glib/gi18n-lib.h>
+#include "query-exec-perspective.h"
+#include "../browser-window.h"
+#include "../browser-page.h"
+#include "query-console.h"
+#include "../browser-stock-icons.h"
+#include "../support.h"
+
+/* 
+ * Main static functions 
+ */
+static void query_exec_perspective_class_init (QueryExecPerspectiveClass *klass);
+static void query_exec_perspective_init (QueryExecPerspective *stmt);
+static void query_exec_perspective_dispose (GObject *object);
+
+/* BrowserPerspective interface */
+static void                 query_exec_perspective_perspective_init (BrowserPerspectiveIface *iface);
+static GtkActionGroup      *query_exec_perspective_get_actions_group (BrowserPerspective *perspective);
+static const gchar         *query_exec_perspective_get_actions_ui (BrowserPerspective *perspective);
+static void                 query_exec_perspective_page_tab_label_change (BrowserPerspective *perspective, BrowserPage *page);
+
+/* get a pointer to the parents to be able to call their destructor */
+static GObjectClass  *parent_class = NULL;
+
+struct _QueryExecPerspectivePrivate {
+	GtkWidget *notebook;
+	BrowserWindow *bwin;
+};
+
+GType
+query_exec_perspective_get_type (void)
+{
+	static GType type = 0;
+
+	if (G_UNLIKELY (type == 0)) {
+		static GStaticMutex registering = G_STATIC_MUTEX_INIT;
+		static const GTypeInfo info = {
+			sizeof (QueryExecPerspectiveClass),
+			(GBaseInitFunc) NULL,
+			(GBaseFinalizeFunc) NULL,
+			(GClassInitFunc) query_exec_perspective_class_init,
+			NULL,
+			NULL,
+			sizeof (QueryExecPerspective),
+			0,
+			(GInstanceInitFunc) query_exec_perspective_init
+		};
+
+		static GInterfaceInfo perspective_info = {
+                        (GInterfaceInitFunc) query_exec_perspective_perspective_init,
+			NULL,
+                        NULL
+                };
+		
+		g_static_mutex_lock (&registering);
+		if (type == 0) {
+			type = g_type_register_static (GTK_TYPE_VBOX, "QueryExecPerspective", &info, 0);
+			g_type_add_interface_static (type, BROWSER_PERSPECTIVE_TYPE, &perspective_info);
+		}
+		g_static_mutex_unlock (&registering);
+	}
+	return type;
+}
+
+static void
+query_exec_perspective_class_init (QueryExecPerspectiveClass * klass)
+{
+	GObjectClass   *object_class = G_OBJECT_CLASS (klass);
+	parent_class = g_type_class_peek_parent (klass);
+
+	object_class->dispose = query_exec_perspective_dispose;
+}
+
+static void
+query_exec_perspective_perspective_init (BrowserPerspectiveIface *iface)
+{
+	iface->i_get_actions_group = query_exec_perspective_get_actions_group;
+	iface->i_get_actions_ui = query_exec_perspective_get_actions_ui;
+	iface->i_page_tab_label_change = query_exec_perspective_page_tab_label_change;
+}
+
+
+static void
+query_exec_perspective_init (QueryExecPerspective *perspective)
+{
+	perspective->priv = g_new0 (QueryExecPerspectivePrivate, 1);
+}
+
+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,
+			       QueryExecPerspective *perspective);
+static void close_button_clicked_cb (GtkWidget *wid, GtkWidget *page_widget);
+
+/**
+ * query_exec_perspective_new
+ *
+ * Creates new #BrowserPerspective widget which 
+ */
+BrowserPerspective *
+query_exec_perspective_new (BrowserWindow *bwin)
+{
+	BrowserConnection *bcnc;
+	BrowserPerspective *bpers;
+	QueryExecPerspective *perspective;
+
+	bpers = (BrowserPerspective*) g_object_new (TYPE_QUERY_EXEC_PERSPECTIVE, NULL);
+	perspective = (QueryExecPerspective*) bpers;
+
+	perspective->priv->bwin = bwin;
+
+	/* contents */
+	GtkWidget *paned, *nb;
+	bcnc = browser_window_get_connection (bwin);
+	paned = gtk_hpaned_new ();
+	/*
+	wid = favorite_selector_new (bcnc);
+	g_signal_connect (wid, "selection-changed",
+			  G_CALLBACK (fav_selection_changed_cb), bpers);
+	gtk_paned_add1 (GTK_PANED (paned), wid);
+	*/
+
+	nb = gtk_notebook_new ();
+	perspective->priv->notebook = nb;
+	gtk_paned_add2 (GTK_PANED (paned), nb);
+	gtk_notebook_set_scrollable (GTK_NOTEBOOK (nb), TRUE);
+	gtk_notebook_popup_enable (GTK_NOTEBOOK (nb));
+	g_signal_connect (G_OBJECT (nb), "switch-page",
+			  G_CALLBACK (nb_switch_page_cb), perspective);
+	g_signal_connect (G_OBJECT (nb), "page-removed",
+			  G_CALLBACK (nb_page_removed_cb), perspective);
+
+	GtkWidget *page, *tlabel, *button;
+
+	page = query_console_new (bcnc);
+	tlabel = browser_page_get_tab_label (BROWSER_PAGE (page), &button);
+	g_signal_connect (button, "clicked",
+			  G_CALLBACK (close_button_clicked_cb), page);
+
+	gtk_notebook_append_page (GTK_NOTEBOOK (nb), page, tlabel);
+
+	gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (nb), page, TRUE);
+	gtk_notebook_set_group (GTK_NOTEBOOK (nb), bcnc + 0x01); /* add 0x01 to differentiate it from SchemaBrowser */
+	gtk_notebook_set_tab_detachable (GTK_NOTEBOOK (perspective->priv->notebook), page,
+					 TRUE);
+
+	tlabel = browser_page_get_tab_label (BROWSER_PAGE (page), NULL);
+	gtk_notebook_set_menu_label (GTK_NOTEBOOK (nb), page, tlabel);
+
+	gtk_box_pack_start (GTK_BOX (bpers), paned, TRUE, TRUE, 0);
+	gtk_widget_show_all (paned);
+
+	return bpers;
+}
+
+static void
+nb_switch_page_cb (GtkNotebook *nb, GtkNotebookPage *page, gint page_num,
+		   QueryExecPerspective *perspective)
+{
+	GtkWidget *page_contents;
+	GtkActionGroup *actions = NULL;
+	const gchar *ui = NULL;
+
+	page_contents = gtk_notebook_get_nth_page (nb, page_num);
+	if (IS_BROWSER_PAGE (page_contents)) {
+		actions = browser_page_get_actions_group (BROWSER_PAGE (page_contents));
+		ui = browser_page_get_actions_ui (BROWSER_PAGE (page_contents));
+	}
+	browser_window_customize_perspective_ui (perspective->priv->bwin,
+						 BROWSER_PERSPECTIVE (perspective), actions, 
+						 ui);
+	if (actions)
+		g_object_unref (actions);
+}
+
+static void
+nb_page_removed_cb (GtkNotebook *nb, GtkNotebookPage *page, gint page_num,
+		    QueryExecPerspective *perspective)
+{
+	if (gtk_notebook_get_n_pages (nb) == 0) {
+		browser_window_customize_perspective_ui (perspective->priv->bwin,
+							 BROWSER_PERSPECTIVE (perspective),
+							 NULL, NULL);
+	}
+}
+
+static void
+close_button_clicked_cb (GtkWidget *wid, GtkWidget *page_widget)
+{
+	gtk_widget_destroy (page_widget);
+}
+
+static void
+query_exec_perspective_dispose (GObject *object)
+{
+	QueryExecPerspective *perspective;
+
+	g_return_if_fail (object != NULL);
+	g_return_if_fail (IS_QUERY_EXEC_PERSPECTIVE (object));
+
+	perspective = QUERY_EXEC_PERSPECTIVE (object);
+	if (perspective->priv) {
+		g_signal_handlers_disconnect_by_func (perspective->priv->notebook,
+						      G_CALLBACK (nb_page_removed_cb), perspective);
+		g_free (perspective->priv);
+		perspective->priv = NULL;
+	}
+
+	/* parent class */
+	parent_class->dispose (object);
+}
+
+static void
+query_exec_add_cb (GtkAction *action, BrowserPerspective *bpers)
+{
+	GtkWidget *page, *tlabel, *button;
+	QueryExecPerspective *perspective;
+	BrowserConnection *bcnc;
+	gint i;
+
+	perspective = QUERY_EXEC_PERSPECTIVE (bpers);
+	bcnc = browser_window_get_connection (perspective->priv->bwin);
+
+	page = query_console_new (bcnc);
+	gtk_widget_show (page);
+	tlabel = browser_page_get_tab_label (BROWSER_PAGE (page), &button);
+	g_signal_connect (button, "clicked",
+			  G_CALLBACK (close_button_clicked_cb), page);
+
+
+	i = gtk_notebook_append_page (GTK_NOTEBOOK (perspective->priv->notebook), page, tlabel);
+	gtk_notebook_set_current_page (GTK_NOTEBOOK (perspective->priv->notebook), i);
+
+	gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (perspective->priv->notebook), page, TRUE);
+	gtk_notebook_set_tab_detachable (GTK_NOTEBOOK (perspective->priv->notebook), page,
+					 TRUE);
+
+	tlabel = browser_page_get_tab_label (BROWSER_PAGE (page), NULL);
+	gtk_notebook_set_menu_label (GTK_NOTEBOOK (perspective->priv->notebook), page, tlabel);
+}
+
+static GtkActionEntry ui_actions[] = {
+        { "QueryExecMenu", NULL, "_Query", NULL, "QueryExecMenu", NULL },
+        { "QueryExecItem1", STOCK_CONSOLE, "_New editor", NULL, "Open a new query editor",
+          G_CALLBACK (query_exec_add_cb)},
+};
+
+static const gchar *ui_actions_info =
+        "<ui>"
+        "  <menubar name='MenuBar'>"
+	"    <placeholder name='MenuExtension'>"
+        "      <menu name='QueryExec' action='QueryExecMenu'>"
+        "        <menuitem name='QueryExecItem1' action= 'QueryExecItem1'/>"
+        "      </menu>"
+	"    </placeholder>"
+        "  </menubar>"
+        "  <toolbar name='ToolBar'>"
+        "    <separator/>"
+        "    <toolitem action='QueryExecItem1'/>"
+        "  </toolbar>"
+        "</ui>";
+
+static GtkActionGroup *
+query_exec_perspective_get_actions_group (BrowserPerspective *bpers)
+{
+	GtkActionGroup *agroup;
+	agroup = gtk_action_group_new ("QueryExecActions");
+	gtk_action_group_add_actions (agroup, ui_actions, G_N_ELEMENTS (ui_actions), bpers);
+	
+	return agroup;
+}
+
+static const gchar *
+query_exec_perspective_get_actions_ui (BrowserPerspective *bpers)
+{
+	return ui_actions_info;
+}
+
+static void
+query_exec_perspective_page_tab_label_change (BrowserPerspective *perspective, BrowserPage *page)
+{
+	QueryExecPerspective *bpers;
+	GtkWidget *tab_label;
+	GtkWidget *close_btn;
+	
+	bpers = QUERY_EXEC_PERSPECTIVE (perspective);
+	tab_label = browser_page_get_tab_label (page, &close_btn);
+	if (tab_label) {
+		gtk_notebook_set_tab_label (GTK_NOTEBOOK (bpers->priv->notebook),
+					    GTK_WIDGET (page), tab_label);
+		g_signal_connect (close_btn, "clicked",
+				  G_CALLBACK (close_button_clicked_cb), page);
+		
+		tab_label = browser_page_get_tab_label (page, NULL);
+		gtk_notebook_set_menu_label (GTK_NOTEBOOK (bpers->priv->notebook),
+					     GTK_WIDGET (page), tab_label);
+	}
+}
diff --git a/tools/browser/query-exec/query-exec-perspective.h b/tools/browser/query-exec/query-exec-perspective.h
new file mode 100644
index 0000000..0e6edaa
--- /dev/null
+++ b/tools/browser/query-exec/query-exec-perspective.h
@@ -0,0 +1,56 @@
+/* 
+ * Copyright (C) 2009 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
+ * 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_EXEC_PERSPECTIVE_H_
+#define __QUERY_EXEC_PERSPECTIVE_H_
+
+#include <glib-object.h>
+#include "../browser-perspective.h"
+
+G_BEGIN_DECLS
+
+#define TYPE_QUERY_EXEC_PERSPECTIVE          (query_exec_perspective_get_type())
+#define QUERY_EXEC_PERSPECTIVE(obj)          G_TYPE_CHECK_INSTANCE_CAST (obj, query_exec_perspective_get_type(), QueryExecPerspective)
+#define QUERY_EXEC_PERSPECTIVE_CLASS(klass)  G_TYPE_CHECK_CLASS_CAST (klass, query_exec_perspective_get_type (), QueryExecPerspectiveClass)
+#define IS_QUERY_EXEC_PERSPECTIVE(obj)       G_TYPE_CHECK_INSTANCE_TYPE (obj, query_exec_perspective_get_type ())
+
+typedef struct _QueryExecPerspective QueryExecPerspective;
+typedef struct _QueryExecPerspectiveClass QueryExecPerspectiveClass;
+typedef struct _QueryExecPerspectivePrivate QueryExecPerspectivePrivate;
+
+/* struct for the object's data */
+struct _QueryExecPerspective
+{
+	GtkVBox              object;
+	QueryExecPerspectivePrivate *priv;
+};
+
+/* struct for the object's class */
+struct _QueryExecPerspectiveClass
+{
+	GtkVBoxClass         parent_class;
+};
+
+GType                query_exec_perspective_get_type               (void) G_GNUC_CONST;
+BrowserPerspective  *query_exec_perspective_new                    (BrowserWindow *bwin);
+
+G_END_DECLS
+
+#endif
diff --git a/tools/browser/schema-browser/schema-browser-perspective.c b/tools/browser/schema-browser/schema-browser-perspective.c
index c18dbb2..9c98e05 100644
--- a/tools/browser/schema-browser/schema-browser-perspective.c
+++ b/tools/browser/schema-browser/schema-browser-perspective.c
@@ -153,7 +153,6 @@ schema_browser_perspective_new (BrowserWindow *bwin)
 	wid = objects_index_new (bcnc);
 	g_signal_connect (wid, "selection-changed",
 			  G_CALLBACK (objects_index_selection_changed_cb), bpers);
-	gtk_paned_add2 (GTK_PANED (paned), wid);
 	gtk_notebook_append_page (GTK_NOTEBOOK (nb), wid,
 				  browser_make_tab_label_with_stock (_("Index"), GTK_STOCK_ABOUT, FALSE,
 								     NULL));
@@ -339,12 +338,14 @@ schema_browser_perspective_page_tab_label_change (BrowserPerspective *perspectiv
 	bpers = SCHEMA_BROWSER_PERSPECTIVE (perspective);
 	tab_label = browser_page_get_tab_label (page, &close_btn);
 	if (tab_label) {
-		gtk_notebook_set_tab_label (bpers->priv->notebook, GTK_WIDGET (page), tab_label);
+		gtk_notebook_set_tab_label (GTK_NOTEBOOK (bpers->priv->notebook),
+					    GTK_WIDGET (page), tab_label);
 		g_signal_connect (close_btn, "clicked",
 				  G_CALLBACK (close_button_clicked_cb), page);
 		
 		tab_label = browser_page_get_tab_label (page, NULL);
-		gtk_notebook_set_menu_label (bpers->priv->notebook, GTK_WIDGET (page), tab_label);
+		gtk_notebook_set_menu_label (GTK_NOTEBOOK (bpers->priv->notebook),
+					     GTK_WIDGET (page), tab_label);
 	}
 }
 
diff --git a/tools/browser/support.c b/tools/browser/support.c
index 63ae98e..8eb647a 100644
--- a/tools/browser/support.c
+++ b/tools/browser/support.c
@@ -105,7 +105,12 @@ browser_connection_close (GtkWindow *parent, BrowserConnection *bcnc)
 
 
 /**
- * show_error
+ * browser_show_error
+ * @parent: a #GtkWindow
+ * @format: printf() style format string
+ * @...: arguments for @format
+ *
+ * Displays a modal error notice untill the user aknowledges it.
  */
 void
 browser_show_error (GtkWindow *parent, const gchar *format, ...)
@@ -113,20 +118,18 @@ browser_show_error (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);
+        vsnprintf (sz, sizeof (sz), format, args);
         va_end (args);
 
         /* create the error message dialog */
-	tmp = g_strdup_printf ("<span weight=\"bold\">%s</span>\n%s", _("Error:"), sz);
 	dialog = gtk_message_dialog_new_with_markup (parent,
                                                      GTK_DIALOG_DESTROY_WITH_PARENT |
                                                      GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR,
-                                                     GTK_BUTTONS_CLOSE, "%s", tmp);
-	g_free (tmp);
+                                                     GTK_BUTTONS_CLOSE,
+						     "<span weight=\"bold\">%s</span>\n%s", _("Error:"), sz);
 
         gtk_widget_show_all (dialog);
         gtk_dialog_run (GTK_DIALOG (dialog));
@@ -194,8 +197,11 @@ browser_make_tab_label_with_stock (const gchar *label,
 				   GtkWidget **out_close_button)
 {
 	GtkWidget *image = NULL;
-	if (stock_id)
-		image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_MENU);
+	if (stock_id) {
+		image = gtk_image_new_from_icon_name (stock_id, GTK_ICON_SIZE_MENU);
+		if (!image)
+			image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_MENU);
+	}
 	return _browser_make_tab_label (label, image, with_close, out_close_button);
 }
 



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