/** @brief Count of file listing operations in flight */
static int choose_list_in_flight;
-/** @brief Count of files inserted in current batch of listing operations */
-static int choose_inserted;
+/** @brief If nonzero autocollapse column won't be set */
+static int choose_suppress_set_autocollapse;
static char *choose_get_string(GtkTreeIter *iter, int column) {
gchar *gs;
return choose_get_string(iter, TRACK_COLUMN)[0] == 0;
}
+int choose_can_autocollapse(GtkTreeIter *iter) {
+ gboolean autocollapse;
+ gtk_tree_model_get(GTK_TREE_MODEL(choose_store), iter,
+ AUTOCOLLAPSE_COLUMN, &autocollapse,
+ -1);
+ return autocollapse;
+}
+
/** @brief Remove node @p it and all its children
* @param Iterator, updated to point to next
* @return True if iterator remains valid
static void choose_populate(GtkTreeRowReference *parent_ref,
int nvec, char **vec,
int isfile) {
- if(!nvec)
- return;
const char *type = isfile ? "track" : "dir";
+ //fprintf(stderr, "%d new children of type %s\n", nvec, type);
+ if(!nvec)
+ goto skip;
/* Compute parent_* */
GtkTreeIter pit[1], *parent_it;
GtkTreePath *parent_path;
ISFILE_COLUMN, isfile,
TRACK_COLUMN, td->track,
SORT_COLUMN, td->sort,
+ AUTOCOLLAPSE_COLUMN, FALSE,
-1);
/* Update length and state; we expect this to kick off length lookups
* rather than necessarily get the right value the first time round. */
inserted, deleted_placeholder);*/
if(parent_ref) {
/* If we deleted a placeholder then we must re-expand the row */
- if(deleted_placeholder)
+ if(deleted_placeholder) {
+ ++choose_suppress_set_autocollapse;
gtk_tree_view_expand_row(GTK_TREE_VIEW(choose_view), parent_path, FALSE);
+ --choose_suppress_set_autocollapse;
+ }
gtk_tree_row_reference_free(parent_ref);
gtk_tree_path_free(parent_path);
}
+skip:
/* We only notify others that we've inserted tracks when there are no more
* insertions pending, so that they don't have to keep track of how many
* requests they've made. */
- choose_inserted += inserted;
if(--choose_list_in_flight == 0) {
/* Notify interested parties that we inserted some tracks, AFTER making
* sure that the row is properly expanded */
- if(choose_inserted) {
- event_raise("choose-inserted-tracks", parent_it);
- choose_inserted = 0;
- }
+ //fprintf(stderr, "raising choose-more-tracks\n");
+ event_raise("choose-more-tracks", 0);
}
+ //fprintf(stderr, "choose_list_in_flight -> %d-\n", choose_list_in_flight);
}
static void choose_dirs_completed(void *v,
path));
/* The row references are destroyed in the _completed handlers. */
choose_list_in_flight += 2;
+ //fprintf(stderr, "choose_list_in_flight -> %d+\n", choose_list_in_flight);
+ if(!choose_suppress_set_autocollapse) {
+ if(choose_auto_expanding) {
+ /* This was an automatic expansion; mark it the row for auto-collapse. */
+ gtk_tree_store_set(choose_store, iter,
+ AUTOCOLLAPSE_COLUMN, TRUE,
+ -1);
+ /*fprintf(stderr, "enable auto-collapse for %s\n",
+ gtk_tree_path_to_string(path));*/
+ } else {
+ /* This was a manual expansion. Inhibit automatic collapse on this row
+ * and all its ancestors. */
+ gboolean itv;
+ do {
+ gtk_tree_store_set(choose_store, iter,
+ AUTOCOLLAPSE_COLUMN, FALSE,
+ -1);
+ /*fprintf(stderr, "suppress auto-collapse for %s\n",
+ gtk_tree_model_get_string_from_iter(GTK_TREE_MODEL(choose_store),
+ iter));*/
+ GtkTreeIter child = *iter;
+ itv = gtk_tree_model_iter_parent(GTK_TREE_MODEL(choose_store),
+ iter,
+ &child);
+ } while(itv);
+ /* The effect of this is that if you expand a row that's actually a
+ * sibling of the real target of the auto-expansion, it stays expanded
+ * when you clear a search. That's find and good, but it _still_ stays
+ * expanded if you expand it and then collapse it.
+ *
+ * An alternative policy would be to only auto-collapse rows that don't
+ * have any expanded children (apart from ones also subject to
+ * auto-collapse). I'm not sure what the most usable policy is.
+ */
+ }
+ }
+}
+
+static void choose_auto_collapse_callback(GtkTreeView *tree_view,
+ GtkTreePath *path,
+ gpointer attribute((unused)) user_data) {
+ GtkTreeIter it[1];
+
+ gtk_tree_model_get_iter(GTK_TREE_MODEL(choose_store), it, path);
+ if(choose_can_autocollapse(it)) {
+ /*fprintf(stderr, "collapse %s\n",
+ gtk_tree_path_to_string(path));*/
+ gtk_tree_store_set(choose_store, it,
+ AUTOCOLLAPSE_COLUMN, FALSE,
+ -1);
+ gtk_tree_view_collapse_row(tree_view, path);
+ }
+}
+
+/** @brief Perform automatic collapse after a search is cleared */
+void choose_auto_collapse(void) {
+ gtk_tree_view_map_expanded_rows(GTK_TREE_VIEW(choose_view),
+ choose_auto_collapse_callback,
+ 0);
}
/** @brief Create the choose tab */
G_TYPE_STRING,
G_TYPE_STRING,
G_TYPE_STRING,
- G_TYPE_STRING);
+ G_TYPE_STRING,
+ G_TYPE_BOOLEAN);
/* Create the view */
choose_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(choose_store));
/* Fill the root */
disorder_eclient_files(client, choose_files_completed, "", NULL, NULL);
disorder_eclient_dirs(client, choose_dirs_completed, "", NULL, NULL);
+ choose_list_in_flight += 2;
+ //fprintf(stderr, "choose_list_in_flight -> %d+\n", choose_list_in_flight);
/* Make the widget scrollable */
GtkWidget *scrolled = scroll_widget(choose_view);