]> www.fi.muni.cz Git - evince.git/blob - libdocument/ev-attachment.c
980d0569bf842b7fd09e783143adef9db751bdf8
[evince.git] / libdocument / ev-attachment.c
1 /* this file is part of evince, a gnome document viewer
2  *
3  *  Copyright (C) 2006 Carlos Garcia Campos <carlosgc@gnome.org>
4  *
5  * Evince is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * Evince is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
18  */
19
20 #include <glib/gi18n.h>
21 #include <glib/gstdio.h>
22 #include <libgnomevfs/gnome-vfs.h>
23 #include <libgnomevfs/gnome-vfs-mime-handlers.h>
24 #include <libgnomevfs/gnome-vfs-mime-utils.h>
25 #include "ev-file-helpers.h"
26 #include "ev-attachment.h"
27
28 enum
29 {
30         PROP_0,
31         PROP_NAME,
32         PROP_DESCRIPTION,
33         PROP_MTIME,
34         PROP_CTIME,
35         PROP_SIZE,
36         PROP_DATA
37 };
38
39 struct _EvAttachmentPrivate {
40         gchar                   *name;
41         gchar                   *description;
42         GTime                    mtime;
43         GTime                    ctime;
44         gsize                    size;
45         gchar                   *data;
46         gchar                   *mime_type;
47
48         GnomeVFSMimeApplication *app;
49         gchar                   *tmp_uri;
50 };
51
52 #define EV_ATTACHMENT_GET_PRIVATE(object) \
53                 (G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_ATTACHMENT, EvAttachmentPrivate))
54
55 G_DEFINE_TYPE (EvAttachment, ev_attachment, G_TYPE_OBJECT)
56
57 GQuark
58 ev_attachment_error_quark (void)
59 {
60         static GQuark error_quark = 0;
61         
62         if (error_quark == 0)
63                 error_quark =
64                         g_quark_from_static_string ("ev-attachment-error-quark");
65         
66         return error_quark;
67 }
68
69 static void
70 ev_attachment_finalize (GObject *object)
71 {
72         EvAttachment *attachment = EV_ATTACHMENT (object);
73
74         if (attachment->priv->name) {
75                 g_free (attachment->priv->name);
76                 attachment->priv->name = NULL;
77         }
78
79         if (attachment->priv->description) {
80                 g_free (attachment->priv->description);
81                 attachment->priv->description = NULL;
82         }
83
84         if (attachment->priv->data) {
85                 g_free (attachment->priv->data);
86                 attachment->priv->data = NULL;
87         }
88
89         if (attachment->priv->mime_type) {
90                 g_free (attachment->priv->mime_type);
91                 attachment->priv->mime_type = NULL;
92         }
93
94         if (attachment->priv->app) {
95                 gnome_vfs_mime_application_free (attachment->priv->app);
96                 attachment->priv->app = NULL;
97         }
98
99         if (attachment->priv->tmp_uri) {
100                 ev_tmp_filename_unlink (attachment->priv->tmp_uri);
101                 g_free (attachment->priv->tmp_uri);
102                 attachment->priv->tmp_uri = NULL;
103         }
104
105         (* G_OBJECT_CLASS (ev_attachment_parent_class)->finalize) (object);
106 }
107
108 static void
109 ev_attachment_set_property (GObject      *object,
110                             guint         prop_id,
111                             const GValue *value,
112                             GParamSpec   *param_spec)
113 {
114         EvAttachment *attachment = EV_ATTACHMENT (object);
115
116         switch (prop_id) {
117         case PROP_NAME:
118                 attachment->priv->name = g_value_dup_string (value);
119                 break;
120         case PROP_DESCRIPTION:
121                 attachment->priv->description = g_value_dup_string (value);
122                 break;
123         case PROP_MTIME:
124                 attachment->priv->mtime = g_value_get_ulong (value);
125                 break;
126         case PROP_CTIME:
127                 attachment->priv->ctime = g_value_get_ulong (value);
128                 break;
129         case PROP_SIZE:
130                 attachment->priv->size = g_value_get_uint (value);
131                 break;
132         case PROP_DATA:
133                 attachment->priv->data = g_value_get_pointer (value);
134                 attachment->priv->mime_type =
135                         g_strdup (gnome_vfs_get_mime_type_for_data (attachment->priv->data,
136                                                                     attachment->priv->size));
137                 break;
138         default:
139                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
140                                                    prop_id,
141                                                    param_spec);
142                 break;
143         }
144 }
145
146 static void
147 ev_attachment_class_init (EvAttachmentClass *klass)
148 {
149         GObjectClass *g_object_class;
150
151         g_object_class = G_OBJECT_CLASS (klass);
152
153         g_object_class->set_property = ev_attachment_set_property;
154
155         g_type_class_add_private (g_object_class, sizeof (EvAttachmentPrivate));
156
157         /* Properties */
158         g_object_class_install_property (g_object_class,
159                                          PROP_NAME,
160                                          g_param_spec_string ("name",
161                                                               "Name",
162                                                               "The attachment name",
163                                                               NULL,
164                                                               G_PARAM_WRITABLE |
165                                                               G_PARAM_CONSTRUCT_ONLY));
166         g_object_class_install_property (g_object_class,
167                                          PROP_DESCRIPTION,
168                                          g_param_spec_string ("description",
169                                                               "Description",
170                                                               "The attachment description",
171                                                               NULL,
172                                                               G_PARAM_WRITABLE |
173                                                               G_PARAM_CONSTRUCT_ONLY));
174         g_object_class_install_property (g_object_class,
175                                          PROP_MTIME,
176                                          g_param_spec_ulong ("mtime",
177                                                              "ModifiedTime", 
178                                                              "The attachment modification date",
179                                                              0, G_MAXULONG, 0,
180                                                              G_PARAM_WRITABLE |
181                                                              G_PARAM_CONSTRUCT_ONLY));
182         g_object_class_install_property (g_object_class,
183                                          PROP_CTIME,
184                                          g_param_spec_ulong ("ctime",
185                                                              "CreationTime",
186                                                              "The attachment creation date",
187                                                              0, G_MAXULONG, 0,
188                                                              G_PARAM_WRITABLE |
189                                                              G_PARAM_CONSTRUCT_ONLY));
190         g_object_class_install_property (g_object_class,
191                                          PROP_SIZE,
192                                          g_param_spec_uint ("size",
193                                                             "Size",
194                                                             "The attachment size",
195                                                             0, G_MAXUINT, 0,
196                                                             G_PARAM_WRITABLE |
197                                                             G_PARAM_CONSTRUCT_ONLY));
198         g_object_class_install_property (g_object_class,
199                                          PROP_DATA,
200                                          g_param_spec_pointer ("data",
201                                                                "Data",
202                                                                "The attachment data",
203                                                                G_PARAM_WRITABLE |
204                                                                G_PARAM_CONSTRUCT_ONLY));
205         
206         g_object_class->finalize = ev_attachment_finalize;
207 }
208
209 static void
210 ev_attachment_init (EvAttachment *attachment)
211 {
212         attachment->priv = EV_ATTACHMENT_GET_PRIVATE (attachment);
213
214         attachment->priv->name = NULL;
215         attachment->priv->description = NULL;
216         attachment->priv->data = NULL;
217         attachment->priv->mime_type = NULL;
218
219         attachment->priv->tmp_uri = NULL;
220 }
221
222 EvAttachment *
223 ev_attachment_new (const gchar *name,
224                    const gchar *description,
225                    GTime        mtime,
226                    GTime        ctime,
227                    gsize        size,
228                    gpointer     data)
229 {
230         EvAttachment *attachment;
231
232         attachment = g_object_new (EV_TYPE_ATTACHMENT,
233                                    "name", name,
234                                    "description", description,
235                                    "mtime", mtime,
236                                    "ctime", ctime,
237                                    "size", size,
238                                    "data", data,
239                                    NULL);
240
241         return attachment;
242 }
243
244 const gchar *
245 ev_attachment_get_name (EvAttachment *attachment)
246 {
247         g_return_val_if_fail (EV_IS_ATTACHMENT (attachment), NULL);
248
249         return attachment->priv->name;
250 }
251
252 const gchar *
253 ev_attachment_get_description (EvAttachment *attachment)
254 {
255         g_return_val_if_fail (EV_IS_ATTACHMENT (attachment), NULL);
256
257         return attachment->priv->description;
258 }
259
260 GTime
261 ev_attachment_get_modification_date (EvAttachment *attachment)
262 {
263         g_return_val_if_fail (EV_IS_ATTACHMENT (attachment), 0);
264
265         return attachment->priv->mtime;
266 }
267
268 GTime
269 ev_attachment_get_creation_date (EvAttachment *attachment)
270 {
271         g_return_val_if_fail (EV_IS_ATTACHMENT (attachment), 0);
272
273         return attachment->priv->ctime;
274 }
275
276 const gchar *
277 ev_attachment_get_mime_type (EvAttachment *attachment)
278 {
279         g_return_val_if_fail (EV_IS_ATTACHMENT (attachment), NULL);
280
281         return attachment->priv->mime_type;
282 }
283
284 gboolean
285 ev_attachment_save (EvAttachment *attachment,
286                     const gchar  *uri,
287                     GError      **error)
288 {
289         GnomeVFSHandle  *handle = NULL;
290         GnomeVFSFileSize written;
291         GnomeVFSResult   result;
292         
293         g_return_val_if_fail (EV_IS_ATTACHMENT (attachment), FALSE);
294         g_return_val_if_fail (uri != NULL, FALSE);
295
296         result = gnome_vfs_create (&handle, uri,
297                                    GNOME_VFS_OPEN_WRITE,
298                                    FALSE, 0644);
299         if (result != GNOME_VFS_OK) {
300                 g_set_error (error,
301                              EV_ATTACHMENT_ERROR, 
302                              (gint) result,
303                              _("Couldn't save attachment “%s”: %s"),
304                              uri, 
305                              gnome_vfs_result_to_string (result));
306                 
307                 return FALSE;
308         }
309
310         result = gnome_vfs_write (handle, attachment->priv->data,
311                                   attachment->priv->size, &written);
312         if (result != GNOME_VFS_OK || written < attachment->priv->size){
313                 g_set_error (error,
314                              EV_ATTACHMENT_ERROR,
315                              (gint) result,
316                              _("Couldn't save attachment “%s”: %s"),
317                              uri,
318                              gnome_vfs_result_to_string (result));
319                 
320                 gnome_vfs_close (handle);
321
322                 return FALSE;
323         }
324
325         gnome_vfs_close (handle);
326
327         return TRUE;
328 }
329
330 static gboolean
331 ev_attachment_launch_app (EvAttachment *attachment,
332                           GError      **error)
333 {
334         GnomeVFSResult result;
335         GList         *uris = NULL;
336
337         g_assert (attachment->priv->tmp_uri != NULL);
338         g_assert (attachment->priv->app != NULL);
339
340         uris = g_list_prepend (uris, attachment->priv->tmp_uri);
341         result = gnome_vfs_mime_application_launch (attachment->priv->app,
342                                                     uris);
343
344         if (result != GNOME_VFS_OK) {
345                 g_set_error (error,
346                              EV_ATTACHMENT_ERROR,
347                              (gint) result,
348                              _("Couldn't open attachment “%s”: %s"),
349                              attachment->priv->name,
350                              gnome_vfs_result_to_string (result));
351
352                 g_list_free (uris);
353                 
354                 return FALSE;
355         }
356
357         g_list_free (uris);
358         
359         return TRUE;
360 }
361
362 gboolean
363 ev_attachment_open (EvAttachment *attachment,
364                     GError      **error)
365 {
366
367         gboolean                 retval = FALSE;
368         GnomeVFSMimeApplication *default_app = NULL;
369
370         g_return_val_if_fail (EV_IS_ATTACHMENT (attachment), FALSE);
371         
372         if (!attachment->priv->app) {
373                 default_app = gnome_vfs_mime_get_default_application (attachment->priv->mime_type);
374                 attachment->priv->app = default_app;
375         }
376
377         if (!attachment->priv->app) {
378                 g_set_error (error,
379                              EV_ATTACHMENT_ERROR,
380                              0,
381                              _("Couldn't open attachment “%s”"),
382                              attachment->priv->name);
383                 
384                 return FALSE;
385         }
386
387         if (attachment->priv->tmp_uri &&
388             g_file_test (attachment->priv->tmp_uri, G_FILE_TEST_EXISTS)) {
389                 retval = ev_attachment_launch_app (attachment, error);
390         } else {
391                 gchar *uri, *filename;
392                 
393                 filename = g_build_filename (ev_tmp_dir (), attachment->priv->name, NULL);
394                 uri = g_filename_to_uri (filename, NULL, NULL);
395
396                 if (ev_attachment_save (attachment, uri, error)) {
397                         if (attachment->priv->tmp_uri)
398                                 g_free (attachment->priv->tmp_uri);
399                         attachment->priv->tmp_uri = g_strdup (filename);
400
401                         retval = ev_attachment_launch_app (attachment, error);
402                 }
403
404                 g_free (filename);
405                 g_free (uri);
406         }
407
408         return retval;
409 }