]> www.fi.muni.cz Git - evince.git/blob - cut-n-paste/recent-files/egg-recent-item.c
bf7fee6c636d153d55d45d64b76bd6ed3c639356
[evince.git] / cut-n-paste / recent-files / egg-recent-item.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as
5  * published by the Free Software Foundation; either version 2 of the
6  * License, or (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
16  *
17  * Authors:
18  *   James Willcox <jwillcox@cs.indiana.edu>
19  */
20
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <glib.h>
25 #include <libgnomevfs/gnome-vfs.h>
26 #include <libgnomevfs/gnome-vfs-mime-utils.h>
27 #include "egg-recent-item.h"
28
29
30
31 EggRecentItem *
32 egg_recent_item_new (void)
33 {
34         EggRecentItem *item;
35
36         item = g_new (EggRecentItem, 1);
37
38         item->groups = NULL;
39         item->private_data = FALSE;
40         item->uri = NULL;
41         item->mime_type = NULL;
42         item->mime_type_is_explicit = FALSE;
43
44         item->refcount = 1;
45
46         return item;
47 }
48
49 static void
50 egg_recent_item_free (EggRecentItem *item)
51 {
52         if (item->uri)
53                 g_free (item->uri);
54
55         if (item->mime_type)
56                 g_free (item->mime_type);
57
58         if (item->groups) {
59                 g_list_foreach (item->groups, (GFunc)g_free, NULL);
60                 g_list_free (item->groups);
61                 item->groups = NULL;
62         }
63
64         g_free (item);
65 }
66
67 EggRecentItem *
68 egg_recent_item_ref (EggRecentItem *item)
69 {
70         item->refcount++;
71         return item;
72 }
73
74 EggRecentItem *
75 egg_recent_item_unref (EggRecentItem *item)
76 {
77         item->refcount--;
78
79         if (item->refcount == 0) {
80                 egg_recent_item_free (item);
81         }
82
83         return item;
84 }
85
86
87 EggRecentItem * 
88 egg_recent_item_new_from_uri (const gchar *uri)
89 {
90         EggRecentItem *item;
91
92         g_return_val_if_fail (uri != NULL, NULL);
93
94         item = egg_recent_item_new ();
95
96         if (!egg_recent_item_set_uri (item ,uri)) {
97                 egg_recent_item_free (item);
98                 return NULL;
99         }
100         
101         return item;
102 }
103
104 /*
105 static GList *
106 egg_recent_item_copy_groups (const GList *list)
107 {
108         GList *newlist = NULL;
109
110         while (list) {
111                 gchar *group = (gchar *)list->data;
112
113                 newlist = g_list_prepend (newlist, g_strdup (group));
114
115                 list = list->next;
116         }
117
118         return newlist;
119 }
120
121
122 EggRecentItem *
123 egg_recent_item_copy (const EggRecentItem *item)
124 {
125         EggRecentItem *newitem;
126
127         newitem = egg_recent_item_new ();
128         newitem->uri = g_strdup (item->uri);
129         if (item->mime_type)
130                 newitem->mime_type = g_strdup (item->mime_type);
131         newitem->mime_type_is_explicit = item->mime_type_is_explicit
132         newitem->timestamp = item->timestamp;
133         newitem->private_data = item->private_data;
134         newitem->groups = egg_recent_item_copy_groups (item->groups);
135
136         return newitem;
137 }
138 */
139
140 /*
141 EggRecentItem *
142 egg_recent_item_new_valist (const gchar *uri, va_list args)
143 {
144         EggRecentItem *item;
145         EggRecentArg arg;
146         gchar *str1;
147         gchar *str2;
148         gboolean priv;
149
150         item = egg_recent_item_new ();
151
152         arg = va_arg (args, EggRecentArg);
153
154         while (arg != EGG_RECENT_ARG_NONE) {
155                 switch (arg) {
156                         case EGG_RECENT_ARG_MIME_TYPE:
157                                 str1 = va_arg (args, gchar*);
158
159                                 egg_recent_item_set_mime_type (item, str1);
160                         break;
161                         case EGG_RECENT_ARG_GROUP:
162                                 str1 = va_arg (args, gchar*);
163
164                                 egg_recent_item_add_group (item, str1);
165                         break;
166                         case EGG_RECENT_ARG_PRIVATE:
167                                 priv = va_arg (args, gboolean);
168
169                                 egg_recent_item_set_private (item, priv);
170                         break;
171                         default:
172                         break;
173                 }
174
175                 arg = va_arg (args, EggRecentArg);
176         }
177
178         return item;
179 }
180 */
181
182 static void
183 egg_recent_item_update_mime_type (EggRecentItem *item)
184 {
185         if (!item->mime_type_is_explicit) {
186                 g_free (item->mime_type);
187                 item->mime_type = NULL;
188
189                 if (item->uri)
190                         item->mime_type = gnome_vfs_get_mime_type (item->uri);
191
192                 if (!item->mime_type)
193                         item->mime_type = g_strdup (GNOME_VFS_MIME_TYPE_UNKNOWN);
194         }
195 }
196
197 gboolean
198 egg_recent_item_set_uri (EggRecentItem *item, const gchar *uri)
199 {
200         gchar *utf8_uri;
201
202         /* if G_BROKEN_FILENAMES is not set, this should succede */
203         if (g_utf8_validate (uri, -1, NULL)) {
204                 item->uri = gnome_vfs_make_uri_from_input (uri);
205         } else {
206                 utf8_uri = g_filename_to_utf8 (uri, -1, NULL, NULL, NULL);
207
208                 if (utf8_uri == NULL) {
209                         g_warning ("Couldn't convert URI to UTF-8");
210                         return FALSE;
211                 }
212
213                 if (g_utf8_validate (utf8_uri, -1, NULL)) {
214                         item->uri = gnome_vfs_make_uri_from_input (utf8_uri);
215                 } else {
216                         g_free (utf8_uri);
217                         return FALSE;
218                 }
219
220                 g_free (utf8_uri);
221         }
222
223         return TRUE;
224 }
225
226 gchar * 
227 egg_recent_item_get_uri (const EggRecentItem *item)
228 {
229         return g_strdup (item->uri);
230 }
231
232 G_CONST_RETURN gchar * 
233 egg_recent_item_peek_uri (const EggRecentItem *item)
234 {
235         return item->uri;
236 }
237
238 gchar * 
239 egg_recent_item_get_uri_utf8 (const EggRecentItem *item)
240 {
241         /* this could fail, but it's not likely, since we've already done it
242          * once in set_uri()
243          */
244         return g_filename_to_utf8 (item->uri, -1, NULL, NULL, NULL);
245 }
246
247 gchar *
248 egg_recent_item_get_uri_for_display (const EggRecentItem *item)
249 {
250         return gnome_vfs_format_uri_for_display (item->uri);
251 }
252
253 /* Stolen from gnome_vfs_make_valid_utf8() */
254 static char *
255 make_valid_utf8 (const char *name)
256 {
257         GString *string;
258         const char *remainder, *invalid;
259         int remaining_bytes, valid_bytes;
260
261         string = NULL;
262         remainder = name;
263         remaining_bytes = name ? strlen (name) : 0;
264
265         while (remaining_bytes != 0) {
266                 if (g_utf8_validate (remainder, remaining_bytes, &invalid))
267                         break;
268
269                 valid_bytes = invalid - remainder;
270
271                 if (string == NULL)
272                         string = g_string_sized_new (remaining_bytes);
273
274                 g_string_append_len (string, remainder, valid_bytes);
275                 g_string_append_c (string, '?');
276
277                 remaining_bytes -= valid_bytes + 1;
278                 remainder = invalid + 1;
279         }
280
281         if (string == NULL)
282                 return g_strdup (name);
283
284         g_string_append (string, remainder);
285 /*      g_string_append (string, _(" (invalid file name)")); */
286         g_assert (g_utf8_validate (string->str, -1, NULL));
287
288         return g_string_free (string, FALSE);
289 }
290
291 /**
292  * egg_recent_item_get_short_name:
293  * @item: an #EggRecentItem
294  *
295  * Computes a valid UTF-8 string that can be used as the name of the item in a
296  * menu or list.  For example, calling this function on an item that refers to
297  * "file:///foo/bar.txt" will yield "bar.txt".
298  *
299  * Return value: A newly-allocated string in UTF-8 encoding; free it with
300  * g_free().
301  **/
302 gchar *
303 egg_recent_item_get_short_name (const EggRecentItem *item)
304 {
305         GnomeVFSURI *uri;
306         char *short_name;
307         gboolean valid;
308
309         g_return_val_if_fail (item != NULL, NULL);
310
311         if (item->uri == NULL)
312                 return NULL;
313
314         uri = gnome_vfs_uri_new (item->uri);
315         if (uri == NULL)
316                 return NULL;
317
318         short_name = gnome_vfs_uri_extract_short_name (uri);
319         if (short_name == NULL) {
320                 gnome_vfs_uri_unref (uri);
321                 return NULL;
322         }
323
324         valid = FALSE;
325
326         if (strcmp (gnome_vfs_uri_get_scheme (uri), "file") == 0) {
327                 char *tmp;
328
329                 tmp = g_filename_to_utf8 (short_name, -1, NULL, NULL, NULL);
330                 if (tmp) {
331                         g_free (short_name);
332                         short_name = tmp;
333                         valid = TRUE;
334                 }
335         }
336
337         if (!valid) {
338                 char *tmp;
339
340                 tmp = make_valid_utf8 (short_name);
341                 g_assert (tmp != NULL);
342                 g_free (short_name);
343                 short_name = tmp;
344         }
345
346         gnome_vfs_uri_unref (uri);
347
348         return short_name;
349 }
350
351 void 
352 egg_recent_item_set_mime_type (EggRecentItem *item, const gchar *mime)
353 {
354         g_free (item->mime_type);
355         item->mime_type = NULL;
356
357         if (mime && mime[0]) {
358                 item->mime_type_is_explicit = TRUE;
359                 item->mime_type             = g_strdup (mime);
360         } else {
361                 item->mime_type_is_explicit = FALSE;
362         }
363 }
364
365 gchar * 
366 egg_recent_item_get_mime_type (EggRecentItem *item)
367 {
368         egg_recent_item_update_mime_type (item);
369
370         return g_strdup (item->mime_type);
371 }
372
373 void 
374 egg_recent_item_set_timestamp (EggRecentItem *item, time_t timestamp)
375 {
376         if (timestamp == (time_t) -1)
377                 time (&timestamp);
378
379         item->timestamp = timestamp;
380 }
381
382 time_t 
383 egg_recent_item_get_timestamp (const EggRecentItem *item)
384 {
385         return item->timestamp;
386 }
387
388 G_CONST_RETURN GList *
389 egg_recent_item_get_groups (const EggRecentItem *item)
390 {
391         return item->groups;
392 }
393
394 gboolean
395 egg_recent_item_in_group (const EggRecentItem *item, const gchar *group_name)
396 {
397         GList *tmp;
398
399         tmp = item->groups;
400         while (tmp != NULL) {
401                 gchar *val = (gchar *)tmp->data;
402                 
403                 if (strcmp (group_name, val) == 0)
404                         return TRUE;
405
406                 tmp = tmp->next;
407         }
408         
409         return FALSE;
410 }
411
412 void
413 egg_recent_item_add_group (EggRecentItem *item, const gchar *group_name)
414 {
415         g_return_if_fail (group_name != NULL);
416
417         if (!egg_recent_item_in_group (item, group_name))
418                 item->groups = g_list_append (item->groups, g_strdup (group_name));
419 }
420
421 void
422 egg_recent_item_remove_group (EggRecentItem *item, const gchar *group_name)
423 {
424         GList *tmp;
425
426         g_return_if_fail (group_name != NULL);
427
428         tmp = item->groups;
429         while (tmp != NULL) {
430                 gchar *val = (gchar *)tmp->data;
431                 
432                 if (strcmp (group_name, val) == 0) {
433                         item->groups = g_list_remove (item->groups,
434                                                       val);
435                         g_free (val);
436                         break;
437                 }
438
439                 tmp = tmp->next;
440         }
441 }
442
443 void
444 egg_recent_item_set_private (EggRecentItem *item, gboolean priv)
445 {
446         item->private_data = priv;
447 }
448
449 gboolean
450 egg_recent_item_get_private (const EggRecentItem *item)
451 {
452         return item->private_data;
453 }
454
455 GType
456 egg_recent_item_get_type (void)
457 {
458         static GType boxed_type = 0;
459         
460         if (!boxed_type) {
461                 boxed_type = g_boxed_type_register_static ("EggRecentItem",
462                                         (GBoxedCopyFunc)egg_recent_item_ref,
463                                         (GBoxedFreeFunc)egg_recent_item_unref);
464         }
465         
466         return boxed_type;
467 }