Mercurial > geeqie
annotate src/filelist.c @ 135:15c1925b3bfb
improved external delete command
| author | nadvornik |
|---|---|
| date | Thu, 16 Aug 2007 20:57:09 +0000 |
| parents | 847e4bc6b54c |
| children | be3328a58875 |
| rev | line source |
|---|---|
| 1 | 1 /* |
| 9 | 2 * GQview |
|
79
528e3432e0c0
Thu Oct 19 07:23:37 2006 John Ellis <johne@verizon.net>
gqview
parents:
53
diff
changeset
|
3 * (C) 2006 John Ellis |
| 1 | 4 * |
| 5 * Author: John Ellis | |
| 6 * | |
| 9 | 7 * This software is released under the GNU General Public License (GNU GPL). |
| 8 * Please read the included file COPYING for more information. | |
| 9 * This software comes with no warranty of any kind, use at your own risk! | |
| 1 | 10 */ |
| 11 | |
| 12 | |
| 9 | 13 #include "gqview.h" |
| 14 #include "filelist.h" | |
| 1 | 15 |
| 9 | 16 #include "cache.h" |
| 17 #include "rcfile.h" | |
|
79
528e3432e0c0
Thu Oct 19 07:23:37 2006 John Ellis <johne@verizon.net>
gqview
parents:
53
diff
changeset
|
18 #include "thumb_standard.h" |
| 9 | 19 #include "ui_fileops.h" |
| 1 | 20 |
| 21 | |
| 22 /* | |
| 23 *----------------------------------------------------------------------------- | |
| 24 * file filtering | |
| 25 *----------------------------------------------------------------------------- | |
| 26 */ | |
| 27 | |
| 9 | 28 static GList *filter_list = NULL; |
| 29 static GList *extension_list = NULL; | |
| 30 | |
| 31 gint ishidden(const gchar *name) | |
| 1 | 32 { |
| 33 if (name[0] != '.') return FALSE; | |
| 34 if (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')) return FALSE; | |
| 35 return TRUE; | |
| 36 } | |
| 37 | |
| 9 | 38 static FilterEntry *filter_entry_new(const gchar *key, const gchar *description, |
| 39 const gchar *extensions, gint enabled) | |
| 40 { | |
| 41 FilterEntry *fe; | |
| 42 | |
| 43 fe = g_new0(FilterEntry, 1); | |
| 44 fe->key = g_strdup(key); | |
| 45 fe->description = g_strdup(description); | |
| 46 fe->extensions = g_strdup(extensions); | |
| 47 fe->enabled = enabled; | |
| 48 | |
| 49 return fe; | |
| 50 } | |
| 51 | |
| 52 static void filter_entry_free(FilterEntry *fe) | |
| 53 { | |
| 54 if (!fe) return; | |
| 55 | |
| 56 g_free(fe->key); | |
| 57 g_free(fe->description); | |
| 58 g_free(fe->extensions); | |
| 59 g_free(fe); | |
| 60 } | |
| 61 | |
| 62 GList *filter_get_list(void) | |
| 63 { | |
| 64 return filter_list; | |
| 65 } | |
| 66 | |
| 67 void filter_remove_entry(FilterEntry *fe) | |
| 68 { | |
| 69 if (!g_list_find(filter_list, fe)) return; | |
| 70 | |
| 71 filter_list = g_list_remove(filter_list, fe); | |
| 72 filter_entry_free(fe); | |
| 73 } | |
| 74 | |
| 75 static gint filter_key_exists(const gchar *key) | |
| 76 { | |
| 77 GList *work; | |
| 78 | |
| 79 if (!key) return FALSE; | |
| 80 | |
| 81 work = filter_list; | |
| 82 while (work) | |
| 83 { | |
| 84 FilterEntry *fe = work->data; | |
| 85 work = work->next; | |
| 86 | |
| 87 if (strcmp(fe->key, key) == 0) return TRUE; | |
| 88 } | |
| 89 | |
| 90 return FALSE; | |
| 91 } | |
| 92 | |
| 93 void filter_add(const gchar *key, const gchar *description, const gchar *extensions, gint enabled) | |
| 94 { | |
| 95 filter_list = g_list_append(filter_list, filter_entry_new(key, description, extensions, enabled)); | |
| 96 } | |
| 97 | |
| 98 void filter_add_unique(const gchar *description, const gchar *extensions, gint enabled) | |
| 99 { | |
| 100 gchar *key; | |
| 101 gint n; | |
| 102 | |
| 103 key = g_strdup("user0"); | |
| 104 n = 1; | |
| 105 while (filter_key_exists(key)) | |
| 106 { | |
| 107 g_free(key); | |
| 108 if (n > 999) return; | |
| 109 key = g_strdup_printf("user%d", n); | |
| 110 n++; | |
| 111 } | |
| 112 | |
| 113 filter_add(key, description, extensions, enabled); | |
| 114 g_free(key); | |
| 115 } | |
| 116 | |
| 117 static void filter_add_if_missing(const gchar *key, const gchar *description, const gchar *extensions, gint enabled) | |
| 118 { | |
| 119 GList *work; | |
| 120 | |
| 121 if (!key) return; | |
| 122 | |
| 123 work = filter_list; | |
| 124 while (work) | |
| 125 { | |
| 126 FilterEntry *fe = work->data; | |
| 127 work = work->next; | |
| 128 if (fe->key && strcmp(fe->key, key) == 0) return; | |
| 129 } | |
| 130 | |
| 131 filter_add(key, description, extensions, enabled); | |
| 132 } | |
| 133 | |
| 134 void filter_reset(void) | |
| 1 | 135 { |
| 136 GList *work; | |
| 9 | 137 |
| 138 work = filter_list; | |
| 139 while (work) | |
| 140 { | |
| 141 FilterEntry *fe = work->data; | |
| 142 work = work->next; | |
| 143 filter_entry_free(fe); | |
| 144 } | |
| 145 | |
| 146 g_list_free(filter_list); | |
| 147 filter_list = NULL; | |
| 148 } | |
| 149 | |
| 150 void filter_add_defaults(void) | |
| 151 { | |
| 152 GSList *list, *work; | |
| 153 | |
| 154 list = gdk_pixbuf_get_formats(); | |
| 155 work = list; | |
| 156 while (work) | |
| 157 { | |
| 158 GdkPixbufFormat *format; | |
| 159 gchar *name; | |
| 160 gchar *desc; | |
| 161 gchar **extensions; | |
| 162 GString *filter = NULL; | |
| 163 gint i; | |
| 164 | |
| 165 format = work->data; | |
| 166 work = work->next; | |
| 167 | |
| 168 name = gdk_pixbuf_format_get_name(format); | |
| 169 desc = gdk_pixbuf_format_get_description(format); | |
| 170 extensions = gdk_pixbuf_format_get_extensions(format); | |
| 171 | |
| 172 i = 0; | |
| 173 while (extensions[i]) | |
| 174 { | |
| 175 if (!filter) | |
| 176 { | |
| 177 filter = g_string_new("."); | |
| 178 filter = g_string_append(filter, extensions[i]); | |
| 179 } | |
| 180 else | |
| 181 { | |
| 182 filter = g_string_append(filter, ";."); | |
| 183 filter = g_string_append(filter, extensions[i]); | |
| 184 } | |
| 185 i++; | |
| 186 } | |
| 187 | |
| 188 if (debug) printf("loader reported [%s] [%s] [%s]\n", name, desc, filter->str); | |
| 189 | |
| 190 filter_add_if_missing(name, desc, filter->str, TRUE); | |
| 191 | |
| 192 g_free(name); | |
| 193 g_free(desc); | |
| 194 g_strfreev(extensions); | |
| 195 g_string_free(filter, TRUE); | |
| 196 } | |
| 197 g_slist_free(list); | |
| 1 | 198 |
| 9 | 199 /* add defaults even if gdk-pixbuf does not have them, but disabled */ |
| 200 filter_add_if_missing("jpeg", "JPEG group", ".jpg;.jpeg;.jpe", FALSE); | |
| 201 filter_add_if_missing("png", "Portable Network Graphic", ".png", FALSE); | |
| 202 filter_add_if_missing("tiff", "Tiff", ".tif;.tiff", FALSE); | |
| 203 filter_add_if_missing("pnm", "Packed Pixel formats", ".pbm;.pgm;.pnm;.ppm", FALSE); | |
| 204 filter_add_if_missing("gif", "Graphics Interchange Format", ".gif", FALSE); | |
| 205 filter_add_if_missing("xbm", "X bitmap", ".xbm", FALSE); | |
| 206 filter_add_if_missing("xpm", "X pixmap", ".xpm", FALSE); | |
| 207 filter_add_if_missing("bmp", "Bitmap", ".bmp", FALSE); | |
| 208 filter_add_if_missing("ico", "Icon file", ".ico;.cur", FALSE); | |
| 209 filter_add_if_missing("ras", "Raster", ".ras", FALSE); | |
| 210 filter_add_if_missing("svg", "Scalable Vector Graphics", ".svg", FALSE); | |
|
43
ee03f36e9e4b
Sun May 15 21:40:26 2005 John Ellis <johne@verizon.net>
gqview
parents:
15
diff
changeset
|
211 |
|
ee03f36e9e4b
Sun May 15 21:40:26 2005 John Ellis <johne@verizon.net>
gqview
parents:
15
diff
changeset
|
212 /* These are the raw camera formats with embedded jpeg/exif. |
|
ee03f36e9e4b
Sun May 15 21:40:26 2005 John Ellis <johne@verizon.net>
gqview
parents:
15
diff
changeset
|
213 * (see format_raw.c) |
|
ee03f36e9e4b
Sun May 15 21:40:26 2005 John Ellis <johne@verizon.net>
gqview
parents:
15
diff
changeset
|
214 */ |
|
53
00843150f7c8
Tue Jun 7 03:47:03 2005 John Ellis <johne@verizon.net>
gqview
parents:
52
diff
changeset
|
215 filter_add_if_missing("crw", "Canon raw format", ".crw;.cr2", TRUE); |
|
45
7cfa60beda76
Thu May 26 13:57:19 2005 John Ellis <johne@verizon.net>
gqview
parents:
43
diff
changeset
|
216 filter_add_if_missing("raf", "Fujifilm raw format", ".raf", TRUE); |
|
53
00843150f7c8
Tue Jun 7 03:47:03 2005 John Ellis <johne@verizon.net>
gqview
parents:
52
diff
changeset
|
217 filter_add_if_missing("nef", "Nikon raw format", ".nef", TRUE); |
|
101
847e4bc6b54c
Tue Nov 7 15:35:59 2006 John Ellis <johne@verizon.net>
gqview
parents:
79
diff
changeset
|
218 filter_add_if_missing("orf", "Olympus raw format", ".orf", TRUE); |
|
847e4bc6b54c
Tue Nov 7 15:35:59 2006 John Ellis <johne@verizon.net>
gqview
parents:
79
diff
changeset
|
219 filter_add_if_missing("pef", "Pentax raw format", ".pef", TRUE); |
| 9 | 220 } |
| 221 | |
| 222 static GList *filter_to_list(const gchar *extensions) | |
| 223 { | |
| 224 GList *list = NULL; | |
| 225 const gchar *p; | |
| 226 | |
| 227 if (!extensions) return NULL; | |
| 228 | |
| 229 p = extensions; | |
| 230 while (*p != '\0') | |
| 231 { | |
| 232 const gchar *b; | |
| 233 gint l = 0; | |
| 234 | |
| 235 b = p; | |
| 236 while (*p != '\0' && *p != ';') | |
| 237 { | |
| 238 p++; | |
| 239 l++; | |
| 240 } | |
| 241 list = g_list_append(list, g_strndup(b, l)); | |
| 242 if (*p == ';') p++; | |
| 243 } | |
| 244 | |
| 245 return list; | |
| 246 } | |
| 247 | |
| 248 void filter_rebuild(void) | |
| 249 { | |
| 250 GList *work; | |
| 251 | |
| 252 path_list_free(extension_list); | |
| 253 extension_list = NULL; | |
| 254 | |
| 255 work = filter_list; | |
| 256 while (work) | |
| 257 { | |
| 258 FilterEntry *fe; | |
| 259 | |
| 260 fe = work->data; | |
| 261 work = work->next; | |
| 262 | |
| 263 if (fe->enabled) | |
| 264 { | |
| 265 GList *ext; | |
| 266 | |
| 267 ext = filter_to_list(fe->extensions); | |
| 268 if (ext) extension_list = g_list_concat(extension_list, ext); | |
| 269 } | |
| 270 } | |
| 271 } | |
| 272 | |
| 273 gint filter_name_exists(const gchar *name) | |
| 274 { | |
| 275 GList *work; | |
| 276 if (!extension_list || file_filter_disable) return TRUE; | |
| 277 | |
| 278 work = extension_list; | |
| 1 | 279 while (work) |
| 280 { | |
| 281 gchar *filter = work->data; | |
| 282 gint lf = strlen(filter); | |
| 283 gint ln = strlen(name); | |
| 284 if (ln >= lf) | |
| 285 { | |
| 286 if (strncasecmp(name + ln - lf, filter, lf) == 0) return TRUE; | |
| 287 } | |
| 288 work = work->next; | |
| 289 } | |
| 290 | |
| 291 return FALSE; | |
| 292 } | |
| 293 | |
| 9 | 294 void filter_write_list(FILE *f) |
| 1 | 295 { |
| 9 | 296 GList *work; |
| 297 | |
| 298 work = filter_list; | |
| 299 while (work) | |
| 300 { | |
| 301 FilterEntry *fe = work->data; | |
| 302 work = work->next; | |
| 303 | |
| 304 fprintf(f, "filter_ext: \"%s%s\" \"%s\" \"%s\"\n", (fe->enabled) ? "" : "#", | |
| 305 fe->key, fe->extensions, | |
| 306 (fe->description) ? fe->description : ""); | |
| 307 } | |
| 1 | 308 } |
| 309 | |
| 9 | 310 void filter_parse(const gchar *text) |
| 1 | 311 { |
| 9 | 312 const gchar *p; |
| 313 gchar *key; | |
| 314 gchar *ext; | |
| 315 gchar *desc; | |
| 316 gint enabled = TRUE; | |
| 317 | |
| 318 if (!text || text[0] != '"') return; | |
| 319 | |
| 320 key = quoted_value(text); | |
| 321 if (!key) return; | |
| 322 | |
| 323 p = text; | |
| 324 p++; | |
| 325 while (*p != '"' && *p != '\0') p++; | |
| 326 if (*p != '"') | |
| 327 { | |
| 328 g_free(key); | |
| 329 return; | |
| 330 } | |
| 331 p++; | |
| 332 while (*p != '"' && *p != '\0') p++; | |
| 333 if (*p != '"') | |
| 1 | 334 { |
| 9 | 335 g_free(key); |
| 336 return; | |
| 337 } | |
| 338 | |
| 339 ext = quoted_value(p); | |
| 340 | |
| 341 p++; | |
| 342 while (*p != '"' && *p != '\0') p++; | |
| 343 if (*p == '"') p++; | |
| 344 while (*p != '"' && *p != '\0') p++; | |
| 345 | |
| 346 if (*p == '"') | |
| 347 { | |
| 348 desc = quoted_value(p); | |
| 349 } | |
| 350 else | |
| 351 { | |
| 352 desc = NULL; | |
| 353 } | |
| 354 | |
| 355 if (key && key[0] == '#') | |
| 356 { | |
| 357 gchar *tmp; | |
| 358 tmp = g_strdup(key + 1); | |
| 359 g_free(key); | |
| 360 key = tmp; | |
| 361 | |
| 362 enabled = FALSE; | |
| 1 | 363 } |
| 364 | |
| 9 | 365 if (key && strlen(key) > 0 && ext) filter_add(key, desc, ext, enabled); |
| 366 | |
| 367 g_free(key); | |
| 368 g_free(ext); | |
| 369 g_free(desc); | |
| 370 } | |
| 1 | 371 |
| 9 | 372 GList *path_list_filter(GList *list, gint is_dir_list) |
| 373 { | |
| 374 GList *work; | |
| 375 | |
| 376 if (!is_dir_list && file_filter_disable && show_dot_files) return list; | |
| 377 | |
| 378 work = list; | |
| 379 while (work) | |
| 1 | 380 { |
| 9 | 381 gchar *name = work->data; |
| 382 const gchar *base; | |
| 383 | |
| 384 base = filename_from_path(name); | |
| 385 | |
| 386 if ((!show_dot_files && ishidden(base)) || | |
| 387 (!is_dir_list && !filter_name_exists(base)) || | |
| 388 (is_dir_list && base[0] == '.' && (strcmp(base, GQVIEW_CACHE_LOCAL_THUMB) == 0 || | |
| 389 strcmp(base, GQVIEW_CACHE_LOCAL_METADATA) == 0)) ) | |
| 390 { | |
| 391 GList *link = work; | |
| 392 work = work->next; | |
| 393 list = g_list_remove_link(list, link); | |
| 394 g_free(name); | |
| 395 g_list_free(link); | |
| 396 } | |
| 397 else | |
| 1 | 398 { |
| 9 | 399 work = work->next; |
| 1 | 400 } |
| 401 } | |
| 9 | 402 |
| 403 return list; | |
| 404 } | |
| 405 | |
| 406 /* | |
| 407 *----------------------------------------------------------------------------- | |
| 408 * path list recursive | |
| 409 *----------------------------------------------------------------------------- | |
| 410 */ | |
| 411 | |
| 412 static gint path_list_sort_cb(gconstpointer a, gconstpointer b) | |
| 413 { | |
| 414 return CASE_SORT((gchar *)a, (gchar *)b); | |
| 415 } | |
| 416 | |
| 417 GList *path_list_sort(GList *list) | |
| 418 { | |
| 419 return g_list_sort(list, path_list_sort_cb); | |
| 420 } | |
| 421 | |
| 422 static void path_list_recursive_append(GList **list, GList *dirs) | |
| 423 { | |
| 424 GList *work; | |
| 425 | |
| 426 work = dirs; | |
| 427 while (work) | |
| 428 { | |
| 429 const gchar *path = work->data; | |
| 430 GList *f = NULL; | |
| 431 GList *d = NULL; | |
| 432 | |
| 433 if (path_list(path, &f, &d)) | |
| 434 { | |
| 435 f = path_list_filter(f, FALSE); | |
| 436 f = path_list_sort(f); | |
| 437 *list = g_list_concat(*list, f); | |
| 438 | |
| 439 d = path_list_filter(d, TRUE); | |
| 440 d = path_list_sort(d); | |
| 441 path_list_recursive_append(list, d); | |
|
52
a210a19f26da
Sun Jun 5 03:05:39 2005 John Ellis <johne@verizon.net>
gqview
parents:
45
diff
changeset
|
442 path_list_free(d); |
| 9 | 443 } |
| 444 | |
| 445 work = work->next; | |
| 446 } | |
| 447 } | |
| 448 | |
| 449 GList *path_list_recursive(const gchar *path) | |
| 450 { | |
| 451 GList *list = NULL; | |
| 452 GList *d = NULL; | |
| 453 | |
| 454 if (!path_list(path, &list, &d)) return NULL; | |
| 455 list = path_list_filter(list, FALSE); | |
| 456 list = path_list_sort(list); | |
| 457 | |
| 458 d = path_list_filter(d, TRUE); | |
| 459 d = path_list_sort(d); | |
| 460 path_list_recursive_append(&list, d); | |
| 461 path_list_free(d); | |
| 462 | |
| 463 return list; | |
| 1 | 464 } |
| 465 | |
| 466 /* | |
| 467 *----------------------------------------------------------------------------- | |
| 9 | 468 * text conversion utils |
| 1 | 469 *----------------------------------------------------------------------------- |
| 470 */ | |
| 471 | |
| 9 | 472 gchar *text_from_size(gint64 size) |
| 1 | 473 { |
| 9 | 474 gchar *a, *b; |
| 475 gchar *s, *d; | |
| 476 gint l, n, i; | |
| 477 | |
| 478 /* what I would like to use is printf("%'d", size) | |
| 479 * BUT: not supported on every libc :( | |
| 480 */ | |
| 481 if (size > G_MAXUINT) | |
| 482 { | |
| 483 /* the %lld conversion is not valid in all libcs, so use a simple work-around */ | |
| 484 a = g_strdup_printf("%d%09d", (guint)(size / 1000000000), (guint)(size % 1000000000)); | |
| 485 } | |
| 486 else | |
| 487 { | |
| 488 a = g_strdup_printf("%d", (guint)size); | |
| 489 } | |
| 490 l = strlen(a); | |
| 491 n = (l - 1)/ 3; | |
| 492 if (n < 1) return a; | |
| 493 | |
| 494 b = g_new(gchar, l + n + 1); | |
| 495 | |
| 496 s = a; | |
| 497 d = b; | |
| 498 i = l - n * 3; | |
| 499 while (*s != '\0') | |
| 500 { | |
| 501 if (i < 1) | |
| 502 { | |
| 503 i = 3; | |
| 504 *d = ','; | |
| 505 d++; | |
| 506 } | |
| 507 | |
| 508 *d = *s; | |
| 509 s++; | |
| 510 d++; | |
| 511 i--; | |
| 512 } | |
| 513 *d = '\0'; | |
| 514 | |
| 515 g_free(a); | |
| 516 return b; | |
| 517 } | |
| 518 | |
| 519 gchar *text_from_size_abrev(gint64 size) | |
| 520 { | |
| 521 if (size < (gint64)1024) | |
| 522 { | |
| 523 return g_strdup_printf(_("%d bytes"), (gint)size); | |
| 524 } | |
| 525 if (size < (gint64)1048576) | |
| 526 { | |
|
15
3263965d5f9e
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
527 return g_strdup_printf(_("%.1f K"), (double)size / 1024.0); |
| 9 | 528 } |
| 529 if (size < (gint64)1073741824) | |
| 530 { | |
|
15
3263965d5f9e
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
531 return g_strdup_printf(_("%.1f MB"), (double)size / 1048576.0); |
| 9 | 532 } |
| 533 | |
|
15
3263965d5f9e
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
534 /* to avoid overflowing the double, do division in two steps */ |
|
3263965d5f9e
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
535 size /= 1048576; |
|
3263965d5f9e
##### Note: GQview CVS on sourceforge is not always up to date, please use #####
gqview
parents:
9
diff
changeset
|
536 return g_strdup_printf(_("%.1f GB"), (double)size / 1024.0); |
| 9 | 537 } |
| 538 | |
| 539 /* note: returned string is valid until next call to text_from_time() */ | |
| 540 const gchar *text_from_time(time_t t) | |
| 541 { | |
| 542 static gchar *ret = NULL; | |
| 543 gchar buf[128]; | |
| 544 gint buflen; | |
| 545 struct tm *btime; | |
| 546 GError *error = NULL; | |
| 547 | |
| 548 btime = localtime(&t); | |
| 549 | |
| 550 /* the %x warning about 2 digit years is not an error */ | |
| 551 buflen = strftime(buf, sizeof(buf), "%x %H:%M", btime); | |
| 552 if (buflen < 1) return ""; | |
| 553 | |
| 554 g_free(ret); | |
| 555 ret = g_locale_to_utf8(buf, buflen, NULL, NULL, &error); | |
| 556 if (error) | |
| 557 { | |
| 558 printf("Error converting locale strftime to UTF-8: %s\n", error->message); | |
| 559 g_error_free(error); | |
| 560 return ""; | |
| 561 } | |
| 562 | |
| 563 return ret; | |
| 1 | 564 } |
| 565 | |
| 9 | 566 /* |
| 567 *----------------------------------------------------------------------------- | |
| 568 * file info struct | |
| 569 *----------------------------------------------------------------------------- | |
| 570 */ | |
| 571 | |
| 572 FileData *file_data_new(const gchar *path, struct stat *st) | |
| 573 { | |
| 574 FileData *fd; | |
| 575 | |
| 576 fd = g_new0(FileData, 1); | |
| 577 fd->path = path_to_utf8(path); | |
| 578 fd->name = filename_from_path(fd->path); | |
| 579 fd->size = st->st_size; | |
| 580 fd->date = st->st_mtime; | |
| 581 fd->pixbuf = NULL; | |
| 582 | |
| 583 return fd; | |
| 584 } | |
| 585 | |
| 586 FileData *file_data_new_simple(const gchar *path) | |
| 587 { | |
| 588 FileData *fd; | |
| 589 struct stat st; | |
| 590 | |
| 591 fd = g_new0(FileData, 1); | |
| 592 fd->path = g_strdup(path); | |
| 593 fd->name = filename_from_path(fd->path); | |
| 594 | |
| 595 if (stat_utf8(fd->path, &st)) | |
| 596 { | |
| 597 fd->size = st.st_size; | |
| 598 fd->date = st.st_mtime; | |
| 599 } | |
| 600 | |
| 601 fd->pixbuf = NULL; | |
| 602 | |
| 603 return fd; | |
| 604 } | |
| 605 | |
| 606 void file_data_free(FileData *fd) | |
| 607 { | |
| 608 g_free(fd->path); | |
| 609 if (fd->pixbuf) g_object_unref(fd->pixbuf); | |
| 610 g_free(fd); | |
| 611 } | |
| 612 | |
| 613 /* | |
| 614 *----------------------------------------------------------------------------- | |
| 615 * load file list | |
| 616 *----------------------------------------------------------------------------- | |
| 617 */ | |
| 618 | |
| 619 static SortType filelist_sort_method = SORT_NONE; | |
| 620 static gint filelist_sort_ascend = TRUE; | |
| 621 | |
| 622 static gint sort_file_cb(void *a, void *b) | |
| 623 { | |
| 624 FileData *fa = a; | |
| 625 FileData *fb = b; | |
| 626 | |
| 627 if (!filelist_sort_ascend) | |
| 628 { | |
| 629 fa = b; | |
| 630 fb = a; | |
| 631 } | |
| 632 | |
| 633 switch (filelist_sort_method) | |
| 634 { | |
| 635 case SORT_SIZE: | |
| 636 if (fa->size < fb->size) return -1; | |
| 637 if (fa->size > fb->size) return 1; | |
| 638 return 0; | |
| 639 break; | |
| 640 case SORT_TIME: | |
| 641 if (fa->date < fb->date) return -1; | |
| 642 if (fa->date > fb->date) return 1; | |
| 643 return 0; | |
| 644 break; | |
| 645 #ifdef HAVE_STRVERSCMP | |
| 646 case SORT_NUMBER: | |
| 647 return strverscmp(fa->name, fb->name); | |
| 648 break; | |
| 649 #endif | |
| 650 case SORT_NAME: | |
| 651 default: | |
| 652 return CASE_SORT(fa->name, fb->name); | |
| 653 break; | |
| 654 } | |
| 655 } | |
| 656 | |
| 657 GList *filelist_sort(GList *list, SortType method, gint ascend) | |
| 658 { | |
| 659 filelist_sort_method = method; | |
| 660 filelist_sort_ascend = ascend; | |
| 661 return g_list_sort(list, (GCompareFunc) sort_file_cb); | |
| 662 } | |
| 663 | |
| 664 GList *filelist_insert_sort(GList *list, FileData *fd, SortType method, gint ascend) | |
| 665 { | |
| 666 filelist_sort_method = method; | |
| 667 filelist_sort_ascend = ascend; | |
| 668 return g_list_insert_sorted(list, fd, (GCompareFunc) sort_file_cb); | |
| 669 } | |
| 670 | |
| 671 gint filelist_read(const gchar *path, GList **files, GList **dirs) | |
| 1 | 672 { |
| 673 DIR *dp; | |
| 674 struct dirent *dir; | |
| 675 struct stat ent_sbuf; | |
| 9 | 676 gchar *pathl; |
| 677 GList *dlist; | |
| 678 GList *flist; | |
| 1 | 679 |
| 9 | 680 dlist = NULL; |
| 681 flist = NULL; | |
| 682 | |
| 683 pathl = path_from_utf8(path); | |
| 684 if (!pathl || (dp = opendir(pathl)) == NULL) | |
| 1 | 685 { |
| 9 | 686 g_free(pathl); |
| 687 if (files) *files = NULL; | |
| 688 if (dirs) *dirs = NULL; | |
| 689 return FALSE; | |
| 1 | 690 } |
| 691 | |
| 9 | 692 /* root dir fix */ |
| 693 if (pathl[0] == '/' && pathl[1] == '\0') | |
| 694 { | |
| 695 g_free(pathl); | |
| 696 pathl = g_strdup(""); | |
| 697 } | |
| 1 | 698 |
| 699 while ((dir = readdir(dp)) != NULL) | |
| 700 { | |
| 9 | 701 gchar *name = dir->d_name; |
| 702 if (show_dot_files || !ishidden(name)) | |
| 1 | 703 { |
| 9 | 704 gchar *filepath = g_strconcat(pathl, "/", name, NULL); |
| 705 if (stat(filepath, &ent_sbuf) >= 0) | |
| 1 | 706 { |
| 9 | 707 if (S_ISDIR(ent_sbuf.st_mode)) |
| 1 | 708 { |
| 9 | 709 /* we ignore the .thumbnails dir for cleanliness */ |
| 710 if ((dirs) && | |
| 711 !(name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'))) && | |
| 712 strcmp(name, GQVIEW_CACHE_LOCAL_THUMB) != 0 && | |
|
79
528e3432e0c0
Thu Oct 19 07:23:37 2006 John Ellis <johne@verizon.net>
gqview
parents:
53
diff
changeset
|
713 strcmp(name, GQVIEW_CACHE_LOCAL_METADATA) != 0 && |
|
528e3432e0c0
Thu Oct 19 07:23:37 2006 John Ellis <johne@verizon.net>
gqview
parents:
53
diff
changeset
|
714 strcmp(name, THUMB_FOLDER_LOCAL) != 0) |
| 9 | 715 { |
| 716 dlist = g_list_prepend(dlist, file_data_new(filepath, &ent_sbuf)); | |
| 717 } | |
| 1 | 718 } |
| 719 else | |
| 720 { | |
| 9 | 721 if ((files) && filter_name_exists(name)) |
| 722 { | |
| 723 flist = g_list_prepend(flist, file_data_new(filepath, &ent_sbuf)); | |
| 724 } | |
| 1 | 725 } |
| 726 } | |
| 9 | 727 g_free(filepath); |
| 1 | 728 } |
| 729 } | |
| 730 | |
| 731 closedir(dp); | |
| 732 | |
| 9 | 733 g_free(pathl); |
| 1 | 734 |
| 9 | 735 if (dirs) *dirs = dlist; |
| 736 if (files) *files = flist; | |
| 1 | 737 |
| 9 | 738 return TRUE; |
| 1 | 739 } |
| 740 | |
| 9 | 741 void filelist_free(GList *list) |
| 1 | 742 { |
| 9 | 743 GList *work; |
| 3 | 744 |
| 9 | 745 work = list; |
| 746 while (work) | |
| 1 | 747 { |
| 9 | 748 file_data_free((FileData *)work->data); |
| 1 | 749 work = work->next; |
| 750 } | |
| 751 | |
| 9 | 752 g_list_free(list); |
| 3 | 753 } |
| 754 | |
| 1 | 755 |
