# HG changeset patch # User Colin Clark # Date 1503062736 -3600 # Node ID 03014a1eb7e755b3a4886955110d34f8d29bdf5b # Parent e6847b39721f3fbb97135111e07d713cbdab36ee Right-click menus - collections On all relevent right-click menus include a sub-menu to store an image selection to either a new or existing collection. On Collection window right-click menu, remove "Append from file list" - that can be achieved with "Append from file selection" diff -r e6847b39721f -r 03014a1eb7e7 src/collect-io.c --- a/src/collect-io.c Wed Aug 16 09:42:42 2017 +0100 +++ b/src/collect-io.c Fri Aug 18 14:25:36 2017 +0100 @@ -969,6 +969,75 @@ case FILEDATA_CHANGE_WRITE_METADATA: break; } +} +static gint collection_manager_sort_cb(gconstpointer a, gconstpointer b) +{ + const gchar *char_a = a; + const gchar *char_b = b; + + return g_strcmp0(char_a, char_b); +} + +/* Creates sorted list of collections + * Inputs: none + * Outputs: list of type gchar + * sorted list of collections names excluding extension + * sorted list of collections names including extension + * sorted list of collection paths + * Return: none + * Used lists must be freed with string_list_free() + */ +void collect_manager_list(GList **names_exc, GList **names_inc, GList **paths) +{ + FileData *dir_fd; + GList *list = NULL; + gchar *name; + FileData *fd; + gchar *filename; + + if (names_exc == NULL && names_inc == NULL && paths == NULL) + { + return; + } + + dir_fd = file_data_new_dir((get_collections_dir())); + + filelist_read(dir_fd, &list, NULL); + + while (list) + { + fd = list->data; + filename = g_strdup(filename_from_path((gchar *)fd->path)); + + if (file_extension_match(filename, GQ_COLLECTION_EXT)) + { + name = remove_extension_from_path(filename); + + if (names_exc != NULL) + { + *names_exc = g_list_insert_sorted(*names_exc, g_strdup(name), + collection_manager_sort_cb); + *names_exc = g_list_first(*names_exc); + } + if (names_inc != NULL) + { + *names_inc = g_list_insert_sorted(*names_inc,filename, + collection_manager_sort_cb); + *names_inc = g_list_first(*names_inc); + } + if (paths != NULL) + { + *paths = g_list_insert_sorted(*paths,fd->path, + collection_manager_sort_cb); + *paths = g_list_first(*paths); + } + g_free(name); + } + list = list->next; + g_free(filename); + } + + filelist_free(list); } /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff -r e6847b39721f -r 03014a1eb7e7 src/collect-io.h --- a/src/collect-io.h Wed Aug 16 09:42:42 2017 +0100 +++ b/src/collect-io.h Fri Aug 18 14:25:36 2017 +0100 @@ -57,7 +57,7 @@ void collect_manager_flush(void); void collect_manager_notify_cb(FileData *fd, NotifyType type, gpointer data); - +void collect_manager_list(GList **names_exc, GList **names_inc, GList **paths); #endif /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff -r e6847b39721f -r 03014a1eb7e7 src/collect-table.c --- a/src/collect-table.c Wed Aug 16 09:42:42 2017 +0100 +++ b/src/collect-table.c Fri Aug 18 14:25:36 2017 +0100 @@ -828,20 +828,6 @@ g_list_free(list); } -static void collection_table_popup_add_filelist_cb(GtkWidget *widget, gpointer data) -{ - CollectTable *ct = data; - GList *list; - - list = layout_list(NULL); - - if (list) - { - collection_table_add_filelist(ct, list); - filelist_free(list); - } -} - static void collection_table_popup_add_file_selection_cb(GtkWidget *widget, gpointer data) { CollectTable *ct = data; @@ -929,8 +915,6 @@ menu_item_add_stock(menu, _("Append from file selection"), GTK_STOCK_ADD, G_CALLBACK(collection_table_popup_add_file_selection_cb), ct); - menu_item_add_stock(menu, _("Append from file list"), GTK_STOCK_ADD, - G_CALLBACK(collection_table_popup_add_filelist_cb), ct); menu_item_add_stock(menu, _("Append from collection..."), GTK_STOCK_OPEN, G_CALLBACK(collection_table_popup_add_collection_cb), ct); menu_item_add_divider(menu); diff -r e6847b39721f -r 03014a1eb7e7 src/collect.c --- a/src/collect.c Wed Aug 16 09:42:42 2017 +0100 +++ b/src/collect.c Fri Aug 18 14:25:36 2017 +0100 @@ -44,8 +44,12 @@ #define COLLECT_DEF_WIDTH 440 #define COLLECT_DEF_HEIGHT 450 -static GList *collection_list = NULL; -static GList *collection_window_list = NULL; +/* list of paths to collections */ + +/* List of currently open Collections*/ +static GList *collection_list = NULL; /* type CollectionData */ +/* List of currently open Collection windows*/ +static GList *collection_window_list = NULL; /* type CollectWindow */ static void collection_window_get_geometry(CollectWindow *cw); static void collection_window_refresh(CollectWindow *cw); @@ -307,6 +311,57 @@ return NULL; } +/* Checks string for existence of Collection. + * The parameter is the filename, + * with or without extension of any collection + * + * Returns: full pathname if found or NULL + * Return value must be freed with g_free() + */ +gchar *collection_path(gchar *param) +{ + gchar *path = NULL; + gchar *full_name = NULL; + + if (file_extension_match(param, GQ_COLLECTION_EXT)) + { + path = g_build_filename(get_collections_dir(), param, NULL); + } + else if (file_extension_match(param, NULL)) + { + full_name = g_strconcat(param, GQ_COLLECTION_EXT, NULL); + path = g_build_filename(get_collections_dir(), full_name, NULL); + } + + if (!isfile(path)) + { + g_free(path); + path = NULL; + } + + g_free(full_name); + return path; +} + +/* Checks input string for existence of Collection. + * The parameter is the filename + * with or without extension of any collection + * + * Returns TRUE if found + */ +gboolean is_collection(gchar *param) +{ + gchar *name = NULL; + + name = collection_path(param); + if (name) + { + g_free(name); + return TRUE; + } + return FALSE; +} + /* *------------------------------------------------------------------- * please use these to actually add/remove stuff diff -r e6847b39721f -r 03014a1eb7e7 src/collect.h --- a/src/collect.h Wed Aug 16 09:42:42 2017 +0100 +++ b/src/collect.h Fri Aug 18 14:25:36 2017 +0100 @@ -86,6 +86,7 @@ CollectWindow *collection_window_find_by_path(const gchar *path); gboolean collection_window_modified_exists(void); - +gboolean is_collection(gchar *param); +gchar *collection_path(gchar *param); #endif /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff -r e6847b39721f -r 03014a1eb7e7 src/dupe.c --- a/src/dupe.c Wed Aug 16 09:42:42 2017 +0100 +++ b/src/dupe.c Fri Aug 18 14:25:36 2017 +0100 @@ -2309,12 +2309,30 @@ return list; } +/* Add file selection list to a collection + * Called from a right-click menu + * Inputs: + * data: index to the collection list menu item selected, or -1 for new collection + */ +static void dupe_pop_menu_collections_cb(GtkWidget *widget, gpointer data) +{ + DupeWindow *dw; + GList *selection_list; + + dw = submenu_item_get_data(widget); + selection_list = dupe_listview_get_selection(dw, dw->listview); + pop_menu_collections(selection_list, data); + + filelist_free(selection_list); +} + static GtkWidget *dupe_menu_popup_main(DupeWindow *dw, DupeItem *di) { GtkWidget *menu; GtkWidget *item; gint on_row; GList *editmenu_fd_list; + GtkWidget *submenu; on_row = (di != NULL); @@ -2340,8 +2358,11 @@ G_CALLBACK(dupe_menu_popup_destroy_cb), editmenu_fd_list); submenu_add_edit(menu, &item, G_CALLBACK(dupe_menu_edit_cb), dw, editmenu_fd_list); if (!on_row) gtk_widget_set_sensitive(item, FALSE); - menu_item_add_stock_sensitive(menu, _("Add to new collection"), GTK_STOCK_INDEX, on_row, - G_CALLBACK(dupe_menu_collection_cb), dw); + + submenu = submenu_add_collections(menu, &item, + G_CALLBACK(dupe_pop_menu_collections_cb), dw); + gtk_widget_set_sensitive(item, on_row); + menu_item_add_stock_sensitive(menu, _("Print..."), GTK_STOCK_PRINT, on_row, G_CALLBACK(dupe_menu_print_cb), dw); menu_item_add_divider(menu); diff -r e6847b39721f -r 03014a1eb7e7 src/img-view.c --- a/src/img-view.c Wed Aug 16 09:42:42 2017 +0100 +++ b/src/img-view.c Fri Aug 18 14:25:36 2017 +0100 @@ -1254,9 +1254,31 @@ return list; } +/* Add file selection list to a collection + * Called from a right-click submenu + * Inputs: + * data: index to the collection list menu item selected, or -1 for new collection + */ +static void image_pop_menu_collections_cb(GtkWidget *widget, gpointer data) +{ + ViewWindow *vw; + ImageWindow *imd; + FileData *fd; + GList *selection_list = NULL; + + vw = submenu_item_get_data(widget); + imd = view_window_active_image(vw); + fd = image_get_fd(imd); + selection_list = g_list_append(selection_list, fd); + pop_menu_collections(selection_list, data); + + filelist_free(selection_list); +} + static GtkWidget *view_popup_menu(ViewWindow *vw) { GtkWidget *menu; + GtkWidget *submenu; GtkWidget *item; GList *editmenu_fd_list; @@ -1291,6 +1313,11 @@ menu_item_add_divider(menu); + submenu = submenu_add_collections(menu, &item, + G_CALLBACK(image_pop_menu_collections_cb), vw); + gtk_widget_set_sensitive(item, TRUE); + menu_item_add_divider(menu); + if (vw->ss) { menu_item_add(menu, _("_Stop slideshow"), G_CALLBACK(view_slideshow_stop_cb), vw); diff -r e6847b39721f -r 03014a1eb7e7 src/layout_image.c --- a/src/layout_image.c Wed Aug 16 09:42:42 2017 +0100 +++ b/src/layout_image.c Fri Aug 18 14:25:36 2017 +0100 @@ -642,6 +642,23 @@ return list; } +/* Add file selection list to a collection + * Called from a right-click submenu + * Inputs: + * data: index to the collection list menu item selected, or -1 for new collection + */ +static void layout_pop_menu_collections_cb(GtkWidget *widget, gpointer data) +{ + LayoutWindow *lw; + GList *selection_list = NULL; + + lw = submenu_item_get_data(widget); + selection_list = g_list_append(selection_list, layout_image_get_fd(lw)); + pop_menu_collections(selection_list, data); + + filelist_free(selection_list); +} + static GtkWidget *layout_image_pop_menu(LayoutWindow *lw) { GtkWidget *menu; @@ -691,7 +708,11 @@ if (!path) gtk_widget_set_sensitive(item, FALSE); item = menu_item_add_stock(menu, _("_Delete..."), GTK_STOCK_DELETE, G_CALLBACK(li_pop_menu_delete_cb), lw); if (!path) gtk_widget_set_sensitive(item, FALSE); - + menu_item_add_divider(menu); + + submenu = submenu_add_collections(menu, &item, + G_CALLBACK(layout_pop_menu_collections_cb), lw); + gtk_widget_set_sensitive(item, TRUE); menu_item_add_divider(menu); if (layout_image_slideshow_active(lw)) diff -r e6847b39721f -r 03014a1eb7e7 src/main.c --- a/src/main.c Wed Aug 16 09:42:42 2017 +0100 +++ b/src/main.c Fri Aug 18 14:25:36 2017 +0100 @@ -214,32 +214,6 @@ parse_command_line_add_file(file_path, path, file, list, collection_list); } -static gboolean is_collection(gchar *cmd_param) -{ - gchar *path = NULL; - gchar *full_name = NULL; - gboolean result = FALSE; - - if (file_extension_match(cmd_param, GQ_COLLECTION_EXT)) - { - path = g_build_filename(get_collections_dir(), cmd_param, NULL); - } - else if (file_extension_match(cmd_param, NULL)) - { - full_name = g_strconcat(cmd_param, GQ_COLLECTION_EXT, NULL); - path = g_build_filename(get_collections_dir(), full_name, NULL); - } - - if (isfile(path)) - { - result = TRUE; - } - - g_free(path); - g_free(full_name); - return result; -} - static void parse_command_line(gint argc, gchar *argv[]) { GList *list = NULL; @@ -285,21 +259,11 @@ else if (is_collection(cmd_line)) { gchar *path = NULL; - gchar *full_name = NULL; - if (file_extension_match(cmd_line, GQ_COLLECTION_EXT)) - { - path = g_build_filename(get_collections_dir(), cmd_line, NULL); - } - else - { - full_name = g_strconcat(cmd_line, GQ_COLLECTION_EXT, NULL); - path = g_build_filename(get_collections_dir(), full_name, NULL); - } + path = collection_path(cmd_line); parse_command_line_process_file(path, &command_line->path, &command_line->file, &list, &command_line->collection_list, &first_dir); g_free(path); - g_free(full_name); } else if (strncmp(cmd_line, "--debug", 7) == 0 && (cmd_line[7] == '\0' || cmd_line[7] == '=')) { diff -r e6847b39721f -r 03014a1eb7e7 src/menu.c --- a/src/menu.c Wed Aug 16 09:42:42 2017 +0100 +++ b/src/menu.c Fri Aug 18 14:25:36 2017 +0100 @@ -25,6 +25,8 @@ #include "cache_maint.h" #include "collect.h" #include "collect-dlg.h" +#include "collect-io.h" +#include "collect-table.h" #include "dupe.h" #include "editors.h" #include "filedata.h" @@ -379,4 +381,92 @@ { return real_submenu_add_alter(menu, func, data, NULL); } + +/* + *----------------------------------------------------------------------------- + * collections + *----------------------------------------------------------------------------- + */ + +/* Add submenu consisting of "New collection", and list of existing collections + * to a right-click menu. + * Used by image windows + */ +static void add_collection_list(GtkWidget *menu, GCallback func, + GList *collection_list, gpointer data) +{ + GList *work; + gint index = 0; /* index to existing collection list menu item selected */ + GtkWidget *item; + + work = collection_list; + while (work) + { + const gchar *collection_name = work->data; + + item = menu_item_add(menu, collection_name, func, + GINT_TO_POINTER(index)); + work = work->next; + index++; + } +} + +GtkWidget *submenu_add_collections(GtkWidget *menu, GtkWidget **menu_item, + GCallback func, gpointer data) +{ + GtkWidget *item; + GtkWidget *submenu; + GList *collection_list = NULL; + + item = menu_item_add(menu, _("_Add to Collection"), NULL, NULL); + + submenu = gtk_menu_new(); + g_object_set_data(G_OBJECT(submenu), "submenu_data", data); + + menu_item_add_stock_sensitive(submenu, _("New collection"), + GTK_STOCK_INDEX, TRUE, G_CALLBACK(func), GINT_TO_POINTER(-1)); + menu_item_add_divider(submenu); + + collect_manager_list(&collection_list,NULL,NULL); + add_collection_list(submenu, func, collection_list, data); + + gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), submenu); + if (menu_item) *menu_item = item; + + g_list_free(collection_list); + + return submenu; +} + +/* Add file selection list to a collection + * Called from a right-click submenu + * Inputs: + * selection_list: GList of FileData + * data: index to the collection list menu item selected, or -1 for new collection + */ +void pop_menu_collections(GList *selection_list, gpointer data) +{ + CollectWindow *cw; + gchar *collection_name; + GList *collection_list = NULL; + gchar *name; + const gint index = GPOINTER_TO_INT(data); + + if (index >= 0) + { + collect_manager_list(&collection_list, NULL, NULL); + collection_name = g_list_nth_data(collection_list, index); + name = collection_path(collection_name); + cw = collection_window_new(name); + g_free(name); + string_list_free(collection_list); + } + else + { + cw = collection_window_new(NULL); + } + + collection_table_add_filelist(cw->table, selection_list); +} + /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff -r e6847b39721f -r 03014a1eb7e7 src/menu.h --- a/src/menu.h Wed Aug 16 09:42:42 2017 +0100 +++ b/src/menu.h Fri Aug 18 14:25:36 2017 +0100 @@ -37,6 +37,8 @@ gchar *alter_type_get_text(AlterType type); GtkWidget *submenu_add_alter(GtkWidget *menu, GCallback func, gpointer data); - +GtkWidget *submenu_add_collections(GtkWidget *menu, GtkWidget **menu_item, + GCallback func, gpointer data); +void pop_menu_collections(GList *selection_list, gpointer data); #endif /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff -r e6847b39721f -r 03014a1eb7e7 src/pan-view/pan-view.c --- a/src/pan-view/pan-view.c Wed Aug 16 09:42:42 2017 +0100 +++ b/src/pan-view/pan-view.c Fri Aug 18 14:25:36 2017 +0100 @@ -2196,6 +2196,23 @@ return list; } +/* Add file selection list to a collection + * Called from a right-click submenu + * Inputs: + * data: index to the collection list menu item selected, or -1 for new collection + */ +static void pan_pop_menu_collections_cb(GtkWidget *widget, gpointer data) +{ + PanWindow *pw; + GList *selection_list = NULL; + + pw = submenu_item_get_data(widget); + selection_list = g_list_append(selection_list, pan_menu_click_fd(pw)); + pop_menu_collections(selection_list, data); + + filelist_free(selection_list); +} + static GtkWidget *pan_popup_menu(PanWindow *pw) { GtkWidget *menu; @@ -2239,6 +2256,13 @@ G_CALLBACK(pan_delete_cb), pw); menu_item_add_divider(menu); + + submenu = submenu_add_collections(menu, &item, + G_CALLBACK(pan_pop_menu_collections_cb), pw); + gtk_widget_set_sensitive(item, TRUE); + menu_item_add_divider(menu); + + item = menu_item_add_check(menu, _("Sort by E_xif date"), pw->exif_date_enable, G_CALLBACK(pan_exif_date_toggle_cb), pw); gtk_widget_set_sensitive(item, (pw->layout == PAN_LAYOUT_TIMELINE || pw->layout == PAN_LAYOUT_CALENDAR)); diff -r e6847b39721f -r 03014a1eb7e7 src/search.c --- a/src/search.c Wed Aug 16 09:42:42 2017 +0100 +++ b/src/search.c Fri Aug 18 14:25:36 2017 +0100 @@ -1030,11 +1030,29 @@ filelist_free(editmenu_fd_list); } +/* Add file selection list to a collection + * Called from a right-click submenu + * Inputs: + * data: index to the collection list menu item selected, or -1 for new collection + */ +static void search_pop_menu_collections_cb(GtkWidget *widget, gpointer data) +{ + SearchData *sd; + GList *selection_list; + + sd = submenu_item_get_data(widget); + selection_list = search_result_selection_list(sd); + pop_menu_collections(selection_list, data); + + filelist_free(selection_list); +} + static GtkWidget *search_result_menu(SearchData *sd, gboolean on_row, gboolean empty) { GtkWidget *menu; GtkWidget *item; GList *editmenu_fd_list; + GtkWidget *submenu; menu = popup_menu_short_lived(); @@ -1054,8 +1072,11 @@ G_CALLBACK(search_result_menu_destroy_cb), editmenu_fd_list); submenu_add_edit(menu, &item, G_CALLBACK(sr_menu_edit_cb), sd, editmenu_fd_list); if (!on_row) gtk_widget_set_sensitive(item, FALSE); - menu_item_add_stock_sensitive(menu, _("Add to new collection"), GTK_STOCK_INDEX, on_row, - G_CALLBACK(sr_menu_collection_cb), sd); + + submenu = submenu_add_collections(menu, &item, + G_CALLBACK(search_pop_menu_collections_cb), sd); + gtk_widget_set_sensitive(item, on_row); + menu_item_add_stock_sensitive(menu, _("Print..."), GTK_STOCK_PRINT, on_row, G_CALLBACK(sr_menu_print_cb), sd); menu_item_add_divider(menu); diff -r e6847b39721f -r 03014a1eb7e7 src/typedefs.h --- a/src/typedefs.h Wed Aug 16 09:42:42 2017 +0100 +++ b/src/typedefs.h Fri Aug 18 14:25:36 2017 +0100 @@ -437,7 +437,6 @@ GtkWidget *window; CollectTable *table; GtkWidget *status_box; - GList *list; GtkWidget *close_dialog; diff -r e6847b39721f -r 03014a1eb7e7 src/view_file/view_file.c --- a/src/view_file/view_file.c Wed Aug 16 09:42:42 2017 +0100 +++ b/src/view_file/view_file.c Fri Aug 18 14:25:36 2017 +0100 @@ -504,6 +504,23 @@ vf->editmenu_fd_list = NULL; } +/* Add file selection list to a collection + * Called from a right-click menu + * Inputs: + * data: index to the collection list menu item selected, or -1 for new collection + */ +static void vf_pop_menu_collections_cb(GtkWidget *widget, gpointer data) +{ + ViewFile *vf; + GList *selection_list; + + vf = submenu_item_get_data(widget); + selection_list = vf_selection_get_list(vf); + pop_menu_collections(selection_list, data); + + filelist_free(selection_list); +} + GtkWidget *vf_pop_menu(ViewFile *vf) { GtkWidget *menu; @@ -603,8 +620,10 @@ menu_item_add_stock_sensitive(menu, _("_Find duplicates..."), GTK_STOCK_FIND, active, G_CALLBACK(vf_pop_menu_duplicates_cb), vf); menu_item_add_divider(menu); - menu_item_add_stock_sensitive(menu, _("Add to new collection"), GTK_STOCK_INDEX, active, - G_CALLBACK(vf_pop_menu_add_collection_cb), vf); + + submenu = submenu_add_collections(menu, &item, + G_CALLBACK(vf_pop_menu_collections_cb), vf); + gtk_widget_set_sensitive(item, active); menu_item_add_divider(menu); submenu = submenu_add_sort(NULL, G_CALLBACK(vf_pop_menu_sort_cb), vf,