d339adf0a849ebbc6fe92e2620272761fe3eaec0
[platform/upstream/pygobject2.git] / tests / test_overrides_gtk.py
1 # -*- Mode: Python; py-indent-offset: 4 -*-
2 # coding: UTF-8
3 # vim: tabstop=4 shiftwidth=4 expandtab
4
5 import contextlib
6 import unittest
7 import time
8 import sys
9 import warnings
10
11 from compathelper import _unicode, _bytes
12
13 import gi.overrides
14 import gi.types
15 from gi.repository import GLib, GObject
16
17 try:
18     from gi.repository import GdkPixbuf, Gdk, Gtk
19     Gtk  # pyflakes
20     PyGTKDeprecationWarning = Gtk.PyGTKDeprecationWarning
21 except ImportError:
22     Gtk = None
23     PyGTKDeprecationWarning = None
24
25
26 @contextlib.contextmanager
27 def realized(widget):
28     """Makes sure the widget is realized.
29
30     view = Gtk.TreeView()
31     with realized(view):
32         do_something(view)
33     """
34
35     if isinstance(widget, Gtk.Window):
36         toplevel = widget
37     else:
38         toplevel = widget.get_parent_window()
39
40     if toplevel is None:
41         window = Gtk.Window()
42         window.add(widget)
43
44     widget.realize()
45     while Gtk.events_pending():
46         Gtk.main_iteration()
47     assert widget.get_realized()
48     yield widget
49
50     if toplevel is None:
51         window.remove(widget)
52         window.destroy()
53
54     while Gtk.events_pending():
55         Gtk.main_iteration()
56
57
58 @unittest.skipUnless(Gtk, 'Gtk not available')
59 class TestGtk(unittest.TestCase):
60     def test_container(self):
61         box = Gtk.Box()
62         self.assertTrue(isinstance(box, Gtk.Box))
63         self.assertTrue(isinstance(box, Gtk.Container))
64         self.assertTrue(isinstance(box, Gtk.Widget))
65         self.assertTrue(box)
66         label = Gtk.Label()
67         label2 = Gtk.Label()
68         box.add(label)
69         box.add(label2)
70         self.assertTrue(label in box)
71         self.assertTrue(label2 in box)
72         self.assertEqual(len(box), 2)
73         self.assertTrue(box)
74         l = [x for x in box]
75         self.assertEqual(l, [label, label2])
76
77     def test_actions(self):
78         self.assertEqual(Gtk.Action, gi.overrides.Gtk.Action)
79         action = Gtk.Action(name="test", label="Test", tooltip="Test Action", stock_id=Gtk.STOCK_COPY)
80         self.assertEqual(action.get_name(), "test")
81         self.assertEqual(action.get_label(), "Test")
82         self.assertEqual(action.get_tooltip(), "Test Action")
83         self.assertEqual(action.get_stock_id(), Gtk.STOCK_COPY)
84
85         self.assertEqual(Gtk.RadioAction, gi.overrides.Gtk.RadioAction)
86         action = Gtk.RadioAction(name="test", label="Test", tooltip="Test Action", stock_id=Gtk.STOCK_COPY, value=1)
87         self.assertEqual(action.get_name(), "test")
88         self.assertEqual(action.get_label(), "Test")
89         self.assertEqual(action.get_tooltip(), "Test Action")
90         self.assertEqual(action.get_stock_id(), Gtk.STOCK_COPY)
91         self.assertEqual(action.get_current_value(), 1)
92
93     def test_actiongroup(self):
94         self.assertEqual(Gtk.ActionGroup, gi.overrides.Gtk.ActionGroup)
95
96         action_group = Gtk.ActionGroup(name='TestActionGroup')
97         callback_data = "callback data"
98
99         def test_action_callback_data(action, user_data):
100             self.assertEqual(user_data, callback_data)
101
102         def test_radio_action_callback_data(action, current, user_data):
103             self.assertEqual(user_data, callback_data)
104
105         action_group.add_actions([
106             ('test-action1', None, 'Test Action 1',
107              None, None, test_action_callback_data),
108             ('test-action2', Gtk.STOCK_COPY, 'Test Action 2',
109              None, None, test_action_callback_data)], callback_data)
110         action_group.add_toggle_actions([
111             ('test-toggle-action1', None, 'Test Toggle Action 1',
112              None, None, test_action_callback_data, False),
113             ('test-toggle-action2', Gtk.STOCK_COPY, 'Test Toggle Action 2',
114              None, None, test_action_callback_data, True)], callback_data)
115         action_group.add_radio_actions([
116             ('test-radio-action1', None, 'Test Radio Action 1'),
117             ('test-radio-action2', Gtk.STOCK_COPY, 'Test Radio Action 2')], 1,
118             test_radio_action_callback_data,
119             callback_data)
120
121         expected_results = [('test-action1', Gtk.Action),
122                             ('test-action2', Gtk.Action),
123                             ('test-toggle-action1', Gtk.ToggleAction),
124                             ('test-toggle-action2', Gtk.ToggleAction),
125                             ('test-radio-action1', Gtk.RadioAction),
126                             ('test-radio-action2', Gtk.RadioAction)]
127
128         for action in action_group.list_actions():
129             a = (action.get_name(), type(action))
130             self.assertTrue(a in expected_results)
131             expected_results.remove(a)
132             action.activate()
133
134     def test_uimanager(self):
135         self.assertEqual(Gtk.UIManager, gi.overrides.Gtk.UIManager)
136         ui = Gtk.UIManager()
137         ui.add_ui_from_string("""<ui>
138     <menubar name="menubar1"></menubar>
139 </ui>
140 """
141 )
142         menubar = ui.get_widget("/menubar1")
143         self.assertEqual(type(menubar), Gtk.MenuBar)
144
145         ag = Gtk.ActionGroup(name="ag1")
146         ui.insert_action_group(ag)
147         ag2 = Gtk.ActionGroup(name="ag2")
148         ui.insert_action_group(ag2)
149         groups = ui.get_action_groups()
150         self.assertEqual(ag, groups[-2])
151         self.assertEqual(ag2, groups[-1])
152
153     def test_uimanager_nonascii(self):
154         ui = Gtk.UIManager()
155         ui.add_ui_from_string(b'<ui><menubar name="menub\xc3\xa6r1" /></ui>'.decode('UTF-8'))
156         mi = ui.get_widget("/menubær1")
157         self.assertEqual(type(mi), Gtk.MenuBar)
158
159     def test_window(self):
160         # standard Window
161         w = Gtk.Window()
162         self.assertEqual(w.get_property('type'), Gtk.WindowType.TOPLEVEL)
163
164         # type works as keyword argument
165         w = Gtk.Window(type=Gtk.WindowType.POPUP)
166         self.assertEqual(w.get_property('type'), Gtk.WindowType.POPUP)
167
168         class TestWindow(Gtk.Window):
169             __gtype_name__ = "TestWindow"
170
171         # works from builder
172         builder = Gtk.Builder()
173         builder.add_from_string('''
174 <interface>
175   <object class="GtkWindow" id="win">
176     <property name="type">popup</property>
177   </object>
178   <object class="TestWindow" id="testwin">
179   </object>
180   <object class="TestWindow" id="testpop">
181     <property name="type">popup</property>
182   </object>
183 </interface>''')
184         self.assertEqual(builder.get_object('win').get_property('type'),
185                          Gtk.WindowType.POPUP)
186         self.assertEqual(builder.get_object('testwin').get_property('type'),
187                          Gtk.WindowType.TOPLEVEL)
188         self.assertEqual(builder.get_object('testpop').get_property('type'),
189                          Gtk.WindowType.POPUP)
190
191     def test_dialog_classes(self):
192         self.assertEqual(Gtk.Dialog, gi.overrides.Gtk.Dialog)
193         self.assertEqual(Gtk.ColorSelectionDialog, gi.overrides.Gtk.ColorSelectionDialog)
194         self.assertEqual(Gtk.FileChooserDialog, gi.overrides.Gtk.FileChooserDialog)
195         self.assertEqual(Gtk.FontSelectionDialog, gi.overrides.Gtk.FontSelectionDialog)
196         self.assertEqual(Gtk.RecentChooserDialog, gi.overrides.Gtk.RecentChooserDialog)
197
198     def test_dialog_base(self):
199         dialog = Gtk.Dialog(title='Foo', modal=True)
200         self.assertTrue(isinstance(dialog, Gtk.Dialog))
201         self.assertTrue(isinstance(dialog, Gtk.Window))
202         self.assertEqual('Foo', dialog.get_title())
203         self.assertTrue(dialog.get_modal())
204
205     def test_dialog_deprecations(self):
206         with warnings.catch_warnings(record=True) as warn:
207             warnings.simplefilter('always')
208             dialog = Gtk.Dialog(title='Foo', flags=Gtk.DialogFlags.MODAL)
209             self.assertTrue(dialog.get_modal())
210             self.assertEqual(len(warn), 1)
211             self.assertTrue(issubclass(warn[0].category, PyGTKDeprecationWarning))
212             self.assertRegexpMatches(str(warn[0].message),
213                                      '.*flags.*modal.*')
214
215         with warnings.catch_warnings(record=True) as warn:
216             warnings.simplefilter('always')
217             dialog = Gtk.Dialog(title='Foo', flags=Gtk.DialogFlags.DESTROY_WITH_PARENT)
218             self.assertTrue(dialog.get_destroy_with_parent())
219             self.assertEqual(len(warn), 1)
220             self.assertTrue(issubclass(warn[0].category, PyGTKDeprecationWarning))
221             self.assertRegexpMatches(str(warn[0].message),
222                                      '.*flags.*destroy_with_parent.*')
223
224     def test_dialog_deprecation_stacklevels(self):
225         # Test warning levels are setup to give the correct filename for
226         # deprecations in different classes in the inheritance hierarchy.
227
228         # Base class
229         self.assertEqual(Gtk.Dialog, gi.overrides.Gtk.Dialog)
230         with warnings.catch_warnings(record=True) as warn:
231             warnings.simplefilter('always')
232             Gtk.Dialog(flags=Gtk.DialogFlags.MODAL)
233             self.assertEqual(len(warn), 1)
234             self.assertRegexpMatches(warn[0].filename, '.*test_overrides_gtk.*')
235
236         # Validate overridden base with overridden sub-class.
237         self.assertEqual(Gtk.MessageDialog, gi.overrides.Gtk.MessageDialog)
238         with warnings.catch_warnings(record=True) as warn:
239             warnings.simplefilter('always')
240             Gtk.MessageDialog(flags=Gtk.DialogFlags.MODAL)
241             self.assertEqual(len(warn), 1)
242             self.assertRegexpMatches(warn[0].filename, '.*test_overrides_gtk.*')
243
244         # Validate overridden base with non-overridden sub-class.
245         self.assertEqual(Gtk.AboutDialog, gi.repository.Gtk.AboutDialog)
246         with warnings.catch_warnings(record=True) as warn:
247             warnings.simplefilter('always')
248             Gtk.AboutDialog(flags=Gtk.DialogFlags.MODAL)
249             self.assertEqual(len(warn), 1)
250             self.assertRegexpMatches(warn[0].filename, '.*test_overrides_gtk.*')
251
252     def test_dialog_add_buttons(self):
253         # The overloaded "buttons" keyword gives a warning when attempting
254         # to use it for adding buttons as was available in PyGTK.
255         with warnings.catch_warnings(record=True) as warn:
256             warnings.simplefilter('always')
257             dialog = Gtk.Dialog(title='Foo', modal=True,
258                                 buttons=('test-button1', 1))
259             self.assertEqual(len(warn), 1)
260             self.assertTrue(issubclass(warn[0].category, PyGTKDeprecationWarning))
261             self.assertRegexpMatches(str(warn[0].message),
262                                      '.*ButtonsType.*add_buttons.*')
263
264         dialog.add_buttons('test-button2', 2, Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE)
265         button = dialog.get_widget_for_response(1)
266         self.assertEqual('test-button1', button.get_label())
267         button = dialog.get_widget_for_response(2)
268         self.assertEqual('test-button2', button.get_label())
269         button = dialog.get_widget_for_response(Gtk.ResponseType.CLOSE)
270         self.assertEqual(Gtk.STOCK_CLOSE, button.get_label())
271
272     def test_about_dialog(self):
273         dialog = Gtk.AboutDialog()
274         self.assertTrue(isinstance(dialog, Gtk.Dialog))
275         self.assertTrue(isinstance(dialog, Gtk.Window))
276
277         # AboutDialog is not sub-classed in overrides, make sure
278         # the mro still injects the base class "add_buttons" override.
279         self.assertTrue(hasattr(dialog, 'add_buttons'))
280
281     def test_message_dialog(self):
282         dialog = Gtk.MessageDialog(title='message dialog test',
283                                    modal=True,
284                                    buttons=Gtk.ButtonsType.OK,
285                                    text='dude!')
286         self.assertTrue(isinstance(dialog, Gtk.Dialog))
287         self.assertTrue(isinstance(dialog, Gtk.Window))
288
289         self.assertEqual('message dialog test', dialog.get_title())
290         self.assertTrue(dialog.get_modal())
291         text = dialog.get_property('text')
292         self.assertEqual('dude!', text)
293
294         dialog.format_secondary_text('2nd text')
295         self.assertEqual(dialog.get_property('secondary-text'), '2nd text')
296         self.assertFalse(dialog.get_property('secondary-use-markup'))
297
298         dialog.format_secondary_markup('2nd markup')
299         self.assertEqual(dialog.get_property('secondary-text'), '2nd markup')
300         self.assertTrue(dialog.get_property('secondary-use-markup'))
301
302     def test_color_selection_dialog(self):
303         dialog = Gtk.ColorSelectionDialog(title="color selection dialog test")
304         self.assertTrue(isinstance(dialog, Gtk.Dialog))
305         self.assertTrue(isinstance(dialog, Gtk.Window))
306         self.assertEqual('color selection dialog test', dialog.get_title())
307
308     def test_file_chooser_dialog(self):
309         # might cause a GVFS warning, do not break on this
310         old_mask = GLib.log_set_always_fatal(
311             GLib.LogLevelFlags.LEVEL_CRITICAL | GLib.LogLevelFlags.LEVEL_ERROR)
312         try:
313             dialog = Gtk.FileChooserDialog(title='file chooser dialog test',
314                                            action=Gtk.FileChooserAction.SAVE)
315         finally:
316             GLib.log_set_always_fatal(old_mask)
317         self.assertTrue(isinstance(dialog, Gtk.Dialog))
318         self.assertTrue(isinstance(dialog, Gtk.Window))
319         self.assertEqual('file chooser dialog test', dialog.get_title())
320
321         action = dialog.get_property('action')
322         self.assertEqual(Gtk.FileChooserAction.SAVE, action)
323
324     def test_file_chooser_dialog_default_action(self):
325         # might cause a GVFS warning, do not break on this
326         old_mask = GLib.log_set_always_fatal(
327             GLib.LogLevelFlags.LEVEL_CRITICAL | GLib.LogLevelFlags.LEVEL_ERROR)
328         try:
329             dialog = Gtk.FileChooserDialog(title='file chooser dialog test')
330         finally:
331             GLib.log_set_always_fatal(old_mask)
332
333         action = dialog.get_property('action')
334         self.assertEqual(Gtk.FileChooserAction.OPEN, action)
335
336     def test_font_selection_dialog(self):
337         dialog = Gtk.FontSelectionDialog(title="font selection dialog test")
338         self.assertTrue(isinstance(dialog, Gtk.Dialog))
339         self.assertTrue(isinstance(dialog, Gtk.Window))
340         self.assertEqual('font selection dialog test', dialog.get_title())
341
342     def test_recent_chooser_dialog(self):
343         test_manager = Gtk.RecentManager()
344         dialog = Gtk.RecentChooserDialog(title='recent chooser dialog test',
345                                          recent_manager=test_manager)
346         self.assertTrue(isinstance(dialog, Gtk.Dialog))
347         self.assertTrue(isinstance(dialog, Gtk.Window))
348         self.assertEqual('recent chooser dialog test', dialog.get_title())
349
350     class TestClass(GObject.GObject):
351         __gtype_name__ = "GIOverrideTreeAPITest"
352
353         def __init__(self, tester, int_value, string_value):
354             super(TestGtk.TestClass, self).__init__()
355             self.tester = tester
356             self.int_value = int_value
357             self.string_value = string_value
358
359         def check(self, int_value, string_value):
360             self.tester.assertEqual(int_value, self.int_value)
361             self.tester.assertEqual(string_value, self.string_value)
362
363     def test_buttons(self):
364         self.assertEqual(Gtk.Button, gi.overrides.Gtk.Button)
365
366         # test Gtk.Button
367         button = Gtk.Button()
368         self.assertTrue(isinstance(button, Gtk.Button))
369         self.assertTrue(isinstance(button, Gtk.Container))
370         self.assertTrue(isinstance(button, Gtk.Widget))
371         button = Gtk.Button.new_from_stock(Gtk.STOCK_CLOSE)
372         self.assertEqual(Gtk.STOCK_CLOSE, button.get_label())
373         self.assertTrue(button.get_use_stock())
374         self.assertTrue(button.get_use_underline())
375
376         # test Gtk.Button use_stock
377         button = Gtk.Button(label=Gtk.STOCK_CLOSE, use_stock=True, use_underline=True)
378         self.assertEqual(Gtk.STOCK_CLOSE, button.get_label())
379         self.assertTrue(button.get_use_stock())
380         self.assertTrue(button.get_use_underline())
381
382         # test Gtk.LinkButton
383         button = Gtk.LinkButton(uri='http://www.Gtk.org', label='Gtk')
384         self.assertTrue(isinstance(button, Gtk.Button))
385         self.assertTrue(isinstance(button, Gtk.Container))
386         self.assertTrue(isinstance(button, Gtk.Widget))
387         self.assertEqual('http://www.Gtk.org', button.get_uri())
388         self.assertEqual('Gtk', button.get_label())
389
390     def test_inheritance(self):
391         for name in gi.overrides.Gtk.__all__:
392             over = getattr(gi.overrides.Gtk, name)
393             for element in dir(Gtk):
394                 try:
395                     klass = getattr(Gtk, element)
396                     info = klass.__info__
397                 except (NotImplementedError, AttributeError):
398                     continue
399
400                 # Get all parent classes and interfaces klass inherits from
401                 if isinstance(info, gi.types.ObjectInfo):
402                     classes = list(info.get_interfaces())
403                     parent = info.get_parent()
404                     while parent.get_name() != "Object":
405                         classes.append(parent)
406                         parent = parent.get_parent()
407                     classes = [kl for kl in classes if kl.get_namespace() == "Gtk"]
408                 else:
409                     continue
410
411                 for kl in classes:
412                     if kl.get_name() == name:
413                         self.assertTrue(issubclass(klass, over,),
414                                         "%r does not inherit from override %r" % (klass, over,))
415
416     def test_editable(self):
417         self.assertEqual(Gtk.Editable, gi.overrides.Gtk.Editable)
418
419         # need to use Gtk.Entry because Editable is an interface
420         entry = Gtk.Entry()
421         pos = entry.insert_text('HeWorld', 0)
422         self.assertEqual(pos, 7)
423         pos = entry.insert_text('llo ', 2)
424         self.assertEqual(pos, 6)
425         text = entry.get_chars(0, 11)
426         self.assertEqual('Hello World', text)
427
428     def test_label(self):
429         label = Gtk.Label(label='Hello')
430         self.assertTrue(isinstance(label, Gtk.Widget))
431         self.assertEqual(label.get_text(), 'Hello')
432
433     def adjustment_check(self, adjustment, value=0.0, lower=0.0, upper=0.0,
434                          step_increment=0.0, page_increment=0.0, page_size=0.0):
435         self.assertEqual(adjustment.get_value(), value)
436         self.assertEqual(adjustment.get_lower(), lower)
437         self.assertEqual(adjustment.get_upper(), upper)
438         self.assertEqual(adjustment.get_step_increment(), step_increment)
439         self.assertEqual(adjustment.get_page_increment(), page_increment)
440         self.assertEqual(adjustment.get_page_size(), page_size)
441
442     def test_adjustment(self):
443         adjustment = Gtk.Adjustment(value=1, lower=0, upper=6, step_increment=4, page_increment=5, page_size=3)
444         self.adjustment_check(adjustment, value=1, lower=0, upper=6, step_increment=4, page_increment=5, page_size=3)
445
446         adjustment = Gtk.Adjustment(value=1, lower=0, upper=6, step_increment=4, page_increment=5)
447         self.adjustment_check(adjustment, value=1, lower=0, upper=6, step_increment=4, page_increment=5)
448
449         adjustment = Gtk.Adjustment(value=1, lower=0, upper=6, step_increment=4)
450         self.adjustment_check(adjustment, value=1, lower=0, upper=6, step_increment=4)
451
452         adjustment = Gtk.Adjustment(value=1, lower=0, upper=6)
453         self.adjustment_check(adjustment, value=1, lower=0, upper=6)
454
455         adjustment = Gtk.Adjustment()
456         self.adjustment_check(adjustment)
457
458     def test_table(self):
459         table = Gtk.Table()
460         self.assertTrue(isinstance(table, Gtk.Table))
461         self.assertTrue(isinstance(table, Gtk.Container))
462         self.assertTrue(isinstance(table, Gtk.Widget))
463         self.assertEqual(table.get_size(), (1, 1))
464         self.assertEqual(table.get_homogeneous(), False)
465
466         table = Gtk.Table(n_rows=2, n_columns=3)
467         self.assertEqual(table.get_size(), (2, 3))
468         self.assertEqual(table.get_homogeneous(), False)
469
470         table = Gtk.Table(n_rows=2, n_columns=3, homogeneous=True)
471         self.assertEqual(table.get_size(), (2, 3))
472         self.assertEqual(table.get_homogeneous(), True)
473
474         label = Gtk.Label(label='Hello')
475         self.assertTrue(isinstance(label, Gtk.Widget))
476         table.attach(label, 0, 1, 0, 1)
477         self.assertEqual(label, table.get_children()[0])
478
479     def test_scrolledwindow(self):
480         sw = Gtk.ScrolledWindow()
481         self.assertTrue(isinstance(sw, Gtk.ScrolledWindow))
482         self.assertTrue(isinstance(sw, Gtk.Container))
483         self.assertTrue(isinstance(sw, Gtk.Widget))
484         sb = sw.get_hscrollbar()
485         self.assertEqual(sw.get_hadjustment(), sb.get_adjustment())
486         sb = sw.get_vscrollbar()
487         self.assertEqual(sw.get_vadjustment(), sb.get_adjustment())
488
489     def test_widget_drag_methods(self):
490         widget = Gtk.Button()
491
492         # here we are not checking functionality, only that the methods exist
493         # and except the right number of arguments
494
495         widget.drag_check_threshold(0, 0, 0, 0)
496
497         # drag_dest_ methods
498         widget.drag_dest_set(Gtk.DestDefaults.DROP, None, Gdk.DragAction.COPY)
499         widget.drag_dest_add_image_targets()
500         widget.drag_dest_add_text_targets()
501         widget.drag_dest_add_uri_targets()
502         widget.drag_dest_get_track_motion()
503         widget.drag_dest_set_track_motion(True)
504         widget.drag_dest_get_target_list()
505         widget.drag_dest_set_target_list(None)
506         widget.drag_dest_set_target_list(Gtk.TargetList.new([Gtk.TargetEntry.new('test', 0, 0)]))
507         widget.drag_dest_unset()
508
509         widget.drag_highlight()
510         widget.drag_unhighlight()
511
512         # drag_source_ methods
513         widget.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, None, Gdk.DragAction.MOVE)
514         widget.drag_source_add_image_targets()
515         widget.drag_source_add_text_targets()
516         widget.drag_source_add_uri_targets()
517         widget.drag_source_set_icon_name("")
518         widget.drag_source_set_icon_pixbuf(GdkPixbuf.Pixbuf())
519         widget.drag_source_set_icon_stock("")
520         widget.drag_source_get_target_list()
521         widget.drag_source_set_target_list(None)
522         widget.drag_source_set_target_list(Gtk.TargetList.new([Gtk.TargetEntry.new('test', 0, 0)]))
523         widget.drag_source_unset()
524
525         # these methods cannot be called because they require a valid drag on
526         # a real GdkWindow. So we only check that they exist and are callable.
527         self.assertTrue(hasattr(widget, 'drag_dest_set_proxy'))
528         self.assertTrue(hasattr(widget, 'drag_get_data'))
529
530     def test_drag_target_list(self):
531         mixed_target_list = [Gtk.TargetEntry.new('test0', 0, 0),
532                              ('test1', 1, 1),
533                              Gtk.TargetEntry.new('test2', 2, 2),
534                              ('test3', 3, 3)]
535
536         def _test_target_list(targets):
537             for i, target in enumerate(targets):
538                 self.assertTrue(isinstance(target, Gtk.TargetEntry))
539                 self.assertEqual(target.target, 'test' + str(i))
540                 self.assertEqual(target.flags, i)
541                 self.assertEqual(target.info, i)
542
543         _test_target_list(Gtk._construct_target_list(mixed_target_list))
544
545         widget = Gtk.Button()
546         widget.drag_dest_set(Gtk.DestDefaults.DROP, None, Gdk.DragAction.COPY)
547         widget.drag_dest_set_target_list(mixed_target_list)
548         widget.drag_dest_get_target_list()
549
550         widget.drag_source_set(Gdk.ModifierType.BUTTON1_MASK, None, Gdk.DragAction.MOVE)
551         widget.drag_source_set_target_list(mixed_target_list)
552         widget.drag_source_get_target_list()
553
554         treeview = Gtk.TreeView()
555         treeview.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK,
556                                           mixed_target_list,
557                                           Gdk.DragAction.DEFAULT | Gdk.DragAction.MOVE)
558
559         treeview.enable_model_drag_dest(mixed_target_list,
560                                         Gdk.DragAction.DEFAULT | Gdk.DragAction.MOVE)
561
562     def test_scrollbar(self):
563         adjustment = Gtk.Adjustment()
564
565         hscrollbar = Gtk.HScrollbar()
566         vscrollbar = Gtk.VScrollbar()
567         self.assertNotEqual(hscrollbar.props.adjustment, adjustment)
568         self.assertNotEqual(vscrollbar.props.adjustment, adjustment)
569
570         hscrollbar = Gtk.HScrollbar(adjustment=adjustment)
571         vscrollbar = Gtk.VScrollbar(adjustment=adjustment)
572         self.assertEqual(hscrollbar.props.adjustment, adjustment)
573         self.assertEqual(vscrollbar.props.adjustment, adjustment)
574
575     def test_iconview(self):
576         # PyGTK compat
577         iconview = Gtk.IconView()
578         self.assertEqual(iconview.props.model, None)
579
580         model = Gtk.ListStore(str)
581         iconview = Gtk.IconView(model=model)
582         self.assertEqual(iconview.props.model, model)
583
584     def test_toolbutton(self):
585         # PyGTK compat
586         button = Gtk.ToolButton()
587         self.assertEqual(button.props.stock_id, None)
588
589         button = Gtk.ToolButton(stock_id='gtk-new')
590         self.assertEqual(button.props.stock_id, 'gtk-new')
591
592         icon = Gtk.Image.new_from_stock(Gtk.STOCK_OPEN, Gtk.IconSize.SMALL_TOOLBAR)
593
594         button = Gtk.ToolButton(label='mylabel', icon_widget=icon)
595         self.assertEqual(button.props.label, 'mylabel')
596         self.assertEqual(button.props.icon_widget, icon)
597
598     def test_iconset(self):
599         Gtk.IconSet()
600         pixbuf = GdkPixbuf.Pixbuf()
601         Gtk.IconSet.new_from_pixbuf(pixbuf)
602
603     def test_viewport(self):
604         vadjustment = Gtk.Adjustment()
605         hadjustment = Gtk.Adjustment()
606
607         viewport = Gtk.Viewport(hadjustment=hadjustment,
608                                 vadjustment=vadjustment)
609
610         self.assertEqual(viewport.props.vadjustment, vadjustment)
611         self.assertEqual(viewport.props.hadjustment, hadjustment)
612
613     def test_stock_lookup(self):
614         l = Gtk.stock_lookup('gtk-ok')
615         self.assertEqual(type(l), Gtk.StockItem)
616         self.assertEqual(l.stock_id, 'gtk-ok')
617         self.assertEqual(Gtk.stock_lookup('nosuchthing'), None)
618
619     def test_gtk_main(self):
620         # with no arguments
621         GLib.timeout_add(100, Gtk.main_quit)
622         Gtk.main()
623
624         # overridden function ignores its arguments
625         GLib.timeout_add(100, Gtk.main_quit, 'hello')
626         Gtk.main()
627
628     def test_widget_render_icon(self):
629         button = Gtk.Button(label='OK')
630         pixbuf = button.render_icon(Gtk.STOCK_OK, Gtk.IconSize.BUTTON)
631         self.assertTrue(pixbuf is not None)
632
633
634 @unittest.skipUnless(Gtk, 'Gtk not available')
635 class TestWidget(unittest.TestCase):
636     def test_style_get_property_gvalue(self):
637         button = Gtk.Button()
638         value = GObject.Value(int, -42)
639         button.style_get_property('focus-padding', value)
640         # Test only that the style property changed since we can't actuall
641         # set it.
642         self.assertNotEqual(value.get_int(), -42)
643
644     def test_style_get_property_return_with_explicit_gvalue(self):
645         button = Gtk.Button()
646         value = GObject.Value(int, -42)
647         result = button.style_get_property('focus-padding', value)
648         self.assertIsInstance(result, int)
649         self.assertNotEqual(result, -42)
650
651     def test_style_get_property_return_with_implicit_gvalue(self):
652         button = Gtk.Button()
653         result = button.style_get_property('focus-padding')
654         self.assertIsInstance(result, int)
655         self.assertNotEqual(result, -42)
656
657     def test_style_get_property_error(self):
658         button = Gtk.Button()
659         with self.assertRaises(ValueError):
660             button.style_get_property('not-a-valid-style-property')
661
662
663 @unittest.skipUnless(Gtk, 'Gtk not available')
664 class TestSignals(unittest.TestCase):
665     def test_class_closure_override_with_aliased_type(self):
666         class WindowWithSizeAllocOverride(Gtk.ScrolledWindow):
667             __gsignals__ = {'size-allocate': 'override'}
668
669             def __init__(self):
670                 Gtk.ScrolledWindow.__init__(self)
671                 self._alloc_called = False
672                 self._alloc_value = None
673                 self._alloc_error = None
674
675             def do_size_allocate(self, alloc):
676                 self._alloc_called = True
677                 self._alloc_value = alloc
678
679                 try:
680                     Gtk.ScrolledWindow.do_size_allocate(self, alloc)
681                 except Exception as e:
682                     self._alloc_error = e
683
684         win = WindowWithSizeAllocOverride()
685         rect = Gdk.Rectangle()
686         rect.width = 100
687         rect.height = 100
688
689         with realized(win):
690             win.show()
691             win.size_allocate(rect)
692             self.assertTrue(win._alloc_called)
693             self.assertIsInstance(win._alloc_value, Gdk.Rectangle)
694             self.assertTrue(win._alloc_error is None, win._alloc_error)
695
696
697 @unittest.skipUnless(Gtk, 'Gtk not available')
698 class TestBuilder(unittest.TestCase):
699     class SignalTest(GObject.GObject):
700         __gtype_name__ = "GIOverrideSignalTest"
701         __gsignals__ = {
702             "test-signal": (GObject.SignalFlags.RUN_FIRST,
703                             None,
704                             []),
705         }
706
707     def test_extract_handler_and_args_object(self):
708         class Obj():
709             pass
710
711         obj = Obj()
712         obj.foo = lambda: None
713
714         handler, args = Gtk.Builder._extract_handler_and_args(obj, 'foo')
715         self.assertEqual(handler, obj.foo)
716         self.assertEqual(len(args), 0)
717
718     def test_extract_handler_and_args_dict(self):
719         obj = {'foo': lambda: None}
720
721         handler, args = Gtk.Builder._extract_handler_and_args(obj, 'foo')
722         self.assertEqual(handler, obj['foo'])
723         self.assertEqual(len(args), 0)
724
725     def test_extract_handler_and_args_with_seq(self):
726         obj = {'foo': (lambda: None, 1, 2)}
727
728         handler, args = Gtk.Builder._extract_handler_and_args(obj, 'foo')
729         self.assertEqual(handler, obj['foo'][0])
730         self.assertSequenceEqual(args, [1, 2])
731
732     def test_extract_handler_and_args_no_handler_error(self):
733         obj = dict(foo=lambda: None)
734         self.assertRaises(AttributeError,
735                           Gtk.Builder._extract_handler_and_args,
736                           obj, 'not_a_handler')
737
738     def test_builder_with_handler_and_args(self):
739         builder = Gtk.Builder()
740         builder.add_from_string("""
741             <interface>
742               <object class="GIOverrideSignalTest" id="object_sig_test">
743                   <signal name="test-signal" handler="on_signal1" />
744                   <signal name="test-signal" handler="on_signal2" after="yes" />
745               </object>
746             </interface>
747             """)
748
749         args_collector = []
750
751         def on_signal(*args):
752             args_collector.append(args)
753
754         builder.connect_signals({'on_signal1': (on_signal, 1, 2),
755                                  'on_signal2': on_signal})
756
757         objects = builder.get_objects()
758         self.assertEqual(len(objects), 1)
759         obj, = objects
760         obj.emit('test-signal')
761
762         self.assertEqual(len(args_collector), 2)
763         self.assertSequenceEqual(args_collector[0], (obj, 1, 2))
764         self.assertSequenceEqual(args_collector[1], (obj, ))
765
766     def test_builder(self):
767         self.assertEqual(Gtk.Builder, gi.overrides.Gtk.Builder)
768
769         class SignalCheck:
770             def __init__(self):
771                 self.sentinel = 0
772                 self.after_sentinel = 0
773
774             def on_signal_1(self, *args):
775                 self.sentinel += 1
776                 self.after_sentinel += 1
777
778             def on_signal_3(self, *args):
779                 self.sentinel += 3
780
781             def on_signal_after(self, *args):
782                 if self.after_sentinel == 1:
783                     self.after_sentinel += 1
784
785         signal_checker = SignalCheck()
786         builder = Gtk.Builder()
787
788         # add object1 to the builder
789         builder.add_from_string("""
790 <interface>
791   <object class="GIOverrideSignalTest" id="object1">
792       <signal name="test-signal" after="yes" handler="on_signal_after" />
793       <signal name="test-signal" handler="on_signal_1" />
794   </object>
795 </interface>
796 """)
797
798         # only add object3 to the builder
799         builder.add_objects_from_string("""
800 <interface>
801   <object class="GIOverrideSignalTest" id="object2">
802       <signal name="test-signal" handler="on_signal_2" />
803   </object>
804   <object class="GIOverrideSignalTest" id="object3">
805       <signal name="test-signal" handler="on_signal_3" />
806   </object>
807   <object class="GIOverrideSignalTest" id="object4">
808       <signal name="test-signal" handler="on_signal_4" />
809   </object>
810 </interface>
811 """, ['object3'])
812
813         # hook up signals
814         builder.connect_signals(signal_checker)
815
816         # call their notify signals and check sentinel
817         objects = builder.get_objects()
818         self.assertEqual(len(objects), 2)
819         for obj in objects:
820             obj.emit('test-signal')
821
822         self.assertEqual(signal_checker.sentinel, 4)
823         self.assertEqual(signal_checker.after_sentinel, 2)
824
825
826 @unittest.skipUnless(Gtk, 'Gtk not available')
827 class TestTreeModel(unittest.TestCase):
828     def test_tree_model_sort(self):
829         self.assertEqual(Gtk.TreeModelSort, gi.overrides.Gtk.TreeModelSort)
830         model = Gtk.TreeStore(int, bool)
831         model_sort = Gtk.TreeModelSort(model=model)
832         self.assertEqual(model_sort.get_model(), model)
833
834     def test_tree_store(self):
835         self.assertEqual(Gtk.TreeStore, gi.overrides.Gtk.TreeStore)
836         self.assertEqual(Gtk.ListStore, gi.overrides.Gtk.ListStore)
837         self.assertEqual(Gtk.TreeModel, gi.overrides.Gtk.TreeModel)
838         self.assertEqual(Gtk.TreeViewColumn, gi.overrides.Gtk.TreeViewColumn)
839
840         class TestPyObject(object):
841             pass
842
843         test_pyobj = TestPyObject()
844         test_pydict = {1: 1, "2": 2, "3": "3"}
845         test_pylist = [1, "2", "3"]
846         tree_store = Gtk.TreeStore(int,
847                                    'gchararray',
848                                    TestGtk.TestClass,
849                                    GObject.TYPE_PYOBJECT,
850                                    object,
851                                    object,
852                                    object,
853                                    bool,
854                                    bool,
855                                    GObject.TYPE_UINT,
856                                    GObject.TYPE_ULONG,
857                                    GObject.TYPE_INT64,
858                                    GObject.TYPE_UINT64,
859                                    GObject.TYPE_UCHAR,
860                                    GObject.TYPE_CHAR)
861
862         parent = None
863         for i in range(97):
864             label = 'this is child #%d' % i
865             testobj = TestGtk.TestClass(self, i, label)
866             parent = tree_store.append(parent, (i,
867                                                 label,
868                                                 testobj,
869                                                 testobj,
870                                                 test_pyobj,
871                                                 test_pydict,
872                                                 test_pylist,
873                                                 i % 2,
874                                                 bool(i % 2),
875                                                 i,
876                                                 GObject.G_MAXULONG,
877                                                 GObject.G_MININT64,
878                                                 0xffffffffffffffff,
879                                                 254,
880                                                 _bytes('a')
881                                                 ))
882         # test set
883         parent = tree_store.append(parent)
884         i = 97
885         label = 'this is child #%d' % i
886         testobj = TestGtk.TestClass(self, i, label)
887         tree_store.set(parent,
888                        0, i,
889                        2, testobj,
890                        1, label,
891                        3, testobj,
892                        4, test_pyobj,
893                        5, test_pydict,
894                        6, test_pylist,
895                        7, i % 2,
896                        8, bool(i % 2),
897                        9, i,
898                        10, GObject.G_MAXULONG,
899                        11, GObject.G_MININT64,
900                        12, 0xffffffffffffffff,
901                        13, 254,
902                        14, _bytes('a'))
903
904         parent = tree_store.append(parent)
905         i = 98
906         label = 'this is child #%d' % i
907         testobj = TestGtk.TestClass(self, i, label)
908         tree_store.set(parent, {0: i,
909                                 2: testobj,
910                                 1: label,
911                                 3: testobj,
912                                 4: test_pyobj,
913                                 5: test_pydict,
914                                 6: test_pylist,
915                                 7: i % 2,
916                                 8: bool(i % 2),
917                                 9: i,
918                                 10: GObject.G_MAXULONG,
919                                 11: GObject.G_MININT64,
920                                 12: 0xffffffffffffffff,
921                                 13: 254,
922                                 14: _bytes('a')})
923
924         parent = tree_store.append(parent)
925         i = 99
926         label = 'this is child #%d' % i
927         testobj = TestGtk.TestClass(self, i, label)
928         tree_store.set(parent, (0, 2, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14),
929                                (i,
930                                 testobj,
931                                 label,
932                                 testobj,
933                                 test_pyobj,
934                                 test_pydict,
935                                 test_pylist,
936                                 i % 2,
937                                 bool(i % 2),
938                                 i,
939                                 GObject.G_MAXULONG,
940                                 GObject.G_MININT64,
941                                 0xffffffffffffffff,
942                                 254,
943                                 _bytes('a')))
944
945         # len gets the number of children in the root node
946         # since we kept appending to the previous node
947         # there should only be one child of the root
948         self.assertEqual(len(tree_store), 1)
949
950         # walk the tree to see if the values were stored correctly
951         parent = None
952         i = 0
953
954         treeiter = tree_store.iter_children(parent)
955         while treeiter:
956             i = tree_store.get_value(treeiter, 0)
957             s = tree_store.get_value(treeiter, 1)
958             obj = tree_store.get_value(treeiter, 2)
959             obj.check(i, s)
960             obj2 = tree_store.get_value(treeiter, 3)
961             self.assertEqual(obj, obj2)
962
963             pyobj = tree_store.get_value(treeiter, 4)
964             self.assertEqual(pyobj, test_pyobj)
965             pydict = tree_store.get_value(treeiter, 5)
966             self.assertEqual(pydict, test_pydict)
967             pylist = tree_store.get_value(treeiter, 6)
968             self.assertEqual(pylist, test_pylist)
969
970             bool_1 = tree_store.get_value(treeiter, 7)
971             bool_2 = tree_store.get_value(treeiter, 8)
972             self.assertEqual(bool_1, bool_2)
973             self.assertTrue(isinstance(bool_1, bool))
974             self.assertTrue(isinstance(bool_2, bool))
975
976             uint_ = tree_store.get_value(treeiter, 9)
977             self.assertEqual(uint_, i)
978             ulong_ = tree_store.get_value(treeiter, 10)
979             self.assertEqual(ulong_, GObject.G_MAXULONG)
980             int64_ = tree_store.get_value(treeiter, 11)
981             self.assertEqual(int64_, GObject.G_MININT64)
982             uint64_ = tree_store.get_value(treeiter, 12)
983             self.assertEqual(uint64_, 0xffffffffffffffff)
984             uchar_ = tree_store.get_value(treeiter, 13)
985             self.assertEqual(ord(uchar_), 254)
986             char_ = tree_store.get_value(treeiter, 14)
987             self.assertEqual(char_, 'a')
988
989             parent = treeiter
990             treeiter = tree_store.iter_children(parent)
991
992         self.assertEqual(i, 99)
993
994     def test_tree_store_signals(self):
995         tree_store = Gtk.TreeStore(int, bool)
996
997         def on_row_inserted(tree_store, tree_path, tree_iter, signal_list):
998             signal_list.append('row-inserted')
999
1000         def on_row_changed(tree_store, tree_path, tree_iter, signal_list):
1001             signal_list.append('row-changed')
1002
1003         signals = []
1004         tree_store.connect('row-inserted', on_row_inserted, signals)
1005         tree_store.connect('row-changed', on_row_changed, signals)
1006
1007         # adding rows with and without data should only call one signal
1008         tree_store.append(None, (0, False))
1009         self.assertEqual(signals, ['row-inserted'])
1010
1011         signals.pop()
1012         tree_store.append(None)
1013         self.assertEqual(signals, ['row-inserted'])
1014
1015         signals.pop()
1016         tree_store.prepend(None, (0, False))
1017         self.assertEqual(signals, ['row-inserted'])
1018
1019         signals.pop()
1020         tree_store.prepend(None)
1021         self.assertEqual(signals, ['row-inserted'])
1022
1023         signals.pop()
1024         tree_store.insert(None, 1, (0, False))
1025         self.assertEqual(signals, ['row-inserted'])
1026
1027         signals.pop()
1028         tree_store.insert(None, 1)
1029         self.assertEqual(signals, ['row-inserted'])
1030
1031     def test_list_store(self):
1032         class TestPyObject(object):
1033             pass
1034
1035         test_pyobj = TestPyObject()
1036         test_pydict = {1: 1, "2": 2, "3": "3"}
1037         test_pylist = [1, "2", "3"]
1038
1039         list_store = Gtk.ListStore(int, str, 'GIOverrideTreeAPITest', object, object, object, bool, bool)
1040         for i in range(1, 93):
1041             label = 'this is row #%d' % i
1042             testobj = TestGtk.TestClass(self, i, label)
1043             list_store.append((i,
1044                                label,
1045                                testobj,
1046                                test_pyobj,
1047                                test_pydict,
1048                                test_pylist,
1049                                i % 2,
1050                                bool(i % 2)))
1051
1052         i = 93
1053         label = _unicode('this is row #93')
1054         treeiter = list_store.append()
1055         list_store.set_value(treeiter, 0, i)
1056         list_store.set_value(treeiter, 1, label)
1057         list_store.set_value(treeiter, 2, TestGtk.TestClass(self, i, label))
1058         list_store.set_value(treeiter, 3, test_pyobj)
1059         list_store.set_value(treeiter, 4, test_pydict)
1060         list_store.set_value(treeiter, 5, test_pylist)
1061         list_store.set_value(treeiter, 6, 1)
1062         list_store.set_value(treeiter, 7, True)
1063
1064         # test prepend
1065         label = 'this is row #0'
1066         list_store.prepend((0,
1067                             label,
1068                             TestGtk.TestClass(self, 0, label),
1069                             test_pyobj,
1070                             test_pydict,
1071                             test_pylist,
1072                             0,
1073                             False))
1074
1075         # test automatic unicode->str conversion
1076         i = 94
1077         label = _unicode('this is row #94')
1078         treeiter = list_store.append((i,
1079                                       label,
1080                                       TestGtk.TestClass(self, i, label),
1081                                       test_pyobj,
1082                                       test_pydict,
1083                                       test_pylist,
1084                                       0,
1085                                       False))
1086
1087         # add sorted items out of order to test insert* apis
1088         # also test sending in None to not set a column
1089         i = 97
1090         label = 'this is row #97'
1091         treeiter = list_store.append((None,
1092                                       None,
1093                                       None,
1094                                       test_pyobj,
1095                                       None,
1096                                       test_pylist,
1097                                       1,
1098                                       None))
1099
1100         list_store.set_value(treeiter, 0, i)
1101         list_store.set_value(treeiter, 1, label)
1102         list_store.set_value(treeiter, 2, TestGtk.TestClass(self, i, label))
1103         list_store.set_value(treeiter, 4, test_pydict)
1104         list_store.set_value(treeiter, 7, True)
1105
1106         # this should append
1107         i = 99
1108         label = 'this is row #99'
1109         list_store.insert(9999, (i,
1110                                  label,
1111                                  TestGtk.TestClass(self, i, label),
1112                                  test_pyobj,
1113                                  test_pydict,
1114                                  test_pylist,
1115                                  1,
1116                                  True))
1117
1118         i = 96
1119         label = 'this is row #96'
1120         list_store.insert_before(treeiter, (i,
1121                                             label,
1122                                             TestGtk.TestClass(self, i, label),
1123                                             test_pyobj,
1124                                             test_pydict,
1125                                             test_pylist,
1126                                             0,
1127                                             False))
1128
1129         i = 98
1130         label = 'this is row #98'
1131         list_store.insert_after(treeiter, (i,
1132                                            label,
1133                                            TestGtk.TestClass(self, i, label),
1134                                            test_pyobj,
1135                                            test_pydict,
1136                                            test_pylist,
1137                                            0,
1138                                            False))
1139
1140         i = 95
1141         label = 'this is row #95'
1142         list_store.insert(95, (i,
1143                                label,
1144                                TestGtk.TestClass(self, i, label),
1145                                test_pyobj,
1146                                test_pydict,
1147                                test_pylist,
1148                                1,
1149                                True))
1150
1151         i = 100
1152         label = 'this is row #100'
1153         treeiter = list_store.append()
1154         list_store.set(treeiter,
1155                        1, label,
1156                        0, i,
1157                        2, TestGtk.TestClass(self, i, label),
1158                        3, test_pyobj,
1159                        4, test_pydict,
1160                        5, test_pylist,
1161                        6, 0,
1162                        7, False)
1163         i = 101
1164         label = 'this is row #101'
1165         treeiter = list_store.append()
1166         list_store.set(treeiter, {1: label,
1167                                   0: i,
1168                                   2: TestGtk.TestClass(self, i, label),
1169                                   3: test_pyobj,
1170                                   4: test_pydict,
1171                                   5: test_pylist,
1172                                   6: 1,
1173                                   7: True})
1174         i = 102
1175         label = 'this is row #102'
1176         treeiter = list_store.append()
1177         list_store.set(treeiter, (1, 0, 2, 3, 4, 5, 6, 7),
1178                                  (label,
1179                                   i,
1180                                   TestGtk.TestClass(self, i, label),
1181                                   test_pyobj,
1182                                   test_pydict,
1183                                   test_pylist,
1184                                   0,
1185                                   False))
1186
1187         self.assertEqual(len(list_store), 103)
1188
1189         # walk the list to see if the values were stored correctly
1190         i = 0
1191         treeiter = list_store.get_iter_first()
1192
1193         counter = 0
1194         while treeiter:
1195             i = list_store.get_value(treeiter, 0)
1196             self.assertEqual(i, counter)
1197             s = list_store.get_value(treeiter, 1)
1198             obj = list_store.get_value(treeiter, 2)
1199             obj.check(i, s)
1200
1201             pyobj = list_store.get_value(treeiter, 3)
1202             self.assertEqual(pyobj, test_pyobj)
1203             pydict = list_store.get_value(treeiter, 4)
1204             self.assertEqual(pydict, test_pydict)
1205             pylist = list_store.get_value(treeiter, 5)
1206             self.assertEqual(pylist, test_pylist)
1207
1208             bool_1 = list_store.get_value(treeiter, 6)
1209             bool_2 = list_store.get_value(treeiter, 7)
1210             self.assertEqual(bool_1, bool_2)
1211             self.assertTrue(isinstance(bool_1, bool))
1212             self.assertTrue(isinstance(bool_2, bool))
1213
1214             treeiter = list_store.iter_next(treeiter)
1215
1216             counter += 1
1217
1218         self.assertEqual(i, 102)
1219
1220     def test_list_store_sort(self):
1221         def comp1(model, row1, row2, user_data):
1222             v1 = model[row1][1]
1223             v2 = model[row2][1]
1224
1225             # make "m" smaller than anything else
1226             if v1.startswith('m') and not v2.startswith('m'):
1227                 return -1
1228             if v2.startswith('m') and not v1.startswith('m'):
1229                 return 1
1230             return (v1 > v2) - (v1 < v2)
1231
1232         list_store = Gtk.ListStore(int, str)
1233         list_store.set_sort_func(2, comp1, None)
1234         list_store.append((1, 'apples'))
1235         list_store.append((3, 'oranges'))
1236         list_store.append((2, 'mango'))
1237
1238         # not sorted yet, should be original order
1239         self.assertEqual([list(i) for i in list_store],
1240                          [[1, 'apples'], [3, 'oranges'], [2, 'mango']])
1241
1242         # sort with our custom function
1243         list_store.set_sort_column_id(2, Gtk.SortType.ASCENDING)
1244         self.assertEqual([list(i) for i in list_store],
1245                          [[2, 'mango'], [1, 'apples'], [3, 'oranges']])
1246
1247         list_store.set_sort_column_id(2, Gtk.SortType.DESCENDING)
1248         self.assertEqual([list(i) for i in list_store],
1249                          [[3, 'oranges'], [1, 'apples'], [2, 'mango']])
1250
1251     def test_list_store_signals(self):
1252         list_store = Gtk.ListStore(int, bool)
1253
1254         def on_row_inserted(list_store, tree_path, tree_iter, signal_list):
1255             signal_list.append('row-inserted')
1256
1257         def on_row_changed(list_store, tree_path, tree_iter, signal_list):
1258             signal_list.append('row-changed')
1259
1260         signals = []
1261         list_store.connect('row-inserted', on_row_inserted, signals)
1262         list_store.connect('row-changed', on_row_changed, signals)
1263
1264         # adding rows with and without data should only call one signal
1265         list_store.append((0, False))
1266         self.assertEqual(signals, ['row-inserted'])
1267
1268         signals.pop()
1269         list_store.append()
1270         self.assertEqual(signals, ['row-inserted'])
1271
1272         signals.pop()
1273         list_store.prepend((0, False))
1274         self.assertEqual(signals, ['row-inserted'])
1275
1276         signals.pop()
1277         list_store.prepend()
1278         self.assertEqual(signals, ['row-inserted'])
1279
1280         signals.pop()
1281         list_store.insert(1, (0, False))
1282         self.assertEqual(signals, ['row-inserted'])
1283
1284         signals.pop()
1285         list_store.insert(1)
1286         self.assertEqual(signals, ['row-inserted'])
1287
1288     def test_tree_path(self):
1289         p1 = Gtk.TreePath()
1290         p2 = Gtk.TreePath.new_first()
1291         self.assertEqual(p1, p2)
1292         self.assertEqual(str(p1), '0')
1293         self.assertEqual(len(p1), 1)
1294         p1 = Gtk.TreePath(2)
1295         p2 = Gtk.TreePath.new_from_string('2')
1296         self.assertEqual(p1, p2)
1297         self.assertEqual(str(p1), '2')
1298         self.assertEqual(len(p1), 1)
1299         p1 = Gtk.TreePath('1:2:3')
1300         p2 = Gtk.TreePath.new_from_string('1:2:3')
1301         self.assertEqual(p1, p2)
1302         self.assertEqual(str(p1), '1:2:3')
1303         self.assertEqual(len(p1), 3)
1304         p1 = Gtk.TreePath((1, 2, 3))
1305         p2 = Gtk.TreePath.new_from_string('1:2:3')
1306         self.assertEqual(p1, p2)
1307         self.assertEqual(str(p1), '1:2:3')
1308         self.assertEqual(len(p1), 3)
1309         self.assertNotEqual(p1, None)
1310         self.assertTrue(p1 > None)
1311         self.assertTrue(p1 >= None)
1312         self.assertFalse(p1 < None)
1313         self.assertFalse(p1 <= None)
1314
1315         self.assertEqual(tuple(p1), (1, 2, 3))
1316         self.assertEqual(p1[0], 1)
1317         self.assertEqual(p1[1], 2)
1318         self.assertEqual(p1[2], 3)
1319         self.assertRaises(IndexError, p1.__getitem__, 3)
1320
1321     def test_tree_model(self):
1322         tree_store = Gtk.TreeStore(int, str)
1323
1324         self.assertTrue(tree_store)
1325         self.assertEqual(len(tree_store), 0)
1326         self.assertEqual(tree_store.get_iter_first(), None)
1327
1328         def get_by_index(row, col=None):
1329             if col:
1330                 return tree_store[row][col]
1331             else:
1332                 return tree_store[row]
1333
1334         self.assertRaises(TypeError, get_by_index, None)
1335         self.assertRaises(TypeError, get_by_index, "")
1336         self.assertRaises(TypeError, get_by_index, ())
1337
1338         self.assertRaises(IndexError, get_by_index, "0")
1339         self.assertRaises(IndexError, get_by_index, 0)
1340         self.assertRaises(IndexError, get_by_index, (0,))
1341
1342         self.assertRaises(ValueError, tree_store.get_iter, "0")
1343         self.assertRaises(ValueError, tree_store.get_iter, 0)
1344         self.assertRaises(ValueError, tree_store.get_iter, (0,))
1345
1346         self.assertRaises(ValueError, tree_store.get_iter_from_string, "0")
1347
1348         for row in tree_store:
1349             self.fail("Should not be reached")
1350
1351         class DerivedIntType(int):
1352             pass
1353
1354         class DerivedStrType(str):
1355             pass
1356
1357         for i in range(100):
1358             label = 'this is row #%d' % i
1359             parent = tree_store.append(None, (DerivedIntType(i), DerivedStrType(label),))
1360             self.assertNotEqual(parent, None)
1361             for j in range(20):
1362                 label = 'this is child #%d of node #%d' % (j, i)
1363                 child = tree_store.append(parent, (j, label,))
1364                 self.assertNotEqual(child, None)
1365
1366         self.assertTrue(tree_store)
1367         self.assertEqual(len(tree_store), 100)
1368
1369         self.assertEqual(tree_store.iter_previous(tree_store.get_iter(0)), None)
1370
1371         for i, row in enumerate(tree_store):
1372             self.assertEqual(row.model, tree_store)
1373             self.assertEqual(row.parent, None)
1374
1375             self.assertEqual(tree_store[i].path, row.path)
1376             self.assertEqual(tree_store[str(i)].path, row.path)
1377             self.assertEqual(tree_store[(i,)].path, row.path)
1378
1379             self.assertEqual(tree_store[i][0], i)
1380             self.assertEqual(tree_store[i][1], "this is row #%d" % i)
1381
1382             aiter = tree_store.get_iter(i)
1383             self.assertEqual(tree_store.get_path(aiter), row.path)
1384
1385             aiter = tree_store.get_iter(str(i))
1386             self.assertEqual(tree_store.get_path(aiter), row.path)
1387
1388             aiter = tree_store.get_iter((i,))
1389             self.assertEqual(tree_store.get_path(aiter), row.path)
1390
1391             self.assertEqual(tree_store.iter_parent(aiter), row.parent)
1392
1393             next = tree_store.iter_next(aiter)
1394             if i < len(tree_store) - 1:
1395                 self.assertEqual(tree_store.get_path(next), row.next.path)
1396                 self.assertEqual(tree_store.get_path(tree_store.iter_previous(next)),
1397                                  tree_store.get_path(aiter))
1398             else:
1399                 self.assertEqual(next, None)
1400
1401             self.assertEqual(tree_store.iter_n_children(row.iter), 20)
1402
1403             child = tree_store.iter_children(row.iter)
1404             for j, childrow in enumerate(row.iterchildren()):
1405                 child_path = tree_store.get_path(child)
1406                 self.assertEqual(childrow.path, child_path)
1407                 self.assertEqual(childrow.parent.path, row.path)
1408                 self.assertEqual(childrow.path, tree_store[child].path)
1409                 self.assertEqual(childrow.path, tree_store[child_path].path)
1410
1411                 self.assertEqual(childrow[0], tree_store[child][0])
1412                 self.assertEqual(childrow[0], j)
1413                 self.assertEqual(childrow[1], tree_store[child][1])
1414                 self.assertEqual(childrow[1], 'this is child #%d of node #%d' % (j, i))
1415
1416                 self.assertRaises(IndexError, get_by_index, child, 2)
1417
1418                 tree_store[child][1] = 'this was child #%d of node #%d' % (j, i)
1419                 self.assertEqual(childrow[1], 'this was child #%d of node #%d' % (j, i))
1420
1421                 nth_child = tree_store.iter_nth_child(row.iter, j)
1422                 self.assertEqual(childrow.path, tree_store.get_path(nth_child))
1423
1424                 childrow2 = tree_store["%d:%d" % (i, j)]
1425                 self.assertEqual(childrow.path, childrow2.path)
1426
1427                 childrow2 = tree_store[(i, j,)]
1428                 self.assertEqual(childrow.path, childrow2.path)
1429
1430                 child = tree_store.iter_next(child)
1431                 if j < 19:
1432                     self.assertEqual(childrow.next.path, tree_store.get_path(child))
1433                 else:
1434                     self.assertEqual(child, childrow.next)
1435                     self.assertEqual(child, None)
1436
1437             self.assertEqual(j, 19)
1438
1439         self.assertEqual(i, 99)
1440
1441         # negative indices
1442         for i in range(-1, -100, -1):
1443             i_real = i + 100
1444             self.assertEqual(tree_store[i][0], i_real)
1445
1446             row = tree_store[i]
1447             for j in range(-1, -20, -1):
1448                 j_real = j + 20
1449                 path = (i_real, j_real,)
1450
1451                 self.assertEqual(tree_store[path][-2], j_real)
1452
1453                 label = 'this was child #%d of node #%d' % (j_real, i_real)
1454                 self.assertEqual(tree_store[path][-1], label)
1455
1456                 new_label = 'this still is child #%d of node #%d' % (j_real, i_real)
1457                 tree_store[path][-1] = new_label
1458                 self.assertEqual(tree_store[path][-1], new_label)
1459
1460                 self.assertRaises(IndexError, get_by_index, path, -3)
1461
1462         self.assertRaises(IndexError, get_by_index, -101)
1463
1464         last_row = tree_store[99]
1465         self.assertNotEqual(last_row, None)
1466
1467         for i, childrow in enumerate(last_row.iterchildren()):
1468             if i < 19:
1469                 self.assertTrue(tree_store.remove(childrow.iter))
1470             else:
1471                 self.assertFalse(tree_store.remove(childrow.iter))
1472
1473         self.assertEqual(i, 19)
1474
1475         self.assertEqual(tree_store.iter_n_children(last_row.iter), 0)
1476         for childrow in last_row.iterchildren():
1477             self.fail("Should not be reached")
1478
1479         aiter = tree_store.get_iter(10)
1480         self.assertRaises(TypeError, tree_store.get, aiter, 1, 'a')
1481         self.assertRaises(ValueError, tree_store.get, aiter, 1, -1)
1482         self.assertRaises(ValueError, tree_store.get, aiter, 1, 100)
1483         self.assertEqual(tree_store.get(aiter, 0, 1), (10, 'this is row #10'))
1484
1485         # check __delitem__
1486         self.assertEqual(len(tree_store), 100)
1487         aiter = tree_store.get_iter(10)
1488         del tree_store[aiter]
1489         self.assertEqual(len(tree_store), 99)
1490         self.assertRaises(TypeError, tree_store.__delitem__, None)
1491         self.assertRaises(IndexError, tree_store.__delitem__, -101)
1492         self.assertRaises(IndexError, tree_store.__delitem__, 101)
1493
1494     def test_tree_model_get_iter_fail(self):
1495         # TreeModel class with a failing get_iter()
1496         class MyTreeModel(GObject.GObject, Gtk.TreeModel):
1497             def do_get_iter(self, iter):
1498                 return (False, None)
1499
1500         tm = MyTreeModel()
1501         self.assertEqual(tm.get_iter_first(), None)
1502
1503     def test_tree_model_edit(self):
1504         model = Gtk.ListStore(int, str, float)
1505         model.append([1, "one", -0.1])
1506         model.append([2, "two", -0.2])
1507
1508         def set_row(value):
1509             model[1] = value
1510
1511         self.assertRaises(TypeError, set_row, 3)
1512         self.assertRaises(TypeError, set_row, "three")
1513         self.assertRaises(ValueError, set_row, [])
1514         self.assertRaises(ValueError, set_row, [3, "three"])
1515
1516         model[0] = (3, "three", -0.3)
1517
1518     def test_tree_row_slice(self):
1519         model = Gtk.ListStore(int, str, float)
1520         model.append([1, "one", -0.1])
1521
1522         self.assertEqual([1, "one", -0.1], model[0][:])
1523         self.assertEqual([1, "one"], model[0][:2])
1524         self.assertEqual(["one", -0.1], model[0][1:])
1525         self.assertEqual(["one"], model[0][1:-1])
1526         self.assertEqual([1], model[0][:-2])
1527         self.assertEqual([], model[0][5:])
1528         self.assertEqual([1, -0.1], model[0][0:3:2])
1529
1530         model[0][:] = (2, "two", -0.2)
1531         self.assertEqual([2, "two", -0.2], model[0][:])
1532
1533         model[0][:2] = (3, "three")
1534         self.assertEqual([3, "three", -0.2], model[0][:])
1535
1536         model[0][1:] = ("four", -0.4)
1537         self.assertEqual([3, "four", -0.4], model[0][:])
1538
1539         model[0][1:-1] = ("five",)
1540         self.assertEqual([3, "five", -0.4], model[0][:])
1541
1542         model[0][0:3:2] = (6, -0.6)
1543         self.assertEqual([6, "five", -0.6], model[0][:])
1544
1545         def set_row1():
1546             model[0][5:] = ("doesn't", "matter",)
1547
1548         self.assertRaises(ValueError, set_row1)
1549
1550         def set_row2():
1551             model[0][:1] = (0, "zero", 0)
1552
1553         self.assertRaises(ValueError, set_row2)
1554
1555         def set_row3():
1556             model[0][:2] = ("0", 0)
1557
1558         self.assertRaises(TypeError, set_row3)
1559
1560     def test_tree_model_set_value_to_none(self):
1561         # Tests allowing the usage of None to set an empty value on a model.
1562         store = Gtk.ListStore(str)
1563         row = store.append(['test'])
1564         self.assertSequenceEqual(store[0][:], ['test'])
1565         store.set_value(row, 0, None)
1566         self.assertSequenceEqual(store[0][:], [None])
1567
1568     def test_signal_emission_tree_path_coerce(self):
1569         class Model(GObject.Object, Gtk.TreeModel):
1570             pass
1571
1572         model = Model()
1573         tree_paths = []
1574
1575         def on_any_signal(model, path, *args):
1576             tree_paths.append(path.to_string())
1577
1578         model.connect('row-changed', on_any_signal)
1579         model.connect('row-deleted', on_any_signal)
1580         model.connect('row-has-child-toggled', on_any_signal)
1581         model.connect('row-inserted', on_any_signal)
1582
1583         model.row_changed('0', Gtk.TreeIter())
1584         self.assertEqual(tree_paths[-1], '0')
1585
1586         model.row_deleted('1')
1587         self.assertEqual(tree_paths[-1], '1')
1588
1589         model.row_has_child_toggled('2', Gtk.TreeIter())
1590         self.assertEqual(tree_paths[-1], '2')
1591
1592         model.row_inserted('3', Gtk.TreeIter())
1593         self.assertEqual(tree_paths[-1], '3')
1594
1595     def test_tree_model_filter(self):
1596         model = Gtk.ListStore(int, str, float)
1597         model.append([1, "one", -0.1])
1598         model.append([2, "two", -0.2])
1599
1600         filtered = Gtk.TreeModelFilter(child_model=model)
1601
1602         self.assertEqual(filtered[0][1], 'one')
1603         filtered[0][1] = 'ONE'
1604         self.assertEqual(filtered[0][1], 'ONE')
1605
1606     def test_list_store_performance(self):
1607         model = Gtk.ListStore(int, str)
1608
1609         iterations = 2000
1610         start = time.clock()
1611         i = iterations
1612         while i > 0:
1613             model.append([1, 'hello'])
1614             i -= 1
1615         end = time.clock()
1616         sys.stderr.write('[%.0f Âµs/append] ' % ((end - start) * 1000000 / iterations))
1617
1618     def test_filter_new_default(self):
1619         # Test filter_new accepts implicit default of None
1620         model = Gtk.ListStore(int)
1621         filt = model.filter_new()
1622         self.assertTrue(filt is not None)
1623
1624
1625 @unittest.skipUnless(Gtk, 'Gtk not available')
1626 class TestTreeView(unittest.TestCase):
1627     def test_tree_view(self):
1628         store = Gtk.ListStore(int, str)
1629         store.append((0, "foo"))
1630         store.append((1, "bar"))
1631         view = Gtk.TreeView()
1632
1633         with realized(view):
1634             view.set_cursor(store[1].path)
1635             view.set_cursor(str(store[1].path))
1636
1637             view.get_cell_area(store[1].path)
1638             view.get_cell_area(str(store[1].path))
1639
1640     def test_tree_view_column(self):
1641         cell = Gtk.CellRendererText()
1642         col = Gtk.TreeViewColumn(title='This is just a test',
1643                                  cell_renderer=cell,
1644                                  text=0,
1645                                  style=2)
1646
1647         # Regression test for: https://bugzilla.gnome.org/show_bug.cgi?id=711173
1648         col.set_cell_data_func(cell, None, None)
1649
1650     def test_tree_view_add_column_with_attributes(self):
1651         model = Gtk.ListStore(str, str, str)
1652         # deliberately use out-of-order sorting here; we assign column 0 to
1653         # model index 2, etc.
1654         model.append(['cell13', 'cell11', 'cell12'])
1655         model.append(['cell23', 'cell21', 'cell22'])
1656
1657         tree = Gtk.TreeView(model=model)
1658         cell1 = Gtk.CellRendererText()
1659         cell2 = Gtk.CellRendererText()
1660         cell3 = Gtk.CellRendererText()
1661         cell4 = Gtk.CellRendererText()
1662
1663         tree.insert_column_with_attributes(0, 'Head2', cell2, text=2)
1664         tree.insert_column_with_attributes(0, 'Head1', cell1, text=1)
1665         tree.insert_column_with_attributes(-1, 'Head3', cell3, text=0)
1666         # unconnected
1667         tree.insert_column_with_attributes(-1, 'Head4', cell4)
1668
1669         with realized(tree):
1670             tree.set_cursor(model[0].path)
1671             while Gtk.events_pending():
1672                 Gtk.main_iteration()
1673
1674             self.assertEqual(tree.get_column(0).get_title(), 'Head1')
1675             self.assertEqual(tree.get_column(1).get_title(), 'Head2')
1676             self.assertEqual(tree.get_column(2).get_title(), 'Head3')
1677             self.assertEqual(tree.get_column(3).get_title(), 'Head4')
1678
1679             # cursor should be at the first row
1680             self.assertEqual(cell1.props.text, 'cell11')
1681             self.assertEqual(cell2.props.text, 'cell12')
1682             self.assertEqual(cell3.props.text, 'cell13')
1683             self.assertEqual(cell4.props.text, None)
1684
1685     def test_tree_view_column_set_attributes(self):
1686         store = Gtk.ListStore(int, str)
1687         directors = ['Fellini', 'Tarantino', 'Tarkovskiy']
1688         for i, director in enumerate(directors):
1689             store.append([i, director])
1690
1691         treeview = Gtk.TreeView()
1692         treeview.set_model(store)
1693
1694         column = Gtk.TreeViewColumn()
1695         treeview.append_column(column)
1696
1697         cell = Gtk.CellRendererText()
1698         column.pack_start(cell, expand=True)
1699         column.set_attributes(cell, text=1)
1700
1701         with realized(treeview):
1702             self.assertTrue(cell.props.text in directors)
1703
1704     def test_tree_selection(self):
1705         store = Gtk.ListStore(int, str)
1706         for i in range(10):
1707             store.append((i, "foo"))
1708         view = Gtk.TreeView()
1709         view.set_model(store)
1710         firstpath = store.get_path(store.get_iter_first())
1711         sel = view.get_selection()
1712
1713         sel.select_path(firstpath)
1714         (m, s) = sel.get_selected()
1715         self.assertEqual(m, store)
1716         self.assertEqual(store.get_path(s), firstpath)
1717
1718         sel.select_path(0)
1719         (m, s) = sel.get_selected()
1720         self.assertEqual(m, store)
1721         self.assertEqual(store.get_path(s), firstpath)
1722
1723         sel.select_path("0:0")
1724         (m, s) = sel.get_selected()
1725         self.assertEqual(m, store)
1726         self.assertEqual(store.get_path(s), firstpath)
1727
1728         sel.select_path((0, 0))
1729         (m, s) = sel.get_selected()
1730         self.assertEqual(m, store)
1731         self.assertEqual(store.get_path(s), firstpath)
1732
1733
1734 @unittest.skipUnless(Gtk, 'Gtk not available')
1735 class TestTextBuffer(unittest.TestCase):
1736     def test_text_buffer(self):
1737         self.assertEqual(Gtk.TextBuffer, gi.overrides.Gtk.TextBuffer)
1738         buffer = Gtk.TextBuffer()
1739         tag = buffer.create_tag('title', font='Sans 18')
1740
1741         self.assertEqual(tag.props.name, 'title')
1742         self.assertEqual(tag.props.font, 'Sans 18')
1743
1744         (start, end) = buffer.get_bounds()
1745
1746         mark = buffer.create_mark(None, start)
1747         self.assertFalse(mark.get_left_gravity())
1748
1749         buffer.set_text('Hello Jane Hello Bob')
1750         (start, end) = buffer.get_bounds()
1751         text = buffer.get_text(start, end, False)
1752         self.assertEqual(text, 'Hello Jane Hello Bob')
1753
1754         buffer.set_text('')
1755         (start, end) = buffer.get_bounds()
1756         text = buffer.get_text(start, end, False)
1757         self.assertEqual(text, '')
1758
1759         buffer.insert(end, 'HelloHello')
1760         buffer.insert(end, ' Bob')
1761
1762         cursor_iter = end.copy()
1763         cursor_iter.backward_chars(9)
1764         buffer.place_cursor(cursor_iter)
1765         buffer.insert_at_cursor(' Jane ')
1766
1767         (start, end) = buffer.get_bounds()
1768         text = buffer.get_text(start, end, False)
1769         self.assertEqual(text, 'Hello Jane Hello Bob')
1770
1771         sel = buffer.get_selection_bounds()
1772         self.assertEqual(sel, ())
1773         buffer.select_range(start, end)
1774         sel = buffer.get_selection_bounds()
1775         self.assertTrue(sel[0].equal(start))
1776         self.assertTrue(sel[1].equal(end))
1777
1778         buffer.set_text('')
1779         buffer.insert_with_tags(buffer.get_start_iter(), 'HelloHello', tag)
1780         (start, end) = buffer.get_bounds()
1781         self.assertTrue(start.begins_tag(tag))
1782         self.assertTrue(start.has_tag(tag))
1783
1784         buffer.set_text('')
1785         buffer.insert_with_tags_by_name(buffer.get_start_iter(), 'HelloHello', 'title')
1786         (start, end) = buffer.get_bounds()
1787         self.assertTrue(start.begins_tag(tag))
1788         self.assertTrue(start.has_tag(tag))
1789
1790         self.assertRaises(ValueError, buffer.insert_with_tags_by_name,
1791                           buffer.get_start_iter(), 'HelloHello', 'unknowntag')
1792
1793     def test_text_iter(self):
1794         self.assertEqual(Gtk.TextIter, gi.overrides.Gtk.TextIter)
1795         buffer = Gtk.TextBuffer()
1796         buffer.set_text('Hello Jane Hello Bob')
1797         tag = buffer.create_tag('title', font='Sans 18')
1798         (start, end) = buffer.get_bounds()
1799         start.forward_chars(10)
1800         buffer.apply_tag(tag, start, end)
1801         self.assertTrue(start.begins_tag())
1802         self.assertTrue(end.ends_tag())
1803         self.assertTrue(start.toggles_tag())
1804         self.assertTrue(end.toggles_tag())
1805         start.backward_chars(1)
1806         self.assertFalse(start.begins_tag())
1807         self.assertFalse(start.ends_tag())
1808         self.assertFalse(start.toggles_tag())
1809
1810     def test_text_buffer_search(self):
1811         buffer = Gtk.TextBuffer()
1812         buffer.set_text('Hello World Hello GNOME')
1813
1814         i = buffer.get_iter_at_offset(0)
1815         self.assertTrue(isinstance(i, Gtk.TextIter))
1816
1817         self.assertEqual(i.forward_search('world', 0, None), None)
1818
1819         (start, end) = i.forward_search('World', 0, None)
1820         self.assertEqual(start.get_offset(), 6)
1821         self.assertEqual(end.get_offset(), 11)
1822
1823         (start, end) = i.forward_search('world',
1824                                         Gtk.TextSearchFlags.CASE_INSENSITIVE,
1825                                         None)
1826         self.assertEqual(start.get_offset(), 6)
1827         self.assertEqual(end.get_offset(), 11)
1828
1829
1830 @unittest.skipUnless(Gtk, 'Gtk not available')
1831 class TestContainer(unittest.TestCase):
1832     def test_child_set_property(self):
1833         box = Gtk.Box()
1834         child = Gtk.Button()
1835         box.pack_start(child, expand=False, fill=True, padding=0)
1836
1837         box.child_set_property(child, 'padding', 42)
1838
1839         value = GObject.Value(int)
1840         box.child_get_property(child, 'padding', value)
1841         self.assertEqual(value.get_int(), 42)
1842
1843     def test_child_get_property_gvalue(self):
1844         box = Gtk.Box()
1845         child = Gtk.Button()
1846         box.pack_start(child, expand=False, fill=True, padding=42)
1847
1848         value = GObject.Value(int)
1849         box.child_get_property(child, 'padding', value)
1850         self.assertEqual(value.get_int(), 42)
1851
1852     def test_child_get_property_return_with_explicit_gvalue(self):
1853         box = Gtk.Box()
1854         child = Gtk.Button()
1855         box.pack_start(child, expand=False, fill=True, padding=42)
1856
1857         value = GObject.Value(int)
1858         result = box.child_get_property(child, 'padding', value)
1859         self.assertEqual(result, 42)
1860
1861     def test_child_get_property_return_with_implicit_gvalue(self):
1862         box = Gtk.Box()
1863         child = Gtk.Button()
1864         box.pack_start(child, expand=False, fill=True, padding=42)
1865
1866         result = box.child_get_property(child, 'padding')
1867         self.assertEqual(result, 42)
1868
1869     def test_child_get_property_error(self):
1870         box = Gtk.Box()
1871         child = Gtk.Button()
1872         box.pack_start(child, expand=False, fill=True, padding=42)
1873         with self.assertRaises(ValueError):
1874             box.child_get_property(child, 'not-a-valid-child-property')
1875
1876     def test_child_get_and_set(self):
1877         box = Gtk.Box()
1878         child = Gtk.Button()
1879         box.pack_start(child, expand=True, fill=True, padding=42)
1880
1881         expand, fill, padding = box.child_get(child, 'expand', 'fill', 'padding')
1882         self.assertEqual(expand, True)
1883         self.assertEqual(fill, True)
1884         self.assertEqual(padding, 42)
1885
1886         box.child_set(child, expand=False, fill=False, padding=21, pack_type=1)
1887         expand, fill, padding, pack_type = box.child_get(child, 'expand', 'fill', 'padding', 'pack-type')
1888         self.assertEqual(expand, False)
1889         self.assertEqual(fill, False)
1890         self.assertEqual(padding, 21)