diff --git a/redo/gtk_unix.h b/redo/gtk_unix.h index 48b9918..a857787 100644 --- a/redo/gtk_unix.h +++ b/redo/gtk_unix.h @@ -34,5 +34,6 @@ struct goTableModelClass { GObjectClass parent_class; }; extern goTableModel *newTableModel(void *); +extern void tableUpdate(goTableModel *, gint, gint); #endif diff --git a/redo/table_unix.c b/redo/table_unix.c index 6354ae7..9e1f4b6 100644 --- a/redo/table_unix.c +++ b/redo/table_unix.c @@ -41,13 +41,13 @@ static void goTableModel_dispose(GObject *obj) G_OBJECT_CLASS(goTableModel_parent_class)->dispose(obj); } -/* and now for the interface function definitions */ - static void goTableModel_finalize(GObject *obj) { G_OBJECT_CLASS(goTableModel_parent_class)->finalize(obj); } +/* and now for the interface function definitions */ + static GtkTreeModelFlags goTableModel_get_flags(GtkTreeModel *model) { return GTK_TREE_MODEL_LIST_ONLY; @@ -96,6 +96,9 @@ static void goTableModel_get_value(GtkTreeModel *model, GtkTreeIter *iter, gint /* TODO what if iter is invalid? */ /* we (actually cgo) allocated str with malloc(), not g_malloc(), so let's free it explicitly and give the GValue a copy to be safe */ str = goTableModel_do_get_value(t->gotable, (gint) iter->user_data, column); + /* value is uninitialized */ + /* TODO add support for multiple types */ + g_value_init(value, G_TYPE_STRING); g_value_set_string(value, str); free(str); } @@ -239,3 +242,38 @@ goTableModel *newTableModel(void *gotable) { return (goTableModel *) g_object_new(goTableModel_get_type(), "gotable", (gpointer) gotable, NULL); } + +/* somewhat naive, but the only alternatives seem to be unloading/reloading the model (or the view!), which is bleh */ +void tableUpdate(goTableModel *t, gint old, gint new) +{ + gint i; + gint nUpdate; + GtkTreePath *path; + GtkTreeIter iter; + + iter.stamp = GOOD_STAMP; + /* first, append extra items */ + if (old < new) { + for (i = old; i < new; i++) { + path = gtk_tree_path_new_from_indices(i, -1); + iter.user_data = (gpointer) i; + g_signal_emit_by_name(t, "row-inserted", path, &iter); + } + nUpdate = old; + } else + nUpdate = new; + /* next, update existing items */ + for (i = 0; i < nUpdate; i++) { + path = gtk_tree_path_new_from_indices(i, -1); + iter.user_data = (gpointer) i; + g_signal_emit_by_name(t, "row-updated", path, &iter); + } + /* finally, remove deleted items */ + if (old > new) + for (i = new; i < old; i++) { + /* note that we repeatedly remove the row at index new, as that changes with each removal; NOT i */ + path = gtk_tree_path_new_from_indices(new, -1); + /* row-deleted has no iter */ + g_signal_emit_by_name(t, "row-deleted", path); + } +} diff --git a/redo/table_unix.go b/redo/table_unix.go index 399ca3d..6ca0cec 100644 --- a/redo/table_unix.go +++ b/redo/table_unix.go @@ -13,6 +13,9 @@ import ( // #include "gtk_unix.h" import "C" +// TODOs +// - make column headers resizeable + type table struct { *widgetbase *tablebase @@ -28,6 +31,7 @@ type table struct { // stuff required by GtkTreeModel nColumns C.gint + old C.gint } func finishNewTable(b *tablebase, ty reflect.Type) Table { @@ -66,6 +70,11 @@ func (t *table) preferredSize(d *sizing) (width int, height int) { return int(r.width), int(r.height) } +func (t *table) Lock() { + t.tablebase.Lock() + d := reflect.Indirect(reflect.ValueOf(t.data)) + t.old = C.gint(d.Len()) +} func (t *table) Unlock() { t.unlock() @@ -73,7 +82,9 @@ func (t *table) Unlock() { // not sure about this one... t.RLock() defer t.RUnlock() - // TODO + d := reflect.Indirect(reflect.ValueOf(t.data)) + new := C.gint(d.Len()) + C.tableUpdate(t.model, t.old, new) } //export goTableModel_get_n_columns