]> www.fi.muni.cz Git - evince.git/blob - shell/ev-sidebar-thumbnails.c
move the thumbnail code into a time-based idle as well. Also, turn off the
[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 96
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
100         priv = ev_sidebar_thumbnails->priv = EV_SIDEBAR_THUMBNAILS_GET_PRIVATE (ev_sidebar_thumbnails);
101
102         priv->list_store = gtk_list_store_new (NUM_COLUMNS, G_TYPE_STRING, GDK_TYPE_PIXBUF);
103         priv->tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (priv->list_store));
104
105         gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->tree_view), FALSE);
106         gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (priv->tree_view), -1,
107                                                      NULL, gtk_cell_renderer_pixbuf_new (),
108                                                      "pixbuf", 1, NULL);
109         gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (priv->tree_view), -1,
110                                                      NULL, gtk_cell_renderer_text_new (),
111                                                      "text", 0, NULL);
112         
113         g_object_unref (priv->list_store);
114
115         swindow = gtk_scrolled_window_new (NULL, NULL);
116         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow),
117                                         GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
118         gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swindow),
119                                              GTK_SHADOW_IN);
120
121         gtk_container_add (GTK_CONTAINER (swindow), priv->tree_view);
122         gtk_box_pack_start (GTK_BOX (ev_sidebar_thumbnails), swindow, TRUE, TRUE, 0);
123         
124         gtk_widget_show_all (swindow);
125 }
126
127 GtkWidget *
128 ev_sidebar_thumbnails_new (void)
129 {
130         GtkWidget *ev_sidebar_thumbnails;
131
132         ev_sidebar_thumbnails = g_object_new (EV_TYPE_SIDEBAR_THUMBNAILS, NULL);
133
134         return ev_sidebar_thumbnails;
135 }
136
137 static gboolean
138 do_one_iteration (EvSidebarThumbnails *ev_sidebar_thumbnails)
139 {
140         EvSidebarThumbnailsPrivate *priv = ev_sidebar_thumbnails->priv;
141         GdkPixbuf *tmp, *pixbuf;
142         GtkTreePath *path;
143         GtkTreeIter iter;
144
145         tmp = ev_document_thumbnails_get_thumbnail (EV_DOCUMENT_THUMBNAILS (priv->document),
146                                                        priv->current_page, THUMBNAIL_WIDTH);
147
148 #if 1
149         /* Don't add the shadow for now, as it's really slow */
150         pixbuf = g_object_ref (tmp);
151 #else
152         /* Add shadow */
153         pixbuf = ev_pixbuf_add_shadow (tmp, 5, 0, 0, 0.5);
154 #endif
155         path = gtk_tree_path_new_from_indices (priv->current_page, -1);
156         gtk_tree_model_get_iter (GTK_TREE_MODEL (priv->list_store), &iter, path);
157         gtk_tree_path_free (path);
158
159         gtk_list_store_set (priv->list_store, &iter,
160                             COLUMN_PIXBUF, pixbuf,
161                             -1);
162
163         g_object_unref (tmp);
164         g_object_unref (pixbuf);
165         
166         priv->current_page++;
167         
168         if (priv->current_page == priv->n_pages)
169                 return FALSE;
170         else
171                 return TRUE;
172 }
173
174 static gboolean
175 populate_thumbnails_idle (gpointer data)
176 {
177         GTimer *timer;
178         gint i;
179         gulong microseconds = 0;
180
181         EvSidebarThumbnails *ev_sidebar_thumbnails = EV_SIDEBAR_THUMBNAILS (data);
182         EvSidebarThumbnailsPrivate *priv = ev_sidebar_thumbnails->priv;
183
184         if (priv->current_page == priv->n_pages) {
185                 priv->idle_id = 0;
186                 return FALSE;
187         }
188
189         timer = g_timer_new ();
190         i = 0;
191         g_timer_start (timer);
192         while (do_one_iteration (ev_sidebar_thumbnails)) {
193                 i++;
194                 g_timer_elapsed (timer, &microseconds);
195                 if (microseconds > IDLE_WORK_LENGTH)
196                         break;
197         }
198         g_timer_destroy (timer);
199 #if 1
200         g_print ("%d rows done this idle in %d\n", i, (int)microseconds);
201 #endif
202
203         return TRUE;
204 }
205
206 void
207 ev_sidebar_thumbnails_set_document (EvSidebarThumbnails *sidebar_thumbnails,
208                                     EvDocument          *document)
209 {
210         GtkIconTheme *theme;
211         GdkPixbuf *loading_icon;
212         gint i, n_pages;
213         EvSidebarThumbnailsPrivate *priv = sidebar_thumbnails->priv;
214         
215         g_return_if_fail (EV_IS_DOCUMENT_THUMBNAILS (document));
216
217         if (priv->idle_id != 0) {
218                 g_source_remove (priv->idle_id);
219         }
220         
221         theme = gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (sidebar_thumbnails)));
222
223         loading_icon = gtk_icon_theme_load_icon (theme, "gnome-fs-loading-icon",
224                                                  THUMBNAIL_WIDTH, 0, NULL);
225
226         n_pages = ev_document_get_n_pages (document);
227         
228         for (i = 0; i < n_pages; i++) {
229                 GtkTreeIter iter;
230                 gchar *page;
231
232                 page = g_strdup_printf ("Page %d", i + 1);
233                 gtk_list_store_append (sidebar_thumbnails->priv->list_store,
234                                        &iter);
235                 gtk_list_store_set (sidebar_thumbnails->priv->list_store,
236                                     &iter,
237                                     COLUMN_PAGE_STRING, page,
238                                     COLUMN_PIXBUF, loading_icon,
239                                     -1);
240                 g_free (page);
241         }
242
243         priv->document = document;
244         priv->idle_id = g_idle_add (populate_thumbnails_idle, sidebar_thumbnails);
245         priv->n_pages = n_pages;
246         priv->current_page = 0;
247 }
248