~elementary-apps/pantheon-files/trunk

« back to all changes in this revision

Viewing changes to src/gof-file.c

  • Committer: am.monkeyd at gmail
  • Date: 2010-11-08 13:17:02 UTC
  • Revision ID: am.monkeyd@gmail.com-20101108131702-rqeywh4r5pyx2ycz
let's roll

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 
2
/*
 
3
 * Copyright (C) 2010 ammonkey
 
4
 *
 
5
 * This library is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU Lesser General Public License
 
7
 * version 3.0 as published by the Free Software Foundation.
 
8
 *
 
9
 * This library is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU Lesser General Public License version 3.0 for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU Lesser General Public
 
15
 * License along with this library. If not, see
 
16
 * <http://www.gnu.org/licenses/>.
 
17
 *
 
18
 * Author: ammonkey <am.monkeyd@gmail.com>
 
19
 */
 
20
 
 
21
#include "gof-file.h"
 
22
#include <stdlib.h>
 
23
#include <string.h>
 
24
#include "nautilus-icon-info.h"
 
25
#include "marlin-global-preferences.h" 
 
26
#include "eel-i18n.h"
 
27
#include "eel-fcts.h"
 
28
 
 
29
 
 
30
/*struct _GOFFilePrivate {
 
31
        GFileInfo* _file_info;
 
32
};*/
 
33
 
 
34
 
 
35
//#define gof_FILE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GOF_TYPE_FILE, GOFFilePrivate))
 
36
/*enum  {
 
37
        gof_FILE_DUMMY_PROPERTY,
 
38
        gof_FILE_NAME,
 
39
        gof_FILE_SIZE,
 
40
        gof_FILE_DIRECTORY
 
41
};*/
 
42
 
 
43
enum {
 
44
        FM_LIST_MODEL_FILE_COLUMN,
 
45
        FM_LIST_MODEL_ICON,
 
46
        FM_LIST_MODEL_FILENAME,
 
47
        FM_LIST_MODEL_SIZE,
 
48
        FM_LIST_MODEL_TYPE,
 
49
        FM_LIST_MODEL_MODIFIED,
 
50
        /*FM_LIST_MODEL_SUBDIRECTORY_COLUMN,
 
51
        FM_LIST_MODEL_SMALLEST_ICON_COLUMN,
 
52
        FM_LIST_MODEL_SMALLER_ICON_COLUMN,
 
53
        FM_LIST_MODEL_SMALL_ICON_COLUMN,
 
54
        FM_LIST_MODEL_STANDARD_ICON_COLUMN,
 
55
        FM_LIST_MODEL_LARGE_ICON_COLUMN,
 
56
        FM_LIST_MODEL_LARGER_ICON_COLUMN,
 
57
        FM_LIST_MODEL_LARGEST_ICON_COLUMN,
 
58
        FM_LIST_MODEL_SMALLEST_EMBLEM_COLUMN,
 
59
        FM_LIST_MODEL_SMALLER_EMBLEM_COLUMN,
 
60
        FM_LIST_MODEL_SMALL_EMBLEM_COLUMN,
 
61
        FM_LIST_MODEL_STANDARD_EMBLEM_COLUMN,
 
62
        FM_LIST_MODEL_LARGE_EMBLEM_COLUMN,
 
63
        FM_LIST_MODEL_LARGER_EMBLEM_COLUMN,
 
64
        FM_LIST_MODEL_LARGEST_EMBLEM_COLUMN,
 
65
        FM_LIST_MODEL_FILE_NAME_IS_EDITABLE_COLUMN,*/
 
66
        FM_LIST_MODEL_NUM_COLUMNS
 
67
};
 
68
 
 
69
 
 
70
//static void gof_file_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec);
 
71
//static void gof_file_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec);
 
72
 
 
73
G_DEFINE_TYPE (GOFFile, gof_file, G_TYPE_OBJECT)
 
74
 
 
75
#define SORT_LAST_CHAR1 '.'
 
76
#define SORT_LAST_CHAR2 '#'
 
77
 
 
78
/*        
 
79
static int _vala_strcmp0 (const char * str1, const char * str2) {
 
80
        if (str1 == NULL) {
 
81
                return -(str1 != str2);
 
82
        }
 
83
        if (str2 == NULL) {
 
84
                return str1 != str2;
 
85
        }
 
86
        return strcmp (str1, str2);
 
87
}*/
 
88
 
 
89
#if 0
 
90
gint gof_file_NameCompareFunc (GOFFile* a, GOFFile* b) {
 
91
        gint result = 0;
 
92
        g_return_val_if_fail (a != NULL, 0);
 
93
        g_return_val_if_fail (b != NULL, 0);
 
94
        if (gof_file_get_directory (a) != gof_file_get_directory (b)) {
 
95
                result = ((gint) gof_file_get_directory (b)) - ((gint) gof_file_get_directory (a));
 
96
                return result;
 
97
        } else {
 
98
                char* _tmp1_ = g_utf8_casefold (gof_file_get_name (b), -1);
 
99
                char* _tmp0_ = g_utf8_casefold (gof_file_get_name (a), -1);
 
100
                if (_vala_strcmp0 (_tmp0_, _tmp1_) < 0) {
 
101
                        _g_free0 (_tmp1_);
 
102
                        _g_free0 (_tmp0_);
 
103
                        return -1;
 
104
                } else {
 
105
                        char* _tmp4_;
 
106
                        char* _tmp3_;
 
107
                        gboolean _tmp5_;
 
108
                        if ((_tmp5_ = _vala_strcmp0 (_tmp3_ = g_utf8_casefold (gof_file_get_name (a), -1), _tmp4_ = g_utf8_casefold (gof_file_get_name (b), -1)) == 0, _g_free0 (_tmp4_), _g_free0 (_tmp3_), _tmp5_)) {
 
109
                                result = 0;
 
110
                                return result;
 
111
                        } else {
 
112
                                result = 1;
 
113
                                return result;
 
114
                        }
 
115
                }
 
116
        }
 
117
}
 
118
 
 
119
gint gof_file_SizeCompareFunc (GOFFile* a, GOFFile* b) {
 
120
        gint result = 0;
 
121
        g_return_val_if_fail (a != NULL, 0);
 
122
        g_return_val_if_fail (b != NULL, 0);
 
123
        if (gof_file_get_directory (a) != gof_file_get_directory (b)) {
 
124
                result = ((gint) gof_file_get_directory (b)) - ((gint) gof_file_get_directory (a));
 
125
                return result;
 
126
        } else {
 
127
                if (gof_file_get_size (a) < gof_file_get_size (b)) {
 
128
                        result = -1;
 
129
                        return result;
 
130
                } else {
 
131
                        if (gof_file_get_size (a) > gof_file_get_size (b)) {
 
132
                                result = 1;
 
133
                                return result;
 
134
                        } else {
 
135
                                result = 0;
 
136
                                return result;
 
137
                        }
 
138
                }
 
139
        }
 
140
}
 
141
#endif
 
142
 
 
143
//GOFFile* gof_file_new (GFileInfo* file_info, GFileEnumerator *enumerator)
 
144
GOFFile* gof_file_new (GFileInfo* file_info, GFile *dir)
 
145
{
 
146
        GOFFile * self;
 
147
        NautilusIconInfo *nicon;
 
148
 
 
149
        g_return_val_if_fail (file_info != NULL, NULL);
 
150
        self = (GOFFile*) g_object_new (GOF_TYPE_FILE, NULL);
 
151
        self->info = file_info;
 
152
        //self->parent_dir = g_file_enumerator_get_container (enumerator);
 
153
        self->directory = dir;
 
154
        //printf ("test parent_dir %s\n", g_file_get_uri(self->directory));
 
155
        //g_object_ref (self->directory);
 
156
        self->name = g_file_info_get_name (file_info);
 
157
        self->location = g_file_get_child(self->directory, self->name);
 
158
        self->ftype = g_file_info_get_attribute_string (file_info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE);
 
159
        self->utf8_collation_key = g_utf8_collate_key (self->name, -1);
 
160
        self->size = (guint64) g_file_info_get_size (file_info);
 
161
        self->format_size = g_format_size_for_display(self->size);
 
162
        self->file_type = g_file_info_get_file_type(file_info);
 
163
        //self->is_directory = (self->file_type & G_FILE_TYPE_DIRECTORY) != 0;
 
164
        self->is_directory = (self->file_type == G_FILE_TYPE_DIRECTORY);
 
165
        self->icon = g_content_type_get_icon (self->ftype);
 
166
        self->is_hidden = g_file_info_get_is_hidden (file_info);
 
167
        self->modified = g_file_info_get_attribute_uint64 (file_info, G_FILE_ATTRIBUTE_TIME_MODIFIED);
 
168
 
 
169
        nicon = nautilus_icon_info_lookup (self->icon, 16);
 
170
        self->pix = nautilus_icon_info_get_pixbuf_nodefault (nicon);
 
171
        g_object_unref (nicon);
 
172
        
 
173
        return self;
 
174
}
 
175
 
 
176
 
 
177
GFileInfo* gof_file_get_file_info (GOFFile* self) {
 
178
        GFileInfo* result;
 
179
        g_return_val_if_fail (self != NULL, NULL);
 
180
        result = self->info;
 
181
        return result;
 
182
}
 
183
 
 
184
static void gof_file_init (GOFFile *self) {
 
185
        ;
 
186
}
 
187
 
 
188
static void gof_file_finalize (GObject* obj) {
 
189
        GOFFile *file;
 
190
 
 
191
        file = GOF_FILE (obj);
 
192
        printf ("%s %s\n", G_STRFUNC, file->name);
 
193
        _g_object_unref0 (file->info);
 
194
        _g_object_unref0 (file->location);
 
195
        g_free(file->utf8_collation_key);
 
196
        g_free(file->format_size);
 
197
        _g_object_unref0 (file->icon);
 
198
        _g_object_unref0 (file->pix);
 
199
        
 
200
        G_OBJECT_CLASS (gof_file_parent_class)->finalize (obj);
 
201
}
 
202
 
 
203
static void gof_file_class_init (GOFFileClass * klass) {
 
204
        gof_file_parent_class = g_type_class_peek_parent (klass);
 
205
        //g_type_class_add_private (klass, sizeof (GOFFilePrivate));
 
206
        /*G_OBJECT_CLASS (klass)->get_property = gof_file_get_property;
 
207
        G_OBJECT_CLASS (klass)->set_property = gof_file_set_property;*/
 
208
        G_OBJECT_CLASS (klass)->finalize = gof_file_finalize;
 
209
        /*g_object_class_install_property (G_OBJECT_CLASS (klass), gof_FILE_NAME, g_param_spec_string ("name", "name", "name", NULL, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
 
210
        g_object_class_install_property (G_OBJECT_CLASS (klass), gof_FILE_SIZE, g_param_spec_uint64 ("size", "size", "size", 0, G_MAXUINT64, 0U, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));
 
211
        g_object_class_install_property (G_OBJECT_CLASS (klass), gof_FILE_DIRECTORY, g_param_spec_boolean ("directory", "directory", "directory", FALSE, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE));*/
 
212
}
 
213
 
 
214
/*
 
215
static void gof_file_instance_init (GOFFile * self) {
 
216
        self->priv = gof_FILE_GET_PRIVATE (self);
 
217
}*/
 
218
 
 
219
#if 0
 
220
GType gof_file_get_type (void) {
 
221
        static volatile gsize gof_file_type_id__volatile = 0;
 
222
        if (g_once_init_enter (&gof_file_type_id__volatile)) {
 
223
                static const GTypeInfo g_define_type_info = { sizeof (GOFFileClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) gof_file_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (GOFFile), 0, (GInstanceInitFunc) gof_file_instance_init, NULL };
 
224
                GType gof_file_type_id;
 
225
                gof_file_type_id = g_type_register_static (G_TYPE_OBJECT, "GOFFile", &g_define_type_info, 0);
 
226
                g_once_init_leave (&gof_file_type_id__volatile, gof_file_type_id);
 
227
        }
 
228
        return gof_file_type_id__volatile;
 
229
}
 
230
#endif
 
231
 
 
232
#if 0
 
233
static void gof_file_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) {
 
234
        GOFFile * self;
 
235
        self = GOF_FILE (object);
 
236
        switch (property_id) {
 
237
                case gof_FILE_NAME:
 
238
                g_value_set_string (value, gof_file_get_name (self));
 
239
                break;
 
240
                case gof_FILE_SIZE:
 
241
                g_value_set_uint64 (value, gof_file_get_size (self));
 
242
                break;
 
243
                case gof_FILE_DIRECTORY:
 
244
                g_value_set_boolean (value, gof_file_get_directory (self));
 
245
                break;
 
246
                default:
 
247
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
248
                break;
 
249
        }
 
250
}
 
251
 
 
252
 
 
253
static void gof_file_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec) {
 
254
        GOFFile * self;
 
255
        self = GOF_FILE (object);
 
256
        switch (property_id) {
 
257
                default:
 
258
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
259
                break;
 
260
        }
 
261
}
 
262
#endif
 
263
 
 
264
static int
 
265
compare_files_by_time (GOFFile *file1, GOFFile *file2)
 
266
{
 
267
        if (file1->modified < file2->modified)
 
268
                return -1;
 
269
        else if (file1->modified > file2->modified)
 
270
                return 1;
 
271
 
 
272
        return 0;
 
273
}
 
274
 
 
275
static int
 
276
compare_by_time (GOFFile *file1, GOFFile *file2)
 
277
{
 
278
        if (file1->is_directory && !file2->is_directory)
 
279
                return -1;
 
280
        if (file2->is_directory && !file1->is_directory)
 
281
                return 1;
 
282
 
 
283
        return compare_files_by_time (file1, file2);
 
284
}
 
285
 
 
286
static int
 
287
compare_by_type (GOFFile *file1, GOFFile *file2)
 
288
{
 
289
        /*char *type_string_1;
 
290
        char *type_string_2;
 
291
        int result;*/
 
292
 
 
293
        /* Directories go first. Then, if mime types are identical,
 
294
         * don't bother getting strings (for speed). This assumes
 
295
         * that the string is dependent entirely on the mime type,
 
296
         * which is true now but might not be later.
 
297
         */
 
298
        if (file1->is_directory && file2->is_directory)
 
299
                return 0;
 
300
        if (file1->is_directory)
 
301
                return -1;
 
302
        if (file2->is_directory)
 
303
                return +1;
 
304
#if 0   
 
305
        if (file1->ftype != NULL && file2->ftype != NULL &&
 
306
            strcmp (eel_ref_str_peek (file_1->details->mime_type),
 
307
                    eel_ref_str_peek (file_2->details->mime_type)) == 0) {
 
308
                return 0;
 
309
        }
 
310
 
 
311
        type_string_1 = nautilus_file_get_type_as_string (file_1);
 
312
        type_string_2 = nautilus_file_get_type_as_string (file_2);
 
313
 
 
314
        result = g_utf8_collate (type_string_1, type_string_2);
 
315
 
 
316
        g_free (type_string_1);
 
317
        g_free (type_string_2);
 
318
#endif
 
319
        return (strcmp (file1->utf8_collation_key, file2->utf8_collation_key));
 
320
        //return result;
 
321
}
 
322
 
 
323
static int
 
324
compare_by_display_name (GOFFile *file1, GOFFile *file2)
 
325
{
 
326
        const char *name_1, *name_2;
 
327
        gboolean sort_last_1, sort_last_2;
 
328
        int compare;
 
329
 
 
330
        name_1 = file1->name;
 
331
        name_2 = file2->name;
 
332
 
 
333
        sort_last_1 = name_1[0] == SORT_LAST_CHAR1 || name_1[0] == SORT_LAST_CHAR2;
 
334
        sort_last_2 = name_2[0] == SORT_LAST_CHAR1 || name_2[0] == SORT_LAST_CHAR2;
 
335
 
 
336
        if (sort_last_1 && !sort_last_2) {
 
337
                compare = +1;
 
338
        } else if (!sort_last_1 && sort_last_2) {
 
339
                compare = -1;
 
340
        } else {
 
341
                compare = strcmp (file1->utf8_collation_key, file2->utf8_collation_key);
 
342
        }
 
343
 
 
344
        return compare;
 
345
}
 
346
 
 
347
static int
 
348
compare_files_by_size (GOFFile *file1, GOFFile *file2)
 
349
{
 
350
        if (file1->size < file2->size) {
 
351
                return -1;
 
352
        }
 
353
        else if (file1->size > file2->size) {
 
354
                return 1;
 
355
        }
 
356
 
 
357
        return 0;
 
358
}
 
359
 
 
360
static int
 
361
compare_by_size (GOFFile *file1, GOFFile *file2)
 
362
{
 
363
        if (file1->is_directory && !file2->is_directory)
 
364
                return -1;
 
365
        if (file2->is_directory && !file1->is_directory)
 
366
                return 1;
 
367
 
 
368
        /*if (file1->is_directory) {
 
369
                return compare_directories_by_count (file1, file2);
 
370
        } else {*/
 
371
                return compare_files_by_size (file1, file2);
 
372
        //}
 
373
}
 
374
 
 
375
static int
 
376
gof_file_compare_for_sort_internal (GOFFile *file1,
 
377
                                    GOFFile *file2,
 
378
                                    gboolean directories_first,
 
379
                                    gboolean reversed)
 
380
{
 
381
        if (directories_first) {
 
382
                if (file1->is_directory && !file2->is_directory) {
 
383
                        return -1;
 
384
                }
 
385
                if (file2->is_directory && !file1->is_directory) {
 
386
                        return 1;
 
387
                }
 
388
        }
 
389
 
 
390
        /*if (file1->details->sort_order < file2->details->sort_order) {
 
391
                return reversed ? 1 : -1;
 
392
        } else if (file_1->details->sort_order > file_2->details->sort_order) {
 
393
                return reversed ? -1 : 1;
 
394
        }*/
 
395
 
 
396
        return 0;
 
397
}
 
398
 
 
399
int
 
400
gof_file_compare_for_sort (GOFFile *file1,
 
401
                           GOFFile *file2,
 
402
                           gint sort_type,
 
403
                           gboolean directories_first,
 
404
                           gboolean reversed)
 
405
{
 
406
        int result;
 
407
 
 
408
        if (file1 == file2) {
 
409
                return 0;
 
410
        }
 
411
 
 
412
        result = gof_file_compare_for_sort_internal (file1, file2, directories_first, reversed);
 
413
        //printf ("res %d %s %s\n", result, file1->name, file2->name);
 
414
 
 
415
        if (result == 0) {
 
416
                switch (sort_type) {
 
417
                case FM_LIST_MODEL_FILENAME:
 
418
                        result = compare_by_display_name (file1, file2);
 
419
                        /*if (result == 0) {
 
420
                                result = compare_by_directory_name (file_1, file_2);
 
421
                        }*/
 
422
                        break;
 
423
                case FM_LIST_MODEL_SIZE:
 
424
                        result = compare_by_size (file1, file2);
 
425
                        break;
 
426
                case FM_LIST_MODEL_TYPE:
 
427
                        result = compare_by_type (file1, file2);
 
428
                        break;
 
429
                case FM_LIST_MODEL_MODIFIED:
 
430
                        result = compare_by_time (file1, file2);
 
431
                        break;
 
432
                }
 
433
 
 
434
                if (reversed) {
 
435
                        result = -result;
 
436
                }
 
437
        }
 
438
#if 0
 
439
        if (result == 0) {
 
440
                switch (sort_type) {
 
441
                case NAUTILUS_FILE_SORT_BY_DISPLAY_NAME:
 
442
                        result = compare_by_display_name (file_1, file_2);
 
443
                        if (result == 0) {
 
444
                                result = compare_by_directory_name (file_1, file_2);
 
445
                        }
 
446
                        break;
 
447
                case NAUTILUS_FILE_SORT_BY_DIRECTORY:
 
448
                        result = compare_by_full_path (file_1, file_2);
 
449
                        break;
 
450
                case NAUTILUS_FILE_SORT_BY_SIZE:
 
451
                        /* Compare directory sizes ourselves, then if necessary
 
452
                         * use GnomeVFS to compare file sizes.
 
453
                         */
 
454
                        result = compare_by_size (file_1, file_2);
 
455
                        if (result == 0) {
 
456
                                result = compare_by_full_path (file_1, file_2);
 
457
                        }
 
458
                        break;
 
459
                case NAUTILUS_FILE_SORT_BY_TYPE:
 
460
                        /* GnomeVFS doesn't know about our special text for certain
 
461
                         * mime types, so we handle the mime-type sorting ourselves.
 
462
                         */
 
463
                        result = compare_by_type (file_1, file_2);
 
464
                        if (result == 0) {
 
465
                                result = compare_by_full_path (file_1, file_2);
 
466
                        }
 
467
                        break;
 
468
                case NAUTILUS_FILE_SORT_BY_MTIME:
 
469
                        result = compare_by_time (file_1, file_2, NAUTILUS_DATE_TYPE_MODIFIED);
 
470
                        if (result == 0) {
 
471
                                result = compare_by_full_path (file_1, file_2);
 
472
                        }
 
473
                        break;
 
474
                case NAUTILUS_FILE_SORT_BY_ATIME:
 
475
                        result = compare_by_time (file_1, file_2, NAUTILUS_DATE_TYPE_ACCESSED);
 
476
                        if (result == 0) {
 
477
                                result = compare_by_full_path (file_1, file_2);
 
478
                        }
 
479
                        break;
 
480
                case NAUTILUS_FILE_SORT_BY_TRASHED_TIME:
 
481
                        result = compare_by_time (file_1, file_2, NAUTILUS_DATE_TYPE_TRASHED);
 
482
                        if (result == 0) {
 
483
                                result = compare_by_full_path (file_1, file_2);
 
484
                        }
 
485
                        break;
 
486
                case NAUTILUS_FILE_SORT_BY_EMBLEMS:
 
487
                        /* GnomeVFS doesn't know squat about our emblems, so
 
488
                         * we handle comparing them here, before falling back
 
489
                         * to tie-breakers.
 
490
                         */
 
491
                        result = compare_by_emblems (file_1, file_2);
 
492
                        if (result == 0) {
 
493
                                result = compare_by_full_path (file_1, file_2);
 
494
                        }
 
495
                        break;
 
496
                default:
 
497
                        g_return_val_if_reached (0);
 
498
                }
 
499
 
 
500
                if (reversed) {
 
501
                        result = -result;
 
502
                }
 
503
        }
 
504
#endif
 
505
        return result;
 
506
}
 
507
 
 
508
GOFFile *
 
509
gof_file_ref (GOFFile *file)
 
510
{
 
511
        if (file == NULL) {
 
512
                return NULL;
 
513
        }
 
514
        g_return_val_if_fail (GOF_IS_FILE (file), NULL);
 
515
 
 
516
        return g_object_ref (file);
 
517
}
 
518
 
 
519
void
 
520
gof_file_unref (GOFFile *file)
 
521
{
 
522
        if (file == NULL) {
 
523
                return;
 
524
        }
 
525
 
 
526
        g_return_if_fail (GOF_IS_FILE (file));
 
527
 
 
528
        g_object_unref (file);
 
529
}
 
530
 
 
531
static const char *TODAY_TIME_FORMATS [] = {
 
532
        /* Today, use special word.
 
533
         * strftime patterns preceeded with the widest
 
534
         * possible resulting string for that pattern.
 
535
         *
 
536
         * Note to localizers: You can look at man strftime
 
537
         * for details on the format, but you should only use
 
538
         * the specifiers from the C standard, not extensions.
 
539
         * These include "%" followed by one of
 
540
         * "aAbBcdHIjmMpSUwWxXyYZ". There are two extensions
 
541
         * in the Nautilus version of strftime that can be
 
542
         * used (and match GNU extensions). Putting a "-"
 
543
         * between the "%" and any numeric directive will turn
 
544
         * off zero padding, and putting a "_" there will use
 
545
         * space padding instead of zero padding.
 
546
         */
 
547
        N_("today at 00:00:00 PM"),
 
548
        N_("today at %-I:%M:%S %p"),
 
549
        
 
550
        N_("today at 00:00 PM"),
 
551
        N_("today at %-I:%M %p"),
 
552
        
 
553
        N_("today, 00:00 PM"),
 
554
        N_("today, %-I:%M %p"),
 
555
        
 
556
        N_("today"),
 
557
        N_("today"),
 
558
 
 
559
        NULL
 
560
};
 
561
 
 
562
static const char *YESTERDAY_TIME_FORMATS [] = {
 
563
        /* Yesterday, use special word.
 
564
         * Note to localizers: Same issues as "today" string.
 
565
         */
 
566
        N_("yesterday at 00:00:00 PM"),
 
567
        N_("yesterday at %-I:%M:%S %p"),
 
568
        
 
569
        N_("yesterday at 00:00 PM"),
 
570
        N_("yesterday at %-I:%M %p"),
 
571
        
 
572
        N_("yesterday, 00:00 PM"),
 
573
        N_("yesterday, %-I:%M %p"),
 
574
        
 
575
        N_("yesterday"),
 
576
        N_("yesterday"),
 
577
 
 
578
        NULL
 
579
};
 
580
 
 
581
static const char *CURRENT_WEEK_TIME_FORMATS [] = {
 
582
        /* Current week, include day of week.
 
583
         * Note to localizers: Same issues as "today" string.
 
584
         * The width measurement templates correspond to
 
585
         * the day/month name with the most letters.
 
586
         */
 
587
        N_("Wednesday, September 00 0000 at 00:00:00 PM"),
 
588
        N_("%A, %B %-d %Y at %-I:%M:%S %p"),
 
589
 
 
590
        N_("Mon, Oct 00 0000 at 00:00:00 PM"),
 
591
        N_("%a, %b %-d %Y at %-I:%M:%S %p"),
 
592
 
 
593
        N_("Mon, Oct 00 0000 at 00:00 PM"),
 
594
        N_("%a, %b %-d %Y at %-I:%M %p"),
 
595
        
 
596
        N_("Oct 00 0000 at 00:00 PM"),
 
597
        N_("%b %-d %Y at %-I:%M %p"),
 
598
        
 
599
        N_("Oct 00 0000, 00:00 PM"),
 
600
        N_("%b %-d %Y, %-I:%M %p"),
 
601
        
 
602
        N_("00/00/00, 00:00 PM"),
 
603
        N_("%m/%-d/%y, %-I:%M %p"),
 
604
 
 
605
        N_("00/00/00"),
 
606
        N_("%m/%d/%y"),
 
607
 
 
608
        NULL
 
609
};
 
610
 
 
611
char *
 
612
gof_file_get_date_as_string (guint64 d)
 
613
{
 
614
        //time_t file_time_raw;
 
615
        struct tm *file_time;
 
616
        const char **formats;
 
617
        const char *width_template;
 
618
        const char *format;
 
619
        char *date_string;
 
620
        //char *result;
 
621
        GDate *today;
 
622
        GDate *file_date;
 
623
        guint32 file_date_age;
 
624
        int i;
 
625
 
 
626
        file_time = localtime (&d);
 
627
 
 
628
        gchar *date_format_pref = g_settings_get_string(settings, MARLIN_PREFERENCES_DATE_FORMAT);
 
629
 
 
630
        if (!strcmp (date_format_pref, "locale"))
 
631
                return eel_strdup_strftime ("%c", file_time);
 
632
        else if (!strcmp (date_format_pref, "iso"))
 
633
                return eel_strdup_strftime ("%Y-%m-%d %H:%M:%S", file_time);
 
634
 
 
635
        file_date = eel_g_date_new_tm (file_time);
 
636
        
 
637
        today = g_date_new ();
 
638
        g_date_set_time_t (today, time (NULL));
 
639
 
 
640
        /* Overflow results in a large number; fine for our purposes. */
 
641
        file_date_age = (g_date_get_julian (today) -
 
642
                         g_date_get_julian (file_date));
 
643
 
 
644
        g_date_free (file_date);
 
645
        g_date_free (today);
 
646
 
 
647
        /* Format varies depending on how old the date is. This minimizes
 
648
         * the length (and thus clutter & complication) of typical dates
 
649
         * while providing sufficient detail for recent dates to make
 
650
         * them maximally understandable at a glance. Keep all format
 
651
         * strings separate rather than combining bits & pieces for
 
652
         * internationalization's sake.
 
653
         */
 
654
 
 
655
        if (file_date_age == 0) {
 
656
                formats = TODAY_TIME_FORMATS;
 
657
        } else if (file_date_age == 1) {
 
658
                formats = YESTERDAY_TIME_FORMATS;
 
659
        } else if (file_date_age < 7) {
 
660
                formats = CURRENT_WEEK_TIME_FORMATS;
 
661
        } else {
 
662
                formats = CURRENT_WEEK_TIME_FORMATS;
 
663
        }
 
664
 
 
665
        /* Find the date format that just fits the required width. Instead of measuring
 
666
         * the resulting string width directly, measure the width of a template that represents
 
667
         * the widest possible version of a date in a given format. This is done by using M, m
 
668
         * and 0 for the variable letters/digits respectively.
 
669
         */
 
670
        format = NULL;
 
671
        
 
672
        for (i = 0; ; i += 2) {
 
673
                width_template = (formats [i] ? _(formats [i]) : NULL);
 
674
                if (width_template == NULL) {
 
675
                        /* no more formats left */
 
676
                        g_assert (format != NULL);
 
677
                        
 
678
                        /* Can't fit even the shortest format -- return an ellipsized form in the
 
679
                         * shortest format
 
680
                         */
 
681
                        
 
682
                        date_string = eel_strdup_strftime (format, file_time);
 
683
 
 
684
                        return date_string;
 
685
                }
 
686
                
 
687
                format = _(formats [i + 1]);
 
688
 
 
689
                /* don't care about fitting the width */
 
690
                break;
 
691
        }
 
692
        
 
693
        return eel_strdup_strftime (format, file_time);
 
694
}
 
695
 
 
696
void
 
697
gof_file_list_unref (GList *list)
 
698
{
 
699
        g_list_foreach (list, (GFunc) gof_file_unref, NULL);
 
700
}
 
701
 
 
702
void
 
703
gof_file_list_free (GList *list)
 
704
{
 
705
        gof_file_list_unref (list);
 
706
        g_list_free (list);
 
707
}
 
708