+ return icon;
+}
+
+static void
+clear_range (EvSidebarThumbnails *sidebar_thumbnails,
+ gint start_page,
+ gint end_page)
+{
+ EvSidebarThumbnailsPrivate *priv = sidebar_thumbnails->priv;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ gboolean result;
+ gint prev_width = -1;
+ gint prev_height = -1;
+
+ g_assert (start_page <= end_page);
+
+ path = gtk_tree_path_new_from_indices (start_page, -1);
+ for (result = gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->list_store), &iter, path);
+ result && start_page <= end_page;
+ result = gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->list_store), &iter), start_page ++) {
+ EvJobThumbnail *job;
+ GdkPixbuf *loading_icon = NULL;
+ gint width, height;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (priv->list_store),
+ &iter,
+ COLUMN_JOB, &job,
+ -1);
+
+ if (job) {
+ g_signal_handlers_disconnect_by_func (job, thumbnail_job_completed_callback, sidebar_thumbnails);
+ ev_job_cancel (EV_JOB (job));
+ g_object_unref (job);
+ }
+
+ ev_thumbnails_size_cache_get_size (priv->size_cache, start_page,
+ priv->rotation,
+ &width, &height);
+ if (!loading_icon || (width != prev_width && height != prev_height)) {
+ loading_icon =
+ ev_sidebar_thumbnails_get_loading_icon (sidebar_thumbnails,
+ width, height);
+ }
+
+ prev_width = width;
+ prev_height = height;
+
+ gtk_list_store_set (priv->list_store, &iter,
+ COLUMN_JOB, NULL,
+ COLUMN_THUMBNAIL_SET, FALSE,
+ COLUMN_PIXBUF, loading_icon,
+ -1);
+ }
+ gtk_tree_path_free (path);
+}
+
+static gdouble
+get_scale_for_page (EvSidebarThumbnails *sidebar_thumbnails,
+ gint page)
+{
+ EvSidebarThumbnailsPrivate *priv = sidebar_thumbnails->priv;
+ gdouble width;
+
+ ev_document_get_page_size (priv->document, page, &width, NULL);
+
+ return (gdouble)THUMBNAIL_WIDTH / width;
+}
+
+static void
+add_range (EvSidebarThumbnails *sidebar_thumbnails,
+ gint start_page,
+ gint end_page)
+{
+ EvSidebarThumbnailsPrivate *priv = sidebar_thumbnails->priv;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ gboolean result;
+ gint page = start_page;
+
+ g_assert (start_page <= end_page);
+
+ path = gtk_tree_path_new_from_indices (start_page, -1);
+ for (result = gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->list_store), &iter, path);
+ result && page <= end_page;
+ result = gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->list_store), &iter), page ++) {
+ EvJob *job;
+ gboolean thumbnail_set;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (priv->list_store), &iter,
+ COLUMN_JOB, &job,
+ COLUMN_THUMBNAIL_SET, &thumbnail_set,
+ -1);
+
+ if (job == NULL && !thumbnail_set) {
+ job = ev_job_thumbnail_new (priv->document,
+ page, priv->rotation,
+ get_scale_for_page (sidebar_thumbnails, page));
+ ev_job_scheduler_push_job (EV_JOB (job), EV_JOB_PRIORITY_HIGH);
+
+ g_object_set_data_full (G_OBJECT (job), "tree_iter",
+ gtk_tree_iter_copy (&iter),
+ (GDestroyNotify) gtk_tree_iter_free);
+ g_signal_connect (job, "finished",
+ G_CALLBACK (thumbnail_job_completed_callback),
+ sidebar_thumbnails);
+ gtk_list_store_set (priv->list_store, &iter,
+ COLUMN_JOB, job,
+ -1);
+
+ /* The queue and the list own a ref to the job now */
+ g_object_unref (job);
+ } else if (job) {
+ g_object_unref (job);
+ }
+ }
+ gtk_tree_path_free (path);
+}
+
+/* This modifies start */
+static void
+update_visible_range (EvSidebarThumbnails *sidebar_thumbnails,
+ gint start_page,
+ gint end_page)
+{
+ EvSidebarThumbnailsPrivate *priv = sidebar_thumbnails->priv;
+ int old_start_page, old_end_page;
+
+ old_start_page = priv->start_page;
+ old_end_page = priv->end_page;
+
+ if (start_page == old_start_page &&
+ end_page == old_end_page)
+ return;
+
+ /* Clear the areas we no longer display */
+ if (old_start_page >= 0 && old_start_page < start_page)
+ clear_range (sidebar_thumbnails, old_start_page, MIN (start_page - 1, old_end_page));