]> www.fi.muni.cz Git - evince.git/blob - backend/ev-attachment.c
*** empty log message ***
[evince.git] / backend / 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-attachment.h"
26
27 enum
28 {
29         PROP_0,
30         PROP_NAME,
31         PROP_DESCRIPTION,
32         PROP_MTIME,
33         PROP_CTIME,
34         PROP_SIZE,
35         PROP_DATA
36 };
37
38 struct _EvAttachmentPrivate {
39         gchar                   *name;
40         gchar                   *description;
41         GTime                    mtime;
42         GTime                    ctime;
43         gsize                    size;
44         gchar                   *data;
45         gchar                   *mime_type;
46
47         GnomeVFSMimeApplication *app;
48         gchar                   *tmp_uri;
49 };
50
51 #define EV_ATTACHMENT_GET_PRIVATE(object) \
52                 (G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_ATTACHMENT, EvAttachmentPrivate))
53
54 G_DEFINE_TYPE (EvAttachment, ev_attachment, G_TYPE_OBJECT)
55
56 GQuark
57 ev_attachment_error_quark (void)
58 {
59         static GQuark error_quark = 0;
60         
61         if (error_quark == 0)
62                 error_quark =
63                         g_quark_from_static_string ("ev-attachment-error-quark");
64         
65         return error_quark;
66 }
67
68 static void
69 ev_attachment_finalize (GObject *object)
70 {
71         EvAttachment *attachment = EV_ATTACHMENT (object);
72
73         if (attachment->priv->name) {
74                 g_free (attachment->priv->name);
75                 attachment->priv->name = NULL;
76         }
77
78         if (attachment->priv->description) {
79                 g_free (attachment->priv->description);
80                 attachment->priv->description = NULL;
81         }
82
83         if (attachment->priv->data) {
84                 g_free (attachment->priv->data);
85                 attachment->priv->data = NULL;
86         }
87
88         if (attachment->priv->mime_type) {
89                 g_free (attachment->priv->mime_type);
90                 attachment->priv->mime_type = NULL;
91         }
92
93         if (attachment->priv->app) {
94                 gnome_vfs_mime_application_free (attachment->priv->app);
95                 attachment->priv->app = NULL;
96         }
97
98         if (attachment->priv->tmp_uri) {
99                 g_unlink (attachment->priv->tmp_uri);
100                 g_free (attachment->priv->tmp_uri);
101                 attachment->priv->tmp_uri = NULL;
102         }
103
104         (* G_OBJECT_CLASS (ev_attachment_parent_class)->finalize) (object);
105 }
106
107 static void
108 ev_attachment_set_property (GObject      *object,
109                             guint         prop_id,
110                             const GValue *value,
111                             GParamSpec   *param_spec)
112 {
113         EvAttachment *attachment = EV_ATTACHMENT (object);
114
115         switch (prop_id) {
116         case PROP_NAME:
117                 attachment->priv->name = g_value_dup_string (value);
118                 break;
119         case PROP_DESCRIPTION:
120                 attachment->priv->description = g_value_dup_string (value);
121                 break;
122         case PROP_MTIME:
123                 attachment->priv->mtime = g_value_get_ulong (value);
124                 break;
125         case PROP_CTIME:
126                 attachment->priv->ctime = g_value_get_ulong (value);
127                 break;
128         case PROP_SIZE:
129                 attachment->priv->size = g_value_get_uint (value);
130                 break;
131         case PROP_DATA:
132                 attachment->priv->data = g_value_get_pointer (value);
133                 attachment->priv->mime_type =
134                         g_strdup (gnome_vfs_get_mime_type_for_data (attachment->priv->data,
135                                                                     attachment->priv->size));
136                 break;
137         default:
138                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object,
139                                                    prop_id,
140                                                    param_spec);
141                 break;
142         }
143 }
144
145 static void
146 ev_attachment_class_init (EvAttachmentClass *klass)
147 {
148         GObjectClass *g_object_class;
149
150         g_object_class = G_OBJECT_CLASS (klass);
151
152         g_object_class->set_property = ev_attachment_set_property;
153
154         g_type_class_add_private (g_object_class, sizeof (EvAttachmentPrivate));
155
156         /* Properties */
157         g_object_class_install_property (g_object_class,
158                                          PROP_NAME,
159                                          g_param_spec_string ("name",
160                                                               "Name",
161                                                               "The attachment name",
162                                                               NULL,
163                                                               G_PARAM_WRITABLE |
164                                                               G_PARAM_CONSTRUCT_ONLY));
165         g_object_class_install_property (g_object_class,
166                                          PROP_DESCRIPTION,
167                                          g_param_spec_string ("description",
168                                                               "Description",
169                                                               "The attachment description",
170                                                               NULL,
171                                                               G_PARAM_WRITABLE |
172                                                               G_PARAM_CONSTRUCT_ONLY));
173         g_object_class_install_property (g_object_class,
174                                          PROP_MTIME,
175                                          g_param_spec_ulong ("mtime",
176                                                              "ModifiedTime", 
177                                                              "The attachment modification date",
178                                                              0, G_MAXULONG, 0,
179                                                              G_PARAM_WRITABLE |
180                                                              G_PARAM_CONSTRUCT_ONLY));
181         g_object_class_install_property (g_object_class,
182                                          PROP_CTIME,
183                                          g_param_spec_ulong ("ctime",
184                                                              "CreationTime",
185                                                              "The attachment creation date",
186                                                              0, G_MAXULONG, 0,
187                                                              G_PARAM_WRITABLE |
188                                                              G_PARAM_CONSTRUCT_ONLY));
189         g_object_class_install_property (g_object_class,
190                                          PROP_SIZE,
191                                          g_param_spec_uint ("size",
192                                                             "Size",
193                                                             "The attachment size",
194                                                             0, G_MAXUINT, 0,
195                                                             G_PARAM_WRITABLE |
196                                                             G_PARAM_CONSTRUCT_ONLY));
197         g_object_class_install_property (g_object_class,
198                                          PROP_DATA,
199                                          g_param_spec_pointer ("data",
200                                                                "Data",
201                                                                "The attachment data",
202                                                                G_PARAM_WRITABLE |
203                                                                G_PARAM_CONSTRUCT_ONLY));
204         
205         g_object_class->finalize = ev_attachment_finalize;
206 }
207
208 static void
209 ev_attachment_init (EvAttachment *attachment)
210 {
211         attachment->priv = EV_ATTACHMENT_GET_PRIVATE (attachment);
212
213         attachment->priv->name = NULL;
214         attachment->priv->description = NULL;
215         attachment->priv->data = NULL;
216         attachment->priv->mime_type = NULL;
217
218         attachment->priv->tmp_uri = NULL;
219 }
220
221 EvAttachment *
222 ev_attachment_new (const gchar *name,
223                    const gchar *description,
224                    GTime        mtime,
225                    GTime        ctime,
226                    gsize        size,
227                    gpointer     data)
228 {
229         EvAttachment *attachment;
230
231         attachment = g_object_new (EV_TYPE_ATTACHMENT,
232                                    "name", name,
233                                    "description", description,
234                                    "mtime", mtime,
235                                    "ctime", ctime,
236                                    "size", size,
237                                    "data", data,
238                                    NULL);
239
240         return attachment;
241 }
242
243 const gchar *
244 ev_attachment_get_name (EvAttachment *attachment)
245 {
246         g_return_val_if_fail (EV_IS_ATTACHMENT (attachment), NULL);
247
248         return attachment->priv->name;
249 }
250
251 const gchar *
252 ev_attachment_get_description (EvAttachment *attachment)
253 {
254         g_return_val_if_fail (EV_IS_ATTACHMENT (attachment), NULL);
255
256         return attachment->priv->description;
257 }
258
259 GTime
260 ev_attachment_get_modification_date (EvAttachment *attachment)
261 {
262         g_return_val_if_fail (EV_IS_ATTACHMENT (attachment), 0);
263
264         return attachment->priv->mtime;
265 }
266
267 GTime
268 ev_attachment_get_creation_date (EvAttachment *attachment)
269 {
270         g_return_val_if_fail (EV_IS_ATTACHMENT (attachment), 0);
271
272         return attachment->priv->ctime;
273 }
274
275 const gchar *
276 ev_attachment_get_mime_type (EvAttachment *attachment)
277 {
278         g_return_val_if_fail (EV_IS_ATTACHMENT (attachment), NULL);
279
280         return attachment->priv->mime_type;
281 }
282
283 gboolean
284 ev_attachment_save (EvAttachment *attachment,
285                     const gchar  *uri,
286                     GError      **error)
287 {
288         GnomeVFSHandle  *handle = NULL;
289         GnomeVFSFileSize written;
290         GnomeVFSResult   result;
291         
292         g_return_val_if_fail (EV_IS_ATTACHMENT (attachment), FALSE);
293         g_return_val_if_fail (uri != NULL, FALSE);
294
295         result = gnome_vfs_create (&handle, uri,
296                                    GNOME_VFS_OPEN_WRITE |
297                                    GNOME_VFS_OPEN_TRUNCATE,
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 (g_get_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 }