Add a way to invert the current selection.
authorLaurent Monin <geeqie@norz.org>
Wed, 7 May 2008 22:48:30 +0000 (22:48 +0000)
committerLaurent Monin <geeqie@norz.org>
Wed, 7 May 2008 22:48:30 +0000 (22:48 +0000)
An item labeled "Invert selection" was added to the Select submenu
in the main menu.

src/layout.c
src/layout.h
src/layout_util.c
src/view_file.c
src/view_file.h
src/view_file_icon.c
src/view_file_icon.h
src/view_file_list.c
src/view_file_list.h

index a04b361..bdc34e5 100644 (file)
@@ -875,6 +875,13 @@ void layout_select_none(LayoutWindow *lw)
        if (lw->vf) vf_select_none(lw->vf);
 }
 
+void layout_select_invert(LayoutWindow *lw)
+{
+       if (!layout_valid(&lw)) return;
+
+       if (lw->vf) vf_select_invert(lw->vf);
+}
+
 void layout_mark_to_selection(LayoutWindow *lw, gint mark, MarkToSelectionMode mode)
 {
        if (!layout_valid(&lw)) return;
index f16ef2c..f0f1dee 100644 (file)
@@ -50,6 +50,7 @@ GList *layout_selection_list_by_index(LayoutWindow *lw);
 gint layout_selection_count(LayoutWindow *lw, gint64 *bytes);
 void layout_select_all(LayoutWindow *lw);
 void layout_select_none(LayoutWindow *lw);
+void layout_select_invert(LayoutWindow *lw);
 
 void layout_mark_to_selection(LayoutWindow *lw, gint mark, MarkToSelectionMode mode);
 void layout_selection_to_mark(LayoutWindow *lw, gint mark, SelectionToMarkMode mode);
index ad787cd..56b3898 100644 (file)
@@ -717,6 +717,13 @@ static void layout_menu_unselect_all_cb(GtkAction *action, gpointer data)
        layout_select_none(lw);
 }
 
+static void layout_menu_invert_selection_cb(GtkAction *action, gpointer data)
+{
+       LayoutWindow *lw = data;
+
+       layout_select_invert(lw);
+}
+
 static void layout_menu_marks_cb(GtkToggleAction *action, gpointer data)
 {
        LayoutWindow *lw = data;
@@ -1095,6 +1102,8 @@ static GtkActionEntry menu_entries[] = {
   { "Properties",GTK_STOCK_PROPERTIES, N_("_Properties"),      "<control>P",   NULL,   CB(layout_menu_info_cb) },
   { "SelectAll",       NULL,           N_("Select _all"),      "<control>A",   NULL,   CB(layout_menu_select_all_cb) },
   { "SelectNone",      NULL,           N_("Select _none"), "<control><shift>A",NULL,   CB(layout_menu_unselect_all_cb) },
+  { "SelectInvert",    NULL,           N_("_Invert Selection"), "<control><shift>I",   NULL,   CB(layout_menu_invert_selection_cb) },
+
   { "Preferences",GTK_STOCK_PREFERENCES,N_("P_references..."), "<control>O",   NULL,   CB(layout_menu_config_cb) },
   { "Maintenance",     NULL,           N_("_Thumbnail maintenance..."),NULL,   NULL,   CB(layout_menu_remove_thumb_cb) },
   { "Wallpaper",       NULL,           N_("Set as _wallpaper"),NULL,           NULL,   CB(layout_menu_wallpaper_cb) },
@@ -1200,6 +1209,7 @@ static const char *menu_ui_description =
 "    <menu action='SelectMenu'>"
 "      <menuitem action='SelectAll'/>"
 "      <menuitem action='SelectNone'/>"
+"      <menuitem action='SelectInvert'/>"
 "      <separator/>"
 "      <menuitem action='ShowMarks'/>"
 "      <separator/>"
index 2cfdc3d..8747eb0 100644 (file)
@@ -222,6 +222,15 @@ void vf_select_none(ViewFile *vf)
        }
 }
 
+void vf_select_invert(ViewFile *vf)
+{
+       switch(vf->type)
+       {
+       case FILEVIEW_LIST: vflist_select_invert(vf); break;
+       case FILEVIEW_ICON: vficon_select_invert(vf); break;
+       }
+}
+
 void vf_select_by_fd(ViewFile *vf, FileData *fd)
 {
        switch(vf->type)
index 86b31c9..3242d12 100644 (file)
@@ -42,6 +42,7 @@ GList *vf_selection_get_list_by_index(ViewFile *vf);
 
 void vf_select_all(ViewFile *vf);
 void vf_select_none(ViewFile *vf);
+void vf_select_invert(ViewFile *vf);
 void vf_select_by_fd(ViewFile *vf, FileData *fd);
 
 void vf_mark_to_selection(ViewFile *vf, gint mark, MarkToSelectionMode mode);
index 3bdc32d..fbde60f 100644 (file)
@@ -829,6 +829,31 @@ void vficon_select_none(ViewFile *vf)
        vficon_send_update(vf);
 }
 
+void vficon_select_invert(ViewFile *vf)
+{
+       GList *work;
+
+       work = vf->list;
+       while (work)
+               {
+               IconData *id = work->data;
+               work = work->next;
+
+               if (id->selected & SELECTION_SELECTED)
+                       {
+                       VFICON_INFO(vf, selection) = g_list_remove(VFICON_INFO(vf, selection), id);
+                       vficon_selection_remove(vf, id, SELECTION_SELECTED, NULL);
+                       }
+               else
+                       {
+                       VFICON_INFO(vf, selection) = g_list_append(VFICON_INFO(vf, selection), id);
+                       vficon_selection_add(vf, id, SELECTION_SELECTED, NULL);
+                       }
+               }
+
+       vficon_send_update(vf);
+}
+
 static void vficon_select(ViewFile *vf, IconData *id)
 {
        VFICON_INFO(vf, prev_selection) = id;
index 331d519..8251634 100644 (file)
@@ -41,6 +41,7 @@ GList *vficon_selection_get_list_by_index(ViewFile *vf);
 
 void vficon_select_all(ViewFile *vf);
 void vficon_select_none(ViewFile *vf);
+void vficon_select_invert(ViewFile *vf);
 void vficon_select_by_fd(ViewFile *vf, FileData *fd);
 
 void vficon_mark_to_selection(ViewFile *vf, gint mark, MarkToSelectionMode mode);
index a68d84a..ba104b9 100644 (file)
@@ -1524,6 +1524,66 @@ void vflist_select_none(ViewFile *vf)
        gtk_tree_selection_unselect_all(selection);
 }
 
+static gboolean tree_model_iter_prev(GtkTreeModel *store, GtkTreeIter *iter)
+{
+       GtkTreePath *tpath;
+       gboolean result;
+
+       tpath = gtk_tree_model_get_path(store, iter);
+       result = gtk_tree_path_prev(tpath);
+       if (result)
+               gtk_tree_model_get_iter(store, iter, tpath);
+
+       gtk_tree_path_free(tpath);
+
+       return result;
+}
+
+static gboolean tree_model_get_iter_last(GtkTreeModel *store, GtkTreeIter *iter)
+{
+       if (!gtk_tree_model_get_iter_first(store, iter))
+               return FALSE;
+
+       while (TRUE)
+               {
+               GtkTreeIter next = *iter;
+               
+               if (gtk_tree_model_iter_next(store, &next))
+                       *iter = next;
+               else
+                       break;
+               }
+       
+       return TRUE;
+}
+
+void vflist_select_invert(ViewFile *vf)
+{
+       GtkTreeIter iter;
+       GtkTreeSelection *selection;
+       GtkTreeModel *store;
+       gboolean valid;
+
+       store = gtk_tree_view_get_model(GTK_TREE_VIEW(vf->listview));
+       selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(vf->listview));
+
+       /* Backward iteration prevents scrolling to the end of the list,
+        * it scrolls to the first selected row instead. */
+       valid = tree_model_get_iter_last(store, &iter);
+
+       while (valid)
+               {
+               gint selected = gtk_tree_selection_iter_is_selected(selection, &iter);
+
+               if (selected)
+                       gtk_tree_selection_unselect_iter(selection, &iter);
+               else
+                       gtk_tree_selection_select_iter(selection, &iter);
+                               
+               valid = tree_model_iter_prev(store, &iter);
+               }
+}
+
 void vflist_select_by_fd(ViewFile *vf, FileData *fd)
 {
        GtkTreeIter iter;
index 72bf440..89091c9 100644 (file)
@@ -45,6 +45,7 @@ GList *vflist_selection_get_list_by_index(ViewFile *vf);
 
 void vflist_select_all(ViewFile *vf);
 void vflist_select_none(ViewFile *vf);
+void vflist_select_invert(ViewFile *vf);
 void vflist_select_by_fd(ViewFile *vf, FileData *fd);
 
 void vflist_mark_to_selection(ViewFile *vf, gint mark, MarkToSelectionMode mode);