Right-click menus - collections
authorColin Clark <colin.clark@cclark.uk>
Fri, 18 Aug 2017 13:25:36 +0000 (14:25 +0100)
committerColin Clark <colin.clark@cclark.uk>
Fri, 18 Aug 2017 13:25:36 +0000 (14:25 +0100)
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"

15 files changed:
src/collect-io.c
src/collect-io.h
src/collect-table.c
src/collect.c
src/collect.h
src/dupe.c
src/img-view.c
src/layout_image.c
src/main.c
src/menu.c
src/menu.h
src/pan-view/pan-view.c
src/search.c
src/typedefs.h
src/view_file/view_file.c

index 8f6b3a2..62326d0 100644 (file)
@@ -969,6 +969,75 @@ void collect_manager_notify_cb(FileData *fd, NotifyType type, gpointer data)
                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: */
index b01325c..78f1cb3 100644 (file)
@@ -57,7 +57,7 @@ void collect_manager_remove(FileData *fd, const gchar *collection);
 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: */
index cf0d618..3eed2e0 100644 (file)
@@ -828,20 +828,6 @@ static void collection_table_popup_remove_cb(GtkWidget *widget, gpointer data)
        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 @@ static GtkWidget *collection_table_popup_menu(CollectTable *ct, gboolean over_ic
 
        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);
index 30c481b..3d97e4c 100644 (file)
 #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 @@ CollectWindow *collection_window_find_by_path(const gchar *path)
        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
index 3cbaa1e..9d0ee38 100644 (file)
@@ -86,6 +86,7 @@ CollectWindow *collection_window_find(CollectionData *cd);
 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: */
index 6b3722b..e02feca 100644 (file)
@@ -2309,12 +2309,30 @@ static GList *dupe_window_get_fd_list(DupeWindow *dw)
        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 @@ static GtkWidget *dupe_menu_popup_main(DupeWindow *dw, DupeItem *di)
                         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);
index 5b7663c..52a59c1 100644 (file)
@@ -1254,9 +1254,31 @@ static GList *view_window_get_fd_list(ViewWindow *vw)
        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 @@ static GtkWidget *view_popup_menu(ViewWindow *vw)
 
        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);
index fdfccb7..5db6599 100644 (file)
@@ -642,6 +642,23 @@ static GList *layout_image_get_fd_list(LayoutWindow *lw)
        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 @@ static GtkWidget *layout_image_pop_menu(LayoutWindow *lw)
        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))
index 97246f7..1d4c82b 100644 (file)
@@ -214,32 +214,6 @@ static void parse_command_line_process_file(const gchar *file_path, gchar **path
        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 @@ static void parse_command_line(gint argc, gchar *argv[])
                        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] == '='))
                                {
index 0e22198..dbbb851 100644 (file)
@@ -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 @@ GtkWidget *submenu_add_alter(GtkWidget *menu, GCallback func, gpointer data)
 {
        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: */
index aec4fd4..52f58c9 100644 (file)
@@ -37,6 +37,8 @@ GtkWidget *submenu_add_zoom(GtkWidget *menu, GCallback func, gpointer data,
 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: */
index 6b4f842..842580e 100644 (file)
@@ -2196,6 +2196,23 @@ static GList *pan_view_get_fd_list(PanWindow *pw)
        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 @@ static GtkWidget *pan_popup_menu(PanWindow *pw)
                                      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));
index 361e03e..da19e91 100644 (file)
@@ -1030,11 +1030,29 @@ static void search_result_menu_destroy_cb(GtkWidget *widget, gpointer data)
        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 @@ static GtkWidget *search_result_menu(SearchData *sd, gboolean on_row, gboolean e
                         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);
index 9d7db51..7f05639 100644 (file)
@@ -437,7 +437,6 @@ struct _CollectWindow
        GtkWidget *window;
        CollectTable *table;
        GtkWidget *status_box;
-       GList *list;
 
        GtkWidget *close_dialog;
 
index dbba21a..43315b8 100644 (file)
@@ -504,6 +504,23 @@ static void vf_popup_destroy_cb(GtkWidget *widget, gpointer data)
        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 @@ GtkWidget *vf_pop_menu(ViewFile *vf)
        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,