]> www.fi.muni.cz Git - evince.git/blob - shell/ev-metadata.c
4deb08460f43b5e0b6c4f9ac2c9eb12a6104e352
[evince.git] / shell / ev-metadata.c
1 /* ev-metadata.c
2  *  this file is part of evince, a gnome document viewer
3  *
4  * Copyright (C) 2009 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 <gio/gio.h>
22 #include <string.h>
23
24 #include "ev-metadata.h"
25
26 struct _EvMetadata {
27         GObject base;
28
29         GFile      *file;
30         GHashTable *items;
31 };
32
33 struct _EvMetadataClass {
34         GObjectClass base_class;
35 };
36
37 G_DEFINE_TYPE (EvMetadata, ev_metadata, G_TYPE_OBJECT)
38
39 #define EV_METADATA_NAMESPACE "metadata::evince"
40
41 static void
42 ev_metadata_finalize (GObject *object)
43 {
44         EvMetadata *metadata = EV_METADATA (object);
45
46         if (metadata->items) {
47                 g_hash_table_destroy (metadata->items);
48                 metadata->items = NULL;
49         }
50
51         if (metadata->file) {
52                 g_object_unref (metadata->file);
53                 metadata->file = NULL;
54         }
55
56         G_OBJECT_CLASS (ev_metadata_parent_class)->finalize (object);
57 }
58
59 static void
60 ev_metadata_init (EvMetadata *metadata)
61 {
62         metadata->items = g_hash_table_new_full (g_str_hash,
63                                                  g_str_equal,
64                                                  g_free,
65                                                  g_free);
66 }
67
68 static void
69 ev_metadata_class_init (EvMetadataClass *klass)
70 {
71         GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
72
73         gobject_class->finalize = ev_metadata_finalize;
74 }
75
76 static void
77 ev_metadata_load (EvMetadata *metadata)
78 {
79         GFileInfo *info;
80         gchar    **attrs;
81         gint       i;
82         GError    *error = NULL;
83
84         info = g_file_query_info (metadata->file, "metadata::*", 0, NULL, &error);
85         if (!info) {
86                 g_warning ("%s", error->message);
87                 g_error_free (error);
88
89                 return;
90         }
91
92 #if GLIB_CHECK_VERSION(2,22,0)
93         if (!g_file_info_has_namespace (info, "metadata")) {
94                 g_object_unref (info);
95
96                 return;
97         }
98 #endif
99
100         attrs = g_file_info_list_attributes (info, "metadata");
101         for (i = 0; attrs[i]; i++) {
102                 GFileAttributeType type;
103                 gpointer           value;
104                 const gchar       *key;
105
106                 if (!g_str_has_prefix (attrs[i], EV_METADATA_NAMESPACE))
107                         continue;
108
109                 if (!g_file_info_get_attribute_data (info, attrs[i],
110                                                      &type, &value, NULL)) {
111                         continue;
112                 }
113
114                 key = attrs[i] + strlen (EV_METADATA_NAMESPACE"::");
115
116                 if (type == G_FILE_ATTRIBUTE_TYPE_STRING) {
117                         g_hash_table_insert (metadata->items,
118                                              g_strdup (key),
119                                              g_strdup (value));
120                 }
121         }
122         g_strfreev (attrs);
123         g_object_unref (info);
124 }
125
126 EvMetadata *
127 ev_metadata_new (GFile *file)
128 {
129         EvMetadata *metadata;
130
131         g_return_val_if_fail (G_IS_FILE (file), NULL);
132
133         metadata = EV_METADATA (g_object_new (EV_TYPE_METADATA, NULL));
134         metadata->file = g_object_ref (file);
135
136         ev_metadata_load (metadata);
137
138         return metadata;
139 }
140
141 gboolean
142 ev_metadata_get_string (EvMetadata  *metadata,
143                         const gchar *key,
144                         gchar     **value)
145 {
146         gchar *v;
147
148         v = g_hash_table_lookup (metadata->items, key);
149         if (!v)
150                 return FALSE;
151
152         *value = v;
153         return TRUE;
154 }
155
156 static void
157 metadata_set_callback (GObject      *file,
158                        GAsyncResult *result,
159                        EvMetadata   *metadata)
160 {
161         GError *error = NULL;
162
163         if (!g_file_set_attributes_finish (G_FILE (file), result, NULL, &error)) {
164                 g_warning ("%s", error->message);
165                 g_error_free (error);
166         }
167 }
168
169 gboolean
170 ev_metadata_set_string (EvMetadata  *metadata,
171                         const gchar *key,
172                         const gchar *value)
173 {
174         GFileInfo *info;
175         gchar     *gio_key;
176
177         info = g_file_info_new ();
178
179         gio_key = g_strconcat (EV_METADATA_NAMESPACE"::", key, NULL);
180         if (value) {
181                 g_file_info_set_attribute_string (info, gio_key, value);
182         } else {
183                 g_file_info_set_attribute (info, gio_key,
184                                            G_FILE_ATTRIBUTE_TYPE_INVALID,
185                                            NULL);
186         }
187         g_free (gio_key);
188
189         g_hash_table_insert (metadata->items, g_strdup (key), g_strdup (value));
190         g_file_set_attributes_async (metadata->file,
191                                      info,
192                                      0,
193                                      G_PRIORITY_DEFAULT,
194                                      NULL,
195                                      (GAsyncReadyCallback)metadata_set_callback,
196                                      metadata);
197         g_object_unref (info);
198
199         return TRUE;
200 }
201
202 gboolean
203 ev_metadata_get_int (EvMetadata  *metadata,
204                      const gchar *key,
205                      gint        *value)
206 {
207         gchar *string_value;
208         gchar *endptr;
209         gint   int_value;
210
211         if (!ev_metadata_get_string (metadata, key, &string_value))
212                 return FALSE;
213
214         int_value = g_ascii_strtoull (string_value, &endptr, 0);
215         if (int_value == 0 && string_value == endptr)
216                 return FALSE;
217
218         *value = int_value;
219         return TRUE;
220 }
221
222 gboolean
223 ev_metadata_set_int (EvMetadata  *metadata,
224                      const gchar *key,
225                      gint         value)
226 {
227         gchar string_value[32];
228
229         g_snprintf (string_value, sizeof (string_value), "%d", value);
230
231         return ev_metadata_set_string (metadata, key, string_value);
232 }
233
234 gboolean
235 ev_metadata_get_double (EvMetadata  *metadata,
236                         const gchar *key,
237                         gdouble     *value)
238 {
239         gchar  *string_value;
240         gchar  *endptr;
241         gdouble double_value;
242
243         if (!ev_metadata_get_string (metadata, key, &string_value))
244                 return FALSE;
245
246         double_value = g_ascii_strtod (string_value, &endptr);
247         if (double_value == 0. && string_value == endptr)
248                 return FALSE;
249
250         *value = double_value;
251         return TRUE;
252 }
253
254 gboolean
255 ev_metadata_set_double (EvMetadata  *metadata,
256                         const gchar *key,
257                         gdouble      value)
258 {
259         gchar string_value[G_ASCII_DTOSTR_BUF_SIZE];
260
261         g_ascii_dtostr (string_value, G_ASCII_DTOSTR_BUF_SIZE, value);
262
263         return ev_metadata_set_string (metadata, key, string_value);
264 }
265
266 gboolean
267 ev_metadata_get_boolean (EvMetadata  *metadata,
268                          const gchar *key,
269                          gboolean    *value)
270 {
271         gint int_value;
272
273         if (!ev_metadata_get_int (metadata, key, &int_value))
274                 return FALSE;
275
276         *value = int_value;
277         return TRUE;
278 }
279
280 gboolean
281 ev_metadata_set_boolean (EvMetadata  *metadata,
282                          const gchar *key,
283                          gboolean     value)
284 {
285         return ev_metadata_set_string (metadata, key, value ? "1" : "0");
286 }
287
288 gboolean
289 ev_is_metadata_supported_for_file (GFile *file)
290 {
291         GFileAttributeInfoList *namespaces;
292         gint i;
293         gboolean retval = FALSE;
294
295         namespaces = g_file_query_writable_namespaces (file, NULL, NULL);
296         if (!namespaces)
297                 return retval;
298
299         for (i = 0; i < namespaces->n_infos; i++) {
300                 if (strcmp (namespaces->infos[i].name, "metadata") == 0) {
301                         retval = TRUE;
302                         break;
303                 }
304         }
305
306         g_file_attribute_info_list_unref (namespaces);
307
308         return retval;
309 }