[evince/wip/recent-view: 3/12] bookshelf: Save thumbnails and metadata
- From: Germán Poó Caamaño <gpoo src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evince/wip/recent-view: 3/12] bookshelf: Save thumbnails and metadata
- Date: Mon, 24 Feb 2014 04:04:49 +0000 (UTC)
commit b7965523f13b09336d40b479ba293b60e5c4324c
Author: Aakash Goenka <aakash goenka gmail com>
Date: Sun Feb 23 15:38:33 2014 -0800
bookshelf: Save thumbnails and metadata
Use gtk_recent_info_get_modified instead of
gtk_recent_info_get_visited for ordering the recent items.
shell/ev-bookshelf.c | 186 ++++++++++++++++++++++++++++++++++++++++++--------
shell/ev-metadata.c | 33 +++++++++
shell/ev-metadata.h | 6 ++
3 files changed, 196 insertions(+), 29 deletions(-)
---
diff --git a/shell/ev-bookshelf.c b/shell/ev-bookshelf.c
index 934ccae..7173c6c 100644
--- a/shell/ev-bookshelf.c
+++ b/shell/ev-bookshelf.c
@@ -22,6 +22,7 @@
#include <gdk-pixbuf/gdk-pixbuf.h>
#include "ev-bookshelf.h"
+#include "ev-file-helpers.h"
#include "gd-icon-utils.h"
#include "gd-main-view-generic.h"
#include "gd-main-icon-view.h"
@@ -29,17 +30,20 @@
#include "ev-document-model.h"
#include "ev-jobs.h"
#include "ev-job-scheduler.h"
+#include "ev-metadata.h"
typedef enum {
EV_BOOKSHELF_JOB_COLUMN = GD_MAIN_COLUMN_LAST,
EV_BOOKSHELF_THUMBNAILED_COLUMN,
EV_BOOKSHELF_DOCUMENT_COLUMN,
+ EV_BOOKSHELF_METADATA_COLUMN,
NUM_COLUMNS
} EvBookshelfColumns;
struct _EvBookshelfPrivate {
GtkWidget *view;
GtkListStore *list_store;
+ GtkRecentManager *recent_manager;
gchar *button_press_item_path;
};
@@ -59,11 +63,12 @@ static gboolean ev_bookshelf_clear_job (GtkTreeModel *model,
GtkTreeIter *iter,
gpointer data);
static void ev_bookshelf_clear_model (EvBookshelf *bookshelf);
+static void ev_bookshelf_refresh (EvBookshelf *bookshelf);
G_DEFINE_TYPE (EvBookshelf, ev_bookshelf, GTK_TYPE_SCROLLED_WINDOW)
#define ICON_VIEW_SIZE 128
-#define MAX_RECENT_ITEMS 20
+#define MAX_BOOKSHELF_ITEMS 20
static void
ev_bookshelf_dispose (GObject *obj)
@@ -76,10 +81,75 @@ ev_bookshelf_dispose (GObject *obj)
self->priv->list_store = NULL;
}
+ if (self->priv->recent_manager) {
+ g_signal_handlers_disconnect_by_func (self->priv->recent_manager,
+ ev_bookshelf_refresh,
+ self);
+ self->priv->recent_manager = NULL;
+ }
G_OBJECT_CLASS (ev_bookshelf_parent_class)->dispose (obj);
}
static gboolean
+metadata_is_stale (EvMetadata *metadata,
+ GFile *file)
+{
+ GFileInfo *info = NULL;
+ GError *error = NULL;
+ guint64 mtime_metadata;
+ guint64 mtime_file;
+
+ info = g_file_query_info (file,
+ G_FILE_ATTRIBUTE_TIME_MODIFIED,
+ 0,
+ NULL,
+ &error);
+ if (!info) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+
+ return TRUE;
+ }
+
+ if (!ev_metadata_get_uint64 (metadata, "mtime", &mtime_metadata))
+ return TRUE;
+
+ mtime_file = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED);
+
+ if (mtime_file != 0 && mtime_metadata >= mtime_file)
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+save_thumbnail (GdkPixbuf *pixbuf,
+ EvMetadata *metadata)
+{
+ GFile *thumbnail_file = NULL;
+ GError *error = NULL;
+ gchar *thumbnail_path = NULL;
+
+ thumbnail_file = ev_mkstemp_file ("thumb.XXXXXX", &error);
+
+ if (thumbnail_file) {
+ thumbnail_path = g_file_get_path (thumbnail_file);
+ g_object_unref (thumbnail_file);
+ }
+
+ if (thumbnail_path) {
+ gdk_pixbuf_save (pixbuf, thumbnail_path,
+ "png", &error, NULL);
+ if (!error)
+ ev_metadata_set_string (metadata, "thumbnail-path", thumbnail_path);
+ g_free (thumbnail_path);
+ }
+
+ if (error)
+ g_error_free (error);
+}
+
+static gboolean
ev_bookshelf_clear_job (GtkTreeModel *model,
GtkTreePath *path,
GtkTreeIter *iter,
@@ -121,8 +191,8 @@ compare_recent_items (GtkRecentInfo *a,
if (has_ev_a && has_ev_b) {
time_t time_a, time_b;
- time_a = gtk_recent_info_get_added (a);
- time_b = gtk_recent_info_get_added (b);
+ time_a = gtk_recent_info_get_modified (a);
+ time_b = gtk_recent_info_get_modified (b);
return (time_b - time_a);
} else if (has_ev_a) {
@@ -186,6 +256,10 @@ on_button_release_event (GtkWidget *view,
gtk_tree_model_get (GTK_TREE_MODEL (self->priv->list_store), &iter,
GD_MAIN_COLUMN_URI, &uri,
-1);
+ gtk_list_store_set (self->priv->list_store,
+ &iter,
+ GD_MAIN_COLUMN_SELECTED, TRUE,
+ -1);
g_signal_emit (self, signals[ITEM_ACTIVATED], 0, uri);
}
exit:
@@ -219,7 +293,8 @@ thumbnail_job_completed_callback (EvJobThumbnail *job,
EvBookshelfPrivate *priv = ev_bookshelf->priv;
GtkTreeIter *iter;
GdkPixbuf *pixbuf;
- EvDocument document;
+ EvDocument *document;
+ EvMetadata *metadata;
GtkBorder border;
border.left = 4;
@@ -237,6 +312,7 @@ thumbnail_job_completed_callback (EvJobThumbnail *job,
gtk_tree_model_get (GTK_TREE_MODEL (priv->list_store),
iter,
EV_BOOKSHELF_DOCUMENT_COLUMN, &document,
+ EV_BOOKSHELF_METADATA_COLUMN, &metadata,
-1);
gtk_list_store_set (priv->list_store,
@@ -246,6 +322,11 @@ thumbnail_job_completed_callback (EvJobThumbnail *job,
EV_BOOKSHELF_JOB_COLUMN, NULL,
-1);
+ if (metadata) {
+ save_thumbnail (pixbuf, metadata);
+ ev_metadata_set_uint64 (metadata, "mtime", g_get_real_time ());
+ g_object_unref (metadata);
+ }
g_object_unref (pixbuf);
}
@@ -256,6 +337,7 @@ document_load_job_completed_callback (EvJobLoad *job_load,
EvBookshelfPrivate *priv = ev_bookshelf->priv;
GtkTreeIter *iter;
EvDocument *document;
+ EvMetadata *metadata;
document = EV_JOB (job_load)->document;
iter = (GtkTreeIter *) g_object_get_data (G_OBJECT (job_load), "tree_iter");
@@ -288,17 +370,39 @@ document_load_job_completed_callback (EvJobLoad *job_load,
EV_BOOKSHELF_JOB_COLUMN, job_thumbnail,
EV_BOOKSHELF_DOCUMENT_COLUMN, document,
-1);
-
+
ev_job_scheduler_push_job (EV_JOB (job_thumbnail), EV_JOB_PRIORITY_HIGH);
g_object_unref (job_thumbnail);
} else {
+ gtk_tree_model_get (GTK_TREE_MODEL (priv->list_store),
+ iter,
+ EV_RECENT_VIEW_METADATA_COLUMN, &metadata,
+ -1);
+
gtk_list_store_set (priv->list_store,
iter,
EV_BOOKSHELF_THUMBNAILED_COLUMN, TRUE,
EV_BOOKSHELF_JOB_COLUMN, NULL,
-1);
+
+ if (metadata) {
+ GdkPixbuf *thumbnail;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (priv->list_store),
+ iter,
+ GD_MAIN_COLUMN_ICON, &thumbnail,
+ -1);
+
+ if (thumbnail)
+ save_thumbnail (thumbnail, metadata);
+
+ ev_metadata_set_uint64 (metadata, "mtime", g_get_real_time ());
+
+ g_object_unref (metadata);
+ g_object_unref (thumbnail);
+ }
}
}
@@ -308,18 +412,20 @@ ev_bookshelf_refresh (EvBookshelf *ev_bookshelf)
GList *items, *l;
guint n_items = 0;
const gchar *evince = g_get_application_name ();
- GtkRecentManager *recent_manager = gtk_recent_manager_get_default ();
GdMainViewGeneric *generic = get_generic (ev_bookshelf);
- items = gtk_recent_manager_get_items (recent_manager);
+ items = gtk_recent_manager_get_items (ev_bookshelf->priv->recent_manager);
items = g_list_sort (items, (GCompareFunc) compare_recent_items);
gtk_list_store_clear (ev_bookshelf->priv->list_store);
for (l = items; l && l->data; l = g_list_next (l)) {
- EvJob *job_load;
+ EvJob *job_load = NULL;
+ EvMetadata *metadata = NULL;
+ GFile *file;
const gchar *name;
const gchar *uri;
+ gchar *thumbnail_path;
GtkRecentInfo *info;
GdkPixbuf *thumbnail;
GtkTreeIter iter;
@@ -332,47 +438,63 @@ ev_bookshelf_refresh (EvBookshelf *ev_bookshelf)
name = gtk_recent_info_get_display_name (info);
uri = gtk_recent_info_get_uri (info);
-
- thumbnail = gtk_recent_info_get_icon (info, ICON_VIEW_SIZE);
-
- job_load = ev_job_load_new (uri);
-
- g_signal_connect (job_load, "finished",
- G_CALLBACK (document_load_job_completed_callback),
- ev_bookshelf);
-
- access_time = gtk_recent_info_get_added (info);
+ file = g_file_new_for_uri (uri);
+
+ if (ev_is_metadata_supported_for_file (file)) {
+
+ metadata = ev_metadata_new (file);
+ if (metadata_is_stale (metadata, file) ||
+ !ev_metadata_get_string (metadata, "thumbnail-path", &thumbnail_path))
+ goto load_document;
+
+ thumbnail = gdk_pixbuf_new_from_file (thumbnail_path, NULL);
+ if (!thumbnail)
+ goto load_document;
+ } else {
+
+ load_document:
+
+ thumbnail = gtk_recent_info_get_icon (info, ICON_VIEW_SIZE);
+ job_load = ev_job_load_new (uri);
+ g_signal_connect (job_load, "finished",
+ G_CALLBACK (document_load_job_completed_callback),
+ ev_bookshelf);
+ }
+ access_time = gtk_recent_info_get_modified (info);
gtk_list_store_append (ev_bookshelf->priv->list_store, &iter);
gtk_list_store_set (ev_bookshelf->priv->list_store, &iter,
GD_MAIN_COLUMN_URI, uri,
GD_MAIN_COLUMN_PRIMARY_TEXT, name,
- GD_MAIN_COLUMN_SECONDARY_TEXT, _(""),
+ GD_MAIN_COLUMN_SECONDARY_TEXT, NULL,
GD_MAIN_COLUMN_ICON, thumbnail,
GD_MAIN_COLUMN_MTIME, access_time,
GD_MAIN_COLUMN_SELECTED, FALSE,
EV_BOOKSHELF_DOCUMENT_COLUMN, NULL,
EV_BOOKSHELF_JOB_COLUMN, job_load,
EV_BOOKSHELF_THUMBNAILED_COLUMN, FALSE,
+ EV_BOOKSHELF_METADATA_COLUMN, metadata,
-1);
- g_object_set_data_full (G_OBJECT (job_load), "tree_iter",
- gtk_tree_iter_copy (&iter),
- (GDestroyNotify) gtk_tree_iter_free);
-
- ev_job_scheduler_push_job (EV_JOB (job_load), EV_JOB_PRIORITY_HIGH);
+ if (job_load) {
+
+ g_object_set_data_full (G_OBJECT (job_load), "tree_iter",
+ gtk_tree_iter_copy (&iter),
+ (GDestroyNotify) gtk_tree_iter_free);
+ ev_job_scheduler_push_job (EV_JOB (job_load), EV_JOB_PRIORITY_HIGH);
+ }
if (thumbnail != NULL)
g_object_unref (thumbnail);
- if (++n_items == MAX_RECENT_ITEMS)
+ if (++n_items == MAX_BOOKSHELF_ITEMS)
break;
}
-
+
g_list_foreach (items, (GFunc) gtk_recent_info_unref, NULL);
g_list_free (items);
-
+
gd_main_view_generic_set_model (generic, GTK_TREE_MODEL (ev_bookshelf->priv->list_store));
}
@@ -415,7 +537,8 @@ static void
ev_bookshelf_init (EvBookshelf *ev_bookshelf)
{
ev_bookshelf->priv = G_TYPE_INSTANCE_GET_PRIVATE (ev_bookshelf, EV_TYPE_BOOKSHELF,
EvBookshelfPrivate);
- ev_bookshelf->priv->list_store = gtk_list_store_new (10,
+ ev_bookshelf->priv->recent_manager = gtk_recent_manager_get_default ();
+ ev_bookshelf->priv->list_store = gtk_list_store_new (11,
G_TYPE_STRING,
G_TYPE_STRING,
G_TYPE_STRING,
@@ -425,7 +548,8 @@ ev_bookshelf_init (EvBookshelf *ev_bookshelf)
G_TYPE_BOOLEAN,
EV_TYPE_JOB,
G_TYPE_BOOLEAN,
- EV_TYPE_DOCUMENT);
+ EV_TYPE_DOCUMENT,
+ EV_TYPE_METADATA);
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (ev_bookshelf->priv->list_store),
GD_MAIN_COLUMN_MTIME,
GTK_SORT_DESCENDING);
@@ -437,6 +561,10 @@ ev_bookshelf_init (EvBookshelf *ev_bookshelf)
GTK_POLICY_NEVER,
GTK_POLICY_AUTOMATIC);
+ g_signal_connect_swapped (ev_bookshelf->priv->recent_manager,
+ "changed",
+ G_CALLBACK (ev_bookshelf_refresh),
+ ev_bookshelf);
}
static void
diff --git a/shell/ev-metadata.c b/shell/ev-metadata.c
index b0e23a1..52e40c1 100644
--- a/shell/ev-metadata.c
+++ b/shell/ev-metadata.c
@@ -18,6 +18,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#include <glib.h>
#include <gio/gio.h>
#include <string.h>
@@ -229,6 +230,26 @@ ev_metadata_get_int (EvMetadata *metadata,
}
gboolean
+ev_metadata_get_uint64 (EvMetadata *metadata,
+ const gchar *key,
+ guint64 *value)
+{
+ gchar *string_value;
+ gchar *endptr;
+ guint64 uint64_value;
+
+ if (!ev_metadata_get_string (metadata, key, &string_value))
+ return FALSE;
+
+ uint64_value = g_ascii_strtoull (string_value, &endptr, 0);
+ if (uint64_value == 0 && string_value == endptr)
+ return FALSE;
+
+ *value = uint64_value;
+ return TRUE;
+}
+
+gboolean
ev_metadata_set_int (EvMetadata *metadata,
const gchar *key,
gint value)
@@ -241,6 +262,18 @@ ev_metadata_set_int (EvMetadata *metadata,
}
gboolean
+ev_metadata_set_uint64 (EvMetadata *metadata,
+ const gchar *key,
+ guint64 value)
+{
+ gchar string_value[21];
+
+ g_snprintf (string_value, sizeof (string_value), "%"G_GUINT64_FORMAT, value);
+
+ return ev_metadata_set_string (metadata, key, string_value);
+}
+
+gboolean
ev_metadata_get_double (EvMetadata *metadata,
const gchar *key,
gdouble *value)
diff --git a/shell/ev-metadata.h b/shell/ev-metadata.h
index 7fd4f05..ba31069 100644
--- a/shell/ev-metadata.h
+++ b/shell/ev-metadata.h
@@ -62,6 +62,12 @@ gboolean ev_metadata_get_boolean (EvMetadata *metadata,
gboolean ev_metadata_set_boolean (EvMetadata *metadata,
const gchar *key,
gboolean value);
+gboolean ev_metadata_get_uint64 (EvMetadata *metadata,
+ const gchar *key,
+ guint64 *value);
+gboolean ev_metadata_set_uint64 (EvMetadata *metadata,
+ const gchar *key,
+ guint64 value);
gboolean ev_metadata_has_key (EvMetadata *metadata,
const gchar *key);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]