Evince
Evince is a document viewer capable of displaying multiple and single page document formats like PDF and Postscript.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
ev-bookmarks.c
Go to the documentation of this file.
1 /* ev-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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  */
20 
21 #include "config.h"
22 
23 #include <string.h>
24 
25 #include "ev-bookmarks.h"
26 
27 enum {
30 };
31 
32 enum {
35 };
36 
37 struct _EvBookmarks {
38  GObject base;
39 
41  GList *items;
42 };
43 
45  GObjectClass base_class;
46 
47  void (*changed) (EvBookmarks *bookmarks);
48 };
49 
50 G_DEFINE_TYPE (EvBookmarks, ev_bookmarks, G_TYPE_OBJECT)
51 
52 static guint signals[N_SIGNALS];
53 
54 static gint
56  EvBookmark *b)
57 {
58  if (a->page < b->page)
59  return -1;
60  if (a->page > b->page)
61  return 1;
62  return 0;
63 }
64 
65 static void
67 {
68  if (G_UNLIKELY(!bm))
69  return;
70 
71  g_free (bm->title);
72  g_slice_free (EvBookmark, bm);
73 }
74 
75 static void
76 ev_bookmarks_finalize (GObject *object)
77 {
78  EvBookmarks *bookmarks = EV_BOOKMARKS (object);
79 
80  if (bookmarks->items) {
81  g_list_free_full (bookmarks->items, (GDestroyNotify)ev_bookmark_free);
82  bookmarks->items = NULL;
83  }
84 
85  if (bookmarks->metadata) {
86  g_object_unref (bookmarks->metadata);
87  bookmarks->metadata = NULL;
88  }
89 
90  G_OBJECT_CLASS (ev_bookmarks_parent_class)->finalize (object);
91 }
92 
93 static void
95 {
96 }
97 
98 static void
99 ev_bookmarks_set_property (GObject *object,
100  guint prop_id,
101  const GValue *value,
102  GParamSpec *pspec)
103 {
104  EvBookmarks *bookmarks = EV_BOOKMARKS (object);
105 
106  switch (prop_id) {
107  case PROP_METADATA:
108  bookmarks->metadata = (EvMetadata *)g_value_dup_object (value);
109  break;
110  default:
111  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
112  }
113 }
114 
115 static void
116 ev_bookmarks_constructed (GObject *object)
117 {
118  EvBookmarks *bookmarks = EV_BOOKMARKS (object);
119  gchar *bm_list_str;
120  GVariant *bm_list;
121  GVariantIter iter;
122  GVariant *child;
123  GError *error = NULL;
124 
125  if (!ev_metadata_get_string (bookmarks->metadata, "bookmarks", &bm_list_str))
126  return;
127 
128  if (!bm_list_str || bm_list_str[0] == '\0')
129  return;
130 
131  bm_list = g_variant_parse ((const GVariantType *)"a(us)",
132  bm_list_str, NULL, NULL,
133  &error);
134  if (!bm_list) {
135  g_warning ("Error getting bookmarks: %s\n", error->message);
136  g_error_free (error);
137 
138  return;
139  }
140 
141  g_variant_iter_init (&iter, bm_list);
142  while ((child = g_variant_iter_next_value (&iter))) {
143  EvBookmark *bm = g_slice_new (EvBookmark);
144 
145  g_variant_get (child, "(us)", &bm->page, &bm->title);
146  if (bm->title && strlen (bm->title) > 0)
147  bookmarks->items = g_list_prepend (bookmarks->items, bm);
148  g_variant_unref (child);
149  }
150  g_variant_unref (bm_list);
151 
152  bookmarks->items = g_list_reverse (bookmarks->items);
153 }
154 
155 static void
157 {
158  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
159 
160  gobject_class->set_property = ev_bookmarks_set_property;
161  gobject_class->finalize = ev_bookmarks_finalize;
162  gobject_class->constructed = ev_bookmarks_constructed;
163 
164  g_object_class_install_property (gobject_class,
166  g_param_spec_object ("metadata",
167  "Metadata",
168  "The document metadata",
170  G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE |
171  G_PARAM_STATIC_STRINGS));
172  /* Signals */
173  signals[CHANGED] =
174  g_signal_new ("changed",
176  G_SIGNAL_RUN_LAST,
177  G_STRUCT_OFFSET (EvBookmarksClass, changed),
178  NULL, NULL,
179  g_cclosure_marshal_VOID__VOID,
180  G_TYPE_NONE, 0);
181 }
182 
183 EvBookmarks *
185 {
186  g_return_val_if_fail (EV_IS_METADATA (metadata), NULL);
187 
188  return EV_BOOKMARKS (g_object_new (EV_TYPE_BOOKMARKS,
189  "metadata", metadata, NULL));
190 }
191 
192 static void
194 {
195  GList *l;
196  GVariantBuilder builder;
197  GVariant *bm_list;
198  gchar *bm_list_str;
199 
200  if (!bookmarks->items) {
201  ev_metadata_set_string (bookmarks->metadata, "bookmarks", "");
202  return;
203  }
204 
205  g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
206  for (l = bookmarks->items; l; l = g_list_next (l)) {
207  EvBookmark *bm = (EvBookmark *)l->data;
208 
209  g_variant_builder_add (&builder, "(u&s)", bm->page, bm->title);
210  }
211  bm_list = g_variant_builder_end (&builder);
212 
213  bm_list_str = g_variant_print (bm_list, FALSE);
214  g_variant_unref (bm_list);
215  ev_metadata_set_string (bookmarks->metadata, "bookmarks", bm_list_str);
216  g_free (bm_list_str);
217 }
218 
219 GList *
221 {
222  g_return_val_if_fail (EV_IS_BOOKMARKS (bookmarks), NULL);
223 
224  return g_list_copy (bookmarks->items);
225 }
226 
227 gboolean
229 {
230  g_return_val_if_fail (EV_IS_BOOKMARKS (bookmarks), FALSE);
231 
232  return bookmarks->items != NULL;
233 }
234 
235 void
237  EvBookmark *bookmark)
238 {
239  EvBookmark *bm;
240 
241  g_return_if_fail (EV_IS_BOOKMARKS (bookmarks));
242  g_return_if_fail (bookmark->title != NULL);
243 
244  if (g_list_find_custom (bookmarks->items, bookmark, (GCompareFunc)ev_bookmark_compare))
245  return;
246 
247  bm = g_slice_new (EvBookmark);
248  *bm = *bookmark;
249  bookmarks->items = g_list_append (bookmarks->items, bm);
250  g_signal_emit (bookmarks, signals[CHANGED], 0);
251  ev_bookmarks_save (bookmarks);
252 }
253 
254 void
256  EvBookmark *bookmark)
257 {
258  GList *bm_link;
259 
260  g_return_if_fail (EV_IS_BOOKMARKS (bookmarks));
261 
262  bm_link = g_list_find_custom (bookmarks->items, bookmark, (GCompareFunc)ev_bookmark_compare);
263  if (!bm_link)
264  return;
265 
266  bookmarks->items = g_list_delete_link (bookmarks->items, bm_link);
267  g_signal_emit (bookmarks, signals[CHANGED], 0);
268  ev_bookmarks_save (bookmarks);
269 }
270 
271 void
273  EvBookmark *bookmark)
274 {
275  GList *bm_link;
276  EvBookmark *bm;
277 
278  g_return_if_fail (EV_IS_BOOKMARKS (bookmarks));
279  g_return_if_fail (bookmark->title != NULL);
280 
281  bm_link = g_list_find_custom (bookmarks->items, bookmark, (GCompareFunc)ev_bookmark_compare);
282  if (!bm_link)
283  return;
284 
285  bm = (EvBookmark *)bm_link->data;
286 
287  if (strcmp (bookmark->title, bm->title) == 0)
288  return;
289 
290  g_free (bm->title);
291  *bm = *bookmark;
292  g_signal_emit (bookmarks, signals[CHANGED], 0);
293  ev_bookmarks_save (bookmarks);
294 }