1 /* ev-sidebar-annotations.c
2 * this file is part of evince, a gnome document viewer
4 * Copyright (C) 2010 Carlos Garcia Campos <carlosgc@gnome.org>
6 * Evince is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * Evince is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
23 #include <glib/gi18n.h>
25 #include "ev-document-annotations.h"
26 #include "ev-sidebar-page.h"
27 #include "ev-sidebar-annotations.h"
29 #include "ev-job-scheduler.h"
30 #include "ev-stock-icons.h"
49 struct _EvSidebarAnnotationsPrivate {
54 guint selection_changed_id;
57 static void ev_sidebar_annotations_page_iface_init (EvSidebarPageInterface *iface);
59 static guint signals[N_SIGNALS];
61 G_DEFINE_TYPE_EXTENDED (EvSidebarAnnotations,
62 ev_sidebar_annotations,
65 G_IMPLEMENT_INTERFACE (EV_TYPE_SIDEBAR_PAGE,
66 ev_sidebar_annotations_page_iface_init))
68 #define EV_SIDEBAR_ANNOTATIONS_GET_PRIVATE(object) \
69 (G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_SIDEBAR_ANNOTATIONS, EvSidebarAnnotationsPrivate))
72 ev_sidebar_annotations_create_simple_model (const gchar *message)
78 /* Creates a fake model to indicate that we're loading */
79 retval = (GtkTreeModel *)gtk_list_store_new (N_COLUMNS,
84 gtk_list_store_append (GTK_LIST_STORE (retval), &iter);
85 markup = g_strdup_printf ("<span size=\"larger\" style=\"italic\">%s</span>",
87 gtk_list_store_set (GTK_LIST_STORE (retval), &iter,
88 COLUMN_MARKUP, markup,
96 ev_sidebar_annotations_add_annots_list (EvSidebarAnnotations *ev_annots)
99 GtkTreeModel *loading_model;
100 GtkCellRenderer *renderer;
101 GtkTreeViewColumn *column;
102 GtkTreeSelection *selection;
104 swindow = gtk_scrolled_window_new (NULL, NULL);
105 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow),
106 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
107 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swindow),
110 /* Create tree view */
111 loading_model = ev_sidebar_annotations_create_simple_model (_("Loading…"));
112 ev_annots->priv->tree_view = gtk_tree_view_new_with_model (loading_model);
113 g_object_unref (loading_model);
115 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (ev_annots->priv->tree_view),
117 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (ev_annots->priv->tree_view));
118 gtk_tree_selection_set_mode (selection, GTK_SELECTION_NONE);
120 column = gtk_tree_view_column_new ();
122 renderer = gtk_cell_renderer_pixbuf_new ();
123 gtk_tree_view_column_pack_start (column, renderer, FALSE);
124 gtk_tree_view_column_set_attributes (column, renderer,
125 "pixbuf", COLUMN_ICON,
128 renderer = gtk_cell_renderer_text_new ();
129 gtk_tree_view_column_pack_start (column, renderer, TRUE);
130 gtk_tree_view_column_set_attributes (column, renderer,
131 "markup", COLUMN_MARKUP,
133 gtk_tree_view_append_column (GTK_TREE_VIEW (ev_annots->priv->tree_view),
136 gtk_container_add (GTK_CONTAINER (swindow), ev_annots->priv->tree_view);
137 gtk_widget_show (ev_annots->priv->tree_view);
139 gtk_notebook_append_page (GTK_NOTEBOOK (ev_annots->priv->notebook),
141 gtk_widget_show (swindow);
145 ev_sidebar_annotations_init (EvSidebarAnnotations *ev_annots)
147 ev_annots->priv = EV_SIDEBAR_ANNOTATIONS_GET_PRIVATE (ev_annots);
149 ev_annots->priv->notebook = gtk_notebook_new ();
150 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (ev_annots->priv->notebook), FALSE);
151 gtk_notebook_set_show_border (GTK_NOTEBOOK (ev_annots->priv->notebook), FALSE);
152 ev_sidebar_annotations_add_annots_list (ev_annots);
153 gtk_container_add (GTK_CONTAINER (ev_annots), ev_annots->priv->notebook);
154 gtk_widget_show (ev_annots->priv->notebook);
158 ev_sidebar_annotations_get_property (GObject *object,
163 EvSidebarAnnotations *ev_sidebar_annots;
165 ev_sidebar_annots = EV_SIDEBAR_ANNOTATIONS (object);
169 g_value_set_object (value, ev_sidebar_annots->priv->notebook);
172 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
178 ev_sidebar_annotations_class_init (EvSidebarAnnotationsClass *klass)
180 GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
182 g_object_class->get_property = ev_sidebar_annotations_get_property;
184 g_type_class_add_private (g_object_class, sizeof (EvSidebarAnnotationsPrivate));
186 g_object_class_override_property (g_object_class, PROP_WIDGET, "main-widget");
188 signals[ANNOT_ACTIVATED] =
189 g_signal_new ("annot-activated",
190 G_TYPE_FROM_CLASS (g_object_class),
191 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
192 G_STRUCT_OFFSET (EvSidebarAnnotationsClass, annot_activated),
194 g_cclosure_marshal_VOID__POINTER,
200 ev_sidebar_annotations_new (void)
202 return GTK_WIDGET (g_object_new (EV_TYPE_SIDEBAR_ANNOTATIONS, NULL));
206 selection_changed_cb (GtkTreeSelection *selection,
207 EvSidebarAnnotations *sidebar_annots)
212 if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
213 EvMapping *mapping = NULL;
215 gtk_tree_model_get (model, &iter,
216 COLUMN_ANNOT_MAPPING, &mapping,
219 g_signal_emit (sidebar_annots, signals[ANNOT_ACTIVATED], 0, mapping);
224 job_finished_callback (EvJobAnnots *job,
225 EvSidebarAnnotations *sidebar_annots)
227 EvSidebarAnnotationsPrivate *priv;
229 GtkTreeSelection *selection;
231 GdkPixbuf *text_icon = NULL;
232 GdkPixbuf *attachment_icon = NULL;
234 priv = sidebar_annots->priv;
239 list = ev_sidebar_annotations_create_simple_model (_("Document contains no annotations"));
240 gtk_tree_view_set_model (GTK_TREE_VIEW (priv->tree_view), list);
241 g_object_unref (list);
243 g_object_unref (job);
249 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree_view));
250 gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
251 if (priv->selection_changed_id == 0) {
252 priv->selection_changed_id =
253 g_signal_connect (selection, "changed",
254 G_CALLBACK (selection_changed_cb),
258 model = gtk_tree_store_new (N_COLUMNS,
263 for (l = job->annots; l; l = g_list_next (l)) {
264 EvMappingList *mapping_list;
268 gboolean found = FALSE;
270 mapping_list = (EvMappingList *)l->data;
271 page_label = g_strdup_printf (_("Page %d"),
272 ev_mapping_list_get_page (mapping_list) + 1);
273 gtk_tree_store_append (model, &iter, NULL);
274 gtk_tree_store_set (model, &iter,
275 COLUMN_MARKUP, page_label,
279 for (ll = ev_mapping_list_get_list (mapping_list); ll; ll = g_list_next (ll)) {
283 GtkTreeIter child_iter;
284 GdkPixbuf *pixbuf = NULL;
286 annot = ((EvMapping *)(ll->data))->data;
287 if (!EV_IS_ANNOTATION_MARKUP (annot))
290 label = ev_annotation_markup_get_label (EV_ANNOTATION_MARKUP (annot));
291 if (annot->modified) {
292 markup = g_strdup_printf ("<span weight=\"bold\">%s</span>\n%s",
293 label, annot->modified);
295 markup = g_strdup_printf ("<span weight=\"bold\">%s</span>", label);
299 if (EV_IS_ANNOTATION_TEXT (annot)) {
301 /* FIXME: use a better icon than EDIT */
302 text_icon = gtk_widget_render_icon (priv->tree_view,
304 GTK_ICON_SIZE_BUTTON,
308 } else if (EV_IS_ANNOTATION_ATTACHMENT (annot)) {
309 if (!attachment_icon) {
310 attachment_icon = gtk_widget_render_icon (priv->tree_view,
312 GTK_ICON_SIZE_BUTTON,
315 pixbuf = attachment_icon;
318 gtk_tree_store_append (model, &child_iter, &iter);
319 gtk_tree_store_set (model, &child_iter,
320 COLUMN_MARKUP, markup,
322 COLUMN_ANNOT_MAPPING, ll->data,
329 gtk_tree_store_remove (model, &iter);
332 gtk_tree_view_set_model (GTK_TREE_VIEW (priv->tree_view),
333 GTK_TREE_MODEL (model));
334 g_object_unref (model);
337 g_object_unref (text_icon);
339 g_object_unref (attachment_icon);
341 g_object_unref (job);
347 ev_sidebar_annotations_document_changed_cb (EvDocumentModel *model,
349 EvSidebarAnnotations *sidebar_annots)
351 EvDocument *document = ev_document_model_get_document (model);
352 EvSidebarAnnotationsPrivate *priv = sidebar_annots->priv;
354 if (!EV_IS_DOCUMENT_ANNOTATIONS (document))
358 g_signal_handlers_disconnect_by_func (priv->job,
359 job_finished_callback,
361 g_object_unref (priv->job);
364 priv->job = ev_job_annots_new (document);
365 g_signal_connect (priv->job, "finished",
366 G_CALLBACK (job_finished_callback),
368 /* The priority doesn't matter for this job */
369 ev_job_scheduler_push_job (priv->job, EV_JOB_PRIORITY_NONE);
372 /* EvSidebarPageIface */
374 ev_sidebar_annotations_set_model (EvSidebarPage *sidebar_page,
375 EvDocumentModel *model)
377 g_signal_connect (model, "notify::document",
378 G_CALLBACK (ev_sidebar_annotations_document_changed_cb),
383 ev_sidebar_annotations_support_document (EvSidebarPage *sidebar_page,
384 EvDocument *document)
386 return (EV_IS_DOCUMENT_ANNOTATIONS (document));
390 ev_sidebar_annotations_get_label (EvSidebarPage *sidebar_page)
392 return _("Annotations");
396 ev_sidebar_annotations_page_iface_init (EvSidebarPageInterface *iface)
398 iface->support_document = ev_sidebar_annotations_support_document;
399 iface->set_model = ev_sidebar_annotations_set_model;
400 iface->get_label = ev_sidebar_annotations_get_label;