4 * Copyright (C) 2008 The Geeqie Team
8 * This software is released under the GNU General Public License (GNU GPL).
9 * Please read the included file COPYING for more information.
10 * This software comes with no warranty of any kind, use at your own risk!
14 #include "cache_maint.h"
19 #include "thumb_standard.h"
20 #include "ui_fileops.h"
22 #include "ui_spinner.h"
23 #include "ui_tabcomp.h"
24 #include "ui_utildlg.h"
27 typedef struct _CMData CMData;
36 GtkWidget *button_stop;
37 GtkWidget *button_close;
42 #define PURGE_DIALOG_WIDTH 400
46 *-------------------------------------------------------------------
48 *-------------------------------------------------------------------
52 static gint extension_truncate(gchar *path, const gchar *ext)
57 if (!path || !ext) return FALSE;
62 if (l < el || strcmp(path + (l - el), ext) != 0) return FALSE;
70 static gchar *extension_find_dot(gchar *path)
74 if (!path) return NULL;
78 if (*path == '.') dot = path;
85 static gint isempty(const gchar *path)
91 pathl = path_from_utf8(path);
94 if (!dp) return FALSE;
96 while ((dir = readdir(dp)) != NULL)
98 gchar *name = dir->d_name;
100 if (!(name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'))) )
111 static void cache_maintain_home_close(CMData *cm)
113 if (cm->idle_id != -1) g_source_remove(cm->idle_id);
114 if (cm->gd) generic_dialog_close(cm->gd);
115 filelist_free(cm->list);
116 g_list_free(cm->done_list);
120 static void cache_maintain_home_stop(CMData *cm)
122 if (cm->idle_id != -1)
124 g_source_remove(cm->idle_id);
128 gtk_entry_set_text(GTK_ENTRY(cm->entry), _("done"));
129 spinner_set_interval(cm->spinner, -1);
131 gtk_widget_set_sensitive(cm->button_stop, FALSE);
132 gtk_widget_set_sensitive(cm->button_close, TRUE);
135 static gint cache_maintain_home_cb(gpointer data)
141 gboolean just_done = FALSE;
142 gboolean still_have_a_file = TRUE;
144 const gchar *cache_folder;
149 cache_folder = GQ_CACHE_RC_METADATA;
153 cache_folder = GQ_CACHE_RC_THUMB;
156 base = g_build_filename(homedir(), cache_folder, NULL);
157 base_length = strlen(base);
162 DEBUG_1("purge chk done.");
164 cache_maintain_home_stop(cm);
170 DEBUG_1("purge chk (%d) \"%s\"", (cm->clear && !cm->metadata), fd->path);
172 if (g_list_find(cm->done_list, fd) == NULL)
174 cm->done_list = g_list_prepend(cm->done_list, fd);
176 if (filelist_read(fd, &list, &dlist))
181 still_have_a_file = FALSE;
186 FileData *fd_list = work->data;
187 gchar *path_buf = strdup(fd_list->path);
190 dot = extension_find_dot(path_buf);
192 if (dot) *dot = '\0';
193 if ((!cm->metadata && cm->clear) ||
194 (strlen(path_buf) > base_length && !isfile(path_buf + base_length)) )
197 if (!unlink_file(path_buf)) log_printf("failed to delete:%s\n", path_buf);
201 still_have_a_file = TRUE;
210 cm->list = g_list_concat(dlist, cm->list);
212 if (cm->list && g_list_find(cm->done_list, cm->list->data) != NULL)
214 /* check if the dir is empty */
216 if (cm->list->data == fd && just_done)
218 if (!still_have_a_file && !dlist && cm->list->next && !rmdir_utf8(fd->path))
220 log_printf("Unable to delete dir: %s\n", fd->path);
225 /* must re-check for an empty dir */
226 if (isempty(fd->path) && cm->list->next && !rmdir_utf8(fd->path))
228 log_printf("Unable to delete dir: %s\n", fd->path);
233 cm->done_list = g_list_remove(cm->done_list, fd);
234 cm->list = g_list_remove(cm->list, fd);
243 if (strlen(fd->path) > base_length)
245 buf = fd->path + base_length;
251 gtk_entry_set_text(GTK_ENTRY(cm->entry), buf);
257 static void cache_maintain_home_close_cb(GenericDialog *gd, gpointer data)
261 if (!GTK_WIDGET_SENSITIVE(cm->button_close)) return;
263 cache_maintain_home_close(cm);
266 static void cache_maintain_home_stop_cb(GenericDialog *gd, gpointer data)
270 cache_maintain_home_stop(cm);
273 /* sorry for complexity (cm->done_list), but need it to remove empty dirs */
274 void cache_maintain_home(gint metadata, gint clear, GtkWidget *parent)
281 const gchar *cache_folder;
286 cache_folder = GQ_CACHE_RC_METADATA;
290 cache_folder = GQ_CACHE_RC_THUMB;
293 base = g_build_filename(homedir(), cache_folder, NULL);
294 dir_fd = file_data_new_simple(base);
295 if (!filelist_read(dir_fd, NULL, &dlist))
298 file_data_unref(dir_fd);
302 dlist = g_list_append(dlist, dir_fd);
305 cm = g_new0(CMData, 1);
307 cm->done_list = NULL;
309 cm->metadata = metadata;
313 msg = _("Removing old metadata...");
317 msg = _("Clearing cached thumbnails...");
321 msg = _("Removing old thumbnails...");
324 cm->gd = generic_dialog_new(_("Maintenance"),
325 GQ_WMCLASS, "main_maintenance",
328 cm->gd->cancel_cb = cache_maintain_home_close_cb;
329 cm->button_close = generic_dialog_add_button(cm->gd, GTK_STOCK_CLOSE, NULL,
330 cache_maintain_home_close_cb, FALSE);
331 gtk_widget_set_sensitive(cm->button_close, FALSE);
332 cm->button_stop = generic_dialog_add_button(cm->gd, GTK_STOCK_STOP, NULL,
333 cache_maintain_home_stop_cb, FALSE);
335 generic_dialog_add_message(cm->gd, NULL, msg, NULL);
336 gtk_window_set_default_size(GTK_WINDOW(cm->gd->dialog), PURGE_DIALOG_WIDTH, -1);
338 hbox = gtk_hbox_new(FALSE, 0);
339 gtk_box_pack_start(GTK_BOX(cm->gd->vbox), hbox, FALSE, FALSE, 5);
340 gtk_widget_show(hbox);
342 cm->entry = gtk_entry_new();
343 GTK_WIDGET_UNSET_FLAGS(cm->entry, GTK_CAN_FOCUS);
344 gtk_editable_set_editable(GTK_EDITABLE(cm->entry), FALSE);
345 gtk_box_pack_start(GTK_BOX(hbox), cm->entry, TRUE, TRUE, 0);
346 gtk_widget_show(cm->entry);
348 cm->spinner = spinner_new(NULL, SPINNER_SPEED);
349 gtk_box_pack_start(GTK_BOX(hbox), cm->spinner, FALSE, FALSE, 0);
350 gtk_widget_show(cm->spinner);
352 gtk_widget_show(cm->gd->dialog);
354 cm->idle_id = g_idle_add(cache_maintain_home_cb, cm);
358 /* This checks all files in ~/GQ_RC_DIR/thumbnails and
359 * removes them if thay have no source counterpart.
360 * (this assumes all cache files have an extension of 4 chars including '.')
362 gint cache_maintain_home_dir(const gchar *dir, gint recursive, gint clear)
369 gint still_have_a_file = FALSE;
371 DEBUG_1("maintainance check: %s", dir);
373 base_length = strlen(homedir()) + strlen("/") + strlen(GQ_CACHE_RC_THUMB);
374 base = g_strconcat(homedir(), "/", GQ_CACHE_RC_THUMB, dir, NULL);
375 dir_fd = file_data_new_simple(base);
378 if (filelist_read(dir_fd, &flist, &dlist))
385 FileData *fd = work->data;
386 if (recursive && strlen(fd->path) > base_length &&
387 !cache_maintain_home_dir(fd->path + base_length, recursive, clear))
389 DEBUG_1("Deleting thumb dir: %s", fd->path);
390 if (!rmdir_utf8(fd->path))
392 log_printf("Unable to delete dir: %s\n", fd->path);
397 still_have_a_file = TRUE;
405 FileData *fd = work->data;
406 gchar *path = g_strdup(fd->path);
409 dot = extension_find_dot(path);
411 if (dot) *dot = '\0';
413 (strlen(path) > base_length && !isfile(path + base_length)) )
416 if (!unlink_file(path)) log_printf("failed to delete:%s\n", path);
420 still_have_a_file = TRUE;
428 filelist_free(dlist);
429 filelist_free(flist);
430 file_data_unref(dir_fd);
432 return still_have_a_file;
435 /* This checks relative caches in dir/.thumbnails and
436 * removes them if they have no source counterpart.
438 gint cache_maintain_dir(FileData *dir_fd, gint recursive, gint clear)
442 FileData *cachedir_fd;
443 gint still_have_a_file = FALSE;
446 cachedir = g_build_filename(dir, GQ_CACHE_LOCAL_THUMB, NULL);
447 cachedir_fd = file_data_new_simple(cachedir);
450 filelist_read(cachedir_fd, &list, NULL);
461 source = g_build_filename(dir->path, fd->name, NULL);
464 extension_truncate(source, GQ_CACHE_EXT_THUMB) ||
465 extension_truncate(source, GQ_CACHE_EXT_SIM))
467 if (!clear && isfile(source))
469 still_have_a_file = TRUE;
473 if (!unlink_file(fd->path))
475 DEBUG_1("Failed to remove cache file %s", fd->path);
476 still_have_a_file = TRUE;
482 still_have_a_file = TRUE;
488 file_data_unref(cachedir_fd);
494 filelist_read(dir_fd, NULL, &list);
498 FileData *fd = work->data;
501 still_have_a_file |= cache_maintain_dir(fd->path, recursive, clear);
507 return still_have_a_file;
511 static void cache_file_move(const gchar *src, const gchar *dest)
513 if (!dest || !src || !isfile(src)) return;
515 if (!move_file(src, dest))
517 DEBUG_1("Failed to move cache file \"%s\" to \"%s\"", src, dest);
518 /* we remove it anyway - it's stale */
523 static void cache_maint_moved(FileData *fd)
527 const gchar *src = fd->change->source;
528 const gchar *dest = fd->change->dest;
530 if (!src || !dest) return;
532 base = cache_get_location(CACHE_TYPE_THUMB, dest, FALSE, &mode);
533 if (cache_ensure_dir_exists(base, mode))
538 buf = cache_find_location(CACHE_TYPE_THUMB, src);
539 d = cache_get_location(CACHE_TYPE_THUMB, dest, TRUE, NULL);
540 cache_file_move(buf, d);
544 buf = cache_find_location(CACHE_TYPE_SIM, src);
545 d = cache_get_location(CACHE_TYPE_SIM, dest, TRUE, NULL);
546 cache_file_move(buf, d);
552 log_printf("Failed to create cache dir for move %s\n", base);
556 base = cache_get_location(CACHE_TYPE_METADATA, dest, FALSE, &mode);
557 if (cache_ensure_dir_exists(base, mode))
562 buf = cache_find_location(CACHE_TYPE_METADATA, src);
563 d = cache_get_location(CACHE_TYPE_METADATA, dest, TRUE, NULL);
564 cache_file_move(buf, d);
570 if (options->thumbnails.enable_caching && options->thumbnails.spec_standard)
571 thumb_std_maint_moved(src, dest);
574 static void cache_file_remove(const gchar *path)
576 if (path && isfile(path) && !unlink_file(path))
578 DEBUG_1("Failed to remove cache file %s", path);
582 static void cache_maint_removed(FileData *fd)
586 buf = cache_find_location(CACHE_TYPE_THUMB, fd->path);
587 cache_file_remove(buf);
590 buf = cache_find_location(CACHE_TYPE_SIM, fd->path);
591 cache_file_remove(buf);
594 buf = cache_find_location(CACHE_TYPE_METADATA, fd->path);
595 cache_file_remove(buf);
598 if (options->thumbnails.enable_caching && options->thumbnails.spec_standard)
599 thumb_std_maint_removed(fd->path);
602 static void cache_maint_copied(FileData *fd)
608 src_cache = cache_find_location(CACHE_TYPE_METADATA, fd->change->source);
609 if (!src_cache) return;
611 dest_base = cache_get_location(CACHE_TYPE_METADATA, fd->change->dest, FALSE, &mode);
612 if (cache_ensure_dir_exists(dest_base, mode))
616 path = cache_get_location(CACHE_TYPE_METADATA, fd->change->dest, TRUE, NULL);
617 if (!copy_file(src_cache, path))
619 DEBUG_1("failed to copy metadata %s to %s", src_cache, path);
628 void cache_notify_cb(FileData *fd, NotifyType type, gpointer data)
630 if (type != NOTIFY_TYPE_CHANGE || !fd->change) return;
632 switch(fd->change->type)
634 case FILEDATA_CHANGE_MOVE:
635 case FILEDATA_CHANGE_RENAME:
636 cache_maint_moved(fd);
638 case FILEDATA_CHANGE_COPY:
639 cache_maint_copied(fd);
641 case FILEDATA_CHANGE_DELETE:
642 cache_maint_removed(fd);
644 case FILEDATA_CHANGE_UNSPECIFIED:
651 *-------------------------------------------------------------------
652 * new cache maintenance utilities
653 *-------------------------------------------------------------------
656 typedef struct _CacheManager CacheManager;
659 GenericDialog *dialog;
660 GtkWidget *folder_entry;
669 typedef struct _CleanData CleanData;
681 GtkWidget *button_close;
682 GtkWidget *button_stop;
683 GtkWidget *button_start;
699 static void cache_manager_render_reset(CleanData *cd)
701 filelist_free(cd->list);
704 filelist_free(cd->list_dir);
707 thumb_loader_free((ThumbLoader *)cd->tl);
711 static void cache_manager_render_close_cb(GenericDialog *fd, gpointer data)
713 CleanData *cd = data;
715 if (!GTK_WIDGET_SENSITIVE(cd->button_close)) return;
717 cache_manager_render_reset(cd);
718 generic_dialog_close(cd->gd);
722 static void cache_manager_render_finish(CleanData *cd)
724 cache_manager_render_reset(cd);
726 gtk_entry_set_text(GTK_ENTRY(cd->progress), _("done"));
727 spinner_set_interval(cd->spinner, -1);
729 gtk_widget_set_sensitive(cd->group, TRUE);
730 gtk_widget_set_sensitive(cd->button_start, TRUE);
731 gtk_widget_set_sensitive(cd->button_stop, FALSE);
732 gtk_widget_set_sensitive(cd->button_close, TRUE);
735 static void cache_manager_render_stop_cb(GenericDialog *fd, gpointer data)
737 CleanData *cd = data;
739 cache_manager_render_finish(cd);
742 static void cache_manager_render_folder(CleanData *cd, FileData *dir_fd)
744 GList *list_d = NULL;
745 GList *list_f = NULL;
749 filelist_read(dir_fd, &list_f, &list_d);
753 filelist_read(dir_fd, &list_f, NULL);
756 list_f = filelist_filter(list_f, FALSE);
757 list_d = filelist_filter(list_d, TRUE);
759 cd->list = g_list_concat(list_f, cd->list);
760 cd->list_dir = g_list_concat(list_d, cd->list_dir);
763 static gint cache_manager_render_file(CleanData *cd);
765 static void cache_manager_render_thumb_done_cb(ThumbLoader *tl, gpointer data)
767 CleanData *cd = data;
769 thumb_loader_free((ThumbLoader *)cd->tl);
772 while (cache_manager_render_file(cd));
775 static gint cache_manager_render_file(CleanData *cd)
783 cd->list = g_list_remove(cd->list, fd);
785 cd->tl = (ThumbLoaderStd *)thumb_loader_new(options->thumbnails.max_width, options->thumbnails.max_height);
786 thumb_loader_set_callbacks((ThumbLoader *)cd->tl,
787 cache_manager_render_thumb_done_cb,
788 cache_manager_render_thumb_done_cb,
790 thumb_loader_set_cache((ThumbLoader *)cd->tl, TRUE, cd->local, TRUE);
791 success = thumb_loader_start((ThumbLoader *)cd->tl, fd->path);
794 gtk_entry_set_text(GTK_ENTRY(cd->progress), fd->path);
798 thumb_loader_free((ThumbLoader *)cd->tl);
806 else if (cd->list_dir)
810 fd = cd->list_dir->data;
811 cd->list_dir = g_list_remove(cd->list_dir, fd);
813 cache_manager_render_folder(cd, fd);
820 cache_manager_render_finish(cd);
825 static void cache_manager_render_start_cb(GenericDialog *fd, gpointer data)
827 CleanData *cd = data;
830 if (cd->list || !GTK_WIDGET_SENSITIVE(cd->button_start)) return;
832 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(cd->entry))));
833 parse_out_relatives(path);
837 warning_dialog(_("Invalid folder"),
838 _("The specified folder can not be found."),
839 GTK_STOCK_DIALOG_WARNING, cd->gd->dialog);
844 gtk_widget_set_sensitive(cd->group, FALSE);
845 gtk_widget_set_sensitive(cd->button_start, FALSE);
846 gtk_widget_set_sensitive(cd->button_stop, TRUE);
847 gtk_widget_set_sensitive(cd->button_close, FALSE);
849 spinner_set_interval(cd->spinner, SPINNER_SPEED);
851 dir_fd = file_data_new_simple(path);
852 cache_manager_render_folder(cd, dir_fd);
853 file_data_unref(dir_fd);
854 while (cache_manager_render_file(cd));
860 static void cache_manager_render_dialog(GtkWidget *widget, const gchar *path)
867 cd = g_new0(CleanData, 1);
869 cd->gd = generic_dialog_new(_("Create thumbnails"),
870 GQ_WMCLASS, "create_thumbnails",
873 gtk_window_set_default_size(GTK_WINDOW(cd->gd->dialog), PURGE_DIALOG_WIDTH, -1);
874 cd->gd->cancel_cb = cache_manager_render_close_cb;
875 cd->button_close = generic_dialog_add_button(cd->gd, GTK_STOCK_CLOSE, NULL,
876 cache_manager_render_close_cb, FALSE);
877 cd->button_start = generic_dialog_add_button(cd->gd, GTK_STOCK_OK, _("S_tart"),
878 cache_manager_render_start_cb, FALSE);
879 cd->button_stop = generic_dialog_add_button(cd->gd, GTK_STOCK_STOP, NULL,
880 cache_manager_render_stop_cb, FALSE);
881 gtk_widget_set_sensitive(cd->button_stop, FALSE);
883 generic_dialog_add_message(cd->gd, NULL, _("Create thumbnails"), NULL);
885 hbox = pref_box_new(cd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
886 pref_spacer(hbox, PREF_PAD_INDENT);
887 cd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
889 hbox = pref_box_new(cd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
890 pref_label_new(hbox, _("Folder:"));
892 label = tab_completion_new(&cd->entry, path, NULL, NULL);
893 tab_completion_add_select_button(cd->entry,_("Select folder") , TRUE);
894 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
895 gtk_widget_show(label);
897 pref_checkbox_new_int(cd->group, _("Include subfolders"), FALSE, &cd->recurse);
898 button = pref_checkbox_new_int(cd->group, _("Store thumbnails local to source images"), FALSE, &cd->local);
899 gtk_widget_set_sensitive(button, options->thumbnails.spec_standard);
901 pref_line(cd->gd->vbox, PREF_PAD_SPACE);
902 hbox = pref_box_new(cd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
904 cd->progress = gtk_entry_new();
905 GTK_WIDGET_UNSET_FLAGS(cd->progress, GTK_CAN_FOCUS);
906 gtk_editable_set_editable(GTK_EDITABLE(cd->progress), FALSE);
907 gtk_entry_set_text(GTK_ENTRY(cd->progress), _("click start to begin"));
908 gtk_box_pack_start(GTK_BOX(hbox), cd->progress, TRUE, TRUE, 0);
909 gtk_widget_show(cd->progress);
911 cd->spinner = spinner_new(NULL, -1);
912 gtk_box_pack_start(GTK_BOX(hbox), cd->spinner, FALSE, FALSE, 0);
913 gtk_widget_show(cd->spinner);
917 gtk_widget_show(cd->gd->dialog);
923 static void cache_manager_standard_clean_close_cb(GenericDialog *gd, gpointer data)
925 CleanData *cd = data;
927 if (!GTK_WIDGET_SENSITIVE(cd->button_close)) return;
929 generic_dialog_close(cd->gd);
931 thumb_loader_std_thumb_file_validate_cancel(cd->tl);
932 filelist_free(cd->list);
936 static void cache_manager_standard_clean_done(CleanData *cd)
938 gtk_widget_set_sensitive(cd->button_stop, FALSE);
939 gtk_widget_set_sensitive(cd->button_close, TRUE);
941 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(cd->progress), 1.0);
942 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(cd->progress), _("done"));
944 if (cd->idle_id != -1)
946 g_source_remove(cd->idle_id);
950 thumb_loader_std_thumb_file_validate_cancel(cd->tl);
953 filelist_free(cd->list);
957 static void cache_manager_standard_clean_stop_cb(GenericDialog *gd, gpointer data)
959 CleanData *cd = data;
961 cache_manager_standard_clean_done(cd);
964 static gint cache_manager_standard_clean_clear_cb(gpointer data)
966 CleanData *cd = data;
972 next_fd = cd->list->data;
973 cd->list = g_list_remove(cd->list, next_fd);
975 DEBUG_1("thumb removed: %s", next_fd->path);
977 unlink_file(next_fd->path);
978 file_data_unref(next_fd);
981 if (cd->count_total != 0)
983 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(cd->progress),
984 (gdouble)cd->count_done / cd->count_total);
991 cache_manager_standard_clean_done(cd);
995 static void cache_manager_standard_clean_valid_cb(const gchar *path, gint valid, gpointer data)
997 CleanData *cd = data;
1003 DEBUG_1("thumb cleaned: %s", path);
1008 if (cd->count_total != 0)
1010 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(cd->progress),
1011 (gdouble)cd->count_done / cd->count_total);
1020 next_fd = cd->list->data;
1021 cd->list = g_list_remove(cd->list, next_fd);
1023 cd->tl = thumb_loader_std_thumb_file_validate(next_fd->path, cd->days,
1024 cache_manager_standard_clean_valid_cb, cd);
1025 file_data_unref(next_fd);
1029 cache_manager_standard_clean_done(cd);
1033 static void cache_manager_standard_clean_start_cb(GenericDialog *gd, gpointer data)
1035 CleanData *cd = data;
1040 if (cd->list || !GTK_WIDGET_SENSITIVE(cd->button_start)) return;
1042 gtk_widget_set_sensitive(cd->button_start, FALSE);
1043 gtk_widget_set_sensitive(cd->button_stop, TRUE);
1044 gtk_widget_set_sensitive(cd->button_close, FALSE);
1046 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(cd->progress), _("running..."));
1048 path = g_build_filename(homedir(), THUMB_FOLDER_GLOBAL, THUMB_FOLDER_NORMAL, NULL);
1049 dir_fd = file_data_new_simple(path);
1050 filelist_read(dir_fd, &list, NULL);
1052 file_data_unref(dir_fd);
1055 path = g_build_filename(homedir(), THUMB_FOLDER_GLOBAL, THUMB_FOLDER_LARGE, NULL);
1056 dir_fd = file_data_new_simple(path);
1057 filelist_read(dir_fd, &list, NULL);
1058 cd->list = g_list_concat(cd->list, list);
1059 file_data_unref(dir_fd);
1062 path = g_build_filename(homedir(), THUMB_FOLDER_GLOBAL, THUMB_FOLDER_FAIL, NULL);
1063 dir_fd = file_data_new_simple(path);
1064 filelist_read(dir_fd, &list, NULL);
1065 cd->list = g_list_concat(cd->list, list);
1066 file_data_unref(dir_fd);
1069 cd->count_total = g_list_length(cd->list);
1072 /* start iterating */
1075 cd->idle_id = g_idle_add(cache_manager_standard_clean_clear_cb, cd);
1079 cache_manager_standard_clean_valid_cb(NULL, TRUE, cd);
1083 static void cache_manager_standard_process(GtkWidget *widget, gint clear)
1086 const gchar *stock_id;
1089 cd = g_new0(CleanData, 1);
1094 stock_id = GTK_STOCK_DELETE;
1095 msg = _("Clearing thumbnails...");
1099 stock_id = GTK_STOCK_CLEAR;
1100 msg = _("Removing old thumbnails...");
1103 cd->gd = generic_dialog_new(_("Maintenance"),
1104 GQ_WMCLASS, "standard_maintenance",
1107 cd->gd->cancel_cb = cache_manager_standard_clean_close_cb;
1108 cd->button_close = generic_dialog_add_button(cd->gd, GTK_STOCK_CLOSE, NULL,
1109 cache_manager_standard_clean_close_cb, FALSE);
1110 cd->button_start = generic_dialog_add_button(cd->gd, GTK_STOCK_OK, _("S_tart"),
1111 cache_manager_standard_clean_start_cb, FALSE);
1112 cd->button_stop = generic_dialog_add_button(cd->gd, GTK_STOCK_STOP, NULL,
1113 cache_manager_standard_clean_stop_cb, FALSE);
1114 gtk_widget_set_sensitive(cd->button_stop, FALSE);
1116 generic_dialog_add_message(cd->gd, stock_id, msg, NULL);
1118 cd->progress = gtk_progress_bar_new();
1119 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(cd->progress), _("click start to begin"));
1120 gtk_box_pack_start(GTK_BOX(cd->gd->vbox), cd->progress, FALSE, FALSE, 0);
1121 gtk_widget_show(cd->progress);
1127 gtk_widget_show(cd->gd->dialog);
1130 static void cache_manager_standard_clean_cb(GtkWidget *widget, gpointer data)
1132 cache_manager_standard_process(widget, FALSE);
1135 static void cache_manager_standard_clear_cb(GtkWidget *widget, gpointer data)
1137 cache_manager_standard_process(widget, TRUE);
1141 static void cache_manager_main_clean_cb(GtkWidget *widget, gpointer data)
1143 cache_maintain_home(FALSE, FALSE, widget);
1147 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1149 /* no op, only so cancel button appears */
1152 static void cache_manager_main_clear_ok_cb(GenericDialog *gd, gpointer data)
1154 cache_maintain_home(FALSE, TRUE, NULL);
1157 void cache_manager_main_clear_confirm(GtkWidget *parent)
1161 gd = generic_dialog_new(_("Clear cache"),
1162 GQ_WMCLASS, "clear_cache", parent, TRUE,
1163 dummy_cancel_cb, NULL);
1164 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear cache"),
1165 _("This will remove all thumbnails that have\nbeen saved to disk, continue?"));
1166 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, cache_manager_main_clear_ok_cb, TRUE);
1168 gtk_widget_show(gd->dialog);
1171 static void cache_manager_main_clear_cb(GtkWidget *widget, gpointer data)
1173 cache_manager_main_clear_confirm(widget);
1176 static void cache_manager_render_cb(GtkWidget *widget, gpointer data)
1178 cache_manager_render_dialog(widget, homedir());
1181 static void cache_manager_metadata_clean_cb(GtkWidget *widget, gpointer data)
1183 cache_maintain_home(TRUE, FALSE, widget);
1187 static CacheManager *cache_manager = NULL;
1189 static void cache_manager_close_cb(GenericDialog *gd, gpointer data)
1191 generic_dialog_close(gd);
1193 g_free(cache_manager);
1194 cache_manager = NULL;
1197 static GtkWidget *cache_manager_location_label(GtkWidget *group, const gchar *subdir)
1203 path = g_build_filename(homedir(), subdir, NULL);
1204 buf = g_strdup_printf(_("Location: %s"), path);
1206 label = pref_label_new(group, buf);
1208 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
1213 void cache_manager_show(void)
1219 GtkSizeGroup *sizegroup;
1223 gtk_window_present(GTK_WINDOW(cache_manager->dialog->dialog));
1227 cache_manager = g_new0(CacheManager, 1);
1229 cache_manager->dialog = generic_dialog_new(_("Cache Maintenance"),
1230 GQ_WMCLASS, "cache_manager",
1232 NULL, cache_manager);
1233 gd = cache_manager->dialog;
1235 gd->cancel_cb = cache_manager_close_cb;
1236 generic_dialog_add_button(gd, GTK_STOCK_CLOSE, NULL,
1237 cache_manager_close_cb, FALSE);
1239 generic_dialog_add_message(gd, NULL, _("Cache and Data Maintenance"), NULL);
1241 sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
1243 group = pref_group_new(gd->vbox, FALSE, _("Thumbnail cache"), GTK_ORIENTATION_VERTICAL);
1245 cache_manager_location_label(group, GQ_CACHE_RC_THUMB);
1247 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1249 button = pref_table_button(table, 0, 0, GTK_STOCK_CLEAR, _("Clean up"), FALSE,
1250 G_CALLBACK(cache_manager_main_clean_cb), cache_manager);
1251 gtk_size_group_add_widget(sizegroup, button);
1252 pref_table_label(table, 1, 0, _("Remove orphaned or outdated thumbnails."), 0.0);
1254 button = pref_table_button(table, 0, 1, GTK_STOCK_DELETE, _("Clear cache"), FALSE,
1255 G_CALLBACK(cache_manager_main_clear_cb), cache_manager);
1256 gtk_size_group_add_widget(sizegroup, button);
1257 pref_table_label(table, 1, 1, _("Delete all cached thumbnails."), 0.0);
1260 group = pref_group_new(gd->vbox, FALSE, _("Shared thumbnail cache"), GTK_ORIENTATION_VERTICAL);
1262 cache_manager_location_label(group, THUMB_FOLDER_GLOBAL);
1264 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1266 button = pref_table_button(table, 0, 0, GTK_STOCK_CLEAR, _("Clean up"), FALSE,
1267 G_CALLBACK(cache_manager_standard_clean_cb), cache_manager);
1268 gtk_size_group_add_widget(sizegroup, button);
1269 pref_table_label(table, 1, 0, _("Remove orphaned or outdated thumbnails."), 0.0);
1271 button = pref_table_button(table, 0, 1, GTK_STOCK_DELETE, _("Clear cache"), FALSE,
1272 G_CALLBACK(cache_manager_standard_clear_cb), cache_manager);
1273 gtk_size_group_add_widget(sizegroup, button);
1274 pref_table_label(table, 1, 1, _("Delete all cached thumbnails."), 0.0);
1276 group = pref_group_new(gd->vbox, FALSE, _("Create thumbnails"), GTK_ORIENTATION_VERTICAL);
1278 table = pref_table_new(group, 2, 1, FALSE, FALSE);
1280 button = pref_table_button(table, 0, 1, GTK_STOCK_EXECUTE, _("Render"), FALSE,
1281 G_CALLBACK(cache_manager_render_cb), cache_manager);
1282 gtk_size_group_add_widget(sizegroup, button);
1283 pref_table_label(table, 1, 1, _("Render thumbnails for a specific folder."), 0.0);
1285 group = pref_group_new(gd->vbox, FALSE, _("Metadata"), GTK_ORIENTATION_VERTICAL);
1287 cache_manager_location_label(group, GQ_CACHE_RC_METADATA);
1289 table = pref_table_new(group, 2, 1, FALSE, FALSE);
1291 button = pref_table_button(table, 0, 0, GTK_STOCK_CLEAR, _("Clean up"), FALSE,
1292 G_CALLBACK(cache_manager_metadata_clean_cb), cache_manager);
1293 gtk_size_group_add_widget(sizegroup, button);
1294 pref_table_label(table, 1, 0, _("Remove orphaned keywords and comments."), 0.0);
1296 gtk_widget_show(cache_manager->dialog->dialog);