]> www.fi.muni.cz Git - evince.git/blob - shell/ev-sidebar-bookmarks.c
shell: Show "filename (title)" in the window title.
[evince.git] / shell / ev-sidebar-bookmarks.c
1 /* ev-sidebar-bookmarks.c
2  *  this file is part of evince, a gnome document viewer
3  *
4  * Copyright (C) 2010 Carlos Garcia Campos  <carlosgc@gnome.org>
5  *
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.
10  *
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.
15  *
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.
19  */
20
21 #include "config.h"
22
23 #include <glib/gi18n.h>
24
25 #include "ev-sidebar-bookmarks.h"
26
27 #include "ev-document.h"
28 #include "ev-sidebar-page.h"
29
30 enum {
31         PROP_0,
32         PROP_WIDGET
33 };
34
35 enum {
36         COLUMN_MARKUP,
37         COLUMN_PAGE,
38         N_COLUMNS
39 };
40
41 enum {
42         ADD_BOOKMARK,
43         N_SIGNALS
44 };
45
46 struct _EvSidebarBookmarksPrivate {
47         EvDocumentModel *model;
48         EvBookmarks     *bookmarks;
49
50         GtkWidget       *tree_view;
51         GtkWidget       *del_button;
52         GtkWidget       *add_button;
53 };
54
55 static void ev_sidebar_bookmarks_page_iface_init (EvSidebarPageInterface *iface);
56
57 G_DEFINE_TYPE_EXTENDED (EvSidebarBookmarks,
58                         ev_sidebar_bookmarks,
59                         GTK_TYPE_VBOX,
60                         0,
61                         G_IMPLEMENT_INTERFACE (EV_TYPE_SIDEBAR_PAGE,
62                                                ev_sidebar_bookmarks_page_iface_init))
63
64 static guint signals[N_SIGNALS];
65
66 static gint
67 compare_bookmarks (EvBookmark *a,
68                    EvBookmark *b)
69 {
70         if (a->page < b->page)
71                 return -1;
72         if (a->page > b->page)
73                 return 1;
74         return 0;
75 }
76
77 static void
78 ev_sidebar_bookmarks_update (EvSidebarBookmarks *sidebar_bookmarks)
79 {
80         EvSidebarBookmarksPrivate *priv = sidebar_bookmarks->priv;
81         GtkListStore              *model;
82         GList                     *items, *l;
83         GtkTreeIter                iter;
84
85         model = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree_view)));
86         gtk_list_store_clear (model);
87
88         if (!priv->bookmarks) {
89                 g_object_set (priv->tree_view, "has-tooltip", FALSE, NULL);
90                 return;
91         }
92
93         items = ev_bookmarks_get_bookmarks (priv->bookmarks);
94         items = g_list_sort (items, (GCompareFunc)compare_bookmarks);
95         for (l = items; l; l = g_list_next (l)) {
96                 EvBookmark *bm = (EvBookmark *)l->data;
97
98                 gtk_list_store_append (model, &iter);
99                 gtk_list_store_set (model, &iter,
100                                     COLUMN_MARKUP, bm->title,
101                                     COLUMN_PAGE, bm->page,
102                                     -1);
103         }
104         g_list_free (items);
105         g_object_set (priv->tree_view, "has-tooltip", TRUE, NULL);
106 }
107
108 static void
109 ev_sidebar_bookmarks_changed (EvBookmarks        *bookmarks,
110                               EvSidebarBookmarks *sidebar_bookmarks)
111 {
112         ev_sidebar_bookmarks_update (sidebar_bookmarks);
113 }
114
115 static gint
116 ev_sidebar_bookmarks_get_selected_page (EvSidebarBookmarks *sidebar_bookmarks,
117                                         GtkTreeSelection   *selection)
118 {
119         GtkTreeModel *model;
120         GtkTreeIter   iter;
121
122         if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
123                 guint page;
124
125                 gtk_tree_model_get (model, &iter,
126                                     COLUMN_PAGE, &page,
127                                     -1);
128                 return page;
129         }
130
131         return -1;
132 }
133
134 static void
135 ev_sidebar_bookmarks_selection_changed (GtkTreeSelection   *selection,
136                                         EvSidebarBookmarks *sidebar_bookmarks)
137 {
138         EvSidebarBookmarksPrivate *priv = sidebar_bookmarks->priv;
139         gint                       page;
140
141         page = ev_sidebar_bookmarks_get_selected_page (sidebar_bookmarks, selection);
142         if (page >= 0) {
143                 ev_document_model_set_page (priv->model, page);
144                 gtk_widget_set_sensitive (priv->del_button, TRUE);
145         } else {
146                 gtk_widget_set_sensitive (priv->del_button, FALSE);
147         }
148 }
149
150 static void
151 ev_sidebar_bookmarks_add_clicked (GtkWidget          *button,
152                                   EvSidebarBookmarks *sidebar_bookmarks)
153 {
154         /* Let the window add the bookmark since
155          * since we don't know the page title
156          */
157         g_signal_emit (sidebar_bookmarks, signals[ADD_BOOKMARK], 0);
158 }
159
160 static void
161 ev_sidebar_bookmarks_del_clicked (GtkWidget          *button,
162                                   EvSidebarBookmarks *sidebar_bookmarks)
163 {
164         EvSidebarBookmarksPrivate *priv = sidebar_bookmarks->priv;
165         GtkTreeSelection          *selection;
166         gint                       page;
167         EvBookmark                 bm;
168
169         selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree_view));
170         page = ev_sidebar_bookmarks_get_selected_page (sidebar_bookmarks, selection);
171         if (page < 0)
172                 return;
173
174         bm.page = page;
175         bm.title = NULL;
176         ev_bookmarks_delete (priv->bookmarks, &bm);
177 }
178
179 static void
180 ev_sidebar_bookmarks_bookmark_renamed (GtkCellRendererText *renderer,
181                                        const gchar         *path_string,
182                                        const gchar         *new_text,
183                                        EvSidebarBookmarks  *sidebar_bookmarks)
184 {
185         EvSidebarBookmarksPrivate *priv = sidebar_bookmarks->priv;
186         GtkTreePath               *path = gtk_tree_path_new_from_string (path_string);
187         GtkTreeModel              *model;
188         GtkTreeIter                iter;
189         guint                      page;
190         EvBookmark                 bm;
191
192         if (!new_text || new_text[0] == '\0')
193                 return;
194
195         model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree_view));
196         gtk_tree_model_get_iter (model, &iter, path);
197         gtk_tree_model_get (model, &iter,
198                             COLUMN_PAGE, &page,
199                             -1);
200         gtk_tree_path_free (path);
201
202         bm.page = page;
203         bm.title = g_strdup (new_text);
204         ev_bookmarks_update (priv->bookmarks, &bm);
205 }
206
207 static gboolean
208 ev_sidebar_bookmarks_query_tooltip (GtkWidget          *widget,
209                                     gint                x,
210                                     gint                y,
211                                     gboolean            keyboard_tip,
212                                     GtkTooltip         *tooltip,
213                                     EvSidebarBookmarks *sidebar_bookmarks)
214 {
215         EvSidebarBookmarksPrivate *priv = sidebar_bookmarks->priv;
216         GtkTreeModel              *model;
217         GtkTreeIter                iter;
218         GtkTreePath               *path = NULL;
219         EvDocument                *document;
220         guint                      page;
221         gchar                     *page_label;
222         gchar                     *text;
223
224         model = gtk_tree_view_get_model (GTK_TREE_VIEW (priv->tree_view));
225         if (!gtk_tree_view_get_tooltip_context (GTK_TREE_VIEW (priv->tree_view),
226                                                 &x, &y, keyboard_tip,
227                                                 &model, &path, &iter))
228                 return FALSE;
229
230         gtk_tree_model_get (model, &iter,
231                             COLUMN_PAGE, &page,
232                             -1);
233
234         document = ev_document_model_get_document (priv->model);
235         page_label = ev_document_get_page_label (document, page);
236         text = g_strdup_printf (_("Page %s"), page_label);
237         gtk_tooltip_set_text (tooltip, text);
238         g_free (text);
239         g_free (page_label);
240
241         gtk_tree_view_set_tooltip_row (GTK_TREE_VIEW (priv->tree_view),
242                                        tooltip, path);
243         gtk_tree_path_free (path);
244
245         return TRUE;
246 }
247
248 static void
249 ev_sidebar_bookmarks_dispose (GObject *object)
250 {
251         EvSidebarBookmarks *sidebar_bookmarks = EV_SIDEBAR_BOOKMARKS (object);
252         EvSidebarBookmarksPrivate *priv = sidebar_bookmarks->priv;
253
254         if (priv->model) {
255                 g_object_unref (priv->model);
256                 priv->model = NULL;
257         }
258
259         if (priv->bookmarks) {
260                 g_object_unref (priv->bookmarks);
261                 priv->bookmarks = NULL;
262         }
263
264         G_OBJECT_CLASS (ev_sidebar_bookmarks_parent_class)->dispose (object);
265 }
266
267 static void
268 ev_sidebar_bookmarks_init (EvSidebarBookmarks *sidebar_bookmarks)
269 {
270         EvSidebarBookmarksPrivate *priv;
271         GtkWidget                 *swindow;
272         GtkWidget                 *hbox;
273         GtkListStore              *model;
274         GtkCellRenderer           *renderer;
275         GtkTreeSelection          *selection;
276
277         sidebar_bookmarks->priv = G_TYPE_INSTANCE_GET_PRIVATE (sidebar_bookmarks,
278                                                                EV_TYPE_SIDEBAR_BOOKMARKS,
279                                                                EvSidebarBookmarksPrivate);
280         priv = sidebar_bookmarks->priv;
281
282         gtk_box_set_spacing (GTK_BOX (sidebar_bookmarks), 6);
283
284         swindow = gtk_scrolled_window_new (NULL, NULL);
285         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow),
286                                         GTK_POLICY_AUTOMATIC,
287                                         GTK_POLICY_AUTOMATIC);
288         gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (swindow),
289                                              GTK_SHADOW_IN);
290         gtk_box_pack_start (GTK_BOX (sidebar_bookmarks), swindow, TRUE, TRUE, 0);
291         gtk_widget_show (swindow);
292
293         model = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_UINT);
294         priv->tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
295         g_object_unref (model);
296         g_signal_connect (priv->tree_view, "query-tooltip",
297                           G_CALLBACK (ev_sidebar_bookmarks_query_tooltip),
298                           sidebar_bookmarks);
299         gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (priv->tree_view), FALSE);
300         selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree_view));
301         g_signal_connect (selection, "changed",
302                           G_CALLBACK (ev_sidebar_bookmarks_selection_changed),
303                           sidebar_bookmarks);
304
305         renderer = gtk_cell_renderer_text_new ();
306         g_object_set (renderer,
307                       "ellipsize", PANGO_ELLIPSIZE_END,
308                       "editable", TRUE,
309                       NULL);
310         g_signal_connect (renderer, "edited",
311                           G_CALLBACK (ev_sidebar_bookmarks_bookmark_renamed),
312                           sidebar_bookmarks);
313         gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (priv->tree_view),
314                                                      0, NULL, renderer,
315                                                      "markup", COLUMN_MARKUP,
316                                                      NULL);
317         gtk_container_add (GTK_CONTAINER (swindow), priv->tree_view);
318         gtk_widget_show (priv->tree_view);
319
320         hbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
321
322         priv->add_button = gtk_button_new_from_stock (GTK_STOCK_ADD);
323         g_signal_connect (priv->add_button, "clicked",
324                           G_CALLBACK (ev_sidebar_bookmarks_add_clicked),
325                           sidebar_bookmarks);
326         gtk_widget_set_sensitive (priv->add_button, FALSE);
327         gtk_box_pack_start (GTK_BOX (hbox), priv->add_button, TRUE, TRUE, 6);
328         gtk_widget_show (priv->add_button);
329
330         priv->del_button = gtk_button_new_from_stock (GTK_STOCK_REMOVE);
331         g_signal_connect (priv->del_button, "clicked",
332                           G_CALLBACK (ev_sidebar_bookmarks_del_clicked),
333                           sidebar_bookmarks);
334         gtk_widget_set_sensitive (priv->del_button, FALSE);
335         gtk_box_pack_start (GTK_BOX (hbox), priv->del_button, TRUE, TRUE, 6);
336         gtk_widget_show (priv->del_button);
337
338         gtk_box_pack_end (GTK_BOX (sidebar_bookmarks), hbox, FALSE, TRUE, 0);
339         gtk_widget_show (hbox);
340         gtk_widget_show (GTK_WIDGET (sidebar_bookmarks));
341 }
342
343 static void
344 ev_sidebar_bookmarks_get_property (GObject    *object,
345                                    guint       prop_id,
346                                    GValue     *value,
347                                    GParamSpec *pspec)
348 {
349         EvSidebarBookmarks *sidebar_bookmarks;
350
351         sidebar_bookmarks = EV_SIDEBAR_BOOKMARKS (object);
352
353         switch (prop_id) {
354         case PROP_WIDGET:
355                 g_value_set_object (value, sidebar_bookmarks->priv->tree_view);
356                 break;
357         default:
358                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
359                 break;
360         }
361 }
362
363 static void
364 ev_sidebar_bookmarks_class_init (EvSidebarBookmarksClass *klass)
365 {
366         GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
367
368         g_object_class->get_property = ev_sidebar_bookmarks_get_property;
369         g_object_class->dispose = ev_sidebar_bookmarks_dispose;
370
371         g_type_class_add_private (g_object_class, sizeof (EvSidebarBookmarksPrivate));
372
373         g_object_class_override_property (g_object_class, PROP_WIDGET, "main-widget");
374
375         signals[ADD_BOOKMARK] =
376                 g_signal_new ("add-bookmark",
377                               G_TYPE_FROM_CLASS (g_object_class),
378                               G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
379                               G_STRUCT_OFFSET (EvSidebarBookmarksClass, add_bookmark),
380                               NULL, NULL,
381                               g_cclosure_marshal_VOID__VOID,
382                               G_TYPE_NONE, 0,
383                               G_TYPE_NONE);
384 }
385
386 GtkWidget *
387 ev_sidebar_bookmarks_new (void)
388 {
389         return GTK_WIDGET (g_object_new (EV_TYPE_SIDEBAR_BOOKMARKS, NULL));
390 }
391
392 void
393 ev_sidebar_bookmarks_set_bookmarks (EvSidebarBookmarks *sidebar_bookmarks,
394                                     EvBookmarks        *bookmarks)
395 {
396         EvSidebarBookmarksPrivate *priv = sidebar_bookmarks->priv;
397
398         g_return_if_fail (EV_IS_BOOKMARKS (bookmarks));
399
400         if (priv->bookmarks == bookmarks)
401                 return;
402
403         if (priv->bookmarks)
404                 g_object_unref (priv->bookmarks);
405         priv->bookmarks = g_object_ref (bookmarks);
406         g_signal_connect (priv->bookmarks, "changed",
407                           G_CALLBACK (ev_sidebar_bookmarks_changed),
408                           sidebar_bookmarks);
409
410         gtk_widget_set_sensitive (priv->add_button, TRUE);
411         ev_sidebar_bookmarks_update (sidebar_bookmarks);
412 }
413
414 /* EvSidebarPageIface */
415 static void
416 ev_sidebar_bookmarks_set_model (EvSidebarPage   *sidebar_page,
417                                 EvDocumentModel *model)
418 {
419         EvSidebarBookmarks *sidebar_bookmarks = EV_SIDEBAR_BOOKMARKS (sidebar_page);
420         EvSidebarBookmarksPrivate *priv = sidebar_bookmarks->priv;
421
422         if (priv->model == model)
423                 return;
424
425         if (priv->model)
426                 g_object_unref (priv->model);
427         priv->model = g_object_ref (model);
428 }
429
430 static gboolean
431 ev_sidebar_bookmarks_support_document (EvSidebarPage *sidebar_page,
432                                        EvDocument    *document)
433 {
434         return TRUE;
435 }
436
437 static const gchar *
438 ev_sidebar_bookmarks_get_label (EvSidebarPage *sidebar_page)
439 {
440         return _("Bookmarks");
441 }
442
443 static void
444 ev_sidebar_bookmarks_page_iface_init (EvSidebarPageInterface *iface)
445 {
446         iface->support_document = ev_sidebar_bookmarks_support_document;
447         iface->set_model = ev_sidebar_bookmarks_set_model;
448         iface->get_label = ev_sidebar_bookmarks_get_label;
449 }