Imported Upstream version 3.7.3
[platform/upstream/python-gobject.git] / tests / test_overrides_gtk.py
1 # -*- Mode: Python; py-indent-offset: 4 -*-
2 # vim: tabstop=4 shiftwidth=4 expandtab
3
4 import unittest
5
6 from compathelper import _unicode, _bytes
7
8 import gi.overrides
9 import gi.types
10 from gi.repository import GLib, GObject
11
12 try:
13     from gi.repository import GdkPixbuf, Gdk, Gtk
14     Gtk  # pyflakes
15 except ImportError:
16     Gtk = None
17
18
19 @unittest.skipUnless(Gtk, 'Gtk not available')
20 class TestGtk(unittest.TestCase):
21     def test_container(self):
22         box = Gtk.Box()
23         self.assertTrue(isinstance(box, Gtk.Box))
24         self.assertTrue(isinstance(box, Gtk.Container))
25         self.assertTrue(isinstance(box, Gtk.Widget))
26         self.assertTrue(box)
27         label = Gtk.Label()
28         label2 = Gtk.Label()
29         box.add(label)
30         box.add(label2)
31         self.assertTrue(label in box)
32         self.assertTrue(label2 in box)
33         self.assertEqual(len(box), 2)
34         self.assertTrue(box)
35         l = [x for x in box]
36         self.assertEqual(l, [label, label2])
37
38     def test_actions(self):
39         self.assertEqual(Gtk.Action, gi.overrides.Gtk.Action)
40         self.assertRaises(TypeError, Gtk.Action)
41         action = Gtk.Action("test", "Test", "Test Action", Gtk.STOCK_COPY)
42         self.assertEqual(action.get_name(), "test")
43         self.assertEqual(action.get_label(), "Test")
44         self.assertEqual(action.get_tooltip(), "Test Action")
45         self.assertEqual(action.get_stock_id(), Gtk.STOCK_COPY)
46
47         self.assertEqual(Gtk.RadioAction, gi.overrides.Gtk.RadioAction)
48         self.assertRaises(TypeError, Gtk.RadioAction)
49         action = Gtk.RadioAction("test", "Test", "Test Action", Gtk.STOCK_COPY, 1)
50         self.assertEqual(action.get_name(), "test")
51         self.assertEqual(action.get_label(), "Test")
52         self.assertEqual(action.get_tooltip(), "Test Action")
53         self.assertEqual(action.get_stock_id(), Gtk.STOCK_COPY)
54         self.assertEqual(action.get_current_value(), 1)
55
56     def test_actiongroup(self):
57         self.assertEqual(Gtk.ActionGroup, gi.overrides.Gtk.ActionGroup)
58         self.assertRaises(TypeError, Gtk.ActionGroup)
59
60         action_group = Gtk.ActionGroup(name='TestActionGroup')
61         callback_data = "callback data"
62
63         def test_action_callback_data(action, user_data):
64             self.assertEqual(user_data, callback_data)
65
66         def test_radio_action_callback_data(action, current, user_data):
67             self.assertEqual(user_data, callback_data)
68
69         action_group.add_actions([
70             ('test-action1', None, 'Test Action 1',
71              None, None, test_action_callback_data),
72             ('test-action2', Gtk.STOCK_COPY, 'Test Action 2',
73              None, None, test_action_callback_data)], callback_data)
74         action_group.add_toggle_actions([
75             ('test-toggle-action1', None, 'Test Toggle Action 1',
76              None, None, test_action_callback_data, False),
77             ('test-toggle-action2', Gtk.STOCK_COPY, 'Test Toggle Action 2',
78              None, None, test_action_callback_data, True)], callback_data)
79         action_group.add_radio_actions([
80             ('test-radio-action1', None, 'Test Radio Action 1'),
81             ('test-radio-action2', Gtk.STOCK_COPY, 'Test Radio Action 2')], 1,
82             test_radio_action_callback_data,
83             callback_data)
84
85         expected_results = [('test-action1', Gtk.Action),
86                             ('test-action2', Gtk.Action),
87                             ('test-toggle-action1', Gtk.ToggleAction),
88                             ('test-toggle-action2', Gtk.ToggleAction),
89                             ('test-radio-action1', Gtk.RadioAction),
90                             ('test-radio-action2', Gtk.RadioAction)]
91
92         for action in action_group.list_actions():
93             a = (action.get_name(), type(action))
94             self.assertTrue(a in expected_results)
95             expected_results.remove(a)
96             action.activate()
97
98     def test_uimanager(self):
99         self.assertEqual(Gtk.UIManager, gi.overrides.Gtk.UIManager)
100         ui = Gtk.UIManager()
101         ui.add_ui_from_string("""<ui>
102     <menubar name="menubar1"></menubar>
103 </ui>
104 """
105 )
106         menubar = ui.get_widget("/menubar1")
107         self.assertEqual(type(menubar), Gtk.MenuBar)
108
109         ag = Gtk.ActionGroup(name="ag1")
110         ui.insert_action_group(ag)
111         ag2 = Gtk.ActionGroup(name="ag2")
112         ui.insert_action_group(ag2)
113         groups = ui.get_action_groups()
114         self.assertEqual(ag, groups[-2])
115         self.assertEqual(ag2, groups[-1])
116
117     def test_builder(self):
118         self.assertEqual(Gtk.Builder, gi.overrides.Gtk.Builder)
119
120         class SignalTest(GObject.GObject):
121             __gtype_name__ = "GIOverrideSignalTest"
122             __gsignals__ = {
123                 "test-signal": (GObject.SignalFlags.RUN_FIRST,
124                                 None,
125                                 []),
126             }
127
128         class SignalCheck:
129             def __init__(self):
130                 self.sentinel = 0
131                 self.after_sentinel = 0
132
133             def on_signal_1(self, *args):
134                 self.sentinel += 1
135                 self.after_sentinel += 1
136
137             def on_signal_3(self, *args):
138                 self.sentinel += 3
139
140             def on_signal_after(self, *args):
141                 if self.after_sentinel == 1:
142                     self.after_sentinel += 1
143
144         signal_checker = SignalCheck()
145         builder = Gtk.Builder()
146
147         # add object1 to the builder
148         builder.add_from_string("""
149 <interface>
150   <object class="GIOverrideSignalTest" id="object1">
151       <signal name="test-signal" after="yes" handler="on_signal_after" />
152       <signal name="test-signal" handler="on_signal_1" />
153   </object>
154 </interface>
155 """)
156
157         # only add object3 to the builder
158         builder.add_objects_from_string("""
159 <interface>
160   <object class="GIOverrideSignalTest" id="object2">
161       <signal name="test-signal" handler="on_signal_2" />
162   </object>
163   <object class="GIOverrideSignalTest" id="object3">
164       <signal name="test-signal" handler="on_signal_3" />
165   </object>
166   <object class="GIOverrideSignalTest" id="object4">
167       <signal name="test-signal" handler="on_signal_4" />
168   </object>
169 </interface>
170 """, ['object3'])
171
172         # hook up signals
173         builder.connect_signals(signal_checker)
174
175         # call their notify signals and check sentinel
176         objects = builder.get_objects()
177         self.assertEqual(len(objects), 2)
178         for obj in objects:
179             obj.emit('test-signal')
180
181         self.assertEqual(signal_checker.sentinel, 4)
182         self.assertEqual(signal_checker.after_sentinel, 2)
183
184     def test_window(self):
185         # standard Window
186         w = Gtk.Window()
187         self.assertEqual(w.get_property('type'), Gtk.WindowType.TOPLEVEL)
188
189         # type works as keyword argument
190         w = Gtk.Window(type=Gtk.WindowType.POPUP)
191         self.assertEqual(w.get_property('type'), Gtk.WindowType.POPUP)
192
193         # pygtk compatible positional argument
194         w = Gtk.Window(Gtk.WindowType.POPUP)
195         self.assertEqual(w.get_property('type'), Gtk.WindowType.POPUP)
196
197         class TestWindow(Gtk.Window):
198             __gtype_name__ = "TestWindow"
199
200         # works from builder
201         builder = Gtk.Builder()
202         builder.add_from_string('''
203 <interface>
204   <object class="GtkWindow" id="win">
205     <property name="type">popup</property>
206   </object>
207   <object class="TestWindow" id="testwin">
208   </object>
209   <object class="TestWindow" id="testpop">
210     <property name="type">popup</property>
211   </object>
212 </interface>''')
213         self.assertEqual(builder.get_object('win').get_property('type'),
214                          Gtk.WindowType.POPUP)
215         self.assertEqual(builder.get_object('testwin').get_property('type'),
216                          Gtk.WindowType.TOPLEVEL)
217         self.assertEqual(builder.get_object('testpop').get_property('type'),
218                          Gtk.WindowType.POPUP)
219
220     def test_dialogs(self):
221         self.assertEqual(Gtk.Dialog, gi.overrides.Gtk.Dialog)
222         self.assertEqual(Gtk.AboutDialog, gi.overrides.Gtk.AboutDialog)
223         self.assertEqual(Gtk.MessageDialog, gi.overrides.Gtk.MessageDialog)
224         self.assertEqual(Gtk.ColorSelectionDialog, gi.overrides.Gtk.ColorSelectionDialog)
225         self.assertEqual(Gtk.FileChooserDialog, gi.overrides.Gtk.FileChooserDialog)
226         self.assertEqual(Gtk.FontSelectionDialog, gi.overrides.Gtk.FontSelectionDialog)
227         self.assertEqual(Gtk.RecentChooserDialog, gi.overrides.Gtk.RecentChooserDialog)
228
229         # Gtk.Dialog
230         dialog = Gtk.Dialog(title='Foo',
231                             flags=Gtk.DialogFlags.MODAL,
232                             buttons=('test-button1', 1))
233         self.assertTrue(isinstance(dialog, Gtk.Dialog))
234         self.assertTrue(isinstance(dialog, Gtk.Window))
235
236         dialog.add_buttons('test-button2', 2, Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE)
237
238         self.assertEqual('Foo', dialog.get_title())
239         self.assertTrue(dialog.get_modal())
240         button = dialog.get_widget_for_response(1)
241         self.assertEqual('test-button1', button.get_label())
242         button = dialog.get_widget_for_response(2)
243         self.assertEqual('test-button2', button.get_label())
244         button = dialog.get_widget_for_response(Gtk.ResponseType.CLOSE)
245         self.assertEqual(Gtk.STOCK_CLOSE, button.get_label())
246
247         # Gtk.AboutDialog
248         dialog = Gtk.AboutDialog()
249         self.assertTrue(isinstance(dialog, Gtk.Dialog))
250         self.assertTrue(isinstance(dialog, Gtk.Window))
251
252         # Gtk.MessageDialog
253         dialog = Gtk.MessageDialog(title='message dialog test',
254                                    flags=Gtk.DialogFlags.MODAL,
255                                    buttons=Gtk.ButtonsType.OK,
256                                    message_format='dude!')
257         self.assertTrue(isinstance(dialog, Gtk.Dialog))
258         self.assertTrue(isinstance(dialog, Gtk.Window))
259
260         self.assertEqual('message dialog test', dialog.get_title())
261         self.assertTrue(dialog.get_modal())
262         text = dialog.get_property('text')
263         self.assertEqual('dude!', text)
264
265         dialog.format_secondary_text('2nd text')
266         self.assertEqual(dialog.get_property('secondary-text'), '2nd text')
267         self.assertFalse(dialog.get_property('secondary-use-markup'))
268
269         dialog.format_secondary_markup('2nd markup')
270         self.assertEqual(dialog.get_property('secondary-text'), '2nd markup')
271         self.assertTrue(dialog.get_property('secondary-use-markup'))
272
273         # Gtk.ColorSelectionDialog
274         dialog = Gtk.ColorSelectionDialog("color selection dialog test")
275         self.assertTrue(isinstance(dialog, Gtk.Dialog))
276         self.assertTrue(isinstance(dialog, Gtk.Window))
277         self.assertEqual('color selection dialog test', dialog.get_title())
278
279         # Gtk.FileChooserDialog
280         # might cause a GVFS warning, do not break on this
281         old_mask = GLib.log_set_always_fatal(
282             GLib.LogLevelFlags.LEVEL_CRITICAL | GLib.LogLevelFlags.LEVEL_ERROR)
283         try:
284             dialog = Gtk.FileChooserDialog(title='file chooser dialog test',
285                                            buttons=('test-button1', 1),
286                                            action=Gtk.FileChooserAction.SAVE)
287         finally:
288             GLib.log_set_always_fatal(old_mask)
289         self.assertTrue(isinstance(dialog, Gtk.Dialog))
290         self.assertTrue(isinstance(dialog, Gtk.Window))
291
292         dialog.add_buttons('test-button2', 2, Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE)
293         self.assertEqual('file chooser dialog test', dialog.get_title())
294         button = dialog.get_widget_for_response(1)
295         self.assertEqual('test-button1', button.get_label())
296         button = dialog.get_widget_for_response(2)
297         self.assertEqual('test-button2', button.get_label())
298         button = dialog.get_widget_for_response(Gtk.ResponseType.CLOSE)
299         self.assertEqual(Gtk.STOCK_CLOSE, button.get_label())
300         action = dialog.get_property('action')
301         self.assertEqual(Gtk.FileChooserAction.SAVE, action)
302
303         # Gtk.FontSelectionDialog
304         dialog = Gtk.ColorSelectionDialog("font selection dialog test")
305         self.assertTrue(isinstance(dialog, Gtk.Dialog))
306         self.assertTrue(isinstance(dialog, Gtk.Window))
307         self.assertEqual('font selection dialog test', dialog.get_title())
308
309         # Gtk.RecentChooserDialog
310         test_manager = Gtk.RecentManager()
311         dialog = Gtk.RecentChooserDialog(title='recent chooser dialog test',
312                                          buttons=('test-button1', 1),
313                                          manager=test_manager)
314         self.assertTrue(isinstance(dialog, Gtk.Dialog))
315         self.assertTrue(isinstance(dialog, Gtk.Window))
316
317         dialog.add_buttons('test-button2', 2, Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE)
318         self.assertEqual('recent chooser dialog test', dialog.get_title())
319         button = dialog.get_widget_for_response(1)
320         self.assertEqual('test-button1', button.get_label())
321         button = dialog.get_widget_for_response(2)
322         self.assertEqual('test-button2', button.get_label())
323         button = dialog.get_widget_for_response(Gtk.ResponseType.CLOSE)
324         self.assertEqual(Gtk.STOCK_CLOSE, button.get_label())
325
326     class TestClass(GObject.GObject):
327         __gtype_name__ = "GIOverrideTreeAPITest"
328
329         def __init__(self, tester, int_value, string_value):
330             super(TestGtk.TestClass, self).__init__()
331             self.tester = tester
332             self.int_value = int_value
333             self.string_value = string_value
334
335         def check(self, int_value, string_value):
336             self.tester.assertEqual(int_value, self.int_value)
337             self.tester.assertEqual(string_value, self.string_value)
338
339     def test_buttons(self):
340         self.assertEqual(Gtk.Button, gi.overrides.Gtk.Button)
341
342         # test Gtk.Button
343         button = Gtk.Button()
344         self.assertTrue(isinstance(button, Gtk.Button))
345         self.assertTrue(isinstance(button, Gtk.Container))
346         self.assertTrue(isinstance(button, Gtk.Widget))
347         button = Gtk.Button(stock=Gtk.STOCK_CLOSE)
348         self.assertEqual(Gtk.STOCK_CLOSE, button.get_label())
349         self.assertTrue(button.get_use_stock())
350         self.assertTrue(button.get_use_underline())
351
352         # test Gtk.Button use_stock
353         button = Gtk.Button(label=Gtk.STOCK_CLOSE, use_stock=True, use_underline=True)
354         self.assertEqual(Gtk.STOCK_CLOSE, button.get_label())
355         self.assertTrue(button.get_use_stock())
356         self.assertTrue(button.get_use_underline())
357
358         # test Gtk.LinkButton
359         self.assertRaises(TypeError, Gtk.LinkButton)
360         button = Gtk.LinkButton('http://www.Gtk.org', 'Gtk')
361         self.assertTrue(isinstance(button, Gtk.Button))
362         self.assertTrue(isinstance(button, Gtk.Container))
363         self.assertTrue(isinstance(button, Gtk.Widget))
364         self.assertEqual('http://www.Gtk.org', button.get_uri())
365         self.assertEqual('Gtk', button.get_label())
366
367     def test_inheritance(self):
368         for name in gi.overrides.Gtk.__all__:
369             over = getattr(gi.overrides.Gtk, name)
370             for element in dir(Gtk):
371                 try:
372                     klass = getattr(Gtk, element)
373                     info = klass.__info__
374                 except (NotImplementedError, AttributeError):
375                     continue
376
377                 # Get all parent classes and interfaces klass inherits from
378                 if isinstance(info, gi.types.ObjectInfo):
379                     classes = list(info.get_interfaces())
380                     parent = info.get_parent()
381                     while parent.get_name() != "Object":
382                         classes.append(parent)
383                         parent = parent.get_parent()
384                     classes = [kl for kl in classes if kl.get_namespace() == "Gtk"]
385                 else:
386                     continue
387
388                 for kl in classes:
389                     if kl.get_name() == name:
390                         self.assertTrue(issubclass(klass, over,),
391                                         "%r does not inherit from override %r" % (klass, over,))
392
393     def test_editable(self):
394         self.assertEqual(Gtk.Editable, gi.overrides.Gtk.Editable)
395
396         # need to use Gtk.Entry because Editable is an interface
397         entry = Gtk.Entry()
398         pos = entry.insert_text('HeWorld', 0)
399         self.assertEqual(pos, 7)
400         pos = entry.insert_text('llo ', 2)
401         self.assertEqual(pos, 6)
402         text = entry.get_chars(0, 11)
403         self.assertEqual('Hello World', text)
404
405     def test_label(self):
406         label = Gtk.Label(label='Hello')
407         self.assertTrue(isinstance(label, Gtk.Widget))
408         self.assertEqual(label.get_text(), 'Hello')
409
410     def adjustment_check(self, adjustment, value=0.0, lower=0.0, upper=0.0,
411                          step_increment=0.0, page_increment=0.0, page_size=0.0):
412         self.assertEqual(adjustment.get_value(), value)
413         self.assertEqual(adjustment.get_lower(), lower)
414         self.assertEqual(adjustment.get_upper(), upper)
415         self.assertEqual(adjustment.get_step_increment(), step_increment)
416         self.assertEqual(adjustment.get_page_increment(), page_increment)
417         self.assertEqual(adjustment.get_page_size(), page_size)
418
419     def test_adjustment(self):
420         adjustment = Gtk.Adjustment(1, 0, 6, 4, 5, 3)
421         self.adjustment_check(adjustment, 1, 0, 6, 4, 5, 3)
422
423         adjustment = Gtk.Adjustment(1, 0, 6, 4, 5)
424         self.adjustment_check(adjustment, 1, 0, 6, 4, 5)
425
426         adjustment = Gtk.Adjustment(1, 0, 6, 4)
427         self.adjustment_check(adjustment, 1, 0, 6, 4)
428
429         adjustment = Gtk.Adjustment(1, 0, 6)
430         self.adjustment_check(adjustment, 1, 0, 6)
431
432         adjustment = Gtk.Adjustment()
433         self.adjustment_check(adjustment)
434
435         adjustment = Gtk.Adjustment(value=1, lower=0, upper=6,
436                                     step_increment=4, page_increment=5, page_size=3)
437         self.adjustment_check(adjustment, 1, 0, 6, 4, 5, 3)
438
439     def test_table(self):
440         table = Gtk.Table()
441         self.assertTrue(isinstance(table, Gtk.Table))
442         self.assertTrue(isinstance(table, Gtk.Container))
443         self.assertTrue(isinstance(table, Gtk.Widget))
444         self.assertEqual(table.get_size(), (1, 1))
445         self.assertEqual(table.get_homogeneous(), False)
446         table = Gtk.Table(2, 3)
447         self.assertEqual(table.get_size(), (2, 3))
448         self.assertEqual(table.get_homogeneous(), False)
449         table = Gtk.Table(2, 3, True)
450         self.assertEqual(table.get_size(), (2, 3))
451         self.assertEqual(table.get_homogeneous(), True)
452
453         # Test PyGTK interface
454         table = Gtk.Table(rows=3, columns=2)
455         self.assertEqual(table.get_size(), (3, 2))
456         # Test using the actual property names
457         table = Gtk.Table(n_rows=2, n_columns=3, homogeneous=True)
458         self.assertEqual(table.get_size(), (2, 3))
459         self.assertEqual(table.get_homogeneous(), True)
460
461         label = Gtk.Label(label='Hello')
462         self.assertTrue(isinstance(label, Gtk.Widget))
463         table.attach(label, 0, 1, 0, 1)
464         self.assertEqual(label, table.get_children()[0])
465
466     def test_scrolledwindow(self):
467         sw = Gtk.ScrolledWindow()
468         self.assertTrue(isinstance(sw, Gtk.ScrolledWindow))
469         self.assertTrue(isinstance(sw, Gtk.Container))
470         self.assertTrue(isinstance(sw, Gtk.Widget))
471         sb = sw.get_hscrollbar()
472         self.assertEqual(sw.get_hadjustment(), sb.get_adjustment())
473         sb = sw.get_vscrollbar()
474         self.assertEqual(sw.get_vadjustment(), sb.get_adjustment())
475
476     def test_widget_drag_methods(self):
477         widget = Gtk.Button()
478
479         # here we are not checking functionality, only that the methods exist
480         # and except the right number of arguments
481
482         widget.drag_check_threshold(0, 0, 0, 0)
483
484         # drag_dest_ methods
485         widget.drag_dest_set(Gtk.DestDefaults.DROP, None, Gdk.DragAction.COPY)
486         widget.drag_dest_add_image_targets()
487         widget.drag_dest_add_text_targets()
488         widget.drag_dest_add_uri_targets()
489         widget.drag_dest_get_track_motion()
490         widget.drag_dest_set_track_motion(True)
491         widget.drag_dest_get_target_list()
492         widget.drag_dest_set_target_list(Gtk.TargetList.new([Gtk.TargetEntry.new('test', 0, 0)]))
493         widget.drag_dest_unset()
494
495         widget.drag_highlight()
496         widget.drag_unhighlight()
497
498         # drag_source_ methods
499         widget.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, None, Gdk.DragAction.MOVE)
500         widget.drag_source_add_image_targets()
501         widget.drag_source_add_text_targets()
502         widget.drag_source_add_uri_targets()
503         widget.drag_source_set_icon_name("")
504         widget.drag_source_set_icon_pixbuf(GdkPixbuf.Pixbuf())
505         widget.drag_source_set_icon_stock("")
506         widget.drag_source_get_target_list()
507         widget.drag_source_set_target_list(Gtk.TargetList.new([Gtk.TargetEntry.new('test', 0, 0)]))
508         widget.drag_source_unset()
509
510         # these methods cannot be called because they require a valid drag on
511         # a real GdkWindow. So we only check that they exist and are callable.
512         self.assertTrue(hasattr(widget.drag_dest_set_proxy, '__call__'))
513         self.assertTrue(hasattr(widget.drag_get_data, '__call__'))
514
515     def test_scrollbar(self):
516         # PyGTK compat
517         adjustment = Gtk.Adjustment()
518
519         hscrollbar = Gtk.HScrollbar()
520         vscrollbar = Gtk.VScrollbar()
521         self.assertNotEqual(hscrollbar.props.adjustment, adjustment)
522         self.assertNotEqual(vscrollbar.props.adjustment, adjustment)
523
524         hscrollbar = Gtk.HScrollbar(adjustment)
525         vscrollbar = Gtk.VScrollbar(adjustment)
526         self.assertEqual(hscrollbar.props.adjustment, adjustment)
527         self.assertEqual(vscrollbar.props.adjustment, adjustment)
528
529     def test_iconview(self):
530         # PyGTK compat
531         iconview = Gtk.IconView()
532         self.assertEqual(iconview.props.model, None)
533
534         model = Gtk.ListStore(str)
535         iconview = Gtk.IconView(model)
536         self.assertEqual(iconview.props.model, model)
537
538     def test_toolbutton(self):
539         # PyGTK compat
540         button = Gtk.ToolButton()
541         self.assertEqual(button.props.stock_id, None)
542
543         button = Gtk.ToolButton('gtk-new')
544         self.assertEqual(button.props.stock_id, 'gtk-new')
545
546         icon = Gtk.Image.new_from_stock(Gtk.STOCK_OPEN, Gtk.IconSize.SMALL_TOOLBAR)
547
548         button = Gtk.ToolButton(label='mylabel', icon_widget=icon)
549         self.assertEqual(button.props.label, 'mylabel')
550         self.assertEqual(button.props.icon_widget, icon)
551
552     def test_iconset(self):
553         # PyGTK compat
554         Gtk.IconSet()
555         pixbuf = GdkPixbuf.Pixbuf()
556         Gtk.IconSet(pixbuf)
557
558     def test_viewport(self):
559         # PyGTK compat
560         vadjustment = Gtk.Adjustment()
561         hadjustment = Gtk.Adjustment()
562
563         viewport = Gtk.Viewport(hadjustment=hadjustment,
564                                 vadjustment=vadjustment)
565
566         self.assertEqual(viewport.props.vadjustment, vadjustment)
567         self.assertEqual(viewport.props.hadjustment, hadjustment)
568
569
570 @unittest.skipUnless(Gtk, 'Gtk not available')
571 class TestTreeModel(unittest.TestCase):
572     def test_tree_model_sort(self):
573         self.assertEqual(Gtk.TreeModelSort, gi.overrides.Gtk.TreeModelSort)
574         self.assertRaises(TypeError, Gtk.TreeModelSort)
575         model = Gtk.TreeStore(int, bool)
576         model_sort = Gtk.TreeModelSort(model)
577         self.assertEqual(model_sort.get_model(), model)
578
579     def test_tree_store(self):
580         self.assertEqual(Gtk.TreeStore, gi.overrides.Gtk.TreeStore)
581         self.assertEqual(Gtk.ListStore, gi.overrides.Gtk.ListStore)
582         self.assertEqual(Gtk.TreeModel, gi.overrides.Gtk.TreeModel)
583         self.assertEqual(Gtk.TreeViewColumn, gi.overrides.Gtk.TreeViewColumn)
584
585         class TestPyObject(object):
586             pass
587
588         test_pyobj = TestPyObject()
589         test_pydict = {1: 1, "2": 2, "3": "3"}
590         test_pylist = [1, "2", "3"]
591         tree_store = Gtk.TreeStore(int,
592                                    'gchararray',
593                                    TestGtk.TestClass,
594                                    GObject.TYPE_PYOBJECT,
595                                    object,
596                                    object,
597                                    object,
598                                    bool,
599                                    bool,
600                                    GObject.TYPE_UINT,
601                                    GObject.TYPE_ULONG,
602                                    GObject.TYPE_INT64,
603                                    GObject.TYPE_UINT64,
604                                    GObject.TYPE_UCHAR,
605                                    GObject.TYPE_CHAR)
606
607         parent = None
608         for i in range(97):
609             label = 'this is child #%d' % i
610             testobj = TestGtk.TestClass(self, i, label)
611             parent = tree_store.append(parent, (i,
612                                                 label,
613                                                 testobj,
614                                                 testobj,
615                                                 test_pyobj,
616                                                 test_pydict,
617                                                 test_pylist,
618                                                 i % 2,
619                                                 bool(i % 2),
620                                                 i,
621                                                 GObject.G_MAXULONG,
622                                                 GObject.G_MININT64,
623                                                 0xffffffffffffffff,
624                                                 254,
625                                                 _bytes('a')
626                                                 ))
627         # test set
628         parent = tree_store.append(parent)
629         i = 97
630         label = 'this is child #%d' % i
631         testobj = TestGtk.TestClass(self, i, label)
632         tree_store.set(parent,
633                        0, i,
634                        2, testobj,
635                        1, label,
636                        3, testobj,
637                        4, test_pyobj,
638                        5, test_pydict,
639                        6, test_pylist,
640                        7, i % 2,
641                        8, bool(i % 2),
642                        9, i,
643                        10, GObject.G_MAXULONG,
644                        11, GObject.G_MININT64,
645                        12, 0xffffffffffffffff,
646                        13, 254,
647                        14, _bytes('a'))
648
649         parent = tree_store.append(parent)
650         i = 98
651         label = 'this is child #%d' % i
652         testobj = TestGtk.TestClass(self, i, label)
653         tree_store.set(parent, {0: i,
654                                 2: testobj,
655                                 1: label,
656                                 3: testobj,
657                                 4: test_pyobj,
658                                 5: test_pydict,
659                                 6: test_pylist,
660                                 7: i % 2,
661                                 8: bool(i % 2),
662                                 9: i,
663                                 10: GObject.G_MAXULONG,
664                                 11: GObject.G_MININT64,
665                                 12: 0xffffffffffffffff,
666                                 13: 254,
667                                 14: _bytes('a')})
668
669         parent = tree_store.append(parent)
670         i = 99
671         label = 'this is child #%d' % i
672         testobj = TestGtk.TestClass(self, i, label)
673         tree_store.set(parent, (0, 2, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14),
674                                (i,
675                                 testobj,
676                                 label,
677                                 testobj,
678                                 test_pyobj,
679                                 test_pydict,
680                                 test_pylist,
681                                 i % 2,
682                                 bool(i % 2),
683                                 i,
684                                 GObject.G_MAXULONG,
685                                 GObject.G_MININT64,
686                                 0xffffffffffffffff,
687                                 254,
688                                 _bytes('a')))
689
690         # len gets the number of children in the root node
691         # since we kept appending to the previous node
692         # there should only be one child of the root
693         self.assertEqual(len(tree_store), 1)
694
695         # walk the tree to see if the values were stored correctly
696         parent = None
697         i = 0
698
699         treeiter = tree_store.iter_children(parent)
700         while treeiter:
701             i = tree_store.get_value(treeiter, 0)
702             s = tree_store.get_value(treeiter, 1)
703             obj = tree_store.get_value(treeiter, 2)
704             obj.check(i, s)
705             obj2 = tree_store.get_value(treeiter, 3)
706             self.assertEqual(obj, obj2)
707
708             pyobj = tree_store.get_value(treeiter, 4)
709             self.assertEqual(pyobj, test_pyobj)
710             pydict = tree_store.get_value(treeiter, 5)
711             self.assertEqual(pydict, test_pydict)
712             pylist = tree_store.get_value(treeiter, 6)
713             self.assertEqual(pylist, test_pylist)
714
715             bool_1 = tree_store.get_value(treeiter, 7)
716             bool_2 = tree_store.get_value(treeiter, 8)
717             self.assertEqual(bool_1, bool_2)
718             self.assertTrue(isinstance(bool_1, bool))
719             self.assertTrue(isinstance(bool_2, bool))
720
721             uint_ = tree_store.get_value(treeiter, 9)
722             self.assertEqual(uint_, i)
723             ulong_ = tree_store.get_value(treeiter, 10)
724             self.assertEqual(ulong_, GObject.G_MAXULONG)
725             int64_ = tree_store.get_value(treeiter, 11)
726             self.assertEqual(int64_, GObject.G_MININT64)
727             uint64_ = tree_store.get_value(treeiter, 12)
728             self.assertEqual(uint64_, 0xffffffffffffffff)
729             uchar_ = tree_store.get_value(treeiter, 13)
730             self.assertEqual(ord(uchar_), 254)
731             char_ = tree_store.get_value(treeiter, 14)
732             self.assertEqual(char_, 'a')
733
734             parent = treeiter
735             treeiter = tree_store.iter_children(parent)
736
737         self.assertEqual(i, 99)
738
739     def test_tree_store_signals(self):
740         tree_store = Gtk.TreeStore(int, bool)
741
742         def on_row_inserted(tree_store, tree_path, tree_iter, signal_list):
743             signal_list.append('row-inserted')
744
745         def on_row_changed(tree_store, tree_path, tree_iter, signal_list):
746             signal_list.append('row-changed')
747
748         signals = []
749         tree_store.connect('row-inserted', on_row_inserted, signals)
750         tree_store.connect('row-changed', on_row_changed, signals)
751
752         # adding rows with and without data should only call one signal
753         tree_store.append(None, (0, False))
754         self.assertEqual(signals, ['row-inserted'])
755
756         signals.pop()
757         tree_store.append(None)
758         self.assertEqual(signals, ['row-inserted'])
759
760         signals.pop()
761         tree_store.prepend(None, (0, False))
762         self.assertEqual(signals, ['row-inserted'])
763
764         signals.pop()
765         tree_store.prepend(None)
766         self.assertEqual(signals, ['row-inserted'])
767
768         signals.pop()
769         tree_store.insert(None, 1, (0, False))
770         self.assertEqual(signals, ['row-inserted'])
771
772         signals.pop()
773         tree_store.insert(None, 1)
774         self.assertEqual(signals, ['row-inserted'])
775
776     def test_list_store(self):
777         class TestPyObject(object):
778             pass
779
780         test_pyobj = TestPyObject()
781         test_pydict = {1: 1, "2": 2, "3": "3"}
782         test_pylist = [1, "2", "3"]
783
784         list_store = Gtk.ListStore(int, str, 'GIOverrideTreeAPITest', object, object, object, bool, bool)
785         for i in range(1, 93):
786             label = 'this is row #%d' % i
787             testobj = TestGtk.TestClass(self, i, label)
788             list_store.append((i,
789                                label,
790                                testobj,
791                                test_pyobj,
792                                test_pydict,
793                                test_pylist,
794                                i % 2,
795                                bool(i % 2)))
796
797         i = 93
798         label = _unicode('this is row #93')
799         treeiter = list_store.append()
800         list_store.set_value(treeiter, 0, i)
801         list_store.set_value(treeiter, 1, label)
802         list_store.set_value(treeiter, 2, TestGtk.TestClass(self, i, label))
803         list_store.set_value(treeiter, 3, test_pyobj)
804         list_store.set_value(treeiter, 4, test_pydict)
805         list_store.set_value(treeiter, 5, test_pylist)
806         list_store.set_value(treeiter, 6, 1)
807         list_store.set_value(treeiter, 7, True)
808
809         # test prepend
810         label = 'this is row #0'
811         list_store.prepend((0,
812                             label,
813                             TestGtk.TestClass(self, 0, label),
814                             test_pyobj,
815                             test_pydict,
816                             test_pylist,
817                             0,
818                             False))
819
820         # test automatic unicode->str conversion
821         i = 94
822         label = _unicode('this is row #94')
823         treeiter = list_store.append((i,
824                                       label,
825                                       TestGtk.TestClass(self, i, label),
826                                       test_pyobj,
827                                       test_pydict,
828                                       test_pylist,
829                                       0,
830                                       False))
831
832         # add sorted items out of order to test insert* apis
833         # also test sending in None to not set a column
834         i = 97
835         label = 'this is row #97'
836         treeiter = list_store.append((None,
837                                       None,
838                                       None,
839                                       test_pyobj,
840                                       None,
841                                       test_pylist,
842                                       1,
843                                       None))
844
845         list_store.set_value(treeiter, 0, i)
846         list_store.set_value(treeiter, 1, label)
847         list_store.set_value(treeiter, 2, TestGtk.TestClass(self, i, label))
848         list_store.set_value(treeiter, 4, test_pydict)
849         list_store.set_value(treeiter, 7, True)
850
851         # this should append
852         i = 99
853         label = 'this is row #99'
854         list_store.insert(9999, (i,
855                                  label,
856                                  TestGtk.TestClass(self, i, label),
857                                  test_pyobj,
858                                  test_pydict,
859                                  test_pylist,
860                                  1,
861                                  True))
862
863         i = 96
864         label = 'this is row #96'
865         list_store.insert_before(treeiter, (i,
866                                             label,
867                                             TestGtk.TestClass(self, i, label),
868                                             test_pyobj,
869                                             test_pydict,
870                                             test_pylist,
871                                             0,
872                                             False))
873
874         i = 98
875         label = 'this is row #98'
876         list_store.insert_after(treeiter, (i,
877                                            label,
878                                            TestGtk.TestClass(self, i, label),
879                                            test_pyobj,
880                                            test_pydict,
881                                            test_pylist,
882                                            0,
883                                            False))
884
885         i = 95
886         label = 'this is row #95'
887         list_store.insert(95, (i,
888                                label,
889                                TestGtk.TestClass(self, i, label),
890                                test_pyobj,
891                                test_pydict,
892                                test_pylist,
893                                1,
894                                True))
895
896         i = 100
897         label = 'this is row #100'
898         treeiter = list_store.append()
899         list_store.set(treeiter,
900                        1, label,
901                        0, i,
902                        2, TestGtk.TestClass(self, i, label),
903                        3, test_pyobj,
904                        4, test_pydict,
905                        5, test_pylist,
906                        6, 0,
907                        7, False)
908         i = 101
909         label = 'this is row #101'
910         treeiter = list_store.append()
911         list_store.set(treeiter, {1: label,
912                                   0: i,
913                                   2: TestGtk.TestClass(self, i, label),
914                                   3: test_pyobj,
915                                   4: test_pydict,
916                                   5: test_pylist,
917                                   6: 1,
918                                   7: True})
919         i = 102
920         label = 'this is row #102'
921         treeiter = list_store.append()
922         list_store.set(treeiter, (1, 0, 2, 3, 4, 5, 6, 7),
923                                  (label,
924                                   i,
925                                   TestGtk.TestClass(self, i, label),
926                                   test_pyobj,
927                                   test_pydict,
928                                   test_pylist,
929                                   0,
930                                   False))
931
932         self.assertEqual(len(list_store), 103)
933
934         # walk the list to see if the values were stored correctly
935         i = 0
936         treeiter = list_store.get_iter_first()
937
938         counter = 0
939         while treeiter:
940             i = list_store.get_value(treeiter, 0)
941             self.assertEqual(i, counter)
942             s = list_store.get_value(treeiter, 1)
943             obj = list_store.get_value(treeiter, 2)
944             obj.check(i, s)
945
946             pyobj = list_store.get_value(treeiter, 3)
947             self.assertEqual(pyobj, test_pyobj)
948             pydict = list_store.get_value(treeiter, 4)
949             self.assertEqual(pydict, test_pydict)
950             pylist = list_store.get_value(treeiter, 5)
951             self.assertEqual(pylist, test_pylist)
952
953             bool_1 = list_store.get_value(treeiter, 6)
954             bool_2 = list_store.get_value(treeiter, 7)
955             self.assertEqual(bool_1, bool_2)
956             self.assertTrue(isinstance(bool_1, bool))
957             self.assertTrue(isinstance(bool_2, bool))
958
959             treeiter = list_store.iter_next(treeiter)
960
961             counter += 1
962
963         self.assertEqual(i, 102)
964
965     def test_list_store_sort(self):
966         def comp1(model, row1, row2, user_data):
967             v1 = model[row1][1]
968             v2 = model[row2][1]
969
970             # make "m" smaller than anything else
971             if v1.startswith('m') and not v2.startswith('m'):
972                 return -1
973             if v2.startswith('m') and not v1.startswith('m'):
974                 return 1
975             return (v1 > v2) - (v1 < v2)
976
977         list_store = Gtk.ListStore(int, str)
978         list_store.set_sort_func(2, comp1, None)
979         list_store.append((1, 'apples'))
980         list_store.append((3, 'oranges'))
981         list_store.append((2, 'mango'))
982
983         # not sorted yet, should be original order
984         self.assertEqual([list(i) for i in list_store],
985                          [[1, 'apples'], [3, 'oranges'], [2, 'mango']])
986
987         # sort with our custom function
988         list_store.set_sort_column_id(2, Gtk.SortType.ASCENDING)
989         self.assertEqual([list(i) for i in list_store],
990                          [[2, 'mango'], [1, 'apples'], [3, 'oranges']])
991
992         list_store.set_sort_column_id(2, Gtk.SortType.DESCENDING)
993         self.assertEqual([list(i) for i in list_store],
994                          [[3, 'oranges'], [1, 'apples'], [2, 'mango']])
995
996     def test_list_store_signals(self):
997         list_store = Gtk.ListStore(int, bool)
998
999         def on_row_inserted(list_store, tree_path, tree_iter, signal_list):
1000             signal_list.append('row-inserted')
1001
1002         def on_row_changed(list_store, tree_path, tree_iter, signal_list):
1003             signal_list.append('row-changed')
1004
1005         signals = []
1006         list_store.connect('row-inserted', on_row_inserted, signals)
1007         list_store.connect('row-changed', on_row_changed, signals)
1008
1009         # adding rows with and without data should only call one signal
1010         list_store.append((0, False))
1011         self.assertEqual(signals, ['row-inserted'])
1012
1013         signals.pop()
1014         list_store.append()
1015         self.assertEqual(signals, ['row-inserted'])
1016
1017         signals.pop()
1018         list_store.prepend((0, False))
1019         self.assertEqual(signals, ['row-inserted'])
1020
1021         signals.pop()
1022         list_store.prepend()
1023         self.assertEqual(signals, ['row-inserted'])
1024
1025         signals.pop()
1026         list_store.insert(1, (0, False))
1027         self.assertEqual(signals, ['row-inserted'])
1028
1029         signals.pop()
1030         list_store.insert(1)
1031         self.assertEqual(signals, ['row-inserted'])
1032
1033     def test_tree_path(self):
1034         p1 = Gtk.TreePath()
1035         p2 = Gtk.TreePath.new_first()
1036         self.assertEqual(p1, p2)
1037         self.assertEqual(str(p1), '0')
1038         self.assertEqual(len(p1), 1)
1039         p1 = Gtk.TreePath(2)
1040         p2 = Gtk.TreePath.new_from_string('2')
1041         self.assertEqual(p1, p2)
1042         self.assertEqual(str(p1), '2')
1043         self.assertEqual(len(p1), 1)
1044         p1 = Gtk.TreePath('1:2:3')
1045         p2 = Gtk.TreePath.new_from_string('1:2:3')
1046         self.assertEqual(p1, p2)
1047         self.assertEqual(str(p1), '1:2:3')
1048         self.assertEqual(len(p1), 3)
1049         p1 = Gtk.TreePath((1, 2, 3))
1050         p2 = Gtk.TreePath.new_from_string('1:2:3')
1051         self.assertEqual(p1, p2)
1052         self.assertEqual(str(p1), '1:2:3')
1053         self.assertEqual(len(p1), 3)
1054         self.assertNotEqual(p1, None)
1055         self.assertTrue(p1 > None)
1056         self.assertTrue(p1 >= None)
1057         self.assertFalse(p1 < None)
1058         self.assertFalse(p1 <= None)
1059
1060         self.assertEqual(tuple(p1), (1, 2, 3))
1061         self.assertEqual(p1[0], 1)
1062         self.assertEqual(p1[1], 2)
1063         self.assertEqual(p1[2], 3)
1064         self.assertRaises(IndexError, p1.__getitem__, 3)
1065
1066     def test_tree_model(self):
1067         tree_store = Gtk.TreeStore(int, str)
1068
1069         self.assertTrue(tree_store)
1070         self.assertEqual(len(tree_store), 0)
1071         self.assertEqual(tree_store.get_iter_first(), None)
1072
1073         def get_by_index(row, col=None):
1074             if col:
1075                 return tree_store[row][col]
1076             else:
1077                 return tree_store[row]
1078
1079         self.assertRaises(TypeError, get_by_index, None)
1080         self.assertRaises(TypeError, get_by_index, "")
1081         self.assertRaises(TypeError, get_by_index, ())
1082
1083         self.assertRaises(IndexError, get_by_index, "0")
1084         self.assertRaises(IndexError, get_by_index, 0)
1085         self.assertRaises(IndexError, get_by_index, (0,))
1086
1087         self.assertRaises(ValueError, tree_store.get_iter, "0")
1088         self.assertRaises(ValueError, tree_store.get_iter, 0)
1089         self.assertRaises(ValueError, tree_store.get_iter, (0,))
1090
1091         self.assertRaises(ValueError, tree_store.get_iter_from_string, "0")
1092
1093         for row in tree_store:
1094             self.fail("Should not be reached")
1095
1096         class DerivedIntType(int):
1097             pass
1098
1099         class DerivedStrType(str):
1100             pass
1101
1102         for i in range(100):
1103             label = 'this is row #%d' % i
1104             parent = tree_store.append(None, (DerivedIntType(i), DerivedStrType(label),))
1105             self.assertNotEqual(parent, None)
1106             for j in range(20):
1107                 label = 'this is child #%d of node #%d' % (j, i)
1108                 child = tree_store.append(parent, (j, label,))
1109                 self.assertNotEqual(child, None)
1110
1111         self.assertTrue(tree_store)
1112         self.assertEqual(len(tree_store), 100)
1113
1114         self.assertEqual(tree_store.iter_previous(tree_store.get_iter(0)), None)
1115
1116         for i, row in enumerate(tree_store):
1117             self.assertEqual(row.model, tree_store)
1118             self.assertEqual(row.parent, None)
1119
1120             self.assertEqual(tree_store[i].path, row.path)
1121             self.assertEqual(tree_store[str(i)].path, row.path)
1122             self.assertEqual(tree_store[(i,)].path, row.path)
1123
1124             self.assertEqual(tree_store[i][0], i)
1125             self.assertEqual(tree_store[i][1], "this is row #%d" % i)
1126
1127             aiter = tree_store.get_iter(i)
1128             self.assertEqual(tree_store.get_path(aiter), row.path)
1129
1130             aiter = tree_store.get_iter(str(i))
1131             self.assertEqual(tree_store.get_path(aiter), row.path)
1132
1133             aiter = tree_store.get_iter((i,))
1134             self.assertEqual(tree_store.get_path(aiter), row.path)
1135
1136             self.assertEqual(tree_store.iter_parent(aiter), row.parent)
1137
1138             next = tree_store.iter_next(aiter)
1139             if i < len(tree_store) - 1:
1140                 self.assertEqual(tree_store.get_path(next), row.next.path)
1141                 self.assertEqual(tree_store.get_path(tree_store.iter_previous(next)),
1142                                  tree_store.get_path(aiter))
1143             else:
1144                 self.assertEqual(next, None)
1145
1146             self.assertEqual(tree_store.iter_n_children(row.iter), 20)
1147
1148             child = tree_store.iter_children(row.iter)
1149             for j, childrow in enumerate(row.iterchildren()):
1150                 child_path = tree_store.get_path(child)
1151                 self.assertEqual(childrow.path, child_path)
1152                 self.assertEqual(childrow.parent.path, row.path)
1153                 self.assertEqual(childrow.path, tree_store[child].path)
1154                 self.assertEqual(childrow.path, tree_store[child_path].path)
1155
1156                 self.assertEqual(childrow[0], tree_store[child][0])
1157                 self.assertEqual(childrow[0], j)
1158                 self.assertEqual(childrow[1], tree_store[child][1])
1159                 self.assertEqual(childrow[1], 'this is child #%d of node #%d' % (j, i))
1160
1161                 self.assertRaises(IndexError, get_by_index, child, 2)
1162
1163                 tree_store[child][1] = 'this was child #%d of node #%d' % (j, i)
1164                 self.assertEqual(childrow[1], 'this was child #%d of node #%d' % (j, i))
1165
1166                 nth_child = tree_store.iter_nth_child(row.iter, j)
1167                 self.assertEqual(childrow.path, tree_store.get_path(nth_child))
1168
1169                 childrow2 = tree_store["%d:%d" % (i, j)]
1170                 self.assertEqual(childrow.path, childrow2.path)
1171
1172                 childrow2 = tree_store[(i, j,)]
1173                 self.assertEqual(childrow.path, childrow2.path)
1174
1175                 child = tree_store.iter_next(child)
1176                 if j < 19:
1177                     self.assertEqual(childrow.next.path, tree_store.get_path(child))
1178                 else:
1179                     self.assertEqual(child, childrow.next)
1180                     self.assertEqual(child, None)
1181
1182             self.assertEqual(j, 19)
1183
1184         self.assertEqual(i, 99)
1185
1186         # negative indices
1187         for i in range(-1, -100, -1):
1188             i_real = i + 100
1189             self.assertEqual(tree_store[i][0], i_real)
1190
1191             row = tree_store[i]
1192             for j in range(-1, -20, -1):
1193                 j_real = j + 20
1194                 path = (i_real, j_real,)
1195
1196                 self.assertEqual(tree_store[path][-2], j_real)
1197
1198                 label = 'this was child #%d of node #%d' % (j_real, i_real)
1199                 self.assertEqual(tree_store[path][-1], label)
1200
1201                 new_label = 'this still is child #%d of node #%d' % (j_real, i_real)
1202                 tree_store[path][-1] = new_label
1203                 self.assertEqual(tree_store[path][-1], new_label)
1204
1205                 self.assertRaises(IndexError, get_by_index, path, -3)
1206
1207         self.assertRaises(IndexError, get_by_index, -101)
1208
1209         last_row = tree_store[99]
1210         self.assertNotEqual(last_row, None)
1211
1212         for i, childrow in enumerate(last_row.iterchildren()):
1213             if i < 19:
1214                 self.assertTrue(tree_store.remove(childrow.iter))
1215             else:
1216                 self.assertFalse(tree_store.remove(childrow.iter))
1217
1218         self.assertEqual(i, 19)
1219
1220         self.assertEqual(tree_store.iter_n_children(last_row.iter), 0)
1221         for childrow in last_row.iterchildren():
1222             self.fail("Should not be reached")
1223
1224         aiter = tree_store.get_iter(10)
1225         self.assertRaises(TypeError, tree_store.get, aiter, 1, 'a')
1226         self.assertRaises(ValueError, tree_store.get, aiter, 1, -1)
1227         self.assertRaises(ValueError, tree_store.get, aiter, 1, 100)
1228         self.assertEqual(tree_store.get(aiter, 0, 1), (10, 'this is row #10'))
1229
1230         # check __delitem__
1231         self.assertEqual(len(tree_store), 100)
1232         aiter = tree_store.get_iter(10)
1233         del tree_store[aiter]
1234         self.assertEqual(len(tree_store), 99)
1235         self.assertRaises(TypeError, tree_store.__delitem__, None)
1236         self.assertRaises(IndexError, tree_store.__delitem__, -101)
1237         self.assertRaises(IndexError, tree_store.__delitem__, 101)
1238
1239     def test_tree_model_get_iter_fail(self):
1240         # TreeModel class with a failing get_iter()
1241         class MyTreeModel(GObject.GObject, Gtk.TreeModel):
1242             def do_get_iter(self, iter):
1243                 return (False, None)
1244
1245         tm = MyTreeModel()
1246         self.assertEqual(tm.get_iter_first(), None)
1247
1248     def test_tree_model_edit(self):
1249         model = Gtk.ListStore(int, str, float)
1250         model.append([1, "one", -0.1])
1251         model.append([2, "two", -0.2])
1252
1253         def set_row(value):
1254             model[1] = value
1255
1256         self.assertRaises(TypeError, set_row, 3)
1257         self.assertRaises(TypeError, set_row, "three")
1258         self.assertRaises(ValueError, set_row, [])
1259         self.assertRaises(ValueError, set_row, [3, "three"])
1260
1261         model[0] = (3, "three", -0.3)
1262
1263     def test_tree_row_slice(self):
1264         model = Gtk.ListStore(int, str, float)
1265         model.append([1, "one", -0.1])
1266
1267         self.assertEqual([1, "one", -0.1], model[0][:])
1268         self.assertEqual([1, "one"], model[0][:2])
1269         self.assertEqual(["one", -0.1], model[0][1:])
1270         self.assertEqual(["one"], model[0][1:-1])
1271         self.assertEqual([1], model[0][:-2])
1272         self.assertEqual([], model[0][5:])
1273         self.assertEqual([1, -0.1], model[0][0:3:2])
1274
1275         model[0][:] = (2, "two", -0.2)
1276         self.assertEqual([2, "two", -0.2], model[0][:])
1277
1278         model[0][:2] = (3, "three")
1279         self.assertEqual([3, "three", -0.2], model[0][:])
1280
1281         model[0][1:] = ("four", -0.4)
1282         self.assertEqual([3, "four", -0.4], model[0][:])
1283
1284         model[0][1:-1] = ("five",)
1285         self.assertEqual([3, "five", -0.4], model[0][:])
1286
1287         model[0][0:3:2] = (6, -0.6)
1288         self.assertEqual([6, "five", -0.6], model[0][:])
1289
1290         def set_row1():
1291             model[0][5:] = ("doesn't", "matter",)
1292
1293         self.assertRaises(ValueError, set_row1)
1294
1295         def set_row2():
1296             model[0][:1] = (0, "zero", 0)
1297
1298         self.assertRaises(ValueError, set_row2)
1299
1300         def set_row3():
1301             model[0][:2] = ("0", 0)
1302
1303         self.assertRaises(ValueError, set_row3)
1304
1305
1306 @unittest.skipUnless(Gtk, 'Gtk not available')
1307 class TestTreeView(unittest.TestCase):
1308     def test_tree_view(self):
1309         store = Gtk.ListStore(int, str)
1310         store.append((0, "foo"))
1311         store.append((1, "bar"))
1312         view = Gtk.TreeView()
1313         # FIXME: We can't easily call get_cursor() to make sure this works as
1314         # expected as we need to realize and focus the column; the following
1315         # will raise a Gtk-CRITICAL which we ignore for now
1316         old_mask = GLib.log_set_always_fatal(
1317             GLib.LogLevelFlags.LEVEL_WARNING | GLib.LogLevelFlags.LEVEL_ERROR)
1318         try:
1319             view.set_cursor(store[1].path)
1320             view.set_cursor(str(store[1].path))
1321
1322             view.get_cell_area(store[1].path)
1323             view.get_cell_area(str(store[1].path))
1324         finally:
1325             GLib.log_set_always_fatal(old_mask)
1326
1327     def test_tree_view_column(self):
1328         cell = Gtk.CellRendererText()
1329         Gtk.TreeViewColumn(title='This is just a test',
1330                            cell_renderer=cell,
1331                            text=0,
1332                            style=2)
1333
1334     def test_tree_view_add_column_with_attributes(self):
1335         model = Gtk.ListStore(str, str, str)
1336         # deliberately use out-of-order sorting here; we assign column 0 to
1337         # model index 2, etc.
1338         model.append(['cell13', 'cell11', 'cell12'])
1339         model.append(['cell23', 'cell21', 'cell22'])
1340
1341         tree = Gtk.TreeView(model)
1342         cell1 = Gtk.CellRendererText()
1343         cell2 = Gtk.CellRendererText()
1344         cell3 = Gtk.CellRendererText()
1345         cell4 = Gtk.CellRendererText()
1346
1347         tree.insert_column_with_attributes(0, 'Head2', cell2, text=2)
1348         tree.insert_column_with_attributes(0, 'Head1', cell1, text=1)
1349         tree.insert_column_with_attributes(-1, 'Head3', cell3, text=0)
1350         # unconnected
1351         tree.insert_column_with_attributes(-1, 'Head4', cell4)
1352
1353         # might cause a Pango warning, do not break on this
1354         old_mask = GLib.log_set_always_fatal(
1355             GLib.LogLevelFlags.LEVEL_CRITICAL | GLib.LogLevelFlags.LEVEL_ERROR)
1356         try:
1357             # causes the widget to get realized and cellN.props.text receive a
1358             # value, otherwise it will be None.
1359             tree.get_preferred_size()
1360         finally:
1361             GLib.log_set_always_fatal(old_mask)
1362
1363         self.assertEqual(tree.get_column(0).get_title(), 'Head1')
1364         self.assertEqual(tree.get_column(1).get_title(), 'Head2')
1365         self.assertEqual(tree.get_column(2).get_title(), 'Head3')
1366         self.assertEqual(tree.get_column(3).get_title(), 'Head4')
1367
1368         # cursor should be at the first row
1369         self.assertEqual(cell1.props.text, 'cell11')
1370         self.assertEqual(cell2.props.text, 'cell12')
1371         self.assertEqual(cell3.props.text, 'cell13')
1372         self.assertEqual(cell4.props.text, None)
1373
1374     def test_tree_view_column_set_attributes(self):
1375         store = Gtk.ListStore(int, str)
1376         directors = ['Fellini', 'Tarantino', 'Tarkovskiy']
1377         for i, director in enumerate(directors):
1378             store.append([i, director])
1379
1380         treeview = Gtk.TreeView()
1381         treeview.set_model(store)
1382
1383         column = Gtk.TreeViewColumn()
1384         treeview.append_column(column)
1385
1386         cell = Gtk.CellRendererText()
1387         column.pack_start(cell, expand=True)
1388         column.set_attributes(cell, text=1)
1389
1390         # might cause a Pango warning, do not break on this
1391         old_mask = GLib.log_set_always_fatal(
1392             GLib.LogLevelFlags.LEVEL_CRITICAL | GLib.LogLevelFlags.LEVEL_ERROR)
1393         try:
1394             # This will make cell.props.text receive a value, otherwise it
1395             # will be None.
1396             treeview.get_preferred_size()
1397         finally:
1398             GLib.log_set_always_fatal(old_mask)
1399
1400         self.assertTrue(cell.props.text in directors)
1401
1402     def test_tree_selection(self):
1403         store = Gtk.ListStore(int, str)
1404         for i in range(10):
1405             store.append((i, "foo"))
1406         view = Gtk.TreeView()
1407         view.set_model(store)
1408         firstpath = store.get_path(store.get_iter_first())
1409         sel = view.get_selection()
1410
1411         sel.select_path(firstpath)
1412         (m, s) = sel.get_selected()
1413         self.assertEqual(m, store)
1414         self.assertEqual(store.get_path(s), firstpath)
1415
1416         sel.select_path(0)
1417         (m, s) = sel.get_selected()
1418         self.assertEqual(m, store)
1419         self.assertEqual(store.get_path(s), firstpath)
1420
1421         sel.select_path("0:0")
1422         (m, s) = sel.get_selected()
1423         self.assertEqual(m, store)
1424         self.assertEqual(store.get_path(s), firstpath)
1425
1426         sel.select_path((0, 0))
1427         (m, s) = sel.get_selected()
1428         self.assertEqual(m, store)
1429         self.assertEqual(store.get_path(s), firstpath)
1430
1431
1432 @unittest.skipUnless(Gtk, 'Gtk not available')
1433 class TestTextBuffer(unittest.TestCase):
1434     def test_text_buffer(self):
1435         self.assertEqual(Gtk.TextBuffer, gi.overrides.Gtk.TextBuffer)
1436         buffer = Gtk.TextBuffer()
1437         tag = buffer.create_tag('title', font='Sans 18')
1438
1439         self.assertEqual(tag.props.name, 'title')
1440         self.assertEqual(tag.props.font, 'Sans 18')
1441
1442         (start, end) = buffer.get_bounds()
1443
1444         mark = buffer.create_mark(None, start)
1445         self.assertFalse(mark.get_left_gravity())
1446
1447         buffer.set_text('Hello Jane Hello Bob')
1448         (start, end) = buffer.get_bounds()
1449         text = buffer.get_text(start, end, False)
1450         self.assertEqual(text, 'Hello Jane Hello Bob')
1451
1452         buffer.set_text('')
1453         (start, end) = buffer.get_bounds()
1454         text = buffer.get_text(start, end, False)
1455         self.assertEqual(text, '')
1456
1457         buffer.insert(end, 'HelloHello')
1458         buffer.insert(end, ' Bob')
1459
1460         cursor_iter = end.copy()
1461         cursor_iter.backward_chars(9)
1462         buffer.place_cursor(cursor_iter)
1463         buffer.insert_at_cursor(' Jane ')
1464
1465         (start, end) = buffer.get_bounds()
1466         text = buffer.get_text(start, end, False)
1467         self.assertEqual(text, 'Hello Jane Hello Bob')
1468
1469         sel = buffer.get_selection_bounds()
1470         self.assertEqual(sel, ())
1471         buffer.select_range(start, end)
1472         sel = buffer.get_selection_bounds()
1473         self.assertTrue(sel[0].equal(start))
1474         self.assertTrue(sel[1].equal(end))
1475
1476         buffer.set_text('')
1477         buffer.insert_with_tags(buffer.get_start_iter(), 'HelloHello', tag)
1478         (start, end) = buffer.get_bounds()
1479         self.assertTrue(start.begins_tag(tag))
1480         self.assertTrue(start.has_tag(tag))
1481
1482         buffer.set_text('')
1483         buffer.insert_with_tags_by_name(buffer.get_start_iter(), 'HelloHello', 'title')
1484         (start, end) = buffer.get_bounds()
1485         self.assertTrue(start.begins_tag(tag))
1486         self.assertTrue(start.has_tag(tag))
1487
1488         self.assertRaises(ValueError, buffer.insert_with_tags_by_name,
1489                           buffer.get_start_iter(), 'HelloHello', 'unknowntag')
1490
1491     def test_text_iter(self):
1492         self.assertEqual(Gtk.TextIter, gi.overrides.Gtk.TextIter)
1493         buffer = Gtk.TextBuffer()
1494         buffer.set_text('Hello Jane Hello Bob')
1495         tag = buffer.create_tag('title', font='Sans 18')
1496         (start, end) = buffer.get_bounds()
1497         start.forward_chars(10)
1498         buffer.apply_tag(tag, start, end)
1499         self.assertTrue(start.begins_tag())
1500         self.assertTrue(end.ends_tag())
1501         self.assertTrue(start.toggles_tag())
1502         self.assertTrue(end.toggles_tag())
1503         start.backward_chars(1)
1504         self.assertFalse(start.begins_tag())
1505         self.assertFalse(start.ends_tag())
1506         self.assertFalse(start.toggles_tag())
1507
1508     def test_text_buffer_search(self):
1509         buffer = Gtk.TextBuffer()
1510         buffer.set_text('Hello World Hello GNOME')
1511
1512         i = buffer.get_iter_at_offset(0)
1513         self.assertTrue(isinstance(i, Gtk.TextIter))
1514
1515         self.assertEqual(i.forward_search('world', 0, None), None)
1516
1517         (start, end) = i.forward_search('World', 0, None)
1518         self.assertEqual(start.get_offset(), 6)
1519         self.assertEqual(end.get_offset(), 11)
1520
1521         (start, end) = i.forward_search('world',
1522                                         Gtk.TextSearchFlags.CASE_INSENSITIVE,
1523                                         None)
1524         self.assertEqual(start.get_offset(), 6)
1525         self.assertEqual(end.get_offset(), 11)