From: Colin Clark Date: Fri, 20 Aug 2021 14:33:20 +0000 (+0100) Subject: Fix #652: Automated cache maintenance X-Git-Tag: v1.7~73 X-Git-Url: http://geeqie.org/cgi-bin/gitweb.cgi?p=geeqie.git;a=commitdiff_plain;h=e634c67bdfbcb95ec91379f02ef45760c311a655 Fix #652: Automated cache maintenance https://github.com/BestImageViewer/geeqie/issues/652 If geeqie is called with --cache-maintenance , the GUI is not loaded and the program behaves as a command line program. It runs recursively to clean thumbnail data, and create thumbnails and .sim files. --- diff --git a/CODING.md b/CODING.md index 2e57b8c8..7a517e91 100644 --- a/CODING.md +++ b/CODING.md @@ -1,4 +1,4 @@ -[Log Window](#log-window) +[Error Logging](#error-logging) [GPL header](#gpl-header) [Git change log](#git-change-log) [Sources](#sources) @@ -7,8 +7,8 @@ ----------- -# -# Log Window +# +# Error Logging `DEBUG_0()` Use `DEBUG_0()` only for temporary debugging i.e. not in code in the repository. @@ -18,6 +18,12 @@ The user will then not see irrelevant debug output when the default `log_printf()` If the first word of the message is "error" or "warning" (case insensitive) the message will be color-coded appropriately. + - Note that these messages are output in the idle loop. + +`print_term(gboolean err, const gchar *text_utf8)` + +- If `err` is TRUE output is to STDERR, otherwise to STDOUT + `DEBUG_NAME(widget)` For use with the [GTKInspector](https://wiki.gnome.org/action/show/Projects/GTK/Inspector?action=show&redirect=Projects%2FGTK%2B%2FInspector) to provide a visual indication of where objects are declared. diff --git a/README.md b/README.md index 9f78709e..779893f0 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,8 @@ Animated GIFs are supported. * Maps from [OpenStreetMap](http://www.openstreetmap.org) may be displayed in a side panel. If an image has GPS coordinates embedded, its position will be displayed on the map - if Image Direction is encoded, that will be displayed also. If an image does not have embedded GPS coordinates, it may be dragged-and-dropped onto the map to encode its position. +* Speed of operation can be increased by caching thumbnails and similarity data of images. When Geeqie is run as a stand-alone command line program (`geeqie --cache-maintenance `) these data will be recursively created from the defined start point. This program can be called from `cron` or `anacron` so that cache updating is automatically done at specified intervals. + # ## Downloading @@ -139,7 +141,7 @@ List compile options: `./autogen.sh --help` Common options: `./autogen.sh --disable-gtk3`, -Compilation: `./autogen.sh [options]; make -j ` +Compilation: `./autogen.sh [options]; make -j` Install: `[sudo] make install` diff --git a/doc/docbook/GuideOtherSoftware.xml b/doc/docbook/GuideOtherSoftware.xml index 52765ddb..90647eeb 100644 --- a/doc/docbook/GuideOtherSoftware.xml +++ b/doc/docbook/GuideOtherSoftware.xml @@ -1,7 +1,8 @@ - Other Software + Useful Software This is a list of other software that users might find useful in conjunction with Geeqie. +
Entangle @@ -16,4 +17,35 @@ https://photini.readthedocs.io/en/latest/
+
+ Geeqie Cache Maintenance + + Command line program to automatically create or update thumbnails and similarity data: geeqie-cache-maintenance + +
+
+ Keyword Merge + + This program will merge the keyword tree of one Geeqie configuration file into another. The keyword trees are simply concatenated. When Geeqie loads the resulting configuration file, any duplicates are discarded: keyword_merge.sh + +
+
+ Install Geeqie from sources on Debian + + This script will clone the Geeqie repository, fulfill all dependecies, and install Geeqie on a Debian based system: geeqie-install-debian.sh + +
+
+ Generic install script + + This script will install Geeqie to a defined location, and will run under any system. However, it is left to you to make sure dependencies are fulfilled: build-geeqie + +
+
+ Decoder for .sim files + + This program is unlikely to be of interest to most users. It shows a summary of the contents of a .sim file. (Requires perl to be installed): decode_sim + +
+
diff --git a/doc/docbook/GuideReferenceCommandLine.xml b/doc/docbook/GuideReferenceCommandLine.xml index 4a72a0ad..2f9ebbb6 100644 --- a/doc/docbook/GuideReferenceCommandLine.xml +++ b/doc/docbook/GuideReferenceCommandLine.xml @@ -110,6 +110,17 @@ --disable-clutter Disable use of Clutter library (i.e. GPU accel.). If the Clutter library is compiled into Geeqie but Clutter fails to initialize, it is necessary to start Geeqie with this option. + + + --cache-maintenance <path> + + Run cache maintenance + + Cache Maintenance. + + in non-GUI mode. + + diff --git a/doc/docbook/GuideReferenceManagement.xml b/doc/docbook/GuideReferenceManagement.xml index 073c3f9a..0ca7d2fc 100644 --- a/doc/docbook/GuideReferenceManagement.xml +++ b/doc/docbook/GuideReferenceManagement.xml @@ -162,4 +162,12 @@ +
+ Command line program + + Geeqie can be run as a command line program: geeqie --cache-maintenance <path>. It will recursively remove orphaned thumbnails, and create thumbnails and similarity data for all images found. + + It may also be called from cron or anacron thus enabling automatic updating of the cached data for all your images. + +
diff --git a/geeqie.1 b/geeqie.1 index 828239e5..430b266f 100644 --- a/geeqie.1 +++ b/geeqie.1 @@ -89,6 +89,10 @@ Print command line options. .B .IP \-\-disable-clutter Disable use of Clutter library (i.e. GPU accel.). +.br +.B +.IP \-\-cache-maintenance\ +Run cache maintenance in non-GUI mode. .SH REMOTE OPTIONS .B diff --git a/src/cache_maint.c b/src/cache_maint.c index d76ee8cd..04b8bd56 100644 --- a/src/cache_maint.c +++ b/src/cache_maint.c @@ -26,6 +26,7 @@ #include "cache-loader.h" #include "filedata.h" #include "layout.h" +#include "pixbuf_util.h" #include "thumb.h" #include "thumb_standard.h" #include "ui_fileops.h" @@ -54,6 +55,65 @@ struct _CMData #define PURGE_DIALOG_WIDTH 400 +/* + *----------------------------------------------------------------------------- + * Command line cache maintenance program functions *----------------------------------------------------------------------------- + */ +static gchar *cache_maintenance_path = NULL; +static GtkStatusIcon *status_icon; + +static void cache_maintenance_sim_stop_cb(gpointer data) +{ + exit(EXIT_SUCCESS); +} + +static void cache_maintenance_render_stop_cb(gpointer data) +{ + gtk_status_icon_set_tooltip_text(status_icon, _("Geeqie: Creating sim data...")); + cache_manager_sim_remote(cache_maintenance_path, TRUE, (GDestroyNotify *)cache_maintenance_sim_stop_cb); +} + +static void cache_maintenance_clean_stop_cb(gpointer data) +{ + gtk_status_icon_set_tooltip_text(status_icon, _("Geeqie: Creating thumbs...")); + cache_manager_render_remote(cache_maintenance_path, TRUE, options->thumbnails.cache_into_dirs, (GDestroyNotify *)cache_maintenance_render_stop_cb); +} + +static void cache_maintenance_user_cancel_cb() +{ + exit(EXIT_FAILURE); +} + +static void cache_maintenance_status_icon_activate_cb(GtkStatusIcon *status, gpointer data) +{ + GtkWidget *menu; + GtkWidget *item; + + menu = gtk_menu_new(); + + item = gtk_menu_item_new_with_label("Exit Geeqie Cache Maintenance"); + + g_signal_connect(G_OBJECT(item), "activate", cache_maintenance_user_cancel_cb, item); + gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + gtk_widget_show(item); + + /* take ownership of menu */ + g_object_ref_sink(G_OBJECT(menu)); + + gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time()); +} + +void cache_maintenance(const gchar *path) +{ + cache_maintenance_path = g_strdup(path); + + status_icon = gtk_status_icon_new_from_pixbuf(pixbuf_inline(PIXBUF_INLINE_ICON)); + gtk_status_icon_set_tooltip_text(status_icon, _("Geeqie: Cleaning thumbs...")); + gtk_status_icon_set_visible(status_icon, TRUE); + g_signal_connect(G_OBJECT(status_icon), "activate", G_CALLBACK(cache_maintenance_status_icon_activate_cb), NULL); + + cache_maintain_home_remote(FALSE, FALSE, (GDestroyNotify *)cache_maintenance_clean_stop_cb); +} /* *------------------------------------------------------------------- @@ -355,7 +415,15 @@ void cache_maintain_home(gboolean metadata, gboolean clear, GtkWidget *parent) cm->idle_id = g_idle_add(cache_maintain_home_cb, cm); } -void cache_maintain_home_remote(gboolean metadata, gboolean clear) +/** + * @brief Clears or culls cached data + * @param metadata TRUE - work on metadata cache, FALSE - work on thumbnail cache + * @param clear TRUE - clear cache, FALSE - delete orphaned cached items + * @param func Function called when idle loop function terminates + * + * + */ +void cache_maintain_home_remote(gboolean metadata, gboolean clear, GDestroyNotify *func) { CMData *cm; GList *dlist; @@ -387,7 +455,7 @@ void cache_maintain_home_remote(gboolean metadata, gboolean clear) cm->metadata = metadata; cm->remote = TRUE; - cm->idle_id = g_idle_add(cache_maintain_home_cb, cm); + cm->idle_id = g_idle_add_full(G_PRIORITY_LOW, cache_maintain_home_cb, cm, (GDestroyNotify)func); } static void cache_file_move(const gchar *src, const gchar *dest) @@ -556,6 +624,7 @@ struct _CacheOpsData GenericDialog *gd; ThumbLoaderStd *tl; CacheLoader *cl; + GDestroyNotify *destroy_func; /* Used by the command line prog. functions */ GList *list; GList *list_dir; @@ -713,9 +782,17 @@ static gboolean cache_manager_render_file(CacheOpsData *cd) return TRUE; } - gtk_entry_set_text(GTK_ENTRY(cd->progress), _("done")); + if (!cd->remote) + { + gtk_entry_set_text(GTK_ENTRY(cd->progress), _("done")); + } cache_manager_render_finish(cd); + if (cd->destroy_func) + { + g_idle_add((GSourceFunc)cd->destroy_func, NULL); + } + return FALSE; } @@ -861,7 +938,16 @@ static void cache_manager_render_dialog(GtkWidget *widget, const gchar *path) gtk_widget_show(cd->gd->dialog); } -void cache_manager_render_remote(const gchar *path, gboolean recurse, gboolean local) +/** + * @brief Create thumbnails + * @param path Path to image folder + * @param recurse + * @param local Create thumbnails in same folder as images + * @param func Function called when idle loop function terminates + * + * + */ +void cache_manager_render_remote(const gchar *path, gboolean recurse, gboolean local, GDestroyNotify *func) { CacheOpsData *cd; @@ -869,6 +955,7 @@ void cache_manager_render_remote(const gchar *path, gboolean recurse, gboolean l cd->recurse = recurse; cd->local = local; cd->remote = TRUE; + cd->destroy_func = func; cache_manager_render_start_render_remote(cd, path); } @@ -1285,6 +1372,50 @@ static void cache_manager_sim_file_done_cb(CacheLoader *cl, gint error, gpointer while (cache_manager_sim_file(cd)); } +static void cache_manager_sim_start_sim_remote(CacheOpsData *cd, const gchar *user_path) +{ + gchar *path; + + path = remove_trailing_slash(user_path); + parse_out_relatives(path); + + if (!isdir(path)) + { + log_printf("The specified folder can not be found: %s\n", path); + } + else + { + FileData *dir_fd; + + dir_fd = file_data_new_dir(path); + cache_manager_sim_folder(cd, dir_fd); + file_data_unref(dir_fd); + while (cache_manager_sim_file(cd)); + } + + g_free(path); +} + +/** + * @brief Generate .sim files + * @param path Path to image folder + * @param recurse + * @param func Function called when idle loop function terminates + * + * + */ +void cache_manager_sim_remote(const gchar *path, gboolean recurse, GDestroyNotify *func) +{ + CacheOpsData *cd; + + cd = g_new0(CacheOpsData, 1); + cd->recurse = recurse; + cd->remote = TRUE; + cd->destroy_func = func; + + cache_manager_sim_start_sim_remote(cd, path); +} + static gboolean cache_manager_sim_file(CacheOpsData *cd) { CacheDataType load_mask; @@ -1298,11 +1429,17 @@ static gboolean cache_manager_sim_file(CacheOpsData *cd) load_mask = CACHE_LOADER_DIMENSIONS | CACHE_LOADER_DATE | CACHE_LOADER_MD5SUM | CACHE_LOADER_SIMILARITY; cd->cl = (CacheLoader *)cache_loader_new(fd, load_mask, (cache_manager_sim_file_done_cb), cd); - gtk_entry_set_text(GTK_ENTRY(cd->progress), fd->path); + if (!cd->remote) + { + gtk_entry_set_text(GTK_ENTRY(cd->progress), fd->path); + } file_data_unref(fd); cd->count_done = cd->count_done + 1; - gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(cd->progress_bar), (gdouble)cd->count_done / cd->count_total); + if (!cd->remote) + { + gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(cd->progress_bar), (gdouble)cd->count_done / cd->count_total); + } return FALSE; } @@ -1319,9 +1456,18 @@ static gboolean cache_manager_sim_file(CacheOpsData *cd) return TRUE; } - gtk_entry_set_text(GTK_ENTRY(cd->progress), _("done")); + if (!cd->remote) + { + gtk_entry_set_text(GTK_ENTRY(cd->progress), _("done")); + } + cache_manager_sim_finish((CacheOpsData *)cd); + if (cd->destroy_func) + { + g_idle_add((GSourceFunc)cd->destroy_func, NULL); + } + return FALSE; } diff --git a/src/cache_maint.h b/src/cache_maint.h index d839496b..816d39ba 100644 --- a/src/cache_maint.h +++ b/src/cache_maint.h @@ -27,8 +27,10 @@ void cache_maintain_home(gboolean metadata, gboolean clear, GtkWidget *parent); void cache_notify_cb(FileData *fd, NotifyType type, gpointer data); void cache_manager_show(void); -void cache_maintain_home_remote(gboolean metadata, gboolean clear); +void cache_maintain_home_remote(gboolean metadata, gboolean clear, GDestroyNotify *func); void cache_manager_standard_process_remote(gboolean clear); -void cache_manager_render_remote(const gchar *path, gboolean recurse, gboolean local); +void cache_manager_render_remote(const gchar *path, gboolean recurse, gboolean local, GDestroyNotify *func); +void cache_manager_sim_remote(const gchar *path, gboolean recurse, GDestroyNotify *func); +void cache_maintenance(const gchar *path); #endif /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff --git a/src/main.c b/src/main.c index 57e17f68..6b19d98e 100644 --- a/src/main.c +++ b/src/main.c @@ -605,7 +605,8 @@ static void parse_command_line(gint argc, gchar *argv[]) print_term(FALSE, _(" -o:, --log-file: save log data to file\n")); print_term(FALSE, _(" -v, --version print version info\n")); print_term(FALSE, _(" -h, --help show this message\n")); - print_term(FALSE, _(" --disable-clutter disable use of Clutter library (i.e. GPU accel.)\n\n")); + print_term(FALSE, _(" --disable-clutter disable use of Clutter library (i.e. GPU accel.)\n")); + print_term(FALSE, _(" --cache-maintenance run cache maintenance in non-GUI mode\n\n")); #if 0 /* these options are not officially supported! @@ -799,6 +800,95 @@ static gboolean parse_command_line_for_clutter_option(gint argc, gchar *argv[]) } #endif +static gboolean parse_command_line_for_cache_maintenance_option(gint argc, gchar *argv[]) +{ + const gchar *cache_maintenance_option = "--cache-maintenance"; + gint len = strlen(cache_maintenance_option); + gboolean ret = FALSE; + + if (argc >= 2) + { + const gchar *cmd_line = argv[1]; + if (strncmp(cmd_line, cache_maintenance_option, len) == 0) + { + ret = TRUE; + } + } + + return ret; +} + +static void process_command_line_for_cache_maintenance_option(gint argc, gchar *argv[]) +{ + gchar *rc_path; + gchar *folder_path = NULL; + gsize size; + gsize i = 0; + gchar *buf_config_file; + gint diff_count; + + if (argc >= 3) + { + folder_path = expand_tilde(argv[2]); + + if (isdir(folder_path)) + { + rc_path = g_build_filename(get_rc_dir(), RC_FILE_NAME, NULL); + + if (isfile(rc_path)) + { + if (g_file_get_contents(rc_path, &buf_config_file, &size, NULL)) + { + while (i < size) + { + diff_count = strncmp("", &buf_config_file[i], 9); + if (diff_count == 0) + { + break; + } + i++; + } + /* Load only the section */ + load_config_from_buf(buf_config_file, i + 9, FALSE); + + if (options->thumbnails.enable_caching) + { + cache_maintenance(folder_path); + } + else + { + print_term(TRUE, "Caching not enabled\n"); + exit(EXIT_FAILURE); + } + g_free(buf_config_file); + } + else + { + print_term(TRUE, g_strconcat(_("Cannot load "), rc_path, "\n", NULL)); + exit(EXIT_FAILURE); + } + } + else + { + print_term(TRUE, g_strconcat(_("Configuration file path "), rc_path, _(" is not a file\n"), NULL)); + exit(EXIT_FAILURE); + } + g_free(rc_path); + } + else + { + print_term(TRUE, g_strconcat(argv[2], _(" is not a folder\n"), NULL)); + exit(EXIT_FAILURE); + } + g_free(folder_path); + } + else + { + print_term(TRUE, _("No path parameter given\n")); + exit(EXIT_FAILURE); + } +} + /* *----------------------------------------------------------------------------- * startup, init, and exit @@ -1257,9 +1347,6 @@ gint main(gint argc, gchar *argv[]) options->disable_gpu = TRUE; } - DEBUG_1("%s main: parse_command_line", get_exec_time()); - parse_command_line(argc, argv); - DEBUG_1("%s main: mkdir_if_not_exists", get_exec_time()); /* these functions don't depend on config file */ mkdir_if_not_exists(get_rc_dir()); @@ -1270,185 +1357,195 @@ gint main(gint argc, gchar *argv[]) setup_env_path(); - keys_load(); - accel_map_load(); + if (parse_command_line_for_cache_maintenance_option(argc, argv)) + { + process_command_line_for_cache_maintenance_option(argc, argv); + } + else + { + DEBUG_1("%s main: parse_command_line", get_exec_time()); + parse_command_line(argc, argv); - /* restore session from the config file */ + keys_load(); + accel_map_load(); + /* restore session from the config file */ - DEBUG_1("%s main: load_options", get_exec_time()); - if (!load_options(options)) - { - /* load_options calls these functions after it parses global options, we have to call it here if it fails */ - filter_add_defaults(); - filter_rebuild(); - } -#ifdef HAVE_CLUTTER -/** @FIXME For the background of this see: - * https://github.com/BestImageViewer/geeqie/issues/397 - * The feature CLUTTER_FEATURE_SWAP_EVENTS indictates if the - * system is liable to exhibit this problem. - * The user is provided with an override in Preferences/Behavior - */ - if (!options->override_disable_gpu && !options->disable_gpu) - { - DEBUG_1("CLUTTER_FEATURE_SWAP_EVENTS %d",clutter_feature_available(CLUTTER_FEATURE_SWAP_EVENTS)); - if (clutter_feature_available(CLUTTER_FEATURE_SWAP_EVENTS) != 0) + DEBUG_1("%s main: load_options", get_exec_time()); + if (!load_options(options)) { - options->disable_gpu = TRUE; + /* load_options calls these functions after it parses global options, we have to call it here if it fails */ + filter_add_defaults(); + filter_rebuild(); } - } -#endif - - /* handle missing config file and commandline additions*/ - if (!layout_window_list) - { - /* broken or no config file or no section */ - layout_new_from_default(); - } - - layout_editors_reload_start(); - /* If no --list option, open a separate collection window for each - * .gqv file on the command line + #ifdef HAVE_CLUTTER + /** @FIXME For the background of this see: + * https://github.com/BestImageViewer/geeqie/issues/397 + * The feature CLUTTER_FEATURE_SWAP_EVENTS indictates if the + * system is liable to exhibit this problem. + * The user is provided with an override in Preferences/Behavior */ - if (command_line->collection_list && !command_line->startup_command_line_collection) - { - GList *work; + if (!options->override_disable_gpu && !options->disable_gpu) + { + DEBUG_1("CLUTTER_FEATURE_SWAP_EVENTS %d",clutter_feature_available(CLUTTER_FEATURE_SWAP_EVENTS)); + if (clutter_feature_available(CLUTTER_FEATURE_SWAP_EVENTS) != 0) + { + options->disable_gpu = TRUE; + } + } + #endif - work = command_line->collection_list; - while (work) + /* handle missing config file and commandline additions*/ + if (!layout_window_list) { - CollectWindow *cw; - const gchar *path; + /* broken or no config file or no section */ + layout_new_from_default(); + } - path = work->data; - work = work->next; + layout_editors_reload_start(); - cw = collection_window_new(path); - if (!first_collection && cw) first_collection = cw->cd; - } - } + /* If no --list option, open a separate collection window for each + * .gqv file on the command line + */ + if (command_line->collection_list && !command_line->startup_command_line_collection) + { + GList *work; - if (command_line->log_file) - { - gchar *pathl; - gchar *path = g_strdup(command_line->log_file); + work = command_line->collection_list; + while (work) + { + CollectWindow *cw; + const gchar *path; - pathl = path_from_utf8(path); - command_line->ssi = secure_open(pathl); - } + path = work->data; + work = work->next; - /* If there is a files list on the command line and no --list option, - * check if they are all in the same folder - */ - if (command_line->cmd_list && !(command_line->startup_command_line_collection)) - { - GList *work; - gchar *path = NULL; + cw = collection_window_new(path); + if (!first_collection && cw) first_collection = cw->cd; + } + } - work = command_line->cmd_list; + if (command_line->log_file) + { + gchar *pathl; + gchar *path = g_strdup(command_line->log_file); - while (work && single_dir) + pathl = path_from_utf8(path); + command_line->ssi = secure_open(pathl); + } + + /* If there is a files list on the command line and no --list option, + * check if they are all in the same folder + */ + if (command_line->cmd_list && !(command_line->startup_command_line_collection)) { - gchar *dirname; + GList *work; + gchar *path = NULL; - dirname = g_path_get_dirname(work->data); - if (!path) - { - path = g_strdup(dirname); - } - else + work = command_line->cmd_list; + + while (work && single_dir) { - if (g_strcmp0(path, dirname) != 0) + gchar *dirname; + + dirname = g_path_get_dirname(work->data); + if (!path) { - single_dir = FALSE; + path = g_strdup(dirname); } + else + { + if (g_strcmp0(path, dirname) != 0) + { + single_dir = FALSE; + } + } + g_free(dirname); + work = work->next; } - g_free(dirname); - work = work->next; + g_free(path); } - g_free(path); - } - - /* Files from multiple folders, or --list option given - * then open an unnamed collection and insert all files - */ - if ((command_line->cmd_list && !single_dir) || (command_line->startup_command_line_collection && command_line->cmd_list)) - { - GList *work; - CollectWindow *cw; - cw = collection_window_new(NULL); - cd = cw->cd; + /* Files from multiple folders, or --list option given + * then open an unnamed collection and insert all files + */ + if ((command_line->cmd_list && !single_dir) || (command_line->startup_command_line_collection && command_line->cmd_list)) + { + GList *work; + CollectWindow *cw; - collection_path_changed(cd); + cw = collection_window_new(NULL); + cd = cw->cd; - work = command_line->cmd_list; - while (work) - { - FileData *fd; + collection_path_changed(cd); - fd = file_data_new_simple(work->data); - collection_add(cd, fd, FALSE); - file_data_unref(fd); - work = work->next; - } + work = command_line->cmd_list; + while (work) + { + FileData *fd; - work = command_line->collection_list; - while (work) - { - collection_load(cd, (gchar *)work->data, COLLECTION_LOAD_APPEND); - work = work->next; - } + fd = file_data_new_simple(work->data); + collection_add(cd, fd, FALSE); + file_data_unref(fd); + work = work->next; + } - if (cd->list) layout_image_set_collection(NULL, cd, cd->list->data); + work = command_line->collection_list; + while (work) + { + collection_load(cd, (gchar *)work->data, COLLECTION_LOAD_APPEND); + work = work->next; + } - /* mem leak, we never unref this collection when !startup_command_line_collection - * (the image view of the main window does not hold a ref to the collection) - * this is sort of unavoidable, for if it did hold a ref, next/back - * may not work as expected when closing collection windows. - * - * collection_unref(cd); - */ + if (cd->list) layout_image_set_collection(NULL, cd, cd->list->data); - } - else if (first_collection) - { - layout_image_set_collection(NULL, first_collection, - collection_get_first(first_collection)); - } + /* mem leak, we never unref this collection when !startup_command_line_collection + * (the image view of the main window does not hold a ref to the collection) + * this is sort of unavoidable, for if it did hold a ref, next/back + * may not work as expected when closing collection windows. + * + * collection_unref(cd); + */ - /* If the files on the command line are from one folder, select those files - * unless it is a command line collection - then leave focus on collection window - */ - lw = NULL; - layout_valid(&lw); + } + else if (first_collection) + { + layout_image_set_collection(NULL, first_collection, + collection_get_first(first_collection)); + } - if (single_dir && command_line->cmd_list && !command_line->startup_command_line_collection) - { - GList *work; - GList *selected; - FileData *fd; + /* If the files on the command line are from one folder, select those files + * unless it is a command line collection - then leave focus on collection window + */ + lw = NULL; + layout_valid(&lw); - selected = NULL; - work = command_line->cmd_list; - while (work) + if (single_dir && command_line->cmd_list && !command_line->startup_command_line_collection) { - fd = file_data_new_simple((gchar *)work->data); - selected = g_list_append(selected, fd); - file_data_unref(fd); - work = work->next; + GList *work; + GList *selected; + FileData *fd; + + selected = NULL; + work = command_line->cmd_list; + while (work) + { + fd = file_data_new_simple((gchar *)work->data); + selected = g_list_append(selected, fd); + file_data_unref(fd); + work = work->next; + } + layout_select_list(lw, selected); } - layout_select_list(lw, selected); - } - buf = g_build_filename(get_rc_dir(), ".command", NULL); - remote_connection = remote_server_init(buf, cd); - g_free(buf); + buf = g_build_filename(get_rc_dir(), ".command", NULL); + remote_connection = remote_server_init(buf, cd); + g_free(buf); - marks_load(); + marks_load(); + } DEBUG_1("%s main: gtk_main", get_exec_time()); gtk_main(); diff --git a/src/remote.c b/src/remote.c index 90030ac5..a6b66fab 100644 --- a/src/remote.c +++ b/src/remote.c @@ -541,9 +541,13 @@ static void gr_slideshow_start_rec(const gchar *text, GIOChannel *channel, gpoin static void gr_cache_thumb(const gchar *text, GIOChannel *channel, gpointer data) { if (!g_strcmp0(text, "clear")) - cache_maintain_home_remote(FALSE, TRUE); + { + cache_maintain_home_remote(FALSE, TRUE, NULL); + } else if (!g_strcmp0(text, "clean")) - cache_maintain_home_remote(FALSE, FALSE); + { + cache_maintain_home_remote(FALSE, FALSE, NULL); + } } static void gr_cache_shared(const gchar *text, GIOChannel *channel, gpointer data) @@ -556,29 +560,33 @@ static void gr_cache_shared(const gchar *text, GIOChannel *channel, gpointer dat static void gr_cache_metadata(const gchar *text, GIOChannel *channel, gpointer data) { - cache_maintain_home_remote(TRUE, FALSE); + cache_maintain_home_remote(TRUE, FALSE, NULL); } static void gr_cache_render(const gchar *text, GIOChannel *channel, gpointer data) { - cache_manager_render_remote(text, FALSE, FALSE); + cache_manager_render_remote(text, FALSE, FALSE, NULL); } static void gr_cache_render_recurse(const gchar *text, GIOChannel *channel, gpointer data) { - cache_manager_render_remote(text, TRUE, FALSE); + cache_manager_render_remote(text, TRUE, FALSE, NULL); } static void gr_cache_render_standard(const gchar *text, GIOChannel *channel, gpointer data) { if(options->thumbnails.spec_standard) - cache_manager_render_remote(text, FALSE, TRUE); + { + cache_manager_render_remote(text, FALSE, TRUE, NULL); + } } static void gr_cache_render_standard_recurse(const gchar *text, GIOChannel *channel, gpointer data) { if(options->thumbnails.spec_standard) - cache_manager_render_remote(text, TRUE, TRUE); + { + cache_manager_render_remote(text, TRUE, TRUE, NULL); + } } static void gr_slideshow_toggle(const gchar *text, GIOChannel *channel, gpointer data)