]> www.fi.muni.cz Git - evince.git/blob - shell/ev-sidebar-attachments.c
More #include cleanups. Again: reordering, single gtk.h includes and other
[evince.git] / shell / ev-sidebar-attachments.c
1 /* ev-sidebar-attachments.c
2  *  this file is part of evince, a gnome document viewer
3  *
4  * Copyright (C) 2006 Carlos Garcia Campos
5  *
6  * Author:
7  *   Carlos Garcia Campos <carlosgc@gnome.org>
8  *
9  * Evince is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Evince is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include <string.h>
29
30 #include <glib/gi18n.h>
31 #include <glib/gstdio.h>
32 #include <gtk/gtk.h>
33
34 #include "ev-file-helpers.h"
35 #include "ev-sidebar-attachments.h"
36 #include "ev-sidebar-page.h"
37
38 enum {
39         COLUMN_ICON,
40         COLUMN_NAME,
41         COLUMN_DESCRIPTION,
42         COLUMN_ATTACHMENT,
43         N_COLS
44 };
45
46 enum {
47         PROP_0,
48         PROP_WIDGET,
49 };
50
51 enum {
52         SIGNAL_POPUP_MENU,
53         N_SIGNALS
54 };
55
56 static const GtkTargetEntry drag_targets[] = {
57         { "text/uri-list", 0, 0 }
58 };
59
60 static guint signals[N_SIGNALS];
61
62 struct _EvSidebarAttachmentsPrivate {
63         GtkWidget      *icon_view;
64         GtkListStore   *model;
65
66         /* Icons */
67         GtkIconTheme   *icon_theme;
68         GHashTable     *icon_cache;
69 };
70
71 static void ev_sidebar_attachments_page_iface_init (EvSidebarPageIface *iface);
72
73 G_DEFINE_TYPE_EXTENDED (EvSidebarAttachments,
74                         ev_sidebar_attachments,
75                         GTK_TYPE_VBOX,
76                         0, 
77                         G_IMPLEMENT_INTERFACE (EV_TYPE_SIDEBAR_PAGE, 
78                                                ev_sidebar_attachments_page_iface_init))
79
80 #define EV_SIDEBAR_ATTACHMENTS_GET_PRIVATE(object) \
81                 (G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_SIDEBAR_ATTACHMENTS, EvSidebarAttachmentsPrivate))
82
83 /* Icon cache */
84 static void
85 ev_sidebar_attachments_icon_cache_add (EvSidebarAttachments *ev_attachbar,
86                                        const gchar          *mime_type,
87                                        const GdkPixbuf      *pixbuf)
88 {
89         g_assert (mime_type != NULL);
90         g_assert (GDK_IS_PIXBUF (pixbuf));
91
92         g_hash_table_insert (ev_attachbar->priv->icon_cache,
93                              (gpointer)g_strdup (mime_type),
94                              (gpointer)pixbuf);
95                              
96 }
97
98 static GdkPixbuf *
99 icon_theme_get_pixbuf_from_mime_type (GtkIconTheme *icon_theme,
100                                       const gchar  *mime_type)
101 {
102         const char *separator;
103         GString *icon_name;
104         GdkPixbuf *pixbuf;
105
106         separator = strchr (mime_type, '/');
107         if (!separator)
108                 return NULL; /* maybe we should return a GError with "invalid MIME-type" */
109
110         icon_name = g_string_new ("gnome-mime-");
111         g_string_append_len (icon_name, mime_type, separator - mime_type);
112         g_string_append_c (icon_name, '-');
113         g_string_append (icon_name, separator + 1);
114         pixbuf = gtk_icon_theme_load_icon (icon_theme, icon_name->str, 48, 0, NULL);
115         g_string_free (icon_name, TRUE);
116         if (pixbuf)
117                 return pixbuf;
118         
119         icon_name = g_string_new ("gnome-mime-");
120         g_string_append_len (icon_name, mime_type, separator - mime_type);
121         pixbuf = gtk_icon_theme_load_icon (icon_theme, icon_name->str, 48, 0, NULL);
122         g_string_free (icon_name, TRUE);
123         
124         return pixbuf;
125 }
126
127 static GdkPixbuf *
128 ev_sidebar_attachments_icon_cache_get (EvSidebarAttachments *ev_attachbar,
129                                        const gchar          *mime_type)
130 {
131         GdkPixbuf *pixbuf = NULL;
132         
133         g_assert (mime_type != NULL);
134
135         pixbuf = g_hash_table_lookup (ev_attachbar->priv->icon_cache,
136                                       mime_type);
137
138         if (GDK_IS_PIXBUF (pixbuf))
139                 return pixbuf;
140
141         pixbuf = icon_theme_get_pixbuf_from_mime_type (ev_attachbar->priv->icon_theme,
142                                                        mime_type);
143
144         if (GDK_IS_PIXBUF (pixbuf))
145                 ev_sidebar_attachments_icon_cache_add (ev_attachbar,
146                                                        mime_type,
147                                                        pixbuf);
148
149         return pixbuf;
150 }
151
152 static gboolean
153 icon_cache_update_icon (gchar                *key,
154                         GdkPixbuf            *value,
155                         EvSidebarAttachments *ev_attachbar)
156 {
157         GdkPixbuf *pixbuf = NULL;
158
159         pixbuf = icon_theme_get_pixbuf_from_mime_type (ev_attachbar->priv->icon_theme,
160                                                        key);
161
162         ev_sidebar_attachments_icon_cache_add (ev_attachbar,
163                                                key,
164                                                pixbuf);
165         
166         return FALSE;
167 }
168
169 static void
170 ev_sidebar_attachments_icon_cache_refresh (EvSidebarAttachments *ev_attachbar)
171 {
172         g_hash_table_foreach_remove (ev_attachbar->priv->icon_cache,
173                                      (GHRFunc) icon_cache_update_icon,
174                                      ev_attachbar);
175 }
176
177 static EvAttachment *
178 ev_sidebar_attachments_get_attachment_at_pos (EvSidebarAttachments *ev_attachbar,
179                                               gint                  x,
180                                               gint                  y)
181 {
182         GtkTreePath  *path = NULL;
183         GtkTreeIter   iter;
184         EvAttachment *attachment = NULL;
185
186         path = gtk_icon_view_get_path_at_pos (GTK_ICON_VIEW (ev_attachbar->priv->icon_view),
187                                               x, y);
188         if (!path) {
189                 return NULL;
190         }
191
192         gtk_tree_model_get_iter (GTK_TREE_MODEL (ev_attachbar->priv->model),
193                                  &iter, path);
194         gtk_tree_model_get (GTK_TREE_MODEL (ev_attachbar->priv->model), &iter,
195                             COLUMN_ATTACHMENT, &attachment,
196                             -1);
197
198         gtk_icon_view_select_path (GTK_ICON_VIEW (ev_attachbar->priv->icon_view),
199                                    path);
200         
201         gtk_tree_path_free (path);
202
203         return attachment;
204 }
205
206 static gboolean
207 ev_sidebar_attachments_popup_menu_show (EvSidebarAttachments *ev_attachbar,
208                                         gint                  x,
209                                         gint                  y)
210 {
211         GtkIconView *icon_view;
212         GtkTreePath *path;
213         GList       *selected = NULL, *l;
214         GList       *attach_list = NULL;
215
216         icon_view = GTK_ICON_VIEW (ev_attachbar->priv->icon_view);
217         
218         path = gtk_icon_view_get_path_at_pos (icon_view, x, y);
219         if (!path)
220                 return FALSE;
221
222         if (!gtk_icon_view_path_is_selected (icon_view, path)) {
223                 gtk_icon_view_unselect_all (icon_view);
224                 gtk_icon_view_select_path (icon_view, path);
225         }
226
227         gtk_tree_path_free (path);
228         
229         selected = gtk_icon_view_get_selected_items (icon_view);
230         if (!selected)
231                 return FALSE;
232
233         for (l = selected; l && l->data; l = g_list_next (l)) {
234                 GtkTreeIter   iter;
235                 EvAttachment *attachment = NULL;
236
237                 path = (GtkTreePath *) l->data;
238
239                 gtk_tree_model_get_iter (GTK_TREE_MODEL (ev_attachbar->priv->model),
240                                          &iter, path);
241                 gtk_tree_model_get (GTK_TREE_MODEL (ev_attachbar->priv->model), &iter,
242                                     COLUMN_ATTACHMENT, &attachment,
243                                     -1);
244
245                 if (attachment)
246                         attach_list = g_list_prepend (attach_list, attachment);
247
248                 gtk_tree_path_free (path);
249         }
250
251         g_list_free (selected);
252
253         if (!attach_list)
254                 return FALSE;
255
256         g_signal_emit (ev_attachbar, signals[SIGNAL_POPUP_MENU], 0, attach_list);
257
258         return TRUE;
259 }
260
261 static gboolean
262 ev_sidebar_attachments_popup_menu (GtkWidget *widget)
263 {
264         EvSidebarAttachments *ev_attachbar = EV_SIDEBAR_ATTACHMENTS (widget);
265         gint                  x, y;
266
267         gtk_widget_get_pointer (widget, &x, &y);
268
269         return ev_sidebar_attachments_popup_menu_show (ev_attachbar, x, y);
270 }
271
272 static gboolean
273 ev_sidebar_attachments_button_press (EvSidebarAttachments *ev_attachbar,
274                                      GdkEventButton       *event,
275                                      GtkWidget            *icon_view)
276 {
277         if (!GTK_WIDGET_HAS_FOCUS (icon_view)) {
278                 gtk_widget_grab_focus (icon_view);
279         }
280         
281         if (event->button == 2)
282                 return FALSE;
283
284         switch (event->button) {
285                 case 1:
286                         if (event->type == GDK_2BUTTON_PRESS) {
287                                 GError *error = NULL;
288                                 EvAttachment *attachment;
289                                 
290                                 attachment = ev_sidebar_attachments_get_attachment_at_pos (ev_attachbar,
291                                                                                            event->x,
292                                                                                            event->y);
293                                 if (!attachment)
294                                         return FALSE;
295                                 
296                                 ev_attachment_open (attachment, &error);
297                                 
298                                 if (error) {
299                                         g_warning ("%s", error->message);
300                                         g_error_free (error);
301                                 }
302                                 
303                                 g_object_unref (attachment);
304                                 
305                                 return TRUE;
306                         }
307                         break;
308                 case 3: 
309                         return ev_sidebar_attachments_popup_menu_show (ev_attachbar, event->x, event->y);
310         }
311
312         return FALSE;
313 }
314
315 static void
316 ev_sidebar_attachments_update_icons (EvSidebarAttachments *ev_attachbar,
317                                      gpointer              user_data)
318 {
319         GtkTreeIter iter;
320         gboolean    valid;
321
322         ev_sidebar_attachments_icon_cache_refresh (ev_attachbar);
323         
324         valid = gtk_tree_model_get_iter_first (
325                 GTK_TREE_MODEL (ev_attachbar->priv->model),
326                 &iter);
327
328         while (valid) {
329                 EvAttachment *attachment = NULL;
330                 GdkPixbuf    *pixbuf = NULL;
331                 const gchar  *mime_type;
332
333                 gtk_tree_model_get (GTK_TREE_MODEL (ev_attachbar->priv->model), &iter,
334                                     COLUMN_ATTACHMENT, &attachment,
335                                     -1);
336
337                 mime_type = ev_attachment_get_mime_type (attachment);
338
339                 if (attachment)
340                         g_object_unref (attachment);
341
342                 pixbuf = ev_sidebar_attachments_icon_cache_get (ev_attachbar,
343                                                                 mime_type);
344
345                 gtk_list_store_set (ev_attachbar->priv->model, &iter,
346                                     COLUMN_ICON, pixbuf,
347                                     -1);
348
349                 valid = gtk_tree_model_iter_next (
350                         GTK_TREE_MODEL (ev_attachbar->priv->model),
351                         &iter);
352         }
353 }
354
355 static void
356 ev_sidebar_attachments_screen_changed (GtkWidget *widget,
357                                        GdkScreen *old_screen)
358 {
359         EvSidebarAttachments *ev_attachbar = EV_SIDEBAR_ATTACHMENTS (widget);
360         GdkScreen            *screen;
361
362         if (!ev_attachbar->priv->icon_theme)
363                 return;
364         
365         screen = gtk_widget_get_screen (widget);
366         if (screen == old_screen)
367                 return;
368
369         if (old_screen) {
370                 g_signal_handlers_disconnect_by_func (
371                         gtk_icon_theme_get_for_screen (old_screen),
372                         G_CALLBACK (ev_sidebar_attachments_update_icons),
373                         ev_attachbar);
374         }
375
376         ev_attachbar->priv->icon_theme = gtk_icon_theme_get_for_screen (screen);
377         g_signal_connect_swapped (ev_attachbar->priv->icon_theme,
378                                   "changed",
379                                   G_CALLBACK (ev_sidebar_attachments_update_icons),
380                                   (gpointer) ev_attachbar);
381
382         if (GTK_WIDGET_CLASS (ev_sidebar_attachments_parent_class)->screen_changed) {
383                 GTK_WIDGET_CLASS (ev_sidebar_attachments_parent_class)->screen_changed (widget, old_screen);
384         }
385 }
386
387 static void
388 ev_sidebar_attachments_drag_data_get (GtkWidget        *widget,
389                                       GdkDragContext   *drag_context,
390                                       GtkSelectionData *data,
391                                       guint             info,
392                                       guint             time,
393                                       gpointer          user_data)
394 {
395         EvSidebarAttachments *ev_attachbar = EV_SIDEBAR_ATTACHMENTS (user_data);
396         GString              *uri_list;
397         gchar                *uris = NULL;
398         GList                *selected = NULL, *l;
399
400         selected = gtk_icon_view_get_selected_items (GTK_ICON_VIEW (ev_attachbar->priv->icon_view));
401         if (!selected)
402                 return;
403
404         uri_list = g_string_new (NULL);
405         
406         for (l = selected; l && l->data; l = g_list_next (l)) {
407                 EvAttachment *attachment;
408                 GtkTreePath  *path;
409                 GtkTreeIter   iter;
410                 GFile        *file;
411                 gchar        *filename;
412                 GError       *error = NULL;
413                 
414                 path = (GtkTreePath *) l->data;
415
416                 gtk_tree_model_get_iter (GTK_TREE_MODEL (ev_attachbar->priv->model),
417                                          &iter, path);
418                 gtk_tree_model_get (GTK_TREE_MODEL (ev_attachbar->priv->model), &iter,
419                                     COLUMN_ATTACHMENT, &attachment,
420                                     -1);
421
422                 filename = g_build_filename (ev_tmp_dir (),
423                                              ev_attachment_get_name (attachment),
424                                              NULL);
425                 file = g_file_new_for_path (filename);
426                 g_free (filename);
427                 
428                 if (ev_attachment_save (attachment, file, &error)) {
429                         gchar *uri;
430
431                         uri = g_file_get_uri (file);
432                         g_string_append (uri_list, uri);
433                         g_string_append_c (uri_list, '\n');
434                         g_free (uri);
435                 }
436         
437                 if (error) {
438                         g_warning ("%s", error->message);
439                         g_error_free (error);
440                 }
441
442                 gtk_tree_path_free (path);
443                 g_object_unref (file);
444                 g_object_unref (attachment);
445         }
446
447         uris = g_string_free (uri_list, FALSE);
448
449         if (uris) {
450                 gtk_selection_data_set (data,
451                                         data->target,
452                                         8,
453                                         (guchar *)uris,
454                                         strlen (uris));
455         }
456
457         g_list_free (selected);
458 }
459
460 static void
461 ev_sidebar_attachments_get_property (GObject    *object,
462                                      guint       prop_id,
463                                      GValue     *value,
464                                      GParamSpec *pspec)
465 {
466         EvSidebarAttachments *ev_sidebar_attachments;
467   
468         ev_sidebar_attachments = EV_SIDEBAR_ATTACHMENTS (object);
469
470         switch (prop_id) {
471                 case PROP_WIDGET:
472                         g_value_set_object (value, ev_sidebar_attachments->priv->icon_view);
473                         break;
474                 default:
475                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
476                         break;
477         }
478 }
479
480 static void
481 ev_sidebar_attachments_destroy (GtkObject *object)
482 {
483         EvSidebarAttachments *ev_attachbar = EV_SIDEBAR_ATTACHMENTS (object);
484
485         if (ev_attachbar->priv->icon_theme) {
486                 g_signal_handlers_disconnect_by_func (
487                         ev_attachbar->priv->icon_theme, 
488                         G_CALLBACK (ev_sidebar_attachments_update_icons),
489                         ev_attachbar);
490                 ev_attachbar->priv->icon_theme = NULL;
491         }
492         
493         if (ev_attachbar->priv->model) {
494                 g_object_unref (ev_attachbar->priv->model);
495                 ev_attachbar->priv->model = NULL;
496         }
497
498         if (ev_attachbar->priv->icon_cache) {
499                 g_hash_table_destroy (ev_attachbar->priv->icon_cache);
500                 ev_attachbar->priv->icon_cache = NULL;
501         }
502
503         (* GTK_OBJECT_CLASS (ev_sidebar_attachments_parent_class)->destroy) (object);
504 }
505
506 static void
507 ev_sidebar_attachments_class_init (EvSidebarAttachmentsClass *ev_attachbar_class)
508 {
509         GObjectClass   *g_object_class;
510         GtkObjectClass *gtk_object_class;
511         GtkWidgetClass *gtk_widget_class;
512
513         g_object_class = G_OBJECT_CLASS (ev_attachbar_class);
514         gtk_object_class = GTK_OBJECT_CLASS (ev_attachbar_class);
515         gtk_widget_class = GTK_WIDGET_CLASS (ev_attachbar_class);
516
517         g_object_class->get_property = ev_sidebar_attachments_get_property;
518         gtk_object_class->destroy = ev_sidebar_attachments_destroy;
519         gtk_widget_class->popup_menu = ev_sidebar_attachments_popup_menu;
520         gtk_widget_class->screen_changed = ev_sidebar_attachments_screen_changed;
521
522         g_type_class_add_private (g_object_class, sizeof (EvSidebarAttachmentsPrivate));
523
524         /* Signals */
525         signals[SIGNAL_POPUP_MENU] =
526                 g_signal_new ("popup",
527                               G_TYPE_FROM_CLASS (g_object_class),
528                               G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
529                               G_STRUCT_OFFSET (EvSidebarAttachmentsClass, popup_menu),
530                               NULL, NULL,
531                               g_cclosure_marshal_VOID__POINTER,
532                               G_TYPE_NONE, 1,
533                               G_TYPE_POINTER);
534
535         g_object_class_override_property (g_object_class,
536                                           PROP_WIDGET,
537                                           "main-widget");
538 }
539
540 static void
541 ev_sidebar_attachments_init (EvSidebarAttachments *ev_attachbar)
542 {
543         GtkWidget *swindow;
544         
545         ev_attachbar->priv = EV_SIDEBAR_ATTACHMENTS_GET_PRIVATE (ev_attachbar);
546
547         swindow = gtk_scrolled_window_new (NULL, NULL);
548         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow),
549                                         GTK_POLICY_NEVER,
550                                         GTK_POLICY_AUTOMATIC);
551         gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swindow),
552                                              GTK_SHADOW_IN);
553         /* Data Model */
554         ev_attachbar->priv->model = gtk_list_store_new (N_COLS,
555                                                         GDK_TYPE_PIXBUF, 
556                                                         G_TYPE_STRING,  
557                                                         G_TYPE_STRING,
558                                                         EV_TYPE_ATTACHMENT);
559
560         /* Icon View */
561         ev_attachbar->priv->icon_view =
562                 gtk_icon_view_new_with_model (GTK_TREE_MODEL (ev_attachbar->priv->model));
563         gtk_icon_view_set_selection_mode (GTK_ICON_VIEW (ev_attachbar->priv->icon_view),
564                                           GTK_SELECTION_MULTIPLE);
565         gtk_icon_view_set_columns (GTK_ICON_VIEW (ev_attachbar->priv->icon_view), -1);
566         g_object_set (G_OBJECT (ev_attachbar->priv->icon_view),
567                       "text-column", COLUMN_NAME,
568                       "pixbuf-column", COLUMN_ICON,
569                       NULL);
570         g_signal_connect_swapped (G_OBJECT (ev_attachbar->priv->icon_view),
571                                   "button-press-event",
572                                   G_CALLBACK (ev_sidebar_attachments_button_press),
573                                   (gpointer) ev_attachbar);
574
575         gtk_container_add (GTK_CONTAINER (swindow),
576                            ev_attachbar->priv->icon_view);
577
578         gtk_container_add (GTK_CONTAINER (ev_attachbar),
579                            swindow);
580         gtk_widget_show_all (GTK_WIDGET (ev_attachbar));
581
582         /* Icon Theme */
583         ev_attachbar->priv->icon_theme = NULL;
584
585         /* Icon Cache */
586         ev_attachbar->priv->icon_cache = g_hash_table_new_full (g_str_hash,
587                                                                 g_str_equal,
588                                                                 g_free,
589                                                                 g_object_unref);
590
591         /* Drag and Drop */
592         gtk_icon_view_enable_model_drag_source (
593                 GTK_ICON_VIEW (ev_attachbar->priv->icon_view),
594                 GDK_BUTTON1_MASK,
595                 drag_targets,
596                 G_N_ELEMENTS (drag_targets),
597                 GDK_ACTION_COPY);
598
599         g_signal_connect (G_OBJECT (ev_attachbar->priv->icon_view),
600                           "drag-data-get",
601                           G_CALLBACK (ev_sidebar_attachments_drag_data_get),
602                           (gpointer) ev_attachbar);     
603 }
604
605 GtkWidget *
606 ev_sidebar_attachments_new (void)
607 {
608         GtkWidget *ev_attachbar;
609
610         ev_attachbar = g_object_new (EV_TYPE_SIDEBAR_ATTACHMENTS, NULL);
611
612         return ev_attachbar;
613 }
614
615 static void
616 ev_sidebar_attachments_set_document (EvSidebarPage   *page,
617                                      EvDocument      *document)
618 {
619         EvSidebarAttachments *ev_attachbar = EV_SIDEBAR_ATTACHMENTS (page);
620         GList *attachments = NULL;
621         GList *l;
622         
623         if (!ev_document_has_attachments (document))
624                 return;
625
626         if (!ev_attachbar->priv->icon_theme) {
627                 GdkScreen *screen;
628
629                 screen = gtk_widget_get_screen (GTK_WIDGET (ev_attachbar));
630                 ev_attachbar->priv->icon_theme = gtk_icon_theme_get_for_screen (screen);
631                 g_signal_connect_swapped (G_OBJECT (ev_attachbar->priv->icon_theme),
632                                           "changed",
633                                           G_CALLBACK (ev_sidebar_attachments_update_icons),
634                                           (gpointer) ev_attachbar);
635         }
636                 
637         attachments = ev_document_get_attachments (document);
638
639         gtk_list_store_clear (ev_attachbar->priv->model);
640                                            
641         for (l = attachments; l && l->data; l = g_list_next (l)) {
642                 EvAttachment *attachment;
643                 GtkTreeIter   iter;
644                 GdkPixbuf    *pixbuf = NULL;
645                 const gchar  *mime_type;
646
647                 attachment = EV_ATTACHMENT (l->data);
648
649                 mime_type = ev_attachment_get_mime_type (attachment);
650                 pixbuf = ev_sidebar_attachments_icon_cache_get (ev_attachbar,
651                                                                 mime_type);
652
653                 gtk_list_store_append (ev_attachbar->priv->model, &iter);
654                 gtk_list_store_set (ev_attachbar->priv->model, &iter,
655                                     COLUMN_NAME, ev_attachment_get_name (attachment),
656                                     COLUMN_ICON, pixbuf,
657                                     COLUMN_ATTACHMENT, attachment, 
658                                     -1);
659
660                 g_object_unref (attachment);
661         }
662
663         g_list_free (attachments);
664 }
665
666 static gboolean
667 ev_sidebar_attachments_support_document (EvSidebarPage   *sidebar_page,
668                                          EvDocument      *document)
669 {
670         return ev_document_has_attachments (document);
671 }
672
673 static const gchar*
674 ev_sidebar_attachments_get_label (EvSidebarPage *sidebar_page)
675 {
676         return _("Attachments");
677 }
678
679 static void
680 ev_sidebar_attachments_page_iface_init (EvSidebarPageIface *iface)
681 {
682         iface->support_document = ev_sidebar_attachments_support_document;
683         iface->set_document = ev_sidebar_attachments_set_document;
684         iface->get_label = ev_sidebar_attachments_get_label;
685 }
686