Summary
Gtk.CustomSorter's compare callback receives undefined for both items it is supposed to compare, so the sorter can never order anything. Any GtkSortListModel driven by a CustomSorter silently keeps the model's original order.
The root cause appears to be that GtkCustomSortFunc is declared as
int (*GtkCustomSortFunc) (gconstpointer a, gconstpointer b, gpointer user_data);
i.e. the two items are untyped gconstpointers. With no GI type information for a/b, node-gtk passes undefined into the JS callback instead of wrapping the underlying GObjects.
Reproduction
const gi = require('node-gtk');
const Gtk = gi.require('Gtk', '4.0');
Gtk.init();
const list = Gtk.StringList.new(['banana', 'apple', 'cherry']);
let firstArgs = null;
const sorter = Gtk.CustomSorter.new((a, b) => {
if (!firstArgs) firstArgs = [a, b];
const av = a && a.getString ? a.getString() : a;
const bv = b && b.getString ? b.getString() : b;
return av < bv ? -1 : av > bv ? 1 : 0;
});
const sorted = Gtk.SortListModel.new(list, sorter);
console.log('callback first args:', firstArgs);
const out = [];
for (let i = 0; i < sorted.getNItems(); i++) out.push(sorted.getItem(i).getString());
console.log('result order:', out.join(', '));
Actual
callback first args: [ undefined, undefined ]
result order: banana, apple, cherry
Expected
a and b should be the GtkStringObject items being compared, and the result should be apple, banana, cherry.
Impact
CustomSorter is the only GtkSorter that takes a plain compare function; the expression-based sorters (StringSorter/NumericSorter) require a GtkExpression, and ClosureExpression.new wants a real GObject.Closure rather than a JS function. So there is currently no working way to do a custom sort (e.g. "directories first, then by name" for a file tree) from JS. The practical workaround is to sort in JS and feed a Gio.ListStore.
The same limitation presumably affects any callback whose arguments are untyped gpointer/gconstpointer (e.g. GCompareDataFunc, GtkMapListModel map funcs returning into untyped slots, etc.).
Environment
- node-gtk 2.0.0
- node v22.22.3
- GTK 4.22.4, GLib 2.88.1
Summary
Gtk.CustomSorter's compare callback receivesundefinedfor both items it is supposed to compare, so the sorter can never order anything. AnyGtkSortListModeldriven by aCustomSortersilently keeps the model's original order.The root cause appears to be that
GtkCustomSortFuncis declared asi.e. the two items are untyped
gconstpointers. With no GI type information fora/b, node-gtk passesundefinedinto the JS callback instead of wrapping the underlyingGObjects.Reproduction
Actual
Expected
aandbshould be theGtkStringObjectitems being compared, and the result should beapple, banana, cherry.Impact
CustomSorteris the onlyGtkSorterthat takes a plain compare function; the expression-based sorters (StringSorter/NumericSorter) require aGtkExpression, andClosureExpression.newwants a realGObject.Closurerather than a JS function. So there is currently no working way to do a custom sort (e.g. "directories first, then by name" for a file tree) from JS. The practical workaround is to sort in JS and feed aGio.ListStore.The same limitation presumably affects any callback whose arguments are untyped
gpointer/gconstpointer(e.g.GCompareDataFunc,GtkMapListModelmap funcs returning into untyped slots, etc.).Environment