diff options
author | Claudio Saavedra <csaavedra@igalia.com> | 2012-04-04 21:36:59 +0800 |
---|---|---|
committer | Claudio Saavedra <csaavedra@igalia.com> | 2012-09-01 02:34:00 +0800 |
commit | 224d74346147e3810069dc33367a49f4b3a6091c (patch) | |
tree | df9db4878dc986b883e4954cb7da9a692af537da | |
parent | 8d260a1a0af94d01e5b90db70746a83bf5ea71de (diff) | |
download | gsoc2013-epiphany-224d74346147e3810069dc33367a49f4b3a6091c.tar.gz gsoc2013-epiphany-224d74346147e3810069dc33367a49f4b3a6091c.tar.zst gsoc2013-epiphany-224d74346147e3810069dc33367a49f4b3a6091c.zip |
Add EphyFrecentStore class files
This subclass of EphyOverviewStore displays the most frecently visited
pages.
https://bugzilla.gnome.org/show_bug.cgi?id=455173
-rw-r--r-- | lib/widgets/Makefile.am | 2 | ||||
-rw-r--r-- | lib/widgets/ephy-frecent-store.c | 404 | ||||
-rw-r--r-- | lib/widgets/ephy-frecent-store.h | 67 |
3 files changed, 473 insertions, 0 deletions
diff --git a/lib/widgets/Makefile.am b/lib/widgets/Makefile.am index 0232edfc5..bc53ec89d 100644 --- a/lib/widgets/Makefile.am +++ b/lib/widgets/Makefile.am @@ -67,6 +67,8 @@ libephywidgets_la_SOURCES = \ ephy-certificate-dialog.h \ ephy-download-widget.c \ ephy-download-widget.h \ + ephy-frecent-store.c \ + ephy-frecent-store.h \ ephy-history-view.c \ ephy-history-view.h \ ephy-hosts-store.c \ diff --git a/lib/widgets/ephy-frecent-store.c b/lib/widgets/ephy-frecent-store.c new file mode 100644 index 000000000..8e9e05b80 --- /dev/null +++ b/lib/widgets/ephy-frecent-store.c @@ -0,0 +1,404 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * Copyright © 2012 Igalia S.L. + * + * 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-frecent-store.h" +#include "ephy-history-service.h" +#include "ephy-snapshot-service.h" + +#define EPHY_FRECENT_STORE_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_FRECENT_STORE, EphyFrecentStorePrivate)) + +struct _EphyFrecentStorePrivate +{ + gint history_length; +}; + +enum +{ + PROP_0, + PROP_HISTORY_LENGTH, +}; + +G_DEFINE_TYPE (EphyFrecentStore, ephy_frecent_store, EPHY_TYPE_OVERVIEW_STORE) + +static void +on_find_urls_cb (EphyHistoryService *service, + gboolean success, + GList *urls, + EphyFrecentStore *store) +{ + EphyHistoryURL *url; + char *old_url; + GtkTreeIter treeiter; + gboolean valid; + GList *iter; + gboolean peek_snapshot; + + if (success != TRUE) + return; + + valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), + &treeiter); + + for (iter = urls; iter != NULL; iter = iter->next) { + peek_snapshot = FALSE; + url = (EphyHistoryURL *)iter->data; + + if (valid) { + gtk_tree_model_get (GTK_TREE_MODEL (store), &treeiter, + EPHY_OVERVIEW_STORE_URI, &old_url, + -1); + gtk_list_store_set (GTK_LIST_STORE (store), &treeiter, + EPHY_OVERVIEW_STORE_URI, url->url, + EPHY_OVERVIEW_STORE_LAST_VISIT, url->last_visit_time, + -1); + if (g_strcmp0 (old_url, url->url) != 0) { + gtk_list_store_set (GTK_LIST_STORE (store), &treeiter, + EPHY_OVERVIEW_STORE_TITLE, url->title, + -1); + peek_snapshot = TRUE; + } + + if (ephy_overview_store_needs_snapshot (EPHY_OVERVIEW_STORE (store), &treeiter)) + peek_snapshot = TRUE; + } else { + gtk_list_store_insert_with_values (GTK_LIST_STORE (store), &treeiter, -1, + EPHY_OVERVIEW_STORE_TITLE, url->title, + EPHY_OVERVIEW_STORE_URI, url->url, + EPHY_OVERVIEW_STORE_LAST_VISIT, url->last_visit_time, + -1); + peek_snapshot = TRUE; + } + + if (peek_snapshot) + ephy_overview_store_peek_snapshot (EPHY_OVERVIEW_STORE (store), + NULL, &treeiter); + + valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &treeiter); + } + + g_list_free_full (urls, (GDestroyNotify)ephy_history_url_free); + + while (valid) + valid = ephy_overview_store_remove (EPHY_OVERVIEW_STORE (store), &treeiter); +} + +static void +ephy_frecent_store_fetch_urls (EphyFrecentStore *store, + EphyHistoryService *service) +{ + EphyHistoryQuery *query; + + query = ephy_history_query_new (); + query->sort_type = EPHY_HISTORY_SORT_MV; + query->limit = store->priv->history_length; + query->ignore_hidden = TRUE; + + ephy_history_service_query_urls (service, query, NULL, + (EphyHistoryJobCallback) on_find_urls_cb, + store); + ephy_history_query_free (query); +} + +static gboolean +on_visit_url_cb (EphyHistoryService *service, + char *url, + EphyHistoryPageVisitType visit_type, + EphyFrecentStore *store) +{ + ephy_frecent_store_fetch_urls (store, service); + + return FALSE; +} + +static void +on_cleared_cb (EphyHistoryService *service, + EphyFrecentStore *store) +{ + /* Should probably emit a signal notifying that this is empty, this + signal probably should live in EphyOverviewStore. */ + + gtk_list_store_clear (GTK_LIST_STORE (store)); +} + +static void +on_url_title_changed (EphyHistoryService *service, + const char *url, + const char *title, + EphyFrecentStore *store) +{ + GtkTreeIter iter; + gchar *iter_url; + + if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) + return; + + do { + gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, + EPHY_OVERVIEW_STORE_URI, &iter_url, + -1); + if (g_strcmp0 (iter_url, url) == 0) { + gtk_list_store_set (GTK_LIST_STORE (store), &iter, + EPHY_OVERVIEW_STORE_TITLE, title, + -1); + g_free (iter_url); + break; + } + g_free (iter_url); + } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter)); +} + +static void +on_url_deleted (EphyHistoryService *service, + const char *url, + EphyFrecentStore *store) +{ + GtkTreeIter iter; + gchar *iter_url; + gboolean needs_update = FALSE; + + if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) + return; + + do { + gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, + EPHY_OVERVIEW_STORE_URI, &iter_url, + -1); + if (g_strcmp0 (iter_url, url) == 0) { + needs_update = TRUE; + ephy_overview_store_remove (EPHY_OVERVIEW_STORE (store), &iter); + g_free (iter_url); + break; + } + g_free (iter_url); + } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter)); + + if (needs_update) + ephy_frecent_store_fetch_urls (store, service); +} + +static void +on_host_deleted (EphyHistoryService *service, + const char *deleted_url, + EphyFrecentStore *store) +{ + GtkTreeIter iter; + gchar *iter_url; + SoupURI *store_uri; + SoupURI *deleted_uri; + gboolean needs_update = FALSE; + gboolean remove, valid; + + if (!gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter)) + return; + + deleted_uri = soup_uri_new (deleted_url); + + do { + gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, + EPHY_OVERVIEW_STORE_URI, &iter_url, + -1); + store_uri = soup_uri_new (iter_url); + remove = g_strcmp0 (soup_uri_get_host (deleted_uri), soup_uri_get_host (store_uri)) == 0; + soup_uri_free (store_uri); + g_free (iter_url); + + if (remove) { + valid = ephy_overview_store_remove (EPHY_OVERVIEW_STORE (store), &iter); + needs_update = TRUE; + } else + valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter); + } while (valid); + + soup_uri_free (deleted_uri); + + if (needs_update) + ephy_frecent_store_fetch_urls (store, service); + +} + +static void +setup_history_service (EphyFrecentStore *store) +{ + EphyHistoryService *service; + + g_object_get (G_OBJECT (store), "history-service", &service, NULL); + + ephy_frecent_store_fetch_urls (store, service); + + g_signal_connect_after (service, "visit-url", + G_CALLBACK (on_visit_url_cb), store); + g_signal_connect (service, "cleared", + G_CALLBACK (on_cleared_cb), store); + g_signal_connect (service, "url-title-changed", + G_CALLBACK (on_url_title_changed), store); + g_signal_connect (service, "url-deleted", + G_CALLBACK (on_url_deleted), store); + g_signal_connect (service, "host-deleted", + G_CALLBACK (on_host_deleted), store); + g_object_unref (service); +} + +static void +ephy_frecent_store_notify (GObject *object, + GParamSpec *pspec) +{ + if (g_strcmp0 (pspec->name, "history-service") == 0) + setup_history_service (EPHY_FRECENT_STORE (object)); + + if (G_OBJECT_CLASS (ephy_frecent_store_parent_class)->notify) + G_OBJECT_CLASS (ephy_frecent_store_parent_class)->notify (object, pspec); +} + +static void +ephy_frecent_store_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + EphyFrecentStore *store = EPHY_FRECENT_STORE (object); + + switch (prop_id) + { + case PROP_HISTORY_LENGTH: + ephy_frecent_store_set_history_length (store, g_value_get_int (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +ephy_frecent_store_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + EphyFrecentStore *store = EPHY_FRECENT_STORE (object); + + switch (prop_id) + { + case PROP_HISTORY_LENGTH: + g_value_set_int (value, ephy_frecent_store_get_history_length (store)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +ephy_frecent_store_class_init (EphyFrecentStoreClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->notify = ephy_frecent_store_notify; + object_class->set_property = ephy_frecent_store_set_property; + object_class->get_property = ephy_frecent_store_get_property; + + g_object_class_install_property (object_class, + PROP_HISTORY_LENGTH, + g_param_spec_int ("history-length", + "History length", + "Length of the history list", + 0, G_MAXINT, 12, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); + + g_type_class_add_private (object_class, sizeof(EphyFrecentStorePrivate)); +} + +static void +ephy_frecent_store_init (EphyFrecentStore *self) +{ + self->priv = EPHY_FRECENT_STORE_GET_PRIVATE (self); +} + +EphyFrecentStore * +ephy_frecent_store_new (void) +{ + return g_object_new (EPHY_TYPE_FRECENT_STORE, + NULL); +} + +static void +set_url_hidden_cb (EphyHistoryService *service, + gboolean success, + gpointer result_data, + EphyFrecentStore *store) +{ + if (!success) + return; + + ephy_frecent_store_fetch_urls (store, service); +} + +void +ephy_frecent_store_set_hidden (EphyFrecentStore *store, + GtkTreeIter *iter) +{ + EphyHistoryService *service; + char *uri; + + g_return_if_fail (EPHY_IS_FRECENT_STORE (store)); + g_return_if_fail (iter != NULL); + + gtk_tree_model_get (GTK_TREE_MODEL (store), iter, + EPHY_OVERVIEW_STORE_URI, &uri, + -1); + g_object_get (store, "history-service", &service, NULL); + + ephy_history_service_set_url_hidden (service, + uri, TRUE, NULL, + (EphyHistoryJobCallback) set_url_hidden_cb, + store); + g_free (uri); + g_object_unref (service); +} + +void +ephy_frecent_store_set_history_length (EphyFrecentStore *store, + gint length) +{ + EphyHistoryService *service; + + g_return_if_fail (EPHY_IS_FRECENT_STORE (store)); + g_return_if_fail (length > 0); + + if (store->priv->history_length == length) + return; + + store->priv->history_length = length; + + g_object_get (G_OBJECT (store), "history-service", &service, NULL); + if (service) { + ephy_frecent_store_fetch_urls (store, service); + g_object_unref (service); + } +} + +int +ephy_frecent_store_get_history_length (EphyFrecentStore *store) +{ + g_return_val_if_fail (EPHY_IS_FRECENT_STORE (store), 0); + + return store->priv->history_length; +} diff --git a/lib/widgets/ephy-frecent-store.h b/lib/widgets/ephy-frecent-store.h new file mode 100644 index 000000000..470e877f8 --- /dev/null +++ b/lib/widgets/ephy-frecent-store.h @@ -0,0 +1,67 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * Copyright © 2012 Igalia S.L. + * + * 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. + * + * Author: Claudio Saavedra <csaavedra@igalia.com> + */ + +#ifndef _EPHY_FRECENT_STORE_H +#define _EPHY_FRECENT_STORE_H + +#include <glib-object.h> + +#include "ephy-overview-store.h" + +G_BEGIN_DECLS + +#define EPHY_TYPE_FRECENT_STORE (ephy_frecent_store_get_type()) +#define EPHY_FRECENT_STORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EPHY_TYPE_FRECENT_STORE, EphyFrecentStore)) +#define EPHY_FRECENT_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EPHY_TYPE_FRECENT_STORE, EphyFrecentStoreClass)) +#define EPHY_IS_FRECENT_STORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EPHY_TYPE_FRECENT_STORE)) +#define EPHY_IS_FRECENT_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EPHY_TYPE_FRECENT_STORE)) +#define EPHY_FRECENT_STORE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EPHY_TYPE_FRECENT_STORE, EphyFrecentStoreClass)) + +typedef struct _EphyFrecentStore EphyFrecentStore; +typedef struct _EphyFrecentStoreClass EphyFrecentStoreClass; +typedef struct _EphyFrecentStorePrivate EphyFrecentStorePrivate; + +struct _EphyFrecentStore +{ + EphyOverviewStore parent; + EphyFrecentStorePrivate *priv; +}; + +struct _EphyFrecentStoreClass +{ + EphyOverviewStoreClass parent_class; +}; + +GType ephy_frecent_store_get_type (void) G_GNUC_CONST; + +EphyFrecentStore* ephy_frecent_store_new (void); + +void ephy_frecent_store_set_hidden (EphyFrecentStore *store, + GtkTreeIter *iter); + +void ephy_frecent_store_set_history_length (EphyFrecentStore *store, + gint length); + +int ephy_frecent_store_get_history_length (EphyFrecentStore *store); + +G_END_DECLS + +#endif /* _EPHY_FRECENT_STORE_H */ |