[libgda] GdaBrowser: added completion in editor on CTRL+SPACE



commit 8fa67680399f6719e227d9db4fa188e2f709c9ee
Author: Vivien Malerba <malerba gnome-db org>
Date:   Thu Oct 1 19:53:02 2009 +0200

    GdaBrowser: added completion in editor on CTRL+SPACE

 tools/browser/browser-connection.c             |   20 ++
 tools/browser/browser-connection.h             |    3 +
 tools/browser/doc/gda-browser-docs.sgml        |    2 +
 tools/browser/doc/gda-browser-sections.txt     |  181 +------------------
 tools/browser/doc/gda-browser.types            |    1 +
 tools/browser/doc/tmpl/browser-connection.sgml |   14 ++-
 tools/browser/doc/tmpl/browser-window.sgml     |    1 +
 tools/browser/doc/tmpl/popup-container.sgml    |   61 +++++++
 tools/browser/query-exec/query-editor.c        |  222 ++++++++++++++++++++++++
 tools/browser/query-exec/query-editor.h        |    3 +-
 10 files changed, 333 insertions(+), 175 deletions(-)
---
diff --git a/tools/browser/browser-connection.c b/tools/browser/browser-connection.c
index 695f3ce..d61fd81 100644
--- a/tools/browser/browser-connection.c
+++ b/tools/browser/browser-connection.c
@@ -736,6 +736,26 @@ browser_connection_get_favorites (BrowserConnection *bcnc)
 }
 
 /**
+ * browser_connection_get_completions
+ * @bcnc: a #BrowserConnection
+ * @sql:
+ * @start:
+ * @end:
+ *
+ * See gda_completion_list_get()
+ *
+ * Returns: a new array of strings, or NULL (use g_strfreev() to free the returned array)
+ */
+gchar **
+browser_connection_get_completions (BrowserConnection *bcnc, const gchar *sql,
+				    gint start, gint end)
+{
+	g_return_val_if_fail (BROWSER_IS_CONNECTION (bcnc), NULL);
+	return gda_completion_list_get (bcnc->priv->cnc, sql, start, end);
+}
+
+
+/**
  * browser_connection_create_parser
  * @bcnc: a #BrowserConnection
  *
diff --git a/tools/browser/browser-connection.h b/tools/browser/browser-connection.h
index e351106..7a38d03 100644
--- a/tools/browser/browser-connection.h
+++ b/tools/browser/browser-connection.h
@@ -68,6 +68,9 @@ const gchar        *browser_connection_get_dictionary_file    (BrowserConnection
 
 BrowserFavorites   *browser_connection_get_favorites          (BrowserConnection *bcnc);
 
+gchar             **browser_connection_get_completions        (BrowserConnection *bcnc, const gchar *sql,
+							       gint start, gint end);
+
 /*
  * statements's execution
  */
diff --git a/tools/browser/doc/gda-browser-docs.sgml b/tools/browser/doc/gda-browser-docs.sgml
index 0645633..28c1807 100644
--- a/tools/browser/doc/gda-browser-docs.sgml
+++ b/tools/browser/doc/gda-browser-docs.sgml
@@ -12,6 +12,7 @@
 <!ENTITY BrowserPage SYSTEM "xml/browser-page.xml">
 <!ENTITY BrowserPerspective SYSTEM "xml/browser-perspective.xml">
 <!ENTITY CCGrayBar SYSTEM "xml/cc-gray-bar.xml">
+<!ENTITY PopupContainer SYSTEM "xml/popup-container.xml">
 ]>
 
 <book id="index">
@@ -138,6 +139,7 @@
 	which can be used in any extension.
       </para>
       &CCGrayBar;
+      &PopupContainer;
     </chapter>
   </part>
 
diff --git a/tools/browser/doc/gda-browser-sections.txt b/tools/browser/doc/gda-browser-sections.txt
index 77702af..043dba4 100644
--- a/tools/browser/doc/gda-browser-sections.txt
+++ b/tools/browser/doc/gda-browser-sections.txt
@@ -1,37 +1,4 @@
 <SECTION>
-<FILE>browser-variable</FILE>
-BrowserVariablePrivate
-<TITLE>BrowserVariable</TITLE>
-BrowserVariable
-browser_variable_new
-<SUBSECTION Standard>
-BROWSER_VARIABLE
-BROWSER_IS_VARIABLE
-BROWSER_TYPE_VARIABLE
-browser_variable_get_type
-BROWSER_VARIABLE_CLASS
-</SECTION>
-
-<SECTION>
-<FILE>browser-spinner</FILE>
-BrowserSpinnerPriv
-<TITLE>BrowserSpinner</TITLE>
-BrowserSpinner
-browser_spinner_new
-browser_spinner_start
-browser_spinner_stop
-browser_spinner_set_size
-<SUBSECTION Standard>
-BROWSER_SPINNER
-BROWSER_IS_SPINNER
-BROWSER_TYPE_SPINNER
-browser_spinner_get_type
-BROWSER_SPINNER_CLASS
-BROWSER_IS_SPINNER_CLASS
-BROWSER_SPINNER_GET_CLASS
-</SECTION>
-
-<SECTION>
 <FILE>browser-window</FILE>
 BrowserWindowPrivate
 <TITLE>BrowserWindow</TITLE>
@@ -50,27 +17,6 @@ BROWSER_WINDOW_CLASS
 </SECTION>
 
 <SECTION>
-<FILE>auth-dialog</FILE>
-AuthDialogPrivate
-auth_dialog_error_quark
-AUTH_DIALOG_ERROR
-AuthDialogError
-<TITLE>AuthDialog</TITLE>
-AuthDialog
-AuthDialogConnection
-auth_dialog_new
-auth_dialog_add_cnc_string
-auth_dialog_run
-auth_dialog_get_connections
-<SUBSECTION Standard>
-AUTH_DIALOG
-AUTH_IS_DIALOG
-AUTH_TYPE_DIALOG
-auth_dialog_get_type
-AUTH_DIALOG_CLASS
-</SECTION>
-
-<SECTION>
 <FILE>browser-core</FILE>
 BrowserCorePrivate
 BrowserCoreInitFactories
@@ -119,24 +65,6 @@ CC_IS_GRAY_BAR_CLASS
 </SECTION>
 
 <SECTION>
-<FILE>login-dialog</FILE>
-LoginDialogPrivate
-login_dialog_error_quark
-LOGIN_DIALOG_ERROR
-LoginDialogError
-<TITLE>LoginDialog</TITLE>
-LoginDialog
-login_dialog_new
-login_dialog_run
-<SUBSECTION Standard>
-LOGIN_DIALOG
-LOGIN_IS_DIALOG
-LOGIN_TYPE_DIALOG
-login_dialog_get_type
-LOGIN_DIALOG_CLASS
-</SECTION>
-
-<SECTION>
 <FILE>browser-connection</FILE>
 BrowserConnectionPrivate
 <TITLE>BrowserConnection</TITLE>
@@ -150,6 +78,7 @@ browser_connection_get_meta_struct
 browser_connection_get_meta_store
 browser_connection_get_dictionary_file
 browser_connection_get_favorites
+browser_connection_get_completions
 browser_connection_create_parser
 browser_connection_render_pretty_sql
 browser_connection_execute_statement
@@ -168,20 +97,6 @@ BROWSER_CONNECTION_CLASS
 </SECTION>
 
 <SECTION>
-<FILE>browser-connections-list</FILE>
-BrowserConnectionsListPrivate
-<TITLE>BrowserConnectionsList</TITLE>
-BrowserConnectionsList
-browser_connections_list_show
-<SUBSECTION Standard>
-BROWSER_CONNECTIONS_LIST
-BROWSER_IS_CONNECTIONS_LIST
-BROWSER_TYPE_CONNECTIONS_LIST
-browser_connections_list_get_type
-BROWSER_CONNECTIONS_LIST_CLASS
-</SECTION>
-
-<SECTION>
 <FILE>browser-favorites</FILE>
 BrowserFavoritesPrivate
 BrowserFavoritesType
@@ -206,22 +121,6 @@ BROWSER_FAVORITES_CLASS
 </SECTION>
 
 <SECTION>
-<FILE>decl</FILE>
-BrowserCore
-BrowserVariable
-BrowserConnection
-BrowserWindow
-BrowserData
-BrowserPerspectiveIface
-BrowserPerspective
-BrowserPageIface
-BrowserPage
-BrowserPerspectiveFactory
-BROWSER_PERSPECTIVE_FACTORY
-ORDER_KEY_SCHEMA
-</SECTION>
-
-<SECTION>
 <FILE>browser-perspective</FILE>
 BROWSER_PERSPECTIVE_TYPE
 BROWSER_PERSPECTIVE
@@ -235,10 +134,6 @@ browser_perspective_page_tab_label_change
 </SECTION>
 
 <SECTION>
-<FILE>dnd</FILE>
-</SECTION>
-
-<SECTION>
 <FILE>browser-page</FILE>
 BROWSER_PAGE_TYPE
 BROWSER_PAGE
@@ -253,77 +148,19 @@ browser_page_get_tab_label
 </SECTION>
 
 <SECTION>
-<FILE>mgr-favorites</FILE>
-MGR_FAVORITES_TYPE
-MGR_FAVORITES
-MGR_FAVORITES_CLASS
-IS_MGR_FAVORITES
-IS_MGR_FAVORITES_CLASS
-MgrFavoritesPriv
-<TITLE>MgrFavorites</TITLE>
-MgrFavorites
-mgr_favorites_get_type
-mgr_favorites_new
-MGR_FAVORITES_CONTENTS_ATT_NAME
-MGR_FAVORITES_ID_ATT_NAME
-MGR_FAVORITES_TYPE_ATT_NAME
-</SECTION>
-
-<SECTION>
-<FILE>support</FILE>
-browser_connection_open
-browser_connection_close
-browser_show_error
-browser_make_tab_label_with_stock
-browser_make_tab_label_with_pixbuf
-browser_find_parent_widget
-BrowserIconType
-browser_get_pixbuf_icon
-</SECTION>
-
-<SECTION>
-<FILE>browser-stock-icons</FILE>
-BROWSER_STOCK_HISTORY
-BROWSER_STOCK_BOOKMARKS
-STOCK_NEW_WINDOW
-STOCK_ADD_BOOKMARK
-STOCK_PRINT_SETUP
-STOCK_CONSOLE
-browser_stock_icons_init
-</SECTION>
-
-<SECTION>
-<FILE>objects-cloud</FILE>
-OBJECTS_CLOUD_TYPE
-OBJECTS_CLOUD
-OBJECTS_CLOUD_CLASS
-IS_OBJECTS_CLOUD
-IS_OBJECTS_CLOUD_CLASS
-ObjectsCloudPrivate
-ObjectsCloudObjType
-<TITLE>ObjectsCloud</TITLE>
-ObjectsCloud
-objects_cloud_get_type
-objects_cloud_new
-objects_cloud_set_meta_struct
-objects_cloud_show_schemas
-objects_cloud_filter
-objects_cloud_create_filter
-</SECTION>
-
-<SECTION>
 <FILE>popup-container</FILE>
-POPUP_CONTAINER_TYPE
-POPUP_CONTAINER
-POPUP_CONTAINER_CLASS
-IS_POPUP_CONTAINER
-IS_POPUP_CONTAINER_CLASS
+PopupContainer
 PopupContainerPrivate
 PopupContainerPositionFunc
 <TITLE>PopupContainer</TITLE>
-PopupContainer
-popup_container_get_type
 popup_container_new
 popup_container_new_with_func
+<SUBSECTION Standard>
+popup_container_get_type
+POPUP_CONTAINER_TYPE
+POPUP_CONTAINER
+POPUP_CONTAINER_CLASS
+IS_POPUP_CONTAINER
+IS_POPUP_CONTAINER_CLASS
 </SECTION>
 
diff --git a/tools/browser/doc/gda-browser.types b/tools/browser/doc/gda-browser.types
index d45b817..121b9d1 100644
--- a/tools/browser/doc/gda-browser.types
+++ b/tools/browser/doc/gda-browser.types
@@ -5,3 +5,4 @@ browser_window_get_type
 browser_perspective_get_type
 browser_page_get_type
 cc_gray_bar_get_type
+popup_container_get_type
diff --git a/tools/browser/doc/tmpl/browser-connection.sgml b/tools/browser/doc/tmpl/browser-connection.sgml
index b7352be..9fbafa4 100644
--- a/tools/browser/doc/tmpl/browser-connection.sgml
+++ b/tools/browser/doc/tmpl/browser-connection.sgml
@@ -59,8 +59,6 @@ An opened connection
 
 </para>
 
-@:
-
 @browserconnection: the object which received the signal.
 
 <!-- ##### FUNCTION browser_connection_new ##### -->
@@ -144,6 +142,18 @@ An opened connection
 @Returns: 
 
 
+<!-- ##### FUNCTION browser_connection_get_completions ##### -->
+<para>
+
+</para>
+
+ bcnc: 
+ sql: 
+ start: 
+ end: 
+ Returns: 
+
+
 <!-- ##### FUNCTION browser_connection_create_parser ##### -->
 <para>
 
diff --git a/tools/browser/doc/tmpl/browser-window.sgml b/tools/browser/doc/tmpl/browser-window.sgml
index 26f2c57..cff4433 100644
--- a/tools/browser/doc/tmpl/browser-window.sgml
+++ b/tools/browser/doc/tmpl/browser-window.sgml
@@ -57,6 +57,7 @@ Top level browser window
 @bwin: 
 @context: 
 @text: 
+ auto_clear: 
 @Returns: 
 
 
diff --git a/tools/browser/doc/tmpl/popup-container.sgml b/tools/browser/doc/tmpl/popup-container.sgml
new file mode 100644
index 0000000..f9b5412
--- /dev/null
+++ b/tools/browser/doc/tmpl/popup-container.sgml
@@ -0,0 +1,61 @@
+<!-- ##### SECTION Title ##### -->
+PopupContainer
+
+<!-- ##### SECTION Short_Description ##### -->
+Popup window without any frame which hides itself when focus goes out
+
+<!-- ##### SECTION Long_Description ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION See_Also ##### -->
+<para>
+
+</para>
+
+<!-- ##### SECTION Stability_Level ##### -->
+
+
+<!-- ##### STRUCT PopupContainer ##### -->
+<para>
+
+</para>
+
+ parent: 
+ priv: 
+
+<!-- ##### STRUCT PopupContainerPrivate ##### -->
+<para>
+
+</para>
+
+
+<!-- ##### USER_FUNCTION PopupContainerPositionFunc ##### -->
+<para>
+
+</para>
+
+ cont: 
+ out_x: 
+ out_y: 
+
+
+<!-- ##### FUNCTION popup_container_new ##### -->
+<para>
+
+</para>
+
+ position_widget: 
+ Returns: 
+
+
+<!-- ##### FUNCTION popup_container_new_with_func ##### -->
+<para>
+
+</para>
+
+ pos_func: 
+ Returns: 
+
+
diff --git a/tools/browser/query-exec/query-editor.c b/tools/browser/query-exec/query-editor.c
index be0c55d..163e637 100644
--- a/tools/browser/query-exec/query-editor.c
+++ b/tools/browser/query-exec/query-editor.c
@@ -34,6 +34,9 @@
 #endif
 #include "query-editor.h"
 #include <binreloc/gda-binreloc.h>
+#include "../browser-connection.h"
+#include "../browser-window.h"
+#include "../common/popup-container.h"
 
 #define QUERY_EDITOR_LANGUAGE_SQL "gda-sql"
 #define COLOR_ALTER_FACTOR 1.8
@@ -82,6 +85,12 @@ struct _QueryEditorPrivate {
 			   */
 	QueryEditorHistoryBatch *insert_into_batch; /* hold ref here */
 	HistItemData *hist_focus; /* ref held here */
+
+	/* completion popup */
+	GtkWidget *completion_popup;
+	GtkTreeView *completion_treeview;
+	GtkCellRenderer *completion_renderer;
+	GtkWidget *completion_sw;
 };
 
 static void query_editor_class_init (QueryEditorClass *klass);
@@ -218,6 +227,209 @@ text_buffer_changed_cb (GtkTextBuffer *buffer, QueryEditor *editor)
 		g_signal_emit (editor, query_editor_signals[CHANGED], 0);
 }
 
+static void
+popup_container_position_func (PopupContainer *cont, gint *out_x, gint *out_y)
+{
+	QueryEditor *editor;
+	GdkWindow *wind;
+        gint x, y, ex, ey;
+	GtkTextBuffer *buffer;
+	GtkTextIter iter;
+	GdkRectangle rect;
+	GtkTextView *textview;
+
+        editor = g_object_get_data (G_OBJECT (cont), "editor");
+	textview = GTK_TEXT_VIEW (editor->priv->text);
+	buffer = gtk_text_view_get_buffer (textview);
+	gtk_text_buffer_get_iter_at_mark (buffer, &iter, gtk_text_buffer_get_insert (buffer));
+	gtk_text_view_get_iter_location (textview, &iter, &rect);
+	gtk_text_view_buffer_to_window_coords (textview, GTK_TEXT_WINDOW_WIDGET,
+					       rect.x, rect.y, &ex, &ey);
+
+	wind = gtk_text_view_get_window (textview, GTK_TEXT_WINDOW_WIDGET);
+        gdk_window_get_origin (wind, &x, &y);	
+
+        x += ex + rect.width;
+        y += ey + rect.height;
+
+        if (x < 0)
+                x = 0;
+
+        if (y < 0)
+                y = 0;
+
+        *out_x = x;
+        *out_y = y;
+}
+
+static gchar *
+get_string_to_complete (QueryEditor *editor, gchar **out_start_pos)
+{
+	GtkTextBuffer *buffer;
+	GtkTextIter start, end;
+	GtkTextMark *mark;
+
+	buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->priv->text));
+	mark = gtk_text_buffer_get_insert (buffer);
+	gtk_text_buffer_get_iter_at_mark (buffer, &end, mark);
+	gtk_text_buffer_get_start_iter (buffer, &start);
+
+	gchar *str, *ptr;
+			
+	str = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
+	if (!*str) {
+		g_free (str);
+		*out_start_pos = NULL;
+		return NULL;
+	}
+
+	for (ptr = str + strlen (str) - 1; ptr > str; ptr--) {
+		if (! g_ascii_isalnum (*ptr) &&
+		    (*ptr != '_') && (*ptr != '.')) {
+			ptr++;
+			break;
+		}
+	}
+	if ((ptr == str) &&
+	    ! g_ascii_isalnum (*ptr) &&
+	    (*ptr != '_'))
+		ptr++;
+	/*g_print ("completing [%s]\n", ptr);*/
+
+	*out_start_pos = ptr;
+	return str;
+}
+
+static void
+completion_row_activated_cb (GtkTreeView *treeview, GtkTreePath *path,
+			     GtkTreeViewColumn *column, QueryEditor *editor)
+{
+	GtkTreeModel *model;
+	GtkTreeIter iter;
+
+	gtk_widget_hide (editor->priv->completion_popup);
+	model = gtk_tree_view_get_model (editor->priv->completion_treeview);
+	if (gtk_tree_model_get_iter (model, &iter, path)) {
+		gchar *compl;
+		gchar *str, *ptr;
+
+		str = get_string_to_complete (editor, &ptr);
+		if (!str)
+			return;
+
+		gtk_tree_model_get (model, &iter, 0, &compl, -1);
+
+		GtkTextBuffer *buffer;
+		GtkTextIter start, end;
+
+		buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (editor->priv->text));
+		gtk_text_buffer_get_iter_at_mark (buffer, &end, gtk_text_buffer_get_insert (buffer));
+		start = end;
+		if (gtk_text_iter_backward_chars (&start, strlen (ptr))) {
+			gtk_text_buffer_delete (buffer, &start, &end);
+			gtk_text_buffer_insert (buffer, &end, compl, -1);
+			gtk_text_buffer_insert_at_cursor (buffer, " ", 1);
+		}
+
+		g_free (str);
+		g_free (compl);
+	}
+}
+
+static void
+display_completions (QueryEditor *editor)
+{
+	gchar *str, *ptr;
+
+	str = get_string_to_complete (editor, &ptr);
+	if (!str)
+		return;
+
+	BrowserConnection *bcnc;
+	gchar **compl;
+
+	bcnc = browser_window_get_connection ((BrowserWindow*) gtk_widget_get_toplevel ((GtkWidget*) editor));
+	compl = browser_connection_get_completions (bcnc, str, ptr - str, strlen (str));
+	g_free (str);
+
+	if (compl) {
+		GtkListStore *model;
+		if (! editor->priv->completion_popup) {
+			GtkWidget *treeview;
+			GtkCellRenderer *renderer;
+			GtkTreeViewColumn *column;
+			GtkWidget *popup, *sw;
+			
+			model = gtk_list_store_new (1, G_TYPE_STRING);
+			treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
+			gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
+			gtk_tree_view_set_grid_lines (GTK_TREE_VIEW (treeview), GTK_TREE_VIEW_GRID_LINES_NONE);
+			gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)),
+						     GTK_SELECTION_BROWSE);
+			g_object_unref (model);
+			
+			renderer = gtk_cell_renderer_text_new ();
+			g_object_set (G_OBJECT (renderer), "scale", 0.8,
+				      "background", "#ffff82", NULL);
+			column = gtk_tree_view_column_new_with_attributes ("", renderer,
+									   "text", 0, NULL);
+			gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+			
+			sw = gtk_scrolled_window_new (NULL, NULL);
+			gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
+							     GTK_SHADOW_NONE);
+			gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+							GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
+			gtk_container_add (GTK_CONTAINER (sw), treeview);
+			
+			popup = popup_container_new_with_func (popup_container_position_func);
+			g_object_set_data ((GObject*) popup, "editor", editor);
+			gtk_container_set_border_width (GTK_CONTAINER (popup), 0);
+			gtk_container_add (GTK_CONTAINER (popup), sw);
+			editor->priv->completion_popup = popup;
+			editor->priv->completion_treeview = GTK_TREE_VIEW (treeview);
+			editor->priv->completion_renderer = renderer;
+			editor->priv->completion_sw = sw;
+
+			g_signal_connect (treeview, "row-activated",
+					  G_CALLBACK (completion_row_activated_cb), editor);
+
+		}
+		else {
+			model = GTK_LIST_STORE (gtk_tree_view_get_model (editor->priv->completion_treeview));
+			gtk_list_store_clear (model);
+		}
+		
+		/* fill in the model */
+		GtkTreeIter iter;
+		gint w, width = 0, h, height = 0;
+		gint i;
+		
+		for (i = 0; ; i++) {
+			if (! compl[i])
+				break;
+			/*g_print ("==> [%s]\n", compl[i]);*/
+			gtk_list_store_append (model, &iter);
+			gtk_list_store_set (model, &iter, 0, compl[i], -1);
+			if (i == 0)
+				gtk_tree_selection_select_iter (gtk_tree_view_get_selection (editor->priv->completion_treeview),
+								&iter);
+
+			g_object_set ((GObject*) editor->priv->completion_renderer, "text", compl[i], NULL);
+			gtk_cell_renderer_get_size (editor->priv->completion_renderer,
+						    (GtkWidget*) editor->priv->completion_treeview,
+						    NULL, NULL, NULL, &w, &h);
+			width = MAX (width, w);
+			height += h + 2;
+		}
+		g_strfreev (compl);
+		
+		gtk_widget_set_size_request (editor->priv->completion_sw,
+					     MIN (width + 30, 400), MIN (height, 400));
+		gtk_widget_show_all (editor->priv->completion_popup);
+	}
+}
+
 /*
  * Returns: -1 if none focussed
  */
@@ -353,6 +565,12 @@ event (GtkWidget *text_view, GdkEvent *ev, QueryEditor *editor)
 			}
 			return TRUE;
 		}
+		else if ((editor->priv->mode == QUERY_EDITOR_READWRITE) && 
+			 (evkey->state & GDK_CONTROL_MASK) &&
+			 (evkey->keyval == GDK_space)) {
+			display_completions (editor);
+			return TRUE;
+		}
 	}
 	else
 		return FALSE;
@@ -450,6 +668,8 @@ query_editor_init (QueryEditor *editor, QueryEditorClass *klass)
 	editor->priv->current_state = G_MAXINT;
 	editor->priv->current_state_text = NULL;
 
+	editor->priv->completion_popup = NULL;
+
 	/* set up widgets */
 	editor->priv->scrolled_window = gtk_scrolled_window_new (NULL, NULL);
         gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (editor->priv->scrolled_window),
@@ -579,6 +799,8 @@ query_editor_finalize (GObject *object)
 		g_array_free (editor->priv->states, TRUE);
 	}
 	g_free (editor->priv->current_state_text);
+	if (editor->priv->completion_popup)
+		gtk_widget_destroy (editor->priv->completion_popup);
 
 	g_free (editor->priv);
 	editor->priv = NULL;
diff --git a/tools/browser/query-exec/query-editor.h b/tools/browser/query-exec/query-editor.h
index 63cb018..3aa207e 100644
--- a/tools/browser/query-exec/query-editor.h
+++ b/tools/browser/query-exec/query-editor.h
@@ -41,7 +41,8 @@ G_BEGIN_DECLS
 			       "   <small><b>CTRL - l</b></small> to clear the editor\n" \
 			       "   <small><b>CTRL - ENTER</b></small> to execute SQL\n" \
 			       "   <small><b>CTRL - Up</b></small> to move to previous executed SQL in history\n" \
-			       "   <small><b>CTRL - Down</b></small> to move to next executed SQL in history")
+			       "   <small><b>CTRL - Down</b></small> to move to next executed SQL in history" \
+			       "   <small><b>CTRL - SPACE</b></small> to obtain a completion list")
 
 typedef struct _QueryEditor        QueryEditor;
 typedef struct _QueryEditorClass   QueryEditorClass;



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