Evince
Evince is a document viewer capable of displaying multiple and single page document formats like PDF and Postscript.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ev-sidebar-thumbnails.c File Reference
#include <string.h>
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <cairo-gobject.h>
#include "ev-document-misc.h"
#include "ev-job-scheduler.h"
#include "ev-sidebar-page.h"
#include "ev-sidebar-thumbnails.h"
#include "ev-utils.h"
#include "ev-window.h"
+ Include dependency graph for ev-sidebar-thumbnails.c:

Go to the source code of this file.

Data Structures

struct  _EvThumbsSize
 
struct  _EvThumbsSizeCache
 
struct  _EvSidebarThumbnailsPrivate
 

Macros

#define THUMBNAIL_WIDTH   100
 
#define MAX_ICON_VIEW_PAGE_COUNT   1500
 
#define EV_SIDEBAR_THUMBNAILS_GET_PRIVATE(object)   (G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_SIDEBAR_THUMBNAILS, EvSidebarThumbnailsPrivate));
 
#define EV_THUMBNAILS_SIZE_CACHE_KEY   "ev-thumbnails-size-cache"
 

Typedefs

typedef struct _EvThumbsSize EvThumbsSize
 
typedef struct _EvThumbsSizeCache EvThumbsSizeCache
 

Enumerations

enum  {
  COLUMN_PAGE_STRING, COLUMN_SURFACE, COLUMN_THUMBNAIL_SET, COLUMN_JOB,
  NUM_COLUMNS
}
 
enum  { PROP_0, PROP_WIDGET }
 

Functions

static void ev_sidebar_thumbnails_clear_model (EvSidebarThumbnails *sidebar)
 
static gboolean ev_sidebar_thumbnails_support_document (EvSidebarPage *sidebar_page, EvDocument *document)
 
static void ev_sidebar_thumbnails_page_iface_init (EvSidebarPageInterface *iface)
 
static const gchar * ev_sidebar_thumbnails_get_label (EvSidebarPage *sidebar_page)
 
static void ev_sidebar_thumbnails_set_current_page (EvSidebarThumbnails *sidebar, gint page)
 
static void thumbnail_job_completed_callback (EvJobThumbnail *job, EvSidebarThumbnails *sidebar_thumbnails)
 
static void ev_sidebar_thumbnails_reload (EvSidebarThumbnails *sidebar_thumbnails)
 
static void adjustment_changed_cb (EvSidebarThumbnails *sidebar_thumbnails)
 
 G_DEFINE_TYPE_EXTENDED (EvSidebarThumbnails, ev_sidebar_thumbnails, GTK_TYPE_BOX, 0, G_IMPLEMENT_INTERFACE(EV_TYPE_SIDEBAR_PAGE, ev_sidebar_thumbnails_page_iface_init))
 
static EvThumbsSizeCacheev_thumbnails_size_cache_new (EvDocument *document)
 
static void ev_thumbnails_size_cache_get_size (EvThumbsSizeCache *cache, gint page, gint rotation, gint *width, gint *height)
 
static void ev_thumbnails_size_cache_free (EvThumbsSizeCache *cache)
 
static EvThumbsSizeCacheev_thumbnails_size_cache_get (EvDocument *document)
 
static gboolean ev_sidebar_thumbnails_page_is_in_visible_range (EvSidebarThumbnails *sidebar, guint page)
 
static void ev_sidebar_thumbnails_dispose (GObject *object)
 
static void ev_sidebar_thumbnails_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
 
static void ev_sidebar_thumbnails_map (GtkWidget *widget)
 
static void ev_sidebar_fullscreen_cb (EvSidebarThumbnails *sidebar)
 
static void ev_sidebar_thumbnails_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
 
static void ev_sidebar_thumbnails_class_init (EvSidebarThumbnailsClass *ev_sidebar_thumbnails_class)
 
GtkWidget * ev_sidebar_thumbnails_new (void)
 
static cairo_surface_t * ev_sidebar_thumbnails_get_loading_icon (EvSidebarThumbnails *sidebar_thumbnails, gint width, gint height)
 
static void cancel_running_jobs (EvSidebarThumbnails *sidebar_thumbnails, gint start_page, gint end_page)
 
static void get_size_for_page (EvSidebarThumbnails *sidebar_thumbnails, gint page, gint *width_return, gint *height_return)
 
static void add_range (EvSidebarThumbnails *sidebar_thumbnails, gint start_page, gint end_page)
 
static void update_visible_range (EvSidebarThumbnails *sidebar_thumbnails, gint start_page, gint end_page)
 
static void ev_sidebar_thumbnails_fill_model (EvSidebarThumbnails *sidebar_thumbnails)
 
static void ev_sidebar_tree_selection_changed (GtkTreeSelection *selection, EvSidebarThumbnails *ev_sidebar_thumbnails)
 
static void ev_sidebar_icon_selection_changed (GtkIconView *icon_view, EvSidebarThumbnails *ev_sidebar_thumbnails)
 
static void ev_sidebar_init_tree_view (EvSidebarThumbnails *ev_sidebar_thumbnails)
 
static void ev_sidebar_init_icon_view (EvSidebarThumbnails *ev_sidebar_thumbnails)
 
static gboolean ev_sidebar_thumbnails_use_icon_view (EvSidebarThumbnails *sidebar_thumbnails)
 
static void ev_sidebar_thumbnails_device_scale_factor_changed_cb (EvSidebarThumbnails *sidebar_thumbnails, GParamSpec *pspec)
 
static void ev_sidebar_thumbnails_row_changed (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
 
static void ev_sidebar_thumbnails_init (EvSidebarThumbnails *ev_sidebar_thumbnails)
 
static void page_changed_cb (EvSidebarThumbnails *sidebar, gint old_page, gint new_page)
 
static gboolean refresh (EvSidebarThumbnails *sidebar_thumbnails)
 
static void ev_sidebar_thumbnails_rotation_changed_cb (EvDocumentModel *model, GParamSpec *pspec, EvSidebarThumbnails *sidebar_thumbnails)
 
static void ev_sidebar_thumbnails_inverted_colors_changed_cb (EvDocumentModel *model, GParamSpec *pspec, EvSidebarThumbnails *sidebar_thumbnails)
 
static void ev_sidebar_thumbnails_document_changed_cb (EvDocumentModel *model, GParamSpec *pspec, EvSidebarThumbnails *sidebar_thumbnails)
 
static void ev_sidebar_thumbnails_set_model (EvSidebarPage *sidebar_page, EvDocumentModel *model)
 
static gboolean ev_sidebar_thumbnails_clear_job (GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
 

Macro Definition Documentation

#define EV_SIDEBAR_THUMBNAILS_GET_PRIVATE (   object)    (G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_SIDEBAR_THUMBNAILS, EvSidebarThumbnailsPrivate));
#define EV_THUMBNAILS_SIZE_CACHE_KEY   "ev-thumbnails-size-cache"
#define MAX_ICON_VIEW_PAGE_COUNT   1500

Definition at line 47 of file ev-sidebar-thumbnails.c.

#define THUMBNAIL_WIDTH   100

Definition at line 43 of file ev-sidebar-thumbnails.c.

Typedef Documentation

typedef struct _EvThumbsSize EvThumbsSize

Enumeration Type Documentation

anonymous enum
Enumerator
COLUMN_PAGE_STRING 
COLUMN_SURFACE 
COLUMN_THUMBNAIL_SET 
COLUMN_JOB 
NUM_COLUMNS 

Definition at line 83 of file ev-sidebar-thumbnails.c.

83  {
87  COLUMN_JOB,
89 };
anonymous enum
Enumerator
PROP_0 
PROP_WIDGET 

Definition at line 91 of file ev-sidebar-thumbnails.c.

91  {
92  PROP_0,
94 };

Function Documentation

static void add_range ( EvSidebarThumbnails sidebar_thumbnails,
gint  start_page,
gint  end_page 
)
static

Definition at line 506 of file ev-sidebar-thumbnails.c.

509 {
510  EvSidebarThumbnailsPrivate *priv = sidebar_thumbnails->priv;
511  GtkTreePath *path;
512  GtkTreeIter iter;
513  gboolean result;
514  gint page = start_page;
515 
516  g_assert (start_page <= end_page);
517 
518  path = gtk_tree_path_new_from_indices (start_page, -1);
519  for (result = gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->list_store), &iter, path);
520  result && page <= end_page;
521  result = gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->list_store), &iter), page ++) {
522  EvJob *job;
523  gboolean thumbnail_set;
524 
525  gtk_tree_model_get (GTK_TREE_MODEL (priv->list_store), &iter,
526  COLUMN_JOB, &job,
527  COLUMN_THUMBNAIL_SET, &thumbnail_set,
528  -1);
529 
530  if (job == NULL && !thumbnail_set) {
531  gint thumbnail_width, thumbnail_height;
532  get_size_for_page (sidebar_thumbnails, page, &thumbnail_width, &thumbnail_height);
533 
535  page, priv->rotation,
536  thumbnail_width, thumbnail_height);
539  g_object_set_data_full (G_OBJECT (job), "tree_iter",
540  gtk_tree_iter_copy (&iter),
541  (GDestroyNotify) gtk_tree_iter_free);
542  g_signal_connect (job, "finished",
544  sidebar_thumbnails);
545  gtk_list_store_set (priv->list_store, &iter,
546  COLUMN_JOB, job,
547  -1);
549 
550  /* The queue and the list own a ref to the job now */
551  g_object_unref (job);
552  } else if (job) {
553  g_object_unref (job);
554  }
555  }
556  gtk_tree_path_free (path);
557 }

+ Here is the caller graph for this function:

static void adjustment_changed_cb ( EvSidebarThumbnails sidebar_thumbnails)
static

Definition at line 597 of file ev-sidebar-thumbnails.c.

598 {
599  EvSidebarThumbnailsPrivate *priv = sidebar_thumbnails->priv;
600  GtkTreePath *path = NULL;
601  GtkTreePath *path2 = NULL;
602  gdouble page_size;
603  gdouble value;
604  gint wy1;
605  gint wy2;
606 
607  /* Widget is not currently visible */
608  if (!gtk_widget_get_mapped (GTK_WIDGET (sidebar_thumbnails)))
609  return;
610 
611  page_size = gtk_adjustment_get_page_size (priv->vadjustment);
612 
613  if (page_size == 0)
614  return;
615 
616  value = gtk_adjustment_get_value (priv->vadjustment);
617 
618  if (priv->tree_view) {
619  if (! gtk_widget_get_realized (priv->tree_view))
620  return;
621 
622  gtk_tree_view_convert_tree_to_bin_window_coords (GTK_TREE_VIEW (priv->tree_view),
623  0, (int) value,
624  NULL, &wy1);
625  gtk_tree_view_convert_tree_to_bin_window_coords (GTK_TREE_VIEW (priv->tree_view),
626  0, (int) (value + page_size),
627  NULL, &wy2);
628  gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (priv->tree_view),
629  1, wy1 + 1, &path,
630  NULL, NULL, NULL);
631  gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (priv->tree_view),
632  1, wy2 -1, &path2,
633  NULL, NULL, NULL);
634  } else if (priv->icon_view) {
635  if (! gtk_widget_get_realized (priv->icon_view))
636  return;
637  if (! gtk_icon_view_get_visible_range (GTK_ICON_VIEW (priv->icon_view), &path, &path2))
638  return;
639  } else {
640  return;
641  }
642 
643  if (path && path2) {
644  update_visible_range (sidebar_thumbnails,
645  gtk_tree_path_get_indices (path)[0],
646  gtk_tree_path_get_indices (path2)[0]);
647  }
648 
649  gtk_tree_path_free (path);
650  gtk_tree_path_free (path2);
651 }

+ Here is the caller graph for this function:

static void cancel_running_jobs ( EvSidebarThumbnails sidebar_thumbnails,
gint  start_page,
gint  end_page 
)
static

Definition at line 436 of file ev-sidebar-thumbnails.c.

439 {
440  EvSidebarThumbnailsPrivate *priv = sidebar_thumbnails->priv;
441  GtkTreePath *path;
442  GtkTreeIter iter;
443  gboolean result;
444 
445  g_assert (start_page <= end_page);
446 
447  path = gtk_tree_path_new_from_indices (start_page, -1);
448  for (result = gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->list_store), &iter, path);
449  result && start_page <= end_page;
450  result = gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->list_store), &iter), start_page ++) {
451  EvJobThumbnail *job;
452  gboolean thumbnail_set;
453 
454  gtk_tree_model_get (GTK_TREE_MODEL (priv->list_store),
455  &iter,
456  COLUMN_JOB, &job,
457  COLUMN_THUMBNAIL_SET, &thumbnail_set,
458  -1);
459 
460  if (thumbnail_set) {
461  g_assert (job == NULL);
462  continue;
463  }
464 
465  if (job) {
466  g_signal_handlers_disconnect_by_func (job, thumbnail_job_completed_callback, sidebar_thumbnails);
467  ev_job_cancel (EV_JOB (job));
468  g_object_unref (job);
469  }
470 
471  gtk_list_store_set (priv->list_store, &iter,
472  COLUMN_JOB, NULL,
474  -1);
475  }
476  gtk_tree_path_free (path);
477 }

+ Here is the caller graph for this function:

static void ev_sidebar_fullscreen_cb ( EvSidebarThumbnails sidebar)
static

Definition at line 326 of file ev-sidebar-thumbnails.c.

327 {
328  /* After activating or deactivating fullscreen mode, the sidebar
329  * window is automatically moved to its start, while scroll bar
330  * stays in its original position.
331  *
332  * The sidebar window move is unwanted and unsolicited, and it's
333  * most probably caused by GtkIconView or GtkScrolledWindow bug.
334  *
335  * Workaround this by having the sidebar sync its window with the
336  * current scroll position after a fullscreen operation, do that by
337  * just emitting a "value-changed" on the current scroll adjustment.
338  * Fixes https://bugzilla.gnome.org/show_bug.cgi?id=783404 */
339  g_signal_emit_by_name (sidebar->priv->vadjustment, "value-changed");
340 }

+ Here is the caller graph for this function:

static void ev_sidebar_icon_selection_changed ( GtkIconView *  icon_view,
EvSidebarThumbnails ev_sidebar_thumbnails 
)
static

Definition at line 714 of file ev-sidebar-thumbnails.c.

716 {
717  EvSidebarThumbnailsPrivate *priv = ev_sidebar_thumbnails->priv;
718  GtkTreePath *path;
719  GList *selected;
720  int page;
721 
722  selected = gtk_icon_view_get_selected_items (icon_view);
723  if (selected == NULL)
724  return;
725 
726  /* We don't handle or expect multiple selection. */
727  g_assert (selected->next == NULL);
728 
729  path = selected->data;
730  page = gtk_tree_path_get_indices (path)[0];
731 
732  gtk_tree_path_free (path);
733  g_list_free (selected);
734 
735  ev_document_model_set_page (priv->model, page);
736 }

+ Here is the caller graph for this function:

static void ev_sidebar_init_icon_view ( EvSidebarThumbnails ev_sidebar_thumbnails)
static

Definition at line 768 of file ev-sidebar-thumbnails.c.

769 {
771  GtkCellRenderer *renderer;
772 
773  priv = ev_sidebar_thumbnails->priv;
774 
775  priv->icon_view = gtk_icon_view_new_with_model (GTK_TREE_MODEL (priv->list_store));
776 
777  renderer = g_object_new (GTK_TYPE_CELL_RENDERER_PIXBUF,
778  "xalign", 0.5,
779  "yalign", 1.0,
780  NULL);
781  gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (priv->icon_view), renderer, FALSE);
782  gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (priv->icon_view),
783  renderer, "surface", 1, NULL);
784 
785  renderer = g_object_new (GTK_TYPE_CELL_RENDERER_TEXT,
786  "alignment", PANGO_ALIGN_CENTER,
787  "wrap-mode", PANGO_WRAP_WORD_CHAR,
788  "xalign", 0.5,
789  "yalign", 0.0,
790  "width", THUMBNAIL_WIDTH,
791  "wrap-width", THUMBNAIL_WIDTH,
792  NULL);
793  gtk_cell_layout_pack_end (GTK_CELL_LAYOUT (priv->icon_view), renderer, FALSE);
794  gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (priv->icon_view),
795  renderer, "markup", 0, NULL);
796  g_signal_connect (priv->icon_view, "selection-changed",
797  G_CALLBACK (ev_sidebar_icon_selection_changed), ev_sidebar_thumbnails);
798 
799  gtk_container_add (GTK_CONTAINER (priv->swindow), priv->icon_view);
800  gtk_widget_show (priv->icon_view);
801 }

+ Here is the caller graph for this function:

static void ev_sidebar_init_tree_view ( EvSidebarThumbnails ev_sidebar_thumbnails)
static

Definition at line 739 of file ev-sidebar-thumbnails.c.

740 {
742  GtkTreeSelection *selection;
743  GtkCellRenderer *renderer;
744 
745  priv = ev_sidebar_thumbnails->priv;
746  priv->tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (priv->list_store));
747 
748  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree_view));
749  g_signal_connect (selection, "changed",
750  G_CALLBACK (ev_sidebar_tree_selection_changed), ev_sidebar_thumbnails);
751  gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->tree_view), FALSE);
752  renderer = g_object_new (GTK_TYPE_CELL_RENDERER_PIXBUF,
753  "xpad", 2,
754  "ypad", 2,
755  NULL);
756  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (priv->tree_view), -1,
757  NULL, renderer,
758  "surface", 1,
759  NULL);
760  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (priv->tree_view), -1,
761  NULL, gtk_cell_renderer_text_new (),
762  "markup", 0, NULL);
763  gtk_container_add (GTK_CONTAINER (priv->swindow), priv->tree_view);
764  gtk_widget_show (priv->tree_view);
765 }

+ Here is the caller graph for this function:

static void ev_sidebar_thumbnails_class_init ( EvSidebarThumbnailsClass ev_sidebar_thumbnails_class)
static

Definition at line 366 of file ev-sidebar-thumbnails.c.

367 {
368  GObjectClass *g_object_class;
369  GtkWidgetClass *widget_class;
370 
371  g_object_class = G_OBJECT_CLASS (ev_sidebar_thumbnails_class);
372  widget_class = GTK_WIDGET_CLASS (ev_sidebar_thumbnails_class);
373 
374  g_object_class->dispose = ev_sidebar_thumbnails_dispose;
375  g_object_class->get_property = ev_sidebar_thumbnails_get_property;
376  widget_class->map = ev_sidebar_thumbnails_map;
377  widget_class->size_allocate = ev_sidebar_thumbnails_size_allocate;
378 
379 #if GTK_CHECK_VERSION(3, 20, 0)
380  gtk_widget_class_set_css_name (widget_class, "evsidebarthumbnails");
381 #endif
382 
383  g_object_class_override_property (g_object_class,
384  PROP_WIDGET,
385  "main-widget");
386 
387  g_type_class_add_private (g_object_class, sizeof (EvSidebarThumbnailsPrivate));
388 }
static gboolean ev_sidebar_thumbnails_clear_job ( GtkTreeModel *  model,
GtkTreePath *  path,
GtkTreeIter *  iter,
gpointer  data 
)
static

Definition at line 1098 of file ev-sidebar-thumbnails.c.

1102 {
1103  EvJob *job;
1104 
1105  gtk_tree_model_get (model, iter, COLUMN_JOB, &job, -1);
1106 
1107  if (job != NULL) {
1108  ev_job_cancel (job);
1109  g_signal_handlers_disconnect_by_func (job, thumbnail_job_completed_callback, data);
1110  g_object_unref (job);
1111  }
1112 
1113  return FALSE;
1114 }

+ Here is the caller graph for this function:

static void ev_sidebar_thumbnails_clear_model ( EvSidebarThumbnails sidebar)
static

Definition at line 1117 of file ev-sidebar-thumbnails.c.

1118 {
1119  EvSidebarThumbnailsPrivate *priv = sidebar_thumbnails->priv;
1120 
1121  gtk_tree_model_foreach (GTK_TREE_MODEL (priv->list_store), ev_sidebar_thumbnails_clear_job, sidebar_thumbnails);
1122  gtk_list_store_clear (priv->list_store);
1123 }

+ Here is the caller graph for this function:

static void ev_sidebar_thumbnails_device_scale_factor_changed_cb ( EvSidebarThumbnails sidebar_thumbnails,
GParamSpec *  pspec 
)
static

Definition at line 812 of file ev-sidebar-thumbnails.c.

815 {
816  ev_sidebar_thumbnails_reload (sidebar_thumbnails);
817 }

+ Here is the caller graph for this function:

static void ev_sidebar_thumbnails_dispose ( GObject *  object)
static

Definition at line 274 of file ev-sidebar-thumbnails.c.

275 {
276  EvSidebarThumbnails *sidebar_thumbnails = EV_SIDEBAR_THUMBNAILS (object);
277 
278  if (sidebar_thumbnails->priv->loading_icons) {
279  g_hash_table_destroy (sidebar_thumbnails->priv->loading_icons);
280  sidebar_thumbnails->priv->loading_icons = NULL;
281  }
282 
283  if (sidebar_thumbnails->priv->list_store) {
284  ev_sidebar_thumbnails_clear_model (sidebar_thumbnails);
285  g_object_unref (sidebar_thumbnails->priv->list_store);
286  sidebar_thumbnails->priv->list_store = NULL;
287  }
288 
289  G_OBJECT_CLASS (ev_sidebar_thumbnails_parent_class)->dispose (object);
290 }

+ Here is the caller graph for this function:

static void ev_sidebar_thumbnails_document_changed_cb ( EvDocumentModel model,
GParamSpec *  pspec,
EvSidebarThumbnails sidebar_thumbnails 
)
static

Definition at line 1007 of file ev-sidebar-thumbnails.c.

1010 {
1011  EvDocument *document = ev_document_model_get_document (model);
1012  EvSidebarThumbnailsPrivate *priv = sidebar_thumbnails->priv;
1013 
1014  if (ev_document_get_n_pages (document) <= 0 ||
1015  !ev_document_check_dimensions (document)) {
1016  return;
1017  }
1018 
1019  priv->size_cache = ev_thumbnails_size_cache_get (document);
1020  priv->document = document;
1021  priv->n_pages = ev_document_get_n_pages (document);
1022  priv->rotation = ev_document_model_get_rotation (model);
1024  if (priv->loading_icons) {
1025  g_hash_table_remove_all (priv->loading_icons);
1026  } else {
1027  priv->loading_icons = g_hash_table_new_full (g_str_hash,
1028  g_str_equal,
1029  (GDestroyNotify)g_free,
1030  (GDestroyNotify)cairo_surface_destroy);
1031  }
1032 
1033  ev_sidebar_thumbnails_clear_model (sidebar_thumbnails);
1034  ev_sidebar_thumbnails_fill_model (sidebar_thumbnails);
1035 
1036  /* Create the view widget, and remove the old one, if needed */
1037  if (ev_sidebar_thumbnails_use_icon_view (sidebar_thumbnails)) {
1038  if (priv->tree_view) {
1039  gtk_container_remove (GTK_CONTAINER (priv->swindow), priv->tree_view);
1040  priv->tree_view = NULL;
1041  }
1042 
1043  if (! priv->icon_view) {
1044  ev_sidebar_init_icon_view (sidebar_thumbnails);
1045  g_object_notify (G_OBJECT (sidebar_thumbnails), "main_widget");
1046  } else {
1047  gtk_widget_queue_resize (priv->icon_view);
1048  }
1049  } else {
1050  if (priv->icon_view) {
1051  gtk_container_remove (GTK_CONTAINER (priv->swindow), priv->icon_view);
1052  priv->icon_view = NULL;
1053  }
1054 
1055  if (! priv->tree_view) {
1056  ev_sidebar_init_tree_view (sidebar_thumbnails);
1057  g_object_notify (G_OBJECT (sidebar_thumbnails), "main_widget");
1058  }
1059  }
1060 
1061  /* Connect to the signal and trigger a fake callback */
1062  g_signal_connect_swapped (priv->model, "page-changed",
1063  G_CALLBACK (page_changed_cb),
1064  sidebar_thumbnails);
1065  g_signal_connect (priv->model, "notify::rotation",
1067  sidebar_thumbnails);
1068  g_signal_connect (priv->model, "notify::inverted-colors",
1070  sidebar_thumbnails);
1071  g_signal_connect_swapped (priv->model, "notify::fullscreen",
1072  G_CALLBACK (ev_sidebar_fullscreen_cb),
1073  sidebar_thumbnails);
1074  sidebar_thumbnails->priv->start_page = -1;
1075  sidebar_thumbnails->priv->end_page = -1;
1076  ev_sidebar_thumbnails_set_current_page (sidebar_thumbnails,
1077  ev_document_model_get_page (model));
1078  adjustment_changed_cb (sidebar_thumbnails);
1079 }

+ Here is the caller graph for this function:

static void ev_sidebar_thumbnails_fill_model ( EvSidebarThumbnails sidebar_thumbnails)
static

Definition at line 654 of file ev-sidebar-thumbnails.c.

655 {
656  EvSidebarThumbnailsPrivate *priv = sidebar_thumbnails->priv;
657  GtkTreeIter iter;
658  int i;
659  gint prev_width = -1;
660  gint prev_height = -1;
661 
662  for (i = 0; i < sidebar_thumbnails->priv->n_pages; i++) {
663  gchar *page_label;
664  gchar *page_string;
665  cairo_surface_t *loading_icon = NULL;
666  gint width, height;
667 
668  page_label = ev_document_get_page_label (priv->document, i);
669  page_string = g_markup_printf_escaped ("<i>%s</i>", page_label);
670  ev_thumbnails_size_cache_get_size (sidebar_thumbnails->priv->size_cache, i,
671  sidebar_thumbnails->priv->rotation,
672  &width, &height);
673  if (!loading_icon || (width != prev_width && height != prev_height)) {
674  loading_icon =
675  ev_sidebar_thumbnails_get_loading_icon (sidebar_thumbnails,
676  width, height);
677  }
678 
679  prev_width = width;
680  prev_height = height;
681 
682  gtk_list_store_append (priv->list_store, &iter);
683  gtk_list_store_set (priv->list_store, &iter,
684  COLUMN_PAGE_STRING, page_string,
685  COLUMN_SURFACE, loading_icon,
687  -1);
688  g_free (page_label);
689  g_free (page_string);
690  }
691 }

+ Here is the caller graph for this function:

static const gchar * ev_sidebar_thumbnails_get_label ( EvSidebarPage sidebar_page)
static

Definition at line 1133 of file ev-sidebar-thumbnails.c.

1134 {
1135  return _("Thumbnails");
1136 }

+ Here is the caller graph for this function:

static cairo_surface_t* ev_sidebar_thumbnails_get_loading_icon ( EvSidebarThumbnails sidebar_thumbnails,
gint  width,
gint  height 
)
static

Definition at line 404 of file ev-sidebar-thumbnails.c.

407 {
408  EvSidebarThumbnailsPrivate *priv = sidebar_thumbnails->priv;
409  cairo_surface_t *icon;
410  gchar *key;
411 
412  key = g_strdup_printf ("%dx%d", width, height);
413  icon = g_hash_table_lookup (priv->loading_icons, key);
414  if (!icon) {
415  gboolean inverted_colors;
416  gint device_scale = 1;
417 
418 #ifdef HAVE_HIDPI_SUPPORT
419  device_scale = gtk_widget_get_scale_factor (GTK_WIDGET (sidebar_thumbnails));
420 #endif
421 
422  inverted_colors = ev_document_model_get_inverted_colors (priv->model);
423  icon = ev_document_misc_render_loading_thumbnail_surface (GTK_WIDGET (sidebar_thumbnails),
424  width * device_scale,
425  height * device_scale,
426  inverted_colors);
427  g_hash_table_insert (priv->loading_icons, key, icon);
428  } else {
429  g_free (key);
430  }
431 
432  return icon;
433 }

+ Here is the caller graph for this function:

static void ev_sidebar_thumbnails_get_property ( GObject *  object,
guint  prop_id,
GValue *  value,
GParamSpec *  pspec 
)
static

Definition at line 293 of file ev-sidebar-thumbnails.c.

297 {
298  EvSidebarThumbnails *sidebar = EV_SIDEBAR_THUMBNAILS (object);
299 
300  switch (prop_id) {
301  case PROP_WIDGET:
302  if (sidebar->priv->tree_view)
303  g_value_set_object (value, sidebar->priv->tree_view);
304  else
305  g_value_set_object (value, sidebar->priv->icon_view);
306  break;
307  default:
308  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
309  break;
310  }
311 }

+ Here is the caller graph for this function:

static void ev_sidebar_thumbnails_init ( EvSidebarThumbnails ev_sidebar_thumbnails)
static

Definition at line 836 of file ev-sidebar-thumbnails.c.

837 {
839  guint signal_id;
840 
841  priv = ev_sidebar_thumbnails->priv = EV_SIDEBAR_THUMBNAILS_GET_PRIVATE (ev_sidebar_thumbnails);
842 
843  priv->list_store = gtk_list_store_new (NUM_COLUMNS,
844  G_TYPE_STRING,
845  CAIRO_GOBJECT_TYPE_SURFACE,
846  G_TYPE_BOOLEAN,
848 
849  signal_id = g_signal_lookup ("row-changed", GTK_TYPE_TREE_MODEL);
850  g_signal_connect (GTK_TREE_MODEL (priv->list_store), "row-changed",
852  GUINT_TO_POINTER (signal_id));
853 
854  priv->swindow = gtk_scrolled_window_new (NULL, NULL);
855 
856  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (priv->swindow),
857  GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
858  priv->vadjustment = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (priv->swindow));
859  g_signal_connect_data (priv->vadjustment, "value-changed",
860  G_CALLBACK (adjustment_changed_cb),
861  ev_sidebar_thumbnails, NULL,
862  G_CONNECT_SWAPPED | G_CONNECT_AFTER);
863  g_signal_connect_swapped (priv->swindow, "size-allocate",
864  G_CALLBACK (adjustment_changed_cb),
865  ev_sidebar_thumbnails);
866  gtk_box_pack_start (GTK_BOX (ev_sidebar_thumbnails), priv->swindow, TRUE, TRUE, 0);
867 
868  g_signal_connect (ev_sidebar_thumbnails, "notify::scale-factor",
870 
871  /* Put it all together */
872  gtk_widget_show_all (priv->swindow);
873 }
static void ev_sidebar_thumbnails_inverted_colors_changed_cb ( EvDocumentModel model,
GParamSpec *  pspec,
EvSidebarThumbnails sidebar_thumbnails 
)
static

Definition at line 958 of file ev-sidebar-thumbnails.c.

961 {
962  gboolean inverted_colors = ev_document_model_get_inverted_colors (model);
963 
964  sidebar_thumbnails->priv->inverted_colors = inverted_colors;
965  ev_sidebar_thumbnails_reload (sidebar_thumbnails);
966 }

+ Here is the caller graph for this function:

static void ev_sidebar_thumbnails_map ( GtkWidget *  widget)
static

Definition at line 314 of file ev-sidebar-thumbnails.c.

315 {
316  EvSidebarThumbnails *sidebar;
317 
318  sidebar = EV_SIDEBAR_THUMBNAILS (widget);
319 
320  GTK_WIDGET_CLASS (ev_sidebar_thumbnails_parent_class)->map (widget);
321 
322  adjustment_changed_cb (sidebar);
323 }

+ Here is the caller graph for this function:

GtkWidget* ev_sidebar_thumbnails_new ( void  )

Definition at line 391 of file ev-sidebar-thumbnails.c.

392 {
393  GtkWidget *ev_sidebar_thumbnails;
394 
395  ev_sidebar_thumbnails = g_object_new (EV_TYPE_SIDEBAR_THUMBNAILS,
396  "orientation", GTK_ORIENTATION_VERTICAL,
397  NULL);
398 
399 
400  return ev_sidebar_thumbnails;
401 }

+ Here is the caller graph for this function:

static void ev_sidebar_thumbnails_page_iface_init ( EvSidebarPageInterface iface)
static
static gboolean ev_sidebar_thumbnails_page_is_in_visible_range ( EvSidebarThumbnails sidebar,
guint  page 
)
static

Definition at line 226 of file ev-sidebar-thumbnails.c.

228 {
229  GtkTreePath *path;
230  GtkTreePath *start, *end;
231  gboolean retval;
232 
233  if (sidebar->priv->tree_view) {
234  GtkTreeSelection *selection;
235  GtkTreeIter iter;
236 
237  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (sidebar->priv->tree_view));
238  if (!gtk_tree_selection_get_selected (selection, NULL, &iter))
239  return FALSE;
240 
241  path = gtk_tree_model_get_path (GTK_TREE_MODEL (sidebar->priv->list_store), &iter);
242  if (!gtk_tree_view_get_visible_range (GTK_TREE_VIEW (sidebar->priv->tree_view), &start, &end)) {
243  gtk_tree_path_free (path);
244  return FALSE;
245  }
246  } else {
247  GList *selection;
248 
249  selection = gtk_icon_view_get_selected_items (GTK_ICON_VIEW (sidebar->priv->icon_view));
250  if (!selection)
251  return FALSE;
252 
253  path = (GtkTreePath *)selection->data;
254 
255  /* We don't handle or expect multiple selection. */
256  g_assert (selection->next == NULL);
257  g_list_free (selection);
258 
259  if (!gtk_icon_view_get_visible_range (GTK_ICON_VIEW (sidebar->priv->icon_view), &start, &end)) {
260  gtk_tree_path_free (path);
261  return FALSE;
262  }
263  }
264 
265  retval = gtk_tree_path_compare (path, start) >= 0 && gtk_tree_path_compare (path, end) <= 0;
266  gtk_tree_path_free (path);
267  gtk_tree_path_free (start);
268  gtk_tree_path_free (end);
269 
270  return retval;
271 }

+ Here is the caller graph for this function:

static void ev_sidebar_thumbnails_reload ( EvSidebarThumbnails sidebar_thumbnails)
static

Definition at line 922 of file ev-sidebar-thumbnails.c.

923 {
924  EvDocumentModel *model;
925 
926  if (sidebar_thumbnails->priv->loading_icons)
927  g_hash_table_remove_all (sidebar_thumbnails->priv->loading_icons);
928 
929  if (sidebar_thumbnails->priv->document == NULL ||
930  sidebar_thumbnails->priv->n_pages <= 0)
931  return;
932 
933  model = sidebar_thumbnails->priv->model;
934 
935  ev_sidebar_thumbnails_clear_model (sidebar_thumbnails);
936  ev_sidebar_thumbnails_fill_model (sidebar_thumbnails);
937 
938  /* Trigger a redraw */
939  sidebar_thumbnails->priv->start_page = -1;
940  sidebar_thumbnails->priv->end_page = -1;
941  ev_sidebar_thumbnails_set_current_page (sidebar_thumbnails,
943  g_idle_add ((GSourceFunc)refresh, sidebar_thumbnails);
944 }

+ Here is the caller graph for this function:

static void ev_sidebar_thumbnails_rotation_changed_cb ( EvDocumentModel model,
GParamSpec *  pspec,
EvSidebarThumbnails sidebar_thumbnails 
)
static

Definition at line 947 of file ev-sidebar-thumbnails.c.

950 {
951  gint rotation = ev_document_model_get_rotation (model);
952 
953  sidebar_thumbnails->priv->rotation = rotation;
954  ev_sidebar_thumbnails_reload (sidebar_thumbnails);
955 }

+ Here is the caller graph for this function:

static void ev_sidebar_thumbnails_row_changed ( GtkTreeModel *  model,
GtkTreePath *  path,
GtkTreeIter *  iter,
gpointer  data 
)
static

Definition at line 820 of file ev-sidebar-thumbnails.c.

824 {
825  guint signal_id;
826 
827  signal_id = GPOINTER_TO_UINT (data);
828 
829  /* PREVENT GtkIconView "row-changed" handler to be reached, as it will
830  * perform a full invalidate and relayout of all items, See bug:
831  * https://bugzilla.gnome.org/show_bug.cgi?id=691448#c9 */
832  g_signal_stop_emission (model, signal_id, 0);
833 }

+ Here is the caller graph for this function:

static void ev_sidebar_thumbnails_set_current_page ( EvSidebarThumbnails sidebar,
gint  page 
)
static

Definition at line 876 of file ev-sidebar-thumbnails.c.

878 {
879  GtkTreeView *tree_view;
880  GtkTreePath *path;
881 
882  path = gtk_tree_path_new_from_indices (page, -1);
883 
884  if (sidebar->priv->tree_view) {
885  tree_view = GTK_TREE_VIEW (sidebar->priv->tree_view);
886  gtk_tree_view_set_cursor (tree_view, path, NULL, FALSE);
887  gtk_tree_view_scroll_to_cell (tree_view, path, NULL, FALSE, 0.0, 0.0);
888  } else if (sidebar->priv->icon_view) {
889 
890  g_signal_handlers_block_by_func
891  (sidebar->priv->icon_view,
892  G_CALLBACK (ev_sidebar_icon_selection_changed), sidebar);
893 
894  gtk_icon_view_select_path (GTK_ICON_VIEW (sidebar->priv->icon_view), path);
895 
896  g_signal_handlers_unblock_by_func
897  (sidebar->priv->icon_view,
898  G_CALLBACK (ev_sidebar_icon_selection_changed), sidebar);
899 
900  gtk_icon_view_scroll_to_path (GTK_ICON_VIEW (sidebar->priv->icon_view), path, FALSE, 0.0, 0.0);
901  }
902 
903  gtk_tree_path_free (path);
904 }

+ Here is the caller graph for this function:

static void ev_sidebar_thumbnails_set_model ( EvSidebarPage sidebar_page,
EvDocumentModel model 
)
static

Definition at line 1082 of file ev-sidebar-thumbnails.c.

1084 {
1085  EvSidebarThumbnails *sidebar_thumbnails = EV_SIDEBAR_THUMBNAILS (sidebar_page);
1086  EvSidebarThumbnailsPrivate *priv = sidebar_thumbnails->priv;
1087 
1088  if (priv->model == model)
1089  return;
1090 
1091  priv->model = model;
1092  g_signal_connect (model, "notify::document",
1094  sidebar_page);
1095 }

+ Here is the caller graph for this function:

static void ev_sidebar_thumbnails_size_allocate ( GtkWidget *  widget,
GtkAllocation *  allocation 
)
static

Definition at line 343 of file ev-sidebar-thumbnails.c.

345 {
346  EvSidebarThumbnails *sidebar = EV_SIDEBAR_THUMBNAILS (widget);
347 
348  GTK_WIDGET_CLASS (ev_sidebar_thumbnails_parent_class)->size_allocate (widget, allocation);
349 
350  if (allocation->width != sidebar->priv->width) {
351  guint page;
352 
353  sidebar->priv->width = allocation->width;
354 
355  /* Might have a new number of columns, reset current page */
356  if (!sidebar->priv->model)
357  return;
358 
359  page = ev_document_model_get_page (sidebar->priv->model);
362  }
363 }

+ Here is the caller graph for this function:

static gboolean ev_sidebar_thumbnails_support_document ( EvSidebarPage sidebar_page,
EvDocument document 
)
static

Definition at line 1126 of file ev-sidebar-thumbnails.c.

1128 {
1129  return TRUE;
1130 }

+ Here is the caller graph for this function:

static gboolean ev_sidebar_thumbnails_use_icon_view ( EvSidebarThumbnails sidebar_thumbnails)
static

Definition at line 804 of file ev-sidebar-thumbnails.c.

805 {
806  EvSidebarThumbnailsPrivate *priv = sidebar_thumbnails->priv;
807 
809 }

+ Here is the caller graph for this function:

static void ev_sidebar_tree_selection_changed ( GtkTreeSelection *  selection,
EvSidebarThumbnails ev_sidebar_thumbnails 
)
static

Definition at line 694 of file ev-sidebar-thumbnails.c.

696 {
697  EvSidebarThumbnailsPrivate *priv = ev_sidebar_thumbnails->priv;
698  GtkTreePath *path;
699  GtkTreeIter iter;
700  int page;
701 
702  if (!gtk_tree_selection_get_selected (selection, NULL, &iter))
703  return;
704 
705  path = gtk_tree_model_get_path (GTK_TREE_MODEL (priv->list_store),
706  &iter);
707  page = gtk_tree_path_get_indices (path)[0];
708  gtk_tree_path_free (path);
709 
710  ev_document_model_set_page (priv->model, page);
711 }

+ Here is the caller graph for this function:

static void ev_thumbnails_size_cache_free ( EvThumbsSizeCache cache)
static

Definition at line 198 of file ev-sidebar-thumbnails.c.

199 {
200  if (cache->sizes) {
201  g_free (cache->sizes);
202  cache->sizes = NULL;
203  }
204 
205  g_free (cache);
206 }

+ Here is the caller graph for this function:

static EvThumbsSizeCache* ev_thumbnails_size_cache_get ( EvDocument document)
static

Definition at line 209 of file ev-sidebar-thumbnails.c.

210 {
211  EvThumbsSizeCache *cache;
212 
213  cache = g_object_get_data (G_OBJECT (document), EV_THUMBNAILS_SIZE_CACHE_KEY);
214  if (!cache) {
215  cache = ev_thumbnails_size_cache_new (document);
216  g_object_set_data_full (G_OBJECT (document),
217  EV_THUMBNAILS_SIZE_CACHE_KEY,
218  cache,
219  (GDestroyNotify)ev_thumbnails_size_cache_free);
220  }
221 
222  return cache;
223 }

+ Here is the caller graph for this function:

static void ev_thumbnails_size_cache_get_size ( EvThumbsSizeCache cache,
gint  page,
gint  rotation,
gint *  width,
gint *  height 
)
static

Definition at line 168 of file ev-sidebar-thumbnails.c.

173 {
174  gint w, h;
175 
176  if (cache->uniform) {
177  w = cache->uniform_width;
178  h = cache->uniform_height;
179  } else {
180  EvThumbsSize *thumb_size;
181 
182  thumb_size = &(cache->sizes[page]);
183 
184  w = thumb_size->width;
185  h = thumb_size->height;
186  }
187 
188  if (rotation == 0 || rotation == 180) {
189  if (width) *width = w;
190  if (height) *height = h;
191  } else {
192  if (width) *width = h;
193  if (height) *height = w;
194  }
195 }

+ Here is the caller graph for this function:

static EvThumbsSizeCache* ev_thumbnails_size_cache_new ( EvDocument document)
static

Definition at line 138 of file ev-sidebar-thumbnails.c.

139 {
140  EvThumbsSizeCache *cache;
141  gint i, n_pages;
142  EvThumbsSize *thumb_size;
143 
144  cache = g_new0 (EvThumbsSizeCache, 1);
145 
146  if (ev_document_is_page_size_uniform (document)) {
147  cache->uniform = TRUE;
148  get_thumbnail_size_for_page (document, 0,
149  &cache->uniform_width,
150  &cache->uniform_height);
151  return cache;
152  }
153 
154  n_pages = ev_document_get_n_pages (document);
155  cache->sizes = g_new0 (EvThumbsSize, n_pages);
156 
157  for (i = 0; i < n_pages; i++) {
158  thumb_size = &(cache->sizes[i]);
159  get_thumbnail_size_for_page (document, i,
160  &thumb_size->width,
161  &thumb_size->height);
162  }
163 
164  return cache;
165 }

+ Here is the caller graph for this function:

G_DEFINE_TYPE_EXTENDED ( EvSidebarThumbnails  ,
ev_sidebar_thumbnails  ,
GTK_TYPE_BOX  ,
,
G_IMPLEMENT_INTERFACE(EV_TYPE_SIDEBAR_PAGE,ev_sidebar_thumbnails_page_iface_init  
)

Definition at line 108 of file ev-sidebar-thumbnails.c.

126 {
127  gdouble scale;
128  gdouble w, h;
129 
130  ev_document_get_page_size (document, page, &w, &h);
131  scale = (gdouble)THUMBNAIL_WIDTH / w;
132 
133  *width = MAX ((gint)(w * scale + 0.5), 1);
134  *height = MAX ((gint)(h * scale + 0.5), 1);
135 }
static void get_size_for_page ( EvSidebarThumbnails sidebar_thumbnails,
gint  page,
gint *  width_return,
gint *  height_return 
)
static

Definition at line 480 of file ev-sidebar-thumbnails.c.

484 {
485  EvSidebarThumbnailsPrivate *priv = sidebar_thumbnails->priv;
486  gdouble width, height;
487  gint thumbnail_height;
488  gint device_scale = 1;
489 
490 #ifdef HAVE_HIDPI_SUPPORT
491  device_scale = gtk_widget_get_scale_factor (GTK_WIDGET (sidebar_thumbnails));
492 #endif
493  ev_document_get_page_size (priv->document, page, &width, &height);
494  thumbnail_height = (int)(THUMBNAIL_WIDTH * height / width + 0.5);
495 
496  if (priv->rotation == 90 || priv->rotation == 270) {
497  *width_return = thumbnail_height * device_scale;
498  *height_return = THUMBNAIL_WIDTH * device_scale;
499  } else {
500  *width_return = THUMBNAIL_WIDTH * device_scale;
501  *height_return = thumbnail_height * device_scale;
502  }
503 }

+ Here is the caller graph for this function:

static void page_changed_cb ( EvSidebarThumbnails sidebar,
gint  old_page,
gint  new_page 
)
static

Definition at line 907 of file ev-sidebar-thumbnails.c.

910 {
911  ev_sidebar_thumbnails_set_current_page (sidebar, new_page);
912 }

+ Here is the caller graph for this function:

static gboolean refresh ( EvSidebarThumbnails sidebar_thumbnails)
static

Definition at line 915 of file ev-sidebar-thumbnails.c.

916 {
917  adjustment_changed_cb (sidebar_thumbnails);
918  return FALSE;
919 }

+ Here is the caller graph for this function:

static void thumbnail_job_completed_callback ( EvJobThumbnail job,
EvSidebarThumbnails sidebar_thumbnails 
)
static

Definition at line 969 of file ev-sidebar-thumbnails.c.

971 {
972  GtkWidget *widget = GTK_WIDGET (sidebar_thumbnails);
973  EvSidebarThumbnailsPrivate *priv = sidebar_thumbnails->priv;
974  GtkTreeIter *iter;
975  cairo_surface_t *surface;
976 #ifdef HAVE_HIDPI_SUPPORT
977  gint device_scale;
978 #endif
979 
980  if (ev_job_is_failed (EV_JOB (job)))
981  return;
982 
983 #ifdef HAVE_HIDPI_SUPPORT
984  device_scale = gtk_widget_get_scale_factor (widget);
985  cairo_surface_set_device_scale (job->thumbnail_surface, device_scale, device_scale);
986 #endif
987 
989  job->thumbnail_surface,
990  -1, -1);
991 
992  iter = (GtkTreeIter *) g_object_get_data (G_OBJECT (job), "tree_iter");
993  if (priv->inverted_colors)
995  gtk_list_store_set (priv->list_store,
996  iter,
997  COLUMN_SURFACE, surface,
999  COLUMN_JOB, NULL,
1000  -1);
1001  cairo_surface_destroy (surface);
1002 
1003  gtk_widget_queue_draw (priv->icon_view);
1004 }

+ Here is the caller graph for this function:

static void update_visible_range ( EvSidebarThumbnails sidebar_thumbnails,
gint  start_page,
gint  end_page 
)
static

Definition at line 561 of file ev-sidebar-thumbnails.c.

564 {
565  EvSidebarThumbnailsPrivate *priv = sidebar_thumbnails->priv;
566  int old_start_page, old_end_page;
567  int n_pages_in_visible_range;
568 
569  /* Preload before and after current visible scrolling range, the same amount of
570  * thumbs in it, to help prevent thumbnail creation happening in the user's sight.
571  * https://bugzilla.gnome.org/show_bug.cgi?id=342110#c15 */
572  n_pages_in_visible_range = (end_page - start_page) + 1;
573  start_page = MAX (0, start_page - n_pages_in_visible_range);
574  end_page = MIN (priv->n_pages - 1, end_page + n_pages_in_visible_range);
575 
576  old_start_page = priv->start_page;
577  old_end_page = priv->end_page;
578 
579  if (start_page == old_start_page &&
580  end_page == old_end_page)
581  return;
582 
583  /* Clear the areas we no longer display */
584  if (old_start_page >= 0 && old_start_page < start_page)
585  cancel_running_jobs (sidebar_thumbnails, old_start_page, MIN (start_page - 1, old_end_page));
586 
587  if (old_end_page > 0 && old_end_page > end_page)
588  cancel_running_jobs (sidebar_thumbnails, MAX (end_page + 1, old_start_page), old_end_page);
589 
590  add_range (sidebar_thumbnails, start_page, end_page);
591 
592  priv->start_page = start_page;
593  priv->end_page = end_page;
594 }

+ Here is the caller graph for this function: