1 /*
2  * Copyright (c) 2003-2006, 2009 by the gtk2-perl team (see the file AUTHORS)
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA  02110-1301  USA.
18  *
19  * $Id$
20  */
21 
22 #include "gtk2perl.h"
23 
24 MODULE = Gtk2::TreeStore	PACKAGE = Gtk2::TreeStore	PREFIX = gtk_tree_store_
25 
26 BOOT:
27 	/* must prepend TreeModel in the hierarchy so that
28 	 * Gtk2::TreeModel::get isn't masked by Glib::Object::get.
29 	 * should we change the api to something unique, instead? */
30 	gperl_prepend_isa ("Gtk2::TreeStore", "Gtk2::TreeModel");
31 
32 ## GtkTreeStore* gtk_tree_store_new (gint n_columns, ...);
33 =for apidoc
34 =for arg ... of strings, package names
35 =cut
36 GtkTreeStore_noinc*
37 gtk_tree_store_new (class, ...)
38     PREINIT:
39 	GArray * typearray;
40     CODE:
41 	GTK2PERL_STACK_ITEMS_TO_GTYPE_ARRAY (typearray, 1, items-1);
42 	RETVAL = gtk_tree_store_newv (typearray->len, (GType*)(typearray->data));
43 	g_array_free (typearray, TRUE);
44     OUTPUT:
45 	RETVAL
46 
47 
48 # for initializing GtkTreeStores derived in perl.
49 ## void gtk_tree_store_set_column_types (GtkTreeStore *tree_store, gint n_columns, GType *types)
50 =for apidoc
51 =for arg ... of strings, package names
52 =cut
53 void
54 gtk_tree_store_set_column_types (tree_store, ...)
55 	GtkTreeStore *tree_store
56     PREINIT:
57 	GArray * types;
58     CODE:
59 	GTK2PERL_STACK_ITEMS_TO_GTYPE_ARRAY (types, 1, items-1);
60 	gtk_tree_store_set_column_types (tree_store, types->len,
61 	                                 (GType*)(types->data));
62 
63 ## void gtk_tree_store_set (GtkTreeStore *tree_store, GtkTreeIter *iter, ...)
64 =for apidoc Gtk2::TreeStore::set_value
65 =for arg col1 (integer) the first column number
66 =for arg val1 (scalar) the first value
67 =for arg ... pairs of columns and values
68 Alias for Gtk2::TreeStore::set().
69 =cut
70 
71 =for apidoc
72 =for arg col1 (integer) the first column number
73 =for arg val1 (scalar) the first value
74 =for arg ... pairs of columns and values
75 =cut
76 void
77 gtk_tree_store_set (tree_store, iter, col1, val1, ...)
78 	GtkTreeStore *tree_store
79 	GtkTreeIter *iter
80     ALIAS:
81 	Gtk2::TreeStore::set_value = 1
82     PREINIT:
83 	int i, ncols;
84     CODE:
85 	PERL_UNUSED_VAR (ix);
86 	/* require at least one pair --- that means there needs to be
87 	 * four items on the stack.  also require that the stack has an
88 	 * even number of items on it. */
89 	if (items < 4 || 0 != (items % 2)) {
90 		/* caller didn't specify an even number of parameters... */
91 		croak ("Usage: $treestore->set ($iter, column1, value1, column2, value2, ...)\n"
92 		       "   there must be a value for every column number");
93 	}
94 	ncols = gtk_tree_model_get_n_columns (GTK_TREE_MODEL (tree_store));
95 	for (i = 2 ; i < items ; i+= 2) {
96 		gint column;
97 		GValue gvalue = {0, };
98 		if (!looks_like_number (ST (i)))
99 			croak ("Usage: $treestore->set ($iter, column1, value1, column2, value2, ...)\n"
100 			       "   the first value in each pair must be a column number");
101 		column = SvIV (ST (i));
102 
103 		if (column >= 0 && column < ncols) {
104 
105 			g_value_init (&gvalue,
106 			              gtk_tree_model_get_column_type
107 			                          (GTK_TREE_MODEL (tree_store),
108 			                           column));
109 			/* gperl_value_from_sv either succeeds or croaks. */
110 			gperl_value_from_sv (&gvalue, ST (i+1));
111 			gtk_tree_store_set_value (GTK_TREE_STORE (tree_store),
112 			                          iter, column, &gvalue);
113 			g_value_unset (&gvalue);
114 
115 		} else {
116 			warn ("can't set value for column %d, model only has %d columns",
117 			      column, ncols);
118 		}
119 	}
120 
121 ### we're trying to hide things like GValue from the perl level!
122 ## void gtk_tree_store_set_value (GtkTreeStore *tree_store, GtkTreeIter *iter, gint column, GValue *value)
123 ## see Gtk2::TreeStore::set instead
124 ## void gtk_tree_store_set_valist (GtkTreeStore *tree_store, GtkTreeIter *iter, va_list var_args)
125 
126 ## gboolean gtk_tree_store_remove (GtkTreeStore *tree_store, GtkTreeIter *iter)
127 =for apidoc
128 The return is always a boolean in the style of Gtk 2.2.x and up, even
129 when running on Gtk 2.0.x.
130 =cut
131 gboolean
132 gtk_tree_store_remove (tree_store, iter)
133 	GtkTreeStore *tree_store
134 	GtkTreeIter *iter
135     CODE:
136 #if GTK_CHECK_VERSION(2,2,0)
137 	RETVAL = gtk_tree_store_remove (tree_store, iter);
138 #else
139 	/* void return in 2.0.x; look for stamp zapped to 0 if no more
140 	 * rows, to emulate the return value of 2.2 and up
141 	 */
142 	gtk_tree_store_remove (tree_store, iter);
143 	RETVAL = (iter->stamp != 0);
144 #endif
145     OUTPUT:
146 	RETVAL
147 
148 ## void gtk_tree_store_insert (GtkTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *parent, gint position)
149 GtkTreeIter_copy *
150 gtk_tree_store_insert (tree_store, parent, position)
151 	GtkTreeStore       * tree_store
152 	GtkTreeIter_ornull * parent
153 	gint                 position
154     PREINIT:
155 	GtkTreeIter iter = {0, };
156     CODE:
157 	gtk_tree_store_insert (tree_store, &iter, parent, position);
158 	RETVAL = &iter;
159     OUTPUT:
160 	RETVAL
161 
162 ## void gtk_tree_store_insert_before (GtkTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *parent, GtkTreeIter *sibling)
163 ## void gtk_tree_store_insert_after (GtkTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *parent, GtkTreeIter *sibling)
164 GtkTreeIter_copy *
165 gtk_tree_store_insert_before (tree_store, parent, sibling)
166 	GtkTreeStore       * tree_store
167 	GtkTreeIter_ornull * parent
168 	GtkTreeIter_ornull * sibling
169     ALIAS:
170 	Gtk2::TreeStore::insert_after = 1
171     PREINIT:
172 	GtkTreeIter iter;
173     CODE:
174 	if (ix == 0)
175 		gtk_tree_store_insert_before (tree_store, &iter,
176 		                              parent, sibling);
177 	else
178 		gtk_tree_store_insert_after (tree_store, &iter,
179 		                             parent, sibling);
180 	RETVAL = &iter;
181     OUTPUT:
182 	RETVAL
183 
184 ## void gtk_tree_store_prepend (GtkTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *parent)
185 ## void gtk_tree_store_append (GtkTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *parent)
186 GtkTreeIter_copy *
187 gtk_tree_store_prepend (tree_store, parent)
188 	GtkTreeStore *tree_store
189 	GtkTreeIter_ornull *parent
190     ALIAS:
191 	Gtk2::TreeStore::append = 1
192     PREINIT:
193 	GtkTreeIter iter;
194     CODE:
195 	if (ix == 0)
196 		gtk_tree_store_prepend (tree_store, &iter, parent);
197 	else
198 		gtk_tree_store_append (tree_store, &iter, parent);
199 	RETVAL = &iter;
200     OUTPUT:
201 	RETVAL
202 
203 ## gboolean gtk_tree_store_is_ancestor (GtkTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *descendant)
204 gboolean
205 gtk_tree_store_is_ancestor (tree_store, iter, descendant)
206 	GtkTreeStore *tree_store
207 	GtkTreeIter *iter
208 	GtkTreeIter *descendant
209 
210 ## gint gtk_tree_store_iter_depth (GtkTreeStore *tree_store, GtkTreeIter *iter)
211 gint
212 gtk_tree_store_iter_depth (tree_store, iter)
213 	GtkTreeStore *tree_store
214 	GtkTreeIter *iter
215 
216 ## void gtk_tree_store_clear (GtkTreeStore *tree_store)
217 void
218 gtk_tree_store_clear (tree_store)
219 	GtkTreeStore *tree_store
220 
221 #if GTK_CHECK_VERSION(2,2,0)
222 
223 ## warning, slow, use only for debugging
224 ## gboolean gtk_tree_store_iter_is_valid (GtkTreeStore *tree_store, GtkTreeIter *iter)
225 gboolean
226 gtk_tree_store_iter_is_valid (tree_store, iter)
227 	GtkTreeStore *tree_store
228 	GtkTreeIter *iter
229 
230 #### void gtk_tree_store_reorder (GtkTreeStore *tree_store, GtkTreeIter *parent, gint *new_order)
231 =for apidoc
232 =for arg ... of integer's, the new_order
233 =cut
234 void
235 gtk_tree_store_reorder (tree_store, parent, ...)
236 	GtkTreeStore       * tree_store
237 	GtkTreeIter_ornull * parent
238    PREINIT:
239 	gint  * new_order;
240 	GNode * level;
241 	GNode * node;
242 	int     length = 0;
243 	int     i;
244    CODE:
245 	if( !parent )
246 		level = ((GNode*)(tree_store->root))->children;
247 	else
248 		level = ((GNode*)(parent->user_data))->children;
249 	/* count nodes */
250 	node = level;
251 	while (node)
252 	{
253 		length++;
254 		node = node->next;
255 	}
256 	if( (items-2) != length )
257 		croak("xs: gtk_tree_store_reorder: wrong number of "
258 		      "positions passed");
259 	new_order = (gint*)g_new(gint, length);
260 	for (i = 0 ; i < length ; i++)
261 		new_order[i] = SvIV (ST (i+2));
262 	gtk_tree_store_reorder(tree_store, parent, new_order);
263 	g_free(new_order);
264 
265 ## void gtk_tree_store_swap (GtkTreeStore *tree_store, GtkTreeIter *a, GtkTreeIter *b)
266 void
267 gtk_tree_store_swap (tree_store, a, b)
268 	GtkTreeStore *tree_store
269 	GtkTreeIter *a
270 	GtkTreeIter *b
271 
272 ## void gtk_tree_store_move_before (GtkTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *position)
273 void
274 gtk_tree_store_move_before (tree_store, iter, position)
275 	GtkTreeStore *tree_store
276 	GtkTreeIter *iter
277 	GtkTreeIter_ornull *position
278 
279 ## void gtk_tree_store_move_after (GtkTreeStore *tree_store, GtkTreeIter *iter, GtkTreeIter *position)
280 void
281 gtk_tree_store_move_after (tree_store, iter, position)
282 	GtkTreeStore *tree_store
283 	GtkTreeIter *iter
284 	GtkTreeIter_ornull *position
285 
286 #endif /* >= 2.2.0 */
287 
288 #if GTK_CHECK_VERSION (2, 10, 0)
289 
290 =for apidoc
291 =for arg position position to insert the new row
292 =for arg ... pairs of column numbers and values
293 Like doing insert followed by set, except that insert_with_values emits only
294 the row-inserted signal, rather than row-inserted, row-changed, and, if the
295 store is sorted, rows-reordered as in the multiple-operation case.
296 Since emitting the rows-reordered signal repeatedly can affect the performance
297 of the program, insert_with_values should generally be preferred when
298 inserting rows in a sorted tree store.
299 =cut
300 GtkTreeIter_copy *
301 gtk_tree_store_insert_with_values (GtkTreeStore *tree_store, GtkTreeIter_ornull *parent, gint position, ...);
302     PREINIT:
303 	gint n_cols, i;
304 	GtkTreeIter iter;
305 	gint * columns = NULL;
306 	GValue * values = NULL;
307 	gint n_values;
308 	const char * errfmt = "Usage: $iter = $treestore->insert_with_values ($parent, $position, column1, value1, ...)\n     %s";
309     CODE:
310 	if (items < 3 || 0 != ((items - 3) % 2))
311 		croak (errfmt, "There must be a value for every column number");
312 	/*
313 	 * we could jump through hoops to prevent leaking arrays and
314 	 * initialized GValues here on column validation croaks, but
315 	 * since gperl_value_from_sv() croaks (and we can't catch it
316 	 * without major work), and since column index validation errors
317 	 * mean there's a programming error anyway, we won't worry about
318 	 * any of that.
319 	 */
320 	n_cols = gtk_tree_model_get_n_columns (GTK_TREE_MODEL (tree_store));
321 	n_values = (items - 3) / 2;
322 	if (n_values > 0) {
323 		columns = gperl_alloc_temp (sizeof (gint) * n_values);
324 		/* gperl_alloc_temp() calls memset(), so we don't need to do
325 		 * anything else special to prepare these GValues. */
326 		values = gperl_alloc_temp (sizeof (GValue) * n_values);
327 		for (i = 0 ; i < n_values ; i ++) {
328 			if (! looks_like_number (ST (3 + i*2)))
329 				croak (errfmt, "The first value in each pair must be a column index number");
330 			columns[i] = SvIV (ST (3 + i*2));
331 			if (! (columns[i] >= 0 && columns[i] < n_cols))
332 				croak (errfmt, form ("Bad column index %d, model only has %d columns",
333 						     columns[i], n_cols));
334 			g_value_init (values + i,
335 			              gtk_tree_model_get_column_type
336 			                        (GTK_TREE_MODEL (tree_store),
337 			                         columns[i]));
338 			gperl_value_from_sv (values + i, ST (3 + i*2 + 1));
339 		}
340 	}
341 	gtk_tree_store_insert_with_valuesv (tree_store, &iter, parent, position,
342 					    columns, values, n_values);
343 	for (i = 0 ; i < n_values ; i++)
344 		g_value_unset (values + i);
345 	RETVAL = &iter;
346     OUTPUT:
347 	RETVAL
348 
349 #endif /* 2.10 */
350