diff options
author | Marco Pesenti Gritti <marco@src.gnome.org> | 2003-10-12 01:41:26 +0800 |
---|---|---|
committer | Marco Pesenti Gritti <marco@src.gnome.org> | 2003-10-12 01:41:26 +0800 |
commit | 890b0f0278c284b3f72b17b2a320d7f443683d77 (patch) | |
tree | 838de9eb530807959804418a6d14f44eb8036e82 | |
parent | 0b5f13ef5a9f6a28812cfa959ad9f5b786312ad2 (diff) | |
download | gsoc2013-epiphany-890b0f0278c284b3f72b17b2a320d7f443683d77.tar gsoc2013-epiphany-890b0f0278c284b3f72b17b2a320d7f443683d77.tar.gz gsoc2013-epiphany-890b0f0278c284b3f72b17b2a320d7f443683d77.tar.bz2 gsoc2013-epiphany-890b0f0278c284b3f72b17b2a320d7f443683d77.tar.lz gsoc2013-epiphany-890b0f0278c284b3f72b17b2a320d7f443683d77.tar.xz gsoc2013-epiphany-890b0f0278c284b3f72b17b2a320d7f443683d77.tar.zst gsoc2013-epiphany-890b0f0278c284b3f72b17b2a320d7f443683d77.zip |
Merge completion branch
-rw-r--r-- | ChangeLog | 189 | ||||
-rw-r--r-- | embed/ephy-history.c | 77 | ||||
-rw-r--r-- | lib/Makefile.am | 6 | ||||
-rw-r--r-- | lib/ephy-autocompletion-source.c | 85 | ||||
-rw-r--r-- | lib/ephy-autocompletion-source.h | 80 | ||||
-rw-r--r-- | lib/ephy-autocompletion.c | 609 | ||||
-rw-r--r-- | lib/ephy-autocompletion.h | 106 | ||||
-rw-r--r-- | lib/ephy-node-common.h | 3 | ||||
-rw-r--r-- | lib/widgets/Makefile.am | 2 | ||||
-rw-r--r-- | lib/widgets/ephy-autocompletion-window.c | 839 | ||||
-rw-r--r-- | lib/widgets/ephy-autocompletion-window.h | 89 | ||||
-rw-r--r-- | lib/widgets/ephy-location-entry.c | 876 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/bookmarks/ephy-bookmark-action.c | 8 | ||||
-rw-r--r-- | src/bookmarks/ephy-bookmarks-export.c | 7 | ||||
-rw-r--r-- | src/bookmarks/ephy-bookmarks.c | 114 | ||||
-rw-r--r-- | src/bookmarks/ephy-bookmarks.h | 3 | ||||
-rw-r--r-- | src/ephy-completion-model.c | 601 | ||||
-rw-r--r-- | src/ephy-completion-model.h | 63 | ||||
-rw-r--r-- | src/ephy-location-action.c | 211 | ||||
-rw-r--r-- | src/ephy-shell.c | 33 | ||||
-rw-r--r-- | src/ephy-shell.h | 2 |
22 files changed, 1425 insertions, 2580 deletions
@@ -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, |