aboutsummaryrefslogtreecommitdiffstats
path: root/lib/widgets/ephy-location-entry.c
diff options
context:
space:
mode:
authorMarco Pesenti Gritti <marco@src.gnome.org>2003-10-12 01:41:26 +0800
committerMarco Pesenti Gritti <marco@src.gnome.org>2003-10-12 01:41:26 +0800
commit890b0f0278c284b3f72b17b2a320d7f443683d77 (patch)
tree838de9eb530807959804418a6d14f44eb8036e82 /lib/widgets/ephy-location-entry.c
parent0b5f13ef5a9f6a28812cfa959ad9f5b786312ad2 (diff)
downloadgsoc2013-epiphany-890b0f0278c284b3f72b17b2a320d7f443683d77.tar
gsoc2013-epiphany-890b0f0278c284b3f72b17b2a320d7f443683d77.tar.gz
gsoc2013-epiphany-890b0f0278c284b3f72b17b2a320d7f443683d77.tar.bz2
gsoc2013-epiphany-890b0f0278c284b3f72b17b2a320d7f443683d77.tar.lz
gsoc2013-epiphany-890b0f0278c284b3f72b17b2a320d7f443683d77.tar.xz
gsoc2013-epiphany-890b0f0278c284b3f72b17b2a320d7f443683d77.tar.zst
gsoc2013-epiphany-890b0f0278c284b3f72b17b2a320d7f443683d77.zip
Merge completion branch
Diffstat (limited to 'lib/widgets/ephy-location-entry.c')
-rw-r--r--lib/widgets/ephy-location-entry.c876
1 files changed, 335 insertions, 541 deletions
diff --git a/lib/widgets/ephy-location-entry.c b/lib/widgets/ephy-location-entry.c
index bca1d9790..c160a898e 100644
--- a/lib/widgets/ephy-location-entry.c
+++ b/lib/widgets/ephy-location-entry.c
@@ -20,106 +20,78 @@
* $Id$
*/
+#include "ephy-tree-model-node.h"
#include "ephy-location-entry.h"
-#include "ephy-autocompletion-window.h"
#include "ephy-marshal.h"
-#include "eel-gconf-extensions.h"
-#include "ephy-prefs.h"
#include "ephy-debug.h"
+#include "ephy-file-helpers.h"
-#include <glib-object.h>
-#include <gtk/gtkhbox.h>
+#include <gtk/gtktoolbar.h>
+#include <gtk/gtkliststore.h>
+#include <gtk/gtkcomboboxentry.h>
#include <gtk/gtkentry.h>
#include <gtk/gtkwindow.h>
-#include <gdk/gdkkeysyms.h>
-#include <gtk/gtkmain.h>
-#include <gtk/gtktoolbar.h>
-#include <gtk/gtktooltips.h>
-#include <libgnomeui/gnome-entry.h>
+#include <gtk/gtkcellrenderertext.h>
+#include <gtk/gtkcelllayout.h>
+#include <gtk/gtktreemodelsort.h>
#include <string.h>
-/**
- * Private data
- */
-
#define EPHY_LOCATION_ENTRY_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_LOCATION_ENTRY, EphyLocationEntryPrivate))
-struct _EphyLocationEntryPrivate {
+struct _EphyLocationEntryPrivate
+{
+ EphyTreeModelNode *combo_model;
GtkWidget *combo;
GtkWidget *entry;
char *before_completion;
- EphyAutocompletion *autocompletion;
- EphyAutocompletionWindow *autocompletion_window;
- gboolean autocompletion_window_visible;
- gint show_alternatives_timeout;
- gboolean block_set_autocompletion_key;
- gboolean going_to_site;
gboolean user_changed;
gboolean activation_mode;
+ EphyNodeDb *combo_db;
+ EphyNode *combo_root;
+ char *xml_file;
+
+ guint text_col;
+ guint action_col;
+ guint keywords_col;
+ guint relevance_col;
+};
- char *autocompletion_key;
- char *last_action_target;
+static char *web_prefixes [] =
+{
+ "http://www.",
+ "http://",
+ "https://www.",
+ "https://",
+ "www."
};
+static int n_web_prefixes = G_N_ELEMENTS (web_prefixes);
-#define AUTOCOMPLETION_DELAY 10
-#define SHOW_ALTERNATIVES_DELAY 100
-
-/**
- * Private functions, only availble from this file
- */
-static void ephy_location_entry_class_init (EphyLocationEntryClass *klass);
-static void ephy_location_entry_init (EphyLocationEntry *w);
-static void ephy_location_entry_finalize_impl (GObject *o);
-static void ephy_location_entry_construct_contents (EphyLocationEntry *w);
-static gboolean ephy_location_entry_key_press_event_cb (GtkWidget *entry, GdkEventKey *event,
- EphyLocationEntry *w);
-static void ephy_location_entry_activate_cb (GtkEntry *entry,
- EphyLocationEntry *w);
-static void ephy_location_entry_autocompletion_sources_changed_cb
- (EphyAutocompletion *aw,
- EphyLocationEntry *w);
-static gint ephy_location_entry_autocompletion_show_alternatives_to (EphyLocationEntry *w);
-static void ephy_location_entry_autocompletion_window_url_activated_cb
- (EphyAutocompletionWindow *aw,
- const gchar *target,
- int action,
- EphyLocationEntry *w);
-static void ephy_location_entry_list_event_after_cb (GtkWidget *list,
- GdkEvent *event,
- EphyLocationEntry *e);
-static void ephy_location_entry_editable_changed_cb (GtkEditable *editable,
- EphyLocationEntry *e);
-static void ephy_location_entry_set_autocompletion_key (EphyLocationEntry *e);
-static void ephy_location_entry_autocompletion_show_alternatives (EphyLocationEntry *w);
-static void ephy_location_entry_autocompletion_hide_alternatives (EphyLocationEntry *w);
-static void ephy_location_entry_autocompletion_window_hidden_cb
- (EphyAutocompletionWindow *aw,
- EphyLocationEntry *w);
-static void
-insert_text_cb (GtkWidget *editable,
- char *new_text,
- int new_text_length,
- int *position,
- EphyLocationEntry *w);
-static void
-delete_text_cb (GtkWidget *editable,
- int start_pos,
- int end_pos,
- EphyLocationEntry *w);
+static void ephy_location_entry_class_init (EphyLocationEntryClass *klass);
+static void ephy_location_entry_init (EphyLocationEntry *le);
+static void ephy_location_entry_finalize (GObject *o);
static GObjectClass *parent_class = NULL;
-/**
- * Signals enums and ids
- */
-enum EphyLocationEntrySignalsEnum {
- ACTIVATED,
+enum EphyLocationEntrySignalsEnum
+{
USER_CHANGED,
LAST_SIGNAL
};
static gint EphyLocationEntrySignals[LAST_SIGNAL];
-#define MENU_ID "ephy-location-entry-menu-id"
+enum
+{
+ LOCATION_HISTORY_NODE_ID = 1
+};
+
+enum
+{
+ EPHY_NODE_LOC_HISTORY_PROP_TEXT = 1
+};
+
+#define MAX_LOC_HISTORY_ITEMS 10
+#define EPHY_LOC_HISTORY_XML_ROOT "ephy_location_history"
+#define EPHY_LOC_HISTORY_XML_VERSION "0.1"
GType
ephy_location_entry_get_type (void)
@@ -172,20 +144,10 @@ ephy_location_entry_class_init (EphyLocationEntryClass *klass)
parent_class = g_type_class_peek_parent (klass);
- object_class->finalize = ephy_location_entry_finalize_impl;
+ object_class->finalize = ephy_location_entry_finalize;
tool_item_class->set_tooltip = ephy_location_entry_set_tooltip;
- EphyLocationEntrySignals[ACTIVATED] = g_signal_new (
- "activated", G_OBJECT_CLASS_TYPE (klass),
- G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST | G_SIGNAL_RUN_CLEANUP,
- G_STRUCT_OFFSET (EphyLocationEntryClass, activated),
- NULL, NULL,
- ephy_marshal_VOID__STRING_STRING,
- G_TYPE_NONE,
- 2,
- G_TYPE_STRING,
- G_TYPE_STRING);
EphyLocationEntrySignals[USER_CHANGED] = g_signal_new (
"user_changed", G_OBJECT_CLASS_TYPE (klass),
G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST | G_SIGNAL_RUN_CLEANUP,
@@ -215,78 +177,30 @@ ephy_location_entry_activation_finished (EphyLocationEntry *entry)
}
static gboolean
-location_focus_out_cb (GtkWidget *widget, GdkEventFocus *event, EphyLocationEntry *w)
+location_focus_out_cb (GtkWidget *leidget, GdkEventFocus *event, EphyLocationEntry *le)
{
- ephy_location_entry_activation_finished (w);
+ ephy_location_entry_activation_finished (le);
return FALSE;
}
static void
-ephy_location_entry_init (EphyLocationEntry *w)
+editable_changed_cb (GtkEditable *editable, EphyLocationEntry *e)
{
- EphyLocationEntryPrivate *p;
-
- LOG ("EphyLocationEntry initialising %p", w)
-
- p = EPHY_LOCATION_ENTRY_GET_PRIVATE (w);
- w->priv = p;
-
- p->last_action_target = NULL;
- p->before_completion = NULL;
- p->user_changed = TRUE;
- p->activation_mode = FALSE;
- p->autocompletion_key = NULL;
- p->autocompletion_window_visible = FALSE;
-
- ephy_location_entry_construct_contents (w);
-
- gtk_tool_item_set_expand (GTK_TOOL_ITEM (w), TRUE);
-
- g_signal_connect (w->priv->entry,
- "focus_out_event",
- G_CALLBACK (location_focus_out_cb),
- w);
-}
-
-static void
-ephy_location_entry_finalize_impl (GObject *o)
-{
- EphyLocationEntry *w = EPHY_LOCATION_ENTRY (o);
- EphyLocationEntryPrivate *p = w->priv;
+ EphyLocationEntryPrivate *p = e->priv;
- if (p->autocompletion)
+ if (p->user_changed)
{
- g_signal_handlers_disconnect_matched (p->autocompletion, G_SIGNAL_MATCH_DATA, 0, 0,
- NULL, NULL, w);
-
- g_signal_handlers_disconnect_matched (p->autocompletion_window, G_SIGNAL_MATCH_DATA, 0, 0,
- NULL, NULL, w);
-
- g_object_unref (G_OBJECT (p->autocompletion));
- g_object_unref (G_OBJECT (p->autocompletion_window));
+ g_signal_emit (e, EphyLocationEntrySignals[USER_CHANGED], 0);
}
-
- LOG ("EphyLocationEntry finalized")
-
- g_free (p->before_completion);
- g_free (p->autocompletion_key);
-
- G_OBJECT_CLASS (parent_class)->finalize (o);
-}
-
-GtkWidget *
-ephy_location_entry_new (void)
-{
- return GTK_WIDGET (g_object_new (EPHY_TYPE_LOCATION_ENTRY, NULL));
}
static gboolean
-ephy_location_entry_button_press_event_cb (GtkWidget *entry, GdkEventButton *event, EphyLocationEntry *w)
+entry_button_press_cb (GtkWidget *entry, GdkEventButton *event, EphyLocationEntry *le)
{
if (event->button == 1 && event->type == GDK_2BUTTON_PRESS)
{
- ephy_location_entry_activate (w);
+ ephy_location_entry_activate (le);
return TRUE;
}
@@ -294,513 +208,393 @@ ephy_location_entry_button_press_event_cb (GtkWidget *entry, GdkEventButton *eve
}
static void
-ephy_location_entry_construct_contents (EphyLocationEntry *w)
+add_to_history (EphyLocationEntry *le, const char *text)
{
- EphyLocationEntryPrivate *p = w->priv;
- GtkWidget *hbox, *list;
-
- LOG ("EphyLocationEntry constructing contents %p", w)
+ GPtrArray *children;
+ int i, l, n_items, index = -1;
+ int *order;
- hbox = gtk_hbox_new (FALSE, 0);
- gtk_container_add (GTK_CONTAINER (w), hbox);
- gtk_widget_show (hbox);
-
- p->combo = gnome_entry_new ("ephy-url-history");
- p->entry = GTK_COMBO (p->combo)->entry;
- gtk_widget_show (p->combo);
- gtk_box_pack_start (GTK_BOX (hbox), p->combo, TRUE, TRUE, 0);
-
- g_signal_connect (p->entry, "key-press-event",
- G_CALLBACK (ephy_location_entry_key_press_event_cb), w);
- g_signal_connect (p->entry, "insert-text",
- G_CALLBACK (insert_text_cb), w);
- g_signal_connect (p->entry, "delete-text",
- G_CALLBACK (delete_text_cb), w);
- g_signal_connect (p->entry, "button-press-event",
- G_CALLBACK (ephy_location_entry_button_press_event_cb), w);
-
- g_signal_connect (p->entry, "activate",
- G_CALLBACK (ephy_location_entry_activate_cb), w);
-
- g_signal_connect (p->entry, "changed",
- G_CALLBACK (ephy_location_entry_editable_changed_cb), w);
-
- list = GTK_COMBO (p->combo)->list;
+ /* check if it already exists */
+ children = ephy_node_get_children (le->priv->combo_root);
+ n_items = children->len;
+ for (i = 0; i < n_items; i++)
+ {
+ EphyNode *kid;
+ const char *node_text;
+
+ kid = g_ptr_array_index (children, i);
+ node_text = ephy_node_get_property_string
+ (kid, EPHY_NODE_LOC_HISTORY_PROP_TEXT);
+
+ if (strcmp (text, node_text) == 0)
+ {
+ index = i;
+ break;
+ }
+ }
+ ephy_node_thaw (le->priv->combo_root);
- g_signal_connect_after (list, "event-after",
- G_CALLBACK (ephy_location_entry_list_event_after_cb), w);
+ /* it doesnt exist, add it */
+ if (index < 0)
+ {
+ GValue value = { 0, };
+ EphyNode *node;
-}
+ node = ephy_node_new (le->priv->combo_db);
+ g_value_init (&value, G_TYPE_STRING);
+ g_value_set_string (&value, text);
+ ephy_node_set_property (node, EPHY_NODE_LOC_HISTORY_PROP_TEXT,
+ &value);
-static gboolean
-ephy_location_ignore_prefix (EphyLocationEntry *w)
-{
- const char *text;
- int text_len;
- int i, k;
- gboolean result = FALSE;
- static const gchar *prefixes[] = {
- EPHY_AUTOCOMPLETION_USUAL_WEB_PREFIXES,
- NULL
- };
+ if (n_items >= MAX_LOC_HISTORY_ITEMS)
+ {
+ EphyNode *last;
- text = ephy_location_entry_get_location (w);
- g_return_val_if_fail (text != NULL, FALSE);
+ last = ephy_node_get_nth_child
+ (le->priv->combo_root, n_items - 1);
+ ephy_node_remove_child (le->priv->combo_root, last);
+ }
- text_len = g_utf8_strlen (text, -1);
+ ephy_node_add_child (le->priv->combo_root, node);
+ }
- for (i = 0; prefixes[i] != NULL; i++)
+ /* move it at the top */
+ n_items = ephy_node_get_n_children (le->priv->combo_root);
+ order = g_new0 (int, n_items);
+ l = 1;
+ if (index == -1) index = n_items -1;
+ for (i = 0; i < n_items; i++)
{
- const char *prefix = prefixes[i];
-
- for (k = 0; k < g_utf8_strlen (prefix, -1); k++)
+ if (index != i)
{
- if (text_len == (k + 1) &&
- (strncmp (text, prefix, k + 1) == 0))
- {
- result = TRUE;
- }
+ order[i] = l;
+ l++;
+ }
+ else
+ {
+ order[i] = 0;
}
}
-
- return result;
+ ephy_node_reorder_children (le->priv->combo_root, order);
+ g_free (order);
}
-static gint
-ephy_location_entry_autocompletion_show_alternatives_to (EphyLocationEntry *w)
+static void
+entry_activate_cb (GtkEntry *entry, EphyLocationEntry *le)
{
- EphyLocationEntryPrivate *p = w->priv;
-
- g_free (p->before_completion);
- p->before_completion = gtk_editable_get_chars (GTK_EDITABLE (p->entry), 0, -1);
-
- if (ephy_location_ignore_prefix (w)) return FALSE;
+ char *content;
- if (p->autocompletion)
+ content = gtk_editable_get_chars (GTK_EDITABLE(entry), 0, -1);
+ if (content)
{
- LOG ("Show alternatives")
- ephy_location_entry_set_autocompletion_key (w);
- ephy_location_entry_autocompletion_show_alternatives (w);
+ add_to_history (le, content);
+ g_free (content);
}
- p->show_alternatives_timeout = 0;
- return FALSE;
}
-static void
-ephy_location_entry_autocompletion_hide_alternatives (EphyLocationEntry *w)
-{
- EphyLocationEntryPrivate *p = w->priv;
- if (p->autocompletion_window)
+static gboolean
+completion_func (GtkEntryCompletion *completion,
+ const char *key,
+ GtkTreeIter *iter,
+ gpointer data)
+{
+ int i;
+ char *item = NULL;
+ char *keywords = NULL;
+ char *normalized_string, *normalized_keywords;
+ char *case_normalized_string, *case_normalized_keywords;
+ gboolean ret = FALSE;
+ EphyLocationEntry *le = EPHY_LOCATION_ENTRY (data);
+ GtkTreeModel *model;
+
+ model = gtk_entry_completion_get_model (completion);
+
+ gtk_tree_model_get (model, iter,
+ le->priv->text_col, &item, -1);
+ gtk_tree_model_get (model, iter,
+ le->priv->keywords_col, &keywords, -1);
+
+ normalized_string = g_utf8_normalize (item, -1, G_NORMALIZE_ALL);
+ case_normalized_string = g_utf8_casefold (normalized_string, -1);
+ normalized_keywords = g_utf8_normalize (keywords, -1, G_NORMALIZE_ALL);
+ case_normalized_keywords = g_utf8_casefold (normalized_keywords, -1);
+
+ if (!strncmp (key, case_normalized_string, strlen (key)))
{
- ephy_autocompletion_window_hide (p->autocompletion_window);
- p->autocompletion_window_visible = FALSE;
+ ret = TRUE;
}
-
- p->autocompletion_window_visible = FALSE;
-
- if (p->show_alternatives_timeout)
+ else if (strstr (case_normalized_keywords, key))
{
- g_source_remove (p->show_alternatives_timeout);
- p->show_alternatives_timeout = 0;
+ ret = TRUE;
}
-}
-
-static void
-ephy_location_entry_autocompletion_show_alternatives (EphyLocationEntry *w)
-{
- EphyLocationEntryPrivate *p = w->priv;
+ else
+ {
+ for (i = 0; i < n_web_prefixes; i++)
+ {
+ char *key_prefixed;
- /* Reset it because if we do a grab on click (like when pasting
- text in the location entry, the entry will lose the release
- event and will not reset it. It's what gtk does for the entry
- popup */
- GTK_ENTRY (p->entry)->button = 0;
+ key_prefixed = g_strconcat (web_prefixes[i], key, NULL);
- if (p->autocompletion_window)
- {
- ephy_autocompletion_window_show (p->autocompletion_window);
- p->autocompletion_window_visible = TRUE;
- }
-}
+ if (!strncmp (key_prefixed, case_normalized_string,
+ strlen (key_prefixed)))
+ {
+ ret = TRUE;
+ break;
+ }
-static void
-ephy_location_entry_autocompletion_unselect_alternatives (EphyLocationEntry *w)
-{
- EphyLocationEntryPrivate *p = w->priv;
- if (p->autocompletion_window)
- {
- ephy_autocompletion_window_unselect (p->autocompletion_window);
+ g_free (key_prefixed);
+ }
}
-}
-static int
-get_editable_number_of_chars (GtkEditable *editable)
-{
- char *text;
- int length;
+ g_free (item);
+ g_free (normalized_string);
+ g_free (case_normalized_string);
- text = gtk_editable_get_chars (editable, 0, -1);
- length = g_utf8_strlen (text, -1);
- g_free (text);
- return length;
+ return ret;
}
static gboolean
-position_is_at_end (GtkEditable *editable)
-{
- int end;
-
- end = get_editable_number_of_chars (editable);
- return gtk_editable_get_position (editable) == end;
-}
-
-static void
-delete_text_cb (GtkWidget *editable,
- int start_pos,
- int end_pos,
- EphyLocationEntry *w)
-{
- ephy_location_entry_autocompletion_hide_alternatives (w);
-}
-
-static void
-insert_text_cb (GtkWidget *editable,
- char *new_text,
- int new_text_length,
- int *position,
- EphyLocationEntry *w)
+match_selected_cb (GtkEntryCompletion *completion,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ EphyLocationEntry *le)
{
- EphyLocationEntryPrivate *p = w->priv;
- GtkWidget *window;
+ char *item = NULL;
- window = gtk_widget_get_toplevel (editable);
- g_return_if_fail (window != NULL);
- if (!GTK_WINDOW (window)->has_focus) return;
+ gtk_tree_model_get (model, iter,
+ le->priv->action_col, &item, -1);
- if (p->going_to_site) return;
+ ephy_location_entry_set_location (le, item);
+ g_signal_emit_by_name (le->priv->entry, "activate");
- if (p->show_alternatives_timeout != 0)
- {
- g_source_remove (p->show_alternatives_timeout);
- p->show_alternatives_timeout = 0;
- }
+ g_free (item);
- ephy_location_entry_autocompletion_unselect_alternatives (w);
- if (position_is_at_end (GTK_EDITABLE (editable)))
- {
- p->show_alternatives_timeout = g_timeout_add
- (SHOW_ALTERNATIVES_DELAY,
- (GSourceFunc) ephy_location_entry_autocompletion_show_alternatives_to, w);
- }
+ return TRUE;
}
-static gboolean
-ephy_location_entry_key_press_event_cb (GtkWidget *entry, GdkEventKey *event, EphyLocationEntry *w)
+static void
+ephy_location_entry_construct_contents (EphyLocationEntry *le)
{
- EphyLocationEntryPrivate *p = w->priv;
- GtkWidget *window;
+ EphyLocationEntryPrivate *p = le->priv;
+ int combo_text_col;
- switch (event->keyval)
- {
- case GDK_Left:
- case GDK_Right:
- ephy_location_entry_autocompletion_hide_alternatives (w);
- break;
- case GDK_Escape:
- ephy_location_entry_set_location (w, p->before_completion);
- gtk_editable_set_position (GTK_EDITABLE (p->entry), -1);
- ephy_location_entry_autocompletion_hide_alternatives (w);
- break;
- case GDK_Tab:
- case GDK_KP_Tab:
- if (p->autocompletion_window_visible)
- {
- ephy_location_entry_autocompletion_hide_alternatives (w);
- window = gtk_widget_get_toplevel (entry);
- g_signal_emit_by_name (window, "move_focus", 1);
- }
- break;
- default:
- break;
- }
+ LOG ("EphyLocationEntry constructing contents %p", le)
- return FALSE;
-}
+ p->combo_model = ephy_tree_model_node_new (p->combo_root, NULL);
+ combo_text_col = ephy_tree_model_node_add_prop_column
+ (p->combo_model, G_TYPE_STRING, EPHY_NODE_LOC_HISTORY_PROP_TEXT);
-static gboolean
-ephy_location_entry_content_is_text (const char *content)
-{
- return ((g_strrstr (content, ".") == NULL) &&
- (g_strrstr (content, "/") == NULL) &&
- (g_strrstr (content, ":") == NULL));
+ p->combo = gtk_combo_box_entry_new (GTK_TREE_MODEL (p->combo_model),
+ combo_text_col);
+ gtk_container_add (GTK_CONTAINER (le), p->combo);
+ gtk_widget_show (p->combo);
+ p->entry = GTK_BIN (p->combo)->child;
+
+ g_signal_connect (p->entry, "button_press_event",
+ G_CALLBACK (entry_button_press_cb), le);
+ g_signal_connect (p->entry, "changed",
+ G_CALLBACK (editable_changed_cb), le);
+ g_signal_connect (p->entry, "activate",
+ G_CALLBACK (entry_activate_cb), le);
}
static void
-ephy_location_entry_activate_cb (GtkEntry *entry, EphyLocationEntry *w)
+ephy_location_entry_init (EphyLocationEntry *le)
{
- char *content;
- char *target = NULL;
+ EphyLocationEntryPrivate *p;
- content = gtk_editable_get_chars (GTK_EDITABLE(entry), 0, -1);
- if (w->priv->last_action_target &&
- ephy_location_entry_content_is_text (content))
- {
- target = g_strdup (w->priv->last_action_target);
- }
- else
- {
- target = content;
- content = NULL;
- g_free ( w->priv->last_action_target);
- w->priv->last_action_target = NULL;
- }
+ LOG ("EphyLocationEntry initialising %p", le)
- ephy_location_entry_autocompletion_hide_alternatives (w);
+ p = EPHY_LOCATION_ENTRY_GET_PRIVATE (le);
+ le->priv = p;
- LOG ("In ephy_location_entry_activate_cb, activating %s", content)
+ p->user_changed = TRUE;
+ p->activation_mode = FALSE;
+ p->combo_db = ephy_node_db_new ("NodeDB");
+ p->combo_root = ephy_node_new_with_id
+ (p->combo_db, LOCATION_HISTORY_NODE_ID);
+ p->xml_file = g_build_filename (ephy_dot_dir (),
+ "ephy-location-history.xml",
+ NULL);
+ ephy_node_db_load_from_file (p->combo_db, p->xml_file,
+ EPHY_LOC_HISTORY_XML_ROOT,
+ EPHY_LOC_HISTORY_XML_VERSION);
+
+ ephy_location_entry_construct_contents (le);
- g_signal_emit (w, EphyLocationEntrySignals[ACTIVATED], 0, content, target);
- ephy_location_entry_activation_finished (w);
+ gtk_tool_item_set_expand (GTK_TOOL_ITEM (le), TRUE);
- g_free (content);
- g_free (target);
+ g_signal_connect (le->priv->entry,
+ "focus_out_event",
+ G_CALLBACK (location_focus_out_cb), le);
}
static void
-ephy_location_entry_autocompletion_sources_changed_cb (EphyAutocompletion *aw,
- EphyLocationEntry *w)
-{
- EphyLocationEntryPrivate *p = w->priv;
-
- LOG ("in ephy_location_entry_autocompletion_sources_changed_cb")
+save_location_history (EphyLocationEntry *le)
+{
+ xmlDocPtr doc;
+ xmlNodePtr root;
+ GPtrArray *children;
+ int i;
+
+ xmlIndentTreeOutput = TRUE;
+
+ doc = xmlNewDoc ("1.0");
+ root = xmlNewDocNode (doc, NULL, EPHY_LOC_HISTORY_XML_ROOT, NULL);
+ xmlSetProp (root, "version", EPHY_LOC_HISTORY_XML_VERSION);
+ xmlDocSetRootElement (doc, root);
+
+ children = ephy_node_get_children (le->priv->combo_root);
+ for (i = 0; i < children->len; i++)
+ {
+ EphyNode *kid;
+
+ kid = g_ptr_array_index (children, i);
+
+ ephy_node_save_to_xml (kid, root);
+ }
+ ephy_node_thaw (le->priv->combo_root);
- if (p->show_alternatives_timeout == 0
- && p->autocompletion_window_visible)
- {
- p->show_alternatives_timeout = g_timeout_add
- (SHOW_ALTERNATIVES_DELAY,
- (GSourceFunc) ephy_location_entry_autocompletion_show_alternatives_to, w);
- }
+ ephy_file_save_xml (le->priv->xml_file, doc);
+ xmlFreeDoc(doc);
}
-void
-ephy_location_entry_set_location (EphyLocationEntry *w,
- const gchar *new_location)
+static void
+ephy_location_entry_finalize (GObject *o)
{
- EphyLocationEntryPrivate *p = w->priv;
- int pos;
-
- g_return_if_fail (new_location != NULL);
-
- p->user_changed = FALSE;
+ EphyLocationEntry *le;
+
+ le = EPHY_LOCATION_ENTRY (o);
- g_signal_handlers_block_by_func (G_OBJECT (p->entry),
- delete_text_cb, w);
- gtk_editable_delete_text (GTK_EDITABLE (p->entry), 0, -1);
- g_signal_handlers_unblock_by_func (G_OBJECT (p->entry),
- delete_text_cb, w);
+ save_location_history (le);
+ g_free (le->priv->xml_file);
- g_signal_handlers_block_by_func (G_OBJECT (p->entry),
- insert_text_cb, w);
- gtk_editable_insert_text (GTK_EDITABLE (p->entry), new_location, strlen(new_location),
- &pos);
- g_signal_handlers_unblock_by_func (G_OBJECT (p->entry),
- insert_text_cb, w);
+ LOG ("EphyLocationEntry finalized")
- p->user_changed = TRUE;
+ G_OBJECT_CLASS (parent_class)->finalize (o);
}
-const char *
-ephy_location_entry_get_location (EphyLocationEntry *w)
+GtkWidget *
+ephy_location_entry_new (void)
{
- return gtk_entry_get_text (GTK_ENTRY (w->priv->entry));
+ return GTK_WIDGET (g_object_new (EPHY_TYPE_LOCATION_ENTRY, NULL));
}
-static void
-ephy_location_entry_autocompletion_window_url_selected_cb (EphyAutocompletionWindow *aw,
- const char *target,
- int action,
- EphyLocationEntry *w)
+static gint
+sort_func (GtkTreeModel *model,
+ GtkTreeIter *a,
+ GtkTreeIter *b,
+ gpointer data)
{
- if (target)
- {
- ephy_location_entry_set_location (w, action ? w->priv->before_completion : target);
- }
- else
- {
- ephy_location_entry_set_location (w, w->priv->before_completion);
- }
+ gint valuea, valueb;
+ EphyLocationEntry *le = EPHY_LOCATION_ENTRY (data);
+
+ gtk_tree_model_get (model, a,
+ le->priv->relevance_col, &valuea, -1);
+ gtk_tree_model_get (model, b,
+ le->priv->relevance_col, &valueb, -1);
- gtk_editable_set_position (GTK_EDITABLE (w->priv->entry), -1);
+ return valueb - valuea;
}
void
-ephy_location_entry_set_autocompletion (EphyLocationEntry *w,
- EphyAutocompletion *ac)
-{
- EphyLocationEntryPrivate *p = w->priv;
- if (p->autocompletion)
- {
- g_signal_handlers_disconnect_matched (p->autocompletion, G_SIGNAL_MATCH_DATA, 0, 0,
- NULL, NULL, w);
-
- g_signal_handlers_disconnect_matched (p->autocompletion_window, G_SIGNAL_MATCH_DATA, 0, 0,
- NULL, NULL, w);
-
- g_object_unref (G_OBJECT (p->autocompletion));
- g_object_unref (p->autocompletion_window);
- }
- p->autocompletion = ac;
- if (p->autocompletion)
- {
- g_object_ref (G_OBJECT (p->autocompletion));
- p->autocompletion_window = ephy_autocompletion_window_new (p->autocompletion,
- p->entry);
- g_signal_connect (p->autocompletion_window, "activated",
- G_CALLBACK (ephy_location_entry_autocompletion_window_url_activated_cb),
- w);
-
- g_signal_connect (p->autocompletion_window, "selected",
- G_CALLBACK (ephy_location_entry_autocompletion_window_url_selected_cb),
- w);
-
- g_signal_connect (p->autocompletion_window, "hidden",
- G_CALLBACK (ephy_location_entry_autocompletion_window_hidden_cb),
- w);
-
- g_signal_connect (p->autocompletion, "sources-changed",
- G_CALLBACK (ephy_location_entry_autocompletion_sources_changed_cb),
- w);
-
- ephy_location_entry_set_autocompletion_key (w);
- }
-
+ephy_location_entry_set_completion (EphyLocationEntry *le,
+ GtkTreeModel *model,
+ guint text_col,
+ guint action_col,
+ guint keywords_col,
+ guint relevance_col)
+{
+ GtkTreeModel *sort_model;
+ GtkEntryCompletion *completion;
+ GtkCellRenderer *cell;
+
+ le->priv->text_col = text_col;
+ le->priv->action_col = action_col;
+ le->priv->keywords_col = keywords_col;
+ le->priv->relevance_col = relevance_col;
+
+ sort_model = gtk_tree_model_sort_new_with_model (model);
+ g_object_unref (model);
+ gtk_tree_sortable_set_default_sort_func
+ (GTK_TREE_SORTABLE (sort_model),
+ sort_func, le, NULL);
+
+ completion = gtk_entry_completion_new ();
+ gtk_entry_completion_set_model (completion, sort_model);
+ g_object_unref (sort_model);
+ gtk_entry_completion_set_match_func (completion, completion_func, le, NULL);
+ g_signal_connect (completion, "match_selected",
+ G_CALLBACK (match_selected_cb), le);
+
+ cell = gtk_cell_renderer_text_new ();
+ gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (completion),
+ cell, TRUE);
+ gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (completion),
+ cell, "text", text_col);
+
+ gtk_entry_set_completion (GTK_ENTRY (le->priv->entry), completion);
}
-static void
-ephy_location_entry_autocompletion_window_url_activated_cb (EphyAutocompletionWindow *aw,
- const char *target,
- int action,
- EphyLocationEntry *w)
+void
+ephy_location_entry_set_location (EphyLocationEntry *le,
+ const gchar *new_location)
{
- char *content;
+ EphyLocationEntryPrivate *p = le->priv;
- if (action)
- {
- if (w->priv->last_action_target)
- g_free (w->priv->last_action_target);
- w->priv->last_action_target = g_strdup (target);
- }
- else
- {
- ephy_location_entry_set_location (w, target);
- }
-
- content = gtk_editable_get_chars (GTK_EDITABLE(w->priv->entry), 0, -1);
-
- LOG ("In location_entry_autocompletion_window_url_activated_cb, going to %s", content);
+ g_return_if_fail (new_location != NULL);
- ephy_location_entry_autocompletion_hide_alternatives (w);
+ p->user_changed = FALSE;
- g_signal_emit (w, EphyLocationEntrySignals[ACTIVATED], 0,
- action ? content : NULL, target);
+ gtk_entry_set_text (GTK_ENTRY (p->entry), new_location);
- g_free (content);
+ p->user_changed = TRUE;
}
-static void
-ephy_location_entry_autocompletion_window_hidden_cb (EphyAutocompletionWindow *aw,
- EphyLocationEntry *w)
+const char *
+ephy_location_entry_get_location (EphyLocationEntry *le)
{
- EphyLocationEntryPrivate *p = w->priv;
-
- LOG ("In location_entry_autocompletion_window_hidden_cb");
-
- p->autocompletion_window_visible = FALSE;
-
- if (p->show_alternatives_timeout)
- {
- g_source_remove (p->show_alternatives_timeout);
- p->show_alternatives_timeout = 0;
- }
+ return gtk_entry_get_text (GTK_ENTRY (le->priv->entry));
}
void
-ephy_location_entry_activate (EphyLocationEntry *w)
+ephy_location_entry_activate (EphyLocationEntry *le)
{
GtkWidget *toplevel, *toolbar;
- toolbar = gtk_widget_get_ancestor (GTK_WIDGET (w), GTK_TYPE_TOOLBAR);
+ toolbar = gtk_widget_get_ancestor (GTK_WIDGET (le), GTK_TYPE_TOOLBAR);
if (!GTK_WIDGET_VISIBLE (toolbar))
{
- w->priv->activation_mode = TRUE;
+ le->priv->activation_mode = TRUE;
gtk_widget_show (toolbar);
}
- toplevel = gtk_widget_get_toplevel (w->priv->entry);
+ toplevel = gtk_widget_get_toplevel (le->priv->entry);
- gtk_editable_select_region (GTK_EDITABLE(w->priv->entry),
+ gtk_editable_select_region (GTK_EDITABLE(le->priv->entry),
0, -1);
gtk_window_set_focus (GTK_WINDOW(toplevel),
- w->priv->entry);
-}
-
-static void
-ephy_location_entry_list_event_after_cb (GtkWidget *list,
- GdkEvent *event,
- EphyLocationEntry *e)
-{
- if (event->type == GDK_BUTTON_PRESS
- && ((GdkEventButton *) event)->button == 1)
- {
- e->priv->going_to_site = TRUE;
- }
+ le->priv->entry);
}
-static void
-ephy_location_entry_editable_changed_cb (GtkEditable *editable, EphyLocationEntry *e)
+void
+ephy_location_entry_clear_history (EphyLocationEntry *le)
{
- EphyLocationEntryPrivate *p = e->priv;
-
- ephy_location_entry_set_autocompletion_key (e);
-
- if (p->going_to_site)
+ EphyNode *node;
+
+ while ((node = ephy_node_get_nth_child (le->priv->combo_root, 0)) != NULL)
{
- const char *url = ephy_location_entry_get_location (e);
- if (url && url[0] != '\0')
- {
- p->going_to_site = FALSE;
- g_signal_emit (e, EphyLocationEntrySignals[ACTIVATED], 0, NULL, url);
- }
+ ephy_node_unref (node);
}
- if (p->user_changed)
- {
- g_signal_emit (e, EphyLocationEntrySignals[USER_CHANGED], 0);
- }
+ save_location_history (le);
}
-static void
-ephy_location_entry_set_autocompletion_key (EphyLocationEntry *e)
+GtkWidget *
+ephy_location_entry_get_entry (EphyLocationEntry *le)
{
- EphyLocationEntryPrivate *p = e->priv;
- if (p->autocompletion && !p->block_set_autocompletion_key)
- {
- GtkEditable *editable = GTK_EDITABLE (p->entry);
- gint sstart, send;
- gchar *text;
- gtk_editable_get_selection_bounds (editable, &sstart, &send);
- text = gtk_editable_get_chars (editable, 0, sstart);
- ephy_autocompletion_set_key (p->autocompletion, text);
- g_free (p->autocompletion_key);
- p->autocompletion_key = text;
- }
+ return le->priv->entry;
}
-void
-ephy_location_entry_clear_history (EphyLocationEntry *w)
-{
- gnome_entry_clear_history (GNOME_ENTRY (w->priv->combo));
-}