From e62275191c520024b3b48dd2bdecbfb407e105e1 Mon Sep 17 00:00:00 2001 From: Cosimo Cecchi Date: Wed, 18 Jan 2012 14:08:09 -0500 Subject: Rename EphyLocationAction -> EphyLocationController Since it's not a GtkAction anymore. https://bugzilla.gnome.org/show_bug.cgi?id=668206 --- src/Makefile.am | 8 +- src/ephy-location-action.c | 914 ----------------------------------------- src/ephy-location-action.h | 67 --- src/ephy-location-controller.c | 914 +++++++++++++++++++++++++++++++++++++++++ src/ephy-location-controller.h | 67 +++ src/ephy-lockdown.c | 12 +- src/ephy-window.c | 35 +- src/ephy-window.h | 4 +- 8 files changed, 1010 insertions(+), 1011 deletions(-) delete mode 100644 src/ephy-location-action.c delete mode 100644 src/ephy-location-action.h create mode 100644 src/ephy-location-controller.c create mode 100644 src/ephy-location-controller.h diff --git a/src/Makefile.am b/src/Makefile.am index 24d47ae7d..a92de5cbc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -24,7 +24,7 @@ NOINST_H_FILES = \ ephy-home-action.h \ ephy-link-action.h \ ephy-lockdown.h \ - ephy-location-action.h \ + ephy-location-controller.h \ ephy-navigation-history-action.h \ ephy-page-menu-action.h \ ephy-password-info.h \ @@ -62,7 +62,7 @@ libephymain_la_SOURCES = \ ephy-history-window.c \ ephy-link.c \ ephy-link-action.c \ - ephy-location-action.c \ + ephy-location-controller.c \ ephy-lockdown.c \ ephy-navigation-history-action.c \ ephy-notebook.c \ @@ -237,7 +237,7 @@ EPHY_GIR_H_FILES = \ $(top_srcdir)/src/ephy-find-toolbar.h \ $(top_srcdir)/src/ephy-link-action.h \ $(top_srcdir)/src/ephy-link.h \ - $(top_srcdir)/src/ephy-location-action.h \ + $(top_srcdir)/src/ephy-location-controller.h \ $(top_srcdir)/src/ephy-notebook.h \ $(top_srcdir)/src/ephy-session.h \ $(top_srcdir)/src/ephy-shell.h \ @@ -267,7 +267,7 @@ EPHY_GIR_C_FILES = \ $(top_srcdir)/src/ephy-find-toolbar.c \ $(top_srcdir)/src/ephy-link-action.c \ $(top_srcdir)/src/ephy-link.c \ - $(top_srcdir)/src/ephy-location-action.c \ + $(top_srcdir)/src/ephy-location-controller.c \ $(top_srcdir)/src/ephy-notebook.c \ $(top_srcdir)/src/ephy-session.c \ $(top_srcdir)/src/ephy-shell.c \ diff --git a/src/ephy-location-action.c b/src/ephy-location-action.c deleted file mode 100644 index 7c319c335..000000000 --- a/src/ephy-location-action.c +++ /dev/null @@ -1,914 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright © 2003, 2004 Marco Pesenti Gritti - * Copyright © 2003, 2004 Christian Persch - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "config.h" -#include "ephy-location-action.h" - -#include "ephy-completion-model.h" -#include "ephy-debug.h" -#include "ephy-embed-container.h" -#include "ephy-embed-utils.h" -#include "ephy-link.h" -#include "ephy-location-entry.h" -#include "ephy-shell.h" - -#include -#include -#include - -/** - * SECTION:ephy-location-action - * @short_description: An #EphyLinkAction implementation - * - * #EphyLocationAction handles navigation together with #EphyLocationEntry - */ - -#define EPHY_LOCATION_ACTION_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_LOCATION_ACTION, EphyLocationActionPrivate)) - -struct _EphyLocationActionPrivate -{ - EphyWindow *window; - EphyLocationEntry *location_entry; - GtkWidget *proxy; - GList *actions; - char *address; - EphyNode *smart_bmks; - EphyBookmarks *bookmarks; - GdkPixbuf *icon; - char *lock_stock_id; - char *lock_tooltip; - guint editable : 1; - guint show_lock : 1; - gboolean sync_address_is_blocked; -}; - -static void ephy_location_action_init (EphyLocationAction *action); -static void ephy_location_action_class_init (EphyLocationActionClass *class); -static void ephy_location_action_finalize (GObject *object); -static void user_changed_cb (GtkWidget *proxy, - EphyLocationAction *action); -static void sync_address (EphyLocationAction *action, - GParamSpec *pspec, - GtkWidget *proxy); - -enum -{ - PROP_0, - PROP_ADDRESS, - PROP_EDITABLE, - PROP_ICON, - PROP_LOCK_STOCK, - PROP_LOCK_TOOLTIP, - PROP_SHOW_LOCK, - PROP_WINDOW, - PROP_LOCATION_ENTRY -}; - -enum -{ - LOCK_CLICKED, - LAST_SIGNAL -}; -static guint signals[LAST_SIGNAL]; - -G_DEFINE_TYPE_WITH_CODE (EphyLocationAction, ephy_location_action, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (EPHY_TYPE_LINK, - NULL)) - -static gboolean -match_func (GtkEntryCompletion *completion, - const char *key, - GtkTreeIter *iter, - gpointer data) -{ - char *item = NULL; - char *url = NULL; - char *keywords = NULL; - - gboolean ret = FALSE; - GtkTreeModel *model; - GSList *search_terms; - - model = gtk_entry_completion_get_model (completion); - - gtk_tree_model_get (model, iter, - EPHY_COMPLETION_TEXT_COL, &item, - EPHY_COMPLETION_URL_COL, &url, - EPHY_COMPLETION_KEYWORDS_COL, &keywords, - -1); - - if (!key) - return FALSE; - - search_terms = ephy_location_entry_get_search_terms (data); - - if (search_terms) - { - GSList *iter; - GRegex *current = NULL; - - ret = TRUE; - for (iter = search_terms; iter != NULL; iter = iter->next) - { - current = (GRegex*) iter->data; - if ((!g_regex_match (current, item, G_REGEX_MATCH_NOTEMPTY, NULL)) && - (!g_regex_match (current, url, G_REGEX_MATCH_NOTEMPTY, NULL)) && - (!g_regex_match (current, keywords, G_REGEX_MATCH_NOTEMPTY, NULL))) - { - ret = FALSE; - break; - } - } - } - - g_free (item); - g_free (url); - g_free (keywords); - - return ret; -} - -static void -action_activated_cb (GtkEntryCompletion *completion, - gint index, - EphyLocationAction *action) -{ - GtkWidget *entry; - char *content; - - 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_resolve_address - (action->priv->bookmarks, smart_url, content); - g_free (content); - if (url == NULL) return; - - ephy_link_open (EPHY_LINK (action), url, NULL, - ephy_link_flags_from_current_event ()); - - g_free (url); - } -} - -static void -entry_activate_cb (GtkEntry *entry, - EphyLocationAction *action) -{ - EphyBookmarks *bookmarks; - const char *content; - char *address; - EphyLocationActionPrivate *priv; - - priv = action->priv; - - if (priv->sync_address_is_blocked) - { - priv->sync_address_is_blocked = FALSE; - g_signal_handlers_unblock_by_func (action, G_CALLBACK (sync_address), entry); - } - - content = gtk_entry_get_text (entry); - if (content == NULL || content[0] == '\0') return; - - bookmarks = ephy_shell_get_bookmarks (ephy_shell_get_default ()); - - address = ephy_bookmarks_resolve_address (bookmarks, content, NULL); - g_return_if_fail (address != NULL); - - ephy_link_open (EPHY_LINK (action), g_strstrip (address), NULL, - ephy_link_flags_from_current_event ()); - - g_free (address); -} - -static void -user_changed_cb (GtkWidget *proxy, EphyLocationAction *action) -{ - const char *address; - - address = ephy_location_entry_get_location (EPHY_LOCATION_ENTRY (proxy)); - - LOG ("user_changed_cb, new address %s", address); - - g_signal_handlers_block_by_func (action, G_CALLBACK (sync_address), proxy); - ephy_location_action_set_address (action, address); - g_signal_handlers_unblock_by_func (action, G_CALLBACK (sync_address), proxy); -} - -static void -lock_clicked_cb (GtkWidget *proxy, - EphyLocationAction *action) -{ - g_signal_emit (action, signals[LOCK_CLICKED], 0); -} - -static void -sync_address (EphyLocationAction *action, - GParamSpec *pspec, - GtkWidget *widget) -{ - EphyLocationActionPrivate *priv = action->priv; - EphyLocationEntry *lentry = EPHY_LOCATION_ENTRY (widget); - - LOG ("sync_address %s", action->priv->address); - - g_signal_handlers_block_by_func (widget, G_CALLBACK (user_changed_cb), action); - ephy_location_entry_set_location (lentry, priv->address); - g_signal_handlers_unblock_by_func (widget, G_CALLBACK (user_changed_cb), action); -} - -static void -sync_editable (EphyLocationAction *action, - GParamSpec *pspec, - GtkWidget *widget) -{ - EphyLocationEntry *lentry = EPHY_LOCATION_ENTRY (widget); - - gtk_editable_set_editable (GTK_EDITABLE (lentry), action->priv->editable); -} - -static void -sync_icon (EphyLocationAction *action, - GParamSpec *pspec, - GtkWidget *widget) -{ - EphyLocationActionPrivate *priv = action->priv; - EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (widget); - - ephy_location_entry_set_favicon (entry, priv->icon); -} - -static void -sync_lock_stock_id (EphyLocationAction *action, - GParamSpec *pspec, - GtkWidget *widget) -{ - EphyLocationActionPrivate *priv = action->priv; - EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (widget); - - ephy_location_entry_set_lock_stock (entry, priv->lock_stock_id); -} - -static void -sync_lock_tooltip (EphyLocationAction *action, - GParamSpec *pspec, - GtkWidget *widget) -{ - EphyLocationActionPrivate *priv = action->priv; - EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (widget); - - ephy_location_entry_set_lock_tooltip (entry, priv->lock_tooltip); -} - -static void -sync_show_lock (EphyLocationAction *action, - GParamSpec *pspec, - GtkWidget *widget) -{ - EphyLocationActionPrivate *priv = action->priv; - EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (widget); - - ephy_location_entry_set_show_lock (entry, priv->show_lock); -} - -static char * -get_location_cb (EphyLocationEntry *entry, - EphyLocationAction *action) -{ - EphyLocationActionPrivate *priv = action->priv; - EphyEmbed *embed; - - embed = ephy_embed_container_get_active_child - (EPHY_EMBED_CONTAINER (priv->window)); - - return g_strdup (ephy_web_view_get_address (ephy_embed_get_web_view (embed))); -} - -static char * -get_title_cb (EphyLocationEntry *entry, - EphyLocationAction *action) -{ - EphyEmbed *embed; - - embed = ephy_embed_container_get_active_child - (EPHY_EMBED_CONTAINER (action->priv->window)); - - return g_strdup (ephy_web_view_get_title (ephy_embed_get_web_view (embed))); -} - -static void -remove_completion_actions (EphyLocationAction *action, - EphyLocationEntry *lentry) -{ - GtkEntryCompletion *completion; - GList *l; - - completion = gtk_entry_get_completion (GTK_ENTRY (lentry)); - - for (l = action->priv->actions; l != NULL; l = l->next) - { - gtk_entry_completion_delete_action (completion, 0); - } - - g_signal_handlers_disconnect_by_func - (completion, G_CALLBACK (action_activated_cb), action); -} - -static void -add_completion_actions (EphyLocationAction *action, - EphyLocationEntry *lentry) -{ - GtkEntryCompletion *completion; - GList *l; - - completion = gtk_entry_get_completion (GTK_ENTRY (lentry)); - - for (l = action->priv->actions; l != NULL; l = l->next) - { - EphyNode *bmk = l->data; - const char *title; - int index; - - index = g_list_position (action->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), action); -} - -static gboolean -focus_in_event_cb (GtkWidget *entry, - GdkEventFocus *event, - EphyLocationAction *action) -{ - EphyLocationActionPrivate *priv = action->priv; - - if (!priv->sync_address_is_blocked) - { - priv->sync_address_is_blocked = TRUE; - g_signal_handlers_block_by_func (action, G_CALLBACK (sync_address), entry); - } - - return FALSE; -} - -static gboolean -focus_out_event_cb (GtkWidget *entry, - GdkEventFocus *event, - EphyLocationAction *action) -{ - EphyLocationActionPrivate *priv = action->priv; - - if (priv->sync_address_is_blocked) - { - priv->sync_address_is_blocked = FALSE; - g_signal_handlers_unblock_by_func (action, G_CALLBACK (sync_address), entry); - } - - return FALSE; -} - -static void -switch_page_cb (GtkNotebook *notebook, - GtkWidget *page, - guint page_num, - EphyLocationAction *action) -{ - EphyLocationActionPrivate *priv = action->priv; - - if (priv->sync_address_is_blocked == TRUE) - { - priv->sync_address_is_blocked = FALSE; - g_signal_handlers_unblock_by_func (action, G_CALLBACK (sync_address), priv->proxy); - } -} - -static void -ephy_location_action_constructed (GObject *object) -{ - EphyLocationAction *action = EPHY_LOCATION_ACTION (object); - EphyLocationActionPrivate *priv = action->priv; - EphyCompletionModel *model; - GtkWidget *notebook, *widget; - - G_OBJECT_CLASS (ephy_location_action_parent_class)->constructed (object); - - notebook = ephy_window_get_notebook (priv->window); - widget = GTK_WIDGET (priv->location_entry); - - g_signal_connect (notebook, "switch-page", - G_CALLBACK (switch_page_cb), action); - - model = ephy_completion_model_new (); - ephy_location_entry_set_completion (priv->location_entry, - GTK_TREE_MODEL (model), - EPHY_COMPLETION_TEXT_COL, - EPHY_COMPLETION_ACTION_COL, - EPHY_COMPLETION_KEYWORDS_COL, - EPHY_COMPLETION_RELEVANCE_COL, - EPHY_COMPLETION_URL_COL, - EPHY_COMPLETION_EXTRA_COL, - EPHY_COMPLETION_FAVICON_COL); - g_object_unref (model); - - ephy_location_entry_set_match_func (priv->location_entry, - match_func, - priv->location_entry, - NULL); - - add_completion_actions (action, priv->location_entry); - - sync_address (action, NULL, widget); - g_signal_connect_object (action, "notify::address", - G_CALLBACK (sync_address), widget, 0); - sync_editable (action, NULL, widget); - g_signal_connect_object (action, "notify::editable", - G_CALLBACK (sync_editable), widget, 0); - sync_icon (action, NULL, widget); - g_signal_connect_object (action, "notify::icon", - G_CALLBACK (sync_icon), widget, 0); - sync_lock_stock_id (action, NULL, widget); - g_signal_connect_object (action, "notify::lock-stock-id", - G_CALLBACK (sync_lock_stock_id), widget, 0); - sync_lock_tooltip (action, NULL, widget); - g_signal_connect_object (action, "notify::lock-tooltip", - G_CALLBACK (sync_lock_tooltip), widget, 0); - sync_show_lock (action, NULL, widget); - g_signal_connect_object (action, "notify::show-lock", - G_CALLBACK (sync_show_lock), widget, 0); - - g_signal_connect_object (widget, "activate", - G_CALLBACK (entry_activate_cb), - action, 0); - g_signal_connect_object (widget, "user-changed", - G_CALLBACK (user_changed_cb), action, 0); - g_signal_connect_object (widget, "lock-clicked", - G_CALLBACK (lock_clicked_cb), action, 0); - g_signal_connect_object (widget, "get-location", - G_CALLBACK (get_location_cb), action, 0); - g_signal_connect_object (widget, "get-title", - G_CALLBACK (get_title_cb), action, 0); - g_signal_connect_object (widget, "focus-in-event", - G_CALLBACK (focus_in_event_cb), action, 0); - g_signal_connect_object (widget, "focus-out-event", - G_CALLBACK (focus_out_event_cb), action, 0); -} - -static void -ephy_location_action_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - EphyLocationAction *action = EPHY_LOCATION_ACTION (object); - EphyLocationActionPrivate *priv = action->priv; - - switch (prop_id) - { - case PROP_ADDRESS: - ephy_location_action_set_address (action, g_value_get_string (value)); - break; - case PROP_EDITABLE: - priv->editable = g_value_get_boolean (value); - break; - case PROP_ICON: - if (priv->icon != NULL) - { - g_object_unref (priv->icon); - } - priv->icon = GDK_PIXBUF (g_value_dup_object (value)); - break; - case PROP_LOCK_STOCK: - g_free (priv->lock_stock_id); - priv->lock_stock_id = g_value_dup_string (value); - break; - case PROP_LOCK_TOOLTIP: - g_free (priv->lock_tooltip); - priv->lock_tooltip = g_value_dup_string (value); - break; - case PROP_SHOW_LOCK: - priv->show_lock = g_value_get_boolean (value); - break; - case PROP_WINDOW: - priv->window = EPHY_WINDOW (g_value_get_object (value)); - break; - case PROP_LOCATION_ENTRY: - priv->location_entry = EPHY_LOCATION_ENTRY (g_value_get_object (value)); - break; - } -} - -static void -ephy_location_action_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - EphyLocationAction *action = EPHY_LOCATION_ACTION (object); - EphyLocationActionPrivate *priv = action->priv; - - switch (prop_id) - { - case PROP_ADDRESS: - g_value_set_string (value, ephy_location_action_get_address (action)); - break; - case PROP_EDITABLE: - g_value_set_boolean (value, priv->editable); - break; - case PROP_ICON: - g_value_set_object (value, priv->icon); - break; - case PROP_LOCK_STOCK: - g_value_set_string (value, priv->lock_stock_id); - break; - case PROP_LOCK_TOOLTIP: - g_value_set_string (value, priv->lock_tooltip); - break; - case PROP_SHOW_LOCK: - g_value_set_boolean (value, priv->show_lock); - break; - case PROP_WINDOW: - case PROP_LOCATION_ENTRY: - /* not readable */ - break; - } -} - -static void -ephy_location_action_dispose (GObject *object) -{ - EphyLocationAction *action = EPHY_LOCATION_ACTION (object); - EphyLocationActionPrivate *priv = action->priv; - GtkWidget *notebook; - - notebook = ephy_window_get_notebook (priv->window); - - if (notebook == NULL || - priv->location_entry == NULL) { - return; - } - - g_signal_handlers_disconnect_matched (action, G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, priv->location_entry); - g_signal_handlers_disconnect_matched (priv->location_entry, G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, action); - g_signal_handlers_disconnect_matched (notebook, G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, action); - priv->location_entry = NULL; - - G_OBJECT_CLASS (ephy_location_action_parent_class)->dispose (object); -} - -static void -ephy_location_action_class_init (EphyLocationActionClass *class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (class); - - object_class->finalize = ephy_location_action_finalize; - object_class->dispose = ephy_location_action_dispose; - object_class->constructed = ephy_location_action_constructed; - object_class->get_property = ephy_location_action_get_property; - object_class->set_property = ephy_location_action_set_property; - - /** - * EphyLocationAction::lock-clicked: - * @action: the object which received the signal. - * - * Emitted when the user clicks on the security icon of the internal - * #EphyLocationEntry. - */ - signals[LOCK_CLICKED] = g_signal_new ( - "lock-clicked", - EPHY_TYPE_LOCATION_ACTION, - G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (EphyLocationActionClass, lock_clicked), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, - 0); - - /** - * EphyLocationAction:address: - * - * The address of the current location. - */ - g_object_class_install_property (object_class, - PROP_ADDRESS, - g_param_spec_string ("address", - "Address", - "The address of the current location", - "", - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - /** - * EphyLocationAction:editable: - * - * Whether the location bar entry can be edited. - */ - g_object_class_install_property (object_class, - PROP_EDITABLE, - g_param_spec_boolean ("editable", - "Editable", - "Whether the location bar entry can be edited", - TRUE, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - /** - * EphyLocationAction:icon: - * - * The icon corresponding to the current location. - */ - g_object_class_install_property (object_class, - PROP_ICON, - g_param_spec_object ("icon", - "Icon", - "The icon corresponding to the current location", - GDK_TYPE_PIXBUF, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - /** - * EphyLocationAction:lock-stock-id: - * - * Stock id of the security icon. - */ - g_object_class_install_property (object_class, - PROP_LOCK_STOCK, - g_param_spec_string ("lock-stock-id", - "Lock Stock ID", - "Stock id of the security icon", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - /** - * EphyLocationAction:lock-tooltip: - * - * Tooltip for the security icon. - */ - g_object_class_install_property (object_class, - PROP_LOCK_TOOLTIP, - g_param_spec_string ("lock-tooltip", - "Lock Tooltip", - "Tooltip for the security icon", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - /** - * EphyLocationAction:show-lock: - * - * If we should show the security icon. - */ - g_object_class_install_property (object_class, - PROP_SHOW_LOCK, - g_param_spec_boolean ("show-lock", - "Show Lock", - "If we should show the security icon", - FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); - - /** - * EphyLocationAction:window: - * - * The parent window. - */ - g_object_class_install_property (object_class, - PROP_WINDOW, - g_param_spec_object ("window", - "Window", - "The parent window", - G_TYPE_OBJECT, - G_PARAM_WRITABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | - G_PARAM_CONSTRUCT_ONLY)); - - /** - * EphyLocationAction:location-entry: - * - * The controlled location entry. - */ - g_object_class_install_property (object_class, - PROP_LOCATION_ENTRY, - g_param_spec_object ("location-entry", - "Location entry", - "The controlled location entry", - G_TYPE_OBJECT, - G_PARAM_WRITABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | - G_PARAM_CONSTRUCT_ONLY)); - - g_type_class_add_private (object_class, sizeof (EphyLocationActionPrivate)); -} - -static int -compare_actions (gconstpointer a, - gconstpointer b) -{ - EphyNode *node_a = (EphyNode *)a; - EphyNode *node_b = (EphyNode *)b; - const char *title1, *title2; - int retval; - - title1 = ephy_node_get_property_string (node_a, EPHY_NODE_BMK_PROP_TITLE); - title2 = ephy_node_get_property_string (node_b, EPHY_NODE_BMK_PROP_TITLE); - - if (title1 == NULL) - { - retval = -1; - } - else if (title2 == NULL) - { - retval = 1; - } - else - { - char *str_a, *str_b; - - str_a = g_utf8_casefold (title1, -1); - str_b = g_utf8_casefold (title2, -1); - retval = g_utf8_collate (str_a, str_b); - g_free (str_a); - g_free (str_b); - } - - return retval; -} - -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_prepend - (action->priv->actions, kid); - } - - action->priv->actions = - g_list_sort (action->priv->actions, (GCompareFunc) compare_actions); -} - -static void -update_actions_list (EphyLocationAction *la) -{ - EphyLocationActionPrivate *priv = la->priv; - - remove_completion_actions (la, priv->location_entry); - - g_list_free (la->priv->actions); - la->priv->actions = NULL; - init_actions_list (la); - - add_completion_actions (la, priv->location_entry); -} - -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, - guint property_id, - EphyLocationAction *action) -{ - update_actions_list (action); -} - -static void -ephy_location_action_init (EphyLocationAction *action) -{ - EphyLocationActionPrivate *priv; - - priv = action->priv = EPHY_LOCATION_ACTION_GET_PRIVATE (action); - - priv->address = g_strdup (""); - priv->editable = TRUE; - priv->bookmarks = ephy_shell_get_bookmarks (ephy_shell); - priv->smart_bmks = ephy_bookmarks_get_smart_bookmarks - (action->priv->bookmarks); - priv->sync_address_is_blocked = FALSE; - - init_actions_list (action); - - ephy_node_signal_connect_object (priv->smart_bmks, - EPHY_NODE_CHILD_ADDED, - (EphyNodeCallback)actions_child_added_cb, - G_OBJECT (action)); - ephy_node_signal_connect_object (priv->smart_bmks, - EPHY_NODE_CHILD_REMOVED, - (EphyNodeCallback)actions_child_removed_cb, - G_OBJECT (action)); - ephy_node_signal_connect_object (priv->smart_bmks, - EPHY_NODE_CHILD_CHANGED, - (EphyNodeCallback)actions_child_changed_cb, - G_OBJECT (action)); -} - -static void -ephy_location_action_finalize (GObject *object) -{ - EphyLocationAction *action = EPHY_LOCATION_ACTION (object); - EphyLocationActionPrivate *priv = action->priv; - - if (priv->icon != NULL) - { - g_object_unref (priv->icon); - } - - g_list_free (priv->actions); - g_free (priv->address); - g_free (priv->lock_stock_id); - g_free (priv->lock_tooltip); - - G_OBJECT_CLASS (ephy_location_action_parent_class)->finalize (object); -} - -/** - * ephy_location_action_get_address: - * @action: an #EphyLocationAction - * - * Retrieves the currently loaded address. - * - * Returns: the current address - **/ -const char * -ephy_location_action_get_address (EphyLocationAction *action) -{ - g_return_val_if_fail (EPHY_IS_LOCATION_ACTION (action), ""); - - return action->priv->address; -} - -/** - * ephy_location_action_set_address: - * @action: an #EphyLocationAction - * @address: new address - * - * Sets @address as the address of @action. - **/ -void -ephy_location_action_set_address (EphyLocationAction *action, - const char *address) -{ - EphyLocationActionPrivate *priv; - - g_return_if_fail (EPHY_IS_LOCATION_ACTION (action)); - - priv = action->priv; - - LOG ("set_address %s", address); - - g_free (priv->address); - priv->address = g_strdup (address); - - g_object_notify (G_OBJECT (action), "address"); -} diff --git a/src/ephy-location-action.h b/src/ephy-location-action.h deleted file mode 100644 index 4680ef879..000000000 --- a/src/ephy-location-action.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright © 2003 Marco Pesenti Gritti - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#if !defined (__EPHY_EPIPHANY_H_INSIDE__) && !defined (EPIPHANY_COMPILATION) -#error "Only can be included directly." -#endif - -#ifndef EPHY_LOCATION_ACTION_H -#define EPHY_LOCATION_ACTION_H - -#include - -G_BEGIN_DECLS - -#define EPHY_TYPE_LOCATION_ACTION (ephy_location_action_get_type ()) -#define EPHY_LOCATION_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EPHY_TYPE_LOCATION_ACTION, EphyLocationAction)) -#define EPHY_LOCATION_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EPHY_TYPE_LOCATION_ACTION, EphyLocationActionClass)) -#define EPHY_IS_LOCATION_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EPHY_TYPE_LOCATION_ACTION)) -#define EPHY_IS_LOCATION_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EPHY_TYPE_LOCATION_ACTION)) -#define EPHY_LOCATION_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EPHY_TYPE_LOCATION_ACTION, EphyLocationActionClass)) - -typedef struct _EphyLocationAction EphyLocationAction; -typedef struct _EphyLocationActionPrivate EphyLocationActionPrivate; -typedef struct _EphyLocationActionClass EphyLocationActionClass; - -struct _EphyLocationAction -{ - GObject parent; - - /*< private >*/ - EphyLocationActionPrivate *priv; -}; - -struct _EphyLocationActionClass -{ - GObjectClass parent_class; - - /* Signals */ - void (* lock_clicked) (EphyLocationAction *action); -}; - -GType ephy_location_action_get_type (void); - -const char *ephy_location_action_get_address (EphyLocationAction *action); - -void ephy_location_action_set_address (EphyLocationAction *action, - const char *address); - -G_END_DECLS - -#endif diff --git a/src/ephy-location-controller.c b/src/ephy-location-controller.c new file mode 100644 index 000000000..4c447ec56 --- /dev/null +++ b/src/ephy-location-controller.c @@ -0,0 +1,914 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright © 2003, 2004 Marco Pesenti Gritti + * Copyright © 2003, 2004 Christian Persch + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" +#include "ephy-location-controller.h" + +#include "ephy-completion-model.h" +#include "ephy-debug.h" +#include "ephy-embed-container.h" +#include "ephy-embed-utils.h" +#include "ephy-link.h" +#include "ephy-location-entry.h" +#include "ephy-shell.h" + +#include +#include +#include + +/** + * SECTION:ephy-location-controller + * @short_description: An #EphyLink implementation + * + * #EphyLocationController handles navigation together with #EphyLocationEntry + */ + +#define EPHY_LOCATION_CONTROLLER_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_LOCATION_CONTROLLER, EphyLocationControllerPrivate)) + +struct _EphyLocationControllerPrivate +{ + EphyWindow *window; + EphyLocationEntry *location_entry; + GtkWidget *proxy; + GList *actions; + char *address; + EphyNode *smart_bmks; + EphyBookmarks *bookmarks; + GdkPixbuf *icon; + char *lock_stock_id; + char *lock_tooltip; + guint editable : 1; + guint show_lock : 1; + gboolean sync_address_is_blocked; +}; + +static void ephy_location_controller_init (EphyLocationController *controller); +static void ephy_location_controller_class_init (EphyLocationControllerClass *class); +static void ephy_location_controller_finalize (GObject *object); +static void user_changed_cb (GtkWidget *proxy, + EphyLocationController *controller); +static void sync_address (EphyLocationController *controller, + GParamSpec *pspec, + GtkWidget *proxy); + +enum +{ + PROP_0, + PROP_ADDRESS, + PROP_EDITABLE, + PROP_ICON, + PROP_LOCK_STOCK, + PROP_LOCK_TOOLTIP, + PROP_SHOW_LOCK, + PROP_WINDOW, + PROP_LOCATION_ENTRY +}; + +enum +{ + LOCK_CLICKED, + LAST_SIGNAL +}; +static guint signals[LAST_SIGNAL]; + +G_DEFINE_TYPE_WITH_CODE (EphyLocationController, ephy_location_controller, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (EPHY_TYPE_LINK, + NULL)) + +static gboolean +match_func (GtkEntryCompletion *completion, + const char *key, + GtkTreeIter *iter, + gpointer data) +{ + char *item = NULL; + char *url = NULL; + char *keywords = NULL; + + gboolean ret = FALSE; + GtkTreeModel *model; + GSList *search_terms; + + model = gtk_entry_completion_get_model (completion); + + gtk_tree_model_get (model, iter, + EPHY_COMPLETION_TEXT_COL, &item, + EPHY_COMPLETION_URL_COL, &url, + EPHY_COMPLETION_KEYWORDS_COL, &keywords, + -1); + + if (!key) + return FALSE; + + search_terms = ephy_location_entry_get_search_terms (data); + + if (search_terms) + { + GSList *iter; + GRegex *current = NULL; + + ret = TRUE; + for (iter = search_terms; iter != NULL; iter = iter->next) + { + current = (GRegex*) iter->data; + if ((!g_regex_match (current, item, G_REGEX_MATCH_NOTEMPTY, NULL)) && + (!g_regex_match (current, url, G_REGEX_MATCH_NOTEMPTY, NULL)) && + (!g_regex_match (current, keywords, G_REGEX_MATCH_NOTEMPTY, NULL))) + { + ret = FALSE; + break; + } + } + } + + g_free (item); + g_free (url); + g_free (keywords); + + return ret; +} + +static void +action_activated_cb (GtkEntryCompletion *completion, + gint index, + EphyLocationController *controller) +{ + GtkWidget *entry; + char *content; + + 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 (controller->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_resolve_address + (controller->priv->bookmarks, smart_url, content); + g_free (content); + if (url == NULL) return; + + ephy_link_open (EPHY_LINK (controller), url, NULL, + ephy_link_flags_from_current_event ()); + + g_free (url); + } +} + +static void +entry_activate_cb (GtkEntry *entry, + EphyLocationController *controller) +{ + EphyBookmarks *bookmarks; + const char *content; + char *address; + EphyLocationControllerPrivate *priv; + + priv = controller->priv; + + if (priv->sync_address_is_blocked) + { + priv->sync_address_is_blocked = FALSE; + g_signal_handlers_unblock_by_func (controller, G_CALLBACK (sync_address), entry); + } + + content = gtk_entry_get_text (entry); + if (content == NULL || content[0] == '\0') return; + + bookmarks = ephy_shell_get_bookmarks (ephy_shell_get_default ()); + + address = ephy_bookmarks_resolve_address (bookmarks, content, NULL); + g_return_if_fail (address != NULL); + + ephy_link_open (EPHY_LINK (controller), g_strstrip (address), NULL, + ephy_link_flags_from_current_event ()); + + g_free (address); +} + +static void +user_changed_cb (GtkWidget *proxy, EphyLocationController *controller) +{ + const char *address; + + address = ephy_location_entry_get_location (EPHY_LOCATION_ENTRY (proxy)); + + LOG ("user_changed_cb, new address %s", address); + + g_signal_handlers_block_by_func (controller, G_CALLBACK (sync_address), proxy); + ephy_location_controller_set_address (controller, address); + g_signal_handlers_unblock_by_func (controller, G_CALLBACK (sync_address), proxy); +} + +static void +lock_clicked_cb (GtkWidget *proxy, + EphyLocationController *controller) +{ + g_signal_emit (controller, signals[LOCK_CLICKED], 0); +} + +static void +sync_address (EphyLocationController *controller, + GParamSpec *pspec, + GtkWidget *widget) +{ + EphyLocationControllerPrivate *priv = controller->priv; + EphyLocationEntry *lentry = EPHY_LOCATION_ENTRY (widget); + + LOG ("sync_address %s", controller->priv->address); + + g_signal_handlers_block_by_func (widget, G_CALLBACK (user_changed_cb), controller); + ephy_location_entry_set_location (lentry, priv->address); + g_signal_handlers_unblock_by_func (widget, G_CALLBACK (user_changed_cb), controller); +} + +static void +sync_editable (EphyLocationController *controller, + GParamSpec *pspec, + GtkWidget *widget) +{ + EphyLocationEntry *lentry = EPHY_LOCATION_ENTRY (widget); + + gtk_editable_set_editable (GTK_EDITABLE (lentry), controller->priv->editable); +} + +static void +sync_icon (EphyLocationController *controller, + GParamSpec *pspec, + GtkWidget *widget) +{ + EphyLocationControllerPrivate *priv = controller->priv; + EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (widget); + + ephy_location_entry_set_favicon (entry, priv->icon); +} + +static void +sync_lock_stock_id (EphyLocationController *controller, + GParamSpec *pspec, + GtkWidget *widget) +{ + EphyLocationControllerPrivate *priv = controller->priv; + EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (widget); + + ephy_location_entry_set_lock_stock (entry, priv->lock_stock_id); +} + +static void +sync_lock_tooltip (EphyLocationController *controller, + GParamSpec *pspec, + GtkWidget *widget) +{ + EphyLocationControllerPrivate *priv = controller->priv; + EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (widget); + + ephy_location_entry_set_lock_tooltip (entry, priv->lock_tooltip); +} + +static void +sync_show_lock (EphyLocationController *controller, + GParamSpec *pspec, + GtkWidget *widget) +{ + EphyLocationControllerPrivate *priv = controller->priv; + EphyLocationEntry *entry = EPHY_LOCATION_ENTRY (widget); + + ephy_location_entry_set_show_lock (entry, priv->show_lock); +} + +static char * +get_location_cb (EphyLocationEntry *entry, + EphyLocationController *controller) +{ + EphyLocationControllerPrivate *priv = controller->priv; + EphyEmbed *embed; + + embed = ephy_embed_container_get_active_child + (EPHY_EMBED_CONTAINER (priv->window)); + + return g_strdup (ephy_web_view_get_address (ephy_embed_get_web_view (embed))); +} + +static char * +get_title_cb (EphyLocationEntry *entry, + EphyLocationController *controller) +{ + EphyEmbed *embed; + + embed = ephy_embed_container_get_active_child + (EPHY_EMBED_CONTAINER (controller->priv->window)); + + return g_strdup (ephy_web_view_get_title (ephy_embed_get_web_view (embed))); +} + +static void +remove_completion_actions (EphyLocationController *controller, + EphyLocationEntry *lentry) +{ + GtkEntryCompletion *completion; + GList *l; + + completion = gtk_entry_get_completion (GTK_ENTRY (lentry)); + + for (l = controller->priv->actions; l != NULL; l = l->next) + { + gtk_entry_completion_delete_action (completion, 0); + } + + g_signal_handlers_disconnect_by_func + (completion, G_CALLBACK (action_activated_cb), controller); +} + +static void +add_completion_actions (EphyLocationController *controller, + EphyLocationEntry *lentry) +{ + GtkEntryCompletion *completion; + GList *l; + + completion = gtk_entry_get_completion (GTK_ENTRY (lentry)); + + for (l = controller->priv->actions; l != NULL; l = l->next) + { + EphyNode *bmk = l->data; + const char *title; + int index; + + index = g_list_position (controller->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), controller); +} + +static gboolean +focus_in_event_cb (GtkWidget *entry, + GdkEventFocus *event, + EphyLocationController *controller) +{ + EphyLocationControllerPrivate *priv = controller->priv; + + if (!priv->sync_address_is_blocked) + { + priv->sync_address_is_blocked = TRUE; + g_signal_handlers_block_by_func (controller, G_CALLBACK (sync_address), entry); + } + + return FALSE; +} + +static gboolean +focus_out_event_cb (GtkWidget *entry, + GdkEventFocus *event, + EphyLocationController *controller) +{ + EphyLocationControllerPrivate *priv = controller->priv; + + if (priv->sync_address_is_blocked) + { + priv->sync_address_is_blocked = FALSE; + g_signal_handlers_unblock_by_func (controller, G_CALLBACK (sync_address), entry); + } + + return FALSE; +} + +static void +switch_page_cb (GtkNotebook *notebook, + GtkWidget *page, + guint page_num, + EphyLocationController *controller) +{ + EphyLocationControllerPrivate *priv = controller->priv; + + if (priv->sync_address_is_blocked == TRUE) + { + priv->sync_address_is_blocked = FALSE; + g_signal_handlers_unblock_by_func (controller, G_CALLBACK (sync_address), priv->proxy); + } +} + +static void +ephy_location_controller_constructed (GObject *object) +{ + EphyLocationController *controller = EPHY_LOCATION_CONTROLLER (object); + EphyLocationControllerPrivate *priv = controller->priv; + EphyCompletionModel *model; + GtkWidget *notebook, *widget; + + G_OBJECT_CLASS (ephy_location_controller_parent_class)->constructed (object); + + notebook = ephy_window_get_notebook (priv->window); + widget = GTK_WIDGET (priv->location_entry); + + g_signal_connect (notebook, "switch-page", + G_CALLBACK (switch_page_cb), controller); + + model = ephy_completion_model_new (); + ephy_location_entry_set_completion (priv->location_entry, + GTK_TREE_MODEL (model), + EPHY_COMPLETION_TEXT_COL, + EPHY_COMPLETION_ACTION_COL, + EPHY_COMPLETION_KEYWORDS_COL, + EPHY_COMPLETION_RELEVANCE_COL, + EPHY_COMPLETION_URL_COL, + EPHY_COMPLETION_EXTRA_COL, + EPHY_COMPLETION_FAVICON_COL); + g_object_unref (model); + + ephy_location_entry_set_match_func (priv->location_entry, + match_func, + priv->location_entry, + NULL); + + add_completion_actions (controller, priv->location_entry); + + sync_address (controller, NULL, widget); + g_signal_connect_object (controller, "notify::address", + G_CALLBACK (sync_address), widget, 0); + sync_editable (controller, NULL, widget); + g_signal_connect_object (controller, "notify::editable", + G_CALLBACK (sync_editable), widget, 0); + sync_icon (controller, NULL, widget); + g_signal_connect_object (controller, "notify::icon", + G_CALLBACK (sync_icon), widget, 0); + sync_lock_stock_id (controller, NULL, widget); + g_signal_connect_object (controller, "notify::lock-stock-id", + G_CALLBACK (sync_lock_stock_id), widget, 0); + sync_lock_tooltip (controller, NULL, widget); + g_signal_connect_object (controller, "notify::lock-tooltip", + G_CALLBACK (sync_lock_tooltip), widget, 0); + sync_show_lock (controller, NULL, widget); + g_signal_connect_object (controller, "notify::show-lock", + G_CALLBACK (sync_show_lock), widget, 0); + + g_signal_connect_object (widget, "activate", + G_CALLBACK (entry_activate_cb), + controller, 0); + g_signal_connect_object (widget, "user-changed", + G_CALLBACK (user_changed_cb), controller, 0); + g_signal_connect_object (widget, "lock-clicked", + G_CALLBACK (lock_clicked_cb), controller, 0); + g_signal_connect_object (widget, "get-location", + G_CALLBACK (get_location_cb), controller, 0); + g_signal_connect_object (widget, "get-title", + G_CALLBACK (get_title_cb), controller, 0); + g_signal_connect_object (widget, "focus-in-event", + G_CALLBACK (focus_in_event_cb), controller, 0); + g_signal_connect_object (widget, "focus-out-event", + G_CALLBACK (focus_out_event_cb), controller, 0); +} + +static void +ephy_location_controller_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + EphyLocationController *controller = EPHY_LOCATION_CONTROLLER (object); + EphyLocationControllerPrivate *priv = controller->priv; + + switch (prop_id) + { + case PROP_ADDRESS: + ephy_location_controller_set_address (controller, g_value_get_string (value)); + break; + case PROP_EDITABLE: + priv->editable = g_value_get_boolean (value); + break; + case PROP_ICON: + if (priv->icon != NULL) + { + g_object_unref (priv->icon); + } + priv->icon = GDK_PIXBUF (g_value_dup_object (value)); + break; + case PROP_LOCK_STOCK: + g_free (priv->lock_stock_id); + priv->lock_stock_id = g_value_dup_string (value); + break; + case PROP_LOCK_TOOLTIP: + g_free (priv->lock_tooltip); + priv->lock_tooltip = g_value_dup_string (value); + break; + case PROP_SHOW_LOCK: + priv->show_lock = g_value_get_boolean (value); + break; + case PROP_WINDOW: + priv->window = EPHY_WINDOW (g_value_get_object (value)); + break; + case PROP_LOCATION_ENTRY: + priv->location_entry = EPHY_LOCATION_ENTRY (g_value_get_object (value)); + break; + } +} + +static void +ephy_location_controller_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + EphyLocationController *controller = EPHY_LOCATION_CONTROLLER (object); + EphyLocationControllerPrivate *priv = controller->priv; + + switch (prop_id) + { + case PROP_ADDRESS: + g_value_set_string (value, ephy_location_controller_get_address (controller)); + break; + case PROP_EDITABLE: + g_value_set_boolean (value, priv->editable); + break; + case PROP_ICON: + g_value_set_object (value, priv->icon); + break; + case PROP_LOCK_STOCK: + g_value_set_string (value, priv->lock_stock_id); + break; + case PROP_LOCK_TOOLTIP: + g_value_set_string (value, priv->lock_tooltip); + break; + case PROP_SHOW_LOCK: + g_value_set_boolean (value, priv->show_lock); + break; + case PROP_WINDOW: + case PROP_LOCATION_ENTRY: + /* not readable */ + break; + } +} + +static void +ephy_location_controller_dispose (GObject *object) +{ + EphyLocationController *controller = EPHY_LOCATION_CONTROLLER (object); + EphyLocationControllerPrivate *priv = controller->priv; + GtkWidget *notebook; + + notebook = ephy_window_get_notebook (priv->window); + + if (notebook == NULL || + priv->location_entry == NULL) { + return; + } + + g_signal_handlers_disconnect_matched (controller, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, priv->location_entry); + g_signal_handlers_disconnect_matched (priv->location_entry, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, controller); + g_signal_handlers_disconnect_matched (notebook, G_SIGNAL_MATCH_DATA, + 0, 0, NULL, NULL, controller); + priv->location_entry = NULL; + + G_OBJECT_CLASS (ephy_location_controller_parent_class)->dispose (object); +} + +static void +ephy_location_controller_class_init (EphyLocationControllerClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + object_class->finalize = ephy_location_controller_finalize; + object_class->dispose = ephy_location_controller_dispose; + object_class->constructed = ephy_location_controller_constructed; + object_class->get_property = ephy_location_controller_get_property; + object_class->set_property = ephy_location_controller_set_property; + + /** + * EphyLocationController::lock-clicked: + * @controller: the object which received the signal. + * + * Emitted when the user clicks on the security icon of the internal + * #EphyLocationEntry. + */ + signals[LOCK_CLICKED] = g_signal_new ( + "lock-clicked", + EPHY_TYPE_LOCATION_CONTROLLER, + G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (EphyLocationControllerClass, lock_clicked), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); + + /** + * EphyLocationController:address: + * + * The address of the current location. + */ + g_object_class_install_property (object_class, + PROP_ADDRESS, + g_param_spec_string ("address", + "Address", + "The address of the current location", + "", + G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); + + /** + * EphyLocationController:editable: + * + * Whether the location bar entry can be edited. + */ + g_object_class_install_property (object_class, + PROP_EDITABLE, + g_param_spec_boolean ("editable", + "Editable", + "Whether the location bar entry can be edited", + TRUE, + G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); + + /** + * EphyLocationController:icon: + * + * The icon corresponding to the current location. + */ + g_object_class_install_property (object_class, + PROP_ICON, + g_param_spec_object ("icon", + "Icon", + "The icon corresponding to the current location", + GDK_TYPE_PIXBUF, + G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); + + /** + * EphyLocationController:lock-stock-id: + * + * Stock id of the security icon. + */ + g_object_class_install_property (object_class, + PROP_LOCK_STOCK, + g_param_spec_string ("lock-stock-id", + "Lock Stock ID", + "Stock id of the security icon", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); + + /** + * EphyLocationController:lock-tooltip: + * + * Tooltip for the security icon. + */ + g_object_class_install_property (object_class, + PROP_LOCK_TOOLTIP, + g_param_spec_string ("lock-tooltip", + "Lock Tooltip", + "Tooltip for the security icon", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); + + /** + * EphyLocationController:show-lock: + * + * If we should show the security icon. + */ + g_object_class_install_property (object_class, + PROP_SHOW_LOCK, + g_param_spec_boolean ("show-lock", + "Show Lock", + "If we should show the security icon", + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); + + /** + * EphyLocationController:window: + * + * The parent window. + */ + g_object_class_install_property (object_class, + PROP_WINDOW, + g_param_spec_object ("window", + "Window", + "The parent window", + G_TYPE_OBJECT, + G_PARAM_WRITABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | + G_PARAM_CONSTRUCT_ONLY)); + + /** + * EphyLocationController:location-entry: + * + * The controlled location entry. + */ + g_object_class_install_property (object_class, + PROP_LOCATION_ENTRY, + g_param_spec_object ("location-entry", + "Location entry", + "The controlled location entry", + G_TYPE_OBJECT, + G_PARAM_WRITABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | + G_PARAM_CONSTRUCT_ONLY)); + + g_type_class_add_private (object_class, sizeof (EphyLocationControllerPrivate)); +} + +static int +compare_actions (gconstpointer a, + gconstpointer b) +{ + EphyNode *node_a = (EphyNode *)a; + EphyNode *node_b = (EphyNode *)b; + const char *title1, *title2; + int retval; + + title1 = ephy_node_get_property_string (node_a, EPHY_NODE_BMK_PROP_TITLE); + title2 = ephy_node_get_property_string (node_b, EPHY_NODE_BMK_PROP_TITLE); + + if (title1 == NULL) + { + retval = -1; + } + else if (title2 == NULL) + { + retval = 1; + } + else + { + char *str_a, *str_b; + + str_a = g_utf8_casefold (title1, -1); + str_b = g_utf8_casefold (title2, -1); + retval = g_utf8_collate (str_a, str_b); + g_free (str_a); + g_free (str_b); + } + + return retval; +} + +static void +init_actions_list (EphyLocationController *controller) +{ + GPtrArray *children; + int i; + + children = ephy_node_get_children (controller->priv->smart_bmks); + for (i = 0; i < children->len; i++) + { + EphyNode *kid; + + kid = g_ptr_array_index (children, i); + + controller->priv->actions = g_list_prepend + (controller->priv->actions, kid); + } + + controller->priv->actions = + g_list_sort (controller->priv->actions, (GCompareFunc) compare_actions); +} + +static void +update_actions_list (EphyLocationController *la) +{ + EphyLocationControllerPrivate *priv = la->priv; + + remove_completion_actions (la, priv->location_entry); + + g_list_free (la->priv->actions); + la->priv->actions = NULL; + init_actions_list (la); + + add_completion_actions (la, priv->location_entry); +} + +static void +actions_child_removed_cb (EphyNode *node, + EphyNode *child, + guint old_index, + EphyLocationController *controller) +{ + update_actions_list (controller); +} + +static void +actions_child_added_cb (EphyNode *node, + EphyNode *child, + EphyLocationController *controller) +{ + update_actions_list (controller); +} + +static void +actions_child_changed_cb (EphyNode *node, + EphyNode *child, + guint property_id, + EphyLocationController *controller) +{ + update_actions_list (controller); +} + +static void +ephy_location_controller_init (EphyLocationController *controller) +{ + EphyLocationControllerPrivate *priv; + + priv = controller->priv = EPHY_LOCATION_CONTROLLER_GET_PRIVATE (controller); + + priv->address = g_strdup (""); + priv->editable = TRUE; + priv->bookmarks = ephy_shell_get_bookmarks (ephy_shell); + priv->smart_bmks = ephy_bookmarks_get_smart_bookmarks + (controller->priv->bookmarks); + priv->sync_address_is_blocked = FALSE; + + init_actions_list (controller); + + ephy_node_signal_connect_object (priv->smart_bmks, + EPHY_NODE_CHILD_ADDED, + (EphyNodeCallback)actions_child_added_cb, + G_OBJECT (controller)); + ephy_node_signal_connect_object (priv->smart_bmks, + EPHY_NODE_CHILD_REMOVED, + (EphyNodeCallback)actions_child_removed_cb, + G_OBJECT (controller)); + ephy_node_signal_connect_object (priv->smart_bmks, + EPHY_NODE_CHILD_CHANGED, + (EphyNodeCallback)actions_child_changed_cb, + G_OBJECT (controller)); +} + +static void +ephy_location_controller_finalize (GObject *object) +{ + EphyLocationController *controller = EPHY_LOCATION_CONTROLLER (object); + EphyLocationControllerPrivate *priv = controller->priv; + + if (priv->icon != NULL) + { + g_object_unref (priv->icon); + } + + g_list_free (priv->actions); + g_free (priv->address); + g_free (priv->lock_stock_id); + g_free (priv->lock_tooltip); + + G_OBJECT_CLASS (ephy_location_controller_parent_class)->finalize (object); +} + +/** + * ephy_location_controller_get_address: + * @controller: an #EphyLocationController + * + * Retrieves the currently loaded address. + * + * Returns: the current address + **/ +const char * +ephy_location_controller_get_address (EphyLocationController *controller) +{ + g_return_val_if_fail (EPHY_IS_LOCATION_CONTROLLER (controller), ""); + + return controller->priv->address; +} + +/** + * ephy_location_controller_set_address: + * @controller: an #EphyLocationController + * @address: new address + * + * Sets @address as the address of @controller. + **/ +void +ephy_location_controller_set_address (EphyLocationController *controller, + const char *address) +{ + EphyLocationControllerPrivate *priv; + + g_return_if_fail (EPHY_IS_LOCATION_CONTROLLER (controller)); + + priv = controller->priv; + + LOG ("set_address %s", address); + + g_free (priv->address); + priv->address = g_strdup (address); + + g_object_notify (G_OBJECT (controller), "address"); +} diff --git a/src/ephy-location-controller.h b/src/ephy-location-controller.h new file mode 100644 index 000000000..84c85dfdf --- /dev/null +++ b/src/ephy-location-controller.h @@ -0,0 +1,67 @@ +/* + * Copyright © 2003 Marco Pesenti Gritti + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#if !defined (__EPHY_EPIPHANY_H_INSIDE__) && !defined (EPIPHANY_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef EPHY_LOCATION_CONTROLLER_H +#define EPHY_LOCATION_CONTROLLER_H + +#include + +G_BEGIN_DECLS + +#define EPHY_TYPE_LOCATION_CONTROLLER (ephy_location_controller_get_type ()) +#define EPHY_LOCATION_CONTROLLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EPHY_TYPE_LOCATION_CONTROLLER, EphyLocationController)) +#define EPHY_LOCATION_CONTROLLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EPHY_TYPE_LOCATION_CONTROLLER, EphyLocationControllerClass)) +#define EPHY_IS_LOCATION_CONTROLLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EPHY_TYPE_LOCATION_CONTROLLER)) +#define EPHY_IS_LOCATION_CONTROLLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), EPHY_TYPE_LOCATION_CONTROLLER)) +#define EPHY_LOCATION_CONTROLLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), EPHY_TYPE_LOCATION_CONTROLLER, EphyLocationControllerClass)) + +typedef struct _EphyLocationController EphyLocationController; +typedef struct _EphyLocationControllerPrivate EphyLocationControllerPrivate; +typedef struct _EphyLocationControllerClass EphyLocationControllerClass; + +struct _EphyLocationController +{ + GObject parent; + + /*< private >*/ + EphyLocationControllerPrivate *priv; +}; + +struct _EphyLocationControllerClass +{ + GObjectClass parent_class; + + /* Signals */ + void (* lock_clicked) (EphyLocationController *controller); +}; + +GType ephy_location_controller_get_type (void); + +const char *ephy_location_controller_get_address (EphyLocationController *controller); + +void ephy_location_controller_set_address (EphyLocationController *controller, + const char *address); + +G_END_DECLS + +#endif diff --git a/src/ephy-lockdown.c b/src/ephy-lockdown.c index 4ffa81534..5a2dc982f 100644 --- a/src/ephy-lockdown.c +++ b/src/ephy-lockdown.c @@ -189,11 +189,11 @@ bind_settings_and_actions (GSettings *settings, } static void -bind_location_action (GSettings *settings, - EphyLocationAction *action) +bind_location_controller (GSettings *settings, + EphyLocationController *controller) { g_settings_bind (settings, EPHY_PREFS_LOCKDOWN_ARBITRARY_URL, - action, "editable", + controller, "editable", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_INVERT_BOOLEAN); } @@ -206,7 +206,7 @@ impl_attach_window (EphyExtension *extension, GtkActionGroup *action_group; GtkAction *action; GSettings *settings; - EphyLocationAction *location_action; + EphyLocationController *location_controller; g_signal_connect (EPHY_SETTINGS_LOCKDOWN, "changed::" EPHY_PREFS_LOCKDOWN_FULLSCREEN, @@ -244,8 +244,8 @@ impl_attach_window (EphyExtension *extension, action_group, special_toolbar_actions, G_N_ELEMENTS (special_toolbar_actions)); - location_action = ephy_window_get_location_action (window); - bind_location_action (EPHY_SETTINGS_LOCKDOWN, location_action); + location_controller = ephy_window_get_location_controller (window); + bind_location_controller (EPHY_SETTINGS_LOCKDOWN, location_controller); } static void diff --git a/src/ephy-window.c b/src/ephy-window.c index 0a897ae1a..a09b4b193 100644 --- a/src/ephy-window.c +++ b/src/ephy-window.c @@ -43,7 +43,6 @@ #include "ephy-gui.h" #include "ephy-home-action.h" #include "ephy-link.h" -#include "ephy-location-action.h" #include "ephy-location-entry.h" #include "ephy-navigation-history-action.h" #include "ephy-notebook.h" @@ -428,7 +427,7 @@ struct _EphyWindowPrivate guint idle_worker; GtkWidget *downloads_box; - EphyLocationAction *location_action; + EphyLocationController *location_controller; guint clear_progress_timeout_id; gulong set_focus_handler; @@ -1520,7 +1519,7 @@ _ephy_window_set_location (EphyWindow *window, if (priv->updating_address) return; priv->updating_address = TRUE; - ephy_location_action_set_address (priv->location_action, address); + ephy_location_controller_set_address (priv->location_controller, address); priv->updating_address = FALSE; } @@ -1586,7 +1585,7 @@ _ephy_window_action_set_favicon (EphyWindow *window, { EphyWindowPrivate *priv = window->priv; - g_object_set (priv->location_action, "icon", icon, NULL); + g_object_set (priv->location_controller, "icon", icon, NULL); } static void @@ -1707,7 +1706,7 @@ _ephy_window_set_security_state (EphyWindow *window, priv->show_lock = show_lock != FALSE; - g_object_set (priv->location_action, + g_object_set (priv->location_controller, "lock-stock-id", stock_id, "lock-tooltip", tooltip, "show-lock", priv->show_lock, @@ -3461,7 +3460,7 @@ allow_popups_notifier (GSettings *settings, } static void -sync_user_input_cb (EphyLocationAction *action, +sync_user_input_cb (EphyLocationController *action, GParamSpec *pspec, EphyWindow *window) { @@ -3476,7 +3475,7 @@ sync_user_input_cb (EphyLocationAction *action, embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (window)); g_assert (EPHY_IS_EMBED (embed)); - address = ephy_location_action_get_address (action); + address = ephy_location_controller_get_address (action); priv->updating_address = TRUE; ephy_web_view_set_typed_address (ephy_embed_get_web_view (embed), address); @@ -3591,14 +3590,14 @@ ephy_window_constructor (GType type, /* Setup the toolbar. */ priv->toolbar = setup_toolbar (window); - priv->location_action = - g_object_new (EPHY_TYPE_LOCATION_ACTION, + priv->location_controller = + g_object_new (EPHY_TYPE_LOCATION_CONTROLLER, "window", window, "location-entry", ephy_toolbar_get_location_entry (EPHY_TOOLBAR (priv->toolbar)), NULL); - g_signal_connect (priv->location_action, "notify::address", + g_signal_connect (priv->location_controller, "notify::address", G_CALLBACK (sync_user_input_cb), window); - g_signal_connect_swapped (priv->location_action, "open-link", + g_signal_connect_swapped (priv->location_controller, "open-link", G_CALLBACK (ephy_link_open), window); g_signal_connect_swapped (priv->notebook, "open-link", @@ -4150,7 +4149,7 @@ ephy_window_get_context_event (EphyWindow *window) * ephy_window_get_location: * @window: an #EphyWindow widget * - * Gets the current address according to @window's #EphyLocationAction. + * Gets the current address according to @window's #EphyLocationController. * * Returns: current @window address **/ @@ -4158,7 +4157,7 @@ const char * ephy_window_get_location (EphyWindow *window) { EphyWindowPrivate *priv = window->priv; - return ephy_location_action_get_address (priv->location_action); + return ephy_location_controller_get_address (priv->location_controller); } /** @@ -4166,7 +4165,7 @@ ephy_window_get_location (EphyWindow *window) * @window: an #EphyWindow widget * @address: new address * - * Sets the internal #EphyLocationAction address to @address. + * Sets the internal #EphyLocationController address to @address. **/ void ephy_window_set_location (EphyWindow *window, @@ -4177,7 +4176,7 @@ ephy_window_set_location (EphyWindow *window, if (priv->updating_address) return; priv->updating_address = TRUE; - ephy_location_action_set_address (priv->location_action, address); + ephy_location_controller_set_address (priv->location_controller, address); priv->updating_address = FALSE; } @@ -4198,10 +4197,10 @@ ephy_window_get_toolbar_action_group (EphyWindow *window) return window->priv->toolbar_action_group; } -EphyLocationAction * -ephy_window_get_location_action (EphyWindow *window) +EphyLocationController * +ephy_window_get_location_controller (EphyWindow *window) { g_return_val_if_fail (EPHY_IS_WINDOW (window), NULL); - return window->priv->location_action; + return window->priv->location_controller; } diff --git a/src/ephy-window.h b/src/ephy-window.h index d8251bf0e..94cc2e3d3 100644 --- a/src/ephy-window.h +++ b/src/ephy-window.h @@ -25,7 +25,7 @@ #define EPHY_WINDOW_H #include "ephy-embed.h" -#include "ephy-location-action.h" +#include "ephy-location-controller.h" #include #include @@ -87,7 +87,7 @@ void ephy_window_set_downloads_box_visibility (EphyWindow *window, gboolean show); GtkActionGroup *ephy_window_get_toolbar_action_group (EphyWindow *window); -EphyLocationAction *ephy_window_get_location_action (EphyWindow *window); +EphyLocationController *ephy_window_get_location_controller (EphyWindow *window); G_END_DECLS -- cgit v1.2.3