Mercurial > geeqie.yaz
annotate src/cache_maint.c @ 276:4f526d436873
Implement secure rc file saving.
First data is written to a temporary file, then if nothing
was wrong, this file is renamed to the final name.
This way the risk of corrupted rc file is greatly reduced.
The code is borrowed from ELinks (http://elinks.cz).
author | zas_ |
---|---|
date | Tue, 08 Apr 2008 21:55:58 +0000 |
parents | 9faf34f047b1 |
children | 9995c5fb202a |
rev | line source |
---|---|
9 | 1 /* |
196 | 2 * Geeqie |
69
31759d770628
Fri Oct 13 10:27:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
3 * (C) 2006 John Ellis |
9 | 4 * |
5 * Author: John Ellis | |
6 * | |
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! | |
10 */ | |
11 | |
12 #include "gqview.h" | |
13 #include "cache_maint.h" | |
14 | |
15 #include "cache.h" | |
16 #include "filelist.h" | |
17 #include "thumb.h" | |
18 #include "thumb_standard.h" | |
19 #include "ui_fileops.h" | |
20 #include "ui_misc.h" | |
21 #include "ui_spinner.h" | |
22 #include "ui_tabcomp.h" | |
23 #include "ui_utildlg.h" | |
24 | |
25 | |
26 typedef struct _CMData CMData; | |
27 struct _CMData | |
28 { | |
29 GList *list; | |
30 GList *done_list; | |
31 gint idle_id; | |
32 GenericDialog *gd; | |
33 GtkWidget *entry; | |
34 GtkWidget *spinner; | |
35 GtkWidget *button_stop; | |
36 GtkWidget *button_close; | |
37 gint clear; | |
38 gint metadata; | |
39 }; | |
40 | |
41 #define PURGE_DIALOG_WIDTH 400 | |
42 | |
43 | |
44 /* | |
45 *------------------------------------------------------------------- | |
46 * cache maintenance | |
47 *------------------------------------------------------------------- | |
48 */ | |
49 | |
50 static gint extension_truncate(gchar *path, const gchar *ext) | |
51 { | |
52 gint l; | |
53 gint el; | |
54 | |
55 if (!path || !ext) return FALSE; | |
56 | |
57 l = strlen(path); | |
58 el = strlen(ext); | |
59 | |
60 if (l < el || strcmp(path + (l - el), ext) != 0) return FALSE; | |
61 | |
62 path[l - el] = '\0'; | |
63 | |
64 return TRUE; | |
65 } | |
66 | |
67 static gchar *extension_find_dot(gchar *path) | |
68 { | |
69 gchar *ptr; | |
70 | |
71 if (!path || *path == '\0') return NULL; | |
72 | |
73 ptr = path; | |
74 while (*ptr != '\0') ptr++; | |
75 | |
76 while (ptr > path && *ptr != '.') ptr--; | |
77 | |
78 if (ptr == path) return NULL; | |
79 | |
80 return ptr; | |
81 } | |
82 | |
83 static gint isempty(const gchar *path) | |
84 { | |
85 DIR *dp; | |
86 struct dirent *dir; | |
87 gchar *pathl; | |
88 | |
89 pathl = path_from_utf8(path); | |
90 dp = opendir(pathl); | |
91 g_free(pathl); | |
92 if (!dp) return FALSE; | |
93 | |
94 while ((dir = readdir(dp)) != NULL) | |
95 { | |
96 gchar *name = dir->d_name; | |
97 | |
69
31759d770628
Fri Oct 13 10:27:22 2006 John Ellis <johne@verizon.net>
gqview
parents:
9
diff
changeset
|
98 if (!(name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'))) ) |
9 | 99 { |
100 closedir(dp); | |
101 return FALSE; | |
102 } | |
103 } | |
104 | |
105 closedir(dp); | |
106 return TRUE; | |
107 } | |
108 | |
109 static void cache_maintain_home_close(CMData *cm) | |
110 { | |
111 if (cm->idle_id != -1) g_source_remove(cm->idle_id); | |
112 if (cm->gd) generic_dialog_close(cm->gd); | |
113 path_list_free(cm->list); | |
114 g_list_free(cm->done_list); | |
115 g_free(cm); | |
116 } | |
117 | |
118 static void cache_maintain_home_stop(CMData *cm) | |
119 { | |
120 if (cm->idle_id != -1) | |
121 { | |
122 g_source_remove(cm->idle_id); | |
123 cm->idle_id = -1; | |
124 } | |
125 | |
126 gtk_entry_set_text(GTK_ENTRY(cm->entry), _("done")); | |
127 spinner_set_interval(cm->spinner, -1); | |
128 | |
129 gtk_widget_set_sensitive(cm->button_stop, FALSE); | |
130 gtk_widget_set_sensitive(cm->button_close, TRUE); | |
131 } | |
132 | |
133 static gint cache_maintain_home_cb(gpointer data) | |
134 { | |
135 CMData *cm = data; | |
136 GList *dlist = NULL; | |
137 GList *list = NULL; | |
138 gchar *path; | |
139 gint just_done = FALSE; | |
140 gint still_have_a_file = TRUE; | |
141 gint base_length; | |
142 const gchar *cache_folder; | |
143 | |
144 if (cm->metadata) | |
145 { | |
146 cache_folder = GQVIEW_CACHE_RC_METADATA; | |
147 } | |
148 else | |
149 { | |
150 cache_folder = GQVIEW_CACHE_RC_THUMB; | |
151 } | |
152 | |
153 base_length = strlen(homedir()) + strlen("/") + strlen(cache_folder); | |
154 | |
155 if (!cm->list) | |
156 { | |
157 if (debug) printf("purge chk done.\n"); | |
158 cm->idle_id = -1; | |
159 cache_maintain_home_stop(cm); | |
160 return FALSE; | |
161 } | |
162 | |
163 path = cm->list->data; | |
164 | |
165 if (debug) printf("purge chk (%d) \"%s\"\n", (cm->clear && !cm->metadata), path); | |
166 | |
167 if (g_list_find(cm->done_list, path) == NULL) | |
168 { | |
169 cm->done_list = g_list_prepend(cm->done_list, path); | |
170 | |
171 if (path_list(path, &list, &dlist)) | |
172 { | |
173 GList *work; | |
174 | |
175 just_done = TRUE; | |
176 still_have_a_file = FALSE; | |
177 | |
178 work = list; | |
179 while (work) | |
180 { | |
181 gchar *path_buf = work->data; | |
182 gchar *dot; | |
183 | |
184 dot = extension_find_dot(path_buf); | |
185 | |
186 if (dot) *dot = '\0'; | |
187 if ((!cm->metadata && cm->clear) || | |
188 (strlen(path_buf) > base_length && !isfile(path_buf + base_length)) ) | |
189 { | |
190 if (dot) *dot = '.'; | |
191 if (!unlink_file(path_buf)) printf("failed to delete:%s\n", path_buf); | |
192 } | |
193 else | |
194 { | |
195 still_have_a_file = TRUE; | |
196 } | |
197 work = work->next; | |
198 } | |
199 } | |
200 } | |
201 path_list_free(list); | |
202 | |
203 cm->list = g_list_concat(dlist, cm->list); | |
204 | |
205 if (cm->list && g_list_find(cm->done_list, cm->list->data) != NULL) | |
206 { | |
207 /* check if the dir is empty */ | |
208 | |
209 if (cm->list->data == path && just_done) | |
210 { | |
211 if (!still_have_a_file && !dlist && cm->list->next && !rmdir_utf8(path)) | |
212 { | |
213 printf("Unable to delete dir: %s\n", path); | |
214 } | |
215 } | |
216 else | |
217 { | |
218 /* must re-check for an empty dir */ | |
219 if (isempty(path) && cm->list->next && !rmdir_utf8(path)) | |
220 { | |
221 printf("Unable to delete dir: %s\n", path); | |
222 } | |
223 } | |
224 | |
225 path = cm->list->data; | |
226 cm->done_list = g_list_remove(cm->done_list, path); | |
227 cm->list = g_list_remove(cm->list, path); | |
228 g_free(path); | |
229 } | |
230 | |
231 if (cm->list) | |
232 { | |
233 const gchar *buf; | |
234 | |
235 path = cm->list->data; | |
236 if (strlen(path) > base_length) | |
237 { | |
238 buf = path + base_length; | |
239 } | |
240 else | |
241 { | |
242 buf = "..."; | |
243 } | |
244 gtk_entry_set_text(GTK_ENTRY(cm->entry), buf); | |
245 } | |
246 | |
247 return TRUE; | |
248 } | |
249 | |
250 static void cache_maintain_home_close_cb(GenericDialog *gd, gpointer data) | |
251 { | |
252 CMData *cm = data; | |
253 | |
254 if (!GTK_WIDGET_SENSITIVE(cm->button_close)) return; | |
255 | |
256 cache_maintain_home_close(cm); | |
257 } | |
258 | |
259 static void cache_maintain_home_stop_cb(GenericDialog *gd, gpointer data) | |
260 { | |
261 CMData *cm = data; | |
262 | |
263 cache_maintain_home_stop(cm); | |
264 } | |
265 | |
266 /* sorry for complexity (cm->done_list), but need it to remove empty dirs */ | |
267 void cache_maintain_home(gint metadata, gint clear, GtkWidget *parent) | |
268 { | |
269 CMData *cm; | |
270 GList *dlist = NULL; | |
271 gchar *base; | |
272 const gchar *msg; | |
273 const gchar *cache_folder; | |
274 GtkWidget *hbox; | |
275 | |
276 if (metadata) | |
277 { | |
278 cache_folder = GQVIEW_CACHE_RC_METADATA; | |
279 } | |
280 else | |
281 { | |
282 cache_folder = GQVIEW_CACHE_RC_THUMB; | |
283 } | |
284 | |
285 base = g_strconcat(homedir(), "/", cache_folder, NULL); | |
286 | |
287 if (!path_list(base, NULL, &dlist)) | |
288 { | |
289 g_free(base); | |
290 return; | |
291 } | |
292 | |
293 dlist = g_list_append(dlist, base); | |
294 | |
295 cm = g_new0(CMData, 1); | |
296 cm->list = dlist; | |
297 cm->done_list = NULL; | |
298 cm->clear = clear; | |
299 cm->metadata = metadata; | |
300 | |
301 if (metadata) | |
302 { | |
303 msg = _("Removing old metadata..."); | |
304 } | |
305 else if (clear) | |
306 { | |
307 msg = _("Clearing cached thumbnails..."); | |
308 } | |
309 else | |
310 { | |
311 msg = _("Removing old thumbnails..."); | |
312 } | |
313 | |
314 cm->gd = generic_dialog_new(_("Maintenance"), | |
254
9faf34f047b1
Make the wmclass value unique among the code by defining
zas_
parents:
229
diff
changeset
|
315 GQ_WMCLASS, "main_maintenance", |
9 | 316 parent, FALSE, |
317 NULL, cm); | |
318 cm->gd->cancel_cb = cache_maintain_home_close_cb; | |
319 cm->button_close = generic_dialog_add_button(cm->gd, GTK_STOCK_CLOSE, NULL, | |
320 cache_maintain_home_close_cb, FALSE); | |
321 gtk_widget_set_sensitive(cm->button_close, FALSE); | |
322 cm->button_stop = generic_dialog_add_button(cm->gd, GTK_STOCK_STOP, NULL, | |
323 cache_maintain_home_stop_cb, FALSE); | |
324 | |
325 generic_dialog_add_message(cm->gd, NULL, msg, NULL); | |
326 gtk_window_set_default_size(GTK_WINDOW(cm->gd->dialog), PURGE_DIALOG_WIDTH, -1); | |
327 | |
328 hbox = gtk_hbox_new(FALSE, 0); | |
329 gtk_box_pack_start(GTK_BOX(cm->gd->vbox), hbox, FALSE, FALSE, 5); | |
330 gtk_widget_show(hbox); | |
331 | |
332 cm->entry = gtk_entry_new(); | |
333 GTK_WIDGET_UNSET_FLAGS(cm->entry, GTK_CAN_FOCUS); | |
334 gtk_editable_set_editable(GTK_EDITABLE(cm->entry), FALSE); | |
335 gtk_box_pack_start(GTK_BOX(hbox), cm->entry, TRUE, TRUE, 0); | |
336 gtk_widget_show(cm->entry); | |
337 | |
338 cm->spinner = spinner_new(NULL, SPINNER_SPEED); | |
339 gtk_box_pack_start(GTK_BOX(hbox), cm->spinner, FALSE, FALSE, 0); | |
340 gtk_widget_show(cm->spinner); | |
341 | |
342 gtk_widget_show(cm->gd->dialog); | |
343 | |
344 cm->idle_id = g_idle_add(cache_maintain_home_cb, cm); | |
345 } | |
346 | |
228 | 347 /* This checks all files in ~/.geeqie/thumbnails and |
9 | 348 * removes them if thay have no source counterpart. |
349 * (this assumes all cache files have an extension of 4 chars including '.') | |
350 */ | |
351 gint cache_maintain_home_dir(const gchar *dir, gint recursive, gint clear) | |
352 { | |
353 gchar *base; | |
354 gint base_length; | |
355 GList *dlist = NULL; | |
356 GList *flist = NULL; | |
357 gint still_have_a_file = FALSE; | |
358 | |
359 if (debug) printf("maintainance check: %s\n", dir); | |
360 | |
361 base_length = strlen(homedir()) + strlen("/") + strlen(GQVIEW_CACHE_RC_THUMB); | |
362 base = g_strconcat(homedir(), "/", GQVIEW_CACHE_RC_THUMB, dir, NULL); | |
363 | |
364 if (path_list(base, &flist, &dlist)) | |
365 { | |
366 GList *work; | |
367 | |
368 work = dlist; | |
369 while(work) | |
370 { | |
371 gchar *path = work->data; | |
372 if (recursive && strlen(path) > base_length && | |
373 !cache_maintain_home_dir(path + base_length, recursive, clear)) | |
374 { | |
375 if (debug) printf("Deleting thumb dir: %s\n", path); | |
376 if (!rmdir_utf8(path)) | |
377 { | |
378 printf("Unable to delete dir: %s\n", path); | |
379 } | |
380 } | |
381 else | |
382 { | |
383 still_have_a_file = TRUE; | |
384 } | |
385 work = work->next; | |
386 } | |
387 | |
388 work = flist; | |
389 while (work) | |
390 { | |
391 gchar *path = work->data; | |
392 gchar *dot; | |
393 | |
394 dot = extension_find_dot(path); | |
395 | |
396 if (dot) *dot = '\0'; | |
397 if (clear || | |
398 (strlen(path) > base_length && !isfile(path + base_length)) ) | |
399 { | |
400 if (dot) *dot = '.'; | |
401 if (!unlink_file(path)) printf("failed to delete:%s\n", path); | |
402 } | |
403 else | |
404 { | |
405 still_have_a_file = TRUE; | |
406 } | |
407 | |
408 work = work->next; | |
409 } | |
410 } | |
411 | |
412 path_list_free(dlist); | |
413 path_list_free(flist); | |
414 g_free(base); | |
415 | |
416 return still_have_a_file; | |
417 } | |
418 | |
419 /* This checks relative caches in dir/.thumbnails and | |
420 * removes them if they have no source counterpart. | |
421 */ | |
422 gint cache_maintain_dir(const gchar *dir, gint recursive, gint clear) | |
423 { | |
424 GList *list = NULL; | |
425 gchar *cachedir; | |
426 gint still_have_a_file = FALSE; | |
427 GList *work; | |
428 | |
429 cachedir = g_strconcat(dir, "/", GQVIEW_CACHE_LOCAL_THUMB, NULL); | |
430 | |
431 path_list(cachedir, &list, NULL); | |
432 work = list; | |
433 | |
434 while (work) | |
435 { | |
436 const gchar *path; | |
437 gchar *source; | |
438 | |
439 path = work->data; | |
440 work = work->next; | |
441 | |
442 source = g_strconcat(dir, "/", filename_from_path(path), NULL); | |
443 | |
444 if (clear || | |
445 extension_truncate(source, GQVIEW_CACHE_EXT_THUMB) || | |
446 extension_truncate(source, GQVIEW_CACHE_EXT_SIM)) | |
447 { | |
448 if (!clear && isfile(source)) | |
449 { | |
450 still_have_a_file = TRUE; | |
451 } | |
452 else | |
453 { | |
454 if (!unlink_file(path)) | |
455 { | |
456 if (debug) printf("Failed to remove cache file %s\n", path); | |
457 still_have_a_file = TRUE; | |
458 } | |
459 } | |
460 } | |
461 else | |
462 { | |
463 still_have_a_file = TRUE; | |
464 } | |
465 g_free(source); | |
466 } | |
467 | |
468 path_list_free(list); | |
469 g_free(cachedir); | |
470 | |
471 if (recursive) | |
472 { | |
473 list = NULL; | |
474 | |
475 path_list(dir, NULL, &list); | |
476 work = list; | |
477 while (work) | |
478 { | |
479 const gchar *path = work->data; | |
480 work = work->next; | |
481 | |
482 still_have_a_file |= cache_maintain_dir(path, recursive, clear); | |
483 } | |
484 | |
485 path_list_free(list); | |
486 } | |
487 | |
488 return still_have_a_file; | |
489 } | |
490 | |
491 static void cache_file_move(const gchar *src, const gchar *dest) | |
492 { | |
493 if (!dest || !src || !isfile(src)) return; | |
494 | |
495 if (!move_file(src, dest)) | |
496 { | |
497 if (debug) printf("Failed to move cache file %s\nto %s\n", src, dest); | |
498 /* we remove it anyway - it's stale */ | |
499 unlink_file(src); | |
500 } | |
501 } | |
502 | |
138 | 503 void cache_maint_moved(FileData *fd) |
9 | 504 { |
505 gchar *base; | |
506 mode_t mode = 0755; | |
138 | 507 const gchar *src = fd->change->source; |
508 const gchar *dest = fd->change->dest; | |
9 | 509 |
510 if (!src || !dest) return; | |
511 | |
512 base = cache_get_location(CACHE_TYPE_THUMB, dest, FALSE, &mode); | |
513 if (cache_ensure_dir_exists(base, mode)) | |
514 { | |
515 gchar *buf; | |
516 gchar *d; | |
517 | |
518 buf = cache_find_location(CACHE_TYPE_THUMB, src); | |
519 d = cache_get_location(CACHE_TYPE_THUMB, dest, TRUE, NULL); | |
520 cache_file_move(buf, d); | |
521 g_free(d); | |
522 g_free(buf); | |
523 | |
524 buf = cache_find_location(CACHE_TYPE_SIM, src); | |
525 d = cache_get_location(CACHE_TYPE_SIM, dest, TRUE, NULL); | |
526 cache_file_move(buf, d); | |
527 g_free(d); | |
528 g_free(buf); | |
529 } | |
530 else | |
531 { | |
532 printf("Failed to create cache dir for move %s\n", base); | |
533 } | |
534 g_free(base); | |
535 | |
536 base = cache_get_location(CACHE_TYPE_METADATA, dest, FALSE, &mode); | |
537 if (cache_ensure_dir_exists(base, mode)) | |
538 { | |
539 gchar *buf; | |
540 gchar *d; | |
541 | |
542 buf = cache_find_location(CACHE_TYPE_METADATA, src); | |
543 d = cache_get_location(CACHE_TYPE_METADATA, dest, TRUE, NULL); | |
544 cache_file_move(buf, d); | |
545 g_free(d); | |
546 g_free(buf); | |
547 } | |
548 g_free(base); | |
549 | |
550 if (enable_thumb_caching && thumbnail_spec_standard) thumb_std_maint_moved(src, dest); | |
551 } | |
552 | |
553 static void cache_file_remove(const gchar *path) | |
554 { | |
555 if (path && isfile(path) && !unlink_file(path)) | |
556 { | |
557 if (debug) printf("Failed to remove cache file %s\n", path); | |
558 } | |
559 } | |
560 | |
138 | 561 void cache_maint_removed(FileData *fd) |
9 | 562 { |
563 gchar *buf; | |
564 | |
138 | 565 buf = cache_find_location(CACHE_TYPE_THUMB, fd->path); |
9 | 566 cache_file_remove(buf); |
567 g_free(buf); | |
568 | |
138 | 569 buf = cache_find_location(CACHE_TYPE_SIM, fd->path); |
9 | 570 cache_file_remove(buf); |
571 g_free(buf); | |
572 | |
138 | 573 buf = cache_find_location(CACHE_TYPE_METADATA, fd->path); |
9 | 574 cache_file_remove(buf); |
575 g_free(buf); | |
576 | |
138 | 577 if (enable_thumb_caching && thumbnail_spec_standard) thumb_std_maint_removed(fd->path); |
9 | 578 } |
579 | |
138 | 580 void cache_maint_copied(FileData *fd) |
9 | 581 { |
582 gchar *dest_base; | |
583 gchar *src_cache; | |
584 mode_t mode = 0755; | |
585 | |
138 | 586 src_cache = cache_find_location(CACHE_TYPE_METADATA, fd->change->source); |
9 | 587 if (!src_cache) return; |
588 | |
138 | 589 dest_base = cache_get_location(CACHE_TYPE_METADATA, fd->change->dest, FALSE, &mode); |
9 | 590 if (cache_ensure_dir_exists(dest_base, mode)) |
591 { | |
592 gchar *path; | |
593 | |
138 | 594 path = cache_get_location(CACHE_TYPE_METADATA, fd->change->dest, TRUE, NULL); |
9 | 595 if (!copy_file(src_cache, path)) |
596 { | |
597 if (debug) printf("failed to copy metadata %s to %s\n", src_cache, path); | |
598 } | |
599 g_free(path); | |
600 } | |
601 | |
602 g_free(dest_base); | |
603 g_free(src_cache); | |
604 } | |
605 | |
606 /* | |
607 *------------------------------------------------------------------- | |
608 * new cache maintenance utilities | |
609 *------------------------------------------------------------------- | |
610 */ | |
611 | |
612 typedef struct _CacheManager CacheManager; | |
613 struct _CacheManager | |
614 { | |
615 GenericDialog *dialog; | |
616 GtkWidget *folder_entry; | |
617 GtkWidget *progress; | |
618 | |
619 GList *list_todo; | |
620 | |
621 gint count_total; | |
622 gint count_done; | |
623 }; | |
624 | |
625 typedef struct _CleanData CleanData; | |
626 struct _CleanData | |
627 { | |
628 GenericDialog *gd; | |
629 ThumbLoaderStd *tl; | |
630 | |
631 GList *list; | |
632 GList *list_dir; | |
633 | |
634 gint days; | |
635 gint clear; | |
636 | |
637 GtkWidget *button_close; | |
638 GtkWidget *button_stop; | |
639 GtkWidget *button_start; | |
640 GtkWidget *progress; | |
641 GtkWidget *spinner; | |
642 | |
643 GtkWidget *group; | |
644 GtkWidget *entry; | |
645 | |
646 gint count_total; | |
647 gint count_done; | |
648 | |
649 gint local; | |
650 gint recurse; | |
651 | |
652 gint idle_id; | |
653 }; | |
654 | |
655 static void cache_manager_render_reset(CleanData *cd) | |
656 { | |
657 path_list_free(cd->list); | |
658 cd->list = NULL; | |
659 | |
660 path_list_free(cd->list_dir); | |
661 cd->list_dir = NULL; | |
662 | |
663 thumb_loader_free((ThumbLoader *)cd->tl); | |
664 cd->tl = NULL; | |
665 } | |
666 | |
667 static void cache_manager_render_close_cb(GenericDialog *fd, gpointer data) | |
668 { | |
669 CleanData *cd = data; | |
670 | |
671 if (!GTK_WIDGET_SENSITIVE(cd->button_close)) return; | |
672 | |
673 cache_manager_render_reset(cd); | |
674 generic_dialog_close(cd->gd); | |
675 g_free(cd); | |
676 } | |
677 | |
678 static void cache_manager_render_finish(CleanData *cd) | |
679 { | |
680 cache_manager_render_reset(cd); | |
681 | |
682 gtk_entry_set_text(GTK_ENTRY(cd->progress), _("done")); | |
683 spinner_set_interval(cd->spinner, -1); | |
684 | |
685 gtk_widget_set_sensitive(cd->group, TRUE); | |
686 gtk_widget_set_sensitive(cd->button_start, TRUE); | |
687 gtk_widget_set_sensitive(cd->button_stop, FALSE); | |
688 gtk_widget_set_sensitive(cd->button_close, TRUE); | |
689 } | |
690 | |
691 static void cache_manager_render_stop_cb(GenericDialog *fd, gpointer data) | |
692 { | |
693 CleanData *cd = data; | |
694 | |
695 cache_manager_render_finish(cd); | |
696 } | |
697 | |
698 static void cache_manager_render_folder(CleanData *cd, const gchar *path) | |
699 { | |
700 GList *list_d = NULL; | |
701 GList *list_f = NULL; | |
702 | |
703 if (cd->recurse) | |
704 { | |
705 path_list(path, &list_f, &list_d); | |
706 } | |
707 else | |
708 { | |
709 path_list(path, &list_f, NULL); | |
710 } | |
711 | |
712 list_f = path_list_filter(list_f, FALSE); | |
713 list_d = path_list_filter(list_d, TRUE); | |
714 | |
715 cd->list = g_list_concat(list_f, cd->list); | |
716 cd->list_dir = g_list_concat(list_d, cd->list_dir); | |
717 } | |
718 | |
719 static gint cache_manager_render_file(CleanData *cd); | |
720 | |
721 static void cache_manager_render_thumb_done_cb(ThumbLoader *tl, gpointer data) | |
722 { | |
723 CleanData *cd = data; | |
724 | |
725 thumb_loader_free((ThumbLoader *)cd->tl); | |
726 cd->tl = NULL; | |
727 | |
728 while (cache_manager_render_file(cd)); | |
729 } | |
730 | |
731 static gint cache_manager_render_file(CleanData *cd) | |
732 { | |
733 if (cd->list) | |
734 { | |
735 gchar *path; | |
736 gint success; | |
737 | |
738 path = cd->list->data; | |
739 cd->list = g_list_remove(cd->list, path); | |
740 | |
741 cd->tl = (ThumbLoaderStd *)thumb_loader_new(thumb_max_width, thumb_max_height); | |
742 thumb_loader_set_callbacks((ThumbLoader *)cd->tl, | |
743 cache_manager_render_thumb_done_cb, | |
744 cache_manager_render_thumb_done_cb, | |
745 NULL, cd); | |
746 thumb_loader_set_cache((ThumbLoader *)cd->tl, TRUE, cd->local, TRUE); | |
747 success = thumb_loader_start((ThumbLoader *)cd->tl, path); | |
748 if (success) | |
749 { | |
750 gtk_entry_set_text(GTK_ENTRY(cd->progress), path); | |
751 } | |
752 else | |
753 { | |
754 thumb_loader_free((ThumbLoader *)cd->tl); | |
755 cd->tl = NULL; | |
756 } | |
757 | |
758 g_free(path); | |
759 | |
760 return (!success); | |
761 } | |
762 else if (cd->list_dir) | |
763 { | |
764 gchar *path; | |
765 | |
766 path = cd->list_dir->data; | |
767 cd->list_dir = g_list_remove(cd->list_dir, path); | |
768 | |
769 cache_manager_render_folder(cd, path); | |
770 | |
771 g_free(path); | |
772 | |
773 return TRUE; | |
774 } | |
775 | |
776 cache_manager_render_finish(cd); | |
777 | |
778 return FALSE; | |
779 } | |
780 | |
781 static void cache_manager_render_start_cb(GenericDialog *fd, gpointer data) | |
782 { | |
783 CleanData *cd = data; | |
784 gchar *path; | |
785 | |
786 if (cd->list || !GTK_WIDGET_SENSITIVE(cd->button_start)) return; | |
787 | |
788 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(cd->entry)))); | |
789 parse_out_relatives(path); | |
790 | |
791 if (!isdir(path)) | |
792 { | |
793 warning_dialog(_("Invalid folder"), | |
794 _("The specified folder can not be found."), | |
795 GTK_STOCK_DIALOG_WARNING, cd->gd->dialog); | |
796 } | |
797 else | |
798 { | |
799 gtk_widget_set_sensitive(cd->group, FALSE); | |
800 gtk_widget_set_sensitive(cd->button_start, FALSE); | |
801 gtk_widget_set_sensitive(cd->button_stop, TRUE); | |
802 gtk_widget_set_sensitive(cd->button_close, FALSE); | |
803 | |
804 spinner_set_interval(cd->spinner, SPINNER_SPEED); | |
805 | |
806 cache_manager_render_folder(cd, path); | |
807 while (cache_manager_render_file(cd)); | |
808 } | |
809 | |
810 g_free(path); | |
811 } | |
812 | |
813 static void cache_manager_render_dialog(GtkWidget *widget, const gchar *path) | |
814 { | |
815 CleanData *cd; | |
816 GtkWidget *hbox; | |
817 GtkWidget *label; | |
818 GtkWidget *button; | |
819 | |
820 cd = g_new0(CleanData, 1); | |
821 | |
822 cd->gd = generic_dialog_new(_("Create thumbnails"), | |
254
9faf34f047b1
Make the wmclass value unique among the code by defining
zas_
parents:
229
diff
changeset
|
823 GQ_WMCLASS, "create_thumbnails", |
9 | 824 widget, FALSE, |
825 NULL, cd); | |
826 gtk_window_set_default_size(GTK_WINDOW(cd->gd->dialog), PURGE_DIALOG_WIDTH, -1); | |
827 cd->gd->cancel_cb = cache_manager_render_close_cb; | |
828 cd->button_close = generic_dialog_add_button(cd->gd, GTK_STOCK_CLOSE, NULL, | |
829 cache_manager_render_close_cb, FALSE); | |
830 cd->button_start = generic_dialog_add_button(cd->gd, GTK_STOCK_OK, _("S_tart"), | |
831 cache_manager_render_start_cb, FALSE); | |
832 cd->button_stop = generic_dialog_add_button(cd->gd, GTK_STOCK_STOP, NULL, | |
833 cache_manager_render_stop_cb, FALSE); | |
834 gtk_widget_set_sensitive(cd->button_stop, FALSE); | |
835 | |
836 generic_dialog_add_message(cd->gd, NULL, _("Create thumbnails"), NULL); | |
837 | |
838 hbox = pref_box_new(cd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0); | |
839 pref_spacer(hbox, PREF_PAD_INDENT); | |
840 cd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP); | |
841 | |
842 hbox = pref_box_new(cd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE); | |
843 pref_label_new(hbox, _("Folder:")); | |
844 | |
845 label = tab_completion_new(&cd->entry, path, NULL, NULL); | |
846 tab_completion_add_select_button(cd->entry,_("Select folder") , TRUE); | |
847 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0); | |
848 gtk_widget_show(label); | |
849 | |
850 pref_checkbox_new_int(cd->group, _("Include subfolders"), FALSE, &cd->recurse); | |
851 button = pref_checkbox_new_int(cd->group, _("Store thumbnails local to source images"), FALSE, &cd->local); | |
852 gtk_widget_set_sensitive(button, thumbnail_spec_standard); | |
853 | |
854 pref_line(cd->gd->vbox, PREF_PAD_SPACE); | |
855 hbox = pref_box_new(cd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE); | |
856 | |
857 cd->progress = gtk_entry_new(); | |
858 GTK_WIDGET_UNSET_FLAGS(cd->progress, GTK_CAN_FOCUS); | |
859 gtk_editable_set_editable(GTK_EDITABLE(cd->progress), FALSE); | |
860 gtk_entry_set_text(GTK_ENTRY(cd->progress), _("click start to begin")); | |
861 gtk_box_pack_start(GTK_BOX(hbox), cd->progress, TRUE, TRUE, 0); | |
862 gtk_widget_show(cd->progress); | |
863 | |
864 cd->spinner = spinner_new(NULL, -1); | |
865 gtk_box_pack_start(GTK_BOX(hbox), cd->spinner, FALSE, FALSE, 0); | |
866 gtk_widget_show(cd->spinner); | |
867 | |
868 cd->list = NULL; | |
869 | |
870 gtk_widget_show(cd->gd->dialog); | |
871 } | |
872 | |
873 | |
874 | |
875 | |
876 static void cache_manager_standard_clean_close_cb(GenericDialog *gd, gpointer data) | |
877 { | |
878 CleanData *cd = data; | |
879 | |
880 if (!GTK_WIDGET_SENSITIVE(cd->button_close)) return; | |
881 | |
882 generic_dialog_close(cd->gd); | |
883 | |
884 thumb_loader_std_thumb_file_validate_cancel(cd->tl); | |
885 path_list_free(cd->list); | |
886 g_free(cd); | |
887 } | |
888 | |
889 static void cache_manager_standard_clean_done(CleanData *cd) | |
890 { | |
891 gtk_widget_set_sensitive(cd->button_stop, FALSE); | |
892 gtk_widget_set_sensitive(cd->button_close, TRUE); | |
893 | |
894 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(cd->progress), 1.0); | |
895 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(cd->progress), _("done")); | |
896 | |
897 if (cd->idle_id != -1) | |
898 { | |
899 g_source_remove(cd->idle_id); | |
900 cd->idle_id = -1; | |
901 } | |
902 | |
903 thumb_loader_std_thumb_file_validate_cancel(cd->tl); | |
904 cd->tl = NULL; | |
905 | |
906 path_list_free(cd->list); | |
907 cd->list = NULL; | |
908 } | |
909 | |
910 static void cache_manager_standard_clean_stop_cb(GenericDialog *gd, gpointer data) | |
911 { | |
912 CleanData *cd = data; | |
913 | |
914 cache_manager_standard_clean_done(cd); | |
915 } | |
916 | |
917 static gint cache_manager_standard_clean_clear_cb(gpointer data) | |
918 { | |
919 CleanData *cd = data; | |
920 | |
921 if (cd->list) | |
922 { | |
923 gchar *next_path; | |
924 | |
925 next_path = cd->list->data; | |
926 cd->list = g_list_remove(cd->list, next_path); | |
927 | |
928 if (debug) printf("thumb removed: %s\n", next_path); | |
929 | |
930 unlink_file(next_path); | |
931 g_free(next_path); | |
932 | |
933 cd->count_done++; | |
934 if (cd->count_total != 0) | |
935 { | |
936 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(cd->progress), | |
937 (gdouble)cd->count_done / cd->count_total); | |
938 } | |
939 | |
940 return TRUE; | |
941 } | |
942 | |
943 cd->idle_id = -1; | |
944 cache_manager_standard_clean_done(cd); | |
945 return FALSE; | |
946 } | |
947 | |
948 static void cache_manager_standard_clean_valid_cb(const gchar *path, gint valid, gpointer data) | |
949 { | |
950 CleanData *cd = data; | |
951 | |
952 if (path) | |
953 { | |
954 if (!valid) | |
955 { | |
956 if (debug) printf("thumb cleaned: %s\n", path); | |
957 unlink_file(path); | |
958 } | |
959 | |
960 cd->count_done++; | |
961 if (cd->count_total != 0) | |
962 { | |
963 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(cd->progress), | |
964 (gdouble)cd->count_done / cd->count_total); | |
965 } | |
966 } | |
967 | |
968 cd->tl = NULL; | |
969 if (cd->list) | |
970 { | |
971 gchar *next_path; | |
972 | |
973 next_path = cd->list->data; | |
974 cd->list = g_list_remove(cd->list, next_path); | |
975 | |
976 cd->tl = thumb_loader_std_thumb_file_validate(next_path, cd->days, | |
977 cache_manager_standard_clean_valid_cb, cd); | |
978 g_free(next_path); | |
979 } | |
980 else | |
981 { | |
982 cache_manager_standard_clean_done(cd); | |
983 } | |
984 } | |
985 | |
986 static void cache_manager_standard_clean_start_cb(GenericDialog *gd, gpointer data) | |
987 { | |
988 CleanData *cd = data; | |
989 GList *list; | |
990 gchar *path; | |
991 | |
992 if (cd->list || !GTK_WIDGET_SENSITIVE(cd->button_start)) return; | |
993 | |
994 gtk_widget_set_sensitive(cd->button_start, FALSE); | |
995 gtk_widget_set_sensitive(cd->button_stop, TRUE); | |
996 gtk_widget_set_sensitive(cd->button_close, FALSE); | |
997 | |
998 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(cd->progress), _("running...")); | |
999 | |
79
528e3432e0c0
Thu Oct 19 07:23:37 2006 John Ellis <johne@verizon.net>
gqview
parents:
69
diff
changeset
|
1000 path = g_strconcat(homedir(), "/", THUMB_FOLDER_GLOBAL, "/", THUMB_FOLDER_NORMAL, NULL); |
9 | 1001 list = NULL; |
1002 path_list(path, &list, NULL); | |
1003 cd->list = list; | |
1004 g_free(path); | |
1005 | |
79
528e3432e0c0
Thu Oct 19 07:23:37 2006 John Ellis <johne@verizon.net>
gqview
parents:
69
diff
changeset
|
1006 path = g_strconcat(homedir(), "/", THUMB_FOLDER_GLOBAL, "/", THUMB_FOLDER_LARGE, NULL); |
9 | 1007 list = NULL; |
1008 path_list(path, &list, NULL); | |
1009 cd->list = g_list_concat(cd->list, list); | |
1010 g_free(path); | |
1011 | |
79
528e3432e0c0
Thu Oct 19 07:23:37 2006 John Ellis <johne@verizon.net>
gqview
parents:
69
diff
changeset
|
1012 path = g_strconcat(homedir(), "/", THUMB_FOLDER_GLOBAL, "/", THUMB_FOLDER_FAIL, NULL); |
9 | 1013 list = NULL; |
1014 path_list(path, &list, NULL); | |
1015 cd->list = g_list_concat(cd->list, list); | |
1016 g_free(path); | |
1017 | |
1018 cd->count_total = g_list_length(cd->list); | |
1019 cd->count_done = 0; | |
1020 | |
1021 /* start iterating */ | |
1022 if (cd->clear) | |
1023 { | |
1024 cd->idle_id = g_idle_add(cache_manager_standard_clean_clear_cb, cd); | |
1025 } | |
1026 else | |
1027 { | |
1028 cache_manager_standard_clean_valid_cb(NULL, TRUE, cd); | |
1029 } | |
1030 } | |
1031 | |
1032 static void cache_manager_standard_process(GtkWidget *widget, gint clear) | |
1033 { | |
1034 CleanData *cd; | |
1035 const gchar *stock_id; | |
1036 const gchar *msg; | |
1037 | |
1038 cd = g_new0(CleanData, 1); | |
1039 cd->clear = clear; | |
1040 | |
1041 if (clear) | |
1042 { | |
1043 stock_id = GTK_STOCK_DELETE; | |
1044 msg = _("Clearing thumbnails..."); | |
1045 } | |
1046 else | |
1047 { | |
1048 stock_id = GTK_STOCK_CLEAR; | |
1049 msg = _("Removing old thumbnails..."); | |
1050 } | |
1051 | |
1052 cd->gd = generic_dialog_new(_("Maintenance"), | |
254
9faf34f047b1
Make the wmclass value unique among the code by defining
zas_
parents:
229
diff
changeset
|
1053 GQ_WMCLASS, "standard_maintenance", |
9 | 1054 widget, FALSE, |
1055 NULL, cd); | |
1056 cd->gd->cancel_cb = cache_manager_standard_clean_close_cb; | |
1057 cd->button_close = generic_dialog_add_button(cd->gd, GTK_STOCK_CLOSE, NULL, | |
1058 cache_manager_standard_clean_close_cb, FALSE); | |
1059 cd->button_start = generic_dialog_add_button(cd->gd, GTK_STOCK_OK, _("S_tart"), | |
1060 cache_manager_standard_clean_start_cb, FALSE); | |
1061 cd->button_stop = generic_dialog_add_button(cd->gd, GTK_STOCK_STOP, NULL, | |
1062 cache_manager_standard_clean_stop_cb, FALSE); | |
1063 gtk_widget_set_sensitive(cd->button_stop, FALSE); | |
1064 | |
1065 generic_dialog_add_message(cd->gd, stock_id, msg, NULL); | |
1066 | |
1067 cd->progress = gtk_progress_bar_new(); | |
1068 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(cd->progress), _("click start to begin")); | |
1069 gtk_box_pack_start(GTK_BOX(cd->gd->vbox), cd->progress, FALSE, FALSE, 0); | |
1070 gtk_widget_show(cd->progress); | |
1071 | |
1072 cd->days = 30; | |
1073 cd->tl = NULL; | |
1074 cd->idle_id = -1; | |
1075 | |
1076 gtk_widget_show(cd->gd->dialog); | |
1077 } | |
1078 | |
1079 static void cache_manager_standard_clean_cb(GtkWidget *widget, gpointer data) | |
1080 { | |
1081 cache_manager_standard_process(widget, FALSE); | |
1082 } | |
1083 | |
1084 static void cache_manager_standard_clear_cb(GtkWidget *widget, gpointer data) | |
1085 { | |
1086 cache_manager_standard_process(widget, TRUE); | |
1087 } | |
1088 | |
1089 | |
229
c44b98370dba
Use more generic names for some cache manager callback functions.
zas_
parents:
228
diff
changeset
|
1090 static void cache_manager_main_clean_cb(GtkWidget *widget, gpointer data) |
9 | 1091 { |
1092 cache_maintain_home(FALSE, FALSE, widget); | |
1093 } | |
1094 | |
1095 | |
1096 static void dummy_cancel_cb(GenericDialog *gd, gpointer data) | |
1097 { | |
1098 /* no op, only so cancel button appears */ | |
1099 } | |
1100 | |
229
c44b98370dba
Use more generic names for some cache manager callback functions.
zas_
parents:
228
diff
changeset
|
1101 static void cache_manager_main_clear_ok_cb(GenericDialog *gd, gpointer data) |
9 | 1102 { |
1103 cache_maintain_home(FALSE, TRUE, NULL); | |
1104 } | |
1105 | |
229
c44b98370dba
Use more generic names for some cache manager callback functions.
zas_
parents:
228
diff
changeset
|
1106 void cache_manager_main_clear_confirm(GtkWidget *parent) |
9 | 1107 { |
1108 GenericDialog *gd; | |
1109 | |
1110 gd = generic_dialog_new(_("Clear cache"), | |
254
9faf34f047b1
Make the wmclass value unique among the code by defining
zas_
parents:
229
diff
changeset
|
1111 GQ_WMCLASS, "clear_cache", parent, TRUE, |
9 | 1112 dummy_cancel_cb, NULL); |
1113 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear cache"), | |
1114 _("This will remove all thumbnails that have\nbeen saved to disk, continue?")); | |
229
c44b98370dba
Use more generic names for some cache manager callback functions.
zas_
parents:
228
diff
changeset
|
1115 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, cache_manager_main_clear_ok_cb, TRUE); |
9 | 1116 |
1117 gtk_widget_show(gd->dialog); | |
1118 } | |
1119 | |
229
c44b98370dba
Use more generic names for some cache manager callback functions.
zas_
parents:
228
diff
changeset
|
1120 static void cache_manager_main_clear_cb(GtkWidget *widget, gpointer data) |
9 | 1121 { |
229
c44b98370dba
Use more generic names for some cache manager callback functions.
zas_
parents:
228
diff
changeset
|
1122 cache_manager_main_clear_confirm(widget); |
9 | 1123 } |
1124 | |
1125 static void cache_manager_render_cb(GtkWidget *widget, gpointer data) | |
1126 { | |
1127 cache_manager_render_dialog(widget, homedir()); | |
1128 } | |
1129 | |
1130 static void cache_manager_metadata_clean_cb(GtkWidget *widget, gpointer data) | |
1131 { | |
1132 cache_maintain_home(TRUE, FALSE, widget); | |
1133 } | |
1134 | |
1135 | |
1136 static CacheManager *cache_manager = NULL; | |
1137 | |
1138 static void cache_manager_close_cb(GenericDialog *gd, gpointer data) | |
1139 { | |
1140 generic_dialog_close(gd); | |
1141 | |
1142 g_free(cache_manager); | |
1143 cache_manager = NULL; | |
1144 } | |
1145 | |
1146 void cache_manager_show(void) | |
1147 { | |
1148 GenericDialog *gd; | |
1149 GtkWidget *group; | |
1150 GtkWidget *button; | |
1151 GtkWidget *label; | |
1152 GtkWidget *table; | |
1153 GtkSizeGroup *sizegroup; | |
1154 gchar *buf; | |
1155 | |
1156 if (cache_manager) | |
1157 { | |
1158 gtk_window_present(GTK_WINDOW(cache_manager->dialog->dialog)); | |
1159 return; | |
1160 } | |
1161 | |
1162 cache_manager = g_new0(CacheManager, 1); | |
1163 | |
196 | 1164 cache_manager->dialog = generic_dialog_new(_("Cache Maintenance - Geeqie"), |
254
9faf34f047b1
Make the wmclass value unique among the code by defining
zas_
parents:
229
diff
changeset
|
1165 GQ_WMCLASS, "cache_manager", |
9 | 1166 NULL, FALSE, |
1167 NULL, cache_manager); | |
1168 gd = cache_manager->dialog; | |
1169 | |
1170 gd->cancel_cb = cache_manager_close_cb; | |
1171 generic_dialog_add_button(gd, GTK_STOCK_CLOSE, NULL, | |
1172 cache_manager_close_cb, FALSE); | |
1173 | |
1174 generic_dialog_add_message(gd, NULL, _("Cache and Data Maintenance"), NULL); | |
1175 | |
1176 sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); | |
1177 | |
196 | 1178 group = pref_group_new(gd->vbox, FALSE, _("Geeqie thumbnail cache"), GTK_ORIENTATION_VERTICAL); |
9 | 1179 |
1180 buf = g_strconcat(_("Location:"), " ", homedir(), "/", GQVIEW_CACHE_RC_THUMB, NULL); | |
1181 label = pref_label_new(group, buf); | |
1182 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); | |
1183 g_free(buf); | |
1184 | |
1185 table = pref_table_new(group, 2, 2, FALSE, FALSE); | |
1186 | |
1187 button = pref_table_button(table, 0, 0, GTK_STOCK_CLEAR, _("Clean up"), FALSE, | |
229
c44b98370dba
Use more generic names for some cache manager callback functions.
zas_
parents:
228
diff
changeset
|
1188 G_CALLBACK(cache_manager_main_clean_cb), cache_manager); |
9 | 1189 gtk_size_group_add_widget(sizegroup, button); |
1190 pref_table_label(table, 1, 0, _("Remove orphaned or outdated thumbnails."), 0.0); | |
1191 | |
1192 button = pref_table_button(table, 0, 1, GTK_STOCK_DELETE, _("Clear cache"), FALSE, | |
229
c44b98370dba
Use more generic names for some cache manager callback functions.
zas_
parents:
228
diff
changeset
|
1193 G_CALLBACK(cache_manager_main_clear_cb), cache_manager); |
9 | 1194 gtk_size_group_add_widget(sizegroup, button); |
1195 pref_table_label(table, 1, 1, _("Delete all cached thumbnails."), 0.0); | |
1196 | |
1197 | |
1198 group = pref_group_new(gd->vbox, FALSE, _("Shared thumbnail cache"), GTK_ORIENTATION_VERTICAL); | |
1199 | |
79
528e3432e0c0
Thu Oct 19 07:23:37 2006 John Ellis <johne@verizon.net>
gqview
parents:
69
diff
changeset
|
1200 buf = g_strconcat(_("Location:"), " ", homedir(), "/", THUMB_FOLDER_GLOBAL, NULL); |
9 | 1201 label = pref_label_new(group, buf); |
1202 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); | |
1203 g_free(buf); | |
1204 | |
1205 table = pref_table_new(group, 2, 2, FALSE, FALSE); | |
1206 | |
1207 button = pref_table_button(table, 0, 0, GTK_STOCK_CLEAR, _("Clean up"), FALSE, | |
1208 G_CALLBACK(cache_manager_standard_clean_cb), cache_manager); | |
1209 gtk_size_group_add_widget(sizegroup, button); | |
1210 pref_table_label(table, 1, 0, _("Remove orphaned or outdated thumbnails."), 0.0); | |
1211 | |
1212 button = pref_table_button(table, 0, 1, GTK_STOCK_DELETE, _("Clear cache"), FALSE, | |
1213 G_CALLBACK(cache_manager_standard_clear_cb), cache_manager); | |
1214 gtk_size_group_add_widget(sizegroup, button); | |
1215 pref_table_label(table, 1, 1, _("Delete all cached thumbnails."), 0.0); | |
1216 | |
1217 group = pref_group_new(gd->vbox, FALSE, _("Create thumbnails"), GTK_ORIENTATION_VERTICAL); | |
1218 | |
1219 table = pref_table_new(group, 2, 1, FALSE, FALSE); | |
1220 | |
1221 button = pref_table_button(table, 0, 1, GTK_STOCK_EXECUTE, _("Render"), FALSE, | |
1222 G_CALLBACK(cache_manager_render_cb), cache_manager); | |
1223 gtk_size_group_add_widget(sizegroup, button); | |
1224 pref_table_label(table, 1, 1, _("Render thumbnails for a specific folder."), 0.0); | |
1225 | |
1226 group = pref_group_new(gd->vbox, FALSE, _("Metadata"), GTK_ORIENTATION_VERTICAL); | |
1227 | |
1228 buf = g_strconcat(_("Location:"), " ", homedir(), "/", GQVIEW_CACHE_RC_METADATA, NULL); | |
1229 label = pref_label_new(group, buf); | |
1230 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); | |
1231 g_free(buf); | |
1232 | |
1233 table = pref_table_new(group, 2, 1, FALSE, FALSE); | |
1234 | |
1235 button = pref_table_button(table, 0, 0, GTK_STOCK_CLEAR, _("Clean up"), FALSE, | |
1236 G_CALLBACK(cache_manager_metadata_clean_cb), cache_manager); | |
1237 gtk_size_group_add_widget(sizegroup, button); | |
1238 pref_table_label(table, 1, 0, _("Remove orphaned keywords and comments."), 0.0); | |
1239 | |
1240 gtk_widget_show(cache_manager->dialog->dialog); | |
1241 } | |
1242 |