This file is indexed.

/usr/share/doc/python-gtk2-tutorial/html/sec-TreeModelInterface.html is in python-gtk2-tutorial 2.4-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>14.2. The TreeModel Interface and Data Stores</title><meta name="generator" content="DocBook XSL Stylesheets V1.65.1"><link rel="home" href="index.html" title="PyGTK 2.0 Tutorial"><link rel="up" href="ch-TreeViewWidget.html" title="Chapter 14. Tree View Widget"><link rel="previous" href="ch-TreeViewWidget.html" title="Chapter 14. Tree View Widget"><link rel="next" href="sec-TreeViews.html" title="14.3. TreeViews"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">14.2. The TreeModel Interface and Data Stores</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ch-TreeViewWidget.html">Prev</a> </td><th width="60%" align="center">Chapter 14. Tree View Widget</th><td width="20%" align="right"> <a accesskey="n" href="sec-TreeViews.html">Next</a></td></tr></table><hr></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="sec-TreeModelInterface"></a>14.2. The TreeModel Interface and Data Stores</h2></div></div><div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="sec-TreeModelIntroduction"></a>14.2.1. Introduction</h3></div></div><div></div></div><p>The <tt class="classname">TreeModel</tt> interface is implemented by
all the <tt class="classname">TreeModel</tt> subclasses and provides methods
to:</p><div class="itemizedlist"><ul type="disc"><li>retrieve the characteristics of the data store such as
the number of columns and the type of data in a column.</li><li>retrieve a <tt class="classname">TreeIter</tt> (a transient
reference) that points at a row in the model</li><li>retrieve information about a node (or row) such as the
number of its child nodes, a list of its child nodes, the contents of its
columns and a pointer to its parent node</li><li>provide notification of <tt class="classname">TreeModel</tt>
data changes</li></ul></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="sec-CreatingTreeStoreAndListStore"></a>14.2.2. Creating TreeStore and ListStore Objects</h3></div></div><div></div></div><p>The base data store classes: <tt class="classname">ListStore</tt> and
<tt class="classname">TreeStore</tt> provide the means to define and manage the
rows and columns of data in the tree model. The constructors of both these
objects require the column types to be specified as any of:</p><div class="itemizedlist"><ul type="disc"><li>Python types such as the built-in types: int, str, long,
float and object</li><li>PyGTK types such as <tt class="classname">Button</tt>,
<tt class="classname">VBox</tt>, <tt class="classname">gdk.Rectangle</tt>,
<tt class="classname">gdk.Pixbuf</tt></li><li><p><tt class="classname">GObject</tt> types (GTK+ GTypes)
specified either as GObject Type constants or as strings. Most GTypes are
mapped to a Python type:</p><div class="itemizedlist"><ul type="circle"><li>gobject.TYPE_CHAR or 'gchar'</li><li>gobject.TYPE_UCHAR or 'guchar'</li><li>gobject.TYPE_BOOLEAN or 'gboolean'</li><li>gobject.TYPE_INT or 'gint'</li><li>gobject.TYPE_UINT or 'guint'</li><li>gobject.TYPE_LONG or 'glong</li><li>gobject.TYPE_ULONG or 'gulong</li><li>gobject.TYPE_INT64 or 'gint64'</li><li>gobject.TYPE_UINT64 or 'guint64'</li><li>gobject.TYPE_FLOAT or 'gfloat'</li><li>gobject.TYPE_DOUBLE or 'gdouble'</li><li>gobject.TYPE_STRING or 'gchararray'</li><li>gobject.TYPE_OBJECT or 'GObject</li></ul></div></li></ul></div><p>For example to create a <tt class="classname">ListStore</tt> or
<tt class="classname">TreeStore</tt> with rows containing a
<tt class="classname">gdk.Pixbuf</tt>, an integer, a string and boolean you
could do something like:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  liststore = ListStore(gtk.gdk.Pixbuf, int, str, 'gboolean')

  treestore = TreeStore(gtk.gdk.Pixbuf, int, str, 'gboolean')
</pre></td></tr></table><p>Once a <tt class="classname">ListStore</tt> or
<tt class="classname">TreeStore</tt> is created and its columns defined, they
cannot be changed or modified. It's also important to realize that there is
no preset relation between the columns in a <tt class="classname">TreeView</tt>
and the columns of its <tt class="classname">TreeModel</tt>. That is, the fifth
column of data in a <tt class="classname">TreeModel</tt> may be displayed in the
first column of one <tt class="classname">TreeView</tt> and in the third column
in another. So you don't have to worry about how the data will be displayed
when creating the data store.</p><p>If these two data stores do not fit your application it is
possible to define your own custom data store in Python as long as it
implements the TreeModel interface. I'll talk more about this later in <a href="sec-GenericTreeModel.html" title="14.11. The Generic TreeModel">Section 14.11, &#8220;The Generic TreeModel&#8221;</a>.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="sec-ReferringToTreeModelRows"></a>14.2.3. Referring to TreeModel Rows</h3></div></div><div></div></div><p>Before we can talk about managing the data rows in a
<tt class="classname">TreeStore</tt> or <tt class="classname">ListStore</tt> we need
a way of specifying which row we want to deal with. PyGTK has three ways of
referring to <tt class="classname">TreeModel</tt> rows: a tree path, a
<tt class="classname">TreeIter</tt> and a
<tt class="classname">TreeRowReference</tt>.</p><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="sec-TreePaths"></a>14.2.3.1. Tree Paths</h4></div></div><div></div></div><p>A tree path is a int, string or tuple representation of the
location of a row in the store. An int value specifies the top level row in
the model starting from 0. For example, a tree path value of 4 would specify
the fifth row in the store. By comparison, a string representation of the
same row would be "4" and the tuple representation would be (4,). This is
sufficient for specifying any row in a <tt class="classname">ListStore</tt> but
for a TreeStore we have to be able to represent the child rows. For these
cases we have to use either the string or tuple representations.</p><p>Since a <tt class="classname">TreeStore</tt> can have an arbitrarily
deep hierarchy the string representation specifies the path from the top
level to the designated row using ints separated by the ":"
character. Similarly, the tuple representation specifies the tree path
starting from the top level to the row as a sequence of ints. For example,
valid tree path string representations are: "0:2" (specifies the row that is
the third child of the first row) and "4:0:1" (specifies the row that is the
second child of the first child of the fifth row). By comparison the same
tree paths are represented by the tuples (0, 2) and (4, 0, 1)
respectively.</p><p>A tree path provides the only way to map from a
<tt class="classname">TreeView</tt> row to a <tt class="classname">TreeModel</tt>
row because the tree path of a <tt class="classname">TreeView</tt> row is the
same as the tree path of the corresponding <tt class="classname">TreeModel</tt>
row. There are also some problems with tree paths:</p><div class="itemizedlist"><ul type="disc"><li>a tree path can specify a row that doesn't exist in the
ListStore or TreeStore.</li><li>a tree path can point to a different data row after
inserting or deleting a row in the <tt class="classname">ListStore</tt> or
<tt class="classname">TreeStore</tt>.</li></ul></div><p>PyGTK uses the tuple representation when returning tree paths
but will accept any of the three forms for a tree path representation. You
should use the tuple representation for a tree path for consistency.</p><p>A tree path can be retrieved from a
<tt class="classname">TreeIter</tt> using the
<tt class="methodname">get_path</tt>() method:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  path = store.get_path(<b class="parameter"><tt>iter</tt></b>)
</pre></td></tr></table><p>where <i class="parameter"><tt>iter</tt></i> is a
<tt class="classname">TreeIter</tt> pointing at a row in store and
<i class="parameter"><tt>path</tt></i> is the row's tree path as a tuple.</p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="sec-TreeIters"></a>14.2.3.2. TreeIters</h4></div></div><div></div></div><p>A <tt class="classname">TreeIter</tt> is an object that provides a
transient reference to a <tt class="classname">ListStore</tt> or
<tt class="classname">TreeStore</tt> row. If the contents of the store change
(usually because a row is added or deleted) the
<tt class="classname">TreeIter</tt>s can become invalid. A
<tt class="classname">TreeModel</tt> that supports persistent TreeIters should
set the <tt class="literal">gtk.TREE_MODEL_ITERS_PERSIST</tt> flag. An application
can check for this flag using the <tt class="methodname">get_flags</tt>()
method.</p><p>A <tt class="classname">TreeIter</tt> is created by one of the
<tt class="classname">TreeModel</tt> methods that are applicable to both
<tt class="classname">TreeStore</tt> and <tt class="classname">ListStore</tt>
objects:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  treeiter = store.get_iter(<b class="parameter"><tt>path</tt></b>)
</pre></td></tr></table><p>where <i class="parameter"><tt>treeiter</tt></i> points at the row at the
tree path <i class="parameter"><tt>path</tt></i>. The ValueError exception is raised if
the tree path is invalid.</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  treeiter = store.get_iter_first()
</pre></td></tr></table><p>where <i class="parameter"><tt>treeiter</tt></i> is a TreeIter pointing
at the row at tree path (0,). <i class="parameter"><tt>treeiter</tt></i> will be
<tt class="literal">None</tt> if the store is empty.</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  treeiter = store.iter_next(<b class="parameter"><tt>iter</tt></b>)
</pre></td></tr></table><p>where <i class="parameter"><tt>treeiter</tt></i> is a
<tt class="classname">TreeIter</tt> that points at the next row at the same
level as the <tt class="classname">TreeIter</tt> specified by
<i class="parameter"><tt>iter</tt></i>. <i class="parameter"><tt>treeiter</tt></i> will be
<tt class="literal">None</tt> if there is no next row (<i class="parameter"><tt>iter</tt></i>
is also invalidated).</p><p>The following methods are useful only for retrieving a
<tt class="classname">TreeIter</tt> from a
<tt class="classname">TreeStore</tt>:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  treeiter = treestore.iter_children(<b class="parameter"><tt>parent</tt></b>)
</pre></td></tr></table><p>where <i class="parameter"><tt>treeiter</tt></i> is a
<tt class="classname">TreeIter</tt> pointing at the first child row of the row
specified by the <tt class="classname">TreeIter</tt>
<i class="parameter"><tt>parent</tt></i>. <i class="parameter"><tt>treeiter</tt></i> will be
<tt class="literal">None</tt> if there is no child.</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  treeiter = treestore.iter_nth_child(<b class="parameter"><tt>parent</tt></b>, <b class="parameter"><tt>n</tt></b>)
</pre></td></tr></table><p>where <i class="parameter"><tt>treeiter</tt></i> is a
<tt class="classname">TreeIter</tt> pointing at the child row (with the index
<i class="parameter"><tt>n</tt></i>) of the row specified by the
<tt class="classname">TreeIter</tt>
<i class="parameter"><tt>parent</tt></i>. <i class="parameter"><tt>parent</tt></i> may be
<tt class="literal">None</tt> to retrieve a top level
row. <i class="parameter"><tt>treeiter</tt></i> will be <tt class="literal">None</tt> if
there is no child.</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  treeiter = treestore.iter_parent(<b class="parameter"><tt>child</tt></b>)
</pre></td></tr></table><p>where <i class="parameter"><tt>treeiter</tt></i> is a
<tt class="classname">TreeIter</tt> pointing at the parent row of the row
specified by the <tt class="classname">TreeIter</tt>
<i class="parameter"><tt>child</tt></i>. treeiter will be <tt class="literal">None</tt> if
there is no child.</p><p>A tree path can be retrieved from a
<tt class="classname">TreeIter</tt> using the
<tt class="methodname">get_path</tt>() method:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  path = store.get_path(<b class="parameter"><tt>iter</tt></b>)
</pre></td></tr></table><p>where <i class="parameter"><tt>iter</tt></i> is a
<tt class="classname">Treeiter</tt> pointing at a row in store and
<i class="parameter"><tt>path</tt></i> is the row's tree path as a tuple.</p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="sec-TreeRowReferences"></a>14.2.3.3. TreeRowReferences</h4></div></div><div></div></div><p>A <tt class="classname">TreeRowReference</tt> is a persistent
reference to a row of data in a store. While the tree path (i.e. the
location) of the row might change as rows are added to or deleted from the
store, the <tt class="classname">TreeRowReference</tt> will point at the same
data row as long as it exists.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p><tt class="classname">TreeRowReference</tt>s are only available in
PyGTK 2.4 and above.</p></div><p>You can create a <tt class="classname">TreeRowReference</tt> using
its constructor:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  treerowref = TreeRowReference(<b class="parameter"><tt>model</tt></b>, <b class="parameter"><tt>path</tt></b>)
</pre></td></tr></table><p>where <i class="parameter"><tt>model</tt></i> is the
<tt class="classname">TreeModel</tt> containing the row and
<i class="parameter"><tt>path</tt></i> is the tree path of the row to track. If
<i class="parameter"><tt>path</tt></i> isn't a valid tree path for
<i class="parameter"><tt>model</tt></i>, <tt class="literal">None</tt> is returned.</p></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="sec-AddingStoreRows"></a>14.2.4. Adding Rows</h3></div></div><div></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="sec-AddingListStoreRows"></a>14.2.4.1. Adding Rows to a ListStore</h4></div></div><div></div></div><p>Once you have a <tt class="classname">ListStore</tt> you'll need to
add data rows using one of the following methods:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  iter = append(<b class="parameter"><tt>row</tt></b>=None)
  iter = prepend(<b class="parameter"><tt>row</tt></b>=None)
  iter = insert(<b class="parameter"><tt>position</tt></b>, <b class="parameter"><tt>row</tt></b>=None)
  iter = insert_before(<b class="parameter"><tt>sibling</tt></b>, <b class="parameter"><tt>row</tt></b>=None)
  iter = insert_after(<b class="parameter"><tt>sibling</tt></b>, <b class="parameter"><tt>row</tt></b>=None)
</pre></td></tr></table><p>Each of these methods inserts a row at an implied or specified
position in the <tt class="classname">ListStore</tt>. The
<tt class="methodname">append</tt>() and <tt class="methodname">prepend</tt>()
methods use implied positions: after the last row and before the first row,
respectively. The <tt class="methodname">insert</tt>() method takes an integer
(the parameter <i class="parameter"><tt>position</tt></i>) that specifies the location
where the row will be inserted. The other two methods take a
<tt class="classname">TreeIter</tt> (<i class="parameter"><tt>sibling</tt></i>) that
references a row in the <tt class="classname">ListStore</tt> to insert the row
before or after.</p><p>The <i class="parameter"><tt>row</tt></i> parameter specifies the data that
should be inserted in the row after it is created. If
<i class="parameter"><tt>row</tt></i> is <tt class="literal">None</tt> or not specified, an
empty row will be created. If <i class="parameter"><tt>row</tt></i> is specified it
must be a tuple or list containing as many items as the number of columns in
the <tt class="classname">ListStore</tt>. The items must also match the data
type of their respective <tt class="classname">ListStore</tt> columns.</p><p>All methods return a <tt class="classname">TreeIter</tt> that points
at the newly inserted row. The following code fragment illustrates the
creation of a <tt class="classname">ListStore</tt> and the addition of data rows
to it:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  ...
  liststore = gtk.ListStore(int, str, gtk.gdk.Color)
  liststore.append([0,'red',colormap.alloc_color('red')])
  liststore.append([1,'green',colormap.alloc_color('green')])
  iter = liststore.insert(1, (2,'blue',colormap.alloc_color('blue')) )
  iter = liststore.insert_after(iter, [3,'yellow',colormap.alloc_color('blue')])
  ...
</pre></td></tr></table></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="sec-AddingTreeStoreRows"></a>14.2.4.2. Adding Rows to a TreeStore</h4></div></div><div></div></div><p>Adding a row to a <tt class="classname">TreeStore</tt> is similar to
adding a row to a <tt class="classname">ListStore</tt> except that you also have
to specify a parent row (using a <tt class="classname">TreeIter</tt>) to add the
new row to. The <tt class="classname">TreeStore</tt> methods are:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  iter = append(<b class="parameter"><tt>parent</tt></b>, <b class="parameter"><tt>row</tt></b>=None)
  iter = prepend(<b class="parameter"><tt>parent</tt></b>, <b class="parameter"><tt>row</tt></b>=None)
  iter = insert(<b class="parameter"><tt>parent</tt></b>, <b class="parameter"><tt>position</tt></b>, <b class="parameter"><tt>row</tt></b>=None)
  iter = insert_before(<b class="parameter"><tt>parent</tt></b>, <b class="parameter"><tt>sibling</tt></b>, <b class="parameter"><tt>row</tt></b>=None)
  iter = insert_after(<b class="parameter"><tt>parent</tt></b>, <b class="parameter"><tt>sibling</tt></b>, <b class="parameter"><tt>row</tt></b>=None)
</pre></td></tr></table><p>If <i class="parameter"><tt>parent</tt></i> is <tt class="literal">None</tt>, the
row will be added to the top level rows.</p><p>Each of these methods inserts a row at an implied or specified
position in the <tt class="classname">TreeStore</tt>. The
<tt class="methodname">append</tt>() and <tt class="methodname">prepend</tt>()
methods use implied positions: after the last child row and before the first
child row, respectively. The <tt class="methodname">insert</tt>() method takes
an integer (the parameter <i class="parameter"><tt>position</tt></i>) that specifies
the location where the child row will be inserted. The other two methods
take a <tt class="classname">TreeIter</tt> (<i class="parameter"><tt>sibling</tt></i>) that
references a child row in the <tt class="classname">TreeStore</tt> to insert the
row before or after.</p><p>The <i class="parameter"><tt>row</tt></i> parameter specifies the data that
should be inserted in the row after it is created. If
<i class="parameter"><tt>row</tt></i> is <tt class="literal">None</tt> or not specified, an
empty row will be created. If <i class="parameter"><tt>row</tt></i> is specified it
must be a tuple or list containing as many items as the number of columns in
the <tt class="classname">TreeStore</tt>. The items must also match the data
type of their respective <tt class="classname">TreeStore</tt> columns.</p><p>All methods return a <tt class="classname">TreeIter</tt> that points
at the newly inserted row. The following code fragment illustrates the
creation of a <tt class="classname">TreeStore</tt> and the addition of data rows
to it:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  ...
  folderpb = gtk.gdk.pixbuf_from_file('folder.xpm')
  filepb = gtk.gdk.pixbuf_from_file('file.xpm')
  treestore = gtk.TreeStore(int, str, gtk.gdk.Pixbuf)
  iter0 = treestore.append(None, [1,'(0,)',folderpb] )
  treestore.insert(iter0, 0, [11,'(0,0)',filepb])
  treestore.append(iter0, [12,'(0,1)',filepb])
  iter1 = treestore.insert_after(None, iter0, [2,'(1,)',folderpb])
  treestore.insert(iter1, 0, [22,'(1,1)',filepb])
  treestore.prepend(iter1, [21,'(1,0)',filepb])
  ...
</pre></td></tr></table></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="sec-LargeDataStores"></a>14.2.4.3. Large Data Stores</h4></div></div><div></div></div><p>When a <tt class="classname">ListStore</tt> or
<tt class="classname">TreeStore</tt> contains a large number of data rows,
adding new rows can become very slow. There are a few things that you can do
to mitigate this problem:</p><div class="itemizedlist"><ul type="disc"><li>If adding a large number of rows disconnect the
<tt class="classname">TreeModel</tt> from its <tt class="classname">TreeView</tt>
(using the <tt class="methodname">set_model</tt>() method with the
<i class="parameter"><tt>model</tt></i> parameter set to <tt class="literal">None</tt>) to
avoid <tt class="classname">TreeView</tt> updates for each row
entered.</li><li>Likewise, disable sorting (using the
<tt class="methodname">set_default_sort_func</tt>() method with the
<i class="parameter"><tt>sort_func</tt></i> set to <tt class="literal">None</tt>) while
adding a large number of rows.</li><li>Limit the number of
<tt class="classname">TreeRowReference</tt>s in use since they update their path
with each addition or removal.</li><li>Set the <tt class="classname">TreeView</tt>
"fixed-height-mode" property to <tt class="literal">TRUE</tt> making all rows have
the same height and avoiding the individual calculation of the height of
each row. Only available in PyGTK 2.4 and above.</li></ul></div></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="sec-RemovingStoreRows"></a>14.2.5. Removing Rows</h3></div></div><div></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="sec-RemovingListStoreRows"></a>14.2.5.1. Removing Rows From a ListStore</h4></div></div><div></div></div><p>You can remove a data row from a
<tt class="classname">ListStore</tt> by using the
<tt class="methodname">remove</tt>() method:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  treeiter = liststore.remove(<b class="parameter"><tt>iter</tt></b>)
</pre></td></tr></table><p>where <i class="parameter"><tt>iter</tt></i> is a
<tt class="classname">TreeIter</tt> pointing at the row to remove. The returned
<tt class="classname">TreeIter</tt> (<i class="parameter"><tt>treeiter</tt></i>) points at
the next row or is invalid if <i class="parameter"><tt>iter</tt></i> was pointing at
the last row.</p><p>The <tt class="methodname">clear</tt>() method removes all rows
from the <tt class="classname">ListStore</tt>:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  liststore.clear()
</pre></td></tr></table></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="sec-RemovingTreeStoreRows"></a>14.2.5.2. Removing Rows From a TreeStore</h4></div></div><div></div></div><p>The methods for removing data rows from a
<tt class="classname">TreeStore</tt> are similar to the
<tt class="classname">ListStore</tt> methods:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  result = treestore.remove(<b class="parameter"><tt>iter</tt></b>)
  treestore.clear()
</pre></td></tr></table><p>where <i class="parameter"><tt>result</tt></i> is <tt class="literal">TRUE</tt>
if the row was removed and <i class="parameter"><tt>iter</tt></i> points at the next
valid row. Otherwise, <i class="parameter"><tt>result</tt></i> is
<tt class="literal">FALSE</tt> and <i class="parameter"><tt>iter</tt></i> is
invalidated.</p></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="sec-ManagingRowData"></a>14.2.6. Managing Row Data</h3></div></div><div></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="sec-AccessingDataValues"></a>14.2.6.1. Setting and Retrieving Data Values</h4></div></div><div></div></div><p>The methods for accessing the data values in a
<tt class="classname">ListStore</tt> and <tt class="classname">TreeStore</tt> have
the same format. All store data manipulations use a
<tt class="classname">TreeIter</tt> to specify the row that you are working
with. Once you have a <tt class="classname">TreeIter</tt> it can be used to
retrieve the values of a row column using the
<tt class="methodname">get_value</tt>() method:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  value = store.get_value(<b class="parameter"><tt>iter</tt></b>, <b class="parameter"><tt>column</tt></b>)
</pre></td></tr></table><p>where <i class="parameter"><tt>iter</tt></i> is a
<tt class="classname">TreeIter</tt> pointing at a row,
<i class="parameter"><tt>column</tt></i> is a column number in
<i class="parameter"><tt>store</tt></i>, and, <i class="parameter"><tt>value</tt></i> is the value
stored at the row-column location.</p><p>If you want to retrieve the values from multiple columns in
one call use the <tt class="methodname">get</tt>() method:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  values = store.get(iter, column, ...)
</pre></td></tr></table><p>where <i class="parameter"><tt>iter</tt></i> is a
<tt class="classname">TreeIter</tt> pointing at a row,
<i class="parameter"><tt>column</tt></i> is a column number in
<i class="parameter"><tt>store</tt></i>, and, <i class="parameter"><tt>...</tt></i> represents
zero or more additional column numbers and <i class="parameter"><tt>values</tt></i> is
a tuple containing the retrieved data values. For example to retrieve the
values in columns 0 and 2:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  val0, val2 = store.get(iter, 0, 2)
</pre></td></tr></table><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>The <tt class="methodname">get</tt>() method is only available
in PyGTK 2.4 and above.</p></div><p>Setting a single column value is effected using the
<tt class="methodname">set_value</tt>() method:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  store.set_value(<b class="parameter"><tt>iter</tt></b>, <b class="parameter"><tt>column</tt></b>, <b class="parameter"><tt>value</tt></b>)
</pre></td></tr></table><p>where <i class="parameter"><tt>iter</tt></i> (a
<tt class="classname">TreeIter</tt>) and <i class="parameter"><tt>column</tt></i> (an int)
specify the row-column location in <i class="parameter"><tt>store</tt></i> and
<i class="parameter"><tt>column</tt></i> is the column number where
<i class="parameter"><tt>value</tt></i> is to be set. <i class="parameter"><tt>value</tt></i> must
be the same data type as the <i class="parameter"><tt>store</tt></i> column.</p><p>If you wish to set the value of more than one column in a row
at a time, use the <tt class="methodname">set</tt>() method:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  store.set(<i class="parameter"><tt>iter</tt></i>, <i class="parameter"><tt>...</tt></i>)
</pre></td></tr></table><p>where <i class="parameter"><tt>iter</tt></i> specifies the store row and
<i class="parameter"><tt>...</tt></i> is one or more column number - value pairs
indicating the column and and value to set. For example, the following
call:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  store.set(iter, 0, 'Foo', 5, 'Bar', 1, 123)
</pre></td></tr></table><p>sets the first column to 'Foo', the sixth column to 'Bar' and
the second column to 123 in the <i class="parameter"><tt>store</tt></i> row specified
by <i class="parameter"><tt>iter</tt></i>.</p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="sec-RearrangingListStoreRows"></a>14.2.6.2. Rearranging ListStore Rows</h4></div></div><div></div></div><p>Individual <tt class="classname">ListStore</tt> rows can be moved
using one of the following methods that are available in PyGTK 2.2 and
above:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  liststore.swap(<b class="parameter"><tt>a</tt></b>, <b class="parameter"><tt>b</tt></b>)
  liststore.move_after(<b class="parameter"><tt>iter</tt></b>, <b class="parameter"><tt>position</tt></b>)
  liststore.move_before(<b class="parameter"><tt>iter</tt></b>, <b class="parameter"><tt>position</tt></b>)
</pre></td></tr></table><p><tt class="methodname">swap</tt>() swaps the locations of the rows
referenced by the <tt class="classname">TreeIter</tt>s <i class="parameter"><tt>a</tt></i>
and <i class="parameter"><tt>b</tt></i>. <tt class="methodname">move_after</tt>() and
<tt class="methodname">move_before</tt>() move the row referenced by the
<tt class="classname">TreeIter</tt> <i class="parameter"><tt>iter</tt></i> after or before
the row referenced by the <tt class="classname">TreeIter</tt>
<i class="parameter"><tt>position</tt></i>. If <i class="parameter"><tt>position</tt></i> is
<tt class="literal">None</tt>, <tt class="methodname">move_after</tt>() will place
the row at the beginning of the store while
<tt class="methodname">move_before</tt>(), at the end of the store.</p><p>If you want to completely rearrange the
<tt class="classname">ListStore</tt> data rows, use the following method:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  liststore.reorder(<i class="parameter"><tt>new_order</tt></i>)
</pre></td></tr></table><p>where <i class="parameter"><tt>new_order</tt></i> is a list of integers
that specify the new row order as:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  <i class="parameter"><tt>new_order</tt></i>[newpos] = oldpos
</pre></td></tr></table><p>For example, if <i class="parameter"><tt>liststore</tt></i> contained
four rows:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  'one'
  'two'
  'three'
  'four'
</pre></td></tr></table><p>The method call:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  liststore.reorder([2, 1, 3, 0])
</pre></td></tr></table><p>would produce the resulting order:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  'three'
  'two'
  'four'
  'one'
</pre></td></tr></table><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>These methods will only rearrange unsorted
<tt class="classname">ListStore</tt>s.</p></div><p>If you want to rearrange rows in PyGTK 2.0 you have to remove
and insert rows using the methods described in <a href="sec-TreeModelInterface.html#sec-AddingStoreRows" title="14.2.4. Adding Rows">Section 14.2.4, &#8220;Adding Rows&#8221;</a> and <a href="sec-TreeModelInterface.html#sec-RemovingStoreRows" title="14.2.5. Removing Rows">Section 14.2.5, &#8220;Removing Rows&#8221;</a>.</p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="sec-RearrangingTreeStoreRows"></a>14.2.6.3. Rearranging TreeStore Rows</h4></div></div><div></div></div><p>The methods used to rearrange <tt class="classname">TreeStore</tt>
rows are similar to the <tt class="classname">ListStore</tt> methods except they
only affect the child rows of an implied parent row - it is not possible to,
say, swap rows with different parent rows.:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  treestore.swap(<b class="parameter"><tt>a</tt></b>, <b class="parameter"><tt>b</tt></b>)
  treestore.move_after(<b class="parameter"><tt>iter</tt></b>, <b class="parameter"><tt>position</tt></b>)
  treestore.move_before(<b class="parameter"><tt>iter</tt></b>, <b class="parameter"><tt>position</tt></b>)
</pre></td></tr></table><p><tt class="methodname">swap</tt>() swaps the locations of the child
rows referenced by the TreeIters <i class="parameter"><tt>a</tt></i> and
<i class="parameter"><tt>b</tt></i>. <i class="parameter"><tt>a</tt></i> and
<i class="parameter"><tt>b</tt></i> must both have the same parent
row. <tt class="methodname">move_after</tt>() and
<tt class="methodname">move_before</tt>() move the row referenced by the
<tt class="classname">TreeIter</tt> <i class="parameter"><tt>iter</tt></i> after or before
the row referenced by the <tt class="classname">TreeIter</tt>
<i class="parameter"><tt>position</tt></i>. <i class="parameter"><tt>iter</tt></i> and
<i class="parameter"><tt>position</tt></i> must both have the same parent row. If
<i class="parameter"><tt>position</tt></i> is <tt class="literal">None</tt>,
<tt class="methodname">move_after</tt>() will place the row at the beginning of
the store while <tt class="methodname">move_before</tt>(), at the end of the
store.</p><p>The <tt class="methodname">reorder</tt>() method requires an
additional parameter specifying the parent row whose child rows will be
reordered:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  treestore.reorder(<b class="parameter"><tt>parent</tt></b>, <b class="parameter"><tt>new_order</tt></b>)
</pre></td></tr></table><p>where <i class="parameter"><tt>new_order</tt></i> is a list of integers
that specify the new child row order of the parent row specified by the
<tt class="classname">TreeIter</tt> <i class="parameter"><tt>parent</tt></i> as:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  <i class="parameter"><tt>new_order</tt></i>[newpos] = oldpos
</pre></td></tr></table><p>For example, if <i class="parameter"><tt>treestore</tt></i> contained
four rows:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  'parent'
      'one'
      'two'
      'three'
      'four'
</pre></td></tr></table><p>The method call:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  treestore.reorder(parent, [2, 1, 3, 0])
</pre></td></tr></table><p>would produce the resulting order:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  'parent'
      'three'
      'two'
      'four'
      'one'
</pre></td></tr></table><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>These methods will only rearrange unsorted 
<tt class="classname">TreeStore</tt>s.</p></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="sec-ManagingMultipleRows"></a>14.2.6.4. Managing Multiple Rows</h4></div></div><div></div></div><p>One of the trickier aspects of dealing with
<tt class="classname">ListStore</tt>s and <tt class="classname">TreeStore</tt>s is
the operation on multiple rows, e.g. moving multiple rows, say, from one
parent row to another or removing rows based on certain criteria. The
difficulty arises from the need to use a <tt class="classname">TreeIter</tt>
that may become invalid as the result of the operation. For
<tt class="classname">ListStore</tt>s and <tt class="classname">TreeStore</tt>s the
TreeIters are persistent as can be checked by using the
<tt class="methodname">get_flags</tt>() method and testing for the
<tt class="literal">gtk.TREE_MODEL_ITERS_PERSIST</tt> flag. However the stackable
<tt class="classname">TreeModelFilter</tt> and
<tt class="classname">TreeModelSort</tt> classes do not have persistent
<tt class="classname">TreeIter</tt>s.</p><p>Assuming that <tt class="classname">TreeIter</tt>s don't persist how
do we move all the child rows from one parent row to another? We have
to:</p><div class="itemizedlist"><ul type="disc"><li>iterate over the parent's children</li><li>retrieve each row's data</li><li>remove each child row</li><li>insert a new row with the old row data in the new
parent's list</li></ul></div><p>We can't rely on the <tt class="methodname">remove</tt>() method to
return a valid <tt class="classname">TreeIter</tt> so we'll just ask for the
first child iter until it returns <tt class="literal">None</tt>. A possible
function to move child rows is:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  def move_child_rows(treestore, from_parent, to_parent):
    n_columns = treestore.get_n_columns()
    iter = treestore.iter_children(from_parent)
    while iter:
      values = treestore.get(iter, *range(n_columns))
      treestore.remove(iter)
      treestore.append(to_parent, values)
      iter = treestore.iter_children(from_parent)
    return
</pre></td></tr></table><p>The above function covers the simple case of moving all child
rows of a single parent row but what if you want to remove all rows in the
<tt class="classname">TreeStore</tt> based on some match criteria, say the first
column value? Here you might think that you could use the
<tt class="methodname">foreach</tt>() method to iterate over all the rows and
remove the matching ones:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  store.foreach(<i class="parameter"><tt>func</tt></i>, <i class="parameter"><tt>user_data</tt></i>)
</pre></td></tr></table><p>where <i class="parameter"><tt>func</tt></i> is a function that is
invoked for each store row and has the signature:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  def func(<i class="parameter"><tt>model</tt></i>, <i class="parameter"><tt>path</tt></i>, <i class="parameter"><tt>iter</tt></i>, <i class="parameter"><tt>user_data</tt></i>):
</pre></td></tr></table><p>where <i class="parameter"><tt>model</tt></i> is the
<tt class="classname">TreeModel</tt> data store, <i class="parameter"><tt>path</tt></i> is
the tree path of a row in <i class="parameter"><tt>model</tt></i>,
<i class="parameter"><tt>iter</tt></i> is a <tt class="classname">TreeIter</tt> pointing at
<i class="parameter"><tt>path</tt></i> and <i class="parameter"><tt>user_data</tt></i> is the
passed in data. if <i class="parameter"><tt>func</tt></i> returns
<tt class="literal">TRUE</tt> the <tt class="methodname">foreach</tt>() method will
cease iterating and return.</p><p>The problem with that is that changing the contents of the store
while the <tt class="methodname">foreach</tt>() method is iterating over it may
have unpredictable results. Using the <tt class="methodname">foreach</tt>()
method to create and save TreeRowReferences to the rows to be removed and
then removing them after the <tt class="methodname">foreach</tt>() method
completes would be a good strategy except that it doesn't work for PyGTK 2.0
and 2.2 where <tt class="classname">TreeRowReference</tt>s are not
available.</p><p>A reliable strategy that covers all the PyGTK variants is to
use the <tt class="methodname">foreach</tt>() method to gather the tree paths
of rows to be removed and then remove them in reverse order to preserve the
validity of the tree paths. An example code fragment utilizing this
strategy is:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  ...
  # match if the value in the first column is &gt;= the passed in value
  # data is a tuple containing the match value and a list to save paths
  def match_value_cb(model, path, iter, data):
    if model.get_value(iter, 0) &gt;= data[0]:
      data[1].append(path)
    return False     # keep the foreach going

  pathlist = []
  treestore.foreach(match_value_cb, (10, pathlist))

  # foreach works in a depth first fashion
  pathlist.reverse()
  for path in pathlist:
    treestore.remove(treestore.get_iter(path))
  ...
</pre></td></tr></table><p>If you want to search a <tt class="classname">TreeStore</tt> for the
first row that matches some criteria, you probably want to do the iteration
yourself using something like:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
   treestore = TreeStore(str)
   ...
   def match_func(model, iter, data):
       column, key = data # data is a tuple containing column number, key
       value = model.get_value(iter, column)
       return value == key
   def search(model, iter, func, data):
       while iter:
           if func(model, iter, data):
               return iter
           result = search(model, model.iter_children(iter), func, data)
           if result: return result
           iter = model.iter_next(iter)
       return None
   ...
   match_iter = search(treestore, treestore.iter_children(None), 
                       match_func, (0, 'foo'))
</pre></td></tr></table><p>The <tt class="function">search</tt>() function iterates recursively
over the row (specified by <i class="parameter"><tt>iter</tt></i>) and its siblings and
their child rows in a depth first fashion looking for a row that has a
column matching the given key string. The search terminates when a row is
found.</p></div></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="sec-PythonProtocolSupport"></a>14.2.7. Python Protocol Support</h3></div></div><div></div></div><p>The classes that implement the <tt class="classname">TreeModel</tt>
interface (<tt class="classname">TreeStore</tt> and
<tt class="classname">ListStore</tt> and in PyGTK 2.4, also the
<tt class="classname">TreeModelSort</tt> and
<tt class="classname">TreeModelFilter</tt>) support the Python mapping and
iterator protocols. The iterator protocol allows you to use the Python
<tt class="function">iter</tt>() function on a <tt class="classname">TreeModel</tt>
to create an iterator to be used to iterate over the top level rows in the
<tt class="classname">TreeModel</tt>. A more useful capability is to iterate
using the <tt class="literal">for</tt> statement or a list comprehension. For
example:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  ...
  liststore = gtk.ListStore(str, str)
  ...
  # add some rows to liststore
  ...
  # for looping
  for row in liststore:
      # do individual row processing
  ...
  # list comprehension returning a list of values in the first column
  values = [ r[0] for r in liststore ]
  ...
</pre></td></tr></table><p>Other parts of the mapping protocols that are supported are using
<tt class="literal">del</tt> to delete a row in the model and extracting a PyGTK
<tt class="classname">TreeModelRow</tt> from the model using a key value that is
a tree path or <tt class="classname">TreeIter</tt>. For example, the following
statements all return the first row in a <tt class="classname">TreeModel</tt>
and the final statement deletes the first child row of the first row:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  row = model[0]
  row = model['0']
  row = model["0"]
  row = model[(0,)]
  i = model.get_iter(0)
  row = model[i]
  del model[(0,0)]
</pre></td></tr></table><p>In addition, you can set the values in an existing row similar
to the following:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  ...
  liststore = gtk.ListStore(str, int, object)
  ...
  liststore[0] = ['Button', 23, gtk.Button('Label')]
</pre></td></tr></table><p>A PyGTK <tt class="classname">TreeModelRow</tt> object supports the
Python sequence and iterator protocols. You can get an iterator to iterate
over the column values in the row or use the for statement or list
comprehension as well. A <tt class="classname">TreeModelRow</tt> uses the column
number as the index to extract a value. For example:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  ...
  liststore = gtk.ListStore(str, int)
  liststore.append(['Random string', 514])
  ...
  row = liststore[0]
  value1 = row[1]
  value0 = liststore['0'][0]
  for value in row:
      print value
  val0, val1 = row
  ...
</pre></td></tr></table><p>Using the example from the previous section to iterate over a
<tt class="classname">TreeStore</tt> to locate a row containing a particular
value, the code becomes:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
   treestore = TreeStore(str)
   ...
   def match_func(row, data):
       column, key = data # data is a tuple containing column number, key
       return row[column] == key
   ...
   def search(rows, func, data):
       if not rows: return None
       for row in rows:
           if func(row, data):
               return row
           result = search(row.iterchildren(), func, data)
           if result: return result
       return None
   ...
   match_row = search(treestore, match_func, (0, 'foo'))
</pre></td></tr></table><p>You can also set a value in an existing column using:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  treestore[(1,0,1)][1] = 'abc'
</pre></td></tr></table><p>The <tt class="classname">TreeModelRow</tt> also supports the
<tt class="literal">del</tt> statement and conversion to lists and tuples using
the Python <tt class="function">list</tt>() and <tt class="function">tuple</tt>()
functions. As illustrated in the above example the
<tt class="classname">TreeModelRow</tt> has the
<tt class="methodname">iterchildren</tt>() method that returns an iterator for
iterating over the child rows of the
<tt class="classname">TreeModelRow</tt>.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="sec-TreeModelSignals"></a>14.2.8. TreeModel Signals</h3></div></div><div></div></div><p>Your application can track changes in a
<tt class="classname">TreeModel</tt> by connecting to the signals that are
emitted by the <tt class="classname">TreeModel</tt>: "row-changed",
"row-deleted", "row-inserted", "row-has-child-toggled" and
"rows-reordered". These signals are used by a
<tt class="classname">TreeView</tt> to track changes in its
<tt class="classname">TreeModel</tt>.</p><p>If you connect to these signals in your application, you may see
clusters of signals when some methods are called. For example the call to
add the first child row to a parent row:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  treestore.append(parent, ['qwe', 'asd', 123])
</pre></td></tr></table><p>will cause the following signal emissions:</p><div class="itemizedlist"><ul type="disc"><li>"row-inserted" where the inserted row will be 
empty.</li><li>"row-has-child-toggled" since
<i class="parameter"><tt>parent</tt></i> didn't previously have any child
rows.</li><li>"row-changed" for the inserted row when setting the value
'qwe' in the first column.</li><li>"row-changed" for the inserted row when setting the value
'asd in the second column.</li><li>"row-changed" for the inserted row when setting the value
123 in the third column.</li></ul></div><p>Note that you can't retrieve the row order in the
"rows-reordered" callback since the new row order is passed as an opaque
pointer to an array of integers.</p><p>See the <a href="http://www.pygtk.org/pygtk2reference/class-gtktreemodel.html" target="_top">PyGTK
Reference Manual</a> for more information on the
<tt class="classname">TreeModel</tt> signals.</p></div><div class="sect2" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="sec-SortingTreeModelRows"></a>14.2.9. Sorting TreeModel Rows</h3></div></div><div></div></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="sec-TreeSortable"></a>14.2.9.1. The TreeSortable Interface</h4></div></div><div></div></div><p>The <tt class="classname">ListStore</tt> and
<tt class="classname">TreeStore</tt> objects implement the
<tt class="classname">TreeSortable</tt> interface that provides methods for
controlling the sorting of <tt class="classname">TreeModel</tt> rows. The key
element of the interface is a "sort column ID" which is an arbitrary integer
value referring to a sort comparison function and associated user data. A
sort column ID must be greater than or equal to zero. A sort column ID is
created by using the method:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  treesortable.set_sort_func(<i class="parameter"><tt>sort_column_id</tt></i>, <i class="parameter"><tt>sort_func</tt></i>, <i class="parameter"><tt>user_data</tt></i>=<tt class="literal">None</tt>)
</pre></td></tr></table><p>where <i class="parameter"><tt>sort_column_id</tt></i> is a programmer
assigned integer value, <i class="parameter"><tt>sort_func</tt></i> is a function or
method used to compare rows and <i class="parameter"><tt>user_data</tt></i> is context
data. <i class="parameter"><tt>sort_func</tt></i> has the signature:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  def sort_func_function(model, iter1, iter2, data)
  def sort_func_method(self, model, iter1, iter2, data)
</pre></td></tr></table><p>where <i class="parameter"><tt>model</tt></i> is the
<tt class="classname">TreeModel</tt> containing the rows pointed to by the
<tt class="classname">TreeIter</tt>s <i class="parameter"><tt>iter1</tt></i> and
<i class="parameter"><tt>iter2</tt></i> and <i class="parameter"><tt>data</tt></i> is
<i class="parameter"><tt>user_data</tt></i>. <i class="parameter"><tt>sort_func</tt></i> should
return: -1 if the <i class="parameter"><tt>iter1</tt></i> row should precede the
<i class="parameter"><tt>iter2</tt></i> row; 0, if the rows are equal; and, 1 if the
<i class="parameter"><tt>iter2</tt></i> row should precede the
<i class="parameter"><tt>iter1</tt></i> row. The sort comparison function should always
assume that the sort order is <tt class="literal">gtk.SORT_ASCENDING</tt> as the
sort order will be taken into account by the
<tt class="classname">TreeSortable</tt> implementations.</p><p>The same sort comparison function can be used for multiple sort
column IDs by varying the user_data to provide context information. For
example, the <i class="parameter"><tt>user_data</tt></i> specified in the
<tt class="methodname">set_sort_func</tt>() method could be the index of the
column to extract the sort data from.</p><p>Once a sort column ID is created a store can use it for sorting
by calling the method:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  treesortable.set_sort_column_id(<b class="parameter"><tt>sort_column_id</tt></b>, <b class="parameter"><tt>order</tt></b>)
</pre></td></tr></table><p>where <i class="parameter"><tt>order</tt></i> is the sort order either
<tt class="literal">gtk.SORT_ASCENDING</tt> or
<tt class="literal">gtk.SORT_DESCENDING</tt>.</p><p>The sort column ID of -1 means that the store should use the
default sort function that is set using the method:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  treesortable.set_default_sort_func(<i class="parameter"><tt>sort_func</tt></i>, <i class="parameter"><tt>user_data</tt></i>=<tt class="literal">None</tt>)
</pre></td></tr></table><p>You can check if a store has a default sort function using the
method:</p><table border="0" bgcolor="#E0E0E0" width="100%"><tr><td><pre class="programlisting">
  result = treesortable.has_default_sort_func()
</pre></td></tr></table><p>which returns <tt class="literal">TRUE</tt> if a default sort function
has been set.</p><p>Once a sort column ID has been set on a
<tt class="classname">TreeModel</tt> implementing the
<tt class="classname">TreeSortable</tt> interface it cannot be returned to the
original unsorted state. You can change the sort function or use a default
sort function but you cannot set the <tt class="classname">TreeModel</tt> to
have no sort function.</p></div><div class="sect3" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="sec-SortingStores"></a>14.2.9.2. Sorting in ListStores and TreeStores</h4></div></div><div></div></div><p>When a <tt class="classname">ListStore</tt> or
<tt class="classname">TreeStore</tt> object is created it automatically sets up
sort column IDs corresponding to the columns in the store using the column
index number. For example, a <tt class="classname">ListStore</tt> with three
columns would have three sort column IDs (0, 1, 2) setup
automatically. These sort column IDs are associated with an internal sort
comparison function that handles the fundamental types:</p><div class="itemizedlist"><ul type="disc"><li>'gboolean'</li><li>str</li><li>int</li><li>long</li><li>float</li></ul></div><p>Initially a <tt class="classname">ListStore</tt> or
<tt class="classname">TreeStore</tt> is set with a sort column ID of -2 that
indicates that no sort function is being used and that the store is
unsorted. Once you set a sort column ID on a
<tt class="classname">ListStore</tt> or <tt class="classname">TreeStore</tt> you
cannot set it back to -2.</p><p>If you want to maintain the default sort column IDs you can set up
a sort column ID well out of the range of the number of columns such as 1000
and up. Then you can switch between the default sort function and your
application sort functions as needed.</p></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ch-TreeViewWidget.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="ch-TreeViewWidget.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="sec-TreeViews.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter 14. Tree View Widget </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 14.3. TreeViews</td></tr></table></div></body></html>