2 * Copyright (C) 2006 John Ellis
3 * Copyright (C) 2008 - 2016 The Geeqie Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "cache-maint.h"
25 #include "cache-loader.h"
28 #include "pixbuf-util.h"
30 #include "thumb-standard.h"
31 #include "ui-fileops.h"
33 #include "ui-spinner.h"
34 #include "ui-tabcomp.h"
35 #include "ui-utildlg.h"
39 typedef struct _CMData CMData;
44 guint idle_id; /* event source id */
48 GtkWidget *button_stop;
49 GtkWidget *button_close;
55 #define PURGE_DIALOG_WIDTH 400
58 *-----------------------------------------------------------------------------
59 * Command line cache maintenance program functions *-----------------------------------------------------------------------------
61 static gchar *cache_maintenance_path = NULL;
62 static GtkStatusIcon *status_icon;
64 static void cache_maintenance_sim_stop_cb(gpointer UNUSED(data))
69 static void cache_maintenance_render_stop_cb(gpointer UNUSED(data))
71 gtk_status_icon_set_tooltip_text(status_icon, _("Geeqie: Creating sim data..."));
72 cache_manager_sim_remote(cache_maintenance_path, TRUE, (GDestroyNotify *)cache_maintenance_sim_stop_cb);
75 static void cache_maintenance_clean_stop_cb(gpointer UNUSED(data))
77 gtk_status_icon_set_tooltip_text(status_icon, _("Geeqie: Creating thumbs..."));
78 cache_manager_render_remote(cache_maintenance_path, TRUE, options->thumbnails.cache_into_dirs, (GDestroyNotify *)cache_maintenance_render_stop_cb);
81 static void cache_maintenance_user_cancel_cb()
86 static void cache_maintenance_status_icon_activate_cb(GtkStatusIcon *UNUSED(status), gpointer UNUSED(data))
91 menu = gtk_menu_new();
93 item = gtk_menu_item_new_with_label(_("Exit Geeqie Cache Maintenance"));
95 g_signal_connect(G_OBJECT(item), "activate", cache_maintenance_user_cancel_cb, item);
96 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
97 gtk_widget_show(item);
99 /* take ownership of menu */
100 g_object_ref_sink(G_OBJECT(menu));
102 gtk_menu_popup_at_pointer(GTK_MENU(menu), NULL);
105 void cache_maintenance(const gchar *path)
107 cache_maintenance_path = g_strdup(path);
109 status_icon = gtk_status_icon_new_from_pixbuf(pixbuf_inline(PIXBUF_INLINE_ICON));
110 gtk_status_icon_set_tooltip_text(status_icon, _("Geeqie: Cleaning thumbs..."));
111 gtk_status_icon_set_visible(status_icon, TRUE);
112 g_signal_connect(G_OBJECT(status_icon), "activate", G_CALLBACK(cache_maintenance_status_icon_activate_cb), NULL);
114 cache_maintain_home_remote(FALSE, FALSE, (GDestroyNotify *)cache_maintenance_clean_stop_cb);
118 *-------------------------------------------------------------------
120 *-------------------------------------------------------------------
123 static gchar *extension_find_dot(gchar *path)
127 if (!path) return NULL;
129 while (*path != '\0')
131 if (*path == '.') dot = path;
138 static gboolean isempty(const gchar *path)
144 pathl = path_from_utf8(path);
147 if (!dp) return FALSE;
149 while ((dir = readdir(dp)) != NULL)
151 gchar *name = dir->d_name;
153 if (!(name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'))) )
164 static void cache_maintain_home_close(CMData *cm)
166 if (cm->idle_id) g_source_remove(cm->idle_id);
167 if (cm->gd) generic_dialog_close(cm->gd);
168 filelist_free(cm->list);
169 g_list_free(cm->done_list);
173 static void cache_maintain_home_stop(CMData *cm)
177 g_source_remove(cm->idle_id);
183 gtk_entry_set_text(GTK_ENTRY(cm->entry), _("done"));
184 spinner_set_interval(cm->spinner, -1);
186 gtk_widget_set_sensitive(cm->button_stop, FALSE);
187 gtk_widget_set_sensitive(cm->button_close, TRUE);
191 static gboolean cache_maintain_home_cb(gpointer data)
193 CMData *cm = static_cast<CMData *>(data);
197 gboolean just_done = FALSE;
198 gboolean still_have_a_file = TRUE;
200 const gchar *cache_folder;
201 gboolean filter_disable;
205 cache_folder = get_metadata_cache_dir();
209 cache_folder = get_thumbnails_cache_dir();
212 base_length = strlen(cache_folder);
216 DEBUG_1("purge chk done.");
218 cache_maintain_home_stop(cm);
222 fd = static_cast<FileData *>(cm->list->data);
224 DEBUG_1("purge chk (%d) \"%s\"", (cm->clear && !cm->metadata), fd->path);
227 * It is necessary to disable the file filter when clearing the cache,
228 * otherwise the .sim (file similarity) files are not deleted.
230 filter_disable = options->file_filter.disable;
231 options->file_filter.disable = TRUE;
233 if (g_list_find(cm->done_list, fd) == NULL)
235 cm->done_list = g_list_prepend(cm->done_list, fd);
237 if (filelist_read(fd, &list, &dlist))
242 still_have_a_file = FALSE;
247 FileData *fd_list = static_cast<FileData *>(work->data);
248 gchar *path_buf = g_strdup(fd_list->path);
251 dot = extension_find_dot(path_buf);
253 if (dot) *dot = '\0';
254 if ((!cm->metadata && cm->clear) ||
255 (strlen(path_buf) > base_length && !isfile(path_buf + base_length)) )
258 if (!unlink_file(path_buf)) log_printf("failed to delete:%s\n", path_buf);
262 still_have_a_file = TRUE;
269 options->file_filter.disable = filter_disable;
273 cm->list = g_list_concat(dlist, cm->list);
275 if (cm->list && g_list_find(cm->done_list, cm->list->data) != NULL)
277 /* check if the dir is empty */
279 if (cm->list->data == fd && just_done)
281 if (!still_have_a_file && !dlist && cm->list->next && !rmdir_utf8(fd->path))
283 log_printf("Unable to delete dir: %s\n", fd->path);
288 /* must re-check for an empty dir */
289 if (isempty(fd->path) && cm->list->next && !rmdir_utf8(fd->path))
291 log_printf("Unable to delete dir: %s\n", fd->path);
295 fd = static_cast<FileData *>(cm->list->data);
296 cm->done_list = g_list_remove(cm->done_list, fd);
297 cm->list = g_list_remove(cm->list, fd);
301 if (cm->list && !cm->remote)
305 fd = static_cast<FileData *>(cm->list->data);
306 if (strlen(fd->path) > base_length)
308 buf = fd->path + base_length;
314 gtk_entry_set_text(GTK_ENTRY(cm->entry), buf);
320 static void cache_maintain_home_close_cb(GenericDialog *UNUSED(gd), gpointer data)
322 CMData *cm = static_cast<CMData *>(data);
324 if (!gtk_widget_get_sensitive(cm->button_close)) return;
326 cache_maintain_home_close(cm);
329 static void cache_maintain_home_stop_cb(GenericDialog *UNUSED(gd), gpointer data)
331 CMData *cm = static_cast<CMData *>(data);
333 cache_maintain_home_stop(cm);
336 /* sorry for complexity (cm->done_list), but need it to remove empty dirs */
337 void cache_maintain_home(gboolean metadata, gboolean clear, GtkWidget *parent)
343 const gchar *cache_folder;
348 cache_folder = get_metadata_cache_dir();
352 cache_folder = get_thumbnails_cache_dir();
355 dir_fd = file_data_new_dir(cache_folder);
356 if (!filelist_read(dir_fd, NULL, &dlist))
358 file_data_unref(dir_fd);
362 dlist = g_list_append(dlist, dir_fd);
364 cm = g_new0(CMData, 1);
366 cm->done_list = NULL;
368 cm->metadata = metadata;
373 msg = _("Removing old metadata...");
377 msg = _("Clearing cached thumbnails...");
381 msg = _("Removing old thumbnails...");
384 cm->gd = generic_dialog_new(_("Maintenance"),
388 cm->gd->cancel_cb = cache_maintain_home_close_cb;
389 cm->button_close = generic_dialog_add_button(cm->gd, GTK_STOCK_CLOSE, NULL,
390 cache_maintain_home_close_cb, FALSE);
391 gtk_widget_set_sensitive(cm->button_close, FALSE);
392 cm->button_stop = generic_dialog_add_button(cm->gd, GTK_STOCK_STOP, NULL,
393 cache_maintain_home_stop_cb, FALSE);
395 generic_dialog_add_message(cm->gd, NULL, msg, NULL, FALSE);
396 gtk_window_set_default_size(GTK_WINDOW(cm->gd->dialog), PURGE_DIALOG_WIDTH, -1);
398 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
399 gtk_box_pack_start(GTK_BOX(cm->gd->vbox), hbox, FALSE, FALSE, 5);
400 gtk_widget_show(hbox);
402 cm->entry = gtk_entry_new();
403 gtk_widget_set_can_focus(cm->entry, FALSE);
404 gtk_editable_set_editable(GTK_EDITABLE(cm->entry), FALSE);
405 gtk_box_pack_start(GTK_BOX(hbox), cm->entry, TRUE, TRUE, 0);
406 gtk_widget_show(cm->entry);
408 cm->spinner = spinner_new(NULL, SPINNER_SPEED);
409 gtk_box_pack_start(GTK_BOX(hbox), cm->spinner, FALSE, FALSE, 0);
410 gtk_widget_show(cm->spinner);
412 gtk_widget_show(cm->gd->dialog);
414 cm->idle_id = g_idle_add(cache_maintain_home_cb, cm);
418 * @brief Clears or culls cached data
419 * @param metadata TRUE - work on metadata cache, FALSE - work on thumbnail cache
420 * @param clear TRUE - clear cache, FALSE - delete orphaned cached items
421 * @param func Function called when idle loop function terminates
425 void cache_maintain_home_remote(gboolean metadata, gboolean clear, GDestroyNotify *func)
430 const gchar *cache_folder;
434 cache_folder = get_metadata_cache_dir();
438 cache_folder = get_thumbnails_cache_dir();
441 dir_fd = file_data_new_dir(cache_folder);
442 if (!filelist_read(dir_fd, NULL, &dlist))
444 file_data_unref(dir_fd);
448 dlist = g_list_append(dlist, dir_fd);
450 cm = g_new0(CMData, 1);
452 cm->done_list = NULL;
454 cm->metadata = metadata;
457 cm->idle_id = g_idle_add_full(G_PRIORITY_LOW, cache_maintain_home_cb, cm, (GDestroyNotify)func);
460 static void cache_file_move(const gchar *src, const gchar *dest)
462 if (!dest || !src || !isfile(src)) return;
464 if (!move_file(src, dest))
466 DEBUG_1("Failed to move cache file \"%s\" to \"%s\"", src, dest);
467 /* we remove it anyway - it's stale */
472 static void cache_maint_moved(FileData *fd)
476 const gchar *src = fd->change->source;
477 const gchar *dest = fd->change->dest;
479 if (!src || !dest) return;
481 base = cache_get_location(CACHE_TYPE_THUMB, dest, FALSE, &mode);
482 if (recursive_mkdir_if_not_exists(base, mode))
487 buf = cache_find_location(CACHE_TYPE_THUMB, src);
488 d = cache_get_location(CACHE_TYPE_THUMB, dest, TRUE, NULL);
489 cache_file_move(buf, d);
493 buf = cache_find_location(CACHE_TYPE_SIM, src);
494 d = cache_get_location(CACHE_TYPE_SIM, dest, TRUE, NULL);
495 cache_file_move(buf, d);
501 log_printf("Failed to create cache dir for move %s\n", base);
505 base = cache_get_location(CACHE_TYPE_METADATA, dest, FALSE, &mode);
506 if (recursive_mkdir_if_not_exists(base, mode))
511 buf = cache_find_location(CACHE_TYPE_METADATA, src);
512 d = cache_get_location(CACHE_TYPE_METADATA, dest, TRUE, NULL);
513 cache_file_move(buf, d);
519 if (options->thumbnails.enable_caching && options->thumbnails.spec_standard)
520 thumb_std_maint_moved(src, dest);
523 static void cache_file_remove(const gchar *path)
525 if (path && isfile(path) && !unlink_file(path))
527 DEBUG_1("Failed to remove cache file %s", path);
531 static void cache_maint_removed(FileData *fd)
535 buf = cache_find_location(CACHE_TYPE_THUMB, fd->path);
536 cache_file_remove(buf);
539 buf = cache_find_location(CACHE_TYPE_SIM, fd->path);
540 cache_file_remove(buf);
543 buf = cache_find_location(CACHE_TYPE_METADATA, fd->path);
544 cache_file_remove(buf);
547 if (options->thumbnails.enable_caching && options->thumbnails.spec_standard)
548 thumb_std_maint_removed(fd->path);
551 static void cache_maint_copied(FileData *fd)
557 src_cache = cache_find_location(CACHE_TYPE_METADATA, fd->change->source);
558 if (!src_cache) return;
560 dest_base = cache_get_location(CACHE_TYPE_METADATA, fd->change->dest, FALSE, &mode);
561 if (recursive_mkdir_if_not_exists(dest_base, mode))
565 path = cache_get_location(CACHE_TYPE_METADATA, fd->change->dest, TRUE, NULL);
566 if (!copy_file(src_cache, path))
568 DEBUG_1("failed to copy metadata %s to %s", src_cache, path);
577 void cache_notify_cb(FileData *fd, NotifyType type, gpointer UNUSED(data))
579 if (!(type & NOTIFY_CHANGE) || !fd->change) return;
581 DEBUG_1("Notify cache_maint: %s %04x", fd->path, type);
582 switch (fd->change->type)
584 case FILEDATA_CHANGE_MOVE:
585 case FILEDATA_CHANGE_RENAME:
586 cache_maint_moved(fd);
588 case FILEDATA_CHANGE_COPY:
589 cache_maint_copied(fd);
591 case FILEDATA_CHANGE_DELETE:
592 cache_maint_removed(fd);
594 case FILEDATA_CHANGE_UNSPECIFIED:
595 case FILEDATA_CHANGE_WRITE_METADATA:
602 *-------------------------------------------------------------------
603 * new cache maintenance utilities
604 *-------------------------------------------------------------------
607 typedef struct _CacheManager CacheManager;
610 GenericDialog *dialog;
611 GtkWidget *folder_entry;
620 typedef struct _CacheOpsData CacheOpsData;
626 GDestroyNotify *destroy_func; /* Used by the command line prog. functions */
634 GtkWidget *button_close;
635 GtkWidget *button_stop;
636 GtkWidget *button_start;
638 GtkWidget *progress_bar;
652 guint idle_id; /* event source id */
655 static void cache_manager_render_reset(CacheOpsData *cd)
657 filelist_free(cd->list);
660 filelist_free(cd->list_dir);
663 thumb_loader_free((ThumbLoader *)cd->tl);
667 static void cache_manager_render_close_cb(GenericDialog *UNUSED(fd), gpointer data)
669 CacheOpsData *cd = static_cast<CacheOpsData *>(data);
671 if (!gtk_widget_get_sensitive(cd->button_close)) return;
673 cache_manager_render_reset(cd);
674 generic_dialog_close(cd->gd);
678 static void cache_manager_render_finish(CacheOpsData *cd)
680 cache_manager_render_reset(cd);
683 gtk_entry_set_text(GTK_ENTRY(cd->progress), _("done"));
684 spinner_set_interval(cd->spinner, -1);
686 gtk_widget_set_sensitive(cd->group, TRUE);
687 gtk_widget_set_sensitive(cd->button_start, TRUE);
688 gtk_widget_set_sensitive(cd->button_stop, FALSE);
689 gtk_widget_set_sensitive(cd->button_close, TRUE);
693 static void cache_manager_render_stop_cb(GenericDialog *UNUSED(fd), gpointer data)
695 CacheOpsData *cd = static_cast<CacheOpsData *>(data);
697 gtk_entry_set_text(GTK_ENTRY(cd->progress), _("stopped"));
698 cache_manager_render_finish(cd);
701 static void cache_manager_render_folder(CacheOpsData *cd, FileData *dir_fd)
703 GList *list_d = NULL;
704 GList *list_f = NULL;
708 filelist_read(dir_fd, &list_f, &list_d);
712 filelist_read(dir_fd, &list_f, NULL);
715 list_f = filelist_filter(list_f, FALSE);
716 list_d = filelist_filter(list_d, TRUE);
718 cd->list = g_list_concat(list_f, cd->list);
719 cd->list_dir = g_list_concat(list_d, cd->list_dir);
722 static gboolean cache_manager_render_file(CacheOpsData *cd);
724 static void cache_manager_render_thumb_done_cb(ThumbLoader *UNUSED(tl), gpointer data)
726 CacheOpsData *cd = static_cast<CacheOpsData *>(data);
728 thumb_loader_free((ThumbLoader *)cd->tl);
731 while (cache_manager_render_file(cd));
734 static gboolean cache_manager_render_file(CacheOpsData *cd)
741 fd = static_cast<FileData *>(cd->list->data);
742 cd->list = g_list_remove(cd->list, fd);
744 cd->tl = (ThumbLoaderStd *)thumb_loader_new(options->thumbnails.max_width, options->thumbnails.max_height);
745 thumb_loader_set_callbacks((ThumbLoader *)cd->tl,
746 cache_manager_render_thumb_done_cb,
747 cache_manager_render_thumb_done_cb,
749 thumb_loader_set_cache((ThumbLoader *)cd->tl, TRUE, cd->local, TRUE);
750 success = thumb_loader_start((ThumbLoader *)cd->tl, fd);
755 gtk_entry_set_text(GTK_ENTRY(cd->progress), fd->path);
756 cd->count_done = cd->count_done + 1;
757 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(cd->progress_bar), (gdouble)cd->count_done / cd->count_total);
762 thumb_loader_free((ThumbLoader *)cd->tl);
770 else if (cd->list_dir)
774 fd = static_cast<FileData *>(cd->list_dir->data);
775 cd->list_dir = g_list_remove(cd->list_dir, fd);
777 cache_manager_render_folder(cd, fd);
786 gtk_entry_set_text(GTK_ENTRY(cd->progress), _("done"));
788 cache_manager_render_finish(cd);
790 if (cd->destroy_func)
792 g_idle_add((GSourceFunc)cd->destroy_func, NULL);
798 static void cache_manager_render_start_cb(GenericDialog *UNUSED(fd), gpointer data)
800 CacheOpsData *cd = static_cast<CacheOpsData *>(data);
802 GList *list_total = NULL;
806 if (cd->list || !gtk_widget_get_sensitive(cd->button_start)) return;
809 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(cd->entry))));
810 parse_out_relatives(path);
816 warning_dialog(_("Invalid folder"),
817 _("The specified folder can not be found."),
818 GTK_STOCK_DIALOG_WARNING, cd->gd->dialog);
822 log_printf("The specified folder can not be found: %s\n", path);
830 gtk_widget_set_sensitive(cd->group, FALSE);
831 gtk_widget_set_sensitive(cd->button_start, FALSE);
832 gtk_widget_set_sensitive(cd->button_stop, TRUE);
833 gtk_widget_set_sensitive(cd->button_close, FALSE);
835 spinner_set_interval(cd->spinner, SPINNER_SPEED);
837 dir_fd = file_data_new_dir(path);
838 cache_manager_render_folder(cd, dir_fd);
839 list_total = filelist_recursive(dir_fd);
840 cd->count_total = g_list_length(list_total);
841 file_data_unref(dir_fd);
842 g_list_free(list_total);
845 while (cache_manager_render_file(cd));
851 static void cache_manager_render_start_render_remote(CacheOpsData *cd, const gchar *user_path)
855 path = remove_trailing_slash(user_path);
856 parse_out_relatives(path);
860 log_printf("The specified folder can not be found: %s\n", path);
866 dir_fd = file_data_new_dir(path);
867 cache_manager_render_folder(cd, dir_fd);
868 file_data_unref(dir_fd);
869 while (cache_manager_render_file(cd));
875 static void cache_manager_render_dialog(GtkWidget *widget, const gchar *path)
882 cd = g_new0(CacheOpsData, 1);
885 cd->gd = generic_dialog_new(_("Create thumbnails"),
889 gtk_window_set_default_size(GTK_WINDOW(cd->gd->dialog), PURGE_DIALOG_WIDTH, -1);
890 cd->gd->cancel_cb = cache_manager_render_close_cb;
891 cd->button_close = generic_dialog_add_button(cd->gd, GTK_STOCK_CLOSE, NULL,
892 cache_manager_render_close_cb, FALSE);
893 cd->button_start = generic_dialog_add_button(cd->gd, GTK_STOCK_OK, _("S_tart"),
894 cache_manager_render_start_cb, FALSE);
895 cd->button_stop = generic_dialog_add_button(cd->gd, GTK_STOCK_STOP, NULL,
896 cache_manager_render_stop_cb, FALSE);
897 gtk_widget_set_sensitive(cd->button_stop, FALSE);
899 generic_dialog_add_message(cd->gd, NULL, _("Create thumbnails"), NULL, FALSE);
901 hbox = pref_box_new(cd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
902 pref_spacer(hbox, PREF_PAD_INDENT);
903 cd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
905 hbox = pref_box_new(cd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
906 pref_label_new(hbox, _("Folder:"));
908 label = tab_completion_new(&cd->entry, path, NULL, NULL, NULL, NULL);
909 tab_completion_add_select_button(cd->entry,_("Select folder") , TRUE);
910 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
911 gtk_widget_show(label);
913 pref_checkbox_new_int(cd->group, _("Include subfolders"), FALSE, &cd->recurse);
914 button = pref_checkbox_new_int(cd->group, _("Store thumbnails local to source images"), FALSE, &cd->local);
915 gtk_widget_set_sensitive(button, options->thumbnails.spec_standard);
917 pref_line(cd->gd->vbox, PREF_PAD_SPACE);
918 hbox = pref_box_new(cd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
920 cd->progress = gtk_entry_new();
921 gtk_widget_set_can_focus(cd->progress, FALSE);
922 gtk_editable_set_editable(GTK_EDITABLE(cd->progress), FALSE);
923 gtk_entry_set_text(GTK_ENTRY(cd->progress), _("click start to begin"));
924 gtk_box_pack_start(GTK_BOX(hbox), cd->progress, TRUE, TRUE, 0);
925 gtk_widget_show(cd->progress);
927 cd->progress_bar = gtk_progress_bar_new();
928 gtk_box_pack_start(GTK_BOX(cd->gd->vbox), cd->progress_bar, TRUE, TRUE, 0);
929 gtk_widget_show(cd->progress_bar);
931 cd->spinner = spinner_new(NULL, -1);
932 gtk_box_pack_start(GTK_BOX(hbox), cd->spinner, FALSE, FALSE, 0);
933 gtk_widget_show(cd->spinner);
937 gtk_widget_show(cd->gd->dialog);
941 * @brief Create thumbnails
942 * @param path Path to image folder
944 * @param local Create thumbnails in same folder as images
945 * @param func Function called when idle loop function terminates
949 void cache_manager_render_remote(const gchar *path, gboolean recurse, gboolean local, GDestroyNotify *func)
953 cd = g_new0(CacheOpsData, 1);
954 cd->recurse = recurse;
957 cd->destroy_func = func;
959 cache_manager_render_start_render_remote(cd, path);
962 static void cache_manager_standard_clean_close_cb(GenericDialog *UNUSED(gd), gpointer data)
964 CacheOpsData *cd = static_cast<CacheOpsData *>(data);
966 if (!gtk_widget_get_sensitive(cd->button_close)) return;
968 generic_dialog_close(cd->gd);
970 thumb_loader_std_thumb_file_validate_cancel(cd->tl);
971 filelist_free(cd->list);
975 static void cache_manager_standard_clean_done(CacheOpsData *cd)
979 gtk_widget_set_sensitive(cd->button_stop, FALSE);
980 gtk_widget_set_sensitive(cd->button_close, TRUE);
982 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(cd->progress), 1.0);
983 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(cd->progress), _("done"));
987 g_source_remove(cd->idle_id);
991 thumb_loader_std_thumb_file_validate_cancel(cd->tl);
994 filelist_free(cd->list);
998 static void cache_manager_standard_clean_stop_cb(GenericDialog *UNUSED(gd), gpointer data)
1000 CacheOpsData *cd = static_cast<CacheOpsData *>(data);
1002 cache_manager_standard_clean_done(cd);
1005 static gint cache_manager_standard_clean_clear_cb(gpointer data)
1007 CacheOpsData *cd = static_cast<CacheOpsData *>(data);
1013 next_fd = static_cast<FileData *>(cd->list->data);
1014 cd->list = g_list_remove(cd->list, next_fd);
1016 DEBUG_1("thumb removed: %s", next_fd->path);
1018 unlink_file(next_fd->path);
1019 file_data_unref(next_fd);
1024 if (cd->count_total != 0)
1026 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(cd->progress),
1027 (gdouble)cd->count_done / cd->count_total);
1035 cache_manager_standard_clean_done(cd);
1039 static void cache_manager_standard_clean_valid_cb(const gchar *path, gboolean valid, gpointer data)
1041 CacheOpsData *cd = static_cast<CacheOpsData *>(data);
1047 DEBUG_1("thumb cleaned: %s", path);
1054 if (cd->count_total != 0)
1056 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(cd->progress),
1057 (gdouble)cd->count_done / cd->count_total);
1067 next_fd = static_cast<FileData *>(cd->list->data);
1068 cd->list = g_list_remove(cd->list, next_fd);
1070 cd->tl = thumb_loader_std_thumb_file_validate(next_fd->path, cd->days,
1071 cache_manager_standard_clean_valid_cb, cd);
1072 file_data_unref(next_fd);
1076 cache_manager_standard_clean_done(cd);
1080 static void cache_manager_standard_clean_start(GenericDialog *UNUSED(gd), gpointer data)
1082 CacheOpsData *cd = static_cast<CacheOpsData *>(data);
1089 if (cd->list || !gtk_widget_get_sensitive(cd->button_start)) return;
1091 gtk_widget_set_sensitive(cd->button_start, FALSE);
1092 gtk_widget_set_sensitive(cd->button_stop, TRUE);
1093 gtk_widget_set_sensitive(cd->button_close, FALSE);
1095 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(cd->progress), _("running..."));
1098 path = g_build_filename(get_thumbnails_standard_cache_dir(), THUMB_FOLDER_NORMAL, NULL);
1099 dir_fd = file_data_new_dir(path);
1100 filelist_read(dir_fd, &list, NULL);
1102 file_data_unref(dir_fd);
1105 path = g_build_filename(get_thumbnails_standard_cache_dir(), THUMB_FOLDER_LARGE, NULL);
1106 dir_fd = file_data_new_dir(path);
1107 filelist_read(dir_fd, &list, NULL);
1108 cd->list = g_list_concat(cd->list, list);
1109 file_data_unref(dir_fd);
1112 path = g_build_filename(get_thumbnails_standard_cache_dir(), THUMB_FOLDER_FAIL, NULL);
1113 dir_fd = file_data_new_dir(path);
1114 filelist_read(dir_fd, &list, NULL);
1115 cd->list = g_list_concat(cd->list, list);
1116 file_data_unref(dir_fd);
1119 cd->count_total = g_list_length(cd->list);
1122 /* start iterating */
1125 cd->idle_id = g_idle_add(cache_manager_standard_clean_clear_cb, cd);
1129 cache_manager_standard_clean_valid_cb(NULL, TRUE, cd);
1133 static void cache_manager_standard_clean_start_cb(GenericDialog *gd, gpointer data)
1135 cache_manager_standard_clean_start(gd, data);
1138 static void cache_manager_standard_process(GtkWidget *widget, gboolean clear)
1141 const gchar *stock_id;
1144 cd = g_new0(CacheOpsData, 1);
1150 stock_id = GTK_STOCK_DELETE;
1151 msg = _("Clearing thumbnails...");
1155 stock_id = GTK_STOCK_CLEAR;
1156 msg = _("Removing old thumbnails...");
1159 cd->gd = generic_dialog_new(_("Maintenance"),
1160 "standard_maintenance",
1163 cd->gd->cancel_cb = cache_manager_standard_clean_close_cb;
1164 cd->button_close = generic_dialog_add_button(cd->gd, GTK_STOCK_CLOSE, NULL,
1165 cache_manager_standard_clean_close_cb, FALSE);
1166 cd->button_start = generic_dialog_add_button(cd->gd, GTK_STOCK_OK, _("S_tart"),
1167 cache_manager_standard_clean_start_cb, FALSE);
1168 cd->button_stop = generic_dialog_add_button(cd->gd, GTK_STOCK_STOP, NULL,
1169 cache_manager_standard_clean_stop_cb, FALSE);
1170 gtk_widget_set_sensitive(cd->button_stop, FALSE);
1172 generic_dialog_add_message(cd->gd, stock_id, msg, NULL, FALSE);
1174 cd->progress = gtk_progress_bar_new();
1175 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(cd->progress), _("click start to begin"));
1176 gtk_progress_bar_set_show_text(GTK_PROGRESS_BAR(cd->progress), TRUE);
1177 gtk_box_pack_start(GTK_BOX(cd->gd->vbox), cd->progress, FALSE, FALSE, 0);
1178 gtk_widget_show(cd->progress);
1184 gtk_widget_show(cd->gd->dialog);
1187 void cache_manager_standard_process_remote(gboolean clear)
1191 cd = g_new0(CacheOpsData, 1);
1198 cache_manager_standard_clean_start(NULL, cd);
1201 static void cache_manager_standard_clean_cb(GtkWidget *widget, gpointer UNUSED(data))
1203 cache_manager_standard_process(widget, FALSE);
1206 static void cache_manager_standard_clear_cb(GtkWidget *widget, gpointer UNUSED(data))
1208 cache_manager_standard_process(widget, TRUE);
1212 static void cache_manager_main_clean_cb(GtkWidget *widget, gpointer UNUSED(data))
1214 cache_maintain_home(FALSE, FALSE, widget);
1218 static void dummy_cancel_cb(GenericDialog *UNUSED(gd), gpointer UNUSED(data))
1220 /* no op, only so cancel button appears */
1223 static void cache_manager_main_clear_ok_cb(GenericDialog *UNUSED(gd), gpointer UNUSED(data))
1225 cache_maintain_home(FALSE, TRUE, NULL);
1228 void cache_manager_main_clear_confirm(GtkWidget *parent)
1232 gd = generic_dialog_new(_("Clear cache"),
1233 "clear_cache", parent, TRUE,
1234 dummy_cancel_cb, NULL);
1235 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear cache"),
1236 _("This will remove all thumbnails and sim. files\nthat have been saved to disk, continue?"), TRUE);
1237 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, cache_manager_main_clear_ok_cb, TRUE);
1239 gtk_widget_show(gd->dialog);
1242 static void cache_manager_main_clear_cb(GtkWidget *widget, gpointer UNUSED(data))
1244 cache_manager_main_clear_confirm(widget);
1247 static void cache_manager_render_cb(GtkWidget *widget, gpointer UNUSED(data))
1249 const gchar *path = layout_get_path(NULL);
1251 if (!path || !*path) path = homedir();
1252 cache_manager_render_dialog(widget, path);
1255 static void cache_manager_metadata_clean_cb(GtkWidget *widget, gpointer UNUSED(data))
1257 cache_maintain_home(TRUE, FALSE, widget);
1261 static CacheManager *cache_manager = NULL;
1263 static void cache_manager_close_cb(GenericDialog *gd, gpointer UNUSED(data))
1265 generic_dialog_close(gd);
1267 g_free(cache_manager);
1268 cache_manager = NULL;
1271 static void cache_manager_help_cb(GenericDialog *UNUSED(gd), gpointer UNUSED(data))
1273 help_window_show("GuideReferenceManagement.html");
1276 static GtkWidget *cache_manager_location_label(GtkWidget *group, const gchar *subdir)
1281 buf = g_strdup_printf(_("Location: %s"), subdir);
1282 label = pref_label_new(group, buf);
1284 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
1285 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
1290 static gboolean cache_manager_sim_file(CacheOpsData *cd);
1292 static void cache_manager_sim_reset(CacheOpsData *cd)
1294 filelist_free(cd->list);
1297 filelist_free(cd->list_dir);
1298 cd->list_dir = NULL;
1300 cache_loader_free((CacheLoader *)cd->cl);
1304 static void cache_manager_sim_close_cb(GenericDialog *UNUSED(fd), gpointer data)
1306 CacheOpsData *cd = static_cast<CacheOpsData *>(data);
1308 if (!gtk_widget_get_sensitive(cd->button_close)) return;
1310 cache_manager_sim_reset(cd);
1311 generic_dialog_close(cd->gd);
1315 static void cache_manager_sim_finish(CacheOpsData *cd)
1317 cache_manager_sim_reset(cd);
1320 spinner_set_interval(cd->spinner, -1);
1322 gtk_widget_set_sensitive(cd->group, TRUE);
1323 gtk_widget_set_sensitive(cd->button_start, TRUE);
1324 gtk_widget_set_sensitive(cd->button_stop, FALSE);
1325 gtk_widget_set_sensitive(cd->button_close, TRUE);
1329 static void cache_manager_sim_stop_cb(GenericDialog *UNUSED(fd), gpointer data)
1331 CacheOpsData *cd = static_cast<CacheOpsData *>(data);
1333 gtk_entry_set_text(GTK_ENTRY(cd->progress), _("stopped"));
1334 cache_manager_sim_finish(cd);
1337 static void cache_manager_sim_folder(CacheOpsData *cd, FileData *dir_fd)
1339 GList *list_d = NULL;
1340 GList *list_f = NULL;
1344 filelist_read(dir_fd, &list_f, &list_d);
1348 filelist_read(dir_fd, &list_f, NULL);
1351 list_f = filelist_filter(list_f, FALSE);
1352 list_d = filelist_filter(list_d, TRUE);
1354 cd->list = g_list_concat(list_f, cd->list);
1355 cd->list_dir = g_list_concat(list_d, cd->list_dir);
1358 static void cache_manager_sim_file_done_cb(CacheLoader *UNUSED(cl), gint UNUSED(error), gpointer data)
1360 CacheOpsData *cd = static_cast<CacheOpsData *>(data);
1362 cache_loader_free((CacheLoader *)cd->cl);
1365 while (cache_manager_sim_file(cd));
1368 static void cache_manager_sim_start_sim_remote(CacheOpsData *cd, const gchar *user_path)
1372 path = remove_trailing_slash(user_path);
1373 parse_out_relatives(path);
1377 log_printf("The specified folder can not be found: %s\n", path);
1383 dir_fd = file_data_new_dir(path);
1384 cache_manager_sim_folder(cd, dir_fd);
1385 file_data_unref(dir_fd);
1386 while (cache_manager_sim_file(cd));
1393 * @brief Generate .sim files
1394 * @param path Path to image folder
1396 * @param func Function called when idle loop function terminates
1400 void cache_manager_sim_remote(const gchar *path, gboolean recurse, GDestroyNotify *func)
1404 cd = g_new0(CacheOpsData, 1);
1405 cd->recurse = recurse;
1407 cd->destroy_func = func;
1409 cache_manager_sim_start_sim_remote(cd, path);
1412 static gboolean cache_manager_sim_file(CacheOpsData *cd)
1414 CacheDataType load_mask;
1419 fd = static_cast<FileData *>(cd->list->data);
1420 cd->list = g_list_remove(cd->list, fd);
1422 load_mask = static_cast<CacheDataType>(CACHE_LOADER_DIMENSIONS | CACHE_LOADER_DATE | CACHE_LOADER_MD5SUM | CACHE_LOADER_SIMILARITY);
1423 cd->cl = (CacheLoader *)cache_loader_new(fd, load_mask, (cache_manager_sim_file_done_cb), cd);
1427 gtk_entry_set_text(GTK_ENTRY(cd->progress), fd->path);
1430 file_data_unref(fd);
1431 cd->count_done = cd->count_done + 1;
1434 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(cd->progress_bar), (gdouble)cd->count_done / cd->count_total);
1439 else if (cd->list_dir)
1443 fd = static_cast<FileData *>(cd->list_dir->data);
1444 cd->list_dir = g_list_remove(cd->list_dir, fd);
1446 cache_manager_sim_folder((CacheOpsData *)cd, fd);
1447 file_data_unref(fd);
1454 gtk_entry_set_text(GTK_ENTRY(cd->progress), _("done"));
1457 cache_manager_sim_finish((CacheOpsData *)cd);
1459 if (cd->destroy_func)
1461 g_idle_add((GSourceFunc)cd->destroy_func, NULL);
1467 static void cache_manager_sim_start_cb(GenericDialog *UNUSED(fd), gpointer data)
1469 CacheOpsData *cd = static_cast<CacheOpsData *>(data);
1471 GList *list_total = NULL;
1475 if (cd->list || !gtk_widget_get_sensitive(cd->button_start)) return;
1478 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(cd->entry))));
1479 parse_out_relatives(path);
1485 warning_dialog(_("Invalid folder"),
1486 _("The specified folder can not be found."),
1487 GTK_STOCK_DIALOG_WARNING, cd->gd->dialog);
1491 log_printf("The specified folder can not be found: %s\n", path);
1499 gtk_widget_set_sensitive(cd->group, FALSE);
1500 gtk_widget_set_sensitive(cd->button_start, FALSE);
1501 gtk_widget_set_sensitive(cd->button_stop, TRUE);
1502 gtk_widget_set_sensitive(cd->button_close, FALSE);
1504 spinner_set_interval(cd->spinner, SPINNER_SPEED);
1506 dir_fd = file_data_new_dir(path);
1507 cache_manager_sim_folder(cd, dir_fd);
1508 list_total = filelist_recursive(dir_fd);
1509 cd->count_total = g_list_length(list_total);
1510 file_data_unref(dir_fd);
1511 g_list_free(list_total);
1514 while (cache_manager_sim_file((CacheOpsData *)cd));
1520 static void cache_manager_sim_load_dialog(GtkWidget *widget, const gchar *path)
1526 cd = g_new0(CacheOpsData, 1);
1530 cd->gd = generic_dialog_new(_("Create sim. files"), "create_sim_files", widget, FALSE, NULL, cd);
1531 gtk_window_set_default_size(GTK_WINDOW(cd->gd->dialog), PURGE_DIALOG_WIDTH, -1);
1532 cd->gd->cancel_cb = cache_manager_sim_close_cb;
1533 cd->button_close = generic_dialog_add_button(cd->gd, GTK_STOCK_CLOSE, NULL,
1534 cache_manager_sim_close_cb, FALSE);
1535 cd->button_start = generic_dialog_add_button(cd->gd, GTK_STOCK_OK, _("S_tart"),
1536 cache_manager_sim_start_cb, FALSE);
1537 cd->button_stop = generic_dialog_add_button(cd->gd, GTK_STOCK_STOP, NULL,
1538 cache_manager_sim_stop_cb, FALSE);
1539 gtk_widget_set_sensitive(cd->button_stop, FALSE);
1541 generic_dialog_add_message(cd->gd, NULL, _("Create sim. files recursively"), NULL, FALSE);
1543 hbox = pref_box_new(cd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
1544 pref_spacer(hbox, PREF_PAD_INDENT);
1545 cd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1547 hbox = pref_box_new(cd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1548 pref_label_new(hbox, _("Folder:"));
1550 label = tab_completion_new(&cd->entry, path, NULL, NULL, NULL, NULL);
1551 tab_completion_add_select_button(cd->entry,_("Select folder") , TRUE);
1552 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
1553 gtk_widget_show(label);
1555 pref_line(cd->gd->vbox, PREF_PAD_SPACE);
1556 hbox = pref_box_new(cd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1558 cd->progress = gtk_entry_new();
1559 gtk_widget_set_can_focus(cd->progress, FALSE);
1560 gtk_editable_set_editable(GTK_EDITABLE(cd->progress), FALSE);
1561 gtk_entry_set_text(GTK_ENTRY(cd->progress), _("click start to begin"));
1562 gtk_box_pack_start(GTK_BOX(hbox), cd->progress, TRUE, TRUE, 0);
1563 gtk_widget_show(cd->progress);
1565 cd->progress_bar = gtk_progress_bar_new();
1566 gtk_box_pack_start(GTK_BOX(cd->gd->vbox), cd->progress_bar, TRUE, TRUE, 0);
1567 gtk_widget_show(cd->progress_bar);
1569 cd->spinner = spinner_new(NULL, -1);
1570 gtk_box_pack_start(GTK_BOX(hbox), cd->spinner, FALSE, FALSE, 0);
1571 gtk_widget_show(cd->spinner);
1575 gtk_widget_show(cd->gd->dialog);
1578 static void cache_manager_sim_load_cb(GtkWidget *widget, gpointer UNUSED(data))
1580 const gchar *path = layout_get_path(NULL);
1582 if (!path || !*path) path = homedir();
1583 cache_manager_sim_load_dialog(widget, path);
1586 static void cache_manager_cache_maintenance_close_cb(GenericDialog *UNUSED(fd), gpointer data)
1588 CacheOpsData *cd = static_cast<CacheOpsData *>(data);
1590 if (!gtk_widget_get_sensitive(cd->button_close)) return;
1592 cache_manager_sim_reset(cd);
1593 generic_dialog_close(cd->gd);
1597 static void cache_manager_cache_maintenance_start_cb(GenericDialog *UNUSED(fd), gpointer data)
1599 CacheOpsData *cd = static_cast<CacheOpsData *>(data);
1605 if (cd->list || !gtk_widget_get_sensitive(cd->button_start)) return;
1608 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(cd->entry))));
1609 parse_out_relatives(path);
1615 warning_dialog(_("Invalid folder"),
1616 _("The specified folder can not be found."),
1617 GTK_STOCK_DIALOG_WARNING, cd->gd->dialog);
1621 log_printf("The specified folder can not be found: \"%s\"\n", path);
1626 cmd_line = g_strdup_printf("%s --cache-maintenance \"%s\"", gq_executable_path, path);
1628 g_spawn_command_line_async(cmd_line, NULL);
1631 generic_dialog_close(cd->gd);
1632 cache_manager_sim_reset(cd);
1639 static void cache_manager_cache_maintenance_load_dialog(GtkWidget *widget, const gchar *path)
1645 cd = g_new0(CacheOpsData, 1);
1649 cd->gd = generic_dialog_new(_("Background cache maintenance"), "background_cache_maintenance", widget, FALSE, NULL, cd);
1650 gtk_window_set_default_size(GTK_WINDOW(cd->gd->dialog), PURGE_DIALOG_WIDTH, -1);
1651 cd->gd->cancel_cb = cache_manager_cache_maintenance_close_cb;
1652 cd->button_close = generic_dialog_add_button(cd->gd, GTK_STOCK_CLOSE, NULL,
1653 cache_manager_cache_maintenance_close_cb, FALSE);
1654 cd->button_start = generic_dialog_add_button(cd->gd, GTK_STOCK_OK, _("S_tart"),
1655 cache_manager_cache_maintenance_start_cb, FALSE);
1657 generic_dialog_add_message(cd->gd, NULL, _("Recursively delete orphaned thumbnails\nand .sim files, and create new\nthumbnails and .sim files"), NULL, FALSE);
1659 hbox = pref_box_new(cd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
1660 pref_spacer(hbox, PREF_PAD_INDENT);
1661 cd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1663 hbox = pref_box_new(cd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1664 pref_label_new(hbox, _("Folder:"));
1666 label = tab_completion_new(&cd->entry, path, NULL, NULL, NULL, NULL);
1667 tab_completion_add_select_button(cd->entry,_("Select folder") , TRUE);
1668 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
1669 gtk_widget_show(label);
1673 gtk_widget_show(cd->gd->dialog);
1676 static void cache_manager_cache_maintenance_load_cb(GtkWidget *widget, gpointer UNUSED(data))
1678 const gchar *path = layout_get_path(NULL);
1680 if (!path || !*path) path = homedir();
1681 cache_manager_cache_maintenance_load_dialog(widget, path);
1684 void cache_manager_show(void)
1690 GtkSizeGroup *sizegroup;
1695 gtk_window_present(GTK_WINDOW(cache_manager->dialog->dialog));
1699 cache_manager = g_new0(CacheManager, 1);
1701 cache_manager->dialog = generic_dialog_new(_("Cache Maintenance"),
1704 NULL, cache_manager);
1705 gd = cache_manager->dialog;
1707 gd->cancel_cb = cache_manager_close_cb;
1708 generic_dialog_add_button(gd, GTK_STOCK_CLOSE, NULL,
1709 cache_manager_close_cb, FALSE);
1710 generic_dialog_add_button(gd, GTK_STOCK_HELP, NULL,
1711 cache_manager_help_cb, FALSE);
1713 generic_dialog_add_message(gd, NULL, _("Cache and Data Maintenance"), NULL, FALSE);
1715 sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
1717 group = pref_group_new(gd->vbox, FALSE, _("Geeqie thumbnail and sim. cache"), GTK_ORIENTATION_VERTICAL);
1719 cache_manager_location_label(group, get_thumbnails_cache_dir());
1721 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1723 button = pref_table_button(table, 0, 0, GTK_STOCK_CLEAR, _("Clean up"), FALSE,
1724 G_CALLBACK(cache_manager_main_clean_cb), cache_manager);
1725 gtk_size_group_add_widget(sizegroup, button);
1726 pref_table_label(table, 1, 0, _("Remove orphaned or outdated thumbnails and sim. files."), 0.0);
1728 button = pref_table_button(table, 0, 1, GTK_STOCK_DELETE, _("Clear cache"), FALSE,
1729 G_CALLBACK(cache_manager_main_clear_cb), cache_manager);
1730 gtk_size_group_add_widget(sizegroup, button);
1731 pref_table_label(table, 1, 1, _("Delete all cached data."), 0.0);
1734 group = pref_group_new(gd->vbox, FALSE, _("Shared thumbnail cache"), GTK_ORIENTATION_VERTICAL);
1736 path = g_build_filename(get_thumbnails_standard_cache_dir(), NULL);
1737 cache_manager_location_label(group, path);
1740 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1742 button = pref_table_button(table, 0, 0, GTK_STOCK_CLEAR, _("Clean up"), FALSE,
1743 G_CALLBACK(cache_manager_standard_clean_cb), cache_manager);
1744 gtk_size_group_add_widget(sizegroup, button);
1745 pref_table_label(table, 1, 0, _("Remove orphaned or outdated thumbnails."), 0.0);
1747 button = pref_table_button(table, 0, 1, GTK_STOCK_DELETE, _("Clear cache"), FALSE,
1748 G_CALLBACK(cache_manager_standard_clear_cb), cache_manager);
1749 gtk_size_group_add_widget(sizegroup, button);
1750 pref_table_label(table, 1, 1, _("Delete all cached thumbnails."), 0.0);
1752 group = pref_group_new(gd->vbox, FALSE, _("Create thumbnails"), GTK_ORIENTATION_VERTICAL);
1754 table = pref_table_new(group, 2, 1, FALSE, FALSE);
1756 button = pref_table_button(table, 0, 1, "system-run", _("Render"), FALSE,
1757 G_CALLBACK(cache_manager_render_cb), cache_manager);
1758 gtk_size_group_add_widget(sizegroup, button);
1759 pref_table_label(table, 1, 1, _("Render thumbnails for a specific folder."), 0.0);
1760 gtk_widget_set_sensitive(group, options->thumbnails.enable_caching);
1762 group = pref_group_new(gd->vbox, FALSE, _("File similarity cache"), GTK_ORIENTATION_VERTICAL);
1764 table = pref_table_new(group, 3, 2, FALSE, FALSE);
1766 button = pref_table_button(table, 0, 0, GTK_STOCK_EXECUTE, _("Create"), FALSE,
1767 G_CALLBACK(cache_manager_sim_load_cb), cache_manager);
1768 gtk_size_group_add_widget(sizegroup, button);
1769 pref_table_label(table, 1, 0, _("Create sim. files recursively."), 0.0);
1770 gtk_widget_set_sensitive(group, options->thumbnails.enable_caching);
1772 group = pref_group_new(gd->vbox, FALSE, _("Metadata"), GTK_ORIENTATION_VERTICAL);
1774 cache_manager_location_label(group, get_metadata_cache_dir());
1776 table = pref_table_new(group, 2, 1, FALSE, FALSE);
1778 button = pref_table_button(table, 0, 0, GTK_STOCK_CLEAR, _("Clean up"), FALSE,
1779 G_CALLBACK(cache_manager_metadata_clean_cb), cache_manager);
1780 gtk_size_group_add_widget(sizegroup, button);
1781 pref_table_label(table, 1, 0, _("Remove orphaned keywords and comments."), 0.0);
1783 group = pref_group_new(gd->vbox, FALSE, _("Background cache maintenance"), GTK_ORIENTATION_VERTICAL);
1785 table = pref_table_new(group, 3, 2, FALSE, FALSE);
1787 button = pref_table_button(table, 0, 0, GTK_STOCK_EXECUTE, _("Select"), FALSE,
1788 G_CALLBACK(cache_manager_cache_maintenance_load_cb), cache_manager);
1789 gtk_size_group_add_widget(sizegroup, button);
1790 pref_table_label(table, 1, 0, _("Run cache maintenance as a background job."), 0.0);
1791 gtk_widget_set_sensitive(group, options->thumbnails.enable_caching);
1793 gtk_widget_show(cache_manager->dialog->dialog);
1795 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */