+
+ /* Now every row's secret column is right, but we might be missing new rows
+ * and they might be in the wrong order */
+
+ /* We're going to have to support arbitrary rearrangements, so we might as
+ * well add new elements at the end. */
+ //fprintf(stderr, "%s: adding rows...\n", ql->name);
+ struct queue_entry *after = 0;
+ for(struct queue_entry *q = newq; q; q = q->next) {
+ const struct newqueue_data *nqd = hash_find(h, q->id);
+ if(!nqd->old) {
+ GtkTreeIter iter[1];
+ if(after) {
+ /* Try to insert at the right sort of place */
+ GtkTreeIter where[1];
+ gboolean wit = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(ql->store),
+ where);
+ while(wit && ql_iter_to_q(GTK_TREE_MODEL(ql->store), where) != after)
+ wit = gtk_tree_model_iter_next(GTK_TREE_MODEL(ql->store), where);
+ if(wit)
+ gtk_list_store_insert_after(ql->store, iter, where);
+ else
+ gtk_list_store_append(ql->store, iter);
+ } else
+ gtk_list_store_prepend(ql->store, iter);
+ gtk_list_store_set(ql->store, iter, ql->ncolumns, q, -1);
+ //fprintf(stderr, " add %s", q->id);
+ ++inserted;
+ }
+ after = newq;
+ }
+
+ /* Now exactly the right set of rows are present, and they have the right
+ * queue_entry pointers in their secret column, but they may be in the wrong
+ * order.
+ *
+ * The current code is simple but amounts to a bubble-sort - we might easily
+ * called gtk_tree_model_iter_next a couple of thousand times.
+ */
+ //fprintf(stderr, "%s: rearranging rows\n", ql->name);
+ //fprintf(stderr, "%s: queue state: ", ql->name);
+ //dump_queue(newq, 0);
+ //fprintf(stderr, "%s: row state: ", ql->name);
+ //dump_rows(ql);
+ it = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(ql->store),
+ iter);
+ struct queue_entry *rq = newq; /* r for 'right, correct' */
+ int swaps = 0, searches = 0;
+ while(it) {
+ struct queue_entry *q = ql_iter_to_q(GTK_TREE_MODEL(ql->store), iter);
+ //fprintf(stderr, " rq = %p, q = %p\n", rq, q);
+ //fprintf(stderr, " rq->id = %s, q->id = %s\n", rq->id, q->id);
+
+ if(q != rq) {
+ //fprintf(stderr, " mismatch\n");
+ GtkTreeIter next[1] = { *iter };
+ gboolean nit = gtk_tree_model_iter_next(GTK_TREE_MODEL(ql->store), next);
+ while(nit) {
+ struct queue_entry *nq = ql_iter_to_q(GTK_TREE_MODEL(ql->store), next);
+ //fprintf(stderr, " candidate: %s\n", nq->id);
+ if(nq == rq)
+ break;
+ nit = gtk_tree_model_iter_next(GTK_TREE_MODEL(ql->store), next);
+ ++searches;
+ }
+ assert(nit);
+ //fprintf(stderr, " found it\n");
+ gtk_list_store_swap(ql->store, iter, next);
+ *iter = *next;
+ //fprintf(stderr, "%s: new row state: ", ql->name);
+ //dump_rows(ql);
+ ++swaps;
+ }
+ /* ...and onto the next one */
+ it = gtk_tree_model_iter_next(GTK_TREE_MODEL(ql->store), iter);
+ rq = rq->next;
+ }
+#if 0
+ fprintf(stderr, "%6s: %3d kept %3d inserted %3d deleted %3d swaps %4d searches\n", ql->name,
+ kept, inserted, deleted, swaps, searches);
+#endif
+ //fprintf(stderr, "done\n");
+ ql->q = newq;
+ /* Set the rest of the columns in new rows */
+ ql_update_list_store(ql);