From: Richard Kettlewell Date: Sun, 7 Dec 2008 20:20:51 +0000 (+0000) Subject: Replace rather bizarre 'select all' in choose tab with 'select X-Git-Tag: 4.3~42 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/commitdiff_plain/a0e78d9698411f5edc54f6aec0040cecfb3f9f65 Replace rather bizarre 'select all' in choose tab with 'select children' which (after jumping through some hoops) selects just the file children of the selected directory. Updated the Disobedience documentation a bit. --- diff --git a/CHANGES.html b/CHANGES.html index 495d898..e8436a4 100644 --- a/CHANGES.html +++ b/CHANGES.html @@ -58,7 +58,7 @@ span.command {

This file documents recent user-visible changes to DisOrder.

-

Changes up to version XXX

+

Changes up to version 4.3

@@ -73,6 +73,10 @@ span.command {

Disobedience's icons have been changed to larger, more colorful ones. The SVG source is included if you want to fiddle with them.

+

“Select all” is now no longer available in the choose + tab. Instead there is a new “Select children” option which + selects the file children of a single subdirectory.

+

Server

diff --git a/disobedience/choose-menu.c b/disobedience/choose-menu.c index 37167e7..16aa593 100644 --- a/disobedience/choose-menu.c +++ b/disobedience/choose-menu.c @@ -25,6 +25,9 @@ /** @brief Popup menu */ static GtkWidget *choose_menu; +/** @brief Path to directory pending a "select children" operation */ +static GtkTreePath *choose_eventually_select_children; + /** @brief Recursion step for choose_get_visible() * @param parent A visible node, or NULL for the root * @param callback Called for each visible node @@ -71,52 +74,14 @@ static int choose_visible_recurse(GtkTreeIter *parent, return 0; } -static void choose_visible_visit(int (*callback)(GtkTreeIter *it, - int isfile, - void *userdata), - void *userdata) { - choose_visible_recurse(NULL, callback, userdata); -} - -static int choose_selectall_sensitive_callback - (GtkTreeIter attribute((unused)) *it, - int isfile, - void *userdata) { - if(isfile) { - *(int *)userdata = 1; - return 1; - } - return 0; -} - -/** @brief Should 'select all' be sensitive? - * - * Yes if there are visible files. - */ +/** @brief Should edit->select all be sensitive? No, for the choose tab. */ static int choose_selectall_sensitive(void attribute((unused)) *extra) { - int files = 0; - choose_visible_visit(choose_selectall_sensitive_callback, &files); - return files > 0; -} - -static int choose_selectall_activate_callback - (GtkTreeIter *it, - int isfile, - void attribute((unused)) *userdata) { - if(isfile) - gtk_tree_selection_select_iter(choose_selection, it); - else - gtk_tree_selection_unselect_iter(choose_selection, it); - return 0; + return FALSE; } -/** @brief Activate select all - * - * Selects all files and deselects everything else. - */ +/** @brief Activate edit->select all (which should do nothing) */ static void choose_selectall_activate(GtkMenuItem attribute((unused)) *item, gpointer attribute((unused)) userdata) { - choose_visible_visit(choose_selectall_activate_callback, 0); } /** @brief Should 'select none' be sensitive @@ -169,6 +134,16 @@ static void choose_gather_selected_files_callback(GtkTreeModel attribute((unused vector_append(v, choose_get_track(iter)); } +static void choose_gather_selected_dirs_callback(GtkTreeModel attribute((unused)) *model, + GtkTreePath attribute((unused)) *path, + GtkTreeIter *iter, + gpointer data) { + struct vector *v = data; + + if(choose_is_dir(iter)) + vector_append(v, choose_get_track(iter)); +} + static void choose_play_activate(GtkMenuItem attribute((unused)) *item, gpointer attribute((unused)) userdata) { @@ -195,6 +170,92 @@ static void choose_properties_activate(GtkMenuItem attribute((unused)) *item, properties(v->nvec, (const char **)v->vec); } +/** @brief Set sensitivity for select children + * + * Sensitive if we've selected exactly one directory. + */ +static int choose_selectchildren_sensitive(void attribute((unused)) *extra) { + struct vector v[1]; + /* Only one thing should be selected */ + if(gtk_tree_selection_count_selected_rows(choose_selection) != 1) + return FALSE; + /* The selected thing should be a directory */ + vector_init(v); + gtk_tree_selection_selected_foreach(choose_selection, + choose_gather_selected_dirs_callback, + v); + return v->nvec == 1; +} + +/** @brief Actually select the children of path + * + * We deselect everything else, too. + */ +static void choose_select_children(GtkTreePath *path) { + GtkTreeIter iter[1], child[1]; + + if(gtk_tree_model_get_iter(GTK_TREE_MODEL(choose_store), iter, path)) { + gtk_tree_selection_unselect_all(choose_selection); + for(int n = 0; + gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(choose_store), child, + iter, n); + ++n) { + if(choose_is_file(child)) + gtk_tree_selection_select_iter(choose_selection, child); + } + } +} + +/** @brief Called to expand the children of path/iter */ +static void choose_selectchildren_callback(GtkTreeModel attribute((unused)) *model, + GtkTreePath *path, + GtkTreeIter attribute((unused)) *iter, + gpointer attribute((unused)) data) { + if(gtk_tree_view_row_expanded(GTK_TREE_VIEW(choose_view), path)) { + /* Directory is already expanded */ + choose_select_children(path); + } else { + /* Directory is not expanded, so expand it */ + gtk_tree_view_expand_row(GTK_TREE_VIEW(choose_view), path, FALSE/*!expand_all*/); + /* Select its children when it's done */ + if(choose_eventually_select_children) + gtk_tree_path_free(choose_eventually_select_children); + choose_eventually_select_children = gtk_tree_path_copy(path); + } +} + +/** @brief Called when all pending track fetches are finished + * + * If there's a pending select-children operation, it can now be actioned + * (or might have gone stale). + */ +void choose_menu_moretracks(const char attribute((unused)) *event, + void attribute((unused)) *eventdata, + void attribute((unused)) *callbackdata) { + if(choose_eventually_select_children) { + choose_select_children(choose_eventually_select_children); + gtk_tree_path_free(choose_eventually_select_children); + choose_eventually_select_children = 0; + } +} + +/** @brief Select all children + * + * Easy enough if the directory is already expanded, we can just select its + * children. However if it is not then we must expand it and _when this has + * completed_ select its children. + * + * The way this is implented could cope with multiple directories but + * choose_selectchildren_sensitive() should stop this. + */ +static void choose_selectchildren_activate + (GtkMenuItem attribute((unused)) *item, + gpointer attribute((unused)) userdata) { + gtk_tree_selection_selected_foreach(choose_selection, + choose_selectchildren_callback, + 0); +} + /** @brief Pop-up menu for choose */ static struct menuitem choose_menuitems[] = { { @@ -212,9 +273,9 @@ static struct menuitem choose_menuitems[] = { 0 }, { - "Select all tracks", - choose_selectall_activate, - choose_selectall_sensitive, + "Select children", + choose_selectchildren_activate, + choose_selectchildren_sensitive, 0, 0 }, diff --git a/disobedience/choose.c b/disobedience/choose.c index d1e9515..b9a9e7e 100644 --- a/disobedience/choose.c +++ b/disobedience/choose.c @@ -619,6 +619,7 @@ GtkWidget *choose_widget(void) { event_register("playing-track-changed", choose_set_state, 0); event_register("search-results-changed", choose_set_state, 0); event_register("lookups-completed", choose_set_state, 0); + event_register("choose-more-tracks", choose_menu_moretracks, 0); /* After a rescan we update the choose tree. We get a rescan-complete * automatically at startup and upon connection too. */ diff --git a/disobedience/choose.h b/disobedience/choose.h index 97f7095..5213332 100644 --- a/disobedience/choose.h +++ b/disobedience/choose.h @@ -79,6 +79,9 @@ void choose_next_clicked(GtkButton *button, void choose_prev_clicked(GtkButton *button, gpointer userdata); void choose_search_new(void); +void choose_menu_moretracks(const char *event, + void *eventdata, + void *callbackdata); #endif /* CHOOSE_H */ diff --git a/doc/disobedience.1.in b/doc/disobedience.1.in index 3e3d386..b174824 100644 --- a/doc/disobedience.1.in +++ b/doc/disobedience.1.in @@ -38,8 +38,11 @@ Terminates the program. .SS "Edit Menu" This has the following options: .TP -.B "Select All" -Select all tracks in whichever of the Queue or Recent tabs are showing. +.B "Select All Tracks" +Select all tracks. +.TP +.B "Deselect All Tracks" +Deselect all tracks. .TP .B Properties Edit the details of the selected tracks. @@ -134,9 +137,12 @@ See .B "Properties Window" below. .TP -.B "Select All" +.B "Select All Tracks" Select all tracks. .TP +.B "Deselect All Tracks" +Deselect all tracks. +.TP .B Scratch Interrupt the currently playing track. (Note that this appears even if you right click over a queued track rather @@ -157,8 +163,14 @@ See .B "Properties Window" below. .TP -.B "Select All" +.B "Play track" +Play the select track(s); +.TP +.B "Select All Tracks" Select all tracks. +.TP +.B "Deselect All Tracks" +Deselect all tracks. .SS "Choose Tab" This displays all the tracks known to the server in a tree structure. .PP @@ -204,11 +216,11 @@ Play all the tracks in the directory, in the order they appear on screen. .B "Track properties" Edit properties of all tracks in the directory. .TP -.B "Select all tracks" +.B "Select children" Select all the tracks in the directory (and deselect everything else). -.PP -Note that these options do not apply recursively - only the tracks in the -relevant directory are affected, not those in its subdirectories. +.TP +.B "Deselect all tracks" +Deselect everything. .SS "Added Tab" This displays a list of tracks recently added to the server's database. The most recently added track is at the top. @@ -229,6 +241,9 @@ Play selected tracks. .TP .B "Select All Tracks" Select all tracks. +.TP +.B "Deselect All Tracks" +Deselect all tracks. .SS "Login Details Window" The login details window allows you to edit the connection details and authorization information used by Disobedience.