/src/wrappers/gtk/examples/tree/tree_demo.e

http://github.com/tybor/Liberty · Specman e · 644 lines · 209 code · 101 blank · 334 comment · 8 complexity · ff65467ed6ce1f35c20fbe00d4b29d60 MD5 · raw file

  1. indexing
  2. description: "Tree example translated to Eiffel from C"
  3. copyright: "Copyright (c) 2003-2004 Tim-Philipp M?ller <tim at centricular dot net>, Copyright (c) 2005, Paolo Redaelli"
  4. license: "LGPL v2 or later"
  5. date: "$Date:$"
  6. revision: "$Revision:$"
  7. original_version_url: "http://scentric.net/tutorial/treeview-tutorial.html"
  8. class TREE_DEMO
  9. -- Tree and List Widget Overview -- Overview of GtkTreeModel,
  10. -- GtkTreeView, and other associated widgets
  11. -- Overview: To create a tree or list in GTK+, use the GtkTreeModel
  12. -- interface in conjunction with the GtkTreeView widget. This
  13. -- widget is designed around a Model/View/Controller design and
  14. -- consists of four major parts:
  15. -- The tree view widget (GtkTreeView)
  16. -- The view column (GtkTreeViewColumn)
  17. -- The cell renderers (GtkCellRenderer etc.)
  18. -- The model interface (GtkTreeModel)
  19. -- The View is composed of the first three objects, while the last
  20. -- is the Model. One of the prime benefits of the MVC design is
  21. -- that multiple views can be created of a single model. For
  22. -- example, a model mapping the file system could be created for a
  23. -- file manager. Many views could be created to display various
  24. -- parts of the file system, but only one copy need be kept in
  25. -- memory.
  26. -- The purpose of the cell renderers is to provide extensibility to
  27. -- the widget and to allow multiple ways of rendering the same type
  28. -- of data. For example, consider how to render a boolean
  29. -- variable. Should it render it as a string of "True" or "False",
  30. -- "On" or "Off", or should it be rendered as a checkbox?
  31. -- Creating a model: GTK+ provides two simple models that can be
  32. -- used: the GtkListStore and the GtkTreeStore. GtkListStore is
  33. -- used to model list widgets, while the GtkTreeStore models
  34. -- trees. It is possible to develop a new type of model, but the
  35. -- existing models should be satisfactory for all but the most
  36. -- specialized of situations. Creating the model is quite simple:
  37. -- GtkListStore *store = gtk_list_store_new (2, G_TYPE_STRING,
  38. -- G_TYPE_BOOLEAN);
  39. -- This creates a list store with two columns: a string column and
  40. -- a boolean column. Typically the 2 is never passed directly like
  41. -- that; usually an enum is created wherein the different columns
  42. -- are enumerated, followed by a token that represents the total
  43. -- number of columns. The next example will illustrate this, only
  44. -- using a tree store instead of a list store. Creating a tree
  45. -- store operates almost exactly the same.
  46. -- enum
  47. -- {
  48. -- TITLE_COLUMN,
  49. -- AUTHOR_COLUMN,
  50. -- CHECKED_COLUMN,
  51. -- N_COLUMNS
  52. -- };
  53. --
  54. -- GtkTreeStore *store = gtk_tree_store_new (N_COLUMNS, /* Total number of columns */
  55. -- G_TYPE_STRING, /* Book title */
  56. -- G_TYPE_STRING, /* Author */
  57. -- G_TYPE_BOOLEAN); /* Is checked out? */
  58. -- Adding data to the model is done using gtk_tree_store_set() or
  59. -- gtk_list_store_set(), depending upon which sort of model was
  60. -- created. To do this, a GtkTreeIter must be acquired. The
  61. -- iterator points to the location where data will be added.
  62. -- Once an iterator has been acquired, gtk_tree_store_set() is used
  63. -- to apply data to the part of the model that the iterator points
  64. -- to. Consider the following example:
  65. -- GtkTreeIter iter;
  66. --
  67. -- gtk_tree_store_append (store, &iter, NULL); /* Acquire an iterator */
  68. --
  69. -- gtk_tree_store_set (store, &iter,
  70. -- TITLE_COLUMN, "The Principle of Reason",
  71. -- AUTHOR_COLUMN, "Martin Heidegger",
  72. -- CHECKED_COLUMN, FALSE,
  73. -- -1);
  74. -- Notice that the last argument is -1. This is always done because
  75. -- this is a variable-argument function and it needs to know when
  76. -- to stop processing arguments. It can be used to set the data in
  77. -- any or all columns in a given row.
  78. -- The third argument to gtk_tree_store_append() is the parent
  79. -- iterator. It is used to add a row to a GtkTreeStore as a child
  80. -- of an existing row. This means that the new row will only be
  81. -- visible when its parent is visible and in its expanded
  82. -- state. Consider the following example:
  83. -- GtkTreeIter iter1; /* Parent iter */
  84. -- GtkTreeIter iter2; /* Child iter */
  85. --
  86. -- gtk_tree_store_append (store, &iter1, NULL); /* Acquire a top-level iterator */
  87. -- gtk_tree_store_set (store, &iter1,
  88. -- TITLE_COLUMN, "The Art of Computer Programming",
  89. -- AUTHOR_COLUMN, "Donald E. Knuth",
  90. -- CHECKED_COLUMN, FALSE,
  91. -- -1);
  92. --
  93. -- gtk_tree_store_append (store, &iter2, &iter1); /* Acquire a child iterator */
  94. -- gtk_tree_store_set (store, &iter2,
  95. -- TITLE_COLUMN, "Volume 1: Fundamental Algorithms",
  96. -- -1);
  97. --
  98. -- gtk_tree_store_append (store, &iter2, &iter1);
  99. -- gtk_tree_store_set (store, &iter2,
  100. -- TITLE_COLUMN, "Volume 2: Seminumerical Algorithms",
  101. -- -1);
  102. --
  103. -- gtk_tree_store_append (store, &iter2, &iter1);
  104. -- gtk_tree_store_set (store, &iter2,
  105. -- TITLE_COLUMN, "Volume 3: Sorting and Searching",
  106. -- -1);
  107. -- Creating the view component: While there are several different
  108. -- models to choose from, there is only one view widget to deal
  109. -- with. It works with either the list or the tree store. Setting
  110. -- up a GtkTreeView is not a difficult matter. It needs a
  111. -- GtkTreeModel to know where to retrieve its data from.
  112. -- GtkWidget *tree;
  113. --
  114. -- tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
  115. -- Columns and cell renderers: Once the GtkTreeView widget has a
  116. -- model, it will need to know how to display the model. It does
  117. -- this with columns and cell renderers.
  118. -- Cell renderers are used to draw the data in the tree model in a
  119. -- way. There are a number of cell renderers that come with GTK+
  120. -- 2.x, including the GtkCellRendererText, GtkCellRendererPixbuf
  121. -- and the GtkCellRendererToggle. It is relatively easy to write a
  122. -- custom renderer.
  123. -- A GtkTreeViewColumn is the object that GtkTreeView uses to
  124. -- organize the vertical columns in the tree view. It needs to know
  125. -- the name of the column to label for the user, what type of cell
  126. -- renderer to use, and which piece of data to retrieve from the
  127. -- model for a given row.
  128. -- GtkCellRenderer *renderer;
  129. -- GtkTreeViewColumn *column;
  130. --
  131. -- renderer = gtk_cell_renderer_text_new ();
  132. -- column = gtk_tree_view_column_new_with_attributes ("Author",
  133. -- renderer,
  134. -- "text", AUTHOR_COLUMN,
  135. -- NULL);
  136. -- gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
  137. --
  138. -- At this point, all the steps in creating a displayable tree have been
  139. -- covered. The model is created, data is stored in it, a tree view is
  140. -- created and columns are added to it.
  141. --
  142. -- --------------------------------------------------------------------------
  143. --
  144. -- Selection handling: Most applications will need to not only deal with displaying data, but
  145. -- also receiving input events from users. To do this, simply get a reference
  146. -- to a selection object and connect to the "changed" signal.
  147. -- /* Prototype for selection handler callback */
  148. -- static void tree_selection_changed_cb (GtkTreeSelection *selection, gpointer data);
  149. --
  150. -- /* Setup the selection handler */
  151. -- GtkTreeSelection *select;
  152. --
  153. -- select = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree));
  154. -- gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE);
  155. -- g_signal_connect (G_OBJECT (select), "changed",
  156. -- G_CALLBACK (tree_selection_changed_cb),
  157. -- NULL);
  158. -- Then to retrieve data for the row selected:
  159. -- static void
  160. -- tree_selection_changed_cb (GtkTreeSelection *selection, gpointer data)
  161. -- {
  162. -- GtkTreeIter iter;
  163. -- GtkTreeModel *model;
  164. -- gchar *author;
  165. --
  166. -- if (gtk_tree_selection_get_selected (selection, &model, &iter))
  167. -- {
  168. -- gtk_tree_model_get (model, &iter, AUTHOR_COLUMN, &author, -1);
  169. --
  170. -- g_print ("You selected a book by <link linkend="s"><literal>s</literal></link>\n", author);
  171. --
  172. -- g_free (author);
  173. -- }
  174. -- }
  175. -- Simple Example: Here is a simple example of using a GtkTreeView
  176. -- widget in context of the other widgets. It simply creates a
  177. -- simple model and view, and puts them together. Note that the
  178. -- model is never populated with data - that is left as an exercise
  179. -- for the reader. More information can be found on this in the
  180. -- GtkTreeModel section.
  181. -- enum
  182. -- {
  183. -- TITLE_COLUMN,
  184. -- AUTHOR_COLUMN,
  185. -- CHECKED_COLUMN,
  186. -- N_COLUMNS
  187. -- };
  188. --
  189. -- void
  190. -- setup_tree (void)
  191. -- {
  192. -- GtkTreeStore *store;
  193. -- GtkWidget *tree;
  194. -- GtkTreeViewColumn *column;
  195. -- GtkCellRenderer *renderer;
  196. --
  197. -- /* Create a model. We are using the store model for now, though we
  198. -- * could use any other GtkTreeModel */
  199. -- store = gtk_tree_store_new (N_COLUMNS,
  200. -- G_TYPE_STRING,
  201. -- G_TYPE_STRING,
  202. -- G_TYPE_BOOLEAN);
  203. --
  204. -- /* custom function to fill the model with data */
  205. -- populate_tree_model (store);
  206. --
  207. -- /* Create a view */
  208. -- tree = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
  209. --
  210. -- /* The view now holds a reference. We can get rid of our own
  211. -- * reference */
  212. -- g_object_unref (G_OBJECT (store));
  213. --
  214. -- /* Create a cell render and arbitrarily make it red for demonstration
  215. -- * purposes */
  216. -- renderer = gtk_cell_renderer_text_new ();
  217. -- g_object_set (G_OBJECT (renderer),
  218. -- "foreground", "red",
  219. -- NULL);
  220. --
  221. -- /* Create a column, associating the "text" attribute of the
  222. -- * cell_renderer to the first column of the model */
  223. -- column = gtk_tree_view_column_new_with_attributes ("Author", renderer,
  224. -- "text", AUTHOR_COLUMN,
  225. -- NULL);
  226. --
  227. -- /* Add the column to the view. */
  228. -- gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
  229. --
  230. -- /* Second column.. title of the book. */
  231. -- renderer = gtk_cell_renderer_text_new ();
  232. -- column = gtk_tree_view_column_new_with_attributes ("Title",
  233. -- renderer,
  234. -- "text", TITLE_COLUMN,
  235. -- NULL);
  236. -- gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
  237. --
  238. -- /* Last column.. whether a book is checked out. */
  239. -- renderer = gtk_cell_renderer_toggle_new ();
  240. -- column = gtk_tree_view_column_new_with_attributes ("Checked out",
  241. -- renderer,
  242. -- "active", CHECKED_COLUMN,
  243. -- NULL);
  244. -- gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
  245. --
  246. -- /* Now we can manipulate the view just like any other GTK widget */
  247. -- ...
  248. -- }
  249. --
  250. insert
  251. GTK -- to initialize the Gimp ToolKit
  252. G_TYPES
  253. -- TODO: This class is necessary when creating GTK_LIST_STOREs,
  254. -- since it requires explicit reference to g_type_*; it's ugly,
  255. -- or better it feels mostly unEiffelish to me. Paolo 2005-06-12
  256. WRAPPER_HANDLER -- required to check for some bug in the
  257. -- implementation and accessing wrappers' handles
  258. GTK_STOCK_ITEMS
  259. GLIB_MESSAGE_LOGGING
  260. GDK_TYPE_EXTERNALS -- To store GDK_PIXMAPS into the store. TODO:
  261. -- give the end-user a better interface.
  262. creation make
  263. feature -- Columns
  264. name_column_n: INTEGER is 0
  265. nick_column_n: INTEGER is 1
  266. flag_column_n: INTEGER is 1
  267. columns_n: INTEGER is 3
  268. feature
  269. developers: FAST_ARRAY[TUPLE[STRING,STRING]] is
  270. once
  271. Result:= {FAST_ARRAY[TUPLE[STRING,STRING]]
  272. << ["Pierre-Nicolas", "eif_pini"],
  273. ["Anthony Lenton", "elachuni"],
  274. ["jose bollo", "jobo"],
  275. ["Natalia B. Bidart", "nessa"],
  276. ["Oliver Elphick", "oliver_elphick"],
  277. ["Raphael Mack", "ramack"],
  278. ["Daniel F Moisset", "trixx"]
  279. ["Paolo Redaelli", "tybor"],
  280. ["Walter Alini", "walteralini"] >>
  281. }
  282. end
  283. feature
  284. model: GTK_TREE_STORE is
  285. -- tree model with some data set
  286. local
  287. top_level, child: GTK_TREE_ITER
  288. developer_iter: ITERATOR[TUPLE[STRING,STRING]]
  289. once
  290. create Result.make (<<g_type_string, g_type_string, gdk_type_pixbuf>>)
  291. -- TODO: change design to remove explicit reference to g_type_*; it's
  292. -- ugly, or better it feels mostly unEiffelish to me. Paolo 2005-06-01
  293. create top_level.make_from_model (Result)
  294. create child.make_from_model (Result)
  295. -- Append an empty top-level row to the tree store.
  296. -- Top_Level will point to the new row
  297. Result.append (top_level, Void)
  298. Result.set_string (top_level, name_column_n, "ISE developers")
  299. -- Append another empty top-level row to the tree store.
  300. -- Top_Level will point to the new row
  301. Result.append(top_level, Void)
  302. Result.set_string (top_level, name_column_n, "SmartEiffel developers")
  303. -- Append a child to the row we just added.
  304. -- Child will point to the new row
  305. Result.append(top_level, Void)
  306. Result.set_string (top_level, name_column_n, "Eiffel-libraries developers")
  307. -- Get the first row, and add a child to it as well (could
  308. -- have been done right away earlier of course, this is just
  309. -- for demonstration purposes)
  310. child := Result.get_iterator_first
  311. if child = Void then
  312. glib_error("Oops, we should have a first row in the tree store!\n")
  313. else
  314. developer_iter := developers.get_new_iterator
  315. from developer_iter.start
  316. until developer_iter.is_off
  317. loop
  318. Result.append (child, top_level)
  319. Result.set_string (child, name_column_n, developer_iter.item.item_1)
  320. Result.set_string (child, nick_column_n, developer_iter.item.item_2)
  321. developer_iter.next
  322. end
  323. end
  324. end
  325. text_renderer, flag_renderer: GTK_CELL_RENDERER
  326. name_column, nick_column, nationality_column: GTK_TREE_VIEW_COLUMN
  327. view: GTK_TREE_VIEW is
  328. once
  329. create {GTK_CELL_RENDERER_TEXT} text_renderer.make
  330. create {GTK_CELL_RENDERER_PIXBUF} flag_renderer.make
  331. create name_column.make
  332. name_column.set_title ("Name")
  333. name_column.pack_start (text_renderer, True)
  334. name_column.add_attribute (text_renderer, "text", name_column_n)
  335. create nick_column.make
  336. nick_column.set_title ("Nick")
  337. nick_column.pack_start (text_renderer, True)
  338. nick_column.add_attribute (text_renderer, "text", nick_column_n)
  339. create nationality_column.make
  340. nick_column.set_title ("Nationality")
  341. nick_column.pack_start (text_renderer, True)
  342. nick_column.pack_start (flag_renderer, True)
  343. nick_column.add_attribute (text_renderer, "text", flag_column_n)
  344. create Result.make
  345. Result.insert_column (name_column, name_column_n)
  346. Result.insert_column (nick_column, nick_column_n)
  347. Result.set_model (model)
  348. -- TODO: Original C example here insert a g_object_unref
  349. -- (model); /* destroy model automatically with view */ I'm
  350. -- not sure, but it shouldn't be necessary. Shall we insert
  351. -- it? Paolo 2005-06-12
  352. end
  353. window: GTK_WINDOW
  354. vbox: GTK_VBOX
  355. button_box: GTK_HBOX
  356. add_button, remove_button, quit_button: GTK_BUTTON
  357. feature {} -- Creation
  358. make is
  359. -- Run the demo
  360. local selection: GTK_TREE_SELECTION
  361. do
  362. gtk.initialize_gtk
  363. -- Create a GTK window toplevel window
  364. create window.make
  365. window.set_title (window_title)
  366. -- It is a good idea to do this for all windows
  367. window.connect_agent_to_destroy_signal (agent on_destroy)
  368. view.show
  369. create add_button.from_stock (gtk_stock_add)
  370. create remove_button.from_stock (gtk_stock_remove)
  371. create quit_button.from_stock (gtk_stock_quit)
  372. create button_box.make(False,0) -- i.e. unhomogeneous, no spacing
  373. button_box.add(add_button)
  374. button_box.add(remove_button)
  375. button_box.add(quit_button)
  376. add_button.connect_agent_to_clicked_signal (agent add_clicked)
  377. remove_button.connect_agent_to_clicked_signal (agent remove_clicked)
  378. quit_button.connect_agent_to_clicked_signal (agent quit_clicked)
  379. create vbox.make(False,0) -- i.e. unhomogeneous, no spacing
  380. vbox.add(view)
  381. vbox.add(button_box)
  382. window.add (vbox)
  383. window.show_all
  384. selection := view.selection
  385. selection.set_single_mode
  386. selection.set_select_function (agent on_select)
  387. gtk.run_main_loop
  388. end
  389. feature
  390. traverse_model is
  391. require valid_model: model /= Void
  392. local iter: GTK_TREE_ITER
  393. do
  394. print ("Iterating over names%N")
  395. create iter.make_from_model (model)
  396. from iter.start
  397. until not iter.is_valid
  398. loop -- print each name ...
  399. print (model.value (iter, name_column_n).string)
  400. -- Note: Is "model.value" clear enough or "model.value_at" would be clearer?
  401. iter.next -- Move to next row
  402. if iter.is_valid then print (", ")
  403. else print ("%N")
  404. end
  405. end
  406. end
  407. paths_demo is
  408. local path: GTK_TREE_PATH
  409. do
  410. print ("Tree paths demo:%N")
  411. create path.make_first
  412. print ("First: ") print (path.to_string) print ("%N")
  413. create path.from_string ("1:3:2")
  414. print ("From string: ") print (path.to_string) print ("%N")
  415. end
  416. feature -- Agents
  417. add_clicked (a_button: GTK_BUTTON) is
  418. do
  419. end
  420. remove_clicked (a_button: GTK_BUTTON) is
  421. do
  422. end
  423. quit_clicked (a_button: GTK_BUTTON) is
  424. do
  425. window.destroy
  426. end
  427. on_destroy (a_gtk_object: GTK_OBJECT) is
  428. do
  429. print ("Tree demo is quitting.%N")
  430. paths_demo
  431. print ("Traversing model:%N")
  432. traverse_model
  433. print ("Using GTK_TREE_MODEL.for_each to print its content:%N")
  434. print ("TODO: in tree_demo on_destroy model.for_each (agent print_person)%N")
  435. print ("If GTK_TREE_MODEL.for_each is implemented correctly you should see above each person's name and age.%N")
  436. gtk.quit
  437. end
  438. print_person (a_model: GTK_TREE_MODEL; a_path: GTK_TREE_PATH; an_iter: GTK_TREE_ITER): BOOLEAN is
  439. do
  440. check right_model: a_model = model end
  441. print ("Person (code: ")
  442. print (a_path.to_string) print (") name '")
  443. print (a_model.value_at (an_iter, name_column_n).string)
  444. print ("' nick ")
  445. print (a_model.value_at (an_iter, nick_column_n).natural.out)
  446. print ("%N")
  447. Result := False -- i.e. go on
  448. end
  449. on_select (a_selection: GTK_TREE_SELECTION; a_model: GTK_TREE_MODEL; a_path: GTK_TREE_PATH; path_selected: BOOLEAN): BOOLEAN is
  450. do
  451. if a_selection.is_node_selected then
  452. print ("A selected row is being de-selected. Disabling buttons.%N")
  453. add_button.set_sensitive(False)
  454. remove_button.set_sensitive(False)
  455. else
  456. print ("A de-selected row is being selected. Enabling buttons.%N")
  457. add_button.set_sensitive(True)
  458. remove_button.set_sensitive(True)
  459. end
  460. print ("Path '") print (a_path.to_string)
  461. if path_selected then print ("' is being selected")
  462. else print ("' is being de-selected")
  463. end
  464. debug
  465. if a_model = Void
  466. then print ("; no model passed but we're sure that out GTK_LIST_STORE at"+model.to_pointer.out+" has handle="+model.handle.out)
  467. else print (".")
  468. end
  469. end
  470. print ("%N")
  471. Result := True -- i.e. effectively select the picked button.
  472. end
  473. feature -- Constants
  474. window_title: STRING is "GTK Trees!"
  475. -- Text top level window title
  476. end
  477. -- Examples from C docs.
  478. -- To help show some common operation of a model, some examples are
  479. -- provided. The first example shows three ways of getting the iter at
  480. -- the location "3:2:5". While the first method shown is easier, the
  481. -- second is much more common, as you often get paths from callbacks.
  482. -- Example 1. Acquiring a GtkTreeIter
  483. -- /* Three ways of getting the iter pointing to the location
  484. -- */
  485. -- {
  486. -- GtkTreePath *path;
  487. -- GtkTreeIter iter;
  488. -- GtkTreeIter parent_iter;
  489. -- /* get the iterator from a string */
  490. -- gtk_tree_model_get_iter_from_string (model, &iter, "3:2:5");
  491. -- /* get the iterator from a path */
  492. -- path = gtk_tree_path_new_from_string ("3:2:5");
  493. -- gtk_tree_model_get_iter (model, &iter, path);
  494. -- gtk_tree_path_free (path);
  495. -- /* walk the tree to find the iterator */
  496. -- gtk_tree_model_iter_nth_child (model, &iter, NULL, 3);
  497. -- parent_iter = iter;
  498. -- gtk_tree_model_iter_nth_child (model, &iter, &parent_iter, 2);
  499. -- parent_iter = iter;
  500. -- gtk_tree_model_iter_nth_child (model, &iter, &parent_iter, 5);
  501. -- }
  502. -- This second example shows a quick way of iterating through a list
  503. -- and getting a string and an integer from each row. The
  504. -- populate_model function used below is not shown, as it is specific
  505. -- to the GtkListStore. For information on how to write such a
  506. -- function, see the GtkListStore documentation.
  507. -- Example 2. Reading data from a GtkTreeModel
  508. -- enum
  509. -- {
  510. -- STRING_COLUMN,
  511. -- INT_COLUMN,
  512. -- N_COLUMNS
  513. -- };
  514. -- {
  515. -- GtkTreeModel *list_store;
  516. -- GtkTreeIter iter;
  517. -- gboolean valid;
  518. -- gint row_count = 0;
  519. -- /* make a new list_store */
  520. -- list_store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_INT);
  521. -- /* Fill the list store with data */
  522. -- populate_model (list_store);
  523. -- /* Get the first iter in the list */
  524. -- valid = gtk_tree_model_get_iter_first (list_store, &iter);
  525. -- while (valid)
  526. -- {
  527. -- /* Walk through the list, reading each row */
  528. -- gchar *str_data;
  529. -- gint int_data;
  530. -- /* Make sure you terminate calls to gtk_tree_model_get()
  531. -- * with a '-1' value
  532. -- */
  533. -- gtk_tree_model_get (list_store, &iter,
  534. -- STRING_COLUMN, &str_data,
  535. -- INT_COLUMN, &int_data,
  536. -- -1);
  537. -- /* Do something with the data */
  538. -- g_print ("Row %d: (%s,%d)\n", row_count, str_data, int_data);
  539. -- g_free (str_data);
  540. -- row_count ++;
  541. -- valid = gtk_tree_model_iter_next (list_store, &iter);
  542. -- }
  543. -- }