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"
29 #include "pixbuf-util.h"
31 #include "thumb-standard.h"
32 #include "ui-fileops.h"
34 #include "ui-tabcomp.h"
35 #include "ui-utildlg.h"
43 guint idle_id; /* event source id */
47 GtkWidget *button_stop;
48 GtkWidget *button_close;
54 #define PURGE_DIALOG_WIDTH 400
57 *-----------------------------------------------------------------------------
58 * Command line cache maintenance program functions *-----------------------------------------------------------------------------
60 static gchar *cache_maintenance_path = nullptr;
61 static GtkStatusIcon *status_icon;
63 static void cache_maintenance_sim_stop_cb(gpointer)
68 static void cache_maintenance_render_stop_cb(gpointer)
70 gtk_status_icon_set_tooltip_text(status_icon, _("Geeqie: Creating sim data..."));
71 cache_manager_sim_remote(cache_maintenance_path, TRUE, reinterpret_cast<GDestroyNotify *>(cache_maintenance_sim_stop_cb));
74 static void cache_maintenance_clean_stop_cb(gpointer)
76 gtk_status_icon_set_tooltip_text(status_icon, _("Geeqie: Creating thumbs..."));
77 cache_manager_render_remote(cache_maintenance_path, TRUE, options->thumbnails.cache_into_dirs, reinterpret_cast<GDestroyNotify *>(cache_maintenance_render_stop_cb));
80 static void cache_maintenance_user_cancel_cb()
85 static void cache_maintenance_status_icon_activate_cb(GtkStatusIcon *, gpointer)
90 menu = gtk_menu_new();
92 item = gtk_menu_item_new_with_label(_("Exit Geeqie Cache Maintenance"));
94 g_signal_connect(G_OBJECT(item), "activate", cache_maintenance_user_cancel_cb, item);
95 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
96 gtk_widget_show(item);
98 /* take ownership of menu */
99 g_object_ref_sink(G_OBJECT(menu));
101 gtk_menu_popup_at_pointer(GTK_MENU(menu), nullptr);
104 void cache_maintenance(const gchar *path)
106 cache_maintenance_path = g_strdup(path);
108 status_icon = gtk_status_icon_new_from_pixbuf(pixbuf_inline(PIXBUF_INLINE_ICON));
109 gtk_status_icon_set_tooltip_text(status_icon, _("Geeqie: Cleaning thumbs..."));
110 gtk_status_icon_set_visible(status_icon, TRUE);
111 g_signal_connect(G_OBJECT(status_icon), "activate", G_CALLBACK(cache_maintenance_status_icon_activate_cb), NULL);
113 cache_maintain_home_remote(FALSE, FALSE, reinterpret_cast<GDestroyNotify *>(cache_maintenance_clean_stop_cb));
117 *-------------------------------------------------------------------
119 *-------------------------------------------------------------------
122 static gchar *extension_find_dot(gchar *path)
124 gchar *dot = nullptr;
126 if (!path) return nullptr;
128 while (*path != '\0')
130 if (*path == '.') dot = path;
137 static gboolean isempty(const gchar *path)
143 pathl = path_from_utf8(path);
146 if (!dp) return FALSE;
148 while ((dir = readdir(dp)) != nullptr)
150 gchar *name = dir->d_name;
152 if (name[0] != '.' || (name[1] != '\0' && (name[1] != '.' || name[2] != '\0')) )
163 static void cache_maintain_home_close(CMData *cm)
165 if (cm->idle_id) g_source_remove(cm->idle_id);
166 if (cm->gd) generic_dialog_close(cm->gd);
167 filelist_free(cm->list);
168 g_list_free(cm->done_list);
172 static void cache_maintain_home_stop(CMData *cm)
176 g_source_remove(cm->idle_id);
182 gq_gtk_entry_set_text(GTK_ENTRY(cm->entry), _("done"));
183 gtk_spinner_stop(GTK_SPINNER(cm->spinner));
185 gtk_widget_set_sensitive(cm->button_stop, FALSE);
186 gtk_widget_set_sensitive(cm->button_close, TRUE);
190 static gboolean cache_maintain_home_cb(gpointer data)
192 auto cm = static_cast<CMData *>(data);
193 GList *dlist = nullptr;
194 GList *list = nullptr;
196 gboolean just_done = FALSE;
197 gboolean still_have_a_file = TRUE;
199 const gchar *cache_folder;
200 gboolean filter_disable;
204 cache_folder = get_metadata_cache_dir();
208 cache_folder = get_thumbnails_cache_dir();
211 base_length = strlen(cache_folder);
215 DEBUG_1("purge chk done.");
217 cache_maintain_home_stop(cm);
218 return G_SOURCE_REMOVE;
221 fd = static_cast<FileData *>(cm->list->data);
223 DEBUG_1("purge chk (%d) \"%s\"", (cm->clear && !cm->metadata), fd->path);
226 * It is necessary to disable the file filter when clearing the cache,
227 * otherwise the .sim (file similarity) files are not deleted.
229 filter_disable = options->file_filter.disable;
230 options->file_filter.disable = TRUE;
232 if (g_list_find(cm->done_list, fd) == nullptr)
234 cm->done_list = g_list_prepend(cm->done_list, fd);
236 if (filelist_read(fd, &list, &dlist))
241 still_have_a_file = FALSE;
246 auto fd_list = static_cast<FileData *>(work->data);
247 gchar *path_buf = g_strdup(fd_list->path);
250 dot = extension_find_dot(path_buf);
252 if (dot) *dot = '\0';
253 if ((!cm->metadata && cm->clear) ||
254 (strlen(path_buf) > base_length && !isfile(path_buf + base_length)) )
257 if (!unlink_file(path_buf)) log_printf("failed to delete:%s\n", path_buf);
261 still_have_a_file = TRUE;
268 options->file_filter.disable = filter_disable;
272 cm->list = g_list_concat(dlist, cm->list);
274 if (cm->list && g_list_find(cm->done_list, cm->list->data) != nullptr)
276 /* check if the dir is empty */
278 if (cm->list->data == fd && just_done)
280 if (!still_have_a_file && !dlist && cm->list->next && !rmdir_utf8(fd->path))
282 log_printf("Unable to delete dir: %s\n", fd->path);
287 /* must re-check for an empty dir */
288 if (isempty(fd->path) && cm->list->next && !rmdir_utf8(fd->path))
290 log_printf("Unable to delete dir: %s\n", fd->path);
294 fd = static_cast<FileData *>(cm->list->data);
295 cm->done_list = g_list_remove(cm->done_list, fd);
296 cm->list = g_list_remove(cm->list, fd);
300 if (cm->list && !cm->remote)
304 fd = static_cast<FileData *>(cm->list->data);
305 if (strlen(fd->path) > base_length)
307 buf = fd->path + base_length;
313 gq_gtk_entry_set_text(GTK_ENTRY(cm->entry), buf);
316 return G_SOURCE_CONTINUE;
319 static void cache_maintain_home_close_cb(GenericDialog *, gpointer data)
321 auto cm = static_cast<CMData *>(data);
323 if (!gtk_widget_get_sensitive(cm->button_close)) return;
325 cache_maintain_home_close(cm);
328 static void cache_maintain_home_stop_cb(GenericDialog *, gpointer data)
330 auto cm = static_cast<CMData *>(data);
332 cache_maintain_home_stop(cm);
335 /* sorry for complexity (cm->done_list), but need it to remove empty dirs */
336 void cache_maintain_home(gboolean metadata, gboolean clear, GtkWidget *parent)
342 const gchar *cache_folder;
347 cache_folder = get_metadata_cache_dir();
351 cache_folder = get_thumbnails_cache_dir();
354 dir_fd = file_data_new_dir(cache_folder);
355 if (!filelist_read(dir_fd, nullptr, &dlist))
357 file_data_unref(dir_fd);
361 dlist = g_list_append(dlist, dir_fd);
363 cm = g_new0(CMData, 1);
365 cm->done_list = nullptr;
367 cm->metadata = metadata;
372 msg = _("Removing old metadata...");
376 msg = _("Clearing cached thumbnails...");
380 msg = _("Removing old thumbnails...");
383 cm->gd = generic_dialog_new(_("Maintenance"),
387 cm->gd->cancel_cb = cache_maintain_home_close_cb;
388 cm->button_close = generic_dialog_add_button(cm->gd, GQ_ICON_CLOSE, _("Close"),
389 cache_maintain_home_close_cb, FALSE);
390 gtk_widget_set_sensitive(cm->button_close, FALSE);
391 cm->button_stop = generic_dialog_add_button(cm->gd, GQ_ICON_STOP, _("Stop"),
392 cache_maintain_home_stop_cb, FALSE);
394 generic_dialog_add_message(cm->gd, nullptr, msg, nullptr, FALSE);
395 gtk_window_set_default_size(GTK_WINDOW(cm->gd->dialog), PURGE_DIALOG_WIDTH, -1);
397 hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
398 gq_gtk_box_pack_start(GTK_BOX(cm->gd->vbox), hbox, FALSE, FALSE, 5);
399 gtk_widget_show(hbox);
401 cm->entry = gtk_entry_new();
402 gtk_widget_set_can_focus(cm->entry, FALSE);
403 gtk_editable_set_editable(GTK_EDITABLE(cm->entry), FALSE);
404 gq_gtk_box_pack_start(GTK_BOX(hbox), cm->entry, TRUE, TRUE, 0);
405 gtk_widget_show(cm->entry);
407 cm->spinner = gtk_spinner_new();
408 gtk_spinner_start(GTK_SPINNER(cm->spinner));
409 gq_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, nullptr, &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 = nullptr;
454 cm->metadata = metadata;
457 cm->idle_id = g_idle_add_full(G_PRIORITY_LOW, cache_maintain_home_cb, cm, reinterpret_cast<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, nullptr);
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, nullptr);
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, nullptr);
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, nullptr);
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)
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 *-------------------------------------------------------------------
609 GenericDialog *dialog;
610 GtkWidget *folder_entry;
624 GDestroyNotify *destroy_func; /* Used by the command line prog. functions */
632 GtkWidget *button_close;
633 GtkWidget *button_stop;
634 GtkWidget *button_start;
636 GtkWidget *progress_bar;
650 guint idle_id; /* event source id */
653 static void cache_manager_render_reset(CacheOpsData *cd)
655 filelist_free(cd->list);
658 filelist_free(cd->list_dir);
659 cd->list_dir = nullptr;
661 thumb_loader_free(reinterpret_cast<ThumbLoader *>(cd->tl));
665 static void cache_manager_render_close_cb(GenericDialog *, gpointer data)
667 auto cd = static_cast<CacheOpsData *>(data);
669 if (!gtk_widget_get_sensitive(cd->button_close)) return;
671 cache_manager_render_reset(cd);
672 generic_dialog_close(cd->gd);
676 static void cache_manager_render_finish(CacheOpsData *cd)
678 cache_manager_render_reset(cd);
681 gq_gtk_entry_set_text(GTK_ENTRY(cd->progress), _("done"));
682 gtk_spinner_stop(GTK_SPINNER(cd->spinner));
684 gtk_widget_set_sensitive(cd->group, TRUE);
685 gtk_widget_set_sensitive(cd->button_start, TRUE);
686 gtk_widget_set_sensitive(cd->button_stop, FALSE);
687 gtk_widget_set_sensitive(cd->button_close, TRUE);
691 static void cache_manager_render_stop_cb(GenericDialog *, gpointer data)
693 auto cd = static_cast<CacheOpsData *>(data);
695 gq_gtk_entry_set_text(GTK_ENTRY(cd->progress), _("stopped"));
696 cache_manager_render_finish(cd);
699 static void cache_manager_render_folder(CacheOpsData *cd, FileData *dir_fd)
701 GList *list_d = nullptr;
702 GList *list_f = nullptr;
706 filelist_read(dir_fd, &list_f, &list_d);
710 filelist_read(dir_fd, &list_f, nullptr);
713 list_f = filelist_filter(list_f, FALSE);
714 list_d = filelist_filter(list_d, TRUE);
716 cd->list = g_list_concat(list_f, cd->list);
717 cd->list_dir = g_list_concat(list_d, cd->list_dir);
720 static gboolean cache_manager_render_file(CacheOpsData *cd);
722 static void cache_manager_render_thumb_done_cb(ThumbLoader *, gpointer data)
724 auto cd = static_cast<CacheOpsData *>(data);
726 thumb_loader_free(reinterpret_cast<ThumbLoader *>(cd->tl));
729 while (cache_manager_render_file(cd));
732 static gboolean cache_manager_render_file(CacheOpsData *cd)
739 fd = static_cast<FileData *>(cd->list->data);
740 cd->list = g_list_remove(cd->list, fd);
742 cd->tl = reinterpret_cast<ThumbLoaderStd *>(thumb_loader_new(options->thumbnails.max_width, options->thumbnails.max_height));
743 thumb_loader_set_callbacks(reinterpret_cast<ThumbLoader *>(cd->tl),
744 cache_manager_render_thumb_done_cb,
745 cache_manager_render_thumb_done_cb,
747 thumb_loader_set_cache(reinterpret_cast<ThumbLoader *>(cd->tl), TRUE, cd->local, TRUE);
748 success = thumb_loader_start(reinterpret_cast<ThumbLoader *>(cd->tl), fd);
753 gq_gtk_entry_set_text(GTK_ENTRY(cd->progress), fd->path);
754 cd->count_done = cd->count_done + 1;
755 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(cd->progress_bar), static_cast<gdouble>(cd->count_done) / cd->count_total);
760 thumb_loader_free(reinterpret_cast<ThumbLoader *>(cd->tl));
768 else if (cd->list_dir)
772 fd = static_cast<FileData *>(cd->list_dir->data);
773 cd->list_dir = g_list_remove(cd->list_dir, fd);
775 cache_manager_render_folder(cd, fd);
784 gq_gtk_entry_set_text(GTK_ENTRY(cd->progress), _("done"));
786 cache_manager_render_finish(cd);
788 if (cd->destroy_func)
790 g_idle_add(reinterpret_cast<GSourceFunc>(cd->destroy_func), nullptr);
796 static void cache_manager_render_start_cb(GenericDialog *, gpointer data)
798 auto cd = static_cast<CacheOpsData *>(data);
800 GList *list_total = nullptr;
804 if (cd->list || !gtk_widget_get_sensitive(cd->button_start)) return;
807 path = remove_trailing_slash((gq_gtk_entry_get_text(GTK_ENTRY(cd->entry))));
808 parse_out_relatives(path);
814 warning_dialog(_("Invalid folder"),
815 _("The specified folder can not be found."),
816 GQ_ICON_DIALOG_WARNING, cd->gd->dialog);
820 log_printf("The specified folder can not be found: %s\n", path);
828 gtk_widget_set_sensitive(cd->group, FALSE);
829 gtk_widget_set_sensitive(cd->button_start, FALSE);
830 gtk_widget_set_sensitive(cd->button_stop, TRUE);
831 gtk_widget_set_sensitive(cd->button_close, FALSE);
833 gtk_spinner_start(GTK_SPINNER(cd->spinner));
835 dir_fd = file_data_new_dir(path);
836 cache_manager_render_folder(cd, dir_fd);
837 list_total = filelist_recursive(dir_fd);
838 cd->count_total = g_list_length(list_total);
839 file_data_unref(dir_fd);
840 g_list_free(list_total);
843 while (cache_manager_render_file(cd));
849 static void cache_manager_render_start_render_remote(CacheOpsData *cd, const gchar *user_path)
853 path = remove_trailing_slash(user_path);
854 parse_out_relatives(path);
858 log_printf("The specified folder can not be found: %s\n", path);
864 dir_fd = file_data_new_dir(path);
865 cache_manager_render_folder(cd, dir_fd);
866 file_data_unref(dir_fd);
867 while (cache_manager_render_file(cd));
873 static void cache_manager_render_dialog(GtkWidget *widget, const gchar *path)
880 cd = g_new0(CacheOpsData, 1);
883 cd->gd = generic_dialog_new(_("Create thumbnails"),
887 gtk_window_set_default_size(GTK_WINDOW(cd->gd->dialog), PURGE_DIALOG_WIDTH, -1);
888 cd->gd->cancel_cb = cache_manager_render_close_cb;
889 cd->button_close = generic_dialog_add_button(cd->gd, GQ_ICON_CLOSE, _("Close"),
890 cache_manager_render_close_cb, FALSE);
891 cd->button_start = generic_dialog_add_button(cd->gd, GQ_ICON_OK, _("S_tart"),
892 cache_manager_render_start_cb, FALSE);
893 cd->button_stop = generic_dialog_add_button(cd->gd, GQ_ICON_STOP, _("Stop"),
894 cache_manager_render_stop_cb, FALSE);
895 gtk_widget_set_sensitive(cd->button_stop, FALSE);
897 generic_dialog_add_message(cd->gd, nullptr, _("Create thumbnails"), nullptr, FALSE);
899 hbox = pref_box_new(cd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
900 pref_spacer(hbox, PREF_PAD_INDENT);
901 cd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
903 hbox = pref_box_new(cd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
904 pref_label_new(hbox, _("Folder:"));
906 label = tab_completion_new(&cd->entry, path, nullptr, nullptr, nullptr, nullptr);
907 tab_completion_add_select_button(cd->entry,_("Select folder") , TRUE);
908 gq_gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
909 gtk_widget_show(label);
911 pref_checkbox_new_int(cd->group, _("Include subfolders"), FALSE, &cd->recurse);
912 button = pref_checkbox_new_int(cd->group, _("Store thumbnails local to source images"), FALSE, &cd->local);
913 gtk_widget_set_sensitive(button, options->thumbnails.spec_standard);
915 pref_line(cd->gd->vbox, PREF_PAD_SPACE);
916 hbox = pref_box_new(cd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
918 cd->progress = gtk_entry_new();
919 gtk_widget_set_can_focus(cd->progress, FALSE);
920 gtk_editable_set_editable(GTK_EDITABLE(cd->progress), FALSE);
921 gq_gtk_entry_set_text(GTK_ENTRY(cd->progress), _("click start to begin"));
922 gq_gtk_box_pack_start(GTK_BOX(hbox), cd->progress, TRUE, TRUE, 0);
923 gtk_widget_show(cd->progress);
925 cd->progress_bar = gtk_progress_bar_new();
926 gq_gtk_box_pack_start(GTK_BOX(cd->gd->vbox), cd->progress_bar, TRUE, TRUE, 0);
927 gtk_widget_show(cd->progress_bar);
929 cd->spinner = gtk_spinner_new();
930 gq_gtk_box_pack_start(GTK_BOX(hbox), cd->spinner, FALSE, FALSE, 0);
931 gtk_widget_show(cd->spinner);
935 gtk_widget_show(cd->gd->dialog);
939 * @brief Create thumbnails
940 * @param path Path to image folder
942 * @param local Create thumbnails in same folder as images
943 * @param func Function called when idle loop function terminates
947 void cache_manager_render_remote(const gchar *path, gboolean recurse, gboolean local, GDestroyNotify *func)
951 cd = g_new0(CacheOpsData, 1);
952 cd->recurse = recurse;
955 cd->destroy_func = func;
957 cache_manager_render_start_render_remote(cd, path);
960 static void cache_manager_standard_clean_close_cb(GenericDialog *, gpointer data)
962 auto cd = static_cast<CacheOpsData *>(data);
964 if (!gtk_widget_get_sensitive(cd->button_close)) return;
966 generic_dialog_close(cd->gd);
968 thumb_loader_std_thumb_file_validate_cancel(cd->tl);
969 filelist_free(cd->list);
973 static void cache_manager_standard_clean_done(CacheOpsData *cd)
977 gtk_widget_set_sensitive(cd->button_stop, FALSE);
978 gtk_widget_set_sensitive(cd->button_close, TRUE);
980 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(cd->progress), 1.0);
981 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(cd->progress), _("done"));
985 g_source_remove(cd->idle_id);
989 thumb_loader_std_thumb_file_validate_cancel(cd->tl);
992 filelist_free(cd->list);
996 static void cache_manager_standard_clean_stop_cb(GenericDialog *, gpointer data)
998 auto cd = static_cast<CacheOpsData *>(data);
1000 cache_manager_standard_clean_done(cd);
1003 static gint cache_manager_standard_clean_clear_cb(gpointer data)
1005 auto cd = static_cast<CacheOpsData *>(data);
1011 next_fd = static_cast<FileData *>(cd->list->data);
1012 cd->list = g_list_remove(cd->list, next_fd);
1014 DEBUG_1("thumb removed: %s", next_fd->path);
1016 unlink_file(next_fd->path);
1017 file_data_unref(next_fd);
1022 if (cd->count_total != 0)
1024 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(cd->progress),
1025 static_cast<gdouble>(cd->count_done) / cd->count_total);
1029 return G_SOURCE_CONTINUE;
1033 cache_manager_standard_clean_done(cd);
1034 return G_SOURCE_REMOVE;
1037 static void cache_manager_standard_clean_valid_cb(const gchar *path, gboolean valid, gpointer data)
1039 auto cd = static_cast<CacheOpsData *>(data);
1045 DEBUG_1("thumb cleaned: %s", path);
1052 if (cd->count_total != 0)
1054 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(cd->progress),
1055 static_cast<gdouble>(cd->count_done) / cd->count_total);
1065 next_fd = static_cast<FileData *>(cd->list->data);
1066 cd->list = g_list_remove(cd->list, next_fd);
1068 cd->tl = thumb_loader_std_thumb_file_validate(next_fd->path, cd->days,
1069 cache_manager_standard_clean_valid_cb, cd);
1070 file_data_unref(next_fd);
1074 cache_manager_standard_clean_done(cd);
1078 static void cache_manager_standard_clean_start(GenericDialog *, gpointer data)
1080 auto cd = static_cast<CacheOpsData *>(data);
1087 if (cd->list || !gtk_widget_get_sensitive(cd->button_start)) return;
1089 gtk_widget_set_sensitive(cd->button_start, FALSE);
1090 gtk_widget_set_sensitive(cd->button_stop, TRUE);
1091 gtk_widget_set_sensitive(cd->button_close, FALSE);
1093 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(cd->progress), _("running..."));
1096 path = g_build_filename(get_thumbnails_standard_cache_dir(), THUMB_FOLDER_NORMAL, NULL);
1097 dir_fd = file_data_new_dir(path);
1098 filelist_read(dir_fd, &list, nullptr);
1100 file_data_unref(dir_fd);
1103 path = g_build_filename(get_thumbnails_standard_cache_dir(), THUMB_FOLDER_LARGE, NULL);
1104 dir_fd = file_data_new_dir(path);
1105 filelist_read(dir_fd, &list, nullptr);
1106 cd->list = g_list_concat(cd->list, list);
1107 file_data_unref(dir_fd);
1110 path = g_build_filename(get_thumbnails_standard_cache_dir(), THUMB_FOLDER_FAIL, NULL);
1111 dir_fd = file_data_new_dir(path);
1112 filelist_read(dir_fd, &list, nullptr);
1113 cd->list = g_list_concat(cd->list, list);
1114 file_data_unref(dir_fd);
1117 cd->count_total = g_list_length(cd->list);
1120 /* start iterating */
1123 cd->idle_id = g_idle_add(cache_manager_standard_clean_clear_cb, cd);
1127 cache_manager_standard_clean_valid_cb(nullptr, TRUE, cd);
1131 static void cache_manager_standard_clean_start_cb(GenericDialog *gd, gpointer data)
1133 cache_manager_standard_clean_start(gd, data);
1136 static void cache_manager_standard_process(GtkWidget *widget, gboolean clear)
1139 const gchar *icon_name;
1142 cd = g_new0(CacheOpsData, 1);
1148 icon_name = GQ_ICON_DELETE;
1149 msg = _("Clearing thumbnails...");
1153 icon_name = GQ_ICON_CLEAR;
1154 msg = _("Removing old thumbnails...");
1157 cd->gd = generic_dialog_new(_("Maintenance"),
1158 "standard_maintenance",
1161 cd->gd->cancel_cb = cache_manager_standard_clean_close_cb;
1162 cd->button_close = generic_dialog_add_button(cd->gd, GQ_ICON_CLOSE, _("Close"),
1163 cache_manager_standard_clean_close_cb, FALSE);
1164 cd->button_start = generic_dialog_add_button(cd->gd, GQ_ICON_OK, _("S_tart"),
1165 cache_manager_standard_clean_start_cb, FALSE);
1166 cd->button_stop = generic_dialog_add_button(cd->gd, GQ_ICON_STOP, _("Stop"),
1167 cache_manager_standard_clean_stop_cb, FALSE);
1168 gtk_widget_set_sensitive(cd->button_stop, FALSE);
1170 generic_dialog_add_message(cd->gd, icon_name, msg, NULL, FALSE);
1172 cd->progress = gtk_progress_bar_new();
1173 gtk_progress_bar_set_text(GTK_PROGRESS_BAR(cd->progress), _("click start to begin"));
1174 gtk_progress_bar_set_show_text(GTK_PROGRESS_BAR(cd->progress), TRUE);
1175 gq_gtk_box_pack_start(GTK_BOX(cd->gd->vbox), cd->progress, FALSE, FALSE, 0);
1176 gtk_widget_show(cd->progress);
1182 gtk_widget_show(cd->gd->dialog);
1185 void cache_manager_standard_process_remote(gboolean clear)
1189 cd = g_new0(CacheOpsData, 1);
1196 cache_manager_standard_clean_start(nullptr, cd);
1199 static void cache_manager_standard_clean_cb(GtkWidget *widget, gpointer)
1201 cache_manager_standard_process(widget, FALSE);
1204 static void cache_manager_standard_clear_cb(GtkWidget *widget, gpointer)
1206 cache_manager_standard_process(widget, TRUE);
1210 static void cache_manager_main_clean_cb(GtkWidget *widget, gpointer)
1212 cache_maintain_home(FALSE, FALSE, widget);
1216 static void dummy_cancel_cb(GenericDialog *, gpointer)
1218 /* no op, only so cancel button appears */
1221 static void cache_manager_main_clear_ok_cb(GenericDialog *, gpointer)
1223 cache_maintain_home(FALSE, TRUE, nullptr);
1226 void cache_manager_main_clear_confirm(GtkWidget *parent)
1230 gd = generic_dialog_new(_("Clear cache"),
1231 "clear_cache", parent, TRUE,
1232 dummy_cancel_cb, nullptr);
1233 generic_dialog_add_message(gd, GQ_ICON_DIALOG_QUESTION, _("Clear cache"),
1234 _("This will remove all thumbnails and sim. files\nthat have been saved to disk, continue?"), TRUE);
1235 generic_dialog_add_button(gd, GQ_ICON_OK, "OK", cache_manager_main_clear_ok_cb, TRUE);
1237 gtk_widget_show(gd->dialog);
1240 static void cache_manager_main_clear_cb(GtkWidget *widget, gpointer)
1242 cache_manager_main_clear_confirm(widget);
1245 static void cache_manager_render_cb(GtkWidget *widget, gpointer)
1247 const gchar *path = layout_get_path(nullptr);
1249 if (!path || !*path) path = homedir();
1250 cache_manager_render_dialog(widget, path);
1253 static void cache_manager_metadata_clean_cb(GtkWidget *widget, gpointer)
1255 cache_maintain_home(TRUE, FALSE, widget);
1259 static CacheManager *cache_manager = nullptr;
1261 static void cache_manager_close_cb(GenericDialog *gd, gpointer)
1263 generic_dialog_close(gd);
1265 g_free(cache_manager);
1266 cache_manager = nullptr;
1269 static void cache_manager_help_cb(GenericDialog *, gpointer)
1271 help_window_show("GuideReferenceManagement.html");
1274 static GtkWidget *cache_manager_location_label(GtkWidget *group, const gchar *subdir)
1279 buf = g_strdup_printf(_("Location: %s"), subdir);
1280 label = pref_label_new(group, buf);
1282 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
1283 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
1288 static gboolean cache_manager_sim_file(CacheOpsData *cd);
1290 static void cache_manager_sim_reset(CacheOpsData *cd)
1292 filelist_free(cd->list);
1295 filelist_free(cd->list_dir);
1296 cd->list_dir = nullptr;
1298 cache_loader_free(cd->cl);
1302 static void cache_manager_sim_close_cb(GenericDialog *, gpointer data)
1304 auto cd = static_cast<CacheOpsData *>(data);
1306 if (!gtk_widget_get_sensitive(cd->button_close)) return;
1308 cache_manager_sim_reset(cd);
1309 generic_dialog_close(cd->gd);
1313 static void cache_manager_sim_finish(CacheOpsData *cd)
1315 cache_manager_sim_reset(cd);
1318 gtk_spinner_stop(GTK_SPINNER(cd->spinner));
1320 gtk_widget_set_sensitive(cd->group, TRUE);
1321 gtk_widget_set_sensitive(cd->button_start, TRUE);
1322 gtk_widget_set_sensitive(cd->button_stop, FALSE);
1323 gtk_widget_set_sensitive(cd->button_close, TRUE);
1327 static void cache_manager_sim_stop_cb(GenericDialog *, gpointer data)
1329 auto cd = static_cast<CacheOpsData *>(data);
1331 gq_gtk_entry_set_text(GTK_ENTRY(cd->progress), _("stopped"));
1332 cache_manager_sim_finish(cd);
1335 static void cache_manager_sim_folder(CacheOpsData *cd, FileData *dir_fd)
1337 GList *list_d = nullptr;
1338 GList *list_f = nullptr;
1342 filelist_read(dir_fd, &list_f, &list_d);
1346 filelist_read(dir_fd, &list_f, nullptr);
1349 list_f = filelist_filter(list_f, FALSE);
1350 list_d = filelist_filter(list_d, TRUE);
1352 cd->list = g_list_concat(list_f, cd->list);
1353 cd->list_dir = g_list_concat(list_d, cd->list_dir);
1356 static void cache_manager_sim_file_done_cb(CacheLoader *, gint, gpointer data)
1358 auto cd = static_cast<CacheOpsData *>(data);
1360 cache_loader_free(cd->cl);
1363 while (cache_manager_sim_file(cd));
1366 static void cache_manager_sim_start_sim_remote(CacheOpsData *cd, const gchar *user_path)
1370 path = remove_trailing_slash(user_path);
1371 parse_out_relatives(path);
1375 log_printf("The specified folder can not be found: %s\n", path);
1381 dir_fd = file_data_new_dir(path);
1382 cache_manager_sim_folder(cd, dir_fd);
1383 file_data_unref(dir_fd);
1384 while (cache_manager_sim_file(cd));
1391 * @brief Generate .sim files
1392 * @param path Path to image folder
1394 * @param func Function called when idle loop function terminates
1398 void cache_manager_sim_remote(const gchar *path, gboolean recurse, GDestroyNotify *func)
1402 cd = g_new0(CacheOpsData, 1);
1403 cd->recurse = recurse;
1405 cd->destroy_func = func;
1407 cache_manager_sim_start_sim_remote(cd, path);
1410 static gboolean cache_manager_sim_file(CacheOpsData *cd)
1412 CacheDataType load_mask;
1417 fd = static_cast<FileData *>(cd->list->data);
1418 cd->list = g_list_remove(cd->list, fd);
1420 load_mask = static_cast<CacheDataType>(CACHE_LOADER_DIMENSIONS | CACHE_LOADER_DATE | CACHE_LOADER_MD5SUM | CACHE_LOADER_SIMILARITY);
1421 cd->cl = cache_loader_new(fd, load_mask, (cache_manager_sim_file_done_cb), cd);
1425 gq_gtk_entry_set_text(GTK_ENTRY(cd->progress), fd->path);
1428 file_data_unref(fd);
1429 cd->count_done = cd->count_done + 1;
1432 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(cd->progress_bar), static_cast<gdouble>(cd->count_done) / cd->count_total);
1437 else if (cd->list_dir)
1441 fd = static_cast<FileData *>(cd->list_dir->data);
1442 cd->list_dir = g_list_remove(cd->list_dir, fd);
1444 cache_manager_sim_folder(cd, fd);
1445 file_data_unref(fd);
1452 gq_gtk_entry_set_text(GTK_ENTRY(cd->progress), _("done"));
1455 cache_manager_sim_finish(cd);
1457 if (cd->destroy_func)
1459 g_idle_add(reinterpret_cast<GSourceFunc>(cd->destroy_func), nullptr);
1465 static void cache_manager_sim_start_cb(GenericDialog *, gpointer data)
1467 auto cd = static_cast<CacheOpsData *>(data);
1469 GList *list_total = nullptr;
1473 if (cd->list || !gtk_widget_get_sensitive(cd->button_start)) return;
1476 path = remove_trailing_slash((gq_gtk_entry_get_text(GTK_ENTRY(cd->entry))));
1477 parse_out_relatives(path);
1483 warning_dialog(_("Invalid folder"),
1484 _("The specified folder can not be found."),
1485 GQ_ICON_DIALOG_WARNING, cd->gd->dialog);
1489 log_printf("The specified folder can not be found: %s\n", path);
1497 gtk_widget_set_sensitive(cd->group, FALSE);
1498 gtk_widget_set_sensitive(cd->button_start, FALSE);
1499 gtk_widget_set_sensitive(cd->button_stop, TRUE);
1500 gtk_widget_set_sensitive(cd->button_close, FALSE);
1502 gtk_spinner_start(GTK_SPINNER(cd->spinner));
1504 dir_fd = file_data_new_dir(path);
1505 cache_manager_sim_folder(cd, dir_fd);
1506 list_total = filelist_recursive(dir_fd);
1507 cd->count_total = g_list_length(list_total);
1508 file_data_unref(dir_fd);
1509 g_list_free(list_total);
1512 while (cache_manager_sim_file(static_cast<CacheOpsData *>(cd)));
1518 static void cache_manager_sim_load_dialog(GtkWidget *widget, const gchar *path)
1524 cd = g_new0(CacheOpsData, 1);
1528 cd->gd = generic_dialog_new(_("Create sim. files"), "create_sim_files", widget, FALSE, nullptr, cd);
1529 gtk_window_set_default_size(GTK_WINDOW(cd->gd->dialog), PURGE_DIALOG_WIDTH, -1);
1530 cd->gd->cancel_cb = cache_manager_sim_close_cb;
1531 cd->button_close = generic_dialog_add_button(cd->gd, GQ_ICON_CLOSE, _("Close"),
1532 cache_manager_sim_close_cb, FALSE);
1533 cd->button_start = generic_dialog_add_button(cd->gd, GQ_ICON_OK, _("S_tart"),
1534 cache_manager_sim_start_cb, FALSE);
1535 cd->button_stop = generic_dialog_add_button(cd->gd, GQ_ICON_STOP, _("Stop"),
1536 cache_manager_sim_stop_cb, FALSE);
1537 gtk_widget_set_sensitive(cd->button_stop, FALSE);
1539 generic_dialog_add_message(cd->gd, nullptr, _("Create sim. files recursively"), nullptr, FALSE);
1541 hbox = pref_box_new(cd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
1542 pref_spacer(hbox, PREF_PAD_INDENT);
1543 cd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1545 hbox = pref_box_new(cd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1546 pref_label_new(hbox, _("Folder:"));
1548 label = tab_completion_new(&cd->entry, path, nullptr, nullptr, nullptr, nullptr);
1549 tab_completion_add_select_button(cd->entry,_("Select folder") , TRUE);
1550 gq_gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
1551 gtk_widget_show(label);
1553 pref_line(cd->gd->vbox, PREF_PAD_SPACE);
1554 hbox = pref_box_new(cd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1556 cd->progress = gtk_entry_new();
1557 gtk_widget_set_can_focus(cd->progress, FALSE);
1558 gtk_editable_set_editable(GTK_EDITABLE(cd->progress), FALSE);
1559 gq_gtk_entry_set_text(GTK_ENTRY(cd->progress), _("click start to begin"));
1560 gq_gtk_box_pack_start(GTK_BOX(hbox), cd->progress, TRUE, TRUE, 0);
1561 gtk_widget_show(cd->progress);
1563 cd->progress_bar = gtk_progress_bar_new();
1564 gq_gtk_box_pack_start(GTK_BOX(cd->gd->vbox), cd->progress_bar, TRUE, TRUE, 0);
1565 gtk_widget_show(cd->progress_bar);
1567 cd->spinner = gtk_spinner_new();
1568 gq_gtk_box_pack_start(GTK_BOX(hbox), cd->spinner, FALSE, FALSE, 0);
1569 gtk_widget_show(cd->spinner);
1573 gtk_widget_show(cd->gd->dialog);
1576 static void cache_manager_sim_load_cb(GtkWidget *widget, gpointer)
1578 const gchar *path = layout_get_path(nullptr);
1580 if (!path || !*path) path = homedir();
1581 cache_manager_sim_load_dialog(widget, path);
1584 static void cache_manager_cache_maintenance_close_cb(GenericDialog *, gpointer data)
1586 auto cd = static_cast<CacheOpsData *>(data);
1588 if (!gtk_widget_get_sensitive(cd->button_close)) return;
1590 cache_manager_sim_reset(cd);
1591 generic_dialog_close(cd->gd);
1595 static void cache_manager_cache_maintenance_start_cb(GenericDialog *, gpointer data)
1597 auto cd = static_cast<CacheOpsData *>(data);
1603 if (cd->list || !gtk_widget_get_sensitive(cd->button_start)) return;
1606 path = remove_trailing_slash((gq_gtk_entry_get_text(GTK_ENTRY(cd->entry))));
1607 parse_out_relatives(path);
1613 warning_dialog(_("Invalid folder"),
1614 _("The specified folder can not be found."),
1615 GQ_ICON_DIALOG_WARNING, cd->gd->dialog);
1619 log_printf("The specified folder can not be found: \"%s\"\n", path);
1624 cmd_line = g_strdup_printf("%s --cache-maintenance \"%s\"", gq_executable_path, path);
1626 g_spawn_command_line_async(cmd_line, nullptr);
1629 generic_dialog_close(cd->gd);
1630 cache_manager_sim_reset(cd);
1637 static void cache_manager_cache_maintenance_load_dialog(GtkWidget *widget, const gchar *path)
1643 cd = g_new0(CacheOpsData, 1);
1647 cd->gd = generic_dialog_new(_("Background cache maintenance"), "background_cache_maintenance", widget, FALSE, nullptr, cd);
1648 gtk_window_set_default_size(GTK_WINDOW(cd->gd->dialog), PURGE_DIALOG_WIDTH, -1);
1649 cd->gd->cancel_cb = cache_manager_cache_maintenance_close_cb;
1650 cd->button_close = generic_dialog_add_button(cd->gd, GQ_ICON_CLOSE, _("Close"),
1651 cache_manager_cache_maintenance_close_cb, FALSE);
1652 cd->button_start = generic_dialog_add_button(cd->gd, GQ_ICON_OK, _("S_tart"),
1653 cache_manager_cache_maintenance_start_cb, FALSE);
1655 generic_dialog_add_message(cd->gd, nullptr, _("Recursively delete orphaned thumbnails\nand .sim files, and create new\nthumbnails and .sim files"), nullptr, FALSE);
1657 hbox = pref_box_new(cd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
1658 pref_spacer(hbox, PREF_PAD_INDENT);
1659 cd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1661 hbox = pref_box_new(cd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1662 pref_label_new(hbox, _("Folder:"));
1664 label = tab_completion_new(&cd->entry, path, nullptr, nullptr, nullptr, nullptr);
1665 tab_completion_add_select_button(cd->entry,_("Select folder") , TRUE);
1666 gq_gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
1667 gtk_widget_show(label);
1671 gtk_widget_show(cd->gd->dialog);
1674 static void cache_manager_cache_maintenance_load_cb(GtkWidget *widget, gpointer)
1676 const gchar *path = layout_get_path(nullptr);
1678 if (!path || !*path) path = homedir();
1679 cache_manager_cache_maintenance_load_dialog(widget, path);
1682 void cache_manager_show()
1688 GtkSizeGroup *sizegroup;
1693 gtk_window_present(GTK_WINDOW(cache_manager->dialog->dialog));
1697 cache_manager = g_new0(CacheManager, 1);
1699 cache_manager->dialog = generic_dialog_new(_("Cache Maintenance"),
1702 nullptr, cache_manager);
1703 gd = cache_manager->dialog;
1705 gd->cancel_cb = cache_manager_close_cb;
1706 generic_dialog_add_button(gd, GQ_ICON_CLOSE, _("Close"),
1707 cache_manager_close_cb, FALSE);
1708 generic_dialog_add_button(gd, GQ_ICON_HELP, _("Help"),
1709 cache_manager_help_cb, FALSE);
1711 generic_dialog_add_message(gd, nullptr, _("Cache and Data Maintenance"), nullptr, FALSE);
1713 sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
1715 group = pref_group_new(gd->vbox, FALSE, _("Geeqie thumbnail and sim. cache"), GTK_ORIENTATION_VERTICAL);
1717 cache_manager_location_label(group, get_thumbnails_cache_dir());
1719 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1721 button = pref_table_button(table, 0, 0, GQ_ICON_CLEAR, _("Clean up"),
1722 G_CALLBACK(cache_manager_main_clean_cb), cache_manager);
1723 gtk_size_group_add_widget(sizegroup, button);
1724 pref_table_label(table, 1, 0, _("Remove orphaned or outdated thumbnails and sim. files."), GTK_ALIGN_START);
1726 button = pref_table_button(table, 0, 1, GQ_ICON_DELETE, _("Clear cache"),
1727 G_CALLBACK(cache_manager_main_clear_cb), cache_manager);
1728 gtk_size_group_add_widget(sizegroup, button);
1729 pref_table_label(table, 1, 1, _("Delete all cached data."), GTK_ALIGN_START);
1732 group = pref_group_new(gd->vbox, FALSE, _("Shared thumbnail cache"), GTK_ORIENTATION_VERTICAL);
1734 path = g_build_filename(get_thumbnails_standard_cache_dir(), NULL);
1735 cache_manager_location_label(group, path);
1738 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1740 button = pref_table_button(table, 0, 0, GQ_ICON_CLEAR, _("Clean up"),
1741 G_CALLBACK(cache_manager_standard_clean_cb), cache_manager);
1742 gtk_size_group_add_widget(sizegroup, button);
1743 pref_table_label(table, 1, 0, _("Remove orphaned or outdated thumbnails."), GTK_ALIGN_START);
1745 button = pref_table_button(table, 0, 1, GQ_ICON_DELETE, _("Clear cache"),
1746 G_CALLBACK(cache_manager_standard_clear_cb), cache_manager);
1747 gtk_size_group_add_widget(sizegroup, button);
1748 pref_table_label(table, 1, 1, _("Delete all cached thumbnails."), GTK_ALIGN_START);
1750 group = pref_group_new(gd->vbox, FALSE, _("Create thumbnails"), GTK_ORIENTATION_VERTICAL);
1752 table = pref_table_new(group, 2, 1, FALSE, FALSE);
1754 button = pref_table_button(table, 0, 1, GQ_ICON_RUN, _("Render"),
1755 G_CALLBACK(cache_manager_render_cb), cache_manager);
1756 gtk_size_group_add_widget(sizegroup, button);
1757 pref_table_label(table, 1, 1, _("Render thumbnails for a specific folder."), GTK_ALIGN_START);
1758 gtk_widget_set_sensitive(group, options->thumbnails.enable_caching);
1760 group = pref_group_new(gd->vbox, FALSE, _("File similarity cache"), GTK_ORIENTATION_VERTICAL);
1762 table = pref_table_new(group, 3, 2, FALSE, FALSE);
1764 button = pref_table_button(table, 0, 0, GQ_ICON_RUN, _("Create"),
1765 G_CALLBACK(cache_manager_sim_load_cb), cache_manager);
1766 gtk_size_group_add_widget(sizegroup, button);
1767 pref_table_label(table, 1, 0, _("Create sim. files recursively."), GTK_ALIGN_START);
1768 gtk_widget_set_sensitive(group, options->thumbnails.enable_caching);
1770 group = pref_group_new(gd->vbox, FALSE, _("Metadata"), GTK_ORIENTATION_VERTICAL);
1772 cache_manager_location_label(group, get_metadata_cache_dir());
1774 table = pref_table_new(group, 2, 1, FALSE, FALSE);
1776 button = pref_table_button(table, 0, 0, GQ_ICON_CLEAR, _("Clean up"),
1777 G_CALLBACK(cache_manager_metadata_clean_cb), cache_manager);
1778 gtk_size_group_add_widget(sizegroup, button);
1779 pref_table_label(table, 1, 0, _("Remove orphaned keywords and comments."), GTK_ALIGN_START);
1781 group = pref_group_new(gd->vbox, FALSE, _("Background cache maintenance"), GTK_ORIENTATION_VERTICAL);
1783 table = pref_table_new(group, 3, 2, FALSE, FALSE);
1785 button = pref_table_button(table, 0, 0, GQ_ICON_RUN, _("Select"),
1786 G_CALLBACK(cache_manager_cache_maintenance_load_cb), cache_manager);
1787 gtk_size_group_add_widget(sizegroup, button);
1788 pref_table_label(table, 1, 0, _("Run cache maintenance as a background job."), GTK_ALIGN_START);
1789 gtk_widget_set_sensitive(group, options->thumbnails.enable_caching);
1791 gtk_widget_show(cache_manager->dialog->dialog);
1793 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */