[yelp/yelp-3-0] [yelp-location-entry] Doing automatic completion on topics in entry
- From: Shaun McCance <shaunm src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [yelp/yelp-3-0] [yelp-location-entry] Doing automatic completion on topics in entry
- Date: Fri, 26 Mar 2010 16:25:22 +0000 (UTC)
commit 8ab562c85d40b0a8a0b2cb142b97d77afcca4efb
Author: Shaun McCance <shaunm gnome org>
Date: Thu Mar 25 17:20:51 2010 -0500
[yelp-location-entry] Doing automatic completion on topics in entry
The core functionality is hooked up in YelpLocationEntry, but this commit
just uses the history GtkTreeModel. We need to get the page list out of
documents and use that for completion instead.
libyelp/Makefile.am | 26 ++++++-
libyelp/yelp-location-entry.c | 175 ++++++++++++++++++++++++++++++++++++++++-
libyelp/yelp-location-entry.h | 20 +++--
libyelp/yelp-marshal.list | 1 +
src/yelp-window.c | 27 ++++++
5 files changed, 238 insertions(+), 11 deletions(-)
---
diff --git a/libyelp/Makefile.am b/libyelp/Makefile.am
index ac847c5..85d2a40 100644
--- a/libyelp/Makefile.am
+++ b/libyelp/Makefile.am
@@ -8,6 +8,7 @@ libyelp_la_SOURCES = \
yelp-io-channel.c \
yelp-location-entry.c \
yelp-mallard-document.c \
+ yelp-marshal.c \
yelp-settings.c \
yelp-simple-document.c \
yelp-transform.c \
@@ -40,7 +41,30 @@ libyelp_include_HEADERS = \
$(libyelp_headers) \
yelp-types.h
-BUILT_SOURCES = yelp-types.c yelp-types.h
+BUILT_SOURCES = \
+ stamp-yelp-marshal.h \
+ yelp-marshal.c \
+ yelp-marshal.h \
+ yelp-types.c \
+ yelp-types.h
+
+EXTRA_DIST = yelp-marshal.list
+
+yelp-marshal.h: stamp-yelp-marshal.h
+ @true
+
+stamp-yelp-marshal.h: yelp-marshal.list
+ @GLIB_GENMARSHAL@ --prefix=yelp_marshal $(srcdir)/yelp-marshal.list --header > xgen-ymh \
+ && (cmp -s xgen-ymh yelp-marshal.h || cp xgen-ymh yelp-marshal.h) \
+ && rm -f xgen-ymh xgen-ymh~ \
+ && echo timestamp > $(@F)
+
+yelp-marshal.c: yelp-marshal.list
+ @GLIB_GENMARSHAL@ --prefix=yelp_marshal $(srcdir)/yelp-marshal.list --body > xgen-ymc \
+ && cp xgen-ymc yelp-marshal.c \
+ && rm -f xgen-ymc xgen-ymc~
+
+yelp-marshal-main.c: yelp-marshal.c
CLEANFILES = $(BUILT_SOURCES)
diff --git a/libyelp/yelp-location-entry.c b/libyelp/yelp-location-entry.c
index 52e6b3d..6b8f926 100644
--- a/libyelp/yelp-location-entry.c
+++ b/libyelp/yelp-location-entry.c
@@ -25,6 +25,7 @@
#include <glib/gi18n.h>
#include "yelp-location-entry.h"
+#include "yelp-marshal.h"
#include "yelp-settings.h"
/**
@@ -111,6 +112,22 @@ static void cell_set_text_cell (GtkCellLayout *layout,
GtkTreeIter *iter,
YelpLocationEntry *entry);
+/* GtkEntryCompletion callbacks */
+static void cell_set_completion_text_cell (GtkCellLayout *layout,
+ GtkCellRenderer *cell,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ YelpLocationEntry *entry);
+static gboolean entry_match_func (GtkEntryCompletion *completion,
+ const gchar *key,
+ GtkTreeIter *iter,
+ YelpLocationEntry *entry);
+static gboolean entry_match_selected (GtkEntryCompletion *completion,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ YelpLocationEntry *entry);
+
+
typedef struct _YelpLocationEntryPrivate YelpLocationEntryPrivate;
struct _YelpLocationEntryPrivate
{
@@ -126,10 +143,15 @@ struct _YelpLocationEntryPrivate
gboolean search_mode;
GtkCellRenderer *icon_cell;
+
+ /* owned by entry, do not free */
+ GtkEntryCompletion *completion;
+ gint completion_desc_column;
};
enum {
LOCATION_SELECTED,
+ COMPLETION_SELECTED,
SEARCH_ACTIVATED,
LAST_SIGNAL
};
@@ -168,7 +190,7 @@ yelp_location_entry_class_init (YelpLocationEntryClass *klass)
* will not be emitted.
**/
location_entry_signals[LOCATION_SELECTED] =
- g_signal_new ("location_selected",
+ g_signal_new ("location-selected",
G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
@@ -176,6 +198,24 @@ yelp_location_entry_class_init (YelpLocationEntryClass *klass)
G_TYPE_NONE, 0);
/**
+ * YelpLocationEntry::completion-selected
+ * @widget: The #YelpLocationEntry for which the signal was emitted.
+ * @model: The #GtkTreeModel contianing the completion.
+ * @iter: A #GtkTreeIter positioned at the completion.
+ * @user_data: User data set when the handler was connected.
+ *
+ * This signal will be emitted whenever a user selects an entry in the
+ * completion drop-down while typing.
+ **/
+ location_entry_signals[COMPLETION_SELECTED] =
+ g_signal_new ("completion-selected",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ yelp_marshal_VOID__OBJECT_BOXED,
+ G_TYPE_NONE, 2, GTK_TYPE_TREE_MODEL, GTK_TYPE_TREE_ITER);
+
+ /**
* YelpLocationEntry::search-activated
* @widget: The #YelpLocationEntry for which the signal was emitted.
* @text: The search text.
@@ -261,7 +301,8 @@ yelp_location_entry_class_init (YelpLocationEntryClass *klass)
sizeof (YelpLocationEntryPrivate));
}
-static void yelp_location_entry_init (YelpLocationEntry *entry)
+static void
+yelp_location_entry_init (YelpLocationEntry *entry)
{
YelpLocationEntryPrivate *priv = GET_PRIV (entry);
GList *cells;
@@ -289,7 +330,7 @@ static void yelp_location_entry_init (YelpLocationEntry *entry)
g_object_set (cells->data, "xpad", 4, NULL);
gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (entry),
GTK_CELL_RENDERER (cells->data),
- cell_set_text_cell,
+ (GtkCellLayoutDataFunc) cell_set_text_cell,
entry, NULL);
g_list_free (cells);
@@ -404,6 +445,49 @@ location_entry_start_search (YelpLocationEntry *entry,
gtk_widget_grab_focus (priv->text_entry);
}
+void
+yelp_location_entry_set_completion_model (YelpLocationEntry *entry,
+ GtkTreeModel *model,
+ gint text_column,
+ gint desc_column,
+ gint icon_column)
+{
+ YelpLocationEntryPrivate *priv = GET_PRIV (entry);
+ GList *cells;
+ GtkCellRenderer *icon_cell;
+
+ priv->completion = gtk_entry_completion_new ();
+ priv->completion_desc_column = desc_column;
+ gtk_entry_completion_set_model (priv->completion, model);
+ gtk_entry_completion_set_text_column (priv->completion, text_column);
+ gtk_entry_completion_set_match_func (priv->completion,
+ (GtkEntryCompletionMatchFunc) entry_match_func,
+ entry, NULL);
+ g_signal_connect (priv->completion, "match-selected",
+ G_CALLBACK (entry_match_selected), entry);
+
+ cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (priv->completion));
+ g_object_set (cells->data, "xpad", 4, NULL);
+ gtk_cell_layout_set_cell_data_func (GTK_CELL_LAYOUT (priv->completion),
+ GTK_CELL_RENDERER (cells->data),
+ (GtkCellLayoutDataFunc) cell_set_completion_text_cell,
+ entry, NULL);
+ g_list_free (cells);
+
+ icon_cell = gtk_cell_renderer_pixbuf_new ();
+ g_object_set (priv->icon_cell, "yalign", 0.2, NULL);
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (priv->completion), icon_cell, FALSE);
+ gtk_cell_layout_reorder (GTK_CELL_LAYOUT (priv->completion), icon_cell, 0);
+ gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (priv->completion),
+ icon_cell,
+ "icon-name",
+ icon_column,
+ NULL);
+
+ gtk_entry_set_completion (GTK_ENTRY (priv->text_entry),
+ priv->completion);
+}
+
static void
location_entry_set_entry (YelpLocationEntry *entry, gboolean emit)
{
@@ -684,6 +768,91 @@ cell_set_text_cell (GtkCellLayout *layout,
}
}
+static void
+cell_set_completion_text_cell (GtkCellLayout *layout,
+ GtkCellRenderer *cell,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ YelpLocationEntry *entry)
+{
+ gint text_col;
+ gchar *title, *desc, *color, *text;
+ YelpLocationEntryPrivate *priv = GET_PRIV (entry);
+
+ g_object_get (priv->completion, "text-column", &text_col, NULL);
+ if (text_col >= 0) {
+ gtk_tree_model_get (model, iter,
+ text_col, &title,
+ priv->completion_desc_column, &desc,
+ -1);
+ if (desc) {
+ color = yelp_settings_get_color (yelp_settings_get_default (),
+ YELP_SETTINGS_COLOR_TEXT_LIGHT);
+ text = g_markup_printf_escaped ("<span size='larger'>%s</span>\n<span color='%s'>%s</span>",
+ title, color, desc);
+ g_free (color);
+ g_free (desc);
+ }
+ else {
+ text = g_markup_printf_escaped ("<span size='larger'>%s</span>", title);
+ }
+
+ g_object_set (cell, "markup", text, NULL);
+ g_free (text);
+ g_free (title);
+ }
+}
+
+static gboolean
+entry_match_func (GtkEntryCompletion *completion,
+ const gchar *key,
+ GtkTreeIter *iter,
+ YelpLocationEntry *entry)
+{
+ gint text_col;
+ gchar *txt = NULL, *txtcase;
+ gboolean ret = FALSE;
+ GtkTreeModel *model = gtk_entry_completion_get_model (completion);
+
+ g_object_get (entry, "text-column", &text_col, NULL);
+ gtk_tree_model_get (model, iter, text_col, &txt, -1);
+ if (txt == NULL)
+ return FALSE;
+ txtcase = g_utf8_casefold (txt, -1);
+
+ if (strstr (txtcase, key))
+ ret = TRUE;
+
+ g_free (txtcase);
+ g_free (txt);
+ if (ret)
+ return ret;
+
+ g_object_get (entry, "desc-column", &text_col, NULL);
+ gtk_tree_model_get (model, iter, text_col, &txt, -1);
+ if (txt == NULL)
+ return FALSE;
+ txtcase = g_utf8_casefold (txt, -1);
+
+ if (strstr (txtcase, key))
+ ret = TRUE;
+
+ g_free (txtcase);
+ g_free (txt);
+
+ return ret;
+}
+
+static gboolean
+entry_match_selected (GtkEntryCompletion *completion,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ YelpLocationEntry *entry)
+{
+ g_signal_emit (entry, location_entry_signals[COMPLETION_SELECTED], 0, model, iter);
+ return TRUE;
+}
+
/**
* yelp_location_entry_new_with_model:
* @model: A #GtkTreeModel.
diff --git a/libyelp/yelp-location-entry.h b/libyelp/yelp-location-entry.h
index 6d6e306..08db5c9 100644
--- a/libyelp/yelp-location-entry.h
+++ b/libyelp/yelp-location-entry.h
@@ -79,14 +79,20 @@ typedef enum {
YELP_LOCATION_ENTRY_IS_SEARCH = 1 << 3
} YelpLocationEntryFlags;
-GType yelp_location_entry_get_type (void);
-GtkWidget* yelp_location_entry_new_with_model (GtkTreeModel *model,
- gint text_column,
- gint desc_column,
- gint icon_column,
- gint flags_column);
+GType yelp_location_entry_get_type (void);
+GtkWidget* yelp_location_entry_new_with_model (GtkTreeModel *model,
+ gint text_column,
+ gint desc_column,
+ gint icon_column,
+ gint flags_column);
-void yelp_location_entry_start_search (YelpLocationEntry *entry);
+void yelp_location_entry_set_completion_model (YelpLocationEntry *entry,
+ GtkTreeModel *model,
+ gint text_column,
+ gint desc_column,
+ gint icon_column);
+
+void yelp_location_entry_start_search (YelpLocationEntry *entry);
G_END_DECLS
diff --git a/libyelp/yelp-marshal.list b/libyelp/yelp-marshal.list
new file mode 100644
index 0000000..0467222
--- /dev/null
+++ b/libyelp/yelp-marshal.list
@@ -0,0 +1 @@
+VOID:OBJECT,BOXED
diff --git a/src/yelp-window.c b/src/yelp-window.c
index ca1dc7c..b6253bd 100644
--- a/src/yelp-window.c
+++ b/src/yelp-window.c
@@ -58,6 +58,10 @@ static void window_font_adjustment (GtkAction *action,
static void entry_location_selected (YelpLocationEntry *entry,
YelpWindow *window);
+static void entry_completion_selected (YelpLocationEntry *entry,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ YelpWindow *window);
static void back_button_clicked (GtkWidget *button,
YelpWindow *window);
@@ -231,6 +235,15 @@ yelp_window_init (YelpWindow *window)
COL_DESC,
COL_ICON,
COL_FLAGS);
+
+ yelp_location_entry_set_completion_model (YELP_LOCATION_ENTRY (priv->entry),
+ GTK_TREE_MODEL (priv->history),
+ COL_TITLE,
+ COL_DESC,
+ COL_ICON);
+ g_signal_connect (priv->entry, "completion-selected",
+ G_CALLBACK (entry_completion_selected), window);
+
priv->entry_location_selected = g_signal_connect (priv->entry, "location-selected",
G_CALLBACK (entry_location_selected), window);
priv->align_location = g_object_ref_sink (gtk_alignment_new (0.0, 0.5, 1.0, 0.0));
@@ -470,6 +483,20 @@ entry_location_selected (YelpLocationEntry *entry,
}
static void
+entry_completion_selected (YelpLocationEntry *entry,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ YelpWindow *window)
+{
+ gchar *uri;
+ YelpWindowPrivate *priv = GET_PRIV (window);
+ gtk_tree_model_get (model, iter, COL_URI, &uri, -1);
+ yelp_view_load (priv->view, uri);
+ g_free (uri);
+ gtk_widget_grab_focus (GTK_WIDGET (priv->view));
+}
+
+static void
back_button_clicked (GtkWidget *button,
YelpWindow *window)
{
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]