chiark / gitweb /
Replace rather bizarre 'select all' in choose tab with 'select
authorRichard Kettlewell <rjk@greenend.org.uk>
Sun, 7 Dec 2008 20:20:51 +0000 (20:20 +0000)
committerRichard Kettlewell <rjk@greenend.org.uk>
Sun, 7 Dec 2008 20:20:51 +0000 (20:20 +0000)
children' which (after jumping through some hoops) selects just the
file children of the selected directory.

Updated the Disobedience documentation a bit.

CHANGES.html
disobedience/choose-menu.c
disobedience/choose.c
disobedience/choose.h
doc/disobedience.1.in

index 495d898..e8436a4 100644 (file)
@@ -58,7 +58,7 @@ span.command {
 <p>This file documents recent user-visible changes to <a
  href="http://www.greenend.org.uk/rjk/disorder/">DisOrder</a>.</p>
 
-<h2>Changes up to version XXX</h2>
+<h2>Changes up to version 4.3</h2>
 
   <div class=section>
 
@@ -73,6 +73,10 @@ span.command {
         <p>Disobedience's icons have been changed to larger, more colorful
         ones.  The SVG source is included if you want to fiddle with them.</p>
 
+        <p>&ldquo;Select all&rdquo; is now no longer available in the choose
+        tab.  Instead there is a new &ldquo;Select children&rdquo; option which
+        selects the file children of a single subdirectory.</p>
+
       </div>
 
     <h3>Server</h3>
index 37167e7..16aa593 100644 (file)
@@ -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
   },
index d1e9515..b9a9e7e 100644 (file)
@@ -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. */
index 97f7095..5213332 100644 (file)
@@ -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 */
 
index 3e3d386..b174824 100644 (file)
@@ -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.