* TODO:
* - sweep up contracted nodes
* - update when content may have changed (e.g. after a rescan)
- * - popup menu (partially implemented now)
- * - playing state
- * - display length of tracks
*/
#include "disobedience.h"
return cd;
}
+struct choosedata *choose_path_to_data(GtkTreePath *path) {
+ GtkTreeIter it[1];
+ gboolean itv = gtk_tree_model_get_iter(GTK_TREE_MODEL(choose_store),
+ it, path);
+ assert(itv);
+ return choose_iter_to_data(it);
+}
+
/** @brief Remove node @p it and all its children
* @param Iterator, updated to point to next
* @return True if iterator remains valid
return gtk_tree_store_remove(choose_store, it);
}
+/** @brief Update length and state fields */
+static gboolean choose_set_state_callback(GtkTreeModel attribute((unused)) *model,
+ GtkTreePath attribute((unused)) *path,
+ GtkTreeIter *it,
+ gpointer attribute((unused)) data) {
+ struct choosedata *cd = choose_iter_to_data(it);
+ if(!cd)
+ return FALSE; /* Skip placeholders*/
+ if(cd->type == CHOOSE_FILE) {
+ const long l = namepart_length(cd->track);
+ char length[64];
+ if(l > 0)
+ byte_snprintf(length, sizeof length, "%ld:%02ld", l / 60, l % 60);
+ else
+ length[0] = 0;
+ gtk_tree_store_set(choose_store, it,
+ LENGTH_COLUMN, length,
+ STATE_COLUMN, queued(cd->track),
+ -1);
+ }
+ return FALSE; /* continue walking */
+}
+
+/** @brief Called when the queue or playing track change */
+static void choose_set_state(const char attribute((unused)) *event,
+ void attribute((unused)) *eventdata,
+ void attribute((unused)) *callbackdata) {
+ gtk_tree_model_foreach(GTK_TREE_MODEL(choose_store),
+ choose_set_state_callback,
+ NULL);
+}
+
/** @brief (Re-)populate a node
* @param parent_ref Node to populate or NULL to fill root
* @param nvec Number of children to add
"display"),
CHOOSEDATA_COLUMN, cd,
-1);
+ /* Update length and state; we expect this to kick off length lookups
+ * rather than necessarily get the right value the first time round. */
+ choose_set_state_callback(0, 0, it, 0);
++inserted;
/* If we inserted a directory, insert a placeholder too, so it appears to
* have children; it will be deleted when we expand the directory. */
GtkWidget *choose_widget(void) {
/* Create the tree store. */
choose_store = gtk_tree_store_new(1 + CHOOSEDATA_COLUMN,
+ G_TYPE_BOOLEAN,
+ G_TYPE_STRING,
G_TYPE_STRING,
G_TYPE_POINTER);
/* Create the view */
choose_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(choose_store));
+ gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(choose_view), TRUE);
/* Create cell renderers and columns */
- GtkCellRenderer *r = gtk_cell_renderer_text_new();
- GtkTreeViewColumn *c = gtk_tree_view_column_new_with_attributes
- ("Track",
- r,
- "text", 0,
- (char *)0);
- gtk_tree_view_append_column(GTK_TREE_VIEW(choose_view), c);
+ /* TODO use a table */
+ {
+ GtkCellRenderer *r = gtk_cell_renderer_text_new();
+ GtkTreeViewColumn *c = gtk_tree_view_column_new_with_attributes
+ ("Track",
+ r,
+ "text", NAME_COLUMN,
+ (char *)0);
+ gtk_tree_view_column_set_resizable(c, TRUE);
+ gtk_tree_view_column_set_reorderable(c, TRUE);
+ g_object_set(c, "expand", TRUE, (char *)0);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(choose_view), c);
+ }
+ {
+ GtkCellRenderer *r = gtk_cell_renderer_text_new();
+ GtkTreeViewColumn *c = gtk_tree_view_column_new_with_attributes
+ ("Length",
+ r,
+ "text", LENGTH_COLUMN,
+ (char *)0);
+ gtk_tree_view_column_set_resizable(c, TRUE);
+ gtk_tree_view_column_set_reorderable(c, TRUE);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(choose_view), c);
+ }
+ {
+ GtkCellRenderer *r = gtk_cell_renderer_toggle_new();
+ GtkTreeViewColumn *c = gtk_tree_view_column_new_with_attributes
+ ("Queued",
+ r,
+ "active", STATE_COLUMN,
+ (char *)0);
+ gtk_tree_view_column_set_resizable(c, TRUE);
+ gtk_tree_view_column_set_reorderable(c, TRUE);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(choose_view), c);
+ /* TODO make checkbox clickable to queue the track */
+ }
/* The selection should support multiple things being selected */
choose_selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(choose_view));
/* Catch row expansions so we can fill in placeholders */
g_signal_connect(choose_view, "row-expanded",
G_CALLBACK(choose_row_expanded), 0);
+
+ event_register("queue-list-changed", choose_set_state, 0);
+ event_register("playing-track-changed", choose_set_state, 0);
/* Fill the root */
disorder_eclient_files(client, choose_files_completed, "", NULL, NULL);