]> www.fi.muni.cz Git - evince.git/blob - shell/ev-sidebar-thumbnails.c
bypass GDKSplashOutputDev and just use a normal SplashOutputDev. Speeds
[evince.git] / shell / ev-sidebar-thumbnails.c
1 /* this file is part of evince, a gnome document viewer
2  *
3  *  Copyright (C) 2004 Red Hat, Inc.
4  *  Copyright (C) 2004 Anders Carlsson <andersca@gnome.org>
5  *
6  *  Authors:
7  *    Jonathan Blandford <jrb@alum.mit.edu>
8  *    Anders Carlsson <andersca@gnome.org>
9  *
10  * Evince is free software; you can redistribute it and/or modify it
11  * under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * Evince is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include <string.h>
30 #include <gtk/gtk.h>
31
32 #include "ev-sidebar-thumbnails.h"
33 #include "ev-document-thumbnails.h"
34 #include "ev-utils.h"
35
36 #define THUMBNAIL_WIDTH 75
37 /* Amount of time we devote to each iteration of the idle, in microseconds */
38 #define IDLE_WORK_LENGTH 5000
39
40 struct _EvSidebarThumbnailsPrivate {
41         GtkWidget *tree_view;
42         GtkListStore *list_store;
43         EvDocument *document;
44         
45         guint idle_id;
46         gint current_page, n_pages;
47 };
48
49 enum {
50         COLUMN_PAGE_STRING,
51         COLUMN_PIXBUF,
52         NUM_COLUMNS
53 };
54
55 static GtkVBoxClass *parent_class;
56
57 G_DEFINE_TYPE (EvSidebarThumbnails, ev_sidebar_thumbnails, GTK_TYPE_VBOX);
58
59 #define EV_SIDEBAR_THUMBNAILS_GET_PRIVATE(object) \
60         (G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_SIDEBAR_THUMBNAILS, EvSidebarThumbnailsPrivate));
61
62 static void
63 ev_sidebar_thumbnails_destroy (GtkObject *object)
64 {
65         EvSidebarThumbnails *ev_sidebar_thumbnails = EV_SIDEBAR_THUMBNAILS (object);
66         EvSidebarThumbnailsPrivate *priv = ev_sidebar_thumbnails->priv;
67         
68         if (priv->idle_id != 0) {
69                 g_source_remove (priv->idle_id);
70
71                 priv->idle_id = 0;
72         }
73         
74         GTK_OBJECT_CLASS (parent_class)->destroy (object);
75 }
76
77 static void
78 ev_sidebar_thumbnails_class_init (EvSidebarThumbnailsClass *ev_sidebar_thumbnails_class)
79 {
80         GObjectClass *g_object_class;
81         GtkObjectClass *gtk_object_class;
82         
83         g_object_class = G_OBJECT_CLASS (ev_sidebar_thumbnails_class);
84         gtk_object_class = GTK_OBJECT_CLASS (ev_sidebar_thumbnails_class);
85
86         parent_class = g_type_class_peek_parent (ev_sidebar_thumbnails_class);
87         
88         gtk_object_class->destroy = ev_sidebar_thumbnails_destroy;
89         
90         g_type_class_add_private (g_object_class, sizeof (EvSidebarThumbnailsPrivate));
91
92 }
93
94 static void
95 ev_sidebar_thumbnails_init (EvSidebarThumbnails *ev_sidebar_thumbnails)
96 {
97         GtkWidget *swindow;
98         EvSidebarThumbnailsPrivate *priv;
99         GtkCellRenderer *renderer;
100
101         priv = ev_sidebar_thumbnails->priv = EV_SIDEBAR_THUMBNAILS_GET_PRIVATE (ev_sidebar_thumbnails);
102
103         priv->list_store = gtk_list_store_new (NUM_COLUMNS, G_TYPE_STRING, GDK_TYPE_PIXBUF);
104         priv->tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (priv->list_store));
105
106         gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->tree_view), FALSE);
107         renderer = g_object_new (GTK_TYPE_CELL_RENDERER_PIXBUF,
108                                  "xpad", 2,
109                                  "ypad", 2,
110                                  NULL);
111         gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (priv->tree_view), -1,
112                                                      NULL, renderer,
113                                                      "pixbuf", 1,
114                                                      NULL);
115         gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (priv->tree_view), -1,
116                                                      NULL, gtk_cell_renderer_text_new (),
117                                                      "markup", 0, NULL);
118         
119         g_object_unref (priv->list_store);
120
121         swindow = gtk_scrolled_window_new (NULL, NULL);
122         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow),
123                                         GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
124         gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swindow),
125                                              GTK_SHADOW_IN);
126
127         gtk_container_add (GTK_CONTAINER (swindow), priv->tree_view);
128         gtk_box_pack_start (GTK_BOX (ev_sidebar_thumbnails), swindow, TRUE, TRUE, 0);
129         
130         gtk_widget_show_all (swindow);
131 }
132
133 GtkWidget *
134 ev_sidebar_thumbnails_new (void)
135 {
136         GtkWidget *ev_sidebar_thumbnails;
137
138         ev_sidebar_thumbnails = g_object_new (EV_TYPE_SIDEBAR_THUMBNAILS, NULL);
139
140         return ev_sidebar_thumbnails;
141 }
142
143 static gboolean
144 do_one_iteration (EvSidebarThumbnails *ev_sidebar_thumbnails)
145 {
146         EvSidebarThumbnailsPrivate *priv = ev_sidebar_thumbnails->priv;
147         GdkPixbuf *pixbuf;
148         GtkTreePath *path;
149         GtkTreeIter iter;
150
151         pixbuf = ev_document_thumbnails_get_thumbnail (EV_DOCUMENT_THUMBNAILS (priv->document),
152                                                        priv->current_page, THUMBNAIL_WIDTH);
153
154         path = gtk_tree_path_new_from_indices (priv->current_page, -1);
155         gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->list_store), &iter, path);
156         gtk_tree_path_free (path);
157
158         gtk_list_store_set (priv->list_store, &iter,
159                             COLUMN_PIXBUF, pixbuf,
160                             -1);
161
162         g_object_unref (pixbuf);
163         
164         priv->current_page++;
165         
166         if (priv->current_page == priv->n_pages)
167                 return FALSE;
168         else
169                 return TRUE;
170 }
171
172 static gboolean
173 populate_thumbnails_idle (gpointer data)
174 {
175         GTimer *timer;
176         int i;
177         gdouble time_elapsed = 0;
178
179         EvSidebarThumbnails *ev_sidebar_thumbnails = EV_SIDEBAR_THUMBNAILS (data);
180         EvSidebarThumbnailsPrivate *priv = ev_sidebar_thumbnails->priv;
181
182
183 #if PROFILE_THUMB == 1
184         static GTimer *total_timer;
185         static gboolean first_time = TRUE;
186
187         if (first_time) {
188                 total_timer = g_timer_new ();
189                 first_time = FALSE;
190                 g_timer_start (total_timer);
191         }
192 #endif
193
194         if (priv->current_page == priv->n_pages) {
195                 priv->idle_id = 0;
196 #if PROFILE_THUMB == 1
197                 time_elapsed = g_timer_elapsed (total_timer, NULL);
198                 g_timer_destroy (total_timer);
199                 g_print ("%d rows done in %f seconds\n",
200                          gtk_tree_model_iter_n_children (GTK_TREE_MODEL (priv->list_store), NULL),
201                          time_elapsed);
202 #endif
203                 return FALSE;
204         }
205
206         timer = g_timer_new ();
207         i = 0;
208         g_timer_start (timer);
209         while (do_one_iteration (ev_sidebar_thumbnails)) {
210                 i++;
211                 time_elapsed = g_timer_elapsed (timer, NULL);
212                 if (time_elapsed > IDLE_WORK_LENGTH/1000000)
213                         break;
214         }
215         g_timer_destroy (timer);
216 #if PROFILE_THUMB == 2
217         g_print ("%d rows done this idle in %f seconds\n", i, time_elapsed);
218 #endif
219
220         return TRUE;
221 }
222
223 void
224 ev_sidebar_thumbnails_set_document (EvSidebarThumbnails *sidebar_thumbnails,
225                                     EvDocument          *document)
226 {
227         GtkIconTheme *theme;
228         GdkPixbuf *loading_icon;
229         gint i, n_pages;
230         EvSidebarThumbnailsPrivate *priv = sidebar_thumbnails->priv;
231         
232         g_return_if_fail (EV_IS_DOCUMENT_THUMBNAILS (document));
233
234         if (priv->idle_id != 0) {
235                 g_source_remove (priv->idle_id);
236         }
237         
238         theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (sidebar_thumbnails)));
239
240         loading_icon = gtk_icon_theme_load_icon (theme, "gnome-fs-loading-icon",
241                                                  THUMBNAIL_WIDTH, 0, NULL);
242
243         n_pages = ev_document_get_n_pages (document);
244         
245         for (i = 0; i < n_pages; i++) {
246                 GtkTreeIter iter;
247                 gchar *page;
248
249                 page = g_strdup_printf ("<i>%d</i>", i + 1);
250                 gtk_list_store_append (sidebar_thumbnails->priv->list_store,
251                                        &iter);
252                 gtk_list_store_set (sidebar_thumbnails->priv->list_store,
253                                     &iter,
254                                     COLUMN_PAGE_STRING, page,
255                                     COLUMN_PIXBUF, loading_icon,
256                                     -1);
257                 g_free (page);
258         }
259
260         priv->document = document;
261         priv->idle_id = g_idle_add (populate_thumbnails_idle, sidebar_thumbnails);
262         priv->n_pages = n_pages;
263         priv->current_page = 0;
264 }
265