aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog189
-rw-r--r--embed/ephy-history.c77
-rw-r--r--lib/Makefile.am6
-rw-r--r--lib/ephy-autocompletion-source.c85
-rw-r--r--lib/ephy-autocompletion-source.h80
-rw-r--r--lib/ephy-autocompletion.c609
-rw-r--r--lib/ephy-autocompletion.h106
-rw-r--r--lib/ephy-node-common.h3
-rw-r--r--lib/widgets/Makefile.am2
-rw-r--r--lib/widgets/ephy-autocompletion-window.c839
-rw-r--r--lib/widgets/ephy-autocompletion-window.h89
-rw-r--r--lib/widgets/ephy-location-entry.c876
-rw-r--r--src/Makefile.am2
-rw-r--r--src/bookmarks/ephy-bookmark-action.c8
-rw-r--r--src/bookmarks/ephy-bookmarks-export.c7
-rw-r--r--src/bookmarks/ephy-bookmarks.c114
-rw-r--r--src/bookmarks/ephy-bookmarks.h3
-rw-r--r--src/ephy-completion-model.c601
-rw-r--r--src/ephy-completion-model.h63
-rw-r--r--src/ephy-location-action.c211
-rw-r--r--src/ephy-shell.c33
-rw-r--r--src/ephy-shell.h2
22 files changed, 1425 insertions, 2580 deletions
diff --git a/ChangeLog b/ChangeLog
index 7ae00aa7b..fb9716a61 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -123,6 +123,195 @@
Use new gtk api for empty submenus
+2003-10-07 Marco Pesenti Gritti <marco@gnome.org>
+
+ * src/ephy-completion-model.c: (node_iter_from_node),
+ (ephy_completion_model_init), (ephy_completion_model_get_value),
+ (ephy_completion_model_get_iter), (ephy_completion_model_get_path),
+ (ephy_completion_model_iter_next),
+ (ephy_completion_model_iter_children),
+ (ephy_completion_model_iter_n_children),
+ (ephy_completion_model_iter_nth_child):
+
+ Add stamp.
+
+2003-10-06 Marco Pesenti Gritti <marco@gnome.org>
+
+ * lib/widgets/ephy-location-entry.c: (completion_func),
+ (match_selected_cb), (ephy_location_entry_construct_contents),
+ (ephy_location_entry_init), (sort_func),
+ (ephy_location_entry_set_completion):
+ * lib/widgets/ephy-location-entry.h:
+ * src/Makefile.am:
+ * src/ephy-completion-model.c: (ephy_completion_model_class_init),
+ (root_child_removed_cb), (node_iter_from_node), (get_path_real),
+ (root_child_added_cb), (root_child_changed_cb), (connect_signals),
+ (ephy_completion_model_init),
+ (ephy_completion_model_get_column_type), (init_text_col),
+ (init_action_col), (init_keywords_col), (init_relevance_col),
+ (ephy_completion_model_get_value),
+ (ephy_completion_model_get_iter):
+ * src/ephy-location-action.c: (connect_proxy):
+
+ Implement our own completion model. The big part of the
+ new location entry impl is done. When gtk completion will
+ be fixed I'll be able to merge this on head.
+
+2003-10-05 Marco Pesenti Gritti <marco@gnome.org>
+
+ * lib/widgets/ephy-location-entry.c:
+ (ephy_location_entry_class_init), (entry_activate_cb):
+ * lib/widgets/ephy-location-entry.h:
+
+ Remove the activated signal.
+
+ * src/ephy-location-action.c: (action_activated_cb),
+ (location_url_activate_cb), (remove_completion_actions),
+ (add_completion_actions), (connect_proxy),
+ (ephy_location_action_init):
+
+ Just use entry activate signal. Implement smart
+ bookmarks activation.
+
+2003-10-05 Marco Pesenti Gritti <marco@gnome.org>
+
+ * lib/ephy-node-common.h:
+ * lib/widgets/ephy-location-entry.c:
+ (ephy_location_entry_get_entry):
+ * lib/widgets/ephy-location-entry.h:
+ * src/bookmarks/ephy-bookmark-action.c: (sync_bookmark_properties):
+ * src/bookmarks/ephy-bookmarks-export.c:
+ (ephy_bookmarks_export_rdf):
+ * src/bookmarks/ephy-bookmarks.c: (ephy_bookmarks_init),
+ (update_has_smart_address), (ephy_bookmarks_add),
+ (ephy_bookmarks_set_address), (ephy_bookmarks_unset_keyword),
+ (ephy_bookmarks_get_smart_bookmarks):
+ * src/bookmarks/ephy-bookmarks.h:
+
+ Modify smart bookmarks to use a separate root instead
+ of a property.
+
+ * src/ephy-location-action.c: (remove_completion_actions),
+ (add_completion_actions), (connect_proxy), (init_actions_list),
+ (update_actions_list), (actions_child_removed_cb),
+ (actions_child_added_cb), (actions_child_changed_cb),
+ (ephy_location_action_init), (ephy_location_action_finalize):
+
+ Implement smart bookmarks as location actions.
+
+2003-10-05 Marco Pesenti Gritti <marco@gnome.org>
+
+ * lib/widgets/ephy-location-entry.c: (add_to_history),
+ (entry_activate_cb), (ephy_location_entry_construct_contents),
+ (ephy_location_entry_init), (save_location_history),
+ (ephy_location_entry_finalize),
+ (ephy_location_entry_clear_history):
+
+ Implement location history.
+
+ * lib/widgets/ephy-tree-model-node.c: (root_children_reordered_cb):
+
+ Fixup reorder notification.
+
+2003-10-03 Marco Pesenti Gritti <marco@gnome.org>
+
+ * lib/widgets/ephy-location-entry.c: (match_selected_cb),
+ (ephy_location_entry_construct_contents),
+ (ephy_location_entry_add_completion):
+
+ Do not create multiple gtk completions, open the
+ url when a match is selected.
+
+2003-10-02 Marco Pesenti Gritti <marco@gnome.org>
+
+ * lib/egg/Makefile.am:
+ * lib/egg/eggtreemodelunion.c:
+ * lib/egg/eggtreemodelunion.h:
+
+ Add from libegg.
+
+ * lib/widgets/ephy-location-entry.c: (completion_func),
+ (ephy_location_entry_construct_contents),
+ (ephy_location_entry_add_completion):
+ * lib/widgets/ephy-location-entry.h:
+ * lib/widgets/ephy-tree-model-node.c:
+ (ephy_tree_model_node_get_value):
+ * src/ephy-location-action.c: (connect_proxy):
+
+ Merge bookmarks in autocompletion and implement
+ case unsensitive match.
+
+2003-10-02 Marco Pesenti Gritti <marco@gnome.org>
+
+ * lib/widgets/ephy-location-entry.c: (completion_func),
+ (ephy_location_entry_init), (ephy_location_entry_add_completion):
+
+ Costum match function to deal with prefixes.
+
+ * lib/widgets/ephy-tree-model-node.c:
+ (ephy_tree_model_node_get_column_type),
+ (ephy_tree_model_node_get_value):
+
+ Fix column indexes.
+
+2003-10-01 Marco Pesenti Gritti <marco@gnome.org>
+
+ * lib/widgets/ephy-location-entry.c: (entry_button_press_cb),
+ (ephy_location_entry_construct_contents):
+
+ Put back double click -> select all
+
+2003-10-01 Marco Pesenti Gritti <marco@gnome.org>
+
+ * lib/widgets/ephy-location-entry.c: (location_focus_out_cb),
+ (ephy_location_entry_construct_contents),
+ (ephy_location_entry_init), (ephy_location_entry_finalize),
+ (ephy_location_entry_add_completion),
+ (ephy_location_entry_set_location),
+ (ephy_location_entry_get_location), (ephy_location_entry_activate),
+ (ephy_location_entry_clear_history):
+ * lib/widgets/ephy-location-entry.h:
+
+ cleanups
+
+2003-10-01 Marco Pesenti Gritti <marco@gnome.org>
+
+ * embed/ephy-history.c: (ephy_history_get_type),
+ (ephy_history_init), (ephy_history_visited):
+ * lib/Makefile.am:
+ * lib/ephy-autocompletion-source.c:
+ * lib/ephy-autocompletion-source.h:
+ * lib/ephy-autocompletion.c:
+ * lib/ephy-autocompletion.h:
+ * lib/widgets/Makefile.am:
+ * lib/widgets/ephy-autocompletion-window.c:
+ * lib/widgets/ephy-autocompletion-window.h:
+ * src/bookmarks/ephy-bookmarks.c: (ephy_bookmarks_get_type),
+ (bookmarks_changed_cb), (bookmarks_removed_cb),
+ (ephy_bookmarks_init), (ephy_bookmarks_add):
+
+ Remove old implementation completely
+
+2003-10-01 Marco Pesenti Gritti <marco@gnome.org>
+
+ * lib/widgets/ephy-location-entry.c:
+ (ephy_location_entry_class_init), (editable_changed_cb),
+ (entry_activate_cb), (ephy_location_entry_construct_contents),
+ (ephy_location_entry_init), (ephy_location_entry_finalize),
+ (ephy_location_entry_new), (ephy_location_entry_add_completion),
+ (ephy_location_entry_set_location),
+ (ephy_location_entry_clear_history):
+ * lib/widgets/ephy-location-entry.h:
+ * lib/widgets/ephy-tree-model-node.c:
+ (ephy_tree_model_node_add_prop_column),
+ (ephy_tree_model_node_add_func_column):
+ * src/ephy-location-action.c: (connect_proxy):
+ * src/ephy-shell.c: (ephy_shell_finalize),
+ (ephy_shell_get_session):
+ * src/ephy-shell.h:
+
+ Beginning of new location entry implementation
+
2003-09-30 Marco Pesenti Gritti <marco@gnome.org>
* data/epiphany.schemas.in:
diff --git a/embed/ephy-history.c b/embed/ephy-history.c
index 911567dda..c6aabef64 100644
--- a/embed/ephy-history.c
+++ b/embed/ephy-history.c
@@ -25,7 +25,6 @@
#include "ephy-types.h"
#include "ephy-history.h"
#include "ephy-file-helpers.h"
-#include "ephy-autocompletion-source.h"
#include "ephy-debug.h"
#include "ephy-node-common.h"
@@ -75,8 +74,6 @@ static void
ephy_history_init (EphyHistory *tab);
static void
ephy_history_finalize (GObject *object);
-static void
-ephy_history_autocompletion_source_init (EphyAutocompletionSourceIface *iface);
static GObjectClass *parent_class = NULL;
@@ -102,87 +99,15 @@ ephy_history_get_type (void)
(GInstanceInitFunc) ephy_history_init
};
- static const GInterfaceInfo autocompletion_source_info =
- {
- (GInterfaceInitFunc) ephy_history_autocompletion_source_init,
- NULL,
- NULL
- };
-
ephy_history_type = g_type_register_static (G_TYPE_OBJECT,
"EphyHistory",
&our_info, 0);
-
- g_type_add_interface_static (ephy_history_type,
- EPHY_TYPE_AUTOCOMPLETION_SOURCE,
- &autocompletion_source_info);
}
return ephy_history_type;
}
static void
-ephy_history_autocompletion_source_set_basic_key (EphyAutocompletionSource *source,
- const gchar *basic_key)
-{
- /* nothing to do here */
-}
-
-static void
-ephy_history_autocompletion_source_foreach (EphyAutocompletionSource *source,
- const gchar *current_text,
- EphyAutocompletionSourceForeachFunc func,
- gpointer data)
-{
- GPtrArray *children;
- int i;
- EphyHistory *eb = EPHY_HISTORY (source);
- GTime now;
-
- now = time (NULL);
-
- children = ephy_node_get_children (eb->priv->pages);
- for (i = 0; i < children->len; i++)
- {
- EphyNode *kid;
- const char *url, *title;
- int last_visit, visits;
- guint32 score;
-
- kid = g_ptr_array_index (children, i);
- g_assert (kid != NULL);
-
- url = ephy_node_get_property_string
- (kid, EPHY_NODE_PAGE_PROP_LOCATION);
- title = ephy_node_get_property_string
- (kid, EPHY_NODE_PAGE_PROP_TITLE);
- last_visit = ephy_node_get_property_int
- (kid, EPHY_NODE_PAGE_PROP_LAST_VISIT);
- visits = ephy_node_get_property_int
- (kid, EPHY_NODE_PAGE_PROP_VISITS);
- score = MAX (visits - ((now - last_visit) >> 15), 1);
-
- func (source, url,
- url, url, FALSE,
- FALSE, score, data);
- }
- ephy_node_thaw (eb->priv->pages);
-}
-
-static void
-ephy_history_emit_data_changed (EphyHistory *eb)
-{
- g_signal_emit_by_name (eb, "data-changed");
-}
-
-static void
-ephy_history_autocompletion_source_init (EphyAutocompletionSourceIface *iface)
-{
- iface->foreach = ephy_history_autocompletion_source_foreach;
- iface->set_basic_key = ephy_history_autocompletion_source_set_basic_key;
-}
-
-static void
ephy_history_class_init (EphyHistoryClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
@@ -520,7 +445,6 @@ ephy_history_init (EphyHistory *eb)
ephy_node_db_load_from_file (eb->priv->db, eb->priv->xml_file,
EPHY_HISTORY_XML_ROOT,
EPHY_HISTORY_XML_VERSION);
- ephy_history_emit_data_changed (eb);
g_hash_table_foreach (eb->priv->hosts_hash,
(GHFunc) connect_page_removed_from_host,
@@ -765,7 +689,6 @@ ephy_history_visited (EphyHistory *eh, EphyNode *node)
eh->priv->last_page = node;
g_signal_emit (G_OBJECT (eh), ephy_history_signals[VISITED], 0, url);
- ephy_history_emit_data_changed (eh);
}
int
diff --git a/lib/Makefile.am b/lib/Makefile.am
index bc0c0901c..7caefb55d 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -16,8 +16,6 @@ header_DATA = $(INST_H_FILES)
NOINST_H_FILES = \
eel-gconf-extensions.h \
- ephy-autocompletion.h \
- ephy-autocompletion-source.h \
ephy-bonobo-extensions.h \
ephy-debug.h \
ephy-dnd.h \
@@ -44,10 +42,6 @@ INST_H_FILES = \
libephy_la_SOURCES = \
eel-gconf-extensions.c \
eel-gconf-extensions.h \
- ephy-autocompletion.c \
- ephy-autocompletion.h \
- ephy-autocompletion-source.c \
- ephy-autocompletion-source.h \
ephy-bonobo-extensions.h \
ephy-bonobo-extensions.c \
ephy-debug.c \
diff --git a/lib/ephy-autocompletion-source.c b/lib/ephy-autocompletion-source.c
deleted file mode 100644
index 717b9924e..000000000
--- a/lib/ephy-autocompletion-source.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2002 Ricardo Fernándezs Pascual <ric@users.sourceforge.net>
- *
- * 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include "ephy-autocompletion-source.h"
-#include "ephy-marshal.h"
-
-static void ephy_autocompletion_source_base_init (gpointer g_class);
-
-GType
-ephy_autocompletion_source_get_type (void)
-{
- static GType autocompletion_source_type = 0;
-
- if (! autocompletion_source_type)
- {
- static const GTypeInfo autocompletion_source_info =
- {
- sizeof (EphyAutocompletionSourceIface), /* class_size */
- ephy_autocompletion_source_base_init, /* base_init */
- NULL, /* base_finalize */
- NULL,
- NULL, /* class_finalize */
- NULL, /* class_data */
- 0,
- 0, /* n_preallocs */
- NULL
- };
-
- autocompletion_source_type = g_type_register_static
- (G_TYPE_INTERFACE, "EphyAutocompletionSource", &autocompletion_source_info, 0);
- g_type_interface_add_prerequisite (autocompletion_source_type, G_TYPE_OBJECT);
- }
-
- return autocompletion_source_type;
-}
-
-static void
-ephy_autocompletion_source_base_init (gpointer g_class)
-{
- static gboolean initialized = FALSE;
-
- if (!initialized)
- {
- g_signal_new ("data-changed",
- EPHY_TYPE_AUTOCOMPLETION_SOURCE,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (EphyAutocompletionSourceIface, data_changed),
- NULL, NULL,
- ephy_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
- initialized = TRUE;
- }
-}
-
-
-void
-ephy_autocompletion_source_foreach (EphyAutocompletionSource *source,
- const gchar *basic_key,
- EphyAutocompletionSourceForeachFunc func,
- gpointer data)
-{
- (* EPHY_AUTOCOMPLETION_SOURCE_GET_IFACE (source)->foreach) (source, basic_key, func, data);
-}
-
-void
-ephy_autocompletion_source_set_basic_key (EphyAutocompletionSource *source,
- const gchar *basic_key)
-{
- (* EPHY_AUTOCOMPLETION_SOURCE_GET_IFACE (source)->set_basic_key) (source, basic_key);
-}
diff --git a/lib/ephy-autocompletion-source.h b/lib/ephy-autocompletion-source.h
deleted file mode 100644
index 595708b3a..000000000
--- a/lib/ephy-autocompletion-source.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2002 Ricardo Fernándezs Pascual <ric@users.sourceforge.net>
- *
- * 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef EPHY_AUTOCOMPLETION_SOUCE_H
-#define EPHY_AUTOCOMPLETION_SOUCE_H
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-
-#define EPHY_TYPE_AUTOCOMPLETION_SOURCE (ephy_autocompletion_source_get_type ())
-#define EPHY_AUTOCOMPLETION_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
- EPHY_TYPE_AUTOCOMPLETION_SOURCE, \
- EphyAutocompletionSource))
-#define EPHY_IS_AUTOCOMPLETION_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
- EPHY_TYPE_AUTOCOMPLETION_SOURCE))
-#define EPHY_AUTOCOMPLETION_SOURCE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), \
- EPHY_TYPE_AUTOCOMPLETION_SOURCE, \
- EphyAutocompletionSourceIface))
-
-
-typedef struct _EphyAutocompletionSource EphyAutocompletionSource;
-typedef struct _EphyAutocompletionSourceIface EphyAutocompletionSourceIface;
-typedef void (* EphyAutocompletionSourceForeachFunc) (EphyAutocompletionSource *source,
- const char *item,
- const char *title,
- const char *target,
- gboolean is_action,
- gboolean substring,
- guint32 score,
- gpointer data);
-
-struct _EphyAutocompletionSourceIface
-{
- GTypeInterface g_iface;
-
- /* Signals */
-
- /**
- * Sources MUST emit this signal when theirs data changes, expecially if the
- * strings are freed / modified. Otherwise, things will crash.
- */
- void (* data_changed) (EphyAutocompletionSource *source);
-
- /* Virtual Table */
- void (* foreach) (EphyAutocompletionSource *source,
- const gchar *basic_key,
- EphyAutocompletionSourceForeachFunc func,
- gpointer data);
- void (* set_basic_key) (EphyAutocompletionSource *source,
- const gchar *basic_key);
-};
-
-GType ephy_autocompletion_source_get_type (void);
-void ephy_autocompletion_source_foreach (EphyAutocompletionSource *source,
- const gchar *basic_key,
- EphyAutocompletionSourceForeachFunc func,
- gpointer data);
-void ephy_autocompletion_source_set_basic_key (EphyAutocompletionSource *source,
- const gchar *basic_key);
-
-G_END_DECLS
-
-#endif
-
diff --git a/lib/ephy-autocompletion.c b/lib/ephy-autocompletion.c
deleted file mode 100644
index 6c28eaf78..000000000
--- a/lib/ephy-autocompletion.c
+++ /dev/null
@@ -1,609 +0,0 @@
-/*
- * Copyright (C) 2002 Ricardo Fernández Pascual
- *
- * 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * $Id$
- */
-
-#include <string.h>
-#include <stdlib.h>
-
-#include "ephy-autocompletion.h"
-#include "ephy-marshal.h"
-#include "ephy-debug.h"
-
-/**
- * Private data
- */
-
-typedef enum {
- GAS_NEEDS_REFINE,
- GAS_NEEDS_FULL_UPDATE,
- GAS_UPDATED
-} EphyAutocompletionStatus;
-
-typedef struct {
- EphyAutocompletionMatch *array;
- guint num_matches;
- guint num_action_matches;
- guint array_size;
-} ACMatchArray;
-
-#define ACMA_BASE_SIZE 10240
-
-#define EPHY_AUTOCOMPLETION_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_AUTOCOMPLETION, EphyAutocompletionPrivate))
-
-struct _EphyAutocompletionPrivate {
- GSList *sources;
-
- guint nkeys;
- gchar **keys;
- guint *key_lengths;
- gchar **prefixes;
- guint *prefix_lengths;
-
- ACMatchArray matches;
- EphyAutocompletionStatus status;
- gboolean sorted;
- gboolean changed;
-
- gboolean sort_alpha;
-};
-
-/**
- * Private functions, only availble from this file
- */
-static void ephy_autocompletion_class_init (EphyAutocompletionClass *klass);
-static void ephy_autocompletion_init (EphyAutocompletion *e);
-static void ephy_autocompletion_finalize_impl (GObject *o);
-static void ephy_autocompletion_reset (EphyAutocompletion *ac);
-static void ephy_autocompletion_update_matches (EphyAutocompletion *ac);
-static void ephy_autocompletion_update_matches_full (EphyAutocompletion *ac);
-static gboolean ephy_autocompletion_sort_by_score (EphyAutocompletion *ac);
-static void ephy_autocompletion_data_changed_cb (EphyAutocompletionSource *s,
- EphyAutocompletion *ac);
-
-static void acma_init (ACMatchArray *a);
-static void acma_destroy (ACMatchArray *a);
-static inline void acma_append (ACMatchArray *a,
- EphyAutocompletionMatch *m,
- gboolean action);
-static void acma_grow (ACMatchArray *a);
-
-
-static gpointer g_object_class;
-
-/**
- * Signals enums and ids
- */
-enum EphyAutocompletionSignalsEnum {
- EPHY_AUTOCOMPLETION_SOURCES_CHANGED,
- EPHY_AUTOCOMPLETION_LAST_SIGNAL
-};
-static gint EphyAutocompletionSignals[EPHY_AUTOCOMPLETION_LAST_SIGNAL];
-
-GType
-ephy_autocompletion_get_type (void)
-{
- static GType ephy_autocompletion_type = 0;
-
- if (ephy_autocompletion_type == 0)
- {
- static const GTypeInfo our_info =
- {
- sizeof (EphyAutocompletionClass),
- NULL,
- NULL,
- (GClassInitFunc) ephy_autocompletion_class_init,
- NULL,
- NULL,
- sizeof (EphyAutocompletion),
- 0,
- (GInstanceInitFunc) ephy_autocompletion_init
- };
-
- ephy_autocompletion_type = g_type_register_static (G_TYPE_OBJECT,
- "EphyAutocompletion",
- &our_info, 0);
- }
-
- return ephy_autocompletion_type;
-}
-
-static void
-ephy_autocompletion_class_init (EphyAutocompletionClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- g_object_class = g_type_class_peek_parent (klass);
-
- object_class->finalize = ephy_autocompletion_finalize_impl;
-
- EphyAutocompletionSignals[EPHY_AUTOCOMPLETION_SOURCES_CHANGED] = g_signal_new (
- "sources-changed", G_OBJECT_CLASS_TYPE (klass),
- G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST | G_SIGNAL_RUN_CLEANUP,
- G_STRUCT_OFFSET (EphyAutocompletionClass, sources_changed),
- NULL, NULL,
- ephy_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- g_type_class_add_private (object_class, sizeof (EphyAutocompletionPrivate));
-}
-
-static void
-ephy_autocompletion_init (EphyAutocompletion *ac)
-{
- EphyAutocompletionPrivate *p = EPHY_AUTOCOMPLETION_GET_PRIVATE (ac);
- ac->priv = p;
- p->sources = NULL;
- acma_init (&p->matches);
- p->status = GAS_NEEDS_FULL_UPDATE;
-
- p->nkeys = 1;
-
- p->keys = g_new0 (gchar *, 2);
- p->keys[0] = g_strdup ("");
- p->key_lengths = g_new0 (guint, 2);
- p->key_lengths[0] = 0;
-
- p->prefixes = g_new0 (gchar *, 2);
- p->prefixes[0] = g_strdup ("");
- p->prefix_lengths = g_new0 (guint, 2);
- p->prefix_lengths[0] = 0;
-
- p->sort_alpha = TRUE;
-}
-
-static void
-ephy_autocompletion_finalize_impl (GObject *o)
-{
- EphyAutocompletion *ac = EPHY_AUTOCOMPLETION (o);
- EphyAutocompletionPrivate *p = ac->priv;
- GSList *li;
-
- ephy_autocompletion_reset (ac);
-
- for (li = p->sources; li; li = li->next)
- {
- g_signal_handlers_disconnect_by_func (li->data,
- ephy_autocompletion_data_changed_cb, ac);
- g_object_unref (li->data);
- }
-
- g_slist_free (p->sources);
-
- g_strfreev (p->keys);
- g_free (p->key_lengths);
- g_strfreev (p->prefixes);
- g_free (p->prefix_lengths);
-
- G_OBJECT_CLASS (g_object_class)->finalize (o);
-
-}
-
-static void
-ephy_autocompletion_reset (EphyAutocompletion *ac)
-{
- EphyAutocompletionPrivate *p = ac->priv;
-
- START_PROFILER ("Resetting autocompletion")
-
- p->status = GAS_NEEDS_FULL_UPDATE;
-
- STOP_PROFILER ("Resetting autocompletion")
-}
-
-EphyAutocompletion *
-ephy_autocompletion_new (void)
-{
- EphyAutocompletion *ret = g_object_new (EPHY_TYPE_AUTOCOMPLETION, NULL);
- return ret;
-}
-void
-ephy_autocompletion_add_source (EphyAutocompletion *ac,
- EphyAutocompletionSource *s)
-{
- EphyAutocompletionPrivate *p = ac->priv;
- g_object_ref (G_OBJECT (s));
- p->sources = g_slist_prepend (p->sources, s);
- ephy_autocompletion_reset (ac);
- g_signal_connect (s, "data-changed", G_CALLBACK (ephy_autocompletion_data_changed_cb), ac);
-
- g_signal_emit (ac, EphyAutocompletionSignals[EPHY_AUTOCOMPLETION_SOURCES_CHANGED], 0);
-}
-
-void
-ephy_autocompletion_set_key (EphyAutocompletion *ac,
- const gchar *key)
-{
- EphyAutocompletionPrivate *p = ac->priv;
- guint i;
- guint keylen = strlen (key);
-
- if (strcmp (key, p->keys[0]))
- {
- GSList *li;
- for (li = p->sources; li; li = li->next)
- {
- ephy_autocompletion_source_set_basic_key
- (EPHY_AUTOCOMPLETION_SOURCE (li->data), key);
- }
- }
-
- LOG ("Set key %s, old key %s", key, p->keys[0])
-
- if (keylen >= p->key_lengths[0]
- && !strncmp (p->keys[0], key, p->key_lengths[0]))
- {
- if (!strcmp (key, p->keys[0]))
- {
- return;
- }
- if (p->status != GAS_NEEDS_FULL_UPDATE)
- {
- p->status = GAS_NEEDS_REFINE;
- }
- }
- else
- {
- p->status = GAS_NEEDS_FULL_UPDATE;
- }
-
- for (i = 0; p->prefixes[i]; ++i)
- {
- g_free (p->keys[i]);
- p->keys[i] = g_strconcat (p->prefixes[i], key, NULL);
- p->key_lengths[i] = keylen + p->prefix_lengths[i];
- }
-
-}
-
-const EphyAutocompletionMatch *
-ephy_autocompletion_get_matches (EphyAutocompletion *ac)
-{
- ephy_autocompletion_update_matches (ac);
- return ac->priv->matches.array;
-}
-
-const EphyAutocompletionMatch *
-ephy_autocompletion_get_matches_sorted_by_score (EphyAutocompletion *ac,
- gboolean *changed)
-{
- *changed = ephy_autocompletion_sort_by_score (ac);
- return ac->priv->matches.array;
-}
-
-guint
-ephy_autocompletion_get_num_matches (EphyAutocompletion *ac)
-{
- ephy_autocompletion_update_matches (ac);
-
- return ac->priv->matches.num_matches;
-}
-
-guint
-ephy_autocompletion_get_num_action_matches (EphyAutocompletion *ac)
-{
- return ac->priv->matches.num_matches -
- ac->priv->matches.num_action_matches;
-}
-
-static void
-ephy_autocompletion_refine_matches (EphyAutocompletion *ac)
-{
- EphyAutocompletionPrivate *p = ac->priv;
- ACMatchArray oldmatches = p->matches;
- ACMatchArray newmatches;
- guint i;
- gchar *key0 = p->keys[0];
- guint key0l = p->key_lengths[0];
-
- START_PROFILER ("Refine matches")
-
- acma_init (&newmatches);
-
- p->changed = FALSE;
-
- for (i = 0; i < oldmatches.num_matches; i++)
- {
- EphyAutocompletionMatch *mi = &oldmatches.array[i];
-
- if (mi->is_action ||
- (mi->match && mi->substring && g_strrstr (mi->match, p->keys[0])) ||
- (mi->title && mi->substring && g_strrstr (mi->title, p->keys[0])) ||
- !strncmp (key0, mi->title + mi->offset, key0l))
- {
- acma_append (&newmatches, mi, mi->is_action);
- }
- else
- {
- p->changed = TRUE;
- }
- }
-
- acma_destroy (&oldmatches);
- p->matches = newmatches;
-
- STOP_PROFILER ("Refine matches")
-}
-
-static void
-ephy_autocompletion_update_matches (EphyAutocompletion *ac)
-{
- EphyAutocompletionPrivate *p = ac->priv;
- if (p->status == GAS_UPDATED)
- {
- return;
- }
- if (p->status == GAS_NEEDS_FULL_UPDATE)
- {
- ephy_autocompletion_update_matches_full (ac);
- }
- if (p->status == GAS_NEEDS_REFINE)
- {
- ephy_autocompletion_refine_matches (ac);
- }
-
- p->status = GAS_UPDATED;
-}
-
-static void
-ephy_autocompletion_update_matches_full_item (EphyAutocompletionSource *source,
- const char *item,
- const char *title,
- const char *target,
- gboolean is_action,
- gboolean substring,
- guint32 score,
- EphyAutocompletionPrivate *p)
-{
- if (substring)
- {
- if ((item && g_strrstr (item, p->keys[0])) ||
- (title && g_strrstr (title, p->keys[0])))
- {
- EphyAutocompletionMatch m;
- m.match = item;
- m.title = title;
- m.target = target;
- m.is_action = is_action;
- m.substring = substring;
- m.offset = 0;
- m.score = score;
- acma_append (&p->matches, &m, is_action);
- }
- }
- else if (is_action)
- {
- EphyAutocompletionMatch m;
- m.match = item;
- m.title = title;
- m.target = target;
- m.is_action = is_action;
- m.substring = substring;
- m.offset = 0;
- m.score = score;
- acma_append (&p->matches, &m, is_action);
- }
- else
- {
- guint i;
- for (i = 0; p->keys[i]; ++i)
- {
- if (!strncmp (item, p->keys[i], p->key_lengths[i]))
- {
- EphyAutocompletionMatch m;
- m.match = item;
- m.title = title;
- m.target = target;
- m.is_action = is_action;
- m.substring = substring;
- m.offset = p->prefix_lengths[i];
- m.score = score;
- acma_append (&p->matches, &m, is_action);
- }
- }
- }
-}
-
-static void
-ephy_autocompletion_update_matches_full (EphyAutocompletion *ac)
-{
- EphyAutocompletionPrivate *p = ac->priv;
- GSList *li;
-
- START_PROFILER ("Update full")
-
- acma_destroy (&p->matches);
-
- for (li = p->sources; li; li = li->next)
- {
- EphyAutocompletionSource *s = EPHY_AUTOCOMPLETION_SOURCE (li->data);
- g_assert (s);
- ephy_autocompletion_source_foreach (s, p->keys[0],
- (EphyAutocompletionSourceForeachFunc)
- ephy_autocompletion_update_matches_full_item,
- p);
- }
-
- STOP_PROFILER ("Update full")
-
- p->sorted = FALSE;
- p->changed = TRUE;
-
- LOG ("AC: %d matches, fully updated", p->matches.num_matches);
-}
-
-static gint
-ephy_autocompletion_compare_scores (EphyAutocompletionMatch *a, EphyAutocompletionMatch *b)
-{
- /* higher scores first */
- return b->score - a->score;
-}
-
-static gint
-ephy_autocompletion_compare_scores_and_alpha (EphyAutocompletionMatch *a, EphyAutocompletionMatch *b)
-{
- if (a->score == b->score)
- {
- return strcmp (a->title, b->title);
- }
- else
- {
- /* higher scores first */
- return b->score - a->score;
- }
-}
-
-static gboolean
-ephy_autocompletion_sort_by_score (EphyAutocompletion *ac)
-{
- EphyAutocompletionPrivate *p = ac->priv;
-
- gint (*comparer) (EphyAutocompletionMatch *m1, EphyAutocompletionMatch *m2);
-
- if (p->sort_alpha)
- {
- comparer = ephy_autocompletion_compare_scores_and_alpha;
- }
- else
- {
- comparer = ephy_autocompletion_compare_scores;
- }
-
- ephy_autocompletion_update_matches (ac);
- if (p->changed == FALSE) return FALSE;
-
- START_PROFILER ("Sorting")
-
- if (p->matches.num_matches > 0)
- {
- qsort (p->matches.array, p->matches.num_matches,
- sizeof (EphyAutocompletionMatch),
- (void *) comparer);
- }
-
- p->sorted = TRUE;
-
- STOP_PROFILER ("Sorting")
-
- return TRUE;
-}
-
-static void
-ephy_autocompletion_data_changed_cb (EphyAutocompletionSource *s,
- EphyAutocompletion *ac)
-{
- LOG ("Data changed, resetting");
- ephy_autocompletion_reset (ac);
-
- g_signal_emit (ac, EphyAutocompletionSignals[EPHY_AUTOCOMPLETION_SOURCES_CHANGED], 0);
-}
-
-void
-ephy_autocompletion_set_prefixes (EphyAutocompletion *ac,
- const gchar **prefixes)
-{
- EphyAutocompletionPrivate *p = ac->priv;
- guint nprefixes = 0;
- gchar *oldkey = g_strdup (p->keys[0]);
- guint i;
-
- /* count prefixes */
- while (prefixes[nprefixes])
- {
- ++nprefixes;
- }
-
- nprefixes--;
-
- g_strfreev (p->keys);
- g_free (p->key_lengths);
- g_strfreev (p->prefixes);
- g_free (p->prefix_lengths);
-
- p->prefixes = g_new0 (gchar *, nprefixes + 2);
- p->prefix_lengths = g_new0 (guint, nprefixes + 2);
- p->keys = g_new0 (gchar *, nprefixes + 2);
- p->key_lengths = g_new0 (guint, nprefixes + 2);
-
- p->prefixes[0] = g_strdup ("");
- p->prefix_lengths[0] = 0;
- p->keys[0] = oldkey;
- p->key_lengths[0] = strlen (p->keys[0]);
-
- for (i = 0; i < nprefixes; ++i)
- {
- p->prefixes[i + 1] = g_strdup (prefixes[i]);
- p->prefix_lengths[i + 1] = strlen (prefixes[i]);
- p->keys[i + 1] = g_strconcat (p->prefixes[i + 1], p->keys[0], NULL);
- p->key_lengths[i + 1] = p->prefix_lengths[i + 1] + p->key_lengths[0];
- }
-
- p->nkeys = nprefixes;
-}
-
-
-/* ACMatchArray */
-
-static void
-acma_init (ACMatchArray *a)
-{
- a->array = NULL;
- a->array_size = 0;
- a->num_matches = 0;
-}
-
-/**
- * Does not free the struct itself, only its contents
- */
-static void
-acma_destroy (ACMatchArray *a)
-{
- g_free (a->array);
- a->array = NULL;
- a->array_size = 0;
- a->num_matches = 0;
- a->num_action_matches = 0;
-}
-
-static inline void
-acma_append (ACMatchArray *a,
- EphyAutocompletionMatch *m,
- gboolean action)
-{
- if (a->array_size == a->num_matches)
- {
- acma_grow (a);
- }
-
- a->array[a->num_matches] = *m;
- a->num_matches++;
- if (action) a->num_action_matches++;
-}
-
-static void
-acma_grow (ACMatchArray *a)
-{
- gint new_size;
- EphyAutocompletionMatch *new_array;
-
- new_size = a->array_size + ACMA_BASE_SIZE;
- new_array = g_renew (EphyAutocompletionMatch, a->array, new_size);
-
- a->array_size = new_size;
- a->array = new_array;
-}
diff --git a/lib/ephy-autocompletion.h b/lib/ephy-autocompletion.h
deleted file mode 100644
index 7a31c0c9f..000000000
--- a/lib/ephy-autocompletion.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2002 Ricardo Fernández Pascual
- *
- * 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef EPHY_AUTOCOMPLETION_H
-#define EPHY_AUTOCOMPLETION_H
-
-#include <glib-object.h>
-#include "ephy-autocompletion-source.h"
-
-G_BEGIN_DECLS
-
-/* object forward declarations */
-
-typedef struct _EphyAutocompletion EphyAutocompletion;
-typedef struct _EphyAutocompletionClass EphyAutocompletionClass;
-typedef struct _EphyAutocompletionPrivate EphyAutocompletionPrivate;
-typedef struct _EphyAutocompletionMatch EphyAutocompletionMatch;
-
-/**
- * EphyAutocompletion object
- */
-
-#define EPHY_TYPE_AUTOCOMPLETION (ephy_autocompletion_get_type())
-#define EPHY_AUTOCOMPLETION(object) (G_TYPE_CHECK_INSTANCE_CAST((object), \
- EPHY_TYPE_AUTOCOMPLETION,\
- EphyAutocompletion))
-#define EPHY_AUTOCOMPLETION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), \
- EPHY_TYPE_AUTOCOMPLETION,\
- EphyAutocompletionClass))
-#define EPHY_IS_AUTOCOMPLETION(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), \
- EPHY_TYPE_AUTOCOMPLETION))
-#define EPHY_IS_AUTOCOMPLETION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), \
- EPHY_TYPE_AUTOCOMPLETION))
-#define EPHY_AUTOCOMPLETION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), \
- EPHY_TYPE_AUTOCOMPLETION,\
- EphyAutocompletionClass))
-
-struct _EphyAutocompletionClass
-{
- GObjectClass parent_class;
-
- /* signals */
- void (*sources_changed) (EphyAutocompletion *ac);
-};
-
-/* Remember: fields are public read-only */
-struct _EphyAutocompletion
-{
- GObject parent_object;
-
- EphyAutocompletionPrivate *priv;
-};
-
-struct _EphyAutocompletionMatch
-{
- const char *match;
- const char *title;
- const char *target;
- guint offset;
- gint32 score;
- gboolean is_action;
- gboolean substring;
-};
-
-/* this is a set of usual prefixes for web browsing */
-#define EPHY_AUTOCOMPLETION_USUAL_WEB_PREFIXES \
- "http://www.", \
- "http://", \
- "https://www.", \
- "https://", \
- "file://", \
- "www."
-
-GType ephy_autocompletion_get_type (void);
-EphyAutocompletion * ephy_autocompletion_new (void);
-void ephy_autocompletion_add_source (EphyAutocompletion *ac,
- EphyAutocompletionSource *s);
-void ephy_autocompletion_set_prefixes (EphyAutocompletion *ac,
- const gchar **prefixes);
-void ephy_autocompletion_set_key (EphyAutocompletion *ac,
- const gchar *key);
-const EphyAutocompletionMatch *ephy_autocompletion_get_matches (EphyAutocompletion *ac);
-const EphyAutocompletionMatch *ephy_autocompletion_get_matches_sorted_by_score
- (EphyAutocompletion *ac,
- gboolean *changed);
-guint ephy_autocompletion_get_num_matches (EphyAutocompletion *ac);
-guint ephy_autocompletion_get_num_action_matches (EphyAutocompletion *ac);
-
-G_END_DECLS
-
-#endif
diff --git a/lib/ephy-node-common.h b/lib/ephy-node-common.h
index 72b550c1d..a81fafb20 100644
--- a/lib/ephy-node-common.h
+++ b/lib/ephy-node-common.h
@@ -37,7 +37,8 @@ enum
STATES_NODE_ID = 4,
HOSTS_NODE_ID = 5,
PAGES_NODE_ID = 6,
- ICONS_NODE_ID = 9
+ ICONS_NODE_ID = 9,
+ SMARTBOOKMARKS_NODE_ID = 10
};
typedef enum
diff --git a/lib/widgets/Makefile.am b/lib/widgets/Makefile.am
index 7331079a5..6a8835728 100644
--- a/lib/widgets/Makefile.am
+++ b/lib/widgets/Makefile.am
@@ -14,8 +14,6 @@ noinst_LTLIBRARIES = libephywidgets.la
libephywidgets_la_SOURCES = \
ephy-arrow-toolbutton.c \
ephy-arrow-toolbutton.h \
- ephy-autocompletion-window.c \
- ephy-autocompletion-window.h \
ephy-ellipsizing-label.c \
ephy-ellipsizing-label.h \
ephy-location-entry.c \
diff --git a/lib/widgets/ephy-autocompletion-window.c b/lib/widgets/ephy-autocompletion-window.c
deleted file mode 100644
index 39bd9d77e..000000000
--- a/lib/widgets/ephy-autocompletion-window.c
+++ /dev/null
@@ -1,839 +0,0 @@
-/*
- * Copyright (C) 2002 Ricardo Fernández Pascual
- *
- * 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * $Id$
- */
-
-#include <gtk/gtkcellrenderertext.h>
-#include <gtk/gtktreeview.h>
-#include <gtk/gtkscrolledwindow.h>
-#include <gtk/gtktreeselection.h>
-#include <gtk/gtkliststore.h>
-#include <gtk/gtkwindow.h>
-#include <gtk/gtkmain.h>
-#include <gtk/gtkvbox.h>
-#include <gdk/gdkkeysyms.h>
-#include <gtk/gtkframe.h>
-
-#include "ephy-autocompletion-window.h"
-#include "ephy-string.h"
-#include "ephy-marshal.h"
-#include "ephy-gui.h"
-#include "ephy-debug.h"
-
-/* This is copied from gtkscrollbarwindow.c */
-#define DEFAULT_SCROLLBAR_SPACING 3
-
-#define SCROLLBAR_SPACING(w) \
- (GTK_SCROLLED_WINDOW_GET_CLASS (w)->scrollbar_spacing >= 0 ? \
- GTK_SCROLLED_WINDOW_GET_CLASS (w)->scrollbar_spacing : DEFAULT_SCROLLBAR_SPACING)
-
-#define MAX_VISIBLE_ROWS 9
-#define MAX_COMPLETION_ALTERNATIVES 7
-
-/**
- * Private data
- */
-
-#define EPHY_AUTOCOMPLETION_WINDOW_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_AUTOCOMPLETION_WINDOW, EphyAutocompletionWindowPrivate))
-
-struct _EphyAutocompletionWindowPrivate {
- EphyAutocompletion *autocompletion;
- GtkWidget *parent;
-
- GtkWidget *window;
- GtkScrolledWindow *scrolled_window;
- GtkTreeView *tree_view;
- GtkTreeViewColumn *col1;
- GtkTreeView *action_tree_view;
- GtkTreeViewColumn *action_col1;
- int sel_index;
- gboolean action;
-
- char *selected;
-
- GtkListStore *list_store;
- GtkListStore *action_list_store;
- guint last_added_match;
- int view_nitems;
-
- gboolean shown;
-};
-
-/**
- * Private functions, only availble from this file
- */
-static void ephy_autocompletion_window_class_init (EphyAutocompletionWindowClass *klass);
-static void ephy_autocompletion_window_init (EphyAutocompletionWindow *aw);
-static void ephy_autocompletion_window_finalize_impl (GObject *o);
-static void ephy_autocompletion_window_init_widgets (EphyAutocompletionWindow *aw);
-static void ephy_autocompletion_window_selection_changed_cb (GtkTreeSelection *treeselection,
- EphyAutocompletionWindow *aw);
-static gboolean ephy_autocompletion_window_button_press_event_cb (GtkWidget *widget,
- GdkEventButton *event,
- EphyAutocompletionWindow *aw);
-static gboolean ephy_autocompletion_window_key_press_cb (GtkWidget *widget,
- GdkEventKey *event,
- EphyAutocompletionWindow *aw);
-static void ephy_autocompletion_window_event_after_cb (GtkWidget *wid, GdkEvent *event,
- EphyAutocompletionWindow *aw);
-static void ephy_autocompletion_window_fill_store_chunk (EphyAutocompletionWindow *aw);
-
-
-static gpointer g_object_class;
-
-enum EphyAutocompletionWindowSignalsEnum {
- ACTIVATED,
- SELECTED,
- EPHY_AUTOCOMPLETION_WINDOW_HIDDEN,
- EPHY_AUTOCOMPLETION_WINDOW_LAST_SIGNAL
-};
-static gint EphyAutocompletionWindowSignals[EPHY_AUTOCOMPLETION_WINDOW_LAST_SIGNAL];
-
-GType
-ephy_autocompletion_window_get_type (void)
-{
- static GType ephy_autocompletion_window_type = 0;
-
- if (ephy_autocompletion_window_type == 0)
- {
- static const GTypeInfo our_info =
- {
- sizeof (EphyAutocompletionWindowClass),
- NULL,
- NULL,
- (GClassInitFunc) ephy_autocompletion_window_class_init,
- NULL,
- NULL,
- sizeof (EphyAutocompletionWindow),
- 0,
- (GInstanceInitFunc) ephy_autocompletion_window_init
- };
-
- ephy_autocompletion_window_type = g_type_register_static (G_TYPE_OBJECT,
- "EphyAutocompletionWindow",
- &our_info, 0);
- }
-
- return ephy_autocompletion_window_type;
-}
-
-static void
-ephy_autocompletion_window_class_init (EphyAutocompletionWindowClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- g_object_class = g_type_class_peek_parent (klass);
-
- object_class->finalize = ephy_autocompletion_window_finalize_impl;
-
- EphyAutocompletionWindowSignals[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 (EphyAutocompletionWindowClass, activated),
- NULL, NULL,
- ephy_marshal_VOID__STRING_INT,
- G_TYPE_NONE,
- 2,
- G_TYPE_STRING,
- G_TYPE_INT);
-
- EphyAutocompletionWindowSignals[SELECTED] = g_signal_new (
- "selected", G_OBJECT_CLASS_TYPE (klass),
- G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST | G_SIGNAL_RUN_CLEANUP,
- G_STRUCT_OFFSET (EphyAutocompletionWindowClass, selected),
- NULL, NULL,
- ephy_marshal_VOID__STRING_INT,
- G_TYPE_NONE,
- 2,
- G_TYPE_STRING,
- G_TYPE_INT);
-
- EphyAutocompletionWindowSignals[EPHY_AUTOCOMPLETION_WINDOW_HIDDEN] = g_signal_new (
- "hidden", G_OBJECT_CLASS_TYPE (klass),
- G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST | G_SIGNAL_RUN_CLEANUP,
- G_STRUCT_OFFSET (EphyAutocompletionWindowClass, hidden),
- NULL, NULL,
- ephy_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- g_type_class_add_private (object_class, sizeof (EphyAutocompletionWindowPrivate));
-}
-
-static void
-ephy_autocompletion_window_init (EphyAutocompletionWindow *aw)
-{
- EphyAutocompletionWindowPrivate *p = EPHY_AUTOCOMPLETION_WINDOW_GET_PRIVATE (aw);
- GtkTreeSelection *s;
-
- aw->priv = p;
- p->selected = NULL;
-
- ephy_autocompletion_window_init_widgets (aw);
-
- s = gtk_tree_view_get_selection (p->tree_view);
- /* I would like to use GTK_SELECTION_SINGLE, but it seems to require that one
- item is selected always */
- gtk_tree_selection_set_mode (s, GTK_SELECTION_MULTIPLE);
-
- g_signal_connect (s, "changed", G_CALLBACK (ephy_autocompletion_window_selection_changed_cb), aw);
-
- s = gtk_tree_view_get_selection (p->action_tree_view);
- gtk_tree_selection_set_mode (s, GTK_SELECTION_MULTIPLE);
-
- g_signal_connect (s, "changed", G_CALLBACK (ephy_autocompletion_window_selection_changed_cb), aw);
-}
-
-static void
-ephy_autocompletion_window_finalize_impl (GObject *o)
-{
- EphyAutocompletionWindow *aw = EPHY_AUTOCOMPLETION_WINDOW (o);
- EphyAutocompletionWindowPrivate *p = aw->priv;
-
- if (p->list_store) g_object_unref (p->list_store);
- if (p->action_list_store) g_object_unref (p->action_list_store);
- if (p->parent) g_object_unref (p->parent);
- if (p->window) gtk_widget_destroy (p->window);
-
- if (p->autocompletion)
- {
- g_signal_handlers_disconnect_matched (p->autocompletion, G_SIGNAL_MATCH_DATA, 0, 0,
- NULL, NULL, aw);
- g_object_unref (p->autocompletion);
- }
-
- g_free (p->selected);
-
- gdk_pointer_ungrab (GDK_CURRENT_TIME);
- gdk_keyboard_ungrab (GDK_CURRENT_TIME);
-
- G_OBJECT_CLASS (g_object_class)->finalize (o);
-}
-
-static gboolean
-set_renderer_bg_color (GtkWidget *widget,
- GtkStyle *previous_style,
- GtkCellRenderer *renderer)
-{
- GValue v = { 0 };
- GdkColor *bg_color;
- GtkStyle *style;
-
- g_value_init (&v, GDK_TYPE_COLOR);
- g_object_get_property (G_OBJECT (renderer), "cell_background_gdk", &v);
- bg_color = g_value_peek_pointer (&v);
- style = gtk_widget_get_style (widget);
- *bg_color = style->bg[GTK_STATE_NORMAL];
- g_object_set_property (G_OBJECT (renderer), "cell_background_gdk", &v);
-
- return FALSE;
-}
-
-static void
-ephy_autocompletion_window_init_widgets (EphyAutocompletionWindow *aw)
-{
- EphyAutocompletionWindowPrivate *p = aw->priv;
- GtkWidget *sw;
- GtkCellRenderer *renderer;
- GtkWidget *frame;
- GtkWidget *vbox;
-
- p->window = gtk_window_new (GTK_WINDOW_POPUP);
- gtk_window_set_resizable (GTK_WINDOW (p->window), FALSE);
-
- frame = gtk_frame_new (NULL);
- gtk_frame_set_shadow_type (GTK_FRAME (frame),
- GTK_SHADOW_OUT);
- gtk_container_add (GTK_CONTAINER (p->window), frame);
- gtk_widget_show (frame);
-
- vbox = gtk_vbox_new (FALSE, 0);
- gtk_widget_show (vbox);
- gtk_container_add (GTK_CONTAINER (frame), vbox);
-
- sw = gtk_scrolled_window_new (NULL, NULL);
- gtk_box_pack_start (GTK_BOX (vbox),
- sw, TRUE, TRUE, 0);
- gtk_scrolled_window_set_shadow_type
- (GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_IN);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
- GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
- p->scrolled_window = GTK_SCROLLED_WINDOW (sw);
- gtk_widget_show (sw);
-
- p->tree_view = GTK_TREE_VIEW (gtk_tree_view_new ());
- gtk_container_add (GTK_CONTAINER (sw), GTK_WIDGET (p->tree_view));
- gtk_widget_realize (GTK_WIDGET (p->tree_view));
-
- renderer = gtk_cell_renderer_text_new ();
- p->col1 = gtk_tree_view_column_new ();
- gtk_tree_view_column_pack_start (p->col1, renderer, TRUE);
- gtk_tree_view_column_set_attributes (p->col1, renderer,
- "text", 0,
- NULL);
- gtk_tree_view_append_column (p->tree_view, p->col1);
-
- gtk_tree_view_set_headers_visible (p->tree_view, FALSE);
- gtk_widget_show (GTK_WIDGET(p->tree_view));
-
- p->action_tree_view = GTK_TREE_VIEW (gtk_tree_view_new ());
- gtk_box_pack_start (GTK_BOX (vbox),
- GTK_WIDGET (p->action_tree_view),
- FALSE, TRUE, 0);
-
- renderer = gtk_cell_renderer_text_new ();
-
- set_renderer_bg_color (p->window, NULL, renderer);
- g_signal_connect (G_OBJECT (p->window), "style-set",
- G_CALLBACK (set_renderer_bg_color), G_OBJECT (renderer));
-
- p->action_col1 = gtk_tree_view_column_new ();
- gtk_tree_view_column_pack_start (p->action_col1, renderer, TRUE);
- gtk_tree_view_column_set_attributes (p->action_col1, renderer,
- "text", 0,
- NULL);
- gtk_tree_view_append_column (p->action_tree_view, p->action_col1);
-
- gtk_tree_view_set_headers_visible (p->action_tree_view, FALSE);
- gtk_widget_show (GTK_WIDGET(p->action_tree_view));
-}
-
-EphyAutocompletionWindow *
-ephy_autocompletion_window_new (EphyAutocompletion *ac, GtkWidget *w)
-{
- EphyAutocompletionWindow *ret = g_object_new (EPHY_TYPE_AUTOCOMPLETION_WINDOW, NULL);
- ephy_autocompletion_window_set_parent_widget (ret, w);
- ephy_autocompletion_window_set_autocompletion (ret, ac);
- return ret;
-}
-
-void
-ephy_autocompletion_window_set_parent_widget (EphyAutocompletionWindow *aw, GtkWidget *w)
-{
- if (aw->priv->parent) g_object_unref (aw->priv->parent);
- aw->priv->parent = g_object_ref (w);
-}
-
-void
-ephy_autocompletion_window_set_autocompletion (EphyAutocompletionWindow *aw,
- EphyAutocompletion *ac)
-{
- EphyAutocompletionWindowPrivate *p = aw->priv;
-
- if (p->autocompletion)
- {
- g_signal_handlers_disconnect_matched (p->autocompletion, G_SIGNAL_MATCH_DATA, 0, 0,
- NULL, NULL, aw);
-
- g_object_unref (p->autocompletion);
-
- }
- p->autocompletion = g_object_ref (ac);
-}
-
-static void
-ephy_autocompletion_window_selection_changed_cb (GtkTreeSelection *treeselection,
- EphyAutocompletionWindow *aw)
-{
- GList *l;
- GtkTreeModel *model;
-
- if (aw->priv->selected) g_free (aw->priv->selected);
-
- l = gtk_tree_selection_get_selected_rows (treeselection, &model);
- if (l)
- {
- GtkTreePath *path;
- GtkTreeIter iter;
- path = (GtkTreePath *)l->data;
-
- gtk_tree_model_get_iter (model, &iter, path);
- gtk_tree_model_get (model, &iter, 1,
- &aw->priv->selected, -1);
-
- g_list_foreach (l, (GFunc)gtk_tree_path_free, NULL);
- g_list_free (l);
- }
- else
- {
- aw->priv->selected = NULL;
- }
-}
-
-static void
-ephy_autocompletion_window_get_dimensions (EphyAutocompletionWindow *aw,
- int *x, int *y, int *width, int *height)
-{
- GtkBin *popwin;
- GtkWidget *widget;
- GtkScrolledWindow *popup;
- gint real_height;
- GtkRequisition list_requisition;
- gboolean show_vscroll = FALSE;
- gint avail_height;
- gint min_height;
- gint alloc_width;
- gint work_height;
- gint old_height;
- gint old_width;
- int row_height;
-
- widget = GTK_WIDGET (aw->priv->parent);
- popup = GTK_SCROLLED_WINDOW (aw->priv->scrolled_window);
- popwin = GTK_BIN (aw->priv->window);
-
- gdk_window_get_origin (widget->window, x, y);
- real_height = MIN (widget->requisition.height,
- widget->allocation.height);
- *y += real_height;
- avail_height = gdk_screen_height () - *y;
-
- gtk_widget_size_request (GTK_WIDGET(aw->priv->tree_view),
- &list_requisition);
-
- alloc_width = (widget->allocation.width -
- 2 * popwin->child->style->xthickness -
- 2 * GTK_CONTAINER (popwin->child)->border_width -
- 2 * GTK_CONTAINER (popup)->border_width -
- 2 * GTK_CONTAINER (GTK_BIN (popup)->child)->border_width -
- 2 * GTK_BIN (popup)->child->style->xthickness);
-
- work_height = (2 * popwin->child->style->ythickness +
- 2 * GTK_CONTAINER (popwin->child)->border_width +
- 2 * GTK_CONTAINER (popup)->border_width +
- 2 * GTK_CONTAINER (GTK_BIN (popup)->child)->border_width +
- 2 * GTK_BIN (popup)->child->style->ythickness);
-
- min_height = MIN (list_requisition.height,
- popup->vscrollbar->requisition.height);
-
- row_height = list_requisition.height / MAX (aw->priv->view_nitems, 1);
- LOG ("Real list requisition %d, Items %d", list_requisition.height, aw->priv->view_nitems)
- list_requisition.height = MIN (row_height * MAX_VISIBLE_ROWS, list_requisition.height);
- LOG ("Row Height %d, Fake list requisition %d", row_height, list_requisition.height)
-
- do
- {
- old_width = alloc_width;
- old_height = work_height;
-
- if (!show_vscroll &&
- work_height + list_requisition.height > avail_height)
- {
- if (work_height + min_height > avail_height &&
- *y - real_height > avail_height)
- {
- *y -= (work_height + list_requisition.height +
- real_height);
- break;
- }
- alloc_width -= (popup->vscrollbar->requisition.width +
- SCROLLBAR_SPACING (popup));
- show_vscroll = TRUE;
- }
- } while (old_width != alloc_width || old_height != work_height);
-
- *width = widget->allocation.width;
-
- if (*x < 0) *x = 0;
-
- *height = MIN (work_height + list_requisition.height,
- avail_height);
-
- /* Action view */
- work_height = (2 * GTK_CONTAINER (popup)->border_width +
- 2 * GTK_WIDGET (popup)->style->ythickness);
-
- if (!GTK_WIDGET_VISIBLE (aw->priv->scrolled_window))
- {
- *height = work_height;
- }
-
- gtk_widget_size_request (GTK_WIDGET(aw->priv->action_tree_view),
- &list_requisition);
-
- if (GTK_WIDGET_VISIBLE (aw->priv->action_tree_view))
- {
- *height += list_requisition.height;
- }
-}
-
-static void
-ephy_autocompletion_window_fill_store_chunk (EphyAutocompletionWindow *aw)
-{
- EphyAutocompletionWindowPrivate *p = aw->priv;
- const EphyAutocompletionMatch *matches;
- guint i;
- gboolean changed;
- guint nmatches;
- guint last;
- guint completion_nitems = 0, action_nitems = 0, substring_nitems = 0;
-
- START_PROFILER ("Fill store")
-
- nmatches = ephy_autocompletion_get_num_matches (p->autocompletion);
- matches = ephy_autocompletion_get_matches_sorted_by_score (p->autocompletion,
- &changed);
- if (!changed) return;
-
- if (p->list_store) g_object_unref (p->list_store);
- p->list_store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
-
- if (p->action_list_store) g_object_unref (p->action_list_store);
- p->action_list_store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
-
- last = p->last_added_match = 0;
-
- for (i = 0; last < nmatches; i++, last++)
- {
- const EphyAutocompletionMatch *m = &matches[last];
- GtkTreeIter iter;
- GtkListStore *store;
-
- if (m->is_action || m->substring ||
- completion_nitems <= MAX_COMPLETION_ALTERNATIVES)
- {
- if (m->is_action)
- {
- store = p->action_list_store;
- action_nitems ++;
- }
- else if (m->substring)
- {
- store = p->list_store;
- substring_nitems ++;
- }
- else
- {
- store = p->list_store;
- completion_nitems ++;
- }
-
- gtk_list_store_append (store, &iter);
- gtk_list_store_set (store, &iter,
- 0, m->title,
- 1, m->target,
- -1);
- }
- }
-
- p->view_nitems = substring_nitems + completion_nitems;
-
- gtk_widget_show (GTK_WIDGET (p->scrolled_window));
- gtk_widget_show (GTK_WIDGET (p->action_tree_view));
- if (p->view_nitems == 0)
- {
- gtk_widget_hide (GTK_WIDGET (p->scrolled_window));
- }
- if (action_nitems == 0)
- {
- gtk_widget_hide (GTK_WIDGET (p->action_tree_view));
- }
-
- p->last_added_match = last;
-
- STOP_PROFILER ("Fill store")
-}
-
-void
-ephy_autocompletion_window_show (EphyAutocompletionWindow *aw)
-{
- EphyAutocompletionWindowPrivate *p = aw->priv;
- gint x, y, height, width;
- guint nmatches;
-
- g_return_if_fail (p->window);
- g_return_if_fail (p->autocompletion);
-
- nmatches = ephy_autocompletion_get_num_matches (p->autocompletion);
- if (nmatches <= 0)
- {
- ephy_autocompletion_window_hide (aw);
- return;
- }
-
- START_PROFILER ("Showing window")
-
- ephy_autocompletion_window_fill_store_chunk (aw);
-
- gtk_tree_view_set_model (p->tree_view, GTK_TREE_MODEL (p->list_store));
- gtk_tree_view_set_model (p->action_tree_view, GTK_TREE_MODEL (p->action_list_store));
-
- ephy_autocompletion_window_get_dimensions (aw, &x, &y, &width, &height);
-
- gtk_widget_set_size_request (GTK_WIDGET (p->window), width,
- height);
- gtk_window_move (GTK_WINDOW (p->window), x, y);
-
- if (!p->shown)
- {
- gtk_widget_show (p->window);
-
- gdk_pointer_grab (p->parent->window, TRUE,
- GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK |
- GDK_BUTTON_RELEASE_MASK,
- NULL, NULL, GDK_CURRENT_TIME);
- gdk_keyboard_grab (p->parent->window, TRUE, GDK_CURRENT_TIME);
- gtk_grab_add (p->window);
-
- g_signal_connect (p->window, "button-press-event",
- G_CALLBACK (ephy_autocompletion_window_button_press_event_cb),
- aw);
- g_signal_connect (p->window, "key-press-event",
- G_CALLBACK (ephy_autocompletion_window_key_press_cb),
- aw);
- g_signal_connect (p->tree_view, "event-after",
- G_CALLBACK (ephy_autocompletion_window_event_after_cb),
- aw);
- g_signal_connect (p->action_tree_view, "event-after",
- G_CALLBACK (ephy_autocompletion_window_event_after_cb),
- aw);
-
- p->shown = TRUE;
- }
-
- gtk_tree_view_scroll_to_point (GTK_TREE_VIEW (p->tree_view), 0, 0);
-
- gtk_widget_grab_focus (GTK_WIDGET (p->tree_view));
-
- STOP_PROFILER ("Showing window")
-}
-
-static gboolean
-ephy_autocompletion_window_button_press_event_cb (GtkWidget *widget,
- GdkEventButton *event,
- EphyAutocompletionWindow *aw)
-{
- GtkWidget *event_widget;
-
- event_widget = gtk_get_event_widget ((GdkEvent *) event);
-
- /* Check to see if button press happened inside the alternatives
- window. If not, destroy the window. */
- if (event_widget != aw->priv->window)
- {
- while (event_widget)
- {
- if (event_widget == aw->priv->window)
- return FALSE;
- event_widget = event_widget->parent;
- }
- }
- ephy_autocompletion_window_hide (aw);
-
- return TRUE;
-}
-
-static void
-move_selection (EphyAutocompletionWindow *aw, int dir)
-{
- int new_index;
- int n_compl, n_actions, n_items;
- GtkTreeModel *compl_model, *actions_model;
- GtkTreeSelection *compl_sel, *actions_sel;
-
- compl_model = gtk_tree_view_get_model (aw->priv->tree_view);
- actions_model = gtk_tree_view_get_model (aw->priv->action_tree_view);
- compl_sel = gtk_tree_view_get_selection (aw->priv->tree_view);
- actions_sel = gtk_tree_view_get_selection (aw->priv->action_tree_view);
-
- n_compl = gtk_tree_model_iter_n_children (compl_model, NULL);
- n_actions = gtk_tree_model_iter_n_children (actions_model, NULL);
- n_items = n_compl + n_actions;
-
- /* Index 0 no selection.
- * Index 1 in the completion.
- * Index -1 in the actions. */
- new_index = aw->priv->sel_index + dir;
-
- /* On overflow stay on 0/max if you are no already there. Otherwise
- go on the opposite limit */
- if (new_index < 0)
- {
- new_index = (aw->priv->sel_index != 0) ? 0 : n_items;
- }
- else if (new_index > n_items)
- {
- new_index = (aw->priv->sel_index != n_items) ? n_items : 0;
- }
-
- gtk_tree_selection_unselect_all (compl_sel);
- gtk_tree_selection_unselect_all (actions_sel);
-
- if (new_index == 0)
- {
- }
- else if (new_index > n_compl)
- {
- GtkTreeIter iter;
- GtkTreePath *path;
-
- gtk_tree_selection_unselect_all (compl_sel);
- gtk_tree_model_iter_nth_child (actions_model, &iter, NULL,
- new_index - n_compl - 1);
- gtk_tree_selection_select_iter (actions_sel, &iter);
-
- path = gtk_tree_model_get_path (actions_model, &iter);
- gtk_tree_view_scroll_to_cell (aw->priv->action_tree_view,
- path, NULL, FALSE, 0, 0);
- gtk_tree_path_free (path);
-
- aw->priv->action = TRUE;
- }
- else if (new_index <= n_compl)
- {
- GtkTreeIter iter;
- GtkTreePath *path;
-
- gtk_tree_selection_unselect_all (actions_sel);
- gtk_tree_model_iter_nth_child (compl_model, &iter, NULL,
- new_index - 1);
- gtk_tree_selection_select_iter (compl_sel, &iter);
-
- path = gtk_tree_model_get_path (compl_model, &iter);
- gtk_tree_view_scroll_to_cell (aw->priv->tree_view,
- path, NULL, FALSE, 0, 0);
- gtk_tree_path_free (path);
-
- aw->priv->action = FALSE;
- }
- else
- {
- g_assert_not_reached ();
- }
-
- aw->priv->sel_index = new_index;
-}
-
-static gboolean
-ephy_autocompletion_window_key_press_hack (EphyAutocompletionWindow *aw,
- guint keyval)
-{
- switch (keyval)
- {
- case GDK_Up:
- move_selection (aw, -1);
- break;
- case GDK_Down:
- move_selection (aw, +1);
- break;
- case GDK_Page_Down:
- move_selection (aw, +5);
- break;
- case GDK_Page_Up:
- move_selection (aw, -5);
- break;
- case GDK_Return:
- case GDK_space:
- if (aw->priv->selected)
- {
- g_signal_emit (aw, EphyAutocompletionWindowSignals
- [ACTIVATED], 0, aw->priv->selected,
- aw->priv->action);
- }
- break;
- }
-
- switch (keyval)
- {
- case GDK_Up:
- case GDK_Down:
- case GDK_Page_Down:
- case GDK_Page_Up:
- if (aw->priv->selected)
- {
- g_signal_emit (aw, EphyAutocompletionWindowSignals
- [SELECTED], 0, aw->priv->selected,
- aw->priv->action);
- }
- break;
- default:
- break;
- }
-
- return TRUE;
-}
-
-static gboolean
-ephy_autocompletion_window_key_press_cb (GtkWidget *widget,
- GdkEventKey *event,
- EphyAutocompletionWindow *aw)
-{
- EphyAutocompletionWindowPrivate *p = aw->priv;
- GdkEventKey tmp_event;
-
- if (event->keyval == GDK_Up || event->keyval == GDK_Down
- || event->keyval == GDK_Page_Up || event->keyval == GDK_Page_Down
- || ((event->keyval == GDK_space || event->keyval == GDK_Return)
- && p->selected))
- {
- return ephy_autocompletion_window_key_press_hack
- (aw, event->keyval);
- }
-
- tmp_event = *event;
- gtk_widget_event (p->parent, (GdkEvent *)&tmp_event);
-
- return TRUE;
-}
-
-void
-ephy_autocompletion_window_hide (EphyAutocompletionWindow *aw)
-{
- if (aw->priv->window && aw->priv->shown)
- {
- gtk_widget_hide (aw->priv->window);
- gtk_grab_remove (aw->priv->window);
- gdk_pointer_ungrab (GDK_CURRENT_TIME);
- gdk_keyboard_ungrab (GDK_CURRENT_TIME);
- ephy_autocompletion_window_unselect (aw);
- g_signal_emit (aw, EphyAutocompletionWindowSignals[EPHY_AUTOCOMPLETION_WINDOW_HIDDEN], 0);
- aw->priv->sel_index = 0;
- aw->priv->action = FALSE;
- }
- g_free (aw->priv->selected);
- aw->priv->selected = NULL;
- aw->priv->shown = FALSE;
-}
-
-void
-ephy_autocompletion_window_unselect (EphyAutocompletionWindow *aw)
-{
- EphyAutocompletionWindowPrivate *p = aw->priv;
- GtkTreeSelection *ts = gtk_tree_view_get_selection (p->tree_view);
- gtk_tree_selection_unselect_all (ts);
-}
-
-static void
-ephy_autocompletion_window_event_after_cb (GtkWidget *wid, GdkEvent *event,
- EphyAutocompletionWindow *aw)
-{
- gboolean action;
- EphyAutocompletionWindowPrivate *p = aw->priv;
-
- action = (wid == GTK_WIDGET (p->action_tree_view));
-
- if (event->type == GDK_BUTTON_PRESS
- && ((GdkEventButton *) event)->button == 1)
- {
- if (p->selected)
- {
- g_signal_emit (aw, EphyAutocompletionWindowSignals
- [ACTIVATED], 0, p->selected, action);
- }
- }
-}
diff --git a/lib/widgets/ephy-autocompletion-window.h b/lib/widgets/ephy-autocompletion-window.h
deleted file mode 100644
index 63b4a4ed3..000000000
--- a/lib/widgets/ephy-autocompletion-window.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2002 Ricardo Fernández Pascual
- *
- * 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef EPHY_AUTOCOMPLETION_WINDOW_H
-#define EPHY_AUTOCOMPLETION_WINDOW_H
-
-#include <glib-object.h>
-#include <gtk/gtkwidget.h>
-
-#include "ephy-autocompletion.h"
-
-G_BEGIN_DECLS
-
-/* object forward declarations */
-
-typedef struct _EphyAutocompletionWindow EphyAutocompletionWindow;
-typedef struct _EphyAutocompletionWindowClass EphyAutocompletionWindowClass;
-typedef struct _EphyAutocompletionWindowPrivate EphyAutocompletionWindowPrivate;
-
-/**
- * Editor object
- */
-
-#define EPHY_TYPE_AUTOCOMPLETION_WINDOW (ephy_autocompletion_window_get_type())
-#define EPHY_AUTOCOMPLETION_WINDOW(object) (G_TYPE_CHECK_INSTANCE_CAST((object), \
- EPHY_TYPE_AUTOCOMPLETION_WINDOW,\
- EphyAutocompletionWindow))
-#define EPHY_AUTOCOMPLETION_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), \
- EPHY_TYPE_AUTOCOMPLETION_WINDOW,\
- EphyAutocompletionWindowClass))
-#define EPHY_IS_AUTOCOMPLETION_WINDOW(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), \
- EPHY_TYPE_AUTOCOMPLETION_WINDOW))
-#define EPHY_IS_AUTOCOMPLETION_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), \
- EPHY_TYPE_AUTOCOMPLETION_WINDOW))
-#define EPHY_AUTOCOMPLETION_WINDOW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), \
- EPHY_TYPE_AUTOCOMPLETION_WINDOW,\
- EphyAutocompletionWindowClass))
-
-struct _EphyAutocompletionWindowClass
-{
- GObjectClass parent_class;
-
- /* signals */
- void (*hidden) (EphyAutocompletionWindow *aw);
- void (*activated) (EphyAutocompletionWindow *aw,
- const char *target,
- int action);
- void (*selected) (EphyAutocompletionWindow *aw,
- const char *target,
- int action);
-};
-
-/* Remember: fields are public read-only */
-struct _EphyAutocompletionWindow
-{
- GObject parent_object;
-
- EphyAutocompletionWindowPrivate *priv;
-};
-
-GType ephy_autocompletion_window_get_type (void);
-EphyAutocompletionWindow *ephy_autocompletion_window_new (EphyAutocompletion *ac,
- GtkWidget *parent);
-void ephy_autocompletion_window_set_parent_widget (EphyAutocompletionWindow *aw,
- GtkWidget *w);
-void ephy_autocompletion_window_set_autocompletion (EphyAutocompletionWindow *aw,
- EphyAutocompletion *ac);
-void ephy_autocompletion_window_show (EphyAutocompletionWindow *aw);
-void ephy_autocompletion_window_hide (EphyAutocompletionWindow *aw);
-void ephy_autocompletion_window_unselect (EphyAutocompletionWindow *aw);
-
-G_END_DECLS
-
-#endif
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));
-}
diff --git a/src/Makefile.am b/src/Makefile.am
index 38c1a5195..f1cc2ad3a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -81,6 +81,8 @@ epiphany_bin_SOURCES = \
$(CORBA_SOURCE) \
$(nautilus_view_sources) \
ephy-automation.c \
+ ephy-completion-model.c \
+ ephy-completion-model.h \
ephy-encoding-menu.c \
ephy-favicon-action.c \
ephy-favorites-menu.c \
diff --git a/src/bookmarks/ephy-bookmark-action.c b/src/bookmarks/ephy-bookmark-action.c
index f805109d4..13d2e2f53 100644
--- a/src/bookmarks/ephy-bookmark-action.c
+++ b/src/bookmarks/ephy-bookmark-action.c
@@ -487,13 +487,17 @@ sync_bookmark_properties (GtkAction *action, EphyNode *bmk)
const char *tmp, *location, *icon;
char *title;
gboolean smart_url;
+ EphyBookmarks *bookmarks;
+ EphyNode *smart_bmks;
+
+ bookmarks = ephy_shell_get_bookmarks (ephy_shell);
+ smart_bmks = ephy_bookmarks_get_smart_bookmarks (bookmarks);
icon = ephy_node_get_property_string
(bmk, EPHY_NODE_BMK_PROP_ICON);
location = ephy_node_get_property_string
(bmk, EPHY_NODE_BMK_PROP_LOCATION);
- smart_url = ephy_node_get_property_boolean
- (bmk, EPHY_NODE_BMK_PROP_HAS_SMART_ADDRESS);
+ smart_url = ephy_node_has_child (smart_bmks, bmk);
tmp = ephy_node_get_property_string
(bmk, EPHY_NODE_BMK_PROP_TITLE);
title = ephy_string_double_underscores (tmp);
diff --git a/src/bookmarks/ephy-bookmarks-export.c b/src/bookmarks/ephy-bookmarks-export.c
index 97c955259..be9b97ea7 100644
--- a/src/bookmarks/ephy-bookmarks-export.c
+++ b/src/bookmarks/ephy-bookmarks-export.c
@@ -73,8 +73,7 @@ void
ephy_bookmarks_export_rdf (EphyBookmarks *bookmarks,
const char *filename)
{
- EphyNode *bmks;
- EphyNode *topics;
+ EphyNode *bmks, *topics, *smart_bmks;
xmlDocPtr doc;
xmlNodePtr root, xml_node, channel_node, channel_seq_node;
xmlNsPtr ephy_ns, rdf_ns, dc_ns;
@@ -110,6 +109,7 @@ ephy_bookmarks_export_rdf (EphyBookmarks *bookmarks,
bmks = ephy_bookmarks_get_bookmarks (bookmarks);
topics = ephy_bookmarks_get_keywords (bookmarks);
+ smart_bmks = ephy_bookmarks_get_smart_bookmarks (bookmarks);
children = ephy_node_get_children (bmks);
for (i = 0; i < children->len; i++)
@@ -123,8 +123,7 @@ ephy_bookmarks_export_rdf (EphyBookmarks *bookmarks,
kid = g_ptr_array_index (children, i);
- smart_url = ephy_node_get_property_boolean
- (kid, EPHY_NODE_BMK_PROP_HAS_SMART_ADDRESS);
+ smart_url = ephy_node_has_child (smart_bmks, kid);
url = ephy_node_get_property_string
(kid, EPHY_NODE_BMK_PROP_LOCATION);
title = ephy_node_get_property_string
diff --git a/src/bookmarks/ephy-bookmarks.c b/src/bookmarks/ephy-bookmarks.c
index 0c05e59c7..9dc4e977e 100644
--- a/src/bookmarks/ephy-bookmarks.c
+++ b/src/bookmarks/ephy-bookmarks.c
@@ -32,7 +32,6 @@
#include "ephy-toolbars-model.h"
#include "ephy-bookmarks-export.h"
#include "ephy-bookmarks-import.h"
-#include "ephy-autocompletion.h"
#include "session.h"
#include <string.h>
@@ -40,7 +39,7 @@
#include <libgnomevfs/gnome-vfs-utils.h>
#define EPHY_BOOKMARKS_XML_ROOT "ephy_bookmarks"
-#define EPHY_BOOKMARKS_XML_VERSION "1.0"
+#define EPHY_BOOKMARKS_XML_VERSION "1.01"
#define BOOKMARKS_SAVE_DELAY (3 * 1000)
#define MAX_FAVORITES_NUM 10
@@ -59,6 +58,7 @@ struct EphyBookmarksPrivate
EphyNode *keywords;
EphyNode *favorites;
EphyNode *notcategorized;
+ EphyNode *smartbookmarks;
EphyNode *lower_fav;
double lower_score;
};
@@ -112,8 +112,6 @@ static void
ephy_bookmarks_init (EphyBookmarks *tab);
static void
ephy_bookmarks_finalize (GObject *object);
-static void
-ephy_bookmarks_autocompletion_source_init (EphyAutocompletionSourceIface *iface);
static GObjectClass *parent_class = NULL;
@@ -137,79 +135,15 @@ ephy_bookmarks_get_type (void)
(GInstanceInitFunc) ephy_bookmarks_init
};
- static const GInterfaceInfo autocompletion_source_info =
- {
- (GInterfaceInitFunc) ephy_bookmarks_autocompletion_source_init,
- NULL,
- NULL
- };
-
ephy_bookmarks_type = g_type_register_static (G_TYPE_OBJECT,
"EphyBookmarks",
&our_info, 0);
-
- g_type_add_interface_static (ephy_bookmarks_type,
- EPHY_TYPE_AUTOCOMPLETION_SOURCE,
- &autocompletion_source_info);
}
return ephy_bookmarks_type;
}
static void
-ephy_bookmarks_autocompletion_source_set_basic_key (EphyAutocompletionSource *source,
- const gchar *basic_key)
-{
- /* nothing to do here */
-}
-
-static void
-ephy_bookmarks_autocompletion_source_foreach (EphyAutocompletionSource *source,
- const gchar *current_text,
- EphyAutocompletionSourceForeachFunc func,
- gpointer data)
-{
- GPtrArray *children;
- int i;
- EphyBookmarks *eb = EPHY_BOOKMARKS (source);
-
- children = ephy_node_get_children (eb->priv->bookmarks);
- for (i = 0; i < children->len; i++)
- {
- EphyNode *kid;
- const char *url, *title, *keywords;
- gboolean smart_url;
-
- kid = g_ptr_array_index (children, i);
- url = ephy_node_get_property_string
- (kid, EPHY_NODE_BMK_PROP_LOCATION);
- smart_url = ephy_node_get_property_boolean
- (kid, EPHY_NODE_BMK_PROP_HAS_SMART_ADDRESS);
- title = ephy_node_get_property_string
- (kid, EPHY_NODE_BMK_PROP_TITLE);
- keywords = ephy_node_get_property_string
- (kid, EPHY_NODE_BMK_PROP_KEYWORDS);
-
- func (source, keywords, title, url, smart_url,
- !smart_url, 0, data);
- }
- ephy_node_thaw (eb->priv->bookmarks);
-}
-
-static void
-ephy_bookmarks_emit_data_changed (EphyBookmarks *eb)
-{
- g_signal_emit_by_name (eb, "data-changed");
-}
-
-static void
-ephy_bookmarks_autocompletion_source_init (EphyAutocompletionSourceIface *iface)
-{
- iface->foreach = ephy_bookmarks_autocompletion_source_foreach;
- iface->set_basic_key = ephy_bookmarks_autocompletion_source_set_basic_key;
-}
-
-static void
ephy_bookmarks_init_defaults (EphyBookmarks *eb)
{
int i;
@@ -527,7 +461,6 @@ bookmarks_changed_cb (EphyNode *node,
EphyNode *child,
EphyBookmarks *eb)
{
- ephy_bookmarks_emit_data_changed (eb);
ephy_bookmarks_save_delayed (eb, BOOKMARKS_SAVE_DELAY);
}
@@ -537,7 +470,6 @@ bookmarks_removed_cb (EphyNode *node,
guint old_index,
EphyBookmarks *eb)
{
- ephy_bookmarks_emit_data_changed (eb);
g_signal_emit (G_OBJECT (eb), ephy_bookmarks_signals[TREE_CHANGED], 0);
ephy_bookmarks_save_delayed (eb, BOOKMARKS_SAVE_DELAY);
}
@@ -715,6 +647,10 @@ ephy_bookmarks_init (EphyBookmarks *eb)
g_value_unset (&value);
ephy_node_add_child (eb->priv->keywords, eb->priv->notcategorized);
+ /* Smart bookmarks */
+ eb->priv->smartbookmarks = ephy_node_new_with_id (db, SMARTBOOKMARKS_NODE_ID);
+ ephy_node_ref (eb->priv->smartbookmarks);
+
if (ephy_node_db_load_from_file (eb->priv->db, eb->priv->xml_file,
EPHY_BOOKMARKS_XML_ROOT,
EPHY_BOOKMARKS_XML_VERSION) == FALSE)
@@ -725,8 +661,6 @@ ephy_bookmarks_init (EphyBookmarks *eb)
}
}
- ephy_bookmarks_emit_data_changed (eb);
-
ephy_setup_history_notifiers (eb);
ephy_bookmarks_update_favorites (eb);
}
@@ -775,21 +709,32 @@ ephy_bookmarks_new ()
}
static void
-update_has_smart_address (EphyNode *bmk, const char *address)
+update_has_smart_address (EphyBookmarks *bookmarks, EphyNode *bmk, const char *address)
{
+ EphyNode *smart_bmks;
gboolean smart = FALSE;
- GValue value = { 0, };
+
+ smart_bmks = bookmarks->priv->smartbookmarks;
if (address)
{
smart = strstr (address, "%s") != NULL;
}
- g_value_init (&value, G_TYPE_BOOLEAN);
- g_value_set_boolean (&value, smart);
- ephy_node_set_property (bmk, EPHY_NODE_BMK_PROP_HAS_SMART_ADDRESS,
- &value);
- g_value_unset (&value);
+ if (smart)
+ {
+ if (!ephy_node_has_child (smart_bmks, bmk))
+ {
+ ephy_node_add_child (smart_bmks, bmk);
+ }
+ }
+ else
+ {
+ if (ephy_node_has_child (smart_bmks, bmk))
+ {
+ ephy_node_add_child (smart_bmks, bmk);
+ }
+ }
}
EphyNode *
@@ -814,12 +759,11 @@ ephy_bookmarks_add (EphyBookmarks *eb,
&value);
g_value_unset (&value);
- update_has_smart_address (bm, url);
+ update_has_smart_address (eb, bm, url);
ephy_node_add_child (eb->priv->bookmarks, bm);
ephy_node_add_child (eb->priv->notcategorized, bm);
- ephy_bookmarks_emit_data_changed (eb);
g_signal_emit (G_OBJECT (eb), ephy_bookmarks_signals[TREE_CHANGED], 0);
ephy_bookmarks_save_delayed (eb, 0);
@@ -839,7 +783,7 @@ ephy_bookmarks_set_address (EphyBookmarks *eb,
&value);
g_value_unset (&value);
- update_has_smart_address (bookmark, address);
+ update_has_smart_address (eb, bookmark, address);
}
EphyNode *
@@ -1235,6 +1179,12 @@ ephy_bookmarks_unset_keyword (EphyBookmarks *eb,
}
EphyNode *
+ephy_bookmarks_get_smart_bookmarks (EphyBookmarks *eb)
+{
+ return eb->priv->smartbookmarks;
+}
+
+EphyNode *
ephy_bookmarks_get_keywords (EphyBookmarks *eb)
{
return eb->priv->keywords;
diff --git a/src/bookmarks/ephy-bookmarks.h b/src/bookmarks/ephy-bookmarks.h
index fbbc2d1f2..8f9ae5986 100644
--- a/src/bookmarks/ephy-bookmarks.h
+++ b/src/bookmarks/ephy-bookmarks.h
@@ -42,7 +42,6 @@ enum
EPHY_NODE_BMK_PROP_LOCATION = 3,
EPHY_NODE_BMK_PROP_KEYWORDS = 4,
EPHY_NODE_KEYWORD_PROP_NAME = 5,
- EPHY_NODE_BMK_PROP_HAS_SMART_ADDRESS = 9,
EPHY_NODE_BMK_PROP_ICON = 7,
EPHY_NODE_KEYWORD_PROP_PRIORITY = 8
};
@@ -127,6 +126,8 @@ EphyNode *ephy_bookmarks_get_bookmarks (EphyBookmarks *eb);
EphyNode *ephy_bookmarks_get_not_categorized (EphyBookmarks *eb);
+EphyNode *ephy_bookmarks_get_smart_bookmarks (EphyBookmarks *eb);
+
G_END_DECLS
#endif
diff --git a/src/ephy-completion-model.c b/src/ephy-completion-model.c
new file mode 100644
index 000000000..95bfe0e69
--- /dev/null
+++ b/src/ephy-completion-model.c
@@ -0,0 +1,601 @@
+/*
+ * Copyright (C) 2002 Jorn Baayen <jorn@nl.linux.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * $Id$
+ */
+
+#include <config.h>
+
+#include "ephy-completion-model.h"
+#include "ephy-node.h"
+#include "ephy-shell.h"
+
+static void ephy_completion_model_class_init (EphyCompletionModelClass *klass);
+static void ephy_completion_model_init (EphyCompletionModel *model);
+static void ephy_completion_model_tree_model_init (GtkTreeModelIface *iface);
+
+#define EPHY_COMPLETION_MODEL_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_COMPLETION_MODEL, EphyCompletionModelPrivate))
+
+struct EphyCompletionModelPrivate
+{
+ EphyNode *history;
+ EphyNode *bookmarks;
+ int stamp;
+};
+
+enum
+{
+ HISTORY_GROUP,
+ BOOKMARKS_GROUP
+};
+
+static GObjectClass *parent_class = NULL;
+
+GType
+ephy_completion_model_get_type (void)
+{
+ static GType ephy_completion_model_type = 0;
+
+ if (ephy_completion_model_type == 0)
+ {
+ static const GTypeInfo our_info =
+ {
+ sizeof (EphyCompletionModelClass),
+ NULL,
+ NULL,
+ (GClassInitFunc) ephy_completion_model_class_init,
+ NULL,
+ NULL,
+ sizeof (EphyCompletionModel),
+ 0,
+ (GInstanceInitFunc) ephy_completion_model_init
+ };
+
+ static const GInterfaceInfo tree_model_info =
+ {
+ (GInterfaceInitFunc) ephy_completion_model_tree_model_init,
+ NULL,
+ NULL
+ };
+
+ ephy_completion_model_type = g_type_register_static (G_TYPE_OBJECT,
+ "EphyCompletionModel",
+ &our_info, 0);
+
+ g_type_add_interface_static (ephy_completion_model_type,
+ GTK_TYPE_TREE_MODEL,
+ &tree_model_info);
+ }
+
+ return ephy_completion_model_type;
+}
+
+static void
+ephy_completion_model_class_init (EphyCompletionModelClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ g_type_class_add_private (object_class, sizeof (EphyCompletionModelPrivate));
+}
+
+static void
+root_child_removed_cb (EphyNode *node,
+ EphyNode *child,
+ guint old_index,
+ EphyCompletionModel *tree_model)
+{
+ EphyCompletionModel *model = EPHY_COMPLETION_MODEL (tree_model);
+ GtkTreePath *path;
+ int real_index;
+
+ real_index = old_index;
+
+ if (node == model->priv->bookmarks)
+ {
+ real_index += ephy_node_get_n_children (model->priv->history);
+ }
+
+ path = gtk_tree_path_new ();
+ gtk_tree_path_append_index (path, real_index);
+ gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
+ gtk_tree_path_free (path);
+}
+
+static void
+node_iter_from_node (EphyCompletionModel *model,
+ EphyNode *node,
+ GtkTreeIter *iter)
+{
+ iter->stamp = model->priv->stamp;
+ iter->user_data = node;
+}
+
+static inline GtkTreePath *
+get_path_real (EphyCompletionModel *model,
+ EphyNode *node)
+{
+ GtkTreePath *retval;
+ int index;
+
+ retval = gtk_tree_path_new ();
+
+ index = ephy_node_get_child_index (model->priv->bookmarks, node);
+ if (index < 0)
+ {
+ index = ephy_node_get_child_index (model->priv->history, node);
+ }
+
+ g_return_val_if_fail (index >= 0, NULL);
+
+ gtk_tree_path_append_index (retval, index);
+
+ return retval;
+}
+
+static void
+root_child_added_cb (EphyNode *node,
+ EphyNode *child,
+ EphyCompletionModel *model)
+{
+ GtkTreePath *path;
+ GtkTreeIter iter;
+
+ node_iter_from_node (model, child, &iter);
+
+ path = get_path_real (model, child);
+ gtk_tree_model_row_inserted (GTK_TREE_MODEL (model), path, &iter);
+ gtk_tree_path_free (path);
+}
+
+static void
+root_child_changed_cb (EphyNode *node,
+ EphyNode *child,
+ EphyCompletionModel *model)
+{
+ GtkTreePath *path;
+ GtkTreeIter iter;
+
+ node_iter_from_node (model, node, &iter);
+
+ path = get_path_real (model, child);
+ gtk_tree_model_row_changed (GTK_TREE_MODEL (model), path, &iter);
+ gtk_tree_path_free (path);
+}
+
+static void
+connect_signals (EphyCompletionModel *model, EphyNode *root)
+{
+ ephy_node_signal_connect_object (root,
+ EPHY_NODE_CHILD_ADDED,
+ (EphyNodeCallback)root_child_added_cb,
+ G_OBJECT (model));
+ ephy_node_signal_connect_object (root,
+ EPHY_NODE_CHILD_REMOVED,
+ (EphyNodeCallback)root_child_removed_cb,
+ G_OBJECT (model));
+ ephy_node_signal_connect_object (root,
+ EPHY_NODE_CHILD_CHANGED,
+ (EphyNodeCallback)root_child_changed_cb,
+ G_OBJECT (model));
+}
+
+static void
+ephy_completion_model_init (EphyCompletionModel *model)
+{
+ EphyBookmarks *bookmarks;
+ EphyHistory *history;
+
+ model->priv = EPHY_COMPLETION_MODEL_GET_PRIVATE (model);
+ model->priv->stamp = g_random_int ();
+
+ history = ephy_embed_shell_get_global_history
+ (EPHY_EMBED_SHELL (ephy_shell));
+ model->priv->history = ephy_history_get_pages (history);
+ connect_signals (model, model->priv->history);
+
+ bookmarks = ephy_shell_get_bookmarks (ephy_shell);
+ model->priv->bookmarks = ephy_bookmarks_get_bookmarks (bookmarks);
+ connect_signals (model, model->priv->bookmarks);
+}
+
+EphyCompletionModel *
+ephy_completion_model_new (void)
+{
+ EphyCompletionModel *model;
+
+ model = EPHY_COMPLETION_MODEL (g_object_new (EPHY_TYPE_COMPLETION_MODEL,
+ NULL));
+
+ g_return_val_if_fail (model->priv != NULL, NULL);
+
+ return model;
+}
+
+static int
+ephy_completion_model_get_n_columns (GtkTreeModel *tree_model)
+{
+ return N_COL;
+}
+
+static GType
+ephy_completion_model_get_column_type (GtkTreeModel *tree_model,
+ int index)
+{
+ GType type = 0;
+
+ switch (index)
+ {
+ case EPHY_COMPLETION_TEXT_COL:
+ case EPHY_COMPLETION_ACTION_COL:
+ case EPHY_COMPLETION_KEYWORDS_COL:
+ type = G_TYPE_STRING;
+ break;
+ case EPHY_COMPLETION_RELEVANCE_COL:
+ type = G_TYPE_INT;
+ break;
+ }
+
+ return type;
+}
+
+static void
+init_text_col (GValue *value, EphyNode *node, int group)
+{
+ const char *text;
+
+ switch (group)
+ {
+ case BOOKMARKS_GROUP:
+ text = ephy_node_get_property_string
+ (node, EPHY_NODE_PAGE_PROP_TITLE);
+ break;
+ case HISTORY_GROUP:
+ text = ephy_node_get_property_string
+ (node, EPHY_NODE_BMK_PROP_LOCATION);
+ break;
+
+ default:
+ text = "";
+ }
+
+ g_value_set_string (value, text);
+}
+
+static void
+init_action_col (GValue *value, EphyNode *node, int group)
+{
+ const char *text;
+
+ switch (group)
+ {
+ case BOOKMARKS_GROUP:
+ text = ephy_node_get_property_string
+ (node, EPHY_NODE_BMK_PROP_LOCATION);
+ break;
+ case HISTORY_GROUP:
+ text = ephy_node_get_property_string
+ (node, EPHY_NODE_PAGE_PROP_LOCATION);
+ break;
+ default:
+ text = "";
+ }
+
+ g_value_set_string (value, text);
+}
+
+static void
+init_keywords_col (GValue *value, EphyNode *node, int group)
+{
+ const char *text = NULL;
+
+ switch (group)
+ {
+ case BOOKMARKS_GROUP:
+ text = ephy_node_get_property_string
+ (node, EPHY_NODE_BMK_PROP_KEYWORDS);
+ break;
+ }
+
+ if (text == NULL)
+ {
+ text = "";
+ }
+
+ g_value_set_string (value, text);
+}
+
+static void
+init_relevance_col (GValue *value, EphyNode *node, int group)
+{
+ int relevance, visits;
+
+ switch (group)
+ {
+ case HISTORY_GROUP:
+ visits = ephy_node_get_property_int
+ (node, EPHY_NODE_PAGE_PROP_VISITS);
+ relevance = visits;
+ break;
+ case BOOKMARKS_GROUP:
+ relevance = 2000;
+ break;
+ default:
+ relevance = 0;
+ }
+
+ g_value_set_int (value, relevance);
+}
+
+static EphyNode *
+get_node_root (EphyCompletionModel *model, EphyNode *node)
+{
+ if (ephy_node_has_child (model->priv->bookmarks, node))
+ {
+ return model->priv->bookmarks;
+ }
+ else
+ {
+ return model->priv->history;
+ }
+}
+
+static int
+get_node_group (EphyCompletionModel *model, EphyNode *node)
+{
+ if (ephy_node_has_child (model->priv->bookmarks, node))
+ {
+ return BOOKMARKS_GROUP;
+ }
+ else
+ {
+ return HISTORY_GROUP;
+ }
+}
+
+static EphyNode *
+get_index_root (EphyCompletionModel *model, int *index)
+{
+ int children;
+
+ children = ephy_node_get_n_children (model->priv->history);
+
+ if (*index >= children)
+ {
+ *index = *index - children;
+ return model->priv->bookmarks;
+ }
+ else
+ {
+ return model->priv->history;
+ }
+}
+
+static void
+ephy_completion_model_get_value (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ int column,
+ GValue *value)
+{
+ int group;
+ EphyCompletionModel *model = EPHY_COMPLETION_MODEL (tree_model);
+ EphyNode *node;
+
+ g_return_if_fail (EPHY_IS_COMPLETION_MODEL (tree_model));
+ g_return_if_fail (iter != NULL);
+ g_return_if_fail (iter->stamp == model->priv->stamp);
+
+ node = iter->user_data;
+ group = get_node_group (model, node);
+
+ switch (column)
+ {
+ case EPHY_COMPLETION_TEXT_COL:
+ g_value_init (value, G_TYPE_STRING);
+ init_text_col (value, node, group);
+ break;
+ case EPHY_COMPLETION_ACTION_COL:
+ g_value_init (value, G_TYPE_STRING);
+ init_action_col (value, node, group);
+ break;
+ case EPHY_COMPLETION_KEYWORDS_COL:
+ g_value_init (value, G_TYPE_STRING);
+ init_keywords_col (value, node, group);
+ break;
+ case EPHY_COMPLETION_RELEVANCE_COL:
+ g_value_init (value, G_TYPE_INT);
+ init_relevance_col (value, node, group);
+ break;
+ }
+}
+
+static guint
+ephy_completion_model_get_flags (GtkTreeModel *tree_model)
+{
+ return 0;
+}
+
+static gboolean
+ephy_completion_model_get_iter (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreePath *path)
+{
+ EphyCompletionModel *model = EPHY_COMPLETION_MODEL (tree_model);
+ EphyNode *root;
+ int i;
+
+ g_return_val_if_fail (EPHY_IS_COMPLETION_MODEL (model), FALSE);
+ g_return_val_if_fail (gtk_tree_path_get_depth (path) > 0, FALSE);
+
+ i = gtk_tree_path_get_indices (path)[0];
+
+ iter->stamp = model->priv->stamp;
+
+ root = get_index_root (model, &i);
+ iter->user_data = ephy_node_get_nth_child (root, i);
+
+ if (iter->user_data == NULL)
+ {
+ iter->stamp = 0;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static GtkTreePath *
+ephy_completion_model_get_path (GtkTreeModel *tree_model,
+ GtkTreeIter *iter)
+{
+ EphyCompletionModel *model = EPHY_COMPLETION_MODEL (tree_model);
+ EphyNode *node;
+
+ g_return_val_if_fail (EPHY_IS_COMPLETION_MODEL (tree_model), NULL);
+ g_return_val_if_fail (iter != NULL, NULL);
+ g_return_val_if_fail (iter->user_data != NULL, NULL);
+ g_return_val_if_fail (iter->stamp == model->priv->stamp, NULL);
+
+ node = iter->user_data;
+
+ if (node == model->priv->history)
+ return gtk_tree_path_new ();
+
+ return get_path_real (model, node);
+}
+
+static gboolean
+ephy_completion_model_iter_next (GtkTreeModel *tree_model,
+ GtkTreeIter *iter)
+{
+ EphyCompletionModel *model = EPHY_COMPLETION_MODEL (tree_model);
+ EphyNode *node, *next, *root;
+
+ g_return_val_if_fail (iter != NULL, FALSE);
+ g_return_val_if_fail (iter->user_data != NULL, FALSE);
+ g_return_val_if_fail (iter->stamp == model->priv->stamp, FALSE);
+
+ node = iter->user_data;
+
+ if (node == model->priv->history)
+ return FALSE;
+
+ root = get_node_root (model, node);
+ next = ephy_node_get_next_child (root, node);
+ if (next == NULL && root == model->priv->history)
+ {
+ next = ephy_node_get_nth_child (model->priv->bookmarks, 0);
+ }
+
+ iter->user_data = next;
+
+ return (iter->user_data != NULL);
+}
+
+static gboolean
+ephy_completion_model_iter_children (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreeIter *parent)
+{
+ EphyCompletionModel *model = EPHY_COMPLETION_MODEL (tree_model);
+
+ if (parent != NULL)
+ return FALSE;
+
+ iter->stamp = model->priv->stamp;
+ iter->user_data = model->priv->history;
+
+ return TRUE;
+}
+
+static gboolean
+ephy_completion_model_iter_has_child (GtkTreeModel *tree_model,
+ GtkTreeIter *iter)
+{
+ return FALSE;
+}
+
+static int
+ephy_completion_model_iter_n_children (GtkTreeModel *tree_model,
+ GtkTreeIter *iter)
+{
+ EphyCompletionModel *model = EPHY_COMPLETION_MODEL (tree_model);
+
+ g_return_val_if_fail (EPHY_IS_COMPLETION_MODEL (tree_model), -1);
+
+ if (iter == NULL)
+ {
+ return ephy_node_get_n_children (model->priv->history) +
+ ephy_node_get_n_children (model->priv->bookmarks);
+ }
+
+ g_return_val_if_fail (model->priv->stamp == iter->stamp, -1);
+
+ return 0;
+}
+
+static gboolean
+ephy_completion_model_iter_nth_child (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreeIter *parent,
+ int n)
+{
+ EphyCompletionModel *model = EPHY_COMPLETION_MODEL (tree_model);
+ EphyNode *node, *root;
+
+ g_return_val_if_fail (EPHY_IS_COMPLETION_MODEL (tree_model), FALSE);
+
+ if (parent != NULL)
+ return FALSE;
+
+ root = get_index_root (model, &n);
+ node = ephy_node_get_nth_child (root, n);
+
+ if (node != NULL)
+ {
+ iter->stamp = model->priv->stamp;
+ iter->user_data = node;
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+static gboolean
+ephy_completion_model_iter_parent (GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ GtkTreeIter *child)
+{
+ return FALSE;
+}
+
+static void
+ephy_completion_model_tree_model_init (GtkTreeModelIface *iface)
+{
+ iface->get_flags = ephy_completion_model_get_flags;
+ iface->get_iter = ephy_completion_model_get_iter;
+ iface->get_path = ephy_completion_model_get_path;
+ iface->iter_next = ephy_completion_model_iter_next;
+ iface->iter_children = ephy_completion_model_iter_children;
+ iface->iter_has_child = ephy_completion_model_iter_has_child;
+ iface->iter_n_children = ephy_completion_model_iter_n_children;
+ iface->iter_nth_child = ephy_completion_model_iter_nth_child;
+ iface->iter_parent = ephy_completion_model_iter_parent;
+ iface->get_n_columns = ephy_completion_model_get_n_columns;
+ iface->get_column_type = ephy_completion_model_get_column_type;
+ iface->get_value = ephy_completion_model_get_value;
+}
diff --git a/src/ephy-completion-model.h b/src/ephy-completion-model.h
new file mode 100644
index 000000000..ee30f595c
--- /dev/null
+++ b/src/ephy-completion-model.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2003 Marco Pesenti Gritti <marco@gnome.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef EPHY_COMPLETION_MODEL_H
+#define EPHY_COMPLETION_MODEL_H
+
+#include <gtk/gtktreemodel.h>
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_COMPLETION_MODEL (ephy_completion_model_get_type ())
+#define EPHY_COMPLETION_MODEL(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EPHY_TYPE_COMPLETION_MODEL, EphyCompletionModel))
+#define EPHY_COMPLETION_MODEL_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), EPHY_TYPE_COMPLETION_MODEL, EphyCompletionModelClass))
+#define EPHY_IS_COMPLETION_MODEL(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EPHY_TYPE_COMPLETION_MODEL))
+#define EPHY_IS_COMPLETION_MODEL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EPHY_TYPE_COMPLETION_MODEL))
+#define EPHY_COMPLETION_MODEL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EPHY_TYPE_COMPLETION_MODEL, EphyCompletionModelClass))
+
+typedef struct EphyCompletionModelPrivate EphyCompletionModelPrivate;
+
+enum
+{
+ EPHY_COMPLETION_TEXT_COL,
+ EPHY_COMPLETION_ACTION_COL,
+ EPHY_COMPLETION_KEYWORDS_COL,
+ EPHY_COMPLETION_RELEVANCE_COL,
+ N_COL
+} EphyCompletionColumn;
+
+typedef struct
+{
+ GObject parent;
+
+ EphyCompletionModelPrivate *priv;
+} EphyCompletionModel;
+
+typedef struct
+{
+ GObjectClass parent;
+} EphyCompletionModelClass;
+
+GType ephy_completion_model_get_type (void);
+
+EphyCompletionModel *ephy_completion_model_new (void);
+
+G_END_DECLS
+
+#endif /* EPHY_COMPLETION_MODEL_H */
diff --git a/src/ephy-location-action.c b/src/ephy-location-action.c
index bd18275a7..0d90e8e24 100644
--- a/src/ephy-location-action.c
+++ b/src/ephy-location-action.c
@@ -22,13 +22,20 @@
#include "ephy-location-action.h"
#include "ephy-location-entry.h"
#include "ephy-shell.h"
+#include "ephy-completion-model.h"
#include "ephy-debug.h"
+#include <gtk/gtkentry.h>
+#include <gtk/gtkentrycompletion.h>
+
#define EPHY_LOCATION_ACTION_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_LOCATION_ACTION, EphyLocationActionPrivate))
struct _EphyLocationActionPrivate
{
+ GList *actions;
char *address;
+ EphyNode *smart_bmks;
+ EphyBookmarks *bookmarks;
};
static void ephy_location_action_init (EphyLocationAction *action);
@@ -84,32 +91,48 @@ ephy_location_action_get_type (void)
}
static void
-location_url_activate_cb (EphyLocationEntry *entry,
- const char *content,
- const char *target,
- EphyLocationAction *action)
+action_activated_cb (GtkEntryCompletion *completion,
+ gint index,
+ EphyLocationAction *action)
{
- EphyBookmarks *bookmarks;
+ GtkWidget *entry;
+ char *content;
- LOG ("Location url activated, content %s target %s", content, target)
-
- bookmarks = ephy_shell_get_bookmarks (ephy_shell);
-
- if (!content)
- {
- LOG ("Go to %s", target);
- g_signal_emit (action, signals[GO_LOCATION], 0, target);
- }
- else
+ entry = gtk_entry_completion_get_entry (completion);
+ content = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
+ if (content)
{
+ EphyNode *node;
+ const char *smart_url;
char *url;
+ node = (EphyNode *)g_list_nth_data (action->priv->actions, index);
+ smart_url = ephy_node_get_property_string
+ (node, EPHY_NODE_BMK_PROP_LOCATION);
+ g_return_if_fail (smart_url != NULL);
+
url = ephy_bookmarks_solve_smart_url
- (bookmarks, target, content);
+ (action->priv->bookmarks, smart_url, content);
g_return_if_fail (url != NULL);
- LOG ("Go to %s", url);
+
g_signal_emit (action, signals[GO_LOCATION], 0, url);
+
g_free (url);
+ g_free (content);
+ }
+}
+
+static void
+location_url_activate_cb (EphyLocationEntry *entry,
+ EphyLocationAction *action)
+{
+ char *content;
+
+ content = gtk_editable_get_chars (GTK_EDITABLE(entry), 0, -1);
+ if (content)
+ {
+ g_signal_emit (action, signals[GO_LOCATION], 0, content);
+ g_free (content);
}
}
@@ -142,23 +165,81 @@ sync_address (GtkAction *act, GParamSpec *pspec, GtkWidget *proxy)
}
static void
+remove_completion_actions (GtkAction *action, GtkWidget *proxy)
+{
+ GtkWidget *entry;
+ GtkEntryCompletion *completion;
+ EphyLocationAction *la = EPHY_LOCATION_ACTION (action);
+ GList *l;
+
+ entry = ephy_location_entry_get_entry (EPHY_LOCATION_ENTRY (proxy));
+ completion = gtk_entry_get_completion (GTK_ENTRY (entry));
+
+ for (l = la->priv->actions; l != NULL; l = l->next)
+ {
+ int index;
+
+ index = g_list_position (la->priv->actions, l);
+ gtk_entry_completion_delete_action (completion, index);
+ }
+
+ g_signal_handlers_disconnect_by_func
+ (completion, G_CALLBACK (action_activated_cb), la);
+}
+
+static void
+add_completion_actions (GtkAction *action, GtkWidget *proxy)
+{
+ GtkWidget *entry;
+ GtkEntryCompletion *completion;
+ EphyLocationAction *la = EPHY_LOCATION_ACTION (action);
+ GList *l;
+
+ entry = ephy_location_entry_get_entry (EPHY_LOCATION_ENTRY (proxy));
+ completion = gtk_entry_get_completion (GTK_ENTRY (entry));
+
+ for (l = la->priv->actions; l != NULL; l = l->next)
+ {
+ EphyNode *bmk = l->data;
+ const char *title;
+ int index;
+
+ index = g_list_position (la->priv->actions, l);
+ title = ephy_node_get_property_string
+ (bmk, EPHY_NODE_BMK_PROP_TITLE);
+ gtk_entry_completion_insert_action_text (completion, index, (char*)title);
+ }
+
+ g_signal_connect (completion, "action_activated",
+ G_CALLBACK (action_activated_cb), la);
+}
+
+static void
connect_proxy (GtkAction *action, GtkWidget *proxy)
{
LOG ("Connect proxy")
if (EPHY_IS_LOCATION_ENTRY (proxy))
{
- EphyAutocompletion *ac;
+ EphyCompletionModel *model;
+ GtkWidget *entry;
- ac = EPHY_AUTOCOMPLETION (ephy_shell_get_autocompletion (ephy_shell));
+ model = ephy_completion_model_new ();
+ ephy_location_entry_set_completion (EPHY_LOCATION_ENTRY (proxy),
+ GTK_TREE_MODEL (model),
+ EPHY_COMPLETION_TEXT_COL,
+ EPHY_COMPLETION_ACTION_COL,
+ EPHY_COMPLETION_KEYWORDS_COL,
+ EPHY_COMPLETION_RELEVANCE_COL);
- ephy_location_entry_set_autocompletion (EPHY_LOCATION_ENTRY (proxy), ac);
+ add_completion_actions (action, proxy);
sync_address (action, NULL, proxy);
g_signal_connect_object (action, "notify::address",
G_CALLBACK (sync_address), proxy, 0);
- g_signal_connect_object (proxy, "activated",
+ entry = ephy_location_entry_get_entry (EPHY_LOCATION_ENTRY (proxy));
+ g_signal_connect_object (entry, "activate",
G_CALLBACK (location_url_activate_cb),
action, 0);
g_signal_connect_object (proxy, "user_changed",
@@ -274,11 +355,97 @@ ephy_location_action_class_init (EphyLocationActionClass *class)
}
static void
+init_actions_list (EphyLocationAction *action)
+{
+ GPtrArray *children;
+ int i;
+
+ children = ephy_node_get_children (action->priv->smart_bmks);
+ for (i = 0; i < children->len; i++)
+ {
+ EphyNode *kid;
+
+ kid = g_ptr_array_index (children, i);
+
+ action->priv->actions = g_list_append
+ (action->priv->actions, kid);
+ }
+}
+
+static void
+update_actions_list (EphyLocationAction *la)
+{
+ GSList *l;
+ GtkAction *action = GTK_ACTION (la);
+
+ l = gtk_action_get_proxies (action);
+ for (; l != NULL; l = l->next)
+ {
+ remove_completion_actions (action, GTK_WIDGET (l->data));
+ }
+
+ g_list_free (la->priv->actions);
+ la->priv->actions = NULL;
+ init_actions_list (la);
+
+ l = gtk_action_get_proxies (action);
+ for (; l != NULL; l = l->next)
+ {
+ add_completion_actions (action, l->data);
+ }
+}
+
+static void
+actions_child_removed_cb (EphyNode *node,
+ EphyNode *child,
+ guint old_index,
+ EphyLocationAction *action)
+{
+ update_actions_list (action);
+}
+
+static void
+actions_child_added_cb (EphyNode *node,
+ EphyNode *child,
+ EphyLocationAction *action)
+{
+ update_actions_list (action);
+}
+
+static void
+actions_child_changed_cb (EphyNode *node,
+ EphyNode *child,
+ EphyLocationAction *action)
+{
+ update_actions_list (action);
+}
+
+static void
ephy_location_action_init (EphyLocationAction *action)
{
action->priv = EPHY_LOCATION_ACTION_GET_PRIVATE (action);
action->priv->address = g_strdup ("");
+ action->priv->actions = NULL;
+
+ action->priv->bookmarks = ephy_shell_get_bookmarks (ephy_shell);
+ action->priv->smart_bmks = ephy_bookmarks_get_smart_bookmarks
+ (action->priv->bookmarks);
+
+ init_actions_list (action);
+
+ ephy_node_signal_connect_object (action->priv->smart_bmks,
+ EPHY_NODE_CHILD_ADDED,
+ (EphyNodeCallback)actions_child_added_cb,
+ G_OBJECT (action));
+ ephy_node_signal_connect_object (action->priv->smart_bmks,
+ EPHY_NODE_CHILD_REMOVED,
+ (EphyNodeCallback)actions_child_removed_cb,
+ G_OBJECT (action));
+ ephy_node_signal_connect_object (action->priv->smart_bmks,
+ EPHY_NODE_CHILD_CHANGED,
+ (EphyNodeCallback)actions_child_changed_cb,
+ G_OBJECT (action));
}
static void
@@ -286,6 +453,8 @@ ephy_location_action_finalize (GObject *object)
{
EphyLocationAction *action = EPHY_LOCATION_ACTION (object);
+ g_list_free (action->priv->actions);
+
g_free (action->priv->address);
}
diff --git a/src/ephy-shell.c b/src/ephy-shell.c
index fa4650b61..17adce496 100644
--- a/src/ephy-shell.c
+++ b/src/ephy-shell.c
@@ -41,7 +41,6 @@
#include "session.h"
#include "downloader-view.h"
#include "ephy-toolbars-model.h"
-#include "ephy-autocompletion.h"
#include "ephy-automation.h"
#include <string.h>
@@ -71,7 +70,6 @@ struct EphyShellPrivate
{
BonoboGenericFactory *automation_factory;
Session *session;
- EphyAutocompletion *autocompletion;
EphyBookmarks *bookmarks;
EphyToolbarsModel *toolbars_model;
EggToolbarsModel *fs_toolbars_model;
@@ -308,12 +306,6 @@ ephy_shell_finalize (GObject *object)
g_object_unref (G_OBJECT (gs->priv->session));
}
- LOG ("Unref autocompletion")
- if (gs->priv->autocompletion)
- {
- g_object_unref (gs->priv->autocompletion);
- }
-
LOG ("Unref Bookmarks Editor");
if (gs->priv->bme)
{
@@ -564,31 +556,6 @@ ephy_shell_get_session (EphyShell *gs)
return G_OBJECT (gs->priv->session);
}
-GObject *
-ephy_shell_get_autocompletion (EphyShell *gs)
-{
- EphyShellPrivate *p = gs->priv;
-
- if (!p->autocompletion)
- {
- static const gchar *prefixes[] = {
- EPHY_AUTOCOMPLETION_USUAL_WEB_PREFIXES,
- NULL
- };
-
- EphyHistory *gh = ephy_embed_shell_get_global_history (EPHY_EMBED_SHELL (gs));
- EphyBookmarks *bmk = ephy_shell_get_bookmarks (gs);
- p->autocompletion = ephy_autocompletion_new ();
- ephy_autocompletion_set_prefixes (p->autocompletion, prefixes);
-
- ephy_autocompletion_add_source (p->autocompletion,
- EPHY_AUTOCOMPLETION_SOURCE (gh));
- ephy_autocompletion_add_source (p->autocompletion,
- EPHY_AUTOCOMPLETION_SOURCE (bmk));
- }
- return G_OBJECT (p->autocompletion);
-}
-
EphyBookmarks *
ephy_shell_get_bookmarks (EphyShell *gs)
{
diff --git a/src/ephy-shell.h b/src/ephy-shell.h
index 6f0f1fd10..5c6d54899 100644
--- a/src/ephy-shell.h
+++ b/src/ephy-shell.h
@@ -93,8 +93,6 @@ EphyTab *ephy_shell_new_tab (EphyShell *shell,
GObject *ephy_shell_get_session (EphyShell *gs);
-GObject *ephy_shell_get_autocompletion (EphyShell *gs);
-
EphyBookmarks *ephy_shell_get_bookmarks (EphyShell *gs);
GObject *ephy_shell_get_toolbars_model (EphyShell *gs,