diff options
Diffstat (limited to 'src')
-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 |
10 files changed, 899 insertions, 145 deletions
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, |