summaryrefslogtreecommitdiff
path: root/redo/table_unix.c
blob: 0bd84de758d38ff84a1b9a4e94e995c3ee41cfea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
/* 29 july 2014 */

#include "gtk_unix.h"
#include "_cgo_export.h"

void tableAppendColumn(GtkTreeView *table, gint index, gchar *name)
{
	GtkTreeViewColumn *col;
	GtkCellRenderer *renderer;

	renderer = gtk_cell_renderer_text_new();
	col = gtk_tree_view_column_new_with_attributes(name, renderer,
		"text", index,
		NULL);
	gtk_tree_view_append_column(table, col);
}

/*
how our GtkTreeIters are stored:
	stamp: either GOOD_STAMP or BAD_STAMP
	user_data: row index
TODO verify range of gint
*/
#define GOOD_STAMP 0x1234
#define BAD_STAMP 0x5678

static void goTableModel_initGtkTreeModel(GtkTreeModelIface *);

G_DEFINE_TYPE_WITH_CODE(goTableModel, goTableModel, G_TYPE_OBJECT,
	G_IMPLEMENT_INTERFACE(GTK_TYPE_TREE_MODEL, goTableModel_initGtkTreeModel))

static void goTableModel_init(goTableModel *t)
{
	/* do nothing */
}

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);
}

static GtkTreeModelFlags goTableModel_get_flags(GtkTreeModel *model)
{
	return GTK_TREE_MODEL_LIST_ONLY;
}

/* get_n_columns in Go */

static GType goTableModel_get_column_type(GtkTreeModel *model, gint column)
{
	/* TODO change when we get more column types */
	return G_TYPE_STRING;
}

static gboolean goTableModel_get_iter(GtkTreeModel *model, GtkTreeIter *iter, GtkTreePath *path)
{
	goTableModel *t = (goTableModel *) model;
	gint index;

	if (gtk_tree_path_get_depth(path) != 1)
		goto bad;
	index = gtk_tree_path_get_indices(path)[0];
	if (index < 0)
		goto bad;
	if (index >= goTableModel_getRowCount(t->gotable))
		goto bad;
	iter->stamp = GOOD_STAMP;
	iter->user_data = (gpointer) index;
	return TRUE;
bad:
	iter->stamp = BAD_STAMP;
	return FALSE;
}

static GtkTreePath *goTableModel_get_path(GtkTreeModel *model, GtkTreeIter *iter)
{
	if (iter->stamp != GOOD_STAMP)
		return NULL;		/* TODO is this right? */
	return gtk_tree_path_new_from_indices((gint) iter->user_data, -1);
}

static void goTableModel_get_value(GtkTreeModel *model, GtkTreeIter *iter, gint column, GValue *value)
{
	goTableModel *t = (goTableModel *) model;
	gchar *str;

	/* 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);
	g_value_set_string(value, str);
	free(str);
}

static gboolean goTableModel_iter_next(GtkTreeModel *model, GtkTreeIter *iter)
{
	goTableModel *t = (goTableModel *) model;
	gint index;

	if (iter->stamp != GOOD_STAMP)
		return FALSE;		/* TODO correct? */
	index = (gint) iter->user_data;
	index++;
	iter->user_data = (gpointer) index;
	if (index >= goTableModel_getRowCount(t->gotable)) {
		iter->stamp = BAD_STAMP;
		return FALSE;
	}
	return TRUE;
}

static gboolean goTableModel_iter_previous(GtkTreeModel *model, GtkTreeIter *iter)
{
	goTableModel *t = (goTableModel *) model;
	gint index;

	if (iter->stamp != GOOD_STAMP)
		return FALSE;		/* TODO correct? */
	index = (gint) iter->user_data;
	index--;
	iter->user_data = (gpointer) index;
	if (index < 0) {
		iter->stamp = BAD_STAMP;
		return FALSE;
	}
	return TRUE;
}

static gboolean goTableModel_iter_children(GtkTreeModel *model, GtkTreeIter *child, GtkTreeIter *parent)
{
	goTableModel *t = (goTableModel *) model;

	if (parent == NULL && goTableModel_getRowCount(t->gotable) > 0) {
		child->stamp = GOOD_STAMP;
		child->user_data = 0;
		return TRUE;
	}
	child->stamp = BAD_STAMP;
	return FALSE;
}

static gboolean goTableModel_iter_has_child(GtkTreeModel *model, GtkTreeIter *iter)
{
	return FALSE;
}

static gint goTableModel_iter_n_children(GtkTreeModel *model, GtkTreeIter *iter)
{
	goTableModel *t = (goTableModel *) model;

	if (iter == NULL)
		return goTableModel_getRowCount(t->gotable);
	return 0;
}

static gboolean goTableModel_iter_nth_child(GtkTreeModel *model, GtkTreeIter *child, GtkTreeIter *parent, gint n)
{
	goTableModel *t = (goTableModel *) model;

	if (parent == NULL && n >= 0 && n < goTableModel_getRowCount(t->gotable)) {
		child->stamp = GOOD_STAMP;
		child->user_data = (gpointer) n;
		return TRUE;
	}
	child->stamp = BAD_STAMP;
	return FALSE;
}

static gboolean goTableModel_iter_parent(GtkTreeModel *model, GtkTreeIter *parent, GtkTreeIter *child)
{
	parent->stamp = BAD_STAMP;
	return FALSE;
}

/* end of interface definitions */

static void goTableModel_initGtkTreeModel(GtkTreeModelIface *interface)
{
	/* don't chain; we have nothing to chain to */
#define DEF(x) interface->x = goTableModel_ ## x;
	DEF(get_flags)
	DEF(get_n_columns)
	DEF(get_column_type)
	DEF(get_iter)
	DEF(get_path)
	DEF(get_value)
	DEF(iter_next)
	DEF(iter_previous)
	DEF(iter_children)
	DEF(iter_has_child)
	DEF(iter_n_children)
	DEF(iter_nth_child)
	DEF(iter_parent)
	/* no need for ref_node and unref_node */
}

static GParamSpec *goTableModelProperties[2];

static void goTableModel_set_property(GObject *obj, guint id, const GValue *value, GParamSpec *pspec)
{
	goTableModel *t = (goTableModel *) obj;

	if (id == 1) {
		t->gotable = (void *) g_value_get_pointer(value);
		return;
	}
	G_OBJECT_WARN_INVALID_PROPERTY_ID(t, id, pspec);
}

static void goTableModel_get_property(GObject *obj, guint id, GValue *value, GParamSpec *pspec)
{
	G_OBJECT_WARN_INVALID_PROPERTY_ID((goTableModel *) obj, id, pspec);
}

static void goTableModel_class_init(goTableModelClass *class)
{
	G_OBJECT_CLASS(class)->dispose = goTableModel_dispose;
	G_OBJECT_CLASS(class)->finalize = goTableModel_finalize;
	G_OBJECT_CLASS(class)->set_property = goTableModel_set_property;
	G_OBJECT_CLASS(class)->get_property = goTableModel_get_property;

	goTableModelProperties[1] = g_param_spec_pointer(
		"gotable",
		"go-table",
		"Go-side *table value",
		G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
	g_object_class_install_properties(G_OBJECT_CLASS(class), 2, goTableModelProperties);
}

goTableModel *newTableModel(void *gotable)
{
	return (goTableModel *) g_object_new(goTableModel_get_type(), "gotable", (gpointer) gotable, NULL);
}